mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
some commenting fixes, converter optimizations, and moves normshift into postproc
This commit is contained in:
parent
9430aebaab
commit
fd3b967496
@ -32,21 +32,21 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module fcvt (
|
module fcvt (
|
||||||
input logic Xs, // input's sign
|
input logic Xs, // input's sign
|
||||||
input logic [`NE-1:0] Xe, // input's exponent
|
input logic [`NE-1:0] Xe, // input's exponent
|
||||||
input logic [`NF:0] Xm, // input's fraction
|
input logic [`NF:0] Xm, // input's fraction
|
||||||
input logic [`XLEN-1:0] Int, // integer input - from IEU
|
input logic [`XLEN-1:0] Int, // integer input - from IEU
|
||||||
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
|
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
|
||||||
input logic ToInt, // is fp->int (since it's writting to the integer register)
|
input logic ToInt, // is fp->int (since it's writting to the integer register)
|
||||||
input logic XZero, // is the input zero
|
input logic XZero, // is the input zero
|
||||||
input logic XDenorm, // is the input denormalized
|
input logic XDenorm, // is the input denormalized
|
||||||
input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half)
|
input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half)
|
||||||
output logic [`NE:0] Ce, // the calculated expoent
|
output logic [`NE:0] Ce, // the calculated expoent
|
||||||
output logic [`LOGCVTLEN-1:0] ShiftAmt, // how much to shift by
|
output logic [`LOGCVTLEN-1:0] ShiftAmt, // how much to shift by
|
||||||
output logic ResDenormUf,// does the result underflow or is denormalized
|
output logic ResDenormUf,// does the result underflow or is denormalized
|
||||||
output logic Cs, // the result's sign
|
output logic Cs, // the result's sign
|
||||||
output logic IntZero, // is the integer zero?
|
output logic IntZero, // is the integer zero?
|
||||||
output logic [`CVTLEN-1:0] LzcIn // input to the Leading Zero Counter (priority encoder)
|
output logic [`CVTLEN-1:0] LzcIn // input to the Leading Zero Counter (priority encoder)
|
||||||
);
|
);
|
||||||
|
|
||||||
// OpCtrls:
|
// OpCtrls:
|
||||||
@ -68,15 +68,15 @@ module fcvt (
|
|||||||
logic [`NE-1:0] OldExp; // the old exponent
|
logic [`NE-1:0] OldExp; // the old exponent
|
||||||
logic Signed; // is the opperation with a signed integer?
|
logic Signed; // is the opperation with a signed integer?
|
||||||
logic Int64; // is the integer 64 bits?
|
logic Int64; // is the integer 64 bits?
|
||||||
logic IntToFp; // is the opperation an int->fp conversion?
|
logic IntToFp; // is the opperation an int->fp conversion?
|
||||||
logic [`CVTLEN:0] LzcInFull; // input to the Leading Zero Counter (priority encoder)
|
logic [`CVTLEN:0] LzcInFull; // input to the Leading Zero Counter (priority encoder)
|
||||||
logic [`LOGCVTLEN-1:0] LeadingZeros; // output from the LZC
|
logic [`LOGCVTLEN-1:0] LeadingZeros; // output from the LZC
|
||||||
|
|
||||||
|
|
||||||
// seperate OpCtrl for code readability
|
// seperate OpCtrl for code readability
|
||||||
assign Signed = OpCtrl[0];
|
assign Signed = OpCtrl[0];
|
||||||
assign Int64 = OpCtrl[1];
|
assign Int64 = OpCtrl[1];
|
||||||
assign IntToFp = OpCtrl[2];
|
assign IntToFp = OpCtrl[2];
|
||||||
|
|
||||||
// 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
|
||||||
@ -110,27 +110,6 @@ module fcvt (
|
|||||||
|
|
||||||
lzc #(`CVTLEN+1) lzc (.num(LzcInFull), .ZeroCnt(LeadingZeros));
|
lzc #(`CVTLEN+1) lzc (.num(LzcInFull), .ZeroCnt(LeadingZeros));
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// shifter
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// kill the shift if it's negitive
|
|
||||||
// select the amount to shift by
|
|
||||||
// fp -> int:
|
|
||||||
// - shift left by CalcExp - essentially shifting until the unbiased exponent = 0
|
|
||||||
// - don't shift if supposed to shift right (underflowed or denorm input)
|
|
||||||
// denormalized/undeflowed result fp -> fp:
|
|
||||||
// - shift left by NF-1+CalcExp - to shift till the biased expoenent is 0
|
|
||||||
// ??? -> fp:
|
|
||||||
// - shift left by LeadingZeros - to shift till the result is normalized
|
|
||||||
// - only shift fp -> fp if the intital value is denormalized
|
|
||||||
// - this is a problem because the input to the lzc was the fraction rather than the mantissa
|
|
||||||
// - rather have a few and-gates than an extra bit in the priority encoder??? *** is this true?
|
|
||||||
always_comb
|
|
||||||
if(ToInt) ShiftAmt = Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}};
|
|
||||||
else if (ResDenormUf&~IntToFp) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0];
|
|
||||||
else ShiftAmt = LeadingZeros;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// exp calculations
|
// exp calculations
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -179,7 +158,7 @@ module fcvt (
|
|||||||
assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp;
|
assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp;
|
||||||
end
|
end
|
||||||
// select the old exponent
|
// select the old exponent
|
||||||
// int -> fp : largest bias + XLEN
|
// int -> fp : largest bias + XLEN-1
|
||||||
// fp -> ??? : XExp
|
// fp -> ??? : XExp
|
||||||
assign OldExp = IntToFp ? (`NE)'(`BIAS)+(`NE)'(`XLEN-1) : Xe;
|
assign OldExp = IntToFp ? (`NE)'(`BIAS)+(`NE)'(`XLEN-1) : Xe;
|
||||||
|
|
||||||
@ -189,6 +168,7 @@ module fcvt (
|
|||||||
// only do ^ if the input was denormalized
|
// only do ^ if the input was denormalized
|
||||||
// - convert the expoenent to the final preciaion (Exp - oldBias + newBias)
|
// - convert the expoenent to the final preciaion (Exp - oldBias + newBias)
|
||||||
// - correct the expoent when there is a normalization shift ( + LeadingZeros+1)
|
// - correct the expoent when there is a normalization shift ( + LeadingZeros+1)
|
||||||
|
// - the plus 1 is built into the leading zeros by counting the leading zeroes in the mantissa rather than the fraction
|
||||||
// fp -> int : XExp - Largest Bias + 1 - (LeadingZeros+1)
|
// fp -> int : XExp - Largest Bias + 1 - (LeadingZeros+1)
|
||||||
// | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
|
// | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
|
||||||
// process:
|
// process:
|
||||||
@ -204,19 +184,45 @@ module fcvt (
|
|||||||
// | keep |
|
// | keep |
|
||||||
//
|
//
|
||||||
// - if the input is denormalized then we dont shift... so the "- LeadingZeros" is just leftovers from other options
|
// - if the input is denormalized then we dont shift... so the "- LeadingZeros" is just leftovers from other options
|
||||||
// int -> fp : largest bias + XLEN - Largest bias + new bias - LeadingZeros = XLEN + NewBias - LeadingZeros
|
// int -> fp : largest bias + XLEN-1 - Largest bias + new bias - LeadingZeros = XLEN-1 + NewBias - LeadingZeros
|
||||||
// Process:
|
// Process:
|
||||||
|
// |XLEN|.0000
|
||||||
// - shifted right by XLEN (XLEN)
|
// - shifted right by XLEN (XLEN)
|
||||||
|
// 000000.|XLEN|
|
||||||
// - shift left to normilize (-LeadingZeros)
|
// - shift left to normilize (-LeadingZeros)
|
||||||
|
// 000000.1...
|
||||||
|
// - shift left 1 to normalize
|
||||||
|
// 000001.stuff
|
||||||
// - newBias to make the biased exponent
|
// - newBias to make the biased exponent
|
||||||
// oldexp - biasold +newbias - LeadingZeros&(XDenorm|IntToFp)
|
//
|
||||||
assign Ce = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE-`LOGCVTLEN+1{1'b0}}, (LeadingZeros&{`LOGCVTLEN{XDenorm|IntToFp}})};
|
// oldexp - biasold - LeadingZeros + newbias
|
||||||
|
assign Ce = {1'b0, OldExp} - (`NE+1)'(`BIAS) - {{`NE-`LOGCVTLEN+1{1'b0}}, (LeadingZeros)} + {2'b0, NewBias};
|
||||||
// find if the result is dnormal or underflows
|
// find if the result is dnormal or underflows
|
||||||
// - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0)
|
// - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0)
|
||||||
// - can't underflow an integer to Fp conversion
|
// - can't underflow an integer to Fp conversion
|
||||||
assign ResDenormUf = (~|Ce | Ce[`NE])&~XZero&~IntToFp;
|
assign ResDenormUf = (~|Ce | Ce[`NE])&~XZero&~IntToFp;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// shifter
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// kill the shift if it's negitive
|
||||||
|
// select the amount to shift by
|
||||||
|
// fp -> int:
|
||||||
|
// - shift left by CalcExp - essentially shifting until the unbiased exponent = 0
|
||||||
|
// - don't shift if supposed to shift right (underflowed or denorm input)
|
||||||
|
// denormalized/undeflowed result fp -> fp:
|
||||||
|
// - shift left by NF-1+CalcExp - to shift till the biased expoenent is 0
|
||||||
|
// ??? -> fp:
|
||||||
|
// - shift left by LeadingZeros - to shift till the result is normalized
|
||||||
|
// - only shift fp -> fp if the intital value is denormalized
|
||||||
|
// - this is a problem because the input to the lzc was the fraction rather than the mantissa
|
||||||
|
// - rather have a few and-gates than an extra bit in the priority encoder??? *** is this true?
|
||||||
|
always_comb//***change denorm to subnorm
|
||||||
|
if(ToInt) ShiftAmt = Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}};
|
||||||
|
else if (ResDenormUf) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0];
|
||||||
|
else ShiftAmt = LeadingZeros;
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// sign
|
// sign
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
///////////////////////////////////////////
|
|
||||||
// normshift.sv
|
|
||||||
//
|
|
||||||
// Written: me@KatherineParry.com
|
|
||||||
// Modified: 7/5/2022
|
|
||||||
//
|
|
||||||
// Purpose: normalization shifter
|
|
||||||
//
|
|
||||||
// A component of the Wally configurable RISC-V project.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
|
||||||
//
|
|
||||||
// MIT LICENSE
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
||||||
// software and associated documentation files (the "Software"), to deal in the Software
|
|
||||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
|
||||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
|
||||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all copies or
|
|
||||||
// substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
||||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
||||||
// OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
`include "wally-config.vh"
|
|
||||||
|
|
||||||
|
|
||||||
// convert shift
|
|
||||||
// fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
|
|
||||||
// process:
|
|
||||||
// - start - CalcExp = 1 + XExp - Largest Bias
|
|
||||||
// | `XLEN zeros | Mantissa | 0's if nessisary |
|
|
||||||
//
|
|
||||||
// - shift left 1 (1)
|
|
||||||
// | `XLEN-1 zeros |bit| frac | 0's if nessisary |
|
|
||||||
// . <- binary point
|
|
||||||
//
|
|
||||||
// - shift left till unbiased exponent is 0 (XExp - Largest Bias)
|
|
||||||
// | 0's | Mantissa | 0's if nessisary |
|
|
||||||
// | keep |
|
|
||||||
//
|
|
||||||
// fp -> fp:
|
|
||||||
// - if result is denormalized or underflowed:
|
|
||||||
// | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1
|
|
||||||
// process:
|
|
||||||
// - start
|
|
||||||
// | mantissa | 0's |
|
|
||||||
//
|
|
||||||
// - shift right by NF-1 (NF-1)
|
|
||||||
// | `NF-1 zeros | mantissa | 0's |
|
|
||||||
//
|
|
||||||
// - shift left by CalcExp = XExp - Largest bias + new bias
|
|
||||||
// | 0's | mantissa | 0's |
|
|
||||||
// | keep |
|
|
||||||
//
|
|
||||||
// - if the input is denormalized:
|
|
||||||
// | lzcIn | 0's if nessisary | << ZeroCnt+1
|
|
||||||
// - plus 1 to shift out the first 1
|
|
||||||
//
|
|
||||||
// int -> fp: | lzcIn | 0's if nessisary | << ZeroCnt+1
|
|
||||||
// - plus 1 to shift out the first 1
|
|
||||||
|
|
||||||
module normshift(
|
|
||||||
input logic [`LOGNORMSHIFTSZ-1:0] ShiftAmt, // normalization shift count
|
|
||||||
input logic [`NORMSHIFTSZ-1:0] ShiftIn, // is the sum zero
|
|
||||||
output logic [`NORMSHIFTSZ-1:0] Shifted // is the sum zero
|
|
||||||
);
|
|
||||||
assign Shifted = ShiftIn << ShiftAmt;
|
|
||||||
|
|
||||||
endmodule
|
|
@ -30,16 +30,16 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module cvtshiftcalc(
|
module cvtshiftcalc(
|
||||||
input logic XZero,
|
input logic XZero, // is the input zero?
|
||||||
input logic ToInt,
|
input logic ToInt, // to integer conversion?
|
||||||
input logic IntToFp,
|
input logic IntToFp, // interger to floating point conversion?
|
||||||
input logic [`NE:0] CvtCe, // the calculated expoent
|
input logic [`NE:0] CvtCe, // the calculated expoent
|
||||||
input logic [`NF:0] Xm, // input mantissas
|
input logic [`NF:0] Xm, // input mantissas
|
||||||
input logic [`FMTBITS-1:0] OutFmt, // output format
|
input logic [`FMTBITS-1:0] OutFmt, // output format
|
||||||
input logic [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (priority encoder)
|
input logic [`CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (priority encoder)
|
||||||
input logic CvtResDenormUf,
|
input logic CvtResDenormUf, // is the conversion result subnormal or underlows
|
||||||
output logic CvtResUf,
|
output logic CvtResUf, // does the cvt result unerflow
|
||||||
output logic [`CVTLEN+`NF:0] CvtShiftIn // number to be shifted
|
output logic [`CVTLEN+`NF:0] CvtShiftIn // number to be shifted
|
||||||
);
|
);
|
||||||
logic [$clog2(`NF):0] ResNegNF; // the result's fraction length negated (-NF)
|
logic [$clog2(`NF):0] ResNegNF; // the result's fraction length negated (-NF)
|
||||||
|
|
||||||
@ -51,6 +51,7 @@ module cvtshiftcalc(
|
|||||||
// seclect the input to the shifter
|
// seclect the input to the shifter
|
||||||
// fp -> int:
|
// fp -> int:
|
||||||
// | `XLEN zeros | Mantissa | 0's if nessisary |
|
// | `XLEN zeros | Mantissa | 0's if nessisary |
|
||||||
|
// .
|
||||||
// Other problems:
|
// Other problems:
|
||||||
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding)
|
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding)
|
||||||
// - we do however want to keep the one in the sticky bit so set one of bits in the sticky bit area to 1
|
// - we do however want to keep the one in the sticky bit so set one of bits in the sticky bit area to 1
|
||||||
@ -58,11 +59,14 @@ module cvtshiftcalc(
|
|||||||
// ??? -> fp:
|
// ??? -> fp:
|
||||||
// - if result is denormalized or underflowed then we want to shift right i.e. shift right then shift left:
|
// - if result is denormalized or underflowed then we want to shift right i.e. shift right then shift left:
|
||||||
// | `NF-1 zeros | Mantissa | 0's if nessisary |
|
// | `NF-1 zeros | Mantissa | 0's if nessisary |
|
||||||
|
// .
|
||||||
// - otherwise:
|
// - otherwise:
|
||||||
// | LzcInM | 0's if nessisary |
|
// | LzcInM | 0's if nessisary |
|
||||||
|
// .
|
||||||
// change to int shift to the left one
|
// change to int shift to the left one
|
||||||
|
|
||||||
always_comb
|
always_comb // get rid of round bit if needed
|
||||||
|
// | add sticky bit if needed
|
||||||
if (ToInt) CvtShiftIn = {{`XLEN{1'b0}}, Xm[`NF]&~CvtCe[`NE], Xm[`NF-1]|(CvtCe[`NE]&Xm[`NF]), Xm[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}};
|
if (ToInt) CvtShiftIn = {{`XLEN{1'b0}}, Xm[`NF]&~CvtCe[`NE], Xm[`NF-1]|(CvtCe[`NE]&Xm[`NF]), Xm[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}};
|
||||||
else if (CvtResDenormUf) CvtShiftIn = {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}};
|
else if (CvtResDenormUf) CvtShiftIn = {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}};
|
||||||
else CvtShiftIn = {CvtLzcIn, {`NF+1{1'b0}}};
|
else CvtShiftIn = {CvtLzcIn, {`NF+1{1'b0}}};
|
||||||
|
@ -241,6 +241,7 @@ module unpackinput (
|
|||||||
// also need to take into account possible zero/denorm/inf/NaN values
|
// also need to take into account possible zero/denorm/inf/NaN values
|
||||||
|
|
||||||
// convert the double precsion exponent into quad precsion
|
// convert the double precsion exponent into quad precsion
|
||||||
|
// 1 is added to the exponent if the input is zero or subnormal
|
||||||
always_comb
|
always_comb
|
||||||
case (Fmt)
|
case (Fmt)
|
||||||
2'b11: Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|~ExpNonZero};
|
2'b11: Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|~ExpNonZero};
|
||||||
|
@ -700,7 +700,7 @@ module testbenchfp;
|
|||||||
.XZero(XZero), .YZero(YZero), .ZZero(ZZero), .CvtShiftAmt(CvtShiftAmtE),
|
.XZero(XZero), .YZero(YZero), .ZZero(ZZero), .CvtShiftAmt(CvtShiftAmtE),
|
||||||
.XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal),
|
.XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal),
|
||||||
.XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero,
|
.XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero,
|
||||||
.FmaZmS(ASticky), .FmaSe(Se),
|
.FmaASticky(ASticky), .FmaSe(Se),
|
||||||
.FmaSm(Sm), .FmaSCnt(SCnt), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal),
|
.FmaSm(Sm), .FmaSCnt(SCnt), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal),
|
||||||
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user