From 77a982c977868b8d723c4dbbe6e172b94ce67587 Mon Sep 17 00:00:00 2001 From: Katherine Parry Date: Wed, 11 Jan 2023 22:02:30 -0600 Subject: [PATCH] cleaned up all FPU files except for division --- pipelined/config/shared/wally-constants.vh | 6 +- pipelined/src/fpu/fclassify.sv | 20 +- pipelined/src/fpu/fcmp.sv | 24 +-- pipelined/src/fpu/fctrl.sv | 190 ++++++++++-------- pipelined/src/fpu/fcvt.sv | 44 ++-- pipelined/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv | 2 +- pipelined/src/fpu/fhazard.sv | 16 +- pipelined/src/fpu/fma/fma.sv | 33 ++- pipelined/src/fpu/fma/fmaadd.sv | 27 ++- pipelined/src/fpu/fma/fmaalign.sv | 18 +- pipelined/src/fpu/fma/fmaexpadd.sv | 8 +- pipelined/src/fpu/fma/fmalza.sv | 8 +- pipelined/src/fpu/fma/fmamult.sv | 4 +- pipelined/src/fpu/fma/fmasign.sv | 11 +- pipelined/src/fpu/fpu.sv | 8 +- pipelined/src/fpu/fregfile.sv | 15 +- pipelined/src/fpu/fsgninj.sv | 8 +- pipelined/src/fpu/postproc/cvtshiftcalc.sv | 37 ++-- pipelined/src/fpu/postproc/divshiftcalc.sv | 22 +- pipelined/src/fpu/postproc/flags.sv | 146 +++++++++----- pipelined/src/fpu/postproc/fmashiftcalc.sv | 30 ++- pipelined/src/fpu/postproc/negateintres.sv | 16 +- pipelined/src/fpu/postproc/normshift.sv | 21 +- pipelined/src/fpu/postproc/postprocess.sv | 161 +++++++-------- pipelined/src/fpu/postproc/resultsign.sv | 49 +++-- pipelined/src/fpu/postproc/round.sv | 122 ++++++----- pipelined/src/fpu/postproc/roundsign.sv | 25 +-- pipelined/src/fpu/postproc/shiftcorrection.sv | 67 +++--- pipelined/src/fpu/postproc/specialcase.sv | 103 +++++----- pipelined/src/fpu/unpack.sv | 28 +-- pipelined/src/fpu/unpackinput.sv | 33 +-- pipelined/src/generic/lzc.sv | 5 +- pipelined/testbench/testbench-fp.sv | 22 +- 33 files changed, 725 insertions(+), 604 deletions(-) diff --git a/pipelined/config/shared/wally-constants.vh b/pipelined/config/shared/wally-constants.vh index 75008049..a865cfd5 100644 --- a/pipelined/config/shared/wally-constants.vh +++ b/pipelined/config/shared/wally-constants.vh @@ -123,11 +123,9 @@ `define CVTLEN ((`NF<`XLEN) ? (`XLEN) : (`NF)) `define LLEN ((`FLEN<`XLEN) ? (`XLEN) : (`FLEN)) `define LOGCVTLEN $unsigned($clog2(`CVTLEN+1)) -`define NORMSHIFTSZ ((`DIVb + 1 +`NF+1) > (3*`NF+6) ? (`DIVb + 1 +`NF+1) : (3*`NF+6)) +`define NORMSHIFTSZ (((`CVTLEN+`NF+1)>(`DIVb + 1 +`NF+1) & (`CVTLEN+`NF+1)>(3*`NF+6)) ? (`CVTLEN+`NF+1) : ((`DIVb + 1 +`NF+1) > (3*`NF+6) ? (`DIVb + 1 +`NF+1) : (3*`NF+6))) `define LOGNORMSHIFTSZ ($clog2(`NORMSHIFTSZ)) -`define CORRSHIFTSZ ((`DIVN+1+`NF) > (3*`NF+4) ? (`DIVN+1+`NF) : (3*`NF+4)) - -// *** CORRSHIFTSZ & NORMSHIFTSZ needs to be longest from divider, convert, fma +`define CORRSHIFTSZ (((`CVTLEN+`NF+1)>(`DIVb + 1 +`NF+1) & (`CVTLEN+`NF+1)>(3*`NF+6)) ? (`CVTLEN+`NF+1) : ((`DIVN+1+`NF) > (3*`NF+4) ? (`DIVN+1+`NF) : (3*`NF+4))) // division constants diff --git a/pipelined/src/fpu/fclassify.sv b/pipelined/src/fpu/fclassify.sv index e91f34d1..9a6b4307 100644 --- a/pipelined/src/fpu/fclassify.sv +++ b/pipelined/src/fpu/fclassify.sv @@ -26,18 +26,18 @@ `include "wally-config.vh" module fclassify ( - input logic Xs, // sign bit - input logic XNaN, // is NaN - input logic XSNaN, // is signaling NaN - input logic XSubnorm,// is Subnormal - input logic XZero, // is zero - input logic XInf, // is infinity - output logic [`XLEN-1:0] ClassRes// classify result + input logic Xs, // sign bit + input logic XNaN, // is NaN + input logic XSNaN, // is signaling NaN + input logic XSubnorm, // is Subnormal + input logic XZero, // is zero + input logic XInf, // is infinity + output logic [`XLEN-1:0] ClassRes // classify result ); - logic PInf, PZero, PNorm, PSubnorm; - logic NInf, NZero, NNorm, NSubnorm; - logic XNorm; + logic PInf, PZero, PNorm, PSubnorm; // is the input a positive infinity/zero/normal/subnormal + logic NInf, NZero, NNorm, NSubnorm; // is the input a negitive infinity/zero/normal/subnormal + logic XNorm; // is the input normal // determine the sub categories assign XNorm= ~(XNaN | XInf| XSubnorm| XZero); diff --git a/pipelined/src/fpu/fcmp.sv b/pipelined/src/fpu/fcmp.sv index 5cea973d..758b589e 100755 --- a/pipelined/src/fpu/fcmp.sv +++ b/pipelined/src/fpu/fcmp.sv @@ -35,18 +35,18 @@ // 011 less than or equal module fcmp ( - input logic [`FMTBITS-1:0] Fmt, // format of fp number - input logic [2:0] OpCtrl, // see above table - input logic Xs, Ys, // input signs - input logic [`NE-1:0] Xe, Ye, // input exponents - input logic [`NF:0] Xm, Ym, // input mantissa - input logic XZero, YZero, // is zero - input logic XNaN, YNaN, // is NaN - input logic XSNaN, YSNaN, // is signaling NaN - input logic [`FLEN-1:0] X, Y, // original inputs (before unpacker) - output logic CmpNV, // invalid flag - output logic [`FLEN-1:0] CmpFpRes, // compare floating-point result - output logic [`XLEN-1:0] CmpIntRes // compare integer result + input logic [`FMTBITS-1:0] Fmt, // format of fp number + input logic [2:0] OpCtrl, // see above table + input logic Xs, Ys, // input signs + input logic [`NE-1:0] Xe, Ye, // input exponents + input logic [`NF:0] Xm, Ym, // input mantissa + input logic XZero, YZero, // is zero + input logic XNaN, YNaN, // is NaN + input logic XSNaN, YSNaN, // is signaling NaN + input logic [`FLEN-1:0] X, Y, // original inputs (before unpacker) + output logic CmpNV, // invalid flag + output logic [`FLEN-1:0] CmpFpRes, // compare floating-point result + output logic [`XLEN-1:0] CmpIntRes // compare integer result ); logic LTabs, LT, EQ; // is X < or > or = Y diff --git a/pipelined/src/fpu/fctrl.sv b/pipelined/src/fpu/fctrl.sv index 4d156666..b8bb2963 100755 --- a/pipelined/src/fpu/fctrl.sv +++ b/pipelined/src/fpu/fctrl.sv @@ -26,56 +26,66 @@ `include "wally-config.vh" module fctrl ( - input logic clk, - input logic reset, - input logic StallE, StallM, StallW, // stall signals - input logic FlushE, FlushM, FlushW, // flush signals - input logic [31:0] InstrD, - input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision - input logic [6:0] OpD, // bits 6:0 of instruction - input logic [4:0] Rs2D, // bits 24:20 of instruction - input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode - input logic IntDivE, - input logic [2:0] FRM_REGW, // rounding mode from CSR - input logic [1:0] STATUS_FS, // is FPU enabled? - input logic FDivBusyE, // is the divider busy - output logic IllegalFPUInstrM, // Is the instruction an illegal fpu instruction - output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable - output logic [2:0] FrmM, // FP rounding mode + input logic clk, + input logic reset, + // input control signals + input logic StallE, StallM, StallW, // stall signals + input logic FlushE, FlushM, FlushW, // flush signals + input logic IntDivE, // is inteteger division + input logic [2:0] FRM_REGW, // rounding mode from CSR + input logic [1:0] STATUS_FS, // is FPU enabled? + input logic FDivBusyE, // is the divider busy + // intruction + input logic [31:0] InstrD, // the full instruction + input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision + input logic [6:0] OpD, // bits 6:0 of instruction + input logic [4:0] Rs2D, // bits 24:20 of instruction + input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode + // input mux selections + output logic XEnD, YEnD, ZEnD, // enable inputs + output logic XEnE, YEnE, ZEnE, // enable inputs + // opperation mux selections + output logic FCvtIntE, FCvtIntW, // convert to integer opperation + output logic [2:0] FrmM, // FP rounding mode output logic [`FMTBITS-1:0] FmtE, FmtM, // FP format - output logic FDivStartE, IDivStartE, // Start division or squareroot - output logic XEnD, YEnD, ZEnD, - output logic XEnE, YEnE, ZEnE, - output logic FWriteIntE, FCvtIntE, FWriteIntM, // Write to integer register - output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component - output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage - output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit - output logic FpLoadStoreM, // FP load or store instruction - output logic FCvtIntW, - output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input - output logic [4:0] Adr1E, Adr2E, Adr3E // adresses of each input + output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component + output logic FpLoadStoreM, // FP load or store instruction + 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 + // register control signals + output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable + output logic FWriteIntE, FWriteIntM, // Write to integer register + output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input + output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input + // other control signals + output logic IllegalFPUInstrM, // Is the instruction an illegal fpu instruction + output logic FDivStartE, IDivStartE // Start division or squareroot ); `define FCTRLW 12 - logic [`FCTRLW-1:0] ControlsD; - logic IllegalFPUInstrD, IllegalFPUInstrE; - logic FRegWriteD; // FP register write enable - logic FDivStartD; // integer register write enable - logic FWriteIntD; // integer register write enable - logic [2:0] OpCtrlD; // Select which opperation to do in each component - logic [1:0] PostProcSelD; // select result in the post processing unit - logic [1:0] FResSelD; // Select one of the results that finish in the memory stage - logic [2:0] FrmD, FrmE; // FP rounding mode - logic [`FMTBITS-1:0] FmtD; // FP format - logic [1:0] Fmt; - logic SupportedFmt; - logic FCvtIntD, FCvtIntM; + + logic [`FCTRLW-1:0] ControlsD; // control signals + logic IllegalFPUInstrD, IllegalFPUInstrE; // is the intruction an illegal fpu instruction + logic FRegWriteD; // FP register write enable + logic FDivStartD; // start division/sqrt + logic FWriteIntD; // integer register write enable + logic [2:0] OpCtrlD; // Select which opperation to do in each component + logic [1:0] PostProcSelD; // select result in the post processing unit + logic [1:0] FResSelD; // Select one of the results that finish in the memory stage + logic [2:0] FrmD, FrmE; // FP rounding mode + logic [`FMTBITS-1:0] FmtD; // FP format + logic [1:0] Fmt; // format - before possible reduction + logic SupportedFmt; // is the format supported + logic FCvtIntD, FCvtIntM; // convert to integer opperation // FPU Instruction Decoder assign Fmt = Funct7D[1:0]; + // Note: only Fmt is checked; fcvt does not check destination format assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & `D_SUPPORTED) | (Fmt == 2'b10 & `ZFH_SUPPORTED) | (Fmt == 2'b11 & `Q_SUPPORTED)); + + // decode the instruction always_comb if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; @@ -180,8 +190,10 @@ module fctrl ( assign FrmD = &Funct3D ? FRM_REGW : Funct3D; // Precision - // 0-single - // 1-double + // 00 - single + // 01 - double + // 10 - half + // 11 - quad if (`FPSIZES == 1) assign FmtD = 0; @@ -210,56 +222,57 @@ module fctrl ( assign ZEnD = (PostProcSelD==2'b10)&(FResSelD==2'b01)&(~OpCtrlD[2]|OpCtrlD[1]); // fma, add, sub -// Final Res Sel: -// fp int -// 00 other cmp -// 01 postproc cvt -// 10 store class -// 11 mv + // Final Res Sel: + // fp int + // 00 other cmp + // 01 postproc cvt + // 10 store class + // 11 mv -// post processing Sel: -// 00 cvt -// 01 div -// 10 fma + // post processing Sel: + // 00 cvt + // 01 div + // 10 fma -// Other Sel: -// Ctrl signal = {OpCtrl[2], &FOpctrl[1:0]} -// 000 - sign 00 -// 001 - negate sign 00 -// 010 - xor sign 00 -// 011 - mv to fp 01 -// 110 - min 10 -// 101 - max 10 + // Other Sel: + // Ctrl signal = {OpCtrl[2], &FOpctrl[1:0]} + // 000 - sign 00 + // 001 - negate sign 00 + // 010 - xor sign 00 + // 011 - mv to fp 01 + // 110 - min 10 + // 101 - max 10 -// OpCtrl: -// Fma: {not multiply-add?, negate prod?, negate Z?} -// 000 - fmadd -// 001 - fmsub -// 010 - fnmsub -// 011 - fnmadd -// 100 - mul -// 110 - add -// 111 - sub -// Div: -// 0 - div -// 1 - sqrt -// Cvt Int: {Int to Fp?, 64 bit int?, signed int?} -// Cvt Fp: output format -// 10 - to half -// 00 - to single -// 01 - to double -// 11 - to quad -// Cmp: {equal?, less than?} -// 010 - eq -// 001 - lt -// 011 - le -// 110 - min -// 101 - max -// Sgn: -// 00 - sign -// 01 - negate sign -// 10 - xor sign + // OpCtrl: + // Fma: {not multiply-add?, negate prod?, negate Z?} + // 000 - fmadd + // 001 - fmsub + // 010 - fnmsub + // 011 - fnmadd + // 100 - mul + // 110 - add + // 111 - sub + // Div: + // 0 - div + // 1 - sqrt + // Cvt Int: {Int to Fp?, 64 bit int?, signed int?} + // Cvt Fp: output format + // 10 - to half + // 00 - to single + // 01 - to double + // 11 - to quad + // Cmp: {equal?, less than?} + // 010 - eq + // 001 - lt + // 011 - le + // 110 - min + // 101 - max + // Sgn: + // 00 - sign + // 01 - negate sign + // 10 - xor sign + // rename input adresses for readability assign Adr1D = InstrD[19:15]; assign Adr2D = InstrD[24:20]; assign Adr3D = InstrD[31:27]; @@ -281,6 +294,7 @@ module fctrl ( {FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, IllegalFPUInstrE, FCvtIntE}, {FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, OpCtrlM, FWriteIntM, IllegalFPUInstrM, FCvtIntM}); + // renameing for readability assign FpLoadStoreM = FResSelM[1]; // M/W pipleine register diff --git a/pipelined/src/fpu/fcvt.sv b/pipelined/src/fpu/fcvt.sv index 5deb543e..41ba1bad 100644 --- a/pipelined/src/fpu/fcvt.sv +++ b/pipelined/src/fpu/fcvt.sv @@ -28,17 +28,17 @@ `include "wally-config.vh" module fcvt ( - input logic Xs, // input's sign - input logic [`NE-1:0] Xe, // input's exponent - input logic [`NF:0] Xm, // input's fraction - input logic [`XLEN-1:0] Int, // integer input - from IEU - input logic [2:0] OpCtrl, // choose which opperation (look below for values) - input logic ToInt, // is fp->int (since it's writting to the integer register) - input logic XZero, // is the input zero - input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half) + input logic Xs, // input's sign + input logic [`NE-1:0] Xe, // input's exponent + input logic [`NF:0] Xm, // input's fraction + input logic [`XLEN-1:0] Int, // integer input - from IEU + input logic [2:0] OpCtrl, // choose which opperation (look below for values) + input logic ToInt, // is fp->int (since it's writting to the integer register) + input logic XZero, // is the input zero + input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half) output logic [`NE:0] Ce, // the calculated expoent output logic [`LOGCVTLEN-1:0] ShiftAmt, // how much to shift by - output logic ResSubnormUf, // does the result underflow or is Subnormalized + output logic ResSubnormUf,// does the result underflow or is subnormal output logic Cs, // the result's sign output logic IntZero, // is the integer zero? output logic [`CVTLEN-1:0] LzcIn // input to the Leading Zero Counter (priority encoder) @@ -101,6 +101,8 @@ module fcvt ( // fp -> fp : | fraction | 00000... (if needed) | assign LzcInFull = IntToFp ? {TrimInt, {`CVTLEN-`XLEN+1{1'b0}}} : {Xm, {`CVTLEN-`NF{1'b0}}}; + + // used as shifter input in postprocessor assign LzcIn = LzcInFull[`CVTLEN-1:0]; lzc #(`CVTLEN+1) lzc (.num(LzcInFull), .ZeroCnt(LeadingZeros)); @@ -109,16 +111,6 @@ module fcvt ( // exp calculations /////////////////////////////////////////////////////////////////////////// - - // *** possible optimizaations: - // - if subtracting exp by bias only the msb needs a full adder, the rest can be HA - dunno how to implement this for synth - // - Smaller exp -> Larger Exp can be calculated with: *** can use in Other units??? FMA??? insert this thing in later - // Exp if in range: {~Exp[SNE-1], Exp[SNE-2:0]} - // Exp in range if: Exp[SNE-1] = 1 & Exp[LNE-2:SNE] = 1111... & Exp[LNE-1] = 0 | Exp[SNE-1] = 0 & Exp[LNE-2:SNE] = 000... & Exp[LNE-1] = 1 - // i.e.: &Exp[LNE-2:SNE-1] xor Exp[LNE-1] - // Too big if: Exp[LNE-1] = 1 - // Too small if: none of the above - // Select the bias of the output // fp -> int : select 1 // ??? -> fp : pick the new bias depending on the output format @@ -152,6 +144,8 @@ module fcvt ( endcase assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp; end + + // select the old exponent // int -> fp : largest bias + XLEN-1 // fp -> ??? : XExp @@ -160,7 +154,7 @@ module fcvt ( // calculate CalcExp // fp -> fp : // - XExp - Largest bias + new bias - (LeadingZeros+1) - // only do ^ if the input was Subnormalized + // only do ^ if the input was subnormal // - convert the expoenent to the final preciaion (Exp - oldBias + newBias) // - correct the expoent when there is a normalization shift ( + LeadingZeros+1) // - the plus 1 is built into the leading zeros by counting the leading zeroes in the mantissa rather than the fraction @@ -178,7 +172,7 @@ module fcvt ( // | 0's | Mantissa | 0's if nessisary | // | keep | // - // - if the input is Subnormalized then we dont shift... so the "- LeadingZeros" is just leftovers from other options + // - if the input is subnormal then we dont shift... so the "- LeadingZeros" is just leftovers from other options // int -> fp : largest bias + XLEN-1 - Largest bias + new bias - LeadingZeros = XLEN-1 + NewBias - LeadingZeros // Process: // |XLEN|.0000 @@ -192,6 +186,8 @@ module fcvt ( // // oldexp - biasold - LeadingZeros + newbias assign Ce = {1'b0, OldExp} - (`NE+1)'(`BIAS) - {{`NE-`LOGCVTLEN+1{1'b0}}, (LeadingZeros)} + {2'b0, NewBias}; + + // find if the result is dnormal or underflows // - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0) // - can't underflow an integer to Fp conversion @@ -207,17 +203,19 @@ module fcvt ( // fp -> int: // - shift left by CalcExp - essentially shifting until the unbiased exponent = 0 // - don't shift if supposed to shift right (underflowed or Subnorm input) - // Subnormalized/undeflowed result fp -> fp: + // subnormal/undeflowed result fp -> fp: // - shift left by NF-1+CalcExp - to shift till the biased expoenent is 0 // ??? -> fp: // - shift left by LeadingZeros - to shift till the result is normalized - // - only shift fp -> fp if the intital value is Subnormalized + // - only shift fp -> fp if the intital value is subnormal // - this is a problem because the input to the lzc was the fraction rather than the mantissa // - rather have a few and-gates than an extra bit in the priority encoder??? *** is this true? always_comb if(ToInt) ShiftAmt = Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}}; else if (ResSubnormUf) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0]; else ShiftAmt = LeadingZeros; + + /////////////////////////////////////////////////////////////////////////// // sign /////////////////////////////////////////////////////////////////////////// diff --git a/pipelined/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv b/pipelined/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv index 8d881d20..b78f3f53 100644 --- a/pipelined/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv +++ b/pipelined/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv @@ -66,7 +66,7 @@ module fdivsqrtexpcalc( assign SXExp = {2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - (`NE+2)'(`BIAS); assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias}; - // correct exponent for Subnormalized input's normalization shifts + // correct exponent for subnormal input's normalization shifts assign DExp = ({2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - {2'b0, Ye} + {{(`NE+1-`DIVBLEN){1'b0}}, m} + {3'b0, Bias}) & {`NE+2{~XZero}}; assign Qe = Sqrt ? SExp : DExp; endmodule diff --git a/pipelined/src/fpu/fhazard.sv b/pipelined/src/fpu/fhazard.sv index 03678ace..4ee31f0f 100644 --- a/pipelined/src/fpu/fhazard.sv +++ b/pipelined/src/fpu/fhazard.sv @@ -27,17 +27,17 @@ `include "wally-config.vh" module fhazard( - input logic [4:0] Adr1D, Adr2D, Adr3D, // read data adresses - input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses + input logic [4:0] Adr1D, Adr2D, Adr3D, // read data adresses + input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses input logic FRegWriteE, FRegWriteM, FRegWriteW, // is the fp register being written to - input logic [4:0] RdE, RdM, RdW, // the adress being written to - input logic [1:0] FResSelM, // the result being selected - input logic XEnD, YEnD, ZEnD, - output logic FPUStallD, // stall the decode stage - output logic [1:0] ForwardXE, ForwardYE, ForwardZE // select a forwarded value + input logic [4:0] RdE, RdM, RdW, // the adress being written to + input logic [1:0] FResSelM, // the result being selected + input logic XEnD, YEnD, ZEnD, // are the inputs needed + output logic FPUStallD, // stall the decode stage + output logic [1:0] ForwardXE, ForwardYE, ForwardZE // select a forwarded value ); - logic MatchDE; + logic MatchDE; // is a value needed in decode stage being worked on in execute stage // Decode-stage instruction source depends on result from execute stage instruction assign MatchDE = ((Adr1D == RdE) & XEnD) | ((Adr2D == RdE) & YEnD) | ((Adr3D == RdE) & ZEnD); diff --git a/pipelined/src/fpu/fma/fma.sv b/pipelined/src/fpu/fma/fma.sv index 23e6710f..b3e1751c 100644 --- a/pipelined/src/fpu/fma/fma.sv +++ b/pipelined/src/fpu/fma/fma.sv @@ -27,19 +27,19 @@ `include "wally-config.vh" module fma( - input logic Xs, Ys, Zs, // input's signs - input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format - input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format - input logic XZero, YZero, ZZero, // is the input zero - input logic [2:0] OpCtrl, // operation control - output logic ASticky, // sticky bit that is calculated during alignment - output logic [3*`NF+3:0] Sm, // the positive sum's significand - output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A) - output logic As, // the aligned addend's sign (modified Z sign for other opperations) - output logic Ps, // the product's sign - output logic Ss, // the sum's sign - output logic [`NE+1:0] Se, // the sum's exponent - output logic [$clog2(3*`NF+5)-1:0] SCnt // normalization shift count + input logic Xs, Ys, Zs, // input's signs + input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format + input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format + input logic XZero, YZero, ZZero, // is the input zero + input logic [2:0] OpCtrl, // operation control + output logic ASticky, // sticky bit that is calculated during alignment + output logic [3*`NF+3:0] Sm, // the positive sum's significand + output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A) + output logic As, // the aligned addend's sign (modified Z sign for other opperations) + output logic Ps, // the product's sign + output logic Ss, // the sum's sign + output logic [`NE+1:0] Se, // the sum's exponent + output logic [$clog2(3*`NF+5)-1:0] SCnt // normalization shift count ); // OpCtrl: @@ -52,7 +52,7 @@ module fma( // 110 - add // 111 - sub - logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format + logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format logic [3*`NF+3:0] Am; // addend aligned's mantissa for addition in U(NF+4.2NF) logic [3*`NF+3:0] AmInv; // aligned addend's mantissa possibly inverted logic [2*`NF+1:0] PmKilled; // the product's mantissa possibly killed U(2.2Nf) @@ -80,8 +80,7 @@ module fma( /////////////////////////////////////////////////////////////////////////////// // Alignment shifter /////////////////////////////////////////////////////////////////////////////// - fmaalign align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, - .Am, .ASticky, .KillProd); + fmaalign align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd); // /////////////////////////////////////////////////////////////////////////////// // // Addition/LZA @@ -89,7 +88,7 @@ module fma( fmaadd add(.Am, .Pm, .Ze, .Pe, .Ps, .KillProd, .ASticky, .AmInv, .PmKilled, .InvA, .Sm, .Se, .Ss); - fmalza #(3*`NF+4) lza(.A(AmInv), .Pm({PmKilled, InvA&Ps&ASticky&KillProd}), .Cin(InvA & ~(ASticky & ~KillProd)), .sub(InvA), .SCnt); + fmalza #(3*`NF+4) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt); endmodule diff --git a/pipelined/src/fpu/fma/fmaadd.sv b/pipelined/src/fpu/fma/fmaadd.sv index 7f1487f2..96d81ed2 100644 --- a/pipelined/src/fpu/fma/fmaadd.sv +++ b/pipelined/src/fpu/fma/fmaadd.sv @@ -27,23 +27,22 @@ `include "wally-config.vh" module fmaadd( - input logic [3*`NF+3:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1) - input logic [2*`NF+1:0] Pm, // the product's mantissa - input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations) - input logic InvA, // invert the aligned addend - input logic KillProd, // should the product be set to 0 - input logic ASticky, - input logic [`NE-1:0] Ze, - input logic [`NE+1:0] Pe, - output logic [3*`NF+3:0] AmInv, // aligned addend possibly inverted - output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed - output logic Ss, - output logic [`NE+1:0] Se, + input logic [3*`NF+3:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1) + input logic [`NE-1:0] Ze, // exponent of Z + input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations) + input logic [`NE+1:0] Pe, // product's exponet + input logic [2*`NF+1:0] Pm, // the product's mantissa + input logic InvA, // invert the aligned addend + input logic KillProd, // should the product be set to 0 + input logic ASticky, // Alighed addend's sticky bit + output logic [3*`NF+3:0] AmInv, // aligned addend possibly inverted + output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed + output logic Ss, // sum's sign + output logic [`NE+1:0] Se, // sum's exponent output logic [3*`NF+3:0] Sm // the positive sum ); logic [3*`NF+3:0] PreSum, NegPreSum; // possibly negitive sum - logic NegSum; // was the sum negitive - logic NegSumdebug; // was the sum negitive + logic NegSum; // was the sum negitive /////////////////////////////////////////////////////////////////////////////// // Addition diff --git a/pipelined/src/fpu/fma/fmaalign.sv b/pipelined/src/fpu/fma/fmaalign.sv index df5080a7..2e1218ce 100644 --- a/pipelined/src/fpu/fma/fmaalign.sv +++ b/pipelined/src/fpu/fma/fmaalign.sv @@ -28,18 +28,18 @@ `include "wally-config.vh" module fmaalign( - input logic [`NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format - input logic [`NF:0] Zm, // significand in U(0.NF) format] - input logic XZero, YZero, ZZero, // is the input zero - output logic [3*`NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1) - output logic ASticky, // Sticky bit calculated from the aliged addend - output logic KillProd // should the product be set to zero + input logic [`NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format + input logic [`NF:0] Zm, // significand in U(0.NF) format] + input logic XZero, YZero, ZZero,// is the input zero + output logic [3*`NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1) + output logic ASticky, // Sticky bit calculated from the aliged addend + output logic KillProd // should the product be set to zero ); logic [`NE+1:0] ACnt; // how far to shift the addend to align with the product in Q(NE+2.0) format - logic [4*`NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1) - logic [4*`NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1) - logic KillZ; + logic [4*`NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1) + logic [4*`NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1) + logic KillZ; // should the addend be killed /////////////////////////////////////////////////////////////////////////////// // Alignment shifter diff --git a/pipelined/src/fpu/fma/fmaexpadd.sv b/pipelined/src/fpu/fma/fmaexpadd.sv index 4521d475..dfee67e1 100644 --- a/pipelined/src/fpu/fma/fmaexpadd.sv +++ b/pipelined/src/fpu/fma/fmaexpadd.sv @@ -27,12 +27,12 @@ `include "wally-config.vh" module fmaexpadd( - input logic [`NE-1:0] Xe, Ye, // input's exponents - input logic XZero, YZero, // are the inputs zero - output logic [`NE+1:0] Pe // product's exponent B^(1023)NE+2 + input logic [`NE-1:0] Xe, Ye, // input's exponents + input logic XZero, YZero, // are the inputs zero + output logic [`NE+1:0] Pe // product's exponent B^(1023)NE+2 ); - logic PZero; + logic PZero; // is the product zero // kill the exponent if the product is zero - either X or Y is 0 assign PZero = XZero | YZero; diff --git a/pipelined/src/fpu/fma/fmalza.sv b/pipelined/src/fpu/fma/fmalza.sv index 5571b2ab..90bf1cf1 100644 --- a/pipelined/src/fpu/fma/fmalza.sv +++ b/pipelined/src/fpu/fma/fmalza.sv @@ -28,17 +28,17 @@ module fmalza #(WIDTH) ( // [Schmookler & Nowka, Leading zero anticipation and detection, IEEE Sym. Computer Arithmetic, 2001] input logic [WIDTH-1:0] A, // addend - input logic [2*`NF+2:0] Pm, // product + input logic [2*`NF+1:0] Pm, // product input logic Cin, // carry in - input logic sub, + input logic sub, // subtraction output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result ); - logic [WIDTH:0] F; + logic [WIDTH:0] F; logic [WIDTH-1:0] B, P, Guard, K; logic [WIDTH-1:0] Pp1, Gm1, Km1; - assign B = {{(`NF+1){1'b0}}, Pm}; // Zero extend product + assign B = {{(`NF+1){1'b0}}, Pm, 1'b0}; // Zero extend product assign P = A^B; assign Guard = A&B; diff --git a/pipelined/src/fpu/fma/fmamult.sv b/pipelined/src/fpu/fma/fmamult.sv index 911f6645..6e3aa442 100644 --- a/pipelined/src/fpu/fma/fmamult.sv +++ b/pipelined/src/fpu/fma/fmamult.sv @@ -27,8 +27,8 @@ `include "wally-config.vh" module fmamult( - input logic [`NF:0] Xm, Ym, - output logic [2*`NF+1:0] Pm + input logic [`NF:0] Xm, Ym, // x and y significand + output logic [2*`NF+1:0] Pm // product's significand ); assign Pm = Xm * Ym; endmodule diff --git a/pipelined/src/fpu/fma/fmasign.sv b/pipelined/src/fpu/fma/fmasign.sv index b9c61ae2..a73e8621 100644 --- a/pipelined/src/fpu/fma/fmasign.sv +++ b/pipelined/src/fpu/fma/fmasign.sv @@ -27,16 +27,15 @@ `include "wally-config.vh" module fmasign( - input logic [2:0] OpCtrl, // opperation contol - input logic Xs, Ys, Zs, // sign of the inputs - output logic Ps, // the product's sign - takes opperation into account - output logic As, // aligned addend sign used in fma - takes opperation into account - output logic InvA // Effective subtraction: invert addend + input logic [2:0] OpCtrl, // opperation contol + input logic Xs, Ys, Zs, // sign of the inputs + output logic Ps, // the product's sign - takes opperation into account + output logic As, // aligned addend sign used in fma - takes opperation into account + output logic InvA // Effective subtraction: invert addend ); // Calculate the product's sign // Negate product's sign if FNMADD or FNMSUB - // flip is negation opperation assign Ps = Xs ^ Ys ^ (OpCtrl[1]&~OpCtrl[2]); // flip addend sign for subtraction diff --git a/pipelined/src/fpu/fpu.sv b/pipelined/src/fpu/fpu.sv index 567b2e0b..49d1b982 100755 --- a/pipelined/src/fpu/fpu.sv +++ b/pipelined/src/fpu/fpu.sv @@ -102,7 +102,7 @@ module fpu ( logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage - logic XSubnormE; // is the input Subnormalized + logic XSubnormE; // is the input subnormal logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage logic XZeroM, YZeroM; // is the input zero - memory stage logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage @@ -124,7 +124,7 @@ module fpu ( // Cvt Signals logic [`NE:0] CeE, CeM; // convert intermediate expoent logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by - logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is Subnormalized + logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal logic CsE, CsM; // convert result sign logic IntZeroE, IntZeroM; // is the integer zero? logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder) @@ -140,7 +140,7 @@ module fpu ( // result and flag signals logic [`XLEN-1:0] ClassResE; // classify result logic [`FLEN-1:0] CmpFpResE; // compare result to FPU (min/max) - logic [`XLEN-1:0] CmpIntResE; // compare result to IEU (eq/gt/geq) + logic [`XLEN-1:0] CmpIntResE; // compare result to IEU (eq/lt/le) logic CmpNVE; // compare invalid flag (Not Valid) logic [`FLEN-1:0] SgnResE; // sign injection result logic [`XLEN-1:0] FIntResE; // FPU to IEU E-stage result (classify, compare, move) @@ -331,7 +331,7 @@ module fpu ( .ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM), .FmaSm(SmM), .DivQe(QeM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM), .CvtCe(CeM), .CvtResSubnormUf(CvtResSubnormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM), - .ToInt(FWriteIntM), .DivS(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM), + .ToInt(FWriteIntM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM), .PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM)); // FPU flag selection - to privileged diff --git a/pipelined/src/fpu/fregfile.sv b/pipelined/src/fpu/fregfile.sv index 4d774bcc..282e581e 100644 --- a/pipelined/src/fpu/fregfile.sv +++ b/pipelined/src/fpu/fregfile.sv @@ -27,14 +27,15 @@ `include "wally-config.vh" module fregfile ( - input logic clk, reset, - input logic we4, - input logic [4:0] a1, a2, a3, a4, - input logic [`FLEN-1:0] wd4, - output logic [`FLEN-1:0] rd1, rd2, rd3); + input logic clk, reset, + input logic we4, // write enable + input logic [4:0] a1, a2, a3, a4, // adresses + input logic [`FLEN-1:0] wd4, // write data + output logic [`FLEN-1:0] rd1, rd2, rd3 // read data +); - logic [`FLEN-1:0] rf[31:0]; - integer i; + logic [`FLEN-1:0] rf[31:0]; + integer i; // three ported register file // read three ports combinationally (A1/RD1, A2/RD2, A3/RD3) diff --git a/pipelined/src/fpu/fsgninj.sv b/pipelined/src/fpu/fsgninj.sv index 4dc07a97..cd425ee7 100755 --- a/pipelined/src/fpu/fsgninj.sv +++ b/pipelined/src/fpu/fsgninj.sv @@ -27,14 +27,14 @@ `include "wally-config.vh" module fsgninj ( - input logic Xs, Ys, // X and Y sign bits - input logic [`FLEN-1:0] X, // X - input logic [`FMTBITS-1:0] Fmt, // format + input logic Xs, Ys, // X and Y sign bits + input logic [`FLEN-1:0] X, // X + input logic [`FMTBITS-1:0] Fmt, // format input logic [1:0] OpCtrl, // operation control output logic [`FLEN-1:0] SgnRes // result ); - logic ResSgn; + logic ResSgn; // result sign // OpCtrl: // 00 - fsgnj - directly copy over sign value of Y diff --git a/pipelined/src/fpu/postproc/cvtshiftcalc.sv b/pipelined/src/fpu/postproc/cvtshiftcalc.sv index 7069cb53..5fbe2882 100644 --- a/pipelined/src/fpu/postproc/cvtshiftcalc.sv +++ b/pipelined/src/fpu/postproc/cvtshiftcalc.sv @@ -23,21 +23,22 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + `include "wally-config.vh" module cvtshiftcalc( - input logic XZero, // is the input zero? - input logic ToInt, // to integer conversion? - input logic IntToFp, // interger to floating point conversion? - input logic [`NE:0] CvtCe, // the calculated expoent - input logic [`NF:0] Xm, // input mantissas - input logic [`FMTBITS-1:0] OutFmt, // output format - input logic [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (priority encoder) - input logic CvtResSubnormUf, // is the conversion result subnormal or underlows - output logic CvtResUf, // does the cvt result unerflow - output logic [`CVTLEN+`NF:0] CvtShiftIn // number to be shifted + input logic XZero, // is the input zero? + input logic ToInt, // to integer conversion? + input logic IntToFp, // interger to floating point conversion? + input logic [`FMTBITS-1:0] OutFmt, // output format + input logic [`NE:0] CvtCe, // the calculated expoent + input logic [`NF:0] Xm, // input mantissas + input logic [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb) + input logic CvtResSubnormUf, // is the conversion result subnormal or underlows + output logic CvtResUf, // does the cvt result unerflow + output logic [`CVTLEN+`NF:0] CvtShiftIn // number to be shifted ); - logic [$clog2(`NF):0] ResNegNF; // the result's fraction length negated (-NF) + logic [$clog2(`NF):0] ResNegNF; // the result's fraction length negated (-NF) /////////////////////////////////////////////////////////////////////////// @@ -46,23 +47,24 @@ module cvtshiftcalc( // seclect the input to the shifter // fp -> int: - // | `XLEN zeros | Mantissa | 0's if nessisary | + // | `XLEN zeros | mantissa | 0's if nessisary | // . // Other problems: // - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding) // - we do however want to keep the one in the sticky bit so set one of bits in the sticky bit area to 1 // - ex: for the case 0010000.... (double) // ??? -> fp: - // - if result is Subnormalized or underflowed then we want to shift right i.e. shift right then shift left: - // | `NF-1 zeros | Mantissa | 0's if nessisary | + // - if result is subnormal or underflowed then we want to shift right i.e. shift right then shift left: + // | `NF-1 zeros | mantissa | 0's if nessisary | // . // - otherwise: // | LzcInM | 0's if nessisary | // . // change to int shift to the left one - - always_comb // get rid of round bit if needed + always_comb + // get rid of round bit if needed // | add sticky bit if needed + // | | if (ToInt) CvtShiftIn = {{`XLEN{1'b0}}, Xm[`NF]&~CvtCe[`NE], Xm[`NF-1]|(CvtCe[`NE]&Xm[`NF]), Xm[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}}; else if (CvtResSubnormUf) CvtShiftIn = {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}}; else CvtShiftIn = {CvtLzcIn, {`NF+1{1'b0}}}; @@ -92,6 +94,9 @@ module cvtshiftcalc( 2'h2: ResNegNF = -($clog2(`NF)+1)'(`H_NF); endcase end + + + // determine if the result underflows ??? -> fp // - if the first 1 is shifted out of the result then the result underflows // - can't underflow an integer to fp conversions diff --git a/pipelined/src/fpu/postproc/divshiftcalc.sv b/pipelined/src/fpu/postproc/divshiftcalc.sv index b98f749f..27db564c 100644 --- a/pipelined/src/fpu/postproc/divshiftcalc.sv +++ b/pipelined/src/fpu/postproc/divshiftcalc.sv @@ -27,21 +27,22 @@ `include "wally-config.vh" module divshiftcalc( - input logic [`DIVb:0] DivQm, - input logic [`NE+1:0] DivQe, - output logic [`LOGNORMSHIFTSZ-1:0] DivShiftAmt, - output logic [`NORMSHIFTSZ-1:0] DivShiftIn, - output logic DivResSubnorm, - output logic DivSubnormShiftPos + input logic [`DIVb:0] DivQm, // divsqrt significand + input logic [`NE+1:0] DivQe, // divsqrt exponent + output logic [`LOGNORMSHIFTSZ-1:0] DivShiftAmt, // divsqrt shift amount + output logic [`NORMSHIFTSZ-1:0] DivShiftIn, // divsqrt shift input + output logic DivResSubnorm, // is the divsqrt result subnormal + output logic DivSubnormShiftPos // is the subnormal shift amount positive ); - logic [`LOGNORMSHIFTSZ-1:0] NormShift, DivSubnormShiftAmt; - logic [`NE+1:0] DivSubnormShift; + logic [`LOGNORMSHIFTSZ-1:0] NormShift; // normalized result shift amount + logic [`LOGNORMSHIFTSZ-1:0] DivSubnormShiftAmt; // subnormal result shift amount (killed if negitive) + logic [`NE+1:0] DivSubnormShift; // subnormal result shift amount - // is the result Subnormalized + // is the result subnormal // if the exponent is 1 then the result needs to be normalized then the result is Subnormalizes assign DivResSubnorm = DivQe[`NE+1]|(~|DivQe[`NE+1:0]); - // if the result is Subnormalized + // if the result is subnormal // 00000000x.xxxxxx... Exp = DivQe // .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1 // .00xxxxxxxxxxxxx... << DivQe+NF+1 Exp = +1 @@ -65,5 +66,6 @@ module divshiftcalc( assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[`LOGNORMSHIFTSZ-1:0] : '0; assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift; + // pre-shift the divider result for normalization assign DivShiftIn = {{`NF{1'b0}}, DivQm, {`NORMSHIFTSZ-`DIVb-1-`NF{1'b0}}}; endmodule diff --git a/pipelined/src/fpu/postproc/flags.sv b/pipelined/src/fpu/postproc/flags.sv index 587c1ce5..6ec601db 100644 --- a/pipelined/src/fpu/postproc/flags.sv +++ b/pipelined/src/fpu/postproc/flags.sv @@ -26,49 +26,70 @@ `include "wally-config.vh" module flags( - input logic Xs, - input logic XSNaN, YSNaN, ZSNaN, // inputs are signaling NaNs - input logic XInf, YInf, ZInf, // inputs are infinity - input logic Plus1, - input logic InfIn, // is a Inf input being used - input logic NaNIn, // is a NaN input being used - input logic [`FMTBITS-1:0] OutFmt, // output format - input logic XZero, YZero, // inputs are zero - input logic Sqrt, // Sqrt? - input logic ToInt, // convert to integer - input logic IntToFp, // convert integer to floating point - input logic Int64, // convert to 64 bit integer - input logic Signed, // convert to a signed integer - input logic [`NE:0] CvtCe, // the calculated expoent - Cvt - input logic CvtOp, // conversion opperation? - input logic DivOp, // conversion opperation? - input logic FmaOp, // Fma opperation? - input logic [`NE+1:0] FullRe, // Re with bits to determine sign and overflow - input logic [`NE+1:0] Me, // exponent of the normalized sum - input logic [1:0] CvtNegResMsbs, // the negitive integer result's most significant bits - input logic FmaAs, FmaPs, // the product and modified Z signs - input logic Round, Guard, Sticky, UfPlus1, // bits used to determine rounding - output logic DivByZero, - output logic IntInvalid, Invalid, Overflow, // flags used to select the res - output logic [4:0] PostProcFlg // flags + input logic Xs, // X sign + input logic [`FMTBITS-1:0] OutFmt, // output format + input logic InfIn, // is a Inf input being used + input logic XInf, YInf, ZInf, // inputs are infinity + input logic NaNIn, // is a NaN input being used + input logic XSNaN, YSNaN, ZSNaN, // inputs are signaling NaNs + input logic XZero, YZero, // inputs are zero + input logic [`NE+1:0] FullRe, // Re with bits to determine sign and overflow + input logic [`NE+1:0] Me, // exponent of the normalized sum + // rounding + input logic Plus1, // do you add one for rounding + input logic Round, Guard, Sticky, // bits used to determine rounding + input logic UfPlus1, // do you add one for rounding for the unbounded exponent result + // convert + input logic CvtOp, // conversion opperation? + input logic ToInt, // convert to integer + input logic IntToFp, // convert integer to floating point + input logic Int64, // convert to 64 bit integer + input logic Signed, // convert to a signed integer + input logic [`NE:0] CvtCe, // the calculated expoent - Cvt + input logic [1:0] CvtNegResMsbs, // the negitive integer result's most significant bits + // divsqrt + input logic DivOp, // conversion opperation? + input logic Sqrt, // Sqrt? + // fma + input logic FmaOp, // Fma opperation? + input logic FmaAs, FmaPs, // the product and modified Z signs + // flags + output logic DivByZero, // divide by zero flag + output logic Overflow, // overflow flag to select result + output logic Invalid, // invalid flag to select the result + output logic IntInvalid, // invalid integer result to select + output logic [4:0] PostProcFlg // flags ); - logic SigNaN; // is an input a signaling NaN - logic Inexact; // inexact flag - logic FpInexact; // floating point inexact flag - logic IntInexact; // integer inexact flag - logic FmaInvalid; // integer invalid flag - logic DivInvalid; // integer invalid flag - logic Underflow; // Underflow flag - logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent - logic ShiftGtIntSz; // is the shift greater than the the integer size (use Re to account for possible roundning "shift") + logic SigNaN; // is an input a signaling NaN + logic Inexact; // final inexact flag + logic FpInexact; // floating point inexact flag + logic IntInexact; // integer inexact flag + logic FmaInvalid; // integer invalid flag + logic DivInvalid; // integer invalid flag + logic Underflow; // Underflow flag + logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent + logic ShiftGtIntSz; // is the shift greater than the the integer size (use Re to account for possible roundning "shift") /////////////////////////////////////////////////////////////////////////////// - // Flags + // Overflow /////////////////////////////////////////////////////////////////////////////// - - - if (`FPSIZES == 1) begin + // determine if the result exponent is greater than or equal to the maximum exponent or + // the shift amount is greater than the integers size (for cvt to int) + // ShiftGtIntSz calculation: + // a left shift of intlen+1 is still in range but any more than that is an overflow + // inital: | 64 0's | XLEN | + // | 64 0's | XLEN | << 64 + // | XLEN | 00000... | + // 65 = ...0 0 0 0 0 1 0 0 0 0 0 1 + // | or | | or | + // 33 = ...0 0 0 0 0 0 1 0 0 0 0 1 + // | or | | or | + // larger or equal if: + // - any of the bits after the most significan 1 is one + // - the most signifcant in 65 or 33 is still a one in the number and + // one of the later bits is one + if (`FPSIZES == 1) begin assign ResExpGteMax = &FullRe[`NE-1:0] | FullRe[`NE]; assign ShiftGtIntSz = (|FullRe[`NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64)); @@ -94,39 +115,37 @@ module flags( `S_FMT: ResExpGteMax = &FullRe[`S_NE-1:0] | (|FullRe[`Q_NE:`S_NE]); `H_FMT: ResExpGteMax = &FullRe[`H_NE-1:0] | (|FullRe[`Q_NE:`H_NE]); endcase - // a left shift of intlen+1 is still in range but any more than that is an overflow - // inital: | 64 0's | XLEN | - // | 64 0's | XLEN | << 64 - // | XLEN | 00000... | - // 65 = ...0 0 0 0 0 1 0 0 0 0 0 1 - // | or | | or | - // 33 = ...0 0 0 0 0 0 1 0 0 0 0 1 - // | or | | or | - // larger or equal if: - // - any of the bits after the most significan 1 is one - // - the most signifcant in 65 or 33 is still a one in the number and - // one of the later bits is one assign ShiftGtIntSz = (|FullRe[`Q_NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64)); end + + // calulate overflow flag: // if the result is greater than or equal to the max exponent(not taking into account sign) // | and the exponent isn't negitive // | | if the input isnt infinity or NaN // | | | assign Overflow = ResExpGteMax & ~FullRe[`NE+1]&~(InfIn|NaNIn|DivByZero); - // detecting tininess after rounding + /////////////////////////////////////////////////////////////////////////////// + // Underflow + /////////////////////////////////////////////////////////////////////////////// + + // calculate underflow flag: detecting tininess after rounding // the exponent is negitive - // | the result is Subnormalized + // | the result is subnormal // | | the result is normal and rounded from a Subnorm // | | | and if given an unbounded exponent the result does not round // | | | | and if the result is not exact // | | | | | and if the input isnt infinity or NaN // | | | | | | assign Underflow = ((FullRe[`NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&Guard)))&(Round|Sticky|Guard))&~(InfIn|NaNIn|DivByZero|Invalid); - //assign Underflow = ((FullRe[`NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&Guard)))&(Round|Sticky|Guard))&~(InfIn|NaNIn|DivByZero|Invalid|XZero); - // Set Inexact flag if the res is diffrent from what would be outputed given infinite precision + + /////////////////////////////////////////////////////////////////////////////// + // Inexact + /////////////////////////////////////////////////////////////////////////////// + + // Set Inexact flag if the result is diffrent from what would be outputed given infinite precision // - Don't set the underflow flag if an underflowed res isn't outputed assign FpInexact = (Sticky|Guard|Overflow|Round)&~(InfIn|NaNIn|DivByZero|Invalid); //assign FpInexact = (Sticky|Guard|Overflow|Round)&~(InfIn|NaNIn|DivByZero|Invalid|XZero); @@ -139,11 +158,16 @@ module flags( // select the inexact flag to output assign Inexact = ToInt ? IntInexact : FpInexact; + /////////////////////////////////////////////////////////////////////////////// + // Invalid + /////////////////////////////////////////////////////////////////////////////// + // Set Invalid flag for following cases: // 1) any input is a signaling NaN // 2) Inf - Inf (unless x or y is NaN) // 3) 0 * Inf + // invalid flag for integer result // if the input is NaN or infinity // | if the integer res overflows (out of range) // | | if the input was negitive but ouputing to a unsigned number @@ -154,16 +178,30 @@ module flags( assign IntInvalid = NaNIn|InfIn|(ShiftGtIntSz&~FullRe[`NE+1])|((Xs&~Signed)&(~((CvtCe[`NE]|(~|CvtCe))&~Plus1)))|(CvtNegResMsbs[1]^CvtNegResMsbs[0]); // | // or when the positive res rounds up out of range + assign SigNaN = (XSNaN&~(IntToFp&CvtOp)) | (YSNaN&~CvtOp) | (ZSNaN&FmaOp); + + // invalid flag for fma assign FmaInvalid = ((XInf | YInf) & ZInf & (FmaPs ^ FmaAs) & ~NaNIn) | (XZero & YInf) | (YZero & XInf); + + //invalid flag for division assign DivInvalid = ((XInf & YInf) | (XZero & YZero))&~Sqrt | (Xs&Sqrt&~NaNIn&~XZero); assign Invalid = SigNaN | (FmaInvalid&FmaOp) | (DivInvalid&DivOp); + /////////////////////////////////////////////////////////////////////////////// + // Divide by Zero + /////////////////////////////////////////////////////////////////////////////// + // if dividing by zero and not 0/0 // - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator) assign DivByZero = YZero&DivOp&~Sqrt&~(XZero|NaNIn|InfIn); + + /////////////////////////////////////////////////////////////////////////////// + // final flags + /////////////////////////////////////////////////////////////////////////////// + // Combine flags // - to integer results do not set the underflow or overflow flags assign PostProcFlg = {Invalid|(IntInvalid&CvtOp&ToInt), DivByZero, Overflow&~(ToInt&CvtOp), Underflow&~(ToInt&CvtOp), Inexact}; diff --git a/pipelined/src/fpu/postproc/fmashiftcalc.sv b/pipelined/src/fpu/postproc/fmashiftcalc.sv index dd1fb11b..79dc1f0d 100644 --- a/pipelined/src/fpu/postproc/fmashiftcalc.sv +++ b/pipelined/src/fpu/postproc/fmashiftcalc.sv @@ -23,16 +23,17 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + `include "wally-config.vh" module fmashiftcalc( - input logic [3*`NF+3:0] FmaSm, // the positive sum - input logic [$clog2(3*`NF+5)-1:0] FmaSCnt, // normalization shift count - input logic [`FMTBITS-1:0] Fmt, // precision 1 = double 0 = single - input logic [`NE+1:0] FmaSe, // sum's exponent - output logic [`NE+1:0] NormSumExp, //*** add fma // exponent of the normalized sum not taking into account Subnormal or zero results - output logic FmaSZero, // is the result Subnormalized - calculated before LZA corection - output logic FmaPreResultSubnorm, // is the result Subnormalized - calculated before LZA corection + input logic [`FMTBITS-1:0] Fmt, // precision 1 = double 0 = single + input logic [`NE+1:0] FmaSe, // sum's exponent + input logic [3*`NF+3:0] FmaSm, // the positive sum + input logic [$clog2(3*`NF+5)-1:0] FmaSCnt, // normalization shift count + output logic [`NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results + output logic FmaSZero, // is the result subnormal - calculated before LZA corection + output logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection output logic [$clog2(3*`NF+5)-1:0] FmaShiftAmt, // normalization shift count output logic [3*`NF+5:0] FmaShiftIn // is the sum zero ); @@ -42,8 +43,10 @@ module fmashiftcalc( /////////////////////////////////////////////////////////////////////////////// // Normalization /////////////////////////////////////////////////////////////////////////////// + // Determine if the sum is zero assign FmaSZero = ~(|FmaSm); + // calculate the sum's exponent assign PreNormSumExp = FmaSe + {{`NE+2-$unsigned($clog2(3*`NF+5)){1'b1}}, ~FmaSCnt} + (`NE+2)'(`NF+3); @@ -79,8 +82,7 @@ module fmashiftcalc( end - // determine if the result is Subnormalized - + // determine if the result is subnormal: (NormSumExp <= 0) & (NormSumExp >= -FracLen) & ~FmaSZero if (`FPSIZES == 1) begin logic Sum0LEZ, Sum0GEFL; assign Sum0LEZ = PreNormSumExp[`NE+1] | ~|PreNormSumExp; @@ -133,16 +135,8 @@ module fmashiftcalc( end - // 010. when should be 001. - // - shift left one - // - add one from exp - // - if kill prod dont add to exp - - // Determine if the result is Subnormal - // assign FmaPreResultSubnorm = $signed(NormSumExp)<=0 & ($signed(NormSumExp)>=$signed(-FracLen)) & ~FmaSZero; - // set and calculate the shift input and amount - // - shift once if killing a product and the result is Subnormalized + // - shift once if killing a product and the result is subnormal assign FmaShiftIn = {2'b0, FmaSm}; if (`FPSIZES == 1) assign FmaShiftAmt = FmaPreResultSubnorm ? FmaSe[$clog2(3*`NF+5)-1:0]+($clog2(3*`NF+5))'(`NF+2): FmaSCnt+1; diff --git a/pipelined/src/fpu/postproc/negateintres.sv b/pipelined/src/fpu/postproc/negateintres.sv index cbca322a..596ddb30 100644 --- a/pipelined/src/fpu/postproc/negateintres.sv +++ b/pipelined/src/fpu/postproc/negateintres.sv @@ -26,16 +26,16 @@ `include "wally-config.vh" module negateintres( - input logic Xs, - input logic [`NORMSHIFTSZ-1:0] Shifted, - input logic Signed, - input logic Int64, - input logic Plus1, - output logic [1:0] CvtNegResMsbs, - output logic [`XLEN+1:0] CvtNegRes + input logic Signed, // is the integer input signed + input logic Int64, // is the integer input 64-bits + input logic Plus1, // should one be added for rounding? + input logic Xs, // X sign + input logic [`NORMSHIFTSZ-1:0] Shifted, // output from normalization shifter + output logic [1:0] CvtNegResMsbs, // most signigficant bits of possibly negated result + output logic [`XLEN+1:0] CvtNegRes // possibly negated integer result ); - logic [2:0] CvtNegResMsbs3; + logic [2:0] CvtNegResMsbs3; // first three msbs of possibly negated result // round and negate the positive res if needed assign CvtNegRes = Xs ? -({2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}; diff --git a/pipelined/src/fpu/postproc/normshift.sv b/pipelined/src/fpu/postproc/normshift.sv index 541c703b..d48e9758 100644 --- a/pipelined/src/fpu/postproc/normshift.sv +++ b/pipelined/src/fpu/postproc/normshift.sv @@ -26,7 +26,7 @@ `include "wally-config.vh" - // convert shift + // convert shift // fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp // process: // - start - CalcExp = 1 + XExp - Largest Bias @@ -41,7 +41,7 @@ // | keep | // // fp -> fp: - // - if result is Subnormalized or underflowed: + // - if result is subnormal or underflowed: // | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1 // process: // - start @@ -54,17 +54,26 @@ // | 0's | mantissa | 0's | // | keep | // - // - if the input is Subnormalized: + // - if the input is subnormal: // | lzcIn | 0's if nessisary | << ZeroCnt+1 // - plus 1 to shift out the first 1 // // int -> fp: | lzcIn | 0's if nessisary | << ZeroCnt+1 // - plus 1 to shift out the first 1 + // fma shift + // | 00 | Sm | << LZA output + // . + // - two extra bits so we can correct for an LZA error of 1 or 2 + + // divsqrt shift + // | Nf 0's | Qm | << calculated shift amount + // . + module normshift( - input logic [`LOGNORMSHIFTSZ-1:0] ShiftAmt, // normalization shift count - input logic [`NORMSHIFTSZ-1:0] ShiftIn, // is the sum zero - output logic [`NORMSHIFTSZ-1:0] Shifted // is the sum zero + input logic [`LOGNORMSHIFTSZ-1:0] ShiftAmt, // shift amount + input logic [`NORMSHIFTSZ-1:0] ShiftIn, // number to be shifted + output logic [`NORMSHIFTSZ-1:0] Shifted // shifted result ); assign Shifted = ShiftIn << ShiftAmt; diff --git a/pipelined/src/fpu/postproc/postprocess.sv b/pipelined/src/fpu/postproc/postprocess.sv index 1e8b9aec..3906ad57 100644 --- a/pipelined/src/fpu/postproc/postprocess.sv +++ b/pipelined/src/fpu/postproc/postprocess.sv @@ -33,83 +33,85 @@ module postprocess ( input logic [2:0] Frm, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude input logic [`FMTBITS-1:0] Fmt, // precision 1 = double 0 = single input logic [2:0] OpCtrl, // choose which opperation (look below for values) - input logic XZero, YZero, // inputs are zero + input logic XZero, YZero, // inputs are zero input logic XInf, YInf, ZInf, // inputs are infinity input logic XNaN, YNaN, ZNaN, // inputs are NaN input logic XSNaN, YSNaN, ZSNaN, // inputs are signaling NaNs - input logic [1:0] PostProcSel, // select result to be written to fp register + input logic [1:0] PostProcSel, // select result to be written to fp register //fma signals - input logic FmaAs, // the modified Z sign - depends on instruction - input logic FmaPs, // the product's sign - input logic [`NE+1:0] FmaSe, // the sum's exponent - input logic [3*`NF+3:0] FmaSm, // the positive sum + input logic FmaAs, // the modified Z sign - depends on instruction + input logic FmaPs, // the product's sign + input logic FmaSs, // Sum sign + input logic [`NE+1:0] FmaSe, // the sum's exponent + input logic [3*`NF+3:0] FmaSm, // the positive sum input logic FmaASticky, // sticky bit that is calculated during alignment - input logic FmaSs, // - input logic [$clog2(3*`NF+5)-1:0] FmaSCnt, // the normalization shift count + input logic [$clog2(3*`NF+5)-1:0] FmaSCnt, // the normalization shift count //divide signals - input logic DivS, - input logic [`NE+1:0] DivQe, - input logic [`DIVb:0] DivQm, + input logic DivSticky, // divider sticky bit + input logic [`NE+1:0] DivQe, // divsqrt exponent + input logic [`DIVb:0] DivQm, // divsqrt significand // conversion signals - input logic CvtCs, // the result's sign - input logic [`NE:0] CvtCe, // the calculated expoent - input logic CvtResSubnormUf, - input logic [`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 [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (priority encoder) - input logic IntZero, // is the input zero + input logic CvtCs, // the result's sign + input logic [`NE:0] CvtCe, // the calculated expoent + input logic CvtResSubnormUf, // the convert result is subnormal or underflows + input logic [`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 [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb) + input logic IntZero, // is the integer input zero // final results - output logic [`FLEN-1:0] PostProcRes, // FMA final result - output logic [4:0] PostProcFlg, - output logic [`XLEN-1:0] FCvtIntRes // the int conversion result + output logic [`FLEN-1:0] PostProcRes,// postprocessor final result + output logic [4:0] PostProcFlg,// postprocesser flags + output logic [`XLEN-1:0] FCvtIntRes // the integer conversion result ); // general signals - logic Rs; - logic [`NF-1:0] Rf; // Result fraction - logic [`NE-1:0] Re; // Result exponent - logic Ms; - logic [`NE+1:0] Me; - logic [`CORRSHIFTSZ-1:0] Mf; // corectly shifted fraction - logic [`NE+1:0] FullRe; // Re with bits to determine sign and overflow - logic UfPlus1; // do you add one (for determining underflow flag) - logic [`LOGNORMSHIFTSZ-1:0] ShiftAmt; // normalization shift count - logic [`NORMSHIFTSZ-1:0] ShiftIn; // is the sum zero - logic [`NORMSHIFTSZ-1:0] Shifted; // the shifted result - logic Plus1; // add one to the final result? - logic IntInvalid, Overflow, Invalid; // flags - logic Guard, Round, Sticky; // bits needed to determine rounding - logic [`FMTBITS-1:0] OutFmt; + logic Rs; // result sign + logic [`NF-1:0] Rf; // Result fraction + logic [`NE-1:0] Re; // Result exponent + logic Ms; // norMalized sign + logic [`CORRSHIFTSZ-1:0] Mf; // norMalized fraction + logic [`NE+1:0] Me; // normalized exponent + logic [`NE+1:0] FullRe; // Re with bits to determine sign and overflow + logic UfPlus1; // do you add one (for determining underflow flag) + logic [`LOGNORMSHIFTSZ-1:0] ShiftAmt; // normalization shift amount + logic [`NORMSHIFTSZ-1:0] ShiftIn; // input to normalization shift + logic [`NORMSHIFTSZ-1:0] Shifted; // the ouput of the normalized shifter (before shift correction) + logic Plus1; // add one to the final result? + logic Overflow; // overflow flag used to select results + logic Invalid; // invalid flag used to select results + logic Guard, Round, Sticky; // bits needed to determine rounding + logic [`FMTBITS-1:0] OutFmt; // output format // fma signals - logic [`NE+1:0] FmaMe; // exponent of the normalized sum - logic FmaSZero; // is the sum zero - logic [3*`NF+5:0] FmaShiftIn; // shift input - logic [`NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account Subnormal or zero results - logic FmaPreResultSubnorm; // is the result Subnormalized - calculated before LZA corection - logic [$clog2(3*`NF+5)-1:0] FmaShiftAmt; // normalization shift count + logic [`NE+1:0] FmaMe; // exponent of the normalized sum + logic FmaSZero; // is the sum zero + logic [3*`NF+5:0] FmaShiftIn; // fma shift input + logic [`NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account Subnormal or zero results + logic FmaPreResultSubnorm; // is the result subnormal - calculated before LZA corection + logic [$clog2(3*`NF+5)-1:0] FmaShiftAmt;// normalization shift amount for fma // division singals - logic [`LOGNORMSHIFTSZ-1:0] DivShiftAmt; - logic [`NORMSHIFTSZ-1:0] DivShiftIn; - logic [`NE+1:0] Qe; - logic DivByZero; - logic DivResSubnorm; - logic DivSubnormShiftPos; + logic [`LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount + logic [`NORMSHIFTSZ-1:0] DivShiftIn; // divsqrt shift input + logic [`NE+1:0] Qe; // divsqrt corrected exponent after corretion shift + logic DivByZero; // divide by zero flag + logic DivResSubnorm; // is the divsqrt result subnormal + logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed) // conversion signals - logic [`CVTLEN+`NF:0] CvtShiftIn; // number to be shifted - logic [1:0] CvtNegResMsbs; - logic [`XLEN+1:0] CvtNegRes; - logic CvtResUf; + logic [`CVTLEN+`NF:0] CvtShiftIn; // number to be shifted for converter + logic [1:0] CvtNegResMsbs; // most significant bits of possibly negated int result + logic [`XLEN+1:0] CvtNegRes; // possibly negated integer result + logic CvtResUf; // did the convert result underflow + logic IntInvalid; // invalid integer flag // readability signals - logic Mult; // multiply opperation - logic Int64; // is the integer 64 bits? - logic Signed; // is the opperation with a signed integer? - logic IntToFp; // is the opperation an int->fp conversion? - logic CvtOp; - logic FmaOp; - logic DivOp; - logic InfIn; - logic NaNIn; - logic Sqrt; + logic Mult; // multiply opperation + logic Sqrt; // is the divsqrt opperation sqrt + logic Int64; // is the integer 64 bits? + logic Signed; // is the opperation with a signed integer? + logic IntToFp; // is the opperation an int->fp conversion? + logic CvtOp; // convertion opperation + logic FmaOp; // fma opperation + logic DivOp; // divider opperation + logic InfIn; // are any of the inputs infinity + logic NaNIn; // are any of the inputs NaN // signals to help readability assign Signed = OpCtrl[0]; @@ -118,7 +120,7 @@ module postprocess ( assign Mult = OpCtrl[2]&~OpCtrl[1]&~OpCtrl[0]; assign CvtOp = (PostProcSel == 2'b00); assign FmaOp = (PostProcSel == 2'b10); - assign DivOp = (PostProcSel == 2'b01); // & DivDone; + assign DivOp = (PostProcSel == 2'b01); assign Sqrt = OpCtrl[0]; // is there an input of infinity or NaN being used @@ -137,12 +139,16 @@ module postprocess ( // Normalization /////////////////////////////////////////////////////////////////////////////// + // final claulations before shifting cvtshiftcalc cvtshiftcalc(.ToInt, .CvtCe, .CvtResSubnormUf, .Xm, .CvtLzcIn, - .XZero, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn); + .XZero, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn); + fmashiftcalc fmashiftcalc(.FmaSm, .FmaSCnt, .Fmt, .NormSumExp, .FmaSe, - .FmaSZero, .FmaPreResultSubnorm, .FmaShiftAmt, .FmaShiftIn); + .FmaSZero, .FmaPreResultSubnorm, .FmaShiftAmt, .FmaShiftIn); + divshiftcalc divshiftcalc(.DivQe, .DivQm, .DivResSubnorm, .DivSubnormShiftPos, .DivShiftAmt, .DivShiftIn); + // select which unit's output to shift always_comb case(PostProcSel) 2'b10: begin // fma @@ -153,14 +159,9 @@ module postprocess ( ShiftAmt = {{`LOGNORMSHIFTSZ-$clog2(`CVTLEN+1){1'b0}}, CvtShiftAmt}; ShiftIn = {CvtShiftIn, {`NORMSHIFTSZ-`CVTLEN-`NF-1{1'b0}}}; end - 2'b01: begin //div - /* if(DivDone) begin */ + 2'b01: begin //divsqrt ShiftAmt = DivShiftAmt; ShiftIn = DivShiftIn; - /* end else begin - ShiftAmt = '0; - ShiftIn = '0; - end */ end default: begin ShiftAmt = {`LOGNORMSHIFTSZ{1'bx}}; @@ -168,11 +169,12 @@ module postprocess ( end endcase + // main normalization shift normshift normshift (.ShiftIn, .ShiftAmt, .Shifted); + // correct for LZA/divsqrt error shiftcorrection shiftcorrection(.FmaOp, .FmaPreResultSubnorm, .NormSumExp, - .DivResSubnorm, .DivSubnormShiftPos, .DivOp, .DivQe, - .Qe, .FmaSZero, .Shifted, .FmaMe, .Mf); + .DivResSubnorm, .DivSubnormShiftPos, .DivOp, .DivQe, .Qe, .FmaSZero, .Shifted, .FmaMe, .Mf); /////////////////////////////////////////////////////////////////////////////// // Rounding @@ -184,20 +186,19 @@ module postprocess ( // round to infinity // round to nearest max magnitude - + // calulate result sign used in rounding unit roundsign roundsign(.FmaOp, .DivOp, .CvtOp, .Sqrt, .FmaSs, .Xs, .Ys, .CvtCs, .Ms); round round(.OutFmt, .Frm, .FmaASticky, .Plus1, .PostProcSel, .CvtCe, .Qe, - .Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResSubnormUf, .Mf, .ToInt, .CvtResUf, - .DivS, //.DivDone, - .DivOp, .UfPlus1, .FullRe, .Rf, .Re, .Sticky, .Round, .Guard, .Me); + .Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResSubnormUf, .Mf, .ToInt, .CvtResUf, + .DivSticky, .DivOp, .UfPlus1, .FullRe, .Rf, .Re, .Sticky, .Round, .Guard, .Me); /////////////////////////////////////////////////////////////////////////////// // Sign calculation /////////////////////////////////////////////////////////////////////////////// resultsign resultsign(.Frm, .FmaPs, .FmaAs, .Round, .Sticky, .Guard, - .FmaOp, .ZInf, .InfIn, .FmaSZero, .Mult, .Ms, .Rs); + .FmaOp, .ZInf, .InfIn, .FmaSZero, .Mult, .Ms, .Rs); /////////////////////////////////////////////////////////////////////////////// // Flags @@ -214,10 +215,10 @@ module postprocess ( /////////////////////////////////////////////////////////////////////////////// negateintres negateintres(.Xs, .Shifted, .Signed, .Int64, .Plus1, .CvtNegResMsbs, .CvtNegRes); + specialcase 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, - .XInf, .YInf, .DivOp, - .DivByZero, .FullRe, .CvtCe, .Rs, .Re, .Rf, .PostProcRes, .FCvtIntRes); + .XInf, .YInf, .DivOp, .DivByZero, .FullRe, .CvtCe, .Rs, .Re, .Rf, .PostProcRes, .FCvtIntRes); endmodule diff --git a/pipelined/src/fpu/postproc/resultsign.sv b/pipelined/src/fpu/postproc/resultsign.sv index d260e549..7ecf3eb6 100644 --- a/pipelined/src/fpu/postproc/resultsign.sv +++ b/pipelined/src/fpu/postproc/resultsign.sv @@ -23,48 +23,53 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + `include "wally-config.vh" module resultsign( - input logic [2:0] Frm, - input logic FmaPs, FmaAs, - input logic ZInf, - input logic InfIn, - input logic FmaOp, - input logic FmaSZero, - input logic Mult, - input logic Round, - input logic Sticky, - input logic Guard, - input logic Ms, - output logic Rs + input logic [2:0] Frm, // rounding mode + input logic FmaOp, // is the operation an Fma + input logic Mult, // is the fma opperation multipy + input logic ZInf, // is Z infinity + input logic InfIn, // are any of the inputs infinity + input logic FmaSZero, // is the fma sum zero + input logic Ms, // normalized result sign + input logic FmaPs, // product's sign + input logic FmaAs, // aligned addend's sign + input logic Guard, // guard bit for rounding + input logic Round, // round bit for rounding + input logic Sticky, // sticky bit for rounding + output logic Rs // result sign ); - logic Zeros; - logic Infs; + logic Zeros; // zero result sign + logic Infs; // infinity result sign - // The IEEE754-2019 standard specifies: + // determine the sign for a result of 0 + // The IEEE754-2019 standard specifies: // - the sign of an exact zero sum (with operands of diffrent signs) should be positive unless rounding toward negitive infinity // - when the exact result of an FMA opperation is non-zero, but is zero due to rounding, use the sign of the exact result // - if x = +0 or -0 then x+x=x and x-(-x)=x // - the sign of a product is the exclisive or or the opperand's signs - // Zero sign will only be selected if: + // Zero sign will only be selected if: // - P=Z and a cancelation occurs - exact zero // - Z is zero and P is zero - exact zero // - P is killed and Z is zero - Psgn // - Z is killed and P is zero - impossible - // Zero sign calculation: + // Zero sign calculation: // - if a multiply opperation is done, then use the products sign(Ps) // - if the zero sum is not exactly zero i.e. Round|Sticky use the sign of the exact result (which is the product's sign) // - if an effective addition occurs (P+A or -P+-A or P--A) then use the product's sign assign Zeros = (FmaPs^FmaAs)&~(Round|Guard|Sticky)&~Mult ? Frm[1:0] == 2'b10 : FmaPs; - - // is the result negitive - // if p - z is the Sum negitive - // if -p + z is the Sum positive - // if -p - z then the Sum is negitive + // determine the sign of an infinity result + // is the result negitive + // if p - z is the Sum negitive + // if -p + z is the Sum positive + // if -p - z then the Sum is negitive assign Infs = ZInf ? FmaAs : FmaPs; + + // select the result sign always_comb if(InfIn&FmaOp) Rs = Infs; else if(FmaSZero&FmaOp) Rs = Zeros; diff --git a/pipelined/src/fpu/postproc/round.sv b/pipelined/src/fpu/postproc/round.sv index 04cd1767..62b7d92b 100644 --- a/pipelined/src/fpu/postproc/round.sv +++ b/pipelined/src/fpu/postproc/round.sv @@ -23,7 +23,9 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + `include "wally-config.vh" + // what position is XLEN in? // options: // 1: XLEN > NF > NF1 @@ -33,38 +35,45 @@ `define XLENPOS ((`XLEN>`NF) ? 1 : (`XLEN>`NF1) ? 2 : 3) module round( - input logic [`FMTBITS-1:0] OutFmt, // precision 1 = double 0 = single - input logic [2:0] Frm, // rounding mode - input logic FmaOp, // is an fma opperation being done? - input logic DivOp, // is a division opperation being done - input logic CvtOp, // is a convert opperation being done - input logic ToInt, // is the cvt op a cvt to integer - input logic [1:0] PostProcSel, // select the postprocessor output - input logic CvtResSubnormUf, // is the cvt result subnormal or underflow - input logic CvtResUf, - input logic [`CORRSHIFTSZ-1:0] Mf, - input logic FmaASticky, // addend's sticky bit - input logic [`NE+1:0] FmaMe, // exponent of the normalized sum - input logic Ms, // the result's sign - input logic [`NE:0] CvtCe, // the calculated expoent - input logic [`NE+1:0] Qe, // the calculated expoent - input logic DivS, // sticky bit - output logic UfPlus1, // do you add or subtract on from the result - output logic [`NE+1:0] FullRe, // Re with bits to determine sign and overflow - output logic [`NF-1:0] Rf, // Result fraction - output logic [`NE-1:0] Re, // Result exponent + input logic [`FMTBITS-1:0] OutFmt, // output format + input logic [2:0] Frm, // rounding mode + input logic [1:0] PostProcSel, // select the postprocessor output + input logic Ms, // normalized sign + input logic [`CORRSHIFTSZ-1:0] Mf, // normalized fraction + // fma + input logic FmaOp, // is an fma opperation being done? + input logic [`NE+1:0] FmaMe, // exponent of the normalized sum for fma + input logic FmaASticky, // addend's sticky bit + // divsqrt + input logic DivOp, // is a division opperation being done + input logic DivSticky, // divsqrt sticky bit + input logic [`NE+1:0] Qe, // the divsqrt calculated expoent + // cvt + input logic CvtOp, // is a convert opperation being done + input logic ToInt, // is the cvt op a cvt to integer + input logic CvtResSubnormUf, // is the cvt result subnormal or underflow + input logic CvtResUf, // does the cvt result underflow + input logic [`NE:0] CvtCe, // the cvt calculated expoent + // outputs + output logic [`NE+1:0] Me, // normalied fraction + output logic UfPlus1, // do you add one to the result if given an unbounded exponent + output logic [`NE+1:0] FullRe, // Re with bits to determine sign and overflow + output logic [`NE-1:0] Re, // Result exponent + output logic [`NF-1:0] Rf, // Result fractionNormS output logic Sticky, // sticky bit - output logic [`NE+1:0] Me, - output logic Plus1, - output logic Round, Guard // bits needed to calculate rounding + output logic Plus1, // do you add one to the final result + output logic Round, Guard // bits needed to calculate rounding ); - logic UfCalcPlus1; - logic NormS; // normalized sum's sticky bit - logic [`NF-1:0] RoundFrac; - logic FpRes, IntRes; - logic FpGuard, FpLsbRes, FpRound; - logic LsbRes; // lsb of result - logic CalcPlus1, FpPlus1; + logic UfCalcPlus1; // calculated plus one for unbounded exponent + logic NormSticky; // normalized sum's sticky bit + logic [`NF-1:0] RoundFrac; // rounded fraction + logic FpRes; // is the result a floating point + logic IntRes; // is the result an integer + logic FpGuard, FpRound; // floating point round/guard bits + logic FpLsbRes; // least significant bit of floating point result + logic LsbRes; // lsb of result + logic CalcPlus1; // calculated plus1 + logic FpPlus1; // do you add one to the fp result logic [`FLEN:0] RoundAdd; // how much to add to the result /////////////////////////////////////////////////////////////////////////////// @@ -97,21 +106,23 @@ module round( // 11 - do nothing if a small number was supposed to subtracted (the sticky bit was set by the small number) // - Plus 1 otherwise + + // determine what format the final result is in: int or fp assign IntRes = CvtOp & ToInt; assign FpRes = ~IntRes; // sticky bit calculation if (`FPSIZES == 1) begin - // 1: XLEN > NF - // | XLEN | - // | NF |1|1| - // ^ ^ if floating point result - // ^ if not an FMA result - if (`XLENPOS == 1)assign NormS = (|Mf[`CORRSHIFTSZ-`NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes) | + // 1: XLEN > NF + // | XLEN | + // | NF |1|1| + // ^ ^ if floating point result + // ^ if not an FMA result + if (`XLENPOS == 1)assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes) | (|Mf[`CORRSHIFTSZ-`XLEN-2:0]); - // 2: NF > XLEN - if (`XLENPOS == 2)assign NormS = (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF-1]&IntRes) | + // 2: NF > XLEN + if (`XLENPOS == 2)assign NormSticky = (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF-1]&IntRes) | (|Mf[`CORRSHIFTSZ-`NF-2:0]); end else if (`FPSIZES == 2) begin @@ -119,31 +130,31 @@ module round( // so half and single are always smaller then XLEN // 1: XLEN > NF > NF1 - if (`XLENPOS == 1) assign NormS = (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`NF-1]&FpRes&~OutFmt) | + if (`XLENPOS == 1) assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`NF-1]&FpRes&~OutFmt) | (|Mf[`CORRSHIFTSZ-`NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes) | (|Mf[`CORRSHIFTSZ-`XLEN-2:0]); // 2: NF > XLEN > NF1 - if (`XLENPOS == 2) assign NormS = (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&~OutFmt) | + if (`XLENPOS == 2) assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&~OutFmt) | (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF-1]&(IntRes|~OutFmt)) | (|Mf[`CORRSHIFTSZ-`NF-2:0]); // 3: NF > NF1 > XLEN - if (`XLENPOS == 3) assign NormS = (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF1-1]&IntRes) | + if (`XLENPOS == 3) assign NormSticky = (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF1-1]&IntRes) | (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`NF-1]&(~OutFmt|IntRes)) | (|Mf[`CORRSHIFTSZ-`NF-2:0]); end else if (`FPSIZES == 3) begin // 1: XLEN > NF > NF1 - if (`XLENPOS == 1) assign NormS = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`NF1-1]&FpRes&(OutFmt==`FMT1)) | + if (`XLENPOS == 1) assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`NF1-1]&FpRes&(OutFmt==`FMT1)) | (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`NF-1]&FpRes&~(OutFmt==`FMT)) | (|Mf[`CORRSHIFTSZ-`NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes) | (|Mf[`CORRSHIFTSZ-`XLEN-2:0]); // 2: NF > XLEN > NF1 - if (`XLENPOS == 2) assign NormS = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`NF1-1]&FpRes&(OutFmt==`FMT1)) | + if (`XLENPOS == 2) assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`NF1-1]&FpRes&(OutFmt==`FMT1)) | (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&~(OutFmt==`FMT)) | (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF-1]&(IntRes|~(OutFmt==`FMT))) | (|Mf[`CORRSHIFTSZ-`NF-2:0]); // 3: NF > NF1 > XLEN - if (`XLENPOS == 3) assign NormS = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&(OutFmt==`FMT1)) | + if (`XLENPOS == 3) assign NormSticky = (|Mf[`CORRSHIFTSZ-`NF2-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&(OutFmt==`FMT1)) | (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`NF1-1]&((OutFmt==`FMT1)|IntRes)) | (|Mf[`CORRSHIFTSZ-`NF1-2:`CORRSHIFTSZ-`NF-1]&(~(OutFmt==`FMT)|IntRes)) | (|Mf[`CORRSHIFTSZ-`NF-2:0]); @@ -151,14 +162,14 @@ module round( end else if (`FPSIZES == 4) begin // Quad precision will always be greater than XLEN // 2: NF > XLEN > NF1 - if (`XLENPOS == 2) assign NormS = (|Mf[`CORRSHIFTSZ-`H_NF-2:`CORRSHIFTSZ-`S_NF-1]&FpRes&(OutFmt==`H_FMT)) | + if (`XLENPOS == 2) assign NormSticky = (|Mf[`CORRSHIFTSZ-`H_NF-2:`CORRSHIFTSZ-`S_NF-1]&FpRes&(OutFmt==`H_FMT)) | (|Mf[`CORRSHIFTSZ-`S_NF-2:`CORRSHIFTSZ-`D_NF-1]&FpRes&((OutFmt==`S_FMT)|(OutFmt==`H_FMT))) | (|Mf[`CORRSHIFTSZ-`D_NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&~(OutFmt==`Q_FMT)) | (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`Q_NF-1]&(~(OutFmt==`Q_FMT)|IntRes)) | (|Mf[`CORRSHIFTSZ-`Q_NF-2:0]); // 3: NF > NF1 > XLEN // The extra XLEN bit will be ored later when caculating the final sticky bit - the ufplus1 not needed for integer - if (`XLENPOS == 3) assign NormS = (|Mf[`CORRSHIFTSZ-`H_NF-2:`CORRSHIFTSZ-`S_NF-1]&FpRes&(OutFmt==`H_FMT)) | + if (`XLENPOS == 3) assign NormSticky = (|Mf[`CORRSHIFTSZ-`H_NF-2:`CORRSHIFTSZ-`S_NF-1]&FpRes&(OutFmt==`H_FMT)) | (|Mf[`CORRSHIFTSZ-`S_NF-2:`CORRSHIFTSZ-`XLEN-1]&FpRes&((OutFmt==`S_FMT)|(OutFmt==`H_FMT))) | (|Mf[`CORRSHIFTSZ-`XLEN-2:`CORRSHIFTSZ-`D_NF-1]&((OutFmt==`S_FMT)|(OutFmt==`H_FMT)|IntRes)) | (|Mf[`CORRSHIFTSZ-`D_NF-2:`CORRSHIFTSZ-`Q_NF-1]&(~(OutFmt==`Q_FMT)|IntRes)) | @@ -170,8 +181,11 @@ module round( // only add the Addend sticky if doing an FMA opperation // - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits) - assign Sticky = FmaASticky&FmaOp | NormS | CvtResUf&CvtOp | FmaMe[`NE+1]&FmaOp | DivS&DivOp; + assign Sticky = FmaASticky&FmaOp | NormSticky | CvtResUf&CvtOp | FmaMe[`NE+1]&FmaOp | DivSticky&DivOp; + + + // determine round and LSB of the rounded value // - underflow round bit is used to determint the underflow flag if (`FPSIZES == 1) begin @@ -266,7 +280,10 @@ module round( assign FpPlus1 = Plus1&~(ToInt&CvtOp); assign UfPlus1 = UfCalcPlus1 & (Sticky|Round); - // Compute rounded result + + + + // place Plus1 into the proper position for the format if (`FPSIZES == 1) begin assign RoundAdd = {{`FLEN{1'b0}}, FpPlus1}; @@ -283,9 +300,14 @@ module round( end else if (`FPSIZES == 4) assign RoundAdd = {(`Q_NE+1+`H_NF)'(0), FpPlus1&(OutFmt==`H_FMT), (`S_NF-`H_NF-1)'(0), FpPlus1&(OutFmt==`S_FMT), (`D_NF-`S_NF-1)'(0), FpPlus1&(OutFmt==`D_FMT), (`Q_NF-`D_NF-1)'(0), FpPlus1&(OutFmt==`Q_FMT)}; - // determine the result to be roundned + + + // trim unneeded bits from fraction assign RoundFrac = Mf[`CORRSHIFTSZ-1:`CORRSHIFTSZ-`NF]; + + + // select the exponent always_comb case(PostProcSel) 2'b10: Me = FmaMe; // fma @@ -295,6 +317,8 @@ module round( default: Me = '0; endcase + + // round the result // - if the fraction overflows one should be added to the exponent assign {FullRe, Rf} = {Me, RoundFrac} + RoundAdd; diff --git a/pipelined/src/fpu/postproc/roundsign.sv b/pipelined/src/fpu/postproc/roundsign.sv index 9bc7c108..e768332a 100644 --- a/pipelined/src/fpu/postproc/roundsign.sv +++ b/pipelined/src/fpu/postproc/roundsign.sv @@ -4,7 +4,7 @@ // Written: me@KatherineParry.com // Modified: 7/5/2022 // -// Purpose: Sign calculation ofr rounding +// Purpose: Sign calculation for rounding // // A component of the CORE-V-WALLY configurable RISC-V project. // @@ -26,22 +26,23 @@ `include "wally-config.vh" module roundsign( - input logic Xs, - input logic Ys, - input logic Sqrt, - input logic FmaOp, - input logic DivOp, - input logic CvtOp, - input logic CvtCs, - input logic FmaSs, - output logic Ms + input logic Xs, // x sign + input logic Ys, // y sign + input logic CvtCs, // convert result sign + input logic FmaSs, // fma sum sign + input logic Sqrt, // sqrt oppertion? (when using divsqrt unit) + input logic FmaOp, // is fma opperation + input logic DivOp, // is divsqrt opperation + input logic CvtOp, // is cvt opperation + output logic Ms // normalized result sign ); - logic Qs; + logic Qs; // divsqrt result sign + // calculate divsqrt sign assign Qs = Xs^(Ys&~Sqrt); - // Sign for rounding calulation + // Select sign for rounding calulation assign Ms = (FmaSs&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp); endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/postproc/shiftcorrection.sv b/pipelined/src/fpu/postproc/shiftcorrection.sv index 673f7cd9..602e72e7 100644 --- a/pipelined/src/fpu/postproc/shiftcorrection.sv +++ b/pipelined/src/fpu/postproc/shiftcorrection.sv @@ -26,39 +26,58 @@ `include "wally-config.vh" module shiftcorrection( - input logic [`NORMSHIFTSZ-1:0] Shifted, // the shifted sum before LZA correction - input logic FmaOp, - input logic DivOp, - input logic DivResSubnorm, - input logic [`NE+1:0] DivQe, - input logic DivSubnormShiftPos, - input logic [`NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results - input logic FmaPreResultSubnorm, // is the result Subnormalized - calculated before LZA corection + input logic [`NORMSHIFTSZ-1:0] Shifted, // the shifted sum before LZA correction + // divsqrt + input logic DivOp, // is it a divsqrt opperation + input logic DivResSubnorm, // is the divsqrt result subnormal + input logic [`NE+1:0] DivQe, // the divsqrt result's exponent + input logic DivSubnormShiftPos, // is the subnorm divider shift amount positive (ie not underflowed) + //fma + input logic FmaOp, // is it an fma opperation + input logic [`NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results + input logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection input logic FmaSZero, - output logic [`CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction - output logic [`NE+1:0] Qe, - output logic [`NE+1:0] FmaMe // exponent of the normalized sum + // output + output logic [`NE+1:0] FmaMe, // exponent of the normalized sum + output logic [`CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction + output logic [`NE+1:0] Qe // corrected exponent for divider ); - logic [3*`NF+3:0] CorrSumShifted; // the shifted sum after LZA correction - logic [`CORRSHIFTSZ-1:0] CorrQmShifted; - logic ResSubnorm; // is the result Subnormalized - logic LZAPlus1; // add one or two to the sum's exponent due to LZA correction + logic [3*`NF+3:0] CorrSumShifted; // the shifted sum after LZA correction + logic [`CORRSHIFTSZ-1:0] CorrQmShifted; // the shifted divsqrt result after one bit shift + logic ResSubnorm; // is the result Subnormal + logic LZAPlus1; // add one or two to the sum's exponent due to LZA correction + logic LeftShiftQm; // should the divsqrt result be shifted one to the left // LZA correction assign LZAPlus1 = Shifted[`NORMSHIFTSZ-1]; - // the only possible mantissa for a plus two is all zeroes - a one has to propigate all the way through a sum. so we can leave the bottom statement alone - assign CorrSumShifted = LZAPlus1 ? Shifted[`NORMSHIFTSZ-2:1] : Shifted[`NORMSHIFTSZ-3:0]; - // if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm) - assign CorrQmShifted = (LZAPlus1|(DivQe==1&~LZAPlus1)) ? Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ-1] : Shifted[`NORMSHIFTSZ-3:`NORMSHIFTSZ-`CORRSHIFTSZ-2]; - // if the result of the divider was calculated to be Subnormalized, then the result was correctly normalized, so select the top shifted bits + + // correct the shifting error caused by the LZA + // - the only possible mantissa for a plus two is all zeroes + // - a one has to propigate all the way through a sum. so we can leave the bottom statement alone + mux2 #(`NORMSHIFTSZ-2) lzacorrmux(Shifted[`NORMSHIFTSZ-3:0], Shifted[`NORMSHIFTSZ-2:1], LZAPlus1, CorrSumShifted); + + // correct the shifting of the divsqrt caused by producing a result in (2, .5] range + // condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm) + assign LeftShiftQm = (LZAPlus1|(DivQe==1&~LZAPlus1)); + mux2 #(`CORRSHIFTSZ) divcorrmux(Shifted[`NORMSHIFTSZ-3:`NORMSHIFTSZ-`CORRSHIFTSZ-2], + Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ-1], LeftShiftQm, CorrQmShifted); + + // if the result of the divider was calculated to be subnormal, then the result was correctly normalized, so select the top shifted bits always_comb if(FmaOp) Mf = {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+4){1'b0}}}; - else if (DivOp&~DivResSubnorm) Mf = CorrQmShifted; + else if (DivOp&~DivResSubnorm) Mf = CorrQmShifted; else Mf = Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ]; // Determine sum's exponent - // if plus1 If plus2 if said Subnorm but norm plus 1 if said Subnorm but norm plus 2 - assign FmaMe = (NormSumExp+{{`NE+1{1'b0}}, LZAPlus1} +{{`NE+1{1'b0}}, ~ResSubnorm&FmaPreResultSubnorm}) & {`NE+2{~(FmaSZero|ResSubnorm)}}; - // recalculate if the result is Subnormalized + // main exponent issues: + // - LZA was one too large + // - LZA was two too large + // - if the result was calulated to be subnorm but it's norm and the LZA was off by 1 + // - if the result was calulated to be subnorm but it's norm and the LZA was off by 2 + // if plus1 If plus2 kill if the result Zero or actually subnormal + // | | | + assign FmaMe = (NormSumExp+{{`NE+1{1'b0}}, LZAPlus1} +{{`NE+1{1'b0}}, FmaPreResultSubnorm}) & {`NE+2{~(FmaSZero|ResSubnorm)}}; + + // recalculate if the result is subnormal after LZA correction assign ResSubnorm = FmaPreResultSubnorm&~Shifted[`NORMSHIFTSZ-2]&~Shifted[`NORMSHIFTSZ-1]; // the quotent is in the range [.5,2) if there is no early termination diff --git a/pipelined/src/fpu/postproc/specialcase.sv b/pipelined/src/fpu/postproc/specialcase.sv index 32f8692c..9c9663c9 100644 --- a/pipelined/src/fpu/postproc/specialcase.sv +++ b/pipelined/src/fpu/postproc/specialcase.sv @@ -27,48 +27,60 @@ `include "wally-config.vh" module specialcase( - input logic Xs, // input signs - input logic [`NF:0] Xm, Ym, Zm, // input mantissas - input logic XNaN, YNaN, ZNaN, // inputs are NaN - input logic [2:0] Frm, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude - input logic [`FMTBITS-1:0] OutFmt, // output format - input logic InfIn, - input logic NaNIn, - input logic XInf, YInf, - input logic XZero, - input logic IntZero, - input logic IntToFp, - input logic Int64, - input logic Signed, - input logic CvtOp, - input logic DivOp, - input logic FmaOp, - input logic Plus1, - input logic DivByZero, - input logic [`NE:0] CvtCe, // the calculated expoent - input logic Rs, // the res's sign - input logic IntInvalid, Invalid, Overflow, // flags - input logic CvtResUf, - input logic [`NE-1:0] Re, // Res exponent - input logic [`NE+1:0] FullRe, // Res exponent - input logic [`NF-1:0] Rf, // Res fraction - input logic [`XLEN+1:0] CvtNegRes, // the negation of the result - output logic [`FLEN-1:0] PostProcRes, // final res - output logic [`XLEN-1:0] FCvtIntRes // final res + input logic Xs, // X sign + input logic [`NF:0] Xm, Ym, Zm, // input significand's + input logic XNaN, YNaN, ZNaN, // are the inputs NaN + input logic [2:0] Frm, // rounding mode + input logic [`FMTBITS-1:0] OutFmt, // output format + input logic InfIn, // are any inputs infinity + input logic NaNIn, // are any input NaNs + input logic XInf, YInf, // are X or Y inifnity + input logic XZero, // is X zero + input logic Plus1, // do you add one for rounding + input logic Rs, // the result's sign + input logic Invalid, Overflow, // flags to choose the result + input logic [`NE-1:0] Re, // Result exponent + input logic [`NE+1:0] FullRe, // Result full exponent + input logic [`NF-1:0] Rf, // Result fraction + // fma + input logic FmaOp, // is it a fma opperation + // divsqrt + input logic DivOp, // is it a divsqrt opperation + input logic DivByZero, // divide by zero flag + // cvt + input logic CvtOp, // is it a conversion opperation + input logic IntZero, // is the integer input zero + 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 [`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 + input logic [`XLEN+1:0] CvtNegRes, // the possibly negated of the integer result + // outputs + output logic [`FLEN-1:0] PostProcRes,// final result + output logic [`XLEN-1:0] FCvtIntRes // final integer result ); - logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, UfRes, NormRes; // possible results - logic OfResMax; - logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output - logic KillRes; - logic SelOfRes; + logic [`FLEN-1:0] XNaNRes; // X is NaN result + logic [`FLEN-1:0] YNaNRes; // Y is NaN result + logic [`FLEN-1:0] ZNaNRes; // Z is NaN result + logic [`FLEN-1:0] InvalidRes; // Invalid result result + logic [`FLEN-1:0] UfRes; // underflowed result result + logic [`FLEN-1:0] OfRes; // overflowed result result + logic [`FLEN-1:0] NormRes; // normal result + logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output + 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 // does the overflow result output the maximum normalized floating point number // output infinity if the input is infinity assign OfResMax = (~InfIn|(IntToFp&CvtOp))&~DivByZero&((Frm[1:0]==2'b01) | (Frm[1:0]==2'b10&~Rs) | (Frm[1:0]==2'b11&Rs)); - if (`FPSIZES == 1) begin + // select correct outputs for special cases + if (`FPSIZES == 1) begin //NaN res selection depending on standard if(`IEEE754) begin assign XNaNRes = {1'b0, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]}; @@ -83,7 +95,7 @@ module specialcase( assign UfRes = {Rs, {`FLEN-2{1'b0}}, Plus1&Frm[1]&~(DivOp&YInf)}; assign NormRes = {Rs, Re, Rf}; - end else if (`FPSIZES == 2) begin //will the format conversion in killprod work in other conversions? + end else if (`FPSIZES == 2) begin if(`IEEE754) begin assign XNaNRes = OutFmt ? {1'b0, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF1]}; assign YNaNRes = OutFmt ? {1'b0, {`NE{1'b1}}, 1'b1, Ym[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, Ym[`NF-2:`NF-`NF1]}; @@ -217,12 +229,11 @@ module specialcase( end OfRes = OfResMax ? {{`FLEN-`H_LEN{1'b1}}, Rs, {`H_NE-1{1'b1}}, 1'b0, {`H_NF{1'b1}}} : {{`FLEN-`H_LEN{1'b1}}, Rs, {`H_NE{1'b1}}, (`H_NF)'(0)}; - // zero is exact fi dividing by infinity so don't add 1 + // zero is exact if dividing by infinity so don't add 1 UfRes = {{`FLEN-`H_LEN{1'b1}}, Rs, (`H_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)}; NormRes = {{`FLEN-`H_LEN{1'b1}}, Rs, Re[`H_NE-1:0], Rf[`NF-1:`NF-`H_NF]}; end endcase - end @@ -234,7 +245,11 @@ module specialcase( // - dont set to zero if fp input is zero but not using the fp input // - dont set to zero if int input is zero but not using the int input assign KillRes = CvtOp ? (CvtResUf|(XZero&~IntToFp)|(IntZero&IntToFp)) : FullRe[`NE+1] | (((YInf&~XInf)|XZero)&DivOp);//Underflow & ~ResSubnorm & (Re!=1); + + // calculate if the overflow result should be selected assign SelOfRes = Overflow|DivByZero|(InfIn&~(YInf&DivOp)); + + // output infinity with result sign if divide by zero if(`IEEE754) always_comb @@ -252,17 +267,15 @@ module specialcase( else if(KillRes) PostProcRes = UfRes; else PostProcRes = NormRes; + + + + + /////////////////////////////////////////////////////////////////////////////////////// - // - // ||||||||||| ||| ||| ||||||||||||| - // ||| |||||| ||| ||| - // ||| ||| ||| ||| ||| - // ||| ||| |||||| ||| - // ||||||||||| ||| ||| ||| - // + // integer result selection /////////////////////////////////////////////////////////////////////////////////////// - // *** probably can optimize the negation // select the overflow integer res // - negitive infinity and out of range negitive input // | int | long | diff --git a/pipelined/src/fpu/unpack.sv b/pipelined/src/fpu/unpack.sv index be914fcf..47eb4fb6 100644 --- a/pipelined/src/fpu/unpack.sv +++ b/pipelined/src/fpu/unpack.sv @@ -26,23 +26,23 @@ `include "wally-config.vh" module unpack ( - input logic [`FLEN-1:0] X, Y, Z, // inputs from register file - input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half - input logic XEn, YEn, ZEn, - output logic Xs, Ys, Zs, // sign bits of XYZ - output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision) - output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision) + input logic [`FLEN-1:0] X, Y, Z, // inputs from register file + input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half + input logic XEn, YEn, ZEn, // input enables + output logic Xs, Ys, Zs, // sign bits of XYZ + output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision) + output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision) output logic XNaN, YNaN, ZNaN, // is XYZ a NaN output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN - output logic XSubnorm, // is X Subnormalized - output logic XZero, YZero, ZZero, // is XYZ zero - output logic XInf, YInf, ZInf, // is XYZ infinity - output logic XExpMax // does X have the maximum exponent (NaN or Inf) + output logic XSubnorm, // is X subnormal + output logic XZero, YZero, ZZero, // is XYZ zero + output logic XInf, YInf, ZInf, // is XYZ infinity + output logic XExpMax // does X have the maximum exponent (NaN or Inf) ); - logic XExpNonZero, YExpNonZero, ZExpNonZero; // is the exponent of XYZ non-zero - logic XFracZero, YFracZero, ZFracZero; // is the fraction zero - logic YExpMax, ZExpMax; // is the exponent all 1s + logic XExpNonZero, YExpNonZero, ZExpNonZero; // is the exponent of XYZ non-zero + logic XFracZero, YFracZero, ZFracZero; // is the fraction zero + logic YExpMax, ZExpMax; // is the exponent all 1s unpackinput unpackinputX (.In(X), .Fmt, .Sgn(Xs), .Exp(Xe), .Man(Xm), .En(XEn), .NaN(XNaN), .SNaN(XSNaN), .ExpNonZero(XExpNonZero), @@ -55,6 +55,6 @@ module unpack ( unpackinput unpackinputZ (.In(Z), .Fmt, .Sgn(Zs), .Exp(Ze), .Man(Zm), .En(ZEn), .NaN(ZNaN), .SNaN(ZSNaN), .ExpNonZero(ZExpNonZero), .Zero(ZZero), .Inf(ZInf), .ExpMax(ZExpMax), .FracZero(ZFracZero)); - // is the input Subnormalized + // is the input subnormal assign XSubnorm = ~XExpNonZero & ~XFracZero; endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/unpackinput.sv b/pipelined/src/fpu/unpackinput.sv index f92c2be4..2d88eee4 100644 --- a/pipelined/src/fpu/unpackinput.sv +++ b/pipelined/src/fpu/unpackinput.sv @@ -26,31 +26,32 @@ `include "wally-config.vh" module unpackinput ( - input logic [`FLEN-1:0] In, // inputs from register file - input logic En, // enable the input - input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half - output logic Sgn, // sign bits of XYZ - output logic [`NE-1:0] Exp, // exponents of XYZ (converted to largest supported precision) - output logic [`NF:0] Man, // mantissas of XYZ (converted to largest supported precision) - output logic NaN, // is XYZ a NaN - output logic SNaN, // is XYZ a signaling NaN - output logic Zero, // is XYZ zero - output logic Inf, // is XYZ infinity - output logic ExpNonZero, // is the exponent not zero - output logic FracZero, // is the fraction zero - output logic ExpMax // does In have the maximum exponent (NaN or Inf) + input logic [`FLEN-1:0] In, // inputs from register file + input logic En, // enable the input + input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half + output logic Sgn, // sign bits of XYZ + output logic [`NE-1:0] Exp, // exponents of XYZ (converted to largest supported precision) + output logic [`NF:0] Man, // mantissas of XYZ (converted to largest supported precision) + output logic NaN, // is XYZ a NaN + output logic SNaN, // is XYZ a signaling NaN + output logic Zero, // is XYZ zero + output logic Inf, // is XYZ infinity + output logic ExpNonZero, // is the exponent not zero + output logic FracZero, // is the fraction zero + output logic ExpMax // does In have the maximum exponent (NaN or Inf) ); - logic [`NF-1:0] Frac; //Fraction of XYZ - logic BadNaNBox; + logic [`NF-1:0] Frac; // Fraction of XYZ + logic BadNaNBox; // is the NaN boxing bad if (`FPSIZES == 1) begin // if there is only one floating point format supported assign BadNaNBox = 0; assign Sgn = In[`FLEN-1]; // sign bit assign Frac = In[`NF-1:0]; // fraction (no assumed 1) assign ExpNonZero = |In[`FLEN-2:`NF]; // is the exponent non-zero - assign Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero}; // exponent. Subnormalized numbers have effective biased exponent of 1 + assign Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero}; // exponent. subnormal numbers have effective biased exponent of 1 assign ExpMax = &In[`FLEN-2:`NF]; // is the exponent all 1's + end else if (`FPSIZES == 2) begin // if there are 2 floating point formats supported //***need better names for these constants // largest format | smaller format diff --git a/pipelined/src/generic/lzc.sv b/pipelined/src/generic/lzc.sv index 54372f8d..e3c8e754 100644 --- a/pipelined/src/generic/lzc.sv +++ b/pipelined/src/generic/lzc.sv @@ -22,10 +22,11 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + //leading zero counter i.e. priority encoder module lzc #(parameter WIDTH = 1) ( - input logic [WIDTH-1:0] num, - output logic [$clog2(WIDTH+1)-1:0] ZeroCnt + input logic [WIDTH-1:0] num, // number to count the leading zeroes of + output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes ); /* verilator lint_off CMPCONST */ /* verilator lint_off WIDTH */ diff --git a/pipelined/testbench/testbench-fp.sv b/pipelined/testbench/testbench-fp.sv index d3162caf..62a739c4 100644 --- a/pipelined/testbench/testbench-fp.sv +++ b/pipelined/testbench/testbench-fp.sv @@ -71,7 +71,7 @@ module testbenchfp; logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs logic XNaN, YNaN, ZNaN; // is the input NaN logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN - logic XDenorm, ZDenorm; // is the input denormalized + logic XSubnorm, ZSubnorm; // is the input denormalized logic XInf, YInf, ZInf; // is the input infinity logic XZero, YZero, ZZero; // is the input zero logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones @@ -81,7 +81,7 @@ module testbenchfp; logic [`NE:0] CvtCalcExpE; // the calculated expoent logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by logic [`DIVb:0] Quot; - logic CvtResDenormUfE; + logic CvtResSubnormUfE; logic DivStart, FDivBusyE, OldFDivBusyE; logic reset = 1'b0; logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt; @@ -666,7 +666,7 @@ module testbenchfp; .Xm, .Ym, .Zm, .DivStart, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, - .XDenorm, .ZDenorm, + .XSubnorm, .ZSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, .XExpMax, .X, .Y, .Z); @@ -694,10 +694,10 @@ module testbenchfp; end postprocess postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]), - .ZDenorm(ZDenorm), .OpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp), - .Xm(Xm), .Ym(Ym), .Zm(Zm), .CvtCe(CvtCalcExpE), .DivS(DivSticky), .FmaSs(Ss), - .XNaN(XNaN), .YNaN(YNaN), .ZNaN(ZNaN), .CvtResDenormUf(CvtResDenormUfE), - .XZero(XZero), .YZero(YZero), .ZZero(ZZero), .CvtShiftAmt(CvtShiftAmtE), + .OpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp), + .Xm(Xm), .Ym(Ym), .Zm(Zm), .CvtCe(CvtCalcExpE), .DivSticky(DivSticky), .FmaSs(Ss), + .XNaN(XNaN), .YNaN(YNaN), .ZNaN(ZNaN), .CvtResSubnormUf(CvtResSubnormUfE), + .XZero(XZero), .YZero(YZero), .CvtShiftAmt(CvtShiftAmtE), .XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal), .XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero, .FmaASticky(ASticky), .FmaSe(Se), @@ -706,8 +706,8 @@ module testbenchfp; if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt fcvt fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal), - .XZero(XZero), .XDenorm(XDenorm), .OpCtrl(OpCtrlVal), .IntZero, - .Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResDenormUf(CvtResDenormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE)); + .XZero(XZero), .XSubnorm(XSubnorm), .OpCtrl(OpCtrlVal), .IntZero, + .Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE)); end if (TEST === "cmp" | TEST === "all") begin: fcmp @@ -966,7 +966,7 @@ module readvectors ( output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision) output logic XNaN, YNaN, ZNaN, // is XYZ a NaN output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN - output logic XDenorm, ZDenorm, // is XYZ denormalized + output logic XSubnorm, ZSubnorm, // is XYZ denormalized output logic XZero, YZero, ZZero, // is XYZ zero output logic XInf, YInf, ZInf, // is XYZ infinity output logic XExpMax, @@ -1333,6 +1333,6 @@ module readvectors ( unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze, .Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, - .XDenorm, .ZDenorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, + .XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, .XEn, .YEn, .ZEn, .XExpMax); endmodule \ No newline at end of file