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

#include  <genlib.h>

#include   DUT_H
#include  "dplimits.h"
#include  "nor3.h"


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


/* Module internal constants. */
#define        E_NOR3_WIDTH         2
#define        E_NOR3_SLICE         3
#define        E_NOR3_DRIVE         4
#define        E_NOR3_NOVIEW        5
#define        E_NOR3_OPENVBE       6
#define        E_NOR3_MODELNAME     7


/* Names of nor3 leaf cells. */
static char *TablLeafCellNor3[2] = {  "no3_fp",
									 "nop3_fp" };


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

/* Internal functions of module. */
static       void  Dgn_ErrorNor3();
static       void  Dgn_VhdlNor3();
static       void  Dgn_NetlistNor3();


/*  Function  :  'Dgn_DispatchNor3'                               */
/* -------------------------------------------------------------- */
/*  Interface of nor3 generator.                                  */

extern char *Dgn_DispatchNor3(nor3_modelname,
							  nor3_width    ,
							  nor3_slice    ,
							  nor3_drive    ,
							  nor3_msb0     ,
							  nor3_vhdl     ,
							  nor3_netlist  ,
							  nor3_icon     )
	char *nor3_modelname;  /* Model name.                    */
	long  nor3_width;      /* Bus wide.                      */
	long  nor3_slice;      /* LSB starting slice.            */
	long  nor3_drive;      /* Output drive capacity.         */
	long  nor3_msb0;       /* Zero as MSB index.             */
	long  nor3_vhdl;       /* Generation of behavioral view. */
	long  nor3_netlist;    /* Generation of netlist view.    */
	long  nor3_icon;       /* Generation of icon.            */
{
	static short  DispachNor3_FirstCall = FALSE;
	static  char  ModelName[C_SUPP_MBKSZNAME];

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

	/* Check if, at least, one view is asked. */
	if (   (nor3_netlist == FALSE)
		 &&(nor3_vhdl    == FALSE)
		 &&(nor3_icon    == FALSE) )
		Dut_PrintError( E_NOR3_ERROR, E_NOR3_NOVIEW);

	/* Check the bus wide. */
	if ((nor3_width < 1) || (nor3_width > DP_WIDTH))
		Dut_PrintError( E_NOR3_ERROR, E_NOR3_WIDTH, nor3_width);

	/* Check the output drive capacity. */
	if ((nor3_drive < 1) || (nor3_drive > C_NOR3_NBDRIVE))
		Dut_PrintError( E_NOR3_ERROR, E_NOR3_DRIVE, nor3_drive);

	/* Check the LSB starting slice. */
	if ((nor3_slice < 0) || ( nor3_slice
							 +nor3_width > DP_WIDTH))
		Dut_PrintError( E_NOR3_ERROR, E_NOR3_SLICE, nor3_slice);

	/* Check the model name. */
	if (nor3_modelname == (char*)NULL)
#ifndef  CRUNCH_FILENAME
		/* Build a more explicit model name. */
		(void*)sprintf( ModelName, "nor3_%ldx%ldx%ldx%ld%c_cl",
					                   DP_WIDTH              ,
					                 nor3_width              ,
					                 nor3_slice              ,
					                 nor3_drive              ,
					               ((nor3_msb0 ) ? 'm' : 'l'));
#else
		/* Build the crunched model name. */
		strcpy( ModelName, Dut_MakeCrunchModelName(
									    "od"       ,
								   8L,   DP_WIDTH-1,
								   8L, nor3_width-1,
								   8L, nor3_slice  ,
								   8L, nor3_drive  ,
								   0L, nor3_msb0   ));
#endif
	else
		strcpy( ModelName, nor3_modelname);


	/* Generation of behaviorial view. */
	if (nor3_vhdl)
		Dgn_VhdlNor3( ModelName,
			   		  nor3_width,
					  nor3_slice,
			   		  nor3_drive,
			   		  nor3_msb0 );

	/* Generation of netlist view. */
	if (nor3_netlist)
		Dgn_NetlistNor3( ModelName,
						 nor3_width,
						 nor3_slice,
					     nor3_drive,
						 nor3_msb0 );

	/* Generation of icone. */
	/* if (nor3_icon) */
	
	/* Return name of the generated model. */
	return((nor3_modelname == (char*)NULL) ?      ModelName 
		                                   : nor3_modelname);
}


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

static void  Dgn_ErrorNor3()
{
	Dut_AddError( E_NOR3_ERROR, E_NOR3_WIDTH,
				  "invalid bus width : %ld.");
	Dut_AddError( E_NOR3_ERROR, E_NOR3_SLICE,
				  "invalid LSB starting slice : %ld.");
	Dut_AddError( E_NOR3_ERROR, E_NOR3_DRIVE,
				  "invalid output drive : %ld.");
	Dut_AddError( E_NOR3_ERROR, E_NOR3_MODELNAME,
				  "Missing model name.");
	Dut_AddError( E_NOR3_ERROR, E_NOR3_NOVIEW,
				  "No view to generate.");
	Dut_AddError( E_NOR3_ERROR, E_NOR3_OPENVBE,
				  "Unable to create file : \"%s\".");
}


/*  Function  :  'Dgn_NetListNor3'                                */
/* -------------------------------------------------------------- */
/*  Generation of nor3 behavioral view.                           */

static void  Dgn_VhdlNor3(nor3_modelname,
					      nor3_width    ,
					      nor3_slice    ,
					      nor3_drive    ,
						  nor3_msb0     )
	char *nor3_modelname;  /* Nom du modele.           */
	long  nor3_width;      /* Largeur du bus.          */
	long  nor3_slice;      /* LSB starting slice.      */
	long  nor3_drive;      /* Output drive power.      */
	long  nor3_msb0;       /* Zero comme index du MSB. */
{
	FILE *Nor3File;
	long  BitIndex,     LenString,      TmpTime;
	char  BusWide[256], TmpString[256];

	/* *** Creating the file holding behavioral view. *** */
	if ((Nor3File=mbkfopen(nor3_modelname,
						            "vbe",
						       WRITE_TEXT)) == (FILE*)NULL)
		Dut_PrintError( E_NOR3_ERROR, E_NOR3_OPENVBE,
					                  nor3_modelname);

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

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

	/* Print name of the generated file. */
	sprintf( TmpString, "\"%s.vbe\"."           , nor3_modelname);
    fprintf( Nor3File , "-- # File : %-55s  #\n",     TmpString);
	fprintf( Nor3File ,
"-- #                                                                 #\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( Nor3File , "-- #           Date : %-45s  #\n", TmpString);

	/* Give the call used to generate the model. */
	sprintf(  TmpString, "\"nor3g %ld %ld %ld %ld%s -vhdl -o %s\"" ,
			                         DP_WIDTH                      ,
			                       nor3_width                      ,
			                       nor3_slice                      ,
			                       nor3_drive                      ,
			                      (nor3_msb0     ) ? " -msb0"  : "",
			                       nor3_modelname                  );
    fprintf( Nor3File , "-- # Generator Call : %-45s  #\n", TmpString);

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


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


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

	/* Terminals of data buses. */
	fprintf( Nor3File, "%14s :  in BIT_VECTOR%s;\n", "i0", BusWide);
	fprintf( Nor3File, "%14s :  in BIT_VECTOR%s;\n", "i1", BusWide);
	fprintf( Nor3File, "%14s :  in BIT_VECTOR%s;\n", "i2", BusWide);
	fprintf( Nor3File, "%14s : out BIT_VECTOR%s;\n",  "o", BusWide);

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

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


	/* *** Behavioral view *** */
	fprintf( Nor3File, "ARCHITECTURE behaviour_data_flow OF %s IS\n\n",
			                                            nor3_modelname);
	fprintf( Nor3File, "BEGIN\n\n");
	fprintf( Nor3File, "\to%s <= not (i0%s or i1%s or i2%s);\n\n" , BusWide,
			                                                BusWide,
			                                                BusWide,
			                                                BusWide);

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

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

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

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


/*  Function  :  'Dgn_NetListNor3'                                */
/* -------------------------------------------------------------- */
/*  Generation of nor3erter/buffer netlist view.                  */

static void  Dgn_NetlistNor3(nor3_modelname,
						     nor3_width    ,
						     nor3_slice    ,
							 nor3_drive    ,
						     nor3_msb0     )
	char *nor3_modelname;  /* Model name.            */
	long  nor3_width;      /* Bus wide.              */
	long  nor3_slice;      /* LSB starting slice.    */
	long  nor3_drive;      /* Output drive capacity. */
	long  nor3_msb0;       /* Zero as MSB index.     */
{
	long       BusIndex;
	long  LeafCellIndex;

	char *LeafCellSliceName;
	char  LeafCellInstaName[C_SUPP_MBKSZNAME];

	char  BusNameI0[C_SUPP_MBKSZNAME];
	char  BusNameI1[C_SUPP_MBKSZNAME];
	char  BusNameI2[C_SUPP_MBKSZNAME];
	char  BusNameO[ C_SUPP_MBKSZNAME];
	char  PinNameI0[C_SUPP_MBKSZNAME];
	char  PinNameI1[C_SUPP_MBKSZNAME];
	char  PinNameI2[C_SUPP_MBKSZNAME];
	char  PinNameO[ C_SUPP_MBKSZNAME];


	/* Select name of the leaf cell model. */
	/* (according to output drive power)   */
	LeafCellSliceName = TablLeafCellNor3[nor3_drive-1];

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

	/* Name of data bus terminals. */
	if (!nor3_msb0)
	{
		sprintf( BusNameI0,"i0[%ld:%ld]", nor3_width-1+nor3_slice, nor3_slice);
		sprintf( BusNameI1,"i1[%ld:%ld]", nor3_width-1+nor3_slice, nor3_slice);
		sprintf( BusNameI2,"i2[%ld:%ld]", nor3_width-1+nor3_slice, nor3_slice);
		sprintf( BusNameO , "o[%ld:%ld]", nor3_width-1+nor3_slice, nor3_slice);
	}
	else
	{
		sprintf( BusNameI0,"i0[%ld:%ld]", DP_WIDTH-nor3_slice
				                                  -nor3_width  ,
				                          DP_WIDTH-nor3_slice-1);
		sprintf( BusNameI1,"i1[%ld:%ld]", DP_WIDTH-nor3_slice
				                                  -nor3_width  ,
				                          DP_WIDTH-nor3_slice-1);
		sprintf( BusNameI2,"i2[%ld:%ld]", DP_WIDTH-nor3_slice
				                                  -nor3_width  ,
				                          DP_WIDTH-nor3_slice-1);
		sprintf( BusNameO , "o[%ld:%ld]", DP_WIDTH-nor3_slice
				                                  -nor3_width  ,
				                          DP_WIDTH-nor3_slice-1);
	}

 
	/* Creation of figure terminals. */
	/* **** Control terminals **** */
	LOCON( BusNameI0, IN   , BusNameI0);
	LOCON( BusNameI1, IN   , BusNameI1);
	LOCON( BusNameI2, IN   , BusNameI2);
	LOCON( BusNameO ,   OUT, BusNameO );

	/* **** Data bus terminals **** */
	LOCON(     "vdd", INOUT,     "vdd"); 
	LOCON(     "vss", INOUT,     "vss"); 
	
	
	/* Creation of leaf cells instances. */
	/* ("normals" cells of column)       */
	for( LeafCellIndex=nor3_slice;
		 LeafCellIndex<nor3_slice+nor3_width; LeafCellIndex++)
	{
		/* Build leaf cell name. */
		sprintf( LeafCellInstaName, "nor3_%ld", LeafCellIndex);
		
		/* Compute terminal index. */
		if (!nor3_msb0) BusIndex =              LeafCellIndex;
		else            BusIndex = DP_WIDTH -1 -LeafCellIndex;

		/* Build signals names. */
		sprintf( PinNameI0, "i0[%ld]", BusIndex);
		sprintf( PinNameI1, "i1[%ld]", BusIndex);
		sprintf( PinNameI2, "i2[%ld]", BusIndex);
		sprintf( PinNameO ,  "o[%ld]", BusIndex);

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

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