diff --git a/Bender.yml b/Bender.yml index 2178c96f7..1bb70ab67 100644 --- a/Bender.yml +++ b/Bender.yml @@ -113,6 +113,7 @@ sources: - core/ariane_regfile_ff.sv - core/ariane_regfile_fpga.sv - core/scoreboard.sv + - core/raw_checker.sv - core/store_buffer.sv - core/amo_buffer.sv - core/store_unit.sv diff --git a/Flist.ariane b/Flist.ariane index 592125b7f..103cd41d0 100644 --- a/Flist.ariane +++ b/Flist.ariane @@ -95,6 +95,7 @@ core/mmu_sv39x4/ptw_sv39x4.sv core/ariane_regfile_ff.sv core/re_name.sv core/scoreboard.sv +core/raw_checker.sv core/store_buffer.sv core/amo_buffer.sv core/store_unit.sv diff --git a/core/Flist.cva6 b/core/Flist.cva6 index 17cb6ae98..c2b2a6f7b 100644 --- a/core/Flist.cva6 +++ b/core/Flist.cva6 @@ -132,6 +132,7 @@ ${CVA6_REPO_DIR}/core/ariane_regfile_ff.sv ${CVA6_REPO_DIR}/core/ariane_regfile_fpga.sv // NOTE: scoreboard.sv modified for DSIM (unchanged for other simulators) ${CVA6_REPO_DIR}/core/scoreboard.sv +${CVA6_REPO_DIR}/core/raw_checker.sv ${CVA6_REPO_DIR}/core/store_buffer.sv ${CVA6_REPO_DIR}/core/amo_buffer.sv ${CVA6_REPO_DIR}/core/store_unit.sv diff --git a/core/include/build_config_pkg.sv b/core/include/build_config_pkg.sv index e40ad5c98..3047f526b 100644 --- a/core/include/build_config_pkg.sv +++ b/core/include/build_config_pkg.sv @@ -101,6 +101,7 @@ package build_config_pkg; cfg.HaltAddress = CVA6Cfg.HaltAddress; cfg.ExceptionAddress = CVA6Cfg.ExceptionAddress; + cfg.Renaming = CVA6Cfg.Renaming; cfg.RASDepth = CVA6Cfg.RASDepth; cfg.BTBEntries = CVA6Cfg.BTBEntries; cfg.BPType = CVA6Cfg.BPType; diff --git a/core/include/config_pkg.sv b/core/include/config_pkg.sv index c6a5f2308..b506f78cc 100644 --- a/core/include/config_pkg.sv +++ b/core/include/config_pkg.sv @@ -216,6 +216,8 @@ package config_pkg; int unsigned NrLoadBufEntries; // Maximum number of outstanding stores int unsigned MaxOutstandingStores; + // Eliminate WAW hazards + bit Renaming; // Return address stack depth int unsigned RASDepth; // Branch target buffer entries @@ -307,6 +309,7 @@ package config_pkg; logic [63:0] HaltAddress; logic [63:0] ExceptionAddress; + bit Renaming; int unsigned RASDepth; int unsigned BTBEntries; bp_type_t BPType; diff --git a/core/include/cv32a60x_config_pkg.sv b/core/include/cv32a60x_config_pkg.sv index c11553878..d2e4e8d6f 100644 --- a/core/include/cv32a60x_config_pkg.sv +++ b/core/include/cv32a60x_config_pkg.sv @@ -60,6 +60,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(0), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(1), RASDepth: unsigned'(2), BTBEntries: unsigned'(0), BPType: config_pkg::BHT, diff --git a/core/include/cv32a65x_config_pkg.sv b/core/include/cv32a65x_config_pkg.sv index d3c530a6c..07f7599b0 100644 --- a/core/include/cv32a65x_config_pkg.sv +++ b/core/include/cv32a65x_config_pkg.sv @@ -60,6 +60,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(0), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(1), RASDepth: unsigned'(2), BTBEntries: unsigned'(0), BPType: config_pkg::BHT, diff --git a/core/include/cv32a6_embedded_config_pkg_deprecated.sv b/core/include/cv32a6_embedded_config_pkg_deprecated.sv index 1c8088dc7..9bfbcc7c0 100644 --- a/core/include/cv32a6_embedded_config_pkg_deprecated.sv +++ b/core/include/cv32a6_embedded_config_pkg_deprecated.sv @@ -115,6 +115,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv index fcaa03fd2..9cede65b3 100644 --- a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv +++ b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv @@ -113,6 +113,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv32a6_imac_sv0_config_pkg.sv b/core/include/cv32a6_imac_sv0_config_pkg.sv index 7ffc90f99..1b2190d43 100644 --- a/core/include/cv32a6_imac_sv0_config_pkg.sv +++ b/core/include/cv32a6_imac_sv0_config_pkg.sv @@ -113,6 +113,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv32a6_imac_sv32_config_pkg.sv b/core/include/cv32a6_imac_sv32_config_pkg.sv index 382c1afcf..ec9dd0fe6 100644 --- a/core/include/cv32a6_imac_sv32_config_pkg.sv +++ b/core/include/cv32a6_imac_sv32_config_pkg.sv @@ -112,6 +112,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv32a6_imafc_sv32_config_pkg.sv b/core/include/cv32a6_imafc_sv32_config_pkg.sv index 4250eac32..62123dff2 100644 --- a/core/include/cv32a6_imafc_sv32_config_pkg.sv +++ b/core/include/cv32a6_imafc_sv32_config_pkg.sv @@ -113,6 +113,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv index d316183a4..6658e098c 100644 --- a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv +++ b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdc_sv39_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_config_pkg.sv index 46e8479ef..4b0e7e76b 100644 --- a/core/include/cv64a6_imafdc_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv index 8bc91135b..fe5c0092a 100644 --- a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv @@ -123,6 +123,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdc_sv39_hpdcache_wb_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_hpdcache_wb_config_pkg.sv index 385ef9046..638c14717 100644 --- a/core/include/cv64a6_imafdc_sv39_hpdcache_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_hpdcache_wb_config_pkg.sv @@ -123,6 +123,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv index c689073b0..28ea427db 100644 --- a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv index 53c92fe8e..475c2db23 100644 --- a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdch_sv39_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_config_pkg.sv index a3f97af2f..2d4f9a472 100644 --- a/core/include/cv64a6_imafdch_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv index c92bf35b6..17e236ca9 100644 --- a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv @@ -116,6 +116,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv index c04cd4fae..2aee8edbc 100644 --- a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv @@ -118,6 +118,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(CVA6ConfigRASDepth), BTBEntries: unsigned'(CVA6ConfigBTBEntries), BPType: config_pkg::BHT, diff --git a/core/include/cv64a6_mmu_config_pkg.sv b/core/include/cv64a6_mmu_config_pkg.sv index c52f8f829..1ea09081b 100644 --- a/core/include/cv64a6_mmu_config_pkg.sv +++ b/core/include/cv64a6_mmu_config_pkg.sv @@ -67,6 +67,7 @@ package cva6_config_pkg; SoftwareInterruptEn: bit'(1), HaltAddress: 64'h800, ExceptionAddress: 64'h808, + Renaming: bit'(0), RASDepth: unsigned'(2), BTBEntries: unsigned'(0), BPType: config_pkg::BHT, diff --git a/core/issue_read_operands.sv b/core/issue_read_operands.sv index 8f70016f0..dc8904cb0 100644 --- a/core/issue_read_operands.sv +++ b/core/issue_read_operands.sv @@ -165,21 +165,39 @@ module issue_read_operands logic [31:0] cvxif_off_instr_n, cvxif_off_instr_q; logic cvxif_instruction_valid; + //RAW detection + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.TRANS_ID_BITS-1:0] idx_hzd_rs1; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs1_has_raw; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs1_fpr; + + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.TRANS_ID_BITS-1:0] idx_hzd_rs2; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs2_has_raw; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs2_fpr; + + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.TRANS_ID_BITS-1:0] idx_hzd_rs3; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs3_has_raw; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs3_fpr; + + + logic [CVA6Cfg.NR_SB_ENTRIES-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] rd_list; + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] rd_fpr; + //fwd logic - logic [CVA6Cfg.NrIssuePorts-1:0] rs1_has_raw; - logic [CVA6Cfg.NrIssuePorts-1:0] rs2_has_raw; - logic [CVA6Cfg.NrIssuePorts-1:0] rs3_has_raw; + logic [CVA6Cfg.NR_SB_ENTRIES-1:0][ CVA6Cfg.XLEN-1:0] fwd_res; + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] fwd_res_valid; - logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs3; - logic [CVA6Cfg.NrIssuePorts-1:0] rs3_fpr; + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] rs1_is_not_csr; + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] rs2_is_not_csr; - logic [CVA6Cfg.NrIssuePorts-1:0] rs1_valid; - logic [CVA6Cfg.NrIssuePorts-1:0] rs2_valid; - logic [CVA6Cfg.NrIssuePorts-1:0] rs3_valid; + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs3; - logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs1_res; - logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs2_res; - logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs3_res; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs1_valid; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs2_valid; + logic [ CVA6Cfg.NrIssuePorts-1:0] rs3_valid; + + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs1_res; + logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs2_res; + 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; @@ -408,226 +426,350 @@ module issue_read_operands end end - // ------------------- - // RD clobber process - // ------------------- - // rd_clobber output: output currently clobbered destination registers - - 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[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 - - 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; - end - - // GPR[0] is always free - gpr_clobber_vld[0] = '0; + for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin + assign rs1_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(issue_instr_i[i].op)); + assign rs2_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(issue_instr_i[i].op)); + assign rs3_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_i[i].op)); 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 + if (CVA6Cfg.Renaming) begin + assign rd_clobber_gpr = '0; + assign rd_clobber_fpr = '0; + assign gpr_clobber_vld = '0; + assign fpr_clobber_vld = '0; + assign clobber_fu = '0; + assign rs1_fwd_req = '0; + assign rs2_fwd_req = '0; + assign rs3_fwd_req = '0; + assign rs1_is_not_gpr0 = '0; + assign rs2_is_not_gpr0 = '0; + assign rs3_is_not_gpr0 = '0; + assign rs_data = '0; + assign rs1_available = '0; + assign rs2_available = '0; + assign rs3_available = '0; + + // ---------------------------------- + // Renaming + // ---------------------------------- + for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin + assign rd_list[i] = fwd_i.sbe[i].rd; + assign rd_fpr[i] = CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(fwd_i.sbe[i].op); + end + + for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin : gen_raw_checks + raw_checker #( + .CVA6Cfg(CVA6Cfg) + ) i_rs1_last_raw ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .rs_i(issue_instr_i[i].rs1), + .rs_fpr_i(rs1_fpr[i]), + .rd_i(rd_list), + .rd_fpr_i(rd_fpr), + .still_issued_i(fwd_i.still_issued), + .issue_pointer_i(fwd_i.issue_pointer), + .idx_o(idx_hzd_rs1[i]), + .valid_o(rs1_has_raw[i]) + ); + + raw_checker #( + .CVA6Cfg(CVA6Cfg) + ) i_rs2_last_raw ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .rs_i(issue_instr_i[i].rs2), + .rs_fpr_i(rs2_fpr[i]), + .rd_i(rd_list), + .rd_fpr_i(rd_fpr), + .still_issued_i(fwd_i.still_issued), + .issue_pointer_i(fwd_i.issue_pointer), + .idx_o(idx_hzd_rs2[i]), + .valid_o(rs2_has_raw[i]) + ); + + raw_checker #( + .CVA6Cfg(CVA6Cfg) + ) i_rs3_last_raw ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .rs_i(issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]), + .rs_fpr_i(rs3_fpr[i]), + .rd_i(rd_list), + .rd_fpr_i(rd_fpr), + .still_issued_i(fwd_i.still_issued), + .issue_pointer_i(fwd_i.issue_pointer), + .idx_o(idx_hzd_rs3[i]), + .valid_o(rs3_has_raw[i]) + ); + end + + // ---------------------------------- + // Read Operands (a.k.a forwarding) + // ---------------------------------- + always_comb begin + for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin + fwd_res[i] = fwd_i.sbe[i].result; + fwd_res_valid[i] = fwd_i.sbe[i].valid; + end + for (int unsigned i = 0; i < CVA6Cfg.NrWbPorts; i++) begin + if (fwd_i.wb[i].valid && !fwd_i.wb[i].ex_valid) begin + fwd_res[fwd_i.wb[i].trans_id] = fwd_i.wb[i].data; + fwd_res_valid[fwd_i.wb[i].trans_id] = 1'b1; + end + end + end + + for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin + + assign rs1_res[i] = fwd_res[idx_hzd_rs1[i]]; + assign rs1_is_not_csr[i] = rs1_fpr[i] || (fwd_i.sbe[idx_hzd_rs1[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA); + assign rs1_valid[i] = fwd_res_valid[idx_hzd_rs1[i]] && rs1_is_not_csr[i]; + + assign rs2_res[i] = fwd_res[idx_hzd_rs2[i]]; + assign rs2_is_not_csr[i] = rs2_fpr[i] || (fwd_i.sbe[idx_hzd_rs2[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA); + assign rs2_valid[i] = fwd_res_valid[idx_hzd_rs2[i]] && rs2_is_not_csr[i]; + + assign rs3[i] = fwd_res[idx_hzd_rs3[i]]; + assign rs3_valid[i] = fwd_res_valid[idx_hzd_rs3[i]]; + + if (CVA6Cfg.NrRgprPorts == 3) begin + assign rs3_res[i] = rs3[i][CVA6Cfg.XLEN-1:0]; + end else begin + assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0]; + end + end + + end else begin + assign idx_hzd_rs1 = '0; + assign idx_hzd_rs2 = '0; + assign idx_hzd_rs3 = '0; + assign rd_list = '0; + assign rd_fpr = '0; + assign fwd_res = '0; + assign fwd_res_valid = '0; + assign rs1_is_not_csr = '0; + assign rs2_is_not_csr = '0; + + // ------------------- + // RD clobber process + // ------------------- + // rd_clobber output: output currently clobbered destination registers + + 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[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 + + 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; + 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_fpr_clobbers ( + ) i_sel_gpr_clobbers ( .clk_i (clk_i), .rst_ni (rst_ni), .flush_i(1'b0), .rr_i ('0), - .req_i (fpr_clobber_vld[k]), + .req_i (gpr_clobber_vld[k]), .gnt_o (), .data_i (clobber_fu), .gnt_i (1'b1), .req_o (), - .data_o (rd_clobber_fpr[k]), + .data_o (rd_clobber_gpr[k]), .idx_o () ); - end else begin - assign rd_clobber_fpr[k] = NONE; - end - end - - // ---------------------------------- - // Read Operands (a.k.a forwarding) - // ---------------------------------- - // read operand interface: same logic as register file - - // WB ports have higher prio than entries - 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( - 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( - 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( - issue_instr_i[i].op - ))); - - assign rs_data[i][k] = fwd_i.wb[k].data; + 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 end - for (genvar k = 0; unsigned'(k) < CVA6Cfg.NR_SB_ENTRIES; k++) begin : gen_rs_entries + // ---------------------------------- + // Read Operands (a.k.a forwarding) + // ---------------------------------- + // read operand interface: same logic as register file - 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( + // WB ports have higher prio than entries + 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( + 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( + 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( + issue_instr_i[i].op + ))); + + 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( + 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( + 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( + issue_instr_i[i].op + ))); + + assign rs_data[i][k+CVA6Cfg.NrWbPorts] = fwd_i.sbe[k].result; + end + + // use fixed prio here + // this implicitly gives higher prio to WB ports + rr_arb_tree #( + .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), + .DataWidth(CVA6Cfg.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[i]), + .gnt_o (), + .data_i (rs_data[i]), + .gnt_i (1'b1), + .req_o (rs1_available[i]), + .data_o (rs1_res[i]), + .idx_o () + ); + + rr_arb_tree #( + .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), + .DataWidth(CVA6Cfg.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[i]), + .gnt_o (), + .data_i (rs_data[i]), + .gnt_i (1'b1), + .req_o (rs2_available[i]), + .data_o (rs2_res[i]), + .idx_o () + ); + + + rr_arb_tree #( + .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), + .DataWidth(CVA6Cfg.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[i]), + .gnt_o (), + .data_i (rs_data[i]), + .gnt_i (1'b1), + .req_o (rs3_available[i]), + .data_o (rs3[i]), + .idx_o () + ); + + if (CVA6Cfg.NrRgprPorts == 3) begin : gen_gp_three_port + assign rs3_res[i] = rs3[i][riscv::XLEN-1:0]; + end else begin : gen_fp_three_port + assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0]; + end + + 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); - 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( + 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) || + (CVA6Cfg.RVS && issue_instr_i[i].op == SFENCE_VMA))); - 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( + 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); - assign rs_data[i][k+CVA6Cfg.NrWbPorts] = fwd_i.sbe[k].result; + 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) || + (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); + + assign rs3_valid[i] = rs3_available[i]; end - - // use fixed prio here - // this implicitly gives higher prio to WB ports - rr_arb_tree #( - .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), - .DataWidth(CVA6Cfg.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[i]), - .gnt_o (), - .data_i (rs_data[i]), - .gnt_i (1'b1), - .req_o (rs1_available[i]), - .data_o (rs1_res[i]), - .idx_o () - ); - - rr_arb_tree #( - .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), - .DataWidth(CVA6Cfg.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[i]), - .gnt_o (), - .data_i (rs_data[i]), - .gnt_i (1'b1), - .req_o (rs2_available[i]), - .data_o (rs2_res[i]), - .idx_o () - ); - - - rr_arb_tree #( - .NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts), - .DataWidth(CVA6Cfg.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[i]), - .gnt_o (), - .data_i (rs_data[i]), - .gnt_i (1'b1), - .req_o (rs3_available[i]), - .data_o (rs3[i]), - .idx_o () - ); - - if (CVA6Cfg.NrRgprPorts == 3) begin : gen_gp_three_port - assign rs3_res[i] = rs3[i][riscv::XLEN-1:0]; - end else begin : gen_fp_three_port - assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0]; - end - - 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); - - 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) || - (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); - - 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) || - (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); - - assign rs3_valid[i] = rs3_available[i]; - assign rs3_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_i[i].op)); - end // --------------- @@ -902,33 +1044,37 @@ 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.Renaming) begin + assign stall_waw = '0; + end else begin + 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 - )) ? (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 + )) ? (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 - 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; + // 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 diff --git a/core/raw_checker.sv b/core/raw_checker.sv new file mode 100644 index 000000000..35bacf398 --- /dev/null +++ b/core/raw_checker.sv @@ -0,0 +1,121 @@ +// Copyright 2024 Thales DIS France SAS +// +// Licensed under the Solderpad Hardware Licence, Version 0.51 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Junheng Zheng - Thales + +module raw_checker + import ariane_pkg::*; +#( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty +) ( + // Subsystem Clock - SUBSYSTEM + input logic clk_i, + // Asynchronous reset active low - SUBSYSTEM + input logic rst_ni, + // Register source of the instruction to check RAW dependancies - SCOREBOARD + input logic [REG_ADDR_SIZE-1:0] rs_i, + // Type of register source (FPR or GPR) - SCOREBOARD + input logic rs_fpr_i, + // Registers of destination of the instructions already issued in the scoreboard - SCOREBOARD + input logic [CVA6Cfg.NR_SB_ENTRIES-1:0][REG_ADDR_SIZE-1:0] rd_i, + // Type of registers of destination (FPR or GPR) - SCOREBOARD + input logic [CVA6Cfg.NR_SB_ENTRIES-1:0] rd_fpr_i, + // Instructions in the scoreboard are still issued - SCOREBOARD + input logic [CVA6Cfg.NR_SB_ENTRIES-1:0] still_issued_i, + // Issue pointer - SCOREBOARD + input logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_i, + + // Index in the scoreboard of the most recent RAW dependancy - SCOREBOARD + output logic [CVA6Cfg.TRANS_ID_BITS-1:0] idx_o, + // Indicates if there is a RAW dependancy - SCOREBOARD + output logic valid_o +); + + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] same_rd_as_rs; + + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] same_rd_as_rs_before; + logic last_before_valid; + logic [CVA6Cfg.TRANS_ID_BITS-1:0] last_before_idx; + + logic [CVA6Cfg.NR_SB_ENTRIES-1:0] same_rd_as_rs_after; + logic last_after_valid; + logic [CVA6Cfg.TRANS_ID_BITS-1:0] last_after_idx; + + logic valid; + logic rs_is_gpr0; + + for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin + assign same_rd_as_rs[i] = (rs_fpr_i == rd_fpr_i[i]) && (rs_i == rd_i[i]) && still_issued_i[i]; + assign same_rd_as_rs_before[i] = (i < issue_pointer_i) && same_rd_as_rs[i]; + assign same_rd_as_rs_after[i] = (i >= issue_pointer_i) && same_rd_as_rs[i]; + end + + //Last finders + // for instructions < instruction pointer + rr_arb_tree #( + .NumIn(CVA6Cfg.NR_SB_ENTRIES), + .DataWidth(1), + .ExtPrio(1'b1), + .AxiVldRdy(1'b1) + ) i_last_finder_before ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i(1'b0), + .rr_i ('1), // Highest index has highest prio. + .req_i (same_rd_as_rs_before), + .gnt_o (), + .data_i ('0), + .gnt_i (1'b1), + .req_o (last_before_valid), + .data_o (), + .idx_o (last_before_idx) + ); + + // for instructions >= instruction pointer + rr_arb_tree #( + .NumIn(CVA6Cfg.NR_SB_ENTRIES), + .DataWidth(1), + .ExtPrio(1'b1), + .AxiVldRdy(1'b1) + ) i_last_finder_after ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i(1'b0), + .rr_i ('1), // Highest index has highest prio. + .req_i (same_rd_as_rs_after), + .gnt_o (), + .data_i ('0), + .gnt_i (1'b1), + .req_o (last_after_valid), + .data_o (), + .idx_o (last_after_idx) + ); + + // take the minimum of the last indexes + rr_arb_tree #( + .NumIn(2), + .DataWidth(CVA6Cfg.TRANS_ID_BITS), + .ExtPrio(1'b1), + .AxiVldRdy(1'b1) + ) min_finder ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i(1'b0), + .rr_i ('0), // Lowest index has highest prio. + .req_i ({last_after_valid,last_before_valid}), + .gnt_o (), + .data_i ({last_after_idx,last_before_idx}), + .gnt_i (1'b1), + .req_o (valid), + .data_o (idx_o), + .idx_o () + ); + + assign rs_is_gpr0 = (rs_i == '0) && !rs_fpr_i; + assign valid_o = valid && !rs_is_gpr0; + +endmodule