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

#include "head.h"

/*-------------------------------------------------------------------------
_elimSignal	: renvoie 1 si le signal doit etre elimine 
---------------------------------------------------------------------------
retour		: un int.
---------------------------------------------------------------------------*/
int _elimSignal(occ,num)
int occ,num;
{
if ( occ == 1 || num == 1)
   return(1);
else
   return(0);
}

/*-------------------------------------------------------------------------
_substTHOccExpr : susbtitue les auxiliaires  de trop petite granularite
                 par leurs expressions associes. 
---------------------------------------------------------------------------
retour		: une expression.
---------------------------------------------------------------------------*/
chain_list *_substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,expr,dejaTraite)
befig_list *beh;
pTH pTHOcc;
pTH pTHNum;
pTH pTHAux;
chain_list *expr;
pTH dejaTraite;
{
if (expr == NULL)
   {
   printf("_substTHOccExpr : error - expression = NULL\n");
   exit(-1);
   }

if (ATOM(expr))
   {
   int num,occ;

   if (!strcmp(VALUE_ATOM(expr),"'0'") ||
       !strcmp(VALUE_ATOM(expr),"'1'") ||
       !strcmp(VALUE_ATOM(expr),"'d'"))
      return(copyExpr(expr));


		/* c'est un signal auxiliaire */

   if ((occ = searchTH(pTHOcc,VALUE_ATOM(expr))) != EMPTYTH)
      {
      beaux_list *aux;

      num = searchTH(pTHNum,VALUE_ATOM(expr));

      aux = (beaux_list *) searchTH(pTHAux,VALUE_ATOM(expr));
      if (aux == (beaux_list *) EMPTYTH)
         {
         printf("_substTHOccExpr : error auxiliary signal doesn't exist %s\n",aux->NAME);
         exit(-1);
         }

      if (_elimSignal(occ,num))
         {

         	/* substitution du signal */

		/* si le signal a deja ete traite */

         if (searchTH(dejaTraite,VALUE_ATOM(expr)) != EMPTYTH)
            return(copyExpr(aux->ABL));

         addTH(dejaTraite,VALUE_ATOM(expr),1);


                /* descente recursive dans la befig */

         aux->ABL= _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,aux->ABL,dejaTraite);
         return(copyExpr(aux->ABL));
         }
      else
         {	/* pas de substitution */

         if (searchTH(dejaTraite,VALUE_ATOM(expr)) != EMPTYTH)
            return copyExpr(expr);

                /* descente recursive dans la befig */

         addTH(dejaTraite,VALUE_ATOM(expr),1);
         aux->ABL= _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,aux->ABL,dejaTraite);
         return(copyExpr(expr));
         }
      }
		/* ce n'est pas une variable aux. */

   return (copyExpr(expr));
   }
else
   {
   chain_list *ret;

   ret = createExpr(OPER(expr));
   while (expr = CDR(expr))
      {
      addQExpr(ret,
               _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,CAR(expr),dejaTraite));
      }
   return(ret);
   }
}
/*-------------------------------------------------------------------------
remplTHOccExpr : changement de la granularite des equations par elimination
		selective des signaux intermediaires. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void remplTHOccExpr(pTHOcc,expr)
pTH pTHOcc;
chain_list *expr;
{
int occ;

if (ATOM(expr))
   {
   occ = searchTH(pTHOcc,VALUE_ATOM(expr));
   if (occ != EMPTYTH)
      {
		/* signal auxiliaire : on incremente */

      addTH(pTHOcc,VALUE_ATOM(expr),1 + occ);
      } 
   }
else
   {
   while (expr = CDR(expr))
      remplTHOccExpr(pTHOcc,CAR(expr));
   }
}
/*-------------------------------------------------------------------------
remplTHOccBeh : remplit une table de hachage avec les occurences des signaux
		que l'on a entree dedans precedemment. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void remplTHOccBeh(beh,pTHOcc)
befig_list *beh;
pTH pTHOcc;
{
beout_list *out;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
beaux_list *aux;

	/* parcours de la befig avec remplissage de pTHOcc */

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      remplTHOccExpr(pTHOcc,aux->ABL);
      }
   aux = aux->NEXT;
   }

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      remplTHOccExpr(pTHOcc,out->ABL);
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         remplTHOccExpr(pTHOcc,biabl->CNDABL);
         remplTHOccExpr(pTHOcc,biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         remplTHOccExpr(pTHOcc,biabl->CNDABL);
         remplTHOccExpr(pTHOcc,biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         remplTHOccExpr(pTHOcc,biabl->CNDABL);
         remplTHOccExpr(pTHOcc,biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }
}

/*-------------------------------------------------------------------------
compactBeh	: changement de la granularite des equations par elimination
		selective des signaux intermediaires. 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void compactBeh(beh)
befig_list *beh;
{
beout_list *out;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
beaux_list *aux,*auxp;
chain_list *expr;
chain_list *_substTHOccExpr();

pTH pTHOcc,pTHNum,pTHAux,dejaTraite;

		/* elimination des 1 et 0 */

mapCarExprBeh(beh,simplif10Expr);



pTHNum = createTH(100);	/* table des auxiliaires/nombre de litteraux */
pTHOcc = createTH(100); /* table des auxiliaires/nombre d'occurences */
pTHAux = createTH(100); /* table des auxiliaires/expression */


dejaTraite = createTH(100);

	/* parcours des auxiliares avec remplissage des tables de hachage */

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      addTH(pTHOcc,aux->NAME,0);
      addTH(pTHNum,aux->NAME,numberAtomExpr(aux->ABL));
      addTH(pTHAux,aux->NAME,(int) aux);
      }
   aux = aux->NEXT;
   }
	/* remplissage de la table pTHOcc */

remplTHOccBeh(beh,pTHOcc);

 
 
		/* substitution des signaux auxiliaires inutiles */

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

   if (out->ABL)
      {
      expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,out->ABL,dejaTraite);

      freeExpr(out->ABL);
      out->ABL = expr;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->CNDABL,dejaTraite);
         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;

         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->VALABL,dejaTraite);
         freeExpr(biabl->VALABL);
         biabl->VALABL = expr;
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->CNDABL,dejaTraite);

         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;

         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->VALABL,dejaTraite);
         freeExpr(biabl->VALABL);
         biabl->VALABL = expr;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }


bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->CNDABL,dejaTraite);

         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;

         expr = _substTHOccExpr(beh,pTHOcc,pTHNum,pTHAux,biabl->VALABL,dejaTraite);
         freeExpr(biabl->VALABL);
         biabl->VALABL = expr;
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }

	/* elimination des signaux auxiliaires expanses */ 

	/* on recalcule le fanout des variables auxiliaires */

destroyTH(pTHOcc);
pTHOcc = createTH(100);

aux = beh->BEAUX;
while (aux) 
   {
   addTH(pTHOcc,aux->NAME,0);
   aux = aux->NEXT;
   }
	/* remplissage de la table pTHOcc */

remplTHOccBeh(beh,pTHOcc);
 

	/* 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;


		/* simplification des not */

mapCarExprBeh(beh,simplifNotExpr);

mapExprBeh(beh,flatArityExpr);

destroyTH(pTHOcc);
destroyTH(pTHNum);
destroyTH(pTHAux);
destroyTH(dejaTraite);
}
