Partial implementation of fcvtmod.w.d; flags disagree in one case where Sail might be wrong, and result 134 is wrong because of overflow

This commit is contained in:
David Harris 2024-01-17 12:25:06 -08:00
parent 4cfc86140c
commit 74b242ce5c
6 changed files with 59 additions and 16 deletions

View File

@ -54,7 +54,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit
output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage
output logic FPUActiveE, // FP instruction being executed
output logic ZfaE, // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod)
output logic ZfaE, ZfaM, // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod)
// register control signals
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
output logic FWriteIntE, FWriteIntM, // Write to integer register
@ -149,7 +149,8 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_0; // fmv.x.w/d/h/q fp to int register
else if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct7D[1:0] == 2'b01 & Funct3D == 3'b000 & Rs2D == 5'b00001)
ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1; // fmvh.x.d (Zfa)
// coverage off Q not supported in RV64GC
// Q not supported in RV64GC
// coverage off
else if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct7D[1:0] == 2'b11 & Funct3D == 3'b000 & Rs2D == 5'b00001)
ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1; // fmvh.x.q (Zfa)
// coverage on
@ -238,11 +239,11 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
endcase
// coverage on
7'b1011001: if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct3D == 3'b000)
ControlsD = '0; // fmvp.d.x (Zfa)
ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fmvp.d.x (Zfa) *** untested, controls could be wrong
// Not covered in testing because rv64gc does not support quad precision
// coverage off
7'b1011011: if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct3D == 3'b000)
ControlsD = '0; // fmvp.q.x (Zfa)
ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fmvp.q.x (Zfa)
// coverage on
endcase
endcase
@ -362,9 +363,9 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
else assign IDivStartE = 0;
// E/M pipleine register
flopenrc #(13+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
{FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE},
{FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, OpCtrlM, FWriteIntM, FCvtIntM});
flopenrc #(14+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
{FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE, ZfaE},
{FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, OpCtrlM, FWriteIntM, FCvtIntM, ZfaM});
// renameing for readability
assign FpLoadStoreM = FResSelM[1];

View File

@ -83,7 +83,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
logic FRegWriteE; // Write floating-point register
logic FPUActiveE; // FP instruction being executed
logic ZfaE; // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod.w.d)
logic ZfaE, ZfaM; // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod.w.d)
// regfile signals
logic [P.FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
@ -171,7 +171,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
fctrl #(P) fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]),
.IntDivE, .InstrD,
.StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, .FRM_REGW, .STATUS_FS, .FDivBusyE,
.reset, .clk, .FRegWriteE, .FRegWriteM, .FRegWriteW, .ZfaE, .FrmM, .FmtE, .FmtM,
.reset, .clk, .FRegWriteE, .FRegWriteM, .FRegWriteW, .ZfaE, .ZfaM, .FrmM, .FmtE, .FmtM,
.FDivStartE, .IDivStartE, .FWriteIntE, .FCvtIntE, .FWriteIntM, .OpCtrlE, .OpCtrlM, .FpLoadStoreM,
.IllegalFPUInstrD, .XEnD, .YEnD, .ZEnD, .XEnE, .YEnE, .ZEnE,
.FResSelE, .FResSelM, .FResSelW, .FPUActiveE, .PostProcSelE, .PostProcSelM, .FCvtIntW,
@ -348,7 +348,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
.ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM),
.FmaSm(SmM), .DivUe(UeM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM),
.CvtCe(CeM), .CvtResSubnormUf(CvtResSubnormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM),
.ToInt(FWriteIntM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM),
.ToInt(FWriteIntM), .Zfa(ZfaM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM),
.PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
// FPU flag selection - to privileged

View File

@ -56,6 +56,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
input logic CvtResSubnormUf, // the convert result is subnormal or underflows
input logic [P.LOGCVTLEN-1:0] CvtShiftAmt, // how much to shift by
input logic ToInt, // is fp->int (since it's writting to the integer register)
input logic Zfa, // Zfa operation (fcvtmod.w.d)
input logic [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
input logic IntZero, // is the integer input zero
// final results
@ -216,9 +217,9 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
negateintres #(P) negateintres(.Xs, .Shifted, .Signed, .Int64, .Plus1, .CvtNegResMsbs, .CvtNegRes);
specialcase #(P) specialcase(.Xs, .Xm, .Ym, .Zm, .XZero, .IntInvalid,
specialcase #(P) specialcase(.Xs, .Xm, .Ym, .Zm, .XZero, .IntInvalid,
.IntZero, .Frm, .OutFmt, .XNaN, .YNaN, .ZNaN, .CvtResUf,
.NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .CvtNegRes,
.NaNIn, .IntToFp, .Int64, .Signed, .Zfa, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .CvtNegRes,
.XInf, .YInf, .DivOp, .DivByZero, .FullRe, .CvtCe, .Rs, .Re, .Rf, .PostProcRes, .FCvtIntRes);
endmodule

View File

