diff --git a/Changes b/Changes index 843177436..f1d8d0b3d 100644 --- a/Changes +++ b/Changes @@ -35,6 +35,7 @@ Verilator 5.015 devel * Fix reference to extended class in parameterized class (#4466). * Fix display %x formatting of real. * Fix mis-warning on #() in classes' own functions. +* Fix ZERODLY to not warn on 'wait(0)'. Verilator 5.014 2023-08-06 diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index f44082085..7f0898b5d 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -1990,11 +1990,15 @@ List Of Warnings .. code-block:: sv - wait(0); // Blocks forever + wait(1); // Blocks forever Warns that a `wait` statement awaits a constant condition, which means it either blocks forever or never blocks. + As a special case `wait(0)` with the literal constant `0` (as opposed to + something that elaborates to zero), does not warn, as it is presumed the + code is making the intent clear. + .. option:: WIDTH diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index a7b6b9923..e61ff5f59 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -591,6 +591,17 @@ private: iterateChildren(nodep); } } + void visit(AstWait* nodep) override { + cleanFileline(nodep); + iterateChildren(nodep); + if (nodep->condp()->isZero()) { + // Special case "wait(0)" we won't throw WAITCONST as user wrote + // it that way with presumed intent - UVM does this. + FileLine* const newfl = nodep->fileline(); + newfl->warnOff(V3ErrorCode::WAITCONST, true); + nodep->fileline(newfl); + } + } void visit(AstWhile* nodep) override { cleanFileline(nodep); VL_RESTORER(m_insideLoop); diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp index 15b5a2e0d..a21892e00 100644 --- a/src/V3Timing.cpp +++ b/src/V3Timing.cpp @@ -997,7 +997,9 @@ private: AstNodeExpr* const condp = V3Const::constifyEdit(nodep->condp()->unlinkFrBack()); auto* const constp = VN_CAST(condp, Const); if (constp) { - condp->v3warn(WAITCONST, "Wait statement condition is constant"); + if (!nodep->fileline()->warnIsOff(V3ErrorCode::WAITCONST)) { + condp->v3warn(WAITCONST, "Wait statement condition is constant"); + } if (constp->isZero()) { // We have to await forever instead of simply returning in case we're deep in a // callstack diff --git a/test_regress/t/t_lint_wait_bad.out b/test_regress/t/t_lint_wait_bad.out index 8cc25f02c..b108720dc 100644 --- a/test_regress/t/t_lint_wait_bad.out +++ b/test_regress/t/t_lint_wait_bad.out @@ -6,9 +6,6 @@ %Warning-WAITCONST: t/t_timing_wait1.v:54:14: Wait statement condition is constant 54 | wait(0 < 1) $write("*-* All Finished *-*\n"); | ^ -%Warning-WAITCONST: t/t_timing_wait1.v:58:17: Wait statement condition is constant - 58 | initial wait(0) $stop; - | ^ %Warning-WAITCONST: t/t_timing_wait1.v:59:19: Wait statement condition is constant 59 | initial wait(1 == 0) $stop; | ^~ diff --git a/test_regress/t/t_timing_wait1.v b/test_regress/t/t_timing_wait1.v index 7ec77a5b4..146e84ab2 100644 --- a/test_regress/t/t_timing_wait1.v +++ b/test_regress/t/t_timing_wait1.v @@ -55,7 +55,7 @@ module t; $finish; end - initial wait(0) $stop; + initial wait(0) $stop; // Note this doesn't give WAITCONST initial wait(1 == 0) $stop; initial #12 $stop; // timeout