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

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

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

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

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

/* fonctions */
#define LSR	0
#define ASR	1
#define LSL1	2
#define LSL2	3
#define ROR1	4
#define ROR2	5
#define ROL1	6
#define ROL2	7

/* direction des signaux */
#define IN_DIR	0
#define OUT_DIR	1
#define NO_DIR	2

#if 0
/***
*	donnees fichier
*/
static FILE *out_h;
#endif

/***
*	entrees-sorties
*	nous sommes obliges d'implementer les entrees-sorties
*	en chaines de caracteres car nous ne connaissons pas
*	leur longeur effective
*/
static char in_d[255], out_d[255];
static long in_s, com;

/***
*	tailles et masque.
*/
static long psize, ad_psize, s_msk;

/***
*	pattern en cours
*/
static long n_pat;

/***
*	routine qui initialise une chaine avec un caractere
*/
static void wd_init( buff, c )
char *buff;
char c;
{
	memset( buff, c , psize );
	buff[psize] = '\0';
}

/***
*	fonctionnement du shifter pour un cycle
*/
static void cycle()
{
	in_s &= s_msk;


	switch ( com )
	{
		case LSL1:
		case LSL2:
			wd_init( out_d, '0' );
			if ( in_s < psize )
				memcpy( out_d, in_d + in_s, psize - in_s );
			break;
		case LSR:
			wd_init( out_d, '0' );
			if ( in_s < psize )
				memcpy( out_d + in_s, in_d, psize - in_s );
			break;
		case ASR:
			wd_init( out_d, in_d[0] );
			if ( in_s < psize )
				memcpy( out_d + in_s, in_d, psize - in_s );
			break;
		case ROL1:
		case ROL2:
			wd_init( out_d, '0' );
			if ( in_s < psize )
			{
				memcpy( out_d, in_d + in_s, psize - in_s );
				memcpy( out_d + psize - in_s, in_d, in_s );
			}
			break;
		case ROR1:
		case ROR2:
			wd_init( out_d, '0' );
			if ( in_s < psize )
			{
				memcpy( out_d, in_d + psize - in_s, in_s );
				memcpy( out_d + in_s, in_d, psize - in_s );
			}
			break;
	}
}

/***
*	procedure d'ecriture de l'entete du fichier de pattern
*/

static void aff_head( msb0 )
long msb0;
{
	/* en tete */
	fprintf( out_h, "--\n-- TEST PATTERNS FOR %d BIT BARREL SHIFTER.\n", psize );
	fprintf( out_h, "-- GENERATED WITH BSG.\n" );
	fprintf( out_h, "-- MADE BY ERIC CHABOD AND ANTOINE MARTIN FOR MASI (1992).\n--\n\n" );

if (msb0)
{
	fprintf( out_h, "IN\tin_d(0 to %d);\n", size );
	fprintf( out_h, "IN\tin_s(0 to %d);\n", ad_size  );
	fprintf( out_h, "OUT\tout_d(0 to %d);\n", size );
}
else
{
	fprintf( out_h, "IN\tin_d(%d downto 0);\n", size );
	fprintf( out_h, "IN\tin_s(%d downto 0);\n", ad_size  );
	fprintf( out_h, "OUT\tout_d(%d downto 0);\n", size );
}

	fprintf( out_h, "IN\trot;\n" );
	fprintf( out_h, "IN\tleft;\n" );
	fprintf( out_h, "IN\text;\n" );

#ifdef PUT_ALIM
	fprintf( out_h, "IN\tvdd;\n" );
	fprintf( out_h, "IN\tvss;\n" );
#endif

	fprintf( out_h, "\n\n--\n-- PATTERN DESCIPTION:\n--\n\n" );
	fprintf( out_h, "begin\n\n" );

}

/***
*	fonction qui produit a partir d'une certaine donnee
*	une chaine de caracteres ASIMUT.
*/
static char *patstr( buff, n, val, dir )
char *buff, *val;
long n, dir;
{
	long i;

	switch ( dir )
	{
		case IN_DIR:
			memset( buff, ' ', n * 2 + 4 );
			buff[ n * 2 + 4 ] = '\0';
			for( i = 0; i < n; i++ )
				buff[ 2 * i ] = val[ i ];
			break;
		case OUT_DIR:
			memset( buff, ' ', n * 2 + 5 );
			buff[ n * 2 + 5 ] = '\0';
			buff[ 0 ] = '?';

			for( i = 0; i < n; i++ )
				buff[ 2 * i + 1 ] = ( val[ i ] == '0' )? '0' : '1';
			break;

		default:
			memset( buff, ' ', n * 2 + 4 );
			buff[ n * 2 + 4 ] = '\0';
			for( i = 0; i < n; i++ )
				buff[ 2 * i ] = '*';
			break;
	}

	return buff;
}

/***
*	routine qui cree une chaine asimut a partir d'un argument numerique
*/
static char *ipatstr( buff, n, val, dir )
char *buff;
long n, val, dir;
{
	int i;


	switch ( dir )
	{
		case IN_DIR:
			memset( buff, ' ', n * 2 + 4 );
			buff[ n * 2 + 4 ] = '\0';
			for( i = 0; i < n; i++ )
				buff[ 2 * i ] = ( ( (val >> (n - i - 1)) & 1) == 0)? '0' : '1';
			break;

		case OUT_DIR:
			memset( buff, ' ', n * 2 + 5 );
			buff[ n * 2 + 5 ] = '\0';
			buff[ 0 ] = '?';

			for( i = 0; i < n; i++ )
				buff[ 2 * i + 1 ] = ( ( (val >> (n - i - 1)) & 1) == 0)? '0' : '1';
			break;

		default:
			memset( buff, ' ', n * 2 + 4 );
			buff[ n * 2 + 4 ] = '\0';
			for( i = 0; i < n; i++ )
				buff[ 2 * i ] = '*';
			break;
	}

	return buff;
}

/***
*	routine qui affiche le pattern en cours
*	elle effectue le cycle en cours
*/
static void aff_pat()
{
	char buff[255];

	/* cycle */
	cycle();

	/* numero de pattern */
	fprintf( out_h, "p%d:\t", n_pat++ );

	fprintf( out_h, patstr( buff, psize, in_d, IN_DIR ) );
	fprintf( out_h, ipatstr( buff, ad_psize, in_s, IN_DIR ) );
	fprintf( out_h, patstr( buff, psize, out_d, OUT_DIR ) );
	fprintf( out_h, ipatstr( buff, 3, com, IN_DIR ) );

	/***
	* 	alimentations
	*/
#ifdef PUT_ALIM
	fprintf( out_h, "1 " ); 
	fprintf( out_h, "0 " ); 
#endif

	fprintf( out_h, ";\n" );
}

/***
*	routine qui reproduit dans in_d
*	une chaine de deux caracteres jusqu'a psize
*/

static void put_in( val )
char *val;
{
	long i;

	in_d[ psize ] = '\0';

	for ( i = 0; i < psize; i+=2 )
		strncpy( in_d + i, val, 2 );
}

/***
*	routine d'ecriture des patterns
*/

static void put_pat()
{
	long i,j;

	j = ( psize < 8 )? 8 : psize;

	for( i = 0; i < j; i++ )
	{
		in_s = i % psize;
		com = i % 8;
		if ( i % 2 || com >= ROR1 )
			put_in( "10" );
		else
			put_in( "01" );

		aff_pat();
	}

	in_s = 1;
	com = ASR;
	put_in( "01" );
	aff_pat();

	fprintf( out_h, "\nEND;\n" );
}

/***
*	fonction globale
*/
static void gen_pat( msb0 )
long msb0;
{

	/* initialisations */
	n_pat = 0;
	psize = size + 1;
	ad_psize = ad_size + 1;
	
	s_msk = (1<<ad_psize) - 1;

	/* ouverture du fichier de sortie */
	out_h = mbkfopen( name, "pat", "w" );
	if ( out_h == NULL )
		bsg_argh( 3 );

	aff_head( msb0 );
	put_pat();

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