Line 123... |
Line 123... |
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums:
|
:sectnums:
|
=== RISC-V Compatibility
|
=== RISC-V Compatibility
|
|
|
The NEORV32 CPU passes the rv32_m/I, rv32_m/M, rv32_m/C, rv32_m/privilege, and
|
The NEORV32 CPU passes the tests of the _RISC-V Architecture Test Framework_. This framework is used to check
|
rv32_m/Zifencei tests of the official RISC-V Architecture Tests (GitHub). The port files for the
|
RISC-V implementations for compatibility with the official RISC-V ISA specifications.
|
NEORV32 processor are located in the repository's `sw/isa-test` folder.
|
The NEORV32 port of this test framework has been moved to a separate repository:
|
|
https://github.com/stnolting/neorv32-verif
|
[NOTE]
|
|
See section https://stnolting.github.io/neorv32/ug/#_risc_v_architecture_test_framework[User Guide: RISC-V Architecture Test Framework]
|
|
for information how to run the tests on the NEORV32.
|
|
|
|
.**RISC-V `rv32_m/C` Tests**
|
.**RISC-V `rv32_m/C` Tests**
|
...................................
|
...................................
|
Check cadd-01 ... OK
|
Check cadd-01 ... OK
|
Check caddi-01 ... OK
|
Check caddi-01 ... OK
|
Line 178... |
Line 175... |
Check bgeu-01 ... OK
|
Check bgeu-01 ... OK
|
Check blt-01 ... OK
|
Check blt-01 ... OK
|
Check bltu-01 ... OK
|
Check bltu-01 ... OK
|
Check bne-01 ... OK
|
Check bne-01 ... OK
|
Check fence-01 ... OK
|
Check fence-01 ... OK
|
Check jal-01 ... OK
|
Check jal-01 ... IGNORED <1>
|
Check jalr-01 ... OK
|
Check jalr-01 ... OK
|
Check lb-align-01 ... OK
|
Check lb-align-01 ... OK
|
Check lbu-align-01 ... OK
|
Check lbu-align-01 ... OK
|
Check lh-align-01 ... OK
|
Check lh-align-01 ... OK
|
Check lhu-align-01 ... OK
|
Check lhu-align-01 ... OK
|
Line 208... |
Line 205... |
Check xori-01 ... OK
|
Check xori-01 ... OK
|
Check fence-01 ... OK
|
Check fence-01 ... OK
|
--------------------------------
|
--------------------------------
|
OK: 39/39 RISCV_TARGET=neorv32 RISCV_DEVICE=I XLEN=32
|
OK: 39/39 RISCV_TARGET=neorv32 RISCV_DEVICE=I XLEN=32
|
...................................
|
...................................
|
|
<1> Test is skipped due to a GHDL simulation issue.
|
|
|
.**RISC-V `rv32_m/M` Tests**
|
.**RISC-V `rv32_m/M` Tests**
|
...................................
|
...................................
|
Check div-01 ... OK
|
Check div-01 ... OK
|
Check divu-01 ... OK
|
Check divu-01 ... OK
|
Line 657... |
Line 655... |
|
|
The "wait for interrupt instruction" `wfi` acts like a sleep command. When executed, the CPU is
|
The "wait for interrupt instruction" `wfi` acts like a sleep command. When executed, the CPU is
|
halted until a valid interrupt request occurs. To wake up again, at least one interrupt source has to
|
halted until a valid interrupt request occurs. To wake up again, at least one interrupt source has to
|
be enabled via the <<_mie>> CSR and the global interrupt enable flag in <<_mstatus>> has to be set.
|
be enabled via the <<_mie>> CSR and the global interrupt enable flag in <<_mstatus>> has to be set.
|
|
|
If the <<_mstatus>> `TW` bis is cleared the `wfi` instruction is also allowed to execute when in user-mode.
|
[NOTE]
|
This is always the case if user-mode is not implemented. If the `TW` bit is set the execution of `wfi` in
|
Executing the `wfi` instruction is user-mode will raise an illegal instruction exception if
|
user-mode will raise an illegal instruction exception.
|
<<_mstatus>>.`TW` is set.
|
|
|
|
|
==== **`Zicntr`** CPU Base Counters
|
==== **`Zicntr`** CPU Base Counters
|
|
|
The `Zicntr` ISA extension adds the basic cycle `[m]cycle[h]`), instruction-retired (`[m]instret[h]`) and time (`time[h]`)
|
The `Zicntr` ISA extension adds the basic cycle `[m]cycle[h]`), instruction-retired (`[m]instret[h]`) and time (`time[h]`)
|
Line 837... |
Line 835... |
| Class | ISA | Instruction(s) | Execution cycles
|
| Class | ISA | Instruction(s) | Execution cycles
|
| ALU | `I/E` | `addi` `slti` `sltiu` `xori` `ori` `andi` `add` `sub` `slt` `sltu` `xor` `or` `and` `lui` `auipc` | 2
|
| ALU | `I/E` | `addi` `slti` `sltiu` `xori` `ori` `andi` `add` `sub` `slt` `sltu` `xor` `or` `and` `lui` `auipc` | 2
|
| ALU | `C` | `c.addi4spn` `c.nop` `c.addi` `c.li` `c.addi16sp` `c.lui` `c.andi` `c.sub` `c.xor` `c.or` `c.and` `c.add` `c.mv` | 2
|
| ALU | `C` | `c.addi4spn` `c.nop` `c.addi` `c.li` `c.addi16sp` `c.lui` `c.andi` `c.sub` `c.xor` `c.or` `c.and` `c.add` `c.mv` | 2
|
| ALU | `I/E` | `slli` `srli` `srai` `sll` `srl` `sra` | 3 + SAfootnote:[Shift amount.]/4 + SA%4; FAST_SHIFTfootnote:[Barrel shift when `FAST_SHIFT_EN` is enabled.]: 4; TINY_SHIFTfootnote:[Serial shift when `TINY_SHIFT_EN` is enabled.]: 2..32
|
| ALU | `I/E` | `slli` `srli` `srai` `sll` `srl` `sra` | 3 + SAfootnote:[Shift amount.]/4 + SA%4; FAST_SHIFTfootnote:[Barrel shift when `FAST_SHIFT_EN` is enabled.]: 4; TINY_SHIFTfootnote:[Serial shift when `TINY_SHIFT_EN` is enabled.]: 2..32
|
| ALU | `C` | `c.srli` `c.srai` `c.slli` | 3 + SAfootnote:[Shift amount (0..31).]; FAST_SHIFTfootnote:[Barrel shifter when `FAST_SHIFT_EN` is enabled.]:
|
| ALU | `C` | `c.srli` `c.srai` `c.slli` | 3 + SAfootnote:[Shift amount (0..31).]; FAST_SHIFTfootnote:[Barrel shifter when `FAST_SHIFT_EN` is enabled.]:
|
| Branches | `I/E` | `beq` `bne` `blt` `bge` `bltu` `bgeu` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
|
| Branches | `I/E` | `beq` `bne` `blt` `bge` `bltu` `bgeu` | Taken: 5 + (ML-1)footnote:[Memory latency.]; Not taken: 3
|
| Branches | `C` | `c.beqz` `c.bnez` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
|
| Branches | `C` | `c.beqz` `c.bnez` | Taken: 5 + (ML-1); Not taken: 3
|
| Jumps / Calls | `I/E` | `jal` `jalr` | 4 + ML
|
| Jumps / Calls | `I/E` | `jal` `jalr` | 5 + (ML-1)
|
| Jumps / Calls | `C` | `c.jal` `c.j` `c.jr` `c.jalr` | 4 + ML
|
| Jumps / Calls | `C` | `c.jal` `c.j` `c.jr` `c.jalr` | 5 + (ML-1)
|
| Memory access | `I/E` | `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw` | 4 + ML
|
| Memory access | `I/E` | `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw` | 5 + (ML-2)
|
| Memory access | `C` | `c.lw` `c.sw` `c.lwsp` `c.swsp` | 4 + ML
|
| Memory access | `C` | `c.lw` `c.sw` `c.lwsp` `c.swsp` | 5 + (ML-2)
|
| Memory access | `A` | `lr.w` `sc.w` | 4 + ML
|
| Memory access | `A` | `lr.w` `sc.w` | 5 + (ML-2)
|
| Multiplication | `M` | `mul` `mulh` `mulhsu` `mulhu` | 2+32+2; FAST_MULfootnote:[DSP-based multiplication; enabled via `FAST_MUL_EN`.]: 4
|
| MulDiv | `M` | `mul` `mulh` `mulhsu` `mulhu` | 2+32+2; FAST_MULfootnote:[DSP-based multiplication; enabled via `FAST_MUL_EN`.]: 4
|
| Division | `M` | `div` `divu` `rem` `remu` | 2+32+2
|
| MulDiv | `M` | `div` `divu` `rem` `remu` | 2+32+2
|
| CSR access | `Zicsr` | `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci` | 3
|
| System | `Zicsr` | `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci` | 3
|
| System | `I/E` | `fence` | 3
|
|
| System | `Zicsr` | `ecall` `ebreak` | 3
|
| System | `Zicsr` | `ecall` `ebreak` | 3
|
| System | `Zicsr`+`C` | `c.break` | 3
|
| System | `Zicsr`+`C` | `c.break` | 3
|
| System | `Zicsr` | `mret` `wfi` | 6
|
| System | `Zicsr` | `wfi` | 3
|
| System | `Zifencei` | `fence.i` | 3 + ML
|
| System | `Zicsr` | `mret` `dret` | 5
|
|
| Fence | `I/E` | `fence` | 4 + ML
|
|
| Fence | `Zifencei` | `fence.i` | 4 + ML
|
| Floating-point - artihmetic | `Zfinx` | `fadd.s` | 110
|
| Floating-point - artihmetic | `Zfinx` | `fadd.s` | 110
|
| Floating-point - artihmetic | `Zfinx` | `fsub.s` | 112
|
| Floating-point - artihmetic | `Zfinx` | `fsub.s` | 112
|
| Floating-point - artihmetic | `Zfinx` | `fmul.s` | 22
|
| Floating-point - artihmetic | `Zfinx` | `fmul.s` | 22
|
| Floating-point - compare | `Zfinx` | `fmin.s` `fmax.s` `feq.s` `flt.s` `fle.s` | 13
|
| Floating-point - compare | `Zfinx` | `fmin.s` `fmax.s` `feq.s` `flt.s` `fle.s` | 13
|
| Floating-point - misc | `Zfinx` | `fsgnj.s` `fsgnjn.s` `fsgnjx.s` `fclass.s` | 12
|
| Floating-point - misc | `Zfinx` | `fsgnj.s` `fsgnjn.s` `fsgnjx.s` `fclass.s` | 12
|
Line 869... |
Line 868... |
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
|
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
|
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
|
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
|
| Bit-manipulation - carry-less multiply | `B(Zbc)` | `clmul` `clmulh` `clmulr` | 3 + 32
|
| Bit-manipulation - carry-less multiply | `B(Zbc)` | `clmul` `clmulh` `clmulr` | 3 + 32
|
| Custom instructions (CFU) | `Zxcfu` | - | min. 4
|
| Custom instructions (CFU) | `Zxcfu` | - | min. 4
|
| | | |
|
| | | |
|
| _Illegal instructions_ | `Zicsr` | - | 2
|
| _Illegal instructions_ | `Zicsr` | - | min. 2
|
|=======================
|
|=======================
|
|
|
[NOTE]
|
[NOTE]
|
The presented values of the *floating-point execution cycles* are average values - obtained from
|
The presented values of the *floating-point execution cycles* are average values - obtained from
|
4096 instruction executions using pseudo-random input values. The execution time for emulating the
|
4096 instruction executions using pseudo-random input values. The execution time for emulating the
|
Line 972... |
Line 971... |
| Prio. | `mcause` | [RISC-V] | ID [C] | Cause | `mepc` | `mtval`
|
| Prio. | `mcause` | [RISC-V] | ID [C] | Cause | `mepc` | `mtval`
|
7+^| **Synchronous Exceptions**
|
7+^| **Synchronous Exceptions**
|
| 1 | `0x00000000` | 0.0 | _TRAP_CODE_I_MISALIGNED_ | instruction address misaligned | **PC** | **ADR**
|
| 1 | `0x00000000` | 0.0 | _TRAP_CODE_I_MISALIGNED_ | instruction address misaligned | **PC** | **ADR**
|
| 2 | `0x00000001` | 0.1 | _TRAP_CODE_I_ACCESS_ | instruction access bus fault | **PC** | **ADR**
|
| 2 | `0x00000001` | 0.1 | _TRAP_CODE_I_ACCESS_ | instruction access bus fault | **PC** | **ADR**
|
| 3 | `0x00000002` | 0.2 | _TRAP_CODE_I_ILLEGAL_ | illegal instruction | **PC** | **INST**
|
| 3 | `0x00000002` | 0.2 | _TRAP_CODE_I_ILLEGAL_ | illegal instruction | **PC** | **INST**
|
| 4 | `0x0000000B` | 0.11 | _TRAP_CODE_MENV_CALL_ | environment call from M-mode | **PC** | **0**
|
| 4 | `0x0000000B` | 0.11 | _TRAP_CODE_MENV_CALL_ | environment call from M-mode (`ecall`) | **PC** | **0**
|
| 5 | `0x00000008` | 0.8 | _TRAP_CODE_UENV_CALL_ | environment call from U-mode | **PC** | **0**
|
| 5 | `0x00000008` | 0.8 | _TRAP_CODE_UENV_CALL_ | environment call from U-mode (`ecall`) | **PC** | **0**
|
| 6 | `0x00000003` | 0.3 | _TRAP_CODE_BREAKPOINT_ | breakpoint instruction | **PC** | **PC**
|
| 6 | `0x00000003` | 0.3 | _TRAP_CODE_BREAKPOINT_ | software breakpoint (`ebreak`) | **PC** | **0**
|
| 7 | `0x00000006` | 0.6 | _TRAP_CODE_S_MISALIGNED_ | store address misaligned | **PC** | **ADR**
|
| 7 | `0x00000006` | 0.6 | _TRAP_CODE_S_MISALIGNED_ | store address misaligned | **PC** | **ADR**
|
| 8 | `0x00000004` | 0.4 | _TRAP_CODE_L_MISALIGNED_ | load address misaligned | **PC** | **ADR**
|
| 8 | `0x00000004` | 0.4 | _TRAP_CODE_L_MISALIGNED_ | load address misaligned | **PC** | **ADR**
|
| 9 | `0x00000007` | 0.7 | _TRAP_CODE_S_ACCESS_ | store access bus fault | **PC** | **ADR**
|
| 9 | `0x00000007` | 0.7 | _TRAP_CODE_S_ACCESS_ | store access bus fault | **PC** | **ADR**
|
| 10 | `0x00000005` | 0.5 | _TRAP_CODE_L_ACCESS_ | load access bus fault | **PC** | **ADR**
|
| 10 | `0x00000005` | 0.5 | _TRAP_CODE_L_ACCESS_ | load access bus fault | **PC** | **ADR**
|
7+^| **Asynchronous Exceptions (Interrupts)**
|
7+^| **Asynchronous Exceptions (Interrupts)**
|