From 3d0a2aba2c21883945f35591a5f64ff3e38dc0c0 Mon Sep 17 00:00:00 2001 From: Alan Feldstein Date: Wed, 27 Jun 2007 14:39:06 -0700 Subject: [PATCH] Add code generator hooks for latches Add code generator hooks missing from the previous patches that add latch synthesis support. --- NetLatch.cc | 12 ++++++++++++ NetLatch.h | 4 ++++ ivl_target.h | 1 + synth2.cc | 3 +-- t-dll-api.cc | 2 ++ t-dll.cc | 27 +++++++++++++++++++++++++++ t-dll.h | 5 +++++ target.cc | 5 +++++ target.h | 2 ++ 9 files changed, 59 insertions(+), 2 deletions(-) diff --git a/NetLatch.cc b/NetLatch.cc index 18d508b9b..d9e667087 100644 --- a/NetLatch.cc +++ b/NetLatch.cc @@ -3,6 +3,7 @@ // Class NetLatch member-function definitions #include "NetLatch.h" // NetLatch class definition +#include "target.h" // target_t structure definition // constructor NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width ) @@ -11,6 +12,11 @@ NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width ) { } // end NetLatch constructor +unsigned NetLatch::width() const +{ + return ( pin_count() - 1U ) / 2U; +} // end function width + Link &NetLatch::pin_Data( unsigned w ) { unsigned pn = 1 + 2 * w; @@ -29,3 +35,9 @@ Link &NetLatch::pin_Gate() { return pin( 0 ); } // end function pin_Q + +bool NetLatch::emit_node( target_t *driverPtr ) const +{ + driverPtr->lpm_latch( this ); + return true; +} // end function emit_node diff --git a/NetLatch.h b/NetLatch.h index 62f8f43bd..e78f5be5b 100644 --- a/NetLatch.h +++ b/NetLatch.h @@ -18,6 +18,8 @@ class NetLatch : public NetNode public: NetLatch( NetScope *, perm_string, unsigned ); + unsigned width() const; + Link &pin_Data( unsigned ); Link &pin_Q( unsigned ); Link &pin_Gate(); @@ -25,6 +27,8 @@ class NetLatch : public NetNode const Link &pin_Data( unsigned ) const; const Link &pin_Q( unsigned ) const; const Link &pin_Gate() const; + + virtual bool emit_node( target_t * ) const; }; // end class NetLatch #endif diff --git a/ivl_target.h b/ivl_target.h index 2fe6d05dd..c951f5862 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -230,6 +230,7 @@ typedef enum ivl_lpm_type_e { IVL_LPM_DEMUX = 16, IVL_LPM_DIVIDE = 12, IVL_LPM_FF = 3, + IVL_LPM_LATCH = 17, IVL_LPM_MOD = 13, IVL_LPM_MULT = 4, IVL_LPM_MUX = 5, diff --git a/synth2.cc b/synth2.cc index 79040730a..77661e646 100644 --- a/synth2.cc +++ b/synth2.cc @@ -231,7 +231,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, } des->add_node( latchPtr ); - delete latchPtr; } catch ( bad_alloc &memoryAllocationException ) @@ -1083,7 +1082,7 @@ bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag, /* * Handle synthesis for an asynchronous condition statement. If we get * here, we know that the CE of a DFF has already been filled, so the - * condition expression goes to the select of an asynchronous mux. + * condition expression goes to the select of an asynchronous mux, unless a latch is inferred in which case it goes to the latch's gate input. */ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag, struct sync_accounting_cell*nex_ff, diff --git a/t-dll-api.cc b/t-dll-api.cc index 5ae31a3cf..8d3dc4abf 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1084,6 +1084,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) case IVL_LPM_FF: case IVL_LPM_RAM: return net->u_.ff.width; + case IVL_LPM_LATCH: + return net->u_.latch.width; case IVL_LPM_DECODE: case IVL_LPM_MUX: return net->u_.mux.width; diff --git a/t-dll.cc b/t-dll.cc index 7ed54a170..aac7255e4 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -33,6 +33,9 @@ #endif # include +#include // standard operator new +using std::bad_alloc; + #if defined(__WIN32__) inline ivl_dll_t ivl_dlopen(const char *name) @@ -1734,6 +1737,30 @@ void dll_target::lpm_ff(const NetFF*net) } } +void dll_target::lpm_latch( const NetLatch *latchPtr ) +{ + try + { + ivl_lpm_s *objPtr = new ivl_lpm_s; + objPtr->type = IVL_LPM_LATCH; + objPtr->name = latchPtr->name(); + objPtr->scope = find_scope( des_, latchPtr->scope() ); + assert( objPtr->scope ); // C++ programmers prefer using exceptions rather than assertions. + + objPtr->u_.latch.width = latchPtr->width(); + + objPtr->nattr = latchPtr->attr_cnt(); + objPtr->attr = fill_in_attributes( latchPtr ); + + scope_add_lpm( objPtr->scope, objPtr ); + } + catch ( bad_alloc &memoryAllocationException ) + { + cerr << "Exception occurred: " << memoryAllocationException.what() << endl; + } + +} // end function lpm_latch + void dll_target::lpm_ram_dq(const NetRamDq*net) { ivl_memory_t mem = find_memory(des_, net->mem()); diff --git a/t-dll.h b/t-dll.h index 654ece579..adec44eae 100644 --- a/t-dll.h +++ b/t-dll.h @@ -80,6 +80,7 @@ struct dll_target : public target_t, public expr_scan_t { bool lpm_demux(const NetDemux*); void lpm_divide(const NetDivide*); void lpm_ff(const NetFF*); + void lpm_latch( const NetLatch * ); void lpm_modulo(const NetModulo*); void lpm_mult(const NetMult*); void lpm_mux(const NetMux*); @@ -328,6 +329,10 @@ struct ivl_lpm_s { ivl_expr_t sset_value; } ff; + struct ivl_lpm_latch_s { + unsigned width; + } latch; + struct ivl_lpm_mux_s { unsigned width; unsigned size; diff --git a/target.cc b/target.cc index 0b3fecdb1..258127e29 100644 --- a/target.cc +++ b/target.cc @@ -133,6 +133,11 @@ void target_t::lpm_ff(const NetFF*) "Unhandled NetFF." << endl; } +void target_t::lpm_latch( const NetLatch * ) +{ + cerr << "target (" << typeid( *this ).name() << "): Unhandled NetLatch." << endl; +} + void target_t::lpm_mult(const NetMult*) { cerr << "target (" << typeid(*this).name() << "): " diff --git a/target.h b/target.h index 3916566a3..94e8fb7e3 100644 --- a/target.h +++ b/target.h @@ -23,6 +23,7 @@ #endif # include "netlist.h" +#include "NetLatch.h" /* * This header file describes the types and constants used to describe @@ -84,6 +85,7 @@ struct target_t { virtual void lpm_divide(const NetDivide*); virtual void lpm_modulo(const NetModulo*); virtual void lpm_ff(const NetFF*); + virtual void lpm_latch( const NetLatch * ); virtual void lpm_mult(const NetMult*); virtual void lpm_mux(const NetMux*); virtual void lpm_ram_dq(const NetRamDq*);