
/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_muse.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 : 19/03/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/

#include <stdio.h>
#include <math.h>
#include MUT_H
#include LOG_H
#include "syf_auto.h"
#include "syf_muse.h"
#include "../util/util.h"

/*---------------------------------------------------------------------------
muse           : regroupe tous les fonctions du codage mustang
---------------------------------------------------------------------------
parametres        : aucun
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
muse(AME)
int AME;
{
int i,selectLabel;
int *tabPoid;
int *tabCode;
p_groupe Se;

initializeMuse();
musePrePoidPresent();
/*musePoidPresent();*/
tabPoid = asp_poidEtat();/*numNodeEtat();*/
tabCode = museChoix(tabPoid);
if(AME)
{
for(i =0; i<AME; i++)
{
  Se= stateGeneration();
	while(Se)
	{
	  selectLabel = codeModification(wp,tabPoid,wf,tabCode,Se);
      Se = delFromgroup(Se, selectLabel);
 	}
   printf("%dieme iteration\n",i+1);
 }
}
/*#ifndef ARCHI_PC*/
free(wf);
free(wp);
free(wcm);
free(nwS);
free(nwO);
/*#endif*/
}

/*---------------------------------------------------------------------------
initializeMuse  : initialise la structure Mustang .
-------------------------------------------------------------------------
parametres      : aucun .
------------------------------------------------------------------------
return          : rien  .
---------------------------------------------------------------------------*/
void initializeMuse()
{
int numberBit;
int i;

numberBit = autoSys->numberReg;

nwS = (int *)mbkalloc((autoSys->numberState +1 )*(autoSys->numberState +1)  * sizeof(int )) ;
nwO = (int *)mbkalloc((autoSys->numberState + 1)*(autoSys->numberOut) * sizeof(int )) ;
 wf = (int *)mbkalloc((autoSys->numberState + 1)* autoSys->numberState * sizeof(int )) ;
 wp = (int *)mbkalloc((autoSys->numberState + 1)* autoSys->numberState * sizeof(int )) ;
 wcm = (p2_groupe *)mbkalloc((autoSys->numberState + 1)* autoSys->numberState * sizeof(struct E2_groupe )) ;
for(i =0; i< (autoSys->numberState + 1)*(autoSys->numberState);i++)
  wcm[i] = NULL;

 for(i = 0; i < bit[numberBit]; i++)
        (autoSys->code + i)->code = bit[numberBit] ;
 autoSys->dc  = autoSys->code + autoSys->numberState;
}

/*---------------------------------------------------------------------------
 musePoidsPresent    :  remplit les matrices de poids des etats .
-----------------------------------------------------------------
 parametres   : aucun .
-----------------------------------------------------------------
 return       : rien
---------------------------------------------------------------------------*/
 void musePrePoidPresent()
 {
 int j;
 int DIMS,DIMO;
 pLocOut out;
 pLocOut outAux;
 pTrans trans;
 pTrans transAux;
 pState state;
 int sPlabel;
 int val;
 int label;

 
  state = autoSys->state;
  DIMS = autoSys->numberState;
  DIMO = autoSys->numberOut;
  for(j = 0; j < autoSys->numberState; j++)
  {
        out = state->locOut;
        while(out)
         {
	   (nwO[out->label *DIMO + j])++ ;
         out = out->next;
        }
    trans = state->trans;
    while (trans)
    {
     if(trans->sPlabel != -1)
     {
      transAux = state->trans;
        sPlabel = trans->sPlabel;
        (nwS[j * DIMS + sPlabel])++ ;
        while(transAux->sPlabel != sPlabel)
        {
         val = compBdd(trans->bdd,transAux->bdd); 
         if(val != 0) 
         {
         wcm[sPlabel*DIMS + transAux->sPlabel] = addTo2group(wcm[sPlabel*DIMS + transAux->sPlabel],val,j);
      /*  out = trans->locOut;
        outAux = transAux->locOut;
        while((outAux)&&(out))
         {
         if((outAux->bit == 1)&&(out->bit==1))
         wcm[sPlabel*DIMS + transAux->sPlabel] = addTo2group(wcm[sPlabel*DIMS + transAux->sPlabel],val,-1);
         outAux = outAux->next;
         out = out->next;
        }*/
       }
        transAux = transAux->next; 
      }
      }
       trans = trans->next;
    }
    state++;
  }
 }
/*---------------------------------------------------------------------------
 musePoidFutur   : calcul le poids effectif de chaque couple d'etats .
---------------------------------------------------------------------
 parametres   : aucun .
--------------------------------------------------------------------
 return       : rien .
---------------------------------------------------------------------------*/
musePoidsFutur()
{
int k,l;
pNode tabBdd[3];
int DIMS,DIMO;

  DIMS = autoSys->numberState;
  DIMO = autoSys->numberOut;
  for(k = 0; k < autoSys->numberState ; k++)
  {
    for(l = 0; l < autoSys->numberState ; l++)
    {
    tabBdd[0] =(autoSys->state + k)->bdd;
    tabBdd[1] =(autoSys->state + l)->bdd;
    tabBdd[2] = NULL;
    printf("APPEL MultiBdd\n") ;
    wf[k*DIMS + l] = 0 ;/*numberNodeMultiBdd(tabBdd);*/
    }
  }
}

/*---------------------------------------------------------------------------
 mustCalcul   : calcul le poids effectif de chaque couple d'etats .
---------------------------------------------------------------------
 parametres   : aucun .
--------------------------------------------------------------------
 return       : rien .
---------------------------------------------------------------------------*/
 void musePoidPresent()
 {
 int i,k,l;
 int DIMS,DIMO;

  DIMS = autoSys->numberState;
  DIMO = autoSys->numberOut;
  for(k = 0; k < autoSys->numberState ; k++)
  {
    for(l = 0; l < autoSys->numberState ; l++)
    {
      for(i = 0; i < autoSys->numberState; i++)
      {
	if (k!=l) 
           wp[k * DIMS +l] += nwS[i*DIMS +k]*nwS[i*DIMS +l] * numbit_1((autoSys->code + i)->code,autoSys->numberReg);
      }
      for(i = 0 ; i < autoSys->numberOut; i++)
     if (k!=l) 	wp[k*DIMS +l] += nwO[i*DIMO +k]*nwO[i*DIMO +l];
    }
    wp[k*DIMS +l] = 0 ;

  }
 }

/*---------------------------------------------------------------------------
 mustCalcul   : calcul le poids effectif de chaque couple d'etats .
---------------------------------------------------------------------
 parametres   : aucun .
--------------------------------------------------------------------
 return       : rien .
---------------------------------------------------------------------------*/
 int musePoid(k,l)
 int k,l;
 {
 int i;
 int DIMS,DIMO;

  DIMS = autoSys->numberState;
  DIMO = autoSys->numberOut;
      for(i = 0; i < autoSys->numberState; i++)
      {
	if (k!=l) 
           wp[k * DIMS +l] += nwS[i*DIMS +k]*nwS[i*DIMS +l] * numbit_1((autoSys->code + i)->code);
      }
      for(i = 0 ; i < autoSys->numberOut; i++)
     if (k!=l) 	wp[k*DIMS +l] += nwO[i*DIMO +k]*nwO[i*DIMO +l];
  return(wp[k*DIMS + l]);

 }
/*---------------------------------------------------------------------------
display2Group      : affiche l'ensembles des etats qui non pas etait choisis 
---------------------------------------------------------------------------
parametres        : le groupe des etats non codes   
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
display2Group(gg)
p2_groupe gg;
{
printf("---------groupe -------\n");
while(gg)
 { 
  printf("val = %d-- label = %d\n",gg->val,gg->label);
  gg = gg->next;
 }
}


/*---------------------------------------------------------------------------
delFromgroup      : enleve un element du groupe  
---------------------------------------------------------------------------
parametres        : le groupe , l'element a enlever .   
--------------------------------------------------------------------------
return            : le groupe modifier .
---------------------------------------------------------------------------*/
p2_groupe delFrom2group(gg, selectLabel)
p2_groupe gg;
int selectLabel;
{
 p2_groupe ggAux;
 p2_groupe ggAux2;

 ggAux =gg;
 
if(ggAux->label == selectLabel) 
   {
   gg = gg->next;
/*#ifndef ARCHI_PC*/
   free(ggAux); 
/*#endif*/
   return(gg);
   }

 while(ggAux->next)
 {
  int label = ggAux->next->label;
   if(label == selectLabel) 
   {
      ggAux2 = ggAux->next;
      ggAux->next = (ggAux->next)->next ; 
/*#ifndef ARCHI_PC*/
      free(ggAux2); 
/*#endif*/
      return(gg);
   }
  ggAux =ggAux->next;
 }
return(gg);
}
/*---------------------------------------------------------------------------
addTogroup        : ajoute un element au groupe  
---------------------------------------------------------------------------
parametres        : le groupe , l'element a ajouter .   
--------------------------------------------------------------------------
return            : le groupe modifier .
---------------------------------------------------------------------------*/
p2_groupe addTo2group(gg,val,selectLabel)
p2_groupe gg;
int selectLabel;
int val;
{
 p2_groupe gmAux;

 gmAux =gg;
 
  gmAux = (p2_groupe)mbkalloc(sizeof(struct E2_groupe)) ;

  gmAux->label = selectLabel ;
  gmAux->val = val ;
  gmAux->next = gg;
  gg = gmAux;
  return(gg);
}

/*---------------------------------------------------------------------------
numNodeEtat       : genere l'etat qui va etre coder a la
                    prochaine iteration .
---------------------------------------------------------------------------
parametres        : aucun
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
int *numNodeEtat()
{
int i;
int *tabPoid;

tabPoid = (int *)mbkalloc(autoSys->numberState * sizeof(int)) ;

for (i=0; i< autoSys->numberState; i++)
tabPoid[i] = numberNodeBdd((autoSys->state + i)->bdd);
return(tabPoid);
}

/*---------------------------------------------------------------------------
compBdd         : genere l'etat qui va etre coder a la
                    prochaine iteration .
---------------------------------------------------------------------------
parametres        : aucun
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
int compBdd(bdd1,bdd2)
pNode bdd1,bdd2;
{
int  val ;
pNode bdd, bdd0;

bdd = applyBinBdd(AND,bdd1,notBdd(bdd2));
bdd0 = applyBinBdd(AND,bdd2,notBdd(bdd1));
if ((bdd == zero)&&(bdd0 == zero))
	val = numberNodeBdd(bdd1) + autoSys->numberReg +1;
else if ((bdd == zero)||(bdd0 == zero))
	val = 1;
else val = 0;
return(val);
}

/*---------------------------------------------------------------------------
choixJedi         : genere l'etat qui va etre coder a la
                    prochaine iteration .
---------------------------------------------------------------------------
parametres        : aucun
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
 int *museChoix(tabPoid)
 int *tabPoid;
 {
 int numberBit;
 int dclabel;
 pCode code;
  int selectLabel;
  int maxW = 0;
 pCode dc;
 int *tabCode;
 int i;
 p_groupe Su;
   p_groupe gga; 
 p_groupe Sa = NULL;
 int DIMS;

 numberBit = autoSys->numberReg;
 DIMS = autoSys->numberState;

 tabCode = (int*)mbkalloc(bit[numberBit] * sizeof(int)) ;
 for  (i = 0; i < bit[numberBit]; i++)
  tabCode[i] = bit[numberBit];

 code = autoSys->code;
 
 Su = stateGeneration();
  
  selectLabel =0;
  maxW = tabPoid[0];
  for(i=1 ; i< autoSys->numberState; i++)
  {
  if( tabPoid[i] > maxW)  
     {
       selectLabel = i;
       maxW = tabPoid[i];
     }
  }
  (code + selectLabel)->code = 0;
  Sa = addTogroup(NULL,selectLabel);
  Su = delFromgroup(Su,selectLabel);
  tabCode[0] = selectLabel;
 
 while(Su)
 {
  p_groupe ggu;
 
  ggu = Su;
  selectLabel = ggu->label;
  musePoidPresent();

  maxW = 0;

  while(ggu)
  { 
   p2_groupe wcmgroup;
   int cout = 0;
   int courantLabel = ggu->label;
  
  gga =Sa;

   while(gga)
   {
    int label = gga->label;
   
    cout += tabPoid[courantLabel] + tabPoid[label] - wf[courantLabel*DIMS +label] + wp[courantLabel*DIMS + label];
    gga = gga->next; 
    }
   if (cout > maxW)
    {
      maxW = cout; 
      selectLabel = courantLabel;
    }
   ggu = ggu->next;
  }
  gga =Sa;
  Sa = addTogroup(gga,selectLabel);
  museCodage(selectLabel, tabCode,tabPoid, gga);
  Su = delFromgroup(Su,selectLabel);
 }
 dc = autoSys->dc;
 dclabel = autoSys->numberState;
 for(i = 0; i < bit[numberBit]; i++)
 {
 if(tabCode[i] == bit[numberBit])
   {
   tabCode[i] = dclabel;
   dc->code = i;
   dclabel++;
   dc++;
   }
 }
 return(tabCode);
}


/*---------------------------------------------------------------------------
jediCodage        : attribue un code a l'element selectionner .
---------------------------------------------------------------------------
parametres        : l'etat selectionner et la table des codes
--------------------------------------------------------------------------
return            : rien .
---------------------------------------------------------------------------*/
 void museCodage(selectLabel,tabCode,tabPoid, Sa)
 int selectLabel;
 p_groupe Sa;
 int *tabPoid;
 int *tabCode;
 {
  int numberBit;
  pCode code;
  p_groupe gga;
  int codeSa;
  int cout =0 ;
  int i,val= -1;
  int DIMS;
   p2_groupe wcmgroup;
  int selectCode;

 
  numberBit = autoSys->numberReg;
  code = autoSys->code;

  DIMS = autoSys->numberState;
   gga = Sa;
   if (gga == NULL) 
    {
     (code + selectLabel)->code = 0;
     tabCode[0] = selectLabel;
     return ;
    }

  for( i =0; i< bit[numberBit]; i++)
  {
   if (tabCode[i]== bit[numberBit])
   {
   cout = tabPoid[selectLabel]*numbit_1(i,numberBit);
   gga = Sa;
   while(gga)
   {
    codeSa = (code + gga->label)->code;
    cout = cout + wf[gga->label*DIMS +selectLabel]*numbit_1Two(codeSa,i,numberBit) + wp[gga->label*DIMS + selectLabel] * (numberBit - distHaming(codeSa,i,numberBit)) ;
    if (distHaming(codeSa,i,numberBit) == 1) 
    {
      wcmgroup = wcm[gga->label * DIMS + selectLabel];
      while(wcmgroup)
      {
        if(wcmgroup->label != -1)
           cout  -= wcmgroup->val * numbit_1((code + wcmgroup->label)->code,numberBit);  
        else
           cout  -= wcmgroup->val ;  
        wcmgroup = wcmgroup->next;
      }
      wcmgroup = wcm[gga->label + selectLabel * DIMS];
      while(wcmgroup)
      {
        if(wcmgroup->label != -1)
           cout  -= wcmgroup->val * numbit_1((code + wcmgroup->label)->code,numberBit);  
        else
           cout  -= wcmgroup->val ;  
        wcmgroup = wcmgroup->next;
      }
    }
    gga= gga->next;
   }
   if ((cout < val)||(val == -1 )) 
     {
      selectCode = i;
      val = cout;
     }
   }  
  }
  (code + selectLabel)->code = selectCode;
  tabCode[selectCode] =  selectLabel;
 }

