Merge branch 'main' of github.com:openhwgroup/cvw

This commit is contained in:
Jacob Pease 2023-08-01 10:47:59 -05:00
commit 19287defe5
30 changed files with 467 additions and 474 deletions

View File

@ -159,4 +159,4 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -172,4 +172,4 @@ localparam ZBS_SUPPORTED = 1;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -160,5 +160,5 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -161,4 +161,4 @@ localparam ZBS_SUPPORTED = 1;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -160,4 +160,4 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -159,4 +159,4 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -162,4 +162,4 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -165,4 +165,4 @@ localparam ZBS_SUPPORTED = 1;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -162,4 +162,4 @@ localparam ZBS_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;
`include "test-shared.vh"
`include "config-shared.vh"

View File

@ -112,8 +112,6 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
assign Xfract = (IFX << ell) << 1;
assign Dfract = (IFD << mE) << 1;
// *** CT: move to fdivsqrtintpreshift
//////////////////////////////////////////////////////
// Integer Right Shift to digit boundary
// Determine DivXShifted (X shifted to digit boundary)
@ -141,8 +139,8 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
assign IntTrunc = TotalIntBits % P.RK; // Truncation check for ceiling operator
assign IntSteps = (TotalIntBits >> P.LOGRK) + |IntTrunc; // Number of steps for int div
assign nE = (IntSteps * P.DIVCOPIES) - 1; // Fractional digits
assign RightShiftX = P.RK - 1 - ((TotalIntBits - 1) % P.RK); // Right shift amount
assign DivXShifted = DivX >> RightShiftX; // shift X by up to R*K-1 to complete in nE steps
assign RightShiftX = P.RK - 1 - ((TotalIntBits - 1) % P.RK); // Right shift amount
assign DivXShifted = DivX >> RightShiftX; // shift X by up to R*K-1 to complete in nE steps
/* verilator lint_on WIDTH */
end else begin // radix 2 1 copy doesn't require shifting
assign nE = p;
@ -152,14 +150,14 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
assign ISpecialCaseE = 0;
end
// CT *** fdivsqrtfplead1
//////////////////////////////////////////////////////
// Floating-Point Preprocessing
// append leading 1 (for nonzero inputs)
// shift square root to be in range [1/4, 1)
// Normalized numbers are shifted right by 1 if the exponent is odd
// Denormalized numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd.
// Subnormal numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd.
// NOTE: there might be a discrepancy that X is never right shifted by 2. However
// it comes out in the wash and gives the right answer. Investigate later if possible.
//////////////////////////////////////////////////////
assign DivX = {3'b000, ~NumerZeroE, Xfract};

View File

@ -27,17 +27,17 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module fma import cvw::*; #(parameter cvw_t P) (
input logic Xs, Ys, Zs, // input's signs
input logic Xs, Ys, Zs, // input's signs
input logic [P.NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format
input logic [P.NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format
input logic XZero, YZero, ZZero, // is the input zero
input logic [2:0] OpCtrl, // operation control
output logic ASticky, // sticky bit that is calculated during alignment
input logic XZero, YZero, ZZero, // is the input zero
input logic [2:0] OpCtrl, // operation control
output logic ASticky, // sticky bit that is calculated during alignment
output logic [3*P.NF+3:0] Sm, // the positive sum's significand
output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A)
output logic As, // the aligned addend's sign (modified Z sign for other opperations)
output logic Ps, // the product's sign
output logic Ss, // the sum's sign
output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A)
output logic As, // the aligned addend's sign (modified Z sign for other opperations)
output logic Ps, // the product's sign
output logic Ss, // the sum's sign
output logic [P.NE+1:0] Se, // the sum's exponent
output logic [$clog2(3*P.NF+5)-1:0] SCnt // normalization shift count
);
@ -56,7 +56,7 @@ module fma import cvw::*; #(parameter cvw_t P) (
logic [3*P.NF+3:0] Am; // addend aligned's mantissa for addition in U(NF+4.2NF)
logic [3*P.NF+3:0] AmInv; // aligned addend's mantissa possibly inverted
logic [2*P.NF+1:0] PmKilled; // the product's mantissa possibly killed U(2.2Nf)
logic KillProd; // set the product to zero before addition if the product is too small to matter
logic KillProd; // set the product to zero before addition if the product is too small to matter
logic [P.NE+1:0] Pe; // the product's exponent B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign
///////////////////////////////////////////////////////////////////////////////
@ -67,7 +67,6 @@ module fma import cvw::*; #(parameter cvw_t P) (
// - Multiply the mantissas
///////////////////////////////////////////////////////////////////////////////
// calculate the product's exponent
fmaexpadd #(P) expadd(.Xe, .Ye, .XZero, .YZero, .Pe);
@ -80,6 +79,7 @@ module fma import cvw::*; #(parameter cvw_t P) (
///////////////////////////////////////////////////////////////////////////////
// Alignment shifter
///////////////////////////////////////////////////////////////////////////////
fmaalign #(P) align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd);
// ///////////////////////////////////////////////////////////////////////////////
@ -91,5 +91,3 @@ module fma import cvw::*; #(parameter cvw_t P) (
fmalza #(3*P.NF+4, P.NF) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt);
endmodule

View File

@ -29,21 +29,21 @@
module fmaadd import cvw::*; #(parameter cvw_t P) (
input logic [3*P.NF+3:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1)
input logic [P.NE-1:0] Ze, // exponent of Z
input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations)
input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations)
input logic [P.NE+1:0] Pe, // product's exponet
input logic [2*P.NF+1:0] Pm, // the product's mantissa
input logic InvA, // invert the aligned addend
input logic KillProd, // should the product be set to 0
input logic ASticky, // Alighed addend's sticky bit
input logic InvA, // invert the aligned addend
input logic KillProd, // should the product be set to 0
input logic ASticky, // Alighed addend's sticky bit
output logic [3*P.NF+3:0] AmInv, // aligned addend possibly inverted
output logic [2*P.NF+1:0] PmKilled, // the product's mantissa possibly killed
output logic Ss, // sum's sign
output logic Ss, // sum's sign
output logic [P.NE+1:0] Se, // sum's exponent
output logic [3*P.NF+3:0] Sm // the positive sum
);
logic [3*P.NF+3:0] PreSum, NegPreSum; // possibly negitive sum
logic NegSum; // was the sum negitive
logic NegSum; // was the sum negitive
///////////////////////////////////////////////////////////////////////////////
// Addition

View File

