diff --git a/src/V3Active.cpp b/src/V3Active.cpp index e7029790a..fc40166c0 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -320,7 +320,8 @@ private: // VISITORS void visit(AstVarRef* nodep) override { const AstVar* const varp = nodep->varp(); - if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()) { + if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx() + && !varp->isFuncLocalSticky()) { m_graph.addAssignment(nodep); } } @@ -333,6 +334,8 @@ private: m_graph.addPathVertex(branchp, "ELSE"); iterateAndNextConstNull(nodep->elsesp()); m_graph.currentp(parentp); + } else { + iterateChildrenConst(nodep); } } //-------------------- diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 4a284b233..90e475d15 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -1646,6 +1646,7 @@ class AstVar final : public AstNode { bool m_usedLoopIdx : 1; // Variable subject of for unrolling bool m_usedVirtIface : 1; // Signal used through a virtual interface bool m_funcLocal : 1; // Local variable for a function + bool m_funcLocalSticky : 1; // As m_funcLocal but remains set if var is moved to a static bool m_funcReturn : 1; // Return variable for a function bool m_attrScBv : 1; // User force bit vector attribute bool m_attrIsolateAssign : 1; // User isolate_assignments attribute @@ -1689,6 +1690,7 @@ class AstVar final : public AstNode { m_sigUserRdPublic = false; m_sigUserRWPublic = false; m_funcLocal = false; + m_funcLocalSticky = false; m_funcReturn = false; m_attrScBv = false; m_attrIsolateAssign = false; @@ -1852,7 +1854,10 @@ public: void isContinuously(bool flag) { m_isContinuously = flag; } void isStatic(bool flag) { m_isStatic = flag; } void isIfaceParent(bool flag) { m_isIfaceParent = flag; } - void funcLocal(bool flag) { m_funcLocal = flag; } + void funcLocal(bool flag) { + m_funcLocal = flag; + if (flag) m_funcLocalSticky = true; + } void funcReturn(bool flag) { m_funcReturn = flag; } void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; } bool hasStrengthAssignment() { return m_hasStrengthAssignment; } @@ -1934,6 +1939,7 @@ public: bool isStatic() const VL_MT_SAFE { return m_isStatic; } bool isLatched() const { return m_isLatched; } bool isFuncLocal() const { return m_funcLocal; } + bool isFuncLocalSticky() const { return m_funcLocalSticky; } bool isFuncReturn() const { return m_funcReturn; } bool isPullup() const { return m_isPullup; } bool isPulldown() const { return m_isPulldown; } diff --git a/test_regress/t/t_lint_latch_6.pl b/test_regress/t/t_lint_latch_6.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_6.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_6.v b/test_regress/t/t_lint_latch_6.v new file mode 100644 index 000000000..9f55fb831 --- /dev/null +++ b/test_regress/t/t_lint_latch_6.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#221 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2023 by Julien Margetts (Originally provided by Adrien Le Masle) +// SPDX-License-Identifier: Unlicense + +module verilator_latch +( + input logic state, + output logic [31:0] b +); + + function logic [31:0 ] toto (); + logic [31:0] res; + res = 10; + return res; + endfunction + + always_comb + begin + b = 0; + if (state) + b = toto(); + end + +endmodule; diff --git a/test_regress/t/t_lint_latch_7.pl b/test_regress/t/t_lint_latch_7.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_7.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_latch_7.v b/test_regress/t/t_lint_latch_7.v new file mode 100644 index 000000000..d8fbbc1c6 --- /dev/null +++ b/test_regress/t/t_lint_latch_7.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#xxxx +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2021 by Julien Margetts +// SPDX-License-Identifier: Unlicense + +module test #(parameter W = 65) + (input logic [W-1:0] a, + input logic e, + output logic [W-1:0] z); + + integer i; + + always @(*) + if (e) + for (i=0;i