From 8978bbd5e65bcb92840438a62c845f3416e2b692 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 16 Sep 2000 21:28:14 +0000 Subject: [PATCH] full featured l-values for non-blocking assiginment. --- t-vvm.cc | 213 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 190 insertions(+), 23 deletions(-) diff --git a/t-vvm.cc b/t-vvm.cc index aece97e3e..bbef3c5ee 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.173 2000/09/10 02:18:16 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.174 2000/09/16 21:28:14 steve Exp $" #endif # include @@ -180,6 +180,10 @@ class target_vvm : public target_t { unsigned wid, unsigned off); virtual void proc_assign_mem(const NetAssignMem*); virtual void proc_assign_nb(const NetAssignNB*); + void proc_assign_nb_rval(const NetAssign_*, const NetEConst*, + unsigned off); + void proc_assign_nb_rval(const NetAssign_*, const string&, + unsigned wid, unsigned off); virtual void proc_assign_mem_nb(const NetAssignMemNB*); virtual bool proc_block(const NetBlock*); virtual void proc_case(const NetCase*net); @@ -2378,47 +2382,207 @@ void target_vvm::proc_assign_mem(const NetAssignMem*amem) } -void target_vvm::proc_assign_nb(const NetAssignNB*net) + +/* + * This method handles the special case of the assignment of a + * constant r-value to the l-value. In this case, I can set specific + * values to each of the bits instead of calculating bit values or + * even reading values from a vpip_bit_t elsewhere. + */ +void target_vvm::proc_assign_nb_rval(const NetAssign_*lv, + const NetEConst*rv, + unsigned off) { - string rval = emit_proc_rval(this, net->rval()); - const unsigned long delay = net->l_val(0)->rise_time(); + const verinum value = rv->value(); - // XXXX I cannot handle this yet. - assert(net->l_val(1) == 0); + /* This condition catches the special case of assigning to a + non-constant bit select. This cal be something like: - if (net->l_val(0)->bmux()) { - /* If the l-value has a bit select, set the output bit - to only the desired bit. Evaluate the index and use - that to drive a switch statement. + a[idx] = x; - XXXX I'm not fully satisfied with this, I might like - better generating a demux device and doing the assign - to the device input. Food for thought. */ + For this sort of assignment, I only need a single bit of + the r-value. That bit is written into a single bit of the + target using a generated switch statement, where each case + of the switch assignes to a specific nexus. This is not + unreasonable because there aren't typically all that many + bits in the l-value. */ - string bval = emit_proc_rval(this, net->l_val(0)->bmux()); - defn << " switch (" << bval << ".as_unsigned()) {" << endl; + if (lv->bmux()) { - for (unsigned idx = 0 ; idx < net->l_val(0)->pin_count() ; idx += 1) { - string nexus = net->l_val(0)->pin(idx).nexus()->name(); + // This is a bit select. Assign the low bit of the + // constant to the selected bit of the lval. + + const char*rval = vvm_val_name(value.get(off), + Link::STRONG, + Link::STRONG); + + string bval = emit_proc_rval(this, lv->bmux()); + + defn << " switch (" << bval + << ".as_unsigned()) {" << endl; + + for (unsigned idx = 0; idx < lv->pin_count(); idx += 1) { + + string nexus = lv->pin(idx).nexus()->name(); unsigned ncode = nexus_wire_map[nexus]; defn << " case " << idx << ":" << endl; + defn << " vvm_delayed_assign(nexus_wire_table[" - << ncode << "], " << rval << "[0], " << delay << ");" - << endl; + <pin_count() ; idx += 1) { + string nexus = lv->pin(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + + verinum::V val = (idx+off) < value.len() + ? value.get(idx+off) + : verinum::V0; + const char*rval = vvm_val_name(val, Link::STRONG, Link::STRONG); + + defn << " vvm_delayed_assign(nexus_wire_table[" + <bmux()) { + + // This is a bit select. Assign the low bit of the rval + // to the selected bit of the lval. + string bval = emit_proc_rval(this, lv->bmux()); + + defn << " switch (" << bval << ".as_unsigned()) {" << endl; + + for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) { + + string nexus = lv->pin(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + + defn << " case " << idx << ":" << endl; + + defn << " vvm_delayed_assign(nexus_wire_table[" + <l_val(0)->pin_count() ; idx += 1) { - string nexus = net->l_val(0)->pin(idx).nexus()->name(); + unsigned min_count = lv->pin_count(); + 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(); unsigned ncode = nexus_wire_map[nexus]; defn << " vvm_delayed_assign(nexus_wire_table[" - << ncode << "], " << rval << "[" << idx << "], " - << delay << ");" << endl; + <pin_count(); idx += 1) { + string nexus = lv->pin(idx).nexus()->name(); + unsigned ncode = nexus_wire_map[nexus]; + defn << " vvm_delayed_assign(nexus_wire_table[" + <(net->rval())) { + + const NetAssign_*cur = net->l_val(0); + unsigned off = 0; + unsigned idx = 0; + while (cur != 0) { + proc_assign_nb_rval(cur, rc, off); + off += cur->lwidth(); + idx += 1; + cur = net->l_val(idx); + } + + return; + } + + + + string rval; + + + /* Handle another special case, that of an r-value that is a + simple identifier. In this case we don't need to generate + the vvm_bitset_t but can pull the result directly out of + the identifier memory. It is OK to turn the r-value string + into a simple vpip_bit_t array (the .bits member of the + signal) because we know that we will only be using the [] + operator on it. */ + + if (const NetESignal*rs = dynamic_cast(net->rval())) { + + if (net->lwidth() > rs->pin_count()) { + rval = emit_proc_rval(this, net->rval()); + + } else { + + rval = mangle(rs->name()) + ".bits"; + } + + } else { + + rval = emit_proc_rval(this, net->rval()); + } + + + defn << " // " << net->get_line() << ": " << endl; + + { const NetAssign_*cur = net->l_val(0); + unsigned wid = net->rval()->expr_width(); + unsigned off = 0; + unsigned idx = 0; + while (cur != 0) { + proc_assign_nb_rval(cur, rval, wid, off); + off += cur->lwidth(); + idx += 1; + cur = net->l_val(idx); + } } } @@ -3182,6 +3346,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.174 2000/09/16 21:28:14 steve + * full featured l-values for non-blocking assiginment. + * * Revision 1.173 2000/09/10 02:18:16 steve * elaborate complex l-values *