mirror of
https://github.com/verilator/verilator.git
synced 2026-09-05 08:42:46 +02:00
Fix MULTIDRIVENPROC on static loop induction variables (#8242)
Disable MULTIDRIVENPROC for static variables used as loop induction variables. Same way as we disable similar warning in Dfg. While bad style and bad for performance, it's common legacy code style.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
.. comment: generated by t_lint_multidriven_proc_bad
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
|
||||
integer i;
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (i = 0; i < 4; i = i + 1) q1[i] <= d[i];
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (i = 0; i < 4; i = i + 1) q2[i] <= ~d[i];
|
||||
end
|
||||
@@ -2,7 +2,7 @@
|
||||
.. code-block::
|
||||
|
||||
%Warning-MULTIDRIVENPROC: example.v:1:25 Variable written to in always block also written by another always block: 'q'
|
||||
: ... note: In instance 't'
|
||||
: ... note: In instance 't.u1'
|
||||
example.v:1:25
|
||||
16 | always @(posedge clk) q <= ~d;
|
||||
54 | always @(posedge clk) q <= ~d;
|
||||
| ^
|
||||
|
||||
@@ -1512,6 +1512,10 @@ List Of Warnings
|
||||
``always_ff``/``always_comb`` if the intent is a single specialized
|
||||
process.
|
||||
|
||||
Does not warn for static variables used as loop induction variables:
|
||||
|
||||
.. include:: ../../docs/gen/ex_MULTIDRIVENPROC_loopidx.rst
|
||||
|
||||
|
||||
.. option:: MULTITOP
|
||||
|
||||
|
||||
+1
-1
@@ -691,7 +691,7 @@ class UndrivenVisitor final : public VNVisitorConst {
|
||||
}
|
||||
warnClockingDriven(nodep, entryp, otherWritep, otherWriteIsStaticInit);
|
||||
}
|
||||
if (multidrivenCommon
|
||||
if (multidrivenCommon && !nodep->varp()->isUsedLoopIdx()
|
||||
&& !nodep->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVENPROC)) {
|
||||
// Two plain always blocks driving the whole signal: legal
|
||||
// SystemVerilog, but a driver conflict for synthesis. The
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
%Warning-MULTIDRIVENPROC: t/t_lint_multidriven_proc_bad.v:16:25: Variable written to in always block also written by another always block: 'q'
|
||||
: ... note: In instance 't'
|
||||
t/t_lint_multidriven_proc_bad.v:16:25:
|
||||
16 | always @(posedge clk) q <= ~d;
|
||||
%Warning-MULTIDRIVENPROC: t/t_lint_multidriven_proc_bad.v:54:25: Variable written to in always block also written by another always block: 'q'
|
||||
: ... note: In instance 't.u1'
|
||||
t/t_lint_multidriven_proc_bad.v:54:25:
|
||||
54 | always @(posedge clk) q <= ~d;
|
||||
| ^
|
||||
t/t_lint_multidriven_proc_bad.v:15:25: ... Location of other write
|
||||
15 | always @(posedge clk) q <= d;
|
||||
t/t_lint_multidriven_proc_bad.v:53:25: ... Location of other write
|
||||
53 | always @(posedge clk) q <= d;
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/MULTIDRIVENPROC?v=latest
|
||||
... Use "/* verilator lint_off MULTIDRIVENPROC */" and lint_on around source to disable this message.
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_proc_bad.v:26:18: Signal has multiple driving blocks with different clocking: 't2.q'
|
||||
t/t_lint_multidriven_proc_bad.v:29:26: ... Location of first driving block
|
||||
29 | always @(posedge clka) q <= d;
|
||||
%Warning-MULTIDRIVEN: t/t_lint_multidriven_proc_bad.v:15:18: Signal has multiple driving blocks with different clocking: 'q2'
|
||||
t/t_lint_multidriven_proc_bad.v:67:26: ... Location of first driving block
|
||||
67 | always @(posedge clka) q <= d;
|
||||
| ^
|
||||
t/t_lint_multidriven_proc_bad.v:30:26: ... Location of other driving block
|
||||
30 | always @(posedge clkb) q <= ~d;
|
||||
t/t_lint_multidriven_proc_bad.v:68:26: ... Location of other driving block
|
||||
68 | always @(posedge clkb) q <= ~d;
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/MULTIDRIVEN?v=latest
|
||||
... Use "/* verilator lint_off MULTIDRIVEN */" and lint_on around source to disable this message.
|
||||
|
||||
@@ -11,18 +11,18 @@ import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
|
||||
# MULTIDRIVENPROC is off by default; enable it explicitly. Module 't' (same
|
||||
# clock) triggers it; module 't2' (different clocks) is reported by MULTIDRIVEN
|
||||
# instead, confirming MULTIDRIVENPROC is suppressed there.
|
||||
# -Wno-MULTITOP: both modules are top-level here on purpose (two independent
|
||||
# demonstrations), so silence the unrelated multiple-top-module warning.
|
||||
# MULTIDRIVENPROC is off by default; enable it explicitly.
|
||||
test.lint(fails=True,
|
||||
verilator_flags2=['-Wwarn-MULTIDRIVENPROC', '-Wno-MULTITOP'],
|
||||
verilator_flags2=['-Wwarn-MULTIDRIVENPROC'],
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.extract(in_filename=test.top_filename,
|
||||
out_filename=test.root + "/docs/gen/ex_MULTIDRIVENPROC_faulty.rst",
|
||||
lines="15-16")
|
||||
lines="53-54")
|
||||
|
||||
test.extract(in_filename=test.top_filename,
|
||||
out_filename=test.root + "/docs/gen/ex_MULTIDRIVENPROC_loopidx.rst",
|
||||
lines="81-89")
|
||||
|
||||
test.extract(in_filename=test.golden_filename,
|
||||
out_filename=test.root + "/docs/gen/ex_MULTIDRIVENPROC_msg.rst",
|
||||
|
||||
@@ -4,9 +4,47 @@
|
||||
// SPDX-FileCopyrightText: 2026 Aisha Salimgereyeva
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
|
||||
module t (
|
||||
input wire clk,
|
||||
input wire clka,
|
||||
input wire clkb,
|
||||
input wire d,
|
||||
input wire [3:0] dv,
|
||||
output logic q1,
|
||||
output logic q2,
|
||||
output logic [3:0] q3a,
|
||||
output logic [3:0] q3b,
|
||||
output logic [3:0] q3c
|
||||
);
|
||||
|
||||
t1 u1 (
|
||||
.clk(clk),
|
||||
.d (d),
|
||||
.q (q1)
|
||||
);
|
||||
|
||||
t2 u2 (
|
||||
.clka(clka),
|
||||
.clkb(clkb),
|
||||
.d (d),
|
||||
.q (q2)
|
||||
);
|
||||
|
||||
t3 u3 (
|
||||
.clk(clk),
|
||||
.d (dv),
|
||||
.q1 (q3a),
|
||||
.q2 (q3b),
|
||||
.q3 (q3c)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Same clock: two plain always blocks drive the whole of 'q', reported by
|
||||
// MULTIDRIVENPROC.
|
||||
module t (
|
||||
module t1 (
|
||||
input wire clk,
|
||||
input wire d,
|
||||
output logic q
|
||||
@@ -30,3 +68,28 @@ module t2 (
|
||||
always @(posedge clkb) q <= ~d;
|
||||
|
||||
endmodule
|
||||
|
||||
// A static loop induction variable should not warn.
|
||||
module t3 (
|
||||
input wire clk,
|
||||
input wire [3:0] d,
|
||||
output logic [3:0] q1,
|
||||
output logic [3:0] q2,
|
||||
output logic [3:0] q3
|
||||
);
|
||||
|
||||
integer i;
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (i = 0; i < 4; i = i + 1) q1[i] <= d[i];
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (i = 0; i < 4; i = i + 1) q2[i] <= ~d[i];
|
||||
end
|
||||
|
||||
always @* begin
|
||||
for (i = 0; i < 4; i = i + 1) q3[i] = d[i] ^ q1[i];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user