From a9f95f2f081b9636919e3c8c3d63cd867ef0210d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 9 Sep 2025 19:27:43 -0400 Subject: [PATCH] Fix false CONSTVAR error on initializers (#4992). --- Changes | 1 + docs/guide/warnings.rst | 11 ++++++++ src/V3Error.h | 4 ++- src/V3LinkParse.cpp | 7 ++++- src/V3Width.cpp | 4 ++- test_regress/t/t_var_const2.py | 16 +++++++++++ test_regress/t/t_var_const2.v | 45 ++++++++++++++++++++++++++++++ test_regress/t/t_var_const_bad.out | 6 ++-- 8 files changed, 88 insertions(+), 6 deletions(-) create mode 100755 test_regress/t/t_var_const2.py create mode 100644 test_regress/t/t_var_const2.v diff --git a/Changes b/Changes index bec8b5643..a349b1dd8 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,7 @@ Verilator 5.041 devel * Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski] * Improve DFG type system (#6390). [Geza Lore] * Optimize dead functions without references (#6380). [Artur Bieniek, Antmicro Ltd.] +* Fix false CONSTVAR error on initializers (#4992). * Fix cell scoping performance (#6059). [Jerry Tianchen] * Fix while loop hang on timing-delayed assignment (#6343) (#6354). [Krzysztof Bieganski, Antmicro Ltd.] * Fix driver analysis of partially assigned variables (#6364) (#6378). [Geza Lore] diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index 11aaaea92..79dd779f2 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -485,6 +485,17 @@ List Of Warnings from other simulators. +.. option:: CONSTWRITTEN + + Error that a :code:`const` data typed variable is being assigned a + value. + + IEEE 1800-2023 6.20.6 requires this error. + + Suppressing this error will suppress the error message check; it will + simulate as if the :code:`const` as not present. + + .. option:: CONTASSREG .. TODO better example diff --git a/src/V3Error.h b/src/V3Error.h index 7e5ab7d30..008b70900 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -60,6 +60,7 @@ public: I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/ I_UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility) // Error codes: + E_CONSTWRITTEN, // Error: Const variable being written. E_LIFETIME, // Error: Reference to a variable might outlive the variable. E_NEEDTIMINGOPT, // Error: --timing/--no-timing option not specified E_NOTIMING, // Timing control encountered with --no-timing @@ -202,7 +203,8 @@ public: " I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_TIMING", " I_TRACING", " I_UNUSED", // Errors - "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", "UNSUPPORTED", + "CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", + "UNSUPPORTED", // Warnings " EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 14190022d..4f477188d 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -396,11 +396,13 @@ class LinkParseVisitor final : public VNVisitor { // Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it FileLine* const newfl = new FileLine{fl}; newfl->warnOff(V3ErrorCode::PROCASSWIRE, true); + newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true); // Create a ParseRef to the wire. We cannot use the var as it may be deleted if // it's a port (see t_var_set_link.v) AstAssign* const assp = new AstAssign{ newfl, new AstParseRef{newfl, VParseRefExp::PX_TEXT, nodep->name()}, VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)}; + UINFOTREE(1, assp, "", "new"); if (nodep->lifetime().isAutomatic()) { nodep->addNextHere(new AstInitialAutomatic{newfl, assp}); } else { @@ -408,9 +410,12 @@ class LinkParseVisitor final : public VNVisitor { } } // 4. Under blocks, it's an initial value to be under an assign else { + FileLine* const newfl = new FileLine{fl}; + newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true); nodep->addNextHere( - new AstAssign{fl, new AstVarRef{fl, nodep, VAccess::WRITE}, + new AstAssign{newfl, new AstVarRef{newfl, nodep, VAccess::WRITE}, VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)}); + UINFOTREE(1, nodep->nextp(), "", "new"); } } } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 8bdf785f7..e99dbb65b 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2608,7 +2608,9 @@ class WidthVisitor final : public VNVisitor { && !VN_IS(m_procedurep, InitialStatic)) { // Too loose, but need to allow our generated first assignment // Move this to a property of the AstInitial block - nodep->v3error("Assigning to const variable: " << nodep->prettyNameQ()); + nodep->v3warn(E_CONSTWRITTEN, "Writing to 'const' data-typed variable " + << nodep->prettyNameQ() + << " (IEEE 1800-2023 6.20.6)"); } nodep->didWidth(true); } diff --git a/test_regress/t/t_var_const2.py b/test_regress/t/t_var_const2.py new file mode 100755 index 000000000..cca4c9e73 --- /dev/null +++ b/test_regress/t/t_var_const2.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() + +test.passes() diff --git a/test_regress/t/t_var_const2.v b/test_regress/t/t_var_const2.v new file mode 100644 index 000000000..acc55230a --- /dev/null +++ b/test_regress/t/t_var_const2.v @@ -0,0 +1,45 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// 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 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +`define checkp(gotv,expv_s) do begin string gotv_s; gotv_s = $sformatf("%p", gotv); if ((gotv_s) != (expv_s)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv_s), (expv_s)); `stop; end end while(0); +// verilog_format: on + +module t; + const static int a1; + const static int a2 = 0; + + const automatic int b1; + const automatic int b2 = 0; + + initial begin + const static int c1; + const static int c2 = 0; + + const automatic int d1; + const automatic int d2 = 0; + end + + function static void tb_func1(); + const static int e1; + const static int e2 = 0; + + const automatic int f1; + const automatic int f2 = 0; + endfunction + + function automatic void tb_func2(); + const static int g1; + const static int g2 = 0; + + const automatic int h1; + const automatic int h2 = 0; + endfunction +endmodule diff --git a/test_regress/t/t_var_const_bad.out b/test_regress/t/t_var_const_bad.out index 2e6990653..8190ff1ed 100644 --- a/test_regress/t/t_var_const_bad.out +++ b/test_regress/t/t_var_const_bad.out @@ -1,6 +1,6 @@ -%Error: t/t_var_const_bad.v:17:7: Assigning to const variable: 'five' - : ... note: In instance 't' +%Error-CONSTWRITTEN: t/t_var_const_bad.v:17:7: Writing to 'const' data-typed variable 'five' (IEEE 1800-2023 6.20.6) + : ... note: In instance 't' 17 | five = 3'd4; | ^~~~ - ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. + ... For error description see https://verilator.org/warn/CONSTWRITTEN?v=latest %Error: Exiting due to