re-enabled basic store forwarding

This commit is contained in:
Eric Matthews 2020-06-12 16:13:53 -07:00
parent 34ab0c59b3
commit f164ef291d
5 changed files with 91 additions and 38 deletions

View file

@ -202,7 +202,7 @@ module decode_and_issue (
//All units share the same operand ready logic except load-store which has an internal forwarding path
always_comb begin
unit_operands_ready = {NUM_UNITS{operands_ready}};
//unit_operands_ready[LS_UNIT_WB_ID] = ~rs1_conflict;
unit_operands_ready[LS_UNIT_WB_ID] = ~rs1_conflict;
end
assign issue_ready = unit_needed_issue_stage & unit_ready;
@ -344,7 +344,7 @@ module decode_and_issue (
assign ls_inputs.fn3 = amo_op ? LS_W_fn3 : issue.fn3;
assign ls_inputs.rs1 = rs_data[RS1];
assign ls_inputs.rs2 = rs_data[RS2];
assign ls_inputs.forwarded_store = 0;//rs2_conflict;
assign ls_inputs.forwarded_store = rs2_conflict;
assign ls_inputs.store_forward_id = rs_id[RS2];
////////////////////////////////////////////////////

View file

@ -202,17 +202,22 @@ interface load_store_queue_interface;
endinterface
interface writeback_store_interface;
id_t id_needed_at_issue;
id_t id_needed_at_commit;
id_t commit_id;
logic commit;
logic [MAX_IDS-1:0] hold_for_store_ids;
id_t id_needed;
logic possibly_waiting;
logic waiting;
logic ack;
logic forwarding_data_ready;
logic [31:0] forwarded_data;
logic id_done;
logic [31:0] data;
modport ls (input forwarding_data_ready, forwarded_data, output id_needed_at_issue, id_needed_at_commit, commit_id, commit, hold_for_store_ids);
modport wb (output forwarding_data_ready, forwarded_data, input id_needed_at_issue, id_needed_at_commit, commit_id, commit, hold_for_store_ids);
modport ls (
input id_done, data,
output id_needed, possibly_waiting ,waiting, ack
);
modport wb (
input id_needed, possibly_waiting, waiting, ack,
output id_done, data
);
endinterface
interface ls_sub_unit_interface #(parameter BASE_ADDR = 32'h00000000, parameter UPPER_BOUND = 32'hFFFFFFFF, parameter BIT_CHECK = 4);

View file

@ -33,15 +33,12 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
input logic gc_issue_flush,
load_store_queue_interface.queue lsq,
output logic [MAX_IDS-1:0] wb_hold_for_store_ids,
//Writeback data
input logic [31:0] writeback_data,
input logic writeback_valid
writeback_store_interface.ls wb_store,
output logic ready_for_forwarded_store
);
logic [MAX_IDS-1:0] valid;
logic [$clog2(MAX_IDS)-1:0] hold_for_store_ids [MAX_IDS];
logic [$clog2(MAX_IDS)-1:0] hold_for_store_ids_r [MAX_IDS];
id_t oldest_id;
typedef struct packed {
@ -122,40 +119,46 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
// );
////////////////////////////////////////////////////
//Counters for determining if an existing ID's data is needed for a store
//As mutiple stores could need the same ID, there is a counter for each ID.
//Store Forwarding Support
//Only a single store can be forwarded at any given time
//The needed result is registered at the writeback stage when the
//needed ID is retired.
logic possible_new_forwarded_store;//To help shorten logic path for registering results in the writeback stage
logic new_forwarded_store;
logic forwarded_store_complete;
id_t needed_id_r;
logic waiting_r;
assign possible_new_forwarded_store = lsq.possible_issue & lsq.forwarded_store;
assign new_forwarded_store = lsq.new_issue & lsq.forwarded_store;
assign forwarded_store_complete = lsq.accepted & oldest_lsq_entry.forwarded_store;
always_comb begin
hold_for_store_ids = hold_for_store_ids_r;
if (new_forwarded_store)
hold_for_store_ids[lsq.data_id] = hold_for_store_ids_r[lsq.data_id] + 1;
if (forwarded_store_complete)
hold_for_store_ids[oldest_lsq_entry.data_id] = hold_for_store_ids_r[oldest_lsq_entry.data_id] - 1;
always_ff @ (posedge clk) begin
if (rst)
waiting_r <= 0;
else
waiting_r <= new_forwarded_store | (waiting_r & ~wb_store.id_done);
end
assign wb_store.waiting = new_forwarded_store | waiting_r;
assign wb_store.possibly_waiting = possible_new_forwarded_store | waiting_r;
assign wb_store.ack = forwarded_store_complete;
assign ready_for_forwarded_store = ~(waiting_r | wb_store.id_done);
always_ff @ (posedge clk) begin
if (rst | gc_issue_flush)
hold_for_store_ids_r <= '{default: 0};
else
hold_for_store_ids_r <= hold_for_store_ids;
if (new_forwarded_store)
needed_id_r <= lsq.data_id;
end
assign wb_store.id_needed = possible_new_forwarded_store ? lsq.data_id : needed_id_r;
always_comb begin
foreach (hold_for_store_ids_r[i])
wb_hold_for_store_ids[i] = (hold_for_store_ids_r[i] != 0);
end
////////////////////////////////////////////////////
//Output
logic [31:0] data_for_alignment;
assign oldest_lsq_entry = lsq_entries[oldest_id];
assign lsq.transaction_ready = oldest_fifo.valid & (~oldest_lsq_entry.forwarded_store | writeback_valid);
assign lsq.transaction_ready = oldest_fifo.valid & (~oldest_lsq_entry.forwarded_store | wb_store.id_done);
assign lsq.id_needed_by_store = oldest_lsq_entry.data_id;
always_comb begin
@ -166,7 +169,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
lsq.transaction_out.fn3 = oldest_lsq_entry.fn3;
lsq.transaction_out.id = oldest_id;
data_for_alignment = oldest_lsq_entry.forwarded_store ? writeback_data : oldest_lsq_entry.data_in;
data_for_alignment = oldest_lsq_entry.forwarded_store ? wb_store.data : oldest_lsq_entry.data_in;
//Input: ABCD
//Assuming aligned requests,
//Possible byte selections: (A/C/D, B/D, C/D, D)

View file

@ -120,7 +120,7 @@ module load_store_unit (
logic [31:0] compare_addr;
logic address_conflict;
logic ready_for_forwarded_store;
////////////////////////////////////////////////////
//Implementation
////////////////////////////////////////////////////
@ -190,7 +190,7 @@ endgenerate
assign lsq.new_issue = issue.new_request & ~unaligned_addr;
logic [MAX_IDS-1:0] wb_hold_for_store_ids;
load_store_queue lsq_block (.*, .writeback_valid(wb_store.forwarding_data_ready), .writeback_data(wb_store.forwarded_data));
load_store_queue lsq_block (.*);
assign shared_inputs = lsq.transaction_out;
assign lsq.accepted = lsq.transaction_ready & ready_for_issue;
@ -228,7 +228,7 @@ endgenerate
assign ready_for_issue = units_ready & (~unit_switch_stall);
assign issue.ready = lsq.ready;
assign issue.ready = lsq.ready & ~(ls_inputs.forwarded_store & ~ready_for_forwarded_store);
assign issue_request = lsq.accepted;
////////////////////////////////////////////////////

View file

@ -39,6 +39,7 @@ module register_file_and_writeback
input id_t id_for_rd [COMMIT_PORTS],
//Writeback
unit_writeback_interface.wb unit_wb[NUM_WB_UNITS],
writeback_store_interface.wb wb_store,
//Trace signals
output logic tr_rs1_forwarding_needed,
@ -148,6 +149,50 @@ module register_file_and_writeback
rs_data[i] = rs_data_set[rs_sel[i]][i];
end
end
////////////////////////////////////////////////////
//Store Forwarding Support
logic [31:0] commit_regs [COMMIT_PORTS];
logic [$clog2(COMMIT_PORTS)-1:0] store_reg_sel;
logic [$clog2(COMMIT_PORTS)-1:0] store_reg_sel_r;
generate for (i = 0; i < COMMIT_PORTS; i++) begin
always_ff @ (posedge clk) begin
if (wb_store.possibly_waiting & retired[i] & (wb_store.id_needed == ids_retiring[i]))
commit_regs[i] <= retiring_data[i];
end
end endgenerate
logic [COMMIT_PORTS-1:0] store_id_match;
always_comb begin
store_id_match = 0;
for (int i = 0; i < COMMIT_PORTS; i++) begin
if (wb_store.waiting & retired[i] & (wb_store.id_needed == ids_retiring[i]))
store_id_match[i] = 1;
end
store_reg_sel = 0;
for (int i = 1; i < COMMIT_PORTS; i++) begin
if (retired[i] & (wb_store.id_needed == ids_retiring[i]))
store_reg_sel = ($clog2(COMMIT_PORTS))'(i);
end
end
always_ff @ (posedge clk) begin
if (|store_id_match)
store_reg_sel_r <= store_reg_sel;
end
always_ff @ (posedge clk) begin
if (rst | wb_store.ack)
wb_store.id_done <= 0;
else if (|store_id_match)
wb_store.id_done <= 1;
end
assign wb_store.data = commit_regs[store_reg_sel_r];
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////