/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_beh2fsm.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"

/*--------------------------------------------------------------------------*
beh2Auto   : remplit la structure d'automate a partir du VHDL.
----------------------------------------------------------------------------
parametres : aucun.
-----------------------------------------------------------------------------
return     :
-----------------------------------------------------------------------------*/
beh2Auto(beh)
struct syf_befig *beh;
{
 struct syf_bepcs *pBepcs;
 struct syf_beasg *pBeasg;
 struct syf_beifs *pBeifs;
 struct syf_becas *pBecas;
 struct syf_betyp *pBetyp;
 chain_list *abl;
 struct syf_bepor *por;
 struct ptype *pType;
 p_groupe Sa;
 char *name;
 int i,label;



pBepcs = beh->BEPCS;
while(pBepcs)
{
   pType = pBepcs->INSTRUCTION;
   while(pType)
   {
   switch(pType->TYPE)
   {
    case BEH_BECAS : pBecas = (struct syf_becas *)pType->DATA;
			  pBetyp = beh->BETYP +  pBecas->TYPE -1;
    /*---------------------------------------------------------------------*/
    /*	only atomique expression is alowed in case of user 's defined types*/
    /*---------------------------------------------------------------------*/
		 if((!strcmp(pBetyp->NAME , ETAT_TYPE))&& ATOM(pBecas->ABL) && 
		   (!strcmp(VALUE_ATOM(pBecas->ABL),CURENT_STATE)))   
		  {
 		   Sa = genGroupe(0,pBetyp->SIZE) ;
		   for(i=0; i< (int) pBecas->SIZE -1;i++) 
		   {
                    label = syf_bintonum((pBecas->CHOICE[i]).VALUE);
	           intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,label,NULL,-1,-1);
		    Sa = delFromgroup(Sa,label);
		   }
		   while(Sa)
		   {
		     intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,Sa->label,NULL,-1,-1);
		     Sa = Sa->next;	
                   }
                 }
         else if( flagPile && !strcmp(pBetyp->NAME , CTRL_TYPE)&& 
		 (ATOM(pBecas->ABL)) && (!strcmp(VALUE_ATOM(pBecas->ABL),CTRL)))  
		{ 
 		   Sa = genGroupe(0,pBetyp->SIZE) ;
		 for(i=0; i< (int) pBecas->SIZE -1;i++) 
		 {
                    label = syf_bintonum((pBecas->CHOICE[i]).VALUE);
		   intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,-1,NULL,-1,label);
		    Sa = delFromgroup(Sa,label);
		 }
		 while(Sa)
		 {
		   intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,-1,NULL,-1,Sa->label);
		   Sa = Sa->next;	
                 }
                }
		 else { 	
			printf("illegal case condition\n");
				exit(-1);
				}
				  break;
   case BEH_BEIFS : pBeifs = (struct syf_beifs*)pType->DATA;
                intpType(beh,pBeifs->CNDTRUE,-1,copyExpr(pBeifs->CND),-1,-1);
                  intpType(beh,pBeifs->CNDFALSE,-1,notExpr(pBeifs->CND),-1,-1);
                  break;
   case BEH_BEASG : pBeasg = (struct syf_beasg *)pType->DATA;
			  pBetyp = beh->BETYP + pBeasg->TYPE -1;
                if(existOut(pBeasg->NAME) != -1) 
                 {
                  if(!ATOM(pBeasg->ABL) || strcmp(VALUE_ATOM(pBeasg->ABL),"'0'"))
                  {
                   if(ATOM(pBeasg->ABL) && strcmp(VALUE_ATOM(pBeasg->ABL),"'1'"))
                  createLocOut(-1,pBeasg->NAME,pBeasg->ABL);
                  }
                }
                else if(!strcmp(pBetyp->NAME,ETAT_TYPE))
                {
             if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, NEXT_STATE))) 
		 {
                   if((label = labelState(VALUE_ATOM(pBeasg->ABL)))!=-1)
		   {
                     ajoutTrans(label,createTrans(createAtom("'1'"),-1));
		   }
                   else if(!strcmp(VALUE_ATOM(pBeasg->ABL),STACK_NAME[0]));
		       else
		       {
			   printf("invalide NEXT_STATE affectation\n");
		           exit(-1);
                       }
                 }
                 else  if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, RETURN_STATE))) 
		      {
                          if((label = labelState(VALUE_ATOM(pBeasg->ABL)))==-1)
			    {
			     printf("invalide returnState  affectation\n");
				exit(-1);
                  	    }
                     }
                 else  if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, CURENT_STATE))) 
				 {
				 if(!strcmp(VALUE_ATOM(pBeasg->ABL),NEXT_STATE))
					 autoSys->cndReg = copyExpr(abl);
					 else {
			            printf("invalide Current State  affectation\n");
				        exit(-1);
					  }
				 }
                 else  if(ATOM(pBeasg->ABL) && (!strcmpSt(pBeasg->NAME))); 
                else
	             {
                  printf("illegal state affectation\n");
                  exit(-1);
                }
	      }
                else if( flagPile && !strcmp(pBetyp->NAME,CTRL_TYPE))
                {
                if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME,CTRL ))); 
		 {
			   if((label= labelCtrl(VALUE_ATOM(pBeasg->ABL)))==-1) 
			    {
			     printf("invalide CTRL affectation : %s <= %s signal doesn't exist \n",pBeasg->NAME,VALUE_ATOM(pBeasg->ABL));
				exit(-1);
                  	   
                  	  }
		}
	      }
		   break;
   default        : break;
   }
 pType = pType->NEXT;
 }
pBepcs = pBepcs->NEXT;
  
} 
   if(autoSys->cndReg)
   {
  	if( searchOperExpr(autoSys->cndReg,STABLE)== 1)
		autoSys->typeReg = REG_D;
  	else 
		autoSys->typeReg = REG_MS;
   }
 else
 {
   printf("SYF : State not assigned \n") ;
   exit(-1) ;
   }
}
/*--------------------------------------------------------------------------*
existOut : retourne le label de la sortie si elle  exite -1 sinon.
----------------------------------------------------------------------------
parametres : out name.
-----------------------------------------------------------------------------
return     :
-----------------------------------------------------------------------------*/
int existOut(name)
char *name;
{
int i;

for(i = 0; i < autoSys->numberOut; i++)
	{
		if(!(strcmp((autoSys->out + i)->name,name)))
				return(i) ;
	}
return(-1);
}
/*--------------------------------------------------------------------------*
genGroup : genere une liste des labels .
----------------------------------------------------------------------------
parametres : left , right.
-----------------------------------------------------------------------------
return     : le groupe des labels
-----------------------------------------------------------------------------*/
p_groupe genGroupe(left,right)
int left;
int right;
{
 int i,flag =1;
 p_groupe gm_aux ;
 p_groupe gm = NULL;
 
 if (right < left)  flag = -1;
 for(i = left ; i != right + flag ; i+= flag)
 {
  gm_aux = (p_groupe)mbkalloc(sizeof(struct E_groupe)) ;

  gm_aux->label = i ;
  gm_aux->next = gm;
  gm=gm_aux;
 }
return(gm);
}

/*--------------------------------------------------------------------------*
labelState : retourne le label de l'etat.
----------------------------------------------------------------------------
parametres : state name.
-----------------------------------------------------------------------------
return     :
-----------------------------------------------------------------------------*/
int labelState(name)
char *name;
{
int i;

for(i = 0; i < autoSys->numberState; i++)
	{
		if(!(strcmp((autoSys->state + i)->name,name)))
				return(i) ;
	}
return(-1);
}
/*--------------------------------------------------------------------------*
labelCtrl : interprete les pType liee a un etat.
----------------------------------------------------------------------------
parametres : ctrl name.
-----------------------------------------------------------------------------
return     :
-----------------------------------------------------------------------------*/
int labelCtrl(name)
char *name;
{
int i;

if(name)
for(i = 0; i < NUMBERCTRL; i++)
	{
		if(!(strcmp(ctrlName[i],name)))
				return(i) ;
	}
return(-1);
}


