/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur Logique                                       */
/*    Fichier :  costlogic.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 : 08/01/1991     */
/*                                                                          */
/*    Modifie par :                                     le : 15/03/92       */
/*    Modifie par :                                     le : 06/04/92       */
/*    Modifie par :                                     le : 06/07/93       */
/*                                                                          */
/****************************************************************************/

#include <math.h>
#include MUT_H
#include LOG_H
#include BEH_H
      

/*------------------------------------------------------------------------------
numberAtomRedFacto2  : renvoie le nombre de litteraux reduit 
                       realisant le multiplexeur a.H + a'.L
-------------------------------------------------------
parametres 	 : Deux pNode et le nombre de litteraux de la commande 
-------------------------------------------------------
return 		 : un int
------------------------------------------------------------------------------*/
int numberAtomRedFacto2(high,low,cpt)
pNode high,low;
int cpt;
{
pNode pBdd;

	/*--------- multiplexeur terminal ---------*/

if (low->index < 2 && high->index < 2)
   return(cpt);

	/*--------- multiplexeur semi-terminal ---------*/

if (low == one || low == zero)	/* F = (or (not a) H) */
    return(cpt + numberAtomRedFact(high));

if (high == one || high == zero)	/* F = (or a L) */
    return(cpt + numberAtomRedFact(low));


pBdd = applyBinBdd(AND,high,low);

if (pBdd == zero)	
   {
   if (applyBinBdd(OR,low,high) == one)
      return(cpt + numberAtomRedFact(high));
   else
      {
      if (cpt == 1)
         return(2 + numberAtomRedFact(low) + numberAtomRedFact(high));
      else
         return(cpt + 2 + numberAtomRedFact(low) + numberAtomRedFact(high));
      }
   }

		/* H est inclu dans L */

		/* F = H + a'.L(H=*) */

if (pBdd == high)
   {
   return(cpt + numberAtomRedFact(high) + 
                numberAtomRedFact(simplifDcOneBdd(low,high)));
   }


		/* L est inclu dans H */

		/* F = L + a.H(L=*) */

if (pBdd == low)
   {
   return(cpt + numberAtomRedFact(low) + 
                numberAtomRedFact(simplifDcOneBdd(high,low)));
   }

		/* cas general */

		/* F = a'.L + a.H  */

if (cpt == 1)
   return(2 + numberAtomRedFact(low) + numberAtomRedFact(high));
else
   return(cpt + 2 + numberAtomRedFact(low) + numberAtomRedFact(high));
}

/*------------------------------------------------------------------------------
numberAtomRedFact  : calcule le nombre de litteraux reduits
                     fonction de cout pour l'ordonnancement
-------------------------------------------------------
parametres 	 :un pointeur de NODE.
-------------------------------------------------------
return 		 :un int 
------------------------------------------------------------------------------*/
int numberAtomRedFact(pt)
pNode pt;
{
pNode pBdd;
pNode ptNotBdd;
int cpt;
pNode pLow, pHigh;

	/*----------------- noeud ONE ou ZERO ------------------*/

if (pt->index < 2)
   return(0);

		  /* noeud atomique */

if ((pt->low)->index < 2 && (pt->high)->index < 2)
   return(1);

        /*------------------ deja traite -------------------------*/

                  /* premiere occurence */

if (pt->mark == 1)
   {
   pt->mark = 2;
   ptNotBdd = notBdd(pt); 
   ptNotBdd->mark = 2;
   return(2);
   }

		/* x-ieme occurence (x > 1) */

if (pt->mark == 2)
   return(1);

        /*------------------ non traite -------------------------*/

pt->mark = 1;

	/*----------------- variable semi-terminale -----------------*/

if ((pt->low)->index < 2 || (pt->high)->index < 2)
   {
   if (pt->low == one || pt->low == zero)	
      cpt = 1+numberAtomRedFact(pt->high);

   if (pt->high == one || pt->high == zero)
      cpt = 1+numberAtomRedFact(pt->low);

   ptNotBdd = notBdd(pt); 
   ptNotBdd->mark = 1;
   return(cpt);
   }

cpt = 1;
pHigh = pt->high;	/* initialisation pHigh et pLow */
pLow  = pt->low;

if (1)
   { 


   if (pt->high == (pt->low)->high || pt->high == (pt->low)->low ||
       pt->low == (pt->high)->low || pt->low == (pt->high)->high ||
       (((pt->high)->index == (pt->low)->index) && 
       ((pt->high)->low == (pt->low)->high) && 
       ((pt->high)->high == (pt->low)->low)))
       {

       pBdd = pt;		/* sauvegarde de pt */
         
       while ((pHigh->index > 1 && pLow->index > 1) &&
                ((pHigh == (pLow)->high || pHigh == (pLow)->low   ||
                pLow  == (pHigh)->low || pLow  == (pHigh)->high ||
                ((pHigh->index == pLow->index) && 
                 (pHigh->low == pLow->high) && (pHigh->high == pLow->low)))))
               {
				/* noyaux OU */

               if (pHigh == (pLow)->high || pHigh == (pLow)->low)
                  {
                  pt = pLow;

                  while (pt->high == pHigh || pt->low == pHigh)
                     {
                     if (pt->high == pHigh)
	                {
                        cpt++; 
                        pt = pt->low;
   	                }
      	             else
	                {
                        cpt++; 
	                pt = pt->high;
 	                }
                     }
                  pLow = pt;		/* mise a jour de pLow */
                  }
				/* noyaux ET */

               if (pLow == (pHigh)->low || pLow == (pHigh)->high)
	          {
                  pt = pHigh;
   
                  while (pt->low == pLow || pt->high == pLow)
                     {     
                     if (pt->low == pLow)
	                {
                        cpt++; 
                        pt = pt->high;
	                }
                     else
	                {
                        cpt++; 
                        pt = pt->low;
	                }
                     }
                  pHigh = pt;		/* mise a jour de pHigh */
                  }

			/* noyaux XOR-NXOR */

               if (RULES_XOR)
                  {
                  if ((pHigh)->index == (pLow)->index)
                     {
	             if ((pHigh->high == pLow->low) && (pLow->high == pHigh->low))
                        {
                        cpt++; 
	                pHigh = pHigh->low;
	                pLow =  pLow->low;
                        }
                     }
                  }
               }

         pt = pBdd;	/* on recupere le pt initial */
         }
      }

         	/* recherche de simplifications au 2eme niveau */

   if (cpt == 1 && (pt->high)->index == (pt->low)->index)
      {

			/* HL = LH */

      if ((pt->high)->low == (pt->low)->high && ((pt->high)->low)->index > 1)
         {
         if (((pt->high)->high)->index < 2 && ((pt->low)->low)->index < 2)
            {
            return(4 + numberAtomRedFact((pt->high)->low));
            }
         }

			/* HH = LL */

      if ((pt->high)->high == (pt->low)->low && ((pt->high)->high)->index > 1)
         {
         if (((pt->high)->low)->index < 2 && ((pt->low)->high)->index < 2)
            {
            return(4 + numberAtomRedFact((pt->high)->high));
            }
         }
   
			   /* HH = LH */
   
      if ((pt->high)->high == (pt->low)->high && ((pt->high)->high)->index > 1)
         {
         if (((pt->high)->low)->index < 2 && ((pt->low)->low)->index < 2)
            {
            return(3 + numberAtomRedFact((pt->high)->high));
            }
         }
   
			   /*  HL = LL */
   
      if ((pt->high)->low == (pt->low)->low && ((pt->high)->low)->index > 1)
         {
         if (((pt->high)->high)->index < 2 && ((pt->low)->high)->index < 2)
            {
            return(3 + numberAtomRedFact((pt->high)->low));
            }
         }
      }

	/*---------------- variable non-terminale ----------------*/


		/*  (or (and a H) (and (not a) L) */

cpt = numberAtomRedFacto2(pHigh,pLow,cpt);

ptNotBdd = notBdd(pt); 
ptNotBdd->mark = 1;

return(cpt);
}

/*-------------------------------------------------------------------------
numberAtomRedBeh 	: calcule le nombre d'atome reduit d'une befig 
---------------------------------------------------------------------------
retour		: un entier.
---------------------------------------------------------------------------*/

int numberAtomRedBeh(beh)
befig_list *beh;
{
int i,numAtomRed;
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
binode_list *binode;

numAtomRed = 0;
markAllBdd(0);

out = beh->BEOUT;
while (out)
   {
   if (out->NODE)
      numAtomRed = numAtomRed + numberAtomRedFact(out->NODE);
   out = out->NEXT;
   }

aux = beh->BEAUX;
while (aux)
   {
   if (aux->NODE)
      numAtomRed = numAtomRed + numberAtomRedFact(aux->NODE);
   aux = aux->NEXT;
   }

reg = beh->BEREG;
while (reg)
   {
   binode = reg->BINODE;
   while (binode)
      {
      if (binode->CNDNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->CNDNODE);
      if (binode->VALNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->VALNODE);
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus)
   {
   binode = bus->BINODE;
   while (binode)
      {
      if (binode->CNDNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->CNDNODE);
      if (binode->VALNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->VALNODE);
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux)
   {
   binode = bux->BINODE;
   while (binode)
      {
      if (binode->CNDNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->CNDNODE);
      if (binode->VALNODE)
         numAtomRed = numAtomRed + numberAtomRedFact(binode->VALNODE);
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }

markAllBdd(0);
return(numAtomRed);
}
