Browse Source

Fixed a bug in model name translation.

pre-master-46
pnenzi 21 years ago
parent
commit
8cc46680ab
  1. 131
      src/frontend/subckt.c

131
src/frontend/subckt.c

@ -4,6 +4,15 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
Modified: 2000 AlansFixes 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 * 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 * 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 char * nupa_copy(char *s, int linenum);
extern int nupa_eval(char *s, int linenum); extern int nupa_eval(char *s, int linenum);
extern int nupa_signal(int sig, char *info); 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 #endif
/* ----- static declarations ----- */ /* ----- static declarations ----- */
static struct line * doit(struct line *deck); static struct line * doit(struct line *deck);
static int translate(struct line *deck, char *formal, char *actual, char *scname, 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 int numdevs(char *s);
static bool modtranslate(struct line *deck, char *subname); static bool modtranslate(struct line *deck, char *subname);
static void devmodtranslate(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 * table is used in settrans and gettrans -- it holds the netnames used
@ -99,7 +101,7 @@ static struct tab {
*--------------------------------------------------------------------*/ *--------------------------------------------------------------------*/
struct subs { struct subs {
char *su_name; /* The .subckt name. */ 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; int su_numargs;
struct line *su_def; /* Pointer to the .subckt definition. */ struct line *su_def; /* Pointer to the .subckt definition. */
struct subs *su_next; struct subs *su_next;
@ -116,6 +118,10 @@ static bool nobjthack = FALSE;
static char start[32], sbend[32], invoke[32], model[32]; 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 */ /* inp_subcktexpand is the top level function which translates */
/* .subckts into mainlined code. Note that there are two things */ /* .subckts into mainlined code. Note that there are two things */
@ -140,13 +146,15 @@ inp_subcktexpand(struct line *deck)
#ifdef NUMPARAMS #ifdef NUMPARAMS
int ok; int ok;
#endif #endif
wordlist *wl;
modnames = NULL;
if(!cp_getvar("substart", VT_STRING, start)) if(!cp_getvar("substart", VT_STRING, start))
(void) strcpy(start, ".subckt"); (void) strcpy(start, ".subckt");
if(!cp_getvar("subend", VT_STRING, sbend)) if(!cp_getvar("subend", VT_STRING, sbend))
(void) strcpy(sbend, ".ends"); (void) strcpy(sbend, ".ends");
if(!cp_getvar("subinvoke", VT_STRING, invoke)) if(!cp_getvar("subinvoke", VT_STRING, invoke))
(void) strcpy(invoke, "X");
(void) strcpy(invoke, "x");
if(!cp_getvar("modelcard", VT_STRING, model)) if(!cp_getvar("modelcard", VT_STRING, model))
(void) strcpy(model, ".model"); (void) strcpy(model, ".model");
if(!cp_getvar("modelline", VT_STRING, model)) if(!cp_getvar("modelline", VT_STRING, model))
@ -165,11 +173,36 @@ inp_subcktexpand(struct line *deck)
} }
#endif #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... * lists...
*/ */
for (c = deck; c; c = c->li_next) { /* iterate on lines in deck */ 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 #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In inp_subcktexpand, found a .subckt: %s\n", c->li_line); printf("In inp_subcktexpand, found a .subckt: %s\n", c->li_line);
@ -212,6 +245,12 @@ inp_subcktexpand(struct line *deck)
#endif #endif
ll = doit(deck); 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... */ /* Now check to see if there are still subckt instances undefined... */
if (ll!=NULL) for (c = ll; c; c = c->li_next) if (ll!=NULL) for (c = ll; c; c = c->li_next)
if (ciprefix(invoke, c->li_line)) { if (ciprefix(invoke, c->li_line)) {
@ -258,30 +297,29 @@ doit(struct line *deck)
char *s, *t, *scname, *subname; char *s, *t, *scname, *subname;
int nest, numpasses = MAXNEST, i; int nest, numpasses = MAXNEST, i;
bool gotone; bool gotone;
wordlist *wl;
wordlist *tmodnames = modnames; wordlist *tmodnames = modnames;
wordlist *tsubmod = submod; wordlist *tsubmod = submod;
struct subs *ts = subs; struct subs *ts = subs;
int error; int error;
/* Save all the old stuff... */ /* Save all the old stuff... */
modnames = NULL;
subs = NULL; subs = NULL;
submod = NULL; submod = NULL;
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In doit, about to start first pass through deck.\n"); 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 #endif
/* First pass: xtract all the .subckts and stick pointers to them into sss. */ /* First pass: xtract all the .subckts and stick pointers to them into sss. */
for (last = deck, lc = NULL; last; ) { 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, fprintf(cp_err, "Error: misplaced %s line: %s\n", sbend,
last->li_line); last->li_line);
return (NULL); 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 */ if (last->li_next == NULL) { /* first check that next line is non null */
fprintf(cp_err, "Error: no %s line.\n", sbend); fprintf(cp_err, "Error: no %s line.\n", sbend);
return (NULL); return (NULL);
@ -296,7 +334,7 @@ doit(struct line *deck)
* .subckt card, and lcc will point to the location of the .ends card. * .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) { 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) if (!nest)
break; /* nest = 0 means we have balanced .subckt and .ends */ break; /* nest = 0 means we have balanced .subckt and .ends */
else { else {
@ -304,7 +342,7 @@ doit(struct line *deck)
lcc = c; /* (lcc points to the position of the .ends) */ lcc = c; /* (lcc points to the position of the .ends) */
continue; /* then continue looping */ 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++; nest++;
lcc = c; /* lcc points to current pos of c */ lcc = c; /* lcc points to current pos of c */
} /* for (nest = 0 . . . */ } /* for (nest = 0 . . . */
@ -382,25 +420,11 @@ doit(struct line *deck)
return (NULL); return (NULL);
subs = ks; /* ks has held pointer to start of subcircuits list. */ 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 #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In doit, about to start second pass through deck.\n"); 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 #endif
error = 0; error = 0;
@ -521,6 +545,19 @@ doit(struct line *deck)
return (NULL); 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) if (error)
return NULL; /* error message already reported; should free( ) */ 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. */ /* Next iterate over all nodes (netnames) found and translate them. */
nnodes = numnodes(c->li_line); nnodes = numnodes(c->li_line);
while (nnodes-- > 0) { while (nnodes-- > 0) {
name = gettok_node(&s); name = gettok_node(&s);
if (name == NULL) {
if (name == NULL ) {
fprintf(cp_err, "Error: too few nodes: %s\n", fprintf(cp_err, "Error: too few nodes: %s\n",
c->li_line); c->li_line);
goto quit; goto quit;
@ -970,7 +1006,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
} /* while (nnodes-- . . . . */ } /* while (nnodes-- . . . . */
/* Now translate any devices (i.e. controlling sources). /* 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 . . . . * source devices above . . . .
*/ */
nnodes = numdevs(c->li_line); nnodes = numdevs(c->li_line);
@ -998,7 +1034,6 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
tfree(t); tfree(t);
} /* while (nnodes--. . . . */ } /* while (nnodes--. . . . */
/* Now we finish off the line. For most components (R, C, etc), /* Now we finish off the line. For most components (R, C, etc),
* this involves adding the component value to the buffer. * this involves adding the component value to the buffer.
* We also scan through the line for v(something) and * 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 */ /* Added this code for variable number of nodes on BSIM3SOI devices */
/* The consequence of this code is that the value returned by the */ /* 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. */ /* for a given device type. */
/* Paolo Nenzi Jan-2001 */ /* Paolo Nenzi Jan-2001 */
@ -1266,17 +1301,16 @@ numnodes(char *name)
} /* while . . . . */ } /* while . . . . */
/* Note: node checks must be done on #_of_node-1 because the */ /* 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! */ /* recognized. This code may be better! */
if (i < 5) { if (i < 5) {
fprintf(cp_err, "Error: too few nodes for MOS: %s\n", name); fprintf(cp_err, "Error: too few nodes for MOS: %s\n", name);
return(0); 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 (c=='m' . . . */
if (nobjthack || (c != 'q')) if (nobjthack || (c != 'q'))
return (n); return (n);
@ -1360,7 +1394,7 @@ modtranslate(struct line *deck, char *subname)
(void) strcpy(model, ".model"); (void) strcpy(model, ".model");
gotone = FALSE; gotone = FALSE;
for (c = deck; c; c = c->li_next) { /* iterate through model def . . . */ 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; gotone = TRUE;
t = c->li_line; t = c->li_line;
@ -1432,9 +1466,12 @@ static void
devmodtranslate(struct line *deck, char *subname) devmodtranslate(struct line *deck, char *subname)
{ {
struct line *s; struct line *s;
char *buffer, *name, *next_name, *t, c;
char *buffer, *name, *t, c;
wordlist *wlsub; wordlist *wlsub;
bool found; bool found;
#ifdef XSPICE
char *next_name;
#endif /* XSPICE */
for (s = deck; s; s = s->li_next) { for (s = deck; s; s = s->li_next) {
t = s->li_line; 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 /* Changed gettok() to gettok_node() on 12.2.2003 by SDB
to enable parsing lines like "S1 10 11 (80,51) SLATCH1" 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 'o': /* what is this element? -- SDB */
case 's': case 's':
@ -1745,7 +1782,7 @@ devmodtranslate(struct line *deck, char *subname)
* else, but... Note that we pretend that dependent sources and mutual * else, but... Note that we pretend that dependent sources and mutual
* inductors have more nodes than they really do... * inductors have more nodes than they really do...
*----------------------------------------------------------------------*/ *----------------------------------------------------------------------*/
int
static int
inp_numnodes(char c) inp_numnodes(char c)
{ {
if (isupper(c)) if (isupper(c))

Loading…
Cancel
Save