/*--------------------------------------------------------------------------*
intpType   : interprete les pType liee a un etat.
----------------------------------------------------------------------------
parametres : pType , CNDstate,splabel,transAbl.
-----------------------------------------------------------------------------
return     :
-----------------------------------------------------------------------------*/
void intpType(beh,pType,splabel,abl,retlabel,ctrl)
struct syf_befig *beh;
struct ptype *pType;
int splabel;
chain_list *abl;
int retlabel;
int ctrl;
{
pTrans trans;
int i;
int sflabel;
struct syf_beifs *pBeifs;
struct syf_becas *pBecas;
struct syf_beasg *pBeasg;
struct syf_betyp *pBetyp;
int label;
p_groupe Sa;
chain_list *ablAux;
while(pType)
{
  switch(pType->TYPE)  
  {
    case BEH_BECAS : pBecas = (struct syf_becas *)pType->DATA;
			  pBetyp = beh->BETYP + pBecas->TYPE -1;
		 if((!strcmp(pBetyp->NAME , ETAT_TYPE))&& 
		  ATOM(pBecas->ABL)  && 
		   (!strcmp(VALUE_ATOM(pBecas->ABL),CURENT_STATE)))   
	          {
		if(splabel ==-1)
		{
 		   Sa = genGroupe(0,pBetyp->SIZE) ;
		 for(i=0; i< (int) pBecas->SIZE -1;i++) 
		 {
                    label = syf_bintonum((pBecas->CHOICE[i]).VALUE);
	           intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,label,abl,-1,-1);
		    Sa = delFromgroup(Sa,label);
		 }
		   while(Sa)
		   {
		     intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,Sa->label,abl,-1,-1);
		     Sa = Sa->next;	
                   }
		}
		 else 
		    { 
		      printf("illegal case condition\n");
					exit(-1);
                    }
                  }
                 else if( flagPile && !strcmp(pBetyp->NAME
		 , CTRL_TYPE)&& 
		   ATOM(pBecas->ABL) && 
		   (!strcmp(VALUE_ATOM(pBecas->ABL),CTRL)))   
		{ 
		if(retlabel ==-1) 
		{
 		   Sa = genGroupe(0,pBetyp->SIZE) ;
		 for(i=0; i< (int) pBecas->SIZE -1;i++) 
		 {
                    label = syf_bintonum((pBecas->CHOICE[i]).VALUE);
		   intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,splabel,abl,-1,label);
		    Sa = delFromgroup(Sa,label);
		 }
		 while(Sa)
		 {
		   intpType(beh,(pBecas->CHOICE[i]).INSTRUCTION,splabel,abl,-1,Sa->label);
		   Sa = Sa->next;	
                 }
		}
		 else 
		  { 
		    printf("illegal case condition\n");
			exit(-1);
		  }
                }
		 else 
		  { 
		    printf("illegal case condition \n");
			exit(-1);
		  }
				   break;
   case BEH_BEIFS : pBeifs = (struct syf_beifs *)pType->DATA;
		  if(abl == NULL)
               ablAux = copyExpr(pBeifs->CND);
		  else 
                  ablAux = createBinExpr(AND,copyExpr(abl),copyExpr(pBeifs->CND));
                  intpType(beh,pBeifs->CNDTRUE,splabel,ablAux,retlabel,ctrl);
		  if(abl == NULL)
               ablAux = notExpr(copyExpr(pBeifs->CND));
		  else 
                  ablAux = createBinExpr(AND,copyExpr(abl),notExpr(copyExpr(pBeifs->CND)));
                  intpType(beh,pBeifs->CNDFALSE,splabel,ablAux,retlabel,ctrl);
                  break;
   case BEH_BEASG : pBeasg = (struct syf_beasg *)pType->DATA;
			  pBetyp = beh->BETYP + pBeasg->TYPE -1;
                if(existOut(pBeasg->NAME) != -1) 
                 {
                  if(!ATOM(pBeasg->ABL) || strcmp(VALUE_ATOM(pBeasg->ABL),"'0'"))
                  {
                   if(abl &&( !ATOM(pBeasg->ABL) || strcmp(VALUE_ATOM(pBeasg->ABL),"'1'")))
                   ablAux = createBinExpr(AND,copyExpr(abl),
                                       copyExpr(pBeasg->ABL)); 
                   else if(abl)
                       ablAux = copyExpr(abl);
                   else ablAux = copyExpr(pBeasg->ABL);
                  createLocOut(splabel,pBeasg->NAME,ablAux);
				  /*printf("name = %s\n",pBeasg->NAME);
				  displayExpr(ablAux);*/
                  }
                }
                else if(!strcmp(pBetyp->NAME,ETAT_TYPE))
                {
             if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, NEXT_STATE))) 
		 {
                   if((sflabel = labelState(VALUE_ATOM(pBeasg->ABL)))!=-1)
		   {
                     if(abl)
                        trans = createTrans(abl,splabel);
                     else
                        trans = createTrans(createAtom("'1'"),splabel);
                     ajoutTrans(sflabel,trans);
		   }
                   else if(!strcmp(VALUE_ATOM(pBeasg->ABL),STACK_NAME[0]));
		       else
		       {
			   printf("invalide NEXT_STATE affectation\n");
		           exit(-1);
                       }
                 }
                 else  if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, RETURN_STATE))) 
		      {
		         if(retlabel == -1)
			 {
                          if((retlabel = labelState(VALUE_ATOM(pBeasg->ABL)))==-1)
			    {
			     printf("invalide returnState  affectation\n");
				exit(-1);
                  	    }
			  else if(ctrl == PUSH)
			  {
			    if (abl != NULL)
			    addStack(ctrl,splabel,retlabel,abl); 
                            else 
			    addStack(ctrl,splabel,retlabel,createAtom("'1'")); 
                          }
			  else if(ctrl !=-1)
			      printf("return State affected in  non PUSH ctrl\n");
		         }
			  else printf("return state declared more than one\n");
                     }
                 else  if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME, CURENT_STATE))) 
				 {
				 if(!strcmp(VALUE_ATOM(pBeasg->ABL),NEXT_STATE))
					 autoSys->cndReg = copyExpr(abl);
				 }
                 else  if(ATOM(pBeasg->ABL) && (!strcmpSt(pBeasg->NAME))); 
                else
	        {
                  printf("illegal state affectation\n");
                  exit(-1);
                }
	      }
                else if( flagPile && !strcmp(pBetyp->NAME,CTRL_TYPE))
                {
                if(ATOM(pBeasg->ABL) && (!strcmp(pBeasg->NAME,CTRL ))); 
		 {
			  if(ctrl ==-1)
			  {
			   if((ctrl= labelCtrl(VALUE_ATOM(pBeasg->ABL)))==-1) 
			    {
			     printf("invalide CTRL affectation : %s <= %s signal doesn't exist \n",pBeasg->NAME,VALUE_ATOM(pBeasg->ABL));
				exit(-1);
                  	    }
                  	 else if ((ctrl != PUSH || retlabel != -1) && splabel != -1)
			     {
			       if (abl != NULL)
			         addStack(ctrl,splabel,retlabel,abl); 
                  	       else 
			         addStack(ctrl,splabel,retlabel,createAtom("'1'")); 
			     }
                  	  }
			 else 
			    {
			     printf("invalide CTRL affectation : %s <= %s CTRL are already affected \n",pBeasg->NAME,VALUE_ATOM(pBeasg->ABL));
				exit(-1);
                  	    }
		 }
                }
                break; 
  default     : break; 
  }
  pType = pType->NEXT;              
} 
  if((splabel != -1)&&(retlabel == -1)&&(ctrl == PUSH))
	 {
     printf("ERROR : RETURN_STATE is not affected for a PUSH.\n");
	 exit(-1) ;
	 }
}
/*--------------------------------------------------------------------------*
strcmpSt   : verifie si name est un stack est retourne son rang .
----------------------------------------------------------------------------
parametres : name .
-----------------------------------------------------------------------------
return     : rang;
-----------------------------------------------------------------------------*/
strcmpSt(name)
char *name;
{
 int i;
 for(i=0;i < autoSys->sizeStack; i++)
 if(!strcmp(name,STACK_NAME[i]))
	return(0);
 return(1);
}
