mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
74b05d371b
@ -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
|
||||||
|
@ -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
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
@ -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[] = '{
|
||||||
|
@ -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)
|
2429
synthDC/ppaData.csv
2429
synthDC/ppaData.csv
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user