diff --git a/dv/cs_registers/tb/tb_cs_registers.sv b/dv/cs_registers/tb/tb_cs_registers.sv index 9661b9d727..e53612b2e4 100644 --- a/dv/cs_registers/tb/tb_cs_registers.sv +++ b/dv/cs_registers/tb/tb_cs_registers.sv @@ -46,6 +46,7 @@ module tb_cs_registers #( logic irq_external_i; logic [14:0] irq_fast_i; logic irq_pending_o; // interupt request pending + logic nmi_mode_i; // core is handling an NMI logic csr_msip_o; // software interrupt pending logic csr_mtip_o; // timer interrupt pending logic csr_meip_o; // external interrupt pending diff --git a/lint/verilator_waiver.vlt b/lint/verilator_waiver.vlt index fe4abe70ef..b8ae534833 100644 --- a/lint/verilator_waiver.vlt +++ b/lint/verilator_waiver.vlt @@ -57,4 +57,4 @@ lint_off -msg UNUSED -file "*/rtl/ibex_pmp.sv" -lines 16 // Signal unoptimizable: Feedback to clock or circular logic: // ibex_core.cs_registers_i.mie_q // Issue lowrisc/ibex#212 -lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 166 +lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 167 diff --git a/rtl/ibex_controller.sv b/rtl/ibex_controller.sv index 9fd07171c9..d3fd26efbd 100644 --- a/rtl/ibex_controller.sv +++ b/rtl/ibex_controller.sv @@ -59,6 +59,7 @@ module ibex_controller ( input logic [14:0] csr_mfip_i, // fast interrupt pending input logic irq_pending_i, // interrupt request pending input logic irq_nm_i, // non-maskeable interrupt + output logic nmi_mode_o, // core executing NMI handler // debug signals input logic debug_req_i, @@ -592,6 +593,9 @@ module ibex_controller ( // signal to CSR when in debug mode assign debug_mode_o = debug_mode_q; + // signal to CSR when in an NMI handler (for nested exception handling) + assign nmi_mode_o = nmi_mode_q; + /////////////////// // Stall control // /////////////////// diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index f7922efc60..f136bddec9 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -176,6 +176,7 @@ module ibex_core #( // Interrupts logic irq_pending; + logic nmi_mode; logic csr_msip; logic csr_mtip; logic csr_meip; @@ -441,6 +442,7 @@ module ibex_core #( .csr_mfip_i ( csr_mfip ), .irq_pending_i ( irq_pending ), .irq_nm_i ( irq_nm_i ), + .nmi_mode_o ( nmi_mode ), // Debug Signal .debug_mode_o ( debug_mode ), @@ -604,6 +606,7 @@ module ibex_core #( .irq_external_i ( irq_external_i ), .irq_fast_i ( irq_fast_i ), .irq_pending_o ( irq_pending ), + .nmi_mode_i ( nmi_mode ), .csr_msip_o ( csr_msip ), .csr_mtip_o ( csr_mtip ), .csr_meip_o ( csr_meip ), diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index 4b4ca9d1d5..5acd1813e6 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -50,6 +50,7 @@ module ibex_cs_registers #( input logic irq_external_i, input logic [14:0] irq_fast_i, output logic irq_pending_o, // interupt request pending + input logic nmi_mode_i, output logic csr_msip_o, // software interrupt pending output logic csr_mtip_o, // timer interrupt pending output logic csr_meip_o, // external interrupt pending @@ -580,13 +581,19 @@ module ibex_cs_registers #( csr_restore_mret_i: begin // MRET priv_lvl_d = mstatus_q.mpp; mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts - // restore previous status for recoverable NMI - mstatus_d.mpie = mstack_q.mpie; - mstatus_d.mpp = mstack_q.mpp; - mepc_d = mstack_epc_q; - mcause_d = mstack_cause_q; - mstack_d.mpie = 1'b1; - mstack_d.mpp = PRIV_LVL_U; + + if (nmi_mode_i) begin + // when returning from an NMI restore state from mstack CSR + mstatus_d.mpie = mstack_q.mpie; + mstatus_d.mpp = mstack_q.mpp; + mepc_d = mstack_epc_q; + mcause_d = mstack_cause_q; + end else begin + // otherwise just set mstatus.MPIE/MPP + // See RISC-V Privileged Specification, version 1.11, Section 3.1.6.1 + mstatus_d.mpie = 1'b1; + mstatus_d.mpp = PRIV_LVL_U; + end end // csr_restore_mret_i default:; diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index 71183761e9..9010cee880 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -97,6 +97,7 @@ module ibex_id_stage #( input logic [14:0] csr_mfip_i, input logic irq_pending_i, input logic irq_nm_i, + output logic nmi_mode_o, input logic lsu_load_err_i, input logic lsu_store_err_i, @@ -434,6 +435,7 @@ module ibex_id_stage #( .csr_mfip_i ( csr_mfip_i ), .irq_pending_i ( irq_pending_i ), .irq_nm_i ( irq_nm_i ), + .nmi_mode_o ( nmi_mode_o ), // CSR Controller Signals .csr_save_if_o ( csr_save_if_o ),