/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_synth.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 : 28/01/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/
#include<stdio.h>
#include<math.h>
#include<fcntl.h>
#include MUT_H
#include LOG_H
#include"../beh104/beh104.h"
#include "syf_auto.h"
#include "syf_must.h"
#include "syf_beh2fsm.h"
#include "../util/util.h"
#include "../dc/dc.h"
extern int syf_scan ;
/*------------------------------------------------------------------------------
code2Abl		: remplit les ABL du champ code d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void code2Abl()
{
pCode code ;
chain_list *abl,*abl2 ;
int i, j ;

code = autoSys->code ;
for(i = 0; i < bit[autoSys->numberReg]; i++)
  {
  abl=createExpr(AND);
  for(j = 0; j < autoSys->numberReg; j++)
     {
     if ((code->code)&bit[j]) 
              addQExpr(abl,createAtom(nameI(CURENT_STATE,j)));
     else
              addQExpr(abl,notExpr(createAtom(nameI(CURENT_STATE,j))));
     }
  if(abl->NEXT->NEXT == NULL)
	{
	abl2 = abl ;
	abl = copyExpr(abl2->NEXT->DATA) ;
	freeExpr(abl2) ;
	}
  code->abl=abl;
  code++;
  }
/*displayCode(1) ;*/
}
/*------------------------------------------------------------------------------
trans2Abl		: remplit les ABL du champ state d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void trans2Abl()
{
pState state ;
pTrans trans ;
chain_list *abl ;
char *name ;
int i ;
 
state = autoSys->state ;

for(i = 0; i < autoSys->numberState; i++)
   {
   trans = state->trans ;
   if (!trans)
      {
        (autoSys->state+i)->abl = createAtom("'0'"); 
        /*printf("warning  ,l'etat '%s' est un etat source\n",state->name);*/
      }

   else if(trans->next == NULL)
	{
    if(trans->sPlabel !=-1)  
		{
      	name = nameSl((autoSys->state +trans->sPlabel)->name) ;
        (autoSys->state+i)->abl = createBinExpr(AND, createAtom(name), 
									copyExpr(trans->abl));
		}
        else 
        (autoSys->state+i)->abl = copyExpr(trans->abl); 
       		
	}
   else
	{
        (autoSys->state+i)->abl = createExpr(OR) ;
   	while(trans)
      	  {
        if(trans->sPlabel !=-1)  
			{
			name = nameSl((autoSys->state +trans->sPlabel)->name);  
      	        abl = createBinExpr(AND, createAtom(name),  
       		                 copyExpr(trans->abl));
			}
          else
                abl = copyExpr(trans->abl); 
      	  addQExpr((autoSys->state + i)->abl, abl) ;
      	  trans = trans->next ;
      	  }
   	} 
    state++ ;
   }
}
 
/*------------------------------------------------------------------------------
out2Abl			: remplit les ABL du champ out d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void out2Abl()
{
pState state ;
pLocOut locOut ;
pOut     out;
chain_list *abl ;
chain_list *abl1 ;
char *name ;
int i ;
 
out = autoSys->out ;

for(i = 0; i < autoSys->numberOut; i++)
	{
    if (out->abl == NULL)
		out->abl = createExpr(OR) ;
	if(syf_scan && !(strcmp(out->name,autoSys->scout)))
		{
		addQExpr(out->abl,createAtom(nameI(CURENT_STATE,
									autoSys->numberReg - 1)));
		}
	out++ ;
	}

state = autoSys->state ;

for(i = 0; i < autoSys->numberState; i++)
   {
   locOut = state->locOut ;
   while(locOut)
      {
	  name = nameSl(state->name);
      abl = createBinExpr(AND, createAtom(name), copyExpr(locOut->abl));
      addQExpr((autoSys->out + locOut->label)->abl, abl) ;
      locOut = locOut->next ;
      }
   state++ ;
   } 

out = autoSys->out; /* cas particulier de out = e_m : elimination de OR*/
for(i = 0; i < autoSys->numberOut; i++)
	{
	if((out->abl == 0) ||(out->abl->NEXT == NULL))
		{
		if(abl)
		abl1 = out->abl ;
		out->abl = createAtom("'0'") ;	
		freeExpr(abl1) ;
		}
	else if(out->abl->NEXT->NEXT == NULL)
		{
		abl1 = out->abl ;
		out->abl = copyExpr(abl1->NEXT->DATA) ;	
		freeExpr(abl1) ;
		}
	out++ ;
	}

out = autoSys->out; 
for(i = 0; i < autoSys->numberOut; i++)
	{
        abl = out->abl;
	out->abl = simplif10Expr(abl) ;
        freeExpr(abl);
	out++ ;
	}
}
   
/*------------------------------------------------------------------------------
ctrl2Abl                        : remplit les ABL du champ ctrl d' autoSys .
--------------------------------------------------------------
parametres              : rien .
--------------------------------------------------------------
return                  : rien .
------------------------------------------------------------------------------*/
void ctrl2Abl()
{
pStack stack ;
pState state ;
pCtrl     ctrl;
chain_list *abl ;
char *name ;
int i ;
 
ctrl = autoSys->inCtrl ;

	ctrl->name = ctrlName[0];
        ctrl->abl = notExpr(createBinExpr(OR,createAtom(ctrlName[1]),createAtom(ctrlName[2]))) ;
        ctrl->bdd = NULL ;
        ctrl++ ;
for(i = 1; i < NUMBERCTRL; i++)
        {
	ctrl->name = ctrlName[i];
        if (ctrl->abl == NULL)
        	ctrl->abl = createExpr(OR) ;
        ctrl->bdd = NULL ;
        ctrl++ ;
        }
 
stack = autoSys->stack ;

   while(stack)
      {
	  name = nameSl((autoSys->state + stack->curentStatelabel)->name);
      abl = createBinExpr(AND, createAtom(name), copyExpr(stack->abl));
      if(stack->ctrl == PUSH)
          addQExpr((autoSys->inCtrl + PUSH)->abl, abl) ;
      else if(stack->ctrl == POP)
          addQExpr((autoSys->inCtrl + POP)->abl, abl) ;
      stack = stack->next ;
       }


ctrl = autoSys->inCtrl+1 ;/* elimination de OR dans les cas particuliers*/
for(i = 1; i < NUMBERCTRL; i++)
        {
        if (ctrl->abl == NULL)
        	ctrl->abl = createAtom("'0'");
		else
			if(ctrl->abl->NEXT->NEXT == NULL)
				{
				abl = ctrl->abl ;
				ctrl->abl = copyExpr(abl->NEXT->DATA) ;	
				freeExpr(abl) ;
				}
        ctrl++ ;
        }
}
/*------------------------------------------------------------------------------
genRegD			: remplit les ABL du champ reg d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void genRegD()
{
chain_list *abl1 ;
chain_list *abl2 ;
pState state ;
pReg reg;
pCode code;
char *name ;
int i,j;

reg = autoSys->reg;
code = autoSys->code;

for(j=0; j < autoSys->numberReg; j++)
   {
   reg->name = nameI(CURENT_STATE,j);	/*enlever dans certains cas le OR */
   reg->abl = createExpr(OR);
   reg->cnd = copyExpr(autoSys->cndReg);
   reg++;
   }

state = autoSys->state;
for(i=0; i < autoSys->numberState; i++)
    { 
    reg = autoSys->reg;
    for(j=0; j < autoSys->numberReg; j++)
      {
      if ((code->code)&bit[j]) 
	  	{
		name = nameMa(state->name);
        addQExpr(reg->abl,createAtom(name));
		}
      reg++;
      }  
    state++;
    code++;
    }

reg = autoSys->reg;	/* cas particulier de y = ei_m : elimination de OR*/
for(i = 0;i < autoSys->numberReg; i++)
	{
	if((reg->abl == 0) ||(reg->abl->NEXT == NULL))
		{
		abl1 = reg->abl ;
		reg->abl = createAtom("'0'") ;	
		freeExpr(abl1) ;
		}
	else if(reg->abl->NEXT->NEXT == NULL)
		{
		abl1 = reg->abl ;
		reg->abl = copyExpr(abl1->NEXT->DATA) ;	
		freeExpr(abl1) ;
		}
	reg++ ;
	}

reg = autoSys->reg;
 if(autoSys->stack)
    for(j=0; j < autoSys->numberReg; j++)
      {
/******** ERREUR CORRIGEE : DANS LE CAS D'UN not(POP) ON REPREND LES 
TRANSITIONS NORMALES D'ETATS .et non pas dans le cas d'un NOP,+0 est remplace
par +2, et on ajoute un notExpr *************/
       abl1 =createBinExpr(AND,notExpr(createAtom((autoSys->inCtrl +2)->name)),reg->abl);
/******** ERREUR CORRIGEE : DANS LE CAS D'UN "POP" ON AFFECTE LES REG.
D'ETATS ET NON PAS "PUSH", +1 est remplace' par +2 ************************/
       abl2 = createBinExpr(AND,createAtom((autoSys->inCtrl +2)->name),
                                createAtom(nameI(STACK_NAME[0], j)));
       reg->abl = createBinExpr(OR,abl1,abl2);
      reg++;
      }  

/* Ajout de scan-path */
if(syf_scan)
	{
	reg = autoSys->reg;
	abl2 = createBinExpr(AND,createAtom(autoSys->scin),
							 createAtom(autoSys->testMode)) ;
	abl1 = createBinExpr(AND,copyExpr(reg->abl),
							notExpr(createAtom(autoSys->testMode))) ;
	freeExpr(reg->abl) ;
	reg->abl = createBinExpr(OR,copyExpr(abl1),copyExpr(abl2)) ;
	freeExpr(abl1) ;
	freeExpr(abl2) ;
	reg++ ;
	for(i = 1;i < autoSys->numberReg; i++)
		{
		abl2 = createBinExpr(AND,createAtom((reg - 1)->name),
								 createAtom(autoSys->testMode)) ;
		abl1 = createBinExpr(AND,copyExpr(reg->abl),
								notExpr(createAtom(autoSys->testMode))) ;
		freeExpr(reg->abl) ;
		reg->abl = createBinExpr(OR,copyExpr(abl1),copyExpr(abl2)) ;
		freeExpr(abl1) ;
		freeExpr(abl2) ;
		reg++ ;
		}
	}
}
/*------------------------------------------------------------------------------
genReg			: remplit les ABL du champ out d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void genReg()
{
chain_list *abl1 ;
chain_list *abl2 ;
pState state ;
pReg reg;
pCode code;
char *name ;
int i,j;

reg = autoSys->reg;

code = autoSys->code;

for(j=0; j < autoSys->numberReg; j++)
   {
   reg->name = nameI(NEXT_STATE,j);	/* enlever dans certains cas le OR */
   reg->abl = createExpr(OR);
   reg->cnd = notExpr(copyExpr(autoSys->cndReg));
   reg++;
   }
/****ATTENTION ****** Operation sur reg continue ne pas affecter reg */
for(j=0; j < autoSys->numberReg; j++)
   {
   reg->name = nameI(CURENT_STATE,j);
   reg->abl = createAtom(nameI(NEXT_STATE,j));
   reg->cnd = copyExpr(autoSys->cndReg);
   reg++;
   }
state = autoSys->state;
for(i=0; i < autoSys->numberState; i++)
    { 
    reg = autoSys->reg;
    for(j=0; j < autoSys->numberReg; j++)
      {
      if ((code->code)&bit[j]) 
		{
		name = nameMa(state->name);
        addQExpr(reg->abl,createAtom(name));
		}
      reg++;
      }  
    state++;
    code++;
    }

reg = autoSys->reg;	/* cas particulier de y = ei_m : elimination de OR*/
for(i = 0;i < autoSys->numberReg; i++)
	{
	if((reg->abl == 0) ||(reg->abl->NEXT == NULL))
		{
		abl1 = reg->abl ;
		reg->abl = createAtom("'0'") ;	
		freeExpr(abl1) ;
		}
	else if(reg->abl->NEXT->NEXT == NULL)
		{
		abl1 = reg->abl ;
		reg->abl = copyExpr(abl1->NEXT->DATA) ;	
		freeExpr(abl1) ;
		}
	reg++ ;
	}

    reg = autoSys->reg;
 if(autoSys->stack)
    for(j=0; j < autoSys->numberReg; j++)
      {
/******** ERREUR CORRIGEE : DANS LE CAS D'UN not(POP) ON REPREND LES 
TRANSITIONS NORMALES D'ETATS .et non pas dans le cas d'un NOP,+0 est remplace
par +2, et on ajoute un notExpr *************/
       abl1 =createBinExpr(AND,notExpr(createAtom((autoSys->inCtrl +2)->name)),reg->abl);
/******** ERREUR CORRIGEE : DANS LE CAS D'UN "POP" ON AFFECTE LES REG.
D'ETATS ET NON PAS "PUSH" +1 est remplace' par +2 ****************************/
       abl2 = createBinExpr(AND,createAtom((autoSys->inCtrl +2)->name),
                                createAtom(nameI(STACK_NAME[0], j)));
       reg->abl = createBinExpr(OR,abl1,abl2);
      reg++;
      }  

/* Ajout de scan-path */
if(syf_scan)
	{
	reg = autoSys->reg;
	abl2 = createBinExpr(AND,createAtom(autoSys->scin),
							 createAtom(autoSys->testMode)) ;
	abl1 = createBinExpr(AND,copyExpr(reg->abl),
							notExpr(createAtom(autoSys->testMode))) ;
	freeExpr(reg->abl) ;
	reg->abl = createBinExpr(OR,copyExpr(abl1),copyExpr(abl2)) ;
	freeExpr(abl1) ;
	freeExpr(abl2) ;
	reg++ ;
printf("ajout de scan\n") ;
	for(i = 1;i < autoSys->numberReg; i++)
		{
		abl2 = createBinExpr(AND,createAtom((reg+ autoSys->numberReg- 1)->name),
								 createAtom(autoSys->testMode)) ;
		abl1 = createBinExpr(AND,copyExpr(reg->abl),
								notExpr(createAtom(autoSys->testMode))) ;
		freeExpr(reg->abl) ;
		reg->abl = createBinExpr(OR,copyExpr(abl1),copyExpr(abl2)) ;
		freeExpr(abl1) ;
		freeExpr(abl2) ;
		reg++ ;
		}
	}

}
/*------------------------------------------------------------------------------
simplifAutoDc		: simplifie le circuit donne' par AUTOMAT en utilisant
			  les DON'T CAREs provenant des "codes" non utilises .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void simplifAutoDc()
{
pCode code ;
int i ;

if(autoSys->ablDc != NULL) 
 {
 code = autoSys->code ;
 for(i = 0; i < autoSys->numberState; i++)
   {
   code->abl = simplifDcAbl(code->abl,autoSys->ablDc) ;

   code++ ;
   }
 }
}
/*------------------------------------------------------------------------------
dc2abl			: remplit le champ ablDc d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void dc2abl()
{
pCode dc ;
int j ;

if(autoSys->numberState == NUMBER_CODE(autoSys->numberState)) 
    autoSys->ablDc = NULL ;
else
    {
    dc = autoSys->dc ;
    if(autoSys->numberState > NUMBER_CODE(autoSys->numberState) -2) 
          autoSys->ablDc = dc->abl ;
    else
       	 {
         autoSys->ablDc = createExpr(OR) ;
         for(j =autoSys->numberState; j < NUMBER_CODE(autoSys->numberState);j++)
    		{
    		addQExpr(autoSys->ablDc,dc->abl) ;
       		dc++ ;
		}
       	 }
      }
}
/*------------------------------------------------------------------------------
makeLocalBdd	: construit une structure Circuit et remplie les bdd des champs
				  locaux de FSM (pourle moment seulement trans->abl) et non pas 
				  out->abl . . . qui sont resultat de la synthese.
--------------------------------------------------------------
parametres		: .
--------------------------------------------------------------
return			: circuit .
------------------------------------------------------------------------------*/
pCircuit makeLocalBdd()
{
int i ;
pCircuit pC;
pState state ;
pTrans trans;
pOut out ;
pReg reg ;
char **name ;
char *Name ;
 
pC = initializeCct("cir",autoSys->numberIn + 2*autoSys->numberState,
			autoSys->numberOut + autoSys->numberState) ;
name = autoSys->input ;
while(*name)
        {
        addInputCct(pC,*name) ;
        name++ ;
        }
state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
		Name = nameSl(state->name) ;
        addInputCct(pC,Name) ;
		Name = nameMa(state->name) ;
        addInputCct(pC,Name) ;
        state++ ;
        }

state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
        trans = state->trans;
        while(trans)
           {
	   		trans->bdd = ablToBddCct(pC,trans->abl) ;
           trans = trans->next;
           }
        state++ ;
	}
return(pC) ;
}
/*------------------------------------------------------------------------------
rempliBddAuto		: remplit les champs bdd des structures d'automat .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
pCircuit rempliBddAuto()
{
int i ;
pCircuit pC;
pState state ;
pTrans trans;
pOut out ;
pReg reg ;
char **name ;
char *Name ;
 
 /*initializeBdd(2) ;*/
pC = initializeCct("cir",autoSys->numberIn + 2*autoSys->numberState,
			autoSys->numberOut + autoSys->numberState) ;
name = autoSys->input ;
while(*name)
        {
        addInputCct(pC,*name) ;
        name++ ;
        }
state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
		Name = nameSl(state->name) ;
        addInputCct(pC,Name) ;
		Name = nameMa(state->name) ;
        addInputCct(pC,Name) ;
        state++ ;
        }

out = autoSys->out ;
for(i = 0; i < autoSys->numberOut; i++)
	{
	displayExpr(out->abl) ;
	fflush(stdout) ;
    out->bdd = ablToBddCct(pC,out->abl) ;
	out++ ;
	}

state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
        trans = state->trans;
        while(trans)
           {
	   trans->bdd = ablToBddCct(pC,trans->abl) ;
           trans = trans->next;
           }
        state++ ;
	}
state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
	state->bdd = ablToBddCct(pC,state->abl) ;
	state++ ;
	}
return(pC) ;
}
/*------------------------------------------------------------------------------
rempliBddAutoReg	: remplit les champs bdd de structure automat .
--------------------------------------------------------------
parametres		: pC .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void rempliBddAutoReg(pC)
pCircuit pC;
{
int i ;
pState state ;
pOut out ;
pReg reg ;
char **name ;
char *Name ;
 
state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
        {
		Name = nameSl(state->name) ;
        addInputCct(pC,Name) ;
		Name = nameMa(state->name) ;
        addInputCct(pC,Name) ;
        state++ ;
        }

reg = autoSys->reg ;
for(i = 0; i < (autoSys->numberReg); i++)
	{
    reg->bdd = ablToBddCct(pC,reg->abl) ;
	freeExpr(reg->abl) ;
    reg->abl = bddToAblCct(pC,reg->bdd) ;
	reg++ ;
	}
reg = autoSys->inStack[0] ;
if(flagPile)
  for(i = 0; i < (autoSys->numberReg)*autoSys->sizeStack; i++)
	{
	if(reg->abl != NULL)
		{
    	reg->bdd = ablToBddCct(pC,reg->abl) ;
		freeExpr(reg->abl) ;
    	reg->abl = bddToAblCct(pC,reg->bdd) ;
		}
	reg++ ;
	}
}
/*------------------------------------------------------------------------------
destroyAuxAuto		: elimine les variables auxiliaires dans :
			autoSys->out et autoSys->reg .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void destroyAuxAuto()
{
pOut out ;
pReg reg ;
int i, j, numReg ;
char *name ;

if(autoSys->typeReg == REG_D)
	numReg = autoSys->numberReg ;
else
	numReg = 2 * autoSys->numberReg ;

for(j = 0; j < autoSys->numberState; j++)
	{
	out = autoSys->out ;
	reg = autoSys->reg ;
	for(i = 0; i < autoSys->numberOut; i++)
		{
		if(out->name != NULL && out->abl != NULL)
			{
			if(ATOM(out->abl))
			   {
			   /*printf("out \n") ;
			   displayExpr(out->abl) ;
			   fflush(stdout) ;*/
			   freeExpr(out->abl) ;
			   out->abl = copyExpr((autoSys->code + j)->abl) ;
			   }
			else
			   {
			   name = nameSl((autoSys->state+j)->name);
			   substPhyExpr(out->abl,name,(autoSys->code + j)->abl) ;
			   }
			}
		out++ ;
		}
	for(i = 0; i < numReg; i++)
		{
		if(ATOM(reg->abl))
		   {
		   freeExpr(reg->abl) ;
		   reg->abl = copyExpr((autoSys->state + j)->abl) ;
		   }
		else
		   {
		   /*printf("reg : %s\n",reg->name) ;
		   displayExpr(reg->abl) ;*/
		   name = nameMa((autoSys->state+j)->name);
		   substPhyExpr(reg->abl,name, (autoSys->state + j)->abl) ;
		   }
		reg++ ;
		}
	}
