/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : DESB  v2.n                                                  */
/*    Fichier : 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 : 04/09/1991     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include "declar.h"

#define dsb_max(a,b) 	( (a) < (b) ? (b) : (a) ) 
#define dsb_min(a,b) 	( (a) > (b) ? (b) : (a) ) 

#define _BITS_(type)	(8*(int)sizeof(type))
#define _HIL_		(1L<<_BITS_(long)-1)
#define LONG_MAX	(~_HIL_)
#define LONG_MIN	(_HIL_)

int NB_MAIL = 0 ;


/****************************************************************************
 *                         fonction make_conelist();                        *
 ****************************************************************************/
cone_list	*make_conelist( pt_mbkfig )
lofig_list *pt_mbkfig;
{
cone_list	*ptcone 	= NULL ;
losig_list 	*ptsig 		= NULL ;
chain_list 	*ptchain 	= NULL ;
int coneSansBranche = 0 ;
int poid_s          = 0 ;
int coneCompt = 0 ;


/* parcours de la liste des signaux */
   for ( ptsig = pt_mbkfig->LOSIG ; ptsig != NULL ; ptsig = ptsig->NEXT )
   {

      /* transparence */
      if ( ptsig->TYPE == 'T' )
      {
      continue ;
      }

      /*------------------------------------------------------------+
      | le signal est il relie a un conecteur externe ou une grille |
      +------------------------------------------------------------*/
      for (ptchain=(chain_list*)getptype( ptsig->USER , LOFIGCHAIN )->DATA ;
           ptchain != NULL ;
           ptchain = ptchain->NEXT )
      {
         if ( ( ( locon_list * )ptchain->DATA )->NAME == NAME_GRID ) break ;
         if ( ( ( ( locon_list * )ptchain->DATA )->TYPE == 'E' )
			&& ( ptsig->TYPE != VDD )
			&& ( ptsig->TYPE != VSS ) )
         break ;
      }
		
      if  ( ptchain != NULL )  
      {
      /* creation d'un cone  */
      ptcone = add_cone( ptcone , ptsig ) ;
      ptcone->NAME = get_name( ptsig ) ;


      /*---------- TEST ----------------
      if(coneCompt < 1) continue ;
      if(coneCompt > 50) continue ;
      coneCompt++;
      printf("addcone sur %d'%s'\n",coneCompt,ptcone->NAME);
      fflush(stdout);
      ---------- FIN TEST ----------------*/

         if ( ( ptsig->TYPE != VDD ) && ( ptsig->TYPE != VSS ) )
         {
            /* ce n'est pas un cone alimentation */
            if ( ptsig->TYPE == 'E' ) 
            {
            /* cone construit sur un connecteur externe */
            ptype_list *ptuser = NULL ;
            locon_list *ptcon  = NULL ;
            list_list  *pt_path  = NULL ;
            int         n_ext     = 0;
            int         n_alim    = 0;
            int         autoref   = 0;
            int         mxmail   = 0;


               /*------------------------------------+
               | on chaine le cone sur le connecteur |
               | et le connecteur sur le cone        |
               +------------------------------------*/
               for(ptchain=(chain_list*)getptype(ptsig->USER,LOFIGCHAIN)->DATA;
                  ptchain != NULL ;
                  ptchain = ptchain->NEXT )
               {
                  if ( ( ( locon_list * )ptchain->DATA )->TYPE == 'E' )
                  {
                  ptcon = ( locon_list * )ptchain->DATA ;
                  ptcone->NAME=ptcon->NAME ;
                  ptcone->USER=addptype(ptcone->USER,EXT,(void *)ptcon) ;
                  ptuser = getptype( ptcon->USER,EXT) ;
                  ptuser->DATA = ( void * )ptcone  ;
                  ptcone->TYPE = EXT ;
                  }
               }
            fflush(stdout);
            NB_MAIL=0;
            ptcone->PATH = make_path( ptcone , ptsig , &autoref, &mxmail, &poid_s) ;

               for(pt_path=ptcone->PATH;pt_path!=NULL;pt_path=pt_path->NEXT )
               {
		/* on cherche des chemins vers les alimentations */
                  if ((pt_path->TYPE & EXT)==EXT) n_ext++;
                  if ( ( ( pt_path->TYPE & VDD ) == VDD ) 
			|| ( ( pt_path->TYPE & VSS ) == VSS ) )
                     n_alim++;
               }

               if (n_alim == 0 )
               {
		/* pas de chemin VSS ou VDD : connecteur d'entree ? */
                  for ( ptchain = ( chain_list * )getptype( ptsig->USER , LOFIGCHAIN )->DATA ;
                  ptchain != NULL ;
                  ptchain = ptchain->NEXT )
                  {
                     if ( ( ( locon_list *)ptchain->DATA )->NAME == NAME_GRID ) 
                     {
                     break ;
                     }
                  }
                  if (( ptchain == NULL ) && (n_ext==1))
                  {
			/* le connecteur externe n'est pas relie a une grille */
					/* on detruit le cone */
                  cone_list	*pt_oldcone ;
                  ptype_list      *ptus=NULL;
                  pt_oldcone = ptcone ;
                  ptcone = ptcone->NEXT ;
                  dsbFreeCone( pt_oldcone ) ;
                  ptus=getptype ( ptcon->USER, (short) EXT);
                  ptus->DATA=NULL;
                  }
                  else
                  {
                  /* entree sur grille \n */
                  }
               }
            }
            else
            {
            int autoref = 0 ;
            int mxmail  = 0 ;
            NB_MAIL=0;
            ptcone->PATH=make_path(ptcone,ptsig,&autoref,&mxmail,&poid_s) ;

               if(ptcone->PATH==NULL)
               {
               coneSansBranche++;
               dsbError(3,"make_path",get_name(ptsig),0,NULL,0);
               }
            }
         }

         else
         {
	/* c'est un cone alimentation */
         ptcone->TYPE = ptsig->TYPE ;
         }

	/* marquage du signal */
      ptsig->USER = addptype( ptsig->USER , CONE_TYPE , (void *)ptcone ) ;

	/* calcul du rectangle englobant : X1 , X2 , Y1 , Y2 */
      get_coord( ptcone ) ;
      }
   }

/*--------------------------------------------+
| compte rendu sur la sortie standart         |
+--------------------------------------------*/
   if(poid_s != 0)
   {
   dsbCrendu(102,NULL,NULL,poid_s);
   }

   if(coneSansBranche != 0)
   {
   dsbCrendu(103,NULL,NULL,coneSansBranche);
   }
   
return( ptcone ) ;
}


/****************************************************************************
 *                         fonction get_name();                             *
 ****************************************************************************/
 /*------------------------------------------------------------*
  | retourne le nom de plus haut niveau : celui dont le nombre |
  | de cheminom est le plus faible                             |
  *------------------------------------------------------------*/
char	*get_name( pt_sig )

losig_list	*pt_sig ;

{
chain_list	*pt_namechain 	= NULL ;
char		*pt_char		= NULL ;
char		default_res[50]	;
char		*result			= NULL ;
short		n_separ			= 0 ;
short		n_separmin		= 100 ;


   for ( pt_namechain = pt_sig->NAMECHAIN ; pt_namechain != NULL ; pt_namechain = pt_namechain->NEXT )
   {
   /* pour chaque alias */
   n_separ = 0 ;
      if ( pt_namechain->DATA != NULL )
      {
         for ( pt_char = (char*)pt_namechain->DATA ; *pt_char != ( char )0 ; pt_char ++ )
         {
	 /* on parcourt cet alias */
            if ( *pt_char == SEPAR )
            {
            /* on compte le nombre de separateurs */
            n_separ ++ ;
            }
         }
         if ( n_separ < n_separmin )
         {
         n_separmin = n_separ ;
         result = (char*)pt_namechain->DATA ;
         }
      }
   }

   /*------------------------------------------------------------*
    | Si  le nom obtenu commence par un chiffre, on insere .desb |
    | devant lui.                                                |
    *------------------------------------------------------------*/
   if ( (result != NULL ) && (*result >= '0') && (*result <='9') )
   {
   char * buff ;
   buff=(char*)mbkalloc(strlen(result)+6);
   sprintf(buff,"desb%c%s",SEPAR,result);
   result=namealloc(buff);
   }

   /*------------------------------------------------------------*
    | Si il n'y avait pas de nom, on construit un nom a partir   |
    | de son index : desbSEPARindex                              |
    *------------------------------------------------------------*/ 
   if ( result == NULL )
   {
   /* si il n'y avait pas d'alias */
   ( void )sprintf( default_res , "desb%c%d" , SEPAR , pt_sig->INDEX ) ;
   result = namealloc( default_res ) ;
   }

return( result ) ;
}



/****************************************************************************
 *                         fonction get_coord();                            *
 ****************************************************************************/
/* calcul du rectangle englobant : X1 , X2 , Y1 , Y2 */

void get_coord( ptcone )

cone_list	*ptcone ;

{
long	xmax = LONG_MIN ;
long	xmin = LONG_MAX ;
long	ymax = LONG_MIN ;
long	ymin = LONG_MAX ;
list_list	*pt_list = NULL ;
link_list	*ptlink	 = NULL ;

   for ( pt_list = ptcone->PATH ; pt_list != NULL ; pt_list = pt_list->NEXT )
   {
      for ( ptlink = ( link_list * )pt_list->DATA ; ptlink != NULL ; ptlink = ptlink->NEXT )
      {
         if ( ( ( ptlink->TYPE & TN ) == TN )
		   || ( ( ptlink->TYPE & TP ) == TP ) )
         {
         xmax = dsb_max( ( ptlink->TRANS->X ) , xmax ) ;
         xmin = dsb_min( ( ptlink->TRANS->X ) , xmin ) ;
         ymax = dsb_max( ( ptlink->TRANS->Y ) , ymax ) ;
         ymin = dsb_min( ( ptlink->TRANS->Y ) , ymin ) ;
         }	
      }
   }	
ptcone->X1 = ( xmin == LONG_MAX ? 0L : xmin ) ;
ptcone->Y1 = ( ymin == LONG_MAX ? 0L : ymin ) ;
ptcone->X2 = ( xmax == LONG_MIN ? 0L : xmax ) ;
ptcone->Y2 = ( ymax == LONG_MIN ? 0L : ymax ) ;
/* fin du calcul du rectangle englobant */
}


