/***
*   ERIC CHABOD
*   ANTOINE MARTIN
*   D.E.A. M.E.M.I. 1992
*
*   Laurent WINCKEL
*
*   PROJET BSG : Barrel Shifter Generator
*
*   NOM:     bsg_vhdl.c
*   VERSION: 2.00
*	DATE:	 (03/12/1993)
*   OBJET:   generation du comportemental.
*/

static char *vhdl_ident="@(#)(BSG) vhdl view generation, version 2.00 (03/12/1993)";

/*******************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*******************************************************************/

/***
*	variables globales
*/

/* fichier de sortie */
static FILE *out_h;

/***
*	fonction donnant l'index d'un signal en tenant compte de l'option "msb0".
*/

static long index_signal( msb0, number, last_index )
long msb0, number, last_index;
{
if ( msb0 )
	return(number);
else
    return(last_index-number);
}

/***
*	ecrituture du port et de l'en-tete
*/
static void mk_port( msb0 )
long msb0;
{
	fprintf( out_h, "-- BEHAVIORAL DESCRIPTION OF BARRELL SHIFTER\n" );
	fprintf( out_h, "-- GENERATED WITH BSG \n" );
	fprintf( out_h, "-- MADE BY ERIC CHABOD & ANTOINE MARTIN FOR MASI (1992).\n\n\n" );

	fprintf( out_h, "--\n-- PORT DECLARATION\n--\n" );

	fprintf( out_h, "ENTITY %s IS\n", name );
        fprintf( out_h, "     PORT(\n");
	fprintf( out_h, "              in_s      :    IN    BIT_VECTOR( %d %s %d );\n",
			index_signal( msb0, 0, ad_size),
			msb0 ? "to" : "downto",
			index_signal( msb0, ad_size, ad_size) );
    fprintf( out_h, "              left      :    IN    BIT;\n");
    fprintf( out_h, "              rot       :    IN    BIT;\n");
    fprintf( out_h, "              ext       :    IN    BIT;\n");
    fprintf( out_h, "              in_d      :    IN    BIT_VECTOR( %d %s %d );\n",
			index_signal( msb0, 0, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, size, size) );
	fprintf( out_h, "              out_d     :    OUT   BIT_VECTOR( %d %s %d )",
			index_signal( msb0, 0, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, size, size) );

	/***
	*	alimentations
	*/
#ifdef PUT_ALIM
	fprintf( out_h, ";\n              vdd       :    IN    BIT" );
	fprintf( out_h, ";\n              vss       :    IN    BIT" );
#endif

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

/***
*	fonction qui renvoie dans une chaine 
*	une valeur convertie en binaire vhdl
*	on suppose qu'il y a assez de place dans le buffer.
*	attention!!! le nombre de bits effectifs est n+1!!!
*/
static char *itob( s, n, val )
char *s;
long n, val;
{
	long bit;
	int i;

	strcpy( s, "B\"" );

	for( i = n; i >= 0; i-- )
	{
		bit = (val >> i ) & 1;
		strcat( s, ( (bit)?  "1" : "0" ) );
	}

	strcat( s, "\"" );

	return (s);
}

/***
*	fonction qui duplique une chaine de caracteres un certain nombre de fois
*	ajoute aussi &
*/
static char *dupbit( buff, s, n )
char *buff, *s;
long n;
{
	strcpy( buff, s );

	for( ; n > 0; n-- )
	{
		strcat( buff, "&" );
		strcat( buff, s );
	}

	return buff;
}

/***
*	ecriture du corps 
*/
static void mk_body( msb0 )
long msb0;
{
	int i;
	char buff[255], zbuff[1000], cbuff[1000];


	fprintf( out_h, "--\n-- BEHAVORAL DESCRIPTION \n--\n" );

	fprintf( out_h, "ARCHITECTURE BEHAVIOUR OF %s IS\n", name );
	fprintf( out_h, "     SIGNAL  lsl    :    BIT_VECTOR( 0 to %d );\n", size );
	fprintf( out_h, "     SIGNAL  lsr    :    BIT_VECTOR( 0 to %d );\n", size );
	fprintf( out_h, "     SIGNAL  asr    :    BIT_VECTOR( 0 to %d );\n", size );
	fprintf( out_h, "     SIGNAL  rol    :    BIT_VECTOR( 0 to %d );\n", size );
	fprintf( out_h, "     SIGNAL  ror    :    BIT_VECTOR( 0 to %d );\n\n", size );
	fprintf( out_h, "BEGIN\n\n\n" );


	/***
	*	generation des asserts pour les alim
	*/
#ifdef PUT_ALIM
	fprintf( out_h, "--\n-- ASSERTS GENERATION FOR POWER SUPPLY\n--\n" );

	fprintf( out_h, "      ASSERT ( vdd = '1' )\n" );
	fprintf( out_h, "      REPORT \"POWER VDD IS MISSING.\"\n" );
	fprintf( out_h, "      SEVERITY WARNING;\n\n" );

	fprintf( out_h, "      ASSERT ( vss = '0' )\n" );
	fprintf( out_h, "      REPORT \"GROUND VSS IS MISSING.\"\n" );
	fprintf( out_h, "      SEVERITY WARNING;\n\n" );
#endif

	/***
	*	generation des asserts eventuels
	*/
	if ( size + 1 != r_size )
		fprintf( out_h, "--\n-- ASSERTS GENERATION FOR ADDRESS\n--\n" );
	for( i = size + 1; i < r_size ; i++ )
	{
		fprintf( out_h, "      ASSERT ( in_s /= %s )\n", itob( buff, ad_size, i ) );
		fprintf( out_h, "      REPORT \"SHIFT NUMBER OUT OF RANGE.\"\n" );
		fprintf( out_h, "      SEVERITY WARNING;\n" );
	}

	/***
	*	generation du code pour lsl 
	*/
	fprintf( out_h, "--\n-- LEFT SHIFT GENERATION\n--\n" );

	fprintf( out_h, "     WITH ( in_s ) SELECT\n" );
	fprintf( out_h,	"          lsl   <=  in_d WHEN %s,\n", itob( buff, ad_size, 0 ) );

	for ( i = 1; i < size; i++ )
		fprintf( out_h, "                    in_d( %d %s %d )&%s WHEN %s,\n",
				index_signal( msb0, i, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size, size),
				itob( zbuff, i - 1, 0 ), itob( buff, 	ad_size, i ) );

	fprintf( out_h, "                    in_d( %d )&%s WHEN %s,\n",
			index_signal( msb0, size, size), 
			itob( zbuff, size - 1, 0 ), itob( buff, ad_size, size ) );

	fprintf( out_h, "                    %s WHEN OTHERS;\n\n\n\n", itob( zbuff, size, 0 ) );



	/*** 
	*	generation du code pour lsr 
	*/
	fprintf( out_h, "--\n-- RIGHT LOGICAL SHIFT GENERATION\n--\n" );

	fprintf( out_h, "     WITH ( in_s ) SELECT\n" );
	fprintf( out_h,	"          lsr   <=  in_d WHEN %s,\n", itob( buff, ad_size, 0 ) );

	for ( i = 1; i < size; i++ )
		fprintf( out_h, "                    %s&in_d( %d %s %d ) WHEN %s,\n",
				itob( zbuff, i - 1, 0 ),
				index_signal( msb0, 0, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size - i, size),
				itob( buff, ad_size, i ) );

	fprintf( out_h, "                    %s&in_d( %d ) WHEN %s,\n",
			itob( zbuff, size - 1, 0 ), 
			index_signal( msb0, 0, size), 
			itob( buff, ad_size, size ) );

	fprintf( out_h, "                    %s WHEN OTHERS;\n\n\n\n", itob( zbuff, size, 0 ) );


	/*** 
	*	generation du code pour asr 
	*/
	fprintf( out_h, "--\n-- RIGHT ARITHMETICAL SHIFT GENERATION\n--\n" );

	fprintf( out_h, "     WITH ( in_s ) SELECT\n" );
	fprintf( out_h,	"          asr   <=  in_d WHEN %s,\n", itob( buff, ad_size, 0 ) );

	for ( i = 1; i < size; i++ )
		fprintf( out_h, "                    %s&in_d( %d %s %d ) WHEN %s,\n",
				dupbit( cbuff, NAME("in_d( %d )", index_signal( msb0, 0, size)), i - 1 ),
				index_signal( msb0, 0, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size - i, size),
				itob( buff, ad_size, i ) );

	fprintf( out_h, "                    %s&in_d( %d ) WHEN %s,\n",  
			dupbit( zbuff, NAME("in_d( %d )", index_signal( msb0, 0, size)), size - 1 ), 
			index_signal( msb0, 0, size), 
			itob( buff, ad_size, size ) );

	fprintf( out_h, "                    %s WHEN OTHERS;\n\n\n\n", itob( zbuff, size, 0 ) );


	/***
	*	generation du code pour rol 
	*/
	fprintf( out_h, "--\n-- LEFT ROTATION GENERATION\n--\n" );

	fprintf( out_h, "     WITH ( in_s ) SELECT\n" );
	fprintf( out_h,	"          rol   <=  in_d WHEN %s,\n", itob( buff, ad_size, 0 ) );

	fprintf( out_h,	"                    in_d( %d %s %d )& in_d( %d ) WHEN %s,\n", 	
			index_signal( msb0, 1, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, size, size),
			index_signal( msb0, 0, size),
			itob( buff, ad_size, 1 ) );

	for ( i = 2; i < size; i++ )
		fprintf( out_h, "                    in_d( %d %s %d )&in_d( %d %s %d ) WHEN %s,\n",
				index_signal( msb0, i, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size, size),
				index_signal( msb0, 0, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, i - 1, size),
				itob( buff, ad_size, i ) );

	fprintf( out_h, "                    in_d( %d )&in_d( %d %s %d ) WHEN %s,\n", 	
			index_signal( msb0, size, size),
			index_signal( msb0, 0, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, i - 1, size),
			itob( buff, ad_size, size ) );

	fprintf( out_h, "                    %s WHEN OTHERS;\n\n\n\n", itob( zbuff, size, 0 ) );


	/***
	*	generation du code pour ror 
	*/
	fprintf( out_h, "--\n-- RIGHT ROTATION GENERATION\n--\n" );

	fprintf( out_h, "     WITH ( in_s ) SELECT\n" );
	fprintf( out_h,	"          ror   <=  in_d WHEN %s,\n", itob( buff, ad_size, 0 ) );

	fprintf( out_h,	"                    in_d( %d )& in_d( %d %s %d ) WHEN %s,\n",
			index_signal( msb0, size, size),
			index_signal( msb0, 0, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, size - 1, size),
			itob( buff, ad_size, 1 ) );

	for ( i = 2; i < size; i++ )
		fprintf( out_h, "                    in_d( %d %s %d )&in_d( %d %s %d ) WHEN %s,\n",
				index_signal( msb0, size + 1 - i, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size, size),
				index_signal( msb0, 0, size),
				msb0 ? "to" : "downto",
				index_signal( msb0, size - i, size),
				itob( buff, ad_size, i ) );

	fprintf( out_h, "                    in_d( %d %s %d )&in_d( %d ) WHEN %s,\n",
			index_signal( msb0, 1, size),
			msb0 ? "to" : "downto",
			index_signal( msb0, size, size),
			index_signal( msb0, 0, size),
			itob( buff, ad_size, size ) );

	fprintf( out_h, "                    %s WHEN OTHERS;\n\n\n\n", itob( zbuff, size, 0 ) );

	/***
	*	generation de la fin
	*/
	fprintf( out_h, "--\n-- OUTPUT SELECTION\n--\n" );

	fprintf( out_h, "     WITH ( left&ext&rot ) SELECT\n" );
	fprintf( out_h, "          out_d <= lsr WHEN B\"000\",\n" );
	fprintf( out_h, "                   asr WHEN B\"010\",\n" );
	fprintf( out_h, "                   lsl WHEN B\"100\",\n" );
	fprintf( out_h, "                   lsl WHEN B\"110\",\n" );
	fprintf( out_h, "                   ror WHEN B\"001\",\n" );
	fprintf( out_h, "                   ror WHEN B\"011\",\n" );
	fprintf( out_h, "                   rol WHEN B\"101\",\n" );
	fprintf( out_h, "                   rol WHEN B\"111\";\n\n\n\n" );
	fprintf( out_h, "END BEHAVIOUR;\n\n\n\n" );

}

static void gen_vbe( msb0 )
long msb0;
{
	/* ouverture du fichier de sortie */
	out_h = mbkfopen( name, "vbe", "w" );

	if ( out_h == NULL )
		bsg_argh( 2 );
	
	mk_port( msb0 );
	mk_body( msb0 );

	fclose( out_h );
/*
	printf( "Behaviour generated...\n");
*/
}
