mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Cherry pick 1
This commit is contained in:
parent
8fe67b303d
commit
d274068643
2 changed files with 89 additions and 9 deletions
|
@ -52,7 +52,7 @@ module cs_registers
|
|||
|
||||
output logic irq_enable_o,
|
||||
output logic [31:0] epcr_o,
|
||||
|
||||
output logic timer_cmp_irq_o,
|
||||
// Performance Counters
|
||||
input logic stall_id_i, // stall ID stage
|
||||
input logic is_compressed_i, // compressed instruction in ID
|
||||
|
@ -100,6 +100,9 @@ module cs_registers
|
|||
// Generic CSRs
|
||||
logic [31:0] csr [0:`CSR_MAX_IDX];
|
||||
logic [31:0] csr_n [0:`CSR_MAX_IDX];
|
||||
|
||||
// mtime - cycle count
|
||||
//logic [31:0] csr_mtime_int, csr_mtime;
|
||||
|
||||
// CSR update logic
|
||||
logic [31:0] csr_wdata_int;
|
||||
|
@ -108,7 +111,16 @@ module cs_registers
|
|||
|
||||
// Interrupt control signals
|
||||
logic irq_enable, irq_enable_n;
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
// ____ ____ ____ ____ //
|
||||
// / ___/ ___|| _ \ | _ \ ___ __ _ //
|
||||
// | | \___ \| |_) | | |_) / _ \/ _` | //
|
||||
// | |___ ___) | _ < | _ < __/ (_| | //
|
||||
// \____|____/|_| \_\ |_| \_\___|\__, | //
|
||||
// |___/ //
|
||||
////////////////////////////////////////////
|
||||
|
||||
// read logic
|
||||
always_comb
|
||||
|
@ -130,6 +142,15 @@ module cs_registers
|
|||
12'hF01: csr_rdata_int = 32'h00_00_80_00;
|
||||
// mhartid: unique hardware thread id
|
||||
12'hF10: csr_rdata_int = {22'b0, cluster_id_i, core_id_i};
|
||||
|
||||
// Machine trap setup 0x300 - 0x321
|
||||
// mtimecmp - machine wall-clock timer compare value
|
||||
12'h321: csr_rdata_int = csr[`CSR_IDX_MTIMECMP];
|
||||
|
||||
// machine level timers and counters 0x701 - 0x741
|
||||
// mtime - machine wall-clock time (? - actually not really wall clock??)
|
||||
12'h701: csr_rdata_int = csr[`CSR_IDX_MTIME];
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -138,6 +159,9 @@ module cs_registers
|
|||
always_comb
|
||||
begin
|
||||
csr_n = csr;
|
||||
//if timer interrupt occured - reset status unless it is written by the application
|
||||
if (timer_cmp_irq_o == 1'b1) csr_n[`CSR_IDX_MTIME] = 32'b0;
|
||||
|
||||
irq_enable_n = irq_enable;
|
||||
|
||||
case (csr_addr_i)
|
||||
|
@ -148,6 +172,12 @@ module cs_registers
|
|||
12'h340: if (csr_we_int) csr_n[`CSR_IDX_MSCRATCH] = csr_wdata_int;
|
||||
// mepc: exception program counter
|
||||
12'h341: if (csr_we_int) csr_n[`CSR_IDX_MEPC] = csr_wdata_int;
|
||||
|
||||
// mtimecmp
|
||||
12'h321: if (csr_we_int) csr_n[`CSR_IDX_MTIMECMP] = csr_wdata_int;
|
||||
|
||||
// mtime
|
||||
12'h701: if (csr_we_int) csr_n[`CSR_IDX_MTIME] = csr_wdata_int;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -198,9 +228,11 @@ module cs_registers
|
|||
else
|
||||
begin
|
||||
// update CSRs
|
||||
csr <= csr_n;
|
||||
irq_enable <= irq_enable_n;
|
||||
csr <= csr_n;
|
||||
// increment the timer register (mtime)
|
||||
csr[`CSR_IDX_MTIME] <= csr_n[`CSR_IDX_MTIME] + 1;
|
||||
|
||||
irq_enable <= irq_enable_n;
|
||||
// exception PC writes from exception controller get priority
|
||||
if (save_pc_if_i == 1'b1)
|
||||
csr[`CSR_IDX_MEPC] <= curr_pc_if_i;
|
||||
|
@ -208,6 +240,30 @@ module cs_registers
|
|||
csr[`CSR_IDX_MEPC] <= curr_pc_id_i;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// _____ _ ____ //
|
||||
// |_ _(_)_ __ ___ / ___|_ __ ___ _ __ //
|
||||
// | | | | '_ ` _ \ | | | '_ ` _ \| '_ \ //
|
||||
// | | | | | | | | || |___| | | | | | |_) | //
|
||||
// |_| |_|_| |_| |_(_)____|_| |_| |_| .__/ //
|
||||
// |_| //
|
||||
// //
|
||||
////////////////////////////////////////////////
|
||||
|
||||
// ommitting timer interrupt status register according to spec 1.7 priv instr.
|
||||
// 32bit comparator
|
||||
always_comb
|
||||
begin
|
||||
if (csr[`CSR_IDX_MTIMECMP] != 32'b0 && csr[`CSR_IDX_MTIMECMP] == csr[`CSR_IDX_MTIME])
|
||||
begin
|
||||
timer_cmp_irq_o = 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
timer_cmp_irq_o = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -67,10 +67,11 @@ module exc_controller
|
|||
);
|
||||
|
||||
// Exception unit state encoding
|
||||
enum logic [1:0] { ExcNone, ExcIR, ExcIllegalInsn } exc_reason;
|
||||
enum logic [1:0] { ExcNone, ExcIR, ExcIRDeferred, ExcIllegalInsn } exc_reason, exc_reason_q, exc_reason_n;
|
||||
|
||||
// Registers
|
||||
logic exc_running_p, exc_running_n;
|
||||
logic new_instr_id_q;
|
||||
|
||||
// disable hardware loops when nops are inserted or the controller is not active
|
||||
assign hwloop_enable_o = (~core_busy_i);
|
||||
|
@ -138,6 +139,9 @@ module exc_controller
|
|||
else
|
||||
exc_reason = ExcIllegalInsn;
|
||||
end
|
||||
|
||||
if (exc_reason_q != ExcNone)
|
||||
exc_reason = exc_reason_q;
|
||||
end
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -149,23 +153,29 @@ module exc_controller
|
|||
// |_| //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// exception control FSM
|
||||
|
||||
always_comb begin
|
||||
exc_running_n = exc_running_p;
|
||||
save_pc_if_o = 1'b0;
|
||||
save_pc_id_o = 1'b0;
|
||||
exc_pc_sel_o = 1'b0;
|
||||
exc_pc_mux_o = `EXC_PC_NO_INCR;
|
||||
exc_reason_n = ExcNone;
|
||||
|
||||
unique case (exc_reason)
|
||||
// an IRQ is present, execute pending jump and then go
|
||||
// to the ISR without flushing the pipeline
|
||||
ExcIR: begin
|
||||
if (jump_in_id_i == 2'b00 && jump_in_ex_i == 2'b00)
|
||||
begin // no jump in ID
|
||||
ExcIR: begin
|
||||
|
||||
if (((jump_in_id_i == `BRANCH_JALR || jump_in_id_i == `BRANCH_JAL) && new_instr_id_q == 1'b0)) || jump_in_ex_i == `BRANCH_COND)
|
||||
begin
|
||||
//wait one cycle
|
||||
exc_reason_n = ExcIRDeferred;
|
||||
end
|
||||
else //don't wait
|
||||
begin
|
||||
exc_pc_sel_o = 1'b1;
|
||||
|
||||
save_pc_if_o = 1'b1; // save current PC
|
||||
|
||||
if (irq_nm_i == 1'b1) // emergency IRQ has higher priority
|
||||
exc_pc_mux_o = `EXC_PC_IRQ_NM;
|
||||
|
@ -173,8 +183,18 @@ module exc_controller
|
|||
exc_pc_mux_o = `EXC_PC_IRQ;
|
||||
|
||||
exc_running_n = 1'b1;
|
||||
|
||||
// jumps in ex stage already taken
|
||||
if (jump_in_id_i != `BRANCH_NONE)
|
||||
save_pc_id_o = 1'b1;
|
||||
else
|
||||
save_pc_if_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
ExcIRDeferred : begin
|
||||
//
|
||||
end
|
||||
|
||||
// Illegal instruction encountered, we directly jump to
|
||||
// the ISR without flushing the pipeline
|
||||
|
@ -195,10 +215,14 @@ module exc_controller
|
|||
if ( rst_n == 1'b0 )
|
||||
begin
|
||||
exc_running_p <= 1'b0;
|
||||
new_instr_id_q <= 1'b0;
|
||||
exc_reason_q <= ExcNone;
|
||||
end
|
||||
else
|
||||
begin
|
||||
exc_running_p <= (clear_isr_running_i == 1'b1) ? 1'b0 : exc_running_n;
|
||||
new_instr_id_q <= ~stall_id_i;
|
||||
exc_reason_q <= exc_reason_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue