/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :synthetiseur de FPGA					    */
/*    Fichier :anealing                                                     */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :Burgun L.                              le : 03/04/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
#include <math.h>
#include "../compil/lax_param.h"
#include "fp_type.h"
#include "../compil/sl_util.h"
#include "../bddorder/bdd_order.h"
#include "fpga.h"


/*----------------------------------------------------------------------------
avance	: tabulation pour la profondeur
------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void avance(level)
int level;
{
int i;
for(i=0;i<level;i++)
   printf("         ");
}

/*----------------------------------------------------------------------------
synthIntFPGA	: fonction interne de cout des FPGA pour guider 
                  le re-odonnancement
------------------------------------------------------------------------------
retour		: un pointeur de liste chainee (support)
                  un cout (entier) -> par adresse
------------------------------------------------------------------------------*/
chain_list *synthIntFPGA(pt,pCount,fatherBdd, pLstCLB4,pLevel,tabLevel)
pNode pt;
int *pCount;
pTH fatherBdd;
chain_list **pLstCLB4;
int *pLevel;
pTH tabLevel;
{
chain_list *lstLow, *lstHigh;
chain_list *res;
int lenRes;
pNode pBdd, low, high;
int coupure = 0;
int levelLow = 0;
int levelHigh = 0;

if (pt->index < 2)	/* noeud terminal */
   return (NULL);

if ((pt->low)->index < 2 && (pt->high)->index < 2)	/* noeud atomique */
   {
   return(addchain(NULL,pt->index));
   }

			/* noeud deja traite */

if (pt->mark == 1)	/* CLB de fonction directe */
   {
   printf("%d reduit 1\n",pt);
   *pLevel = 1 + searchTH(tabLevel,pt);
   return(addchain(NULL,pt));
   }

if (pt->mark == 2)	/* CLB de fonction inverse */
   {
   printf("%d reduit 2\n",notBdd(pt));
   *pLevel = 1 + searchTH(tabLevel,notBdd(pt));
   return(addchain(NULL,notBdd(pt)));
   }

		/* simplifications eventuelles avant l'appel
                   recursif sur les fils */

high = pt->high;
low = pt->low;

if (RULES_DC)
   {
   pNode simplifHigh, simplifLow;

   pBdd = applyBinBdd(AND,high,low);

   if (pBdd == pt->low)
      {
      simplifHigh = simplifDcOneBdd(high,low);
      high = simplifHigh;
      }

   if (pBdd == pt->high)
      {
      simplifLow = simplifDcOneBdd(low,high);
      low = simplifLow;
      }
   }

lstLow = synthIntFPGA(low,pCount,fatherBdd, pLstCLB4,&levelLow,tabLevel);
lstHigh = synthIntFPGA(high,pCount,fatherBdd, pLstCLB4,&levelHigh,tabLevel);

if (levelLow > levelHigh)
   *pLevel = levelLow;
else
   *pLevel = levelHigh;


while (1)
   {
   pNode ptInv;
   chain_list *toto;
   int resIndex;

	 /* fusion lexico-graphique des listes chainees */	

   res = (chain_list *) fusionLC(lstLow,lstHigh);
    

   lenRes = countChain_list(res);


   if (lenRes < SUPPORTMAX)
      {
      freechain(lstLow);
      freechain(lstHigh);
      if (coupure)
         *pLevel = *pLevel + 1;
      return(addchain(res,pt->index));
      }

   if (lenRes == SUPPORTMAX)	/* CLB */
      {
      chain_list *lc;

      avance(*pLevel);
      printf("%d = (%d ",pt,pt->index);
      lc = res;
      while (lc)
         {
         printf("%d ", lc->DATA);
         lc = lc->NEXT;
         }
      printf(")\n");

      freechain(lstLow);
      freechain(lstHigh);
      freechain(res);

      pt->mark = 1;
      ptInv = notBdd(pt);
      ptInv->mark = 2; 

      addTH(tabLevel,pt,*pLevel);
      *pCount = *pCount + 1;
      *pLevel = *pLevel+1;
      return(addchain(NULL,pt));
      }

   if (lenRes > SUPPORTMAX)	/* on coupe un fils */
      {
      int lenHigh, lenLow;
      int numInputHigh, numInputLow;

      lenLow  = countChain_list(lstLow);
      lenHigh = countChain_list(lstHigh);

      if (X3000 && lenRes == SUPPORTMAX + 1)
         {
            		/* CLB 2 sorties */

         if (lenLow > 3 && lenHigh > 3)
            {
            chain_list *lc;

            avance(*pLevel);
            printf("%d = (",low);
            lc = lstLow;
            while (lc)
               {
               printf("%d ", lc->DATA);
               lc = lc->NEXT;
               }

            printf(") + %d = (",high);
            lc = lstHigh;
            while (lc)
               {
               printf("%d ", lc->DATA);
               lc = lc->NEXT;
               }
            printf(")\n");

            low->mark = 1;
            ptInv = notBdd(low);
            ptInv->mark = 2; 

            high->mark = 1;
            ptInv = notBdd(high);
            ptInv->mark = 2; 

            *pCount = *pCount + 1;
            freechain(lstLow);
            freechain(lstHigh);
            freechain(res);
            res = addchain(NULL,high);
            res = addchain(res,low);
            res = addchain(res,pt->index);

            addTH(tabLevel,high,*pLevel);
            addTH(tabLevel,low,*pLevel);
            *pLevel = *pLevel+1;
            return(res);
            }
         }


		/* en cas d'egalite, on coupe celui qui a le plus
                   d'entrees primaires dans le support */

      if (lenLow == lenHigh)
         {
         chain_list *lc;
         int numInputLow = 0;
         int numInputHigh = 0;

         lc = lstLow;
         while (lc)
            {
            if ((long)lc->DATA < 1000)
               numInputLow++;
            lc = lc->NEXT;
            }
         lc = lstHigh;
         while (lc)
            {
            if ((long)lc->DATA < 1000)
               numInputHigh++;
            lc = lc->NEXT;
            }
         lenLow = numInputLow;
         lenHigh = numInputHigh;
         }

      if (lenLow > lenHigh)
         {
         chain_list *lc;

         coupure = 1;
         avance(levelLow);

         printf("%d = (",low);
         lc = lstLow;
         while (lc)
            {
            printf("%d ", lc->DATA);
            lc = lc->NEXT;
            }
         printf(")\n");

			/* on cree un CLB pour low */

         low->mark = 1;
         ptInv = notBdd(low);
         ptInv->mark = 2; 
         *pCount = *pCount + 1;

         addTH(tabLevel,low,levelLow);
         *pLstCLB4 = addchain(*pLstCLB4,lstLow);
         freechain(res);
         lstLow = addchain(NULL,low);
         }
      else
			/* on cree un CLB pour high */
         {
         chain_list *lc;

         coupure = 1;
         avance(levelHigh);

         printf("%d = (",high);
         lc = lstHigh;
         while (lc)
            {
            printf("%d ", lc->DATA);
            lc = lc->NEXT;
            }
         printf(")\n");

         high->mark = 1;
         ptInv = notBdd(high);
         ptInv->mark = 2; 
         *pCount = *pCount + 1;

         addTH(tabLevel,high,levelHigh);
         *pLstCLB4 = addchain(*pLstCLB4,lstHigh);
         freechain(res);
         lstHigh = addchain(NULL,high);
         }
      }
   }
}
/*----------------------------------------------------------------------------
synthFPGA	: fonction de synthese des FPGA 
------------------------------------------------------------------------------
retour		: un cout (entier)
------------------------------------------------------------------------------*/
int synthFPGA(pt,fatherBdd,pLstCLB4,tabLevel)
pNode pt;
pTH fatherBdd;
chain_list **pLstCLB4;
pTH tabLevel;
{
int level = 0;
chain_list *res;
int count = 0;		/* nombre de CLB utilise */

res = synthIntFPGA(pt,&count,fatherBdd,pLstCLB4,&level,tabLevel);

if (res == NULL || res->NEXT == NULL && pt->mark != 2)
   {
   if (res) freechain(res);
   return(count);
   }
else
   {
   chain_list *lc;
   pNode ptInv;

   avance(level);
   printf("%d = (",pt);
   lc = res;
   while (lc)
      {
      printf("%d ", lc->DATA);
      lc = lc->NEXT;
      }
   printf(")\n");

   if (countChain_list(res) < 5)
      *pLstCLB4 = addchain(*pLstCLB4,res);
   else
      freechain(res);

   pt->mark = 1;
   ptInv = notBdd(pt);
   ptInv->mark = 2; 
   return(1 + count);
   }
}

/*-------------------------------------------------------------------------
printList	: display of  a chain list 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void printList(ls)
chain_list *ls;
{
chain_list *cl;
cl = ls;
printf("(");
while (cl)
   {
   printf(" %d",cl->DATA);
   cl = cl->NEXT;
   }
printf(")\n");
}

/*-------------------------------------------------------------------------
printList2	: display of  a chain list of chain lists
---------------------------------------------------------------------------
returns		:  void.
---------------------------------------------------------------------------*/

void printList2(ls)
chain_list *ls;
{
chain_list *cl;

cl = ls;
while (cl)
   {
    printList(cl->DATA);
   cl = cl->NEXT;
    }
 }




/*-------------------------------------------------------------------------
scanList	: scans a chain list of chain lists 
---------------------------------------------------------------------------
retour		: The pointer for the larger element (in number of elements)
---------------------------------------------------------------------------*/

chain_list *scanList(lst)
chain_list *lst;

{
chain_list *pg = NULL;
chain_list *pt = NULL;
chain_list *auxlst = NULL;

/*d
printf("entrou na scanlist  \n");
*/  
pg = lst->DATA;
pt = lst;
/*d
printf("the first is "); 
printList(pg);
*/
while (lst)
   {
    auxlst = lst->DATA;
    if (countChain_list(lst->DATA) <  countChain_list(pg))
       {
/*d
	 printf("achou um maior %d \n",countChain_list(auxlst));
*/
       pg = lst->DATA;
       pt = lst;  
       }   
    lst = lst->NEXT;
    }
/*d
printf("the larger is "); 
printList(pg);
printf("saiu da scanlist \n");
*/
return(pt);
} 

/* -------------------------------------------------------------------------
copylst2(lst) 	: create a copy of a chain_list of chain_lists 
---------------------------------------------------------------------------
retour		: a copy of a chain_list of chain_lists
---------------------------------------------------------------------------*/

chain_list *copylst(lst)
chain_list *lst;

{
chain_list *newlist=NULL;
/*d
printf("Entrou na copylst \n");
printf("vai tratar a lista: \n");
   printList(lst);
*/
while(lst)
      {
      newlist = addchain(newlist,lst->DATA);
      lst = lst->NEXT;
      }
/*d
printf("newlist e': \n");
   printList(newlist);
*/
return(newlist);
}
 


chain_list *copylst2(lst2) 
chain_list *lst2;

{ 
chain_list *newlist2=NULL;
/*d
printf("Entrou na copylst2 \n");
*/
while (lst2)
   {
/*d
   printf("vai tratar a lista: \n");
   printList(lst2->DATA);
*/
   newlist2 = addchain(newlist2,copylst(lst2->DATA));
/*d
   printf("a nova lista fica : \n");
   printList2(newlist2);
 */
   lst2 = lst2->NEXT;
   }
return (newlist2);
}


 /*******************************************************************************
* function delchain2()                                                          *
* delete a single element of a chain_list and gives it back to freechain       *
*******************************************************************************/
chain_list *delchain2(pthead, ptdel)
chain_list *pthead;
chain_list *ptdel;
{
chain_list *ptaux;
chain_list *pt;
chain_list *ptsav;
/*d
printf("entrou na delchain2 \n");
printf("vai deletar : \n ");
printList(ptdel);
printf("da lista : \n");
printList2(pthead);
*/
	if (pthead == NULL || ptdel == NULL)
           {
		(void)fflush(stdout);
		(void)fprintf(stderr,"*** mbk error ***");
		(void)fprintf(stderr,"  delchain() impossible : pointer = NULL !\n");
		EXIT(1);
	   }

	if (ptdel == pthead)
           {
               	pt = pthead->NEXT;
		pthead->NEXT = NULL;
		freechain(pthead);
		return pt;
	   }
        else 
           { 
	      for (pt = pthead; pt; pt = pt->NEXT)
                   {
/*d
                         printf("               ptdel :%d \n",ptdel);
                         printf("              pt->DATA : %d  \n",pt->DATA);
*/
 		     if (pt->DATA == ptdel)
                         {
/*d
                         printf("				achou o igual \n");
                         printList(ptdel); 
                         printf("				achou o igual \n");
                         printList(pt->DATA);
*/ 
                 	 break;
                         }
                    ptsav = pt;
		   }
		if (pt != NULL)
                   {
/*d
			printf("vai deletar o :\n");
                        printList(ptdel);
*/
			ptsav->NEXT = pt->NEXT;
			ptdel->NEXT = NULL;
/*d 
                        printf("               pt  : %d  \n", pt  );
                        printf("               ptsav : %d  \n", ptsav );
                        printf("               ptsav->NEXT :%d \n", ptsav->NEXT);
*/
			freechain(ptdel);
/*d 
                        printf("saiu da delchain2 \n");
                        printf("                    vai ficar :\n");
                        printList2(pthead);
*/
			return pthead;
		   }
               else
			{
/*d
            		printf("saiu 3");
*/
			return NULL;
			}
	   }
/*d
printf("saiu da delchain2 \n");
*/
}


/*******************************************************************************
* function delchain1()                                                          *
* delete a single element of a chain_list and gives it back to freechain       *
*******************************************************************************/
chain_list *delchain1(pthead, ptdel)
chain_list *pthead;
chain_list *ptdel;
{
chain_list *pt;
chain_list *ptsav;

	if (pthead == NULL || ptdel == NULL) {
		(void)fflush(stdout);
		(void)fprintf(stderr,"*** mbk error ***");
		(void)fprintf(stderr,"  delchain() impossible : pointer = NULL !\n");
		EXIT(1);
	}

	if (ptdel == pthead) {
		pt = pthead->NEXT;
		pthead->NEXT = NULL;
		freechain(pthead);
		return pt;
	}
        else {
    		for (pt = pthead; pt; pt = pt->NEXT) {
/*d
                printf("               pt  : %d  \n", pt  );
                printf("               ptdel  : %d  \n", ptdel  );
*/
                if (pt == ptdel)
			break;
		ptsav = pt;
		}
		if (pt != NULL) {
			ptsav->NEXT = pt->NEXT;
			ptdel->NEXT = NULL;
			freechain(ptdel);
			return pthead;
		} else
			return NULL;
	}
}


/*******************************************************************************
* function addchain2()                                                          *
* chain list specialized allocator to avoid too many mallocs                   *
*******************************************************************************/
chain_list *addchain2(pthead, ptdata)
chain_list *pthead;
chain_list *ptdata;
{
chain_list *pt;
register int i;
/*d
printf("entrou na adddchain2 \n");
*/

	if (HEAD_CHAIN == NULL) {
		pt = (chain_list *)mbkalloc(BUFSIZE*sizeof(chain_list));
		HEAD_CHAIN = pt;
		for (i = 1; i < BUFSIZE; i++) {
			pt->NEXT = pt + 1;
			pt++;
		}
		pt->NEXT = NULL;
	}

	pt = HEAD_CHAIN;
	HEAD_CHAIN = HEAD_CHAIN->NEXT;
	pt->NEXT = pthead;
	pt->DATA = ptdata;
	return pt;
/*d
printf("saiu da addchain2 \n");
*/
}



/* -------------------------------------------------------------------------
displayCLB4 	: display of  CLBs with a support <= 4 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
displayCLB4(lst)
 
chain_list *lst;

{
chain_list *listeordonne = NULL;
chain_list *listeaux = NULL; 
chain_list *ls = NULL;
chain_list *aux = NULL;
chain_list *pg = NULL; 
chain_list *pt = NULL;
chain_list *first = NULL;
chain_list *plusgrand= NULL ;


ls = lst; 
 /*d  printList2(ls);
*/ 
aux = copylst2(ls);
while (ls)
    {
    plusgrand = scanList(aux);

 /*d   printList(plusgrand->DATA);
    printf("\n                         INICIO DO LOOP \n");
    printf("\n the larger one has %d elements \n",countChain_list(plusgrand->DATA));

    printf(" the larger is' ");
    printList(plusgrand->DATA);
  
    
    printf("the list BEFORE delete is: \n");

    printList2(aux);
    printf("the larger will be deleted \n");

    printf(" The element is added to the new ordered list  \n");
*/
    pg = copylst(plusgrand->DATA);
    listeordonne = addchain(listeordonne,pg); 

 /*d   printf("the new ordered list is: \n");
    printList2(listeordonne);
*/
    aux = delchain1(aux,plusgrand); 

 /*d       printf("the list AFTER delete is: \n");
    printList2(aux);
*/
    ls = ls->NEXT;
    }
      
printf("\n ordered CLB4 list is:\n");
printList2(listeordonne);
printf(" Number of at most 4-input functions %d \n", countChain_list(listeordonne));
printf("number of matched CLBs = %d  \n" ,regroupeXMap(listeordonne));

}

 


/*-------------------------------------------------------------------------
searchelemlist		: searchs one element (a list) in a chain list of
			  chain lists	 ---------------------------------------------------------------------------
returns			: a pointer to this element  ---------------------------------------------------------------------------*/
chain_list *searchelemlist(list, elem)
chain_list *list;
chain_list *elem;
{
while(list)
   {
    if (list->DATA != elem)
       list = list->NEXT;
    else
      return(list);
    }
return(list);
}

/*-------------------------------------------------------------------------
remgreatlist		: removes from a chain list of chain lists
			  the larger one
---------------------------------------------------------------------------
returns			:  a a chain list of chain lists without
			  the larger one
---------------------------------------------------------------------------*/
chain_list *remgreatlist(cl,newlist)

chain_list *cl;
chain_list *newlist;

{
int count, larger;
chain_list *lstlarger, *great, *savelist;

larger = 1;
lstlarger = cl;
savelist = cl;
printf("list beeing scanned  :\n");
printList2(cl);

while (cl)
   {
   count = countChain_list(cl->DATA);
   if (count > larger)
      {
         printf("new larger is : %d \n",count);
         larger = count;
         lstlarger = cl->DATA;
      }
   cl = cl->NEXT;
    }
great = searchelemlist(lstlarger); 
return(great); 
}





/*-------------------------------------------------------------------------
orderingCLBlist		: ordering a chain list by number of elem.
---------------------------------------------------------------------------
returns			: the ordered chain list
---------------------------------------------------------------------------*/

chain_list *orderingCLBlist(clblist)

chain_list *clblist;

{
chain_list *lstlarger;
chain_list *cl, *claux;
chain_list *newcl = NULL;
int  count;
 

cl = clblist;
claux = cl;

count = countChain_list(cl->DATA);

while (count)
   {
   ;
      
   cl = cl->NEXT;
   }
 return(newcl);
}



/*-------------------------------------------------------------------------
bdd2FpgaBeh 	: regeneration des abl(s) du circuit en FPGA 
---------------------------------------------------------------------------
---------------------------------------------------------------------------*/
void bdd2FpgaBeh(beh)
befig_list *beh;
{
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
binode_list *binode;
biabl_list *biabl;
pTH fatherBdd;
int numCLB;
chain_list *lstCLB4=NULL;
chain_list *clordered;
chain_list *cl,*clint;
chain_list **claux;
pTH tabLevel;

printf("bdd2FpgaBeh Running...\n\n");

	/* calcul du nombre de peres */


fatherBdd = (pTH) computeFathersBddBeh(beh);
if (FP_TRACE == 3) 
   displayTH(fatherBdd);

markAllBdd(0);
numCLB = 0;
tabLevel = createTH(500);

out = beh->BEOUT;
while (out) 
   {
   if (out->NODE)
      {
      numCLB = numCLB + synthFPGA(out->NODE,fatherBdd,&lstCLB4,tabLevel);
      printf("\nOutput '%s' CLB = %d\n",out->NAME,numCLB);
      }
   else
      {
      printf("bdd2FpgaBeh : error there's no graph on %s !\n",out->NAME);
      exit(-1);
      }
   out = out->NEXT;
   }

if (FP_AUX)
   {
   aux = beh->BEAUX;
   while (aux) 
      {
      if (aux->NODE)
         {
         numCLB = numCLB + synthFPGA(aux->NODE,fatherBdd,&lstCLB4,tabLevel);
         printf("\nAux '%s' CLB = %d\n",aux->NAME,numCLB);
         }
      else
         {
         printf("bdd2FpgaBeh : error there's no graph on %s !\n",aux->NAME);
         exit(-1);
         }
      aux = aux->NEXT;
      }
   }

reg = beh->BEREG;
while (reg) 
   {
   binode = reg->BINODE;
   while (binode)
      {
      if (binode->CNDNODE && binode->VALNODE)
         {
         numCLB = numCLB + synthFPGA(binode->VALNODE,fatherBdd,&lstCLB4,tabLevel);
         numCLB = numCLB + synthFPGA(binode->CNDNODE,fatherBdd,&lstCLB4,tabLevel);
         printf("\nRegister '%s' CLB = %d\n",reg->NAME,numCLB);
         }
      else
         {
         printf("bdd2FpgaBeh : error there's no graph on %s !\n",out->NAME);
         exit(-1);
         }
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

printf("\nCLB4 :\n");
*claux = lstCLB4;
cl = lstCLB4;
while (cl)
   {
   clint = cl->DATA;
   printf("(");
   while (clint)
      {
      printf(" %d",clint->DATA);
      clint = clint->NEXT;
      }
   printf(")\n");
   cl = cl->NEXT;
   }
/*d
printf("\n");
printList2(lstCLB4);
printf("vai entrar na displayCLB4 \n");
*/
displayCLB4(claux);
/*d
printf("saiu da displayCLB4 \n");
*/


/*
clordered =  orderingCLBlist(lstCLB4);
while (clordered)
   {
   clint = clordered->DATA;
   printList(clint);
   clordered = cl->NEXT;
    }
*/


printf("End of bdd2FpgaBeh\n");
destroyTH(tabLevel);
}



/*-------------------------------------------------------------------------
anealingFPGA 	: recuit simule pour l'optimisation FPGA 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/

void anealingFPGA(beh,trace)
befig_list *beh;
int trace;
{
tabSolutionFPGA *tabSol;
chain_list *order;
int level;

int numCLB,depthCLB;
int amplitude;
int numberSol,indiceMin,coutMin;
int i;
int existDC;
chain_list *lst, *lstExpr;

printf("Running FPGA Optimizer on `%s`...\n",beh->NAME);

if (FP_GUARDEDAUX)
   printf("Warning : there exists some intermediate signals !!!\n");


printf("==============================  INITIAL COST  ==================================\n");

costFpgaBeh(beh,costFPGA,&numCLB,&depthCLB);

printf("Total number of 5-LUT = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costX3000Beh(beh,&numCLB,&depthCLB);

printf("Total number of X3000 = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costFpgaBeh(beh,costX4000,&numCLB,&depthCLB);

printf("Total number of X4000 = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costFpgaBeh(beh,costACT1,&numCLB,&depthCLB);

printf("Total number of ACT1  = %d\n",numCLB);
printf("Depth in ACT1         = %d\n",depthCLB);

costFpgaBeh(beh,numberNodeBdd,&numCLB,&depthCLB);

printf("Total number of BDD   = %d\n",numCLB);
printf("Depth in BDD          = %d\n",depthCLB);
printf("===============================================================================\n");

		/* prise en compte des Don't care */

        /* existe-t-il des constantes 'd' dans les expressions ? */
 
lstExpr = exprToCLBeh(beh);
lst = lstExpr;
existDC = 0;
while (lst)
   {
   if (searchExpr((chain_list *)lst->DATA,"'d'"))
      existDC = 1;
   lst = lst->NEXT;
   }
freechain(lstExpr);
 
if (existDC)    /* appel au traitement des don't care */
   {
   for (i=0;i<2;i++)
      {
      if (FP_FAMILY == X3000)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costX3000); 

      if (FP_FAMILY == X4000)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costFPGA); 

      if (FP_FAMILY == ACT1)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costACT1); 

      if (FP_FAMILY == XNODE)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,numberNodeBdd); 

      makeBddBeh(beh,beh->CIRCUI,0,trace,200,1000000,NULL);
      }

   if (FP_FAMILY == X3000)
      traitementDCBeh(beh,trace,costX3000);

   if (FP_FAMILY == X4000)
      traitementDCBeh(beh,trace,costFPGA);

   if (FP_FAMILY == ACT1)
      traitementDCBeh(beh,trace,costACT1);

   if (FP_FAMILY == XNODE)
      traitementDCBeh(beh,trace,numberNodeBdd);
   }


		/* calcul de l'amplitude */

amplitude = 10;
level = FP_LEVEL;

tabSol = (tabSolutionFPGA *) mbkalloc (100 * sizeof(tabSolutionFPGA));
numberSol = 0;

printf("\n============== Simulated Anealing ===============\n");

while (amplitude >= 0 && level >= 1)
   {
   for (i=2;i>0;i--)
      {
		/* calcul de l'ordonnancement par gradient */


      if (FP_FAMILY == X3000)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costX3000); 

      if (FP_FAMILY == X4000)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costFPGA); 

      if (FP_FAMILY == ACT1)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,costACT1); 

      if (FP_FAMILY == XNODE)
         order = makeOrderBddBeh(beh,0,NULL,NULL,1,5,1,trace,50,1,numberNodeBdd); 

      regenereBddBeh(beh,order);
      makeBddBeh(beh,beh->CIRCUI,0,trace,200,1000000,NULL);

		      	/* calcul d'une nouvelle solution */

      if (i == 1)
         {
         if (FP_FAMILY == X3000)
            costX3000Beh(beh,&numCLB,&depthCLB);

         if (FP_FAMILY == X4000)
            costFpgaBeh(beh,costX4000,&numCLB,&depthCLB);

         if (FP_FAMILY == ACT1)
            costFpgaBeh(beh,costACT1,&numCLB,&depthCLB);

         if (FP_FAMILY == XNODE)
            costFpgaBeh(beh,numberNodeBdd,&numCLB,&depthCLB);

         tabSol[numberSol].numCLB = numCLB;
         tabSol[numberSol].depthCLB = depthCLB;
         tabSol[numberSol].order = copyChain_list(order);
         numberSol++;

         }
      }

   		/* recuit simule */

   if (amplitude > 0 && level > 1)
      {
      order = randomOrder(order,amplitude);
      regenereBddBeh(beh,order);
      makeBddBeh(beh,beh->CIRCUI,0,trace,200,1000000,NULL);
      }
   if (amplitude > 1)
      amplitude--;
   level--;
   }

		/* choix de la meilleure solution */

coutMin = 10000000;
for (i=0;i<numberSol;i++)
   {
   int coutI = tabSol[i].numCLB;
   if (coutMin > coutI)
      {
      coutMin = coutI;
      indiceMin = i;
      }
   }

order = tabSol[indiceMin].order;

regenereBddBeh(beh,order);
makeBddBeh(beh,beh->CIRCUI,0,trace,200,1000000,NULL);


printf("===============================  FINAL COST  ===================================\n");

costFpgaBeh(beh,costFPGA,&numCLB,&depthCLB);
printf("Total number of 5-LUT = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costX3000Beh(beh,&numCLB,&depthCLB);

printf("Total number of X3000 = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costFpgaBeh(beh,costX4000,&numCLB,&depthCLB);

printf("Total number of X4000 = %d\n",numCLB);
printf("Depth in CLB          = %d\n",depthCLB);

costFpgaBeh(beh,costACT1,&numCLB,&depthCLB);

printf("Total number of ACT1  = %d\n",numCLB);
printf("Depth in ACT1         = %d\n",depthCLB);

costFpgaBeh(beh,numberNodeBdd,&numCLB,&depthCLB);

printf("Total number of BDD   = %d\n",numCLB);
printf("Depth in BDD          = %d\n",depthCLB);
printf("===============================================================================\n");

		/* calcul de l'amplitude */

printf("End of the FPGA Optimizer\n");

mbkfree(tabSol);
}
