forked from github/verilator
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 modport function import not-found error.
|
||||
|
||||
**** Fix Mac OS-X test issues. [Holger Waechtler]
|
||||
|
||||
**** Fix C++-2011 warnings.
|
||||
|
@ -96,6 +96,12 @@ private:
|
||||
AstUser2InUse m_inuser2;
|
||||
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
|
||||
typedef multimap<string,VSymEnt*> NameScopeSymMap;
|
||||
typedef map<VSymEnt*,VSymEnt*> ScopeAliasMap;
|
||||
@ -110,7 +116,7 @@ private:
|
||||
VSymEnt* m_dunitEntp; // $unit entry
|
||||
NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name
|
||||
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
|
||||
IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed
|
||||
bool m_forPrimary; // First link
|
||||
@ -131,9 +137,18 @@ public:
|
||||
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
ostream& os = *logp;
|
||||
m_syms.dump(os);
|
||||
if (!m_scopeAliasMap.empty()) os<<"\nScopeAliasMap:\n";
|
||||
for (ScopeAliasMap::iterator it = m_scopeAliasMap.begin(); it != m_scopeAliasMap.end(); ++it) {
|
||||
os<<"\t"<<it->first<<" -> "<<it->second<<endl;
|
||||
bool first = true;
|
||||
for (int samn=0; samn<SAMN__MAX; ++samn) {
|
||||
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()));
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Track and later insert scope aliases
|
||||
void insertScopeAlias(VSymEnt* lhsp, VSymEnt* rhsp) { // Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell
|
||||
void insertScopeAlias(SAMNum samn, VSymEnt* lhsp, VSymEnt* rhsp) {
|
||||
// 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);
|
||||
m_scopeAliasMap.insert(make_pair(lhsp, rhsp));
|
||||
m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp));
|
||||
}
|
||||
void computeScopeAliases() {
|
||||
UINFO(9,"computeIfaceAliases\n");
|
||||
for (ScopeAliasMap::iterator it=m_scopeAliasMap.begin(); it!=m_scopeAliasMap.end(); ++it) {
|
||||
VSymEnt* lhsp = it->first;
|
||||
VSymEnt* srcp = lhsp;
|
||||
while (1) { // Follow chain of aliases up to highest level non-alias
|
||||
ScopeAliasMap::iterator it2 = m_scopeAliasMap.find(srcp);
|
||||
if (it2 != m_scopeAliasMap.end()) { srcp = it2->second; continue; }
|
||||
else break;
|
||||
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* srcp = lhsp;
|
||||
while (1) { // Follow chain of aliases up to highest level non-alias
|
||||
ScopeAliasMap::iterator it2 = m_scopeAliasMap[samn].find(srcp);
|
||||
if (it2 != m_scopeAliasMap[samn].end()) { srcp = it2->second; continue; }
|
||||
else break;
|
||||
}
|
||||
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
|
||||
lhsp->importFromIface(symsp(), srcp);
|
||||
}
|
||||
UINFO(9," iiasa: Insert alias se"<<lhsp<<" <- se"<<srcp<<" "<<srcp->nodep()<<endl);
|
||||
// srcp should be an interface reference pointing to the interface we want to import
|
||||
lhsp->importFromIface(symsp(), srcp);
|
||||
//m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file
|
||||
}
|
||||
m_scopeAliasMap.clear();
|
||||
}
|
||||
private:
|
||||
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
|
||||
// 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,
|
||||
// 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
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
@ -1212,7 +1232,8 @@ class LinkDotIfaceVisitor : public AstNVisitor {
|
||||
} else if (AstNodeFTask* ftaskp = symp->nodep()->castNodeFTask()) {
|
||||
// Make symbol under modport that points at the _interface_'s var, not the modport.
|
||||
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 {
|
||||
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);
|
||||
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
|
||||
const string& name = it->first;
|
||||
VSymEnt* srcp = it->second;
|
||||
VSymEnt* symp = new VSymEnt(graphp, srcp);
|
||||
reinsert(name, symp);
|
||||
VSymEnt* subSrcp = it->second;
|
||||
VSymEnt* subSymp = new VSymEnt(graphp, subSrcp);
|
||||
reinsert(name, subSymp);
|
||||
// And recurse to create children
|
||||
srcp->importFromIface(graphp, symp);
|
||||
subSymp->importFromIface(graphp, subSrcp);
|
||||
}
|
||||
}
|
||||
void cellErrorScopes(AstNode* lookp, string prettyName="") {
|
||||
|
18
test_regress/t/t_interface_mp_func.pl
Executable file
18
test_regress/t/t_interface_mp_func.pl
Executable file
@ -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;
|
28
test_regress/t/t_interface_mp_func.v
Normal file
28
test_regress/t/t_interface_mp_func.v
Normal file
@ -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
Block a user