Fix modport function import not-found error.
This commit is contained in:
parent
28e35a64ea
commit
6cf6d9f7e1
2
Changes
2
Changes
|
|
@ -23,6 +23,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
**** Fix missing coverage line on else-if, bug727. [Sharad Bagri]
|
**** Fix missing coverage line on else-if, bug727. [Sharad Bagri]
|
||||||
|
|
||||||
|
**** Fix modport function import not-found error.
|
||||||
|
|
||||||
**** Fix Mac OS-X test issues. [Holger Waechtler]
|
**** Fix Mac OS-X test issues. [Holger Waechtler]
|
||||||
|
|
||||||
**** Fix C++-2011 warnings.
|
**** Fix C++-2011 warnings.
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,12 @@ private:
|
||||||
AstUser2InUse m_inuser2;
|
AstUser2InUse m_inuser2;
|
||||||
AstUser4InUse m_inuser4;
|
AstUser4InUse m_inuser4;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// ENUMS
|
||||||
|
// In order of priority, compute first ... compute last
|
||||||
|
enum SAMNum { SAMN_MODPORT, SAMN_IFTOP, SAMN__MAX }; // Values for m_scopeAliasMap
|
||||||
|
|
||||||
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef multimap<string,VSymEnt*> NameScopeSymMap;
|
typedef multimap<string,VSymEnt*> NameScopeSymMap;
|
||||||
typedef map<VSymEnt*,VSymEnt*> ScopeAliasMap;
|
typedef map<VSymEnt*,VSymEnt*> ScopeAliasMap;
|
||||||
|
|
@ -110,7 +116,7 @@ private:
|
||||||
VSymEnt* m_dunitEntp; // $unit entry
|
VSymEnt* m_dunitEntp; // $unit entry
|
||||||
NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name
|
NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name
|
||||||
ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it
|
ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it
|
||||||
ScopeAliasMap m_scopeAliasMap; // Map of <lhs,rhs> aliases
|
ScopeAliasMap m_scopeAliasMap[SAMN__MAX]; // Map of <lhs,rhs> aliases
|
||||||
IfaceVarSyms m_ifaceVarSyms; // List of AstIfaceRefDType's to be imported
|
IfaceVarSyms m_ifaceVarSyms; // List of AstIfaceRefDType's to be imported
|
||||||
IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed
|
IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed
|
||||||
bool m_forPrimary; // First link
|
bool m_forPrimary; // First link
|
||||||
|
|
@ -131,9 +137,18 @@ public:
|
||||||
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||||
ostream& os = *logp;
|
ostream& os = *logp;
|
||||||
m_syms.dump(os);
|
m_syms.dump(os);
|
||||||
if (!m_scopeAliasMap.empty()) os<<"\nScopeAliasMap:\n";
|
bool first = true;
|
||||||
for (ScopeAliasMap::iterator it = m_scopeAliasMap.begin(); it != m_scopeAliasMap.end(); ++it) {
|
for (int samn=0; samn<SAMN__MAX; ++samn) {
|
||||||
os<<"\t"<<it->first<<" -> "<<it->second<<endl;
|
if (!m_scopeAliasMap[samn].empty()) {
|
||||||
|
if (first) os<<"\nScopeAliasMap:\n";
|
||||||
|
first = false;
|
||||||
|
for (ScopeAliasMap::iterator it = m_scopeAliasMap[samn].begin();
|
||||||
|
it != m_scopeAliasMap[samn].end(); ++it) {
|
||||||
|
// left side is what we will import into
|
||||||
|
os<<"\t"<<samn<<"\t"<<it->first<<" ("<<it->first->nodep()->typeName()
|
||||||
|
<<") <- "<<it->second<<" "<<it->second->nodep()<<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -382,31 +397,36 @@ public:
|
||||||
<<"': "<<ifacerefp->prettyName(ifacerefp->modportName()));
|
<<"': "<<ifacerefp->prettyName(ifacerefp->modportName()));
|
||||||
}
|
}
|
||||||
// Alias won't expand until interfaces and modport names are known; see notes at top
|
// Alias won't expand until interfaces and modport names are known; see notes at top
|
||||||
insertScopeAlias(varSymp, ifOrPortSymp);
|
insertScopeAlias(SAMN_IFTOP, varSymp, ifOrPortSymp);
|
||||||
}
|
}
|
||||||
m_ifaceVarSyms.clear();
|
m_ifaceVarSyms.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track and later insert scope aliases
|
void insertScopeAlias(SAMNum samn, VSymEnt* lhsp, VSymEnt* rhsp) {
|
||||||
void insertScopeAlias(VSymEnt* lhsp, VSymEnt* rhsp) { // Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell
|
// Track and later insert scope aliases; an interface referenced by a child cell connecting to that interface
|
||||||
|
// Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell
|
||||||
UINFO(9," insertScopeAlias se"<<(void*)lhsp<<" se"<<(void*)rhsp<<endl);
|
UINFO(9," insertScopeAlias se"<<(void*)lhsp<<" se"<<(void*)rhsp<<endl);
|
||||||
m_scopeAliasMap.insert(make_pair(lhsp, rhsp));
|
m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp));
|
||||||
}
|
}
|
||||||
void computeScopeAliases() {
|
void computeScopeAliases() {
|
||||||
UINFO(9,"computeIfaceAliases\n");
|
UINFO(9,"computeIfaceAliases\n");
|
||||||
for (ScopeAliasMap::iterator it=m_scopeAliasMap.begin(); it!=m_scopeAliasMap.end(); ++it) {
|
for (int samn=0; samn<SAMN__MAX; ++samn) {
|
||||||
|
for (ScopeAliasMap::iterator it=m_scopeAliasMap[samn].begin();
|
||||||
|
it!=m_scopeAliasMap[samn].end(); ++it) {
|
||||||
VSymEnt* lhsp = it->first;
|
VSymEnt* lhsp = it->first;
|
||||||
VSymEnt* srcp = lhsp;
|
VSymEnt* srcp = lhsp;
|
||||||
while (1) { // Follow chain of aliases up to highest level non-alias
|
while (1) { // Follow chain of aliases up to highest level non-alias
|
||||||
ScopeAliasMap::iterator it2 = m_scopeAliasMap.find(srcp);
|
ScopeAliasMap::iterator it2 = m_scopeAliasMap[samn].find(srcp);
|
||||||
if (it2 != m_scopeAliasMap.end()) { srcp = it2->second; continue; }
|
if (it2 != m_scopeAliasMap[samn].end()) { srcp = it2->second; continue; }
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
UINFO(9," iiasa: Insert alias se"<<lhsp<<" <- se"<<srcp<<" "<<srcp->nodep()<<endl);
|
UINFO(9," iiasa: Insert alias se"<<lhsp<<" ("<<lhsp->nodep()->typeName()
|
||||||
|
<<") <- se"<<srcp<<" "<<srcp->nodep()<<endl);
|
||||||
// srcp should be an interface reference pointing to the interface we want to import
|
// srcp should be an interface reference pointing to the interface we want to import
|
||||||
lhsp->importFromIface(symsp(), srcp);
|
lhsp->importFromIface(symsp(), srcp);
|
||||||
}
|
}
|
||||||
m_scopeAliasMap.clear();
|
//m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
VSymEnt* findWithAltFallback(VSymEnt* symp, const string& name, const string& altname) {
|
VSymEnt* findWithAltFallback(VSymEnt* symp, const string& name, const string& altname) {
|
||||||
|
|
@ -1105,7 +1125,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
||||||
}
|
}
|
||||||
// Interface reference; need to put whole thing into symtable, but can't clone it now
|
// Interface reference; need to put whole thing into symtable, but can't clone it now
|
||||||
// as we may have a later alias for it.
|
// as we may have a later alias for it.
|
||||||
m_statep->insertScopeAlias(varSymp, cellSymp);
|
m_statep->insertScopeAlias(LinkDotState::SAMN_IFTOP, varSymp, cellSymp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1151,7 +1171,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
||||||
}
|
}
|
||||||
// Remember the alias - can't do it yet because we may have additional symbols to be added,
|
// Remember the alias - can't do it yet because we may have additional symbols to be added,
|
||||||
// or maybe an alias of an alias
|
// or maybe an alias of an alias
|
||||||
m_statep->insertScopeAlias(lhsSymp, rhsSymp);
|
m_statep->insertScopeAlias(LinkDotState::SAMN_IFTOP, lhsSymp, rhsSymp);
|
||||||
// We have stored the link, we don't need these any more
|
// We have stored the link, we don't need these any more
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1212,7 +1232,8 @@ class LinkDotIfaceVisitor : public AstNVisitor {
|
||||||
} else if (AstNodeFTask* ftaskp = symp->nodep()->castNodeFTask()) {
|
} else if (AstNodeFTask* ftaskp = symp->nodep()->castNodeFTask()) {
|
||||||
// Make symbol under modport that points at the _interface_'s var, not the modport.
|
// Make symbol under modport that points at the _interface_'s var, not the modport.
|
||||||
nodep->ftaskp(ftaskp);
|
nodep->ftaskp(ftaskp);
|
||||||
m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, NULL/*package*/);
|
VSymEnt* subSymp = m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, NULL/*package*/);
|
||||||
|
m_statep->insertScopeAlias(LinkDotState::SAMN_MODPORT, subSymp, symp);
|
||||||
} else {
|
} else {
|
||||||
nodep->v3error("Modport item is not a function/task: "<<nodep->prettyName());
|
nodep->v3error("Modport item is not a function/task: "<<nodep->prettyName());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,11 +188,11 @@ public:
|
||||||
UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)srcp<<endl);
|
UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)srcp<<endl);
|
||||||
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
|
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
|
||||||
const string& name = it->first;
|
const string& name = it->first;
|
||||||
VSymEnt* srcp = it->second;
|
VSymEnt* subSrcp = it->second;
|
||||||
VSymEnt* symp = new VSymEnt(graphp, srcp);
|
VSymEnt* subSymp = new VSymEnt(graphp, subSrcp);
|
||||||
reinsert(name, symp);
|
reinsert(name, subSymp);
|
||||||
// And recurse to create children
|
// And recurse to create children
|
||||||
srcp->importFromIface(graphp, symp);
|
subSymp->importFromIface(graphp, subSrcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||||
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
interface pads_if();
|
||||||
|
modport mp_dig(
|
||||||
|
import fIn,
|
||||||
|
import fOut );
|
||||||
|
|
||||||
|
integer exists[8];
|
||||||
|
function automatic integer fIn (integer i);
|
||||||
|
fIn = exists[i];
|
||||||
|
endfunction
|
||||||
|
task automatic fOut (integer i);
|
||||||
|
exists[i] = 33;
|
||||||
|
endtask
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module t();
|
||||||
|
pads_if padsif();
|
||||||
|
initial begin
|
||||||
|
padsif.fOut(3);
|
||||||
|
if (padsif.fIn(3) != 33) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue