diff --git a/design_dump.cc b/design_dump.cc index d82bb4098..1a7d5a41d 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.149.2.1 2006/01/18 01:23:23 steve Exp $" +#ident "$Id: design_dump.cc,v 1.149.2.2 2006/02/19 00:11:31 steve Exp $" #endif # include "config.h" @@ -216,6 +216,14 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const dump_obj_attr(o, ind+4); } +void NetDecode::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name() + << " ff=" << ff_->name() << endl; + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetDivide::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl; @@ -272,7 +280,11 @@ void NetFF::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_FF: " << name() << " scope=" << (scope()? scope()->name() : "") - << " aset_value=" << aset_value_ << endl; + << " aset_value=" << aset_value_; + + if (demux_) o << " demux=" << demux_->name(); + + o << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); @@ -358,7 +370,6 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const o << setw(ind) << "" << "LPM_RAM_DQ ("; if (mem_) o << "mem=" << mem_->name(); - if (sig_) o << "sig=" << sig_->name(); o << "): " << name() << endl; @@ -1094,6 +1105,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.149.2.2 2006/02/19 00:11:31 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.149.2.1 2006/01/18 01:23:23 steve * Rework l-value handling to allow for more l-value type flexibility. * diff --git a/emit.cc b/emit.cc index fcf19d0c1..2df371447 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $" +#ident "$Id: emit.cc,v 1.77.2.1 2006/02/19 00:11:31 steve Exp $" #endif # include "config.h" @@ -86,6 +86,11 @@ bool NetConst::emit_node(struct target_t*tgt) const return tgt->net_const(this); } +bool NetDecode::emit_node(struct target_t*tgt) const +{ + return tgt->lpm_decode(this); +} + bool NetDivide::emit_node(struct target_t*tgt) const { tgt->lpm_divide(this); @@ -511,6 +516,9 @@ bool emit(const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.77.2.1 2006/02/19 00:11:31 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.77 2004/10/04 01:10:53 steve * Clean up spurious trailing white space. * diff --git a/ivl.def b/ivl.def index 1291f1fd9..2467f695a 100644 --- a/ivl.def +++ b/ivl.def @@ -68,6 +68,7 @@ ivl_lpm_data ivl_lpm_datab ivl_lpm_data2 ivl_lpm_data2_width +ivl_lpm_decode ivl_lpm_define ivl_lpm_enable ivl_lpm_memory diff --git a/ivl_target.h b/ivl_target.h index abc448984..e9a68579c 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.126 2004/10/04 01:10:53 steve Exp $" +#ident "$Id: ivl_target.h,v 1.126.2.1 2006/02/19 00:11:31 steve Exp $" #endif #ifdef __cplusplus @@ -226,6 +226,7 @@ typedef enum ivl_lpm_type_e { IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GT = 2, IVL_LPM_CMP_NE = 11, + IVL_LPM_DECODE = 15, IVL_LPM_DIVIDE = 12, IVL_LPM_FF = 3, IVL_LPM_MOD = 13, @@ -642,13 +643,18 @@ extern const char* ivl_udp_name(ivl_udp_t net); * Return the input data nexus for device types that have a second * input vector. For example, arithmetic devices are like this. * + * ivl_lpm_decode + * Return the DECODER associated with this LPM_FF device. The + * decoder for a FF takes an input address and generates an enable + * input for no more then 1 bit (can be none) of the FF device. + * * ivl_lpm_q * Return the output data nexus for device types that have a single * output vector. This is most devices, it turns out. * * ivl_lpm_selects - * This is the size of the select input for a LPM_MUX device, or the - * address bus width of an LPM_RAM. + * This is the size of the select input for a LPM_MUX or LPM_DECODE + * device, or the address bus width of an LPM_RAM. * * ivl_lpm_signed * Arithmetic LPM devices may be signed or unsigned if there is a @@ -658,6 +664,14 @@ extern const char* ivl_udp_name(ivl_udp_t net); * In addition to a width, some devices have a size. The size is * often the number of inputs per out, i.e., the number of inputs * per bit for a MUX. + * + * SEMANTIC NOTES: + * + * The IVL_LPM_FF and IVL_LPM_DECODE devices are closely related. If + * the ivl_lpm_decode function returns a non-nil value, then the + * decoder represents an extra ENABLE-like input, where exactly one(1) + * bit of the width of the FF is enabled. The decoder inputs are and + * address that selects the FF to be enabled. */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ @@ -676,6 +690,8 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net); extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net); /* IVL_LPM_FF IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); + /* IVL_LPM_FF */ +extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net); /* IVL_LPM_UFUNC */ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); /* IVL_LPM_FF IVL_LPM_RAM */ @@ -691,9 +707,9 @@ extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx); /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB IVL_LPM_UFUNC */ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); - /* IVL_LPM_MUX IVL_LPM_RAM */ + /* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_RAM */ extern unsigned ivl_lpm_selects(ivl_lpm_t net); - /* IVL_LPM_MUX IVL_LPM_RAM */ + /* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); /* IVL_LPM_MUX */ extern unsigned ivl_lpm_size(ivl_lpm_t net); @@ -1236,6 +1252,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.126.2.1 2006/02/19 00:11:31 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.126 2004/10/04 01:10:53 steve * Clean up spurious trailing white space. * diff --git a/netlist.cc b/netlist.cc index 9ab5e976f..eab27ed95 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.226.2.1 2006/01/18 01:23:23 steve Exp $" +#ident "$Id: netlist.cc,v 1.226.2.2 2006/02/19 00:11:32 steve Exp $" #endif # include "config.h" @@ -234,7 +234,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) assert(s); release_list_ = 0; - ram_ = 0; verinum::V init_value = verinum::Vz; Link::DIR dir = Link::PASSIVE; @@ -276,7 +275,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls) assert(s); release_list_ = 0; - ram_ = 0; verinum::V init_value = verinum::Vz; Link::DIR dir = Link::PASSIVE; @@ -535,6 +533,8 @@ const NetScope* NetProcTop::scope() const NetFF::NetFF(NetScope*s, perm_string n, unsigned wid) : NetNode(s, n, 8 + 2*wid) { + demux_ = 0; + pin_Clock().set_dir(Link::INPUT); pin_Clock().set_name(perm_string::literal("Clock"), 0); pin_Enable().set_dir(Link::INPUT); @@ -686,6 +686,20 @@ const verinum& NetFF::sset_value() const return sset_value_; } +unsigned NetDecode::awidth() const +{ + return pin_count(); +} + +NetDecode* NetFF::get_demux() +{ + return demux_; +} + +const NetDecode* NetFF::get_demux() const +{ + return demux_; +} /* * The NetAddSub class represents an LPM_ADD_SUB device. The pinout is @@ -1062,6 +1076,36 @@ const Link& NetCompare::pin_DataB(unsigned idx) const return pin(8+width_+idx); } +NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid) +: NetNode(s, name, awid) +{ + ff_ = mem; + ff_->demux_ = this; + make_pins_(awid); +} + +NetDecode::~NetDecode() +{ +} + +void NetDecode::make_pins_(unsigned awid) +{ + for (unsigned idx = 0 ; idx < awid ; idx += 1) { + pin(idx).set_dir(Link::INPUT); + pin(idx).set_name(perm_string::literal("Address"), idx); + } +} + +Link& NetDecode::pin_Address(unsigned idx) +{ + return pin(idx); +} + +const Link& NetDecode::pin_Address(unsigned idx) const +{ + return pin(idx); +} + NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr, unsigned wa, unsigned wb) : NetNode(sc, n, wr+wa+wb), @@ -1412,23 +1456,13 @@ void NetRamDq::make_pins_(unsigned wid) NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid) : NetNode(s, n, 3+2*mem->width()+awid), - mem_(mem), sig_(0), awidth_(awid) + mem_(mem), awidth_(awid) { make_pins_(mem->width()); next_ = mem_->ram_list_; mem_->ram_list_ = this; } -NetRamDq::NetRamDq(NetScope*s, perm_string n, NetNet*sig, unsigned awid) -: NetNode(s, n, 3+2*1+awid), - mem_(0), sig_(sig), awidth_(awid) -{ - make_pins_(1); - - assert(sig->ram_ == 0); - sig->ram_ = this; -} - NetRamDq::~NetRamDq() { if (mem_) { @@ -1445,17 +1479,11 @@ NetRamDq::~NetRamDq() cur->next_ = next_; } } - - if (sig_) { - assert(sig_->ram_ == this); - sig_->ram_ = 0; - } } unsigned NetRamDq::width() const { if (mem_) return mem_->width(); - if (sig_) return 1; return 0; } @@ -1467,7 +1495,6 @@ unsigned NetRamDq::awidth() const unsigned NetRamDq::size() const { if (mem_) return mem_->count(); - if (sig_) return sig_->pin_count(); return 0; } @@ -1476,11 +1503,6 @@ const NetMemory* NetRamDq::mem() const return mem_; } -const NetNet* NetRamDq::sig() const -{ - return sig_; -} - unsigned NetRamDq::count_partners() const { unsigned count = 0; @@ -2313,6 +2335,9 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.226.2.2 2006/02/19 00:11:32 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.226.2.1 2006/01/18 01:23:23 steve * Rework l-value handling to allow for more l-value type flexibility. * diff --git a/netlist.h b/netlist.h index 291cd23e6..c9dfb318d 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.321.2.9 2006/01/21 21:42:31 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.10 2006/02/19 00:11:32 steve Exp $" #endif /* @@ -447,9 +447,6 @@ class NetNet : public NetObj { friend class NetRelease; NetRelease*release_list_; - friend class NetRamDq; - class NetRamDq*ram_; - private: Type type_; PortType port_type_; @@ -594,6 +591,36 @@ class NetCompare : public NetNode { bool signed_flag_; }; +/* + * A decoder takes an address input and activates (high) the single + * Q bit that is addressed. This can be used, for example, to + * generate an enable for a FF from an array of FFs. + */ +class NetDecode : public NetNode { + + public: + NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid); + ~NetDecode(); + + unsigned awidth() const; + + const NetFF*ff() const; + + Link& pin_Address(unsigned idx); + + const Link& pin_Address(unsigned idx) const; + const Link& pin_Q(unsigned idx) const; + + virtual void dump_node(ostream&, unsigned ind) const; + virtual bool emit_node(struct target_t*) const; + + private: + NetFF* ff_; + + private: + void make_pins_(unsigned awid); +}; + /* * This class represents a theoretical (though not necessarily * practical) integer divider gate. This is not to represent any real @@ -716,10 +743,19 @@ class NetFF : public NetNode { void sset_value(const verinum&val); const verinum& sset_value() const; + NetDecode* get_demux(); + const NetDecode* get_demux() const; + virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; virtual void functor_node(Design*des, functor_t*fun); + private: + // If there is a demux associated with this gate, the demux_ + // member will point to the decoder. + friend class NetDecode; + NetDecode*demux_; + private: verinum aset_value_; verinum sset_value_; @@ -886,14 +922,12 @@ class NetRamDq : public NetNode { public: NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid); - NetRamDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid); ~NetRamDq(); unsigned width() const; unsigned awidth() const; unsigned size() const; const NetMemory*mem() const; - const NetNet*sig() const; Link& pin_InClock(); Link& pin_OutClock(); @@ -925,7 +959,6 @@ class NetRamDq : public NetNode { private: NetMemory*mem_; - NetNet* sig_; NetRamDq*next_; unsigned awidth_; @@ -1518,6 +1551,10 @@ class NetAssignBase : public NetProc { bool synth_async(Design*des, NetScope*scope, bool sync_flag, NetNet*nex_map, NetNet*nex_out, NetNet*accum_in); + bool synth_sync(Design*des, NetScope*scope, + struct sync_accounting_cell*nex_ff, + NetNet*nex_map, NetNet*nex_out, + const svector&events); // This dumps all the lval structures. void dump_lval(ostream&) const; @@ -3402,6 +3439,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.10 2006/02/19 00:11:32 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.321.2.9 2006/01/21 21:42:31 steve * When mux has wide select but sparse choices, use 1hot translation. * diff --git a/synth2.cc b/synth2.cc index 2679ce80c..d912e152e 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: synth2.cc,v 1.39.2.20 2006/01/27 01:58:53 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.21 2006/02/19 00:11:33 steve Exp $" #endif # include "config.h" @@ -59,13 +59,6 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet*nex_map, NetNet*nex_out, const svector&events) { -#if 0 - if (events.count() > 0) { - cerr << get_line() << ": error: Events are unaccounted" - << " for in process synthesis. (proc)" << endl; - des->errors += 1; - } -#endif /* Synthesize the input to the DFF. */ return synth_async(des, scope, true, nex_map, nex_out); } @@ -128,31 +121,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, return false; } - /* Detect and handle the special case that this is a - memory-like access to a vector. */ - if (cur->bmux()) { - NetNet*adr = cur->bmux()->synthesize(des); - NetRamDq*dq = new NetRamDq(scope, scope->local_symbol(), - lsig, adr->pin_count()); - des->add_node(dq); - dq->set_line(*this); - - for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1) - connect(dq->pin_Address(idx), adr->pin(idx)); -#if 0 - /* Connect the Q bit to all the bits of the - output. This is a signal to a later stage that - the DFF should be replaced with a RAM to - support this port. */ - for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1){ - unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus()); - connect(dq->pin_Q(0), nex_out->pin(ptr)); - } -#endif - connect(dq->pin_Data(0), rsig->pin(roff)); - roff += cur->lwidth(); - continue; - } + assert(! cur->bmux()); /* Bind the outputs that we do make to the nex_out. Use the nex_map to map the l-value bit position to the nex_out bit @@ -871,6 +840,55 @@ static bool merge_ff_slices(NetFF*ff1, unsigned idx1, return true; } +bool NetAssignBase::synth_sync(Design*des, NetScope*scope, + struct sync_accounting_cell*nex_ff, + NetNet*nex_map, NetNet*nex_out, + const svector&events) +{ + unsigned count_lval = 0; + NetAssign_*demux = 0; + + for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { + if (cur->bmux()) + demux = cur; + + count_lval += 1; + } + + if (demux != 0 && count_lval != 1) { + cerr << get_line() << ": error: Cannot synthesize assignmnents" + << "that mix memory and vector assignments." << endl; + return false; + } + + /* There is no memory address, so resort to async + assignments. */ + if (demux == 0) { + /* Synthesize the input to the DFF. */ + return synth_async(des, scope, true, nex_map, nex_out); + } + + assert(demux->bmux() != 0); + + NetNet*adr = demux->bmux()->synthesize(des); + NetDecode*dq = new NetDecode(scope, scope->local_symbol(), + nex_ff[0].ff, adr->pin_count()); + des->add_node(dq); + dq->set_line(*this); + + for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1) + connect(dq->pin_Address(idx), adr->pin(idx)); + + NetNet*rsig = rval_->synthesize(des); + assert(rsig->pin_count() == 1); + + for (unsigned idx = 0 ; idx < nex_ff[0].ff->width() ; idx += 1) + connect(nex_ff[0].ff->pin_Data(idx), rsig->pin(0)); + + lval_->turn_sig_to_wire_on_release(); + return true; +} + /* * This method is called when a block is encountered near the surface * of a synchronous always statement. For example, this code will be @@ -1459,10 +1477,11 @@ bool NetProcTop::synth_sync(Design*des) nex_set.count()); des->add_node(ff); ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF")); + unsigned process_pin_count = ff->width(); struct sync_accounting_cell*nex_ff = new struct sync_accounting_cell[ff->pin_count()]; - for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1) { + for (unsigned idx = 0 ; idx < process_pin_count ; idx += 1) { nex_ff[idx].ff = ff; nex_ff[idx].pin = idx; nex_ff[idx].proc = statement_; @@ -1494,6 +1513,47 @@ bool NetProcTop::synth_sync(Design*des) nex_q, nex_d, svector()); +#if 0 + /* Now look for FFs that have been attached to a + decoder. These need to be handled specially. */ + for (unsigned idx = 0; idx < process_pin_count ; idx += 1) { + NetFF*ff = nex_ff[idx].ff; + unsigned pin = nex_ff[idx].pin; + if (ff == 0) + continue; + + NetDecode*demux = ff->get_demux(); + + nex_ff[idx].ff = 0; + + if (demux == 0) + continue; + + cerr << "XXXX Demux bit " << idx << "["<type) { + case IVL_LPM_FF: + return net->u_.ff.a.decode; + default: + assert(0); + return 0; + } +} + /* * This function returns the hierarchical name for the LPM device. The * name needs to be built up from the scope name and the lpm base @@ -929,6 +941,7 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx) else return net->u_.ff.s.pins[idx]; + case IVL_LPM_DECODE: case IVL_LPM_MUX: assert(idx < net->u_.mux.swid); if (net->u_.mux.swid == 1) @@ -952,6 +965,7 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) switch (net->type) { case IVL_LPM_RAM: return net->u_.ff.swid; + case IVL_LPM_DECODE: case IVL_LPM_MUX: return net->u_.mux.swid; case IVL_LPM_SHIFTL: @@ -984,7 +998,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTR: return net->u_.shift.signed_flag; - return 0; + case IVL_LPM_DECODE: case IVL_LPM_UFUNC: return 0; default: @@ -1035,6 +1049,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) return net->u_.shift.width; case IVL_LPM_UFUNC: return net->u_.ufunc.port_wid[0]; + case IVL_LPM_DECODE: + return 1; default: assert(0); return 0; @@ -1046,7 +1062,7 @@ extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net) assert(net); switch (net->type) { case IVL_LPM_RAM: - return net->u_.ff.mem; + return net->u_.ff.a.mem; default: assert(0); return 0; @@ -1935,6 +1951,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.108.2.1 2006/02/19 00:11:33 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.108 2004/10/04 01:10:55 steve * Clean up spurious trailing white space. * diff --git a/t-dll.cc b/t-dll.cc index f30b25d53..72dfecd7b 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.cc,v 1.131.2.2 2006/01/21 21:42:33 steve Exp $" +#ident "$Id: t-dll.cc,v 1.131.2.3 2006/02/19 00:11:34 steve Exp $" #endif # include "config.h" @@ -1491,12 +1491,55 @@ void dll_target::lpm_modulo(const NetModulo*net) scope_add_lpm(obj->scope, obj); } +bool dll_target::lpm_decode(const NetDecode*net) +{ + return true; +} + +ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net) +{ + if (net == 0) + return 0; + + ivl_lpm_t obj = new struct ivl_lpm_s; + obj->type = IVL_LPM_DECODE; + obj->name = net->name(); + obj->scope = find_scope(des_, net->scope()); + + obj->u_.mux.swid = net->awidth(); + obj->u_.mux.size = 0; + obj->u_.mux.width = 0; + obj->u_.mux.d = 0; + + if (obj->u_.mux.swid > 1) { + obj->u_.mux.s.pins = new ivl_nexus_t[obj->u_.mux.swid]; + + for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) { + const Nexus*nex = net->pin_Address(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, idx, + IVL_DR_HiZ, IVL_DR_HiZ); + } + } else { + assert(obj->u_.mux.swid == 1); + const Nexus*nex = net->pin_Address(0).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); + } + + scope_add_lpm(obj->scope, obj); + return obj; +} + void dll_target::lpm_ff(const NetFF*net) { ivl_lpm_t obj = new struct ivl_lpm_s; obj->type = IVL_LPM_FF; obj->name = net->name(); obj->scope = find_scope(des_, net->scope()); + obj->u_.ff.a.decode = lpm_decode_ff_(net->get_demux()); assert(obj->scope); obj->u_.ff.width = net->width(); @@ -1612,8 +1655,8 @@ void dll_target::lpm_ram_dq(const NetRamDq*net) ivl_lpm_t obj = new struct ivl_lpm_s; obj->type = IVL_LPM_RAM; obj->name = net->name(); - obj->u_.ff.mem = find_memory(des_, net->mem()); - assert(obj->u_.ff.mem); + obj->u_.ff.a.mem = find_memory(des_, net->mem()); + assert(obj->u_.ff.a.mem); obj->scope = find_scope(des_, net->mem()->scope()); assert(obj->scope); @@ -2182,6 +2225,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.131.2.3 2006/02/19 00:11:34 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.131.2.2 2006/01/21 21:42:33 steve * When mux has wide select but sparse choices, use 1hot translation. * diff --git a/t-dll.h b/t-dll.h index f20f936f7..5db0bdc94 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $" +#ident "$Id: t-dll.h,v 1.115.2.1 2006/02/19 00:11:34 steve Exp $" #endif # include "target.h" @@ -76,6 +76,7 @@ struct dll_target : public target_t, public expr_scan_t { void lpm_add_sub(const NetAddSub*); void lpm_clshift(const NetCLShift*); void lpm_compare(const NetCompare*); + bool lpm_decode(const NetDecode*); void lpm_divide(const NetDivide*); void lpm_ff(const NetFF*); void lpm_modulo(const NetModulo*); @@ -162,6 +163,8 @@ struct dll_target : public target_t, public expr_scan_t { void add_root(ivl_design_s &des_, const NetScope *s); + ivl_lpm_t lpm_decode_ff_(const NetDecode*); + void sub_off_from_expr_(long); void mul_expr_by_const_(long); @@ -312,7 +315,10 @@ struct ivl_lpm_s { ivl_nexus_t*pins; ivl_nexus_t pin; } s; - ivl_memory_t mem; // ram only + union { + ivl_memory_t mem; // ram only + ivl_lpm_t decode; // FF only + } a; ivl_expr_t aset_value; ivl_expr_t sset_value; } ff; @@ -684,6 +690,9 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.115.2.1 2006/02/19 00:11:34 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.115 2004/10/04 01:10:56 steve * Clean up spurious trailing white space. * diff --git a/target.cc b/target.cc index 117662933..89dc6f2ef 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $" +#ident "$Id: target.cc,v 1.69.2.1 2006/02/19 00:11:34 steve Exp $" #endif # include "config.h" @@ -101,6 +101,13 @@ void target_t::lpm_compare(const NetCompare*) "Unhandled NetCompare." << endl; } +bool target_t::lpm_decode(const NetDecode*) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled NetDecode." << endl; + return false; +} + void target_t::lpm_divide(const NetDivide*) { cerr << "target (" << typeid(*this).name() << "): " @@ -420,6 +427,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.69.2.1 2006/02/19 00:11:34 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.69 2004/05/31 23:34:39 steve * Rewire/generalize parsing an elaboration of * function return values to allow for better diff --git a/target.h b/target.h index 21b366667..2966f486c 100644 --- a/target.h +++ b/target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $" +#ident "$Id: target.h,v 1.65.2.1 2006/02/19 00:11:34 steve Exp $" #endif # include "netlist.h" @@ -79,6 +79,7 @@ struct target_t { virtual void lpm_add_sub(const NetAddSub*); virtual void lpm_clshift(const NetCLShift*); virtual void lpm_compare(const NetCompare*); + virtual bool lpm_decode(const NetDecode*); virtual void lpm_divide(const NetDivide*); virtual void lpm_modulo(const NetModulo*); virtual void lpm_ff(const NetFF*); @@ -170,6 +171,9 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.65.2.1 2006/02/19 00:11:34 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.65 2004/05/31 23:34:39 steve * Rewire/generalize parsing an elaboration of * function return values to allow for better diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index e36eff551..f67f7cbaa 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: stub.c,v 1.90.2.4 2006/01/21 21:42:33 steve Exp $" +#ident "$Id: stub.c,v 1.90.2.5 2006/02/19 00:11:34 steve Exp $" #endif # include "config.h" @@ -278,6 +278,16 @@ static void show_lpm(ivl_lpm_t net) break; } + case IVL_LPM_DECODE: { + fprintf(out, " LPM_DECODE %s\n", ivl_lpm_basename(net)); + for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) { + ivl_nexus_t nex = ivl_lpm_select(net, idx); + fprintf(out, " Address %u: %s\n", idx, + nex? ivl_nexus_name(nex) : ""); + } + break; + } + case IVL_LPM_SHIFTL: { fprintf(out, " LPM_SHIFTL %s: \n", ivl_lpm_basename(net), width, ivl_lpm_selects(net), @@ -330,6 +340,12 @@ static void show_lpm(ivl_lpm_t net) fprintf(out, " LPM_FF %s: \n", ivl_lpm_basename(net), width); + if (ivl_lpm_decode(net)) { + ivl_lpm_t dec = ivl_lpm_decode(net); + fprintf(out, " decoder: %s\n", + ivl_lpm_basename(dec)); + } + if (ivl_lpm_enable(net)) fprintf(out, " clk: %s CE: %s\n", ivl_nexus_name(ivl_lpm_clk(net)), @@ -1007,6 +1023,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.90.2.5 2006/02/19 00:11:34 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.90.2.4 2006/01/21 21:42:33 steve * When mux has wide select but sparse choices, use 1hot translation. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index b77c8f279..b90d24465 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_scope.c,v 1.103.2.1 2006/01/18 06:15:45 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.103.2.2 2006/02/19 00:11:35 steve Exp $" #endif # include "vvp_priv.h" @@ -383,6 +383,11 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) lpm = ivl_nexus_ptr_lpm(nptr); if (lpm) switch (ivl_lpm_type(lpm)) { + case IVL_LPM_DECODE: + /* The decoder has no outputs. + (It is bound to other devices.) */ + break; + case IVL_LPM_FF: case IVL_LPM_MUX: for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) @@ -1224,6 +1229,28 @@ static void draw_lpm_cmp(ivl_lpm_t net) fprintf(vvp_out, ";\n"); } +static void draw_lpm_decode(ivl_lpm_t net) +{ + unsigned idx; + + fprintf(vvp_out, "L_%s.%s .decode/adr ", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net))); + + for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) { + ivl_nexus_t a = ivl_lpm_select(net, idx); + if (idx > 0) + fprintf(vvp_out, ", "); + if (a) { + draw_input_from_net(a); + } else { + fprintf(vvp_out, "C<0>"); + } + } + + fprintf(vvp_out, ";\n"); +} + /* * Draw == and != gates. This is done as XNOR functors to compare each * pair of bits. The result is combined with a wide and, or a NAND if @@ -1349,6 +1376,28 @@ static void draw_lpm_ff(ivl_lpm_t net) fprintf(vvp_out, ", C<1>;\n"); } + /* If there is a decoder for this FF, then create a + decoder enable node. */ + if (ivl_lpm_decode(net)) { + ivl_lpm_t dec = ivl_lpm_decode(net); + fprintf(vvp_out, "L_%s.%s/dec/%u .decode/en L_%s.%s, %u", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net)), idx, + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(dec))), + vvp_mangle_id(ivl_lpm_basename(dec)), idx); + + tmp = ivl_lpm_enable(net); + if (tmp && (ivl_lpm_sync_clr(net)||ivl_lpm_sync_set(net))) { + fprintf(vvp_out, ", L_%s.%s/en", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net))); + } else if (tmp) { + fprintf(vvp_out, ", "); + draw_input_from_net(tmp); + } + fprintf(vvp_out, ";\n"); + } + fprintf(vvp_out, "L_%s.%s/%u .udp ", vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), vvp_mangle_id(ivl_lpm_basename(net)), idx); @@ -1363,17 +1412,28 @@ static void draw_lpm_ff(ivl_lpm_t net) /* Draw the enable input. */ tmp = ivl_lpm_enable(net); fprintf(vvp_out, ", "); - if (tmp && (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net))) { + if (ivl_lpm_decode(net)) { + /* If there is a decoder, get the enable from a + decoder node. */ + fprintf(vvp_out, "L_%s.%s/dec/%u", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net)), idx); + } else if (tmp && (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net))) { + /* If there is no decoder but an otherwise complex + enable, get the enable from the calculated + logic. */ fprintf(vvp_out, "L_%s.%s/en", vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), vvp_mangle_id(ivl_lpm_basename(net))); } else if (tmp) { + /* Draw a simple enable if that's what we got. */ draw_input_from_net(tmp); } else { + /* Otherwise, permanently enable the DFF. */ fprintf(vvp_out, "C<1>"); } - /* Drat the data input. MUX it with the sync input + /* Draw the data input. MUX it with the sync input if there is one. */ if (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net)) { fprintf(vvp_out, ", L_%s.%s/din/%u", @@ -1558,6 +1618,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net) draw_lpm_ufunc(net); return; + case IVL_LPM_DECODE: + draw_lpm_decode(net); + return; + default: fprintf(stderr, "XXXX LPM not supported: %s.%s\n", ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net)); @@ -1681,6 +1745,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.103.2.2 2006/02/19 00:11:35 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.103.2.1 2006/01/18 06:15:45 steve * Support DFF with synchronous inputs. * diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 653b02da8..157e8db58 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.61.2.1 2005/02/23 18:40:24 steve Exp $" +#ident "$Id: Makefile.in,v 1.61.2.2 2006/02/19 00:11:35 steve Exp $" # # SHELL = /bin/sh @@ -85,7 +85,7 @@ vpip_to_dec.o vpip_format.o vvp_vpi.o O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o \ functor.o fvectors.o npmos.o resolv.o stop.o symbols.o ufunc.o codes.o \ vthread.o schedule.o statistics.o tables.o udp.o memory.o force.o event.o \ -logic.o delay.o words.o $V +logic.o delay.o words.o decoder.o $V ifeq (@WIN32@,yes) # Under Windows (mingw) I need to make the ivl.exe in two steps. diff --git a/vvp/compile.h b/vvp/compile.h index 67d787900..9df29d1d1 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: compile.h,v 1.56 2004/10/04 01:10:59 steve Exp $" +#ident "$Id: compile.h,v 1.56.2.1 2006/02/19 00:11:35 steve Exp $" #endif # include @@ -115,6 +115,10 @@ extern void compile_cmp_ge(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_cmp_gt(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); +extern void compile_decode_adr(char*label, + unsigned argc, struct symb_s*argv); +extern void compile_decode_en(char*label, char*decoder, int slice, + struct symb_s enable); extern void compile_shiftl(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_shiftr(char*label, long width, @@ -268,6 +272,9 @@ extern void compile_net(char*label, char*name, /* * $Log: compile.h,v $ + * Revision 1.56.2.1 2006/02/19 00:11:35 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.56 2004/10/04 01:10:59 steve * Clean up spurious trailing white space. * diff --git a/vvp/decoder.cc b/vvp/decoder.cc new file mode 100644 index 000000000..917ab8bf4 --- /dev/null +++ b/vvp/decoder.cc @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2006 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ident "$Id: decoder.cc,v 1.1.2.1 2006/02/19 00:11:36 steve Exp $" + +# include "compile.h" +# include "functor.h" +# include "symbols.h" +# include +# include +# include +# include + +struct vvp_decode_adr_s; +struct vvp_decode_en_s; + +static symbol_table_t decoder_table = 0; + +static struct vvp_decode_adr_s* decoder_find(char *label) +{ + if (decoder_table == 0) + return 0; + + symbol_value_t v = sym_get_value(decoder_table, label); + return (vvp_decode_adr_s*)v.ptr; +} + +static void decoder_save(char*label, struct vvp_decode_adr_s*obj) +{ + if (! decoder_table) + decoder_table = new_symbol_table(); + + assert(! decoder_find(label)); + + symbol_value_t v; + v.ptr = obj; + sym_set_value(decoder_table, label, v); +} + +/* + * This structure represents a decoder address object. We receive the + * value changes of address bits, and accumulate the current address value. + */ +struct vvp_decode_adr_s : public functor_s { + + vvp_decode_adr_s(vvp_ipoint_t i, unsigned w); + + void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str); + + // functor index for this node, for finding all the input + // functors related to me. + vvp_ipoint_t ix; + const unsigned width; + // Keep a list of decode_en objects that reference me. + struct vvp_decode_en_s* enable_list; +}; + +struct vvp_decode_en_s : public functor_s { + + vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s); + + void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str); + + void propagate_decoder_address(unsigned adr); + + struct vvp_decode_adr_s*decoder; + struct vvp_decode_en_s* enable_next; + + const unsigned self; + // This is the enable calculated from the decoder + bool decode_en; + // This is the enable that arrives from the extra input. + bool extra_en; +}; + +vvp_decode_adr_s::vvp_decode_adr_s(vvp_ipoint_t me, unsigned w) +: ix(me), width(w), enable_list(0) +{ +} + +void vvp_decode_adr_s::set(vvp_ipoint_t i, bool push, + unsigned val, unsigned str) +{ + functor_t ifu = functor_index(i); + ifu->put(i, val); + unsigned cur_adr = 0; + for (unsigned idx = 0 ; idx < width ; idx += 1) { + int abval = functor_get_input(ix + idx); + unsigned mask = 1 << idx; + if (abval > 1) + cur_adr |= UINT_MAX; + else if (abval == 1) + cur_adr |= mask; + + } + + for (vvp_decode_en_s*cur = enable_list ; cur ; cur = cur->enable_next) + cur->propagate_decoder_address(cur_adr); +} + +vvp_decode_en_s::vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s) +: self(s) +{ + enable_next = 0; + decode_en = false; + extra_en = true; + + decoder = dec; + enable_next = decoder->enable_list; + decoder->enable_list = this; +} + +void vvp_decode_en_s::set(vvp_ipoint_t i, bool push, + unsigned val, unsigned str) +{ + functor_t ifu = functor_index(i); + ifu->put(i, val); + + int abval = functor_get_input(i); + if (abval == 1) { + extra_en = true; + } else { + extra_en = false; + } + + if (extra_en && decode_en) + put_oval(1, true); + else + put_oval(0, true); +} + +void vvp_decode_en_s::propagate_decoder_address(unsigned adr) +{ + if (adr == self) { + decode_en = true; + } else { + decode_en = false; + } + + if (extra_en && decode_en) + put_oval(1, true); + else + put_oval(0, true); +} + +void compile_decode_adr(char*label, unsigned argc, struct symb_s*argv) +{ + unsigned nfun = (argc + 3)/4; + vvp_ipoint_t ix = functor_allocate(nfun); + + vvp_decode_adr_s*a = new struct vvp_decode_adr_s(ix, argc); + + functor_define(ix, a); + + if (nfun > 0) { + extra_ports_functor_s *fu = new extra_ports_functor_s[nfun-1]; + for (unsigned idx = 1 ; idx < nfun ; idx += 1) { + fu[idx-1].base_ = ix; + functor_define(ipoint_index(ix, idx), fu+idx-1); + } + } + + inputs_connect(ix, argc, argv); + free(argv); + + decoder_save(label, a); + free(label); +} + +void compile_decode_en(char*label, char*decoder, int slice, + struct symb_s enable) +{ + vvp_decode_adr_s*adr = decoder_find(decoder); + vvp_decode_en_s*a = new struct vvp_decode_en_s(adr, slice); + + vvp_ipoint_t ix = functor_allocate(1); + functor_define(ix, a); + + if (enable.text) { + inputs_connect(ix, 1, &enable); + } + + define_functor_symbol(label, ix); + free(label); +} + +/* + * $Log: decoder.cc,v $ + * Revision 1.1.2.1 2006/02/19 00:11:36 steve + * Handle synthesis of FF vectors with l-value decoder. + * + */ + diff --git a/vvp/functor.h b/vvp/functor.h index eebec25a9..bb03ec376 100644 --- a/vvp/functor.h +++ b/vvp/functor.h @@ -19,11 +19,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: functor.h,v 1.52 2004/10/04 01:10:59 steve Exp $" +#ident "$Id: functor.h,v 1.52.2.1 2006/02/19 00:11:36 steve Exp $" #endif # include "pointers.h" # include "delay.h" +# include /* * The vvp_ipoint_t is an integral type that is 32bits. The low 2 bits @@ -340,9 +341,27 @@ extern vvp_ipoint_t *vvp_fvector_member(vvp_fvector_t v, unsigned i); extern vvp_fvector_t vvp_fvector_new(unsigned size); extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p); +inline static +unsigned char functor_get_inputs(vvp_ipoint_t ip) +{ + functor_t fp = functor_index(ip); + assert(fp); + return fp->ival; +} + +inline static +unsigned char functor_get_input(vvp_ipoint_t ip) +{ + unsigned char bits = functor_get_inputs(ip); + return (bits >> (2*ipoint_port(ip))) & 3; +} + /* * $Log: functor.h,v $ + * Revision 1.52.2.1 2006/02/19 00:11:36 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.52 2004/10/04 01:10:59 steve * Clean up spurious trailing white space. * diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 454271caa..41854b889 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: lexor.lex,v 1.43 2004/06/30 02:15:57 steve Exp $" +#ident "$Id: lexor.lex,v 1.43.2.1 2006/02/19 00:11:36 steve Exp $" #endif # include "parse_misc.h" @@ -95,6 +95,8 @@ ".cmp/ge.s" { return K_CMP_GE_S; } ".cmp/gt" { return K_CMP_GT; } ".cmp/gt.s" { return K_CMP_GT_S; } +".decode/adr" { return K_DECODE_ADR; } +".decode/en" { return K_DECODE_EN; } ".event" { return K_EVENT; } ".event/or" { return K_EVENT_OR; } ".functor" { return K_FUNCTOR; } @@ -182,6 +184,9 @@ int yywrap() /* * $Log: lexor.lex,v $ + * Revision 1.43.2.1 2006/02/19 00:11:36 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.43 2004/06/30 02:15:57 steve * Add signed LPM divide. * diff --git a/vvp/memory.cc b/vvp/memory.cc index 8e14d26fa..aca3411a2 100644 --- a/vvp/memory.cc +++ b/vvp/memory.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: memory.cc,v 1.22 2004/10/04 01:10:59 steve Exp $" +#ident "$Id: memory.cc,v 1.22.2.1 2006/02/19 00:11:36 steve Exp $" #endif #include "memory.h" @@ -292,21 +292,6 @@ unsigned char get_bit(vvp_memory_bits_t bits, int bit) return (get_nibble(bits, bit) >> (2*(bit&3))) & 3; } -inline static -unsigned char functor_get_inputs(vvp_ipoint_t ip) -{ - functor_t fp = functor_index(ip); - assert(fp); - return fp->ival; -} - -inline static -unsigned char functor_get_input(vvp_ipoint_t ip) -{ - unsigned char bits = functor_get_inputs(ip); - return (bits >> (2*ipoint_port(ip))) & 3; -} - static bool update_addr_bit(vvp_memory_port_t addr, vvp_ipoint_t ip) { @@ -509,6 +494,9 @@ void schedule_memory(vvp_memory_t mem, unsigned idx, /* * $Log: memory.cc,v $ + * Revision 1.22.2.1 2006/02/19 00:11:36 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.22 2004/10/04 01:10:59 steve * Clean up spurious trailing white space. * diff --git a/vvp/parse.y b/vvp/parse.y index 8c330b91e..41b031d0a 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.60 2004/10/04 01:10:59 steve Exp $" +#ident "$Id: parse.y,v 1.60.2.1 2006/02/19 00:11:36 steve Exp $" #endif # include "parse_misc.h" @@ -60,6 +60,7 @@ extern FILE*yyin; %token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT %token K_ARITH_SUB K_ARITH_SUM %token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S +%token K_DECODE_ADR K_DECODE_EN %token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM %token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC %token K_UDP K_UDP_C K_UDP_S @@ -262,6 +263,16 @@ statement compile_shiftr($1, $3, obj.cnt, obj.vect); } + /* Decoder nodes. */ + + | T_LABEL K_DECODE_ADR symbols ';' + { struct symbv_s obj = $3; + compile_decode_adr($1, obj.cnt, obj.vect); + } + + | T_LABEL K_DECODE_EN T_SYMBOL ',' T_NUMBER ',' symbol ';' + { compile_decode_en($1, $3, $5, $7); + } /* Event statements take a label, a type (the first T_SYMBOL) and a list of inputs. If the type is instead a string, then we have a @@ -635,6 +646,9 @@ int compile_design(const char*path) /* * $Log: parse.y,v $ + * Revision 1.60.2.1 2006/02/19 00:11:36 steve + * Handle synthesis of FF vectors with l-value decoder. + * * Revision 1.60 2004/10/04 01:10:59 steve * Clean up spurious trailing white space. *