fix trap priority (#784)

This commit is contained in:
stnolting 2024-01-31 22:13:27 +01:00 committed by GitHub
commit 2162a1094e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 37 additions and 59 deletions

View file

@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
| 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) |
| 29.01.2024 | 1.9.3.9 | :test_tube: extend switchable clock domain (CPU bus switch, i-cache, d-cache) | [#780](https://github.com/stnolting/neorv32/pull/780) |

View file

@ -935,16 +935,16 @@ 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 | `0x00000000` | `TRAP_CODE_I_MISALIGNED` | instruction address misaligned | PC | 0 | INS
| 2 | `0x00000001` | `TRAP_CODE_I_ACCESS` | instruction bus access fault | I-PC | 0 | INS
| 3 | `0x00000002` | `TRAP_CODE_I_ILLEGAL` | illegal instruction | PC | 0 | INS
| 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 bus access fault | PC | ADR | INS
| 10 | `0x00000005` | `TRAP_CODE_L_ACCESS` | load bus access fault | 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
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

View file

@ -471,7 +471,7 @@ begin
-- Compressed Instructions Decoder --------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
if CPU_EXTENSION_RISCV_C generate
neorv32_cpu_decompressor_inst: entity neorv32.neorv32_cpu_decompressor
port map (
ci_instr16_i => issue_engine.ci_i16, -- compressed instruction
@ -480,7 +480,7 @@ begin
end generate;
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
if not CPU_EXTENSION_RISCV_C generate
issue_engine.ci_i32 <= (others => '0');
end generate;
@ -491,7 +491,7 @@ begin
-- Issue Engine FSM (required if C extension is enabled) ----------------------------------
-- -------------------------------------------------------------------------------------------
issue_engine_enabled:
if (CPU_EXTENSION_RISCV_C = true) generate
if CPU_EXTENSION_RISCV_C generate
issue_engine_fsm_sync: process(rstn_i, clk_i)
begin
@ -538,7 +538,7 @@ begin
end generate; -- /issue_engine_enabled
issue_engine_disabled: -- use IPB(0) status flags only
if (CPU_EXTENSION_RISCV_C = false) generate
if not CPU_EXTENSION_RISCV_C generate
issue_engine.valid <= (others => ipb.avail(0));
issue_engine.data <= '0' & ipb.rdata(0)(16) & (ipb.rdata(1)(15 downto 0) & ipb.rdata(0)(15 downto 0));
end generate; -- /issue_engine_disabled
@ -974,12 +974,12 @@ begin
-- FPU: floating-point operations --
when opcode_fop_c =>
ctrl_nxt.alu_cp_trig(cp_sel_fpu_c) <= '1'; -- trigger FPU CP
ctrl_nxt.alu_cp_trig(cp_sel_fpu_c) <= '1'; -- trigger FPU co-processor
execute_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor exception if FPU not implemented
-- CFU: custom RISC-V instructions --
when opcode_cust0_c | opcode_cust1_c | opcode_cust2_c | opcode_cust3_c =>
ctrl_nxt.alu_cp_trig(cp_sel_cfu_c) <= '1'; -- trigger CFU CP
ctrl_nxt.alu_cp_trig(cp_sel_cfu_c) <= '1'; -- trigger CFU co-processor
execute_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor exception if CFU not implemented
-- environment/CSR operation or ILLEGAL opcode --
@ -1211,7 +1211,7 @@ begin
csr_mhpmcounter13h_c | csr_mhpmcounter14h_c | csr_mhpmcounter15h_c | -- machine counters HIGH
csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c |
csr_mhpmevent8_c | csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c |
csr_mhpmevent13_c | csr_mhpmevent14_c | csr_mhpmevent15_c => -- event configuration
csr_mhpmevent13_c | csr_mhpmevent14_c | csr_mhpmevent15_c => -- machine event configuration
csr_reg_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- available if Zihpm implemented
-- counter and timer CSRs --
@ -1360,7 +1360,7 @@ begin
when funct12_mret_c => illegal_cmd <= (not csr.privilege) or debug_ctrl.running; -- mret allowed in M-mode only
when funct12_dret_c => illegal_cmd <= not debug_ctrl.running; -- dret allowed in debug mode only
when funct12_wfi_c => illegal_cmd <= (not csr.privilege) and csr.mstatus_tw; -- wfi allowed in M-mode or if TW is zero
when others => illegal_cmd <= '1';
when others => illegal_cmd <= '1';
end case;
else
illegal_cmd <= '1';
@ -1513,11 +1513,11 @@ begin
trap_ctrl.cause <= (others => '0');
elsif rising_edge(clk_i) then
-- standard RISC-V exceptions --
if (trap_ctrl.exc_buf(exc_ialign_c) = '1') then trap_ctrl.cause <= trap_ima_c; -- instruction address misaligned
elsif (trap_ctrl.exc_buf(exc_iaccess_c) = '1') then trap_ctrl.cause <= trap_iaf_c; -- instruction access fault
if (trap_ctrl.exc_buf(exc_iaccess_c) = '1') then trap_ctrl.cause <= trap_iaf_c; -- instruction access fault
elsif (trap_ctrl.exc_buf(exc_illegal_c) = '1') then trap_ctrl.cause <= trap_iil_c; -- illegal instruction
elsif (trap_ctrl.exc_buf(exc_ialign_c) = '1') then trap_ctrl.cause <= trap_ima_c; -- instruction address misaligned
elsif (trap_ctrl.exc_buf(exc_ecall_c) = '1') then trap_ctrl.cause <= trap_env_c(6 downto 2) & csr.privilege & csr.privilege; -- environment call (U/M)
elsif (trap_ctrl.exc_buf(exc_ebreak_c) = '1') then trap_ctrl.cause <= trap_brk_c; -- breakpoint
elsif (trap_ctrl.exc_buf(exc_ebreak_c) = '1') then trap_ctrl.cause <= trap_brk_c; -- environment breakpoint
elsif (trap_ctrl.exc_buf(exc_salign_c) = '1') then trap_ctrl.cause <= trap_sma_c; -- store address misaligned
elsif (trap_ctrl.exc_buf(exc_lalign_c) = '1') then trap_ctrl.cause <= trap_lma_c; -- load address misaligned
elsif (trap_ctrl.exc_buf(exc_saccess_c) = '1') then trap_ctrl.cause <= trap_saf_c; -- store access fault
@ -1525,7 +1525,7 @@ begin
-- standard RISC-V debug mode exceptions and interrupts --
elsif (trap_ctrl.irq_buf(irq_db_halt_c) = '1') then trap_ctrl.cause <= trap_db_halt_c; -- external halt request (async)
elsif (trap_ctrl.exc_buf(exc_db_hw_c) = '1') then trap_ctrl.cause <= trap_db_trig_c; -- hardware trigger (sync)
elsif (trap_ctrl.exc_buf(exc_db_break_c) = '1') then trap_ctrl.cause <= trap_db_break_c; -- break instruction (sync)
elsif (trap_ctrl.exc_buf(exc_db_break_c) = '1') then trap_ctrl.cause <= trap_db_break_c; -- breakpoint (sync)
elsif (trap_ctrl.irq_buf(irq_db_step_c) = '1') then trap_ctrl.cause <= trap_db_step_c; -- single stepping (async)
-- NEORV32-specific fast interrupts --
elsif (trap_ctrl.irq_buf(irq_firq_0_c) = '1') then trap_ctrl.cause <= trap_firq0_c; -- fast interrupt channel 0
@ -1548,6 +1548,7 @@ begin
elsif (trap_ctrl.irq_buf(irq_mei_irq_c) = '1') then trap_ctrl.cause <= trap_mei_c; -- machine external interrupt (MEI)
elsif (trap_ctrl.irq_buf(irq_msi_irq_c) = '1') then trap_ctrl.cause <= trap_msi_c; -- machine software interrupt (MSI)
elsif (trap_ctrl.irq_buf(irq_mti_irq_c) = '1') then trap_ctrl.cause <= trap_mti_c; -- machine timer interrupt (MTI)
--
else trap_ctrl.cause <= trap_mti_c; end if; -- don't care
end if;
end process trap_priority;
@ -2281,7 +2282,7 @@ begin
-- Hardware Performance Monitors (HPM) - Counter Event Configuration CSRs -----------------
-- -------------------------------------------------------------------------------------------
hpmevent_gen_enable:
if (CPU_EXTENSION_RISCV_Zihpm = true) generate
if CPU_EXTENSION_RISCV_Zihpm generate
-- write enable decoder --
hpmevent_write: process(csr)
@ -2323,7 +2324,7 @@ begin
-- no HPMs implemented --
hpm_gen_disable:
if (CPU_EXTENSION_RISCV_Zihpm = false) generate
if not CPU_EXTENSION_RISCV_Zihpm generate
hpmevent_we <= (others => '0');
hpmevent_cfg <= (others => (others => '0'));
hpmevent_rd <= (others => (others => '0'));

View file

@ -56,7 +56,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090400"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090401"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
@ -610,7 +610,7 @@ package neorv32_package is
constant trap_ima_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00000"; -- 0: instruction misaligned
constant trap_iaf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00001"; -- 1: instruction access fault
constant trap_iil_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00010"; -- 2: illegal instruction
constant trap_brk_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00011"; -- 3: breakpoint
constant trap_brk_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00011"; -- 3: environment breakpoint
constant trap_lma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00100"; -- 4: load address misaligned
constant trap_laf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00101"; -- 5: load access fault
constant trap_sma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00110"; -- 6: store address misaligned

View file

@ -3,7 +3,7 @@
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2023, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2024, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
@ -52,14 +52,14 @@
* NEORV32 runtime environment trap IDs.
**************************************************************************/
enum NEORV32_RTE_TRAP_enum {
RTE_TRAP_I_MISALIGNED = 0, /**< Instruction address misaligned */
RTE_TRAP_I_ACCESS = 1, /**< Instruction (bus) access fault */
RTE_TRAP_I_ILLEGAL = 2, /**< Illegal instruction */
RTE_TRAP_I_ACCESS = 0, /**< Instruction access fault */
RTE_TRAP_I_ILLEGAL = 1, /**< Illegal instruction */
RTE_TRAP_I_MISALIGNED = 2, /**< Instruction address misaligned */
RTE_TRAP_BREAKPOINT = 3, /**< Breakpoint (EBREAK instruction) */
RTE_TRAP_L_MISALIGNED = 4, /**< Load address misaligned */
RTE_TRAP_L_ACCESS = 5, /**< Load (bus) access fault */
RTE_TRAP_L_ACCESS = 5, /**< Load access fault */
RTE_TRAP_S_MISALIGNED = 6, /**< Store address misaligned */
RTE_TRAP_S_ACCESS = 7, /**< Store (bus) access fault */
RTE_TRAP_S_ACCESS = 7, /**< Store access fault */
RTE_TRAP_UENV_CALL = 8, /**< Environment call from user mode (ECALL instruction) */
RTE_TRAP_MENV_CALL = 9, /**< Environment call from machine mode (ECALL instruction) */
RTE_TRAP_MSI = 10, /**< Machine software interrupt */

View file

@ -66,8 +66,6 @@ static void __neorv32_rte_print_hex_word(uint32_t num);
* @note This function installs a debug handler for ALL trap sources, which
* gives detailed information about the trap. Actual handlers can be installed afterwards
* via neorv32_rte_handler_install(uint8_t id, void (*handler)(void)).
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
void neorv32_rte_setup(void) {
@ -98,14 +96,9 @@ void neorv32_rte_setup(void) {
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
* @param[in] handler The actual handler function for the specified trap (function MUST be of type "void function(void);").
* @return 0 if success, -1 if error (invalid id or targeted trap not supported).
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
int neorv32_rte_handler_install(int id, void (*handler)(void)) {
// raise an exception if we're not in machine-mode
asm volatile ("csrr x0, mhartid");
// id valid?
uint32_t index = (uint32_t)id;
if (index < ((uint32_t)NEORV32_RTE_NUM_TRAPS)) {
@ -123,14 +116,9 @@ int neorv32_rte_handler_install(int id, void (*handler)(void)) {
*
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
* @return 0 if success, -1 if error (invalid id or targeted trap not supported).
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
int neorv32_rte_handler_uninstall(int id) {
// raise an exception if we're not in machine-mode
asm volatile ("csrr x0, mhartid");
// id valid?
uint32_t index = (uint32_t)id;
if (index < ((uint32_t)NEORV32_RTE_NUM_TRAPS)) {
@ -199,9 +187,9 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
// find according trap handler base address
uint32_t handler_base;
switch (neorv32_cpu_csr_read(CSR_MCAUSE)) {
case TRAP_CODE_I_MISALIGNED: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
case TRAP_CODE_I_ACCESS: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
case TRAP_CODE_I_ILLEGAL: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
case TRAP_CODE_I_MISALIGNED: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
case TRAP_CODE_BREAKPOINT: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
case TRAP_CODE_L_MISALIGNED: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
case TRAP_CODE_L_ACCESS: handler_base = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
@ -301,8 +289,6 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
* NEORV32 runtime environment (RTE):
* Read register from application context.
*
* @warning This function can be called from machine-mode only.
*
* @param[in] x Register number (0..31, corresponds to register x0..x31).
* @return Content of register x.
**************************************************************************/
@ -322,8 +308,6 @@ uint32_t neorv32_rte_context_get(int x) {
* NEORV32 runtime environment (RTE):
* Write register in application context.
*
* @warning This function can be called from machine-mode only.
*
* @param[in] x Register number (0..31, corresponds to register x0..x31).
* @param[in] data Data to be written to register x.
**************************************************************************/
@ -363,9 +347,9 @@ static void __neorv32_rte_debug_handler(void) {
// cause
uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
switch (trap_cause) {
case TRAP_CODE_I_MISALIGNED: neorv32_uart0_puts("Instruction address misaligned"); break;
case TRAP_CODE_I_ACCESS: neorv32_uart0_puts("Instruction access fault"); break;
case TRAP_CODE_I_ILLEGAL: neorv32_uart0_puts("Illegal instruction"); break;
case TRAP_CODE_I_MISALIGNED: neorv32_uart0_puts("Instruction address misaligned"); break;
case TRAP_CODE_BREAKPOINT: neorv32_uart0_puts("Breakpoint"); break;
case TRAP_CODE_L_MISALIGNED: neorv32_uart0_puts("Load address misaligned"); break;
case TRAP_CODE_L_ACCESS: neorv32_uart0_puts("Load access fault"); break;
@ -429,18 +413,13 @@ static void __neorv32_rte_debug_handler(void) {
/**********************************************************************//**
* NEORV32 runtime environment (RTE):
* Print current RTE configuration via UART0.
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
void neorv32_rte_print_info(void) {
// raise an exception if we're not in machine-mode
asm volatile ("csrr x0, mhartid");
const char trap_name[NEORV32_RTE_NUM_TRAPS][13] = {
"I_MISALIGNED",
"I_ACCESS ",
"I_ILLEGAL ",
"I_MISALIGNED",
"BREAKPOINT ",
"L_MISALIGNED",
"L_ACCESS ",
@ -469,7 +448,11 @@ void neorv32_rte_print_info(void) {
"FIRQ_15 "
};
neorv32_uart0_puts("\n\n<< NEORV32 Runtime Environment (RTE) Configuration >>\n\n");
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
neorv32_uart0_puts("\n\n<< NEORV32 RTE Configuration >>\n\n");
// header
neorv32_uart0_puts("---------------------------------\n");
@ -499,14 +482,9 @@ void neorv32_rte_print_info(void) {
/**********************************************************************//**
* NEORV32 runtime environment (RTE):
* Print hardware configuration information via UART0.
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
void neorv32_rte_print_hw_config(void) {
// raise an exception if we're not in machine-mode
asm volatile ("csrr x0, mhartid");
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
@ -754,8 +732,6 @@ void __neorv32_rte_print_hex_word(uint32_t num) {
/**********************************************************************//**
* NEORV32 runtime environment (RTE):
* Print the processor version in human-readable format via UART0.
*
* @warning This function can be called from machine-mode only.
**************************************************************************/
void neorv32_rte_print_hw_version(void) {