From 5df591c02309c086229029808c21ab8721278888 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 22 Nov 2019 09:04:54 +0000 Subject: hierarchy: Resolve SV wildcard port connections Signed-off-by: David Shah --- passes/hierarchy/hierarchy.cc | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'passes/hierarchy/hierarchy.cc') 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; -- cgit v1.2.3 From 7e741714df62338a2037d24721ef99ca8a0c6763 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 22 Nov 2019 09:21:35 +0000 Subject: hierarchy: Correct handling of wildcard port connections with default values Signed-off-by: David Shah --- passes/hierarchy/hierarchy.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'passes/hierarchy/hierarchy.cc') diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 0704c2651..c298a6600 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -983,6 +983,15 @@ struct HierarchyPass : public Pass { } } + // Determine default values + dict> defaults_db; + if (!nodefaults) + { + for (auto module : design->modules()) + for (auto wire : module->wires()) + if (wire->port_input && wire->attributes.count("\\defaultvalue")) + defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); + } // Process SV implicit port connections std::set blackbox_derivatives; std::vector design_modules = design->modules(); @@ -1019,6 +1028,11 @@ struct HierarchyPass : public Pass { continue; // Make sure a wire of correct name exists in the parent Wire* parent_wire = find_implicit_port_wire(module, cell, wire->name.str()); + + // Missing wires are OK when a default value is set + if (!nodefaults && parent_wire == nullptr && defaults_db.count(cell->type) && defaults_db.at(cell->type).count(wire->name)) + continue; + 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)); @@ -1034,13 +1048,6 @@ struct HierarchyPass : public Pass { if (!nodefaults) { - dict> defaults_db; - - for (auto module : design->modules()) - for (auto wire : module->wires()) - if (wire->port_input && wire->attributes.count("\\defaultvalue")) - defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); - for (auto module : design->modules()) for (auto cell : module->cells()) { -- cgit v1.2.3 From 4bfd2ef4f328b4a95918ed3e0d7a7e38406c4ae8 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 22 Nov 2019 15:07:55 +0000 Subject: sv: Improve handling of wildcard port connections Signed-off-by: David Shah --- passes/hierarchy/hierarchy.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'passes/hierarchy/hierarchy.cc') diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index c298a6600..fa4a8ea29 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -992,7 +992,7 @@ struct HierarchyPass : public Pass { if (wire->port_input && wire->attributes.count("\\defaultvalue")) defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); } - // Process SV implicit port connections + // Process SV implicit wildcard port connections std::set blackbox_derivatives; std::vector design_modules = design->modules(); @@ -1000,7 +1000,7 @@ struct HierarchyPass : public Pass { { for (auto cell : module->cells()) { - if (!cell->get_bool_attribute(ID(implicit_port_conns))) + if (!cell->get_bool_attribute(ID(wildcard_port_conns))) continue; Module *m = design->module(cell->type); @@ -1042,7 +1042,7 @@ struct HierarchyPass : public Pass { 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)); + cell->attributes.erase(ID(wildcard_port_conns)); } } -- cgit v1.2.3