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

#include  <genlib.h>

#include   DUT_H
#include  "dplimits.h"
#include  "const.h"


/*      Alliance CAD System 2.0                                   */
/*        FITPATH Package 0.0                                     */
/*                                                                */
/*  Author  :      Jean-Paul CHAPUT                               */
/*  E-mail  :  cao-vlsi@masi.ibp.fr                               */
/* ************************************************************** */
/*  module  :  "const.c"                                       */


/* Module internal constants. */
#define        E_CONST_WIDTH         2
#define        E_CONST_SLICE         3
#define        E_CONST_NOVIEW        4
#define        E_CONST_OPENVBE       5
#define        E_CONST_MODELNAME     6


/* Names of tristate leaf cells. */
static char *TablLeafCellConst[3] = { "zero_dp",
									   "one_dp"};


/* Interface function of module.
   extern       char *Dgn_DispachConst();
   */

/* Internal functions of module. */
static       void  Dgn_ErrorConst();
static       void  Dgn_VhdlConst();
static       void  Dgn_NetlistConst();


/*  Function  :  'Dgn_DispatchConst'                              */
/* -------------------------------------------------------------- */
/*  Interface of constants generator.                             */

extern char *Dgn_DispatchConst(const_modelname,
							   const_width    ,
							   const_slice    ,
							   const_xlcons   ,
							   const_msb0     ,
							   const_vhdl     ,
							   const_netlist  ,
							   const_icon     )
	char *const_modelname;  /* Model name.                    */
	long  const_width;      /* Bus wide.                      */
	long  const_slice;      /* LSB starting slice.            */
	long *const_xlcons;     /* Constant to generate.          */
	long  const_msb0;       /* Zero as MSB index.             */
	long  const_vhdl;       /* Generation of behavioral view. */
	long  const_netlist;    /* Generation of netlist view.    */
	long  const_icon;       /* Generation of icon.            */
{
	static short  DispachConst_FirstCall = FALSE;
	static  char  ModelName[C_SUPP_MBKSZNAME];

	/* The first time the generator is call : */
	/*     - Load specific errors.            */
	if (!DispachConst_FirstCall)
	{
		Dgn_ErrorConst();
		DispachConst_FirstCall = TRUE;
	}

	/* Check if, at least, one view is asked. */
	if (   (const_netlist == FALSE)
		 &&(const_vhdl    == FALSE)
		 &&(const_icon    == FALSE) )
		Dut_PrintError( E_CONST_ERROR, E_CONST_NOVIEW);

	/* Check the bus wide. */
	if ((const_width < 1) || (const_width > DP_WIDTH))
		Dut_PrintError( E_CONST_ERROR, E_CONST_WIDTH, const_width);

	/* Check the LSB starting slice. */
	if ((const_slice < 0) || (const_slice+const_width > DP_WIDTH))
		Dut_PrintError( E_CONST_ERROR, E_CONST_SLICE, const_slice);

	/* Check the model name. */
	if (const_modelname == (char*)NULL)
		/* Build a more explicit model name. */
		(void*)sprintf( ModelName, "nor2m%s_%ldx%ldx%ld%c_cl"   ,
					    Dut_XlToStr(const_xlcons,
									   DP_WIDTH ,
							 C_SUPP_BaseHexadecimal)            ,
					                      DP_WIDTH              ,
					                const_width              ,
					                const_slice              ,
					              ((const_msb0 ) ? 'm' : 'l'));
	else
		strcpy( ModelName, const_modelname);

	/* Generation of behaviorial view. */
	if (const_vhdl)
		Dgn_VhdlConst( ModelName      ,
						  const_width ,
						  const_slice ,
						  const_xlcons,
						  const_msb0  );

	/* Generation of netlist view. */
	if (const_netlist)
		Dgn_NetlistConst( ModelName      ,
							 const_width ,
							 const_slice ,
							 const_xlcons,
							 const_msb0  );

	/* Generation of icon. */
	/* if (const_icon) */
	
	/* Return name of the generated model. */
	return((const_modelname == (char*)NULL) ?          ModelName 
		                                       : const_modelname);
}


/*  Function  :  'Dgn_ErrorConst'                              */
/* -------------------------------------------------------------- */
/*  Adds generator specific errors to the main errors data base.  */

static void  Dgn_ErrorConst()
{
	Dut_AddError( E_CONST_ERROR, E_CONST_WIDTH,
				  "invalid bus width : %ld.");
	Dut_AddError( E_CONST_ERROR, E_CONST_SLICE,
				  "invalid LSB starting slice : %ld.");
	Dut_AddError( E_CONST_ERROR, E_CONST_MODELNAME,
				  "Missing model name.");
	Dut_AddError( E_CONST_ERROR, E_CONST_NOVIEW,
				  "No view to generate.");
	Dut_AddError( E_CONST_ERROR, E_CONST_OPENVBE,
				  "Unable to create file : \"%s\".");
}


/*  Function  :  'Dgn_NetListConst'                           */
/* -------------------------------------------------------------- */
/*  Generation of NOR2 cotrollable cons behavioral view.         */

static void  Dgn_VhdlConst(const_modelname,
							  const_width    ,
							  const_slice    ,
							  const_xlcons   ,
							  const_msb0     )
	char *const_modelname;  /* Model name.         */
	long  const_width;      /* Bus width.          */
	long  const_slice;      /* LSB starting slice. */
	long *const_xlcons;     /* Cons to apply.      */
	long  const_msb0;       /* Zero as MSB index.  */
{
	FILE *ConstFile;
	long  BitIndex,     LenString,      TmpTime;
	char  BusWide[256], TmpString[256];

	/* *** Creating the file holding behavioral view. *** */
	if ((ConstFile=mbkfopen(const_modelname,
							                "vbe",
						               WRITE_TEXT)) == (FILE*)NULL)
		Dut_PrintError( E_CONST_ERROR, E_CONST_OPENVBE,
					                      const_modelname);


	/* *** Write an identification header *** */

	/* Standart begin of header. */
	fprintf( ConstFile, 
"-- ###-------------------------------------------------------------###\n"
			);
	fprintf( ConstFile, 
"-- #                                                                 #\n"
			);
	fprintf( ConstFile,
"-- #    Alliance CAD System 2.0                                      #\n"
			);
    fprintf( ConstFile,
"-- #      FITPATH Package 0.0                                        #\n"
			);
    fprintf( ConstFile,
"-- #                                                                 #\n"
			);
    fprintf( ConstFile,
"-- # Author :     Jean-Paul CHAPUT                                   #\n" 
			);
    fprintf( ConstFile,
"-- # E-mail : cao-vlsi@masi.ibp.fr                                   #\n"
			);
	fprintf( ConstFile, 
"-- # *************************************************************** #\n"
			);
	fprintf( ConstFile,
"-- #                                                                 #\n"
			);
    fprintf( ConstFile,
"-- # Generator : \"constg\" (constants generator)                      #\n"
			);
	fprintf( ConstFile, 
"-- # --------------------------------------------------------------- #\n"
			);

	/* Print name of the generated file. */
	fprintf( ConstFile, 
"-- # File  :                                                         #\n"
			);
	sprintf(      TmpString, "\"%s.vbe\"."   , const_modelname);
    fprintf( ConstFile  , "-- # %62s  #\n",          TmpString);
	fprintf( ConstFile  ,
"-- #                                                                 #\n"
			);

	/* Print date of generation. */
	TmpTime                = time((time_t*)NULL);
	sprintf( TmpString, "%s", asctime(localtime(&TmpTime)) );
	LenString              = strlen( TmpString);
	TmpString[LenString-1] = (char)0;
    fprintf( ConstFile, "-- #           Date : %-45s  #\n", TmpString);

	/* Give the call used to generate the model. */
	sprintf(  TmpString, "\"constg %ld %ld %ld",
			                      DP_WIDTH        ,
			                const_width        ,
			                const_slice        );
    fprintf( ConstFile  , "-- # Generator Call : %-45s  #\n", TmpString);
	sprintf(  TmpString, "%s%s -vhdl"                        ,
			  Dut_XlToStr(const_xlcons,
						  const_width ,
				   C_SUPP_BaseHexadecimal)                   ,
			             (const_msb0  ) ? " -msb0"  : ""  );
    fprintf( ConstFile  , "-- # %62s  #\n",          TmpString);
	sprintf(      TmpString, "-o %s\""       , const_modelname);
    fprintf( ConstFile  , "-- # %62s  #\n",          TmpString);

	fprintf( ConstFile, 
"-- ###-------------------------------------------------------------###\n"
			);


	/* Select terminals (and signals) bus indexation. */
	/* (depending to the flag "const_msb0")            */
	if (!const_msb0)
		sprintf( BusWide, "(%ld downto %ld)", const_width-1
				                             +const_slice  ,
				                              const_slice  );
	else
		sprintf( BusWide,     "(%ld to %ld)", DP_WIDTH-const_slice
				                                      -const_width  ,
				                              DP_WIDTH-const_slice-1);


	/* *** Interface description. *** */
	fprintf( ConstFile, "\nENTITY %s IS\n\tPORT(\n", const_modelname);

	/* Controls terminals. */

	/* Terminals of data consts. */
	fprintf( ConstFile, "%14s : out BIT_VECTOR%s;\n",  "o", BusWide);

	/* Supplies terminals. */
	fprintf( ConstFile, "%14s :  in BIT;\n", "vdd");
	fprintf( ConstFile, "%14s :  in BIT\n" , "vss");

	/* *** End of interface description *** */
	fprintf( ConstFile, "\t);\nEND %s;\n\n\n", const_modelname);


	/* *** Behavioral view *** */
	fprintf( ConstFile, "ARCHITECTURE behaviour_data_flow OF %s IS\n\n",
			                                            const_modelname);
	fprintf( ConstFile, "BEGIN\n\n");

	fprintf( ConstFile, "\to%s <= %s;\n\n" , BusWide,
			                 Dut_XlToStrVHDL(const_xlcons,const_width));

	/* Check supplies connections. */
	fprintf( ConstFile, "\t-- ****************>");
	fprintf( ConstFile, " Supplies Check "      );
	fprintf( ConstFile, "<****************\n\n" );

	fprintf( ConstFile, "\tASSERT ((vdd = '1') and (vss = '0'))\n");
	fprintf( ConstFile, "\t\tREPORT \"Power supply is missing on %s.\"\n",
			                                              const_modelname);
	fprintf( ConstFile, "\t\tSEVERITY WARNING;\n\n");

	/* *** End of behavioral view *** */
	fprintf( ConstFile, "END behaviour_data_flow;\n");

	/* *** Close the file holding the behavioral view *** */
	fclose( ConstFile);
}


/*  Fonction  :  'Dgn_NetListConst'                               */
/* -------------------------------------------------------------- */
/*  Generation of NOR2 cotrollable cons Netlist.                  */

static void  Dgn_NetlistConst(const_modelname,
								 const_width    ,
								 const_slice    ,
								 const_xlcons   ,
								 const_msb0     )
	char *const_modelname;  /* Model name.         */
	long  const_width;      /* Bus wide.           */
	long  const_slice;      /* LSB starting slice. */
	long *const_xlcons;     /* Cons to apply.      */
	long  const_msb0;       /* Zero as MSB index.  */
{
	long       BitNumber;
	long       BusIndex;
	long  LeafCellIndex;

	char *LeafCellSliceName;
	char  LeafCellInstaName[C_SUPP_MBKSZNAME];

	char  BusNameO[ C_SUPP_MBKSZNAME];
	char  PinNameO[ C_SUPP_MBKSZNAME];


	/* Creation of the new logical figure. */
	DEF_LOFIG( const_modelname);

	/* Name of data bus terminals. */
	if (!const_msb0)
		sprintf( BusNameO , "o[%ld:%ld]", const_width-1
				                         +const_slice  ,
				                          const_slice  );
	else
		sprintf( BusNameO , "o[%ld:%ld]", DP_WIDTH-const_slice
				                                  -const_width  ,
				                          DP_WIDTH-const_slice-1);
 
	/* Creation of figure terminals. */
	/* **** Control terminals **** */

	/* **** Data bus terminals **** */
	LOCON( BusNameO ,   OUT, BusNameO );

	/* **** Supply terminals **** */
	LOCON(     "vdd", INOUT,      "vdd"); 
	LOCON(     "vss", INOUT,      "vss"); 
	
	
	/* Creation of leaf cells instances. */
	/* ("normals" cells of column)       */
	for( LeafCellIndex=const_slice,BitNumber=const_width; 
		 LeafCellIndex<const_slice          +const_width;
		 LeafCellIndex++          ,BitNumber--          )
	{
	    /* Select the correct cons cells. */
	    LeafCellSliceName = TablLeafCellConst[
			Dut_XlGetBit(     const_xlcons,
		        LeafCellIndex-const_slice )];

		/* Build leaf cell name. */
		sprintf( LeafCellInstaName, "const_%ld", LeafCellIndex);
		
		/* Compute terminal index. */
		if (!const_msb0) BusIndex =              LeafCellIndex;
		else             BusIndex = DP_WIDTH -1 -LeafCellIndex;

		/* Build signals names. */
		sprintf( PinNameO ,  "o[%ld]", BusIndex);

		/* Leaf cell instanciation. */
		LOINS( LeafCellSliceName,
			   LeafCellInstaName,
				       PinNameO , "vdd", "vss", EOL);
	}

	/* Ends and write to disk the new figure. */
	SAVE_LOFIG();
}
