Fix LATCH warning with CASEINCOMPLETE (#3301).

This commit is contained in:
Wilson Snyder 2025-09-28 21:13:42 -04:00
parent ca0a679413
commit 21b42c4463
5 changed files with 48 additions and 1 deletions

View File

@ -37,6 +37,7 @@ Verilator 5.041 devel
* Optimize dead functions in more cases (#6380) (#6430). [Artur Bieniek, Antmicro Ltd.] * Optimize dead functions in more cases (#6380) (#6430). [Artur Bieniek, Antmicro Ltd.]
* Optimize constant folding in wide expression expansion (#6381). [Geza Lore] * Optimize constant folding in wide expression expansion (#6381). [Geza Lore]
* Fix missing BLKSEQ when connecting module port to array (#2973). * Fix missing BLKSEQ when connecting module port to array (#2973).
* Fix LATCH warning with CASEINCOMPLETE (#3301).
* Fix unused parameterized class causing internal error (#4013). [Alberto Del Rio] * Fix unused parameterized class causing internal error (#4013). [Alberto Del Rio]
* Fix false CONSTVAR error on initializers (#4992). * Fix false CONSTVAR error on initializers (#4992).
* Fix interface exposure with `--public-depth` or `--trace-depth` (#5758). * Fix interface exposure with `--public-depth` or `--trace-depth` (#5758).

View File

@ -143,6 +143,7 @@ class CaseVisitor final : public VNVisitor {
// Per-CASE // Per-CASE
int m_caseWidth = 0; // Width of valueItems int m_caseWidth = 0; // Width of valueItems
int m_caseItems = 0; // Number of caseItem unique values int m_caseItems = 0; // Number of caseItem unique values
bool m_caseIncomplete = false; // Proven incomplete
bool m_caseNoOverlapsAllCovered = false; // Proven to be synopsys parallel_case compliant bool m_caseNoOverlapsAllCovered = false; // Proven to be synopsys parallel_case compliant
// For each possible value, the case branch we need // For each possible value, the case branch we need
std::array<AstNode*, 1 << CASE_OVERLAP_WIDTH> m_valueItem; std::array<AstNode*, 1 << CASE_OVERLAP_WIDTH> m_valueItem;
@ -178,6 +179,7 @@ class CaseVisitor final : public VNVisitor {
if (!m_valueItem[i]) { if (!m_valueItem[i]) {
nodep->v3warn(CASEINCOMPLETE, "Enum item " << itemp->prettyNameQ() nodep->v3warn(CASEINCOMPLETE, "Enum item " << itemp->prettyNameQ()
<< " not covered by case\n"); << " not covered by case\n");
m_caseIncomplete = true;
return false; // enum has uncovered value by case items return false; // enum has uncovered value by case items
} }
} }
@ -306,6 +308,7 @@ class CaseVisitor final : public VNVisitor {
nodep->v3warn(CASEINCOMPLETE, "Case values incompletely covered " nodep->v3warn(CASEINCOMPLETE, "Case values incompletely covered "
"(example pattern 0x" "(example pattern 0x"
<< std::hex << i << ")"); << std::hex << i << ")");
m_caseIncomplete = true;
m_caseNoOverlapsAllCovered = false; m_caseNoOverlapsAllCovered = false;
return false; return false;
} }
@ -578,6 +581,7 @@ class CaseVisitor final : public VNVisitor {
// VISITORS // VISITORS
void visit(AstCase* nodep) override { void visit(AstCase* nodep) override {
VL_RESTORER(m_caseIncomplete);
{ CaseLintVisitor{nodep}; } { CaseLintVisitor{nodep}; }
iterateChildren(nodep); iterateChildren(nodep);
UINFOTREE(9, nodep, "", "case_old"); UINFOTREE(9, nodep, "", "case_old");
@ -588,7 +592,7 @@ class CaseVisitor final : public VNVisitor {
VL_DO_DANGLING(replaceCaseFast(nodep), nodep); VL_DO_DANGLING(replaceCaseFast(nodep), nodep);
} else { } else {
// If a case statement is whole, presume signals involved aren't forming a latch // If a case statement is whole, presume signals involved aren't forming a latch
if (m_alwaysp) m_alwaysp->fileline()->warnOff(V3ErrorCode::LATCH, true); if (m_alwaysp && !m_caseIncomplete) m_alwaysp->fileline()->warnOff(V3ErrorCode::LATCH, true);
++m_statCaseSlow; ++m_statCaseSlow;
VL_DO_DANGLING(replaceCaseComplicated(nodep), nodep); VL_DO_DANGLING(replaceCaseComplicated(nodep), nodep);
} }

View File

@ -0,0 +1,7 @@
%Warning-LATCH: t/t_lint_latch_casei_bad.v:12:3: Latch inferred for signal 'o' (not all control paths of combinational always assign a value)
: ... Suggest use of always_latch for intentional latches
12 | always_comb begin
| ^~~~~~~~~~~
... For warning description see https://verilator.org/warn/LATCH?v=latest
... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('linter')
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module for Issue#1609
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (
input a,
output reg o
);
always_comb begin
// verilator lint_off CASEINCOMPLETE
case (a)
1'b0: o = 1;
endcase
end
endmodule