/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : DESB  v2.n                                                  */
/*    Fichier : useabl.c                                                    */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Marc LAURENTIN                        le : 06/09/1991     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/
#include"head.h"

befig_list * CURRENT_BEFIG;
chain_list * FCF_CONE_LIST ;
short FCF_X_CONTR;            /* Il existe des contrainte a respecter */

static chain_list * anOtherMakeOrder();
static void affOrder();

/****************************************************************************
 *                         fonction NameToBeout();                          *
 ****************************************************************************/
beout_list * NameToBeout(fig,name)
befig_list * fig;
char * name;
{
beout_list * out= NULL;

   for(out=fig->BEOUT;out!=NULL;out=out->NEXT)
   {
      if(out->NAME==name) return(out);
   }

fcfFatalError(4,"NameToBeout",name,NULL,0);
return(NULL);
}

/****************************************************************************
 *                         fonction BeoutNameToAbl();                       *
 ****************************************************************************/
chain_list * BeoutNameToAbl(fig,name)
befig_list * fig ;
char * name ;
{
beout_list * beout;
beout=NameToBeout(fig,name);
   if(beout!=NULL) return(beout->ABL);
   else
   {
   fcfFatalError(4,"BeoutNameToAbl",name,NULL,0);
   }
}


/****************************************************************************
 *                         fonction BeoutNameToBdd();                       *
 ****************************************************************************/
pNode BeoutNameToBdd(fig,name)
befig_list * fig ;
char * name ;
{
beout_list * beout;
beout=NameToBeout(fig,name);
   if(beout!=NULL) return(beout->NODE);
   else
   {
   fcfFatalError(4,"BeoutNameToBdd",name,NULL,0);
   }
}

   
/****************************************************************************
 *                         fonction dsdAddBerin();                          *
 ****************************************************************************/
berin_list * dsbAddBerin(berin,name)
berin_list * berin;
char * name;
{
berin_list * curBerin;

   for(curBerin=berin; curBerin != NULL;curBerin=curBerin->NEXT)
      if(curBerin->NAME==name) break ;

   if(curBerin==NULL)
   {
   berin=beh_addberin(berin,name);
   }
return(berin);
}

/****************************************************************************
 *                         fonction dsbAddBeaux();                          *
 ****************************************************************************/
beaux_list * dsbAddBeaux(beaux,name,abl)
beaux_list * beaux;
chain_list * abl ;
char * name ;
{
beaux_list * curBeaux;
   for(curBeaux=beaux; curBeaux != NULL; curBeaux=curBeaux->NEXT)
   {
      if(curBeaux->NAME==name) break;
   }
   if(curBeaux==NULL) beaux=beh_addbeaux(beaux,name,abl,NULL);
return(beaux);
}

/****************************************************************************
 *                         fonction dsbAddBeout();                          *
 ****************************************************************************/
beout_list * dsbAddBeout(beout,name,abl)
beout_list *beout;
char * name ;
chain_list * abl ;
{
beout_list * curBeout;
   for(curBeout=beout; curBeout != NULL; curBeout=curBeout->NEXT)
   {
      if(curBeout->NAME==name) break;
   }
   if(curBeout==NULL) beout=beh_addbeout(beout,name,abl,NULL);
return(beout);
}

/****************************************************************************
 *                         fonction PathToAbl();                            *
 ****************************************************************************/
 /*-------------------------------------------------------------------------*
 | Renvoie l'Abl correspondant a la branche. Ne fait pas les verifications :|
 | Soit Bleeder, soit coupee etc...                                         |
 |+------------------------------------------------------------------------+|
 || Avec cette fonction, les abl des branches externes ne donnent qu'une   ||
 || valeur au connecteur externe                                           ||
 |+------------------------------------------------------------------------+|
 *-------------------------------------------------------------------------*/
chain_list * PathToAbl(branche)
list_list * branche;
{
chain_list * abl ;
link_list * link ; 
chain_list * atom ;
cone_list * cone ;
chain_list * ablUp;
chain_list * ablDn;

abl=NULL;
link=(link_list*)branche->DATA ;

   /*--------------------------------*
    | Cas du maillon Unique          |
    *--------------------------------*/
   if(link->NEXT == NULL )
   {
      /*---------------------------------*
       | Si c'est une resistance         |
       *---------------------------------*/
      if ((link->TYPE & RESIST) == RESIST)
      {
         if((branche->TYPE & VSS)==VSS)
         return(createAtom("'0'"));
         else if ((branche->TYPE & VDD)==VDD)
         return(createAtom("'1'"));
      }
      /*---------------------------------*
       | Si ce n'est pas une resistance  |
       *---------------------------------*/
      else if ((link->TYPE & TN)==TN)
      {
      abl=createAtom(((cone_list*)link->TRANS->GRID)->NAME);
      return(abl);
      }
      else if ((link->TYPE & TP)==TP)
      {
      abl=createAtom(((cone_list*)link->TRANS->GRID)->NAME);
      return(notExpr(abl));
      }
      else /* Connecteur Externe */
      {
      return(createAtom(((locon_list*)link->TRANS)->NAME));
      }
   }

   /*--------------------------------------------*
    | Branche comportant plusieurs maillons      |
    *--------------------------------------------*/
   if (((branche->TYPE & EXT) != EXT ) && (link->NEXT != NULL) )
   {
   short n_link = 0 ;
   short n_resist = 0 ;
   abl=createExpr(AND);

      for(link=(link_list*)branche->DATA ; link != NULL ; link= link->NEXT)
      {
         if ((link->TYPE & RESIST)==RESIST) n_resist ++ ;
      n_link ++ ;
      cone=(cone_list*)link->TRANS->GRID ;
      atom=createAtom(cone->NAME);

         if((link->TYPE & TN)==TN) 
         {
         addQExpr(abl,atom);
         }
         else if((link->TYPE & TP)==TP)
         {
         addQExpr(abl,notExpr(atom));
         }
      }

      /*---------------------------------------------------*
       | La branche est composee uniquement de resistances |
       *---------------------------------------------------*/
      if(n_link==n_resist)
      {
         if((branche->TYPE & VSS)==VSS) return(createAtom("'0'"));
         else if ((branche->TYPE & VDD) == VDD) return(createAtom("'1'"));
      }
      else return(abl);
   }

   /*------------------------------------------------------*
    | Branche de type EXT comportant plusieurs maillons    |
    *------------------------------------------------------*/
   if(((branche->TYPE & EXT)==EXT) && (link->NEXT != NULL) )
   {
   short n_resist = 0 ;
   short n_link   = 0 ;

   ablUp=createExpr(AND);

      for(link=(link_list*)branche->DATA;link->NEXT != NULL;link=link->NEXT)
      {
         if((link->TYPE & RESIST)==RESIST) n_resist++ ;
      n_link++;
      cone=(cone_list*)link->TRANS->GRID ;
      atom=createAtom(cone->NAME);
         if((link->TYPE & TN)==TN) 
         {
         addQExpr(ablUp,atom);
         }
         else if((link->TYPE & TP)==TP)
         {
         addQExpr(ablUp,notExpr(atom));
         }
      }
   /* On traite le dernier maillon qui est un connecteur */
   atom=createAtom( ((locon_list*)link->TRANS)->NAME );
   addQExpr(ablUp,atom);

      if(n_link==n_resist)
      {
      return(atom);
      }
   return(ablUp);
   }
}


/****************************************************************************
 *                         fonction PathToAblHz();                          *
 ****************************************************************************/
/*--------------------------------------------------------------------------*
 | Renvoie l'Abl correspondant a la branche. Ne fait pas les verifications :|
 | Soit Bleeder, soit coupee etc...                                         |
 *--------------------------------------------------------------------------*/
chain_list * PathToAblHz(branche)
list_list * branche;
{
chain_list * abl ;
link_list * link ; 
chain_list * atom ;
cone_list * cone ;
chain_list * ablUp;
chain_list * ablDn;

abl=NULL;
link=(link_list*)branche->DATA ;

   /*--------------------------------*
    | Cas du maillon Unique          |
    *--------------------------------*/
   if(link->NEXT == NULL )
   {
      /*---------------------------------*
       | Si c'est une resistance         |
       *---------------------------------*/
      if ((link->TYPE & RESIST) == RESIST)
      {
         if((branche->TYPE & VSS)==VSS)
         return(createAtom("'0'"));
         else if ((branche->TYPE & VDD)==VDD)
         return(createAtom("'1'"));
      }
      /*---------------------------------*
       | Si ce n'est pas une resistance  |
       *---------------------------------*/
      else if ((link->TYPE & TN)==TN)
      {
      abl=createAtom(((cone_list*)link->TRANS->GRID)->NAME);
      return(abl);
      }
      else if ((link->TYPE & TP)==TP)
      {
      abl=createAtom(((cone_list*)link->TRANS->GRID)->NAME);
      return(notExpr(abl));
      }
      else
      {
      return(createAtom(((locon_list*)link->TRANS)->NAME));
      }
   }

   /*--------------------------------------------*
    | Branche comportant plusieurs maillons      |
    *--------------------------------------------*/
   if (((branche->TYPE & EXT) != EXT ) && (link->NEXT != NULL) )
   {
   short n_link = 0 ;
   short n_resist = 0 ;
   abl=createExpr(AND);

      for(link=(link_list*)branche->DATA ; link != NULL ; link= link->NEXT)
      {
         if ((link->TYPE & RESIST)==RESIST) n_resist ++ ;
      n_link ++ ;
      cone=(cone_list*)link->TRANS->GRID ;
      atom=createAtom(cone->NAME);

         if((link->TYPE & TN)==TN) 
         {
         addQExpr(abl,atom);
         }
         else if((link->TYPE & TP)==TP)
         {
         addQExpr(abl,notExpr(atom));
         }
      }

      /*---------------------------------------------------*
       | La branche est composee uniquement de resistances |
       *---------------------------------------------------*/
      if(n_link==n_resist)
      {
         if((branche->TYPE & VSS)==VSS) return(createAtom("'0'"));
         else if ((branche->TYPE & VDD) == VDD) return(createAtom("'1'"));
      }
      else return(abl);
   }

   /*------------------------------------------------------*
    | Branche de type EXT comportant plusieurs maillons    |
    *------------------------------------------------------*/
   if(((branche->TYPE & EXT)==EXT) && (link->NEXT != NULL) )
   {
   short n_resist = 0 ;
   short n_link   = 0 ;

   abl=createExpr(OR);
   ablUp=createExpr(AND);
   ablDn=createExpr(AND);

      for(link=(link_list*)branche->DATA;link->NEXT != NULL;link=link->NEXT)
      {
         if((link->TYPE & RESIST)==RESIST) n_resist++ ;
      n_link++;
      cone=(cone_list*)link->TRANS->GRID ;
         if((link->TYPE & TN)==TN) 
         {
         atom=createAtom(cone->NAME);
         addQExpr(ablUp,atom);

         atom=createAtom(cone->NAME);
         addQExpr(ablDn,atom);
         }

         else if((link->TYPE & TP)==TP)
         {
         atom=createAtom(cone->NAME);
         addQExpr(ablUp,notExpr(atom));

         atom=createAtom(cone->NAME);
         addQExpr(ablDn,notExpr(atom));
         }
      }
   /* On traite le dernier maillon qui est un connecteur */
   atom=createAtom( ((locon_list*)link->TRANS)->NAME );
   addQExpr(ablUp,atom);

   atom=createAtom( ((locon_list*)link->TRANS)->NAME );
   addQExpr(ablDn,notExpr(atom));

   /* on fait le OR sur les deux abl intermediaires */
   addQExpr(abl,ablUp);
   addQExpr(abl,ablDn);

      if(n_link==n_resist)
      {
      freeExpr(abl);
      atom=createAtom( ((locon_list*)link->TRANS)->NAME );
      return(atom);
      }
   return(abl);
   }
}



