Fix false CONSTVAR error on initializers (#4992).
This commit is contained in:
parent
f8f5f8f84b
commit
a9f95f2f08
1
Changes
1
Changes
|
|
@ -19,6 +19,7 @@ Verilator 5.041 devel
|
||||||
* Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski]
|
* Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski]
|
||||||
* Improve DFG type system (#6390). [Geza Lore]
|
* Improve DFG type system (#6390). [Geza Lore]
|
||||||
* Optimize dead functions without references (#6380). [Artur Bieniek, Antmicro Ltd.]
|
* 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 cell scoping performance (#6059). [Jerry Tianchen]
|
||||||
* Fix while loop hang on timing-delayed assignment (#6343) (#6354). [Krzysztof Bieganski, Antmicro Ltd.]
|
* 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]
|
* Fix driver analysis of partially assigned variables (#6364) (#6378). [Geza Lore]
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,17 @@ List Of Warnings
|
||||||
from other simulators.
|
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
|
.. option:: CONTASSREG
|
||||||
|
|
||||||
.. TODO better example
|
.. TODO better example
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public:
|
||||||
I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/
|
I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/
|
||||||
I_UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility)
|
I_UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility)
|
||||||
// Error codes:
|
// Error codes:
|
||||||
|
E_CONSTWRITTEN, // Error: Const variable being written.
|
||||||
E_LIFETIME, // Error: Reference to a variable might outlive the variable.
|
E_LIFETIME, // Error: Reference to a variable might outlive the variable.
|
||||||
E_NEEDTIMINGOPT, // Error: --timing/--no-timing option not specified
|
E_NEEDTIMINGOPT, // Error: --timing/--no-timing option not specified
|
||||||
E_NOTIMING, // Timing control encountered with --no-timing
|
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_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_TIMING",
|
||||||
" I_TRACING", " I_UNUSED",
|
" I_TRACING", " I_UNUSED",
|
||||||
// Errors
|
// Errors
|
||||||
"LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", "UNSUPPORTED",
|
"CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR",
|
||||||
|
"UNSUPPORTED",
|
||||||
// Warnings
|
// Warnings
|
||||||
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN",
|
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN",
|
||||||
"BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
"BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
||||||
|
|
|
||||||
|
|
@ -396,11 +396,13 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
||||||
FileLine* const newfl = new FileLine{fl};
|
FileLine* const newfl = new FileLine{fl};
|
||||||
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
|
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
|
// 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)
|
// it's a port (see t_var_set_link.v)
|
||||||
AstAssign* const assp = new AstAssign{
|
AstAssign* const assp = new AstAssign{
|
||||||
newfl, new AstParseRef{newfl, VParseRefExp::PX_TEXT, nodep->name()},
|
newfl, new AstParseRef{newfl, VParseRefExp::PX_TEXT, nodep->name()},
|
||||||
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)};
|
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)};
|
||||||
|
UINFOTREE(1, assp, "", "new");
|
||||||
if (nodep->lifetime().isAutomatic()) {
|
if (nodep->lifetime().isAutomatic()) {
|
||||||
nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
|
nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -408,9 +410,12 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
} // 4. Under blocks, it's an initial value to be under an assign
|
} // 4. Under blocks, it's an initial value to be under an assign
|
||||||
else {
|
else {
|
||||||
|
FileLine* const newfl = new FileLine{fl};
|
||||||
|
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
|
||||||
nodep->addNextHere(
|
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)});
|
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)});
|
||||||
|
UINFOTREE(1, nodep->nextp(), "", "new");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2608,7 +2608,9 @@ class WidthVisitor final : public VNVisitor {
|
||||||
&& !VN_IS(m_procedurep, InitialStatic)) {
|
&& !VN_IS(m_procedurep, InitialStatic)) {
|
||||||
// Too loose, but need to allow our generated first assignment
|
// Too loose, but need to allow our generated first assignment
|
||||||
// Move this to a property of the AstInitial block
|
// 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);
|
nodep->didWidth(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
%Error: t/t_var_const_bad.v:17:7: Assigning to const variable: 'five'
|
%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'
|
: ... note: In instance 't'
|
||||||
17 | five = 3'd4;
|
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
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue