#include <string.h>
#include <stdio.h>
#include "util.h"
#include "vpack.h"
#include "globals.h"
#include "read_vhdl.h"

/*------------------------------------------------------------
 *  Copyright 2002 By Kara K.W. Poon and Steve Wilton
 *
 * Permission to use, copy, and modify this software and its documentation is
 * hereby granted only under the following terms and conditions.  Both the
 * above copyright notice and this permission notice must appear in all copies
 * of the software, derivative works or modified versions, and any portions
 * thereof, and both notices must appear in supporting documentation.
 * Permission is granted ONLY for non-commercial use.  For
 * commercial use, please contact the authors.
 *
 * This software may be distributed (but not offered for sale or transferred
 * for compensation) to third parties, provided such third parties agree to
 * abide by the terms and conditions of this notice.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS, AS
 * WELL AS THE UNIVERSITY OF BRITISH COLUMBIA AND THE
 * UNIVERSITY OF TORONTO DISCLAIM ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL THE
 * AUTHORS OR THE UNIVERSITY OF BRITISH COLUMBIA OR THE
 * UNIVERSITY OF TORONTO BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *------------------------------------------------------------*/

/*
  T-Vpack was written by Vaughn Betz at the University of Toronto.
  
  May 2001   Modified by Dr. Steve Wilton at the University 
             of British Columbia to propagate signal 
             activities
  July 2001  Further modified by Kara Poon at the University 
             of British Columbia to propagate both
             static probability and transition density
 */
/*
  April 2007		Modified by Yu Chi Wai at the Imperial
					College of London to support adding 
					virtual embedded block (VEB) to the circuit
 */

/*
	Read VHDL consisting of basic library components
	LUT, FF, carry chain, IO buffer..
*/

#define TOKENS " \t\n"

static int last_lut_read;
static int previous_last_lut = -1;

static int *num_driver, *temp_num_pins;

/* # of .input, .output, .model and .end lines */
static int ilines, olines, model_lines, endlines;  
static struct hash_nets **hash;
static char *model;
static FILE *vhdl;
static char **block_name_list;
static int num_blocks_in_block_name_list;

static int num_dsp;  /* Used only for naming */
static int num_veb;  /* Used only for naming */
static int num_memory;

static int num_name_convert;
static struct oname_convert * oname;

static char ** saved_names;

void read_parse_until_begin (char *buf) ;
void get_tok(char *buffer, int pass, int doall, int *done, 
        int lut_size, char *inside_names_ptr);
void init_parse(int doall);
void init_block_name_list();
void free_parse (void);
void free_block_name_list();
void dum_parse (char *buf);

int hash_value (char *name);


void io_line(int in_or_out, int doall, char * blockname, char *net_name, int is_gnd, int is_vcc) ;
void add_block_name_to_block_name_list(char *name);
int add_net (char *ptr, int type, int bnum, int doall); 
void add_lut (int doall, int lut_size, int input_size, int output_size, enum block_types type, char * blockname );
void null_function(int blockno, int lut_size);
int get_index_in_block_name_list(char *name);
void add_latch (int doall, int lut_size,  enum block_types type, char* blockname);
void add_carry (int doall, int lut_size,  enum block_types type, char* blockname);
void add_internal (int doall, int lut_size,  enum block_types type, char* blockname);

void add_veb (int doall, int lut_size,  enum block_types type, char* blockname, char* veb_name);
void add_dsp (int doall, int lut_size,  enum block_types type, char* blockname, char* dsp_name);
void add_muxf (int doall, int lut_size,  enum block_types type, char* blockname);
int convert_ouput(char * netname);
/*

static void get_function_line(char *firsttoken, int lut_size);

static void check_net (int lut_size);

static void add_dsp (int doall);
static void add_veb (int doall);
static void add_memory(int doall);
static void add_carryout_to_line(int doall, int lut_size);


static char add_activity_to_net (char *ptr, 
				 float probability,
				 float density);




void read_activity(char *filename);
void convert2binary (int lut_size,
		     int decimal_number,
		     char* binary_string);

*/


void read_vhdl (char *vhdl_file, char *activity,int lut_size) {
 char buffer[BUFSIZE];
 int pass, done, doall;
 char inside_names;

int i;

printf("read_vhdl \n");
 vhdl = my_fopen (vhdl_file, "r", 0);

 last_lut_read = -1;

saved_names = malloc(sizeof(char*) * (MAXLUT));
for (i= 0; i < MAXLUT; i++)
{
	saved_names[i] = malloc(sizeof(char) * BUFSIZE);	
}


 for (doall=0;doall<=1;doall++) 
 {
    init_parse(doall);


/* Three passes to ensure inputs are first blocks, outputs second and    *
 * LUTs, FF, carry chain, internal logic.  Just makes the output netlist more readable. */

    for (pass=0;pass<=8;pass++) { 
//    for (pass=0;pass<=2;pass++) { 

       inside_names = 0;
       linenum = 0;   /* Reset line number. */
       done = 0;
       num_name_convert = 0;
	   read_parse_until_begin(buffer);
	   
	   //read until the end of the file
	   //printf("pass %d \n", pass);
	   if (pass == 0)
		   printf("Reading pass 0 : read the net connect to output buffer directly \n");
	   if (pass == 1)
		   printf("Reading pass 1 : get output \n");
		if (pass == 2)
			printf("Reading pass 2 : get input \n");
		if (pass == 3)
			printf("Reading pass 3 : get LUT \n");
		if (pass == 4)
			printf("Reading pass 4 : get FF \n");
		if (pass == 5)
			printf("Reading pass 5 : get carry chain \n");
		if (pass == 6)
			printf("Reading pass 6 : get internal logic \n");
		if (pass == 7)
			printf("Reading pass 7 : get EB \n");
		if (pass == 8)
			printf("Reading pass 8 : get DSP \n");
			
		
       while((my_fgets(buffer,BUFSIZE,vhdl) != NULL)) {
          get_tok(buffer, pass, doall, &done, lut_size, &inside_names);

       }
	   

       rewind (vhdl);  /* Start at beginning of file again */
    }
 } 

 fclose(vhdl);
 //check_net(lut_size);
/*
 if (activity[0] != '\0') {
    read_activity(activity);
 }
 */


for (i= 0; i < MAXLUT; i++)
{
	if (saved_names[i] != NULL)
		free(saved_names[i]);	
}
	if (saved_names != NULL)
		free(saved_names);	

 free_parse();
 //exit(1);
}


void read_parse_until_begin (char *buf) {

char *ptr; 
//read the vhdl file until "begin"

	while((my_fgets(buf,BUFSIZE,vhdl) != NULL)) {          
		ptr =my_strtok(buf,TOKENS,vhdl,buf);
		if (ptr != NULL)
		{
			//printf("%s \n", ptr);
			if (strcmp(ptr, "begin")==0)
			{
				return;
			}
		}
    }
	printf("Error: Can't find begin in vhdl file \n");
	exit(1);
}


void init_parse(int doall) {

/* Allocates and initializes the data structures needed for the parse. */

 int i, len;
 struct hash_nets *h_ptr;

 if (!doall) {  /* Initialization before first (counting) pass */
    num_nets = 0;  
    hash = (struct hash_nets **) my_calloc(sizeof(struct hash_nets *),
            HASHSIZE);
    init_block_name_list();
 }

/* Allocate memory for second (load) pass */ 

 else {   
    net = (struct s_net *) my_malloc(num_nets*sizeof(struct s_net));
    block = (struct s_block *) my_malloc(num_blocks*
        sizeof(struct s_block));   
    num_driver = (int *) my_malloc(num_nets * sizeof(int));
    temp_num_pins = (int *) my_malloc(num_nets*sizeof(int));

    for (i=0;i<num_nets;i++) {
       num_driver[i] = 0;
       net[i].num_pins = 0;
       net[i].num_packed = 0;
       net[i].num_clusters = 0;
    }

    for (i=0;i<HASHSIZE;i++) {
       h_ptr = hash[i];   
       while (h_ptr != NULL) {
          net[h_ptr->index].pins = (int *) my_malloc(h_ptr->count*sizeof(int));

/* For avoiding assigning values beyond end of pins array. */
          temp_num_pins[h_ptr->index] = h_ptr->count;
          len = strlen (h_ptr->name);
          net[h_ptr->index].name = (char *) my_malloc ((len + 1)* sizeof(char));
          strcpy (net[h_ptr->index].name, h_ptr->name);
          h_ptr = h_ptr->next;
       }
    }
 }

/* Initializations for both passes. */

 ilines = 0;
 olines = 0;
 model_lines = 0;
 endlines = 0;
 num_p_inputs = 0;
 num_p_outputs = 0;
 num_luts = 0;
 num_latches = 0;
 num_blocks = 0;
 num_dsp = 0;
 num_veb = 0;
 num_memory = 0;
}

void init_block_name_list()
{
   block_name_list = (char **)NULL;
   num_blocks_in_block_name_list = 0;
}

void free_parse (void) {  

/* Release memory needed only during blif network parsing. */

 int i;
 struct hash_nets *h_ptr, *temp_ptr;

 for (i=0;i<HASHSIZE;i++) {
    h_ptr = hash[i];
    while (h_ptr != NULL) {
       free ((void *) h_ptr->name);
       temp_ptr = h_ptr->next;
       free ((void *) h_ptr);
       h_ptr = temp_ptr;
    }
 }
 
 for(i=0; i<num_name_convert; i++)
 {
 	if (oname != NULL)
	{
		if (oname[i].output_name != NULL)
		{
			free(oname[i].output_name);
		}
		
		if (oname[i].net_name)
		{
			free(oname[i].net_name);
		}
		
		free(oname);
	}
 }
 
 free ((void *) num_driver);
 free ((void *) hash);
 free ((void *) temp_num_pins);
 free_block_name_list();
}

void free_block_name_list()
{
   int i;

   if (block_name_list != (char **)NULL) {
      for(i=0;i<num_blocks_in_block_name_list;i++) {
         free(block_name_list[i]);
      }
      free(block_name_list);
   }
}


void get_tok (char *buffer, int pass, int doall, int *done,
       int lut_size, char *inside_names_ptr) {

/* Figures out which, if any token is at the start of this line and *
 * takes the appropriate action.                                    */

	char *ptr; 
	char  buffer2[BUFSIZE];
	char blockname[BUFSIZE];
	char netname[BUFSIZE];
	char onetname[BUFSIZE];
	char *tempptr;
	int i;
	int len;


	//strcpy(buffer2, buffer);

	ptr = my_strtok(buffer," \t\n",vhdl,buffer);

	if (ptr == NULL) return; 
	
	if (pass == 0)	//read the net connect to output buffer directly 
	{
		
		strcpy(onetname, ptr);	//output name
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
		
		if (ptr != NULL)
		{
			if (strcmp(ptr, "<=") ==0)
			{
				//the net connect to output buffer
				ptr = my_strtok(NULL," \t\n;",vhdl,buffer);	//get the net name
				strcpy(netname, ptr);
			
				if (num_name_convert == 0)
				{
					oname = (struct oname_convert *) malloc(sizeof (struct oname_convert));				
				}
				else	
				{
					oname = (struct oname_convert *) realloc(oname, (num_name_convert +1) * sizeof(struct oname_convert));				
				}	
						
				oname[i].output_name = malloc(strlen(onetname) + 1);
				strcpy(oname[i].output_name, onetname);
					
				oname[i].net_name = malloc(strlen(netname) + 1);
				strcpy(oname[i].net_name, netname);		
		
				//printf("%s <= %s \n", oname[i].output_name, oname[i].net_name);
						
				num_name_convert ++;
			}			
		}
	}
			
	
	if (pass == 1)	//first pass to get output
	{
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name

		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":\\",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);

		if (strcmp(ptr, "OBUF")==0)
		{
			//output buffer
			//second line is the input of the buffer
			my_fgets(buffer,BUFSIZE,vhdl);
			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{				
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				strncpy (netname ,ptr, strlen(ptr) -2);						
				netname[strlen(ptr) -2] = '\0';
				//printf("blockname : %s, netname : %s \n", blockname, netname);
				io_line(RECEIVER, doall, blockname, netname, 0, 0);							 
			}			

		}
/*
		//dummy output, no use
		if (strcmp(ptr, "OBUFT")==0)
		{
			//output buffer
			//second line is the input of the buffer
			my_fgets(buffer,BUFSIZE,vhdl);
			my_fgets(buffer,BUFSIZE,vhdl);

			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{				
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				strncpy (netname ,ptr, strlen(ptr) -2);						
				netname[strlen(ptr) -2] = '\0';
				//printf("blockname : %s, netname : %s \n", blockname, netname);
				io_line(RECEIVER, doall, blockname, netname, 0, 0);							 
			}			

		}
*/

	}
	

	if (pass == 2)	//second pass to get Input
	{			
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name				

		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":\\",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);

		if (strcmp(ptr, "IBUF") ==0)
		{
			
			//input buffer								
			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{				
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				tempptr = my_strtok(ptr,",",vhdl, ptr);
				strcpy (netname, tempptr);			
				io_line(DRIVER, doall, blockname, netname, 0, 0);
				my_fgets(buffer,BUFSIZE,vhdl);	//get next line

			}			
		}

		if (strcmp(ptr, "BUFGP") ==0)
		{
			//clock buffer
			//second line is the output of the buffer
			my_fgets(buffer,BUFSIZE,vhdl);
			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{				
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);				

				strncpy (netname ,ptr, strlen(ptr) -2);						
				netname[strlen(ptr) -2] = '\0';

				io_line(DRIVER, doall, blockname, netname, 0, 0);							 
			}			
		}

		if (strcmp(ptr, "GND") ==0)
		{
			//ground 						
			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{			
	
				//printf("%s \n", buffer);	
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				strncpy (netname ,ptr, strlen(ptr) -2);						
				netname[strlen(ptr) -2] = '\0';			
	
				//printf("%s \n", netname);
				io_line(DRIVER, doall, blockname, netname,1, 0);							 
			}			
		}

		if (strcmp(ptr, "VCC") ==0)
		{
			//vcc
			if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
			{			
				//get the output netname
				ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				strncpy (netname ,ptr, strlen(ptr) -2);						
				netname[strlen(ptr) -2] = '\0';			
	
				io_line(DRIVER, doall, blockname, netname, 0, 1);							 
			}			

		}		
	}


	if (pass == 3)	//third pass to get LUT
	{
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
		
		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);
		
		if (strcmp(ptr, "LUT1") ==0)
		{
			add_lut (doall, lut_size, 1, 1 , LUT, blockname );
		}

		if (strcmp(ptr, "LUT1_L") ==0)
		{
			add_lut (doall, lut_size, 1, 1 , LUT,  blockname );
		}

		if (strcmp(ptr, "LUT2") ==0)
		{
			add_lut (doall, lut_size, 2, 1 , LUT,  blockname);
		}

		if (strcmp(ptr, "LUT2_L") ==0)
		{
			add_lut (doall, lut_size, 2, 1 , LUT, blockname );
		}

		if (strcmp(ptr, "LUT3") ==0)
		{
			add_lut (doall, lut_size, 3, 1 , LUT,  blockname);
		}

		if (strcmp(ptr, "LUT3_L") ==0)
		{
			add_lut (doall, lut_size, 3, 1 , LUT,  blockname );
		}

		if (strcmp(ptr, "LUT4") ==0)
		{
			add_lut (doall, lut_size, 4, 1 , LUT,  blockname );
		}

		if (strcmp(ptr, "LUT4_L") ==0)
		{
			add_lut (doall, lut_size, 4, 1 , LUT,  blockname );
		}
	}

	if (pass == 4)	//forth pass to get FF
	{		
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
				
		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);

		//printf("Block name : %s , library name : %s \n", blockname, ptr);

		if (strcmp(ptr, "FD") ==0)
		{
			add_latch (doall, lut_size, FD, blockname);	
		}	

		if (strcmp(ptr, "FDP") ==0)
		{
			add_latch (doall, lut_size, FDP, blockname);	
		}

		if (strcmp(ptr, "FDPE") ==0)
		{
			add_latch (doall, lut_size, FDP, blockname);	
		}	

		if (strcmp(ptr, "FDC") ==0)
		{
			add_latch (doall, lut_size, FDC, blockname);	
		}	

		if (strcmp(ptr, "FDCE") ==0)
		{
			add_latch (doall, lut_size, FDCE, blockname);	
		}	

		if (strcmp(ptr, "FDE") ==0)
		{
			add_latch (doall, lut_size, FDE, blockname);	
		}	

		if (strcmp(ptr, "FDR") ==0)
		{
			add_latch (doall, lut_size, FDR, blockname);	
		}	

		if (strcmp(ptr, "FDS") ==0)
		{
			add_latch (doall, lut_size, FDS, blockname);	
		}	

		if (strcmp(ptr, "FDCP") ==0)
		{
			add_latch (doall, lut_size, FDCP, blockname);	
		}
		
		if (strcmp(ptr, "FDRS") ==0)
		{
			add_latch (doall, lut_size, FDRS, blockname);	
		}
		if (strcmp(ptr, "LDC") ==0)
		{
			add_latch (doall, lut_size, LDC, blockname);	
		}	


	}

	if (pass == 5)	//fifth pass to get carry chain
	{
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
		
		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);

		if (strcmp(ptr, "XORCY") ==0)
		{
			add_carry (doall, lut_size, XORCY, blockname);	
		}	

		if (strcmp(ptr, "MUXCY")  ==0)
		{
			add_carry (doall, lut_size, MUXCY, blockname);	
		}	

		if (strcmp(ptr, "MUXCY_L") ==0)
		{
			add_carry (doall, lut_size, MUXCY_L, blockname);	
		}	
	}

	if (pass == 6)	//sixth pass to get internal logic
	{
		
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
		
		if (ptr == NULL) return; 

		tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);

		if (strcmp(ptr, "INV") ==0)
		{
			add_internal (doall, lut_size, INV, blockname);	
		}	

		if (strcmp(ptr, "MULT_AND") ==0)
		{
			add_internal (doall, lut_size, MULT_AND, blockname);	
		}	

		if (strcmp(ptr, "MUXF5") ==0 || strcmp(ptr, "MUXF6") ==0 || strcmp(ptr, "MUXF7") ==0 || strcmp(ptr, "MUXF8") ==0)
		{
			add_muxf (doall, lut_size, MUXF, blockname);	
		}	
	}
	
	if (pass == 7)	//get the veb
	{
	
		strcpy(blockname, ptr);		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
		
		if (ptr == NULL) return; 
				
		tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		strcpy(blockname, tempptr);
			
		
		if (strncmp(ptr, "veb", 3) ==0)
		{
  			add_veb (doall, lut_size, VEB, blockname, ptr);	
		}	

//		if (strncmp(ptr, "fpadder", 6) ==0)
//		{
//  			add_veb (doall, lut_size, VEB, blockname, ptr);	
//		}	

//		if (strncmp(ptr, "fpmult", 6) ==0)
//		{
//  			add_veb (doall, lut_size, VEB, blockname, ptr);	
//		}

		if (strncmp(ptr, "fp", 2) ==0)
		{
//			printf("%s %s \n",blockname, ptr);
  			add_veb (doall, lut_size, VEB, blockname, ptr);	
		}	

	}
	
	if (pass == 8) //get the MULT18x18
	{						
		strcpy(blockname, ptr);
		
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the library name
				
		if (ptr == NULL) return; 

		//tempptr = my_strtok(blockname,":",vhdl,blockname);	//get the block name		
		//strcpy(blockname, tempptr);
		
										
		if (strcmp(ptr, "MULT18X18") ==0)
		{			
			len = strlen(blockname);
			blockname[len - 1] = '\0';
		
			//printf ("blockname : %s , DSP name: %s \n", blockname, ptr);
			add_dsp (doall, lut_size,  DSP,  blockname, ptr);

		}else if (strcmp(ptr, "MULT18X18S") ==0)
		{
						
			len = strlen(blockname);
			blockname[len - 1] = '\0';

			//printf ("blockname : %s , DSP name: %s \n", blockname, ptr);
			add_dsp (doall, lut_size,  DSPS,  blockname, ptr);
			
		}
	}

}



void io_line(int in_or_out, int doall, char * blockname, char *net_name, int is_gnd, int is_vcc) {  

/* Adds an input or output block to the block data structures.           *
 * in_or_out:  DRIVER for input, RECEIVER for output.                    *
 * doall:  1 for final pass when structures are loaded.  0 for           *
 * first pass when hash table is built and pins, nets, etc. are counted. */ 

 char *ptr;
 char buf2[BUFSIZE];
 char buf3[BUFSIZE]; /* SC_05 */
 int nindex, len;
  
 
        
		num_blocks++;
   
//		printf("add net %s, in/out %d \n", net_name, in_or_out); 
		nindex = add_net(net_name, in_or_out,num_blocks-1,doall); 
                 /* zero offset indexing */

		if (!doall) 
		{

			if (in_or_out == RECEIVER) 
			{
				sprintf(buf3, "out:%s", blockname); /* SC_05 */
				add_block_name_to_block_name_list(buf3); /* SC_05 */
			} else
			{
				  add_block_name_to_block_name_list(blockname);
			}
			return;
		}


		len = strlen (blockname);
		if (in_or_out == RECEIVER) 
		{  /* output pads need out: prefix 
                                     to make names unique from LUTs */
		    block[num_blocks-1].name = (char *) my_malloc ((len+1+4) *sizeof (char));          /* Space for out: at start */
			strcpy(block[num_blocks-1].name,"out:");
			strcat(block[num_blocks-1].name,blockname);
		}
		else 
		{
			block[num_blocks-1].name = (char *) my_malloc ((len+1) *sizeof (char));     
			strcpy(block[num_blocks-1].name,blockname);
		}

		block[num_blocks-1].num_nets = 1;
		block[num_blocks-1].nets[0] = nindex;  /* Put in driver position for */
		block[num_blocks-1].carryout_to = -1;
		block[num_blocks-1].carryout_to_name = (char *)NULL;
		block[num_blocks-1].use_lut = 0;
		block[num_blocks-1].use_ff = 0;
		block[num_blocks-1].use_xorcy = 0;
		block[num_blocks-1].use_muxcy = 0;
		block[num_blocks-1].use_inv = 0;
		block[num_blocks-1].use_inv_ce = 0;
		block[num_blocks-1].use_inv_sr = 0;
		block[num_blocks-1].use_inv_clk = 0;
		block[num_blocks-1].use_ff_int_conn = 0;
		block[num_blocks-1].use_mult_and = 0;

		/*  OUTPAD, since it has only one pin (even though it's a receiver */
	
		if (in_or_out == DRIVER) 
		{             /* processing .inputs line */
			num_p_inputs++;

			block[num_blocks-1].type = INPAD;
			if (is_vcc == 1)
			{
				block[num_blocks-1].type = VCC;
			}
			
			if (is_gnd == 1)
			{
				block[num_blocks-1].type = GND;
			}
												
			block[num_blocks-1].num_input = 0;
			block[num_blocks-1].num_output = 1;
		}
		else 
		{                                 /* processing .outputs line */
			num_p_outputs++;
			block[num_blocks-1].type = OUTPAD;
			block[num_blocks-1].num_input = 1;
			block[num_blocks-1].num_output = 0;
		}

}


void add_block_name_to_block_name_list(char *name)
{
   if (num_blocks_in_block_name_list == 0) {
      block_name_list = (char **)my_malloc(sizeof(char *)*1);
   } else {
      block_name_list = (char **)my_realloc(block_name_list,
                                 sizeof(char *)*(1+num_blocks_in_block_name_list));
   }
   block_name_list[num_blocks_in_block_name_list] = my_malloc(
                                 (1+(int)strlen(name)));
   strcpy(block_name_list[num_blocks_in_block_name_list],name);
   num_blocks_in_block_name_list ++;
}


int add_net (char *ptr, int type, int bnum, int doall) {   

/* This routine is given a net name in *ptr, either DRIVER or RECEIVER *
 * specifying whether the block number given by bnum is driving this   *
 * net or in the fan-out and doall, which is 0 for the counting pass   *
 * and 1 for the loading pass.  It updates the net data structure and  *
 * returns the net number so the calling routine can update the block  *
 * data structure.                                                     */

 struct hash_nets *h_ptr, *prev_ptr;
 int index, j, nindex;

 index = hash_value(ptr);
 h_ptr = hash[index]; 
 prev_ptr = h_ptr;

 while (h_ptr != NULL) {
    if (strcmp(h_ptr->name,ptr) == 0) 
	{ /* Net already in hash table */
       nindex = h_ptr->index;

	   
       if (!doall) 
	   {   /* Counting pass only */
		   //printf("add_net , doall = %d, nindex = %d \n", doall, nindex);
          (h_ptr->count)++;		  
          return (nindex);
       }


       net[nindex].num_pins++;

       if (type == DRIVER) {
          num_driver[nindex]++;
          j=0;           /* Driver always in position 0 of pinlist */
       }
       else {
          j = net[nindex].num_pins - num_driver[nindex]; 
   /* num_driver is the number of signal drivers of this net. *
    * should always be zero or 1 unless the netlist is bad.   */
          if (j >= temp_num_pins[nindex]) {
             printf("Error:  Net #%d (%s) has no driver and will cause\n",
                nindex, ptr);
             printf("memory corruption.\n");
          }
       }
       net[nindex].pins[j] = bnum;
       return (nindex);
    }
    prev_ptr = h_ptr;
    h_ptr = h_ptr->next;
 }

 /* Net was not in the hash table. */

 if (doall == 1) {
    printf("Error in add_net:  the second (load) pass could not\n");
    printf("find net %s in the symbol table.\n", ptr);
    exit(1);
 }

/* Add the net (only counting pass will add nets to symbol table). */

 num_nets++;
 h_ptr = (struct hash_nets *) my_malloc (sizeof(struct hash_nets));
 if (prev_ptr == NULL) {
    hash[index] = h_ptr;
 }     
 else {  
    prev_ptr->next = h_ptr;
 }    
 h_ptr->next = NULL;
 h_ptr->index = num_nets - 1;
 h_ptr->count = 1;
 h_ptr->name = (char *) my_malloc((strlen(ptr)+1)*sizeof(char));
 strcpy(h_ptr->name,ptr);
 return (h_ptr->index);
}

int hash_value (char *name) {

 int i,k;
 int val=0, mult=1;
 
 i = strlen(name);
 k = max (i-7,0);
 for (i=strlen(name)-1;i>=k;i--) {
    val += mult*((int) name[i]);
    mult *= 10;
 }
 val += (int) name[0];
 val %= HASHSIZE;
 return(val);
}


void add_lut (int doall, int lut_size, int input_size, int output_size, enum block_types type , char* blockname ) {

/* Adds a LUT (.names) currently being parsed to the block array.  Adds *
 * its pins to the nets data structure by calling add_net.  If doall is *
 * zero this is a counting pass; if it is 1 this is the final (loading) *
 * pass.                                                                */

// char *ptr, saved_names[MAXLUT+2][BUFSIZE], buf[BUFSIZE];
char *ptr, buf[BUFSIZE];

 int i, j, len;

 char  buffer[BUFSIZE];
 char  buffer2[BUFSIZE];
 char netname[BUFSIZE];
 char *tempptr;
 int get_input_line;
 int num_input;
 int num_output;
 int num_net;
 
 int entry;

 num_blocks++;
 last_lut_read = num_blocks-1;

 
//read until I0

 get_input_line = 0;
 num_input = 0;
 num_output =0;

//get the input
 while (get_input_line == 0)
 {			
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);
			if (strcmp(ptr, "I0")  ==0)
			{
				get_input_line = 1;
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);
				ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

				tempptr = my_strtok(ptr,",",vhdl, ptr);					
				strcpy (saved_names[num_input], tempptr);				

				num_input ++;
			}
			//else continue to read next line

		}				
		else
		{
			printf("Error: can't fine input of the LUT \n");
			exit(1);
		}
 }	

 for (i = num_input; i < input_size; i++)
 {

		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[num_input], tempptr);						
			num_input ++;
		}
		else
		{
			printf("Error: can't fine input of the LUT \n");
			exit(1);
		}
 }


//get the output
for (i = num_output; i < output_size; i++)
{
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{	
		//get the netname
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name
		
		if (num_output == (output_size -1))
		{			
			strncpy (netname,ptr, strlen(ptr) -2);						
			netname[strlen(ptr) -2] = '\0';
			//strncpy (saved_names[num_input+num_output],ptr, strlen(ptr) -2);						
			//saved_names[num_input+num_output][strlen(ptr) -2] = '\0';			
		}
		else
		{			
			strncpy (netname,ptr, strlen(ptr) -1);						
			netname[strlen(ptr) -1] = '\0';
			//strncpy (saved_names[num_input+num_output], ptr, strlen(ptr) -1);						
			//saved_names[num_input+num_output][strlen(ptr) -2] = '\0';
		}
		entry = convert_ouput(netname);	
		if (entry == -1)	//can't find netname connect to output buffer
		{
			strcpy(saved_names[num_input+num_output], netname);
		}
		else
		{
			//printf("entry number %d, %s <= %s\n", oname[entry].output_name, netname);
			strcpy(saved_names[num_input+num_output], oname[entry].output_name);
		}
		num_output ++;
	}
	else
	{
		printf("Error: can't fine input of the LUT \n");
		exit(1);
	}
}

/*
printf("LUT output net: \n");
for (i=0; i< output_size;i++)
{
	printf("%s \n", saved_names[num_input + i]);
}
*/

if (!doall) {          // Counting pass only ...
	
	for (i = 0; i< num_output ; i++)
	{
		add_net (saved_names[num_input + i], DRIVER,num_blocks-1,doall);
	}

    for (j=0;j<num_input;j++) 
	{
       add_net(saved_names[j],RECEIVER,num_blocks-1,doall);
	}

	add_block_name_to_block_name_list(blockname);
    return;
 }


block[num_blocks-1].num_nets = num_input + num_output;
block[num_blocks-1].type =  type;
block[num_blocks-1].carryout_to = -1;
block[num_blocks-1].carryout_to_name = (char *)NULL;
block[num_blocks-1].num_input = num_input;
block[num_blocks-1].num_input = num_output;
block[num_blocks-1].use_lut = 1;
block[num_blocks-1].use_ff = 0;
block[num_blocks-1].use_xorcy = 0;
block[num_blocks-1].use_muxcy = 0;
block[num_blocks-1].use_inv = 0;
block[num_blocks-1].use_inv_ce = 0;
block[num_blocks-1].use_inv_sr = 0;
block[num_blocks-1].use_inv_clk = 0;
block[num_blocks-1].use_ff_int_conn = 0;
block[num_blocks-1].use_mult_and = 0;
block[num_blocks-1].lut_type = type;

//null_function(num_blocks-1,lut_size);


//set the unused pin to open
for (i=0; i< B_LUT_IN  + lut_size; i++)
{
    block[num_blocks-1].nets[i] = OPEN;
}

//output of LUT
block[num_blocks-1].nets[LUT_D] = add_net (saved_names[num_input], DRIVER,num_blocks-1,doall);

// store the lut in
for (i=0;i<input_size;i++)   //Do inputs 
{
    block[num_blocks-1].nets[i+ B_LUT_IN] = add_net (saved_names[input_size -1 - i],RECEIVER,num_blocks-1,doall); 
}

len = strlen (blockname);
block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
strcpy(block[num_blocks-1].name, blockname);

if (get_index_in_block_name_list(block[num_blocks-1].name) != num_blocks-1) {
    printf("Error: inconsistency in block_name_list %d %d\n",
            get_index_in_block_name_list(block[num_blocks-1].name),num_blocks-1);

 }
 num_luts++;
}

/* set all the sram cells to zero if no function is implemented */
void null_function(int blockno, int lut_size)
{
   int i;
	int function_range;

	function_range = pow(2, lut_size);

   block[blockno].function = (char *)malloc( sizeof(char)*(function_range+1) );
	for(i=0;i < function_range;i++) {

      block[blockno].function[i] = '0';
   }
   
	block[blockno].function[function_range] = '\0';
}

int get_index_in_block_name_list(char *name)
{
   int i;
  
   for(i=0;i<num_blocks_in_block_name_list;i++) {
      if(strcmp(name,block_name_list[i])==0) {
         return(i);
      }
   }
   return(-1);
}

void add_latch (int doall, int lut_size,  enum block_types type, char* blockname)
{

	/*
		Adds the flipflop (.latch) currently being parsed to the block array. 
		Adds its pins to the nets data structure by calling add_net.
		If doall is zero this is a counting pass; if it is 1 this is the final 
		net order:
		Q, D, Clock, preset, clear, ce, reset
	*/
/* Adds the flipflop (.latch) currently being parsed to the block array.  *
 * Adds its pins to the nets data structure by calling add_net.  If doall *
 * is zero this is a counting pass; if it is 1 this is the final          * 
 * (loading) pass.  Blif format for a latch is:                           *
 * .latch <input> <output> <type (latch on)> <control (clock)> <init_val> *
 * The latch pins are in .nets 0 to 2 in the order: Q D CLOCK.            */

// char *ptr, buf[BUFSIZE], saved_names[7][BUFSIZE];
char *ptr, buf[BUFSIZE];

 int i, len;
 char  buffer[BUFSIZE];
 char  buffer2[BUFSIZE];
 char netname[BUFSIZE];
 char *tempptr; 
 char num_nets;
 
 int entry;

 num_blocks++;

 num_nets = 0;
 
//get Q
if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
{				
	//get the netname
	ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

	tempptr = my_strtok(ptr,",",vhdl, ptr);	
	
	entry = convert_ouput(tempptr);	
	
	if (entry == -1)
	{
		strcpy (saved_names[0], tempptr);		
	}
	else
	{
		strcpy (saved_names[0], oname[entry].output_name);		
	}	
}

//get D
if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
{				
	//get the netname
	ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

	tempptr = my_strtok(ptr,",",vhdl, ptr);	
	strcpy (saved_names[1], tempptr);	
}

//get clock
if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
{				
	ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
	ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

	if ( type == LDC)
	{
		//remove , at the end
		strncpy (saved_names[5],ptr, strlen(ptr) -1);	//ce as latch input	
		saved_names[5][strlen(ptr) -1] = '\0';
	}
	else if ( type == FD)
	{	
		//remove ); at the end
		strncpy (saved_names[2],ptr, strlen(ptr) -2);		
		saved_names[2][strlen(ptr) -2] = '\0';
		strcpy (saved_names[3],"OPEN");		//preset
		strcpy (saved_names[4],"OPEN");		//clear
		strcpy (saved_names[5],"OPEN");		//ce
		strcpy (saved_names[6],"OPEN");		//reset
		num_nets = 3;
	}
	else
	{
		//remove , at the end
		strncpy (saved_names[2],ptr, strlen(ptr) -1);		
		saved_names[2][strlen(ptr) -1] = '\0';
	}		
}

//get preset
if ( type == FDP || type == FDS)
{
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end		
		strncpy (saved_names[3],ptr, strlen(ptr) -2); //preset
		saved_names[3][strlen(ptr) -2] = '\0';
		strcpy (saved_names[4],"OPEN");		//clear
		strcpy (saved_names[5],"OPEN");		//ce
		strcpy (saved_names[6],"OPEN");		//reset
		
		num_nets = 4;	
	}
}

//get clear
if  ( type == LDC) 
{
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strcpy (saved_names[2],"OPEN");		//preset

		strcpy (saved_names[3],"OPEN");		//preset
		strncpy (saved_names[4],ptr, strlen(ptr) -2); //preset		
		saved_names[4][strlen(ptr) -2] = '\0';
		strcpy (saved_names[6],"OPEN");		//reset
	
		num_nets = 4;
	}
}


//get clear
if  ( type == FDC) 
{
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strcpy (saved_names[3],"OPEN");		//preset
		strncpy (saved_names[4],ptr, strlen(ptr) -2); //preset		
		saved_names[4][strlen(ptr) -2] = '\0';
		strcpy (saved_names[5],"OPEN");		//ce
		strcpy (saved_names[6],"OPEN");		//reset
	
		num_nets = 4;
	}
}

//get ce
if  ( type == FDE) 
{	
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	
		
		//remove ); at the end
		strcpy (saved_names[3],"OPEN");		//preset
		strcpy (saved_names[4],"OPEN");		//clear
		strncpy (saved_names[5],ptr, strlen(ptr) -2); //ce				
		saved_names[5][strlen(ptr) -2] = '\0';
		strcpy (saved_names[6],"OPEN");		//reset		

		num_nets = 4;
	}
}

//get reset
if  ( type == FDR) 
{
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strcpy (saved_names[3],"OPEN");		//preset
		strcpy (saved_names[4],"OPEN");		//clear
		strcpy (saved_names[5],"OPEN");		//ce		
		strncpy (saved_names[6],ptr, strlen(ptr) -2); //reset		
		saved_names[6][strlen(ptr) -2] = '\0';
		num_nets = 4;			
	}
}

//get clear and ce
if  ( type == FDCE) 
{
	//get clear
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove , at the end
		strcpy (saved_names[3],"OPEN");		//preset
		strncpy (saved_names[4],ptr, strlen(ptr) -1); //clear				
		saved_names[4][strlen(ptr) -1] = '\0';
		strcpy (saved_names[6],"OPEN"); //reset		
	}

	//get ce
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strncpy (saved_names[5],ptr, strlen(ptr) -2); //ce		
		saved_names[5][strlen(ptr) -2] = '\0';

	}
	num_nets = 5;
}

//get preset and ce
if  ( type == FDPE) 
{
	//get preset
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove , at the end
		strncpy (saved_names[3],ptr, strlen(ptr) -1); //preset				
		saved_names[3][strlen(ptr) -1] = '\0';
		strcpy (saved_names[4],"OPEN");		//clear
		strcpy (saved_names[6],"OPEN"); //reset		
	}

	//get ce
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strncpy (saved_names[5],ptr, strlen(ptr) -2); //ce		
		saved_names[5][strlen(ptr) -2] = '\0';

	}
	num_nets = 5;
}


//get clear and preset
if  ( type == FDCP) 
{
	//get clear
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove , at the end
//		strcpy (saved_names[3],"OPEN");		//preset
		strncpy (saved_names[4],ptr, strlen(ptr) -1); //clear				
		saved_names[4][strlen(ptr) -1] = '\0';
		strcpy (saved_names[5],"OPEN"); //ce		

		strcpy (saved_names[6],"OPEN"); //reset		
	}

	//get preset
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strncpy (saved_names[3],ptr, strlen(ptr) -2); //preset		
		saved_names[3][strlen(ptr) -2] = '\0';

	}
	num_nets = 5;
}

//get reset and preset
if  ( type == FDRS) 
{
	//get clear
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove , at the end
//		strcpy (saved_names[3],"OPEN");		//preset		
		strcpy (saved_names[4],"OPEN"); //clear				
		strcpy (saved_names[5],"OPEN"); //ce		

		strncpy (saved_names[6],ptr, strlen(ptr) -1); //reset			
		saved_names[6][strlen(ptr) -1] = '\0';		
	}

	//get preset
	if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{				
		ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
		ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name	

		//remove ); at the end
		strncpy (saved_names[3],ptr, strlen(ptr) -2); //preset		
		saved_names[3][strlen(ptr) -2] = '\0';

	}
	num_nets = 5;
}

 if (!doall) {   // If only a counting pass ... 
    add_net(saved_names[0],DRIVER,num_blocks-1,doall);    // Q
	add_net(saved_names[1],RECEIVER,num_blocks-1,doall);  // D 
    add_net(saved_names[2],RECEIVER,num_blocks-1,doall);  // Clock/latch trigger 

	for (i = 3; i< 7; i ++)
	{
		 //add to net when the pin is not open
		if (strcmp(saved_names[i], "OPEN") != 0)
		{
			add_net(saved_names[i],RECEIVER,  num_blocks-1,doall);                                            
		}				
	}

	/*
	printf("FF  net: \n");
	for (i=0; i< 7;i++)
	{
		printf("%s \n", saved_names[i]);
	}
*/
    add_block_name_to_block_name_list(blockname);
    return;
 }

 block[num_blocks-1].carryout_to = -1;
 block[num_blocks-1].carryout_to_name = (char *)NULL;
 block[num_blocks-1].type = LATCH;
 block[num_blocks-1].num_nets = num_nets;
 block[num_blocks-1].use_lut = 0;
block[num_blocks-1].use_ff = 1;
block[num_blocks-1].use_xorcy = 0;
block[num_blocks-1].use_muxcy = 0;
block[num_blocks-1].use_inv = 0;
block[num_blocks-1].use_inv_ce = 0;
block[num_blocks-1].use_inv_sr = 0;
block[num_blocks-1].use_inv_clk = 0;
block[num_blocks-1].use_ff_int_conn = 0;
block[num_blocks-1].use_mult_and = 0;
block[num_blocks-1].use_muxf = 0;
block[num_blocks-1].ff_type = type;

//set all net to open first
for (i=0; i< B_LUT_IN + lut_size; i++)
{
    block[num_blocks-1].nets[i] = OPEN;
}

 block[num_blocks-1].nets[FF_Q] = add_net(saved_names[0],DRIVER,num_blocks-1,
     doall);                                                        // Q 
 block[num_blocks-1].nets[FF_D] = add_net(saved_names[1],RECEIVER,num_blocks-1,
     doall);                                                        // D , use input dy
if (strcmp(saved_names[2], "OPEN") != 0)
{
 block[num_blocks-1].nets[FF_CLK] = add_net(saved_names[2],RECEIVER,     
     num_blocks-1,doall);                                           // Clock 
}

if (strcmp(saved_names[5], "OPEN") != 0)
{
	block[num_blocks-1].nets[FF_CE] = add_net(saved_names[5],RECEIVER, num_blocks-1,doall);  //ce
}

if (strcmp(saved_names[3], "OPEN") != 0)
{
	block[num_blocks-1].nets[FF_SR] = add_net(saved_names[3],RECEIVER, num_blocks-1,doall);  //preset, store in sr
}

if (strcmp(saved_names[4], "OPEN") != 0)
{
	block[num_blocks-1].nets[FF_SR] = add_net(saved_names[4],RECEIVER, num_blocks-1,doall);  //clear, store in sr
}


if (strcmp(saved_names[6], "OPEN") != 0)
{
	block[num_blocks-1].nets[FF_SR] = add_net(saved_names[6],RECEIVER, num_blocks-1,doall);  //reset, store in sr
}
 

 len = strlen (blockname);
 block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
 strcpy(block[num_blocks-1].name,blockname);
 num_latches++;
}

void add_carry (int doall, int lut_size,  enum block_types type, char* blockname)
{
//	char *ptr, saved_names[MAXLUT+2][BUFSIZE], buf[BUFSIZE];
	char *ptr, buf[BUFSIZE];

	int i, j, len;

	char  buffer[BUFSIZE];
	char  buffer2[BUFSIZE];
	char netname[BUFSIZE];
	char *tempptr;
	int get_input_line;
	int num_input;
	int num_output;
	int num_nets;
	
	int entry;

	num_nets = 0;
	num_blocks++;
	if (type == XORCY)
	{
		//get LI			
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[0], tempptr);			
		}

		//get CI
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[1], tempptr);			
		}

		//get O			
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name
			
			//strncpy (saved_names[2],ptr, strlen(ptr) -2); 						
			//saved_names[2][strlen(ptr) -2] = '\0';
			
			strncpy (netname,ptr, strlen(ptr) -2); 						
			netname[strlen(ptr) -2] = '\0';
			
			entry = convert_ouput(netname);	
			
			if (entry == -1)
			{
				strcpy (saved_names[2], netname);		
			}
			else
			{
				strcpy (saved_names[2], oname[entry].output_name);		
			}	
						
		}

		num_nets = 3;
	}

	if ((type == MUXCY_L) || (type == MUXCY))
	{
		//get DI			
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[0], tempptr);			
		}

		//get CI
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[1], tempptr);			
		}

		//get S
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			//printf("MUXCY_S : %s \n", tempptr);
			strcpy (saved_names[2], tempptr);			
		}

		//get LO/O		
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name
			
			
			strncpy (netname,ptr, strlen(ptr) -2); 						
			netname[strlen(ptr) -2] = '\0';
			
			entry = convert_ouput(netname);	
			
			if (entry == -1)
			{
				strcpy (saved_names[3], netname);		
			}
			else
			{
				strcpy (saved_names[3], oname[entry].output_name);		
			}	
			
			//strncpy (saved_names[3],ptr, strlen(ptr) -2); 				
			//saved_names[3][strlen(ptr) -2] = '\0';
		}		

		num_nets = 4;
	}
	 
	if (!doall) 
	 {   // If only a counting pass ... 
		add_net(saved_names[0],RECEIVER,num_blocks-1,doall);  
		add_net(saved_names[1],RECEIVER,num_blocks-1,doall);   
		
		if (num_nets == 3)
		{
			add_net(saved_names[2],DRIVER,num_blocks-1,doall);     
		}
		else
		{
			add_net(saved_names[2],RECEIVER,num_blocks-1,doall);     
			add_net(saved_names[3],DRIVER,num_blocks-1,doall);     
		}
					
		add_block_name_to_block_name_list(blockname);

		return;
	}


	block[num_blocks-1].carryout_to = -1;
	block[num_blocks-1].carryout_to_name = (char *)NULL;
	block[num_blocks-1].type = type;
	block[num_blocks-1].num_nets = num_nets;
	block[num_blocks-1].use_lut = 0;
	block[num_blocks-1].use_ff = 0;
	block[num_blocks-1].use_inv = 0;
	block[num_blocks-1].use_inv_ce = 0;
	block[num_blocks-1].use_inv_sr = 0;
	block[num_blocks-1].use_inv_clk = 0;
	block[num_blocks-1].use_ff_int_conn = 0;
	block[num_blocks-1].use_mult_and = 0;
	block[num_blocks-1].use_muxf = 0;

	//set all net to open first
	for (i=0; i< B_LUT_IN + lut_size; i++)
	{
		block[num_blocks-1].nets[i] = OPEN;
	}

	if (num_nets ==3)
	{
		//xorcy
		block[num_blocks-1].nets[XORCY_O] = add_net(saved_names[2],DRIVER,num_blocks-1, doall);		//O , y
		block[num_blocks-1].nets[XORCY_LI] = add_net(saved_names[0],RECEIVER, num_blocks-1,doall);	//LI, lut_in[0]
		block[num_blocks-1].nets[XORCY_CI] = add_net(saved_names[1],RECEIVER, num_blocks-1,doall);	//CI, cin

		block[num_blocks-1].use_xorcy = 1;
		block[num_blocks-1].use_muxcy = 0;
	}
	else
	{
		//muxcy
		
		block[num_blocks-1].nets[MUXCY_O] = add_net(saved_names[3],DRIVER,num_blocks-1, doall);		//LO/O, cout
		block[num_blocks-1].nets[MUXCY_DI] = add_net(saved_names[0],RECEIVER, num_blocks-1,doall);	//DI, lut_in[0]
		block[num_blocks-1].nets[MUXCY_CI] = add_net(saved_names[1],RECEIVER, num_blocks-1,doall);	//CI, cin
		block[num_blocks-1].nets[MUXCY_S] = add_net(saved_names[2],RECEIVER, num_blocks-1,doall);	//S, y

//		printf("blockname %s , MUXCY_DI %s \n",blockname,  saved_names[0]);
//		printf("block number %d (%s), MUXCY_O = %d, MUXCY_DI(%s) = %d, MUXCY_CI = %d, MUXCY_S = %d \n", num_blocks-1, block[num_blocks-1].name, block[num_blocks-1].nets[MUXCY_O], block[num_blocks-1].nets[MUXCY_DI], saved_names[0], block[num_blocks-1].nets[MUXCY_CI], block[num_blocks-1].nets[MUXCY_S]);

		block[num_blocks-1].use_xorcy = 0;
		block[num_blocks-1].use_muxcy = 1;
	}
			
	len = strlen (blockname);
	block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
	strcpy(block[num_blocks-1].name,blockname);

}

void add_veb (int doall, int lut_size,  enum block_types type, char* blockname, char* veb_name)
{
//	#define EBBUFSIZE 4000
//	char *ptr, saved_names[MAXLUT+ MAXLUT][BUFSIZE], buf[BUFSIZE];
	char *ptr, buf[BUFSIZE];
//	char *ptr, buf[BUFSIZE];
//	char ** saved_names;

	int i, j, len;

	char  buffer[BUFSIZE];
	char  buffer2[BUFSIZE];
	char netname[BUFSIZE];
	char *tempptr;
	int get_input_line;
	int num_input;
	int upperbound;
	int lowerbound;
	int num_output;
	int num_nets;
	FILE *veb_file;
	
	int pin_pos;
	
	int entry;
	
	
	num_nets = 0;
	
	num_blocks++;
/*
	saved_names = malloc(sizeof(char*) * (MAXEB));
	for (i= 0; i < MAXEB; i++)
	{
		saved_names[i] = malloc(sizeof(char) * BUFSIZE);	
//		saved_names[i] = malloc(sizeof(EBBUFSIZE));	

	}
*/
	//read veb file	
	strcpy(buffer2, veb_name);
	strcat(buffer2, ".vhm");

	veb_file = my_fopen (buffer2, "r", 0);
	
	if (veb_file == NULL)
	{
		printf("Error can't read veb file : %s\n", buffer2);
		exit(1);
	}
		
	
	printf("add_veb %s \n", buffer2);
	
	num_input = 0;
	num_output = 0;
	//read until port(
	while (my_fgets(buffer,BUFSIZE,veb_file) != NULL)
	{		
		tempptr = my_strtok(buffer," \t\n",veb_file,buffer);	//signal name
		
		if (tempptr != NULL)
		{			
			if (strcmp(tempptr, "port(") == 0)
			{							
				break;	
			}
		}
		
	}
		
	
	while (my_fgets(buffer,BUFSIZE,veb_file) != NULL)
	{
		if (buffer != NULL)
		{
			if (strncmp(buffer, "end", 3) == 0)
			{
				break;	
			}
			else
			{
				//read the number of input and output	
						
				tempptr = my_strtok(buffer,":",veb_file,buffer);	//signal name
				tempptr = my_strtok(NULL,TOKENS,veb_file,buffer);	//in or out
				
				if (strcmp(tempptr, "in") ==0)
				{
					//in
					tempptr = my_strtok(NULL, " \t();",veb_file,buffer);	//std_logic or std_logic_vector
					//printf("%s \n", tempptr);
					if (strcmp (tempptr, "std_logic") ==0) 
					{
						num_input ++;
					}
					else
					{
						//count number of input vector
						tempptr = my_strtok(NULL," (\t",veb_file,buffer); //get the upper bound	
												
						upperbound = atoi(tempptr);
						
						tempptr = my_strtok(NULL," ",veb_file,buffer); //download
						
						tempptr = my_strtok(NULL," )",veb_file,buffer); //get the lower bound
						
						lowerbound = atoi(tempptr);
						
						num_input = num_input + (upperbound - lowerbound + 1);							
						
					}
				}
				else
				{
					//out					
					tempptr = my_strtok(NULL, " \t();",veb_file,buffer);	//std_logic or std_logic_vector
					//printf("%s \n", tempptr);
					if (strcmp (tempptr, "std_logic") ==0) 
					{
						num_output ++;
					}
					else
					{
						//count number of input vector
						tempptr = my_strtok(NULL," (\t",veb_file,buffer); //get the upper bound	
												
						upperbound = atoi(tempptr);
						
						tempptr = my_strtok(NULL," ",veb_file,buffer); //download
						
						tempptr = my_strtok(NULL," )",veb_file,buffer); //get the lower bound
						
						lowerbound = atoi(tempptr);
						
						num_output = num_output + (upperbound - lowerbound + 1);												
					}
					
				}								
			}
		}		
	}
	
	
	printf("number of input : %d, number of output : %d \n", num_input , num_output);
			
	
	fclose(veb_file); 
	
	
	//read the actual io pins 
	pin_pos = 0;
	printf("read veb actual io pins, io number %d\n", num_input + num_output);	
	while (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{
//		printf("%s \n", buffer);	
		ptr = my_strtok(buffer," \t\n,=>;",vhdl,buffer);						
		ptr = my_strtok(NULL," \t\n,=>;",vhdl,buffer);						
		
		if ( (pin_pos + 1) == (num_input + num_output))
		{
			//end of reading I/O
			
			
//			printf("%s,  pin_pos %d, num_input %d, num_output %d\n", ptr, pin_pos, num_input, num_output);
			
			strncpy(netname, ptr, strlen(ptr) -1);
			netname[strlen(ptr) -1] = '\0';
			
			entry = convert_ouput(netname);	
			
			if (entry == -1)
			{
				strcpy(saved_names[pin_pos], netname);
//				strncpy(saved_names[pin_pos], netname, EBBUFSIZE);
	
			}
			else
			{
				strcpy(saved_names[pin_pos], oname[entry].output_name);
//				strncpy(saved_names[pin_pos], oname[entry].output_name, EBBUFSIZE);

			}
			
			//strncpy(saved_names[pin_pos], ptr, strlen(ptr) -1);
			//saved_names[pin_pos][strlen(ptr) -1] = '\0';
			pin_pos ++;
			//printf("Finish pin_pos %d \n", pin_pos);
			break;
		}
		else
		{
//			printf("%s,  pin_pos %d, num_input %d, num_output %d\n", ptr, pin_pos, num_input, num_output);
			entry = convert_ouput(ptr);	
			if (entry == -1)
			{
			//	printf("%s \n", ptr);
				strcpy(saved_names[pin_pos], ptr);
//				strncpy(saved_names[pin_pos], ptr, EBBUFSIZE);

			}
			else
			{
				//printf("convert name \n");
				strcpy(saved_names[pin_pos], oname[entry].output_name);
//				strncpy(saved_names[pin_pos], oname[entry].output_name, EBBUFSIZE);

			}
			pin_pos ++;
			//printf("pin_pos %d \n", pin_pos);

		}			
	}
		
//	printf("add net \n");
	if (!doall)
	{
		for(i= 0; i<num_input; i++)
		{
//			printf("%s \n", saved_names[i]);

			add_net(saved_names[i], RECEIVER, num_blocks -1, doall);
		}
		
		for (j= 0; j<num_output; j++)
		{		
//			printf("%s \n", saved_names[num_input + j ]);

			add_net(saved_names[num_input + j], DRIVER, num_blocks-1, doall);			
		}
		
		add_block_name_to_block_name_list(blockname);
		
//		printf("before free\n");
/*
		for (i= 0; i < MAXEB; i++)
		{
//			printf("%s \n", saved_names[i]);
//			printf("free %d \n", i);
			if (saved_names[i] != NULL)
				free(saved_names[i]);	
		}
		if (saved_names != NULL)
			free(saved_names);	
*/
		return;
	}
	
//	printf("finish add net \n");

	//set the block
	
	block[num_blocks-1].num_nets = num_input + num_output;
	block[num_blocks-1].type =  type;
	block[num_blocks-1].carryout_to = -1;
	block[num_blocks-1].carryout_to_name = (char *)NULL;
	block[num_blocks-1].num_input = num_input;
	block[num_blocks-1].num_output = num_output;
	block[num_blocks-1].use_lut = 0;
	block[num_blocks-1].use_ff = 0;
	block[num_blocks-1].use_xorcy = 0;
	block[num_blocks-1].use_muxcy = 0;
	block[num_blocks-1].use_inv = 0;
	block[num_blocks-1].use_inv_ce = 0;
	block[num_blocks-1].use_inv_sr = 0;
	block[num_blocks-1].use_inv_clk = 0;
	block[num_blocks-1].use_ff_int_conn = 0;
	block[num_blocks-1].use_mult_and = 0;
	block[num_blocks-1].use_muxf = 0;
	block[num_blocks-1].lut_type = type;
	
	//null_function(num_blocks-1,lut_size);
	
	
	for(i= 0;i< num_input + num_output; i++)
	{
		block[num_blocks-1].nets[i] = OPEN;
	}
	
	//input
	for(i= 0; i<num_input; i++)
	{

		block[num_blocks -1].nets[i] = add_net(saved_names[i], RECEIVER, num_blocks -1, doall);
	}
	//output
	for(i= 0; i<num_output; i++)
	{

		block[num_blocks -1].nets[num_input + i] = add_net(saved_names[num_input + i], DRIVER, num_blocks -1, doall);
		
		//printf("%s,  %d\n", saved_names[num_input+i], block[num_blocks -1].nets[num_input + i]);	
	}
	
				
	len = strlen (blockname);
	block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
	strcpy(block[num_blocks-1].name, blockname);

	if (get_index_in_block_name_list(block[num_blocks-1].name) != num_blocks-1) 
	{
		printf("Error: inconsistency in block_name_list %d %d\n",
		get_index_in_block_name_list(block[num_blocks-1].name),num_blocks-1);
 	}

//	printf("final free \n");
/*	
	for (i= 0; i < MAXEB; i++)
	{
		if (saved_names[i] != NULL)
			free(saved_names[i]);	
	}
	if (saved_names != NULL)
		free(saved_names);	
*/
}

void add_internal (int doall, int lut_size,  enum block_types type, char* blockname)
{
//	char *ptr, saved_names[MAXLUT+2][BUFSIZE], buf[BUFSIZE];
	char *ptr, buf[BUFSIZE];

	int i, j, len;

	char  buffer[BUFSIZE];
	char  buffer2[BUFSIZE];
	char netname[BUFSIZE];
	char *tempptr;
	int get_input_line;
	int num_input;
	int num_output;
	int num_nets;
	
	int entry;

	num_nets = 0;
	num_blocks++;

	if (type == INV)
	{
		//get I
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[0], tempptr);			
		}

		//get O
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			
			//strncpy (saved_names[1],ptr, strlen(ptr) -2);
			//saved_names[1][strlen(ptr) -2] = '\0';
			
			strncpy (netname,ptr, strlen(ptr) -2);
			netname[strlen(ptr) -2] = '\0';
			
			
			entry = convert_ouput(netname);	
						
			if (entry == -1)
			{
				strcpy(saved_names[1], netname);
			}
			else
			{
				strcpy(saved_names[1], oname[entry].output_name);
			}
			
			
		}
		
		num_nets = 2;
	}

	if (type == MULT_AND)
	{
		//get I0
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[0], tempptr);			
		}

		//get I1
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[1], tempptr);			
		}

		//get LO
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			//strncpy (saved_names[2],ptr, strlen(ptr) -2); 	
			//saved_names[2][strlen(ptr) -2] = '\0';
			
			strncpy (netname,ptr, strlen(ptr) -2);
			netname[strlen(ptr) -2] = '\0';
			
			
			entry = convert_ouput(netname);	
						
			if (entry == -1)
			{
				strcpy(saved_names[2], netname);
			}
			else
			{
				strcpy(saved_names[2], oname[entry].output_name);
			}
		}

		num_nets = 3;
	}

	if (!doall) 
	 {   // If only a counting pass ... 
		add_net(saved_names[0],RECEIVER,num_blocks-1,doall);  		
		
		if (num_nets == 2)
		{
			add_net(saved_names[1],DRIVER,num_blocks-1,doall);     
		}
		else
		{
			add_net(saved_names[1],RECEIVER,num_blocks-1,doall);     
			add_net(saved_names[2],DRIVER,num_blocks-1,doall);     
		}
					
		add_block_name_to_block_name_list(blockname);

		return;
	}


	block[num_blocks-1].carryout_to = -1;
	block[num_blocks-1].carryout_to_name = (char *)NULL;
	block[num_blocks-1].type = type;
	block[num_blocks-1].num_nets = num_nets;
	block[num_blocks-1].use_lut = 0;
	block[num_blocks-1].use_ff = 0;
	block[num_blocks-1].use_xorcy = 0;
	block[num_blocks-1].use_muxcy = 0;
	block[num_blocks-1].use_inv = 0;
	block[num_blocks-1].use_inv_ce = 0;
	block[num_blocks-1].use_inv_sr = 0;
	block[num_blocks-1].use_inv_clk = 0;
	block[num_blocks-1].use_ff_int_conn = 0;
	block[num_blocks-1].use_mult_and = 0;
	block[num_blocks-1].use_muxf = 0;

	//set all net to open first
	for (i=0; i< B_LUT_IN + lut_size; i++)
	{
		block[num_blocks-1].nets[i] = OPEN;
	}

	if (num_nets ==2)
	{
		//inv
		block[num_blocks-1].nets[INV_O] = add_net(saved_names[1],DRIVER,num_blocks-1, doall);		//O, y
		block[num_blocks-1].nets[INV_IN] = add_net(saved_names[0],RECEIVER, num_blocks-1,doall);	//I

		block[num_blocks-1].use_inv = 1;
	}
	else
	{
		//mult_and
		block[num_blocks-1].nets[MULTAND_O] = add_net(saved_names[2],DRIVER,num_blocks-1, doall);		//LO, y
		block[num_blocks-1].nets[MULTAND_I0] = add_net(saved_names[0],RECEIVER, num_blocks-1,doall);	//I0, lut_in[0]
		block[num_blocks-1].nets[MULTAND_I1 ] = add_net(saved_names[1],RECEIVER, num_blocks-1,doall);	//I1, lut_in[1]	

		block[num_blocks-1].use_mult_and = 1;
	}
			
	len = strlen (blockname);
	block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
	strcpy(block[num_blocks-1].name,blockname);

}


int convert_ouput(char * netname)
{
	//return the entry number of the oname_convert
	int i;
				
	for (i= 0; i< num_name_convert; i++)
	{
		if(strcmp(oname[i].net_name, netname) ==0)
		{
			return i;
		}	
	}
			
	return -1;
}


void add_dsp (int doall, int lut_size,  enum block_types type, char* blockname, char* dsp_name)
{
//	char *ptr, saved_names[MAXLUT+ MAXLUT][BUFSIZE], buf[BUFSIZE];
	char *ptr, buf[BUFSIZE];
//	char ** saved_names;

	int i, j, len;

	char  buffer[BUFSIZE];	
	char netname[BUFSIZE];
	char *tempptr;
	int get_input_line;
	int num_input;
	
	int num_output;
	int num_nets;
		
	int pin_pos;

/*		
	saved_names = malloc(sizeof(char*) * (MAXEB));
	for (i= 0; i < MAXEB; i++)
	{
		saved_names[i] = malloc(sizeof(char) * BUFSIZE);
	}
*/	
	num_nets = 0;
	
	num_blocks++;
	//printf ("number of block = %d \n", num_blocks);
			
	if (type == DSP)
	{
		//out : P (0-35)
		//in : A (0-17), B(0-17)
		num_input = 36;
		num_output = 36;
		//printf ("num_input =%d , num_output=%d \n", num_input, num_output);
	}else if (type == DSPS)
	{
		//out : P (0-35)
		//in : A (0-17), B(0-17), C, CE, R
		num_input = 39;
		num_output = 36;
	}

	//read the actual io pins 
	pin_pos = 0;
	//printf("read dsp actual io pins, io number %d\n", num_input + num_output);	
	while (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
	{	
		ptr = my_strtok(buffer," \t\n,=>;",vhdl,buffer);						
		ptr = my_strtok(NULL," \t\n,=>;",vhdl,buffer);						
		
		if ( (pin_pos + 1) == (num_input + num_output))
		{
			//end of reading I/O			
			
			strncpy(netname, ptr, strlen(ptr) -1);
			netname[strlen(ptr) -1] = '\0';												
			strcpy(saved_names[pin_pos], netname);									
			pin_pos ++;			
			break;
		}
		else
		{
			//printf("%s\n", ptr);												
			strcpy(saved_names[pin_pos], ptr);			
			pin_pos ++;
			//printf("pin_pos %d \n", pin_pos);

		}			
	}
		
	if (!doall)
	{	
		for (j= 0; j<num_output; j++)
		{			
			add_net(saved_names[j], DRIVER, num_blocks-1, doall);			
		}
		
		for(i= 0; i<num_input; i++)
		{
			add_net(saved_names[num_output + i], RECEIVER, num_blocks -1, doall);	
		}

		
		add_block_name_to_block_name_list(blockname);
	/*	
		for (i= 0; i < MAXEB; i++)
		{
			free(saved_names[i]);	
		}
		free(saved_names);	
*/
		return;
	}
	
	
	//set the block
	
	block[num_blocks-1].num_nets = num_input + num_output;
	block[num_blocks-1].type =  type;
	block[num_blocks-1].carryout_to = -1;
	block[num_blocks-1].carryout_to_name = (char *)NULL;
	block[num_blocks-1].num_input = num_input;
	block[num_blocks-1].num_output = num_output;
	block[num_blocks-1].use_lut = 0;
	block[num_blocks-1].use_ff = 0;
	block[num_blocks-1].use_xorcy = 0;
	block[num_blocks-1].use_muxcy = 0;
	block[num_blocks-1].use_inv = 0;
	block[num_blocks-1].use_inv_ce = 0;
	block[num_blocks-1].use_inv_sr = 0;
	block[num_blocks-1].use_inv_clk = 0;
	block[num_blocks-1].use_ff_int_conn = 0;
	block[num_blocks-1].use_mult_and = 0;
	block[num_blocks-1].use_muxf = 0;
	block[num_blocks-1].lut_type = type;
	
	//null_function(num_blocks-1,lut_size);
	
	
	for(i= 0;i< num_input + num_output; i++)
	{
		block[num_blocks-1].nets[i] = OPEN;
	}
	
	printf ("Block name : %s \n", blockname);
	//output
	for(i= 0; i<num_output; i++)
	{
		block[num_blocks -1].nets[i] = add_net(saved_names[i], DRIVER, num_blocks -1, doall);
		
		//printf("%s,  %d\n", saved_names[i], block[num_blocks -1].nets[i]);	
	}

	//input
	for(i= 0; i<num_input; i++)
	{
		block[num_blocks -1].nets[num_output + i] = add_net(saved_names[num_output + i], RECEIVER, num_blocks -1, doall);
		//printf("%s,  %d\n", saved_names[num_output+i], block[num_blocks -1].nets[num_output+i]);	
	}
	
				
	len = strlen (blockname);
	block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
	strcpy(block[num_blocks-1].name, blockname);

	if (get_index_in_block_name_list(block[num_blocks-1].name) != num_blocks-1) 
	{
		printf("Error: inconsistency in block_name_list %d %d\n",
		get_index_in_block_name_list(block[num_blocks-1].name),num_blocks-1);
 	}
/*
	for (i= 0; i < MAXEB; i++)
	{
		free(saved_names[i]);	
	}
	free(saved_names);	
*/

}


void add_muxf (int doall, int lut_size,  enum block_types type, char* blockname)
{
//	char *ptr, saved_names[MAXLUT+2][BUFSIZE], buf[BUFSIZE];
	char *ptr, buf[BUFSIZE];

	int i, j, len;

	char  buffer[BUFSIZE];
	char  buffer2[BUFSIZE];
	char netname[BUFSIZE];
	char *tempptr;
	int get_input_line;
	int num_input;
	int num_output;
	int num_nets;
	
	int entry;

	num_nets = 0;
	num_blocks++;

/*	
	saved_names = malloc(sizeof(char*) * (MAXLUT));
	for (i= 0; i < MAXLUT; i++)
	{
		saved_names[i] = malloc(sizeof(char) * BUFSIZE);
	}
*/
	if (type == MUXF) 
	{
		//get I0			
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[0], tempptr);			
		}

		//get I1
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);	
			strcpy (saved_names[1], tempptr);			
		}

		//get S
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name

			tempptr = my_strtok(ptr,",",vhdl, ptr);				
			strcpy (saved_names[2], tempptr);			
		}

		//get O		
		if (my_fgets(buffer,BUFSIZE,vhdl) != NULL)
		{				
			//get the netname
			ptr = my_strtok(buffer,TOKENS,vhdl,buffer);						
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	
			ptr = my_strtok(NULL,TOKENS,vhdl,buffer);	//get the net name
			
			
			strncpy (netname,ptr, strlen(ptr) -2); 						
			netname[strlen(ptr) -2] = '\0';
						
			strcpy (saved_names[3], netname);		
										
		}		

		num_nets = 4;
	}
	 
	if (!doall) 
	 {   // If only a counting pass ... 
		add_net(saved_names[0],RECEIVER,num_blocks-1,doall);  
		add_net(saved_names[1],RECEIVER,num_blocks-1,doall);   
		
		
		add_net(saved_names[2],RECEIVER,num_blocks-1,doall);     
		add_net(saved_names[3],DRIVER,num_blocks-1,doall);     		
					
		add_block_name_to_block_name_list(blockname);
		return;
	}


	block[num_blocks-1].carryout_to = -1;
	block[num_blocks-1].carryout_to_name = (char *)NULL;
	block[num_blocks-1].type = type;
	block[num_blocks-1].num_nets = num_nets;
	block[num_blocks-1].use_lut = 0;
	block[num_blocks-1].use_ff = 0;
	block[num_blocks-1].use_inv = 0;
	block[num_blocks-1].use_inv_ce = 0;
	block[num_blocks-1].use_inv_sr = 0;
	block[num_blocks-1].use_inv_clk = 0;
	block[num_blocks-1].use_ff_int_conn = 0;
	block[num_blocks-1].use_mult_and = 0;
	block[num_blocks-1].use_xorcy = 0;
	block[num_blocks-1].use_muxcy = 0;

	block[num_blocks-1].use_muxf = 1;

	//set all net to open first
	for (i=0; i< B_LUT_IN + lut_size; i++)
	{
		block[num_blocks-1].nets[i] = OPEN;
	}


	block[num_blocks-1].nets[MUXF_O] = add_net(saved_names[3],DRIVER,num_blocks-1, doall);		//O
	block[num_blocks-1].nets[MUXF_I0] = add_net(saved_names[0],RECEIVER, num_blocks-1,doall);	//I0
	block[num_blocks-1].nets[MUXF_I1] = add_net(saved_names[1],RECEIVER, num_blocks-1,doall);	//I1
	block[num_blocks-1].nets[MUXF_S] = add_net(saved_names[2],RECEIVER, num_blocks-1,doall);	//S

					
	len = strlen (blockname);
	block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char));
	strcpy(block[num_blocks-1].name,blockname);
}
