Rewrote V3LifePost to not depend on having AstAssignPre and
AstAssignPost types, but work with generic AstNodeAssign. There is an
extra flag in AstVarScope to denote it's part of an NBA and should be
considered.
Step towards #6280.
NBAs targeting a variable in a different scope are now allocated
temporary variables for captured values in the scope of the NBA, not the
scope of the target variable.
Fixes#6286
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 happened to work before #5516, by creating a whole shadow copy of
the entire array. Revert back to that behaviour for now, it will be
slow, but works still.
Fixes#5590
An ordering constraint between NBA commit blocks ('Post' logic) and the
written variable were previously added as soft constraints (cutable
edges). However these are required for correctness, so if it ever is
cut we will have incorrect simulation results.
Change these into hard constraints instead. This necessitates adding a
flag on AstVar to ignore special variables constructed during V3Delayed
that might otherwise appear as degenerate logic loops. E.g.:
if (VdlySet) {
VdlySet = 0; // <- This write to VdlySet can and must be ignored
LHS = VdlyVal;
}
No functional change, but you might get an error if this constraint was
ever violated. (Theoretically it should never be, as these variables
were inserted in a way that does not require violating these constraints
...)
* Refactor V3Delay for extensibility
Introduce the concept of an "NBA Scheme", which is the lowering pattern
we can use for various variables that are the targets of NBAs.
E.g.:
- ShadowVariable (old default scheme)
- FlagShared (old array set flag scheme)
- ValueQueueWhole (recent dynamic commit queue)
We now analyse all AstAssignDly before making any decisions on which
scheme to apply. We then choose a specific scheme for each variable that
is the target of an NBA, and then all NBAs targeting that variable use
the same scheme. This enables easy mix and match of schemes as needed,
while remaining consistent by design after extensions.
Output is perturbed due to node insertion order, but no functional
or performance change is intended.
For NBAs that might execute a dynamic number of times in a single
evaluation (specifically: those that assign to array elements inside
loops), we introduce a new run-time VlNBACommitQueue data-structure
(currently a vector), which stores all pending updates and the necessary
info to reconstruct the LHS reference of the AstAssignDly at run-time.
All variables needing a commit queue has their corresponding unique
commit queue.
All NBAs to a variable that requires a commit queue go through the
commit queue. This is necessary to preserve update order in sequential
code, e.g.:
a[7] <= 10
for (int i = 1 ; i < 10; ++i) a[i] <= i;
a[2] <= 10
needs to end with array elements 1..9 being 1, 10, 3, 4, 5, 6, 7, 8, 9.
This enables supporting common forms of NBAs to arrays on the left hand
side of <= in non-suspendable/non-fork code. (Suspendable/fork
implementation is unclear to me so I left it unchanged, see #5084).
Any NBA that does not need a commit queue (i.e.: those that were
supported before), use the same scheme as before, and this patch should
have no effect on the generated code for those NBAs.
No functional change. Postpone the conversion of all AstAssignDlys that
use the 'VdlySet' scheme for array LHSs until after the complete
traversal of the netlist. The next patch takes advantage of this by
using some extra information also gathered through the traversal to
change the conversion.
AstAssignDlys inside suspendable or fork are not deferred and are
processed identical to the previous version.
There are some TODOs in this patch that are fixed in the next patch.
Output code perturbed due to variable ordering.
MULTIDRIVEN message ordering perturbed due to processing order change.
No functional change.
This patch is just cleanup with some non-functional changes to enable
the next patch. Most importantly createDlyOnSet, which implements NBAs
for arrays, has a new streamlined implementation that does the same
thing. Some output code is perturbed due to statement/local variable
insertion order.
Also renamed Vdlyvfoo to VdlyFoo for easier readability of the generated
code.
Checking the wrong node meant we never actually pushed constant
bit-select indices into the delayed update, as was the intention, but
always generated a temporary instead.
This saves about 5% memory. V3AstUserAllocator is appropriate for most use
cases, performance is marginally up as we are mostly D-cache bound on
large designs.
The typical find/if-not-exists-insert pattern can be achieved with 1
lookup instead of 2 using emplace with a sentinel value. Also maps value
initialize their values when inserted with the [] operator, this is
defined and so there is no need to explicitly insert zeroes for integer
values.