package MyRTPCore;

import  com.xilinx.JBits.Virtex.JBits;
import  com.xilinx.JBits.Virtex.State;
import  com.xilinx.JBits.Virtex.Expr;
import  com.xilinx.JBits.Virtex.Util;
import  com.xilinx.JBits.Virtex.ConfigurationException;

import  com.xilinx.JBits.Virtex.Bits.LUT;
import  com.xilinx.JBits.Virtex.Bits.S0BX;
import  com.xilinx.JBits.Virtex.Bits.S0CE;
import  com.xilinx.JBits.Virtex.Bits.S0Clk;
import  com.xilinx.JBits.Virtex.Bits.S0Control;
import  com.xilinx.JBits.Virtex.Bits.S1BX;
import  com.xilinx.JBits.Virtex.Bits.S1CE;
import  com.xilinx.JBits.Virtex.Bits.S1Clk;
import  com.xilinx.JBits.Virtex.Bits.S1Control;
import  com.xilinx.JBits.Virtex.Bits.Single;

import  com.xilinx.JBits.Virtex.RTPCore.Core;
import  com.xilinx.JBits.Virtex.RTPCore.Tags;

import com.xilinx.JRoute.Virtex.Router.Pin;
import com.xilinx.JRoute.Virtex.Router.RouteException;
import com.xilinx.JRoute.Virtex.Router.Connections;
import com.xilinx.JRoute.Virtex.Router.Port;
import com.xilinx.JRoute.Virtex.Router.RouterWithPorts;

import com.xilinx.JRoute.Virtex.ResourceDB.Wires;



/**
This design implements a constant multiplier using signed canonical
recoding, i.e. it implements for example x*7 as 
x<<3 - x 
instead of 
x + x<<1 + x<<2 
*/


public class RecodingConstMult extends Core {

    /** The size in bits of the X input */
    protected static int sizeX;

    /** The size in bits of the constant K */
    protected static int sizeK;

    /** The constant K */
    protected static int K;

    /** A variable saying if it's a power of two */
    private int isPowerOfTwo = -1;

    /** its first non-zero bit */
    private int firstNonZero = -1;

    /** K shifted so that its first bit is non zero */
    private int realK, realKsize;

    /** Its Booth recoding */
    private int BoothCode[];

    /** The operators and shifts needed for the multiplier */
    private int operators [][];

    /** A flag telling if this multiplier will use a subtraction
     (this allows a minor optimization)*/
    private boolean useMinus=false;

    /** The Zero port: the user of the core should feed it a logical zero */
    public Port Zero;

    /** The X input, will be of size sizeX */
    public Port X[];

    /** The output will be the product of X by K. 
	The size of this array is sizeX+sizeK */
    public Port Out[];

    /** The user may set the verbose level */
    public static boolean verbose = true;


    /* Useful LUT constants */
    
    /*
    ** Please note that the following LUT expressions are inverted but
    ** they perform as if uninverted.*/
    
    /* Sum0 = F1 */
    private static final int  SUM0_F[] = 
	Util.InvertIntArray(Expr.F_LUT("F1"));
    private static final int  SUM0_G[] = 
	Util.InvertIntArray(Expr.G_LUT("G1"));
    
    /* Sum1 = F2 ^ F1 */
    private static final int  SUM1_F[] = 
	Util.InvertIntArray(Expr.F_LUT("F2 ^ F1"));
    private static final int  SUM1_G[] = 
	Util.InvertIntArray(Expr.G_LUT("G2 ^ G1"));
    
    
    /* XOR of two inputs */
    private static final int  SUM_F[] = 
	Util.InvertIntArray(Expr.F_LUT("F1 ^ F2"));
    private static final int  SUM_G[] = 
	Util.InvertIntArray(Expr.G_LUT("G1 ^ G2"));

    /* Invert first input*/
    private static final int  INV_F[] = 
	Util.InvertIntArray(Expr.F_LUT("F1^1"));
    private static final int  INV_G[] = 
	Util.InvertIntArray(Expr.G_LUT("G1^1"));

    /* Zero */
    private static final int  Zero_F[] = Util.InvertIntArray(Expr.F_LUT("0"));
    private static final int  Zero_G[] = Util.InvertIntArray(Expr.G_LUT("0"));


    /**
       A function to compute the log in base 2 of an int. Surely it
       already existed somewhere */
    private static int log2(int k) {
	int l=0;
	while(k!=0) {
	    l++;
	    k = k>>1;
	};
	return l;
    }
       
    /**
       Does the Booth recoding of an int as in the Hwang, 
       but with an additional trick to avoid subs when possible. 
       Returns an array of ints in {0,1,-1}.
     */
    private static int[] BoothRecode  (int k) {
	int i,l,kk;
	int b[], bb[], c[], d[];

	bb = new int[32];
	l = 0;
	kk=k;
	
	while(kk!=0) {
	    bb[l] = kk % 2;
	    l++;
	    kk = kk>>1;
	}
	b = new int[l+1];
	for (i=0; i<l; i++)
	    b[i] = bb[i];
	b[l]=0;

	c = new int[l+1];
	d = new int[l+1];
	
	c[0] = 0;
	for (i=0; i<l; i++) {
	    if (b[i] + b[i+1] + c[i] >= 2)
		c[i+1] = 1;
	    else 
		c[i+1] = 0;
	    d[i] = b[i] + c[i] -2*c[i+1];
	}
	d[l] = c[l];

	// This method generates 10(-1) for 3 instead of 011.
	// As the -1 will cost us more, we rewrite that

	if (l>=2) {
	    for (i=l-2; i>=0; i--) {
		if ((d[i]==-1) && (d[i+1]==0) && (d[i+2]==1)) {
		    d[i]=1;
		    d[i+1]=1;
		    d[i+2]=0;
		}
	    }
	}
	if(verbose) {
	    System.out.print(" Recoding:  "+k+" = ");
	    for(int j=b.length-1; j>=0; j--)
		System.out.print(" "+d[j]);
	    System.out.println();
	}
	return d;
    }


    /**
       Does the Booth recoding of an int, as in the Hwang. 
       Returns an array of ints in {0,1,-1}.
     */
    private static int[] BoothRecode0  (int k) {
	int i,l,kk;
	int b[], bb[], c[], d[];

	bb = new int[32];
	l = 0;
	kk=k;
	
	while(kk!=0) {
	    bb[l] = kk % 2;
	    l++;
	    kk = kk>>1;
	}
	b = new int[l+1];
	for (i=0; i<l; i++)
	    b[i] = bb[i];
	b[l]=0;

	c = new int[l+1];
	d = new int[l+1];
	
	c[0] = 0;
	for (i=0; i<l; i++) {
	    if (b[i] + b[i+1] + c[i] >= 2)
		c[i+1] = 1;
	    else 
		c[i+1] = 0;
	    d[i] = b[i] + c[i] -2*c[i+1];
	}
	d[l] = c[l];

	return d;
    }



    /**
       Computes the int value of a booth encoding.
       (for testing purpose)
    */
    private static int BoothDecode (int b[]) {
	int i,r,w;
	r=0;
	w=1;
	for (i=0; i<b.length; i++) {
	    r = r + w*b[i];
	    w = w *2;
	}
	return r;
    }

    /** A constant used to access arrays of shifts and operators */
    private static int OP = 0;
    /** A constant used to access arrays of shifts and operators */
    private static int SHIFT = 1;


    /**
     Takes a Booth encoding and transforms it into a description of
     the shifts needed to implement it.

     Returns an array of pairs, 
     r[i][0] being an operation (-1 means minus, +1 means plus) 
     and r[i][1] being a shift
    */

    private static int[][] compactEncoding( int b[])
    {
	int i,j,last;

	// count the non-zero bits
	j=0;
	for (i=0; i<b.length; i++)
	    if (b[i] != 0) 
		j++;
	// build result array
	int r[][] = new int[j][2];
	
	j=0; 
	last=0;
	for (i=0; i<b.length; i++) {
	    if (b[i] != 0) {
		r[j][OP] = b[i];  // operation
		r[j][SHIFT] = i-last; // shift
		last = i;
		j++;
	    }
	}
	return r;
    }


    /**
     Test function */
    public static void testBooth (){
	int i, j;
	int b[];
	int c[][];
	for (i=3; i<255; i++) {
	    b = BoothRecode(i);
	    c = compactEncoding(b);
	    System.out.print(i + "  " + BoothDecode(b));
	    for(j=b.length-1; j>=0; j--)
		System.out.print(" "+b[j]);
	    System.out.print("  = ");
	    for(j=0; j<c.length; j++) {
		if (c[j][0]==1) 
		    System.out.print("; + ");
		if (c[j][0]==-1) 
		    System.out.print("; - ");
		System.out.print(c[j][1]);
	    }
	    System.out.println();
	}
    }
	

    /** This method sets up an adder slice. As we will allways add a
     shifted value to another value, we want to extend the shifted
     value : the shift most significant bits of the second argument
     are set to signextension (0 or 1)*/

    private void setAddSlice(JBits jBits, 
			     int row, int col, int slice, 
			     int shift, int signextension) 
	throws ConfigurationException {
	if (slice==0) 
	    setAddSlice0(jBits, row, col, shift, signextension);
	else
	    setAddSlice1(jBits, row, col, shift, signextension);
    }


    /** Does the job for setAddSlice */

    private void setAddSlice0(JBits jBits, int row, int col, 
			      int shift, int signextension) 
	throws ConfigurationException {
	int     i, bit;
	
	bit=0;
	for (i=0; i<clbHeight; i++) {
	    // Set up the LUT values

	    if (bit < (sizeX-shift))
		jBits.set(row+i, col, LUT.SLICE0_F, SUM_F);
	    else if (signextension==0)
		jBits.set(row+i, col, LUT.SLICE0_F, SUM0_F);
	    else
		jBits.set(row+i, col, LUT.SLICE0_F, SUM1_F);
	    
	    if ((bit+1) < (sizeX-shift))
		jBits.set(row+i, col, LUT.SLICE0_G, SUM_G);
	    else if (signextension==0)
		jBits.set(row+i, col, LUT.SLICE0_G, SUM0_G);
	    else
		jBits.set(row+i, col, LUT.SLICE0_G, SUM1_G);
	    
      
	    // Set up the and muxes to output the result of IN1 and IN2;
	    // when IN2 is not connected, it gets the value 1 
	    // and thus this is equivalent to IN1
	    jBits.set(row+i, col, 
		      S0Control.AndMux.AndMux, S0Control.AndMux.IN1_AND_IN2);

	    // Set up the carry out controller mux so that        
	    // the carry out output is controlled by the LUT output
	    jBits.set(row+i, col, 
		      S0Control.YCarrySelect.YCarrySelect, 
		      S0Control.YCarrySelect.LUT_CONTROL);
	    jBits.set(row+i, col, 
		      S0Control.XCarrySelect.XCarrySelect, 
		      S0Control.XCarrySelect.LUT_CONTROL);

	    // Set up carry chain    
	    if (0==i) {    // Set carry in to zero for the very first CLB    
		// turning off the S0BX input mux makes the S0BX line logic one 
		jBits.set(row+i, col, S0BX.S0BX, S0BX.OFF);
		//  invert  
		jBits.set(row+i, col, S0Control.BxInvert, S0Control.ON);
		// set the carry in to that
		jBits.set(row+i, col, S0Control.Cin.Cin, S0Control.Cin.BX);
	    } 
	    else {
		jBits.set(row+i, col, S0Control.Cin.Cin, S0Control.Cin.CIN);
	    }

	    // The sum bit is the XOR 
	    jBits.set(row+i, col, S0Control.X.X, S0Control.X.FOUT_XOR_CARRY);
	    jBits.set(row+i, col, S0Control.Y.Y, S0Control.Y.GOUT_XOR_CARRY); 
	    /*         
	     * Set up flip flops          
	     */      
	    // Set flip flop inputs 
	    // Set up the XD input to be the X output
	    jBits.set(row+i, col, S0Control.XDin.XDin, S0Control.XDin.X);
	    
	    /* Set up the YD input to be the X output */
	    jBits.set(row+i, col, S0Control.YDin.YDin, S0Control.YDin.Y);
	    
	    // Set slice 0 flip flop clocks (shared)
	    jBits.set(row+i, col, S0Clk.S0Clk, S0Clk.GCLK1);
	    
	    /* Enable flip flop clocks 
	     * Turning OFF the CE input Mux pulls the Mux output high */
	    jBits.set(row+i, col, S0CE.S0CE, S0CE.OFF);
	    
	    /* Set  slice 0 flip flops to flip flop mode */
	    jBits.set(row+i, col, S0Control.LatchMode, S0Control.OFF); 
	    
	    // I don't what that means 
	    state.setBitEntry(bit, row+i, col, State.SLICE0_XQ);
	    state.setBitEntry(bit+1, row+i, col, State.SLICE0_YQ);
	    setTag(jBits, row+i, col);

	    bit = bit + 2;
	}	
    }


    /** Does the job for setAddSlice */

    private void setAddSlice1(JBits jBits, int row, int col, 
			      int shift, int signextension) 
	throws ConfigurationException {
	int     i, bit;
	
	bit=0;
	for (i=0; i<clbHeight; i++) {
	    // Set up the LUT values

	    if (bit < (sizeX-shift))
		jBits.set(row+i, col, LUT.SLICE1_F, SUM_F);
	    else if (signextension==0)
		jBits.set(row+i, col, LUT.SLICE1_F, SUM0_F);
	    else
		jBits.set(row+i, col, LUT.SLICE1_F, SUM1_F);
	    
	    if ((bit+1) < (sizeX-shift))
		jBits.set(row+i, col, LUT.SLICE1_G, SUM_G);
	    else if (signextension==0)
		jBits.set(row+i, col, LUT.SLICE1_G, SUM0_G);
	    else
		jBits.set(row+i, col, LUT.SLICE1_G, SUM1_G);
	    
      
	    // Set up the and muxes to output the result of IN1 and IN2;
	    // when IN2 is not connected, it gets the value 1 and thus this is equivalent to IN1
	    jBits.set(row+i, col, 
		      S1Control.AndMux.AndMux, 
		      S1Control.AndMux.IN1_AND_IN2);

	    // Set up the carry out controller mux so that        
	    // the carry out output is controlled by the LUT output
	    jBits.set(row+i, col, 
		      S1Control.YCarrySelect.YCarrySelect, 
		      S1Control.YCarrySelect.LUT_CONTROL);
	    jBits.set(row+i, col, 
		      S1Control.XCarrySelect.XCarrySelect, 
		      S1Control.XCarrySelect.LUT_CONTROL);

	    // Set up carry chain    
	    if (0==i) {// Set carry in to zero for the very first CLB    
		// turning off the S1BX input mux makes the S1BX line 
		// a logic one 
		jBits.set(row+i, col, S1BX.S1BX, S1BX.OFF);
		// invert  
		jBits.set(row+i, col, S1Control.BxInvert, S1Control.ON);
		// set the carry in to that
		jBits.set(row+i, col, S1Control.Cin.Cin, S1Control.Cin.BX);
	    } 
	    else {
		jBits.set(row+i, col, S1Control.Cin.Cin, S1Control.Cin.CIN);
	    }

	    // The sum bit is the XOR 
	    jBits.set(row+i, col, S1Control.X.X, S1Control.X.FOUT_XOR_CARRY);
	    jBits.set(row+i, col, S1Control.Y.Y, S1Control.Y.GOUT_XOR_CARRY);
	    /*         
	     * Set up flip flops          
	     */      
	    // Set flip flop inputs 
	    // Set up the XD input to be the X output
	    jBits.set(row+i, col, S1Control.XDin.XDin, S1Control.XDin.X);
	    
	    /* Set up the YD input to be the X output */
	    jBits.set(row+i, col, S1Control.YDin.YDin, S1Control.YDin.Y);
	    
	    // Set slice 0 flip flop clocks (shared)
	    jBits.set(row+i, col, S1Clk.S1Clk, S1Clk.GCLK1);
	    
	    /* Enable flip flop clocks 
	     * Turning OFF the CE input Mux pulls the Mux output high */
	    jBits.set(row+i, col, S1CE.S1CE, S1CE.OFF);
	    
	    /* Set  slice 0 flip flops to flip flop mode */
	    jBits.set(row+i, col, S1Control.LatchMode, S1Control.OFF);
	    
	    state.setBitEntry(bit, row+i, col, State.SLICE1_XQ);
	    state.setBitEntry(bit+1, row+i, col, State.SLICE1_YQ);
	    setTag(jBits, row+i, col);

	    bit = bit + 2;
	}	
    }


    /** Instantiates in slice one a slice that will compute -x
	i.e. /x + 1 */

    private void setMinusXSlice1(JBits jBits, int row, int col) 
	throws ConfigurationException {
	int     i, bit;
	
	bit=0;
	for (i=0; i<clbHeight; i++) {
	    // Set up the LUT values

	    jBits.set(row+i, col, LUT.SLICE1_F, INV_F);
	    jBits.set(row+i, col, LUT.SLICE1_G, INV_G);
	          
	    // Set up the and muxes to output IN1;
	    jBits.set(row+i, col, 
		      S1Control.AndMux.AndMux, S1Control.AndMux.ZERO);

	    // Set up the carry out controller mux so that        
	    // the carry out output is controlled by the LUT output
	    jBits.set(row+i, col, 
		      S1Control.YCarrySelect.YCarrySelect, 
		      S1Control.YCarrySelect.LUT_CONTROL);
	    jBits.set(row+i, col, 
		      S1Control.XCarrySelect.XCarrySelect, 
		      S1Control.XCarrySelect.LUT_CONTROL);

	    // Set up carry chain    
	    if (0==i) {    // Set carry in to zero for the very first CLB    
		// turning off the S1BX input mux makes the S1BX line 
		// a logic one 
		jBits.set(row+i, col, S1BX.S1BX, S1BX.OFF);
		// do not invert  
		jBits.set(row+i, col, S1Control.BxInvert, S1Control.OFF);
		// set the carry in to that
		jBits.set(row+i, col, S1Control.Cin.Cin, S1Control.Cin.BX);
	    } 
	    else {
		jBits.set(row+i, col, S1Control.Cin.Cin, S1Control.Cin.CIN);
	    }

	    // The sum bit is the XOR 
	    jBits.set(row+i, col, S1Control.X.X, S1Control.X.FOUT_XOR_CARRY);
	    jBits.set(row+i, col, S1Control.Y.Y, S1Control.Y.GOUT_XOR_CARRY);
	    /*         
	     * Set up flip flops          
	     */      
	    // Set flip flop inputs 
	    // Set up the XD input to be the X output
	    jBits.set(row+i, col, S1Control.XDin.XDin, S1Control.XDin.X);
	    
	    /* Set up the YD input to be the X output */
	    jBits.set(row+i, col, S1Control.YDin.YDin, S1Control.YDin.Y);

	    // Set slice 0 flip flop clocks (shared)
	    jBits.set(row+i, col, S1Clk.S1Clk, S1Clk.GCLK1);
	    
	    /* Enable flip flop clocks 
	     * Turning OFF the CE input Mux pulls the Mux output high */
	    jBits.set(row+i, col, S1CE.S1CE, S1CE.OFF);
	    
	    /* Set  slice 0 flip flops to flip flop mode */
	    jBits.set(row+i, col, S1Control.LatchMode, S1Control.OFF);
	    
	    state.setBitEntry(bit, row+i, col, State.SLICE1_XQ);
	    state.setBitEntry(bit+1, row+i, col, State.SLICE1_YQ);
	    setTag(jBits, row+i, col);

	    bit = bit + 2;
	}	
    }



    /**
       Constructor of the multiplier. It takes the sizes of both the
       constant an the input port, and the constant value K. It
       computes the size the core will have without actually placing
       and routing it. This size will be in the Core variables
       clbWidth and clbHeight. This constructor also creates the three
       ports of this multiplier: the input X (of sizeX bits), the
       output Out (of sizeX+sizeK bits) and the input Zero, which
       should be connected to logic zero */

    public RecodingConstMult (int _sizeX, int _sizeK, int _K) {
	int i, p, power;

	if(verbose)
	    System.out.println("Booth multiplier : sizeX=" + _sizeX 
			       + ", sizeK=" + _sizeK + ", K=" + _K);
	sizeK = _sizeK;
	K = _K;

	if((_sizeX % 2) == 0) {
	    sizeX = _sizeX;
	}
	else {
	    sizeX = _sizeX+1;
	    System.out.println("RecodingConstMult warning: extending odd size "+_sizeX+" to "+(_sizeX+1));
	}

	// Create the ports 
	Zero = new Port(Wires.IN, "MultBy"+K+".Zero");

	X = new Port[sizeX];
	for (i=0; i<X.length; i++) {
	    X[i] = new Port(Wires.IN, "MultBy"+K+".X["+i+"]");
	}

	Out = new Port[sizeX+sizeK];
	for (i=0; i<Out.length; i++) {
	    Out[i] = new Port(Wires.OUT, "MultBy"+K+".Out["+i+"]");
	}

	/* Allocate the state object */
	// don't know what it's there for...
	state = new State(sizeX);
	tag = 0xF2D; // completely random value set to my initials
	name = "RecodingConstMult";
	setUniqueTag(K);

	// compute the size of the core.

	// There are several degenerated cases to handle.  If the
	// constant is zero, one or another power of 2, we simply
	// reset/shift the output, and the core occupies no space. 
	// If it is another number with zeroes
	// as the LSB, we may remove them and build a smaller
	// multiplier.
	
	// check if K is a power of 2
	p = 1;
	for (power=0; power<sizeK; power++) {
	    if (K==p) 
		break;
	    p = 2*p;
	};
	// first case: K=0
	if (K==0) {
	    clbWidth=0;
	    clbHeight=0;
	}
	else  if (power<sizeK){
	    // second case: K is a power of 2: 
	    clbWidth=0;
	    clbHeight=0;
	    isPowerOfTwo = power;
	}
	else {
	    // search the first non-zero digit
	    p=K;
	    power=0;
	    while (p % 2 == 0) {
		p = p>>1;
		power += 1;
	    }
	    firstNonZero = power;
	    realK = p; // i.e. K shifted to the right as much as possible
	    realKsize = sizeK - power;
	    
	    // Compute the Booth encoding of k
	    BoothCode = BoothRecode(realK);
	    
	    // Generate the shifts
	    operators = compactEncoding(BoothCode);
	    
	    // test wether there is at least one substractor
	    for (i=0; i<operators.length; i++) {
		if(operators[i][OP]==-1)
		    useMinus=true;
	    }
	    if (useMinus) 
		clbWidth = (operators.length +1) / 2 ;
	    else
		clbWidth = (operators.length) / 2 ;
	    clbHeight = sizeX/2;
	}
	if (verbose) 
	    System.out.println(" Core size will be: CLB height "
			       +clbHeight+", CLB width "+clbWidth); 
    }
    
          

    /** Instantiates the multiplier in the case when there is no
        router object available. Warning, this function does
        instantiate a router object, and using it will probably lead
        to resource conflicts at a later date.*/


    public void set (JBits jBits, int row, int col)  
	throws ConfigurationException
    {     
	RouterWithPorts router;
	
	// Set up the router object and the ports     
	if(verbose) 
	    router = new RouterWithPorts(jBits, System.out);
	else
	    router = new RouterWithPorts(jBits);
	
     // calls the other set() function
	set (jBits, router, row, col);
    }
    


    /** Instantiates the multiplier. This method takes a JBits object,
        a Router object which will be used to route the inners of the
        core, and the position of the multiplier */
    public void set (JBits jBits,  RouterWithPorts router, int row, int col)  
	throws ConfigurationException
    {     
	int i,j,k,n,p,clbcol,slice, shift, signExtension, currentshift;
	Pin minusX[] = new Pin[sizeX];
	Pin addin1[][];
	Pin addin2[][];
	Pin addout[][];
          
	if(verbose)
	    System.out.println(" Setting up Booth multiplier by "+K
			       +" at ("+row+","+col+")");

	// first case: K=0
	if (K==0) {
	    if(verbose)
		System.out.println("Constant is zero");
	    // set all the outputs to zero
	    for(i=0; i<Out.length; i++) {
		Out[i].setDrivenBy(Zero);
	    }
	}
	else  if (isPowerOfTwo != -1){
	    // second case: K is a power of 2 (computed in the constructor)
	    // shift by power, padding with zeroes
	    if(verbose)
		System.out.println(" The constant is two to the power of "
				   +isPowerOfTwo);
	    for(i=0; i<isPowerOfTwo; i++)
		Out[i].setDrivenBy(Zero);
	    for(i=isPowerOfTwo; i<isPowerOfTwo+sizeX; i++) 
		Out[i].setDrivenBy(X[i-isPowerOfTwo]);
	    for(i=isPowerOfTwo+sizeX; i<sizeK+sizeX; i++) 
		Out[i].setDrivenBy(Zero);
	}
	else {
	    // catch the routing exceptions
	    try{
		if(verbose)
		    System.out.println("  Using " + (operators.length-1) 
				       + " adder(s)...");
		// the least significant zeroes in the binary writing will
		// not entail any computation
		if(verbose)
		    System.out.println(" First shifting by "+firstNonZero);
		for(i=0; i<firstNonZero; i++)
		    //Out[i].setDrivenBy(Zero);  
		    // don't know why the above doesn't work, but it doesn't
		    // Fortunately the version below is OK
		    Zero.addDrives(Out[i]);

		// from now on we know there is at least two additions to
		// compute the product
		if(verbose)
		    System.out.println(" Now building a multiplier by "+realK);
		
		// create the ports for the adders
		addin1 = new Pin[operators.length-1][sizeX];
		addin2 = new Pin[operators.length-1][sizeX];
		addout = new Pin[operators.length-1][sizeX];
		
		slice=1; // will be 1,0,1,0,1,0,1...
		clbcol=0;
		
		//if there is a substractor, let the first slice compute -x
		if(useMinus) {
		    if(verbose)
			System.out.println("  Need to build -X ");
		    //instantiate the slice
		    setMinusXSlice1(jBits, row, col);
		    // allocate the minusX pins
		    minusX = new Pin[sizeX];
		    //route x (the in port) to its F1 input
		    for (j=0; j<clbHeight; j++) { //loop on the CLBs
			router.route(X[2*j],   
				     new Pin(row+j, col, Wires.S1F1));
			router.route(X[2*j+1], 
				     new Pin(row+j, col, Wires.S1G1)); 
			minusX[2*j] = new Pin(row+j, col, Wires.S1_X);
			minusX[2*j+1] = new Pin(row+j, col, Wires.S1_Y);
		    }
		    // increase the (row, slice) counter
		    // (here the first branch is always taken)
		    if (slice==1) {
			slice= 0;
		    }
		    else {
			slice =1;
			clbcol++;
		    }
		}
		// now we have x in port X and -x in pin minusX
		
		currentshift=firstNonZero;
		
		for (k=0; k<operators.length-1; k++) {
		    // each operator will compute the sum of the
		    // previous result, shifted by shift, and with the
		    // sign extension corresponding to the previous
		    // operator, added to either x or -x.  

		    // First we extend the sign of the result of the
		    // previous operation
		    
		    if (operators[k][OP]==-1)
			signExtension = 1;
		    else
			signExtension = 0;
		    
		    shift = operators[k+1][SHIFT];
		    if(verbose) {
			System.out.println("  Setting up an adder at col "
					   + clbcol + ",slice " + slice 
					   + " : signExtension="+signExtension
					   + ";  shift="+shift
					   + ".   currentshift="+currentshift);
		    }

		    // set the adder slice
		    setAddSlice(jBits, row, col+clbcol, slice, 
				shift, signExtension);
		    // define its pins
		    if (slice==0) {
			for (i=0; i<clbHeight; i++) {
			    addin1[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S0F1);
			    addin1[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S0G1);
			    addin2[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S0F2);
			    addin2[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S0G2);
			    addout[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S0_X);
			    addout[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S0_Y);
			}
		    }
		    else {// slice == 1
			for (i=0; i<clbHeight; i++) {
			    addin1[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S1F1);
			    addin1[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S1G1);
			    addin2[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S1F2);
			    addin2[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S1G2);
			    addout[k][2*i]=new Pin(row+i, col+clbcol, 
						   Wires.S1_X);
			    addout[k][2*i+1]=new Pin(row+i, col+clbcol, 
						     Wires.S1_Y);
			}
		    }
		    // route
		    
		    // first input is either X or -X
		    if (operators[k+1][OP]==1) {
			for(i=0; i<sizeX; i++) { 
			    router.route(X[i], addin1[k][i]);
			}
		    }
		    else {
			for(i=0; i<sizeX; i++) { 
			    router.route(minusX[i], addin1[k][i]);
			}
		    }
		    
		    // second input depends whether this is the first adder 
		    // or not:
		    // if first, the first input is either x or -x, 
		    // if not it is the output of the previous adder
		    if (k==0) {
			// then we connect to F2/G2 to X or -X, shifted
			if (operators[k][OP]==1) {
			    // First output the shift least
			    // significant bits directly
			    for(i=0; i<shift; i++) {
				Out[i+currentshift].setDrivenBy(X[i]);
			    }
			    // then input x shifted in F2/G2
			    for(i=0; i<sizeX-shift; i++) { 
				// the remaining bits are the sign extension
				router.route(X[i+shift], addin2[k][i]);
			    }
			}
			else {
			    // First output the shift least
			    // significant bits directly
			    for(i=0; i<shift; i++) {
				Out[i+currentshift].setDrivenBy(minusX[i]);
			    }
			    // then input x shifted in F2/G2
			    for(i=0; i<sizeX-shift; i++) { 
				// the remaining bits are the sign extension
				router.route(minusX[i+shift], addin2[k][i]);
			    }
			}
			
		    }
		    else { // k>=1
			// then we connect to F2/G2 to 
			// the shifted result of previous slice

			// First output the shift least significant
			// bits directly
			for(i=0; i<shift; i++) {
			    Out[i+currentshift].setDrivenBy(addout[k-1][i]);
			}
			// then input x shifted in F2/G2
			for(i=0; i<sizeX-shift; i++) { 
			    // the remaining bits are the sign extension
			    router.route(addout[k-1][i+shift], addin2[k][i]);
			}
		    }
		    //
		    currentshift += shift; 
		    // increase the (row, slice) counter
		    if (slice==1) {
			slice= 0;
		    }
		    else {
			slice = 1;
			clbcol++;
		    }
		}
		
		//Route the final sum output to the output Port
		if(verbose)
		    System.out.println("  Routing final outputs from " 
				       + (currentshift) + 
				       " to " + (currentshift+sizeX-1));
		for (i=0; i<sizeX; i++) { 
		    Out[i+currentshift].setDrivenBy(addout[operators.length-2][i]);
		}  
		if(verbose)
		    System.out.println("  Wiring Zero to outputs " 
				       + (currentshift+sizeX) + 
				       " to " + Out.length);
		for (i=sizeX+currentshift; i<Out.length; i++)
		     Out[i].setDrivenBy(Zero);
	    }
	    catch(RouteException a) {
		System.out.println(a);
		throw new ConfigurationException("Route exception while routing RecodingConstMult("
						 +sizeX+","+K+")");
	    }
	}
    }



    /** The main method tests the booth encoding functions */
    public static void main(String arg[]) {
	testBooth();
	
    }
}



