mirror of https://github.com/YosysHQ/yosys.git
hierarchy interfaces: refactor
This commit is contained in:
parent
6488928a9c
commit
343538becc
|
|
@ -130,7 +130,7 @@ RTLIL::Module *get_module(RTLIL::Design &design,
|
||||||
if (!check_file_exists(filename))
|
if (!check_file_exists(filename))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Frontend::frontend_call(&design, NULL, filename, ext.second);
|
Frontend::frontend_call(&design, nullptr, filename, ext.second);
|
||||||
RTLIL::Module *mod = design.module(cell.type);
|
RTLIL::Module *mod = design.module(cell.type);
|
||||||
if (!mod)
|
if (!mod)
|
||||||
log_error("File `%s' from libdir does not declare module `%s'.\n",
|
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<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used_modules(Design* design, Module* top_mod) {
|
std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used_modules(Design* design, Module* top_mod) {
|
||||||
std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used;
|
std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used;
|
||||||
if (top_mod != NULL) {
|
if (top_mod != nullptr) {
|
||||||
log_header(design, "Analyzing design hierarchy..\n");
|
log_header(design, "Analyzing design hierarchy (used)..\n");
|
||||||
mark_used(design, used, top_mod, 0);
|
mark_used(design, used, top_mod, 0);
|
||||||
} else {
|
} else {
|
||||||
for (auto mod : design->modules())
|
for (auto mod : design->modules())
|
||||||
|
|
@ -159,7 +159,20 @@ std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used_modules(Des
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs) {
|
// Delete modules marked as 'to_delete'
|
||||||
|
void delete_marked_modules(Design* design) {
|
||||||
|
std::vector<RTLIL::Module *> 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; i<modules_to_delete.size(); i++) {
|
||||||
|
design->remove(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<std::string> &libdirs) {
|
||||||
bool did_something = true;
|
bool did_something = true;
|
||||||
while (did_something)
|
while (did_something)
|
||||||
{
|
{
|
||||||
|
|
@ -170,33 +183,73 @@ void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, boo
|
||||||
did_something = true;
|
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);
|
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){
|
if (tmp_top_mod != top_mod){
|
||||||
top_mod = tmp_top_mod;
|
top_mod = tmp_top_mod;
|
||||||
top_mod->attributes[ID::initial_top] = RTLIL::Const(1);
|
top_mod->attributes[ID::initial_top] = RTLIL::Const(1);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delete_marked_modules(design);
|
||||||
// Delete modules marked as 'to_delete':
|
|
||||||
std::vector<RTLIL::Module *> 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; i<modules_to_delete.size(); i++) {
|
|
||||||
design->remove(modules_to_delete[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CellArrays {
|
||||||
|
std::map<RTLIL::Cell*, std::pair<int, int>> cells;
|
||||||
|
std::optional<std::string> 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<int, int>(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<std::string> &libdirs)
|
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs)
|
||||||
{
|
{
|
||||||
bool did_something = false;
|
bool did_something = false;
|
||||||
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
|
CellArrays cell_arrays;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
||||||
bool has_interface_ports = false;
|
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;
|
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);
|
RTLIL::Module *submod = design->module(cell->type);
|
||||||
|
if (!submod)
|
||||||
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<int, int>(idx, num);
|
|
||||||
cell->type = cell->type.substr(a->pos_type + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RTLIL::Module *mod = design->module(cell->type);
|
|
||||||
if (!mod)
|
|
||||||
{
|
{
|
||||||
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
|
// 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
|
// it. Otherwise, we either loaded or derived something so should set the
|
||||||
// did_something flag before returning (to ensure we come back and expand
|
// did_something flag before returning (to ensure we come back and expand
|
||||||
// the thing we just loaded).
|
// the thing we just loaded).
|
||||||
if (mod)
|
if (submod)
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
|
||||||
continue;
|
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
|
// Go over all connections and check if any of them are SV
|
||||||
// interfaces.
|
// interfaces.
|
||||||
if_expander.visit_connections(*cell, *mod);
|
if_expander.visit_connections(*submod);
|
||||||
|
|
||||||
if (flag_check || flag_simcheck || flag_smtcheck)
|
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 (submod->get_blackbox_attribute()) {
|
||||||
if (flag_simcheck || (flag_smtcheck && !mod->get_bool_attribute(ID::smtlib2_module)))
|
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",
|
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());
|
cell->type.c_str(), module->name.c_str(), cell->name.c_str());
|
||||||
continue;
|
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 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) {
|
if(if_expander.has_interfaces_not_found) {
|
||||||
|
// TODO special defer value instead
|
||||||
did_something = true; // waiting for interfaces to be handled
|
did_something = true; // waiting for interfaces to be handled
|
||||||
continue;
|
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
|
// If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
|
||||||
// for the cell:
|
// 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)))) {
|
!(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:",
|
// 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.
|
// 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;
|
goto handle_interface_instance;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->type = mod->derive(design,
|
cell->type = submod->derive(design,
|
||||||
cell->parameters,
|
cell->parameters,
|
||||||
if_expander.interfaces_to_add_to_submodule,
|
if_expander.interfaces_to_add_to_submodule,
|
||||||
if_expander.modports_used_in_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
|
// We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter
|
||||||
// an interface instance:
|
// 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);
|
cell->set_bool_attribute(ID::is_interface);
|
||||||
RTLIL::Module *derived_module = design->module(cell->type);
|
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;
|
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)
|
// 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 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)) {
|
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_expander.interfaces_in_module);
|
module->expand_interfaces(design, if_mod_expander.interfaces_in_module);
|
||||||
return did_something;
|
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))
|
if (module->reprocess_if_necessary(design))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (auto &it : array_cells)
|
cell_arrays.resolve();
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return did_something;
|
return did_something;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFExpander::IFExpander (RTLIL::Design &design, RTLIL::Module &m)
|
IFModExpander::IFModExpander (RTLIL::Design &design, RTLIL::Module &m) : module(m)
|
||||||
: module(m), has_interfaces_not_found(false)
|
|
||||||
{
|
{
|
||||||
// Keep track of all derived interfaces available in the current
|
// Keep track of all derived interfaces available in the current
|
||||||
// module in 'interfaces_in_module':
|
// 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
|
// 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
|
// 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.
|
// 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
|
// If there are cells that haven't yet been processed, maybe
|
||||||
// we'll find this interface in the future.
|
// 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;
|
has_interfaces_not_found = true;
|
||||||
return;
|
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
|
// about it and don't set has_interfaces_not_found (to avoid a
|
||||||
// loop).
|
// loop).
|
||||||
log_warning("Could not find interface instance for `%s' in `%s'\n",
|
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
|
// Handle an interface connection from the module
|
||||||
void IFExpander::on_interface(RTLIL::Module &submodule,
|
void IFCellExpander::on_interface(RTLIL::Module &submodule,
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals)
|
const RTLIL::SigSpec &conn_signals)
|
||||||
{
|
{
|
||||||
// Check if the connected wire is a potential interface in the parent module
|
// Check if the connected wire is a potential interface in the parent module
|
||||||
std::string interface_name_str = conn_signals[0].wire->name.str();
|
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
|
// If 'interfaces' in the cell have not be been handled yet, we aren't
|
||||||
// ready to derive the sub-module either
|
// 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);
|
on_missing_interface(interface_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -413,10 +414,10 @@ void IFExpander::on_interface(RTLIL::Module &submodule,
|
||||||
// Check if the interface instance is present in module. Interface
|
// Check if the interface instance is present in module. Interface
|
||||||
// instances may either have the plain name or the name appended with
|
// instances may either have the plain name or the name appended with
|
||||||
// '_inst_from_top_dummy'. Check for both of them here
|
// '_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";
|
std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy";
|
||||||
RTLIL::IdString interface_name2 = interface_name_str2;
|
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 we can't find either name, this is a missing interface.
|
||||||
if (! (nexactmatch || nmatch2)) {
|
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
|
if (nexactmatch != 0) // Choose the one with the plain name if it exists
|
||||||
interface_name2 = interface_name;
|
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.
|
// Go over all wires in interface, and add replacements to lists.
|
||||||
for (auto mod_wire : mod_replace_ports->wires()) {
|
for (auto mod_wire : mod_replace_ports->wires()) {
|
||||||
std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name);
|
std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name);
|
||||||
std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire);
|
std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire);
|
||||||
connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
|
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",
|
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 {
|
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_add_signal.push_back(wire_in_parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connections_to_remove.push_back(conn_name);
|
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
|
// 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
|
// 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
|
// Handle a single connection from the module, making a note to expand
|
||||||
// it if it's an interface connection.
|
// it if it's an interface connection.
|
||||||
void IFExpander::on_connection(RTLIL::Module &submodule,
|
void IFCellExpander::on_connection(RTLIL::Module &submodule,
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals)
|
const RTLIL::SigSpec &conn_signals)
|
||||||
{
|
{
|
||||||
// Does the connection look like an interface
|
// Does the connection look like an interface
|
||||||
if (
|
if (
|
||||||
|
|
@ -485,7 +486,7 @@ void IFExpander::on_connection(RTLIL::Module &submodule,
|
||||||
* parent and child).
|
* parent and child).
|
||||||
*/
|
*/
|
||||||
log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n",
|
log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n",
|
||||||
module.name,
|
cell->module->name,
|
||||||
submodule.name,
|
submodule.name,
|
||||||
conn_signals[0].wire->name.str().substr(23)
|
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
|
// Iterate over the connections in a cell, tracking any interface
|
||||||
// connections
|
// connections
|
||||||
void IFExpander::visit_connections(const RTLIL::Cell &cell,
|
void IFCellExpander::visit_connections(RTLIL::Module &submodule)
|
||||||
RTLIL::Module &submodule)
|
|
||||||
{
|
{
|
||||||
for (const auto &conn : cell.connections()) {
|
for (const auto &conn : cell->connections()) {
|
||||||
on_connection(submodule, conn.first, conn.second);
|
on_connection(submodule, conn.first, conn.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add/remove connections to the cell as necessary, replacing any SV
|
// Add/remove connections to the cell as necessary, replacing any SV
|
||||||
// interface port connection with the individual signal connections.
|
// 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;i<connections_to_add_name.size();i++) {
|
for(unsigned int i=0;i<connections_to_add_name.size();i++) {
|
||||||
cell.connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
|
cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
|
||||||
}
|
}
|
||||||
// Remove the connection for the interface itself:
|
// Remove the connection for the interface itself:
|
||||||
for(unsigned int i=0;i<connections_to_remove.size();i++) {
|
for(unsigned int i=0;i<connections_to_remove.size();i++) {
|
||||||
cell.connections_.erase(connections_to_remove[i]);
|
cell->connections_.erase(connections_to_remove[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,51 +26,45 @@
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
namespace Hierarchy {
|
namespace Hierarchy {
|
||||||
|
|
||||||
void expand_all_interfaces(Design* design, Module* top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
||||||
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
||||||
|
|
||||||
// For expanding a module's interface connections
|
// 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;
|
RTLIL::Module &module;
|
||||||
dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
|
dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
|
||||||
|
};
|
||||||
|
|
||||||
bool has_interfaces_not_found;
|
struct IFCellExpander {
|
||||||
std::vector<RTLIL::IdString> connections_to_remove;
|
IFModExpander& mod_expander;
|
||||||
std::vector<RTLIL::IdString> connections_to_add_name;
|
RTLIL::Cell* cell;
|
||||||
std::vector<RTLIL::SigSpec> connections_to_add_signal;
|
bool has_interfaces_not_found = false;
|
||||||
dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
|
std::vector<RTLIL::IdString> connections_to_remove = {};
|
||||||
dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
|
std::vector<RTLIL::IdString> connections_to_add_name = {};
|
||||||
|
std::vector<RTLIL::SigSpec> connections_to_add_signal = {};
|
||||||
// Reset the per-cell state
|
dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule = {};
|
||||||
void start_cell();
|
dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule = {};
|
||||||
|
|
||||||
// Set has_interfaces_not_found if there are pending interfaces that
|
// 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
|
// 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.
|
// warning if we've already gone over all the cells in the module.
|
||||||
void on_missing_interface(RTLIL::IdString interface_name);
|
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
|
// Handle an interface connection from the module
|
||||||
void on_interface(RTLIL::Module &submodule,
|
void on_interface(RTLIL::Module &submodule,
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals);
|
const RTLIL::SigSpec &conn_signals);
|
||||||
|
|
||||||
// Handle a single connection from the module, making a note to expand
|
// Handle a single connection from the module, making a note to expand
|
||||||
// it if it's an interface connection.
|
// it if it's an interface connection.
|
||||||
void on_connection(RTLIL::Module &submodule,
|
void on_connection(RTLIL::Module &submodule,
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals);
|
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);
|
|
||||||
|
|
||||||
// Add/remove connections to the cell as necessary, replacing any SV
|
// Add/remove connections to the cell as necessary, replacing any SV
|
||||||
// interface port connection with the individual signal connections.
|
// interface port connection with the individual signal connections.
|
||||||
void rewrite_interface_connections(RTLIL::Cell &cell) const;
|
void rewrite_interface_connections() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue