Handle unpacked arrays as module input ports.

This commit is contained in:
Stephen Williams 2014-03-22 20:50:47 -07:00
parent 6caa41cc93
commit fc1f9ac6a5
5 changed files with 74 additions and 19 deletions

View File

@ -3970,7 +3970,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
if (name_tail.index.empty()) {
cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl;
<< " needs an array index here." << endl;
des->errors += 1;
return 0;
}

View File

@ -890,13 +890,26 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
<< ", port_type()=" << sig->port_type() << endl;
}
if (sig->unpacked_dimensions()) {
cerr << get_fileline() << ": sorry: "
<< "Don't know now to elaborate unpacked array ports." << endl;
if (sig->unpacked_dimensions() && !gn_system_verilog()) {
cerr << get_fileline() << ": error: "
<< "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
des->errors += 1;
return 0;
}
// There cannot be parts to an unpacked array, so process this
// simply as an unpacked array.
if (sig->unpacked_dimensions()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
<< "path_=\"" << path_
<< "\" is an unpacked array with " << sig->pin_count()
<< " elements." << endl;
}
scope->add_module_port_net(sig);
return sig;
}
/* Evaluate the part/bit select expressions, to get the part
select of the signal that attaches to the port. Also handle
range and direction checking here. */

View File

@ -228,15 +228,7 @@ void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval
ivl_assert(*this, rval_net->pin_count() == lval->pin_count());
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) {
NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(),
lval->vector_width(), false);
driver->set_line(*this);
des->add_node(driver);
connect(lval->pin(idx), driver->pin(0));
connect(driver->pin(1), rval_net->pin(idx));
}
assign_unpacked_with_bufz(des, scope, this, lval, rval_net);
}
unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
@ -1378,18 +1370,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
// Scan the module sub-ports for this instance...
// (Sub-ports are concatenated ports that form the
// single port for the instance. This is not a
// commonly used feature.)
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
unsigned lbase = inst * mport.size();
PEIdent*pport = mport[ldx];
assert(pport);
ivl_assert(*this, pport);
NetNet *netnet = pport->elaborate_subport(des, inst_scope);
prts[lbase + ldx] = netnet;
if (netnet == 0)
continue;
assert(netnet);
prts_vector_width += netnet->vector_width();
prt_vector_width += netnet->vector_width();
ivl_assert(*this, netnet);
unsigned port_width = netnet->vector_width() * netnet->pin_count();
prts_vector_width += port_width;
prt_vector_width += port_width;
ptype = PortType::merged(netnet->port_type(), ptype);
}
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
@ -1420,9 +1416,25 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// module[s] port. sig is the thing outside the module
// that connects to the port.
NetNet*sig;
NetNet*sig = 0;
if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) {
// Special case: If the input port is an unpacked
// array, then there should be no sub-ports and
// the r-value expression is processed
// differently.
if (prts.size() >= 1 && prts[0]->pin_count()>1) {
ivl_assert(*this, prts.size()==1);
PEIdent*rval_pident = dynamic_cast<PEIdent*> (pins[idx]);
ivl_assert(*this, rval_pident);
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count());
assign_unpacked_with_bufz(des, scope, this, prts[0], rval_net);
continue;
}
/* Input to module. elaborate the expression to
the desired width. If this in an instance
array, then let the net determine its own
@ -1499,6 +1511,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else if (prts[0]->port_type() == NetNet::PINOUT) {
// For now, do not support unpacked array outputs.
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
/* Inout to/from module. This is a more
complicated case, where the expression must be
an lnet, but also an r-value net.
@ -1555,6 +1570,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else {
// For now, do not support unpacked array outputs.
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
/* Port type must be OUTPUT here. */
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
@ -5840,7 +5858,9 @@ Design* elaborate(list<perm_string>roots)
// stuff to the design that should be cleaned later.
NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
if (netnet != 0) {
// Elaboration may actually fail with erroneous input source
// Elaboration may actually fail with
// erroneous input source
ivl_assert(*mport[pin], netnet->pin_count()==1);
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}

View File

@ -1338,3 +1338,21 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
eval_expr(res, -1);
return res;
}
void assign_unpacked_with_bufz(Design*des, NetScope*scope,
const LineInfo*loc,
NetNet*lval, NetNet*rval)
{
ivl_assert(*loc, lval->pin_count()==rval->pin_count());
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) {
NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(),
lval->vector_width(), false);
driver->set_line(*loc);
des->add_node(driver);
connect(lval->pin(idx), driver->pin(0));
connect(driver->pin(1), rval->pin(idx));
}
}

View File

@ -349,4 +349,8 @@ extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
const LineInfo*loc, NetNet*net,
const list<index_component_t>&indices);
extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
const LineInfo*loc,
NetNet*lval, NetNet*rval);
#endif