Fix white space and nested subckt bug
This commit is contained in:
parent
a272966ea8
commit
2ff6713e89
|
|
@ -6,7 +6,23 @@ Author: 1985 Wayne A. Christopher
|
|||
/*
|
||||
* 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
|
||||
* 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 */
|
||||
#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' *
|
||||
|
|
@ -56,7 +79,7 @@ readline(FILE *fd)
|
|||
strptr = tmalloc(memlen);
|
||||
memlen -= 1; /* Save constant -1's in while loop */
|
||||
while((c = getc(fd)) != EOF) {
|
||||
if (strlen == 0 && c == '\n')
|
||||
if (strlen == 0 && (c == '\n' || c == ' ')) /* Leading spaces away */
|
||||
continue;
|
||||
strptr[strlen] = c;
|
||||
strlen++;
|
||||
|
|
@ -132,7 +155,7 @@ inp_readall(FILE *fp, struct line **data)
|
|||
char *buffer, *s, *t, c;
|
||||
/* segfault fix */
|
||||
char *copys=NULL;
|
||||
int line = 1;
|
||||
int line_number = 1; /* sjb - renamed to avoid confusion with struct line */
|
||||
FILE *newfp;
|
||||
|
||||
/* 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
|
||||
/* SDB debug statement */
|
||||
printf ("in inp_readall, just read %s . . .\n", buffer);
|
||||
printf ("in inp_readall, just read '%s' . . .\n", buffer);
|
||||
#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 ( (strcmp(buffer,"\n") == 0)
|
||||
if ( (strcmp(buffer,"\n") == 0)
|
||||
|| (strcmp(buffer,"\r\n") == 0) ) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -204,7 +227,7 @@ inp_readall(FILE *fp, struct line **data)
|
|||
fprintf(cp_err, "Warning: premature EOF\n");
|
||||
}
|
||||
*s = '\0'; /* Zap the newline. */
|
||||
|
||||
|
||||
if(*(s-1) == '\r') /* Zop the carriage return under windows */
|
||||
*(s-1) = '\0';
|
||||
|
||||
|
|
@ -265,12 +288,13 @@ inp_readall(FILE *fp, struct line **data)
|
|||
end->li_error = NULL;
|
||||
end->li_actual = NULL;
|
||||
end->li_line = copy(buffer);
|
||||
end->li_linenum = line++;
|
||||
end->li_linenum = line_number++;
|
||||
end->li_next = newcard;
|
||||
|
||||
/* Renumber the lines */
|
||||
for (end = newcard; end && end->li_next; end = end->li_next)
|
||||
end->li_linenum = line++;
|
||||
for (end = newcard; end && end->li_next; end = end->li_next)
|
||||
end->li_linenum = line_number++;
|
||||
end->li_linenum = line_number++; /* SJB - renumber the last line */
|
||||
|
||||
/* Fix the buffer up a bit. */
|
||||
(void) strncpy(buffer + 1, "end of:", 7);
|
||||
|
|
@ -290,7 +314,7 @@ inp_readall(FILE *fp, struct line **data)
|
|||
end->li_error = NULL;
|
||||
end->li_actual = NULL;
|
||||
end->li_line = buffer;
|
||||
end->li_linenum = line++;
|
||||
end->li_linenum = line_number++;
|
||||
}
|
||||
|
||||
if (!end) { /* No stuff here */
|
||||
|
|
@ -302,21 +326,28 @@ inp_readall(FILE *fp, struct line **data)
|
|||
/* 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
|
||||
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) {
|
||||
for (s = working->li_line; (c = *s) && c <= ' '; s++)
|
||||
;
|
||||
|
||||
#ifdef TRACE
|
||||
/* 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
|
||||
|
||||
switch (c) {
|
||||
case '#':
|
||||
case '#':
|
||||
case '$':
|
||||
case '*':
|
||||
case '\0':
|
||||
|
|
@ -399,3 +430,76 @@ inp_casefix(char *string)
|
|||
return;
|
||||
#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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,18 @@
|
|||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||
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
|
||||
* properly. This is particularly important for dependent sources, whose argument
|
||||
|
|
@ -51,6 +61,12 @@ Modified: 2000 AlansFixes
|
|||
#include "subckt.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 struct line * doit(struct line *deck);
|
||||
|
|
@ -63,6 +79,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
|
||||
|
|
@ -81,19 +98,32 @@ 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;
|
||||
} ;
|
||||
|
||||
|
||||
/* 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 struct subs *subs = NULL;
|
||||
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];
|
||||
|
||||
#ifdef GLOBAL_NODE
|
||||
static char node[128][128];
|
||||
static int numgnode;
|
||||
#endif /* GLOBAL_NODE */
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* inp_subcktexpand is the top level function which translates */
|
||||
/* .subckts into mainlined code. Note that there are two things */
|
||||
|
|
@ -115,28 +145,127 @@ inp_subcktexpand(struct line *deck)
|
|||
{
|
||||
struct line *ll, *c;
|
||||
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))
|
||||
(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))
|
||||
(void) strcpy(model, ".model");
|
||||
(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...
|
||||
*/
|
||||
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);
|
||||
#endif
|
||||
#endif /* TRACE */
|
||||
for (s = c->li_line; *s && (*s != '('); s++) /* Iterate charwise along line until ( is found */
|
||||
;
|
||||
if (*s) {
|
||||
|
|
@ -172,17 +301,47 @@ inp_subcktexpand(struct line *deck)
|
|||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In inp_subcktexpand, about to call doit.\n");
|
||||
#endif
|
||||
#endif /* TRACE */
|
||||
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)) {
|
||||
fprintf(cp_err, "Error: unknown subckt: %s\n",
|
||||
c->li_line);
|
||||
fprintf(cp_err, "Error: unknown subckt: %s\n", c->li_line);
|
||||
#ifdef NUMPARAMS
|
||||
if ( use_numparams ) {
|
||||
ok= ok && nupa_signal(NUPAEVALDONE, NULL);
|
||||
}
|
||||
#endif /* NUMPARAMS */
|
||||
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. */
|
||||
}
|
||||
|
||||
|
|
@ -202,34 +361,36 @@ static struct line *
|
|||
doit(struct line *deck)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
|
|
@ -244,7 +405,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 {
|
||||
|
|
@ -252,7 +413,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 . . . */
|
||||
|
|
@ -267,6 +428,9 @@ doit(struct line *deck)
|
|||
sss = alloc(struct subs);
|
||||
if (!lcc) /* if lcc is null, then no .ends was found. */
|
||||
lcc = last;
|
||||
#ifdef NUMPARAMS
|
||||
if ( use_numparams==FALSE )
|
||||
#endif /* NUMPARAMS */
|
||||
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 */
|
||||
|
|
@ -297,8 +461,12 @@ doit(struct line *deck)
|
|||
subs = sss; /* Now that sss is built, assign it to subs */
|
||||
last = c->li_next;
|
||||
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. */
|
||||
/* make lc point to this card, and advance last to next card. */
|
||||
lc = last;
|
||||
|
|
@ -323,25 +491,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;
|
||||
|
|
@ -406,7 +560,7 @@ doit(struct line *deck)
|
|||
|
||||
/* Change the names of .models found in .subckts . . . */
|
||||
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;
|
||||
txfree(gettok(&t)); /* Throw out the subcircuit refdes */
|
||||
|
|
@ -419,13 +573,31 @@ doit(struct line *deck)
|
|||
tfree(subname);
|
||||
|
||||
/* 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)
|
||||
lc->li_next = lcc;
|
||||
else
|
||||
deck = lcc;
|
||||
#endif /* NUMPARAMS */
|
||||
while (lcc->li_next != NULL)
|
||||
lcc = lcc->li_next;
|
||||
lcc->li_next = c->li_next;
|
||||
#ifdef NUMPARAMS
|
||||
lcc->li_next = savenext;
|
||||
#endif /* NUMPARAMS */
|
||||
c = lcc->li_next;
|
||||
lc = lcc;
|
||||
tfree(tofree);
|
||||
|
|
@ -444,6 +616,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( ) */
|
||||
|
|
@ -500,7 +685,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
{
|
||||
struct line *c;
|
||||
char *buffer, *next_name, dev_type, *name, *s, *t, ch, *nametofree;
|
||||
int nnodes, i, dim;
|
||||
int nnodes, i, dim, blen;
|
||||
int rtn=0;
|
||||
|
||||
/* 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 '.':
|
||||
/* 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;
|
||||
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 */
|
||||
|
||||
buffer = tmalloc(2000); /* XXXXX */
|
||||
|
||||
s = c->li_line;
|
||||
name = MIFgettok(&s);
|
||||
|
||||
/* maschmann
|
||||
sprintf(buffer, "%s:%s ", name, scname); */
|
||||
buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
|
||||
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 '~':
|
||||
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;
|
||||
|
||||
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 */
|
||||
|
||||
name = next_name;
|
||||
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;
|
||||
|
||||
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 */
|
||||
|
||||
t = gettrans(name);
|
||||
if (t)
|
||||
sprintf(buffer + strlen(buffer), "%s ", t);
|
||||
else
|
||||
|
||||
if (t) {
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(t)+2)*sizeof(char));
|
||||
sprintf(buffer + blen, "%s ", t);
|
||||
} else {
|
||||
/* maschmann: changed order
|
||||
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);
|
||||
else sprintf(buffer + strlen(buffer), "%s:%s ", scname, name);
|
||||
|
||||
if(name[0]=='v' || name[0]=='V') {
|
||||
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;
|
||||
|
||||
|
||||
} /* switch */
|
||||
|
||||
} /* 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 */
|
||||
|
||||
if(name)
|
||||
sprintf(buffer + strlen(buffer), "%s ", name);
|
||||
|
||||
if(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 */
|
||||
/* 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.
|
||||
*/
|
||||
ch = *name; /* ch identifies the type of component */
|
||||
buffer = tmalloc(2000); /* XXXXX */
|
||||
name++;
|
||||
if (*name == ':')
|
||||
name++; /* now name point to the rest of the refdes */
|
||||
|
||||
|
||||
if (*name)
|
||||
(void) sprintf(buffer, "%c:%s:%s ", ch, scname, /* F:subcircuitname:refdesname */
|
||||
if (*name) {
|
||||
buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
|
||||
sprintf(buffer, "%c:%s:%s ", ch, scname, /* F:subcircuitname:refdesname */
|
||||
name);
|
||||
else
|
||||
(void) sprintf(buffer, "%c:%s ", ch, scname); /* F:subcircuitname */
|
||||
} else {
|
||||
buffer = (char *)tmalloc((strlen(scname)+4)*sizeof(char));
|
||||
sprintf(buffer, "%c:%s ", ch, scname); /* F:subcircuitname */
|
||||
}
|
||||
tfree(t);
|
||||
|
||||
|
||||
|
|
@ -689,13 +894,16 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
t = gettrans(name);
|
||||
|
||||
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
|
||||
* translated name into the buffer.
|
||||
*/
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%s:%s ", scname, name);
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+3)*sizeof(char));
|
||||
sprintf(buffer + blen, "%s:%s ", scname, name);
|
||||
}
|
||||
tfree(name);
|
||||
} /* while (nnodes-- . . . . */
|
||||
|
|
@ -734,8 +942,9 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
}
|
||||
|
||||
/* Write POLY(dim) into buffer */
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"POLY( %d ) ", dim);
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+17)*sizeof(char));
|
||||
sprintf(buffer + blen, "POLY( %d ) ", dim);
|
||||
|
||||
|
||||
} /* 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. */
|
||||
name++;
|
||||
if (*name == ':')
|
||||
name++; /* name now points to the remainder of the token */
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%c:%s:%s ", ch, scname, name);
|
||||
name++; /* name now points to the remainder of the token */
|
||||
blen = strlen(buffer);
|
||||
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 */
|
||||
}
|
||||
else { /* Handle netname */
|
||||
|
|
@ -784,13 +994,16 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
t = gettrans(name);
|
||||
|
||||
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
|
||||
* translated name into the buffer.
|
||||
*/
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%s:%s ", scname, name);
|
||||
blen = strlen(buffer);
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
|
@ -798,7 +1011,9 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
} /* while (nnodes--. . . . */
|
||||
|
||||
/* 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 = "";
|
||||
break;
|
||||
|
||||
|
|
@ -818,25 +1033,26 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
* and stick the translated name into buffer.
|
||||
*/
|
||||
ch = *name;
|
||||
buffer = tmalloc(2000); /* XXXXX */
|
||||
|
||||
name++;
|
||||
if (*name == ':')
|
||||
name++;
|
||||
|
||||
if (*name)
|
||||
(void) sprintf(buffer, "%c:%s:%s ", ch, scname,
|
||||
name);
|
||||
else
|
||||
(void) sprintf(buffer, "%c:%s ", ch, scname);
|
||||
if (*name) {
|
||||
buffer = (char *)tmalloc((strlen(scname)+strlen(name)+5)*sizeof(char));
|
||||
sprintf(buffer, "%c:%s:%s ", ch, scname, name);
|
||||
} else {
|
||||
buffer = (char *)tmalloc((strlen(scname)+4)*sizeof(char));
|
||||
sprintf(buffer, "%c:%s ", ch, scname);
|
||||
}
|
||||
tfree(nametofree);
|
||||
|
||||
|
||||
/* 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;
|
||||
|
|
@ -846,19 +1062,22 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
t = gettrans(name);
|
||||
|
||||
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
|
||||
* translated name into the buffer.
|
||||
*/
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%s:%s ", scname, name);
|
||||
blen = strlen(buffer);
|
||||
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-- . . . . */
|
||||
|
||||
/* 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);
|
||||
|
|
@ -874,29 +1093,35 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
|
|||
if (*name == ':')
|
||||
name++;
|
||||
|
||||
if (*name)
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%c:%s:%s ", ch, scname, name);
|
||||
else
|
||||
(void) sprintf(buffer + strlen(buffer),
|
||||
"%c:%s ", ch, scname);
|
||||
if (*name) {
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+strlen(name)+5)*sizeof(char));
|
||||
sprintf(buffer + blen, "%c:%s:%s ", ch, scname, name);
|
||||
} else {
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(scname)+4)*sizeof(char));
|
||||
sprintf(buffer + blen, "%c:%s ", ch, scname);
|
||||
}
|
||||
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
|
||||
* i(something)...
|
||||
*/
|
||||
finishLine(buffer + strlen(buffer), s, scname);
|
||||
s = "";
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(s)+strlen(scname)+1000)*sizeof(char));
|
||||
finishLine(buffer + blen, s, scname);
|
||||
s = "";
|
||||
|
||||
} /* switch(c->li_line . . . . */
|
||||
|
||||
(void) strcat(buffer, s);
|
||||
tfree(c->li_line);
|
||||
c->li_line = copy(buffer);
|
||||
blen = strlen(buffer);
|
||||
buffer = (char *)trealloc(buffer, (blen+strlen(s)+1)*sizeof(char));
|
||||
strcat(buffer, s);
|
||||
tfree(c->li_line);
|
||||
c->li_line = copy(buffer);
|
||||
|
||||
#ifdef TRACE
|
||||
/* 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++ = ':';
|
||||
i = 1;
|
||||
|
|
@ -1016,6 +1242,7 @@ finishLine(char *dst, char *src, char *scname)
|
|||
}
|
||||
}
|
||||
|
||||
*dst = '\0'; /* va, append in each case '\0' */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1070,6 +1297,12 @@ gettrans(char *name)
|
|||
/* gtri - end */
|
||||
#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"))
|
||||
return (name);
|
||||
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 */
|
||||
/* 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 */
|
||||
|
||||
|
|
@ -1135,7 +1368,7 @@ numnodes(char *name)
|
|||
i = 0;
|
||||
s = buf;
|
||||
gotit = 0;
|
||||
txfree(gettok(&s)); /* Skip component name */
|
||||
txfree(gettok(&s)); /* Skip component name */
|
||||
while ((i < n) && (*s) && !gotit) {
|
||||
t = gettok_node(&s); /* get nodenames . . . */
|
||||
for (wl = modnames; wl; wl = wl->wl_next)
|
||||
|
|
@ -1146,17 +1379,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);
|
||||
|
||||
|
|
@ -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:
|
||||
* *deck = pointer to the .subckt definition (linked list)
|
||||
* *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");
|
||||
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;
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In modtranslate, translating line %s\n", t);
|
||||
#endif
|
||||
|
||||
name = gettok(&t); /* at this point, name = .model */
|
||||
buffer = tmalloc(strlen(name) + strlen(t) +
|
||||
strlen(subname) + 4);
|
||||
(void) sprintf(buffer, "%s ",name); /* at this point, buffer = ".model " */
|
||||
tfree(name);
|
||||
tfree(name);
|
||||
name = gettok(&t); /* name now holds model name */
|
||||
wlsub = alloc(struct wordlist);
|
||||
wlsub->wl_next = submod;
|
||||
if (submod)
|
||||
submod->wl_prev = wlsub;
|
||||
/* here's where we insert the model name into the model name list */
|
||||
submod = wlsub;
|
||||
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 ",
|
||||
subname, name); /* buffer = "model subname:modelname " */
|
||||
(void) strcat(buffer, t);
|
||||
tfree(c->li_line);
|
||||
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;
|
||||
txfree(gettok(&t));
|
||||
wl = alloc(struct wordlist);
|
||||
|
|
@ -1268,6 +1521,12 @@ modtranslate(struct line *deck, char *subname)
|
|||
modnames->wl_prev = wl;
|
||||
modnames = wl;
|
||||
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);
|
||||
|
|
@ -1288,6 +1547,9 @@ devmodtranslate(struct line *deck, char *subname)
|
|||
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;
|
||||
|
|
@ -1304,6 +1566,78 @@ devmodtranslate(struct line *deck, char *subname)
|
|||
|
||||
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 'c':
|
||||
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
|
||||
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':
|
||||
|
|
@ -1526,7 +1860,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))
|
||||
|
|
@ -1552,6 +1886,7 @@ inp_numnodes(char c)
|
|||
case 'l': return (2);
|
||||
case 'm': return (7); /* This means that 7 is the maximun number of nodes */
|
||||
case 'o': return (4);
|
||||
case 'p': return (0);
|
||||
case 'q': return (4);
|
||||
case 'r': return (2);
|
||||
case 's': return (4);
|
||||
|
|
@ -1560,6 +1895,7 @@ inp_numnodes(char c)
|
|||
case 'v': return (2);
|
||||
/* change 3 to 2 here to fix w bug, NCF 1/31/95 */
|
||||
case 'w': return (2);
|
||||
case 'y': return (2);
|
||||
case 'z': return (3);
|
||||
|
||||
default:
|
||||
|
|
@ -1567,11 +1903,3 @@ inp_numnodes(char c)
|
|||
return (2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ namespace eval spicewish {
|
|||
}
|
||||
#eval spice::bltplot $l
|
||||
eval spice::bltplot $args
|
||||
|
||||
return "${::spicewish::viewer::wNames}[expr $::spicewish::viewer::viewCnt -1]"
|
||||
|
||||
}
|
||||
|
||||
proc gui { } {
|
||||
|
|
@ -127,4 +130,5 @@ proc spice_gr_Plot { args } {
|
|||
set ::spicewish::viewer::bltplotCnt $viewerCnt
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue