This commit is contained in:
DTowersM 2022-05-26 23:36:49 +00:00
commit 74b05d371b
8 changed files with 1949 additions and 1438 deletions

View File

@ -39,12 +39,12 @@
// MISA RISC-V configuration per specification // MISA RISC-V configuration per specification
//16 - quad 3 - double 5 - single //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 ZICSR_SUPPORTED 1
`define ZIFENCEI_SUPPORTED 1 `define ZIFENCEI_SUPPORTED 1
`define COUNTERS 32 `define COUNTERS 32
`define ZICOUNTERS_SUPPORTED 1 `define ZICOUNTERS_SUPPORTED 1
`define ZFH_SUPPORTED 0 `define ZFH_SUPPORTED 1
/// Microarchitectural Features /// Microarchitectural Features
`define UARCH_PIPELINED 1 `define UARCH_PIPELINED 1

View File

@ -82,7 +82,11 @@ module fcvt (
// choose the ouptut format depending on the opperation // choose the ouptut format depending on the opperation
// - fp -> fp: OpCtrl contains the percision of the output // - fp -> fp: OpCtrl contains the percision of the output
// - int -> fp: FmtE 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 // negation
@ -108,7 +112,7 @@ module fcvt (
// int -> fp : | positive integer | 00000... (if needed) | // int -> fp : | positive integer | 00000... (if needed) |
// fp -> fp : | fraction | 00000... (if needed) | // fp -> fp : | fraction | 00000... (if needed) |
assign LzcIn = IntToFp ? {PosInt, {`LGLEN-`XLEN{1'b0}}} : // I->F 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 // lglen is the largest possible value of ZeroCnt (NF or XLEN) hence normcnt must be log2(lglen) bits
logic [$clog2(`LGLEN):0] i, ZeroCnt; logic [$clog2(`LGLEN):0] i, ZeroCnt;
@ -122,25 +126,6 @@ module fcvt (
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// shifter // 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 // seclect the input to the shifter
// fp -> int: // 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 // - 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) // - ex: for the case 0010000.... (double)
// ??? -> fp: // ??? -> fp:
// - if result is denormalized or underflowed then we want to normalize the result: // - if result is denormalized or underflowed then we want to shift right i.e. shift right then shift left:
// | `NF zeros | Mantissa | 0's if nessisary | // | `NF-1 zeros | Mantissa | 0's if nessisary |
// - otherwise: // - otherwise:
// | lzcIn | 0's if nessisary | // | 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}}} : 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 // kill the shift if it's negitive
// select the amount to shift by // select the amount to shift by
// fp -> int: // 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 // - 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? // - 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]}} : 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 // 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; assign Shifted = ShiftIn << ShiftAmt;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// exp calculations // exp calculations
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// fp -> int
// CalcExp = 1 - largest bias + 1 -
// *** possible optimizaations: // *** possible optimizaations:
@ -193,9 +212,34 @@ module fcvt (
// Select the bias of the output // Select the bias of the output
// fp -> int : select 1 // 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 // select the old exponent
// int -> fp : largest bias + XLEN // int -> fp : largest bias + XLEN
// fp -> ??? : XExp // fp -> ??? : XExp
@ -203,22 +247,76 @@ module fcvt (
// calculate CalcExp // calculate CalcExp
// fp -> fp : // fp -> fp :
// - XExp - Largest bias + new bias // - XExp - Largest bias + new bias - (ZeroCnt+1)
// fp -> int : XExp // only do ^ if the input was denormalized
// int -> fp : largest bias + XLEN // - convert the expoenent to the final preciaion (Exp - oldBias + newBias)
// the -XOrigDenorm is to take into account the correction (which had a plus 1) // - 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}})}; 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 // find if the result is dnormal or underflows
assign ResDenormUf = (~|CalcExp | CalcExp[`NE])&~XZeroE; // - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0)
assign ResNegNF = (FOpCtrlE[1:0] == `FMT) ? -`NF : -`NF1; // - can't underflow an integer to Fp conversion
// if the reuslt underflows and somthing is shifted out set the sticky bit assign ResDenormUf = (~|CalcExp | CalcExp[`NE])&~XZeroE&~IntToFp;
assign ResUf = ($signed(CalcExp) < $signed({{`NE-$clog2(`NF){1'b1}}, ResNegNF}))&~XZeroE; // 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 // 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; assign ResSgn = IntToFp ? Int64 ? ForwardedSrcAE[`XLEN-1]&Signed : ForwardedSrcAE[31]&Signed : XSgnE;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -241,17 +339,80 @@ module fcvt (
// {Guard, Round, Sticky} // {Guard, Round, Sticky}
// 0x - do nothing // 0x - do nothing
// 1x - Plus1 // 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 end else if (`FPSIZES == 2) begin
assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] : assign Sticky = ToInt ? |Shifted[`LGLEN+`NF-`XLEN-1:0] :
(OutFmt ? |Shifted[`LGLEN+`NF-`NF-1:0] : |Shifted[`LGLEN+`NF-`NF1-1:0])|ResUf; (OutFmt ? |Shifted[`LGLEN+`NF-`NF-1:0] : |Shifted[`LGLEN+`NF-`NF1-1:0])|ResUf;
assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] : assign Round = ToInt ? Shifted[`LGLEN+`NF-`XLEN] :
OutFmt ? Shifted[`LGLEN+`NF-`NF] : |Shifted[`LGLEN+`NF-`NF1]; OutFmt ? Shifted[`LGLEN+`NF-`NF] : Shifted[`LGLEN+`NF-`NF1];
assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] : assign LSBFrac = ToInt ? Shifted[`LGLEN+`NF-`XLEN+1] :
OutFmt ? Shifted[`LGLEN+`NF-`NF+1] : Shifted[`LGLEN+`NF-`NF1+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 // Determine if you add 1
case (FrmE) case (FrmE)
3'b000: CalcPlus1 = Round & (Sticky | LSBFrac);//round to nearest even 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 3'b100: CalcPlus1 = Round;//round to nearest max magnitude
default: CalcPlus1 = 1'bx; default: CalcPlus1 = 1'bx;
endcase 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 // kill calcExp if the result is denormalized
assign {FullResExp, ResFrac} = {CalcExp&{`NE+1{~ResDenormUf}}, Shifted[`LGLEN+`NF:`LGLEN+`NF+1-`NF]} + ShiftedPlus1; 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]; assign ResExp = FullResExp[`NE-1:0];
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// flags // flags
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// calculate the flags // calculate the flags
// dont set underflow overflow or inexact flags if result is NaN
assign MaxExp = ToInt ? Int64 ? 65 : 33 : // find the maximum exponent (the exponent and larger overflows)
OutFmt ? {`NE{1'b1}} : {{`NE-`NE1{1'b0}}, {`NE1{1'b1}}}; if (`FPSIZES == 1) begin
// if the exponent is lager or equal to the maximum and it's not negitive assign MaxExp = ToInt ? Int64 ? 65 : 33 : {`NE{1'b1}};
// F->F if the input is inf then the output is also Inf ie exact, so dont set the underflow flag
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 // if the result exponent is larger then the maximum possible exponent
// | and the exponent is positive // | and the exponent is positive
// | | and the input is not NaN or Infinity // | | and the input is not NaN or Infinity
// | | | // | | |
assign Overflow = ((ResExp >= MaxExp)&~CalcExp[`NE]&~(XNaNE|XInfE)); assign Overflow = ((ResExp >= MaxExp)&~CalcExp[`NE]&(~(XNaNE|XInfE)|IntToFp));
// 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
// if the result is denormalized or underflowed // if the result is denormalized or underflowed
// | and the result did not round into normal values // | and the result did not round into normal values
@ -294,18 +521,24 @@ module fcvt (
// | | | and the result isn't NaN // | | | and the result isn't NaN
// | | | | // | | | |
assign Underflow = ResDenormUf & ~(ResExp==1 & CalcExp == 0) & (Sticky|Round)&~(XNaNE); 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 // 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 there were bits thrown away
// | if overflowed or underflowed // | if overflowed or underflowed
// | | and if not a NaN // | | and if not a NaN
// | | | // | | |
assign FpInexact = (Sticky|Round|Underflow|Overflow)&(~XNaNE|IntToFp); assign FpInexact = (Sticky|Round|Underflow|Overflow)&(~XNaNE|IntToFp);
// if the result is too small to be represented and not 0 // if the result is too small to be represented and not 0
// | and if the result is not invalid (outside the integer bounds) // | and if the result is not invalid (outside the integer bounds)
// | | // | |
assign IntInexact = ((CalcExp[`NE]&~XZeroE)|Sticky|Round)&~Invalid; assign IntInexact = ((CalcExp[`NE]&~XZeroE)|Sticky|Round)&~Invalid;
// select the inexact flag to output
assign Inexact = ToInt ? IntInexact : FpInexact; assign Inexact = ToInt ? IntInexact : FpInexact;
// if an input was a singaling NaN(and we're using a FP input) // if an input was a singaling NaN(and we're using a FP input)
// |
assign FpInvalid = (XSNaNE&~IntToFp); assign FpInvalid = (XSNaNE&~IntToFp);
assign NegResMSBS = Signed ? Int64 ? NegRes[`XLEN:`XLEN-1] : NegRes[32:31] : 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]); 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 // or when the positive result rounds up out of range
// select the inexact flag to output
assign Invalid = ToInt ? IntInvalid : FpInvalid; assign Invalid = ToInt ? IntInvalid : FpInvalid;
// pack the flags together and choose the result based on the opperation // pack the flags together
// don't set the overflow or underfolw flags if converting to integer // - fp -> int does not set the overflow or underflow flags
assign CvtFlgE = {Invalid, 1'b0, Overflow&~ToInt, Underflow&~ToInt, Inexact}; assign CvtFlgE = {Invalid, 1'b0, Overflow&~ToInt, Underflow&~ToInt, Inexact};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// result selection // 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; // determine if you shoould kill the result
//assign MinDenormExp = FOpCtrlE[1:0] == `FMT ? -`NE : -`NE1; // - 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 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 if (`FPSIZES == 1) 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]}; // IEEE sends a payload while Riscv says to send a canonical quiet NaN
end else begin if(`IEEE754) 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}}}; 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 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 // choose the floating point result
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}}} : // - if the input is NaN (and using the NaN input) output the NaN result
{ResSgn, {`NE{1'b1}}, {`NF{1'b0}}} : // - if the input is infinity or the output overflows
~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}}} : // - kill the InfE signal if the input isn't a floating point value
{{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; // - if killing the result output the underflow result
// if RU/RD then round the underflowed result if needed // - otherwise output the normal result
// 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]};
assign CvtResE = XNaNE&~IntToFp ? NaNRes : assign CvtResE = XNaNE&~IntToFp ? NaNRes :
(XInfE|Overflow)&~IntToFp ? InfRes : (XInfE&~IntToFp)|Overflow ? InfRes :
KillRes ? UfRes : KillRes ? UfRes :
Res; Res;
// *** probably can optimize the negation // *** probably can optimize the negation
// NaNs sould ouput the same as a positive infinity // select the overflow integer result
// a 32bit unsigend result should be sign extended (as if it is not a unsigned number) // - 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 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 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 XSgnE&~XNaNE ? {`XLEN{1'b0}} : // unsigned negitive
{`XLEN{1'b1}};// unsigned positive {`XLEN{1'b1}};// unsigned positive
// 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}; 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 : 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?? 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]}; Int64 ? NegRes[`XLEN-1:0] : {{`XLEN-32{NegRes[31]}}, NegRes[31:0]};
endmodule endmodule

View File

@ -86,13 +86,13 @@ module srt #(parameter Nf=52) (
// Partial Product Generation // Partial Product Generation
csa csa(WS, WC, Dsel, qp, WSA, WCA); csa csa(WS, WC, Dsel, qp, WSA, WCA);
otfc2 otfc2(clk, Start, qp, qz, qm, QuotOTFC);
expcalc expcalc(.XExp, .YExp, .calcExp); expcalc expcalc(.XExp, .YExp, .calcExp);
signcalc signcalc(.XSign, .YSign, .calcSign); signcalc signcalc(.XSign, .YSign, .calcSign);
srtpostproc postproc(rp, rm, Quot); srtpostproc postproc(rp, rm, Quot);
otfc otfc(qp, qz, qm, Quot, QuotOTFC);
endmodule endmodule
module srtpostproc #(parameter N=52) ( module srtpostproc #(parameter N=52) (
@ -216,13 +216,46 @@ endmodule
// otfc // // otfc //
////////// //////////
module otfc #(parameter N=52) ( module otfc2 #(parameter N=52) (
input logic clk,
input logic Start,
input logic qp, qz, qm, input logic qp, qz, qm,
input logic [N-1:0] Quot, output logic [N-1:0] r
output logic [N-1:0] QuotOTFC
); );
assign QuotOTFC = Quot; // The on-the-fly converter transfers the quotient
// bits to the quotient as they come.
//
// This code follows the psuedocode presented in the
// floating point chapter of the book. Right now,
// it is written for Radix-2 division.
//
// QM is Q-1. It allows us to write negative bits
// without using a costly CPA.
logic [N+2:0] Q, QM, QNext, QMNext;
// QR and QMR are the shifted versions of Q and QM.
// They are treated as [N-1:r] size signals, and
// discard the r most significant bits of Q and QM.
logic [N+1:0] QR, QMR;
flopr #(N+3) Qreg(clk, Start, QNext, Q);
flopr #(N+3) QMreg(clk, Start, QMNext, QM);
always_comb begin
QR = Q[N+1:0];
QMR = QM[N+1:0]; // Shift Q and QM
if (qp) begin
QNext = {QR, 1'b1};
QMNext = {QR, 1'b0};
end else if (qz) begin
QNext = {QR, 1'b0};
QMNext = {QMR, 1'b1};
end else begin // If qp and qz are not true, then qm is
QNext = {QMR, 1'b1};
QMNext = {QMR, 1'b0};
end
end
assign r = Q[54] ? Q[53:2] : Q[52:1];
endmodule endmodule
@ -286,7 +319,7 @@ module expcalc(
output logic [`NE-1:0] calcExp output logic [`NE-1:0] calcExp
); );
assign calcExp = XExp - YExp + `BIAS; assign calcExp = XExp - YExp + 11'b01111111111;
endmodule endmodule

View File

@ -121,8 +121,8 @@ module testbench;
begin begin
errors = errors+1; errors = errors+1;
$display("OTFC is %h, should be %h\n", rOTFC, r); $display("OTFC is %h, should be %h\n", rOTFC, r);
$display("failed/n"); $display("failed\n");
$stop; // $stop;
end end
if (afrac === 52'hxxxxxxxxxxxxx) if (afrac === 52'hxxxxxxxxxxxxx)
begin begin

View File

@ -545,15 +545,15 @@ module testbenchfp;
Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
end end
if (`XLEN == 64) begin // if 64-bit integers are supported if (`XLEN == 64) begin // if 64-bit integers are supported
Tests = {Tests, f16rv64cvtint, f16rv32cvtint}; Tests = {Tests, f16rv64cvtint};
// add the op-codes for these tests to the op-code list // 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}; OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; 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) // add what unit is used and the fmt to their lists (one for each test)
for(int i = 0; i<20; i++) begin for(int i = 0; i<20; i++) begin
Unit = {Unit, `CVTINTUNIT}; Unit = {Unit, `CVTINTUNIT};
Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
end end
end end
end end
if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested 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 // 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... // 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))) | 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 === {1'b0, {`FLEN-1{1'b1}}})) | (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 === {{`FLEN{1'b0}}, 1'b0, {31{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 (Res === Ans | NaNGood | NaNGood === 1'bx)) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin
errors += 1; errors += 1;
$display("There is an error in %s", Tests[TestNum]); $display("There is an error in %s", Tests[TestNum]);

View File

@ -54,16 +54,6 @@
`define CMPUNIT 4 `define CMPUNIT 4
string f16rv32cvtint[] = '{ 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_rne.tv",
"ui32_to_f16_rz.tv", "ui32_to_f16_rz.tv",
"ui32_to_f16_ru.tv", "ui32_to_f16_ru.tv",
@ -73,20 +63,20 @@ string f16rv32cvtint[] = '{
"i32_to_f16_rz.tv", "i32_to_f16_rz.tv",
"i32_to_f16_ru.tv", "i32_to_f16_ru.tv",
"i32_to_f16_rd.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[] = '{ 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_rne.tv",
"ui64_to_f16_rz.tv", "ui64_to_f16_rz.tv",
"ui64_to_f16_ru.tv", "ui64_to_f16_ru.tv",
@ -96,7 +86,17 @@ string f16rv64cvtint[] = '{
"i64_to_f16_rz.tv", "i64_to_f16_rz.tv",
"i64_to_f16_ru.tv", "i64_to_f16_ru.tv",
"i64_to_f16_rd.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[] = '{ string f32rv32cvtint[] = '{
@ -307,16 +307,16 @@ string f128f32cvt[] = '{
string f128f64cvt[] = '{ 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_rne.tv",
"f128_to_f64_rz.tv", "f128_to_f64_rz.tv",
"f128_to_f64_ru.tv", "f128_to_f64_ru.tv",
"f128_to_f64_rd.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[] = '{ string f16add[] = '{

View File

@ -7,6 +7,7 @@ import csv
import re import re
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.lines as lines import matplotlib.lines as lines
import matplotlib.axes as axes
import numpy as np import numpy as np
from collections import namedtuple from collections import namedtuple
@ -24,60 +25,69 @@ def synthsfromcsv(filename):
except: pass except: pass
allSynths[i] = Synth(*allSynths[i]) allSynths[i] = Synth(*allSynths[i])
def synthsintocsv(mod=None, width=None): def synthsintocsv():
''' writes a CSV with one line for every available synthesis ''' writes a CSV with one line for every available synthesis
each line contains the module, tech, width, target freq, and resulting metrics each line contains the module, tech, width, target freq, and resulting metrics
''' '''
specStr = ''
if mod != None:
specStr = mod
if width != None:
specStr += ('_'+str(width))
specStr += '*'
bashCommand = "grep 'Critical Path Length' runs/ppa_{}/reports/*qor*".format(specStr) bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
outputCPL = subprocess.check_output(['bash','-c', bashCommand]) output = subprocess.check_output(['bash','-c', bashCommand])
linesCPL = outputCPL.decode("utf-8").split('\n')[:-1] allSynths = output.decode("utf-8").split('\n')[:-1]
bashCommand = "grep 'Design Area' runs/ppa_{}/reports/*qor*".format(specStr) specReg = re.compile('[a-zA-Z0-9]+')
outputDA = subprocess.check_output(['bash','-c', bashCommand]) metricReg = re.compile('\d+\.\d+[e]?[-+]?\d*')
linesDA = outputDA.decode("utf-8").split('\n')[:-1]
bashCommand = "grep '100' runs/ppa_{}/reports/*power*".format(specStr)
outputP = subprocess.check_output(['bash','-c', bashCommand])
linesP = outputP.decode("utf-8").split('\n')[:-1]
cpl = re.compile('\d{1}\.\d{6}')
f = re.compile('_\d*_MHz')
wm = re.compile('ppa_\w*_\d*_qor')
da = re.compile('\d*\.\d{6}')
p = re.compile('\d+\.\d+[e-]*\d+')
t = re.compile('[a-zA-Z0-9]+nm')
file = open("ppaData.csv", "w") file = open("ppaData.csv", "w")
writer = csv.writer(file) writer = csv.writer(file)
writer.writerow(['Module', 'Tech', 'Width', 'Target Freq', 'Delay', 'Area', 'L Power (nW)', 'D energy (mJ)']) writer.writerow(['Module', 'Tech', 'Width', 'Target Freq', 'Delay', 'Area', 'L Power (nW)', 'D energy (mJ)'])
for i in range(len(linesCPL)): for oneSynth in allSynths:
line = linesCPL[i] module, width, risc, tech, freq = specReg.findall(oneSynth)[2:7]
mwm = wm.findall(line)[0][4:-4].split('_') tech = tech[:-2]
freq = int(f.findall(line)[0][1:-4]) metrics = []
delay = float(cpl.findall(line)[0]) for phrase in [['Path Length', 'qor'], ['Design Area', 'qor'], ['100', 'power']]:
area = float(da.findall(linesDA[i])[0]) bashCommand = 'grep "{}" '+ oneSynth[2:]+'/reports/*{}*'
mod = mwm[0] bashCommand = bashCommand.format(*phrase)
width = int(mwm[1]) try: output = subprocess.check_output(['bash','-c', bashCommand])
tech = t.findall(line)[0][:-2] except: print("At least one synth run doesn't have reports, try cleanup() first")
try: #fix nums = metricReg.findall(str(output))
power = p.findall(linesP[i]) nums = [float(m) for m in nums]
lpower = float(power[2]) metrics += nums
denergy = float(power[1])*delay delay = metrics[0]
except: area = metrics[1]
lpower = 0 lpower = metrics[4]
denergy = 0 denergy = (metrics[2] + metrics[3])*delay # (switching + internal powers)*delay
writer.writerow([mod, tech, width, freq, delay, area, lpower, denergy]) writer.writerow([module, tech, width, freq, delay, area, lpower, denergy])
file.close() file.close()
def cleanup():
''' removes runs that didn't work
'''
bashCommand = 'grep -r "Error" runs/ppa*/reports/*qor*'
try:
output = subprocess.check_output(['bash','-c', bashCommand])
allSynths = output.decode("utf-8").split('\n')[:-1]
for run in allSynths:
run = run.split('MHz')[0]
bc = 'rm -r '+ run + '*'
output = subprocess.check_output(['bash','-c', bc])
except: pass
bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
output = subprocess.check_output(['bash','-c', bashCommand])
allSynths = output.decode("utf-8").split('\n')[:-1]
for oneSynth in allSynths:
for phrase in [['Path Length', 'qor'], ['Design Area', 'qor'], ['100', 'power']]:
bashCommand = 'grep "{}" '+ oneSynth[2:]+'/reports/*{}*'
bashCommand = bashCommand.format(*phrase)
try: output = subprocess.check_output(['bash','-c', bashCommand])
except:
bc = 'rm -r '+ oneSynth[2:]
try: output = subprocess.check_output(['bash','-c', bc])
except: pass
print("All cleaned up!")
def getVals(tech, module, var, freq=None): def getVals(tech, module, var, freq=None):
''' for a specified tech, module, and variable/metric ''' for a specified tech, module, and variable/metric
returns a list of values for that metric in ascending width order with the appropriate units returns a list of values for that metric in ascending width order with the appropriate units
@ -112,7 +122,8 @@ def getVals(tech, module, var, freq=None):
m = oneSynth.delay m = oneSynth.delay
osdict = oneSynth._asdict() osdict = oneSynth._asdict()
met = osdict[var] met = osdict[var]
metric += [met] try: metric += [met]
except: pass
if ('flop' in module) & (var == 'area'): if ('flop' in module) & (var == 'area'):
metric = [m/2 for m in metric] # since two flops in each module metric = [m/2 for m in metric] # since two flops in each module
@ -144,9 +155,9 @@ def genLegend(fits, coefs, r2, techcolor):
eq += " + " + coefsr[ind] + "*Nlog2(N)" eq += " + " + coefsr[ind] + "*Nlog2(N)"
ind += 1 ind += 1
tech, c = techcolor tech, c, m = techcolor
legend_elements = [lines.Line2D([0], [0], color=c, label=eq), legend_elements = [lines.Line2D([0], [0], color=c, label=eq),
lines.Line2D([0], [0], color=c, ls='', marker='o', label=tech +' $R^2$='+ str(round(r2, 4)))] lines.Line2D([0], [0], color=c, ls='', marker=m, label=tech +' $R^2$='+ str(round(r2, 4)))]
return legend_elements return legend_elements
def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn'): def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn'):
@ -167,13 +178,13 @@ def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn'):
global techcolors global techcolors
global widths global widths
for combo in techcolors: for combo in techcolors:
tech, c = combo tech, c, m = combo
metric, units = getVals(tech, module, var, freq=freq) metric, units = getVals(tech, module, var, freq=freq)
if len(metric) == 5: if len(metric) == 5:
xp, pred, leg = regress(widths, metric, combo, fits) xp, pred, leg = regress(widths, metric, combo, fits)
fullLeg += leg fullLeg += leg
ax.scatter(widths, metric, color=c) ax.scatter(widths, metric, color=c, marker=m)
ax.plot(xp, pred, color=c) ax.plot(xp, pred, color=c)
ax.legend(handles=fullLeg) ax.legend(handles=fullLeg)
@ -183,7 +194,7 @@ def oneMetricPlot(module, var, freq=None, ax=None, fits='clsgn'):
ax.set_ylabel(str.title(var) + units) ax.set_ylabel(str.title(var) + units)
if singlePlot: if singlePlot:
titleStr = " (target " + str(freq)+ "MHz)" if freq != None else " (min delay)" titleStr = " (target " + str(freq)+ "MHz)" if freq != None else " (best delay)"
ax.set_title(module + titleStr) ax.set_title(module + titleStr)
plt.show() plt.show()
@ -266,17 +277,14 @@ def noOutliers(freqs, delays, areas):
f=[] f=[]
d=[] d=[]
a=[] a=[]
ind = delays.index(min(delays))
try: med = freqs[ind]
ind = delays.index(min(delays)) for i in range(len(freqs)):
med = freqs[ind] norm = freqs[i]/med
for i in range(len(freqs)): if (norm > 0.25) & (norm<1.75):
norm = freqs[i]/med f += [freqs[i]]
if (norm > 0.25) & (norm<1.75): d += [delays[i]]
f += [freqs[i]] a += [areas[i]]
d += [delays[i]]
a += [areas[i]]
except: pass
return f, d, a return f, d, a
@ -292,7 +300,7 @@ def freqPlot(tech, mod, width):
delaysL[ind] += [oneSynth.delay] delaysL[ind] += [oneSynth.delay]
areasL[ind] += [oneSynth.area] areasL[ind] += [oneSynth.area]
f, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 1, sharex=True) f, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, sharex=True)
for ind in [0,1]: for ind in [0,1]:
areas = areasL[ind] areas = areasL[ind]
@ -300,17 +308,15 @@ def freqPlot(tech, mod, width):
freqs = freqsL[ind] freqs = freqsL[ind]
if ('flop' in mod): areas = [m/2 for m in areas] # since two flops in each module if ('flop' in mod): areas = [m/2 for m in areas] # since two flops in each module
freqs, delays, areas = noOutliers(freqs, delays, areas) freqs, delays, areas = noOutliers(freqs, delays, areas) # comment out to see all syntheses
c = 'blue' if ind else 'green' c = 'blue' if ind else 'green'
adprod = adprodpow(areas, delays, 2) adprod = adprodpow(areas, delays, 1)
adpow = adprodpow(areas, delays, 3) adpow = adprodpow(areas, delays, 2)
adpow2 = adprodpow(areas, delays, 4)
ax1.scatter(freqs, delays, color=c) ax1.scatter(freqs, delays, color=c)
ax2.scatter(freqs, areas, color=c) ax2.scatter(freqs, areas, color=c)
ax3.scatter(freqs, adprod, color=c) ax3.scatter(freqs, adprod, color=c)
ax4.scatter(freqs, adpow, color=c) ax4.scatter(freqs, adpow, color=c)
ax5.scatter(freqs, adpow2, color=c)
legend_elements = [lines.Line2D([0], [0], color='green', ls='', marker='o', label='timing achieved'), legend_elements = [lines.Line2D([0], [0], color='green', ls='', marker='o', label='timing achieved'),
lines.Line2D([0], [0], color='blue', ls='', marker='o', label='slack violated')] lines.Line2D([0], [0], color='blue', ls='', marker='o', label='slack violated')]
@ -325,6 +331,43 @@ def freqPlot(tech, mod, width):
ax1.set_title(mod + '_' + str(width)) ax1.set_title(mod + '_' + str(width))
plt.show() plt.show()
def squareAreaDelay(tech, mod, width):
''' plots delay, area, area*delay, and area*delay^2 for syntheses with specified tech, module, width
'''
global allSynths
freqsL, delaysL, areasL = ([[], []] for i in range(3))
for oneSynth in allSynths:
if (mod == oneSynth.module) & (width == oneSynth.width) & (tech == oneSynth.tech):
ind = (1000/oneSynth.delay < oneSynth.freq) # when delay is within target clock period
freqsL[ind] += [oneSynth.freq]
delaysL[ind] += [oneSynth.delay]
areasL[ind] += [oneSynth.area]
fig = plt.figure()
ax = fig.add_subplot(111)
for ind in [0,1]:
areas = areasL[ind]
delays = delaysL[ind]
freqs = freqsL[ind]
if ('flop' in mod): areas = [m/2 for m in areas] # since two flops in each module
freqs, delays, areas = noOutliers(freqs, delays, areas) # comment out to see all syntheses
c = 'blue' if ind else 'green'
plt.scatter(delays, areas, color=c)
legend_elements = [lines.Line2D([0], [0], color='green', ls='', marker='o', label='timing achieved'),
lines.Line2D([0], [0], color='blue', ls='', marker='o', label='slack violated')]
plt.legend(handles=legend_elements)
plt.xlabel("Delay Achieved (ns)")
plt.ylabel('Area (sq microns)')
plt.title(mod + '_' + str(width))
ax.set_aspect(1./ax.get_data_ratio())
plt.show()
def adprodpow(areas, delays, pow): def adprodpow(areas, delays, pow):
''' for each value in [areas] returns area*delay^pow ''' for each value in [areas] returns area*delay^pow
helper function for freqPlot''' helper function for freqPlot'''
@ -341,22 +384,27 @@ def plotPPA(mod, freq=None):
overlays data from both techs overlays data from both techs
''' '''
fig, axs = plt.subplots(2, 2) fig, axs = plt.subplots(2, 2)
oneMetricPlot(mod, 'delay', ax=axs[0,0], fits='clg', freq=freq) oneMetricPlot(mod, 'delay', ax=axs[0,0], fits='cg', freq=freq)
oneMetricPlot(mod, 'area', ax=axs[0,1], fits='s', freq=freq) oneMetricPlot(mod, 'area', ax=axs[0,1], fits='s', freq=freq)
oneMetricPlot(mod, 'lpower', ax=axs[1,0], fits='c', freq=freq) oneMetricPlot(mod, 'lpower', ax=axs[1,0], fits='s', freq=freq)
oneMetricPlot(mod, 'denergy', ax=axs[1,1], fits='s', freq=freq) oneMetricPlot(mod, 'denergy', ax=axs[1,1], fits='s', freq=freq)
titleStr = " (target " + str(freq)+ "MHz)" if freq != None else " (min delay)" titleStr = " (target " + str(freq)+ "MHz)" if freq != None else " (best delay)"
plt.suptitle(mod + titleStr) plt.suptitle(mod + titleStr)
plt.show() plt.show()
Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy") if __name__ == '__main__':
techcolors = [['sky90', 'green'], ['tsmc28', 'blue']]
widths = [8, 16, 32, 64, 128]
synthsintocsv()
synthsfromcsv('ppaData.csv') # your csv here! # set up stuff, global variables
Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy")
techcolors = [['sky90', 'green', 'o'], ['tsmc28', 'blue', '^']] # add another list here for gf32
widths = [8, 16, 32, 64, 128]
### examples # synthsintocsv() # slow, run only when new synth runs to add to csv
# oneMetricPlot('add', 'delay')
#freqPlot('sky90', 'add', 8) synthsfromcsv('ppaData.csv') # your csv here!
#plotPPA('add')
### examples
# oneMetricPlot('add', 'delay')
# freqPlot('sky90', 'comparator', 16)
# plotPPA('add')
squareAreaDelay('sky90', 'comparator', 16)

File diff suppressed because it is too large Load Diff