/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur Logique                                       */
/*    Fichier :  sl_DC.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 : 03/09/1991     */
/*                                                                          */
/*    Modifie par :                                     le : ../../..       */
/*    Modifie par :                                     le : ../../..       */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
      
int costX3000();

/*------------------------------------------------------------------------------
costTab : calcul le cout en nombre de litteraux 
-------------------------------------------------------
parametres 	 : une table de pNode
-------------------------------------------------------
return 		 : int
------------------------------------------------------------------------------*/
int costTab(tab,len,func)
pNode *tab;
int len;
int (*func)();
{
int i;
int count = 0;

markAllBdd(0);

if ((* func) == costX3000)
   {
   chain_list *tete, *lstCLB4 = NULL;

   for (i=0;i<len;i++)
      {
      count = count + costX3000(tab[i],&lstCLB4); 
      }

   tete = lstCLB4;
   while (lstCLB4)
      {
      if (lstCLB4->DATA)
         freechain(lstCLB4->DATA);
      lstCLB4 = lstCLB4->NEXT;
      }
   freechain(tete);
   }
else
   {
   for (i=0;i<len;i++)
      {
      count = count + (* func)(tab[i]); 
      }
   }
markAllBdd(0);
return(count);
}

/*------------------------------------------------------------------------------
sigmaDFBeh     : calcul des DC provenant des entrees 
-------------------------------------------------------
parametres 	 : une befig
-------------------------------------------------------
return 		 : void
------------------------------------------------------------------------------*/
pNode sigmaDFBeh(support,Fon,beh,dejaTraite)
chain_list *support;
pNode Fon;
befig_list *beh;
pTH dejaTraite;
{
pNode ret = zero;
chain_list *supp = support;
beaux_list *aux;
pNode obs;
pNode inter;

	/* parcours du support */

while (supp)
   {
   pNode deja = (pNode) searchTH(dejaTraite,(char *) supp->DATA);


   if (deja != (pNode) EMPTYTH)      /* noeud deja traite */
      {
      aux = beh->BEAUX;
      while (aux && strcmp(aux->NAME,supp->DATA))
         {
         aux = aux->NEXT;
         }

		/* calcul de la fonction d'observabilite */

      obs = applyBinBdd(XOR,
                        constraintBdd(Fon,(pNode) aux->NODE), 
                        constraintBdd(Fon,notBdd((pNode) aux->NODE)));

		/* ajout a la fonction de retour */

      ret = applyBinBdd(OR,ret,applyBinBdd(AND,deja,obs));
      }
   else
      {
      pNode reportDC;

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

      if (aux)
         {

         if (searchExpr(aux->ABL,"'d'"))
            {
            chain_list *expr;

            if (!aux->NODE)
               aux->NODE = ablToBddCct(beh->CIRCUI,aux->ABL); 

            expr = substExpr(aux->ABL,"'d'",createAtom("'1'"));

            deja = applyBinBdd(AND,notBdd(aux->NODE),
                                     ablToBddCct(beh->CIRCUI,expr)); 
            freeExpr(expr);
            }
         else
            deja = zero; 

/*
        printf("DC local : ");
        displayExpr(bddToAblCct(beh->CIRCUI,deja));
*/

		/* report des DC provenant du support */

         reportDC = sigmaDFBeh(supportChain_listExpr(aux->ABL),deja,
                                  beh,dejaTraite);
         if (reportDC != zero)
            deja = applyBinBdd(OR,deja,reportDC);

/*
        printf("DC en fn des entrees : ");
        displayExpr(bddToAblCct(beh->CIRCUI,deja));
*/

		/* calcul de la fonction d'observabilite */

         obs = applyBinBdd(XOR,
                           constraintBdd(Fon,(pNode) aux->NODE), 
                           constraintBdd(Fon,notBdd((pNode) aux->NODE)));

		/* ajout a la fonction de retour */

         ret = applyBinBdd(OR,ret,
                  applyBinBdd(AND,deja,obs));

/*
        printf("Observabilite : ");
        displayExpr(bddToAblCct(beh->CIRCUI,ret));
*/
         addTH(dejaTraite,supp->DATA,deja);
         }
      }

/*
printf("NAME = %s\n",supp->DATA);
displayExpr(bddToAblCct(beh->CIRCUI,ret));
*/

   supp = supp->NEXT;
   }


freechain(support);
return ret;
}

/*------------------------------------------------------------------------------
traitementDCBeh     : procedure de prise en compte des Don't care
-------------------------------------------------------
parametres 	 : une befig
-------------------------------------------------------
return 		 : void
------------------------------------------------------------------------------*/
void traitementDCBeh(beh,trace,func)
befig_list *beh;
int trace;
int (*func)();
{
beout_list *out;
beaux_list *aux;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
binode_list *binode;
pNode *pDC;
pNode *pON;
int numberGraph=0;
int i,j;
pNode simplifPlusDcZeroBdd();
pTH dejaTraite;
pNode reportDC;
pElemTH pEl;

dejaTraite = createTH(100);

		/* calcul du nombre de graphes */

printf("Running Don't Care optimization...\n");

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      numberGraph++;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         numberGraph++;
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         numberGraph++;
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         numberGraph++;
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }

pDC = (pNode *) mbkalloc (numberGraph*sizeof(pNode));
pON = (pNode *) mbkalloc (numberGraph*sizeof(pNode));

		/* mise a jour des tables */

i = 0;

if (trace)
   printf("Computing the Don't Care of each signal...\n");

		/* ajout dans la couche circuit des BDD des auxiliaires */

aux = beh->BEAUX;
while (aux)
   {
   if (aux->NODE)
      addOutputCct(beh->CIRCUI,aux->NAME,aux->NODE);
   aux = aux->NEXT;
   }

		/* traitement des sorties primaires */

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      pON[i] = out->NODE;

		/* recherche des DC locaux */

      if (searchExpr(out->ABL,"'d'"))
         {
         chain_list *expr;

         expr = substExpr(out->ABL,"'d'",createAtom("'1'"));

         pDC[i] = applyBinBdd(AND,notBdd(pON[i]),
                                  ablToBddCct(beh->CIRCUI,expr)); 
         freeExpr(expr);
         }
      else
         pDC[i] = zero; 

		/* report des DC provenant du support */
/*
      reportDC = sigmaDFBeh(supportChain_listExpr(out->ABL),out->NODE,
                               beh,dejaTraite);
      if (reportDC != zero)
         pDC[i] = applyBinBdd(OR,pDC[i],reportDC);
*/

      i++;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   binode = reg->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         pON[i] = binode->VALNODE;

		/* recherche des DC locaux */

         if (searchExpr(biabl->VALABL,"'d'"))
            {
            chain_list *expr;

            expr = substExpr(biabl->VALABL,"'d'",createAtom("'1'"));

            pDC[i] = applyBinBdd(AND,notBdd(pON[i]),
                                     ablToBddCct(beh->CIRCUI,expr)); 
            freeExpr(expr);
            }
         else
            pDC[i] = zero; 

		/* report des DC provenant du support */
/*
         reportDC = sigmaDFBeh(supportChain_listExpr(biabl->VALABL),
                               binode->VALNODE,beh,dejaTraite);

         if (reportDC != zero)
            pDC[i] = applyBinBdd(OR,pDC[i],reportDC);
*/

         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   binode = bus->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         pON[i] = binode->VALNODE;

		/* recherche des DC locaux */

         if (searchExpr(biabl->VALABL,"'d'"))
            {
            chain_list *expr;

            expr = substExpr(biabl->VALABL,"'d'",createAtom("'1'"));

            pDC[i] = applyBinBdd(AND,notBdd(pON[i]),
                                     ablToBddCct(beh->CIRCUI,expr)); 
            freeExpr(expr);
            }
         else
            pDC[i] = zero; 

		/* report des DC provenant du support */

/*
         reportDC = sigmaDFBeh(supportChain_listExpr(biabl->VALABL),
                               binode->VALNODE,beh,dejaTraite);

         if (reportDC != zero)
            pDC[i] = applyBinBdd(OR,pDC[i],reportDC);
*/

         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   binode = bux->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         pON[i] = binode->VALNODE;

		/* recherche des DC locaux */

         if (searchExpr(biabl->VALABL,"'d'"))
            {
            chain_list *expr;

            expr = substExpr(biabl->VALABL,"'d'",createAtom("'1'"));

            pDC[i] = applyBinBdd(AND,notBdd(pON[i]),
                                     ablToBddCct(beh->CIRCUI,expr)); 
            freeExpr(expr);
            }
         else
            pDC[i] = zero; 

		/* report des DC provenant du support */

/*
         reportDC = sigmaDFBeh(supportChain_listExpr(biabl->VALABL),
                               binode->VALNODE,beh,dejaTraite);

         if (reportDC != zero)
            pDC[i] = applyBinBdd(OR,pDC[i],reportDC);
*/

         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }

		/* application successive des DC sur les ON */

if (trace)
   printf("Applying the Don't Care simplification function...\n");

for (j=1; j < 3; j++)
   {
   for (i=0; i < numberGraph; i++)
      {
		/* le i-eme graphe possede un DC */

      if (pDC[i] != zero)
         {
         int cout = costTab(pON,numberGraph,func);
         int coutFinal;
         pNode pInter;
   
         if (trace) printf("cost %d --> ",cout);
         pInter = pON[i];
         pON[i] = simplifPlusDcZeroBdd(pON[i],pDC[i]);
   
         coutFinal = costTab(pON,numberGraph,func);

         if (trace) printf("%d\n",coutFinal);
   
         if (cout < coutFinal)    /* pas d'amelioration */
            pON[i] = pInter;
         else      /* on enleve au DC la partie utilisee dans ON */
            pDC[i] = applyBinBdd(AND,pDC[i],notBdd(pON[i]));
         } 
      }
   }

		/* regeneration des equations simplifiees */

		/* on vide la table des sorties de la couches circuit */

pEl = ((beh->CIRCUI)->pTO)->pElem;

for (i = 0; i < ((beh->CIRCUI)->pTO)->length; i++)
   {
   pEl->value = EMPTYTH;
   pEl++;
   }

i = 0;

out = beh->BEOUT;
while (out) 
   {
   if (out->ABL)
      {
      if (pDC[i] != zero)
         {
         out->NODE = pON[i];
         freeExpr(out->ABL);
         out->ABL = bddToAblCct(beh->CIRCUI,pON[i]);
         }
      i++;
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg) 
   {
   biabl = reg->BIABL;
   binode = reg->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         if (pDC[i] != zero)
            {
            binode->VALNODE = pON[i];
            freeExpr(biabl->VALABL);
            biabl->VALABL = bddToAblCct(beh->CIRCUI,pON[i]);
            }
         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   reg = reg->NEXT;
   }

bus = beh->BEBUS;
while (bus) 
   {
   biabl = bus->BIABL;
   binode = bus->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         if (pDC[i] != zero)
            {
            binode->VALNODE = pON[i];
            freeExpr(biabl->VALABL);
            biabl->VALABL = bddToAblCct(beh->CIRCUI,pON[i]);
            }
         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bus = bus->NEXT;
   }

bux = beh->BEBUX;
while (bux) 
   {
   biabl = bux->BIABL;
   binode = bux->BINODE;
   while (biabl)
      {
      if (biabl->VALABL)
         {
         if (pDC[i] != zero)
            {
            binode->VALNODE = pON[i];
            freeExpr(biabl->VALABL);
            biabl->VALABL = bddToAblCct(beh->CIRCUI,pON[i]);
            }
         i++;
         }
      biabl = biabl->NEXT;
      binode = binode->NEXT;
      }
   bux = bux->NEXT;
   }


mbkfree(pON);
mbkfree(pDC);
destroyTH(dejaTraite);
}
