Fix white space and nested subckt bug

This commit is contained in:
stefanjones 2005-07-22 18:20:07 +00:00
parent a272966ea8
commit 2ff6713e89
3 changed files with 562 additions and 126 deletions

View File

@ -6,7 +6,23 @@ Author: 1985 Wayne A. Christopher
/* /*
* For dealing with spice input decks and command scripts * For dealing with spice input decks and command scripts
*/ */
/*
* SJB 21 April 2005
* Added support for end-of-line comments that begin with any of the following:
* ';' (for PSpice compatability)
* '$ ' (for HSpice compatability)
* '//' (like in c++ and as per the numparam code)
* '--' (as per the numparam code)
* Any following text to the end of the line is ignored.
* Note requirement for $ to be followed by a space. This is to avoid conflict
* with use in front of a variable.
* Comments on a contunuation line (i.e. line begining with '+') are allowed
* and are removed before lines are stitched.
* Lines that contain only an end-of-line comment with or withou leading white
* space are also allowed.
*/
/* /*
* SJB 22 May 2001 * SJB 22 May 2001
* Fixed memory leaks in inp_readall() when first(?) line of input begins with a '@'. * Fixed memory leaks in inp_readall() when first(?) line of input begins with a '@'.
@ -32,6 +48,13 @@ Author: 1985 Wayne A. Christopher
/* gtri - end - 12/12/90 */ /* gtri - end - 12/12/90 */
#endif #endif
/* SJB - Uncomment this line for debug tracing */
/*#define TRACE */
/* static declarations */
static char * readline(FILE *fd);
static void inp_stripcomments_deck(struct line *deck);
static void inp_stripcomments_line(char * s);
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* This routine reads a line (of arbitrary length), up to a '\n' or 'EOF' * * This routine reads a line (of arbitrary length), up to a '\n' or 'EOF' *
@ -56,7 +79,7 @@ readline(FILE *fd)
strptr = tmalloc(memlen); strptr = tmalloc(memlen);
memlen -= 1; /* Save constant -1's in while loop */ memlen -= 1; /* Save constant -1's in while loop */
while((c = getc(fd)) != EOF) { while((c = getc(fd)) != EOF) {
if (strlen == 0 && c == '\n') if (strlen == 0 && (c == '\n' || c == ' ')) /* Leading spaces away */
continue; continue;
strptr[strlen] = c; strptr[strlen] = c;
strlen++; strlen++;
@ -132,7 +155,7 @@ inp_readall(FILE *fp, struct line **data)
char *buffer, *s, *t, c; char *buffer, *s, *t, c;
/* segfault fix */ /* segfault fix */
char *copys=NULL; char *copys=NULL;
int line = 1; int line_number = 1; /* sjb - renamed to avoid confusion with struct line */
FILE *newfp; FILE *newfp;
/* Must set this to NULL or non-tilde includes segfault. -- Tim Molteno */ /* Must set this to NULL or non-tilde includes segfault. -- Tim Molteno */
@ -179,12 +202,12 @@ inp_readall(FILE *fp, struct line **data)
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf ("in inp_readall, just read %s . . .\n", buffer); printf ("in inp_readall, just read '%s' . . .\n", buffer);
#endif #endif
/* OK -- now we have loaded the next line into 'buffer'. Process it. */ /* OK -- now we have loaded the next line into 'buffer'. Process it. */
/* If input line is blank, ignore it & continue looping. */ /* If input line is blank, ignore it & continue looping. */
if ( (strcmp(buffer,"\n") == 0) if ( (strcmp(buffer,"\n") == 0)
|| (strcmp(buffer,"\r\n") == 0) ) { || (strcmp(buffer,"\r\n") == 0) ) {
continue; continue;
} }
@ -204,7 +227,7 @@ inp_readall(FILE *fp, struct line **data)
fprintf(cp_err, "Warning: premature EOF\n"); fprintf(cp_err, "Warning: premature EOF\n");
} }
*s = '\0'; /* Zap the newline. */ *s = '\0'; /* Zap the newline. */
if(*(s-1) == '\r') /* Zop the carriage return under windows */ if(*(s-1) == '\r') /* Zop the carriage return under windows */
*(s-1) = '\0'; *(s-1) = '\0';
@ -265,12 +288,13 @@ inp_readall(FILE *fp, struct line **data)
end->li_error = NULL; end->li_error = NULL;
end->li_actual = NULL; end->li_actual = NULL;
end->li_line = copy(buffer); end->li_line = copy(buffer);
end->li_linenum = line++; end->li_linenum = line_number++;
end->li_next = newcard; end->li_next = newcard;
/* Renumber the lines */ /* Renumber the lines */
for (end = newcard; end && end->li_next; end = end->li_next) for (end = newcard; end && end->li_next; end = end->li_next)
end->li_linenum = line++; end->li_linenum = line_number++;
end->li_linenum = line_number++; /* SJB - renumber the last line */
/* Fix the buffer up a bit. */ /* Fix the buffer up a bit. */
(void) strncpy(buffer + 1, "end of:", 7); (void) strncpy(buffer + 1, "end of:", 7);
@ -290,7 +314,7 @@ inp_readall(FILE *fp, struct line **data)
end->li_error = NULL; end->li_error = NULL;
end->li_actual = NULL; end->li_actual = NULL;
end->li_line = buffer; end->li_line = buffer;
end->li_linenum = line++; end->li_linenum = line_number++;
} }
if (!end) { /* No stuff here */ if (!end) { /* No stuff here */
@ -302,21 +326,28 @@ inp_readall(FILE *fp, struct line **data)
/* tfree(buffer); */ /* tfree(buffer); */
/* Now clean up li: remove comments & stitch together continuation lines. */ /* Now clean up li: remove comments & stitch together continuation lines. */
working = cc->li_next; /* cc points to head of deck. Start with the working = cc->li_next; /* cc points to head of deck. Start with the
next card. */ next card. */
/* sjb - strip or convert end-of-line comments.
This must be cone before stitching continuation lines.
If the line only contains an end-of-line comment then it is converted
into a normal comment with a '*' at the start. This will then get
stripped in the following code. */
inp_stripcomments_deck(working);
while (working) { while (working) {
for (s = working->li_line; (c = *s) && c <= ' '; s++) for (s = working->li_line; (c = *s) && c <= ' '; s++)
; ;
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In inp_readall, processing linked list element s = %s . . . \n", s); printf("In inp_readall, processing linked list element line = %d, s = %s . . . \n", working->li_linenum,s);
#endif #endif
switch (c) { switch (c) {
case '#': case '#':
case '$': case '$':
case '*': case '*':
case '\0': case '\0':
@ -399,3 +430,76 @@ inp_casefix(char *string)
return; return;
#endif #endif
} }
/* Strip all end-of-line comments from a deck */
static void
inp_stripcomments_deck(struct line *deck)
{
struct line *c=deck;
while( c!=NULL) {
inp_stripcomments_line(c->li_line);
c= c->li_next;
}
}
/* Strip end of line comment from a string and remove trailing white space
supports comments that begin with single characters ';'
or double characters '$ ' or '//' or '--'
If there is only white space before the end-of-line comment the
the whole line is converted to a normal comment line (i.e. one that
begins with a '*').
BUG: comment characters in side of string literals are not ignored. */
static void
inp_stripcomments_line(char * s)
{
char c = ' '; /* anything other than a comment character */
char * d = s;
if(*s=='\0') return; /* empty line */
/* look for comments */
while((c=*d)!='\0') {
d++;
if (*d==';') {
break;
} else if ((c=='$') && (*d==' ')) {
*d--; /* move d back to first comment character */
break;
} else if( (*d==c) && ((c=='/') || (c=='-'))) {
*d--; /* move d back to first comment character */
break;
}
}
/* d now points to the first comment character of the null at the string end */
/* check for special case of comment at start of line */
if(d==s) {
*s = '*'; /* turn into normal comment */
return;
}
if(d>s) {
d--;
/* d now points to character just before comment */
/* eat white space at end of line */
while(d>=s) {
if( (*d!=' ') && (*d!='\t' ) )
break;
d--;
}
d++;
/* d now points to the first white space character before the
end-of-line or end-of-line comment, or it points to the first
end-of-line comment character, or to the begining of the line */
}
/* Check for special case of comment at start of line
with or without preceeding white space */
if(d<=s) {
*s = '*'; /* turn the whole line into normal comment */
return;
}
*d='\0'; /* terminate line in new location */
}

View File

@ -2,8 +2,18 @@
Copyright 1990 Regents of the University of California. All rights reserved. Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
Modified: 2000 AlansFixes Modified: 2000 AlansFixes
$Id$
**********/ **********/
/*------------------------------------------------------------------------------
* 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
@ -51,6 +61,12 @@ Modified: 2000 AlansFixes
#include "subckt.h" #include "subckt.h"
#include "variable.h" #include "variable.h"
#ifdef NUMPARAMS
/* Uncomment to turn on tracing for the Numparam */
/*#define TRACE_NUMPARAMS*/
#include "numparam/numpaif.h"
#endif
/* ----- static declarations ----- */ /* ----- static declarations ----- */
static struct line * doit(struct line *deck); static struct line * doit(struct line *deck);
@ -63,6 +79,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
@ -81,19 +98,32 @@ 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;
} ; } ;
/* submod is the list of original model names, modnames is the
* list of translated names (i.e. after subckt expansion)
*/
static wordlist *modnames, *submod; static wordlist *modnames, *submod;
static struct subs *subs = NULL; static struct subs *subs = NULL;
static bool nobjthack = FALSE; static bool nobjthack = FALSE;
#ifdef NUMPARAMS
/* flag indicating use of the experimental numparams library */
static bool use_numparams = FALSE;
#endif /* NUMPARAMS */
static char start[32], sbend[32], invoke[32], model[32]; static char start[32], sbend[32], invoke[32], model[32];
#ifdef GLOBAL_NODE
static char node[128][128];
static int numgnode;
#endif /* GLOBAL_NODE */
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/* 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 */
@ -115,28 +145,127 @@ inp_subcktexpand(struct line *deck)
{ {
struct line *ll, *c; struct line *ll, *c;
char *s; char *s;
#ifdef NUMPARAMS
int ok;
#endif /* NUMPARAMS */
#ifdef GLOBAL_NODE
char *t;
int i;
#endif /* GLOBAL_NODE */
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))
(void) strcpy(model, ".model"); (void) strcpy(model, ".model");
(void) cp_getvar("nobjthack", VT_BOOL, (char *) &nobjthack); (void) cp_getvar("nobjthack", VT_BOOL, (char *) &nobjthack);
#ifdef NUMPARAMS
(void) cp_getvar("numparams", VT_BOOL, (char *) &use_numparams);
/* Let's do a few cleanup things first... Get rid of ( ) around node /* deck has .control sections already removed, but not comments */
if ( use_numparams ) {
#ifdef TRACE_NUMPARAMS
printf("Numparams is processing this deck:\n");
c=deck;
while( c!=NULL) {
printf("%3d:%s\n",c->li_linenum, c->li_line);
c= c->li_next;
}
#endif /* TRACE_NUMPARAMS */
ok = nupa_signal( NUPADECKCOPY, NULL);
c=deck;
while ( c != NULL) { /* first Numparam pass */
nupa_scan(c->li_line, c->li_linenum);
c= c->li_next;
}
c=deck;
while ( c != NULL) { /* first Numparam pass */
c->li_line = nupa_copy(c->li_line, c->li_linenum);
c= c->li_next;
}
#ifdef TRACE_NUMPARAMS
printf("Numparams transformed deck:\n");
c=deck;
while( c!=NULL) {
printf("%3d:%s\n",c->li_linenum, c->li_line);
c= c->li_next;
}
#endif /* TRACE_NUMPARAMS */
}
#endif /* NUMPARAMS */
/* 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 /* TRACE */
/* Added by H.Tanaka to find global nodes */
#ifdef GLOBAL_NODE
for(i=0;i<128;i++) strcpy(node[i],"");/* Clear global node holder */
for (c = deck; c; c = c->li_next) {
if (ciprefix(".global", c->li_line)) {
s = c->li_line;
txfree(gettok(&s));
numgnode=0;
while(*s) {
i=0;
t=s;
for (/*s*/; *s && !isspace(*s); s++) i++;
strncpy(node[numgnode],t,i);
while (isspace(*s)) s++;
numgnode++;
} /* node[] holds name of global node */
#ifdef TRACE
printf("***Global node option has been found.***\n");
for(i=0;i<numgnode;i++)
printf("***Global node no.%d is %s.***\n",i,node[i]);
printf("\n");
#endif /* TRACE */
c->li_line[0] = '*'; /* comment it out */
}/* if(ciprefix.. */
} /* for(c=deck.. */
#endif /* GLOBAL_NODE */
/* 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);
#endif #endif /* TRACE */
for (s = c->li_line; *s && (*s != '('); s++) /* Iterate charwise along line until ( is found */ for (s = c->li_line; *s && (*s != '('); s++) /* Iterate charwise along line until ( is found */
; ;
if (*s) { if (*s) {
@ -172,17 +301,47 @@ inp_subcktexpand(struct line *deck)
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In inp_subcktexpand, about to call doit.\n"); printf("In inp_subcktexpand, about to call doit.\n");
#endif #endif /* TRACE */
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)) {
fprintf(cp_err, "Error: unknown subckt: %s\n", fprintf(cp_err, "Error: unknown subckt: %s\n", c->li_line);
c->li_line); #ifdef NUMPARAMS
if ( use_numparams ) {
ok= ok && nupa_signal(NUPAEVALDONE, NULL);
}
#endif /* NUMPARAMS */
return NULL; return NULL;
} }
#ifdef NUMPARAMS
if ( use_numparams ) {
/* the NUMPARAM final line translation pass */
ok= ok && nupa_signal(NUPASUBDONE, NULL);
c= ll;
while (c != NULL) {
ok= ok && nupa_eval( c->li_line, c->li_linenum);
c= c->li_next;
}
#ifdef TRACE_NUMPARAMS
printf("Numparams converted deck:\n");
c=ll;
while( c!=NULL) {
printf("%3d:%s\n",c->li_linenum, c->li_line);
c= c->li_next;
}
#endif /* TRACE_NUMPARAMS */
ok= ok && nupa_signal(NUPAEVALDONE, NULL);
}
#endif /* NUMPARAMS */
return (ll); /* return the spliced deck. */ return (ll); /* return the spliced deck. */
} }
@ -202,34 +361,36 @@ static struct line *
doit(struct line *deck) doit(struct line *deck)
{ {
struct line *c, *last, *lc, *lcc; struct line *c, *last, *lc, *lcc;
#ifdef NUMPARAMS
struct line *savenext;
#endif /* NUMPARAMS */
struct subs *sss = (struct subs *) NULL, *ks; /* *sss and *ks temporarily hold decks to substitute */ struct subs *sss = (struct subs *) NULL, *ks; /* *sss and *ks temporarily hold decks to substitute */
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);
@ -244,7 +405,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 {
@ -252,7 +413,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 . . . */
@ -267,6 +428,9 @@ doit(struct line *deck)
sss = alloc(struct subs); sss = alloc(struct subs);
if (!lcc) /* if lcc is null, then no .ends was found. */ if (!lcc) /* if lcc is null, then no .ends was found. */
lcc = last; lcc = last;
#ifdef NUMPARAMS
if ( use_numparams==FALSE )
#endif /* NUMPARAMS */
lcc->li_next = NULL; /* shouldn't we free some memory here????? */ lcc->li_next = NULL; /* shouldn't we free some memory here????? */
/* At this point, last points to the .subckt card, and lcc points to the .ends card */ /* At this point, last points to the .subckt card, and lcc points to the .ends card */
@ -297,8 +461,12 @@ doit(struct line *deck)
subs = sss; /* Now that sss is built, assign it to subs */ subs = sss; /* Now that sss is built, assign it to subs */
last = c->li_next; last = c->li_next;
lcc = subs->su_def; lcc = subs->su_def;
} #ifdef NUMPARAMS
/*gp */ c->li_next = NULL; /* Numparam needs line c */
c->li_line[0] = '*'; /* comment it out */
#endif /* NUMPARAMS */
}
else { /* line is neither .ends nor .subckt. */ else { /* line is neither .ends nor .subckt. */
/* make lc point to this card, and advance last to next card. */ /* make lc point to this card, and advance last to next card. */
lc = last; lc = last;
@ -323,25 +491,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;
@ -406,7 +560,7 @@ doit(struct line *deck)
/* Change the names of .models found in .subckts . . . */ /* Change the names of .models found in .subckts . . . */
if (modtranslate(lcc, scname)) /* this translates the model name in the .model line */ if (modtranslate(lcc, scname)) /* this translates the model name in the .model line */
devmodtranslate(lcc, scname); /* This translates the model name on all components in the deck */ devmodtranslate(lcc, scname); /* This translates the model name on all components in the deck */
s = sss->su_args; s = sss->su_args;
txfree(gettok(&t)); /* Throw out the subcircuit refdes */ txfree(gettok(&t)); /* Throw out the subcircuit refdes */
@ -419,13 +573,31 @@ doit(struct line *deck)
tfree(subname); tfree(subname);
/* Now splice the decks together. */ /* Now splice the decks together. */
#ifdef NUMPARAMS
savenext = c->li_next;
if ( use_numparams==FALSE ) {
/* old style: c will drop a dangling pointer: memory leak */
if (lc)
lc->li_next = lcc;
else
deck = lcc;
} else {
/* ifdef NUMPARAMS, keep the invoke line as a comment */
c->li_next = lcc;
c->li_line[0] = '*'; /* comment it out */
}
#else
if (lc) if (lc)
lc->li_next = lcc; lc->li_next = lcc;
else else
deck = lcc; deck = lcc;
#endif /* NUMPARAMS */
while (lcc->li_next != NULL) while (lcc->li_next != NULL)
lcc = lcc->li_next; lcc = lcc->li_next;
lcc->li_next = c->li_next; lcc->li_next = c->li_next;
#ifdef NUMPARAMS
lcc->li_next = savenext;
#endif /* NUMPARAMS */
c = lcc->li_next; c = lcc->li_next;
lc = lcc; lc = lcc;
tfree(tofree); tfree(tofree);
@ -444,6 +616,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( ) */
@ -500,7 +685,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
{ {
struct line *c; struct line *c;
char *buffer, *next_name, dev_type, *name, *s, *t, ch, *nametofree; char *buffer, *next_name, dev_type, *name, *s, *t, ch, *nametofree;
int nnodes, i, dim; int nnodes, i, dim, blen;
int rtn=0; int rtn=0;
/* settrans builds the table holding the translated netnames. */ /* settrans builds the table holding the translated netnames. */
@ -534,7 +719,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
case '*': case '*':
case '.': case '.':
/* Just a pointer to the line into s and then break */ /* Just a pointer to the line into s and then break */
buffer = tmalloc(2000); /* XXXXX */ buffer = tmalloc(2000+strlen(c->li_line)); /* DW,VA */
s = c->li_line; s = c->li_line;
break; break;
@ -549,13 +734,13 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* translate the instance name according to normal rules */ /* translate the instance name according to normal rules */
buffer = tmalloc(2000); /* XXXXX */
s = c->li_line; s = c->li_line;
name = MIFgettok(&s); name = MIFgettok(&s);
/* maschmann /* maschmann
sprintf(buffer, "%s:%s ", name, scname); */ sprintf(buffer, "%s:%s ", name, scname); */
buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
sprintf(buffer, "a:%s:%s ", scname, name+1 ); sprintf(buffer, "a:%s:%s ", scname, name+1 );
@ -586,19 +771,25 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
case '[': case '[':
case ']': case ']':
case '~': case '~':
sprintf(buffer + strlen(buffer), "%s ", name); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(name)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", name);
break; break;
case '%': case '%':
sprintf(buffer + strlen(buffer), "%%"); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+2)*sizeof(char));
sprintf(buffer + blen, "%%");
/* don't translate the port type identifier */ /* don't translate the port type identifier */
name = next_name; name = next_name;
next_name = MIFgettok(&s); next_name = MIFgettok(&s);
sprintf(buffer + strlen(buffer), "%s ", name); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(name)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", name);
break; break;
default: default:
@ -606,16 +797,26 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* must be a node name at this point, so translate it */ /* must be a node name at this point, so translate it */
t = gettrans(name); t = gettrans(name);
if (t)
sprintf(buffer + strlen(buffer), "%s ", t); if (t) {
else blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(t)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", t);
} else {
/* maschmann: changed order /* maschmann: changed order
sprintf(buffer + strlen(buffer), "%s:%s ", name, scname); */ sprintf(buffer + strlen(buffer), "%s:%s ", name, scname); */
if(name[0]=='v' || name[0]=='V') sprintf(buffer + strlen(buffer), "v:%s:%s ", scname, name+1); if(name[0]=='v' || name[0]=='V') {
else sprintf(buffer + strlen(buffer), "%s:%s ", scname, name); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+5)*sizeof(char));
sprintf(buffer + blen, "v:%s:%s ", scname, name+1);
} else {
blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+3)*sizeof(char));
sprintf(buffer + blen, "%s:%s ", scname, name);
}
}
break; break;
} /* switch */ } /* switch */
} /* while */ } /* while */
@ -623,9 +824,11 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* copy in the last token, which is the model name */ /* copy in the last token, which is the model name */
if(name) if(name) {
sprintf(buffer + strlen(buffer), "%s ", name); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(name)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", name);
}
/* Set s to null string for compatibility with code */ /* Set s to null string for compatibility with code */
/* after switch statement */ /* after switch statement */
@ -660,17 +863,19 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
* and stick the translated name into buffer. * and stick the translated name into buffer.
*/ */
ch = *name; /* ch identifies the type of component */ ch = *name; /* ch identifies the type of component */
buffer = tmalloc(2000); /* XXXXX */
name++; name++;
if (*name == ':') if (*name == ':')
name++; /* now name point to the rest of the refdes */ name++; /* now name point to the rest of the refdes */
if (*name) if (*name) {
(void) sprintf(buffer, "%c:%s:%s ", ch, scname, /* F:subcircuitname:refdesname */ buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
sprintf(buffer, "%c:%s:%s ", ch, scname, /* F:subcircuitname:refdesname */
name); name);
else } else {
(void) sprintf(buffer, "%c:%s ", ch, scname); /* F:subcircuitname */ buffer = (char *)tmalloc((strlen(scname)+4)*sizeof(char));
sprintf(buffer, "%c:%s ", ch, scname); /* F:subcircuitname */
}
tfree(t); tfree(t);
@ -689,13 +894,16 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
t = gettrans(name); t = gettrans(name);
if (t) { /* the netname was used during the invocation; print it into the buffer */ if (t) { /* the netname was used during the invocation; print it into the buffer */
(void) sprintf(buffer + strlen(buffer), "%s ", t); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(t)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", t);
} }
else { /* net netname was not used during the invocation; place a else { /* net netname was not used during the invocation; place a
* translated name into the buffer. * translated name into the buffer.
*/ */
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"%s:%s ", scname, name); buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+3)*sizeof(char));
sprintf(buffer + blen, "%s:%s ", scname, name);
} }
tfree(name); tfree(name);
} /* while (nnodes-- . . . . */ } /* while (nnodes-- . . . . */
@ -734,8 +942,9 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
} }
/* Write POLY(dim) into buffer */ /* Write POLY(dim) into buffer */
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"POLY( %d ) ", dim); buffer = (char *)trealloc(buffer, (blen+17)*sizeof(char));
sprintf(buffer + blen, "POLY( %d ) ", dim);
} /* if ( (strcmp(next_name, "POLY") == 0) . . . */ } /* if ( (strcmp(next_name, "POLY") == 0) . . . */
@ -768,9 +977,10 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
ch = *name; /* ch is the first char of the token. */ ch = *name; /* ch is the first char of the token. */
name++; name++;
if (*name == ':') if (*name == ':')
name++; /* name now points to the remainder of the token */ name++; /* name now points to the remainder of the token */
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"%c:%s:%s ", ch, scname, name); buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+5)*sizeof(char));
sprintf(buffer + blen, "%c:%s:%s ", ch, scname, name);
/* From Vsense and Urefdes creates V:Urefdes:sense */ /* From Vsense and Urefdes creates V:Urefdes:sense */
} }
else { /* Handle netname */ else { /* Handle netname */
@ -784,13 +994,16 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
t = gettrans(name); t = gettrans(name);
if (t) { /* the netname was used during the invocation; print it into the buffer */ if (t) { /* the netname was used during the invocation; print it into the buffer */
(void) sprintf(buffer + strlen(buffer), "%s ", t); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(t)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", t);
} }
else { /* net netname was not used during the invocation; place a else { /* net netname was not used during the invocation; place a
* translated name into the buffer. * translated name into the buffer.
*/ */
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"%s:%s ", scname, name); buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+3)*sizeof(char));
sprintf(buffer + blen, "%s:%s ", scname, name);
/* From netname and Urefdes creates Urefdes:netname */ /* From netname and Urefdes creates Urefdes:netname */
} }
} }
@ -798,7 +1011,9 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
} /* while (nnodes--. . . . */ } /* while (nnodes--. . . . */
/* Now write out remainder of line (polynomial coeffs) */ /* Now write out remainder of line (polynomial coeffs) */
finishLine(buffer + strlen(buffer), s, scname); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(s)+strlen(scname)+1000)*sizeof(char));
finishLine(buffer + blen, s, scname);
s = ""; s = "";
break; break;
@ -818,25 +1033,26 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
* and stick the translated name into buffer. * and stick the translated name into buffer.
*/ */
ch = *name; ch = *name;
buffer = tmalloc(2000); /* XXXXX */
name++; name++;
if (*name == ':') if (*name == ':')
name++; name++;
if (*name) if (*name) {
(void) sprintf(buffer, "%c:%s:%s ", ch, scname, buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
name); sprintf(buffer, "%c:%s:%s ", ch, scname, name);
else } else {
(void) sprintf(buffer, "%c:%s ", ch, scname); buffer = (char *)tmalloc((strlen(scname)+4)*sizeof(char));
sprintf(buffer, "%c:%s ", ch, scname);
}
tfree(nametofree); tfree(nametofree);
/* 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;
@ -846,19 +1062,22 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
t = gettrans(name); t = gettrans(name);
if (t) { /* the netname was used during the invocation; print it into the buffer */ if (t) { /* the netname was used during the invocation; print it into the buffer */
(void) sprintf(buffer + strlen(buffer), "%s ", t); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(t)+2)*sizeof(char));
sprintf(buffer + blen, "%s ", t);
} }
else { /* net netname was not used during the invocation; place a else { /* net netname was not used during the invocation; place a
* translated name into the buffer. * translated name into the buffer.
*/ */
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"%s:%s ", scname, name); buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+3)*sizeof(char));
sprintf(buffer + blen, "%s:%s ", scname, name);
} }
free(name); tfree(name);
} /* 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);
@ -874,29 +1093,35 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
if (*name == ':') if (*name == ':')
name++; name++;
if (*name) if (*name) {
(void) sprintf(buffer + strlen(buffer), blen = strlen(buffer);
"%c:%s:%s ", ch, scname, name); buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+5)*sizeof(char));
else sprintf(buffer + blen, "%c:%s:%s ", ch, scname, name);
(void) sprintf(buffer + strlen(buffer), } else {
"%c:%s ", ch, scname); blen = strlen(buffer);
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+4)*sizeof(char));
sprintf(buffer + blen, "%c:%s ", ch, scname);
}
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
* i(something)... * i(something)...
*/ */
finishLine(buffer + strlen(buffer), s, scname); blen = strlen(buffer);
s = ""; buffer = (char *)trealloc(buffer, (blen+strlen(s)+strlen(scname)+1000)*sizeof(char));
finishLine(buffer + blen, s, scname);
s = "";
} /* switch(c->li_line . . . . */ } /* switch(c->li_line . . . . */
(void) strcat(buffer, s); blen = strlen(buffer);
tfree(c->li_line); buffer = (char *)trealloc(buffer, (blen+strlen(s)+1)*sizeof(char));
c->li_line = copy(buffer); strcat(buffer, s);
tfree(c->li_line);
c->li_line = copy(buffer);
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
@ -976,7 +1201,8 @@ finishLine(char *dst, char *src, char *scname)
/* /*
* *
*/ */
if (buf[0] == 'v' || buf[0] == 'V') { if ((which == 'i' || which == 'I') &&
(buf[0] == 'v' || buf[0] == 'V')) {
*dst++ = buf[0]; *dst++ = buf[0];
*dst++ = ':'; *dst++ = ':';
i = 1; i = 1;
@ -1016,6 +1242,7 @@ finishLine(char *dst, char *src, char *scname)
} }
} }
*dst = '\0'; /* va, append in each case '\0' */
return; return;
} }
@ -1070,6 +1297,12 @@ gettrans(char *name)
/* gtri - end */ /* gtri - end */
#endif #endif
/* Added by H.Tanaka to translate global nodes */
#ifdef GLOBAL_NODE
for(i=0;i<numgnode;i++)
if(eq(node[i],name)) return (name);
#endif /* GLOBAL_NODE */
if (eq(name, "0")) if (eq(name, "0"))
return (name); return (name);
for (i = 0; table[i].t_old; i++) for (i = 0; table[i].t_old; i++)
@ -1124,7 +1357,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 */
@ -1135,7 +1368,7 @@ numnodes(char *name)
i = 0; i = 0;
s = buf; s = buf;
gotit = 0; gotit = 0;
txfree(gettok(&s)); /* Skip component name */ txfree(gettok(&s)); /* Skip component name */
while ((i < n) && (*s) && !gotit) { while ((i < n) && (*s) && !gotit) {
t = gettok_node(&s); /* get nodenames . . . */ t = gettok_node(&s); /* get nodenames . . . */
for (wl = modnames; wl; wl = wl->wl_next) for (wl = modnames; wl; wl = wl->wl_next)
@ -1146,17 +1379,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);
@ -1222,7 +1454,7 @@ numdevs(char *s)
} }
/*----------------------------------------------------------------------* /*----------------------------------------------------------------------*
* modtranslate -- translates .model liness found in subckt definitions. * modtranslate -- translates .model lines found in subckt definitions.
* Calling arguments are: * Calling arguments are:
* *deck = pointer to the .subckt definition (linked list) * *deck = pointer to the .subckt definition (linked list)
* *subname = pointer to the subcircuit name used at the subcircuit invocation (string) * *subname = pointer to the subcircuit name used at the subcircuit invocation (string)
@ -1240,26 +1472,47 @@ 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;
#ifdef TRACE
/* SDB debug statement */
printf("In modtranslate, translating line %s\n", t);
#endif
name = gettok(&t); /* at this point, name = .model */ name = gettok(&t); /* at this point, name = .model */
buffer = tmalloc(strlen(name) + strlen(t) + buffer = tmalloc(strlen(name) + strlen(t) +
strlen(subname) + 4); strlen(subname) + 4);
(void) sprintf(buffer, "%s ",name); /* at this point, buffer = ".model " */ (void) sprintf(buffer, "%s ",name); /* at this point, buffer = ".model " */
tfree(name); tfree(name);
name = gettok(&t); /* name now holds model name */ name = gettok(&t); /* name now holds model name */
wlsub = alloc(struct wordlist); wlsub = alloc(struct wordlist);
wlsub->wl_next = submod; wlsub->wl_next = submod;
if (submod) if (submod)
submod->wl_prev = wlsub; submod->wl_prev = wlsub;
/* here's where we insert the model name into the model name list */
submod = wlsub; submod = wlsub;
wlsub->wl_word = name; wlsub->wl_word = name;
#ifdef TRACE
/* SDB debug statement */
printf("In modtranslate, sticking model name %s into submod\n", wlsub->wl_word);
#endif
/* now stick the new model name into the model line. */
(void) sprintf(buffer + strlen(buffer), "%s:%s ", (void) sprintf(buffer + strlen(buffer), "%s:%s ",
subname, name); /* buffer = "model subname:modelname " */ subname, name); /* buffer = "model subname:modelname " */
(void) strcat(buffer, t); (void) strcat(buffer, t);
tfree(c->li_line); tfree(c->li_line);
c->li_line = buffer; c->li_line = buffer;
#ifdef TRACE
/* SDB debug statement */
printf("In modtranslate, translated line= %s\n", c->li_line);
#endif
/* this looks like it tries to stick the translated model name into the list of model names */
t = c->li_line; t = c->li_line;
txfree(gettok(&t)); txfree(gettok(&t));
wl = alloc(struct wordlist); wl = alloc(struct wordlist);
@ -1268,6 +1521,12 @@ modtranslate(struct line *deck, char *subname)
modnames->wl_prev = wl; modnames->wl_prev = wl;
modnames = wl; modnames = wl;
wl->wl_word = gettok(&t); wl->wl_word = gettok(&t);
#ifdef TRACE
/* SDB debug statement */
printf("In modtranslate, sticking model name %s into modnames\n", wl->wl_word);
#endif
} }
} }
return(gotone); return(gotone);
@ -1288,6 +1547,9 @@ devmodtranslate(struct line *deck, char *subname)
char *buffer, *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;
@ -1304,6 +1566,78 @@ devmodtranslate(struct line *deck, char *subname)
switch (c) { switch (c) {
#ifdef XSPICE
case 'a':
/* Code for codemodels (dev prefix "A") added by SDB on 6.10.2004.
* The algorithm is simple. We don't know how many nodes or sources are attached,
* but the name of the model is always last. Therefore, just iterate through all
* tokens until the last one is reached. Then translate it.
*/
#ifdef TRACE
/* SDB debug statement */
printf("In devmodtranslate, found codemodel, line= %s\n", t);
#endif
/* first do refdes. */
name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name);
tfree(name);
/* now do remainder of line. */
next_name = gettok(&t);
while(1) {
name = next_name;
next_name = gettok(&t);
if(next_name == NULL) {
/* if next_name is NULL, we are at the line end.
* name holds the model name. Therefore, break */
break;
} else {
/* next_name holds something. Write name into the buffer and continue. */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
}
} /* while */
/* Now, is name a subcircuit model?
* Note that we compare against submod = untranslated names of models.
*/
for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) {
#ifdef TRACE
/* SDB debug statement */
printf("In devmodtranslate, comparing model name against submod list item %s\n", wlsub->wl_word );
#endif
if (eq(name, wlsub->wl_word)) {
(void) sprintf(buffer + strlen(buffer), "%s:%s ",
subname, name);
found = TRUE;
break;
}
}
if (!found)
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
#ifdef TRACE
/* SDB debug statement */
printf("In devmodtranslate, translated codemodel line= %s\n", buffer);
#endif
(void) strcat(buffer, t);
tfree(s->li_line);
s->li_line = buffer;
break;
#endif /* XSPICE */
case 'r': case 'r':
case 'c': case 'c':
name = gettok(&t); /* get refdes */ name = gettok(&t); /* get refdes */
@ -1421,7 +1755,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':
@ -1526,7 +1860,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))
@ -1552,6 +1886,7 @@ inp_numnodes(char c)
case 'l': return (2); case 'l': return (2);
case 'm': return (7); /* This means that 7 is the maximun number of nodes */ case 'm': return (7); /* This means that 7 is the maximun number of nodes */
case 'o': return (4); case 'o': return (4);
case 'p': return (0);
case 'q': return (4); case 'q': return (4);
case 'r': return (2); case 'r': return (2);
case 's': return (4); case 's': return (4);
@ -1560,6 +1895,7 @@ inp_numnodes(char c)
case 'v': return (2); case 'v': return (2);
/* change 3 to 2 here to fix w bug, NCF 1/31/95 */ /* change 3 to 2 here to fix w bug, NCF 1/31/95 */
case 'w': return (2); case 'w': return (2);
case 'y': return (2);
case 'z': return (3); case 'z': return (3);
default: default:
@ -1567,11 +1903,3 @@ inp_numnodes(char c)
return (2); return (2);
} }
} }

View File

@ -27,6 +27,9 @@ namespace eval spicewish {
} }
#eval spice::bltplot $l #eval spice::bltplot $l
eval spice::bltplot $args eval spice::bltplot $args
return "${::spicewish::viewer::wNames}[expr $::spicewish::viewer::viewCnt -1]"
} }
proc gui { } { proc gui { } {
@ -127,4 +130,5 @@ proc spice_gr_Plot { args } {
set ::spicewish::viewer::bltplotCnt $viewerCnt set ::spicewish::viewer::bltplotCnt $viewerCnt
} }
} }
} }