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

📄 subckt.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 5 页
字号:
/**********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: subckt.c,v 1.21 2005/05/30 20:28:35 sjborley Exp $**********//*------------------------------------------------------------------------------ * 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 * list changes when POLY is used. * Major changes include: * -- Added lots of comments which (hopefully) elucidate the steps taken *    by the program during its processing. * -- Re-wrote translate, which does the processing of each card. * Please direct comments/questions/complaints to Stuart Brorson: * mailto:sdb@cloud9.net *-----------------------------------------------------------------------------*//* * Expand subcircuits. This is very spice-dependent. Bug fixes by Norbert  * Jeske on 10/5/85. *//*======================================================================* * 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. *======================================================================*/#include "ngspice.h"#include "cpdefs.h"#include "ftedefs.h"#include "fteinp.h"#ifdef XSPICE/* gtri - add - wbk - 11/9/90 - include MIF function prototypes */#include "mifproto.h"/* gtri - end - wbk - 11/9/90 */#endif#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);static int translate(struct line *deck, char *formal, char *actual, char *scname, 		     char *subname);static void finishLine(char *dst, char *src, char *scname);static int settrans(char *formal, char *actual, char *subname);static char * gettrans(char *name);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  * in the .subckt definition (t_old), and in the subcircuit invocation * (t_new) *--------------------------------------------------------------------*/static struct tab {    char *t_old;    char *t_new;} table[512];   /* That had better be enough. *//*--------------------------------------------------------------------- *  subs is the linked list which holds the .subckt definitions  *  found during processing.  *--------------------------------------------------------------------*/struct subs {    char *su_name;          /* The .subckt name. */    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_NODEstatic 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    *//* we need to do:  1. Find all .subckt definitions & stick them      *//* into a list.  2. Find all subcircuit invocations (refdes X)       *//* and replace them with the .subckt definition stored earlier.      *//*                                                                   *//* The algorithm is as follows:                                      *//* 1.  Define some aliases for .subckt, .ends, etc.                  *//* 2.  Clean up parens around netnames                               *//* 3.  Call doit, which does the actual translation.                 *//* 4.  Check the results & return.                                   *//* inp_subcktexpand takes as argument a pointer to deck, and         *//* it returns a pointer to the same deck after the new subcircuits   *//* are spliced in.                                                   *//*-------------------------------------------------------------------*/struct line *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");    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);    /*  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 (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 /* TRACE */	for (s = c->li_line; *s && (*s != '('); s++)    /* Iterate charwise along line until ( is found */	  ;	if (*s) {	  while (s[0] && (s[1] != ')')) {	    s[0] = s[1];	    s++;	  }	  while (s[1]) {	    s[0] = s[2];	    s++;	  }	}  /* if (*s)  . . . */      } else {	for (s = c->li_line; *s && !isspace(*s); s++)    /* Iterate charwise along line until space is found */	  ;	while (isspace(*s))	  s++;	if (*s == '(') {	  while (s[0] && (s[1] != ')')) {	    s[0] = s[1];	    s++;	  }	  while (s[1]) {	    s[0] = s[2];	    s++;	  } /* while */	} /* if (*s == '(' . . . */      }    }   /*  for (c = deck . . . */        /* doit does the actual splicing in of the .subckt . . .  */#ifdef TRACE	/* SDB debug statement */	printf("In inp_subcktexpand, about to call doit.\n");#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);#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.  */}#define MAXNEST 21/*-------------------------------------------------------------------*//*  doit does the actual substitution of .subckts.                   *//*  It takes two passes:  the first extracts .subckts                *//*  and sticks pointer to them into the linked list sss.  It does    *//*  the extraction recursively.  Then, it look for subcircuit        *//*  invocations and substitutes the stored .subckt into              *//*  the main circuit file.                                           *//*  It takes as argument a pointer to the deck, and returns a        *//*  pointer to the deck after the subcircuit has been spliced in.    *//*-------------------------------------------------------------------*/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 *tmodnames = modnames;    wordlist *tsubmod = submod;    struct subs *ts = subs;    int error;    /* Save all the old stuff... */    subs = NULL;    submod = NULL;#ifdef TRACE	/* SDB debug statement */	printf("In doit, about to start first pass through deck.\n");

⌨️ 快捷键说明

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