hierarchy: Resolve SV wildcard port connections

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2019-11-22 09:04:54 +00:00
parent 50f86c11b2
commit 5df591c023
2 changed files with 63 additions and 4 deletions

View File

@ -1582,7 +1582,7 @@ cell_port:
free_attr($1);
} |
attr TOK_AUTOCONNECT_ALL {
astbuf2->attributes[ID(autoconnect)] = AstNode::mkconst_int(1, false);
astbuf2->attributes[ID(implicit_port_conns)] = AstNode::mkconst_int(1, false);
};
always_comb_or_latch:

View File

@ -548,6 +548,19 @@ RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod)
return NULL;
}
// Find a matching wire for an implicit port connection; traversing generate block scope
RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::string& port)
{
const std::string &cellname = cell->name.str();
size_t idx = cellname.size();
while ((idx = cellname.find_last_of('.', idx-1)) != std::string::npos) {
Wire *found = module->wire(cellname.substr(0, idx+1) + port.substr(1));
if (found != nullptr)
return found;
}
return module->wire(port);
}
struct HierarchyPass : public Pass {
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
void help() YS_OVERRIDE
@ -970,6 +983,55 @@ struct HierarchyPass : public Pass {
}
}
// Process SV implicit port connections
std::set<Module*> blackbox_derivatives;
std::vector<Module*> design_modules = design->modules();
for (auto module : design_modules)
{
for (auto cell : module->cells())
{
if (!cell->get_bool_attribute(ID(implicit_port_conns)))
continue;
Module *m = design->module(cell->type);
if (m == nullptr)
log_error("Cell %s.%s (%s) has implicit port connections but the module it instantiates is unknown.\n",
RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
// Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
IdString new_m_name = m->derive(design, cell->parameters, true);
if (new_m_name.empty())
continue;
if (new_m_name != m->name) {
m = design->module(new_m_name);
blackbox_derivatives.insert(m);
}
}
auto old_connections = cell->connections();
for (auto wire : m->wires()) {
// Find ports of the module that aren't explicitly connected
if (!wire->port_input && !wire->port_output)
continue;
if (old_connections.count(wire->name))
continue;
// Make sure a wire of correct name exists in the parent
Wire* parent_wire = find_implicit_port_wire(module, cell, wire->name.str());
if (parent_wire == nullptr)
log_error("No matching wire for implicit port connection `%s' of cell %s.%s (%s).\n",
RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
if (parent_wire->width != wire->width)
log_error("Width mismatch between wire (%d bits) and port (%d bits) for implicit port connection `%s' of cell %s.%s (%s).\n",
parent_wire->width, wire->width,
RTLIL::id2cstr(wire->name), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
cell->setPort(wire->name, parent_wire);
}
cell->attributes.erase(ID(implicit_port_conns));
}
}
if (!nodefaults)
{
dict<IdString, dict<IdString, Const>> defaults_db;
@ -1000,9 +1062,6 @@ struct HierarchyPass : public Pass {
}
}
std::set<Module*> blackbox_derivatives;
std::vector<Module*> design_modules = design->modules();
for (auto module : design_modules)
{
pool<Wire*> wand_wor_index;