Add ASSIGNEQEXPR when use `=` inside expressions (#5567).
This commit is contained in:
parent
06c3c87f4e
commit
b455f9b591
1
Changes
1
Changes
|
|
@ -16,6 +16,7 @@ Verilator 5.041 devel
|
||||||
* Add error on non-packed struct randc (#5999). [Seth Pellegrino]
|
* Add error on non-packed struct randc (#5999). [Seth Pellegrino]
|
||||||
* Add configure `--enable-asan` to compile verilator_bin with the address sanitizer (#6404). [Geza Lore]
|
* Add configure `--enable-asan` to compile verilator_bin with the address sanitizer (#6404). [Geza Lore]
|
||||||
* Add $(LDFLAGS) and $(LIBS) to when building shared libraries (#6425) (#6426). [Ahmed El-Mahmoudy]
|
* Add $(LDFLAGS) and $(LIBS) to when building shared libraries (#6425) (#6426). [Ahmed El-Mahmoudy]
|
||||||
|
* Add ASSIGNEQEXPR when use `=` inside expressions (#5567). [Ethan Sifferman]
|
||||||
* Support pure functions in sensitivity lists (#6393). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Support pure functions in sensitivity lists (#6393). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
* Improve automatic selection of logic for DFG synthesis (#6370). [Geza Lore]
|
* Improve automatic selection of logic for DFG synthesis (#6370). [Geza Lore]
|
||||||
* Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski]
|
* Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
.. comment: generated by t_lint_assigneqexpr_bad
|
||||||
|
.. code-block:: sv
|
||||||
|
:linenos:
|
||||||
|
:emphasize-lines: 3
|
||||||
|
|
||||||
|
assign d_o = // Note = not == below
|
||||||
|
(
|
||||||
|
c_o = 1 // <--- Warning: ASSIGNEQEXPR
|
||||||
|
) ? 1 : (
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
.. comment: generated by t_lint_assigneqexpr_bad
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
%Warning-ASSIGNEQEXPR: example.v:1:11 Assignment '=' inside expression
|
||||||
|
: ... Was a '==' intended, or suggest use a separate statement
|
||||||
|
|
@ -1878,7 +1878,7 @@ Summary:
|
||||||
.. option:: -Wno-lint
|
.. option:: -Wno-lint
|
||||||
|
|
||||||
Disable all lint-related warning messages, and all style warnings. This
|
Disable all lint-related warning messages, and all style warnings. This
|
||||||
is equivalent to ``-Wno-ALWCOMBORDER`` ``-Wno-ASCRANGE``
|
is equivalent to ``-Wno-ALWCOMBORDER`` ``-Wno-ASCRANGE`` ``-Wno-ASSIGNEQEXPR``
|
||||||
``-Wno-BSSPACE`` ``-Wno-CASEINCOMPLETE`` ``-Wno-CASEOVERLAP``
|
``-Wno-BSSPACE`` ``-Wno-CASEINCOMPLETE`` ``-Wno-CASEOVERLAP``
|
||||||
``-Wno-CASEX`` ``-Wno-CASTCONST`` ``-Wno-CASEWITHX`` ``-Wno-CMPCONST``
|
``-Wno-CASEX`` ``-Wno-CASTCONST`` ``-Wno-CASEWITHX`` ``-Wno-CMPCONST``
|
||||||
``-Wno-COLONPLUS`` ``-Wno-IMPLICIT`` ``-Wno-IMPLICITSTATIC``
|
``-Wno-COLONPLUS`` ``-Wno-IMPLICIT`` ``-Wno-IMPLICITSTATIC``
|
||||||
|
|
@ -1932,14 +1932,14 @@ Summary:
|
||||||
|
|
||||||
Enable all lint-related warning messages (note that by default, they are
|
Enable all lint-related warning messages (note that by default, they are
|
||||||
already enabled), but do not affect style messages. This is equivalent
|
already enabled), but do not affect style messages. This is equivalent
|
||||||
to ``-Wwarn-ALWCOMBORDER`` ``-Wwarn-ASCRANGE`` ``-Wwarn-BSSPACE``
|
to ``-Wwarn-ALWCOMBORDER`` ``-Wwarn-ASCRANGE`` ``-Wno-ASSIGNEQEXPR``
|
||||||
``-Wwarn-CASEINCOMPLETE`` ``-Wwarn-CASEOVERLAP`` ``-Wwarn-CASEWITHX``
|
``-Wwarn-BSSPACE`` ``-Wwarn-CASEINCOMPLETE`` ``-Wwarn-CASEOVERLAP``
|
||||||
``-Wwarn-CASEX`` ``-Wwarn-CASTCONST`` ``-Wwarn-CMPCONST``
|
``-Wwarn-CASEWITHX`` ``-Wwarn-CASEX`` ``-Wwarn-CASTCONST``
|
||||||
``-Wwarn-COLONPLUS`` ``-Wwarn-IMPLICIT`` ``-Wwarn-IMPLICITSTATIC``
|
``-Wwarn-CMPCONST`` ``-Wwarn-COLONPLUS`` ``-Wwarn-IMPLICIT``
|
||||||
``-Wwarn-LATCH`` ``-Wwarn-MISINDENT`` ``-Wwarn-NEWERSTD``
|
``-Wwarn-IMPLICITSTATIC`` ``-Wwarn-LATCH`` ``-Wwarn-MISINDENT``
|
||||||
``-Wwarn-PREPROCZERO`` ``-Wwarn-PINMISSING`` ``-Wwarn-REALCVT``
|
``-Wwarn-NEWERSTD`` ``-Wwarn-PREPROCZERO`` ``-Wwarn-PINMISSING``
|
||||||
``-Wwarn-STATICVAR`` ``-Wwarn-UNSIGNED`` ``-Wwarn-WIDTHTRUNC``
|
``-Wwarn-REALCVT`` ``-Wwarn-STATICVAR`` ``-Wwarn-UNSIGNED``
|
||||||
``-Wwarn-WIDTHEXPAND`` ``-Wwarn-WIDTHXZEXPAND``.
|
``-Wwarn-WIDTHTRUNC`` ``-Wwarn-WIDTHEXPAND`` ``-Wwarn-WIDTHXZEXPAND``.
|
||||||
|
|
||||||
.. option:: -Wwarn-style
|
.. option:: -Wwarn-style
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,29 @@ List Of Warnings
|
||||||
This warning is issued only if Verilator is run with :vlopt:`--no-timing`.
|
This warning is issued only if Verilator is run with :vlopt:`--no-timing`.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: ASSIGNEQEXPR
|
||||||
|
|
||||||
|
Warning that an assignment with `=` appears in a complex expression.
|
||||||
|
The intent may have been to use `==`, or, if `=` is correct this may be
|
||||||
|
a readability issue.
|
||||||
|
|
||||||
|
Faulty example:
|
||||||
|
|
||||||
|
.. include:: ../../docs/gen/ex_ASSIGNEQEXPR_faulty.rst
|
||||||
|
|
||||||
|
Results in:
|
||||||
|
|
||||||
|
.. include:: ../../docs/gen/ex_ASSIGNEQEXPR_msg.rst
|
||||||
|
|
||||||
|
To repair, make the assignment into a separate statement.
|
||||||
|
|
||||||
|
Disabled by default as this is a code-style warning; it will simulate
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
Ignoring this warning will only suppress the lint check; it will
|
||||||
|
simulate correctly.
|
||||||
|
|
||||||
|
|
||||||
.. option:: ASSIGNIN
|
.. option:: ASSIGNIN
|
||||||
|
|
||||||
.. TODO better example
|
.. TODO better example
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ public:
|
||||||
ALWNEVER, // always will never execute
|
ALWNEVER, // always will never execute
|
||||||
ASCRANGE, // Ascending bit range vector
|
ASCRANGE, // Ascending bit range vector
|
||||||
ASSIGNDLY, // Assignment delays
|
ASSIGNDLY, // Assignment delays
|
||||||
|
ASSIGNEQEXPR, // Assignment equal (=) in expression
|
||||||
ASSIGNIN, // Assigning to input
|
ASSIGNIN, // Assigning to input
|
||||||
BADSTDPRAGMA, // Any error related to pragmas
|
BADSTDPRAGMA, // Any error related to pragmas
|
||||||
BADVLTPRAGMA, // Unknown Verilator pragma
|
BADVLTPRAGMA, // Unknown Verilator pragma
|
||||||
|
|
@ -206,15 +207,15 @@ public:
|
||||||
"CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR",
|
"CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR",
|
||||||
"UNSUPPORTED",
|
"UNSUPPORTED",
|
||||||
// Warnings
|
// Warnings
|
||||||
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN",
|
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNEQEXPR",
|
||||||
"BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
"ASSIGNIN", "BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ",
|
||||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC",
|
"BSSPACE", "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST",
|
||||||
"CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG",
|
"CDCRSTLOGIC", "CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN",
|
||||||
"COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED", "ENCAPSULATED",
|
"CONTASSREG", "COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED",
|
||||||
"ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "GENCLK", "GENUNNAMED",
|
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "GENCLK",
|
||||||
"HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC",
|
"GENUNNAMED", "HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT",
|
||||||
"IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
"IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY",
|
||||||
"LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING",
|
"INSECURE", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING",
|
||||||
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT",
|
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT",
|
||||||
"PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND",
|
"PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND",
|
||||||
"PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
|
"PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
|
||||||
|
|
@ -264,12 +265,12 @@ public:
|
||||||
}
|
}
|
||||||
// Warnings that are lint only
|
// Warnings that are lint only
|
||||||
bool lintError() const VL_MT_SAFE {
|
bool lintError() const VL_MT_SAFE {
|
||||||
return (m_e == ALWCOMBORDER || m_e == ASCRANGE || m_e == BSSPACE || m_e == CASEINCOMPLETE
|
return (m_e == ALWCOMBORDER || m_e == ASCRANGE || m_e == ASSIGNEQEXPR || m_e == BSSPACE
|
||||||
|| m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST
|
|| m_e == CASEINCOMPLETE || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX
|
||||||
|| m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT || m_e == IMPLICITSTATIC
|
|| m_e == CASTCONST || m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT
|
||||||
|| m_e == LATCH || m_e == MISINDENT || m_e == NEWERSTD || m_e == PREPROCZERO
|
|| m_e == IMPLICITSTATIC || m_e == LATCH || m_e == MISINDENT || m_e == NEWERSTD
|
||||||
|| m_e == PINMISSING || m_e == REALCVT || m_e == STATICVAR || m_e == UNSIGNED
|
|| m_e == PREPROCZERO || m_e == PINMISSING || m_e == REALCVT || m_e == STATICVAR
|
||||||
|| m_e == WIDTH || m_e == WIDTHTRUNC || m_e == WIDTHEXPAND
|
|| m_e == UNSIGNED || m_e == WIDTH || m_e == WIDTHTRUNC || m_e == WIDTHEXPAND
|
||||||
|| m_e == WIDTHXZEXPAND);
|
|| m_e == WIDTHXZEXPAND);
|
||||||
}
|
}
|
||||||
// Warnings that are style only
|
// Warnings that are style only
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,13 @@ static void ERRSVKWD(FileLine* fileline, const string& tokname) {
|
||||||
: ""));
|
: ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ASSIGNEQEXPR(FileLine* fileline) {
|
||||||
|
fileline->v3warn(ASSIGNEQEXPR,
|
||||||
|
"Assignment '=' inside expression\n"
|
||||||
|
<< fileline->warnMore()
|
||||||
|
<< "... Was a '==' intended, or suggest use a separate statement");
|
||||||
|
}
|
||||||
|
|
||||||
static void UNSUPREAL(FileLine* fileline) {
|
static void UNSUPREAL(FileLine* fileline) {
|
||||||
fileline->v3warn(SHORTREAL,
|
fileline->v3warn(SHORTREAL,
|
||||||
"Unsupported: shortreal being promoted to real (suggest use real instead)");
|
"Unsupported: shortreal being promoted to real (suggest use real instead)");
|
||||||
|
|
@ -4828,7 +4835,8 @@ expr<nodeExprp>: // IEEE: part of expression/constant_expression/
|
||||||
// // Need exprScope of variable_lvalue to prevent conflict
|
// // Need exprScope of variable_lvalue to prevent conflict
|
||||||
| '(' ~p~exprScope '=' expr ')'
|
| '(' ~p~exprScope '=' expr ')'
|
||||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, $4},
|
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, $4},
|
||||||
$2->cloneTreePure(true)}; }
|
$2->cloneTreePure(true)};
|
||||||
|
ASSIGNEQEXPR($<fl>3); }
|
||||||
| '(' ~p~exprScope yP_PLUSEQ expr ')'
|
| '(' ~p~exprScope yP_PLUSEQ expr ')'
|
||||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAdd{$3, $2->cloneTreePure(true), $4}},
|
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAdd{$3, $2->cloneTreePure(true), $4}},
|
||||||
$2->cloneTreePure(true)}; }
|
$2->cloneTreePure(true)}; }
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ module t;
|
||||||
int b;
|
int b;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
// verilator lint_off ASSIGNEQEXPR
|
||||||
initial begin
|
initial begin
|
||||||
a = 10;
|
a = 10;
|
||||||
i = (a = 2);
|
i = (a = 2);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=['--binary', '--trace', '-Wno-ASSIGNEQEXPR'])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
module t (
|
||||||
|
input logic a2_i,
|
||||||
|
a1_i,
|
||||||
|
a0_i,
|
||||||
|
input logic b_i,
|
||||||
|
output logic d_o
|
||||||
|
);
|
||||||
|
// verilator lint_off PINMISSING
|
||||||
|
Sub sub (.a_i({a2_i, a1_i, a0_i}), .b_i, .d_o);
|
||||||
|
// verilator lint_on PINMISSING
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Sub (
|
||||||
|
input logic [2:0] a_i,
|
||||||
|
input logic b_i,
|
||||||
|
output logic c_o,
|
||||||
|
output logic d_o
|
||||||
|
);
|
||||||
|
assign c_o = (a_i != 0) ? 1 : 0;
|
||||||
|
assign d_o = // Note = not == below
|
||||||
|
(
|
||||||
|
c_o = 1 // <--- Warning: ASSIGNEQEXPR
|
||||||
|
) ? 1 : (
|
||||||
|
c_o = 0 // <--- Warning: ASSIGNEQEXPR
|
||||||
|
) ? b_i : 0;
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
%Warning-ASSIGNEQEXPR: t/t_lint_assigneqexpr.v:28:11: Assignment '=' inside expression
|
||||||
|
: ... Was a '==' intended, or suggest use a separate statement
|
||||||
|
28 | c_o = 1
|
||||||
|
| ^
|
||||||
|
... For warning description see https://verilator.org/warn/ASSIGNEQEXPR?v=latest
|
||||||
|
... Use "/* verilator lint_off ASSIGNEQEXPR */" and lint_on around source to disable this message.
|
||||||
|
%Warning-ASSIGNEQEXPR: t/t_lint_assigneqexpr.v:30:11: Assignment '=' inside expression
|
||||||
|
: ... Was a '==' intended, or suggest use a separate statement
|
||||||
|
30 | c_o = 0
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/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('vlt')
|
||||||
|
test.top_filename = "t/t_lint_assigneqexpr.v"
|
||||||
|
|
||||||
|
root = ".."
|
||||||
|
|
||||||
|
test.lint(verilator_flags2=['-Wall -Wno-DECLFILENAME'],
|
||||||
|
fails=True,
|
||||||
|
expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.extract(in_filename=test.top_filename,
|
||||||
|
out_filename=root + "/docs/gen/ex_ASSIGNEQEXPR_faulty.rst",
|
||||||
|
lines="26-29")
|
||||||
|
|
||||||
|
test.extract(in_filename=test.golden_filename,
|
||||||
|
out_filename=root + "/docs/gen/ex_ASSIGNEQEXPR_msg.rst",
|
||||||
|
lines="7-8")
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -21,7 +21,9 @@ module t (/*AUTOARG*/
|
||||||
x <= 1;
|
x <= 1;
|
||||||
end
|
end
|
||||||
else if (cyc == 1) begin
|
else if (cyc == 1) begin
|
||||||
|
// verilator lint_off ASSIGNEQEXPR
|
||||||
y <= (x = 2);
|
y <= (x = 2);
|
||||||
|
// verilator lint_on ASSIGNEQEXPR
|
||||||
end else begin
|
end else begin
|
||||||
if (x != 2) $stop;
|
if (x != 2) $stop;
|
||||||
if (y != 2) $stop;
|
if (y != 2) $stop;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue