From e35ed6e91c8e8abb7fc5c6162433a0315086c91a Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 25 Aug 2001 23:50:02 +0000 Subject: [PATCH] Change the NetAssign_ class to refer to the signal instead of link into the netlist. This is faster and uses less space. Make the NetAssignNB carry the delays instead of the NetAssign_ lval objects. Change the vvp code generator to support multiple l-values, i.e. concatenations of part selects. --- design_dump.cc | 49 +++++--- elab_lval.cc | 73 ++++------- elaborate.cc | 47 ++++--- emit.cc | 17 +-- ivl.def | 2 + ivl_target.h | 41 +++++-- link_const.cc | 27 +++- net_assign.cc | 86 +++++++++++-- netlist.cc | 17 ++- netlist.h | 42 ++++++- syn-rules.y | 10 +- t-dll-api.cc | 30 ++++- t-dll-proc.cc | 64 ++++------ t-dll.h | 23 ++-- t-vvm.cc | 74 ++++++----- target.cc | 17 +-- target.h | 12 +- tgt-vvp/vvp_process.c | 277 +++++++++++++++++++++++------------------- 18 files changed, 560 insertions(+), 348 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 6c15cb3f1..37ad3ce19 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.116 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: design_dump.cc,v 1.117 2001/08/25 23:50:02 steve Exp $" #endif # include "config.h" @@ -237,15 +237,6 @@ void NetMux::dump_node(ostream&o, unsigned ind) const dump_obj_attr(o, ind+4); } -void NetAssign_::dump_node(ostream&o, unsigned ind) const -{ - o << setw(ind) << "" << "Procedural assign (NetAssign_): " << name(); - if (bmux()) - o << "[" << *bmux() << "]"; - o << endl; - dump_node_pins(o, ind+4); -} - void NetBUFZ::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "NetBUFZ: " << name() @@ -417,16 +408,29 @@ void NetProcTop::dump(ostream&o, unsigned ind) const statement_->dump(o, ind+2); } +void NetAssign_::dump_lval(ostream&o) const +{ + if (sig_) { + o << sig_->name(); + if (bmux_) { + o << "[" << *bmux_ << "]"; + + } else { + o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]"; + } + } else { + o << ""; + } +} + void NetAssignBase::dump_lval(ostream&o) const { - o << "" << "{" << lval_->name(); - if (lval_->bmux()) - o << "[" << *lval_->bmux() << "]"; + o << "{"; + lval_->dump_lval(o); for (NetAssign_*cur = lval_->more ; cur ; cur = cur->more) { - o << ", " << cur->name(); - if (cur->bmux()) - o << "[" << *cur->bmux() << "]"; + o << ", "; + cur->dump_lval(o); } o << "}"; @@ -439,8 +443,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const dump_lval(o); o << " = "; +#if 0 if (l_val(0)->rise_time()) o << "#" << l_val(0)->rise_time() << " "; +#endif o << *rval() << ";" << endl; } @@ -450,8 +456,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const dump_lval(o); o << " <= "; +#if 0 if (l_val(0)->rise_time()) o << "#" << l_val(0)->rise_time() << " "; +#endif o << *rval() << ";" << endl; } @@ -960,6 +968,15 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.117 2001/08/25 23:50:02 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.116 2001/07/27 04:51:44 steve * Handle part select expressions as variants of * NetESignal/IVL_EX_SIGNAL objects, instead of diff --git a/elab_lval.cc b/elab_lval.cc index 7aea1003c..4a56f4685 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_lval.cc,v 1.13 2001/07/25 03:10:48 steve Exp $" +#ident "$Id: elab_lval.cc,v 1.14 2001/08/25 23:50:02 steve Exp $" #endif # include "config.h" @@ -74,10 +74,7 @@ NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const return 0; } - NetAssign_*lv = new NetAssign_(scope->local_symbol(), ll->pin_count()); - for (unsigned idx = 0 ; idx < ll->pin_count() ; idx += 1) - connect(lv->pin(idx), ll->pin(idx)); - des->add_node(lv); + NetAssign_*lv = new NetAssign_(ll); return lv; } @@ -116,42 +113,15 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const assert(tmp); - /* If adjacent l-values in the concatenation are not bit - selects, then merge them into a single NetAssign_ - object. - If we cannot merge, then just link the new one to the - previous one. */ + /* Link the new l-value to the previous one. */ - if (res && (res->bmux() == 0) && (tmp->bmux() == 0)) { - unsigned wid1 = tmp->pin_count(); - unsigned wid2 = res->pin_count() + tmp->pin_count(); - NetAssign_*tmp2 = new NetAssign_(res->name(), wid2); + NetAssign_*last = tmp; + while (last->more) + last = last->more; - assert(tmp->more == 0); - - tmp2->more = res->more; - res->more = 0; - - for (unsigned idx = 0 ; idx < wid1 ; idx += 1) - connect(tmp2->pin(idx), tmp->pin(idx)); - - for (unsigned idx = 0 ; idx < res->pin_count() ; idx += 1) - connect(tmp2->pin(idx+wid1), res->pin(idx)); - - delete res; - delete tmp; - res = tmp2; - des->add_node(res); - - } else { - NetAssign_*last = tmp; - while (last->more) - last = last->more; - - last->more = res; - res = tmp; - } + last->more = res; + res = tmp; } return res; @@ -259,13 +229,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const if (mux) { /* If there is a non-constant bit select, make a - NetAssign_ the width of the target reg and attach a + NetAssign_ to the target reg and attach a bmux to select the target bit. */ - unsigned wid = reg->pin_count(); - lv = new NetAssign_(des->local_symbol(scope->name()), wid); - - for (unsigned idx = 0 ; idx < wid ; idx += 1) - connect(lv->pin(idx), reg->pin(idx)); + lv = new NetAssign_(reg); lv->set_bmux(mux); @@ -278,8 +244,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const unsigned moff = reg->sb_to_idx(msb); unsigned wid = moff - loff + 1; - lv = new NetAssign_(des->local_symbol(scope->name()), wid); - if (moff < loff) { cerr << get_line() << ": error: part select " << reg->name() << "[" << msb<<":"<pin_count()); - for (unsigned idx = 0 ; idx < wid ; idx += 1) - connect(lv->pin(idx), reg->pin(idx+loff)); + lv = new NetAssign_(reg); + lv->set_part(loff, wid); + assert(moff < reg->pin_count()); } - des->add_node(lv); - return lv; } /* * $Log: elab_lval.cc,v $ + * Revision 1.14 2001/08/25 23:50:02 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.13 2001/07/25 03:10:48 steve * Create a config.h.in file to hold all the config * junk, and support gcc 3.0. (Stephan Boettcher) diff --git a/elaborate.cc b/elaborate.cc index 9c42b0f44..fb5aa6453 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.219 2001/08/01 05:17:31 steve Exp $" +#ident "$Id: elaborate.cc,v 1.220 2001/08/25 23:50:02 steve Exp $" #endif # include "config.h" @@ -927,12 +927,12 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const if (rise_time || event_) { string n = des->local_symbol(path); - unsigned wid = lv->pin_count(); + unsigned wid = lv->lwidth(); - rv->set_width(lv->pin_count()); - rv = pad_to_width(rv, lv->pin_count()); + rv->set_width(wid); + rv = pad_to_width(rv, wid); - if (! rv->set_width(lv->pin_count())) { + if (! rv->set_width(wid)) { cerr << get_line() << ": error: Unable to match " "expression width of " << rv->expr_width() << " to l-value width of " << wid << "." << endl; @@ -947,11 +947,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const /* Generate an assignment of the l-value to the temporary... */ n = des->local_symbol(path); - NetAssign_*lvt = new NetAssign_(n, wid); - des->add_node(lvt); - - for (unsigned idx = 0 ; idx < wid ; idx += 1) - connect(lvt->pin(idx), tmp->pin(idx)); + NetAssign_*lvt = new NetAssign_(tmp); NetAssign*a1 = new NetAssign(lvt, rv); a1->set_line(*this); @@ -1078,13 +1074,12 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const unsigned long rise_time, fall_time, decay_time; delay_.eval_delays(des, path, rise_time, fall_time, decay_time); - lv->rise_time(rise_time); - lv->fall_time(fall_time); - lv->decay_time(decay_time); - /* All done with this node. mark its line number and check it in. */ NetAssignNB*cur = new NetAssignNB(lv, rv); + cur->rise_time(rise_time); + cur->fall_time(fall_time); + cur->decay_time(decay_time); cur->set_line(*this); return cur; } @@ -1409,10 +1404,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const continue; NetExpr*rv = parms_[idx]->elaborate_expr(des, scope); - NetAssign_*lv = new NetAssign_("@", port->pin_count()); - des->add_node(lv); - for (unsigned pi = 0 ; pi < port->pin_count() ; pi += 1) - connect(port->pin(pi), lv->pin(pi)); + NetAssign_*lv = new NetAssign_(port); NetAssign*pr = new NetAssign(lv, rv); block->append(pr); } @@ -1971,10 +1963,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const return 0; } assert(sig); - NetAssign_*lv = new NetAssign_("@for-assign", sig->pin_count()); - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) - connect(lv->pin(idx), sig->pin(idx)); - des->add_node(lv); + NetAssign_*lv = new NetAssign_(sig); /* Make the r-value of the initial assignment, and size it properly. Then use it to build the assignment statement. */ @@ -2001,10 +1990,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const statement. Put this into the "body" block. */ sig = des->find_signal(scope, id2->name()); assert(sig); - lv = new NetAssign_("@for-assign", sig->pin_count()); - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) - connect(lv->pin(idx), sig->pin(idx)); - des->add_node(lv); + lv = new NetAssign_(sig); /* Make the rvalue of the increment expression, and size it for the lvalue. */ @@ -2362,6 +2348,15 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.220 2001/08/25 23:50:02 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.219 2001/08/01 05:17:31 steve * Accept empty port lists to module instantiation. * diff --git a/emit.cc b/emit.cc index 51bf2099c..6bce57806 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: emit.cc,v 1.61 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: emit.cc,v 1.62 2001/08/25 23:50:02 steve Exp $" #endif # include "config.h" @@ -57,12 +57,6 @@ bool NetAddSub::emit_node(struct target_t*tgt) const return true; } -bool NetAssign_::emit_node(struct target_t*tgt) const -{ - tgt->net_assign(this); - return true; -} - bool NetCaseCmp::emit_node(struct target_t*tgt) const { tgt->net_case_cmp(this); @@ -476,6 +470,15 @@ bool emit(const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.62 2001/08/25 23:50:02 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.61 2001/07/27 04:51:44 steve * Handle part select expressions as variants of * NetESignal/IVL_EX_SIGNAL objects, instead of diff --git a/ivl.def b/ivl.def index 823eab3cc..ad9fb300d 100644 --- a/ivl.def +++ b/ivl.def @@ -63,8 +63,10 @@ ivl_lpm_width ivl_lval_idx ivl_lval_mem ivl_lval_mux +ivl_lval_part_off ivl_lval_pin ivl_lval_pins +ivl_lval_sig ivl_memory_basename ivl_memory_name diff --git a/ivl_target.h b/ivl_target.h index cfd1df16a..03ff40d62 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: ivl_target.h,v 1.76 2001/08/10 00:40:45 steve Exp $" +#ident "$Id: ivl_target.h,v 1.77 2001/08/25 23:50:03 steve Exp $" #endif #ifdef __cplusplus @@ -551,11 +551,17 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); /* LVAL * The l-values of assignments are concatenation of ivl_lval_t - * objects. Each l-value has a bunch of connections (in the form of - * ivl_nexus_t objects) and possibly a mux expression. The compiler - * takes care of part selects and nested concatenations. The - * ivl_stmt_lval function pulls ivl_lval_t objects out of the - * statement. + * objects. Each lvi_lval_t object is an assignment to a var or a + * memory, through a bit select, part select or word select. + * + * Var lvals are things like assignments to a part select or a bit + * select. Assignment to the whole variable is a special case of a + * part select, as is a bit select with a constant expression. The + * ivl_lval_pins statement returns the width of the part select for + * the lval. The ivl_lval_pin function returns the nexus to the N-th + * bit of the part select. The compiler takes care of positioning the + * part select so that ivl_lval_pin(net, 0) is the proper bit in the + * signal. * * ivl_lval_mux * If the l-value includes a bit select expression, this method @@ -567,6 +573,14 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); * ivl_memory_t that represents that memory. Otherwise, it * returns 0. * + * ivl_lval_sig + * If the l-value is a variable, this method returns the signal + * object that is the target of the assign. + * + * ivl_lval_part_off + * The part select of the signal is based here. This is the + * canonical index of bit-0 of the part select. + * * ivl_lval_idx * If the l-value is a memory, this method returns an * ivl_expr_t that represents the index expression. Otherwise, it @@ -576,14 +590,16 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); * Return an ivl_nexus_t for the connection of the ivl_lval_t. * * ivl_lval_pins - * Return the number of pins for this object. */ + * Return the number of pins for this object. + */ extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); extern ivl_expr_t ivl_lval_idx(ivl_lval_t net); extern ivl_memory_t ivl_lval_mem(ivl_lval_t net); +extern unsigned ivl_lval_part_off(ivl_lval_t net); extern unsigned ivl_lval_pins(ivl_lval_t net); extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx); - +extern ivl_signal_t ivl_lval_sig(ivl_lval_t net); /* NEXUS * connections of signals and nodes is handled by single-bit @@ -907,6 +923,15 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.77 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.76 2001/08/10 00:40:45 steve * tgt-vvp generates code that skips nets as inputs. * diff --git a/link_const.cc b/link_const.cc index 91d885722..d28bccc38 100644 --- a/link_const.cc +++ b/link_const.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: link_const.cc,v 1.10 2001/07/25 03:10:49 steve Exp $" +#ident "$Id: link_const.cc,v 1.11 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -44,9 +44,18 @@ bool link_drivers_constant(const Link&lnk) if (cur->get_dir() == Link::INPUT) continue; - /* If this is an input or input port of a root module, + /* If this is an input or inout port of a root module, then the is probably not a constant value. I - certainly don't know what the value is, anyhow. */ + certainly don't know what the value is, anyhow. This + can happen in cases like this: + + module main(sig); + input sig; + endmodule + + If main is a root module (it has no parent) then sig + is not constant because it connects to an unspecified + outside world. */ if (sig = dynamic_cast(cur->get_obj())) do { if (sig->port_type() == NetNet::NOT_A_PORT) @@ -63,7 +72,8 @@ bool link_drivers_constant(const Link&lnk) /* If the link is PASSIVE then it doesn't count as a - driver if its initial value is Vz. */ + driver if its initial value is Vz. PASSIVE nodes + include wires and tri nets. */ if (cur->get_dir() == Link::PASSIVE) continue; @@ -113,6 +123,15 @@ verinum::V driven_value(const Link&lnk) /* * $Log: link_const.cc,v $ + * Revision 1.11 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.10 2001/07/25 03:10:49 steve * Create a config.h.in file to hold all the config * junk, and support gcc 3.0. (Stephan Boettcher) diff --git a/net_assign.cc b/net_assign.cc index 5e612e7f1..dcebc85b0 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: net_assign.cc,v 1.7 2001/07/25 03:10:49 steve Exp $" +#ident "$Id: net_assign.cc,v 1.8 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -38,19 +38,18 @@ unsigned count_lval_width(const NetAssign_*idx) return wid; } -NetAssign_::NetAssign_(const string&n, unsigned w) -: NetNode(n, w), bmux_(0) +NetAssign_::NetAssign_(NetNet*s) +: sig_(s), bmux_(0) { - for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { - pin(idx).set_dir(Link::OUTPUT); - pin(idx).set_name("P", idx); - } - + loff_ = 0; + lwid_ = sig_->pin_count(); + sig_->incr_eref(); more = 0; } NetAssign_::~NetAssign_() { + if (sig_) sig_->decr_eref(); assert( more == 0 ); if (bmux_) delete bmux_; } @@ -69,7 +68,34 @@ const NetExpr* NetAssign_::bmux() const unsigned NetAssign_::lwidth() const { if (bmux_) return 1; - else return pin_count(); + else return lwid_; +} + +const char*NetAssign_::name() const +{ + if (sig_) { + return sig_->name(); + } else { + return ""; + } +} + +NetNet* NetAssign_::sig() const +{ + assert(sig_); + return sig_; +} + +void NetAssign_::set_part(unsigned lo, unsigned lw) +{ + loff_ = lo; + lwid_ = lw; + assert(sig_->pin_count() >= (lo + lw)); +} + +unsigned NetAssign_::get_loff() const +{ + return loff_; } NetAssignBase::NetAssignBase(NetAssign_*lv, NetExpr*rv) @@ -167,14 +193,56 @@ NetAssign::~NetAssign() NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv) : NetAssignBase(lv, rv) { + rise_time_ = 0; + fall_time_ = 0; + decay_time_ = 0; } NetAssignNB::~NetAssignNB() { } +void NetAssignNB::rise_time(unsigned t) +{ + rise_time_ = t; +} + +void NetAssignNB::fall_time(unsigned t) +{ + fall_time_ = t; +} + +void NetAssignNB::decay_time(unsigned t) +{ + decay_time_ = t; +} + +unsigned NetAssignNB::rise_time() const +{ + return rise_time_; +} + +unsigned NetAssignNB::fall_time() const +{ + return fall_time_; +} + +unsigned NetAssignNB::decay_time() const +{ + return decay_time_; +} + /* * $Log: net_assign.cc,v $ + * Revision 1.8 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.7 2001/07/25 03:10:49 steve * Create a config.h.in file to hold all the config * junk, and support gcc 3.0. (Stephan Boettcher) diff --git a/netlist.cc b/netlist.cc index 9d191dffb..40de3ef11 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.169 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: netlist.cc,v 1.170 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -363,16 +363,21 @@ NetNet::NetNet(NetScope*s, const string&n, Type t, long ms, long ls) assert(s); verinum::V init_value = verinum::Vz; + Link::DIR dir = Link::PASSIVE; + switch (t) { case REG: case IMPLICIT_REG: init_value = verinum::Vx; + dir = Link::OUTPUT; break; case SUPPLY0: init_value = verinum::V0; + dir = Link::OUTPUT; break; case SUPPLY1: init_value = verinum::V1; + dir = Link::OUTPUT; break; default: break; @@ -380,6 +385,7 @@ NetNet::NetNet(NetScope*s, const string&n, Type t, long ms, long ls) for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { pin(idx).set_name("P", idx); + pin(idx).set_dir(dir); pin(idx).set_init(init_value); } @@ -2385,6 +2391,15 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.170 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.169 2001/07/27 04:51:44 steve * Handle part select expressions as variants of * NetESignal/IVL_EX_SIGNAL objects, instead of diff --git a/netlist.h b/netlist.h index e31467177..9f20ebe88 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.213 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: netlist.h,v 1.214 2001/08/25 23:50:03 steve Exp $" #endif /* @@ -1162,10 +1162,10 @@ class NetProc : public LineInfo { * should know that this is not a guarantee. */ -class NetAssign_ : public NetNode { +class NetAssign_ { public: - NetAssign_(const string&n, unsigned w); + NetAssign_(NetNet*sig); ~NetAssign_(); // If this expression exists, then only a single bit is to be @@ -1173,21 +1173,32 @@ class NetAssign_ : public NetNode { // the pin that gets the value. const NetExpr*bmux() const; + unsigned get_loff() const; + void set_bmux(NetExpr*); + void set_part(unsigned loff, unsigned wid); // Get the width of the r-value that this node expects. This // method accounts for the presence of the mux, so it not // nexessarily the same as the pin_count(). unsigned lwidth() const; - virtual bool emit_node(struct target_t*) const; - virtual void dump_node(ostream&, unsigned ind) const; + // Get the name of the underlying object. + const char*name() const; + + NetNet* sig() const; // This pointer is for keeping simple lists. NetAssign_* more; + void dump_lval(ostream&o) const; + private: + NetNet *sig_; NetExpr*bmux_; + + unsigned loff_; + unsigned lwid_; }; class NetAssignBase : public NetProc { @@ -1211,6 +1222,7 @@ class NetAssignBase : public NetProc { // accounts for any grouping of NetAssign_ objects that might happen. unsigned lwidth() const; + // This dumps all the lval structures. void dump_lval(ostream&) const; private: @@ -1236,12 +1248,23 @@ class NetAssignNB : public NetAssignBase { explicit NetAssignNB(NetAssign_*lv, NetExpr*rv); ~NetAssignNB(); + void rise_time(unsigned); + void fall_time(unsigned); + void decay_time(unsigned); + + unsigned rise_time() const; + unsigned fall_time() const; + unsigned decay_time() const; virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; private: + + unsigned rise_time_; + unsigned fall_time_; + unsigned decay_time_; }; /* @@ -2824,6 +2847,15 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.214 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.213 2001/07/27 04:51:44 steve * Handle part select expressions as variants of * NetESignal/IVL_EX_SIGNAL objects, instead of diff --git a/syn-rules.y b/syn-rules.y index 5272152b0..4b69c5e83 100644 --- a/syn-rules.y +++ b/syn-rules.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: syn-rules.y,v 1.13 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: syn-rules.y,v 1.14 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -151,11 +151,11 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk, assert(d); NetFF*ff = new NetFF(top->scope(), asn->l_val(0)->name(), - asn->l_val(0)->pin_count()); + asn->l_val(0)->lwidth()); for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { connect(ff->pin_Data(idx), d->bit(idx)); - connect(ff->pin_Q(idx), asn->l_val(0)->pin(idx)); + connect(ff->pin_Q(idx), asn->l_val(0)->sig()->pin(idx)); } connect(ff->pin_Clock(), pclk->pin(0)); @@ -215,11 +215,11 @@ static void make_initializer(Design*des, NetProcTop*top, NetAssignBase*asn) NetESignal*rsig = dynamic_cast (asn->rval()); assert(rsig); - for (unsigned idx = 0 ; idx < asn->l_val(0)->pin_count() ; idx += 1) { + for (unsigned idx = 0 ; idx < asn->l_val(0)->lwidth() ; idx += 1) { verinum::V bit = driven_value(rsig->bit(idx)); - Nexus*nex = asn->l_val(0)->pin(idx).nexus(); + Nexus*nex = asn->l_val(0)->sig()->pin(idx).nexus(); for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) { diff --git a/t-dll-api.cc b/t-dll-api.cc index ab5aec69c..bda5fa75d 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll-api.cc,v 1.62 2001/08/10 00:40:45 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.63 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -730,10 +730,16 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net) { assert(net); if (net->type_ == IVL_LVAL_MEM) - return net->n.mem_; + return net->n.mem; return 0x0; } +extern "C" unsigned ivl_lval_part_off(ivl_lval_t net) +{ + assert(net); + return net->loff_; +} + extern "C" unsigned ivl_lval_pins(ivl_lval_t net) { assert(net); @@ -745,10 +751,13 @@ extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx) assert(net); assert(idx < net->width_); assert(net->type_ != IVL_LVAL_MEM); - if (net->width_ == 1) - return net->n.pin_; - else - return net->n.pins_[idx]; + return ivl_signal_pin(net->n.sig, idx+net->loff_); +} + +extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net) +{ + assert(net); + return net->n.sig; } extern "C" const char* ivl_nexus_name(ivl_nexus_t net) @@ -1309,6 +1318,15 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.63 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.62 2001/08/10 00:40:45 steve * tgt-vvp generates code that skips nets as inputs. * diff --git a/t-dll-proc.cc b/t-dll-proc.cc index dd100e6d2..20e42ec23 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll-proc.cc,v 1.33 2001/07/27 02:41:56 steve Exp $" +#ident "$Id: t-dll-proc.cc,v 1.34 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -135,22 +135,10 @@ void dll_target::proc_assign(const NetAssign*net) struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx; const NetAssign_*asn = net->l_val(idx); - cur->width_ = asn->pin_count(); - cur->type_ = IVL_LVAL_REG; - - if (cur->width_ > 1) { - cur->n.pins_ = new ivl_nexus_t[cur->width_]; - for (unsigned pp = 0 ; pp < cur->width_ ; pp += 1) { - const Nexus*nex = asn->pin(pp).nexus(); - assert(nex->t_cookie()); - cur->n.pins_[pp] = (ivl_nexus_t)nex->t_cookie(); - } - - } else { - const Nexus*nex = asn->pin(0).nexus(); - assert(nex->t_cookie()); - cur->n.pin_ = (ivl_nexus_t)nex->t_cookie(); - } + cur->width_ = asn->lwidth(); + cur->loff_ = asn->get_loff(); + cur->type_ = IVL_LVAL_REG; + cur->n.sig = find_signal(des_.root_, asn->sig()); cur->idx = 0; if (asn->bmux()) { @@ -173,8 +161,7 @@ void dll_target::proc_assign_nb(const NetAssignNB*net) { unsigned cnt = net->l_val_count(); - unsigned long delay_val = net->l_val(0)->rise_time(); - + unsigned long delay_val = net->rise_time(); assert(stmt_cur_); assert(stmt_cur_->type_ == IVL_ST_NONE); @@ -188,24 +175,10 @@ void dll_target::proc_assign_nb(const NetAssignNB*net) struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx; const NetAssign_*asn = net->l_val(idx); - assert(asn->rise_time() == delay_val); - cur->type_ = IVL_LVAL_REG; - cur->width_ = asn->pin_count(); - - if (cur->width_ > 1) { - cur->n.pins_ = new ivl_nexus_t[cur->width_]; - for (unsigned pp = 0 ; pp < cur->width_ ; pp += 1) { - const Nexus*nex = asn->pin(pp).nexus(); - assert(nex->t_cookie()); - cur->n.pins_[pp] = (ivl_nexus_t)nex->t_cookie(); - } - - } else { - const Nexus*nex = asn->pin(0).nexus(); - assert(nex->t_cookie()); - cur->n.pin_ = (ivl_nexus_t)nex->t_cookie(); - } + cur->width_ = asn->lwidth(); + cur->loff_ = asn->get_loff(); + cur->n.sig = find_signal(des_.root_, asn->sig()); cur->idx = 0; if (asn->bmux()) { @@ -245,9 +218,9 @@ void dll_target::proc_assign_mem(const NetAssignMem*net) struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_; cur->type_ = IVL_LVAL_MEM; - cur->n.mem_ = lookup_memory_(net->memory()); - assert(cur->n.mem_); - cur->width_ = ivl_memory_width(cur->n.mem_); + cur->n.mem = lookup_memory_(net->memory()); + assert(cur->n.mem); + cur->width_ = ivl_memory_width(cur->n.mem); assert(expr_ == 0); @@ -274,8 +247,8 @@ void dll_target::proc_assign_mem_nb(const NetAssignMemNB*net) struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_; cur->type_ = IVL_LVAL_MEM; - cur->n.mem_ = lookup_memory_(net->memory()); - cur->width_ = ivl_memory_width(cur->n.mem_); + cur->n.mem = lookup_memory_(net->memory()); + cur->width_ = ivl_memory_width(cur->n.mem); assert(expr_ == 0); @@ -693,6 +666,15 @@ void dll_target::proc_while(const NetWhile*net) /* * $Log: t-dll-proc.cc,v $ + * Revision 1.34 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.33 2001/07/27 02:41:56 steve * Fix binding of dangling function ports. do not elide them. * diff --git a/t-dll.h b/t-dll.h index ea8d3a4c6..99c065f74 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll.h,v 1.59 2001/08/10 00:40:45 steve Exp $" +#ident "$Id: t-dll.h,v 1.60 2001/08/25 23:50:03 steve Exp $" #endif # include "target.h" @@ -289,9 +289,9 @@ struct ivl_lpm_s { }; /* - * This object contains references to ivl_nexus_t objects that in turn - * are reg nets. This is used by the assignment to represent the - * l-value expressions. + * This object represents l-values to assignments. The l-value can be + * a register bit or part select, or a memory word select with a part + * select. */ enum ivl_lval_type_t { @@ -302,12 +302,12 @@ enum ivl_lval_type_t { struct ivl_lval_s { unsigned width_ :24; + unsigned loff_ :24; unsigned type_ : 8; ivl_expr_t idx; union { - ivl_nexus_t*pins_; - ivl_nexus_t pin_; - ivl_memory_t mem_; + ivl_signal_t sig; + ivl_memory_t mem; } n; }; @@ -562,6 +562,15 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.60 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.59 2001/08/10 00:40:45 steve * tgt-vvp generates code that skips nets as inputs. * diff --git a/t-vvm.cc b/t-vvm.cc index 50c1aa07b..192e9f93e 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.211 2001/07/27 04:51:44 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.212 2001/08/25 23:50:03 steve Exp $" #endif # include "config.h" @@ -168,7 +168,6 @@ class target_vvm : public target_t { virtual void logic(const NetLogic*); virtual bool bufz(const NetBUFZ*); virtual void udp(const NetUDP*); - virtual void net_assign(const NetAssign_*) { } virtual void net_case_cmp(const NetCaseCmp*); virtual bool net_cassign(const NetCAssign*); virtual bool net_const(const NetConst*); @@ -2348,9 +2347,9 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, defn << " switch (" << bval << ".as_unsigned()) {" << endl; - for (unsigned idx = 0; idx < lv->pin_count(); idx += 1) { + for (unsigned idx = 0; idx < lv->lwidth(); idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " case " << idx << ":" << endl; @@ -2379,7 +2378,7 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, that does the assignment. This is an optimization that reduces the size of the generated C++. */ - unsigned*nexus_map = new unsigned[lv->pin_count()]; + unsigned*nexus_map = new unsigned[lv->lwidth()]; bool sequential_flag = true; bool uniform_flag = true; @@ -2388,8 +2387,8 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, : verinum::V0; unsigned zeros_start = 0; - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { + string nexus = lv->sig()->pin(idx).nexus()->name(); nexus_map[idx] = nexus_wire_map[nexus]; verinum::V tmp = (idx+off) < value.len() @@ -2409,18 +2408,18 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, } - if (sequential_flag && uniform_flag && (lv->pin_count() > 1)) { + if (sequential_flag && uniform_flag && (lv->lwidth() > 1)) { const char*rval = vvm_val_name(val, Link::STRONG, Link::STRONG); unsigned base = nexus_map[0]; defn << " for (unsigned idx = 0 ; idx < " - << lv->pin_count() << " ; idx += 1)" << endl; + << lv->lwidth() << " ; idx += 1)" << endl; defn << " nexus_wire_table[idx+" <pin_count())) { + } else if (sequential_flag && (zeros_start < lv->lwidth())) { /* If the nexa are sequential and the high bits are all zeros, then we can write simple reg_assign statements @@ -2449,13 +2448,13 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, unsigned base = nexus_map[zeros_start]; defn << " for (unsigned idx = 0 ; idx < " - << (lv->pin_count()-zeros_start) << " ; idx += 1)" << endl; + << (lv->lwidth()-zeros_start) << " ; idx += 1)" << endl; defn << " nexus_wire_table[idx+" <pin_count() ; idx += 1) { + } else for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { unsigned ncode = nexus_map[idx]; val = (idx+off) < value.len() @@ -2493,9 +2492,9 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, defn << " switch (" << bval << ".as_unsigned()) {" << endl; - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { + for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " case " << idx << ":" << endl; @@ -2509,7 +2508,7 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, defn << " }" << endl; } else { - unsigned min_count = lv->pin_count(); + unsigned min_count = lv->lwidth(); if ((wid-off) < min_count) min_count = wid - off; @@ -2517,9 +2516,9 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, the l-value. */ bool sequential_flag = true; - unsigned*nexus_map = new unsigned[lv->pin_count()]; - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + unsigned*nexus_map = new unsigned[lv->lwidth()]; + for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { + string nexus = lv->sig()->pin(idx).nexus()->name(); nexus_map[idx] = nexus_wire_map[nexus]; if ((idx >= 1) && (nexus_map[idx] != (nexus_map[idx-1]+1))) @@ -2544,7 +2543,7 @@ void target_vvm::proc_assign_rval(const NetAssign_*lv, } } - for (unsigned idx = min_count; idx < lv->pin_count(); idx += 1) { + for (unsigned idx = min_count; idx < lv->lwidth(); idx += 1) { unsigned ncode = nexus_map[idx]; defn << " nexus_wire_table["<value(); +#if 0 const unsigned rise_time = lv->rise_time(); +#else + const unsigned rise_time = 0; +#endif /* This condition catches the special case of assigning to a non-constant bit select. This cal be something like: @@ -2695,9 +2698,9 @@ void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, defn << " switch (" << bval << ".as_unsigned()) {" << endl; - for (unsigned idx = 0; idx < lv->pin_count(); idx += 1) { + for (unsigned idx = 0; idx < lv->lwidth(); idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " case " << idx << ":" << endl; @@ -2720,8 +2723,8 @@ void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, the entire width of the l-value, assign constant bit values to the appropriate nexus. */ - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; verinum::V val = (idx+off) < value.len() @@ -2744,7 +2747,11 @@ void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, unsigned wid, unsigned off) { assert(lv); +#if 0 const unsigned rise_time = lv->rise_time(); +#else + const unsigned rise_time = 0; +#endif /* Now, if there is a mux on the l-value, generate a code to assign a single bit to one of the bits of the @@ -2759,9 +2766,9 @@ void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, defn << " switch (" << bval << ".as_unsigned()) {" << endl; - for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { + for (unsigned idx = 0 ; idx < lv->lwidth() ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " case " << idx << ":" << endl; @@ -2776,12 +2783,12 @@ void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, defn << " }" << endl; } else { - unsigned min_count = lv->pin_count(); + unsigned min_count = lv->lwidth(); if ((wid-off) < min_count) min_count = wid - off; for (unsigned idx = 0 ; idx < min_count ; idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " vvm_delayed_assign(nexus_wire_table[" <pin_count(); idx += 1) { - string nexus = lv->pin(idx).nexus()->name(); + for (unsigned idx = min_count; idx < lv->lwidth(); idx += 1) { + string nexus = lv->sig()->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " vvm_delayed_assign(nexus_wire_table[" < ivl_lval_pins(lval)) - wid = ivl_lval_pins(lval); + if (bit_limit > ivl_lval_pins(lval)) + bit_limit = ivl_lval_pins(lval); - for (idx = 0 ; idx < wid ; idx += 1) - if (mem) - set_to_memory(mem, idx, bitchar_to_idx(bits[idx])); - else - set_to_nexus(ivl_lval_pin(lval, idx), - bitchar_to_idx(bits[idx])); + for (idx = 0 ; idx < bit_limit ; idx += 1) { + if (mem) + set_to_memory(mem, idx, + bitchar_to_idx(bits[cur_rbit])); + else + set_to_lvariable(lval, idx, + bitchar_to_idx(bits[cur_rbit])); - for (idx = wid ; idx < ivl_lval_pins(lval) ; idx += 1) - if (mem) - set_to_memory(mem, idx, 0); - else - set_to_nexus(ivl_lval_pin(lval, idx), 0); + cur_rbit += 1; + } + + for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) + if (mem) + set_to_memory(mem, idx, 0); + else + set_to_lvariable(lval, idx, 0); + + } return 0; } { struct vector_info res = draw_eval_expr(rval); unsigned wid = res.wid; - unsigned idx; + unsigned lidx; + unsigned cur_rbit = 0; - /* XXXX Only single l-value supported for now */ - assert(ivl_stmt_lvals(net) == 1); + for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { + unsigned idx; + unsigned bit_limit = wid - cur_rbit; + lval = ivl_stmt_lval(net, lidx); - lval = ivl_stmt_lval(net, 0); - /* XXXX No mux support yet. */ - assert(ivl_lval_mux(lval) == 0); - mem = ivl_lval_mem(lval); + /* XXXX No mux support yet. */ + assert(ivl_lval_mux(lval) == 0); - if (ivl_lval_pins(lval) < wid) - wid = ivl_lval_pins(lval); + mem = ivl_lval_mem(lval); + if (mem) + draw_memory_index_expr(mem, ivl_lval_idx(lval)); + + if (bit_limit > ivl_lval_pins(lval)) + bit_limit = ivl_lval_pins(lval); + + for (idx = 0 ; idx < bit_limit ; idx += 1) { + unsigned bidx = res.base < 4 + ? res.base + : (res.base+cur_rbit); + if (mem) + set_to_memory(mem, idx, bidx); + else + set_to_lvariable(lval, idx, bidx); + + cur_rbit += 1; + } + + for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) + if (mem) + set_to_memory(mem, idx, 0); + else + set_to_lvariable(lval, idx, 0); - if (mem) - draw_memory_index_expr(mem, ivl_lval_idx(lval)); - - for (idx = 0 ; idx < wid ; idx += 1) { - unsigned bidx = res.base < 4 ? res.base : (res.base+idx); - if (mem) - set_to_memory(mem, idx, bidx); - else - set_to_nexus(ivl_lval_pin(lval, idx), bidx); } - for (idx = wid ; idx < ivl_lval_pins(lval) ; idx += 1) - if (mem) - set_to_memory(mem, idx, 0); - else - set_to_nexus(ivl_lval_pin(lval, idx), 0); - clr_vector(res); } + return 0; } @@ -219,72 +222,89 @@ static int show_stmt_assign_nb(ivl_statement_t net) about generating code to evaluate the r-value expressions. */ if (ivl_expr_type(rval) == IVL_EX_NUMBER) { - unsigned idx; + unsigned lidx; const char*bits = ivl_expr_bits(rval); unsigned wid = ivl_expr_width(rval); + unsigned cur_rbit = 0; - /* XXXX Only single l-value supported for now */ - assert(ivl_stmt_lvals(net) == 1); + for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { + unsigned idx; + unsigned bit_limit = wid - cur_rbit; + lval = ivl_stmt_lval(net, lidx); - lval = ivl_stmt_lval(net, 0); - /* XXXX No mux support yet. */ - assert(ivl_lval_mux(lval) == 0); - mem = ivl_lval_mem(lval); + /* XXXX No mux support yet. */ + assert(ivl_lval_mux(lval) == 0); - if (mem) - draw_memory_index_expr(mem, ivl_lval_idx(lval)); - - if (wid > ivl_lval_pins(lval)) - wid = ivl_lval_pins(lval); - - for (idx = 0 ; idx < wid ; idx += 1) + mem = ivl_lval_mem(lval); if (mem) - assign_to_memory(mem, idx, - bitchar_to_idx(bits[idx]), delay); - else - assign_to_nexus(ivl_lval_pin(lval, idx), - bitchar_to_idx(bits[idx]), delay); - - for (idx = wid ; idx < ivl_lval_pins(lval) ; idx += 1) - if (mem) - assign_to_memory(mem, idx, 0, delay); - else - assign_to_nexus(ivl_lval_pin(lval, idx), 0, delay); - + draw_memory_index_expr(mem, ivl_lval_idx(lval)); + + if (bit_limit > ivl_lval_pins(lval)) + bit_limit = ivl_lval_pins(lval); + + for (idx = 0 ; idx < bit_limit ; idx += 1) { + if (mem) + assign_to_memory(mem, idx, + bitchar_to_idx(bits[cur_rbit]), + delay); + else + assign_to_lvariable(lval, idx, + bitchar_to_idx(bits[cur_rbit]), + delay); + + cur_rbit += 1; + } + + for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1) + if (mem) + assign_to_memory(mem, idx, 0, delay); + else + assign_to_lvariable(lval, idx, 0, delay); + + } return 0; } + { struct vector_info res = draw_eval_expr(rval); unsigned wid = res.wid; - unsigned idx; + unsigned lidx; + unsigned cur_rbit = 0; - /* XXXX Only single l-value supported for now */ - assert(ivl_stmt_lvals(net) == 1); + for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { + unsigned idx; + unsigned bit_limit = wid - cur_rbit; + lval = ivl_stmt_lval(net, lidx); - lval = ivl_stmt_lval(net, 0); - /* XXXX No mux support yet. */ - assert(ivl_lval_mux(lval) == 0); - mem = ivl_lval_mem(lval); + /* XXXX No mux support yet. */ + assert(ivl_lval_mux(lval) == 0); - if (ivl_lval_pins(lval) < wid) - wid = ivl_lval_pins(lval); + mem = ivl_lval_mem(lval); + if (mem) + draw_memory_index_expr(mem, ivl_lval_idx(lval)); + + if (bit_limit > ivl_lval_pins(lval)) + bit_limit = ivl_lval_pins(lval); + + for (idx = 0 ; idx < bit_limit ; idx += 1) { + unsigned bidx = res.base < 4 + ? res.base + : (res.base+cur_rbit); + if (mem) + assign_to_memory(mem, idx, bidx, delay); + else + assign_to_lvariable(lval, idx, bidx, delay); + + cur_rbit += 1; + } + + for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) + if (mem) + assign_to_memory(mem, idx, 0, delay); + else + assign_to_lvariable(lval, idx, 0, delay); - if (mem) - draw_memory_index_expr(mem, ivl_lval_idx(lval)); - - for (idx = 0 ; idx < wid ; idx += 1) { - unsigned bidx = res.base < 4 ? res.base : (res.base+idx); - if (mem) - assign_to_memory(mem, idx, bidx, delay); - else - assign_to_nexus(ivl_lval_pin(lval, idx), bidx, delay); } - - for (idx = wid ; idx < ivl_lval_pins(lval) ; idx += 1) - if (mem) - assign_to_memory(mem, idx, 0, delay); - else - assign_to_nexus(ivl_lval_pin(lval, idx), 0, delay); clr_vector(res); } @@ -931,6 +951,15 @@ int draw_func_definition(ivl_scope_t scope) /* * $Log: vvp_process.c,v $ + * Revision 1.42 2001/08/25 23:50:03 steve + * Change the NetAssign_ class to refer to the signal + * instead of link into the netlist. This is faster + * and uses less space. Make the NetAssignNB carry + * the delays instead of the NetAssign_ lval objects. + * + * Change the vvp code generator to support multiple + * l-values, i.e. concatenations of part selects. + * * Revision 1.41 2001/08/16 03:45:17 steve * statement ends after while loop labels. *