/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  Synthetiseur de FSM                                       */
/*    Fichier :  syf_rom.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 : 28/09/1993     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/***************************************************************************/
#include<stdio.h>
#include<math.h>
#include MUT_H
#include LOG_H
#include"../beh104/beh104.h"
#include "syf_auto.h"
#include "../util/util.h"
/*------------------------------------------------------------------------------
driveRomOut		: Cree un fichier vbe contenant la description ROM pour grog
				  de la fonction de generation.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void driveRomOut()
{
int i,j; 
FILE *fic;
char fName[80];
char name[80] ;
char *romWord, *romAdr, *getRomWord(), *getRomAdr() ;
int len ;

if(autoSys->typeMachine != MOORE)
	{
	printf("\tgiven FSM is not a MOORE FSM, ROM implementation Impossible\n");
	exit(-1) ;
	}
printf("ROM generation ....\n") ;
strcpy(name,autoSys->name) ;
len = strlen(name) ;
strcat(name,"rom") ;
strcpy(fName,name);
strcat(fName,".vbe") ;

if(!(fic = fopen(fName,"w")))
	{
	printf("SYF : fopen impossible\n");
	exit(-1);
	} 

fprintf(fic,"-- VHDL grog description generated by SYF\n");
fprintf(fic,"-- Word number	: %d\n",autoSys->numberState);
fprintf(fic,"-- bit number	: %d\n",autoSys->numberOut);
fprintf(fic,"-- tri_state output	: no\n");
fprintf(fic,"-- package to be used outside of cao-vlsi VHDL simulator\n");
fprintf(fic,"-- USE pkg.p6b_pkg.all;\n\n");
fprintf(fic,"ENTITY %s IS\n", name);

fprintf(fic,"	PORT(\n");
fprintf(fic,"		%s	: IN BIT ;\n",autoSys->horloge);

fprintf(fic,"		adr	: IN BIT_VECTOR(%d DOWNTO 0);\n",NUMBER_BIT(autoSys->numberState) -1);
fprintf(fic,"		f	: OUT BIT_VECTOR(%d DOWNTO 0);\n",autoSys->numberOut-1);

fprintf(fic,"		vdd	: IN BIT ;\n");
fprintf(fic,"		vss	: IN BIT) ;\n");

fprintf(fic,"END %s ;\n\n", name);


fprintf(fic,"ARCHITECTURE dataflow OF %s IS\n", name);
fprintf(fic,"	SIGNAL m_f	: BIT_VECTOR(%d DOWNTO 0) ;\n",autoSys->numberOut-1);
/*
out = autoSys->out ;
for(i = 0; i < autoSys->numberOut; i++)
	{
	fprintf(fic,"	SIGNAL m_%s	: BIT ;\n",out->name);
	out++ ;
	}
	*/

fprintf(fic,"\nBEGIN\n");

fprintf(fic,"	f <= m_f WHEN (%s) ELSE ",exprToChar(autoSys->cndReg,1));
fprintf(fic,"	B\"");
for(i = 0; i < autoSys->numberOut; i++)
	fprintf(fic,"0");
fprintf(fic,"\" ;\n");

fprintf(fic,"	WITH adr(%d DOWNTO 0) SELECT\n", NUMBER_BIT(autoSys->numberState) - 1);
fprintf(fic,"		m_f(%d DOWNTO 0) <= ",autoSys->numberOut - 1);
for(i = 0; i < autoSys->numberState - 1; i++)
	{
	romWord = getRomWord(i) ;
	romAdr = getRomAdr(i) ;
	fprintf(fic,"			B\"%s\" WHEN B\"%s\",\n",romWord,romAdr);
	}
romWord = getRomWord(i) ;
romAdr = getRomAdr(i) ;
fprintf(fic,"			B\"%s\" WHEN B\"%s\" ;\n",romWord,romAdr);


fprintf(fic,"\nASSERT( vss = '0')\n");
fprintf(fic,"REPORT \"Power supply is missing on vss\"\n");
fprintf(fic,"SEVERITY ERROR ;\n");
fprintf(fic,"\nASSERT( vdd = '1')\n");
fprintf(fic,"REPORT \"Power supply is missing on vdd\"\n");
fprintf(fic,"SEVERITY ERROR ;\n");
fprintf(fic,"\nEND dataflow ;\n");

printf("%s has been generated\n",fName) ;
driveVst(name) ;
}
/*------------------------------------------------------------------------------
getRomWord		: A partir de locOut d'un etat genere un mot pour la ROM .
				  Les output qui ont une valeur sont recopies et pour les autres
				  un '0' est rajoute.
--------------------------------------------------------------
parametres		: label de l'etat .
--------------------------------------------------------------
return			: le mot pour la ROM .
------------------------------------------------------------------------------*/
char *getRomWord(label)
int label ;
{
pLocOut locOut ;
char *romWord ;
int i ;

romWord = mbkalloc(autoSys->numberOut) ;
for(i = 0; i < autoSys->numberOut; i++)
	romWord[i] = '0' ;

locOut = (autoSys->state + label)->locOut ;
while(locOut)
	{
	romWord[autoSys->numberOut - (int)locOut->label - 1] = '1' ;	
	/*if(ATOM(locOut->abl) && (!strcmp(VALUE_ATOM(locOut->abl),"'0'") ||
					 !strcmp(VALUE_ATOM(locOut->abl),"'1'")))
		romWord[(int)locOut->label] = exprToChar(locOut->abl,1)[1] ;	
	else
		{
		printf("\tgiven FSM is not a MOORE FSM, ROM generation Impossible\n");
		exit(-1) ;
		}
		*/
	locOut = locOut->next ;
	}
return(romWord) ;
}
/*------------------------------------------------------------------------------
getRomAdr		: A partir d'un etat genere l'adresse de la ROM .
				  Il y a une bijection entre l'adresse de la rome et le code
				  d'etat.
--------------------------------------------------------------
parametres		: label de l'etat .
--------------------------------------------------------------
return			: le adresse dans la ROM de l'etat.
------------------------------------------------------------------------------*/
char *getRomAdr(label)
int label ;
{
pCode code ;
char *romAdr ;
int i, m_size ;

m_size = NUMBER_BIT(autoSys->numberState) ;
romAdr = mbkalloc(m_size) ;
for(i = 0; i < m_size; i++)
	romAdr[i] = '0' ;

code = (autoSys->code + label) ;
for(i = 0; i < m_size ; i++)
	{
	if(bit[i] & code->code)
		romAdr[m_size - i - 1] = '1' ;
	}
return(romAdr) ;
}
/*------------------------------------------------------------------------------
driveVst		: Create a VST file to merge the ROM with Standard Cells bloc
				  for a rom implementation of FSM.
--------------------------------------------------------------
parametres		: rien .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
driveVst(romName)
char *romName ;
{
int i,j; 
FILE *fic;
char fName[80];
char name[80] ;
char *romWord, *romAdr, *getRomWord(), *getRomAdr() ;
char **input ;
char *pt2us() ;
pOut out ;
int len ;

strcpy(name,autoSys->name);
strcat(name,"g") ;
strcpy(fName,name);
strcat(fName,".vst") ;

if(!(fic = fopen(fName,"w")))
	{
	printf("SYF : fopen impossible\n");
	exit(-1);
	} 

fprintf(fic,"-- VST description generated by SYF\n");
fprintf(fic,"-- Merges the ROM with Trnsition Standard Cells bloc\n");
fprintf(fic,"\nENTITY %s IS\n", name);

fprintf(fic,"	PORT(\n");

input = autoSys->input + autoSys->numberIn -1 ;
for(i = 0; i < autoSys->numberIn; i++)
	{
  	if(existOut(*input) == -1)/* sinon bidirectionnel */
		fprintf(fic,"		%s	: IN BIT ;\n",pt2us(*input));
	input--;
	}

out = autoSys->out + autoSys->numberOut -1;
for(i = 0; i < autoSys->numberOut; i++)
  {
  if(existName(autoSys->input,autoSys->numberIn,out->name))/* bidirectionnel */
	fprintf(fic,"		%s	: INOUT BIT ;\n",pt2us(out->name));
  else
	fprintf(fic,"		%s	: OUT BIT ;\n",pt2us(out->name));
  out--;
  }

fprintf(fic,"		vdd	: IN BIT ;\n");
fprintf(fic,"		vss	: IN BIT) ;\n");

fprintf(fic,"END %s ;\n\n", name);

fprintf(fic,"ARCHITECTURE dataflow OF %s IS\n\n", name);

fprintf(fic,"	SIGNAL local_adr	: BIT_VECTOR(%d DOWNTO 0) ;\n\n",NUMBER_BIT(autoSys->numberState)-1);

fprintf(fic,"COMPONENT %s\n",romName);
fprintf(fic,"	PORT(\n");
fprintf(fic,"		%s	: IN BIT ;\n",autoSys->horloge);

fprintf(fic,"		adr	: IN BIT_VECTOR(%d DOWNTO 0);\n",NUMBER_BIT(autoSys->numberState) -1);
fprintf(fic,"		f	: OUT BIT_VECTOR(%d DOWNTO 0);\n",autoSys->numberOut-1);

fprintf(fic,"		vdd	: IN BIT ;\n");
fprintf(fic,"		vss	: IN BIT) ;\n");

fprintf(fic,"END COMPONENT ;\n\n");

fprintf(fic,"COMPONENT %s\n",autoSys->name);
fprintf(fic,"	PORT(\n");

input = autoSys->input + autoSys->numberIn -1 ;
for(i = 0; i < autoSys->numberIn; i++)
	{
  	if(existOut(*input) == -1)/* sinon bidirectionnel */
		fprintf(fic,"		%s	: IN BIT ;\n",*input);
	else
		fprintf(fic,"		%s	: INOUT BIT ;\n",*input);
	input--;
	}
fprintf(fic,"		adr	: OUT BIT_VECTOR(%d DOWNTO 0);\n",NUMBER_BIT(autoSys->numberState) -1);

fprintf(fic,"		vdd	: IN BIT ;\n");
fprintf(fic,"		vss	: IN BIT) ;\n");

fprintf(fic,"END COMPONENT ;\n\n");

fprintf(fic,"BEGIN\n");

fprintf(fic,"	my_rom : %s\n",romName);
fprintf(fic,"	port map (\n");
fprintf(fic,"		%s => %s, adr => local_adr,\n",autoSys->horloge,autoSys->horloge);

out = autoSys->out + autoSys->numberOut - 1 ;
fprintf(fic,"		f(%d DOWNTO 0) =>\n",autoSys->numberOut-1);
for(i = 0; i < autoSys->numberOut -1; i++)
	{
	fprintf(fic,"			%s &\n",out->name);
	out--;
	}
	fprintf(fic,"			%s,\n",out->name);

fprintf(fic,"		vdd => vdd, vss => vss) ;\n\n");




fprintf(fic,"	my_sc : %s\n",autoSys->name);
fprintf(fic,"	port map (\n");
fprintf(fic,"		adr => local_adr,\n");
input = autoSys->input + autoSys->numberIn -1 ;
for(i = 0; i < autoSys->numberIn; i++)
	{
	fprintf(fic,"		%s => %s,\n",*input,*input);
	input--;
	}

fprintf(fic,"		vdd => vdd, vss => vss) ;\n");

fprintf(fic,"END ;\n");

printf("%s has been generated\n",fName) ;
}
/*------------------------------------------------------------------------------
driveVect		: ecrit des connecteurs sous la forme vectorielle
--------------------------------------------------------------
parametres		: fic .
--------------------------------------------------------------
return			: rien .
------------------------------------------------------------------------------*/
void driveVect (fp,tabName)
FILE         *fp;
char **tabName ;
{
char **pName ;
int           oldred;			/* previous value of redvar	*/
char          oldname [ 256];		/* previous root name		*/
int           left  ;			/* the left  bound of an array	*/
int           right ;			/* the right bound of an array	*/
int           i = 0 ;
char          name    [ 256];		/* current register's root name	*/
int           indx  ;			/* current register's index	*/
char         *direc ;			/* array's direction		*/
int           redvar;			/* = 2 if (name + index)	*/

pName = tabName ;

oldred = sscanf (*pName, "%s %d", oldname, &left);

strcpy (name, oldname);
redvar    = oldred;
right     = left;

i++;
pName++ ;

while (i < autoSys->numberIn)
    {
    redvar = sscanf (*pName, "%s %d", name, &indx);

    if (!strcmp (name, oldname))
      right = indx;

    else
      {
      if (oldred == 1)
        fprintf (fp, "		%s	: IN BIT ;\n", oldname);
      else
        {
        if (left < right)
          direc = "to";
        else
          direc = "downto";
        fprintf (fp, "		%s	: IN BIT_VECTOR(%d %s %d) ;\n", oldname, left, 
													direc, right);
        }
      i      = 0;
      left   = indx;
      oldred = redvar;
      strcpy (oldname, name);
      }
    i++;
    pName++ ;
    }
}
/*------------------------------------------------------------------------------
pt2us		: transforme les points par '_' dans une chaine de char
--------------------------------------------------------------
parametres		: name .
--------------------------------------------------------------
return			: newName .
------------------------------------------------------------------------------*/
char *pt2us(name)
char *name ;
{
char *newName ;
int len, i ;

len = strlen(name) ;
newName = name ;

for(i = 0 ; i < len; i++)
	if(!strncmp(newName+i,".",1))
		newName[i] = '_' ;

newName = namealloc(newName) ;
return(newName) ;
}
