module parameter bind by name.

This commit is contained in:
steve 1999-05-29 02:36:17 +00:00
parent 5ef3970714
commit 35893919e0
6 changed files with 222 additions and 50 deletions

42
PGate.h
View File

@ -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<PExpr*>&pins, long del)
explicit PGate(const string&name, svector<PExpr*>*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<PExpr*>* get_pins() const { return pins_; }
void dump_pins(ostream&out) const;
private:
const string name_;
const unsigned long delay_;
svector<PExpr*> pins_;
svector<PExpr*>*pins_;
private: // not implemented
PGate(const PGate&);
@ -76,8 +78,8 @@ class PGate : public LineInfo {
class PGAssign : public PGate {
public:
explicit PGAssign(const svector<PExpr*>&pins)
: PGate("", pins, 0) { assert(pins.count() == 2); }
explicit PGAssign(svector<PExpr*>*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<PExpr*>&pins, long del = 0)
svector<PExpr*>*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<PExpr*>&pins)
: PGate(name, pins, 0), type_(type) { }
svector<PExpr*>*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<PExpr*>

View File

@ -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<PExpr*>*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<PExpr*>*exp = new svector<PExpr*>(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<string,Module*>&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.
*

37
parse.y
View File

@ -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<lgate>*gates;
portname_t*portname;
svector<portname_t*>*portnames;
PExpr*expr;
svector<PExpr*>*exprs;
@ -96,6 +99,9 @@ extern void lex_end_table();
%type <wire> port
%type <wires> list_of_ports list_of_ports_opt
%type <portname> port_name
%type <portnames> port_name_list
%type <citem> case_item
%type <citems> 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<portname_t*>*tmp;
tmp = new svector<portname_t*>(*$1, $3);
delete $1;
$$ = tmp;
}
| port_name
{ svector<portname_t*>*tmp = new svector<portname_t*>(1);
(*tmp)[0] = $1;
$$ = tmp;
}
;
port_type

View File

@ -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<string>*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<PExpr*>&wires,
svector<PExpr*>*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<portname_t*>*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<lgate>*gates)
{
for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) {
lgate cur = (*gates)[idx];
if (cur.parms) {
svector<PExpr*>wires = *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 {
svector<PExpr*>wires (0);
svector<PExpr*>*wires = new svector<PExpr*>(0);
pform_make_modgate(type, cur.name, wires, cur.file,
cur.lineno);
}
@ -306,9 +345,9 @@ void pform_make_modgates(const string&type, svector<lgate>*gates)
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval)
{
svector<PExpr*> wires (2);
wires[0] = lval;
wires[1] = rval;
svector<PExpr*>*wires = new svector<PExpr*>(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<string,Module*>&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,

17
pform.h
View File

@ -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<PExpr*>*parms;
svector<portname_t*>*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,

View File

@ -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<PExpr*>