mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Rework AGU mux for misaligned loads/stores
This operation only depends on the LSU detecting a misaligned address. Previously, the mux control was scattered across ID stage, controller and decoder. With this commit, all the relevant code for this operation is moved into the ID stage and also streamlined.
This commit is contained in:
parent
71a1ccc08d
commit
5171ee79f0
4 changed files with 51 additions and 70 deletions
|
@ -58,7 +58,6 @@ module ibex_controller (
|
|||
output ibex_defines::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC
|
||||
|
||||
// LSU
|
||||
input logic data_misaligned_i,
|
||||
input logic load_err_i,
|
||||
input logic store_err_i,
|
||||
|
||||
|
@ -98,9 +97,6 @@ module ibex_controller (
|
|||
output logic csr_restore_dret_id_o,
|
||||
output logic csr_save_cause_o,
|
||||
|
||||
// forwarding signals
|
||||
output ibex_defines::op_fw_sel_e operand_a_fw_mux_sel_o, // regfile ra selector for ID stage
|
||||
|
||||
// stall signals
|
||||
output logic halt_if_o,
|
||||
output logic halt_id_o,
|
||||
|
@ -526,9 +522,6 @@ module ibex_controller (
|
|||
// or in case of illegal instruction
|
||||
assign deassert_we_o = ~is_decoding_o | illegal_insn_i;
|
||||
|
||||
// Forwarding control unit
|
||||
assign operand_a_fw_mux_sel_o = data_misaligned_i ? SEL_MISALIGNED : SEL_REGFILE;
|
||||
|
||||
// update registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : update_regs
|
||||
if (!rst_ni) begin
|
||||
|
|
|
@ -30,8 +30,6 @@ module ibex_decoder #(
|
|||
// singals running to/from controller
|
||||
input logic deassert_we_i, // deassert we, we are stalled or
|
||||
// not active
|
||||
input logic data_misaligned_i, // misaligned data load/store in
|
||||
// progress
|
||||
input logic branch_mux_i,
|
||||
input logic jump_mux_i,
|
||||
output logic illegal_insn_o, // illegal instr encountered
|
||||
|
@ -108,8 +106,8 @@ module ibex_decoder #(
|
|||
jump_in_id = 1'b0;
|
||||
branch_in_id = 1'b0;
|
||||
alu_operator_o = ALU_SLTU;
|
||||
alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD;
|
||||
alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD;
|
||||
alu_op_a_mux_sel_o = OP_A_REG_A;
|
||||
alu_op_b_mux_sel_o = OP_B_REG_B;
|
||||
|
||||
imm_a_mux_sel_o = IMM_A_ZERO;
|
||||
imm_b_mux_sel_o = IMM_B_I;
|
||||
|
@ -160,7 +158,7 @@ module ibex_decoder #(
|
|||
// Calculate and store PC+4
|
||||
alu_op_a_mux_sel_o = OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = OP_B_IMM;
|
||||
imm_b_mux_sel_o = IMM_B_PCINCR;
|
||||
imm_b_mux_sel_o = IMM_B_INCR_PC;
|
||||
alu_operator_o = ALU_ADD;
|
||||
regfile_we = 1'b1;
|
||||
end
|
||||
|
@ -170,7 +168,7 @@ module ibex_decoder #(
|
|||
jump_in_id = 1'b1;
|
||||
if (jump_mux_i) begin
|
||||
// Calculate jump target
|
||||
alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD;
|
||||
alu_op_a_mux_sel_o = OP_A_REG_A;
|
||||
alu_op_b_mux_sel_o = OP_B_IMM;
|
||||
imm_b_mux_sel_o = IMM_B_I;
|
||||
alu_operator_o = ALU_ADD;
|
||||
|
@ -179,7 +177,7 @@ module ibex_decoder #(
|
|||
// Calculate and store PC+4
|
||||
alu_op_a_mux_sel_o = OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = OP_B_IMM;
|
||||
imm_b_mux_sel_o = IMM_B_PCINCR;
|
||||
imm_b_mux_sel_o = IMM_B_INCR_PC;
|
||||
alu_operator_o = ALU_ADD;
|
||||
regfile_we = 1'b1;
|
||||
end
|
||||
|
@ -270,7 +268,7 @@ module ibex_decoder #(
|
|||
// reg-reg load (different encoding)
|
||||
if (instr_rdata_i[14:12] == 3'b111) begin
|
||||
// offset from RS2
|
||||
alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD;
|
||||
alu_op_b_mux_sel_o = OP_B_REG_B;
|
||||
|
||||
// sign/zero extension
|
||||
data_sign_extension_o = ~instr_rdata_i[30];
|
||||
|
@ -491,7 +489,7 @@ module ibex_decoder #(
|
|||
// rs1 field is used as immediate
|
||||
alu_op_a_mux_sel_o = OP_A_IMM;
|
||||
end else begin
|
||||
alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD;
|
||||
alu_op_a_mux_sel_o = OP_A_REG_A;
|
||||
end
|
||||
|
||||
unique case (instr_rdata_i[13:12])
|
||||
|
@ -525,21 +523,6 @@ module ibex_decoder #(
|
|||
if (illegal_c_insn_i) begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
// misaligned access was detected by the LSU
|
||||
// TODO: this section should eventually be moved out of the decoder
|
||||
if (data_misaligned_i) begin
|
||||
// only part of the pipeline is unstalled, make sure that the
|
||||
// correct operands are sent to the AGU
|
||||
alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD;
|
||||
alu_op_b_mux_sel_o = OP_B_IMM;
|
||||
imm_b_mux_sel_o = IMM_B_PCINCR;
|
||||
|
||||
// if prepost increments are used, we do not write back the
|
||||
// second address since the first calculated address was
|
||||
// the correct one
|
||||
regfile_we = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// deassert we signals (in case of stalls)
|
||||
|
|
|
@ -122,15 +122,10 @@ typedef enum logic[3:0] {
|
|||
// ID stage //
|
||||
//////////////
|
||||
|
||||
// Forwarding operand mux selection
|
||||
typedef enum logic {
|
||||
SEL_REGFILE,
|
||||
SEL_MISALIGNED
|
||||
} op_fw_sel_e;
|
||||
|
||||
// Operand a selection
|
||||
typedef enum logic[1:0] {
|
||||
OP_A_REGA_OR_FWD,
|
||||
OP_A_REG_A,
|
||||
OP_A_FWD,
|
||||
OP_A_CURRPC,
|
||||
OP_A_IMM
|
||||
} op_a_sel_e;
|
||||
|
@ -143,7 +138,7 @@ typedef enum logic {
|
|||
|
||||
// Operand b selection
|
||||
typedef enum logic {
|
||||
OP_B_REGB_OR_FWD,
|
||||
OP_B_REG_B,
|
||||
OP_B_IMM
|
||||
} op_b_sel_e;
|
||||
|
||||
|
@ -154,7 +149,8 @@ typedef enum logic [2:0] {
|
|||
IMM_B_B,
|
||||
IMM_B_U,
|
||||
IMM_B_J,
|
||||
IMM_B_PCINCR
|
||||
IMM_B_INCR_PC,
|
||||
IMM_B_INCR_ADDR
|
||||
} imm_b_sel_e;
|
||||
|
||||
|
||||
|
|
|
@ -207,18 +207,18 @@ module ibex_id_stage #(
|
|||
logic [4:0] regfile_addr_rb_id;
|
||||
|
||||
logic [4:0] regfile_alu_waddr_id;
|
||||
logic regfile_we_id;
|
||||
logic regfile_we_id, regfile_we_dec;
|
||||
|
||||
logic [31:0] regfile_data_ra_id;
|
||||
logic [31:0] regfile_data_rb_id;
|
||||
|
||||
// ALU Control
|
||||
alu_op_e alu_operator;
|
||||
op_a_sel_e alu_op_a_mux_sel;
|
||||
op_b_sel_e alu_op_b_mux_sel;
|
||||
op_a_sel_e alu_op_a_mux_sel, alu_op_a_mux_sel_dec;
|
||||
op_b_sel_e alu_op_b_mux_sel, alu_op_b_mux_sel_dec;
|
||||
|
||||
imm_a_sel_e imm_a_mux_sel;
|
||||
imm_b_sel_e imm_b_mux_sel;
|
||||
imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec;
|
||||
|
||||
// Multiplier Control
|
||||
logic mult_int_en; // use integer multiplier
|
||||
|
@ -239,11 +239,9 @@ module ibex_id_stage #(
|
|||
csr_op_e csr_op;
|
||||
logic csr_status;
|
||||
|
||||
// Forwarding
|
||||
op_fw_sel_e operand_a_fw_mux_sel;
|
||||
|
||||
logic [31:0] operand_a_fw_id;
|
||||
logic [31:0] operand_b_fw_id;
|
||||
// For tracer
|
||||
logic [31:0] operand_a_fw_id, unused_operand_a_fw_id;
|
||||
logic [31:0] operand_b_fw_id, unused_operand_b_fw_id;
|
||||
|
||||
logic [31:0] alu_operand_a;
|
||||
logic [31:0] alu_operand_b;
|
||||
|
@ -282,6 +280,18 @@ module ibex_id_stage #(
|
|||
// signal to 0 for instructions that are done
|
||||
assign clear_instr_valid_o = id_ready_o | halt_id;
|
||||
|
||||
/////////////
|
||||
// LSU Mux //
|
||||
/////////////
|
||||
|
||||
// Misaligned loads/stores result in two aligned loads/stores, compute second address
|
||||
assign alu_op_a_mux_sel = data_misaligned_i ? OP_A_FWD : alu_op_a_mux_sel_dec;
|
||||
assign alu_op_b_mux_sel = data_misaligned_i ? OP_B_IMM : alu_op_b_mux_sel_dec;
|
||||
assign imm_b_mux_sel = data_misaligned_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;
|
||||
|
||||
// do not write back the second address since the first calculated address was the correct one
|
||||
assign regfile_we_id = data_misaligned_i ? 1'b0 : regfile_we_dec;
|
||||
|
||||
///////////////
|
||||
// Operand A //
|
||||
///////////////
|
||||
|
@ -289,7 +299,8 @@ module ibex_id_stage #(
|
|||
// ALU_Op_a Mux
|
||||
always_comb begin : alu_operand_a_mux
|
||||
unique case (alu_op_a_mux_sel)
|
||||
OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id;
|
||||
OP_A_REG_A: alu_operand_a = regfile_data_ra_id;
|
||||
OP_A_FWD: alu_operand_a = misaligned_addr_i;
|
||||
OP_A_CURRPC: alu_operand_a = pc_id_i;
|
||||
OP_A_IMM: alu_operand_a = imm_a;
|
||||
default: alu_operand_a = 'X;
|
||||
|
@ -298,10 +309,6 @@ module ibex_id_stage #(
|
|||
|
||||
assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0;
|
||||
|
||||
// Operand a forwarding mux used with LSU instructions
|
||||
assign operand_a_fw_id
|
||||
= (operand_a_fw_mux_sel == SEL_MISALIGNED) ? misaligned_addr_i : regfile_data_ra_id;
|
||||
|
||||
///////////////
|
||||
// Operand B //
|
||||
///////////////
|
||||
|
@ -309,20 +316,27 @@ module ibex_id_stage #(
|
|||
// Immediate Mux for operand B
|
||||
always_comb begin : immediate_b_mux
|
||||
unique case (imm_b_mux_sel)
|
||||
IMM_B_I: imm_b = imm_i_type;
|
||||
IMM_B_S: imm_b = imm_s_type;
|
||||
IMM_B_B: imm_b = imm_b_type;
|
||||
IMM_B_U: imm_b = imm_u_type;
|
||||
IMM_B_J: imm_b = imm_j_type;
|
||||
IMM_B_PCINCR: imm_b = (is_compressed_i && !data_misaligned_i) ? 32'h2 : 32'h4;
|
||||
default: imm_b = imm_i_type;
|
||||
IMM_B_I: imm_b = imm_i_type;
|
||||
IMM_B_S: imm_b = imm_s_type;
|
||||
IMM_B_B: imm_b = imm_b_type;
|
||||
IMM_B_U: imm_b = imm_u_type;
|
||||
IMM_B_J: imm_b = imm_j_type;
|
||||
IMM_B_INCR_PC: imm_b = is_compressed_i ? 32'h2 : 32'h4;
|
||||
IMM_B_INCR_ADDR: imm_b = 32'h4;
|
||||
default: imm_b = imm_i_type;
|
||||
endcase
|
||||
end
|
||||
|
||||
// ALU_Op_b Mux
|
||||
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_data_rb_id;
|
||||
|
||||
// Signals used by tracer
|
||||
assign operand_a_fw_id = data_misaligned_i ? misaligned_addr_i : regfile_data_ra_id;
|
||||
assign operand_b_fw_id = regfile_data_rb_id;
|
||||
|
||||
assign unused_operand_a_fw_id = operand_a_fw_id;
|
||||
assign unused_operand_b_fw_id = operand_b_fw_id;
|
||||
|
||||
///////////////
|
||||
// Registers //
|
||||
///////////////
|
||||
|
@ -382,7 +396,6 @@ module ibex_id_stage #(
|
|||
ibex_decoder #( .RV32M ( RV32M ) ) decoder_i (
|
||||
// controller related signals
|
||||
.deassert_we_i ( deassert_we ),
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
.branch_mux_i ( branch_mux_dec ),
|
||||
.jump_mux_i ( jump_mux_dec ),
|
||||
|
||||
|
@ -399,18 +412,18 @@ module ibex_id_stage #(
|
|||
|
||||
// ALU signals
|
||||
.alu_operator_o ( alu_operator ),
|
||||
.alu_op_a_mux_sel_o ( alu_op_a_mux_sel ),
|
||||
.alu_op_b_mux_sel_o ( alu_op_b_mux_sel ),
|
||||
.alu_op_a_mux_sel_o ( alu_op_a_mux_sel_dec ),
|
||||
.alu_op_b_mux_sel_o ( alu_op_b_mux_sel_dec ),
|
||||
|
||||
.imm_a_mux_sel_o ( imm_a_mux_sel ),
|
||||
.imm_b_mux_sel_o ( imm_b_mux_sel ),
|
||||
.imm_b_mux_sel_o ( imm_b_mux_sel_dec ),
|
||||
|
||||
.mult_int_en_o ( mult_int_en ),
|
||||
.div_int_en_o ( div_int_en ),
|
||||
.multdiv_operator_o ( multdiv_operator ),
|
||||
.multdiv_signed_mode_o ( multdiv_signed_mode ),
|
||||
// Register file control signals
|
||||
.regfile_we_o ( regfile_we_id ),
|
||||
.regfile_we_o ( regfile_we_dec ),
|
||||
|
||||
// CSR control signals
|
||||
.csr_access_o ( csr_access ),
|
||||
|
@ -481,7 +494,6 @@ module ibex_id_stage #(
|
|||
.exc_cause_o ( exc_cause_o ),
|
||||
|
||||
// LSU
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
.load_err_i ( lsu_load_err_i ),
|
||||
.store_err_i ( lsu_store_err_i ),
|
||||
|
||||
|
@ -519,9 +531,6 @@ module ibex_id_stage #(
|
|||
.debug_single_step_i ( debug_single_step_i ),
|
||||
.debug_ebreakm_i ( debug_ebreakm_i ),
|
||||
|
||||
// Forwarding signals
|
||||
.operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ),
|
||||
|
||||
// Stall signals
|
||||
.halt_if_o ( halt_if_o ),
|
||||
.halt_id_o ( halt_id ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue