forked from Github_Repos/cvw
		
	Reduced cycle count for DIVW/DIVUW by two
This commit is contained in:
		
							parent
							
								
									648cc8ef64
								
							
						
					
					
						commit
						48e33c79a9
					
				@ -67,7 +67,7 @@
 | 
			
		||||
 | 
			
		||||
// Integer Divider Configuration
 | 
			
		||||
// DIV_BITSPERCYCLE must be 1, 2, or 4
 | 
			
		||||
`define DIV_BITSPERCYCLE 4
 | 
			
		||||
`define DIV_BITSPERCYCLE 1
 | 
			
		||||
 | 
			
		||||
// Legal number of PMP entries are 0, 16, or 64
 | 
			
		||||
`define PMP_ENTRIES 64
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ module intdivrestoring (
 | 
			
		||||
  input  logic clk,
 | 
			
		||||
  input  logic reset,
 | 
			
		||||
  input  logic StallM, FlushM,
 | 
			
		||||
  input  logic SignedDivideE,
 | 
			
		||||
  input  logic SignedDivideE, W64E,
 | 
			
		||||
  input  logic StartDivideE,
 | 
			
		||||
  input  logic [`XLEN-1:0] XE, DE,
 | 
			
		||||
  output logic BusyE, DivDoneM,
 | 
			
		||||
@ -40,7 +40,7 @@ module intdivrestoring (
 | 
			
		||||
 | 
			
		||||
  logic [`XLEN-1:0] WE[`DIV_BITSPERCYCLE:0];
 | 
			
		||||
  logic [`XLEN-1:0] XQE[`DIV_BITSPERCYCLE:0];
 | 
			
		||||
  logic [`XLEN-1:0] DSavedE, XSavedE, XSavedM, DnE, DAbsBE, XnE, XInitE, WM, XQM, WnM, XQnM;
 | 
			
		||||
  logic [`XLEN-1:0] DSavedE, XSavedE, XSavedM, DinE, XinE, DnE, DAbsBE, XnE, XInitE, WM, XQM, WnM, XQnM;
 | 
			
		||||
  localparam STEPBITS = $clog2(`XLEN/`DIV_BITSPERCYCLE);
 | 
			
		||||
  logic [STEPBITS:0] step;
 | 
			
		||||
  logic Div0E, Div0M;
 | 
			
		||||
@ -52,9 +52,22 @@ module intdivrestoring (
 | 
			
		||||
  // Saving the inputs is the most hardware-efficient way to fix the issue.
 | 
			
		||||
  flopen #(`XLEN) dsavereg(~clk, StartDivideE, DE, DSavedE); 
 | 
			
		||||
  flopen #(`XLEN) xsavereg(~clk, StartDivideE, XE, XSavedE);
 | 
			
		||||
  assign SignDE = DSavedE[`XLEN-1]; 
 | 
			
		||||
  assign SignXE = XSavedE[`XLEN-1];
 | 
			
		||||
  assign Div0E = (DSavedE == 0);
 | 
			
		||||
 | 
			
		||||
  // Handle sign extension for W-type instructions
 | 
			
		||||
  generate
 | 
			
		||||
    if (`XLEN == 64) begin // RV64 has W-type instructions
 | 
			
		||||
      mux2 #(`XLEN) xinmux(XSavedE, {XSavedE[31:0], 32'b0}, W64E, XinE);
 | 
			
		||||
      mux2 #(`XLEN) dinmux(DSavedE, {{32{DSavedE[31]&SignedDivideE}}, DSavedE[31:0]}, W64E, DinE);
 | 
			
		||||
	end else begin // RV32 has no W-type instructions
 | 
			
		||||
      assign XinE = XSavedE;
 | 
			
		||||
      assign DinE = DSavedE;	    
 | 
			
		||||
    end   
 | 
			
		||||
  endgenerate 
 | 
			
		||||
 | 
			
		||||
  // Extract sign bits and check fo division by zero
 | 
			
		||||
  assign SignDE = DinE[`XLEN-1]; 
 | 
			
		||||
  assign SignXE = XinE[`XLEN-1];
 | 
			
		||||
  assign Div0E = (DinE == 0);
 | 
			
		||||
 | 
			
		||||
  // pipeline registers
 | 
			
		||||
  flopenrc #(1) SignedDivideMReg(clk, reset, FlushM, ~StallM, SignedDivideE, SignedDivideM);
 | 
			
		||||
@ -64,10 +77,10 @@ module intdivrestoring (
 | 
			
		||||
  flopenrc #(`XLEN) XSavedMReg(clk, reset, FlushM, ~StallM, XSavedE, XSavedM); // is this truly necessary?
 | 
			
		||||
 | 
			
		||||
  // Take absolute value for signed operations, and negate D to handle subtraction in divider stages
 | 
			
		||||
  neg #(`XLEN) negd(DSavedE, DnE);
 | 
			
		||||
  mux2 #(`XLEN) dabsmux(DnE, DSavedE, SignedDivideE & SignDE, DAbsBE);  // take absolute value for signed operations, and negate for subtraction setp
 | 
			
		||||
  neg #(`XLEN) negx(XSavedE, XnE);
 | 
			
		||||
  mux2 #(`XLEN) xabsmux(XSavedE, XnE, SignedDivideE & SignXE, XInitE);  // need original X as remainder if doing divide by 0
 | 
			
		||||
  neg #(`XLEN) negd(DinE, DnE);
 | 
			
		||||
  mux2 #(`XLEN) dabsmux(DnE, DinE, SignedDivideE & SignDE, DAbsBE);  // take absolute value for signed operations, and negate for subtraction setp
 | 
			
		||||
  neg #(`XLEN) negx(XinE, XnE);
 | 
			
		||||
  mux2 #(`XLEN) xabsmux(XinE, XnE, SignedDivideE & SignXE, XInitE);  // need original X as remainder if doing divide by 0
 | 
			
		||||
 | 
			
		||||
  // initialization multiplexers on first cycle of operation (one cycle after start is asserted)
 | 
			
		||||
  mux2 #(`XLEN) wmux(WM, {`XLEN{1'b0}}, DivInitE, WE[0]);
 | 
			
		||||
@ -106,7 +119,7 @@ module intdivrestoring (
 | 
			
		||||
    end else if (BusyE & ~DivDoneM) begin // pause one cycle at beginning of signed operations for absolute value
 | 
			
		||||
        DivInitE = 0;
 | 
			
		||||
        step = step + 1;
 | 
			
		||||
        if (step[STEPBITS]) begin 
 | 
			
		||||
        if (step[STEPBITS] | (`XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
 | 
			
		||||
            step = 0;
 | 
			
		||||
            BusyE = 0;
 | 
			
		||||
            DivDoneM = 1;
 | 
			
		||||
 | 
			
		||||
@ -34,11 +34,10 @@ module intdivrestoringstep(
 | 
			
		||||
  logic [`XLEN-1:0] WShift, WPrime;
 | 
			
		||||
  logic qi, qib;
 | 
			
		||||
  
 | 
			
		||||
  assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi};
 | 
			
		||||
  adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime});
 | 
			
		||||
  //assign {qib, WPrime} = {1'b0, WShift} + {1'b1, DAbsB}; // effective subtractor, carry out determines quotient bit
 | 
			
		||||
  assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi};  // shift W and X/Q left, insert quotient bit at bottom
 | 
			
		||||
  adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime}); // effective subtractor, carry out determines quotient bit
 | 
			
		||||
  assign qi = ~qib;
 | 
			
		||||
  mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut);
 | 
			
		||||
  mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut); // if quotient is zero, restore W
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
/* verilator lint_on UNOPTFLAT */
 | 
			
		||||
 | 
			
		||||
@ -65,20 +65,12 @@ module muldiv (
 | 
			
		||||
	 flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM); 
 | 
			
		||||
 | 
			
		||||
	 // Divide
 | 
			
		||||
 | 
			
		||||
	 // Handle sign extension for W-type instructions
 | 
			
		||||
	 if (`XLEN == 64) begin // RV64 has W-type instructions
 | 
			
		||||
            assign XE = W64E ? {{32{SrcAE[31]&SignedDivideE}}, SrcAE[31:0]} : SrcAE;
 | 
			
		||||
            assign DE = W64E ? {{32{SrcBE[31]&SignedDivideE}}, SrcBE[31:0]} : SrcBE;
 | 
			
		||||
	 end else begin // RV32 has no W-type instructions
 | 
			
		||||
            assign XE = SrcAE;
 | 
			
		||||
            assign DE = SrcBE;	    
 | 
			
		||||
	 end	    
 | 
			
		||||
 | 
			
		||||
	 assign XE = SrcAE;
 | 
			
		||||
	 assign DE = SrcBE;
 | 
			
		||||
	 assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]);	 
 | 
			
		||||
	 //intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE);
 | 
			
		||||
	 intdivrestoring div(.clk, .reset, .StallM, .FlushM, 
 | 
			
		||||
	   .SignedDivideE, .StartDivideE, .XE, .DE, .BusyE, .DivDoneM, .QuotM, .RemM);
 | 
			
		||||
	   .SignedDivideE, .W64E, .StartDivideE, .XE, .DE, .BusyE, .DivDoneM, .QuotM, .RemM);
 | 
			
		||||
 | 
			
		||||
	 // Start a divide when a new division instruction is received and the divider isn't already busy or finishing
 | 
			
		||||
	 assign StartDivideE = MulDivE & Funct3E[2] & ~BusyE & ~DivDoneM; 
 | 
			
		||||
 | 
			
		||||
@ -161,6 +161,10 @@ string tests32f[] = '{
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  string tests64m[] = '{
 | 
			
		||||
    "rv64m/I-REMUW-01", "3000",
 | 
			
		||||
    "rv64m/I-REMW-01", "3000",
 | 
			
		||||
    "rv64m/I-DIVUW-01", "3000",
 | 
			
		||||
    "rv64m/I-DIVW-01", "3000",
 | 
			
		||||
    "rv64m/I-MUL-01", "3000",
 | 
			
		||||
    "rv64m/I-MULH-01", "3000",
 | 
			
		||||
    "rv64m/I-MULHSU-01", "3000",
 | 
			
		||||
@ -168,12 +172,8 @@ string tests32f[] = '{
 | 
			
		||||
    "rv64m/I-MULW-01", "3000",
 | 
			
		||||
    "rv64m/I-DIV-01", "3000",
 | 
			
		||||
    "rv64m/I-DIVU-01", "3000",
 | 
			
		||||
    "rv64m/I-DIVUW-01", "3000",
 | 
			
		||||
    "rv64m/I-DIVW-01", "3000",
 | 
			
		||||
    "rv64m/I-REM-01", "3000",
 | 
			
		||||
    "rv64m/I-REMU-01", "3000",
 | 
			
		||||
    "rv64m/I-REMUW-01", "3000",
 | 
			
		||||
    "rv64m/I-REMW-01", "3000"
 | 
			
		||||
    "rv64m/I-REMU-01", "3000"
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  string tests64ic[] = '{
 | 
			
		||||
@ -536,11 +536,11 @@ string tests32f[] = '{
 | 
			
		||||
        tests = {tests64p,tests64i, tests64periph};
 | 
			
		||||
        if (`C_SUPPORTED) tests = {tests, tests64ic};
 | 
			
		||||
        else              tests = {tests, tests64iNOc};
 | 
			
		||||
        if (`M_SUPPORTED) tests = {tests, tests64m};
 | 
			
		||||
        if (`F_SUPPORTED) tests = {tests64f, tests};
 | 
			
		||||
        if (`D_SUPPORTED) tests = {tests64d, tests};
 | 
			
		||||
        if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
 | 
			
		||||
        if (`A_SUPPORTED) tests = {tests64a, tests};
 | 
			
		||||
        if (`M_SUPPORTED) tests = {tests64m, tests};
 | 
			
		||||
      end
 | 
			
		||||
      //tests = {tests64a, tests};
 | 
			
		||||
    end else begin // RV32
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user