diff --git a/design_dump.cc b/design_dump.cc index 3c5cc8200..651636110 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.101 2000/10/28 00:51:41 steve Exp $" +#ident "$Id: design_dump.cc,v 1.102 2000/11/04 06:36:24 steve Exp $" #endif /* @@ -395,7 +395,7 @@ void NetUDP::dump_comb_(ostream&o, unsigned ind) const void NetUDP::dump_node(ostream&o, unsigned ind) const { - if (sequential_) + if (is_sequential()) dump_sequ_(o, ind); else dump_comb_(o, ind); @@ -975,6 +975,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.102 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.101 2000/10/28 00:51:41 steve * Add scope to threads in vvm, pass that scope * to vpi sysTaskFunc objects, and add vpi calls diff --git a/net_udp.cc b/net_udp.cc index 94de41c8f..de399bab9 100644 --- a/net_udp.cc +++ b/net_udp.cc @@ -17,26 +17,19 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: net_udp.cc,v 1.1 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: net_udp.cc,v 1.2 2000/11/04 06:36:24 steve Exp $" #endif # include "netlist.h" -NetUDP::NetUDP(const string&n, unsigned pins, bool sequ) -: NetNode(n, pins), sequential_(sequ), init_('x') -{ - pin(0).set_dir(Link::OUTPUT); - for (unsigned idx = 1 ; idx < pins ; idx += 1) - pin(idx).set_dir(Link::INPUT); - -} - bool NetUDP::set_table(const string&input, char output) { - assert((output == '0') || (output == '1') || (sequential_ && - (output == '-'))); + assert((output == '0') || (output == '1') + || (is_sequential() && (output == '-'))); - if (sequential_) { + cm_[input] = output; + + if (is_sequential()) { assert(input.length() == pin_count()); /* XXXX Need to check to make sure that the input vector contains a legal combination of characters. */ @@ -46,8 +39,7 @@ bool NetUDP::set_table(const string&input, char output) assert(input.length() == (pin_count()-1)); /* XXXX Need to check to make sure that the input vector contains a legal combination of characters. In - combinational UDPs, only 0, 1 and x are allowed. */ - cm_[input] = output; + combinational UDPs, only 0, 1, x, and ? are allowed. */ return true; } @@ -124,7 +116,7 @@ char NetUDP::table_lookup(const string&from, char to, unsigned pin) const void NetUDP::set_initial(char val) { - assert(sequential_); + assert(is_sequential()); assert((val == '0') || (val == '1') || (val == 'x')); init_ = val; } @@ -145,8 +137,8 @@ NetUDP::state_t_* NetUDP::find_state_(const string&str) return st; } -NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins) -: NetNode(n, pins) +NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins, bool sequ) + : NetNode(n, pins), sequential_(sequ) { pin(0).set_dir(Link::OUTPUT); pin(0).set_name("O", 0); @@ -156,16 +148,17 @@ NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins) } } -void NetUDP_COMB::set_table(const string&input, char output) +bool NetUDP_COMB::set_table(const string&input, char output) { assert((output == '0') || (output == '1')); assert(input.length() == (pin_count()-1)); /* XXXX Need to check to make sure that the input vector contains a legal combination of characters. In - combinational UDPs, only 0, 1 and x are allowed. */ + combinational UDPs, only 0, 1, x, and ? are allowed. */ cm_[input] = output; + return true; } void NetUDP_COMB::cleanup_table() @@ -198,6 +191,9 @@ bool NetUDP_COMB::next(string&inp, char&out) const /* * $Log: net_udp.cc,v $ + * Revision 1.2 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.1 2000/03/29 04:37:11 steve * New and improved combinational primitives. * diff --git a/netlist.h b/netlist.h index 7b92c57bb..6e67267c3 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.176 2000/10/31 17:49:02 steve Exp $" +#ident "$Id: netlist.h,v 1.177 2000/11/04 06:36:24 steve Exp $" #endif /* @@ -1044,11 +1044,52 @@ class NetLogic : public NetNode { * 1 are listed. * */ -class NetUDP : public NetNode { +class NetUDP_COMB : public NetNode { public: - explicit NetUDP(const string&n, unsigned pins, bool sequ =false); + explicit NetUDP_COMB(const string&n, unsigned pins, bool sequ = false); + virtual bool emit_node(struct target_t*) const; + virtual void dump_node(ostream&, unsigned ind) const; + + /* append a new truth table row. */ + bool set_table(const string&input, char output); + + /* After the primitive is built up, this method is called to + clean up redundancies, and possibly optimize the table. */ + void cleanup_table(); + + /* Use these methods to scan the truth table of the + device. "first" returns the first item in the table, and + "next" returns the next item in the table. The method will + return false when the scan is done. */ + bool first(string&inp, char&out) const; + bool next(string&inp, char&out) const; + + bool is_sequential() const { return sequential_; } + + protected: + + // A combinational primitive is more simply represented as a + // simple map of input signals to a single output. + typedef map CM_; + CM_ cm_; + + private: + + bool sequential_; + + mutable CM_::const_iterator idx_; +}; + + + +class NetUDP : public NetUDP_COMB { + + public: + explicit NetUDP(const string&n, unsigned pins, bool sequ = true) + : NetUDP_COMB(n, pins, sequ), init_('x') {}; + virtual bool emit_node( struct target_t*) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -1065,10 +1106,7 @@ class NetUDP : public NetNode { void set_initial(char); char get_initial() const { return init_; } - bool is_sequential() const { return sequential_; } - private: - bool sequential_; char init_; struct state_t_; @@ -1095,48 +1133,10 @@ class NetUDP : public NetNode { state_t_*find_state_(const string&); - // A combinational primitive is more simply represented as a - // simple map of input signals to a single output. - typedef map CM_; - CM_ cm_; - void dump_sequ_(ostream&o, unsigned ind) const; void dump_comb_(ostream&o, unsigned ind) const; }; -class NetUDP_COMB : public NetNode { - - public: - explicit NetUDP_COMB(const string&n, unsigned pins); - - virtual bool emit_node(struct target_t*) const; - virtual void dump_node(ostream&, unsigned ind) const; - - /* append a new truth table row. */ - void set_table(const string&input, char output); - - /* After the primitive is built up, this method is called to - clean up redundancies, and possibly optimize the table. */ - void cleanup_table(); - - /* Use these methods to scan the truth table of the - device. "first" returns the first item in the table, and - "next" returns the next item in the table. The method will - return false when the scan is done. */ - bool first(string&inp, char&out) const; - bool next(string&inp, char&out) const; - - private: - - // A combinational primitive is more simply represented as a - // simple map of input signals to a single output. - map cm_; - - mutable map::const_iterator idx_; -}; - - - /* ========= * A process is a behavioral-model description. A process is a * statement that may be compound. the various statement types may @@ -2811,6 +2811,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.177 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.176 2000/10/31 17:49:02 steve * Support time variables. * diff --git a/t-vvm.cc b/t-vvm.cc index e241a358f..fd9dcc757 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.182 2000/10/29 17:10:02 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.183 2000/11/04 06:36:24 steve Exp $" #endif # include @@ -166,7 +166,6 @@ class target_vvm : public target_t { virtual bool bufz(const NetBUFZ*); virtual void udp(const NetUDP*); virtual void udp_comb(const NetUDP_COMB*); - void udp_sequ_(ostream&os, const NetUDP*); virtual void net_assign(const NetAssign_*) { } virtual void net_case_cmp(const NetCaseCmp*); virtual bool net_cassign(const NetCAssign*); @@ -1922,7 +1921,9 @@ void target_vvm::udp_comb(const NetUDP_COMB*gate) } out << " ;" << endl; - out << "static vvm_udp_comb " << mname << "(" + out << (gate->is_sequential() ? "static vvm_udp_sequ1 " + : "static vvm_udp_comb " ) + << mname << "(" << (gate->pin_count()-1) << ", " << mname<<"_ctab);" << endl; /* Connect the output of the device... */ @@ -1945,81 +1946,11 @@ void target_vvm::udp_comb(const NetUDP_COMB*gate) } -static string state_to_string(unsigned state, unsigned npins) -{ - static const char cur_table[3] = { '0', '1', 'x' }; - string res = ""; - for (unsigned idx = 0 ; idx < npins ; idx += 1) { - char cur = cur_table[state%3]; - res = cur + res; - state /= 3; - } - - return res; -} void target_vvm::udp(const NetUDP*gate) { assert(gate->is_sequential()); - udp_sequ_(out, gate); -} - -void target_vvm::udp_sequ_(ostream&os, const NetUDP*gate) -{ - assert(gate->pin_count() <= 9); - assert(gate->is_sequential()); - unsigned states = 1; - for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) - states *= 3; - - os << "static vvm_u32 " << mangle(gate->name()) << "_table[" << - states << "] = {" << endl; - os << hex; - for (unsigned state = 0 ; state < states ; state += 1) { - string sstr = state_to_string(state, gate->pin_count()); - - unsigned long entry = 0; - for (unsigned idx = 1 ; idx < sstr.length() ; idx += 1) { - char o[2]; - switch (sstr[idx]) { - case '0': - o[0] = '1'; - o[1] = 'x'; - break; - case '1': - o[0] = '0'; - o[1] = 'x'; - break; - case 'x': - o[0] = '0'; - o[1] = '1'; - break; - } - - o[0] = gate->table_lookup(sstr, o[0], idx); - o[1] = gate->table_lookup(sstr, o[1], idx); - entry <<= 2; - entry |= (o[0] == '0')? 0 : (o[0] == '1')? 1 : 2; - entry <<= 2; - entry |= (o[1] == '0')? 0 : (o[1] == '1')? 1 : 2; - } - os << " 0x" << setw(8) << setfill('0') << entry << ","; - if (state % 3 == 2) - os << endl; - } - os << "};" << dec << setfill(' ') << endl; - - string outfun = defn_gate_outputfun_(os, gate, 0); - - os << "static vvm_udp_ssequ<" << gate->pin_count()-1 << "> " << - mangle(gate->name()) << "(&" << outfun << ", V" << - gate->get_initial() << ", " << mangle(gate->name()) << - "_table);" << endl; - - /* The UDP output function is much like other logic gates. Use - this general method to output the output function. */ - emit_gate_outputfun_(gate, 0); - + udp_comb(gate); } void target_vvm::net_case_cmp(const NetCaseCmp*gate) @@ -3398,6 +3329,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.183 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.182 2000/10/29 17:10:02 steve * task threads ned their scope initialized. (PR#32) * diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index 8d8964ffe..41dc1a7ca 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.65 2000/09/17 21:26:16 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.66 2000/11/04 06:36:24 steve Exp $" #endif # include "vvm.h" @@ -792,74 +792,22 @@ class vvm_udp_comb : public vvm_1bit_out, public vvm_nexus::recvr_t { void init_I(unsigned idx, vpip_bit_t val); void start(); - private: + protected: void take_value(unsigned key, vpip_bit_t val); - vpip_bit_t*ibits_; + char*ibits_; + char obit_; unsigned width_; const char*table_; }; -/* - * A Sequential UDP has a more complex truth table, and handles - * edges. Pin 0 is an output, and all the remaining pins are - * input. The WIDTH is the number of input pins. - * - * See vvm.txt for a description of the gate transition table. - */ -template class vvm_udp_ssequ { - - public: - explicit vvm_udp_ssequ(vvm_out_event::action_t o, vpip_bit_t i, - const vvm_u32*tab) - : output_(o), table_(tab) - { state_[0] = i; - for (unsigned idx = 1; idx < WIDTH+1 ; idx += 1) - state_[idx] = Vx; - } - - void init(unsigned pin, vpip_bit_t val) - { state_[pin] = val; } - - void set(unsigned pin, vpip_bit_t val) - { assert(pin > 0); - assert(pin < WIDTH+1); - if (val == Vz) val = Vx; - if (state_[pin] == val) return; - // Convert the current state into a table index. - unsigned entry = 0; - for (unsigned idx = 0 ; idx < WIDTH+1 ; idx += 1) { - entry *= 3; - entry += state_[idx]; - } - // Get the table entry, and the 4bits that encode - // activity on this pin. - vvm_u32 code = table_[entry]; - code >>= 4 * (WIDTH-pin); - switch (state_[pin]*4 + val) { - case (V0*4 + V1): - case (V1*4 + V0): - case (Vx*4 + V0): - code = (code>>2) & 3; - break; - case (V0*4 + Vx): - case (V1*4 + Vx): - case (Vx*4 + V1): - code &= 3; - break; - } - // Convert the code to a vpip_bit_t and run with it. - vpip_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx; - state_[0] = outval; - state_[pin] = val; - vvm_event*ev = new vvm_out_event(outval, output_); - ev->schedule(1); // XXXX Delay not supported. - } - - private: - vvm_out_event::action_t output_; - const vvm_u32*const table_; - vpip_bit_t state_[WIDTH+1]; +class vvm_udp_sequ1 : public vvm_udp_comb +{ + public: + explicit vvm_udp_sequ1(unsigned w, const char*t) + : vvm_udp_comb(w+1, t) {}; + private: + void take_value(unsigned key, vpip_bit_t val); }; /* @@ -976,6 +924,9 @@ class vvm_posedge : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.66 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.65 2000/09/17 21:26:16 steve * Add support for modulus (Eric Aardoom) * diff --git a/vvm/vvm_udp.cc b/vvm/vvm_udp.cc index 6a7709fa9..245ba738d 100644 --- a/vvm/vvm_udp.cc +++ b/vvm/vvm_udp.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_udp.cc,v 1.1 2000/03/29 04:37:11 steve Exp $" +#ident "$Id: vvm_udp.cc,v 1.2 2000/11/04 06:36:24 steve Exp $" #endif # include "vvm_gates.h" @@ -25,7 +25,8 @@ vvm_udp_comb::vvm_udp_comb(unsigned w, const char*t) : vvm_1bit_out(0), width_(w), table_(t) { - ibits_ = new vpip_bit_t[width_]; + ibits_ = new char[width_]; + obit_ = 'x'; } vvm_udp_comb::~vvm_udp_comb() @@ -36,54 +37,123 @@ vvm_udp_comb::~vvm_udp_comb() void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val) { assert(idx < width_); - ibits_[idx] = val; + if (B_IS1(val)) + ibits_[idx] = '1'; + else if (B_IS0(val)) + ibits_[idx] = '0'; + else + ibits_[idx] = 'x'; +} + +void vvm_udp_sequ1::take_value(unsigned key, vpip_bit_t val) +{ + assert(key < width_ - 1); + ibits_[0] = obit_; + vvm_udp_comb::take_value(key+1, val); } void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val) { - if (ibits_[key] == val) + char old_bit = ibits_[key]; + init_I(key, val); + + if (ibits_[key] == old_bit) return; - ibits_[key] = val; - char bit; - if (B_IS1(val)) - bit = '1'; - else if (B_IS0(val)) - bit = '0'; - else - bit = 'x'; - - for (const char*row = table_ ; row[0] ; row += width_+1) { unsigned idx; for (idx = 0 ; idx < width_ ; idx += 1) - if (row[idx] != bit) - break; + { + if (row[idx] != ibits_[idx] + && row[idx] != '?') + { + if (idx == key) + { + char new_bit = ibits_[idx]; + switch (row[idx]) + { + case '*': + continue; + case '_': + if (new_bit == '0') + continue; + break; + case '+': + if (new_bit == '1') + continue; + break; + case '%': + if (new_bit == 'x') + continue; + break; + case 'r': + if (old_bit=='0' && new_bit=='1') + continue; + break; + case 'R': + if (old_bit=='x' && new_bit=='1') + continue; + break; + case 'f': + if (old_bit=='1' && new_bit=='0') + continue; + break; + case 'F': + if (old_bit=='x' && new_bit=='0') + continue; + break; + case 'P': + if (old_bit=='1' && new_bit=='x') + continue; + break; + case 'N': + if (old_bit=='0' && new_bit=='x') + continue; + break; + } + // bad edge + } + break; // bad edge/level + } + } - if (idx == width_) switch (row[width_]) { + if (idx == width_) + { + if (row[width_] == '-' + || row[width_] == obit_) + return; - case '0': - output(St0); - return; - case '1': - output(St1); - return; - case 'z': - output(HiZ); - return; - default: - output(StX); - return; - } + obit_ = row[width_]; + + switch (obit_) + { + case '0': + output(St0); + return; + case '1': + output(St1); + return; + case 'z': + output(HiZ); + return; + default: + output(StX); + return; + } + } } output(StX); + obit_ = 'x'; } /* * $Log: vvm_udp.cc,v $ + * Revision 1.2 2000/11/04 06:36:24 steve + * Apply sequential UDP rework from Stephan Boettcher (PR#39) + * * Revision 1.1 2000/03/29 04:37:11 steve * New and improved combinational primitives. *