mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-20 12:07:53 -04:00
L/S exception rework
This commit is contained in:
parent
56c5b2bbf3
commit
30d314c263
9 changed files with 75 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue