mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-24 22:07:43 -04:00
Remove misaligned data access from LSU
This commit is contained in:
parent
c161668a15
commit
e17e8059f6
6 changed files with 142 additions and 2 deletions
|
@ -72,7 +72,10 @@ module riscv_controller
|
|||
|
||||
// LSU
|
||||
input logic data_req_ex_i, // data memory access is currently performed in EX stage
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
input logic data_misaligned_i,
|
||||
`endif // ONLY_ALIGNED
|
||||
input logic data_load_event_i,
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
|
@ -146,7 +149,10 @@ module riscv_controller
|
|||
output logic halt_if_o,
|
||||
output logic halt_id_o,
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
output logic misaligned_stall_o,
|
||||
`endif // ONLY_ALIGNED
|
||||
output logic jr_stall_o,
|
||||
output logic load_stall_o,
|
||||
|
||||
|
@ -581,8 +587,11 @@ module riscv_controller
|
|||
end
|
||||
end
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
// stall because of misaligned data access
|
||||
assign misaligned_stall_o = data_misaligned_i;
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
|
||||
// Forwarding control unit
|
||||
|
@ -624,12 +633,15 @@ module riscv_controller
|
|||
`endif // THREE_PORT_REG_FILE
|
||||
end
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
// for misaligned memory accesses
|
||||
if (data_misaligned_i)
|
||||
begin
|
||||
operand_a_fw_mux_sel_o = SEL_FW_EX;
|
||||
operand_b_fw_mux_sel_o = SEL_REGFILE;
|
||||
end
|
||||
`endif // ONLY_ALIGNED
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
else if (mult_multicycle_i) begin
|
||||
|
|
|
@ -33,7 +33,10 @@ module riscv_decoder
|
|||
(
|
||||
// singals running to/from controller
|
||||
input logic deassert_we_i, // deassert we, we are stalled or not active
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
input logic data_misaligned_i, // misaligned data load/store in progress
|
||||
`endif // ONLY_ALIGNED
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
// MUL related control signals
|
||||
|
@ -1172,6 +1175,8 @@ module riscv_decoder
|
|||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
// misaligned access was detected by the LSU
|
||||
// TODO: this section should eventually be moved out of the decoder
|
||||
if (data_misaligned_i == 1'b1)
|
||||
|
@ -1200,6 +1205,7 @@ module riscv_decoder
|
|||
scalar_replication_o = 1'b0;
|
||||
`endif // VEC_SUPPORT
|
||||
end
|
||||
`endif // ONLY_ALIGNED
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
else if (mult_multicycle_i) begin
|
||||
|
|
39
id_stage.sv
39
id_stage.sv
|
@ -184,14 +184,21 @@ module riscv_id_stage
|
|||
output logic [1:0] data_reg_offset_ex_o,
|
||||
output logic data_load_event_ex_o,
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
output logic data_misaligned_ex_o,
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// CONFIG_REGION: PREPOST_SUPPORT
|
||||
`ifdef PREPOST_SUPPORT
|
||||
output logic prepost_useincr_ex_o,
|
||||
`endif // PREPOST_SUPPORT
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
input logic data_misaligned_i,
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
|
||||
// Interrupt signals
|
||||
input logic [31:0] irq_i,
|
||||
|
@ -721,7 +728,13 @@ module riscv_id_stage
|
|||
IMMB_I: imm_b = imm_i_type;
|
||||
IMMB_S: imm_b = imm_s_type;
|
||||
IMMB_U: imm_b = imm_u_type;
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
IMMB_PCINCR: imm_b = (is_compressed_i && (~data_misaligned_i)) ? 32'h2 : 32'h4;
|
||||
`else
|
||||
IMMB_PCINCR: imm_b = (is_compressed_i) ? 32'h2 : 32'h4;
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
IMMB_S2: imm_b = imm_s2_type;
|
||||
IMMB_BI: imm_b = imm_bi_type;
|
||||
IMMB_S3: imm_b = imm_s3_type;
|
||||
|
@ -992,7 +1005,10 @@ module riscv_id_stage
|
|||
(
|
||||
// controller related signals
|
||||
.deassert_we_i ( deassert_we ),
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
`endif // ONLY_ALIGNED
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
.mult_multicycle_i ( mult_multicycle_i ),
|
||||
|
@ -1136,7 +1152,10 @@ module riscv_id_stage
|
|||
|
||||
// LSU
|
||||
.data_req_ex_i ( data_req_ex_o ),
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
`endif // ONLY_ALIGNED
|
||||
.data_load_event_i ( data_load_event_ex_o ),
|
||||
|
||||
// ALU
|
||||
|
@ -1210,7 +1229,10 @@ module riscv_id_stage
|
|||
.halt_if_o ( halt_if_o ),
|
||||
.halt_id_o ( halt_id ),
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.misaligned_stall_o ( misaligned_stall ),
|
||||
`endif // ONLY_ALIGNED
|
||||
.jr_stall_o ( jr_stall ),
|
||||
.load_stall_o ( load_stall ),
|
||||
|
||||
|
@ -1374,10 +1396,15 @@ always_ff @(posedge clk, negedge rst_n)
|
|||
data_reg_offset_ex_o <= 2'b0;
|
||||
data_req_ex_o <= 1'b0;
|
||||
data_load_event_ex_o <= 1'b0;
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
`endif // ONLY_ALIGNED
|
||||
pc_ex_o <= '0;
|
||||
branch_in_ex_o <= 1'b0;
|
||||
end
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
else if (data_misaligned_i) begin
|
||||
// misaligned data access case
|
||||
if (ex_ready_i)
|
||||
|
@ -1404,6 +1431,7 @@ always_ff @(posedge clk, negedge rst_n)
|
|||
data_misaligned_ex_o <= 1'b1;
|
||||
end
|
||||
end
|
||||
`endif // ONLY_ALIGNED
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
else if (mult_multicycle_i) begin
|
||||
|
@ -1488,7 +1516,10 @@ always_ff @(posedge clk, negedge rst_n)
|
|||
end else begin
|
||||
data_load_event_ex_o <= 1'b0;
|
||||
end
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
`endif // ONLY_ALIGNED
|
||||
if ((jump_in_id == BRANCH_COND) || data_load_event_id) begin
|
||||
pc_ex_o <= pc_id_i;
|
||||
end
|
||||
|
@ -1501,7 +1532,10 @@ always_ff @(posedge clk, negedge rst_n)
|
|||
csr_op_ex_o <= CSR_OP_NONE;
|
||||
data_req_ex_o <= 1'b0;
|
||||
data_load_event_ex_o <= 1'b0;
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
data_misaligned_ex_o <= 1'b0;
|
||||
`endif // ONLY_ALIGNED
|
||||
branch_in_ex_o <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
@ -1510,7 +1544,12 @@ always_ff @(posedge clk, negedge rst_n)
|
|||
|
||||
|
||||
// stall control
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
assign id_ready_o = ((~misaligned_stall) & (~jr_stall) & (~load_stall) & ex_ready_i);
|
||||
`else
|
||||
assign id_ready_o = ((~jr_stall) & (~load_stall) & ex_ready_i);
|
||||
`endif // ONLY_ALIGNED
|
||||
assign id_valid_o = (~halt_id) & id_ready_o;
|
||||
|
||||
|
||||
|
|
|
@ -66,8 +66,12 @@ module riscv_load_store_unit
|
|||
input logic addr_useincr_ex_i, // use a + b or just a for address -> from ex stage
|
||||
`endif // PREPOST_SUPPORT
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
input logic data_misaligned_ex_i, // misaligned access in last ld/st -> from ID/EX pipeline
|
||||
output logic data_misaligned_o, // misaligned access was detected -> to controller
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
|
||||
// exception signals
|
||||
output logic load_err_o,
|
||||
|
@ -94,8 +98,10 @@ module riscv_load_store_unit
|
|||
logic [3:0] data_be;
|
||||
logic [31:0] data_wdata;
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
logic misaligned_st; // high if we are currently performing the second part of a misaligned store
|
||||
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
enum logic [1:0] { IDLE, WAIT_RVALID, WAIT_RVALID_EX_STALL, IDLE_EX_STALL } CS, NS;
|
||||
|
||||
|
@ -107,6 +113,8 @@ module riscv_load_store_unit
|
|||
case (data_type_ex_i) // Data type 00 Word, 01 Half word, 11,10 byte
|
||||
2'b00:
|
||||
begin // Writing a word
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
if (misaligned_st == 1'b0)
|
||||
begin // non-misaligned case
|
||||
case (data_addr_int[1:0])
|
||||
|
@ -125,10 +133,15 @@ module riscv_load_store_unit
|
|||
2'b11: data_be = 4'b0111;
|
||||
endcase; // case (data_addr_int[1:0])
|
||||
end
|
||||
`else
|
||||
data_be = 4'b1111;
|
||||
`endif // ONLY_ALIGNED
|
||||
end
|
||||
|
||||
2'b01:
|
||||
begin // Writing a half word
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
if (misaligned_st == 1'b0)
|
||||
begin // non-misaligned case
|
||||
case (data_addr_int[1:0])
|
||||
|
@ -142,6 +155,12 @@ module riscv_load_store_unit
|
|||
begin // misaligned case
|
||||
data_be = 4'b0001;
|
||||
end
|
||||
`else
|
||||
case (data_addr_int[1])
|
||||
1'b0: data_be = 4'b0011;
|
||||
1'b1: data_be = 4'b1100;
|
||||
endcase; // case (data_addr_int[1])
|
||||
`endif // ONLY_ALIGNED
|
||||
end
|
||||
|
||||
2'b10,
|
||||
|
@ -209,17 +228,25 @@ module riscv_load_store_unit
|
|||
// take care of misaligned words
|
||||
always_comb
|
||||
begin
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
case (rdata_offset_q)
|
||||
2'b00: rdata_w_ext = data_rdata_i[31:0];
|
||||
2'b01: rdata_w_ext = {data_rdata_i[ 7:0], rdata_q[31:8]};
|
||||
2'b10: rdata_w_ext = {data_rdata_i[15:0], rdata_q[31:16]};
|
||||
2'b11: rdata_w_ext = {data_rdata_i[23:0], rdata_q[31:24]};
|
||||
endcase
|
||||
`else
|
||||
rdata_w_ext = data_rdata_i[31:0];
|
||||
`endif // ONLY_ALIGNED
|
||||
endcase
|
||||
end
|
||||
|
||||
// sign extension for half words
|
||||
always_comb
|
||||
begin
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
case (rdata_offset_q)
|
||||
2'b00:
|
||||
begin
|
||||
|
@ -253,6 +280,24 @@ module riscv_load_store_unit
|
|||
rdata_h_ext = {{16{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]};
|
||||
end
|
||||
endcase // case (rdata_offset_q)
|
||||
`else
|
||||
case (rdata_offset_q[1])
|
||||
1'b0:
|
||||
begin
|
||||
if (data_sign_ext_q == 1'b0)
|
||||
rdata_h_ext = {16'h0000, data_rdata_i[15:0]};
|
||||
else
|
||||
rdata_h_ext = {{16{data_rdata_i[15]}}, data_rdata_i[15:0]};
|
||||
end
|
||||
|
||||
1'b1:
|
||||
begin
|
||||
if (data_sign_ext_q == 1'b0)
|
||||
rdata_h_ext = {16'h0000, data_rdata_i[31:16]};
|
||||
else
|
||||
rdata_h_ext = {{16{data_rdata_i[31]}}, data_rdata_i[31:16]};
|
||||
end
|
||||
`endif // ONLY_ALIGNED
|
||||
end
|
||||
|
||||
// sign extension for bytes
|
||||
|
@ -322,10 +367,16 @@ module riscv_load_store_unit
|
|||
// store the data coming from memory in rdata_q.
|
||||
// In all other cases, rdata_q gets the value that we are
|
||||
// writing to the register file
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
if ((data_misaligned_ex_i == 1'b1) || (data_misaligned_o == 1'b1))
|
||||
rdata_q <= data_rdata_i;
|
||||
else
|
||||
rdata_q <= data_rdata_ext;
|
||||
`else
|
||||
rdata_q <= data_rdata_ext;
|
||||
`endif // ONLY_ALIGNED
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -339,7 +390,10 @@ module riscv_load_store_unit
|
|||
assign data_we_o = data_we_ex_i;
|
||||
assign data_be_o = data_be;
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
assign misaligned_st = data_misaligned_ex_i;
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
assign load_err_o = data_gnt_i && data_err_i && ~data_we_o;
|
||||
assign store_err_o = data_gnt_i && data_err_i && data_we_o;
|
||||
|
@ -447,6 +501,8 @@ module riscv_load_store_unit
|
|||
endcase
|
||||
end
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
// check for misaligned accesses that need a second memory access
|
||||
// If one is detected, this is signaled with data_misaligned_o to
|
||||
// the controller which selectively stalls the pipeline
|
||||
|
@ -470,6 +526,7 @@ module riscv_load_store_unit
|
|||
endcase // case (data_type_ex_i)
|
||||
end
|
||||
end
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// CONFIG_REGION: LSU_ADDER_SUPPORT
|
||||
`ifdef LSU_ADDER_SUPPORT
|
||||
|
|
|
@ -126,7 +126,10 @@ module riscv_core
|
|||
logic useincr_addr_ex; // Active when post increment
|
||||
`endif // PREPOST_SUPPORT
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
logic data_misaligned;
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// CONFIG_REGION: MUL_SUPPORT
|
||||
`ifdef MUL_SUPPORT
|
||||
|
@ -217,7 +220,10 @@ module riscv_core
|
|||
logic data_req_ex;
|
||||
logic [31:0] data_pc_ex;
|
||||
logic data_load_event_ex;
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
logic data_misaligned_ex;
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// stall control
|
||||
logic halt_if;
|
||||
|
@ -551,14 +557,20 @@ module riscv_core
|
|||
.data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit
|
||||
.data_load_event_ex_o ( data_load_event_ex ), // to load store unit
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// CONFIG_REGION: PREPOST_SUPPORT
|
||||
`ifdef PREPOST_SUPPORT
|
||||
.prepost_useincr_ex_o ( useincr_addr_ex ),
|
||||
`endif // PREPOST_SUPPORT
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.data_misaligned_i ( data_misaligned ),
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// Interrupt Signals
|
||||
.irq_i ( irq_i ), // incoming interrupts
|
||||
|
@ -748,8 +760,11 @@ module riscv_core
|
|||
.addr_useincr_ex_i ( useincr_addr_ex ),
|
||||
`endif // PREPOST_SUPPORT
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.data_misaligned_ex_i ( data_misaligned_ex ), // from ID/EX pipeline
|
||||
.data_misaligned_o ( data_misaligned ),
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
// exception signals
|
||||
.load_err_o ( lsu_load_err ),
|
||||
|
@ -1018,7 +1033,10 @@ module riscv_core
|
|||
.ex_data_wdata ( data_wdata_o ),
|
||||
|
||||
.wb_bypass ( ex_stage_i.branch_in_ex_i ),
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
.lsu_misaligned ( data_misaligned ),
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
.wb_valid ( wb_valid ),
|
||||
.wb_reg_addr ( id_stage_i.registers_i.waddr_a_i ),
|
||||
|
|
|
@ -79,7 +79,10 @@ module riscv_simchecker
|
|||
input logic [31:0] ex_data_addr,
|
||||
input logic [31:0] ex_data_wdata,
|
||||
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
input logic lsu_misaligned,
|
||||
`endif // ONLY_ALIGNED
|
||||
input logic wb_bypass,
|
||||
|
||||
input logic wb_valid,
|
||||
|
@ -181,7 +184,12 @@ module riscv_simchecker
|
|||
|
||||
trace.mem_access.push_back(mem_acc);
|
||||
end
|
||||
// CONFIG_REGION: ONLY_ALIGNED
|
||||
`ifndef ONLY_ALIGNED
|
||||
end while ((!ex_valid || lsu_misaligned) && (!wb_bypass));
|
||||
`else
|
||||
end while ((!ex_valid) && (!wb_bypass));
|
||||
`endif // ONLY_ALIGNED
|
||||
|
||||
trace.wb_bypass = wb_bypass;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue