This commit is contained in:
David Harris 2022-07-04 03:21:08 +00:00
commit 37ae414ff2
9 changed files with 136 additions and 186 deletions

View File

@ -32,7 +32,7 @@
`define DESIGN_COMPILER 0 `define DESIGN_COMPILER 0
// RV32 or RV64: XLEN = 32 or 64 // RV32 or RV64: XLEN = 32 or 64
`define XLEN 32 `define XLEN 64
// IEEE 754 compliance // IEEE 754 compliance
`define IEEE754 0 `define IEEE754 0

View File

@ -11,7 +11,7 @@ module divshiftcalc(
output logic [`NE+1:0] DivDenormShift output logic [`NE+1:0] DivDenormShift
); );
logic [`NE+1:0] NormShift; logic [`NE+1:0] NormShift;
logic [`NE+1:0] Nf, NfPlus1; logic [`NE+1:0] Nf;
// is the result denromalized // is the result denromalized
// if the exponent is 1 then the result needs to be normalized then the result is denormalizes // if the exponent is 1 then the result needs to be normalized then the result is denormalizes
@ -19,51 +19,25 @@ module divshiftcalc(
// select the proper fraction lengnth // select the proper fraction lengnth
if (`FPSIZES == 1) begin if (`FPSIZES == 1) begin
assign Nf = (`NE+2)'(`NF); assign Nf = (`NE+2)'(`NF);
assign NfPlus1 = (`NE+2)'(`NF+1);
end else if (`FPSIZES == 2) begin end else if (`FPSIZES == 2) begin
assign Nf = FmtM ? (`NE+2)'(`NF) : (`NE+2)'(`NF1); assign Nf = FmtM ? (`NE+2)'(`NF) : (`NE+2)'(`NF1);
assign NfPlus1 = FmtM ? (`NE+2)'(`NF+1) : (`NE+2)'(`NF1+1);
end else if (`FPSIZES == 3) begin end else if (`FPSIZES == 3) begin
always_comb always_comb
case (FmtM) case (FmtM)
`FMT: begin `FMT: Nf = (`NE+2)'(`NF);
Nf = (`NE+2)'(`NF); `FMT1: Nf = (`NE+2)'(`NF1);
NfPlus1 = (`NE+2)'(`NF+1); `FMT2: Nf = (`NE+2)'(`NF2);
end default: Nf = 1'bx;
`FMT1: begin
Nf = (`NE+2)'(`NF1);
NfPlus1 = (`NE+2)'(`NF1+1);
end
`FMT2: begin
Nf = (`NE+2)'(`NF2);
NfPlus1 = (`NE+2)'(`NF2+1);
end
default: begin
Nf = 1'bx;
NfPlus1 = 1'bx;
end
endcase endcase
end else if (`FPSIZES == 4) begin end else if (`FPSIZES == 4) begin
always_comb always_comb
case (FmtM) case (FmtM)
2'h3: begin 2'h3: Nf = (`NE+2)'(`Q_NF);
Nf = (`NE+2)'(`Q_NF); 2'h1: Nf = (`NE+2)'(`D_NF);
NfPlus1 = (`NE+2)'(`Q_NF+1); 2'h0: Nf = (`NE+2)'(`S_NF);
end 2'h2: Nf = (`NE+2)'(`H_NF);
2'h1: begin
Nf = (`NE+2)'(`D_NF);
NfPlus1 = (`NE+2)'(`D_NF+1);
end
2'h0: begin
Nf = (`NE+2)'(`S_NF);
NfPlus1 = (`NE+2)'(`S_NF+1);
end
2'h2: begin
Nf = (`NE+2)'(`H_NF);
NfPlus1 = (`NE+2)'(`H_NF+1);
end
endcase endcase
end end
// if the result is denormalized // if the result is denormalized

View File

@ -30,27 +30,27 @@
`include "wally-config.vh" `include "wally-config.vh"
module fma( module fma(
input logic XSgnE, YSgnE, ZSgnE, // input's signs input logic Xs, Ys, Zs, // input's signs
input logic [`NE-1:0] XExpE, YExpE, ZExpE, // biased exponents in B(NE.0) format input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format
input logic [`NF:0] XManE, YManE, ZManE, // fractions in U(0.NF) format input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format
input logic XZeroE, YZeroE, ZZeroE, // is the input zero input logic XZeroE, YZeroE, ZZeroE, // is the input zero
input logic [2:0] FOpCtrlE, // 000 = fmadd (X*Y)+Z, 001 = fmsub (X*Y)-Z, 010 = fnmsub -(X*Y)+Z, 011 = fnmadd -(X*Y)-Z, 100 = fmul (X*Y) input logic [2:0] FOpCtrlE, // 000 = fmadd (X*Y)+Z, 001 = fmsub (X*Y)-Z, 010 = fnmsub -(X*Y)+Z, 011 = fnmadd -(X*Y)-Z, 100 = fmul (X*Y)
input logic [`FMTBITS-1:0] FmtE, // precision 1 = double 0 = single input logic [`FMTBITS-1:0] FmtE, // precision 1 = double 0 = single
output logic [`NE+1:0] ProdExpE, // X exponent + Y exponent - bias in B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign output logic [`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
output logic AddendStickyE, // sticky bit that is calculated during alignment output logic AddendStickyE, // sticky bit that is calculated during alignment
output logic KillProdE, // set the product to zero before addition if the product is too small to matter output logic KillProdE, // set the product to zero before addition if the product is too small to matter
output logic [3*`NF+5:0] SumE, // the positive sum output logic [3*`NF+5:0] Sm, // the positive sum
output logic NegSumE, // was the sum negitive output logic NegSumE, // was the sum negitive
output logic InvZE, // intert Z output logic InvA, // intert Z
output logic ZSgnEffE, // the modified Z sign output logic ZSgnEffE, // the modified Z sign
output logic PSgnE, // the product's sign output logic Ps, // the product's sign
output logic [$clog2(3*`NF+7)-1:0] FmaNormCntE // normalization shift cnt output logic [$clog2(3*`NF+7)-1:0] FmaNormCntE // normalization shift cnt
); );
logic [2*`NF+1:0] ProdManE; // 1.X frac * 1.Y frac in U(2.2Nf) format logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format
logic [3*`NF+5:0] AlignedAddendE; // Z aligned for addition in U(NF+5.2NF+1) logic [3*`NF+5:0] Am; // Z aligned for addition in U(NF+5.2NF+1)
logic [3*`NF+6:0] AlignedAddendInv; // aligned addend possibly inverted logic [3*`NF+6:0] AmInv; // aligned addend possibly inverted
logic [2*`NF+1:0] ProdManKilled; // the product's mantissa possibly killed logic [2*`NF+1:0] PmKilled; // the product's mantissa possibly killed
logic [3*`NF+6:0] PreSum, NegPreSum; // positive and negitve versions of the sum logic [3*`NF+6:0] PreSum, NegPreSum; // positive and negitve versions of the sum
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Calculate the product // Calculate the product
@ -62,43 +62,40 @@ module fma(
// calculate the product's exponent // calculate the product's exponent
expadd expadd(.FmtE, .XExpE, .YExpE, .XZeroE, .YZeroE, .ProdExpE); expadd expadd(.FmtE, .Xe, .Ye, .XZeroE, .YZeroE, .Pe);
// multiplication of the mantissa's // multiplication of the mantissa's
mult mult(.XManE, .YManE, .ProdManE); mult mult(.Xm, .Ym, .Pm);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Alignment shifter // Alignment shifter
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
align align(.ZExpE, .ZManE, .XZeroE, .YZeroE, .ZZeroE, .XExpE, .YExpE, align align(.Ze, .Zm, .XZeroE, .YZeroE, .ZZeroE, .Xe, .Ye,
.AlignedAddendE, .AddendStickyE, .KillProdE); .Am, .AddendStickyE, .KillProdE);
// calculate the signs and take the opperation into account // calculate the signs and take the opperation into account
sign sign(.FOpCtrlE, .XSgnE, .YSgnE, .ZSgnE, .PSgnE, .ZSgnEffE); sign sign(.FOpCtrlE, .Xs, .Ys, .Zs, .Ps, .ZSgnEffE);
// /////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////
// // Addition/LZA // // Addition/LZA
// /////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////
add add(.AlignedAddendE, .ProdManE, .PSgnE, .ZSgnEffE, .KillProdE, .AlignedAddendInv, .ProdManKilled, .NegSumE, .PreSum, .NegPreSum, .InvZE, .XZeroE, .YZeroE); add add(.Am, .Pm, .Ps, .ZSgnEffE, .KillProdE, .AmInv, .PmKilled, .NegSumE, .PreSum, .NegPreSum, .InvA, .XZeroE, .YZeroE, .Sm);
loa loa(.A(AlignedAddendInv+{(3*`NF+6)'(0),InvZE}), .P(ProdManKilled), .FmaNormCntE); loa loa(.A(AmInv+{(3*`NF+6)'(0),InvA}), .P(PmKilled), .FmaNormCntE);
// Choose the positive sum and accompanying LZA result.
assign SumE = NegSumE ? NegPreSum[3*`NF+5:0] : PreSum[3*`NF+5:0];
endmodule endmodule
module expadd( module expadd(
input logic [`FMTBITS-1:0] FmtE, // precision input logic [`FMTBITS-1:0] FmtE, // precision
input logic [`NE-1:0] XExpE, YExpE, // input exponents input logic [`NE-1:0] Xe, Ye, // input exponents
input logic XZeroE, YZeroE, // are the inputs zero input logic XZeroE, YZeroE, // are the inputs zero
output logic [`NE+1:0] ProdExpE // product's exponent B^(1023)NE+2 output logic [`NE+1:0] Pe // product's exponent B^(1023)NE+2
); );
// kill the exponent if the product is zero - either X or Y is 0 // kill the exponent if the product is zero - either X or Y is 0
assign ProdExpE = ({2'b0, XExpE} + {2'b0, YExpE} - {2'b0, (`NE)'(`BIAS)})&{`NE+2{~(XZeroE|YZeroE)}}; assign Pe = ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)})&{`NE+2{~(XZeroE|YZeroE)}};
endmodule endmodule
@ -107,10 +104,10 @@ endmodule
module mult( module mult(
input logic [`NF:0] XManE, YManE, input logic [`NF:0] Xm, Ym,
output logic [2*`NF+1:0] ProdManE output logic [2*`NF+1:0] Pm
); );
assign ProdManE = XManE * YManE; assign Pm = Xm * Ym;
endmodule endmodule
@ -122,8 +119,8 @@ endmodule
module sign( module sign(
input logic [2:0] FOpCtrlE, // precision input logic [2:0] FOpCtrlE, // precision
input logic XSgnE, YSgnE, ZSgnE, // are the inputs denormalized input logic Xs, Ys, Zs, // are the inputs denormalized
output logic PSgnE, // the product's sign - takes opperation into account output logic Ps, // the product's sign - takes opperation into account
output logic ZSgnEffE // Z sign used in fma - takes opperation into account output logic ZSgnEffE // Z sign used in fma - takes opperation into account
); );
@ -131,9 +128,9 @@ module sign(
// Negate product's sign if FNMADD or FNMSUB // Negate product's sign if FNMADD or FNMSUB
// flip is negation opperation // flip is negation opperation
assign PSgnE = XSgnE ^ YSgnE ^ (FOpCtrlE[1]&~FOpCtrlE[2]); assign Ps = Xs ^ Ys ^ (FOpCtrlE[1]&~FOpCtrlE[2]);
// flip if subtraction // flip if subtraction
assign ZSgnEffE = ZSgnE^FOpCtrlE[0]; assign ZSgnEffE = Zs^FOpCtrlE[0];
endmodule endmodule
@ -145,10 +142,10 @@ endmodule
module align( module align(
input logic [`NE-1:0] XExpE, YExpE, ZExpE, // biased exponents in B(NE.0) format input logic [`NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
input logic [`NF:0] ZManE, // fractions in U(0.NF) format] input logic [`NF:0] Zm, // fractions in U(0.NF) format]
input logic XZeroE, YZeroE, ZZeroE, // is the input zero input logic XZeroE, YZeroE, ZZeroE, // is the input zero
output logic [3*`NF+5:0] AlignedAddendE, // Z aligned for addition in U(NF+5.2NF+1) output logic [3*`NF+5:0] Am, // Z aligned for addition in U(NF+5.2NF+1)
output logic AddendStickyE, // Sticky bit calculated from the aliged addend output logic AddendStickyE, // Sticky bit calculated from the aliged addend
output logic KillProdE // should the product be set to zero output logic KillProdE // should the product be set to zero
); );
@ -156,6 +153,7 @@ module align(
logic [`NE+1:0] AlignCnt; // how far to shift the addend to align with the product in Q(NE+2.0) format logic [`NE+1:0] AlignCnt; // how far to shift the addend to align with the product in Q(NE+2.0) format
logic [4*`NF+5:0] ZManShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1) logic [4*`NF+5:0] ZManShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1)
logic [4*`NF+5:0] ZManPreShifted; // input to the alignment shifter U(NF+5.3NF+1) logic [4*`NF+5:0] ZManPreShifted; // input to the alignment shifter U(NF+5.3NF+1)
logic KillZ;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Alignment shifter // Alignment shifter
@ -164,15 +162,19 @@ module align(
// determine the shift count for alignment // determine the shift count for alignment
// - negitive means Z is larger, so shift Z left // - negitive means Z is larger, so shift Z left
// - positive means the product is larger, so shift Z right // - positive means the product is larger, so shift Z right
// This could have been done using ProdExpE, but AlignCnt is on the critical path so we replicate logic for speed // This could have been done using Pe, but AlignCnt is on the critical path so we replicate logic for speed
assign AlignCnt = XZeroE|YZeroE ? -(`NE+2)'($unsigned(1)) : {2'b0, XExpE} + {2'b0, YExpE} - {2'b0, (`NE)'(`BIAS)} + (`NE+2)'(`NF)+3 - {2'b0, ZExpE}; assign AlignCnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)} + (`NE+2)'(`NF+3) - {2'b0, Ze};
// Defualt Addition without shifting // Defualt Addition without shifting
// | 54'b0 | 106'b(product) | 2'b0 | // | 54'b0 | 106'b(product) | 2'b0 |
// | addnend | // | addnend |
// the 1'b0 before the added is because the product's mantissa has two bits before the binary point (xx.xxxxxxxxxx...) // the 1'b0 before the added is because the product's mantissa has two bits before the binary point (xx.xxxxxxxxxx...)
assign ZManPreShifted = {ZManE,(3*`NF+5)'(0)}; assign ZManPreShifted = {Zm,(3*`NF+5)'(0)};
assign KillProdE = AlignCnt[`NE+1]|XZeroE|YZeroE;
assign KillZ = $signed(AlignCnt)>$signed((`NE+2)'(3)*(`NE+2)'(`NF)+(`NE+2)'(5));
always_comb always_comb
begin begin
@ -180,34 +182,31 @@ module align(
// | 54'b0 | 106'b(product) | 2'b0 | // | 54'b0 | 106'b(product) | 2'b0 |
// | addnend | // | addnend |
if ($signed(AlignCnt) < $signed((`NE+2)'(0))) begin if (KillProdE) begin
KillProdE = 1;
ZManShifted = ZManPreShifted; ZManShifted = ZManPreShifted;
AddendStickyE = ~(XZeroE|YZeroE); AddendStickyE = ~(XZeroE|YZeroE);
// If the Addend is shifted right
// | 54'b0 | 106'b(product) | 2'b0 |
// | addnend |
end else if ($signed(AlignCnt)<=$signed((`NE+2)'(3)*(`NE+2)'(`NF)+(`NE+2)'(5))) begin
KillProdE = 0;
ZManShifted = ZManPreShifted >> AlignCnt;
AddendStickyE = |(ZManShifted[`NF-1:0]);
// If the addend is too small to effect the addition // If the addend is too small to effect the addition
// - The addend has to shift two past the end of the addend to be considered too small // - The addend has to shift two past the end of the addend to be considered too small
// - The 2 extra bits are needed for rounding // - The 2 extra bits are needed for rounding
// | 54'b0 | 106'b(product) | 2'b0 | // | 54'b0 | 106'b(product) | 2'b0 |
// | addnend | // | addnend |
end else begin end else if (KillZ) begin
KillProdE = 0;
ZManShifted = 0; ZManShifted = 0;
AddendStickyE = ~ZZeroE; AddendStickyE = ~ZZeroE;
// If the Addend is shifted right
// | 54'b0 | 106'b(product) | 2'b0 |
// | addnend |
end else begin
ZManShifted = ZManPreShifted >> AlignCnt;
AddendStickyE = |(ZManShifted[`NF-1:0]);
end end
end end
assign AlignedAddendE = ZManShifted[4*`NF+5:`NF]; assign Am = ZManShifted[4*`NF+5:`NF];
endmodule endmodule
@ -218,15 +217,16 @@ endmodule
module add( module add(
input logic [3*`NF+5:0] AlignedAddendE, // Z aligned for addition in U(NF+5.2NF+1) input logic [3*`NF+5:0] Am, // Z aligned for addition in U(NF+5.2NF+1)
input logic [2*`NF+1:0] ProdManE, // the product's mantissa input logic [2*`NF+1:0] Pm, // the product's mantissa
input logic PSgnE, ZSgnEffE,// the product and modified Z signs input logic Ps, ZSgnEffE,// the product and modified Z signs
input logic KillProdE, // should the product be set to 0 input logic KillProdE, // should the product be set to 0
input logic XZeroE, YZeroE, // is the input zero input logic XZeroE, YZeroE, // is the input zero
output logic [3*`NF+6:0] AlignedAddendInv, // aligned addend possibly inverted output logic [3*`NF+6:0] AmInv, // aligned addend possibly inverted
output logic [2*`NF+1:0] ProdManKilled, // the product's mantissa possibly killed output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed
output logic NegSumE, // was the sum negitive output logic NegSumE, // was the sum negitive
output logic InvZE, // do you invert Z output logic InvA, // do you invert Z
output logic [3*`NF+5:0] Sm, // the positive sum
output logic [3*`NF+6:0] PreSum, NegPreSum// possibly negitive sum output logic [3*`NF+6:0] PreSum, NegPreSum// possibly negitive sum
); );
@ -237,23 +237,25 @@ module add(
// Negate Z when doing one of the following opperations: // Negate Z when doing one of the following opperations:
// -prod + Z // -prod + Z
// prod - Z // prod - Z
assign InvZE = ZSgnEffE ^ PSgnE; assign InvA = ZSgnEffE ^ Ps;
// Choose an inverted or non-inverted addend - the one has to be added now for the LZA // Choose an inverted or non-inverted addend - the one has to be added now for the LZA
assign AlignedAddendInv = InvZE ? {1'b1, ~AlignedAddendE} : {1'b0, AlignedAddendE}; assign AmInv = InvA ? {1'b1, ~Am} : {1'b0, Am};
// Kill the product if the product is too small to effect the addition (determined in fma1.sv) // Kill the product if the product is too small to effect the addition (determined in fma1.sv)
assign ProdManKilled = ProdManE&{2*`NF+2{~KillProdE}}; assign PmKilled = Pm&{2*`NF+2{~KillProdE}};
// Do the addition // Do the addition
// - calculate a positive and negitive sum in parallel // - calculate a positive and negitive sum in parallel
assign PreSum = AlignedAddendInv + {{`NF+3{1'b0}}, ProdManKilled, 2'b0} + {{3*`NF+6{1'b0}}, InvZE}; assign PreSum = {{`NF+3{1'b0}}, PmKilled, 2'b0} + AmInv + {{3*`NF+6{1'b0}}, InvA};
assign NegPreSum = XZeroE|YZeroE|KillProdE ? {1'b0, AlignedAddendE} : {1'b0, AlignedAddendE} + {{`NF+3{1'b1}}, ~ProdManKilled, 2'b0} + {(3*`NF+7)'(4)}; assign NegPreSum = {1'b0, Am} + {{`NF+3{1'b1}}, ~PmKilled, 2'b0} + {(3*`NF+7)'(4)};
// Is the sum negitive // Is the sum negitive
assign NegSumE = PreSum[3*`NF+6]; assign NegSumE = PreSum[3*`NF+6];
// Choose the positive sum and accompanying LZA result.
assign Sm = NegSumE ? NegPreSum[3*`NF+5:0] : PreSum[3*`NF+5:0];
endmodule endmodule

View File

@ -27,7 +27,7 @@ module fmashiftcalc(
// calculate the sum's exponent // calculate the sum's exponent
assign NormSumExp = KillProdM ? {2'b0, ZExpM[`NE-1:1], ZExpM[0]&~ZDenormM} : ProdExpM + -{{`NE+2-$unsigned($clog2(3*`NF+7)){1'b0}}, FmaNormCntM} - 1 + (`NE+2)'(`NF+4); assign NormSumExp = KillProdM ? {2'b0, ZExpM[`NE-1:1], ZExpM[0]&~ZDenormM} : ProdExpM + -{{`NE+2-$unsigned($clog2(3*`NF+7)){1'b0}}, FmaNormCntM} - 1 + (`NE+2)'(`NF+4);
//convert the sum's exponent into the propper percision //convert the sum's exponent into the proper percision
if (`FPSIZES == 1) begin if (`FPSIZES == 1) begin
assign ConvNormSumExp = NormSumExp; assign ConvNormSumExp = NormSumExp;
@ -105,7 +105,7 @@ module fmashiftcalc(
2'h1: PreResultDenorm = Sum1LEZ & Sum1GEFL & ~SumZero; 2'h1: PreResultDenorm = Sum1LEZ & Sum1GEFL & ~SumZero;
2'h0: PreResultDenorm = Sum2LEZ & Sum2GEFL & ~SumZero; 2'h0: PreResultDenorm = Sum2LEZ & Sum2GEFL & ~SumZero;
2'h2: PreResultDenorm = Sum3LEZ & Sum3GEFL & ~SumZero; 2'h2: PreResultDenorm = Sum3LEZ & Sum3GEFL & ~SumZero;
endcase endcase // *** remove checking to see if it's underflowed and only check for less than zero for denorm checking
end end
end end

View File

@ -110,7 +110,7 @@ module fpu (
logic [`NE+1:0] ProdExpE, ProdExpM; logic [`NE+1:0] ProdExpE, ProdExpM;
logic AddendStickyE, AddendStickyM; logic AddendStickyE, AddendStickyM;
logic KillProdE, KillProdM; logic KillProdE, KillProdM;
logic InvZE, InvZM; logic InvAE, InvAM;
logic NegSumE, NegSumM; logic NegSumE, NegSumM;
logic ZSgnEffE, ZSgnEffM; logic ZSgnEffE, ZSgnEffM;
logic PSgnE, PSgnM; logic PSgnE, PSgnM;
@ -249,10 +249,10 @@ module fpu (
.XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE); .XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE);
// fma - does multiply, add, and multiply-add instructions // fma - does multiply, add, and multiply-add instructions
fma fma (.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE, fma fma (.Xs(XSgnE), .Ys(YSgnE), .Zs(ZSgnE), .Xe(XExpE), .Ye(YExpE), .Ze(ZExpE),
.XManE, .YManE, .ZManE, .XZeroE, .YZeroE, .ZZeroE, .Xm(XManE), .Ym(YManE), .Zm(ZManE), .XZeroE, .YZeroE, .ZZeroE,
.FOpCtrlE, .FmtE, .SumE, .NegSumE, .InvZE, .FmaNormCntE, .FOpCtrlE, .FmtE, .Sm(SumE), .NegSumE, .InvA(InvAE), .FmaNormCntE,
.ZSgnEffE, .PSgnE, .ProdExpE, .AddendStickyE, .KillProdE); .ZSgnEffE, .Ps(PSgnE), .Pe(ProdExpE), .AddendStickyE, .KillProdE);
// fpdivsqrt using Goldschmidt's iteration // fpdivsqrt using Goldschmidt's iteration
if(`FLEN == 64) begin if(`FLEN == 64) begin
@ -351,8 +351,8 @@ module fpu (
flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SumE, SumM); flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SumE, SumM);
flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, ProdExpE, ProdExpM); flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, ProdExpE, ProdExpM);
flopenrc #($clog2(3*`NF+7)+6) EMRegFma4(clk, reset, FlushM, ~StallM, flopenrc #($clog2(3*`NF+7)+6) EMRegFma4(clk, reset, FlushM, ~StallM,
{AddendStickyE, KillProdE, InvZE, FmaNormCntE, NegSumE, ZSgnEffE, PSgnE}, {AddendStickyE, KillProdE, InvAE, FmaNormCntE, NegSumE, ZSgnEffE, PSgnE},
{AddendStickyM, KillProdM, InvZM, FmaNormCntM, NegSumM, ZSgnEffM, PSgnM}); {AddendStickyM, KillProdM, InvAM, FmaNormCntM, NegSumM, ZSgnEffM, PSgnM});
flopenrc #(`NE+`LOGCVTLEN+`CVTLEN+4) EMRegCvt(clk, reset, FlushM, ~StallM, flopenrc #(`NE+`LOGCVTLEN+`CVTLEN+4) EMRegCvt(clk, reset, FlushM, ~StallM,
{CvtCalcExpE, CvtShiftAmtE, CvtResDenormUfE, CvtResSgnE, IntZeroE, CvtLzcInE}, {CvtCalcExpE, CvtShiftAmtE, CvtResDenormUfE, CvtResSgnE, IntZeroE, CvtLzcInE},
{CvtCalcExpM, CvtShiftAmtM, CvtResDenormUfM, CvtResSgnM, IntZeroM, CvtLzcInM}); {CvtCalcExpM, CvtShiftAmtM, CvtResDenormUfM, CvtResSgnM, IntZeroM, CvtLzcInM});
@ -374,7 +374,7 @@ module fpu (
postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, .EarlyTermShiftDiv2M, postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, .EarlyTermShiftDiv2M,
.AddendStickyM, .KillProdM, .XZeroM, .YZeroM, .ZZeroM, .XInfM, .YInfM, .Quot, .AddendStickyM, .KillProdM, .XZeroM, .YZeroM, .ZZeroM, .XInfM, .YInfM, .Quot,
.ZInfM, .XNaNM, .YNaNM, .ZNaNM, .XSNaNM, .YSNaNM, .ZSNaNM, .SumM, .DivCalcExpM, .ZInfM, .XNaNM, .YNaNM, .ZNaNM, .XSNaNM, .YSNaNM, .ZSNaNM, .SumM, .DivCalcExpM,
.NegSumM, .InvZM, .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, .DivNegStickyM, .NegSumM, .InvZM(InvAM), .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, .DivNegStickyM,
.CvtCalcExpM, .CvtResDenormUfM,.CvtShiftAmtM, .CvtResSgnM, .FWriteIntM, .DivStickyM, .CvtCalcExpM, .CvtResDenormUfM,.CvtShiftAmtM, .CvtResSgnM, .FWriteIntM, .DivStickyM,
.CvtLzcInM, .IntZeroM, .PostProcSelM, .PostProcResM, .PostProcFlgM, .FCvtIntResM); .CvtLzcInM, .IntZeroM, .PostProcSelM, .PostProcResM, .PostProcFlgM, .FCvtIntResM);

