Skip to content

Conversation

@SamuelRiedel
Copy link
Contributor

@SamuelRiedel SamuelRiedel commented Oct 13, 2025

This PR adds support for the Zcb and Zcmp code-saving extensions. This support is implemented in a parameterizable way via the RV32ZC parameter, which allows choosing none, either, or both extensions. By default, both extensions are enabled because their combined hardware overhead is small, approximately 800 gate equivalents.

The Zcb extension introduces new compressed encodings for common instructions already supported in Ibex. The Zcmp extension introduces single compressed instructions that expand into multiple existing instructions within Ibex. For example, a stack push expands into multiple store instructions and a stack pointer update. Therefore, both extensions are implemented in the IF stage.

Adding these new instructions requires updates to the following components:

Missing Components and Known Issues:

  • The verification for the Zcmp's CMPP instructions (cm.push, cm.pop(ret(z))) is not fully working yet. The primary issue lies in the cosimulation interface with Spike. Checking multiple memory accesses that occur within a single step causes riscv-isa-sim to throw an error. Fixed.
  • This PR depends on Fix the riscv_dret_test #2338 to fix a DV error that is triggered with the new tests, but unrelated to the new changes. Merged
  • This PR depends on [dv] Use id_done to accurately track instruction monitor #2346 to fix a DV error that is triggered in the CI here, but unrelated to the new changes.
  • This PR currently disables the new Zcb/Zcmp checks with the latest few WIP commits. This is done to make the current regression tests work with the current compiler. The Zcb/Zcmp regressions will require the updated compiler.

Copy link
Contributor

