summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/createKicadLibrary.py23
-rwxr-xr-xsrc/ghdlserver/Vhpi_Package.vhdl16
-rw-r--r--src/ghdlserver/ghdlserver.c645
-rw-r--r--src/ghdlserver/ghdlserver.h3
-rw-r--r--src/model_generation.py241
-rwxr-xr-xsrc/ngspice_ghdl.py24
-rw-r--r--src/outitf.c891
7 files changed, 1135 insertions, 708 deletions
diff --git a/src/createKicadLibrary.py b/src/createKicadLibrary.py
index bf520d1..b66d487 100644
--- a/src/createKicadLibrary.py
+++ b/src/createKicadLibrary.py
@@ -10,10 +10,10 @@ class AutoSchematic(QtGui.QWidget):
def __init__(self, modelname):
QtGui.QWidget.__init__(self)
self.modelname = modelname.split('.')[0]
- self.template = Appconfig.kicad_lib_template
+ self.template = Appconfig.kicad_lib_template.copy()
self.xml_loc = Appconfig.xml_loc
self.lib_loc = Appconfig.lib_loc
- self.kicad_nghdl_lib = 'eSim_kicad.lib'
+ self.kicad_nghdl_lib = '/usr/share/kicad/library/eSim_Nghdl.lib'
self.parser = Appconfig.parser_nghdl
def createKicadLibrary(self):
@@ -21,14 +21,15 @@ class AutoSchematic(QtGui.QWidget):
for root, dirs, files in os.walk(self.xml_loc):
if (str(self.modelname) + '.xml') in files:
xmlFound = root
+ print(xmlFound)
if (xmlFound == None):
self.getPortInformation()
self.createXML()
self.createLib()
- elif (xmlFound == self.xml_loc + 'Nghdl'):
+ elif (xmlFound == self.xml_loc + '/Nghdl'):
print 'Library already exists...'
ret = QtGui.QMessageBox.critical(self, "Critical",'''<b>The Libraries of this model already exist.Do you want to overwrite it?</b><br/>
- <b>If yes press ok else cancel it and change the name of your vhdl file</b>''', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
+ <b>If yes, press ok else cancel it and change the name of your vhdl file</b>''', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
if ret == QtGui.QMessageBox.Ok:
print "Overwriting existing libraries"
self.getPortInformation()
@@ -43,7 +44,7 @@ class AutoSchematic(QtGui.QWidget):
ret = QtGui.QMessageBox.critical(self, "Error",'''<b>A standard library already exists in this name.</b><br/>
<b>Please change the name of your vhdl file and upload it again</b>''', QtGui.QMessageBox.Ok)
- quit()
+ # quit()
def getPortInformation(self):
portInformation = PortInfo(self)
@@ -124,7 +125,7 @@ class AutoSchematic(QtGui.QWidget):
lib_file = open(self.kicad_nghdl_lib,"a")
line1 = self.template["start_def"]
line1 = line1.split()
- line1 = [w.replace('comp_name', self.modelname) for w in line1]
+ line1 = [w.replace('comp_name', self.modelname) for w in line1]
self.template["start_def"] = ' '.join(line1)
if os.stat(self.kicad_nghdl_lib).st_size == 0:
lib_file.write("EESchema-LIBRARY Version 2.3"+ "\n\n")
@@ -164,8 +165,14 @@ class AutoSchematic(QtGui.QWidget):
output_port = output_port.split()
inputs = self.portInfo[0: self.input_length]
outputs = self.portInfo[self.input_length:]
+
+ print "INPUTS AND OUTPUTS "
+ print inputs
+ print outputs
+
inputs = self.char_sum(inputs)
outputs= self.char_sum(outputs)
+
total = inputs+outputs
port_list = []
@@ -191,7 +198,7 @@ class AutoSchematic(QtGui.QWidget):
os.chdir(cwd)
print 'Leaving directory, ', self.lib_loc
- QtGui.QMessageBox.information(self, "Library added", '''Library details for this model is added to the <b>eSim-kicad.lib</b> in the home directory''', QtGui.QMessageBox.Ok)
+ QtGui.QMessageBox.information(self, "Library added", '''Library details for this model is added to the <b>eSim_Nghdl.lib</b> in the KiCad shared directory''', QtGui.QMessageBox.Ok)
class PortInfo:
@@ -225,5 +232,3 @@ class PortInfo:
self.input_len = len(self.bit_list)
for out_list in output_list:
self.bit_list.append(out_list[2])
-
-
diff --git a/src/ghdlserver/Vhpi_Package.vhdl b/src/ghdlserver/Vhpi_Package.vhdl
index 0c0baac..600804c 100755
--- a/src/ghdlserver/Vhpi_Package.vhdl
+++ b/src/ghdlserver/Vhpi_Package.vhdl
@@ -1,4 +1,8 @@
-- author: Madhav P. Desai
+-- modified: Rahul Paknikar
+-- -changed procedure of Vhpi_Initialize - 26.Sept.2019
+-- -removed procedure Vhpi_Close - 15.Oct.2019
+
library ieee;
use ieee.std_logic_1164.all;
library work;
@@ -8,12 +12,9 @@ package Vhpi_Foreign is
-----------------------------------------------------------------------------
-- foreign Vhpi function
-----------------------------------------------------------------------------
- procedure Vhpi_Initialize(sock_port : in integer);
+ procedure Vhpi_Initialize(sock_port : in integer; sock_ip : in VhpiString);
attribute foreign of Vhpi_Initialize : procedure is "VHPIDIRECT Vhpi_Initialize";
- procedure Vhpi_Close; -- close .
- attribute foreign of Vhpi_Close : procedure is "VHPIDIRECT Vhpi_Close";
-
procedure Vhpi_Listen;
attribute foreign of Vhpi_Listen : procedure is "VHPIDIRECT Vhpi_Listen";
@@ -36,16 +37,11 @@ package body Vhpi_Foreign is
-----------------------------------------------------------------------------
-- subprogram bodies for foreign vhpi routines. will never be called
-----------------------------------------------------------------------------
- procedure Vhpi_Initialize(sock_port: in integer) is
+ procedure Vhpi_Initialize(sock_port: in integer; sock_ip : in VhpiString) is
begin
assert false report "fatal: this should never be called" severity failure;
end Vhpi_Initialize;
- procedure Vhpi_Close is
- begin
- assert false report "fatal: this should never be called" severity failure;
- end Vhpi_Close;
-
procedure Vhpi_Listen is
begin
assert false report "fatal: this should never be called" severity failure;
diff --git a/src/ghdlserver/ghdlserver.c b/src/ghdlserver/ghdlserver.c
index 09514e1..e05a156 100644
--- a/src/ghdlserver/ghdlserver.c
+++ b/src/ghdlserver/ghdlserver.c
@@ -1,5 +1,24 @@
-/*************************************************************************
- * <ghdlserver.c> FOSSEE, IIT-Mumbai
+/**********************************************************************************
+ * <ghdlserver.c> FOSSEE, IIT-Bombay
+ **********************************************************************************
+ * 08.Nov.2019 - Rahul Paknikar - Switched to blocking sockets from non-blocking
+ * - Close previous used socket to prevent from
+ * generating too many socket descriptors
+ * - Enabled SO_REUSEPORT, SO_DONTROUTE socket options
+ * 26.Sept.2019 - Rahul Paknikar - Added reading of IP from a file to
+ * support multiple digital models
+ * - On exit, the test bench removes the
+ * NGHDL_COMMON_IP_<ngspice_pid> file, shared by all
+ * nghdl digital models and is stored in /tmp
+ * directory. It tracks the used IPs for existing
+ * digital models in current simulation.
+ * - Writes PID file in append mode.
+ * 5.July.2019 - Rahul Paknikar - Added loop to send all port values for
+ * a given event.
+ * - Removed bug to terminate multiple testbench
+ * instances in ngpsice windows.
+ **********************************************************************************
+ **********************************************************************************
* 24.Mar.2017 - Raj Mohan - Added signal handler for SIGUSR1, to handle an
* orphan test bench process.
* The test bench will now create a PID file in
@@ -21,8 +40,8 @@
* Added the following functions:
* o curtim()
* o print_hash_table()
- *************************************************************************
- */
+ *********************************************************************************/
+
#include <string.h>
#include "ghdlserver.h"
#include "uthash.h"
@@ -33,9 +52,10 @@
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
#include <sys/time.h>
-#include <netinet/in.h>
+#include <netinet/in.h>
#include <netdb.h>
#include <limits.h>
#include <time.h>
@@ -45,16 +65,10 @@
#define _XOPEN_SOURCE 500
#define MAX_NUMBER_PORT 100
-
#define NGSPICE "ngspice" // 17.Mar.2017 - RM
-extern char* __progname; // 26.Feb.2017 May not be portable to non-GNU systems.
-
-void Vhpi_Exit(int sig);
-
static FILE* pid_file;
static char pid_filename[80];
-
static char* Out_Port_Array[MAX_NUMBER_PORT];
static int out_port_num = 0;
static int server_socket_id = -1;
@@ -62,6 +76,10 @@ static int sendto_sock; // 22.Feb.2017 - RM - Kludge
static int prev_sendto_sock; // 22.Feb.2017 - RM - Kludge
static int pid_file_created; // 10.Mar.2017 - RM
+extern char* __progname; // 26.Feb.2017 May not be portable to non-GNU systems.
+
+void Vhpi_Exit(int sig);
+
struct my_struct {
char val[1024];
char key[1024];
@@ -70,6 +88,7 @@ struct my_struct {
static struct my_struct *s, *users, *tmp = NULL;
+
/* 17.Mar.2017 - RM - Get the process id of ngspice program.*/
static int get_ngspice_pid(void)
{
@@ -81,45 +100,45 @@ static int get_ngspice_pid(void)
if ((dirp = opendir("/proc/")) == NULL)
{
- perror("opendir /proc failed");
- exit(-1);
+ perror("opendir /proc failed");
+ exit(-1);
}
while ((dir_entry = readdir(dirp)) != NULL)
{
- char* nptr;
- int valid_num = 0;
-
- int tmp = strtol(dir_entry->d_name, &nptr, 10);
- if ((errno == ERANGE) && (tmp == LONG_MAX || tmp == LONG_MIN))
- {
- perror("strtol"); // Number out of range.
- return(-1);
- }
- if (dir_entry->d_name == nptr)
- {
- continue; // No digits found.
- }
- if (tmp)
- {
- sprintf(path, "/proc/%s/comm", dir_entry->d_name);
- if ((fp = fopen(path, "r")) != NULL)
- {
- fscanf(fp, "%s", rd_buff);
- if (strcmp(rd_buff, NGSPICE) == 0)
+ char* nptr;
+ int valid_num = 0;
+
+ int tmp = strtol(dir_entry->d_name, &nptr, 10);
+ if ((errno == ERANGE) && (tmp == LONG_MAX || tmp == LONG_MIN))
+ {
+ perror("strtol"); // Number out of range.
+ return(-1);
+ }
+ if (dir_entry->d_name == nptr)
{
- pid = (pid_t)tmp;
- break;
+ continue; // No digits found.
+ }
+ if (tmp)
+ {
+ sprintf(path, "/proc/%s/comm", dir_entry->d_name);
+ if ((fp = fopen(path, "r")) != NULL)
+ {
+ fscanf(fp, "%s", rd_buff);
+ if (strcmp(rd_buff, NGSPICE) == 0)
+ {
+ pid = (pid_t)tmp; // 5.July.2019 - RP - Kludge
+ }
+ }
}
- }
- }
}
-
+
if (fp) fclose(fp);
return(pid);
}
+
/* 23.Mar.2017 - RM - Pass the sock_port argument. We need this if a netlist
* uses more than one instance of the same test bench, so that we can uniquely
* identify the PID files.
@@ -128,30 +147,31 @@ static int get_ngspice_pid(void)
static void create_pid_file(int sock_port)
{
pid_t my_pid = getpid();
- pid_t ngspice_pid = get_ngspice_pid();
+ pid_t ngspice_pid = get_ngspice_pid();
+
if (ngspice_pid == -1)
{
- fprintf(stderr, "create_pid_file() Failed to get ngspice PID");
- syslog(LOG_ERR, "create_pid_file() Failed to get ngspice PID");
- exit(1);
+ fprintf(stderr, "create_pid_file() Failed to get ngspice PID");
+ syslog(LOG_ERR, "create_pid_file() Failed to get ngspice PID");
+ exit(1);
}
- sprintf(pid_filename, "/tmp/NGHDL_%d_%s_%d", ngspice_pid, __progname,
- sock_port);
- pid_file = fopen(pid_filename, "w");
+
+ sprintf(pid_filename, "/tmp/NGHDL_%d_%s_%d", ngspice_pid, __progname, sock_port);
+ pid_file = fopen(pid_filename, "a"); // 26.Sept.2019 - RP - Open file in append mode
+
if (pid_file)
{
- pid_file_created = 1;
- fprintf(pid_file,"%d\n", my_pid);
- fclose(pid_file);
+ pid_file_created = 1;
+ fprintf(pid_file,"%d\n", my_pid);
+ fclose(pid_file);
} else {
perror("fopen() - PID file");
- syslog(LOG_ERR, "create_pid_file(): Unable to open PID file in /tmp");
+ syslog(LOG_ERR, "create_pid_file(): Unable to open PID file in /tmp");
exit(1);
}
-
- return;
}
+
#ifdef DEBUG
static char* curtim(void)
{
@@ -170,18 +190,18 @@ static char* curtim(void)
}
#endif
+
#ifdef DEBUG
static void print_hash_table(void)
{
struct my_struct *sptr;
for(sptr=users; sptr != NULL; sptr=sptr->hh.next)
- {
- syslog(LOG_INFO, "Hash table:val:%s: key: %s", sptr->val, sptr->key);
- }
+ syslog(LOG_INFO, "Hash table:val:%s: key: %s", sptr->val, sptr->key);
}
#endif
+
static void parse_buffer(int sock_id, char* receive_buffer)
{
static int rcvnum;
@@ -202,308 +222,198 @@ static void parse_buffer(int sock_id, char* receive_buffer)
ptr1 = rest;
while(var=strtok_r(token, ":", &value))
{
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, var, 10);
- strncpy(s->val, value, 10);
- HASH_ADD_STR(users, key, s );
- break;
+ s = (struct my_struct*)malloc(sizeof(struct my_struct));
+ strncpy(s->key, var, 64);
+ strncpy(s->val, value, 64);
+ HASH_ADD_STR(users, key, s );
+ break;
}
}
s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, "sock_id", 10);
- snprintf(s->val,10, "%d", sock_id);
+ strncpy(s->key, "sock_id", 64);
+ snprintf(s->val,64, "%d", sock_id);
HASH_ADD_STR(users, key, s);
}
-//
+
//Create Server and listen for client connections.
-//
-static int create_server(int port_number,int max_connections)
+// 26.Sept.2019 - RP - added parameter of socket ip
+static int create_server(int port_number, char my_ip[], int max_connections)
{
- int sockfd, reuse = 1;
- struct sockaddr_in serv_addr;
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- if (sockfd < 0)
- {
- fprintf(stderr, "%s- Error: in opening socket on port %d\n",
- __progname, port_number);
- exit(1);
- }
-
-/* 20.Mar.2017 - RM - SO_REUSEADDR option. To take care of TIME_WAIT state.*/
- int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
- if (ret < 0)
- {
- syslog(LOG_ERR, "create_server:setsockopt() failed....");
- }
-
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_port = htons(port_number);
-
- if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
- {
- fprintf(stderr,"%s- Error: could not bind socket to port %d\n",
- __progname, port_number);
- syslog(LOG_ERR, "Error: could not bind socket to port %d", port_number);
+ int sockfd, reuse = 1;
+ struct sockaddr_in serv_addr;
- close(sockfd);
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
- exit(1);
- }
+ if (sockfd < 0)
+ {
+ fprintf(stderr, "%s- Error: in opening socket at server \n", __progname);
+ //exit(1);
+ return -1;
+ }
- // Start listening on the server.
- listen(sockfd, max_connections);
+ /* 20.Mar.2017 - RM - SO_REUSEADDR option. To take care of TIME_WAIT state.*/
+ int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
- return sockfd;
+ /* 08.Nov.2019 - RP - SO_REUSEPORT and SO_DONTROUTE option.*/
+ ret += setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int));
+ ret += setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &reuse, sizeof(int));
+
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "create_server:setsockopt() failed....");
+ // close(sockfd);
+ // return -1;
+ }
+
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = inet_addr(my_ip); // 26.Sept.2019 - RP - Bind to specific IP only
+ serv_addr.sin_port = htons(port_number);
+
+ if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
+ {
+ fprintf(stderr,"%s- Error: could not bind socket to port %d\n",
+ __progname, port_number);
+ syslog(LOG_ERR, "Error: could not bind socket to port %d", port_number);
+ close(sockfd);
+ exit(1);
+ }
+
+ // Start listening on the server.
+ listen(sockfd, max_connections);
+
+ return sockfd;
}
-// The server to wait (non-blocking) for a client connection.
+
+// The server to wait (blocking) for a client connection.
static int connect_to_client(int server_fd)
{
- int ret_val = 1;
+ int ret_val = 0;
int newsockfd = -1;
socklen_t clilen;
- struct sockaddr_in cli_addr;
- fd_set c_set;
- struct timeval time_limit;
-
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
+ struct sockaddr_in cli_addr;
clilen = sizeof(cli_addr);
- FD_ZERO(&c_set);
- FD_SET(server_fd, &c_set);
-
- select(server_fd + 1, &c_set, NULL, NULL, &time_limit);
-
- ret_val = FD_ISSET(server_fd, &c_set);
-
- if(ret_val)
+ /* 08.Nov.2019 - RP - Blocking Socket (Accept) */
+ newsockfd = accept(server_fd, (struct sockaddr *) &cli_addr, &clilen);
+ if (newsockfd >= 0)
+ {
+ syslog(LOG_INFO, "SRV:%d New Client Connection CLT:%d", server_fd, newsockfd);
+ }
+ else
{
- newsockfd = accept(server_fd, (struct sockaddr *) &cli_addr, &clilen);
- if (newsockfd >= 0)
- {
- syslog(LOG_INFO, "SRV:%d New Client Connection CLT:%d",
- server_fd, newsockfd);
- }
- else
- {
- syslog(LOG_ERR,"Error: failed in accept(), socket=%d", server_fd);
+ syslog(LOG_ERR,"Error: failed in accept(), socket=%d", server_fd);
exit(1);
- }
- }
- return(newsockfd);
-}
+ }
-//
-// Check if we can read from the socket..
-//
-static int can_read_from_socket(int socket_id)
-{
- struct timeval time_limit;
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
-
- fd_set c_set;
- FD_ZERO(&c_set);
- FD_SET(socket_id, &c_set);
-
- int npending = select(socket_id + 1, &c_set, NULL, NULL, &time_limit);
- if (npending == -1)
- {
- npending = errno;
- syslog(LOG_ERR, "can_read_from_socket:select() ERRNO=%d",npending);
- return(-100);
- }
- return(FD_ISSET(socket_id, &c_set));
+ return newsockfd;
}
-//
-// Check if we can write to the socket..
-//
-static int can_write_to_socket(int socket_id)
-{
- struct timeval time_limit;
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
-
- fd_set c_set;
- FD_ZERO(&c_set);
- FD_SET(socket_id, &c_set);
-
- int npending = select(socket_id + 1, NULL, &c_set, NULL, &time_limit);
- if (npending == -1)
- {
- npending = errno;
-
- syslog(LOG_ERR, "can_write_to_socket() select() ERRNO=%d",npending);
-
- return (-100);
- } else if (npending == 0) { // select() timed out...
- return(0);
- }
- return(FD_ISSET(socket_id,&c_set));
-}
//Receive string from socket and put it inside buffer.
-static int receive_string(int sock_id, char* buffer)
+static void receive_string(int sock_id, char* buffer)
{
- int nbytes = 0;
- int ret;
-
- while(1)
- {
- ret = can_read_from_socket(sock_id);
- if (ret == 0)
- { // select() had timed out. Retry...
- usleep(1000);
- continue;
- } else
- if (ret == -100)
- {
- return(-1);
- }
- break;
- }
-
+ int nbytes = 0;
+
+ /* 08.Nov.2019 - RP - Blocking Socket - Receive */
nbytes = recv(sock_id, buffer, MAX_BUF_SIZE, 0);
- if (nbytes < 0)
+ if (nbytes <= 0)
{
- perror("READ FAILURE");
+ perror("READ FAILURE");
exit(1);
}
- return(nbytes);
-}
+}
-static void set_non_blocking(int sock_id)
-{
- int x;
- x = fcntl(sock_id, F_GETFL, 0);
- fcntl(sock_id, F_SETFL, x | O_NONBLOCK);
- syslog(LOG_INFO, "Setting server to non blocking state.");
-}
static void Data_Send(int sockid)
-{
- static int trnum;
- char* out;
-
- int i;
- char colon = ':';
- char semicolon = ';';
- int wrt_retries = 0;
- int ret;
-
- s = NULL;
- int found = 0;
-
- out = calloc(1, 1024);
-
- for (i=0;i<out_port_num;i++)
- {
- HASH_FIND_STR(users,Out_Port_Array[i],s);
- if (strcmp(Out_Port_Array[i], s->key) == 0)
- {
- found=1;
- break;
- }
- }
-
- if(found)
- {
- strncat(out, s->key, strlen(s->key));
- strncat(out, &colon, 1);
- strncat(out, s->val, strlen(s->val));
- strncat(out, &semicolon, 1);
-
- while(1)
- {
- if (wrt_retries > 2) // 22.Feb.2017 - Kludge
- {
- free(out);
- return;
- }
- ret = can_write_to_socket(sockid);
- if (ret > 0) break;
- if( ret == -100)
- {
- syslog(LOG_ERR,"Send aborted to CLT:%d buffer:%s ret=%d",
- sockid, out,ret);
- free(out);
- return;
- }
- else // select() timed out. Retry....
- {
- usleep(1000);
- wrt_retries++;
- }
- }
- }
- else
- {
- syslog(LOG_ERR,"The %s's value not found in the table.",
- Out_Port_Array[i]);
- free(out);
- return;
- }
-
- if ((send(sockid, out, strlen(out), 0)) == -1)
+{
+ static int trnum;
+ char* out;
+
+ int i;
+ char colon = ':';
+ char semicolon = ';';
+ int wrt_retries = 0;
+ int ret;
+
+ s = NULL;
+
+ out = calloc(1, 2048);
+
+ // 5.July.2019 - RP - loop to send all ports at once for an event
+ for (i=0; i<out_port_num; i++)
+ {
+ HASH_FIND_STR(users,Out_Port_Array[i],s);
+ if (strcmp(Out_Port_Array[i], s->key) == 0)
+ {
+ strncat(out, s->key, strlen(s->key));
+ strncat(out, &colon, 1);
+ strncat(out, s->val, strlen(s->val));
+ strncat(out, &semicolon, 1);
+ }
+ else
+ {
+ syslog(LOG_ERR,"The %s's value not found in the table.",
+ Out_Port_Array[i]);
+ free(out);
+ return;
+ }
+ }
+
+ /* 08.Nov.2019 - RP - Blocking Socket (Send) */
+ if ((send(sockid, out, strlen(out), 0)) == -1)
{
- syslog(LOG_ERR,"Failure sending to CLT:%d buffer:%s", sockid, out);
- exit(1);
+ syslog(LOG_ERR,"Failure sending to CLT:%d buffer:%s", sockid, out);
+ exit(1);
}
- syslog(LOG_INFO,"SNT:TRNUM:%d to CLT:%d buffer: %s", trnum++, sockid, out);
- free(out);
+ syslog(LOG_INFO,"SNT:TRNUM:%d to CLT:%d buffer: %s", trnum++, sockid, out);
+ free(out);
}
-void Vhpi_Initialize(int sock_port)
+
+// 26.Sept.2019 - RP - added parameter of socket ip
+void Vhpi_Initialize(int sock_port, char sock_ip[])
{
DEFAULT_SERVER_PORT = sock_port;
signal(SIGINT,Vhpi_Exit);
signal(SIGTERM,Vhpi_Exit);
-
signal(SIGUSR1, Vhpi_Exit); //10.Mar.2017 - RM
int try_limit = 100;
while(try_limit > 0)
{
- server_socket_id = create_server(DEFAULT_SERVER_PORT,DEFAULT_MAX_CONNECTIONS);
- if(server_socket_id > 0)
- {
+ // 26.Sept.2019 - RP
+ server_socket_id = create_server(DEFAULT_SERVER_PORT, sock_ip, DEFAULT_MAX_CONNECTIONS);
+
+ if(server_socket_id >= 0)
+ {
syslog(LOG_INFO,"Started the server on port %d SRV:%d",
DEFAULT_SERVER_PORT, server_socket_id);
- set_non_blocking(server_socket_id);
break;
}
- else
- {
- syslog(LOG_ERR,"Could not start server on port %d,will try again",
+
+ syslog(LOG_ERR,"Could not start server on port %d,will try again",
DEFAULT_SERVER_PORT);
usleep(1000);
try_limit--;
-
+
if(try_limit==0)
{
- syslog(LOG_ERR,
- "Error:Tried to start server on port %d, failed..giving up.",
- DEFAULT_SERVER_PORT);
- exit(1);
- }
-
- }
+ syslog(LOG_ERR,
+ "Error:Tried to start server on port %d, failed..giving up.",
+ DEFAULT_SERVER_PORT);
+ exit(1);
+ }
}
- //
- //Reading Output Port name and storing in Out_Port_Array;
- //
+
+ //Reading Output Port name and storing in Out_Port_Array;
char* line = NULL;
size_t len = 0;
ssize_t read;
@@ -512,145 +422,92 @@ void Vhpi_Initialize(int sock_port)
struct timespec ts;
fp=fopen("connection_info.txt","r");
- if (! fp)
+ if (!fp)
{
- syslog(LOG_ERR,"Vhpi_Initialize: Failed to open connection_info.txt. Exiting...");
- exit(1);
+ syslog(LOG_ERR,"Vhpi_Initialize: Failed to open connection_info.txt. Exiting...");
+ exit(1);
}
line = (char*) malloc(80);
while ((read = getline(&line, &len, fp)) != -1)
{
- if (strstr(line,"OUT") != NULL || strstr(line,"out") != NULL )
- {
- strtok_r(line, " ",&token);
- Out_Port_Array[out_port_num] = line;
- out_port_num++;
- }
- line = (char*) malloc(80);
+ if (strstr(line,"OUT") != NULL || strstr(line,"out") != NULL)
+ {
+ strtok_r(line, " ",&token);
+ Out_Port_Array[out_port_num] = line;
+ out_port_num++;
+ }
+ line = (char*) malloc(80);
}
fclose(fp);
-
free(line);
ts.tv_sec = 2;
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
-// 10.Mar.2017 - RM - Create PID file for the test bench.
+ // 10.Mar.2017 - RM - Create PID file for the test bench.
create_pid_file(sock_port);
}
+
+
void Vhpi_Set_Port_Value(char *port_name,char *port_value,int port_width)
{
-
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, port_name,10);
- strncpy(s->val,port_value,10);
- HASH_ADD_STR( users, key, s );
-
+ s = (struct my_struct*)malloc(sizeof(struct my_struct));
+ strncpy(s->key, port_name,64);
+ strncpy(s->val,port_value,64);
+ HASH_ADD_STR( users, key, s );
}
+
void Vhpi_Get_Port_Value(char* port_name,char* port_value,int port_width)
{
-
- HASH_FIND_STR(users,port_name,s);
- if(s)
- {
- snprintf(port_value,sizeof(port_value),"%s",s->val);
-
- HASH_DEL(users, s);
- free(s);
- s=NULL;
- }
+ HASH_FIND_STR(users,port_name,s);
+ if(s)
+ {
+ snprintf(port_value,sizeof(port_value),"%s",s->val);
+ HASH_DEL(users, s);
+ free(s);
+ s=NULL;
+ }
}
+
void Vhpi_Listen()
{
- int new_sock;
+ sendto_sock = connect_to_client(server_socket_id); // 22.Feb.2017 - RM - Kludge
+ char receive_buffer[MAX_BUF_SIZE];
+ receive_string(sendto_sock, receive_buffer);
+
+ syslog(LOG_INFO, "Vhpi_Listen:New socket connection CLT:%d",sendto_sock);
- while(1)
+ if(strcmp(receive_buffer, "END")==0)
{
- new_sock=connect_to_client(server_socket_id);
- if(new_sock > 0)
- {
- char receive_buffer[MAX_BUF_SIZE];
- int n = receive_string(new_sock, receive_buffer);
- if(n > 0)
- {
- sendto_sock = new_sock; // 22.Feb.2017 - RM - Kludge
- syslog(LOG_INFO,
- "Vhpi_Listen:New socket connection CLT:%d",new_sock);
- if(strcmp(receive_buffer, "END")==0)
- {
- syslog(LOG_INFO,
- "RCVD:CLOSE REQUEST from CLT:%d", new_sock);
- Vhpi_Exit(0);
- }
- else
- {
- parse_buffer(new_sock,receive_buffer);
- }
- break;
- }
- }
- else
- {
- break;
- }
- }
+ syslog(LOG_INFO, "RCVD:CLOSE REQUEST from CLT:%d", sendto_sock);
+ Vhpi_Exit(0);
+ }
+
+ parse_buffer(sendto_sock, receive_buffer);
}
void Vhpi_Send()
{
- int sockid;
- char* out;
-
-// Traverse the list of finished jobs and send out the resulting port values..
// 22.Feb.2017 - RM - Kludge
-// log_server=fopen("server.log","a");
-// fprintf(log_server, "%s Vhpi_Send() called\n", curtim());
-
-// fprintf(log_server,"Vhpi_Send()-------------------\n");
-// print_hash_table();
-// fprintf(log_server,"----------------------------------------\n");
-// HASH_FIND_STR(users,"sock_id",s);
-// if(s)
-// {
-// sockid=atoi(s->val);
-// }
-// else
-// {
-// fprintf(log_server,"%s Socket id not in table - key=%s val=%s\n",
-// curtim(),
-// users->key, users->val);
-// }
-// Data_Send(sockid);
-
if (prev_sendto_sock != sendto_sock)
{
- Data_Send(sendto_sock);
- prev_sendto_sock = sendto_sock;
+ Data_Send(sendto_sock);
+
+ close(prev_sendto_sock); // 08.Nov.2019 - RP - Close previous socket
+ prev_sendto_sock = sendto_sock;
}
-// 22.Feb.2017 End kludge
-
+// 22.Feb.2017 End kludge
}
-void Vhpi_Close()
-{
- close(server_socket_id);
- syslog(LOG_INFO, "*** Closed VHPI link. ***");
-}
void Vhpi_Exit(int sig)
-{
- Vhpi_Close();
-
-// 10.Mar.2017 - RM
- if (pid_file_created)
- remove(pid_filename);
-
- syslog(LOG_INFO, "*** Exiting ***");
-
+{
+ close(server_socket_id);
+ syslog(LOG_INFO, "*** Closed VHPI link. Exiting... ***");
exit(0);
-}
+} \ No newline at end of file
diff --git a/src/ghdlserver/ghdlserver.h b/src/ghdlserver/ghdlserver.h
index 9dc8afc..9f23f0b 100644
--- a/src/ghdlserver/ghdlserver.h
+++ b/src/ghdlserver/ghdlserver.h
@@ -21,8 +21,7 @@
int DEFAULT_SERVER_PORT;
//Vhpi Functions.
-void Vhpi_Initialize(int sock_port);
-void Vhpi_Close();
+void Vhpi_Initialize(int sock_port, char sock_ip[]); /* 26.Sept.2019 - RP */
void Vhpi_Exit();
void Vhpi_Listen();
void Vhpi_Send();
diff --git a/src/model_generation.py b/src/model_generation.py
index 15dc3e6..dffd690 100644
--- a/src/model_generation.py
+++ b/src/model_generation.py
@@ -41,6 +41,7 @@ for item in vhdl_data:
#print "Scan Data",scan_data
port_info=[]
+port_vector_info = []
for item in scan_data:
print "Scan Data :",item
@@ -67,7 +68,12 @@ for item in scan_data:
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)))
+ if bit_info:
+ port_info.append(lhs+":"+str(int(bit_info)+int(1)))
+ port_vector_info.append(1)
+ else:
+ port_info.append(lhs+":"+str(int(1)))
+ port_vector_info.append(0)
print "Port Info :",port_info
@@ -92,7 +98,9 @@ data=read_file.readlines()
read_file.close()
#Extracting input and output port list from data
+print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
for line in data:
+ print line
if re.match(r'^\s*$', line):
pass
#print "Blank Line"
@@ -135,7 +143,7 @@ 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
+Developed by Fahim, Rahul at IIT Bombay */ \n
'''
header='''
@@ -205,10 +213,12 @@ systime_info='''
time_t systime;
systime = time(NULL);
printf(ctime(&systime));
- printf("Client-Initialising ngspice \\n");
+ printf("Client-Initialising GHDL...");
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");
@@ -216,46 +226,88 @@ init_else='''
'''
els_evt_ptr=[]
-els_evt_count1=[]
+els_evt_count1=0
+els_evt_count2=0
for item in output_port:
- els_evt_count2=0
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");
+client_setup_ip='''
+ /* Client Setup IP Addr */
+ FILE *fptr;
+ int ip_count = 0;
+ char* my_ip = malloc(16);
+
+ char ip_filename[40];
+ sprintf(ip_filename, "/tmp/NGHDL_COMMON_IP_%d.txt", getpid());
+
+ fptr = fopen(ip_filename, "r");
+ if (fptr)
+ {
+ char line[20];
+ while(fscanf(fptr, "%s", line) == 1) {
+ ip_count++;
+ }
+
+ fclose(fptr);
+ }
+
+ if (ip_count < 255) {
+ sprintf(my_ip, "127.0.0.%d", ip_count+1);
+ } else {
+ sprintf(my_ip, "127.0.%d.1", (ip_count+1)%256);
+ }
+
+ fptr = fopen(ip_filename, "a");
+ if (fptr)
+ {
+ fprintf(fptr, "%s\\n", my_ip);
+ fclose(fptr);
+ } else {
+ perror("fopen() - Common IP");
+ exit(1);
+ }
+
+ STATIC_VAR(my_ip) = my_ip;
+'''
+
+client_fetch_ip='''
+ /* Client Fetch IP Addr */
+
+ char* my_ip = STATIC_VAR(my_ip);
+
+ host = gethostbyname(my_ip);
+ printf("\\n\\nClient-Creating 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);
+ //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 socket \\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");
+ printf("Client-Connecting to server \\n");
fprintf(log_client,"Client-Connecting to server \\n");
//Conneting to server
@@ -418,9 +470,9 @@ els_time_limit='''
fprintf(log_client,"Socket Id : %d & Message sent : %s for END signal \\n",socket_fd,send_data);
}
flag++;
- close(socket_fd);
}
+ close(socket_fd);
'''
@@ -463,10 +515,12 @@ for item in cm_event_get_ptr:
cfunc.write("\n")
cfunc.write(systime_info)
cfunc.write("\n")
-cfunc.write("\t\tchar command[1024];")
-cfunc.write('\t\tsnprintf(command,1024,"'+home+'/ngspice-nghdl/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(client_setup_ip)
+cfunc.write("\n")
+cfunc.write("\t\tchar command[1024];\n")
+cfunc.write('\t\tsnprintf(command,1024,"'+home+'/ngspice-nghdl/src/xspice/icm/ghdl/'+fname.split('.')[0]+'/DUTghdl/start_server.sh %d %s &",sock_port, my_ip);')
+cfunc.write('\n\t\tsystem(command);')
+cfunc.write("\n\t}")
cfunc.write("\n")
cfunc.write("\telse\n\t{\n")
@@ -476,7 +530,7 @@ for item in els_evt_ptr:
cfunc.write("\t}")
cfunc.write("\n\n")
cfunc.write("\tif(flag==0)\n\t{")
-cfunc.write(client_setup)
+cfunc.write(client_fetch_ip)
cfunc.write(create_socket)
cfunc.write(connect_server)
cfunc.write(time_limit)
@@ -590,6 +644,16 @@ Null_Allowed: yes no
'''
+static_table='''
+
+STATIC_VAR_TABLE:
+
+Static_Var_Name: my_ip
+Data_Type: pointer
+Description: "connect to ghdlserver through this ip"
+
+'''
+
#Writing all the content in ifspec file
ifspec.write(ifspec_comment)
@@ -605,6 +669,8 @@ for item in out_port_table:
ifspec.write("\n")
ifspec.write(parameter_table)
+ifspec.write("\n")
+ifspec.write(static_table)
ifspec.close()
@@ -612,8 +678,11 @@ ifspec.close()
print "Starting with testbench file"
testbench=open(fname.split('.')[0]+'_tb.vhdl','w')
+print fname.split('.')[0] + '_tb.vhdl'
#comment
-comment_vhdl="--------------------------------------------------------------------------------\n--This testbench has been created by Ambikeshwar Srivastava, FOSSEE, IIT Bombay\n-------------------------------------------------------------------------------"
+comment_vhdl="--------------------------------------------------------------------------------\n--This testbench has been created by Ambikeshwar Srivastava, FOSSEE, IIT Bombay\n--------------------------------------------------------------------------------\n"
+comment_vhdl+="--------------------------------------------------------------------------------\n--Modified by Rahul Paknikar, FOSSEE, IIT Bombay\n"
+comment_vhdl+="--retrieves the IP-Addr from sock_pkg and forwards it to the ghdlserver\n--------------------------------------------------------------------------------\n"
#Adding header, entity and architecture statement
tb_header='''
library ieee;
@@ -636,16 +705,32 @@ arch="architecture "+fname.split('.')[0]+"_tb_beh of "+fname.split('.')[0]+"_tb
components=[]
components.append("\tcomponent "+fname.split('.')[0]+" is\n\t\tport(\n\t\t\t\t")
+port_vector_count = 0
+
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")
+ if port_vector_info[port_vector_count]:
+ 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;\n\t\t\t\t")
+
+ port_vector_count += 1
+ #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 port_vector_info[port_vector_count]:
+ 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;\n\t\t\t\t")
+
+ port_vector_count += 1
+
+if port_vector_info[port_vector_count]:
+ 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")
+else:
+ components.append(output_port[-1].split(':')[0]+": out std_logic\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:
@@ -658,8 +743,15 @@ components.append("\tend component;\n\n")
signals=[]
signals.append("\tsignal clk_s : std_logic := '0';\n")
+port_vector_count = 0
+
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 port_vector_info[port_vector_count]:
+ 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;\n")
+ port_vector_count += 1
+
#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:
@@ -667,7 +759,11 @@ for item in input_port:
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 port_vector_info[port_vector_count]:
+ 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;\n")
+ port_vector_count += 1
#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:
@@ -692,7 +788,7 @@ map.append("\t\t\t);")
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")
+process_Vhpi.append("\tprocess\n\t\tvariable sock_port : integer;\n\t\ttype string_ptr is access string;\n\t\tvariable sock_ip : string_ptr;\n\t\tbegin\n\t\tsock_port := sock_port_fun;\n\t\tsock_ip := new string'(sock_ip_fun);\n\t\tVhpi_Initialize(sock_port, Pack_String_To_Vhpi_String(sock_ip.all));\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")
@@ -708,17 +804,28 @@ process.append("\tbegin\n")
process.append("\t\twhile true loop\n")
process.append("\t\t\twait until clk_s = '0';\n\n")
+port_vector_count = 0
+
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')
+ if port_vector_info[port_vector_count]:
+ process.append('\t\t\t'+item.split(':')[0]+' <= Unpack_String('+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
+ else:
+ process.append('\t\t\t'+item.split(':')[0]+' <= To_Std_Logic('+item.split(':')[0]+'_v'+');\n')
+ port_vector_count += 1
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')
+ if port_vector_info[port_vector_count]:
+ process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(Convert_SLV_To_String('+item.split(':')[0]+'));\n')
+ else:
+ process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(To_String('+item.split(':')[0]+'));\n')
+ port_vector_count += 1
+
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')
@@ -764,12 +871,9 @@ 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-nghdl/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("./sock_pkg_create.sh $1 $2 &&\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")
@@ -783,21 +887,24 @@ start_server.close()
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("##This file creates sock_pkg.vhdl file and sets the port and ip from parameters passed to it\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("\tfunction sock_port_fun return integer;\n")
+sock_pkg_create.write("\tfunction sock_ip_fun return string;\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("package body sock_pkg is\n")
+sock_pkg_create.write("\tfunction sock_port_fun return integer is\n")
+sock_pkg_create.write("\t\tvariable sock_port : 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")
-
-
-
-
-
+sock_pkg_create.write("\t\t\t\tsock_port := $1;\n")
+sock_pkg_create.write("\t\t\t\treturn sock_port;\n")
+sock_pkg_create.write("\t\t\tend function;\n\n")
+sock_pkg_create.write("\tfunction sock_ip_fun return string is\n")
+sock_pkg_create.write("\t\ttype string_ptr is access string;\n")
+sock_pkg_create.write("\t\tvariable sock_ip : string_ptr;\n")
+sock_pkg_create.write("\t\t\tbegin\n")
+sock_pkg_create.write('\t\t\t\tsock_ip := new string\'(\\"$2\\");\n')
+sock_pkg_create.write("\t\t\t\treturn sock_ip.all;\n")
+sock_pkg_create.write("\t\t\tend function;\n\n")
+sock_pkg_create.write("\t\tend package body;\" > sock_pkg.vhdl") \ No newline at end of file
diff --git a/src/ngspice_ghdl.py b/src/ngspice_ghdl.py
index 0a9e88c..a4c3637 100755
--- a/src/ngspice_ghdl.py
+++ b/src/ngspice_ghdl.py
@@ -31,6 +31,7 @@ class Mainwindow(QtGui.QWidget):
#Printing LICENCE file on terminal
fileopen = open(self.licensefile, 'r')
print fileopen.read()
+ fileopen.close()
self.file_list = [] #to keep the supporting files
self.initUI()
@@ -75,7 +76,6 @@ class Mainwindow(QtGui.QWidget):
self.show()
-
def closeWindow(self):
try:
self.process.close()
@@ -84,12 +84,14 @@ class Mainwindow(QtGui.QWidget):
print "Close button clicked"
quit()
+
def browseFile(self):
print "Browse button clicked"
self.filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
self.ledit.setText(self.filename)
print "Vhdl file uploaded to process :", self.filename
+
def addFiles(self):
print "Starts adding supporting files"
title = self.addbtn.text()
@@ -137,13 +139,11 @@ class Mainwindow(QtGui.QWidget):
else:
print "Exiting application"
quit()
-
-
-
else:
print "Creating model "+self.modelname+" directory"
os.mkdir(self.modelname)
+
def addingModelInModpath(self):
print "Adding Model "+self.modelname+" in Modpath file "+self.digital_home
#Adding name of model in the modpath file
@@ -222,6 +222,7 @@ class Mainwindow(QtGui.QWidget):
cmd = " make"
print "Running Make command in "+self.release_home
path = os.getcwd()
+ self.process = QtCore.QProcess(self)
self.process.start(cmd)
self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
QtCore.QObject.connect(self.process, QtCore.SIGNAL("readyReadStandardOutput()"), self, QtCore.SLOT("readStdOutput()"))
@@ -231,6 +232,7 @@ class Mainwindow(QtGui.QWidget):
print "There is error in 'make' "
quit()
+
def runMakeInstall(self):
print "run Make Install Called"
try:
@@ -241,8 +243,10 @@ class Mainwindow(QtGui.QWidget):
self.process.close()
except:
pass
- self.process.finished.connect(self.createSchematicLib)
+
+ self.process = QtCore.QProcess(self)
self.process.start(cmd)
+ self.process.finished.connect(self.createSchematicLib)
self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
QtCore.QObject.connect(self.process, QtCore.SIGNAL("readyReadStandardOutput()"), self, QtCore.SLOT("readStdOutput()"))
os.chdir(self.cur_dir)
@@ -251,11 +255,13 @@ class Mainwindow(QtGui.QWidget):
print "There is error during in 'make install' "
quit()
+
def createSchematicLib(self):
if Appconfig.esimFlag == 1:
print 'Creating library files.................................'
- self.schematicLib = AutoSchematic(self.modelname)
- self.schematicLib.createKicadLibrary()
+ schematicLib = AutoSchematic(self.modelname)
+ schematicLib.createKicadLibrary()
+
def uploadModle(self):
print "Upload button clicked"
@@ -277,8 +283,8 @@ class Mainwindow(QtGui.QWidget):
self.runMakeInstall()
else:
QtGui.QMessageBox.about(self,'Message','''<b>Important Message.</b><br/><br/>This accepts only <b>.vhdl</b> file ''')
- except:
- QtGui.QMessageBox.about(self, 'Message','''<b>Error</b><br/><br/> select a <b>.vhdl</b> file ''')
+ except Exception as e:
+ QtGui.QMessageBox.about(self, 'Message','''<b>Error</b><br/><br/> ''' + str(e))
class FileRemover(QtGui.QWidget):
diff --git a/src/outitf.c b/src/outitf.c
index ce3e910..fba5224 100644
--- a/src/outitf.c
+++ b/src/outitf.c
@@ -1,15 +1,19 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group
-Modified: 2000 AlansFixes
+Modified: 2000 AlansFixes, 2013/2015 patch by Krzysztof Blaszkowski
**********/
/**************************************************************************
* 10.Mar.2017 - RM - Added a dirty fix to handle orphan FOSSEE test bench
* processes. The following static functions were added in the process:
* o nghdl_orphan_tb()
* o nghdl_tb_SIGUSR1()
- **************************************************************************
- */
+ **************************************************************************/
+/**************************************************************************
+ * 22.Oct.2019 - RP - Read all the PIDs and send kill signal to all those
+ * processes. Also, Remove the common file of used IPs and PIDs for this
+ * Ngspice's instance rather than depending on GHDLServer to do the same.
+ **************************************************************************/
/*
* This module replaces the old "writedata" routines in nutmeg.
* Unlike the writedata routines, the OUT routines are only called by
@@ -53,8 +57,8 @@ extern char *spice_analysis_get_description(int index);
static int beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analName,
char *refName, int refType, int numNames, char **dataNames, int dataType,
bool windowed, runDesc **runp);
-static int addDataDesc(runDesc *run, char *name, int type, int ind);
-static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind);
+static int addDataDesc(runDesc *run, char *name, int type, int ind, int meminit);
+static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit);
static void fileInit(runDesc *run);
static void fileInit_pass2(runDesc *run);
static void fileStartPoint(FILE *fp, bool bin, int num);
@@ -70,6 +74,8 @@ static bool parseSpecial(char *name, char *dev, char *param, char *ind);
static bool name_eq(char *n1, char *n2);
static bool getSpecial(dataDesc *desc, runDesc *run, IFvalue *val);
static void freeRun(runDesc *run);
+static int InterpFileAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr);
+static int InterpPlotAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr);
/*Output data to spice module*/
#ifdef TCL_MODULE
@@ -84,6 +90,11 @@ extern void sh_vecinit(runDesc *run);
extern bool orflag;
#endif
+// fixme
+// ugly hack to work around missing api to specify the "type" of signals
+int fixme_onoise_type = SV_NOTYPE;
+int fixme_inoise_type = SV_NOTYPE;
+
#define DOUBLE_PRECISION 15
@@ -94,36 +105,56 @@ static size_t column, rowbuflen;
static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */
+static bool interpolated = FALSE;
+static double *valueold, *valuenew;
+
+#ifdef SHARED_MODULE
+static bool savenone = FALSE;
+#endif
+
/* 10.Mar.2017 - RM - Added nghdl_tb_SIGUSR1().*/
static void nghdl_tb_SIGUSR1(char* pid_file)
{
int ret;
char line[80];
char* nptr;
+ pid_t pid[256], tmp;
+ int count=0, i;
FILE* fp = fopen(pid_file, "r");
if (fp)
{
- if (fscanf(fp, "%s", line) != EOF)
- {
- fclose(fp);
- pid_t pid = (pid_t) strtol(line, &nptr, 10);
- // PID is converted to a decimal value.
- if ((errno != ERANGE) && (errno!= EINVAL))
- {
- if (pid)
- {
- // Check if a process with this pid really exists.
- ret = kill(pid, 0);
- if (ret == 0)
- {
- kill(pid, SIGUSR1);
- }
- }
- }
- }
+ /* 22.Oct.2019 - RP - Scan and store all the PIDs in this file */
+ while (fscanf(fp, "%s", line) == 1)
+ {
+ // PID is converted to a decimal value.
+ tmp = (pid_t) strtol(line, &nptr, 10);
+ if ((errno != ERANGE) && (errno!= EINVAL))
+ {
+ pid[count++] = tmp;
+ }
+ }
+
+ fclose(fp);
}
+
+ /* 22.Oct.2019 - RP - Kill all the active PIDs */
+ for(i=0; i<count; i++)
+ {
+ if (pid[i])
+ {
+ // Check if a process with this pid really exists.
+ ret = kill(pid[i], 0);
+ if (ret == 0)
+ {
+ kill(pid[i], SIGUSR1);
+ }
+ }
+ }
+
+ // 22.Oct.2019 - RP
+ remove(pid_file);
}
/* 10.Mar.2017 - RM - Added nghdl_orphan_tb().*/
@@ -139,35 +170,40 @@ static void nghdl_orphan_tb(void)
if ((dirfd = opendir(dir)) == NULL)
{
- fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n");
+ fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n");
return;
}
-/* Loop through /tmp directories looking for "NGHDL_<my pid>*" files.*/
+ /* Loop through /tmp directories looking for "NGHDL_<my pid>*" files.*/
while ((dirp = readdir(dirfd)) != NULL)
{
- struct stat stbuf;
- sprintf(filename_tmp, "/tmp/%s", dirp->d_name);
- if (strstr(filename_tmp, pid_file_prefix))
- {
- if (stat(filename_tmp, &stbuf) == -1)
- {
- fprintf(stderr,
+ struct stat stbuf;
+ sprintf(filename_tmp, "/tmp/%s", dirp->d_name);
+ if (strstr(filename_tmp, pid_file_prefix))
+ {
+ if (stat(filename_tmp, &stbuf) == -1)
+ {
+ fprintf(stderr,
"nghdl_orphan_tb: stat() failed; ERRNO=%d on file:%s\n",
errno, filename_tmp);
- continue;
- }
-
- if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
- {
- continue;
- }
- else
- {
- nghdl_tb_SIGUSR1(filename_tmp);
- }
- }
+ continue;
+ }
+
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
+ {
+ continue;
+ }
+ else
+ {
+ nghdl_tb_SIGUSR1(filename_tmp);
+ }
+ }
}
+
+ // 22.Oct.2019 - RP
+ char ip_filename[40];
+ sprintf(ip_filename, "/tmp/NGHDL_COMMON_IP_%d.txt", getpid());
+ remove(ip_filename);
}
/* End 10.Mar.2017 - RM */
@@ -220,9 +256,11 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
bool saveall = TRUE;
bool savealli = FALSE;
char *an_name;
+ int initmem;
/*to resume a run saj
*All it does is reassign the file pointer and return (requires *runp to be NULL if this is not needed)
*/
+
if (dataType == 666 && numNames == 666) {
run = *runp;
run->writeOut = ft_getOutReq(&run->fp, &run->runPlot, &run->binary,
@@ -232,10 +270,16 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
/*end saj*/
/* Check to see if we want to print informational data. */
- if (cp_getvar("printinfo", CP_BOOL, NULL))
+ if (cp_getvar("printinfo", CP_BOOL, NULL, 0))
fprintf(cp_err, "(debug printing enabled)\n");
- *runp = run = alloc(struct runDesc);
+ /* Check to see if we want to save only interpolated data. */
+ if (cp_getvar("interp", CP_BOOL, NULL, 0)) {
+ interpolated = TRUE;
+ fprintf(cp_out, "Warning: Interpolated raw file data!\n\n");
+ }
+
+ *runp = run = TMALLOC(struct runDesc, 1);
/* First fill in some general information. */
run->analysis = analysisPtr;
@@ -281,12 +325,27 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
saves[i].used = 1;
continue;
}
+#ifdef SHARED_MODULE
+ /* this may happen if shared ngspice*/
+ if (cieq(saves[i].name, "none")) {
+ savenone = TRUE;
+ saveall = TRUE;
+ savesused[i] = TRUE;
+ saves[i].used = 1;
+ continue;
+ }
+#endif
}
}
+ if (numsaves && !saveall)
+ initmem = numsaves;
+ else
+ initmem = numNames;
+
/* Pass 0. */
if (refName) {
- addDataDesc(run, refName, refType, -1);
+ addDataDesc(run, refName, refType, -1, initmem);
for (i = 0; i < numsaves; i++)
if (!savesused[i] && name_eq(saves[i].name, refName)) {
savesused[i] = TRUE;
@@ -303,7 +362,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
if (!savesused[i])
for (j = 0; j < numNames; j++)
if (name_eq(saves[i].name, dataNames[j])) {
- addDataDesc(run, dataNames[j], dataType, j);
+ addDataDesc(run, dataNames[j], dataType, j, initmem);
savesused[i] = TRUE;
saves[i].used = 1;
break;
@@ -319,7 +378,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
!strstr(dataNames[i], "#emitter") &&
!strstr(dataNames[i], "#base"))
{
- addDataDesc(run, dataNames[i], dataType, i);
+ addDataDesc(run, dataNames[i], dataType, i, initmem);
}
}
@@ -349,17 +408,17 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
} else if (strstr(ch, "#emitter")) {
strcpy(ch, "[ie]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[is]");
} else if (strstr(ch, "#drain")) {
strcpy(ch, "[id]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[ig]");
} else if (strstr(ch, "#source")) {
strcpy(ch, "[is]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[ib]");
} else if (strstr(ch, "#internal") && (tmpname[1] == 'd')) {
strcpy(ch, "[id]");
@@ -373,7 +432,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
fprintf(stderr,
"Warning : unexpected dependent variable on %s\n", tmpname);
} else {
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
}
}
}
@@ -410,7 +469,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
depbuf, saves[i].name);
continue;
}
- addDataDesc(run, dataNames[j], dataType, j);
+ addDataDesc(run, dataNames[j], dataType, j, initmem);
savesused[i] = TRUE;
saves[i].used = 1;
depind = j;
@@ -419,7 +478,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
}
}
- addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind);
+ addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind, initmem);
}
if (numsaves) {
@@ -455,6 +514,14 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
}
}
+ /* define storage for old and new data, to allow interpolation */
+ if (interpolated && run->circuit->CKTcurJob->JOBtype == 4) {
+ valueold = TMALLOC(double, run->numData);
+ for (i = 0; i < run->numData; i++)
+ valueold[i] = 0.0;
+ valuenew = TMALLOC(double, run->numData);
+ }
+
/*Start BLT, initilises the blt vectors saj*/
#ifdef TCL_MODULE
blt_init(run);
@@ -465,20 +532,28 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
return (OK);
}
-
+/* Initialze memory for the list of all vectors in the current plot.
+ Add a standard vector to this plot */
static int
-addDataDesc(runDesc *run, char *name, int type, int ind)
+addDataDesc(runDesc *run, char *name, int type, int ind, int meminit)
{
dataDesc *data;
- if (!run->numData)
- run->data = TMALLOC(dataDesc, 1);
- else
- run->data = TREALLOC(dataDesc, run->data, run->numData + 1);
+ /* initialize memory (for all vectors or given by 'save') */
+ if (!run->numData) {
+ /* even if input 0, do a malloc */
+ run->data = TMALLOC(dataDesc, ++meminit);
+ run->maxData = meminit;
+ }
+ /* If there is need for more memory */
+ else if (run->numData == run->maxData) {
+ run->maxData = (int)(run->maxData * 1.1) + 1;
+ run->data = TREALLOC(dataDesc, run->data, run->maxData);
+ }
data = &run->data[run->numData];
/* so freeRun will get nice NULL pointers for the fields we don't set */
- bzero(data, sizeof(dataDesc));
+ memset(data, 0, sizeof(dataDesc));
data->name = copy(name);
data->type = type;
@@ -495,30 +570,40 @@ addDataDesc(runDesc *run, char *name, int type, int ind)
return (OK);
}
-
+/* Initialze memory for the list of all vectors in the current plot.
+ Add a special vector (e.g. @q1[ib]) to this plot */
static int
-addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind)
+addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit)
{
dataDesc *data;
- char *unique; /* unique char * from back-end */
+ char *unique, *freeunique; /* unique char * from back-end */
+ int ret;
- if (!run->numData)
- run->data = TMALLOC(dataDesc, 1);
- else
- run->data = TREALLOC(dataDesc, run->data, run->numData + 1);
+ if (!run->numData) {
+ /* even if input 0, do a malloc */
+ run->data = TMALLOC(dataDesc, ++meminit);
+ run->maxData = meminit;
+ }
+ else if (run->numData == run->maxData) {
+ run->maxData = (int)(run->maxData * 1.1) + 1;
+ run->data = TREALLOC(dataDesc, run->data, run->maxData);
+ }
data = &run->data[run->numData];
/* so freeRun will get nice NULL pointers for the fields we don't set */
- bzero(data, sizeof(dataDesc));
+ memset(data, 0, sizeof(dataDesc));
data->name = copy(name);
- unique = copy(devname);
+ freeunique = unique = copy(devname);
- /* MW. My "special" routine here */
- INPinsertNofree(&unique, ft_curckt->ci_symtab);
+ /* unique will be overridden, if it already exists */
+ ret = INPinsertNofree(&unique, ft_curckt->ci_symtab);
data->specName = unique;
+ if (ret == E_EXISTS)
+ tfree(freeunique);
+
data->specParamName = copy(param);
data->specIndex = depind;
@@ -532,6 +617,56 @@ addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind)
}
+static void
+OUTpD_memory(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i, n = run->numData;
+
+ for (i = 0; i < n; i++) {
+
+ dataDesc *d;
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(i);
+#endif
+
+ d = &run->data[i];
+
+ if (d->outIndex == -1) {
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, refValue->rValue);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, refValue->cValue);
+ } else if (d->regular) {
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, valuePtr->v.vec.rVec[d->outIndex]);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, valuePtr->v.vec.cVec[d->outIndex]);
+ } else {
+ IFvalue val;
+
+ /* should pre-check instance */
+ if (!getSpecial(d, run, &val))
+ continue;
+
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, val.rValue);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, val.cValue);
+ else
+ fprintf(stderr, "OUTpData: unsupported data type\n");
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(i, d->vec);
+#endif
+
+ }
+}
+
+
int
OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
{
@@ -543,8 +678,18 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
#ifdef TCL_MODULE
steps_completed = run->pointCount;
#endif
-
- if (run->writeOut) {
+ /* interpolated batch mode output to file in transient analysis */
+ if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) {
+ InterpFileAdd(run, refValue, valuePtr);
+ return (OK);
+ }
+ /* interpolated interactive or control mode output to plot in transient analysis */
+ else if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && !(run->writeOut)) {
+ InterpPlotAdd(run, refValue, valuePtr);
+ return (OK);
+ }
+ /* standard batch mode output to file */
+ else if (run->writeOut) {
if (run->pointCount == 1)
fileInit_pass2(run);
@@ -559,7 +704,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
every quarter of a second, to give some feedback without using
too much CPU time */
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r",
@@ -574,7 +719,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
fileAddRealValue(run->fp, run->binary, refValue->rValue);
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r",
@@ -642,7 +787,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
-
fileEndPoint(run->fp, run->binary);
/* Check that the write to disk completed successfully, otherwise abort */
@@ -654,11 +798,13 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
} else {
+ OUTpD_memory(run, refValue, valuePtr);
+
/* This is interactive mode. Update the screen with the reference
variable just the same */
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
if (run->isComplex) {
@@ -673,45 +819,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
#endif
- for (i = 0; i < run->numData; i++) {
-
-#ifdef TCL_MODULE
- /*Locks the blt vector to stop access*/
- blt_lockvec(i);
-#endif
-
- if (run->data[i].outIndex == -1) {
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i], refValue->rValue);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i], refValue->cValue);
- } else if (run->data[i].regular) {
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i],
- valuePtr->v.vec.rVec[run->data[i].outIndex]);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i],
- valuePtr->v.vec.cVec[run->data[i].outIndex]);
- } else {
- IFvalue val;
- /* should pre-check instance */
- if (!getSpecial(&run->data[i], run, &val))
- continue;
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i], val.rValue);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i], val.cValue);
- else
- fprintf(stderr, "OUTpData: unsupported data type\n");
- }
-
-#ifdef TCL_MODULE
- /*relinks and unlocks vector*/
- blt_relink(i, (run->data[i]).vec);
-#endif
-
- }
-
gr_iplot(run->runPlot);
}
@@ -728,7 +835,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
{
@@ -740,7 +846,6 @@ OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr)
{
@@ -753,7 +858,6 @@ OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwEnd(runDesc *plotPtr)
{
@@ -766,22 +870,22 @@ OUTwEnd(runDesc *plotPtr)
int
OUTendPlot(runDesc *plotPtr)
{
- runDesc *run = plotPtr; // FIXME
-
- if (run->writeOut) {
- fileEnd(run);
+ if (plotPtr->writeOut) {
+ fileEnd(plotPtr);
} else {
gr_end_iplot();
- plotEnd(run);
+ plotEnd(plotPtr);
}
- freeRun(run);
+ tfree(valueold);
+ tfree(valuenew);
+
+ freeRun(plotPtr);
return (OK);
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefValue)
{
@@ -794,7 +898,6 @@ OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefVa
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTendDomain(runDesc *plotPtr)
{
@@ -804,7 +907,6 @@ OUTendDomain(runDesc *plotPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTattributes(runDesc *plotPtr, IFuid varName, int param, IFvalue *value)
{
@@ -897,6 +999,42 @@ fileInit(runDesc *run)
}
+static int
+guess_type(const char *name)
+{
+ int type;
+
+ if (substring("#branch", name))
+ type = SV_CURRENT;
+ else if (cieq(name, "time"))
+ type = SV_TIME;
+ else if (cieq(name, "frequency"))
+ type = SV_FREQUENCY;
+ else if (ciprefix("inoise", name))
+ type = fixme_inoise_type;
+ else if (ciprefix("onoise", name))
+ type = fixme_onoise_type;
+ else if (cieq(name, "temp-sweep"))
+ type = SV_TEMP;
+ else if (cieq(name, "res-sweep"))
+ type = SV_RES;
+ else if ((*name == '@') && substring("[g", name)) /* token starting with [g */
+ type = SV_ADMITTANCE;
+ else if ((*name == '@') && substring("[c", name))
+ type = SV_CAPACITANCE;
+ else if ((*name == '@') && substring("[i", name))
+ type = SV_CURRENT;
+ else if ((*name == '@') && substring("[q", name))
+ type = SV_CHARGE;
+ else if ((*name == '@') && substring("[p]", name)) /* token is exactly [p] */
+ type = SV_POWER;
+ else
+ type = SV_VOLTAGE;
+
+ return type;
+}
+
+
static void
fileInit_pass2(runDesc *run)
{
@@ -906,26 +1044,7 @@ fileInit_pass2(runDesc *run)
char *name = run->data[i].name;
- if (substring("#branch", name))
- type = SV_CURRENT;
- else if (cieq(name, "time"))
- type = SV_TIME;
- else if (cieq(name, "frequency"))
- type = SV_FREQUENCY;
- else if (cieq(name, "temp-sweep"))
- type = SV_TEMP;
- else if (cieq(name, "res-sweep"))
- type = SV_RES;
- else if ((*name == '@') && (substring("[g", name)))
- type = SV_ADMITTANCE;
- else if ((*name == '@') && (substring("[c", name)))
- type = SV_CAPACITANCE;
- else if ((*name == '@') && (substring("[i", name)))
- type = SV_CURRENT;
- else if ((*name == '@') && (substring("[q", name)))
- type = SV_CHARGE;
- else
- type = SV_VOLTAGE;
+ type = guess_type(name);
if (type == SV_CURRENT) {
char *branch = strstr(name, "#branch");
@@ -957,7 +1076,7 @@ fileInit_pass2(runDesc *run)
rowbuflen *= 2;
rowbuf = TMALLOC(double, rowbuflen);
} else {
- // fIXME rowbuflen = 0;
+ rowbuflen = 0;
rowbuf = NULL;
}
}
@@ -998,7 +1117,6 @@ fileAddComplexValue(FILE *fp, bool bin, IFcomplex value)
}
-/* ARGSUSED */ /* until some code gets written */
static void
fileEndPoint(FILE *fp, bool bin)
{
@@ -1015,12 +1133,13 @@ fileEndPoint(FILE *fp, bool bin)
static void
fileEnd(runDesc *run)
{
-/* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are
- * found, force them to exit.
- */
- nghdl_orphan_tb();
+ /* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are
+ * found, force them to exit.
+ */
+ nghdl_orphan_tb();
+
+ /* End 10.Mar.2017 */
-/* End 10.Mar.2017 */
if (run->fp != stdout) {
long place = ftell(run->fp);
@@ -1035,10 +1154,7 @@ fileEnd(runDesc *run)
fflush(run->fp);
- if (run->binary) {
- /* deallocate row buffer */
- tfree(rowbuf);
- }
+ tfree(rowbuf);
}
@@ -1048,9 +1164,7 @@ static void
plotInit(runDesc *run)
{
struct plot *pl = plot_alloc(run->type);
- char buf[100];
struct dvec *v;
- dataDesc *dd;
int i;
pl->pl_title = copy(run->name);
@@ -1069,71 +1183,83 @@ plotInit(runDesc *run)
run->isComplex = TRUE;
for (i = 0; i < run->numData; i++) {
- dd = &run->data[i];
- v = alloc(struct dvec);
- if (isdigit(*dd->name)) {
- (void) sprintf(buf, "V(%s)", dd->name);
- v->v_name = copy(buf);
- } else {
- v->v_name = copy(dd->name);
- }
- if (substring("#branch", v->v_name))
- v->v_type = SV_CURRENT;
- else if (cieq(v->v_name, "time"))
- v->v_type = SV_TIME;
- else if (cieq(v->v_name, "frequency"))
- v->v_type = SV_FREQUENCY;
- else if (cieq(v->v_name, "onoise_spectrum"))
- v->v_type = SV_OUTPUT_N_DENS;
- else if (cieq(v->v_name, "onoise_integrated"))
- v->v_type = SV_OUTPUT_NOISE;
- else if (cieq(v->v_name, "inoise_spectrum"))
- v->v_type = SV_INPUT_N_DENS;
- else if (cieq(v->v_name, "inoise_integrated"))
- v->v_type = SV_INPUT_NOISE;
- else if (cieq(v->v_name, "temp-sweep"))
- v->v_type = SV_TEMP;
- else if (cieq(v->v_name, "res-sweep"))
- v->v_type = SV_RES;
- else if ((*(v->v_name) == '@') && (substring("[g", v->v_name)))
- v->v_type = SV_ADMITTANCE;
- else if ((*(v->v_name) == '@') && (substring("[c", v->v_name)))
- v->v_type = SV_CAPACITANCE;
- else if ((*(v->v_name) == '@') && (substring("[i", v->v_name)))
- v->v_type = SV_CURRENT;
- else if ((*(v->v_name) == '@') && (substring("[q", v->v_name)))
- v->v_type = SV_CHARGE;
+ dataDesc *dd = &run->data[i];
+ char *name;
+
+ if (isdigit_c(dd->name[0]))
+ name = tprintf("V(%s)", dd->name);
else
- v->v_type = SV_VOLTAGE;
- v->v_length = 0;
- v->v_scale = NULL;
- if (!run->isComplex) {
- v->v_flags = VF_REAL;
- v->v_realdata = NULL;
- } else {
- v->v_flags = VF_COMPLEX;
- v->v_compdata = NULL;
- }
+ name = copy(dd->name);
- v->v_flags |= VF_PERMANENT;
+ v = dvec_alloc(name,
+ guess_type(name),
+ run->isComplex
+ ? (VF_COMPLEX | VF_PERMANENT)
+ : (VF_REAL | VF_PERMANENT),
+ 0, NULL);
vec_new(v);
dd->vec = v;
}
}
+/* prepare the vector length data for memory allocation
+ If new, and tran or pss, length is TSTOP / TSTEP plus some margin.
+ If allocated length is exceeded, check progress. When > 20% then extrapolate memory needed,
+ if less than 20% then just double the size.
+ If not tran or pss, return fixed value (1024) of memory to be added.
+ */
+static inline int
+vlength2delta(int len)
+{
+#ifdef SHARED_MODULE
+ if (savenone)
+ /* We need just a vector length of 1 */
+ return 1;
+#endif
+ /* TSTOP / TSTEP */
+ int points = ft_curckt->ci_ckt->CKTtimeListSize;
+ /* transient and pss analysis (points > 0) upon start */
+ if (len == 0 && points > 0) {
+ /* number of timesteps plus some overhead */
+ return points + 100;
+ }
+ /* transient and pss if original estimate is exceeded */
+ else if (points > 0) {
+ /* check where we are */
+ double timerel = ft_curckt->ci_ckt->CKTtime / ft_curckt->ci_ckt->CKTfinalTime;
+ /* return an estimate of the appropriate number of time points, if more than 20% of
+ the anticipated total time has passed */
+ if (timerel > 0.2)
+ return (int)(len / timerel) - len + 1;
+ /* If not, just double the available memory */
+ else
+ return len;
+ }
+ /* other analysis types that do not set CKTtimeListSize */
+ else
+ return 1024;
+}
+
static void
plotAddRealValue(dataDesc *desc, double value)
{
struct dvec *v = desc->vec;
+#ifdef SHARED_MODULE
+ if (savenone)
+ /* always save new data to same location */
+ v->v_length = 0;
+#endif
+
+ if (v->v_length >= v->v_alloc_length)
+ dvec_extend(v, v->v_length + vlength2delta(v->v_length));
+
if (isreal(v)) {
- v->v_realdata = TREALLOC(double, v->v_realdata, v->v_length + 1);
v->v_realdata[v->v_length] = value;
} else {
/* a real parading as a VF_COMPLEX */
- v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1);
v->v_compdata[v->v_length].cx_real = value;
v->v_compdata[v->v_length].cx_imag = 0.0;
}
@@ -1148,7 +1274,14 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value)
{
struct dvec *v = desc->vec;
- v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1);
+#ifdef SHARED_MODULE
+ if (savenone)
+ v->v_length = 0;
+#endif
+
+ if (v->v_length >= v->v_alloc_length)
+ dvec_extend(v, v->v_length + vlength2delta(v->v_length));
+
v->v_compdata[v->v_length].cx_real = value.real;
v->v_compdata[v->v_length].cx_imag = value.imag;
@@ -1157,18 +1290,17 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value)
}
-/* ARGSUSED */ /* until some code gets written */
static void
plotEnd(runDesc *run)
{
-/* 10.Mar.2017 - RM */
- nghdl_orphan_tb();
-/* End 10.Mar.2017 */
+ /* 10.Mar.2017 - RM */
+ nghdl_orphan_tb();
+ /* End 10.Mar.2017 */
- fprintf(stderr, "\n");
fprintf(stdout, "\nNo. of Data Rows : %d\n", run->pointCount);
}
+
/* ParseSpecial takes something of the form "@name[param,index]" and rips
* out name, param, andstrchr.
*/
@@ -1327,7 +1459,7 @@ OUTerror(int flags, char *format, IFuid *names)
char buf[BSIZE_SP], *s, *bptr;
int nindex = 0;
- if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL))
+ if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0))
return;
for (m = msgs; m->flag; m++)
@@ -1352,3 +1484,328 @@ OUTerror(int flags, char *format, IFuid *names)
fprintf(cp_err, "%s\n", buf);
fflush(cp_err);
}
+
+
+void
+OUTerrorf(int flags, const char *format, ...)
+{
+ struct mesg *m;
+ va_list args;
+
+ if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0))
+ return;
+
+ for (m = msgs; m->flag; m++)
+ if (flags & m->flag)
+ fprintf(cp_err, "%s: ", m->string);
+
+ va_start (args, format);
+
+ vfprintf(cp_err, format, args);
+ fputc('\n', cp_err);
+
+ fflush(cp_err);
+
+ va_end(args);
+}
+
+
+static int
+InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i;
+ static double timeold = 0.0, timenew = 0.0, timestep = 0.0;
+ bool nodata = FALSE;
+ bool interpolatenow = FALSE;
+
+ if (run->pointCount == 1) {
+ fileInit_pass2(run);
+ timestep = run->circuit->CKTinitTime + run->circuit->CKTstep;
+ }
+
+ if (run->refIndex != -1) {
+ /* Save first time step */
+ if (refValue->rValue == run->circuit->CKTinitTime) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, run->circuit->CKTinitTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save last time step */
+ else if (refValue->rValue == run->circuit->CKTfinalTime) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, run->circuit->CKTfinalTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save exact point */
+ else if (refValue->rValue == timestep) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, timestep);
+ timestep += run->circuit->CKTstep;
+ interpolatenow = nodata = FALSE;
+ }
+ else if (refValue->rValue > timestep) {
+ /* add the next time step value to the vector */
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ timenew = refValue->rValue;
+ fileAddRealValue(run->fp, run->binary, timestep);
+ timestep += run->circuit->CKTstep;
+ nodata = FALSE;
+ interpolatenow = TRUE;
+ }
+ else {
+ /* Do not save this step */
+ run->pointCount--;
+ timeold = refValue->rValue;
+ nodata = TRUE;
+ interpolatenow = FALSE;
+ }
+#ifndef HAS_WINGUI
+ if (!orflag && !ft_norefprint) {
+ currclock = clock();
+ if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
+ fprintf(stderr, " Reference value : % 12.5e\r",
+ refValue->rValue);
+ lastclock = currclock;
+ }
+ }
+#endif
+
+ }
+
+ for (i = 0; i < run->numData; i++) {
+ /* we've already printed reference vec first */
+ if (run->data[i].outIndex == -1)
+ continue;
+
+#ifdef TCL_MODULE
+ blt_add(i, refValue ? refValue->rValue : NAN);
+#endif
+
+ if (run->data[i].regular) {
+ /* Store value or interpolate and store or do not store any value to file */
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ fileAddRealValue(run->fp, run->binary, valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ fileAddRealValue(run->fp, run->binary, newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ } else {
+ IFvalue val;
+ /* should pre-check instance */
+ if (!getSpecial(&run->data[i], run, &val)) {
+
+ /* If this is the first data point, print a warning for any unrecognized
+ variables, since this has not already been checked */
+ if (run->pointCount == 1)
+ fprintf(stderr, "Warning: unrecognized variable - %s\n",
+ run->data[i].name);
+ val.rValue = 0;
+ fileAddRealValue(run->fp, run->binary, val.rValue);
+ continue;
+ }
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = val.rValue;
+ fileAddRealValue(run->fp, run->binary, valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = val.rValue;
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ fileAddRealValue(run->fp, run->binary, newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = val.rValue;
+ }
+
+#ifdef TCL_MODULE
+ blt_add(i, valuePtr->v.vec.rVec [run->data[i].outIndex]);
+#endif
+
+ }
+
+ fileEndPoint(run->fp, run->binary);
+
+ /* Check that the write to disk completed successfully, otherwise abort */
+ if (ferror(run->fp)) {
+ fprintf(stderr, "Warning: rawfile write error !!\n");
+ shouldstop = TRUE;
+ }
+
+ if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE)
+ shouldstop = TRUE;
+
+#ifdef TCL_MODULE
+ Tcl_ExecutePerLoop();
+#elif defined SHARED_MODULE
+ sh_ExecutePerLoop();
+#endif
+ return(OK);
+}
+
+static int
+InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i, iscale = -1;
+ static double timeold = 0.0, timenew = 0.0, timestep = 0.0;
+ bool nodata = FALSE;
+ bool interpolatenow = FALSE;
+
+ if (run->pointCount == 1)
+ timestep = run->circuit->CKTinitTime + run->circuit->CKTstep;
+
+ /* find the scale vector */
+ for (i = 0; i < run->numData; i++)
+ if (run->data[i].outIndex == -1) {
+ iscale = i;
+ break;
+ }
+ if (iscale == -1)
+ fprintf(stderr, "Error: no scale vector found\n");
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(iscale);
+#endif
+
+ /* Save first time step */
+ if (refValue->rValue == run->circuit->CKTinitTime) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], refValue->rValue);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save last time step */
+ else if (refValue->rValue == run->circuit->CKTfinalTime) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], run->circuit->CKTfinalTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save exact point */
+ else if (refValue->rValue == timestep) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], timestep);
+ timestep += run->circuit->CKTstep;
+ interpolatenow = nodata = FALSE;
+ }
+ else if (refValue->rValue > timestep) {
+ /* add the next time step value to the vector */
+ timenew = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], timestep);
+ timestep += run->circuit->CKTstep;
+ nodata = FALSE;
+ interpolatenow = TRUE;
+ }
+ else {
+ /* Do not save this step */
+ run->pointCount--;
+ timeold = refValue->rValue;
+ nodata = TRUE;
+ interpolatenow = FALSE;
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(iscale, (run->data[iscale]).vec);
+#endif
+
+#ifndef HAS_WINGUI
+ if (!orflag && !ft_norefprint) {
+ currclock = clock();
+ if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
+ fprintf(stderr, " Reference value : % 12.5e\r",
+ refValue->rValue);
+ lastclock = currclock;
+ }
+ }
+#endif
+
+ for (i = 0; i < run->numData; i++) {
+ if (i == iscale)
+ continue;
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(i);
+#endif
+
+ if (run->data[i].regular) {
+ /* Store value or interpolate and store or do not store any value to file */
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ plotAddRealValue(&run->data[i], valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ plotAddRealValue(&run->data[i], newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ } else {
+ IFvalue val;
+ /* should pre-check instance */
+ if (!getSpecial(&run->data[i], run, &val))
+ continue;
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = val.rValue;
+ plotAddRealValue(&run->data[i], valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = val.rValue;
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ plotAddRealValue(&run->data[i], newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = val.rValue;
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(i, (run->data[i]).vec);
+#endif
+
+ }
+
+ gr_iplot(run->runPlot);
+
+ if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE)
+ shouldstop = TRUE;
+
+#ifdef TCL_MODULE
+ Tcl_ExecutePerLoop();
+#elif defined SHARED_MODULE
+ sh_ExecutePerLoop();
+#endif
+
+ return(OK);
+}