From 2ccaae77aea679eed5c139c6b1533ac8680b50c0 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 30 May 2026 15:23:02 -0400 Subject: [PATCH] Fix CONTASSINIT false positive on wire inside two different instantiations Fixes #7640. --- Changes | 2 +- src/V3Undriven.cpp | 5 ++++- test_regress/t/t_lint_contassinit_bad.out | 8 ++++---- test_regress/t/t_lint_contassinit_bad.v | 10 ++++++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 793d8b838..0a9355f04 100644 --- a/Changes +++ b/Changes @@ -788,7 +788,7 @@ Verilator 5.038 2025-07-08 * Support non-overlapping blocking/non-blocking assignments (#6137). [Geza Lore] * Support parameter forward types. * Support constant functions with left-hand-side concatenates. -* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon] +* Add PROCINITASSIGN on initial assignments to process variables (#2481) (#7640). [Niraj Menon] * Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu] * Add ternary operator into branch coverage (#5880). [Ryszard Rozak, Antmicro Ltd.] * Add aggregate type error checks (#5570) (#5950). [Shou-Li Hsu] diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index d4a2a1fd5..51187098f 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -594,7 +594,10 @@ class UndrivenVisitor final : public VNVisitorConst { if (m_alwaysCombp) entryp->drivenAlwaysCombWhole(m_alwaysCombp); if (m_alwaysFFp) entryp->drivenAlwaysFFWhole(m_alwaysFFp, nodep->varp()); } - if (nodep->access().isWriteOrRW()) { + if (nodep->access().isWriteOrRW() && !VN_IS(nodep, VarXRef)) { + // Ignoring xrefs as the initial and assignment to track might refer to two + // different instances. Ideally all of V3Undriven would move after V3Scope, + // then could use VarScope tracking instead. if (m_inInitialStatic && !entryp->initStaticp()) entryp->initStaticp(nodep); if (m_inInitial && !entryp->initialp()) entryp->initialp(nodep); if (m_inContAssign && !entryp->contAssignp()) entryp->contAssignp(nodep); diff --git a/test_regress/t/t_lint_contassinit_bad.out b/test_regress/t/t_lint_contassinit_bad.out index 5e2246144..8130affde 100644 --- a/test_regress/t/t_lint_contassinit_bad.out +++ b/test_regress/t/t_lint_contassinit_bad.out @@ -1,10 +1,10 @@ -%Error-CONTASSINIT: t/t_lint_contassinit_bad.v:11:13: Continuous assignment to variable with initial value: 'a' +%Error-CONTASSINIT: t/t_lint_contassinit_bad.v:15:13: Continuous assignment to variable with initial value: 'a' : ... note: In instance 't' : ... Location of variable initialization - 11 | logic a = 1'b0; + 15 | logic a = 1'b0; | ^~~~ - t/t_lint_contassinit_bad.v:12:10: ... Location of continuous assignment - 12 | assign a = 1'b1; + t/t_lint_contassinit_bad.v:16:10: ... Location of continuous assignment + 16 | assign a = 1'b1; | ^ ... For error description see https://verilator.org/warn/CONTASSINIT?v=latest %Error: Exiting due to diff --git a/test_regress/t/t_lint_contassinit_bad.v b/test_regress/t/t_lint_contassinit_bad.v index 5471ae43b..736a9b4ee 100644 --- a/test_regress/t/t_lint_contassinit_bad.v +++ b/test_regress/t/t_lint_contassinit_bad.v @@ -4,6 +4,10 @@ // SPDX-FileCopyrightText: 2026 Zhi QU // SPDX-License-Identifier: CC0-1.0 +interface decoupled_ifc; + logic ready; +endinterface + module t ( output wire out ); @@ -13,4 +17,10 @@ module t ( assign out = a; + // OK as two different instances + decoupled_ifc ifc_in (); + decoupled_ifc ifc_out (); + initial ifc_out.ready = 0; + assign ifc_in.ready = ifc_out.ready; + endmodule