/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : synthetiseur logique                                        */
/*    Fichier : bib.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 MUT_H
#include LOG_H
#include "bib.h"

/*------------------------------------------------------------------
  IDENT : levelExpr
  ------------------------------------------------------------------
  FUNCTION : calcule la profondeur en ET et OU d'une expression.
  ------------------------------------------------------------------*/
 
int levelExpr(expr)
chain_list *expr;
{
if (ATOM(expr))
   return(0);
else
   {
   int max=0,profCar;
 
   if (OPER(expr) == NOT)
      return levelExpr(CADR(expr));

   while (expr = CDR(expr))
      {
      profCar = levelExpr(CAR(expr));
      if (profCar >max)
         max = profCar;
      }
   return(++max);
   }  
}


/*-------------------------------------------------------------------------
calculTNTPExpr: calcule le nbre de transistors N et P en serie dans une fonction
	  positive. 
---------------------------------------------------------------------------
retour		: un int.
---------------------------------------------------------------------------*/
void calculTPTNExpr(expr,tp,tn)
chain_list *expr;
int *tp,*tn;
{
/*
displayExpr(expr);
printf(" : tN = %d, tP = %d\n",*tn,*tp);
*/

if (ATOM(expr))
   {
   *tn = 1;
   *tp = 1;
   }
else
   {
   if (OPER(expr) == OR)
	{
	int max = 0;
	int som = 0;

	while(expr = CDR(expr))
	     {
	     int auxn = 0, auxp = 0;

	     calculTPTNExpr(CAR(expr),&auxp,&auxn);
	     som += auxp;
	     if (auxn > max)
		max = auxn;
	     }
	*tn = max;
	*tp = som;
	return;
	}
   if (OPER(expr) == AND)
	{
	int som = 0;
	int max = 0;
	int auxn = 0, auxp = 0;

	while(expr = CDR(expr))
	     {
	     calculTPTNExpr(CAR(expr),&auxp,&auxn);
	     som += auxn;
	     if (auxp > max)
		max = auxp;
	     }
	*tn = som;
	*tp = max;
	return;
	}
   if (OPER(expr) == NOT)
	{
	*tn = 1;
	*tp = 1;
	return;
	}
   }
}

/*-------------------------------------------------------------------------
polarityExpr : calcule la  polarite d'une expression
---------------------------------------------------------------------------
retour		: un int = 0 pour negatif, 1 pour positif et 2 sinon
---------------------------------------------------------------------------*/
int polarityExpr(expr)
chain_list *expr;
{
if (ATOM(expr))
   return 1;
else
   {
   int polar;

   if (OPER(expr) == NOT)
	{
	if (ATOM(CADR(expr)))
	   return 0;
	else
	   {
	   printf("polarityExpr : error - bad expression\n");
           displayExpr(expr);
	   exit(-1);
	   }
	}
   if (OPER(expr) != AND && (OPER(expr) != OR))
	   {
	   printf("polarityExpr : error - bad operator\n");
	   exit(-1);
	   }
   expr = CDR(expr);
   polar = polarityExpr(CAR(expr));
   if (polar == 2) 
	return 2;
   while(expr = CDR(expr))
	{
	int val = polarityExpr(CAR(expr));

	if ((val == 2) || (val ^ polar)) 
	   return 2;
	}
   return polar;
   }
}

/*-------------------------------------------------------------------------
respectTrExpr : verifie qu'une expression respecte la contrainte 
	        d'empilement niveau par niveau.
---------------------------------------------------------------------------
retour		: un int = 0 pour KO, 1 pour OK
---------------------------------------------------------------------------*/
int respectTrExpr(expr,tp,tn)
chain_list *expr;
int tp, tn;
{
if (ATOM(expr))
   return 1;
if (OPER(expr) == NOT)
	{
	if (ATOM(CADR(expr)))
	   return 1;
	else
	   {
	   printf("respectTrExpr : error - bad expression\n");
	   exit(-1);
	   }
	}
   if (OPER(expr) != AND && (OPER(expr) != OR))
	   {
	   printf("respectTrExpr : error - bad operator\n");
	   exit(-1);
	   }
   if (OPER(expr) == OR)
	{
	if (lengthExpr(expr) > tp)
	   return 0;
	}
   if (OPER(expr) == AND)
	{
	if (lengthExpr(expr) > tn)
	   return 0;
	}
   while(expr = CDR(expr))
	if (!respectTrExpr(CAR(expr),tp-1,tn-1))
		return 0;
   return 1;
}

/*-------------------------------------------------------------------------
empileOKExpr : verifie qu'une expression respecte la contrainte 
	        d'empilement.
---------------------------------------------------------------------------
retour		: un int = 0 pour KO, 1 pour OK
---------------------------------------------------------------------------*/
int empileOKExpr(expr,tp,tn,polarite)
chain_list *expr;
int tp, tn, polarite;
{
int tpint = 0, tnint = 0;
chain_list *inter;
int result;

if (levelExpr(expr) > MAXLEVEL)
   return(0);
 
inter = copyExpr(expr);
flatArityExpr(inter);

if (polarite == 1)
   {
   calculTPTNExpr(expr,&tpint,&tnint);
   if (tpint > tp || tnint > tn || !respectTrExpr(inter,tp,tn))
      result =  0;
   else
      result =  1;
   }
if (polarite == 0)
   {
   calculTPTNExpr(expr,&tnint,&tpint);
   if (tpint > tp || tnint > tn || !respectTrExpr(inter,tn,tp))
      result =  0;
   else
      result =  1;
   }
freeExpr(inter);
return result;
}
/*-------------------------------------------------------------------------
maxTH : calcule la valeur max d'une table de hachage. 
---------------------------------------------------------------------------
retour		: un int.
---------------------------------------------------------------------------*/
int maxTH(pTable)
pTH pTable;
{
int i;
pElemTH pEl;
int max=0;

pEl=pTable->pElem;
for (i=0;i<pTable->length;i++)
    {
    if (pEl->value != EMPTYTH && pEl->value !=DELETETH)
       {
       if (pEl->value > max)
          max = pEl->value;
       }
    pEl++;
    }
return max;
}
/*-------------------------------------------------------------------------
delaisCarac : calcul le delais au dessus duquel le cone doit etre
              optimise en delais. 
---------------------------------------------------------------------------
retour		: un int.
---------------------------------------------------------------------------*/
int delaisCarac(pTable,optim)
pTH pTable;
int optim;
{
int max = maxTH(pTable);

switch (optim)
   {
   case 0 : return max;
   case 1 : return (9*max)/10;
   case 2 : return (8*max)/10;
   case 3 : return (8*max)/10;
   case 4 : return (7*max)/10;
   }
}
