diff --git a/dv/cs_registers/tb/tb_cs_registers.sv b/dv/cs_registers/tb/tb_cs_registers.sv index d93b8a31..ea2893fe 100644 --- a/dv/cs_registers/tb/tb_cs_registers.sv +++ b/dv/cs_registers/tb/tb_cs_registers.sv @@ -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; diff --git a/lint/verilator_waiver.vlt b/lint/verilator_waiver.vlt index 065a46cd..7be67c3e 100644 --- a/lint/verilator_waiver.vlt +++ b/lint/verilator_waiver.vlt @@ -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 diff --git a/rtl/ibex_controller.sv b/rtl/ibex_controller.sv index 796bc05a..aee4f55b 100644 --- a/rtl/ibex_controller.sv +++ b/rtl/ibex_controller.sv @@ -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 diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 244e4998..7291d2bd 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -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 ), diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index c7e074d2..67ab0013 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -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 diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index dad78b78..56c8c5aa 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -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 ), diff --git a/rtl/ibex_pkg.sv b/rtl/ibex_pkg.sv index 60059c49..15faa54d 100644 --- a/rtl/ibex_pkg.sv +++ b/rtl/ibex_pkg.sv @@ -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},