/* ###--------------------------------------------------------------### */
/*									*/
/* file		: bdd_order.c						*/
/* date		: april 05 92	                           		*/
/* author	: BURGUN L.						*/
/*									*/
/* contents	: This file contains ordonnancer on BDD			*/
/*		  for the logical synthetiser 				*/
/*									*/
/* ###--------------------------------------------------------------### */
#include MUT_H
#include LOG_H
#include BEH_H
#include <math.h>
#include "bdd_order.h"
#include "../compil/lax_param.h"
#include "../synthe/sl_type.h"
#include "../compil/sl_util.h"

int costX3000();

/*-------------------------------------------------------------------------
randomOrder 	: effectue une re-ordonnancement aleatoire d'amplitude amp. 
---------------------------------------------------------------------------
retour		: une liste d'entrees 
---------------------------------------------------------------------------*/
chain_list *randomOrder(ptChain,amp)
chain_list * ptChain;
int amp;
{
chain_list *pt;
int cpt,i,j;
struct st_ptab {
   int index;
   char *name;
   } *pTabChain;

cpt = 0;
pt = ptChain;
while (pt)
   {
   pt = pt->NEXT;
   cpt++;
   }
pTabChain = (struct st_ptab *) mbkalloc (cpt * sizeof(struct st_ptab));
cpt = 0;
pt = ptChain;
while (pt)
   {
   pTabChain[cpt].index = cpt + abs((int) srand(((int) pt)>>2) % amp);
   pTabChain[cpt].name = (char *)pt->DATA;
   pt = pt->NEXT;
   cpt++;
   }
freechain(ptChain);
ptChain = NULL;

for (i=0;i<cpt;i++)
   {
   int indexMax= -1;
   int indiceMax;
   for (j=0;j<cpt;j++)
      if (pTabChain[j].index > indexMax)
         {
	 indiceMax = j;
         indexMax = pTabChain[j].index;
         } 
   pTabChain[indiceMax].index = -1;
   ptChain = addchain(ptChain,pTabChain[indiceMax].name);
   }
mbkfree(pTabChain);
return(ptChain);
}

/*-------------------------------------------------------------------------
numberBddSup 	: calcule le nombre d'ABL d'une befig de taille superieur
                  a numnode.
---------------------------------------------------------------------------
retour		: le nombre d'ABL.
---------------------------------------------------------------------------*/
int  numberBddSup(beh,numnode)
befig_list *beh;
int numnode;
{
beout_list *out;
beaux_list *aux;
bebus_list *bus;
bebux_list *bux;
bereg_list *reg;
binode_list *binode;
biabl_list *biabl;

int numberAbl=0;

out = beh->BEOUT;
while (out)
   {
   if (out->NODE != NULL && numberNodeBdd(out->NODE)>numnode)
      numberAbl++;
   out = out->NEXT;
   }

	/* on prend en compte les "aux" passes dans les "input" du circuit */

aux = beh->BEAUX;
while (aux)
   {
   if (searchInputCct(beh->CIRCUI,aux->NAME) != EMPTYTH ||
       searchOutputCct(beh->CIRCUI,aux->NAME) !=  NULL)
      if (aux->NODE != NULL && numberNodeBdd(aux->NODE)>numnode)
         numberAbl++;
   aux = aux->NEXT;
   }

reg = beh->BEREG;
while (reg)
   {
   binode = reg->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         numberAbl++;
      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         numberAbl++;
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus)
   {
   binode = bus->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         numberAbl++;
      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         numberAbl++;
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux)
   {
   binode = bux->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         numberAbl++;
      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         numberAbl++;
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }


return(numberAbl);
}

/*-------------------------------------------------------------------------
makeOrderBddBeh 	: calcule un bon ordonnancement sur le circuit d'une befig.
  		  optim : mode d'optimisation (ne sert plus a rien...)
		  optimPO : les sorties a optimiser (ponderation)
  		  delayPI : les entrees retardees
                  accuracy : precision de l'ordonnancement (1 = + precis)
                  numnode  : le nombre de noeuds a partir duquel on
                             prend en compte le graphe.
                  gcOK     : 1 si on peut faire un garbage collector
                  mode     : 0 si cout = nombre de noeuds uniquement
---------------------------------------------------------------------------
retour		: la liste des entrees ordonnnees.
---------------------------------------------------------------------------*/
chain_list *makeOrderBddBeh(beh,optim,optimPO,delayPI,
                        accuracy,numnode,gcOK,trace,numberInputUpMax,mode,func)
befig_list *beh;
int optim;
chain_list *optimPO;
ptype_list *delayPI;
int accuracy;
int numnode;
int gcOK;
int trace;
int numberInputUpMax;
int mode;
int (*func)();
{
int i,j,k,countNodeSys;
pNode ptNode;
int index,indexNewPI;
int numberNoPI;
int bestInput;
long bestCout;
long bestCoutInit;
char **pNameO;
beout_list *out;
beaux_list *aux;
bebus_list *bus;
bebux_list *bux;
bereg_list *reg;
binode_list *binode;
biabl_list *biabl;

int *pTabDelayPI,*pTabOptimPO;
int *pTabCoutPI;
pCircuit pC;
int numberI,numberO;
bdd_tableOrder *matOrder;
chain_list *result,*resultI,*ptChain;
int cpt_other;
int numberInputUp = 0;
chain_list *support;
chain_list *makeOrderAbl();

if (trace)
   printf("Running make order BDD...\n");

if (accuracy < 1)
   {
   printf("makeOrderBddBeh : error on accuracy = %d  < 1\n",accuracy);
   exit(-1);
   }
		/* initialisation */
 
numberI = ((beh->CIRCUI)->pTI)->count;
numberO = numberBddSup(beh,numnode);

if (trace)
   printf("input = %d  ouput = %d\n",numberI,numberO);

pC = beh->CIRCUI;


result = NULL;
resultI = NULL;

if (numberO == 0)
   {
   for (i=0;i<pC->countI-2;i++)
      {
      result = addchain(result,*(pC->pNameI+i));
      }
   regenereBddBeh(beh,result);
   return(result);
   }

pNameO = (char **) mbkalloc (sizeof (char *) * numberO) ;


matOrder = (bdd_tableOrder *) mbkalloc (numberI*numberO*sizeof(bdd_tableOrder));
for (i=0;i<numberI;i++)
   for (j=0;j<numberO;j++)
      {
      matOrder[i+numberI*j].ptNode = NULL;
      matOrder[i+numberI*j].support = 'N';
      }

	/* table des facteurs d'optimisation pour les entrees */

pTabDelayPI = (int *) mbkalloc (numberI*sizeof(int));
for (i=0;i<numberI;i++)
   pTabDelayPI[i] = 10;

while (delayPI)
   {
   i = searchInputCct(pC,delayPI->DATA);
   if (i != EMPTYTH)
      {
		/* calcul du facteur pour une delai entre 1 et 100 ns */

      if (delayPI->TYPE > 1000 && delayPI->TYPE < 100000)
         pTabDelayPI[i-2] = pTabDelayPI[i-2] - (int) log((double) (delayPI->TYPE / 1000)) -1;   

		/* on bloque la progression a 100 ns */

      if (delayPI->TYPE >= 100000)
         pTabDelayPI[i-2] = 5;
      }
   delayPI = delayPI->NEXT;
   }

	/* table des resultats d'optimisation pour les entrees */

pTabCoutPI = (int *) mbkalloc (numberI*sizeof(int));
for (i=0;i<numberI;i++)
   pTabCoutPI[i] = 1;

	/* table des facteurs d'optimisation pour les sorties */

pTabOptimPO = (int *) mbkalloc (numberO*sizeof(int));
for (j=0;j<numberO;j++)
   pTabOptimPO[j] = 1;


j=0;

out = beh->BEOUT;
while (out) 
   {
		 /* si le BDD existe  et si il est interessant */

   if (out->NODE != NULL && numberNodeBdd(out->NODE)>numnode)  
      {
      *(pNameO + j) = out->NAME;

		/* sortie a optimiser */

      if (inChain_list(optimPO,out->NAME))
         pTabOptimPO[j] = 2;

				/* calcul du support */

      support = (chain_list *) supportIndexBdd(out->NODE,1);
      while (support)
         {
         matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
         support = support->NEXT; 
         }
      freechain(support);
      addOutputCct(pC,out->NAME,out->NODE);
      j++;
      }
   else
      if (out->NODE != NULL)
         addOutputCct(pC,out->NAME,out->NODE);
   out = out->NEXT;
   }

   aux = beh->BEAUX;
   while (aux) 
      {

      if (searchInputCct(pC,aux->NAME) != EMPTYTH ||
          searchOutputCct(pC,aux->NAME) != NULL)
         {

		 /* si le BDD existe  et si il est interessant */

         if (aux->NODE != NULL && numberNodeBdd(aux->NODE)>numnode)  
            {
            *(pNameO + j) = aux->NAME;

		/* sortie a optimiser */

            if (inChain_list(optimPO,aux->NAME))
               pTabOptimPO[j] = 2;

				/* calcul du support */

            support = (chain_list *) supportIndexBdd(aux->NODE,1);
            while (support)
               {
               matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
               support = support->NEXT; 
               }
            freechain(support);
            addOutputCct(pC,aux->NAME,aux->NODE);
            j++;
            }
         else
            if (aux->NODE != NULL)
               addOutputCct(pC,aux->NAME,aux->NODE);
         }
      aux = aux->NEXT;
      }

cpt_other = 0;
reg = beh->BEREG;
while (reg)
   {
   binode = reg->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         {
         *(pNameO + j) = gensym("reg",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,reg->NAME))
            pTabOptimPO[j] = 2;

				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->CNDNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("reg",j),binode->CNDNODE);
         j++;
         }
      else
         if (binode->CNDNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->CNDNODE);

      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         {
         *(pNameO + j) = gensym("reg",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,reg->NAME))
            pTabOptimPO[j] = 2;
				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->VALNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("reg",j),binode->VALNODE);
         j++;
         }
      else
         if (binode->VALNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->VALNODE);

      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }


bus = beh->BEBUS;
while (bus)
   {
   binode = bus->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         {
         *(pNameO + j) = gensym("bus",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,bus->NAME))
            pTabOptimPO[j] = 2;
				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->CNDNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("bus",j),binode->CNDNODE);
         j++;
         }
      else
         if (binode->CNDNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->CNDNODE);

      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         {
         *(pNameO + j) = gensym("bus",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,bus->NAME))
            pTabOptimPO[j] = 2;

				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->VALNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("bus",j),binode->VALNODE);
         j++;
         }
      else
         if (binode->VALNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->VALNODE);

      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }


bux = beh->BEBUX;
while (bux)
   {
   binode = bux->BINODE;
   while (binode)
      {
      if (binode->CNDNODE != NULL && numberNodeBdd(binode->CNDNODE)>numnode)
         {
         *(pNameO + j) = gensym("bux",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,bux->NAME))
            pTabOptimPO[j] = 2;
				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->CNDNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("bux",j),binode->CNDNODE);
         j++;
         }
      else
         if (binode->CNDNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->CNDNODE);

      if (binode->VALNODE != NULL && numberNodeBdd(binode->VALNODE)>numnode)
         {
         *(pNameO + j) = gensym("bux",j);

		/* sortie a optimiser */

         if (inChain_list(optimPO,bux->NAME))
            pTabOptimPO[j] = 2;

				/* calcul du support */

         support = (chain_list *) supportIndexBdd(binode->VALNODE,1);
         while (support)
            {
            matOrder[(int) (support->DATA) - 2 + numberI*j].support = 'O';
            support = support->NEXT; 
            }
         freechain(support);
         addOutputCct(pC,gensym("bux",j),binode->VALNODE);
         j++;
         }
      else
         if (binode->VALNODE != NULL)
            addOutputCct(pC,gensym("other",++cpt_other),binode->VALNODE);

      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }
numberO = j;
countNodeSys = numberNodeCct(beh->CIRCUI);

if (trace)
   printf("initial number of nodes = %d\n",countNodeSys);

		/* si le circuit est trop gros...optimisation en surface */
if (countNodeSys > 10000) 
   {
   mode = 0;
   if (numberNodeAllBdd() > 50000 && gcOK)
      {
		/* sauvegarde des noeuds du circuit */

      gcNodeCct(pC); 
      if (trace)
         printf("after gc = %d\n",sysBdd.pRT->compteur);
      }
   }



	/* elimination des entrees qui ne font parties d'aucun support */

numberNoPI=0;
for(i=numberI-1;i>=0;i--)
   {
   for (j=0;j<numberO;j++)
      if (matOrder[i + numberI*j].support == 'O') break;
   if (j == numberO)
      {
      for (j=0;j<numberO;j++)
         matOrder[i + numberI*j].support = 'D';
      resultI = addchain(resultI,*(pC->pNameI+i));
/*
      printf("%s ne fait partie d'aucun support\n",*(pC->pNameI+i));
*/
      numberNoPI++;
      }
   }
		/* creation des input(s) virtuels */

for (i=0;i<numberI - numberNoPI;i++)
   {
   addInputCct(pC,gensym("newpi",i+numberI+2));
   }

				/* re-ordonnancement */

indexNewPI = 2*numberI + 1;

while (indexNewPI != numberI+1+numberNoPI)
   {
   int numberInputComputed = 0;
   int nodeMin;

   for (i=0;i<numberI;i++)
      {
      index = i+2;
      
      for (j=0;j<numberO;j++)
         {

	/* si on a trop de noeuds, on ne cherche pas le cout
           des autres entrees */

         if (numberNodeAllBdd() > 500000) 
            {
            ptNode = searchOutputCct(pC,*(pNameO + j));
            if (ptNode == NULL)
               {
               printf("makeOrdeBddBeh : error output %s has no Bdd\n",*(pNameO + j));
               exit(-1);
               }
      	    matOrder[i+numberI*j].ptNode = ptNode;
            }
         else
            {
            switch (matOrder[i+numberI*j].support)
               {
               case 'O' : 
                  ptNode = searchOutputCct(pC,*(pNameO + j));
                  if (ptNode == NULL)
                     {
                     printf("makeOrdeBddBeh : error output %s has no Bdd\n",*(pNameO + j));
                     exit(-1);
                  }
      	          matOrder[i+numberI*j].ptNode = upVarBdd(ptNode,
                                                       createNodeTermBdd(i+2),
                                                       indexNewPI);
                  break;
               case 'N' :
                  ptNode = searchOutputCct(pC,*(pNameO + j));
                  if (ptNode == NULL)
                     {
                     printf("makeOrdeBddBeh : error output %s has no Bdd\n",*(pNameO + j));
                     exit(-1);
                     }
      	          matOrder[i+numberI*j].ptNode = ptNode;
                  break;
               case 'D' :
                  break; 
               }
            }
         }
      } 
   		/* calcul des couts de chaque input */

   if (trace)
      printf("Computing the cost of each input...\n");

   nodeMin = 100000;

   for (i=numberI-1;i>=0;i--)
      {
      int countNodeI;
      int numberLitR;

      countNodeI = 0;
      numberLitR = 0;


      if (matOrder[i].support != 'D')	/* entree non traitee */
         {
         int costInput;

	/* quand mode = 0  seul le nombre de noeud BDD compte */
        /* si mode = 1 seul la fonction de cout passee en argument 
           'func' compte */

         
		/* calcul du nombre de noeuds Bdd */

         for (j=0;j<numberO;j++)
            {
            markBdd(matOrder[i+numberI*j].ptNode,0);
            } 

         for (j=0;j<numberO;j++)
            {
            countNodeI = countNodeI+countNode(matOrder[i+numberI*j].ptNode);
            } 

         for (j=0;j<numberO;j++)
            {
            markBdd(matOrder[i+numberI*j].ptNode,0);
            } 


         if (nodeMin > countNodeI)
            nodeMin = countNodeI;

			/* si le nombre de noeuds BDD n'est pas trop grand
                           on calcule le nombre de litteraux reduits */

         if (mode != 0 && func != NULL)
            {

         		/* calcul du nombre d'atomes reduits estimes */

            if (100*nodeMin > 95*countNodeI)
               {
               numberInputComputed++;
               markAllBdd(0);

               if ((* func) == costX3000)
                  {
                  chain_list *lstCLB4 = NULL;
                  chain_list *tete;

                  for (j=0;j<numberO;j++)
                     {
                     numberLitR = numberLitR + 
                          costX3000(matOrder[i+numberI*j].ptNode,&lstCLB4);
                     } 
 
                  tete = lstCLB4;
                  while (lstCLB4)
                     {
                     if (lstCLB4->DATA)
                        freechain(lstCLB4->DATA);
                     lstCLB4 = lstCLB4->NEXT;
                     }
                  freechain(tete);
                  }
               else
                  {
                  for (j=0;j<numberO;j++)
                     {
                     numberLitR = numberLitR + 
                               (* func)(matOrder[i+numberI*j].ptNode);
                     } 
                  }

               markAllBdd(0);
               }
            else
               numberLitR = 100000;
            }
         else
            numberInputComputed++;



	/* quand mode = 0  seul le nombre de noeuds compte */
 
         if (mode == 0)
            costInput = countNodeI;
         else
            costInput = numberLitR;

         if (trace)
            {
            printf("%s :\t ",*(pC->pNameI+i));
            printf("--- nodes = %d ",countNodeI);
            printf("--- cost = %d \n",numberLitR);
            }

         pTabCoutPI[i] =  costInput;
         }
      }

   		/* selection des meilleures input */

   if (trace)
      printf("Selecting the best inputs...\n");

   for (k=0;(k<accuracy) && (k < numberInputComputed);k++)
      {
      bestInput = -1;
      bestCout = 10000000;
      for (i=0;i<numberI;i++)
         {
         if (matOrder[i].support != 'D' && pTabCoutPI[i] < bestCout)
            {
            bestInput = i;
            bestCout = pTabCoutPI[i];
            }
         }

		/* le meilleur cout initial */

      if (k == 0)
         bestCoutInit = bestCout;

      if (bestInput == -1)	/* sortie quand il ne reste plus d'entrees */
         break;
      result = addchain(result,*(pC->pNameI+bestInput));
      upVarCct(pC,createNodeTermBdd(bestInput+2),indexNewPI);
      numberInputUp++;

      if (trace)
         {
         printf("*** Selected input : %s \t ",*(pC->pNameI+bestInput));
         printf("--- nodes = %d ",numberNodeCct(pC));
         if (k == 0)
            printf("--- cost = %d \n",bestCout);
         else
            printf("\n");
         }
      PRINTF(".");
      fflush(stdout);

      for (j=0;j<numberO;j++)
         matOrder[bestInput+numberI*j].support = 'D';
      indexNewPI--; 
      }
			/* la reallocation */

   if (numberNodeAllBdd() > 50000 && gcOK)
      {
		/* sauvegarde des noeuds du circuit */

      gcNodeCct(pC); 
      if (trace)
         printf("after gc = %d\n",sysBdd.pRT->compteur);
      }

		/* on avance sur les solutions de meme cout */

   while (1)
      {
      int factor;

      if (mode == 0)
         factor = 990;
      else
         factor = 995;

      bestInput = -1;
      for (i=0;i<numberI;i++)
         {
         if (accuracy > 1)
            {
            if (matOrder[i].support != 'D' && 
               (factor*pTabCoutPI[i] < 1000*bestCoutInit))
               {
               bestInput = i;
               }
            }
         else
            {
            if (matOrder[i].support != 'D' && 
                pTabCoutPI[i] == bestCoutInit)
               {
               bestInput = i;
               } 
            }
         }
      if (bestInput == -1)	/* sortie quand il ne reste plus d'entrees */
         break;
      result = addchain(result,*(pC->pNameI+bestInput));
      upVarCct(pC,createNodeTermBdd(bestInput+2),indexNewPI);
      numberInputUp++;
   
      if (trace)
         {
         printf("* Input with same cost :  %s \t ",*(pC->pNameI+bestInput));
         printf("--- nodes = %d ",numberNodeCct(pC));
         printf("--- cost = %d \n",pTabCoutPI[bestInput]);
         }
      PRINTF(".");
      fflush(stdout);

      for (j=0;j<numberO;j++)
      matOrder[bestInput+numberI*j].support = 'D';
      indexNewPI--; 
      }

		/* nombre d'entrees traitees suffisant */

      if (numberInputUp > numberInputUpMax)
         {
         while (1)
            {
          	/* on prend l'ordonnancement que l'on avait calcule avant */

            bestInput = -1;
            for (i=numberI-1;i>=0;i--)
               {
               if (matOrder[i].support != 'D')
                  {
                  bestInput = i;
                  i = 0;
                  }
               }

		/* sortie quand il ne reste plus d'entrees */

            if (bestInput == -1)
               break;

            result = addchain(result,*(pC->pNameI+bestInput));
            upVarCct(pC,createNodeTermBdd(bestInput+2),indexNewPI);


            if (trace)
               {
               printf("** Last input : %s --- ",*(pC->pNameI+bestInput));
               printf("--- nodes = %d ",numberNodeCct(pC));
               printf("--- cost = %d \n",pTabCoutPI[bestInput]);
               }
            PRINTF(".");
            fflush(stdout);

            for (j=0;j<numberO;j++)
               matOrder[bestInput+numberI*j].support = 'D';
            indexNewPI--; 

			/* la reallocation */

            if (numberNodeAllBdd() > 50000 && gcOK)
               {
		/* sauvegarde des noeuds du circuit */

               gcNodeCct(pC); 
               if (trace)
                  printf("after gc = %d\n",sysBdd.pRT->compteur);
               }
            }
         }

	/* la re-allocation si le nombre de noeuds est trop gros */

   if (trace)
      printf("number of nodes in memory = %d\n",numberNodeAllBdd());

   if (numberNodeAllBdd() > 50000 && gcOK)
      {
		/* sauvegarde des noeuds du circuit */

      gcNodeCct(pC); 
      if (trace)
         printf("after gc = %d\n",sysBdd.pRT->compteur);
      }
   }
		/* remise a jour des BDD de la befig */


		/* concatenation result + resultI */

if (resultI != NULL)
   {
   ptChain = resultI;
   while (ptChain->NEXT != NULL)
      {
      ptChain = CDR(ptChain);
      }
   ptChain->NEXT = result;
   result = resultI;
   }
PRINTF("\n");

if (result == NULL)
   {
   printf("makeOrderBddBeh : error no order found\n");
   exit(-1); 
   }
regenereBddBeh(beh,result);

mbkfree(matOrder);
mbkfree(pTabDelayPI);
mbkfree(pTabCoutPI);
mbkfree(pTabOptimPO);
mbkfree(pNameO);

return(result);
}
