
/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_ncod.c                                                  */
/*                                                                          */
/*    (c) copyright 1992 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :  C. Sarwary                            le : 15/06/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/
#include <stdio.h>
#include <math.h>
#include MUT_H
#include LOG_H
#include "../util/util.h"
#include "syf_must.h"
#include "syf_asp.h"
#include "syf_auto.h"
#include "syf_ncod.h"
/*-----------------------------------------------------------------------------
nc_genGroup	: Genere des goupes d'etats selon le motif donne.
---------------------------------------------
parametres	: int motif : FUSION -> regroupement des etats permettant
				une fusion .
			    : FACT -> regroupement des etats permettant
				une factorisation .
--------------------------------------------
return		: liste des groupes generes .
------------------------------------------------------------------------------*/
chain_list *nc_genGroup(motif,AME)
int motif ;
int AME;
{
p_groupe *tabGrp ;
pTrans trans, trans2 ;
chain_list *listGrp ;
chain_list *head ;
int *tabState ;
pState state;
pNode bdd1, bdd2 ;
int i,j;
int *tabPoidEtat, *tabPoidGroup, *tabCode ;
p_groupe Se;
int *tabPoidFutur;
int selectLabel;
int *nwS,*nwO;
int *we;
chain_list **tabGroup ;
int *tabSp ;

printf("entree nc_genGroup\n") ;
/**** Pour le moment seulement la fusion ******/
tabState = (int *)mbkalloc(sizeof(int) * autoSys->numberState) ;
tabSp = (int *)mbkalloc(sizeof(int) * NB_GROUP) ;


/*********** CAS DES NOEUDS PRECEDANTS ALLANT VERS MEME ETAT SUIVANT ***********
******************* AVEC MEME FONCTION DE TRANSITIN **************************/

numberGroup = 0;
state = autoSys->state ;
listGrp = NULL ;
for(i = 0; i < autoSys->numberState; i++)
	{
	fflush(stdout) ;
	head = NULL ;
	trans = state->trans ;
	for(j = 0; j < autoSys->numberState; j++)
		*(tabState + j) = EMPTY ;
	for(j = 0; j < NB_GROUP; j++)
		*(tabSp + j) = EMPTY ;
	while(trans)
		{
		if(!existInt(tabState,trans->sPlabel))
			{
			bdd1 = trans->bdd ;
			trans2 = trans ;
			while(trans2)
				{
				if(!existInt(tabState,trans2->sPlabel))
					{
					bdd2 = trans2->bdd ;
					if(bdd1 == bdd2)
						{
						head = addchain(head,trans2->sPlabel) ;	
						addTabInt(tabState,trans2->sPlabel) ;
						}	
					}
				trans2 = trans2->next ;
				}
			if(head != NULL && head->NEXT != NULL)
				{
				listGrp = addchain(listGrp,head) ;
				printf("head = %d\n",head) ;
				/* remplissage de la table des Ep */
				if(!existInt(tabSp,i))
					{
					addTabInt(tabSp,i) ;
					}
				}
			}
		trans= trans->next ;
		}
	state++ ;
	}
printf("************ LES GROUPES 1ERE PRIORITE *********\n") ;
nc_displayGrp(listGrp,tabSp) ;
/************ CAS DES NOEUDS FUTUR PROVENANT D'UN MEME NOEUD *******************
******************* MEME S'IL N'ONT PAS FONCTION DE TRANSITIN ******************
*************** CELA SERA TENU COMPTE DANS UNE FONCTION DE COUT ***************/
tabGroup=(chain_list**)mbkalloc(autoSys->numberState*sizeof(chain_list *)) ;
for(i = 0; i < autoSys->numberState; i++)
	*(tabGroup + i) = NULL ;

state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
	{
	trans = state->trans ;
	while(trans)
		{
		*(tabGroup+i) = addchain(*(tabGroup+i),trans->sPlabel) ;	
		trans = trans->next ;
		}
	}
printf("elimination des groupes inutils \n") ;
tabGroup = elimineGroupInutil(tabGroup) ;
/**** Jusqu'a ce que la liste des groupes d'avant devient table des groupes***/
for(i = 0; *(tabGroup + i) != NULL; i++)
	addchain(listGrp,*(tabGroup + i)) ;

/*
head = NULL ;
for(i = 0; i < autoSys->numberOut; i++)
	{
	state = autoSys->state ;
	out = state->locOut ;
	for(k = 0; k < i; k++)
		out = out->next ;
	outBdd = out->bdd ;
	for(j = 0; j < autoSys->numberState; j++)
		{
		out2 = state->locOut ;
		for(k = 0; k < i; k++)
			out2 = out2->next ;
		if(outBdd == out2->bdd)
			head = addchain(head,state->label) ;	
		state++ ;
		}
	}
*/
tabGrp = chain_list2group(listGrp) ;
printf("Debut code\n") ;
tabPoidEtat = asp_poidEtat() ;
tabPoidGroup = asp_poidGroup(tabGrp,tabPoidEtat) ;
/*displayTabGrp(tabGrp,tabPoidGroup) ;*/
tabGrp[numberGroup] = stateGeneration();
tabPoidGroup[numberGroup++] = 0;
tabCode = asp_codage(tabGrp,tabPoidGroup) ;
if(AME)
{
nwS = (int *)mbkalloc((autoSys->numberState +1 )*(autoSys->numberState +1)  * sizeof(int )) ;
nwO = (int *)mbkalloc((autoSys->numberState + 1)*(autoSys->numberOut) * sizeof(int )) ;
mustPoids(nwS,nwO);
we = mustCalcul(nwS,nwO);
tabPoidFutur = PoidsFutur();
if(AME)
	printf("fin du codage et debut de l'amelioration\n");
for(i=0; i< AME; i++)
{
Se = stateGeneration();
while(Se)
 {
  selectLabel = codeModification(we,tabPoidEtat,tabPoidFutur,tabCode,Se);
  Se = delFromgroup(Se,selectLabel);
}
 printf("fin du %dieme iteration\n",i);
}
}

printf("fin code\n") ;
return(listGrp) ;
}
/*-----------------------------------------------------------------------------
nc_displayGrp : visualise les groupes .
---------------------------------------------
parametres	  : liste des groupes, et table des etats presents correspondante .
--------------------------------------------
return		  : void .
------------------------------------------------------------------------------*/
void nc_displayGrp(listGrp,tabSp)
chain_list *listGrp ;
int *tabSp ;
{
chain_list *grp,*curentList ;
int i ;

printf("****************** DISPLAYGRP *******************\n") ;
if(listGrp == NULL)
	printf("nc_displayGrp : pas de groupe\n") ;
else
	{
	i = 0 ;
	curentList = listGrp ;
	while(curentList)
		{
		printf("ETAT : %s\n",(autoSys->state+*(tabSp+i))->name) ;
		i++ ;
		grp = (chain_list *)curentList->DATA ;
		if(grp != NULL)
			printf("******* GROUPE : %d\n",i) ;
		while(grp)
			{
			printf("\t%s\n",(autoSys->state+(int)grp->DATA)->name) ;
			grp = grp->NEXT ;
			}
		curentList = curentList->NEXT ;
		}
	}
}
/*-----------------------------------------------------------------------------
chain_list2group : convertit une structure chain_list en structure groupe(asp) .
---------------------------------------------
parametres	  : la structure chain_list .
--------------------------------------------
return		  : structure grpoupe generee .
------------------------------------------------------------------------------*/
p_groupe *chain_list2group(chain)
chain_list *chain ;
{
p_groupe *pGroup, *pGroup2, group ;
chain_list *chainEl ;

pGroup = (p_groupe *) mbkalloc(NB_GROUP * sizeof(p_groupe)) ;
group = NULL ;
pGroup2 = pGroup ;
while(chain)
	{
	chainEl = (chain_list *)chain->DATA ;
	while(chainEl)
		{
	    group = addTogroup(group,chainEl->DATA) ;
		chainEl = chainEl->NEXT ;
		}
	*pGroup2 = group ;
	numberGroup++;
	pGroup2++ ;
	group = NULL ;
	chain = chain->NEXT ;
	}
return(pGroup) ;
}
/*-----------------------------------------------------------------------------
elimineGroupInutil : elimine les groupes ne possedant qu'un element .
---------------------------------------------
parametres	  : table des groupes .
--------------------------------------------
return		  : nouvelle table reduite .
------------------------------------------------------------------------------*/
chain_list ** elimineGroupInutil(tabGrp)
chain_list **tabGrp ;
{
int i, j ;
chain_list **newTabGrp ;

for(i = 0; i < autoSys->numberState; i++)
	if((*(tabGrp + i))->NEXT == NULL)
		*(tabGrp + i) = NULL ;

newTabGrp=(chain_list**)mbkalloc(autoSys->numberState*sizeof(chain_list *)) ;
for(i = 0; i < autoSys->numberState; i++)
	*(newTabGrp + i) = NULL ;

j = 0 ;
for(i = 0; i < autoSys->numberState; i++)
	if(*(tabGrp+i) != NULL)
		{
		*(newTabGrp + j) = *(tabGrp + i) ;
		j++ ;
		}
/*#ifndef ARCHI_PC*/
free(tabGrp) ;
/*#endif*/
return(newTabGrp) ;
}
/*-----------------------------------------------------------------------------
displayTabGrp : visualise la table des groupes .
---------------------------------------------
parametres	  : table des groupes .
--------------------------------------------
return		  : void .
------------------------------------------------------------------------------*/
void displayTabGrp(tabGrp, tabPoidGrp)
p_groupe *tabGrp ;
int * tabPoidGrp ;
{
p_groupe grp ;
int i ;

printf("****************** DISPLAYTabGRP *******************\n") ;
for(i = 0; i < NB_GROUP; i++)
	{
	printf("*** poid = %d\n",*(tabPoidGrp+i)) ;
	grp = *(tabGrp + i) ; 
	printf("******* GROUPE : %d\n",i) ;
		while(grp)
			{
			printf("\t%s\n",(autoSys->state+(int)grp->label)->name) ;
			grp = grp->next ;
			}
	}
}
/*-----------------------------------------------------------------------------
completGroupCub : utilise les codes non utilise pour completer les groupes
					en 2^n etats .
---------------------------------------------
parametres	  : list des groupes ordonnee par ordre de priorite.
--------------------------------------------
return		  : void .
------------------------------------------------------------------------------*/
void completGroupCub(listGrp)
chain_list *listGrp ;
{
int i, remainState ;
chain_list *curListGrp ;
chain_list *grp ;

remainState = autoSys->numberReg - autoSys->numberState ;
curListGrp = listGrp ;
while(curListGrp && remainState)
	{
	grp = (chain_list *)curListGrp->DATA ;
	i = 0 ;
	while(grp)
		{
		i++ ;
		grp = grp->NEXT ;
		}
	if(!isCub(i))
		remainState = completGrp(curListGrp->DATA, remainState) ;
	curListGrp = curListGrp->NEXT ;
	}
}
/*-----------------------------------------------------------------------------
isCub		 : verifie si un nombre est une puissance de n
---------------------------------------------
parametres	  : le nombre.
--------------------------------------------
return		  : 1, si oui, 0 sinon .
------------------------------------------------------------------------------*/
int isCub(i)
int i ;
{
for(; i>=1; i/2) ;
if(i == 1)
	return(1) ;
return(0) ;
}
/*-----------------------------------------------------------------------------
completGrp		: complete la liste des etats en puissance de 2 .
---------------------------------------------
parametres	  	: groupe d'etats,nombre d'etats a ajouter,
					nombre de codes disponibles .
--------------------------------------------
return		  	: nouveau nombre de codes disponibles .
------------------------------------------------------------------------------*/
int completGrp(grp,remainState)
chain_list *grp ;
int remainState ;
{

}
