/********************************************************************
*                                                                   *
* 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: load_R.c                                         *
*       version : 3.0                                                            *
*       date    : 17/03/92                                                       *
*********************************************************************************/
#include "dpr_R.h"
#include "util_R.h"
extern  void sigconfils();  /*actually in sig_R.c*/
extern  void sigconpere();  /*actually in sig_R.c*/

/*******************************************************************************
* checkname : check for busses                                                 *
*******************************************************************************/
 char *checkname(name)
 char *name;
 {
 char *s, *t;

   s = t = name;
   while (*t) {
      if (*t == '[')
         *t = ' ';
      else if (*t == ']')
         if (*(++t) == '\0') /* ok, it's finished */
				goto end;
         else if (*t == '[') /* multiple array */
            continue;
      *s++ = *t++;
   }
 end:
	*s = '\0';
	return name;
 }
/*****************************************************************************
* calcule si deux segments se touchent et renvoi 1 si oui sinon 0            *
*****************************************************************************/
 int     inter(min1,max1,min2,max2)
 long            min1,max1,min2,max2;

 {
 if ((min1<=max2)&&(min2<=max1))
    {
    return(1);
    }
 else
    {
    return(0);
    }
 }

/*****************************************************************************
* horv:calcule l'orientation du model H ou V en se basant sur l'orientation  *
* des connecteurs VDD* et VSS* en ALU2                                       *
*****************************************************************************/
 char    horv(ptfigf_ph)
 phfig_list      *ptfigf_ph;

 {
 char            *vdd,*vss;
 phcon_list      *ptcon;

 vdd=namealloc("vdd");
 vss=namealloc("vss");
 for (ptcon=ptfigf_ph->PHCON;ptcon;ptcon=ptcon->NEXT)
     {
     if ((!strncmp(vdd,ptcon->NAME,3))||(!strncmp(vss,ptcon->NAME,3)))
        {
        if (ptcon->LAYER==(char)ALU2)
           {
           if ((ptcon->ORIENT=='E')||(ptcon->ORIENT=='W'))
              {
              return('H');
              break;
              }
           else
              {
              if ((ptcon->ORIENT=='N')||(ptcon->ORIENT=='S'))
                 {
                 return('V');
                 break;
                 }
              else
                 {
                 printf("Error: Alim orientation %c not valid\n",ptcon->ORIENT);
                 exit(1);
                 }
              }
           }
        }
     }
 if (ptcon==NULL)
    {
    printf("Error: ALU2 alim terminals do not exist in %s\n",ptfigf_ph->NAME);
    exit(1);
    }
 }

/*****************************************************************************
* unifsegs:unifie les segments ALLOWM2 de bonne orientation du model pour    *
* simplifier le calcul d'acces des references                                *
*****************************************************************************/
 void    unifsegs(ptfigf_ph,orientation)
 phfig_list      *ptfigf_ph;
 char            orientation;

 {
 phseg_list      *ptseg1=NULL;
 phseg_list      *ptseg2=NULL;
 phseg_list      *ptsegtmp=NULL;
 
 for (ptseg1=ptfigf_ph->PHSEG;ptseg1;ptseg1=ptseg1->NEXT)
     {
     if (ptseg1->LAYER==(char)TALU2)
        {
        if (manorme(ptseg1->TYPE)==orientation)
           {
           for (ptseg2=ptseg1->NEXT;ptseg2;ptseg2=ptsegtmp)
               {
               ptsegtmp = ptseg2->NEXT;
               if (ptseg2->LAYER==(char)TALU2)
                  {
                  if (manorme(ptseg2->TYPE)==orientation)
                     {
                     if (orientation=='V')
                        {
                        if (ptseg2->X1==ptseg1->X1)
                           {
                           if (inter(ptseg1->Y1,ptseg1->Y2,ptseg2->Y1,ptseg2->Y2)==1)
                              {
                              ptseg1->Y1=dpr_min(ptseg1->Y1,ptseg2->Y1);
                              ptseg1->Y2=dpr_max(ptseg1->Y2,ptseg2->Y2);
                              delphseg(ptfigf_ph,ptseg2);
                              }
                           }
                        }
                     if (orientation=='H')
                        {
                        if (ptseg2->Y1==ptseg1->Y1)
                           {
                           if (inter(ptseg1->X1,ptseg1->X2,ptseg2->X1,ptseg2->X2)==1)
                              {
                              ptseg1->X1=dpr_min(ptseg1->X1,ptseg2->X1);
                              ptseg1->X2=dpr_max(ptseg1->X2,ptseg2->X2);
                              delphseg(ptfigf_ph,ptseg2);
                              }
                           }
                        }
                     }
                  }
               }
           }
        else
           {
           printf("Warning: Allow-metal2 segment in %s not parallel to ALU2 alims\n",ptfigf_ph->NAME);
           }
        }
     }
 }

/*****************************************************************************
* setaccess:deduit le type d'acces de chaque ref_con et range le resultat    *
* dans le champs USER de la reference                                        *
*****************************************************************************/
 void    setaccess(ptfig_ph)
 phfig_list      *ptfig_ph;

 {
 chain_list      *ptcmodel;
 char            *ptmodel;
 char            *ref_con;
 char            *ref_ref;
 char            *nwell;
 char            *ref_type;
 char            *newrefname;
 char             orientation;
 phfig_list      *ptfigf_ph;
 phseg_list      *ptseg;
 phref_list      *ptref;
 phref_list      *ptreftmp;
 ptype_list      *ptype;
 int              nberr=0;

 ref_con = namealloc("ref_con");
 ref_ref = namealloc("ref_ref");
 nwell = namealloc("nwell");

 for (ptcmodel=ptfig_ph->MODELCHAIN;ptcmodel;ptcmodel=ptcmodel->NEXT)
     {
     ptmodel = (char *)ptcmodel->DATA;
     ptfigf_ph = getphfig(ptmodel,'P');
     orientation = horv(ptfigf_ph);
     unifsegs(ptfigf_ph,orientation);
     for (ptseg=ptfigf_ph->PHSEG;ptseg;ptseg=ptseg->NEXT)
         {
         if ((manorme(ptseg->TYPE)==orientation)&&(ptseg->LAYER==(char)TALU2))
            {
            if (orientation=='V')
               {
               if ((ptseg->Y1==ptfigf_ph->YAB1)&&(ptseg->Y2==ptfigf_ph->YAB2))
                  ref_type=namealloc("ref_a2ud");
               else
                  if ((ptseg->Y1==ptfigf_ph->YAB1)&&(ptseg->Y2<ptfigf_ph->YAB2))
                     ref_type=namealloc("ref_a2d");
                  else
                     if ((ptseg->Y1>ptfigf_ph->YAB1)&&
                         (ptseg->Y2==ptfigf_ph->YAB2))
                        ref_type=namealloc("ref_a2u");
                     else
                        {
                        printf("Warning: Allow-metal2 segment in %s not valid\n",
                               ptfigf_ph->NAME);
                        break;
                        }
               }
            if (orientation=='H')
               {
               if ((ptseg->X1==ptfigf_ph->XAB1)&&(ptseg->X2==ptfigf_ph->XAB2))
                  ref_type=namealloc("ref_a2rl");
               else
                  if ((ptseg->X1==ptfigf_ph->XAB1)&&(ptseg->X2<ptfigf_ph->XAB2))
                     ref_type=namealloc("ref_a2l");
                  else
                     if ((ptseg->X1>ptfigf_ph->XAB1)&&
                         (ptseg->X2==ptfigf_ph->XAB2))
                        ref_type=namealloc("ref_a2r");
                     else
                        {
                        printf("Warning: Allow-metal2 segment in %s not valid\n",
                               ptfigf_ph->NAME);
                        break;
                        }
               }
            for (ptref=ptfigf_ph->PHREF;ptref;ptref=ptreftmp)
                {
                ptreftmp = ptref->NEXT;
                if (ptref->FIGNAME==ref_con)
                   {
                   newrefname = namealloc(checkname(ptref->NAME));/* tmp */
                   ptref->NAME = newrefname;/* tmp */
                   if (orientation=='V')
                      {
                      if ((ptref->XREF==ptseg->X1)&&(ptref->YREF>=ptseg->Y1)&&
                          (ptref->YREF<=ptseg->Y2))
                         {
                         ptref->USER = addptype(ptref->USER,
                                                (long)SETACCESS,(void *)ref_type);
                         }
                      }
                   if (orientation=='H')
                      {
                      if ((ptref->YREF==ptseg->Y1)&&(ptref->XREF>=ptseg->X1)&&
                          (ptref->XREF<=ptseg->X2))
                         {
                         ptref->USER = addptype(ptref->USER,
                                                (long)SETACCESS,(void *)ref_type);
                         }
                      }
                   }
                else
                   {
                   if ((ptref->FIGNAME!=ref_ref)||(strncmp(ptref->NAME,nwell,5)))
                      {
                      delphref(ptfigf_ph,ptref);
                      }
                   }
                }
            }
         }
     for (ptref=ptfigf_ph->PHREF;ptref;ptref=ptref->NEXT)
         {
         if (ptref->FIGNAME==ref_con)
            {
            ptype = getptype(ptref->USER,(long)SETACCESS);
            if (ptype == NULL)
               {
               printf("Error: the virtual terminal %s in %s is not valid\n",
                      ptref->NAME,ptfigf_ph->NAME);
               nberr++;
               }
            }
         }
     }
 if (nberr!=0)
    {
    printf("sorry, can not continue!!\n");
    exit(1);
    }
 }

/*****************************************************************************
*  concompare: verifie la coherence ph_lo des connecteurs                    *
*****************************************************************************/
 long	concompare(ptphcon,ptlocon)
 phcon_list	*ptphcon;
 locon_list	*ptlocon;

 {
 phcon_list	*ptcphcon,*ptcorphcon;
 locon_list	*ptclocon;
 int		trouve;
 ptype_list	*ptype = NULL;
 chain_list	*ptchain = NULL;
 char		*vdd,*vss;
 long		nberr=0;

 vdd = namealloc("vdd");
 vss = namealloc("vss");
 for (ptclocon=ptlocon;ptclocon;ptclocon=ptclocon->NEXT)
     {
     trouve = 0;
     for (ptcphcon=ptphcon;ptcphcon;ptcphcon=ptcphcon->NEXT)
         {
         if (ptcphcon->NAME==ptclocon->NAME)
            {
            trouve = 1;
            ptcphcon->USER = addptype(ptcphcon->USER,(long)SESAME,(void *)'y');
            ptchain=addchain(ptchain,(void *)ptcphcon);
            }
         }
     if (trouve != 1)
        {
        if ((ptclocon->NAME!=vdd) && (ptclocon->NAME!=vss))
           printf("Warning: No physical connector corresponding to %s\n",
                   ptclocon->NAME);
        }
     else
        {
        ptclocon->USER = addptype(ptclocon->USER,(long)SESAME,(void *)ptchain);
        }
     ptype = getptype(ptclocon->USER,(long)SESAME);
     if (ptype == NULL)
        {
        /*printf("le connecteur %s aura la position X\n",ptclocon->NAME);*/
        }
     else
        {
        /*printf("le connecteur %s aura la (les) position(s):\n",ptclocon->NAME);*/
        for (ptchain=(chain_list *)ptype->DATA;ptchain;ptchain=ptchain->NEXT)
            {
            ptcorphcon = (phcon_list *)ptchain->DATA;
            /*printf("con orient: %c\n",ptcorphcon->ORIENT);*/
            }
        }
     }

 for (ptcphcon=ptphcon;ptcphcon;ptcphcon=ptcphcon->NEXT)
     {
     ptype = getptype(ptcphcon->USER,(long)SESAME);
     if (ptype == NULL)
        {
        printf("Error: no logical connector corresponding to %s\n",
               ptcphcon->NAME);
        nberr++;
        }
     }
 return(nberr);
 }

/*****************************************************************************
*  inscompare: verifie la coherence ph_lo des instances                      *
*****************************************************************************/
 long	inscompare(ptphins,ptloins)
 phins_list	*ptphins;
 loins_list	*ptloins;

 {
 phins_list	*ptcphins;
 loins_list	*ptcloins;
 ptype_list	*ptype;
 long		nberr=0;

 for (ptcloins=ptloins;ptcloins;ptcloins=ptcloins->NEXT)
     {
     for (ptcphins=ptphins;ptcphins;ptcphins=ptcphins->NEXT)
         {
         if (ptcphins->INSNAME==ptcloins->INSNAME)
            {
            ptcphins->USER = addptype(ptcphins->USER,(long)SESAME,(void *)'y');
            break;
            }
         }
     if (ptcphins == NULL)
        {
        printf("Error: no physical instance corresponding to %s\n",
               ptcloins->INSNAME);
        nberr++;
        }
     }

 for (ptcphins=ptphins;ptcphins;ptcphins=ptcphins->NEXT)
     {
     ptype = getptype(ptcphins->USER,(long)SESAME);
     if (ptype == NULL)
        {
        printf("Error: no logical instance corresponding to %s\n",
               ptcphins->INSNAME);
        nberr++;
        }
     }
 return(nberr);
 }

/*****************************************************************************
*  sigcheck: verifie la coherence et la consistance des signaux              *
*****************************************************************************/
 long	sigcheck(ptfig_lo)
 lofig_list	*ptfig_lo;

 {
 long		 nberr=0;
 losig_list	*ptclosig,*ptlosig,*ptnewlosig;
 locon_list	*ptlocon;
 ptype_list	*ptype = NULL;
 chain_list	*ptchain = NULL;
 long		 nbcon = 0;
 long		 nbconex = 0;

 ptlosig = ptfig_lo->LOSIG;
 for (ptclosig=ptlosig;ptclosig;ptclosig=ptclosig->NEXT)
     {
    /*if (DEBUG_SESAME) printf("father fig sig name: %s\n",getsigname(ptclosig));*/
     ptype = getptype(ptclosig->USER,(long)LOFIGCHAIN);
     nbcon = 0;
     nbconex = 0;
     for (ptchain=(chain_list *)ptype->DATA;ptchain;ptchain=ptchain->NEXT)
         {
         ptlocon = (locon_list *)ptchain->DATA;
         /*if (DEBUG_SESAME) printf("con name: %s\n",ptlocon->NAME);*/
         if (ptlocon->TYPE == 'I')
            {
            /*if (DEBUG_SESAME) printf("his ins name: %s\n",(char *)((loins_list *)(ptlocon->ROOT))->INSNAME);*/
            }
         else
            {
            /*if (DEBUG_SESAME) printf("his fig name: %s\n",(char *)((lofig_list *)(ptlocon->ROOT))->NAME);*/
            nbconex++;
            }
         ptnewlosig = ptlocon->SIG;
         /*if (DEBUG_SESAME) printf("his sig name: %s\n",getsigname(ptnewlosig));*/
         nbcon++;
         }
     if (nbconex > 1)
        {
        printf("Error: signal %s connected to more than one external logical terminal!!\n",
                getsigname(ptclosig));
        nberr++;
        }
     if (nbcon < 2)
        {
        printf("Warning: signal %s not connected to any other terminal!!\n",
                getsigname(ptclosig));
        }
     }
 return(nberr);
 }

/*****************************************************************************
* sesame: calcule le nb d'erreurs apres verification de la coherence des     *
* connecteurs, des instances et des signaux du pere                          *
*****************************************************************************/
 void	sesame(ptfig_ph,ptfig_lo)
 phfig_list	*ptfig_ph;
 lofig_list	*ptfig_lo;

 {
 phcon_list	*ptphcon;
 locon_list	*ptlocon;
 phins_list	*ptphins;
 loins_list	*ptloins;
 long		 nberr=0;

 if ((ptfig_ph->PHSEG!=NULL)||(ptfig_ph->PHVIA!=NULL)||(ptfig_ph->PHREF!=NULL))
    {
    printf("Error: segment, via and reference lists of figure must be NULL!!\n");
    exit(1);
    }

 lofigchain(ptfig_lo);
 ptphcon = ptfig_ph->PHCON;
 ptlocon = ptfig_lo->LOCON;
 ptphins = ptfig_ph->PHINS;
 ptloins = ptfig_lo->LOINS;
 nberr = concompare(ptphcon,ptlocon);
 nberr = nberr + inscompare(ptphins,ptloins);
 nberr = nberr + sigcheck(ptfig_lo);
 if (nberr != 0)
    {
    printf("sorry, can not continue because of %ld errors !!!\n",nberr);
    exit(1);
    }
 }

/************************************************************************
*    fonction addcol(): creation et ajout d'une nouvelle colonne        *
************************************************************************/
 chain_list	*addcol(pthead,type,x1,y1,x2,y2)
 chain_list	*pthead;
 char		 type;
 long		 x1,y1,x2,y2;

 {
 COLUMN          *ptnewcol;

 ptnewcol               =(COLUMN *)mbkalloc(sizeof(COLUMN));
 ptnewcol->NAME         =NULL;
 ptnewcol->TYPE         =type;
 ptnewcol->X		=x1;
 ptnewcol->Y		=y1;
 ptnewcol->WIDTH	=x2-x1;
 ptnewcol->S_WIDTH      =0;
 ptnewcol->HEIGHT	=y2-y1;
 ptnewcol->S_HEIGHT     =0;
 ptnewcol->INDEX	=0;
 ptnewcol->SIG		=NULL;
 if (type=='C')
    ptnewcol->DF_CON    =(chain_list *)addchannel(NULL,NULL,NULL,NULL,NULL);
 else
    ptnewcol->DF_CON    =NULL;
 ptnewcol->CT_CON	=NULL;
 ptnewcol->ALIMS	=NULL;
 ptnewcol->INS		=NULL;
 ptnewcol->VIA		=NULL;
 ptnewcol->SEG		=NULL;
 ptnewcol->ALLOW	=NULL;
 ptnewcol->RDATA	=NULL;
 ptnewcol->ALLOWUSED	=NULL;
 ptnewcol->USER	 	=NULL;
 
 return(addchain(pthead,(void *)ptnewcol));
 }

/************************************************************************
*		fonction	mkcolumns()				*
* creer les differentes lignes  a partir des fils directs apres flatten *
************************************************************************/
 void		mkcolumns(ptfig_ph,ptfig)

 phfig_list	*ptfig_ph;
 FIGURE	        *ptfig;

 {
 phfig_list	*ptfigf_ph;
 phins_list	*ptins;
 COLUMN		*ptcol,*ptnextcol;
 chain_list	*ptccol,*ptsav,*pthead,*ptnext,*ptfree;
 long		 xab2,xab1,yab2,yab1;
 long		 x1col,x2col;
 long		 y1ins,y2ins,x1ins,x2ins;
 long		 x1next,x2next;
 long		 xleft,xright;
 long             xmax=MINLONG,ymax=MINLONG,xmin=MAXLONG,ymin=MAXLONG;
 int              index = 0;

 xab1=ptfig_ph->XAB1;
 xab2=ptfig_ph->XAB2;
 yab1=ptfig_ph->YAB1;
 yab2=ptfig_ph->YAB2;
 if (((xab2-xab1) <= 0)||((yab2-yab1) <= 0))
    {
    printf("Error: Not valid abutment box coordinates\n");
    exit(11);
    }
 xleft  = xab1;
 xright = xab2;
 
/*  building  perephiric Right Column */
 pthead = addcol(NULL,'R',xright,yab1,xright,yab2);

/*  building  cell lines   */
 for (ptins=ptfig_ph->PHINS ; ptins ; ptins=ptins->NEXT)
     {
     ptfigf_ph=getphfig(ptins->FIGNAME,'P');
     x1ins=ptins->XINS;
     x2ins=ptins->XINS+deltab_x(ptfigf_ph->XAB1,ptfigf_ph->YAB1,ptfigf_ph->XAB2,
                                ptfigf_ph->YAB2,ptins->TRANSF);
     y1ins=ptins->YINS;
     y2ins=ptins->YINS+deltab_y(ptfigf_ph->XAB1,ptfigf_ph->YAB1,ptfigf_ph->XAB2,
                                ptfigf_ph->YAB2,ptins->TRANSF);

/* pour tester si l'abutment box englobe toutes les instances */
     xmin=dpr_min(xmin,x1ins);
     xmax=dpr_max(xmax,x2ins);
     ymin=dpr_min(ymin,y1ins);
     ymax=dpr_max(ymax,y2ins);
  
     for (ptccol=pthead;ptccol;ptccol=ptccol->NEXT)
         {
         ptcol = (COLUMN *)ptccol->DATA;
         x1col = ptcol->X;
         x2col = x1col + ptcol->WIDTH;
         if (x2col > x1ins) break;
         ptsav = ptccol;
         }
     if (x2ins <= x1col) 		    /*  insert new column  */
        {
        if (ptccol == pthead)
           {
           pthead = addcol(ptccol,'O',x1ins,yab1,x2ins,yab2);
           }
        else
           {
           ptsav->NEXT = addcol(ptccol,'O',x1ins,yab1,x2ins,yab2);
           }
        }
     else   		 		/* modify the column  */
        {
        x1col = ((x1ins < x1col) ? x1ins : x1col);
        x2col = ((x2ins > x2col) ? x2ins : x2col);
        ptcol->X = x1col;
        ptcol->WIDTH = x2col - x1col;
/*merge columns if needed*/
        for (ptnext=ptccol->NEXT;ptnext;ptnext=ptnext->NEXT)
            {
            ptnextcol = (COLUMN *)ptnext->DATA; 
            x1next = ptnextcol->X;
            x2next = x1next + ptnextcol->WIDTH;
            if (x1next < x2col)
               {
               x2col = ((x2next > x2col) ? x2next : x2col);
               ptcol->WIDTH = x2col - x1col;
               /*ptfree = ptccol->NEXT;*/
               ptccol->NEXT = ptccol->NEXT->NEXT;
               /*freechain(ptfree);*/
               }
            }
        }
     }

 if ((xmin < xab1)||(xmax > xab2)||(ymin < yab1)||(ymax > yab2))
    {
    printf("Error: All the instances must be inside the abutment box!!\n");
    exit(1);
    }

/*  building  perepherical  Left column  */
 pthead = addcol(pthead,'L',xleft,yab1,xleft,yab2);

/*  building Channel columns  */
 for (ptccol = pthead ; ptccol->NEXT ; ptccol = ptsav)
     {
     ptsav = ptccol->NEXT;
     ptcol = (COLUMN *)ptccol->DATA;
     x1col = ptcol->X + ptcol->WIDTH;
     ptnextcol = (COLUMN *)ptsav->DATA;
     x2col = ptnextcol->X;
     ptccol->NEXT = addcol(ptsav,'C',x1col,yab1,x2col,yab2);
     }
    
/*  indexing  lines  */
 for (ptccol = pthead ; ptccol ; ptccol = ptccol->NEXT)
     {
     ptcol=(COLUMN *)ptccol->DATA;
     ptcol->INDEX = ++index;
     if (ptcol->TYPE == 'C') ptcol->NAME = nameindex("DPR_C",index);
     else
      if (ptcol->TYPE == 'O') ptcol->NAME = nameindex("DPR_O",index);
      else
       if (ptcol->TYPE == 'R') ptcol->NAME = nameindex("DPR_R",index);
       else
        if (ptcol->TYPE == 'L') ptcol->NAME = nameindex("DPR_L",index);
        else
         {
         printf("BUG: Column type not valid!!\n");
         exit(3);
         }
# ifdef DEBUG_SESAME
    if (DEBUG_SESAME) 
    printf("Le nom: %s, type: %c, x: %ld, dx: %ld, y: %ld, dy: %ld, index: %d;\n"
             ,ptcol->NAME
             ,ptcol->TYPE
             ,ptcol->X
             ,ptcol->WIDTH
             ,ptcol->Y
             ,ptcol->HEIGHT
             ,ptcol->INDEX);
# endif
     }

 ptfig->COL = pthead;
 }

/************************************************************************ 
*		fonction	addins()				*
************************************************************************/
 chain_list 	*addins(pthead,insname,x,y,width,height,figname,transf)
 chain_list      *pthead;
 char		*insname;
 char		*figname;
 char		 transf;
 long		 x,y,width,height;

 {
 INSTANCE 	*ptnewcell;

 ptnewcell=(INSTANCE  *)mbkalloc(sizeof(INSTANCE ));
 ptnewcell->INSNAME=insname;
 ptnewcell->FIGNAME=figname;
 ptnewcell->X=x;
 ptnewcell->Y=y;
 ptnewcell->WIDTH=width;
 ptnewcell->HEIGHT=height;
 ptnewcell->TRANSF=transf;
 ptnewcell->DF_CON=NULL;
 ptnewcell->CT_CON=NULL;
 ptnewcell->ALIMS=NULL;
 ptnewcell->RAPPELS=NULL;
 ptnewcell->ALLOW=NULL;
 ptnewcell->N_WELL=NULL;
 ptnewcell->USER=NULL;
 
 return (addchain(pthead,(void *)ptnewcell));
 }

/************************************************************************ 
*		fonction	insertins()				*
************************************************************************/
 INSTANCE 	*insertins(ptcol,insname,x,y,width,height,figname,transf)
 COLUMN 		*ptcol;
 char		 transf;
 char		*insname;
 char		*figname;
 long		 x,y,width,height;

 {
 INSTANCE 	*ptcell=NULL;
 chain_list      *ptsavccell=NULL,*ptccell=NULL;
 char		*ptnewcell=NULL;

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Entree de insertins :(insname = %s )\n",insname);
# endif

 for (ptccell=ptcol->INS;ptccell;ptccell=ptccell->NEXT)
     {
     ptcell=(INSTANCE  *)ptccell->DATA;
     if (ptcell->Y >y)
        break;
     else
        if ((ptcell->Y==y)||((ptcell->Y + ptcell->HEIGHT)>y))
           {
           printf("Error: X or Y overlapping between instances %s and %s\n"
                  ,insname,ptcell->INSNAME);
           exit(7);
           }
     ptsavccell=ptccell;
     }
 if (ptsavccell==NULL)
    { 
    ptcol->INS=addins(ptcol->INS,insname,x,y,width,height,figname,transf);
    ptnewcell = ptcol->INS->DATA;
    }
 else 
    { 
    ptsavccell->NEXT = addins(ptsavccell->NEXT,insname,x,y,width,
                              height,figname,transf);
    ptnewcell = ptsavccell->NEXT->DATA;
    }
for (;ptccell;ptccell=ptccell->NEXT)
    {
    ptcell=(INSTANCE *)ptccell->DATA;
    if ((y+height)>ptcell->Y)
       {
       printf("Error: X or Y overlapping between instances %s and %s\n"
              ,insname,ptcell->INSNAME);
       exit(7);
       }
    else 
       if ((y+height)<ptcell->Y) break;
    }

# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de insertins :(insname = %s )\n",insname);
# endif
 
 return((INSTANCE *)ptnewcell);
 }

/************************************************************************
*	Procedure		dprcol()				*
************************************************************************/
 void  dprcol(ptfig_ph,ptfig_lo,ptroot)
 phfig_list		*ptfig_ph;
 lofig_list		*ptfig_lo;
 FIGURE	      		*ptroot;

 {
 COLUMN			*ptcol=NULL;
 INSTANCE 		*ptcell=NULL;
 chain_list		*ptccol=NULL;
 phins_list		*ptins_ph=NULL;
 phfig_list		*ptfigf_ph=NULL;
 loins_list		*ptins_lo=NULL;
 long			 xlins_col,xrins_col,yuins_col,ydins_col;
 long			 xlins_pere,xrins_pere,yuins_pere,ydins_pere;
 long			 xrcol_pere,xlcol_pere,yucol_pere,ydcol_pere;

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

/*    scan  physical instances list        */
 for (ptins_ph=ptfig_ph->PHINS;ptins_ph;ptins_ph=ptins_ph->NEXT)
     {
     ptfigf_ph=getphfig(ptins_ph->FIGNAME,'P');
     xlins_pere=ptins_ph->XINS;
     ydins_pere=ptins_ph->YINS;
     xrins_pere=xlins_pere+deltab_x(ptfigf_ph->XAB1,ptfigf_ph->YAB1,
                           ptfigf_ph->XAB2,ptfigf_ph->YAB2,ptins_ph->TRANSF);
     yuins_pere=ydins_pere+deltab_y(ptfigf_ph->XAB1,ptfigf_ph->YAB1,
                           ptfigf_ph->XAB2,ptfigf_ph->YAB2,ptins_ph->TRANSF);
/*       find corresponding line   */
     for (ptccol=ptroot->COL->NEXT->NEXT;ptccol->NEXT;ptccol=ptccol->NEXT->NEXT)
         {
         ptcol=(COLUMN *)ptccol->DATA;
         xlcol_pere=ptcol->X;
         xrcol_pere=xlcol_pere+ptcol->WIDTH;
         if ((xlcol_pere <= xlins_pere) && (xrcol_pere >= xrins_pere)) break;
         }
     if (ptccol->NEXT==NULL)
        {
        printf("BUG: there is a prroblem with mkcolumns and dprcol!!\n");
        exit(1);
        }

     xrins_col = xrins_pere - xlcol_pere;
     xlins_col = xlins_pere - xlcol_pere;
     /*       add instance in line       */
     ptcell = insertins(ptcol,ptins_ph->INSNAME,xlins_col,ydins_pere
                             ,xrins_col-xlins_col,yuins_pere-ydins_pere
		             ,ptins_ph->FIGNAME,ptins_ph->TRANSF);

     /*On garde les modeles physique et logique de l'instance*/
     ptcell->USER = addchain(ptcell->USER,(void *)ptfigf_ph);
     ptins_lo = getloins(ptfig_lo,ptins_ph->INSNAME);
     ptcell->USER = addchain(ptcell->USER,(void *)ptins_lo);
     }
# ifdef DEBUG_LOAD
    if(DEBUG_LOAD) fprintf(FOUT,"Sortie de dprcol  :\n");
# endif
 }
	
 /***********************************************************************
 *		fonction	loaddprfig()				*
 ***********************************************************************/
 FIGURE	*loaddprfig(ptname)
 char		*ptname;

 {
 FIGURE    	*ptroot=NULL;
 lofig_list	*ptfig_lo=NULL;
 lofig_list	*pttmp_lo=NULL;
 phfig_list	*ptfig_ph=NULL;
 phfig_list	*pttmp_ph=NULL;

 if(DEBUG_LOAD) printf("Go in loaddprfig: \n");

/* Liberation de la memoire occupee par la structure MBK */
/* creee par l'eventuelle etape de placement             */
 for (ptfig_ph=HEAD_PHFIG;ptfig_ph;ptfig_ph=pttmp_ph)
     {
     pttmp_ph = ptfig_ph->NEXT;
     delphfig(ptfig_ph->NAME);
     }
 for (ptfig_lo=HEAD_LOFIG;ptfig_lo;ptfig_lo=pttmp_lo)
     {
     pttmp_lo = ptfig_lo->NEXT;
     dellofig(ptfig_lo->NAME);
     }

 ptfig_lo = getlofig(ptname,'A');
 rflattenlofig(ptfig_lo,'y','y');
 ptfig_ph = getphfig(ptname,'A');
 rflattenphfig(ptfig_ph,'y','y');

 if (DEBUG_MBK_LO) viewlo() ;
 if (DEBUG_MBK_PH) viewph() ;

 printf("* Setting access types *\n");
 setaccess(ptfig_ph);
 printf("* Checking logical and physical correspondance *\n");
 sesame(ptfig_ph,ptfig_lo);

 ptroot        =(FIGURE *)mbkalloc(sizeof(FIGURE));
 ptroot->LIN   =NULL;
 ptroot->COL   =NULL;
 ptroot->SIG   =NULL;
 ptroot->CON   =NULL;
 ptroot->ALLOW =NULL;
 ptroot->ALIM  =NULL;
 ptroot->GRID  =NULL;
 ptroot->USER  =NULL;

 printf("* Making DPR data structures *\n");
 mkcolumns(ptfig_ph,ptroot);
 dprcol(ptfig_ph,ptfig_lo,ptroot);
 sigconfils(ptroot);
 sigconpere(ptfig_lo,ptfig_ph,ptroot);

/* Liberation de la memoire occupee par la structure MBK */
/* apres avoir fini la construction de la structure DPR  */
 for (ptfig_ph=HEAD_PHFIG;ptfig_ph;ptfig_ph=pttmp_ph)
     {
     pttmp_ph = ptfig_ph->NEXT;
     delphfig(ptfig_ph->NAME);
     }
 for (ptfig_lo=HEAD_LOFIG;ptfig_lo;ptfig_lo=pttmp_lo)
     {
     pttmp_lo = ptfig_lo->NEXT;
     dellofig(ptfig_lo->NAME);
     }

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

 return (ptroot);
 }