@ -53,6 +53,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
input logic IntToFp, // is cvt int -> fp opperation
input logic Int64, // is the integer 64 bits
input logic Signed, // is the integer signed
input logic Zfa, // Zfa conversion operation: fcvtmod.w.d
input logic [P.NE:0] CvtCe, // the calculated expoent for cvt
input logic IntInvalid, // integer invalid flag to choose the result
input logic CvtResUf, // does the convert result underflow
@ -70,10 +71,12 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
logic [P.FLEN-1:0] OfRes; // overflowed result result
logic [P.FLEN-1:0] NormRes; // normal result
logic [P.XLEN-1:0] OfIntRes; // the overflow result for integer output
logic [P.XLEN-1:0] OfIntRes2; // the overflow result for integer output after accounting for fcvtmod.w.d
logic [P.XLEN-1:0] Int64Res; // Result for conversion to 64-bit int after accounting for fcvtmod.w.d
logic OfResMax; // does the of result output maximum norm fp number
logic KillRes; // kill the result for underflow
logic SelOfRes; // should the overflow result be selected
logic SelOfRes; // should the overflow result be selected (excluding convert)
logic SelCvtOfRes; // select overflow result for convert instruction
// does the overflow result output the maximum normalized floating point number
// output infinity if the input is infinity
@ -329,6 +332,25 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
end
// fcvtmod.w.d logic
// fcvtmod.w.d is like fcvt.w.d excep thtat it takes bits [31:0] and sign extends the rest,
// and converts +/-inf and NaN to zero.
if (P.ZFA_SUPPORTED & P.D_SUPPORTED) // fcvtmod.w.d support
always_comb begin
if (Zfa) OfIntRes2 = '0;
else OfIntRes2 = OfIntRes;
if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]};
else Int64Res = CvtNegRes[P.XLEN-1:0];
if (Zfa) SelCvtOfRes = InfIn | NaNIn; // fcvtmod.w.d only overflows to 0 on NaN or Infinity
else SelCvtOfRes = IntInvalid; // regular fcvt gives an overflow if out of range
end
else
always_comb begin // no fcvtmod.w.d support
OfIntRes2 = OfIntRes;
Int64Res = CvtNegRes[P.XLEN-1:0];
SelCvtOfRes = IntInvalid;
end
// select the integer output
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
@ -337,10 +359,10 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
// - otherwise output a rounded 0
// - otherwise output the normal res (trmined and sign extended if nessisary)
always_comb
if(IntInvalid) FCvtIntRes = OfIntRes;
if(SelCvtOfRes) FCvtIntRes = OfIntRes2;
else if(CvtCe[P.NE])
if(Xs&Signed&Plus1) FCvtIntRes = {{P.XLEN{1'b1}}};
else FCvtIntRes = {{P.XLEN-1{1'b0}}, Plus1};
else if(Int64) FCvtIntRes = CvtNegRes[P.XLEN-1:0];
else if(Int64) FCvtIntRes = Int64Res;
else FCvtIntRes = {{P.XLEN-32{CvtNegRes[31]}}, CvtNegRes[31:0]};
endmodule

View File

@ -298,6 +298,18 @@ module instrNameDecTB(
else if (funct7[6:2] == 5'b11100 & funct3 == 3'b001) name = "FCLASS";
else if (funct7[6:2] == 5'b00100 & funct3 == 3'b010) name = "FSGNJX";
else if (funct7[6:2] == 5'b10100 & funct3 == 3'b010) name = "FEQ";
else if (funct7[6:2] == 5'b11110 & funct3 == 3'b000 & rs2 == 5'b00001) name = "FLI";
else if (funct7[6:2] == 5'b00101 & funct3 == 3'b010) name = "FMINM";
else if (funct7[6:2] == 5'b00101 & funct3 == 3'b011) name = "FMAXM";
else if (funct7[6:2] == 5'b01000 & rs2 == 5'b00100) name = "FROUND";
else if (funct7[6:2] == 5'b01000 & rs2 == 5'b00101) name = "FROUNDNX";
else if (funct7[6:2] == 5'b10100 & funct3 == 3'b100) name = "FLEQ";
else if (funct7[6:2] == 5'b10100 & funct3 == 3'b101) name = "FLTQ";
else if (funct7 == 7'b1110001 & funct3 == 3'b000 & rs2 == 5'b00001) name = "FMVH.X.D";
else if (funct7 == 7'b1110011 & funct3 == 3'b000 & rs2 == 5'b00001) name = "FMVH.X.Q";
else if (funct7 == 7'b1011001 & funct3 == 3'b000) name = "FMVP.D.X";
else if (funct7 == 7'b1011011 & funct3 == 3'b000) name = "FMVP.Q.X";
else if (funct7 == 7'b1100001 & funct3 == 3'b001 & rs2 == 5'b01000) name = "FCVTMOD.W.D";
else name = "ILLEGAL";
10'b0000111_010: name = "FLW";
10'b0100111_010: name = "FSW";

View File

@ -2015,6 +2015,13 @@ string arch64zbs[] = '{
string arch32zfad[] = '{
`RISCVARCHTEST,
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b1-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b22-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b23-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b24-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b27-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b28-01.S",
"rv32i_m/D_Zfa/src/fcvtmod.w.d_b29-01.S",
"rv32i_m/D_Zfa/src/fleq_b1-01.S",
"rv32i_m/D_Zfa/src/fleq_b19-01.S",
"rv32i_m/D_Zfa/src/fleq.d_b1-01.S",