<<<
: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 "Name [ASM]" column provides the CSR name aliases that can be used in (inline) assembly.
The "Name [C]" column lists the name aliases that are defined by the NEORV32 core library. These can be used in plain C code.
The "Access" column shows the minimal required privilege mode required for accessing the according CSR (`M` = machine-mode,
`U` = user-mode, `D` = debug-mode) and the read/write capabilities (`RW` = read-write, `RO` = read-only)

.Unused, Reserved, Unimplemented and Disabled CSRs
[NOTE]
All CSRs and CSR bits that are not listed in the table below are _unimplemented_ and are _hardwired to zero_. Additionally,
CSRs that are unavailable ("disabled") because the according ISA extension is not enabled are also considered _unimplemented_
and are also hardwired to zero. Any access to such a CSR will raise an illegal instruction exception. 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.

.Read-Only RW CSRs
[WARNING]
Some CSRs are listed with "read-write" capabilities but will ignore any value written to them.
In the following table these CSRs are highlighted with "⚠️".

.NEORV32 Control and Status Registers (CSRs)
[cols="<3,<5,<6,^3,<12"]
[options="header"]
|=======================
| Address | Name [ASM] | Name [C] | Access | Description
5+^| **<<_floating_point_csrs>>**
| 0x001 | <<_fflags>> | `CSR_FFLAGS` | URW | Floating-point accrued exceptions
| 0x002 | <<_frm>>    | `CSR_FRM`    | URW | Floating-point dynamic rounding mode
| 0x003 | <<_fcsr>>   | `CSR_FCSR`   | URW | Floating-point control and status
5+^| **<<_machine_trap_setup_csrs>>**
| 0x300 | <<_mstatus>>    | `CSR_MSTATUS`    | MRW | Machine status register - low word
| 0x301 | <<_misa>>       | `CSR_MISA`       | MRW | Machine CPU ISA and extensions
| 0x304 | <<_mie>>        | `CSR_MIE`        | MRW | Machine interrupt enable register
| 0x305 | <<_mtvec>>      | `CSR_MTVEC`      | MRW | Machine trap-handler base address for ALL traps
| 0x306 | <<_mcounteren>> | `CSR_MCOUNTEREN` | MRW | Machine counter-enable register
| 0x310 | <<_mstatush>>   | `CSR_MSTATUSH`   | MRW | Machine status register - high word
5+^| **<<_machine_configuration_csrs>>**
| 0x30a | <<_menvcfg>>  | `CSR_MENVCFG`  | MRW | Machine environment configuration register - low word
| 0x31a | <<_menvcfgh>> | `CSR_MENVCFGH` | MRW | Machine environment configuration register - high word
5+^| **<<_machine_counter_setup_csrs>>**
| 0x320 | <<_mcountinhibit>> | `CSR_MCOUNTINHIBIT` | MRW | Machine counter-inhibit register
5+^| **<<_machine_trap_handling_csrs>>**
| 0x340 | <<_mscratch>> | `CSR_MSCRATCH` | MRW | Machine scratch register
| 0x341 | <<_mepc>>     | `CSR_MEPC`     | MRW | Machine exception program counter
| 0x342 | <<_mcause>>   | `CSR_MCAUSE`   | MRW ⚠️| Machine trap cause
| 0x343 | <<_mtval>>    | `CSR_MTVAL`    | MRW ⚠️ | Machine trap value
| 0x344 | <<_mip>>      | `CSR_MIP`      | MRW | Machine interrupt pending register
| 0x34a | <<_mtinst>>   | `CSR_MTINST`   | MRW ⚠️ | Machine trap instruction
5+^| **<<_machine_physical_memory_protection_csrs>>**
| 0x3a0 .. 0x303 | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>>      | `CSR_PMPCFG0` .. `CSR_PMPCFG3`    | MRW | Physical memory protection configuration registers
| 0x3b0 .. 0x3bf | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | `CSR_PMPADDR0` .. `CSR_PMPADDR15` | MRW | Physical memory protection address registers
5+^| **<<_trigger_module_csrs>>**
| 0x7a0 | <<_tselect>>  | `CSR_TSELECT`  | MRW | Trigger select register
| 0x7a1 | <<_tdata1>>   | `CSR_TDATA1`   | MRW | Trigger data register 1
| 0x7a2 | <<_tdata2>>   | `CSR_TDATA2`   | MRW | Trigger data register 2
| 0x7a4 | <<_tinfo>>    | `CSR_TINFO`    | MRW | Trigger information register
5+^| **<<_cpu_debug_mode_csrs>>**
| 0x7b0 | <<_dcsr>>      | - | DRW | Debug control and status register
| 0x7b1 | <<_dpc>>       | - | DRW | Debug program counter
| 0x7b2 | <<_dscratch0>> | - | DRW | Debug scratch register 0
5+^| **<<_machine_counter_and_timer_csrs>>**
| 0xb00 | <<_mcycleh, `mcycle`>>      | `CSR_MCYCLE`    | MRW | Machine cycle counter low word
| 0xb02 | <<_minstreth, `minstret`>>  | `CSR_MINSTRET`  | MRW | Machine instruction-retired counter low word
| 0xb80 | <<_mcycleh, `mcycleh`>>     | `CSR_MCYCLEH`   | MRW | Machine cycle counter high word
| 0xb82 | <<_minstreth, `minstreth`>> | `CSR_MINSTRETH` | MRW | Machine instruction-retired counter high word
| 0xc00 | <<_cycleh, `cycle`>>        | `CSR_CYCLE`     | URO | Cycle counter low word
| 0xc02 | <<_instreth, `instret`>>    | `CSR_INSTRET`   | URO | Instruction-retired counter low word
| 0xc80 | <<_cycleh, `cycleh`>>       | `CSR_CYCLEH`    | URO | Cycle counter high word
| 0xc82 | <<_instreth, `instreth`>>   | `CSR_INSTRETH`  | URO | Instruction-retired counter high word
5+^| **<<_hardware_performance_monitors_hpm_csrs>>**
| 0x323 .. 0x32f | <<_mhpmevent, `mhpmevent3`>> .. <<_mhpmevent, `mhpmevent15`>>             | `CSR_MHPMEVENT3` .. `CSR_MHPMEVENT15`       | MRW | Machine performance-monitoring event select for counter 3..15
| 0xb03 .. 0xb0f | <<_mhpmcounterh, `mhpmcounter3`>> .. <<_mhpmcounterh, `mhpmcounter15`>>   | `CSR_MHPMCOUNTER3` .. `CSR_MHPMCOUNTER15`   | MRW | Machine performance-monitoring counter 3..15 low word
| 0xb83 .. 0xb8f | <<_mhpmcounterh, `mhpmcounter3h`>> .. <<_mhpmcounterh, `mhpmcounter15h`>> | `CSR_MHPMCOUNTER3H` .. `CSR_MHPMCOUNTER15H` | MRW | Machine performance-monitoring counter 3..15 high word
5+^| **<<_machine_information_csrs>>**
| 0xf11 | <<_mvendorid>>  | `CSR_MVENDORID`  | MRO | Machine vendor ID
| 0xf12 | <<_marchid>>    | `CSR_MARCHID`    | MRO | Machine architecture ID
| 0xf13 | <<_mimpid>>     | `CSR_MIMPID`     | MRO | Machine implementation ID / version
| 0xf14 | <<_mhartid>>    | `CSR_MHARTID`    | MRO | Machine hardware thread ID
| 0xf15 | <<_mconfigptr>> | `CSR_MCONFIGPTR` | MRO | Machine configuration pointer register
5+^| **<<_neorv32_specific_csrs>>**
| 0xbc0 | <<_mxcsr>> | `CSR_MXCSR` | MRW | Machine status and control register
| 0xfc0 | <<_mxisa>> | `CSR_MXISA` | MRO | Extended machine CPU ISA and extensions
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Floating-Point CSRs

