mirror of
https://github.com/openhwgroup/cvw
synced 2025-01-23 13:04:28 +00:00
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:
parent
4cfc86140c
commit
74b242ce5c
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user