 /****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  synthese FPGA                                              */
/*    Fichier :  fp_util.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 "../synthe/sl_type.h"
#include "../compil/sl_util.h"
#include "../synthe/sl_system.h"
#include "../bddorder/bdd_order.h"
#include "fp_type.h"
#include "fpga.h"


/*----------------------------------------------------------------------------
numbBdd	: assigns with an integer each vertex  in a Hash Table
------------------------------------------------------------------------------
return		: nothing
------------------------------------------------------------------------------*/

void numbBdd(bdd)
pNode bdd ;
{
/*t printf(" numbBdd: assigns with an integer each vertex  in a Hash Table :\n" ); t*/
 if(bdd != one && bdd != zero)
	{
	numbBdd(bdd->high) ;
	numbBdd(bdd->low) ; 
	if (searchTH(vtable,bdd) == EMPTYTH || searchTH(vtable,bdd) == DELETETH)
		{ 
		addTH(vtable,bdd,nodenumber);
/*d		printf(" il a numerote non feuille avec %d\n", nodenumber); */
		nodenumber++;
		}
	}
else
	{
/*d 	printf(" il a trouve une feuille !\n" );
*/ 
	if(bdd == one)
		{
		if (searchTH(vtable,bdd) == EMPTYTH || searchTH(vtable,bdd) == DELETETH)
			{  
			addTH(vtable,bdd,1);
/*d			printf(" il a numerote feuille avec 1\n");
*/ 
			}
		}
	else
		if (searchTH(vtable,bdd) == EMPTYTH || searchTH(vtable,bdd) == DELETETH)
			{
			addTH(vtable,bdd,0);
/*d			printf(" il a numerote feuille avec 0\n");
*/  			}

	}
 }

/*----------------------------------------------------------------------------
vertexVariable	:  gets a vertex and finds its variable name 
------------------------------------------------------------------------------
retour		: string of char with the variable name
------------------------------------------------------------------------------*/
char* vertexVariable(beh,index)
struct befig *beh;
int index;
{
char* varname;
char** tabName;

tabName = beh->CIRCUI->pNameI;
varname = *(tabName + index - 2);
return(varname);
}

/*
----------------------------------------------------------------------------
suppBdd	:  put in a Hash Table (supptable) the variable support of each vertex
------------------------------------------------------------------------------
return		: nothing
------------------------------------------------------------------------------

char *suppBdd(bdd, ptstring)
pNode bdd;
char *ptstring; 

{
char *newvarname, *aux1, *aux2;
char *strleft;
char *strright;
char *st;


st = ptstring;

printf(" suppBdd: assigns with a pointer each vertex  in a Hash Table :\n" ); 

 if(bdd != one && bdd != zero)
	{

	strleft = (char *) mbkalloc (100);
	strright= (char *) mbkalloc (100);

	strright = suppBdd(bdd->high) ;
	strleft  = suppBdd(bdd->low);
	if (searchTH(supptable,bdd) == EMPTYTH || searchTH(supptable,bdd) == DELETETH)
		{

		st = (char *) mbkalloc (strlen(ptstring)+ 100);

		st ="";
		aux1 = "";
		aux2 = "";
		strcpy(st,ptstring);

 		fflush(stdout);

		newvarname = vertexVariable(FP_BEH,bdd->index);

 		fflush(stdout);

		aux1 = st;
		aux2 = newvarname;
		strcat(st,aux2);

		printf(" the string st concatenated  is: %s \n", st );
		printf(" the length of st is : %d \n", strlen(st));
 		fflush(stdout);


 		strcpy(aux2,"");

		printf("will concatenate strright = %s and st = %s \n", strright, st);
		fflush(stdout);

 		aux2 = strright;
		strcat(st,aux2);

 		strcpy(aux2,"");


		printf(" the string st concatenated  is: %s \n", st );
		printf(" the length of st is : %d \n", strlen(st));
 		fflush(stdout);

		printf("will concatenate strleft = %s and st = %s \n", strleft, st);
		fflush(stdout);


 		aux2 = strleft;
		strcat(st,aux2);

		printf(" the string st concatenated  is: %s \n", st );
		printf(" the length of st is : %d \n", strlen(st));
 		fflush(stdout);


		return(st);
		}
	else
		return ("@");
	}
else
	return("#");
  }

*/

/*----------------------------------------------------------------------------
suppBdd	:  put in a Hash Table (supptable) the variable support of each vertex
------------------------------------------------------------------------------
return	: nothing
------------------------------------------------------------------------------*/

void suppBdd(bdd, pC)
pNode bdd;
pCircuit pC; 

{
chain_list *stsupp;
chain_list *expr, *ch;
char *name, *chain2Str() ; 
 

 if(bdd != one && bdd != zero)
	{
	suppBdd(bdd->high,pC);
	suppBdd(bdd->low,pC);
	if (searchTH(supptable,bdd) == EMPTYTH || searchTH(supptable,bdd) == DELETETH)
		{
		stsupp = (chain_list *)supportIndexBdd(bdd,1);
 		ch = stsupp;
 		while(stsupp)
			{
			stsupp->DATA = (void *)searchIndexCct(pC,stsupp->DATA);
			stsupp = stsupp->NEXT;
			}
	 	stsupp = ch;
		name = chain2Str(stsupp) ;
	 	addTH(supptable,bdd,name);
 		}
	}
  }

/*----------------------------------------------------------------------------
dispHashBdd	: Displays of a Bdd from a Hash Table
------------------------------------------------------------------------------
retour		: nothing
------------------------------------------------------------------------------*/

dispHashBdd(bdd)
pNode bdd ;
{
 /*d printf(" entrou na dispHashBdd :\n" );*/
 if(bdd != one && bdd != zero)
	{
	dispHashBdd(bdd->high) ; 
	printf("%d\n",searchTH(vtable,bdd)); 
	dispHashBdd(bdd->low) ;
	
	}
else
	{
/*d	printf(" encontrou uma folha !\n" ); 
	printf("%d\n",searchTH(vtable,bdd)); */
	 }
 }


/*----------------------------------------------------------------------------
markXBdd	: marque avec un entier les noeds d'un bdd 
------------------------------------------------------------------------------
retour		: rien
------------------------------------------------------------------------------*/

markXBdd(nN,bdd)
int nN ;
pNode bdd ;
{
 if(bdd->mark > 0)
	return ;
 if(bdd != one && bdd != zero)
	{
	markXBdd(nN+1, bdd->high) ;
	markXBdd(nN+2, bdd->low) ;
	bdd->mark = nN ;

	}
else
	{
	if(bdd == zero)
	bdd->mark = 0  ;	
	if(bdd == one)
	bdd->mark =  1 ;
	}

}
 

/*----------------------------------------------------------------------------
displaymyTH	: vertical display of HT ------------------------------------------------------------------------------
retour		: nothing
------------------------------------------------------------------------------*/

 
/* affichage des elements de la table */

void displaymyTH(pTable)
pTH pTable;
{
int i;
pElemTH pEl;
pEl=pTable->pElem; 
printf("================== DISPLAYTH ================\n");
printf("length = %d\t		count = %d\n",pTable->length,pTable->count);
printf("=============================================\n");
for (i=0;i<pTable->length;i++)
    {
    if (pEl->value != EMPTYTH && pEl->value !=DELETETH)
       {
       printf("index  %d\t",i);
       printf("key pointer  %d\t",pEl->key);
       printf("index  %d\t",(int)pEl->key->index);
       printf("value  %d \n",pEl->value);
       }
    pEl++;
    }
}


/*----------------------------------------------------------------------------
OutFunctionName	: search if the vertex is a function root  ------------------------------------------------------------------------------
returns		: a string assigned to the name of the function 
		  if it is not a root function it returns NULL
------------------------------------------------------------------------------*/
char* OutFunctionName(beh,bdd)
struct befig *beh ;
pNode bdd;

{
beout_list *out;

 out = beh->BEOUT;
 while (out)
        {
 	if (out->NODE == bdd)
		{
/*t		printf("il a trouve une racine de fonction");
		fflush(stdout);
		printf("la fonction est %s \n", out->NAME);
		fflush(stdout);
*/
		return(out->NAME);
		}
        out = out->NEXT;
        }
return("@");
}



/*----------------------------------------------------------------------------
printBdd	: ecrit les champs: mark , mark des fils et index 
		  d'un noed bdd.
------------------------------------------------------------------------------
retour		: rien
------------------------------------------------------------------------------*/
printBdd(fN,bdd) 
char* fN;
pNode bdd ;
 
{
int i, tabu;
int vertexnb, lonb, hinb;
char* varname;
char** tabName;
char* st;
chain_list *supp; 
if (bdd->mark != 0) 
	return;
bdd->mark = 1;
vertexnb = searchTH(vtable,bdd);
hinb = searchTH(vtable,bdd->high);
lonb = searchTH(vtable,bdd->low);
supp = (chain_list *)searchTH(supptable,bdd);

/*tabName = beh->CIRCUI->pNameI;*/

tabName = FP_CIRCUIT->pNameI;

varname = *(tabName + bdd->index - 2);

inputnb = FP_CIRCUIT->pTI->count;
 
st = OutFunctionName(FP_BEH,bdd);
if (strcmp("@",st))
	{
	tabu =  (inputnb + 1 - bdd->index) + 1;
	printf("%8s", st);
	}
else 
	{
	tabu =  (inputnb + 1 - bdd->index) + 2;
 	}

for(i = 1; i < tabu; i++)
	printf("\t");
printf(" %d_%d_%d %s,%d,%d",vertexnb,hinb,lonb,supp,bdd->index, bdd) ; 
/*printf(" (%d %d %d %d %s %s)",vertexnb,hinb,lonb,bdd->index,varname, supp) ;*/
printf("\n");
printf("\n");

}


 

/*----------------------------------------------------------------------------
displayXBdd	: vertical display of a bdd graph ------------------------------------------------------------------------------
retour		: rien
------------------------------------------------------------------------------*/
   
displayXBdd(funcName,bdd)
char* funcName;
pNode bdd ; 
{
int i;
char* fN;

 
fN = funcName; 
if(bdd == one || bdd == zero)
	return;
if(bdd != one && bdd != zero)
	{
 	displayXBdd(fN,bdd->high) ;
	printBdd(fN,bdd);
	displayXBdd(fN,bdd->low) ;
	}
}
/*----------------------------------------------------------------------------
displayVarAxis	: horizontal display of the variables names ------------------------------------------------------------------------------
retour		: nothing
------------------------------------------------------------------------------*/
void displayVarAxis(beh)
struct befig *beh ;
{
char *varname;
char** tabName;
int i, countin;
char *ptstring;

varname = (char *) mbkalloc (9);

 
/*d printf(" %s\n", smask) ;
fflush(stdout);
*/

/* detect if there is vdd or vss within the inputs */
tabName = beh->CIRCUI->pNameI;
countin = beh->CIRCUI->countI-2;
for(i = 0; i < countin; i++)
	{
	varname = *(tabName + countin - 1 - i);
	if (!strcmp(varname,"vdd") || !strcmp(varname,"vss"))
		 inputnb-- ; 
	}

 
tabName = beh->CIRCUI->pNameI;
countin = beh->CIRCUI->countI-2; 
for(i = 0; i < countin; i++)
	{
	varname = *(tabName + countin - 1 - i);
	if (strcmp(varname,"vdd") && strcmp(varname,"vss"))
		printf("\t %s", varname) ;
	}
printf("\n");
mbkfree(varname);
}

/*----------------------------------------------------------------------------
freeTH		: makes free TH 
------------------------------------------------------------------------------
retour		: nothing
------------------------------------------------------------------------------*/
/* liberation de l'espace  de la table */

void freeTH(pTable, varname)
pTH pTable;
char *varname;
{
int i;
pElemTH pEl;
pEl=pTable->pElem; 
printf("making free %s\n", varname);

for (i=0;i<pTable->length;i++)
    {
    if (pEl->value != EMPTYTH && pEl->value !=DELETETH)
       {
 	mbkfree(pEl->value);
       }
    pEl++;
    }
}


/*----------------------------------------------------------------------------
displayMultiGraph	: vertical display of a Multigraph ------------------------------------------------------------------------------
retour		: nothing
------------------------------------------------------------------------------*/
 
void displayMultiGraph(beh)
struct befig *beh ;
{ 
struct beout *out;
pNode res;
char* funcName;


markAllBdd(0); 


/* create a hash table for vertex numbering */

 
vtable = createTH(1000);


/* create a hash table for vertex support assignment */

supptable = createTH(1000);


/*  numbering each of subgraphs */

 
nodenumber = 2;
       
out = beh->BEOUT;
while (out)
	{
	res = out->NODE;
	numbBdd(res);
        out = out->NEXT; 
        }

/***** ici *****/

/*  support assignment of  each subgraphs */

 
out = beh->BEOUT;


while (out)
	{
	res = out->NODE;
 	suppBdd(res,beh->CIRCUI);
        out = out->NEXT;  
        }

/* display the multigraph from  hash table  */

 
if (trace)
	displaymyTH(vtable);


out = beh->BEOUT;
displayVarAxis(beh);
markBdd(out->NODE,0);
 
while (out)
	{
	funcName = out->NAME;
	res = out->NODE;
	fatherlevel = res->index;
  	displayXBdd(funcName,res);
 	out = out->NEXT;
	}

freeTH(vtable,"vtable");
destroyTH(vtable);
freeTH(supptable, "supptable");
destroyTH(supptable);
}


/*----------------------------------------------------------------------------
orderCostEval	: Evaluate the cost of an ordered graph 
------------------------------------------------------------------------------
retour		: an integer
------------------------------------------------------------------------------

int orderCostEval(vert)
pNode vert;
{
pNode pBdd;
pNode ptnotBdd;
pNode ptLow, ptHigh;
int cost;

if (vert->index < 2)
	return(0);  terminal vertex cost = 0 
}

*/


/*----------------------------------------------------------------------------
computeFathersBddBeh	: computes the number of fathers of all vertices
		  of a multigraph and put it in a hash table
------------------------------------------------------------------------------
return		: hash table
------------------------------------------------------------------------------*/
fathersNumber(pt,fatherTable)
pNode pt;
pTH fatherTable;
{ 
int countfather, notcountfather;

if (pt == one || pt == zero)
	return;

countfather = searchTH(fatherTable,pt);

if (countfather == EMPTYTH )
 	countfather = 1;
else
	countfather++;

addTH(fatherTable,pt,countfather);
addTH(fatherTable,notBdd(pt),countfather);

if (countfather == 1)
   {
   pNode pBdd;

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

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

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


pTH computeFathersBddBeh(beh)
befig_list *beh ;
{
beout_list *out;
bereg_list *reg;
binode_list *binode;
pTH fatherTable; /* hash table for vertex fathers computing */


markAllBdd(0);
fatherTable = createTH(1000); /* create a hash table for fathers computing */

out = beh->BEOUT;
while (out)
   {
   fathersNumber(out->NODE,fatherTable);
   out = out->NEXT; 
   }

reg = beh->BEREG;
while (reg)
   {
   binode = reg->BINODE;
   while (binode)
      {  
      fathersNumber(binode->CNDNODE,fatherTable);
      fathersNumber(binode->VALNODE,fatherTable);
      binode = binode->NEXT;
      }  
   reg = reg->NEXT;
   }  

return(fatherTable);
}

/*----------------------------------------------------------------------------
chain2Str	: transforme a chain_list to string. 
------------------------------------------------------------------------------
retour		: char *.
------------------------------------------------------------------------------*/
char *chain2Str(chain)
chain_list *chain ;
{
chain_list *chain2 ;
char *name ;

name = mbkalloc(1000) ;
strcpy(name,"") ;

chain2 = chain ;
while(chain2)
	{
	sprintf(name,"%s %s",name,(char *)chain2->DATA) ;
	chain2 = chain2->NEXT ;
	}
return(name) ;
}