/****************************************************************************
 *                         fonction ConeToAbl();                            *
 ****************************************************************************/
/*--------------------------------------------------------------------------*
 | Renvoie l'abl du cone. A utiliser lorsque le cone est ni HZ, ni un Latch |
 *--------------------------------------------------------------------------*/

chain_list * ConeToAbl(cone)
cone_list * cone ;
{
chain_list *abl;
list_list * path ;
int n_path = 0 ;
int n_vss = 0 ;
int n_vdd = 0 ;
int n_ext = 0 ;

   /*---------------------------------------*
    | On cherche le nombre de branches      |
    *---------------------------------------*/
   for(path=cone->PATH;path != NULL ; path=path->NEXT) 
   {
      if((path->TYPE & BLEEDER)==BLEEDER) continue ;
      else 
      {
      n_path++ ;
         if((path->TYPE & VSS)==VSS) n_vss++;
         else if((path->TYPE & VDD)==VDD) n_vdd++;
         else if((path->TYPE & EXT)==EXT) n_ext++;
      }
   }

   /*--------------------------*
    | Cas de la branche unique |
    *--------------------------*/
   if(n_path==1)
   {
      for(path=cone->PATH;path != NULL;path=path->NEXT)
      {
         if((path->TYPE & BLEEDER)==BLEEDER) continue ;
         else
         {
         abl=PathToAbl(path);
            if((path->TYPE & VSS)==VSS) return(notExpr(abl));
            else return(abl);
         }
      }
   }

   /*--------------------------*
    | Branches multiples       |
    *--------------------------*/
   if(n_path >=2)
   {
   chain_list * ablUp;
   chain_list * ablDn;
   chain_list * ablXt;

   abl=createExpr(OR);

      if(n_ext>=2) ablXt=createExpr(OR);
      if(n_vdd>=2) ablUp=createExpr(OR);
      if(n_vss>=2) ablDn=createExpr(OR);

      /*-------------------------------------------*
       | On fabrique les abl intermediaires        |
       *-------------------------------------------*/
      for(path=cone->PATH;path;path=path->NEXT)
      {
         if((path->TYPE & BLEEDER)==BLEEDER) continue ;
         if((path->TYPE & VSS)==VSS)  
         {
            if(n_vss>=2)
            addQExpr(ablDn,PathToAbl(path));
            else ablDn=PathToAbl(path);
         }

         else if ((path->TYPE & VDD)==VDD)
         {
            if(n_vdd>=2)
            addQExpr(ablUp,PathToAbl(path));
            else ablUp=PathToAbl(path);
         }

         else if((path->TYPE & EXT)==EXT)
         {
            if(n_ext>=2)
            addQExpr(ablXt,PathToAbl(path));
            else ablXt=PathToAbl(path);
         }
      }

      /*-----------------------------------*
       | On cumule tout dans un abl final  |
       | en prenant en compte le cas ou le |
       | cone emet toujours sans reseau P  |
       *-----------------------------------*/

      /*-----------------------*
       | Il existe un reseau P |
       *-----------------------*/
      if(n_vdd>=1)
      {
         if(n_ext>=1)
         {
         addQExpr(abl,ablUp);
         addQExpr(abl,ablXt);
         return(abl);
         }
         else return(ablUp);
      }

       /*-----------------------------*
       | Pas de reseau P, On retourne |
       | l'inverse du reseau N        |
       *-----------------------------*/
      else if(n_vss>=1)
      {
         if(n_ext>=1)
         {
         addQExpr(abl,notExpr(ablDn));
         addQExpr(abl,ablXt);
         return(abl);
         }
         else return(notExpr(ablDn));
      }

      /*---------------------------*
       | Que des branches externes |
       *---------------------------*/
      else if(n_ext>=1)
      {
      return(ablXt);
      }
     
      /*---------------------------------*
       | Pas de branches fonctionnelles  |
       *---------------------------------*/
      else return(NULL) ;
   }
}
      
/****************************************************************************
 *                         fonction FoncCone();                             *
 ****************************************************************************/
/*--------------------------------------------+
|    Calcule la Fonctionnalite de cone et met |
|      le pointeur du noeud Bdd correspondant |
|      dans son champ USER                    |
+--------------------------------------------*/
void FoncCone(cone)
cone_list *cone;
{
chain_list * abl;
ptype_list * user;

abl=ConeToAbl(cone);
   if((user=getptype(cone->USER,ABL_UP))==NULL)
   cone->USER=addptype(cone->USER,ABL_UP,(void*)abl);
   else user->DATA=(void*)abl;
}



/****************************************************************************
 *                         fonction makeBefigFromCone();                    *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Fabrique une Befig a partir du cone. La befig est constituee dans le  but |
| d'utiliser les fonctions d'ordonancement developpees pour elle.           |
|                                                                           |
| - A chaque branche est associe une sortie de la befig avec son ABL.  Dans |
|   le cas des branches externes, il y a deux sorties associees.            |
|   Le nom de chaque sortie est fonction du numero de la  branche  et  d'un |
|   prefixe fixe en dur dans le programme.                                  |
|                                                                           |
| - Les eventuelles contraintes externes  sont  aussi  intoduites  dans  la |
|   Befig, de sorte que des sorties supplementaires sont crees.             |
|   Le nom des sorties associees aux contraintes externes est  fonction  du |
|   numero de la contrainte et d'un prefixe fixe en dur dans  le  programme |
|                                                                           |
| - La somme de toutes les branche est auusi calculee. Le nom de la  sortie |
|   est lui aussi fixe                                                      |
|                                                                           |
| - Apres la phase d'ordonancement, les BDD recuperes dans  la  befig  sont |
|   associes aux branches du cone par le ptype.                             |
|                                                                           |
| - Les Bdd non associes a des barnches sont recuperes par  le  nom  de  la |
|   sortie de Befig a laquelle ils sont associes                            |
|                                                                           |
| Entree: + ptr, le pointeur du cone pour lequel une  Befig  est  fabriquee |
|         + coneIndex, l'index du cone dont on veut decompiler la befig  au |
|           format Vhdl. Utilise pour debugger par exemple.                 |
|         + trace, active le mode trace!!                                   |
|         + sign. Cette variable change de valeur si l'ensemble des cones   |
|           primaires a change par rapport a l'iteration precedente         |
|                                                                           |
| Sortie: + Le pointeur de befig fabriquee                                  |
|                                                                           |
+--------------------------------------------------------------------------*/

befig_list * makeBefigFromCone(ptr,coneIndex,trace,sign)
cone_list * ptr ;
long  coneIndex ;
short trace ;
short *sign;
{
int ctrxNum=0;
chain_list * prim_chain ;
befig_list * coneBefig=NULL;
ptype_list * user ;

befig_list * vhdlloadbefig();

      profondeur=0;

      /*------------------------------------------*
       | On cree un befig pour le cone a probleme |
       *------------------------------------------*/
      VHB_HEDFIG=beh_addbefig(VHB_HEDFIG,ptr->NAME);
      CURRENT_BEFIG=VHB_HEDFIG;
      coneBefig=VHB_HEDFIG;


      /*-----------------*
      | Marquage Phase I |
      *-----------------*/
      FCF_CONE_LIST=NULL;
      PropStepMarqOutput(ptr); 
      FCF_CONE_LIST=NULL;

        /*------------------------------------------*
        | On regarde si il existe des connecteurs   |
        | qui doivent respecter des contraintes ext |
        | Si c'est le cas ils sont types Primaire   |
        | et on ajoute l'abl dans la befig          |
        *------------------------------------------*/
         for (prim_chain=HEAD_VARCON; prim_chain; prim_chain=prim_chain->NEXT) 
         {
         prim_chain = GetABL(prim_chain);
            if (prim_chain != NULL) 
            {
            char ctrxName[20];
            chain_list * abl ;
            ctrxNum++;
            sprintf(ctrxName,"ctrx_%d",ctrxNum);
            abl=(chain_list*)((list_list*)(prim_chain->DATA))->USER;
            coneBefig->BEOUT=(beout_list *)dsbAddBeout(coneBefig->BEOUT,namealloc(ctrxName),copyExpr(abl));
            AddPrimType((list_list*)prim_chain->DATA);
            FCF_X_CONTR++;
            }
            else break;
         }

      /*-------------------*
      | Marquage Phase II  |
      | Profondeur init=0  |
      *-------------------*/
      FCF_CONE_LIST=NULL;
      PropStep(ptr,0);
      FCF_CONE_LIST = NULL ;

      /*----------------------------------------------------+
      | On regarde si la liste des variables primaires      |
      | trouvees pour le cone courant a changee par rapport |
      | a l'iteration precedente                            |
      +----------------------------------------------------*/
      {
      ptype_list * user ;
      char *signature;

      signature=fcfMakeSign(FCF_PRIM_INDEX);
      user=getptype(ptr->USER,FCF_SIGN);

         if(user == NULL)
         {
         (*sign)++;
         ptr->USER=addptype(ptr->USER,FCF_SIGN,(void*)signature);
         }
         else
         {
         char * oldSign=(char*)user->DATA ;
            if(signature==oldSign)
            {
            return; 
            }
            else 
            {
            (*sign)++;
            user->DATA=(void*)signature;
            }
         }
      }

     /*--------------------------------------------------+
     | A chaque branche du cone est associee une sortie  |
     | de la BEFIG dont l'abl est l'abl de la branche    |
     | On range dans le User NAME  du path, son nom      |
     | On range dans le user ABL , l'abl                 |
     | Si la branche est externe, on fabrique deux abl   |
     | -- un pour lequel le connecteur n'a qu'une valeur |
     |    (pour la detection de conflit)                 |
     | -- un autre pour lequel il en a deux              |
     |    (pour la detection de Haute Impedance)         |
     |  Il y a donc 2 noms et 2 abl pour ces branches    |
     +--------------------------------------------------*/
      {
      list_list * path;
      int branNum =0 ;
         for(path=ptr->PATH;path != NULL; path=path->NEXT)
         {
         chain_list * abl;
         char brancheName[15];
         ptype_list* user;
         branNum++;

            if((path->TYPE & BLEEDER)==BLEEDER) continue;

         sprintf(brancheName,"Br_%d",branNum);

         abl=PathToAbl(path);
         coneBefig->BEOUT=(beout_list *)dsbAddBeout(coneBefig->BEOUT,namealloc(brancheName),abl);

         user=getptype(path->USER,ABL_PTR);
            if(user!=NULL) user->DATA=(void*)abl;
            else path->USER=addptype(path->USER,ABL_PTR,(void*)abl);

         user=getptype(path->USER,PATH_NAME);
            if(user!=NULL) user->DATA=(void*)namealloc(brancheName);
            else path->USER=addptype(path->USER,PATH_NAME,(void*)namealloc(brancheName));

            if((path->TYPE & EXT)==EXT)
            {
            ptype_list * user;
            sprintf(brancheName,"BrHz_%d",branNum);
            abl=PathToAblHz(path);
            coneBefig->BEOUT=(beout_list *)dsbAddBeout(coneBefig->BEOUT,namealloc(brancheName),abl);
          
            user=getptype(path->USER,PATH_NAME_HZ);
               if(user==NULL) path->USER=addptype(path->USER,PATH_NAME_HZ,(void*)namealloc(brancheName));
               else user->DATA=(void*)namealloc(brancheName);

            user=getptype(path->USER,ABL_PTR_HZ);
               if(user!=NULL) user->DATA=(void*)abl;
               else path->USER=addptype(path->USER,ABL_PTR_HZ,(void*)abl);
            
            }
         }
      }

      /*------------------------------------+
      | On calcule Fup+Fdn+Fext pour la     |
      | detection de haute Impedance        |
      +------------------------------------*/
      {
      list_list* path;
      short n_path = 0 ;
      chain_list * abltot = NULL;

      abltot=createExpr(OR);
         
         for(path=ptr->PATH;path!=NULL;path=path->NEXT)
         {
            if((path->TYPE & BLEEDER)==BLEEDER) continue ;

         n_path++;
            if((path->TYPE & EXT)==EXT)
            addQExpr(abltot,copyExpr((chain_list*)getptype(path->USER,ABL_PTR_HZ)->DATA));
            else addQExpr(abltot,copyExpr((chain_list *)getptype(path->USER,ABL_PTR)->DATA));
         }
            
         if(n_path < 2)
         abltot=CADR(abltot);
     
      coneBefig->BEOUT=dsbAddBeout(coneBefig->BEOUT,(char*)namealloc("sigma"),abltot);
      }

      /*-----------------------------------*
       | On remplit le BEPOR de la BEFIG   |
       | BEPOR=BERIN+BEOUT                 |
       *-----------------------------------*/
      {
      berin_list * berin ;
      beout_list * beout ;

         for(berin=coneBefig->BERIN; berin != NULL;berin=berin->NEXT)
         coneBefig->BEPOR=beh_addbepor(coneBefig->BEPOR,berin->NAME,'I','B');

         for(beout=coneBefig->BEOUT; beout != NULL;beout=beout->NEXT)
         coneBefig->BEPOR=beh_addbepor(coneBefig->BEPOR,beout->NAME,'O','B');
      }


      /*--------------------------------------+
      | Decompilation de la beFig eventuelle  |
      +--------------------------------------*/
      if(ptr->INDEX==coneIndex)
      {
      vhdlsavebefig(coneBefig);  
      }

      /*------------------------------------------------*
       | On calcule tous les Bdd des sortie de la befig |
       | ie des branches du cone a probleme             |
       *------------------------------------------------*/
      {
      chain_list * order = NULL ;
      int test;

         if(trace!=0)
         {
         printf("makeorderAbl...\n");
         fflush(stdout);
         }

      compactBeh(coneBefig); 

         if(FCF_BDD_ORDER==2) order=anOtherMakeOrder(ptr,NULL);
         else if(FCF_BDD_ORDER==1)
         order=makeOrderAbl(coneBefig,1,0); /*mode(auto/1,appar/0),trace*/

      coneBefig->CIRCUI=initializeCct("local",2*countInputBeh(coneBefig),20);

         while(order)
         {
         addInputCct(coneBefig->CIRCUI,order->DATA);
         order=order->NEXT;
         }

         if(trace!=0)
         {
         printf("makeBddBeh...\n");
         fflush(stdout);
         }

      test=makeBddBeh(coneBefig,coneBefig->CIRCUI,0,0,10000);
      }


      /*-----------------------------------------------*
       | On range le bdd de chaque sortie de la befig  |
       | dans le USER de la branche correspondante     |
       *-----------------------------------------------*/
      {
      list_list * path = NULL ;
      beout_list * beout = NULL ; 

         for(path=ptr->PATH;path!=NULL;path=path->NEXT)
         {
         ptype_list * user;
         char *name=(char*)NULL;
         char *nameHz=(char*)NULL;

            if((path->TYPE & BLEEDER)==BLEEDER) continue ;

         user=getptype(path->USER,PATH_NAME);
            if(user==NULL)
            {
            fcfFatalError(6,"makeBefig",NULL,NULL,0);
            }
         name=(char*)user->DATA;
       
            if((path->TYPE & EXT)==EXT)
            {
            user=getptype(path->USER,PATH_NAME_HZ);
               if(user==NULL) 
               { 
               fcfFatalError(5,"makeBefig",NULL,NULL,0);
               } 
            nameHz=(char*)user->DATA;
            }
            
             /*--------------------------------------------------+
             | On scan la liste des sortie a la recherche du nom |
             | des branches                                      |
             +--------------------------------------------------*/  
            for(beout=coneBefig->BEOUT;beout != NULL;beout=beout->NEXT)
            {

               if(name==beout->NAME)
               {
               ptype_list * ures;
                  if((ures=getptype(path->USER,BDD_PTR))!=NULL)
                  ures->DATA=(void*)beout->NODE;
                  else path->USER=addptype(path->USER,BDD_PTR,(void*)beout->NODE); 
                  
                  if((path->TYPE & EXT)!=EXT) break;
               } 

              if(nameHz==beout->NAME)
              {
              ptype_list * ures;
                 if((ures=getptype(path->USER,BDD_PTR_HZ))!=NULL)
                 ures->DATA=(void*)beout->NODE;
                 else path->USER=addptype(path->USER,BDD_PTR_HZ,(void*)beout->NODE);
              } 
            }
         }
      }

return(coneBefig);
}



/****************************************************************************
 *                         fonction varInBeauxList();                   *
 ****************************************************************************/
     /*------------------------------------------------+
     | Renvoie 0 si varName est dans la Liste auxListe |
     |         1 si varName n'y est pas                |
     +------------------------------------------------*/
short varInBeauxList(varName,auxList)
char * varName;
beaux_list * auxList ;
{
beaux_list * aux ;

   for(aux=auxList ; aux != NULL; aux=aux->NEXT)
   {
      if(aux->NAME==varName) return(0) ;
   }

return(1);
}


/****************************************************************************
 *                         fonction ctrxBeOfBefig();                        *
 ****************************************************************************/
/*-------------------------------------------------------------------------+
| Renvoie la beout dont le nom correspond a celui d'une contrainte externe |
| Entree: Un pointeur dans la liste des beout de la befig                  |
| Sortie: un pointeur de beout correspondant a une contrainte              |
|         NULL l'on ne trouve pas de contrainte supp                       |
+-------------------------------------------------------------------------*/ 
beout_list * ctrxBeOfBefig(befout)
beout_list * befout;
{
beout_list * out ;
char ident[6];
short i = 0 ;
strcpy(ident,"ctrx_");

   for(out=befout;out!=NULL;out=out->NEXT)
   {
      for(i=0;(ident[i]!='\0')&&(out->NAME[i]!='\0');i++)
      {
         if(out->NAME[i] != ident[i]) break ;
      }
      if (i<strlen(ident)) continue ;
      else break ;
   }
return(out);
}


/****************************************************************************
 *                         fonction fcfBddContr();                          *
 ****************************************************************************/
pNode fcfBddContr(bdd,contr)
pNode bdd ;
pNode contr ;
{
chain_list * bddSup = NULL ;
chain_list * conSup = NULL ;
pNode res = bdd ;


bddSup=supportChain_listBdd(bdd);
conSup=supportChain_listBdd(contr);

   if(bddList1InList2(conSup,bddSup)==0)
   {
   res=constraintBdd(bdd,contr);
   }

freechain(bddSup);
freechain(conSup);
return(res);
}
   

/****************************************************************************
 *                         fonction fcfBddGarbage();                        *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Appel le Garbage Collector sur le sysytem Bdd; Sont sauvegardes tous les  |
| Bdd de la befig passee en argument, et tous les bdd associes aux branches |
| du cone que l'on veut traiter par foconf                                  |
| Entree: fig la befig associee au cone                                     |
|         cone le cone a probleme                                           |
| Sortie: Neant                                                             |
+--------------------------------------------------------------------------*/
void fcfBddGarbage(fig,cone)
cone_list  * cone ;            /* Cone a traiter par foconf */
befig_list * fig  ;            /* Befig associee            */
{
list_list  * path  = NULL    ;
beout_list * bout  = NULL    ;
chain_list * saveNode = NULL ;
chain_list * chaiNode = NULL ;

   /*--------------------------------------+
   | Sauvegarde des Bdd de la befig        |
   +--------------------------------------*/
   for(bout=fig->BEOUT;bout != NULL ;bout=bout->NEXT)
   {
   saveNode=addchain(saveNode,(void*)bout->NODE);
   }

   /*--------------------------------------------------------+
   | Sauvegarde des bdd associe aux branches : ce sont les   |
   | memes que precedemment mais c'est plus facile de sauver |
   | deux fois que de memoriser l'association branche/bdd    |
   +--------------------------------------------------------*/
   for(path=cone->PATH ; path != NULL ;path=path->NEXT)      
   {
   ptype_list * user = NULL ;

      if((path->TYPE & BLEEDER)==BLEEDER) continue;

   user=getptype(path->USER,BDD_PTR);

      if(user == NULL) 
      {
      fprintf(stdout,"ERR fcfBddGarbage branche de cone ");
      fprintf(stdout,"(%d) sans Bdd\n",cone->INDEX);
      fflush(stdout);
      exit(-1);
      }
      else saveNode=addchain(saveNode,(void*)user->DATA);

      if((path->TYPE &  EXT)==EXT) 
      {
      user=getptype(path->USER,BDD_PTR_HZ);
         if(user == NULL) 
         {
         fprintf(stdout,"ERR fcfBddGarbage branche EXT de cone ");
         fprintf(stdout,"(%d) sans Bdd\n",cone->INDEX);
         fflush(stdout);
         exit(-1);
         }
         else saveNode=addchain(saveNode,(void*)user->DATA);
      }
   }

gcNodeBdd(saveNode);
saveNode=reverse(saveNode);
chaiNode = saveNode ;

   /*---------------------------------+
   | Restauration des Bdd de la Befig |
   +---------------------------------*/
   for(bout=fig->BEOUT;bout != NULL ;bout=bout->NEXT)
   {
   bout->NODE=(pNode)chaiNode->DATA;
   chaiNode=chaiNode->NEXT;
   }

   /*---------------------------------------------------+
   | Restauration des bdd associes aux branches du cone |
   +---------------------------------------------------*/
   for(path=cone->PATH ; path !=NULL ; path=path->NEXT)
   {
   ptype_list * user = NULL  ;
      if((path->TYPE & BLEEDER)==BLEEDER) continue;
   user=getptype(path->USER,BDD_PTR);
   user->DATA=(void*)chaiNode->DATA;
   chaiNode=chaiNode->NEXT;
   
      if((path->TYPE & EXT)==EXT)
      {
      user=getptype(path->USER,BDD_PTR_HZ);
      user->DATA=(void*)chaiNode->DATA ;
      chaiNode=chaiNode->NEXT;
      }
   }
freechain(saveNode);
}


/****************************************************************************
 *                         fonction bddList1InList2();                      *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Teste l'inclusion de la chaine1 dans la chain2 ie la presence de tous les |
| NODE de la chaine1 dans les NODE de la chaine2                            |
| Entree: deux chain_list *                                                 |
| Sortie: -1 si non inclusion                                               |
|          0 si chain1 est inclue dans chain2                               |
+--------------------------------------------------------------------------*/
short bddList1InList2(chaine1,chaine2)
chain_list * chaine1 ;
chain_list * chaine2 ;
{
chain_list * chn1 ;
chain_list * chn2 ;

   for(chn1=chaine1 ; chn1 != NULL ; chn1=chn1->NEXT)
   {
      for(chn2=chaine2 ; chn2 != NULL ; chn2=chn2->NEXT)
      {
         if(((pNode)chn1->DATA)->index==((pNode)chn2->DATA)->index) break ;
      }

      if (chn2 == NULL) return(-1) ;
   }

return(0);
}


/****************************************************************************
 *                         fonction fcfContrainte();                        *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Contraint bdd par toute les contrainte presente dans la Befig Courante    |
| Un test est effectue par fcfBddContr() sur l'inclusion du suport de la    |
| contrainte dans le support du bdd a contraindre.                          |
|                                                                           |
| Entree: le bdd a contraindre                                              |
|         La tete de liste de Beout de la befig                             |
|                                                                           |
| Sortie: NULL On a depasse le seuil de nombre de noeuds                    |
|         zero Le resultat des contraintes est le bdd 'zero'                |
|         res  Le resultat des contraintes est un bdd non null              |
+--------------------------------------------------------------------------*/
pNode fcfContrainte(fig,cone,bdd,beout)
befig_list *fig ;
cone_list  *cone ;
pNode       bdd ;
beout_list *beout ;
{
int nbContr= 1 ;
beout_list * bout= NULL ;
short giveUp = 0 ;
pNode res = bdd ;


      if(bdd == zero) return(zero);

      for (bout=ctrxBeOfBefig(beout);
           (bout!=NULL)&&(nbContr <= FCF_X_CONTR);
           bout=ctrxBeOfBefig(bout->NEXT))
      {
      nbContr++;

      res=fcfBddContr(res,bout->NODE);

         if(res==zero) return(zero);

         if(cfAbandon(fig,cone) !=0)
         {
         return(NULL) ;
         }
      }   
return(res);
}



/****************************************************************************
 *                         fonction cfAbandon();                            *
 ****************************************************************************/
short cfAbandon(fig,cone)
befig_list * fig ;
cone_list  * cone;
{
short abandon=0 ;
long NbNode = 0 ;

   if((NbNode=numberNodeAllBdd())>=FCF_MAX_NODE)
   {
   printf("cfAbandon sur (%d)%s NbNode = %d\n" ,cone->INDEX,cone->NAME,NbNode );
   fflush(stdout); 

   fcfBddGarbage(fig,cone);
   NbNode=numberNodeAllBdd();

   printf("Apres Gc(); NbNode = %d\n",NbNode);
   fflush(stdout);

      if(NbNode >= FCF_MAX_NODE) abandon++;
   }
return(abandon);
}


/****************************************************************************
 *                         fonction anOtherMakeOrder;                      *
 ****************************************************************************/
static chain_list * anOtherMakeOrder(cone,order)
cone_list * cone ;
chain_list * order ;
{
list_list * in ;
chain_list * FANOUT2LIST = NULL ;
chain_list * FANOUT1LIST = NULL ;


   for(in=cone->INCONE;in!=NULL;in=in->NEXT)
   {
      if ((in->TYPE & LOOP)==LOOP) continue ;

      if((in->TYPE & EXT) == EXT) 
      {
      locon_list * conect = (locon_list*)in->DATA ;
      ptype_list * user =  getptype(conect->USER,OUTPUT_MARK);
      char * conectName = conect->NAME ;


         if ((user!=NULL) && (user->DATA == NULL))
         {
         chain_list * ptchain=NULL ;

         FANOUT2LIST = addchain(FANOUT2LIST,(void*)conectName);

            for (ptchain=order;ptchain!=NULL;ptchain=ptchain->NEXT)
               if(conectName == (char*)ptchain->DATA) break ;
            
            if(ptchain == NULL) 
            {
               if(order==NULL) order=addchain(order,(void*)conectName);
               else 
               order=append (order,addchain(NULL,(void*)conectName));
            }

           else if( (user=getptype(conect->USER,DSB_CONTRAINT))!=NULL)
           {
              if((((long)user->DATA)&PRIM)==PRIM)
              {
              chain_list * ptchain=NULL ;

              FANOUT2LIST = addchain(FANOUT2LIST,(void*)conectName);

                 for (ptchain=order;ptchain!=NULL;ptchain=ptchain->NEXT)
                    if(conectName == (char*)ptchain->DATA) break ;
            
                 if(ptchain == NULL) 
                 {
                    if(order==NULL) order=addchain(order,(void*)conectName);
                    else 
                    order=append (order,addchain(NULL,(void*)conectName));
                 }

              }
           }

         }
         else 
         FANOUT1LIST = addchain(FANOUT1LIST,(void*)conectName);
      }

      else    /* in de type CONE */
      {
      cone_list * incone = (cone_list *) in->DATA ;


         if ((incone->TYPE & FCF_PRIM)== FCF_PRIM)
         {
         char * coneName = incone->NAME ;

            if(CountOutputMark(incone) > 1) /* fanout >1 */
            {
            chain_list * ptchain=NULL ;

            FANOUT2LIST = addchain(FANOUT2LIST,(void*)coneName);

               for(ptchain=order;ptchain!=NULL;ptchain=ptchain->NEXT)
                  if(coneName==(char*)ptchain->DATA) break ;

               if(ptchain == NULL) 
               {
                  if (order==NULL) order = addchain(order,(void*)coneName);
                  else order = append(order,addchain(NULL,(void*)coneName));
               }
            }
            else FANOUT1LIST=addchain(FANOUT1LIST,(void*)coneName); 
         }
         else 
         {
         order=anOtherMakeOrder(incone,order) ;
         }
      }
   }
   /* tous les incones sont parcourus */

   if(FANOUT2LIST == NULL)
   {
   chain_list * ptr ;
   chain_list * ptr2 ;

      for ( ptr=FANOUT1LIST;ptr!=NULL;ptr=ptr->NEXT)
      {
         for(ptr2=order;ptr2!=NULL;ptr2=ptr2->NEXT)
            if(ptr2->DATA==ptr->DATA) break ;

         if(ptr2 == NULL) 
         {
            if(order==NULL) order=addchain(order,(void*)ptr->DATA);
            else order=append(order,addchain(NULL,(void*)ptr->DATA));
         }
      }
   }
   else
   {
   chain_list * ptr ;
   chain_list * ptr2 ;
   char * name = (char*)FANOUT2LIST->DATA ;

      /* on cherche le dernier in a 2 fanout dans order */
      for (ptr=order;ptr!=NULL;ptr=ptr->NEXT)
         if(name == (char*)ptr->DATA) break ;


      for(ptr2 = FANOUT1LIST ; ptr2 != NULL ; ptr2=ptr2->NEXT)
      {
      chain_list * ptr3 ;

         for(ptr3=order;ptr3!=NULL;ptr3=ptr3->NEXT)
            if(ptr3->DATA == ptr2->DATA) break ;

         if(ptr3 == NULL)
         {
         chain_list * save = ptr->NEXT ;
         ptr->NEXT=addchain(NULL,(void*)ptr2->DATA);
         ptr->NEXT->NEXT=save ;
         }
      }
   freechain(FANOUT2LIST);
   }

   if(FANOUT1LIST != NULL)
   freechain(FANOUT1LIST);

return(order);
}
          
   
/****************************************************************************
 *                         fonction affOrder();                             *
 ****************************************************************************/
static void affOrder(order)
chain_list * order ;
{
chain_list * chain ;

printf("--- ORDER ---\n");
fflush(stdout);

   for(chain=order;chain!=NULL;chain=chain->NEXT)
   {
   printf("order : %s\n",(char*)chain->DATA);
   }
}
