Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for page fault exceptions #786

Merged
merged 11 commits into from
Feb 3, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12

| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
| 01.02.2024 | 1.9.4.2 | :sparkles: add support for page fault exceptions (yet unused) | [#786](https://github.com/stnolting/neorv32/pull/786) |
| 31.01.2024 | 1.9.4.1 | fix trap priority | [#784](https://github.com/stnolting/neorv32/pull/784) |
| 31.01.2024 | [**:rocket:1.9.4**](https://github.com/stnolting/neorv32/releases/tag/v1.9.4) | **New release** | |
| 31.01.2024 | 1.9.3.10 | close illegal compressed instruction decoding loophole | [#783](https://github.com/stnolting/neorv32/pull/783) |
Expand Down
67 changes: 37 additions & 30 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,7 @@ written to the according CSRs when a trap is triggered:
* **PC** - address of instruction that caused the trap (instruction has been executed)
* **ADR** - bad data memory access address that caused the trap
* **INS** - the transformed/decompressed instruction word that caused the trap
* **UND** - undefined
* **0** - zero

.NEORV32 Trap Listing
Expand All @@ -935,51 +936,57 @@ written to the according CSRs when a trap is triggered:
|=======================
| Prio. | `mcause` | RTE Trap ID | Cause | `mepc` | `mtval` | `mtinst`
7+^| **Exceptions** (_synchronous_ to instruction execution)
| 1 | `0x00000001` | `TRAP_CODE_I_ACCESS` | instruction access fault | I-PC | 0 | INS
| 2 | `0x00000002` | `TRAP_CODE_I_ILLEGAL` | illegal instruction | PC | 0 | INS
| 3 | `0x00000000` | `TRAP_CODE_I_MISALIGNED` | instruction address misaligned | PC | 0 | INS
| 4 | `0x0000000b` | `TRAP_CODE_MENV_CALL` | environment call from M-mode | PC | 0 | INS
| 5 | `0x00000008` | `TRAP_CODE_UENV_CALL` | environment call from U-mode | PC | 0 | INS
| 6 | `0x00000003` | `TRAP_CODE_BREAKPOINT` | software breakpoint / trigger firing | PC | 0 | INS
| 7 | `0x00000006` | `TRAP_CODE_S_MISALIGNED` | store address misaligned | PC | ADR | INS
| 8 | `0x00000004` | `TRAP_CODE_L_MISALIGNED` | load address misaligned | PC | ADR | INS
| 9 | `0x00000007` | `TRAP_CODE_S_ACCESS` | store access fault | PC | ADR | INS
| 10 | `0x00000005` | `TRAP_CODE_L_ACCESS` | load access fault | PC | ADR | INS
| 1 | `0x0000000c` | `TRAP_CODE_I_PAGE` | instruction page fault | I-PC | UND | INS
| 2 | `0x00000001` | `TRAP_CODE_I_ACCESS` | instruction access fault | I-PC | 0 | INS
| 3 | `0x00000002` | `TRAP_CODE_I_ILLEGAL` | illegal instruction | PC | 0 | INS
| 4 | `0x00000000` | `TRAP_CODE_I_MISALIGNED` | instruction address misaligned | PC | 0 | INS
| 5 | `0x0000000b` | `TRAP_CODE_MENV_CALL` | environment call from M-mode | PC | 0 | INS
| 6 | `0x00000008` | `TRAP_CODE_UENV_CALL` | environment call from U-mode | PC | 0 | INS
| 7 | `0x00000003` | `TRAP_CODE_BREAKPOINT` | software breakpoint / trigger firing | PC | 0 | INS
| 8 | `0x00000006` | `TRAP_CODE_S_MISALIGNED` | store address misaligned | PC | ADR | INS
| 9 | `0x00000004` | `TRAP_CODE_L_MISALIGNED` | load address misaligned | PC | ADR | INS
| 10 | `0x0000000f` | `TRAP_CODE_S_PAGE` | store page fault | PC | ADR | INS
| 11 | `0x0000000d` | `TRAP_CODE_L_PAGE` | load page fault | PC | ADR | INS
| 12 | `0x00000007` | `TRAP_CODE_S_ACCESS` | store access fault | PC | ADR | INS
| 13 | `0x00000005` | `TRAP_CODE_L_ACCESS` | load access fault | PC | ADR | INS
7+^| **Interrupts** (_asynchronous_ to instruction execution)
| 11 | `0x80000010` | `TRAP_CODE_FIRQ_0` | fast interrupt request channel 0 | I-PC | 0 | 0
| 12 | `0x80000011` | `TRAP_CODE_FIRQ_1` | fast interrupt request channel 1 | I-PC | 0 | 0
| 13 | `0x80000012` | `TRAP_CODE_FIRQ_2` | fast interrupt request channel 2 | I-PC | 0 | 0
| 14 | `0x80000013` | `TRAP_CODE_FIRQ_3` | fast interrupt request channel 3 | I-PC | 0 | 0
| 15 | `0x80000014` | `TRAP_CODE_FIRQ_4` | fast interrupt request channel 4 | I-PC | 0 | 0
| 16 | `0x80000015` | `TRAP_CODE_FIRQ_5` | fast interrupt request channel 5 | I-PC | 0 | 0
| 17 | `0x80000016` | `TRAP_CODE_FIRQ_6` | fast interrupt request channel 6 | I-PC | 0 | 0
| 18 | `0x80000017` | `TRAP_CODE_FIRQ_7` | fast interrupt request channel 7 | I-PC | 0 | 0
| 19 | `0x80000018` | `TRAP_CODE_FIRQ_8` | fast interrupt request channel 8 | I-PC | 0 | 0
| 20 | `0x80000019` | `TRAP_CODE_FIRQ_9` | fast interrupt request channel 9 | I-PC | 0 | 0
| 21 | `0x8000001a` | `TRAP_CODE_FIRQ_10` | fast interrupt request channel 10 | I-PC | 0 | 0
| 22 | `0x8000001b` | `TRAP_CODE_FIRQ_11` | fast interrupt request channel 11 | I-PC | 0 | 0
| 23 | `0x8000001c` | `TRAP_CODE_FIRQ_12` | fast interrupt request channel 12 | I-PC | 0 | 0
| 24 | `0x8000001d` | `TRAP_CODE_FIRQ_13` | fast interrupt request channel 13 | I-PC | 0 | 0
| 25 | `0x8000001e` | `TRAP_CODE_FIRQ_14` | fast interrupt request channel 14 | I-PC | 0 | 0
| 26 | `0x8000001f` | `TRAP_CODE_FIRQ_15` | fast interrupt request channel 15 | I-PC | 0 | 0
| 27 | `0x8000000B` | `TRAP_CODE_MEI` | machine external interrupt (MEI) | I-PC | 0 | 0
| 28 | `0x80000003` | `TRAP_CODE_MSI` | machine software interrupt (MSI) | I-PC | 0 | 0
| 29 | `0x80000007` | `TRAP_CODE_MTI` | machine timer interrupt (MTI) | I-PC | 0 | 0
| 14 | `0x80000010` | `TRAP_CODE_FIRQ_0` | fast interrupt request channel 0 | I-PC | 0 | 0
| 15 | `0x80000011` | `TRAP_CODE_FIRQ_1` | fast interrupt request channel 1 | I-PC | 0 | 0
| 16 | `0x80000012` | `TRAP_CODE_FIRQ_2` | fast interrupt request channel 2 | I-PC | 0 | 0
| 17 | `0x80000013` | `TRAP_CODE_FIRQ_3` | fast interrupt request channel 3 | I-PC | 0 | 0
| 18 | `0x80000014` | `TRAP_CODE_FIRQ_4` | fast interrupt request channel 4 | I-PC | 0 | 0
| 19 | `0x80000015` | `TRAP_CODE_FIRQ_5` | fast interrupt request channel 5 | I-PC | 0 | 0
| 20 | `0x80000016` | `TRAP_CODE_FIRQ_6` | fast interrupt request channel 6 | I-PC | 0 | 0
| 21 | `0x80000017` | `TRAP_CODE_FIRQ_7` | fast interrupt request channel 7 | I-PC | 0 | 0
| 22 | `0x80000018` | `TRAP_CODE_FIRQ_8` | fast interrupt request channel 8 | I-PC | 0 | 0
| 23 | `0x80000019` | `TRAP_CODE_FIRQ_9` | fast interrupt request channel 9 | I-PC | 0 | 0
| 24 | `0x8000001a` | `TRAP_CODE_FIRQ_10` | fast interrupt request channel 10 | I-PC | 0 | 0
| 25 | `0x8000001b` | `TRAP_CODE_FIRQ_11` | fast interrupt request channel 11 | I-PC | 0 | 0
| 26 | `0x8000001c` | `TRAP_CODE_FIRQ_12` | fast interrupt request channel 12 | I-PC | 0 | 0
| 27 | `0x8000001d` | `TRAP_CODE_FIRQ_13` | fast interrupt request channel 13 | I-PC | 0 | 0
| 28 | `0x8000001e` | `TRAP_CODE_FIRQ_14` | fast interrupt request channel 14 | I-PC | 0 | 0
| 29 | `0x8000001f` | `TRAP_CODE_FIRQ_15` | fast interrupt request channel 15 | I-PC | 0 | 0
| 30 | `0x8000000B` | `TRAP_CODE_MEI` | machine external interrupt (MEI) | I-PC | 0 | 0
| 31 | `0x80000003` | `TRAP_CODE_MSI` | machine software interrupt (MSI) | I-PC | 0 | 0
| 32 | `0x80000007` | `TRAP_CODE_MTI` | machine timer interrupt (MTI) | I-PC | 0 | 0
|=======================

.NEORV32 Trap Description
[cols="<3,<7"]
[options="header",grid="rows"]
|=======================
| Trap ID [C] | Triggered when ...
| `TRAP_CODE_I_MISALIGNED` | fetching a 32-bit instruction word that is not 32-bit-aligned (see note below)
| `TRAP_CODE_I_PAGE` | instruction page fault, **no trigger mechanism implemented yet**
| `TRAP_CODE_I_ACCESS` | bus timeout, bus access error or <<_pmp_isa_extension,PMP>> rule violation during instruction fetch
| `TRAP_CODE_I_ILLEGAL` | trying to execute an invalid instruction word (malformed or not supported) or on a privilege violation
| `TRAP_CODE_I_MISALIGNED` | fetching a 32-bit instruction word that is not 32-bit-aligned (see note below)
| `TRAP_CODE_MENV_CALL` | executing `ecall` instruction in machine-mode
| `TRAP_CODE_UENV_CALL` | executing `ecall` instruction in user-mode
| `TRAP_CODE_BREAKPOINT` | executing `ebreak` instruction or if <<_trigger_module>> fires
| `TRAP_CODE_S_MISALIGNED` | storing data to an address that is not naturally aligned to the data size (half/word)
| `TRAP_CODE_L_MISALIGNED` | loading data from an address that is not naturally aligned to the data size (half/word)
| `TRAP_CODE_S_PAGE` | store page fault, **no trigger mechanism implemented yet**
| `TRAP_CODE_L_PAGE` | load page fault, **no trigger mechanism implemented yet**
| `TRAP_CODE_S_ACCESS` | bus timeout, bus access error or <<_pmp_isa_extension,PMP>> rule violation during load data operation
| `TRAP_CODE_L_ACCESS` | bus timeout, bus access error or <<_pmp_isa_extension,PMP>> rule violation during store data operation
| `TRAP_CODE_FIRQ_*` | caused by interrupt-condition of **processor-internal modules**, see <<_neorv32_specific_fast_interrupt_requests>>
Expand Down
86 changes: 48 additions & 38 deletions rtl/core/neorv32_cpu.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ architecture neorv32_cpu_rtl of neorv32_cpu is
signal link_pc : std_ulogic_vector(XLEN-1 downto 0); -- link pc (return address)
signal pmp_ex_fault : std_ulogic; -- PMP instruction fetch fault
signal pmp_rw_fault : std_ulogic; -- PMP read/write access fault
signal i_page_fault : std_ulogic; -- instruction page fault
signal l_page_fault : std_ulogic; -- load page fault
signal s_page_fault : std_ulogic; -- store page fault

begin

Expand Down Expand Up @@ -206,46 +209,45 @@ begin
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
clk_aux_i => clk_aux_i, -- always-on clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_o => ctrl, -- main control bus
clk_i => clk_i, -- global clock, rising edge
clk_aux_i => clk_aux_i, -- always-on clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_o => ctrl, -- main control bus
-- instruction fetch interface --
bus_req_o => ibus_req_o, -- request
bus_rsp_i => ibus_rsp_i, -- response
-- status input --
i_pmp_fault_i => pmp_ex_fault, -- instruction fetch pmp fault
alu_cp_done_i => cp_done, -- ALU iterative operation done
lsu_wait_i => lsu_wait, -- wait for data bus
cmp_i => alu_cmp, -- comparator status
-- data input --
alu_add_i => alu_add, -- ALU address result
rs1_i => rs1, -- rf source 1
-- data output --
imm_o => imm, -- immediate
fetch_pc_o => fetch_pc, -- instruction fetch address
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
link_pc_o => link_pc, -- link PC (return address)
csr_rdata_o => csr_rdata, -- CSR read data
i_page_fault_i => i_page_fault, -- instruction fetch page fault
i_pmp_fault_i => pmp_ex_fault, -- instruction fetch pmp fault
bus_req_o => ibus_req_o, -- request
bus_rsp_i => ibus_rsp_i, -- response
-- data path interface --
alu_cp_done_i => cp_done, -- ALU iterative operation done
cmp_i => alu_cmp, -- comparator status
alu_add_i => alu_add, -- ALU address result
rs1_i => rs1, -- rf source 1
imm_o => imm, -- immediate
fetch_pc_o => fetch_pc, -- instruction fetch address
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
link_pc_o => link_pc, -- link PC (return address)
csr_rdata_o => csr_rdata, -- CSR read data
-- external CSR interface --
xcsr_we_o => xcsr_we, -- global write enable
xcsr_addr_o => xcsr_addr, -- address
xcsr_wdata_o => xcsr_wdata, -- write data
xcsr_rdata_i => xcsr_rdata_res, -- read data
-- debug mode (halt) request --
db_halt_req_i => dbi_i,
-- interrupts (risc-v compliant) --
msi_i => msi_i, -- machine software interrupt
mei_i => mei_i, -- machine external interrupt
mti_i => mti_i, -- machine timer interrupt
-- fast interrupts (custom) --
firq_i => firq_i, -- fast interrupt trigger
-- bus access exceptions --
mar_i => mar, -- memory address register
ma_load_i => ma_load, -- misaligned load data address
ma_store_i => ma_store, -- misaligned store data address
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store -- bus error on store data access
xcsr_we_o => xcsr_we, -- global write enable
xcsr_addr_o => xcsr_addr, -- address
xcsr_wdata_o => xcsr_wdata, -- write data
xcsr_rdata_i => xcsr_rdata_res, -- read data
-- interrupts --
db_halt_req_i => dbi_i, -- debug mode (halt) request
msi_i => msi_i, -- machine software interrupt
mei_i => mei_i, -- machine external interrupt
mti_i => mti_i, -- machine timer interrupt
firq_i => firq_i, -- fast interrupts
-- data access interface --
lsu_wait_i => lsu_wait, -- wait for data bus
mar_i => mar, -- memory address register
ma_load_i => ma_load, -- misaligned load data address
ma_store_i => ma_store, -- misaligned store data address
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store, -- bus error on store data access
l_page_fault_i => l_page_fault, -- load page fault
s_page_fault_i => s_page_fault -- store page fault
);

-- external CSR read-back --
Expand Down Expand Up @@ -392,4 +394,12 @@ begin
end generate;


-- Memory Management/Paging Unit ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- nothing to see here yet --
i_page_fault <= '0'; -- instruction page fault
l_page_fault <= '0'; -- load page fault
s_page_fault <= '0'; -- store page fault


end neorv32_cpu_rtl;
Loading
Loading