[smc/hw] Always require rvalid for successful SC.W - Since the ALU is used for writing to rd to indicate the success reponse, a dTLB hit is no longer registered and the write is qualified directly in ID. Fix: 293617243 Change-Id: I28a00a14574c25f3d74fe5622e7fd2edc05f3c26
diff --git a/hw/top_matcha/ip/smc/rtl/smc_core.sv b/hw/top_matcha/ip/smc/rtl/smc_core.sv index 7748ffc..5559088 100644 --- a/hw/top_matcha/ip/smc/rtl/smc_core.sv +++ b/hw/top_matcha/ip/smc/rtl/smc_core.sv
@@ -777,6 +777,7 @@ .sfence_rs2_asid_o (sfence_rs2_asid), // Atomics + .data_rvalid_i(data_rvalid_i), .amo_rf_success_o(amo_sc_lsu_written) );
diff --git a/hw/top_matcha/ip/smc/rtl/smc_decoder.sv b/hw/top_matcha/ip/smc/rtl/smc_decoder.sv index ba1b91e..3add819 100644 --- a/hw/top_matcha/ip/smc/rtl/smc_decoder.sv +++ b/hw/top_matcha/ip/smc/rtl/smc_decoder.sv
@@ -371,19 +371,22 @@ AMO_SC: begin amo_sc_o = 1'b1; + data_we_cmd_o = STORE; + // Address generation if (amo_outstanding_req_i || amo_ptw_finished_i) begin rf_ren_a_o = 1'b1; rf_ren_b_o = 1'b1; data_req_o = 1'b1; - data_we_cmd_o = STORE; + + // Valid reservation end else if (amo_rf_success_i) begin - rf_we = 1'b1; + rf_we = 1'b1; + data_req_o = 1'b1; + + // No reservation end else begin - // We don't qualify here with !amo_sc_success_i in order to - // set rd=1 immediately in case an interrupt disrupts - // an LSU PTW. The downside is rf_we is high throughout the PTW. - rf_we = 1'b1; + rf_we = 1'b1; end end @@ -947,13 +950,16 @@ end AMO_SC: begin + + // Address generation if (amo_outstanding_req_i || amo_ptw_finished_i) begin alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMM_B_ZERO; alu_operator_o = ALU_ADD; - // Failure and success both use SLTU. Set success to write 0 instead of 1 by default. + // Regardless of reservation, the ALU uses SLTU. + // If there is no reservation we write 1 by default. end else if (amo_rf_success_i) begin alu_op_a_mux_sel_o = OP_A_IMM; imm_a_mux_sel_o = IMM_A_ZERO;
diff --git a/hw/top_matcha/ip/smc/rtl/smc_id_stage.sv b/hw/top_matcha/ip/smc/rtl/smc_id_stage.sv index 85458d8..a1257bc 100644 --- a/hw/top_matcha/ip/smc/rtl/smc_id_stage.sv +++ b/hw/top_matcha/ip/smc/rtl/smc_id_stage.sv
@@ -214,7 +214,8 @@ output logic [ASIDWidth-1:0] sfence_rs2_asid_o, // Atomics - output logic amo_rf_success_o // one cycle after writing to DMEM + input logic data_rvalid_i, + output logic amo_rf_success_o ); import smc_pkg::*; @@ -329,7 +330,7 @@ // Atomics logic amo_lr, amo_sc; - logic amo_sc_valid; + logic amo_sc_valid, amo_sc_invalid; logic amo_sc_success_d, amo_sc_success_q; logic amo_rf_success_d, amo_rf_success_q; logic amo_outstanding_res_q, amo_outstanding_res_d; @@ -562,7 +563,7 @@ .amo_lr_o (amo_lr), .amo_outstanding_req_i(amo_outstanding_req), .amo_ptw_finished_i (ptw_finished_q), - .amo_rf_success_i (amo_rf_success_o) + .amo_rf_success_i (amo_rf_success_q) ); assign lsu_req_in_dec_o = lsu_req_dec; @@ -759,17 +760,19 @@ // Atomics // //////////////////////// - assign amo_sc_valid = amo_sc && amo_outstanding_res_q; - assign amo_outstanding_req = amo_outstanding_res_q; - assign amo_rf_success_o = amo_rf_success_q; - - // Valid reservation is registered as soon as LR executes, regardless - // if the LSU receives a valid response. + // if the LSU receives a valid response. amo_sc_invalid masks additional LSU + // requests on valid SC after address generation. + + assign amo_sc_valid = amo_sc && amo_outstanding_res_q; + assign amo_sc_invalid = amo_sc && ~amo_outstanding_res_q; + assign amo_outstanding_req = amo_outstanding_res_q; + assign amo_rf_success_o = (amo_rf_success_d == 1'b0) && (amo_rf_success_q == 1'b1); + always_comb begin amo_outstanding_res_d = amo_outstanding_res_q; amo_sc_success_d = id_ptw_active_i ? amo_sc_success_q : 1'b0; - amo_rf_success_d = 1'b0; + amo_rf_success_d = data_rvalid_i ? 1'b0 : amo_rf_success_q; if (lsu_req) begin if (amo_lr) begin @@ -779,7 +782,8 @@ amo_sc_success_d = 1'b1; end - // Only write 1 to rd one cycle after valid SC.W (PTW and non-PTW). + // Write 0 to rd one cycle after valid SC.W and hold amo_rf_success until + // we receive rvalid to prevent default rf write of 1. if ((amo_sc_valid && !ptw_spec_walk_i) || (ptw_finished_q && amo_sc_success_q)) begin amo_rf_success_d = 1'b1; end @@ -804,7 +808,8 @@ assign multdiv_en_dec = mult_en_dec | div_en_dec; assign lsu_req = instr_executing ? (data_req_allowed | ptw_finished_q) & - lsu_req_dec & ~mmu_data_req_fault : 1'b0; + lsu_req_dec & ~mmu_data_req_fault & ~amo_sc_invalid + : 1'b0; assign mult_en_id = instr_executing ? mult_en_dec : 1'b0; assign div_en_id = instr_executing ? div_en_dec : 1'b0;