diff --git a/passes/hierarchy/util/interfaces.cc b/passes/hierarchy/util/interfaces.cc index b3b30af94..ae73a2f94 100644 --- a/passes/hierarchy/util/interfaces.cc +++ b/passes/hierarchy/util/interfaces.cc @@ -130,7 +130,7 @@ RTLIL::Module *get_module(RTLIL::Design &design, if (!check_file_exists(filename)) continue; - Frontend::frontend_call(&design, NULL, filename, ext.second); + Frontend::frontend_call(&design, nullptr, filename, ext.second); RTLIL::Module *mod = design.module(cell.type); if (!mod) log_error("File `%s' from libdir does not declare module `%s'.\n", @@ -149,8 +149,8 @@ RTLIL::Module *get_module(RTLIL::Design &design, std::set> used_modules(Design* design, Module* top_mod) { std::set> used; - if (top_mod != NULL) { - log_header(design, "Analyzing design hierarchy..\n"); + if (top_mod != nullptr) { + log_header(design, "Analyzing design hierarchy (used)..\n"); mark_used(design, used, top_mod, 0); } else { for (auto mod : design->modules()) @@ -159,7 +159,20 @@ std::set> used_modules(Des return used; } -void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs) { +// Delete modules marked as 'to_delete' +void delete_marked_modules(Design* design) { + std::vector modules_to_delete; + for(auto mod : design->modules()) { + if (mod->get_bool_attribute(ID::to_delete)) { + modules_to_delete.push_back(mod); + } + } + for(size_t i=0; iremove(modules_to_delete[i]); + } +} + +void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs) { bool did_something = true; while (did_something) { @@ -170,33 +183,73 @@ void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, boo did_something = true; } - // The top module might have changed if interface instances have been detected in it: + // The top module might have changed if interface instances have been detected in it RTLIL::Module *tmp_top_mod = check_if_top_has_changed(design, top_mod); - if (tmp_top_mod != NULL) { + if (tmp_top_mod != nullptr) { if (tmp_top_mod != top_mod){ top_mod = tmp_top_mod; top_mod->attributes[ID::initial_top] = RTLIL::Const(1); did_something = true; } } - - // Delete modules marked as 'to_delete': - std::vector modules_to_delete; - for(auto mod : design->modules()) { - if (mod->get_bool_attribute(ID::to_delete)) { - modules_to_delete.push_back(mod); - } - } - for(size_t i=0; iremove(modules_to_delete[i]); - } + delete_marked_modules(design); } } +struct CellArrays { + std::map> cells; + std::optional trim_and_register(Cell* cell) { + if (auto a = try_make_array(cell->type.str())) { + int idx = atoi(cell->type.substr(a->pos_idx + 1, a->pos_num).c_str()); + int num = atoi(cell->type.substr(a->pos_num + 1, a->pos_type).c_str()); + cells[cell] = std::pair(idx, num); + return cell->type.substr(a->pos_type + 1); + } + return std::nullopt; + } + void resolve() { + for (auto &it : cells) + { + Cell* cell = it.first; + Module* module = cell->module; + log_assert(module); + Design* design = module->design; + + int idx = it.second.first, num = it.second.second; + + if (design->module(cell->type) == nullptr) + log_error("Array cell `%s.%s' of unknown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); + + RTLIL::Module *mod = design->module(cell->type); + + for (auto &conn : cell->connections_) { + int conn_size = conn.second.size(); + RTLIL::IdString portname = conn.first; + if (portname.begins_with("$")) { + int port_id = atoi(portname.substr(1).c_str()); + for (auto wire : mod->wires()) + if (wire->port_id == port_id) { + portname = wire->name; + break; + } + } + if (mod->wire(portname) == nullptr) + log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); + int port_size = mod->wire(portname)->width; + if (conn_size == port_size || conn_size == 0) + continue; + if (conn_size != port_size*num) + log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); + conn.second = conn.second.extract(port_size*idx, port_size); + } + } + } +}; + bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs) { bool did_something = false; - std::map> array_cells; + CellArrays cell_arrays; std::string filename; bool has_interface_ports = false; @@ -209,46 +262,35 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check has_interface_ports = true; } } + IFModExpander if_mod_expander(*design, *module); + for (auto cell : module->cells()) { + if (auto unarrayed_type = cell_arrays.trim_and_register(cell)) + cell->type = *unarrayed_type; - IFExpander if_expander(*design, *module); - - for (auto cell : module->cells()) - { - if_expander.start_cell(); - - if (auto a = try_make_array(cell->type.str())) { - int idx = atoi(cell->type.substr(a->pos_idx + 1, a->pos_num).c_str()); - int num = atoi(cell->type.substr(a->pos_num + 1, a->pos_type).c_str()); - array_cells[cell] = std::pair(idx, num); - cell->type = cell->type.substr(a->pos_type + 1); - } - - RTLIL::Module *mod = design->module(cell->type); - if (!mod) + RTLIL::Module *submod = design->module(cell->type); + if (!submod) { - mod = get_module(*design, *cell, *module, flag_check || flag_simcheck || flag_smtcheck, libdirs); - + submod = get_module(*design, *cell, *module, flag_check || flag_simcheck || flag_smtcheck, libdirs); // If we still don't have a module, treat the cell as a black box and skip // it. Otherwise, we either loaded or derived something so should set the // did_something flag before returning (to ensure we come back and expand // the thing we just loaded). - if (mod) + if (submod) did_something = true; - continue; } + log_assert(submod); - log_assert(mod); - + IFCellExpander if_expander = {if_mod_expander, cell}; // Go over all connections and check if any of them are SV // interfaces. - if_expander.visit_connections(*cell, *mod); + if_expander.visit_connections(*submod); if (flag_check || flag_simcheck || flag_smtcheck) - check_cell_connections(*module, *cell, *mod); + check_cell_connections(*module, *cell, *submod); - if (mod->get_blackbox_attribute()) { - if (flag_simcheck || (flag_smtcheck && !mod->get_bool_attribute(ID::smtlib2_module))) + if (submod->get_blackbox_attribute()) { + if (flag_simcheck || (flag_smtcheck && !submod->get_bool_attribute(ID::smtlib2_module))) log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n", cell->type.c_str(), module->name.c_str(), cell->name.c_str()); continue; @@ -256,11 +298,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here: if(if_expander.has_interfaces_not_found) { + // TODO special defer value instead did_something = true; // waiting for interfaces to be handled continue; } - if_expander.rewrite_interface_connections(*cell); + if_expander.rewrite_interface_connections(); // If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type // for the cell: @@ -269,13 +312,13 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check !(cell->get_bool_attribute(ID::module_not_derived)))) { // If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:", // so that the signals of the interface are added to the parent module. - if (mod->get_bool_attribute(ID::is_interface)) { + if (submod->get_bool_attribute(ID::is_interface)) { goto handle_interface_instance; } continue; } - cell->type = mod->derive(design, + cell->type = submod->derive(design, cell->parameters, if_expander.interfaces_to_add_to_submodule, if_expander.modports_used_in_submodule); @@ -286,10 +329,10 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter // an interface instance: - if (mod->get_bool_attribute(ID::is_interface) && cell->get_bool_attribute(ID::module_not_derived)) { + if (submod->get_bool_attribute(ID::is_interface) && cell->get_bool_attribute(ID::module_not_derived)) { cell->set_bool_attribute(ID::is_interface); RTLIL::Module *derived_module = design->module(cell->type); - if_expander.interfaces_in_module[cell->name] = derived_module; + if_mod_expander.interfaces_in_module[cell->name] = derived_module; did_something = true; } // We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell) @@ -302,8 +345,8 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check // If any interface instances or interface ports were found in the module, we need to rederive it completely: - if ((if_expander.interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) { - module->expand_interfaces(design, if_expander.interfaces_in_module); + if ((if_mod_expander.interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) { + module->expand_interfaces(design, if_mod_expander.interfaces_in_module); return did_something; } @@ -312,43 +355,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check if (module->reprocess_if_necessary(design)) return true; - for (auto &it : array_cells) - { - RTLIL::Cell *cell = it.first; - int idx = it.second.first, num = it.second.second; - - if (design->module(cell->type) == nullptr) - log_error("Array cell `%s.%s' of unknown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - - RTLIL::Module *mod = design->module(cell->type); - - for (auto &conn : cell->connections_) { - int conn_size = conn.second.size(); - RTLIL::IdString portname = conn.first; - if (portname.begins_with("$")) { - int port_id = atoi(portname.substr(1).c_str()); - for (auto wire : mod->wires()) - if (wire->port_id == port_id) { - portname = wire->name; - break; - } - } - if (mod->wire(portname) == nullptr) - log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); - int port_size = mod->wire(portname)->width; - if (conn_size == port_size || conn_size == 0) - continue; - if (conn_size != port_size*num) - log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first)); - conn.second = conn.second.extract(port_size*idx, port_size); - } - } + cell_arrays.resolve(); return did_something; } -IFExpander::IFExpander (RTLIL::Design &design, RTLIL::Module &m) - : module(m), has_interfaces_not_found(false) +IFModExpander::IFModExpander (RTLIL::Design &design, RTLIL::Module &m) : module(m) { // Keep track of all derived interfaces available in the current // module in 'interfaces_in_module': @@ -360,25 +372,14 @@ IFExpander::IFExpander (RTLIL::Design &design, RTLIL::Module &m) } } -// Reset the per-cell state -void IFExpander::start_cell() -{ - has_interfaces_not_found = false; - connections_to_remove.clear(); - connections_to_add_name.clear(); - connections_to_add_signal.clear(); - interfaces_to_add_to_submodule.clear(); - modports_used_in_submodule.clear(); -} - // Set has_interfaces_not_found if there are pending interfaces that // haven't been found yet (and might be found in the future). Print a // warning if we've already gone over all the cells in the module. -void IFExpander::on_missing_interface(RTLIL::IdString interface_name) +void IFCellExpander::on_missing_interface(RTLIL::IdString interface_name) { // If there are cells that haven't yet been processed, maybe // we'll find this interface in the future. - if (module.get_bool_attribute(ID::cells_not_processed)) { + if (cell->module->get_bool_attribute(ID::cells_not_processed)) { has_interfaces_not_found = true; return; } @@ -388,13 +389,13 @@ void IFExpander::on_missing_interface(RTLIL::IdString interface_name) // about it and don't set has_interfaces_not_found (to avoid a // loop). log_warning("Could not find interface instance for `%s' in `%s'\n", - log_id(interface_name), log_id(&module)); + log_id(interface_name), log_id(cell->module)); } // Handle an interface connection from the module -void IFExpander::on_interface(RTLIL::Module &submodule, - RTLIL::IdString conn_name, - const RTLIL::SigSpec &conn_signals) +void IFCellExpander::on_interface(RTLIL::Module &submodule, + RTLIL::IdString conn_name, + const RTLIL::SigSpec &conn_signals) { // Check if the connected wire is a potential interface in the parent module std::string interface_name_str = conn_signals[0].wire->name.str(); @@ -405,7 +406,7 @@ void IFExpander::on_interface(RTLIL::Module &submodule, // If 'interfaces' in the cell have not be been handled yet, we aren't // ready to derive the sub-module either - if (!module.get_bool_attribute(ID::interfaces_replaced_in_module)) { + if (!cell->module->get_bool_attribute(ID::interfaces_replaced_in_module)) { on_missing_interface(interface_name); return; } @@ -413,10 +414,10 @@ void IFExpander::on_interface(RTLIL::Module &submodule, // Check if the interface instance is present in module. Interface // instances may either have the plain name or the name appended with // '_inst_from_top_dummy'. Check for both of them here - int nexactmatch = interfaces_in_module.count(interface_name) > 0; + int nexactmatch = mod_expander.interfaces_in_module.count(interface_name) > 0; std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy"; RTLIL::IdString interface_name2 = interface_name_str2; - int nmatch2 = interfaces_in_module.count(interface_name2) > 0; + int nmatch2 = mod_expander.interfaces_in_module.count(interface_name2) > 0; // If we can't find either name, this is a missing interface. if (! (nexactmatch || nmatch2)) { @@ -427,24 +428,24 @@ void IFExpander::on_interface(RTLIL::Module &submodule, if (nexactmatch != 0) // Choose the one with the plain name if it exists interface_name2 = interface_name; - RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2); + RTLIL::Module *mod_replace_ports = mod_expander.interfaces_in_module.at(interface_name2); // Go over all wires in interface, and add replacements to lists. for (auto mod_wire : mod_replace_ports->wires()) { std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name); std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire); connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); - if(module.wire(signal_name2) == nullptr) { + if(cell->module->wire(signal_name2) == nullptr) { log_error("Could not find signal '%s' in '%s'\n", - signal_name2.c_str(), log_id(module.name)); + signal_name2.c_str(), log_id(cell->module->name)); } else { - RTLIL::Wire *wire_in_parent = module.wire(signal_name2); + RTLIL::Wire *wire_in_parent = cell->module->wire(signal_name2); connections_to_add_signal.push_back(wire_in_parent); } } connections_to_remove.push_back(conn_name); - interfaces_to_add_to_submodule[conn_name] = interfaces_in_module.at(interface_name2); + interfaces_to_add_to_submodule[conn_name] = mod_expander.interfaces_in_module.at(interface_name2); // Find if the sub-module has set a modport for the current interface // connection. Add any modports to a dict which will be passed to @@ -457,9 +458,9 @@ void IFExpander::on_interface(RTLIL::Module &submodule, // Handle a single connection from the module, making a note to expand // it if it's an interface connection. -void IFExpander::on_connection(RTLIL::Module &submodule, - RTLIL::IdString conn_name, - const RTLIL::SigSpec &conn_signals) +void IFCellExpander::on_connection(RTLIL::Module &submodule, + RTLIL::IdString conn_name, + const RTLIL::SigSpec &conn_signals) { // Does the connection look like an interface if ( @@ -485,7 +486,7 @@ void IFExpander::on_connection(RTLIL::Module &submodule, * parent and child). */ log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n", - module.name, + cell->module->name, submodule.name, conn_signals[0].wire->name.str().substr(23) ); @@ -501,24 +502,23 @@ void IFExpander::on_connection(RTLIL::Module &submodule, // Iterate over the connections in a cell, tracking any interface // connections -void IFExpander::visit_connections(const RTLIL::Cell &cell, - RTLIL::Module &submodule) +void IFCellExpander::visit_connections(RTLIL::Module &submodule) { - for (const auto &conn : cell.connections()) { + for (const auto &conn : cell->connections()) { on_connection(submodule, conn.first, conn.second); } } // Add/remove connections to the cell as necessary, replacing any SV // interface port connection with the individual signal connections. -void IFExpander::rewrite_interface_connections(RTLIL::Cell &cell) const +void IFCellExpander::rewrite_interface_connections() const { for(unsigned int i=0;iconnections_[connections_to_add_name[i]] = connections_to_add_signal[i]; } // Remove the connection for the interface itself: for(unsigned int i=0;iconnections_.erase(connections_to_remove[i]); } } diff --git a/passes/hierarchy/util/interfaces.h b/passes/hierarchy/util/interfaces.h index 488a34286..138d25daf 100644 --- a/passes/hierarchy/util/interfaces.h +++ b/passes/hierarchy/util/interfaces.h @@ -26,51 +26,45 @@ YOSYS_NAMESPACE_BEGIN namespace Hierarchy { -void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs); +void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs); bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector &libdirs); // For expanding a module's interface connections -struct IFExpander +struct IFModExpander { - IFExpander (RTLIL::Design &design, RTLIL::Module &m); - + IFModExpander (RTLIL::Design &design, RTLIL::Module &m); RTLIL::Module &module; dict interfaces_in_module; +}; - bool has_interfaces_not_found; - std::vector connections_to_remove; - std::vector connections_to_add_name; - std::vector connections_to_add_signal; - dict interfaces_to_add_to_submodule; - dict modports_used_in_submodule; - - // Reset the per-cell state - void start_cell(); - +struct IFCellExpander { + IFModExpander& mod_expander; + RTLIL::Cell* cell; + bool has_interfaces_not_found = false; + std::vector connections_to_remove = {}; + std::vector connections_to_add_name = {}; + std::vector connections_to_add_signal = {}; + dict interfaces_to_add_to_submodule = {}; + dict modports_used_in_submodule = {}; // Set has_interfaces_not_found if there are pending interfaces that // haven't been found yet (and might be found in the future). Print a // warning if we've already gone over all the cells in the module. void on_missing_interface(RTLIL::IdString interface_name); - + // Iterate over the connections of the cell, tracking any interface + // connections + void visit_connections(RTLIL::Module &submodule); // Handle an interface connection from the module void on_interface(RTLIL::Module &submodule, - RTLIL::IdString conn_name, - const RTLIL::SigSpec &conn_signals); - + RTLIL::IdString conn_name, + const RTLIL::SigSpec &conn_signals); // Handle a single connection from the module, making a note to expand // it if it's an interface connection. void on_connection(RTLIL::Module &submodule, - RTLIL::IdString conn_name, - const RTLIL::SigSpec &conn_signals); - - // Iterate over the connections in a cell, tracking any interface - // connections - void visit_connections(const RTLIL::Cell &cell, - RTLIL::Module &submodule); - + RTLIL::IdString conn_name, + const RTLIL::SigSpec &conn_signals); // Add/remove connections to the cell as necessary, replacing any SV // interface port connection with the individual signal connections. - void rewrite_interface_connections(RTLIL::Cell &cell) const; + void rewrite_interface_connections() const; }; };