2003-08-01 Stefan Jones <stefan.jones@multigig.com>
* src/xspice/mif/mif_inp2.c:
Reverted to version 1.1.2.2 so POLY and codemodels work
* src/xspice/mif/mifutil.c:
Check for NULL MIFcopy arg.
* src/Makefile.am:
Fixed libspice.so dependancies
* configure.in src/tclspice.c:
tclspice can now be built without thread support
* src/frontend/{com_let.c,device.c,evaluate.c}:
more memory leak fixes by Vera Albrecht <albrecht@danalyse.de>
This commit is contained in:
parent
3c44d3d4a4
commit
6e80733381
14
ChangeLog
14
ChangeLog
|
|
@ -1,3 +1,17 @@
|
|||
2003-08-01 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* src/xspice/mif/mif_inp2.c:
|
||||
Reverted to version 1.1.2.2 so POLY and codemodels work
|
||||
|
||||
* src/Makefile.am:
|
||||
Fixed libspice.so dependancies
|
||||
|
||||
* configure.in src/tclspice.c:
|
||||
tclspice can now be built without thread support
|
||||
|
||||
* src/frontend/{com_let.c,device.c,evaluate.c}:
|
||||
more memory leak fixes by Vera Albrecht <albrecht@danalyse.de>
|
||||
|
||||
2003-07-18 Vera Albrecht <albrecht@danalyse.de>
|
||||
|
||||
* src/{main.c,tclspice.c}
|
||||
|
|
|
|||
|
|
@ -217,6 +217,8 @@ else
|
|||
fi
|
||||
rm -f conftest.tcl
|
||||
|
||||
AC_CHECK_LIB(pthread,pthread_create)
|
||||
|
||||
else
|
||||
TCL_PACKAGE_PATH=""
|
||||
TCL_BUILD_LIB_SPEC=""
|
||||
|
|
|
|||
|
|
@ -213,8 +213,8 @@ install-tclspice: ${TCL_FILES}
|
|||
tclspice.o: tclspice.c
|
||||
$(COMPILE) -c -fpic tclspice.c -DTCLSPICE_version="\"$(TCLSPICE_VERSION)\""
|
||||
|
||||
libspice.so: $(ngspice_OBJECTS) $(LIBSPICE_OBJS) $(ngspice_DEPENDENCIES)
|
||||
$(LINK) $(ngspice_LDFLAGS) $(ngspice_OBJECTS) $(ngspice_LDADD) $(LIBS) $(LIBSPICE_OBJS) -shared -lpthread -Wl,--version-script=tclspice.map
|
||||
libspice.so: $(ngspice_OBJECTS) $(LIBSPICE_OBJS) $(ngspice_LDADD)
|
||||
$(LINK) $(ngspice_LDFLAGS) $(ngspice_OBJECTS) $(ngspice_LDADD) $(LIBS) $(LIBSPICE_OBJS) -shared -Wl,--version-script=tclspice.map
|
||||
if test -f .libs/$@ ; then \
|
||||
mv .libs/$@ ./ ;\
|
||||
rmdir .libs ;\
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ com_let(wordlist *wl)
|
|||
*rhs++ = 0;
|
||||
} else {
|
||||
fprintf(cp_err, "Error: bad let syntax\n");
|
||||
tfree(p);
|
||||
return;
|
||||
}
|
||||
if ((s =strchr(p, '['))) {
|
||||
|
|
@ -63,6 +64,7 @@ com_let(wordlist *wl)
|
|||
|
||||
if (depth != 0 || !*q) {
|
||||
printf("syntax error specifyingstrchr\n");
|
||||
tfree(p);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +88,7 @@ com_let(wordlist *wl)
|
|||
/* sanity check */
|
||||
if (eq(p, "all") ||strchr(p, '@')) {
|
||||
fprintf(cp_err, "Error: bad variable name %s\n", p);
|
||||
tfree(p);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +103,8 @@ com_let(wordlist *wl)
|
|||
t = ft_evaluate(nn);
|
||||
if (!t) {
|
||||
fprintf(cp_err, "Error: Can't evaluate %s\n", rhs);
|
||||
tfree(p);
|
||||
free_pnode(nn);
|
||||
tfree(p);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +120,7 @@ com_let(wordlist *wl)
|
|||
} else {
|
||||
if (numdims) {
|
||||
fprintf(cp_err, "Can't assign into a subindex of a new vector\n");
|
||||
tfree(p);
|
||||
free_pnode(nn);
|
||||
return;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* create and assign a new vector */
|
||||
|
|
@ -177,18 +178,14 @@ com_let(wordlist *wl)
|
|||
length * cube);
|
||||
if (newvec)
|
||||
n->v_flags &= ~VF_PERMANENT;
|
||||
tfree(p);
|
||||
free_pnode(nn);
|
||||
return;
|
||||
goto quit;
|
||||
}
|
||||
if (isreal(t) != isreal(n)) {
|
||||
fprintf(cp_err,
|
||||
"Types of vectors are not the same (real vs. complex)\n");
|
||||
if (newvec)
|
||||
n->v_flags &= ~VF_PERMANENT;
|
||||
tfree(p);
|
||||
free_pnode(nn);
|
||||
return;
|
||||
goto quit;
|
||||
} else if (isreal(t)) {
|
||||
bcopy((char *) t->v_realdata, (char *) (n->v_realdata + offset),
|
||||
length * sizeof (double));
|
||||
|
|
@ -205,7 +202,10 @@ com_let(wordlist *wl)
|
|||
if (newvec)
|
||||
cp_addkword(CT_VECTOR, n->v_name);
|
||||
|
||||
quit:
|
||||
/* va: garbage collection for t, if pnode nn is no simple value */
|
||||
if (nn->pn_value==NULL && t!=NULL) vec_free(t);
|
||||
free_pnode(nn); /* frees also t, if pnode nn is simple value */
|
||||
tfree(p);
|
||||
free_pnode(nn);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -648,8 +648,9 @@ com_alter_common(wordlist *wl, int do_model)
|
|||
|
||||
if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
|
||||
|
||||
free_pnode(names);
|
||||
|
||||
/* va: garbage collection for dv, if pnode names is no simple value */
|
||||
if (names->pn_value==NULL && dv!=NULL) vec_free(dv);
|
||||
free_pnode(names); /* free also dv, if pnode names is simple value */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,14 +39,16 @@ sig_matherr(void)
|
|||
|
||||
|
||||
/* Note that ft_evaluate will return NULL on invalid expressions. */
|
||||
|
||||
/* va: NOTE: ft_evaluate returns a new vector for expressions (func, op, ...)
|
||||
and an existing vector (node->pn_value) when node->pn_value != NULL.
|
||||
For garbage collection caller must vec_free() expression-vector. */
|
||||
struct dvec *
|
||||
ft_evaluate(struct pnode *node)
|
||||
{
|
||||
struct dvec *d = NULL;
|
||||
|
||||
if (!node)
|
||||
return (NULL);
|
||||
d = NULL;
|
||||
else if (node->pn_value)
|
||||
d = node->pn_value;
|
||||
else if (node->pn_func)
|
||||
|
|
@ -55,21 +57,22 @@ ft_evaluate(struct pnode *node)
|
|||
if (node->pn_op->op_arity == 1)
|
||||
d = (struct dvec *)
|
||||
((*node->pn_op->op_func) (node->pn_left));
|
||||
else if (node->pn_op->op_arity == 2)
|
||||
else if (node->pn_op->op_arity == 2) {
|
||||
d = (struct dvec *) ((*node->pn_op->op_func)
|
||||
(node->pn_left, node->pn_right));
|
||||
}
|
||||
} else {
|
||||
fprintf(cp_err, "ft_evaluate: Internal Error: bad node\n");
|
||||
return (NULL);
|
||||
d = NULL;
|
||||
}
|
||||
|
||||
if (!d) {
|
||||
if (d==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->pn_name && !ft_evdb && d && !d->v_link2) {
|
||||
if(d->v_name)
|
||||
tfree(d->v_name);
|
||||
if (d->v_name)
|
||||
tfree(d->v_name); /* patch by Stefan Jones */
|
||||
d->v_name = copy(node->pn_name);
|
||||
}
|
||||
|
||||
|
|
@ -294,6 +297,9 @@ doop(char what,
|
|||
}
|
||||
}
|
||||
|
||||
/* va: garbage collection */
|
||||
if (arg1->pn_value==NULL && v1!=NULL) vec_free(v1);
|
||||
if (arg2->pn_value==NULL && v2!=NULL) vec_free(v2);
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
|
@ -493,6 +499,10 @@ op_range(struct pnode *arg1, struct pnode *arg2)
|
|||
*/
|
||||
|
||||
vec_new(res);
|
||||
|
||||
/* va: garbage collection */
|
||||
if (arg1->pn_value==NULL && v!=NULL) vec_free(v);
|
||||
if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind);
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
|
@ -642,6 +652,10 @@ op_ind(struct pnode *arg1, struct pnode *arg2)
|
|||
*/
|
||||
|
||||
vec_new(res);
|
||||
|
||||
/* va: garbage collection */
|
||||
if (arg1->pn_value==NULL && v!=NULL) vec_free(v);
|
||||
if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind);
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
|
@ -768,6 +782,8 @@ apply_func(struct func *func, struct pnode *arg)
|
|||
end = t;
|
||||
}
|
||||
|
||||
/* va: garbage collection */
|
||||
if (arg->pn_value==NULL && v!=NULL) vec_free(v);
|
||||
return (newv);
|
||||
}
|
||||
|
||||
|
|
|
|||
105
src/tclspice.c
105
src/tclspice.c
|
|
@ -81,8 +81,10 @@ extern jmp_buf jbuf;
|
|||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
/* run spicein background */
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h> /* for va_copy() */
|
||||
|
||||
|
|
@ -95,7 +97,9 @@ extern int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator);
|
|||
/*For blt spice to use*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_t mutex;/*lock for this vector*/
|
||||
#endif
|
||||
double *data;/* vector data*/
|
||||
int size;/*data it can store*/
|
||||
int length;/*actual amount of data*/
|
||||
|
|
@ -187,7 +191,9 @@ void blt_init(void *run) {
|
|||
if(ownVectors)
|
||||
FREE(vectors[i].data);
|
||||
FREE(vectors[i].name);
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_destroy(&vectors[i].mutex);
|
||||
#endif
|
||||
}
|
||||
FREE(vectors);
|
||||
}
|
||||
|
|
@ -198,7 +204,9 @@ void blt_init(void *run) {
|
|||
vectors = (vector *)MALLOC(cur_run->numData*sizeof(vector));
|
||||
for(i = 0;i < cur_run->numData;i++){
|
||||
vectors[i].name = copy((cur_run->data[i]).name);
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_init(&vectors[i].mutex,NULL);
|
||||
#endif
|
||||
vectors[i].data = NULL;
|
||||
vectors[i].size = 0;
|
||||
vectors[i].length = 0;
|
||||
|
|
@ -212,20 +220,26 @@ void blt_init(void *run) {
|
|||
void blt_add(int index,double value){
|
||||
vector *v;
|
||||
v = &vectors[index];
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&vectors[index].mutex);
|
||||
#endif
|
||||
if(!(v->length < v->size)){
|
||||
v->size += 100;
|
||||
v->data = (double *)REALLOC(v->data,sizeof(double)*v->size);
|
||||
}
|
||||
v->data[v->length] = value;
|
||||
v->length ++;
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&vectors[index].mutex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Locks the vector data to stop conflicts*/
|
||||
void blt_lockvec(int index){
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&vectors[index].mutex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +251,9 @@ void blt_relink(int index,void *tmp){
|
|||
vectors[index].data = v->v_realdata;
|
||||
vectors[index].length = v->v_length;
|
||||
vectors[index].size = v->v_length;/*silly spice doesn't use v_rlength*/
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&vectors[index].mutex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -270,9 +286,13 @@ static int lastVector TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
}
|
||||
|
||||
for(i=0;i < blt_vnum;i++){
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&vectors[i].mutex);
|
||||
#endif
|
||||
V[i] = vectors[i].data[vectors[i].length-1];
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&vectors[i].mutex);
|
||||
#endif
|
||||
}
|
||||
Blt_ResetVector(vec,V,blt_vnum,
|
||||
blt_vnum,TCL_VOLATILE);
|
||||
|
|
@ -319,7 +339,9 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
if(argc == 5)
|
||||
end = atoi(argv[4]);
|
||||
if(vectors[index].length) {
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&vectors[index].mutex);
|
||||
#endif
|
||||
|
||||
len = vectors[index].length;
|
||||
|
||||
|
|
@ -337,8 +359,10 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
|
||||
Blt_ResetVector(vec,(vectors[index].data + start),len,
|
||||
len,TCL_VOLATILE);
|
||||
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&vectors[index].mutex);
|
||||
#endif
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
|
@ -348,6 +372,7 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
/* Main spice command executions and thread control */
|
||||
/*****************************************************************/
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
static pthread_t tid, bgtid=(pthread_t)0;
|
||||
static bool fl_running = FALSE;
|
||||
static bool fl_exited = TRUE;
|
||||
|
|
@ -389,11 +414,14 @@ static int _thread_stop(){
|
|||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /*HAVE_LIBPTHREAD*/
|
||||
|
||||
static int _run(int argc,char **argv){
|
||||
char buf[1024] = "", *string;
|
||||
char buf[1024] = "";
|
||||
int i;
|
||||
sighandler_t oldHandler;
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
char *string;
|
||||
bool fl_bg = FALSE;
|
||||
/* run task in background if preceeded by "bg"*/
|
||||
if(!strcmp(argv[0],"bg")) {
|
||||
|
|
@ -401,6 +429,7 @@ static int _run(int argc,char **argv){
|
|||
argv = &argv[1];
|
||||
fl_bg = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Catch Ctrl-C to break simulations */
|
||||
oldHandler = signal(SIGINT,ft_sigintr);
|
||||
|
|
@ -415,7 +444,7 @@ static int _run(int argc,char **argv){
|
|||
strcat(buf," ");
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
/* run in the background */
|
||||
if(fl_bg){
|
||||
if(fl_running) _thread_stop();
|
||||
|
|
@ -449,6 +478,9 @@ static int _run(int argc,char **argv){
|
|||
cp_evloop(buf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
cp_evloop(buf);
|
||||
#endif /*HAVE_LIBPTHREAD*/
|
||||
signal(SIGINT,oldHandler);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
|
@ -471,12 +503,13 @@ static int _spice_dispatch TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
return _run(argc-1,(char **)&argv[1]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
/*Checks if spice is runnuing in the background */
|
||||
static int running TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
||||
Tcl_SetObjResult(interp,Tcl_NewIntObj((long) (fl_running && !fl_exited)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**************************************/
|
||||
/* plot manipulation functions */
|
||||
|
|
@ -1098,7 +1131,9 @@ struct triggerEvent {
|
|||
struct triggerEvent *eventQueue=NULL;
|
||||
struct triggerEvent *eventQueueEnd=NULL;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_t triggerMutex;
|
||||
#endif
|
||||
|
||||
struct watch {
|
||||
struct watch *next;
|
||||
|
|
@ -1114,14 +1149,18 @@ struct watch *watches=NULL;
|
|||
int Tcl_ExecutePerLoop() {
|
||||
|
||||
struct watch *current;
|
||||
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&vectors[0].mutex);
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
for(current=watches;current;current = current->next) {
|
||||
vector *v;
|
||||
v = &vectors[current->vector];
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&v->mutex);
|
||||
#endif
|
||||
|
||||
if((current->type > 0 && current->state && v->data[v->length-1] > current->Vmax) ||
|
||||
(current->type < 0 && current->state && v->data[v->length-1] < current->Vmin) ) {
|
||||
|
|
@ -1149,18 +1188,24 @@ int Tcl_ExecutePerLoop() {
|
|||
if((current->type > 0 && v->data[v->length-1] < current->Vmin) ||
|
||||
(current->type < 0 && v->data[v->length-1] > current->Vmax))
|
||||
current->state = 1;
|
||||
pthread_mutex_unlock(&v->mutex);
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&v->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
|
||||
pthread_mutex_unlock(&vectors[0].mutex);
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resetTriggers() {
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
while(watches) {
|
||||
struct watch *tmp = watches;
|
||||
|
|
@ -1176,7 +1221,9 @@ static int resetTriggers() {
|
|||
|
||||
eventQueueEnd = NULL;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1207,7 +1254,9 @@ static int registerTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
return TCL_ERROR;
|
||||
} else index = i;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
tmp = (struct watch *)MALLOC(sizeof(struct watch));
|
||||
|
||||
|
|
@ -1224,7 +1273,9 @@ static int registerTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
watches->Vmin = atof(argv[2]);
|
||||
watches->Vmax = atof(argv[3]);
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
|
@ -1258,7 +1309,9 @@ static int unregisterTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
else
|
||||
type = 1;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
cut = &watches;
|
||||
|
||||
|
|
@ -1275,8 +1328,10 @@ static int unregisterTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
|
||||
#endif
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1294,8 +1349,10 @@ static int popTriggerEvent TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
struct triggerEvent *popedEvent;
|
||||
Tcl_Obj *list;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
|
||||
#endif
|
||||
|
||||
popedEvent = eventQueue;
|
||||
|
||||
eventQueue = popedEvent->next;
|
||||
|
|
@ -1315,7 +1372,9 @@ static int popTriggerEvent TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
|
||||
FREE(popedEvent);
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
|
|
@ -1332,13 +1391,17 @@ static int listTriggers TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
|
||||
list = Tcl_NewListObj(0,NULL);
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&triggerMutex);
|
||||
#endif
|
||||
|
||||
for(tmp=watches;tmp;tmp=tmp->next)
|
||||
Tcl_ListObjAppendElement(interp,list,Tcl_NewStringObj(vectors[tmp->vector].name,strlen(vectors[tmp->vector].name)));
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&triggerMutex);
|
||||
|
||||
#endif
|
||||
|
||||
Tcl_SetObjResult(interp,list);
|
||||
|
||||
return TCL_OK;
|
||||
|
|
@ -1406,8 +1469,10 @@ int Spice_Init(Tcl_Interp *interp) {
|
|||
ARCHsize = 1;
|
||||
|
||||
/* init the mutex */
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_init(&triggerMutex,NULL);
|
||||
|
||||
#endif
|
||||
|
||||
/*register functions*/
|
||||
for (i = 0;(key = cp_coms[i].co_comname); i++) {
|
||||
sprintf(buf,"%s%s",TCLSPICE_prefix,key);
|
||||
|
|
@ -1424,13 +1489,10 @@ int Spice_Init(Tcl_Interp *interp) {
|
|||
Tcl_CreateCommand(interp, TCLSPICE_prefix "lastVector", lastVector, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "spice", _spice_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "get_output", get_output, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "bg", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "halt", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "get_param", get_param, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "get_mod_param", get_mod_param, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "delta", delta, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "maxstep", maxstep, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_variables", plot_variables, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_get_value", plot_get_value, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_datapoints", plot_datapoints, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
|
|
@ -1443,6 +1505,12 @@ int Spice_Init(Tcl_Interp *interp) {
|
|||
Tcl_CreateCommand(interp, TCLSPICE_prefix "unregisterTrigger", unregisterTrigger, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "listTriggers", listTriggers, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "bg", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "halt", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
#endif
|
||||
|
||||
Tcl_LinkVar(interp, TCLSPICE_prefix "steps_completed", (char *)&steps_completed, TCL_LINK_READ_ONLY|TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, TCLSPICE_prefix "blt_vnum", (char *)&blt_vnum, TCL_LINK_READ_ONLY|TCL_LINK_INT);
|
||||
}
|
||||
|
|
@ -1478,8 +1546,11 @@ int tcl_vfprintf(FILE *f, const char *fmt, va_list args_in)
|
|||
char *outptr, *bigstr = NULL, *finalstr = NULL;
|
||||
int i, nchars, result, escapes = 0;
|
||||
|
||||
if((f != stdout && f != stderr) ||
|
||||
( fl_running && bgtid == pthread_self()) )
|
||||
if((f != stdout && f != stderr)
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
|| ( fl_running && bgtid == pthread_self())
|
||||
#endif
|
||||
)
|
||||
return vfprintf(f,fmt,args_in);
|
||||
|
||||
strcpy (outstr + 19, (f == stderr) ? "err \"" : "out \"");
|
||||
|
|
@ -1576,8 +1647,10 @@ void tcl_stdflush(FILE *f)
|
|||
static char stdstr[] = "flush stdxxx";
|
||||
char *stdptr = stdstr + 9;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
if ( fl_running && bgtid == pthread_self())
|
||||
return;
|
||||
#endif
|
||||
|
||||
Tcl_SaveResult(spice_interp, &state);
|
||||
strcpy(stdptr, (f == stderr) ? "err" : "out");
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ card *current; /* the card we are to parse */
|
|||
/* and return a pointer to its structure in 'thismodel' */
|
||||
|
||||
current->error = MIFgetMod(ckt, model, &thismodel, tab);
|
||||
tfree(name);
|
||||
|
||||
if(current->error) {
|
||||
return;
|
||||
|
|
@ -196,8 +195,8 @@ card *current; /* the card we are to parse */
|
|||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In MIF_INP2A, about to get ports on line %s\n",
|
||||
current->line);
|
||||
printf("In MIF_INP2A, after tokenizing, name = %s, model = %s\n",
|
||||
name, model);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -232,21 +231,20 @@ card *current; /* the card we are to parse */
|
|||
/* and reading the first token following */
|
||||
|
||||
line = current->line;
|
||||
MIFgettok(&line); /* read instance name again . . . .*/
|
||||
MIFgettok(&line);
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
|
||||
|
||||
/* loop through the fixed number of connections expected */
|
||||
|
||||
/******* loop through the fixed number of connections expected *******/
|
||||
for(i = 0; i < DEVices[type]->DEVpublic.num_conn; i++) {
|
||||
|
||||
/* there better be at least one more token besides the model name */
|
||||
if(*line == '\0') {
|
||||
LITERR("Encountered end of line before all connections were found in model.");
|
||||
LITERR("Missing connections on A device");
|
||||
return;
|
||||
}
|
||||
|
||||
/* now get next token, should be a % after this statement */
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
|
||||
|
||||
/* prepare a pointer for fast access to info about this connection */
|
||||
conn_info = &(DEVices[type]->DEVpublic.conn[i]);
|
||||
|
||||
|
|
@ -254,34 +252,6 @@ card *current; /* the card we are to parse */
|
|||
def_port_type = conn_info->default_port_type;
|
||||
def_port_type_str = conn_info->default_type;
|
||||
|
||||
|
||||
/* Now get real info about connection type (instead of default info) */
|
||||
if(next_token_type == MIF_PERCENT_TOK) { /* next_token_type should be a % */
|
||||
|
||||
/* get the port type identifier and check it for validity */
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
MIFget_port_type(ckt,
|
||||
tab,
|
||||
current,
|
||||
&line,
|
||||
&next_token,
|
||||
&next_token_type,
|
||||
&def_port_type,
|
||||
&def_port_type_str,
|
||||
conn_info,
|
||||
&status);
|
||||
if(status == MIF_ERROR)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
LITERR("Non percent token encountered when expecting MIF_PERCENT_TOK");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* At this point, next_token should hold the token *after* the port type
|
||||
identified (%v, %id, etc). */
|
||||
|
||||
/* set analog and event_driven flags on instance and model */
|
||||
if((def_port_type == MIF_DIGITAL) || (def_port_type == MIF_USER_DEFINED)) {
|
||||
fast->event_driven = MIF_TRUE;
|
||||
|
|
@ -292,8 +262,8 @@ card *current; /* the card we are to parse */
|
|||
mdfast->analog = MIF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* check for a null connection and continue to next connection if found */
|
||||
|
||||
if(next_token_type == MIF_NULL_TOK) {
|
||||
|
||||
/* make sure null is allowed */
|
||||
|
|
@ -315,13 +285,10 @@ card *current; /* the card we are to parse */
|
|||
fast->conn[i]->is_null = MIF_FALSE;
|
||||
}
|
||||
|
||||
/* process connection as appropriate for scalar or array */
|
||||
|
||||
|
||||
/* ===== process connection as appropriate for scalar or array ====== */
|
||||
if(! conn_info->is_array) { /* a scalar connection - the simpler case */
|
||||
|
||||
/* At this point, next_token should hold the first netname in the port netlist. */
|
||||
|
||||
/* do a couple of error checks */
|
||||
if(next_token_type == MIF_LARRAY_TOK) {
|
||||
LITERR("ERROR - Scalar connection expected, [ found");
|
||||
|
|
@ -348,27 +315,44 @@ card *current; /* the card we are to parse */
|
|||
0, /* port index for scalar connection */
|
||||
&status);
|
||||
|
||||
/* upon leaving MIFget_port, we should be *ready* to read a % with the next
|
||||
get_token */
|
||||
|
||||
if(status == MIF_ERROR)
|
||||
return;
|
||||
|
||||
fast->conn[i]->size = 1;
|
||||
}
|
||||
else { /* ====== the connection is an array - much to be done ... ====== */
|
||||
else { /* the connection is an array - much to be done ... */
|
||||
|
||||
/* At this point, the next_token should be a [ */
|
||||
/* get the leading port type for the array if any */
|
||||
/* it will distribute across all ports inside the braces */
|
||||
/* overriding the default type in the interface spec */
|
||||
|
||||
if(next_token_type == MIF_PERCENT_TOK) {
|
||||
|
||||
/* get the port type identifier and check it for validity */
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
MIFget_port_type(ckt,
|
||||
tab,
|
||||
current,
|
||||
&line,
|
||||
&next_token,
|
||||
&next_token_type,
|
||||
&def_port_type,
|
||||
&def_port_type_str,
|
||||
conn_info,
|
||||
&status);
|
||||
if(status == MIF_ERROR)
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for required leading array delim character and eat it if found */
|
||||
if(next_token_type != MIF_LARRAY_TOK) {
|
||||
LITERR("Missing [, an array connection was expected");
|
||||
return;
|
||||
}
|
||||
else /* eat the [ */
|
||||
else
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
|
||||
/*------ get and process ports until ] is encountered ------*/
|
||||
/* get and process ports until ] is encountered */
|
||||
|
||||
for(j = 0;
|
||||
(next_token_type != MIF_RARRAY_TOK) &&
|
||||
|
|
@ -402,24 +386,16 @@ card *current; /* the card we are to parse */
|
|||
|
||||
if(status == MIF_ERROR)
|
||||
return;
|
||||
} /*------ end of for loop until ] is encountered ------*/
|
||||
|
||||
/* At this point, next_token should hold the next token after the
|
||||
port netnames. This token should be a ]. */
|
||||
}
|
||||
|
||||
/* make sure we exited because the end of the array connection */
|
||||
/* was reached. If so, eat the closing array delimiter ] */
|
||||
/* was reached. If so, eat the closing array delimiter */
|
||||
if(*line == '\0') {
|
||||
LITERR("Missing ] in array connection");
|
||||
return;
|
||||
}
|
||||
|
||||
/* else {
|
||||
* next_token = MIFget_token(&line,&next_token_type);
|
||||
* }
|
||||
*/
|
||||
|
||||
/* At this point, the next time we get_token, we should get a % */
|
||||
else
|
||||
next_token = MIFget_token(&line,&next_token_type);
|
||||
|
||||
/* record the number of ports found for this connection */
|
||||
if(j < 1) {
|
||||
|
|
@ -428,13 +404,12 @@ card *current; /* the card we are to parse */
|
|||
}
|
||||
fast->conn[i]->size = j;
|
||||
|
||||
} /* ====== array connection processing ====== */
|
||||
} /* array connection processing */
|
||||
|
||||
/* be careful about putting stuff here, there is a 'continue' used */
|
||||
/* in the processing of NULL connections above */
|
||||
|
||||
|
||||
} /******* for number of connections *******/
|
||||
} /* for number of connections */
|
||||
|
||||
|
||||
/* *********************** */
|
||||
|
|
@ -443,12 +418,8 @@ card *current; /* the card we are to parse */
|
|||
|
||||
/* check for too many connections */
|
||||
|
||||
/* At this point, we should have eaten all the net connections. At
|
||||
this point, line should hold only the remainder of the model line (i.e.
|
||||
the model name). */
|
||||
|
||||
if(strcmp(line,name) != 0) {
|
||||
LITERR("Too many connections -- expecting model name but encountered other tokens.");
|
||||
if(*line != '\0') {
|
||||
LITERR("Too many connections");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -615,17 +586,7 @@ static void MIFinit_inst(
|
|||
/*
|
||||
MIFget_port_type
|
||||
|
||||
This function gets the port type identifier and checks it for validity. It also
|
||||
replaces false default information in conn_info with the real info based upon
|
||||
the discovered port type string.
|
||||
|
||||
When we call it, we expect that the next token type (sent from above)
|
||||
should be the port type (MIF_STRING_TOK type). That is, we should be sitting right
|
||||
on the def of the port type (i.e. %vnam, %vd, %id, etc.) Note that the parser
|
||||
should have stripped the % already.
|
||||
|
||||
Upon return, this fcn should leave next_token holding the token *after* the
|
||||
port type (i.e. the thing after vnam, v, vd, id, etc).
|
||||
This function gets the port type identifier and checks it for validity.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -682,20 +643,8 @@ MIFget_port_type(
|
|||
LITERR("Port type is invalid");
|
||||
*status = MIF_ERROR;
|
||||
}
|
||||
else {
|
||||
|
||||
/* Fix by SDB so that the netlist parser uses the actual nature
|
||||
of the port instead of the default state to decide if it is an array. */
|
||||
if ( (*port_type == MIF_DIFF_VOLTAGE) ||
|
||||
(*port_type == MIF_DIFF_CURRENT) ||
|
||||
(*port_type == MIF_DIFF_CONDUCTANCE) ||
|
||||
(*port_type == MIF_DIFF_RESISTANCE) ) {
|
||||
conn_info->is_array = 1;
|
||||
}
|
||||
|
||||
else
|
||||
*status = MIF_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -709,13 +658,6 @@ MIFget_port
|
|||
|
||||
This function processes a port being parsed, either single ended,
|
||||
or both connections of a differential.
|
||||
|
||||
When we call this fcn, next_token should be the *first* netname in the port
|
||||
net list. Depending upon the type of port, this fcn should eat the appropriate
|
||||
number of net tokens.
|
||||
|
||||
When we leave this fcn, next_token should hold the next token after the last
|
||||
netname processed.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -745,6 +687,27 @@ MIFget_port(
|
|||
|
||||
char *node;
|
||||
|
||||
/* get the leading port type if any */
|
||||
|
||||
if(*next_token_type == MIF_PERCENT_TOK) {
|
||||
|
||||
/* get the port type identifier and check it for validity */
|
||||
*next_token = MIFget_token(line, next_token_type);
|
||||
MIFget_port_type(ckt,
|
||||
tab,
|
||||
current,
|
||||
line,
|
||||
next_token,
|
||||
next_token_type,
|
||||
&def_port_type,
|
||||
&def_port_type_str,
|
||||
conn_info,
|
||||
status);
|
||||
|
||||
if(*status == MIF_ERROR) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate space in the instance data struct for this port */
|
||||
if(port_num == 0) {
|
||||
|
|
|
|||
|
|
@ -314,11 +314,8 @@ This function allocates a new copy of a string.
|
|||
|
||||
char *MIFcopy(char *str)
|
||||
{
|
||||
char *temp;
|
||||
|
||||
/* Allocate space for the string and then copy it */
|
||||
temp = MALLOC(strlen(str) + 1);
|
||||
strcpy(temp,str);
|
||||
|
||||
return(temp);
|
||||
if(str)
|
||||
return copy(str);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue