Fixed a bug in model name translation.

This commit is contained in:
pnenzi 2005-04-04 10:38:45 +00:00
parent bccd01f403
commit 8cc46680ab
1 changed files with 84 additions and 47 deletions

View File

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