diff --git a/Makefile.in b/Makefile.in index 4f7c81926..239867998 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.40 2000/03/21 05:08:32 steve Exp $" +#ident "$Id: Makefile.in,v 1.41 2000/03/29 04:37:10 steve Exp $" # # SHELL = /bin/sh @@ -72,7 +72,7 @@ FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o xnfsyn.o O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ elab_net.o elab_pexpr.o elab_scope.o emit.o eval.o eval_tree.o \ expr_synth.o functor.o lexor.o lexor_keyword.o mangle.o netlist.o \ -net_design.o nexus_from_link.o pad_to_width.o \ +net_design.o net_udp.o nexus_from_link.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \ diff --git a/PGate.h b/PGate.h index 1bb5dcdc0..46603c005 100644 --- a/PGate.h +++ b/PGate.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PGate.h,v 1.15 2000/03/08 04:36:53 steve Exp $" +#ident "$Id: PGate.h,v 1.16 2000/03/29 04:37:10 steve Exp $" #endif # include "svector.h" @@ -194,12 +194,16 @@ class PGModule : public PGate { PExpr*lsb_; void elaborate_mod_(Design*, Module*mod, const string&path) const; - void elaborate_udp_(Design*, PUdp *udp, const string&path) const; + void elaborate_sudp_(Design*, PUdp *udp, const string&path) const; + void elaborate_cudp_(Design*, PUdp *udp, const string&path) const; void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const; }; /* * $Log: PGate.h,v $ + * Revision 1.16 2000/03/29 04:37:10 steve + * New and improved combinational primitives. + * * Revision 1.15 2000/03/08 04:36:53 steve * Redesign the implementation of scopes and parameters. * I now generate the scopes and notice the parameters diff --git a/design_dump.cc b/design_dump.cc index 401ae25f0..2ae65b1fc 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.69 2000/03/12 17:09:40 steve Exp $" +#ident "$Id: design_dump.cc,v 1.70 2000/03/29 04:37:10 steve Exp $" #endif /* @@ -336,18 +336,7 @@ void NetUDP::dump_sequ_(ostream&o, unsigned ind) const void NetUDP::dump_comb_(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "Combinational UDP: "; - o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() << - ") " << name() << endl; - - for (CM_::const_iterator ent = cm_.begin() - ; ent != cm_.end() ; ent++) { - o << setw(ind+6) << "" << (*ent).first << " --> " << - (*ent).second << endl; - } - - dump_node_pins(o, ind+4); - dump_obj_attr(o, ind+4); + assert(0); } void NetUDP::dump_node(ostream&o, unsigned ind) const @@ -358,6 +347,22 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const dump_comb_(o, ind); } +void NetUDP_COMB::dump_node(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "Combinational primitive: "; + o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() << + ") " << name() << endl; + + for (map::const_iterator ent = cm_.begin() + ; ent != cm_.end() ; ent++) { + o << setw(ind+6) << "" << (*ent).first << " --> " << + (*ent).second << endl; + } + + dump_node_pins(o, ind+4); + dump_obj_attr(o, ind+4); +} + void NetNEvent::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "event: "; @@ -892,6 +897,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.70 2000/03/29 04:37:10 steve + * New and improved combinational primitives. + * * Revision 1.69 2000/03/12 17:09:40 steve * Support localparam. * diff --git a/elaborate.cc b/elaborate.cc index 8a8026910..9737af896 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.150 2000/03/20 15:28:58 steve Exp $" +#ident "$Id: elaborate.cc,v 1.151 2000/03/29 04:37:11 steve Exp $" #endif /* @@ -535,12 +535,53 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const } } +void PGModule::elaborate_cudp_(Design*des, PUdp*udp, const string&path) const +{ + const string my_name = path+"."+get_name(); + NetUDP_COMB*net = new NetUDP_COMB(my_name, udp->ports.count()); + net->set_attributes(udp->attributes); + + /* Run through the pins, making netlists for the pin + expressions and connecting them to the pin in question. All + of this is independent of the nature of the UDP. */ + for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { + if (pin(idx) == 0) + continue; + + NetNet*sig = pin(idx)->elaborate_net(des, path, 1, 0, 0, 0); + if (sig == 0) { + cerr << "internal error: Expression too complicated " + "for elaboration:" << *pin(idx) << endl; + continue; + } + + connect(sig->pin(0), net->pin(idx)); + + // Delete excess holding signal. + if (NetTmp*tmp = dynamic_cast(sig)) + delete tmp; + } + + /* Build up the truth table for the netlist from the input + strings. */ + for (unsigned idx = 0 ; idx < udp->tinput.count() ; idx += 1) { + string input = udp->tinput[idx]; + + net->set_table(input, udp->toutput[idx]); + } + + net->cleanup_table(); + + // All done. Add the object to the design. + des->add_node(net); +} + /* * From a UDP definition in the source, make a NetUDP * object. Elaborate the pin expressions as netlists, then connect * those networks to the pins. */ -void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const +void PGModule::elaborate_sudp_(Design*des, PUdp*udp, const string&path) const { const string my_name = path+"."+get_name(); NetUDP*net = new NetUDP(my_name, udp->ports.count(), udp->sequential); @@ -570,16 +611,13 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const /* Build up the truth table for the netlist from the input strings. */ for (unsigned idx = 0 ; idx < udp->tinput.count() ; idx += 1) { - string input = udp->sequential - ? (string("") + udp->tcurrent[idx] + udp->tinput[idx]) - : udp->tinput[idx]; - + string input = string("") + udp->tcurrent[idx] + udp->tinput[idx]; net->set_table(input, udp->toutput[idx]); } net->cleanup_table(); - if (udp->sequential) switch (udp->initial) { + switch (udp->initial) { case verinum::V0: net->set_initial('0'); break; @@ -608,7 +646,10 @@ void PGModule::elaborate(Design*des, const string&path) const // Try a primitive type map::const_iterator udp = udplist->find(type_); if (udp != udplist->end()) { - elaborate_udp_(des, (*udp).second, path); + if ((*udp).second->sequential) + elaborate_sudp_(des, (*udp).second, path); + else + elaborate_cudp_(des, (*udp).second, path); return; } @@ -1962,6 +2003,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.151 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.150 2000/03/20 15:28:58 steve * Fix lval part select of non-blocking assign. * diff --git a/emit.cc b/emit.cc index 7d67eb36b..409db2982 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.34 2000/03/08 04:36:53 steve Exp $" +#ident "$Id: emit.cc,v 1.35 2000/03/29 04:37:11 steve Exp $" #endif /* @@ -40,6 +40,11 @@ void NetLogic::emit_node(ostream&o, struct target_t*tgt) const tgt->logic(o, this); } +void NetUDP_COMB::emit_node(ostream&o, struct target_t*tgt) const +{ + tgt->udp_comb(o, this); +} + void NetUDP::emit_node(ostream&o, struct target_t*tgt) const { tgt->udp(o, this); @@ -397,6 +402,9 @@ bool emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.35 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.34 2000/03/08 04:36:53 steve * Redesign the implementation of scopes and parameters. * I now generate the scopes and notice the parameters diff --git a/net_udp.cc b/net_udp.cc new file mode 100644 index 000000000..94de41c8f --- /dev/null +++ b/net_udp.cc @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * 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 $" +#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 == '-'))); + + if (sequential_) { + assert(input.length() == pin_count()); + /* XXXX Need to check to make sure that the input vector + contains a legal combination of characters. */ + return sequ_glob_(input, output); + + } else { + 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; + + return true; + } +} + +void NetUDP::cleanup_table() +{ + for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; idx++) { + string str = (*idx).first; + state_t_*st = (*idx).second; + assert(str[0] == st->out); + + for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) { + if (st->pins[pin].zer && st->pins[pin].zer->out == 'x') + st->pins[pin].zer = 0; + if (st->pins[pin].one && st->pins[pin].one->out == 'x') + st->pins[pin].one = 0; + if (st->pins[pin].xxx && st->pins[pin].xxx->out == 'x') + st->pins[pin].xxx = 0; + } + } + + for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; ) { + FSM_::iterator cur = idx; + idx ++; + + state_t_*st = (*cur).second; + + if (st->out != 'x') + continue; + + for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) { + if (st->pins[pin].zer) + goto break_label; + if (st->pins[pin].one) + goto break_label; + if (st->pins[pin].xxx) + goto break_label; + } + + //delete st; + fsm_.erase(cur); + + break_label:; + } +} + +char NetUDP::table_lookup(const string&from, char to, unsigned pin) const +{ + assert(pin <= pin_count()); + assert(from.length() == pin_count()); + FSM_::const_iterator idx = fsm_.find(from); + if (idx == fsm_.end()) + return 'x'; + + state_t_*next; + switch (to) { + case '0': + next = (*idx).second->pins[pin].zer; + break; + case '1': + next = (*idx).second->pins[pin].one; + break; + case 'x': + next = (*idx).second->pins[pin].xxx; + break; + default: + assert(0); + next = 0; + } + + return next? next->out : 'x'; +} + +void NetUDP::set_initial(char val) +{ + assert(sequential_); + assert((val == '0') || (val == '1') || (val == 'x')); + init_ = val; +} + +NetUDP::state_t_* NetUDP::find_state_(const string&str) +{ + map::iterator cur = fsm_.find(str); + if (cur != fsm_.end()) + return (*cur).second; + + state_t_*st = fsm_[str]; + if (st == 0) { + st = new state_t_(pin_count()); + st->out = str[0]; + fsm_[str] = st; + } + + return st; +} + +NetUDP_COMB::NetUDP_COMB(const string&n, unsigned pins) +: NetNode(n, pins) +{ + pin(0).set_dir(Link::OUTPUT); + pin(0).set_name("O", 0); + for (unsigned idx = 1 ; idx < pins ; idx += 1) { + pin(idx).set_dir(Link::INPUT); + pin(idx).set_name("I", idx-1); + } +} + +void 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. */ + cm_[input] = output; + +} + +void NetUDP_COMB::cleanup_table() +{ +} + +bool NetUDP_COMB::first(string&inp, char&out) const +{ + idx_ = cm_.begin(); + if (idx_ == cm_.end()) + return false; + + inp = (*idx_).first; + out = (*idx_).second; + + return true; +} + +bool NetUDP_COMB::next(string&inp, char&out) const +{ + idx_ ++; + if (idx_ == cm_.end()) + return false; + + inp = (*idx_).first; + out = (*idx_).second; + + return true; +} + +/* + * $Log: net_udp.cc,v $ + * Revision 1.1 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * + */ + diff --git a/netlist.cc b/netlist.cc index be0d3a470..d0d98ef85 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.108 2000/03/12 17:09:41 steve Exp $" +#ident "$Id: netlist.cc,v 1.109 2000/03/29 04:37:11 steve Exp $" #endif # include @@ -2374,31 +2374,6 @@ NetNet* NetTaskDef::port(unsigned idx) return ports_[idx]; } -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); - -} - -NetUDP::state_t_* NetUDP::find_state_(const string&str) -{ - map::iterator cur = fsm_.find(str); - if (cur != fsm_.end()) - return (*cur).second; - - state_t_*st = fsm_[str]; - if (st == 0) { - st = new state_t_(pin_count()); - st->out = str[0]; - fsm_[str] = st; - } - - return st; -} - /* * This method takes the input string, which contains exactly one * edge, and connects it to the correct output state. The output state @@ -2546,106 +2521,11 @@ bool NetUDP::sequ_glob_(string input, char output) return set_sequ_(input, output); } -bool NetUDP::set_table(const string&input, char output) -{ - assert((output == '0') || (output == '1') || (sequential_ && - (output == '-'))); - - if (sequential_) { - assert(input.length() == pin_count()); - /* XXXX Need to check to make sure that the input vector - contains a legal combination of characters. */ - return sequ_glob_(input, output); - - } else { - 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; - - return true; - } -} - -void NetUDP::cleanup_table() -{ - for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; idx++) { - string str = (*idx).first; - state_t_*st = (*idx).second; - assert(str[0] == st->out); - - for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) { - if (st->pins[pin].zer && st->pins[pin].zer->out == 'x') - st->pins[pin].zer = 0; - if (st->pins[pin].one && st->pins[pin].one->out == 'x') - st->pins[pin].one = 0; - if (st->pins[pin].xxx && st->pins[pin].xxx->out == 'x') - st->pins[pin].xxx = 0; - } - } - - for (FSM_::iterator idx = fsm_.begin() ; idx != fsm_.end() ; ) { - FSM_::iterator cur = idx; - idx ++; - - state_t_*st = (*cur).second; - - if (st->out != 'x') - continue; - - for (unsigned pin = 0 ; pin < pin_count() ; pin += 1) { - if (st->pins[pin].zer) - goto break_label; - if (st->pins[pin].one) - goto break_label; - if (st->pins[pin].xxx) - goto break_label; - } - - //delete st; - fsm_.erase(cur); - - break_label:; - } -} - -char NetUDP::table_lookup(const string&from, char to, unsigned pin) const -{ - assert(pin <= pin_count()); - assert(from.length() == pin_count()); - FSM_::const_iterator idx = fsm_.find(from); - if (idx == fsm_.end()) - return 'x'; - - state_t_*next; - switch (to) { - case '0': - next = (*idx).second->pins[pin].zer; - break; - case '1': - next = (*idx).second->pins[pin].one; - break; - case 'x': - next = (*idx).second->pins[pin].xxx; - break; - default: - assert(0); - next = 0; - } - - return next? next->out : 'x'; -} - -void NetUDP::set_initial(char val) -{ - assert(sequential_); - assert((val == '0') || (val == '1') || (val == 'x')); - init_ = val; -} - /* * $Log: netlist.cc,v $ + * Revision 1.109 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.108 2000/03/12 17:09:41 steve * Support localparam. * @@ -2670,33 +2550,5 @@ void NetUDP::set_initial(char val) * * Revision 1.102 1999/12/30 04:19:12 steve * Propogate constant 0 in low bits of adders. - * - * Revision 1.101 1999/12/17 03:38:46 steve - * NetConst can now hold wide constants. - * - * Revision 1.100 1999/12/16 02:42:15 steve - * Simulate carry output on adders. - * - * Revision 1.99 1999/12/05 19:30:43 steve - * Generate XNF RAMS from synthesized memories. - * - * Revision 1.98 1999/12/05 02:24:09 steve - * Synthesize LPM_RAM_DQ for writes into memories. - * - * Revision 1.97 1999/12/02 16:58:58 steve - * Update case comparison (Eric Aardoom). - * - * Revision 1.96 1999/11/28 23:42:02 steve - * NetESignal object no longer need to be NetNode - * objects. Let them keep a pointer to NetNet objects. - * - * Revision 1.95 1999/11/28 01:16:18 steve - * gate outputs need to set signal values. - * - * Revision 1.94 1999/11/27 19:07:57 steve - * Support the creation of scopes. - * - * Revision 1.93 1999/11/24 04:01:59 steve - * Detect and list scope names. */ diff --git a/netlist.h b/netlist.h index 1d2aa532c..e0170fc60 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.114 2000/03/12 17:09:41 steve Exp $" +#ident "$Id: netlist.h,v 1.115 2000/03/29 04:37:11 steve Exp $" #endif /* @@ -919,6 +919,39 @@ class NetUDP : public NetNode { void dump_comb_(ostream&o, unsigned ind) const; }; +class NetUDP_COMB : public NetNode { + + public: + explicit NetUDP_COMB(const string&n, unsigned pins); + + virtual void emit_node(ostream&, 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 @@ -2195,6 +2228,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.115 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.114 2000/03/12 17:09:41 steve * Support localparam. * diff --git a/t-vvm.cc b/t-vvm.cc index 47248b5ea..d407b5042 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.126 2000/03/26 16:28:31 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.127 2000/03/29 04:37:11 steve Exp $" #endif # include @@ -73,6 +73,8 @@ class target_vvm : public target_t { virtual void logic(ostream&os, const NetLogic*); virtual void bufz(ostream&os, const NetBUFZ*); virtual void udp(ostream&os, const NetUDP*); + virtual void udp_comb(ostream&os, const NetUDP_COMB*); + void udp_sequ_(ostream&os, const NetUDP*); virtual void net_assign_nb(ostream&os, const NetAssignNB*); virtual void net_case_cmp(ostream&os, const NetCaseCmp*); virtual void net_const(ostream&os, const NetConst*); @@ -1527,6 +1529,47 @@ void target_vvm::bufz(ostream&os, const NetBUFZ*gate) } +void target_vvm::udp_comb(ostream&os, const NetUDP_COMB*gate) +{ + string mname = mangle(gate->name()); + string nexus; + unsigned ncode; + + + os << "static const char*" << mname << "_ctab =" << endl; + + string inp; + char out; + for (bool rc = gate->first(inp, out) + ; rc ; rc = gate->next(inp,out)) { + + os << " \"" << inp << out << "\"" << endl; + } + os << " ;" << endl; + + os << "static vvm_udp_comb " << mname << "(" + << (gate->pin_count()-1) << ", " << mname<<"_ctab);" << endl; + + /* Connect the output of the device... */ + nexus = nexus_from_link(&gate->pin(0)); + ncode = nexus_wire_map[nexus]; + init_code << " nexus_wire_table["<pin_count() ; idx += 1) { + if (! gate->pin(idx).is_linked()) + continue; + + nexus = nexus_from_link(&gate->pin(idx)); + ncode = nexus_wire_map[nexus]; + + init_code << " nexus_wire_table["<is_sequential()); + udp_sequ_(os, gate); +} + +void target_vvm::udp_sequ_(ostream&os, const NetUDP*gate) { assert(gate->pin_count() <= 9); assert(gate->is_sequential()); @@ -2440,6 +2489,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.127 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.126 2000/03/26 16:28:31 steve * vvm_bitset_t is no longer a template. * diff --git a/target.cc b/target.cc index e4bfad2ff..74dfabb2d 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: target.cc,v 1.30 2000/02/23 02:56:56 steve Exp $" +#ident "$Id: target.cc,v 1.31 2000/03/29 04:37:11 steve Exp $" #endif # include "target.h" @@ -73,6 +73,12 @@ void target_t::udp(ostream&os, const NetUDP*) "Unhandled UDP." << endl; } +void target_t::udp_comb(ostream&os, const NetUDP_COMB*) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled combinational primitive." << endl; +} + void target_t::lpm_add_sub(ostream&, const NetAddSub*) { cerr << "target (" << typeid(*this).name() << "): " @@ -314,6 +320,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.31 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.30 2000/02/23 02:56:56 steve * Macintosh compilers do not support ident. * diff --git a/target.h b/target.h index fba46500d..be77eb3bc 100644 --- a/target.h +++ b/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: target.h,v 1.29 2000/02/23 02:56:56 steve Exp $" +#ident "$Id: target.h,v 1.30 2000/03/29 04:37:11 steve Exp $" #endif # include "netlist.h" @@ -82,6 +82,7 @@ struct target_t { virtual void logic(ostream&os, const NetLogic*); virtual void bufz(ostream&os, const NetBUFZ*); virtual void udp(ostream&os, const NetUDP*); + virtual void udp_comb(ostream&os, const NetUDP_COMB*); virtual void net_assign(ostream&os, const NetAssign*); virtual void net_assign_nb(ostream&os, const NetAssignNB*); virtual void net_case_cmp(ostream&os, const NetCaseCmp*); @@ -147,6 +148,9 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.30 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.29 2000/02/23 02:56:56 steve * Macintosh compilers do not support ident. * diff --git a/vvm/Makefile.in b/vvm/Makefile.in index a72d3efe4..938a6d147 100644 --- a/vvm/Makefile.in +++ b/vvm/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.26 2000/03/22 05:16:38 steve Exp $" +#ident "$Id: Makefile.in,v 1.27 2000/03/29 04:37:11 steve Exp $" # # SHELL = /bin/sh @@ -61,7 +61,7 @@ all: libvvm.a O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \ vvm_event.o vvm_ff.o \ vvm_func.o vvm_gates.o vvm_mult.o vvm_mux.o \ -vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vpip.o +vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o vpip.o P = vpi_bit.o vpi_callback.o \ vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \ diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index ec387a10b..ad46df9d9 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.52 2000/03/26 16:28:31 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.53 2000/03/29 04:37:11 steve Exp $" #endif # include "vvm.h" @@ -640,6 +640,49 @@ class vvm_eeq : public vvm_1bit_out, public vvm_nexus::recvr_t { vpip_bit_t input_[2]; }; +/* + * This class allows programmers to define combinational primitives at + * truth tables. The device has a single bit output, and any fixed + * width. + * + * The truth table is specified as a string of characters organized as + * a table. Every width+1 characters represents one row, including the + * set of inputs and the output that they generated. There can be any + * number of rows in the table, which is terminated by a nul byte. The + * table is passed to the constructor as a constant string. + * + * This is a simple example of a truth table for an inverter. The + * width is 1, so there are two characters in each row. The last + * character in each row is the output if all the other characters in + * the row match the input. As you can see, this table inverts its + * input and outputs 'x' if the input is unknown. + * + * const char*invert_table = + * "01" + * "10" + * "xx"; + * + * The valid input characters are '0', '1' and 'x'. The valid output + * characters are '0', '1', 'x' and 'z'. (The last is not supported by + * Verilog primitives, so ivl will never generate it.) + */ +class vvm_udp_comb : public vvm_1bit_out, public vvm_nexus::recvr_t { + + public: + explicit vvm_udp_comb(unsigned w, const char*t); + ~vvm_udp_comb(); + + void init_I(unsigned idx, vpip_bit_t val); + void start(); + + private: + void take_value(unsigned key, vpip_bit_t val); + vpip_bit_t*ibits_; + + 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 @@ -796,6 +839,9 @@ template class vvm_pevent : public vvm_nexus::recvr_t { /* * $Log: vvm_gates.h,v $ + * Revision 1.53 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * * Revision 1.52 2000/03/26 16:28:31 steve * vvm_bitset_t is no longer a template. * diff --git a/vvm/vvm_udp.cc b/vvm/vvm_udp.cc new file mode 100644 index 000000000..6a7709fa9 --- /dev/null +++ b/vvm/vvm_udp.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2000 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * 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 $" +#endif + +# include "vvm_gates.h" + +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_]; +} + +vvm_udp_comb::~vvm_udp_comb() +{ + delete[]ibits_; +} + +void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val) +{ + assert(idx < width_); + ibits_[idx] = val; +} + +void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val) +{ + if (ibits_[key] == val) + 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 (idx == width_) switch (row[width_]) { + + case '0': + output(St0); + return; + case '1': + output(St1); + return; + case 'z': + output(HiZ); + return; + default: + output(StX); + return; + } + } + + output(StX); +} + + +/* + * $Log: vvm_udp.cc,v $ + * Revision 1.1 2000/03/29 04:37:11 steve + * New and improved combinational primitives. + * + */ +