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

chain_list * FCF_PRIM_INDEX =NULL ; /* chainlist pour le calcul de la sign */

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
               /*------------------------------------+
               |     Compte le nombre d'output       |
               |     marque de cone                  |
               +------------------------------------*/
short CountOutputMark(cone)
cone_list *cone;
{
list_list *out;
short output_mark=0;

for (out=cone->OUTCONE; out; out=out->NEXT) 
    {
    if ((getptype(out->USER,OUTPUT_MARK)) != NULL ) output_mark++;
    }
return(output_mark);
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
               /*------------------------------------+
               |     Compte le nombre d'input        |
               |     marque de cone                  |
               +------------------------------------*/
short CountInputMark(cone)
cone_list *cone;
{
list_list *in;
short input_mark=0;

for (in=cone->INCONE; in; in=in->NEXT) 
    {
    if ((getptype(in->USER,INPUT_MARK)) != NULL ) input_mark++;
    }
return(input_mark);
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
                /*------------------------------------+
                |    Marque l'entree du cone source   |
                |      pointant vers dest             | 
                +------------------------------------*/
void MarqInput(source_cone,dest_cone)
cone_list *source_cone, *dest_cone;
{
list_list *in;

in=source_cone->INCONE;
   
while (((cone_list*)in->DATA) != dest_cone) in=in->NEXT;
  
if ((getptype(in->USER,INPUT_MARK)) == NULL)
   in->USER=addptype(in->USER,INPUT_MARK,(void*)NULL);
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
void AddPrimConect(conx)
locon_list *conx;
{ 

if ((getptype(conx->USER,BDD_INDEX)) == NULL) 
   {
   conx->USER=addptype(conx->USER,BDD_INDEX,(void*)((long)index_bdd));
   index_bdd++;
   }

}

/****************************************************************************
 *                         fonction AddPrimVar();                           *
 ****************************************************************************/
void AddPrimVar(cone)
cone_list *cone;
{ 

/*------------------------------------------------------+
| ON enrichit la liste des variables primaires par ordre |
| d'index de cone croissant                             |
+------------------------------------------------------*/
fcfAddPrimCone(cone);
cone->TYPE |= FCF_PRIM ;
/*-------------------------------------------------------------+
| On range le nom du cone dans la liste des entree de la befig |
+-------------------------------------------------------------*/
CURRENT_BEFIG->BERIN=dsbAddBerin(CURRENT_BEFIG->BERIN,cone->NAME);
}
   

/****************************************************************************
 *                         fonction AddPrimVarNotMark();                    *
 ****************************************************************************/
void AddPrimVarNotMark(cone)
cone_list *cone;
{
cone_list *in_cone;
locon_list *conect;
list_list *in;

   for (in=cone->INCONE; in; in=in->NEXT)
   {
      if ((in->TYPE & LOOP) == LOOP) continue;
      if ((getptype(in->USER,INPUT_MARK)) == NULL)
      {
         if ((in->TYPE & EXT) == EXT)
         {
         conect=(locon_list*)in->DATA;

         fcfAddPrimConect(conect);

         CURRENT_BEFIG->BERIN=dsbAddBerin(CURRENT_BEFIG->BERIN,conect->NAME);
         }

         else
         {
         AddPrimVar((cone_list*)in->DATA);
         }
      }
   }

}


/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/

/*************************************/
/** Retourne PRIM s'il existe un    **/
/** connecteur  contraint primaire  **/ 
/**  dans le champ INCONE de `cone` **/
/*************************************/
long FindConectPrim(cone)
cone_list *cone;
{
list_list  *in;
locon_list *conect;
ptype_list *user;

for (in=cone->INCONE; in; in=in->NEXT) 
    {

    if ((in->TYPE & EXT) == EXT) 
       {
       conect=(locon_list*)in->DATA;
       if ((user=getptype(conect->USER,DSB_CONTRAINT)) != NULL)
          if ((((long)user->DATA) & PRIM) == PRIM) return(PRIM);
       }
    }
return((long)0);
}     


/****************************************************************************
 *                         fonction PropStep();                             *
 ****************************************************************************/
    /*------------------------------------------------------------------*
    | Assure la deuxiemme propagation et detecte les variables primaires|
    | Chacune d'entre elles sont stockee en BERIN de la figure courante |
    | Les variables d'un cone situe sur le chemin du cone conflict vers |
    | une variable primaire sont stokee en BEAUX                        |
    | Chacune des variables auxiliaire implique la creation d'un abl    |
    | decrivant leur fonctionnalite                                     |
    *------------------------------------------------------------------*/
short PropStep(cone,deep)
cone_list *cone;
int deep ;
{
list_list *input;
ptype_list *user;
short result, prof;
chain_list * conechain;

   if ((user=getptype(cone->USER,PROF)) != NULL) prof=(short)((long)user->DATA);
   else prof=PROF_MAX;

   /* Traitement des rebouclages */
      for(conechain=FCF_CONE_LIST;conechain!=NULL;conechain=conechain->NEXT)
      {
         if(cone==(cone_list *)conechain->DATA) break ;
      }
      if (conechain != NULL) return(1) ;
      else FCF_CONE_LIST=addchain(FCF_CONE_LIST,(void *)cone) ;
   


   if (prof < PROF_MAX) 
   {

      /*---------------------------------------------------------------------*
      | Point d'arret obligatoire: on ne se propage pas au dela des cones    |
      | conflictuels dont on ne saurait exprimer la fonctionnalite correcte- |
      | ment (probabilite de fausses branches), ni des cones tristate pour   |
      | lesquel la BEFIG au 30/10/91 n'est pas adaptee                      | 
      | Pour des raisons evidentes on ne se propage pas non plus au dela des |
      | latches. Ceci n'exclut cependant pas que les variables designees par |
      | ces cones puissent quand meme etre des variables primaires, Cest la  |
      | raison pour laquelle on fait le test ci dessous                      |
      *---------------------------------------------------------------------*/
      if ((prof>=1) && (((cone->TYPE & CONFLICT) == CONFLICT) 
                          || ((cone->TYPE & HZ)==HZ) 
                          || ((cone->TYPE & LATCH) == LATCH)
                          || ((cone->TYPE & FCF_LOOP)==FCF_LOOP))) 
      {
         if (CountOutputMark(cone) >= 2) 
         {
         AddPrimVar(cone); 
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
         return(0); 
         }
         else 
         {
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
         return(1);
         }
      }

      /*------------------------------------------------------*
      | variable auxiliaire deja parcourue  et dont on a donc |
      | deja fabrique l'abl                                   |
      | On propage l'information que l'on est sur le chemin   |
      | d'un variable primaire (au dessus) par le return(0)   |
      *------------------------------------------------------*/
      if ((getptype(cone->USER,ABL_UP)) != NULL) 
      {
      FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
      return(0); 
      }

      /*-------------------------------------------------------*
      | Cas general, on rappelle recursivement la fonction sur |
      | chacune des entrees du cone                            |
      *-------------------------------------------------------*/
      for (input=(list_list*)cone->INCONE; input; input=input->NEXT) 
      {
         if (((input->TYPE) & LOOP) == LOOP) continue;

         if ((getptype(input->USER,INPUT_MARK)) != NULL) continue;

         /*----------------------------*
         | Cas des incone de type CONE |
         *----------------------------*/
         if (((input->TYPE) & EXT) != EXT )  
         {
	 result=PropStep((cone_list*)input->DATA,prof);
         
            /*-----------------------------------------*
            | On a rien trouve d'interessant au dessus |
            *-----------------------------------------*/
	    if (result == 1) continue;

            /*---------------------------------------------*
            | On est sur le chemin d'une variable primaire |
            *---------------------------------------------*/
	    else MarqInput(cone,(cone_list*)input->DATA);
	 }

         /*----------------------------------*
         | Cas de l'incone qui un connecteur |
         | On ne se propagera pas au dela    |
         *----------------------------------*/
         else
         {
            if ((user=getptype(((locon_list*)input->DATA)->USER,
                                 OUTPUT_MARK)) != NULL)
            if ((cone_list*)user->DATA == NULL)  
            {
            /* user->DATA = NULL <=> plusieurs cones y menent */
            /* c'est un point d'intersection du graphe        */

            fcfAddPrimConect((locon_list*)input->DATA);

            CURRENT_BEFIG->BERIN=dsbAddBerin(CURRENT_BEFIG->BERIN,((locon_list*)input->DATA)->NAME);
            input->USER=addptype(input->USER,INPUT_MARK,(void*)NULL);
            }
         }
      }

      /*-----------------------------------------------------*
      | TOUTES LES ENTREES ON FAIT L'OBJET D'UNE PROPAGATION |
      *-----------------------------------------------------*/

      if (prof == 0) 
      { 
      /*---------------------------------------------------*
      | On est redescendu au niveau du cone a probleme     |
      | On marque primaire toutes autres entrees du cone a |
      | probleme: Toutes celles qui ne sont par sur le     |
      | chemin d'une variable primaire                     |
      *----------------------------------------------------*/
      AddPrimVarNotMark(cone);
      FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
      return(1);
      }

      /*------------------------------------------*
      | Variable Primaire potentielle             |
      *------------------------------------------*/
      if (CountOutputMark(cone) >= 2) 
      {
         if ((CountInputMark(cone) == 0) && (FindConectPrim(cone) != PRIM))
         {
         /* C'est un variable Primaire */ 
	 AddPrimVar(cone);
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
	 return(0);
	 }
         /*-------------------------------------------------+
         |  Le cone est une intersection du graphe          |
         |  Mais il en existe une autre au dessus           |
         |  Ou un de ses connecteurs d'entree est Primaire  |
         +-------------------------------------------------*/

         /*-----------------------------------------------------*
          | Si c'est un cone connecteur, on ne rajoute pas de   |
          | Beaux, et on ne fabrique pas l'abl                  |
          *-----------------------------------------------------*/
         if(fcfConeConect(cone)==0) 
         {
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
         return(0);
         }

      AddPrimVarNotMark(cone);
      FoncCone(cone);
      CURRENT_BEFIG->BEAUX=dsbAddBeaux(CURRENT_BEFIG->BEAUX,
                           cone->NAME,
                          (chain_list*)getptype(cone->USER,ABL_UP)->DATA );
      FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
      return(0);
      }

      else 
      {
         if (CountInputMark(cone) > 0 ) 
         {
         /* Le cone est sur le chemin d'un variable Prim */
         AddPrimVarNotMark(cone);
	 FoncCone(cone);
         CURRENT_BEFIG->BEAUX=dsbAddBeaux(CURRENT_BEFIG->BEAUX,
                              cone->NAME,
                             (chain_list*)getptype(cone->USER,ABL_UP)->DATA );
      FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
	 return(0);
         }
         else 
         {
            /*-----------------------------------------------------*
             | Le cone a en entree un connecteur qui est primaire  |
             | Si c'est un cone connecteur, on ne rajoute pas de   |
             | Beaux, et on ne fabrique pas l'abl                  |
             *-----------------------------------------------------*/
            if (FindConectPrim(cone) == PRIM) 
            { 
               if((cone->TYPE & EXT)==EXT)
               {
                  if(cone->PATH->NEXT==NULL) /* cone connecteur */
                  {
                  FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
                  return(0);
                  }
               }
            AddPrimVarNotMark(cone);
            FoncCone(cone);
            CURRENT_BEFIG->BEAUX=dsbAddBeaux(CURRENT_BEFIG->BEAUX,
                           cone->NAME,
                          (chain_list*)getptype(cone->USER,ABL_UP)->DATA );
            FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
            return(0);
            }
            else 
            {
            FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
	    return(1);
            }
         }
      }
   }

   else  /* prof = PROF_MAX */
   {
      if (CountOutputMark(cone) >= 2) 
      {
      AddPrimVar(cone);
      FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
      return(0);
      }
      else 
      {
         if (FindConectPrim(cone) == PRIM) 
         { 
         AddPrimVarNotMark(cone);
         FoncCone(cone);
         CURRENT_BEFIG->BEAUX=dsbAddBeaux(CURRENT_BEFIG->BEAUX,
                              cone->NAME,
                             (chain_list*)getptype(cone->USER,ABL_UP)->DATA );
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
         return(0);
         }
         else 
         {
         FCF_CONE_LIST=FCF_CONE_LIST->NEXT;
         return(1);
         }
      }
   }
}

/****************************************************************************
 *                         fonction fcfDyspPrimList();                      *
 ****************************************************************************/
void fcfDyspPrimList()
{
chain_list *chain ;

printf("fcfDyspPrimList : \n");

   for(chain=FCF_PRIM_INDEX;chain!=NULL;chain=chain->NEXT)
   {
   printf("index = %ld \n",(long)chain->DATA); 
   fflush(stdout);
   }
}
