[Sim] Create clocked and procedural sim.exit/pause ops#8893
Conversation
fzi-hielscher
left a comment
There was a problem hiding this comment.
LGTM, just a few pedantic comments.
Apologies for soapboxing, but when I was writing the SV lowering for sim.triggered I got frustrated by attempting to prettify ifs to the point where I ended up adding the sim.trigger_gate operation, see #7973. Thereby a trigger value encodes both the clock and the condition. That allowed me to relatively easily shuffle and merge conditions as part of the canonicalizers:
https://github.com/fzi-hielscher/circt/blob/triggers-2025-squashed/lib/Dialect/Sim/SimOps.cpp#L753
The whole triggered thing was very much aimed at FIRRTL lowering, but since there does not appear to be a consensus on how to handle simulation procedures in FIRRTL yet, it is still up in the air. I assumed that the ImportVerilog pipeline would exclusively rely on LLHD for all sorts of control flow handling, but maybe sim.triggered could be useful there too?
Incidentally, I've also rewritten the arcilator support for sim.triggered a while ago. Based on your new LowerState pass that turned out to be pleasingly simple:
https://github.com/fzi-hielscher/circt/blob/triggers-2025-squashed/lib/Dialect/Arc/Transforms/LowerState.cpp
| // If there was no pre-existing guard, create one. | ||
| if (!block) { | ||
| OpBuilder builder(op); | ||
| if (op->getParentOp()->hasTrait<sv::ProceduralRegion>()) |
There was a problem hiding this comment.
Is this sufficient at this point? What if the parent op has not been lowered to SV yet, but will become a procedural region? I've been struggling in the past with the lack of a cross-dialect notion of procedural regions.
There was a problem hiding this comment.
I think it is, at least for now. We only ever nest into ifdefs and always processes, which implement the trait. And the verification of SV ops simply checks if the parent has one of these traits.
Maybe we should just switch over to checking if the parent is a graph region or not 🤔, which is universal across dialects, instead of relying on an SV trait.
4b8749d to
d79a0f3
Compare
|
@fzi-hielscher Yeah I also don't like that we have all these clocked and unclocked flavors of ops. 😞. How about we start by just factoring the clock and condition operand out into a surrounding op in the Sim dialect? Basically a trivial version of |
Combine the existing `sim.finish` and `sim.fatal` ops into a single `sim.clocked_exit` op. Create a `sim.exit` op for the procedural case. This op now accepts a `success` operand to indicate whether the simulation should terminate with a success or failure exit code, and a `verbose` operand to indicate whether the exit should behave like a `$finish(0)` or a `$finish(1)` in SystemVerilog. Also add a `sim.pause` and `sim.clocked_pause` operation which only suspends simulation and gives control back to the user in an interactive simulation. This corresponds to `$stop` in SystemVerilog. These new ops will allow circt-verilog to lower `$finish`, `$fatal`, `$stop`, and `$exit` in the input. Adjust the Sim-to-SV conversion pass to support the new operations. Also try to reuse existing ifdef and always/if ops, effectively combining multiple consecutive Sim ops into a single ifdef guard or always process.
d79a0f3 to
5e18c07
Compare
Combine the existing
sim.finishandsim.fatalops into a singlesim.clocked_exitop. Create asim.exitop for the procedural case. This op now accepts asuccessoperand to indicate whether the simulation should terminate with a success or failure exit code, and averboseoperand to indicate whether the exit should behave like a$finish(0)or a$finish(1)in SystemVerilog.Also add a
sim.pauseandsim.clocked_pauseoperation which only suspends simulation and gives control back to the user in an interactive simulation. This corresponds to$stopin SystemVerilog.These new ops will allow circt-verilog to lower
$finish,$fatal,$stop, and$exitin the input.Adjust the Sim-to-SV conversion pass to support the new operations. Also try to reuse existing ifdef and always/if ops, effectively combining multiple consecutive Sim ops into a single ifdef guard or always process.