From 829b83c5255912e1a464415c11a595a08985c5a6 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Wed, 30 Aug 2023 11:53:36 +0200 Subject: [PATCH 01/10] first draft --- rtl/cve2_cs_registers.sv | 90 +++++++++++++++++++++++++--------------- rtl/cve2_pkg.sv | 6 +++ 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/rtl/cve2_cs_registers.sv b/rtl/cve2_cs_registers.sv index cfd67f4d09..e630f548b3 100644 --- a/rtl/cve2_cs_registers.sv +++ b/rtl/cve2_cs_registers.sv @@ -185,11 +185,14 @@ module cve2_cs_registers #( logic dscratch0_en, dscratch1_en; // CSRs for recoverable NMIs - // NOTE: these CSRS are nonstandard, see https://github.com/riscv/riscv-isa-manual/issues/261 - status_stk_t mstack_q, mstack_d; - logic mstack_en; - logic [31:0] mstack_epc_q, mstack_epc_d; - logic [6:0] mstack_cause_q, mstack_cause_d; + // NOTE: these CSRS are following draft implementation of SMRNMI in priviledged + // see chapter 4.3 + // (https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-1239329-2023-05-23/riscv-privileged.pdf) + // beware it is a subject of changes and might (will) be different than the final standard implementation + status_stk_t mnstatus_q, mnstatus_d; + logic mnstatus_en, mnscratch_en, mnepc_en; + logic [31:0] mnepc_q, mnepc_d; + logic [5:0] mncause_q, mncause_d; // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; @@ -497,11 +500,13 @@ module cve2_cs_registers #( dscratch0_en = 1'b0; dscratch1_en = 1'b0; - mstack_en = 1'b0; - mstack_d.mpie = mstatus_q.mpie; - mstack_d.mpp = mstatus_q.mpp; - mstack_epc_d = mepc_q; - mstack_cause_d = mcause_q; + mnstatus_en = 1'b0; + mnscratch_en = 1'b0; + mnepc_en = 1'b0; + mnstatus_d.mpie = mstatus_q.mpie; + mnstatus_d.mpp = mstatus_q.mpp; + mnepc_d = mepc_q; + mncause_d = mcause_q; mcountinhibit_we = 1'b0; mhpmcounter_we = '0; @@ -530,9 +535,14 @@ module cve2_cs_registers #( CSR_MSCRATCH: mscratch_en = 1'b1; + CSR_MNSCRATCH: mnscratch_en = 1'b1; + // mepc: exception program counter CSR_MEPC: mepc_en = 1'b1; + // mnepc: rNMI program counter + CSR_MNEPC: mnepc_en = 1'b1; + // mcause CSR_MCAUSE: mcause_en = 1'b1; @@ -648,7 +658,7 @@ module cve2_cs_registers #( mcause_en = 1'b1; mcause_d = {csr_mcause_i}; // save previous status for recoverable NMI - mstack_en = 1'b1; + mnstatus_en = 1'b1; end end // csr_save_cause_i @@ -670,13 +680,13 @@ module cve2_cs_registers #( // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC 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; + // when returning from an NMI restore state from mnstatus CSR + mstatus_d.mpie = mnstatus_q.mpie; + mstatus_d.mpp = mnstatus_q.mpp; mepc_en = 1'b1; - mepc_d = mstack_epc_q; + mepc_d = mnepc_q; mcause_en = 1'b1; - mcause_d = mstack_cause_q; + mcause_d = mncause_q; end else begin // otherwise just set mstatus.MPIE/MPP // See RISC-V Privileged Specification, version 1.11, Section 3.1.6.1 @@ -805,6 +815,20 @@ module cve2_cs_registers #( .rd_error_o() ); + // MNSCRATCH + cve2_csr #( + .Width (32), + .ShadowCopy(1'b0), + .ResetValue('0) + ) u_mnscratch_csr ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .wr_data_i (csr_wdata_int), + .wr_en_i (mnscratch_en), + .rd_data_o (mnscratch_q), + .rd_error_o() + ); + // MCAUSE cve2_csr #( .Width (7), @@ -908,46 +932,46 @@ module cve2_cs_registers #( .rd_error_o() ); - // MSTACK - localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; + // MNSTATUS + localparam status_stk_t MNSTATUS_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; cve2_csr #( .Width ($bits(status_stk_t)), .ShadowCopy(1'b0), - .ResetValue({MSTACK_RESET_VAL}) - ) u_mstack_csr ( + .ResetValue({MNSTATUS_RESET_VAL}) + ) u_mnstatus_csr ( .clk_i (clk_i), .rst_ni (rst_ni), - .wr_data_i ({mstack_d}), - .wr_en_i (mstack_en), - .rd_data_o (mstack_q), + .wr_data_i (mnstatus_d), + .wr_en_i (mnstatus_en), + .rd_data_o (mnstatus_q), .rd_error_o() ); - // MSTACK_EPC + // MNEPC cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) - ) u_mstack_epc_csr ( + ) u_mnepc_csr ( .clk_i (clk_i), .rst_ni (rst_ni), - .wr_data_i (mstack_epc_d), - .wr_en_i (mstack_en), - .rd_data_o (mstack_epc_q), + .wr_data_i (mnepc_d), + .wr_en_i (mnepc_en), + .rd_data_o (mnepc_q), .rd_error_o() ); - // MSTACK_CAUSE + // MNCAUSE cve2_csr #( .Width (7), .ShadowCopy(1'b0), .ResetValue('0) - ) u_mstack_cause_csr ( + ) u_mncause_csr ( .clk_i (clk_i), .rst_ni (rst_ni), - .wr_data_i (mstack_cause_d), - .wr_en_i (mstack_en), - .rd_data_o (mstack_cause_q), + .wr_data_i (mncause_d), + .wr_en_i (mncause_en), + .rd_data_o (mncause_q), .rd_error_o() ); diff --git a/rtl/cve2_pkg.sv b/rtl/cve2_pkg.sv index e488580b61..98e9213a45 100644 --- a/rtl/cve2_pkg.sv +++ b/rtl/cve2_pkg.sv @@ -409,6 +409,12 @@ package cve2_pkg; CSR_PMPADDR14 = 12'h3BE, CSR_PMPADDR15 = 12'h3BF, + // Resumable NMI + CSR_MNSCRATCH = 12'h740, + CSR_MNEPC = 12'h741, + CSR_MNCAUSE = 12'h742, + CSR_MNSTATUS = 12'h743, + // ePMP control CSR_MSECCFG = 12'h747, CSR_MSECCFGH = 12'h757, From 15932c08bdf9e6bb2d72d377cbb5d705e484a426 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Thu, 14 Sep 2023 10:58:53 +0200 Subject: [PATCH 02/10] PC restoration when MNRET executed requires a new MUX control combination Access to NMI related CSR Signed-off-by: Szymon Bieganski --- rtl/cve2_controller.sv | 21 ++++++-- rtl/cve2_core.sv | 7 ++- rtl/cve2_cs_registers.sv | 114 ++++++++++++++++++++++++++++++++------- rtl/cve2_csr.sv | 2 +- rtl/cve2_decoder.sv | 6 +++ rtl/cve2_id_stage.sv | 5 ++ rtl/cve2_if_stage.sv | 3 ++ rtl/cve2_pkg.sv | 3 +- rtl/cve2_tracer.sv | 1 + rtl/cve2_tracer_pkg.sv | 1 + 10 files changed, 135 insertions(+), 28 deletions(-) diff --git a/rtl/cve2_controller.sv b/rtl/cve2_controller.sv index 16ef29dba4..f5bf0463ed 100644 --- a/rtl/cve2_controller.sv +++ b/rtl/cve2_controller.sv @@ -22,6 +22,7 @@ module cve2_controller #( input logic illegal_insn_i, // decoder has an invalid instr input logic ecall_insn_i, // decoder has ECALL instr input logic mret_insn_i, // decoder has MRET instr + input logic mnret_insn_i, // decoder has MNRET instr input logic dret_insn_i, // decoder has DRET instr input logic wfi_insn_i, // decoder has WFI instr input logic ebrk_insn_i, // decoder has EBREAK instr @@ -81,6 +82,7 @@ module cve2_controller #( output logic csr_save_if_o, output logic csr_save_id_o, output logic csr_restore_mret_id_o, + output logic csr_restore_mnret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, @@ -146,6 +148,7 @@ module cve2_controller #( logic ecall_insn; logic mret_insn; + logic mnret_insn; logic dret_insn; logic wfi_insn; logic ebrk_insn; @@ -176,6 +179,7 @@ module cve2_controller #( // Decoder doesn't take instr_valid into account, factor it in here. assign ecall_insn = ecall_insn_i & instr_valid_i; assign mret_insn = mret_insn_i & instr_valid_i; + assign mnret_insn = mnret_insn_i & instr_valid_i; assign dret_insn = dret_insn_i & instr_valid_i; assign wfi_insn = wfi_insn_i & instr_valid_i; assign ebrk_insn = ebrk_insn_i & instr_valid_i; @@ -189,7 +193,7 @@ module cve2_controller #( // Some instructions can only be executed in M-Mode assign illegal_umode = (priv_mode_i != PRIV_LVL_M) & // MRET must be in M-Mode. TW means trap WFI to M-Mode. - (mret_insn | (csr_mstatus_tw_i & wfi_insn)); + (mret_insn | mnret_insn | (csr_mstatus_tw_i & wfi_insn)); // This is recorded in the illegal_insn_q flop to help timing. Specifically // it is needed to break the path from cve2_cs_registers/illegal_csr_insn_o @@ -218,7 +222,7 @@ module cve2_controller #( assign special_req_flush_only = wfi_insn | csr_pipe_flush; // These special requests cause a change in PC - assign special_req_pc_change = mret_insn | dret_insn | exc_req_d | exc_req_lsu; + assign special_req_pc_change = mret_insn | mnret_insn | dret_insn | exc_req_d | exc_req_lsu; // generic special request signal, applies to all instructions assign special_req = special_req_pc_change | special_req_flush_only; @@ -323,6 +327,7 @@ module cve2_controller #( csr_save_if_o = 1'b0; csr_save_id_o = 1'b0; csr_restore_mret_id_o = 1'b0; + csr_restore_mnret_id_o = 1'b0; csr_restore_dret_id_o = 1'b0; csr_save_cause_o = 1'b0; csr_mtval_o = '0; @@ -657,10 +662,16 @@ module cve2_controller #( endcase end else begin // special instructions and pipeline flushes - if (mret_insn) begin - pc_mux_o = PC_ERET; + if (mret_insn | mnret_insn) begin pc_set_o = 1'b1; - csr_restore_mret_id_o = 1'b1; + if(mret_insn) begin + csr_restore_mret_id_o = 1'b1; + pc_mux_o = PC_ERET; + end + if(mnret_insn) begin + csr_restore_mnret_id_o = 1'b1; + pc_mux_o = PC_NRET; + end if (nmi_mode_q) begin nmi_mode_d = 1'b0; // exit NMI mode end diff --git a/rtl/cve2_core.sv b/rtl/cve2_core.sv index 600f87890b..d3b591b682 100644 --- a/rtl/cve2_core.sv +++ b/rtl/cve2_core.sv @@ -223,7 +223,7 @@ module cve2_core import cve2_pkg::*; #( logic nmi_mode; irqs_t irqs; logic csr_mstatus_mie; - logic [31:0] csr_mepc, csr_depc; + logic [31:0] csr_mepc, csr_mnepc, csr_depc; // PMP signals logic [33:0] csr_pmp_addr [PMPNumRegions]; @@ -235,6 +235,7 @@ module cve2_core import cve2_pkg::*; #( logic csr_save_if; logic csr_save_id; logic csr_restore_mret_id; + logic csr_restore_mnret_id; logic csr_restore_dret_id; logic csr_save_cause; logic csr_mtvec_init; @@ -329,6 +330,7 @@ module cve2_core import cve2_pkg::*; #( // CSRs .csr_mepc_i (csr_mepc), // exception return address + .csr_mnepc_i (csr_mnepc), // NMI return address .csr_depc_i (csr_depc), // debug return address .csr_mtvec_i (csr_mtvec), // trap-vector base address .csr_mtvec_init_o(csr_mtvec_init), @@ -417,6 +419,7 @@ module cve2_core import cve2_pkg::*; #( .csr_save_if_o (csr_save_if), // control signal to save PC .csr_save_id_o (csr_save_id), // control signal to save PC .csr_restore_mret_id_o(csr_restore_mret_id), // restore mstatus upon MRET + .csr_restore_mnret_id_o(csr_restore_mnret_id), // restore mstatus upon MNRET .csr_restore_dret_id_o(csr_restore_dret_id), // restore mstatus upon MRET .csr_save_cause_o (csr_save_cause), .csr_mtval_o (csr_mtval), @@ -712,6 +715,7 @@ module cve2_core import cve2_pkg::*; #( .csr_mstatus_mie_o(csr_mstatus_mie), .csr_mstatus_tw_o (csr_mstatus_tw), .csr_mepc_o (csr_mepc), + .csr_mnepc_o (csr_mnepc), // PMP .csr_pmp_cfg_o (csr_pmp_cfg), @@ -734,6 +738,7 @@ module cve2_core import cve2_pkg::*; #( .csr_save_if_i (csr_save_if), .csr_save_id_i (csr_save_id), .csr_restore_mret_i(csr_restore_mret_id), + .csr_restore_mnret_i(csr_restore_mnret_id), .csr_restore_dret_i(csr_restore_dret_id), .csr_save_cause_i (csr_save_cause), .csr_mcause_i (exc_cause), diff --git a/rtl/cve2_cs_registers.sv b/rtl/cve2_cs_registers.sv index e630f548b3..2b3bf10d58 100644 --- a/rtl/cve2_cs_registers.sv +++ b/rtl/cve2_cs_registers.sv @@ -59,6 +59,7 @@ module cve2_cs_registers #( output cve2_pkg::irqs_t irqs_o, // interrupt requests qualified with mie output logic csr_mstatus_mie_o, output logic [31:0] csr_mepc_o, + output logic [31:0] csr_mnepc_o, // PMP output cve2_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], @@ -82,6 +83,7 @@ module cve2_cs_registers #( input logic csr_save_if_i, input logic csr_save_id_i, input logic csr_restore_mret_i, + input logic csr_restore_mnret_i, input logic csr_restore_dret_i, input logic csr_save_cause_i, input cve2_pkg::exc_cause_e csr_mcause_i, @@ -133,10 +135,10 @@ module cve2_cs_registers #( logic tw; } status_t; - typedef struct packed { +/* typedef struct packed { logic mpie; priv_lvl_e mpp; - } status_stk_t; + } status_stk_t;*/ typedef struct packed { x_debug_ver_e xdebugver; @@ -189,10 +191,10 @@ module cve2_cs_registers #( // see chapter 4.3 // (https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-1239329-2023-05-23/riscv-privileged.pdf) // beware it is a subject of changes and might (will) be different than the final standard implementation - status_stk_t mnstatus_q, mnstatus_d; - logic mnstatus_en, mnscratch_en, mnepc_en; - logic [31:0] mnepc_q, mnepc_d; - logic [5:0] mncause_q, mncause_d; + status_t mnstatus_q, mnstatus_d; + logic mnstatus_en, mnscratch_en, mnepc_en, mncause_en; + logic [31:0] mnepc_q, mnepc_d, mnscratch_q, mnscratch_d; + logic [6:0] mncause_q, mncause_d; // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; @@ -288,6 +290,16 @@ module cve2_cs_registers #( csr_rdata_int[CSR_MSTATUS_TW_BIT] = mstatus_q.tw; end + // mnstatus: always M-mode, contains IE bit + CSR_MNSTATUS: begin + csr_rdata_int = '0; + csr_rdata_int[CSR_MSTATUS_MIE_BIT] = mnstatus_q.mie; + csr_rdata_int[CSR_MSTATUS_MPIE_BIT] = mnstatus_q.mpie; + csr_rdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mnstatus_q.mpp; + csr_rdata_int[CSR_MSTATUS_MPRV_BIT] = mnstatus_q.mprv; + csr_rdata_int[CSR_MSTATUS_TW_BIT] = mnstatus_q.tw; + end + // mstatush: All zeros for Ibex (fixed little endian and all other bits reserved) CSR_MSTATUSH: csr_rdata_int = '0; @@ -320,9 +332,15 @@ module cve2_cs_registers #( // mepc: exception program counter CSR_MEPC: csr_rdata_int = mepc_q; + // mnepc: exception program counter + CSR_MNEPC: csr_rdata_int = mnepc_q; + // mcause: exception cause CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; + // mcause: exception cause + CSR_MNCAUSE: csr_rdata_int = {mncause_q[6], 25'b0, mncause_q[5:0]}; + // mtval: trap value CSR_MTVAL: csr_rdata_int = mtval_q; @@ -501,12 +519,14 @@ module cve2_cs_registers #( dscratch1_en = 1'b0; mnstatus_en = 1'b0; + mnstatus_d = mnstatus_q; mnscratch_en = 1'b0; mnepc_en = 1'b0; mnstatus_d.mpie = mstatus_q.mpie; mnstatus_d.mpp = mstatus_q.mpp; - mnepc_d = mepc_q; - mncause_d = mcause_q; + mnepc_d = {csr_wdata_int[31:1], 1'b0}; + mncause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; + mncause_en = 1'b0; mcountinhibit_we = 1'b0; mhpmcounter_we = '0; @@ -530,6 +550,22 @@ module cve2_cs_registers #( end end + // mnstatus: IE bit + CSR_MNSTATUS: begin + mnstatus_en = 1'b1; + mnstatus_d = '{ + mie: csr_wdata_int[CSR_MSTATUS_MIE_BIT], + mpie: csr_wdata_int[CSR_MSTATUS_MPIE_BIT], + mpp: priv_lvl_e'(csr_wdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW]), + mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT], + tw: csr_wdata_int[CSR_MSTATUS_TW_BIT] + }; + // Convert illegal values to M-mode + if ((mnstatus_d.mpp != PRIV_LVL_M) && (mnstatus_d.mpp != PRIV_LVL_U)) begin + mnstatus_d.mpp = PRIV_LVL_M; + end + end + // interrupt enable CSR_MIE: mie_en = 1'b1; @@ -546,6 +582,9 @@ module cve2_cs_registers #( // mcause CSR_MCAUSE: mcause_en = 1'b1; + // mncause + CSR_MNCAUSE: mncause_en = 1'b1; + // mtval: trap value CSR_MTVAL: mtval_en = 1'b1; @@ -648,17 +687,18 @@ module cve2_cs_registers #( // includes cause, epc, tval, dpc and mstatus." [Debug Spec v0.13.2, p.39] mtval_en = 1'b1; mtval_d = csr_mtval_i; - mstatus_en = 1'b1; - mstatus_d.mie = 1'b0; // disable interrupts + //mstatus_en = 1'b1; + mnstatus_d.mie = 1'b0; // disable interrupts // save current status - mstatus_d.mpie = mstatus_q.mie; - mstatus_d.mpp = priv_lvl_q; - mepc_en = 1'b1; - mepc_d = exception_pc; - mcause_en = 1'b1; - mcause_d = {csr_mcause_i}; + mnstatus_d.mpie = mstatus_q.mie; + mnstatus_d.mpp = priv_lvl_q; + mnepc_en = 1'b1; + mnepc_d = exception_pc; + mncause_en = 1'b1; + mnscratch_en = 1'b1; + mncause_d = {csr_mcause_i}; // save previous status for recoverable NMI - mnstatus_en = 1'b1; + mnstatus_en = 1'b1; end end // csr_save_cause_i @@ -679,6 +719,34 @@ module cve2_cs_registers #( // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC + if (nmi_mode_i) begin + // when returning from an NMI restore state from mstatus CSR + mstatus_d.mpie = mnstatus_q.mpie; + mstatus_d.mpp = mnstatus_q.mpp; + mepc_en = 1'b1; + mepc_d = mepc_q; + mcause_en = 1'b1; + mcause_d = mcause_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 + + csr_restore_mnret_i: begin // MNRET + priv_lvl_d = mnstatus_q.mpp; + mnstatus_en = 1'b1; + mnstatus_d.mie = mnstatus_q.mpie; // re-enable interrupts + + if (mnstatus_q.mpp != PRIV_LVL_M) begin + mnstatus_d.mprv = 1'b0; + end + + // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC + // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC + if (nmi_mode_i) begin // when returning from an NMI restore state from mnstatus CSR mstatus_d.mpie = mnstatus_q.mpie; @@ -693,7 +761,7 @@ module cve2_cs_registers #( mstatus_d.mpie = 1'b1; mstatus_d.mpp = PRIV_LVL_U; end - end // csr_restore_mret_i + end // csr_restore_mnret_i default:; endcase @@ -733,6 +801,7 @@ module cve2_cs_registers #( // directly output some registers assign csr_mepc_o = mepc_q; + assign csr_mnepc_o = mnepc_q; assign csr_depc_o = depc_q; assign csr_mtvec_o = mtvec_q; @@ -933,9 +1002,14 @@ module cve2_cs_registers #( ); // MNSTATUS - localparam status_stk_t MNSTATUS_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; + localparam status_t MNSTATUS_RESET_VAL = '{mie: 1'b0, + mpie: 1'b0, + mpp: PRIV_LVL_M, + mprv: 1'b0, + tw: 1'b0}; + cve2_csr #( - .Width ($bits(status_stk_t)), + .Width ($bits(status_t)), .ShadowCopy(1'b0), .ResetValue({MNSTATUS_RESET_VAL}) ) u_mnstatus_csr ( diff --git a/rtl/cve2_csr.sv b/rtl/cve2_csr.sv index b464bccedb..abe095f1f0 100644 --- a/rtl/cve2_csr.sv +++ b/rtl/cve2_csr.sv @@ -52,6 +52,6 @@ module cve2_csr #( assign rd_error_o = 1'b0; end - `ASSERT_KNOWN(IbexCSREnValid, wr_en_i) + `ASSERT_KNOWN(CVE2CSREnValid, wr_en_i) endmodule diff --git a/rtl/cve2_decoder.sv b/rtl/cve2_decoder.sv index 5b9cbca148..e882d9ca13 100644 --- a/rtl/cve2_decoder.sv +++ b/rtl/cve2_decoder.sv @@ -26,6 +26,8 @@ module cve2_decoder #( output logic ebrk_insn_o, // trap instr encountered output logic mret_insn_o, // return from exception instr // encountered + output logic mnret_insn_o, // return from NM exception instr + // encountered output logic dret_insn_o, // return from debug instr encountered output logic ecall_insn_o, // syscall instr encountered output logic wfi_insn_o, // wait for interrupt instr encountered @@ -222,6 +224,7 @@ module cve2_decoder #( illegal_insn = 1'b0; ebrk_insn_o = 1'b0; mret_insn_o = 1'b0; + mnret_insn_o = 1'b0; dret_insn_o = 1'b0; ecall_insn_o = 1'b0; wfi_insn_o = 1'b0; @@ -595,6 +598,9 @@ module cve2_decoder #( 12'h302: // mret mret_insn_o = 1'b1; + 12'h702: // mnret + mnret_insn_o = 1'b1; + 12'h7b2: // dret dret_insn_o = 1'b1; diff --git a/rtl/cve2_id_stage.sv b/rtl/cve2_id_stage.sv index e989ff295e..f1613bf3bb 100644 --- a/rtl/cve2_id_stage.sv +++ b/rtl/cve2_id_stage.sv @@ -85,6 +85,7 @@ module cve2_id_stage #( output logic csr_save_if_o, output logic csr_save_id_o, output logic csr_restore_mret_id_o, + output logic csr_restore_mnret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, @@ -159,6 +160,7 @@ module cve2_id_stage #( logic illegal_insn_dec; logic ebrk_insn; logic mret_insn_dec; + logic mnret_insn_dec; logic dret_insn_dec; logic ecall_insn_dec; logic wfi_insn_dec; @@ -346,6 +348,7 @@ module cve2_id_stage #( .illegal_insn_o(illegal_insn_dec), .ebrk_insn_o (ebrk_insn), .mret_insn_o (mret_insn_dec), + .mnret_insn_o (mnret_insn_dec), .dret_insn_o (dret_insn_dec), .ecall_insn_o (ecall_insn_dec), .wfi_insn_o (wfi_insn_dec), @@ -456,6 +459,7 @@ module cve2_id_stage #( .illegal_insn_i (illegal_insn_o), .ecall_insn_i (ecall_insn_dec), .mret_insn_i (mret_insn_dec), + .mnret_insn_i (mnret_insn_dec), .dret_insn_i (dret_insn_dec), .wfi_insn_i (wfi_insn_dec), .ebrk_insn_i (ebrk_insn), @@ -501,6 +505,7 @@ module cve2_id_stage #( .csr_save_if_o (csr_save_if_o), .csr_save_id_o (csr_save_id_o), .csr_restore_mret_id_o(csr_restore_mret_id_o), + .csr_restore_mnret_id_o(csr_restore_mnret_id_o), .csr_restore_dret_id_o(csr_restore_dret_id_o), .csr_save_cause_o (csr_save_cause_o), .csr_mtval_o (csr_mtval_o), diff --git a/rtl/cve2_if_stage.sv b/rtl/cve2_if_stage.sv index cbb050547b..f6eb174681 100644 --- a/rtl/cve2_if_stage.sv +++ b/rtl/cve2_if_stage.sv @@ -63,6 +63,8 @@ module cve2_if_stage import cve2_pkg::*; #( // CSRs input logic [31:0] csr_mepc_i, // PC to restore after handling // the interrupt/exception + input logic [31:0] csr_mnepc_i, // PC to restore after handling + // the interrupt/exception input logic [31:0] csr_depc_i, // PC to restore after handling // the debug request input logic [31:0] csr_mtvec_i, // base PC to jump to on exception @@ -139,6 +141,7 @@ module cve2_if_stage import cve2_pkg::*; #( PC_JUMP: fetch_addr_n = branch_target_ex_i; PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC + PC_NRET: fetch_addr_n = csr_mnepc_i; // restore PC when returning from EXC PC_DRET: fetch_addr_n = csr_depc_i; default: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; endcase diff --git a/rtl/cve2_pkg.sv b/rtl/cve2_pkg.sv index 98e9213a45..05587675bf 100644 --- a/rtl/cve2_pkg.sv +++ b/rtl/cve2_pkg.sv @@ -275,6 +275,7 @@ package cve2_pkg; PC_JUMP, PC_EXC, PC_ERET, + PC_NRET, PC_DRET, PC_BP } pc_sel_e; @@ -413,7 +414,7 @@ package cve2_pkg; CSR_MNSCRATCH = 12'h740, CSR_MNEPC = 12'h741, CSR_MNCAUSE = 12'h742, - CSR_MNSTATUS = 12'h743, + CSR_MNSTATUS = 12'h744, // ePMP control CSR_MSECCFG = 12'h747, diff --git a/rtl/cve2_tracer.sv b/rtl/cve2_tracer.sv index 707419e449..80811736d5 100644 --- a/rtl/cve2_tracer.sv +++ b/rtl/cve2_tracer.sv @@ -893,6 +893,7 @@ module cve2_tracer ( INSN_ECALL: decode_mnemonic("ecall"); INSN_EBREAK: decode_mnemonic("ebreak"); INSN_MRET: decode_mnemonic("mret"); + INSN_MNRET: decode_mnemonic("mnret"); INSN_DRET: decode_mnemonic("dret"); INSN_WFI: decode_mnemonic("wfi"); // RV32M diff --git a/rtl/cve2_tracer_pkg.sv b/rtl/cve2_tracer_pkg.sv index 700dd37b38..a65dd647ad 100644 --- a/rtl/cve2_tracer_pkg.sv +++ b/rtl/cve2_tracer_pkg.sv @@ -57,6 +57,7 @@ package cve2_tracer_pkg; parameter logic [31:0] INSN_ECALL = { 12'b000000000000, 13'b0, {OPCODE_SYSTEM} }; parameter logic [31:0] INSN_EBREAK = { 12'b000000000001, 13'b0, {OPCODE_SYSTEM} }; parameter logic [31:0] INSN_MRET = { 12'b001100000010, 13'b0, {OPCODE_SYSTEM} }; + parameter logic [31:0] INSN_MNRET = { 12'b011100000010, 13'b0, {OPCODE_SYSTEM} }; parameter logic [31:0] INSN_DRET = { 12'b011110110010, 13'b0, {OPCODE_SYSTEM} }; parameter logic [31:0] INSN_WFI = { 12'b000100000101, 13'b0, {OPCODE_SYSTEM} }; From add5a7b1e769d6d658756f429035fca6e55ea489 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Wed, 4 Oct 2023 15:21:20 +0200 Subject: [PATCH 03/10] correct nmi_status_t ignore unimplemented hypervisor extension features Signed-off-by: Szymon Bieganski --- rtl/cve2_cs_registers.sv | 83 ++++++++++++++++++---------------------- rtl/cve2_pkg.sv | 6 +++ 2 files changed, 43 insertions(+), 46 deletions(-) diff --git a/rtl/cve2_cs_registers.sv b/rtl/cve2_cs_registers.sv index 2b3bf10d58..2af03af178 100644 --- a/rtl/cve2_cs_registers.sv +++ b/rtl/cve2_cs_registers.sv @@ -135,10 +135,11 @@ module cve2_cs_registers #( logic tw; } status_t; -/* typedef struct packed { - logic mpie; - priv_lvl_e mpp; - } status_stk_t;*/ + typedef struct packed { + logic nmie; + logic mnpv; + priv_lvl_e mnpp; + } nm_status_t; typedef struct packed { x_debug_ver_e xdebugver; @@ -191,7 +192,7 @@ module cve2_cs_registers #( // see chapter 4.3 // (https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-1239329-2023-05-23/riscv-privileged.pdf) // beware it is a subject of changes and might (will) be different than the final standard implementation - status_t mnstatus_q, mnstatus_d; + nm_status_t mnstatus_q, mnstatus_d; logic mnstatus_en, mnscratch_en, mnepc_en, mncause_en; logic [31:0] mnepc_q, mnepc_d, mnscratch_q, mnscratch_d; logic [6:0] mncause_q, mncause_d; @@ -292,12 +293,10 @@ module cve2_cs_registers #( // mnstatus: always M-mode, contains IE bit CSR_MNSTATUS: begin - csr_rdata_int = '0; - csr_rdata_int[CSR_MSTATUS_MIE_BIT] = mnstatus_q.mie; - csr_rdata_int[CSR_MSTATUS_MPIE_BIT] = mnstatus_q.mpie; - csr_rdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mnstatus_q.mpp; - csr_rdata_int[CSR_MSTATUS_MPRV_BIT] = mnstatus_q.mprv; - csr_rdata_int[CSR_MSTATUS_TW_BIT] = mnstatus_q.tw; + csr_rdata_int = '0; + csr_rdata_int[CSR_MNSTATUS_NMIE_BIT] = mnstatus_q.nmie; + csr_rdata_int[CSR_MNSTATUS_MNPV_BIT] = mnstatus_q.mnpv; + csr_rdata_int[CSR_MNSTATUS_MNPP_BIT_HIGH:CSR_MNSTATUS_MNPP_BIT_LOW] = mnstatus_q.mnpp; end // mstatush: All zeros for Ibex (fixed little endian and all other bits reserved) @@ -522,8 +521,8 @@ module cve2_cs_registers #( mnstatus_d = mnstatus_q; mnscratch_en = 1'b0; mnepc_en = 1'b0; - mnstatus_d.mpie = mstatus_q.mpie; - mnstatus_d.mpp = mstatus_q.mpp; + /*mnstatus_d.mnpv = mstatus_q.mpv;*/ + mnstatus_d.mnpp = mstatus_q.mpp; mnepc_d = {csr_wdata_int[31:1], 1'b0}; mncause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; mncause_en = 1'b0; @@ -554,15 +553,13 @@ module cve2_cs_registers #( CSR_MNSTATUS: begin mnstatus_en = 1'b1; mnstatus_d = '{ - mie: csr_wdata_int[CSR_MSTATUS_MIE_BIT], - mpie: csr_wdata_int[CSR_MSTATUS_MPIE_BIT], - mpp: priv_lvl_e'(csr_wdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW]), - mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT], - tw: csr_wdata_int[CSR_MSTATUS_TW_BIT] + nmie: csr_wdata_int[CSR_MNSTATUS_NMIE_BIT], + mnpv: csr_wdata_int[CSR_MNSTATUS_MNPV_BIT], + mnpp: priv_lvl_e'(csr_wdata_int[CSR_MNSTATUS_MNPP_BIT_HIGH:CSR_MNSTATUS_MNPP_BIT_LOW]) }; // Convert illegal values to M-mode - if ((mnstatus_d.mpp != PRIV_LVL_M) && (mnstatus_d.mpp != PRIV_LVL_U)) begin - mnstatus_d.mpp = PRIV_LVL_M; + if ((mnstatus_d.mnpp != PRIV_LVL_M) && (mnstatus_d.mnpp != PRIV_LVL_U)) begin + mnstatus_d.mnpp = PRIV_LVL_M; end end @@ -687,11 +684,12 @@ module cve2_cs_registers #( // includes cause, epc, tval, dpc and mstatus." [Debug Spec v0.13.2, p.39] mtval_en = 1'b1; mtval_d = csr_mtval_i; - //mstatus_en = 1'b1; - mnstatus_d.mie = 1'b0; // disable interrupts + mstatus_en = 1'b1; + mstatus_d.mie = 1'b0; // disable interrupts // save current status - mnstatus_d.mpie = mstatus_q.mie; - mnstatus_d.mpp = priv_lvl_q; + mnstatus_en = 1'b1; + //mnstatus_d.mpie = mstatus_q.mie; + mnstatus_d.mnpp = priv_lvl_q; mnepc_en = 1'b1; mnepc_d = exception_pc; mncause_en = 1'b1; @@ -721,8 +719,8 @@ module cve2_cs_registers #( if (nmi_mode_i) begin // when returning from an NMI restore state from mstatus CSR - mstatus_d.mpie = mnstatus_q.mpie; - mstatus_d.mpp = mnstatus_q.mpp; + mstatus_d.mpie = mstatus_q.mpie; + mstatus_d.mpp = mnstatus_q.mnpp; mepc_en = 1'b1; mepc_d = mepc_q; mcause_en = 1'b1; @@ -736,31 +734,24 @@ module cve2_cs_registers #( end // csr_restore_mret_i csr_restore_mnret_i: begin // MNRET - priv_lvl_d = mnstatus_q.mpp; - mnstatus_en = 1'b1; - mnstatus_d.mie = mnstatus_q.mpie; // re-enable interrupts + priv_lvl_d = mnstatus_q.mnpp; + mstatus_en = 1'b1; + mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts - if (mnstatus_q.mpp != PRIV_LVL_M) begin - mnstatus_d.mprv = 1'b0; + if (mnstatus_q.mnpp != PRIV_LVL_M) begin + mstatus_d.mprv = 1'b0; end // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - if (nmi_mode_i) begin - // when returning from an NMI restore state from mnstatus CSR - mstatus_d.mpie = mnstatus_q.mpie; - mstatus_d.mpp = mnstatus_q.mpp; - mepc_en = 1'b1; - mepc_d = mnepc_q; - mcause_en = 1'b1; - mcause_d = mncause_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 + // when returning from an NMI restore state from mnstatus CSR + mstatus_d.mpie = mstatus_q.mpie; + mstatus_d.mpp = mnstatus_q.mnpp; + mepc_en = 1'b1; + mepc_d = mnepc_q; + mcause_en = 1'b1; + mcause_d = mncause_q; end // csr_restore_mnret_i default:; @@ -1009,7 +1000,7 @@ module cve2_cs_registers #( tw: 1'b0}; cve2_csr #( - .Width ($bits(status_t)), + .Width ($bits(nm_status_t)), .ShadowCopy(1'b0), .ResetValue({MNSTATUS_RESET_VAL}) ) u_mnstatus_csr ( diff --git a/rtl/cve2_pkg.sv b/rtl/cve2_pkg.sv index 05587675bf..6451b3cede 100644 --- a/rtl/cve2_pkg.sv +++ b/rtl/cve2_pkg.sv @@ -545,6 +545,12 @@ package cve2_pkg; parameter int unsigned CSR_MSTATUS_MPRV_BIT = 17; parameter int unsigned CSR_MSTATUS_TW_BIT = 21; + // CSR mnstatus bits + parameter int unsigned CSR_MNSTATUS_NMIE_BIT = 3; + parameter int unsigned CSR_MNSTATUS_MNPV_BIT = 7; + parameter int unsigned CSR_MNSTATUS_MNPP_BIT_LOW = 11; + parameter int unsigned CSR_MNSTATUS_MNPP_BIT_HIGH = 12; + // CSR machine ISA parameter logic [1:0] CSR_MISA_MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32 From 96c73e0e517793a4d60391f3cbab936351b27831 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Mon, 9 Oct 2023 14:50:23 +0200 Subject: [PATCH 04/10] ignore virtualisation mode of the interrupted context Signed-off-by: Szymon Bieganski --- rtl/cve2_cs_registers.sv | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rtl/cve2_cs_registers.sv b/rtl/cve2_cs_registers.sv index 2af03af178..96d80a488b 100644 --- a/rtl/cve2_cs_registers.sv +++ b/rtl/cve2_cs_registers.sv @@ -137,7 +137,6 @@ module cve2_cs_registers #( typedef struct packed { logic nmie; - logic mnpv; priv_lvl_e mnpp; } nm_status_t; @@ -295,7 +294,6 @@ module cve2_cs_registers #( CSR_MNSTATUS: begin csr_rdata_int = '0; csr_rdata_int[CSR_MNSTATUS_NMIE_BIT] = mnstatus_q.nmie; - csr_rdata_int[CSR_MNSTATUS_MNPV_BIT] = mnstatus_q.mnpv; csr_rdata_int[CSR_MNSTATUS_MNPP_BIT_HIGH:CSR_MNSTATUS_MNPP_BIT_LOW] = mnstatus_q.mnpp; end @@ -521,7 +519,6 @@ module cve2_cs_registers #( mnstatus_d = mnstatus_q; mnscratch_en = 1'b0; mnepc_en = 1'b0; - /*mnstatus_d.mnpv = mstatus_q.mpv;*/ mnstatus_d.mnpp = mstatus_q.mpp; mnepc_d = {csr_wdata_int[31:1], 1'b0}; mncause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; @@ -554,7 +551,6 @@ module cve2_cs_registers #( mnstatus_en = 1'b1; mnstatus_d = '{ nmie: csr_wdata_int[CSR_MNSTATUS_NMIE_BIT], - mnpv: csr_wdata_int[CSR_MNSTATUS_MNPV_BIT], mnpp: priv_lvl_e'(csr_wdata_int[CSR_MNSTATUS_MNPP_BIT_HIGH:CSR_MNSTATUS_MNPP_BIT_LOW]) }; // Convert illegal values to M-mode From 36d0660766780d1639e843f9cba2abe23f00c471 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Mon, 30 Oct 2023 14:41:03 +0100 Subject: [PATCH 05/10] [doc] brief description Signed-off-by: Szymon Bieganski --- doc/03_reference/exception_interrupts.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/03_reference/exception_interrupts.rst b/doc/03_reference/exception_interrupts.rst index 3a010e78de..d2aa8e2ec9 100644 --- a/doc/03_reference/exception_interrupts.rst +++ b/doc/03_reference/exception_interrupts.rst @@ -67,11 +67,13 @@ In Debug Mode, all interrupts including the NMI are ignored independent of ``mst Recoverable Non-Maskable Interrupt ---------------------------------- -To support recovering from an NMI happening during a trap handling routine, Ibex features additional CSRs for backing up ``mstatus``.MPP, ``mstatus``.MPIE, ``mepc`` and ``mcause``. -These CSRs are not accessible by software running on the core. +The base machine-level architecture supports only unresumable non-maskable interrupts (UNMIs), where the NMI jumps to a handler in machine mode, overwriting the current ``mepc`` and ``mcause`` +register values. If the hart had been executing machine-mode code in a trap handler, the previous values in ``mepc`` and ``mcause`` would not be recoverable and so execution is not generally resumable. -These CSRs are nonstandard. -For more information, see `the corresponding proposal `_. +To support recovering from an NMI (RNMI) happening during a trap handling routine, CVE2 supports the Smrnmi extension. The extension adds four new CSRs (``mnepc``, ``mncause``, ``mnstatus``, and ``mnscratch``) to hold the +interrupted state, and one new instruction, MNRET, to resume from the RNMI handler. + +For more information, see chapter 4 in draft of 'The RISC-V Instruction Set Manual '_. Exceptions From 74850fdd024ab6e65733ed89d21e7ed9fb621e17 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Tue, 14 Nov 2023 09:45:35 +0100 Subject: [PATCH 06/10] correct url to a named chapter Signed-off-by: Szymon Bieganski --- doc/03_reference/exception_interrupts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/03_reference/exception_interrupts.rst b/doc/03_reference/exception_interrupts.rst index d2aa8e2ec9..1477ba4ea0 100644 --- a/doc/03_reference/exception_interrupts.rst +++ b/doc/03_reference/exception_interrupts.rst @@ -73,7 +73,7 @@ register values. If the hart had been executing machine-mode code in a trap hand To support recovering from an NMI (RNMI) happening during a trap handling routine, CVE2 supports the Smrnmi extension. The extension adds four new CSRs (``mnepc``, ``mncause``, ``mnstatus``, and ``mnscratch``) to hold the interrupted state, and one new instruction, MNRET, to resume from the RNMI handler. -For more information, see chapter 4 in draft of 'The RISC-V Instruction Set Manual '_. +For more information, see chapter '"Smrnmi" Standard Extension for Resumable Non-Maskable Interrupts"' in draft of 'The RISC-V Instruction Set Manual '_. Exceptions From 315621bd1505c37993cc33e0ed50d45636fbbb48 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Tue, 14 Nov 2023 13:25:37 +0100 Subject: [PATCH 07/10] [doc] reference to the specification draft/documentation Signed-off-by: Szymon Bieganski --- doc/01_specification/index.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/01_specification/index.rst b/doc/01_specification/index.rst index 36e38b6583..c3c7beef2b 100644 --- a/doc/01_specification/index.rst +++ b/doc/01_specification/index.rst @@ -193,6 +193,9 @@ identify the versions of RISC-V extensions from these specifications. Privileged Architecture Extension, version 0.9-draft, 3/15/2022, https://github.com/riscv/riscv-fast-interrupt/blob/master/clic.pdf +.. [SMRNMI] "Smrnmi" Standard Extension for Resumable Non-Maskable Interrupts + https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-056b6ff-2023-10-02/riscv-privileged.pdf#chapter.4 + Other documents =============== @@ -709,9 +712,7 @@ IRQs, but is not yet ratified at the time of specification. +---------+------------------------------------------------------------+ .. note:: - It should be noted that Ibex had implemented a custom mechanism for NMI - recovery. A standard RISC-V way of NMI recovery is in draft stage. In - future, the custom mechanism could be reworked to follow the standard. + A standard RISC-V way of NMI recovery is in draft stage [SMRNMI]_ Coprocessor interface --------------------- From ad54ed05d5cb54c338be969b160d57409b90939a Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Wed, 15 Nov 2023 12:16:41 +0100 Subject: [PATCH 08/10] [doc] refer to the original Ibex implementation Signed-off-by: Szymon Bieganski --- doc/01_specification/index.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/01_specification/index.rst b/doc/01_specification/index.rst index c3c7beef2b..a55bb9cab7 100644 --- a/doc/01_specification/index.rst +++ b/doc/01_specification/index.rst @@ -202,6 +202,9 @@ Other documents .. [FPGAreset] Ken Chapman, “Get Smart About Reset: Think Local, Not Global”, Xilinx WP272 white paper, https://docs.xilinx.com/v/u/en-US/wp272 +.. [Ibex] Production-quality open source 32-bit RISC-V CPU core written in SystemVerilog + https://ibex-core.readthedocs.io/en/latest/index.html + CV32E20 core functional requirements ==================================== @@ -712,7 +715,8 @@ IRQs, but is not yet ratified at the time of specification. +---------+------------------------------------------------------------+ .. note:: - A standard RISC-V way of NMI recovery is in draft stage [SMRNMI]_ + [Ibex] had implemented a custom mechanism for NMI recovery. In CVE2 this + custom mechanism is reworked to follow the drafted standsrd [SMRNMI]_. Coprocessor interface --------------------- From f05cdd90b791908deeb8c14c21a6c096200a7ed1 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Mon, 20 Nov 2023 12:23:31 +0100 Subject: [PATCH 09/10] [doc] correct typo Signed-off-by: Szymon Bieganski --- doc/01_specification/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/01_specification/index.rst b/doc/01_specification/index.rst index a55bb9cab7..f8bf3afaa1 100644 --- a/doc/01_specification/index.rst +++ b/doc/01_specification/index.rst @@ -716,7 +716,7 @@ IRQs, but is not yet ratified at the time of specification. .. note:: [Ibex] had implemented a custom mechanism for NMI recovery. In CVE2 this - custom mechanism is reworked to follow the drafted standsrd [SMRNMI]_. + custom mechanism is reworked to follow the drafted standard [SMRNMI]_. Coprocessor interface --------------------- From 1372bdc95f763f737ffbaf628463c70e34c257f1 Mon Sep 17 00:00:00 2001 From: Szymon Bieganski Date: Wed, 22 Nov 2023 14:11:27 +0100 Subject: [PATCH 10/10] [doc] list additional CSRs Signed-off-by: Szymon Bieganski --- doc/03_reference/cs_registers.rst | 58 ++++++++++++++++++++++++++++++- rtl/cve2_cs_registers.sv | 7 ++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/doc/03_reference/cs_registers.rst b/doc/03_reference/cs_registers.rst index c772aa744a..fd72bafefd 100644 --- a/doc/03_reference/cs_registers.rst +++ b/doc/03_reference/cs_registers.rst @@ -46,7 +46,13 @@ Ibex implements all the Control and Status Registers (CSRs) listed in the follow +---------+--------------------+--------+-----------------------------------------------+ | 0x3BF | ``pmpaddr15`` | WARL | PMP Address Register | +---------+--------------------+--------+-----------------------------------------------+ -| . . . . | +| 0x740 | ``mnscratch`` | WARL | Resumable NMI scratch register | ++---------+--------------------+--------+-----------------------------------------------+ +| 0x741 | ``mnepc`` | WARL | Resumable NMI program counter | ++---------+--------------------+--------+-----------------------------------------------+ +| 0x742 | ``mncause`` | WARL | Resumable NMI cause register | ++---------+--------------------+--------+-----------------------------------------------+ +| 0x744 | ``mnstatus`` | WARL | Resumable NMI status register | +---------+--------------------+--------+-----------------------------------------------+ | 0x757 | ``mseccfgh`` | WARL | Upper 32 bits of ``mseccfg`` | +---------+--------------------+--------+-----------------------------------------------+ @@ -310,6 +316,56 @@ Reset Value: ``0x0000_0000`` .. _csr-tselect: +Resumable NMI Machine Exception PC (mnepc) +--------------------------- + +CSR Address: ``0x741`` + +Reset Value: ``0x0000_0000`` + +When an NMI exception is encountered, the current program counter is saved in ``mnepc``, and the core jumps to the exception address. +When an MNRET instruction is executed, the value from ``mnepc`` replaces the current program counter. + + +Resumable NMI Machine Cause (mncause) +---------------------- + +CSR Address: ``0x742`` + +Reset Value: ``0x0000_0000`` + ++-------+------+------------------------------------------------------------------+ +| Bit# | R/W | Description | ++-------+------+------------------------------------------------------------------+ +| 31 | R | **Interrupt:** This bit is set when the exception was triggered | +| | | by an interrupt. | ++-------+------+------------------------------------------------------------------+ +| 30:0 | WARL | **NMI Cause** | ++-------+------+------------------------------------------------------------------+ + +The mncause CSR holds the reason for the NMI, with bit MXLEN-1 set to 1, and the NMI cause +encoded in the least-significant bits or zero if NMI causes are not supported. + +Resumable NMI Machine Status (mnstatus) +------------------------ + +CSR Address: ``0x744`` + +Reset Value: ``0x0000_0000`` + ++-------+-----+---------------------------------------------------------------------------------+ +| Bit# | R/W | Description | ++-------+-----+---------------------------------------------------------------------------------+ +| 12:11 | RW | **MNPP:** Machine Previous Privilege mode. | ++-------+-----+---------------------------------------------------------------------------------+ +| 3 | RW | **Interrupt Enable (NMIE):** If set to 1'b1, interrupts are globally enabled. | ++-------+-----+---------------------------------------------------------------------------------+ + +When an RNMI interrupt is detected, The ``mnstatus``.NMIE bit is cleared, masking all interrupts. If you want to enable interrupt handling in your exception handler, set ``mnstatus``.NMIE back to 1'b1 inside your handler code. + +Only Machine Mode and User Mode are supported. +Any write to ``mnstatus``.MNPP of an unsupported value will be interpreted as Machine Mode. + Trigger Select Register (tselect) --------------------------------- diff --git a/rtl/cve2_cs_registers.sv b/rtl/cve2_cs_registers.sv index 4d17297687..191e982a87 100644 --- a/rtl/cve2_cs_registers.sv +++ b/rtl/cve2_cs_registers.sv @@ -999,11 +999,8 @@ module cve2_cs_registers #( ); // MNSTATUS - localparam status_t MNSTATUS_RESET_VAL = '{mie: 1'b0, - mpie: 1'b0, - mpp: PRIV_LVL_M, - mprv: 1'b0, - tw: 1'b0}; + localparam nm_status_t MNSTATUS_RESET_VAL = '{nmie: 1'b0, + mnpp: PRIV_LVL_M}; cve2_csr #( .Width ($bits(nm_status_t)),