/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  synthese ACT1                                              */
/*    Fichier :  act1.c                                                     */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :  Eudes Prado Lopes                       le : 20 /10/1993 */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include <stdio.h>
#include MUT_H
#include LOG_H
#include BEH_H
#include "../compil/lax_param.h"
#include "../compil/sl_util.h"
#include "../bddorder/bdd_order.h"
#include "fp_type.h"
#include "fpga.h"

#define TYPE_T 0
#define TYPE_A 1
#define TYPE_I 3
#define TYPE_G 5

/*----------------------------------------------------------------------------
costIntACT1	: fonction interne de cout des ACT1 pour guider 
                  le re-odonnancement
------------------------------------------------------------------------------
retour		: un pointeur de liste chainee (support)
                  un cout (entier) -> par adresse
------------------------------------------------------------------------------*/

/* ======================================================================

Tableau de codage   :  T = 0, A = 1, I = 3, G = 5

  TYPE(L)	TYPE(H)		Resultat	Coupure		Somme
  ----------------------------------------------------------------------
  T		T		A				0
			        I				0
  T		A		G				1
  T		I		G				3
  				A		x		3
  T		G		A		x		5
  ----------------------------------------------------------------------
  A		A		G				2
  A		I		A		x		4
  A		G		A		x		6
  ----------------------------------------------------------------------
  I		I		A		x		6
  I		G		A		x		8
  G		G		A		x		10
  ----------------------------------------------------------------------

  ====================================================================== */

int costIntACT1(pt,pCount,markOR)
pNode pt;
int *pCount;
int markOR;
{
int type_l, type_h;
int somme;
pNode ptInv, pBdd, low, high;

if (pt->index < 2)	/* noeud terminal */
   return (TYPE_T);

			/* noeud deja traite */

if (pt->mark == 1)	/* ACT1 de fonction directe */
   {
   return(TYPE_A);
   }

if (pt->mark == 2)	/* ACT1 de fonction inverse */
   {
   return(TYPE_I);
   }

		/* simplifications eventuelles avant l'appel
                   recursif sur les fils */

if (RULES_DC)
   {
   pBdd = applyBinBdd(AND,pt->high,pt->low);

   if (pBdd == pt->low || pBdd == pt->high)
      {
      if (pBdd == pt->low)
         high = simplifDcOneBdd(pt->high,pt->low);
      else
         high = pt->high;

      if (pBdd == pt->high)
         low = simplifDcOneBdd(pt->low,pt->high);
      else
         low = pt->low;

		/* si un fils a ete simplifie ... */

      if (low != pt->low || high != pt->high)
         {
         *pCount = *pCount + costACT1(low);
         *pCount = *pCount + costACT1(high);

         pt->mark = 1;
         ptInv = notBdd(pt);
         ptInv->mark = 2;

         *pCount = *pCount + 1;

         return(TYPE_A);
         }
      }
   }


high = pt->high;
low = pt->low;

		/* specifique aux ACTEL 1 */
		/* detection du OU */

if (markOR)
   type_l = costIntACT1(low,pCount,0);
else
   {
   if (high == low->high)
      type_l = costIntACT1(low,pCount,1);
   else
      type_l = costIntACT1(low,pCount,0);
   }

type_h = costIntACT1(high,pCount,0);

/*
printf("index = %d L = %d  H = %d \n",pt->index,type_l,type_h);
*/

somme = type_l + type_h;

if (somme > 3)		/* coupure */
   {
		/* commande OU */

   if (markOR)
      return(TYPE_G);

   pt->mark = 1;
   ptInv = notBdd(pt);
   ptInv->mark = 2;

   *pCount = *pCount + 1;

   return(TYPE_A);
   }
else
   {
   if (somme == 0)		/* TYPE_T - TYPE_T  */
      {
      if (low == zero)
         return(TYPE_A);
      else
         return(TYPE_I);
      }

   if (somme == 3)		/* TYPE_T - TYPE_I */
      {
      if (high == zero || low == one)	/* coupure */
         {
			/* commande OU */

         if (markOR)
            return(TYPE_G);

         pt->mark = 1;
         ptInv = notBdd(pt);
         ptInv->mark = 2;

         *pCount = *pCount + 1;
         return(TYPE_A);
         }
      }

			/* Dans les autres cas :
				TYPE_T - TYPE_A
				TYPE_A - TYPE_A
			*/
   return(TYPE_G);
   }
}
/*----------------------------------------------------------------------------
costACT1	: fonction de cout des ACT1 pour guider le re-odonnancement
------------------------------------------------------------------------------
retour		: un cout (entier)
------------------------------------------------------------------------------*/
int costACT1(pt)
pNode pt;
{
int res;
pNode ptInv;
int count = 0;		/* nombre de ACT1 utilises */

res = costIntACT1(pt,&count,0);

if (res < TYPE_I)		/* TYPE_T ou TYPE_A */ 
   {
   return(count);
   }
else
   {
   pt->mark = 1;
   ptInv = notBdd(pt);
   ptInv->mark = 2; 

   return(1 + count);
   }
}
