Safely support non-overlapping blocking/non-blocking assignments (#6137)

The manual for the BLKANDNBLK warning describes that it is safe to
disable that error if the updated ranges are non-overlapping. This
however was not true (see the added t_nba_mixed_update* tests).

In this patch we change V3Delayed to use a new ShadowVarMasked
scheme for variables that have mixed blocking and non-blocking 
updates (or the FlagUnique scheme for unpacked variables), which
is in fact safe to use when the updated parts are non-overlapping.

Furthermore, mixed assignments are safe as far as scheduling is
concerned if either:

- They are to independent parts (bits/members/etc) (with this patch)
- Or if the blocking assignment is in clocked (or suspendable) logic.

The risk in scheduling is a race between the Post scheduled NBA
commit, and blocking assignments in combinational logic, which might
order incorrectly.

The second point highlights that we can handle stuff like this safely,
which is sometimes used in testbenches:

```systemverilog
always @(posedge clk) begin
    if ($time == 0) a = 0;
end

always @(posedge clk) begin
    if ($time > 0) a <= 2;
end
````

The only dangerous case is:

```systemverilog
always @(posedge clk) foo[idx] <= val;
assign foo[0] = bar;
```

Whit this patch, this will still resolve fine at run-time if 'idx' is
never zero, but might resolve incorrectly if 'idx' is zero.

With the above in mind, the BLKANDNBLK warning is now only issued if:

- We can't prove that the assignments are to non-overlapping bits
- And the blocking assignment is in combinational logic

These are the cases that genuinely require user attention to resolve.

With this patch, there are no more BLKANDNBLK warnings in the RTLMeter
designs.

Fixes #6122.
This commit is contained in:
Geza Lore
2025-06-28 20:45:45 +01:00
committed by GitHub
parent b914cda1c7
commit bc892deacc
22 changed files with 521 additions and 100 deletions
+16 -7
View File
@@ -211,23 +211,32 @@ List Of Warnings
public task, or when the blocking and non-blocking assignments have
non-overlapping bits and structure members.
From Verilator 5.038, this warning is only issued when Verilator can't prove that
the assignments are to non-overlapping sub-parts, and the blocking
assignment is in combinational logic (which is the case where simulation
results might differ from other simulators). Review any BLKANDNBLK
cases carefully after this version, and sign them off as
described above, only if know for sure the updates are not to overlapping
parts of the signal.
Generally, this is caused by a register driven by both combo logic and a
flop:
.. code-block:: sv
logic [1:0] foo;
always @(posedge clk) foo[0] <= ...
always_comb foo[1] = ...
logic [3:0] foo;
always @(posedge clk) foo[index] <= ... // With index != 0
always_comb foo[0] = ...
Instead, use a different register for the flop:
.. code-block:: sv
logic [1:0] foo;
always @(posedge clk) foo_flopped[0] <= ...
always_comb foo[0] = foo_flopped[0];
always_comb foo[1] = ...
logic [3:0] foo;
logic [3:1] foo_flopped;
always @(posedge clk) foo_flopped[index] <= ... // With index != 0
always_comb foo[0] = ...
always_comb foo[3:1] = foo_flopped;
Or, this may also avoid the error: