📄 subckt.c
字号:
* finishLine now doesn't handle current or voltage sources. * Therefore, it just writes out the final netnames, if required. * Changes made by SDB on 4.29.2003. *-------------------------------------------------------------------*/static voidfinishLine(char *dst, char *src, char *scname){ char buf[4 * BSIZE_SP], which; char *s; int i; int lastwasalpha; lastwasalpha = 0; while (*src) { /* Find the next instance of "<non-alpha>[vi]<opt spaces>(" in * this string. */ if (((*src != 'v') && (*src != 'V') && (*src != 'i') && (*src != 'I')) || lastwasalpha) { lastwasalpha = isalpha(*src); *dst++ = *src++; continue; } for (s = src + 1; *s && isspace(*s); s++) ; if (!*s || (*s != '(')) { lastwasalpha = isalpha(*src); *dst++ = *src++; continue; } lastwasalpha = 0; which = *dst++ = *src; src = s; *dst++ = *src++; while (isspace(*src)) src++; for (i = 0; *src && !isspace(*src) && *src != ',' && (*src != ')'); i++) { buf[i] = *src++; } buf[i] = '\0'; if ((which == 'v') || (which == 'V')) s = gettrans(buf); else s = NULL; if (s) { while (*s) *dst++ = *s++; } else { /* just a normal netname . . . . */ /* * */ if ((which == 'i' || which == 'I') && (buf[0] == 'v' || buf[0] == 'V')) { *dst++ = buf[0]; *dst++ = ':'; i = 1; } else { i = 0; } for (s = scname; *s; ) *dst++ = *s++; *dst++ = ':'; for (s = buf + i; *s; ) *dst++ = *s++; } /* translate the reference node, as in the "2" in "v(4,2)" */ if ((which == 'v') || (which == 'V')) { while (*src && (isspace(*src) || *src == ',')) { src++; } if (*src && *src != ')') { for (i = 0; *src && !isspace(*src) && (*src != ')'); i++) buf[i] = *src++; buf[i] = '\0'; s = gettrans(buf); *dst++ = ','; if (s) { while (*s) *dst++ = *s++; } else { for (s = scname; *s; ) *dst++ = *s++; *dst++ = ':'; for (s = buf; *s; ) *dst++ = *s++; } } } } *dst = '\0'; /* va, append in each case '\0' */ return;}/*------------------------------------------------------------------------------* * settrans builds the table which holds the old and new netnames. * it also compares the number of nets present in the .subckt definition against * the number of nets present in the subcircuit invocation. It returns 0 if they * match, otherwise, it returns an error. * * Variable definitions: * formal = copy of the .subckt definition line (e.g. ".subckt subcircuitname 1 2 3") (string) * actual = copy of the .subcircuit invocation line (e.g. "Xexample 4 5 6 subcircuitname") (string) * subname = copy of the subcircuit name *------------------------------------------------------------------------------*/static intsettrans(char *formal, char *actual, char *subname){ int i; bzero(table,sizeof(*table)); for (i = 0; ; i++) { table[i].t_old = gettok(&formal); table[i].t_new = gettok(&actual); if (table[i].t_new == NULL) { return -1; /* Too few actual / too many formal */ } else if (table[i].t_old == NULL) { if (eq(table[i].t_new, subname)) break; else return 1; /* Too many actual / too few formal */ } } return 0;}/*------------------------------------------------------------------------------* * gettrans returns the name of the top level net if it is in the list, * otherwise it returns NULL. *------------------------------------------------------------------------------*/static char *gettrans(char *name){ int i;#ifdef XSPICE /* gtri - wbk - 2/27/91 - don't translate the reserved word 'null' */ if (eq(name, "null")) return (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++) if (eq(table[i].t_old, name)) return (table[i].t_new); return (NULL);}/*-------------------------------------------------------------------*//*-------------------------------------------------------------------*/static intnumnodes(char *name){/* gtri - comment - wbk - 10/23/90 - Do not modify this routine for *//* 'A' type devices since the callers will not know how to find the *//* nodes even if they know how many there are. Modify the callers *//* instead. *//* gtri - end - wbk - 10/23/90 */ char c; struct subs *sss; char *s, *t, buf[4 * BSIZE_SP]; wordlist *wl; int n, i, gotit; while (*name && isspace(*name)) name++; c = (isupper(*name) ? tolower(*name) : *name); (void) strncpy(buf, name, sizeof(buf)); s = buf; if (c == 'x') { /* Handle this ourselves. */ 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; if (!sss) { fprintf(cp_err, "Error: no such subcircuit: %s\n", s); return (0); } return (sss->su_numargs); } n = inp_numnodes(c); /* 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 "maximum number of nodes */ /* for a given device type. */ /* Paolo Nenzi Jan-2001 */ /* I hope that works, this code is very very untested */ if (c=='m') { /* IF this is a mos */ i = 0; s = buf; gotit = 0; 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) if (eq(t, wl->wl_word)) gotit = 1; i++; tfree(t); } /* while . . . . */ /* Note: node checks must be done on #_of_node-1 because the */ /* "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); /* compensate the unnecessary increment in the while cycle */ } /* if (c=='m' . . . */ if (nobjthack || (c != 'q')) return (n); for (s = buf, i = 0; *s && (i < 4); i++) txfree(gettok(&s)); if (i == 3) return (3); else if (i < 4) { fprintf(cp_err, "Error: too few nodes for BJT: %s\n", name); return (0); } /* Now, is this a model? */ t = gettok(&s); for (wl = modnames; wl; wl = wl->wl_next) if (eq(t, wl->wl_word)) { tfree(t); return (3); } tfree(t); return (4);}/*-------------------------------------------------------------------* * This function returns the number of controlling voltage sources * (for F, H) or controlling nodes (for G, E) attached to a dependent * source. *-------------------------------------------------------------------*/static int numdevs(char *s){ while (*s && isspace(*s)) s++; switch (*s) { case 'K': case 'k': return (2); /* two nodes per voltage controlled source */ case 'G': case 'g': case 'E': case 'e': return(2); /* one source per current controlled source */ case 'F': case 'f': case 'H': case 'h': /* 2 lines here added to fix w bug, NCF 1/31/95 */ case 'W': case 'w': return (1); default: return (0); }}/*----------------------------------------------------------------------* * 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) * Modtranslate returns TRUE if it translated a model name, FALSE * otherwise. *----------------------------------------------------------------------*/static boolmodtranslate(struct line *deck, char *subname){ struct line *c; char *buffer, *name, *t, model[4 * BSIZE_SP]; wordlist *wl, *wlsub; bool gotone; (void) strcpy(model, ".model"); gotone = FALSE; for (c = deck; c; c = c->li_next) { /* iterate through model def . . . */ 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); 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); wl->wl_next = modnames; if (modnames) 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -