From c24e81c57f4ff071b85d88c5fccecfad2d988a20 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 6 Apr 2023 21:42:34 -0700 Subject: [PATCH] Division cleanup --- src/fpu/fdivsqrt/fdivsqrtpreproc.sv | 66 ++++++++++++++++------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv index d24b7238..a00d8266 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv @@ -54,21 +54,21 @@ module fdivsqrtpreproc ( logic [`DIVb:0] PreSqrtX; logic [`DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed logic [`NE+1:0] QeE; // Quotient Exponent (FP only) - logic [`DIVb-1:0] IFNormLenX, IFNormLenD; // Correctly-sized inputs for iterator + logic [`DIVb-1:0] IFX, IFD; // Correctly-sized inputs for iterator, selected from int or fp input logic [`DIVBLEN:0] mE, ell; // Leading zeros of inputs logic NumerZeroE; // Numerator is zero (X or A) logic AZeroE, BZeroE; // A or B is Zero for integer division + logic signedDiv; // signed division + logic NegQuotE; // Integer quotient is negative + logic AsE, BsE; // Signs of integer inputs + logic [`XLEN-1:0] AE; // input A after W64 adjustment if (`IDIV_ON_FPU) begin:intpreproc // Int Supported - logic signedDiv, NegQuotE; - logic AsE, BsE, ALTBE; - logic [`XLEN-1:0] AE, BE, PosA, PosB; - logic [`DIVBLEN:0] ZeroDiff, p; + logic [`XLEN-1:0] BE, PosA, PosB; // Extract inputs, signs, zero, depending on W64 mode if applicable assign signedDiv = ~Funct3E[0]; - assign NegQuotE = AsE ^ BsE; // Quotient is negative - + // Source handling if (`XLEN==64) begin // 64-bit, supports W64 mux2 #(64) amux(ForwardedSrcAE, {{32{ForwardedSrcAE[31] & signedDiv}}, ForwardedSrcAE[31:0]}, W64E, AE); @@ -81,14 +81,40 @@ module fdivsqrtpreproc ( assign BZeroE = ~(|BE); assign AsE = AE[`XLEN-1] & signedDiv; assign BsE = BE[`XLEN-1] & signedDiv; + assign NegQuotE = AsE ^ BsE; // Integer Quotient is negative // Force integer inputs to be postiive mux2 #(`XLEN) posamux(AE, -AE, AsE, PosA); mux2 #(`XLEN) posbmux(BE, -BE, BsE, PosB); // Select integer or floating point inputs - mux2 #(`DIVb) ifxmux({Xm, {(`DIVb-`NF-1){1'b0}}}, {PosA, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFNormLenX); - mux2 #(`DIVb) ifdmux({Ym, {(`DIVb-`NF-1){1'b0}}}, {PosB, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFNormLenD); + mux2 #(`DIVb) ifxmux({Xm, {(`DIVb-`NF-1){1'b0}}}, {PosA, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFX); + mux2 #(`DIVb) ifdmux({Ym, {(`DIVb-`NF-1){1'b0}}}, {PosB, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFD); + + + end else begin // Int not supported + assign IFX = {Xm, {(`DIVb-`NF-1){1'b0}}}; + assign IFD = {Ym, {(`DIVb-`NF-1){1'b0}}}; + end + + // count leading zeros for Subnorm FP and to normalize integer inputs + lzc #(`DIVb) lzcX (IFX, ell); + lzc #(`DIVb) lzcY (IFD, mE); + + // Normalization shift + assign XPreproc = IFX << (ell + {{`DIVBLEN{1'b0}}, 1'b1}); // *** try to remove this +1 + assign DPreproc = IFD << (mE + {{`DIVBLEN{1'b0}}, 1'b1}); + + // append leading 1 (for normal 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. + mux2 #(`DIVb+1) sqrtxmux({~XZeroE, XPreproc}, {1'b0, ~XZeroE, XPreproc[`DIVb-1:1]}, (Xe[0] ^ ell[0]), PreSqrtX); + assign DivX = {3'b000, ~NumerZeroE, XPreproc}; + + if (`IDIV_ON_FPU) begin:intrightshift // Int Supported + logic [`DIVBLEN:0] ZeroDiff, p; + logic ALTBE; // calculate number of fractional bits p assign ZeroDiff = mE - ell; // Difference in number of leading zeros @@ -127,34 +153,16 @@ module fdivsqrtpreproc ( flopen #(1) negquotreg(clk, IFDivStartE, NegQuotE, NegQuotM); flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM); flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM); - flopen #(`DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM); + flopen #(`DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM); flopen #(`DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM); flopen #(`XLEN) srcareg(clk, IFDivStartE, AE, AM); if (`XLEN==64) flopen #(1) w64reg(clk, IFDivStartE, W64E, W64M); - - end else begin // Int not supported - assign IFNormLenX = {Xm, {(`DIVb-`NF-1){1'b0}}}; - assign IFNormLenD = {Ym, {(`DIVb-`NF-1){1'b0}}}; + end else begin assign NumerZeroE = XZeroE; assign X = PreShiftX; end - // count leading zeros for Subnorm FP and to normalize integer inputs - lzc #(`DIVb) lzcX (IFNormLenX, ell); - lzc #(`DIVb) lzcY (IFNormLenD, mE); - - // Normalization shift - assign XPreproc = IFNormLenX << (ell + {{`DIVBLEN{1'b0}}, 1'b1}); // *** try to remove this +1 - assign DPreproc = IFNormLenD << (mE + {{`DIVBLEN{1'b0}}, 1'b1}); - - // append leading 1 (for normal 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. - mux2 #(`DIVb+1) sqrtxmux({~XZeroE, XPreproc}, {1'b0, ~XZeroE, XPreproc[`DIVb-1:1]}, (Xe[0] ^ ell[0]), PreSqrtX); - assign DivX = {3'b000, ~NumerZeroE, XPreproc}; - // Sqrt is initialized on step one as R(X-1), so depends on Radix if (`RADIX == 2) assign SqrtX = {3'b111, PreSqrtX}; else assign SqrtX = {2'b11, PreSqrtX, 1'b0};