Projet_SETI_RISC-V/neorv32/docs/datasheet/cpu_csr.adoc
2023-03-06 14:48:14 +01:00

872 lines
38 KiB
Text

<<<
:sectnums:
=== Control and Status Registers (CSRs)
The following table shows a summary of all available NEORV32 CSRs. The address field defines the CSR address for
the CSR access instructions. The *[ASM]* name can be used for (inline) assembly code and is directly
understood by the assembler/compiler. The *[C]* names are defined by the NEORV32 core library and can be
used as immediate in plain C code. The *R/W* column shows whether the CSR can be read and/or written.
.CSRs that are not Implemented
[IMPORTANT]
All CSR bits that are unused / not implemented / not shown are _hardwired to zero_. All CSRs that are not
implemented, not supported or disabled will raise an illegal instruction exception when being accessed.
.WARL Behavior
[IMPORTANT]
All writable CSRs provide **WARL** behavior (write all values; read only legal values). Application software
should always read back a CSR after writing to check if the targeted bits can actually be modified (or are
just read-only).
.NEORV32 Control and Status Registers (CSRs)
[cols="<2,<4,<5,^1,<11"]
[options="header"]
|=======================
| 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`)
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
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
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
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
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
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
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
5+^| **<<_machine_counter_setup_csrs>>**
| 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
5+^| **<<_neorv32_specific_csrs>>**
| 0xFC0 | <<_mxisa>> | _CSR_MXISA_ | r/- | NEORV32-specific "extended" machine CPU ISA and extensions
|=======================
[NOTE]
The following CSR sections provide a "headline" for each CSRs. It shows the 12-bit CSR address, the register's ISA/assembly name,
a short description, the reset value and all ISA extension(s) that are required for implementing the according CSR.
<<<
// ####################################################################################################################
:sectnums:
==== Floating-Point CSRs
:sectnums!:
===== **`fflags`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x001 | `fflags` - **Floating-point accrued exceptions** | `Zicsr` + `Zfinx`
3+<| Reset value: `0x00000000`
|=======================
The `fflags` CSR gives access to the FPU status flags.
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:5 | r/- | _reserved_, writes are ignored; reads always return 0
| 4 | r/w | **NV**: invalid operation
| 3 | r/w | **DZ**: division by zero
| 2 | r/w | **OF**: overflow
| 1 | r/w | **UF**: underflow
| 0 | r/w | **NX**: inexact
|=======================
:sectnums!:
===== **`frm`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x002 | `frm` - **Floating-point dynamic rounding mode** | `Zicsr` + `Zfinx`
3+<| Reset value: `0x00000000`
|=======================
The `frm` CSR is used to configure the rounding mode of the FPU.
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:3 | r/- | _reserved_, writes are ignored; reads always return 0
| 2:0 | r/w | Rounding mode
|=======================
:sectnums!:
===== **`fcsr`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x003 | `fcsr` - **Floating-point control and status register** | `Zicsr` + `Zfinx`
3+<| Reset value: `0x00000000`
|=======================
The `fcsr` provides combined access to the <<_fflags>> and <<_frm>> flags.
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:6 | r/- | _reserved_, writes are ignored; reads always return 0
| 7:5 | r/w | Rounding mode (<<_frm>>)
| 4:0 | r/w | Accrued exception flags (<<_fflags>>)
|=======================
<<<
// ####################################################################################################################
:sectnums:
==== Machine Configuration CSRs
:sectnums!:
===== **`menvcfg`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x30a | `menvcfg` - **Machine environment configuration register** | `Zicsr` + `U`
3+<| Reset value: `0x00000000`
|=======================
[NOTE]
The features of this CSR are not implemented yet. The register is read-only and always returns zero.
:sectnums!:
===== **`menvcfgh`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x31a | `menvcfgh` - **Machine environment configuration register - high word** | `Zicsr` + `U`
3+<| Reset value: `0x00000000`
|=======================
[NOTE]
The features of this CSR are not implemented yet. The register is read-only and always returns zero.
<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Setup CSRs
:sectnums!:
===== **`mstatus`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x300 | `mstatus` - **Machine status register** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mstatus` is used to configure general machine environment parameters.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 21 | _CSR_MSTATUS_TW_ | r/w | **TW**: Trap on execution of `wfi` instruction in user mode when set; hardwired to zero if user-mode not implemented
| 17 | _CSR_MSTATUS_MPRV_ | r/w | **MPRV**: Effective privilege level for load/stores in machine mode; use `MPP`'s as effective privilege level when set; hardwired to zero if user-mode not implemented
| 12:11 | _CSR_MSTATUS_MPP_H_ : _CSR_MSTATUS_MPP_L_ | r/w | **MPP**: Previous machine privilege level, 11 = machine (M) level, 00 = user (U) level
| 7 | _CSR_MSTATUS_MPIE_ | r/w | **MPIE**: Previous machine global interrupt enable flag state
| 3 | _CSR_MSTATUS_MIE_ | r/w | **MIE**: Machine global interrupt enable flag
|=======================
[NOTE]
If the core is in user-mode, machine-mode interrupts are globally **enabled** even if `mstatus.mie` is cleared:
"Interrupts for higher-privilege modes, y>x, are always globally enabled regardless of the setting of the global yIE
bit for the higher-privilege mode." - RISC-V ISA Spec.
:sectnums!:
===== **`misa`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x301 | `misa` - **ISA and extensions** | `Zicsr`
3+<| Reset value: `DEFINED`
|=======================
The `misa` CSR provides information regarding the availability of baic RISC-V ISa extensions.
[NOTE]
The NEORV32 `misa` CSR is read-only. Hence, active CPU extensions are entirely defined by pre-synthesis configurations
and cannot be switch on/off during runtime. For compatibility reasons any write access to this CSR is simply ignored and
will _not_ cause an illegal instruction exception.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:30 | _CSR_MISA_MXL_HI_EXT_ : _CSR_MISA_MXL_LO_EXT_ | r/- | **MXL**: 32-bit architecture indicator (always _01_)
| 23 | _CSR_MISA_X_EXT_ | r/- | **X**: extension bit is always set to indicate custom non-standard extensions
| 20 | _CSR_MISA_U_EXT_ | r/- | **U**: CPU extension (user mode) available, set when <<_cpu_extension_riscv_u>> enabled
| 12 | _CSR_MISA_M_EXT_ | r/- | **M**: CPU extension (mul/div) available, set when <<_cpu_extension_riscv_m>> enabled
| 8 | _CSR_MISA_I_EXT_ | r/- | **I**: CPU base ISA, cleared when <<_cpu_extension_riscv_e>> enabled
| 4 | _CSR_MISA_E_EXT_ | r/- | **E**: CPU extension (embedded) available, set when <<_cpu_extension_riscv_e>> enabled
| 2 | _CSR_MISA_C_EXT_ | r/- | **C**: CPU extension (compressed instruction) available, set when <<_cpu_extension_riscv_c>> enabled
|=======================
[TIP]
Machine-mode software can discover available `Z*` _sub-extensions_ (like `Zicsr` or `Zfinx`) by checking the NEORV32-specific
<<_mxisa>> CSR.
:sectnums!:
===== **`mie`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x304 | `mie` - **Machine interrupt-enable register** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mie` CSR is used to enable/disable individual interrupt sources.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:16 | _CSR_MIE_FIRQ15E_ : _CSR_MIE_FIRQ0E_ | r/w | Fast interrupt channel 15..0 enable
| 11 | _CSR_MIE_MEIE_ | r/w | **MEIE**: Machine _external_ interrupt enable
| 7 | _CSR_MIE_MTIE_ | r/w | **MTIE**: Machine _timer_ interrupt enable (from <<_machine_system_timer_mtime>>)
| 3 | _CSR_MIE_MSIE_ | r/w | **MSIE**: Machine _software_ interrupt enable
|=======================
:sectnums!:
===== **`mtvec`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x305 | `mtvec` - **Machine trap-handler base address** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mtvec` CSR contain the address of the primary trap handler, which gets executed whenever an
interrupt is triggered or an exception is raised.
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:2 | r/w | **BASE**: 4-byte aligned base address of trap base handler
| 1:0 | r/- | **MODE**: always zero; BASE defines entry for _all_ traps
|=======================
:sectnums!:
===== **`mcounteren`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x306 | `mcounteren` - **Machine counter enable** | `Zicsr` + `U`
3+<| Reset value: _see below_
|=======================
The `mcounteren` CSR is used to constrain user-level access to the CPU's counter CSRs.
[cols="^1,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:3 | r/- | **HPM** = all `1`: user-level code is **not** allowed to read HPM counters <<_hpm_num_cnts>>
| 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
|=======================
[NOTE]
If User mode is not implemented this register is read-only and always return zero when read.
[NOTE]
This CSR is read-only. Any write access will be ignored and will not raise an illegal
instruction exception.
:sectnums!:
===== **`mstatush`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x310 | `mstatush` - **Machine status register - high word** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
[NOTE]
The features of this CSR are not implemented yet. The register is read-only and always returns zero.
<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Handling CSRs
:sectnums!:
===== **`mscratch`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x340 | `mscratch` - **Scratch register for machine trap handlers** | `Zicsr`
3+<| Reset value: `DEFINED`
|=======================
The `mscratch` is a general machine-mode scratch register.
:sectnums!:
===== **`mepc`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x341 | `mepc` - **Machine exception program counter** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mepc` CSR provides the instruction address where execution has stopped/failed when
an instruction is triggered / an exception is raised.
[TIP]
See section <<_traps_exceptions_and_interrupts>> for more information.
:sectnums!:
===== **`mcause`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x342 | `mcause` - **Machine trap cause** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mcause` CSRs shows the exact cause of a trap.
[TIP]
See section <<_traps_exceptions_and_interrupts>> for more information.
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31 | r/w | **Interrupt**: `1` if the trap is caused by an interrupt (`0` if the trap is caused by an exception)
| 30:5 | r/- | _Reserved_, read as zero
| 4:0 | r/w | **Exception code**: see <<_neorv32_trap_listing>>
|=======================
:sectnums!:
===== **`mtval`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x343 | `mtval` - **Machine trap value register** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mtval` CSR provides additional information why a trap was entered.
[cols="^5,^5"]
[options="header",grid="rows"]
|=======================
| Trap cause | `mtval` content
| misaligned instruction fetch address or instruction fetch access fault | address of faulting instruction fetch
| misaligned load address, load access fault, misaligned store address or store access fault | program counter (= address) of faulting instruction
| everything else (including all interrupts) | 0x00000000 (all-zero)
|=======================
[NOTE]
In case an invalid **compressed instruction** raised an illegal instruction exception, `mtval` will show the
according de-compressed instruction word. To get the actually 16-bit instruction that caused the exception
perform a memory load using the address stored in <<_mepc>>.
[TIP]
See section <<_traps_exceptions_and_interrupts>> for more information.
:sectnums!:
===== **`mip`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x344 | `mip` - **Machine interrupt pending** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
The `mip` CSR shows currently _pending_ machine-level interrupt requests. The bits for the standard RISC-V
machine-level interrupts (`MEIP`, `MTIP`, `MSIP`) are read-only. Hence, these interrupts cannot be
cleared/set using the `mip` register. These interrupts are cleared/acknowledged by mechanism that are
specific for the interrupt-causing modules. the according interrupt-generating device.
The upper 16 bits represent the status of the CPU's fast interrupt request lines (FIRQ). Once triggered, these
bit have to be cleared manually by writing zero to the according `mip` bits (in the interrupt handler routine)
to clear the current interrupt request.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:16 | _CSR_MIP_FIRQ15P_ : _CSR_MIP_FIRQ0P_ | r/c | **FIRQxP**: Fast interrupt channel 15..0 pending; has to be cleared manually by writing zero
| 11 | _CSR_MIP_MEIP_ | r/- | **MEIP**: Machine _external_ interrupt pending; _cleared by platform-defined mechanism_
| 7 | _CSR_MIP_MTIP_ | r/- | **MTIP**: Machine _timer_ interrupt pending; _cleared by platform-defined mechanism_
| 3 | _CSR_MIP_MSIP_ | r/- | **MSIP**: Machine _software_ interrupt pending; _cleared by platform-defined mechanism_
|=======================
.FIRQ Channel Mapping
[TIP]
See section <<_neorv32_specific_fast_interrupt_requests>> for the mapping of the FIRQ channels and the according
interrupt-triggering processor module.
<<<
// ####################################################################################################################
:sectnums:
==== Machine Physical Memory Protection CSRs
The available physical memory protection logic is configured via the <<_pmp_num_regions>> and
<<_pmp_min_granularity>> top entity generics. <<_pmp_num_regions>> defines the number of implemented
protection regions and thus, the implementation of the available _PMP entries_.
See section <<_pmp_physical_memory_protection>> for more information.
If trying to access an PMP-related CSR beyond <<_pmp_num_regions>> **no illegal instruction
exception** is triggered. The according CSRs are read-only (writes are ignored) and always return zero.
However, any access beyond `pmpcfg3` or `pmpaddr15`, which are the last physically implemented registers if
<<_pmp_num_regions>> == 16, will raise an illegal instruction exception as these CSRs are not implemented at all.
:sectnums!:
===== **`pmpcfg`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x3a0 | `pmpcfg0` - **Physical memory protection configuration register (region 0-3)** | `Zicsr` + `PMP`
3+<| ...
| 0x3a3| `pmpcfg3` - **Physical memory protection configuration register (region 12-15)** | `Zicsr` + `PMP`
3+<| Reset value: all `0x00000000`
|=======================
The `pmpcfg*` CSRs are used to configure the different PMP regions. Each region features an independent 8-bit array
in these CSRs.
[cols="^1,^2,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 7 | _PMPCFG_L_ | r/w | **L**: Lock bit, prevents further write accesses, also enforces access rights in machine-mode, can only be cleared by CPU reset
| 6:5 | - | r/- | _reserved_, read as zero
| 4 | _PMPCFG_A_MSB_ | r/- .2+<| **A**: Mode configuration; only **OFF** (`00`) and **TOR** (`01`) modes are supported, any other value will map back to OFF/TOR
as the MSB is hardwired to zero
| 3 | _PMPCFG_A_LSB_ | r/w
| 2 | _PMPCFG_X_ | r/w | **X**: Execute permission
| 1 | _PMPCFG_W_ | r/w | **W**: Write permission
| 0 | _PMPCFG_R_ | r/w | **R**: Read permission
|=======================
[WARNING]
Setting the lock bit `L` and setting TOR mode in `pmpcfg(i)` will also lock write access to `pmpaddr(i-1)`.
See the RISC-V specs. for more information.
:sectnums!:
===== **`pmpaddr`**
The `pmpaddr*` CSRs are used to configure the region's address boundaries.
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x3b0 | `pmpaddr0` - **Physical memory protection address registers (region 0)** | `Zicsr` + `PMP`
3+<| ...
| 0x3bf | `pmpaddr15` - **Physical memory protection address registers (region 15)** | `Zicsr` + `PMP`
3+<| Reset value: all `0x00000000`
|=======================
.Physical Address Size
[NOTE]
The two MSBs of each `pmpaddr` are hardwired to zero (= bits 33:32 of the physical address).
<<<
// ####################################################################################################################
:sectnums:
==== (Machine) Counter and Timer CSRs
.Counter Size
[NOTE]
When implemented (by enabling the `Zicntr` ISA extension) the standard CPU counters are always 64-bit wide (low-word + high-word).
.Instruction Retired Counter Increment
[NOTE]
The `[m]instret[h]` counter always increments when a instruction enters the pipeline's execute stage no matter
if this instruction is actually going to retire or if it causes an exception.
:sectnums!:
===== **`cycle[h]`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xc00 | `cycle` - **Cycle counter - low word** | `Zicsr` + `Zicntr`
| 0xc80 | `cycleh` - **Cycle counter - high word** | `Zicsr` + `Zicntr`
3+<| Reset value: all `0x00000000`
|=======================
The `cycle[h]` 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.
:sectnums!:
===== **`instret[h]`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xc02 | `instret` - **Instructions-retired counter - low word** | `Zicsr` + `Zicntr`
| 0xc82 | `instreth` - **Instructions-retired counter - high word** | `Zicsr` + `Zicntr`
3+<| Reset value: all `0x00000000`
|=======================
The `instret[h]` 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.
:sectnums!:
===== **`mcycle[h]`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xb00 | `mcycle` - **Machine cycle counter - low word** | `Zicsr` + `Zicntr`
| 0xb80 | `mcycleh` - **Machine cycle counter - high word** | `Zicsr` + `Zicntr`
3+<| Reset value: all `0x00000000`
|=======================
If not halted via the <<_mcountinhibit>> CSR the `cycle[h]` CSR will increment with every active CPU clock
cycle (CPU not in sleep mode). These registers are read/write only for machine-mode software.
:sectnums!:
===== **`minstret[h]`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xb02 | `minstret` - **Machine instructions-retired counter - low word** | `Zicsr` + `Zicntr`
| 0xb82 | `minstreth` - **Machine instructions-retired counter - high word** | `Zicsr` + `Zicntr`
3+<| Reset value: all `0x00000000`
|=======================
If not halted via the <<_mcountinhibit>> CSR the `minstret[h]` CSRs will increment with every retired instruction.
These registers are read/write only for machine-mode software.
<<<
// ####################################################################################################################
:sectnums:
==== Hardware Performance Monitors (HPM) CSRs
The actual number of implemented hardware performance monitors is configured via the <<_hpm_num_cnts>> top entity generic,
Note that always all 28 HPM counter and configuration registers (`mhpmcounter*[h]` and `mhpmevent*`) are implemented, but
only the actually configured ones are implemented as "real" physical registers - the remaining ones will be hardwired to zero.
If trying to access an HPM-related CSR beyond <<_hpm_num_cnts>> **no illegal instruction exception is
triggered**. These CSRs are read-only (writes are ignored) and always return zero.
The total counter width of the HPMs can be configured before synthesis via the <<_hpm_cnt_width>> generic (0..64-bit).
If <<_hpm_num_cnts>> is less than 64, all remaining MSB-aligned bits are hardwired to zero.
:sectnums!:
===== **`mhpmevent`**
[cols="1,9,>2"]
[frame="topbot",grid="none"]
|=======================
| 0x232 | `mhpmevent3` - **Machine hardware performance monitor event select (counter 3)** | `Zicsr` + `Zihpm`
3+<| ...
| 0x33f | `mhpmevent31` - **Machine hardware performance monitor event select (counter 31)** | `Zicsr` + `Zihpm`
3+<| Reset value: all `0x00000000`
|=======================
The value in these CSRs define the architectural events that cause an increment of the according `mhpmcounter*[h]` counter(s).
All available events are listed in the table below. If more than one event is selected, the according counter will increment if _any_ of
the enabled events is observed (logical OR). Note that the counter will only increment by 1 step per clock
cycle even if more than one trigger event is observed.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Event
| 31:15 | - | r/- | _reserved_, writes are ignored, read always return zero
| 14 | _HPMCNT_EVENT_ILLEGAL_ | r/w | illegal instruction exception
| 13 | _HPMCNT_EVENT_TRAP_ | r/w | entered trap (synchronous exception or interrupt)
| 12 | _HPMCNT_EVENT_TBRANCH_ | r/w | _taken_ conditional branch
| 11 | _HPMCNT_EVENT_BRANCH_ | r/w | conditional branch (_taken_ or _not taken_)
| 10 | _HPMCNT_EVENT_JUMP_ | r/w | unconditional jump
| 9 | _HPMCNT_EVENT_WAIT_LS_ | r/w | load/store memory wait cycle: if more than 1 cycle memory latency or high bus traffic
| 8 | _HPMCNT_EVENT_STORE_ | r/w | memory data store operation
| 7 | _HPMCNT_EVENT_LOAD_ | r/w | memory data load operation
| 6 | _HPMCNT_EVENT_WAIT_MC_ | r/w | multi-cycle ALU operation wait cycle (like iterative shift operation)
| 5 | _HPMCNT_EVENT_WAIT_II_ | r/w | instruction issue pipeline wait cycle: if more than 1 cycle latency, pipelines flush (like taken branches) / cache miss or high bus traffic
| 4 | _HPMCNT_EVENT_WAIT_IF_ | r/w | instruction fetch memory wait cycle: if more than 1 cycle memory latency, cache miss or high bus traffic
| 3 | _HPMCNT_EVENT_CIR_ | r/w | retired compressed instruction
| 2 | _HPMCNT_EVENT_IR_ | r/w | retired instruction (compressed or uncompressed)
| 1 | - | r/- | _not implemented, always read as zero_
| 0 | _HPMCNT_EVENT_CY_ | r/w | active clock cycle (CPU not in sleep mode)
|=======================
:sectnums!:
===== **`mhpmcounter[h]`**
[cols="1,9,>2"]
[frame="topbot",grid="none"]
|=======================
| 0xb03 | `mhpmcounter3` - **Machine hardware performance monitor - counter 3 low** | `Zicsr` + `Zihpm`
3+<| ...
| 0xb1f | `mhpmcounter31` - **Machine hardware performance monitor - counter 31 low** | `Zicsr` + `Zihpm`
| 0xb83 | `mhpmcounter3h` - **Machine hardware performance monitor - counter 3 high** | `Zicsr` + `Zihpm`
3+<| ...
| 0xb9f | `mhpmcounter31h` - **Machine hardware performance monitor - counter 31 high** | `Zicsr` + `Zihpm`
3+<| Reset value: all `0x00000000`
|=======================
If not halted via the <<_mcountinhibit>> CSR the `mhpmcounter*[h]` counter CSR increment whenever a configured
event from the according <<_mhpmevent>> CSR occurs. The counter registers are read/write for machine mode and
are not accessible for lower-privileged software.
:sectnums!:
===== **`hpmcounter[h]`**
[cols="1,9,>2"]
[frame="topbot",grid="none"]
|=======================
| 0xc03 | `hpmcounter3` - **User hardware performance monitor - counter 3 low** | `Zicsr` + `Zihpm`
3+<| ...
| 0xc1f | `hpmcounter31` - **User hardware performance monitor - counter 31 low** | `Zicsr` + `Zihpm`
| 0xc83 | `hpmcounter3h` - **User hardware performance monitor - counter 3 high** | `Zicsr` + `Zihpm`
3+<| ...
| 0xc9f | `hpmcounter31h` - **User hardware performance monitor - counter 31 high** | `Zicsr` + `Zihpm`
3+<| Reset value: all `0x00000000`
|=======================
The `hpmcounter*[h]` are user-level shadow copies of the according <<_mhpmcounterh>> CSRs. The user level
counter CSRs are read-only. Any write access will raise an illegal instruction exception.
<<<
// ####################################################################################################################
:sectnums:
==== Machine Counter Setup CSRs
:sectnums!:
===== **`mcountinhibit`**
The `mcountinhibit` CSR can be used to halt specific counter CSRs.
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x320 | `mcountinhibit` - **Machine counter-inhibit register** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Event
| 3:31 | _CSR_MCOUNTINHIBIT_HPM3_ : _CSR_MCOUNTINHIBIT_HPM31_ | r/w | **HPMx**: Set to `1` to halt `[m]hpmcount*[h]`; hardwired to zero if `Zihpm` ISA extension is disabled
| 2 | _CSR_MCOUNTINHIBIT_CY_ | r/w | **CY**: Set to `1` to halt `[m]cycle[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
| 0 | _CSR_MCOUNTINHIBIT_IR_ | r/w | **IR**: Set to `1` to halt `[m]instret[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
|=======================
<<<
// ####################################################################################################################
:sectnums:
==== Machine Information CSRs
[NOTE]
All machine information registers can only be accessed in machine mode and are read-only.
:sectnums!:
===== **`mvendorid`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xf11 | `mvendorid` - **Machine vendor ID** | `Zicsr`
3+<| Reset value: `0x00000000`
|=======================
[NOTE]
The features of this CSR are not implemented yet. The register is read-only and always returns zero.
:sectnums!:
===== **`marchid`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xf12 | `marchid` - **Machine architecture ID** | `Zicsr`
3+<| Reset value: `0x00000013`
|=======================
The `marchid` CSR is read-only and provides the NEORV32 official RISC-V open-source architecture ID
(decimal: 19, 32-bit hexadecimal: 0x00000013).
:sectnums!:
===== **`mimpid`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xf13 | `mimpid` - **Machine implementation ID** | `Zicsr`
3+<| Reset value: `DEFINED`
|=======================
The `mimpid` CSR is read-only and provides the version of the
NEORV32 as BCD-coded number (example: `mimpid` = _0x01020312_ → 01.02.03.12 → version 1.2.3.12).
:sectnums!:
===== **`mhartid`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xf14 | `mhartid` - **Machine hardware thread ID** | `Zicsr`
3+<| Reset value: `DEFINED`
|=======================
The `mhartid` CSR is read-only and provides the core's hart ID,
which is assigned via the <<_hw_thread_id>> top generic.
:sectnums!:
===== **`mconfigptr`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0xf15 | `mconfigptr` - **Machine configuration pointer register** | `zicsr`
3+<| Reset value: `0x00000000`
|=======================
[NOTE]
The features of this CSR are not implemented yet. The register is read-only and always returns zero.
<<<
// ####################################################################################################################
:sectnums:
==== NEORV32-Specific CSRs
[NOTE]
All NEORV32-specific CSRs are mapped to addresses that are explicitly reserved for custom **Machine-Mode, read-only** CSRs
(assured by the RISC-V privileged specifications). Hence, these CSRs can only be accessed when in machine-mode. Any access
outside of machine-mode will raise an illegal instruction exception.
:sectnums!:
===== **`mxisa`**
[cols="1,8,>3"]
[frame="topbot",grid="none"]
|=======================
| 0x7c0 | `mxisa` - **Machine EXTENDED ISA and Extensions register** | `Zicsr` + `X`
3+<| Reset value: `DEFINED`
|=======================
The `mxisa` CSRs is a NEORV32-specific read-only CSR that helps machine-mode software to
discover ISA sub-extensions and CPU configuration options.
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31 | _CSR_MXISA_FASTSHIFT_ | r/- | fast shifts available when set (via top's <<_fast_shift_en>> generic)
| 30 | _CSR_MXISA_FASTMUL_ | r/- | fast multiplication available when set (via top's <<_fast_mul_en>> generic)
| 31:21 | - | r/- | _reserved_, read as zero
| 20 | _CSR_MXISA_IS_SIM_ | r/- | set if CPU is being **simulated** (⚠️ not guaranteed)
| 19:11 | - | r/- | _reserved_, read as zero
| 11 | _CSR_MXISA_SDTRIG_ | r/- | `Sdtrig` extension (trigger module) available when set (via top's <<_cpu_extension_riscv_sdtrig>> generic)
| 10 | _CSR_MXISA_SDEXT_ | r/- | `Sdext` extension (debug mode) available when set (via top's <<_cpu_extension_riscv_sdext>> generic)
| 9 | _CSR_MXISA_ZIHPM_ | r/- | `Zihpm` (hardware performance monitors) extension available when set (via top's <<_cpu_extension_riscv_zihpm>> generic)
| 8 | _CSR_MXISA_PMP_ | r/- | `PMP` (physical memory protection) extension available when set (via top's <<_pmp_num_regions>> generic)
| 7 | _CSR_MXISA_ZICNTR_ | r/- | `Zicntr` extension (`I` sub-extension) available when set - `[m]cycle` and `[m]instret` CSRs available when set (via top's <<_cpu_extension_riscv_zicntr>> generic)
| 6 | - | r/- | _reserved_, read as zero
| 5 | _CSR_MXISA_ZFINX_ | r/- | `Zfinx` extension (`F` sub-/alternative-extension: FPU using `x` registers) available when set (via top's <<_cpu_extension_riscv_zfinx>> generic)
| 4 | - | r/- | _reserved_, read as zero
| 3 | _CSR_MXISA_ZXCFU_ | r/- | `Zxcfu` extension (custom functions unit for custom RISC-V instructions) available when set (via top's <<_cpu_extension_riscv_zxcfu>> generic)
| 2 | _CSR_MXISA_ZMMUL_ | r/- | `Zmmul` extension (`M` sub-extension) available when set (via top's <<_cpu_extension_riscv_zmmul>> generic)
| 1 | _CSR_MXISA_ZIFENCEI_ | r/- | `Zifencei` extension (`I` sub-extension) available when set (via top's <<_cpu_extension_riscv_zifencei>> generic)
| 0 | _CSR_MXISA_ZICSR_ | r/- | `Zicsr` extension (`I` sub-extension) available when set (via top's <<_cpu_extension_riscv_zicsr>> generic)
|=======================