[discrete]
===== **`fflags`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point accrued exceptions
| Address     | `0x001`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Zfinx`
| Description | FPU status flags.
|=======================

.`fflags` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 0   | r/w | **NX**: inexact
| 1   | r/w | **UF**: underflow
| 2   | r/w | **OF**: overflow
| 3   | r/w | **DZ**: division by zero
| 4   | r/w | **NV**: invalid operation
|=======================

{empty} +
[discrete]
===== **`frm`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point dynamic rounding mode
| Address     | `0x002`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Zfinx`
| Description | The `frm` CSR is used to configure the rounding mode of the FPU.
|=======================

.`frm` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 2:0 | r/w | Rounding mode
|=======================


{empty} +
[discrete]
===== **`fcsr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point control and status register
| Address     | `0x003`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Zfinx`
| Description | The `fcsr` provides combined access to the <<_fflags>> and <<_frm>> flags.
|=======================

.`fcsr` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 4:0 | r/w | Accrued exception flags (<<_fflags>>)
| 7:5 | r/w | Rounding mode (<<_frm>>)
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Setup CSRs

[discrete]
===== **`mstatus`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine status register - low word
| Address     | `0x300`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mstatus` CSR is used to configure general machine environment parameters.
|=======================

.`mstatus` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 3     | `CSR_MSTATUS_MIE`  | r/w | **MIE**: Machine-mode interrupt enable flag
| 7     | `CSR_MSTATUS_MPIE` | r/w | **MPIE**: Previous machine-mode interrupt enable flag state
| 12:11 | `CSR_MSTATUS_MPP_H` : `CSR_MSTATUS_MPP_L` | r/w | **MPP**: Previous machine privilege mode, `11` = machine-mode "M", `00` = user-mode "U"; other values will fall-back to machine-mode
| 17    | `CSR_MSTATUS_MPRV` | r/w | **MPRV**: Effective privilege mode for load/stores; use `MPP` as effective privilege mode when set; hardwired to zero if user-mode not implemented
| 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
|=======================


{empty} +
[discrete]
===== **`misa`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | ISA and extensions
| Address     | `0x301`
| Reset value | `DEFINED`, according to enabled ISA extensions
| ISA         | `Zicsr`
| Description | The `misa` CSR provides information regarding the availability of basic 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 switched on/off during runtime. For compatibility reasons any write access to this CSR is simply ignored and
will _not_ cause an illegal instruction exception.

.`misa` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit   | Name [C] | R/W | Function
| 0     | `CSR_MISA_A_EXT` | r/- | **A**: CPU extension (atomic memory access) available, set when <<_a_isa_extension>> enabled
| 1     | `CSR_MISA_B_EXT` | r/- | **B**: CPU extension (bit-manipulation) available, set when <<_b_isa_extension>> enabled
| 2     | `CSR_MISA_C_EXT` | r/- | **C**: CPU extension (compressed instruction) available, set when <<_c_isa_extension>> enabled
| 4     | `CSR_MISA_E_EXT` | r/- | **E**: CPU extension (embedded) available, set when <<_e_isa_extension>> enabled
| 8     | `CSR_MISA_I_EXT` | r/- | **I**: CPU base ISA, cleared when <<_e_isa_extension>> enabled
| 12    | `CSR_MISA_M_EXT` | r/- | **M**: CPU extension (mul/div) available, set when <<_m_isa_extension>> enabled
| 20    | `CSR_MISA_U_EXT` | r/- | **U**: CPU extension (user mode) available, set when <<_u_isa_extension>> enabled
| 23    | `CSR_MISA_X_EXT` | r/- | **X**: bit is always set to indicate non-standard / NEORV32-specific extensions
| 31:30 | `CSR_MISA_MXL_HI_EXT` : `CSR_MISA_MXL_LO_EXT` | r/- | **MXL**: 32-bit architecture indicator (always `01`)
|=======================

[TIP]
Machine-mode software can discover available `Z*` sub-extensions (like `Zicsr` or `Zfinx`) by checking the NEORV32-specific
<<_mxisa>> CSR.


{empty} +
[discrete]
===== **`mie`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine interrupt-enable register
| Address     | `0x304`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mie` CSR is used to enable/disable individual interrupt sources.
|=======================

.`mie` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit   | Name [C] | R/W | Function
| 3     | `CSR_MIE_MSIE` | r/w | **MSIE**: Machine _software_ interrupt enable (from <<_core_local_interruptor_clint>>)
| 7     | `CSR_MIE_MTIE` | r/w | **MTIE**: Machine _timer_ interrupt enable (from <<_core_local_interruptor_clint>>)
| 11    | `CSR_MIE_MEIE` | r/w | **MEIE**: Machine _external_ interrupt enable
| 31:16 | `CSR_MIE_FIRQ15E` : `CSR_MIE_FIRQ0E` | r/w | Fast interrupt channel 15..0 enable
|=======================


{empty} +
[discrete]
===== **`mtvec`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap-handler base address
| Address     | `0x305`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mtvec` CSR holds the trap vector configuration.
|=======================

.`mtvec` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit  | R/W | Function
| 1:0  | r/w | **MODE**: mode configuration, `00` = DIRECT, `01` = VECTORED; other encodings are _reserved_.
| 31:2 | r/w | **BASE**: in DIRECT mode = 4-byte-aligned base address of trap base handler, _all_ traps jump to `pc = BASE`;
in VECTORED mode = 128-byte-aligned base address of trap vector table, interrupts cause a jump to `pc = BASE + 4 * mcause`
and exceptions a jump to `pc = BASE`.
|=======================

.Interrupt Latency
[TIP]
The vectored `mtvec` mode is useful for reducing the time between interrupt request (IRQ) and servicing it (ISR).
As software does not need to determine the interrupt cause the reduction in latency can be 5 to 10 times and as low as _26_ cycles.

{empty} +
[discrete]
===== **`mcounteren`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine counter enable
| Address     | `0x306`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `U`
| Description | The `mcounteren` CSR is used to constrain user-mode access to the CPU's counter CSRs.
|=======================

.`mcounteren` CSR bits
[cols="^1,<3,^1,<8"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 0    | `CSR_MCOUNTEREN_CY` | r/w | **CY**: User-mode is allowed to read <<_cycleh>> CSRs when set
| 1    | -                   | r/- | **TM**: not implemented, hardwired to zero
| 2    | `CSR_MCOUNTEREN_IR` | r/w | **IR**: User-mode is allowed to read <<_instreth>> CSRs when set
| 31:3 | -                   | r/- | **HPM**: hardwired to zero; hardware performance monitors are accessible by machine-mode software only
|=======================


{empty} +
[discrete]
===== **`mstatush`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine status register - high word
| Address     | `0x310`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The features of this CSR are not implemented yet. The register is read-only and always returns zero.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Handling CSRs

[discrete]
===== **`mscratch`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Scratch register for machine trap handlers
| Address     | `0x340`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mscratch` is a general-purpose machine-mode scratch register.
|=======================


{empty} +
[discrete]
===== **`mepc`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine exception program counter
| Address     | `0x341`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mepc` CSR provides the instruction address where execution has stopped/failed when
an interrupt is triggered / an exception is raised. See section <<_traps_exceptions_and_interrupts>> for a list of all legal values.
The `mret` instruction will return to the address stored in `mepc` by automatically moving `mepc` to the program counter.
|=======================

[NOTE]
`mepc[0]` is hardwired to zero. If IALIGN = 32 (i.e. <<_c_isa_extension>> is disabled) then `mepc[1]` is also hardwired to zero.


{empty} +
[discrete]
===== **`mcause`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap cause
| Address     | `0x342`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mcause` CSRs shows the exact cause of a trap. See section <<_traps_exceptions_and_interrupts>> for a list of all legal values.
|=======================

.Read-Only
[IMPORTANT]
Note that the NEORV32 `mcause` CSR is updated by the hardware only and cannot be written from software.
However, any write-access will be ignored and will not cause any exception to maintain RISC-V compatibility.


.`mcause` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 4:0 | r/w | **Exception code**: see <<_neorv32_trap_listing>>
| 31  | r/w | **Interrupt**: `1` if the trap is caused by an interrupt (`0` if the trap is caused by an exception)
|=======================


{empty} +
[discrete]
===== **`mtval`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap value
| Address     | `0x343`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mtval` CSR provides additional information why a trap was entered. See section <<_traps_exceptions_and_interrupts>> for more information.
|=======================

.Read-Only
[IMPORTANT]
Note that the NEORV32 `mtval` CSR is updated by the hardware only and cannot be written from software.
However, any write-access will be ignored and will not cause any exception to maintain RISC-V compatibility.


{empty} +
[discrete]
===== **`mip`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine interrupt pending
| Address     | `0x344`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mip` CSR shows currently _pending_ machine-mode interrupt requests. Any write access to this register is ignored.
|=======================

.`mip` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 3     | `CSR_MIP_MSIP`                       | r/- | **MSIP**: Machine _software_ interrupt pending, triggered by `msi_i` top port (see <<_cpu_top_entity_signals>>); cleared by source-specific mechanism
| 7     | `CSR_MIP_MTIP`                       | r/- | **MTIP**: Machine _timer_ interrupt pending, triggered by `mei_i` top port (see <<_cpu_top_entity_signals>>) or by the processor-internal <<_core_local_interruptor_clint>>; cleared by source-specific mechanism
| 11    | `CSR_MIP_MEIP`                       | r/- | **MEIP**: Machine _external_ interrupt pending, triggered by `mti_i` top port (see <<_cpu_top_entity_signals>>) or by the processor-internal <<_core_local_interruptor_clint>>; cleared by source-specific mechanism
| 31:16 | `CSR_MIP_FIRQ15P` : `CSR_MIP_FIRQ0P` | r/- | **FIRQxP**: Fast interrupt channel 15..0 pending, see <<_neorv32_specific_fast_interrupt_requests>>; cleared by source-specific 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.


{empty} +
[discrete]
===== **`mtinst`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap instruction
| Address     | `0x34a`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The `mtinst` CSR provides additional information why a trap was entered. See section <<_traps_exceptions_and_interrupts>> for more information.
|=======================

.Read-Only
[IMPORTANT]
Note that the NEORV32 `mtinst` CSR is updated by the hardware only and cannot be written from software.
However, any write-access will be ignored and will not cause any exception to maintain RISC-V compatibility.

.Instruction Transformation
[IMPORTANT]
The RISC-V priv. spec. suggests that the instruction word written to `mtinst` by the hardware should be "transformed".
However, the NEORV32 `mtinst` CSR uses a simplified transformation scheme: if the trap-causing instruction is a
standard 32-bit instruction, `mtinst` contains the exact instruction word that caused the trap. If the trap-causing
instruction is a compressed instruction, `mtinst` contains the de-compressed 32-bit equivalent with bit 1 being cleared
while all remaining bits represent the pre-decoded 32-bit instruction equivalent.



<<<
// ####################################################################################################################
:sectnums:
==== Machine Configuration CSRs

[discrete]
===== **`menvcfg`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine environment configuration register - low word
| Address     | `0x30a`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `U`
| Description | Currently, the features of this CSR are not supported. Hence, the entire register is hardwired to all-zero.
|=======================


{empty} +
[discrete]
===== **`menvcfgh`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine environment configuration register - high word
| Address     | `0x31a`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `U`
| Description | Currently, the features of this CSR are not supported. Hence, the entire register is hardwired to all-zero.
|=======================



<<<
// ####################################################################################################################
:sectnums:
==== Machine Physical Memory Protection CSRs

