mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 21:17:46 -04:00
re-enabled basic store forwarding
This commit is contained in:
parent
34ab0c59b3
commit
f164ef291d
5 changed files with 91 additions and 38 deletions
|
@ -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];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue