From f2d05911ca3b151e01db9489df557bc8eb339a16 Mon Sep 17 00:00:00 2001 From: Katherine Parry Date: Tue, 28 Jun 2022 00:16:22 +0000 Subject: [PATCH] very basic early termination passes testfloat 64-bit tests --- pipelined/src/fpu/divshiftcalc.sv | 25 +++++++++++-------------- pipelined/src/fpu/lzacorrection.sv | 14 +++++++++++++- pipelined/src/fpu/postprocess.sv | 7 +++++-- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/pipelined/src/fpu/divshiftcalc.sv b/pipelined/src/fpu/divshiftcalc.sv index d867efc44..51698590e 100644 --- a/pipelined/src/fpu/divshiftcalc.sv +++ b/pipelined/src/fpu/divshiftcalc.sv @@ -7,16 +7,15 @@ module divshiftcalc( input logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2M, output logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt, output logic [`NORMSHIFTSZ-1:0] DivShiftIn, - output logic [`NE+1:0] CorrDivExp + output logic DivResDenorm, + output logic [`NE+1:0] DivDenormShift ); - logic ResDenorm; - logic [`NE+1:0] DenormShift; logic [`NE+1:0] NormShift; logic [`NE+1:0] Nf, NfPlus1; // is the result denromalized // if the exponent is 1 then the result needs to be normalized then the result is denormalizes - assign ResDenorm = DivCalcExpM[`NE+1]|(~|DivCalcExpM[`NE+1:1]&~(DivCalcExpM[0]&Quot[`DIVLEN+2])); + assign DivResDenorm = DivCalcExpM[`NE+1]|(~|DivCalcExpM[`NE+1:0]); // select the proper fraction lengnth if (`FPSIZES == 1) begin assign Nf = (`NE+2)'(`NF); @@ -70,24 +69,22 @@ module divshiftcalc( // if the result is denormalized // 00000000x.xxxxxx... Exp = DivCalcExp // .00000000xxxxxxx... >> NF+1 Exp = DivCalcExp+NF+1 - // .000xxxxxxxxxxxx... << DivCalcExp+NF+1 Exp = 0 + // .00xxxxxxxxxxxxx... << DivCalcExp+NF+1 Exp = +1 // .0000xxxxxxxxxxx... >> 1 Exp = 1 // Left shift amount = DivCalcExp+NF+1-1 - assign DenormShift = Nf+DivCalcExpM; + assign DivDenormShift = Nf+DivCalcExpM; // if the result is normalized // 00000000x.xxxxxx... Exp = DivCalcExp // .00000000xxxxxxx... >> NF+1 Exp = DivCalcExp+NF+1 - // 00000000x.xxxxxx... << NF+1 Exp = DivCalcExp - // 00000000xx.xxxxx... << 1? Exp = DivCalcExp-1 - // Left shift amount = NF+1 plus 1 if normalization required - assign NormShift = NfPlus1 + {(`NE+1)'(0), ~Quot[`DIVLEN+2]}; + // 00000000.xxxxxxx... << NF Exp = DivCalcExp+1 + // 00000000x.xxxxxx... << NF Exp = DivCalcExp (extra shift done afterwards) + // 00000000xx.xxxxx... << 1? Exp = DivCalcExp-1 (determined after) + // inital Left shift amount = NF + assign NormShift = Nf; // if the shift amount is negitive then dont shift (keep sticky bit) - assign DivShiftAmt = (ResDenorm ? DenormShift[$clog2(`NORMSHIFTSZ)-1:0]&{$clog2(`NORMSHIFTSZ){~DenormShift[`NE+1]}} : NormShift[$clog2(`NORMSHIFTSZ)-1:0])+{{$clog2(`NORMSHIFTSZ)-$clog2(`DIVLEN/2+3)-1{1'b0}}, EarlyTermShiftDiv2M, 1'b0}; + assign DivShiftAmt = (DivResDenorm ? DivDenormShift[$clog2(`NORMSHIFTSZ)-1:0]&{$clog2(`NORMSHIFTSZ){~DivDenormShift[`NE+1]}} : NormShift[$clog2(`NORMSHIFTSZ)-1:0])+{{$clog2(`NORMSHIFTSZ)-$clog2(`DIVLEN/2+3)-1{1'b0}}, EarlyTermShiftDiv2M&{$clog2(`DIVLEN/2+3){~DivDenormShift[`NE+1]}}, 1'b0}; // *** may be able to reduce shifter size assign DivShiftIn = {{`NF{1'b0}}, Quot[`DIVLEN+2:0], {`NORMSHIFTSZ-`DIVLEN-3-`NF{1'b0}}}; - // the quotent is in the range [.5,2) if there is no early termination - // if the quotent < 1 and not denormal then subtract 1 to account for the normalization shift - assign CorrDivExp = (ResDenorm&~DenormShift[`NE+1]) ? (`NE+2)'(0) : DivCalcExpM - {(`NE+1)'(0), ~Quot[`DIVLEN+2]}; endmodule diff --git a/pipelined/src/fpu/lzacorrection.sv b/pipelined/src/fpu/lzacorrection.sv index f06dd84a9..e5a2d5c34 100644 --- a/pipelined/src/fpu/lzacorrection.sv +++ b/pipelined/src/fpu/lzacorrection.sv @@ -3,14 +3,20 @@ module lzacorrection( input logic [`NORMSHIFTSZ-1:0] Shifted, // the shifted sum before LZA correction input logic FmaOp, + input logic DivOp, + input logic DivResDenorm, + input logic [`NE+1:0] DivCalcExpM, + input logic [`NE+1:0] DivDenormShift, input logic [`NE+1:0] ConvNormSumExp, // exponent of the normalized sum not taking into account denormal or zero results input logic PreResultDenorm, // is the result denormalized - calculated before LZA corection input logic KillProdM, // is the product set to zero input logic SumZero, output logic [`CORRSHIFTSZ-1:0] CorrShifted, // the shifted sum before LZA correction + output logic [`NE+1:0] CorrDivExp, output logic [`NE+1:0] SumExp // exponent of the normalized sum ); logic [3*`NF+5:0] CorrSumShifted; // the shifted sum after LZA correction + logic [`CORRSHIFTSZ:0] CorrQuotShifted; logic ResDenorm; // is the result denormalized logic LZAPlus1, LZAPlus2; // add one or two to the sum's exponent due to LZA correction @@ -19,11 +25,17 @@ module lzacorrection( assign LZAPlus2 = 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-3:1] : Shifted[`NORMSHIFTSZ-4:0]; - assign CorrShifted = FmaOp ? {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}} : Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ]; + // if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Denorm) + assign CorrQuotShifted = {LZAPlus2|(DivCalcExpM==1&~LZAPlus2) ? Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ] : {Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ], 1'b0}, 1'b0}; + // if the result of the divider was calculated to be denormalized, then the result was correctly normalized, so select the top shifted bits + assign CorrShifted = FmaOp ? {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}} : DivOp&~DivResDenorm ? CorrQuotShifted[`CORRSHIFTSZ-1:0] : Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ]; // Determine sum's exponent // if plus1 If plus2 if said denorm but norm plus 1 if said denorm but norm plus 2 assign SumExp = (ConvNormSumExp+{{`NE+1{1'b0}}, LZAPlus1&~KillProdM}+{{`NE{1'b0}}, LZAPlus2&~KillProdM, 1'b0}+{{`NE+1{1'b0}}, ~ResDenorm&PreResultDenorm&~KillProdM}+{{`NE+1{1'b0}}, &ConvNormSumExp&Shifted[3*`NF+6]&~KillProdM}) & {`NE+2{~(SumZero|ResDenorm)}}; // recalculate if the result is denormalized assign ResDenorm = PreResultDenorm&~Shifted[`NORMSHIFTSZ-3]&~Shifted[`NORMSHIFTSZ-2]; + // the quotent is in the range [.5,2) if there is no early termination + // if the quotent < 1 and not denormal then subtract 1 to account for the normalization shift + assign CorrDivExp = ((DivResDenorm)&~DivDenormShift[`NE+1]) ? (`NE+2)'(0) : DivCalcExpM - {(`NE+1)'(0), ~LZAPlus2}; endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/postprocess.sv b/pipelined/src/fpu/postprocess.sv index 217e3f586..ab06a9406 100644 --- a/pipelined/src/fpu/postprocess.sv +++ b/pipelined/src/fpu/postprocess.sv @@ -112,6 +112,8 @@ module postprocess( logic UfLSBRes; logic Sqrt; logic [`FMTBITS-1:0] OutFmt; + logic DivResDenorm; + logic [`NE+1:0] DivDenormShift; // signals to help readability assign Signed = FOpCtrlM[0]; @@ -144,7 +146,7 @@ module postprocess( .XZeroM, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn); fmashiftcalc fmashiftcalc(.SumM, .ZExpM, .ProdExpM, .FmaNormCntM, .FmtM, .KillProdM, .ConvNormSumExp, .ZDenormM, .SumZero, .PreResultDenorm, .FmaShiftAmt, .FmaShiftIn); - divshiftcalc divshiftcalc(.FmtM, .Quot, .DivCalcExpM, .EarlyTermShiftDiv2M, .CorrDivExp, .DivShiftAmt, .DivShiftIn); + divshiftcalc divshiftcalc(.FmtM, .Quot, .DivCalcExpM, .EarlyTermShiftDiv2M, .DivResDenorm, .DivDenormShift, .DivShiftAmt, .DivShiftIn); always_comb case(PostProcSelM) @@ -169,7 +171,8 @@ module postprocess( normshift normshift (.ShiftIn, .ShiftAmt, .Shifted); lzacorrection lzacorrection(.FmaOp, .KillProdM, .PreResultDenorm, .ConvNormSumExp, - .SumZero, .Shifted, .SumExp, .CorrShifted); + .DivResDenorm, .DivDenormShift, .DivOp, .DivCalcExpM, + .CorrDivExp, .SumZero, .Shifted, .SumExp, .CorrShifted); /////////////////////////////////////////////////////////////////////////////// // Rounding