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


/**********************************************************************/
/*            findin_in                                               */
/* cherche dans la liste des incones d'un cone pointe par ptcone      */
/* l'un des incones pointe par le char *                              */
/* retourne 1 si trouve, 0 sinon                                      */
/**********************************************************************/
int findin_in(ptcx,type,ptcone)
char * ptcx;
long type;
cone_list * ptcone ;
{
cone_list   * incone=NULL;
locon_list  * inext=NULL;
list_list   * ptin =NULL;

   if (type == EXT) 
   inext=(locon_list*)ptcx;
   else incone=(cone_list *)ptcx;

   for ( ptin=ptcone->INCONE;ptin;ptin=ptin->NEXT)
   {
      if ( (type == EXT) && ((ptin->TYPE & EXT) == EXT ) ) 
      {
         if (  ((locon_list*)(ptin->DATA)) == inext  ) return (1);
      }
      
      if ( (type== CONE_TYPE) && ((ptin->TYPE & CONE_TYPE)==CONE_TYPE) )
      {
         if ( ((cone_list*)ptin->DATA) == incone) return (1);
      }
   }
/* incone non trouve */   
return (0);
}



/**********************************************************************/
/*      findin_mail                                                   */
/*  cherche l'input pointe par ptcx en entree des maillons du cone    */
/* pointe par ptcone                                                  */ 
/* retourne 1 si trouve, 0 sinon                                      */
/**********************************************************************/
int findin_mail(ptcx,type,ptcone)
char * ptcx;
long type;
cone_list * ptcone;
{
int res=0;
link_list * ptlink=NULL;
cone_list * incone=NULL;
locon_list * inext=NULL;
list_list * ptpath=NULL;

   if (type == CONE_TYPE)
   {
   incone=(cone_list*)ptcx;
   }
   else
   {
      if (type == INOUT)
      {
      inext=(locon_list*)ptcx;
      }
   }


   for(ptpath=ptcone->PATH;ptpath;ptpath=ptpath->NEXT)
   {
      for (ptlink=(link_list*)(ptpath->DATA);ptlink;ptlink=ptlink->NEXT)
      {
         if ( (type==CONE_TYPE)&&
              ((((ptlink->TYPE)&TN)==TN)  || (((ptlink->TYPE)&TP)==TP)) ) 
         {
            if ( (cone_list*)((trans_list*)(ptlink->TRANS)->GRID)==incone)
            {
            return(1);
            }
         }
         
         if ( (type==INOUT)&&
              (((ptlink->TYPE) & TN) == 0) &&
              (((ptlink->TYPE) & TP) == 0) )
         {
            if ( (locon_list*)(ptlink->TRANS)==inext )
            {
            return(1);
            }
         }
      }
   }
/* incone non trouve */
return(0);
}  

/****************************************************************************
 *                         fonction test_chmlat();                          *
 ****************************************************************************/
   
      /*-----------------------------------------------------------* 
       |  Detecte et marque Bleeder les branches qui passent par   |
       |              par des points latchs ou memory              |
       *-----------------------------------------------------------*/     

void test_chmlat(cone)
cone_list *cone;
{
list_list   *path  = NULL;
link_list   *link  = NULL;
lotrs_list  *trans = NULL;
losig_list  *signal= NULL;
ptype_list  *user  = NULL;
cone_list   *latch = NULL;
int         fx_chm = 0;
int         flag   = 0;

/*   if ((cone->TYPE & LATCH) == LATCH) return; */

   for(path=cone->PATH;path;path=path->NEXT)
   {
      if((path->TYPE & BLEEDER)==BLEEDER) continue;

   fx_chm=0;
   link=(link_list*)path->DATA;
      
      if(link->NEXT!=NULL) link=link->NEXT;
      else continue;
   
      for(;link;link=link->NEXT)
      {
         if (((link->TYPE & TP)!=TP)&&((link->TYPE & TN)!=TN))
         continue; /* maillon connecteur */

      trans=(lotrs_list*)link->TRANS;
      /*--------------------------------------------------*/
      /* signal de source est il un point latch ou memory */
      /*--------------------------------------------------*/
      signal=((locon_list*)trans->SOURCE)->SIG;
      user=getptype(signal->USER,(short)CONE_TYPE);
         if (user!=NULL)
         {
         latch=(cone_list*)user->DATA;
            if ((latch->TYPE & LATCH)==LATCH)
            {
            fx_chm=1;
            break;
            }
            else if ((latch->TYPE & MEMORY)==MEMORY)
            {
               if((cone->TYPE & MEMORY)==MEMORY)
               {
               fx_chm=1;
               break;
               }
            }
         }
      /*--------------------------------------------------*/
      /* signal de drain est il un point latch ou memory  */
      /*--------------------------------------------------*/
      signal=((locon_list*)trans->DRAIN)->SIG;
      user=getptype(signal->USER,(short)CONE_TYPE); 
         if (user!=NULL)
         {
         latch=(cone_list*)user->DATA;
            if ((latch->TYPE & LATCH)==LATCH) 
            {
            fx_chm=1;
            break;
            }
            else if ((latch->TYPE & MEMORY)==MEMORY)
            {
               if((cone->TYPE & MEMORY)==MEMORY)
               {
               fx_chm=1;
               break;
               }
            }
         }
      }
      
      if(fx_chm == 1)
      {
      (path->TYPE) |= BLEEDER;
      flag=1;
      }
   }

   if(flag==1)
   marq_incone(cone);
}



/****************************************************************************
 *                         fonction RefAuto();                              *
 ****************************************************************************/

/*----------------------------------------------------------------------------*
 | Supprime les branches autoreferentielles II dont les caracteristiques sont |
 | En allant du sommet vers l'alim, on trouve un signal qui attaque un        |
 | transistor que l'on a traverse                                             |
 *----------------------------------------------------------------------------*/

void RefAuto(cone)
cone_list * cone;
{
list_list  * path ;
losig_list * tabsig[20];
chain_list * pathtodel;
chain_list * chain;
short idglob;


pathtodel = NULL;


   for(path=cone->PATH;path!=NULL;path=path->NEXT)
   {
   link_list * link;
   short autoref = 0 ;
   idglob = 0 ;

      for(link=(link_list*)path->DATA;link!=NULL;link=link->NEXT)
      {
         if (((link->TYPE & TP)==TP)||((link->TYPE & TN)==TN))
         {
         short idx2 = 0;
         lotrs_list * mos = link->TRANS;
         tabsig[idglob++]=mos->GRID->SIG;

            for(idx2=0 ; idx2 < idglob ; idx2++)
            {
               if( ((mos->DRAIN->SIG==tabsig[idx2])||(mos->SOURCE->SIG==tabsig[idx2])) 
                     &&(tabsig[idx2]->TYPE != VDD)
                     &&(tabsig[idx2]->TYPE != VSS)) 
               {
               autoref++;
               pathtodel=addchain(pathtodel,(void*)path);
               break;
               }
            }  
            if(autoref!=0) break;
         }
      }
   }

   for(chain=pathtodel;chain !=NULL;chain=chain->NEXT)
   del_path(cone,(list_list*)chain->DATA);

   freechain(pathtodel);
}


/****************************************************************************
 *                         fonction test_degr();                       *
 ****************************************************************************/

void test_degr(ptcone)
cone_list * ptcone;
{
list_list * ptlist;
link_list * ptlink;
int degH = 0 ;
int degL = 0 ;

   if  ( ( (ptcone->TYPE & TNINVDD) != TNINVDD ) &&
         ( (ptcone->TYPE & TPINVSS) != TPINVSS ) )
   {
   /* pas la peine */
   return ;
   }

   for(ptlist=ptcone->PATH;ptlist;ptlist=ptlist->NEXT)
   {
      if ((ptlist->TYPE & BLEEDER)==BLEEDER) continue ;

      if ( ((ptlist->TYPE & TNINVDD)==TNINVDD) ||
           ((ptlist->TYPE & TPINVSS)==TPINVSS) )
      {
         for (ptlink=(link_list*)ptlist->DATA;ptlink;ptlink=ptlink->NEXT)
         {
         /* recherche un maillon degradant=pass&non_switch */
            if(  ( ((ptlist->TYPE & (EXT|VSS)) != 0) && 
                   ((ptlink->TYPE & TP)==TP)   &&
                   ((ptlink->TYPE & SWITCH)!=SWITCH) )
               ||( ((ptlist->TYPE & (EXT|VDD)) != 0) &&
                   ((ptlink->TYPE & TN)==TN)   &&
                   ((ptlink->TYPE & SWITCH)!=SWITCH) ) )
            {
            break;
            }
         }

         if (ptlink==NULL) 
         {
         /* en fait tous les pass sont des switchs  */
         ptlist->TYPE=(ptlist->TYPE)&(~(TNINVDD|TPINVSS));
         }
      } /* finif path degrade */
   } /* finfor path  */

/* On regarde s'il reste des path degrades */
   for (ptlist=ptcone->PATH;ptlist;ptlist=ptlist->NEXT)
   {
      if ((ptlist->TYPE & BLEEDER)==BLEEDER) continue ;
      if ((ptlist->TYPE & TNINVDD)==TNINVDD) degH++; 
      if ((ptlist->TYPE & TPINVSS)==TPINVSS) degL++;
   }

   if (degH==0) ptcone->TYPE &= ~TNINVDD;
   if (degL==0) ptcone->TYPE &= ~TPINVSS;
}
