
/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : synthetiseur logique                                        */
/*    Fichier : carac.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 : 01/06/1992     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include MUT_H
#include LOG_H
#include BEH_H
#include "carac.h"

/*------------------------------------------------------------------
  IDENT : supportOptimExpr
  ------------------------------------------------------------------
  FUNCTION : renvoie une liste de Variables auxiliaires a optimiser 
  ------------------------------------------------------------------ */

void supportOptimExprInt(expr,caracTH,delais,ppCL)
chain_list *expr;
pTH caracTH;
int delais;
chain_list **ppCL;
{
if (ATOM(expr))
   {
   chain_list *pCL = *ppCL;
   int val;
 
   val = searchTH(caracTH,VALUE_ATOM(expr));
   if (val == EMPTYTH)
      {
      printf("supportOptimExpr : error - expression not characterized\n");
      displayExpr(expr);
      exit(-1);
      }
   if ((val > delais*0.8) || (val+500 > delais))
      {
      while (pCL)                  /* recherche occurence */
         {   
         if ((char *)pCL->DATA == VALUE_ATOM(expr))
            return;
         pCL = pCL->NEXT;
         }   
      *ppCL = addchain(*ppCL,(void *)VALUE_ATOM(expr));
      }
   }
else
   {
   if (OPER(expr) == XOR || OPER(expr) == NXOR)
      delais = delais - 1000*logsup2(lengthExpr(expr));
   else
      delais = delais - 500*logsup2(lengthExpr(expr));

   while (expr = CDR(expr))
      supportOptimExprInt(CAR(expr),caracTH,delais,ppCL);
   }
}

chain_list *supportOptimExpr(expr,caracTH,delais)
chain_list *expr;
pTH caracTH;
int delais;
{
chain_list **ppCL;
ppCL = (chain_list **) mbkalloc (sizeof(chain_list *));
*ppCL = NULL;
supportOptimExprInt(expr,caracTH,delais,ppCL);
return(*ppCL);
}

/*-------------------------------------------------------------------------
calculDelaisExpr: parcours d'une expression pour la caracterisation. 
                  si balance : calcul balancee
                  sinon      : ponderation par la moyenne
---------------------------------------------------------------------------
retour		: le delais estime. 
---------------------------------------------------------------------------*/
int calculDelaisExpr(beh,ret,expr,balance)
befig_list *beh;
pTH ret;
chain_list *expr;
int balance;
{
int delais;
int okPermu;
chain_list *expr1;

if (ATOM(expr))
   {
   beaux_list *aux;

   if (!strcmp(VALUE_ATOM(expr),"'d'") ||
       !strcmp(VALUE_ATOM(expr),"'0'") || !strcmp(VALUE_ATOM(expr),"'1'"))
      {
      addTH(ret,VALUE_ATOM(expr),0);
      addTH(ret,expr,0);
      return(0);
      }

   delais = searchTH(ret,VALUE_ATOM(expr));

		/* si deja calcule ou signal primaire */

   if (delais != EMPTYTH && delais != DELETETH)
      {
      addTH(ret,expr,delais);
      return(delais);
      }

   aux = beh->BEAUX;
   while (aux && strcmp(aux->NAME,VALUE_ATOM(expr)))
	aux = aux->NEXT;
   if (aux == NULL)
      {
      printf("caracBeh : error - auxiliary signal doesn't exist : -%s-\n",
             VALUE_ATOM(expr));
      exit(-1);
      }
   delais = calculDelaisExpr(beh,ret,aux->ABL,balance);
   if (delais == EMPTYTH)
      {
      printf("caracBeh : error - auxiliary signal doesn't compute : %s\n",
             VALUE_ATOM(expr));
      exit(-1);
      }
   addTH(ret,VALUE_ATOM(expr),delais);
   addTH(ret,expr,delais);
   return(delais); 
   }
else
   {
   chain_list *oldExpr = expr;
   int max = 0;
   int somme = 0;
   int delais;

			/* calcul du max */

   while (expr = CDR(expr))
      {
      delais = calculDelaisExpr(beh,ret,CAR(expr),balance);
      somme = somme + delais;
      if (max < delais)
         max = delais;
      }

		/* tri des arguments par delais croissants */
   okPermu = 1;
   while (okPermu)
      {
      expr1 = CDR(oldExpr);
      okPermu = 0;
      while (CDR(expr1))
         {
         if (searchTH(ret,CAR(expr1)) > searchTH(ret,CADR(expr1)))
            {
            chain_list *permu;
 
            permu = CAR(expr1);
            expr1->DATA = (void *)CADR(expr1);
            (expr1->NEXT)->DATA = (void *)permu;
            okPermu = 1;
            }
         expr1 = CDR(expr1);
         }  
      }

		/* prise en compte des entrees retardees */

   if (balance || OPER(oldExpr) == NOT || OPER(oldExpr) == STABLE)
      {
      if (OPER(oldExpr) == XOR || OPER(oldExpr) == NXOR)
         delais = 1000*logsup2(lengthExpr(oldExpr))+max;
      else
         delais = 500*logsup2(lengthExpr(oldExpr))+max;
      }
   else
      {

		/* calcul pondere 
                       Delais = max(500,delaisEstime)

		   avec
                       DelaisEstime = 500xlogsup2(arite) - max + moyenne
                 */
 
      int moyenne;
      int delaisEstime;

      expr = oldExpr;
			/* calcul de la moyenne */

      moyenne = somme/lengthExpr(oldExpr);

      if (OPER(oldExpr) == XOR || OPER(oldExpr) == NXOR)
         {
         delaisEstime = 1000*logsup2(lengthExpr(oldExpr)) - max + moyenne;
         if (1000 > delaisEstime)
            delais = 1000+max;
         else
            delais = delaisEstime+max;
         }
      else
         {
         delaisEstime = 500*logsup2(lengthExpr(oldExpr)) - max + moyenne;
         if (500 > delaisEstime)
            delais = 500+max;
         else
            delais = delaisEstime+max;
         }
      }

   addTH(ret,oldExpr,delais);
   return(delais);
   }
}

/*-------------------------------------------------------------------------
caracBeh	: caracterise une befig en remplissant une table de hachage
		  signal/delais en pico-sec. 
---------------------------------------------------------------------------
retour		: une table remplie.
---------------------------------------------------------------------------*/
pTH caracBeh(beh,delais,balance)
befig_list *beh;
ptype_list *delais;
int balance;
{
berin_list *in;
beout_list *out;
bereg_list *reg;
bebus_list *bus;
bebux_list *bux;
biabl_list *biabl;
pTH ret;

ret = createTH(300);

		/* parcours des entrees et latches */

 
in = beh->BERIN;
while (in)
   {  
   addTH(ret,in->NAME,0);
   in = in->NEXT;
   }  
 
	/* on ecrase avec les valeurs de delayPI pour les entrees */

while (delais)
   {
   if (searchTH(ret,delais->DATA) != EMPTYTH)
      { 
      addTH(ret,delais->DATA,delais->TYPE);
      }
   delais = delais->NEXT;
   }

		/* parcours des expressions - calcul des delais */

out = beh->BEOUT;
while (out)
   {
   if (out->ABL)
      {
      calculDelaisExpr(beh,ret,out->ABL,balance);
      }
   out = out->NEXT;
   }

reg = beh->BEREG;
while (reg)
   {  
   biabl = reg->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         calculDelaisExpr(beh,ret,biabl->CNDABL,balance);
         calculDelaisExpr(beh,ret,biabl->VALABL,balance);
         }
      biabl = biabl->NEXT;
      }
   reg = reg->NEXT;
   }  
      
bus = beh->BEBUS;
while (bus)
   {  
   biabl = bus->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         calculDelaisExpr(beh,ret,biabl->CNDABL,balance);
         calculDelaisExpr(beh,ret,biabl->VALABL,balance);
         }
      biabl = biabl->NEXT;
      }
   bus = bus->NEXT;
   }  

bux = beh->BEBUX;
while (bux)
   {  
   biabl = bux->BIABL;
   while (biabl)
      {
      if (biabl->CNDABL && biabl->VALABL)
         {
         calculDelaisExpr(beh,ret,biabl->CNDABL,balance);
         calculDelaisExpr(beh,ret,biabl->VALABL,balance);
         }
      biabl = biabl->NEXT;
      }
   bux = bux->NEXT;
   }  
return(ret);
}     
