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:
Geza Lore
2026-08-28 15:27:50 +02:00
committed by GitHub
parent 1ad9acd22e
commit c64afda7fc
7 changed files with 102 additions and 22 deletions
+13
View File
@@ -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 -2
View File
@@ -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;
| ^
+4
View File
@@ -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
View File
@@ -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
+11 -11
View File
@@ -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",
+64 -1
View File
@@ -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