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

chain_list *SIG_CHAIN = NULL ;

/****************************************************************************
 *                         fonction make_path();                            *
 ****************************************************************************/
list_list 	*make_path( pt_cone , ptsig , autoref, mxmail,poid_s)

cone_list	*pt_cone ;
losig_list	*ptsig ;
int             *autoref;
int             *mxmail;
int             *poid_s;
{
chain_list	*ptchain     = NULL ;
chain_list	*pt2_chain   = NULL ;
list_list	*pt_list     = NULL ;
list_list	*pt_path     = NULL ;
list_list	*result_path = NULL ;
locon_list	*ptcon       = NULL ;
losig_list	*pt_nextsig  = NULL ;
trans_list 	*pt_trans    = NULL ;
link_list	*pt_link	 = NULL ;
long 		type 		 = 0 ;
long		capa 		 = 0 ;
short actual_s  =0;
short next_s = 0;

NB_MAIL++;
   if ( NB_MAIL > (DESB_MAIL_MAX + 1) )
   { 
   NB_MAIL--;
   (*mxmail)++ ;
   return(NULL);
   }

/* calcul de la capacite */
	capa = (ptsig->CAPA)*(1000.0);


/*----------------------------------------------------------------------------*
 | Parcours des connecteurs relies au signal                                  |
 *----------------------------------------------------------------------------*/

   for ( ptchain = ( chain_list * )getptype( ptsig->USER , LOFIGCHAIN )->DATA ;
      ptchain != NULL ;
      ptchain = ptchain->NEXT )
   { 	
   /* pour chaque connecteur relie au signal en entree */
   pt_link = NULL ;
   pt_path = NULL ;
   ptcon = ( locon_list * )ptchain->DATA ;

      /*-------------------+
      | Connecteur EXTERNE |
      +-------------------*/
      if ( ptcon->TYPE == 'E' )
      {	
      /*si ce connecteur est externe , on rajoute un chemin avec un seul maillon */
         switch( ptcon->DIRECTION )
         {
            case 'I' :
            {
            type = IN ;
            break ;
            }
            case 'X' :
            {
            type = INOUT ;
            break ;
            }
            case 'O' :
            {
            type = IN | INOUT ;
            break ;
            }
            default :
            {
            type = INOUT ;
            ptcon->DIRECTION='X';
            break ;
            }
         }
      pt_link = add_link( pt_link , type , ( char * )ptcon , capa );
      result_path = add_list( result_path , ( char * )pt_link , ( long )EXT ) ;
      }	

      /*--------------------------+
      | Connecteur de transistor  |
      |--------------------------*/
      else if ( ptcon->TYPE == 'T' )
      {
      pt_trans = ( trans_list * )(ptcon->ROOT) ;

        /* on teste l'autoreferentialite */
         for(pt2_chain=SIG_CHAIN;pt2_chain;pt2_chain=pt2_chain->NEXT)
         {
            if (pt2_chain->DATA==(void*)(pt_trans->GRID->SIG))
            break;
         }
         if (pt2_chain!=NULL)
         /* le signal de grille du transistor que l'on veut
            traverser a deja ete rencontre */
         {
         (*autoref)++ ;
         continue; 
         }

         /* on determine le prochain signal a etudier */
         if ( ptcon->NAME == NAME_SOURCE )
         {
         /* si c'est une source */ 
         pt_nextsig = pt_trans->DRAIN->SIG ;
         }
         else if ( ptcon->NAME == NAME_DRAIN )
         {
         /* si c'est un drain */ 
         pt_nextsig = pt_trans->SOURCE->SIG ;
         }
         else if ( ptcon->NAME == NAME_GRID )
         {
         /* sinon c'est une grille : on passe au connecteur suivant */
         continue ;
         }
         else 
         {
         dsbFatalError(6,"make_path",NULL,0);
         }

         /*---------------------------------------+
         | On teste si nextSig est un point Latch |
         +---------------------------------------*/
         if ((DSB_HELP_L != 0)&&(test_l(pt_nextsig)!=0))
         {
         continue; 
         }

         /*------------------------------------*
         | le prochain signal est suffixe _s   |
         *-------------------------------------*/
         if ((DSB_HELP_S !=0)&&((next_s=test_si_sig(pt_nextsig)) >= 0 ))
         {
            if ( ((DSB_HELP_L !=0)&&(test_l(ptsig) == 0)) ||
                  (DSB_HELP_L == 0) )
            {
               /*---------------------------------------------+
               | si un _l est trouve sur le signal precedent  |
               | les considerarions sur les _s sont ignorees  |
               +---------------------------------------------*/
               if((actual_s=test_si_sig(ptsig)) < 0) continue ;
               if(actual_s > next_s) continue ;
               if(actual_s == next_s) 
               {
               (*poid_s)++;
               dsbError(2,"make_path",get_name(ptsig),0,get_name(pt_nextsig),0);
               }
            }
         }

         for ( pt2_chain = SIG_CHAIN ; pt2_chain != NULL ; pt2_chain = pt2_chain->NEXT ) 
         {
         /* on verifie que le nouveau signal n'a pas deja ete etudie */
            if ( pt2_chain->DATA == ( void * )pt_nextsig )
            {
            break ;
            }
         }

         if ( pt2_chain != NULL ) 
         {
         /* si le signal relie a la source a deja ete etudie
            on passe au connecteur suivant */
         continue ;
         }

         else if ( ( pt_nextsig->TYPE == VDD ) || ( pt_nextsig->TYPE == VSS ) )
         {
         /* si le signal relie a la source est une alimentation on rajoute un chemin avec un seul maillon */
         type = pt_trans->TYPE ;
         pt_link = add_link( pt_link , type , ( char * )pt_trans , capa ) ;
         result_path = add_list( result_path , ( char * )pt_link , ( long )pt_nextsig->TYPE ) ;
         }

         else
         {
         /* sinon on appelle make_path recursivement avec le nouveau signal */
         SIG_CHAIN = addchain( SIG_CHAIN , ( void * )ptsig ) ;
         pt_path = make_path( pt_cone , pt_nextsig , autoref,mxmail,poid_s) ;			
            for ( pt_list = pt_path ; pt_list != NULL ; pt_list = pt_list->NEXT )
            {
               /* a chaque chemin obtenu on rajoute un maillon */
            pt_list->DATA 
            = ( char * )(add_link(  ( link_list *)( pt_list->DATA ) , ( long )pt_trans->TYPE , ( char * )pt_trans , capa )) ; 
            }
         result_path = append_list( result_path , pt_path ) ; 
         SIG_CHAIN = delchain( SIG_CHAIN , SIG_CHAIN ) ;
         }
      }
      else
      {
      dsbFatalError(6,"make_path",NULL,0);
      }
   }
NB_MAIL--;
return( result_path ) ;
}

