Move stall and IF-ID control from ID stage into controller

This commit is contained in:
Pirmin Vogel 2019-07-01 19:29:31 +01:00
parent 3eb147dbc2
commit a6c2846346
4 changed files with 73 additions and 62 deletions

View file

@ -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

View file

@ -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 ),

View file

@ -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 //
////////////////

View file

@ -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