refactor(interface): share port resolution paths
This commit is contained in:
parent
39072cd452
commit
2228e31a6a
47
Module.cc
47
Module.cc
|
|
@ -21,8 +21,11 @@
|
||||||
|
|
||||||
# include "Module.h"
|
# include "Module.h"
|
||||||
# include "PGate.h"
|
# include "PGate.h"
|
||||||
|
# include "PModport.h"
|
||||||
# include "PWire.h"
|
# include "PWire.h"
|
||||||
|
# include "parse_api.h"
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
# include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
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<perm_string,Module*>::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<perm_string,PModport*>::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. */
|
/* n is a permallocated string. */
|
||||||
Module::Module(LexicalScope*parent, perm_string n)
|
Module::Module(LexicalScope*parent, perm_string n)
|
||||||
: PScopeExtra(n, parent)
|
: PScopeExtra(n, parent)
|
||||||
|
|
|
||||||
13
Module.h
13
Module.h
|
|
@ -43,6 +43,7 @@ class PFunction;
|
||||||
class PWire;
|
class PWire;
|
||||||
class PProcess;
|
class PProcess;
|
||||||
class Design;
|
class Design;
|
||||||
|
class LineInfo;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -197,4 +198,16 @@ class Module : public PScopeExtra, public PNamedItem {
|
||||||
Module& operator= (const Module&);
|
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 */
|
#endif /* IVL_Module_H */
|
||||||
|
|
|
||||||
20
elab_sig.cc
20
elab_sig.cc
|
|
@ -300,24 +300,8 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pp->is_interface_port()) {
|
if (pp->is_interface_port()) {
|
||||||
map<perm_string,Module*>::const_iterator mod =
|
interface_formal_port_t formal;
|
||||||
pform_modules.find(pp->interface_type);
|
resolve_interface_formal_port(this, des, pp, formal, true);
|
||||||
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;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
97
elaborate.cc
97
elaborate.cc
|
|
@ -1325,6 +1325,48 @@ bool PGModule::match_module_ports_(Design*des, const Module*rmod,
|
||||||
return true;
|
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<const PEIdent*>(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,
|
bool PGModule::bind_interface_ports_(Design*des, const Module*rmod,
|
||||||
NetScope*parent_scope,
|
NetScope*parent_scope,
|
||||||
NetScope*instance_scope,
|
NetScope*instance_scope,
|
||||||
|
|
@ -1347,10 +1389,8 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PEIdent*actual_ident = dynamic_cast<const PEIdent*>(pins[idx]);
|
interface_actual_scope_t actual;
|
||||||
if (!actual_ident || actual_ident->path().package ||
|
if (!resolve_interface_actual_scope(pins[idx], parent_scope, des, actual)) {
|
||||||
actual_ident->path().name.size() != 1 ||
|
|
||||||
!actual_ident->path().name.front().index.empty()) {
|
|
||||||
cerr << pins[idx]->get_fileline() << ": error: Interface port `"
|
cerr << pins[idx]->get_fileline() << ": error: Interface port `"
|
||||||
<< port->name << "' must be connected to a simple "
|
<< port->name << "' must be connected to a simple "
|
||||||
"interface instance name." << endl;
|
"interface instance name." << endl;
|
||||||
|
|
@ -1359,19 +1399,7 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
perm_string actual_name = actual_ident->path().name.front().name;
|
if (!actual.scope || !actual.scope->is_interface()) {
|
||||||
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()) {
|
|
||||||
cerr << pins[idx]->get_fileline() << ": error: Actual for "
|
cerr << pins[idx]->get_fileline() << ": error: Actual for "
|
||||||
"interface port `" << port->name
|
"interface port `" << port->name
|
||||||
<< "' is not an interface instance." << endl;
|
<< "' is not an interface instance." << endl;
|
||||||
|
|
@ -1380,40 +1408,35 @@ bool PGModule::bind_interface_ports_(Design*des, const Module*rmod,
|
||||||
continue;
|
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 `"
|
cerr << pins[idx]->get_fileline() << ": error: Interface port `"
|
||||||
<< port->name << "' expects interface type `"
|
<< port->name << "' expects interface type `"
|
||||||
<< port->interface_type << "' but actual `" << actual_name
|
<< port->interface_type << "' but actual `" << actual.display_name
|
||||||
<< "' has type `" << actual_scope->module_name() << "'." << endl;
|
<< "' has type `" << actual.scope->module_name() << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
flag = false;
|
flag = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<perm_string,Module*>::const_iterator mod =
|
if (actual.modport && formal.modport &&
|
||||||
pform_modules.find(port->interface_type);
|
actual.modport->name() != formal.modport->name()) {
|
||||||
const PModport*formal_modport = 0;
|
|
||||||
if (port->modport_name.str() && mod != pform_modules.end()) {
|
|
||||||
map<perm_string,PModport*>::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()) {
|
|
||||||
cerr << pins[idx]->get_fileline() << ": error: Interface port `"
|
cerr << pins[idx]->get_fileline() << ": error: Interface port `"
|
||||||
<< port->name << "' cannot forward actual `" << actual_name
|
<< port->name << "' cannot forward actual `" << actual.display_name
|
||||||
<< "' restricted by modport `" << actual_modport->name()
|
<< "' restricted by modport `" << actual.modport->name()
|
||||||
<< "' to formal modport `" << formal_modport->name()
|
<< "' to formal modport `" << formal.modport->name()
|
||||||
<< "'." << endl;
|
<< "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
flag = false;
|
flag = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PModport*modport = formal_modport? formal_modport : actual_modport;
|
const PModport*modport = formal.modport? formal.modport : actual.modport;
|
||||||
instance_scope->add_interface_port_alias(port->name, actual_scope,
|
instance_scope->add_interface_port_alias(port->name, actual.scope,
|
||||||
modport);
|
modport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
net_scope.cc
12
net_scope.cc
|
|
@ -831,18 +831,6 @@ NetScope::find_interface_port_alias(perm_string formal_name) const
|
||||||
return &cur->second;
|
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
|
/* Helper function to see if the given scope is defined in a class and if
|
||||||
* so return the class scope. */
|
* so return the class scope. */
|
||||||
const NetScope* NetScope::get_class_scope() const
|
const NetScope* NetScope::get_class_scope() const
|
||||||
|
|
|
||||||
|
|
@ -1061,8 +1061,6 @@ class NetScope : public Definitions, public Attrib {
|
||||||
NetScope*actual_scope,
|
NetScope*actual_scope,
|
||||||
const PModport*modport);
|
const PModport*modport);
|
||||||
const interface_port_alias_t* find_interface_port_alias(perm_string formal_name) const;
|
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. */
|
/* A helper function to find the enclosing class scope. */
|
||||||
const NetScope* get_class_scope() const;
|
const NetScope* get_class_scope() const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue