diff --git a/design_dump.cc b/design_dump.cc index a82582220..5edec26af 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.4 2006/03/26 23:09:21 steve Exp $" +#ident "$Id: design_dump.cc,v 1.149.2.5 2006/04/16 19:26:37 steve Exp $" #endif # include "config.h" @@ -227,7 +227,8 @@ void NetDecode::dump_node(ostream&o, unsigned ind) const void NetDemux::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name() - << " word width=" << width() << ", address width=" << awidth() << endl; + << " bus width=" << width() << ", address width=" << awidth() + << ", word count=" << size() << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); } @@ -288,7 +289,8 @@ void NetFF::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_FF: " << name() << " scope=" << (scope()? scope()->name() : "") - << " aset_value=" << aset_value_; + << " aset_value=" << aset_value_ + << " sset_value=" << sset_value_; if (demux_) o << " demux=" << demux_->name(); @@ -1117,6 +1119,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.149.2.5 2006/04/16 19:26:37 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.149.2.4 2006/03/26 23:09:21 steve * Handle asynchronous demux/bit replacements. * diff --git a/ivl_target.h b/ivl_target.h index 8c155b62f..2fe6d05dd 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.2.4 2006/03/26 23:09:22 steve Exp $" +#ident "$Id: ivl_target.h,v 1.126.2.5 2006/04/16 19:26:37 steve Exp $" #endif #ifdef __cplusplus @@ -708,12 +708,23 @@ extern const char* ivl_udp_name(ivl_udp_t net); * idx the bit within the word. * * - IVL_LPM_DEMUX - * This device is a form of bit replacement. The device has a data + * This device is a form of bit replacement. The device has a data bus * width (ivl_lpm_width) and an address width. The Data outputs are - * ivl_lpm_q and have the data width. The ivl_lpm_data functions are + * ivl_lpm_q and have the data bus width. The ivl_lpm_data functions are * inputs to the device. Normally, the device passes the data inputs * through to the Q output. * + * The IVL_LPM_DEMUX also has a size (ivl_lpm_size) which is the + * number of addressable units in the device. If the device is bit- + * addressable, then the size is the same as the width. I.e. if + * ivl_lpm_width == ivl_lpm_size, then the address selects a single + * bit. If ivl_lpm_width/ivl_lpm_size == 8, then the address selects + * words of 8 bits and there are ivl_lpm_size of them. The + * ivl_lpm_width will always be an exact multiple of + * ivl_lpm_size. This is slightly different from the meaning of width + * in memory ports, but reflects that the DEMUX manipulates fixed + * width ranges within a single vector. + * * The ivl_lpm_select inputs address a bit of the device. The * addressed bit is substituted by the replacement bit. This * replacement bit comes from the ivl_lpm_datab(net,0) nexus. @@ -760,7 +771,7 @@ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern unsigned ivl_lpm_selects(ivl_lpm_t net); /* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); - /* IVL_LPM_MUX, IVL_LPM_RAM */ + /* IVL_LPM_DEMUX, IVL_LPM_MUX, IVL_LPM_RAM */ extern unsigned ivl_lpm_size(ivl_lpm_t net); /* IVL_LPM_RAM */ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); @@ -1301,6 +1312,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.126.2.5 2006/04/16 19:26:37 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.126.2.4 2006/03/26 23:09:22 steve * Handle asynchronous demux/bit replacements. * diff --git a/net_assign.cc b/net_assign.cc index 9ab26e6a9..f52b645cb 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_assign.cc,v 1.18.2.1 2006/03/12 07:34:17 steve Exp $" +#ident "$Id: net_assign.cc,v 1.18.2.2 2006/04/16 19:26:38 steve Exp $" #endif # include "config.h" @@ -61,6 +61,7 @@ NetAssign_::NetAssign_(NetVariable*s) loff_ = 0; lwid_ = 0; more = 0; + mem_lref_ = 0; } NetAssign_::~NetAssign_() @@ -73,7 +74,7 @@ NetAssign_::~NetAssign_() if (mem_) { NetNet*exp = mem_->reg_from_explode(); - if (exp) { + if (exp && mem_lref_) { exp->decr_lref(); if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0) exp->type(NetNet::WIRE); @@ -135,6 +136,16 @@ NetVariable* NetAssign_::var() const return var_; } +void NetAssign_::incr_mem_lref() +{ + if (! mem_lref_) { + assert(mem_); + NetNet*exp = mem_->reg_from_explode(); + assert(exp); + exp->incr_lref(); + mem_lref_ = true; + } +} void NetAssign_::set_part(unsigned lo, unsigned lw) { @@ -272,6 +283,9 @@ NetAssignNB::~NetAssignNB() /* * $Log: net_assign.cc,v $ + * Revision 1.18.2.2 2006/04/16 19:26:38 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.18.2.1 2006/03/12 07:34:17 steve * Fix the memsynth1 case. * diff --git a/net_nex_output.cc b/net_nex_output.cc index 4cab98c09..ce7149e1a 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_nex_output.cc,v 1.11.2.2 2006/03/12 07:34:17 steve Exp $" +#ident "$Id: net_nex_output.cc,v 1.11.2.3 2006/04/16 19:26:38 steve Exp $" #endif # include "config.h" @@ -76,11 +76,11 @@ void NetAssignBase::nex_output(NexusSet&out) out.add(tmp->pin(adr+idx).nexus()); } else { - /* Fake an address of 0. The context will - actually shove a decoder in place here. */ - long adr= 0; - for (unsigned idx = 0; idx < cur->lwidth(); idx += 1) - out.add(tmp->pin(adr+idx).nexus()); + /* Put all the bits of the memory into the + set. The synthesis will generate a + decoder to handle this. */ + for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1) + out.add(tmp->pin(idx).nexus()); } } else { @@ -154,6 +154,9 @@ void NetWhile::nex_output(NexusSet&out) /* * $Log: net_nex_output.cc,v $ + * Revision 1.11.2.3 2006/04/16 19:26:38 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.11.2.2 2006/03/12 07:34:17 steve * Fix the memsynth1 case. * diff --git a/netlist.cc b/netlist.cc index 70fff8faf..c2ea5daae 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.5 2006/03/26 23:09:22 steve Exp $" +#ident "$Id: netlist.cc,v 1.226.2.6 2006/04/16 19:26:38 steve Exp $" #endif # include "config.h" @@ -722,11 +722,12 @@ unsigned NetDecode::awidth() const } NetDemux::NetDemux(NetScope*s, perm_string name, - unsigned word_width, unsigned address_width) -: NetNode(s, name, word_width*2+address_width+1) + unsigned bus_width, unsigned address_width, unsigned size) +: NetNode(s, name, bus_width*2+address_width+bus_width/size) { - width_ = word_width; + width_ = bus_width; awidth_ = address_width; + size_ = size; for (unsigned idx = 0 ; idx < width_ ; idx += 1) { pin_Q(idx).set_dir(Link::OUTPUT); @@ -740,8 +741,10 @@ NetDemux::NetDemux(NetScope*s, perm_string name, pin_Address(idx).set_dir(Link::INPUT); pin_Address(idx).set_name(perm_string::literal("Address"), idx); } - pin_WriteData().set_dir(Link::INPUT); - pin_WriteData().set_name(perm_string::literal("Writedata"), 0); + for (unsigned idx = 0 ; idx < width_/size_ ; idx += 1) { + pin_WriteData(idx).set_dir(Link::INPUT); + pin_WriteData(idx).set_name(perm_string::literal("Writedata"), idx); + } } NetDemux::~NetDemux() @@ -758,6 +761,11 @@ unsigned NetDemux::awidth() const return awidth_; } +unsigned NetDemux::size() const +{ + return size_; +} + Link& NetDemux::pin_Q(unsigned idx) { assert(idx < width_); @@ -794,14 +802,16 @@ const Link& NetDemux::pin_Address(unsigned idx) const return pin(width_+width_+idx); } -Link& NetDemux::pin_WriteData() +Link& NetDemux::pin_WriteData(unsigned idx) { - return pin(width_+width_+awidth_); + assert(idx < width_/size_); + return pin(width_+width_+awidth_+idx); } -const Link& NetDemux::pin_WriteData() const +const Link& NetDemux::pin_WriteData(unsigned idx) const { - return pin(width_+width_+awidth_); + assert(idx < width_/size_); + return pin(width_+width_+awidth_+idx); } NetDecode* NetFF::get_demux() @@ -2211,7 +2221,7 @@ NetNet* NetMemory::explode_to_reg() return explode_; explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_); - explode_->mref(this); + //explode_->incr_lref(); return explode_; } @@ -2471,6 +2481,9 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.226.2.6 2006/04/16 19:26:38 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.226.2.5 2006/03/26 23:09:22 steve * Handle asynchronous demux/bit replacements. * diff --git a/netlist.h b/netlist.h index cee3b1f11..d59200795 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.15 2006/04/10 03:43:39 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.16 2006/04/16 19:26:38 steve Exp $" #endif /* @@ -645,31 +645,35 @@ class NetDemux : public NetNode { public: NetDemux(NetScope*s, perm_string name, - unsigned word_width, unsigned address_width); + unsigned bus_width, unsigned address_width, + unsigned size); ~NetDemux(); - // This is the width of the word. The width of the NetFF mem - // is an even multiple of this. + // This is the width of the bus that passes through the + // device. The address addresses into this width. unsigned width() const; // This is the width of the address. The address value for the // base of a word is the address * width(). unsigned awidth() const; + // This is the number of words in the width that can be + // addressed. This implies (by division) the width of a word. + unsigned size() const; Link& pin_Address(unsigned idx); Link& pin_Data(unsigned idx); Link& pin_Q(unsigned idx); - Link& pin_WriteData(); + Link& pin_WriteData(unsigned idx); const Link& pin_Address(unsigned idx) const; const Link& pin_Data(unsigned idx) const; const Link& pin_Q(unsigned idx) const; - const Link& pin_WriteData() const; + const Link& pin_WriteData(unsigned idx) const; virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; private: - unsigned width_, awidth_; + unsigned width_, awidth_, size_; private: void make_pins_(unsigned wid, unsigned awid); @@ -1564,6 +1568,8 @@ class NetAssign_ { // into a wire. void turn_sig_to_wire_on_release(); + void incr_mem_lref(); + // It is possible that l-values can have *inputs*, as well as // being outputs. For example foo[idx] = ... is the l-value // (NetAssign_ object) with a foo l-value and the input @@ -1584,6 +1590,7 @@ class NetAssign_ { bool turn_sig_to_wire_on_release_; unsigned loff_; unsigned lwid_; + bool mem_lref_; }; class NetAssignBase : public NetProc { @@ -1627,6 +1634,11 @@ class NetAssignBase : public NetProc { void dump_lval(ostream&) const; virtual void dump(ostream&, unsigned ind) const; + private: + bool synth_async_mem_sync_(Design*des, NetScope*scope, + NetAssign_*cur, NetNet*rsig, unsigned&roff, + NetNet*nex_map, NetNet*nex_out); + private: NetAssign_*lval_; NetExpr *rval_; @@ -3512,6 +3524,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.16 2006/04/16 19:26:38 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.321.2.15 2006/04/10 03:43:39 steve * Exploded memories accessed by constant indices. * diff --git a/synth2.cc b/synth2.cc index b1d54ecce..e15afd45c 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.28 2006/04/10 03:43:40 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.29 2006/04/16 19:26:39 steve Exp $" #endif # include "config.h" @@ -126,19 +126,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, sync_flag must be true in this case. */ if (lmem) { assert(sync_flag); - NetNet*msig = lmem->explode_to_reg(); - msig->incr_lref(); - - if (NetEConst*ae = dynamic_cast(cur->bmux())) { - long adr= ae->value().as_long(); - adr = lmem->index_to_address(adr) * lmem->width(); - for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) { - unsigned off = adr+idx; - unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); - assert(ptr <= nex_map->pin_count()); - connect(nex_out->pin(ptr), rsig->pin(roff+idx)); - } - } + synth_async_mem_sync_(des, scope, cur, rsig, roff, + nex_map, nex_out); continue; } @@ -171,7 +160,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, NetDemux*dq = new NetDemux(scope, scope->local_symbol(), lsig->pin_count(), - adr->pin_count()); + adr->pin_count(), + lsig->pin_count()); des->add_node(dq); dq->set_line(*this); @@ -190,7 +180,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, for (unsigned idx = 0 ; idx < lsig->pin_count(); idx += 1) connect(dq->pin_Data(idx), nex_map->pin(roff+idx)); - connect(dq->pin_WriteData(), rsig->pin(roff)); + connect(dq->pin_WriteData(0), rsig->pin(roff)); roff += cur->lwidth(); cur->turn_sig_to_wire_on_release(); @@ -224,6 +214,73 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, return true; } +/* + * Handle the special case of assignment to memory. Explode the memory + * to an array of reg bits. The context that is calling this will + * attach a decoder between the ff and the r-val. In fact, the memory + * at this point has already been scanned and exploded, so the + * explode_to_reg method below will return a pre-existing vector. + */ +bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope, + NetAssign_*cur, + NetNet*rsig, unsigned&roff, + NetNet*nex_map, NetNet*nex_out) +{ + NetMemory*lmem = cur->mem(); + assert(lmem); + + NetNet*msig = lmem->explode_to_reg(); + cur->incr_mem_lref(); + + /* Handle the special case that the mux expression is + constant. In this case, just hook up the pertinent bits. */ + if (NetEConst*ae = dynamic_cast(cur->bmux())) { + long adr= ae->value().as_long(); + adr = lmem->index_to_address(adr) * lmem->width(); + for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) { + unsigned off = adr+idx; + unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); + assert(ptr <= nex_map->pin_count()); + connect(nex_out->pin(ptr), rsig->pin(roff+idx)); + } + + cur->turn_sig_to_wire_on_release(); + return true; + } + + assert(cur->bmux() != 0); + + NetNet*adr = cur->bmux()->synthesize(des); + + NetDemux*dq = new NetDemux(scope, scope->local_symbol(), + msig->pin_count(), + adr->pin_count(), + msig->pin_count() / cur->lwidth()); + 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)); + + for (unsigned idx = 0; idx < msig->pin_count(); idx += 1) { + unsigned off = idx; + unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); + assert(ptr <= nex_map->pin_count()); + connect(nex_out->pin(ptr), dq->pin_Q(idx)); + } + + for (unsigned idx = 0 ; idx < msig->pin_count(); idx += 1) + connect(dq->pin_Data(idx), nex_map->pin(roff+idx)); + + for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) + connect(dq->pin_WriteData(idx), rsig->pin(roff+idx)); + + roff += cur->lwidth(); + cur->turn_sig_to_wire_on_release(); + + return true; +} + /* * Sequential blocks are translated to asynchronous logic by * translating each statement of the block, in order, into gates. The @@ -951,7 +1008,7 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, if (demux->mem() && dynamic_cast(demux->bmux())) { NetMemory*lmem = demux->mem(); NetNet*msig = lmem->explode_to_reg(); - msig->incr_lref(); + demux->incr_mem_lref(); NetEConst*ae = dynamic_cast(demux->bmux()); long adr = ae->value().as_long(); @@ -985,7 +1042,7 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, if (lval_->mem()) { NetNet*exp = lval_->mem()->reg_from_explode(); assert(exp); - exp->incr_lref(); + lval_->incr_mem_lref(); } lval_->turn_sig_to_wire_on_release(); return true; @@ -1441,17 +1498,22 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, break; } - if (! tmp.is_defined()) - cerr << get_line() << ": internal error: " - << "Strange clr r-value=" << tmp << endl; - assert(tmp.is_defined()); if (tmp.is_zero()) { connect(ff->pin_Sclr(), rst->pin(0)); + if (debug_synth) + cerr << get_line() << ": debug: " + << "Create a synchronous clr (set=0) for " + << ff->width() << " bit ff." << endl; } else { connect(ff->pin_Sset(), rst->pin(0)); ff->sset_value(tmp); + + if (debug_synth) + cerr << get_line() << ": debug: " + << "Create a synchronous set for " + << ff->width() << " bit ff." << endl; } delete a_set; @@ -1748,6 +1810,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.39.2.29 2006/04/16 19:26:39 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.39.2.28 2006/04/10 03:43:40 steve * Exploded memories accessed by constant indices. * diff --git a/t-dll-api.cc b/t-dll-api.cc index b070e72ad..5ae31a3cf 100644 --- a/t-dll-api.cc +++ b/t-dll-api.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-api.cc,v 1.108.2.4 2006/03/26 23:09:24 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.108.2.5 2006/04/16 19:26:40 steve Exp $" #endif # include "config.h" @@ -806,8 +806,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx) return net->u_.arith.b[idx]; case IVL_LPM_DEMUX: - assert(idx < 1); - return net->u_.demux.bit_in; + assert(idx < net->u_.demux.width/net->u_.demux.size); + return net->u_.demux.bit_in[idx]; default: assert(0); @@ -1058,6 +1058,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) { switch (net->type) { + case IVL_LPM_DEMUX: + return net->u_.demux.size; case IVL_LPM_MUX: return net->u_.mux.size; case IVL_LPM_RAM: @@ -2002,6 +2004,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.108.2.5 2006/04/16 19:26:40 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.108.2.4 2006/03/26 23:09:24 steve * Handle asynchronous demux/bit replacements. * diff --git a/t-dll.cc b/t-dll.cc index 2b5b6d5d6..bc3b86646 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.6 2006/03/26 23:09:24 steve Exp $" +#ident "$Id: t-dll.cc,v 1.131.2.7 2006/04/16 19:26:40 steve Exp $" #endif # include "config.h" @@ -1552,6 +1552,7 @@ bool dll_target::lpm_demux(const NetDemux*net) unsigned idx; unsigned width = net->width(); unsigned awid = net->awidth(); + unsigned size = net->size(); ivl_lpm_t obj = new struct ivl_lpm_s; obj->type = IVL_LPM_DEMUX; obj->name = net->name(); @@ -1562,11 +1563,13 @@ bool dll_target::lpm_demux(const NetDemux*net) obj->u_.demux.width = width; obj->u_.demux.awid = awid; + obj->u_.demux.size = net->size(); - ivl_nexus_t*tmp = new ivl_nexus_t [2*net->width() + net->awidth()]; + ivl_nexus_t*tmp = new ivl_nexus_t [2*width + awid + width/size]; obj->u_.demux.q = tmp; obj->u_.demux.d = tmp + width; obj->u_.demux.a = tmp + 2*width; + obj->u_.demux.bit_in = tmp + 2*width + awid; for (idx = 0 ; idx < width ; idx += 1) { const Nexus*nex = net->pin_Q(idx).nexus(); @@ -1592,11 +1595,11 @@ bool dll_target::lpm_demux(const NetDemux*net) IVL_DR_HiZ, IVL_DR_HiZ); } - { - const Nexus*nex = net->pin_WriteData().nexus(); + for (idx = 0 ; idx < width/size ; idx += 1) { + const Nexus*nex = net->pin_WriteData(idx).nexus(); assert(nex->t_cookie()); - obj->u_.demux.bit_in = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.demux.bit_in, obj, 0, + obj->u_.demux.bit_in[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.demux.bit_in[idx], obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); } @@ -2331,6 +2334,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.131.2.7 2006/04/16 19:26:40 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.131.2.6 2006/03/26 23:09:24 steve * Handle asynchronous demux/bit replacements. * diff --git a/t-dll.h b/t-dll.h index e7277d7a9..654ece579 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.2.4 2006/03/26 23:09:25 steve Exp $" +#ident "$Id: t-dll.h,v 1.115.2.5 2006/04/16 19:26:40 steve Exp $" #endif # include "target.h" @@ -346,7 +346,8 @@ struct ivl_lpm_s { struct ivl_lpm_demux_s { unsigned width; unsigned awid; - ivl_nexus_t bit_in; + unsigned size; + ivl_nexus_t*bit_in; ivl_nexus_t *q,*d,*a; } demux; @@ -702,6 +703,9 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.115.2.5 2006/04/16 19:26:40 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.115.2.4 2006/03/26 23:09:25 steve * Handle asynchronous demux/bit replacements. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 62bab132c..804e8dd33 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.8 2006/03/26 23:09:25 steve Exp $" +#ident "$Id: stub.c,v 1.90.2.9 2006/04/16 19:26:41 steve Exp $" #endif # include "config.h" @@ -238,9 +238,14 @@ static void show_lpm_demux(ivl_lpm_t net) unsigned idx; unsigned width = ivl_lpm_width(net); unsigned awid = ivl_lpm_selects(net); + unsigned size = ivl_lpm_size(net); - fprintf(out, " LPM_DEMUX %s (word-width=%u, addr-width=%u)\n", - ivl_lpm_basename(net), width, awid); + fprintf(out, " LPM_DEMUX %s (bus-width=%u, addr-width=%u, size=%u)\n", + ivl_lpm_basename(net), width, awid, size); + + if (width%size != 0) { + fprintf(out, " ERROR: width %% size == %u\n", width%size); + } for (idx = 0 ; idx < width ; idx += 1) fprintf(out, " Q %u: %s\n", idx, @@ -256,9 +261,9 @@ static void show_lpm_demux(ivl_lpm_t net) nex? ivl_nexus_name(nex) : ""); } - { - ivl_nexus_t nex = ivl_lpm_datab(net, 0); - fprintf(out, " WriteIn: %s\n", + for (idx = 0 ; idx < width/size ; idx += 1) { + ivl_nexus_t nex = ivl_lpm_datab(net, idx); + fprintf(out, " WriteIn %u: %s\n", idx, nex? ivl_nexus_name(nex) : ""); } } @@ -463,6 +468,8 @@ static void show_lpm(ivl_lpm_t net) if (ivl_lpm_sync_set(net)) { fprintf(out, " Sset: %s\n", ivl_nexus_name(ivl_lpm_sync_set(net))); + if (ivl_lpm_sset_value(net)) + show_expression(ivl_lpm_sset_value(net), 10); } for (idx = 0 ; idx < width ; idx += 1) @@ -1107,6 +1114,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.90.2.9 2006/04/16 19:26:41 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.90.2.8 2006/03/26 23:09:25 steve * Handle asynchronous demux/bit replacements. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 89d761210..87ef5d9f6 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.5 2006/03/26 23:09:26 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.103.2.6 2006/04/16 19:26:41 steve Exp $" #endif # include "vvp_priv.h" @@ -1302,41 +1302,47 @@ static void draw_lpm_decode(ivl_lpm_t net) */ static void draw_lpm_demux(ivl_lpm_t net) { - unsigned idx; + unsigned idx, wbit; unsigned width = ivl_lpm_width(net); + unsigned size = ivl_lpm_size(net); + unsigned word = width / size; + + assert(width%size == 0); /* Draw a .decode/adr node to do address decoding. */ draw_lpm_decode(net); - for (idx = 0 ; idx < width ; idx += 1) { - ivl_nexus_t nex; + for (wbit = 0 ; wbit < word ; wbit += 1) { + for (idx = wbit ; idx < width ; idx += word) { + ivl_nexus_t nex; - /* This is a demux bit slice idx */ - fprintf(vvp_out, "L_%s.%s/%u .demux ", - vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), - vvp_mangle_id(ivl_lpm_basename(net)), idx); + /* This is a demux bit slice idx */ + fprintf(vvp_out, "L_%s.%s/%u .demux ", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net)), idx); - /* Reference the address decoder... */ - fprintf(vvp_out, "L_%s.%s, %u, ", - vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), - vvp_mangle_id(ivl_lpm_basename(net)), idx); + /* Reference the address decoder... */ + fprintf(vvp_out, "L_%s.%s, %u, ", + vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), + vvp_mangle_id(ivl_lpm_basename(net)), idx/word); - /* not-selected bit value. */ - nex = ivl_lpm_data(net, idx); - if (nex) - draw_input_from_net(nex); - else - fprintf(vvp_out, "C"); + /* not-selected bit value. */ + nex = ivl_lpm_data(net, idx); + if (nex) + draw_input_from_net(nex); + else + fprintf(vvp_out, "C"); - /* selected bit value. */ - fprintf(vvp_out, ", "); - nex = ivl_lpm_datab(net, 0); - if (nex) - draw_input_from_net(nex); - else - fprintf(vvp_out, "C"); + /* selected bit value. */ + fprintf(vvp_out, ", "); + nex = ivl_lpm_datab(net, wbit); + if (nex) + draw_input_from_net(nex); + else + fprintf(vvp_out, "C"); - fprintf(vvp_out, ";\n"); + fprintf(vvp_out, ";\n"); + } } } @@ -1390,7 +1396,9 @@ static void draw_lpm_eq(ivl_lpm_t net) static void draw_lpm_ff(ivl_lpm_t net) { ivl_expr_t aset_expr = 0; + ivl_expr_t sset_expr = 0; const char*aset_bits = 0; + const char*sset_bits = 0; unsigned width, idx; ivl_attribute_t clock_pol = find_lpm_attr(net, "ivl:clock_polarity"); @@ -1439,6 +1447,12 @@ static void draw_lpm_ff(ivl_lpm_t net) aset_bits = ivl_expr_bits(aset_expr); } + sset_expr = ivl_lpm_sset_value(net); + if (sset_expr) { + assert(ivl_expr_width(sset_expr) == width); + sset_bits = ivl_expr_bits(sset_expr); + } + /* If there is a synchronous clear or set, then draw a compound enable that includes the Sclr or Sset input. We will use this for the enable of the basic DFF. */ @@ -1480,7 +1494,10 @@ static void draw_lpm_ff(ivl_lpm_t net) vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), vvp_mangle_id(ivl_lpm_basename(net)), idx); draw_input_from_net(ivl_lpm_data(net,idx)); - fprintf(vvp_out, ", C<1>, "); + if (sset_bits[idx] == '1') + fprintf(vvp_out, ", C<1>, "); + else + fprintf(vvp_out, ", C<0>, "); draw_input_from_net(ivl_lpm_sync_set(net)); fprintf(vvp_out, ", C<1>;\n"); } @@ -1869,6 +1886,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.103.2.6 2006/04/16 19:26:41 steve + * Fix handling of exploded memories with partial or missing resets. + * * Revision 1.103.2.5 2006/03/26 23:09:26 steve * Handle asynchronous demux/bit replacements. *