module parameter bind by name.
This commit is contained in:
parent
5ef3970714
commit
35893919e0
42
PGate.h
42
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<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*>
|
||||
|
|
|
|||
89
elaborate.cc
89
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<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
37
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<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
|
||||
|
|
|
|||
66
pform.cc
66
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<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
17
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<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,
|
||||
|
|
|
|||
|
|
@ -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*>
|
||||
|
|
|
|||
Loading…
Reference in New Issue