for(j = 0; j < autoSys->numberState; j++)
	{
	reg = autoSys->reg ;
	for(i = 0; i < numReg; i++)
		{
		if(ATOM(reg->abl))
		   {
		   freeExpr(reg->abl) ;
		   reg->abl = copyExpr((autoSys->code + j)->abl) ;
		   }
		else
		   {
		   name = nameSl((autoSys->state+j)->name);
		   substPhyExpr(reg->abl,name,(autoSys->code + j)->abl) ;
		   }
		reg++ ;
		}
	}
if(flagPile)
  for(j = 0; j < autoSys->sizeStack * autoSys->numberReg; j++)
	{
	reg = autoSys->inStack[0] ;
	for(i = 0; i < numReg; i++)
		{
		   name = nameSl((autoSys->state+j)->name);
		substPhyExpr(reg->abl,name, (autoSys->code + j)->abl) ;
		}
	reg++ ;
	}
}
/*------------------------------------------------------------------------------
simplifDcAutoBeh	: effectue une simplification sur les champs bdd de 
			  befig en utilisant les DC des codes non utilises .
--------------------------------------------------------------
parametres		: befig .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void simplifDcAutoBeh(beh)
struct syf_befig *beh ;
{
pNode bdd,bddDc ;
struct syf_bereg *reg ;
struct syf_beout *out ;
int i ;

bddDc = searchOutputCct(beh->CIRCUI,"dc") ;
if(bddDc == NULL)
	{
	printf("bddDc n'existe pas dans le circuit, utiliser la fonction\n");
	printf("	rempliOutCctAuto	\n") ;
	exit(-1) ;
	}

	/* les registres */

i = 0 ;
reg = beh->BEREG ;
while(reg)
     {
	 /* Garbage entraine une destruction des ABLs de CIRCUI(Error)
		en attendant la fonction n'est pas utile. 
     i++ ;
     if(i == 10)
  	{
	i = 0;
	printf("APPEL GC num node = %d\n",numberNodeAllBdd()) ;
printf("Avant Garbage\n") ;
displayCct(beh->CIRCUI,1) ;
	syf_syf_gcNodeBeh(beh) ;
printf("Apres Garbage\n") ;
displayCct(beh->CIRCUI,1) ;
	bddDc = ablToBddCct(beh->CIRCUI,autoSys->ablDc) ;
	printf("FIN GC num node = %d\n",numberNodeAllBdd()) ;
	}
	*/
     bdd = reg->BINODE->VALNODE ;
     printf("********* simplifDc **********\n") ;
     printf("nbre de noeud total = %d\n",numberNodeBdd(bdd)) ;
     /*for(i = 0; i < autoSys->numberReg; i++)
	{
	upVarCct(beh->CIRCUI,createNodeTermBdd(
		searchInputCct(beh->CIRCUI,nameI(CURENT_STATE,i))),
						 beh->CIRCUI->countI+i) ;
	bdd= simplifDcZeroBdd(bdd,bddDc);
        printf("    nbre de noeud initermediaire : %d => %d\n",i,numberNodeBdd(bdd)) ;
	} */
	 bdd = simplifDc(bdd,bddDc) ;
     printf("nbre de noeud reduit = %d\n",numberNodeBdd(bdd)) ;
     reg->BINODE->VALNODE = bdd ;
     freeExpr(reg->BIABL->VALABL) ;
     reg->BIABL->VALABL = bddToAblCct(beh->CIRCUI,reg->BINODE->VALNODE) ;
     reg->BINODE->VALNODE = NULL ;
     reg = reg->NEXT ;
     }
	/* les signaux output */

out = beh->BEOUT ;
while(out)
     {
     bdd = out->NODE ;
     printf("********* simplifDc **********\n") ;
     printf("nbre de noeud total = %d\n",numberNodeBdd(bdd)) ;
    /* for(i = 0; i < autoSys->numberReg; i++)
	{
	upVarCct(beh->CIRCUI,createNodeTermBdd(
		searchInputCct(beh->CIRCUI,nameI(CURENT_STATE,i))),
						 beh->CIRCUI->countI+i) ;
	bdd= simplifDcZeroBdd(bdd,bddDc);
	}*/
	bdd= simplifDc(bdd,bddDc);
     printf("nbre de noeud reduit = %d\n",numberNodeBdd(bdd)) ;
     /*out->NODE = simplifDc(bdd,bddDc) ;*/
     freeExpr(out->ABL) ;
     out->ABL = bddToAblCct(beh->CIRCUI,out->NODE) ;
     out->NODE = NULL ;
     out = out->NEXT ;
     }
  
	/* elimination des signaux auxiliaires de beh */

