From 52f206f917bfb81925f0f82e18f1f5dd459dd989 Mon Sep 17 00:00:00 2001 From: Alae Eddine Ez zejjari Date: Thu, 31 Aug 2023 12:00:03 +0200 Subject: [PATCH] Code_coverage: Add conditions for the FPU Signed-off-by: Alae Eddine Ez zejjari --- core/commit_stage.sv | 20 ++++--- core/csr_regfile.sv | 50 ++++++++-------- core/cva6.sv | 3 +- core/include/ariane_pkg.sv | 112 +++++++++++++----------------------- core/issue_read_operands.sv | 51 +++++++++------- core/load_unit.sv | 22 ++++++- core/scoreboard.sv | 63 ++++++++++---------- 7 files changed, 159 insertions(+), 162 deletions(-) diff --git a/core/commit_stage.sv b/core/commit_stage.sv index 62018600c08..9638433c457 100644 --- a/core/commit_stage.sv +++ b/core/commit_stage.sv @@ -77,7 +77,7 @@ module commit_stage import ariane_pkg::*; #( always_comb begin : dirty_fp_state dirty_fp_state_o = 1'b0; for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin - dirty_fp_state_o |= commit_ack_o[i] & (commit_instr_i[i].fu inside {FPU, FPU_VEC} || ariane_pkg::is_rd_fpr_cfg(commit_instr_i[i].op, CVA6Cfg.FpPresent)); + dirty_fp_state_o |= commit_ack_o[i] & (commit_instr_i[i].fu inside {FPU, FPU_VEC} || (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[i].op))); // Check if we issued a vector floating-point instruction to the accellerator dirty_fp_state_o |= commit_instr_i[i].fu == ACCEL && commit_instr_i[i].vfp; end @@ -117,7 +117,7 @@ module commit_stage import ariane_pkg::*; #( // we can definitely write the register file // if the instruction is not committing anything the destination commit_ack_o[0] = 1'b1; - if (ariane_pkg::is_rd_fpr_cfg(commit_instr_i[0].op, CVA6Cfg.FpPresent)) begin + if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[0].op)) begin we_fpr_o[0] = 1'b1; end else begin we_gpr_o[0] = 1'b1; @@ -136,11 +136,13 @@ module commit_stage import ariane_pkg::*; #( // --------- // FPU Flags // --------- - if (commit_instr_i[0].fu inside {FPU, FPU_VEC}) begin - // write the CSR with potential exception flags from retiring floating point instruction - csr_wdata_o = {{riscv::XLEN-5{1'b0}}, commit_instr_i[0].ex.cause[4:0]}; - csr_write_fflags_o = 1'b1; - commit_ack_o[0] = 1'b1; + if(CVA6Cfg.FpPresent) begin + if (commit_instr_i[0].fu inside {FPU, FPU_VEC}) begin + // write the CSR with potential exception flags from retiring floating point instruction + csr_wdata_o = {{riscv::XLEN-5{1'b0}}, commit_instr_i[0].ex.cause[4:0]}; + csr_write_fflags_o = 1'b1; + commit_ack_o[0] = 1'b1; + end end // --------- // CSR Logic @@ -229,7 +231,7 @@ module commit_stage import ariane_pkg::*; #( if (!exception_o.valid && !commit_instr_i[1].ex.valid && (commit_instr_i[1].fu inside {ALU, LOAD, CTRL_FLOW, MULT, FPU, FPU_VEC})) begin - if (ariane_pkg::is_rd_fpr_cfg(commit_instr_i[1].op, CVA6Cfg.FpPresent)) + if (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_i[1].op)) we_fpr_o[1] = 1'b1; else we_gpr_o[1] = 1'b1; @@ -238,7 +240,7 @@ module commit_stage import ariane_pkg::*; #( // additionally check if we are retiring an FPU instruction because we need to make sure that we write all // exception flags - if (commit_instr_i[1].fu inside {FPU, FPU_VEC}) begin + if (CVA6Cfg.FpPresent && commit_instr_i[1].fu inside {FPU, FPU_VEC}) begin if (csr_write_fflags_o) csr_wdata_o = {{riscv::XLEN-5{1'b0}}, (commit_instr_i[0].ex.cause[4:0] | commit_instr_i[1].ex.cause[4:0])}; else diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 7fb1c470267..91da44fc544 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -195,32 +195,32 @@ module csr_regfile import ariane_pkg::*; #( if (csr_read) begin unique case (csr_addr.address) riscv::CSR_FFLAGS: begin - if (mstatus_q.fs == riscv::Off) begin - read_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin csr_rdata = {{riscv::XLEN-5{1'b0}}, fcsr_q.fflags}; + end else begin + read_access_exception = 1'b1; end end riscv::CSR_FRM: begin - if (mstatus_q.fs == riscv::Off) begin - read_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin csr_rdata = {{riscv::XLEN-3{1'b0}}, fcsr_q.frm}; + end else begin + read_access_exception = 1'b1; end end riscv::CSR_FCSR: begin - if (mstatus_q.fs == riscv::Off) begin - read_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin csr_rdata = {{riscv::XLEN-8{1'b0}}, fcsr_q.frm, fcsr_q.fflags}; + end else begin + read_access_exception = 1'b1; end end // non-standard extension riscv::CSR_FTRAN: begin - if (mstatus_q.fs == riscv::Off) begin - read_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin csr_rdata = {{riscv::XLEN-7{1'b0}}, fcsr_q.fprec}; + end else begin + read_access_exception = 1'b1; end end // debug registers @@ -574,43 +574,43 @@ module csr_regfile import ariane_pkg::*; #( unique case (csr_addr.address) // Floating-Point riscv::CSR_FFLAGS: begin - if (mstatus_q.fs == riscv::Off) begin - update_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin dirty_fp_state_csr = 1'b1; fcsr_d.fflags = csr_wdata[4:0]; // this instruction has side-effects flush_o = 1'b1; + end else begin + update_access_exception = 1'b1; end end riscv::CSR_FRM: begin - if (mstatus_q.fs == riscv::Off) begin - update_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin dirty_fp_state_csr = 1'b1; fcsr_d.frm = csr_wdata[2:0]; // this instruction has side-effects flush_o = 1'b1; + end else begin + update_access_exception = 1'b1; end end riscv::CSR_FCSR: begin - if (mstatus_q.fs == riscv::Off) begin - update_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin dirty_fp_state_csr = 1'b1; fcsr_d[7:0] = csr_wdata[7:0]; // ignore writes to reserved space // this instruction has side-effects flush_o = 1'b1; + end else begin + update_access_exception = 1'b1; end end riscv::CSR_FTRAN: begin - if (mstatus_q.fs == riscv::Off) begin - update_access_exception = 1'b1; - end else begin + if(CVA6Cfg.FpPresent) begin dirty_fp_state_csr = 1'b1; fcsr_d.fprec = csr_wdata[6:0]; // ignore writes to reserved space // this instruction has side-effects flush_o = 1'b1; + end else begin + update_access_exception = 1'b1; end end // debug CSR @@ -912,7 +912,7 @@ module csr_regfile import ariane_pkg::*; #( for (int i = 0; i < NrPMPEntries; i++) pmpcfg_d[i].reserved = 2'b0; // write the floating point status register - if (csr_write_fflags_i) begin + if (CVA6Cfg.FpPresent && csr_write_fflags_i) begin fcsr_d.fflags = csr_wdata_i[4:0] | fcsr_q.fflags; end diff --git a/core/cva6.sv b/core/cva6.sv index 216018f2f27..2fe72b2efb7 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -1261,7 +1261,8 @@ module cva6 import ariane_pkg::*; #( rvfi_o[i].rs1_addr = commit_instr_id_commit[i].rs1[4:0]; rvfi_o[i].rs2_addr = commit_instr_id_commit[i].rs2[4:0]; rvfi_o[i].rd_addr = commit_instr_id_commit[i].rd[4:0]; - rvfi_o[i].rd_wdata = ariane_pkg::is_rd_fpr_cfg(commit_instr_id_commit[i].op, CVA6ExtendCfg.FpPresent) == 0 ? wdata_commit_id[i] : commit_instr_id_commit[i].result; + rvfi_o[i].rd_wdata = (CVA6ExtendCfg.FpPresent && ariane_pkg::is_rd_fpr(commit_instr_id_commit[i].op) == 0) ? wdata_commit_id[i] : commit_instr_id_commit[i].result; + rvfi_o[i].pc_rdata = commit_instr_id_commit[i].pc; rvfi_o[i].mem_addr = commit_instr_id_commit[i].lsu_addr; diff --git a/core/include/ariane_pkg.sv b/core/include/ariane_pkg.sv index 2d7e2b330d0..244f9aa5741 100644 --- a/core/include/ariane_pkg.sv +++ b/core/include/ariane_pkg.sv @@ -530,94 +530,62 @@ package ariane_pkg; // function used in instr_trace svh // is_rs1_fpr function is kept to allow cva6 compilation with instr_trace feature function automatic logic is_rs1_fpr (input fu_op op); - return is_rs1_fpr_cfg (op, 1); - endfunction - - function automatic logic is_rs1_fpr_cfg (input fu_op op, input bit FpPresent); - if (FpPresent) begin - unique case (op) inside - [FMUL:FNMADD], // Computational Operations (except ADD/SUB) - FCVT_F2I, // Float-Int Casts - FCVT_F2F, // Float-Float Casts - FSGNJ, // Sign Injections - FMV_F2X, // FPR-GPR Moves - FCMP, // Comparisons - FCLASS, // Classifications - [VFMIN:VFCPKCD_D], // Additional Vectorial FP ops - ACCEL_OP_FS1 : return 1'b1; // Accelerator instructions - default : return 1'b0; // all other ops - endcase - end else begin - return 1'b0; - end + unique case (op) inside + [FMUL:FNMADD], // Computational Operations (except ADD/SUB) + FCVT_F2I, // Float-Int Casts + FCVT_F2F, // Float-Float Casts + FSGNJ, // Sign Injections + FMV_F2X, // FPR-GPR Moves + FCMP, // Comparisons + FCLASS, // Classifications + [VFMIN:VFCPKCD_D], // Additional Vectorial FP ops + ACCEL_OP_FS1 : return 1'b1; // Accelerator instructions + default : return 1'b0; // all other ops + endcase endfunction // function used in instr_trace svh // is_rs2_fpr function is kept to allow cva6 compilation with instr_trace feature function automatic logic is_rs2_fpr (input fu_op op); - return is_rs2_fpr_cfg (op, 1); - endfunction - - function automatic logic is_rs2_fpr_cfg (input fu_op op, input bit FpPresent); - if (FpPresent) begin - unique case (op) inside - [FSD:FSB], // FP Stores - [FADD:FMIN_MAX], // Computational Operations (no sqrt) - [FMADD:FNMADD], // Fused Computational Operations - FCVT_F2F, // Vectorial F2F Conversions requrie target - [FSGNJ:FMV_F2X], // Sign Injections and moves mapped to SGNJ - FCMP, // Comparisons - [VFMIN:VFCPKCD_D] : return 1'b1; // Additional Vectorial FP ops - default : return 1'b0; // all other ops - endcase - end else begin - return 1'b0; - end + unique case (op) inside + [FSD:FSB], // FP Stores + [FADD:FMIN_MAX], // Computational Operations (no sqrt) + [FMADD:FNMADD], // Fused Computational Operations + FCVT_F2F, // Vectorial F2F Conversions requrie target + [FSGNJ:FMV_F2X], // Sign Injections and moves mapped to SGNJ + FCMP, // Comparisons + [VFMIN:VFCPKCD_D] : return 1'b1; // Additional Vectorial FP ops + default : return 1'b0; // all other ops + endcase endfunction // function used in instr_trace svh // is_imm_fpr function is kept to allow cva6 compilation with instr_trace feature // ternary operations encode the rs3 address in the imm field, also add/sub function automatic logic is_imm_fpr (input fu_op op); - return is_imm_fpr_cfg (op, 1); - endfunction - - function automatic logic is_imm_fpr_cfg (input fu_op op, input bit FpPresent); - if (FpPresent) begin - unique case (op) inside - [FADD:FSUB], // ADD/SUB need inputs as Operand B/C - [FMADD:FNMADD], // Fused Computational Operations - [VFCPKAB_S:VFCPKCD_D] : return 1'b1; // Vectorial FP cast and pack ops - default : return 1'b0; // all other ops - endcase - end else begin - return 1'b0; - end + unique case (op) inside + [FADD:FSUB], // ADD/SUB need inputs as Operand B/C + [FMADD:FNMADD], // Fused Computational Operations + [VFCPKAB_S:VFCPKCD_D] : return 1'b1; // Vectorial FP cast and pack ops + default : return 1'b0; // all other ops + endcase endfunction // function used in instr_trace svh // is_rd_fpr function is kept to allow cva6 compilation with instr_trace feature function automatic logic is_rd_fpr (input fu_op op); - return is_rd_fpr_cfg (op, 1); - endfunction - - function automatic logic is_rd_fpr_cfg (input fu_op op, input bit FpPresent); - if (FpPresent) begin - unique case (op) inside - [FLD:FLB], // FP Loads - [FADD:FNMADD], // Computational Operations - FCVT_I2F, // Int-Float Casts - FCVT_F2F, // Float-Float Casts - FSGNJ, // Sign Injections - FMV_X2F, // GPR-FPR Moves - [VFMIN:VFSGNJX], // Vectorial MIN/MAX and SGNJ - [VFCPKAB_S:VFCPKCD_D], // Vectorial FP cast and pack ops - ACCEL_OP_FD : return 1'b1; // Accelerator instructions - default : return 1'b0; // all other ops - endcase - end else begin - return 1'b0; - end + unique case (op) inside + [FLD:FLB], // FP Loads + [FADD:FNMADD], // Computational Operations + FCVT_I2F, // Int-Float Casts + FCVT_F2F, // Float-Float Casts + FSGNJ, // Sign Injections + FMV_X2F, // GPR-FPR Moves + [VFMIN:VFSGNJX], // Vectorial MIN/MAX and SGNJ + [VFCPKAB_S:VFCPKCD_D], // Vectorial FP cast and pack ops + ACCEL_OP_FD : return 1'b1; // Accelerator instructions + default : return 1'b0; // all other ops + endcase endfunction function automatic logic is_amo (fu_op op); diff --git a/core/issue_read_operands.sv b/core/issue_read_operands.sv index 43b0b2f278a..3962af0c33d 100644 --- a/core/issue_read_operands.sv +++ b/core/issue_read_operands.sv @@ -147,7 +147,9 @@ module issue_read_operands import ariane_pkg::*; #( ALU, CTRL_FLOW, CSR, MULT: fu_busy = ~flu_ready_i; FPU, FPU_VEC: - fu_busy = ~fpu_ready_i; + if(CVA6Cfg.FpPresent) begin + fu_busy = ~fpu_ready_i; + end LOAD, STORE: fu_busy = ~lsu_ready_i; CVXIF: @@ -177,22 +179,22 @@ module issue_read_operands import ariane_pkg::*; #( // as this is an immediate we do not have to wait on anything here // 1. check if the source registers are clobbered --> check appropriate clobber list (gpr/fpr) // 2. poll the scoreboard - if (!issue_instr_i.use_zimm && (is_rs1_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? rd_clobber_fpr_i[issue_instr_i.rs1] != NONE + if (!issue_instr_i.use_zimm && ((CVA6Cfg.FpPresent && is_rs1_fpr(issue_instr_i.op)) ? rd_clobber_fpr_i[issue_instr_i.rs1] != NONE : rd_clobber_gpr_i[issue_instr_i.rs1] != NONE)) begin // check if the clobbering instruction is not a CSR instruction, CSR instructions can only // be fetched through the register file since they can't be forwarded // if the operand is available, forward it. CSRs don't write to/from FPR - if (rs1_valid_i && (is_rs1_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? 1'b1 : ((rd_clobber_gpr_i[issue_instr_i.rs1] != CSR) || (issue_instr_i.op == SFENCE_VMA)))) begin + if (rs1_valid_i && (CVA6Cfg.FpPresent && is_rs1_fpr(issue_instr_i.op) ? 1'b1 : ((rd_clobber_gpr_i[issue_instr_i.rs1] != CSR) || (issue_instr_i.op == SFENCE_VMA)))) begin forward_rs1 = 1'b1; end else begin // the operand is not available -> stall stall = 1'b1; end end - if (is_rs2_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? rd_clobber_fpr_i[issue_instr_i.rs2] != NONE + if ((CVA6Cfg.FpPresent && is_rs2_fpr(issue_instr_i.op)) ? rd_clobber_fpr_i[issue_instr_i.rs2] != NONE : rd_clobber_gpr_i[issue_instr_i.rs2] != NONE) begin // if the operand is available, forward it. CSRs don't write to/from FPR - if (rs2_valid_i && (is_rs2_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? 1'b1 : ( (rd_clobber_gpr_i[issue_instr_i.rs2] != CSR) || (issue_instr_i.op == SFENCE_VMA)))) begin + if (rs2_valid_i && (CVA6Cfg.FpPresent && is_rs2_fpr(issue_instr_i.op) ? 1'b1 : ( (rd_clobber_gpr_i[issue_instr_i.rs2] != CSR) || (issue_instr_i.op == SFENCE_VMA)))) begin forward_rs2 = 1'b1; end else begin // the operand is not available -> stall stall = 1'b1; @@ -200,7 +202,7 @@ module issue_read_operands import ariane_pkg::*; #( end // Only check clobbered gpr for OFFLOADED instruction - if (is_imm_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? rd_clobber_fpr_i[issue_instr_i.result[REG_ADDR_SIZE-1:0]] != NONE + if ((CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i.op)) ? rd_clobber_fpr_i[issue_instr_i.result[REG_ADDR_SIZE-1:0]] != NONE : issue_instr_i.op == OFFLOAD && CVA6Cfg.NrRgprPorts == 3 ? rd_clobber_gpr_i[issue_instr_i.result[REG_ADDR_SIZE-1:0]] != NONE : 0) begin // if the operand is available, forward it. CSRs don't write to/from FPR so no need to check if (rs3_valid_i) begin @@ -219,10 +221,10 @@ module issue_read_operands import ariane_pkg::*; #( // immediates are the third operands in the store case // for FP operations, the imm field can also be the third operand from the regfile if (CVA6Cfg.NrRgprPorts == 3) begin - imm_n = is_imm_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, operand_c_regfile} : + imm_n = (CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i.op)) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, operand_c_regfile} : issue_instr_i.op == OFFLOAD ? operand_c_regfile : issue_instr_i.result; end else begin - imm_n = is_imm_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, operand_c_regfile} : issue_instr_i.result; + imm_n = (CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i.op)) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, operand_c_regfile} : issue_instr_i.result; end trans_id_n = issue_instr_i.trans_id; fu_n = issue_instr_i.fu; @@ -252,7 +254,7 @@ module issue_read_operands import ariane_pkg::*; #( end // or is it an immediate (including PC), this is not the case for a store, control flow, and accelerator instructions // also make sure operand B is not already used as an FP operand - if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE) && (issue_instr_i.fu != CTRL_FLOW) && (issue_instr_i.fu != ACCEL) && !is_rs2_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent)) begin + if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE) && (issue_instr_i.fu != CTRL_FLOW) && (issue_instr_i.fu != ACCEL) && !(CVA6Cfg.FpPresent && is_rs2_fpr(issue_instr_i.op))) begin operand_b_n = issue_instr_i.result; end end @@ -293,14 +295,18 @@ module issue_read_operands import ariane_pkg::*; #( mult_valid_q <= 1'b1; end FPU : begin - fpu_valid_q <= 1'b1; - fpu_fmt_q <= orig_instr.rftype.fmt; // fmt bits from instruction - fpu_rm_q <= orig_instr.rftype.rm; // rm bits from instruction + if(CVA6Cfg.FpPresent) begin + fpu_valid_q <= 1'b1; + fpu_fmt_q <= orig_instr.rftype.fmt; // fmt bits from instruction + fpu_rm_q <= orig_instr.rftype.rm; // rm bits from instruction + end end FPU_VEC : begin - fpu_valid_q <= 1'b1; - fpu_fmt_q <= orig_instr.rvftype.vfmt; // vfmt bits from instruction - fpu_rm_q <= {2'b0, orig_instr.rvftype.repl}; // repl bit from instruction + if(CVA6Cfg.FpPresent) begin + fpu_valid_q <= 1'b1; + fpu_fmt_q <= orig_instr.rvftype.vfmt; // vfmt bits from instruction + fpu_rm_q <= {2'b0, orig_instr.rvftype.repl}; // repl bit from instruction + end end LOAD, STORE: begin lsu_valid_q <= 1'b1; @@ -364,17 +370,18 @@ module issue_read_operands import ariane_pkg::*; #( // WAW - Write After Write Dependency Check // ----------------------------------------- // no other instruction has the same destination register -> issue the instruction - if (ariane_pkg::is_rd_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? (rd_clobber_fpr_i[issue_instr_i.rd] == NONE) + if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(issue_instr_i.op)) ? (rd_clobber_fpr_i[issue_instr_i.rd] == NONE) : (rd_clobber_gpr_i[issue_instr_i.rd] == NONE)) begin issue_ack_o = 1'b1; end // or check that the target destination register will be written in this cycle by the // commit stage for (int unsigned i = 0; i < CVA6Cfg.NrCommitPorts; i++) - if (ariane_pkg::is_rd_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? (we_fpr_i[i] && waddr_i[i] == issue_instr_i.rd[4:0]) - : (we_gpr_i[i] && waddr_i[i] == issue_instr_i.rd[4:0])) begin - issue_ack_o = 1'b1; + if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(issue_instr_i.op)) ? (rd_clobber_fpr_i[issue_instr_i.rd] == NONE) + : (rd_clobber_gpr_i[issue_instr_i.rd] == NONE)) begin + issue_ack_o = 1'b1; end + end // we can also issue the instruction under the following two circumstances: // we can do this even if we are stalled or no functional unit is ready (as we don't need one) @@ -496,9 +503,9 @@ module issue_read_operands import ariane_pkg::*; #( end endgenerate - assign operand_a_regfile = is_rs1_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[0]} : rdata[0]; - assign operand_b_regfile = is_rs2_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[1]} : rdata[1]; - assign operand_c_regfile = CVA6Cfg.NrRgprPorts == 3 ? (is_imm_fpr_cfg(issue_instr_i.op, CVA6Cfg.FpPresent) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[2]} : rdata[2]) + assign operand_a_regfile = (CVA6Cfg.FpPresent && is_rs1_fpr(issue_instr_i.op)) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[0]} : rdata[0]; + assign operand_b_regfile = (CVA6Cfg.FpPresent && is_rs2_fpr(issue_instr_i.op)) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[1]} : rdata[1]; + assign operand_c_regfile = CVA6Cfg.NrRgprPorts == 3 ? ((CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i.op)) ? {{riscv::XLEN-CVA6Cfg.FLen{1'b0}}, fprdata[2]} : rdata[2]) : fprdata[2]; // ---------------------- diff --git a/core/load_unit.sv b/core/load_unit.sv index eb858895705..32085d533bb 100644 --- a/core/load_unit.sv +++ b/core/load_unit.sv @@ -455,9 +455,25 @@ module load_unit import ariane_pkg::*; #( // result mux always_comb begin unique case (ldbuf_rdata.operation) - ariane_pkg::LW, ariane_pkg::LWU, ariane_pkg::FLW: result_o = {{riscv::XLEN-32{rdata_sign_bit}}, shifted_data[31:0]}; - ariane_pkg::LH, ariane_pkg::LHU, ariane_pkg::FLH: result_o = {{riscv::XLEN-32+16{rdata_sign_bit}}, shifted_data[15:0]}; - ariane_pkg::LB, ariane_pkg::LBU, ariane_pkg::FLB: result_o = {{riscv::XLEN-32+24{rdata_sign_bit}}, shifted_data[7:0]}; + ariane_pkg::LW, ariane_pkg::LWU: result_o = {{riscv::XLEN-32{rdata_sign_bit}}, shifted_data[31:0]}; + ariane_pkg::LH, ariane_pkg::LHU: result_o = {{riscv::XLEN-32+16{rdata_sign_bit}}, shifted_data[15:0]}; + ariane_pkg::LB, ariane_pkg::LBU: result_o = {{riscv::XLEN-32+24{rdata_sign_bit}}, shifted_data[7:0]}; + ariane_pkg::FLW: begin + if(CVA6Cfg.FpPresent) begin + result_o = {{riscv::XLEN-32{rdata_sign_bit}}, shifted_data[31:0]}; + end + end + ariane_pkg::FLH: begin + if(CVA6Cfg.FpPresent) begin + result_o = {{riscv::XLEN-32+16{rdata_sign_bit}}, shifted_data[15:0]}; + end + end + ariane_pkg::FLB: begin + if(CVA6Cfg.FpPresent) begin + result_o = {{riscv::XLEN-32+24{rdata_sign_bit}}, shifted_data[7:0]}; + end + end + default: result_o = shifted_data[riscv::XLEN-1:0]; endcase end diff --git a/core/scoreboard.sv b/core/scoreboard.sv index 0586cec683a..da94a01cc03 100644 --- a/core/scoreboard.sv +++ b/core/scoreboard.sv @@ -139,7 +139,7 @@ module scoreboard #( // increase the issue counter and advance issue pointer issue_en = 1'b1; mem_n[issue_pointer_q] = {1'b1, // valid bit - ariane_pkg::is_rd_fpr_cfg(decoded_instr_i.op, CVA6Cfg.FpPresent), // whether rd goes to the fpr + (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(decoded_instr_i.op)), // whether rd goes to the fpr decoded_instr // decoded instruction record }; end @@ -182,8 +182,9 @@ module scoreboard #( if (ex_i[i].valid) mem_n[trans_id_i[i]].sbe.ex = ex_i[i]; // write the fflags back from the FPU (exception valid is never set), leave tval intact - else if (mem_q[trans_id_i[i]].sbe.fu inside {ariane_pkg::FPU, ariane_pkg::FPU_VEC}) - mem_n[trans_id_i[i]].sbe.ex.cause = ex_i[i].cause; + else if(CVA6Cfg.FpPresent && mem_q[trans_id_i[i]].sbe.fu inside {ariane_pkg::FPU, ariane_pkg::FPU_VEC}) begin + mem_n[trans_id_i[i]].sbe.ex.cause = ex_i[i].cause; + end end end @@ -274,24 +275,26 @@ module scoreboard #( .data_o ( rd_clobber_gpr_o[k] ), .idx_o ( ) ); - 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 ( ) - ); + if(CVA6Cfg.FpPresent) begin + 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 ( ) + ); + end end // ---------------------------------- @@ -304,22 +307,22 @@ module scoreboard #( // WB ports have higher prio than entries for (genvar k = 0; unsigned'(k) < CVA6Cfg.NrWbPorts; k++) begin : gen_rs_wb - assign rs1_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs1_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == ariane_pkg::is_rs1_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs2_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs2_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == ariane_pkg::is_rs2_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs3_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs3_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == ariane_pkg::is_imm_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); + assign rs1_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs1_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(issue_instr_o.op))); + assign rs2_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs2_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(issue_instr_o.op))); + assign rs3_fwd_req[k] = (mem_q[trans_id_i[k]].sbe.rd == rs3_i) & wt_valid_i[k] & (~ex_i[k].valid) & (mem_q[trans_id_i[k]].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_o.op))); assign rs_data[k] = wbdata_i[k]; end for (genvar k = 0; unsigned'(k) < NR_ENTRIES; k++) begin : gen_rs_entries - assign rs1_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs1_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs1_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs2_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs2_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs2_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs3_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs3_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_imm_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); + assign rs1_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs1_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(issue_instr_o.op))); + assign rs2_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs2_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(issue_instr_o.op))); + assign rs3_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs3_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_o.op))); assign rs_data[k+CVA6Cfg.NrWbPorts] = mem_q[k].sbe.result; end // check whether we are accessing GPR[0] - assign rs1_valid_o = rs1_valid & ((|rs1_i) | ariane_pkg::is_rs1_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs2_valid_o = rs2_valid & ((|rs2_i) | ariane_pkg::is_rs2_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)); - assign rs3_valid_o = CVA6Cfg.NrRgprPorts == 3 ? rs3_valid & ((|rs3_i) | ariane_pkg::is_imm_fpr_cfg(issue_instr_o.op, CVA6Cfg.FpPresent)) : rs3_valid; + assign rs1_valid_o = rs1_valid & ((|rs1_i) | (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(issue_instr_o.op))); + assign rs2_valid_o = rs2_valid & ((|rs2_i) | (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(issue_instr_o.op))); + assign rs3_valid_o = CVA6Cfg.NrRgprPorts == 3 ? rs3_valid & ((|rs3_i) | (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_o.op))) : rs3_valid; // use fixed prio here // this implicitly gives higher prio to WB ports