Basically did
set(CMAKE_CXX_CLANG_TIDY local/clang-tidy -checks=-*,llvm-use-new-mlir-op-builder -fix)
and then fixed cases where temporary OpBuilders were used (as passed in
by reference now).
This PR introduces a new assert property op to the sv dialect and uses that as an intermediary for property assertion emission. This should solve the issue of the polarity being different in SV and in verif for the enable signals ( enable in verif, disable in sv ).
This PR adds DPI func/call op and SimToSV lowering.
`sim.dpi.func` is a just bridge to `sv.func`. This op can be lowered into `func.func` in the future for Arc integration.
`sim.func.dpi.call` represents SystemVerilog DPI function call. There are two optional operands `clock` and `enable`.
If `clock` is not provided, the callee is invoked when input values are changed. If provided, the dpi function is called at clock's posedge. The result values behave like registers and the DPI function is used as a state transfer function of them. `enable` operand is used to conditionally call the DPI since DPI call could be quite more expensive than native constructs. When `enable` is low, results of unclocked calls are undefined and in SV results they are lowered into `X`. Users are expected to gate result values by another `enable` to model a default value of results. For clocked calls, a low enable means that its register state transfer function is not called. Hence their values will not be modify in that clock.
A function that returns an explicit return is not supported yet.
Add the `verif.has_been_reset` operation to detect if a circuit has been
properly reset. Useful to disable assertions before and during reset.
The result of `verif.has_been_reset` reads as 0 immediately after
simulation startup and after each power-cycle in a power-aware
simulation. The result remains 0 before and during reset and only
switches to 1 after the reset is deasserted again.
This is a useful utility to disable the evaluation of assertions and
other verification constructs in the IR before the circuit being tested
has been properly reset. Verification failures due to uninitialized or
randomized initial state can thus be prevented.
Using the result of `verif.has_been_reset` to enable verification is
more powerful and proper than just disabling verification during reset.
The latter does not properly handle the period of time between
simulation startup or power-cycling and the start of reset.
`verif.has_been_reset` is guaranteed to produce a 0 value in that
period, as well as during the reset.
Example:
```
hw.module @HasBeenResetAsync(%clock: i1, %reset: i1) -> (out: i1) {
%0 = verif.has_been_reset %clock, async %reset
hw.output %0 : i1
}
```
The above produces the following Verilog:
```
module HasBeenResetAsync(input clock, reset, output out);
reg hasBeenResetReg;
initial begin
if (reset)
hasBeenResetReg = 1'h1;
else
hasBeenResetReg = 1'bx;
end
always @(posedge reset) hasBeenResetReg <= 1'h1;
assign out = hasBeenResetReg === 1'h1 & reset === 1'h0;
endmodule
```
*Future work:* This is a verification-only construct. It lowers to a
register that will not behave in the right way in actual silicon. Tools
like `firtool` may need a linting pass that ensures the results of this
op don't leak into synthesizable parts of the IR.
#5577, #5575
Re. the lowering; `verif.print` lowers directly to a `sv.fwrite` via. inspection of its source operand (which is expected to be a `verif.format_verilog_string`). The source `format_verilog_string` is `not` deleted in the process (there may be other users). However, i marked `verif.format_verilog_string` as `Pure` meaning that it'll get removed if `canonicalize` is run after `lower-verif-to-sv` and there are no more users of the result.
It's expected that `verif.print` will reside inside *something* that eventually lowers to a procedural SV region, if one is going the SV route. I'd imagine that most users will embed `verif.print` inside `hw.triggered` regions.