/********************************************************************
*                                                                   *
* 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                     *
*                                                                   *
********************************************************************/
#include "dpr_R.h"
#include "util_P.h"
 
DPP_SPACE *tab[MAXLIN][MAXCOL];
DPP_DATAPATH *ptdatapath;

/***********************************************************************/
/*        makecon_fig_DF():Structure DPP_CONNECTOR pour les connecteurs*/
/*                      de la figure.                                  */   
/***********************************************************************/
DPP_CONNECTOR *makecon_fig_DF(name, j, sig)
char *name;
int j;
DPP_SIGNAL *sig;
{
DPP_CONNECTOR *ptcon=NULL;
ptcon=(DPP_CONNECTOR *)mbkalloc(sizeof(struct ADPP_CONNECTOR));
ptcon->NAME=name;
ptcon->COL=j;
ptcon->LIN=0;
ptcon->ORIENT='X';
ptcon->POS=NULL;
ptcon->SIGN=sig;
ptcon->USER=NULL;
return(ptcon);
}
/*******************************************************************/
/*        makecon_fig_CTRL():Structure DPP_CONNECTOR pour les connecteurs*/
/*                      de la figure.                              */   
/*******************************************************************/
DPP_CONNECTOR *makecon_fig_CTRL(name,ligne, orient, sig)
char *name;
int ligne;
char orient;
DPP_SIGNAL *sig;
{
DPP_CONNECTOR *ptcon=NULL;
ptcon=(DPP_CONNECTOR *)mbkalloc(sizeof(struct ADPP_CONNECTOR));
ptcon->NAME=name;
ptcon->COL=0;
ptcon->LIN=ligne;
ptcon->ORIENT=orient;
ptcon->POS=NULL;
ptcon->SIGN=sig;
ptcon->USER=NULL;
return(ptcon);
}
/****************************************************************/
/*        pos_fig():Possibilite pour un connecteur de la figure*/
/****************************************************************/
DPP_POSSIBILITY *pos_fig(x, y)
long x;
long y;
{
DPP_POSSIBILITY *ptpos=NULL;
ptpos=(DPP_POSSIBILITY *)mbkalloc(sizeof(struct ADPP_POSSIBILITY));
ptpos->XCON=x;
ptpos->YCON=y;
ptpos->LAYER=((char)ALU2);
return(ptpos);
}
/****************************************************************/
/*     is_DF():Le connecteur de la figure est-il un DATA-FLOW ? */   
/****************************************************************/
int is_DF(sig)
DPP_SIGNAL *sig;
{
chain_list *con=NULL;
DPP_CONNECTOR  *con_DF=NULL;
int flag=0;

for(con=sig->CON;con;con=con->NEXT)
   {
    con_DF=(DPP_CONNECTOR *)con->DATA;
    if(con_DF->ORIENT=='X')
      {
      flag=0;
      break;
      }
    else flag=1;
   }
return(flag);
}
   
/****************************************************************/
/*      add_con_DF():Associer le connecteur de la figure.       */   
/*                   Creation des 2 colonnes extremes pour le   */
/*                   placement des connecteurs de la figure.    */
/****************************************************************/
void add_con_DF( colonne, name, signal)
int colonne;
char *name;
DPP_SIGNAL *signal;
{
int j=0, max=0, ligne=0, y=0, x=0;
DPP_CONNECTOR *con_fig=NULL;
DPP_SPACE *ptspace=NULL;

if(colonne==0) 
   {
   tab[ligne][colonne]=ptspace;
   ptspace=makespace(name, NULL, NULL, NULL, 0, 0, 0, colonne);
   con_fig=makecon_fig_DF(name, colonne, signal);
   ptdatapath->CON=addchain(ptdatapath->CON,(void *)con_fig);
   signal->CON=addchain(signal->CON, (void *)con_fig);
   signal->COL=addchain(signal->COL, (void *)colonne);
   signal->MIN_COL=colonne;
   signal->TMP_MIN_COL=colonne;
   signal->width=(max_index(signal) - signal->MIN_COL);
   signal->TMP_width=signal->width;
   }
else 
   {
   tab[ligne][colonne]=ptspace;
   ptspace=makespace(name, NULL, NULL, NULL, 0, 0, 0, colonne);
   con_fig=makecon_fig_DF(name, colonne, signal);
   ptdatapath->CON=addchain(ptdatapath->CON,(void *)con_fig);
   signal->CON=addchain(signal->CON, (void *)con_fig);
   signal->COL=addchain(signal->COL, (void *)colonne);
   signal->width=(colonne - signal->MIN_COL);
   signal->TMP_width=signal->width;
   }
}
/****************************************************************/
/*    con_ctrl():Le connecteur de la figure est un CTRL         */ 
/****************************************************************/
void con_ctrl(signal, name, lig, col)
DPP_SIGNAL *signal;
char   *name;
int lig;
int col;
{
DPP_CONNECTOR *con_fig=NULL;

if((lig-(signal->height + signal->MIN_LIN)) > signal->MIN_LIN)
    {
    con_fig=makecon_fig_CTRL(name,0,'S',signal);
    ptdatapath->CON=addchain(ptdatapath->CON,(void *)con_fig);
    signal->CON=addchain(signal->CON, (void *)con_fig);
    }
else if((lig-(signal->height + signal->MIN_LIN)) < signal->MIN_LIN)
    {
    con_fig=makecon_fig_CTRL(name,lig,'N',signal);
    ptdatapath->CON=addchain(ptdatapath->CON,(void *)con_fig);
    signal->CON=addchain(signal->CON, (void *)con_fig);
    }
else if((lig-(signal->height + signal->MIN_LIN)) == signal->MIN_LIN)
    {
    con_fig=makecon_fig_CTRL(name,lig,'N',signal);
    ptdatapath->CON=addchain(ptdatapath->CON,(void *)con_fig);
    signal->CON=addchain(signal->CON, (void *)con_fig);
    }
}
/****************************************************************/
/*        place_con():Placement des connecteurs de la figure     */   
/****************************************************************/
void place_con(ptlo,lig,col)
lofig_list *ptlo;
int lig;
int col;
{
locon_list *ptcon=NULL;
chain_list *sig=NULL;
DPP_SIGNAL     *signal=NULL;
int colonne=0;
int flag=0;
char *vss;
char *vdd;

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

for(ptcon=ptlo->LOCON;ptcon;ptcon=ptcon->NEXT)
   {
   if(strncmp(vdd,ptcon->NAME,3)!=0 && strncmp(vss,ptcon->NAME,3)!=0){
   for(sig=ptdatapath->SIG;sig;sig=sig->NEXT)
      {
      signal=(DPP_SIGNAL *)sig->DATA;
      if(signal->index==ptcon->SIG->INDEX)
        {
        flag=is_DF(signal);
        if(flag==0)  /*le connecteur est un DF */
          {
          if((signal->MIN_COL) > abs((signal->MIN_COL + signal->width)-(col + 1)))
            {
            colonne=col + 1;
            }
          else
            {
            colonne=0; 
            }
         add_con_DF(colonne, ptcon->NAME, signal);
         }
        else if (flag==1) /* le connecteur est un CTRL */
                {
                con_ctrl(signal, ptcon->NAME,lig, col);/*le connecteur est un CTRL*/
                break;
                }
      }
    }
   }
  }
}

/****************************************************************/
/*  search_min():recherche de l'ordonnee du connecteur de la    */
/*               figure oriente a l'ouest.                      */
/****************************************************************/
long search_min(signal)
DPP_SIGNAL *signal;
{
chain_list *con=NULL;
DPP_CONNECTOR   *connector=NULL, *connect=NULL, *pt=NULL;
int min=0;
long ord=0;
int flag=0;

for(con=signal->CON;con;con=con->NEXT)
   {
   connect=(DPP_CONNECTOR *)con->DATA;
   if(connect->POS != NULL)
     {
     if(flag==0)
       {
       min=connect->COL;
       pt=connect;
       connector=connect;
       flag=1;
       }
     else
      {
      if(connect->COL < min)
        {
        pt=connect;
        min=connect->COL;
        }
      }
    }
   }
if(pt!=NULL)
  {
  ord=connector->INS->Y;
  }
else if(pt==NULL)
  {
  fprintf(stdout,"Le signal %s est traversant\n",signal->NAME);
  }
return(ord);
}
/****************************************************************/
/*  search_max():recherche de l'ordonnee du connecteur de la    */
/*               figure oriente a l'est.                        */
/****************************************************************/
long search_max(signal)
DPP_SIGNAL *signal;
{
chain_list *con=NULL;
DPP_CONNECTOR   *connector=NULL, *connect=NULL, *pt=NULL;
int max=0;
long ord=0;
int flag=0;

for(con=signal->CON;con;con=con->NEXT)
   {
   connect=(DPP_CONNECTOR *)con->DATA;
   if(connect->POS != NULL)
     {
     if(flag==0)
       {
       max=connect->COL;
       pt=connect;
       flag=1;
       }
     else
      {
      if(connect->COL > max)
        {
        pt=connect;
        max=connect->COL;
        }
      }
    }
   }
if(pt!=NULL)
  {
  ord=pt->INS->Y;
  }
else if(pt==NULL)
  {
  fprintf(stdout,"Le signal %s est traversant\n",signal->NAME);
  }
return(ord );

}
/****************************************************************/
/*  search_abscis():recherche de l'abscisse du connecteur de la */
/*                  figure oriente au nord ou au sud.           */
/****************************************************************/
long search_abscis(signal)
DPP_SIGNAL *signal;
{
phfig_list *ptfig=NULL;
chain_list *con=NULL;
chain_list *poss=NULL;
DPP_CONNECTOR   *connector=NULL;
DPP_POSSIBILITY *pos=NULL;
long abscisse=0;
int flag=0;

for(con=signal->CON;con;con=con->NEXT)
   {
   connector=(DPP_CONNECTOR *)con->DATA;
   if(connector->POS != NULL)
     {
     if(flag==0)
       {
       for(poss=connector->POS;poss;poss=poss->NEXT)
          {
          pos=(DPP_POSSIBILITY *)poss->DATA;
          ptfig=getphfig(connector->INS->FIGNAME,'A');
          abscisse=(connector->INS->X + pos->XCON);
          flag=1;
          }
       }
      }
  }
return(abscisse);
}
/****************************************************************/
/*   addphcon_fig():Associer les connecteurs a la figure        */   
/****************************************************************/
void addphcon_fig(ptfig, col)
phfig_list *ptfig;
int         col;
{
chain_list  *con=NULL;
DPP_CONNECTOR   *connector=NULL;
DPP_POSSIBILITY *ptpos=NULL;
long ord=0;
long absc=0;

for(con=ptdatapath->CON;con;con=con->NEXT)
   {
   connector=(DPP_CONNECTOR *)con->DATA;
   if(connector->ORIENT=='X')         /*connecteur DATA-FLOW */
     {
     if(connector->SIGN->MIN_COL==0)   /*connecteur place sur la colonne de gauche*/
       {
       connector->ORIENT='W';
       ord=search_min(connector->SIGN);
       ptpos=pos_fig(ptfig->XAB1,ord);
       connector->POS=addchain(connector->POS,(void *)ptpos);
       addphcon(ptfig,connector->ORIENT,connector->NAME,ptfig->XAB1,ptpos->YCON,
               ((char)ALU2), LAYERWIDTH);
       }
     /*connecteur place sur la colonne de droite*/
     else if(connector->SIGN->MIN_COL==((col+1)-(connector->SIGN->width)))
       {
       connector->ORIENT='E';
       ord=search_max(connector->SIGN);
       ptpos=pos_fig(ptfig->XAB2,ord);
       connector->POS=addchain(connector->POS,(void *)ptpos);
       addphcon(ptfig,connector->ORIENT,connector->NAME,ptfig->XAB2,ptpos->YCON,
               ((char)ALU2), LAYERWIDTH);
       }
     }
    else if(connector->ORIENT=='S')  /*connecteur de CTRL place au sud*/
     {
     absc=search_abscis(connector->SIGN);
     ptpos=pos_fig(absc,ptfig->YAB1);
     connector->POS=addchain(connector->POS,(void *)ptpos);
     addphcon(ptfig,connector->ORIENT,connector->NAME,ptpos->XCON,ptfig->YAB1,
             ((char)ALU1), SCALE_X);
     }
    else if(connector->ORIENT=='N')  /*connecteur de CTRL place au nord*/
     {
     absc=search_abscis(connector->SIGN);
     ptpos=pos_fig(absc,ptfig->YAB2);
     connector->POS=addchain(connector->POS,(void *)ptpos);
     addphcon(ptfig,connector->ORIENT,connector->NAME,ptpos->XCON,ptfig->YAB2,
             ((char)ALU1), SCALE_X);
     }
   }
}
