/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : synthetiseur logique                                        */
/*    Fichier : post.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 : 23/10/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
#include "bib.h"
#include "../compil/lax_param.h"
#include "../synthe/sl_type.h"
#include "../compil/sl_util.h"

#define FANOUT_MAX 4

/*-------------------------------------------------------------------------
phaseExpr : fonction d'optimisation de la phase 

            -----  cellP
            |   |-------------------  numPeigneP
            -----     |-------------
                      |-------------
                      |
                      ----------------|>o---------------   numPeigneN
                                          |-------------
                                          |-------------
                                           -------------
                                          cellN

           si numPeigneN = 0  RAS (on ne passe pas dans cette fonction)
           si numPeigneP = 1  on elimine cellP en substituant son equation
                              dans cellN en verifiant la regle de FANOUT 
           sinon 
                 si cellP est une fonction negative RAS 
                 si cellP est une fonction positive
                    on inverse si l'on respecte la regle de FANOUT
---------------------------------------------------------------------------
retour		: void 
---------------------------------------------------------------------------*/
chain_list *phaseExpr(expr,pTHOcc,beh,cellN,sl_aux)
chain_list *expr;
pTH pTHOcc;
befig_list *beh;
char *cellN;
int sl_aux;
{
beaux_list *aux;

if (!ATOM(expr))
   {
   if ((OPER(expr) == NOT) && profExpr(expr) == 1)
      {
      char *cellP = VALUE_ATOM(CADR(expr));
      int numPeigneN,numPeigneP;

      numPeigneN = searchTH(pTHOcc,cellN);
      numPeigneP = searchTH(pTHOcc,cellP);

		/* cellP est en fait une entree primaire */

      if (numPeigneP == 0 || numPeigneP == EMPTYTH)
         return (copyExpr(expr));

      aux = beh->BEAUX;
      while (aux && strcmp(cellP,aux->NAME))
         aux = aux->NEXT;

      if (!aux)
         {
         printf("phaseExpr : error - %s doesn't exist\n",cellP);
         exit(-1);
         }

      if (numPeigneP == 1 && sl_aux == 0)  /* cellP a un fanout de 1 */
         {
         if (numPeigneN <= FANOUT_MAX || polarityExpr(aux->ABL) == 0)
            {
/*
            printf("j'elimine %s\n",cellP);
            displayExpr(aux->ABL);
*/
            addTH(pTHOcc,cellP,0);
            return(flatPolarityExpr(aux->ABL,0)); 
            }
         } 

			/* numPeigneP et numPeigneN sont diff. de 0 */

      if (polarityExpr(aux->ABL) == 1)
         {
         if (numPeigneN + 1 <= FANOUT_MAX)
            {
            chain_list *res;

            res = flatPolarityExpr(aux->ABL,0);
            freeExpr(aux->ABL);
            aux->ABL = notExpr(createAtom(cellN)); 
/*
            printf("Changement de phase (%s,%s) :\n",cellP,cellN);
            printf("%s = ",cellP);
            displayExpr(aux->ABL);
            printf("%s = ",cellN);
            displayExpr(res);
*/

            addTH(pTHOcc,cellP,numPeigneP-1);
            addTH(pTHOcc,cellN,numPeigneN+1);
            return(res);
            }
         }
      }
   }
return(copyExpr(expr));
}

/*-------------------------------------------------------------------------
postBeh	: post-traitement pour l'assignation de phase
---------------------------------------------------------------------------
retour		: void 
---------------------------------------------------------------------------*/
void postBeh(beh,sl_aux)
befig_list *beh;
int sl_aux;
{
berin_list *in;
beaux_list *aux,*auxp;
beout_list *out;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
pTH pTHOcc;
chain_list *inter;

pTHOcc = createTH(100); /* table des auxiliaires/nombre d'occurences */


        /* parcours des auxiliares avec remplissage des tables de hachage */
 
aux = beh->BEAUX;
while (aux)
   {
   if (aux->ABL)
      {
      addTH(pTHOcc,aux->NAME,0);
      }
   aux = aux->NEXT;
   }
        /* remplissage de la table pTHOcc */
 
remplTHOccBeh(beh,pTHOcc);
 
out = beh->BEOUT;
while (out)
   {
   if (out->ABL)
      {
      inter = flatPolarityExpr(out->ABL,1);
      freeExpr(out->ABL);
      out->ABL = inter;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg)
   {  
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = flatPolarityExpr(biabl->VALABL,1);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }  
      
bus = beh->BEBUS;
while (bus)
   {  
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = flatPolarityExpr(biabl->VALABL,1);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }  

bux = beh->BEBUX;
while (bux)
   {  
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = flatPolarityExpr(biabl->VALABL,1);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }  

aux = beh->BEAUX;
while (aux)
   {
   if (aux->ABL)
      {
      inter = flatPolarityExpr(aux->ABL,1);
      freeExpr(aux->ABL);
      aux->ABL = inter;
      }
   aux = aux->NEXT;
   }

out = beh->BEOUT;
while (out)
   {
   if (out->ABL)
      {
      inter = phaseExpr(out->ABL,pTHOcc,beh,out->NAME,sl_aux);
      freeExpr(out->ABL);
      out->ABL = inter;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg)
   {  
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = phaseExpr(biabl->VALABL,pTHOcc,beh,reg->NAME,sl_aux);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }  
      
bus = beh->BEBUS;
while (bus)
   {  
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = phaseExpr(biabl->VALABL,pTHOcc,beh,bus->NAME,sl_aux);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }  


bux = beh->BEBUX;
while (bux)
   {  
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         inter = phaseExpr(biabl->VALABL,pTHOcc,beh,bux->NAME,sl_aux);
         freeExpr(biabl->VALABL);
         biabl->VALABL = inter;
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }

aux = beh->BEAUX;
while (aux)
   {
   if (aux->ABL)
      {
      inter = phaseExpr(aux->ABL,pTHOcc,beh,aux->NAME,sl_aux);
      freeExpr(aux->ABL);
      aux->ABL = inter;
      }
   aux = aux->NEXT;
   }

        /* on elimine les signaux de fanout 0 */
 
aux = beh->BEAUX;
auxp = NULL;
while (aux)
   {
   int occ;
 
   occ = searchTH(pTHOcc,aux->NAME);
 
   if (occ != 0)
      {
      auxp = beh_addbeaux(auxp,aux->NAME,aux->ABL,NULL);
      auxp->NODE = aux->NODE;
      }
   aux = aux->NEXT;
   }
beh->BEAUX = auxp;
 
 
destroyTH(pTHOcc);
}
