⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subckt.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 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 "spice.h"#include "cpdefs.h"#include "ftedefs.h"#include "fteinp.h"#include "suffix.h"static struct line *doit();static int translate();static int 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 line. * What we do is as follows: first make one pass through the circuit * and collect all of the subcircuits. Then, whenever a line 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");    if(!cp_getvar("modelline", 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...     */    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++;                }            }        }    }        ll = doit(deck);    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;    int error;    /* Save all the old stuff... */    modnames = NULL;    subs = NULL;    submod = NULL;    /* Extract all the .subckts */    for (last = deck, lc = NULL; last; ) {        if (prefix(sbend, last->li_line)) {            fprintf(cp_err, "Error: misplaced %s line: %s\n", sbend,                    last->li_line);            return (NULL);        } else if (prefix(start, last->li_line)) {            if (last->li_next == NULL) {                fprintf(cp_err, "Error: no %s line.\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 line.\n", sbend);                return (NULL);            }            sss = alloc(struct subs);	    if (!lcc)		lcc = last;            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(struct wordlist);            wl->wl_next = modnames;            if (modnames)                modnames->wl_prev = wl;            modnames = wl;            wl->wl_word = gettok(&s);        }    error = 0;    /* 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);                scname += strlen(invoke);                while ((*scname == ' ') || (*scname == '\t') ||                        (*scname == ':'))                    scname++;                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 line 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. */                if (!translate(lcc, s, t, scname, subname))		    error = 1;                /* 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 (!error && numpasses-- && gotone);    if (!numpasses) {        fprintf(cp_err, "Error: infinite subckt recursion\n");        return (NULL);    }    /* Now check to see if there are still subckt instances undefined... */    for (c = deck; c; c = c->li_next)	if (ciprefix(invoke, c->li_line)) {	    fprintf(cp_err, "Error: unknown subckt: %s\n",		    c->li_line);	    error = 1;	}    if (error)	return NULL;	/* error message already reported; should free( ) */    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(struct line);            d = d->li_next;        } else            nd = d = alloc(struct 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 inttranslate(deck, formal, actual, scname, subname)    struct line *deck;    char *formal, *actual, *scname, *subname;{    struct line *c;    char *buffer, *name, *s, *t, ch;    int nnodes, i;    i = settrans(formal, actual, subname);    if (i < 0) {	fprintf(stderr,	"Too few parameters for subcircuit type \"%s\" (instance: x%s)\n",		subname, scname);	return 0;    } else if (i > 0) {	fprintf(stderr,	"Too many parameters for subcircuit type \"%s\" (instance: x%s)\n",		subname, scname);	return 0;    }    for (c = deck; c; c = c->li_next) {        /* Rename the device. */        switch (*c->li_line) {        case '\0':        case '*':        case '.':            /* Nothing any good here. */            continue;        default:                s = c->li_line;            name = gettok(&s);	    if (!name)		continue;	    if (!*name) {		tfree(name);		continue;	    }            ch = *name;            buffer = tmalloc(10000);    /* XXXXX */            name++;            if (*name == ':')            name++;            if (*name)                (void) sprintf(buffer, "%c:%s:%s ", ch, scname,                    name);            else                (void) sprintf(buffer, "%c:%s ", ch, scname);            nnodes = numnodes(c->li_line);            while (nnodes-- > 0) {            name = gettok(&s);            if (name == NULL) {                fprintf(cp_err, "Error: too few nodes: %s\n",                        c->li_line);                return 0;            }            t = gettrans(name);            if (t)                (void) sprintf(buffer + strlen(buffer), "%s ",                        t);            else                (void) sprintf(buffer + strlen(buffer),                        "%s:%s ", scname, name);            }                nnodes = numdevs(c->li_line);            while (nnodes-- > 0) {            name = gettok(&s);            if (name == NULL) {                fprintf(cp_err, "Error: too few devs: %s\n",                        c->li_line);                return 0;            }            ch = *name;            name++;            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);            }            /* Now scan through the line for v(something) and             * i(something)...             */            finishLine(buffer + strlen(buffer), s, scname);            s = "";        }            (void) strcat(buffer, s);        tfree(c->li_line);        c->li_line = copy(buffer);        tfree(buffer);    }    return 1;}static voidfinishLine(dst, src, scname)    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++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -