diff --git a/t-vvm.cc b/t-vvm.cc index 613b3911b..bb174b5a2 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.147 2000/05/07 21:17:21 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.148 2000/05/09 21:16:35 steve Exp $" #endif # include @@ -1567,6 +1567,7 @@ void target_vvm::lpm_ram_dq(ostream&os, const NetRamDq*ram) void target_vvm::logic(ostream&os, const NetLogic*gate) { + const string mname = mangle(gate->name()); /* Draw the definition of the gate object. The exact type to use depends on the gate type. Whatever the type, the basic @@ -1614,13 +1615,35 @@ void target_vvm::logic(ostream&os, const NetLogic*gate) gate->name() << "\"" << endl; } - os << mangle(gate->name()) << " (" << gate->rise_time() << ");" << endl; + os << mname << " (" << gate->rise_time() << ");" << endl; /* Write the code to invoke startup for this object. */ - start_code << " " << mangle(gate->name()) << ".start();" << endl; + start_code << " " << mname << ".start();" << endl; + /* Setup drive strengths that are not STRONG. The gates + default to strong outputs, so don't generate the + unnecessary code to set the signal to strong. We know for + all these types of gates that pin(0) is the output, and the + vvm class takes drive0 and drive1 methods. */ + + const char*str0 = vvm_val_name(verinum::V0, + gate->pin(0).drive0(), + gate->pin(0).drive1()); + if (gate->pin(0).drive0() != Link::STRONG) { + init_code << " " << mname << ".drive0(" << str0 << ");" + << endl; + } + + const char*str1 = vvm_val_name(verinum::V1, + gate->pin(0).drive0(), + gate->pin(0).drive1()); + if (gate->pin(0).drive1() != Link::STRONG) { + init_code << " " << mname << ".drive1(" << str1 << ");" + << endl; + } + /* Connect the output and all the inputs of the gate to the nexus objects, one bit at a time. */ @@ -1653,6 +1676,27 @@ void target_vvm::bufz(ostream&os, const NetBUFZ*gate) nexus = nexus_from_link(&gate->pin(0)); ncode = nexus_wire_map[nexus]; + /* Setup drive strengths that are not STRONG. The BUFZ + defaults to strong outputs, so don't generate the + unnecessary code to set the signal to strong. We also know + that the vvm_bufz class takes drive0 and drive1 methods. */ + + if (gate->pin(0).drive0() != Link::STRONG) { + const char*str = vvm_val_name(verinum::V0, + gate->pin(0).drive0(), + gate->pin(0).drive1()); + init_code << " " << mname << ".drive0(" << str << ");" + << endl; + } + + if (gate->pin(0).drive1() != Link::STRONG) { + const char*str = vvm_val_name(verinum::V1, + gate->pin(0).drive0(), + gate->pin(0).drive1()); + init_code << " " << mname << ".drive1(" << str << ");" + << endl; + } + init_code << " nexus_wire_table["< (res&0x07)) { + + /* New value is stronger. Take it. */ + res = b; + + } else if ((b&0x77) == (res&0x77)) { + + /* Strengths are the same. Make value ambiguous. */ + res = (res&0x70) | (b&0x07) | 0x80; + + } else { + + /* Must be res is the stronger one. */ + } + + } else if (UNAMBIG(res) || UNAMBIG(b)) { + + /* If one of the signals is unambiguous, then it + will sweep up the weaker parts of the ambiguous + signal. The result may be ambiguous, or maybe not. */ + + vpip_bit_t tmp = 0; + + if ((res&0x70) > (b&0x70)) + tmp |= res&0xf0; + else + tmp |= b&0xf0; + + if ((res&0x07) > (b&0x07)) + tmp |= res&0x0f; + else + tmp |= b&0x0f; + + res = tmp; + + } else { + + /* If both signals are ambiguous, then the result + has an even wider ambiguity. */ + + vpip_bit_t tmp = 0; + + if (STREN1(b) > STREN1(res)) + tmp |= b&0xf0; + else + tmp |= res&0xf0; + + if (STREN0(b) < STREN0(res)) + tmp |= b&0x0f; + else + tmp |= res&0x0f; + + res = tmp; + } + + /* Cannonicalize the HiZ value. */ + if ((res&0x77) == 0) + res = HiZ; + + return res; +} + vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits) { unsigned idx; @@ -45,86 +125,18 @@ vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits) idx += 1; } - for ( ; idx < nbits ; idx += 1) { - /* High-impedence drives do not affect the result. */ - if (bits[idx] == HiZ) - continue; + for ( ; idx < nbits ; idx += 1) + res = vpip_pair_resolve(res, bits[idx]); - if (UNAMBIG(res) && UNAMBIG(bits[idx])) { - - /* If both signals are unambiguous, simply choose - the stronger. If they have the same strength - but different values, then this becomes - ambiguous. */ - - if (bits[idx] == res) { - - /* values are equal. do nothing. */ - - } else if ((bits[idx]&0x07) > (res&0x07)) { - - /* New value is stronger. Take it. */ - res = bits[idx]; - - } else if ((bits[idx]&0x77) == (res&0x77)) { - - /* Strengths are the same. Make value ambiguous. */ - res = (res&0x70) | (bits[idx]&0x07) | 0x80; - - } else { - - /* Must be res is the stronger one. */ - } - - } else if (UNAMBIG(res) || UNAMBIG(bits[idx])) { - - /* If one of the signals is unambiguous, then it - will sweep up the weaker parts of the ambiguous - signal. The result may be ambiguous, or maybe - not. */ - - vpip_bit_t tmp = 0; - - if ((res&0x70) > (bits[idx]&0x70)) - tmp |= res&0xf0; - else - tmp |= bits[idx]&0xf0; - - if ((res&0x07) > (bits[idx]&0x07)) - tmp |= res&0x0f; - else - tmp |= bits[idx]&0x0f; - - } else { - - /* If both signals are ambiguous, then the result - has an even wider ambiguity. */ - - vpip_bit_t tmp = 0; - - if (STREN1(bits[idx]) > STREN1(res)) - tmp |= bits[idx]&0xf0; - else - tmp |= res&0xf0; - - if (STREN0(bits[idx]) < STREN0(res)) - tmp |= bits[idx]&0x0f; - else - tmp |= res&0x0f; - - res = tmp; - } - - } - - if ((res&0x77) == 0) - res = HiZ; return res; } /* * $Log: vpi_bit.c,v $ + * Revision 1.4 2000/05/09 21:16:35 steve + * Give strengths to logic and bufz devices. + * * Revision 1.3 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/vvm/vpi_priv.h b/vvm/vpi_priv.h index ce0f12069..d9fbdeff2 100644 --- a/vvm/vpi_priv.h +++ b/vvm/vpi_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_priv.h,v 1.18 2000/05/07 18:20:08 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.19 2000/05/09 21:16:35 steve Exp $" #endif /* @@ -98,6 +98,7 @@ typedef unsigned char vpip_bit_t; /* Take as input an array of bits, and return the resolved value. The result accounts for the strengths involved. */ +extern vpip_bit_t vpip_pair_resolve(vpip_bit_t a, vpip_bit_t b); extern vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits); @@ -367,6 +368,9 @@ extern int vpip_finished(); /* * $Log: vpi_priv.h,v $ + * Revision 1.19 2000/05/09 21:16:35 steve + * Give strengths to logic and bufz devices. + * * Revision 1.18 2000/05/07 18:20:08 steve * Import MCD support from Stephen Tell, and add * system function parameter support to the IVL core. diff --git a/vvm/vvm_gates.cc b/vvm/vvm_gates.cc index f04e4caf8..4e1527885 100644 --- a/vvm/vvm_gates.cc +++ b/vvm/vvm_gates.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vvm_gates.cc,v 1.14 2000/05/08 05:27:32 steve Exp $" +#ident "$Id: vvm_gates.cc,v 1.15 2000/05/09 21:16:35 steve Exp $" #endif # include "vvm_gates.h" @@ -39,14 +39,47 @@ void vvm_out_event::event_function() vvm_1bit_out::vvm_1bit_out(unsigned d) : delay_(d) { + drive0_ = St0; + drive1_ = St1; + driveX_ = StX; + driveZ_ = HiZ; } vvm_1bit_out::~vvm_1bit_out() { } +void vvm_1bit_out::drive0(vpip_bit_t v) +{ + drive0_ = v; +} + +void vvm_1bit_out::drive1(vpip_bit_t v) +{ + drive1_ = v; +} + +void vvm_1bit_out::driveX(vpip_bit_t v) +{ + driveX_ = v; +} + +void vvm_1bit_out::driveZ(vpip_bit_t v) +{ + driveZ_ = v; +} + void vvm_1bit_out::output(vpip_bit_t val) { + if (B_IS0(val)) + val = drive0_; + else if (B_IS1(val)) + val = drive1_; + else if (B_ISZ(val)) + val = driveZ_; + else + val = driveX_; + vvm_event*ev = new vvm_out_event(val, this); ev -> schedule(delay_); } @@ -214,6 +247,7 @@ void vvm_bufif1::take_value(unsigned key, vpip_bit_t val) } vvm_bufz::vvm_bufz() +: vvm_1bit_out(0) { } @@ -227,7 +261,7 @@ void vvm_bufz::init_I(unsigned, vpip_bit_t) void vvm_bufz::take_value(unsigned, vpip_bit_t val) { - set_value(val); + output(val); } vvm_eeq::vvm_eeq(unsigned long d) @@ -319,6 +353,9 @@ void vvm_not::take_value(unsigned, vpip_bit_t val) /* * $Log: vvm_gates.cc,v $ + * Revision 1.15 2000/05/09 21:16:35 steve + * Give strengths to logic and bufz devices. + * * Revision 1.14 2000/05/08 05:27:32 steve * Restore vvm_bufz to working condition. * diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index b007d096d..832a93a56 100644 --- a/vvm/vvm_gates.h +++ b/vvm/vvm_gates.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vvm_gates.h,v 1.61 2000/05/08 05:27:32 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.62 2000/05/09 21:16:35 steve Exp $" #endif # include "vvm.h" @@ -69,8 +69,18 @@ class vvm_1bit_out : public vvm_nexus::drive_t { ~vvm_1bit_out(); void output(vpip_bit_t); + void drive0(vpip_bit_t); + void drive1(vpip_bit_t); + void driveX(vpip_bit_t); + void driveZ(vpip_bit_t); + private: unsigned delay_; + + vpip_bit_t drive0_; + vpip_bit_t drive1_; + vpip_bit_t driveX_; + vpip_bit_t driveZ_; }; /* @@ -823,7 +833,7 @@ template class vvm_udp_ssequ { * * This device is useful for isolating nets. */ -class vvm_bufz : public vvm_nexus::recvr_t, public vvm_nexus::drive_t { +class vvm_bufz : public vvm_nexus::recvr_t, public vvm_1bit_out { public: explicit vvm_bufz(); ~vvm_bufz(); @@ -930,6 +940,9 @@ class vvm_posedge : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.62 2000/05/09 21:16:35 steve + * Give strengths to logic and bufz devices. + * * Revision 1.61 2000/05/08 05:27:32 steve * Restore vvm_bufz to working condition. *