From a841a962ceb816b6775d298256d17f1558f53835 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Tue, 26 Aug 2025 11:24:15 +0100 Subject: [PATCH] Optimize interfaces in Dfg (#6332) Interfaces that have no corresponding virtual interface references can be safely optimized by Dfg after V3Scope. Enabling it to do so. --- src/V3AstNodeOther.h | 5 ++++- src/V3Dfg.h | 14 ++++++++++---- src/V3DfgOptimizer.cpp | 9 +++++++++ test_regress/t/t_interface_gen7.v | 2 ++ 4 files changed, 25 insertions(+), 5 deletions(-) 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