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:
Pirmin Vogel 2019-06-27 10:10:26 +01:00
parent 71a1ccc08d
commit 5171ee79f0
4 changed files with 51 additions and 70 deletions

View file

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

View file

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

View file

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

View file

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