/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : DESB  v2.n                                                  */
/*    Fichier : highz.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"


/****************************************************************************
 *                         fonction CountMaillon();                         *
 ****************************************************************************/
/*--------------------------------------------*/
/*    retourne 1 si le chemin externe n'est   */
/*    constitue que d'1 maillon (connecteur)  */
/*--------------------------------------------*/
short CountMaillon(path)
list_list *path;
{
link_list *last;
short i=0;

for (last=(link_list*)path->DATA ; last; last=last->NEXT) i++;
/** i=1 si un seul maillon dans le chemin path **/
return(i);
}


/****************************************************************************
 *                         fonction TypeConectOut();                        *
 ****************************************************************************/
/*---------------------------------------------*/
/** Type OUT le connecteur du chemin path s'il**/
/**  existe d'autres branches fonctionnelles  **/
/*---------------------------------------------*/
void TypeConectOut(cone,path)
cone_list *cone;
list_list *path;
{
 link_list *link;	
 locon_list *conect;
 ptype_list *user;

link=(link_list*)path->DATA;
conect=(locon_list*)link->TRANS;
user=getptype(conect->USER,EXT);
if (user == NULL) {(void)printf(" TypeConectOut USER == NULL\n"); exit(0);}
if (((cone_list*)user->DATA) != cone) 
   {
   (void)printf("CONE : %d, TypeConectOut.user->DATA != CONE \n",cone->INDEX);
   (void)fflush(stdout);
   exit(2);
   }
conect->DIRECTION  = 'O';

}


/****************************************************************************
 *                         fonction TypeBleeder();                          *
 ****************************************************************************/
/*----------------------------------------*/
/** type bleeder les branches ext dont le**/
/** connecteur est le maillon de ptdel   **/
/** ainsi que LOOP si dans INCONE        **/
/*----------------------------------------*/
void TypeBleeder(ptdel)
list_list *ptdel;
{
link_list *link;
chain_list *chain;
ptype_list *user;
cone_list *ptcone;
list_list *in, *path;
locon_list *conect;

link=(link_list*)ptdel->DATA;
conect=(locon_list*)link->TRANS;
   if ((user=getptype(conect->USER,CONE_TYPE)) != NULL) 
   {
      for(chain=(chain_list*)user->DATA; chain; chain=chain->NEXT)
      {
      ptcone=(cone_list*)chain->DATA;
         /*-----------------------------------------------+
         | on marque bleeder les paths qui doivent l'etre |
         +-----------------------------------------------*/
         for(path=ptcone->PATH; path; path=path->NEXT)
         {
            if ((path->TYPE & EXT) != EXT) continue;
            else
            {
               for(link=(link_list*)path->DATA; link->NEXT; link=link->NEXT) ;
               if ((locon_list*)link->TRANS == conect)
               {
               path->TYPE |= BLEEDER;
               }
            }
         }
      marq_incone(ptcone);
      }
   /*----------------------------+
   | raz du user conetype        |
   +----------------------------*/
   freechain(chain);
   user->DATA=NULL; 
   }
}


/****************************************************************************
 *                         fonction del_conect();                           *
 ****************************************************************************/
/*-----------------------------------------*/
/**  detruit le connecteur (maillon de    **/
/**  path) dans le champ INCONE de ptcone **/
/*-----------------------------------------*/
void del_conect(ptcone,path)
cone_list *ptcone;
list_list *path;
{
link_list *link;
list_list *in;
locon_list *conect;

link=(link_list*)path->DATA;
conect=(locon_list*)link->TRANS;

in=ptcone->INCONE;
if ((in->TYPE & EXT) == EXT) 
   {
   if ((locon_list*)in->DATA == conect)
      {
      ptcone->INCONE = in->NEXT;
      /** free((char*)in); **/
      }
   }
else
   {
   for(in=ptcone->INCONE; in; in=in->NEXT)
      {
      if ((in->NEXT->TYPE & EXT) != EXT) continue;
      else
         {
         if ((locon_list*)in->NEXT->DATA == conect)
            {
            in->NEXT = in->NEXT->NEXT;
            /** free((char*)in->NEXT); **/
            break;
            }
         } 
      }
   }

}         
         

/****************************************************************************
 *                         fonction del_other();                            *
 ****************************************************************************/
/*---------------------------------------*/
/** detruit les ptype_list BDD_INDEX et **/
/**  OUTPUT_MARK si existant            **/
/*---------------------------------------*/
void del_other(path)
list_list *path;
{
link_list *link;
locon_list *conect;

link=(link_list*)path->DATA;
conect=(locon_list*)link->TRANS;

if ((getptype(conect->USER,BDD_INDEX)) != NULL)
   conect->USER=delptype(conect->USER,BDD_INDEX);
if ((getptype(conect->USER,OUTPUT_MARK)) != NULL)
   conect->USER=delptype(conect->USER,OUTPUT_MARK);
}

/****************************************************************************
 *                         fonction fcfHz();                                *
 ****************************************************************************/
short fcfHz(bfig,ptcone)
befig_list  *bfig;
cone_list   *ptcone;
{
list_list   *path, *path_del=NULL;
pNode sigma = NULL;
int nb_path = 0 ;
pNode Term = NULL;
pNode Ctr = NULL ;
chain_list * chain = NULL;

/*-----------------------------------------------------+
| On recupere le Bdd associe a la somme de toutes les  |
| les branches du cone                                 |
+----------------------------------------------------*/
sigma=BeoutNameToBdd(CURRENT_BEFIG,namealloc("sigma"));

   for (path=ptcone->PATH; path!=NULL; path=path->NEXT)
   {

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

      if ( ((ptcone->TYPE & EXT) == EXT) && 
           ((path->TYPE   & EXT) == EXT) &&
           ((CountMaillon(path)) == 1)    ) 
      {
      path_del=path;
      continue;
      }

      if ((path->TYPE & EXT) == EXT) 
      {
      ptype_list * user;
      nb_path++; 

         if((user=getptype(path->USER,BDD_PTR_HZ))!=NULL)
         Term=(pNode)user->DATA;
         else 
         {
         printf("Hz(ext) : Branche sans Bdd associe\n");
         fflush(stdout);
         exit(-1);
         }

         if(Term==zero) nb_path--;

      continue;
      }

      if ((path->TYPE & VDD) == VDD)  
      {
      ptype_list * user;
      nb_path++;

         if((user=getptype(path->USER,BDD_PTR))!=NULL)
         Term=(pNode)user->DATA;
         else 
         {
         printf("[ERR] Hz(vdd) : Path without Bdd\n");
         fflush(stdout);
         exit(-1);
         }
        
         if(FCF_X_CONTR != 0)
         Term=fcfContrainte(bfig,ptcone,Term,bfig->BEOUT);
    
         if(Term==NULL) return(-1);

         if (Term == zero) 
         { 
         path->TYPE |= BLEEDER;
         fausse_b++;
         nb_path--;
	 continue;
         }
      continue;
      }

      if ((path->TYPE & VSS) == VSS) 
      {
      ptype_list * user;
      nb_path++;

         if((user=getptype(path->USER,BDD_PTR))!=NULL) Term=(pNode)user->DATA;
         else 
         {
         printf("[ERR] Hz(vss) : Path  without Bdd \n");
         fflush(stdout);
         exit(-1);
         }

         if(FCF_X_CONTR != 0)
         Term=fcfContrainte(bfig,ptcone,Term,bfig->BEOUT);
    
         if(Term==NULL) return(-1);

         if (Term == zero) 
         { 
         path->TYPE |= BLEEDER;
         fausse_b++;
         nb_path--;
	 continue;
         }
     }
  }
 
  if (nb_path == 0) Term=one;
  else 
  {
  Term=BeoutNameToBdd(CURRENT_BEFIG,namealloc("sigma"));
  }

   if(FCF_X_CONTR != 0)
   Term=fcfContrainte(bfig,ptcone,Term,bfig->BEOUT);
    
   if(Term==NULL) return(-1);

  if (Term == one) 
  { 
     if (path_del != NULL)    
     {
        if (nb_path > 0) 
        {
        /**Il faut typer OUT le connecteur s'il existe d'autres
           branches fonc **/
        TypeConectOut(ptcone,path_del);
        TypeBleeder(path_del); /** type bleeder les branches concernees **/
                               /** par ce connecteur **/
        del_conect(ptcone,path_del);  /** detruit le connecteur en INPUT **/ 
        del_other(path_del);          /** detruit index_bdd et output_mark **/
        del_path(ptcone,path_del);    /** On detruit la branche  **/ 
        }
        else
        {
        /*---------------------------------------------------------*
         | le connecteur est un connecteur IN                      |
         | car toutes les autres branches sont bleeder             |
         | il faut typer le connecteur en entree et changer le type|
         | de tous les maillons qui designent ce connecteur        |
         *---------------------------------------------------------*/
        locon_list * conect;
        del_other(path_del);          /** detruit index_bdd et output_mark **/
        conect=(locon_list*)((link_list*)path_del->DATA)->TRANS;
           if(conect->DIRECTION != 'I')
           {
           ((link_list*)path_del->DATA)->TYPE &= ~(INOUT|IN);
           ((link_list*)path_del->DATA)->TYPE |= (IN);
           TypeConxIn(conect,ptcone);
           }
        }
     }
  no_hz++;
  ptcone->TYPE ^= HZ;
   }
return(0);
} 

/****************************************************************************
 *                         fonction TypeConxIn();                           *
 ****************************************************************************/

     /*---------------------------------------------------------* 
      | TypeConxIn(); Surtype les connecteurs qui n'ont que des | 
      |             chemins non fonctionnel (BLEEDER)           | 
      |            entree: un pointeur de connecteur type INOUT | 
      *---------------------------------------------------------*/

void TypeConxIn(conect,cone)
locon_list * conect;
cone_list * cone;
{
ptype_list *user = NULL;
list_list  *path = NULL;
link_list  *link = NULL;

/*--------------------------------------------*
 | il faut changer la direction du connecteur |
 | et le type du maillon dans tous les cones  |
 | qui le contiennent en entree               |
 *--------------------------------------------*/

conect->DIRECTION = 'I';

user=getptype(conect->USER,CONE_TYPE);

   if (user != NULL)
   {
   /*-----------------------------------------------*
    |  pour chaque cone qui contient le connecteur  |
    |  on change le type du maillon INOUT en IN     |
    *-----------------------------------------------*/
   chain_list * pchain;

      for(pchain=(chain_list*)user->DATA; pchain!=NULL;pchain=pchain->NEXT)
      {
      cone_list * pcone;
      pcone=(cone_list*)pchain->DATA;

         for(path=pcone->PATH;path != NULL;path=path->NEXT)
         {
            if ((path->TYPE & EXT)!=EXT) continue;

            /* on va sur le dernier maillon */
            for(link=(link_list*)path->DATA;link->NEXT!=NULL;link=link->NEXT);

            if((locon_list*)link->TRANS==conect)
            {
            (link->TYPE)&=~(IN|INOUT);
            (link->TYPE)|=IN;
            }
         }
      }
   }
   else 
   {
   /* le USER CONE_TYPE est NULL */
   fcfFatalError(3,"TypeConxIn",NULL,NULL,0);
   }
    
/*----------------------------------------------------------------*
 | on supprime l'outcone correspondant au connecteur              |
 *----------------------------------------------------------------*/
cone->OUTCONE=(list_list*)rmv_list(cone->OUTCONE,(char*)conect);
}

