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:
Andreas Traber 2015-09-10 13:05:24 +02:00
parent 6fb05eab34
commit e41c7b96be
4 changed files with 105 additions and 158 deletions

View file

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

View file

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

View file

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

View file

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