#!/usr/bin/env python

"""#!/usr/bin/python """
import re
import sys
import os

#######Script start from here
print "Arguement is :", sys.argv[1]
fname = os.path.basename(sys.argv[1])
print "VHDL filename is :",fname
home = os.path.expanduser("~")
###########Creating connection_info.txt file from vhdl file#####################
read_vhdl = open(sys.argv[1],'r')
vhdl_data = read_vhdl.readlines()
read_vhdl.close()

start_flag = -1 #Used for scaning part of data
scan_data=[]
#p=re.search('port(.*?)end',read_vhdl,re.M|re.I|re.DOTALL).group()

for item in vhdl_data:
    if re.search('port',item,re.I):
        start_flag = 1
        
    elif re.search("end",item,re.I):
        start_flag = 0
    else:
        pass

    if start_flag == 1:
        item=re.sub("port", " ", item, flags=re.I)
        item=re.sub("\(", " ", item, flags=re.I)
        item=re.sub("\)", " ", item, flags=re.I)
        item=re.sub(";"," ",item,flags=re.I)
        
        scan_data.append(item.rstrip())
        scan_data=filter(None, scan_data)
    elif start_flag == 0:
        break
    
#print "Scan Data",scan_data
port_info=[]

for item in scan_data:
    print "Scan Data :",item
    if re.search("in",item,flags=re.I):
        if re.search("std_logic_vector",item,flags=re.I):
            temp=re.compile(r"\s*std_logic_vector\s*",flags=re.I)
        elif re.search("std_logic",item,flags=re.I):
            temp=re.compile(r"\s*std_logic\s*",flags=re.I)
        else:
            print "Please check your vhdl code for datatype of input port"
            sys.exit()
    elif re.search("out",item,flags=re.I):
        if re.search("std_logic_vector",item,flags=re.I):                                                                                      
            temp=re.compile(r"\s*std_logic_vector\s*",flags=re.I)                                                               
        elif re.search("std_logic",item,flags=re.I):                                                                                           
            temp=re.compile(r"\s*std_logic\s*",flags=re.I)                                                                      
        else:                                                                                                                                  
            print "Please check your vhdl code for datatype of output port"
            sys.exit()
    else:
        print "Please check the in/out direction of your port"
        sys.exit()
        
    lhs=temp.split(item)[0]
    rhs=temp.split(item)[1]
    bit_info=re.compile(r"\s*downto\s*",flags=re.I).split(rhs)[0]
    port_info.append(lhs+":"+str(int(bit_info)+int(1)))

print "Port Info :",port_info

#Open connection_info.txt file 

con_ifo=open('connection_info.txt','w')

for item in port_info:
    word=item.split(':')
    con_ifo.write(word[0].strip()+' '+word[1].strip()+' '+word[2].strip())
    con_ifo.write("\n")
con_ifo.close()
############### Reading connection/port information#############################

#Declaring input and output list
input_list=[]
output_list=[]

#Reading connection_info.txt file for port infomation
read_file=open('connection_info.txt','r')
data=read_file.readlines()
read_file.close()

#Extracting input and output port list from data
for line in data:
    if re.match(r'^\s*$', line):
        pass
        #print "Blank Line"
    else:
        in_items=re.findall("IN",line,re.MULTILINE|re.IGNORECASE)
        out_items=re.findall("OUT",line,re.MULTILINE|re.IGNORECASE)
        #print "Line",line
        if in_items:
            input_list.append(line.split())
            #print "Found IN"
        else:
            pass
            #print "Not Found"
        
        if out_items:
            output_list.append(line.split())
            #print "Found Out"
        else:
            pass

print "Inout List :",input_list
print "Output list",output_list
input_port=[]
output_port=[]
#creating list of input and output port with its weight 
for input in input_list:
    input_port.append(input[0]+":"+input[2])
    #print "Input List: ",input
for output in output_list:
    output_port.append(output[0]+":"+output[2])
    #print "Output List: ",output

print "Output Port List : ",output_port
print "Input Port List : ",input_port

######################Creating content for cfunc.mod file#######################
print "Starting With cfunc.mod file"
cfunc=open('cfunc.mod','w')

print "Building content for cfunc.mod file"

comment='''/* This is cfunc.mod file auto generated by gen_con_info.py
Developed by Fahim at IIT Bombay */ \n 
        '''

header='''
#include <stdio.h>                                                                                                                             
#include <math.h>                                                                                                                              
#include <string.h>                                                                                                                            
#include <time.h>                                                                                                                              
#include <sys/socket.h>                                                                                                                        
#include <sys/types.h>                                                                                                                         
#include <netinet/in.h>                                                                                                                        
#include <netdb.h>                                                                                                                             
#include <stdlib.h>                                                                                                                            
#include <unistd.h>                                                                                                                            
#include <errno.h> 
'''

function_open='''void cm_'''+fname.split('.')[0]+'''(ARGS) \n{'''

digital_state_output=[]
for item in output_port:
    digital_state_output.append("Digital_State_t *_op_"+item.split(':')[0]+", *_op_"+item.split(':')[0]+"_old;")


var_section='''
    // Declaring components of Client                                                                                                          
    static int flag=0;                                                                                                                         
    FILE *log_client = NULL;                                                                                                                   
    log_client=fopen("client.log","a");                                                                                                        
    int socket_fd, bytes_recieved;                                                                                                             
    char send_data[1024];                                                                                                                      
    char recv_data[1024];
    char *key_iter;
    struct hostent *host;                                                                                                                      
    struct sockaddr_in server_addr;                                                                                                            
    double time_limit = PARAM(stop_time);
    int sock_port = 5000+PARAM(instance_id);
'''
temp_input_var=[]
for item in input_port:
    temp_input_var.append("char temp_"+item.split(':')[0]+"[1024];")

#Start of INIT function 
init_start_function='''
    if(INIT)
    {
        /* Allocate storage for output ports.And set the load for input ports */
'''
  
cm_event_alloc=[]
cm_count_output=0
for item in output_port:
   cm_event_alloc.append("cm_event_alloc("+str(cm_count_output)+","+item.split(':')[1]+"*sizeof(Digital_State_t));")
   cm_count_output=cm_count_output+1

load_in_port=[]
for item in input_port:
    load_in_port.append("for(Ii=0;Ii<PORT_SIZE("+item.split(':')[0]+");Ii++)\n\t\t{\n\t\t\tLOAD("+item.split(':')[0]+"[Ii])=PARAM(input_load); \n\t\t}")

cm_count_ptr=0
cm_event_get_ptr=[]
for item in output_port:
    cm_event_get_ptr.append("_op_"+item.split(':')[0]+" = _op_"+item.split(':')[0]+"_old = (Digital_State_t *) cm_event_get_ptr("+str(cm_count_ptr)+",0);")
    cm_count_ptr=cm_count_ptr+1

systime_info='''
        /*Taking system time info for log */                                                                                                   
        time_t systime;                                                                                                                        
        systime = time(NULL);                                                                                                                  
        printf(ctime(&systime));                                                                                                               
        printf("Client-Initialising ngspice \\n");                                                                                              
        fprintf(log_client,"Setup Client Server Connection at %s \\n",ctime(&systime));                                                         
'''

init_else='''
        printf("Client-Inside else of INIT \\n");                                                                                               
        fprintf(log_client,"Inside else of INIT \\n");                                                                                          
        /*  retrieve storage for output ports. */
'''

els_evt_count1=0
els_evt_count2=0
els_evt_ptr=[]
for item in output_port:
    els_evt_ptr.append("_op_"+item.split(":")[0]+" = cm_event_get_ptr("+str(els_evt_count1)+","+str(els_evt_count2)+");")
    els_evt_count2=els_evt_count2+1
    els_evt_ptr.append("_op_"+item.split(":")[0]+"_old"+" = cm_event_get_ptr("+str(els_evt_count1)+","+str(els_evt_count2)+");")
    els_evt_count1=els_evt_count1+1


client_setup='''
        /* Client setup */                                                                                                                     
        //Default hostname assignment                                                                                                          
        host = gethostbyname("127.0.0.1");                                                                                                     
        printf("Client-Creating Client Socket \\n");                                                                                             
        fprintf(log_client,"Creating client socket \\n"); 
'''
create_socket='''
        //Creating socket for client                                                                                                           
        if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)                                                                               
        {                                                                                                                                      
            perror("Client-Error while creating client Socket \\n");                                                                             
            fprintf(log_client,"Error while creating client sockte \\n");                                                                        
            exit(1);                                                                                                                           
        }                                                                                                                                      
                                                                                                                                                              
        printf("Client-Client Socket created successfully \\n");                                                                                 
        printf("Client- Socket Id : %d \\n",socket_fd);                                                                                         
        fprintf(log_client,"Client-Client Socket created successfully \\n");                                                                     
        fprintf(log_client,"Client- Socket Id : %d \\n",socket_fd);                                                                             

        // memset(&server_addr, 0, sizeof(server_addr));                                                                                       
        server_addr.sin_family = AF_INET;                                                                                                      
        server_addr.sin_port = htons(sock_port);                                                                                                    
        server_addr.sin_addr = *((struct in_addr *)host->h_addr);                                                                              
        bzero(&(server_addr.sin_zero),8);                                                                                                      

'''

connect_server='''
        printf("Client-Connecting to server \\n");                                                                                              
        fprintf(log_client,"Client-Connecting to server \\n");                                                                                  
        //Conneting to server                                                                                                                  

        int try_limit=10;                                                                                                                      
        while(try_limit>0)                                                                                                                     
        {                                                                                                                                      
            if (connect(socket_fd, (struct sockaddr*)&server_addr,sizeof(struct sockaddr)) == -1)                                              
            {                                                                                                                                  
                sleep(1);                                                                                                                      
                try_limit--;                                                                                                                   
                if(try_limit==0)                                                                                                               
                {                                                                                                                              
                    fprintf(stderr,"Connect- Error:Tried to connect server on port , failed..giving up \\n");                                   
                    fprintf(log_client,"Connect- Error:Tried to connect server on port , failed..giving up \\n");                               
                    exit(1);                                                                                                                   
                }                                                                                                                              
            }                                                                                                                                
            else                                                                                                                               
            {                                                                                                                                  
                printf("Client-Connected to server \\n");                                                                                       
                fprintf(log_client,"Client-Connected to server \\n");                                                                           
                break;                                                                                                                         
            }                                                                                                                                  
        } 

'''

time_limit ='''
        if(TIME < time_limit)                                                                                                                  
        {                                                                                                                                      
            //Formating data for sending it to client
            int Ii;

'''
#Assign bit value to every input
assign_data_to_input=[]
for item in input_port:
    assign_data_to_input.append("\t\t\tfor(Ii=0;Ii<PORT_SIZE("+item.split(':')[0]+");Ii++)\n\
\t\t\t{\n\t\t\t\tif( INPUT_STATE("+item.split(':')[0]+"[Ii])==ZERO )\n\
\t\t\t\t{\n\t\t\t\t\ttemp_"+item.split(':')[0]+"[Ii]='0';\n\t\t\t\t}\n\
\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttemp_"+item.split(':')[0]+"[Ii]='1';\n\
\t\t\t\t}\n\t\t\t}\n\t\t\ttemp_"+item.split(':')[0]+"[Ii]='\\0';\n\n")


snprintf_stmt=[]
snprintf_count=0
snprintf_stmt.append("\t\t\t//Sending and receiving data to-from server \n")
snprintf_stmt.append('\t\t\tsnprintf(send_data,sizeof(send_data),"')
for item in input_port:
    snprintf_count=snprintf_count+1
    snprintf_stmt.append(item.split(':')[0]+":%s")
    if snprintf_count == len(input_port):
        snprintf_stmt.append('",')
        internal_count=0
        for item1 in input_port:
            if internal_count == len(input_port):
                pass
            else:    
                snprintf_stmt.append("temp_"+item1.split(':')[0])
                internal_count=internal_count+1
                if internal_count == len(input_port):
                    pass
                else:
                    snprintf_stmt.append(",")
        snprintf_stmt.append(");")
    else:
        snprintf_stmt.append(",")

snprintf_stmt.append('\n\t\t\tprintf("Client-Value of buffer string is %s \\n",send_data);')
snprintf_stmt.append('\n\t\t\tprintf("Client-Sending data to server from client \\n");')

send_data='''

            if ( send(socket_fd,send_data,sizeof(send_data),0)==-1)                                                                            
            {                                                                                                                                  
                fprintf(stderr, "Client-Failure Sending Message \\n");                                                                           
                close(socket_fd);                                                                                                              
                exit(1);                                                                                                                       
            }                                                                                                                                  
            else                                                                                                                               
            {                                                                                                                                  
                printf("Client-Message being sent: %s \\n",send_data);                                                                           
                fprintf(log_client,"Socket Id : %d & Message sent : %s \\n",socket_fd,send_data);                                               
            }

'''

recv_data='''

            bytes_recieved=recv(socket_fd,recv_data,sizeof(recv_data),0);                                                                      
            if ( bytes_recieved <= 0 )                                                                                                         
            {                                                                                                                                  
                printf("Client-Either Connection Closed or Error \\n");                                                                          
                exit(1);                                                                                                                       
            }                                                                                                                                  
            recv_data[bytes_recieved] = '\\0';                                                                                                
            
            printf("Client-Message Received From Server -  %s\\n",recv_data);                                                                   
            fprintf(log_client,"Message Received From Server- %s\\n",recv_data);   

'''

#Scheduling output event

sch_output_event=[]

for item in output_port:
    sch_output_event.append("\t\t\t/* Scheduling event and processing them */\n\
\t\t\tif((key_iter=strstr(recv_data, "+'"'+item.split(':')[0]+':"'")) != NULL)\n\
\t\t\t{\n\
\t\t\twhile(*key_iter++ != ':');\n\
\t\t\tfor(Ii=0;*key_iter != ';';Ii++,key_iter++)\n\
\t\t\t{\n\
\t\t\t\tprintf(\"Client- Bit val is %c \\n\",*key_iter);\n\
\t\t\t\tfprintf(log_client,\"Client-Bit val is %c \\n\",*key_iter);\n\
\t\t\t\tif(*key_iter=='0')\n\t\t\t\t{\n\
\t\t\t\t\tprintf(\"Client-Zero Received \");\n\
\t\t\t\t\t_op_"+item.split(':')[0]+"[Ii]=ZERO;\n\t\t\t\t}\n\
\t\t\t\telse if(*key_iter=='1')\n\t\t\t\t{\n\
\t\t\t\t\tprintf(\"Client-One Received \\n\");\n\
\t\t\t\t\t_op_"+item.split(':')[0]+"[Ii]=ONE;\n\
\t\t\t\t}\n\t\t\t\telse\t\t\t\t{\n\
\t\t\t\t\tfprintf(log_client,\"Unknow value return from server \\n\");\n\
\t\t\t\t\tprintf(\"Client-Unknown value return \\n\");\n\t\t\t\t}\n\
\t\t\t\tif(ANALYSIS == DC)\n\t\t\t\t{\n\
\t\t\t\t\tOUTPUT_STATE("+item.split(':')[0]+"[Ii]) = _op_"+item.split(':')[0]+"[Ii];\n\
\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\
\t\t\t\t\tif(_op_"+item.split(':')[0]+"[Ii] != _op_"+item.split(':')[0]+"_old[Ii])\n\
\t\t\t\t\t{\n\
\t\t\t\t\t\tOUTPUT_STATE("+item.split(':')[0]+"[Ii]) = _op_"+item.split(':')[0]+"[Ii];\n\
\t\t\t\t\t\tOUTPUT_DELAY("+item.split(':')[0]+"[Ii]) = ((_op_"+item.split(':')[0]+"[Ii] == ZERO) ? PARAM(fall_delay) : PARAM(rise_delay));\n\
\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\
\t\t\t\t\t\tOUTPUT_CHANGED("+item.split(':')[0]+"[Ii]) = FALSE;\n\t\t\t\t\t}\n\
\t\t\t\t}\n\t\t\t\tOUTPUT_STRENGTH("+item.split(':')[0]+"[Ii]) = STRONG;\n\
\t\t\t}\n\
\t\t\t}\n")


els_time_limit='''

        else                                                                                                                                   
        {                                                                                                                                     
            char *end_signal="END";                                                                                                            
            printf("Closing Ngspice Simulation \\n");                                                                                           
            printf("current time = %g\\n",TIME);                                                                                                
            fprintf(log_client,"Times : Closing Socket \\n");                                                                                   
            snprintf(send_data,sizeof(send_data),"%s",end_signal);                                                                             
            printf("Client-Value of buffer string is for END signal is %s \\n",send_data);                                                      
            printf("Client-Sending data to server from client for end signal \\n");                                                             
            
            if ( send(socket_fd,send_data,sizeof(send_data),0)==-1)                                                                            
            {                                                                                                                                  
                printf("Client-Failure Sending Message for END signal \\n");                                                                    
                close(socket_fd);                                                                                                              
                exit(1);                                                                                                                       
            }                                                                                                                                  
            else                                                                                                                               
            {                                                                                                                                  
                printf("Client-Message being sent for END signal : %s\\n",send_data);                                                           
                fprintf(log_client,"Socket Id : %d & Message sent : %s for END signal \\n",socket_fd,send_data);                                
            }                                                                                                                                  
            flag++;                                                                                                                            
            close(socket_fd);                                                                                                                  
        }    

'''


#Writing content in cfunc.mod file 
cfunc.write(comment)
cfunc.write(header)
cfunc.write("\n")
cfunc.write(function_open)
cfunc.write("\n")

#Adding digital state Variable
for item in digital_state_output:
    cfunc.write("\t"+item+"\n")
    
#Adding variable declaration section
cfunc.write(var_section)
for item in temp_input_var:
    cfunc.write("\t"+item+"\n")
cfunc.write("\n");

#Adding INIT portion
cfunc.write(init_start_function)
for item in cm_event_alloc:
    cfunc.write(2*"\t"+item)
    cfunc.write("\n")

cfunc.write(2*"\t"+"/* set the load for input ports. */")
cfunc.write("\n")
cfunc.write(2*"\t"+"int Ii;")
cfunc.write("\n");

for item in load_in_port:
    cfunc.write(2*"\t"+item)
    cfunc.write("\n")
cfunc.write("\n")
cfunc.write(2*"\t"+"/*Retrieve Storage for output*/")
cfunc.write("\n")
for item in cm_event_get_ptr:
    cfunc.write(2*"\t"+item)
    cfunc.write("\n")
cfunc.write(systime_info)
cfunc.write("\n")
cfunc.write("\t\tchar command[1024];")
cfunc.write('\t\tsnprintf(command,1024,"'+home+'/ngspice-26/src/xspice/icm/ghdl/'+fname.split('.')[0]+'/DUTghdl/start_server.sh %d &",sock_port);\n')
cfunc.write('\t\tsystem(command);')
cfunc.write("\t}")
cfunc.write("\n")
cfunc.write("\telse\n\t{\n")

for item in els_evt_ptr:
    cfunc.write(2*"\t"+item)
    cfunc.write("\n")
cfunc.write("\t}")
cfunc.write("\n\n")
cfunc.write("\tif(flag==0)\n\t{")
cfunc.write(client_setup)
cfunc.write(create_socket)
cfunc.write(connect_server)
cfunc.write(time_limit)

for item in assign_data_to_input:
    cfunc.write(item)

for item in snprintf_stmt:
    cfunc.write(item)

cfunc.write(send_data)
cfunc.write(recv_data)

for item in sch_output_event:
    cfunc.write(item)
#End of if statement of time limit
cfunc.write(2*"\t"+"}")

#Else part of time limit -sending END signal
cfunc.write(els_time_limit)

#Close if of flag==0
cfunc.write("\t}\n\n")

#close log_client file
cfunc.write("\tfclose(log_client);")

#Close cm_ function
cfunc.write("\n}")
cfunc.close()

################Creating ifspec.ifs file########################################
print "Starting with ifspec.ifs file"
ifspec=open('ifspec.ifs','w')

print "Gathering Al the content for ifspec file"

ifspec_comment='''
/*
SUMMARY: This file is auto generated and it contains the interface specification for the                                                                            
code model. */\n  
'''

name_table='NAME_TABLE:\n\
C_Function_Name: cm_'+fname.split('.')[0]+'\n\
Spice_Model_Name: '+fname.split('.')[0]+'\n\
Description: "Model generated from ghdl code '+fname+'" \n'

#Input and Output Port Table
in_port_table=[]
out_port_table=[]

for item in input_port:
    port_table = 'PORT_TABLE:\n'
    port_name = 'Port_Name:\t'+item.split(':')[0]+'\n'
    description = 'Description:\t"input port '+item.split(':')[0]+'"\n'
    direction = 'Direction:\tin\n'
    default_type = 'Default_Type:\td\n'
    allowed_type = 'Allowed_Types:\t[d]\n'
    vector = 'Vector:\tyes\n'
    vector_bounds = 'Vector_Bounds:\t['+item.split(':')[1]+' '+item.split(":")[1]+']\n'
    null_allowed = 'Null_Allowed:\tno\n'
    #Insert detail in the list
    in_port_table.append(port_table+port_name+description+direction+default_type+allowed_type+vector+vector_bounds+null_allowed)


for item in output_port:
    port_table = 'PORT_TABLE:\n'
    port_name = 'Port_Name:\t'+item.split(':')[0]+'\n'
    description = 'Description:\t"output port '+item.split(':')[0]+'"\n'
    direction = 'Direction:\tout\n'
    default_type = 'Default_Type:\td\n'
    allowed_type = 'Allowed_Types:\t[d]\n'
    vector = 'Vector:\tyes\n'
    vector_bounds = 'Vector_Bounds:\t['+item.split(':')[1]+' '+item.split(":")[1]+']\n'
    null_allowed = 'Null_Allowed:\tno\n'
    #Insert detail in the list
    in_port_table.append(port_table+port_name+description+direction+default_type+allowed_type+vector+vector_bounds+null_allowed)

parameter_table='''

PARAMETER_TABLE:
Parameter_Name:     instance_id
Description:        "instance_id"
Data_Type:          real
Default_Value:      0
Limits:             -
Vector:              no
Vector_Bounds:       -
Null_Allowed:       yes

PARAMETER_TABLE:                                                                                                                               
Parameter_Name:     rise_delay                  fall_delay                                                                                     
Description:        "rise delay"                "fall delay"                                                                                   
Data_Type:          real                        real                                                                                           
Default_Value:      1.0e-9                      1.0e-9                                                                                         
Limits:             [1e-12 -]                   [1e-12 -]                                                                                      
Vector:              no                          no                                                                                            
Vector_Bounds:       -                           -                                                                                             
Null_Allowed:       yes                         yes                                                                                            

PARAMETER_TABLE:                                                                                                                               
Parameter_Name:     input_load                  stop_time                                                                                      
Description:        "input load value (F)"      "time at which to shut-down (seconds)"                                                         
Data_Type:          real                        real                                                                                           
Default_Value:      1.0e-12                     1.0                                                                                            
Limits:             -                           [0.0 -]                                                                                        
Vector:              no                         no                                                                                             
Vector_Bounds:       -                          -                                                                                              
Null_Allowed:       yes                         no    

'''


#Writing all the content in ifspec file
ifspec.write(ifspec_comment)
ifspec.write(name_table+"\n\n")

for item in in_port_table:
    ifspec.write(item+"\n")

ifspec.write("\n")

for item in out_port_table:
    ifspec.write(item+"\n")

ifspec.write("\n")
ifspec.write(parameter_table)
ifspec.close()


########Creating testbench file ################################################
print "Starting with testbench file"

testbench=open(fname.split('.')[0]+'_tb.vhdl','w')
#comment
comment_vhdl="--------------------------------------------------------------------------------\n--This testbench has been created by Ambikeshwar Srivastava, FOSSEE, IIT Bombay\n-------------------------------------------------------------------------------"
#Adding header, entity and architecture statement
tb_header='''
library ieee;                                                                                                                                   
use ieee.std_logic_1164.all;                                                                                                                    
use ieee.numeric_std.all;                                                                                                                       
library work;                                                                                                                                   
use work.Vhpi_Foreign.all;                                                                                                                      
use work.Utility_Package.all;
use work.sock_pkg.all;


'''

tb_entity="entity "+fname.split('.')[0]+"_tb is\nend entity;\n\n"

arch="architecture "+fname.split('.')[0]+"_tb_beh of "+fname.split('.')[0]+"_tb is\n"

#Adding components

components=[]
components.append("\tcomponent "+fname.split('.')[0]+" is\n\t\tport(\n\t\t\t\t")

for item in input_port:
    components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
    #if item.split(":")[1] != '1':
    #    components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
    #else:
    #    components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")

for item in output_port[:-1]:
    components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
components.append(output_port[-1].split(':')[0]+": out std_logic_vector("+str(int(output_port[-1].split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")
    #if item.split(":")[1] != '1':                                                                                                               
    #    components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")                
    #else:                                                                                                                                       
    #    components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")

components.append(");\n")
components.append("\tend component;\n\n")

#Adding signals
signals=[]
signals.append("\tsignal clk_s : std_logic := '0';\n")

for item in input_port:
    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
    #if item.split(":")[1] != '1':                                                                                                               
    #    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")                
    #else:                                                                                                                                       
    #    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")


for item in output_port:
    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
    #if item.split(":")[1] != '1':                                                                                                               
    #    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")                
    #else:                                                                                                                                       
    #    signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")

#Adding mapping part 
map=[]
map.append("\tu1 : "+fname.split('.')[0]+" port map(\n")

for item in input_port:
    map.append("\t\t\t\t"+item.split(':')[0]+" => "+item.split(':')[0]+",\n")

for item in output_port:
    if output_port.index(item) == len(output_port) - 1:
        map.append("\t\t\t\t"+item.split(':')[0]+" => "+item.split(':')[0]+"\n")
    else:
        map.append("\t\t\t\t"+item.split(':')[0]+" => "+item.split(':')[0]+",\n")
map.append("\t\t\t);")


#testbench Clock
tb_clk= "clk_s <= not clk_s after 5 us;\n\n"
#Adding Process block for Vhpi
process_Vhpi=[]
process_Vhpi.append("\tprocess\n\t\tvariable sock_port : integer;\n\t\tbegin\n\t\tsock_port := sock_pkg_fun;\n\t\tVhpi_Initialize(sock_port);\n\t\twait until clk_s = '1';\n\t\twhile true loop\n\t\t\twait until clk_s = '0';\n\t\t\tVhpi_Listen;\n\t\t\twait for 1 us;\n\t\t\tVhpi_Send;\n\t\tend loop;\n\t\twait;\n\tend process;\n\n")
#Adding process block 
process=[]
process.append("\tprocess\n\n")

for item in input_port:
    process.append("\t\tvariable "+item.split(':')[0]+"_v : VhpiString;\n")

for item in output_port:
    process.append("\t\tvariable "+item.split(':')[0]+"_v : VhpiString;\n")

process.append("\t\tvariable obj_ref : VhpiString;\n")
process.append("\tbegin\n")
process.append("\t\twhile true loop\n")
process.append("\t\t\twait until clk_s = '0';\n\n")

for item in input_port:
    process.append('\t\t\tobj_ref := Pack_String_To_Vhpi_String("'+item.split(':')[0]+'");\n')
    process.append('\t\t\tVhpi_Get_Port_Value(obj_ref,'+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
    process.append('\t\t\tassert false report "Get port value '+item.split(':')[0]+' returns " &'+item.split(':')[0]+'_v severity note;\n')
    process.append('\t\t\t'+item.split(':')[0]+' <= Unpack_String('+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
    process.append("\n")

process.append('\t\t\twait for 1 us;\n')

for item in output_port:
    process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(Convert_SLV_To_String('+item.split(':')[0]+'));\n')
    process.append('\t\t\tobj_ref := Pack_String_To_Vhpi_String("'+item.split(':')[0]+'");\n')
    process.append('\t\t\tVhpi_Set_Port_Value(obj_ref,'+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
    process.append('\t\t\tassert false report "Set port value '+item.split(':')[0]+' returns " &'+item.split(':')[0]+'_v severity note;\n')
    process.append("\n")
process.append("\t\tend loop;\n")
process.append("\tend process;\n\n")
process.append("end architecture;")


#Writing all the components to testbench file
testbench.write(comment_vhdl)
testbench.write(tb_header)
testbench.write(tb_entity)
testbench.write(arch)

for item in components:
    testbench.write(item)

for item in signals:
    testbench.write(item)

testbench.write("\n\n")

testbench.write("begin\n\n")

for item in map:
    testbench.write(item)

testbench.write("\n\t"+tb_clk)

for item in process_Vhpi:
    testbench.write(item)

for item in process:
    testbench.write(item)


testbench.close()

##################################### Creating and writing components in start_server.sh ################################

start_server = open('start_server.sh','w')

start_server.write("#!/bin/bash\n\n")
start_server.write("###This server run ghdl testebench for infinite time till ngspice send END signal to stop it\n\n")
start_server.write("#gcc -c ghdlserver.c\n")
start_server.write("#ghdl -a Utility_Package.vhdl &&\n")
start_server.write("#ghdl -a Vhpi_Package.vhdl &&\n")
start_server.write("cd "+home+"/ngspice-26/src/xspice/icm/ghdl/"+fname.split('.')[0]+"/DUTghdl/\n")
start_server.write("chmod 775 sock_pkg_create.sh &&\n")
start_server.write("./sock_pkg_create.sh $1 &&\n")
start_server.write("ghdl -a sock_pkg.vhdl &&\n")
start_server.write("ghdl -a "+fname+" &&\n")
start_server.write("ghdl -a "+fname.split('.')[0]+"_tb.vhdl  &&\n")
start_server.write("ghdl -e -Wl,ghdlserver.o "+fname.split('.')[0]+"_tb &&\n")
start_server.write("./"+fname.split('.')[0]+"_tb")

start_server.close()

##################################### Creating and writing in sock_pkg_create.sh ########################################

sock_pkg_create = open('sock_pkg_create.sh','w')

sock_pkg_create.write("#!/bin/bash\n\n")
sock_pkg_create.write("##This file create sock_pkg_create.vhdl file and set the instance id from parameter based on parameter\n\n")
sock_pkg_create.write("echo \"library ieee;\n")
sock_pkg_create.write("package sock_pkg is\n")
sock_pkg_create.write("\tfunction sock_pkg_fun return integer;\n")
sock_pkg_create.write("end;\n\n")
sock_pkg_create.write("\tpackage body sock_pkg is\n")
sock_pkg_create.write("\t function sock_pkg_fun return integer is")
sock_pkg_create.write("\t\tvariable sock_id : integer;\n")
sock_pkg_create.write("\t\t\tbegin\n")
sock_pkg_create.write("\t\t\t\tsock_id := $1;\n")
sock_pkg_create.write("\t\t\t\treturn sock_id;\n")
sock_pkg_create.write("\t\t\tend function;\n")
sock_pkg_create.write("\t\tend package body;\" > sock_pkg.vhdl")