diff --git a/pipelined/config/rv64fp/wally-config.vh b/pipelined/config/rv64fp/wally-config.vh index e88b012a..36cda4d9 100644 --- a/pipelined/config/rv64fp/wally-config.vh +++ b/pipelined/config/rv64fp/wally-config.vh @@ -39,12 +39,12 @@ // MISA RISC-V configuration per specification //16 - quad 3 - double 5 - single -`define MISA (32'h00000104 | 1 << 5 | 1 << 3 | 0 << 16 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0 ) +`define MISA (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 16 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0 ) `define ZICSR_SUPPORTED 1 `define ZIFENCEI_SUPPORTED 1 `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 1 -`define ZFH_SUPPORTED 0 +`define ZFH_SUPPORTED 1 /// Microarchitectural Features `define UARCH_PIPELINED 1 diff --git a/pipelined/src/fpu/fcvt.sv b/pipelined/src/fpu/fcvt.sv index 9195bc89..55e6706c 100644 --- a/pipelined/src/fpu/fcvt.sv +++ b/pipelined/src/fpu/fcvt.sv @@ -82,7 +82,11 @@ module fcvt ( // choose the ouptut format depending on the opperation // - fp -> fp: OpCtrl contains the percision of the output // - int -> fp: FmtE contains the percision of the output - assign OutFmt = IntToFp ? FmtE : (FOpCtrlE[1:0] == `FMT); + if (`FPSIZES == 2) + assign OutFmt = IntToFp ? FmtE : (FOpCtrlE[1:0] == `FMT); + else if (`FPSIZES == 3 | `FPSIZES == 4) + assign OutFmt = IntToFp ? FmtE : FOpCtrlE[1:0]; + /////////////////////////////////////////////////////////////////////////// // negation @@ -108,7 +112,7 @@ module fcvt ( // int -> fp : | positive integer | 00000... (if needed) | // fp -> fp : | fraction | 00000... (if needed) | assign LzcIn = IntToFp ? {PosInt, {`LGLEN-`XLEN{1'b0}}} : // I->F - {XManE[`NF-1:0], {`LGLEN-`NF{1'b0}}}; // F->F + {XManE[`NF-1:0], {`LGLEN-`NF{1'b0}}}; // F->F // lglen is the largest possible value of ZeroCnt (NF or XLEN) hence normcnt must be log2(lglen) bits logic [$clog2(`LGLEN):0] i, ZeroCnt; @@ -122,25 +126,6 @@ module fcvt ( /////////////////////////////////////////////////////////////////////////// // shifter /////////////////////////////////////////////////////////////////////////// - // F->F shift so the fraction is not denormalized - // Large->Small Denrom -> Norm Frac: - // - // | Frac | `NF zeros| << ShiftCnt - // - // Small->Large Norm -> Denorm Frac: - // - shift right so that the new-bias exponet = 1 - // - so shift right by new-bias - 1 exponent - // - ie shift left by NF - 1 + new-bias exponent (if this is negitive then 0 is selected as a result later) - // - new-bias exponent is negitive - // - // | `NF-1 zeros |1| Frac | << NF + new-bias exponent - // | keep | - // - // Int -> Fp : - // | Int | `NF zeros| << ShiftCnt - // Fp -> Int : - // | `XLEN zeros | Man | << CalcExp - // seclect the input to the shifter // fp -> int: @@ -150,12 +135,13 @@ module fcvt ( // - 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 denormalized or underflowed then we want to normalize the result: - // | `NF zeros | Mantissa | 0's if nessisary | + // - if result is denormalized or underflowed then we want to shift right i.e. shift right then shift left: + // | `NF-1 zeros | Mantissa | 0's if nessisary | // - otherwise: // | lzcIn | 0's if nessisary | assign ShiftIn = ToInt ? {{`XLEN{1'b0}}, XManE[`NF]&~CalcExp[`NE], XManE[`NF-1]|(CalcExp[`NE]&XManE[`NF]), XManE[`NF-2:0], {`LGLEN-`XLEN{1'b0}}} : - ResDenormUf ? {{`NF-1{1'b0}}, XManE, {`LGLEN-`NF+1{1'b0}}} : {LzcIn, {`NF+1{1'b0}}}; + ResDenormUf ? {{`NF-1{1'b0}}, XManE, {`LGLEN-`NF+1{1'b0}}} : + {LzcIn, {`NF+1{1'b0}}}; // kill the shift if it's negitive // select the amount to shift by // fp -> int: @@ -169,16 +155,49 @@ module fcvt ( // - 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? assign ShiftAmt = ToInt ? CalcExp[$clog2(`LGLEN):0]&{$clog2(`LGLEN)+1{~CalcExp[`NE]}} : - ResDenormUf&~IntToFp ? ($clog2(`LGLEN)+1)'(`NF-1)+CalcExp[$clog2(`LGLEN):0] : (ZeroCnt+1)&{$clog2(`LGLEN)+1{XOrigDenormE|IntToFp}}; + ResDenormUf&~IntToFp ? ($clog2(`LGLEN)+1)'(`NF-1)+CalcExp[$clog2(`LGLEN):0] : + (ZeroCnt+1)&{$clog2(`LGLEN)+1{XOrigDenormE|IntToFp}}; // shift + // fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp + // process: + // - start - CalcExp = 1 + XExp - Largest Bias + // | `XLEN zeros | Mantissa | 0's if nessisary | + // + // - shift left 1 (1) + // | `XLEN-1 zeros |bit| frac | 0's if nessisary | + // . <- binary point + // + // - shift left till unbiased exponent is 0 (XExp - Largest Bias) + // | 0's | Mantissa | 0's if nessisary | + // | keep | + // + // fp -> fp: + // - if result is denormalized or underflowed: + // | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1 + // process: + // - start + // | mantissa | 0's | + // + // - shift right by NF-1 (NF-1) + // | `NF-1 zeros | mantissa | 0's | + // + // - shift left by CalcExp = XExp - Largest bias + new bias + // | 0's | mantissa | 0's | + // | keep | + // + // - if the input is denormalized: + // | lzcIn | 0's if nessisary | << ZeroCnt+1 + // - plus 1 to shift out the first 1 + // + // int -> fp: | lzcIn | 0's if nessisary | << ZeroCnt+1 + // - plus 1 to shift out the first 1 + assign Shifted = ShiftIn << ShiftAmt; /////////////////////////////////////////////////////////////////////////// // exp calculations /////////////////////////////////////////////////////////////////////////// - // fp -> int - // CalcExp = 1 - largest bias + 1 - // *** possible optimizaations: @@ -192,10 +211,35 @@ module fcvt ( // Select the bias of the output // fp -> int : select 1 - // ??? -> fp : pick the new bias depending on the output format + // ??? -> fp : pick the new bias depending on the output format + if (`FPSIZES == 1) begin + assign NewBias = ToInt ? (`NE-1)'(1) : (`NE-1)'(`BIAS); - assign NewBias = ToInt ? (`NE-1)'(1) : OutFmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1); + end else if (`FPSIZES == 2) begin + assign NewBias = ToInt ? (`NE-1)'(1) : OutFmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1); + end else if (`FPSIZES == 3) begin + logic [`NE-2:0] NewBiasToFp; + always_comb + case (OutFmt) + `FMT: NewBiasToFp = (`NE-1)'(`BIAS); + `FMT1: NewBiasToFp = (`NE-1)'(`BIAS1); + `FMT2: NewBiasToFp = (`NE-1)'(`BIAS2); + default: NewBiasToFp = 1'bx; + endcase + assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp; + + end else if (`FPSIZES == 4) begin + logic [`NE-2:0] NewBiasToFp; + always_comb + case (OutFmt) + 2'h3: NewBiasToFp = (`NE-1)'(`Q_BIAS); + 2'h1: NewBiasToFp = (`NE-1)'(`D_BIAS); + 2'h0: NewBiasToFp = (`NE-1)'(`S_BIAS); + 2'h2: NewBiasToFp = (`NE-1)'(`H_BIAS); + endcase + assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp; + end // select the old exponent // int -> fp : largest bias + XLEN // fp -> ??? : XExp @@ -203,22 +247,76 @@ module fcvt ( // calculate CalcExp // fp -> fp : - // - XExp - Largest bias + new bias - // fp -> int : XExp - // int -> fp : largest bias + XLEN - // the -XOrigDenorm is to take into account the correction (which had a plus 1) + // - XExp - Largest bias + new bias - (ZeroCnt+1) + // only do ^ if the input was denormalized + // - convert the expoenent to the final preciaion (Exp - oldBias + newBias) + // - correct the expoent when there is a normalization shift ( + ZeroCnt+1) + // fp -> int : XExp - Largest Bias + 1 - (ZeroCnt+1) + // | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp + // process: + // - start + // | `XLEN zeros | Mantissa | 0's if nessisary | + // + // - shift left 1 (1) + // | `XLEN-1 zeros |bit| frac | 0's if nessisary | + // . <- binary point + // + // - shift left till unbiased exponent is 0 (XExp - Largest Bias) + // | 0's | Mantissa | 0's if nessisary | + // | keep | + // + // - if the input is denormalized then we dont shift... so the "- (ZeroCnt+1)" is just leftovers from other options + // int -> fp : largest bias XLEN - Largest bias + new bias - 1 - ZeroCnt = XLEN + NewBias - 1 - ZeroCnt + // Process: + // - shifted right by XLEN (XLEN) + // - shift left to normilize (-1-ZeroCnt) + // - newBias to make the biased exponent + // assign CalcExp = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE{1'b0}}, XOrigDenormE|IntToFp} - {{`NE-$clog2(`LGLEN){1'b0}}, (ZeroCnt&{$clog2(`LGLEN)+1{XOrigDenormE|IntToFp}})}; - // if result is 0 or negitive - assign ResDenormUf = (~|CalcExp | CalcExp[`NE])&~XZeroE; - assign ResNegNF = (FOpCtrlE[1:0] == `FMT) ? -`NF : -`NF1; - // if the reuslt underflows and somthing is shifted out set the sticky bit - assign ResUf = ($signed(CalcExp) < $signed({{`NE-$clog2(`NF){1'b1}}, ResNegNF}))&~XZeroE; + // find if the result is dnormal or underflows + // - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0) + // - can't underflow an integer to Fp conversion + assign ResDenormUf = (~|CalcExp | CalcExp[`NE])&~XZeroE&~IntToFp; + // choose the negative of the fraction size + if (`FPSIZES == 1) begin + assign ResNegNF = -`NF; + + end else if (`FPSIZES == 2) begin + assign ResNegNF = OutFmt ? -`NF : -`NF1; + + end else if (`FPSIZES == 3) begin + always_comb + case (OutFmt) + `FMT: ResNegNF = -`NF; + `FMT1: ResNegNF = -`NF1; + `FMT2: ResNegNF = -`NF2; + default: ResNegNF = 1'bx; + endcase + + end else if (`FPSIZES == 4) begin + always_comb + case (OutFmt) + 2'h3: ResNegNF = -`Q_NF; + 2'h1: ResNegNF = -`D_NF; + 2'h0: ResNegNF = -`S_NF; + 2'h2: ResNegNF = -`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 + assign ResUf = ($signed(CalcExp) < $signed({{`NE-$clog2(`NF){1'b1}}, ResNegNF}))&~XZeroE&~IntToFp; /////////////////////////////////////////////////////////////////////////// // sign /////////////////////////////////////////////////////////////////////////// + // determine the sign of the result + // - if int -> fp + // - if 64-bit : check the msb of the 64-bit integer input and if it's signed + // - if 32-bit : check the msb of the 32-bit integer input and if it's signed + // - otherwise: the floating point input's sign assign ResSgn = IntToFp ? Int64 ? ForwardedSrcAE[`XLEN-1]&Signed : ForwardedSrcAE[31]&Signed : XSgnE; /////////////////////////////////////////////////////////////////////////// @@ -241,17 +339,80 @@ module fcvt ( // {Guard, Round, Sticky} // 0x - do nothing // 1x - Plus1 + // ResUf is used when a fp->fp result underflows but all the bits get shifted out, which leaves nothing for the sticky bit + if (`FPSIZES == 1) begin + assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : |Shifted[`LGLEN+`NF-`NF-1:0]|ResUf; + assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : Shifted[`LGLEN+`NF-`NF]; + assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : Shifted[`LGLEN+`NF-`NF+1]; - // ResUf is used when a fp->fp result underflows but all the bits get shifted out, leaving nothing for the sticky bit - assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : - (OutFmt ? |Shifted[`LGLEN+`NF-`NF-1:0] : |Shifted[`LGLEN+`NF-`NF1-1:0])|ResUf; - assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : - OutFmt ? Shifted[`LGLEN+`NF-`NF] : |Shifted[`LGLEN+`NF-`NF1]; - assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : - OutFmt ? Shifted[`LGLEN+`NF-`NF+1] : Shifted[`LGLEN+`NF-`NF1+1]; + end else if (`FPSIZES == 2) begin + assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : + (OutFmt ? |Shifted[`LGLEN+`NF-`NF-1:0] : |Shifted[`LGLEN+`NF-`NF1-1:0])|ResUf; + assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : + OutFmt ? Shifted[`LGLEN+`NF-`NF] : Shifted[`LGLEN+`NF-`NF1]; + assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : + OutFmt ? Shifted[`LGLEN+`NF-`NF+1] : Shifted[`LGLEN+`NF-`NF1+1]; + end else if (`FPSIZES == 3) begin + logic ToFpSticky, ToFpRound, ToFpLSBFrac; + always_comb + case (OutFmt) + `FMT: begin + ToFpSticky = |Shifted[`LGLEN+`NF-`NF-1:0]; + ToFpRound = Shifted[`LGLEN+`NF-`NF]; + ToFpLSBFrac = Shifted[`LGLEN+`NF-`NF+1]; + end + `FMT1: begin + ToFpSticky = |Shifted[`LGLEN+`NF-`NF1-1:0]; + ToFpRound = Shifted[`LGLEN+`NF-`NF1]; + ToFpLSBFrac = Shifted[`LGLEN+`NF-`NF1+1]; + end + `FMT2: begin + ToFpSticky = |Shifted[`LGLEN+`NF-`NF2-1:0]; + ToFpRound = Shifted[`LGLEN+`NF-`NF2]; + ToFpLSBFrac = Shifted[`LGLEN+`NF-`NF2+1]; + end + default: begin + ToFpSticky = 1'bx; + ToFpRound = 1'bx; + ToFpLSBFrac = 1'bx; + end + endcase + assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : ToFpSticky|ResUf; + assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : ToFpRound; + assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : ToFpLSBFrac; - always_comb begin // ***remove guard bit + end else if (`FPSIZES == 4) begin + logic ToFpSticky, ToFpRound, ToFpLSBFrac; + always_comb + case (OutFmt) + 2'h3: begin + ToFpSticky = |Shifted[`LGLEN+`Q_NF-`Q_NF-1:0]; + ToFpRound = Shifted[`LGLEN+`Q_NF-`Q_NF]; + ToFpLSBFrac = Shifted[`LGLEN+`Q_NF-`Q_NF+1]; + end + 2'h1: begin + ToFpSticky = |Shifted[`LGLEN+`Q_NF-`D_NF-1:0]; + ToFpRound = Shifted[`LGLEN+`Q_NF-`D_NF]; + ToFpLSBFrac = Shifted[`LGLEN+`Q_NF-`D_NF+1]; + end + 2'h0: begin + ToFpSticky = |Shifted[`LGLEN+`Q_NF-`S_NF-1:0]; + ToFpRound = Shifted[`LGLEN+`Q_NF-`S_NF]; + ToFpLSBFrac = Shifted[`LGLEN+`Q_NF-`S_NF+1]; + end + 2'h2: begin + ToFpSticky = |Shifted[`LGLEN+`Q_NF-`H_NF-1:0]; + ToFpRound = Shifted[`LGLEN+`Q_NF-`H_NF]; + ToFpLSBFrac = Shifted[`LGLEN+`Q_NF-`H_NF+1]; + end + endcase + assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : ToFpSticky|ResUf; + assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : ToFpRound; + assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : ToFpLSBFrac; + end + + always_comb // Determine if you add 1 case (FrmE) 3'b000: CalcPlus1 = Round & (Sticky | LSBFrac);//round to nearest even @@ -261,32 +422,98 @@ module fcvt ( 3'b100: CalcPlus1 = Round;//round to nearest max magnitude default: CalcPlus1 = 1'bx; endcase - end - assign Plus1 = CalcPlus1&(Round|Sticky); - assign ShiftedPlus1 = OutFmt ? {{`FLEN-1{1'b0}},Plus1} : {{`NE+`NF1{1'b0}}, Plus1, {`FLEN-`NE-`NF1-1{1'b0}}}; + // dont round if exact + assign Plus1 = CalcPlus1&(Round|Sticky); + + // shift the 1 to the propper position for rounding + // - dont round it converting to integer + if (`FPSIZES == 1) begin + assign ShiftedPlus1 = {{`FLEN-1{1'b0}},Plus1&~ToInt}; + + end else if (`FPSIZES == 2) begin + assign ShiftedPlus1 = OutFmt ? {{`FLEN-1{1'b0}},Plus1&~ToInt} : {{`NE+`NF1{1'b0}}, Plus1&~ToInt, {`FLEN-`NE-`NF1-1{1'b0}}}; + + end else if (`FPSIZES == 3) begin + always_comb + case (OutFmt) + `FMT: ShiftedPlus1 = {{`FLEN-1{1'b0}},Plus1&~ToInt}; + `FMT1: ShiftedPlus1 = {{`NE+`NF1{1'b0}}, Plus1&~ToInt, {`FLEN-`NE-`NF1-1{1'b0}}}; + `FMT2: ShiftedPlus1 = {{`NE+`NF2{1'b0}}, Plus1&~ToInt, {`FLEN-`NE-`NF2-1{1'b0}}}; + default: ShiftedPlus1 = 0; + endcase + + end else if (`FPSIZES == 4) begin + always_comb + case (OutFmt) + 2'h3: ShiftedPlus1 = {{`Q_LEN-1{1'b0}},Plus1&~ToInt}; + 2'h1: ShiftedPlus1 = {{`Q_NE+`D_NF{1'b0}}, Plus1&~ToInt, {`Q_LEN-`Q_NE-`D_NF-1{1'b0}}}; + 2'h0: ShiftedPlus1 = {{`Q_NE+`S_NF{1'b0}}, Plus1&~ToInt, {`Q_LEN-`Q_NE-`S_NF-1{1'b0}}}; + 2'h2: ShiftedPlus1 = {{`Q_NE+`H_NF{1'b0}}, Plus1&~ToInt, {`Q_LEN-`Q_NE-`H_NF-1{1'b0}}}; + endcase + end // kill calcExp if the result is denormalized assign {FullResExp, ResFrac} = {CalcExp&{`NE+1{~ResDenormUf}}, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`NF]} + ShiftedPlus1; + // trim the result's expoent to size assign ResExp = FullResExp[`NE-1:0]; /////////////////////////////////////////////////////////////////////////// // flags /////////////////////////////////////////////////////////////////////////// // calculate the flags - // dont set underflow overflow or inexact flags if result is NaN - assign MaxExp = ToInt ? Int64 ? 65 : 33 : - OutFmt ? {`NE{1'b1}} : {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}}; - // if the exponent is lager or equal to the maximum and it's not negitive - // F->F if the input is inf then the output is also Inf ie exact, so dont set the underflow flag + + // find the maximum exponent (the exponent and larger overflows) + if (`FPSIZES == 1) begin + assign MaxExp = ToInt ? Int64 ? 65 : 33 : {`NE{1'b1}}; + + end else if (`FPSIZES == 2) begin + assign MaxExp = ToInt ? Int64 ? 65 : 33 : + OutFmt ? {`NE{1'b1}} : {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}}; + + end else if (`FPSIZES == 3) begin + logic [`NE-1:0] MaxExpFp; + always_comb + case (OutFmt) + `FMT: begin + MaxExpFp = {`NE{1'b1}}; + end + `FMT1: begin + MaxExpFp = {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}}; + end + `FMT2: begin + MaxExpFp = {{`NE-`NE2{1'b0}}, {`NE2{1'b1}}}; + end + default: begin + MaxExpFp = 1'bx; + end + endcase + assign MaxExp = ToInt ? Int64 ? 65 : 33 : MaxExpFp; + + end else if (`FPSIZES == 4) begin + logic [`NE-1:0] MaxExpFp; + always_comb + case (OutFmt) + 2'h3: begin + MaxExpFp = {`Q_NE{1'b1}}; + end + 2'h1: begin + MaxExpFp = {{`Q_NE-`D_NE{1'b0}}, {`D_NE{1'b1}}}; + end + 2'h0: begin + MaxExpFp = {{`Q_NE-`S_NE{1'b0}}, {`S_NE{1'b1}}}; + end + 2'h2: begin + MaxExpFp = {{`Q_NE-`H_NE{1'b0}}, {`H_NE{1'b1}}}; + end + endcase + assign MaxExp = ToInt ? Int64 ? 65 : 33 : MaxExpFp; + end // if the result exponent is larger then the maximum possible exponent // | and the exponent is positive // | | and the input is not NaN or Infinity // | | | - assign Overflow = ((ResExp >= MaxExp)&~CalcExp[`NE]&~(XNaNE|XInfE)); - // only set the underflow flag if not-exact - // set the underflow flag if the result is denomal or underflowed - // can't underflow durring to integer conversions + assign Overflow = ((ResExp >= MaxExp)&~CalcExp[`NE]&(~(XNaNE|XInfE)|IntToFp)); // if the result is denormalized or underflowed // | and the result did not round into normal values @@ -294,18 +521,24 @@ module fcvt ( // | | | and the result isn't NaN // | | | | assign Underflow = ResDenormUf & ~(ResExp==1 & CalcExp == 0) & (Sticky|Round)&~(XNaNE); + // we are using the IEEE convertToIntegerExact opperations (rather then the exact ones) which do singal the inexact flag // if there were bits thrown away // | if overflowed or underflowed // | | and if not a NaN // | | | assign FpInexact = (Sticky|Round|Underflow|Overflow)&(~XNaNE|IntToFp); + // if the result is too small to be represented and not 0 // | and if the result is not invalid (outside the integer bounds) // | | assign IntInexact = ((CalcExp[`NE]&~XZeroE)|Sticky|Round)&~Invalid; + + // select the inexact flag to output assign Inexact = ToInt ? IntInexact : FpInexact; + // if an input was a singaling NaN(and we're using a FP input) + // | assign FpInvalid = (XSNaNE&~IntToFp); assign NegResMSBS = Signed ? Int64 ? NegRes[`XLEN:`XLEN-1] : NegRes[32:31] : @@ -320,54 +553,262 @@ module fcvt ( assign IntInvalid = XNaNE|XInfE|Overflow|((XSgnE&~Signed)&(~((CalcExp[`NE]|(~|CalcExp))&~Plus1)))|(NegResMSBS[1]^NegResMSBS[0]); // | // or when the positive result rounds up out of range + // select the inexact flag to output assign Invalid = ToInt ? IntInvalid : FpInvalid; - // pack the flags together and choose the result based on the opperation - // don't set the overflow or underfolw flags if converting to integer + // pack the flags together + // - fp -> int does not set the overflow or underflow flags assign CvtFlgE = {Invalid, 1'b0, Overflow&~ToInt, Underflow&~ToInt, Inexact}; /////////////////////////////////////////////////////////////////////////// // result selection /////////////////////////////////////////////////////////////////////////// - // when the input is zero for F->F the exponent is not calulated as 0 so combine with underflow result - //logic [$clog2(`NF)-1:0] MinDenormExp; - //assign MinDenormExp = FOpCtrlE[1:0] == `FMT ? -`NE : -`NE1; + // determine if you shoould kill the result + // - do so if the result underflows, is zero (the exp doesnt calculate correctly). or the integer input is 0 + // - 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 = (ResUf|(XZeroE&~IntToFp)|(~|PosInt&IntToFp)); - //assign NaNRes = FOpCtrlE[1:0] == `FMT ? {1'b0, {`NE+1{1'b1}}, (`NF-1)'(0)} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)}; - - if(`IEEE754) begin - assign NaNRes = FOpCtrlE[1:0] == `FMT ? {1'b0, {`NE+1{1'b1}}, XManE[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, XManE[`NF-2:`NF-`NF1]}; - end else begin - assign NaNRes = FOpCtrlE[1:0] == `FMT ? {1'b0, {`NE+1{1'b1}}, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, {`NF1-1{1'b0}}}; + + if (`FPSIZES == 1) begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + assign NaNRes = {1'b0, {`NE+1{1'b1}}, XManE[`NF-2:0]}; + end else begin + assign NaNRes = {1'b0, {`NE+1{1'b1}}, {`NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + assign InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + assign UfRes = {ResSgn, (`FLEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + assign Res = {ResSgn, ResExp, ResFrac}; + + + end else if (`FPSIZES == 2) begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + assign NaNRes = OutFmt ? {1'b0, {`NE+1{1'b1}}, XManE[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, XManE[`NF-2:`NF-`NF1]}; + end else begin + assign NaNRes = OutFmt ? {1'b0, {`NE+1{1'b1}}, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, {`NF1-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + assign InfRes = OutFmt ? (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : + {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}} : + (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : + {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + assign UfRes = OutFmt ? {ResSgn, (`FLEN-2)'(0), Plus1&FrmE[1]} : {{`FLEN-`LEN1{1'b1}}, ResSgn, (`LEN1-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + assign Res = OutFmt ? {ResSgn, ResExp, ResFrac} : {{`FLEN-`LEN1{1'b1}}, ResSgn, ResExp[`NE1-1:0], ResFrac[`NF-1:`NF-`NF1]}; + + end else if (`FPSIZES == 3) begin + always_comb + case (OutFmt) + `FMT: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {1'b0, {`NE+1{1'b1}}, XManE[`NF-2:0]}; + end else begin + NaNRes = {1'b0, {`NE+1{1'b1}}, {`NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {ResSgn, (`FLEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {ResSgn, ResExp, ResFrac}; + end + `FMT1: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, XManE[`NF-2:`NF-`NF1]}; + end else begin + NaNRes = {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1+1{1'b1}}, {`NF1-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {{`FLEN-`LEN1{1'b1}}, ResSgn, (`LEN1-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {{`FLEN-`LEN1{1'b1}}, ResSgn, ResExp[`NE1-1:0], ResFrac[`NF-1:`NF-`NF1]}; + end + `FMT2: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {{`FLEN-`LEN2{1'b1}}, 1'b0, {`NE2+1{1'b1}}, XManE[`NF-2:`NF-`NF2]}; + end else begin + NaNRes = {{`FLEN-`LEN2{1'b1}}, 1'b0, {`NE2+1{1'b1}}, {`NF2-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`FLEN-`LEN2{1'b1}}, ResSgn, {`NE2-1{1'b1}}, 1'b0, {`NF2{1'b1}}} : {{`FLEN-`LEN2{1'b1}}, ResSgn, {`NE2{1'b1}}, (`NF2)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {{`FLEN-`LEN2{1'b1}}, ResSgn, (`LEN2-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {{`FLEN-`LEN2{1'b1}}, ResSgn, ResExp[`NE2-1:0], ResFrac[`NF-1:`NF-`NF2]}; + end + default: begin + NaNRes = 1'bx; + InfRes = 1'bx; + UfRes = 1'bx; + Res = 1'bx; + end + endcase + end else if (`FPSIZES == 4) begin + always_comb + case (OutFmt) + 2'h3: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {1'b0, {`Q_NE+1{1'b1}}, XManE[`Q_NF-2:0]}; + end else begin + NaNRes = {1'b0, {`Q_NE+1{1'b1}}, {`Q_NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {ResSgn, {`Q_NE-1{1'b1}}, 1'b0, {`Q_NF{1'b1}}} : {ResSgn, {`Q_NE{1'b1}}, {`Q_NF{1'b0}}}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {ResSgn, (`Q_LEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {ResSgn, ResExp, ResFrac}; + end + 2'h1: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {{`Q_LEN-`D_LEN{1'b1}}, 1'b0, {`D_NE+1{1'b1}}, XManE[`Q_NF-2:`Q_NF-`D_NF]}; + end else begin + NaNRes = {{`Q_LEN-`D_LEN{1'b1}}, 1'b0, {`D_NE+1{1'b1}}, {`D_NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`Q_LEN-`D_LEN{1'b1}}, ResSgn, {`D_NE-1{1'b1}}, 1'b0, {`D_NF{1'b1}}} : {{`Q_LEN-`D_LEN{1'b1}}, ResSgn, {`D_NE{1'b1}}, (`D_NF)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {{`Q_LEN-`D_LEN{1'b1}}, ResSgn, (`D_LEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {{`Q_LEN-`D_LEN{1'b1}}, ResSgn, ResExp[`D_NE-1:0], ResFrac[`Q_NF-1:`Q_NF-`D_NF]}; + end + 2'h0: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {{`Q_LEN-`S_LEN{1'b1}}, 1'b0, {`S_NE+1{1'b1}}, XManE[`Q_NF-2:`Q_NF-`S_NF]}; + end else begin + NaNRes = {{`Q_LEN-`S_LEN{1'b1}}, 1'b0, {`S_NE+1{1'b1}}, {`S_NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`Q_LEN-`S_LEN{1'b1}}, ResSgn, {`S_NE-1{1'b1}}, 1'b0, {`S_NF{1'b1}}} : {{`Q_LEN-`S_LEN{1'b1}}, ResSgn, {`S_NE{1'b1}}, (`S_NF)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {{`Q_LEN-`S_LEN{1'b1}}, ResSgn, (`S_LEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {{`Q_LEN-`S_LEN{1'b1}}, ResSgn, ResExp[`S_NE-1:0], ResFrac[`Q_NF-1:`Q_NF-`S_NF]}; + end + 2'h2: begin + // IEEE sends a payload while Riscv says to send a canonical quiet NaN + if(`IEEE754) begin + NaNRes = {{`Q_LEN-`H_LEN{1'b1}}, 1'b0, {`H_NE+1{1'b1}}, XManE[`Q_NF-2:`Q_NF-`H_NF]}; + end else begin + NaNRes = {{`Q_LEN-`H_LEN{1'b1}}, 1'b0, {`H_NE+1{1'b1}}, {`H_NF-1{1'b0}}}; + end + // determine the infinity result + // - if the input was infinity or rounding mode RZ, RU, RD (and not rounding the value) then output the maximum normalized floating point number with the correct sign + // - otherwise: output infinity with the correct sign + // - kill the infinity singal if the input isn't fp + InfRes = (~XInfE|IntToFp)&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`Q_LEN-`H_LEN{1'b1}}, ResSgn, {`H_NE-1{1'b1}}, 1'b0, {`H_NF{1'b1}}} : {{`Q_LEN-`H_LEN{1'b1}}, ResSgn, {`H_NE{1'b1}}, (`H_NF)'(0)}; + + // result for when the result is killed i.e. underflowes + // - output a rounded 0 with the correct sign + UfRes = {{`Q_LEN-`H_LEN{1'b1}}, ResSgn, (`H_LEN-2)'(0), Plus1&FrmE[1]}; + + // format the result - NaN box single precision (put 1's in the unused msbs) + Res = {{`Q_LEN-`H_LEN{1'b1}}, ResSgn, ResExp[`H_NE-1:0], ResFrac[`Q_NF-1:`Q_NF-`H_NF]}; + end + endcase end - // assign InfRes = FOpCtrlE[1:0] == `FMT ? {ResSgn, {`NE{1'b1}}, (`NF)'(0)} : {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; -// output one less then the maximum value if rounding down (RZ RU RD) -// if infinitiy output infinity - assign InfRes = FOpCtrlE[1:0] == `FMT ? ~XInfE&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : - {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}} : - ~XInfE&((FrmE[1:0]==2'b01) | (FrmE[1:0]==2'b10&~ResSgn) | (FrmE[1:0]==2'b11&ResSgn)) ? {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : - {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; -// if RU/RD then round the underflowed result if needed -// integer zero's exponent is not calculated corresctly so go through underflow result - assign UfRes = OutFmt ? {ResSgn, (`FLEN-2)'(0), Plus1&FrmE[1]} : {{`FLEN-`LEN1{1'b1}}, ResSgn, (`LEN1-2)'(0), Plus1&FrmE[1]}; - assign Res = OutFmt ? {ResSgn, ResExp, ResFrac} : {{`FLEN-`LEN1{1'b1}}, ResSgn, ResExp[`NE1-1:0], ResFrac[`NF-1:`NF-`NF1]}; + + + // choose the floating point result + // - if the input is NaN (and using the NaN input) output the NaN result + // - if the input is infinity or the output overflows + // - kill the InfE signal if the input isn't a floating point value + // - if killing the result output the underflow result + // - otherwise output the normal result assign CvtResE = XNaNE&~IntToFp ? NaNRes : - (XInfE|Overflow)&~IntToFp ? InfRes : + (XInfE&~IntToFp)|Overflow ? InfRes : KillRes ? UfRes : Res; // *** probably can optimize the negation - // NaNs sould ouput the same as a positive infinity - // a 32bit unsigend result should be sign extended (as if it is not a unsigned number) + // select the overflow integer result + // - negitive infinity and out of range negitive input + // | int | long | + // signed | -2^31 | -2^63 | + // unsigned | 0 | 0 | + // + // - positive infinity and out of range negitive input and NaNs + // | int | long | + // signed | 2^31-1 | 2^63-1 | + // unsigned | 2^32-1 | 2^64-1 | + // + // other: 32 bit unsinged result should be sign extended as if it were a signed number assign OfIntRes = Signed ? XSgnE&~XNaNE ? Int64 ? {1'b1, {`XLEN-1{1'b0}}} : {{`XLEN-32{1'b1}}, 1'b1, {31{1'b0}}} : // signed negitive - Int64 ? {1'b0, {`XLEN-1{1'b1}}} : {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}} : // signed positive - XSgnE&~XNaNE ? {`XLEN{1'b0}} : // unsigned negitive - {`XLEN{1'b1}};// unsigned positive + Int64 ? {1'b0, {`XLEN-1{1'b1}}} : {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}} : // signed positive + XSgnE&~XNaNE ? {`XLEN{1'b0}} : // unsigned negitive + {`XLEN{1'b1}};// unsigned positive - - assign NegRes = XSgnE ? -({2'b0, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`XLEN]}+{{`XLEN+1{1'b0}},Plus1}) : {2'b0, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`XLEN]}+{{`XLEN+1{1'b0}},Plus1}; + // round and negate the positive result if needed + assign NegRes = XSgnE ? -({2'b0, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}; + // select the integer output + // - if the input is invalid (out of bounds NaN or Inf) then output overflow result + // - if the input underflows + // - if rounding and signed opperation and negitive input, output -1 + // - otherwise output a rounded 0 + // - otherwise output the normal result (trmined and sign extended if nessisary) assign CvtIntResE = Invalid ? OfIntRes : - CalcExp[`NE] ? XSgnE&Signed&Plus1 ? {{`XLEN{1'b1}}} : {{`XLEN-1{1'b0}}, Plus1} : //CalcExp has to come after invalid ***swap to actual mux at some point?? - Int64 ? NegRes[`XLEN-1:0] : {{`XLEN-32{NegRes[31]}}, NegRes[31:0]}; + CalcExp[`NE] ? XSgnE&Signed&Plus1 ? {{`XLEN{1'b1}}} : {{`XLEN-1{1'b0}}, Plus1} : //CalcExp has to come after invalid ***swap to actual mux at some point?? + Int64 ? NegRes[`XLEN-1:0] : {{`XLEN-32{NegRes[31]}}, NegRes[31:0]}; endmodule \ No newline at end of file diff --git a/pipelined/testbench/testbench-fp.sv b/pipelined/testbench/testbench-fp.sv index 0870acad..3e90aeaf 100644 --- a/pipelined/testbench/testbench-fp.sv +++ b/pipelined/testbench/testbench-fp.sv @@ -545,15 +545,15 @@ module testbenchfp; Fmt = {Fmt, 2'b10}; end if (`XLEN == 64) begin // if 64-bit integers are supported - Tests = {Tests, f16rv64cvtint, f16rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b10}; - end + Tests = {Tests, f16rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b10}; + end end end if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested @@ -1187,9 +1187,9 @@ end // Testfloat outputs 800... for both the largest integer values for both positive and negitive numbers but // the riscv spec specifies 2^31-1 for positive values out of range and NaNs ie 7fff... - else if ((UnitVal === `CVTINTUNIT) & ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&XSgn&(Res === (`FLEN)'(0))) | - (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&OpCtrlVal[1]&(Res === {1'b0, {`FLEN-1{1'b1}}})) | - (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&~OpCtrlVal[1]&(Res === {{`FLEN{1'b0}}, 1'b0, {31{1'b1}}})) | + else if ((UnitVal === `CVTINTUNIT) & ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&XSgn&(Res[`XLEN-1:0] === (`XLEN)'(0))) | + (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&OpCtrlVal[1]&(Res[`XLEN-1:0] === {1'b0, {`XLEN-1{1'b1}}})) | + (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&~OpCtrlVal[1]&(Res[`XLEN-1:0] === {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}})) | (Res === Ans | NaNGood | NaNGood === 1'bx)) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin errors += 1; $display("There is an error in %s", Tests[TestNum]); diff --git a/pipelined/testbench/tests-fp.vh b/pipelined/testbench/tests-fp.vh index d872da71..15abb652 100644 --- a/pipelined/testbench/tests-fp.vh +++ b/pipelined/testbench/tests-fp.vh @@ -54,16 +54,6 @@ `define CMPUNIT 4 string f16rv32cvtint[] = '{ - "f16_to_i32_rne.tv", - "f16_to_i32_rz.tv", - "f16_to_i32_ru.tv", - "f16_to_i32_rd.tv", - "f16_to_i32_rnm.tv", - "f16_to_ui32_rne.tv", - "f16_to_ui32_rz.tv", - "f16_to_ui32_ru.tv", - "f16_to_ui32_rd.tv", - "f16_to_ui32_rnm.tv", "ui32_to_f16_rne.tv", "ui32_to_f16_rz.tv", "ui32_to_f16_ru.tv", @@ -73,20 +63,20 @@ string f16rv32cvtint[] = '{ "i32_to_f16_rz.tv", "i32_to_f16_ru.tv", "i32_to_f16_rd.tv", - "i32_to_f16_rnm.tv" + "i32_to_f16_rnm.tv", + "f16_to_ui32_rne.tv", + "f16_to_ui32_rz.tv", + "f16_to_ui32_ru.tv", + "f16_to_ui32_rd.tv", + "f16_to_ui32_rnm.tv", + "f16_to_i32_rne.tv", + "f16_to_i32_rz.tv", + "f16_to_i32_ru.tv", + "f16_to_i32_rd.tv", + "f16_to_i32_rnm.tv" }; string f16rv64cvtint[] = '{ - "f16_to_ui64_rne.tv", - "f16_to_ui64_rz.tv", - "f16_to_ui64_ru.tv", - "f16_to_ui64_rd.tv", - "f16_to_ui64_rnm.tv", - "f16_to_i64_rne.tv", - "f16_to_i64_rz.tv", - "f16_to_i64_ru.tv", - "f16_to_i64_rd.tv", - "f16_to_i64_rnm.tv", "ui64_to_f16_rne.tv", "ui64_to_f16_rz.tv", "ui64_to_f16_ru.tv", @@ -96,7 +86,17 @@ string f16rv64cvtint[] = '{ "i64_to_f16_rz.tv", "i64_to_f16_ru.tv", "i64_to_f16_rd.tv", - "i64_to_f16_rnm.tv" + "i64_to_f16_rnm.tv", + "f16_to_ui64_rne.tv", + "f16_to_ui64_rz.tv", + "f16_to_ui64_ru.tv", + "f16_to_ui64_rd.tv", + "f16_to_ui64_rnm.tv", + "f16_to_i64_rne.tv", + "f16_to_i64_rz.tv", + "f16_to_i64_ru.tv", + "f16_to_i64_rd.tv", + "f16_to_i64_rnm.tv" }; string f32rv32cvtint[] = '{ @@ -307,16 +307,16 @@ string f128f32cvt[] = '{ string f128f64cvt[] = '{ - "f64_to_f128_rne.tv", - "f64_to_f128_rz.tv", - "f64_to_f128_ru.tv", - "f64_to_f128_rd.tv", - "f64_to_f128_rnm.tv", "f128_to_f64_rne.tv", "f128_to_f64_rz.tv", "f128_to_f64_ru.tv", "f128_to_f64_rd.tv", - "f128_to_f64_rnm.tv" + "f128_to_f64_rnm.tv", + "f64_to_f128_rne.tv", + "f64_to_f128_rz.tv", + "f64_to_f128_ru.tv", + "f64_to_f128_rd.tv", + "f64_to_f128_rnm.tv" }; string f16add[] = '{