diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 8dae34f89..6d5a91aa6 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -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]; diff --git a/src/fpu/fpu.sv b/src/fpu/fpu.sv index 85ea9dba6..c304219aa 100755 --- a/src/fpu/fpu.sv +++ b/src/fpu/fpu.sv @@ -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 diff --git a/src/fpu/postproc/postprocess.sv b/src/fpu/postproc/postprocess.sv index c2de8644e..516752a78 100644 --- a/src/fpu/postproc/postprocess.sv +++ b/src/fpu/postproc/postprocess.sv @@ -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 diff --git a/src/fpu/postproc/specialcase.sv b/src/fpu/postproc/specialcase.sv index 677ccce16..76784e4a1 100644 --- a/src/fpu/postproc/specialcase.sv +++ b/src/fpu/postproc/specialcase.sv @@ -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 diff --git a/testbench/common/instrNameDecTB.sv b/testbench/common/instrNameDecTB.sv index a3b5ef58e..ee6cd6900 100644 --- a/testbench/common/instrNameDecTB.sv +++ b/testbench/common/instrNameDecTB.sv @@ -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"; diff --git a/testbench/tests.vh b/testbench/tests.vh index 7d2d320a8..fecf4ebc9 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -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",