Repository navigation
[ImportVerilog] Support sequential user-defined primitives (UDPs) in circt::ImportVerilog (edge-sensitive and level-sensitive). - #11289
Conversation
|
Results of circt-tests run for bc98646 compared to results for 4f82d6f: sv-testsChanges in emitted diagnostics:
|
c9107d3 to
589fe72
Compare
|
Results of circt-tests run for 589fe72 compared to results for fec4477: sv-testsChanges in emitted diagnostics:
|
async-row support to come in follow-up change.
Expected behavior: Not supporting not 2-state edge.
async-row support to come in follow-up change.
Unrelated after UDP successful conversion. |
589fe72 to
f7e99fa
Compare
|
Besides the comment, I also made 3 changes: 1. add skipUnsupportedRow back for minimal change, 2. added back some change accidentally reverted 3. re-ordered test cases in .sv for better readability and consistency (some check rules also updated). |
f7e99fa to
632c3cc
Compare
|
Results of circt-tests run for 632c3cc compared to results for fec4477: sv-testsChanges in emitted diagnostics:
|
e6ab9a3 to
59d8d84
Compare
59d8d84 to
0d5c5c9
Compare
37bd594 to
1531728
Compare
|
Results of circt-tests run for 1531728 compared to results for 2d74cea: sv-testsChanges in emitted diagnostics:
|
|
@jpienaar @TaoBi22 @fabianschuiki Dear reviewers, would you have time for another review? Thanks in advance. |
1531728 to
3045efa
Compare
…circt::ImportVerilog (edge-sensitive and level-sensitive).
* Support sequential user-defined primitives (UDPs) in `circt::ImportVerilog` for both edge-sensitive (flip-flops, clock enables, dual-edge) and level-sensitive (asynchronous reset/preset, latches) models.
* In `classifySequentialTableRows`, filter non-functional entries (4-state simulation artifacts, explicit '-' holds, and idempotent state == output holds) and enforce 5 structural hardware requirements on surviving transitions:
1. Well-formed edge transitions:
a. At most one edge transition per table row.
b. Supported transition specifiers: each edge transition must specify a recognized 2-state edge token.
2. Single edge-sensitive port: all active edge transitions must share the same edge-sensitive clock port, diagnosing unsupported multi-clock UDPs.
3. No mixed sensitivity on edge-sensitive port: in edge-triggered models, active level-sensitive rows must specify '?' on the edge-sensitive clock pin, disallowing unsupported mixed latch/flip-flop models.
4. Pure asynchronous control: asynchronous clear/preset rows must not depend on internal state `q`, disallowing feedback loops in asynchronous control.
5. Separation of asynchronous control and synchronous data:
a. Asynchronous control pins cannot also act as varying synchronous data inputs (only dedicated clear/preset lines are supported).
b. Synchronous transitions cannot be conditioned on active asynchronous clear/preset levels.
* Correctly classify clock enables: ports that contain wildcards / don't-cares ('?') in any synchronous row are not misclassified as common clock enables (`syncEn`), but are instead preserved in the next-state logic (`computeSyncNextState`).
* In `buildAsyncConditions`, synthesize composite boolean conditions for clear and preset (`clearCond`, `presetCond`). Evaluate wildcards symmetrically across clear and preset rows to determine relative dominance (`presetDominates`).
* For clocked sequential primitives with dual clear and preset, lower clear and preset as direct asynchronous reset on the register via `asyncCond = clearCond | presetCond`, `asyncVal = presetCond`. This allows downstream synthesis and Deseq to infer a single `seq.firreg ... reset async (clear | preset), preset`, ensuring the register itself is asynchronously updated even when clocks are gated. For single asynchronous reset or preset, emit true asynchronous reset with constant value.
* For dual-edge triggered primitives (`BothEdges`), emit two independent single-edge procedures (`q_pos` on posedge and `q_neg` on negedge) driving separate state registers combined by a clock multiplexer (`q = (clk & q_pos) | (~clk & q_neg)`). This avoids multiple processes driving the same signal in LLHD, enabling downstream Deseq to extract two standard single-edge `seq.firreg` ops and allowing CIRCT clock inference and downstream simulation tools to execute dual-edge UDPs natively.
* In `emitSequentialLevelSensitiveProcedure`, emit `moore.procedure always_latch` for purely level-sensitive sequential UDPs (latches).
* Unify instantiation of combinational and sequential UDPs via `moore.instance`.
* Diagnostics:
* Add diagnostic error tests in `errors.sv` covering multi-clock UDPs (`udp_multi_clock`), steady-clock mixed latch/flip-flop transitions (`udp_mixed_latch`), and state-dependent asynchronous control (`udp_async_state_dep`).
* Tests:
* In `udp.sv`: Test posedge, negedge, clock-enable, benign hold rows, dual-edge flip-flops, dual-edge muxes, asymmetric condition UDPs (`udp_dff_asym_cond`), async reset (`udp_dff_async_rst`), async set/reset (`udp_dff_async_sr`), and generic active-low clear/preset (`udp_dff_async_clear_preset`).
* In `primitives.sv`: Expand sequential primitive suite with `udp_seq_dff`, `udp_seq_dff_neg`, `udp_seq_dff_en`, `udp_seq_dff_hold`, `udp_seq_dual_edge_dff`, `udp_seq_dual_edge_mux`, `udp_seq_dff_rst`, `udp_seq_dff_sr`, asymmetric condition UDPs (`udp_seq_asym_cond`), and generic `udp_seq_dff_clear_preset` along with instantiation test module `udp_seq_prim`.
3045efa to
6f95676
Compare
|
Results of circt-tests run for 6f95676 compared to results for 2d74cea: sv-testsChanges in emitted diagnostics:
|
@qiaozhang-pr it looks like this PR is adding a few things at once now and the diff has become quite big to review 😅 do you think it would be possible to split this up any further? (or trim it down at all - I'm a little surprised we need so much churn for this coverage but I guess there are a lot of corner cases?) |
This change includes the following:
circt::ImportVerilogfor both edge-sensitive (flip-flops, clock enables, dual-edge) and level-sensitive (asynchronous reset/preset, latches) models.classifySequentialTableRows, filter non-functional entries (4-state simulation artifacts, explicit '-' holds, and idempotent state == output holds) and enforce 5 structural hardware requirements on surviving transitions:a. At most one edge transition per table row.
b. Supported transition specifiers: each edge transition must specify a recognized 2-state edge token.
q, disallowing feedback loops in asynchronous control.a. Asynchronous control pins cannot also act as varying synchronous data inputs (only dedicated clear/preset lines are supported).
b. Synchronous transitions cannot be conditioned on active asynchronous clear/preset levels.
syncEn), but are instead preserved in the next-state logic (computeSyncNextState).buildAsyncConditions, synthesize composite boolean conditions for clear and preset (clearCond,presetCond). Evaluate wildcards symmetrically across clear and preset rows to determine relative dominance (presetDominates).asyncCond = clearCond | presetCond,asyncVal = presetCond. This allows downstream synthesis and Deseq to infer a singleseq.firreg ... reset async (clear | preset), preset, ensuring the register itself is asynchronously updated even when clocks are gated. For single asynchronous reset or preset, emit true asynchronous reset with constant value.BothEdges), emit two independent single-edge procedures (q_poson posedge andq_negon negedge) driving separate state registers combined by a clock multiplexer (q = (clk & q_pos) | (~clk & q_neg)). This avoids multiple processes driving the same signal in LLHD, enabling downstream Deseq to extract two standard single-edgeseq.firregops and allowing CIRCT clock inference and downstream simulation tools to execute dual-edge UDPs natively.emitSequentialLevelSensitiveProcedure, emitmoore.procedure always_latchfor purely level-sensitive sequential UDPs (latches).moore.instance.errors.svcovering multi-clock UDPs (udp_multi_clock), steady-clock mixed latch/flip-flop transitions (udp_mixed_latch), and state-dependent asynchronous control (udp_async_state_dep).udp.sv: Test posedge, negedge, clock-enable, benign hold rows, dual-edge flip-flops, dual-edge muxes, asymmetric condition UDPs (udp_dff_asym_cond), async reset (udp_dff_async_rst), async set/reset (udp_dff_async_sr), and generic active-low clear/preset (udp_dff_async_clear_preset).primitives.sv: Expand sequential primitive suite withudp_seq_dff,udp_seq_dff_neg,udp_seq_dff_en,udp_seq_dff_hold,udp_seq_dual_edge_dff,udp_seq_dual_edge_mux,udp_seq_dff_rst,udp_seq_dff_sr, asymmetric condition UDPs (udp_seq_asym_cond), and genericudp_seq_dff_clear_presetalong with instantiation test moduleudp_seq_prim.Note: This PR is follow-up of #11238.
Assisted-by: Antigravity:GeminiFlash