/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : DESB  v2.n                                                  */
/*    Fichier : dsbmbk.c                                                    */
/*                                                                          */
/*    (c) copyright 1993 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Marc LAURENTIN                        le : 27/01/1993     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/
#include "declar.h"

lofig_list * DSB_HEAD_MODEL=NULL ;

static short coneConect();
static void  saveVbeConeModel();
static short coneIsEmpty();
static void  prepConeExtT();
static void  restoreConeExtT();
static void  prepConeMemory();
static void  restConeMemory();
static void  delOutconeForVst();
static void  genCatal();


/****************************************************************************
 *                         fonction dsbmodToLomod();                        *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Fabrique un lofig contenant essentiellement l'interface du cone           |
+--------------------------------------------------------------------------*/
lofig_list * dsbmodToLomod(cone,index)
cone_list * cone ;
int         index;
{
ptype_list * user ;
list_list  * incone ;
long          nbIn=0 ;
char       * model ;
int i = 0 ;
lofig_list * fig ;
char  figname[20] ;

   for(incone=cone->INCONE;incone!=NULL;incone=incone->NEXT)
   {
   long  poids ;

      if((incone->TYPE & LOOP)==LOOP) continue ;

   user=getptype(incone->USER,DSB_POIDS);
      if(user==NULL)
      {
      dsbBug(3,"dsbmodToLomod",cone->NAME,"DSB_POIDS",0);
      }
   poids = (long)user->DATA ;

   if (poids > nbIn) nbIn = poids ;
   }

sprintf(figname,"dsb_model_%d",index);

DSB_HEAD_MODEL=addlomodel(DSB_HEAD_MODEL,namealloc(figname));
fig = DSB_HEAD_MODEL ;

   for(i=1;i<=nbIn;i++) addlosig(fig,i,(void*)NULL,EXTERNAL,1);
    
addlosig(fig,nbIn+1,(void *) NULL,EXTERNAL,1); /* f */
addlosig(fig,nbIn+2,(void *) NULL,EXTERNAL,1); /* vdd */
addlosig(fig,nbIn+3,(void *) NULL,EXTERNAL,1); /* vss */

   for(i=1;i<=nbIn;i++)
   {
   char buff[6];
   sprintf(buff,"in%d",i);
   addlocon(fig,namealloc(buff),getlosig(fig,i),'I');
   }

   if((cone->TYPE & HZ)==HZ) addlocon(fig,namealloc("f"),getlosig(fig,nbIn+1),'Z');
   else addlocon(fig,namealloc("f"),getlosig(fig,nbIn+1),'O');

addlocon(fig,namealloc("vdd"),getlosig(fig,nbIn+2),'I');
addlocon(fig,namealloc("vss"),getlosig(fig,nbIn+3),'I');
return(fig);
}

/****************************************************************************
 *                         fonction dsbfigToMbkfig();                        *
 ****************************************************************************/
lofig_list * dsbfigToMbkfig(figDesb)
desafig_list * figDesb ;
{
pTH funcTable ;
pTH modelTable ;
lofig_list * tabModel[200]; /* tableau des model:index donne par modelTable*/
lofig_list * mbkFig;
long vddSigIndex ;
long vssSigIndex ;
long bidonSig    ;
long nbSig = 1 ;
int modelIdx = 1 ;
locon_list * conect  ;
cone_list*   cone = NULL  ;

funcTable=createTH(100);  /* table des occurences de modeles (stat..)*/
modelTable=createTH(100); /* correspondance model <-> index */

/*-----------------------------------------------------------------+
 | On supprime iterativement les outcones qui pointe sur des cones |
 | qui n'ont pas de sorties, ceci pour que la netlist structurelle |
 | soit avalable par Asimut ou par SaX                             |
 +----------------------------------------------------------------*/
delOutconeForVst(figDesb);

   /*--------------------------------------------------------+
   | On associe a chaque cone son modele (char * ~= structrel|
   | Si le model est nouveau , il est ajoute a la table de   |
   | hasch modelTable avec un index qui est incremente.      |
   | et le model logique MBK est cree                        |
   | Le pointeur sur le model logique (MBK) est ajoute dans  |
   | un tableau de pointeur, dont l'index est celui precite  |
   | ON accedera donc au  pointeur de model en cherchant     |
   | table[i] avec i = le res du hash sur l'expression du    |
   | modele                                                  |
   | Enfin, le vbe du model est crache sur disque            |
   +--------------------------------------------------------*/
   for(cone = figDesb->CONE;cone != NULL ; cone = cone->NEXT)
   {
   list_list * in ;

      if((cone->TYPE & VDD)==VDD)       continue ;
      if((cone->TYPE & VSS)==VSS)       continue ;
      if((cone->TYPE & INUTIL)==INUTIL) continue ;
      if((cone->TYPE & SLAVE)==SLAVE)   continue ;
      if(cone->OUTCONE == NULL)         continue ;
      if(coneIsEmpty(cone)==0)          continue ; 
      if(coneConect(cone)==0)           continue ;
      else 
      {
      ptype_list * user ;
      char * expr       ;
      int value ;

         if((cone->TYPE & EXT)==EXT) prepConeExtT(cone);
         if((cone->TYPE & (MEMORY | LATCH))==MEMORY)
         prepConeMemory(cone);

      dsbMakeConeModel(cone);
      user=getptype(cone->USER,DSB_MODEL);
      expr=(char*)user->DATA ;
      value=searchTH(funcTable,expr);

         if(value == -1)       /* Nouveau model de cone */
         {
         lofig_list * fig ;
         addTH(funcTable,expr,1);
         addTH(modelTable,expr,modelIdx);
         fig=dsbmodToLomod(cone,modelIdx);
         savelofig(fig); 
         saveVbeConeModel(cone,modelIdx,expr);
         tabModel[modelIdx++]=fig;
         }
         else addTH(funcTable,expr,value+1);

      }
   }
/* displayTH(funcTable); */
/* displayTH(modelTable);*/

/*-----------------------------------------------------+
| On cree la figure proprement dit                     |
+-----------------------------------------------------*/
mbkFig=addlofig(figDesb->NAME);

   /*--------------------------------------------------+
   | Signaux de la figure                            :   |
   +--------------------------------------------------*/
   for(cone=figDesb->CONE;cone!=NULL;cone=cone->NEXT)
   {
   chain_list * signame = NULL ;

   nbSig ++ ;

      if(cone->OUTCONE == NULL) continue ;
      /*
      if((cone->TYPE & VDD)==VDD)       continue ;
      if((cone->TYPE & VSS)==VSS)       continue ;
      */
      if((cone->TYPE & INUTIL)==INUTIL) continue ;
      if(coneIsEmpty(cone)==0)          continue ;
      if((cone->TYPE & MAST)==MAST)   continue ;
      
      /* Les latch et les slaves */
      if((cone->TYPE & LATCH )==LATCH) signame=NULL;
      else  signame=addchain(NULL,(void*)cone->NAME);

      if((cone->TYPE & (EXT|VDD|VSS))!=0)
      addlosig(mbkFig,cone->INDEX,signame,EXTERNAL,1);
      else addlosig(mbkFig,cone->INDEX,signame,INTERNAL,1);

      if((cone->TYPE & VDD)==VDD)
      vddSigIndex=cone->INDEX ;
  
      if((cone->TYPE & VSS)==VSS)
      vssSigIndex=cone->INDEX  ;
   }

   /*---------------------------------------------------------+
   | Connecteurs externes: Ceux sur lequel un cone est monte  |
   | sont craches tels quel puisque un signal ( un cone) leur |
   | associe. Pour les autres (fin de branche EXT sur lequel ,|
   | il n'y a pas de cone -xor de connecteur=contre exemple-) |
   |il faut                                                   |
   | un signal supplementaire, dont on range l'index dans un  |
   | user MBK_SIG du connecteur                               |
   +---------------------------------------------------------*/
   for(conect=figDesb->LOCON;conect!=NULL;conect=conect->NEXT)
   {
   ptype_list * titiuser ;

      if(conect->DIRECTION=='X') continue ;  /* Transparence */

      if(conect->DIRECTION=='A') /* Alimentations */
      {
      cone_list  * vdsCone ;
      ptype_list * vdsUser = getptype (conect->USER,EXT);

         /* l'alim est aussi un cone */
         if((vdsUser!=NULL)&&(vdsUser->DATA !=NULL)) 
         {
         vdsCone = (cone_list *)vdsUser->DATA ;
         addlocon(mbkFig,conect->NAME,getlosig(mbkFig,vdsCone->INDEX),'I');
         }
         else 
         {
            if(test_chainin(conect->NAME,NAME_VDD)==1)
            {
            vddSigIndex=nbSig ;
            addlosig(mbkFig,nbSig,addchain(NULL,(void*)conect->NAME),
                                                  EXTERNAL,1);
            addlocon(mbkFig,conect->NAME,getlosig(mbkFig,vddSigIndex),'I');
            nbSig++;
            }
             
            else if(test_chainin(conect->NAME,NAME_VSS)==1)
            {
            vssSigIndex=nbSig ;
            addlosig(mbkFig,nbSig,addchain(NULL,(void*)conect->NAME),
                                                  EXTERNAL,1);
            addlocon(mbkFig,conect->NAME,getlosig(mbkFig,vssSigIndex),'I');
            nbSig++;
            }
         }
      continue ;
      }

   titiuser=getptype(conect->USER,EXT);
   
      if(titiuser!=NULL)   /* connecteur sur lequel est monte un cone
                              ATTENTION c'est peut etre un cone vide */ 
      {
      cone_list * tata = (cone_list*)titiuser->DATA ;
         if(coneIsEmpty(tata)!=0)       /* si cone non vide */
         addlocon(mbkFig,conect->NAME,getlosig(mbkFig,tata->INDEX),conect->DIRECTION);
         else
         {
         addlosig(mbkFig,nbSig,NULL,EXTERNAL,1);
         addlocon(mbkFig,conect->NAME,getlosig(mbkFig,nbSig),conect->DIRECTION);
         conect->USER=addptype(conect->USER,DSB_MBK_SIG,(void*)nbSig);
         nbSig++;
         }
      }
      else   /* les autres */
      {
      addlosig(mbkFig,nbSig,NULL,EXTERNAL,1);
      addlocon(mbkFig,conect->NAME,getlosig(mbkFig,nbSig),conect->DIRECTION);
      conect->USER=addptype(conect->USER,DSB_MBK_SIG,(void*)nbSig);
      nbSig++;
      }
   }

   /*-----------------------------------------------------+
   | On change temporairement l'index de tous les cones   |
   | VDD ou VSS. Leur index prend la valeur de l'index    |
   | du signal associe aux connecteurs ext d'alimentation |
   +-----------------------------------------------------*/
   for(cone=figDesb->CONE;cone!=NULL;cone=cone->NEXT)
   {
      if((cone->TYPE & VDD) ==VDD)
      {
      cone->USER=addptype(cone->USER,OLDINDEX,(void*)cone->INDEX);
      cone->INDEX=vddSigIndex;
      }
      else if ((cone->TYPE & VSS)==VSS)
      {
      cone->USER=addptype(cone->USER,OLDINDEX,(void*)cone->INDEX);
      cone->INDEX=vssSigIndex ;
      }
      else continue ;
   } 


   /*----------------------------------------------------+
   | on crache les instances                             |
   +----------------------------------------------------*/
   for(cone=figDesb->CONE;cone!=NULL;cone=cone->NEXT)
   {
   list_list * path ;
   char * model ;
   int    nbModel ;
   ptype_list * user ;
   lofig_list * loModel;
   list_list * tabIncone[500];
   list_list * in ;
   chain_list * sigchain=NULL ;
   int i = 0 ;
   int nbIn = 0 ;

      /* TEST */ if(cone->OUTCONE == NULL) continue ;
      if(coneIsEmpty(cone)==0) continue ;
      if(coneConect(cone)==0) continue ;
      if((cone->TYPE & VDD)==VDD) continue ;
      if((cone->TYPE & VSS)==VSS) continue ;
      if((cone->TYPE & INUTIL)==INUTIL) continue ;
      if((cone->TYPE & SLAVE)==SLAVE)  continue  ;
   
   user=getptype(cone->USER,DSB_MODEL);

      if(user==NULL)
      {
      dsbBug(4,"dsbfigToMbkfig",cone->NAME,NULL,0);
      }

   /*------------------------------------------------------------------+
   | On recupere le lomodele du cone  a partir du model passe dans TsH |
   +------------------------------------------------------------------*/
   model = (char *) user->DATA ;
   nbModel=searchTH(modelTable,model);
   loModel=tabModel[nbModel];

      /*-------------------------------------------+
      | On constitue un tableau ordonnee de incone |
      +-------------------------------------------*/
      for(in=cone->INCONE;in!=NULL;in=in->NEXT)
      {
      int index ;

         if((in->TYPE & LOOP)==LOOP) continue ;

      user=getptype(in->USER,DSB_POIDS);
      index=(int)((long)user->DATA);
      tabIncone[index]=in;
      nbIn++;
      }

       /*----------------------------------------+
      | On fabrique la chainlist des entrees     |
      +-----------------------------------------*/
      for(i=1;i<=nbIn;i++)
      {
      list_list * in = tabIncone[i];

         if(((in->TYPE & CONE_TYPE )==CONE_TYPE) ||
            ((in->TYPE & VDD )==VDD) ||
            ((in->TYPE & VSS )==VSS) )
         {
         cone_list * toto = (cone_list*)in->DATA ;
         sigchain=addchain(sigchain,(void*)getlosig(mbkFig,toto->INDEX));
         }
         else   /* Entree de type Connecteur */
         {
         locon_list * Conect ;
         ptype_list * User   ;
         Conect=(locon_list*)in->DATA;
            /*-----------------------------------------------------+
            | Si un cone est monte sur le connecteur , ATTENTION , |
            | C'est peut etre un cone vide                         |
            +-----------------------------------------------------*/
            if((User=getptype(Conect->USER,EXT))!=NULL) 
            {
            cone_list * coneX;
            coneX=(cone_list*)User->DATA;

               if(coneIsEmpty(coneX)!=0) /* si cone non vide */
               {
                  sigchain=addchain(sigchain,
                                 (void*)getlosig(mbkFig,coneX->INDEX));
               }

               else              /* si cone vide, le signal 
                         qui y est attache n'a pas ete declare mais 
                         un signal a ete creee pour le connecteur  */
               { 
               User=getptype(Conect->USER,DSB_MBK_SIG);
               sigchain=addchain(sigchain,
                                 (void*)getlosig(mbkFig,(long)User->DATA));
               }
            }
            else  /* Pas de cone monte sur le connecteur -> comme cone vide */
            { 
            User=getptype(Conect->USER,DSB_MBK_SIG);
            sigchain=addchain(sigchain,
                              (void*)getlosig(mbkFig,(long)User->DATA));
            }
         }
      }
      /* ON RAJOUTE la SORTIE VDD et VSS puis on fait le ADDLOINS*/
      if((cone->TYPE & MAST)==MAST )
      {
      cone_list * slave ;
      ptype_list * mastUser ;
      mastUser=getptype(cone->USER,SLAVE);
      slave=(cone_list*)mastUser->DATA ;
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,slave->INDEX));
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,vddSigIndex));
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,vssSigIndex));
      addloins(mbkFig,namealloc(GetVectName(slave->NAME)),loModel,sigchain);
      }
      else 
      {
      char  insName[80];
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,cone->INDEX));
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,vddSigIndex));
      sigchain=addchain(sigchain,(void*)getlosig(mbkFig,vssSigIndex));
      sprintf(insName,"dsbins_%s",GetVectName(cone->NAME));
      addloins(mbkFig,namealloc(insName),loModel,sigchain);
      }
   }

   /*----------------------------------------------------+
   | On remet en place les index des cones alimentation  |
   | et les con EXT contenant un connecteur 'T'          |
   +----------------------------------------------------*/
   for(cone=figDesb->CONE;cone!=NULL;cone=cone->NEXT)
   {
      if((cone->TYPE & VDD)==VDD)
      {
      ptype_list * alimUser =getptype(cone->USER,OLDINDEX);
      cone->INDEX=(long)alimUser->DATA;
      cone->USER=delptype(cone->USER,OLDINDEX);
      }
      else if((cone->TYPE & VSS)==VSS)
      {
      ptype_list * alimUser =getptype(cone->USER,OLDINDEX);
      cone->INDEX=(long)alimUser->DATA;
      cone->USER=delptype(cone->USER,OLDINDEX);
      }
      else if((cone->TYPE & EXT)==EXT)
      restoreConeExtT(cone);
      else if((cone->TYPE & (MEMORY | LATCH))==MEMORY)
      restConeMemory(cone);
      else continue ;
      
   }

