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


long TRANS_ISOL = 0 ;


/****************************************************************************
 *                         fonction trans_paral();                          *
 ****************************************************************************/
               /*----------------------------------------*/
               /* detection des transistors en parallele */
               /*----------------------------------------*/
int		trans_paral( pt_mbkfig , pt_trans )

lofig_list	*pt_mbkfig ;
trans_list	*pt_trans ;

{
locon_list	*pt_con 	= NULL ;
trans_list	*pt2_trans 	= NULL ;
chain_list	*pt_chain 	= NULL ;
int 		n_parallele = 0 ;


/* parcours de tous les connecteurs relies a la grille */
   for ( pt_chain = ( chain_list * )getptype( pt_trans->GRID->SIG->USER , LOFIGCHAIN )->DATA ;
   pt_chain != NULL ;
   pt_chain = pt_chain->NEXT )
   {
   pt_con = ( locon_list * )pt_chain->DATA ;
      if ( ( pt_con->NAME == NAME_GRID ) 
      && ( pt_con->TYPE == 'T' )
      && ( pt_con->ROOT != ( void * )pt_trans ) )
      {
      /* on a trouve une autre grille de transistor relie au meme signal */
      pt2_trans = ( trans_list * )pt_con->ROOT ; 
         if ( ( pt2_trans->DRAIN->SIG == pt_trans->DRAIN->SIG )
         && ( pt2_trans->TYPE == pt_trans->TYPE ) 
         && ( pt2_trans->SOURCE->SIG == pt_trans->SOURCE->SIG ) )
         {
         /* transistors montes en parallele */ 
         break ;
         }
         if ( ( pt2_trans->SOURCE->SIG == pt_trans->DRAIN->SIG )
         && ( pt2_trans->TYPE == pt_trans->TYPE ) 
         && ( pt2_trans->DRAIN->SIG == pt_trans->SOURCE->SIG ) )
         {
         /* transistors montes en parallele : on en detruit un */ 
         break ;
         }
      }
   }
   if ( pt_chain != NULL )
   {
   /* transistors montes en parallele */ 
   n_parallele = 1 ;
   clean_trans( pt_mbkfig , pt_trans , pt2_trans ) ;
   }
   else
   {
   /* ce n'est pas un transistor en parallele */
   }
return( n_parallele ) ;
}


/****************************************************************************
 *                         fonction clean_trans();                          *
 ****************************************************************************/
       /*--------------------------------------------------*/
        /* on detruit un des deux transistors en parallele */
        /*-------------------------------------------------*/
void 	clean_trans( pt_mbkfig , pt_trans , pt2_trans )

lofig_list	*pt_mbkfig ;
trans_list	*pt_trans ;
trans_list	*pt2_trans ;

{
ptype_list	*pt_user = NULL ;


/* on modifie les caracteristiques du transistor non elimine */
pt2_trans->WIDTH += pt_trans->WIDTH * ( pt2_trans->LENGTH / pt_trans->LENGTH ) ;
pt2_trans->X += pt_trans->X ;
pt2_trans->X /= 2 ;
pt2_trans->Y += pt_trans->Y ;
pt2_trans->Y /= 2 ;

/* on nettoye la liste des connecteurs relies au signal de drain */
pt_user = getptype( pt_trans->DRAIN->SIG->USER , LOFIGCHAIN ) ;
pt_user->DATA  = ( void * )rmchain( ( chain_list * )pt_user->DATA , ( char * )pt_trans->DRAIN ) ;


/* on nettoye la liste des connecteurs relies au signal de source */
pt_user = getptype( pt_trans->SOURCE->SIG->USER , LOFIGCHAIN ) ;
pt_user->DATA  = ( void * )rmchain( ( chain_list * )pt_user->DATA , ( char * )pt_trans->SOURCE ) ;


/* on nettoye la liste des connecteurs relies au signal de grille */
pt_user = getptype( pt_trans->GRID->SIG->USER , LOFIGCHAIN ) ;
pt_user->DATA  = ( void * )rmchain( ( chain_list * )pt_user->DATA , ( char * )pt_trans->GRID ) ;

/* on detruit le transistor */
/*
dellotrs( pt_mbkfig , pt_trans ) ;
*/
}


/****************************************************************************
 *                         fonction test_resist();                          *
 ****************************************************************************/
       /* detection des transistors montes en parallele */
int	test_resist( pt_trans )
trans_list	*pt_trans ;
{
int	n_resist = 0 ;


/*-------------------------------------------+
|  test si transistor N monte en resistance  |
+-------------------------------------------*/
   if ( ( pt_trans->TYPE == TN ) && ( pt_trans->GRID->SIG->TYPE == VDD ) )
   {
   dsbWarning(4,"test_resist","N",(char*)pt_trans,0);
   pt_trans->TYPE |= RESIST ;
   n_resist ++ ;
   }

/*-------------------------------------------+
|  test si transistor P monte en resistance  |
+-------------------------------------------*/
   else if ( ( pt_trans->TYPE == TP ) && ( pt_trans->GRID->SIG->TYPE == VSS ) )
   {
   dsbWarning(4,"test_resist","P",(char*)pt_trans,0);
   pt_trans->TYPE |= RESIST ;
   n_resist ++ ;
   }

return( n_resist ) ;
}


/****************************************************************************
 *                         fonction test_diode();                           *
 ****************************************************************************/
          /* detection des transistors monte en diode */

int 	test_diode( pt_trans ) 
trans_list	*pt_trans ;
{
int 	n_diode = 0 ;


   if ( ( pt_trans->GRID->SIG == pt_trans->DRAIN->SIG ) 
   && ( pt_trans->GRID->SIG->TYPE != VDD ) 
   && ( pt_trans->GRID->SIG->TYPE != VSS ) )
   {
   dsbWarning(5,"test_diode",NULL,(char*)pt_trans,0);
   pt_trans->TYPE |= DIODE ;
   n_diode ++ ;
   }


   if ( ( pt_trans->GRID->SIG == pt_trans->SOURCE->SIG )
   && ( pt_trans->GRID->SIG->TYPE != VDD ) 
   && ( pt_trans->GRID->SIG->TYPE != VSS ) )
   {
   dsbWarning(5,"test_diode",NULL,(char*)pt_trans,0);
   pt_trans->TYPE |= DIODE ;
   n_diode ++ ;
   }

return( n_diode ) ;
}


/****************************************************************************
 *                         fonction test_tr_bloque();                       *
 ****************************************************************************/
                  /* detection des transistors bloques */
int	test_tr_bloque( pt_trans )
trans_list	*pt_trans ;
{
int 	n_tr_bloque = 0 ;


/* test si transistor P bloque */
if ( ( pt_trans->TYPE == TP ) && ( pt_trans->GRID->SIG->TYPE == VDD ) )
	{
        dsbWarning(6,"test_tr_bloque","P",(char*)pt_trans,0);
	n_tr_bloque ++ ;
	}

/* test si transistor N bloque */
else if ( ( pt_trans->TYPE == TN ) && ( pt_trans->GRID->SIG->TYPE == VSS ) )
	{
        dsbWarning(6,"test_tr_bloque","N",(char*)pt_trans,0);
	n_tr_bloque ++ ;
	}

return( n_tr_bloque ) ;
}

/*****************************************************************************/
/* detection des transistors montes en capacite */

int 	test_capa( pt_trans )

trans_list	*pt_trans ;

{
int 	n_capa = 0 ;


/* test si transistor monte en capa */
if ( pt_trans->DRAIN->SIG == pt_trans->SOURCE->SIG )
	{
        dsbWarning(7,"test_capa",NULL,(char*)pt_trans,0);
	pt_trans->TYPE |= CAPACITE ;
	n_capa ++ ;
	}
return( n_capa ) ;
}


/****************************************************************************
 *                         fonction test_trans();                            *
 ****************************************************************************/

void	test_trans( pt_mbkfig )

lofig_list	*pt_mbkfig ;

{
trans_list	*pt_trans = NULL ;
trans_list	*pt_prevtrans = NULL ;
long 	n_parallele = 0L ;
long 	n_diode 	= 0L ;
long 	n_capa 		= 0L ;
long 	n_resist	= 0L ;
long 	n_bloque	= 0L ;
long 	n_isole		= 0L ;

 
/* parcours de la liste des transistors de la figure MBK */
   for ( pt_trans = pt_prevtrans = pt_mbkfig->LOTRS ;
     pt_trans != NULL ;
     pt_prevtrans = pt_trans , pt_trans = pt_trans->NEXT )
   {
   /* transformation du type MBK en type DESB */
      if ( pt_trans->TYPE == TRANSN )
      pt_trans->TYPE = TN ;
      else if ( pt_trans->TYPE == TRANSP )
      pt_trans->TYPE = TP ;

   

   /* test si patte en l'air */
   n_isole += trans_isole( pt_trans ) ;

   /* test si transistor monte en resistance */
   n_resist += test_resist( pt_trans ) ;

   /* test si transistor bloque */
   n_bloque += test_tr_bloque( pt_trans ) ;

   /* test si transistor monte en diode */
   n_diode += test_diode( pt_trans ) ;

   /* test si transistor monte en capa */
   n_capa += test_capa( pt_trans ) ;

   /* test si transistor monte en parallele */

   /*-----------------------------------------
   ON NE TESTE PLUS LES TRANSISTORS EN PARALLELE 
   --------------------------------------------
      if ( trans_paral( pt_mbkfig , pt_trans ) == 1 )
      {
      n_parallele ++ ;
         if ( pt_trans == pt_mbkfig->LOTRS )
         {
         pt_mbkfig->LOTRS = pt_trans->NEXT ;
         }
         else
         {
         }
      pt_prevtrans->NEXT = pt_trans->NEXT ;
      free( pt_trans->GRID ) ;
      free( pt_trans->SOURCE ) ;
      free( pt_trans->DRAIN ) ;
      free( pt_trans ) ;
      pt_trans = pt_prevtrans ;
      }
    ----------------------------------*/
   }

   /*-----------------------------+
   | compte rendu sortie standart |
   +-----------------------------*/
   if(n_resist != 0)
   {
   char buff[200];

    dsbCrendu(4,NULL,NULL,n_resist);
   }

   if ( n_isole > 0 )
   {
   dsbCrendu(8,NULL,NULL,n_isole);
   }

   if ( n_bloque > 0 )
   { 
   dsbCrendu(6,NULL,NULL,n_bloque);
   }

   if ( n_capa > 0 )
   { 
   dsbCrendu(7,NULL,NULL,n_capa);
   }
if ( DESB_STAT_MODE >= STAT_2 )
	{
	( void )fprintf(DESB_STAT_FILE,"transistors en parallele      : %ld \n" , n_parallele ) ;
	( void )fprintf(DESB_STAT_FILE, "transistors en diode          : %ld \n" , n_diode ) ;
	( void )fprintf(DESB_STAT_FILE, "transistors en capacite       : %ld \n" , n_capa ) ;
	( void )fprintf(DESB_STAT_FILE, "transistors en resistance     : %ld \n" , n_resist ) ;
	( void )fprintf(DESB_STAT_FILE, "transistors bloques           : %ld \n" , n_bloque ) ;
	}
}


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

int trans_isole( pt_trans )

trans_list	*pt_trans ;

{
locon_list	*pt_con 	= NULL ;
chain_list	*pt_chain 	= NULL ;
int			n_isole 	= 0	   ;


/* parcours de tous les connecteurs relies a la grille */
for ( pt_chain = ( chain_list * )getptype( pt_trans->GRID->SIG->USER , LOFIGCHAIN )->DATA ;
	pt_chain != NULL ;
	pt_chain = pt_chain->NEXT )
	{
	pt_con = ( locon_list * )pt_chain->DATA ;
	if ( pt_con != pt_trans->GRID )
		{
		/* on a trouve un autre connecteur relie au meme signal */
			break ;
		}
	}
if( ( pt_chain == NULL ) && ( pt_con == pt_trans->GRID ) )
	{
	/* grille en l'air */ 
	n_isole = 1 ;
        dsbError(5,"trans_isole","Gate",pt_trans->X,NULL,pt_trans->Y,0);
	}


/* parcours de tous les connecteurs relies a la source */
if( ( pt_trans->SOURCE->SIG->TYPE != VDD ) 
	&& ( pt_trans->SOURCE->SIG->TYPE != VSS ) )
	{
	for ( pt_chain = ( chain_list * )getptype( pt_trans->SOURCE->SIG->USER , LOFIGCHAIN )->DATA ;
			pt_chain != NULL ;
			pt_chain = pt_chain->NEXT )
		{
		pt_con = ( locon_list * )pt_chain->DATA ;
		if ( pt_con != pt_trans->SOURCE )
			{
			/* on a trouve un autre connecteur relie au meme signal */
				break ;
			}
		}
	if( pt_chain == NULL ) 
		{
		/* source en l'air */ 
		n_isole = 1 ;
                dsbWarning(8,"trans_isole","Source",(char*)pt_trans,0);
		}
	}



/* parcours de tous les connecteurs relies au drain */
if( ( pt_trans->DRAIN->SIG->TYPE != VDD ) 
	&& ( pt_trans->DRAIN->SIG->TYPE != VSS ) )
	{
	for ( pt_chain = ( chain_list * )getptype( pt_trans->DRAIN->SIG->USER , LOFIGCHAIN )->DATA ;
		pt_chain != NULL ;
		pt_chain = pt_chain->NEXT )
		{
		pt_con = ( locon_list * )pt_chain->DATA ;
		if ( pt_con != pt_trans->DRAIN )
			{
			/* on a trouve un autre connecteur relie au meme signal */
				break ;
			}
		}
	if( ( pt_chain == NULL ) && ( pt_con == pt_trans->DRAIN ) )
		{
		/* drain en l'air */ 
		n_isole = 1 ;
                dsbWarning(8,"trans_isole","Drain",(char*)pt_trans,0);
		}
	}

return( n_isole ) ;
}


/****************************************************************************
 *                         fonction util_trans();                           *
 ****************************************************************************/
/*-----------------------------------------------* 
 | util_trans: teste que tous les transistors    | 
 | servent a moins qu'ils ne soient dans une     | 
 | branche bloquee                               | 
 *-----------------------------------------------*/
void util_trans(pthead)
trans_list * pthead;
{
trans_list * ptmos = NULL ;
ptype_list * ptuser = NULL;
long         n_trans = 0 ;
long         n_utiltrans = 0 ;
long         n_bltrans   = 0 ;

   for (ptmos = pthead;ptmos;ptmos=ptmos->NEXT)
   {
   n_trans++;
      if ((ptmos->TYPE & USED ) == USED) n_utiltrans++;
      else
      {
         if((ptmos->TYPE & IN_CH_BL)==IN_CH_BL) 
         {
         n_bltrans ++;
         }
         else
         {
            if ((ptmos->TYPE & TP)==TP)
            {
            dsbWarning(9,"util_trans","P",(char*)ptmos,0);  
            }

            if ((ptmos->TYPE & TN)==TN)
            {
            dsbWarning(9,"util_trans","N",(char*)ptmos,0);  
            }
         }
      }
   }

   if ( n_trans > (n_utiltrans + n_bltrans ))
   {
   dsbCrendu(9,NULL,NULL,(n_trans-n_utiltrans));
   }
}

