/*__________________________________________________________________________________*/
/*										    */
/* 		This file contains the layout generation 			    */
/*__________________________________________________________________________________*/


/* Inclusion des fichiers header 						    */

# include<genlib.h>
# include<stdio.h>
# include<ctype.h>
# include<string.h>
# include<math.h>

#define TRUE  		(1)		/* valeur booleenne VRAI		    */
#define FALSE 		(0)		/* valeur booleenne FAUX		    */
#define TAILLE_MAX	(40)		/* nb max de colonne de la partie ARRAY	    */ 
#define alim_step	(5)		/* Rappel d'alim tout les 5 MUX+CSA	    */


				

/* definition des macros	                                                    */

#define x_max(a,b)	((a)>(b)?(a):(b))	/* rend le max de  a et b	    */
#define x_min(a,b)	((a)>(b)?(b):(a))	/* rend le min de  a et b	    */ 
#define round(a)        (2*((a+1)/2))		/* rend a si il est pair,a+1 sinon  */


/* definition des variables externes globales                                       */

extern int step,step1,step2;	/* pas de pipeline				    */
extern long op1,op2;	 	/* Taille temporaire des operandes		    */
extern long N,M;		/* Taille des operandes				    */
extern int 	layout,vhdl,data,icon;	/* vues generes				    */
extern int	virtual,msb0;	/* parametres pour les connecteurs		    */
extern char	*name;		/* nom du bloc genere				    */
extern int 	t0,t1,n;	/* Parametres pour l'emplacement du pipeline	    */




/* definition des variables globales	                                            */
int 	alim_count=0;		/* Compteur pour le rappel d'alim		    */
int 	regs_count=0;		/* Compteur pour les bancs de registres		    */
int 	i=0,j=0,k=0;		/* Indices de boucles				    */
int	nb_effectif=0;		/* nb effectif de bancs de registres	 	    */

				/****************************************************/
static char comp [TAILLE_MAX];	/* contient la composition du          	 	    */
				/* multiplieur en terme de colonne		    */	
				/* d pour dnc 					    */
				/* p pour mux et mux+csa 			    */
				/* c pour le cla 				    */
				/* r pour registres				    */
				/* a pour alim 					    */
				/****************************************************/

				/****************************************************/
int	pipe [TAILLE_MAX];	/* contient la composition du pipeline		    */
				/* en terme d'indice de colonne			    */
				/****************************************************/

int 	ploum=0;		/* indice de la colonne dans comp []		    */
int	nreg=0;		  	/* indice du registre   dans pipe []		    */
				/* a la fin du placement nreg=nb de registres 	    */
int	last=0;			/* indice de la colonne csaout 			    */
/*__________________________________________________________________________________*/



/************************************************************************************************/
/*             				REALISE LE LAYOUT PIPELINE OU NON       		*/
/************************************************************************************************/

void laypack ()
{
/************************************************************************************************/
/*												*/
/* L'architecture des multiplieurs generes par AMG peut etre vue comme un sandwich		*/
/* Ce sont des multiplieurs " en tranches ".							*/
/* Generer le layout va donc consister a empiler des couches comme on entasserait		*/
/* des tranches de jambon ou de fromage dans un hamburger.					*/
/* 												*/
/*  -> La tranche de pain du debut, c'est la colonne de DNC qui calcule les commandes de booth	*/
/* D2j, D2jbar, N2j et C2j.									*/
/*  -> suit une tranche de mux de booth								*/
/*  -> ensuite on entre dans la partie array consituee de N/2-1 couche de MUX+CSA		*/
/*  -> on couvre le tout d'une sauce RSA pour le CLA final					*/
/*  -> et on ferme le sandwich avec une tranche "out" qui permute circ. les bits de sortie 	*/
/* 												*/
/* Chaque fonction a pour but de rajouter un couche sur la precedente et ce jusqu'au		*/
/* cla final. On s'applique ensuite a router les commandes et a remonter les connecteurs	*/
/*												*/
/************************************************************************************************/

def_cell ();			/* ouvre le fichier .ap						*/
dnc ();				/* Place la colonne de DNC 					*/
muxin ();			/* place la premiere colonne de MUX 				*/
half_add ();			/* place la premiere colonne d'additionneurs 			*/
array (); 			/* place la matrice reguliere					*/
csaout ();			/* place la colonne de sortie de la matrice 			*/
cla ();				/* instancie, place, durcie les connecteurs et route le cla 	*/

cmd ();				/* routage des signaux de commande D, N, C et poids faibles 	*/ 

allowm2 ();			/*  route les transparences alu2				*/
if (virtual)
vir_con ();			/* copy les connecteurs virtuels dans le pere 			*/
else
	dur_con ();		/* durcie les connecteurs					*/

if ((t0+t1+n) !=0 )
	{			/* s'il s'agit d'une version pipelinee il faut 			*/
	scan_rout ();		/* router le scan et						*/
	reg_con ();		/* remonter les connnecteurs ck, sd, st, scanin, scanout	*/
	}

end_cell ();
}
/*______________________________________________________________________________________________*/




/************************************************************************************************/
/*            				Initialisation du multiplieur 8X8                       */
/************************************************************************************************/

def_cell ()
{
DEF_PHFIG (NAME(name));
}
/*______________________________________________________________________________________________*/







/*****************************************************************/
/*                    colonne de dnc                             */
/*****************************************************************/
dnc ()
{
int i;
comp [ploum++]='d';
PLACE         ("amdncbot_c",NAME("d_%d",0),NOSYM,0L,0L);

for (i=1;i<(N/2);i++)
 	{
	PLACE_TOP ("amdnc_c",NAME ("d_%d",2*i),NOSYM);
	}

for (i=(N/2);i<(M/2);i++)
	{
	PLACE_TOP ("amdnctop2_c",NAME ("d_%d",2*i),NOSYM);
	}
PLACE_TOP ("amdnctop1_c",NAME ("d_%d",M),NOSYM);
DEF_PHINS ("d_0");
if (t0) reg_t0 ();  /* si t0 on pipeline apres la couche de  DNC */
}

/*_______________________________________________________________*/




/*****************************************************************/
/*                      premiere couche de mux                   */
/*****************************************************************/
muxin ()
{
int i;


comp [ploum++]='p';

PLACE_RIGHT ("amcoin_c","coin",NOSYM);
PLACE_TOP ("ammuxiinbot_c",NAME("p_%d_%d",ploum-1,1),SYM_Y);

for (i=2;i<(M+2);i+=2)
	{
	if (i==M)
	PLACE_TOP ("ammuxpintop_c",NAME("p_%d_%d",ploum-1,i),NOSYM);
	else
	PLACE_TOP ("ammuxpin_c",NAME("p_%d_%d",ploum-1,i),NOSYM);

	if (i==M)
	PLACE_TOP ("ammuxiintop_c",NAME ("p_%d_%d",ploum-1,i+1),SYM_Y);
	else
	PLACE_TOP ("ammuxiin_c",NAME("p_%d_%d",ploum-1,i+1),SYM_Y);
	}
DEF_PHINS ("coin");
}
/*_______________________________________________________________*/
 



/*****************************************************************/
/*                      colonne de Half-adder                    */
/*****************************************************************/
half_add()
{
int i;

comp [ploum++]='p';
 
PLACE_RIGHT ("amcl4lft_c",NAME ("cl4_%d",ploum-1),NOSYM);
for (i=1;i<M;i+=2)
	{
	if (i==1)
	{
	PLACE_TOP   ("ammuxi1bot_c"  ,NAME ("p_%d_%d",ploum-1,i),SYM_Y);
	PLACE_RIGHT ("amcsaiinbot_c",NAME ("c_%d_%d",ploum-1,i),SYM_Y);
	}
	else
	{
	PLACE_TOP   ("ammuxi1_c"  ,NAME ("p_%d_%d",ploum-1,i),SYM_Y);
	PLACE_RIGHT ("amcsaiin_c",NAME ("c_%d_%d",ploum-1,i),SYM_Y);
	}

	if (i==3) PHSEG (ALU2,2,"",
			GET_REF_X(NAME("c_%d_%d",ploum-1,i),"cinnext_in"),
			GET_REF_Y(NAME("c_%d_%d",ploum-1,i),"cinnext_in"),
			GET_REF_X(NAME("p_%d_%d",ploum-1,i),"C2j_in"),
			GET_REF_Y(NAME("p_%d_%d",ploum-1,i),"C2j_in"));

	if (i==M-1)
		{
		/* cellules sommet pour router l'extension de signe 			*/
		PLACE_TOP   ("amcsapintop_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM);
		PLACE_LEFT  ("ammuxp1top_c"     ,NAME ("p_%d_%d",ploum-1,i+1),NOSYM);
		PLACE_TOP   ("ammuxi1top_c"     ,NAME ("p_%d_%d",ploum-1,i+2),SYM_Y);
		PLACE_RIGHT ("amcsaiintop_c",NAME ("c_%d_%d",ploum-1,i+2),SYM_Y);
		
		/* pour remonter le poids faible m1 					*/
		PLACE_VIA_REF (NAME("c_%d_1",ploum-1),"mi_out",CONT_VIA);

		/* pour un csa impair en haut de la colonne cin=0 			*/
		for (k=N/2;k<M/2;k+=1)
			{
			if (t0==0)	/* on n'a pas de registre apres le CND		*/
			WIRE1 (ALU2,2,NAME ("d_%d",2*k),"vss2_out",0L,NAME ("c_%d_%d",ploum-1,2*k+1),"cinnext_in",0L);
			else
			WIRE1 (ALU2,2,NAME ("r_%d_%d",1,2*k+1),"c2j_out" ,0L,NAME ("c_%d_%d",ploum-1,2*k+1),"cinnext_in",0L);
			}

		DEF_PHINS (NAME("cl4_%d",ploum-1));
		break;
		}
	PLACE_TOP   ("amcsapin_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM);
	PLACE_LEFT  ("ammuxp1_c", NAME ("p_%d_%d",ploum-1,i+1),NOSYM);
	}
}
/*_________________________________________________________________*/



/*******************************************************************/
/*			RAPPEL D'ALIM				   */
/*******************************************************************/
alim ()
{
int i;

comp [ploum++]='a';

PLACE_RIGHT ("amalimpbot_c",NAME("a_%d_%d",ploum-1,0),NOSYM);
for (i=1;(i<M+2);i+=2)
	{
	PLACE_TOP ("amalimi_c",NAME("a_%d_%d",ploum-1,i),SYM_Y);
	if (i==M-1)
		{
		PLACE_TOP ("amalimptop_c",NAME("a_%d_%d",ploum-1,i+1),NOSYM);
		PLACE_TOP ("amalimitop_c",NAME("a_%d_%d",ploum-1,i+2),SYM_Y);
		DEF_PHINS (NAME ("a_%d_%d",ploum-1,0));
		alim_count=0;
		break;
		}
	PLACE_TOP ("amalimp_c",NAME("a_%d_%d",ploum-1,i+1),NOSYM);
	}
}
/*_________________________________________________________________*/




/*******************************************************************/
/*			RAPPEL D'ALIM	de sortie		   */
/*******************************************************************/
alimout ()
{
int i;

comp [ploum++]='a';

PLACE_RIGHT ("amalimpout_c",NAME("a_%d_%d",ploum-1,0),NOSYM);
for (i=1;(i<M+2);i+=2)
	{
	PLACE_TOP ("amalimiout_c",NAME("a_%d_%d",ploum-1,i),SYM_Y);
	if (i==M+1)
		{
		DEF_PHINS (NAME ("a_%d_%d",ploum-1,0));
		alim_count=0;
		break;
		}
	PLACE_TOP ("amalimpout_c",NAME("a_%d_%d",ploum-1,i+1),NOSYM);
	}
}
/*________________________________________________________________*/




/***************************************************************************************/
/*		BANC DE REGISTRES MAITRES ESCLAVES   DANS LA PARTIE ARRAY              */
/***************************************************************************************/
reg_n ()
{
int i;
int frontiere;

pipe [nreg++]=ploum;	/* on stoque l'indice de la colonne courante dans pipe []	*/
comp [ploum++]='r';	/* on stoque le type registre dans comp []			*/ 
nb_effectif++;		/* il y a un registre de plus dans la partie ARRAY		*/
if (nb_effectif <= (N/2-1)%(n+1))
frontiere = 2*step1*nb_effectif-1;	/* frontiere entre la zone ou on remonte le 	*/
					/* le poids faible et celle ou on cable les	*/
					/* signaux de commande de booth			*/
else
frontiere = 2*step1*((N/2-1)%(n+1))+2*step2*((nb_effectif-((N/2-1)%(n+1))))-1;
PLACE_RIGHT ("amregbotn_c",NAME("r_%d_%d",ploum-1,0),NOSYM); /* en bas slice 3 registres*/
for (i=1;i<M;i+=2)
	{
	PLACE_TOP ("amregni1_c",NAME("r_%d_%d",ploum-1,i),SYM_Y);
	if (i == frontiere) break;	/* jusqu'a la frontiere: bancs de 4 registres	*/
	PLACE_TOP ("amregnp1_c",NAME("r_%d_%d",ploum-1,i+1),NOSYM);
	}
PLACE_TOP ("amregnp2_c",NAME("r_%d_%d",ploum-1,frontiere+1),NOSYM);/* zone  limite 3 reg*/
PLACE_TOP ("amregni2_c",NAME("r_%d_%d",ploum-1,frontiere+2),SYM_Y);

for (i=frontiere+3;i<N;i+=2)	/* apres la frontiere : banc 5 registres		*/
	{
	PLACE_TOP ("amregnp_c",NAME("r_%d_%d",ploum-1,i),NOSYM);
	PLACE_TOP ("amregni_c",NAME("r_%d_%d",ploum-1,i+1),SYM_Y);
	}
 
for (i=N;i<M;i+=2)
	{
	PLACE_TOP ("amregnp2_c",NAME("r_%d_%d",ploum-1,i),NOSYM);
	PLACE_TOP ("amregni2_c",NAME("r_%d_%d",ploum-1,i+1),SYM_Y);
	}
	

PLACE_TOP ("amregtopn1_c",NAME ("r_%d_%d",ploum-1,M),NOSYM); /*  zone de bufferisation	*/
PLACE_TOP ("amregtopn2_c",NAME ("r_%d_%d",ploum-1,M+1),SYM_Y);
DEF_PHINS (NAME ("r_%d_%d",ploum-1,0));
regs_count=0;	/* on reinitialise le compteur de couches pour l'insertion des registres*/
}
/*______________________________________________________________________________________*/



	
/****************************************************************************************/
/*                  BANC  DE REGISTRES POUR UN BLOC DE PIPELINE APRES LE CND            */
/****************************************************************************************/
reg_t0 ()
{
int	i;

pipe [nreg++]=ploum;	/* on stocke l'indice cd la colonne courante dans pipe []	*/
comp [ploum++]='r';	/* on stocke le type de la colonne courante dans comp []	*/
PLACE_RIGHT ("amregbot0_c",NAME ("r_%d_%d",ploum-1,0),NOSYM);
PLACE_TOP   ("amregt0i_c" ,NAME ("r_%d_%d",ploum-1,1),SYM_Y);
for (i=2;i<N-1;i+=2)	/* il faut transmettre ai ainsi que 2 commandes de booth par	*/
	{		/* slice. Il y a donc trois registres dans cette zone		*/
	PLACE_TOP ("amregt0p_c",NAME ("r_%d_%d",ploum-1,i)  ,NOSYM);
	PLACE_TOP ("amregt0i_c",NAME ("r_%d_%d",ploum-1,i+1),SYM_Y);
	}

for (i=N;i<M;i+=2)	/* si M>N il n'y a plus de commande de booth a transmettre 	*/
	{		/* on a donc un zone ne contenant plus qu'un ou deux registres	*/
	PLACE_TOP ("amregt0p1_c",NAME ("r_%d_%d",ploum-1,i)  ,NOSYM);
	PLACE_TOP ("amregt0i1_c",NAME ("r_%d_%d",ploum-1,i+1),SYM_Y);
	}

PLACE_TOP ("amregtop01_c",NAME ("r_%d_%d",ploum-1,M)  ,NOSYM);	/* la zone buffer	*/
PLACE_TOP ("amregtop02_c",NAME ("r_%d_%d",ploum-1,M+1),SYM_Y);	/* occupe les 2 derniers*/
DEF_PHINS (NAME ("r_%d_%d",ploum-1,0));				/* slice		*/
}
/*______________________________________________________________________________________*/




/****************************************************************************************/
/*                  BANC  DE REGISTRES POUR UN BLOC DE PIPELINE AVANT LE CLA	        */
/****************************************************************************************/
reg_t1 ()
{
int	i;

pipe [nreg++]=ploum;	/* on stocke l'indice de la colonne courante dans pipe []	*/
comp [ploum++]='r';	/* on stocke le type de la colonne courante dans comp []	*/
PLACE_RIGHT ("amregbot1_c",NAME ("r_%d_%d",ploum-1,0),NOSYM);
PLACE_TOP   ("amregt1i_c" ,NAME ("r_%d_%d",ploum-1,1),SYM_Y);
for (i=2;i<N-2;i+=2)	/* pour transmettre les operandes au CLA et pour le lsb il faut */
	{		/* une zone de trois registres					*/
	PLACE_TOP ("amregt1p_c",NAME ("r_%d_%d",ploum-1,i)  ,NOSYM);
	PLACE_TOP ("amregt1i_c",NAME ("r_%d_%d",ploum-1,i+1),SYM_Y);
	}

for (i=N-2;i<M-2;i+=2)	/* si M>N on a une zone ou il n'y a plus de lsb a passer	*/
	{		/* il n'y a donc plus que deux registres dans cette zone	*/
	PLACE_TOP ("amregt1p1_c",NAME ("r_%d_%d",ploum-1,i)  ,NOSYM);
	PLACE_TOP ("amregt1i1_c",NAME ("r_%d_%d",ploum-1,i+1),SYM_Y);
	}

PLACE_TOP ("amregtop10_c",NAME ("r_%d_%d",ploum-1,M-2),NOSYM); /* au sommet la zone	*/
PLACE_TOP ("amregtop11_c",NAME ("r_%d_%d",ploum-1,M-1),SYM_Y); /* buffer occupe 	*/
PLACE_TOP ("amregtop12_c",NAME ("r_%d_%d",ploum-1,M)  ,NOSYM); /* quatre slices		*/
PLACE_TOP ("amregtop13_c",NAME ("r_%d_%d",ploum-1,M+1),SYM_Y);
DEF_PHINS (NAME ("r_%d_%d",ploum-1,0));
}
/*______________________________________________________________________________________*/





/****************************************************************************************/
/*                                  ARRAY                                               */
/****************************************************************************************/
array ()
{
int i,j;
alim_count=1; /* initialisation du compteur de couche pour le rappel d'alim 		*/
regs_count=1; /* initialisation du compteur de couche pour le pipeline      		*/
step=step1;   /* initialisation du pas de pipelinage					*/
for (j=2;j<(N/2-1);j++)
	{
	
	if (alim_count==alim_step) alim ();

	
	comp [ploum++]='p';


/***************************************** Debut du placement de la colonne   *****************************/
	PLACE_RIGHT ("amcl4_c",NAME ("cl4_%d",ploum-1),NOSYM);
	for (i=1;i<(M);i+=2)
		{
		if (i==1)
		PLACE_TOP   ("ammuxibot_c",NAME ("p_%d_%d",ploum-1,i),SYM_Y);
		else
		PLACE_TOP   ("ammuxi_c"   ,NAME ("p_%d_%d",ploum-1,i),SYM_Y);
		PLACE_RIGHT ("amcsai_c"   ,NAME ("c_%d_%d",ploum-1,i),SYM_Y); 

		if (nb_effectif == ((N/2-1)%(n+1))) step = step2;
		/* pour remonter un lsb de poids impair */
		if (i==2*j-2) 
			{
			PLACE_VIA_REF (NAME("c_%d_%d",ploum-1,i),"mi_out",CONT_VIA);
			}

		if (i==M-1)
			{
			/* cellules sommet pour router l'extension de signe */
			PLACE_TOP   ("amcsaptop_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM);
			PLACE_LEFT  ("ammuxptop_c",NAME ("p_%d_%d",ploum-1,i+1),NOSYM);
			PLACE_TOP   ("ammuxitop_c",NAME ("p_%d_%d",ploum-1,i+2),SYM_Y);
			PLACE_RIGHT ("amcsaitop_c",NAME ("c_%d_%d",ploum-1,i+2),SYM_Y);
			
			DEF_PHINS (NAME("cl4_%d",ploum-1));
			break;
			}
		
		PLACE_TOP    ("amcsap_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM); 
		PLACE_LEFT   ("ammuxp_c",NAME ("p_%d_%d",ploum-1,i+1),NOSYM);

		/* pour remonter un lsb de poids pair */
		if (i==2*j-4)
			{
		PLACE_VIA_REF(NAME("p_%d_%d",ploum-1,i+1),"mi",CONT_VIA);
			}
		}
	alim_count++;
	regs_count++;

	if (regs_count==step && (nb_effectif<=n)) reg_n ();  /* Banc de registres tout les step (MUX+CSA)  */

	}
}
/*_________________________________________________________________________________________________________*/




/******************************************************************/
/*         		Couche de csa de sortie                   */
/******************************************************************/
csaout ()
{
int i;

comp [ploum++]='p';
last=ploum-1;

PLACE_RIGHT ("amcl4_c",NAME ("cl4_%d",ploum-1),NOSYM);
for (i=1;i<M;i+=2)
	{
	if (i==1)
	PLACE_TOP   ("ammuxibot_c",NAME ("p_%d_%d",ploum-1,i),SYM_Y);
	else 
	PLACE_TOP   ("ammuxi_c"   ,NAME ("p_%d_%d",ploum-1,i),SYM_Y);
	PLACE_RIGHT ("amcsaiout_c",NAME ("c_%d_%d",ploum-1,i),SYM_Y);

	/* pour remonter un lsb de poids impair */
	if (i==N-4) 
		{
		PLACE_VIA_REF (NAME("c_%d_%d",ploum-1,i),"mi_out",CONT_VIA);
		}

	if(i==M-1)
		{
		/* cellules sommet pour router l'extension de signe */
		PLACE_TOP   ("amcsapouttop_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM);
		PLACE_LEFT  ("ammuxptop_c"   ,NAME ("p_%d_%d",ploum-1,i+1),NOSYM);
		PLACE_TOP   ("ammuxitop_c"   ,NAME ("p_%d_%d",ploum-1,i+2),SYM_Y);
		PLACE_RIGHT ("amcsaiouttop_c",NAME ("c_%d_%d",ploum-1,i+2),SYM_Y);


		DEF_PHINS (NAME ("cl4_%d",ploum-1));

			
		/* banc de registres*/
	 	if (t1)	
			{
			j=N-2;
			reg_t1();
			}
		break;
		}

	PLACE_TOP   ("amcsapout_c",NAME ("c_%d_%d",ploum-1,i+1),NOSYM);
	PLACE_LEFT  ("ammuxp_c"   ,NAME ("p_%d_%d",ploum-1,i+1),NOSYM);

	/* pour remonter un lsb de poids pair */
	if (i==N-6)
		{
		PLACE_VIA_REF(NAME("p_%d_%d",ploum-1,i+1),"mi",CONT_VIA);
		}
	}
}
/*_________________________________________________________________*/





/*******************************************************************/
/*                      PLACEMENT ROUTAGE DU CLA                   */
/*******************************************************************/
cla ()
{
int i;
system (NAME ("rsa %d -layout -virtual -msb0 > /dev/null",M+2));
PLACE_RIGHT (NAME ("rsa%daaib",M+2),"cla",NOSYM);
alimout ();
comp [ploum++]='c';
PLACE_RIGHT ("amoutpbot_c","out_0",NOSYM);

/*Pour durcir les connecteurs du slice 0*/
PLACE_VIA_REF ("cla",NAME ("b[%d_7]",M+1),CONT_VIA);
PLACE_VIA_REF ("cla",NAME ("a[%d_2]",M+1),CONT_VIA);

if (t1) 
	{
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,0),"cout_out",0L,"cla",NAME("b[%d_7]",M+1),0L);
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,0),"sum_out", 0L,"cla",NAME("a[%d_2]",M+1),0L);
	}
else
	{
	WIRE1 (ALU2,2,	"cla",NAME ("b[%d_7]",M+1),0L,
			NAME ("cl4_%d",last),"y1next",0L);
	WIRE1 (ALU2,2,	"cla",NAME ("a[%d_2]",M+1),0L,
			NAME ("cl4_%d",last),"cout",0L);
	}


PLACE_VIA_REF  ("cla",NAME ("s[%d_4]",M+1),CONT_VIA);
WIRE1 (ALU2,2,	"cla",NAME ("s[%d_4]",M+1),0L,
		NAME ("out_%d",0),"mnext_in",0L);


/*********************************************************/


for (i=1;i<M;i+=2)
	{
	if (i==1) 
	PLACE_TOP ("amoutibot_c",NAME ("out_%d",i),SYM_Y);
	else if (i>N && i<M)
	PLACE_TOP ("amoutitop2_c",NAME ("out_%d",i),SYM_Y); 
	else
	PLACE_TOP ("amouti_c",NAME ("out_%d",i),SYM_Y);

	/*Pour durcir les connecteurs d'un slice impair*/
	PLACE_VIA_REF ("cla",NAME ("b[%d_7]",M-i+1),CONT_VIA);
	PLACE_VIA_REF ("cla",NAME ("a[%d_2]",M-i+1),CONT_VIA);
if (t1) 
	{
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i),"sum_out" ,0L,"cla",NAME("b[%d_7]",M-i+1),0L);
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i),"cout_out",0L,"cla",NAME("a[%d_2]",M-i+1),0L);
	}
else
	{
	WIRE1 (ALU2,2,	"cla",NAME ("b[%d_7]",M-i+1),0L,
			NAME ("c_%d_%d",last,i),"sumnext_out",0L);
	WIRE1 (ALU2,2,	"cla",NAME ("a[%d_2]",M-i+1),0L,
			NAME ("c_%d_%d",last,i),"cout",0L);
	}

	PLACE_VIA_REF ("cla",NAME ("s[%d_4]",M-i+1),CONT_VIA);
	WIRE1 (ALU2,2,	"cla",NAME("s[%d_4]",M-i+1),0L,
			NAME ("out_%d",i),"mnext_in",0L);

	if (i==M-1)
		
		{
		PLACE_TOP ("amoutptop1_c",NAME ("out_%d",i+1),NOSYM);
	/*Pour durcir les connecteurs d'un slice pair*/
	PLACE_VIA_REF ("cla",NAME ("b[%d_7]",M-i),CONT_VIA);
	PLACE_VIA_REF ("cla",NAME ("a[%d_2]",M-i),CONT_VIA);
if (t1) 
	{
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+1),"cout_out",0L,"cla",NAME("b[%d_7]",M-i),0L);
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+1),"sum_out", 0L,"cla",NAME("a[%d_2]",M-i),0L);
	}
else
	{
	WIRE1 (ALU2,2,	"cla",NAME ("b[%d_7]",M-i),0L,
			NAME ("c_%d_%d",last,i+1),"cout",0L);
	WIRE1 (ALU2,2,	"cla",NAME ("a[%d_2]",M-i),0L,
			NAME ("c_%d_%d",last,i+1),"sumnext_out",0L);
	}

	PLACE_VIA_REF ("cla",NAME ("s[%d_4]",M-i),CONT_VIA);
	WIRE1 (ALU2,2,	"cla",NAME("s[%d_4]",M-i),0L,
			NAME ("out_%d",1+i),"mnext_in",0L);

		PLACE_TOP ("amoutitop1_c",NAME ("out_%d",i+2),SYM_Y);
	/*Pour durcir les connecteurs d'un slice impair*/
	PLACE_VIA_REF ("cla",NAME ("b[%d_7]",M-i-1),CONT_VIA);
	PLACE_VIA_REF ("cla",NAME ("a[%d_2]",M-i-1),CONT_VIA);
if (t1) 
	{
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+2),"sum_out" ,0L,"cla",NAME("b[%d_7]",M-i-1),0L);
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+2),"cout_out",0L,"cla",NAME("a[%d_2]",M-i-1),0L);
	}
else
	{
	WIRE1 (ALU2,2,	"cla",NAME ("b[%d_7]",M-i-1),0L,
			NAME ("c_%d_%d",last,i+2),"sum_out",0L);
	WIRE1 (ALU2,2,	"cla",NAME ("a[%d_2]",M-i-1),0L,
			NAME ("c_%d_%d",last,i+2),"cout",0L);
	}

	PLACE_VIA_REF ("cla",NAME ("s[%d_4]",M-i-1),CONT_VIA);
	WIRE1 (ALU2,2,	"cla",NAME("s[%d_4]",M-i-1),0L,
			NAME ("out_%d",i+2),"mnext_in",0L);


		/*pour permuter circulairement les MSB
                 de deux crans vers le bas*/
 
                PLACE_VIA_REF (NAME ("out_%d",N-2),"m0_o",CONT_VIA);
                PLACE_VIA_REF (NAME ("out_%d",N-2),"lsb_0",CONT_VIA);
                PHSEG (ALU2,2,"",
                        GET_REF_X (NAME("out_%d",N-2),"m0_o"),
                        GET_REF_Y (NAME("out_%d",N-2),"m0_o"),
                        GET_REF_X (NAME("out_%d",N-2),"lsb_0"),
                        GET_REF_Y (NAME("out_%d",N-2),"lsb_0"));
                        
                PLACE_VIA_REF (NAME ("out_%d",N-1),"m1_o",CONT_VIA);
                PLACE_VIA_REF (NAME ("out_%d",N-1),"lsb_0",CONT_VIA);
                PHSEG (ALU2,2,"",
                        GET_REF_X (NAME("out_%d",N-1),"m1_o"),
                        GET_REF_Y (NAME("out_%d",N-1),"m1_o"),
                        GET_REF_X (NAME("out_%d",N-1),"lsb_0"),
                        GET_REF_Y (NAME("out_%d",N-1),"lsb_0"));
		break;
		}

	if ( (i>N-2) && i<M )
	PLACE_TOP ("amoutptop2_c",NAME ("out_%d",i+1),NOSYM);
	else
	PLACE_TOP ("amoutp_c",NAME ("out_%d",i+1),NOSYM);


	/*Pour durcir les connecteurs d'un slice pair*/
	PLACE_VIA_REF ("cla",NAME ("b[%d_7]",M-i),CONT_VIA);
	PLACE_VIA_REF ("cla",NAME ("a[%d_2]",M-i),CONT_VIA);
if (t1) 
	{
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+1),"cout_out",0L,"cla",NAME("b[%d_7]",M-i),0L);
	WIRE1 (ALU2,2,NAME ("r_%d_%d",last+1,i+1),"sum_out", 0L,"cla",NAME("a[%d_2]",M-i),0L);
	}
else
	{
	WIRE1 (ALU2,2,	"cla",NAME ("b[%d_7]",M-i),0L,
			NAME ("c_%d_%d",last,i+1),"cout",0L);
	WIRE1 (ALU2,2,	"cla",NAME ("a[%d_2]",M-i),0L,
			NAME ("c_%d_%d",last,i+1),"sumnext_out",0L);
	}

	PLACE_VIA_REF ("cla",NAME ("s[%d_4]",M-i),CONT_VIA);
	WIRE1 (ALU2,2,	"cla",NAME("s[%d_4]",M-i),0L,
			NAME ("out_%d",1+i),"mnext_in",0L);
	}
}
/*______________________________________________________________________*/




	
/************************************************************************/
/*      	ROUTAGE DES SIGNAUX DE COMMANDE DNC             	*/
/************************************************************************/
cmd ()
{
int i=0,j=0,k=0;
int temp;
int nb_p=0; 		/* compteur de mux 				*/
char prev_ins[10];	/* instance source 				*/
char next_ins[10];	/* instance cible 				*/

DEF_AB (0,0,0,0);

/* pour sortir lsb0 							*/
while (comp[j]!='p') j++;
temp=j;
strcpy (prev_ins,NAME ("cl4_%d",temp+1));
for (j=temp;j<TAILLE_MAX;j++)
	{
	strcpy (next_ins,NAME("%c_%d_%d",comp[j],j,0));
	if (comp[j]=='r') /* si on rencontre un registre 		*/
		{
		WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,next_ins,"D2jbar_in",0L);
		strcpy (prev_ins,next_ins);
		}
	if (comp[j]=='c') /* on a atteind le cla 			*/
		{
		WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,"out_0","lsb_0",0L);
		PLACE_VIA_REF ("out_0","lsb_0",CONT_VIA);
		break;
		}
	}
	

for (i=0;i<N;i+=2)
	{
	/* On veut envoyer la commande C2j de dnc_i a p_i_i 		*/
	strcpy (prev_ins,NAME("d_%d",i));
	nb_p=0;
	for (j=1;j<TAILLE_MAX;j++)
		{
		strcpy (next_ins,NAME("%c_%d_%d",comp[j],j,i+1));

		if (comp[j]=='p') /* si on rencontre un mux 		*/
		nb_p++;

		if (comp[j]=='r') /* si on rencontre un registre 	*/
			{
			WIRE1 (ALU2,2,prev_ins,"C2j_out",0L,next_ins,"C2j_in",0L);
			strcpy (prev_ins,next_ins);
			}

		if (nb_p==i/2+1) /* si on est arrive a destination 	*/
			{
			if (i==3)/* dans le 3ieme slice il faut aller   */
				/* plus loins pour que le premier cl4	*/
				/* prenne C0 pour operande		*/ 
			WIRE1 (ALU2,2,prev_ins,"C2j_out",0L,NAME("c_%d_3",j+1),"c2j_in",0L);
			else
			WIRE1 (ALU2,2,prev_ins,"C2j_out",0L,next_ins,"C2j_in",0L);
			PLACE_VIA_REF (NAME ("p_%d_%d",j,i+1),"C2j_in",CONT_VIA);
			break;
			}
		
		}

	/* On veut envoyer la commande N2j de dnc_i a p_i_i 		*/
	strcpy (prev_ins,NAME("d_%d",i));
	nb_p=0;
	for (j=1;j<TAILLE_MAX;j++)
		{
		strcpy (next_ins,NAME("%c_%d_%d",comp[j],j,i+1));

		if (comp[j]=='p') /* si on rencontre un mux 		*/
		nb_p++;

		if (comp[j]=='r') /* si on rencontre un registre 	*/
			{
			WIRE1 (ALU2,2,prev_ins,"N2j_out",0L,next_ins,"N2j_in",0L);
			strcpy (prev_ins,next_ins);
			}

		if (nb_p==i/2+1) /* si on est arrive a destination 	*/
			{
			WIRE1 (ALU2,2,prev_ins,"N2j_out",0L,next_ins,"N2j_in",0L);
			PLACE_VIA_REF (NAME ("p_%d_%d",j,i+1),"N2j_in",CONT_VIA);
			j++;
			if (i<N-2)
			{
			/* Puis on en profite pour remonter un poids faible */
			while (comp[j]!='p') j++;
			strcpy (prev_ins,NAME ("c_%d_%d",j,i+1));
			PLACE_VIA_REF (NAME ("c_%d_%d",j,i+1),"mi_out",CONT_VIA);
			for (k=j+1;k<TAILLE_MAX;k++)
				{
				strcpy (next_ins,NAME("%c_%d_%d",comp[k],k,i+1));
				if (comp[k]=='r') /* si on rencontre un registre */
					{
					if (strncmp(prev_ins,"c",1)==0)
					WIRE1 (ALU2,2,prev_ins,"mi_out",0L,next_ins,"C2j_in",0L);
					else
					WIRE1 (ALU2,2,prev_ins,"C2j_out",0L,next_ins,"C2j_in",0L);
					strcpy (prev_ins,next_ins);
					}
				if (comp[k]=='c') /* on rencontre le cla */
					{
					if (strncmp(prev_ins,"c",1)==0)
					WIRE1 (ALU2,2,prev_ins,"mi_out",0L,NAME("out_%d",i+1),"lsb_0",0L);
					else
					WIRE1 (ALU2,2,prev_ins,"C2j_out",0L,NAME("out_%d",i+1),"lsb_0",0L);
					PLACE_VIA_REF (NAME ("out_%d",i+1),"lsb_0",CONT_VIA);
					break;
					}
				}
			}

			break;
			}
		
		}

/*************************************************************************************/
	if (i==N-2) break;
/*************************************************************************************/

	/* On veut envoyer la commande D2j de dnc_i a p_i_i */
	strcpy (prev_ins,NAME("d_%d",i+2));
	nb_p=0;
	for (j=1;j<TAILLE_MAX;j++)
		{
		strcpy (next_ins,NAME("%c_%d_%d",comp[j],j,i+2));

		if (comp[j]=='p') /* si on rencontre un mux */
		nb_p++;

		if (comp[j]=='r') /* si on rencontre un registre */
			{
			WIRE1 (ALU2,2,prev_ins,"D2j_out",0L,next_ins,"D2j_in",0L);
			strcpy (prev_ins,next_ins);
			}

		if (nb_p==i/2+2) /* si on est arrive a destination */
			{
			WIRE1 (ALU2,2,prev_ins,"D2j_out",0L,next_ins,"D2j_in",0L);
			PLACE_VIA_REF (NAME ("p_%d_%d",j,i+2),"D2j_in",CONT_VIA);
			break;
			}
		
		}

	/* On veut envoyer la commande D2jbar de dnc_i a p_i_i */
	strcpy (prev_ins,NAME("d_%d",i+2));
	nb_p=0;
	for (j=1;j<TAILLE_MAX;j++)
		{
		strcpy (next_ins,NAME("%c_%d_%d",comp[j],j,i+2));

		if (comp[j]=='p') /* si on rencontre un mux */
		nb_p++;

		if (comp[j]=='r') /* si on rencontre un registre */
			{
			WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,next_ins,"D2jbar_in",0L);
			strcpy (prev_ins,next_ins);
			}

		if (nb_p==i/2+2) /* si on est arrive a destination */
			{
			WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,next_ins,"D2jbar_in",0L);
			PLACE_VIA_REF (NAME ("p_%d_%d",j,i+2),"D2jbar_in",CONT_VIA);
			j++;
			if (i<N-4)
			{
			/* Puis on en profite pour remonter un poids faible */
			while (comp[j]!='p') j++;
			strcpy (prev_ins,NAME ("p_%d_%d",j,i+2));
			PLACE_VIA_REF (NAME ("p_%d_%d",j,i+2),"mi_out",CONT_VIA);
			for (k=j+1;k<TAILLE_MAX;k++)
				{
				strcpy (next_ins,NAME("%c_%d_%d",comp[k],k,i+2));
				if (comp[k]=='r') /* si on rencontre un registre */
					{
					if (strncmp (prev_ins,"p",1)==0)
					WIRE1 (ALU2,2,prev_ins,"mi_out",0L,next_ins,"D2jbar_in",0L);
					else
					WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,next_ins,"D2jbar_in",0L);
					strcpy (prev_ins,next_ins);
					}
				if (comp[k]=='c') /* on rencontre le cla */
					{
					if (strncmp (prev_ins,"p",1)==0)
					WIRE1 (ALU2,2,prev_ins,"mi_out",0L,NAME("out_%d",i+2),"lsb_0",0L);
					else
					WIRE1 (ALU2,2,prev_ins,"D2jbar_out",0L,NAME("out_%d",i+2),"lsb_0",0L);
					PLACE_VIA_REF (NAME ("out_%d",i+2),"lsb_0",CONT_VIA);
					break;
					}
				}
			}

			break;
			}
		
		}
	}
}
/*________________________________________________________________*/




/****************************************************************/
/*           Placement des transparences metal 2                */
/****************************************************************/
allowm2 ()
{
/* transparences sur tout le multiplieur			*/
for (i=0;i<M+2;i+=2)
	{
	THRU_H (TALU2, 2, 60*i+8+5*3);
	THRU_H (TALU2, 2, 60*i+8+5*4);
	THRU_H (TALU2, 2, 60*i+8+5*6);
	THRU_H (TALU2, 2, 60*i+8+5*8);
	THRU_H (TALU2, 2, 60*i+8+5*9);

	THRU_H (TALU2, 2, 60*i+60+7+5*3);
	THRU_H (TALU2, 2, 60*i+60+7+5*5);
	THRU_H (TALU2, 2, 60*i+60+7+5*6);
	THRU_H (TALU2, 2, 60*i+60+7+5*8);
	THRU_H (TALU2, 2, 60*i+60+7+5*9);
	}

/* Acces aux connecteurs virtuels d'entree			*/
COPY_UP_SEG ("b2j3" ,"d_0","");
COPY_UP_SEG ("b2j4" ,"d_0","");
COPY_UP_SEG ("b2j5" ,"d_0","");
COPY_UP_SEG ("b2j6" ,"d_0","");
COPY_UP_SEG ("b2j7" ,"d_0","");
COPY_UP_SEG ("b2j9" ,"d_0","");
COPY_UP_SEG ("b2j12","d_0","");
COPY_UP_SEG ("b2j13","d_0","");

COPY_UP_SEG ("ai14","d_0","");
COPY_UP_SEG ("ai15","d_0","");
COPY_UP_SEG ("ai16","d_0","");

for (i=1;i<(N/2);i++)
	{
	COPY_UP_SEG ("ai3"  ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("ai4"  ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("ai5"  ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("ai14" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("ai15" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("ai16" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("b2j6" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("b2j7" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("b2j9" ,NAME("d_%d",2*i),"");
	COPY_UP_SEG ("b2j12",NAME("d_%d",2*i),"");
	COPY_UP_SEG ("b2j13",NAME("d_%d",2*i),"");
	}


for (i=(N/2);i<(M/2);i++)
	{
	for (j=0;j<20;j++)
		{
		COPY_UP_SEG (NAME("ai%d",j),NAME("d_%d",2*i),"");
		}
	}


for (j=0;j<10;j++)
	{
	COPY_UP_SEG (NAME("ai%d",j),NAME("d_%d",M),"");
	}

/* Acces aux connecteurs virtuels de sortie			*/
for (i=0;i<M;i++)
	{
	for (j=0;j<10;j++)
		{
		COPY_UP_SEG (NAME("p%d",j),NAME("OUT_%d",i),"");
		}
	}

}
/*________________________________________________________________*/




/******************************************************************/
/*	REMONTE LES CONNECTEURS VIRTUELS			  */
/******************************************************************/
vir_con ()
{
int i;
int index;

/* remonte les ref_con des entrees a[i]   			 */
if (msb0) 	index=M-1;
else		index=0;
COPY_UP_REF ("ai1_4",NAME ("d_%d",0),NAME ("a[%d]_4",index  ));
COPY_UP_REF ("ai1_5",NAME ("d_%d",0),NAME ("a[%d]_5",index  ));
COPY_UP_REF ("ai1_6",NAME ("d_%d",0),NAME ("a[%d]_6",index  ));

for (i=2;i<M;i+=2)
	{
	if (msb0 ) 	
		{
		index=M-1-i;
		COPY_UP_REF ("ai_3" ,NAME ("d_%d",i),NAME ("a[%d]_3",index+1));
		COPY_UP_REF ("ai_4" ,NAME ("d_%d",i),NAME ("a[%d]_4",index+1));
		COPY_UP_REF ("ai_5" ,NAME ("d_%d",i),NAME ("a[%d]_5",index+1));
		}
	else 
		{
		index=i;
		COPY_UP_REF ("ai_3" ,NAME ("d_%d",i),NAME ("a[%d]_3",index-1));
		COPY_UP_REF ("ai_4" ,NAME ("d_%d",i),NAME ("a[%d]_4",index-1));
		COPY_UP_REF ("ai_5" ,NAME ("d_%d",i),NAME ("a[%d]_5",index-1));
		}

	COPY_UP_REF ("ai1_4",NAME ("d_%d",i),NAME ("a[%d]_4",index  ));
	COPY_UP_REF ("ai1_5",NAME ("d_%d",i),NAME ("a[%d]_5",index  ));
	COPY_UP_REF ("ai1_6",NAME ("d_%d",i),NAME ("a[%d]_6",index  ));
	}
	
if (msb0) 	index=0;
else		index=M-1;
COPY_UP_REF ("ai_3" ,NAME ("d_%d",M),NAME ("a[%d]_3",index));
COPY_UP_REF ("ai_4" ,NAME ("d_%d",M),NAME ("a[%d]_4",index));
COPY_UP_REF ("ai_5" ,NAME ("d_%d",M),NAME ("a[%d]_5",index));


/* remonte les ref_con des b2j 					 */
for (i=0;i<N;i+=2)
	{
	if (msb0 ) 	
		{
		index=N-1-i;
		COPY_UP_REF ("b2j1_2",NAME ("d_%d",i),NAME ("b[%d]_2",index-1));
		COPY_UP_REF ("b2j1_3",NAME ("d_%d",i),NAME ("b[%d]_3",index-1));
		COPY_UP_REF ("b2j1_5",NAME ("d_%d",i),NAME ("b[%d]_5",index-1));
		COPY_UP_REF ("b2j1_6",NAME ("d_%d",i),NAME ("b[%d]_6",index-1));
		}
	else	 
		{
		index=i;
		COPY_UP_REF ("b2j1_2",NAME ("d_%d",i),NAME ("b[%d]_2",index+1));
		COPY_UP_REF ("b2j1_3",NAME ("d_%d",i),NAME ("b[%d]_3",index+1));
		COPY_UP_REF ("b2j1_5",NAME ("d_%d",i),NAME ("b[%d]_5",index+1));
		COPY_UP_REF ("b2j1_6",NAME ("d_%d",i),NAME ("b[%d]_6",index+1));
		}

	COPY_UP_REF ("b2j_6" ,NAME ("d_%d",i),NAME ("b[%d]_6",index  ));
	COPY_UP_REF ("b2j_7" ,NAME ("d_%d",i),NAME ("b[%d]_7",index  ));
	COPY_UP_REF ("b2j_9" ,NAME ("d_%d",i),NAME ("b[%d]_9",index  ));

	}

/* remonte les ref_con des lsb 					 */
for (i=0;i<N;i++)
	{
	if (msb0 ) 	
		index=M+N-1-i;
	else 
		index=i;
	COPY_UP_REF ("lsb_0",NAME ("out_%d",i),NAME ("p[%d]_0",index));
	COPY_UP_REF ("lsb_1",NAME ("out_%d",i),NAME ("p[%d]_1",index));
	COPY_UP_REF ("lsb_2",NAME ("out_%d",i),NAME ("p[%d]_2",index));
	COPY_UP_REF ("lsb_3",NAME ("out_%d",i),NAME ("p[%d]_3",index));
	COPY_UP_REF ("lsb_4",NAME ("out_%d",i),NAME ("p[%d]_4",index));
	COPY_UP_REF ("lsb_5",NAME ("out_%d",i),NAME ("p[%d]_5",index));
	COPY_UP_REF ("lsb_6",NAME ("out_%d",i),NAME ("p[%d]_6",index));
	COPY_UP_REF ("lsb_7",NAME ("out_%d",i),NAME ("p[%d]_7",index));
	COPY_UP_REF ("lsb_8",NAME ("out_%d",i),NAME ("p[%d]_8",index));
	COPY_UP_REF ("lsb_9",NAME ("out_%d",i),NAME ("p[%d]_9",index));
	}

/* remonte les ref_con des msb 					 */
for (i=0;i<M;i++)
	{
	if (msb0 ) 	
		index=M-1-i;
	else 
		index=i+N;
	COPY_UP_REF ("msb_1",NAME ("out_%d",i),NAME ("p[%d]_1",index));
	COPY_UP_REF ("msb_2",NAME ("out_%d",i),NAME ("p[%d]_2",index));
	COPY_UP_REF ("msb_3",NAME ("out_%d",i),NAME ("p[%d]_3",index));
	COPY_UP_REF ("msb_4",NAME ("out_%d",i),NAME ("p[%d]_4",index));
	COPY_UP_REF ("msb_5",NAME ("out_%d",i),NAME ("p[%d]_5",index));
	COPY_UP_REF ("msb_6",NAME ("out_%d",i),NAME ("p[%d]_6",index));
	COPY_UP_REF ("msb_7",NAME ("out_%d",i),NAME ("p[%d]_7",index));
	COPY_UP_REF ("msb_8",NAME ("out_%d",i),NAME ("p[%d]_8",index));
	COPY_UP_REF ("msb_9",NAME ("out_%d",i),NAME ("p[%d]_9",index));
	}

/* durcissement des alimentations 				 */
for (i=0;i<M+2;i+=2)
	{
	COPY_UP_CON_FACE (WEST,"vss1",NAME ("d_%d",i),"vss");
	COPY_UP_CON_FACE (WEST,"vdd" ,NAME ("d_%d",i),"vdd");
	}
COPY_UP_CON_FACE (WEST,"vss2"  ,NAME ("d_%d",M),"vss");
	
for (i=0;i<M+2;i+=2)
	{
	COPY_UP_CON_FACE (EAST,"vss"  ,NAME ("out_%d",i),"vss");
	COPY_UP_CON_FACE (EAST,"vdd"  ,NAME ("out_%d",i),"vdd");
	}
COPY_UP_CON_FACE (EAST,"vss"   ,NAME ("out_%d",M+1),"vss");

}
/*________________________________________________________________*/





/******************************************************************/
/*        Durcissement des connecteurs				  */
/******************************************************************/
dur_con ()
{
int i;
int index;

/* durcissement des connecteurs ai 				 */
if (msb0) 	index=M-1;
else		index=0;
PLACE_VIA_REF (NAME ("d_%d",0),NAME ("ai1_%d",4),CONT_VIA);
PLACE_SEG_REF (NAME ("d_%d",0),NAME ("ai1_%d",4),ALU2,2,WEST);
PLACE_CON_REF (NAME ("d_%d",0),"ai1",NAME ("a[%d]",index),ALU2,2,WEST);
for (i=2;i<M;i+=2)
	{
	if (msb0)
		{
		index=M-1-i;
		PLACE_VIA_REF (NAME ("d_%d",i),NAME ("ai_%d",5),CONT_VIA);
		PLACE_SEG_REF (NAME ("d_%d",i),NAME ("ai_%d",5),ALU2,2,WEST);
		PLACE_CON_REF (NAME ("d_%d",i),"ai",NAME ("a[%d]",index+1),ALU2,2,WEST);
		}
	else
		{
		index=i;
		PLACE_VIA_REF (NAME ("d_%d",i),NAME ("ai_%d",5),CONT_VIA);
		PLACE_SEG_REF (NAME ("d_%d",i),NAME ("ai_%d",5),ALU2,2,WEST);
		PLACE_CON_REF (NAME ("d_%d",i),"ai",NAME ("a[%d]",index-1),ALU2,2,WEST);
		}

		PLACE_VIA_REF (NAME ("d_%d",i),NAME ("ai1_%d",4),CONT_VIA);
		PLACE_SEG_REF (NAME ("d_%d",i),NAME ("ai1_%d",4),ALU2,2,WEST);
		PLACE_CON_REF (NAME ("d_%d",i),"ai1",NAME ("a[%d]",index),ALU2,2,WEST);
	}
if (msb0) 	index=0;
else		index=M-1;
PLACE_VIA_REF (NAME ("d_%d",M),NAME ("ai_%d",5),CONT_VIA);
PLACE_SEG_REF (NAME ("d_%d",M),NAME ("ai_%d",5),ALU2,2,WEST);
PLACE_CON_REF (NAME ("d_%d",M),"ai",NAME ("a[%d]",index),ALU2,2,WEST);

/* durcissement des alimentations 				 */
for (i=0;i<M+2;i+=2)
	{
	COPY_UP_CON_FACE (WEST,"vss1",NAME ("d_%d",i),"vss");
	COPY_UP_CON_FACE (WEST,"vdd" ,NAME ("d_%d",i),"vdd");
	}
COPY_UP_CON_FACE (WEST,"vss2"  ,NAME ("d_%d",M),"vss");
	
for (i=0;i<M+2;i+=2)
	{
	COPY_UP_CON_FACE (EAST,"vss"  ,NAME ("out_%d",i),"vss");
	COPY_UP_CON_FACE (EAST,"vdd"  ,NAME ("out_%d",i),"vdd");
	}
COPY_UP_CON_FACE (EAST,"vss"   ,NAME ("out_%d",M+1),"vss");



/* durcissement des connecteurs bi 				 */
for (i=0;i<N;i+=2)
	{
	if (msb0)
		{
		index=N-1-i;
		PLACE_VIA_REF (NAME ("d_%d",i),NAME ("b2j1_%d",2),CONT_VIA);
		PLACE_SEG_REF (NAME ("d_%d",i),NAME ("b2j1_%d",2),ALU2,2,WEST);
		PLACE_CON_REF (NAME ("d_%d",i),"b2j1",NAME ("b[%d]",index-1),ALU2,2,WEST);
		}
	else
		{	
		index=i;
		PLACE_VIA_REF (NAME ("d_%d",i),NAME ("b2j1_%d",2),CONT_VIA);
		PLACE_SEG_REF (NAME ("d_%d",i),NAME ("b2j1_%d",2),ALU2,2,WEST);
		PLACE_CON_REF (NAME ("d_%d",i),"b2j1",NAME ("b[%d]",index+1),ALU2,2,WEST);
		}
	
	PLACE_VIA_REF (NAME ("d_%d",i),NAME ("b2j_%d",7),CONT_VIA);
	PLACE_SEG_REF (NAME ("d_%d",i),NAME ("b2j_%d",7),ALU2,2,WEST);
	PLACE_CON_REF (NAME ("d_%d",i),"b2j",NAME ("b[%d]",index),ALU2,2,WEST);

	}

/*
 durcissement des connecteurs pi  poids faibles version  pipeline
if ((t0+t1+n)!=0)
{
for (i=0;i<N;i++)
	{
	if (msb0 ) 	
		index=M+N-1-i;
	else 
		index=i;
	PLACE_VIA_REF (NAME ("out_%d",i),NAME ("lsb_%d",0),CONT_VIA);
	PLACE_SEG_REF (NAME ("out_%d",i),NAME ("lsb_%d",0),ALU2,2,EAST);
	if (i==N-2)
	PLACE_CON_REF (NAME ("out_%d",i),"lsb",NAME ("msb[%d]",index),ALU2,2,EAST);
	else if (i==N-1)
	PLACE_CON_REF (NAME ("out_%d",i),"lsb",NAME ("msb[%d]",index),ALU2,2,EAST);
	else
	PLACE_CON_REF (NAME ("out_%d",i),"lsb",NAME ("lsb[%d]",index),ALU2,2,EAST);
	}
}
else
*/

/* durcissement des connecteurs pi  poids faibles version non  pipeline	 */
for (i=0;i<N;i++)
	{
	if (msb0 ) 	
		index=M+N-1-i;
	else 
		index=i;
	PLACE_VIA_REF (NAME ("out_%d",i),NAME ("lsb_%d",0),CONT_VIA);
	PLACE_SEG_REF (NAME ("out_%d",i),NAME ("lsb_%d",0),ALU2,2,EAST);
	PLACE_CON_REF (NAME ("out_%d",i),"lsb",NAME ("p[%d]",index),ALU2,2,EAST);
	}

/*  durcissement des connecteurs pi  poids forts 			 */
for (i=0;i<M;i++)
	{
	if (msb0 ) 	
		index=M-1-i;
	else 
		index=i+N;
	if (i % 2==0)
		{
		PLACE_VIA_REF (NAME ("out_%d",i),NAME ("msb_%d",5),CONT_VIA);
		PLACE_SEG_REF (NAME ("out_%d",i),NAME ("msb_%d",5),ALU2,2,EAST);
		}
	else
		{
		PLACE_VIA_REF (NAME ("out_%d",i),NAME ("msb_%d",4),CONT_VIA);
		PLACE_SEG_REF (NAME ("out_%d",i),NAME ("msb_%d",4),ALU2,2,EAST);
		}
/*	if ((t0+t1+n)!=0)
	PLACE_CON_REF (NAME ("out_%d",i),"msb",NAME ("msb[%d]",index),ALU2,2,EAST);
	else
*/
	PLACE_CON_REF (NAME ("out_%d",i),"msb",NAME ("p[%d]",index),ALU2,2,EAST);
	}
}
/*______________________________________________________________________*/




/************************************************************************************************/
/*    		          		ROUTAGE DU SCAN						*/
/************************************************************************************************/
scan_rout ()
{
char	prev_ins[10];
char	next_ins[10];
int	i=0;

strcpy (prev_ins,NAME ("r_%d_%d",pipe [i],M+1)); 	/*on cherche le premier registre	*/
while (i++<nreg-1)					/*et tant qu'on n'arrive pas au dernier	*/
	{
	strcpy (next_ins,NAME ("r_%d_%d",pipe[i],M+1));      		/* on tire des fils	*/
	PLACE_VIA_REF (prev_ins,"scanout_r",CONT_VIA);
	PLACE_VIA_REF (next_ins,"scanin_l" ,CONT_VIA);
	WIRE1 (ALU2,2,prev_ins,"scanout_r",0L,next_ins,"scanin_l",0L);	/* du scanout precedent */
	strcpy (prev_ins,next_ins);					/* au  scanin suivant	*/
	}
/* Pour durcir le connecteur scanin		 						*/
COPY_UP_CON_FACE (NORTH,"scanin" ,NAME ("r_%d_%d",pipe [0]     ,M+1),"scanin");
/* pour durcir le connecteur scanout								*/
COPY_UP_CON_FACE (NORTH,"scanout",NAME ("r_%d_%d",pipe [nreg-1],M+1),"scanout");
}
/*______________________________________________________________________________________________*/





/************************************************************************************************/
/* 		REMONTE LES CONNECTEURS POUR LE PIPELINE					*/
/************************************************************************************************/
reg_con ()
{
char	prev_ins[10];
char	next_ins[10];
int	i;	
		/*pour la premiere colonne de registres on remonte les connecteurs ck sd st 	*/
COPY_UP_CON_FACE (NORTH,"ck",NAME ("r_%d_%d",pipe [0],M+1),"ck");
COPY_UP_CON_FACE (NORTH,"sd",NAME ("r_%d_%d",pipe [0],M+1),"sd");
COPY_UP_CON_FACE (NORTH,"st",NAME ("r_%d_%d",pipe [0],M+1),"st");

/* puis on connecte ces signaux en interne						      	*/
i=0;
strcpy (prev_ins,NAME ("r_%d_%d",pipe [i],M+1)); 	/*on cherche le premier registre	*/
while (i++<nreg-1)					/*et tant qu'on n'arrive pas au dernier	*/
	{
	strcpy (next_ins,NAME ("r_%d_%d",pipe[i],M+1));      		/* on tire des fils	*/
	PLACE_VIA_REF (prev_ins,"sd_ci",CONT_VIA);			/* du sd		*/
	PLACE_VIA_REF (next_ins,"sd_ci" ,CONT_VIA);			/* precedent		*/
	WIRE1 (ALU2,2,prev_ins,"sd_ci",0L,next_ins,"sd_ci",0L);
	strcpy (prev_ins,next_ins);					/* au  sd suivant	*/
	}
	
i=0;
strcpy (prev_ins,NAME ("r_%d_%d",pipe [i],M+1)); 	/*on cherche le premier registre	*/
while (i++<nreg-1)					/*et tant qu'on n'arrive pas au dernier	*/
	{
	strcpy (next_ins,NAME ("r_%d_%d",pipe[i],M+1));      		/* on tire des fils	*/
	PLACE_VIA_REF (prev_ins,"st_ci",CONT_VIA);			/* du st		*/
	PLACE_VIA_REF (next_ins,"st_ci" ,CONT_VIA);			/* precedent		*/
	WIRE1 (ALU2,2,prev_ins,"st_ci",0L,next_ins,"st_ci",0L);
	strcpy (prev_ins,next_ins);					/* au  st suivant	*/
	}

i=0;
strcpy (prev_ins,NAME ("r_%d_%d",pipe [i],M+1)); 	/*on cherche le premier registre	*/
while (i++<nreg-1)					/*et tant qu'on n'arrive pas au dernier	*/
	{
	strcpy (next_ins,NAME ("r_%d_%d",pipe[i],M+1));      		/* on tire des fils	*/
	PLACE_VIA_REF (prev_ins,"ck_ci",CONT_VIA);			/* du ck		*/
	PLACE_VIA_REF (next_ins,"ck_ci" ,CONT_VIA);			/* precedent		*/
	WIRE1 (ALU2,2,prev_ins,"ck_ci",0L,next_ins,"ck_ci",0L);
	strcpy (prev_ins,next_ins);					/* au  ck suivant	*/
	}
}
/*______________________________________________________________________________________________*/





/************************************************************************/
/*                           Fermeture du fichier .ap             	*/
/************************************************************************/
end_cell  ()
{
SAVE_PHFIG ();	/* sauvegarde le fichier contenant le layout sur disque */
}
/*______________________________________________________________________*/

