mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Simplified IntDivNormShift
This commit is contained in:
		
							parent
							
								
									2903791820
								
							
						
					
					
						commit
						b315ead575
					
				@ -67,7 +67,7 @@ module fdivsqrt import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
  // Integer div/rem signals                                
 | 
					  // Integer div/rem signals                                
 | 
				
			||||||
  logic                        BZeroM;                       // Denominator is zero
 | 
					  logic                        BZeroM;                       // Denominator is zero
 | 
				
			||||||
  logic                        IntDivM;                      // Integer operation
 | 
					  logic                        IntDivM;                      // Integer operation
 | 
				
			||||||
  logic [P.DIVBLEN:0]          nM, mM;                       // Shift amounts
 | 
					  logic [P.DIVBLEN:0]          mM, IntDivNormShiftM;         // Shift amounts
 | 
				
			||||||
  logic                        ALTBM, AsM, BsM, W64M;        // Special handling for postprocessor
 | 
					  logic                        ALTBM, AsM, BsM, W64M;        // Special handling for postprocessor
 | 
				
			||||||
  logic [P.XLEN-1:0]           AM;                           // Original Numerator for postprocessor
 | 
					  logic [P.XLEN-1:0]           AM;                           // Original Numerator for postprocessor
 | 
				
			||||||
  logic                        ISpecialCaseE;                // Integer div/remainder special cases
 | 
					  logic                        ISpecialCaseE;                // Integer div/remainder special cases
 | 
				
			||||||
@ -77,7 +77,7 @@ module fdivsqrt import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
    .FmtE, .SqrtE, .XZeroE, .Funct3E, .UeM, .X, .D, .CyclesE,
 | 
					    .FmtE, .SqrtE, .XZeroE, .Funct3E, .UeM, .X, .D, .CyclesE,
 | 
				
			||||||
    // Int-specific 
 | 
					    // Int-specific 
 | 
				
			||||||
    .ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
 | 
					    .ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
 | 
				
			||||||
    .BZeroM, .nM, .mM, .AM, 
 | 
					    .BZeroM, .IntDivNormShiftM, .mM, .AM, 
 | 
				
			||||||
    .IntDivM, .W64M, .ALTBM, .AsM, .BsM);
 | 
					    .IntDivM, .W64M, .ALTBM, .AsM, .BsM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fdivsqrtfsm #(P) fdivsqrtfsm(                                  // FSM
 | 
					  fdivsqrtfsm #(P) fdivsqrtfsm(                                  // FSM
 | 
				
			||||||
@ -96,6 +96,6 @@ module fdivsqrt import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
    .SqrtE, .Firstun, .SqrtM, .SpecialCaseM, 
 | 
					    .SqrtE, .Firstun, .SqrtM, .SpecialCaseM, 
 | 
				
			||||||
    .UmM, .WZeroE, .DivStickyM, 
 | 
					    .UmM, .WZeroE, .DivStickyM, 
 | 
				
			||||||
    // Int-specific 
 | 
					    // Int-specific 
 | 
				
			||||||
    .nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM, 
 | 
					    .IntDivNormShiftM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM, 
 | 
				
			||||||
    .FIntDivResultM);
 | 
					    .FIntDivResultM);
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
				
			|||||||
@ -67,6 +67,13 @@ module fdivsqrtcycles import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
        P.Q_FMT: Nf = P.Q_NF;
 | 
					        P.Q_FMT: Nf = P.Q_NF;
 | 
				
			||||||
      endcase 
 | 
					      endcase 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Cycle logic
 | 
				
			||||||
 | 
					  // P.DIVCOPIES = k. P.LOGR = log(R) = r.  P.RK = rk.  
 | 
				
			||||||
 | 
					  // Integer division needs p fractional + r integer result bits
 | 
				
			||||||
 | 
					  // FP Division needs at least Nf fractional bits + 2 guard/round bits and one integer digit (LOG R integer bits) = Nf + 2 + r bits
 | 
				
			||||||
 | 
					  // FP Sqrt needs at least Nf fractional bits, 2 guard/round bits, and *** shift bits
 | 
				
			||||||
 | 
					  // The datapath produces rk bits per cycle, so Cycles = ceil (ResultBits / rk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  always_comb begin 
 | 
					  always_comb begin 
 | 
				
			||||||
    if (SqrtE) FPResultBits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1 rather than +2; is it related to DIVCOPIES logic below?
 | 
					    if (SqrtE) FPResultBits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1 rather than +2; is it related to DIVCOPIES logic below?
 | 
				
			||||||
    else       FPResultBits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
 | 
					    else       FPResultBits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
 | 
				
			||||||
@ -74,7 +81,7 @@ module fdivsqrtcycles import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
    if (P.IDIV_ON_FPU) ResultBits = IntDivE ? IntResultBits : FPResultBits;
 | 
					    if (P.IDIV_ON_FPU) ResultBits = IntDivE ? IntResultBits : FPResultBits;
 | 
				
			||||||
    else               ResultBits = FPResultBits;
 | 
					    else               ResultBits = FPResultBits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assign CyclesE = (ResultBits-1)/(P.RK) + 1;
 | 
					    assign CyclesE = (ResultBits-1)/(P.RK) + 1; // ceil (ResultBits/rk)
 | 
				
			||||||
  end 
 | 
					  end 
 | 
				
			||||||
  /* verilator lint_on WIDTH */
 | 
					  /* verilator lint_on WIDTH */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ module fdivsqrtpostproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
  input  logic               Firstun, SqrtM, SpecialCaseM, 
 | 
					  input  logic               Firstun, SqrtM, SpecialCaseM, 
 | 
				
			||||||
  input  logic [P.XLEN-1:0]  AM,
 | 
					  input  logic [P.XLEN-1:0]  AM,
 | 
				
			||||||
  input  logic               RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
 | 
					  input  logic               RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
 | 
				
			||||||
  input  logic [P.DIVBLEN:0] nM, mM,
 | 
					  input  logic [P.DIVBLEN:0] mM, IntDivNormShiftM,
 | 
				
			||||||
  output logic [P.DIVb:0]    UmM,               // result significand
 | 
					  output logic [P.DIVb:0]    UmM,               // result significand
 | 
				
			||||||
  output logic               WZeroE,
 | 
					  output logic               WZeroE,
 | 
				
			||||||
  output logic               DivStickyM,
 | 
					  output logic               DivStickyM,
 | 
				
			||||||
@ -111,7 +111,7 @@ module fdivsqrtpostproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Select quotient or remainder and do normalization shift
 | 
					    // Select quotient or remainder and do normalization shift
 | 
				
			||||||
    localparam DIVa        = (P.DIVb+1-P.XLEN); // used for idiv on fpu: Shift residual right by b - (XLEN-1) to put remainder in lsbs of integer result
 | 
					    localparam DIVa        = (P.DIVb+1-P.XLEN); // used for idiv on fpu: Shift residual right by b - (XLEN-1) to put remainder in lsbs of integer result
 | 
				
			||||||
    mux2 #(P.DIVBLEN+1) normshiftmux(((P.DIVBLEN+1)'(P.DIVb) - (nM * (P.DIVBLEN+1)'(P.LOGR))), (mM + (P.DIVBLEN+1)'(DIVa)), RemOpM, NormShiftM);
 | 
					    mux2 #(P.DIVBLEN+1) normshiftmux(IntDivNormShiftM, (mM + (P.DIVBLEN+1)'(DIVa)), RemOpM, NormShiftM);
 | 
				
			||||||
    mux2 #(P.DIVb+4)    presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM);
 | 
					    mux2 #(P.DIVb+4)    presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM);
 | 
				
			||||||
    assign PreIntResultM = $signed(PreResultM >>> NormShiftM); 
 | 
					    assign PreIntResultM = $signed(PreResultM >>> NormShiftM); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,7 @@ module fdivsqrtpreproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
  input  logic                 IntDivE, W64E,
 | 
					  input  logic                 IntDivE, W64E,
 | 
				
			||||||
  output logic                 ISpecialCaseE,
 | 
					  output logic                 ISpecialCaseE,
 | 
				
			||||||
  output logic [P.DURLEN-1:0]  CyclesE,
 | 
					  output logic [P.DURLEN-1:0]  CyclesE,
 | 
				
			||||||
  output logic [P.DIVBLEN:0]   nM, mM,
 | 
					  output logic [P.DIVBLEN:0]   mM, IntDivNormShiftM,
 | 
				
			||||||
  output logic                 ALTBM, IntDivM, W64M,
 | 
					  output logic                 ALTBM, IntDivM, W64M,
 | 
				
			||||||
  output logic                 AsM, BsM, BZeroM,
 | 
					  output logic                 AsM, BsM, BZeroM,
 | 
				
			||||||
  output logic [P.XLEN-1:0]    AM
 | 
					  output logic [P.XLEN-1:0]    AM
 | 
				
			||||||
@ -53,7 +53,7 @@ module fdivsqrtpreproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
  logic [P.DIVb+3:0]           DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed
 | 
					  logic [P.DIVb+3:0]           DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed
 | 
				
			||||||
  logic [P.NE+1:0]             UeE;                                 // Result Exponent (FP only)
 | 
					  logic [P.NE+1:0]             UeE;                                 // Result Exponent (FP only)
 | 
				
			||||||
  logic [P.DIVb:0]             IFX, IFD;                            // Correctly-sized inputs for iterator, selected from int or fp input
 | 
					  logic [P.DIVb:0]             IFX, IFD;                            // Correctly-sized inputs for iterator, selected from int or fp input
 | 
				
			||||||
  logic [P.DIVBLEN:0]          mE, nE, ell;                         // Leading zeros of inputs
 | 
					  logic [P.DIVBLEN:0]          mE, ell;                             // Leading zeros of inputs
 | 
				
			||||||
  logic [P.DIVBLEN:0]          IntResultBits;                       // bits in integer result
 | 
					  logic [P.DIVBLEN:0]          IntResultBits;                       // bits in integer result
 | 
				
			||||||
  logic                        NumerZeroE;                          // Numerator is zero (X or A)
 | 
					  logic                        NumerZeroE;                          // Numerator is zero (X or A)
 | 
				
			||||||
  logic                        AZeroE, BZeroE;                      // A or B is Zero for integer division
 | 
					  logic                        AZeroE, BZeroE;                      // A or B is Zero for integer division
 | 
				
			||||||
@ -126,27 +126,21 @@ module fdivsqrtpreproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
    mux2 #(P.DIVBLEN+1) pmux(ZeroDiff, '0, ALTBE, p);          
 | 
					    mux2 #(P.DIVBLEN+1) pmux(ZeroDiff, '0, ALTBE, p);          
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* verilator lint_off WIDTH */
 | 
					    /* verilator lint_off WIDTH */
 | 
				
			||||||
    assign IntResultBits = P.LOGR + p;                            // Total number of result bits (r integer bits plus p fractional bits)
 | 
					    assign IntResultBits = P.LOGR + p;  // Total number of result bits (r integer bits plus p fractional bits)
 | 
				
			||||||
    /* verilator lint_on WIDTH */
 | 
					    /* verilator lint_on WIDTH */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Integer special cases (terminate immediately)
 | 
					    // Integer special cases (terminate immediately)
 | 
				
			||||||
    assign ISpecialCaseE = BZeroE | ALTBE;
 | 
					    assign ISpecialCaseE = BZeroE | ALTBE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // calculate number of fractional digits nE and right shift amount RightShiftX to complete in discrete number of steps
 | 
					    // calculate right shift amount RightShiftX to complete in discrete number of steps
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (P.LOGRK > 0) begin // more than 1 bit per cycle
 | 
					    if (P.LOGRK > 0) begin // more than 1 bit per cycle
 | 
				
			||||||
      logic [P.LOGRK-1:0] IntTrunc, RightShiftX;
 | 
					      logic [P.LOGRK-1:0] IntTrunc, RightShiftX;
 | 
				
			||||||
      logic [P.DIVBLEN:0] IntSteps;
 | 
					      logic [P.DIVBLEN:0] IntSteps;
 | 
				
			||||||
      /* verilator lint_off WIDTH */
 | 
					      /* verilator lint_offf WIDTH */
 | 
				
			||||||
      // n = k*ceil((r+p)/rk) - 1
 | 
					 | 
				
			||||||
      assign IntTrunc = IntResultBits % P.RK;                       // Truncation check for ceiling operator
 | 
					 | 
				
			||||||
      assign IntSteps = (IntResultBits >> P.LOGRK) + |IntTrunc;     // Number of steps for int div
 | 
					 | 
				
			||||||
      assign nE = (IntSteps * P.DIVCOPIES) - 1;                     // Fractional digits = total digits - 1 integer digit
 | 
					 | 
				
			||||||
      assign RightShiftX = P.RK - 1 - ((IntResultBits - 1) % P.RK); // Right shift amount
 | 
					      assign RightShiftX = P.RK - 1 - ((IntResultBits - 1) % P.RK); // Right shift amount
 | 
				
			||||||
      assign DivXShifted = DivX >> RightShiftX;                     // shift X by up to R*K-1 to complete in nE steps
 | 
					      assign DivXShifted = DivX >> RightShiftX;                     // shift X by up to R*K-1 to complete in n steps
 | 
				
			||||||
      /* verilator lint_on WIDTH */
 | 
					      /* verilator lint_on WIDTH */
 | 
				
			||||||
    end else begin // radix 2 1 copy doesn't require shifting
 | 
					    end else begin // radix 2 1 copy doesn't require shifting
 | 
				
			||||||
      assign nE = p; 
 | 
					 | 
				
			||||||
      assign DivXShifted = DivX;
 | 
					      assign DivXShifted = DivX;
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end else begin
 | 
					  end else begin
 | 
				
			||||||
@ -199,17 +193,22 @@ module fdivsqrtpreproc import cvw::*;  #(parameter cvw_t P) (
 | 
				
			|||||||
  fdivsqrtcycles #(P) cyclecalc(.FmtE, .SqrtE, .IntDivE, .IntResultBits, .CyclesE);
 | 
					  fdivsqrtcycles #(P) cyclecalc(.FmtE, .SqrtE, .IntDivE, .IntResultBits, .CyclesE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (P.IDIV_ON_FPU) begin:intpipelineregs
 | 
					  if (P.IDIV_ON_FPU) begin:intpipelineregs
 | 
				
			||||||
 | 
					    logic [P.DIVBLEN:0] IntDivNormShiftE;
 | 
				
			||||||
 | 
					    /* verilator lint_off WIDTH */
 | 
				
			||||||
 | 
					    assign IntDivNormShiftE = P.DIVb - (CyclesE * P.RK - P.LOGR); // b - rn, used for integer normalization right shift.  rn = Cycles * r * k - r ***explain
 | 
				
			||||||
 | 
					    /* verilator lint_on WIDTH */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // pipeline registers
 | 
					    // pipeline registers
 | 
				
			||||||
    flopen #(1)        mdureg(clk, IFDivStartE, IntDivE,  IntDivM);
 | 
					    flopen #(1)          mdureg(clk, IFDivStartE, IntDivE,  IntDivM);
 | 
				
			||||||
    flopen #(1)       altbreg(clk, IFDivStartE, ALTBE,    ALTBM);
 | 
					    flopen #(1)         altbreg(clk, IFDivStartE, ALTBE,    ALTBM);
 | 
				
			||||||
    flopen #(1)      bzeroreg(clk, IFDivStartE, BZeroE,   BZeroM);
 | 
					    flopen #(1)        bzeroreg(clk, IFDivStartE, BZeroE,   BZeroM);
 | 
				
			||||||
    flopen #(1)      asignreg(clk, IFDivStartE, AsE,      AsM);
 | 
					    flopen #(1)        asignreg(clk, IFDivStartE, AsE,      AsM);
 | 
				
			||||||
    flopen #(1)      bsignreg(clk, IFDivStartE, BsE,      BsM);
 | 
					    flopen #(1)        bsignreg(clk, IFDivStartE, BsE,      BsM);
 | 
				
			||||||
    flopen #(P.DIVBLEN+1) nreg(clk, IFDivStartE, nE,       nM); 
 | 
					    flopen #(P.DIVBLEN+1) nsreg(clk, IFDivStartE, IntDivNormShiftE, IntDivNormShiftM); 
 | 
				
			||||||
    flopen #(P.DIVBLEN+1) mreg(clk, IFDivStartE, mE,       mM);
 | 
					    flopen #(P.DIVBLEN+1)  mreg(clk, IFDivStartE, mE,       mM);
 | 
				
			||||||
    flopen #(P.XLEN)   srcareg(clk, IFDivStartE, AE,       AM);
 | 
					    flopen #(P.XLEN)    srcareg(clk, IFDivStartE, AE,       AM);
 | 
				
			||||||
    if (P.XLEN==64) 
 | 
					    if (P.XLEN==64) 
 | 
				
			||||||
      flopen #(1)      w64reg(clk, IFDivStartE, W64E,     W64M);
 | 
					      flopen #(1)        w64reg(clk, IFDivStartE, W64E,     W64M);
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user