/*syf_beh_frebeaux(beh->BEAUX) ; */
/*beh->BEAUX = NULL ;*/ /***** Tenir compte de la pile et ajouter ca ******/
}
/*------------------------------------------------------------------------------
syf_syf_gcNodeBeh		: effectue un garbage collecteur sur le befig . 
--------------------------------------------------------------
parametres		: befig .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void syf_syf_gcNodeBeh(beh)
struct syf_befig *beh ;
{
chain_list *tabNode ;
syf_beaux_list *aux ;
syf_bereg_list *reg ;
syf_beout_list *out ;

tabNode = NULL ;
aux = beh->BEAUX ;
while(aux)
   {
   tabNode = addchain(tabNode,aux->NODE) ;
   aux = aux->NEXT ;
   }

reg = beh->BEREG ;
while(reg)
   {
   if(reg->BINODE->VALNODE != NULL)
         tabNode = addchain(tabNode,reg->BINODE->VALNODE) ;
   tabNode = addchain(tabNode,reg->BINODE->CNDNODE) ;
   reg = reg->NEXT ;
   }

out = beh->BEOUT ;
while(out)
   {
   if(out->NODE != NULL)
   	tabNode = addchain(tabNode,out->NODE) ;
   out = out->NEXT ;
   }

gcNodeBdd(tabNode) ;
tabNode = invChainList(tabNode) ;

aux = beh->BEAUX ;
while(aux)
   {
   aux->NODE = (pNode)tabNode->DATA ;
   tabNode = tabNode->NEXT ;
   aux = aux->NEXT ;
   }

reg = beh->BEREG ;
while(reg)
   {
   if(reg->BINODE->VALNODE != NULL)
	{
   	reg->BINODE->VALNODE = (pNode)tabNode->DATA ;
   	tabNode = tabNode->NEXT ;
	}
   reg->BINODE->CNDNODE = (pNode)tabNode->DATA ;
   tabNode = tabNode->NEXT ;
   reg = reg->NEXT ;
   }

out = beh->BEOUT ; /* L'ordre est tres important */
while(out)
   {
   if(out->NODE != NULL)
	{
   	out->NODE = (pNode)tabNode->DATA ;
   	tabNode = tabNode->NEXT ;
	}
   out = out->NEXT ;
   }

}
/*------------------------------------------------------------------------------
invChainList		: renverse l'ordre dans une chain_list * . 
--------------------------------------------------------------
parametres		: chain .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
chain_list *invChainList(chain)
chain_list *chain ;
{
chain_list *newChain ;

newChain = NULL ;
while(chain)
	{
	newChain = addchain(newChain,chain->DATA) ;
	chain = chain->NEXT ;
	}
return(newChain) ;
}
/*------------------------------------------------------------------------------
rempliOutCctAuto	: ajout les sorties du circuit(seulement 
		       	 les registres et les sorties et la fonction de DC) .
--------------------------------------------------------------
parametres		: pC .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
rempliOutCctAuto(pC)
pCircuit *pC ;
{
pState state ;
pReg reg ;
pOut out ;
char *Name ;
int i ;

state = autoSys->state ;
for(i = 0; i < autoSys->numberState; i++)
      { /* Ne doit pas etre mis dans createCir car syf_makeBddBeh() 
	  garderait  %s_s comme var intermediaire */
	  Name = nameSl(state->name) ;
      addInputCct(pC,Name) ;
	  Name = nameMa(state->name) ;
      addInputCct(pC,Name) ;
      state++ ;
      }

addOutputCct(pC,"dc",ablToBddCct(pC,autoSys->ablDc)) ;
reg = autoSys->reg ;
for(i = 0; i < autoSys->numberReg; i++)
	{
	/*printf("Les registres \n") ;
	displayBdd(reg->bdd,1) ;*/
	addOutputCct(pC,reg->name,reg->bdd) ;
	reg++ ;
	}
out = autoSys->out ;
for(i = 0; i < autoSys->numberOut; i++)
	{
	addOutputCct(pC,out->name,out->bdd) ;
	/*printf("Les outputs\n") ;
	displayBdd(out->bdd,1) ;*/
	/*displayExpr(bddToAbl(pC,out->bdd)) ;*/
	out++ ;
	}

/*displayCct(pC,1) ;*/
}
/*------------------------------------------------------------------------------
completStackForMS	: complete les registres de pile (inStack) en ajoutant
					  les slaves.*** Afin de garder les noms transparents
					  pour les autres fonctions, on donne les noms generes
					  par genRegD au esclave(qui seront consideres comme sortie
					  de stack), et on precede ce nom de 'm' pour les maitre
					  qui sont generes par genRegD. met a jour aussi l'horloge.
					  on inverse le ck pour esclaves.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void completStackForMS()
{
int i, num;
pReg stack1, stack2 ;
char name[30] ;

if(autoSys->stackNumBit != 0)
	{
	num = (autoSys->numberReg) * autoSys->sizeStack ;

	stack1 = autoSys->inStack[0] ;
	stack2 = autoSys->inStack[0] + num ;
	for(i = 0; i<num; i++)
		{
		if(stack1->abl != NULL) /* voir si il etait mis a NULL auparavant*/
			{
			stack2->name = namealloc(stack1->name);
			/*** changement de nom des maitres ****/
			sprintf(name,"m%s",stack1->name);	
			stack1->name = namealloc(name);	
			/*** nom des esclaves meme que le nom des regD ****/
			stack2->abl = createAtom(namealloc(stack1->name));
			stack2->cnd = copyExpr(stack1->cnd) ;
			stack1->cnd = notExpr(stack1->cnd);/* inverse le ck pour maitre */
			stack2->bdd = NULL;
			}
		stack1++ ;
		stack2++ ;
		}
	}
}
/*------------------------------------------------------------------------------
genStackD			: remplit les ABL du champ out d' autoSys .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void genStackD()
{
int i ;

if(autoSys->stackNumBit == 0)
	genFix() ;
else
	{
	if(syf_trace)
		printf("initializeInStackInFix\n") ;
	initializeInStackInFix() ;
	if(syf_trace)
		printf("genInStack0Push\n") ;
	genInStack0Push() ;
	if(syf_trace)
		printf("completInStack0InFix\n") ;
	completInStack0InFix() ;
	if(syf_trace)
		printf("completAllStack\n") ;
	completAllStack() ;
	if(syf_trace)
		printf("erasefix\n") ;
	eraseFix() ;

	if(syf_trace)
		{
		printf("*********** inStack structure *********\n") ;
		displayReg(autoSys->inStack[0],1) ;
		fflush(stdout) ;
		}
	}
}
/*------------------------------------------------------------------------------
genFix			: dans le cas ou il y a un seul etat a empiler, on ne genere
				  que des inFixStack.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
genFix()
{
int i ;
pOut inFixStack ;

autoSys->inFixStack = (pSignal) mbkalloc((autoSys->numberReg) * sizeof(struct output)) ;

inFixStack = autoSys->inFixStack ;
for(i = 0; i < autoSys->numberReg; i++)
	{
	inFixStack->name = nameI(STACK_NAME[0],i);
   	if(autoSys->stackFixCode&bit[i])
		inFixStack->abl = createAtom("'1'");
    else
        inFixStack->abl = createAtom("'0'");
    inFixStack->bdd = NULL;
    inFixStack++;
	}
}
/*------------------------------------------------------------------------------
initializeInstackInFix	: initialize les structures inStack, et inFixStack .
						  ex: profondeur pile : 3; nb reg etat: 2 .
		inStack :
					0	2	4
					1	3	5

					0 = inStack_0_0
					1 = inStack_0_1
					2 = inStack_1_0
					3 = inStack_1_1
					4 = inStack_2_0
					5 = inStack_2_1
taille d'allocation : autoSys->numberReg * autoSys->numStack.

		inFixStack:
					0
					1
taille d'allocation : autoSys->numberReg
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
initializeInStackInFix()
{
pReg oneStack;
pCode code;
char name[30] ;
int j, numberReg ;

	/*printf("initialize\n") ;
	displayStack() ;*/

if(autoSys->typeReg == REG_D)
	numberReg = autoSys->numberReg ;
else
	numberReg = 2 * autoSys->numberReg ;

/***** ATTENTION : autoSys->inStack est *pReg, mais ici juste inStack[0] 
contient tous les reg. pour stack instack[1] . . . Ne sont pas utilise'
ce n'est pas le cas dans le cas de genStack(bascule M/S) le changer aussi
de meme que l'allocation dans initializeAuto *******/
code = autoSys->code;
autoSys->inStack[0]  = (pReg)mbkalloc(numberReg * autoSys->sizeStack * sizeof(struct Sregister)) ;
oneStack = autoSys->inStack[0] ;
for(j = 0; j < autoSys->sizeStack * numberReg; j++)
	{
	oneStack->name = NULL ;
	oneStack->abl = NULL ;
	oneStack->cnd = NULL ;
	oneStack++ ;
	}

autoSys->inFixStack = (pSignal) mbkalloc((autoSys->numberReg) * sizeof(struct output)) ;

oneStack = autoSys->inStack[0];
   for(j=0; j < numberReg; j++)
   {
   sprintf(name,"%s_%d",STACK_NAME[0],j);	
   oneStack->name = namealloc(name);	
   oneStack->abl = createExpr(OR);
   oneStack->cnd = copyExpr(autoSys->cndReg);
   oneStack->bdd = NULL;
   oneStack++;
   }
	/*printf("fin initialize\n") ;
	displayStack() ;
	for(j = 0; j < 25; j++) 
	printf("\n") ;*/
}
/*------------------------------------------------------------------------------
genInStack0Puch	: genere les inStack_0_i, seulement le cas ou on a un push.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
genInStack0Push()
{
chain_list *abl1 ;
pStack stack ;
pReg oneStack;
char *name ;
int j;

stack = autoSys->stack ;

   while(stack)
      {
oneStack = autoSys->inStack[0];
        if(stack->ctrl == PUSH)
        {
		   name = nameSl((autoSys->state +stack->curentStatelabel)->name);
           abl1 = createBinExpr(AND, createAtom(name), copyExpr(stack->abl));
          for(j=0; j < autoSys->numberReg; j++)
          {
            if (((autoSys->code + stack->returnStatelabel)->code)&bit[j])
                    addQExpr(oneStack->abl,copyExpr(abl1));
			oneStack++ ;
          }
	 freeExpr(abl1);
        }
       stack = stack->next ;
      }

oneStack = autoSys->inStack[0];
for(j=0; j < autoSys->numberReg; j++)
	{
	if((oneStack->abl == NULL) ||(oneStack->abl->NEXT == NULL))
		{
		abl1 = oneStack->abl ;
		oneStack->abl = createAtom("'0'") ;	
		}
	else if(oneStack->abl->NEXT->NEXT == NULL)
		{
		abl1 = oneStack->abl ;
		oneStack->abl = copyExpr(abl1->NEXT->DATA) ;	
		freeExpr(abl1) ;
		}
	oneStack++ ;
	}
}
/*------------------------------------------------------------------------------
completInStack0InFix : complete les inStack_0_i, en ajoutant les cas pop et nop.
					   Et remplit les inFixStack.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
completInStack0InFix()
{
pReg oneStack ;
pOut inFixStack ;
int j ;
chain_list *abl1,*abl2,*abl3 ;

oneStack = autoSys->inStack[0];
inFixStack = autoSys->inFixStack ;
if(autoSys->sizeStack ==1)
	{
    for(j=0;j<autoSys->numberReg;j++)
      {
       if(autoSys->stackCodeMask&bit[j])
          {
       abl1= createBinExpr(AND,createAtom(ctrlName[1]),copyExpr(oneStack->abl));
       abl2 = createBinExpr(AND, notExpr(createAtom(ctrlName[1])),
                              createAtom(nameI(STACK_NAME[0], j)));
           oneStack->abl = createBinExpr(OR,abl1,abl2);
		  }
		else
    	  {
    		inFixStack->name = nameI(STACK_NAME[0],j);
    		if(autoSys->stackFixCode&bit[j])
				inFixStack->abl = createAtom("'1'");
    		 else
        		inFixStack->abl = createAtom("'0'");
    		inFixStack->bdd = NULL;
    	   }
      inFixStack++;
	  oneStack++ ;
      }
	}
else
	{
    for(j=0;j<autoSys->numberReg;j++)
      {
       if(autoSys->stackCodeMask&bit[j])
        {
        abl1 = createBinExpr(AND,createAtom(ctrlName[1]),copyExpr(oneStack->abl));
        abl2 = createBinExpr(AND, createAtom(ctrlName[0]),
                         createAtom(nameI(STACK_NAME[0], j)));
         abl3 = createBinExpr(AND,createAtom(ctrlName[2]),
                                  createAtom(nameI(STACK_NAME[1], j)));
         oneStack->abl = createExpr(OR);
         addQExpr(oneStack->abl, abl1);
         addQExpr(oneStack->abl, abl2);
         addQExpr(oneStack->abl, abl3);
		 }
	   else
        {
    	inFixStack->name = nameI(STACK_NAME[0],j);
    	if(autoSys->stackFixCode&bit[j])
			inFixStack->abl = createAtom("'1'");
      	else
        	inFixStack->abl = createAtom("'0'");
      	inFixStack->bdd = NULL;
    	}
      inFixStack++;
	oneStack++ ;
  	 }
   }
/*printf("FIN inStack0In\n") ;
displayMask() ;*/
}
/*------------------------------------------------------------------------------
completAllStack : complete les inStack_i_j, avec (i != 0).
					   Et remplit les inFixStack.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
completAllStack()
{
chain_list *abl1 ;
chain_list *abl2 ;
chain_list *abl3 ;
chain_list *st ;
pStack stack ;
char name[30] ;
pReg oneStack ;
pOut inFixStack ;
int i,j,k;

oneStack = autoSys->inStack[0] + autoSys->numberReg;
for(i=1; i<autoSys->sizeStack-1;i++)
  {
	/*oneStack = autoSys->inStack[i];*/
     for(j=0; j < autoSys->numberReg; j++)
     {
	 /*for(k = 0; k < 3; k++)
		printf("trl[%d] = %s\n",k,ctrlName[k]) ;
		printf("nameI[%d] = %s\n",i,nameI(STACK_NAME[i+1],j)) ;
		fflush(stdout) ;*/
       sprintf(name,"%s_%d",STACK_NAME[i],j);
       oneStack->name = namealloc(name);
                       st =  createAtom(nameI(STACK_NAME[i-1], j));
        abl1 = createBinExpr(AND,createAtom(namealloc(ctrlName[1])),st) ;
        abl2 = createBinExpr(AND, createAtom(ctrlName[0]),
                         createAtom(nameI(STACK_NAME[i], j)));
                       st =  createAtom(nameI(STACK_NAME[i+1], j));
         abl3 = createBinExpr(AND,createAtom(ctrlName[2]),st) ;
         oneStack->abl = createExpr(OR);
         addQExpr(oneStack->abl, abl1);
         addQExpr(oneStack->abl, abl2);
         addQExpr(oneStack->abl, abl3);
       oneStack->cnd = copyExpr(autoSys->cndReg);
       oneStack->bdd = NULL;
       oneStack++;
     }
  }
if(autoSys->sizeStack < 2)
   {
   printf("ERREUR:pile de profondeur 1,traitement suivant doit etre arrete\n");
   exit(-1) ;
   }
/*if(i > 1)
	oneStack = autoSys->inStack[i];*/
for(j=0; j < autoSys->numberReg; j++)
   {
   sprintf(name,"%s_%d",STACK_NAME[i],j);
   oneStack->name = namealloc(name);
   abl1 = createBinExpr(AND,createAtom(ctrlName[1]),
                       createAtom(nameI(STACK_NAME[i-1], j)));
   abl2 = createBinExpr(AND, notExpr(createAtom(ctrlName[1])),
                        createAtom(nameI(STACK_NAME[i], j)));
   oneStack->abl = createBinExpr(OR,abl1,abl2);
   oneStack->cnd = copyExpr(autoSys->cndReg);
   oneStack->bdd = NULL;
   /*displayExpr(oneStack->abl) ;	
   printf("rang : %d,adr : %d\n",oneStack - autoSys->inStack[0],oneStack) ;
	displayReg(autoSys->inStack[0],1) ;*/

   oneStack++;
}
/*oneStack = autoSys->inStack[0] ;
	displayReg(oneStack,1) ;*/
}
/*------------------------------------------------------------------------------
eraseFix 	: elimine les inStack_i_j/ infix_i_j = 1 ou 0 ..
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
eraseFix()
{
pOut inFixStack ;
pReg oneStack ;
int i, j ;

inFixStack = autoSys->inFixStack ;

for(i = 0; i < autoSys->numberReg; i++)
	{
	oneStack = autoSys->inStack[0] + i ;
	if(!(autoSys->stackCodeMask&bit[i]))
		for(j = 0; j < autoSys->sizeStack; j++)
			{
			if(oneStack != NULL)
				{
				freeExpr(oneStack->abl) ;
				oneStack->abl = NULL ;
				oneStack = oneStack + autoSys->numberReg ;
				}
			}
	else
		(inFixStack + i)->abl = NULL ;
	}
}
/*---------------------------------------------------------------------------
nameI : genere un nom, a partire d'un chaine d caractere et un int.
-----------------------------------------
parametres : char *name, int index .
-----------------------------------------
return : nouvelle chaine.
---------------------------------------------------------------------------*/
char *nameI(name,index)
char *name ;
int index ;
{
char *newName ;
char nName[30] ;

sprintf(nName,"%s_%d",name,index) ;
newName = namealloc(nName) ;
return(newName) ;
}
/*-----------------------------------------------------------------------------
genRegOutD		: remplit les ABL du champ regOut de abl, bascule D .
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void genRegOutD()
{
pStack stack ;
chain_list *abl,*savAbl,*listRetState ;
chain_list *stateCodExprForStack(), *addLab();
chain_list *list,*newList,*newListCur ;
pLocOut locOut ;
pState state ;
pReg reg;
char name[50] ;
char *name2 ;
int i,num;

reg = autoSys->regOut;
for(i = 0; i < autoSys->numberOut; i++)
	{
    if (reg->abl == NULL)
		{
   		sprintf(name,"s%s",namealloc((autoSys->out+i)->name));
   		reg->name = namealloc(name);
   		reg->cnd = copyExpr(autoSys->cndReg);
		reg->abl = createExpr(OR) ;
		}
	reg++ ;
	}

state = autoSys->state ;

for(i = 0; i < autoSys->numberState; i++)
   {
   locOut = state->locOut ;
   while(locOut)
      {
	  name2 = nameMa(state->name);
      abl = createAtom(name2);
      addQExpr((autoSys->regOut + locOut->label)->abl, abl) ;
      locOut = locOut->next ;
      }
   state++ ;
   } 

/******** Si automate a pile ajouter les etats de la pile ********/
if(flagPile)
	{
	stack = autoSys->stack ;
	listRetState = NULL ;
	num = 0;
	while(stack) /*list de ts les etats de la pile */
		{
		if(stack->ctrl == PUSH)
			listRetState = addLab(listRetState,stack->returnStatelabel,&num) ;
		stack = stack->next ;
		}

	reg = autoSys->regOut ;
	for(i = 0; i < autoSys->numberOut; i++) /*Pour chaque sortie */
		{
		list = listRetState ;
		newList = NULL ;
		while(list)/* list de ts les etats de la pile qui ont out = 1 */
			{
			state = autoSys->state + (int)(list->DATA) ;
			name2 = nameMa(state->name) ;
			if(searchExpr(reg->abl,name2))
				newList = addchain(newList,list->DATA) ;
			list = list->NEXT ;
			}

		newListCur = newList ;
		abl = createExpr(OR) ;
		while(newListCur) /* ajout dans regOut */
			{
			addQExpr(abl,stateCodExprForStack(newListCur->DATA)) ;
			newListCur = newListCur->NEXT ;
			}
		if(newList)
			{
			if(abl->NEXT->NEXT == NULL)
				{
				savAbl = abl ;
				abl = copyExpr(abl->NEXT->DATA) ;
				freeExpr(savAbl) ;
				}
			savAbl = createBinExpr(AND,copyExpr(abl),createAtom(namealloc(ctrlName[2])));
			freeExpr(abl) ;
			abl = reg->abl ;
			reg->abl = createBinExpr(OR,copyExpr(reg->abl),copyExpr(savAbl)) ; 
			freeExpr(abl) ;
			freeExpr(savAbl) ;
			}
		reg++ ;
		}
	}

reg = autoSys->regOut; /* cas particulier de regOut = e_m : elimination de OR*/
for(i = 0; i < autoSys->numberOut; i++)
	{
	if((reg->abl == 0) ||(reg->abl->NEXT == NULL))
		{
		abl = reg->abl ;
		reg->abl = createAtom("'0'") ;	
		freeExpr(abl) ;
		}
	else 
	  if(reg->abl->NEXT->NEXT == NULL)
		{
		abl = reg->abl ;
		reg->abl = copyExpr(abl->NEXT->DATA) ;	
		freeExpr(abl) ;
		}
	reg++ ;
	}

reg = autoSys->regOut; 
for(i = 0; i < autoSys->numberOut; i++)
	{
	if((!syf_scan) || strcmp(autoSys->scout,reg->name + 1))
		{
    	abl = reg->abl;
		reg->abl = simplif10Expr(abl) ;
    	freeExpr(abl);
		}
	else
		{
		freeExpr(reg->abl) ;
		reg->name = NULL ;
		}
	reg++ ;
	}
}
/*-----------------------------------------------------------------------------
genRegOut		: remplit les ABL du champ regOut de abl registres M/S.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void genRegOut()
{
pStack stack ;
chain_list *abl,*savAbl,*listRetState ;
chain_list *stateCodExprForStack(),*addLab();
chain_list *list,*newList,*newListCur ;
pLocOut locOut ;
pState state ;
pReg reg;
char name[50] ;
char *name2 ;
int i,num;

reg = autoSys->regOut;

for(i = 0; i < autoSys->numberOut; i++)
	{
    if (reg->abl == NULL)
		{
   		sprintf(name,"m%s",namealloc((autoSys->out + i)->name));
   		reg->name = namealloc(name);
		reg->abl = createExpr(OR) ;
   		reg->cnd = notExpr(copyExpr(autoSys->cndReg));
		}
	reg++ ;
	}

for(i=0; i < autoSys->numberOut; i++)
   {
   sprintf(name,"s%s",namealloc((autoSys->out + i)->name));
   reg->name =  namealloc(name);
   sprintf(name,"m%s",namealloc((autoSys->out + i)->name));
   reg->abl =createAtom(name);
   reg->cnd = copyExpr(autoSys->cndReg);
   reg++;
   }


state = autoSys->state ;

for(i = 0; i < autoSys->numberState; i++)
   {
   locOut = state->locOut ;
   while(locOut)
      {
	  name2 = nameMa(state->name);
      abl = createAtom(name2) ;
      addQExpr((autoSys->regOut + locOut->label)->abl, abl) ;
      locOut = locOut->next ;
      }
   state++ ;
   } 

/******** Si automate a pile ajouter les etats de la pile ********/
if(flagPile)
	{
	stack = autoSys->stack ;
	listRetState = NULL ;
	while(stack) /*list de ts les etats de la pile */
		{
		if(stack->ctrl == PUSH)
			listRetState = addchain(listRetState,stack->returnStatelabel) ;
		stack = stack->next ;
		}

	reg = autoSys->regOut ;
	for(i = 0; i < autoSys->numberOut; i++) /*Pour chaque sortie */
		{
		list = listRetState ;
		newList = NULL ;
		num = 0 ;
		while(list)/* list de ts les etats de la pile qui ont out = 1 */
			{
			state = autoSys->state + (int)(list->DATA) ;
			name2 = nameMa(state->name);
			if(searchExpr(reg->abl,name2))
				newList = addLab(newList,list->DATA,&num) ;
			list = list->NEXT ;
			}

		newListCur = newList ;
		abl = createExpr(OR) ;
		while(newListCur) /* ajout dans regOut */
			{
			addQExpr(abl,stateCodExprForStack(newListCur->DATA)) ;
			newListCur = newListCur->NEXT ;
			}
		if(newList)
			{
			if(abl->NEXT->NEXT == NULL)
				{
				savAbl = abl ;
				abl = copyExpr(abl->NEXT->DATA) ;
				freeExpr(savAbl) ;
				}
			savAbl = createBinExpr(AND,copyExpr(abl),createAtom(namealloc(ctrlName[2])));
			freeExpr(abl) ;
			abl = reg->abl ;
			reg->abl = createBinExpr(OR,copyExpr(reg->abl),copyExpr(savAbl)) ; 
			freeExpr(abl) ;
			freeExpr(savAbl) ;
			}
		reg++ ;
		}
	}

reg = autoSys->regOut; /* cas particulier de regOut = e_m : elimination de OR*/
for(i = 0; i < autoSys->numberOut; i++)
	{
	if((reg->abl == 0) ||(reg->abl->NEXT == NULL))
		{
		abl = reg->abl ;
		reg->abl = createAtom("'0'") ;	
		freeExpr(abl) ;
		}
	else 
	  if(reg->abl->NEXT->NEXT == NULL)
		{
		abl = reg->abl ;
		reg->abl = copyExpr(abl->NEXT->DATA) ;	
		freeExpr(abl) ;
		}
	reg++ ;
	}

reg = autoSys->regOut; 
for(i = 0; i < autoSys->numberOut; i++)
	{
	if((!syf_scan) || strcmp(autoSys->scout,reg->name+1))
		{
    	abl = reg->abl;
		reg->abl = simplif10Expr(abl) ;
    	freeExpr(abl);
		}
	else
		{
		freeExpr(reg->abl) ;
		reg->abl = NULL ;
		reg->name = NULL ;
    	freeExpr((reg + autoSys->numberReg)->abl) ;
		(reg + autoSys->numberReg)->abl = NULL ;
		(reg + autoSys->numberReg)->name = NULL ;
		}
	reg++ ;
	}
}
/*-----------------------------------------------------------------------------
synthOut		: synthetise les sorties de l'automate dans le cas particulier
				  ou on demande les sorties sortant de registres. Cette fonction
				  doit etre apele' apres la fonction genRegOutD ou genRegOut.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void synthOut()
{
pOut     out;
char name[30] ;
int i ;
 
out = autoSys->out ;

for(i = 0; i < autoSys->numberOut; i++)
	{
	if(!syf_scan || strcmp(out->name,autoSys->scout))
		{
		sprintf(name,"s%s",out->name) ;
		out->abl = createAtom(namealloc(name)) ;
		}
	else
		out->abl = createAtom(nameI(CURENT_STATE,autoSys->numberReg-1));
	out++ ;
	}
}
/*-----------------------------------------------------------------------------
stateCodExprForStack	: Genere un abl a partir du code de l'etat dont le label
						  est passe en parametre, utilise les noms de STACK.
						  Cette fonction ne peut etre appelee qu'apres le codage
--------------------------------------------------------------
parametres		: label de l'etat .
--------------------------------------------------------------
return			: abl .
------------------------------------------------------------------------------*/
chain_list *stateCodExprForStack(label)
int label ;
{
int code ;
chain_list *abl,*abl2 ;
int j ;

code = ((autoSys->code) + label)->code;
abl=createExpr(AND);
for(j = 0; j < autoSys->numberReg; j++)
   {
   if ((code)&bit[j]) 
      addQExpr(abl,createAtom(nameI(STACK_NAME[0],j)));
   else
      addQExpr(abl,notExpr(createAtom(nameI(STACK_NAME[0],j))));
   }
if(abl->NEXT->NEXT == NULL)
	{
	abl2 = abl ;
	abl = copyExpr(abl2->NEXT->DATA) ;
	freeExpr(abl2) ;
	}
return(abl) ;
}
/*-------------------------------------------------------------------------
nameSl	: genere une chaine de caractere a partir d'un name, pour les "slaves".
--------------------------------------
parametres : name.
--------------------------------------
return : nouvelle chaine.
--------------------------------------------------------------------------*/
char *nameSl(name)
char *name;
{
char *newName ;
char nName[60] ;

sprintf(nName,"%s_s",name) ;
newName = namealloc(nName) ;

return(newName) ;
}
/*-------------------------------------------------------------------------
nameMa	: genere une chaine de caractere a partir d'un name, pour les "maitre".
--------------------------------------
parametres : name.
--------------------------------------
return : nouvelle chaine.
--------------------------------------------------------------------------*/
char *nameMa(name)
char *name;
{
char *newName ;
char nName[60] ;

sprintf(nName,"%s_m",name) ;
newName = namealloc(nName) ;

return(newName) ;
}
