diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 221bada4f..3e9ee98ad 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -309,16 +309,16 @@ private: } } virtual void visit(AstNodeIf* nodep) { - LatchDetectGraphVertex* parentp = m_graph.currentp(); - LatchDetectGraphVertex* branchp = m_graph.addPathVertex(parentp, "BRANCH", true); - m_graph.addPathVertex(branchp, "IF"); - iterateAndNextNull(nodep->ifsp()); - m_graph.addPathVertex(branchp, "ELSE"); - iterateAndNextNull(nodep->elsesp()); - m_graph.currentp(parentp); + if (!nodep->isBoundsCheck()) { + LatchDetectGraphVertex* parentp = m_graph.currentp(); + LatchDetectGraphVertex* branchp = m_graph.addPathVertex(parentp, "BRANCH", true); + m_graph.addPathVertex(branchp, "IF"); + iterateAndNextNull(nodep->ifsp()); + m_graph.addPathVertex(branchp, "ELSE"); + iterateAndNextNull(nodep->elsesp()); + m_graph.currentp(parentp); + } } - // Empty visitors, speed things up - virtual void visit(AstNodeMath* nodep) {} //-------------------- virtual void visit(AstNode* nodep) { iterateChildren(nodep); } diff --git a/src/V3Ast.h b/src/V3Ast.h index d915ff156..8ac87c735 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2216,12 +2216,14 @@ public: class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { private: VBranchPred m_branchPred; // Branch prediction as taken/untaken? + bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking protected: AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) : AstNodeStmt{t, fl} { setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp); + isBoundsCheck(false); } public: @@ -2238,6 +2240,8 @@ public: virtual bool same(const AstNode* samep) const override { return true; } void branchPred(VBranchPred flag) { m_branchPred = flag; } VBranchPred branchPred() const { return m_branchPred; } + void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } + bool isBoundsCheck() const { return m_isBoundsCheck; } }; class AstNodeCase VL_NOT_FINAL : public AstNodeStmt { diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 5878a70c9..e79db26eb 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -127,6 +127,7 @@ private: new AstAssign(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))), nullptr); newp->branchPred(VBranchPred::BP_LIKELY); + newp->isBoundsCheck(true); if (debug() >= 9) newp->dumpTree(cout, " _new: "); abovep->addNextStmt(newp, abovep); prep->user2p(newp); // Save so we may LogAnd it next time diff --git a/test_regress/t/t_lint_latch_4.pl b/test_regress/t/t_lint_latch_4.pl new file mode 100755 index 000000000..629a44bbb --- /dev/null +++ b/test_regress/t/t_lint_latch_4.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_4.v b/test_regress/t/t_lint_latch_4.v new file mode 100644 index 000000000..e7182f4ca --- /dev/null +++ b/test_regress/t/t_lint_latch_4.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Verilog Test module for Issue#2938 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2021 by Julien Margetts (Originally provided by YanJiun) + +module test ( + input [2:0] a, + input [3:0] c, + + output reg [7:0] b +); + + integer i; + + always @ (*) + begin + case(a) + {3'b000}: b = 8'd1; + {3'b001}: + for(i=0;i<4;i=i+1) b[i*2+:2] = 2'(c[i]); + {3'b010}: b = 8'd3; + {3'b011}: b = 8'd4; + default : b = 0; + endcase + end + +endmodule