/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : DESB  v2.n                                                  */
/*    Fichier : alim.c                                                      */
/*                                                                          */
/*    (c) copyright 1993 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Marc LAURENTIN                        le : 27/01/1993     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include "declar.h"

/****************************************************************************
 *                         fonction get_alim();                            *
 ****************************************************************************/
void	get_alim( pt_mbkfig )
lofig_list *pt_mbkfig ;
{
locon_list    *connect= NULL ;
int            n_VDD = 0 ;
int            n_VSS = 0 ;
int            type  = 0 ;

/*------------------------------------------------*/
/*  parcours de la liste des connecteurs externes */
/*------------------------------------------------*/

   for(connect=pt_mbkfig->LOCON;connect;connect=connect->NEXT)
   {
   type = 0;
      if (connect->TYPE=='I') continue; /* connecteur interne */

      if (test_chainin(connect->NAME,NAME_VDD)==1) 
      {
      type |= VDD;
      (connect->SIG->TYPE) = VDD;
      connect->DIRECTION = 'A';
      n_VDD++;
      }

      if (test_chainin(connect->NAME,NAME_VSS)==1) 
      {
      type |= VSS;
      (connect->SIG->TYPE) = VSS; 
      connect->DIRECTION = 'A';
      n_VSS++;
      }

      if (((type & VSS)==VSS) && ((type & VDD)==VDD)) 
      {
      dsbFatalError(3,"get_alim",connect->NAME,0);
      } 
   }

   if ( n_VDD == 0 )
   {
   dsbFatalError(1,"get_alim",NULL,0);
   }

   if ( n_VSS == 0 )
   {
   dsbFatalError(2,"get_alim",NULL,0);
   }
}

/****************************************************************************
 *                         fonction get_alim_bis();                         *
 ****************************************************************************/
void	get_alim_bis( pt_mbkfig )

lofig_list *pt_mbkfig ;

{
chain_list	*ptchain 	= NULL ;
losig_list	*ptsig 		= NULL ;
int		n_VDD 		= 0 ;
int		n_VSS 		= 0 ;
int 		n_con_VSS 	= 0 ;
int 		n_con_VDD 	= 0 ;
chain_list	*pt_conchain 	= NULL ;
int		type		= 0 ;
int             nAlimErr       = 0 ;

   /* parcours de la liste des signaux */
   for ( ptsig = pt_mbkfig->LOSIG ; ptsig != NULL ; ptsig = ptsig->NEXT )
   {
      /*--------------------------------------------------*
       | cas des signaux relies aux connecteurs externes  |
       | de type vdd ou vss, detecte par get_alim();      |
       | Ils sont deja traites, on continue...            |
       *--------------------------------------------------*/
      if(ptsig->TYPE == VDD) 
      {
      n_VDD++;
      continue;
      }

      if (ptsig->TYPE == VSS)
      {
      n_VSS++;
      continue;
      }

   /*---------------------------------------------------------*
    | Les autres signaux sont testes sur la base de leurs noms |
    *---------------------------------------------------------*/
   type = 0 ;
      for ( ptchain = ptsig->NAMECHAIN ; ptchain != NULL ; ptchain = ptchain->NEXT )
      {	
         /* pour chaque alias */
         if(test_chainin(DeepestName(ptchain->DATA),NAME_VDD)==1)
         type |= VDD ;

         if(test_chainin(DeepestName(ptchain->DATA),NAME_VSS)==1)
         type |= VSS ;
      }

      if ( type != 0 ) 
      {
         if ( ( ( type & VSS ) == VSS ) && ( ( type & VDD ) == VDD ) )
         {
         nAlimErr++;
         dsbError(1,"get_alim_bis",NULL,ptsig->INDEX,NULL,0);
         }
      }
   }

   if ( n_VDD == 0 )
   dsbFatalError(4,"get_alim_bis",NULL,0);

   if ( n_VSS == 0 )
   dsbFatalError(5,"get_alim_bis",NULL,0);

   if ((n_VSS * n_VDD)==0) exit(-1);

   if(nAlimErr != 0)
   {
   char buff[200];

      if(DESB_LANG=='F')
      sprintf(buff,"[WAR] %d %s ",nAlimErr,"court-circuit(s) detetcte(s)?");

      else if (DESB_LANG == 'E')
      sprintf(buff,"[WAR] %d %s ",nAlimErr,"short-circuit(s) detected?");

   DESB_RECAP_ERR=addchain(DESB_RECAP_ERR,(void*)namealloc(buff)); 
   }


   if ( DESB_STAT_MODE >= STAT_2 )
   {
      if(DESB_LANG=='F')
      {
      ( void )fprintf(DESB_STAT_FILE, "signal(aux) VDD               : %d \n" , n_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "connecteurs VDD               : %d \n" , n_con_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "signal(aux) VSS               : %d \n" , n_VSS ) ;
      ( void )fprintf(DESB_STAT_FILE, "connecteurs VSS               : %d \n" , n_con_VSS ) ;
      }
      else if(DESB_LANG=='E')
      {
      ( void )fprintf(DESB_STAT_FILE, "VDD signal(s)                  : %d \n" , n_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "VDD connector(s)               : %d \n" , n_con_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "VSS signal(s)                  : %d \n" , n_VSS ) ;
      ( void )fprintf(DESB_STAT_FILE, "VSS connector(s)               : %d \n" , n_con_VSS ) ;
      }
   }
}


/****************************************************************************
 *                         fonction get_alim_ter();                         *
 ****************************************************************************/
 /*--------------------------------------------------------------------+
 | On teste si le dernier nom de l'alias le moins cheminone' comporte  |
 | la chain NAME_VDD ou NAME_VSS                                       |
 +--------------------------------------------------------------------*/
void	get_alim_ter( pt_mbkfig )

lofig_list *pt_mbkfig ;

{
chain_list	*ptchain 	= NULL ;
losig_list	*ptsig 		= NULL ;
int		n_VDD 		= 0 ;
int		n_VSS 		= 0 ;
int 		n_con_VSS 	= 0 ;
int 		n_con_VDD 	= 0 ;
chain_list	*pt_conchain 	= NULL ;
int		type		= 0 ;
int             nAlimErr       = 0 ;

   /* parcours de la liste des signaux */
   for ( ptsig = pt_mbkfig->LOSIG ; ptsig != NULL ; ptsig = ptsig->NEXT )
   {
      /*--------------------------------------------------*
       | cas des signaux relies aux connecteurs externes  |
       | de type vdd ou vss, detecte par get_alim();      |
       | Ils sont deja traites, on continue...            |
       *--------------------------------------------------*/
      if(ptsig->TYPE == VDD) 
      {
      n_VDD++;
      continue;
      }

      if (ptsig->TYPE == VSS)
      {
      n_VSS++;
      continue;
      }

   /*---------------------------------------------------------*
    | Les autres signaux sont testes sur la base de leurs noms |
    *---------------------------------------------------------*/
   type = 0 ;
      if(test_chainin(DeepestName(get_name(ptsig)),NAME_VDD)==1)
      type |= VDD ;

      if(test_chainin(DeepestName(get_name(ptsig)),NAME_VSS)==1)
      type |= VSS ;

      if ( type != 0 ) 
      {
         if ( ( ( type & VSS ) == VSS ) && ( ( type & VDD ) == VDD ) )
         {
         nAlimErr++;
         dsbError(1,"get_alim_ter",NULL,ptsig->INDEX,NULL,0);
         }

         if ( type == VSS )
         {
         ptsig->TYPE = VSS ;
            for ( pt_conchain = ( chain_list* )getptype( ptsig->USER , LOFIGCHAIN )->DATA ;
            pt_conchain != NULL ;
            pt_conchain = pt_conchain->NEXT )
            {
            locon_list * locon =(locon_list*)pt_conchain->DATA;
            locon->DIRECTION='A';
            n_con_VSS ++ ;
            }

         }   

         if ( type == VDD )
         {
         ptsig->TYPE = VDD ;
            for ( pt_conchain = ( chain_list* )getptype( ptsig->USER , LOFIGCHAIN )->DATA ;
            pt_conchain != NULL ;
            pt_conchain = pt_conchain->NEXT )
            {
            locon_list * locon =(locon_list*)pt_conchain->DATA;
            locon->DIRECTION='A';
            n_con_VDD ++ ;
            }
         }
      }
   }

   if ( n_VDD == 0 )
   dsbFatalError(4,"get_alim_ter",NULL,0);

   if ( n_VSS == 0 )
   dsbFatalError(5,"get_alim_ter",NULL,0);

   if ((n_VSS * n_VDD)==0) exit(-1);

   if(nAlimErr != 0)
   {
   char buff[200];

      if(DESB_LANG=='F')
      sprintf(buff,"[WAR] %d %s ",nAlimErr,"court-circuit(s) detetcte(s)?");

      else if (DESB_LANG == 'E')
      sprintf(buff,"[WAR] %d %s ",nAlimErr,"short-circuit(s) detected?");

   DESB_RECAP_ERR=addchain(DESB_RECAP_ERR,(void*)namealloc(buff)); 
   }


   if ( DESB_STAT_MODE >= STAT_2 )
   {
      if(DESB_LANG=='F')
      {
      ( void )fprintf(DESB_STAT_FILE, "signal(aux) VDD               : %d \n" , n_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "connecteurs VDD               : %d \n" , n_con_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "signal(aux) VSS               : %d \n" , n_VSS ) ;
      ( void )fprintf(DESB_STAT_FILE, "connecteurs VSS               : %d \n" , n_con_VSS ) ;
      }
      else if(DESB_LANG=='E')
      {
      ( void )fprintf(DESB_STAT_FILE, "VDD signal(s)                  : %d \n" , n_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "VDD connector(s)               : %d \n" , n_con_VDD ) ;
      ( void )fprintf(DESB_STAT_FILE, "VSS signal(s)                  : %d \n" , n_VSS ) ;
      ( void )fprintf(DESB_STAT_FILE, "VSS connector(s)               : %d \n" , n_con_VSS ) ;
      }
   }
}



/****************************************************************************

/****************************************************************************
 *                         fonction test_transp();                          *
 ****************************************************************************/
                    /*----------------------------*
                     | marquage des transparences | 
                     *----------------------------*/

void test_transp( pt_mbkfig )
lofig_list	*pt_mbkfig ;
{
locon_list	*pt_con = NULL ;
chain_list	*pt_conchain = NULL ;

for ( pt_con = pt_mbkfig->LOCON ; pt_con != NULL ; pt_con = pt_con->NEXT )
	{
        if (pt_con->DIRECTION=='A') continue ; 
	/* pour chaque connecteur externe */
	for ( pt_conchain = ( chain_list * )getptype( pt_con->SIG->USER , LOFIGCHAIN )->DATA ;
			pt_conchain != NULL ;
			pt_conchain = pt_conchain->NEXT )
		{
		/* pour chaque connecteur qui lui est relie */
  
		if ( ( ( ( locon_list * )pt_conchain->DATA )->TYPE != 'E' )
			&& ( ( ( locon_list * )pt_conchain->DATA )->TYPE != 'X' ) )
			{
			/* ce n'est pas une transparence */
                        
			break ;
			}
		}
	if ( pt_conchain == NULL )
		{
		/* c'est une transparence : on marque le connecteur et le signal */
		pt_con->TYPE = 'X' ;
		pt_con->DIRECTION = 'T' ;
		pt_con->SIG->TYPE = 'T' ;
		}
	}
}


/****************************************************************************
 *                         fonction DeepestName();                          *
 ****************************************************************************/
/*-----------------------------------------------------+
 | Retourne la chaine de caractere qui suit le dernier |
 | separateur de cheminom d'un nom                     |
 | Ou la chaine elle meme si elle ne comporte aucun    |
 | cheminom                                            |
 +-----------------------------------------------------*/
char * DeepestName(nom)
char * nom;
{
char * courant;
   for(courant=nom ; courant != NULL ; courant=NextCheminom(courant) )
      if (NextCheminom(courant)==NULL) return(courant);
}


/****************************************************************************
 *                         fonction NextCheminom();                         *
 ****************************************************************************/
static char *NextCheminom(nom)
char * nom;
{
char * courant;
   for(courant=nom; *courant != '\0' ; courant++)
      if (*courant == SEPAR)
      {
      courant++;
         if(*courant != '\0')
         return(courant);
         else return(NULL);
      }
return(NULL);
}


