mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-20 03:57:25 -04:00
[rtl] Decouple mip
and mie
CSRs
This commit modifies the `mip` CSR to not depend on the `mie` CSR. While the values of both these CSRs are combined to decide whether an interrupt shall be handled, the RISC-V spec does not state that the content of of `mip` should depend on `mie`. This commit better aligns Ibex with other open-source RISC-V cores. This resolves lowRISC/ibex#567 reported by @pfmooney. Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
This commit is contained in:
parent
6708ba62ac
commit
2a42c23eaf
7 changed files with 54 additions and 79 deletions
|
@ -45,12 +45,9 @@ module tb_cs_registers #(
|
|||
logic irq_timer_i;
|
||||
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
|
||||
logic [14:0] csr_mfip_o; // fast interrupt pending
|
||||
logic irq_pending_o; // interupt request pending
|
||||
ibex_pkg::irqs_t irqs_o;
|
||||
logic csr_mstatus_mie_o;
|
||||
logic [31:0] csr_mepc_o;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ lint_off -msg UNUSED -file "*/rtl/ibex_register_file_fpga.sv" -lines 20
|
|||
// 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 170
|
||||
lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 158
|
||||
|
||||
// Bits of signal are not used: instr_alu[24:15,11:7]
|
||||
// instr flops are duplicated to reduce fan-out, neater to just leave unused
|
||||
|
|
|
@ -56,11 +56,9 @@ module ibex_controller (
|
|||
|
||||
// interrupt signals
|
||||
input logic csr_mstatus_mie_i, // M-mode interrupt enable bit
|
||||
input logic csr_msip_i, // software interrupt pending
|
||||
input logic csr_mtip_i, // timer interrupt pending
|
||||
input logic csr_meip_i, // external interrupt pending
|
||||
input logic [14:0] csr_mfip_i, // fast interrupt pending
|
||||
input logic irq_pending_i, // interrupt request pending
|
||||
input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with
|
||||
// mie CSR
|
||||
input logic irq_nm_i, // non-maskeable interrupt
|
||||
output logic nmi_mode_o, // core executing NMI handler
|
||||
|
||||
|
@ -124,7 +122,7 @@ module ibex_controller (
|
|||
logic handle_irq;
|
||||
|
||||
logic [3:0] mfip_id;
|
||||
logic unused_csr_mtip;
|
||||
logic unused_irq_timer;
|
||||
|
||||
logic ecall_insn;
|
||||
logic mret_insn;
|
||||
|
@ -221,25 +219,25 @@ module ibex_controller (
|
|||
|
||||
// generate ID of fast interrupts, highest priority to highest ID
|
||||
always_comb begin : gen_mfip_id
|
||||
if (csr_mfip_i[14]) mfip_id = 4'd14;
|
||||
else if (csr_mfip_i[13]) mfip_id = 4'd13;
|
||||
else if (csr_mfip_i[12]) mfip_id = 4'd12;
|
||||
else if (csr_mfip_i[11]) mfip_id = 4'd11;
|
||||
else if (csr_mfip_i[10]) mfip_id = 4'd10;
|
||||
else if (csr_mfip_i[ 9]) mfip_id = 4'd9;
|
||||
else if (csr_mfip_i[ 8]) mfip_id = 4'd8;
|
||||
else if (csr_mfip_i[ 7]) mfip_id = 4'd7;
|
||||
else if (csr_mfip_i[ 6]) mfip_id = 4'd6;
|
||||
else if (csr_mfip_i[ 5]) mfip_id = 4'd5;
|
||||
else if (csr_mfip_i[ 5]) mfip_id = 4'd5;
|
||||
else if (csr_mfip_i[ 4]) mfip_id = 4'd4;
|
||||
else if (csr_mfip_i[ 3]) mfip_id = 4'd3;
|
||||
else if (csr_mfip_i[ 2]) mfip_id = 4'd2;
|
||||
else if (csr_mfip_i[ 1]) mfip_id = 4'd1;
|
||||
else mfip_id = 4'd0;
|
||||
if (irqs_i.irq_fast[14]) mfip_id = 4'd14;
|
||||
else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
|
||||
else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
|
||||
else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
|
||||
else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
|
||||
else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
|
||||
else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
|
||||
else if (irqs_i.irq_fast[ 7]) mfip_id = 4'd7;
|
||||
else if (irqs_i.irq_fast[ 6]) mfip_id = 4'd6;
|
||||
else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
|
||||
else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
|
||||
else if (irqs_i.irq_fast[ 4]) mfip_id = 4'd4;
|
||||
else if (irqs_i.irq_fast[ 3]) mfip_id = 4'd3;
|
||||
else if (irqs_i.irq_fast[ 2]) mfip_id = 4'd2;
|
||||
else if (irqs_i.irq_fast[ 1]) mfip_id = 4'd1;
|
||||
else mfip_id = 4'd0;
|
||||
end
|
||||
|
||||
assign unused_csr_mtip = csr_mtip_i;
|
||||
assign unused_irq_timer = irqs_i.irq_timer;
|
||||
|
||||
/////////////////////
|
||||
// Core controller //
|
||||
|
@ -418,17 +416,17 @@ module ibex_controller (
|
|||
if (irq_nm_i && !nmi_mode_q) begin
|
||||
exc_cause_o = EXC_CAUSE_IRQ_NM;
|
||||
nmi_mode_d = 1'b1; // enter NMI mode
|
||||
end else if (csr_mfip_i != 15'b0) begin
|
||||
end else if (irqs_i.irq_fast != 15'b0) begin
|
||||
// generate exception cause ID from fast interrupt ID:
|
||||
// - first bit distinguishes interrupts from exceptions,
|
||||
// - second bit adds 16 to fast interrupt ID
|
||||
// for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16}
|
||||
exc_cause_o = exc_cause_e'({2'b11, mfip_id});
|
||||
end else if (csr_meip_i) begin
|
||||
end else if (irqs_i.irq_external) begin
|
||||
exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M;
|
||||
end else if (csr_msip_i) begin
|
||||
end else if (irqs_i.irq_software) begin
|
||||
exc_cause_o = EXC_CAUSE_IRQ_SOFTWARE_M;
|
||||
end else begin // csr_mtip_i
|
||||
end else begin // irqs_i.irq_timer
|
||||
exc_cause_o = EXC_CAUSE_IRQ_TIMER_M;
|
||||
end
|
||||
end
|
||||
|
|
|
@ -184,10 +184,7 @@ module ibex_core #(
|
|||
// Interrupts
|
||||
logic irq_pending;
|
||||
logic nmi_mode;
|
||||
logic csr_msip;
|
||||
logic csr_mtip;
|
||||
logic csr_meip;
|
||||
logic [14:0] csr_mfip;
|
||||
irqs_t irqs;
|
||||
logic csr_mstatus_mie;
|
||||
logic [31:0] csr_mepc, csr_depc;
|
||||
|
||||
|
@ -450,11 +447,8 @@ module ibex_core #(
|
|||
|
||||
// Interrupt Signals
|
||||
.csr_mstatus_mie_i ( csr_mstatus_mie ),
|
||||
.csr_msip_i ( csr_msip ),
|
||||
.csr_mtip_i ( csr_mtip ),
|
||||
.csr_meip_i ( csr_meip ),
|
||||
.csr_mfip_i ( csr_mfip ),
|
||||
.irq_pending_i ( irq_pending ),
|
||||
.irqs_i ( irqs ),
|
||||
.irq_nm_i ( irq_nm_i ),
|
||||
.nmi_mode_o ( nmi_mode ),
|
||||
|
||||
|
@ -626,12 +620,9 @@ module ibex_core #(
|
|||
.irq_timer_i ( irq_timer_i ),
|
||||
.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 ),
|
||||
.csr_mfip_o ( csr_mfip ),
|
||||
.irq_pending_o ( irq_pending ),
|
||||
.irqs_o ( irqs ),
|
||||
.csr_mstatus_mie_o ( csr_mstatus_mie ),
|
||||
.csr_mstatus_tw_o ( csr_mstatus_tw ),
|
||||
.csr_mepc_o ( csr_mepc ),
|
||||
|
|
|
@ -52,12 +52,9 @@ module ibex_cs_registers #(
|
|||
input logic irq_timer_i,
|
||||
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
|
||||
output logic [14:0] csr_mfip_o, // fast interrupt pending
|
||||
output logic irq_pending_o, // interrupt request pending
|
||||
output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie
|
||||
output logic csr_mstatus_mie_o,
|
||||
output logic [31:0] csr_mepc_o,
|
||||
|
||||
|
@ -134,15 +131,6 @@ module ibex_cs_registers #(
|
|||
priv_lvl_e mpp;
|
||||
} StatusStk_t;
|
||||
|
||||
// struct for mip/mie CSRs
|
||||
typedef struct packed {
|
||||
logic irq_software;
|
||||
logic irq_timer;
|
||||
logic irq_external;
|
||||
logic [14:0] irq_fast; // 15 fast interrupts,
|
||||
// one interrupt is reserved for NMI (not visible through mip/mie)
|
||||
} Interrupts_t;
|
||||
|
||||
typedef struct packed {
|
||||
x_debug_ver_e xdebugver;
|
||||
logic [11:0] zero2;
|
||||
|
@ -167,13 +155,13 @@ module ibex_cs_registers #(
|
|||
// CSRs
|
||||
priv_lvl_e priv_lvl_q, priv_lvl_d;
|
||||
Status_t mstatus_q, mstatus_d;
|
||||
Interrupts_t mie_q, mie_d;
|
||||
irqs_t mie_q, mie_d;
|
||||
logic [31:0] mscratch_q, mscratch_d;
|
||||
logic [31:0] mepc_q, mepc_d;
|
||||
logic [5:0] mcause_q, mcause_d;
|
||||
logic [31:0] mtval_q, mtval_d;
|
||||
logic [31:0] mtvec_q, mtvec_d;
|
||||
Interrupts_t mip;
|
||||
irqs_t mip;
|
||||
Dcsr_t dcsr_q, dcsr_d;
|
||||
logic [31:0] depc_q, depc_d;
|
||||
logic [31:0] dscratch0_q, dscratch0_d;
|
||||
|
@ -242,10 +230,10 @@ module ibex_cs_registers #(
|
|||
assign illegal_csr_insn_o = csr_access_i & (illegal_csr | illegal_csr_write | illegal_csr_priv);
|
||||
|
||||
// mip CSR is purely combinational - must be able to re-enable the clock upon WFI
|
||||
assign mip.irq_software = irq_software_i & mie_q.irq_software;
|
||||
assign mip.irq_timer = irq_timer_i & mie_q.irq_timer;
|
||||
assign mip.irq_external = irq_external_i & mie_q.irq_external;
|
||||
assign mip.irq_fast = irq_fast_i & mie_q.irq_fast;
|
||||
assign mip.irq_software = irq_software_i;
|
||||
assign mip.irq_timer = irq_timer_i;
|
||||
assign mip.irq_external = irq_external_i;
|
||||
assign mip.irq_fast = irq_fast_i;
|
||||
|
||||
// read logic
|
||||
always_comb begin
|
||||
|
@ -632,11 +620,6 @@ module ibex_cs_registers #(
|
|||
assign csr_rdata_o = csr_rdata_int;
|
||||
|
||||
// directly output some registers
|
||||
assign csr_msip_o = mip.irq_software;
|
||||
assign csr_mtip_o = mip.irq_timer;
|
||||
assign csr_meip_o = mip.irq_external;
|
||||
assign csr_mfip_o = mip.irq_fast;
|
||||
|
||||
assign csr_mepc_o = mepc_q;
|
||||
assign csr_depc_o = depc_q;
|
||||
assign csr_mtvec_o = mtvec_q;
|
||||
|
@ -647,7 +630,10 @@ module ibex_cs_registers #(
|
|||
assign debug_ebreakm_o = dcsr_q.ebreakm;
|
||||
assign debug_ebreaku_o = dcsr_q.ebreaku;
|
||||
|
||||
assign irq_pending_o = csr_msip_o | csr_mtip_o | csr_meip_o | (|csr_mfip_o);
|
||||
// Qualify incoming interrupt requests in mip CSR with mie CSR for controller and to re-enable
|
||||
// clock upon WFI (must be purely combinational).
|
||||
assign irqs_o = mip & mie_q;
|
||||
assign irq_pending_o = |irqs_o;
|
||||
|
||||
// actual registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
|
|
@ -101,11 +101,8 @@ module ibex_id_stage #(
|
|||
|
||||
// Interrupt signals
|
||||
input logic csr_mstatus_mie_i,
|
||||
input logic csr_msip_i,
|
||||
input logic csr_mtip_i,
|
||||
input logic csr_meip_i,
|
||||
input logic [14:0] csr_mfip_i,
|
||||
input logic irq_pending_i,
|
||||
input ibex_pkg::irqs_t irqs_i,
|
||||
input logic irq_nm_i,
|
||||
output logic nmi_mode_o,
|
||||
|
||||
|
@ -447,11 +444,8 @@ module ibex_id_stage #(
|
|||
|
||||
// interrupt signals
|
||||
.csr_mstatus_mie_i ( csr_mstatus_mie_i ),
|
||||
.csr_msip_i ( csr_msip_i ),
|
||||
.csr_mtip_i ( csr_mtip_i ),
|
||||
.csr_meip_i ( csr_meip_i ),
|
||||
.csr_mfip_i ( csr_mfip_i ),
|
||||
.irq_pending_i ( irq_pending_i ),
|
||||
.irqs_i ( irqs_i ),
|
||||
.irq_nm_i ( irq_nm_i ),
|
||||
.nmi_mode_o ( nmi_mode_o ),
|
||||
|
||||
|
|
|
@ -166,6 +166,15 @@ typedef enum logic [1:0] {
|
|||
EXC_PC_DBG_EXC // Exception while in debug mode
|
||||
} exc_pc_sel_e;
|
||||
|
||||
// Interrupt requests
|
||||
typedef struct packed {
|
||||
logic irq_software;
|
||||
logic irq_timer;
|
||||
logic irq_external;
|
||||
logic [14:0] irq_fast; // 15 fast interrupts,
|
||||
// one interrupt is reserved for NMI (not visible through mip/mie)
|
||||
} irqs_t;
|
||||
|
||||
// Exception cause
|
||||
typedef enum logic [5:0] {
|
||||
EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue