diff --git a/src/scoreboard.sv b/src/scoreboard.sv index 92254af99c0b4c1cdc40605cdcf8bdaedf2a4acf..a53aacbb2292075b972de64c224c2fa47b8ded0e 100644 --- a/src/scoreboard.sv +++ b/src/scoreboard.sv @@ -239,70 +239,45 @@ module scoreboard #( // RD clobber process // ------------------- // rd_clobber output: output currently clobbered destination registers - logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][NR_ENTRIES:0] gpr_clobber_vld; - logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][NR_ENTRIES:0] fpr_clobber_vld; - ariane_pkg::fu_t [NR_ENTRIES:0] clobber_fu; - - always_comb begin : clobber_assign - gpr_clobber_vld = '0; - fpr_clobber_vld = '0; - - // default (highest entry hast lowest prio in arbiter tree below) - clobber_fu[NR_ENTRIES] = ariane_pkg::NONE; - for (int unsigned i = 0; i < 2**ariane_pkg::REG_ADDR_SIZE; i++) begin - gpr_clobber_vld[i][NR_ENTRIES] = 1'b1; - fpr_clobber_vld[i][NR_ENTRIES] = 1'b1; - end - - // check for all valid entries and set the clobber accordingly - for (int unsigned i = 0; i < NR_ENTRIES; i++) begin - gpr_clobber_vld[mem_q[i].sbe.rd][i] = ~mem_q[i].pending & mem_q[i].issued & ~mem_q[i].is_rd_fpr_flag; - fpr_clobber_vld[mem_q[i].sbe.rd][i] = ~mem_q[i].pending & mem_q[i].issued & mem_q[i].is_rd_fpr_flag; - clobber_fu[i] = mem_q[i].sbe.fu; + logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][NR_ENTRIES-1:0] gpr_clobber_vld; + logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][NR_ENTRIES-1:0] fpr_clobber_vld; + ariane_pkg::fu_t [NR_ENTRIES-1:0] clobber_fu; + + for (genvar i = 0; i < 2**ariane_pkg::REG_ADDR_SIZE; i++) begin + for (genvar j = 0; j < NR_ENTRIES; j++) begin + assign gpr_clobber_vld[i][j] = mem_q[j].sbe.rd == i & ~mem_q[j].pending & mem_q[j].issued & ~mem_q[j].is_rd_fpr_flag & i != 0; + assign fpr_clobber_vld[i][j] = mem_q[j].sbe.rd == i & ~mem_q[j].pending & mem_q[j].issued & mem_q[j].is_rd_fpr_flag; end + end - // GPR[0] is always free - gpr_clobber_vld[0] = '0; + for (genvar k = 0; k < NR_ENTRIES; k++) begin + assign clobber_fu[k] = mem_q[k].sbe.fu; 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(NR_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_o[k] ), - .idx_o ( ) + for (genvar k = 0; k < 2**ariane_pkg::REG_ADDR_SIZE; k++) begin + logic [$clog2(NR_ENTRIES)-1:0] gpr_clobber_idx, fpr_clobber_idx; + logic gpr_no_clobber, fpr_no_clobber; + + lzc #( + .WIDTH ( NR_ENTRIES ), + .MODE ( 0 ) + ) lzc_gpr_clobbers ( + .in_i ( gpr_clobber_vld[k] ), + .cnt_o ( gpr_clobber_idx ), + .empty_o ( gpr_no_clobber ) ); - rr_arb_tree #( - .NumIn(NR_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_o[k] ), - .idx_o ( ) + + lzc #( + .WIDTH ( NR_ENTRIES ), + .MODE ( 0 ) + ) lzc_fpr_clobbers ( + .in_i ( fpr_clobber_vld[k] ), + .cnt_o ( fpr_clobber_idx ), + .empty_o ( fpr_no_clobber ) ); + + assign rd_clobber_gpr_o[k] = (gpr_no_clobber) ? ariane_pkg::NONE : clobber_fu[gpr_clobber_idx]; + assign rd_clobber_fpr_o[k] = (fpr_no_clobber) ? ariane_pkg::NONE : clobber_fu[fpr_clobber_idx]; end // ---------------------------------- @@ -310,6 +285,7 @@ module scoreboard #( // ---------------------------------- // read operand interface: same logic as register file logic [NR_ENTRIES+NR_WB_PORTS-1:0] rs1_fwd_req, rs2_fwd_req, rs3_fwd_req; + logic [$clog2(NR_WB_PORTS+NR_ENTRIES)-1:0] rs1_fwd_idx, rs2_fwd_idx, rs3_fwd_idx; logic [NR_ENTRIES+NR_WB_PORTS-1:0][riscv::XLEN-1:0] rs_data; logic rs1_valid, rs2_valid; @@ -327,72 +303,44 @@ module scoreboard #( assign rs_data[k+NR_WB_PORTS] = mem_q[k].sbe.result; end - // check whether we are accessing GPR[0], rs3 is only used with the FPR! - assign rs1_valid_o = rs1_valid & ((|rs1_i) | ariane_pkg::is_rs1_fpr(issue_instr_o.op)); - assign rs2_valid_o = rs2_valid & ((|rs2_i) | ariane_pkg::is_rs2_fpr(issue_instr_o.op)); - - // use fixed prio here - // this implicitly gives higher prio to WB ports - rr_arb_tree #( - .NumIn(NR_ENTRIES+NR_WB_PORTS), - .DataWidth(riscv::XLEN), - .ExtPrio(1'b1), - .AxiVldRdy(1'b1) - ) i_sel_rs1 ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( rs1_fwd_req ), - .gnt_o ( ), - .data_i ( rs_data ), - .gnt_i ( 1'b1 ), - .req_o ( rs1_valid ), - .data_o ( rs1_o ), - .idx_o ( ) + lzc #( + .WIDTH ( NR_WB_PORTS+NR_ENTRIES ), + .MODE ( 0 ) + ) i_lzc_rs1_wb ( + .in_i ( rs1_fwd_req ), + .cnt_o ( rs1_fwd_idx ), + .empty_o ( ) ); - rr_arb_tree #( - .NumIn(NR_ENTRIES+NR_WB_PORTS), - .DataWidth(riscv::XLEN), - .ExtPrio(1'b1), - .AxiVldRdy(1'b1) - ) i_sel_rs2 ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( rs2_fwd_req ), - .gnt_o ( ), - .data_i ( rs_data ), - .gnt_i ( 1'b1 ), - .req_o ( rs2_valid ), - .data_o ( rs2_o ), - .idx_o ( ) + lzc #( + .WIDTH ( NR_WB_PORTS+NR_ENTRIES ), + .MODE ( 0 ) + ) i_lzc_rs2_wb ( + .in_i ( rs2_fwd_req ), + .cnt_o ( rs2_fwd_idx ), + .empty_o ( ) ); - riscv::xlen_t rs3; - - rr_arb_tree #( - .NumIn(NR_ENTRIES+NR_WB_PORTS), - .DataWidth(riscv::XLEN), - .ExtPrio(1'b1), - .AxiVldRdy(1'b1) - ) i_sel_rs3 ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( rs3_fwd_req ), - .gnt_o ( ), - .data_i ( rs_data ), - .gnt_i ( 1'b1 ), - .req_o ( rs3_valid_o ), - .data_o ( rs3 ), - .idx_o ( ) + lzc #( + .WIDTH ( NR_WB_PORTS+NR_ENTRIES ), + .MODE ( 0 ) + ) i_lzc_rs3_wb ( + .in_i ( rs3_fwd_req ), + .cnt_o ( rs3_fwd_idx ), + .empty_o ( ) ); - assign rs3_o = rs3[ariane_pkg::FLEN-1:0]; + assign rs1_valid = |rs1_fwd_req; + assign rs2_valid = |rs2_fwd_req; + assign rs3_valid_o = |rs3_fwd_req; + + assign rs1_o = (rs1_valid) ? rs_data[rs1_fwd_idx] : '0; + assign rs2_o = (rs2_valid) ? rs_data[rs2_fwd_idx] : '0; + assign rs3_o = (rs3_valid_o) ? rs_data[rs3_fwd_idx] : '0; + + // check whether we are accessing GPR[0], rs3 is only used with the FPR! + assign rs1_valid_o = rs1_valid & ((|rs1_i) | ariane_pkg::is_rs1_fpr(issue_instr_o.op)); + assign rs2_valid_o = rs2_valid & ((|rs2_i) | ariane_pkg::is_rs2_fpr(issue_instr_o.op)); // sequential process always_ff @(posedge clk_i or negedge rst_ni) begin : regs