diff --git a/Changes b/Changes index 61efdc8cd..19fd02a32 100644 --- a/Changes +++ b/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. diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a51d109fe..eb80833a2 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -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 NameScopeSymMap; typedef map 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 aliases + ScopeAliasMap m_scopeAliasMap[SAMN__MAX]; // Map of 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 "<first<<" -> "<second<first<<" ("<first->nodep()->typeName() + <<") <- "<second<<" "<second->nodep()<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<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; samnfirst; + 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"<nodep()->typeName() + <<") <- se"<nodep()<importFromIface(symsp(), srcp); } - UINFO(9," iiasa: Insert alias se"<nodep()<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: "<prettyName()); } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 51402abba..50a2fe52c 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -188,11 +188,11 @@ public: UINFO(9, " importIf se"<<(void*)this<<" from se"<<(void*)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="") { diff --git a/test_regress/t/t_interface_mp_func.pl b/test_regress/t/t_interface_mp_func.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_interface_mp_func.pl @@ -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; diff --git a/test_regress/t/t_interface_mp_func.v b/test_regress/t/t_interface_mp_func.v new file mode 100644 index 000000000..35fc69536 --- /dev/null +++ b/test_regress/t/t_interface_mp_func.v @@ -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