From: David Shah Date: Fri, 22 Nov 2019 09:04:54 +0000 (+0000) Subject: hierarchy: Resolve SV wildcard port connections X-Git-Tag: working-ls180~824^2~5 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5df591c02309c086229029808c21ab8721278888;p=yosys.git hierarchy: Resolve SV wildcard port connections Signed-off-by: David Shah --- diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index cb413e13a..5ec8e66a6 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -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: diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index d8a628448..0704c2651 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -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 blackbox_derivatives; + std::vector 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> defaults_db; @@ -1000,9 +1062,6 @@ struct HierarchyPass : public Pass { } } - std::set blackbox_derivatives; - std::vector design_modules = design->modules(); - for (auto module : design_modules) { pool wand_wor_index;