sortlocon(&mbkFig->LOCON);
genCatal(DSB_HEAD_MODEL);
return(mbkFig);
}



/****************************************************************************
 *                         fonction ConeConect();                        *
 ****************************************************************************/
/*-------------------------------------------------------------------------+
| Retourne 0 si le cone est un cone connecteur ie il possede une branche  |
|            fonctionnelle unique qui est la branche maillon connecteur   |
|          -1 si le cone possede au moins une branche fonctionnele qui    |
|             n'est pas externe.                                          |
+-------------------------------------------------------------------------*/
static short coneConect(cone)
cone_list *cone;
{
list_list * path ;
short coneconect=0;
short funcPath=0;

   if((cone->TYPE & EXT)!=EXT) return(-1);

   if(cone->PATH==NULL)
   {
   dsbBug(17,"ConeConect",cone->NAME,NULL,0);
   }

   for(path=cone->PATH;path != NULL;path=path->NEXT)
   {
      if((path->TYPE & BLEEDER)==BLEEDER) continue ;

      if((path->TYPE & EXT)==EXT)
      {
         if(((link_list*)path->DATA)->NEXT==NULL)
         {
         coneconect++;
         }
         else funcPath++;
      }
      else funcPath++;
   }

   if(funcPath!=0) return(-1);
   else if(coneconect==1) return(0);
   else
   {
   dsbFatalError(9,"coneConnect",cone->NAME,0);
   }
}

/****************************************************************************
 *                         fonction coneIsEmpty();                          *
 ****************************************************************************/
static short coneIsEmpty(cone)
cone_list * cone ;
{
   if((cone->PATH == NULL ) &&
      (cone->INCONE == NULL ) &&
      (cone->OUTCONE == NULL ))
   return(0);
   else return(-1);
}
  
    

/****************************************************************************
 *                         fonction vbeConeModel();                        *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
 | Sauvegarde sur disque le comportemental Vhdl d'un model de cone          |
 +-------------------------------------------------------------------------*/
static void saveVbeConeModel(cone,index,modelName)
cone_list * cone ;
int index ;
char * modelName ;
{
ptype_list * coneUser ;
ptype_list * inUser   ;
list_list * in        ;
list_list * path      ;
link_list * link      ;
cone_list * incone    ;
locon_list * inconect ;
char newName[20]      ;
FILE * vbeModel       ;
char * figname        ;
char   buff[20]       ;
long poids            ;

/*--------------------------------------------------------------+
| On renomme temporairement tous les cones ou les connecteurs   |
| qui sont en entree du cone. On parcourt les incones dont on   |
| connait le poids, et in renomme le cone/connect correspondant |
| par un ("in%s",poids) comme pour les instances                |
| La sortie s'appellera invariablement 'f'                      |
+--------------------------------------------------------------*/
   for(in=(list_list*)cone->INCONE;in!=NULL;in=in->NEXT)
   {
      if((in->TYPE & LOOP)==LOOP) continue ;

      if(((in->TYPE & CONE_TYPE)==CONE_TYPE) ||
        ((in->TYPE & VSS)==VSS) ||
        ((in->TYPE & VDD)==VDD) )
      {
      incone=(cone_list*)in->DATA;
      incone->USER=addptype(incone->USER,OLDNAME,(void*)incone->NAME);
      inUser=getptype(in->USER,DSB_POIDS);
      poids=(long)inUser->DATA;
      sprintf(newName,"in%d",poids);
      incone->NAME=namealloc(newName);
      }
      else 
      {
      inconect=(locon_list*)in->DATA;
      inconect->USER=addptype(inconect->USER,OLDNAME,(void*)inconect->NAME);
      inUser=getptype(in->USER,DSB_POIDS);
      poids=(long)inUser->DATA;
      sprintf(newName,"in%d",poids);
      inconect->NAME=namealloc(newName);
      }
   }

   /*------------------------------------------------+
   | Renommage du cone                               |
   +------------------------------------------------*/
   if((cone->TYPE & MAST)==MAST)
   {
   ptype_list * mastUser ;
   cone_list * slave ;
   mastUser=getptype(cone->USER,SLAVE);
   slave = (cone_list*) mastUser->DATA ;
   slave->USER = addptype(slave->USER,OLDNAME,(void*)slave->NAME);
   slave->NAME=namealloc("aux");
   }
   else if((cone->TYPE & LATCH )==LATCH)
   {
   cone->USER=addptype(cone->USER,OLDNAME,(void*)cone->NAME);
   cone->NAME = namealloc("aux");
   }
   else
   {
   cone->USER=addptype(cone->USER,OLDNAME,(void*)cone->NAME);
   cone->NAME=namealloc("f");
   }

/*-----------------------------------------------------+
| Ecriture du modele sur disque                        |
+-----------------------------------------------------*/
sprintf(buff,"dsb_model_%d",index);
figname=namealloc(buff);
vbeModel = mbkfopen(figname,DSB_VHDSFX,WRITE_TEXT);
fprintf(vbeModel,"-- %s \n", modelName);
fprintf(vbeModel,"entity %s is \n",figname);
fprintf(vbeModel,"\n\n   port\n(\n");


   if((cone->TYPE & HZ)==HZ) fprintf(vbeModel,"f   : out wor_bit bus ;\n"); 
   else fprintf(vbeModel,"f   : out bit ;\n");

   for(in=(list_list*)cone->INCONE;in!=NULL;in=in->NEXT)
   {
      if((in->TYPE & LOOP)==LOOP) continue ;

   inUser=getptype(in->USER,DSB_POIDS);
   poids=(long)inUser->DATA;
   fprintf(vbeModel,"in%d : in bit ;\n",poids); 
   }

fprintf(vbeModel,"%s : in bit ;\n",NAME_VDD);
fprintf(vbeModel,"%s : in bit \n);\n   end %s ;\n",NAME_VSS,figname);
fprintf(vbeModel,"architecture FUNCTIONAL of %s is\n",figname);

   if((cone->TYPE & LATCH )==LATCH)
   fprintf(vbeModel,"signal aux : reg_bit register;\n");

fprintf(vbeModel,"begin\n");

   if((cone->TYPE & LATCH)==LATCH) 
   {
   fprintf(vbeModel,"%s",hashchar_toto(latchexpr(cone))) ;
   fprintf(vbeModel,"f <= aux ;\n");
   }

   else if ((cone->TYPE & MEMORY)==MEMORY) 
   fprintf(vbeModel,"%s",hashchar_toto(dualexpr(cone)));

   else if (((cone->TYPE)&HZ)!=HZ) 
   fprintf(vbeModel,"%s",hashchar_toto(dualexpr(cone)));

   else if (((cone->TYPE)&HZ)==HZ) 
   fprintf(vbeModel,"%s",hashchar_toto(hzexpr(cone))); 

fprintf(vbeModel,"end FUNCTIONAL ;\n");
fclose (vbeModel);

  /*----------------------------------------------------------+
  | On remet tous les noms en place                           |
  +----------------------------------------------------------*/
   for(in=(list_list*)cone->INCONE;in!=NULL;in=in->NEXT)
   {
      if((in->TYPE & LOOP)==LOOP) continue ;

      if(((in->TYPE & CONE_TYPE)==CONE_TYPE) ||
         ((in->TYPE & VSS)==VSS) ||
         ((in->TYPE & VDD)==VDD))
      {
      incone=(cone_list*)in->DATA;
      inUser=getptype(incone->USER,OLDNAME);
      incone->NAME=(char*)inUser->DATA;
      incone->USER=delptype(incone->USER,OLDNAME);
      }
      else 
      {
      inconect=(locon_list*)in->DATA;
      inUser=getptype(inconect->USER,OLDNAME);
      inconect->NAME=(char*)inUser->DATA;
      inconect->USER=delptype(inconect->USER,OLDNAME);
      }
   }

   if((cone->TYPE & MAST)==MAST)
   {
   ptype_list * mastUser ;
   ptype_list * slavUser ;
   cone_list   * slave ;
   mastUser=getptype(cone->USER,SLAVE);
   slave=(cone_list*)mastUser->DATA ;
   slavUser=getptype(slave->USER,OLDNAME);
   slave->NAME=(char*)slavUser->DATA;
   }
   else 
   { 
   coneUser=getptype(cone->USER,OLDNAME);
   cone->NAME=(char*)coneUser->DATA;
   cone->USER=delptype(cone->USER,OLDNAME);
   }
}
   

/****************************************************************************
 *                         fonction prepConeExtT();                         *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| sauvegarde puis supprime de la liste des  branche, la branche qui contient|
| un conecteur T , des cone montes sur un connecteur T. L'entree contenant  |
| le connecteur T est elle type LOOP . Il va de soit que ces modif ne doiven|
| etre que temporaires                                                      |
+--------------------------------------------------------------------------*/
static void prepConeExtT(cone)
cone_list * cone ;
{
ptype_list * coneUser ;
locon_list * conectCone ;
locon_list * conectLink ;
list_list  * path ;
list_list  * prevPath ;
list_list  * nextPath ;
link_list  * link  ;
list_list * incone ;

coneUser = getptype(cone->USER,EXT) ;
conectCone = (locon_list*)coneUser->DATA ;

   if(conectCone->DIRECTION != 'T') return ;

prevPath = cone->PATH ;
   for(path=cone->PATH;path!=NULL;path=path->NEXT)
   {
      if ((path->TYPE & EXT)!= EXT)  
      {
      prevPath=path ;
      continue ;
      }
      if ((((link_list*)path->DATA)->NEXT)!=NULL) 
      {
      prevPath=path ;
      continue ;
      }
   conectLink = (locon_list*) ((link_list*)path->DATA)->TRANS;
      if((conectLink != conectCone)) 
      {
      prevPath = path ;
      continue ;
      }
   cone->USER=addptype(cone->USER,SAV_PATH,(void*)path);
      if(path==cone->PATH) cone->PATH = path->NEXT ;
      else prevPath->NEXT = path->NEXT ;

   break ;
   }

   for(incone=cone->INCONE;incone!=NULL;incone=incone->NEXT)
   {
      if((incone->TYPE & EXT)!=EXT) continue ;
      else
      {
      locon_list * inconect ;
      inconect = (locon_list*) incone->DATA ;
         if(inconect == conectCone)
         {
         (incone->TYPE) |= LOOP ;
         break ;
         }
         else continue ;
      }
   }
}
 

/****************************************************************************
 *                         fonction restoreConeExtT();                      *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Remet en place la branche contenant le connecteur T supprimee par la      |
| fonction prepConeExtT. Enleve le type LOOP de l'entree designant ce conX  |
+--------------------------------------------------------------------------*/
static void restoreConeExtT(cone)
cone_list * cone ;
{
list_list * path ;
ptype_list * coneUser ;
list_list  * incone   ;
locon_list * conect   ;
locon_list * conectLink ;

   if((coneUser=getptype(cone->USER,SAV_PATH))==NULL)
   return ;

path = (list_list*)coneUser->DATA ;
path->NEXT=cone->PATH ;
cone->PATH=path ;
cone->USER = delptype(cone->USER,SAV_PATH);

   for(incone=cone->INCONE;incone!=NULL;incone=incone->NEXT)
   {
      if((incone->TYPE & LOOP)!=LOOP) continue ;
      if((incone->TYPE & EXT)!=EXT)   continue ;

   conect=(locon_list*)incone->DATA ;
   conectLink=(locon_list*)((link_list*)path->DATA)->TRANS ;

      if(conect==conectLink) 
      {
      incone->TYPE &= ~LOOP ;
      break ;
      }
      else continue ;
   }
}
/****************************************************************************
 *                         fonction delOutConeForVst()                      *
 ****************************************************************************/
 /*------------------------------------------------------------------------+
 | Suprime les outcone pointant sur des cones sans sorties. Fonction       |
 | iterative, puisque d'une passe a l'autre, les cones perdent des outcones|
 +------------------------------------------------------------------------*/
