Handle unpacked arrays as module input ports.
This commit is contained in:
parent
6caa41cc93
commit
fc1f9ac6a5
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
elab_net.cc
19
elab_net.cc
|
|
@ -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. */
|
||||||
|
|
|
||||||
50
elaborate.cc
50
elaborate.cc
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
netmisc.cc
18
netmisc.cc
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue