/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : synthetiseur logique                                        */
/*    Fichier : dec4.c                                                      */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : L. Burgun                             le : 09/10/1991     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
#include "../compil/lax_param.h"
#include "../synthe/sl_type.h"
#include "../compil/sl_util.h"
#include "../mapping/types.h"
#include "../mapping/compile.h"
#include "../mapping/regles.h"
#include "../cccc/c4.h"
#include "dec4.h"

/*------------------------------------------------------------------
  IDENT : normExprC4
  ------------------------------------------------------------------
  FUNCTION : normalise une expression a tous les niveaux
                variable = pointeur d'allocation
                expression = numero d'operateur.
             ex : (and a b (or x f) (or e g o))
                --> (and (or e o g) (or x f) b a)

  --> Tri decroissant
  1er critere : nombre de litteraux
  2eme  "     : longueur au premier niveau
  3eme  "     : numero d'operateur
  ------------------------------------------------------------------ */

int funcNormExprC4(expr)
chain_list *expr;
{
if (ATOM(expr))
   return 0;
else
   if (OPER(expr) == NOT)
      return 0;
   else
      return(numberAtomExpr(expr)*100 +
             OPER(expr) + lengthExpr(expr)*10);
}

void normExprC4(expr)
chain_list *expr;
{
if (!ATOM(expr))
   {
   sortExpr(expr,funcNormExprC4,0);
   while (expr = CDR(expr))
      normExprC4(CAR(expr));
   }
}
 


/*------------------------------------------------------------------------------
expr2Bst 	: cree une expression au format bst (ident_porte i0 i1 ... in)
		  a partir d'une expression beh et d'un ident (int) de porte.
------------------------------------------------------
parametres  	: un operateur (int) et un ABL. 
-------------------------------------------------------
return 		: un chain_list * 
------------------------------------------------------------------------------*/
chain_list *expr2Bst(oper,expr)
short oper;
chain_list *expr;
{
chain_list *res;
void addNExpr();

res = createExpr(oper);
addNExpr(res,expr);
return(res);
}


	/* rajoute au premier niveau dans e1 les entrees de e2 */

void addNExpr(e1,e2)
chain_list *e1,*e2;
{
if (ATOM(e2))
   addQExpr(e1,createAtom(VALUE_ATOM(e2)));
else
   {
   while(e2 = CDR(e2))
	addNExpr(e1,CAR(e2));
   }
}

/*------------------------------------------------------------------------------
c4AssocExpr 	: tri une expression normalisee avec la liste assocative de
		  la memFig. 
------------------------------------------------------
parametres  	: un ABL et la memFig. 
-------------------------------------------------------
return 		: un chain_list* 
------------------------------------------------------------------------------*/
chain_list *c4AssocExpr(mf,expr)
MemFig *mf;
chain_list *expr;
{
chain_list *result;
chain_list *assoc = mf->assocList;

result = createExpr(OPER(expr));
while (assoc)
  {
  addQExpr(result,copyExpr(searchNumExpr(expr,assoc->DATA)));  
  assoc = assoc->NEXT;
  }
return(result);
}
/*------------------------------------------------------------------------------
c4MappExprBeh 	: creation des modeles virtuels.  (memF)
------------------------------------------------------
parametres  	: un ABL.. 
-------------------------------------------------------
return 		: un void 
------------------------------------------------------------------------------*/
void c4MappExprBeh(beh,expr,mode)
befig_list *beh;
chain_list *expr;
int mode;
{
MemFig *memF;
char *ident;

if (mode == 1)
   printf("c4MappExpr : \n");

if (!ATOM(expr))
   {
		 /* modification de expr */

		/* normalisation */

   normExprC4(expr);

		/* appel a C4 */

   ident = identExpr(expr);

		/* ce n'est pas un not  */

   if (strcmp(ident,"not1"))
      {
		/* cellule existe deja ? */

      if (searchTH(pTC4,ident) == EMPTYTH)
         {
         memF = c4_comp(expr2Model(expr),ident,SL_NUMCANP,SL_NUMCANN,1);
         if (memF->result->polarity == 2)
            {
            printf("C4 compiler : error function has a bad polarity\n");
            printf("---> ");
            displayExpr(expr);
            exit(-1);
            }
         if (memF->result->nbTPSer > SL_NUMTRANSP)
            {
            printf("C4 compiler : error function has too many serial transistors");
            printf(" in P-graph\n");
            printf("---> ");
            displayExpr(expr);
            exit(-1);
            }
         if (memF->result->nbTNSer > SL_NUMTRANSN)
            {
            printf("C4 compiler : error function has too many serial transistors");
            printf(" in N-graph\n");
            printf("---> ");
            displayExpr(expr);
            exit(-1);
            }
         addTH(pTC4,ident,memF);
         mf_list = addchain(mf_list,memF);
         }
      }
   }
}

/*------------------------------------------------------------------------------
c4GenCell 	: effectue la mise en forme structurelle d'une expression. 
------------------------------------------------------
parametres  	: un ABL. 
-------------------------------------------------------
return 		: un void 
------------------------------------------------------------------------------*/
chain_list *c4GenCell(expr,mode)
chain_list *expr;
int mode;
{
MemFig *memF;
int val;
char *ident;
chain_list *newExpr;

if (mode == 1)
   printf("c4GenCell\n");

if (!ATOM(expr))
   {
   ident = identExpr(expr);


   if (!strcmp(ident,"not1"))
      {
      newExpr = expr2Bst(searchNumOper(ident),expr);
      freeExpr(expr);
      } 
   else
      {
      if ((val = searchTH(pTC4,ident)) != VIDETH)
         {
         memF = (MemFig *) val;
         newExpr = expr2Bst(searchNumOper(ident),expr);
         if (mode == 1)
            {
            displayArite(newExpr);printf("\n");
            }
         newExpr = c4AssocExpr(memF,newExpr);
         if (mode == 1)
            {
            displayArite(newExpr);printf("\n");
            }
         freeExpr(expr);
         }
      else
         {
         printf("c4Gencell : error unknown operator %s\n",ident);
         exit(-1);
         }
      }
   return(newExpr);
   }
else
   return(expr);
}
   
/*------------------------------------------------------------------------------
maxDepthExpr 	: calcule la prof. max. d'une expression dans une bst. 
------------------------------------------------------
parametres  	: une expression, befig et table de hachage. 
-------------------------------------------------------
return 		: un int.
------------------------------------------------------------------------------*/
int maxDepthExpr(beh,expr,nCellTH,nConeTH,numberCell,numberCone)
befig_list *beh;
chain_list *expr;
pTH nCellTH;
pTH nConeTH;
int *numberCell,*numberCone;
{
int max = 0;
int nCell,nCone;

char *searchCharOper();

if (ATOM(expr))
   {
   nCell = searchTH(nCellTH,VALUE_ATOM(expr));
   nCone = searchTH(nConeTH,VALUE_ATOM(expr));

   if (nCell == EMPTYTH)
      {
      beaux_list *aux = beh->BEAUX;
      bebux_list *bux = beh->BEBUX;

      		/* descente recursive */

      nCell = 0;
      nCone = 0;

      while (aux && nCell == 0)
         {
         if (!strcmp(aux->NAME,VALUE_ATOM(expr)))
            {
            maxDepthExpr(beh,aux->ABL,nCellTH,nConeTH,&nCell,&nCone);
            }
         aux = aux->NEXT;
         }

      while (bux && nCell == 0)
         {
         if (!strcmp(bux->NAME,VALUE_ATOM(expr)))
            {
            biabl_list *biabl = bux->BIABL;
            *numberCell = 0;
            *numberCone = 0;

            while (biabl)
               {
               if (biabl->VALABL)
                  {
                  nCell = 0;  
                  nCone = 0;  

                  maxDepthExpr(beh,biabl->VALABL,nCellTH,nConeTH,&nCell,&nCone);
                  if (nCell > *numberCell)
                     *numberCell = nCell;
                  if (nCone > *numberCone)
                     *numberCone = nCone;
                  }
               if (biabl->CNDABL)
                  {
                  nCell = 0;  
                  nCone = 0;  

                  maxDepthExpr(beh,biabl->CNDABL,nCellTH,nConeTH,&nCell,&nCone);
                  if (nCell > *numberCell)
                     *numberCell = nCell;
                  if (nCone > *numberCone)
                     *numberCone = nCone;
                  }
               biabl = biabl->NEXT;
               }
            }
         bux = bux->NEXT;
         }

      addTH(nCellTH,VALUE_ATOM(expr),nCell);
      addTH(nConeTH,VALUE_ATOM(expr),nCone);
      }

   *numberCell = nCell;
   *numberCone = nCone;
   }
else
   {
   int polarity;
   char *oper = searchCharOper(OPER(expr));
   *numberCell = 0;
   *numberCone = 0;

   polarity = 2;
   if (oper[0] == 'a' || oper[0] == 'o')   /* positive */
      polarity = 1;
   if (oper[0] == 'n' && oper[1] != 'x')  /* negative */
      polarity = 0;
   if (oper[0] == 'b')			/* bus */
      polarity = 0;

   while (expr = CDR(expr))
      {
      nCell = 0;
      nCone = 0;

      maxDepthExpr(beh,CAR(expr),nCellTH,nConeTH,&nCell,&nCone);
      if (nCell > *numberCell)
         *numberCell = nCell;
      if (nCone > *numberCone)
         *numberCone = nCone;
      }

   *numberCell = *numberCell + 1;
   if (polarity == 0)
      *numberCone = *numberCone + 1;
   else
      *numberCone = *numberCone + 2;
   }
}

/*------------------------------------------------------------------------------
maxDepthBst 	: calcule la prof. max. dans une bst. 
------------------------------------------------------
parametres  	: une befig. 
-------------------------------------------------------
return 		: un int.
------------------------------------------------------------------------------*/
void maxDepthBst(beh,numberCell,numberCone)
befig_list *beh;
int *numberCell,*numberCone;
{
beout_list *out;
bereg_list *reg;
biabl_list *biabl;
pTH nCellTH,nConeTH;
bebus_list *bus;
int result = 0;
int nCell,nCone;

nCellTH = createTH(500);
nConeTH = createTH(500);

*numberCell = 0;
*numberCone = 0;

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      nCell = 0;  
      nCone = 0;  

      maxDepthExpr(beh,out->ABL,nCellTH,nConeTH,&nCell,&nCone);
      if (nCell > *numberCell)
         *numberCell = nCell;
      if (nCone > *numberCone)
         *numberCone = nCone;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   if (biabl->VALABL)
      {
      nCell = 0;  
      nCone = 0;  

      maxDepthExpr(beh,biabl->VALABL,nCellTH,nConeTH,&nCell,&nCone);
      if (nCell > *numberCell)
         *numberCell = nCell;
      if (nCone > *numberCone)
         *numberCone = nCone;
      }
   if (biabl->CNDABL)
      {
      nCell = 0;  
      nCone = 0;  

      maxDepthExpr(beh,biabl->CNDABL,nCellTH,nConeTH,&nCell,&nCone);
      if (nCell > *numberCell)
         *numberCell = nCell;
      if (nCone > *numberCone)
         *numberCone = nCone;
      }
   reg = reg->NEXT;
   }


bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         nCell = 0;  
         nCone = 0;  

         maxDepthExpr(beh,biabl->VALABL,nCellTH,nConeTH,&nCell,&nCone);
         if (nCell > *numberCell)
            *numberCell = nCell;
         if (nCone > *numberCone)
            *numberCone = nCone;
         }
      if (biabl->CNDABL)
         {
         nCell = 0;  
         nCone = 0;  

         maxDepthExpr(beh,biabl->CNDABL,nCellTH,nConeTH,&nCell,&nCone);
         if (nCell > *numberCell)
            *numberCell = nCell;
         if (nCone > *numberCone)
            *numberCone = nCone;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

destroyTH(nCellTH);
destroyTH(nConeTH);
}

/*------------------------------------------------------------------------------
interfaceBeh 	: renvoie dans une liste chainee l'interface d'une befig 
------------------------------------------------------
parametres  	: une befig. 
-------------------------------------------------------
return 		: un chain_list *.
------------------------------------------------------------------------------*/
chain_list *interfaceBeh(beh)
befig_list *beh;
{
chain_list *lc_io = NULL;
bepor_list *port = beh->BEPOR;
 
while (port)
   {
   lc_io = addchain(lc_io,port->NAME);
   port = port->NEXT;
   }
return lc_io;
}

/*------------------------------------------------------------------------------
c4MappBeh 	: genere un format befig structurel en appelant le compilateur
                  de cellule. (decomposition comprise)
------------------------------------------------------
parametres  	: une befig. 
-------------------------------------------------------
return 		: un void.
------------------------------------------------------------------------------*/
void c4MappBeh(beh,mode,delais)
befig_list *beh;
int mode;
ptype_list *delais;
{
beout_list *out;
beaux_list *aux;
beaux_list *beh_addbeaux();
chain_list *simplifExpr10();
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
chain_list *pCL;
char *name;
char *ident;

int coNOT = 0;
int coL1 = 0;
int coL2 = 0;
int coNT1 = 0;

pTH caracTH;
pTH caracBeh();
int cptCell,cptInst;
char *c4High = NULL, *c4Low = NULL;
int cptPitch;
int val;
chain_list *lc_io;
MemFig *memF;
char *searchCharOper();
char *genNAME();


	/* caracterisation ==> tri des expressions */


caracTH = caracBeh(beh,delais,0);

	/* initialisation */

pTC4 = createTH(100);
mf_list = NULL;

	/* extraction des latches */

reg = beh->BEREG;
while (reg)
   {
   biabl = reg->BIABL;

   if (biabl && biabl->NEXT == NULL)
      {
		/* latch 1 */

      coL1++;
      if (!ATOM(biabl->VALABL))
         {
         name = gensym("auxc4_l1d",coL1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
         biabl->VALABL = createAtom(name);
         }
      if (!ATOM(biabl->CNDABL))
         {
         name = gensym("auxc4_l1c",coL1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
         biabl->CNDABL = createAtom(name);
         }
      }
   else
    if (biabl->NEXT && biabl->NEXT->NEXT == NULL)
      {
		/* latch 2 */

      while(biabl)
           {
           coL2++;
           if (!ATOM(biabl->VALABL))
              {
              name = gensym("auxc4_l2d",coL2);
              beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
              biabl->VALABL = createAtom(name);
              }
           if (!ATOM(biabl->CNDABL))
              {
              name = gensym("auxc4_l2c",coL2);
              beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
              biabl->CNDABL = createAtom(name);
              }
           biabl = biabl->NEXT;
           }
      }
    else
      {
      printf("Latches extraction : error - unknown latch '%s'\n",reg->NAME);
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus)
   {
   biabl = bus->BIABL;

		/* BUS */

   while (biabl)
      {
      coNT1++;
      if (!ATOM(biabl->VALABL))
         {
         name = gensym("auxc4_nt1d",coNT1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
         biabl->VALABL = createAtom(name);
         }

      if (!ATOM(biabl->CNDABL))
         {
         name = gensym("auxc4_nt1c",coNT1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
         biabl->CNDABL = createAtom(name);
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux)
   {
   biabl = bux->BIABL;

		/* BUS */

   while (biabl)
      {
      coNT1++;
      if (!ATOM(biabl->VALABL))
         {
         name = gensym("auxc4_nt1d",coNT1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->VALABL,NULL);
         biabl->VALABL = createAtom(name);
         }

      if (!ATOM(biabl->CNDABL))
         {
         name = gensym("auxc4_nt1c",coNT1);
         beh->BEAUX = beh_addbeaux(beh->BEAUX,name,biabl->CNDABL,NULL);
         biabl->CNDABL = createAtom(name);
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }

	/* une fois les latches et bus extraits, 
           on s'occupe du combinatoire ... */

out = beh->BEOUT;
while (out) 
   {

   if (out->ABL)
      {
      if (mode == 1)
         {
         printf("je traite %s =\n ",out->NAME);
         displayExpr(out->ABL);
         }

      if (ATOM(out->ABL))
         {
         beout_list *out1 = beh->BEOUT;
         bepor_list *bepor = beh->BEPOR;
         int entreecon = 0;
         int sortiecon = 0;

         while (bepor) 
            {
            if (!strcmp(bepor->NAME,VALUE_ATOM(out->ABL)))
               {
               entreecon = 1;
               }
            bepor = bepor->NEXT;
            } 

                /* la sortie est connecte directement a une entree */

         if (entreecon == 1)
            {
            coNOT++;
            name = gensym("auxc4_not",coNOT);
            beh->BEAUX = beh_addbeaux(beh->BEAUX,name,notExpr(out->ABL),NULL);
            out->ABL = notExpr(createAtom(name)); 
            }
         

         while (out1) 
            {
            if (ATOM(out1->ABL))
               {
               if (!strcmp(VALUE_ATOM(out1->ABL),VALUE_ATOM(out->ABL)))
                  {
                  sortiecon = 1;
                  }
               }
            out1 = out1->NEXT;
            } 
                /* la sortie est connectee a une autre sortie */

         if (sortiecon == 1)
            {
            coNOT++;
            name = gensym("auxc4_not",coNOT);
            if ((!strcmp(VALUE_ATOM(out->ABL),"'0'")) ||
               (!strcmp(VALUE_ATOM(out->ABL),"'1'")))
               {
               if (!strcmp(VALUE_ATOM(out->ABL),"'1'"))
                  beh->BEAUX = beh_addbeaux(beh->BEAUX,name,
                                            createAtom("'0'"),NULL);
               else
                  beh->BEAUX = beh_addbeaux(beh->BEAUX,name,
                                            createAtom("'1'"),NULL);
               }
            else
               beh->BEAUX = beh_addbeaux(beh->BEAUX,name,
                                         notExpr(out->ABL),NULL);
            out->ABL = notExpr(createAtom(name)); 
            }
         
         }
      c4MappExprBeh(beh,out->ABL,mode);
      }
   out = out->NEXT;
   }

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      if (mode == 1)
         {
         printf("je traite %s =\n ",aux->NAME);
         displayExpr(aux->ABL);
         }

      c4MappExprBeh(beh,aux->ABL,mode);
      }
   aux = aux->NEXT;
   }


if (mode == 1)
   printf("fin de la decomposition avec c4\n");

	/* initialisation de mappSys */

mappSys = initMapping();

	/* appel au compilateur c4 sur chaque element de mf_list */

if (mode == 1)
   printf("generation des cellules:  \n");

		/* ===== generation du not ===== */
 
cptCell = 1;

		 /* comportement */


VHB_HEDFIG = not1();
decompileVHDL(VHB_HEDFIG,NULL,0);


		/* logique + physique */

lc_io = interfaceBeh(VHB_HEDFIG);
c4_genPCells(N1,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
             lc_io,(VHB_HEDFIG->BEOUT)->NAME,
             VALUE_ATOM(CADR((VHB_HEDFIG->BEOUT)->ABL)),0,0,0,0);


		/* operateur interne pour la bst */

ident = namealloc("not1");
addOper(ident);
mappSys->ptcell = 
   initCellList(mappSys->ptcell,ident,'l',VHB_HEDFIG);

mappSys->ptcell->nom = VHB_HEDFIG->NAME;


recupGeneric(VHB_HEDFIG,mappSys->ptcell);

addTH(mappSys->cell_hash,ident,mappSys->ptcell);

if (mode == 1)
   displayCell(mappSys->ptcell);


if (beh->BEREG)
   {
   biabl_list *biablN;
   bereg_list *reg;
   int stable;

   cptCell = cptCell + 2;

		/* =====  generation du latch 1 ===== */

		/* comportement */


   VHB_HEDFIG = latch1();
   decompileVHDL(VHB_HEDFIG,NULL,0);



		/* logique + physique */

   lc_io = interfaceBeh(VHB_HEDFIG);
   biabl = (VHB_HEDFIG->BEREG)->BIABL;
   c4_genPCells(L1,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                lc_io, (VHB_HEDFIG->BEOUT)->NAME,
                VALUE_ATOM(biabl->VALABL),
                VALUE_ATOM(biabl->CNDABL),
                (VHB_HEDFIG->BEREG)->NAME,0,0);


		/* operateur interne pour la bst */

   ident = namealloc("reg1");
   addOper(ident);
   mappSys->ptcell = 
      initCellList(mappSys->ptcell,ident,'r',VHB_HEDFIG);

   recupGeneric(VHB_HEDFIG,mappSys->ptcell);
   mappSys->ptcell->nom = VHB_HEDFIG->NAME; 
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);
   



		/* =====  generation du latch 2 ===== */

		/* comportement */


   VHB_HEDFIG = latch2();
   decompileVHDL(VHB_HEDFIG,NULL,0);



		/* logique + physique */

   lc_io = interfaceBeh(VHB_HEDFIG);
   biabl = (VHB_HEDFIG->BEREG)->BIABL;
   biablN = biabl->NEXT;
   c4_genPCells(L2,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                lc_io, (VHB_HEDFIG->BEOUT)->NAME,
                VALUE_ATOM(biabl->VALABL),
                VALUE_ATOM(biabl->CNDABL),
                VALUE_ATOM(biablN->VALABL),
                VALUE_ATOM(biablN->CNDABL),
                (VHB_HEDFIG->BEREG)->NAME);


		/* operateur interne pour la bst */

   ident = namealloc("reg2");
   addOper(ident);
   mappSys->ptcell = 
      initCellList(mappSys->ptcell,ident,'r',VHB_HEDFIG);

   recupGeneric(VHB_HEDFIG,mappSys->ptcell);
   mappSys->ptcell->nom = VHB_HEDFIG->NAME; 
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);

   if (beh->TYPE & BEH_STABLE)
      {
		/* =====  generation de la Bascule D ===== */

		/* comportement */


      VHB_HEDFIG = bd();
      decompileVHDL(VHB_HEDFIG,NULL,0);


		/* logique + physique */

		/* on invente un nom de point memo pour le slave */

      lc_io = interfaceBeh(VHB_HEDFIG);
      biabl = (VHB_HEDFIG->BEREG)->BIABL;
      c4_genPCells(BD,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                   lc_io, (VHB_HEDFIG->BEOUT)->NAME,
                   VALUE_ATOM(biabl->VALABL),
                   VALUE_ATOM(CADR(biabl->CNDABL)),
                   genNAME("%ss",(VHB_HEDFIG->BEREG)->NAME),
                   (VHB_HEDFIG->BEREG)->NAME);


		/* operateur interne pour la bst */

      ident = namealloc("bd1");
      addOper(ident);
      mappSys->ptcell = 
         initCellList(mappSys->ptcell,ident,'d',VHB_HEDFIG);

      recupGeneric(VHB_HEDFIG,mappSys->ptcell);
      mappSys->ptcell->nom = VHB_HEDFIG->NAME; 
      addTH(mappSys->cell_hash,ident,mappSys->ptcell);
      if (mode == 1)
         displayCell(mappSys->ptcell);
      }
   }

		/* ===== generation du bus 1 ===== */

if (beh->BEBUS || beh->BEBUX)
   {
   chain_list *support;
   char *com1, *com2;

   cptCell++;

		/* comportement */


   VHB_HEDFIG = bus1();
   decompileVHDL(VHB_HEDFIG,NULL,0);

		/* logique + physique */

   lc_io = interfaceBeh(VHB_HEDFIG);

             /* calcul des commandes par collage */

   biabl = (VHB_HEDFIG->BEBUS)->BIABL;


   support = supportChain_listExpr(biabl->CNDABL);
 
   com1 = (char *) support->DATA;
   com2 = (char *) (support->NEXT)->DATA;
 
   if (ATOM(simplif10Expr(substExpr(biabl->CNDABL,com1,createAtom("'1'")))))
      {
      com2 = (char *) support->DATA;
      com1 = (char *) (support->NEXT)->DATA;
      }

   c4_genPCells(NT1,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                lc_io,(VHB_HEDFIG->BEBUS)->NAME,
                VALUE_ATOM(CADR(biabl->VALABL)),com1,com2,0,0);


		/* operateur interne pour la bst */

   ident = namealloc("bus1");
   addOper(ident);
   mappSys->ptcell = 
      initCellList(mappSys->ptcell,ident,'b',VHB_HEDFIG);

   recupGeneric(VHB_HEDFIG,mappSys->ptcell);
   mappSys->ptcell->nom = VHB_HEDFIG->NAME; 
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);
   }
   
		/* ===== cellule HIGH ===== */

if (searchNameBeh(beh,"'1'"))
   {
   cptCell++;

		/* comportement */

   VHB_HEDFIG = high1();
   decompileVHDL(VHB_HEDFIG,NULL,0);


		/* logique + physique */

   lc_io = interfaceBeh(VHB_HEDFIG);
   c4_genPCells(HIGH,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                lc_io,(VHB_HEDFIG->BEOUT)->NAME,0,0,0,0,0);

		/* operateur interne pour la bst */

   ident = namealloc("high");
   addOper(ident);
   mappSys->ptcell = 
      initCellList(mappSys->ptcell,ident,'l',VHB_HEDFIG);

   recupGeneric(VHB_HEDFIG,mappSys->ptcell);
   mappSys->ptcell->nom = VHB_HEDFIG->NAME; 
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);
   }
   
		/* ===== cellule LOW ===== */

if (searchNameBeh(beh,"'0'"))
   {
   cptCell++;

		/* comportement */

   VHB_HEDFIG = low1();
   decompileVHDL(VHB_HEDFIG,NULL,0);


		/* logique + physique */

   lc_io = interfaceBeh(VHB_HEDFIG);
   c4_genPCells(LOW,VHB_HEDFIG->NAME,SL_NUMCANP,SL_NUMCANN,
                lc_io,(VHB_HEDFIG->BEOUT)->NAME,0,0,0,0,0);

		/* operateur interne pour la bst */

   ident = namealloc("low");
   addOper(ident);
   mappSys->ptcell = 
      initCellList(mappSys->ptcell,ident,'l',VHB_HEDFIG);

   recupGeneric(VHB_HEDFIG,mappSys->ptcell);
   mappSys->ptcell->nom = VHB_HEDFIG->NAME;
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);
   }

		/* les autres cellules logiques */

printf("C4 compilation : \n");
pCL = mf_list;
while (pCL)
   {
   MemFig *memF = (MemFig *) pCL->DATA;
   ident = memF->fName;

   printf("-- %s\n",ident);
   if (SL_TRACE)
      {
      displayExpr(memF->inExprABL);
      displayExpr(memF->trExprABL);
      }
   c4_gen(memF,1,1,1);


   if (mode == 1)
      c4_dbg_printInfo(memF);
   addOper(ident);
   mappSys->ptcell = 
            initCellList(mappSys->ptcell,ident,'l',memF->beh);

   recupGeneric(memF->beh,mappSys->ptcell);
   addTH(mappSys->cell_hash,ident,mappSys->ptcell);
   if (mode == 1)
      displayCell(mappSys->ptcell);
   cptCell++;
   pCL = pCL->NEXT;
   }

	/* compteurs d'instances et de pitches*/

cptInst = 0;
cptPitch = 0;

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      if (mode == 1)
         {
         printf("je traite %s =\n ",out->NAME);
         displayExpr(out->ABL);
         }
      if (ATOM(out->ABL))
         {
         if (!strcmp(VALUE_ATOM(out->ABL),"'0'"))
            {
            if (c4Low == NULL)
               {
               c4Low = namealloc("c4Low");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
               cptPitch++;
               }
            out->ABL = createAtom(c4Low);
            }
         if (!strcmp(VALUE_ATOM(out->ABL),"'1'"))
            {
            if (c4High == NULL)
               {
               c4High = namealloc("c4High");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
               cptPitch++;
               }
            out->ABL = createAtom(c4High);
            }
         }
      else
         {
         out->ABL = c4GenCell(out->ABL,mode);

		/* calcul du nombre de pitch */

         name = searchCharOper(OPER(out->ABL));
         if ((val = searchTH(pTC4,name)) != EMPTYTH)
            {
            memF = (MemFig *) val;
            cptPitch = cptPitch + memF->nbCut + memF->nbInp +
                       memF->result->polarity + 1;
            }
         else 			/* c'est un not1 */
            cptPitch = cptPitch + 2;
         }
      cptInst++;
      }
   out = out->NEXT;
   }

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      if (mode == 1)
         {
         printf("je traite %s =\n ",aux->NAME);
         displayExpr(aux->ABL);
         }
      if (ATOM(aux->ABL))
         {
         if (!strcmp(VALUE_ATOM(aux->ABL),"'0'"))
            {
            if (c4Low == NULL)
               {
               c4Low = namealloc("c4Low");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
               cptPitch++;
               }
            aux->ABL = createAtom(c4Low);
            }
         if (!strcmp(VALUE_ATOM(aux->ABL),"'1'"))
            {
            if (c4High == NULL)
               {
               c4High = namealloc("c4High");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
               cptPitch++;
               }
            aux->ABL = createAtom(c4High);
            }
         }
      else
         {
         aux->ABL = c4GenCell(aux->ABL,mode);
		/* calcul du nombre de pitch */

         name = searchCharOper(OPER(aux->ABL));
         if ((val = searchTH(pTC4,name)) != EMPTYTH)
            {
            memF = (MemFig *) val;
            cptPitch = cptPitch + memF->nbCut + memF->nbInp +
                       memF->result->polarity + 1;
            }
         else 			/* c'est un not1 */
            cptPitch = cptPitch + 2;
         }
      cptInst++;
      }
   aux = aux->NEXT;
   }


reg = beh->BEREG;
while (reg) 
   {
   chain_list *LC = NULL;
   if (mode == 1)
      printf("je traite le registre %s =\n ",reg->NAME);

   biabl = reg->BIABL;

   if (biabl && biabl->NEXT == NULL)
      {            
      if (!strcmp(VALUE_ATOM(biabl->CNDABL),"'0'"))
         {
         if (c4Low == NULL)
            {
            c4Low = namealloc("c4Low");
            beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
            cptPitch++;
            }
         LC = addchain(LC,c4Low); 
         }
      else
         if (!strcmp(VALUE_ATOM(biabl->CNDABL),"'1'"))
            {
            if (c4High == NULL)
               {
               c4High = namealloc("c4High");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
               cptPitch++;
               }
            LC = addchain(LC,c4High); 
            }
         else
            LC = addchain(LC,VALUE_ATOM(biabl->CNDABL));
      if (!strcmp(VALUE_ATOM(biabl->VALABL),"'0'"))
         {
         if (c4Low == NULL)
            {
            c4Low = namealloc("c4Low");
            beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
            cptPitch++;
            }
         LC = addchain(LC,c4Low); 
         }
      else
         if (!strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
            {
            if (c4High == NULL)
               {
               c4High = namealloc("c4High");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
               cptPitch++;
               }
            LC = addchain(LC,c4High); 
            }
         else
            LC = addchain(LC,VALUE_ATOM(biabl->VALABL));
      cptPitch = cptPitch + 5;
      freeExpr(biabl->VALABL);
      freeExpr(biabl->CNDABL);
      biabl->VALABL = createExprCL(searchNumOper(namealloc("reg1")),LC);
      biabl->CNDABL = NULL;
      }
   else
      if (biabl->NEXT && biabl->NEXT->NEXT == NULL)
         {
         while(biabl)
           {
           if (!strcmp(VALUE_ATOM(biabl->CNDABL),"'0'"))
              {
              if (c4Low == NULL)
                 {
                 c4Low = namealloc("c4Low");
                 beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
                 cptPitch++;
                 }
              LC = addchain(LC,c4Low); 
              }
           else
              if (!strcmp(VALUE_ATOM(biabl->CNDABL),"'1'"))
                 {
                 if (c4High == NULL)
                    {
                    c4High = namealloc("c4High");
                    beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
                    cptPitch++;
                    }
                 LC = addchain(LC,c4High); 
                 }
              else
                 LC = addchain(LC,VALUE_ATOM(biabl->CNDABL));
           if (!strcmp(VALUE_ATOM(biabl->VALABL),"'0'"))
              {
              if (c4Low == NULL)
                 {
                 c4Low = namealloc("c4Low");
                 beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
                 cptPitch++;
                 }
              LC = addchain(LC,c4Low); 
              }
           else
              if (!strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
                 {
                 if (c4High == NULL)
                    {
                    c4High = namealloc("c4High");
                    beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
                    cptPitch++;
                    }
                 LC = addchain(LC,c4High); 
                 }
              else
                 LC = addchain(LC,VALUE_ATOM(biabl->VALABL));
           freeExpr(biabl->VALABL);
           freeExpr(biabl->CNDABL);
           biabl = biabl->NEXT;
           }
         biabl = reg->BIABL;
         biabl->VALABL = createExprCL(searchNumOper(namealloc("reg2")),LC);
         biabl->CNDABL = NULL;
         cptPitch = cptPitch + 7;
         }
   reg = reg->NEXT;
   cptInst++;
   }

bus = beh->BEBUS;
while (bus) 
   {
   if (mode == 1)
      printf("je traite le bus %s =\n ",bus->NAME);

   biabl = bus->BIABL;

   while(biabl)
      {
      chain_list *LC = NULL;
      int numOper = searchNumOper(namealloc("not1"));

      /* creation d'une var. aux. pour la commande inversee du bus */

      char *newViCND = genNAME("notc4map_%s",VALUE_ATOM(biabl->CNDABL));

      LC = addchain(LC,VALUE_ATOM(biabl->CNDABL)); /* pour c2 */

		/* pour c1=not c2 */

      aux = beh->BEAUX;
      while (aux && strcmp(aux->NAME,newViCND))
         {
         aux = aux->NEXT;
         }

		/* on cree not c2 */
      if (!aux)
         {
         chain_list *auxCND;

         auxCND = createExpr(numOper);
         addQExpr(auxCND,copyExpr(biabl->CNDABL));
         beh->BEAUX = beh_addbeaux(beh->BEAUX,newViCND,auxCND,NULL);
         }

      LC = addchain(LC,newViCND); 

		/* la donnee est un atome */

      if (strcmp(VALUE_ATOM(biabl->VALABL),"'0'") &&
          strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
         {
         LC = addchain(LC,VALUE_ATOM(biabl->VALABL));
         }
      else
         if (!strcmp(VALUE_ATOM(biabl->VALABL),"'0'"))
            {
            if (c4Low == NULL)
               {
               c4Low = namealloc("c4Low");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
               cptPitch++;
               }
            LC = addchain(LC,c4Low); 
            }
         else
            if (!strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
               {
               if (c4High == NULL)
                  {
                  c4High = namealloc("c4High");
                  beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
                  cptPitch++;
                  }
               LC = addchain(LC,c4High); 
               }

      freeExpr(biabl->VALABL);
      freeExpr(biabl->CNDABL);
      biabl->VALABL = createExprCL(searchNumOper(namealloc("bus1")),LC);
      biabl->CNDABL = NULL;
      biabl = biabl->NEXT;
      cptInst++;
      cptPitch = cptPitch + 4;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   if (mode == 1)
      printf("je traite le bux %s =\n ",bux->NAME);

   biabl = bux->BIABL;

   while(biabl)
      {
      chain_list *LC = NULL;
      int numOper = searchNumOper(namealloc("not1"));

      /* creation d'une var. aux. pour la commande inversee du bux */

      char *newViCND = genNAME("notc4map_%s",VALUE_ATOM(biabl->CNDABL));

      LC = addchain(LC,VALUE_ATOM(biabl->CNDABL)); /* pour c2 */

		/* pour c1=not c2 */

      aux = beh->BEAUX;
      while (aux && strcmp(aux->NAME,newViCND))
         {
         aux = aux->NEXT;
         }

		/* on cree not c2 */
      if (!aux)
         {
         chain_list *auxCND;

         auxCND = createExpr(numOper);
         addQExpr(auxCND,copyExpr(biabl->CNDABL));
         beh->BEAUX = beh_addbeaux(beh->BEAUX,newViCND,auxCND,NULL);
         }

      LC = addchain(LC,newViCND); 

		/* la donnee est un atome */

      if (strcmp(VALUE_ATOM(biabl->VALABL),"'0'") &&
          strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
         {
         LC = addchain(LC,VALUE_ATOM(biabl->VALABL));
         }
      else
         if (!strcmp(VALUE_ATOM(biabl->VALABL),"'0'"))
            {
            if (c4Low == NULL)
               {
               c4Low = namealloc("c4Low");
               beh->BEAUX = beh_addbeaux(beh->BEAUX,c4Low,createAtom("low"),NULL);
               cptPitch++;
               }
            LC = addchain(LC,c4Low); 
            }
         else
            if (!strcmp(VALUE_ATOM(biabl->VALABL),"'1'"))
               {
               if (c4High == NULL)
                  {
                  c4High = namealloc("c4High");
                  beh->BEAUX = beh_addbeaux(beh->BEAUX,c4High,createAtom("high"),NULL);
                  cptPitch++;
                  }
               LC = addchain(LC,c4High); 
               }

      freeExpr(biabl->VALABL);
      freeExpr(biabl->CNDABL);
      biabl->VALABL = createExprCL(searchNumOper(namealloc("bus1")),LC);
      biabl->CNDABL = NULL;
      biabl = biabl->NEXT;
      cptInst++;
      cptPitch = cptPitch + 4;
      }
   bux = bux->NEXT;
   }

if (mode == 1)
   printf("desallocation des cellules:  \n");

pCL = mf_list;
while (pCL)
   {
   MemFig *memF = (MemFig *) pCL->DATA;
   ident = memF->fName;

   if (strcmp(ident,"not1"))
      {
      deleteTH(pTC4,ident);
      c4_free(memF);
      }
   pCL = pCL->NEXT;
   }
if (mode == 1)
   displayBeh(beh,0);

}
