Wildcard named port connections.

Implements Section 23.3.2.4 of IEEE 1800-2009.
This commit is contained in:
Jared Casper 2009-11-26 09:39:21 -08:00 committed by Stephen Williams
parent ab265c6373
commit 5ba1814e64
3 changed files with 51 additions and 5 deletions

View File

@ -1100,6 +1100,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// bind by order, this is the same as the source list. Otherwise,
// the source list is rearranged by name binding into this list.
vector<PExpr*>pins (rmod->port_count());
vector<bool>pins_fromwc (rmod->port_count(), false);
// If the instance has a pins_ member, then we know we are
// binding by name. Therefore, make up a pins array that
@ -1110,6 +1111,28 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// Scan the bindings, matching them with port names.
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
// Handle wildcard named port
if (pins_[idx].name[0] == '*') {
for (unsigned j = 0 ; j < nexp ; j += 1) {
if (!pins[j]) {
pins_fromwc[j] = true;
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
pform_name_t path_;
path_.push_back(name_component_t(rmod->ports[j]->name));
symbol_search(this, des, scope,
path_, net, par, eve);
if (net != 0) {
pins[j] = new PEIdent(rmod->ports[j]->name, true);
pins[j]->set_lineno(get_lineno());
pins[j]->set_file(get_file());
}
}
}
continue;
}
// Given a binding, look at the module port names
// for the position that matches the binding name.
unsigned pidx = rmod->find_port(pins_[idx].name);
@ -1125,10 +1148,17 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
continue;
}
// If I already bound something to this port, then
// the pins array will already have a pointer
// value where I want to place this expression.
if (pins[pidx]) {
// If I am overriding a wildcard port, delete and
// override it
if (pins_fromwc[pidx]) {
delete pins[pidx];
pins_fromwc[pidx] = false;
// If I already explicitely bound something to
// this port, then the pins array will already
// have a pointer value where I want to place this
// expression.
} else if (pins[pidx]) {
cerr << get_fileline() << ": error: port ``" <<
pins_[idx].name << "'' already bound." <<
endl;
@ -1204,6 +1234,15 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// null parameter is passed in.
if (pins[idx] == 0) {
if (pins_fromwc[idx]) {
cerr << get_fileline() << ": error: Wildcard named port " <<
"connection (.*) did not find a matching identifier " <<
"for port '" << rmod->ports[idx]->name << "'." << endl;
des->errors += 1;
return;
}
// We need this information to support the
// unconnected_drive directive and for a
// unconnected input warning when asked for.

View File

@ -136,6 +136,7 @@ TU [munpf]
"(*" { return K_PSTAR; }
"*)" { return K_STARP; }
".*" { return K_DOTSTAR; }
"<<" { return K_LS; }
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
">>" { return K_RS; }

View File

@ -300,7 +300,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
/* K_CONTRIBUTE is <+, the contribution assign. */
%token K_CONTRIBUTE
%token K_PO_POS K_PO_NEG K_POW
%token K_PSTAR K_STARP
%token K_PSTAR K_STARP K_DOTSTAR
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
%token K_edge_descriptor
@ -3318,6 +3318,12 @@ port_name
delete[]$2;
$$ = tmp;
}
| K_DOTSTAR
{ named_pexpr_t*tmp = new named_pexpr_t;
tmp->name = lex_strings.make("*");
tmp->parm = 0;
$$ = tmp;
}
;
port_name_list