L/S exception rework

This commit is contained in:
Eric Matthews 2022-01-18 10:57:33 -08:00
parent 56c5b2bbf3
commit 30d314c263
9 changed files with 75 additions and 20 deletions

View file

@ -69,6 +69,7 @@ module gc_unit
//Ordering support
input logic sq_empty,
input logic no_released_stores_pending,
input logic [LOG2_MAX_IDS:0] post_issue_count
);
@ -129,6 +130,7 @@ module gc_unit
logic gc_fetch_flush;
logic gc_supress_writeback;
logic gc_tlb_flush;
logic gc_sq_flush;
logic gc_pc_override;
logic [31:0] gc_pc;
@ -147,10 +149,11 @@ module gc_unit
always_ff @ (posedge clk) begin
gc_fetch_hold <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, ISSUE_DRAIN};
gc_issue_hold <= processing_csr | (next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, TLB_CLEAR_STATE, ISSUE_DRAIN});
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE};
gc_issue_hold <= processing_csr | (next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, TLB_CLEAR_STATE, ISSUE_DRAIN, ISSUE_DISCARD});
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, ISSUE_DISCARD};
gc_init_clear <= next_state inside {INIT_CLEAR_STATE};
gc_tlb_flush <= next_state inside {INIT_CLEAR_STATE, TLB_CLEAR_STATE};
gc_sq_flush <= state inside {ISSUE_DISCARD} && next_state inside {IDLE_STATE};
end
//work-around for verilator BLKANDNBLK signal optimizations
assign gc.fetch_hold = gc_fetch_hold;
@ -158,6 +161,7 @@ module gc_unit
assign gc.supress_writeback = gc_supress_writeback;
assign gc.init_clear = gc_init_clear;
assign gc.tlb_flush = gc_tlb_flush;
assign gc.sq_flush = gc_sq_flush;
////////////////////////////////////////////////////
//GC State Machine
always @(posedge clk) begin
@ -174,11 +178,17 @@ module gc_unit
PRE_CLEAR_STATE : next_state = INIT_CLEAR_STATE;
INIT_CLEAR_STATE : if (init_clear_done) next_state = IDLE_STATE;
IDLE_STATE : begin
if (issue.new_request | interrupt_pending | gc.exception_pending)
if (gc.exception.valid)
next_state = ISSUE_DISCARD;
else if (issue.new_request | interrupt_pending | gc.exception_pending)
next_state = ISSUE_DRAIN;
end
TLB_CLEAR_STATE : if (tlb_clear_done) next_state = IDLE_STATE;
ISSUE_DRAIN : if (post_issue_idle) next_state = IDLE_STATE;
ISSUE_DRAIN : begin
if (post_issue_idle) next_state = IDLE_STATE;
else if (gc.exception.valid) next_state = ISSUE_DISCARD;
end
ISSUE_DISCARD : if ((post_issue_count == 0) & no_released_stores_pending) next_state = IDLE_STATE;
default : next_state = RST_STATE;
endcase
end

View file

@ -213,10 +213,12 @@ interface load_store_queue_interface;
logic transaction_ready;
logic sq_empty;
logic empty;
logic no_released_stores_pending;
logic accepted;
modport queue (input addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, output ready, transaction_out, transaction_ready, sq_empty, empty);
modport ls (output addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, input ready, transaction_out, transaction_ready, sq_empty, empty);
modport queue (input addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, output ready, transaction_out, transaction_ready, sq_empty, empty, no_released_stores_pending);
modport ls (output addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, input ready, transaction_out, transaction_ready, sq_empty, empty, no_released_stores_pending);
endinterface
interface writeback_store_interface;

View file

@ -53,6 +53,8 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
logic sq_full;
logic sq_empty;
logic no_released_stores_pending;
sq_entry_t sq_entry;
logic [31:0] sq_data;
logic store_conflict;
@ -88,7 +90,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
load_queue #(.SQ_DEPTH(SQ_DEPTH)) lq_block (
.clk (clk),
.rst (rst | gc.issue_flush),
.rst (rst),
.lsq (lsq_entry),
.lq_entry (lq_entry),
.potential_store_conflicts (potential_store_conflicts),
@ -96,13 +98,19 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
.lq_output_valid (lq_output_valid)
);
logic sq_retire_port_valid [RETIRE_PORTS];
always_comb begin
for (int i=0; i < RETIRE_PORTS; i++)
sq_retire_port_valid[i] = retire_port_valid[i] & ~gc.supress_writeback;
end
store_queue #(.DEPTH(SQ_DEPTH)) sq_block (
.clk (clk),
.rst (rst | gc.issue_flush),
.rst (rst | gc.sq_flush),
.lsq (lsq_entry),
.sq_empty (sq_empty),
.sq_full (sq_full),
.no_released_stores_pending (no_released_stores_pending),
.addr_hash (addr_hash),
.potential_store_conflicts (potential_store_conflicts),
.load_issued (load_ack),
@ -112,7 +120,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
.sq_data (sq_data),
.wb_snoop (wb_snoop),
.retire_ids (retire_ids),
.retire_port_valid (retire_port_valid),
.retire_port_valid (sq_retire_port_valid),
.store_ack (store_ack),
.sq_output_valid (sq_output_valid)
);
@ -138,6 +146,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
assign lsq.transaction_out.id = lq_entry.id;
assign lsq.sq_empty = sq_empty;
assign lsq.no_released_stores_pending = no_released_stores_pending;
assign lsq.empty = ~lq_output_valid & sq_empty;
////////////////////////////////////////////////////

View file

@ -63,6 +63,7 @@ module load_store_unit
exception_interface.unit exception,
output logic sq_empty,
output logic no_released_stores_pending,
output logic load_store_idle,
unit_writeback_interface.unit wb,
@ -103,6 +104,7 @@ module load_store_unit
logic [NUM_SUB_UNITS-1:0] current_unit;
logic unaligned_addr;
logic load_exception_complete;
logic [NUM_SUB_UNITS-1:0] sub_unit_address_match;
logic fence_hold;
logic unit_stall;
@ -149,12 +151,19 @@ generate if (CONFIG.INCLUDE_M_MODE) begin
end
always_ff @(posedge clk) begin
if (new_exception) begin
if (new_exception & ~exception.valid) begin
exception.code <= ls_inputs.store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED;
exception.tval <= virtual_address;
exception.id <= issue.id;
end
end
always_ff @(posedge clk) begin
if (rst)
load_exception_complete <= 0;
else
load_exception_complete <= exception.valid & exception.ack & (exception.code == LOAD_ADDR_MISSALIGNED);
end
end
endgenerate
////////////////////////////////////////////////////
@ -239,10 +248,11 @@ endgenerate
assign ready_for_issue_from_lsq = units_ready & (~unit_switch_stall);
assign issue.ready = (~tlb_on | tlb.ready) & lsq.ready & ~fence_hold;
assign issue.ready = (~tlb_on | tlb.ready) & lsq.ready & ~fence_hold & ~exception.valid;
assign issue_request = lsq.transaction_ready & ready_for_issue_from_lsq;
assign sq_empty = lsq.sq_empty;
assign no_released_stores_pending = lsq.no_released_stores_pending;
assign load_store_idle = lsq.empty & units_ready;
always_ff @ (posedge clk) begin
@ -390,8 +400,8 @@ endgenerate
////////////////////////////////////////////////////
//Output bank
assign wb.rd = final_load_data;
assign wb.done = load_complete;
assign wb.id = stage2_attr.id;
assign wb.done = load_complete | load_exception_complete;
assign wb.id = load_exception_complete ? exception.id : stage2_attr.id;
////////////////////////////////////////////////////
//End of Implementation

View file

@ -111,7 +111,7 @@ module register_file
.clk, .rst,
.write_addr(commit[i].phys_addr),
.new_data(commit[i].data),
.commit(commit[i].valid),
.commit(commit[i].valid & ~gc.supress_writeback),
.read_addr(decode_phys_rs_addr),
.data(rs_data_set[i])
);

View file

@ -45,7 +45,11 @@ module renamer
input retire_packet_t retire
);
//////////////////////////////////////////
(* ramstyle = "MLAB, no_rw_check" *) phys_addr_t architectural_id_to_phys_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) phys_addr_t architectural_id_to_old_phys_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] architectural_id_to_old_wb_group_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) phys_addr_t architectural_id_to_current_phys_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic[4:0] architectural_id_to_current_rd_addr_table [MAX_IDS];
logic [5:0] clear_index;
fifo_interface #(.DATA_WIDTH(6)) free_list ();
@ -79,7 +83,7 @@ module renamer
assign free_list.potential_push = (gc.init_clear & ~clear_index[5]) | (retire.valid);
assign free_list.push = free_list.potential_push;
//TODO: restore spec if instruction has been discarded due to a speculation failure
assign free_list.data_in = gc.init_clear ? {1'b1, clear_index[4:0]} : architectural_id_to_phys_table[retire.phys_id];
assign free_list.data_in = gc.init_clear ? {1'b1, clear_index[4:0]} : (gc.supress_writeback ? architectural_id_to_current_phys_table[retire.phys_id] : architectural_id_to_old_phys_table[retire.phys_id]);
assign free_list.pop = rename_valid;
////////////////////////////////////////////////////
@ -100,7 +104,7 @@ module renamer
logic spec_table_update;
logic [4:0] spec_table_write_index;
assign spec_table_update = rename_valid | rollback | gc.init_clear;
assign spec_table_update = rename_valid | rollback | gc.init_clear | (retire.valid & gc.supress_writeback);
always_comb begin
if (gc.init_clear) begin
@ -108,6 +112,11 @@ module renamer
spec_table_next.phys_addr = {1'b0, clear_index[4:0]};
spec_table_next.wb_group = '0;
end
else if (gc.supress_writeback) begin
spec_table_write_index = architectural_id_to_current_rd_addr_table[retire.phys_id];
spec_table_next.phys_addr = architectural_id_to_old_phys_table[retire.phys_id];
spec_table_next.wb_group = architectural_id_to_old_wb_group_table[retire.phys_id];
end
else if (rollback) begin
spec_table_write_index = issue.rd_addr;
spec_table_next.phys_addr = spec_table_old_r.phys_addr;
@ -145,12 +154,20 @@ module renamer
end
////////////////////////////////////////////////////
//Arch ID-to-phys Table
//Arch ID-to-phys Tables
always_ff @ (posedge clk) begin
if (rename_valid)
architectural_id_to_phys_table[decode.id] <= spec_table_old.phys_addr;
if (rename_valid) begin
architectural_id_to_old_phys_table[decode.id] <= spec_table_old.phys_addr;
architectural_id_to_old_wb_group_table[decode.id] <= spec_table_old.wb_group;
end
end
always_ff @ (posedge clk) begin
if (rename_valid) begin
architectural_id_to_current_phys_table[decode.id] <= decode.phys_rd_addr;
architectural_id_to_current_rd_addr_table[decode.id] <= decode.rd_addr;
end
end
////////////////////////////////////////////////////
//Renamed Outputs
spec_table_t [REGFILE_READ_PORTS-1:0] spec_table_decode;

View file

@ -36,6 +36,7 @@ module store_queue
//Queue status
output logic sq_empty,
output logic sq_full,
output logic no_released_stores_pending,
//Request interface
input lsq_entry_t lsq,
@ -219,6 +220,8 @@ module store_queue
released <= (released | newly_released) & ~new_request_one_hot;
end
assign no_released_stores_pending = ~|(valid & released);
////////////////////////////////////////////////////
//Store Data
always_ff @ (posedge clk) begin

View file

@ -170,6 +170,7 @@ module taiga
logic [$clog2(NUM_EXCEPTION_SOURCES)-1:0] current_exception_unit;
gc_outputs_t gc;
logic sq_empty;
logic no_released_stores_pending;
logic load_store_idle;
logic [LOG2_MAX_IDS:0] post_issue_count;
@ -495,6 +496,7 @@ module taiga
.retire_port_valid(retire_port_valid),
.exception (exception[LS_EXCEPTION]),
.sq_empty (sq_empty),
.no_released_stores_pending (no_released_stores_pending),
.load_store_idle (load_store_idle),
.wb (unit_wb[UNIT_IDS.LS]),
.tr_load_conflict_delay (tr_load_conflict_delay)
@ -575,6 +577,7 @@ module taiga
.interrupt_pending(interrupt_pending),
.processing_csr(processing_csr),
.sq_empty (sq_empty),
.no_released_stores_pending (no_released_stores_pending),
.post_issue_count (post_issue_count)
);

View file

@ -267,6 +267,7 @@ package taiga_types;
logic issue_flush;
logic fetch_flush;
logic supress_writeback;
logic sq_flush;
logic tlb_flush;
logic exception_pending;
exception_packet_t exception;