From 2228e31a6a742ad6f3a89c7b263535437aedafcc Mon Sep 17 00:00:00 2001 From: Jose Tejada Date: Sun, 10 May 2026 17:08:35 +0200 Subject: [PATCH] refactor(interface): share port resolution paths --- Module.cc | 47 +++++++++++++++++++++++++ Module.h | 13 +++++++ elab_sig.cc | 20 ++--------- elaborate.cc | 97 ++++++++++++++++++++++++++++++++-------------------- net_scope.cc | 12 ------- netlist.h | 2 -- 6 files changed, 122 insertions(+), 69 deletions(-) diff --git a/Module.cc b/Module.cc index 5babfb973..212fe87ad 100644 --- a/Module.cc +++ b/Module.cc @@ -21,8 +21,11 @@ # include "Module.h" # include "PGate.h" +# include "PModport.h" # include "PWire.h" +# include "parse_api.h" # include "ivl_assert.h" +# include using namespace std; @@ -33,6 +36,50 @@ Module::port_t::port_t() { } +bool resolve_interface_formal_port(const LineInfo*li, Design*des, + const Module::port_t*port, + interface_formal_port_t&res, + bool emit_errors) +{ + ivl_assert(*li, port); + ivl_assert(*li, port->is_interface_port()); + + res = interface_formal_port_t(); + + map::const_iterator mod = + pform_modules.find(port->interface_type); + if (mod == pform_modules.end() || !mod->second->is_interface) { + if (emit_errors) { + cerr << li->get_fileline() << ": error: Interface port " + << port->name << " uses unknown interface type `" + << port->interface_type << "'." << endl; + des->errors += 1; + } + return false; + } + + res.module = mod->second; + + if (port->modport_name.str()) { + map::const_iterator mp = + mod->second->modports.find(port->modport_name); + if (mp == mod->second->modports.end()) { + if (emit_errors) { + cerr << li->get_fileline() << ": error: Interface port " + << port->name << " uses unknown modport `" + << port->modport_name << "' of interface `" + << port->interface_type << "'." << endl; + des->errors += 1; + } + return false; + } + + res.modport = mp->second; + } + + return true; +} + /* n is a permallocated string. */ Module::Module(LexicalScope*parent, perm_string n) : PScopeExtra(n, parent) diff --git a/Module.h b/Module.h index 2713be544..ac9f3da5d 100644 --- a/Module.h +++ b/Module.h @@ -43,6 +43,7 @@ class PFunction; class PWire; class PProcess; class Design; +class LineInfo; class NetScope; /* @@ -197,4 +198,16 @@ class Module : public PScopeExtra, public PNamedItem { Module& operator= (const Module&); }; +struct interface_formal_port_t { + interface_formal_port_t() : module(0), modport(0) { } + + const Module*module; + const PModport*modport; +}; + +extern bool resolve_interface_formal_port(const LineInfo*li, Design*des, + const Module::port_t*port, + interface_formal_port_t&res, + bool emit_errors); + #endif /* IVL_Module_H */ diff --git a/elab_sig.cc b/elab_sig.cc index d0b202ae0..1526e1426 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -300,24 +300,8 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const continue; if (pp->is_interface_port()) { - map::const_iterator mod = - pform_modules.find(pp->interface_type); - if (mod == pform_modules.end() || !mod->second->is_interface) { - cerr << get_fileline() << ": error: Interface port " - << pp->name << " uses unknown interface type `" - << pp->interface_type << "'." << endl; - des->errors += 1; - continue; - } - - if (pp->modport_name.str() && - mod->second->modports.find(pp->modport_name) == mod->second->modports.end()) { - cerr << get_fileline() << ": error: Interface port " - << pp->name << " uses unknown modport `" - << pp->modport_name << "' of interface `" - << pp->interface_type << "'." << endl; - des->errors += 1; - } + interface_formal_port_t formal; + resolve_interface_formal_port(this, des, pp, formal, true); continue; } diff --git a/elaborate.cc b/elaborate.cc index bd6354164..e8de36fc3 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1325,6 +1325,48 @@ bool PGModule::match_module_ports_(Design*des, const Module*rmod, return true; } +struct interface_actual_scope_t { + interface_actual_scope_t() : scope(0), modport(0) { } + + NetScope*scope; + const PModport*modport; + perm_string display_name; +}; + +static bool resolve_interface_actual_scope(const PExpr*actual, + NetScope*parent_scope, + Design*des, + interface_actual_scope_t&res) +{ + res = interface_actual_scope_t(); + + const PEIdent*actual_ident = dynamic_cast(actual); + if (!actual_ident || actual_ident->path().package || + actual_ident->path().name.size() != 1 || + !actual_ident->path().name.front().index.empty()) { + return false; + } + + res.display_name = actual_ident->path().name.front().name; + + symbol_search_results sr; + symbol_search(actual, des, parent_scope, actual_ident->path(), + actual_ident->lexical_pos(), &sr); + + res.scope = sr.scope; + if (sr.through_interface_alias()) + res.modport = sr.interface_alias_modport; + else if (NetScope*child = parent_scope->child(hname_t(res.display_name))) + res.scope = child; + else if (const NetScope::interface_port_alias_t*alias = + parent_scope->find_interface_port_alias(res.display_name)) { + res.scope = alias->actual_scope; + res.modport = alias->modport; + } + + return true; +} + bool PGModule::bind_interface_ports_(Design*des, const Module*rmod, NetScope*parent_scope, NetScope*instance_scope, @@ -1347,10 +1389,8 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod, continue; } - const PEIdent*actual_ident = dynamic_cast(pins[idx]); - if (!actual_ident || actual_ident->path().package || - actual_ident->path().name.size() != 1 || - !actual_ident->path().name.front().index.empty()) { + interface_actual_scope_t actual; + if (!resolve_interface_actual_scope(pins[idx], parent_scope, des, actual)) { cerr << pins[idx]->get_fileline() << ": error: Interface port `" << port->name << "' must be connected to a simple " "interface instance name." << endl; @@ -1359,19 +1399,7 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod, continue; } - perm_string actual_name = actual_ident->path().name.front().name; - NetScope*actual_scope = parent_scope->child(hname_t(actual_name)); - const PModport*actual_modport = 0; - if (!actual_scope) { - const NetScope::interface_port_alias_t*actual_alias = - parent_scope->find_interface_port_alias(actual_name); - if (actual_alias) { - actual_scope = actual_alias->actual_scope; - actual_modport = actual_alias->modport; - } - } - - if (!actual_scope || !actual_scope->is_interface()) { + if (!actual.scope || !actual.scope->is_interface()) { cerr << pins[idx]->get_fileline() << ": error: Actual for " "interface port `" << port->name << "' is not an interface instance." << endl; @@ -1380,40 +1408,35 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod, continue; } - if (actual_scope->module_name() != port->interface_type) { + interface_formal_port_t formal; + resolve_interface_formal_port(pins[idx], des, port, formal, false); + if (!formal.module) + continue; + + if (actual.scope->module_name() != formal.module->mod_name()) { cerr << pins[idx]->get_fileline() << ": error: Interface port `" << port->name << "' expects interface type `" - << port->interface_type << "' but actual `" << actual_name - << "' has type `" << actual_scope->module_name() << "'." << endl; + << port->interface_type << "' but actual `" << actual.display_name + << "' has type `" << actual.scope->module_name() << "'." << endl; des->errors += 1; flag = false; continue; } - map::const_iterator mod = - pform_modules.find(port->interface_type); - const PModport*formal_modport = 0; - if (port->modport_name.str() && mod != pform_modules.end()) { - map::const_iterator mp = - mod->second->modports.find(port->modport_name); - if (mp != mod->second->modports.end()) - formal_modport = mp->second; - } - - if (actual_modport && formal_modport && - actual_modport->name() != formal_modport->name()) { + if (actual.modport && formal.modport && + actual.modport->name() != formal.modport->name()) { cerr << pins[idx]->get_fileline() << ": error: Interface port `" - << port->name << "' cannot forward actual `" << actual_name - << "' restricted by modport `" << actual_modport->name() - << "' to formal modport `" << formal_modport->name() + << port->name << "' cannot forward actual `" << actual.display_name + << "' restricted by modport `" << actual.modport->name() + << "' to formal modport `" << formal.modport->name() << "'." << endl; des->errors += 1; flag = false; continue; } - const PModport*modport = formal_modport? formal_modport : actual_modport; - instance_scope->add_interface_port_alias(port->name, actual_scope, + const PModport*modport = formal.modport? formal.modport : actual.modport; + instance_scope->add_interface_port_alias(port->name, actual.scope, modport); } diff --git a/net_scope.cc b/net_scope.cc index 6292817a2..0719bcc6c 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -831,18 +831,6 @@ NetScope::find_interface_port_alias(perm_string formal_name) const return &cur->second; } -NetScope* NetScope::find_interface_port_alias_scope(perm_string formal_name) const -{ - const interface_port_alias_t*cur = find_interface_port_alias(formal_name); - return cur? cur->actual_scope : 0; -} - -const PModport* NetScope::find_interface_port_modport(perm_string formal_name) const -{ - const interface_port_alias_t*cur = find_interface_port_alias(formal_name); - return cur? cur->modport : 0; -} - /* Helper function to see if the given scope is defined in a class and if * so return the class scope. */ const NetScope* NetScope::get_class_scope() const diff --git a/netlist.h b/netlist.h index 7011c5a9f..4b465fd13 100644 --- a/netlist.h +++ b/netlist.h @@ -1061,8 +1061,6 @@ class NetScope : public Definitions, public Attrib { NetScope*actual_scope, const PModport*modport); const interface_port_alias_t* find_interface_port_alias(perm_string formal_name) const; - NetScope* find_interface_port_alias_scope(perm_string formal_name) const; - const PModport* find_interface_port_modport(perm_string formal_name) const; /* A helper function to find the enclosing class scope. */ const NetScope* get_class_scope() const;