From 21b42c44636ae78a1b8e9402a133515df22a2783 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 28 Sep 2025 21:13:42 -0400 Subject: [PATCH] Fix LATCH warning with CASEINCOMPLETE (#3301). --- Changes | 1 + src/V3Case.cpp | 6 +++++- test_regress/t/t_lint_latch_casei_bad.out | 7 +++++++ test_regress/t/t_lint_latch_casei_bad.py | 16 ++++++++++++++++ test_regress/t/t_lint_latch_casei_bad.v | 19 +++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test_regress/t/t_lint_latch_casei_bad.out create mode 100755 test_regress/t/t_lint_latch_casei_bad.py create mode 100644 test_regress/t/t_lint_latch_casei_bad.v diff --git a/Changes b/Changes index 0a740b883..6dfc1e0ff 100644 --- a/Changes +++ b/Changes @@ -37,6 +37,7 @@ Verilator 5.041 devel * Optimize dead functions in more cases (#6380) (#6430). [Artur Bieniek, Antmicro Ltd.] * Optimize constant folding in wide expression expansion (#6381). [Geza Lore] * 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 false CONSTVAR error on initializers (#4992). * Fix interface exposure with `--public-depth` or `--trace-depth` (#5758). diff --git a/src/V3Case.cpp b/src/V3Case.cpp index b2f6d8f01..1bb969ada 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -143,6 +143,7 @@ class CaseVisitor final : public VNVisitor { // Per-CASE int m_caseWidth = 0; // Width of valueItems 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 // For each possible value, the case branch we need std::array m_valueItem; @@ -178,6 +179,7 @@ class CaseVisitor final : public VNVisitor { if (!m_valueItem[i]) { nodep->v3warn(CASEINCOMPLETE, "Enum item " << itemp->prettyNameQ() << " not covered by case\n"); + m_caseIncomplete = true; 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 " "(example pattern 0x" << std::hex << i << ")"); + m_caseIncomplete = true; m_caseNoOverlapsAllCovered = false; return false; } @@ -578,6 +581,7 @@ class CaseVisitor final : public VNVisitor { // VISITORS void visit(AstCase* nodep) override { + VL_RESTORER(m_caseIncomplete); { CaseLintVisitor{nodep}; } iterateChildren(nodep); UINFOTREE(9, nodep, "", "case_old"); @@ -588,7 +592,7 @@ class CaseVisitor final : public VNVisitor { VL_DO_DANGLING(replaceCaseFast(nodep), nodep); } else { // 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; VL_DO_DANGLING(replaceCaseComplicated(nodep), nodep); } diff --git a/test_regress/t/t_lint_latch_casei_bad.out b/test_regress/t/t_lint_latch_casei_bad.out new file mode 100644 index 000000000..e4dd06c0f --- /dev/null +++ b/test_regress/t/t_lint_latch_casei_bad.out @@ -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 diff --git a/test_regress/t/t_lint_latch_casei_bad.py b/test_regress/t/t_lint_latch_casei_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_lint_latch_casei_bad.py @@ -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() diff --git a/test_regress/t/t_lint_latch_casei_bad.v b/test_regress/t/t_lint_latch_casei_bad.v new file mode 100644 index 000000000..001813cd2 --- /dev/null +++ b/test_regress/t/t_lint_latch_casei_bad.v @@ -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