/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : synthetiseur logique                                        */
/*    Fichier : prep.h                                                      */
/*                                                                          */
/*    (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 || 
    (occ == 2 && num <= 3) || 
    (occ == 3 && num <= 2) || 
     num == 1)
   return(1);
else
   return(0);
}

/*-------------------------------------------------------------------------
mapCarExprBeh	: applique une fonction de conversion sur chaque expression
                  d'une befig 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void mapCarExprBeh(beh,func)

befig_list *beh;
chain_list *(*func)();
{
beout_list *out;
bereg_list *reg;
bebus_list *bus;
biabl_list *biabl;
beaux_list *aux;
chain_list *expr;


aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      expr = (*func)(aux->ABL);
      freeExpr(aux->ABL); 
      aux->ABL = expr;
      }
   aux = aux->NEXT;
   }

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      expr = (*func)(out->ABL);
      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 = (*func)(biabl->CNDABL);
         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;
         expr = (*func)(biabl->VALABL);
         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 = (*func)(biabl->CNDABL);
         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;
         expr = (*func)(biabl->VALABL);
         freeExpr(biabl->VALABL);
         biabl->VALABL = expr;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }
}
/*-------------------------------------------------------------------------
mapExprBeh	: applique une procedure sur chaque expression d'une befig 
---------------------------------------------------------------------------
retour		: un void.
---------------------------------------------------------------------------*/
void mapExprBeh(beh,func)
befig_list *beh;
void (*func)();
{
beout_list *out;
bereg_list *reg;
bebus_list *bus;
biabl_list *biabl;
beaux_list *aux;

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

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      (*func)(aux->ABL);
      }
   aux = aux->NEXT;
   }

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      (*func)(out->ABL);
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         (*func)(biabl->CNDABL);
         (*func)(biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         (*func)(biabl->CNDABL);
         (*func)(biabl->VALABL);
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }
}
/*-------------------------------------------------------------------------
substTHOccExpr : susbtitue les auxiliaires  de trop petite granularite
                 par leurs expressions associes. 
---------------------------------------------------------------------------
retour		: une expression.
---------------------------------------------------------------------------*/
chain_list *substTHOccExpr(pTHOcc,pTHNum,pTHAux,expr)
pTH pTHOcc;
pTH pTHNum;
pTH pTHAux;
chain_list *expr;
{
if (ATOM(expr))
   {
   int num,occ;

		/* c'est un signal auxiliaire */

   if ((occ = searchTH(pTHOcc,VALUE_ATOM(expr))) != EMPTYTH)
      {
      num = searchTH(pTHNum,VALUE_ATOM(expr));

      if (elimSignal(occ,num))
         {
         beaux_list *aux;

         	/* substitution du signal */

         aux = (beaux_list *) searchTH(pTHAux,VALUE_ATOM(expr));
         return(substTHOccExpr(pTHOcc,pTHNum,pTHAux,aux->ABL));
         }
      }
   return (copyExpr(expr));
   }
else
   {
   chain_list *ret;
   ret = createExpr(OPER(expr));
   while (expr = CDR(expr))
      {
      addQExpr(ret,substTHOccExpr(pTHOcc,pTHNum,pTHAux,CAR(expr)));
      }
   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))
   {
   if ((occ = searchTH(pTHOcc,VALUE_ATOM(expr))) != 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;
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;
   }
}

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

pTH pTHOcc,pTHNum,pTHAux;

		/* elimination des 1 et 0 */

mapCarExprBeh(beh,simplif10Expr);
checkExprBeh(beh);


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

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

aux = beh->BEAUX;
while (aux) 
   {
   addTH(pTHOcc,aux->NAME,0);
   if (aux->ABL)
      {
      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 */

aux = beh->BEAUX;
while (aux) 
   {
   if (aux->ABL)
      {
      expr = substTHOccExpr(pTHOcc,pTHNum,pTHAux,aux->ABL);
      freeExpr(aux->ABL);
      aux->ABL = expr;
      }
   aux = aux->NEXT;
   }

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      expr = substTHOccExpr(pTHOcc,pTHNum,pTHAux,out->ABL);
      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(pTHOcc,pTHNum,pTHAux,biabl->CNDABL);
         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;
         expr = substTHOccExpr(pTHOcc,pTHNum,pTHAux,biabl->VALABL);
         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(pTHOcc,pTHNum,pTHAux,biabl->CNDABL);
         freeExpr(biabl->CNDABL);
         biabl->CNDABL = expr;
         expr = substTHOccExpr(pTHOcc,pTHNum,pTHAux,biabl->VALABL);
         freeExpr(biabl->VALABL);
         biabl->VALABL = expr;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

	/* elimination des signaux auxiliaires expanses */ 

aux = beh->BEAUX;
auxp = NULL;
while (aux) 
   {
   int num,occ;

   occ = searchTH(pTHOcc,aux->NAME);
   num = searchTH(pTHNum,aux->NAME);

   if (elimSignal(occ,num))
      {
      printf("auxiliary signal erased : %s\n",aux->NAME);
      }
   else
      {
      auxp = beh_addbeaux(auxp,aux->NAME,aux->ABL,NULL);
      } 
   aux = aux->NEXT;
   }
beh->BEAUX = auxp;

		/* simplification des not */

mapCarExprBeh(beh,simplifNotExpr);

mapExprBeh(beh,flatArityExpr);
}
