diff --git a/Makefile.in b/Makefile.in index e09054187..46f811f50 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.26 1999/11/01 02:07:40 steve Exp $" +#ident "$Id: Makefile.in,v 1.27 1999/11/02 04:55:34 steve Exp $" # # SHELL = /bin/sh @@ -69,7 +69,7 @@ TT = t-null.o t-verilog.o t-vvm.o t-xnf.o FF = nobufz.o propinit.o sigfold.o synth.o xnfio.o xnfsyn.o O = main.o cprop.o design_dump.o elaborate.o elab_expr.o elab_net.o \ -emit.o eval.o eval_tree.o functor.o \ +emit.o eval.o eval_tree.o expr_synth.o functor.o \ lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ diff --git a/expr_synth.cc b/expr_synth.cc new file mode 100644 index 000000000..385583f12 --- /dev/null +++ b/expr_synth.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1999 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) +#ident "$Id: expr_synth.cc,v 1.1 1999/11/02 04:55:34 steve Exp $" +#endif + +# include "netlist.h" + + +NetNet* NetExpr::synthesize(Design*des) +{ + cerr << get_line() << ": internal error: cannot synthesize expression: " + << *this << endl; + des->errors += 1; + return 0; +} + +/* + * The bitwise logic operators are turned into discrete gates pretty + * easily. Synthesize the left and right sub-expressions to get + * signals, then just connect a single gate to each bit of the vector + * of the expression. + */ +NetNet* NetEBBits::synthesize(Design*des) +{ + string path = des->local_symbol("SYNTH"); + NetNet*lsig = left_->synthesize(des); + NetNet*rsig = right_->synthesize(des); + + assert(lsig->pin_count() == rsig->pin_count()); + NetNet*osig = new NetNet(path, NetNet::IMPLICIT, lsig->pin_count()); + + for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) { + string oname = des->local_symbol(path); + NetLogic*gate; + + switch (op()) { + case '&': + gate = new NetLogic(oname, 3, NetLogic::AND); + break; + case '|': + gate = new NetLogic(oname, 3, NetLogic::OR); + break; + case '^': + gate = new NetLogic(oname, 3, NetLogic::XOR); + break; + case 'O': + gate = new NetLogic(oname, 3, NetLogic::NOR); + break; + case 'X': + gate = new NetLogic(oname, 3, NetLogic::XNOR); + break; + default: + assert(0); + } + + connect(osig->pin(idx), gate->pin(0)); + connect(lsig->pin(idx), gate->pin(1)); + connect(rsig->pin(idx), gate->pin(2)); + + des->add_node(gate); + } + + des->add_signal(osig); + return osig; +} + +NetNet* NetESignal::synthesize(Design*des) +{ + NetNet*sig = new NetNet(name(), NetNet::WIRE, pin_count()); + for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) + connect(sig->pin(idx), pin(idx)); + des->add_signal(sig); + return sig; +} + +/* + * $Log: expr_synth.cc,v $ + * Revision 1.1 1999/11/02 04:55:34 steve + * Add the synthesize method to NetExpr to handle + * synthesis of expressions, and use that method + * to improve r-value handling of LPM_FF synthesis. + * + * Modify the XNF target to handle LPM_FF objects. + * + */ + diff --git a/netlist.cc b/netlist.cc index ff0329187..144024296 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) -#ident "$Id: netlist.cc,v 1.79 1999/11/01 02:07:40 steve Exp $" +#ident "$Id: netlist.cc,v 1.80 1999/11/02 04:55:34 steve Exp $" #endif # include @@ -433,11 +433,21 @@ NetObj::Link& NetFF::pin_Clock() return pin(0); } +const NetObj::Link& NetFF::pin_Clock() const +{ + return pin(0); +} + NetObj::Link& NetFF::pin_Enable() { return pin(1); } +const NetObj::Link& NetFF::pin_Enable() const +{ + return pin(1); +} + NetObj::Link& NetFF::pin_Aload() { return pin(2); @@ -475,6 +485,13 @@ NetObj::Link& NetFF::pin_Data(unsigned w) return pin(pn); } +const NetObj::Link& NetFF::pin_Data(unsigned w) const +{ + unsigned pn = 8 + 2*w; + assert(pn < pin_count()); + return pin(pn); +} + NetObj::Link& NetFF::pin_Q(unsigned w) { unsigned pn = 9 + w*2; @@ -687,47 +704,6 @@ NetAssignMemNB::~NetAssignMemNB() { } -#if 0 -/* - * This method looks at the objects connected to me, and searches for - * a signal that I am fully connected to. Return that signal, and the - * range of bits that I use. - */ -void NetAssign::find_lval_range(const NetNet*&net, unsigned&msb, - unsigned&lsb) const -{ - const NetObj*cur; - unsigned cpin; - - for (pin(0).next_link(cur,cpin) ; pin(0) != cur->pin(cpin) - ; cur->pin(cpin).next_link(cur, cpin)) { - const NetNet*s = dynamic_cast(cur); - if (s == 0) - continue; - - if (!connected(*this, *s)) - continue; - - unsigned idx; - for (idx = 1 ; idx < pin_count() ; idx += 1) { - if (idx+cpin > s->pin_count()) - break; - if (! connected(pin(idx), s->pin(idx+cpin))) - break; - } - - if (idx < pin_count()) - continue; - - net = s; - lsb = cpin; - msb = cpin+pin_count()-1; - return; - } - - assert(0); // No suitable signals?? -} -#endif NetBlock::~NetBlock() { @@ -1993,6 +1969,13 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.80 1999/11/02 04:55:34 steve + * Add the synthesize method to NetExpr to handle + * synthesis of expressions, and use that method + * to improve r-value handling of LPM_FF synthesis. + * + * Modify the XNF target to handle LPM_FF objects. + * * Revision 1.79 1999/11/01 02:07:40 steve * Add the synth functor to do generic synthesis * and add the LPM_FF device to handle rows of diff --git a/netlist.h b/netlist.h index 07b25b515..63f418576 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) -#ident "$Id: netlist.h,v 1.82 1999/11/01 02:07:40 steve Exp $" +#ident "$Id: netlist.h,v 1.83 1999/11/02 04:55:34 steve Exp $" #endif /* @@ -347,6 +347,9 @@ class NetFF : public NetNode { NetObj::Link& pin_Data(unsigned); NetObj::Link& pin_Q(unsigned); + const NetObj::Link& pin_Clock() const; + const NetObj::Link& pin_Enable() const; + const NetObj::Link& pin_Data(unsigned) const; const NetObj::Link& pin_Q(unsigned) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -428,6 +431,11 @@ class NetExpr : public LineInfo { // any. This is a deep copy operation. virtual NetExpr*dup_expr() const =0; + // Return a version of myself that is structural. This is used + // for converting expressions to gates. + virtual NetNet*synthesize(Design*); + + protected: void expr_width(unsigned w) { width_ = w; } @@ -1306,6 +1314,8 @@ class NetEBBits : public NetEBinary { virtual bool set_width(unsigned w); virtual NetEBBits* dup_expr() const; + + virtual NetNet* synthesize(Design*); }; /* @@ -1600,6 +1610,8 @@ class NetESignal : public NetExpr, public NetNode { virtual NetESignal* dup_expr() const; + NetNet* synthesize(Design*des); + virtual void expr_scan(struct expr_scan_t*) const; virtual void emit_node(ostream&, struct target_t*) const; virtual void dump(ostream&) const; @@ -1782,6 +1794,13 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.83 1999/11/02 04:55:34 steve + * Add the synthesize method to NetExpr to handle + * synthesis of expressions, and use that method + * to improve r-value handling of LPM_FF synthesis. + * + * Modify the XNF target to handle LPM_FF objects. + * * Revision 1.82 1999/11/01 02:07:40 steve * Add the synth functor to do generic synthesis * and add the LPM_FF device to handle rows of diff --git a/netlist.txt b/netlist.txt index 150c1cb3d..10bdc8c4a 100644 --- a/netlist.txt +++ b/netlist.txt @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id: netlist.txt,v 1.4 1999/09/29 00:03:27 steve Exp $" +#ident "$Id: netlist.txt,v 1.5 1999/11/02 04:55:34 steve Exp $" Note that the netlist.h header contains detailed descriptions of how @@ -57,6 +57,31 @@ destructors for nets and nodes automatically arrange for pins to be disconnected when the item is deleted, so that the netlist can be changed during processing. +STRUCTURAL LINKS + +The NetNode and NetNet classes contain arrays of Link objects, one +object per pin. Each pin is a single bit. The Link objects link +circularly to all the NetNode and NetNet objects' links that are +connected together in the design. This way, code that examines a node +of the design can discover what is connected to each pin. + +See the NetObj::Link class definition for a description of the link +methods. + +Currently, a link has 3 possible direction properties: + + PASSIVE -- These pins are sampled by the object that holds the + pin based on some external event. These are used, + for example, by NetESignal objects that read a + point for a procedural expression. + + INPUT -- These pins potentially react to the setting of its + input. + + OUTPUT -- These pins potentially drive the node. (They may be + three-state.) + + BEHAVIORAL ITEMS: NetProcTop, NetProc and derived classes Behavioral items are not in general linked to the netlist. Instead, @@ -189,6 +214,13 @@ some task calls. C++ programmers recognize this as inlining a task.) $Log: netlist.txt,v $ + Revision 1.5 1999/11/02 04:55:34 steve + Add the synthesize method to NetExpr to handle + synthesis of expressions, and use that method + to improve r-value handling of LPM_FF synthesis. + + Modify the XNF target to handle LPM_FF objects. + Revision 1.4 1999/09/29 00:03:27 steve Spelling fixes from Larry. diff --git a/synth.cc b/synth.cc index d2c9a9bb9..08e2276eb 100644 --- a/synth.cc +++ b/synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: synth.cc,v 1.1 1999/11/01 02:07:41 steve Exp $" +#ident "$Id: synth.cc,v 1.2 1999/11/02 04:55:34 steve Exp $" #endif /* @@ -132,14 +132,9 @@ void synth_f::proc_always_(class Design*des) */ void synth_f::proc_casn_(class Design*des) { - - // ... and the rval must be a simple signal. - NetESignal*sig = dynamic_cast(asn_->rval()); - if (sig == 0) { - cerr << "Noted complex rval in DFF, name " << asn_->name() << - ", not yet implemented" << endl; - return ; - } + // Turn the r-value into gates. + NetNet*sig = asn_->rval()->synthesize(des); + assert(sig); // The signal and the assignment must be the same width... assert(asn_->pin_count() == sig->pin_count()); @@ -185,9 +180,8 @@ void synth_f::proc_ccon_(class Design*des) if (asn_ == 0) return; - NetESignal*sig = dynamic_cast(asn_->rval()); - if (sig == 0) - return; + NetNet*sig = asn_->rval()->synthesize(des); + assert(sig); // The signal and the assignment must be the same width... assert(asn_->pin_count() == sig->pin_count()); @@ -235,6 +229,13 @@ void synth(Design*des) /* * $Log: synth.cc,v $ + * Revision 1.2 1999/11/02 04:55:34 steve + * Add the synthesize method to NetExpr to handle + * synthesis of expressions, and use that method + * to improve r-value handling of LPM_FF synthesis. + * + * Modify the XNF target to handle LPM_FF objects. + * * Revision 1.1 1999/11/01 02:07:41 steve * Add the synth functor to do generic synthesis * and add the LPM_FF device to handle rows of diff --git a/t-xnf.cc b/t-xnf.cc index d6b566c7c..a9b2df860 100644 --- a/t-xnf.cc +++ b/t-xnf.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-xnf.cc,v 1.9 1999/08/25 22:22:08 steve Exp $" +#ident "$Id: t-xnf.cc,v 1.10 1999/11/02 04:55:34 steve Exp $" #endif /* XNF BACKEND @@ -70,6 +70,9 @@ class target_xnf : public target_t { void start_design(ostream&os, const Design*); void end_design(ostream&os, const Design*); void signal(ostream&os, const NetNet*); + + void lpm_ff(ostream&os, const NetFF*); + void logic(ostream&os, const NetLogic*); void bufz(ostream&os, const NetBUFZ*); void udp(ostream&os, const NetUDP*); @@ -176,8 +179,9 @@ void target_xnf::draw_sym_with_lcaname(ostream&os, string lca, void target_xnf::start_design(ostream&os, const Design*des) { os << "LCANET,6" << endl; - os << "PROG,verilog,0.0,\"Icarus Verilog\"" << endl; - os << "PART," << des->get_flag("part") << endl; + os << "PROG,verilog,0.2PRE,\"Icarus Verilog\"" << endl; + if (des->get_flag("part") != "") + os << "PART," << des->get_flag("part") << endl; } void target_xnf::end_design(ostream&os, const Design*) @@ -254,6 +258,35 @@ void target_xnf::signal(ostream&os, const NetNet*net) << ", " << num << endl; } +void target_xnf::lpm_ff(ostream&os, const NetFF*net) +{ + string type = net->attribute("LPM_FFType"); + if (type == "") type = "DFF"; + + // XXXX For now, only support DFF + assert(type == "DFF"); + // XXXX For now, I do not now how to deal with XNF-LCA attributes. + assert(net->attribute("XNF-LCA") == ""); + + for (unsigned idx = 0 ; idx < net->width() ; idx += 1) { + + os << "SYM, " << mangle(net->name()) << "<" << idx + << ">, DFF, LIBVER=2.0.0" << endl; + draw_pin(os, "Q", net->pin_Q(idx)); + draw_pin(os, "D", net->pin_Data(idx)); + + if (net->attribute("Clock:LPM_Polarity") == "INVERT") + draw_pin(os, "~C", net->pin_Clock()); + else + draw_pin(os, "C", net->pin_Clock()); + + if (count_outputs(net->pin_Enable()) > 0) + draw_pin(os, "CE", net->pin_Enable()); + + os << "END" << endl; + } +} + /* * The logic gates I know so far can be translated directly into XNF * standard symbol types. This is a fairly obvious transformation. @@ -349,6 +382,13 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj }; /* * $Log: t-xnf.cc,v $ + * Revision 1.10 1999/11/02 04:55:34 steve + * Add the synthesize method to NetExpr to handle + * synthesis of expressions, and use that method + * to improve r-value handling of LPM_FF synthesis. + * + * Modify the XNF target to handle LPM_FF objects. + * * Revision 1.9 1999/08/25 22:22:08 steve * handle bufz in XNF backend. * diff --git a/verilog.sh b/verilog.sh index 15428aa01..61ce4bfd6 100644 --- a/verilog.sh +++ b/verilog.sh @@ -78,7 +78,7 @@ fi case "$target" in vvm) targetSuffix="" ;; xnf) targetSuffix=".xnf" - functors="-Fxnfsyn -Fsigfold -Fxnfio" ;; + functors="-Fsynth -Fsigfold -Fxnfio" ;; *) targetSuffix=".$target" ;; esac