View File

@ -109,6 +109,7 @@ module postprocess(
// conversion signals // conversion signals
logic [`CVTLEN+`NF:0] CvtShiftIn; // number to be shifted logic [`CVTLEN+`NF:0] CvtShiftIn; // number to be shifted
logic [1:0] NegResMSBS; logic [1:0] NegResMSBS;
logic [`XLEN+1:0] NegRes;
logic CvtResUf; logic CvtResUf;
// readability signals // readability signals
logic Mult; // multiply opperation logic Mult; // multiply opperation
@ -166,7 +167,7 @@ module postprocess(
ShiftAmt = {{$clog2(`NORMSHIFTSZ)-$clog2(`CVTLEN+1){1'b0}}, CvtShiftAmtM}; ShiftAmt = {{$clog2(`NORMSHIFTSZ)-$clog2(`CVTLEN+1){1'b0}}, CvtShiftAmtM};
ShiftIn = {CvtShiftIn, {`NORMSHIFTSZ-`CVTLEN-`NF-1{1'b0}}}; ShiftIn = {CvtShiftIn, {`NORMSHIFTSZ-`CVTLEN-`NF-1{1'b0}}};
end end
2'b01: begin //div ***prob can take out 2'b01: begin //div
ShiftAmt = DivShiftAmt; ShiftAmt = DivShiftAmt;
ShiftIn = DivShiftIn; ShiftIn = DivShiftIn;
end end
@ -201,9 +202,11 @@ module postprocess(
// Sign calculation // Sign calculation
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
resultsign resultsign(.FrmM, .PSgnM, .ZSgnEffM, .InvZM, .SumExp, .Round, .Sticky, resultsign resultsign(.FrmM, .PSgnM, .ZSgnEffM, .SumExp, .Round, .Sticky,
.FmaOp, .DivOp, .CvtOp, .ZInfM, .InfIn, .NegSumM, .SumZero, .Mult, .FmaOp, .ZInfM, .InfIn, .SumZero, .Mult, .RoundSgn, .ResSgn);
.XSgnM, .YSgnM, .CvtResSgnM, .RoundSgn, .ResSgn);
roundsign roundsign(.PSgnM, .ZSgnEffM, .InvZM, .FmaOp, .DivOp, .CvtOp, .NegSumM,
.XSgnM, .YSgnM, .CvtResSgnM, .RoundSgn);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Flags // Flags
@ -219,10 +222,11 @@ module postprocess(
// Select the result // Select the result
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
resultselect resultselect(.XSgnM, .ZExpM, .XManM, .YManM, .ZManM, .ZDenormM, .ZZeroM, .XZeroM, .IntInvalid, negateintres negateintres(.XSgnM, .Shifted, .Signed, .Int64, .Plus1, .NegResMSBS, .NegRes);
.IntZeroM, .FrmM, .OutFmt, .AddendStickyM, .KillProdM, .XNaNM, .YNaNM, .ZNaNM, .RoundAdd, .CvtResUf, resultselect resultselect(.XSgnM, .XManM, .YManM, .ZManM, .XZeroM, .IntInvalid,
.NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .NegResMSBS, .IntZeroM, .FrmM, .OutFmt, .XNaNM, .YNaNM, .ZNaNM, .CvtResUf,
.NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .NegRes,
.XInfM, .YInfM, .DivOp, .XInfM, .YInfM, .DivOp,
.DivByZero, .FullResExp, .Shifted, .CvtCalcExpM, .ResSgn, .ResExp, .ResFrac, .PostProcResM, .FCvtIntResM); .DivByZero, .FullResExp, .CvtCalcExpM, .ResSgn, .ResExp, .ResFrac, .PostProcResM, .FCvtIntResM);
endmodule endmodule

View File

@ -1,45 +1,38 @@
`include "wally-config.vh" `include "wally-config.vh"
module resultselect( module resultselect(
input logic XSgnM, // input signs input logic XSgnM, // input signs
input logic [`NE-1:0] ZExpM, // input exponents input logic [`NF:0] XManM, YManM, ZManM, // input mantissas
input logic [`NF:0] XManM, YManM, ZManM, // input mantissas input logic XNaNM, YNaNM, ZNaNM, // inputs are NaN
input logic XNaNM, YNaNM, ZNaNM, // inputs are NaN input logic [2:0] FrmM, // 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 [2:0] FrmM, // 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] OutFmt, // output format
input logic [`FMTBITS-1:0] OutFmt, // output format input logic InfIn,
input logic InfIn, input logic XInfM, YInfM,
input logic XInfM, YInfM, input logic XZeroM,
input logic XZeroM, ZZeroM, input logic IntZeroM,
input logic IntZeroM, input logic NaNIn,
input logic NaNIn, input logic IntToFp,
input logic IntToFp, input logic Int64,
input logic Int64, input logic Signed,
input logic Signed, input logic CvtOp,
input logic CvtOp, input logic DivOp,
input logic DivOp, input logic FmaOp,
input logic FmaOp, input logic Plus1,
input logic [`NORMSHIFTSZ-1:0] Shifted, // is the sum zero input logic DivByZero,
input logic Plus1, input logic [`NE:0] CvtCalcExpM, // the calculated expoent
input logic DivByZero, input logic ResSgn, // the res's sign
input logic [`NE:0] CvtCalcExpM, // the calculated expoent input logic IntInvalid, Invalid, Overflow, // flags
input logic AddendStickyM, // sticky bit that is calculated during alignment input logic CvtResUf,
input logic KillProdM, // set the product to zero before addition if the product is too small to matter input logic [`NE-1:0] ResExp, // Res exponent
input logic ZDenormM, // is the original precision denormalized input logic [`NE+1:0] FullResExp, // Res exponent
input logic ResSgn, // the res's sign input logic [`NF-1:0] ResFrac, // Res fraction
input logic [`FLEN:0] RoundAdd, // how much to add to the res input logic [`XLEN+1:0] NegRes, // the negation of the result
input logic IntInvalid, Invalid, Overflow, // flags output logic [`FLEN-1:0] PostProcResM, // final res
input logic CvtResUf, output logic [`XLEN-1:0] FCvtIntResM // final res
input logic [`NE-1:0] ResExp, // Res exponent
input logic [`NE+1:0] FullResExp, // Res exponent
input logic [`NF-1:0] ResFrac, // Res fraction
output logic [`FLEN-1:0] PostProcResM, // final res
output logic [1:0] NegResMSBS,
output logic [`XLEN-1:0] FCvtIntResM // final res
); );
logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, UfRes, NormRes; // possible results logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, UfRes, NormRes; // possible results
logic OfResMax; logic OfResMax;
logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output
logic [`XLEN+1:0] NegRes; // the negation of the result
logic KillRes; logic KillRes;
logic SelOfRes; logic SelOfRes;
@ -255,12 +248,6 @@ module resultselect(
XSgnM&~XNaNM ? {`XLEN{1'b0}} : // unsigned negitive XSgnM&~XNaNM ? {`XLEN{1'b0}} : // unsigned negitive
{`XLEN{1'b1}};// unsigned positive {`XLEN{1'b1}};// unsigned positive
// round and negate the positive res if needed
assign NegRes = XSgnM ? -({2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1};
//*** false critical path probably
assign NegResMSBS = Signed ? Int64 ? NegRes[`XLEN:`XLEN-1] : NegRes[32:31] :
Int64 ? NegRes[`XLEN+1:`XLEN] : NegRes[33:32];
// select the integer output // select the integer output
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res // - if the input is invalid (out of bounds NaN or Inf) then output overflow res

View File

@ -3,31 +3,21 @@
module resultsign( module resultsign(
input logic [2:0] FrmM, input logic [2:0] FrmM,
input logic PSgnM, ZSgnEffM, input logic PSgnM, ZSgnEffM,
input logic InvZM,
input logic XSgnM,
input logic YSgnM,
input logic ZInfM, input logic ZInfM,
input logic InfIn, input logic InfIn,
input logic NegSumM,
input logic FmaOp, input logic FmaOp,
input logic DivOp,
input logic CvtOp,
input logic [`NE+1:0] SumExp, input logic [`NE+1:0] SumExp,
input logic SumZero, input logic SumZero,
input logic Mult, input logic Mult,
input logic Round, input logic Round,
input logic Sticky, input logic Sticky,
input logic CvtResSgnM, input logic RoundSgn,
output logic RoundSgn,
output logic ResSgn output logic ResSgn
); );
logic ZeroSgn; logic ZeroSgn;
logic InfSgn; logic InfSgn;
logic FmaResSgn;
logic FmaResSgnTmp;
logic Underflow; logic Underflow;
logic DivSgn;
// logic ResultSgnTmp; // logic ResultSgnTmp;
// Determine the sign if the sum is zero // Determine the sign if the sum is zero
@ -42,14 +32,7 @@ module resultsign(
// if p - z is the Sum negitive // if p - z is the Sum negitive
// if -p + z is the Sum positive // if -p + z is the Sum positive
// if -p - z then the Sum is negitive // if -p - z then the Sum is negitive
assign FmaResSgnTmp = InvZM&(ZSgnEffM)&NegSumM | InvZM&PSgnM&~NegSumM | (ZSgnEffM&PSgnM);
assign InfSgn = ZInfM ? ZSgnEffM : PSgnM; assign InfSgn = ZInfM ? ZSgnEffM : PSgnM;
assign FmaResSgn = InfIn ? InfSgn : SumZero ? ZeroSgn : FmaResSgnTmp; assign ResSgn = InfIn&FmaOp ? InfSgn : SumZero&FmaOp ? ZeroSgn : RoundSgn;
assign DivSgn = XSgnM^YSgnM;
// Sign for rounding calulation
assign RoundSgn = (FmaResSgnTmp&FmaOp) | (CvtResSgnM&CvtOp) | (DivSgn&DivOp);
assign ResSgn = (FmaResSgn&FmaOp) | (CvtResSgnM&CvtOp) | (DivSgn&DivOp);
endmodule endmodule

View File

@ -61,15 +61,15 @@ module testbenchfp;
// in-between FMA signals // in-between FMA signals
logic Mult; logic Mult;
logic [`NE+1:0] ProdExpE; logic [`NE+1:0] Pe;
logic AddendStickyE; logic AddendStickyE;
logic KillProdE; logic KillProdE;
logic [$clog2(3*`NF+7)-1:0] FmaNormCntE; logic [$clog2(3*`NF+7)-1:0] FmaNormCntE;
logic [3*`NF+5:0] SumE; logic [3*`NF+5:0] Sm;
logic InvZE; logic InvZE;
logic NegSumE; logic NegSumE;
logic ZSgnEffE; logic ZSgnEffE;
logic PSgnE; logic Ps;
logic DivSticky; logic DivSticky;
logic DivNegSticky; logic DivNegSticky;
logic [`NE+1:0] DivCalcExp; logic [`NE+1:0] DivCalcExp;
@ -637,12 +637,12 @@ module testbenchfp;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// instantiate devices under test // instantiate devices under test
fma fma(.XSgnE(XSgn), .YSgnE(YSgn), .ZSgnE(ZSgn), fma fma(.Xs(XSgn), .Ys(YSgn), .Zs(ZSgn),
.XExpE(XExp), .YExpE(YExp), .ZExpE(ZExp), .Xe(XExp), .Ye(YExp), .Ze(ZExp),
.XManE(XMan), .YManE(YMan), .ZManE(ZMan), .Xm(XMan), .Ym(YMan), .Zm(ZMan),
.XZeroE(XZero), .YZeroE(YZero), .ZZeroE(ZZero), .XZeroE(XZero), .YZeroE(YZero), .ZZeroE(ZZero),
.FOpCtrlE(OpCtrlVal), .FmtE(ModFmt), .SumE, .NegSumE, .InvZE, .FmaNormCntE, .ZSgnEffE, .PSgnE, .FOpCtrlE(OpCtrlVal), .FmtE(ModFmt), .Sm, .NegSumE, .InvZE, .FmaNormCntE, .ZSgnEffE, .Ps,
.ProdExpE, .AddendStickyE, .KillProdE); .Pe, .AddendStickyE, .KillProdE);
postprocess postprocess(.XSgnM(XSgn), .YSgnM(YSgn), .PostProcSelM(UnitVal[1:0]), postprocess postprocess(.XSgnM(XSgn), .YSgnM(YSgn), .PostProcSelM(UnitVal[1:0]),
.ZExpM(ZExp), .ZDenormM(ZDenorm), .FOpCtrlM(OpCtrlVal), .Quot, .DivCalcExpM(DivCalcExp), .ZExpM(ZExp), .ZDenormM(ZDenorm), .FOpCtrlM(OpCtrlVal), .Quot, .DivCalcExpM(DivCalcExp),
@ -651,8 +651,8 @@ module testbenchfp;
.XZeroM(XZero), .YZeroM(YZero), .ZZeroM(ZZero), .CvtShiftAmtM(CvtShiftAmtE), .XZeroM(XZero), .YZeroM(YZero), .ZZeroM(ZZero), .CvtShiftAmtM(CvtShiftAmtE),
.XInfM(XInf), .YInfM(YInf), .ZInfM(ZInf), .CvtResSgnM(CvtResSgnE), .FWriteIntM(WriteIntVal), .XInfM(XInf), .YInfM(YInf), .ZInfM(ZInf), .CvtResSgnM(CvtResSgnE), .FWriteIntM(WriteIntVal),
.XSNaNM(XSNaN), .YSNaNM(YSNaN), .ZSNaNM(ZSNaN), .CvtLzcInM(CvtLzcInE), .IntZeroM(IntZeroE), .XSNaNM(XSNaN), .YSNaNM(YSNaN), .ZSNaNM(ZSNaN), .CvtLzcInM(CvtLzcInE), .IntZeroM(IntZeroE),
.KillProdM(KillProdE), .AddendStickyM(AddendStickyE), .ProdExpM(ProdExpE), .KillProdM(KillProdE), .AddendStickyM(AddendStickyE), .ProdExpM(Pe),
.SumM(SumE), .NegSumM(NegSumE), .InvZM(InvZE), .FmaNormCntM(FmaNormCntE), .EarlyTermShiftDiv2M(EarlyTermShiftDiv2), .ZSgnEffM(ZSgnEffE), .PSgnM(PSgnE), .FmtM(ModFmt), .FrmM(FrmVal), .SumM(Sm), .NegSumM(NegSumE), .InvZM(InvZE), .FmaNormCntM(FmaNormCntE), .EarlyTermShiftDiv2M(EarlyTermShiftDiv2), .ZSgnEffM(ZSgnEffE), .PSgnM(Ps), .FmtM(ModFmt), .FrmM(FrmVal),
.PostProcFlgM(Flg), .PostProcResM(FpRes), .FCvtIntResM(IntRes)); .PostProcFlgM(Flg), .PostProcResM(FpRes), .FCvtIntResM(IntRes));
fcvt fcvt (.XSgnE(XSgn), .XExpE(XExp), .XManE(XMan), .ForwardedSrcAE(SrcA), .FWriteIntE(WriteIntVal), fcvt fcvt (.XSgnE(XSgn), .XExpE(XExp), .XManE(XMan), .ForwardedSrcAE(SrcA), .FWriteIntE(WriteIntVal),