diff --git a/core/cva5.sv b/core/cva5.sv index 6e3fd9f..adcdce4 100644 --- a/core/cva5.sv +++ b/core/cva5.sv @@ -464,6 +464,7 @@ module cva5 .senvcfg (senvcfg), .wb_packet (wb_packet), .fp_wb_packet (fp_wb_packet), + .retire_id (retire_ids[0]), .store_retire (store_retire), .exception (exception[LS_EXCEPTION]), .load_store_status(load_store_status), diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index c2a6729..9b1e13b 100644 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -337,6 +337,7 @@ module decode_and_issue assign exception.code = ecode; assign exception.tval = tval; assign exception.pc = issue.pc; + assign exception.discard = 0; end endgenerate //////////////////////////////////////////////////// diff --git a/core/execution_units/branch_unit.sv b/core/execution_units/branch_unit.sv index eaa672c..b816699 100644 --- a/core/execution_units/branch_unit.sv +++ b/core/execution_units/branch_unit.sv @@ -214,6 +214,7 @@ module branch_unit assign exception.code = INST_ADDR_MISSALIGNED; assign exception.tval = new_pc_ex; assign exception.pc = issue_stage.pc_r; + assign exception.discard = 0; end endgenerate diff --git a/core/execution_units/csr_unit.sv b/core/execution_units/csr_unit.sv index 3362215..43616fe 100644 --- a/core/execution_units/csr_unit.sv +++ b/core/execution_units/csr_unit.sv @@ -971,6 +971,7 @@ generate if (CONFIG.MODES != BARE) begin : gen_csr_exceptions assign exception.code = ILLEGAL_INST; assign exception.pc = issue_stage.pc_r; assign exception.tval = issue_stage.instruction_r; + assign exception.discard = 1; end endgenerate diff --git a/core/execution_units/gc_unit.sv b/core/execution_units/gc_unit.sv index 37b1465..9f7f043 100644 --- a/core/execution_units/gc_unit.sv +++ b/core/execution_units/gc_unit.sv @@ -130,6 +130,7 @@ module gc_unit logic gc_init_clear; logic gc_fetch_hold; logic gc_issue_hold; + logic gc_rename_revert; logic gc_fetch_flush; logic gc_fetch_ifence; logic gc_tlb_flush; @@ -242,6 +243,7 @@ module gc_unit assign local_gc_exception.code = ILLEGAL_INST; assign local_gc_exception.tval = issue_stage.instruction_r; assign local_gc_exception.pc = issue_stage.pc_r; + assign local_gc_exception.discard = 0; end endgenerate @@ -355,12 +357,14 @@ generate if (CONFIG.MODES != BARE) begin :gen_gc_m_mode exception_code_t [NUM_EXCEPTION_SOURCES-1:0] exception_code; logic [NUM_EXCEPTION_SOURCES-1:0][31:0] exception_tval; logic [NUM_EXCEPTION_SOURCES-1:0][31:0] exception_pc; + logic [NUM_EXCEPTION_SOURCES-1:0] exception_discard; logic [31:0] muxed_exception_pc; for (genvar i = 0; i < NUM_EXCEPTION_SOURCES; i++) begin assign exception_valid[i] = exception[i].valid; assign exception_code[i] = exception[i].code; assign exception_tval[i] = exception[i].tval; + assign exception_discard[i] = exception[i].discard; assign exception_pc[i] = exception[i].pc; end @@ -383,10 +387,25 @@ generate if (CONFIG.MODES != BARE) begin :gen_gc_m_mode .choices(exception_pc), .sel(muxed_exception_pc), .*); - assign gc.exception.pc = |exception_valid ? muxed_exception_pc : issue_stage.pc; + assign gc.exception.pc = |exception_valid ? muxed_exception_pc : issue_stage.pc; assign interrupt_taken = interrupt_pending & (next_state == PRE_ISSUE_FLUSH) & ~(gc.exception.valid) & ~csr_frontend_flush; + //Writeback and rename handling + logic gc_writeback_suppress_r; + logic gc_rename_revert; + always_ff @(posedge clk) begin + if (rst) begin + gc_writeback_suppress_r <= 0; + gc_rename_revert <= 0; + end + else begin + gc_writeback_suppress_r <= gc.writeback_suppress; + gc_rename_revert <= gc_writeback_suppress_r; + end + end + assign gc.writeback_suppress = |(exception_valid & exception_discard); + assign gc.rename_revert = gc_rename_revert; end endgenerate //PC determination (trap, flush or return) diff --git a/core/execution_units/load_store_unit/load_store_unit.sv b/core/execution_units/load_store_unit/load_store_unit.sv index 59f902d..4e04a86 100644 --- a/core/execution_units/load_store_unit/load_store_unit.sv +++ b/core/execution_units/load_store_unit/load_store_unit.sv @@ -84,7 +84,8 @@ module load_store_unit input wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS], input fp_wb_packet_t fp_wb_packet [2], - //Retire release + //Retire + input id_t retire_id, input retire_packet_t store_retire, exception_interface.unit exception, @@ -172,7 +173,6 @@ module load_store_unit logic [3:0] be; //FIFOs fifo_interface #(.DATA_TYPE(load_attributes_t)) load_attributes(); - fifo_interface #(.DATA_TYPE(logic[31:0])) backstop(); load_store_queue_interface lsq(); //////////////////////////////////////////////////// @@ -352,7 +352,30 @@ module load_store_unit assign senv_illegal = CONFIG.INCLUDE_CBO & (issue_attr.is_cbo & issue_attr.cbo_type == INVAL ? senvcfg.cbie == 2'b00 : ~senvcfg.cbcfe); assign illegal_cbo = CONFIG.MODES == MU ? current_privilege == USER_PRIVILEGE & menv_illegal : (current_privilege != MACHINE_PRIVILEGE & menv_illegal) | (current_privilege == USER_PRIVILEGE & senv_illegal); - assign new_exception = (issue.new_request & ((unaligned_addr & ~issue_attr.is_fence & ~issue_attr.is_cbo) | illegal_cbo)) | tlb.is_fault; + //Hold writeback exceptions until they are ready to retire + logic delay_exception; + logic delayed_exception; + assign delay_exception = ( + (issue.new_request & unaligned_addr & (issue_attr.is_load | issue_attr.is_amo) & issue.id != retire_id) | + (tlb.is_fault & tlb_lq & exception_id != retire_id) + ); + always_ff @(posedge clk) begin + if (rst) + delayed_exception <= 0; + else if (delay_exception) + delayed_exception <= 1; + else if (new_exception) + delayed_exception <= 0; + end + + assign new_exception = ( + (issue.new_request & ((unaligned_addr & issue_attr.is_store) | illegal_cbo)) | + (issue.new_request & unaligned_addr & (issue_attr.is_load | issue_attr.is_amo) & issue.id == retire_id) | + (tlb.is_fault & ~tlb_lq) | + (tlb.is_fault & tlb_lq & exception_id == retire_id) | + (delayed_exception & exception_id == retire_id) + ); + always_ff @(posedge clk) begin if (rst) exception.valid <= 0; @@ -381,8 +404,9 @@ module load_store_unit if (tlb.is_fault) exception.code <= is_load_r ? LOAD_PAGE_FAULT : STORE_OR_AMO_PAGE_FAULT; end - assign exception.possible = (tlb_request_r & ~tlb.done) | exception.valid; //Must suppress issue for issue-time exceptions too + assign exception.possible = (tlb_request_r & ~tlb.done) | exception.valid | delayed_exception; //Must suppress issue for issue-time exceptions too assign exception.pc = issue_stage.pc_r; + assign exception.discard = tlb_lq; assign exception_is_store = ~tlb_lq; end endgenerate @@ -676,7 +700,7 @@ module load_store_unit logic sign_bit_data [4]; logic sign_bit; - assign unit_muxed_load_data = backstop.valid ? backstop.data_out : unit_data_array[wb_attr.subunit_id]; + assign unit_muxed_load_data = unit_data_array[wb_attr.subunit_id]; //Byte/halfword select: assumes aligned operations assign aligned_load_data[31:16] = unit_muxed_load_data[31:16]; @@ -725,17 +749,6 @@ module load_store_unit assign fp_result = 'x; end endgenerate - //////////////////////////////////////////////////// - //Backstop buffering - //Required if load response overlaps an exception - assign backstop.push = load_response & exception.valid & ~exception_is_store; - assign backstop.potential_push = backstop.push; - assign backstop.data_in = unit_muxed_load_data; - assign backstop.pop = backstop.valid; - cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(1)) backstop_fifo ( - .fifo(backstop), - .*); - //////////////////////////////////////////////////// //Output bank assign wb.rd = final_load_data; diff --git a/core/register_file.sv b/core/register_file.sv index 6c67997..a3a78a0 100644 --- a/core/register_file.sv +++ b/core/register_file.sv @@ -118,7 +118,7 @@ module register_file .clk, .waddr(wb_phys_addr[i]), .raddr(decode_phys_rs_addr), - .ram_write(commit[i].valid), + .ram_write(commit[i].valid & ~gc.writeback_suppress), .new_ram_data(commit[i].data), .ram_data_out(regfile_rs_data[i]) ); diff --git a/core/renamer.sv b/core/renamer.sv index 5ae7412..56d888e 100644 --- a/core/renamer.sv +++ b/core/renamer.sv @@ -96,7 +96,7 @@ module renamer assign free_list.potential_push = (gc.init_clear & ~clear_index[5]) | (wb_retire.valid); assign free_list.push = free_list.potential_push; - assign free_list.data_in = gc.init_clear ? {1'b1, clear_index[4:0]} : inuse_table_output.previous_phys_addr; + assign free_list.data_in = gc.init_clear ? {1'b1, clear_index[4:0]} : (gc.rename_revert ? inuse_table_output.spec_phys_addr : inuse_table_output.previous_phys_addr); assign free_list.pop = rename_valid; //////////////////////////////////////////////////// @@ -137,12 +137,12 @@ module renamer rs_addr_t spec_table_write_index; rs_addr_t spec_table_write_index_mux [4]; - assign spec_table_update = rename_valid | rollback | gc.init_clear; + assign spec_table_update = rename_valid | rollback | gc.init_clear | gc.rename_revert; logic [1:0] spec_table_sel; - one_hot_to_integer #(.C_WIDTH(3)) spec_table_sel_one_hot_to_int ( - .one_hot ({gc.init_clear, rollback, 1'b0}), + one_hot_to_integer #(.C_WIDTH(4)) spec_table_sel_one_hot_to_int ( + .one_hot ({gc.init_clear, rollback, gc.rename_revert, 1'b0}), .int_out (spec_table_sel) ); @@ -150,14 +150,18 @@ module renamer assign spec_table_write_index_mux[0] = decode.rd_addr; assign spec_table_next_mux[0].phys_addr = free_list.data_out; assign spec_table_next_mux[0].wb_group = decode.rd_wb_group; + //gc.rename_revert + assign spec_table_write_index_mux[1] = inuse_table_output.rd_addr; + assign spec_table_next_mux[1].phys_addr = inuse_table_output.previous_phys_addr; + assign spec_table_next_mux[1].wb_group = inuse_table_output.previous_wb_group; //rollback - assign spec_table_write_index_mux[1] = issue.rd_addr; - assign spec_table_next_mux[1].phys_addr = spec_table_previous_r.phys_addr; - assign spec_table_next_mux[1].wb_group = spec_table_previous_r.wb_group; + assign spec_table_write_index_mux[2] = issue.rd_addr; + assign spec_table_next_mux[2].phys_addr = spec_table_previous_r.phys_addr; + assign spec_table_next_mux[2].wb_group = spec_table_previous_r.wb_group; //gc.init_clear - assign spec_table_write_index_mux[2] = clear_index[4:0]; - assign spec_table_next_mux[2].phys_addr = {1'b0, clear_index[4:0]}; - assign spec_table_next_mux[2].wb_group = '0; + assign spec_table_write_index_mux[3] = clear_index[4:0]; + assign spec_table_next_mux[3].phys_addr = {1'b0, clear_index[4:0]}; + assign spec_table_next_mux[3].wb_group = '0; assign spec_table_write_index = spec_table_write_index_mux[spec_table_sel]; assign spec_table_next = spec_table_next_mux[spec_table_sel]; diff --git a/core/types_and_interfaces/cva5_types.sv b/core/types_and_interfaces/cva5_types.sv index 6dd057d..27f6602 100644 --- a/core/types_and_interfaces/cva5_types.sv +++ b/core/types_and_interfaces/cva5_types.sv @@ -188,6 +188,8 @@ package cva5_types; logic issue_hold; logic fetch_flush; logic fetch_ifence; + logic writeback_suppress; + logic rename_revert; exception_packet_t exception; logic pc_override; logic [31:0] pc; diff --git a/core/types_and_interfaces/internal_interfaces.sv b/core/types_and_interfaces/internal_interfaces.sv index c5ca99b..041b40b 100644 --- a/core/types_and_interfaces/internal_interfaces.sv +++ b/core/types_and_interfaces/internal_interfaces.sv @@ -103,9 +103,10 @@ interface exception_interface; exception_code_t code; logic [31:0] tval; logic [31:0] pc; + logic discard; - modport unit (output valid, possible, code, tval, pc); - modport econtrol (input valid, possible, code, tval, pc); + modport unit (output valid, possible, code, tval, pc, discard); + modport econtrol (input valid, possible, code, tval, pc, discard); endinterface interface fifo_interface #(parameter type DATA_TYPE = logic);