mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Move stall and IF-ID control from ID stage into controller
This commit is contained in:
parent
3eb147dbc2
commit
a6c2846346
4 changed files with 73 additions and 62 deletions
|
@ -44,16 +44,19 @@ module ibex_controller (
|
|||
input logic ebrk_insn_i, // decoder has EBREAK instr
|
||||
input logic csr_status_i, // decoder has CSR status instr
|
||||
|
||||
// from IF/ID pipeline
|
||||
// from IF-ID pipeline stage
|
||||
input logic instr_valid_i, // instr from IF-ID reg is valid
|
||||
input logic [31:0] instr_i, // instr from IF-ID reg, for mtval
|
||||
input logic [15:0] instr_compressed_i, // instr from IF-ID reg, for mtval
|
||||
input logic instr_is_compressed_i, // instr from IF-ID reg is compressed
|
||||
|
||||
// from prefetcher
|
||||
output logic instr_req_o, // start fetching instructions
|
||||
// to IF-ID pipeline stage
|
||||
output logic instr_valid_clear_o, // kill instr in IF-ID reg
|
||||
output logic id_ready_o, // ID stage is ready for new instr
|
||||
output logic halt_if_o, // request halt of IF stage
|
||||
|
||||
// to prefetcher
|
||||
output logic instr_req_o, // start fetching instructions
|
||||
output logic pc_set_o, // jump to address set by pc_mux
|
||||
output ibex_defines::pc_sel_e pc_mux_o, // IF stage fetch address selector
|
||||
// (boot, normal, exception...)
|
||||
|
@ -69,8 +72,6 @@ module ibex_controller (
|
|||
input logic branch_set_i, // branch taken set signal
|
||||
input logic jump_set_i, // jump taken set signal
|
||||
|
||||
input logic instr_multicyle_i, // multicycle instructions active
|
||||
|
||||
// External Interrupt Req Signals, used to wake up from wfi even if the interrupt is not taken
|
||||
input logic irq_i,
|
||||
// Interrupt Controller Signals
|
||||
|
@ -101,16 +102,19 @@ module ibex_controller (
|
|||
output logic [31:0] csr_mtval_o,
|
||||
|
||||
// stall signals
|
||||
output logic halt_if_o,
|
||||
output logic halt_id_o,
|
||||
input logic stall_lsu_i,
|
||||
input logic stall_multdiv_i,
|
||||
input logic stall_jump_i,
|
||||
input logic stall_branch_i,
|
||||
input logic instr_multicyle_i, // multicycle instructions active
|
||||
|
||||
input logic id_ready_i, // ID stage is ready
|
||||
output logic id_valid_o,
|
||||
|
||||
// Performance Counters
|
||||
output logic perf_jump_o, // we are executing a jump
|
||||
// instruction (j, jr, jal, jalr)
|
||||
output logic perf_tbranch_o // we are executing a taken branch
|
||||
// instruction
|
||||
output logic perf_jump_o, // we are executing a jump
|
||||
// instruction (j, jr, jal, jalr)
|
||||
output logic perf_tbranch_o // we are executing a taken branch
|
||||
// instruction
|
||||
);
|
||||
import ibex_defines::*;
|
||||
|
||||
|
@ -128,6 +132,8 @@ module ibex_controller (
|
|||
logic load_err_q, load_err_n;
|
||||
logic store_err_q, store_err_n;
|
||||
|
||||
logic halt_id;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
// synopsys translate_off
|
||||
// make sure we are called later so that we do not generate messages for
|
||||
|
@ -174,7 +180,7 @@ module ibex_controller (
|
|||
first_fetch_o = 1'b0;
|
||||
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
halt_id = 1'b0;
|
||||
irq_ack_o = 1'b0;
|
||||
irq_id_o = irq_id_ctrl_i;
|
||||
irq_enable_int = m_IE_i;
|
||||
|
@ -213,7 +219,7 @@ module ibex_controller (
|
|||
ctrl_busy_o = 1'b0;
|
||||
instr_req_o = 1'b0;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
ctrl_fsm_ns = SLEEP;
|
||||
end
|
||||
|
||||
|
@ -224,7 +230,7 @@ module ibex_controller (
|
|||
ctrl_busy_o = 1'b0;
|
||||
instr_req_o = 1'b0;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
|
||||
// normal execution flow
|
||||
// in debug mode or single step mode we leave immediately (wfi=nop)
|
||||
|
@ -236,7 +242,7 @@ module ibex_controller (
|
|||
FIRST_FETCH: begin
|
||||
first_fetch_o = 1'b1;
|
||||
// Stall because of IF miss
|
||||
if (id_ready_i) begin
|
||||
if (id_ready_o) begin
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
|
||||
|
@ -246,14 +252,14 @@ module ibex_controller (
|
|||
// going to sleep.
|
||||
ctrl_fsm_ns = IRQ_TAKEN;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
end
|
||||
|
||||
// enter debug mode
|
||||
if (debug_req_i && !debug_mode_q) begin
|
||||
ctrl_fsm_ns = DBG_TAKEN_IF;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -272,14 +278,14 @@ module ibex_controller (
|
|||
// Enter debug mode from external request
|
||||
ctrl_fsm_ns = DBG_TAKEN_ID;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
end
|
||||
|
||||
irq_req_ctrl_i && irq_enable_int && !debug_req_i && !debug_mode_q: begin
|
||||
// Serve an interrupt (not in debug mode)
|
||||
ctrl_fsm_ns = IRQ_TAKEN;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
|
@ -300,7 +306,7 @@ module ibex_controller (
|
|||
store_err_i || load_err_i) begin
|
||||
ctrl_fsm_ns = FLUSH;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
load_err_n = load_err_i;
|
||||
store_err_n = store_err_i;
|
||||
end
|
||||
|
@ -399,7 +405,7 @@ module ibex_controller (
|
|||
FLUSH: begin
|
||||
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
|
||||
if (!pipe_flush_i) begin
|
||||
ctrl_fsm_ns = DECODE;
|
||||
|
@ -519,6 +525,15 @@ module ibex_controller (
|
|||
// instruction
|
||||
assign deassert_we_o = ~is_decoding_o | illegal_insn_i;
|
||||
|
||||
// signal to IF stage that ID stage is ready for next instruction
|
||||
assign id_ready_o = ~stall_lsu_i & ~stall_multdiv_i & ~stall_jump_i & ~stall_branch_i;
|
||||
|
||||
// kill instruction in IF-ID reg for instructions that are done
|
||||
assign instr_valid_clear_o = id_ready_o | halt_id;
|
||||
|
||||
// signal that ID stage has valid output
|
||||
assign id_valid_o = id_ready_o & ~halt_id;
|
||||
|
||||
// update registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : update_regs
|
||||
if (!rst_ni) begin
|
||||
|
|
|
@ -117,7 +117,7 @@ module ibex_core #(
|
|||
logic [31:0] pc_if; // Program counter in IF stage
|
||||
logic [31:0] pc_id; // Program counter in ID stage
|
||||
|
||||
logic clear_instr_valid;
|
||||
logic instr_valid_clear;
|
||||
logic pc_set;
|
||||
pc_sel_e pc_mux_id; // Mux selector for next PC
|
||||
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
|
||||
|
@ -321,7 +321,7 @@ module ibex_core #(
|
|||
.pc_id_o ( pc_id ),
|
||||
|
||||
// control signals
|
||||
.clear_instr_valid_i ( clear_instr_valid ),
|
||||
.instr_valid_clear_i ( instr_valid_clear ),
|
||||
.pc_set_i ( pc_set ),
|
||||
.pc_mux_i ( pc_mux_id ),
|
||||
.exc_pc_mux_i ( exc_pc_mux_id ),
|
||||
|
@ -376,7 +376,7 @@ module ibex_core #(
|
|||
.branch_decision_i ( branch_decision ),
|
||||
|
||||
// IF and ID control signals
|
||||
.clear_instr_valid_o ( clear_instr_valid ),
|
||||
.instr_valid_clear_o ( instr_valid_clear ),
|
||||
.pc_set_o ( pc_set ),
|
||||
.pc_mux_o ( pc_mux_id ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_id ),
|
||||
|
|
|
@ -57,12 +57,14 @@ module ibex_id_stage #(
|
|||
input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers
|
||||
input logic instr_is_compressed_i,
|
||||
output logic instr_req_o,
|
||||
output logic instr_valid_clear_o, // kill instr in IF-ID reg
|
||||
output logic id_ready_o, // ID stage is ready for next instr
|
||||
output logic halt_if_o, // ID stage requests IF stage to halt
|
||||
|
||||
// Jumps and branches
|
||||
input logic branch_decision_i,
|
||||
|
||||
// IF and ID stage signals
|
||||
output logic clear_instr_valid_o,
|
||||
output logic pc_set_o,
|
||||
output ibex_defines::pc_sel_e pc_mux_o,
|
||||
output ibex_defines::exc_pc_sel_e exc_pc_mux_o,
|
||||
|
@ -72,8 +74,6 @@ module ibex_id_stage #(
|
|||
input logic [31:0] pc_id_i,
|
||||
|
||||
// Stalls
|
||||
output logic halt_if_o, // controller requests a halt of the IF stage
|
||||
output logic id_ready_o, // ID stage is ready for the next instruction
|
||||
input logic ex_ready_i,
|
||||
output logic id_valid_o, // ID stage is done
|
||||
|
||||
|
@ -174,13 +174,11 @@ module ibex_id_stage #(
|
|||
logic jump_in_id, jump_in_dec;
|
||||
|
||||
logic instr_multicyle;
|
||||
logic load_stall;
|
||||
logic multdiv_stall;
|
||||
logic branch_stall;
|
||||
logic jump_stall;
|
||||
logic stall_lsu;
|
||||
logic stall_multdiv;
|
||||
logic stall_branch;
|
||||
logic stall_jump;
|
||||
|
||||
logic halt_id;
|
||||
//FSM signals to write back multi cycles instructions
|
||||
logic regfile_we;
|
||||
|
||||
typedef enum logic {RF_LSU, RF_EX} select_e;
|
||||
|
@ -276,10 +274,6 @@ module ibex_id_stage #(
|
|||
//else
|
||||
assign illegal_reg_rv32e = 1'b0;
|
||||
|
||||
// kill instruction in the IF/ID stage by setting the instr_valid_id control
|
||||
// signal to 0 for instructions that are done
|
||||
assign clear_instr_valid_o = id_ready_o | halt_id;
|
||||
|
||||
/////////////
|
||||
// LSU Mux //
|
||||
/////////////
|
||||
|
@ -479,12 +473,17 @@ module ibex_id_stage #(
|
|||
.ebrk_insn_i ( ebrk_insn ),
|
||||
.csr_status_i ( csr_status ),
|
||||
|
||||
// from IF/ID pipeline
|
||||
// from IF-ID pipeline
|
||||
.instr_valid_i ( instr_valid_i ),
|
||||
.instr_i ( instr ),
|
||||
.instr_compressed_i ( instr_rdata_c_i ),
|
||||
.instr_is_compressed_i ( instr_is_compressed_i ),
|
||||
|
||||
// to IF-ID pipeline
|
||||
.instr_valid_clear_o ( instr_valid_clear_o ),
|
||||
.id_ready_o ( id_ready_o ),
|
||||
.halt_if_o ( halt_if_o ),
|
||||
|
||||
// from prefetcher
|
||||
.instr_req_o ( instr_req_o ),
|
||||
|
||||
|
@ -533,11 +532,13 @@ module ibex_id_stage #(
|
|||
.debug_single_step_i ( debug_single_step_i ),
|
||||
.debug_ebreakm_i ( debug_ebreakm_i ),
|
||||
|
||||
// Stall signals
|
||||
.halt_if_o ( halt_if_o ),
|
||||
.halt_id_o ( halt_id ),
|
||||
// stall signals
|
||||
.stall_lsu_i ( stall_lsu ),
|
||||
.stall_multdiv_i ( stall_multdiv ),
|
||||
.stall_jump_i ( stall_jump ),
|
||||
.stall_branch_i ( stall_branch ),
|
||||
|
||||
.id_ready_i ( id_ready_o ),
|
||||
.id_valid_o ( id_valid_o ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump_o ),
|
||||
|
@ -626,10 +627,10 @@ module ibex_id_stage #(
|
|||
always_comb begin : id_wb_fsm
|
||||
id_wb_fsm_ns = id_wb_fsm_cs;
|
||||
regfile_we = regfile_we_id;
|
||||
load_stall = 1'b0;
|
||||
multdiv_stall = 1'b0;
|
||||
jump_stall = 1'b0;
|
||||
branch_stall = 1'b0;
|
||||
stall_lsu = 1'b0;
|
||||
stall_multdiv = 1'b0;
|
||||
stall_jump = 1'b0;
|
||||
stall_branch = 1'b0;
|
||||
select_data_rf = RF_EX;
|
||||
instr_multicyle = 1'b0;
|
||||
branch_set_n = 1'b0;
|
||||
|
@ -648,13 +649,13 @@ module ibex_id_stage #(
|
|||
//LSU operation
|
||||
regfile_we = 1'b0;
|
||||
id_wb_fsm_ns = WAIT_MULTICYCLE;
|
||||
load_stall = 1'b1;
|
||||
stall_lsu = 1'b1;
|
||||
instr_multicyle = 1'b1;
|
||||
end
|
||||
branch_in_id: begin
|
||||
//Cond Branch operation
|
||||
id_wb_fsm_ns = branch_decision_i ? WAIT_MULTICYCLE : IDLE;
|
||||
branch_stall = branch_decision_i;
|
||||
stall_branch = branch_decision_i;
|
||||
instr_multicyle = branch_decision_i;
|
||||
branch_set_n = branch_decision_i;
|
||||
perf_branch_o = 1'b1;
|
||||
|
@ -663,14 +664,14 @@ module ibex_id_stage #(
|
|||
//MUL or DIV operation
|
||||
regfile_we = 1'b0;
|
||||
id_wb_fsm_ns = WAIT_MULTICYCLE;
|
||||
multdiv_stall = 1'b1;
|
||||
stall_multdiv = 1'b1;
|
||||
instr_multicyle = 1'b1;
|
||||
end
|
||||
jump_in_id: begin
|
||||
//UnCond Branch operation
|
||||
regfile_we = 1'b0;
|
||||
id_wb_fsm_ns = WAIT_MULTICYCLE;
|
||||
jump_stall = 1'b1;
|
||||
stall_jump = 1'b1;
|
||||
instr_multicyle = 1'b1;
|
||||
jump_set = 1'b1;
|
||||
end
|
||||
|
@ -682,17 +683,17 @@ module ibex_id_stage #(
|
|||
if (ex_ready_i) begin
|
||||
regfile_we = regfile_we_id;
|
||||
id_wb_fsm_ns = IDLE;
|
||||
load_stall = 1'b0;
|
||||
multdiv_stall = 1'b0;
|
||||
stall_lsu = 1'b0;
|
||||
stall_multdiv = 1'b0;
|
||||
select_data_rf = data_req_id ? RF_LSU : RF_EX;
|
||||
end else begin
|
||||
regfile_we = 1'b0;
|
||||
instr_multicyle = 1'b1;
|
||||
unique case (1'b1)
|
||||
data_req_id:
|
||||
load_stall = 1'b1;
|
||||
stall_lsu = 1'b1;
|
||||
multdiv_en_id:
|
||||
multdiv_stall = 1'b1;
|
||||
stall_multdiv = 1'b1;
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
@ -702,11 +703,6 @@ module ibex_id_stage #(
|
|||
endcase
|
||||
end
|
||||
|
||||
// stall control
|
||||
assign id_ready_o = ~load_stall & ~branch_stall & ~jump_stall & ~multdiv_stall;
|
||||
|
||||
assign id_valid_o = ~halt_id & id_ready_o;
|
||||
|
||||
////////////////
|
||||
// Assertions //
|
||||
////////////////
|
||||
|
|
|
@ -61,7 +61,7 @@ module ibex_if_stage #(
|
|||
output logic [31:0] pc_id_o,
|
||||
|
||||
// Forwarding ports - control signals
|
||||
input logic clear_instr_valid_i, // clear instr valid bit in IF-ID
|
||||
input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
|
||||
input logic pc_set_i, // set the PC to a new value
|
||||
input logic [31:0] csr_mepc_i, // PC to restore after handling
|
||||
// the interrupt/exception
|
||||
|
@ -246,7 +246,7 @@ module ibex_if_stage #(
|
|||
instr_is_compressed_id_o <= instr_is_compressed_int;
|
||||
illegal_c_insn_id_o <= illegal_c_insn;
|
||||
pc_id_o <= pc_if_o;
|
||||
end else if (clear_instr_valid_i) begin
|
||||
end else if (instr_valid_clear_i) begin
|
||||
instr_valid_id_o <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue