mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Change LSU to use correct protocol
With prefetching there is no long path to the icache anymore starting from the LSU, so this modification is no longer critical
This commit is contained in:
parent
6fb05eab34
commit
e41c7b96be
4 changed files with 105 additions and 158 deletions
|
@ -82,9 +82,10 @@ module controller
|
|||
output logic data_sign_extension_o, // Sign extension on read data from data memory
|
||||
output logic [1:0] data_reg_offset_o, // Offset in bytes inside register for stores
|
||||
output logic data_req_o, // Request for a transaction to data memory
|
||||
input logic data_ack_i, // Data memory request-acknowledge
|
||||
input logic data_req_ex_i, // Delayed copy of the data_req_o
|
||||
input logic data_rvalid_i, // rvalid from data memory
|
||||
|
||||
input logic lsu_ready_ex_i,
|
||||
input logic lsu_ready_wb_i,
|
||||
|
||||
// hwloop signals
|
||||
output logic [2:0] hwloop_we_o, // write enable for hwloop regs
|
||||
|
@ -173,7 +174,6 @@ module controller
|
|||
logic mult_en;
|
||||
logic [1:0] csr_op;
|
||||
|
||||
logic lsu_stall;
|
||||
logic misalign_stall;
|
||||
logic instr_ack_stall;
|
||||
logic load_stall;
|
||||
|
@ -1256,9 +1256,6 @@ module controller
|
|||
// Stall because of IF miss
|
||||
assign instr_ack_stall = ~instr_ack_i;
|
||||
|
||||
// Stall if TCDM contention has been detected
|
||||
assign lsu_stall = ~data_ack_i;
|
||||
|
||||
assign misalign_stall = data_misaligned_i;
|
||||
|
||||
assign trap_stall = trap_insn_o;
|
||||
|
@ -1284,10 +1281,10 @@ module controller
|
|||
// 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_stall | misalign_stall | halt_if | (~pc_valid_i) | (jump_in_id_o == `BRANCH_COND);
|
||||
stall_id_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | halt_id;
|
||||
stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i;
|
||||
stall_wb_o = lsu_stall | dbg_stall_i;
|
||||
stall_if_o = instr_ack_stall | load_stall | jr_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | misalign_stall | halt_if | (~pc_valid_i) | (jump_in_id_o == `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
|
||||
|
||||
|
||||
|
|
10
id_stage.sv
10
id_stage.sv
|
@ -108,8 +108,9 @@ module id_stage
|
|||
output logic [1:0] data_reg_offset_ex_o,
|
||||
output logic data_misaligned_ex_o,
|
||||
output logic data_req_ex_o,
|
||||
input logic data_ack_i, // Grant from data memory
|
||||
input logic data_rvalid_i,
|
||||
|
||||
input logic lsu_ready_ex_i,
|
||||
input logic lsu_ready_wb_i,
|
||||
|
||||
// Interrupt signals
|
||||
input logic irq_i,
|
||||
|
@ -575,9 +576,10 @@ module id_stage
|
|||
.data_sign_extension_o ( data_sign_ext_id ),
|
||||
.data_reg_offset_o ( data_reg_offset_id ),
|
||||
.data_req_o ( data_req_id ),
|
||||
.data_ack_i ( data_ack_i ),
|
||||
.data_req_ex_i ( data_req_ex_o ),
|
||||
.data_rvalid_i ( data_rvalid_i ),
|
||||
|
||||
.lsu_ready_ex_i ( lsu_ready_ex_i ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb_i ),
|
||||
|
||||
// hwloop signals
|
||||
.hwloop_we_o ( hwloop_we ),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// Engineer: Igor Loi - igor.loi@unibo.it //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 01/07/2014 //
|
||||
|
@ -42,7 +43,6 @@ module load_store_unit
|
|||
|
||||
output logic [31:0] data_rdata_ex_o, // requested data -> to ex stage
|
||||
input logic data_req_ex_i, // data request -> from ex stage
|
||||
output logic data_ack_int_o, // data ack -> to controller
|
||||
input logic [31:0] operand_a_ex_i, // operand a from RF for address -> from ex stage
|
||||
input logic [31:0] operand_b_ex_i, // operand b from RF for address -> from ex stage
|
||||
input logic addr_useincr_ex_i, // use a + b or just a for address -> from ex stage
|
||||
|
@ -61,7 +61,10 @@ module load_store_unit
|
|||
input logic data_rvalid_i,
|
||||
input logic data_gnt_i,
|
||||
|
||||
// stall signal
|
||||
// stall signal
|
||||
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
|
||||
);
|
||||
|
||||
|
@ -74,20 +77,14 @@ module load_store_unit
|
|||
|
||||
logic [1:0] wdata_offset; // mux control for data to be written to memory
|
||||
|
||||
// signals for tcdm contention
|
||||
logic [3:0] data_be, data_be_q;
|
||||
logic [31:0] data_wdata, data_wdata_q;
|
||||
logic data_we_q;
|
||||
logic [31:0] data_addr_q;
|
||||
logic [3:0] data_be;
|
||||
logic [31:0] data_wdata;
|
||||
|
||||
logic misaligned_st; // high if we are currently performing the second part of a misaligned store
|
||||
logic misaligned_st_q; // register for misaligned_st
|
||||
|
||||
logic request_entered;
|
||||
|
||||
enum logic [2:0] { IDLE, WAIT_GNT, PENDING_W_EX_STALL_2, PENDING_W_EX_STALL_1, PENDING_WO_EX_STALL} CS, NS;
|
||||
enum logic [1:0] { IDLE, WAIT_RVALID, WAIT_RVALID_EX_STALL, IDLE_EX_STALL } CS, NS;
|
||||
|
||||
logic latch_rdata;
|
||||
logic [31:0] rdata_q;
|
||||
|
||||
///////////////////////////////// BE generation ////////////////////////////////
|
||||
|
@ -169,7 +166,7 @@ module load_store_unit
|
|||
rdata_offset_q <= '0;
|
||||
data_sign_ext_q <= '0;
|
||||
end
|
||||
else if (request_entered == 1'b1) // request entered FSM
|
||||
else if (data_gnt_i == 1'b1) // request was granted, we wait for rvalid and can continue to WB
|
||||
begin
|
||||
data_type_q <= data_type_ex_i;
|
||||
rdata_offset_q <= data_addr_int[1:0];
|
||||
|
@ -177,39 +174,6 @@ module load_store_unit
|
|||
end
|
||||
end
|
||||
|
||||
// pipeline gnt signal
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
data_ack_int_o <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data_ack_int_o <= ~((data_req_o == 1'b1) & (data_gnt_i == 1'b0));
|
||||
end
|
||||
end
|
||||
|
||||
// FF for not accepted requests
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
data_be_q <= '0;
|
||||
data_addr_q <= '0;
|
||||
data_we_q <= '0;
|
||||
data_wdata_q <= '0;
|
||||
misaligned_st_q <= 1'b0;
|
||||
end
|
||||
else if ((data_req_o == 1'b1) & (data_gnt_i == 1'b0)) // request was not granted
|
||||
begin
|
||||
data_be_q <= data_be_o;
|
||||
data_addr_q <= data_addr_o;
|
||||
data_we_q <= data_we_o;
|
||||
data_wdata_q <= data_wdata_o;
|
||||
misaligned_st_q <= misaligned_st;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ____ _ _____ _ _ //
|
||||
|
@ -335,7 +299,7 @@ module load_store_unit
|
|||
begin
|
||||
CS <= NS;
|
||||
|
||||
if(latch_rdata)
|
||||
if(data_rvalid_i)
|
||||
begin
|
||||
// if we have detected a misaligned access, and we are
|
||||
// currently doing the first part of this access, then
|
||||
|
@ -351,133 +315,112 @@ module load_store_unit
|
|||
end
|
||||
|
||||
// output to register file
|
||||
assign data_rdata_ex_o = (latch_rdata == 1'b1) ? data_rdata_ext : rdata_q;
|
||||
assign data_rdata_ex_o = (data_rvalid_i == 1'b1) ? data_rdata_ext : rdata_q;
|
||||
|
||||
assign data_addr_o = data_addr_int;
|
||||
assign data_wdata_o = data_wdata;
|
||||
assign data_we_o = data_we_ex_i;
|
||||
assign data_be_o = data_be;
|
||||
|
||||
assign misaligned_st = data_misaligned_ex_i;
|
||||
|
||||
// FSM
|
||||
always_comb
|
||||
begin
|
||||
NS = CS;
|
||||
|
||||
data_req_o = 1'b0;
|
||||
data_we_o = 1'b0;
|
||||
data_addr_o = data_addr_int;
|
||||
data_wdata_o = data_wdata;
|
||||
data_be_o = data_be;
|
||||
misaligned_st = data_misaligned_ex_i;
|
||||
latch_rdata = 1'b0;
|
||||
request_entered = 1'b0;
|
||||
|
||||
lsu_ready_ex_o = 1'b1;
|
||||
lsu_ready_wb_o = 1'b1;
|
||||
|
||||
case(CS)
|
||||
// starts from not active and stays in IDLE until request was granted
|
||||
IDLE:
|
||||
begin
|
||||
data_req_o = data_req_ex_i;
|
||||
data_we_o = data_we_ex_i;
|
||||
data_req_o = data_req_ex_i;
|
||||
|
||||
if(data_req_ex_i)
|
||||
begin
|
||||
request_entered = 1'b1;
|
||||
if(data_req_ex_i) begin
|
||||
lsu_ready_ex_o = 1'b0;
|
||||
|
||||
if(data_gnt_i) begin
|
||||
lsu_ready_ex_o = 1'b1;
|
||||
|
||||
if(data_gnt_i)
|
||||
begin
|
||||
if(ex_stall_i)
|
||||
NS = PENDING_W_EX_STALL_1;
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
else
|
||||
NS = PENDING_WO_EX_STALL;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(ex_stall_i)
|
||||
NS = IDLE;
|
||||
else
|
||||
begin
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
NS = WAIT_RVALID;
|
||||
end
|
||||
end
|
||||
else
|
||||
NS = IDLE;
|
||||
end //~ IDLE
|
||||
|
||||
WAIT_GNT:
|
||||
// wait for rvalid in WB stage and send a new request if there is any
|
||||
WAIT_RVALID:
|
||||
begin
|
||||
data_req_o = 1'b1;
|
||||
data_we_o = data_we_q;
|
||||
lsu_ready_wb_o = 1'b0;
|
||||
|
||||
data_addr_o = data_addr_q;
|
||||
data_be_o = data_be_q;
|
||||
data_wdata_o = data_wdata_q;
|
||||
misaligned_st = misaligned_st_q;
|
||||
data_req_o = data_req_ex_i;
|
||||
|
||||
if(data_gnt_i)
|
||||
begin
|
||||
NS = PENDING_WO_EX_STALL;
|
||||
if (data_rvalid_i) begin
|
||||
// we don't have to wait for anything here as we are the only stall
|
||||
// source for the WB stage
|
||||
lsu_ready_wb_o = 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
end // case: WAIT_GNT
|
||||
|
||||
PENDING_WO_EX_STALL:
|
||||
begin
|
||||
latch_rdata = ~data_we_o;
|
||||
if(data_req_ex_i) begin
|
||||
lsu_ready_ex_o = 1'b0;
|
||||
|
||||
data_req_o = data_req_ex_i;
|
||||
data_we_o = data_we_ex_i;
|
||||
if(data_gnt_i) begin
|
||||
lsu_ready_ex_o = 1'b1;
|
||||
|
||||
if(data_req_ex_i)
|
||||
begin
|
||||
request_entered = 1'b1;
|
||||
|
||||
if(data_gnt_i)
|
||||
begin
|
||||
if(ex_stall_i)
|
||||
NS = PENDING_W_EX_STALL_1;
|
||||
NS = WAIT_RVALID_EX_STALL;
|
||||
else
|
||||
NS = PENDING_WO_EX_STALL;
|
||||
NS = WAIT_RVALID;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(ex_stall_i)
|
||||
NS = IDLE;
|
||||
else
|
||||
NS = WAIT_GNT;
|
||||
end else begin
|
||||
// no request, so go to IDLE
|
||||
NS = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
// wait for rvalid while still in EX stage
|
||||
// we end up here when there was an EX stall, so in this cycle we just
|
||||
// wait and don't send new requests
|
||||
WAIT_RVALID_EX_STALL:
|
||||
begin
|
||||
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
|
||||
// we are done and can go back to idle
|
||||
// the data is safely stored already
|
||||
NS = IDLE;
|
||||
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)
|
||||
NS = WAIT_RVALID;
|
||||
end
|
||||
else
|
||||
NS = IDLE;
|
||||
end //~PENDING_WO_EX_STALL
|
||||
end
|
||||
|
||||
PENDING_W_EX_STALL_1 :
|
||||
IDLE_EX_STALL:
|
||||
begin
|
||||
data_req_o = 1'b0;
|
||||
|
||||
latch_rdata = ~data_we_o;
|
||||
|
||||
if(ex_stall_i)
|
||||
begin
|
||||
NS = PENDING_W_EX_STALL_2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// wait for us to be unstalled and then change back to IDLE state
|
||||
if (~ex_stall_i) begin
|
||||
NS = IDLE;
|
||||
end
|
||||
end //~ PENDING_W_EX_STALL_1
|
||||
end
|
||||
|
||||
PENDING_W_EX_STALL_2 :
|
||||
begin
|
||||
if(ex_stall_i)
|
||||
begin
|
||||
NS = PENDING_W_EX_STALL_2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NS = IDLE;
|
||||
end
|
||||
end //~ PENDING_W_EX_STALL_2
|
||||
|
||||
default :
|
||||
begin
|
||||
default: begin
|
||||
NS = IDLE;
|
||||
|
||||
data_req_o = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
|
|
@ -166,7 +166,9 @@ module riscv_core
|
|||
logic [1:0] data_reg_offset_ex;
|
||||
logic data_req_ex;
|
||||
logic data_misaligned_ex;
|
||||
logic data_ack_int;
|
||||
|
||||
logic lsu_ready_ex;
|
||||
logic lsu_ready_wb;
|
||||
|
||||
// Signals between instruction core interface and pipe (if and id stages)
|
||||
logic instr_req_int; // Id stage asserts a req to instruction core interface
|
||||
|
@ -361,8 +363,9 @@ module riscv_core
|
|||
.data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit
|
||||
.data_req_ex_o ( data_req_ex ), // to load store unit
|
||||
.data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit
|
||||
.data_ack_i ( data_ack_int ), // from load store unit
|
||||
.data_rvalid_i ( data_r_valid_i ),
|
||||
|
||||
.lsu_ready_ex_i ( lsu_ready_ex ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb ),
|
||||
|
||||
// Interrupt Signals
|
||||
.irq_i ( irq_i ), // incoming interrupts
|
||||
|
@ -482,7 +485,6 @@ module riscv_core
|
|||
|
||||
.data_rdata_ex_o ( regfile_wdata ),
|
||||
.data_req_ex_i ( data_req_ex ),
|
||||
.data_ack_int_o ( data_ack_int ), // ack used in controller to stall
|
||||
.operand_a_ex_i ( alu_operand_a_ex ),
|
||||
.operand_b_ex_i ( alu_operand_b_ex ),
|
||||
.addr_useincr_ex_i ( useincr_addr_ex ),
|
||||
|
@ -492,14 +494,17 @@ module riscv_core
|
|||
|
||||
//output to data memory
|
||||
.data_req_o ( data_req_o ),
|
||||
.data_gnt_i ( data_gnt_i ),
|
||||
.data_rvalid_i ( data_r_valid_i ),
|
||||
|
||||
.data_addr_o ( data_addr_o ),
|
||||
.data_we_o ( data_we_o ),
|
||||
|
||||
.data_be_o ( data_be_o ),
|
||||
.data_wdata_o ( data_wdata_o ),
|
||||
.data_rdata_i ( data_rdata_i ),
|
||||
.data_rvalid_i ( data_r_valid_i ),
|
||||
.data_gnt_i ( data_gnt_i ),
|
||||
|
||||
.lsu_ready_ex_o ( lsu_ready_ex ),
|
||||
.lsu_ready_wb_o ( lsu_ready_wb ),
|
||||
|
||||
.ex_stall_i ( stall_ex )
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue