<<<
: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
[IMPORTANT]
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.


.NEORV32 Control and Status Registers (CSRs)
[cols="<2,<4,<5,^1,<11"]
[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+^| **<<_custom_functions_unit_cfu_csrs>>**
| 0x800 .. 0x803 | <<_cfureg, `cfureg0`>> .. <<_cfureg, `cfureg3`>> | `CSR_CFUCREG0` .. `CSR_CFUCREG3` | URW | Custom CFU registers 0 to 3
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>>**
| 0xfc0 | <<_mxisa>> | `CSR_MXISA` | MRO | NEORV32-specific "eXtended" machine CPU ISA and extensions
|=======================


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

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

[cols="<1,<8"]
[frame="topbot",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"]
[frame="topbot",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"]
[frame="topbot",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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine status register - low word
| Address     | `0x300`
| Reset value | `0x00001800`
| 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
|=======================

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


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

[cols="<1,<8"]
[frame="topbot",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
| 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"]
[frame="topbot",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
| 7     | `CSR_MIE_MTIE` | r/w | **MTIE**: Machine _timer_ interrupt enable (from <<_machine_system_timer_mtime>>)
| 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"]
[frame="topbot",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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine counter enable
| Address     | `0x306`
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Zicntr` & `U`
| Description | The `mcounteren` CSR is used to constrain user-mode access to the CPU's counter CSRs.
|=======================

.`mcounteren` CSR bits
[cols="^1,^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/- | not implemented, hardwired to zero
|=======================


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

[cols="<1,<8"]
[frame="topbot",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"]
[frame="topbot",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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine exception program counter
| Address     | `0x341`
| Reset value | `BOOT_ADDR` (CPU boot address, see <<_cpu_top_entity_generics>>)
| 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"]
[frame="topbot",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.
|=======================


.`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"]
[frame="topbot",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 an exception to maintain RISC-V compatibility.


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

[cols="<1,<8"]
[frame="topbot",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; _cleared by platform-defined mechanism_
| 7     | `CSR_MIP_MTIP`                       | r/- | **MTIP**: Machine _timer_ interrupt pending; _cleared by platform-defined mechanism_
| 11    | `CSR_MIP_MEIP`                       | r/- | **MEIP**: Machine _external_ interrupt pending; _cleared by platform-defined mechanism_
| 31:16 | `CSR_MIP_FIRQ15P` : `CSR_MIP_FIRQ0P` | r/- | **FIRQxP**: Fast interrupt channel 15..0 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.


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

[cols="<1,<8"]
[frame="topbot",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 an 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"]
[frame="topbot",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"]
[frame="topbot",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` **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"]
[frame="topbot",grid="none"]
|=======================
| Name        | PMP region configuration registers
| Address     | `0x3a0` (`pmpcfg0`)
|             | `0x3a1` (`pmpcfg1`)
|             | `0x3a2` (`pmpcfg2`)
|             | `0x3a3` (`pmpcfg3`)
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Smpmp`
| Description | Configuration of physical memory protection regions. Each region provides an individual 8-bit array in these CSRs.
|=======================

.`pmpcfg0` 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`**

The `pmpaddr*` CSRs are used to configure the region's address boundaries.

[cols="<1,<8"]
[frame="topbot",grid="none"]
|=======================
| Name        | Physical memory protection 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 | `0x00000000`
| ISA         | `Zicsr` & `Smpmp`
| Description | Region address configuration. The two MSBs of each CSR are hardwired to zero (= bits 33:32 of the physical address).
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Custom Functions Unit (CFU) CSRs

[discrete]
===== **`cfureg`**

[cols="<1,<8"]
[frame="topbot",grid="none"]
|=======================
| Name        | Custom (user-defined) CFU CSRs
| Address     | `0x800` (`cfureg0`)
|             | `0x801` (`cfureg1`)
|             | `0x802` (`cfureg2`)
|             | `0x803` (`cfureg3`)
| Reset value | `0x00000000`
| ISA         | `Zicsr` & `Zxcfu`
| Description | User-defined CSRs to be used within the <<_custom_functions_unit_cfu>>.
|=======================


<<<
// ####################################################################################################################
: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 platform-defined <<_machine_system_timer_mtime>>.

.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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Cycle counter
| Address     | `0xc00` (`cycle`)
|             | `0xc80` (`cycleh`)
| Reset value | `0x00000000`
| 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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Instructions-retired counter
| Address     | `0xc02` (`instret`)
|             | `0xc82` (`instreth`)
| Reset value | `0x00000000`
| 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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine cycle counter
| Address     | `0xb00` (`mcycle`)
|             | `0xb80` (`mcycleh`)
| Reset value | `0x00000000`
| 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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine instructions-retired counter
| Address     | `0xb02` (`minstret`)
|             | `0xb82` (`minstreth`)
| Reset value | `0x00000000`
| 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"]
[frame="topbot",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 | `0x00000000`
| ISA         | `Zicsr` & `Zihpm`
| Description | 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.
|=======================

.`mhpmevent*` CSR Bits
[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 (including atomic memory operations, <<_zalrsc_isa_extension>>)
| 9   | `HPMCNT_EVENT_STORE`    | r/w | any executed store operation (including atomic memory operations, <<_zalrsc_isa_extension>>)
| 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.).


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

[cols="<1,<8"]
[frame="topbot",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 | `0x00000000`
| ISA         | `Zicsr` & `Zihpm`
| Description | If not halted via the <<_mcountinhibit>> CSR the HPM counter CSR(s) increment whenever the
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:
==== Machine Counter Setup CSRs


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

[cols="<1,<8"]
[frame="topbot",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"]
[frame="topbot",grid="none"]
|=======================
| Name        | Machine vendor ID
| Address     | `0xf11`
| Reset value | `DEFINED`
| ISA         | `Zicsr`
| Description | Vendor ID (JEDEC identifier, lowest 11 bits), assigned via the `JEDEC_ID` top generic (<<_processor_top_entity_generics>>).
|=======================


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

[cols="<1,<8"]
[frame="topbot",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"]
[frame="topbot",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"]
[frame="topbot",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,
which is assigned via the `HW_THREAD_ID` top generic (<<_processor_top_entity_generics>>).
|=======================


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

[cols="<1,<8"]
[frame="topbot",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

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


[discrete]
===== **`mxisa`**

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

.`mxisa` CSR Bits
[cols="^1,^3,^1,<5"]
[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_ZALRSC`    | r/- | <<_zalrsc_isa_extension>> available
| 27:26 | -                     | r/- | _reserved_, hardwired to zero
| 28    | `CSR_MXISA_RFHWRST`   | r/- | full hardware reset of register file available when set (`REGFILE_HW_RST`)
| 29    | `CSR_MXISA_FASTMUL`   | r/- | fast multiplication available when set (`FAST_MUL_EN`)
| 30    | `CSR_MXISA_FASTSHIFT` | r/- | fast shifts available when set (`FAST_SHIFT_EN`)
| 31    | `CSR_MXISA_IS_SIM`    | r/- | set if CPU is being **simulated** (⚠️ not guaranteed)
|=======================
