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:
stefanjones 2003-08-01 11:03:01 +00:00
parent 3c44d3d4a4
commit 6e80733381
9 changed files with 213 additions and 147 deletions

View File

@ -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}

View File

@ -217,6 +217,8 @@ else
fi
rm -f conftest.tcl
AC_CHECK_LIB(pthread,pthread_create)
else
TCL_PACKAGE_PATH=""
TCL_BUILD_LIB_SPEC=""

View File

@ -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 ;\

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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");

View File

@ -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) {

View File

@ -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;
}