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()) { if (name_tail.index.empty()) {
cerr << get_fileline() << ": error: Array " << path() cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl; << " needs an array index here." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }

View File

@ -890,13 +890,26 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
<< ", port_type()=" << sig->port_type() << endl; << ", port_type()=" << sig->port_type() << endl;
} }
if (sig->unpacked_dimensions()) { if (sig->unpacked_dimensions() && !gn_system_verilog()) {
cerr << get_fileline() << ": sorry: " cerr << get_fileline() << ": error: "
<< "Don't know now to elaborate unpacked array ports." << endl; << "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
des->errors += 1; des->errors += 1;
return 0; 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 /* Evaluate the part/bit select expressions, to get the part
select of the signal that attaches to the port. Also handle select of the signal that attaches to the port. Also handle
range and direction checking here. */ 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()); ivl_assert(*this, rval_net->pin_count() == lval->pin_count());
for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) { assign_unpacked_with_bufz(des, scope, this, lval, rval_net);
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));
}
} }
unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope, 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; unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT; PortType::Enum ptype = PortType::PIMPLICIT;
// Scan the module sub-ports for this instance... // 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) { for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
unsigned lbase = inst * mport.size(); unsigned lbase = inst * mport.size();
PEIdent*pport = mport[ldx]; PEIdent*pport = mport[ldx];
assert(pport); ivl_assert(*this, pport);
NetNet *netnet = pport->elaborate_subport(des, inst_scope); NetNet *netnet = pport->elaborate_subport(des, inst_scope);
prts[lbase + ldx] = netnet; prts[lbase + ldx] = netnet;
if (netnet == 0) if (netnet == 0)
continue; continue;
assert(netnet); ivl_assert(*this, netnet);
prts_vector_width += netnet->vector_width(); unsigned port_width = netnet->vector_width() * netnet->pin_count();
prt_vector_width += netnet->vector_width(); prts_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, 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 // module[s] port. sig is the thing outside the module
// that connects to the port. // that connects to the port.
NetNet*sig; NetNet*sig = 0;
if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) { 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 /* Input to module. elaborate the expression to
the desired width. If this in an instance the desired width. If this in an instance
array, then let the net determine its own 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) { } 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 /* Inout to/from module. This is a more
complicated case, where the expression must be complicated case, where the expression must be
an lnet, but also an r-value net. an lnet, but also an r-value net.
@ -1555,6 +1570,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else { } else {
// For now, do not support unpacked array outputs.
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
/* Port type must be OUTPUT here. */ /* Port type must be OUTPUT here. */
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT); 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. // stuff to the design that should be cleaned later.
NetNet *netnet = mport[pin]->elaborate_subport(des, scope); NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
if (netnet != 0) { 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(); prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype); 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); eval_expr(res, -1);
return res; 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 LineInfo*loc, NetNet*net,
const list<index_component_t>&indices); const list<index_component_t>&indices);
extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
const LineInfo*loc,
NetNet*lval, NetNet*rval);
#endif #endif