static void delOutconeForVst(fig)
desafig_list *fig ;
{
short change = 0;

   while (change == 0)
   {
   cone_list * cone ;
   change = -1 ;

      for(cone=fig->CONE;cone!=NULL;cone=cone->NEXT)
      {
      list_list * in ;
      list_list * out ;
      cone_list * incone ;
      cone_list * outcone ;
      
         if(cone->OUTCONE != NULL ) continue ;

         for(in=cone->INCONE; in!=NULL;in=in->NEXT)
         {
            if(in->TYPE & EXT == EXT) continue ;

         incone=(cone_list*) in->DATA ;

            for(out=incone->OUTCONE;out!=NULL;out=out->NEXT)
            {
               if((out->TYPE & EXT)== EXT ) continue ;

            outcone=(cone_list*)out->DATA;

               if(outcone==cone) 
               {
               incone->OUTCONE=rmv_list(incone->OUTCONE,(char*)outcone);
               change=0;
               break ;
               } 
            }
         }
      }
   }
}
                  
          
          
/****************************************************************************
 *                         fonction genCatal();                             *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
 | Genere le fichier CATAL contenant la liste des modeles suivi de ' C'     |
 +-------------------------------------------------------------------------*/
static void genCatal(headModel)
lofig_list * headModel ;
{
FILE * dsbNhCatal ;  
lofig_list * fig  ;

   if((dsbNhCatal=mbkfopen(CATAL,NULL,WRITE_TEXT))==NULL)
   dsbFatalError(7,NULL,CATAL,0);

   for(fig=headModel;fig!=NULL;fig=fig->NEXT)
   fprintf(dsbNhCatal,"%s C \n",fig->NAME);

   if(fclose(dsbNhCatal)!=0)
   dsbFatalError(8,NULL,CATAL,0);
}

      
/****************************************************************************
 *                         fonction prepConeMemory();                       *
 ****************************************************************************/
/*--------------------------------------------------------------------------+
| Cette fonction fait en sorte que le cone ressemble temporairement a un    |
| inverseur                                                                 |
+--------------------------------------------------------------------------*/
static void prepConeMemory(cone)
cone_list * cone ;
{
list_list  *path ;
list_list * in ;
ptype_list * user = getptype(cone->USER,MEMORY);

   for(in=cone->INCONE ; in!= NULL ; in=in->NEXT)
   {
      if((in->TYPE & LOOP)!=LOOP) in->TYPE |= LOOP ;
      else in->TYPE &= (~LOOP);
   }

   cone->INCONE=add_list(cone->INCONE,(void*)user->DATA,CONE_TYPE);

   for(path=cone->PATH;path!=NULL;path=path->NEXT)
   {
      if((path->TYPE & BLEEDER) != BLEEDER) path->TYPE |= BLEEDER;
      else path->TYPE &= (~BLEEDER) ;
   }
}

/****************************************************************************
 *                         fonction restConeMemory();                       *
 ****************************************************************************/
static void restConeMemory(cone)
cone_list * cone ;
{
list_list  *path ;
list_list * in ;
list_list * save ;

save=cone->INCONE ;
cone->INCONE=cone->INCONE->NEXT ;
dsbFreeList(save);

   for(in=cone->INCONE ; in!= NULL ; in=in->NEXT)
   {
      if((in->TYPE & LOOP)!=LOOP) in->TYPE |= LOOP ;
      else in->TYPE &= (~LOOP);
   }

   for(path=cone->PATH;path!=NULL;path=path->NEXT)
   {
      if((path->TYPE & BLEEDER) != BLEEDER) path->TYPE |= BLEEDER;
      else path->TYPE &= (~BLEEDER) ;
   }
}
