2022-06-13 22:47:51 +00:00
///////////////////////////////////////////
//
2022-07-07 23:01:33 +00:00
// Written: me@KatherineParry.com
// Modified: 7/5/2022
2022-06-13 22:47:51 +00:00
//
2022-07-07 23:01:33 +00:00
// Purpose: Post-Processing
2022-06-13 22:47:51 +00:00
//
// 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 "
2022-07-13 01:32:17 +00:00
module postprocess (
2022-07-01 21:55:46 +00:00
// general signals
2022-07-07 23:01:33 +00:00
input logic Xs , Ys , // input signs
input logic [ `NE - 1 : 0 ] Ze , // input exponents
input logic [ `NF : 0 ] Xm , Ym , Zm , // input mantissas
input logic [ 2 : 0 ] Frm , // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
input logic [ `FMTBITS - 1 : 0 ] Fmt , // precision 1 = double 0 = single
2022-07-20 02:27:39 +00:00
input logic [ 2 : 0 ] OpCtrl , // choose which opperation (look below for values)
2022-07-07 23:01:33 +00:00
input logic XZero , YZero , ZZero , // inputs are zero
2022-07-08 19:30:43 +00:00
input logic XInf , YInf , ZInf , // inputs are infinity
input logic XNaN , YNaN , ZNaN , // inputs are NaN
input logic XSNaN , YSNaN , ZSNaN , // inputs are signaling NaNs
input logic ZDenorm , // is the original precision denormalized
input logic [ 1 : 0 ] PostProcSel , // select result to be written to fp register
2022-07-01 21:55:46 +00:00
//fma signals
2022-07-08 19:30:43 +00:00
input logic FmaAs , // the modified Z sign - depends on instruction
input logic FmaPs , // the product's sign
2022-07-19 01:10:10 +00:00
input logic [ `NE + 1 : 0 ] FmaSe ,
2022-07-08 19:30:43 +00:00
input logic [ `NE + 1 : 0 ] FmaPe , // Product exponent
input logic [ 3 * `NF + 5 : 0 ] FmaSm , // the positive sum
2022-07-18 17:31:17 +00:00
input logic FmaZmS , // sticky bit that is calculated during alignment
2022-07-08 19:30:43 +00:00
input logic FmaKillProd , // set the product to zero before addition if the product is too small to matter
input logic FmaNegSum , // was the sum negitive
input logic FmaInvA , // do you invert Z
2022-07-18 20:48:56 +00:00
input logic FmaSs ,
2022-07-20 02:27:39 +00:00
input logic [ $clog2 ( 3 * `NF + 7 ) - 1 : 0 ] FmaSCnt , // the normalization shift count
2022-07-01 21:55:46 +00:00
//divide signals
2022-07-12 01:30:21 +00:00
input logic [ `DURLEN - 1 : 0 ] DivEarlyTermShift ,
2022-07-18 17:31:17 +00:00
input logic DivS ,
2022-07-07 23:01:33 +00:00
input logic DivDone ,
2022-07-18 17:31:17 +00:00
input logic [ `NE + 1 : 0 ] DivQe ,
2022-07-22 22:02:04 +00:00
input logic [ `DIVb - ( `RADIX / 4 ) : 0 ] DivQm ,
2022-07-01 21:55:46 +00:00
// conversion signals
2022-07-08 19:30:43 +00:00
input logic CvtCs , // the result's sign
input logic [ `NE : 0 ] CvtCe , // the calculated expoent
input logic CvtResDenormUf ,
input logic [ `LOGCVTLEN - 1 : 0 ] CvtShiftAmt , // how much to shift by
input logic ToInt , // is fp->int (since it's writting to the integer register)
input logic [ `CVTLEN - 1 : 0 ] CvtLzcIn , // input to the Leading Zero Counter (priority encoder)
input logic IntZero , // is the input zero
2022-07-01 21:55:46 +00:00
// final results
2022-07-12 01:30:21 +00:00
output logic [ `FLEN - 1 : 0 ] PostProcRes , // FMA final result
2022-07-08 19:30:43 +00:00
output logic [ 4 : 0 ] PostProcFlg ,
output logic [ `XLEN - 1 : 0 ] FCvtIntRes // the int conversion result
2022-06-13 22:47:51 +00:00
) ;
2022-07-01 21:55:46 +00:00
// general signals
2022-07-08 19:30:43 +00:00
logic Ws ;
logic [ `NF - 1 : 0 ] Rf ; // Result fraction
logic [ `NE - 1 : 0 ] Re ; // Result exponent
2022-07-18 17:31:17 +00:00
logic Ms ;
logic [ `NE + 1 : 0 ] Me ;
logic [ `CORRSHIFTSZ - 1 : 0 ] Mf ; // corectly shifted fraction
2022-07-12 01:30:21 +00:00
logic [ `NE + 1 : 0 ] FullRe ; // Re with bits to determine sign and overflow
2022-07-01 21:55:46 +00:00
logic UfPlus1 ; // do you add one (for determining underflow flag)
logic [ $clog2 ( `NORMSHIFTSZ ) - 1 : 0 ] ShiftAmt ; // normalization shift count
logic [ `NORMSHIFTSZ - 1 : 0 ] ShiftIn ; // is the sum zero
logic [ `NORMSHIFTSZ - 1 : 0 ] Shifted ; // the shifted result
logic Plus1 ; // add one to the final result?
logic IntInvalid , Overflow , Invalid ; // flags
2022-08-23 16:36:20 +00:00
logic G , R , S ; // bits needed to determine rounding
2022-07-01 21:55:46 +00:00
logic [ `FMTBITS - 1 : 0 ] OutFmt ;
// fma signals
2022-07-19 01:10:10 +00:00
logic [ `NE + 1 : 0 ] FmaMe ; // exponent of the normalized sum
2022-07-12 01:30:21 +00:00
logic FmaSZero ; // is the sum zero
2022-08-03 22:16:51 +00:00
logic [ 3 * `NF + 7 : 0 ] FmaShiftIn ; // shift input
2022-07-19 01:10:10 +00:00
logic [ `NE + 1 : 0 ] NormSumExp ; // exponent of the normalized sum not taking into account denormal or zero results
2022-07-08 19:30:43 +00:00
logic FmaPreResultDenorm ; // is the result denormalized - calculated before LZA corection
2022-07-01 21:55:46 +00:00
logic [ $clog2 ( 3 * `NF + 7 ) - 1 : 0 ] FmaShiftAmt ; // normalization shift count
// division singals
logic [ $clog2 ( `NORMSHIFTSZ ) - 1 : 0 ] DivShiftAmt ;
logic [ `NORMSHIFTSZ - 1 : 0 ] DivShiftIn ;
2022-07-18 17:31:17 +00:00
logic [ `NE + 1 : 0 ] Qe ;
2022-07-01 21:55:46 +00:00
logic DivByZero ;
logic DivResDenorm ;
logic [ `NE + 1 : 0 ] DivDenormShift ;
// conversion signals
logic [ `CVTLEN + `NF : 0 ] CvtShiftIn ; // number to be shifted
2022-07-08 19:30:43 +00:00
logic [ 1 : 0 ] CvtNegResMsbs ;
logic [ `XLEN + 1 : 0 ] CvtNegRes ;
2022-07-01 21:55:46 +00:00
logic CvtResUf ;
// readability signals
logic Mult ; // multiply opperation
logic Int64 ; // is the integer 64 bits?
logic Signed ; // is the opperation with a signed integer?
logic IntToFp ; // is the opperation an int->fp conversion?
2022-06-13 22:47:51 +00:00
logic CvtOp ;
logic FmaOp ;
logic DivOp ;
logic InfIn ;
logic NaNIn ;
logic Sqrt ;
// signals to help readability
2022-07-20 02:27:39 +00:00
assign Signed = OpCtrl [ 0 ] ;
assign Int64 = OpCtrl [ 1 ] ;
assign IntToFp = OpCtrl [ 2 ] ;
assign Mult = OpCtrl [ 2 ] & ~ OpCtrl [ 1 ] & ~ OpCtrl [ 0 ] ;
2022-07-08 19:30:43 +00:00
assign CvtOp = ( PostProcSel = = 2 'b00 ) ;
assign FmaOp = ( PostProcSel = = 2 'b10 ) ;
assign DivOp = ( PostProcSel = = 2 'b01 ) & DivDone ;
2022-07-20 02:27:39 +00:00
assign Sqrt = OpCtrl [ 0 ] ;
2022-06-13 22:47:51 +00:00
// is there an input of infinity or NaN being used
2022-07-21 01:20:06 +00:00
assign InfIn = XInf | YInf | ZInf ;
assign NaNIn = XNaN | YNaN | ZNaN ;
2022-06-13 22:47:51 +00:00
// choose the ouptut format depending on the opperation
// - fp -> fp: OpCtrl contains the percision of the output
2022-07-07 23:01:33 +00:00
// - otherwise: Fmt contains the percision of the output
2022-06-13 22:47:51 +00:00
if ( `FPSIZES = = 2 )
2022-07-20 02:27:39 +00:00
assign OutFmt = IntToFp | ~ CvtOp ? Fmt : ( OpCtrl [ 1 : 0 ] = = `FMT ) ;
2022-06-13 22:47:51 +00:00
else if ( `FPSIZES = = 3 | `FPSIZES = = 4 )
2022-07-20 02:27:39 +00:00
assign OutFmt = IntToFp | ~ CvtOp ? Fmt : OpCtrl [ 1 : 0 ] ;
2022-06-13 22:47:51 +00:00
///////////////////////////////////////////////////////////////////////////////
// Normalization
///////////////////////////////////////////////////////////////////////////////
2022-07-08 19:30:43 +00:00
cvtshiftcalc cvtshiftcalc ( . ToInt , . CvtCe , . CvtResDenormUf , . Xm , . CvtLzcIn ,
2022-07-07 23:01:33 +00:00
. XZero , . IntToFp , . OutFmt , . CvtResUf , . CvtShiftIn ) ;
2022-07-20 02:27:39 +00:00
fmashiftcalc fmashiftcalc ( . FmaSm , . Ze , . FmaPe , . FmaSCnt , . Fmt , . FmaKillProd , . NormSumExp , . FmaSe ,
2022-07-13 22:01:38 +00:00
. FmaSZero , . FmaPreResultDenorm , . FmaShiftAmt , . FmaShiftIn ) ;
2022-07-22 22:02:04 +00:00
divshiftcalc divshiftcalc ( . Fmt , . Sqrt , . DivQe , . DivQm , . DivEarlyTermShift , . DivResDenorm , . DivDenormShift , . DivShiftAmt , . DivShiftIn ) ;
2022-06-13 22:47:51 +00:00
always_comb
2022-07-08 19:30:43 +00:00
case ( PostProcSel )
2022-06-13 22:47:51 +00:00
2 'b10 : begin // fma
ShiftAmt = { { $clog2 ( `NORMSHIFTSZ ) - $clog2 ( 3 * `NF + 7 ) { 1 'b0 } } , FmaShiftAmt } ;
2022-08-03 22:16:51 +00:00
ShiftIn = { FmaShiftIn , { `NORMSHIFTSZ - ( 3 * `NF + 8 ) { 1 'b0 } } } ;
2022-06-13 22:47:51 +00:00
end
2 'b00 : begin // cvt
2022-07-08 19:30:43 +00:00
ShiftAmt = { { $clog2 ( `NORMSHIFTSZ ) - $clog2 ( `CVTLEN + 1 ) { 1 'b0 } } , CvtShiftAmt } ;
2022-06-23 00:07:34 +00:00
ShiftIn = { CvtShiftIn , { `NORMSHIFTSZ - `CVTLEN - `NF - 1 { 1 'b0 } } } ;
2022-06-13 22:47:51 +00:00
end
2022-07-03 19:26:22 +00:00
2 'b01 : begin //div
2022-07-07 23:01:33 +00:00
if ( DivDone ) begin
ShiftAmt = DivShiftAmt ;
ShiftIn = DivShiftIn ;
end else begin
ShiftAmt = '0 ;
ShiftIn = '0 ;
end
2022-06-13 22:47:51 +00:00
end
default : begin
2022-06-14 23:58:39 +00:00
ShiftAmt = { $clog2 ( `NORMSHIFTSZ ) { 1 ' bx } } ;
ShiftIn = { `NORMSHIFTSZ { 1 ' bx } } ;
2022-06-13 22:47:51 +00:00
end
endcase
normshift normshift ( . ShiftIn , . ShiftAmt , . Shifted ) ;
2022-07-19 01:10:10 +00:00
shiftcorrection shiftcorrection ( . FmaOp , . FmaPreResultDenorm , . NormSumExp ,
2022-07-18 17:31:17 +00:00
. DivResDenorm , . DivDenormShift , . DivOp , . DivQe ,
2022-07-19 01:10:10 +00:00
. Qe , . FmaSZero , . Shifted , . FmaMe , . Mf ) ;
2022-06-13 22:47:51 +00:00
///////////////////////////////////////////////////////////////////////////////
// Rounding
///////////////////////////////////////////////////////////////////////////////
// round to nearest even
// round to zero
// round to -infinity
// round to infinity
// round to nearest max magnitude
2022-07-07 23:01:33 +00:00
2022-07-08 19:30:43 +00:00
roundsign roundsign ( . FmaPs , . FmaAs , . FmaInvA , . FmaOp , . DivOp , . CvtOp , . FmaNegSum ,
2022-07-22 22:02:04 +00:00
. Sqrt , . FmaSs , . Xs , . Ys , . CvtCs , . Ms ) ;
2022-07-07 23:01:33 +00:00
2022-08-23 16:36:20 +00:00
round round ( . OutFmt , . Frm , . FmaZmS , . Plus1 , . PostProcSel , . CvtCe , . Qe ,
2022-07-19 01:10:10 +00:00
. Ms , . FmaMe , . FmaOp , . CvtOp , . CvtResDenormUf , . Mf , . ToInt , . CvtResUf ,
2022-07-18 17:31:17 +00:00
. DivS , . DivDone ,
2022-08-23 16:36:20 +00:00
. DivOp , . UfPlus1 , . FullRe , . Rf , . Re , . S , . R , . G , . Me ) ;
2022-06-13 22:47:51 +00:00
///////////////////////////////////////////////////////////////////////////////
// Sign calculation
///////////////////////////////////////////////////////////////////////////////
2022-08-23 16:36:20 +00:00
resultsign resultsign ( . Frm , . FmaPs , . FmaAs , . FmaMe , . R , . S , . G ,
2022-07-18 17:31:17 +00:00
. FmaOp , . ZInf , . InfIn , . FmaSZero , . Mult , . Ms , . Ws ) ;
2022-06-13 22:47:51 +00:00
///////////////////////////////////////////////////////////////////////////////
// Flags
///////////////////////////////////////////////////////////////////////////////
2022-07-08 19:30:43 +00:00
flags flags ( . XSNaN , . YSNaN , . ZSNaN , . XInf , . YInf , . ZInf , . InfIn , . XZero , . YZero ,
. Xs , . Sqrt , . ToInt , . IntToFp , . Int64 , . Signed , . OutFmt , . CvtCe ,
2022-07-21 01:20:06 +00:00
. NaNIn , . FmaAs , . FmaPs , . R , . IntInvalid , . DivByZero ,
2022-08-23 16:36:20 +00:00
. G , . S , . UfPlus1 , . CvtOp , . DivOp , . FmaOp , . FullRe , . Plus1 ,
2022-07-18 17:31:17 +00:00
. Me , . CvtNegResMsbs , . Invalid , . Overflow , . PostProcFlg ) ;
2022-06-13 22:47:51 +00:00
///////////////////////////////////////////////////////////////////////////////
// Select the result
///////////////////////////////////////////////////////////////////////////////
2022-07-08 19:30:43 +00:00
negateintres negateintres ( . Xs , . Shifted , . Signed , . Int64 , . Plus1 , . CvtNegResMsbs , . CvtNegRes ) ;
2022-07-12 01:30:21 +00:00
specialcase specialcase ( . Xs , . Xm , . Ym , . Zm , . XZero , . IntInvalid ,
2022-07-08 19:30:43 +00:00
. IntZero , . Frm , . OutFmt , . XNaN , . YNaN , . ZNaN , . CvtResUf ,
. NaNIn , . IntToFp , . Int64 , . Signed , . CvtOp , . FmaOp , . Plus1 , . Invalid , . Overflow , . InfIn , . CvtNegRes ,
. XInf , . YInf , . DivOp ,
2022-07-12 01:30:21 +00:00
. DivByZero , . FullRe , . CvtCe , . Ws , . Re , . Rf , . PostProcRes , . FCvtIntRes ) ;
2022-06-13 22:47:51 +00:00
endmodule