cleaned up all FPU files except for division

This commit is contained in:
Katherine Parry 2023-01-11 22:02:30 -06:00
parent 67d474995e
commit 77a982c977
33 changed files with 725 additions and 604 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
///////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 |

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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