mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Decentralize stall control
Stall control for IF/ID pipeline is not yet ideal though, we could still gain one or two cycles there
This commit is contained in:
parent
e98e47b9e5
commit
49f7249b0a
8 changed files with 265 additions and 224 deletions
159
controller.sv
159
controller.sv
|
@ -44,7 +44,6 @@ module controller
|
|||
// decoder related signals
|
||||
output logic deassert_we_o, // deassert write enable for next instruction
|
||||
input logic illegal_insn_i, // decoder encountered an invalid instruction
|
||||
input logic trap_insn_i, // decoder encountered a trap instruction
|
||||
input logic eret_insn_i, // decoder encountered an eret instruction
|
||||
input logic pipe_flush_i, // decoder wants to do a pipe flush
|
||||
|
||||
|
@ -67,9 +66,6 @@ module controller
|
|||
input logic data_req_ex_i, // data memory access is currently performed in EX stage
|
||||
input logic data_misaligned_i,
|
||||
|
||||
input logic lsu_ready_ex_i,
|
||||
input logic lsu_ready_wb_i,
|
||||
|
||||
// hwloop signals
|
||||
input logic hwloop_jump_i, // modify pc_mux_sel to select the hwloop addr
|
||||
|
||||
|
@ -108,10 +104,17 @@ module controller
|
|||
output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage
|
||||
|
||||
// stall signals
|
||||
output logic stall_if_o, // Stall IF stage (deassert requests)
|
||||
output logic stall_id_o, // Stall ID stage (and instr and data memory interface) ( ID_STAGE )
|
||||
output logic stall_ex_o, // Stall ex stage ( EX_STAGE )
|
||||
output logic stall_wb_o, // Stall write to register file due contentions ( WB_STAGE )
|
||||
output logic halt_if_o,
|
||||
output logic halt_id_o,
|
||||
|
||||
output logic misaligned_stall_o,
|
||||
output logic jr_stall_o,
|
||||
output logic load_stall_o,
|
||||
|
||||
input logic if_valid_i, // IF stage is done
|
||||
input logic id_valid_i, // ID stage is done
|
||||
input logic ex_valid_i, // EX stage is done
|
||||
input logic wb_valid_i, // WB stage is done
|
||||
|
||||
// Performance Counters
|
||||
output logic perf_jump_o, // we are executing a jump instruction (j, jr, jal, jalr)
|
||||
|
@ -137,16 +140,6 @@ module controller
|
|||
logic reg_d_alu_is_reg_c_id;
|
||||
|
||||
|
||||
logic misalign_stall;
|
||||
logic instr_ack_stall;
|
||||
logic load_stall;
|
||||
logic jr_stall;
|
||||
logic trap_stall;
|
||||
|
||||
logic halt_if;
|
||||
logic halt_id;
|
||||
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
// synopsys translate_off
|
||||
// make sure we are called later so that we do not generate messages for
|
||||
|
@ -185,8 +178,8 @@ module controller
|
|||
core_busy_o = 1'b1;
|
||||
is_decoding_o = 1'b0;
|
||||
|
||||
halt_if = 1'b0;
|
||||
halt_id = 1'b0;
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_trap_o = 1'b0;
|
||||
illegal_insn_o = 1'b0;
|
||||
clear_isr_running_o = 1'b0;
|
||||
|
@ -249,7 +242,7 @@ module controller
|
|||
// handle conditional branches
|
||||
if (jump_in_dec_i == `BRANCH_COND) begin
|
||||
// handle branch if decision is available in next cycle
|
||||
if (~stall_id_o)
|
||||
if (id_valid_i)
|
||||
ctrl_fsm_ns = BRANCH;
|
||||
end
|
||||
|
||||
|
@ -293,8 +286,8 @@ module controller
|
|||
// sleep
|
||||
if (pipe_flush_i || exc_pipe_flush_i)
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = FLUSH_EX;
|
||||
end
|
||||
|
@ -304,13 +297,14 @@ module controller
|
|||
if(trap_hit_i && jump_in_dec_i != `BRANCH_COND)
|
||||
begin
|
||||
// halt pipeline immediately
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
// TODO: take a second look at this
|
||||
// make sure the current instruction has been executed
|
||||
// before changing state to non-decode
|
||||
if (~stall_ex_o)
|
||||
ctrl_fsm_ns = DBG_FLUSH_EX;
|
||||
//if (~stall_ex_o)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -326,12 +320,12 @@ module controller
|
|||
// be executed (NPC)
|
||||
if (trap_hit_i)
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DBG_FLUSH_EX;
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end else begin
|
||||
if (~stall_id_o)
|
||||
if (if_valid_i)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end else begin
|
||||
|
@ -343,41 +337,41 @@ module controller
|
|||
// be executed (NPC)
|
||||
if (trap_hit_i)
|
||||
begin
|
||||
ctrl_fsm_ns = DBG_FLUSH_EX;
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end else begin
|
||||
if (~stall_id_o)
|
||||
if (if_valid_i)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// make sure EX stage is flushed
|
||||
DBG_FLUSH_EX:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
// // make sure EX stage is flushed
|
||||
// DBG_FLUSH_EX:
|
||||
// begin
|
||||
// halt_if_o = 1'b1;
|
||||
// halt_id_o = 1'b1;
|
||||
|
||||
if(stall_ex_o == 1'b0)
|
||||
ctrl_fsm_ns = DBG_FLUSH_WB;
|
||||
end
|
||||
// if(stall_ex_o == 1'b0)
|
||||
// ctrl_fsm_ns = DBG_FLUSH_WB;
|
||||
// end
|
||||
|
||||
// make sure WB stage is flushed
|
||||
DBG_FLUSH_WB:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
// // make sure WB stage is flushed
|
||||
// DBG_FLUSH_WB:
|
||||
// begin
|
||||
// halt_if_o = 1'b1;
|
||||
// halt_id_o = 1'b1;
|
||||
|
||||
if(stall_ex_o == 1'b0)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
// if(stall_ex_o == 1'b0)
|
||||
// ctrl_fsm_ns = DBG_SIGNAL;
|
||||
// end
|
||||
|
||||
// now we can signal to the debugger that our pipeline is empty and it
|
||||
// can examine our current state
|
||||
DBG_SIGNAL:
|
||||
begin
|
||||
dbg_trap_o = 1'b1;
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
@ -386,19 +380,19 @@ module controller
|
|||
// we wait until it is done and go back to DECODE
|
||||
DBG_WAIT:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if(dbg_set_npc_i == 1'b1) begin
|
||||
halt_id = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
pc_mux_sel_o = `PC_DBG_NPC;
|
||||
pc_set_o = 1'b1;
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
||||
if(dbg_stall_i == 1'b0) begin
|
||||
halt_if = 1'b0;
|
||||
halt_id = 1'b0;
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end
|
||||
|
@ -406,29 +400,29 @@ module controller
|
|||
// flush the pipeline, insert NOP into EX stage
|
||||
FLUSH_EX:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if(~stall_ex_o)
|
||||
if(ex_valid_i)
|
||||
ctrl_fsm_ns = FLUSH_WB;
|
||||
end
|
||||
|
||||
// flush the pipeline, insert NOP into EX and WB stage
|
||||
FLUSH_WB:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if (~fetch_enable_i) begin
|
||||
// we are requested to go to sleep
|
||||
if(~stall_wb_o)
|
||||
if(wb_valid_i)
|
||||
ctrl_fsm_ns = SLEEP;
|
||||
end else begin
|
||||
// unstall pipeline and continue operation
|
||||
halt_if = 1'b0;
|
||||
halt_id = 1'b0;
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
|
||||
if (~stall_id_o)
|
||||
if (id_valid_i)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end
|
||||
|
@ -450,8 +444,8 @@ module controller
|
|||
/////////////////////////////////////////////////////////////
|
||||
always_comb
|
||||
begin
|
||||
load_stall = 1'b0;
|
||||
jr_stall = 1'b0;
|
||||
load_stall_o = 1'b0;
|
||||
jr_stall_o = 1'b0;
|
||||
deassert_we_o = 1'b0;
|
||||
|
||||
// deassert WE when the core is not decoding instructions
|
||||
|
@ -467,7 +461,7 @@ module controller
|
|||
((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) )
|
||||
begin
|
||||
deassert_we_o = 1'b1;
|
||||
load_stall = 1'b1;
|
||||
load_stall_o = 1'b1;
|
||||
end
|
||||
|
||||
// Stall because of jr path
|
||||
|
@ -479,32 +473,13 @@ module controller
|
|||
((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_a_id == 1'b1)) ||
|
||||
((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_a_id == 1'b1))) )
|
||||
begin
|
||||
jr_stall = 1'b1;
|
||||
jr_stall_o = 1'b1;
|
||||
deassert_we_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Stall because of IF miss
|
||||
assign instr_ack_stall = ~instr_ack_i;
|
||||
|
||||
assign misalign_stall = data_misaligned_i;
|
||||
|
||||
assign trap_stall = trap_insn_i;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Freeze Unit. This unit controls the pipeline stages //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
always_comb
|
||||
begin
|
||||
// we unstall the if_stage if the debug unit wants to set a new
|
||||
// pc, so that the new value gets written into current_pc_if and is
|
||||
// used by the instr_core_interface
|
||||
stall_if_o = instr_ack_stall | load_stall | jr_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | misalign_stall | halt_if | (jump_in_id_i == `BRANCH_COND);
|
||||
stall_id_o = instr_ack_stall | load_stall | jr_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | misalign_stall | halt_id;
|
||||
stall_ex_o = instr_ack_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | dbg_stall_i;
|
||||
stall_wb_o = (~lsu_ready_wb_i) | dbg_stall_i;
|
||||
end
|
||||
// stall because of misaligned data access
|
||||
assign misaligned_stall_o = data_misaligned_i;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -582,7 +557,7 @@ module controller
|
|||
// Performance Counters
|
||||
assign perf_jump_o = (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR);
|
||||
assign perf_branch_o = (jump_in_id_i == `BRANCH_COND);
|
||||
assign perf_jr_stall_o = jr_stall;
|
||||
assign perf_ld_stall_o = load_stall;
|
||||
assign perf_jr_stall_o = jr_stall_o;
|
||||
assign perf_ld_stall_o = load_stall_o;
|
||||
|
||||
endmodule // controller
|
||||
|
|
|
@ -54,7 +54,7 @@ module cs_registers
|
|||
output logic [31:0] epcr_o,
|
||||
|
||||
// Performance Counters
|
||||
input logic stall_id_i, // stall ID stage
|
||||
input logic id_valid_i, // ID stage is done
|
||||
input logic is_compressed_i, // compressed instruction in ID
|
||||
input logic is_decoding_i, // controller is in DECODE state
|
||||
|
||||
|
@ -82,7 +82,7 @@ module cs_registers
|
|||
`endif
|
||||
|
||||
// Performance Counter Signals
|
||||
logic stall_id_q;
|
||||
logic id_valid_q;
|
||||
logic [N_PERF_COUNTERS-1:0] PCCR_in; // input signals for each counter category
|
||||
logic [N_PERF_COUNTERS-1:0] PCCR_inc, PCCR_inc_q; // should the counter be increased?
|
||||
|
||||
|
@ -227,17 +227,16 @@ module cs_registers
|
|||
// //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
assign PCCR_in[0] = 1'b1; // cycle counter
|
||||
assign PCCR_in[1] = ~stall_id_i & is_decoding_i; // instruction counter
|
||||
assign PCCR_in[2] = ld_stall_i & (~stall_id_q); // nr of load use hazards
|
||||
assign PCCR_in[3] = jr_stall_i & (~stall_id_q); // nr of jump register hazards
|
||||
assign PCCR_in[4] = instr_fetch_i; // cycles waiting for instruction fetches
|
||||
assign PCCR_in[5] = mem_load_i; // nr of loads
|
||||
assign PCCR_in[6] = mem_store_i; // nr of stores
|
||||
assign PCCR_in[7] = jump_i & (~stall_id_q); // nr of jumps (unconditional)
|
||||
assign PCCR_in[8] = branch_i & (~stall_id_q); // nr of branches (conditional)
|
||||
assign PCCR_in[9] = ~stall_id_i & is_decoding_i
|
||||
& is_compressed_i; // compressed instruction counter
|
||||
assign PCCR_in[0] = 1'b1; // cycle counter
|
||||
assign PCCR_in[1] = id_valid_q & is_decoding_i; // instruction counter
|
||||
assign PCCR_in[2] = ld_stall_i & id_valid_q; // nr of load use hazards
|
||||
assign PCCR_in[3] = jr_stall_i & id_valid_q; // nr of jump register hazards
|
||||
assign PCCR_in[4] = instr_fetch_i; // cycles waiting for instruction fetches
|
||||
assign PCCR_in[5] = mem_load_i; // nr of loads
|
||||
assign PCCR_in[6] = mem_store_i; // nr of stores
|
||||
assign PCCR_in[7] = jump_i & id_valid_q; // nr of jumps (unconditional)
|
||||
assign PCCR_in[8] = branch_i & id_valid_q; // nr of branches (conditional)
|
||||
assign PCCR_in[9] = id_valid_q & is_decoding_i & is_compressed_i; // compressed instruction counter
|
||||
|
||||
// assign external performance counters
|
||||
generate
|
||||
|
@ -358,7 +357,7 @@ module cs_registers
|
|||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
stall_id_q <= 1'b0;
|
||||
id_valid_q <= 1'b0;
|
||||
|
||||
PCER_q <= 'h0;
|
||||
PCMR_q <= 2'h3;
|
||||
|
@ -371,7 +370,7 @@ module cs_registers
|
|||
end
|
||||
else
|
||||
begin
|
||||
stall_id_q <= stall_id_i;
|
||||
id_valid_q <= id_valid_i;
|
||||
|
||||
PCER_q <= PCER_n;
|
||||
PCMR_q <= PCMR_n;
|
||||
|
|
|
@ -97,7 +97,6 @@ module riscv_decoder
|
|||
logic regfile_mem_we;
|
||||
logic regfile_alu_we;
|
||||
logic data_req;
|
||||
logic data_we;
|
||||
logic [2:0] hwloop_we;
|
||||
|
||||
logic trap_insn;
|
||||
|
@ -155,7 +154,7 @@ module riscv_decoder
|
|||
csr_access_o = 1'b0;
|
||||
csr_op = `CSR_OP_NONE;
|
||||
|
||||
data_we = 1'b0;
|
||||
data_we_o = 1'b0;
|
||||
data_type_o = 2'b00;
|
||||
data_sign_extension_o = 1'b0;
|
||||
data_reg_offset_o = 2'b00;
|
||||
|
@ -249,7 +248,7 @@ module riscv_decoder
|
|||
`OPCODE_STORE,
|
||||
`OPCODE_STORE_POST: begin
|
||||
data_req = 1'b1;
|
||||
data_we = 1'b1;
|
||||
data_we_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
alu_operator = `ALU_ADD;
|
||||
|
@ -278,7 +277,7 @@ module riscv_decoder
|
|||
2'b10: data_type_o = 2'b00; // SW
|
||||
default: begin
|
||||
data_req = 1'b0;
|
||||
data_we = 1'b0;
|
||||
data_we_o = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
|
@ -852,7 +851,6 @@ module riscv_decoder
|
|||
assign regfile_mem_we_o = (deassert_we_i) ? 1'b0 : regfile_mem_we;
|
||||
assign regfile_alu_we_o = (deassert_we_i) ? 1'b0 : regfile_alu_we;
|
||||
assign data_req_o = (deassert_we_i) ? 1'b0 : data_req;
|
||||
assign data_we_o = (deassert_we_i) ? 1'b0 : data_we; // TODO: is this needed?
|
||||
assign alu_operator_o = (deassert_we_i) ? `ALU_NOP : alu_operator;
|
||||
assign mult_en_o = (deassert_we_i) ? 1'b0 : mult_en;
|
||||
assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we;
|
||||
|
|
20
ex_stage.sv
20
ex_stage.sv
|
@ -53,8 +53,6 @@ module ex_stage
|
|||
input logic mult_mac_en_i,
|
||||
|
||||
// input from ID stage
|
||||
input logic stall_wb_i,
|
||||
|
||||
input logic [4:0] regfile_alu_waddr_i,
|
||||
input logic regfile_alu_we_i,
|
||||
|
||||
|
@ -77,7 +75,14 @@ module ex_stage
|
|||
|
||||
// To IF: Jump and branch target and decision
|
||||
output logic [31:0] jump_target_o,
|
||||
output logic branch_decision_o
|
||||
output logic branch_decision_o,
|
||||
|
||||
// Stall Control
|
||||
input logic lsu_ready_ex_i, // EX part of LSU is done
|
||||
|
||||
output logic ex_ready_o, // EX stage ready for new data
|
||||
output logic ex_valid_o, // EX stage gets new data
|
||||
input logic wb_ready_i // WB stage ready for new data
|
||||
);
|
||||
|
||||
|
||||
|
@ -165,12 +170,19 @@ module ex_stage
|
|||
end
|
||||
else
|
||||
begin
|
||||
if (stall_wb_i == 1'b0)
|
||||
if (ex_valid_o) // wb_ready_i is implied
|
||||
begin
|
||||
regfile_we_wb_o <= regfile_we_i;
|
||||
regfile_waddr_wb_o <= regfile_waddr_i;
|
||||
end else if (wb_ready_i) begin
|
||||
// we are ready for a new instruction, but there is none available,
|
||||
// so we just flush the current one out of the pipe
|
||||
regfile_we_wb_o <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign ex_ready_o = lsu_ready_ex_i & wb_ready_i;
|
||||
assign ex_valid_o = ex_ready_o;
|
||||
|
||||
endmodule
|
||||
|
|
154
id_stage.sv
154
id_stage.sv
|
@ -65,10 +65,16 @@ module id_stage
|
|||
input logic [31:0] current_pc_id_i,
|
||||
|
||||
// Stalls
|
||||
output logic stall_if_o,
|
||||
output logic stall_id_o,
|
||||
output logic stall_ex_o,
|
||||
output logic stall_wb_o,
|
||||
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, // EX stage is ready for the next instruction
|
||||
|
||||
input logic if_ready_i, // IF stage is done
|
||||
input logic if_valid_i, // IF stage is done
|
||||
output logic id_valid_o, // ID stage is done
|
||||
input logic ex_valid_i, // EX stage is done
|
||||
input logic wb_valid_i, // WB stage is done
|
||||
|
||||
// To the Pipeline ID/EX
|
||||
output logic [31:0] regfile_rb_data_ex_o,
|
||||
|
@ -114,9 +120,6 @@ module id_stage
|
|||
output logic prepost_useincr_ex_o,
|
||||
input logic data_misaligned_i,
|
||||
|
||||
input logic lsu_ready_ex_i,
|
||||
input logic lsu_ready_wb_i,
|
||||
|
||||
// Interrupt signals
|
||||
input logic irq_i,
|
||||
input logic irq_nm_i,
|
||||
|
@ -169,6 +172,10 @@ module id_stage
|
|||
|
||||
logic [1:0] jump_in_dec;
|
||||
|
||||
logic misaligned_stall;
|
||||
logic jr_stall;
|
||||
logic load_stall;
|
||||
|
||||
|
||||
// Immediate decoding and sign extension
|
||||
logic [31:0] imm_i_type;
|
||||
|
@ -617,7 +624,6 @@ module id_stage
|
|||
// decoder related signals
|
||||
.deassert_we_o ( deassert_we ),
|
||||
.illegal_insn_i ( illegal_insn_dec ),
|
||||
.trap_insn_i ( trap_insn ),
|
||||
.eret_insn_i ( eret_insn_dec ),
|
||||
.pipe_flush_i ( pipe_flush_dec ),
|
||||
|
||||
|
@ -640,9 +646,6 @@ module id_stage
|
|||
.data_req_ex_i ( data_req_ex_o ),
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
|
||||
.lsu_ready_ex_i ( lsu_ready_ex_i ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb_i ),
|
||||
|
||||
// hwloop signals
|
||||
.hwloop_jump_i ( hwloop_jump ),
|
||||
|
||||
|
@ -684,10 +687,17 @@ module id_stage
|
|||
.operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ),
|
||||
|
||||
// Stall signals
|
||||
.stall_if_o ( stall_if_o ),
|
||||
.stall_id_o ( stall_id_o ),
|
||||
.stall_ex_o ( stall_ex_o ),
|
||||
.stall_wb_o ( stall_wb_o ),
|
||||
.halt_if_o ( halt_if_o ),
|
||||
.halt_id_o ( halt_id ),
|
||||
|
||||
.misaligned_stall_o ( misaligned_stall ),
|
||||
.jr_stall_o ( jr_stall ),
|
||||
.load_stall_o ( load_stall ),
|
||||
|
||||
.if_valid_i ( if_valid_i ),
|
||||
.id_valid_i ( id_valid_o ),
|
||||
.ex_valid_i ( ex_valid_i ),
|
||||
.wb_valid_i ( wb_valid_i ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump_o ),
|
||||
|
@ -734,7 +744,7 @@ module id_stage
|
|||
.core_busy_i ( core_busy_o ),
|
||||
.jump_in_id_i ( jump_in_id_o ),
|
||||
.jump_in_ex_i ( jump_in_ex_o ),
|
||||
.stall_id_i ( stall_id_o ),
|
||||
.stall_id_i ( ~id_valid ),
|
||||
.illegal_insn_i ( illegal_insn ),
|
||||
.trap_insn_i ( trap_insn ),
|
||||
.drop_instruction_i ( 1'b0 ),
|
||||
|
@ -792,7 +802,7 @@ module id_stage
|
|||
.hwloop_regid_i ( hwloop_regid ),
|
||||
|
||||
// from controller
|
||||
.stall_id_i ( stall_id_o ),
|
||||
.stall_id_i ( ~id_valid ),
|
||||
|
||||
// to hwloop controller
|
||||
.hwloop_start_addr_o ( hwloop_start_addr ),
|
||||
|
@ -850,67 +860,91 @@ module id_stage
|
|||
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
|
||||
jump_in_ex_o <= 2'b0;
|
||||
jump_in_ex_o <= `BRANCH_NONE;
|
||||
|
||||
end
|
||||
else if ((stall_ex_o == 1'b0) && (data_misaligned_i == 1'b1))
|
||||
begin // misaligned access case, only unstall alu operands
|
||||
else if (data_misaligned_i) begin
|
||||
// misaligned data access case
|
||||
if (ex_ready_i)
|
||||
begin // misaligned access case, only unstall alu operands
|
||||
|
||||
// if we are using post increments, then we have to use the
|
||||
// original value of the register for the second memory access
|
||||
// => keep it stalled
|
||||
if (prepost_useincr_ex_o == 1'b1)
|
||||
begin
|
||||
alu_operand_a_ex_o <= alu_operand_a;
|
||||
// if we are using post increments, then we have to use the
|
||||
// original value of the register for the second memory access
|
||||
// => keep it stalled
|
||||
if (prepost_useincr_ex_o == 1'b1)
|
||||
begin
|
||||
alu_operand_a_ex_o <= alu_operand_a;
|
||||
end
|
||||
|
||||
alu_operand_b_ex_o <= alu_operand_b;
|
||||
regfile_alu_we_ex_o <= regfile_alu_we_id;
|
||||
prepost_useincr_ex_o <= prepost_useincr;
|
||||
|
||||
data_misaligned_ex_o <= 1'b1;
|
||||
end
|
||||
|
||||
alu_operand_b_ex_o <= alu_operand_b;
|
||||
regfile_alu_we_ex_o <= regfile_alu_we_id;
|
||||
prepost_useincr_ex_o <= prepost_useincr;
|
||||
|
||||
data_misaligned_ex_o <= 1'b1;
|
||||
end
|
||||
else if ((stall_ex_o == 1'b0) && (data_misaligned_i == 1'b0))
|
||||
begin // unstall the whole pipeline
|
||||
regfile_rb_data_ex_o <= operand_b_fw_id;
|
||||
else if (~data_misaligned_i) begin
|
||||
if (id_valid_o)
|
||||
begin // unstall the whole pipeline
|
||||
regfile_rb_data_ex_o <= operand_b_fw_id;
|
||||
|
||||
alu_operator_ex_o <= alu_operator;
|
||||
alu_operand_a_ex_o <= alu_operand_a;
|
||||
alu_operand_b_ex_o <= alu_operand_b;
|
||||
alu_operand_c_ex_o <= alu_operand_c;
|
||||
alu_operator_ex_o <= alu_operator;
|
||||
alu_operand_a_ex_o <= alu_operand_a;
|
||||
alu_operand_b_ex_o <= alu_operand_b;
|
||||
alu_operand_c_ex_o <= alu_operand_c;
|
||||
|
||||
vector_mode_ex_o <= vector_mode;
|
||||
alu_cmp_mode_ex_o <= alu_cmp_mode;
|
||||
alu_vec_ext_ex_o <= alu_vec_ext;
|
||||
vector_mode_ex_o <= vector_mode;
|
||||
alu_cmp_mode_ex_o <= alu_cmp_mode;
|
||||
alu_vec_ext_ex_o <= alu_vec_ext;
|
||||
|
||||
mult_en_ex_o <= mult_en;
|
||||
mult_sel_subword_ex_o <= mult_sel_subword;
|
||||
mult_signed_mode_ex_o <= mult_signed_mode;
|
||||
mult_mac_en_ex_o <= mult_mac_en;
|
||||
mult_en_ex_o <= mult_en;
|
||||
mult_sel_subword_ex_o <= mult_sel_subword;
|
||||
mult_signed_mode_ex_o <= mult_signed_mode;
|
||||
mult_mac_en_ex_o <= mult_mac_en;
|
||||
|
||||
|
||||
regfile_waddr_ex_o <= regfile_waddr_id;
|
||||
regfile_we_ex_o <= regfile_we_id;
|
||||
regfile_waddr_ex_o <= regfile_waddr_id;
|
||||
regfile_we_ex_o <= regfile_we_id;
|
||||
|
||||
regfile_alu_waddr_ex_o <= regfile_alu_waddr_id;
|
||||
regfile_alu_we_ex_o <= regfile_alu_we_id;
|
||||
regfile_alu_waddr_ex_o <= regfile_alu_waddr_id;
|
||||
regfile_alu_we_ex_o <= regfile_alu_we_id;
|
||||
|
||||
prepost_useincr_ex_o <= prepost_useincr;
|
||||
prepost_useincr_ex_o <= prepost_useincr;
|
||||
|
||||
csr_access_ex_o <= csr_access;
|
||||
csr_op_ex_o <= csr_op;
|
||||
csr_access_ex_o <= csr_access;
|
||||
csr_op_ex_o <= csr_op;
|
||||
|
||||
data_we_ex_o <= data_we_id;
|
||||
data_type_ex_o <= data_type_id;
|
||||
data_sign_ext_ex_o <= data_sign_ext_id;
|
||||
data_reg_offset_ex_o <= data_reg_offset_id;
|
||||
data_req_ex_o <= data_req_id;
|
||||
data_we_ex_o <= data_we_id;
|
||||
data_type_ex_o <= data_type_id;
|
||||
data_sign_ext_ex_o <= data_sign_ext_id;
|
||||
data_reg_offset_ex_o <= data_reg_offset_id;
|
||||
data_req_ex_o <= data_req_id;
|
||||
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
|
||||
jump_in_ex_o <= jump_in_id_o;
|
||||
jump_in_ex_o <= jump_in_id_o;
|
||||
end else if(ex_ready_i) begin
|
||||
// EX stage is ready but we don't have a new instruction for it,
|
||||
// so we set all write enables to 0, but unstall the pipe
|
||||
|
||||
regfile_we_ex_o <= 1'b0;
|
||||
|
||||
regfile_alu_we_ex_o <= 1'b0;
|
||||
|
||||
csr_op_ex_o <= `CSR_OP_NONE;
|
||||
|
||||
data_req_ex_o <= 1'b0;
|
||||
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
|
||||
jump_in_ex_o <= `BRANCH_NONE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// stall control
|
||||
assign id_ready_o = (~misaligned_stall) & (~jr_stall) & (~load_stall) & ex_ready_i;
|
||||
assign id_valid_o = (~halt_id) & if_ready_i & id_ready_o;
|
||||
|
||||
endmodule
|
||||
|
|
23
if_stage.sv
23
if_stage.sv
|
@ -80,8 +80,10 @@ module if_stage
|
|||
input logic [31:0] dbg_npc_i,
|
||||
|
||||
// pipeline stall
|
||||
input logic stall_if_i,
|
||||
input logic stall_id_i,
|
||||
input logic halt_if_i,
|
||||
output logic if_ready_o,
|
||||
input logic id_ready_i,
|
||||
output logic if_valid_o,
|
||||
|
||||
// misc signals
|
||||
output logic if_busy_o // is the IF stage busy fetching instructions?
|
||||
|
@ -219,10 +221,10 @@ module if_stage
|
|||
end else begin
|
||||
offset_fsm_cs <= offset_fsm_ns;
|
||||
|
||||
if (stall_if_i)
|
||||
branch_req_Q <= branch_req | branch_req_Q;
|
||||
else
|
||||
if (if_valid_o)
|
||||
branch_req_Q <= 1'b0;
|
||||
else
|
||||
branch_req_Q <= branch_req | branch_req_Q;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -252,7 +254,7 @@ module if_stage
|
|||
if (fetch_valid) begin
|
||||
valid_o = 1'b1; // an instruction is ready for ID stage
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
if (req_i && if_valid_o) begin
|
||||
|
||||
if (~is_compressed[0]) begin
|
||||
// 32 bit aligned instruction found
|
||||
|
@ -277,7 +279,7 @@ module if_stage
|
|||
if (is_compressed[1]) begin
|
||||
valid_o = 1'b1; // an instruction is ready for ID stage
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
if (req_i && if_valid_o) begin
|
||||
// next instruction will be aligned
|
||||
fetch_ready = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
|
@ -288,7 +290,7 @@ module if_stage
|
|||
if (fetch_unaligned_valid) begin
|
||||
valid_o = 1'b1; // an instruction is ready for ID stage
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
if (req_i && if_valid_o) begin
|
||||
// next instruction will be unaligned
|
||||
fetch_ready = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED;
|
||||
|
@ -367,7 +369,7 @@ module if_stage
|
|||
end
|
||||
else
|
||||
begin
|
||||
if (~stall_id_i)
|
||||
if (if_valid_o)
|
||||
begin : ENABLED_PIPE
|
||||
instr_rdata_id_o <= instr_decompressed;
|
||||
illegal_c_insn_id_o <= illegal_c_insn;
|
||||
|
@ -377,4 +379,7 @@ module if_stage
|
|||
end
|
||||
end
|
||||
|
||||
assign if_ready_o = valid_o & id_ready_i;
|
||||
assign if_valid_o = (~halt_if_i) & if_ready_o & (jump_in_id_i != `BRANCH_COND);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -65,7 +65,7 @@ module load_store_unit
|
|||
output logic lsu_ready_ex_o, // LSU ready for new data in EX stage
|
||||
output logic lsu_ready_wb_o, // LSU ready for new data in WB stage
|
||||
|
||||
input logic ex_stall_i
|
||||
input logic ex_valid_i
|
||||
);
|
||||
|
||||
logic [31:0] data_addr_int;
|
||||
|
@ -317,6 +317,7 @@ module load_store_unit
|
|||
// output to register file
|
||||
assign data_rdata_ex_o = (data_rvalid_i == 1'b1) ? data_rdata_ext : rdata_q;
|
||||
|
||||
// output to data interface
|
||||
assign data_addr_o = data_addr_int;
|
||||
assign data_wdata_o = data_wdata;
|
||||
assign data_we_o = data_we_ex_i;
|
||||
|
@ -346,10 +347,10 @@ module load_store_unit
|
|||
if(data_gnt_i) begin
|
||||
lsu_ready_ex_o = 1'b1;
|
||||
|
||||
if(ex_stall_i)
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
else
|
||||
if (ex_valid_i)
|
||||
NS = WAIT_RVALID;
|
||||
else
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
end
|
||||
end
|
||||
end //~ IDLE
|
||||
|
@ -367,16 +368,18 @@ module load_store_unit
|
|||
lsu_ready_wb_o = 1'b1;
|
||||
end
|
||||
|
||||
if(data_req_ex_i) begin
|
||||
if (data_req_ex_i) begin
|
||||
lsu_ready_ex_o = 1'b0;
|
||||
|
||||
if(data_gnt_i) begin
|
||||
if (data_gnt_i) begin
|
||||
lsu_ready_ex_o = 1'b1;
|
||||
|
||||
if(ex_stall_i)
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
else
|
||||
if(ex_valid_i)
|
||||
NS = WAIT_RVALID;
|
||||
else
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
end else begin
|
||||
NS = IDLE;
|
||||
end
|
||||
end else begin
|
||||
// no request, so go to IDLE
|
||||
|
@ -392,19 +395,19 @@ module load_store_unit
|
|||
data_req_o = 1'b0;
|
||||
|
||||
if (data_rvalid_i) begin
|
||||
if (ex_stall_i) begin
|
||||
// we have to wait until ex_stall is deasserted
|
||||
NS = IDLE_EX_STALL;
|
||||
end else begin
|
||||
if (ex_valid_i) begin
|
||||
// we are done and can go back to idle
|
||||
// the data is safely stored already
|
||||
NS = IDLE;
|
||||
end else begin
|
||||
// we have to wait until ex_stall is deasserted
|
||||
NS = IDLE_EX_STALL;
|
||||
end
|
||||
end else begin
|
||||
// we didn't yet receive the rvalid, so we check the ex_stall
|
||||
// signal. If we are no longer stalled we can change to the "normal"
|
||||
// WAIT_RVALID state
|
||||
if (~ex_stall_i)
|
||||
if (ex_valid_i)
|
||||
NS = WAIT_RVALID;
|
||||
end
|
||||
end
|
||||
|
@ -412,7 +415,7 @@ module load_store_unit
|
|||
IDLE_EX_STALL:
|
||||
begin
|
||||
// wait for us to be unstalled and then change back to IDLE state
|
||||
if (~ex_stall_i) begin
|
||||
if (ex_valid_i) begin
|
||||
NS = IDLE;
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,12 +105,6 @@ module riscv_core
|
|||
logic branch_decision;
|
||||
|
||||
|
||||
// Stalling
|
||||
logic stall_if; // Stall instruction fetch(deassert request)
|
||||
logic stall_id; // Stall PC stage and instr memory and data memo
|
||||
logic stall_ex; // Stall EX Stage
|
||||
logic stall_wb; // Stall write back stage
|
||||
|
||||
logic core_busy;
|
||||
logic if_busy;
|
||||
|
||||
|
@ -167,6 +161,17 @@ module riscv_core
|
|||
logic data_req_ex;
|
||||
logic data_misaligned_ex;
|
||||
|
||||
// stall control
|
||||
logic halt_if;
|
||||
logic if_ready;
|
||||
logic id_ready;
|
||||
logic ex_ready;
|
||||
|
||||
logic if_valid;
|
||||
logic id_valid;
|
||||
logic ex_valid;
|
||||
logic wb_valid;
|
||||
|
||||
logic lsu_ready_ex;
|
||||
logic lsu_ready_wb;
|
||||
|
||||
|
@ -269,8 +274,10 @@ module riscv_core
|
|||
.jump_target_ex_i ( jump_target_ex ),
|
||||
|
||||
// pipeline stalls
|
||||
.stall_if_i ( stall_if ),
|
||||
.stall_id_i ( stall_id ),
|
||||
.halt_if_i ( halt_if ),
|
||||
.if_ready_o ( if_ready ),
|
||||
.id_ready_i ( id_ready ),
|
||||
.if_valid_o ( if_valid ),
|
||||
|
||||
.if_busy_o ( if_busy )
|
||||
);
|
||||
|
@ -316,10 +323,16 @@ module riscv_core
|
|||
.current_pc_id_i ( current_pc_id ),
|
||||
|
||||
// Stalls
|
||||
.stall_if_o ( stall_if ),
|
||||
.stall_id_o ( stall_id ),
|
||||
.stall_ex_o ( stall_ex ),
|
||||
.stall_wb_o ( stall_wb ),
|
||||
.halt_if_o ( halt_if ),
|
||||
|
||||
.if_ready_i ( if_ready ),
|
||||
.id_ready_o ( id_ready ),
|
||||
.ex_ready_i ( ex_ready ),
|
||||
|
||||
.if_valid_i ( if_valid ),
|
||||
.id_valid_o ( id_valid ),
|
||||
.ex_valid_i ( ex_valid ),
|
||||
.wb_valid_i ( wb_valid ),
|
||||
|
||||
// From the Pipeline ID/EX
|
||||
.regfile_rb_data_ex_o ( regfile_rb_data_ex ),
|
||||
|
@ -365,9 +378,6 @@ module riscv_core
|
|||
.prepost_useincr_ex_o ( useincr_addr_ex ),
|
||||
.data_misaligned_i ( data_misaligned ),
|
||||
|
||||
.lsu_ready_ex_i ( lsu_ready_ex ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb ),
|
||||
|
||||
// Interrupt Signals
|
||||
.irq_i ( irq_i ), // incoming interrupts
|
||||
.irq_nm_i ( irq_nm_i ), // incoming interrupts
|
||||
|
@ -439,9 +449,6 @@ module riscv_core
|
|||
.csr_access_i ( csr_access_ex ),
|
||||
.csr_rdata_i ( csr_rdata ),
|
||||
|
||||
// input from ID stage
|
||||
.stall_wb_i ( stall_wb ),
|
||||
|
||||
// From ID Stage: Regfile control signals
|
||||
.regfile_waddr_i ( regfile_waddr_ex ),
|
||||
.regfile_we_i ( regfile_we_ex ),
|
||||
|
@ -460,7 +467,14 @@ module riscv_core
|
|||
// To ID stage: Forwarding signals
|
||||
.regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ),
|
||||
.regfile_alu_we_fw_o ( regfile_alu_we_fw ),
|
||||
.regfile_alu_wdata_fw_o ( regfile_alu_wdata_fw )
|
||||
.regfile_alu_wdata_fw_o ( regfile_alu_wdata_fw ),
|
||||
|
||||
// stall control
|
||||
.lsu_ready_ex_i ( lsu_ready_ex ),
|
||||
|
||||
.ex_ready_o ( ex_ready ),
|
||||
.ex_valid_o ( ex_valid ),
|
||||
.wb_ready_i ( lsu_ready_wb )
|
||||
);
|
||||
|
||||
|
||||
|
@ -474,8 +488,8 @@ module riscv_core
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
load_store_unit load_store_unit_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
// signal from ex stage
|
||||
.data_we_ex_i ( data_we_ex ),
|
||||
|
@ -507,9 +521,10 @@ module riscv_core
|
|||
.lsu_ready_ex_o ( lsu_ready_ex ),
|
||||
.lsu_ready_wb_o ( lsu_ready_wb ),
|
||||
|
||||
.ex_stall_i ( stall_ex )
|
||||
.ex_valid_i ( ex_valid )
|
||||
);
|
||||
|
||||
assign wb_valid = lsu_ready_wb;
|
||||
|
||||
//////////////////////////////////////
|
||||
// ____ ____ ____ //
|
||||
|
@ -549,7 +564,7 @@ module riscv_core
|
|||
.epcr_o ( epcr ),
|
||||
|
||||
// performance counter related signals
|
||||
.stall_id_i ( stall_id ),
|
||||
.id_valid_i ( id_valid ),
|
||||
.is_compressed_i ( is_compressed_id ),
|
||||
.is_decoding_i ( is_decoding ),
|
||||
|
||||
|
@ -666,7 +681,7 @@ module riscv_core
|
|||
rs2_value = id_stage_i.operand_b_fw_id;
|
||||
|
||||
// special case for WFI because we don't wait for unstalling there
|
||||
if ((id_stage_i.stall_ex_o == 1'b0 && is_decoding) || id_stage_i.controller_i.pipe_flush_i)
|
||||
if ((id_valid && is_decoding) || id_stage_i.controller_i.pipe_flush_i)
|
||||
begin
|
||||
mnemonic = "";
|
||||
imm = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue