diff --git a/elaborate.cc b/elaborate.cc index dc3ccb862..4629c735b 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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. vectorpins (rmod->port_count()); + vectorpins_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. diff --git a/lexor.lex b/lexor.lex index 56791672c..48ad58070 100644 --- a/lexor.lex +++ b/lexor.lex @@ -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; } diff --git a/parse.y b/parse.y index fe517aef2..a6bc54cf2 100644 --- a/parse.y +++ b/parse.y @@ -300,7 +300,7 @@ static list* 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