While simulating large-scale processors using Arcilator, I've observed that the hw targets generated by firtool are heavily interleaved with SystemVerilog (sv) operations. While this is natural for the SystemVerilog backend, it creates significant overhead for non-SV backends.
As discussed in previous PRs (and following feedback from @fabianschuiki ), attempting to handle these SV ops within Arcilator leads to an unnecessarily bloated processing pipeline. Since CIRCT already provides the sim and verif dialects, we should leverage them to decouple simulation/verification semantics from the structural hardware description.
I have drafted a plan as part of the migration.
1. firrtl.attach -> hw.attach (or equivalent)
Currently, firrtl.attach often lowers directly to sv.alias or a complex all-pairs sv.assign matrix (wrapped in ifdef SYNTHESIS).
- Proposed Change: Introduce a structural
hw.attach op.
- Keep the "connectivity intent" in the
hw dialect. Move the decision of whether to emit an alias, an assign matrix, or a verbatim error into the HW-to-SV lowering phase.
2. Print-related Ops (printf, fprintf, fflush)
These currently generate SV always blocks during lowering.
- Proposed Change: Lower these to the
sim dialect.
- Additions to
sim Dialect:
- Support output stream specifiers (stdout vs. file descriptors) in
sim.print.
- Add
sim.get_file to manage file descriptors via filename mapping.
- Add
sim.fflush for stream synchronization.
- Only lower to SV
always blocks during the final Sim-to-SV phase.
3. Simulation Interventions (ref.force, ref.release)
These are purely simulation-level constructs and currently "leak" into SV always blocks early.
- Proposed Change: Lower to
sim.force and sim.release.
- These ops need support for Cross-Module References.
4. Cross-Module References (xmr.ref, xmr.deref)
- Proposed Change: Standardize on
sim.xmr.ref (or a similar intrinsic) referencing an hw.hierpath symbol. This provides a unified way for backends to track remote signals.
5. Verification Ops (assert, assume, cover)
Currently, these generate SV-specific logic (e.g., sv.always, sv.if) depending on the "flavor".
- Uniformly lower these to
verif.clocked_assert/assume/cover.
- Addition: Ensure message/format string support is fully integrated into the
verif dialect ops.
I intend to follow up on this work incrementally. This is not exhaustive for now and I would love to hear feedback on the proposed change.
While simulating large-scale processors using Arcilator, I've observed that the
hwtargets generated byfirtoolare heavily interleaved with SystemVerilog (sv) operations. While this is natural for the SystemVerilog backend, it creates significant overhead for non-SV backends.As discussed in previous PRs (and following feedback from @fabianschuiki ), attempting to handle these SV ops within Arcilator leads to an unnecessarily bloated processing pipeline. Since CIRCT already provides the
simandverifdialects, we should leverage them to decouple simulation/verification semantics from the structural hardware description.I have drafted a plan as part of the migration.
1.
firrtl.attach->hw.attach(or equivalent)Currently,
firrtl.attachoften lowers directly tosv.aliasor a complexall-pairs sv.assignmatrix (wrapped inifdef SYNTHESIS).hw.attachop.hwdialect. Move the decision of whether to emit analias, anassignmatrix, or averbatimerror into the HW-to-SV lowering phase.2. Print-related Ops (
printf,fprintf,fflush)These currently generate SV
alwaysblocks during lowering.simdialect.simDialect:sim.print.sim.get_fileto manage file descriptors via filename mapping.sim.fflushfor stream synchronization.alwaysblocks during the final Sim-to-SV phase.3. Simulation Interventions (
ref.force,ref.release)These are purely simulation-level constructs and currently "leak" into SV
alwaysblocks early.sim.forceandsim.release.4. Cross-Module References (
xmr.ref,xmr.deref)sim.xmr.ref(or a similar intrinsic) referencing anhw.hierpathsymbol. This provides a unified way for backends to track remote signals.5. Verification Ops (
assert,assume,cover)Currently, these generate SV-specific logic (e.g.,
sv.always,sv.if) depending on the "flavor".verif.clocked_assert/assume/cover.verifdialect ops.I intend to follow up on this work incrementally. This is not exhaustive for now and I would love to hear feedback on the proposed change.