@ -1,4 +1,3 @@
///////////////////////////////////////////
// fmaalign.sv
//
@ -28,18 +27,18 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module fmaalign import cvw::*; #(parameter cvw_t P) (
input logic [P.NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
input logic [P.NF:0] Zm, // significand in U(0.NF) format]
input logic XZero, YZero, ZZero,// is the input zero
output logic [3*P.NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1)
output logic ASticky, // Sticky bit calculated from the aliged addend
output logic KillProd // should the product be set to zero
input logic [P.NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
input logic [P.NF:0] Zm, // significand in U(0.NF) format]
input logic XZero, YZero, ZZero, // is the input zero
output logic [3*P.NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1)
output logic ASticky, // Sticky bit calculated from the aliged addend
output logic KillProd // should the product be set to zero
);
logic [P.NE+1:0] ACnt; // how far to shift the addend to align with the product in Q(NE+2.0) format
logic [4*P.NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1)
logic [4*P.NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1)
logic KillZ; // should the addend be killed
logic [P.NE+1:0] ACnt; // how far to shift the addend to align with the product in Q(NE+2.0) format
logic [4*P.NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1)
logic [4*P.NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1)
logic KillZ; // should the addend be killed
///////////////////////////////////////////////////////////////////////////////
// Alignment shifter
@ -51,45 +50,41 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
// This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed
assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)} + (P.NE+2)'(P.NF+2) - {2'b0, Ze};
// Defualt Addition with only inital left shift
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
// Default Addition with only inital left shift
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
assign ZmPreshifted = {Zm,(3*P.NF+3)'(0)};
assign KillProd = (ACnt[P.NE+1]&~ZZero)|XZero|YZero;
assign KillZ = $signed(ACnt)>$signed((P.NE+2)'(3)*(P.NE+2)'(P.NF)+(P.NE+2)'(3));
assign KillProd = (ACnt[P.NE+1]&~ZZero)|XZero|YZero;
assign KillZ = $signed(ACnt)>$signed((P.NE+2)'(3)*(P.NE+2)'(P.NF)+(P.NE+2)'(3));
always_comb begin
// If the product is too small to effect the sum, kill the product
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
if (KillProd) begin
ZmShifted = {(P.NF+2)'(0), Zm, (2*P.NF+1)'(0)};
ASticky = ~(XZero|YZero);
ASticky = ~(XZero|YZero);
// If the addend is too small to effect the addition
// - The addend has to shift two past the end of the product to be considered too small
// - The 2 extra bits are needed for rounding
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
end else if (KillZ) begin
ZmShifted = 0;
ASticky = ~ZZero;
ASticky = ~ZZero;
// If the Addend is shifted right
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
// | 53'b0 | 106'b(product) | 1'b0 |
// | addnend |
end else begin
ZmShifted = ZmPreshifted >> ACnt;
ASticky = |(ZmShifted[P.NF-1:0]);
ASticky = |(ZmShifted[P.NF-1:0]);
end
end
assign Am = ZmShifted[4*P.NF+3:P.NF];
endmodule

View File

@ -28,14 +28,14 @@
module fmaexpadd import cvw::*; #(parameter cvw_t P) (
input logic [P.NE-1:0] Xe, Ye, // input's exponents
input logic XZero, YZero, // are the inputs zero
input logic XZero, YZero, // are the inputs zero
output logic [P.NE+1:0] Pe // product's exponent B^(1023)NE+2
);
logic PZero; // is the product zero?
logic PZero; // is the product zero?
// kill the exponent if the product is zero - either X or Y is 0
assign PZero = XZero | YZero;
assign Pe = PZero ? '0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)});
assign Pe = PZero ? '0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)});
endmodule

View File

@ -28,11 +28,11 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module fmalza #(WIDTH, NF) (
input logic [WIDTH-1:0] A, // addend
input logic [2*NF+1:0] Pm, // product
input logic Cin, // carry in
input logic sub, // subtraction
output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result
input logic [WIDTH-1:0] A, // addend
input logic [2*NF+1:0] Pm, // product
input logic Cin, // carry in
input logic sub, // subtraction
output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result
);
logic [WIDTH:0] F; // most significant bit of F indicates leading digit
@ -40,19 +40,19 @@ module fmalza #(WIDTH, NF) (
logic [WIDTH-1:0] P, G, K; // propagate, generate, kill for each column
logic [WIDTH-1:0] Pp1, Gm1, Km1; // propagate shifted right by 1, generate/kill shifted left 1
assign B = {{(NF+1){1'b0}}, Pm, 1'b0}; // Zero extend product
assign B = {{(NF+1){1'b0}}, Pm, 1'b0}; // Zero extend product
assign P = A^B;
assign G = A&B;
assign K= ~A&~B;
assign K = ~A&~B;
assign Pp1 = {sub, P[WIDTH-1:1]}; // shift P right by 1 (for P_i+1) , use subtract flag in most significant bit
assign Gm1 = {G[WIDTH-2:0], Cin}; // shift G left by 1 (for G_i-1) and bring in Cin
assign Km1 = {K[WIDTH-2:0], ~Cin}; // shift K left by 1 (for K_i-1) and bring in Cin
assign Pp1 = {sub, P[WIDTH-1:1]}; // shift P right by 1 (for P_i+1) , use subtract flag in most significant bit
assign Gm1 = {G[WIDTH-2:0], Cin}; // shift G left by 1 (for G_i-1) and bring in Cin
assign Km1 = {K[WIDTH-2:0], ~Cin}; // shift K left by 1 (for K_i-1) and bring in Cin
// Apply function to determine Leading pattern
// - note: Schmookler01 uses the numbering system where 0 is the most significant bit
assign F[WIDTH] = ~sub&P[WIDTH-1];
assign F[WIDTH] = ~sub&P[WIDTH-1];
assign F[WIDTH-1:0] = (Pp1&(G&~Km1 | K&~Gm1)) | (~Pp1&(K&~Km1 | G&~Gm1));
lzc #(WIDTH+1) lzc (.num(F), .ZeroCnt(SCnt));

View File

@ -33,4 +33,3 @@ module fmamult import cvw::*; #(parameter cvw_t P) (
assign Pm = Xm * Ym;
endmodule

View File

@ -34,7 +34,7 @@ module fmasign(
output logic InvA // Effective subtraction: invert addend
);
assign Ps = Xs ^ Ys ^ (OpCtrl[1]&~OpCtrl[2]); // product sign. Negate for FMNADD or FNMSUB
assign As = Zs^OpCtrl[0]; // flip addend sign for subtraction
assign InvA = As ^ Ps; // Effective subtraction when product and addend have opposite signs
assign Ps = Xs ^ Ys ^ (OpCtrl[1]&~OpCtrl[2]); // product sign. Negate for FMNADD or FNMSUB
assign As = Zs^OpCtrl[0]; // flip addend sign for subtraction
assign InvA = As ^ Ps; // Effective subtraction when product and addend have opposite signs
endmodule

View File

@ -27,16 +27,16 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
input logic XZero, // is the input zero?
input logic ToInt, // to integer conversion?
input logic IntToFp, // interger to floating point conversion?
input logic XZero, // is the input zero?
input logic ToInt, // to integer conversion?
input logic IntToFp, // interger to floating point conversion?
input logic [P.FMTBITS-1:0] OutFmt, // output format
input logic [P.NE:0] CvtCe, // the calculated expoent
input logic [P.NF:0] Xm, // input mantissas
input logic [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
input logic CvtResSubnormUf, // is the conversion result subnormal or underlows
output logic CvtResUf, // does the cvt result unerflow
output logic [P.CVTLEN+P.NF:0] CvtShiftIn // number to be shifted
input logic CvtResSubnormUf, // is the conversion result subnormal or underlows
output logic CvtResUf, // does the cvt result unerflow
output logic [P.CVTLEN+P.NF:0] CvtShiftIn // number to be shifted
);
logic [$clog2(P.NF):0] ResNegNF; // the result's fraction length negated (-NF)
@ -47,7 +47,7 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
// seclect the input to the shifter
// fp -> int:
// | P.XLEN zeros | mantissa | 0's if nessisary |
// | P.XLEN zeros | mantissa | 0's if necessary |
// .
// 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)
@ -58,16 +58,16 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
// | P.NF-1 zeros | mantissa | 0's if nessisary |
// .
// - otherwise:
// | LzcInM | 0's if nessisary |
// | LzcInM | 0's if necessary |
// .
// change to int shift to the left one
always_comb
// get rid of round bit if needed
// | add sticky bit if needed
// | |
if (ToInt) CvtShiftIn = {{P.XLEN{1'b0}}, Xm[P.NF]&~CvtCe[P.NE], Xm[P.NF-1]|(CvtCe[P.NE]&Xm[P.NF]), Xm[P.NF-2:0], {P.CVTLEN-P.XLEN{1'b0}}};
if (ToInt) CvtShiftIn = {{P.XLEN{1'b0}}, Xm[P.NF]&~CvtCe[P.NE], Xm[P.NF-1]|(CvtCe[P.NE]&Xm[P.NF]), Xm[P.NF-2:0], {P.CVTLEN-P.XLEN{1'b0}}};
else if (CvtResSubnormUf) CvtShiftIn = {{P.NF-1{1'b0}}, Xm, {P.CVTLEN-P.NF+1{1'b0}}};
else CvtShiftIn = {CvtLzcIn, {P.NF+1{1'b0}}};
else CvtShiftIn = {CvtLzcIn, {P.NF+1{1'b0}}};
// choose the negative of the fraction size
if (P.FPSIZES == 1) begin
@ -79,9 +79,9 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 3) begin
always_comb
case (OutFmt)
P.FMT: ResNegNF = -($clog2(P.NF)+1)'(P.NF);
P.FMT1: ResNegNF = -($clog2(P.NF)+1)'(P.NF1);
P.FMT2: ResNegNF = -($clog2(P.NF)+1)'(P.NF2);
P.FMT: ResNegNF = -($clog2(P.NF)+1)'(P.NF);
P.FMT1: ResNegNF = -($clog2(P.NF)+1)'(P.NF1);
P.FMT2: ResNegNF = -($clog2(P.NF)+1)'(P.NF2);
default: ResNegNF = 'x;
endcase
@ -95,8 +95,6 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
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

View File

@ -31,8 +31,8 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
input logic [P.NE+1:0] DivQe, // divsqrt exponent
output logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt, // divsqrt shift amount
output logic [P.NORMSHIFTSZ-1:0] DivShiftIn, // divsqrt shift input
output logic DivResSubnorm, // is the divsqrt result subnormal
output logic DivSubnormShiftPos // is the subnormal shift amount positive
output logic DivResSubnorm, // is the divsqrt result subnormal
output logic DivSubnormShiftPos // is the subnormal shift amount positive
);
logic [P.LOGNORMSHIFTSZ-1:0] NormShift; // normalized result shift amount
@ -46,10 +46,10 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
// if the result is subnormal
// 00000000x.xxxxxx... Exp = DivQe
// .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1
// .00xxxxxxxxxxxxx... << DivQe+NF+1 Exp = +1
// .00xxxxxxxxxxxxx... << DivQe+NF+1 Exp = +1
// .0000xxxxxxxxxxx... >> 1 Exp = 1
// Left shift amount = DivQe+NF+1-1
assign DivSubnormShift = (P.NE+2)'(P.NF)+DivQe;
// Left shift amount = DivQe+NF+1-1
assign DivSubnormShift = (P.NE+2)'(P.NF)+DivQe;
assign DivSubnormShiftPos = ~DivSubnormShift[P.NE+1];
// if the result is normalized
@ -65,7 +65,7 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
// if the shift amount is negitive then don't shift (keep sticky bit)
// need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES)
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : '0;
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
// pre-shift the divider result for normalization
assign DivShiftIn = {{P.NF{1'b0}}, DivQm, {P.NORMSHIFTSZ-P.DIVb-1-P.NF{1'b0}}};

View File

@ -27,50 +27,50 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module flags import cvw::*; #(parameter cvw_t P) (
input logic Xs, // X sign
input logic Xs, // X sign
input logic [P.FMTBITS-1:0] OutFmt, // output format
input logic InfIn, // is a Inf input being used
input logic XInf, YInf, ZInf, // inputs are infinity
input logic NaNIn, // is a NaN input being used
input logic XSNaN, YSNaN, ZSNaN, // inputs are signaling NaNs
input logic XZero, YZero, // inputs are zero
input logic InfIn, // is a Inf input being used
input logic XInf, YInf, ZInf, // inputs are infinity
input logic NaNIn, // is a NaN input being used
input logic XSNaN, YSNaN, ZSNaN, // inputs are signaling NaNs
input logic XZero, YZero, // inputs are zero
input logic [P.NE+1:0] FullRe, // Re with bits to determine sign and overflow
input logic [P.NE+1:0] Me, // exponent of the normalized sum
// rounding
input logic Plus1, // do you add one for rounding
input logic Round, Guard, Sticky, // bits used to determine rounding
input logic UfPlus1, // do you add one for rounding for the unbounded exponent result
input logic Plus1, // do you add one for rounding
input logic Round, Guard, Sticky, // bits used to determine rounding
input logic UfPlus1, // do you add one for rounding for the unbounded exponent result
// convert
input logic CvtOp, // conversion opperation?
input logic ToInt, // convert to integer
input logic IntToFp, // convert integer to floating point
input logic Int64, // convert to 64 bit integer
input logic Signed, // convert to a signed integer
input logic CvtOp, // conversion opperation?
input logic ToInt, // convert to integer
input logic IntToFp, // convert integer to floating point
input logic Int64, // convert to 64 bit integer
input logic Signed, // convert to a signed integer
input logic [P.NE:0] CvtCe, // the calculated expoent - Cvt
input logic [1:0] CvtNegResMsbs, // the negitive integer result's most significant bits
input logic [1:0] CvtNegResMsbs, // the negitive integer result's most significant bits
// divsqrt
input logic DivOp, // conversion opperation?
input logic Sqrt, // Sqrt?
input logic DivOp, // conversion opperation?
input logic Sqrt, // Sqrt?
// fma
input logic FmaOp, // Fma opperation?
input logic FmaAs, FmaPs, // the product and modified Z signs
input logic FmaOp, // Fma opperation?
input logic FmaAs, FmaPs, // the product and modified Z signs
// flags
output logic DivByZero, // divide by zero flag
output logic Overflow, // overflow flag to select result
output logic Invalid, // invalid flag to select the result
output logic IntInvalid, // invalid integer result to select
output logic [4:0] PostProcFlg // flags
output logic DivByZero, // divide by zero flag
output logic Overflow, // overflow flag to select result
output logic Invalid, // invalid flag to select the result
output logic IntInvalid, // invalid integer result to select
output logic [4:0] PostProcFlg // flags
);
logic SigNaN; // is an input a signaling NaN
logic Inexact; // final inexact flag
logic FpInexact; // floating point inexact flag
logic IntInexact; // integer inexact flag
logic FmaInvalid; // integer invalid flag
logic DivInvalid; // integer invalid flag
logic Underflow; // Underflow flag
logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent
logic ShiftGtIntSz; // is the shift greater than the the integer size (use Re to account for possible roundning "shift")
logic SigNaN; // is an input a signaling NaN
logic Inexact; // final inexact flag
logic FpInexact; // floating point inexact flag
logic IntInexact; // integer inexact flag
logic FmaInvalid; // integer invalid flag
logic DivInvalid; // integer invalid flag
logic Underflow; // Underflow flag
logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent
logic ShiftGtIntSz; // is the shift greater than the the integer size (use Re to account for possible roundning "shift")
///////////////////////////////////////////////////////////////////////////////
// Overflow
@ -86,7 +86,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
// 65 = ...0 0 0 0 0 1 0 0 0 0 0 1
// | or | | or |
// 33 = ...0 0 0 0 0 0 1 0 0 0 0 1
// | or | | or |
// | or | | or |
// larger or equal if:
// - any of the bits after the most significan 1 is one
// - the most signifcant in 65 or 33 is still a one in the number and
@ -102,9 +102,9 @@ module flags import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 3) begin
always_comb
case (OutFmt)
P.FMT: ResExpGteMax = &FullRe[P.NE-1:0] | FullRe[P.NE];
P.FMT1: ResExpGteMax = &FullRe[P.NE1-1:0] | (|FullRe[P.NE:P.NE1]);
P.FMT2: ResExpGteMax = &FullRe[P.NE2-1:0] | (|FullRe[P.NE:P.NE2]);
P.FMT: ResExpGteMax = &FullRe[P.NE-1:0] | FullRe[P.NE];
P.FMT1: ResExpGteMax = &FullRe[P.NE1-1:0] | (|FullRe[P.NE:P.NE1]);
P.FMT2: ResExpGteMax = &FullRe[P.NE2-1:0] | (|FullRe[P.NE:P.NE2]);
default: ResExpGteMax = 1'bx;
endcase
assign ShiftGtIntSz = (|FullRe[P.NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64));
@ -119,8 +119,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
endcase
assign ShiftGtIntSz = (|FullRe[P.Q_NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64));
end
// calulate overflow flag:
// if the result is greater than or equal to the max exponent(not taking into account sign)
// | and the exponent isn't negitive
@ -142,7 +141,6 @@ module flags import cvw::*; #(parameter cvw_t P) (
// | | | | | |
assign Underflow = ((FullRe[P.NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&Guard)))&(Round|Sticky|Guard))&~(InfIn|NaNIn|DivByZero|Invalid);
///////////////////////////////////////////////////////////////////////////////
// Inexact
///////////////////////////////////////////////////////////////////////////////
@ -199,7 +197,6 @@ module flags import cvw::*; #(parameter cvw_t P) (
// - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator)
assign DivByZero = YZero&DivOp&~Sqrt&~(XZero|NaNIn|InfIn);
///////////////////////////////////////////////////////////////////////////////
// final flags
///////////////////////////////////////////////////////////////////////////////
@ -209,7 +206,3 @@ module flags import cvw::*; #(parameter cvw_t P) (
assign PostProcFlg = {Invalid|(IntInvalid&CvtOp&ToInt), DivByZero, Overflow&~(ToInt&CvtOp), Underflow&~(ToInt&CvtOp), Inexact};
endmodule

View File

@ -27,18 +27,18 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
input logic [P.FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
input logic [P.NE+1:0] FmaSe, // sum's exponent
input logic [3*P.NF+3:0] FmaSm, // the positive sum
input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // normalization shift count
output logic [P.NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results
output logic FmaSZero, // is the result subnormal - calculated before LZA corection
output logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
output logic [$clog2(3*P.NF+5)-1:0] FmaShiftAmt, // normalization shift count
output logic [3*P.NF+5:0] FmaShiftIn // is the sum zero
input logic [P.FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
input logic [P.NE+1:0] FmaSe, // sum's exponent
input logic [3*P.NF+3:0] FmaSm, // the positive sum
input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // normalization shift count
output logic [P.NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results
output logic FmaSZero, // is the result subnormal - calculated before LZA corection
output logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
output logic [$clog2(3*P.NF+5)-1:0] FmaShiftAmt, // normalization shift count
output logic [3*P.NF+5:0] FmaShiftIn // is the sum zero
);
logic [P.NE+1:0] PreNormSumExp; // the exponent of the normalized sum with the P.FLEN bias
logic [P.NE+1:0] BiasCorr; // correction for bias
logic [P.NE+1:0] PreNormSumExp; // the exponent of the normalized sum with the P.FLEN bias
logic [P.NE+1:0] BiasCorr; // correction for bias
///////////////////////////////////////////////////////////////////////////////
// Normalization
@ -59,9 +59,9 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 3) begin
always_comb begin
case (Fmt)
P.FMT: BiasCorr = '0;
P.FMT1: BiasCorr = (P.NE+2)'(P.BIAS1-P.BIAS);
P.FMT2: BiasCorr = (P.NE+2)'(P.BIAS2-P.BIAS);
P.FMT: BiasCorr = '0;
P.FMT1: BiasCorr = (P.NE+2)'(P.BIAS1-P.BIAS);
P.FMT2: BiasCorr = (P.NE+2)'(P.BIAS2-P.BIAS);
default: BiasCorr = 'x;
endcase
end
@ -101,9 +101,9 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
assign Sum2GEFL = $signed(PreNormSumExp) >= $signed((P.NE+2)'(-P.NF2-2+P.BIAS-P.BIAS2)) | ~|PreNormSumExp;
always_comb begin
case (Fmt)
P.FMT: FmaPreResultSubnorm = Sum0LEZ & Sum0GEFL & ~FmaSZero;
P.FMT1: FmaPreResultSubnorm = Sum1LEZ & Sum1GEFL & ~FmaSZero;
P.FMT2: FmaPreResultSubnorm = Sum2LEZ & Sum2GEFL & ~FmaSZero;
P.FMT: FmaPreResultSubnorm = Sum0LEZ & Sum0GEFL & ~FmaSZero;
P.FMT1: FmaPreResultSubnorm = Sum1LEZ & Sum1GEFL & ~FmaSZero;
P.FMT2: FmaPreResultSubnorm = Sum2LEZ & Sum2GEFL & ~FmaSZero;
default: FmaPreResultSubnorm = 1'bx;
endcase
end
@ -131,5 +131,5 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
// - shift once if killing a product and the result is subnormal
assign FmaShiftIn = {2'b0, FmaSm};
if (P.FPSIZES == 1) assign FmaShiftAmt = FmaPreResultSubnorm ? FmaSe[$clog2(3*P.NF+5)-1:0]+($clog2(3*P.NF+5))'(P.NF+2): FmaSCnt+1;
else assign FmaShiftAmt = FmaPreResultSubnorm ? FmaSe[$clog2(3*P.NF+5)-1:0]+($clog2(3*P.NF+5))'(P.NF+2)+BiasCorr[$clog2(3*P.NF+5)-1:0]: FmaSCnt+1;
else assign FmaShiftAmt = FmaPreResultSubnorm ? FmaSe[$clog2(3*P.NF+5)-1:0]+($clog2(3*P.NF+5))'(P.NF+2)+BiasCorr[$clog2(3*P.NF+5)-1:0]: FmaSCnt+1;
endmodule

View File

@ -27,20 +27,20 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module negateintres import cvw::*; #(parameter cvw_t P) (
input logic Signed, // is the integer input signed
input logic Int64, // is the integer input 64-bits
input logic Plus1, // should one be added for rounding?
input logic Xs, // X sign
input logic Signed, // is the integer input signed
input logic Int64, // is the integer input 64-bits
input logic Plus1, // should one be added for rounding?
input logic Xs, // X sign
input logic [P.NORMSHIFTSZ-1:0] Shifted, // output from normalization shifter
output logic [1:0] CvtNegResMsbs, // most signigficant bits of possibly negated result
output logic [1:0] CvtNegResMsbs, // most signigficant bits of possibly negated result
output logic [P.XLEN+1:0] CvtNegRes // possibly negated integer result
);
logic [P.XLEN+1:0] CvtPreRes; // integer result with rounding
logic [2:0] CvtNegResMsbs3; // first three msbs of possibly negated result
logic [2:0] CvtNegResMsbs3; // first three msbs of possibly negated result
// round and negate the positive res if needed
assign CvtPreRes = {2'b0, Shifted[P.NORMSHIFTSZ-1:P.NORMSHIFTSZ-P.XLEN]}+{{P.XLEN+1{1'b0}}, Plus1};
assign CvtPreRes = {2'b0, Shifted[P.NORMSHIFTSZ-1:P.NORMSHIFTSZ-P.XLEN]}+{{P.XLEN+1{1'b0}}, Plus1};
mux2 #(P.XLEN+2) resmux(CvtPreRes, -CvtPreRes, Xs, CvtNegRes);
// select 2 most significant bits

View File

@ -27,47 +27,47 @@
////////////////////////////////////////////////////////////////////////////////////////////////
// convert shift
// fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
// fp -> int: | `XLEN zeros | Mantissa | 0's if necessary | << CalcExp
// process:
// - start - CalcExp = 1 + XExp - Largest Bias
// | `XLEN zeros | Mantissa | 0's if nessisary |
// | `XLEN zeros | Mantissa | 0's if necessary |
//
// - shift left 1 (1)
// | `XLEN-1 zeros |bit| frac | 0's if nessisary |
// | `XLEN-1 zeros |bit| frac | 0's if necessary |
// . <- binary point
//
// - shift left till unbiased exponent is 0 (XExp - Largest Bias)
// | 0's | Mantissa | 0's if nessisary |
// | 0's | Mantissa | 0's if necessary |
// | keep |
//
// fp -> fp:
// - if result is subnormal or underflowed:
// | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1
// | `NF-1 zeros | Mantissa | 0's if necessary | << NF+CalcExp-1
// process:
// - start
// | mantissa | 0's |
//
// - shift right by NF-1 (NF-1)
// | `NF-1 zeros | mantissa | 0's |
// | `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 subnormal:
// | lzcIn | 0's if nessisary | << ZeroCnt+1
// | lzcIn | 0's if necessary | << ZeroCnt+1
// - plus 1 to shift out the first 1
//
// int -> fp: | lzcIn | 0's if nessisary | << ZeroCnt+1
// int -> fp: | lzcIn | 0's if necessary | << ZeroCnt+1
// - plus 1 to shift out the first 1
// fma shift
// | 00 | Sm | << LZA output
// | 00 | Sm | << LZA output
// .
// - two extra bits so we can correct for an LZA error of 1 or 2
// divsqrt shift
// | Nf 0's | Qm | << calculated shift amount
// | Nf 0's | Qm | << calculated shift amount
// .
module normshift import cvw::*; #(parameter cvw_t P) (

View File

@ -28,100 +28,100 @@
module postprocess import cvw::*; #(parameter cvw_t P) (
// general signals
input logic Xs, Ys, // input signs
input logic [P.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 [P.FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
input logic XZero, YZero, // inputs are zero
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 [1:0] PostProcSel, // select result to be written to fp register
input logic Xs, Ys, // input signs
input logic [P.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 [P.FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
input logic XZero, YZero, // inputs are zero
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 [1:0] PostProcSel, // select result to be written to fp register
//fma signals
input logic FmaAs, // the modified Z sign - depends on instruction
input logic FmaPs, // the product's sign
input logic FmaSs, // Sum sign
input logic [P.NE+1:0] FmaSe, // the sum's exponent
input logic [3*P.NF+3:0] FmaSm, // the positive sum
input logic FmaASticky, // sticky bit that is calculated during alignment
input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // the normalization shift count
input logic FmaAs, // the modified Z sign - depends on instruction
input logic FmaPs, // the product's sign
input logic FmaSs, // Sum sign
input logic [P.NE+1:0] FmaSe, // the sum's exponent
input logic [3*P.NF+3:0] FmaSm, // the positive sum
input logic FmaASticky, // sticky bit that is calculated during alignment
input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // the normalization shift count
//divide signals
input logic DivSticky, // divider sticky bit
input logic [P.NE+1:0] DivQe, // divsqrt exponent
input logic [P.DIVb:0] DivQm, // divsqrt significand
input logic DivSticky, // divider sticky bit
input logic [P.NE+1:0] DivQe, // divsqrt exponent
input logic [P.DIVb:0] DivQm, // divsqrt significand
// conversion signals
input logic CvtCs, // the result's sign
input logic [P.NE:0] CvtCe, // the calculated expoent
input logic CvtResSubnormUf, // the convert result is subnormal or underflows
input logic [P.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 [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
input logic IntZero, // is the integer input zero
input logic CvtCs, // the result's sign
input logic [P.NE:0] CvtCe, // the calculated expoent
input logic CvtResSubnormUf, // the convert result is subnormal or underflows
input logic [P.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 [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
input logic IntZero, // is the integer input zero
// final results
output logic [P.FLEN-1:0] PostProcRes,// postprocessor final result
output logic [4:0] PostProcFlg,// postprocesser flags
output logic [P.XLEN-1:0] FCvtIntRes // the integer conversion result
output logic [P.FLEN-1:0] PostProcRes, // postprocessor final result
output logic [4:0] PostProcFlg, // postprocesser flags
output logic [P.XLEN-1:0] FCvtIntRes // the integer conversion result
);
// general signals
logic Rs; // result sign
logic [P.NF-1:0] Rf; // Result fraction
logic [P.NE-1:0] Re; // Result exponent
logic Ms; // norMalized sign
logic [P.CORRSHIFTSZ-1:0] Mf; // norMalized fraction
logic [P.NE+1:0] Me; // normalized exponent
logic [P.NE+1:0] FullRe; // Re with bits to determine sign and overflow
logic UfPlus1; // do you add one (for determining underflow flag)
logic [P.LOGNORMSHIFTSZ-1:0] ShiftAmt; // normalization shift amount
logic [P.NORMSHIFTSZ-1:0] ShiftIn; // input to normalization shift
logic [P.NORMSHIFTSZ-1:0] Shifted; // the ouput of the normalized shifter (before shift correction)
logic Plus1; // add one to the final result?
logic Overflow; // overflow flag used to select results
logic Invalid; // invalid flag used to select results
logic Guard, Round, Sticky; // bits needed to determine rounding
logic [P.FMTBITS-1:0] OutFmt; // output format
logic Rs; // result sign
logic [P.NF-1:0] Rf; // Result fraction
logic [P.NE-1:0] Re; // Result exponent
logic Ms; // norMalized sign
logic [P.CORRSHIFTSZ-1:0] Mf; // norMalized fraction
logic [P.NE+1:0] Me; // normalized exponent
logic [P.NE+1:0] FullRe; // Re with bits to determine sign and overflow
logic UfPlus1; // do you add one (for determining underflow flag)
logic [P.LOGNORMSHIFTSZ-1:0] ShiftAmt; // normalization shift amount
logic [P.NORMSHIFTSZ-1:0] ShiftIn; // input to normalization shift
logic [P.NORMSHIFTSZ-1:0] Shifted; // the ouput of the normalized shifter (before shift correction)
logic Plus1; // add one to the final result?
logic Overflow; // overflow flag used to select results
logic Invalid; // invalid flag used to select results
logic Guard, Round, Sticky; // bits needed to determine rounding
logic [P.FMTBITS-1:0] OutFmt; // output format
// fma signals
logic [P.NE+1:0] FmaMe; // exponent of the normalized sum
logic FmaSZero; // is the sum zero
logic [3*P.NF+5:0] FmaShiftIn; // fma shift input
logic [P.NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account Subnormal or zero results
logic FmaPreResultSubnorm; // is the result subnormal - calculated before LZA corection
logic [$clog2(3*P.NF+5)-1:0] FmaShiftAmt;// normalization shift amount for fma
logic [P.NE+1:0] FmaMe; // exponent of the normalized sum
logic FmaSZero; // is the sum zero
logic [3*P.NF+5:0] FmaShiftIn; // fma shift input
logic [P.NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account Subnormal or zero results
logic FmaPreResultSubnorm; // is the result subnormal - calculated before LZA corection
logic [$clog2(3*P.NF+5)-1:0] FmaShiftAmt; // normalization shift amount for fma
// division singals
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount
logic [P.NORMSHIFTSZ-1:0] DivShiftIn; // divsqrt shift input
logic [P.NE+1:0] Qe; // divsqrt corrected exponent after corretion shift
logic DivByZero; // divide by zero flag
logic DivResSubnorm; // is the divsqrt result subnormal
logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed)
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount
logic [P.NORMSHIFTSZ-1:0] DivShiftIn; // divsqrt shift input
logic [P.NE+1:0] Qe; // divsqrt corrected exponent after corretion shift
logic DivByZero; // divide by zero flag
logic DivResSubnorm; // is the divsqrt result subnormal
logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed)
// conversion signals
logic [P.CVTLEN+P.NF:0] CvtShiftIn; // number to be shifted for converter
logic [1:0] CvtNegResMsbs; // most significant bits of possibly negated int result
logic [P.XLEN+1:0] CvtNegRes; // possibly negated integer result
logic CvtResUf; // did the convert result underflow
logic IntInvalid; // invalid integer flag
logic [P.CVTLEN+P.NF:0] CvtShiftIn; // number to be shifted for converter
logic [1:0] CvtNegResMsbs; // most significant bits of possibly negated int result
logic [P.XLEN+1:0] CvtNegRes; // possibly negated integer result
logic CvtResUf; // did the convert result underflow
logic IntInvalid; // invalid integer flag
// readability signals
logic Mult; // multiply opperation
logic Sqrt; // is the divsqrt opperation sqrt
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?
logic CvtOp; // convertion opperation
logic FmaOp; // fma opperation
logic DivOp; // divider opperation
logic InfIn; // are any of the inputs infinity
logic NaNIn; // are any of the inputs NaN
logic Mult; // multiply opperation
logic Sqrt; // is the divsqrt opperation sqrt
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?
logic CvtOp; // convertion opperation
logic FmaOp; // fma opperation
logic DivOp; // divider opperation
logic InfIn; // are any of the inputs infinity
logic NaNIn; // are any of the inputs NaN
// signals to help readability
assign Signed = OpCtrl[0];
assign Int64 = OpCtrl[1];
assign Signed = OpCtrl[0];
assign Int64 = OpCtrl[1];
assign IntToFp = OpCtrl[2];
assign Mult = OpCtrl[2]&~OpCtrl[1]&~OpCtrl[0];
assign CvtOp = (PostProcSel == 2'b00);
assign FmaOp = (PostProcSel == 2'b10);
assign DivOp = (PostProcSel == 2'b01);
assign Sqrt = OpCtrl[0];
assign Mult = OpCtrl[2]&~OpCtrl[1]&~OpCtrl[0];
assign CvtOp = (PostProcSel == 2'b00);
assign FmaOp = (PostProcSel == 2'b10);
assign DivOp = (PostProcSel == 2'b01);
assign Sqrt = OpCtrl[0];
// is there an input of infinity or NaN being used
assign InfIn = XInf|YInf|ZInf;
@ -153,19 +153,19 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
case(PostProcSel)
2'b10: begin // fma
ShiftAmt = {{P.LOGNORMSHIFTSZ-$clog2(3*P.NF+5){1'b0}}, FmaShiftAmt};
ShiftIn = {FmaShiftIn, {P.NORMSHIFTSZ-(3*P.NF+6){1'b0}}};
ShiftIn = {FmaShiftIn, {P.NORMSHIFTSZ-(3*P.NF+6){1'b0}}};
end
2'b00: begin // cvt
ShiftAmt = {{P.LOGNORMSHIFTSZ-$clog2(P.CVTLEN+1){1'b0}}, CvtShiftAmt};
ShiftIn = {CvtShiftIn, {P.NORMSHIFTSZ-P.CVTLEN-P.NF-1{1'b0}}};
ShiftIn = {CvtShiftIn, {P.NORMSHIFTSZ-P.CVTLEN-P.NF-1{1'b0}}};
end
2'b01: begin //divsqrt
ShiftAmt = DivShiftAmt;
ShiftIn = DivShiftIn;
ShiftIn = DivShiftIn;
end
default: begin
ShiftAmt = {P.LOGNORMSHIFTSZ{1'bx}};
ShiftIn = {P.NORMSHIFTSZ{1'bx}};
ShiftIn = {P.NORMSHIFTSZ{1'bx}};
end
endcase

View File

@ -28,46 +28,46 @@
module round import cvw::*; #(parameter cvw_t P) (
input logic [P.FMTBITS-1:0] OutFmt, // output format
input logic [2:0] Frm, // rounding mode
input logic [1:0] PostProcSel, // select the postprocessor output
input logic Ms, // normalized sign
input logic [2:0] Frm, // rounding mode
input logic [1:0] PostProcSel, // select the postprocessor output
input logic Ms, // normalized sign
input logic [P.CORRSHIFTSZ-1:0] Mf, // normalized fraction
// fma
input logic FmaOp, // is an fma opperation being done?
input logic FmaOp, // is an fma opperation being done?
input logic [P.NE+1:0] FmaMe, // exponent of the normalized sum for fma
input logic FmaASticky, // addend's sticky bit
input logic FmaASticky, // addend's sticky bit
// divsqrt
input logic DivOp, // is a division opperation being done
input logic DivSticky, // divsqrt sticky bit
input logic DivOp, // is a division opperation being done
input logic DivSticky, // divsqrt sticky bit
input logic [P.NE+1:0] Qe, // the divsqrt calculated expoent
// cvt
input logic CvtOp, // is a convert opperation being done
input logic ToInt, // is the cvt op a cvt to integer
input logic CvtResSubnormUf, // is the cvt result subnormal or underflow
input logic CvtResUf, // does the cvt result underflow
input logic CvtOp, // is a convert opperation being done
input logic ToInt, // is the cvt op a cvt to integer
input logic CvtResSubnormUf, // is the cvt result subnormal or underflow
input logic CvtResUf, // does the cvt result underflow
input logic [P.NE:0] CvtCe, // the cvt calculated expoent
// outputs
output logic [P.NE+1:0] Me, // normalied fraction
output logic UfPlus1, // do you add one to the result if given an unbounded exponent
output logic UfPlus1, // do you add one to the result if given an unbounded exponent
output logic [P.NE+1:0] FullRe, // Re with bits to determine sign and overflow
output logic [P.NE-1:0] Re, // Result exponent
output logic [P.NF-1:0] Rf, // Result fractionNormS
output logic Sticky, // sticky bit
output logic Plus1, // do you add one to the final result
output logic Round, Guard // bits needed to calculate rounding
output logic Sticky, // sticky bit
output logic Plus1, // do you add one to the final result
output logic Round, Guard // bits needed to calculate rounding
);
logic UfCalcPlus1; // calculated plus one for unbounded exponent
logic NormSticky; // normalized sum's sticky bit
logic [P.NF-1:0] RoundFrac; // rounded fraction
logic FpRes; // is the result a floating point
logic IntRes; // is the result an integer
logic FpGuard, FpRound; // floating point round/guard bits
logic FpLsbRes; // least significant bit of floating point result
logic LsbRes; // lsb of result
logic CalcPlus1; // calculated plus1
logic FpPlus1; // do you add one to the fp result
logic [P.FLEN:0] RoundAdd; // how much to add to the result
logic UfCalcPlus1; // calculated plus one for unbounded exponent
logic NormSticky; // normalized sum's sticky bit
logic [P.NF-1:0] RoundFrac; // rounded fraction
logic FpRes; // is the result a floating point
logic IntRes; // is the result an integer
logic FpGuard, FpRound; // floating point round/guard bits
logic FpLsbRes; // least significant bit of floating point result
logic LsbRes; // lsb of result
logic CalcPlus1; // calculated plus1
logic FpPlus1; // do you add one to the fp result
logic [P.FLEN:0] RoundAdd; // how much to add to the result
// what position is XLEN in?
// options:
@ -86,7 +86,7 @@ module round import cvw::*; #(parameter cvw_t P) (
// {Round, Sticky}
// 0x - do nothing
// 10 - tie - Plus1 if result is odd (LSBNormSum = 1)
// - don't add 1 if a small number was supposed to be subtracted
// - don't add 1 if a small number was supposed to be subtracted
// 11 - do nothing if a small number was supposed to subtracted (the sticky bit was set by the small number)
// - plus 1 otherwise
@ -104,14 +104,13 @@ module round import cvw::*; #(parameter cvw_t P) (
// {Guard, Round, Sticky}
// 0x - do nothing
// 10 - tie - Plus1
// - don't add 1 if a small number was supposed to be subtracted
// - don't add 1 if a small number was supposed to be subtracted
// 11 - do nothing if a small number was supposed to subtracted (the sticky bit was set by the small number)
// - Plus 1 otherwise
// determine what format the final result is in: int or fp
assign IntRes = ToInt;
assign FpRes = ~IntRes;
assign FpRes = ~IntRes;
// sticky bit calculation
if (P.FPSIZES == 1) begin
@ -121,7 +120,7 @@ module round import cvw::*; #(parameter cvw_t P) (
// | NF |1|1|
// ^ ^ if floating point result
// ^ if not an FMA result
if (XLENPOS == 1)assign NormSticky = (|Mf[P.CORRSHIFTSZ-P.NF-2:P.CORRSHIFTSZ-P.XLEN-1]&FpRes) |
if (XLENPOS == 1)assign NormSticky = (|Mf[P.CORRSHIFTSZ-P.NF-2:P.CORRSHIFTSZ-P.XLEN-1]&FpRes) |
(|Mf[P.CORRSHIFTSZ-P.XLEN-2:0]);
// 2: NF > XLEN
if (XLENPOS == 2)assign NormSticky = (|Mf[P.CORRSHIFTSZ-P.XLEN-2:P.CORRSHIFTSZ-P.NF-1]&IntRes) |
@ -178,113 +177,104 @@ module round import cvw::*; #(parameter cvw_t P) (
(|Mf[P.CORRSHIFTSZ-P.Q_NF-2:0]);
end
// only add the Addend sticky if doing an FMA opperation
// - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits)
assign Sticky = FmaASticky&FmaOp | NormSticky | CvtResUf&CvtOp | FmaMe[P.NE+1]&FmaOp | DivSticky&DivOp;
// determine round and LSB of the rounded value
// - underflow round bit is used to determint the underflow flag
if (P.FPSIZES == 1) begin
assign FpGuard = Mf[P.CORRSHIFTSZ-P.NF-1];
assign FpGuard = Mf[P.CORRSHIFTSZ-P.NF-1];
assign FpLsbRes = Mf[P.CORRSHIFTSZ-P.NF];
assign FpRound = Mf[P.CORRSHIFTSZ-P.NF-2];
assign FpRound = Mf[P.CORRSHIFTSZ-P.NF-2];
end else if (P.FPSIZES == 2) begin
assign FpGuard = OutFmt ? Mf[P.CORRSHIFTSZ-P.NF-1] : Mf[P.CORRSHIFTSZ-P.NF1-1];
assign FpGuard = OutFmt ? Mf[P.CORRSHIFTSZ-P.NF-1] : Mf[P.CORRSHIFTSZ-P.NF1-1];
assign FpLsbRes = OutFmt ? Mf[P.CORRSHIFTSZ-P.NF] : Mf[P.CORRSHIFTSZ-P.NF1];
assign FpRound = OutFmt ? Mf[P.CORRSHIFTSZ-P.NF-2] : Mf[P.CORRSHIFTSZ-P.NF1-2];
assign FpRound = OutFmt ? Mf[P.CORRSHIFTSZ-P.NF-2] : Mf[P.CORRSHIFTSZ-P.NF1-2];
end else if (P.FPSIZES == 3) begin
always_comb
case (OutFmt)
P.FMT: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.NF-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.NF-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.NF];
FpRound = Mf[P.CORRSHIFTSZ-P.NF-2];
FpRound = Mf[P.CORRSHIFTSZ-P.NF-2];
end
P.FMT1: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.NF1-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.NF1-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.NF1];
FpRound = Mf[P.CORRSHIFTSZ-P.NF1-2];
FpRound = Mf[P.CORRSHIFTSZ-P.NF1-2];
end
P.FMT2: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.NF2-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.NF2-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.NF2];
FpRound = Mf[P.CORRSHIFTSZ-P.NF2-2];
FpRound = Mf[P.CORRSHIFTSZ-P.NF2-2];
end
default: begin
FpGuard = 1'bx;
FpGuard = 1'bx;
FpLsbRes = 1'bx;
FpRound = 1'bx;
FpRound = 1'bx;
end
endcase
end else if (P.FPSIZES == 4) begin
always_comb
case (OutFmt)
2'h3: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.Q_NF-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.Q_NF-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.Q_NF];
FpRound = Mf[P.CORRSHIFTSZ-P.Q_NF-2];
FpRound = Mf[P.CORRSHIFTSZ-P.Q_NF-2];
end
2'h1: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.D_NF-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.D_NF-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.D_NF];
FpRound = Mf[P.CORRSHIFTSZ-P.D_NF-2];
FpRound = Mf[P.CORRSHIFTSZ-P.D_NF-2];
end
2'h0: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.S_NF-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.S_NF-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.S_NF];
FpRound = Mf[P.CORRSHIFTSZ-P.S_NF-2];
FpRound = Mf[P.CORRSHIFTSZ-P.S_NF-2];
end
2'h2: begin
FpGuard = Mf[P.CORRSHIFTSZ-P.H_NF-1];
FpGuard = Mf[P.CORRSHIFTSZ-P.H_NF-1];
FpLsbRes = Mf[P.CORRSHIFTSZ-P.H_NF];
FpRound = Mf[P.CORRSHIFTSZ-P.H_NF-2];
FpRound = Mf[P.CORRSHIFTSZ-P.H_NF-2];
end
endcase
end
assign Guard = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-1] : FpGuard;
assign Guard = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-1] : FpGuard;
assign LsbRes = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN] : FpLsbRes;
assign Round = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound;
assign Round = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound;
always_comb begin
// Determine if you add 1
case (Frm)
3'b000: CalcPlus1 = Guard & (Round|Sticky|LsbRes);//round to nearest even
3'b001: CalcPlus1 = 0;//round to zero
3'b010: CalcPlus1 = Ms;//round down
3'b011: CalcPlus1 = ~Ms;//round up
3'b100: CalcPlus1 = Guard;//round to nearest max magnitude
3'b000: CalcPlus1 = Guard & (Round|Sticky|LsbRes);//round to nearest even
3'b001: CalcPlus1 = 0;//round to zero
3'b010: CalcPlus1 = Ms;//round down
3'b011: CalcPlus1 = ~Ms;//round up
3'b100: CalcPlus1 = Guard;//round to nearest max magnitude
default: CalcPlus1 = 1'bx;
endcase
// Determine if you add 1 (for underflow flag)
case (Frm)
3'b000: UfCalcPlus1 = Round & (Sticky|Guard);//round to nearest even
3'b001: UfCalcPlus1 = 0;//round to zero
3'b010: UfCalcPlus1 = Ms;//round down
3'b011: UfCalcPlus1 = ~Ms;//round up
3'b100: UfCalcPlus1 = Round;//round to nearest max magnitude
3'b000: UfCalcPlus1 = Round & (Sticky|Guard);//round to nearest even
3'b001: UfCalcPlus1 = 0;//round to zero
3'b010: UfCalcPlus1 = Ms;//round down
3'b011: UfCalcPlus1 = ~Ms;//round up
3'b100: UfCalcPlus1 = Round;//round to nearest max magnitude
default: UfCalcPlus1 = 1'bx;
endcase
end
// If an answer is exact don't round
assign Plus1 = CalcPlus1 & (Sticky|Round|Guard);
assign Plus1 = CalcPlus1 & (Sticky|Round|Guard);
assign FpPlus1 = Plus1&~(ToInt&CvtOp);
assign UfPlus1 = UfCalcPlus1 & (Sticky|Round);
// place Plus1 into the proper position for the format
if (P.FPSIZES == 1) begin
assign RoundAdd = {{P.FLEN{1'b0}}, FpPlus1};
@ -302,21 +292,17 @@ module round import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 4)
assign RoundAdd = {(P.Q_NE+1+P.H_NF)'(0), FpPlus1&(OutFmt==P.H_FMT), (P.S_NF-P.H_NF-1)'(0), FpPlus1&(OutFmt==P.S_FMT), (P.D_NF-P.S_NF-1)'(0), FpPlus1&(OutFmt==P.D_FMT), (P.Q_NF-P.D_NF-1)'(0), FpPlus1&(OutFmt==P.Q_FMT)};
// trim unneeded bits from fraction
assign RoundFrac = Mf[P.CORRSHIFTSZ-1:P.CORRSHIFTSZ-P.NF];
// select the exponent
always_comb
case(PostProcSel)
2'b10: Me = FmaMe; // fma
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt
2'b10: Me = FmaMe; // fma
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt
// 2'b01: Me = DivDone ? Qe : '0; // divide
2'b01: Me = Qe; // divide
default: Me = '0;
2'b01: Me = Qe; // divide
default: Me = '0;
endcase
@ -324,7 +310,6 @@ module round import cvw::*; #(parameter cvw_t P) (
// round the result
// - if the fraction overflows one should be added to the exponent
assign {FullRe, Rf} = {Me, RoundFrac} + RoundAdd;
assign Re = FullRe[P.NE-1:0];
assign Re = FullRe[P.NE-1:0];
endmodule

View File

@ -29,41 +29,41 @@
module shiftcorrection import cvw::*; #(parameter cvw_t P) (
input logic [P.NORMSHIFTSZ-1:0] Shifted, // the shifted sum before LZA correction
// divsqrt
input logic DivOp, // is it a divsqrt opperation
input logic DivResSubnorm, // is the divsqrt result subnormal
input logic DivOp, // is it a divsqrt opperation
input logic DivResSubnorm, // is the divsqrt result subnormal
input logic [P.NE+1:0] DivQe, // the divsqrt result's exponent
input logic DivSubnormShiftPos, // is the subnorm divider shift amount positive (ie not underflowed)
input logic DivSubnormShiftPos, // is the subnorm divider shift amount positive (ie not underflowed)
//fma
input logic FmaOp, // is it an fma opperation
input logic FmaOp, // is it an fma opperation
input logic [P.NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results
input logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
input logic FmaSZero,
input logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
input logic FmaSZero,
// output
output logic [P.NE+1:0] FmaMe, // exponent of the normalized sum
output logic [P.CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction
output logic [P.NE+1:0] Qe // corrected exponent for divider
);
logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction
logic [P.CORRSHIFTSZ-1:0] CorrQm0, CorrQm1; // portions of Shifted to select for CorrQmShifted
logic [P.CORRSHIFTSZ-1:0] CorrQmShifted; // the shifted divsqrt result after one bit shift
logic ResSubnorm; // is the result Subnormal
logic LZAPlus1; // add one or two to the sum's exponent due to LZA correction
logic LeftShiftQm; // should the divsqrt result be shifted one to the left
logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction
logic [P.CORRSHIFTSZ-1:0] CorrQm0, CorrQm1; // portions of Shifted to select for CorrQmShifted
logic [P.CORRSHIFTSZ-1:0] CorrQmShifted; // the shifted divsqrt result after one bit shift
logic ResSubnorm; // is the result Subnormal
logic LZAPlus1; // add one or two to the sum's exponent due to LZA correction
logic LeftShiftQm; // should the divsqrt result be shifted one to the left
// LZA correction
assign LZAPlus1 = Shifted[P.NORMSHIFTSZ-1];
// correct the shifting error caused by the LZA
// - the only possible mantissa for a plus two is all zeroes
// - a one has to propigate all the way through a sum. so we can leave the bottom statement alone
// - a one has to propigate all the way through a sum. so we can leave the bottom statement alone
mux2 #(P.NORMSHIFTSZ-2) lzacorrmux(Shifted[P.NORMSHIFTSZ-3:0], Shifted[P.NORMSHIFTSZ-2:1], LZAPlus1, CorrSumShifted);
// correct the shifting of the divsqrt caused by producing a result in (2, .5] range
// condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm)
// condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm)
assign LeftShiftQm = (LZAPlus1|(DivQe==1&~LZAPlus1));
assign CorrQm0 = Shifted[P.NORMSHIFTSZ-3:P.NORMSHIFTSZ-P.CORRSHIFTSZ-2];
assign CorrQm1 = Shifted[P.NORMSHIFTSZ-2:P.NORMSHIFTSZ-P.CORRSHIFTSZ-1];
assign CorrQm0 = Shifted[P.NORMSHIFTSZ-3:P.NORMSHIFTSZ-P.CORRSHIFTSZ-2];
assign CorrQm1 = Shifted[P.NORMSHIFTSZ-2:P.NORMSHIFTSZ-P.CORRSHIFTSZ-1];
mux2 #(P.CORRSHIFTSZ) divcorrmux(CorrQm0, CorrQm1, LeftShiftQm, CorrQmShifted);
// if the result of the divider was calculated to be subnormal, then the result was correctly normalized, so select the top shifted bits

View File

@ -27,39 +27,39 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module specialcase import cvw::*; #(parameter cvw_t P) (
input logic Xs, // X sign
input logic [P.NF:0] Xm, Ym, Zm, // input significand's
input logic XNaN, YNaN, ZNaN, // are the inputs NaN
input logic [2:0] Frm, // rounding mode
input logic [P.FMTBITS-1:0] OutFmt, // output format
input logic InfIn, // are any inputs infinity
input logic NaNIn, // are any input NaNs
input logic XInf, YInf, // are X or Y inifnity
input logic XZero, // is X zero
input logic Plus1, // do you add one for rounding
input logic Rs, // the result's sign
input logic Invalid, Overflow, // flags to choose the result
input logic [P.NE-1:0] Re, // Result exponent
input logic [P.NE+1:0] FullRe, // Result full exponent
input logic [P.NF-1:0] Rf, // Result fraction
input logic Xs, // X sign
input logic [P.NF:0] Xm, Ym, Zm, // input significand's
input logic XNaN, YNaN, ZNaN, // are the inputs NaN
input logic [2:0] Frm, // rounding mode
input logic [P.FMTBITS-1:0] OutFmt, // output format
input logic InfIn, // are any inputs infinity
input logic NaNIn, // are any input NaNs
input logic XInf, YInf, // are X or Y inifnity
input logic XZero, // is X zero
input logic Plus1, // do you add one for rounding
input logic Rs, // the result's sign
input logic Invalid, Overflow, // flags to choose the result
input logic [P.NE-1:0] Re, // Result exponent
input logic [P.NE+1:0] FullRe, // Result full exponent
input logic [P.NF-1:0] Rf, // Result fraction
// fma
input logic FmaOp, // is it a fma opperation
input logic FmaOp, // is it a fma opperation
// divsqrt
input logic DivOp, // is it a divsqrt opperation
input logic DivByZero, // divide by zero flag
input logic DivOp, // is it a divsqrt opperation
input logic DivByZero, // divide by zero flag
// cvt
input logic CvtOp, // is it a conversion opperation
input logic IntZero, // is the integer input zero
input logic IntToFp, // is cvt int -> fp opperation
input logic Int64, // is the integer 64 bits
input logic Signed, // is the integer signed
input logic [P.NE:0] CvtCe, // the calculated expoent for cvt
input logic IntInvalid, // integer invalid flag to choose the result
input logic CvtResUf, // does the convert result underflow
input logic [P.XLEN+1:0] CvtNegRes, // the possibly negated of the integer result
input logic CvtOp, // is it a conversion opperation
input logic IntZero, // is the integer input zero
input logic IntToFp, // is cvt int -> fp opperation
input logic Int64, // is the integer 64 bits
input logic Signed, // is the integer signed
input logic [P.NE:0] CvtCe, // the calculated expoent for cvt
input logic IntInvalid, // integer invalid flag to choose the result
input logic CvtResUf, // does the convert result underflow
input logic [P.XLEN+1:0] CvtNegRes, // the possibly negated of the integer result
// outputs
output logic [P.FLEN-1:0] PostProcRes,// final result
output logic [P.XLEN-1:0] FCvtIntRes // final integer result
output logic [P.FLEN-1:0] PostProcRes, // final result
output logic [P.XLEN-1:0] FCvtIntRes // final integer result
);
logic [P.FLEN-1:0] XNaNRes; // X is NaN result
@ -70,9 +70,9 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
logic [P.FLEN-1:0] OfRes; // overflowed result result
logic [P.FLEN-1:0] NormRes; // normal result
logic [P.XLEN-1:0] OfIntRes; // the overflow result for integer output
logic OfResMax; // does the of result output maximum norm fp number
logic KillRes; // kill the result for underflow
logic SelOfRes; // should the overflow result be selected
logic OfResMax; // does the of result output maximum norm fp number
logic KillRes; // kill the result for underflow
logic SelOfRes; // should the overflow result be selected
// does the overflow result output the maximum normalized floating point number
@ -83,23 +83,23 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
if (P.FPSIZES == 1) begin
//NaN res selection depending on standard
if(P.IEEE754) begin
assign XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
assign YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
assign ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
assign XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
assign YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
assign ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
assign InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end else begin
assign InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end
assign OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
assign UfRes = {Rs, {P.FLEN-2{1'b0}}, Plus1&Frm[1]&~(DivOp&YInf)};
assign OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
assign UfRes = {Rs, {P.FLEN-2{1'b0}}, Plus1&Frm[1]&~(DivOp&YInf)};
assign NormRes = {Rs, Re, Rf};
end else if (P.FPSIZES == 2) begin
if(P.IEEE754) begin
assign XNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
assign YNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF1]};
assign ZNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF1]};
assign XNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
assign YNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF1]};
assign ZNaNRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF1]};
assign InvalidRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
end else begin
assign InvalidRes = OutFmt ? {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
@ -120,57 +120,57 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
case (OutFmt)
P.FMT: begin
if(P.IEEE754) begin
XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end else begin
InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end
OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
UfRes = {Rs, (P.FLEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
UfRes = {Rs, (P.FLEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {Rs, Re, Rf};
end
P.FMT1: begin
if(P.IEEE754) begin
XNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
YNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF1]};
ZNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF1]};
XNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
YNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF1]};
ZNaNRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF1]};
InvalidRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
end else begin
InvalidRes = {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
end
OfRes = OfResMax ? {{P.FLEN-P.LEN1{1'b1}}, Rs, {P.NE1-1{1'b1}}, 1'b0, {P.NF1{1'b1}}} : {{P.FLEN-P.LEN1{1'b1}}, Rs, {P.NE1{1'b1}}, (P.NF1)'(0)};
UfRes = {{P.FLEN-P.LEN1{1'b1}}, Rs, (P.LEN1-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.LEN1{1'b1}}, Rs, Re[P.NE1-1:0], Rf[P.NF-1:P.NF-P.NF1]};
OfRes = OfResMax ? {{P.FLEN-P.LEN1{1'b1}}, Rs, {P.NE1-1{1'b1}}, 1'b0, {P.NF1{1'b1}}} : {{P.FLEN-P.LEN1{1'b1}}, Rs, {P.NE1{1'b1}}, (P.NF1)'(0)};
UfRes = {{P.FLEN-P.LEN1{1'b1}}, Rs, (P.LEN1-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.LEN1{1'b1}}, Rs, Re[P.NE1-1:0], Rf[P.NF-1:P.NF-P.NF1]};
end
P.FMT2: begin
if(P.IEEE754) begin
XNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF2]};
YNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF2]};
ZNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF2]};
XNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF2]};
YNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.NF2]};
ZNaNRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.NF2]};
InvalidRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, (P.NF2-1)'(0)};
end else begin
InvalidRes = {{P.FLEN-P.LEN2{1'b1}}, 1'b0, {P.NE2{1'b1}}, 1'b1, (P.NF2-1)'(0)};
end
OfRes = OfResMax ? {{P.FLEN-P.LEN2{1'b1}}, Rs, {P.NE2-1{1'b1}}, 1'b0, {P.NF2{1'b1}}} : {{P.FLEN-P.LEN2{1'b1}}, Rs, {P.NE2{1'b1}}, (P.NF2)'(0)};
UfRes = {{P.FLEN-P.LEN2{1'b1}}, Rs, (P.LEN2-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
OfRes = OfResMax ? {{P.FLEN-P.LEN2{1'b1}}, Rs, {P.NE2-1{1'b1}}, 1'b0, {P.NF2{1'b1}}} : {{P.FLEN-P.LEN2{1'b1}}, Rs, {P.NE2{1'b1}}, (P.NF2)'(0)};
UfRes = {{P.FLEN-P.LEN2{1'b1}}, Rs, (P.LEN2-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.LEN2{1'b1}}, Rs, Re[P.NE2-1:0], Rf[P.NF-1:P.NF-P.NF2]};
end
default: begin
if(P.IEEE754) begin
XNaNRes = (P.FLEN)'(0);
YNaNRes = (P.FLEN)'(0);
ZNaNRes = (P.FLEN)'(0);
XNaNRes = (P.FLEN)'(0);
YNaNRes = (P.FLEN)'(0);
ZNaNRes = (P.FLEN)'(0);
InvalidRes = (P.FLEN)'(0);
end else begin
InvalidRes = (P.FLEN)'(0);
end
OfRes = (P.FLEN)'(0);
UfRes = (P.FLEN)'(0);
NormRes = (P.FLEN)'(0);
OfRes = (P.FLEN)'(0);
UfRes = (P.FLEN)'(0);
NormRes = (P.FLEN)'(0);
end
endcase
@ -179,58 +179,58 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
case (OutFmt)
2'h3: begin
if(P.IEEE754) begin
XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
XNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
YNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Ym[P.NF-2:0]};
ZNaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, Zm[P.NF-2:0]};
InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end else begin
InvalidRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
end
OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
UfRes = {Rs, (P.FLEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
OfRes = OfResMax ? {Rs, {P.NE-1{1'b1}}, 1'b0, {P.NF{1'b1}}} : {Rs, {P.NE{1'b1}}, {P.NF{1'b0}}};
UfRes = {Rs, (P.FLEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {Rs, Re, Rf};
end
2'h1: begin
if(P.IEEE754) begin
XNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.D_NF]};
YNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.D_NF]};
ZNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.D_NF]};
XNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.D_NF]};
YNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.D_NF]};
ZNaNRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.D_NF]};
InvalidRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, (P.D_NF-1)'(0)};
end else begin
InvalidRes = {{P.FLEN-P.D_LEN{1'b1}}, 1'b0, {P.D_NE{1'b1}}, 1'b1, (P.D_NF-1)'(0)};
end
OfRes = OfResMax ? {{P.FLEN-P.D_LEN{1'b1}}, Rs, {P.D_NE-1{1'b1}}, 1'b0, {P.D_NF{1'b1}}} : {{P.FLEN-P.D_LEN{1'b1}}, Rs, {P.D_NE{1'b1}}, (P.D_NF)'(0)};
UfRes = {{P.FLEN-P.D_LEN{1'b1}}, Rs, (P.D_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
OfRes = OfResMax ? {{P.FLEN-P.D_LEN{1'b1}}, Rs, {P.D_NE-1{1'b1}}, 1'b0, {P.D_NF{1'b1}}} : {{P.FLEN-P.D_LEN{1'b1}}, Rs, {P.D_NE{1'b1}}, (P.D_NF)'(0)};
UfRes = {{P.FLEN-P.D_LEN{1'b1}}, Rs, (P.D_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.D_LEN{1'b1}}, Rs, Re[P.D_NE-1:0], Rf[P.NF-1:P.NF-P.D_NF]};
end
2'h0: begin
if(P.IEEE754) begin
XNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.S_NF]};
YNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.S_NF]};
ZNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.S_NF]};
XNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.S_NF]};
YNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.S_NF]};
ZNaNRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.S_NF]};
InvalidRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, (P.S_NF-1)'(0)};
end else begin
InvalidRes = {{P.FLEN-P.S_LEN{1'b1}}, 1'b0, {P.S_NE{1'b1}}, 1'b1, (P.S_NF-1)'(0)};
end
OfRes = OfResMax ? {{P.FLEN-P.S_LEN{1'b1}}, Rs, {P.S_NE-1{1'b1}}, 1'b0, {P.S_NF{1'b1}}} : {{P.FLEN-P.S_LEN{1'b1}}, Rs, {P.S_NE{1'b1}}, (P.S_NF)'(0)};
UfRes = {{P.FLEN-P.S_LEN{1'b1}}, Rs, (P.S_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
OfRes = OfResMax ? {{P.FLEN-P.S_LEN{1'b1}}, Rs, {P.S_NE-1{1'b1}}, 1'b0, {P.S_NF{1'b1}}} : {{P.FLEN-P.S_LEN{1'b1}}, Rs, {P.S_NE{1'b1}}, (P.S_NF)'(0)};
UfRes = {{P.FLEN-P.S_LEN{1'b1}}, Rs, (P.S_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.S_LEN{1'b1}}, Rs, Re[P.S_NE-1:0], Rf[P.NF-1:P.NF-P.S_NF]};
end
2'h2: begin
if(P.IEEE754) begin
XNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.H_NF]};
YNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.H_NF]};
ZNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.H_NF]};
XNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.H_NF]};
YNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Ym[P.NF-2:P.NF-P.H_NF]};
ZNaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, Zm[P.NF-2:P.NF-P.H_NF]};
InvalidRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, (P.H_NF-1)'(0)};
end else begin
InvalidRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, (P.H_NF-1)'(0)};
end
OfRes = OfResMax ? {{P.FLEN-P.H_LEN{1'b1}}, Rs, {P.H_NE-1{1'b1}}, 1'b0, {P.H_NF{1'b1}}} : {{P.FLEN-P.H_LEN{1'b1}}, Rs, {P.H_NE{1'b1}}, (P.H_NF)'(0)};
OfRes = OfResMax ? {{P.FLEN-P.H_LEN{1'b1}}, Rs, {P.H_NE-1{1'b1}}, 1'b0, {P.H_NF{1'b1}}} : {{P.FLEN-P.H_LEN{1'b1}}, Rs, {P.H_NE{1'b1}}, (P.H_NF)'(0)};
// zero is exact if dividing by infinity so don't add 1
UfRes = {{P.FLEN-P.H_LEN{1'b1}}, Rs, (P.H_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
UfRes = {{P.FLEN-P.H_LEN{1'b1}}, Rs, (P.H_LEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
NormRes = {{P.FLEN-P.H_LEN{1'b1}}, Rs, Re[P.H_NE-1:0], Rf[P.NF-1:P.NF-P.H_NF]};
end
endcase
@ -290,7 +290,6 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
// select the integer output
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
// - if the input underflows

View File

@ -73,6 +73,15 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
logic [`C-1:0][7:1] threshMask;
logic [P.PLIC_NUM_SRC-1:0] One;
// hacks to handle gracefully PLIC_NUM_SRC being smaller than 32
// Otherwise Questa and other simulators produce part-select out of bounds even
// though sources >=32 are never used
localparam PLIC_SRC_TOP = (P.PLIC_NUM_SRC >= 32) ? P.PLIC_NUM_SRC : 1;
localparam PLIC_SRC_BOT = (P.PLIC_NUM_SRC >= 32) ? 32 : 1;
localparam PLIC_SRC_DINTOP = (P.PLIC_NUM_SRC >= 32) ? P.PLIC_NUM_SRC -32 : 0;
localparam PLIC_SRC_EXT = (P.PLIC_NUM_SRC >= 32) ? 63-P.PLIC_NUM_SRC : 31;
// =======
// AHB I/O
// =======
@ -107,18 +116,13 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
intInProgress <= #1 '0;
// writing
end else begin
if (memwrite)
if (memwrite)
casez(entry)
24'h0000??: intPriority[entry[7:2]] <= #1 Din[2:0];
24'h002000: intEn[0][PLIC_NUM_SRC_MIN_32:1] <= #1 Din[PLIC_NUM_SRC_MIN_32:1];
24'h002080: intEn[1][PLIC_NUM_SRC_MIN_32:1] <= #1 Din[PLIC_NUM_SRC_MIN_32:1];
// verilator lint_off SELRANGE
// *** RT: Long term we want to factor out these variable number of registers as a generate loop
// I think this won't work as a case statement.
24'h002004: if (P.PLIC_NUM_SRC >= 32) intEn[0][P.PLIC_NUM_SRC:32] <= #1 Din[P.PLIC_NUM_SRC-32:0];
24'h002084: if (P.PLIC_NUM_SRC >= 32) intEn[1][P.PLIC_NUM_SRC:32] <= #1 Din[P.PLIC_NUM_SRC-32:0];
// verilator lint_on SELRANGE
24'h002004: if (P.PLIC_NUM_SRC >= 32) intEn[0][PLIC_SRC_TOP:PLIC_SRC_BOT] <= #1 Din[PLIC_SRC_DINTOP:0];
24'h002084: if (P.PLIC_NUM_SRC >= 32) intEn[1][PLIC_SRC_TOP:PLIC_SRC_BOT] <= #1 Din[PLIC_SRC_DINTOP:0];
24'h200000: intThreshold[0] <= #1 Din[2:0];
24'h200004: intInProgress <= #1 intInProgress & ~(One << (Din[5:0]-1)); // lower "InProgress" to signify completion
24'h201000: intThreshold[1] <= #1 Din[2:0];
@ -131,20 +135,10 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
24'h001000: Dout <= #1 {{(31-PLIC_NUM_SRC_MIN_32){1'b0}},intPending[PLIC_NUM_SRC_MIN_32:1],1'b0};
24'h002000: Dout <= #1 {{(31-PLIC_NUM_SRC_MIN_32){1'b0}},intEn[0][PLIC_NUM_SRC_MIN_32:1],1'b0};
// verilator lint_off SELRANGE
// verilator lint_off WIDTHTRUNC
24'h001004: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intPending[P.PLIC_NUM_SRC:32]};
24'h002004: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intEn[0][P.PLIC_NUM_SRC:32]};
// verilator lint_on SELRANGE
// verilator lint_on WIDTHTRUNC
24'h001004: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(PLIC_SRC_EXT){1'b0}},intPending[PLIC_SRC_TOP:PLIC_SRC_BOT]};
24'h002004: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(PLIC_SRC_EXT){1'b0}},intEn[0][PLIC_SRC_TOP:PLIC_SRC_BOT]};
24'h002080: Dout <= #1 {{(31-PLIC_NUM_SRC_MIN_32){1'b0}},intEn[1][PLIC_NUM_SRC_MIN_32:1],1'b0};
// verilator lint_off SELRANGE
// verilator lint_off WIDTHTRUNC
24'h002084: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(63-P.PLIC_NUM_SRC){1'b0}},intEn[1][P.PLIC_NUM_SRC:32]};
// verilator lint_on SELRANGE
// verilator lint_on WIDTHTRUNC
24'h002084: if (P.PLIC_NUM_SRC >= 32) Dout <= #1 {{(PLIC_SRC_EXT){1'b0}},intEn[1][PLIC_SRC_TOP:PLIC_SRC_BOT]};
24'h200000: Dout <= #1 {29'b0,intThreshold[0]};
24'h200004: begin
Dout <= #1 {26'b0,intClaim[0]};

View File

@ -27,6 +27,18 @@
#include "WALLY-init-lib.h"
main:
# Tests sret in machine mode
la t1, sretdone
csrw sepc, t1
sret
sretdone:
addi t2, x0, 42
# switch to user mode
li a0, 0
ecall
sret #should be treated as illegal instruction
mret #mret in user mode and should be illegal
# switch to supervisor mode
li a0, 1
@ -44,16 +56,38 @@ main:
csrw satp, zero
# STIMECMP from S mode
li t0, 1
# 1st is when MENVCFG_STCE is cleared
li a0, 3
ecall # starts in M-mode
csrw menvcfg, x0
li a0, 1
ecall # enter S-mode
csrw stimecmp, zero
li t0, 3
li a0, 3
ecall # return to M-mode
csrsi mcounteren, 2 # mcounteren_tm = 1
li t0, 1
li a0, 1
ecall # supervisor mode again
csrw stimecmp, zero
li t0, 3
li a0, 3
ecall # machine mode again
# STIMECMP from S mode
# 2nd is when MENVCFG_STCE is set
csrci mcounteren, 2 # mcounteren_tm = 0
li t0, 1
slli t0, t0, 63
csrw menvcfg, t0
li a0, 1
ecall # enter S-mode
csrw stimecmp, zero
li a0, 3
ecall # return to M-mode
csrsi mcounteren, 2 # mcounteren_tm = 1
li a0, 1
ecall # supervisor mode again
csrw stimecmp, zero
li a0, 3
ecall # machine mode again