mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 11:57:12 -04:00
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:
parent
1a487c4626
commit
c2fffe0440
5 changed files with 120 additions and 20 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ),
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ),
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue