Add mip and mie CSRs + interrupts

This commit adds the `mip` and `mie` CSRs as well as the software,
timer and external interrupts.

Currently these interrupts are overlapped with some of the legacy
interrupts, i.e., the core will jump to the same address for different
interrupts. For example, the software interrupt has the same ID as
legacy interrupt #3. Thus, the handler must read the `mip` register
to find out whether the interrupt routine has been entered because of
the software interrupt or the legacy interrupt.

Eventually, the number of legacy interrupts will be reduced to avoid
this overlapping, and they will be connected to the `mie` and `mip`
CSRs directly.
This commit is contained in:
Pirmin Vogel 2019-07-11 13:15:03 +01:00
parent 1a487c4626
commit c2fffe0440
5 changed files with 120 additions and 20 deletions

View file

@ -73,14 +73,19 @@ module ibex_controller (
input logic [4:0] irq_id_ctrl_i,
input logic m_IE_i, // interrupt enable bit from CSR
// (M mode)
output logic irq_ack_o,
output logic [4:0] irq_id_o,
output ibex_pkg::exc_cause_e exc_cause_o,
output logic exc_ack_o,
output logic exc_kill_o,
// interrupt pending bits from CSRs
input logic csr_msip_i, // software interrupt pending
input logic csr_mtip_i, // timer interrupt pending
input logic csr_meip_i, // external interrupt pending
output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs
// debug signals
input logic debug_req_i,
output ibex_pkg::dbg_cause_e debug_cause_o,
@ -128,6 +133,7 @@ module ibex_controller (
logic exc_req_lsu;
logic special_req;
logic enter_debug_mode;
logic irq;
logic handle_irq;
`ifndef SYNTHESIS
@ -167,8 +173,9 @@ module ibex_controller (
assign enter_debug_mode = debug_req_i & ~debug_mode_q;
assign irq = csr_msip_i | csr_mtip_i | csr_meip_i;
// interrupts including NMI are ignored while in debug mode [Debug Spec v0.13.2, p.39]
assign handle_irq = irq_req_ctrl_i & m_IE_i & ~debug_mode_q;
assign handle_irq = (irq | irq_req_ctrl_i) & m_IE_i & ~debug_mode_q;
assign exc_kill_o = 1'b0;
/////////////////////
@ -249,7 +256,7 @@ module ibex_controller (
// normal execution flow
// in debug mode or single step mode we leave immediately (wfi=nop)
if (irq_i || debug_req_i || debug_mode_q || debug_single_step_i) begin
if (irq_i || irq || debug_req_i || debug_mode_q || debug_single_step_i) begin
ctrl_fsm_ns = FIRST_FETCH;
end
end
@ -342,14 +349,23 @@ module ibex_controller (
pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_IRQ;
exc_cause_o = exc_cause_e'({1'b1, irq_id_ctrl_i});
// interrupt priorities according to Privileged Spec v1.11 p.31
if (csr_meip_i) begin
exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M;
end else if (csr_msip_i) begin
exc_cause_o = EXC_CAUSE_IRQ_SOFTWARE_M;
end else if (csr_mtip_i) begin
exc_cause_o = EXC_CAUSE_IRQ_TIMER_M;
end else begin
exc_cause_o = exc_cause_e'({1'b1, irq_id_ctrl_i});
irq_ack_o = 1'b1;
exc_ack_o = 1'b1;
end
csr_save_cause_o = 1'b1;
csr_save_if_o = 1'b1;
irq_ack_o = 1'b1;
exc_ack_o = 1'b1;
ctrl_fsm_ns = DECODE;
end

View file

@ -66,6 +66,9 @@ module ibex_core #(
input logic data_err_i,
// Interrupt inputs
input logic irq_software_i,
input logic irq_timer_i,
input logic irq_external_i,
input logic irq_i, // level sensitive IR lines
input logic [4:0] irq_id_i,
output logic irq_ack_o, // irq ack
@ -187,6 +190,9 @@ module ibex_core #(
logic instr_req_int; // Id stage asserts a req to instruction core interface
// Interrupts
logic csr_msip;
logic csr_mtip;
logic csr_meip;
logic m_irq_enable;
logic [31:0] csr_mepc, csr_depc;
@ -268,7 +274,7 @@ module ibex_core #(
assign core_busy = core_ctrl_firstfetch ? 1'b1 : core_busy_q;
assign clock_en = core_busy | irq_i | debug_req_i;
assign clock_en = core_busy | irq_i | csr_meip | csr_mtip | csr_msip | debug_req_i;
// main clock gate of the core
// generates all clocks except the one for the debug unit which is
@ -417,6 +423,9 @@ module ibex_core #(
.lsu_store_err_i ( lsu_store_err ),
// Interrupt Signals
.csr_msip_i ( csr_msip ),
.csr_mtip_i ( csr_mtip ),
.csr_meip_i ( csr_meip ),
.irq_i ( irq_i ), // incoming interrupts
.irq_id_i ( irq_id_i ),
.m_irq_enable_i ( m_irq_enable ),
@ -560,6 +569,12 @@ module ibex_core #(
.csr_rdata_o ( csr_rdata ),
// Interrupt related control signals
.irq_software_i ( irq_software_i ),
.irq_timer_i ( irq_timer_i ),
.irq_external_i ( irq_external_i ),
.csr_msip_o ( csr_msip ),
.csr_mtip_o ( csr_mtip ),
.csr_meip_o ( csr_meip ),
.m_irq_enable_o ( m_irq_enable ),
.csr_mepc_o ( csr_mepc ),

View file

@ -46,7 +46,13 @@ module ibex_cs_registers #(
input ibex_pkg::csr_op_e csr_op_i,
output logic [31:0] csr_rdata_o,
// Interrupts
// interrupts
input logic irq_software_i,
input logic irq_timer_i,
input logic irq_external_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 m_irq_enable_o,
output logic [31:0] csr_mepc_o,
@ -127,6 +133,13 @@ module ibex_cs_registers #(
priv_lvl_e mpp;
} Status_t;
// struct for mip/mie CSRs
typedef struct packed {
logic software;
logic timer;
logic external;
} Interrupts_t;
typedef struct packed {
x_debug_ver_e xdebugver;
logic [11:0] zero2;
@ -150,10 +163,12 @@ module ibex_cs_registers #(
// CSRs
Status_t mstatus_q, mstatus_d;
Interrupts_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;
Interrupts_t mip;
Dcsr_t dcsr_q, dcsr_d;
logic [31:0] depc_q, depc_d;
logic [31:0] dscratch0_q, dscratch0_d;
@ -195,6 +210,11 @@ module ibex_cs_registers #(
assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wreq;
assign illegal_csr_insn_o = illegal_csr | illegal_csr_write | illegal_csr_priv;
// mip CSR is purely combintational - must be able to re-enable the clock upon WFI
assign mip.software = irq_software_i & mie_q.software;
assign mip.timer = irq_timer_i & mie_q.timer;
assign mip.external = irq_external_i & mie_q.external;
// read logic
always_comb begin
csr_rdata_int = '0;
@ -220,6 +240,14 @@ module ibex_cs_registers #(
// misa
CSR_MISA: csr_rdata_int = MISA_VALUE;
// interrupt enable
CSR_MIE: begin
csr_rdata_int = '0;
csr_rdata_int[CSR_MSIX_BIT] = mie_q.software;
csr_rdata_int[CSR_MTIX_BIT] = mie_q.timer;
csr_rdata_int[CSR_MEIX_BIT] = mie_q.external;
end
CSR_MSCRATCH: csr_rdata_int = mscratch_q;
// mtvec: trap-vector base address
@ -234,6 +262,14 @@ module ibex_cs_registers #(
// mtval: trap value
CSR_MTVAL: csr_rdata_int = mtval_q;
// mip: interrupt pending
CSR_MIP: begin
csr_rdata_int = '0;
csr_rdata_int[CSR_MSIX_BIT] = mip.software;
csr_rdata_int[CSR_MTIX_BIT] = mip.timer;
csr_rdata_int[CSR_MEIX_BIT] = mip.external;
end
CSR_DCSR: csr_rdata_int = dcsr_q;
CSR_DPC: csr_rdata_int = depc_q;
CSR_DSCRATCH0: csr_rdata_int = dscratch0_q;
@ -285,6 +321,7 @@ module ibex_cs_registers #(
exception_pc = pc_id_i;
mstatus_d = mstatus_q;
mie_d = mie_q;
mscratch_d = mscratch_q;
mepc_d = mepc_q;
mcause_d = mcause_q;
@ -309,6 +346,15 @@ module ibex_cs_registers #(
end
end
// interrupt enable
CSR_MIE: begin
if (csr_we_int) begin
mie_d.software = csr_wdata_int[CSR_MSIX_BIT];
mie_d.timer = csr_wdata_int[CSR_MTIX_BIT];
mie_d.external = csr_wdata_int[CSR_MEIX_BIT];
end
end
CSR_MSCRATCH: if (csr_we_int) mscratch_d = csr_wdata_int;
// mepc: exception program counter
@ -469,6 +515,10 @@ module ibex_cs_registers #(
assign csr_rdata_o = csr_rdata_int;
// directly output some registers
assign csr_msip_o = mip.software;
assign csr_mtip_o = mip.timer;
assign csr_meip_o = mip.external;
assign m_irq_enable_o = mstatus_q.mie;
assign csr_mepc_o = mepc_q;
assign csr_depc_o = depc_q;
@ -484,6 +534,7 @@ module ibex_cs_registers #(
mpie: 1'b0,
mpp: PRIV_LVL_M
};
mie_q <= '0;
mscratch_q <= '0;
mepc_q <= '0;
mcause_q <= '0;
@ -504,6 +555,7 @@ module ibex_cs_registers #(
mpie: mstatus_d.mpie,
mpp: PRIV_LVL_M
};
mie_q <= mie_d;
mscratch_q <= mscratch_d;
mepc_q <= mepc_d;
mcause_q <= mcause_d;

View file

@ -106,6 +106,9 @@ module ibex_id_stage #(
input logic [31:0] lsu_addr_last_i,
// Interrupt signals
input logic csr_msip_i,
input logic csr_mtip_i,
input logic csr_meip_i,
input logic irq_i,
input logic [4:0] irq_id_i,
input logic m_irq_enable_i,
@ -427,14 +430,11 @@ module ibex_id_stage #(
.instr_valid_clear_o ( instr_valid_clear_o ),
.id_in_ready_o ( id_in_ready_o ),
// from prefetcher
.instr_req_o ( instr_req_o ),
// to prefetcher
.instr_req_o ( instr_req_o ),
.pc_set_o ( pc_set_o ),
.pc_mux_o ( pc_mux_o ),
.exc_pc_mux_o ( exc_pc_mux_o ),
.exc_cause_o ( exc_cause_o ),
// LSU
.lsu_addr_last_i ( lsu_addr_last_i ),
@ -457,6 +457,13 @@ module ibex_id_stage #(
.exc_ack_o ( exc_ack ),
.exc_kill_o ( exc_kill ),
// interrupt pending bits from CSRs
.csr_msip_i ( csr_msip_i ),
.csr_mtip_i ( csr_mtip_i ),
.csr_meip_i ( csr_meip_i ),
.exc_cause_o ( exc_cause_o ),
// CSR Controller Signals
.csr_save_if_o ( csr_save_if_o ),
.csr_save_id_o ( csr_save_id_o ),

View file

@ -183,12 +183,15 @@ typedef enum logic [1:0] {
// Exception cause
typedef enum logic [5:0] {
EXC_CAUSE_INSN_ADDR_MISA = 6'h00,
EXC_CAUSE_ILLEGAL_INSN = 6'h02,
EXC_CAUSE_BREAKPOINT = 6'h03,
EXC_CAUSE_LOAD_ACCESS_FAULT = 6'h05,
EXC_CAUSE_STORE_ACCESS_FAULT = 6'h07,
EXC_CAUSE_ECALL_MMODE = 6'h0B
EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03},
EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07},
EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11},
EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00},
EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd01},
EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03},
EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05},
EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11}
} exc_cause_e;
// Debug cause
@ -208,6 +211,7 @@ typedef enum logic[11:0] {
// Machine trap setup
CSR_MSTATUS = 12'h300,
CSR_MISA = 12'h301,
CSR_MIE = 12'h304,
CSR_MTVEC = 12'h305,
// Machine trap handling
@ -215,6 +219,7 @@ typedef enum logic[11:0] {
CSR_MEPC = 12'h341,
CSR_MCAUSE = 12'h342,
CSR_MTVAL = 12'h343,
CSR_MIP = 12'h344,
// Debug/trace
CSR_DCSR = 12'h7b0,
@ -238,4 +243,9 @@ parameter logic [11:0] CSR_OFF_MCOUNTER = 12'hB00; // mcounter @ 12'
parameter logic [11:0] CSR_OFF_MCOUNTERH = 12'hB80; // mcounterh @ 12'hB83 - 12'hB9F
parameter logic [11:0] CSR_MASK_MCOUNTER = 12'hFE0;
// CSR interrupt pending/enable bits
parameter int unsigned CSR_MSIX_BIT = 3;
parameter int unsigned CSR_MTIX_BIT = 7;
parameter int unsigned CSR_MEIX_BIT = 11;
endpackage