The physical memory protection system is configured via the `PMP_NUM_REGIONS` and `PMP_MIN_GRANULARITY` top entity
generics. `PMP_NUM_REGIONS` defines the total number of implemented regions. Note that the maximum number of regions
is constrained to 16. If trying to access a PMP-related CSR beyond `PMP_NUM_REGIONS` (but below PMP configuration/address
register 16) **no illegal instruction exception** is triggered. The according CSRs are read-only (writes are ignored) and
always return zero. See section <<_smpmp_isa_extension>> for more information.

[discrete]
===== **`pmpcfg`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Physical memory protection region configuration registers
| Address     | `0x3a0` (`pmpcfg0`)
|             | `0x3a1` (`pmpcfg1`)
|             | `0x3a2` (`pmpcfg2`)
|             | `0x3a3` (`pmpcfg3`)
| Reset value | all `0x00000000`
| ISA         | `Zicsr` & `Smpmp`
| Description | Configuration of physical memory protection regions. Each region provides an individual 8-bit array in these CSRs.
Note that, depending on `PMP_NUM_REGIONS`, a **maximum** of the lowest 4 configuration registers are physically implemented (`pmpcfg0 .. pmpcfg3`).
All remaining register are hardwired to zero.
|=======================

.`pmpcfg*` CSR Bits
[cols="^1,<2,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 0   | `PMPCFG_R`     | r/w | **R**: Read permission
| 1   | `PMPCFG_W`     | r/w | **W**: Write permission
| 2   | `PMPCFG_X`     | r/w | **X**: Execute permission
| 4:3 | `PMPCFG_A_MSB` : `PMPCFG_A_LSB` | r/w | **A**: Mode configuration (`00` = OFF, `01` = TOR, `10` = NA4, `11` = NAPOT)
| 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
|=======================

.Implemented Modes
[NOTE]
In order to reduce the CPU size certain PMP modes (`A` bits) can be excluded from synthesis.
Use the `PMP_TOR_MODE_EN` and `PMP_NAP_MODE_EN` <<_processor_top_entity_generics>> to control
implementation of the according modes.

{empty} +
[discrete]
===== **`pmpaddr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Physical memory protection region address registers
| Address     | `0x3b0` (`pmpaddr1`)
|             | `0x3b1` (`pmpaddr2`)
|             | `0x3b2` (`pmpaddr3`)
|             | `0x3b3` (`pmpaddr4`)
|             | `0x3b4` (`pmpaddr5`)
|             | `0x3b5` (`pmpaddr6`)
|             | `0x3b6` (`pmpaddr6`)
|             | `0x3b7` (`pmpaddr7`)
|             | `0x3b8` (`pmpaddr8`)
|             | `0x3b9` (`pmpaddr9`)
|             | `0x3ba` (`pmpaddr10`)
|             | `0x3bb` (`pmpaddr11`)
|             | `0x3bc` (`pmpaddr12`)
|             | `0x3bd` (`pmpaddr13`)
|             | `0x3be` (`pmpaddr14`)
|             | `0x3bf` (`pmpaddr15`)
| Reset value | all `0x00000000`
| ISA         | `Zicsr` & `Smpmp`
| Description | Region address/boundaries configuration.
Note that, depending on `PMP_NUM_REGIONS`, a **maximum** of the lowest 16 address registers are physically implemented (`pmpaddr0 .. pmpaddr15`).
All remaining register are hardwired to zero.
|=======================

.`pmpaddr*` CSR Bits
[cols="^1,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit   | R/W | Description
| 31:30 | r-w | address bits `33 downto 32`´, hardwired to zero
| 29:0  | r/w | address bits `31 downto 2`
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== (Machine) Counter and Timer CSRs

.`time[h]` CSRs (Wall Clock Time)
[IMPORTANT]
The NEORV32 does not implement the user-mode `time[h]` registers. Any access to these registers will trap.
It is recommended that the trap handler software provides a means of accessing the machine timer oft the
<<_core_local_interruptor_clint>>.

.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.


[discrete]
===== **`cycle[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Cycle counter
| Address     | `0xc00` (`cycle`)
|             | `0xc80` (`cycleh`)
| Reset value | `0x00000000_00000000`
| ISA         | `Zicsr` & `Zicntr`
| Description | The `cycle[h]` CSRs are user-mode shadow copies of the according <<_mcycleh>> CSRs. The user-mode
counter are read-only. Any write access will raise an illegal instruction exception.
|=======================


{empty} +
[discrete]
===== **`instret[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Instructions-retired counter
| Address     | `0xc02` (`instret`)
|             | `0xc82` (`instreth`)
| Reset value | `0x00000000_00000000`
| ISA         | `Zicsr` & `Zicntr`
| Description | The `instret[h]` CSRs are user-mode shadow copies of the according <<_minstreth>> CSRs. The user-mode
counter are read-only. Any write access will raise an illegal instruction exception.
|=======================


{empty} +
[discrete]
===== **`mcycle[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine cycle counter
| Address     | `0xb00` (`mcycle`)
|             | `0xb80` (`mcycleh`)
| Reset value | `0x00000000_00000000`
| ISA         | `Zicsr` & `Zicntr`
| 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.
|=======================


{empty} +
[discrete]
===== **`minstret[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine instructions-retired counter
| Address     | `0xb02` (`minstret`)
|             | `0xb82` (`minstreth`)
| Reset value | `0x00000000_00000000`
| ISA         | `Zicsr` & `Zicntr`
| Description | 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
|=======================

.Instruction Retiring
[IMPORTANT]
Note that **all** executed instruction do increment the `[m]instret[h]` counters even if they do not retire
(e.g. if the instruction causes an exception).


<<<
// ####################################################################################################################
:sectnums:
==== Hardware Performance Monitors (HPM) CSRs

.Machine-Mode HPMs Only
[NOTE]
Note that only the machine-mode hardware performance counter CSR are available (`mhpmcounter*[h]`).
Accessing any user-mode HPM CSR (`hpmcounter*[h]`) will raise an illegal instruction exception.

The actual number of implemented hardware performance monitors is configured via the `HPM_NUM_CNTS` top entity generic,
Note that always all 13 HPM counter and configuration registers (`mhpmcounter*[h]`) 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 reads 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.


[discrete]
===== **`mhpmevent`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware performance monitor event select
| Address     | `0x233` (`mhpmevent3`)
|             | `0x234` (`mhpmevent4`)
|             | `0x235` (`mhpmevent5`)
|             | `0x236` (`mhpmevent6`)
|             | `0x237` (`mhpmevent7`)
|             | `0x238` (`mhpmevent8`)
|             | `0x239` (`mhpmevent9`)
|             | `0x23a` (`mhpmevent10`)
|             | `0x23b` (`mhpmevent11`)
|             | `0x23c` (`mhpmevent12`)
|             | `0x23d` (`mhpmevent13`)
|             | `0x23e` (`mhpmevent14`)
|             | `0x23f` (`mhpmevent15`)
| Reset value | all `0x00000000`
| ISA         | `Zicsr` & `Zihpm`
| Description | The value in these CSRs define the micro-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 enabled, 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.
|=======================

.`mhpmevent*` CSR Bits (Micro-Architectural Counter Events)
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C]                | R/W | Event Description
4+^| **RISC-V-compatible**
| 0   | `HPMCNT_EVENT_CY`       | r/w | active clock cycle (CPU not in <<_sleep_mode>>)
| 1   | `HPMCNT_EVENT_TM`       | r/- | _not implemented_, hardwired to zero
| 2   | `HPMCNT_EVENT_IR`       | r/w | any executed instruction (16-bit/compressed or 32-bit/uncompressed)
4+^| **NEORV32-specific**
| 3   | `HPMCNT_EVENT_COMPR`    | r/w | any executed 16-bit/compressed (<<_c_isa_extension>>) instruction
| 4   | `HPMCNT_EVENT_WAIT_DIS` | r/w | instruction dispatch wait cycle (wait for instruction prefetch-buffer refill (<<_cpu_control_unit>> IPB);
caused by a fence instruction, a control flow transfer or a instruction fetch bus wait cycle)
| 5   | `HPMCNT_EVENT_WAIT_ALU` | r/w | any delay/wait cycle caused by a _multi-cycle_ <<_cpu_arithmetic_logic_unit>> operation
| 6   | `HPMCNT_EVENT_BRANCH`   | r/w | any executed branch instruction (unconditional, conditional-taken or conditional-not-taken)
| 7   | `HPMCNT_EVENT_BRANCHED` | r/w | any control transfer operation (unconditional jump, taken conditional branch or trap entry/exit)
| 8   | `HPMCNT_EVENT_LOAD`     | r/w | any executed load operation (read-modify-write AMOs are counted as one load and one store operation)
| 9   | `HPMCNT_EVENT_STORE`    | r/w | any executed store operation (read-modify-write AMOs are counted as one load and one store operation)
| 10  | `HPMCNT_EVENT_WAIT_LSU` | r/w | any memory/bus/cache/etc. delay/wait cycle while executing any load or store operation (caused by a data bus wait cycle))
| 11  | `HPMCNT_EVENT_TRAP`     | r/w | starting processing of any trap (<<_traps_exceptions_and_interrupts>>)
|=======================

.Instruction Retiring ("Retired == Executed")
[IMPORTANT]
The CPU HPM/counter logic treats all executed instruction as "retired" even if they raise an exception,
cause an interrupt, trigger a privilege mode change or were not meant to retire (i.e. claimed by the RISC-V spec.).

.Atomic Memory Access
[NOTE]
The read-modify-write instructions of the <<_zaamo_isa_extension>> operate as simple load for the CPU hardware.
Hence, they will only trigger `HPMCNT_EVENT_LOAD` and only once.


{empty} +
[discrete]
===== **`mhpmcounter[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware performance monitor (HPM) counter
| Address     | `0xb03`, `0xb83` (`mhpmcounter3`, `mhpmcounter3h`)
|             | `0xb04`, `0xb84` (`mhpmcounter4`, `mhpmcounter4h`)
|             | `0xb05`, `0xb85` (`mhpmcounter5`, `mhpmcounter5h`)
|             | `0xb06`, `0xb86` (`mhpmcounter6`, `mhpmcounter6h`)
|             | `0xb07`, `0xb87` (`mhpmcounter7`, `mhpmcounter7h`)
|             | `0xb08`, `0xb88` (`mhpmcounter8`, `mhpmcounter8h`)
|             | `0xb09`, `0xb89` (`mhpmcounter9`, `mhpmcounter9h`)
|             | `0xb0a`, `0xb8a` (`mhpmcounter10`, `mhpmcounter10h`)
|             | `0xb0b`, `0xb8b` (`mhpmcounter11`, `mhpmcounter11h`)
|             | `0xb0c`, `0xb8c` (`mhpmcounter12`, `mhpmcounter12h`)
|             | `0xb0d`, `0xb8d` (`mhpmcounter13`, `mhpmcounter13h`)
|             | `0xb0e`, `0xb8e` (`mhpmcounter14`, `mhpmcounter14h`)
|             | `0xb0f`, `0xb8f` (`mhpmcounter15`, `mhpmcounter15h`)
| Reset value | all `0x00000000_00000000`
| ISA         | `Zicsr` & `Zihpm`
| Description | If not halted via the <<_mcountinhibit>> CSR the HPM counter CSRs increment whenever the
configured events from the according <<_mhpmevent>> CSR occur. The HPM counter registers are read/write for machine mode
software and are not accessible for lower-privileged software.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Counter Setup CSRs


[discrete]
===== **`mcountinhibit`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine counter-inhibit register
| Address     | `0x320`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | Set bit to halt the according counter CSR.
|=======================

.`mcountinhibit` CSR Bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 0    | `CSR_MCOUNTINHIBIT_IR` | r/w | **IR**: Set to `1` to halt `[m]instret[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
| 1    | -                      | r/- | **TM**: Hardwired to zero as `time[h]` CSRs are not implemented
| 2    | `CSR_MCOUNTINHIBIT_CY` | r/w | **CY**: Set to `1` to halt `[m]cycle[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
| 15:3 | `CSR_MCOUNTINHIBIT_HPM3` : `CSR_MCOUNTINHIBIT_HPM15` | r/w | **HPMx**: Set to `1` to halt `[m]hpmcount*[h]`; hardwired to zero if `Zihpm` ISA extension is disabled
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Information CSRs

[discrete]
===== **`mvendorid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine vendor ID
| Address     | `0xf11`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | Read-only and hardwired to zero.
|=======================


{empty} +
[discrete]
===== **`marchid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine architecture ID
| Address     | `0xf12`
| Reset value | `0x00000013`
| ISA         | `Zicsr`
| Description | The `marchid` CSR is read-only and provides the NEORV32 official RISC-V open-source architecture ID
(decimal: 19, 32-bit hexadecimal: 0x00000013).
|=======================


{empty} +
[discrete]
===== **`mimpid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine implementation ID
| Address     | `0xf13`
| Reset value | `DEFINED`
| ISA         | `Zicsr`
| Description | 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).
|=======================


{empty} +
[discrete]
===== **`mhartid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware thread ID
| Address     | `0xf14`
| Reset value | `DEFINED`
| ISA         | `Zicsr`
| Description | The `mhartid` CSR is read-only and provides the core's hart ID. In a multi-core system, the hard
ID of each core is unique and starts at 0 and is incremented continuously.
|=======================


{empty} +
[discrete]
===== **`mconfigptr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine configuration pointer register
| Address     | `0xf15`
| Reset value | `0x00000000`
| ISA         | `Zicsr`
| Description | The features of this CSR are not implemented yet. The register is read-only and always returns zero.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== NEORV32-Specific CSRs

.RISC-V-Compliant Mapping
[NOTE]
All NEORV32-specific CSRs are mapped to addresses that are explicitly reserved for custom/implementation-specific use.


[discrete]
===== **`mxcsr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine status and control register
| Address     | `0xbc0`
| Reset value | `DEFINED`
| ISA         | `Zicsr` & `X`
| Description | The `mxcsr` CSR is a NEORV32-specific read/write CSR that provides additional
machine configurations and status information.
|=======================

.`mxcsr` CSR Bits
[cols="^1,<2,^1,<6"]
[options="header",grid="rows"]
|=======================
| Bit   | Name [C] | R/W | Description
| 25:0  | -                     | r/- | _reserved_, read as zero
| 26    | `CSR_MXCSR_TRACE`     | r/- | <<_cpu_tuning_options>>: CPU trace generator and <<_execution_trace_port>> enabled (implicitly enabled when enabling <<_execution_trace_buffer_tracer>>)
| 27    | `CSR_MXCSR_CONSTTBR`  | r/- | <<_cpu_tuning_options>>: constant-time branches enabled when set (`CPU_CONSTT_BR_EN` top generic)
| 28    | `CSR_MXCSR_RFHWRST`   | r/- | <<_cpu_tuning_options>>: full hardware reset of register file available when set (`CPU_RF_HW_RST_EN` top generic)
| 29    | `CSR_MXCSR_FASTMUL`   | r/- | <<_cpu_tuning_options>>: fast multiplication available when set (`CPU_FAST_MUL_EN` top generic)
| 30    | `CSR_MXCSR_FASTSHIFT` | r/- | <<_cpu_tuning_options>>: fast shifts available when set (`CPU_FAST_SHIFT_EN` top generic)
| 31    | `CSR_MXCSR_IS_SIM`    | r/- | set if CPU is being _simulated_ (not guaranteed)
|=======================


{empty} +
[discrete]
===== **`mxisa`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine extended ISA and extensions register
| Address     | `0xfc0`
| Reset value | `DEFINED`
| ISA         | `Zicsr` & `X`
| Description | The `mxisa` CSR is a NEORV32-specific read-only CSR that helps machine-mode software to
discover additional ISA (sub-)extensions and CPU configuration options.
|=======================

.`mxisa` CSR Bits
[cols="^1,<2,^1,<6"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
|  0  | `CSR_MXISA_ZICSR`    | r/- | <<_zicsr_isa_extension>> available
|  1  | `CSR_MXISA_ZIFENCEI` | r/- | <<_zifencei_isa_extension>> available
|  2  | `CSR_MXISA_ZMMUL`    | r/- | <<_zmmul_isa_extension>> available
|  3  | `CSR_MXISA_ZXCFU`    | r/- | <<_zxcfu_isa_extension>> available
|  4  | `CSR_MXISA_ZKT`      | r/- | <<_zkt_isa_extension>> available
|  5  | `CSR_MXISA_ZFINX`    | r/- | <<_zfinx_isa_extension>> available
|  6  | `CSR_MXISA_ZICOND`   | r/- | <<_zicond_isa_extension>> available
|  7  | `CSR_MXISA_ZICNTR`   | r/- | <<_zicntr_isa_extension>> available
|  8  | `CSR_MXISA_SMPMP`    | r/- | <<_smpmp_isa_extension>> available
|  9  | `CSR_MXISA_ZIHPM`    | r/- | <<_zihpm_isa_extension>> available
| 10  | `CSR_MXISA_SDEXT`    | r/- | <<_sdext_isa_extension>> available
| 11  | `CSR_MXISA_SDTRIG`   | r/- | <<_sdtrig_isa_extension>> available
| 12  | `CSR_MXISA_ZBKX`     | r/- | <<_zbkx_isa_extension>> available
| 13  | `CSR_MXISA_ZKND`     | r/- | <<_zknd_isa_extension>> available
| 14  | `CSR_MXISA_ZKNE`     | r/- | <<_zkne_isa_extension>> available
| 15  | `CSR_MXISA_ZKNH`     | r/- | <<_zknh_isa_extension>> available
| 16  | `CSR_MXISA_ZBKB`     | r/- | <<_zbkb_isa_extension>> available
| 17  | `CSR_MXISA_ZBKC`     | r/- | <<_zbkc_isa_extension>> available
| 18  | `CSR_MXISA_ZKN`      | r/- | <<_zkn_isa_extension>> available
| 19  | `CSR_MXISA_ZKSH`     | r/- | <<_zksh_isa_extension>> available
| 20  | `CSR_MXISA_ZKSED`    | r/- | <<_zksed_isa_extension>> available
| 21  | `CSR_MXISA_ZKS`      | r/- | <<_zks_isa_extension>> available
| 22  | `CSR_MXISA_ZBA`      | r/- | <<_zba_isa_extension>> available
| 23  | `CSR_MXISA_ZBB`      | r/- | <<_zbb_isa_extension>> available
| 24  | `CSR_MXISA_ZBS`      | r/- | <<_zbs_isa_extension>> available
| 25  | `CSR_MXISA_ZAAMO`    | r/- | <<_zaamo_isa_extension>> available
| 26  | `CSR_MXISA_ZALRSC`   | r/- | <<_zalrsc_isa_extension>> available
| 27  | `CSR_MXISA_ZCB`      | r/- | <<_zcb_isa_extension>> available
| 28  | `CSR_MXISA_ZCA`      | r/- | "`C` without floating-point", available when <<_c_isa_extension>> is available
| 29  | `CSR_MXISA_ZIBI`     | r/- | <<_zibi_isa_extension>> available
| 30  | `CSR_MXISA_ZIMOP`    | r/- | <<_zimop_isa_extension>> available
| 31  | -                    | r/- | _reserved_, read as zero
|=======================
