Improve error reporting for unnamed module ports.

Implicit ports may be unnamed, either because the port expression
is not a simple/escaped identifier, or because there is no port
expression. To handle these cases, error messages should report
the port position as well as the port name.
This commit is contained in:
Martin Whitaker 2015-07-10 23:02:27 +01:00
parent 97c6339241
commit e6be9dec08
2 changed files with 38 additions and 35 deletions

View File

@ -94,13 +94,15 @@ perm_string Module::get_port_name(unsigned idx) const
{ {
assert(idx < ports.size()); assert(idx < ports.size());
if (ports[idx] == 0) { if (ports[idx] == 0 || ports[idx]->name.str() == 0) {
/* It is possible to have undeclared ports. These /* It is possible to have undeclared ports. These
are ports that are skipped in the declaration, are ports that are skipped in the declaration,
for example like so: module foo(x ,, y); The for example like so: module foo(x ,, y); The
port between x and y is unnamed and thus port between x and y is unnamed and thus
inaccessible to binding by name. */ inaccessible to binding by name. Port references
return perm_string::literal(""); that aren't simple or escaped identifiers are
also inaccessible to binding by name. */
return perm_string::literal("unnamed");
} }
return ports[idx]->name; return ports[idx]->name;
} }

View File

@ -1287,15 +1287,18 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
for (unsigned idx = 0 ; idx < pins.size() ; idx += 1) { for (unsigned idx = 0 ; idx < pins.size() ; idx += 1) {
bool unconnected_port = false; bool unconnected_port = false;
perm_string port_name = rmod->get_port_name(idx);
// Skip unconnected module ports. This happens when a // Skip unconnected module ports. This happens when a
// null parameter is passed in. // null parameter is passed in.
if (pins[idx] == 0) { if (pins[idx] == 0) {
if (pins_fromwc[idx]) { if (pins_fromwc[idx]) {
cerr << get_fileline() << ": error: Wildcard named port " << cerr << get_fileline() << ": error: Wildcard named "
"connection (.*) did not find a matching identifier " << "port connection (.*) did not find a matching "
"for port '" << rmod->ports[idx]->name << "'." << endl; "identifier for port " << (idx+1) << " ("
<< port_name << ")." << endl;
des->errors += 1; des->errors += 1;
return; return;
} }
@ -1330,22 +1333,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
break; break;
} }
// Print a waring for an unconnected input. // Print a warning for an unconnected input.
if (warn_portbinding) { if (warn_portbinding) {
cerr << get_fileline() << ": warning: " cerr << get_fileline() << ": warning: "
<< "Instantiating module " << "Instantiating module "
<< rmod->mod_name() << rmod->mod_name()
<< " with dangling input port '" << " with dangling input port "
<< rmod->ports[idx]->name; << (idx+1) << " (" << port_name;
switch (rmod->uc_drive) { switch (rmod->uc_drive) {
case Module::UCD_PULL0: case Module::UCD_PULL0:
cerr << "' (pulled low)." << endl; cerr << ") pulled low." << endl;
break; break;
case Module::UCD_PULL1: case Module::UCD_PULL1:
cerr << "' (pulled high)." << endl; cerr << ") pulled high." << endl;
break; break;
case Module::UCD_NONE: case Module::UCD_NONE:
cerr << "' (floating)." << endl; cerr << ") floating." << endl;
break; break;
} }
} }
@ -1361,8 +1364,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: " << get_name() cerr << get_fileline() << ": debug: " << get_name()
<< ": Port " << (idx+1) << " has " << prts.size() << ": Port " << (idx+1) << " (" << port_name
<< " sub-ports." << endl; << ") has " << prts.size() << " sub-ports." << endl;
} }
// Count the internal vector bits of the port. // Count the internal vector bits of the port.
@ -1394,7 +1397,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
prt_vector_width += port_width; prt_vector_width += port_width;
ptype = PortType::merged(netnet->port_type(), ptype); ptype = PortType::merged(netnet->port_type(), ptype);
} }
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width ); inst_scope->add_module_port_info(idx, port_name, ptype, prt_vector_width );
} }
// If I find that the port is unconnected inside the // If I find that the port is unconnected inside the
@ -1454,8 +1457,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1); NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1);
if (tmp_expr == 0) { if (tmp_expr == 0) {
cerr << pins[idx]->get_fileline() cerr << pins[idx]->get_fileline()
<< ": internal error: Port expression " << ": error: Failed to elaborate port expression."
<< "too complicated for elaboration." << endl; << endl;
des->errors += 1;
continue; continue;
} }
@ -1541,8 +1545,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "
<< "Inout port expression must support " << "Inout port expression must support "
<< "continuous assignment." << endl; << "continuous assignment." << endl;
cerr << pins[idx]->get_fileline() << ": : " cerr << pins[idx]->get_fileline() << ": : Port "
<< "Port " << rmod->ports[idx]->name << " of " << (idx+1) << " (" << port_name << ") of "
<< rmod->mod_name() << " is connected to " << rmod->mod_name() << " is connected to "
<< *pins[idx] << endl; << *pins[idx] << endl;
des->errors += 1; des->errors += 1;
@ -1555,9 +1559,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) { !prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "
<< "Cannot automatically connect bit based " << "Cannot automatically connect bit based "
"inout port " << rmod->ports[idx]->name "inout port " << (idx+1) << " (" << port_name
<< " of module " << rmod->mod_name() << " to real " << ") of module " << rmod->mod_name()
"signal " << sig->name() << "." << endl; << " to real signal " << sig->name() << "." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
} }
@ -1566,9 +1570,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) { if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) {
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "
<< "No support for connecting real inout ports (" << "No support for connecting real inout ports ("
"port " "port " << (idx+1) << " (" << port_name
<< rmod->ports[idx]->name << " of module " << ") of module " << rmod->mod_name() << ")." << endl;
<< rmod->mod_name() << ")." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
} }
@ -1611,8 +1614,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "
<< "Output port expression must support " << "Output port expression must support "
<< "continuous assignment." << endl; << "continuous assignment." << endl;
cerr << pins[idx]->get_fileline() << ": : " cerr << pins[idx]->get_fileline() << ": : Port "
<< "Port " << rmod->ports[idx]->name << " of " << (idx+1) << " (" << port_name << ") of "
<< rmod->mod_name() << " is connected to " << rmod->mod_name() << " is connected to "
<< *pins[idx] << endl; << *pins[idx] << endl;
des->errors += 1; des->errors += 1;
@ -1687,8 +1690,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
instance.size() != 1) { instance.size() != 1) {
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "
<< "An arrayed instance of " << rmod->mod_name() << "An arrayed instance of " << rmod->mod_name()
<< " cannot have a real port (" << " cannot have a real port (port " << (idx+1)
<< rmod->ports[idx]->name << ") connected to a " << " : " << port_name << ") connected to a "
"real signal (" << sig->name() << ")." << endl; "real signal (" << sig->name() << ")." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
@ -1721,8 +1724,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: " << get_name() cerr << get_fileline() << ": debug: " << get_name()
<< ": Port " << (idx+1) << " has vector width of " << ": Port " << (idx+1) << " (" << port_name
<< prts_vector_width << "." << endl; << ") has vector width of " << prts_vector_width
<< "." << endl;
} }
// Check that the parts have matching pin counts. If // Check that the parts have matching pin counts. If
@ -1730,11 +1734,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// based, but users count parameter positions from 1. // based, but users count parameter positions from 1.
if ((instance.size() == 1) if ((instance.size() == 1)
&& (prts_vector_width != sig->vector_width())) { && (prts_vector_width != sig->vector_width())) {
const char *tmp3 = rmod->ports[idx]->name.str();
bool as_signed = false; bool as_signed = false;
if (tmp3 == 0) tmp3 = "???";
switch (prts[0]->port_type()) { switch (prts[0]->port_type()) {
case NetNet::POUTPUT: case NetNet::POUTPUT:
as_signed = prts[0]->get_signed(); as_signed = prts[0]->get_signed();
@ -1754,7 +1755,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} }
cerr << get_fileline() << ": warning: Port " << (idx+1) cerr << get_fileline() << ": warning: Port " << (idx+1)
<< " (" << tmp3 << ") of " << " (" << port_name << ") of "
<< type_ << " expects " << prts_vector_width << << type_ << " expects " << prts_vector_width <<
" bits, got " << sig->vector_width() << "." << endl; " bits, got " << sig->vector_width() << "." << endl;