Skip to content

Commit

Permalink
🐛⚠️ CPU bug-fixes, major cleanups and optimizations (#586)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting authored Apr 16, 2023
2 parents ee3d50d + d317003 commit 4b2a724
Show file tree
Hide file tree
Showing 14 changed files with 663 additions and 602 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 15.04.2023 | 1.8.3.7 | :bug: :warning: `wfi` and XIRQ bug fixes; massive RTL code cleanup and optimization of CPU control; [#586](https://github.com/stnolting/neorv32/pull/586) |
| 14.04.2023 | 1.8.3.6 | [UARTs] software can now retrieve the configured RX/TX FIFO sizes from the `DATA` register; [#581](https://github.com/stnolting/neorv32/pull/581) |
| 13.04.2023 | 1.8.3.5 | :bug: fixed bug in FPU control logic (introduced in some earlier clean-up commit); minor code edits and optimizations; [#578](https://github.com/stnolting/neorv32/pull/578) |
| 07.04.2023 | 1.8.3.4 | rtl edits and cleanups; [#571](https://github.com/stnolting/neorv32/pull/571) |
Expand Down
21 changes: 11 additions & 10 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -165,17 +165,17 @@ includes the <<_control_and_status_registers_csrs>> as well as the trap controll
=== Sleep Mode

The NEORV32 CPU provides a single sleep mode that can be entered to power-down the core reducing dynamic
power consumption. Sleep mode in entered by executing the `wfi` instruction.
When the CPU is in sleep mode, all CPU-internal operations are stopped (execution, instruction fetch, ...).
However, this does not affect the operation of any peripheral/IO modules like interfaces and timers. Furthermore,
the CPU will continue to buffer/enqueue incoming interrupt requests. The CPU will leave sleep mode as soon as
any interrupt source becomes _pending_.
power consumption. Sleep mode in entered by executing the `wfi` instruction. When in sleep mode, all CPU-internal
operations are stopped (execution, instruction fetch, counter increments, ...). However, this does not affect the
operation of any peripheral/IO modules like interfaces and timers. Furthermore, the CPU will continue to buffer/enqueue
incoming interrupt requests. The CPU will leave sleep mode as soon as any _enabled_ interrupt source becomes _pending_.

[IMPORTANT]
If sleep mode is entered without at least one enabled interrupt source the CPU will be _permanently_ halted.

[NOTE]
The CPU automatically wakes up from sleep mode if a debug session via the on-chip debugger is started.
The CPU automatically wakes up from sleep mode if a debug session is started via the on-chip debugger. `wfi` behaves as
a simple `nop` when the CPU is _in_ debug-mode or during single-stepping.


// ####################################################################################################################
Expand Down Expand Up @@ -671,9 +671,10 @@ cause ID of the according trap that is written to <<_mcause>> CSR. The "ID [C]"
core library (the runtime environment _RTE_) and can be used in plain C code. The <<_mepc>> and <<_mtval>> columns
show the values written to the according CSRs when a trap is triggered:

* **I-PC** - address of interrupted instruction (instruction has not been executed yet)
* **I-PC** - address of interrupted instruction (instruction has _not_ been executed yet)
* **PC** - address of instruction that caused the trap (instruction has been executed)
* **ADR** - bad memory access address that caused the trap
* **CMD** - the instruction word that caused the trap (zero-extended if compressed instruction)
* **0** - zero

.NEORV32 Trap Listing
Expand All @@ -682,9 +683,9 @@ show the values written to the according CSRs when a trap is triggered:
|=======================
| Prio. | `mcause` | ID [C] | Cause | `mepc` | `mtval`
6+^| **Exceptions** (synchronous to instruction execution)
| 1 | `0x00000000` | `TRAP_CODE_I_MISALIGNED` | instruction address misaligned | **PC** | **ADR**
| 2 | `0x00000001` | `TRAP_CODE_I_ACCESS` | instruction access bus fault | **I-PC** | **ADR**
| 3 | `0x00000002` | `TRAP_CODE_I_ILLEGAL` | illegal instruction | **PC** | **0**
| 1 | `0x00000000` | `TRAP_CODE_I_MISALIGNED` | instruction address misaligned | **I-PC** | **0**
| 2 | `0x00000001` | `TRAP_CODE_I_ACCESS` | instruction access bus fault | **I-PC** | **0**
| 3 | `0x00000002` | `TRAP_CODE_I_ILLEGAL` | illegal instruction | **PC** | **CMD**
| 4 | `0x0000000B` | `TRAP_CODE_MENV_CALL` | environment call from M-mode (`ecall`) | **PC** | **0**
| 5 | `0x00000008` | `TRAP_CODE_UENV_CALL` | environment call from U-mode (`ecall`) | **PC** | **0**
| 6 | `0x00000003` | `TRAP_CODE_BREAKPOINT` | software breakpoint (`ebreak`) | **PC** | **0**
Expand Down
34 changes: 23 additions & 11 deletions docs/datasheet/cpu_csr.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ Any illegal read access to a CSR will return zero in the operation's destination
| 0x343 | <<_mtval>> | `CSR_MTVAL` | MRW | Machine bad address or instruction
| 0x344 | <<_mip>> | `CSR_MIP` | MRW | Machine interrupt pending register
5+^| **<<_machine_physical_memory_protection_csrs>>**
| 0x3A0 .. 0x3A3 | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>> | `CSR_PMPCFG0` .. `CSR_PMPCFG3` | MRW | Physical memory protection configuration for region 0..15
| 0x3B0 .. 0x3BF | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | `CSR_PMPADDR0` .. `CSR_PMPADDR15` | MRW | Physical memory protection address register region 0..15
| 0x3A0 .. 0x3AF | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg15`>> | `CSR_PMPCFG0` .. `CSR_PMPCFG15` | MRW | Physical memory protection configuration for region 0..15
| 0x3B0 .. 0x3EF | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr63`>> | `CSR_PMPADDR0` .. `CSR_PMPADDR63` | MRW | Physical memory protection address register region 0..15
5+^| **<<_trigger_module_csrs>>**
| 0x7A0 | <<_tselect>> | `CSR_TSELECT` | MRW | Trigger select register
| 0x7A1 | <<_tdata1>> | `CSR_TDATA1` | MRW | Trigger data register 1
Expand Down Expand Up @@ -447,14 +447,19 @@ an instruction is triggered / an exception is raised. See section <<_traps_excep
| Description | The `mtval` CSR provides additional information why a trap was entered. See section <<_traps_exceptions_and_interrupts>> for more information
|=======================

[IMPORTANT]
Note that the NEORV32 `mtval` register is read only. Any write-access will be ignored and will not cause an exception to
maintain RISC-V compatibility.

.`mtval` CSR bits
[cols="^5,^5"]
[options="header",grid="rows"]
|=======================
| Trap cause | `mtval` content
| Trap cause | `mtval` value
| 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)
| illegal instruction | instruction word that caused the exception (zero-extended if compressed instruction)
| everything else (including all interrupts) | all-zero
|=======================


Expand Down Expand Up @@ -498,11 +503,10 @@ interrupt-triggering processor module.
==== 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. 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. 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. See section <<_pmp_isa_extension>> for more information.
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 <<_pmp_isa_extension>> for more information.

[discrete]
===== **`pmpcfg`**
Expand All @@ -511,12 +515,16 @@ implemented at all. See section <<_pmp_isa_extension>> for more information.
[frame="topbot",grid="none"]
|=======================
| Name | PMP region configuration registers
| Address | `0x3a0` (`pmpcfg0`) ... `0x3a3` (`pmpcfg3`)
| Address | `0x3a0` (`pmpcfg0`) ... `0x3af` (`pmpcfg15`)
| Reset value | `0x00000000`
| ISA | `Zicsr` + `PMP`
| Description | Configuration of physical memory protection regions. Each region provides an individual 8-bit array in these CSRs.
|=======================

[IMPORTANT]
Note that only PMP configuration registers `pmpcfg0` to `pmpcfg3` will be implemented if `PMP_NUM_REGIONS` is set to its
maximum value (=16). The remaining `pmpcfg4` to `pmpcfg15` CSRs are read-only and will always read as zero.

.`pmpcfg0` CSR Bits
[cols="^1,^2,^1,<11"]
[options="header",grid="rows"]
Expand All @@ -541,12 +549,16 @@ The `pmpaddr*` CSRs are used to configure the region's address boundaries.
[frame="topbot",grid="none"]
|=======================
| Name | Physical memory protection address registers
| Address | `0x3b0` (`pmpaddr0`) ... `0x3bf` (`pmpaddr15`)
| Address | `0x3b0` (`pmpaddr0`) ... `0x3ef` (`pmpaddr63`)
| Reset value | `0x00000000`
| ISA | `Zicsr` + `PMP`
| Description | Region address configuration. The two MSBs of each CSR are hardwired to zero (= bits 33:32 of the physical address).
|=======================

[IMPORTANT]
Note that only PMP address registers `pmpaddr0` to `pmpaddr15` will be implemented if `PMP_NUM_REGIONS` is set to its
maximum value (=16). The remaining `pmpaddr16` to `pmpaddr63` CSRs are read-only and will always read as zero.

.Address Register Update Latency
[IMPORTANT]
After writing a `pmpaddr` CSR the hardware requires up to 32 clock cycles to compute the according
Expand Down
2 changes: 1 addition & 1 deletion docs/datasheet/software.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ The `crt0.S` start-up performs the following operations:
** `mains`'s return value is copied to the <<_mscratch>> CSR to allow inspection by the debugger.
** Call all _destructors_ (if there are any).
** An optional <<_after_main_handler>> is called (if defined at all).
** The CPU enters sleep mode (using the `wfi` instruction) or remains in an endless loop (if `wfi` "returns").
** The CPU enters sleep mode (executing the `wfi` instruction) in an endless loop.
.Bootloader Start-Up Code
[NOTE]
Expand Down
23 changes: 13 additions & 10 deletions docs/datasheet/software_rte.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,23 @@ try to resume normal program execution. Some exemplary RTE outputs are shown bel
[WARNING]
In most cases the RTE can successfully continue operation - for example if it catches an **interrupt** request
that is not handled by the actual application program. However, if the RTE catches an un-handled **trap** like
a bus access fault exception continuing execution will most likely fail making the CPU crash.
a bus access fault exception continuing execution will most likely fail making the CPU crash. Some exceptions
cannot be resolved by the default debug trap handlers and will halt the CPU (see example below).

.RTE Default Trap Handler Output Examples
[source]
----
<RTE> Illegal instruction @ PC=0x000002d6, INST=0x000000FF </RTE> <1>
<RTE> Illegal instruction @ PC=0x00000302, INST=0x0000 </RTE> <2>
<RTE> Load address misaligned @ PC=0x00000440, ADDR=0x80000101 </RTE> <3>
<RTE> Fast IRQ 0x00000003 @ PC=0x00000820 </RTE> <4>
<RTE> [M] Illegal instruction @ PC=0x000002d6, MTVAL=0x000000FF </RTE> <1>
<RTE> [U] Illegal instruction @ PC=0x00000302, MTVAL=0x00000000 </RTE> <2>
<RTE> [U] Load address misaligned @ PC=0x00000440, MTVAL=0x80000101 </RTE> <3>
<RTE> [M] Fast IRQ 0x00000003 @ PC=0x00000820, MTVAL=0x00000000 </RTE> <4>
<RTE> [M] Instruction access fault @ PC=0x90000000, MTVAL=0x00000000 [FATAL EXCEPTION] Halting CPU. </RTE>\n <5>
----
<1> Illegal 32-bit instruction at address `0x000002d6`.
<2> Illegal 16-bit instruction at address `0x00000302`.
<3> Misaligned load access at address `0x00000440` (trying to load a full 32-bit word from address `0x80000101`).
<4> Fast interrupt request from channel 3 before executing instruction at address `0x00000820`.
<1> Illegal 32-bit instruction `0x000000FF` at address `0x000002d6` while the CPU was in machine-mode (`[M]`).
<2> Illegal 16-bit instruction `0x0000` (zero-extended) at address `0x00000302` while the CPU was in user-mode (`[U]`).
<3> Misaligned load access at address `0x00000440` (trying to load a full 32-bit word from address `0x80000101`) while the CPU was in machine-mode.
<4> Fast interrupt request from channel 3 before executing instruction at address `0x00000820` while the CPU was in machine-mode.
<5> Instruction bus access fault at address `0x90000000` - this is fatal for the default debug trap handler while the CPU was in machine-mode.

The specific message right at the beginning of the debug trap handler message corresponds to the trap code
obtained from the <<_mcause>> CSR (see <<_neorv32_trap_listing>>). A full list of all messages and the according
Expand Down Expand Up @@ -209,7 +212,7 @@ For bus access faults the RTE default trap handlers also outputs the error code
----

The additional message encapsulated in `[ ]` shows the actual cause of the bus access fault.
Three different messages are possible here:
Several different message identifiers are possible here:

* `[TIMEOUT_ERR]`: The accessed memory-mapped module did not respond within the valid access time window.
In Most cases this is caused by accessing a module that has not been implemented or when accessing
Expand Down
Loading

0 comments on commit 4b2a724

Please sign in to comment.