📄 subckt.c
字号:
/* RCS Info: $Revision: 1.2 $ on $Date: 91/04/10 12:18:44 $ * $Source: //pepper/atesse_spice/spice3/FTE/RCS/subckt.c,v $ * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group * * Expand subcircuits. This is very spice-dependent. Bug fixes by Norbert * Jeske on 10/5/85. */#include "prefix.h"#include "CPdefs.h"#include "FTEdefs.h"#include "FTEinp.h"/* gtri - add - wbk - 11/9/90 - include MIF function prototypes */#include "MIFproto.h"/* gtri - end - wbk - 11/9/90 */#include "suffix.h"static struct line *doit();static void translate();static void settrans();static void finishLine();static char *gettrans();static int numnodes(), numdevs();static bool modtranslate();static void devmodtranslate();struct subs { char *su_name; /* The name. */ char *su_args; /* The arguments, space seperated. */ int su_numargs; struct line *su_def; /* The deck that is to be substituted. */ struct subs *su_next;} ;/* Expand all subcircuits in the deck. This handles imbedded .subckt * definitions. The variables substart, subend, and subinvoke can be used * to redefine the controls used. The syntax is invariant though. * NOTE: the deck must be passed without the title card. * What we do is as follows: first make one pass through the circuit * and collect all of the subcircuits. Then, whenever a card that starts * with 'x' is found, copy the subcircuit associated with that name and * splice it in. A few of the problems: the nodes in the spliced-in * stuff must be unique, so when we copy it, append "subcktname:" to * each node. If we are in a nested subcircuit, use foo:bar:...:node. * Then we have to systematically change all references to the renamed * nodes. On top of that, we have to know how many args BJT's have, * so we have to keep track of model names. */static wordlist *modnames, *submod;static struct subs *subs = NULL;static bool nobjthack = false;static char start[32], sbend[32], invoke[32], model[32];struct line *inp_subcktexpand(deck) struct line *deck;{ struct line *ll, *c; char *s; 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"); if(!cp_getvar("modelcard", VT_STRING, model)) (void) strcpy(model, ".model"); (void) cp_getvar("nobjthack", VT_BOOL, (char *) &nobjthack); /* Let's do a few cleanup things first... Get rid of ( ) around node * lists... *//* gtri - modify - wbk - 10/22/90 - fix so that all '(' and ')' are *//* changed to white space (i.e. ' '). Previous code only removed *//* one instance of '(' or ')', and did not replace it with white *//* space. */ /* bypass old code that eliminated a single ')' and '(' */#if 0 for (c = deck; c; c = c->li_next) { if (prefix(start, c->li_line)) { for (s = c->li_line; *s && (*s != '('); s++) ; if (*s) { while (s[0] && (s[1] != ')')) { s[0] = s[1]; s++; } while (s[1]) { s[0] = s[2]; s++; } } } else { for (s = c->li_line; *s && !isspace(*s); s++) ; while (isspace(*s)) s++; if (*s == '(') { while (s[0] && (s[1] != ')')) { s[0] = s[1]; s++; } while (s[1]) { s[0] = s[2]; s++; } } } }#endif /* new code - replace all '(' and ')' with ' ' */ for(c = deck; c; c = c->li_next) for(s = c->li_line; *s; s++) if( (*s == '(') || (*s == ')') ) *s = ' ';/* gtri - end - wbk - 10/22/90 */ ll = doit(deck); /* Now check to see if there are still subckt instances undefined... */ if (ll) { 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); ll = NULL; } } return (ll);}#define MAXNEST 21static struct line *doit(deck) struct line *deck;{ struct line *c, *last, *lc, *lcc; struct subs *sss = (struct subs *) NULL, *ks; char *s, *t, *scname, *subname; int nest, numpasses = MAXNEST, i; bool gotone; wordlist *wl; wordlist *tmodnames = modnames; wordlist *tsubmod = submod; struct subs *ts = subs; /* Save all the old stuff... */ modnames = NULL; subs = NULL; submod = NULL; /* First extract all the subckts. */ for (last = deck, lc = NULL; last; ) { if (prefix(sbend, last->li_line)) { fprintf(cp_err, "Error: misplaced %s card: %s\n", sbend, last->li_line); return (NULL); } else if (prefix(start, last->li_line)) { /* We've got one now. */ if (last->li_next == NULL) { fprintf(cp_err, "Error: no %s card.\n", sbend); return (NULL); } lcc = NULL; wl_free(submod); submod = NULL; gotone = false; for (nest = 0, c = last->li_next; c; c = c->li_next) { if (prefix(sbend, c->li_line)) { if (!nest) break; else { nest--; lcc = c; continue; } } else if (prefix(start, c->li_line)) nest++; lcc = c; } if (!c) { fprintf(cp_err, "Error: no %s card.\n", sbend); return (NULL); } sss = alloc(subs); lcc->li_next = NULL; if (lc) lc->li_next = c->li_next; else deck = c->li_next; sss->su_def = last->li_next; s = last->li_line; (void) gettok(&s); sss->su_name = gettok(&s); sss->su_args = copy(s); for (sss->su_numargs = 0, i = 0; s[i]; ) { while (isspace(s[i])) i++; if (s[i]) { sss->su_numargs++; while (s[i] && !isspace(s[i])) i++; } } sss->su_next = subs; subs = sss; last = c->li_next; lcc = subs->su_def; } else { lc = last; last = last->li_next; } } if (!sss) return (deck); /* Expand sub-subcircuits. */ for (ks = sss = subs; sss; sss = sss->su_next) if (!(sss->su_def = doit(sss->su_def))) return (NULL); subs = ks; /* Get all the model names so we can deal with BJT's. */ for (c = deck; c; c = c->li_next) if (prefix(model, c->li_line)) { s = c->li_line; (void) gettok(&s); wl = alloc(wordlist); wl->wl_next = modnames; if (modnames) modnames->wl_prev = wl; modnames = wl; wl->wl_word = gettok(&s); } /* Now do the replacements. */ do { gotone = false; for (c = deck, lc = NULL; c; ) { if (ciprefix(invoke, c->li_line)) { gotone = true; t = s = copy(c->li_line); scname = gettok(&s);/* gtri - modify - wbk - 4/10/91 - change way pathnames are built *//* comment out so that whole instance name is used in pathnames *//* scname += strlen(invoke); while ((*scname == ' ') || (*scname == '\t') || (*scname == ':')) scname++;*//* gtri - end - wbk - 4/10/91 - change way pathnames are built */ while(*s) s++; s--; while ((*s == ' ') || (*s == '\t')) *s-- = '\0'; while ((*s != ' ') && (*s != '\t')) s--; s++; for (sss = subs; sss; sss = sss->su_next) if (eq(sss->su_name, s)) break; /* Don't complain -- this might be an * instance of a subckt that is defined above. */ if (!sss) { lc = c; c = c->li_next; continue; } /* Now we have to replace this card with the * macro definition. */ subname = copy(sss->su_name); lcc = inp_deckcopy(sss->su_def); /* Change the names of the models... */ if (modtranslate(lcc, scname)) devmodtranslate(lcc, scname); s = sss->su_args; (void) gettok(&t); /* Throw out the name. */ translate(lcc, s, t, scname, subname); /* Now splice the decks together. */ if (lc) lc->li_next = lcc; else deck = lcc; while (lcc->li_next != NULL) lcc = lcc->li_next; lcc->li_next = c->li_next; c = lcc->li_next; lc = lcc; } else { lc = c; c = c->li_next; } } } while (numpasses-- && gotone); if (!numpasses) { fprintf(cp_err, "Error: infinite subckt recursion\n"); return (NULL); } subs = ts; modnames = tmodnames; submod = tsubmod; return (deck);}/* Copy a deck, including the actual lines. */struct line *inp_deckcopy(deck) struct line *deck;{ struct line *d = NULL, *nd = NULL; while (deck) { if (nd) { d->li_next = alloc(line); d = d->li_next; } else nd = d = alloc(line); d->li_linenum = deck->li_linenum; d->li_line = copy(deck->li_line); if (deck->li_error) d->li_error = copy(deck->li_error); d->li_actual = inp_deckcopy(deck->li_actual); deck = deck->li_next; } return (nd);}/* Translate all of the device names and node names in the deck. They are * pre-pended with subname:, unless they are in the formal list, in which case * they are replaced with the corresponding entry in the actual list. * The one special case is node 0 -- this is always ground and we don't * touch it. */static voidtranslate(deck, formal, actual, scname, subname) struct line *deck; char *formal, *actual, *scname, *subname;{ struct line *c; char *buffer, *name, *s, *t, ch; int nnodes;/* gtri - add - wbk - 10/23/90 - add new local variables */ char *next_name; /* for look-ahead during tokenizing *//* gtri - end - wbk - 10/23/90 */ settrans(formal, actual, subname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -