diff --git a/LineInfo.h b/LineInfo.h index 2f83cd867..973715d0e 100644 --- a/LineInfo.h +++ b/LineInfo.h @@ -19,10 +19,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: LineInfo.h,v 1.2 1999/02/01 00:26:48 steve Exp $" +#ident "$Id: LineInfo.h,v 1.3 1999/02/15 02:06:15 steve Exp $" #endif # include +# include class LineInfo { public: @@ -49,6 +50,9 @@ class LineInfo { /* * $Log: LineInfo.h,v $ + * Revision 1.3 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.2 1999/02/01 00:26:48 steve * Carry some line info to the netlist, * Dump line numbers for processes. diff --git a/Makefile b/Makefile index 30de84c4b..c23e6445b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ FF = nobufz.o propinit.o sigfold.o stupid.o xnfio.o O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o lexor.o mangle.o \ netlist.o parse.o parse_misc.o pform.o pform_dump.o verinum.o target.o \ -targets.o Module.o PExpr.o Statement.o $(FF) $(TT) +targets.o Module.o PExpr.o PGate.o Statement.o $(FF) $(TT) ivl: $O $(CXX) $(CXXFLAGS) -o ivl $O diff --git a/PGate.cc b/PGate.cc new file mode 100644 index 000000000..4448b7e1a --- /dev/null +++ b/PGate.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999 Stephen Williams (steve@picturel.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: PGate.cc,v 1.1 1999/02/15 02:06:15 steve Exp $" +#endif + +# include "PGate.h" + +void PGBuiltin::set_range(PExpr*msb, PExpr*lsb) +{ + assert(msb_ == 0); + assert(lsb_ == 0); + + msb_ = msb; + lsb_ = lsb; +} + +/* + * $Log: PGate.cc,v $ + * Revision 1.1 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * + */ + diff --git a/PGate.h b/PGate.h index c292daf40..b9ab56749 100644 --- a/PGate.h +++ b/PGate.h @@ -1,7 +1,7 @@ #ifndef __PGate_H #define __PGate_H /* - * Copyright (c) 1998 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PGate.h,v 1.3 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: PGate.h,v 1.4 1999/02/15 02:06:15 steve Exp $" #endif # include @@ -27,6 +27,7 @@ class PExpr; class PUdp; class Design; +class Module; /* * A PGate represents a Verilog gate. The gate has a name and other @@ -85,9 +86,16 @@ class PGAssign : public PGate { }; -/* The Builtin class is specifically a gate with one of the builtin - types. The parser recognizes these types during parse. These types - have special properties that allow them to be treated specially. */ +/* + * The Builtin class is specifically a gate with one of the builtin + * types. The parser recognizes these types during parse. These types + * have special properties that allow them to be treated specially. + * + * A PGBuiltin can be grouped into an array of devices. If this is + * done, the msb_ and lsb_ are set to the indices of the array + * range. Elaboration causes a gate to be created for each element of + * the array, and a name will be generated for each gate. + */ class PGBuiltin : public PGate { public: @@ -99,16 +107,20 @@ class PGBuiltin : public PGate { public: explicit PGBuiltin(Type t, const string&name, const vector&pins, long del = 0) - : PGate(name, pins, del), type_(t) + : PGate(name, pins, del), type_(t), msb_(0), lsb_(0) { } Type type() const { return type_; } + void set_range(PExpr*msb, PExpr*lsb); virtual void dump(ostream&out) const; virtual void elaborate(Design*, const string&path) const; private: Type type_; + + PExpr*msb_; + PExpr*lsb_; }; /* @@ -136,6 +148,9 @@ class PGModule : public PGate { /* * $Log: PGate.h,v $ + * Revision 1.4 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.3 1999/01/25 05:45:56 steve * Add the LineInfo class to carry the source file * location of things. PGate, Statement and PProcess. diff --git a/design_dump.cc b/design_dump.cc index 81d56b4f2..4a584182b 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) -#ident "$Id: design_dump.cc,v 1.12 1999/02/08 02:49:56 steve Exp $" +#ident "$Id: design_dump.cc,v 1.13 1999/02/15 02:06:15 steve Exp $" #endif /* @@ -143,6 +143,12 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const case BUF: o << "buf"; break; + case BUFIF0: + o << "bufif0"; + break; + case BUFIF1: + o << "bufif1"; + break; case NAND: o << "nand"; break; @@ -330,7 +336,10 @@ void NetCondit::dump(ostream&o, unsigned ind) const o << setw(ind) << "" << "if ("; expr_->dump(o); o << ")" << endl; - if_->dump(o, ind+4); + + if (if_) if_->dump(o, ind+4); + else o << setw(ind+4) << "" << "/* empty */ ;" << endl; + if (else_) { o << setw(ind) << "" << "else" << endl; else_->dump(o, ind+4); @@ -497,6 +506,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.13 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.12 1999/02/08 02:49:56 steve * Turn the NetESignal into a NetNode so * that it can connect to the netlist. diff --git a/elaborate.cc b/elaborate.cc index 7aaa93220..4563cc2b3 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) -#ident "$Id: elaborate.cc,v 1.14 1999/02/08 02:49:56 steve Exp $" +#ident "$Id: elaborate.cc,v 1.15 1999/02/15 02:06:15 steve Exp $" #endif /* @@ -145,53 +145,127 @@ void PGAssign::elaborate(Design*des, const string&path) const do_assign(des, path, lval, rval); } -/* Elaborate a Builtin gate. These normally get translated into - NetLogic nodes that reflect the particular logic function. */ +/* + * Elaborate a Builtin gate. These normally get translated into + * NetLogic nodes that reflect the particular logic function. + */ void PGBuiltin::elaborate(Design*des, const string&path) const { - NetLogic*cur = 0; + unsigned count = 1; + unsigned low, high; string name = get_name(); if (name == "") name = des->local_symbol(path); - switch (type()) { - case AND: - cur = new NetLogic(name, pin_count(), NetLogic::AND); - break; - case BUF: - cur = new NetLogic(name, pin_count(), NetLogic::BUF); - break; - case NAND: - cur = new NetLogic(name, pin_count(), NetLogic::NAND); - break; - case NOR: - cur = new NetLogic(name, pin_count(), NetLogic::NOR); - break; - case NOT: - cur = new NetLogic(name, pin_count(), NetLogic::NOT); - break; - case OR: - cur = new NetLogic(name, pin_count(), NetLogic::OR); - break; - case XNOR: - cur = new NetLogic(name, pin_count(), NetLogic::XNOR); - break; - case XOR: - cur = new NetLogic(name, pin_count(), NetLogic::XOR); - break; + /* If the verilog source has a range specification for the + gates, then I am expected to make more then one + gate. Figure out how many are desired. */ + if (msb_) { + verinum*msb = msb_->eval_const(); + verinum*lsb = lsb_->eval_const(); + + if (msb == 0) { + cerr << get_line() << ": Unable to evaluate expression " + << *msb_ << endl; + des->errors += 1; + return; + } + + if (lsb == 0) { + cerr << get_line() << ": Unable to evaluate expression " + << *lsb_ << endl; + des->errors += 1; + return; + } + + if (msb->as_long() > lsb->as_long()) + count = msb->as_long() - lsb->as_long() + 1; + else + count = lsb->as_long() - msb->as_long() + 1; + + low = lsb->as_long(); + high = msb->as_long(); } + + /* Allocate all the getlist nodes for the gates. */ + NetLogic**cur = new NetLogic*[count]; assert(cur); - cur->delay1(get_delay()); - cur->delay2(get_delay()); - cur->delay3(get_delay()); - des->add_node(cur); + + for (unsigned idx = 0 ; idx < count ; idx += 1) { + strstream tmp; + unsigned index; + if (low < high) + index = low + idx; + else + index = low - idx; + + tmp << name << "<" << index << ">"; + const string inm = tmp.str(); + + switch (type()) { + case AND: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::AND); + break; + case BUF: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::BUF); + break; + case BUFIF0: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::BUFIF0); + break; + case BUFIF1: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::BUFIF1); + break; + case NAND: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::NAND); + break; + case NOR: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::NOR); + break; + case NOT: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::NOT); + break; + case OR: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::OR); + break; + case XNOR: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::XNOR); + break; + case XOR: + cur[idx] = new NetLogic(inm, pin_count(), NetLogic::XOR); + break; + } + + cur[idx]->delay1(get_delay()); + cur[idx]->delay2(get_delay()); + cur[idx]->delay3(get_delay()); + des->add_node(cur[idx]); + } + + /* The gates have all been allocated, this loop runs through + the parameters and attaches the ports of the objects. */ for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { const PExpr*ex = pin(idx); NetNet*sig = ex->elaborate_net(des, path); assert(sig); - connect(cur->pin(idx), sig->pin(0)); + + if (sig->pin_count() == 1) + for (unsigned gdx = 0 ; gdx < count ; gdx += 1) + connect(cur[gdx]->pin(idx), sig->pin(0)); + + else if (sig->pin_count() == count) + for (unsigned gdx = 0 ; gdx < count ; gdx += 1) + connect(cur[gdx]->pin(idx), sig->pin(gdx)); + + else { + cerr << get_line() << ": Gate count of " << count << + " does not match net width of " << + sig->pin_count() << " at pin " << idx << "." + << endl; + des->errors += 1; + } + if (NetTmp*tmp = dynamic_cast(sig)) delete tmp; } @@ -873,6 +947,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.15 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.14 1999/02/08 02:49:56 steve * Turn the NetESignal into a NetNode so * that it can connect to the netlist. diff --git a/netlist.h b/netlist.h index f2f5509e3..85b957f0f 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.18 1999/02/08 02:49:56 steve Exp $" +#ident "$Id: netlist.h,v 1.19 1999/02/15 02:06:15 steve Exp $" #endif /* @@ -337,7 +337,8 @@ class NetConst : public NetNode { class NetLogic : public NetNode { public: - enum TYPE { AND, BUF, NAND, NOR, NOT, OR, XNOR, XOR }; + enum TYPE { AND, BUF, BUFIF0, BUFIF1, NAND, NOR, NOT, OR, XNOR, + XOR }; explicit NetLogic(const string&n, unsigned pins, TYPE t); @@ -959,6 +960,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.19 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.18 1999/02/08 02:49:56 steve * Turn the NetESignal into a NetNode so * that it can connect to the netlist. diff --git a/parse.y b/parse.y index b181a92b7..b9cf76fcf 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: parse.y,v 1.12 1999/02/03 04:20:11 steve Exp $" +#ident "$Id: parse.y,v 1.13 1999/02/15 02:06:15 steve Exp $" #endif # include "parse_misc.h" @@ -316,6 +316,21 @@ gate_instance delete $1; $$ = tmp; } + | IDENTIFIER range '(' expression_list ')' + { lgate*tmp = new lgate; + list*rng = $2; + tmp->name = *$1; + tmp->parms = $4; + tmp->range[0] = rng->front(); + rng->pop_front(); + tmp->range[1] = rng->front(); + rng->pop_front(); + tmp->file = @1.text; + tmp->lineno = @1.first_line; + delete $1; + delete rng; + $$ = tmp; + } | '(' expression_list ')' { lgate*tmp = new lgate; tmp->name = ""; diff --git a/pform.cc b/pform.cc index 1893cf76f..81198b2e6 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.cc,v 1.8 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: pform.cc,v 1.9 1999/02/15 02:06:15 steve Exp $" #endif # include "pform.h" @@ -226,35 +226,44 @@ void pform_make_udp(string*name, list*parms, delete init_expr; } - +/* + * pform_makegates is called when a list of gates (with the same type) + * are ready to be instantiated. The function runs through the list of + * gates and makes an array of wires for the ports of the gate. It + * then calls the pform_makegate function to make the individual gate. + */ void pform_makegate(PGBuiltin::Type type, - const string&name, - const vector&wires, - unsigned long delay_val) + unsigned long delay_val, + const lgate&info) { - PGate*cur = new PGBuiltin(type, name, wires, delay_val); + vectorwires (info.parms->size()); + for (unsigned idx = 0 ; idx < wires.size() ; idx += 1) { + PExpr*ep = info.parms->front(); + info.parms->pop_front(); + wires[idx] = ep; + } + + PGBuiltin*cur = new PGBuiltin(type, info.name, wires, delay_val); + if (info.range[0]) + cur->set_range(info.range[0], info.range[1]); + + cur->set_file(info.file); + cur->set_lineno(info.lineno); + cur_module->add_gate(cur); } void pform_makegates(PGBuiltin::Type type, PExpr*delay, list*gates) { - unsigned long delay_val = evaluate_delay(delay); + unsigned long delay_val = delay? evaluate_delay(delay) : 0; delete delay; while (! gates->empty()) { lgate cur = gates->front(); gates->pop_front(); - vectorwires (cur.parms->size()); - for (unsigned idx = 0 ; idx < wires.size() ; idx += 1) { - PExpr*ep = cur.parms->front(); - cur.parms->pop_front(); - - wires[idx] = ep; - } - - pform_makegate(type, cur.name, wires, delay_val); + pform_makegate(type, delay_val, cur); } delete gates; @@ -500,6 +509,9 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.9 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.8 1999/01/25 05:45:56 steve * Add the LineInfo class to carry the source file * location of things. PGate, Statement and PProcess. diff --git a/pform.h b/pform.h index 3906ea516..6cdebee05 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef __pform_H #define __pform_H /* - * Copyright (c) 1998 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.h,v 1.6 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: pform.h,v 1.7 1999/02/15 02:06:15 steve Exp $" #endif # include "netlist.h" @@ -63,11 +63,17 @@ class PExpr; */ struct lgate { - lgate() : parms(0), lineno(0) { } + lgate() + : parms(0), lineno(0) + { range[0] = 0; + range[1] = 0; + } string name; list*parms; + PExpr*range[2]; + string file; unsigned lineno; }; @@ -110,11 +116,6 @@ extern list* pform_make_udp_input_ports(list*); * The makegate function creates a new gate (which need not have a * name) and connects it to the specified wires. */ -extern void pform_makegate(PGBuiltin::Type type, - const string&name, - const vector&wires, - unsigned long delay_value); - extern void pform_makegates(PGBuiltin::Type type, PExpr*delay, list*gates); @@ -137,6 +138,9 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.7 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.6 1999/01/25 05:45:56 steve * Add the LineInfo class to carry the source file * location of things. PGate, Statement and PProcess. diff --git a/pform_dump.cc b/pform_dump.cc index d103376a3..bd555459c 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform_dump.cc,v 1.9 1999/02/03 04:20:11 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.10 1999/02/15 02:06:15 steve Exp $" #endif /* @@ -157,6 +157,12 @@ void PGAssign::dump(ostream&out) const void PGBuiltin::dump(ostream&out) const { switch (type()) { + case PGBuiltin::BUFIF0: + out << " bufif0 #"; + break; + case PGBuiltin::BUFIF1: + out << " bufif1 #"; + break; case PGBuiltin::NAND: out << " nand #"; break; @@ -164,7 +170,13 @@ void PGBuiltin::dump(ostream&out) const out << " builtin gate #"; } - out << get_delay() << " " << get_name() << "("; + out << get_delay() << " " << get_name(); + + if (msb_) { + out << " [" << *msb_ << ":" << *lsb_ << "]"; + } + + out << "("; dump_pins(out); out << ");" << endl; } @@ -395,6 +407,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.10 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.9 1999/02/03 04:20:11 steve * Parse and elaborate the Verilog CASE statement. * diff --git a/t-vvm.cc b/t-vvm.cc index e4665b7b9..3b30557ca 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) -#ident "$Id: t-vvm.cc,v 1.11 1999/02/08 03:55:55 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.12 1999/02/15 02:06:15 steve Exp $" #endif # include @@ -360,6 +360,12 @@ void target_vvm::logic(ostream&os, const NetLogic*gate) os << "static vvm_and" << "<" << gate->pin_count()-1 << "," << gate->delay1() << "> "; break; + case NetLogic::BUFIF0: + os << "static vvm_bufif0<" << gate->delay1() << "> "; + break; + case NetLogic::BUFIF1: + os << "static vvm_bufif1<" << gate->delay1() << "> "; + break; case NetLogic::NAND: os << "static vvm_nand" << "<" << gate->pin_count()-1 << "," << gate->delay1() << "> "; @@ -831,6 +837,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.12 1999/02/15 02:06:15 steve + * Elaborate gate ranges. + * * Revision 1.11 1999/02/08 03:55:55 steve * Do not generate code for signals, * instead use the NetESignal node to