From 8cc46680abe80dad6dedc121575fcc072f01d7e1 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Mon, 4 Apr 2005 10:38:45 +0000 Subject: [PATCH] Fixed a bug in model name translation. --- src/frontend/subckt.c | 131 +++++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 47 deletions(-) diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index a176063be..48cfe7d4f 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -4,6 +4,15 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group Modified: 2000 AlansFixes **********/ +/*------------------------------------------------------------------------------ + * Added changes supplied by by H.Tanaka with some tidy up of comments, debug + * statements, and variables. This fixes a problem with nested .subsck elements + * that accessed .model lines. Code not ideal, but it seems to work okay. + * Also took opportunity to tidy a few other items (unused variables etc.), plus + * fix a few spelling errors in the comments, and a memory leak. + * SJB 25th March 2005 + *----------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------------ * re-written by SDB during 4.2003 to enable SPICE2 POLY statements to be processed * properly. This is particularly important for dependent sources, whose argument @@ -60,16 +69,8 @@ Modified: 2000 AlansFixes extern char * nupa_copy(char *s, int linenum); extern int nupa_eval(char *s, int linenum); extern int nupa_signal(int sig, char *info); -static char NumParams='y'; -static char DoGarbage='n'; - -#else -#define nupa_copy(x,y) copy(x) -#define nupa_eval(x,y) 1 -#define nupa_signal(x,y) 1 #endif - /* ----- static declarations ----- */ static struct line * doit(struct line *deck); static int translate(struct line *deck, char *formal, char *actual, char *scname, @@ -81,6 +82,7 @@ static int numnodes(char *name); static int numdevs(char *s); static bool modtranslate(struct line *deck, char *subname); static void devmodtranslate(struct line *deck, char *subname); +static int inp_numnodes(char c); /*--------------------------------------------------------------------- * table is used in settrans and gettrans -- it holds the netnames used @@ -99,7 +101,7 @@ static struct tab { *--------------------------------------------------------------------*/ struct subs { char *su_name; /* The .subckt name. */ - char *su_args; /* The .subckt arguments, space seperated. */ + char *su_args; /* The .subckt arguments, space separated. */ int su_numargs; struct line *su_def; /* Pointer to the .subckt definition. */ struct subs *su_next; @@ -116,6 +118,10 @@ static bool nobjthack = FALSE; static char start[32], sbend[32], invoke[32], model[32]; +#ifdef NUMPARAMS +static char NumParams='y'; +#endif + /*-------------------------------------------------------------------*/ /* inp_subcktexpand is the top level function which translates */ /* .subckts into mainlined code. Note that there are two things */ @@ -140,13 +146,15 @@ inp_subcktexpand(struct line *deck) #ifdef NUMPARAMS int ok; #endif + wordlist *wl; + modnames = NULL; if(!cp_getvar("substart", VT_STRING, start)) (void) strcpy(start, ".subckt"); if(!cp_getvar("subend", VT_STRING, sbend)) (void) strcpy(sbend, ".ends"); if(!cp_getvar("subinvoke", VT_STRING, invoke)) - (void) strcpy(invoke, "X"); + (void) strcpy(invoke, "x"); if(!cp_getvar("modelcard", VT_STRING, model)) (void) strcpy(model, ".model"); if(!cp_getvar("modelline", VT_STRING, model)) @@ -165,11 +173,36 @@ inp_subcktexpand(struct line *deck) } #endif - /* Let's do a few cleanup things first... Get rid of ( ) around node + /* Get all the model names so we can deal with BJTs, etc. + * Stick all the model names into the doubly-linked wordlist modnames. + */ + for (c = deck; c; c = c->li_next) + if (ciprefix(model, c->li_line)) { + s = c->li_line; + txfree(gettok(&s)); // discard the model keyword + wl = alloc(struct wordlist); + wl->wl_next = modnames; + if (modnames) + modnames->wl_prev = wl; + modnames = wl; + wl->wl_word = gettok(&s); /* wl->wl_word now holds name of model */ + }/*model name finding routine*/ + +#ifdef TRACE + { + wordlist * w; + printf("Models found:\n"); + for(w = modnames; w; w = w->wl_next) + printf("%s\n",w->wl_word); + } +#endif + + + /* Let's do a few cleanup things... Get rid of ( ) around node * lists... */ for (c = deck; c; c = c->li_next) { /* iterate on lines in deck */ - if (prefix(start, c->li_line)) { /* if we find .subckt . . . */ + if (ciprefix(start, c->li_line)) { /* if we find .subckt . . . */ #ifdef TRACE /* SDB debug statement */ printf("In inp_subcktexpand, found a .subckt: %s\n", c->li_line); @@ -212,6 +245,12 @@ inp_subcktexpand(struct line *deck) #endif ll = doit(deck); + // SJB: free up the modnames linked list now we are done with it + if(modnames != NULL) { + wl_free(modnames); + modnames = NULL; + } + /* Now check to see if there are still subckt instances undefined... */ if (ll!=NULL) for (c = ll; c; c = c->li_next) if (ciprefix(invoke, c->li_line)) { @@ -258,30 +297,29 @@ doit(struct line *deck) char *s, *t, *scname, *subname; int nest, numpasses = MAXNEST, i; bool gotone; - wordlist *wl; wordlist *tmodnames = modnames; wordlist *tsubmod = submod; struct subs *ts = subs; int error; /* Save all the old stuff... */ - modnames = NULL; subs = NULL; submod = NULL; #ifdef TRACE /* SDB debug statement */ printf("In doit, about to start first pass through deck.\n"); + for(c=deck;c; c=c->li_next) + printf(" %s\n",c->li_line); #endif - /* First pass: xtract all the .subckts and stick pointers to them into sss. */ for (last = deck, lc = NULL; last; ) { - if (prefix(sbend, last->li_line)) { /* if line == .ends */ + if (ciprefix(sbend, last->li_line)) { /* if line == .ends */ fprintf(cp_err, "Error: misplaced %s line: %s\n", sbend, last->li_line); return (NULL); } - else if (prefix(start, last->li_line)) { /* if line == .subckt */ + else if (ciprefix(start, last->li_line)) { /* if line == .subckt */ if (last->li_next == NULL) { /* first check that next line is non null */ fprintf(cp_err, "Error: no %s line.\n", sbend); return (NULL); @@ -296,7 +334,7 @@ doit(struct line *deck) * .subckt card, and lcc will point to the location of the .ends card. */ for (nest = 0, c = last->li_next; c; c = c->li_next) { - if (prefix(sbend, c->li_line)) { /* found a .ends */ + if (ciprefix(sbend, c->li_line)) { /* found a .ends */ if (!nest) break; /* nest = 0 means we have balanced .subckt and .ends */ else { @@ -304,7 +342,7 @@ doit(struct line *deck) lcc = c; /* (lcc points to the position of the .ends) */ continue; /* then continue looping */ } - } else if (prefix(start, c->li_line)) /* if .subckt, increment nesting */ + } else if (ciprefix(start, c->li_line)) /* if .subckt, increment nesting */ nest++; lcc = c; /* lcc points to current pos of c */ } /* for (nest = 0 . . . */ @@ -382,25 +420,11 @@ doit(struct line *deck) return (NULL); subs = ks; /* ks has held pointer to start of subcircuits list. */ - - /* Get all the model names so we can deal with BJT's. - * Stick all the model names into the doubly-linked wordlist wl. - */ - for (c = deck; c; c = c->li_next) - if (prefix(model, c->li_line)) { - s = c->li_line; - txfree(gettok(&s)); - wl = alloc(struct wordlist); - wl->wl_next = modnames; - if (modnames) - modnames->wl_prev = wl; - modnames = wl; - wl->wl_word = gettok(&s); /* wl->wl_word now holds name of model */ - } - #ifdef TRACE /* SDB debug statement */ printf("In doit, about to start second pass through deck.\n"); + for(c=deck;c; c=c->li_next) + printf(" %s\n",c->li_line); #endif error = 0; @@ -521,6 +545,19 @@ doit(struct line *deck) return (NULL); } +#ifdef TRACE + /* Added by H.Tanaka to display converted deck */ + printf("Converted deck\n"); + for (c = deck; c; c = c->li_next){ + printf( "%s\n",c->li_line); + } + { + wordlist * w; + printf("Models:\n"); + for(w = modnames; w; w = w->wl_next) + printf("%s\n",w->wl_word); + } +#endif if (error) return NULL; /* error message already reported; should free( ) */ @@ -942,10 +979,9 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub /* Next iterate over all nodes (netnames) found and translate them. */ nnodes = numnodes(c->li_line); - while (nnodes-- > 0) { name = gettok_node(&s); - if (name == NULL) { + if (name == NULL ) { fprintf(cp_err, "Error: too few nodes: %s\n", c->li_line); goto quit; @@ -970,7 +1006,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub } /* while (nnodes-- . . . . */ /* Now translate any devices (i.e. controlling sources). - * This may be supurfluous because we handle dependent + * This may be superfluous because we handle dependent * source devices above . . . . */ nnodes = numdevs(c->li_line); @@ -998,7 +1034,6 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub tfree(t); } /* while (nnodes--. . . . */ - /* Now we finish off the line. For most components (R, C, etc), * this involves adding the component value to the buffer. * We also scan through the line for v(something) and @@ -1244,7 +1279,7 @@ numnodes(char *name) /* Added this code for variable number of nodes on BSIM3SOI devices */ /* The consequence of this code is that the value returned by the */ - /* inp_numnodes(c) call must be regarded as "maximun number of nodes */ + /* inp_numnodes(c) call must be regarded as "maximum number of nodes */ /* for a given device type. */ /* Paolo Nenzi Jan-2001 */ @@ -1266,17 +1301,16 @@ numnodes(char *name) } /* while . . . . */ /* Note: node checks must be done on #_of_node-1 because the */ - /* "while" cicle increments the counter even when a model is */ + /* "while" cycle increments the counter even when a model is */ /* recognized. This code may be better! */ if (i < 5) { fprintf(cp_err, "Error: too few nodes for MOS: %s\n", name); return(0); } - return(i-1); /* compesate the unnecessary inrement in the while cicle */ + return(i-1); /* compensate the unnecessary increment in the while cycle */ } /* if (c=='m' . . . */ - if (nobjthack || (c != 'q')) return (n); @@ -1360,7 +1394,7 @@ modtranslate(struct line *deck, char *subname) (void) strcpy(model, ".model"); gotone = FALSE; for (c = deck; c; c = c->li_next) { /* iterate through model def . . . */ - if (prefix(model, c->li_line)) { + if (ciprefix(model, c->li_line)) { gotone = TRUE; t = c->li_line; @@ -1432,9 +1466,12 @@ static void devmodtranslate(struct line *deck, char *subname) { struct line *s; - char *buffer, *name, *next_name, *t, c; + char *buffer, *name, *t, c; wordlist *wlsub; bool found; +#ifdef XSPICE + char *next_name; +#endif /* XSPICE */ for (s = deck; s; s = s->li_next) { t = s->li_line; @@ -1640,7 +1677,7 @@ devmodtranslate(struct line *deck, char *subname) /* Changed gettok() to gettok_node() on 12.2.2003 by SDB to enable parsing lines like "S1 10 11 (80,51) SLATCH1" - which occurr in real Analog Devices SPICE models. + which occur in real Analog Devices SPICE models. */ case 'o': /* what is this element? -- SDB */ case 's': @@ -1745,7 +1782,7 @@ devmodtranslate(struct line *deck, char *subname) * else, but... Note that we pretend that dependent sources and mutual * inductors have more nodes than they really do... *----------------------------------------------------------------------*/ -int +static int inp_numnodes(char c) { if (isupper(c))