diff --git a/.gitlab-ci/scripts/report_benchmark.py b/.gitlab-ci/scripts/report_benchmark.py index cec2c10fd..c711b10f9 100644 --- a/.gitlab-ci/scripts/report_benchmark.py +++ b/.gitlab-ci/scripts/report_benchmark.py @@ -23,8 +23,8 @@ valid_cycles = { "dhrystone_single": 24127, "coremark_dual": 1001191, "coremark_single": 1300030, - "dhrystone_cv32a65x": 31976, - "dhrystone_cv32a60x": 39449, + "dhrystone_cv32a65x": 30056, + "dhrystone_cv32a60x": 37474, } for arg in sys.argv[1:]: diff --git a/core/issue_read_operands.sv b/core/issue_read_operands.sv index 8f70016f0..4123f4c9a 100644 --- a/core/issue_read_operands.sv +++ b/core/issue_read_operands.sv @@ -136,7 +136,9 @@ module issue_read_operands logic none, load, store, alu, alu2, ctrl_flow, mult, csr, fpu, fpu_vec, cvxif, accel; } fus_busy_t; - logic [CVA6Cfg.NrIssuePorts-1:0] stall_raw, stall_waw, stall_rs1, stall_rs2, stall_rs3; + typedef logic [CVA6Cfg.TRANS_ID_BITS:0] clobber_t; + + logic [CVA6Cfg.NrIssuePorts-1:0] stall_raw, stall_rs1, stall_rs2, stall_rs3; logic [CVA6Cfg.NrIssuePorts-1:0] fu_busy; // functional unit is busy fus_busy_t [CVA6Cfg.NrIssuePorts-1:0] fus_busy; // which functional units are considered busy logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack; @@ -182,10 +184,17 @@ module issue_read_operands logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs3_res; // clobber - fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_gpr, rd_clobber_fpr; - logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] gpr_clobber_vld; - logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] fpr_clobber_vld; - ariane_pkg::fu_t [ CVA6Cfg.NR_SB_ENTRIES:0] clobber_fu; + clobber_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_gpr, rd_clobber_fpr; + + // Csr issued check + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] csr_issued_raw; + logic [ CVA6Cfg.NR_SB_ENTRIES:0] csr_issued; + + for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin + assign csr_issued_raw[i] = fwd_i.still_issued[i] && fwd_i.sbe[i].fu == ariane_pkg::CSR; + end + + assign csr_issued = {1'b0, csr_issued_raw}; //forward logic logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0] @@ -246,7 +255,7 @@ module issue_read_operands // TODO check only for 1st instruction ?? // Allow a cvxif transaction if we WaW condition are ok. - assign cvxif_req_allowed = (issue_instr_i[0].fu == CVXIF) && !stall_waw[0]; + assign cvxif_req_allowed = (issue_instr_i[0].fu == CVXIF); assign cvxif_instruction_valid = !issue_instr_i[0].ex.valid && issue_instr_valid_i[0] && cvxif_req_allowed; assign x_transaction_accepted_o = x_issue_valid_o && x_issue_ready_i && x_issue_resp_i.accept; assign x_transaction_rejected = x_issue_valid_o && x_issue_ready_i && ~x_issue_resp_i.accept; @@ -412,74 +421,32 @@ module issue_read_operands // RD clobber process // ------------------- // rd_clobber output: output currently clobbered destination registers + logic [2*CVA6Cfg.NR_SB_ENTRIES-1:0] still_issued_rotated_raw; + logic [ CVA6Cfg.NR_SB_ENTRIES-1:0] still_issued_rotated; + logic [ CVA6Cfg.TRANS_ID_BITS-1:0] unrotated_index; + + assign still_issued_rotated_raw = {fwd_i.still_issued, fwd_i.still_issued} >> fwd_i.commit_pointer; + assign still_issued_rotated = still_issued_rotated_raw[CVA6Cfg.NR_SB_ENTRIES-1:0]; always_comb begin : clobber_assign - gpr_clobber_vld = '0; - fpr_clobber_vld = '0; + rd_clobber_gpr = '{default: clobber_t'(CVA6Cfg.NR_SB_ENTRIES)}; + rd_clobber_fpr = '{default: clobber_t'(CVA6Cfg.NR_SB_ENTRIES)}; // default (highest entry hast lowest prio in arbiter tree below) - clobber_fu[CVA6Cfg.NR_SB_ENTRIES] = ariane_pkg::NONE; - for (int unsigned i = 0; i < 2 ** ariane_pkg::REG_ADDR_SIZE; i++) begin - gpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1; - fpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1; - end - - // check for all valid entries and set the clobber accordingly - + unrotated_index = '0; for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin - gpr_clobber_vld[fwd_i.sbe[i].rd][i] = fwd_i.still_issued[i] & ~(CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[i].op)); - fpr_clobber_vld[fwd_i.sbe[i].rd][i] = fwd_i.still_issued[i] & (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[i].op)); - clobber_fu[i] = fwd_i.sbe[i].fu; + unrotated_index = i + fwd_i.commit_pointer; + if (still_issued_rotated[i]) begin + if (~(CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(fwd_i.sbe[unrotated_index].op))) begin + rd_clobber_gpr[fwd_i.sbe[unrotated_index].rd] = clobber_t'(unrotated_index[CVA6Cfg.TRANS_ID_BITS-1:0]); + end else begin + rd_clobber_fpr[fwd_i.sbe[unrotated_index].rd] = clobber_t'(unrotated_index[CVA6Cfg.TRANS_ID_BITS-1:0]); + end + end end // GPR[0] is always free - gpr_clobber_vld[0] = '0; - end - - for (genvar k = 0; k < 2 ** ariane_pkg::REG_ADDR_SIZE; k++) begin : gen_sel_clobbers - // get fu that is going to clobber this register (there should be only one) - rr_arb_tree #( - .NumIn(CVA6Cfg.NR_SB_ENTRIES + 1), - .DataType(ariane_pkg::fu_t), - .ExtPrio(1'b1), - .AxiVldRdy(1'b1) - ) i_sel_gpr_clobbers ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i(1'b0), - .rr_i ('0), - .req_i (gpr_clobber_vld[k]), - .gnt_o (), - .data_i (clobber_fu), - .gnt_i (1'b1), - .req_o (), - .data_o (rd_clobber_gpr[k]), - .idx_o () - ); - if (CVA6Cfg.FpPresent) begin - rr_arb_tree #( - .NumIn(CVA6Cfg.NR_SB_ENTRIES + 1), - .DataType(ariane_pkg::fu_t), - .ExtPrio(1'b1), - .AxiVldRdy(1'b1) - ) i_sel_fpr_clobbers ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i(1'b0), - .rr_i ('0), - .req_i (fpr_clobber_vld[k]), - .gnt_o (), - .data_i (clobber_fu), - .gnt_i (1'b1), - .req_o (), - .data_o (rd_clobber_fpr[k]), - .idx_o () - ); - end else begin - assign rd_clobber_fpr[k] = NONE; - end + rd_clobber_gpr[0] = clobber_t'(CVA6Cfg.NR_SB_ENTRIES); end // ---------------------------------- @@ -491,47 +458,48 @@ module issue_read_operands for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin for (genvar k = 0; unsigned'(k) < CVA6Cfg.NrWbPorts; k++) begin : gen_rs_wb - assign rs1_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].rs1) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[fwd_i.wb[k].trans_id].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr( + assign rs1_fwd_req[i][k] = ((clobber_t'(fwd_i.wb[k].trans_id) == rd_clobber_gpr[issue_instr_i[i].rs1] && (!ariane_pkg::is_rs1_fpr( issue_instr_i[i].op - ))); - - assign rs2_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].rs2) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[fwd_i.wb[k].trans_id].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr( + ))) || (clobber_t'(fwd_i.wb[k].trans_id) == rd_clobber_fpr[issue_instr_i[i].rs1] && + (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr( issue_instr_i[i].op - ))); - - assign rs3_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[fwd_i.wb[k].trans_id].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr( + )))) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid); + assign rs2_fwd_req[i][k] = ((clobber_t'(fwd_i.wb[k].trans_id) == rd_clobber_gpr[issue_instr_i[i].rs2] && (!ariane_pkg::is_rs2_fpr( issue_instr_i[i].op - ))); - + ))) || (clobber_t'(fwd_i.wb[k].trans_id) == rd_clobber_fpr[issue_instr_i[i].rs2] && + (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr( + issue_instr_i[i].op + )))) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid); + assign rs3_fwd_req[i][k] = ((clobber_t'(fwd_i.wb[k].trans_id) == rd_clobber_gpr[issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]] && (!ariane_pkg::is_imm_fpr( + issue_instr_i[i].op + ))) || (clobber_t'(fwd_i.wb[k].trans_id) == + rd_clobber_fpr[issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]] && + (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr( + issue_instr_i[i].op + )))) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid); assign rs_data[i][k] = fwd_i.wb[k].data; end for (genvar k = 0; unsigned'(k) < CVA6Cfg.NR_SB_ENTRIES; k++) begin : gen_rs_entries - assign rs1_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].rs1) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[k].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr( + assign rs1_fwd_req[i][k+CVA6Cfg.NrWbPorts] = ((rd_clobber_gpr[issue_instr_i[i].rs1] == clobber_t'(k) &&(!ariane_pkg::is_rs1_fpr( issue_instr_i[i].op - ))); - - assign rs2_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].rs2) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[k].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr( + ))) || (rd_clobber_fpr[issue_instr_i[i].rs1] == clobber_t'(k) && + (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr( issue_instr_i[i].op - ))); - - assign rs3_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - fwd_i.sbe[k].op - )) == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr( + )))) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid; + assign rs2_fwd_req[i][k+CVA6Cfg.NrWbPorts] = ((rd_clobber_gpr[issue_instr_i[i].rs2] == clobber_t'(k) && (!ariane_pkg::is_rs2_fpr( issue_instr_i[i].op - ))); - + ))) || (rd_clobber_fpr[issue_instr_i[i].rs2] == clobber_t'(k) && + (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr( + issue_instr_i[i].op + )))) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid; + assign rs3_fwd_req[i][k+CVA6Cfg.NrWbPorts] = ((rd_clobber_gpr[issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]] == clobber_t'(k) && (!ariane_pkg::is_imm_fpr( + issue_instr_i[i].op + ))) || (rd_clobber_fpr[issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]] == + clobber_t'(k) && (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr( + issue_instr_i[i].op + )))) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid; assign rs_data[i][k+CVA6Cfg.NrWbPorts] = fwd_i.sbe[k].result; end @@ -603,27 +571,27 @@ module issue_read_operands assign rs1_has_raw[i] = !issue_instr_i[i].use_zimm && ((CVA6Cfg.FpPresent && is_rs1_fpr( issue_instr_i[i].op - )) ? rd_clobber_fpr[issue_instr_i[i].rs1] != NONE : - rd_clobber_gpr[issue_instr_i[i].rs1] != NONE); + )) ? rd_clobber_fpr[issue_instr_i[i].rs1] != clobber_t'(CVA6Cfg.NR_SB_ENTRIES) : + rd_clobber_gpr[issue_instr_i[i].rs1] != clobber_t'(CVA6Cfg.NR_SB_ENTRIES)); assign rs1_valid[i] = rs1_available[i] && (CVA6Cfg.FpPresent && is_rs1_fpr( issue_instr_i[i].op - ) ? 1'b1 : ((rd_clobber_gpr[issue_instr_i[i].rs1] != CSR) || + ) ? 1'b1 : (!(csr_issued[rd_clobber_gpr[issue_instr_i[i].rs1]]) || (CVA6Cfg.RVS && issue_instr_i[i].op == SFENCE_VMA))); assign rs2_has_raw[i] = ((CVA6Cfg.FpPresent && is_rs2_fpr( issue_instr_i[i].op - )) ? rd_clobber_fpr[issue_instr_i[i].rs2] != NONE : - rd_clobber_gpr[issue_instr_i[i].rs2] != NONE); + )) ? rd_clobber_fpr[issue_instr_i[i].rs2] != clobber_t'(CVA6Cfg.NR_SB_ENTRIES) : + rd_clobber_gpr[issue_instr_i[i].rs2] != clobber_t'(CVA6Cfg.NR_SB_ENTRIES)); assign rs2_valid[i] = rs2_available[i] && (CVA6Cfg.FpPresent && is_rs2_fpr( issue_instr_i[i].op - ) ? 1'b1 : ((rd_clobber_gpr[issue_instr_i[i].rs2] != CSR) || + ) ? 1'b1 : (!(csr_issued[rd_clobber_gpr[issue_instr_i[i].rs2]]) || (CVA6Cfg.RVS && issue_instr_i[i].op == SFENCE_VMA))); assign rs3_has_raw[i] = ((CVA6Cfg.FpPresent && is_imm_fpr( issue_instr_i[i].op - )) ? rd_clobber_fpr[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != NONE : 0); + )) ? rd_clobber_fpr[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != CVA6Cfg.NR_SB_ENTRIES : 0); assign rs3_valid[i] = rs3_available[i]; assign rs3_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_i[i].op)); @@ -902,40 +870,6 @@ module issue_read_operands end end - always_comb begin : gen_check_waw_dependencies - stall_waw = '1; - for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin - if (issue_instr_valid_i[i] && !fu_busy[i]) begin - // ----------------------------------------- - // WAW - Write After Write Dependency Check - // ----------------------------------------- - // no other instruction has the same destination register -> issue the instruction - if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - issue_instr_i[i].op - )) ? (rd_clobber_fpr[issue_instr_i[i].rd] == NONE) : - (rd_clobber_gpr[issue_instr_i[i].rd] == NONE)) begin - stall_waw[i] = 1'b0; - end - // or check that the target destination register will be written in this cycle by the - // commit stage - for (int unsigned c = 0; c < CVA6Cfg.NrCommitPorts; c++) begin - if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr( - issue_instr_i[i].op - )) ? (we_fpr_i[c] && waddr_i[c] == issue_instr_i[i].rd) : - (we_gpr_i[c] && waddr_i[c] == issue_instr_i[i].rd)) begin - stall_waw[i] = 1'b0; - end - end - if (i > 0) begin - if ((issue_instr_i[i].rd == issue_instr_i[i-1].rd) && (issue_instr_i[i].rd != '0)) begin - stall_waw[i] = 1'b1; - end - end - end - end - end - - // We can issue an instruction if we do not detect that any other instruction is writing the same // destination register. // We also need to check if there is an unresolved branch in the scoreboard. @@ -946,7 +880,7 @@ module issue_read_operands // check that the instruction we got is valid // and that the functional unit we need is not busy if (issue_instr_valid_i[i] && !fu_busy[i]) begin - if (!stall_raw[i] && !stall_waw[i]) begin + if (!stall_raw[i]) begin issue_ack[i] = 1'b1; end if (issue_instr_i[i].ex.valid) begin diff --git a/core/issue_stage.sv b/core/issue_stage.sv index 4ffc5382e..eea7181b9 100644 --- a/core/issue_stage.sv +++ b/core/issue_stage.sv @@ -172,6 +172,7 @@ module issue_stage typedef struct packed { logic [CVA6Cfg.NR_SB_ENTRIES-1:0] still_issued; logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer; + logic [CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer; writeback_t [CVA6Cfg.NrWbPorts-1:0] wb; scoreboard_entry_t [CVA6Cfg.NR_SB_ENTRIES-1:0] sbe; } forwarding_t; diff --git a/core/scoreboard.sv b/core/scoreboard.sv index 6a1b3d094..2f2332540 100644 --- a/core/scoreboard.sv +++ b/core/scoreboard.sv @@ -295,6 +295,7 @@ module scoreboard #( assign fwd_o.still_issued = still_issued; assign fwd_o.issue_pointer = issue_pointer; + assign fwd_o.commit_pointer = commit_pointer_q[0]; assign fwd_o.wb = wb; for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin assign fwd_o.sbe[i] = mem_q[i].sbe;