From 35893919e0803930061d5856272b784f0164827f Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 29 May 1999 02:36:17 +0000 Subject: [PATCH] module parameter bind by name. --- PGate.h | 42 +++++++++++++++++------- elaborate.cc | 89 ++++++++++++++++++++++++++++++++++++++++++--------- parse.y | 37 +++++++++++++++++---- pform.cc | 66 +++++++++++++++++++++++++++++++------- pform.h | 17 ++++++++-- pform_dump.cc | 21 ++++++++++-- 6 files changed, 222 insertions(+), 50 deletions(-) diff --git a/PGate.h b/PGate.h index 4a36b105c..281560c29 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) -#ident "$Id: PGate.h,v 1.5 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: PGate.h,v 1.6 1999/05/29 02:36:17 steve Exp $" #endif # include "svector.h" @@ -41,7 +41,7 @@ class Module; class PGate : public LineInfo { public: - explicit PGate(const string&name, const svector&pins, long del) + explicit PGate(const string&name, svector*pins, long del) : name_(name), delay_(del), pins_(pins) { } virtual ~PGate() { } @@ -50,19 +50,21 @@ class PGate : public LineInfo { long get_delay() const { return delay_; } - unsigned pin_count() const { return pins_.count(); } - const PExpr*pin(unsigned idx) const { return pins_[idx]; } + unsigned pin_count() const { return pins_? pins_->count() : 0; } + const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; } virtual void dump(ostream&out) const; virtual void elaborate(Design*des, const string&path) const; protected: + const svector* get_pins() const { return pins_; } + void dump_pins(ostream&out) const; private: const string name_; const unsigned long delay_; - svector pins_; + svector*pins_; private: // not implemented PGate(const PGate&); @@ -76,8 +78,8 @@ class PGate : public LineInfo { class PGAssign : public PGate { public: - explicit PGAssign(const svector&pins) - : PGate("", pins, 0) { assert(pins.count() == 2); } + explicit PGAssign(svector*pins) + : PGate("", pins, 0) { assert(pins->count() == 2); } void dump(ostream&out) const; virtual void elaborate(Design*des, const string&path) const; @@ -106,7 +108,7 @@ class PGBuiltin : public PGate { public: explicit PGBuiltin(Type t, const string&name, - const svector&pins, long del = 0) + svector*pins, long del = 0) : PGate(name, pins, del), type_(t), msb_(0), lsb_(0) { } @@ -126,21 +128,36 @@ class PGBuiltin : public PGate { /* * This kind of gate is an instantiation of a module. The stored type * is the name of a module definition somewhere in the pform. This - * type als handles UDP devices, because it is generally not known at + * type also handles UDP devices, because it is generally not known at * parse time whether a name belongs to a module or a UDP. */ class PGModule : public PGate { public: + // If the binding of ports is by position, this constructor + // builds everything all at once. explicit PGModule(const string&type, const string&name, - const svector&pins) - : PGate(name, pins, 0), type_(type) { } + svector*pins) + : PGate(name, pins, 0), type_(type), pins_(0), npins_(0) { } + + // If the binding of ports is by name, this constructor takes + // the bindings and stores them for later elaboration. + struct bind_t { + string name; + PExpr* parm; + }; + explicit PGModule(const string&type, const string&name, + bind_t*pins, unsigned npins) + : PGate(name, 0, 0), type_(type), pins_(pins), npins_(npins) { } + virtual void dump(ostream&out) const; virtual void elaborate(Design*, const string&path) const; private: string type_; + bind_t*pins_; + unsigned npins_; void elaborate_mod_(Design*, Module*mod, const string&path) const; void elaborate_udp_(Design*, PUdp *udp, const string&path) const; @@ -148,6 +165,9 @@ class PGModule : public PGate { /* * $Log: PGate.h,v $ + * Revision 1.6 1999/05/29 02:36:17 steve + * module parameter bind by name. + * * Revision 1.5 1999/05/10 00:16:58 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector diff --git a/elaborate.cc b/elaborate.cc index 53497a49c..a6f8d2381 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.28 1999/05/27 04:13:08 steve Exp $" +#ident "$Id: elaborate.cc,v 1.29 1999/05/29 02:36:17 steve Exp $" #endif /* @@ -340,6 +340,69 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const else my_name = path + "." + get_name(); + const svector*pins; + + // Detect binding by name. If I am binding by name, then make + // up a pins array that reflects the positions of the named + // ports. If this is simply positional binding in the first + // place, then get the binding from the base class. + if (pins_) { + unsigned nexp = rmod->ports.size(); + svector*exp = new svector(nexp); + + // Scan the bindings, matching them with port names. + for (unsigned idx = 0 ; idx < npins_ ; idx += 1) { + + // Given a binding, look at the module port names + // for the position that matches the binding name. + unsigned pidx = 0; + while (pidx < nexp) { + if (pins_[idx].name == rmod->ports[pidx]->name) + break; + + pidx += 1; + } + + if (pidx == nexp) { + cerr << get_line() << ": port ``" << + pins_[idx].name << "'' is not a port of " + << get_name() << "." << endl; + des->errors += 1; + continue; + } + + if ((*exp)[pidx]) { + cerr << get_line() << ": port ``" << + pins_[idx].name << "'' already bound." << + endl; + des->errors += 1; + continue; + } + + // OK, od the binding by placing the expression in + // the right place. + (*exp)[pidx] = pins_[idx].parm; + } + + pins = exp; + + } else { + + if (pin_count() != rmod->ports.size()) { + cerr << get_line() << ": Wrong number " + "of parameters. Expecting " << rmod->ports.size() << + ", got " << pin_count() << "." + << endl; + des->errors += 1; + return; + } + + // No named bindings, just use the positional list I + // already have. + assert(pin_count() == rmod->ports.size()); + pins = get_pins(); + } + // Elaborate this instance of the module. The recursive // elaboration causes the module to generate a netlist with // the ports represented by NetNet objects. I will find them @@ -347,24 +410,15 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const rmod->elaborate(des, my_name); // Now connect the ports of the newly elaborated designs to - // the expressions that are the instantiation parameters. + // the expressions that are the instantiation parameters. Scan + // the pins, elaborate the expressions attached to them, and + // bind them to the port of the elaborated module. - if (pin_count() != rmod->ports.size()) { - cerr << get_line() << ": Wrong number " - "of parameters. Expecting " << rmod->ports.size() << - ", got " << pin_count() << "." - << endl; - des->errors += 1; - return; - } - - assert(pin_count() == rmod->ports.size()); - - for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { + for (unsigned idx = 0 ; idx < pins->count() ; idx += 1) { // Skip unconnected module ports. - if (pin(idx) == 0) + if ((*pins)[idx] == 0) continue; - NetNet*sig = pin(idx)->elaborate_net(des, path); + NetNet*sig = (*pins)[idx]->elaborate_net(des, path); if (sig == 0) { cerr << "Expression too complicated for elaboration." << endl; continue; @@ -1193,6 +1247,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.29 1999/05/29 02:36:17 steve + * module parameter bind by name. + * * Revision 1.28 1999/05/27 04:13:08 steve * Handle expression bit widths with non-fatal errors. * diff --git a/parse.y b/parse.y index 8509679d2..12da85632 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.28 1999/05/27 03:31:29 steve Exp $" +#ident "$Id: parse.y,v 1.29 1999/05/29 02:36:17 steve Exp $" #endif # include "parse_misc.h" @@ -40,6 +40,9 @@ extern void lex_end_table(); lgate*gate; svector*gates; + portname_t*portname; + svector*portnames; + PExpr*expr; svector*exprs; @@ -96,6 +99,9 @@ extern void lex_end_table(); %type port %type list_of_ports list_of_ports_opt +%type port_name +%type port_name_list + %type case_item %type case_items @@ -552,11 +558,10 @@ gate_instance | IDENTIFIER '(' port_name_list ')' { lgate*tmp = new lgate; tmp->name = *$1; - tmp->parms = 0; + tmp->parms_by_name = $3; tmp->file = @1.text; tmp->lineno = @1.first_line; delete $1; - yyerror(@1, "Sorry, named port connections not supported."); $$ = tmp; } ; @@ -883,21 +888,41 @@ port port_name : PORTNAME '(' expression ')' - { delete $1; - delete $3; + { portname_t*tmp = new portname_t; + tmp->name = *$1; + tmp->parm = $3; + delete $1; + $$ = tmp; } | PORTNAME '(' error ')' { yyerror(@3, "invalid port connection expression."); + portname_t*tmp = new portname_t; + tmp->name = *$1; + tmp->parm = 0; delete $1; + $$ = tmp; } | PORTNAME '(' ')' - { delete $1; + { portname_t*tmp = new portname_t; + tmp->name = *$1; + tmp->parm = 0; + delete $1; + $$ = tmp; } ; port_name_list : port_name_list ',' port_name + { svector*tmp; + tmp = new svector(*$1, $3); + delete $1; + $$ = tmp; + } | port_name + { svector*tmp = new svector(1); + (*tmp)[0] = $1; + $$ = tmp; + } ; port_type diff --git a/pform.cc b/pform.cc index 3c1e44fee..a8f93dd14 100644 --- a/pform.cc +++ b/pform.cc @@ -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.19 1999/05/20 04:31:45 steve Exp $" +#ident "$Id: pform.cc,v 1.20 1999/05/29 02:36:17 steve Exp $" #endif # include "pform.h" @@ -237,14 +237,20 @@ void pform_make_udp(string*name, list*parms, /* * 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. + * gates and calls the pform_makegate function to make the individual gate. */ void pform_makegate(PGBuiltin::Type type, unsigned long delay_val, const lgate&info) { - PGBuiltin*cur = new PGBuiltin(type, info.name, *info.parms, delay_val); + if (info.parms_by_name) { + cerr << info.file << ":" << info.lineno << ": Gates do not " + "have port names." << endl; + error_count += 1; + return; + } + + PGBuiltin*cur = new PGBuiltin(type, info.name, info.parms, delay_val); if (info.range[0]) cur->set_range(info.range[0], info.range[1]); @@ -267,9 +273,13 @@ void pform_makegates(PGBuiltin::Type type, delete gates; } +/* + * A module is different from a gate in that there are different + * constraints, and sometimes different syntax. + */ static void pform_make_modgate(const string&type, const string&name, - const svector&wires, + svector*wires, const string&fn, unsigned ln) { if (name == "") { @@ -285,17 +295,46 @@ static void pform_make_modgate(const string&type, cur_module->add_gate(cur); } +static void pform_make_modgate(const string&type, + const string&name, + svector*bind, + const string&fn, unsigned ln) +{ + if (name == "") { + cerr << fn << ":" << ln << ": Instantiation of " << type + << " module requires an instance name." << endl; + error_count += 1; + return; + } + + unsigned npins = bind->count(); + PGModule::bind_t*pins = new PGModule::bind_t[npins]; + for (unsigned idx = 0 ; idx < npins ; idx += 1) { + portname_t*curp = (*bind)[idx]; + pins[idx].name = curp->name; + pins[idx].parm = curp->parm; + } + + PGate*cur = new PGModule(type, name, pins, npins); + cur->set_file(fn); + cur->set_lineno(ln); + cur_module->add_gate(cur); +} + void pform_make_modgates(const string&type, svector*gates) { for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) { lgate cur = (*gates)[idx]; - if (cur.parms) { - svectorwires = *cur.parms; - pform_make_modgate(type, cur.name, wires, cur.file, + if (cur.parms_by_name) { + pform_make_modgate(type, cur.name, cur.parms_by_name, + cur.file, cur.lineno); + + } else if (cur.parms) { + pform_make_modgate(type, cur.name, cur.parms, cur.file, cur.lineno); } else { - svectorwires (0); + svector*wires = new svector(0); pform_make_modgate(type, cur.name, wires, cur.file, cur.lineno); } @@ -306,9 +345,9 @@ void pform_make_modgates(const string&type, svector*gates) PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval) { - svector wires (2); - wires[0] = lval; - wires[1] = rval; + svector*wires = new svector(2); + (*wires)[0] = lval; + (*wires)[1] = rval; PGAssign*cur = new PGAssign(wires); cur_module->add_gate(cur); return cur; @@ -517,6 +556,9 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.20 1999/05/29 02:36:17 steve + * module parameter bind by name. + * * Revision 1.19 1999/05/20 04:31:45 steve * Much expression parsing work, * mark continuous assigns with source line info, diff --git a/pform.h b/pform.h index 582482510..c6a54fd6c 100644 --- a/pform.h +++ b/pform.h @@ -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.15 1999/05/20 04:31:45 steve Exp $" +#ident "$Id: pform.h,v 1.16 1999/05/29 02:36:17 steve Exp $" #endif # include "netlist.h" @@ -62,15 +62,24 @@ class PExpr; * not in any way preserved once parsing is done. */ +/* This is information about port name information for named port + connections. */ +struct portname_t { + string name; + PExpr*parm; +}; + +/* The lgate is gate instantiation information. */ struct lgate { lgate(int =0) - : parms(0), lineno(0) + : parms(0), parms_by_name(0), lineno(0) { range[0] = 0; range[1] = 0; } string name; svector*parms; + svector*parms_by_name; PExpr*range[2]; @@ -78,7 +87,6 @@ struct lgate { unsigned lineno; }; - /* * The parser uses startmodule and endmodule together to build up a * module as it parses it. The startmodule tells the pform code that a @@ -140,6 +148,9 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.16 1999/05/29 02:36:17 steve + * module parameter bind by name. + * * Revision 1.15 1999/05/20 04:31:45 steve * Much expression parsing work, * mark continuous assigns with source line info, diff --git a/pform_dump.cc b/pform_dump.cc index 578e53944..a191c868c 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.16 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.17 1999/05/29 02:36:17 steve Exp $" #endif /* @@ -111,12 +111,18 @@ void PEBinary::dump(ostream&out) const case 'E': out << "==="; break; + case 'l': + out << "<<"; + break; case 'n': out << "!="; break; case 'N': out << "!=="; break; + case 'r': + out << ">>"; + break; default: out << op_; break; @@ -226,7 +232,15 @@ void PGBuiltin::dump(ostream&out) const void PGModule::dump(ostream&out) const { out << " " << type_ << " " << get_name() << "("; - dump_pins(out); + if (pins_) { + out << "." << pins_[0].name << "(" << *pins_[0].parm << ")"; + for (unsigned idx = 1 ; idx < npins_ ; idx += 1) { + out << ", ." << pins_[idx].name << "(" << + *pins_[idx].parm << ")"; + } + } else { + dump_pins(out); + } out << ");" << endl; } @@ -454,6 +468,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.17 1999/05/29 02:36:17 steve + * module parameter bind by name. + * * Revision 1.16 1999/05/10 00:16:58 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector