diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a3ea98b..e437f5d12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12 | Date (*dd.mm.yyyy*) | Version | Comment | |:-------------------:|:-------:|:--------| +| 17.03.2023 | 1.8.2.5 | add RISC-V `time[h]` CSRs (part of the `Zicntr` ISA extension); [#556](https://github.com/stnolting/neorv32/pull/556) | | 17.03.2023 | 1.8.2.4 | re-add VHDL process names; [#555](https://github.com/stnolting/neorv32/pull/555) | | 15.03.2023 | 1.8.2.3 | rtl reworks, cleanups and optimizations; [#550](https://github.com/stnolting/neorv32/pull/550) | | 11.03.2023 | 1.8.2.2 | :sparkles: add support for RISC-V `Zicond` ISA extension (conditional operations); [#546](https://github.com/stnolting/neorv32/pull/546) | diff --git a/docs/datasheet/cpu.adoc b/docs/datasheet/cpu.adoc index e7ba58782..c0f25e677 100644 --- a/docs/datasheet/cpu.adoc +++ b/docs/datasheet/cpu.adoc @@ -459,10 +459,16 @@ code (see `sw/example/floating_point_test`). ==== `Zicntr` ISA Extension -The `Zicntr` ISA extension adds the basic cycle <<_cycleh>>, <<_mcycleh>> and instruction-retired -<<_instreth>>, <<_minstreth>> counters. This extensions is stated as _mandatory_ by the RISC-V spec. -However, area-constrained setups may remove support for these counters. Section <<_machine_counter_and_timer_csrs>> -shows a list of all `Zicntr`-related CSRs. +The `Zicntr` ISA extension adds the basic <<_cycleh>>, <<_mcycleh>>, <<_timeh>> and <<_instreth>>, <<_minstreth>> +counter CSRs. Section <<_machine_counter_and_timer_csrs>> shows a list of all `Zicntr`-related CSRs. + +[NOTE] +Note that the <<_timeh>> CSRs are implemented as just another user-level shadow copy of the machine-mode cycle +counters <<_mcycleh>> (just like <<_cycleh>>). + +[NOTE] +This extensions is stated as _mandatory_ by the RISC-V spec. However, area-constrained setups may remove +support for these counters. ==== `Zicond` ISA Extension diff --git a/docs/datasheet/cpu_csr.adoc b/docs/datasheet/cpu_csr.adoc index 09120c879..bcfd5251b 100644 --- a/docs/datasheet/cpu_csr.adoc +++ b/docs/datasheet/cpu_csr.adoc @@ -24,66 +24,68 @@ should always read back a CSR after writing to check if the targeted bits can ac |======================= | Address | Name [ASM] | Name [C] | R/W | Function 5+^| **<<_floating_point_csrs>>** -| 0x001 | <<_fflags>> | _CSR_FFLAGS_ | r/w | Floating-point accrued exceptions -| 0x002 | <<_frm>> | _CSR_FRM_ | r/w | Floating-point dynamic rounding mode -| 0x003 | <<_fcsr>> | _CSR_FCSR_ | r/w | Floating-point control and status (`frm` + `fflags`) +| 0x001 | <<_fflags>> | `CSR_FFLAGS` | r/w | Floating-point accrued exceptions +| 0x002 | <<_frm>> | `CSR_FRM` | r/w | Floating-point dynamic rounding mode +| 0x003 | <<_fcsr>> | `CSR_FCSR` | r/w | Floating-point control and status (`frm` + `fflags`) 5+^| **<<_machine_configuration_csrs>>** -| 0x30A | <<_menvcfg>> | _CSR_MENVCFG_ | r/- | Machine environment configuration register - low word -| 0x31A | <<_menvcfgh>> | _CSR_MENVCFGH_ | r/- | Machine environment configuration register - low word +| 0x30A | <<_menvcfg>> | `CSR_MENVCFG` | r/- | Machine environment configuration register - low word +| 0x31A | <<_menvcfgh>> | `CSR_MENVCFGH` | r/- | Machine environment configuration register - low word 5+^| **<<_machine_trap_setup_csrs>>** -| 0x300 | <<_mstatus>> | _CSR_MSTATUS_ | r/w | Machine status register - low word -| 0x301 | <<_misa>> | _CSR_MISA_ | r/- | Machine CPU ISA and extensions -| 0x304 | <<_mie>> | _CSR_MIE_ | r/w | Machine interrupt enable register -| 0x305 | <<_mtvec>> | _CSR_MTVEC_ | r/w | Machine trap-handler base address for ALL traps -| 0x306 | <<_mcounteren>> | _CSR_MCOUNTEREN_ | r/- | Machine counter-enable register -| 0x310 | <<_mstatush>> | _CSR_MSTATUSH_ | r/- | Machine status register - high word +| 0x300 | <<_mstatus>> | `CSR_MSTATUS` | r/w | Machine status register - low word +| 0x301 | <<_misa>> | `CSR_MISA` | r/- | Machine CPU ISA and extensions +| 0x304 | <<_mie>> | `CSR_MIE` | r/w | Machine interrupt enable register +| 0x305 | <<_mtvec>> | `CSR_MTVEC` | r/w | Machine trap-handler base address for ALL traps +| 0x306 | <<_mcounteren>> | `CSR_MCOUNTEREN` | r/- | Machine counter-enable register +| 0x310 | <<_mstatush>> | `CSR_MSTATUSH` | r/- | Machine status register - high word 5+^| **<<_machine_trap_handling_csrs>>** -| 0x340 | <<_mscratch>> | _CSR_MSCRATCH_ | r/w | Machine scratch register -| 0x341 | <<_mepc>> | _CSR_MEPC_ | r/w | Machine exception program counter -| 0x342 | <<_mcause>> | _CSR_MCAUSE_ | r/w | Machine trap cause -| 0x343 | <<_mtval>> | _CSR_MTVAL_ | r/w | Machine bad address or instruction -| 0x344 | <<_mip>> | _CSR_MIP_ | r/w | Machine interrupt pending register +| 0x340 | <<_mscratch>> | `CSR_MSCRATCH` | r/w | Machine scratch register +| 0x341 | <<_mepc>> | `CSR_MEPC` | r/w | Machine exception program counter +| 0x342 | <<_mcause>> | `CSR_MCAUSE` | r/w | Machine trap cause +| 0x343 | <<_mtval>> | `CSR_MTVAL` | r/w | Machine bad address or instruction +| 0x344 | <<_mip>> | `CSR_MIP` | r/w | Machine interrupt pending register 5+^| **<<_machine_physical_memory_protection_csrs>>** -| 0x3A0 .. 0x3A3 | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>> | _CSR_PMPCFG0_ .. _CSR_PMPCFG3_ | r/w | Physical memory protection configuration for region 0..15 -| 0x3B0 .. 0x3BF | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | _CSR_PMPADDR0_ .. _CSR_PMPADDR15_ | r/w | Physical memory protection address register region 0..15 +| 0x3A0 .. 0x3A3 | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>> | `CSR_PMPCFG0` .. `CSR_PMPCFG3` | r/w | Physical memory protection configuration for region 0..15 +| 0x3B0 .. 0x3BF | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | `CSR_PMPADDR0` .. `CSR_PMPADDR15` | r/w | Physical memory protection address register region 0..15 5+^| **<<_trigger_module_csrs>>** -| 0x7A0 | <<_tselect>> | _CSR_TSELECT_ | r/w | Trigger select register -| 0x7A1 | <<_tdata1>> | _CSR_TDATA1_ | r/w | Trigger data register 1 -| 0x7A2 | <<_tdata2>> | _CSR_TDATA2_ | r/w | Trigger data register 2 -| 0x7A3 | <<_tdata3>> | _CSR_TDATA3_ | r/w | Trigger data register 3 -| 0x7A4 | <<_tinfo>> | _CSR_TINFO_ | r/w | Trigger information register -| 0x7A5 | <<_tcontrol>> | _CSR_TCONTROL_ | r/w | Trigger control register -| 0x7A8 | <<_mcontext>> | _CSR_MCONTEXT_ | r/w | Machine context register -| 0x7AA | <<_scontext>> | _CSR_SCONTEXT_ | r/w | Supervisor context register +| 0x7A0 | <<_tselect>> | `CSR_TSELECT` | r/w | Trigger select register +| 0x7A1 | <<_tdata1>> | `CSR_TDATA1` | r/w | Trigger data register 1 +| 0x7A2 | <<_tdata2>> | `CSR_TDATA2` | r/w | Trigger data register 2 +| 0x7A3 | <<_tdata3>> | `CSR_TDATA3` | r/w | Trigger data register 3 +| 0x7A4 | <<_tinfo>> | `CSR_TINFO` | r/w | Trigger information register +| 0x7A5 | <<_tcontrol>> | `CSR_TCONTROL` | r/w | Trigger control register +| 0x7A8 | <<_mcontext>> | `CSR_MCONTEXT` | r/w | Machine context register +| 0x7AA | <<_scontext>> | `CSR_SCONTEXT` | r/w | Supervisor context register 5+^| **<<_cpu_debug_mode_csrs>>** | 0x7B0 | <<_dcsr>> | - | r/w | Debug control and status register | 0x7B1 | <<_dpc>> | - | r/w | Debug program counter | 0x7B2 | <<_dscratch0>> | - | r/w | Debug scratch register 0 5+^| **<<_machine_counter_and_timer_csrs>>** -| 0xB00 | <<_mcycleh, `mcycle`>> | _CSR_MCYCLE_ | r/w | Machine cycle counter low word -| 0xB02 | <<_minstreth, `minstret`>> | _CSR_MINSTRET_ | r/w | Machine instruction-retired counter low word -| 0xB80 | <<_mcycleh, `mcycleh`>> | _CSR_MCYCLEH_ | r/w | Machine cycle counter high word -| 0xB82 | <<_minstreth, `minstreth`>> | _CSR_MINSTRETH_ | r/w | Machine instruction-retired counter high word -| 0xC00 | <<_cycleh, `cycle`>> | _CSR_CYCLE_ | r/- | Cycle counter low word -| 0xC02 | <<_instreth, `instret`>> | _CSR_INSTRET_ | r/- | Instruction-retired counter low word -| 0xC80 | <<_cycleh, `cycleh`>> | _CSR_CYCLEH_ | r/- | Cycle counter high word -| 0xC82 | <<_instreth, `instreth`>> | _CSR_INSTRETH_ | r/- | Instruction-retired counter high word +| 0xB00 | <<_mcycleh, `mcycle`>> | `CSR_MCYCLE` | r/w | Machine cycle counter low word +| 0xB02 | <<_minstreth, `minstret`>> | `CSR_MINSTRET` | r/w | Machine instruction-retired counter low word +| 0xB80 | <<_mcycleh, `mcycleh`>> | `CSR_MCYCLEH` | r/w | Machine cycle counter high word +| 0xB82 | <<_minstreth, `minstreth`>> | `CSR_MINSTRETH` | r/w | Machine instruction-retired counter high word +| 0xC00 | <<_cycleh, `cycle`>> | `CSR_CYCLE` | r/- | Cycle counter low word +| 0xC01 | <<_timeh, `time`>> | `CSR_TIME` | r/- | Time counter low word +| 0xC02 | <<_instreth, `instret`>> | `CSR_INSTRET` | r/- | Instruction-retired counter low word +| 0xC80 | <<_cycleh, `cycleh`>> | `CSR_CYCLEH` | r/- | Cycle counter high word +| 0xC81 | <<_timeh, `timeh`>> | `CSR_TIMEH` | r/- | Time counter high word +| 0xC82 | <<_instreth, `instreth`>> | `CSR_INSTRETH` | r/- | Instruction-retired counter high word 5+^| **<<_hardware_performance_monitors_hpm_csrs>>** -| 0x323 .. 0x33F | <<_mhpmevent, `mhpmevent3`>> .. <<_mhpmevent, `mhpmevent31`>> | _CSR_MHPMEVENT3_ .. _CSR_MHPMEVENT31_ | r/w | Machine performance-monitoring event select for counter 3..31 -| 0xB03 .. 0xB1F | <<_mhpmcounterh, `mhpmcounter3`>> .. <<_mhpmcounterh, `mhpmcounter31`>> | _CSR_MHPMCOUNTER3_ .. _CSR_MHPMCOUNTER3H_ | r/w | Machine performance-monitoring counter 3..31 low word -| 0xB83 .. 0xB9F | <<_mhpmcounterh, `mhpmcounter3h`>> .. <<_mhpmcounterh, `mhpmcounter31h`>> | _CSR_MHPMCOUNTER3H_ .. _CSR_MHPMCOUNTER31H_| r/w | Machine performance-monitoring counter 3..31 high word -| 0xC03 .. 0xC1F | <<_hpmcounterh, `hpmcounter3`>> .. <<_hpmcounterh, `hpmcounter31`>> | _CSR_HPMCOUNTER3_ .. _CSR_HPMCOUNTER3H_ | r/- | User performance-monitoring counter 3..31 low word -| 0xC83 .. 0xC9F | <<_hpmcounterh, `hpmcounter3h`>> .. <<_hpmcounterh, `hpmcounter31h`>> | _CSR_HPMCOUNTER3H_ .. _CSR_HPMCOUNTER31H_ | r/- | User performance-monitoring counter 3..31 high word +| 0x323 .. 0x33F | <<_mhpmevent, `mhpmevent3`>> .. <<_mhpmevent, `mhpmevent31`>> | `CSR_MHPMEVENT3` .. `CSR_MHPMEVENT31` | r/w | Machine performance-monitoring event select for counter 3..31 +| 0xB03 .. 0xB1F | <<_mhpmcounterh, `mhpmcounter3`>> .. <<_mhpmcounterh, `mhpmcounter31`>> | `CSR_MHPMCOUNTER3` .. `CSR_MHPMCOUNTER3H` | r/w | Machine performance-monitoring counter 3..31 low word +| 0xB83 .. 0xB9F | <<_mhpmcounterh, `mhpmcounter3h`>> .. <<_mhpmcounterh, `mhpmcounter31h`>> | `CSR_MHPMCOUNTER3H` .. `CSR_MHPMCOUNTER31H` | r/w | Machine performance-monitoring counter 3..31 high word +| 0xC03 .. 0xC1F | <<_hpmcounterh, `hpmcounter3`>> .. <<_hpmcounterh, `hpmcounter31`>> | `CSR_HPMCOUNTER3` .. `CSR_HPMCOUNTER3H` | r/- | User performance-monitoring counter 3..31 low word +| 0xC83 .. 0xC9F | <<_hpmcounterh, `hpmcounter3h`>> .. <<_hpmcounterh, `hpmcounter31h`>> | `CSR_HPMCOUNTER3H` .. `CSR_HPMCOUNTER31H` | r/- | User performance-monitoring counter 3..31 high word 5+^| **<<_machine_counter_setup_csrs>>** -| 0x320 | <<_mcountinhibit>> | _CSR_MCOUNTINHIBIT_ | r/w | Machine counter-enable register +| 0x320 | <<_mcountinhibit>> | `CSR_MCOUNTINHIBIT` | r/w | Machine counter-enable register 5+^| **<<_machine_information_csrs>>** -| 0xF11 | <<_mvendorid>> | _CSR_MVENDORID_ | r/- | Machine vendor ID -| 0xF12 | <<_marchid>> | _CSR_MARCHID_ | r/- | Machine architecture ID -| 0xF13 | <<_mimpid>> | _CSR_MIMPID_ | r/- | Machine implementation ID / version -| 0xF14 | <<_mhartid>> | _CSR_MHARTID_ | r/- | Machine thread ID -| 0xF15 | <<_mconfigptr>> | _CSR_MCONFIGPTR_ | r/- | Machine configuration pointer register +| 0xF11 | <<_mvendorid>> | `CSR_MVENDORID` | r/- | Machine vendor ID +| 0xF12 | <<_marchid>> | `CSR_MARCHID` | r/- | Machine architecture ID +| 0xF13 | <<_mimpid>> | `CSR_MIMPID` | r/- | Machine implementation ID / version +| 0xF14 | <<_mhartid>> | `CSR_MHARTID` | r/- | Machine thread ID +| 0xF15 | <<_mconfigptr>> | `CSR_MCONFIGPTR` | r/- | Machine configuration pointer register 5+^| **<<_neorv32_specific_csrs>>** -| 0xFC0 | <<_mxisa>> | _CSR_MXISA_ | r/- | NEORV32-specific "extended" machine CPU ISA and extensions +| 0xFC0 | <<_mxisa>> | `CSR_MXISA` | r/- | NEORV32-specific "extended" machine CPU ISA and extensions |======================= @@ -338,18 +340,19 @@ interrupt is triggered or an exception is raised. | Reset value | `0x00000000` | ISA | `Zicsr` + `U` | Description | The `mcounteren` CSR is used to constrain user-level access to the CPU's counter CSRs. -This CSR is read-only. However, any write access will be ignored and will not raise an illegal instruction exception. +This CSR is read-only providing hardwired access rights (see table below). +However, any write access will be ignored and will not raise an illegal instruction exception. |======================= .`mcounteren` CSR bits -[cols="^1,^1,<9"] +[cols="^1,^1,<8"] [options="header",grid="rows"] |======================= | Bit | R/W | Function -| 31:3 | r/- | **HPM** = all `1`: user-level code is **not** allowed to read HPM counters -| 2 | r/- | **IR** = `1`: User-level code is allowed to read `cycle[h]` CSRs when set -| 1 | r/- | **TM** = `0`: `time` CSRs not implemented, always zero -| 0 | r/- | **CY** = `1`: User-level code is allowed to read `instret[h]` CSRs when set +| 31:3 | r/- | **HPM** = all `1`: user-level code is allowed to read <<_hpmcounterh>> CSRs +| 2 | r/- | **IR** = `1`: User-level code is allowed to read <<_instreth>> CSRs +| 1 | r/- | **TM** = `1`: User-level code is allowed to read <<_timeh>> CSRs +| 0 | r/- | **CY** = `1`: User-level code is allowed to read <<_cycleh>> CSRs |======================= @@ -579,11 +582,27 @@ if this instruction is actually going to retire or if it causes an exception. | Address | `0xc00` (`cycle`), `0xc80` (`cycleh`) | Reset value | `0x00000000` | ISA | `Zicsr` + `Zicntr` -| Description | The `cycle[h]` are user-mode shadow copies of the according <<_mcycleh>> CSRs. The user-level +| Description | The `cycle[h]` CSRs are user-mode shadow copies of the according <<_mcycleh>> CSRs. The user-level counter are read-only. Any write access will raise an illegal instruction exception. |======================= +{empty} + +[discrete] +===== **`time[h]`** + +[cols="<1,<8"] +[frame="topbot",grid="none"] +|======================= +| Name | Time counter +| Address | `0xc01` (`time`), `0xc81` (`timeh`) +| Reset value | `0x00000000` +| ISA | `Zicsr` + `Zicntr` +| Description | The `time[h]` CSRs are a shadow copy of the <<_cycleh>> cycle counter CSRs. These CSRs +are read-only. Any write access will raise an illegal instruction exception. +|======================= + + {empty} + [discrete] ===== **`instret[h]`** @@ -595,7 +614,7 @@ counter are read-only. Any write access will raise an illegal instruction except | Address | `0xc02` (`instret`), `0xc82` (`instreth`) | Reset value | `0x00000000` | ISA | `Zicsr` + `Zicntr` -| Description | The `instret[h]` are user-mode shadow copies of the according <<_minstreth>> CSRs. The user-level +| Description | The `instret[h]` CSRs are user-mode shadow copies of the according <<_minstreth>> CSRs. The user-level counter are read-only. Any write access will raise an illegal instruction exception. |======================= @@ -611,7 +630,7 @@ counter are read-only. Any write access will raise an illegal instruction except | Address | `0xb00` (`mcycle`), `0xb80` (`mcycleh`) | Reset value | `0x00000000` | ISA | `Zicsr` + `Zicntr` -| Description | If not halted via the <<_mcountinhibit>> CSR the `cycle[h]` CSR will increment with every active CPU clock +| Description | If not halted via the <<_mcountinhibit>> CSR the `cycle[h]` CSRs will increment with every active CPU clock cycle (CPU not in sleep mode). These registers are read/write only for machine-mode software. |======================= diff --git a/rtl/core/neorv32_cpu_control.vhd b/rtl/core/neorv32_cpu_control.vhd index 7665b75c5..7473ace43 100644 --- a/rtl/core/neorv32_cpu_control.vhd +++ b/rtl/core/neorv32_cpu_control.vhd @@ -1276,7 +1276,7 @@ begin csr_reg_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- valid if Zihpm implemented -- counter and timer CSRs -- - when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c => + when csr_cycle_c | csr_cycleh_c | csr_time_c | csr_timeh_c | csr_instret_c | csr_instreth_c => csr_reg_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr); -- valid if Zicntr implemented -- debug-mode CSRs -- @@ -2088,33 +2088,33 @@ begin -- hardware-only CSRs -- -- -------------------------------------------------------------------- --- when csr_zero_c => -- zero (r/-): always returns zero, only relevant for hardware-access, not visible to ISA +-- when csr_zero_c => -- zero: always returns zero, only relevant for hardware-access, not visible to ISA -- csr.rdata <= (others => '0'); -- floating-point CSRs -- -- -------------------------------------------------------------------- - when csr_fflags_c => -- fflags (r/w): floating-point (FPU) exception flags + when csr_fflags_c => -- floating-point (FPU) exception flags if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(4 downto 0) <= csr.fflags; end if; - when csr_frm_c => -- frm (r/w): floating-point (FPU) rounding mode + when csr_frm_c => -- floating-point (FPU) rounding mode if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(2 downto 0) <= csr.frm; end if; - when csr_fcsr_c => -- fcsr (r/w): floating-point (FPU) control/status (frm + fflags) + when csr_fcsr_c => -- floating-point (FPU) control/status (frm + fflags) if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(7 downto 0) <= csr.frm & csr.fflags; end if; -- machine trap setup -- -- -------------------------------------------------------------------- - when csr_mstatus_c => -- mstatus (r/w): machine status register - low word + when csr_mstatus_c => -- machine status register - low word csr.rdata(03) <= csr.mstatus_mie; -- MIE csr.rdata(07) <= csr.mstatus_mpie; -- MPIE csr.rdata(12 downto 11) <= (others => csr.mstatus_mpp); -- MPP: machine previous privilege mode csr.rdata(17) <= csr.mstatus_mprv; csr.rdata(21) <= csr.mstatus_tw and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- TW --- when csr_mstatush_c => -- mstatush (r/w): machine status register - high word, implemented but always zero +-- when csr_mstatush_c => -- machine status register - high word, implemented but always zero -- csr.rdata <= (others => '0'); - when csr_misa_c => -- misa (r/-): ISA and extensions + when csr_misa_c => -- ISA and extensions csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension @@ -2125,18 +2125,19 @@ begin csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo) csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi) - when csr_mie_c => -- mie (r/w): machine interrupt-enable register + when csr_mie_c => -- machine interrupt-enable register csr.rdata(03) <= csr.mie_msi; -- machine software IRQ enable csr.rdata(07) <= csr.mie_mti; -- machine timer IRQ enable csr.rdata(11) <= csr.mie_mei; -- machine external IRQ enable csr.rdata(31 downto 16) <= csr.mie_firq; - when csr_mtvec_c => -- mtvec (r/w): machine trap-handler base address (for ALL exceptions) + when csr_mtvec_c => --machine trap-handler base address (for ALL exceptions) csr.rdata <= csr.mtvec(XLEN-1 downto 2) & "00"; -- mtvec.MODE=0 - when csr_mcounteren_c => -- mcounteren (r/-): machine counter enable register + when csr_mcounteren_c => -- machine counter enable register if (CPU_EXTENSION_RISCV_U = true) then csr.rdata(0) <= '1'; -- allow user-level access to cycle[h] + csr.rdata(1) <= '1'; -- allow user-level access to time[h] csr.rdata(2) <= '1'; -- allow user-level access to instret[h] for i in 0 to HPM_NUM_CNTS-1 loop csr.rdata(3+i) <= '1'; -- allow user-level access to all available hpmcounter*[h] CSRs @@ -2150,32 +2151,34 @@ begin -- machine trap handling -- -- -------------------------------------------------------------------- - when csr_mscratch_c => -- mscratch (r/w): machine scratch register + when csr_mscratch_c => -- machine scratch register csr.rdata <= csr.mscratch; - when csr_mepc_c => -- mepc (r/w): machine exception program counter + when csr_mepc_c => -- machine exception program counter csr.rdata <= csr.mepc(XLEN-1 downto 1) & '0'; - when csr_mcause_c => -- mcause (r/w): machine trap cause + when csr_mcause_c => -- machine trap cause csr.rdata(31) <= csr.mcause(5); csr.rdata(4 downto 0) <= csr.mcause(4 downto 0); - when csr_mtval_c => -- mtval (r/w): machine bad address or instruction + when csr_mtval_c => -- machine bad address or instruction csr.rdata <= csr.mtval; - when csr_mip_c => -- mip (r/c): machine interrupt pending + when csr_mip_c => -- machine interrupt pending csr.rdata(03) <= trap_ctrl.irq_pnd(irq_msi_irq_c); csr.rdata(07) <= trap_ctrl.irq_pnd(irq_mti_irq_c); csr.rdata(11) <= trap_ctrl.irq_pnd(irq_mei_irq_c); csr.rdata(31 downto 16) <= trap_ctrl.irq_pnd(irq_firq_15_c downto irq_firq_0_c); - -- physical memory protection - configuration (r/w) -- + -- physical memory protection -- -- -------------------------------------------------------------------- - when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c => - if (PMP_NUM_REGIONS > 0) then csr.rdata <= csr.pmpcfg_rd(to_integer(unsigned(csr_raddr(1 downto 0)))); end if; + -- region configuration -- + when csr_pmpcfg0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= csr.pmpcfg_rd(0); end if; + when csr_pmpcfg1_c => if (PMP_NUM_REGIONS > 04) then csr.rdata <= csr.pmpcfg_rd(1); end if; + when csr_pmpcfg2_c => if (PMP_NUM_REGIONS > 08) then csr.rdata <= csr.pmpcfg_rd(2); end if; + when csr_pmpcfg3_c => if (PMP_NUM_REGIONS > 12) then csr.rdata <= csr.pmpcfg_rd(3); end if; - -- physical memory protection - addresses (r/w) -- - -- -------------------------------------------------------------------- + -- region address -- when csr_pmpaddr0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= csr.pmpaddr_rd(00); end if; when csr_pmpaddr1_c => if (PMP_NUM_REGIONS > 01) then csr.rdata <= csr.pmpaddr_rd(01); end if; when csr_pmpaddr2_c => if (PMP_NUM_REGIONS > 02) then csr.rdata <= csr.pmpaddr_rd(02); end if; @@ -2195,7 +2198,7 @@ begin -- machine counter setup -- -- -------------------------------------------------------------------- - when csr_mcountinhibit_c => -- mcountinhibit (r/w): machine counter-inhibit register + when csr_mcountinhibit_c => -- machine counter-inhibit register if (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata(0) <= csr.mcountinhibit_cy; -- inhibit auto-increment of [m]cycle[h] counter csr.rdata(2) <= csr.mcountinhibit_ir; -- inhibit auto-increment of [m]instret[h] counter @@ -2204,7 +2207,7 @@ begin csr.rdata((HPM_NUM_CNTS+3)-1 downto 3) <= csr.mcountinhibit_hpm(HPM_NUM_CNTS-1 downto 0); -- inhibit auto-increment of [m]hpmcounter*[h] counter end if; - -- HPM event selector (r/w) -- + -- HPM event selector -- when csr_mhpmevent3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(00); end if; when csr_mhpmevent4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(01); end if; when csr_mhpmevent5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(02); end if; @@ -2237,12 +2240,13 @@ begin -- counters and timers -- -- -------------------------------------------------------------------- - when csr_cycle_c | csr_mcycle_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.mcycle; end if; - when csr_cycleh_c | csr_mcycleh_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.mcycleh; end if; + when csr_cycle_c | csr_mcycle_c | csr_time_c | csr_mtime_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.mcycle; end if; + when csr_cycleh_c | csr_mcycleh_c | csr_timeh_c | csr_mtimeh_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.mcycleh; end if; + when csr_instret_c | csr_minstret_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.minstret; end if; when csr_instreth_c | csr_minstreth_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= csr.minstreth; end if; - -- HPM low word (r/w) -- + -- HPM low word -- when csr_mhpmcounter3_c | csr_hpmcounter3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(00); end if; when csr_mhpmcounter4_c | csr_hpmcounter4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(01); end if; when csr_mhpmcounter5_c | csr_hpmcounter5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(02); end if; @@ -2273,7 +2277,7 @@ begin when csr_mhpmcounter30_c | csr_hpmcounter30_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(27); end if; when csr_mhpmcounter31_c | csr_hpmcounter31_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(28); end if; - -- HPM high word (r/w) -- + -- HPM high word -- when csr_mhpmcounter3h_c | csr_hpmcounter3h_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(00); end if; when csr_mhpmcounter4h_c | csr_hpmcounter4h_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(01); end if; when csr_mhpmcounter5h_c | csr_hpmcounter5h_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(02); end if; @@ -2306,28 +2310,28 @@ begin -- machine information registers -- -- -------------------------------------------------------------------- --- when csr_mvendorid_c => csr.rdata <= (others => '0'); -- mvendorid (r/-): vendor ID, implemented but always zero - when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID - when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version - when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID --- when csr_mconfigptr_c => csr.rdata <= (others => '0'); -- mconfigptr (r/-): machine configuration pointer register, implemented but always zero +-- when csr_mvendorid_c => csr.rdata <= (others => '0'); -- vendor ID, implemented but always zero + when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- architecture ID - official RISC-V open-source arch ID + when csr_mimpid_c => csr.rdata <= hw_version_c; -- implementation ID -- NEORV32 hardware version + when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- hardware thread ID +-- when csr_mconfigptr_c => csr.rdata <= (others => '0'); -- machine configuration pointer register, implemented but always zero -- debug mode CSRs -- -- -------------------------------------------------------------------- - when csr_dcsr_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dcsr_rd; end if; -- dcsr (r/w): debug mode control and status - when csr_dpc_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dpc; end if; -- dpc (r/w): debug mode program counter - when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dscratch0; end if; -- dscratch0 (r/w): debug mode scratch register 0 + when csr_dcsr_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dcsr_rd; end if; -- debug mode control and status + when csr_dpc_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dpc; end if; -- debug mode program counter + when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_Sdext) then csr.rdata <= csr.dscratch0; end if; -- debug mode scratch register 0 -- trigger module CSRs -- -- -------------------------------------------------------------------- --- when csr_tselect_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- tselect (r/w): always zero = only 1 trigger available - when csr_tdata1_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= csr.tdata1_rd; end if; -- tdata1 (r/w): match control - when csr_tdata2_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= csr.tdata2; end if; -- tdata2 (r/w): address-compare --- when csr_tdata3_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- tdata3 (r/w): implemented but always zero - when csr_tinfo_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= x"00000004"; end if; -- tinfo (r/w): address-match trigger only --- when csr_tcontrol_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- tcontrol (r/w): implemented but always zero --- when csr_mcontext_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- mcontext (r/w): implemented but always zero --- when csr_scontext_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- scontext (r/w): implemented but always zero +-- when csr_tselect_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- always zero = only 1 trigger available + when csr_tdata1_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= csr.tdata1_rd; end if; -- match control + when csr_tdata2_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= csr.tdata2; end if; -- address-compare +-- when csr_tdata3_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- implemented but always zero + when csr_tinfo_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= x"00000004"; end if; -- address-match trigger only +-- when csr_tcontrol_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- implemented but always zero +-- when csr_mcontext_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- implemented but always zero +-- when csr_scontext_c => if (CPU_EXTENSION_RISCV_Sdtrig) then csr.rdata <= (others => '0'); end if; -- implemented but always zero -- NEORV32-specific (RISC-V "custom") read-only CSRs -- -- -------------------------------------------------------------------- diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index 270c2c192..3c1109eb5 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -53,7 +53,7 @@ package neorv32_package is -- "response time window" for processor-internal modules -- -- = cycles after which an *unacknowledged* internal bus access will timeout and trigger a bus fault exception - constant max_proc_int_response_time_c : natural := 15; -- min 2 + constant max_proc_int_response_time_c : natural := 15; -- default = 15 (min 2) -- log2 of co-processor timeout cycles -- constant cp_timeout_c : natural := 7; -- default = 7 (= 128 cycles) @@ -65,7 +65,7 @@ package neorv32_package is -- Architecture Constants (do not modify!) ------------------------------------------------ -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080204"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080205"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID -- Check if we're inside the Matrix ------------------------------------------------------- diff --git a/sim/neorv32_tb.vhd b/sim/neorv32_tb.vhd index ae115b079..671ca9c5e 100644 --- a/sim/neorv32_tb.vhd +++ b/sim/neorv32_tb.vhd @@ -180,7 +180,7 @@ begin if ci_mode then -- No need to send the full expectation in one big chunk check_uart(net, uart1_rx_handle, nul & nul); - check_uart(net, uart1_rx_handle, "0/47" & cr & lf); + check_uart(net, uart1_rx_handle, "0/46" & cr & lf); end if; -- Wait until all expected data has been received diff --git a/sw/example/processor_check/main.c b/sw/example/processor_check/main.c index 09b160560..2951ef6f8 100644 --- a/sw/example/processor_check/main.c +++ b/sw/example/processor_check/main.c @@ -125,7 +125,7 @@ uint32_t pmp_num_regions; **************************************************************************/ int main() { - uint32_t tmp_a, tmp_b; + uint32_t tmp_a, tmp_b, tmp_c; uint8_t id; // disable machine-mode interrupts @@ -313,58 +313,41 @@ int main() { // ---------------------------------------------------------- - // Test standard RISC-V performance counter [m]cycle[h] + // Test standard RISC-V counters // ---------------------------------------------------------- neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c); - PRINT_STANDARD("[%i] cycle counter ", cnt_test); + PRINT_STANDARD("[%i] Zicntr counters ", cnt_test); - cnt_test++; - - // make sure counter is enabled - asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<