Code_coverage: Add conditions for the FPU (#1442)

This commit is contained in:
AEzzejjari 2023-09-19 17:24:40 +01:00 committed by GitHub
parent 59863becc7
commit b952b0d7c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 161 deletions

View file

@ -3,4 +3,4 @@ cv64a6_imafdc_sv39:
cv32a60x:
gates: 160719
cv32a6_embedded:
gates: 127763
gates: 127388

View file

@ -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

View file

@ -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

View file

@ -1261,7 +1261,7 @@ 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)) ? commit_instr_id_commit[i].result : wdata_commit_id[i];
rvfi_o[i].pc_rdata = commit_instr_id_commit[i].pc;
rvfi_o[i].mem_addr = commit_instr_id_commit[i].lsu_addr;

View file

@ -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);

View file

@ -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])
if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(issue_instr_i.op)) ? (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;
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];
// ----------------------

View file

@ -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

View file

@ -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