/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_lax.c                                                  */
/*                                                                          */
/*    (c) copyright 1993 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :  C. Sarwary                            le : 24/10/1993     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/
#include <stdio.h>
#include <math.h>
#include MUT_H 
#include LOG_H 
#include <signal.h>
#include"../beh104/beh104.h"
#include "syf_auto.h"
#include "syf_must.h"
#include "syf_beh2fsm.h"
#include "y.tab.h"
extern FILE *yyin;
extern FILE *syf_y_in;
int syf_rom, syf_pseudorom, syf_stack, syf_eval, syf_save, syf_kiss, syf_lax ;

/*---------------------------------------------------------------
laxSyf :
-----------------------------------------------------------------*/
laxSyf(option,dir,fileName,trace,stack,pseudorom,rom,eval,save,kiss)
char option ;
int trace, stack, pseudorom, rom, eval, save, kiss ;
char *dir, *fileName ;
{
char *parFile ;
char name[20];
int numBit,i,l,k,AME=0 ;
int FIN =0;
struct syf_befig *beh ;
long beg, end ;
long delay ;
chain_list *listGrp ;
pState state ;
pCircuit pC ;
char Name[30] ;
char *getenv();
int msgBus() ;
int val,par ;
char *getFileName() ;

FSM_FILE = namealloc(fileName) ;
/*
#ifndef  SYF_CORE
signal(SIGBUS,(void *)msgBus) ;
signal(SIGSEGV,(void *)msgBus) ;
#endif
*/

syf_stack = stack ;
syf_pseudorom = pseudorom ;
syf_eval = eval ;
syf_save = rom ;
syf_kiss = kiss ;
syf_rom = rom ;

initializeBdd(2) ;

SYF_COMPILE = 0 ;
syf_trace = trace ;
syf_trace = 1 ;
rempMaskTab();
/*
if(syf_kiss)
	sprintf(FILE_NAME,"%s.kiss2",fileName) ;
else	
	sprintf(FILE_NAME,"%s.fsm",fileName) ;
*/
/*strcpy(FSM_FILE,dir);

sprintf(FSM_FILE,"%s/%s",FSM_FILE,FILE_NAME) ;*/

FILE_NAME = getFileName(FSM_FILE) ;
printf("dir : %s\n",FSM_FILE) ;
printf("fileName : %s\n",FILE_NAME) ;
if(syf_kiss)
	{
	printf("input file format : kiss2\n") ;
	pC = compileKiss() ;
	}
else
	pC = compile() ;

switch(option)
	{
	case RECUIT :
		syf_cod(RECUIT,pC,AME,0) ;
		break ;
	case FORC :
		syf_cod(FORC,pC,AME,0) ;
		break ;
	case MUST :
		syf_cod(MUST,pC,AME,0) ;
		break ;
	case VERT :
		syf_cod(VERT,pC,AME,0) ;
		break ;
	case ALEA :
		syf_cod(ALEA,pC,AME,0) ;
		break ;
	case JEDI :
		syf_cod(JEDI,pC,AME,0) ;
		break ;
	case MUSE :
		syf_cod(MUSE,pC,AME,0) ;
		break ;
	case NEWC :
		printf("n : option not disponible\n") ;
	 	exit(-1) ;
	case ASP :
		syf_cod(ASP,pC,AME,0) ;
		break ;
	default :
		msg(ER_PARAM) ;
	}
return(0) ;
}

/*---------------------------------------------------------
traiteDc	: applique la simplification par dc sur le beh d'automate.
----------------------------
parametres	: befig.
----------------------------
return		: void.
-----------------------------------------------------------*/
void traiteDc(beh)
struct syf_befig *beh ;
{
int i ;
pState state ;
pCircuit pC ;
char *Name ;

pC = beh->CIRCUI ;
printf("traitement des DC lies aux etats\n") ;
rempliBddAuto() ;
dc2abl() ;

if(autoSys->ablDc != NULL)
	{
	/* On elimine les "state"_s et _m de pC->pTI pour que syf_makeBddBeh() ne 
	les garde pas comme var intermediaire, rempliBddAutoReg les rajout apres*/
	state = autoSys->state ;
	displayCct(pC,1) ;
	for(i = 0; i < autoSys->numberState; i++)
		{
		Name = nameSl(state->name) ;
		deleteTH(pC->pTI,Name,state->name) ;
		Name = nameMa(state->name) ;
		deleteTH(pC->pTI,Name,state->name) ;
		deleteTH(pC->pTI,"push") ;
		deleteTH(pC->pTI,"pop") ;
		deleteTH(pC->pTI,"nop") ;
		state++ ;
		}
	displayCct(pC,1) ;
	for(i = 0; i < autoSys->numberReg; i++)
		addInputCct(pC,nameindex(CURENT_STATE,i)) ;
	for(i = 0; i < autoSys->numberReg; i++)
		addInputCct(pC,nameindex(NEXT_STATE,i)) ;
	syf_makeBddBeh(beh,beh->CIRCUI,1,syf_trace,100) ;
	rempliBddAutoReg(beh->CIRCUI) ;
	rempliOutCctAuto(beh->CIRCUI) ;
	/*displayDc() ;
	displayCct(pC) ;*/
	syf_displayBehMap(beh) ;
	simplifDcAutoBeh(beh) ;
	syf_displayBehMap(beh) ;
   	/*syf_beh_debug(beh,"befig");*/
	}
else
	printf("No Don't Care\n") ;
}
	
/*---------------------------------------------------------
compileKiss	: Compile un fichier de format KISS2.
----------------------------
parametres	: aucun.
----------------------------
return		: une structure circuit.
-----------------------------------------------------------*/
pCircuit compileKiss()
{
int i, j, k, l;
char name[20] ;
int FIN = 0;
pCircuit pC ;

printf("Running FSM Compiler Kiss format ......\n") ;
fflush(stdout) ;
if (!(yyin=fopen(FSM_FILE,"r")))
	{
	printf("%s : doesn't exist\n",FSM_FILE);
	exit(-1);
	}

if(yyparse() == 1)
	exit(-1) ;
defaultName() ;
l = strlen(FSM_FILE);
i =0 ;
while((i < l +1) &&(!FIN))
	{
	if(FSM_FILE[l-i] == '/') FIN =1; 
	else i++;
	}
for(k=0; k< i; k++)
	{
	if(FSM_FILE[l-i+k+1] == '.')
		{
		name[k] = '\0';
		k =i;
		}
	else      name[k] = FSM_FILE[l-i+k+1];
	}

autoSys->numberReg = NUMBER_BIT(autoSys->numberState);  
printf("--> Number of States : %d\n",autoSys->numberState) ;
getTypeMachine() ;
if(autoSys->typeMachine == MOORE)
	printf("--> Type FSM : MOORE\n") ;
else
	printf("--> Type FSM : MEALEY\n") ;
if(syf_trace)
	{
	printf("----> Number of states : %d\n",autoSys->numberState) ;
	printf("----> Number of registers : %d\n",autoSys->numberReg) ;
	}
autoSys->name = namealloc(name);  
autoSys->dc = autoSys->code + autoSys->numberState;
/*if(syf_trace)
	equivState() ;*/
trans2Abl();
pC = NULL ;
/*pC = rempliBddAuto() ;*/
displayAuto() ;
return(pC) ;
}
/*---------------------------------------------------------
compile		: compile le fichier d'entree : FSM_FILE.
----------------------------
parametres	: aucun.
----------------------------
return		: une structure circuit.
-----------------------------------------------------------*/
pCircuit compile()
{
int i, j, k, l;
char name[20] ;
int FIN = 0;
pCircuit pC ;

printf("Running VHDL Compiler .....\n") ;
fflush(stdout) ;
if (!(yyin=fopen(FSM_FILE,"r")))
	{
	printf("%s : doesn't exist\n",FSM_FILE);
	exit(-1);
	}
syf_y_in  =  yyin ;

if(syf_y_parse() == 1)
	exit(-1) ;
SYF_HEDFIG->FLAG = SYF_ERRFLG;
if(SYF_HEDFIG->FLAG != 0 )
	{
	  syf_error(200,NULL);
		exit(1);
	}

initInOutST(SYF_HEDFIG) ;
l = strlen(FILE_NAME);
i =0 ;
while((i < l +1) &&(!FIN))
	{
	if(FILE_NAME[l-i] == '/') FIN =1; 
	else i++;
	}
for(k=0; k< i; k++)
	{
	if(FILE_NAME[l-i+k+1] == '.')
		{
		name[k] = '\0';
		k =i;
		}
	else      name[k] = FILE_NAME[l-i+k+1];
	}

autoSys->name = namealloc(name);  
autoSys->dc = autoSys->code + autoSys->numberState;
syf_beh_verify(SYF_HEDFIG) ;
beh2Auto(SYF_HEDFIG) ;
/*if(!syf_stack)
	flattenStack() ;*/
/*verifPushPop() ; */

autoSys->numberReg = NUMBER_BIT(autoSys->numberState);  
printf("--> Number of States : %d\n",autoSys->numberState) ;
getTypeMachine() ;
if(autoSys->typeMachine == MOORE)
	printf("--> Type FSM : MOORE\n") ;
else
	printf("--> Type FSM : MEALEY\n") ;
if(syf_trace)
	{
	printf("----> Number of states : %d\n",autoSys->numberState) ;
	printf("----> Number of registers : %d\n",autoSys->numberReg) ;
	}
trans2Abl();

pC = NULL ;
/*pC = rempliBddAuto() ;*/
/*displayAuto() ;*/
return(pC) ;
}
/*---------------------------------------------------------
syf_cod	: synthese avec le codage MUSTANG.
----------------------------
parametres	: type de codage(differents algo).
----------------------------
return		: void.
-----------------------------------------------------------*/
void syf_cod(typeCod, pC, ame,dc)
char typeCod ;
pCircuit pC ;
int ame, dc ;
{
pOut savOut, saveOut() ;
struct syf_befig *beh ;
char out_file[50] ;
char name[50],extend[50] ;
char *path ;
char saveRes[20] ;
char bidon[200] ;
pCircuit makeCctBeh() ;
int i ;
char *getenv() ;

verifOption() ;
strcpy(extend,autoSys->name) ;

fsm_verify() ;
printf("FSM's States Encoding .....\n") ;
fflush(stdout) ;

razSys() ;
if(!syf_pseudorom && !syf_rom)
	{
	savOut = saveOut(autoSys->out) ;/*Comme out2Abl n'est pas definitif, on
					sauvegarde out,et on le recupere avant le prochain out2Abl*/
	out2Abl();/*on relance cette fonction apres genStack, ici elle sert pour
			calcul de cout par constructBehGivCost(recuit et stack) */
	}
switch(typeCod)
	{
	case RECUIT :
		strcat(extend,"r") ;
		autoSys->codage = namealloc("RECUIT");
		recuit(); 
		break ;
	case MUST :
		strcat(extend,"m") ;
		autoSys->codage = namealloc("MUSTANG");
		mustang(ame); 
		break ;
	case ASP :
		strcat(extend,"s") ;
		autoSys->codage = namealloc("sASP");
		asp(0,ame); 
		break ;
	case ALEA :
		strcat(extend,"a") ;
		autoSys->codage = namealloc("ALEATOIRE");
		codageAleatoire(autoSys->numberReg,ame); 
		break ;
	case FORC :
		strcat(extend,"h") ;
		autoSys->codage = namealloc("hFORCAGE");
		codageHorizontal(autoSys->numberReg,ame); 
		break ;
	case VERT :
		strcat(extend,"v") ;
		autoSys->codage = namealloc("VERTICAL");
		codageVertical(autoSys->numberReg); 
		break ;
	case JEDI :
		strcat(extend,"j") ;
		autoSys->codage = namealloc("JEDI");
		mustJedi(); 
		break ;
	case MUSE :
		printf("Syf : '-u' Optin no disponible\n") ;
		return ;
		/*autoSys->codage = namealloc("uMUSE");
		strcat(extend,"u") ;
		muse(ame); */
		break ;
	case NEWC :
		printf("Syf : '-n' Optin no disponible\n") ;
		return ;
		/*autoSys->codage = namealloc("NEW_COD");
		strcat(extend,"n") ;
		nc_genGroup(0,ame);*/ 
		break ;
	default :
		printf("SyF : Unknwon Encoding Algorithm\n") ;
		exit(-1) ;
	}
verifCode() ;
autoSys->name = namealloc(extend) ;
if (syf_save)
		saveCode();

if(syf_rom)
	driveRomOut() ;

if(flagPile)
	{
	if(syf_stack)
		optimCodForStack(pC) ;
	rempStackFixCode() ;

	if(syf_trace)
		{
		displayMask() ;
		displayStack() ;
		fflush(stdout) ;
		}
	}

if(syf_trace)
	printf("------ code2Abl -----\n") ;
code2Abl();
if(syf_trace)
	printf("------ end code2Abl -----\n") ;
if(syf_trace)
	displayCode(1) ;

if(flagPile ==1)
	{
	if(syf_trace)
		printf("----- ctrl2Abl ----\n") ;
	ctrl2Abl();
	if(syf_trace)
		printf("----- end ctrl2Abl ----\n") ;
	if(autoSys->typeReg == REG_D)
		{
		if(syf_trace)
			printf("********* D stack generation *********\n") ;
    	genStackD();
		}
	else
		{
		if(syf_trace)
			printf("********* MS stack generation *********\n") ;
    	genStackD();
		completStackForMS() ;
		}
	}
if(autoSys->typeReg == REG_D)
	{
	if(syf_trace)
		printf("D Registers generation\n") ;
	genRegD();
	}
else
	{
	if(syf_trace)
		printf("MS registers generation\n") ;
	genReg();
	}
if(!syf_pseudorom && !syf_rom)
	{
	/* Avant la synthese des out on recupere out original */
	freeOut(autoSys->out) ;
	autoSys->out = savOut ;
	}

if(syf_pseudorom)
	{
	if(syf_trace)
		printf("******** OUTPUT OPTIMIZATION *********\n") ;
	if(autoSys->typeReg == REG_D)
		genRegOutD() ;
	else
		genRegOut() ;
	if(syf_trace)
		printf("******** OUTPUT GENERATION *********\n") ;
	synthOut() ;
	}
else if(!syf_rom)
	{
	if(syf_trace)
		printf("******** OUTPUT GENERATION *********\n") ;
	out2Abl();
	}

if(dc == 1)
	destroyAuxAuto() ; /**** Pour le traiteDc *****/
if(syf_rom)
	beh = a2behRom(pC) ;
else
	beh = auto2beh(pC) ;
syf_mapCarExprBeh(beh,simplif10Expr) ;
syf_mapCarExprBeh(beh,simplifNotExpr) ;
if(syf_trace)
	syf_displayBehMap(beh,1) ;
/*#ifndef ARCHI_PC*/
pC = makeCctBeh(beh,0,syf_trace) ; /*eliminer partout ailleur le pC */
if(syf_trace)
	displayCct(pC) ;
if(syf_eval)
	{
	printf("-----> Initial cost, number of litterals : %d\n",coutBehAuto(beh)) ;
	printf("behavioral Minimizer running ......\n") ;
	fflush(stdout) ;
	minimBehAbl(beh,syf_trace) ;
	printf("-----> Estimated cost, number of litterals: %d\n",coutBehAuto(beh));
	fflush(stdout) ;
	}
if(dc == 1)
	traiteDc(beh) ;
/*#endif */
syf_vhdlsavebefig(beh) ;
if (getenv("SL_BEH_LIB"))
	{
	path = (char *)mbkalloc(70) ;
	strcpy(path,getenv("SL_BEH_LIB")) ;
	if(strcmp(path,"."))
		{
		system(sprintf(bidon,"mv %s.vbe %s/%s.vbe",autoSys->name,path,autoSys->name));
		}
	}
}
/*---------------------------------------------------------
razSys		: Reinitialise de certaines structures d' autoSys pour un nouveau 
			  codage.
----------------------------
parametres	: rien .
----------------------------
return		: void.
-----------------------------------------------------------*/
razSys()
{
int i, numReg ;

autoSys->dc = NULL ;
autoSys->ablDc = NULL ;
for(i = 0; i < NUMBER_CODE(autoSys->numberReg); i++)
	{   
	(autoSys->code + i)->code = 0 ;
	(autoSys->code + i)->abl = NULL ;
	}
if(autoSys->typeReg == REG_D)
	numReg = autoSys->numberReg ;
else
	numReg = 2 * autoSys->numberReg ;
for(i = 0; i < numReg; i++)
	{   
	(autoSys->reg + i)->name = NULL ;
	(autoSys->reg + i)->abl = NULL ;
	(autoSys->reg + i)->cnd = NULL ;
	(autoSys->reg + i)->bdd = NULL ;
	}
}

msg(n)
int n ;
{
switch (n)
	{
	case ER_PARAM :
		printf("syf    : usage syf -option <input_file> [-stack] [-pseudorom] [-eval] [-save]\n") ;	
		printf("option :  -s Uses the \"vertical\" encoding algrithm.\n") ;
		printf("          -m Uses the \"horizontal\" encoding algrithm.\n");
		printf("          -a Uses the random encoding.\n");
		printf("          -r Optimal encoding.\n");
		printf("          -j Uses a jedi like encoding algorithm.\n");
		printf("          -h Uses an encoding given by user through par.aut file.\n");
		exit(-1) ;

	default :
		printf("syf: errno unknown\n") ;
		exit(-1) ;
	}
}
msgBus()
{
printf("syf : Fatal error.\n");
printf("Please, send your file to cao-vlsi@masi.ibp.fr\n");
exit(-1) ;
}
/*---------------------------------------------------------
givParam	: ouvre le fichier de parametres et les lit. s'il n'y a pas de 
			  fichier de parametres renvoie 0, sinon 1.
			  codage.
----------------------------
parametres	: les adresses de parametres .
----------------------------
return		: int.
-----------------------------------------------------------*/
givParam(fileName,outOpt,stackOpt,behavOpt)
char *fileName ;
int *outOpt, *stackOpt, *behavOpt ;
{
FILE *file ;
char *s ;
char par[30] ;
char newline[30] ;
int val,line ;

/* par defaut les parm sont a 1 */
*outOpt = 1 ;
*stackOpt = 1 ;
*behavOpt = 1 ;

for(line = 0; line < 30; line++)
	newline[line] = (char)NULL ;
line = 0 ;
if((file = fopen(fileName,"rt")))
	{
	s = (char *)mbkalloc(200) ;
 
	while(fgets(s,200,file) != NULL)
		{
		while(!strncmp(s," ",1) || !strncmp(s," ",1))/*elimination des blancs*/
			s++ ;
 	 
		line++ ;
		if(strncmp(s,"#",1) && strncmp(s,"\n",1) && strcmp(s,""))
			{
			if((sscanf(s,"%s %d %s",par, &val, newline) != 2) || (val != 0 && val != 1))
				{
			   printf("syf : assignement error in %s, Line %d\n",fileName,line);
				exit(-1) ;
				}
			if(!strcmp(par,"OUT_OPTIM") || !strcmp(par,"out_optim"))
					*outOpt = val ;
			else if(!strcmp(par,"STACK_OPTIM") || !strcmp(par,"stack_optim"))
					*stackOpt = val ;
			else if(!strcmp(par,"BEHAV_OPTIM") || !strcmp(par,"behav_optim"))
					*behavOpt = val ;
			else
				{
				printf("syf : Invalide Parameter name in %s, Line %d\n",fileName,line);
				exit(-1) ;
				}
			}
		}
	}
/*#ifdef ARCHI_PC
*stackOpt = 0 ;
*behavOpt = 0 ;
#endif*/
}
/*---------------------------------------------------------
verifOption	: Verifie la coherence des options :
			  - pseudorom et typeMachine non MOORE.
			  - stack et machine sans pile.
----------------------------
parametres	: .
----------------------------
return		: .
-----------------------------------------------------------*/
verifOption()
{

if(autoSys->typeMachine != MOORE && syf_pseudorom)
	{
	printf("MEALEY FSM : pseudorom implementation impossible\n") ;
	exit(-1) ;
	}
if(!flagPile && syf_stack)
	{
	printf("FSM without STACK: STACK optimization impossible\n") ;
	exit(-1) ;
	}
if(syf_rom && syf_pseudorom)
	{
	printf("rom and pseudorom incompatible options\n") ;
	exit(-1) ;
	}
}
/*---------------------------------------------------------
getFileNAme	: Give the file name
----------------------------
parametres	: path.
----------------------------
return		: .
-----------------------------------------------------------*/
char *getFileName(path)
char *path ;
{
int i, len ;
char *name ;

len = strlen(path) ;
name = mbkalloc(len) ;

for(i = len; i > 0; i--)
	{
	if(path[i] == '/')
		{
		name = namealloc(path+i+1) ;
		return(name) ;
		}
	}
name = namealloc(path+i + 1) ;
return(name) ;
}
