/*******************************************************************************
*
* Fichier de fonction util .
*
* v.0		28/01/92 .
*******************************************************************************/
#include  MUT_H
#include  LOG_H
#include"../beh104/beh104.h"
#include "util.h"

chain_list *ptr_ctrlst ;
/*---------------------------------------------------------------------------
commonLiteralExpr	: calcule le nombre de literaux commun a deux ABL .
-------------------------------------------------------
Arguments	: abl,tab : l'abl et la table au les noms seront stockees .
-------------------------------------------------------
return		: return le nombre de literaux distincts de l'abl .
---------------------------------------------------------------------------*/
int commonLitExpr(abl1,abl2)
chain_list* abl1;
chain_list* abl2;
{
int number;
int cpt;
int spnumber=0;
char **tab;

  number = numberAtomExpr(abl1);
  if(!(tab = (char **)malloc(number * sizeof(char * ))))
	 {
		printf("allocation impossible \n");
	   exit(-1);
	  }
   spnumber = markAbl(abl1,tab,0);
   cpt = commonLitAbl(abl2,tab,spnumber);
return(cpt);
}
/*---------------------------------------------------------------------------
commonLitAbl	: recense les noms des litearux qui apparaiseent dans abl.
-------------------------------------------------------
Arguments	: abl1,abl2 : les deux abl  .
-------------------------------------------------------
return		: return le nombre de literaux commun l'abl .
---------------------------------------------------------------------------*/
int commonLitAbl(abl,tab,numberEle)
chain_list* abl;
char **tab;
int numberEle;
{
int cpt =0,i;
if(ATOM(abl))
for(i =0;i < numberEle;i++)
  if(!strcmp(tab[i],abl->DATA))
  return(1);
   else 
   {
     while(abl = CDR(abl))
     {
      cpt = cpt + commonLitAbl(CAR(abl),tab,numberEle);
     }
  }
  return(cpt);
}
/*---------------------------------------------------------------------------
markAbl	: recense les noms des litearux qui apparaiseent dans abl.
-------------------------------------------------------
Arguments	: abl1,abl2 : les deux abl  .
-------------------------------------------------------
return		: return le nombre de literaux commun l'abl .
---------------------------------------------------------------------------*/
markAbl(abl1,tab,numberEle)
chain_list* abl1;
char **tab;
int numberEle;
{
int i;
if(ATOM(abl1))
{
for(i =0;i < numberEle;i++)
  if(!strcmp(tab[i],abl1->DATA))
  return(i);
  tab[i] = namealloc(abl1->DATA);
 numberEle++;
  return(numberEle);
 } 
   else 
   {
     while(abl1 = CDR(abl1))
     {
      numberEle = markAbl(CAR(abl1),tab,numberEle);
     }
  }
  return(numberEle);
}
/*---------------------------------------------------------------------------
distHaming	: calcule la distance de Haming entre deux codes binaires .
-------------------------------------------------------
Arguments	: int c1,c2 : Les codes binaires .
-------------------------------------------------------
return		: distance de Haming des codes fournis .
---------------------------------------------------------------------------*/
int distHaming(l,k,Nb)
int l;
int k;
int Nb;
{
int i,a,b=0;
a=l^k;
for(i=0;i<Nb;i++)
if(bit[i]&a) b++;
return(b) ;
}
/*---------------------------------------------------------------------------
numbit_1Two	: calcule le nombre de 1 dans un code binaire .
-------------------------------------------------------
Arguments	: int c1 : Le codes binaires .
-------------------------------------------------------
return		: le nombre de 1 du code fournit .
---------------------------------------------------------------------------*/
int numbit_1Two(code1,code2,Nb)
int code1,code2;
int Nb;
{
int i,a,b=0;
a=code1&code2;
for(i=0;i<Nb;i++)
if(bit[i]&a) b++;
return(b) ;
}
/*---------------------------------------------------------------------------
numbit_1	: calcule le nombre de 1 dans un code binaire .
-------------------------------------------------------
Arguments	: int c1 : Le codes binaires .
-------------------------------------------------------
return		: le nombre de 1 du code fournit .
---------------------------------------------------------------------------*/
int numbit_1(code,Nb)
int code,Nb;
{
int i,b=0;
if (code == bit[Nb]) return(Nb);
for(i=0;i<Nb;i++)
if(bit[i]&code) b++;
return(b) ;
}

/*---------------------------------------------------------------------------
rempMaskTab	: remplie la table de masque binaire .
-------------------------------------------------------
Arguments	: rien 
-------------------------------------------------------
return		: rien 
---------------------------------------------------------------------------*/
rempMaskTab() 
{
int i;
bit[0]=1;
for(i=1;i< 16;i++)
bit[i]=bit[i-1]*2;
}
/*--------------------------------------------------------------------- 
syf_makeBddBeh	: Remplit le champ bdd de befig, en eliminant ou pas les
		variables aux .
----------------------------------------------------------------------*/

int syf_makeBddBeh( ptr_befig, ptr_circuit, reorder, trace, max_node )

struct syf_befig *ptr_befig;		/* pointer on current BEFIG	*/
pCircuit      ptr_circuit;		/* pointer on current circuit	*/
int           reorder;			/* order parameter 		*/
int trace;
int max_node;

  {
  pNode syf_makeBddAbl();
  int vhb_numberNode = numberNodeAllBdd();
  int vhb_count = 0;

if(trace)
	printf("------- MakeBddBeh --------\n");

  ptr_ctrlst = NULL;

  if (trace)
    {
    printf("Running Abl2Bdd on `%s`...\n\n",ptr_befig->NAME);
    }

  if (ptr_befig->BEAUX != NULL)
    {
    struct syf_beaux *ptr_aux;
    ptr_aux=ptr_befig->BEAUX;
    while (ptr_aux != NULL)
      {
      if ((ptr_aux->ABL != NULL) && (ptr_aux->NODE == NULL))
          {
	  	  if(trace)
			printf("aux : %s\n",ptr_aux->NAME) ;
          ptr_ctrlst = addchain (ptr_ctrlst,(void *)ptr_aux->NAME);
          ptr_aux->NODE = syf_makeBddAbl (ptr_circuit,ptr_aux->ABL,ptr_befig,&vhb_count);
          ptr_ctrlst = delchain (ptr_ctrlst,ptr_ctrlst);
          addOutputCct(ptr_circuit,ptr_aux->NAME,ptr_aux->NODE);
	  }
      ptr_aux = ptr_aux->NEXT;
      vhb_count++;
      if ( vhb_count>1 &&
           reorder && 
           ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
           {
           return(1);
           }
      }
    }


  if (ptr_befig->BEOUT != NULL)
    {
    struct syf_beout *ptr_beout;
    ptr_beout=ptr_befig->BEOUT;
    while (ptr_beout != NULL)
      {
      if ((ptr_beout->ABL != NULL) && (ptr_beout->NODE == NULL))
	  {
	  if(trace)
		printf("out : %s\n",ptr_beout->NAME) ;
          ptr_ctrlst = addchain (ptr_ctrlst,(void *)ptr_beout->NAME);
          ptr_beout->NODE = syf_makeBddAbl (ptr_circuit,ptr_beout->ABL,ptr_befig,&vhb_count);
          ptr_ctrlst = delchain (ptr_ctrlst,ptr_ctrlst);
	  }

      ptr_beout = ptr_beout->NEXT;
      vhb_count++;
      if ( vhb_count>1 &&
           reorder && 
           ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
        {
        return(1);
        }
      }
    }
  if (ptr_befig->BEBUS != NULL)
    {
    struct syf_bebus *ptr_bebus;
    ptr_bebus=ptr_befig->BEBUS;
    while (ptr_bebus != NULL)
      {
      if (ptr_bebus->BIABL != NULL)
        {
        struct biabl *ptr_biabl;
        struct binode *ptr_binode;
        ptr_biabl = ptr_bebus->BIABL;
        ptr_binode = ptr_bebus->BINODE;
        while (ptr_biabl != NULL)
          {
          if (ptr_biabl->CNDABL != NULL)
	      {
              ptr_binode->CNDNODE = syf_makeBddAbl (ptr_circuit, ptr_biabl->CNDABL, ptr_befig,&vhb_count);
	      }

           vhb_count++;
           if ( vhb_count>1 &&
                reorder && 
                ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
             {
             return(1);
             }
          
          if ( ptr_biabl->VALABL != NULL )
	      {
              ptr_ctrlst = addchain (ptr_ctrlst,(void *)ptr_bebus->NAME);
              ptr_binode->VALNODE = syf_makeBddAbl (ptr_circuit,ptr_biabl->VALABL,ptr_befig,&vhb_count);
              ptr_ctrlst = delchain (ptr_ctrlst,ptr_ctrlst);
	      }

           vhb_count++;
           if ( vhb_count>1 &&
                reorder && 
                ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
             {
             return(1);
             }

          ptr_biabl = ptr_biabl->NEXT;
          ptr_binode = ptr_binode->NEXT;
          }
        }
      ptr_bebus = ptr_bebus->NEXT;
      }
    }

  if (ptr_befig->BEREG != NULL)
    {
    struct syf_bereg *ptr_bereg;
    ptr_bereg=ptr_befig->BEREG;
    while (ptr_bereg != NULL)
      {
      if (ptr_bereg->BIABL != NULL)
        {
        struct biabl *ptr_biabl;
        struct binode *ptr_binode;
	  	if(trace)
			printf("reg : %s\n",ptr_bereg->NAME) ;
        ptr_biabl = ptr_bereg->BIABL;
	ptr_bereg->BINODE = (struct binode *)malloc(sizeof(struct binode)) ;
	ptr_bereg->BINODE->VALNODE = NULL ;
	ptr_bereg->BINODE->CNDNODE = NULL ;
	ptr_bereg->BINODE->NEXT = NULL ;
        ptr_binode = ptr_bereg->BINODE;
        while (ptr_biabl != NULL)
          {
          if (ptr_biabl->CNDABL != NULL)
	      {
          ptr_binode->CNDNODE = syf_makeBddAbl (ptr_circuit,ptr_biabl->CNDABL,ptr_befig,&vhb_count);
	      }

           vhb_count++;
           if ( vhb_count>1 &&
                reorder && 
                ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
             {
             return(1);
             }

          if (ptr_biabl->VALABL != NULL)
	      {
              ptr_ctrlst = addchain (ptr_ctrlst,(void *)ptr_bereg->NAME);
              ptr_binode->VALNODE = syf_makeBddAbl (ptr_circuit,ptr_biabl->VALABL,ptr_befig,&vhb_count);
              ptr_ctrlst = delchain (ptr_ctrlst,ptr_ctrlst);
	      }

           vhb_count++;
           if ( vhb_count>1 &&
                reorder && 
                ((numberNodeAllBdd() - vhb_numberNode) /vhb_count) >max_node)
             {
             return(1);
             }

          ptr_biabl = ptr_biabl->NEXT;
          ptr_binode = ptr_binode->NEXT;
          }
        }
      ptr_bereg = ptr_bereg->NEXT;
      }
    }

  if (ptr_befig->BEMSG != NULL)
    {
    struct syf_bemsg *ptr_bemsg;
    ptr_bemsg=ptr_befig->BEMSG;
    while (ptr_bemsg != NULL)
      {
      if ((ptr_bemsg->ABL != NULL) && (ptr_bemsg->NODE == NULL))
          {
          ptr_bemsg->NODE = syf_makeBddAbl (ptr_circuit,ptr_bemsg->ABL,ptr_befig,&vhb_count);
	  }
      ptr_bemsg = ptr_bemsg->NEXT;
      }
    }

		/* destruction des auxiliares */

  destroyTH(ptr_circuit->pTO);
  ptr_circuit->pTO = createTH(100);

if(trace)
	printf("------- END MakeBddBeh --------\n");
  return(0);
  }

/*-------------------------------------------------------------------
makeBddAll	: 
-------------------------------------------------------------------*/
pNode syf_makeBddAbl (ptr_circuit, expr, ptr_befig,vhb_count)
pCircuit ptr_circuit;		/* circuit for level 1 bdd functions 	*/
chain_list *expr;		/* pointer abl expression		*/
struct syf_befig *ptr_befig;	/* pointer on  behavioural figure	*/
int *vhb_count;
  {
  short         oper;
  pNode         pt;
  chain_list   *lstGbd;
  chain_list   *ptr_cntrl=ptr_ctrlst;
  struct syf_beaux *ptr_beaux=ptr_befig->BEAUX;
  int           index;
  char         *atom;

  if (expr == NULL)
    {
    printf("syf_makeBddAbl : error ABL = NULL \n");
    exit(1);
    }

  if (ATOM(expr))
    {					/* is atom a constant ?           */
    atom = (char *)VALUE_ATOM (expr);
					
    if (!strcmp(atom, "'0'"))
      return (zero);
    if (!strcmp(atom, "'1'"))
      return (one);
    					/* is atom a primary variable ?     */
    if ((index=searchInputCct (ptr_circuit, atom)) != VIDETH)
      {
      return (createNodeTermBdd (index));
      }

    else				/* neither constant, nor primary     */
      {					/* it must be an auxilliary variable */

      while ((ptr_beaux != NULL) && (strcmp(ptr_beaux->NAME,atom)))
        ptr_beaux = ptr_beaux->NEXT;

      if (ptr_beaux == NULL)		/* neither constant, nor primary, nor */
         {
         printf("syf_makeBddAbl : error signal %s not found\n",atom);
         exit(1);
         }
      else				/* does that signal depends of        */
	{				/* himself ? ptr_ctrlst is the        */
					/* dependance list of expression being*/
					/* transformed from abl to bdd        */
        while ((ptr_cntrl != NULL) && ((char *) ptr_cntrl->DATA != atom))
          ptr_cntrl = ptr_cntrl->NEXT;

        if (ptr_cntrl != NULL)
					/* to ensure that no signal depends  */
					/* of himself			     */
          {				/* if it does it's a fatal error!    */
          printf("syf_makeBddAbl : error signal %s in combinatory loop \n",atom);
          exit(1);
          }
        else
          {
          if (ptr_beaux->NODE == NULL)
            {
            ptr_ctrlst = addchain ( ptr_ctrlst,(void *)atom);
					/* add a signal to the dependences    */
					/* list that ptr_ctrlst is pointing at*/
            ptr_beaux->NODE = syf_makeBddAbl ( ptr_circuit,ptr_beaux->ABL,ptr_befig,
                                           vhb_count );
            *vhb_count = *vhb_count+1;
            ptr_ctrlst = delchain (ptr_ctrlst,ptr_ctrlst);
					/* del a signal to the dependences    */
            return (ptr_beaux->NODE);
            }
          else
            {
            return (ptr_beaux->NODE);
            }
          }
        }
      }
    }
  else
    {
    oper = OPER( expr );		/* operator to be applyed on lstgbd  */
    lstGbd = NULL;		  	/* list of operands		     */
    while ( expr = CDR( expr ) )
      {
      pNode ptNode = syf_makeBddAbl(ptr_circuit,CAR(expr),ptr_befig,vhb_count);
      lstGbd = addListBdd (lstGbd,ptNode);
      }

	  /* patch pour stable */
	  if(oper == STABLE)
		oper = NOT ;

    pt = applyBdd(oper,lstGbd);
    freechain (lstGbd);
    return(pt);
    }
  }
/*-----------------------------------------------------------------------------
addTabInt	: ajoute un entier dans la table des entiers.
---------------------------------------------
parametres	: int *tab : La table des entiers . 
		  int data : la donnee a ajouter .
--------------------------------------------
return		: void .
------------------------------------------------------------------------------*/
void addTabInt(tab,data)
int *tab ;
int data ;
{
int i;

for(i = 0; *(tab + i) != EMPTY; i++) ;
*(tab + i) = data ;
}
/*-----------------------------------------------------------------------------
existInt	: verifie si un element existe dans la table des entiers.
---------------------------------------------
parametres	: int *tab : La table des entiers . 
		  int data : la donnee .
--------------------------------------------
return		:  int : 1 si existe, 0 sinon .
------------------------------------------------------------------------------*/
int existInt(tab,data)
int *tab ;
int data ;
{
int i;

for(i = 0; *(tab + i) != EMPTY ; i++)
	if(*(tab + i) == data)
		return(1) ;
return(0) ;	
}
/*-----------------------------------------------------------------------------
delAuxBeh	: elimine les variables aux d'un beh.
---------------------------------------------
parametres	: beh
--------------------------------------------
return		:  rien.
------------------------------------------------------------------------------*/
delAuxBeh(beh,trace)
struct syf_befig *beh ;
int trace ;
{
struct syf_beout *out ;
struct syf_beaux *aux ;
struct syf_beaux *aux1 ;
struct syf_bebus *bus ;
struct syf_bereg *reg ;
struct syf_bemsg *msg ;
struct biabl *biabl ;


reg = beh->BEREG ;
while (reg != NULL)
	{
	biabl = reg->BIABL ;
	while(biabl)
		{
		aux = beh->BEAUX ;
		while(aux)
			{
			if(ATOM(biabl->CNDABL) && !strcmp(aux->NAME,(char *)(biabl->CNDABL->DATA)))
				biabl->CNDABL = copyExpr(aux->ABL) ;
			else
				substPhyExpr(biabl->CNDABL,aux->NAME,aux->ABL) ;
			if(ATOM(biabl->VALABL) && !strcmp(aux->NAME,(char *)(biabl->VALABL->DATA)))
				biabl->VALABL = copyExpr(aux->ABL) ;
			else
				substPhyExpr(biabl->VALABL,aux->NAME,aux->ABL) ;
			aux = aux->NEXT ;
			}
		biabl = biabl->NEXT ;
		}
	reg = reg->NEXT ;
	}

msg=beh->BEMSG;
aux1 = beh->BEAUX;
while (aux1 != NULL)
	{
	aux = beh->BEAUX ;
	while(aux)
		{
		substPhyExpr(aux1->ABL,aux->NAME,aux->ABL) ;
		aux = aux->NEXT ;
		}
	aux1 = aux1->NEXT ;
	}

out = beh->BEOUT;
while (out != NULL)
	{
	aux = beh->BEAUX ;
	while(aux)
		{
		if(ATOM(out->ABL) && !strcmp(aux->NAME,(char *)(out->ABL->DATA)))
			out->ABL = copyExpr(aux->ABL) ;
		else
			substPhyExpr(out->ABL,aux->NAME,aux->ABL) ;
		aux = aux->NEXT ;
		}
	out = out->NEXT ;
	}

bus = beh->BEBUS;
while (bus != NULL)
	{
	biabl = bus->BIABL ;
	while(biabl)
		{
		aux = beh->BEAUX ;
		while(aux)
			{
			substPhyExpr(biabl->CNDABL,aux->NAME,aux->ABL) ;
			substPhyExpr(biabl->VALABL,aux->NAME,aux->ABL) ;
			aux = aux->NEXT ;
			}
		biabl = biabl->NEXT ;
		}
	bus = bus->NEXT ;
	}

reg = beh->BEREG ;
while (reg != NULL)
	{
	biabl = reg->BIABL ;
	while(biabl)
		{
		aux = beh->BEAUX ;
		while(aux)
			{
			substPhyExpr(biabl->CNDABL,aux->NAME,aux->ABL) ;
			substPhyExpr(biabl->VALABL,aux->NAME,aux->ABL) ;
			aux = aux->NEXT ;
			}
		biabl = biabl->NEXT ;
		}
	reg = reg->NEXT ;
	}

msg=beh->BEMSG;
while (msg != NULL)
	{
	aux = beh->BEAUX ;
	while(aux)
		{
		substPhyExpr(msg->ABL,aux->NAME,aux->ABL) ;
		aux = aux->NEXT ;
		}
	msg = msg->NEXT ;
	}
syf_beh_frebeaux(beh->BEAUX) ;
beh->BEAUX = NULL ;
}