@rswarbrick rswarbrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of nitty comments on the draft (sorry, but I'd started reading so thought I may as well review it properly...)

I really like this though! Thank you all so much for the improvement.

@SamuelRiedel
Copy link
Contributor Author

Lots of nitty comments on the draft (sorry, but I'd started reading so thought I may as well review it properly...)

I really like this though! Thank you all so much for the improvement.

Thank you for the feedback. Sorry for the delay in implementing it. I just pushed an updated version that should address all your comments.

@SamuelRiedel
Copy link
Contributor Author

Here are the regression results when running the full regression with the new compiler and the Zcb/Zcmp tests included. Note, those tests do not include the bitmanipulation tests, because the new compiler I used for testing doesn't support our curstom bitmanip versions.

Test NamePassingTotalPass Rate
riscv_arithmetic_basic_test 10 10 100.0%
riscv_machine_mode_rand_test 10 10 100.0%
riscv_rand_instr_test 10 10 100.0%
riscv_rand_jump_test 10 10 100.0%
riscv_jump_stress_test 10 10 100.0%
riscv_loop_test 10 10 100.0%
riscv_mmu_stress_test 10 10 100.0%
riscv_illegal_instr_test 15 15 100.0%
riscv_hint_instr_test 10 10 100.0%
riscv_ebreak_test 10 10 100.0%
riscv_debug_basic_test 9 10 90.0%
riscv_debug_stress_test 15 15 100.0%
riscv_debug_branch_jump_test 10 10 100.0%
riscv_debug_instr_test 25 25 100.0%
riscv_debug_wfi_test 10 10 100.0%
riscv_dret_test 5 5 100.0%
riscv_debug_ebreak_test 15 15 100.0%
riscv_debug_ebreakmu_test 14 15 93.3%
riscv_debug_csr_entry_test 10 10 100.0%
riscv_irq_in_debug_mode_test 10 10 100.0%
riscv_debug_in_irq_test 10 10 100.0%
riscv_assorted_traps_interrupts_debug_test 6 10 60.0%
riscv_single_interrupt_test 15 15 100.0%
riscv_multiple_interrupt_test 10 10 100.0%
riscv_nested_interrupt_test 10 10 100.0%
riscv_interrupt_instr_test 25 25 100.0%
riscv_interrupt_wfi_test 15 15 100.0%
riscv_interrupt_csr_test 10 10 100.0%
riscv_csr_test 5 5 100.0%
riscv_unaligned_load_store_test 5 5 100.0%
riscv_mem_error_test 15 15 100.0%
riscv_mem_intg_error_test 50 50 100.0%
riscv_debug_single_step_test 14 15 93.3%
riscv_reset_test 15 15 100.0%
riscv_rv32im_instr_test 5 5 100.0%
riscv_user_mode_rand_test 10 10 100.0%
riscv_umode_tw_test 10 10 100.0%
riscv_invalid_csr_test 10 10 100.0%
riscv_pmp_basic_test 50 50 100.0%
riscv_pmp_disable_all_regions_test 50 50 100.0%
riscv_pmp_out_of_bounds_test 50 50 100.0%
riscv_pmp_full_random_test 580 600 96.7%
riscv_pmp_region_exec_test 20 20 100.0%
riscv_epmp_mml_test 20 20 100.0%
riscv_epmp_mml_execute_only_test 20 20 100.0%
riscv_epmp_mml_read_only_test 20 20 100.0%
riscv_epmp_mmwp_test 20 20 100.0%
riscv_epmp_rlb_test 20 20 100.0%
riscv_zcb_balanced_test 20 20 100.0%
riscv_zcmp_balanced_test 20 20 100.0%
riscv_zcmp_directed_test 20 20 100.0%
riscv_debug_triggers_test 0 5 0.0%
Total 1378 1410 97.7%

Copy link
Contributor

@andreaskurth andreaskurth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTL changes LGTM, thanks @SamuelRiedel!

Just a couple of smaller points, then I'm happy to merge the RTL changes ahead of the DV changes

@SamuelRiedel
Copy link
Contributor Author

Thank you @andreaskurth for your feedback. As discussed offline, we split the RTL part into a separate PR #2347 and I implemented your feedback. It also includes a fix for the formal CI by disabling the newly added Zc extensions in the formal flow for now.

This PR is currently rebased on top of it and then adds all the DV environment.

The new DV still passes with the following full regression results:

Test NamePassingTotalPass Rate
riscv_arithmetic_basic_test 10 10 100.0%
riscv_machine_mode_rand_test 10 10 100.0%
riscv_rand_instr_test 10 10 100.0%
riscv_rand_jump_test 10 10 100.0%
riscv_jump_stress_test 10 10 100.0%
riscv_loop_test 10 10 100.0%
riscv_mmu_stress_test 10 10 100.0%
riscv_illegal_instr_test 15 15 100.0%
riscv_hint_instr_test 10 10 100.0%
riscv_ebreak_test 10 10 100.0%
riscv_debug_basic_test 10 10 100.0%
riscv_debug_stress_test 15 15 100.0%
riscv_debug_branch_jump_test 10 10 100.0%
riscv_debug_instr_test 25 25 100.0%
riscv_debug_wfi_test 10 10 100.0%
riscv_dret_test 5 5 100.0%
riscv_debug_ebreak_test 15 15 100.0%
riscv_debug_ebreakmu_test 14 15 93.3%
riscv_debug_csr_entry_test 10 10 100.0%
riscv_irq_in_debug_mode_test 10 10 100.0%
riscv_debug_in_irq_test 10 10 100.0%
riscv_assorted_traps_interrupts_debug_test 1 10 10.0%
riscv_single_interrupt_test 15 15 100.0%
riscv_multiple_interrupt_test 10 10 100.0%
riscv_nested_interrupt_test 10 10 100.0%
riscv_interrupt_instr_test 25 25 100.0%
riscv_interrupt_wfi_test 15 15 100.0%
riscv_interrupt_csr_test 10 10 100.0%
riscv_csr_test 5 5 100.0%
riscv_unaligned_load_store_test 5 5 100.0%
riscv_mem_error_test 15 15 100.0%
riscv_mem_intg_error_test 50 50 100.0%
riscv_debug_single_step_test 11 15 73.3%
riscv_reset_test 15 15 100.0%
riscv_rv32im_instr_test 5 5 100.0%
riscv_user_mode_rand_test 10 10 100.0%
riscv_umode_tw_test 10 10 100.0%
riscv_invalid_csr_test 10 10 100.0%
riscv_pmp_basic_test 50 50 100.0%
riscv_pmp_disable_all_regions_test 50 50 100.0%
riscv_pmp_out_of_bounds_test 49 50 98.0%
riscv_pmp_full_random_test 573 600 95.5%
riscv_pmp_region_exec_test 20 20 100.0%
riscv_epmp_mml_test 20 20 100.0%
riscv_epmp_mml_execute_only_test 20 20 100.0%
riscv_epmp_mml_read_only_test 20 20 100.0%
riscv_epmp_mmwp_test 20 20 100.0%
riscv_epmp_rlb_test 20 20 100.0%
riscv_zcb_balanced_test 20 20 100.0%
riscv_zcmp_balanced_test 20 20 100.0%
riscv_zcmp_directed_test 20 20 100.0%
riscv_debug_triggers_test 0 5 0.0%
Total 1363 1410 96.7%

This refactors `instr_vif` to use `rvfi_id_done` instead of
`instr_new_id` to track when a new instruction appears in the ID stage.
This interface and signal are only used to keep track of instruction
fetch errors by using the aforementioned valid signal and checking
whether the `rvfi_order_id` has changed. However, if an instruction
fetch error is consecutive to another error, `instr_new_id` will be
gated, which leads us to miss the `fetch_err` in the verification.

This will fix failing `riscv_mem_error_test`
Add a function and state to process multiple Ibex instructions that are
modeled as a single instruction in riscv-isa-sim. The current function
checks that the same registers are written overall.
Instead of stepping Spike once at the beginning of the expanded
instruction and then comparing each next operation with Spike's changes,
this commit logs all of Ibex's changes and then steps spike at the last
expanded instruction, i.e., the committing instruction. This then allows
checking a list of changes from Ibex with a list of changes from Spike.

The reason to do it this way around is that the memory access checks are
triggered by Spike. Therefore, when Spike steps through the expanded
instruction, it simultaneously checks all memory accesses. Previously,
only the first instructions on Ibex were executed at this stage and only
those memory accesses were visible. Now, Ibex will also have completed
the entire instruction and memory accesses, and the check initiated by
Spike will succeed.
Clean up once our changes are upstreamed
Update code from upstream repository
https://github.com/SamuelRiedel/riscv-dv to revision
71ceff7bb7d332fcf8037752ccdec19b33c2d210

Signed-off-by: Samuel Riedel <[email protected]>
Temporarily disable the Zcb/Zcmp tests while we wait to upgrade the
compiler. This ensures the CI can run regressions with the current
compiler to verify that we do not introduce breaking changes.
@SamuelRiedel SamuelRiedel changed the title Add Zcb and Zcmp extensions Add Zcb and Zcmp extensions DV Dec 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants