/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :synthetiseur logique					    */
/*    Fichier :sl_facto.c                                                   */
/*                                                                          */
/*    (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 : 20/12/1994     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
#include <math.h>
#include "../compil/lax_param.h"
#include "../synthe/sl_type.h"
#include "../compil/sl_util.h"
#include "../bddorder/bdd_order.h"
#include "sl_facto.h"
#include "optim.h"


/*-------------------------------------------------------------------------
coutAblBeh 	: calcule le cout d'une befig avec ces ABL.
			- lit : nombre de litteraux non reduits.
			- maxLit : max du nombre de litteraux non reduits.
			- litRed : nombre de litteraux reduits.
			- litReg : nombre de litteraux equivalent registre.
			- profMax : profondeux max.
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
coutAblBeh(beh,lit,maxLit,litRed,profMax,delaisMax,operBin,litReg,mode,delayPI)
befig_list *beh;
int *lit,*maxLit,*litRed,*profMax,*delaisMax,*operBin,*litReg;
int mode;
ptype_list *delayPI;
{
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
long numberAtomExprBehInt;
long numberAtomExprBehIntVal;
long numberAtomExprBehIntCnd;

int profExprBehInt;
int profExprBehIntVal;
int profExprBehIntCnd;

	/* initialisation */

long _lit = 0;
long _maxLit = 0;
int _litRed = 0;
int _litReg = 0;
int _profMax = 0;
int _delaisMax = 0;
int _numberOperBin = 0;

pTH caracTH;
pTH caracBeh();
pTH profTH;
pTH numberTH;
                /* caracterisation */

caracTH = caracBeh(beh,delayPI,0);

profTH = createTH(100);
numberTH = createTH(100);


out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      _litRed	= _litRed + numberAtomExpr(out->ABL);
      _numberOperBin	= _numberOperBin + numberOperBinExpr(out->ABL);
      numberAtomExprBehInt = numberAtomExprBeh(beh,out->ABL,numberTH);
      _lit 	= _lit + numberAtomExprBehInt;
      profExprBehInt = profExprBeh(beh,out->ABL,profTH); 

      if (mode == 1)
         {
         printf("%s = ",out->NAME);
         printf("(%d",numberAtomExprBehInt);
         printf(", %d",profExprBehInt);
         printf(", %d)\n",searchTH(caracTH,out->ABL));
         }
      
      if (numberAtomExprBehInt > _maxLit)
         _maxLit = numberAtomExprBehInt; 

      if (profExprBehInt > _profMax)
         _profMax = profExprBehInt; 

      if (searchTH(caracTH,out->ABL) > _delaisMax)
         _delaisMax = searchTH(caracTH,out->ABL); 
      }
   out = out->NEXT;
   }

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      if (mode == 1)
         {
         printf("%s = ",aux->NAME);
         printf("(%d",numberAtomExprBeh(beh,aux->ABL,numberTH));
         printf(", %d",profExprBeh(beh,aux->ABL,profTH));
         printf(", %d)\n",searchTH(caracTH,aux->ABL));
         }

      _numberOperBin	= _numberOperBin + numberOperBinExpr(aux->ABL);
      _litRed	= _litRed + numberAtomExpr(aux->ABL);
      }
   aux = aux->NEXT;
   }


reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   if (mode == 1)
      printf("%s = ",reg->NAME);

   if (biabl->USER)             /* bascule D */
      _litReg = _litReg + 6;
   else                         /* latch */
      _litReg = _litReg + 3;

   while (biabl)
      {

      _litReg++;

      if (biabl->CNDABL && biabl->VALABL)
         {

         _litRed= _litRed + numberAtomExpr(biabl->VALABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->VALABL);
         numberAtomExprBehIntVal =numberAtomExprBeh(beh,biabl->VALABL,numberTH);
         profExprBehIntVal = profExprBeh(beh,biabl->VALABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntVal;

         _litRed= _litRed + numberAtomExpr(biabl->CNDABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->CNDABL);
         numberAtomExprBehIntCnd =numberAtomExprBeh(beh,biabl->CNDABL,numberTH);
         profExprBehIntCnd = profExprBeh(beh,biabl->CNDABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntCnd;

         if (mode == 1)
            {
            printf("(%d",numberAtomExprBehIntVal);
            printf(", %d",profExprBehIntVal);
            printf(", %d) ",searchTH(caracTH,biabl->VALABL));
            printf("(%d",numberAtomExprBehIntCnd);
            printf(", %d",profExprBehIntCnd);
            printf(", %d) ",searchTH(caracTH,biabl->CNDABL));
            }
      
         if (numberAtomExprBehIntVal > _maxLit)
            _maxLit = numberAtomExprBehIntVal;

         if (profExprBehIntVal > _profMax)
            _profMax = profExprBehIntVal;

         if (searchTH(caracTH,biabl->VALABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->VALABL); 

         if (numberAtomExprBehIntCnd > _maxLit)
            _maxLit = numberAtomExprBehIntCnd; 

         if (profExprBehIntCnd > _profMax)
            _profMax = profExprBehIntCnd;

         if (searchTH(caracTH,biabl->CNDABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->CNDABL); 
         }
      biabl = biabl->NEXT;
      }
   if (mode)
      printf("\n");
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   if (mode == 1)
      printf("%s = ",bus->NAME);

   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {

         _litRed= _litRed + numberAtomExpr(biabl->VALABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->VALABL);
         numberAtomExprBehIntVal =numberAtomExprBeh(beh,biabl->VALABL,numberTH);
         profExprBehIntVal = profExprBeh(beh,biabl->VALABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntVal;

         _litRed= _litRed + numberAtomExpr(biabl->CNDABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->CNDABL);
         numberAtomExprBehIntCnd =numberAtomExprBeh(beh,biabl->CNDABL,numberTH);
         profExprBehIntCnd = profExprBeh(beh,biabl->CNDABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntCnd;

         if (mode == 1)
            {
            printf("(%d",numberAtomExprBehIntVal);
            printf(", %d",profExprBehIntVal);
            printf(", %d) ",searchTH(caracTH,biabl->VALABL));
            printf("(%d",numberAtomExprBehIntCnd);
            printf(", %d",profExprBehIntCnd);
            printf(", %d) ",searchTH(caracTH,biabl->CNDABL));
            }
      
         if (numberAtomExprBehIntVal > _maxLit)
            _maxLit = numberAtomExprBehIntVal;

         if (profExprBehIntVal > _profMax)
            _profMax = profExprBehIntVal;

         if (searchTH(caracTH,biabl->VALABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->VALABL); 

         if (numberAtomExprBehIntCnd > _maxLit)
            _maxLit = numberAtomExprBehIntCnd; 

         if (profExprBehIntCnd > _profMax)
            _profMax = profExprBehIntCnd;

         if (searchTH(caracTH,biabl->CNDABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->CNDABL); 
         }
      biabl = biabl->NEXT;
      }

   if (mode)
      printf("\n");
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   if (mode == 1)
      printf("%s = ",bux->NAME);

   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {

         _litRed= _litRed + numberAtomExpr(biabl->VALABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->VALABL);
         numberAtomExprBehIntVal =numberAtomExprBeh(beh,biabl->VALABL,numberTH);
         profExprBehIntVal = profExprBeh(beh,biabl->VALABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntVal;

         _litRed= _litRed + numberAtomExpr(biabl->CNDABL);
         _numberOperBin	= _numberOperBin + numberOperBinExpr(biabl->CNDABL);
         numberAtomExprBehIntCnd =numberAtomExprBeh(beh,biabl->CNDABL,numberTH);
         profExprBehIntCnd = profExprBeh(beh,biabl->CNDABL,profTH);
         _lit 	= _lit + numberAtomExprBehIntCnd;

         if (mode == 1)
            {
            printf("(%d",numberAtomExprBehIntVal);
            printf(", %d",profExprBehIntVal);
            printf(", %d) ",searchTH(caracTH,biabl->VALABL));
            printf("(%d",numberAtomExprBehIntCnd);
            printf(", %d",profExprBehIntCnd);
            printf(", %d) ",searchTH(caracTH,biabl->CNDABL));
            }
      
         if (numberAtomExprBehIntVal > _maxLit)
            _maxLit = numberAtomExprBehIntVal;

         if (profExprBehIntVal > _profMax)
            _profMax = profExprBehIntVal;

         if (searchTH(caracTH,biabl->VALABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->VALABL); 

         if (numberAtomExprBehIntCnd > _maxLit)
            _maxLit = numberAtomExprBehIntCnd; 

         if (profExprBehIntCnd > _profMax)
            _profMax = profExprBehIntCnd;

         if (searchTH(caracTH,biabl->CNDABL) > _delaisMax)
            _delaisMax = searchTH(caracTH,biabl->CNDABL); 
         }
      biabl = biabl->NEXT;
      }

   if (mode)
      printf("\n");
   bux = bux->NEXT;
   }

if (mode == 1)
   {
   printf("--------------> Total number of litterals = %d\n",_lit);
   printf("--------------> Max = %d\n",_maxLit);
   printf("--------------> Number of reduced litterals = %d\n",_litRed);
   printf("--------------> Number of binary operator = %d\n",_numberOperBin);
   printf("--------------> Depth Max = %d\n",_profMax);
   printf("--------------> Delay Max = %.3f\n",((float) _delaisMax)/1000);
   }

	/* mise a jour */

*lit = _lit;
*maxLit = _maxLit;
*litRed = _litRed;
*litReg = _litReg;
*profMax = _profMax;
*delaisMax = _delaisMax;
*operBin = _numberOperBin;
destroyTH(caracTH);
destroyTH(profTH);
destroyTH(numberTH);
}

/*-------------------------------------------------------------------------
markAblWBddBeh 	: marque le champs user des expressions avec le pNode
                  correspondant dans une befig. 
---------------------------------------------------------------------------
retour		: un pNode.
---------------------------------------------------------------------------*/
pNode markAblWBddBeh(beh,expr)
befig_list *beh;
chain_list *expr;
{
pCircuit pC = beh->CIRCUI;

if (ATOM(expr))

		/* c'est forcement une entree de pC */
   {
   int val;

   if (!strcmp((char *) VALUE_ATOM(expr),"'0'"))
      return(zero);

   if (!strcmp((char *) VALUE_ATOM(expr),"'1'"))
      return(one);

   val = searchInputCct(pC,VALUE_ATOM(expr));
   if (val != EMPTYTH)
      return(createNodeTermBdd(val));
   else
      {
		/* recherche d'un auxiliaire */


      beaux_list *aux = beh->BEAUX;
      pNode node = searchOutputCct(pC,VALUE_ATOM(expr));

		/* deja calcule */

      if (node != NULL)
         return(node);

      while (aux && strcmp(VALUE_ATOM(expr),aux->NAME))
         {
         aux = aux->NEXT;
         }
      if (!aux)
         {
         printf("markAblWBeh : error auxiliary signal %s does'nt exist\n",
                VALUE_ATOM(expr));
         exit(-1);
         }

      node = markAblWBddBeh(beh,aux->ABL);
      addOutputCct(beh->CIRCUI,aux->NAME,node);
      return(node);
      }
   }
else
   {
   short oper;
   pNode pt;
   chain_list *lstGdb;
   chain_list *tete;
   
   tete = expr;
   oper = OPER(expr);
   lstGdb = NULL;
   while (expr = CDR(expr))
      lstGdb = addListBdd(lstGdb,markAblWBddBeh(beh,CAR(expr)));
   pt = applyBdd(oper,lstGdb);
   freechain(lstGdb);

		/* le marquage */

   CDR(CAR(tete)) = (chain_list *) pt;
   return(pt);
   }
}

/*-------------------------------------------------------------------------
occTHBddBeh 	: calcule le nombre d'occurences de chaque graphe. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void occTHBddBeh(expr,pTabNode)
chain_list *expr;
pTH pTabNode;
{
pNode nodeP,nodeN;
int valueN,valueP;

if (!ATOM(expr))
   {
   nodeP = (pNode) CDR(CAR(expr));
   nodeN = notBdd(nodeP);

   valueP = searchTH(pTabNode,(char *) nodeP);
   if (valueP == EMPTYTH)
      valueP = 0;
   valueN = searchTH(pTabNode,(char *) nodeN);
   if (valueN == EMPTYTH)
      valueN = 0;
   

   if (valueN + valueP == 0)
      {
      if (OPER(expr) != NOT)
         addTH(pTabNode,nodeP,1);

		/* appel recursif sur les arguments */

      while (expr = CDR(expr))
         {
         occTHBddBeh(CAR(expr),pTabNode);
         }
      }
   else
      addTH(pTabNode,nodeP,1 + valueP);
   }
}
   
/*-------------------------------------------------------------------------
createVIBeh 	: creation des variables intermediaires. 
---------------------------------------------------------------------------
retour		: une liste des var. aux.
---------------------------------------------------------------------------*/
chain_list *createVIBeh(beh,expr,pTabNode,numberSon)
befig_list *beh;
chain_list *expr;
pTH pTabNode;
int numberSon;
{
static int co=0;
int isNot = 0;

if (expr == NULL)
   {
   printf("createVIBeh : error expr = NULL\n");
   exit(-1);
   }

if (ATOM(expr))
   return(copyExpr(expr));
else
   {
   chain_list *resul;
   pNode nodeP,nodeN;
   int valueP,valueN;	/* le nombre d'occurence des graphes */

   nodeP = (pNode) CDR(CAR(expr));

		/* 1 cas particuliers */

		/* 1. Graphe non calcule            */

   if (nodeP == 0)
      return(copyExpr(expr));


		/* cas normal */

   valueP = abs(searchTH(pTabNode,nodeP));

		/* est ce un noeud atomique ? */

   if (((nodeP->low)->index < 2) && ((nodeP->high)->index < 2))
      {
      if (nodeP->low == one)       /* not de la variable */
         resul = notExpr(createAtom(*(beh->CIRCUI->pNameI + nodeP->index - 2)));
      else                      /* variable directe */
         resul = createAtom(*(beh->CIRCUI->pNameI + nodeP->index - 2));
      return(resul);
      }


   if (valueP > MAX_FATHER)
      {
 		/* c'est deja une variable auxiliaire... */

      return(copyExpr((chain_list *) valueP));

		/* carrement ...!!! */
      }

   resul = createExpr(OPER(expr));

	/* on evite de creer trop de variables intermediaires... */


		/* traitement du not */
   

   if (OPER(expr) == NOT)
      {
      if (!(ATOM(CADR(expr))))
         {
         isNot = 1;
         expr = CADR(expr);
         resul = createExpr(OPER(expr));
         }
      else
         return(copyExpr(expr));
      }

   while (expr = CDR(expr))
      {
      addQExpr(resul,createVIBeh(beh,CAR(expr),
                                  pTabNode,numberSon));
      }   
  

   nodeN = notBdd(nodeP);
   valueN = searchTH(pTabNode,nodeN);
   if (valueN == EMPTYTH)
      valueN = 0;
   if (valueP == EMPTYTH)
      {
      printf("error : createVIBeh - expr with empty user NULL\n");
      exit(-1);
      }  
   
		/* la fonction possedent suffisament de peres ? */

   if (valueP + valueN >= 2)
      {
      char *name;
      beaux_list *aux;
         
      name = gensym("aux",co++);

   if (SL_TRACE == 2)
      {
      printf("Generating %s  P = %d N = %d\n Expr : ",name,valueP,valueN);
      displayExpr(resul);
      }
         
      if (valueP >= valueN)
         {
         if (isNot)
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,notExpr(resul),NULL);
         else
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,resul,NULL);
         aux = beh->BEAUX;

         while (aux && strcmp(aux->NAME,name))
            aux = aux->NEXT;

         if (aux)
            aux->NODE = nodeP;
         else
            {
            printf("createVIBeh error - %s doesn't exist\n",name);
            exit(-1);
            }

         addTH(pTabNode,nodeP,(int) createAtom(name));
         addTH(pTabNode,nodeN,(int) notExpr(createAtom(name))); 
         return(createAtom(name));
         }
      else
         {
         if (isNot)
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,resul,NULL);
         else
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,notExpr(resul),NULL);
         aux = beh->BEAUX;
         while(aux)
            {
            if (aux->NAME == name)
               {
               aux->NODE = nodeN;
               aux = NULL;
               }
            else
               aux = aux->NEXT;
            }
         addTH(pTabNode,nodeP,(int) notExpr(createAtom(name))); 
         addTH(pTabNode,nodeN,(int) createAtom(name));
         return(notExpr(createAtom(name)));
         }
      }
		/* pas de variable auxilaire */

   if (isNot)
      resul = notExpr(resul);

   return(resul);
   }
}

/*-------------------------------------------------------------------------
resetDustExpr 	: remet les champs poubelles d'une expression a 0. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void resetDustExpr(expr)
chain_list *expr;
{
if (!ATOM(expr))
   {
   CDR(CAR(expr)) = 0;
   while (expr = CDR(expr))
      {
      resetDustExpr(CAR(expr));
      }
   }
}
/*-------------------------------------------------------------------------
reverseExpr 	: inverse les arguments des expression 
---------------------------------------------------------------------------
retour		: un chain_list *.
---------------------------------------------------------------------------*/
chain_list *reverseExpr(expr)
chain_list *expr;
{
if (ATOM(expr))
   return(copyExpr(expr));
else
   {
   chain_list *resul;
   
   resul = createExpr(OPER(expr));
   if (lengthExpr(expr) <= 2)
      {
      while (expr = CDR(expr))
         addQExpr(resul,reverseExpr(CAR(expr)));
      return(resul);
      }
   else
     {
     int i;
      
     resul = createExpr(OPER(expr));
     while (expr = CDR(expr))
        {
        addHExpr(resul,reverseExpr(CAR(expr)));
        } 
     return(resul);
     }
   }
}

/*-------------------------------------------------------------------------
arity2Expr 	: transforme une expression avec operateur d'arite 2.   
---------------------------------------------------------------------------
retour		: un chain_list *.
---------------------------------------------------------------------------*/
chain_list *arity2Expr(expr)
chain_list *expr;
{
if (ATOM(expr))
   return(copyExpr(expr));
else
   {
   chain_list *resul;
   
   resul = createExpr(OPER(expr));
   if (lengthExpr(expr) <= 2)
      {
      while (expr = CDR(expr))
         addQExpr(resul,arity2Expr(CAR(expr)));
      return(resul);
      }
   else
     {
     int i;
     chain_list *inter = NULL;
      
     for (i = lengthExpr(expr)-1 ; i>0 ; i--)
        {
        resul = createExpr(OPER(expr));
        if (inter == NULL)
           {
           addHExpr(resul,arity2Expr(searchNumExpr(expr,i)));
           addHExpr(resul,arity2Expr(searchNumExpr(expr,i-1)));
           }
        else
           {
           addHExpr(resul,inter);
           addHExpr(resul,arity2Expr(searchNumExpr(expr,i-1)));
           }
        inter = resul;
        } 
     return(resul);
     }
   }
}
/*-------------------------------------------------------------------------
gcBddToAblBeh	: garbage sur la fonction BddToAbl 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void gcBddToAblBeh(beh,trace)
befig_list *beh;
int trace;
{
int i;

      

if (numberNodeAllBdd() > 100000)
   {
   if (trace)
      printf("gc %d ...\n",numberNodeAllBdd());

   gcNodeBeh(beh);

   if (trace)
      printf("End of gc pTabExpr %d\n",numberNodeAllBdd());
   }
}

/*-------------------------------------------------------------------------
rempTabExpr 	: remplissage de pTabExpr 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
pNode rempTabExpr(beh,expr)
befig_list *beh;
chain_list *expr;
{
pCircuit pC = beh->CIRCUI;

if (ATOM(expr))

		/* c'est forcement une entree de pC */
   {
   int val;

   if (!strcmp((char *) VALUE_ATOM(expr),"'0'"))
      return(zero);

   if (!strcmp((char *) VALUE_ATOM(expr),"'1'"))
      return(one);

   val = searchInputCct(pC,VALUE_ATOM(expr));
   if (val != EMPTYTH)
      return(createNodeTermBdd(val));
   else
      {
      printf("rempTabExpr : error signal %s does'nt exist as input\n",
                VALUE_ATOM(expr));
      exit(-1);
      }
   }
else
   {
   short oper;
   pNode pt;
   chain_list *lstGdb;
   chain_list *tete;
   
   tete = expr;
   oper = OPER(expr);
   lstGdb = NULL;
   while (expr = CDR(expr))
      lstGdb = addListBdd(lstGdb,rempTabExpr(beh,CAR(expr)));
   pt = applyBdd(oper,lstGdb);
   freechain(lstGdb);

		/* la mise a jour de pTabExpr */

   addTH(pTabExpr,pt,tete);
   return(pt);
   }
}

/*-------------------------------------------------------------------------
bddToAblBeh 	: regeneration des abl(s) du circuit. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void bddToAblBeh(beh,optim)
befig_list *beh;
int optim;
{
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
binode_list *binode;
biabl_list *biabl;
int i;
pElemTH pEl;
chain_list *expr;
chain_list *tete;
chain_list *lstNotExpr;

if (SL_TRACE)
   printf("bddToAblBeh Running...\n");


pTabExpr = createTH(4999);

	/* la desallocation des expression de la befig */

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      freeExpr(out->ABL) ;
   out = out->NEXT;
   }

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      freeExpr(aux->ABL) ;
   aux = aux->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         freeExpr(biabl->CNDABL);
         freeExpr(biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         freeExpr(biabl->CNDABL);
         freeExpr(biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         freeExpr(biabl->CNDABL);
         freeExpr(biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }
         
	/* la regeneration des expressions a partir des BDD */

lstNotExpr = NULL;

out = beh->BEOUT;
while (out) 
   {
   if (out->NODE)
      {


      out->ABL = bdd2Abl(out->NODE,beh->CIRCUI->pNameI,optim);

      expr = out->ABL;

      out->ABL = arity2Expr(expr);
      freeExpr(expr);

      rempTabExpr(beh,out->ABL);

      expr = createExpr(NOT);
      addQExpr(expr,copyExpr(out->ABL));

      rempTabExpr(beh,expr);
      lstNotExpr = addchain(lstNotExpr,expr);

			/* la reallocation si necessaire */

   if (SL_TRACE == 2)
      {
      printf("+++ out +++ (%s) count %d",out->NAME,numberNodeAllBdd());
      printf("numberAtom = %d\n",numberAtomExpr(out->ABL));
      }

      gcBddToAblBeh(beh,SL_TRACE);
      }
   else
      {
      printf("bddToAblBeh : error there's no graph on %s !\n",out->NAME);
      exit(-1);
      }

   out = out->NEXT;
   }


aux = beh->BEAUX;
while (aux) 
   {
   if (aux->NODE)
      {
      aux->ABL = bdd2Abl(aux->NODE,beh->CIRCUI->pNameI,optim);

      expr = aux->ABL;

      aux->ABL = arity2Expr(expr);
      freeExpr(expr);

      rempTabExpr(beh,aux->ABL);

      expr = createExpr(NOT);
      addQExpr(expr,copyExpr(aux->ABL));

      rempTabExpr(beh,expr);
      lstNotExpr = addchain(lstNotExpr,expr);

   if (SL_TRACE == 2)
      {
      printf("+++ aux +++ (%s) count %d",aux->NAME,numberNodeAllBdd());
      printf("numberAtom = %d\n",numberAtomExpr(aux->ABL));
      }

      gcBddToAblBeh(beh,SL_TRACE);
      }
   else
      {
      printf("bddToAblBeh : error there's no graph on %s !\n",aux->NAME);
      exit(-1);
      }
   aux = aux->NEXT;
   }


reg = beh->BEREG;
while (reg) 
   {
   binode = reg->BINODE;
   biabl = reg->BIABL;
   while (binode)
      {
      if (binode->VALNODE && binode->CNDNODE)
         {
         biabl->VALABL = bdd2Abl(binode->VALNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->VALABL;

         biabl->VALABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->VALABL);

         expr = createExpr(NOT);
         addQExpr(expr,copyExpr(biabl->VALABL));
   
         rempTabExpr(beh,expr);
         lstNotExpr = addchain(lstNotExpr,expr);


         biabl->CNDABL = bdd2Abl(binode->CNDNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->CNDABL;

         biabl->CNDABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->CNDABL);

         expr = createExpr(NOT);
         addQExpr(expr,copyExpr(biabl->CNDABL));
   
         rempTabExpr(beh,expr);
         lstNotExpr = addchain(lstNotExpr,expr);

			/* la reallocation si necessaire */

         if (SL_TRACE == 2)
            {
            printf("+++ reg +++ (%s) count %d",reg->NAME,numberNodeAllBdd());
            printf("numberAtom = %d\n",numberAtomExpr(biabl->VALABL));
            printf("numberAtom = %d\n",numberAtomExpr(biabl->CNDABL));
            }

         gcBddToAblBeh(beh,SL_TRACE);

         }
      else
         {
         printf("bddToAblBeh : error there's no graph on %s !\n",reg->NAME);
         exit(-1);
         }
      binode = binode->NEXT;
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   binode = bus->BINODE;
   biabl = bus->BIABL;
   while (binode)
      {
      if (binode->VALNODE && binode->CNDNODE)
         {
         biabl->VALABL = bdd2Abl(binode->VALNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->VALABL;

         biabl->VALABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->VALABL);


         biabl->CNDABL = bdd2Abl(binode->CNDNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->CNDABL;

         biabl->CNDABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->CNDABL);

         if (SL_TRACE)
            {
            printf("+++ bus +++ (%s) count %d",bus->NAME,numberNodeAllBdd());
            printf("numberAtom = %d\n",numberAtomExpr(biabl->VALABL));
            printf("numberAtom = %d\n",numberAtomExpr(biabl->CNDABL));
            }

         gcBddToAblBeh(beh,SL_TRACE);

         }
      else
         {
         printf("bddToAblBeh : error there's no graph on %s !\n",bus->NAME);
         exit(-1);
         }
      binode = binode->NEXT;
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   binode = bux->BINODE;
   biabl = bux->BIABL;
   while (binode)
      {
      if (binode->VALNODE && binode->CNDNODE)
         {
         biabl->VALABL = bdd2Abl(binode->VALNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->VALABL;

         biabl->VALABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->VALABL);


         biabl->CNDABL = bdd2Abl(binode->CNDNODE,beh->CIRCUI->pNameI,optim);

         expr = biabl->CNDABL;

         biabl->CNDABL = arity2Expr(expr);
         freeExpr(expr);

         rempTabExpr(beh,biabl->CNDABL);

         if (SL_TRACE == 2)
            {
            printf("+++ bux +++ (%s) count %d",bux->NAME,numberNodeAllBdd());
            printf("numberAtom = %d\n",numberAtomExpr(biabl->VALABL));
            printf("numberAtom = %d\n",numberAtomExpr(biabl->CNDABL));
            }

         gcBddToAblBeh(beh,SL_TRACE);

         }
      else
         {
         printf("bddToAblBeh : error there's no graph on %s !\n",bux->NAME);
         exit(-1);
         }
      binode = binode->NEXT;
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }

tete = lstNotExpr;
while (lstNotExpr)
   {
   freeExpr(lstNotExpr->DATA);
   lstNotExpr = lstNotExpr->NEXT;
   }
freechain(tete);

destroyTH(pTabExpr);

if (numberNodeAllBdd() > 20000)
   gcNodeBeh(beh);

if (SL_TRACE)
   printf("End of BddToAbl\n");
}

/*-------------------------------------------------------------------------
createAuxBeh 	: creation de VI pour une befig 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void createAuxBeh(beh)
befig_list *beh;
{
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
chain_list *expr;
int numberSon;
pTH pTabNode;

pTabNode = createTH(1999);

if (SL_TRACE == 2)
   displayBeh(beh,1);

mapExprBeh(beh,resetDustExpr);

		/* transformation en arbres binaires */

mapCarExprBeh(beh,arity2Expr);

		/* le marquage des ABL */

   aux = beh->BEAUX;
   while (aux) 
      {
      addOutputCct(beh->CIRCUI,aux->NAME,markAblWBddBeh(beh,aux->ABL));
      aux = aux->NEXT;
      }

   out = beh->BEOUT;
   while (out) 
      {
      markAblWBddBeh(beh,out->ABL);
      out = out->NEXT;
      }

   reg = beh->BEREG;
   while (reg) 
      {
      biabl = reg->BIABL;
      while (biabl)
         {
         markAblWBddBeh(beh,biabl->CNDABL);
         markAblWBddBeh(beh,biabl->VALABL);
         biabl = biabl->NEXT;
         }
      reg = reg->NEXT;
      }


   bus = beh->BEBUS;
   while (bus) 
      {
      biabl = bus->BIABL;
      while (biabl)
         {
         markAblWBddBeh(beh,biabl->CNDABL);
         markAblWBddBeh(beh,biabl->VALABL);
         biabl = biabl->NEXT;
         }
      bus = bus->NEXT;
      }

   bux = beh->BEBUX;
   while (bux) 
      {
      biabl = bux->BIABL;
      while (biabl)
         {
         markAblWBddBeh(beh,biabl->CNDABL);
         markAblWBddBeh(beh,biabl->VALABL);
         biabl = biabl->NEXT;
         }
      bux = bux->NEXT;
      }

		/* le calcul du nombre d'occurence */

   out = beh->BEOUT;
   while (out) 
      {
      occTHBddBeh(out->ABL,pTabNode);
      out = out->NEXT;
      }

   aux = beh->BEAUX;
   while (aux) 
      {
      occTHBddBeh(aux->ABL,pTabNode);
      aux = aux->NEXT;
      }

   reg = beh->BEREG;
   while (reg) 
      {
      biabl = reg->BIABL;
      while (biabl)
         {
         occTHBddBeh(biabl->VALABL,pTabNode);
         occTHBddBeh(biabl->CNDABL,pTabNode);
         biabl = biabl->NEXT;
         }
      reg = reg->NEXT;
      }


   bus = beh->BEBUS;
   while (bus) 
      {
      biabl = bus->BIABL;
      while (biabl)
         {
         occTHBddBeh(biabl->VALABL,pTabNode);
         occTHBddBeh(biabl->CNDABL,pTabNode);
         biabl = biabl->NEXT;
         }
      bus = bus->NEXT;
      }

   bux = beh->BEBUX;
   while (bux) 
      {
      biabl = bux->BIABL;
      while (biabl)
         {
         occTHBddBeh(biabl->VALABL,pTabNode);
         occTHBddBeh(biabl->CNDABL,pTabNode);
         biabl = biabl->NEXT;
         }
      bux = bux->NEXT;
      }
		/* fin du calcul des occurences de pNode
                   Ce calcul etant partiel , il faut necessairement
                   parcourir la befig de la meme maniere pour la
		   la creation des VI            
                 */


   numberSon = 2;

		/* on evite de creer des VI deja existante.... */

   aux = beh->BEAUX;
   while (aux) 
      {
      pNode tete = aux->NODE; 


			/* aux->NAME est deja une variable aux. */

      addTH(pTabNode,tete,createAtom(aux->NAME));
      addTH(pTabNode,notBdd(tete),notExpr(createAtom(aux->NAME)));

      aux = aux->NEXT;
      }

   out = beh->BEOUT;
   while (out) 
      {
      expr =out->ABL;
      out->ABL = createVIBeh(beh,out->ABL,pTabNode,numberSon);
      freeExpr(expr);
      out = out->NEXT;
      }

   aux = beh->BEAUX;
   while (aux) 
      {
      chain_list *resExpr;
      int teteNot = 0;

      if (!ATOM(aux->ABL))     /* traitement special pour eviter de boucler */
         {
         expr = aux->ABL;
         if (OPER(expr) == NOT)
            {
            expr = CADR(expr);
            teteNot = 1;
            }
         if (!ATOM(expr))		/* on evite de traiter x <= not a; */
            {
            resExpr = createExpr(OPER(expr));
            while (expr = CDR(expr))
               {
               addQExpr(resExpr,createVIBeh(beh,CAR(expr),pTabNode,numberSon));
               }
            expr = aux->ABL;
            if (teteNot)
               aux->ABL = notExpr(resExpr);
            else
               aux->ABL = resExpr;
            freeExpr(expr);
            }
         }
      aux = aux->NEXT;
      }

   reg = beh->BEREG;
   while (reg) 
      {
      biabl = reg->BIABL;
      while (biabl)
         {
         expr =biabl->CNDABL;
         biabl->CNDABL = createVIBeh(beh,biabl->CNDABL,pTabNode,numberSon);
         freeExpr(expr);
         expr =biabl->VALABL;
         biabl->VALABL = createVIBeh(beh,biabl->VALABL,pTabNode,numberSon);
         freeExpr(expr);
         biabl = biabl->NEXT;
         }
      reg = reg->NEXT;
      }

   bus = beh->BEBUS;
   while (bus) 
      {
      biabl = bus->BIABL;
      while (biabl)
         {
         expr =biabl->CNDABL;
         biabl->CNDABL = createVIBeh(beh,biabl->CNDABL,pTabNode,numberSon);
         freeExpr(expr);
         expr =biabl->VALABL;
         biabl->VALABL = createVIBeh(beh,biabl->VALABL,pTabNode,numberSon);
         freeExpr(expr);
         biabl = biabl->NEXT;
         }
      bus = bus->NEXT;
      }

   bux = beh->BEBUX;
   while (bux) 
      {
      biabl = bux->BIABL;
      while (biabl)
         {
         expr =biabl->CNDABL;
         biabl->CNDABL = createVIBeh(beh,biabl->CNDABL,pTabNode,numberSon);
         freeExpr(expr);
         expr =biabl->VALABL;
         biabl->VALABL = createVIBeh(beh,biabl->VALABL,pTabNode,numberSon);
         freeExpr(expr);
         biabl = biabl->NEXT;
         }
      bux = bux->NEXT;
      }

   flatArityExprBeh(beh);

   destroyTH(pTabNode);


if (SL_TRACE == 2)
   {
   printf("End of the generating VI\n");
   displayBeh(beh,1);
   }
}

/*-------------------------------------------------------------------------
coutSol 	: calcule le cout d'une solution dans le recuit simule. 
---------------------------------------------------------------------------
retour		: un int.
---------------------------------------------------------------------------*/
int coutSol(lit,delaisMax,litRed,profMax,operBin,optim)
int lit,delaisMax,litRed,profMax,operBin,optim;
{
return(optim * (2*(litRed + operBin + 5*profMax*profMax + delaisMax/10) + lit) +
       (4 - optim) * (litRed)); 
}
/*-------------------------------------------------------------------------
regenereBddBeh 	: regenere les Bdd d'une befig avec le nouvel ordonnancement 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void regenereBddBeh(beh,order)
befig_list *beh;
chain_list *order;
{
chain_list *ptChain;
if (order == NULL)
   {
   printf("regenereBddBeh : error order = NULL\n");
   exit(-1);
   }

videBddBefig(beh);
if (beh->NEXT)
   gcNodeBeh(beh->NEXT);
else
   resetBdd();
destroyCct(beh->CIRCUI);
beh->CIRCUI =  initializeCct(beh->NAME,2*lengthExpr(order)+1,100);
ptChain = order;
while (ptChain) 
   {
   addInputCct(beh->CIRCUI,ptChain->DATA);
   ptChain = ptChain->NEXT;
   } 
}
/*-------------------------------------------------------------------------
createAuxInitBeh : creation de VI pour eviter de traiter x fois
                   le meme cone. Les nouvelles VI sont ajoutes
                   dans la couche circuit de beh.
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
chain_list *createAuxInitBeh(beh)
befig_list *beh;
{
pTH occTH;
static int co=0;
int val;
chain_list *saveAux;
beout_list *out;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
binode_list *binode;
char *name;

	/* initialisation */

saveAux = NULL;
occTH = createTH(200);

	/* calcul du nombre d'occurences des tetes d'expression */

out = beh->BEOUT;
while (out)
   {
   if (out->NODE && numberNodeBdd(out->NODE) > 1)
      {
      val = searchTH(occTH,out->NODE);
      if (val != EMPTYTH)
         addTH(occTH,out->NODE,2);
      else 
         addTH(occTH,out->NODE,1);
      }
   out = out->NEXT;
   }
reg = beh->BEREG;
while (reg)
   {
   binode = reg->BINODE;
   while (binode)
      {
      if (binode->VALNODE && numberNodeBdd(binode->VALNODE) > 1)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->VALNODE,2);
         else 
            addTH(occTH,binode->VALNODE,1);
         }
      if (binode->CNDNODE && numberNodeBdd(binode->CNDNODE) > 1)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->CNDNODE,2);
         else 
            addTH(occTH,binode->CNDNODE,1);
         }
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus)
   {
   binode = bus->BINODE;
   while (binode)
      {
      if (binode->VALNODE && numberNodeBdd(binode->VALNODE) > 1)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->VALNODE,2);
         else 
            addTH(occTH,binode->VALNODE,1);
         }
      if (binode->CNDNODE && numberNodeBdd(binode->CNDNODE) > 1)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->CNDNODE,2);
         else 
            addTH(occTH,binode->CNDNODE,1);
         }
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux)
   {
   binode = bux->BINODE;
   while (binode)
      {
      if (binode->VALNODE && numberNodeBdd(binode->VALNODE) > 1)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->VALNODE,2);
         else 
            addTH(occTH,binode->VALNODE,1);
         }
      if (binode->CNDNODE && numberNodeBdd(binode->CNDNODE) > 1)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val != EMPTYTH)
            addTH(occTH,binode->CNDNODE,2);
         else 
            addTH(occTH,binode->CNDNODE,1);
         }
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }
		/* parcours avec creation de VI */

out = beh->BEOUT;
while (out)
   {
   if (out->NODE)
      {
      val = searchTH(occTH,out->NODE);
      if (val == 2)
         {
         name = gensym("auxinit",++co);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,out->ABL,NULL);
         (beh->BEAUX)->NODE = out->NODE;
         out->ABL = createAtom(name);
         addTH(occTH,out->NODE,name);
         saveAux = addchain(saveAux,name);
         addInputCct(beh->CIRCUI,name);
         out->NODE = createNodeTermBdd(
                           searchInputCct(beh->CIRCUI,name));
         }
      else
         if (val != EMPTYTH && val != 1)
            {
            name = (char *) val;
            freeExpr(out->ABL);
            out->ABL = createAtom(name);
            out->NODE = createNodeTermBdd(
                           searchInputCct(beh->CIRCUI,name));
            }
      }
   out = out->NEXT;
   }
reg = beh->BEREG;
while (reg)
   {
   biabl = reg->BIABL;
   binode = reg->BINODE;
   while (biabl)
      {
      if (binode->VALNODE && biabl->VALABL)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
            (beh->BEAUX)->NODE = binode->VALNODE;
            biabl->VALABL = createAtom(name);
            addTH(occTH,binode->VALNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->VALABL);
               biabl->VALABL = createAtom(name);
               binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
               }
         }
      if (binode->CNDNODE && biabl->CNDABL)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
            (beh->BEAUX)->NODE = binode->CNDNODE;
            biabl->CNDABL = createAtom(name);
            addTH(occTH,binode->CNDNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->CNDNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->CNDABL);
               biabl->CNDABL = createAtom(name);
               binode->CNDNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
               }
         }
      binode = binode->NEXT;
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus)
   {
   binode = bus->BINODE;
   biabl = bus->BIABL;
   while (biabl)
      {
      if (binode->VALNODE && biabl->VALABL)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
            (beh->BEAUX)->NODE = binode->VALNODE;
            biabl->VALABL = createAtom(name);
            addTH(occTH,binode->VALNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->VALABL);
               biabl->VALABL = createAtom(name);
               binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
               }
         }
      if (binode->CNDNODE && biabl->CNDABL)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
            (beh->BEAUX)->NODE = binode->CNDNODE;
            biabl->CNDABL = createAtom(name);
            addTH(occTH,binode->CNDNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->CNDNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->CNDABL);
               biabl->CNDABL = createAtom(name);
               binode->CNDNODE = createNodeTermBdd(
                                    searchInputCct(beh->CIRCUI,name));
               }
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux)
   {
   binode = bux->BINODE;
   biabl = bux->BIABL;
   while (biabl)
      {
      if (binode->VALNODE && biabl->VALABL)
         {
         val = searchTH(occTH,binode->VALNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
            (beh->BEAUX)->NODE = binode->VALNODE;
            biabl->VALABL = createAtom(name);
            addTH(occTH,binode->VALNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->VALABL);
               biabl->VALABL = createAtom(name);
               binode->VALNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
               }
         }
      if (binode->CNDNODE && biabl->CNDABL)
         {
         val = searchTH(occTH,binode->CNDNODE);
         if (val == 2)
            {
            name = gensym("auxinit",++co);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
            (beh->BEAUX)->NODE = binode->CNDNODE;
            biabl->CNDABL = createAtom(name);
            addTH(occTH,binode->CNDNODE,name);
            saveAux = addchain(saveAux,name);
            addInputCct(beh->CIRCUI,name);
            binode->CNDNODE = createNodeTermBdd(
                                 searchInputCct(beh->CIRCUI,name));
            }
         else
            if (val != EMPTYTH && val != 1)
               {
               name = (char *) val;
               freeExpr(biabl->CNDABL);
               biabl->CNDABL = createAtom(name);
               binode->CNDNODE = createNodeTermBdd(
                                    searchInputCct(beh->CIRCUI,name));
               }
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }


destroyTH(occTH);
return saveAux;
}
/*-------------------------------------------------------------------------
notSameOrder 	: verifie que l'ordonnancement Order n'a pas deja ete
                  memorise dans tabSol 
---------------------------------------------------------------------------
retour		: 1 si l'order est nouveau 0 sinon 
---------------------------------------------------------------------------*/
int notSameOrder(tabSol,numberSol,order)
tabSolution *tabSol;
int numberSol;
chain_list *order;
{
int i;

for (i=0;i<numberSol;i++)
   {
   int egal;
   chain_list *order1,*order2;

   order1 = order;
   order2 = tabSol[i].order;
   egal = 1;
   while (order1 != NULL && order2 != NULL)
      {
      if (strcmp((char *) order1->DATA,(char *) order2->DATA))
         egal = 0; 
      order1 = order1->NEXT;
      order2 = order2->NEXT;
      }
		/* meme ordonnancement */

   if (egal == 1)
      {
      return (0);
      }
   }
return(1);
}

/*-------------------------------------------------------------------------
localOpt 	: optimisation locale d'une befig 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void localOpt(trace)
int trace;
{
beaux_list *aux; 
chain_list *saveAux;
int numberNode;
befig_list *beh;

beh = SL_BEH;

aux = beh->BEAUX;
saveAux = NULL;               /* on vide les auxinit eventuels */
while (aux)
  {
  saveAux = addchain(saveAux,aux->NAME);
  aux = aux->NEXT;
  }

			/* re-ordonnancement */

numberNode = 20;

if (SL_MAKEORDER == 2)
   sl_sys->orderPI = makeOrderBddBeh(SL_BEH,SL_OPTIM,SL_OPTIMPO,SL_DELAYPI,1,
                           numberNode,1,trace,100,1,numberAtomRedFact); 

else		 /* on recupere l'ordre de la couche circuit */
   {
   char **ptChar;
   int c;
 
   ptChar = (SL_CIRCUIT)->pNameI;		/* les entrees */

   sl_sys->orderPI = NULL;
   for (c = ((SL_CIRCUIT)->countI)-2; c != 0; c--)
      {
      sl_sys->orderPI =  addchain(sl_sys->orderPI,*ptChar);
      ptChar++;
      } 
   sl_sys->orderPI = reverse(sl_sys->orderPI);
   }

makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);

removeAuxBeh(SL_BEH,saveAux);

		/* faut-il essayer les deux re-generations ? */

if (SL_OPTIM > 2)
   bddToAblBeh(SL_BEH,1);
else
   bddToAblBeh(SL_BEH,0);

if (trace)
   printf("Generating VI\n");

if (SL_AUXOF)
   createAuxBeh(SL_BEH);

		/* l'optimisation locale peut quand meme eliminer
		   des variables intermediaires */

compactBeh(SL_BEH);

	/* on inverse l'ordre des expressions et 
           on cree des variable Inter a nouveau */

mapCarExprBeh(SL_BEH,reverseExpr);

if (SL_AUXOF)
   createAuxBeh(SL_BEH);

compactBeh(SL_BEH);

mapCarExprBeh(SL_BEH,reverseExpr);
}


/*-------------------------------------------------------------------------
globalOpt 	: optimisation globale d'une befig 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void globalOpt(trace)
int trace;
{
pTH caracTH;
pTH caracBeh();
tabSolution *tabSol;
int lit,maxLit,litRed,litReg,profMax,delaisMax,operBin;
int amplitude;
int numberSol,indiceMin,coutMin;
int i,level;
chain_list *saveAux;
beaux_list *aux;
int numberInput=0;
int numberNode=0;
chain_list *makeOrderAbl();
chain_list *lstExpr, *lst;
int existDC;

	/* sauvegarde dans saveAux des auxiliaires a garder */

saveAux = createAuxInitBeh(SL_BEH);

	/* premiere phase d'ordonnancement pour la prise en compte des DC */

	/* existe-t-il des constantes 'd' dans les expressions ? */

lstExpr = exprToCLBeh(SL_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=1;i<3;i++)
      {
      if (SL_MAKEORDER == 2)
         makeOrderBddBeh(SL_BEH,SL_OPTIM,SL_OPTIMPO,
                            SL_DELAYPI,1,8,1,trace,5,1,numberAtomRedFact); 

      makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);
      }
   traitementDCBeh(SL_BEH,trace,numberAtomRedFact);
   }

		/* on met dans saveaux les variables intermediaires
                   que l'on conserve */

   {
   chain_list *intermediate = SL_GUARDEDAUX;
   while (intermediate)
      {
      if (existAuxBeh(SL_BEH,intermediate->DATA))
         saveAux = addchain(saveAux,intermediate->DATA);
      intermediate = intermediate->NEXT;
      numberInput++;
      }
   }

numberInput = numberInput + countInputBeh(SL_BEH);
amplitude = (int) log((double) numberInput);
if (amplitude < 4) 
   amplitude = 4;

numberNode = 2*amplitude;

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

if (SL_MAKEORDER < 2)
   (sl_sys->par)->level = 0;
level = SL_LEVEL;
if (level < amplitude)
   amplitude = level - 1;

numberInput = numberInput / 2;
if (numberInput < 2)
   numberInput = 2;

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


while (amplitude >= 0 && level >= 1)
   {
   int mode;

   mode = FUN_COUT ;

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

      if ( i == 2 )
         sl_sys->orderPI = makeOrderBddBeh(SL_BEH,SL_OPTIM,SL_OPTIMPO,
                            SL_DELAYPI,1,numberNode,1,trace,numberInput,mode,numberAtomRedFact); 
      else
         sl_sys->orderPI = makeOrderBddBeh(SL_BEH,SL_OPTIM,SL_OPTIMPO,
                             SL_DELAYPI,1,numberNode,1,trace,2000,mode,numberAtomRedFact); 
      makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);

		      	/* calcul d'une nouvelle solution */

      if (i == 1 && notSameOrder(tabSol,numberSol,SL_ORDERPI))
         {
		/* cette phase n'est pas effectuee si l'ordonnancement 
                   a deja ete trouve */

         removeAuxBeh(SL_BEH,saveAux);

         if (SL_OPTIM > 2)
            bddToAblBeh(SL_BEH,1);
         else
            bddToAblBeh(SL_BEH,0);

         if (SL_AUXOF)
            createAuxBeh(SL_BEH);

         compactBeh(SL_BEH);

         coutAblBeh(SL_BEH,&lit,&maxLit,&litRed,&profMax,&delaisMax,&operBin,
                    &litReg,trace,SL_DELAYPI);
         tabSol[numberSol].lit = lit;
         tabSol[numberSol].maxLit = maxLit;
         tabSol[numberSol].litRed = litRed;
         tabSol[numberSol].operBin = operBin;
         tabSol[numberSol].profMax = profMax;
         tabSol[numberSol].delaisMax = delaisMax;
         tabSol[numberSol].order = copyChain_list(SL_ORDERPI);
         numberSol++;

         }
      }

   		/* recuit simule */

   if (amplitude > 0 && level > 1)
      {
      sl_sys->orderPI = randomOrder(SL_ORDERPI,amplitude);
      regenereBddBeh(SL_BEH,SL_ORDERPI);
      makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);
      }
   if (amplitude > 1)
      amplitude--;
   level--;
   }

if (trace)
   printf("--- end of anealing\n");

		/* choix de la meilleure solution */

coutMin = 10000000;
for (i=0;i<numberSol;i++)
   {
   int coutI = coutSol(tabSol[i].lit,
                       tabSol[i].delaisMax,
                       tabSol[i].litRed,
                       tabSol[i].profMax,
                       tabSol[i].operBin,
                       SL_OPTIM);
   if (coutMin > coutI)
      {
      coutMin = coutI;
      indiceMin = i;
      }
   }

		/* regeneration des graphes */

if (trace)
   printf("Graph regeneration %d \n",indiceMin);

sl_sys->orderPI = tabSol[indiceMin].order; 

regenereBddBeh(SL_BEH,SL_ORDERPI);
makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);

removeAuxBeh(SL_BEH,saveAux);

if (trace)
   {
   gcNodeBeh(SL_BEH);
   printf("$$$$$$ final number of nodes = %d\n\n",numberNodeAllBdd());
   }

if (SL_MAKEORDER < 2 || trace)
   {
   printf("Cost Function --- litt. = %d ",numberAtomRedBeh(SL_BEH));
   gcNodeBeh(SL_BEH);
   printf("--- nodes = %d\n\n",numberNodeAllBdd());
   }

if (SL_OPTIM > 2)
   bddToAblBeh(SL_BEH,1);
else
   bddToAblBeh(SL_BEH,0);

if (trace)
   printf("Generating VI\n");

if (SL_AUXOF)
   createAuxBeh(SL_BEH);

compactBeh(SL_BEH);

	/* on inverse l'ordre des expressions et 
           on cree des variable Inter a nouveau */

mapCarExprBeh(SL_BEH,reverseExpr);

if (SL_AUXOF)
   createAuxBeh(SL_BEH);

compactBeh(SL_BEH);

mapCarExprBeh(SL_BEH,reverseExpr);
}



/*-------------------------------------------------------------------------
anealingFOOD 	: recuit simule pour l'optimisation comportementale 
	          on prend en entree une befig qui possede un certain nombre
		  de graphes deja calcules.
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/

void anealingFOOD(trace)
int trace;
{
int lit,maxLit,litRed,litReg,profMax,delaisMax,operBin;


printf("Running Behavioral Optimizer on `%s`...\n\n",SL_NAME);

coutAblBeh(SL_BEH,&lit,&maxLit,&litRed,&profMax,&delaisMax,&operBin,
           &litReg,trace,SL_DELAYPI);
PRINTF("==============================  INITIAL COST  ==================================\n");
PRINTF("Total number of litterals   = %d\n",lit);
PRINTF("Reduced number of litterals = %d\n",litRed);
PRINTF("Register litterals          = %d\n",litReg);
PRINTF("Number of binary operators  = %d\n",operBin);
PRINTF("Cone maximum                = %d\n",maxLit);
PRINTF("Depth maximum               = %d\n",profMax);
PRINTF("Delay maximum               = %.3f\n",((float) delaisMax)/1000);
PRINTF("===============================================================================\n");

if (SL_AUX)
   localOpt(trace);
else
   globalOpt(trace);

		/* pro-crastination des VI */

if (PROCRASTINATION)
   {
   int i;

   for (i=0;i<PROCRASTINATION;i++)
      {
      chain_list *order = copyChain_list(SL_ORDERPI);

      if (trace)
         printf("******  Procrastination of VI\n");

      optimBeh(SL_BEH,SL_OPTIM,SL_DELAYPI,SL_OPTIMPO,order);

      if (trace == 2)
         printf("******* End of procrastination\n");

      regenereBddBeh(SL_BEH,SL_ORDERPI);
      makeBddBeh(SL_BEH,SL_CIRCUIT,0,trace,200,1000000,NULL);

	/* on normalise les expressions avant de creer les auxiliaires */

      mapExprBeh(SL_BEH,normExpr);

      if (SL_AUXOF)
         createAuxBeh(SL_BEH);
   
      if (trace == 2)
         {
         displayBeh(SL_BEH,1);
         printf("Collapsing\n");
         }

      compactExprBeh(SL_BEH,SL_OPTIM,SL_DELAYPI,SL_OPTIMPO,1);
      }
   }

coutAblBeh(SL_BEH,&lit,&maxLit,&litRed,&profMax,&delaisMax,&operBin,
                 &litReg,trace,SL_DELAYPI);
PRINTF("===============================  FINAL COST  ===================================\n");
PRINTF("Total number of litterals   = %d\n",lit);
PRINTF("Reduced number of litterals = %d\n",litRed);
PRINTF("Register litterals          = %d\n",litReg);
PRINTF("Number of binary operators  = %d\n",operBin);
PRINTF("Cone maximum                = %d\n",maxLit);
PRINTF("Depth maximum               = %d\n",profMax);
PRINTF("Delay maximum               = %.3f\n",((float) delaisMax)/1000);
PRINTF("================================================================================\n");
}

