diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index a2693a6e7..d190df286 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2531,7 +2531,8 @@ public: void classp(AstClass* classp) { m_classp = classp; } }; class AstIface final : public AstNodeModule { - // A module declaration + // An interface declaration + bool m_hasVirtualRef = false; // There exists a virtual interface reference for this interface public: AstIface(FileLine* fl, const string& name, const string& libname) : ASTGEN_SUPER_Iface(fl, name, libname) {} @@ -2540,6 +2541,8 @@ public: // get false warnings if we enable this string verilogKwd() const override { return "interface"; } bool timescaleMatters() const override { return false; } + bool hasVirtualRef() const { return m_hasVirtualRef; } + void setHasVirtualRef() { m_hasVirtualRef = true; } }; class AstModule final : public AstNodeModule { // A module declaration diff --git a/src/V3Dfg.h b/src/V3Dfg.h index 0297f975d..c76cc8bf2 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -798,10 +798,16 @@ public: // Returns true if variable can be represented in the graph static bool isSupported(const AstVarScope* vscp) { - // If the variable is not in a regular module, then we do not support it. - // This is especially needed for variabels in interfaces which might be - // referenced via virtual intefaces, which cannot be resovled statically. - if (!VN_IS(vscp->scopep()->modp(), Module)) return false; + AstNodeModule* const modp = vscp->scopep()->modp(); + if (VN_IS(modp, Module)) { + // Regular module supported + } else if (AstIface* const ifacep = VN_CAST(modp, Iface)) { + // Interfaces supported if there are no virtual interfaces for + // them, otherwise they cannot be resovled statically. + if (ifacep->hasVirtualRef()) return false; + } else { + return false; // Anything else (package, class, etc) not supported + } // Check the AstVar return isSupported(vscp->varp()); } diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp index b4d0ef642..451a78841 100644 --- a/src/V3DfgOptimizer.cpp +++ b/src/V3DfgOptimizer.cpp @@ -321,6 +321,15 @@ class DataflowOptimize final { DataflowOptimize(AstNetlist* netlistp, const string& label) : m_ctx{label} { + + // Mark interfaces that might be referenced by a virtual interface + if (v3Global.hasVirtIfaces()) { + netlistp->typeTablep()->foreach([](AstIfaceRefDType* nodep) { + if (!nodep->isVirtual()) return; + nodep->ifaceViaCellp()->setHasVirtualRef(); + }); + } + if (!netlistp->topScopep()) { // Pre V3Scope application. Run on each module separately. diff --git a/test_regress/t/t_interface_gen7.v b/test_regress/t/t_interface_gen7.v index 1bf047801..5ffb79c37 100644 --- a/test_regress/t/t_interface_gen7.v +++ b/test_regress/t/t_interface_gen7.v @@ -9,7 +9,9 @@ interface intf #(parameter PARAM = 0) (); + /* verilator lint_off MULTIDRIVEN */ logic val; + /* verilator lint_on MULTIDRIVEN */ function integer func (); return 5; endfunction endinterface