Add Zcb and Zcmp extensions
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:
- [x] Ibex RTL: Implemented in this PR
- [x] Documentation: Updated in this PR
- [ ] Verification: Implemented in this PR as well. Some missing parts still (see at the bottom)
- [x]
riscv-isa-sim(Spike): Updated Spike to support those new extensions https://github.com/lowRISC/riscv-isa-sim/pull/27 - [ ]
riscv-dv: Add both extensions to riscv-dv. We can either try to upstream those or create a fork. I didn't open a PR yet, but the diff is here: https://github.com/chipsalliance/riscv-dv/compare/master...SamuelRiedel:riscv-dv:zcbzcmp- [x] Support for Zcb extension
- [x] Support for the Zcmp's CMMV instructions
- [ ] Support for Zcmp's CMPP instructions
- [ ] Ibex co-simulation: Updated in this PR. Requires changes to get Zcmp's CMPP to work fully.
- [x] Support for Zcb extension
- [x] Support for the Zcmp's CMMV instructions
- [ ] Support for Zcmp's CMPP instructions
- [x]
- [ ] Compiler Support: We need to update the compiler to a version that supports the Zcb and Zcmp instructions. Currently, we are still on an rather old version. The latest RISC-V GCC and Clang support those instructions already.
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.
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.
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 Name | Passing | Total | Pass 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% |