diff --git a/pipelined/src/fpu/fcvt.sv b/pipelined/src/fpu/fcvt.sv index b7f2f672e..6252eea57 100644 --- a/pipelined/src/fpu/fcvt.sv +++ b/pipelined/src/fpu/fcvt.sv @@ -32,21 +32,21 @@ `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 XDenorm, // is the input denormalized - 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 ResDenormUf,// does the result underflow or is denormalized - 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) + 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 XDenorm, // is the input denormalized + 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 ResDenormUf,// does the result underflow or is denormalized + 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) ); // OpCtrls: @@ -68,15 +68,15 @@ module fcvt ( logic [`NE-1:0] OldExp; // the old exponent logic Signed; // is the opperation with a signed integer? logic Int64; // is the integer 64 bits? - logic IntToFp; // is the opperation an int->fp conversion? - logic [`CVTLEN:0] LzcInFull; // input to the Leading Zero Counter (priority encoder) + logic IntToFp; // is the opperation an int->fp conversion? + logic [`CVTLEN:0] LzcInFull; // input to the Leading Zero Counter (priority encoder) logic [`LOGCVTLEN-1:0] LeadingZeros; // output from the LZC // seperate OpCtrl for code readability - assign Signed = OpCtrl[0]; - assign Int64 = OpCtrl[1]; - assign IntToFp = OpCtrl[2]; + assign Signed = OpCtrl[0]; + assign Int64 = OpCtrl[1]; + assign IntToFp = OpCtrl[2]; // choose the ouptut format depending on the opperation // - fp -> fp: OpCtrl contains the percision of the output @@ -109,27 +109,6 @@ module fcvt ( assign LzcIn = LzcInFull[`CVTLEN-1:0]; lzc #(`CVTLEN+1) lzc (.num(LzcInFull), .ZeroCnt(LeadingZeros)); - - /////////////////////////////////////////////////////////////////////////// - // shifter - /////////////////////////////////////////////////////////////////////////// - - // kill the shift if it's negitive - // select the amount to shift by - // fp -> int: - // - shift left by CalcExp - essentially shifting until the unbiased exponent = 0 - // - don't shift if supposed to shift right (underflowed or denorm input) - // denormalized/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 denormalized - // - 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 (ResDenormUf&~IntToFp) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0]; - else ShiftAmt = LeadingZeros; /////////////////////////////////////////////////////////////////////////// // exp calculations @@ -179,7 +158,7 @@ module fcvt ( assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp; end // select the old exponent - // int -> fp : largest bias + XLEN + // int -> fp : largest bias + XLEN-1 // fp -> ??? : XExp assign OldExp = IntToFp ? (`NE)'(`BIAS)+(`NE)'(`XLEN-1) : Xe; @@ -189,6 +168,7 @@ module fcvt ( // only do ^ if the input was denormalized // - 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 // fp -> int : XExp - Largest Bias + 1 - (LeadingZeros+1) // | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp // process: @@ -204,19 +184,45 @@ module fcvt ( // | keep | // // - if the input is denormalized then we dont shift... so the "- LeadingZeros" is just leftovers from other options - // int -> fp : largest bias + XLEN - Largest bias + new bias - LeadingZeros = XLEN + NewBias - LeadingZeros + // int -> fp : largest bias + XLEN-1 - Largest bias + new bias - LeadingZeros = XLEN-1 + NewBias - LeadingZeros // Process: + // |XLEN|.0000 // - shifted right by XLEN (XLEN) + // 000000.|XLEN| // - shift left to normilize (-LeadingZeros) + // 000000.1... + // - shift left 1 to normalize + // 000001.stuff // - newBias to make the biased exponent - // oldexp - biasold +newbias - LeadingZeros&(XDenorm|IntToFp) - assign Ce = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE-`LOGCVTLEN+1{1'b0}}, (LeadingZeros&{`LOGCVTLEN{XDenorm|IntToFp}})}; + // + // 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 assign ResDenormUf = (~|Ce | Ce[`NE])&~XZero&~IntToFp; - + + /////////////////////////////////////////////////////////////////////////// + // shifter + /////////////////////////////////////////////////////////////////////////// + + // kill the shift if it's negitive + // select the amount to shift by + // fp -> int: + // - shift left by CalcExp - essentially shifting until the unbiased exponent = 0 + // - don't shift if supposed to shift right (underflowed or denorm input) + // denormalized/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 denormalized + // - 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//***change denorm to subnorm + if(ToInt) ShiftAmt = Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}}; + else if (ResDenormUf) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0]; + else ShiftAmt = LeadingZeros; /////////////////////////////////////////////////////////////////////////// // sign /////////////////////////////////////////////////////////////////////////// diff --git a/pipelined/src/fpu/normshift.sv b/pipelined/src/fpu/normshift.sv deleted file mode 100644 index 0d23d2f7b..000000000 --- a/pipelined/src/fpu/normshift.sv +++ /dev/null @@ -1,75 +0,0 @@ -/////////////////////////////////////////// -// normshift.sv -// -// Written: me@KatherineParry.com -// Modified: 7/5/2022 -// -// Purpose: normalization shifter -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// MIT LICENSE -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -//////////////////////////////////////////////////////////////////////////////////////////////// -`include "wally-config.vh" - - - // convert shift - // fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp - // process: - // - start - CalcExp = 1 + XExp - Largest Bias - // | `XLEN zeros | Mantissa | 0's if nessisary | - // - // - shift left 1 (1) - // | `XLEN-1 zeros |bit| frac | 0's if nessisary | - // . <- binary point - // - // - shift left till unbiased exponent is 0 (XExp - Largest Bias) - // | 0's | Mantissa | 0's if nessisary | - // | keep | - // - // fp -> fp: - // - if result is denormalized or underflowed: - // | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1 - // process: - // - start - // | mantissa | 0's | - // - // - shift right by NF-1 (NF-1) - // | `NF-1 zeros | mantissa | 0's | - // - // - shift left by CalcExp = XExp - Largest bias + new bias - // | 0's | mantissa | 0's | - // | keep | - // - // - if the input is denormalized: - // | 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 - -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 -); - assign Shifted = ShiftIn << ShiftAmt; - -endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/postproc/cvtshiftcalc.sv b/pipelined/src/fpu/postproc/cvtshiftcalc.sv index 88382bdc1..a6ba456e1 100644 --- a/pipelined/src/fpu/postproc/cvtshiftcalc.sv +++ b/pipelined/src/fpu/postproc/cvtshiftcalc.sv @@ -30,16 +30,16 @@ `include "wally-config.vh" module cvtshiftcalc( - input logic XZero, - input logic ToInt, - input logic IntToFp, - 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 CvtResDenormUf, - output logic CvtResUf, - 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 [`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 CvtResDenormUf, // 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) @@ -51,6 +51,7 @@ module cvtshiftcalc( // seclect the input to the shifter // fp -> int: // | `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 @@ -58,11 +59,14 @@ module cvtshiftcalc( // ??? -> fp: // - if result is denormalized 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 + 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 (CvtResDenormUf) CvtShiftIn = {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}}; else CvtShiftIn = {CvtLzcIn, {`NF+1{1'b0}}}; diff --git a/pipelined/src/fpu/unpackinput.sv b/pipelined/src/fpu/unpackinput.sv index bf524698a..a66f8e61f 100644 --- a/pipelined/src/fpu/unpackinput.sv +++ b/pipelined/src/fpu/unpackinput.sv @@ -241,6 +241,7 @@ module unpackinput ( // also need to take into account possible zero/denorm/inf/NaN values // convert the double precsion exponent into quad precsion + // 1 is added to the exponent if the input is zero or subnormal always_comb case (Fmt) 2'b11: Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|~ExpNonZero}; diff --git a/pipelined/testbench/testbench-fp.sv b/pipelined/testbench/testbench-fp.sv index ac81a1376..d3162cafc 100644 --- a/pipelined/testbench/testbench-fp.sv +++ b/pipelined/testbench/testbench-fp.sv @@ -700,7 +700,7 @@ module testbenchfp; .XZero(XZero), .YZero(YZero), .ZZero(ZZero), .CvtShiftAmt(CvtShiftAmtE), .XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal), .XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero, - .FmaZmS(ASticky), .FmaSe(Se), + .FmaASticky(ASticky), .FmaSe(Se), .FmaSm(Sm), .FmaSCnt(SCnt), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal), .PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));