/********************************************************************
*                                                                   *
* Laboratoire MASI CAO-VLSI, UPMC, Copyright 1991 1992 1993 1994    *
*                                                                   *
* Software support Email : cao-vlsi@masi.ibp.fr                     *
*                                                                   *
* Authors : Zouina AKTOUF &                                         *
*           El Arabi RHOMARI &                                      *
*           Jose MARTINS DOS SANTOS                                 *
*                                                                   *
* Supervision & Modifications : Lotfi BEN AMMAR                     *
*                                                                   *
********************************************************************/
/*********************************************************************************
*                      Fichier: sig_R.c                                          *
*       version : 3.0                                                            *
*       date    : 19/03/92                                                       *
*********************************************************************************/

#include "dpr_R.h"
#include "util_R.h"
#define orient_ud(x) 'V'
#define orient_u(x) 'V'
#define orient_d(x) 'V'

/*****************************************************************
*          fonction Affconch()                                   *
*    Affiche a l'ecran une structure connecteur                  *
*****************************************************************/
 void Affconch(fsortie,ptccon)
 FILE *fsortie;
 chain_list *ptccon;
 {
 INSTANCE   *ptcell;
 CONNECTOR  *ptcon;
 char       *ps;

 for (;ptccon;ptccon=ptccon->NEXT)
     {
     ptcon = (CONNECTOR *)ptccon->DATA;
     if (ptcon)
        {
        if (ptcon->INS)
           {
           ptcell = (INSTANCE *)ptcon->INS->DATA;
           ps = ptcell->INSNAME ;
           }
        else 
           ps = "$" ;
        fprintf(fsortie ,"|	|__(INSNAME).CON     : (%s).%s\n",ps,ptcon->NAME);
        }
     }
 }

/*********************************************************
**            fonction existlocon()                     **
**  Retourne le connecteur lolgique de nom ptname       **
**  s'il existe dans la liste ptcon_lo sinon NULL       **
*********************************************************/
 locon_list *existlocon(ptcon_lo,ptname)
 locon_list *ptcon_lo;
 char       *ptname;
 {

 if (ptname)
    for (;ptcon_lo;ptcon_lo=ptcon_lo->NEXT)
        if (ptcon_lo->NAME==ptname)
           return(ptcon_lo);
 return NULL ;
 }

/**********************************************************
**        fonction Alim_NAME()                           **
**   retourne le pointeur sur la chaine "VDD" ou "VSS"   **
**   si la chaine donnee debute par l'une des deux       **
**   chaines sinon elle retourne NULL.                   **
**********************************************************/
 char *Alim_NAME(ptname)
 char *ptname;
 {
 char        name_con[3];
 char       *ptname_con;
 char       *vdd;
 char       *vss;
 long        i;

 vdd = namealloc("vdd");
 vss = namealloc("vss");

 if (sizeof(ptname)>3)
    {
    for (i=0;(i<3);i++)
        name_con[i]=Upcase(ptname[i]);
    name_con[i]='\0';
    ptname_con = namealloc(name_con);
    return((ptname_con==vdd)||(ptname_con==vss))?ptname_con:NULL;
    }
 else
    return((ptname==vdd)||(ptname==vss))?ptname:NULL;
}

/****************************************************************
**           fonction listphref()                              **
****************************************************************/
 phref_list  *listphref(ptfig,ptnameref)
 phfig_list  *ptfig;
 char  *ptnameref;

 {
 phref_list *ptref_save = NULL ;
 phref_list *ptref_list = NULL ;
 phref_list *ptref_ph=NULL;
 char        ptauxname[20];
 long        i,imax;
 char       *ref_con;

 ref_con = namealloc("ref_con");
 for (ptref_ph=ptfig->PHREF;ptref_ph;)
     {
     if (ptref_ph->FIGNAME==ref_con)
        {
        for (i=0,imax=strrch(ptref_ph->NAME,'_');i<imax;i++)
            ptauxname[i] = ptref_ph->NAME[i];
        ptauxname[imax]='\0';
        if (ptnameref==namealloc(ptauxname))
           if (ptref_save)
              {
              ptref_save->NEXT = ptref_ph->NEXT;
              ptref_ph->NEXT = ptref_list;
              ptref_list = ptref_ph;
              ptref_ph = ptref_save->NEXT;
              }
           else
              {
              ptfig->PHREF = ptfig->PHREF->NEXT;
              ptref_ph->NEXT = ptref_list;
              ptref_list = ptref_ph;
              ptref_ph = ptfig->PHREF;
              }
        else 
           {
           ptref_save = ptref_ph;
           ptref_ph = ptref_ph->NEXT;
           }
        }
     else
        {
        ptref_save = ptref_ph;
        ptref_ph = ptref_ph->NEXT;
        }
     }
 return ptref_list;
 }

/****************************************************************
**           fonction listphcon()                              **
****************************************************************/
 phcon_list  *listphcon(ptfig,ptnamecon)
 phfig_list  *ptfig;
 char  *ptnamecon;

 {
 phcon_list *ptcon_save = NULL ;
 phcon_list *ptcon_list = NULL ;
 phcon_list *ptcon_ph=NULL;

 for (ptcon_ph=ptfig->PHCON;ptcon_ph;)
     {
     if (ptcon_ph->NAME==ptnamecon)
        {
        if (ptcon_save)
           {
           ptcon_save->NEXT = ptcon_ph->NEXT ;
           ptcon_ph->NEXT = ptcon_list;
           ptcon_list = ptcon_ph ;
           ptcon_ph = ptcon_save->NEXT ;
           }
        else
           {
           ptfig->PHCON = ptfig->PHCON->NEXT ;
           ptcon_ph->NEXT = ptcon_list;
           ptcon_list = ptcon_ph ;
           ptcon_ph = ptfig->PHCON ;
           }
        }
     else 
        {
        ptcon_save = ptcon_ph ;
        ptcon_ph = ptcon_ph->NEXT;
        }
     }
 return ptcon_list;
 }

/****************************************************************
*		fonction	insertsig()			*
****************************************************************/
 chain_list       *insertsig(ptcol,ptroot,ptcon,ptsig_mbk)
 COLUMN	*ptcol;
 FIGURE  *ptroot;
 CONNECTOR	*ptcon;
 losig_list	*ptsig_mbk;

 {
 chain_list	*ptcconlat=NULL;
 CONNECTOR      *ptconlat=NULL;
 CONNECTOR      *ptcon_ct=NULL;
 chain_list	*ptcsig=NULL;
 chain_list	*ptcsig1=NULL;
 SIGNAL		*ptsig=NULL;
 SIGNAL		*ptsig1=NULL;
 long            aux_min;

/* see if SIG already exist in list */
 for (ptcsig=ptroot->SIG ; ptcsig ; ptcsig=ptcsig->NEXT)
     {
     ptsig=(SIGNAL *)ptcsig->DATA;
     if (ptsig->INDEX==ptsig_mbk->INDEX) break;
     }
 if (ptcsig == NULL) /*c.a.d creation d'un nouveau signal DPR*/
    {
    ptsig=(SIGNAL *)mbkalloc(sizeof(SIGNAL));
    ptsig->NAME=getsigname(ptsig_mbk);
    ptsig->INDEX=ptsig_mbk->INDEX;
    ptsig->TYPE=ptsig_mbk->TYPE;
    ptsig->MIN_LIN = MAXINT;
    ptsig->HEIGHT = 0;
    ptsig->MIN_COL = MAXINT;
    ptsig->WIDTH = 0;
    ptsig->CON=NULL;
    ptsig->COL=NULL;
    ptsig->LIN=NULL;
    ptsig->BCROSS=NULL;
    ptsig->YPRIOR=NULL;
    ptsig->USER=NULL;
    ptroot->SIG=addchain(ptroot->SIG,(void *)ptsig);
    if (ptcol)
       {
       ptsig->MIN_COL=ptcol->INDEX;
       ptsig->WIDTH=0;
       ptsig->COL = addchain((chain_list *)NULL,(void *)ptcol);
       ptcol->SIG = addchain(ptcol->SIG,(void *)ptsig);
       }
    else
       {
       ptsig->MIN_COL=MAXINT;
       ptsig->WIDTH=0;
       ptsig->COL=NULL;
       }
    ptcon->SIG = ptroot->SIG;
    if (ptcon->USER)
       {
       ptcon_ct = (CONNECTOR *)ptcon->USER->DATA;
       ptcon_ct->SIG = ptroot->SIG;
       }
    }
 else /*c.a.d signal DPR deja existant*/
    {
    if (ptcol)
       {
       ptsig=(SIGNAL *)ptcsig->DATA;
       /* see if sig already exist in line */
       for (ptcsig1=ptcol->SIG;ptcsig1;ptcsig1=ptcsig1->NEXT)
           {
           ptsig1=(SIGNAL *)ptcsig1->DATA;
           if (ptsig1==ptsig) break;
           }
       if (ptcsig1 == NULL)
          {
          ptcol->SIG=addchain(ptcol->SIG,(void *)ptsig);
          ptsig->COL=addchain(ptsig->COL,(void *)ptcol);
          aux_min = ptsig->MIN_COL;
          ptsig->MIN_COL=dpr_min(ptsig->MIN_COL,ptcol->INDEX);
          ptsig->WIDTH=dpr_max(aux_min+ptsig->WIDTH,ptcol->INDEX)-ptsig->MIN_COL;
          } 
       }
    ptcon->SIG = ptcsig;
    if (ptcon->USER)
       {
       ptcon_ct = (CONNECTOR *)ptcon->USER->DATA;
       ptcon_ct->SIG = ptcsig;
       }
    }
/* add connector link to this sig        */
 ptsig->CON = addchain(ptsig->CON,(void *)ptcon);
 if (ptcon->USER)
    {
    ptcon_ct = (CONNECTOR *)ptcon->USER->DATA;
    ptsig->CON = addchain(ptsig->CON,(void *)ptcon_ct);
    }
 
 return (ptcon->SIG);
 }

/************************************************************************
*		fonction	mkcon()				*
************************************************************************/
 CONNECTOR           *mkcon(ptccol,ptccell,ptname,type)

 chain_list	*ptccol;
 chain_list	*ptccell;
 char		*ptname;
 char		 type;
 
 {
 CONNECTOR       *ptcon=NULL;
 ptcon=(CONNECTOR *)mbkalloc(sizeof(CONNECTOR));
 ptcon->NAME=ptname;
 ptcon->TYPE=type;
 ptcon->NBPOSS=0;
 ptcon->MINPOS=MAXLONG;
 ptcon->MAXPOS=MINLONG;
 ptcon->POS=NULL;
 ptcon->SIG=NULL;
 ptcon->INS=ptccell;
 ptcon->COL=ptccol;
 ptcon->LIN=NULL;
 ptcon->USER=NULL;

 return(ptcon);
 }

/***********************************************************************
**           fonction insertcon()                                     **
***********************************************************************/
 CONNECTOR  *insertcon(ptccol,ptccell,ptcon_lo,ptref_ph,ptcon_ph)
 chain_list *ptccol;
 chain_list *ptccell;
 locon_list *ptcon_lo;
 phref_list *ptref_ph;
 phcon_list *ptcon_ph;

 {
 long     xref_col;
 long     yref_col;
 long     track=0;
 long     width=2;
 char     orient='X';
 long     miny_df=MAXLONG;
 long     miny_ct=MAXLONG;
 long     maxy_df=MINLONG;
 long     maxy_ct=MINLONG;
 long     xcon_col=0;
 long     ycon_col=0;
 long     nbposs_df=0;
 long     nbposs_ct=0;
 long     xab1=0,yab1=0,xab2=0,yab2=0;
 CONNECTOR    *ptcon_df=NULL;
 CONNECTOR    *ptcon_ct=NULL;
 CONNECTOR    *ptcon1=NULL;
 INSTANCE     *ptcell=NULL; 
 COLUMN       *ptcol=NULL; 
 chain_list *ptccon=NULL;
 chain_list *ptcpos_df=NULL;
 chain_list *ptcpos_ct=NULL;
 chain_list *ptccon_save=NULL;
 phfig_list *ptinsf_ph=NULL;
 ptype_list *pttype=NULL;
 char     *name_a2r=NULL, *name_a2l=NULL, *name_a2rl=NULL;
 char     *name_a2u=NULL, *name_a2d=NULL, *name_a2ud=NULL;
 char     *ptfigname=NULL;

# ifdef DEBUG_LOAD
    if (DEBUG_LOAD) fprintf(FOUT,"Entree de insertcon : %s \n",ptcon_lo->NAME);
# endif

 name_a2d  = namealloc("ref_a2d");
 name_a2u  = namealloc("ref_a2u");
 name_a2ud = namealloc("ref_a2ud");
 name_a2r  = namealloc("ref_a2r");
 name_a2l  = namealloc("ref_a2l");
 name_a2rl = namealloc("ref_a2rl");

 ptcell = (INSTANCE *)ptccell->DATA;
 ptinsf_ph = (phfig_list *)ptcell->USER->NEXT->DATA;
 xab1 = ptinsf_ph->XAB1;
 xab2 = ptinsf_ph->XAB2;
 yab1 = ptinsf_ph->YAB1;
 yab2 = ptinsf_ph->YAB2;

 ptcon_df = mkcon(ptccol,ptccell,ptcon_lo->NAME,INTERN);
 ptcon_ct = mkcon(ptccol,ptccell,ptcon_lo->NAME,INTERN);
 
 for (;ptref_ph;ptref_ph=ptref_ph->NEXT)
     {
     xref_col = ptcell->X + delta_x(xab1,yab1,xab2,yab2,ptref_ph->XREF,
                                     ptref_ph->YREF,ptcell->TRANSF);
     yref_col = ptcell->Y + delta_y(xab1,yab1,xab2,yab2,ptref_ph->XREF,
                                     ptref_ph->YREF,ptcell->TRANSF);
     if (pttype = getptype(ptref_ph->USER,SETACCESS))
        {
        ptfigname = pttype->DATA;
        if (ptfigname==name_a2rl)
           orient = orient_rl(ptcell->TRANSF);
        else
           if (ptfigname==name_a2r)
              orient = orient_r(ptcell->TRANSF);
           else 
              if (ptfigname==name_a2l)
                 orient = orient_l(ptcell->TRANSF);
              else 
                 if (ptfigname == name_a2ud)
                    orient = orient_ud(ptcell->TRANSF);
                 else 
                    if (ptfigname == name_a2u)
                       orient = orient_u(ptcell->TRANSF);
                    else 
                       if (ptfigname == name_a2d)
                          orient = orient_d(ptcell->TRANSF);
                       else
                          {
                          printf("BUG: Reference orientation not valid!!\n");
                          exit(4);
                          }
        ptcpos_df= addpos(ptcpos_df,xref_col,yref_col,(char)ALU2,
                       orient,MULTIAX,track,width,ptcon_df);
        nbposs_df += 1;
        miny_df = dpr_min(miny_df,yref_col);
        maxy_df = dpr_max(maxy_df,yref_col);
        }
     else
        {
        printf("BUG: A problem with setaccess\n");
        exit(2);
        }
     }

 for (;ptcon_ph;ptcon_ph=ptcon_ph->NEXT)
     {
     xcon_col = ptcell->X + delta_x(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                     ptcon_ph->YCON,ptcell->TRANSF);
     ycon_col = ptcell->Y + delta_y(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                     ptcon_ph->YCON,ptcell->TRANSF);
     orient = Orient(ptcon_ph->ORIENT,ptcell->TRANSF);
     if ((orient==NORTH)||(orient==SOUTH)) /* c.a.d controle */
        {
        ptcpos_ct = addpos(ptcpos_ct,xcon_col,ycon_col,ptcon_ph->LAYER,
                           orient,TYPEFIX,FTRACK,ptcon_ph->WIDTH,ptcon_ct);
        nbposs_ct += 1;
        miny_ct = dpr_min(miny_ct,ycon_col);
        maxy_ct = dpr_max(maxy_ct,ycon_col);
        }
     else /* c.a.d data_flow */
        {
        ptcpos_df = addpos(ptcpos_df,xcon_col,ycon_col,ptcon_ph->LAYER,
                        orient,TYPEFIX,FTRACK,ptcon_ph->WIDTH,ptcon_df);
        nbposs_df += 1;
        miny_df =dpr_min(miny_df,ycon_col);
        maxy_df =dpr_max(maxy_df,ycon_col);
        }
     }

 if (ptcpos_df)
    {
    ptcon_df->POS = ptcpos_df;
    ptcon_df->NBPOSS = nbposs_df;
    ptcon_df->MINPOS = miny_df;
    ptcon_df->MAXPOS = maxy_df;
    /* find posis con in cell */
    ptccon_save = NULL;
    for (ptccon=ptcell->DF_CON;ptccon;ptccon=ptccon->NEXT)
        {
        ptcon1 = (CONNECTOR *)ptccon->DATA;
        if (ptcon1->MINPOS > miny_df) break;
           ptccon_save = ptccon;
        }
    if (ptccon_save)
       ptccon_save->NEXT = addchain(ptccon_save->NEXT,(void *)ptcon_df);
    else
       ptcell->DF_CON = addchain(ptcell->DF_CON,(void *)ptcon_df);
    }

 if (ptcpos_ct)
    {
    ptcon_ct->POS = ptcpos_ct;
    ptcon_ct->NBPOSS = nbposs_ct;
    ptcon_ct->MINPOS = miny_ct;
    ptcon_ct->MAXPOS = maxy_ct;
    /* find posis con in cell */
    ptccon_save = NULL;
    for (ptccon=ptcell->CT_CON;ptccon;ptccon=ptccon->NEXT)
        {
        ptcon1 = (CONNECTOR *)ptccon->DATA;
        if (ptcon1->MINPOS > miny_ct) break;
           ptccon_save = ptccon;
        }
    if (ptccon_save)
       ptccon_save->NEXT = addchain(ptccon_save->NEXT,(void *)ptcon_ct);
    else
       ptcell->CT_CON = addchain(ptcell->CT_CON,(void *)ptcon_ct);
    }

# ifdef DEBUG_LOAD 
     if (DEBUG_LOAD) fprintf(FOUT,"Sortie de insertcon : %s \n",ptcon_df->NAME);
# endif

/* pour inseretsig mettre ptcon_ct dans USER de ptcon_df */
 if (ptcpos_df)
    {
    if (ptcpos_ct)
       ptcon_df->USER = addchain(ptcon_df->USER,(void *)ptcon_ct);
    return(ptcon_df);
    }
 else
    {
    return(ptcon_ct);
    }
 }

/*********************************************************************
**     fonction inserappel()                                        **
*********************************************************************/
 void  inserappel(ptroot,ptccol,ptccell,ptcon_lo,ptcon_ph)
 FIGURE     *ptroot;
 chain_list *ptccol;
 chain_list *ptccell;
 locon_list *ptcon_lo;
 phcon_list *ptcon_ph;
 
 {
 chain_list *ptcalim=NULL;
 chain_list *ptcconb=NULL;
 chain_list *ptcalim_save=NULL;
 CONNECTOR  *ptalim=NULL;
 CONNECTOR  *ptconb=NULL;
 INSTANCE   *ptcell=NULL;
 CONNECTOR  *ptcon=NULL;
 long        xcon_col,ycon_col;
 long        xab1,xab2,yab1,yab2;
 char        orient;
 long        min_y=MAXLONG;
 long        max_y=MINLONG;
 long        nbposs = 0;
 chain_list *ptcpos=NULL;
 phfig_list *ptinsf_ph=NULL;
 phcon_list *ptcon_phsav;

# ifdef DEBUG_LOAD 
    if(DEBUG_LOAD) fprintf(FOUT,"Entree de inserappel .\n");
# endif

 /* sauvegarde du pointeur sur les con ph de mbk pour insertcon() */
 ptcon_phsav = ptcon_ph;

 ptcon = mkcon(ptccol,ptccell,ptcon_lo->NAME,INTERN);

 ptcell = (INSTANCE *)ptccell->DATA;
 ptinsf_ph = (phfig_list *)ptcell->USER->NEXT->DATA;
 xab1 = ptinsf_ph->XAB1;
 xab2 = ptinsf_ph->XAB2;
 yab1 = ptinsf_ph->YAB1;
 yab2 = ptinsf_ph->YAB2;
 for (;ptcon_ph;ptcon_ph=ptcon_ph->NEXT)
     {
     xcon_col = ptcell->X + delta_x(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                    ptcon_ph->YCON,ptcell->TRANSF);
     ycon_col = ptcell->Y + delta_y(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                    ptcon_ph->YCON,ptcell->TRANSF);
     orient = Orient(ptcon_ph->ORIENT,ptcell->TRANSF);
     if ((orient==NORTH)||(orient==SOUTH))
        {
        ptcpos = addpos(ptcpos,xcon_col,ycon_col,ptcon_ph->LAYER,
                        orient,TYPEFIX,FTRACK,ptcon_ph->WIDTH,ptcon);
        nbposs += 1;
        min_y = dpr_min(min_y,ycon_col);
        max_y = dpr_max(max_y,ycon_col);
        }
     else
        {
        printf("DPR Error: Alim orientation not valid in %s!!\n",
                ptcell->INSNAME);
        exit(3);
        }
     }
 if (ptcpos)
    {
    ptcon->POS = ptcpos ;
    ptcon->NBPOSS = nbposs;
    ptcon->MINPOS = min_y;
    ptcon->MAXPOS = max_y;
    /* find posis alim in cell */
    for (ptcalim=ptcell->RAPPELS;ptcalim;ptcalim=ptcalim->NEXT)
        {
        ptalim = (CONNECTOR *)ptcalim->DATA;
        if (ptalim->MINPOS > min_y) break;
        ptcalim_save = ptcalim;
        }
    if (ptcalim_save)
       {
       ptcalim_save->NEXT = addchain(ptcalim_save->NEXT,(void *)ptcon);
       }
    else
       {
       ptcell->RAPPELS = addchain(ptcell->RAPPELS,(void *)ptcon);
       }
    }
 else
    {
    printf("DPR Error: North/South Alim refresh terminal in figure %s not in ALU1!!\n",
            ptcell->INSNAME);
    exit(3);
    }

 /*pas necess*/
 /*(void *)insertcon(ptccol,ptccell,ptcon_lo,NULL,ptcon_phsav);*/
 /*(void *)insertsig((COLUMN *)ptccol->DATA,ptroot,ptcon,ptcon_lo->SIG);*/

# ifdef DEBUG_LOAD 
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de inserappel .\n");
# endif

 }

/*********************************************************************
**     fonction insertalim()                                        **
*********************************************************************/
 void  insertalim(ptroot,ptccol,ptccell,ptcon_lo,ptcon_ph)
 FIGURE     *ptroot;
 chain_list *ptccol;
 chain_list *ptccell;
 locon_list *ptcon_lo;
 phcon_list *ptcon_ph;
 
 {
 chain_list *ptcalim=NULL;
 chain_list *ptcconb=NULL;
 chain_list *ptcalim_save=NULL;
 CONNECTOR  *ptalim=NULL;
 CONNECTOR  *ptconb=NULL;
 INSTANCE   *ptcell=NULL;
 CONNECTOR  *ptcon=NULL;
 long        xcon_col,ycon_col;
 long        xab1,xab2,yab1,yab2;
 char        orient;
 long        min_y=MAXLONG;
 long        max_y=MINLONG;
 long        nbposs = 0;
 chain_list *ptcpos=NULL;
 phfig_list *ptinsf_ph=NULL;
 phcon_list *ptcon_phsav;

# ifdef DEBUG_LOAD 
    if(DEBUG_LOAD) fprintf(FOUT,"Entree de insertalim .\n");
# endif

 /* sauvegarde du pointeur sur les con ph de mbk pour insertcon() */
 ptcon_phsav = ptcon_ph;

 ptcon = mkcon(ptccol,ptccell,ptcon_lo->NAME,INTERN);

 ptcell = (INSTANCE *)ptccell->DATA;
 ptinsf_ph = (phfig_list *)ptcell->USER->NEXT->DATA;
 xab1 = ptinsf_ph->XAB1;
 xab2 = ptinsf_ph->XAB2;
 yab1 = ptinsf_ph->YAB1;
 yab2 = ptinsf_ph->YAB2;
 for (;ptcon_ph;ptcon_ph=ptcon_ph->NEXT)
     {
     xcon_col = ptcell->X + delta_x(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                    ptcon_ph->YCON,ptcell->TRANSF);
     ycon_col = ptcell->Y + delta_y(xab1,yab1,xab2,yab2,ptcon_ph->XCON,
                                    ptcon_ph->YCON,ptcell->TRANSF);
     orient = Orient(ptcon_ph->ORIENT,ptcell->TRANSF);
     if ((orient==EAST)||(orient==WEST))
        {
        ptcpos = addpos(ptcpos,xcon_col,ycon_col,ptcon_ph->LAYER,
                        orient,TYPEFIX,FTRACK,ptcon_ph->WIDTH,ptcon);
        nbposs += 1;
        min_y = dpr_min(min_y,ycon_col);
        max_y = dpr_max(max_y,ycon_col);
        }
     else
        {
        printf("DPR Error: Alim orientation not valid in %s!!\n",
                ptcell->INSNAME);
        exit(3);
        }
     }
 if (ptcpos)
    {
    ptcon->POS = ptcpos ;
    ptcon->NBPOSS = nbposs;
    ptcon->MINPOS = min_y;
    ptcon->MAXPOS = max_y;
    /* find posis alim in cell */
    for (ptcalim=ptcell->ALIMS;ptcalim;ptcalim=ptcalim->NEXT)
        {
        ptalim = (CONNECTOR *)ptcalim->DATA;
        if (ptalim->MINPOS > min_y) break;
        ptcalim_save = ptcalim;
        }
    if (ptcalim_save)
       {
       ptcalim_save->NEXT = addchain(ptcalim_save->NEXT,(void *)ptcon);
       }
    else
       {
       ptcell->ALIMS = addchain(ptcell->ALIMS,(void *)ptcon);
       }
    }
 else
    {
    printf("DPR Error: East/West Alim connector in figure %s not in ALU2!!\n",
            ptcell->FIGNAME);
    exit(3);
    }

 (void *)insertcon(ptccol,ptccell,ptcon_lo,NULL,ptcon_phsav);
 (void *)insertsig((COLUMN *)ptccol->DATA,ptroot,ptcon,ptcon_lo->SIG);/*pas necess*/

# ifdef DEBUG_LOAD 
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de insertalim .\n");
# endif

 }

/*********************************************************************
**        fonction inserttrans()                                    **
*********************************************************************/
 void    inserttrans(ptcol,ptcel,ptseg_ph)
 COLUMN     *ptcol;
 INSTANCE   *ptcel;
 phseg_list *ptseg_ph;
 
 {
 SEGMENT     *ptseg=NULL;
 phfig_list  *ptfig=NULL;
 chain_list  *ptcseg_save=NULL;
 chain_list  *ptctmp=NULL;
 chain_list  *ptcseg=NULL;
 long      xab1,yab1,xab2,yab2;
 long      x1seg_col,y1seg_col;
 long      x2seg_col,y2seg_col;

# ifdef DEBUG_LOAD
    if (DEBUG_LOAD) fprintf (FOUT , "Entree de inserttrans : %s \n",ptseg_ph->NAME);
# endif

 ptfig  = (phfig_list *)ptcel->USER->NEXT->DATA;
 xab1   = ptfig->XAB1;
 xab2   = ptfig->XAB2;
 yab1   = ptfig->YAB1;
 yab2   = ptfig->YAB2;
 x1seg_col = ptcel->X + delta_x(xab1,yab1,xab2,yab2,ptseg_ph->X1,ptseg_ph->Y1,
                                ptcel->TRANSF);
 y1seg_col = ptcel->Y + delta_y(xab1,yab1,xab2,yab2,ptseg_ph->X1,ptseg_ph->Y1,
                                ptcel->TRANSF);
 x2seg_col = ptcel->X + delta_x(xab1,yab1,xab2,yab2,ptseg_ph->X2,ptseg_ph->Y2,
                                ptcel->TRANSF);
 y2seg_col = ptcel->Y + delta_y(xab1,yab1,xab2,yab2,ptseg_ph->X2,ptseg_ph->Y2,
                                ptcel->TRANSF);
                                  
 if (!ptcel->ALLOW) /* liste des transparences de la cellule vide */
    {
    for (ptcseg=ptcol->ALLOW;ptcseg;ptcseg=ptcseg->NEXT)
        {
        if ((ptseg=(SEGMENT *)ptcseg->DATA))
           if (ptseg->Y1>y1seg_col) break;
        ptcseg_save = ptcseg;
        }

    /* insertion de la transparence dans la colonne */
    if (ptcseg_save)
       {
       ptcseg = addseg(ptcseg_save->NEXT,ptseg_ph->NAME,x1seg_col,y1seg_col, 
                       x2seg_col,y2seg_col,ptseg_ph->WIDTH,ptseg_ph->TYPE,
                       ptseg_ph->LAYER);
       ptcseg_save->NEXT = ptcseg;
       }
    else
       {
       ptcseg = addseg(ptcol->ALLOW,ptseg_ph->NAME,x1seg_col,y1seg_col, 
                       x2seg_col,y2seg_col,ptseg_ph->WIDTH,ptseg_ph->TYPE,
                       ptseg_ph->LAYER);
       ptcol->ALLOW = ptcseg;
       }

    /* insertion de la transparence dans l'instance si elle est la premiere */
    /* sinon le chainage dans la ligne assure linsertion.                   */

    ptcseg->NEXT = addchain(ptcseg->NEXT,(void *)NULL);
    ptcel->ALLOW = ptcseg;
    }
 else /* liste non vide */
    {
    for (ptcseg=ptcel->ALLOW;ptcseg->DATA;ptcseg=ptcseg->NEXT)
        {
        ptseg = (SEGMENT *)ptcseg->DATA;
        if (ptseg->Y1>y1seg_col) break;
        ptcseg_save = ptcseg;
        }
    /* insertion de la transparence dans l'instance et de meme dans la colonne */
    if (ptcseg_save)
       {
       ptcseg = addseg(ptcseg_save->NEXT,ptseg_ph->NAME,x1seg_col,y1seg_col, 
                       x2seg_col,y2seg_col,ptseg_ph->WIDTH,ptseg_ph->TYPE,
                       ptseg_ph->LAYER);
       ptcseg_save->NEXT = ptcseg;
       }
    else
       {
       ptcseg = addseg(ptcel->ALLOW,ptseg_ph->NAME,x1seg_col,y1seg_col, 
                       x2seg_col,y2seg_col,ptseg_ph->WIDTH,ptseg_ph->TYPE,
                       ptseg_ph->LAYER);
       for (ptctmp=ptcol->ALLOW;ptctmp;ptctmp=ptctmp->NEXT)
           {
           if (ptctmp==ptcel->ALLOW) break;
           ptcseg_save = ptctmp;
           }
       if (ptcseg_save)
          ptcseg_save->NEXT = ptcseg;
       if (ptcol->ALLOW==ptcel->ALLOW)
          ptcol->ALLOW = ptcseg;
       ptcel->ALLOW = ptcseg;
       }
    }

# ifdef DEBUG_LOAD
    if (DEBUG_LOAD) fprintf (FOUT , "Sortie de inserttrans : %s \n",ptseg_ph->NAME);
# endif

 }

/********************************************************************
**        fonction insertnwell()                                   **
********************************************************************/
 void        insertnwell(ptccol,ptccell,ptref_ph)
 chain_list *ptccol;
 chain_list *ptccell;
 phref_list *ptref_ph;

 {
 phfig_list   *ptinsf_ph=NULL;
 INSTANCE     *ptcell=NULL;
 long          xnwell_col, ynwell_col;
 long          xab1, yab1,xab2,yab2;
 long          width;
 char         *souligne;

 ptcell = (INSTANCE *)ptccell->DATA;
 ptinsf_ph = (phfig_list *)ptcell->USER->NEXT->DATA;
 xab1 = ptinsf_ph->XAB1;
 xab2 = ptinsf_ph->XAB2;
 yab1 = ptinsf_ph->YAB1;
 yab2 = ptinsf_ph->YAB2;

 for (;ptref_ph;ptref_ph=ptref_ph->NEXT)
     {
     souligne = strrchr(ptref_ph->NAME,'_');
     if (!souligne)
        {
        printf("Warning: Nwell reference in %s not valid!!\n",ptinsf_ph->NAME);
        continue;
        }
     xnwell_col = ptcell->X + delta_x(xab1,yab1,xab2,yab2,ptref_ph->XREF,
                                    ptref_ph->YREF,ptcell->TRANSF);
     ynwell_col = ptcell->Y + delta_y(xab1,yab1,xab2,yab2,ptref_ph->XREF,
                                    ptref_ph->YREF,ptcell->TRANSF);
     width = atoi(souligne+1);
     ptcell->N_WELL = addnwell(ptcell->N_WELL,xnwell_col,ynwell_col,SCALE_X*width,
                               ptccell,ptccol);
     }
 }

/***********************************************************************
**           fonction mkrappel_list()                                  **
** creer une liste de type chain_list dont chaque element contient un **
** pointeur sur une liste (2) de connecteurs MBK ayant le meme x.     **
***********************************************************************/
 chain_list  *mkrappel_list(ptheadalim)
 phcon_list  *ptheadalim;

 {
 phcon_list  *ptalim1=NULL;
 phcon_list  *ptalim2=NULL;
 phcon_list  *ptnewalim=NULL;
 phcon_list  *ptnewalimnext=NULL;
 chain_list  *ptcalim=NULL;
 chain_list  *ptcusedhead=NULL;
 chain_list  *ptcused=NULL;
 phcon_list  *ptused=NULL;

 for (ptalim1=ptheadalim;ptalim1;ptalim1=ptalim1->NEXT)
     {
     if ((ptalim1->LAYER==ALU1)&&
         ((ptalim1->ORIENT==NORTH)||(ptalim1->ORIENT==SOUTH)))
        {
        for (ptcused=ptcusedhead;ptcused;ptcused=ptcused->NEXT)
            {
            ptused = (phcon_list *)ptcused->DATA;
            if (ptused==ptalim1)
               break;
            }
        if (!ptcused) /* c.a.d pas deja considere */
           {
           ptnewalim         = (phcon_list *)mbkalloc(sizeof(phcon_list));
           ptnewalim->NEXT   = NULL;
           ptnewalim->NAME   = ptalim1->NAME;
           ptnewalim->INDEX  = ptalim1->INDEX;
           ptnewalim->XCON   = ptalim1->XCON;
           ptnewalim->YCON   = ptalim1->YCON;
           ptnewalim->WIDTH  = ptalim1->WIDTH;
           ptnewalim->ORIENT = ptalim1->ORIENT;
           ptnewalim->LAYER  = ptalim1->LAYER;
           ptnewalim->USER   = ptalim1->USER;
           for (ptalim2=ptalim1->NEXT;ptalim2;ptalim2=ptalim2->NEXT)
               {
               if ((ptalim2->LAYER==ALU1)&&
                   ((ptalim2->ORIENT==NORTH)||(ptalim2->ORIENT==SOUTH)))
                  {
                  if (ptalim2->XCON==ptalim1->XCON)
                     {
                     ptnewalimnext     = ptnewalim;
                     ptnewalim         = (phcon_list *)mbkalloc(sizeof(phcon_list));
                     ptnewalim->NEXT   = ptnewalimnext;
                     ptnewalim->NAME   = ptalim2->NAME;
                     ptnewalim->INDEX  = ptalim2->INDEX;
                     ptnewalim->XCON   = ptalim2->XCON;
                     ptnewalim->YCON   = ptalim2->YCON;
                     ptnewalim->WIDTH  = ptalim2->WIDTH;
                     ptnewalim->ORIENT = ptalim2->ORIENT;
                     ptnewalim->LAYER  = ptalim2->LAYER;
                     ptnewalim->USER   = ptalim2->USER;
                     /* ranger le pointeur sur le connecteur de meme x dans ptcused */
                     ptcusedhead = addchain(ptcusedhead,(void *)ptalim2);
                     }
                  }
               }
           ptcalim = addchain(ptcalim,(void *)ptnewalim);
           }
        }
     }
 return ptcalim;
 }

/***********************************************************************
**           fonction mkalims_list()                                  **
** creer une liste de type chain_list dont chaque element contient un **
** pointeur sur une liste (2) de connecteurs MBK ayant le meme y.     **
***********************************************************************/
 chain_list  *mkalims_list(ptheadalim)
 phcon_list  *ptheadalim;

 {
 phcon_list  *ptalim1=NULL;
 phcon_list  *ptalim2=NULL;
 phcon_list  *ptnewalim=NULL;
 phcon_list  *ptnewalimnext=NULL;
 chain_list  *ptcalim=NULL;
 chain_list  *ptcusedhead=NULL;
 chain_list  *ptcused=NULL;
 phcon_list  *ptused=NULL;

 for (ptalim1=ptheadalim;ptalim1;ptalim1=ptalim1->NEXT)
     {
     if ((ptalim1->LAYER==ALU2)&&
         ((ptalim1->ORIENT==EAST)||(ptalim1->ORIENT==WEST)))
        {
        for (ptcused=ptcusedhead;ptcused;ptcused=ptcused->NEXT)
            {
            ptused = (phcon_list *)ptcused->DATA;
            if (ptused==ptalim1)
               break;
            }
        if (!ptcused) /* c.a.d pas deja considere */
           {
           ptnewalim         = (phcon_list *)mbkalloc(sizeof(phcon_list));
           ptnewalim->NEXT   = NULL;
           ptnewalim->NAME   = ptalim1->NAME;
           ptnewalim->INDEX  = ptalim1->INDEX;
           ptnewalim->XCON   = ptalim1->XCON;
           ptnewalim->YCON   = ptalim1->YCON;
           ptnewalim->WIDTH  = ptalim1->WIDTH;
           ptnewalim->ORIENT = ptalim1->ORIENT;
           ptnewalim->LAYER  = ptalim1->LAYER;
           ptnewalim->USER   = ptalim1->USER;
           for (ptalim2=ptalim1->NEXT;ptalim2;ptalim2=ptalim2->NEXT)
               {
               if ((ptalim2->LAYER==ALU2)&&
                   ((ptalim2->ORIENT==EAST)||(ptalim2->ORIENT==WEST)))
                  {
                  if (ptalim2->YCON==ptalim1->YCON)
                     {
                     ptnewalimnext     = ptnewalim;
                     ptnewalim         = (phcon_list *)mbkalloc(sizeof(phcon_list));
                     ptnewalim->NEXT   = ptnewalimnext;
                     ptnewalim->NAME   = ptalim2->NAME;
                     ptnewalim->INDEX  = ptalim2->INDEX;
                     ptnewalim->XCON   = ptalim2->XCON;
                     ptnewalim->YCON   = ptalim2->YCON;
                     ptnewalim->WIDTH  = ptalim2->WIDTH;
                     ptnewalim->ORIENT = ptalim2->ORIENT;
                     ptnewalim->LAYER  = ptalim2->LAYER;
                     ptnewalim->USER   = ptalim2->USER;
                     /* ranger le pointeur sur le connecteur de meme y dans ptcused */
                     ptcusedhead = addchain(ptcusedhead,(void *)ptalim2);
                     }
                  }
               }
           ptcalim = addchain(ptcalim,(void *)ptnewalim);
           }
        }
     }
 return ptcalim;
 }

/***********************************************************************
**           fonction sigconfils()                                    **
***********************************************************************/
 void sigconfils(ptroot)
 FIGURE *ptroot;
 
 {
 chain_list   *ptccon_d=NULL;
 chain_list   *ptccon_c=NULL;
 chain_list   *ptcalim=NULL;
 chain_list   *ptcalims=NULL;
 chain_list   *ptcconb=NULL;
 chain_list   *ptccol=NULL;
 chain_list   *ptccell=NULL;
 chain_list   *ptcallow=NULL;
 COLUMN       *ptcol=NULL;
 INSTANCE     *ptcell=NULL;
 CONNECTOR    *ptcon=NULL;
 CONNECTOR    *ptconb=NULL;
 phref_list   *ptref_ph=NULL;
 phcon_list   *ptcon_ph=NULL;
 phcon_list   *ptalim_ph=NULL;
 phfig_list   *ptinsf_ph=NULL;
 loins_list   *ptins_lo=NULL;
 locon_list   *ptcon_lo=NULL;
 phcon_list   *ptsavecon_ph=NULL,*ptauxcon_ph=NULL;
 phcon_list   *ptcon_phaux=NULL;
 phref_list   *ptsaveref_ph=NULL,*ptauxref_ph=NULL;
 phseg_list   *ptseg_ph=NULL;
 phfig_list   *ptfig=NULL;
 char         *vdd=NULL;
 char         *vss=NULL;
 char         *ref_con;
 long i;

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Entree de sigconfils : \n");
# endif

 vdd = namealloc("vdd");
 vss = namealloc("vss");
 ref_con = namealloc("ref_con");

 for (ptccol=ptroot->COL->NEXT->NEXT;ptccol->NEXT;ptccol=ptccol->NEXT->NEXT)
     {
     ptcol = (COLUMN *)ptccol->DATA;
     ptcol->DF_CON = addchain(ptcol->DF_CON,(void *)NULL);
     ptccon_d = ptcol->DF_CON;
     ptcol->CT_CON = addchain(ptcol->CT_CON,(void *)NULL);
     ptccon_c = ptcol->CT_CON;
     ptcol->ALIMS = addchain(ptcol->ALIMS,(void *)NULL);
     ptcalim = ptcol->ALIMS;
     for (ptccell=ptcol->INS;ptccell;ptccell=ptccell->NEXT)
         {
         ptcell = (INSTANCE *)ptccell->DATA;
         ptins_lo = (loins_list *)ptcell->USER->DATA;
         ptinsf_ph = (phfig_list *)ptcell->USER->NEXT->DATA;
      
         ptsavecon_ph = NULL ;
         ptsaveref_ph = NULL ;

         for (ptcon_lo=ptins_lo->LOCON;ptcon_lo;ptcon_lo=ptcon_lo->NEXT)
             {
             ptref_ph = NULL ;
             ptcon_ph = NULL ;
             if (!strncmp(ptcon_lo->NAME,vdd,3)||!strncmp(ptcon_lo->NAME,vss,3))
                {
                ptcon_ph = listphcon(ptinsf_ph,ptcon_lo->NAME);
                if (!ptcon_ph)
                   {
                   printf("Error: No physical connector corresponding to %s in figure %s\n",ptcon_lo->NAME,ptcell->FIGNAME);
                   exit(1);
                   }
                else 
                   {
                   /* creer une chain_liste pour ranger les alims N/S a X != (par 2) */
                   ptcalims = mkrappel_list(ptcon_ph);
                   /* pour chaque couple de rappels inserappel */
                   for (;ptcalims;ptcalims=ptcalims->NEXT)
                       {
                       ptalim_ph = (phcon_list *)ptcalims->DATA;
                       inserappel(ptroot,ptccol,ptccell,ptcon_lo,ptalim_ph);
                       }
                   /* creer une chain_liste pour ranger les alims E/W a Y != (par 2) */
                   ptcalims = mkalims_list(ptcon_ph);
                   /* pour chaque couple d'alims insertalim */
                   for (;ptcalims;ptcalims=ptcalims->NEXT)
                       {
                       ptalim_ph = (phcon_list *)ptcalims->DATA;
                       insertalim(ptroot,ptccol,ptccell,ptcon_lo,ptalim_ph);
                       }
                   }
                }
             else
                {
                ptcon_ph = listphcon(ptinsf_ph,ptcon_lo->NAME);
                ptref_ph = listphref(ptinsf_ph,ptcon_lo->NAME);
                if ((ptcon_ph==NULL)&&(ptref_ph==NULL))
                   {
                   printf("Error: No physical connector corresponding to %s in figure %s\n",ptcon_lo->NAME,ptcell->FIGNAME);
                   exit(1);
                   }
                else 
                   {
                   ptcon = insertcon(ptccol,ptccell,ptcon_lo,ptref_ph,ptcon_ph);
                   (void *)insertsig(ptcol,ptroot,ptcon,ptcon_lo->SIG);
                   }
                }
             if (ptcon_ph)
                {
                for (ptauxcon_ph=ptcon_ph;ptauxcon_ph->NEXT;
                     ptauxcon_ph=ptauxcon_ph->NEXT);
                ptauxcon_ph->NEXT = ptsavecon_ph;
                ptsavecon_ph = ptcon_ph;
                }
             if (ptref_ph)
                {
                for (ptauxref_ph=ptref_ph;ptauxref_ph->NEXT;
                     ptauxref_ph=ptauxref_ph->NEXT);
                ptauxref_ph->NEXT = ptsaveref_ph;
                ptsaveref_ph = ptref_ph;
                }
             }
         if (ptinsf_ph->PHCON)
            {
            for (ptauxcon_ph=ptinsf_ph->PHCON;ptauxcon_ph;
                 ptauxcon_ph=ptauxcon_ph->NEXT)
                {
                printf("Error: No logical connector corresponding to %s in figure %s\n",ptauxcon_ph->NAME,ptcell->FIGNAME);
                }
            exit(5);
            }
         else
            {
            ptinsf_ph->PHCON = ptsavecon_ph;
            }
         if (ptinsf_ph->PHREF)
            {
            for (ptauxref_ph=ptinsf_ph->PHREF;ptauxref_ph;
                 ptauxref_ph=ptauxref_ph->NEXT)
                {
                if (ptauxref_ph->FIGNAME==ref_con)
                   {
                   printf("Error: No logical connector corresponding to %s in figure %s\n",
                          ptauxref_ph->NAME,ptcell->FIGNAME);
                   exit(5);
                   }
                }
/* recuperation des NWELL du model de l'instance en cours de traitement */
            insertnwell(ptccol,ptccell,ptinsf_ph->PHREF);
            for (ptauxref_ph=ptinsf_ph->PHREF;ptauxref_ph->NEXT;
                 ptauxref_ph=ptauxref_ph->NEXT);
            ptauxref_ph->NEXT = ptsaveref_ph;
            ptsaveref_ph = ptinsf_ph->PHREF;
            ptinsf_ph->PHREF = ptsaveref_ph;
            } 
         else
            {
            ptinsf_ph->PHREF = ptsaveref_ph;
            }

/* former la liste des connecteurs ct, df et alims de la colonne */
         for (ptccon_d->NEXT=ptcell->DF_CON;ptccon_d->NEXT;ptccon_d=ptccon_d->NEXT);
         ptccon_d->NEXT = addchain(ptccon_d->NEXT,(void *)NULL);
         ptccon_d = ptccon_d->NEXT;

         for (ptccon_c->NEXT=ptcell->CT_CON;ptccon_c->NEXT;ptccon_c=ptccon_c->NEXT);
         ptccon_c->NEXT = addchain(ptccon_c->NEXT,(void *)NULL);
         ptccon_c = ptccon_c->NEXT;

         for (ptcalim->NEXT=ptcell->ALIMS;ptcalim->NEXT;ptcalim=ptcalim->NEXT);
         ptcalim->NEXT = addchain(ptcalim->NEXT,(void *)NULL);
         ptcalim = ptcalim->NEXT;

/* recuperation des transparences du model de l'instance en cours de traitement */
         for (ptseg_ph=ptinsf_ph->PHSEG;ptseg_ph;ptseg_ph=ptseg_ph->NEXT)
             {
             if (ptseg_ph->LAYER == (char)TALU2)
                {
                inserttrans(ptcol,ptcell,ptseg_ph);
                }
             }
         }
/* pour insertlin dans dprlin.c, USER de la colonne doit pointer sur les DF_CON */
     ptcol->USER = ptcol->DF_CON->NEXT;
     }

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de sigconfils : \n");
# endif
 
 }

/***************************************************************************
**               fonction sigconpere()                                    **
***************************************************************************/
 void sigconpere(ptlofig,ptphfig,ptdprfig)
 lofig_list *ptlofig;
 phfig_list *ptphfig;
 FIGURE     *ptdprfig;
 
 {
 chain_list *ptccolr=NULL;
 chain_list *ptccoll=NULL;
 chain_list *ptccol=NULL;
 COLUMN     *ptcolr=NULL;
 COLUMN     *ptcoll=NULL;
 COLUMN     *ptcol=NULL;
 chain_list *ptccon=NULL;
 chain_list *ptccon1=NULL;
 chain_list *ptccon_ph=NULL;
 chain_list *ptcsig=NULL;
 phcon_list *ptcon_ph=NULL;
 locon_list *ptcon_lo=NULL;
 ptype_list *pttype=NULL;
 SIGNAL        *ptsig =NULL;
 CONNECTOR     *ptcon =NULL;
 POSSIBILITY   *ptpos =NULL;
 char  orient=(char )NULL;
 long  xo=MAXINT,yo=MAXINT,x=0;
 char          *vdd=NULL,*vss=NULL;

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Entree de sigconpere : \n");
# endif

 vdd = namealloc("vdd");
 vss = namealloc("vss");

 for (ptccolr=ptdprfig->COL;ptccolr->NEXT;ptccolr=ptccolr->NEXT);	
 ptcolr = (COLUMN *)ptccolr->DATA;
 ptccoll = ptdprfig->COL;
 ptcoll = (COLUMN *)ptccoll->DATA;

 for (ptcon_lo=ptlofig->LOCON;ptcon_lo;ptcon_lo=ptcon_lo->NEXT)
     {
     if (!strncmp(ptcon_lo->NAME,vdd,3)||!strncmp(ptcon_lo->NAME,vss,3))
        {
        pttype = getptype(ptcon_lo->USER,(long )SESAME);
        if (pttype) /* c.a.d alim place: rappel d'alim */
           for (ptccon_ph=pttype->DATA;ptccon_ph;ptccon_ph=ptccon_ph->NEXT) 
               {
               ptcon = mkcon(NULL,NULL,ptcon_lo->NAME,EXTERN);
               ptdprfig->ALIM = addchain(ptdprfig->ALIM,(void *)ptcon);
               ptcon_ph = (phcon_list *)ptccon_ph->DATA;
               ptcon->POS = addpos(ptcon->POS,ptcon_ph->XCON,ptcon_ph->YCON,
                                   ptcon_ph->LAYER,ptcon_ph->ORIENT,TYPEFIX,
                                   FTRACK,ptcon_ph->WIDTH,ptcon);
               ptcon->NBPOSS = ptcon->NBPOSS + 1;
               ptcon->MINPOS = ptcon_ph->YCON;
               ptcon->MAXPOS = ptcon_ph->YCON;
               x = ((POSSIBILITY *)ptcon->POS->DATA)->X;
               orient = ptcon_ph->ORIENT;
               if ((orient==NORTH)||(orient==SOUTH))
                  {
                  /* boucle de recherche de la colonne pour le connecteur donne*/ 
                  for (ptccol=ptdprfig->COL;ptccol->NEXT;
                       ptccol=ptccol->NEXT->NEXT)
                      {
                      ptcol = (COLUMN *)ptccol->DATA;
                      if ((ptcol->X<x)&&((ptcol->X+ptcol->WIDTH)>x))
                         break;
                      }  
                  if (ptccol->NEXT) /* c.a.d connecteur dans une colonne O */
                     {
                     printf("Error: Refresh Alim %s terminal must be in a Channel!!\n",
                             ptcon_lo->NAME);
                     exit(3);
                     }
                  }
               else
                  {
                  printf("Error: Refresh Alim %s terminal must be North or South!!\n",
                          ptcon_lo->NAME);
                  exit(3);
                  } 
               }
        continue;
        }
     pttype = getptype(ptcon_lo->USER,(long )SESAME);
     if (pttype) /* c.a.d place */
        for (ptccon_ph=pttype->DATA;ptccon_ph;ptccon_ph=ptccon_ph->NEXT) 
            {
            ptcon = mkcon(NULL,NULL,ptcon_lo->NAME,EXTERN);
            ptdprfig->CON = addchain(ptdprfig->CON,(void *)ptcon);
            ptcon_ph = (phcon_list *)ptccon_ph->DATA;
            ptcon->POS = addpos(ptcon->POS,ptcon_ph->XCON,ptcon_ph->YCON,
                                ptcon_ph->LAYER,ptcon_ph->ORIENT,TYPEFIX,
                                FTRACK,ptcon_ph->WIDTH,ptcon);
            ptcon->NBPOSS = ptcon->NBPOSS + 1;
            ptcon->MINPOS = ptcon_ph->YCON;
            ptcon->MAXPOS = ptcon_ph->YCON;
            x = ((POSSIBILITY *)ptcon->POS->DATA)->X;
            orient = ptcon_ph->ORIENT;
            if (orient==EAST)
               {
               ptcon->COL = ptccolr; 
               ((POSSIBILITY *)ptcon->POS->DATA)->X = x - ptcolr->X;
               ptcolr->DF_CON = addchain(ptcolr->DF_CON,(void *)ptcon);
               ptcsig = insertsig(ptcolr,ptdprfig,ptcon,ptcon_lo->SIG);
               }
            else 
               if (orient==WEST)
                  {
                  ptcon->COL = ptccoll;
                  ((POSSIBILITY *)ptcon->POS->DATA)->X = x - ptcoll->X;
                  ptcoll->DF_CON = addchain(ptcoll->DF_CON,(void *)ptcon);
                  ptcsig = insertsig(ptcoll,ptdprfig,ptcon,ptcon_lo->SIG);
                  }
               else /* c.a.d NORTH/SOUTH */
                  {
                  /* boucle de recherche de la colonne pour le connecteur donne*/ 
                  for (ptccol=ptdprfig->COL;ptccol->NEXT;
                       ptccol=ptccol->NEXT->NEXT)
                      {
                      ptcol = (COLUMN *)ptccol->DATA;
                      if ((ptcol->X<x)&&((ptcol->X+ptcol->WIDTH)>x))
                         break;
                      }  
                  if (ptccol->NEXT) /* c.a.d connecteur dans une colonne O */
                     {
                     ptcon->COL = ptccol;
                     ((POSSIBILITY *)ptcon->POS->DATA)->X = x - ptcol->X;
                     ptcol->CT_CON = addchain(ptcol->CT_CON,(void *)ptcon);
                     ptcsig = insertsig(ptcol,ptdprfig,ptcon,ptcon_lo->SIG);
                     }
                  else /* c.a.d connecteur dans une colonne C */
                     {
                     ptcsig = insertsig(NULL,ptdprfig,ptcon,ptcon_lo->SIG);
                     }
                  }
            }
     else /* connecteur pas place: on le met dans la figure */
        {
        ptcon = mkcon(NULL,NULL,ptcon_lo->NAME,EXTERN);
        ptdprfig->CON = addchain(ptdprfig->CON,(void *)ptcon);
        ptcon->POS = addpos(ptcon->POS,xo,yo,(char)ALU2,ORIENTX,TYPEFIX,
                            FTRACK,WLAYER2,ptcon);
        ptcon->NBPOSS = ptcon->NBPOSS + 1;
        ptcsig = insertsig(NULL,ptdprfig,ptcon,ptcon_lo->SIG);
        }
     }

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de sigconpere : \n");
# endif

 }

/****************************************************************
**  placeconpere():placement des Connecteur du pere non places **
**  par le concepteur ou places N/S dans un canal.             **
**  cette fonction est appele apres un eventuel optiplce       **
****************************************************************/
 void     placeconpere(ptdprfig)
 FIGURE  *ptdprfig;

 {
 chain_list  *ptccon=NULL;
 chain_list  *ptccon1=NULL;
 chain_list  *ptccolr=NULL;
 chain_list  *ptccoll=NULL;
 chain_list  *ptccol=NULL;
 CONNECTOR   *ptcon=NULL;
 CONNECTOR   *ptcon1=NULL;
 POSSIBILITY *ptpos=NULL;
 SIGNAL      *ptsig=NULL;
 COLUMN      *ptcol=NULL;
 COLUMN      *ptcolr=NULL;
 COLUMN      *ptcoll=NULL;
 LINE        *ptlincour=NULL;
 TRACK       *pttrack=NULL;
 CHANNEL     *ptchannel=NULL;
 char        *vdd=NULL;
 char        *vss=NULL;
 long         x=0;
 long         i=0;
 long         index_col=0;

 vdd = namealloc("vdd");
 vss = namealloc("vss");

 ptccoll = ptdprfig->COL;
 for(ptccolr=ptccoll;ptccolr->NEXT;ptccolr=ptccolr->NEXT);
 ptcoll = (COLUMN *)ptccoll->DATA;
 ptcolr = (COLUMN *)ptccolr->DATA;

 for (ptccon=ptdprfig->CON;ptccon;ptccon=ptccon->NEXT)
     {
     ptcon = (CONNECTOR *)ptccon->DATA;
     if (!strncmp(ptcon->NAME,vdd,3)||!strncmp(ptcon->NAME,vss,3)||(ptcon->COL))
        continue;
     ptpos = (POSSIBILITY *)ptcon->POS->DATA;
     if (ptpos->ACCES == ORIENTX) /* c.a.d Connecteur DF non place */
        {
        ptsig = (SIGNAL *)ptcon->SIG->DATA;
        if ((ptsig->MIN_COL - ptcoll->INDEX) <=
            (ptcolr->INDEX - ptsig->MIN_COL - ptsig->WIDTH))
           {
           ptcon->COL = ptccoll;
           ptcol = ptcoll;
           ptcol->DF_CON = addchain(ptcol->DF_CON,(void *)ptcon);
           ptsig->WIDTH = (ptsig->MIN_COL==MAXINT)?0:
                           ptsig->MIN_COL + ptsig->WIDTH - ptcol->INDEX;
           index_col = ptsig->MIN_COL;
           ptsig->MIN_COL = ptcol->INDEX;
           ptpos->ACCES = WEST;
           ptpos->X = 0;
           }
        else
           {
           ptcon->COL = ptccolr;
           ptcol = ptcolr;
           ptcol->DF_CON = addchain(ptcol->DF_CON,(void *)ptcon);
           index_col = ptsig->MIN_COL + ptsig->WIDTH;
           ptsig->MIN_COL = (ptsig->MIN_COL==MAXINT)?ptcol->INDEX:ptsig->MIN_COL;
           ptsig->WIDTH = ptcol->INDEX - ptsig->MIN_COL;
           ptpos->ACCES = EAST;
           ptpos->X = 0;
           }
        if (!existsig(ptcol->SIG,ptsig))
           {
           ptsig->COL = addchain(ptsig->COL,(void *)ptcol);
           ptcol->SIG = addchain(ptcol->SIG,(void *)ptsig);
           }

/* Placement des connecteurs du pere non places aux y du gab de la ligne */
        for (ptccon1=ptsig->CON;ptccon1;ptccon1=ptccon1->NEXT)
            {
            ptcon1 = (CONNECTOR *)ptccon1->DATA;
            if (!ptcon1->COL)
               continue;
            if ((ptcon1->LIN)&&(((COLUMN *)ptcon1->COL->DATA)->INDEX==index_col))
               break;
            }
        if ((ptccon1)&&(ptcon1->COL))
           { 
           ptcon->LIN = ptcon1->LIN;
           ptlincour = (LINE *)ptcon->LIN->DATA;
           ptlincour->CON = addchain(ptlincour->CON,(void *)ptcon);
           pttrack = ptlincour->GAB->TRACK->NEXT;
           ptpos->Y = pttrack->Y ;
           ptcon->MINPOS = dpr_min(ptcon->MINPOS,pttrack->Y);
           ptcon->MAXPOS = dpr_max(ptcon->MAXPOS,pttrack->Y);
           for (pttrack=pttrack->NEXT;pttrack;pttrack=pttrack->NEXT)
               {
               ptcon->POS->NEXT = addpos(ptcon->POS->NEXT,ptpos->X,pttrack->Y,
                                         ptpos->LAYER,ptpos->ACCES,ptpos->TYPE,
                                         ptpos->TRACK,ptpos->WIDTH,ptcon);
               ptcon->NBPOSS = ptcon->NBPOSS + 1;
               ptcon->MINPOS = dpr_min(ptcon->MINPOS,pttrack->Y);
               ptcon->MAXPOS = dpr_max(ptcon->MAXPOS,pttrack->Y);
               }
           }
        else
           {
           /*printf("Warning: Connecteur %s unique et non place!!\n",ptcon->NAME);*/
           }
        }
     else /* c.a.d connecteur place N/S ==>> connnecteur dans canal */
        {
        x = ptpos->X;
        /* boucle de recherche du canal pour le connecteur donne*/ 
        for (ptccol=ptdprfig->COL->NEXT;ptccol;ptccol=ptccol->NEXT->NEXT)
            {
            ptcol = (COLUMN *)ptccol->DATA;
            if ((ptcol->X<=x)&&((ptcol->X+ptcol->WIDTH)>=x))
               break;
            }  
        if (ptcol->TYPE!='C')
           {
           printf("BUG: Channel of the terminal %s not found!!\n",ptcon->NAME);
           exit(8);
           }
        ptsig = (SIGNAL *)ptcon->SIG->DATA;
        if (ptsig->WIDTH==0)
           {
           if ((ptcol->INDEX!=ptsig->MIN_COL-1)&&
               (ptcol->INDEX!=ptsig->MIN_COL+ptsig->WIDTH+1))
              {
              printf("Warning: External North/South terminal %s replaced!\n",ptcon->NAME);
              for (ptccol=ptdprfig->COL->NEXT;ptccol;ptccol=ptccol->NEXT->NEXT)
                  {
                  ptcol = (COLUMN *)ptccol->DATA;
                  if (ptcol->INDEX==ptsig->MIN_COL-1)
                     break;
                  }
              }
           }
        else
           {
           if ((ptcol->INDEX<ptsig->MIN_COL)||
               (ptcol->INDEX>ptsig->MIN_COL+ptsig->WIDTH))
              {
              printf("Warning: External North/South terminal %s replaced!\n",ptcon->NAME);
              for (ptccol=ptdprfig->COL->NEXT;ptccol;ptccol=ptccol->NEXT->NEXT)
                  {
                  ptcol = (COLUMN *)ptccol->DATA;
                  if (ptcol->INDEX==ptsig->MIN_COL+1)
                     break;
                  }
              }
           } 
 /* le connecteur est mis dans son canal d'origine ou choisi par le routeur*/
        ptcon->COL = ptccol;
        if (ptpos->ACCES==NORTH)
           ptpos->Y = ptcol->Y + ptcol->HEIGHT;
        else
           ptpos->Y = ptcol->Y;
        ptpos->X = 0;
        ptchannel = (CHANNEL *)ptcol->DF_CON->DATA;
        (void *)insertcon_inchan(ptchannel,ptpos->ACCES,ptsig->INDEX,0);
        }
     }

 /* traitement des rappels d'alimentations */
 for (ptccon=ptdprfig->ALIM;ptccon;ptccon=ptccon->NEXT)
     {
     ptcon = (CONNECTOR *)ptccon->DATA;
     ptpos = (POSSIBILITY *)ptcon->POS->DATA;
     x = ptpos->X;
     /* boucle de recherche du canal pour le connecteur donne*/ 
     for (ptccol=ptdprfig->COL->NEXT;ptccol;ptccol=ptccol->NEXT->NEXT)
         {
         ptcol = (COLUMN *)ptccol->DATA;
         if ((ptcol->X<=x)&&((ptcol->X+ptcol->WIDTH)>=x))
            break;
         }
     if (!ptccol) /* c.a.d pas de canal correspondant */
        {
        for (ptccol=ptdprfig->COL->NEXT;ptccol;ptccol=ptccol->NEXT->NEXT)
            {
            ptcol = (COLUMN *)ptccol->DATA;
            if (ptcol->X>=x)
               break;
            }
        }
/* le connecteur est mis dans son canal d'origine ou choisi par le routeur*/
     ptcon->COL = ptccol;
     if (ptpos->ACCES==NORTH)
        ptpos->Y = ptcol->Y + ptcol->HEIGHT;
     else
        ptpos->Y = ptcol->Y;
     ptpos->X = 0;
     ptcol->ALIMS = addchain(ptcol->ALIMS,(void *)ptcon);
     }
 }

