From 8dc5eac0eef8ef4acb840ffb694e45c715f0db49 Mon Sep 17 00:00:00 2001 From: arno Date: Tue, 5 Sep 2000 19:48:22 +0000 Subject: [PATCH] * TODO, doc/ngspice.texi: Small updates * configure.in: New --enable-smoketest. * src/main.c src/ngspice.c src/frontend/outitf.c src/frontend/runcoms.c src/frontend/spiceif.c src/frontend/parser/numparse.c src/include/cktdefs.h src/include/fteext.h src/include/inpdefs.h src/include/jobdefs.h src/include/ngspice.h src/include/tskdefs.h src/spicelib/analysis/Makefile.am src/spicelib/analysis/acsetp.c src/spicelib/analysis/cktaskaq.c src/spicelib/analysis/cktdojob.c src/spicelib/analysis/cktnewan.c src/spicelib/analysis/cktsetap.c src/spicelib/analysis/cktsopt.c src/spicelib/analysis/ckttroub.c src/spicelib/analysis/dcosetp.c src/spicelib/analysis/dctsetp.c src/spicelib/analysis/dsetparm.c src/spicelib/analysis/nsetparm.c src/spicelib/analysis/pzsetp.c src/spicelib/analysis/senssetp.c src/spicelib/analysis/tfsetp.c src/spicelib/analysis/transetp.c src/spicelib/devices/bjt/bjtdset.h src/spicelib/devices/bjt/bjtext.h src/spicelib/devices/bjt/bjtsetup.c src/spicelib/devices/bsim2/b2set.c src/spicelib/devices/bsim3/b3acld.c src/spicelib/devices/bsim3/b3set.c src/spicelib/devices/bsim3/bsim3def.h src/spicelib/devices/csw/cswtrunc.c src/spicelib/devices/dio/diodset.c src/spicelib/devices/dio/dioinit.c src/spicelib/devices/jfet/jfetset.c src/spicelib/devices/mes/messetup.c src/spicelib/devices/mos1/mos1ask.c src/spicelib/devices/mos1/mos1set.c src/spicelib/devices/mos1/mos1temp.c src/spicelib/devices/mos3/mos3load.c src/spicelib/devices/mos6/mos6set.c src/spicelib/devices/sw/swtrunc.c src/spicelib/parser/inppas2.c src/spicelib/parser/inppas3.c src/spicelib/parser/inppas3.h: Paolo and I have integrated patches from Alan Gillespie . --- ChangeLog | 5 + TODO | 50 +- configure.in | 27 +- doc/ngspice.texi | 2 +- src/frontend/outitf.c | 128 +- src/frontend/parser/numparse.c | 6 +- src/frontend/runcoms.c | 3 +- src/frontend/spiceif.c | 37 +- src/include/cktdefs.h | 225 +-- src/include/fteext.h | 4 +- src/include/inpdefs.h | 2 +- src/include/jobdefs.h | 11 - src/include/ngspice.h | 19 +- src/include/tskdefs.h | 1 + src/main.c | 3 + src/ngspice.c | 32 +- src/spicelib/analysis/Makefile.am | 2 + src/spicelib/analysis/acsetp.c | 2 + src/spicelib/analysis/cktaskaq.c | 1 + src/spicelib/analysis/cktdojob.c | 5 +- src/spicelib/analysis/cktnewan.c | 3 + src/spicelib/analysis/cktsetap.c | 1 + src/spicelib/analysis/cktsopt.c | 1 + src/spicelib/analysis/ckttroub.c | 1 + src/spicelib/analysis/dcosetp.c | 2 + src/spicelib/analysis/dctsetp.c | 1 + src/spicelib/analysis/dsetparm.c | 1 + src/spicelib/analysis/nsetparm.c | 1 + src/spicelib/analysis/pzsetp.c | 1 + src/spicelib/analysis/senssetp.c | 1 + src/spicelib/analysis/tfsetp.c | 1 + src/spicelib/analysis/transetp.c | 2 + src/spicelib/devices/bjt/bjtdset.h | 2 +- src/spicelib/devices/bjt/bjtext.h | 31 +- src/spicelib/devices/bjt/bjtsetup.c | 9 +- src/spicelib/devices/bsim2/b2set.c | 35 +- src/spicelib/devices/bsim3/b3acld.c | 548 ++++---- src/spicelib/devices/bsim3/b3set.c | 12 +- src/spicelib/devices/bsim3/bsim3def.h | 4 +- src/spicelib/devices/csw/cswtrunc.c | 13 +- src/spicelib/devices/dio/diodset.c | 11 +- src/spicelib/devices/dio/dioinit.c | 2 + src/spicelib/devices/jfet/jfetset.c | 9 +- src/spicelib/devices/mes/messetup.c | 9 +- src/spicelib/devices/mos1/mos1ask.c | 2 +- src/spicelib/devices/mos1/mos1set.c | 9 +- src/spicelib/devices/mos1/mos1temp.c | 1 - src/spicelib/devices/mos3/mos3load.c | 1803 ++++++++++++------------- src/spicelib/devices/mos6/mos6set.c | 4 +- src/spicelib/devices/sw/swtrunc.c | 4 +- src/spicelib/parser/inppas2.c | 115 +- src/spicelib/parser/inppas3.c | 174 +-- src/spicelib/parser/inppas3.h | 3 +- 53 files changed, 1716 insertions(+), 1665 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45c2eae3e..9e229009f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2000-09-05 Arno W. Peters + + * ???: Paolo and I have integrated patches from Alan Gillespie + . + 2000-07-28 Arno W. Peters * tests/polezero/*.out: Changed the content of these files because diff --git a/TODO b/TODO index e2a7b5ee1..9264ed01b 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,16 @@ +Long term vision +================ + +Remove distinction between subcircuits and models as much as possible. +With a Spice netlist compiler (to be written), the subcircuit can be +translated into a compiled version, dynamically loadable into the +simulation core. + +Using the approach outlined above, we can cut down on maintenance for +the bsim[123], bjt, and other transistor models. For inspiration, +look at *.model files in ACS (Al's Circuit Simulator). + + List of Things To Do ==================== @@ -23,7 +36,9 @@ Usability issues ------------------ Plug all memory leaks; use debauch (http://quorum.tamu.edu/jon/gnu/) -or another memory checker to find them. +or another memory checker to find them. Could also try a garbage +collector (http://www.hpl.hp.com/personal/Hans_Boehm/gc/) to +circumvent memory leaks. Either get help program functioning again; OR interface to webbrowser, info reader and get rid of all help-related code. Option 2 is the @@ -43,10 +58,6 @@ Separate ngspice and nutmeg; i.e., no more SIMULATOR define. ngspice should probably only contain the batch processor. nutmeg would have the complete frontend. -Integrate bsim3, bsim3v1, bsim3v2 to use a single codebase instead of -three only slighty differing implementations. This also cuts down -compilation time. - All frontend commands can now be found in the frontend directory. Move frontend helper functions into frontend directory as well. Not all files that define commands, start with com_*; fix that. @@ -54,10 +65,25 @@ Not all files that define commands, start with com_*; fix that. Make devices dynamically loadable. Perhaps use framework from glib (http://developer.gnome.org/doc/API/glib/index.html). +Integrate bsim3, bsim3v1, bsim3v2 to use a single codebase instead of +three only slighty differing implementations. This also cuts down +compilation time. + +Code for determing memory limits and resource usage, now use +setjmp()/longjmp(), replace this by rlimit() on systems that have it. + +Program frontend in Guile (http://www.gnu.org/software/guile ), +Python (http://www.python.org ), or SWIG (http://www.swig.org). This +shows where the spicelib API needs refining. + Testability ----------- +Verify C code device models by building equivalent netlists and +comparing simulation results. Equivalent netlists also help document +the models currently in Spice. + Add tests for all functions in the complex library in src/maths/cmaths. @@ -72,11 +98,23 @@ src/maths/deriv. Add more circuit tests into the tests directory. +Use gcov to measure current test coverage (and to find out where more +tests are needed.) Make this a configure switch. + +Let GCC generate even more warnings on dubious construction by +specifying the following compile switches: -pedantic -W +-Wmissing-prototypes -Wstrict-prototypes -Wtraditional -Wconversion +-Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings +-Waggregate-return -fshort-enums -fno-common -Wnested-externs +-Dinline= -g -O4. Use 'configure --enable-smoketest' to use these +compile switches. Our goal is to remove all warnings. + Documentation ------------- -Update ARCHITECTURE to contain a high level overview of spice. +Make a document that contains a high level architectural overview of +spice. Convert ngspice.texi further to texinfo format. [PARTIAL] diff --git a/configure.in b/configure.in index 4d794ef69..4c1974624 100644 --- a/configure.in +++ b/configure.in @@ -27,6 +27,10 @@ dnl --enable-sense2 : define HAVE_SENSE2 for the code AC_ARG_ENABLE(sense2, [ --enable-sense2 Use spice2 sensitivity analysis]) +dnl --enable-smoketest : a smoketest +AC_ARG_ENABLE(smoketest, + [ --enable-smoketest Enables smoketest compile]) + dnl --enable-experimental : define EXPERIMENTAL_CODE for the code AC_ARG_ENABLE(experimental, [ --enable-experimental Enables some experimental code]) @@ -52,6 +56,7 @@ if test "$enable_debug" = "no"; then CFLAGS=" " fi + dnl Not sure that this will work.... if test "$with_checkergcc" = "yes"; then CC="checkergcc" @@ -68,24 +73,20 @@ if test "$enable_ansi" = "yes"; then fi fi - +if test "$enable_smoketest" = "yes"; then +dnl CFLAGS="$CFLAGS -Werror" + CFLAGS="$CFLAGS -pedantic -W -Wmissing-prototypes" + CFLAGS="$CFLAGS -Wstrict-prototypes -Wtraditional" + CFLAGS="$CFLAGS -Wconversion -Wshadow -Wpointer-arith" + CFLAGS="$CFLAGS -Wcast-qual -Wcast-align -Wwrite-strings" + CFLAGS="$CFLAGS -Waggregate-return -fshort-enums -fno-common" + CFLAGS="$CFLAGS -Wnested-externs -Dinline= -g -O4" +fi dnl Chech system we're on , and tune accordingly AC_CANONICAL_HOST -case "$host" in - -*bsd* ) CFLAGS="$CFLAGS";; -*linux*) CFLAGS="$CFLAGS";; -*rs6000* ) CFLAGS="$CFLAGS";; -*sgi* ) CFLAGS="$CFLAGS";; -*sun* ) CFLAGS="$CFLAGS";; -*ultrix* ) CFLAGS="$CFLAGS";; - -esac - - dnl Checks for programs diff --git a/doc/ngspice.texi b/doc/ngspice.texi index 397c2788c..ab5923b30 100644 --- a/doc/ngspice.texi +++ b/doc/ngspice.texi @@ -146,7 +146,7 @@ Emmanuel Rouat , Jaijeet S. Roychowdhury, Takayasu Sakurai, Kanwar Jit Singh, -Andrew Tuckey +Andrew Tuckey , Michael Widlok , and many others... diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 9f12b0504..93023c983 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -30,7 +30,9 @@ Modified: 2000 AlansFixes extern void gr_end_iplot(void); -extern SPICEanalysis *analInfo[]; +extern char *spice_analysis_get_name(int index); +extern char *spice_analysis_get_description(int index); + /* static declarations */ static int beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, @@ -135,7 +137,7 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch run->windowed = windowed; run->numData = 0; - an_name = analInfo[((JOB *) analysisPtr)->JOBtype]->public.name; + an_name = spice_analysis_get_name(((JOB *) analysisPtr)->JOBtype); /* Now let's see which of these things we need. First toss in the * reference vector. Then toss in anything that getSaves() tells @@ -159,8 +161,8 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch continue; } if (cieq(saves[i].name, "alli")) { - savealli = true; - savesused[i] = true; + savealli = TRUE; + savesused[i] = TRUE; saves[i].used = 1; continue; } @@ -315,7 +317,7 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch && run->refIndex == -1)) { fprintf(cp_err, "Error: no data saved for %s; analysis not run\n", - analInfo[((JOB *) analysisPtr)->JOBtype]->public.description); + spice_analysis_get_description(((JOB *) analysisPtr)->JOBtype)); return E_NOTFOUND; } @@ -488,7 +490,7 @@ OUTpData(void *plotPtr, IFvalue *refValue, IFvalue *valuePtr) fileEndPoint(run->fp, run->binary); if (ferror(run->fp)) { fprintf(stderr, "Warning: rawfile write error !!\n"); - shouldstop=true; + shouldstop = TRUE; }; } else { for (i = 0; i < run->numData; i++) { @@ -711,13 +713,13 @@ fileInit(runDesc *run) /* Write Analysis Type */ - if (strnicmp(run->type,"AC",2)==0) { + if (strncasecmp(run->type,"AC",2)==0) { sprintf(buf, "AC Sweep"); sweep=2; - } else if (strnicmp(run->type,"DC",2)==0) { + } else if (strncasecmp(run->type,"DC",2)==0) { sprintf(buf, "DC Sweep"); sweep=1; - } else if (strnicmp(run->type,"Tran",4)==0) { + } else if (strncasecmp(run->type,"Tran",4)==0) { sprintf(buf, "Transient Analysis"); sweep=4; }; @@ -818,23 +820,24 @@ fileInit_pass2(runDesc *run) int i, type; char *name, buf[BSIZE_SP]; char *ch, *end; + int tmp; for (i = 0; i < run->numData; i++) { - if ((run->data[i].regular==false) || + if ((run->data[i].regular == FALSE) || cieq(run->data[i].name, "time") || cieq(run->data[i].name, "sweep") || cieq(run->data[i].name, "frequency")) - (void) sprintf(name, "%s", run->data[i].name); + (void) sprintf(name, "%s", run->data[i].name); else - (void) sprintf(name, "V(%s)", run->data[i].name); + (void) sprintf(name, "V(%s)", run->data[i].name); - if (ch=strstr(name, "#branch")) { + if (ch=strstr(name, "#branch")) { name[0]='I'; *ch++=')'; *ch='\0'; type = SV_CURRENT; - } + } else if (cieq(name, "time")) type = SV_TIME; else if (cieq(name, "frequency")) @@ -842,56 +845,57 @@ fileInit_pass2(runDesc *run) else type = SV_VOLTAGE; if (*name=='@') { - type = SV_CURRENT; - memmove(name, &name[1], strlen(name)-1); - if ((ch=strchr(name, '['))!=NULL) { - ch++; - strncpy(buf, ch, BSIZE_SP); - ch--; - *ch='\0'; - if ((ch=strchr(buf, ']'))!=NULL) *ch='\0'; - strcat(buf, "("); - if ((ch=strchr(name, ':'))!=NULL) { - ch++; - strncat(buf, ch, BSIZE_SP-strlen(buf)); - ch--; - *ch='\0'; - if ((ch=strrchr(buf, ':'))!=NULL) { - ch++; - memmove(&ch[strlen(name)], ch, strlen(ch)+1); - memmove(ch, name, strlen(name)); - }; - } else { - strncat(buf, name, BSIZE_SP-strlen(buf)); - }; - strcat(buf, ")"); - }; - strncpy(name, buf, BSIZE_SP); + type = SV_CURRENT; + memmove(name, &name[1], strlen(name)-1); + if ((ch=strchr(name, '['))!=NULL) { + ch++; + strncpy(buf, ch, BSIZE_SP); + ch--; + *ch='\0'; + if ((ch=strchr(buf, ']'))!=NULL) *ch='\0'; + strcat(buf, "("); + if ((ch=strchr(name, ':'))!=NULL) { + ch++; + strncat(buf, ch, BSIZE_SP-strlen(buf)); + ch--; + *ch='\0'; + if ((ch=strrchr(buf, ':'))!=NULL) { + ch++; + memmove(&ch[strlen(name)], ch, strlen(ch)+1); + memmove(ch, name, strlen(name)); + }; + } else { + strncat(buf, name, BSIZE_SP-strlen(buf)); + }; + strcat(buf, ")"); + }; + strncpy(name, buf, BSIZE_SP); }; - while ((ch=strchr(name, ':'))!=NULL) *ch='.'; + while ((ch=strchr(name, ':'))!=NULL) + *ch='.'; if ((ch=strchr(name, '('))!=NULL) { - ch++; - end=(char *)memchr(name, '\0', BSIZE_SP); - while (strchr(ch, '.')!=NULL) { - memmove(ch+1, ch, end-ch+1); - end++; - *ch='x'; - ch=strchr(ch, '.'); - ch++; - }; + ch++; + end=(char *)memchr(name, '\0', BSIZE_SP); + while (strchr(ch, '.')!=NULL) { + memmove(ch+1, ch, end-ch+1); + end++; + *ch='x'; + ch=strchr(ch, '.'); + ch++; + }; }; fprintf(run->fp, "%s", name); tmp=0; - fwrite((char*)&tmp,1,1,run->fp); + fwrite((void *)&tmp,1,1,run->fp); } fflush(run->fp); /* Make all sure this gets to disk */ -/* Allocate Row buffer */ + /* Allocate Row buffer */ rowbuflen=(run->numData)*sizeof(float); if (run->isComplex) rowbuflen *=2; @@ -1126,7 +1130,7 @@ parseSpecial(char *name, char *dev, char *param, char *ind) *dev = *param = *ind = '\0'; if (*name != '@') - return (FALSE); + return FALSE; name++; s = dev; @@ -1134,7 +1138,7 @@ parseSpecial(char *name, char *dev, char *param, char *ind) *s++ = *name++; *s = '\0'; if (!*name) - return (TRUE); + return TRUE; name++; s = param; @@ -1144,7 +1148,7 @@ parseSpecial(char *name, char *dev, char *param, char *ind) if (*name == ']') return (!name[1] ? TRUE : FALSE); else if (!*name) - return (FALSE); + return FALSE; name++; s = ind; @@ -1152,9 +1156,9 @@ parseSpecial(char *name, char *dev, char *param, char *ind) *s++ = *name++; *s = '\0'; if (*name && !name[1]) - return (TRUE); + return TRUE; else - return (FALSE); + return FALSE; } /* This routine must match two names with or without a V() around them. */ @@ -1167,14 +1171,14 @@ name_eq(char *n1, char *n2) if ((s =strchr(n1, '('))) { strcpy(buf1, s); if (!(s =strchr(buf1, ')'))) - return (FALSE); + return FALSE; *s = '\0'; n1 = buf1; } if ((s =strchr(n2, '('))) { strcpy(buf2, s); if (!(s =strchr(buf2, ')'))) - return (FALSE); + return FALSE; *s = '\0'; n2 = buf2; } @@ -1193,7 +1197,7 @@ getSpecial(dataDesc *desc, runDesc *run, IFvalue *val) desc->specName, &desc->specFast, ft_sim, &desc->type, &selector) == OK) { desc->type &= (IF_REAL | IF_COMPLEX); /* mask out other bits */ - return(TRUE); + return TRUE; } else if ((vv = if_getstat(run->circuit, &desc->name[1]))) { /* skip @ sign */ desc->type = IF_REAL; @@ -1204,13 +1208,13 @@ getSpecial(dataDesc *desc, runDesc *run, IFvalue *val) else if (vv->va_type == VT_BOOL) val->rValue = (vv->va_bool ? 1.0 : 0.0); else { - return (FALSE); /* not a real */ + return FALSE; /* not a real */ } tfree(vv); - return(TRUE); + return TRUE; } - return (FALSE); + return FALSE; } static void diff --git a/src/frontend/parser/numparse.c b/src/frontend/parser/numparse.c index ef4b2150e..64400819c 100644 --- a/src/frontend/parser/numparse.c +++ b/src/frontend/parser/numparse.c @@ -13,7 +13,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group static double -pow10(double num) /* Chris Inbody */ +power10(double num) /* Chris Inbody */ { double d = 1.0; @@ -65,7 +65,7 @@ ft_numparse(char **s, bool whole) string++; p = 1; while (isdigit(*string)) - mant += (*string++ - '0') / pow10(p++); + mant += (*string++ - '0') / power10(p++); } /* Now look for the scale factor or the exponent (can't have both). */ @@ -87,7 +87,7 @@ ft_numparse(char **s, bool whole) string++; p = 1; while (isdigit(*string)) - expo += (*string++ - '0') / pow10(p++); + expo += (*string++ - '0') / power10(p++); } expo *= exsign; break; diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index ba98e0bbc..279d17e49 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -294,11 +294,10 @@ ft_getOutReq(FILE **fpp, struct plot **plotp, bool *binp, char *name, char *titl { /*struct plot *pl;*/ #ifndef BATCH -struct plot *pl; if ( (strcmp(name, "Operating Point")==0) || (strcmp(name, "AC Operating Point")==0) ) { - return (false); + return (FALSE); }; #endif diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index 92e89bceb..136352ff6 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -51,27 +51,32 @@ if_inpdeck(struct line *deck, INPtables **tab) i++; *tab = INPtabInit(i); ft_curckt->ci_symtab = *tab; - if ((err = (*(ft_sim->newCircuit))(&ckt)) - != OK) { + + err = (*(ft_sim->newCircuit))(&ckt); + if (err != OK) { ft_sperror(err, "CKTinit"); return (NULL); } + err = IFnewUid(ckt,&taskUid,(IFuid)NULL,"default",UID_TASK,(void**)NULL); if(err) { ft_sperror(err,"newUid"); return(NULL); } + err = (*(ft_sim->newTask))(ckt,(void**)&(ft_curckt->ci_defTask),taskUid); if(err) { ft_sperror(err,"newTask"); return(NULL); } + for(j=0;jnumAnalyses;j++) { if(strcmp(ft_sim->analyses[j]->name,"options")==0) { which = j; break; } } + if(which != -1) { err = IFnewUid(ckt,&optUid,(IFuid)NULL,"options",UID_ANALYSIS, (void**)NULL); @@ -79,6 +84,7 @@ if_inpdeck(struct line *deck, INPtables **tab) ft_sperror(err,"newUid"); return(NULL); } + err = (*(ft_sim->newAnalysis))(ft_curckt->ci_ckt,which,optUid, (void**)&(ft_curckt->ci_defOpt), (void*)ft_curckt->ci_defTask); @@ -86,33 +92,34 @@ if_inpdeck(struct line *deck, INPtables **tab) ft_sperror(err,"createOptions"); return(NULL); } + ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; } + ft_curckt->ci_curTask = ft_curckt->ci_defTask; INPpas1((void *) ckt, (card *) deck->li_next,(INPtables *)*tab); INPpas2((void *) ckt, (card *) deck->li_next, (INPtables *) *tab,ft_curckt->ci_defTask); INPkillMods(); -/* INPpas2 has been modified to ignore .NODESET and .IC cards. These are - * left till INPpas3 so that we can check for nodeset/ic of non-existant - * nodes. - */ + /* INPpas2 has been modified to ignore .NODESET and .IC + * cards. These are left till INPpas3 so that we can check for + * nodeset/ic of non-existant nodes. */ - INPpas3((GENERIC *) ckt, (card *) deck->li_next, - (INPtables *) *tab,ft_curckt->ci_defTask); + INPpas3((void *) ckt, (card *) deck->li_next, + (INPtables *) *tab,ft_curckt->ci_defTask, ft_sim->nodeParms, + ft_sim->numNodeParms); return (ckt); } -/* Do a run of the circuit, of the given type. Type "resume" is special -- - * it means to resume whatever simulation that was in progress. The - * return value of this routine is 0 if the exit was ok, and 1 if there was - * a reason to interrupt the circuit (interrupt typed at the keyboard, - * error in the simulation, etc). args should be the entire command line, - * e.g. "tran 1 10 20 uic" - */ +/* Do a run of the circuit, of the given type. Type "resume" is + * special -- it means to resume whatever simulation that was in + * progress. The return value of this routine is 0 if the exit was ok, + * and 1 if there was a reason to interrupt the circuit (interrupt + * typed at the keyboard, error in the simulation, etc). args should + * be the entire command line, e.g. "tran 1 10 20 uic" */ int if_run(char *t, char *what, wordlist *args, char *tab) { diff --git a/src/include/cktdefs.h b/src/include/cktdefs.h index e31d8c4d9..b38ff46d6 100644 --- a/src/include/cktdefs.h +++ b/src/include/cktdefs.h @@ -6,10 +6,10 @@ #ifndef CKT #define CKT "CKTdefs.h $Revision$ on $Date$ " -#define MAXNUMDEVS 32 /* Max number of possible devices; */ -extern int DEVmaxnum; /* Not sure if still used */ -#define MAXNUMDEVNODES 4 /* Max No. of nodes per device */ - /* Need to change for SOI devs ? */ +#define MAXNUMDEVS 32 /* Max number of possible devices; */ +extern int DEVmaxnum; /* Not sure if still used */ +#define MAXNUMDEVNODES 4 /* Max No. of nodes per device */ + /* Need to change for SOI devs ? */ #include "smpdefs.h" #include "ifsim.h" @@ -32,13 +32,13 @@ typedef struct sCKTnode { #define NODE_VOLTAGE SP_VOLTAGE #define NODE_CURRENT SP_CURRENT - int number; /* Number of the node */ - double ic; /* Value of the initial condition */ - double nodeset; /* Value of the .nodeset option */ - double *ptr; /* ??? */ - struct sCKTnode *next; /* pointer to the next node */ - unsigned int icGiven:1; /* FLAG ic given */ - unsigned int nsGiven:1; /* FLAG nodeset given */ + int number; /* Number of the node */ + double ic; /* Value of the initial condition */ + double nodeset; /* Value of the .nodeset option */ + double *ptr; /* ??? */ + struct sCKTnode *next; /* pointer to the next node */ + unsigned int icGiven:1; /* FLAG ic given */ + unsigned int nsGiven:1; /* FLAG nodeset given */ } CKTnode; /* defines for node parameters */ @@ -49,11 +49,11 @@ typedef struct sCKTnode { typedef struct { - GENmodel *CKThead[MAXNUMDEVS]; /* The max number of loadable devices */ - STATistics *CKTstat; /* The STATistics structure */ - double *(CKTstates[8]); /* Used as memory of past steps ??? */ + GENmodel *CKThead[MAXNUMDEVS]; /* The max number of loadable devices */ + STATistics *CKTstat; /* The STATistics structure */ + double *(CKTstates[8]); /* Used as memory of past steps ??? */ - /* Some shortcut for CKTstates */ + /* Some shortcut for CKTstates */ #define CKTstate0 CKTstates[0] #define CKTstate1 CKTstates[1] #define CKTstate2 CKTstates[2] @@ -62,40 +62,44 @@ typedef struct { #define CKTstate5 CKTstates[5] #define CKTstate6 CKTstates[6] #define CKTstate7 CKTstates[7] - double CKTtime; /* ??? */ - double CKTdelta; /* ??? */ - double CKTdeltaOld[7]; /* Memory for ??? */ - double CKTtemp; /* Actual temperature of CKT */ - double CKTnomTemp; /* Reference temperature 27 C ? */ - double CKTvt; /* Thernmal voltage at CKTtemp */ - double CKTag[7]; /* the gear variable coefficient matrix */ + double CKTtime; /* ??? */ + double CKTdelta; /* ??? */ + double CKTdeltaOld[7]; /* Memory for ??? */ + double CKTtemp; /* Actual temperature of CKT */ + double CKTnomTemp; /* Reference temperature 27 C ? */ + double CKTvt; /* Thernmal voltage at CKTtemp */ + double CKTag[7]; /* the gear variable coefficient matrix */ #ifdef PREDICTOR - double CKTagp[7]; /* the gear predictor variable coefficient matrix */ + double CKTagp[7]; /* the gear predictor variable + coefficient matrix */ #endif /*PREDICTOR*/ - int CKTorder; /* the integration method order */ - int CKTmaxOrder; /* maximum integration method order */ - int CKTintegrateMethod; /* the integration method to be used */ + int CKTorder; /* the integration method order */ + int CKTmaxOrder; /* maximum integration method order */ + int CKTintegrateMethod; /* the integration method to be used */ /* known integration methods */ #define TRAPEZOIDAL 1 #define GEAR 2 - SMPmatrix *CKTmatrix; /* pointer to sparse matrix */ - int CKTniState; /* internal state */ - double *CKTrhs; /* current rhs value - being loaded */ - double *CKTrhsOld; /* previous rhs value for convergence testing */ - double *CKTrhsSpare; /* spare rhs value for reordering */ - double *CKTirhs; /* current rhs value - being loaded (imag) */ - double *CKTirhsOld; /* previous rhs value (imaginary)*/ - double *CKTirhsSpare; /* spare rhs value (imaginary)*/ + SMPmatrix *CKTmatrix; /* pointer to sparse matrix */ + int CKTniState; /* internal state */ + double *CKTrhs; /* current rhs value - being loaded */ + double *CKTrhsOld; /* previous rhs value for convergence + testing */ + double *CKTrhsSpare; /* spare rhs value for reordering */ + double *CKTirhs; /* current rhs value - being loaded + (imag) */ + double *CKTirhsOld; /* previous rhs value (imaginary)*/ + double *CKTirhsSpare; /* spare rhs value (imaginary)*/ #ifdef PREDICTOR - double *CKTpred; /* predicted solution vector */ - double *CKTsols[8]; /* previous 8 solutions */ + double *CKTpred; /* predicted solution vector */ + double *CKTsols[8]; /* previous 8 solutions */ #endif /* PREDICTOR */ - double *CKTrhsOp; /* opearating point values */ - double *CKTsenRhs; /* current sensitivity rhs values */ - double *CKTseniRhs; /* current sensitivity rhs values (imag)*/ + double *CKTrhsOp; /* opearating point values */ + double *CKTsenRhs; /* current sensitivity rhs values */ + double *CKTseniRhs; /* current sensitivity rhs values + (imag)*/ /* @@ -113,19 +117,21 @@ typedef struct { #define NIDIDPREORDER 0x100 #define NIPZSHOULDREORDER 0x200 - int CKTmaxEqNum; /* And this ? */ - int CKTcurrentAnalysis; /* the analysis in progress (if any) */ + int CKTmaxEqNum; /* And this ? */ + int CKTcurrentAnalysis; /* the analysis in progress (if any) */ /* defines for the value of CKTcurrentAnalysis */ /* are in TSKdefs.h */ - CKTnode *CKTnodes; /* ??? */ - CKTnode *CKTlastNode; /* ??? */ + CKTnode *CKTnodes; /* ??? */ + CKTnode *CKTlastNode; /* ??? */ - /* This define should be somewhere else ??? */ + /* This define should be somewhere else ??? */ #define NODENAME(ckt,nodenum) CKTnodName(ckt,nodenum) - int CKTnumStates; /* Number of sates effectively valid ??? */ - long CKTmode; /* Mode of operation of the circuit ??? */ + int CKTnumStates; /* Number of sates effectively valid + ??? */ + long CKTmode; /* Mode of operation of the circuit + ??? */ /* defines for CKTmode */ @@ -152,72 +158,78 @@ typedef struct { /* old 'nosolv' paramater */ #define MODEUIC 0x10000l - int CKTbypass; /* bypass option, how does it work ? */ - int CKTdcMaxIter; /* iteration limit for dc op. (itl1) */ - int CKTdcTrcvMaxIter; /* iteration limit for dc tran. curv (itl2) */ - int CKTtranMaxIter; /* iteration limit for each timepoint for tran*/ - /* (itl4) */ - int CKTbreakSize; /* ??? */ - int CKTbreak; /* ??? */ - double CKTsaveDelta; /* ??? */ - double CKTminBreak; /* ??? */ - double *CKTbreaks; /* List of breakpoints ??? */ - double CKTabstol; /* --- */ - double CKTpivotAbsTol; /* --- */ - double CKTpivotRelTol; /* --- */ - double CKTreltol; /* --- */ - double CKTchgtol; /* --- */ - double CKTvoltTol; /* --- */ - /* What is this define for ? */ + int CKTbypass; /* bypass option, how does it work ? */ + int CKTdcMaxIter; /* iteration limit for dc op. (itl1) */ + int CKTdcTrcvMaxIter; /* iteration limit for dc tran. curv + (itl2) */ + int CKTtranMaxIter; /* iteration limit for each timepoint + for tran*/ + /* (itl4) */ + int CKTbreakSize; /* ??? */ + int CKTbreak; /* ??? */ + double CKTsaveDelta; /* ??? */ + double CKTminBreak; /* ??? */ + double *CKTbreaks; /* List of breakpoints ??? */ + double CKTabstol; /* --- */ + double CKTpivotAbsTol; /* --- */ + double CKTpivotRelTol; /* --- */ + double CKTreltol; /* --- */ + double CKTchgtol; /* --- */ + double CKTvoltTol; /* --- */ + /* What is this define for ? */ #ifdef NEWTRUNC double CKTlteReltol; double CKTlteAbstol; #endif /* NEWTRUNC */ - double CKTgmin; /* Parallel Conductance --- */ - double CKTgshunt; - double CKTdelmin; /* ??? */ - double CKTtrtol; /* ??? */ - double CKTfinalTime; /* ??? */ - double CKTstep; /* ??? */ - double CKTmaxStep; /* ??? */ - double CKTinitTime; /* ??? */ - double CKTomega; /* ??? */ - double CKTsrcFact; /* ??? */ - double CKTdiagGmin; /* ??? */ - int CKTnumSrcSteps; /* ??? */ - int CKTnumGminSteps; /* ??? */ - double CKTgminFactor; - int CKTnoncon; /* ??? */ - double CKTdefaultMosM; - double CKTdefaultMosL; /* Default Channel Lenght of MOS devices */ - double CKTdefaultMosW; /* Default Channel Width of MOS devics */ - double CKTdefaultMosAD; /* Default Drain Area of MOS */ - double CKTdefaultMosAS; /* Default Source Area of MOS */ - unsigned int CKThadNodeset:1; /* ??? */ - unsigned int CKTfixLimit:1; /* flag to indicate that the limiting of - * MOSFETs should be done as in SPICE2 */ - unsigned int CKTnoOpIter:1; /* flag to indicate not to try the operating - * point brute force, but to use gmin stepping - * first */ - unsigned int CKTisSetup:1; /* flag to indicate if CKTsetup done */ - JOB *CKTcurJob; /* Next analysis to be performed ??? */ + double CKTgmin; /* Parallel Conductance --- */ + double CKTgshunt; + double CKTdelmin; /* ??? */ + double CKTtrtol; /* ??? */ + double CKTfinalTime; /* ??? */ + double CKTstep; /* ??? */ + double CKTmaxStep; /* ??? */ + double CKTinitTime; /* ??? */ + double CKTomega; /* ??? */ + double CKTsrcFact; /* ??? */ + double CKTdiagGmin; /* ??? */ + int CKTnumSrcSteps; /* ??? */ + int CKTnumGminSteps; /* ??? */ + double CKTgminFactor; + int CKTnoncon; /* ??? */ + double CKTdefaultMosM; + double CKTdefaultMosL; /* Default Channel Lenght of MOS devices */ + double CKTdefaultMosW; /* Default Channel Width of MOS devics */ + double CKTdefaultMosAD; /* Default Drain Area of MOS */ + double CKTdefaultMosAS; /* Default Source Area of MOS */ + unsigned int CKThadNodeset:1; /* ??? */ + unsigned int CKTfixLimit:1; /* flag to indicate that the limiting + of MOSFETs should be done as in + SPICE2 */ + unsigned int CKTnoOpIter:1; /* flag to indicate not to try the operating + point brute force, but to use gmin stepping + first */ + unsigned int CKTisSetup:1; /* flag to indicate if CKTsetup done */ + JOB *CKTcurJob; /* Next analysis to be performed ??? */ - SENstruct *CKTsenInfo; /* the sensitivity information */ - double *CKTtimePoints; /* list of all accepted timepoints in the + SENstruct *CKTsenInfo; /* the sensitivity information */ + double *CKTtimePoints; /* list of all accepted timepoints in + the current transient simulation */ + double *CKTdeltaList; /* list of all timesteps in the current transient simulation */ - double *CKTdeltaList; /* list of all timesteps in the current - transient simulation */ - int CKTtimeListSize; /* size of above lists */ - int CKTtimeIndex; /* current position in above lists */ - int CKTsizeIncr; /* amount to increment size of above arrays - when you run out of space */ - unsigned int CKTtryToCompact:1; /* try to compact past history for LTRA - lines */ - unsigned int CKTbadMos3:1; /* Use old, unfixed MOS3 equations */ - unsigned int CKTkeepOpInfo:1; /* flag for small signal analyses */ - unsigned int CKTcopyNodesets:1; /* NodesetFIX */ - int CKTtroubleNode; /* Non-convergent node number */ - GENinstance *CKTtroubleElt; /* Non-convergent device instance */ + int CKTtimeListSize; /* size of above lists */ + int CKTtimeIndex; /* current position in above lists */ + int CKTsizeIncr; /* amount to increment size of above + arrays when you run out of space */ + unsigned int CKTtryToCompact:1; /* try to compact past history for LTRA + lines */ + unsigned int CKTbadMos3:1; /* Use old, unfixed MOS3 equations */ + unsigned int CKTkeepOpInfo:1; /* flag for small signal analyses */ + unsigned int CKTcopyNodesets:1; /* NodesetFIX */ + unsigned int CKTnodeDamping:1; /* flag for node damping fix */ + double CKTabsDv; /* abs limit for iter-iter voltage change */ + double CKTrelDv; /* rel limit for iter-iter voltage change */ + int CKTtroubleNode; /* Non-convergent node number */ + GENinstance *CKTtroubleElt; /* Non-convergent device instance */ } CKTcircuit; @@ -339,7 +351,6 @@ extern int NIpzSym2(PZtrial **, PZtrial *); extern int NIreinit( CKTcircuit *); extern int NIsenReinit( CKTcircuit *); extern int NIdIter (CKTcircuit *); -/*extern int NInzIter (CKTcircuit *, int, int ); */ extern IFfrontEnd *SPfrontEnd; #endif /*CKT*/ diff --git a/src/include/fteext.h b/src/include/fteext.h index fff3fadb3..16c9a6f3d 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -187,8 +187,8 @@ extern void fatal(); extern void fperror(); extern void ft_sperror(); extern char ErrorMessage[]; -extern int internalerror(char *); -extern int externalerror(char *); +extern void internalerror(char *); +extern void externalerror(char *); diff --git a/src/include/inpdefs.h b/src/include/inpdefs.h index 788e3be2a..d5248a31e 100644 --- a/src/include/inpdefs.h +++ b/src/include/inpdefs.h @@ -104,7 +104,7 @@ int INPmakeMod(char*,int,card*); char *INPmkTemp(char*); void INPpas1(void*,card*,INPtables*); void INPpas2(void*,card*,INPtables*,void *); -void INPpas3(void*,card*,INPtables*,void *); +void INPpas3(void*,card*,INPtables*,void *,IFparm*,int); int INPpName(char*,IFvalue*,void*,int,void*); int INPtermInsert(void*,char**,INPtables*,void**); int INPmkTerm(void*,char**,INPtables*,void**); diff --git a/src/include/jobdefs.h b/src/include/jobdefs.h index 71bbe2412..fd47d7959 100644 --- a/src/include/jobdefs.h +++ b/src/include/jobdefs.h @@ -16,17 +16,6 @@ typedef struct sJOB{ } JOB; -typedef struct { - IFanalysis public; - int size; - int domain; - int do_ic; - int (*(setParm))( ); - int (*(askQuest))( ); - int (*an_init)( ); - int (*an_func)( ); -} SPICEanalysis; - #define NODOMAIN 0 #define TIMEDOMAIN 1 #define FREQUENCYDOMAIN 2 diff --git a/src/include/ngspice.h b/src/include/ngspice.h index 7f8a12c5c..e48dd9c5c 100644 --- a/src/include/ngspice.h +++ b/src/include/ngspice.h @@ -95,16 +95,9 @@ struct timeb timebegin; #endif #ifdef HAS_TIME_ -# ifdef HAVE_GETTIMEOFDAY -/* extern char *timezone(); */ /* never used ? (ER) */ -# endif -extern char *asctime(); -extern struct tm *localtime(); +#include #endif -extern char *sbrk(); - - /* Functions declarations from src/misc/[].c */ @@ -122,12 +115,12 @@ extern char *tilde_expand(char *string); extern char *smktemp(char *id); -extern char *copy(); -extern int prefix(); -extern int substring(); -extern void cp_printword(); +extern char *copy(char *str); +extern int prefix(char *p, char *str); +extern int substring(char *sub, char *str); +extern void cp_printword(char *string, FILE *fp); -extern char *datestring(); +extern char *datestring(void); extern double seconds(void); /* Some external variables */ diff --git a/src/include/tskdefs.h b/src/include/tskdefs.h index e1c2b1d7d..c74dcb103 100644 --- a/src/include/tskdefs.h +++ b/src/include/tskdefs.h @@ -34,6 +34,7 @@ typedef struct { /* (itl4) */ int TSKnumSrcSteps; /* number of steps for source stepping */ int TSKnumGminSteps; /* number of steps for Gmin stepping */ + double TSKgminFactor; /* factor for Gmin stepping */ double TSKminBreak; double TSKabstol; double TSKpivotAbsTol; diff --git a/src/main.c b/src/main.c index 44aec719a..749bbbd0d 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -164,6 +165,8 @@ int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator) spice_init_devices(); SIMinfo.numDevices = DEVmaxnum = num_devices(); SIMinfo.devices = devices_ptr(); + SIMinfo.numAnalyses = spice_num_analysis(); + SIMinfo.analyses = spice_analysis_ptr(); #endif /* SIMULATOR */ SPfrontEnd = frontEnd; diff --git a/src/ngspice.c b/src/ngspice.c index 74ad7753f..628003d82 100644 --- a/src/ngspice.c +++ b/src/ngspice.c @@ -20,33 +20,6 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include "suffix.h" -extern SPICEanalysis OPTinfo; -extern SPICEanalysis ACinfo; -extern SPICEanalysis DCTinfo; -extern SPICEanalysis DCOinfo; -extern SPICEanalysis TRANinfo; -extern SPICEanalysis PZinfo; -extern SPICEanalysis TFinfo; -extern SPICEanalysis DISTOinfo; -extern SPICEanalysis NOISEinfo; -extern SPICEanalysis SENSinfo; - - -SPICEanalysis *analInfo[] = { - &OPTinfo, - &ACinfo, - &DCTinfo, - &DCOinfo, - &TRANinfo, - &PZinfo, - &TFinfo, - &DISTOinfo, - &NOISEinfo, - &SENSinfo, - -}; - -int ANALmaxnum = sizeof(analInfo)/sizeof(SPICEanalysis*); /* XXX Should be -1 ? There is always an extra null element at the end ? */ static char * specSigList[] = { "time" @@ -100,9 +73,8 @@ IFsimulator SIMinfo = { 0, /* Initialized in SIMinit() */ NULL, /* Initialized in SIMinit() */ - - sizeof(analInfo)/sizeof(SPICEanalysis *), - (IFanalysis **)analInfo, + 0, /* Initialized in SIMinit() */ + NULL, /* Initialized in SIMinit() */ sizeof(nodeParms)/sizeof(IFparm), nodeParms, diff --git a/src/spicelib/analysis/Makefile.am b/src/spicelib/analysis/Makefile.am index e2e77a4f1..d025034c7 100644 --- a/src/spicelib/analysis/Makefile.am +++ b/src/spicelib/analysis/Makefile.am @@ -6,6 +6,8 @@ libckt_a_SOURCES = \ acan.c \ acaskq.c \ acsetp.c \ + analysis.c \ + analysis.h \ cktacct.c \ cktacdum.c \ cktaskaq.c \ diff --git a/src/spicelib/analysis/acsetp.c b/src/spicelib/analysis/acsetp.c index d4bb6e47b..bc977e1a8 100644 --- a/src/spicelib/analysis/acsetp.c +++ b/src/spicelib/analysis/acsetp.c @@ -5,11 +5,13 @@ Author: 1985 Thomas L. Quarles #include "ngspice.h" #include + #include "ifsim.h" #include "iferrmsg.h" #include "acdefs.h" #include "cktdefs.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/cktaskaq.c b/src/spicelib/analysis/cktaskaq.c index 8fecd3ee9..dbeb8690c 100644 --- a/src/spicelib/analysis/cktaskaq.c +++ b/src/spicelib/analysis/cktaskaq.c @@ -11,6 +11,7 @@ Author: 1985 Thomas L. Quarles #include "ifsim.h" #include "iferrmsg.h" +#include "analysis.h" extern SPICEanalysis *analInfo[]; diff --git a/src/spicelib/analysis/cktdojob.c b/src/spicelib/analysis/cktdojob.c index d1d454016..99a4a3353 100644 --- a/src/spicelib/analysis/cktdojob.c +++ b/src/spicelib/analysis/cktdojob.c @@ -10,9 +10,9 @@ Modified: 2000 AlansFixes #include "sperror.h" #include "trandefs.h" +#include "analysis.h" extern SPICEanalysis *analInfo[]; -extern int ANALmaxnum; int CKTdoJob(void *inCkt, int reset, void *inTask) @@ -22,6 +22,7 @@ CKTdoJob(void *inCkt, int reset, void *inTask) JOB *job; double startTime; int error, i, error2; + int ANALmaxnum; #ifdef WANT_SENSE2 int senflag; @@ -36,6 +37,8 @@ CKTdoJob(void *inCkt, int reset, void *inTask) } #endif + ANALmaxnum = spice_num_analysis(); + startTime = (*(SPfrontEnd->IFseconds))( ); ckt->CKTtemp = task->TSKtemp; diff --git a/src/spicelib/analysis/cktnewan.c b/src/spicelib/analysis/cktnewan.c index 63e10fe29..d8900884e 100644 --- a/src/spicelib/analysis/cktnewan.c +++ b/src/spicelib/analysis/cktnewan.c @@ -5,11 +5,14 @@ Author: 1985 Thomas L. Quarles #include "ngspice.h" #include + #include "tskdefs.h" #include "jobdefs.h" #include "ifsim.h" #include "iferrmsg.h" +#include +#include "analysis.h" extern SPICEanalysis *analInfo[]; diff --git a/src/spicelib/analysis/cktsetap.c b/src/spicelib/analysis/cktsetap.c index f0c00e6f0..b6f9d75fc 100644 --- a/src/spicelib/analysis/cktsetap.c +++ b/src/spicelib/analysis/cktsetap.c @@ -11,6 +11,7 @@ Author: 1985 Thomas L. Quarles #include "iferrmsg.h" #include "cktdefs.h" +#include "analysis.h" extern SPICEanalysis *analInfo[]; diff --git a/src/spicelib/analysis/cktsopt.c b/src/spicelib/analysis/cktsopt.c index 226bd07f9..3f9f72285 100644 --- a/src/spicelib/analysis/cktsopt.c +++ b/src/spicelib/analysis/cktsopt.c @@ -19,6 +19,7 @@ Modified: 2000 AlansFixes #include "cktdefs.h" #include "sperror.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/ckttroub.c b/src/spicelib/analysis/ckttroub.c index 0cdca9bd3..86541a15d 100644 --- a/src/spicelib/analysis/ckttroub.c +++ b/src/spicelib/analysis/ckttroub.c @@ -11,6 +11,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include "isrc/isrcdefs.h" #include "jobdefs.h" +#include "analysis.h" extern SPICEdev *DEVices[]; extern SPICEanalysis *analInfo[]; diff --git a/src/spicelib/analysis/dcosetp.c b/src/spicelib/analysis/dcosetp.c index 31d507c65..bcf174223 100644 --- a/src/spicelib/analysis/dcosetp.c +++ b/src/spicelib/analysis/dcosetp.c @@ -11,6 +11,8 @@ Author: 1985 Thomas L. Quarles #include "opdefs.h" +#include "analysis.h" + /* ARGSUSED */ int DCOsetParm(CKTcircuit *ckt, void *anal, int which, IFvalue *value) diff --git a/src/spicelib/analysis/dctsetp.c b/src/spicelib/analysis/dctsetp.c index d9dc3d063..a596e9445 100644 --- a/src/spicelib/analysis/dctsetp.c +++ b/src/spicelib/analysis/dctsetp.c @@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles #include "trcvdefs.h" #include "cktdefs.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/dsetparm.c b/src/spicelib/analysis/dsetparm.c index fc96b0606..e04d21ed5 100644 --- a/src/spicelib/analysis/dsetparm.c +++ b/src/spicelib/analysis/dsetparm.c @@ -10,6 +10,7 @@ Author: 1988 Jaijeet S Roychowdhury #include "cktdefs.h" #include "distodef.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/nsetparm.c b/src/spicelib/analysis/nsetparm.c index d1e932178..0e6ef3f7c 100644 --- a/src/spicelib/analysis/nsetparm.c +++ b/src/spicelib/analysis/nsetparm.c @@ -10,6 +10,7 @@ Author: 1987 Gary W. Ng #include "iferrmsg.h" #include "noisedef.h" +#include "analysis.h" int NsetParm(CKTcircuit *ckt, void *anal, int which, IFvalue *value) diff --git a/src/spicelib/analysis/pzsetp.c b/src/spicelib/analysis/pzsetp.c index 6e2822542..6b1e95e6a 100644 --- a/src/spicelib/analysis/pzsetp.c +++ b/src/spicelib/analysis/pzsetp.c @@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles #include "pzdefs.h" #include "cktdefs.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/senssetp.c b/src/spicelib/analysis/senssetp.c index d7751619f..cf5ee8a21 100644 --- a/src/spicelib/analysis/senssetp.c +++ b/src/spicelib/analysis/senssetp.c @@ -9,6 +9,7 @@ Copyright 1991 Regents of the University of California. All rights reserved. #include "cktdefs.h" #include "sensdefs.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/tfsetp.c b/src/spicelib/analysis/tfsetp.c index 411d78829..2d8952e72 100644 --- a/src/spicelib/analysis/tfsetp.c +++ b/src/spicelib/analysis/tfsetp.c @@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles #include "tfdefs.h" #include "cktdefs.h" +#include "analysis.h" /* ARGSUSED */ int diff --git a/src/spicelib/analysis/transetp.c b/src/spicelib/analysis/transetp.c index 1c81b851a..0594e87a0 100644 --- a/src/spicelib/analysis/transetp.c +++ b/src/spicelib/analysis/transetp.c @@ -10,6 +10,8 @@ Author: 1985 Thomas L. Quarles #include "trandefs.h" #include "cktdefs.h" +#include "analysis.h" + /* ARGSUSED */ int TRANsetParm(CKTcircuit *ckt, void *anal, int which, IFvalue *value) diff --git a/src/spicelib/devices/bjt/bjtdset.h b/src/spicelib/devices/bjt/bjtdset.h index b13f82662..d3b28685c 100644 --- a/src/spicelib/devices/bjt/bjtdset.h +++ b/src/spicelib/devices/bjt/bjtdset.h @@ -1,6 +1,6 @@ #ifndef __BJTDSET_H #define __BJTDSET_H -int BJTdSetup(BJTmodel *inModel, CKTcircuit *ckt); +int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt); #endif diff --git a/src/spicelib/devices/bjt/bjtext.h b/src/spicelib/devices/bjt/bjtext.h index 18b675bf5..fa0c77edd 100644 --- a/src/spicelib/devices/bjt/bjtext.h +++ b/src/spicelib/devices/bjt/bjtext.h @@ -3,8 +3,10 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AnalsFixes **********/ +#ifndef __BJTEXT_H +#define __BJTEXT_H + -#ifdef __STDC__ extern int BJTacLoad(GENmodel *,CKTcircuit*); extern int BJTask(CKTcircuit *,GENinstance*,int,IFvalue*,IFvalue*); extern int BJTconvTest(GENmodel*,CKTcircuit*); @@ -31,29 +33,4 @@ extern int BJTnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BJTdSetup(GENmodel*, register CKTcircuit*); -#else /* stdc */ -extern int BJTacLoad(); -extern int BJTask(); -extern int BJTconvTest(); -extern int BJTdelete(); -extern void BJTdestroy(); -extern int BJTgetic(); -extern int BJTload(); -extern int BJTmAsk(); -extern int BJTmDelete(); -extern int BJTmParam(); -extern int BJTparam(); -extern int BJTpzLoad(); -extern int BJTsAcLoad(); -extern int BJTsLoad(); -extern void BJTsPrint(); -extern int BJTsSetup(); -extern int BJTsUpdate(); -extern int BJTsetup(); -extern int BJTunsetup(); -extern int BJTtemp(); -extern int BJTtrunc(); -extern int BJTdisto(); -extern int BJTnoise(); -#endif /* stdc */ - +#endif diff --git a/src/spicelib/devices/bjt/bjtsetup.c b/src/spicelib/devices/bjt/bjtsetup.c index 3fb4bb39e..bce2a9da0 100644 --- a/src/spicelib/devices/bjt/bjtsetup.c +++ b/src/spicelib/devices/bjt/bjtsetup.c @@ -149,11 +149,12 @@ BJTsetup(matrix,inModel,ckt,states) /* loop through all the instances of the model */ for (here = model->BJTinstances; here != NULL ; here=here->BJTnextInstance) { - if (here->BJTowner != ARCHme) goto matrixpointers; - - CKTnode *tmpNode; - IFuid tmpName; + CKTnode *tmpNode; + IFuid tmpName; + if (here->BJTowner != ARCHme) + goto matrixpointers; + if(!here->BJTareaGiven) { here->BJTarea = 1; } diff --git a/src/spicelib/devices/bsim2/b2set.c b/src/spicelib/devices/bsim2/b2set.c index 002f6ad99..e54dadd33 100644 --- a/src/spicelib/devices/bsim2/b2set.c +++ b/src/spicelib/devices/bsim2/b2set.c @@ -492,16 +492,19 @@ B2setup(matrix,inModel,ckt,states) (here->B2drainSquares != 0.0 ) && (here->B2dNodePrime == 0) ) { error = CKTmkVolt(ckt,&tmp,here->B2name,"drain"); - if(error) return(error); + if(error) return(error); here->B2dNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { - if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { - if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; - } - } - } + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->B2dNodePrime = here->B2dNode; } @@ -512,14 +515,18 @@ B2setup(matrix,inModel,ckt,states) (here->B2sNodePrime == 0) ) { if(here->B2sNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->B2name,"source"); - if(error) return(error); + if(error) + return(error); here->B2sNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { - if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { - if (tmpNode->nsGiven) { - tmp->nodeset=tmpNode->nodeset; - tmp->nsGiven=tmpNode->nsGiven; - } + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } } } } diff --git a/src/spicelib/devices/bsim3/b3acld.c b/src/spicelib/devices/bsim3/b3acld.c index e064f6397..480ee12ee 100644 --- a/src/spicelib/devices/bsim3/b3acld.c +++ b/src/spicelib/devices/bsim3/b3acld.c @@ -15,325 +15,317 @@ File: b3acld.c int -BSIM3acLoad(inModel,ckt) -GENmodel *inModel; -CKTcircuit *ckt; +BSIM3acLoad(GENmodel *inModel, CKTcircuit *ckt) { -BSIM3model *model = (BSIM3model*)inModel; -BSIM3instance *here; -double xcggb, xcgdb, xcgsb, xcbgb, xcbdb, xcbsb, xcddb, xcssb, xcdgb; -double gdpr, gspr, gds, gbd, gbs, capbd, capbs, xcsgb, xcdsb, xcsdb; -double cggb, cgdb, cgsb, cbgb, cbdb, cbsb, cddb, cdgb, cdsb, omega; -double GSoverlapCap, GDoverlapCap, GBoverlapCap, FwdSum, RevSum, Gm, Gmbs; -double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb, xcqdb, xcqsb, xcqbb; -double gbspsp, gbbdp, gbbsp, gbspg, gbspb; -double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; -double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; -double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; -double T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; -double ScalingFactor = 1.0e-9; - + BSIM3model *model = (BSIM3model*)inModel; + BSIM3instance *here; + double xcggb, xcgdb, xcgsb, xcbgb, xcbdb, xcbsb, xcddb, xcssb, xcdgb; + double gdpr, gspr, gds, gbd, gbs, capbd, capbs, xcsgb, xcdsb, xcsdb; + double cggb, cgdb, cgsb, cbgb, cbdb, cbsb, cddb, cdgb, cdsb, omega; + double GSoverlapCap, GDoverlapCap, GBoverlapCap, FwdSum, RevSum, Gm, Gmbs; + double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb, xcqdb, xcqsb, xcqbb; + double gbspsp, gbbdp, gbbsp, gbspg, gbspb; + double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; + double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; + double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; + double T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; + double ScalingFactor = 1.0e-9; + double m; + omega = ckt->CKTomega; - for (; model != NULL; model = model->BSIM3nextModel) - { for (here = model->BSIM3instances; here!= NULL; - here = here->BSIM3nextInstance) { - if (here->BSIM3owner != ARCHme) continue; - if (here->BSIM3mode >= 0) - { Gm = here->BSIM3gm; - Gmbs = here->BSIM3gmbs; - FwdSum = Gm + Gmbs; - RevSum = 0.0; + for (; model != NULL; model = model->BSIM3nextModel) { + for (here = model->BSIM3instances; here!= NULL; + here = here->BSIM3nextInstance) { + if (here->BSIM3owner != ARCHme) + continue; + if (here->BSIM3mode >= 0) { + Gm = here->BSIM3gm; + Gmbs = here->BSIM3gmbs; + FwdSum = Gm + Gmbs; + RevSum = 0.0; - gbbdp = -here->BSIM3gbds; - gbbsp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + gbbdp = -here->BSIM3gbds; + gbbsp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; - gbdpg = here->BSIM3gbgs; - gbdpb = here->BSIM3gbbs; - gbdpdp = here->BSIM3gbds; - gbdpsp = -(gbdpg + gbdpb + gbdpdp); + gbdpg = here->BSIM3gbgs; + gbdpb = here->BSIM3gbbs; + gbdpdp = here->BSIM3gbds; + gbdpsp = -(gbdpg + gbdpb + gbdpdp); + + gbspdp = 0.0; + gbspg = 0.0; + gbspb = 0.0; + gbspsp = 0.0; - gbspdp = 0.0; - gbspg = 0.0; - gbspb = 0.0; - gbspsp = 0.0; + if (here->BSIM3nqsMod == 0) { + cggb = here->BSIM3cggb; + cgsb = here->BSIM3cgsb; + cgdb = here->BSIM3cgdb; - if (here->BSIM3nqsMod == 0) - { cggb = here->BSIM3cggb; - cgsb = here->BSIM3cgsb; - cgdb = here->BSIM3cgdb; + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbsb; + cbdb = here->BSIM3cbdb; - cbgb = here->BSIM3cbgb; - cbsb = here->BSIM3cbsb; - cbdb = here->BSIM3cbdb; + cdgb = here->BSIM3cdgb; + cdsb = here->BSIM3cdsb; + cddb = here->BSIM3cddb; - cdgb = here->BSIM3cdgb; - cdsb = here->BSIM3cdsb; - cddb = here->BSIM3cddb; + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.6; + dxpart = 0.4; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } else { + cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; - xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.6; - dxpart = 0.4; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { cggb = cgdb = cgsb = 0.0; - cbgb = cbdb = cbsb = 0.0; - cdgb = cddb = cdsb = 0.0; - - xgtg = here->BSIM3gtg; - xgtd = here->BSIM3gtd; - xgts = here->BSIM3gts; - xgtb = here->BSIM3gtb; + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gtd; + xgts = here->BSIM3gts; + xgtb = here->BSIM3gtb; - xcqgb = here->BSIM3cqgb * omega; - xcqdb = here->BSIM3cqdb * omega; - xcqsb = here->BSIM3cqsb * omega; - xcqbb = here->BSIM3cqbb * omega; + xcqgb = here->BSIM3cqgb * omega; + xcqdb = here->BSIM3cqdb * omega; + xcqsb = here->BSIM3cqsb * omega; + xcqbb = here->BSIM3cqbb * omega; - CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV - * here->pParam->BSIM3leffCV; - qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3xpart < 0.5) - { dxpart = 0.4; - } - else if (model->BSIM3xpart > 0.5) - { dxpart = 0.0; - } - else - { dxpart = 0.5; - } - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - } - else - { dxpart = here->BSIM3qdrn / qcheq; - Cdd = here->BSIM3cddb; - Csd = -(here->BSIM3cgdb + here->BSIM3cddb - + here->BSIM3cbdb); - ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; - Cdg = here->BSIM3cdgb; - Csg = -(here->BSIM3cggb + here->BSIM3cdgb - + here->BSIM3cbgb); - ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) { + if (model->BSIM3xpart < 0.5) { + dxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) { + dxpart = 0.0; + } else { + dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } else { + dxpart = here->BSIM3qdrn / qcheq; + Cdd = here->BSIM3cddb; + Csd = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3cdgb; + Csg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; - Cds = here->BSIM3cdsb; - Css = -(here->BSIM3cgsb + here->BSIM3cdsb - + here->BSIM3cbsb); - ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + Cds = here->BSIM3cdsb; + Css = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg - + ddxpart_dVs); - } - sxpart = 1.0 - dxpart; - dsxpart_dVd = -ddxpart_dVd; - dsxpart_dVg = -ddxpart_dVg; - dsxpart_dVs = -ddxpart_dVs; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); - } - } - else - { Gm = -here->BSIM3gm; - Gmbs = -here->BSIM3gmbs; - FwdSum = 0.0; - RevSum = -(Gm + Gmbs); + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + } + } else { + Gm = -here->BSIM3gm; + Gmbs = -here->BSIM3gmbs; + FwdSum = 0.0; + RevSum = -(Gm + Gmbs); - gbbsp = -here->BSIM3gbds; - gbbdp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + gbbsp = -here->BSIM3gbds; + gbbdp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; - gbdpg = 0.0; - gbdpsp = 0.0; - gbdpb = 0.0; - gbdpdp = 0.0; + gbdpg = 0.0; + gbdpsp = 0.0; + gbdpb = 0.0; + gbdpdp = 0.0; - gbspg = here->BSIM3gbgs; - gbspsp = here->BSIM3gbds; - gbspb = here->BSIM3gbbs; - gbspdp = -(gbspg + gbspsp + gbspb); + gbspg = here->BSIM3gbgs; + gbspsp = here->BSIM3gbds; + gbspb = here->BSIM3gbbs; + gbspdp = -(gbspg + gbspsp + gbspb); - if (here->BSIM3nqsMod == 0) - { cggb = here->BSIM3cggb; - cgsb = here->BSIM3cgdb; - cgdb = here->BSIM3cgsb; + if (here->BSIM3nqsMod == 0) { + cggb = here->BSIM3cggb; + cgsb = here->BSIM3cgdb; + cgdb = here->BSIM3cgsb; - cbgb = here->BSIM3cbgb; - cbsb = here->BSIM3cbdb; - cbdb = here->BSIM3cbsb; + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbdb; + cbdb = here->BSIM3cbsb; - cdgb = -(here->BSIM3cdgb + cggb + cbgb); - cdsb = -(here->BSIM3cddb + cgsb + cbsb); - cddb = -(here->BSIM3cdsb + cgdb + cbdb); + cdgb = -(here->BSIM3cdgb + cggb + cbgb); + cdsb = -(here->BSIM3cddb + cgsb + cbsb); + cddb = -(here->BSIM3cdsb + cgdb + cbdb); - xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.4; - dxpart = 0.6; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { cggb = cgdb = cgsb = 0.0; - cbgb = cbdb = cbsb = 0.0; - cdgb = cddb = cdsb = 0.0; + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.4; + dxpart = 0.6; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } else { + cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; - xgtg = here->BSIM3gtg; - xgtd = here->BSIM3gts; - xgts = here->BSIM3gtd; - xgtb = here->BSIM3gtb; + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gts; + xgts = here->BSIM3gtd; + xgtb = here->BSIM3gtb; - xcqgb = here->BSIM3cqgb * omega; - xcqdb = here->BSIM3cqsb * omega; - xcqsb = here->BSIM3cqdb * omega; - xcqbb = here->BSIM3cqbb * omega; + xcqgb = here->BSIM3cqgb * omega; + xcqdb = here->BSIM3cqsb * omega; + xcqsb = here->BSIM3cqdb * omega; + xcqbb = here->BSIM3cqbb * omega; - CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV - * here->pParam->BSIM3leffCV; - qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3xpart < 0.5) - { sxpart = 0.4; - } - else if (model->BSIM3xpart > 0.5) - { sxpart = 0.0; - } - else - { sxpart = 0.5; - } - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { sxpart = here->BSIM3qdrn / qcheq; - Css = here->BSIM3cddb; - Cds = -(here->BSIM3cgdb + here->BSIM3cddb - + here->BSIM3cbdb); - dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; - Csg = here->BSIM3cdgb; - Cdg = -(here->BSIM3cggb + here->BSIM3cdgb - + here->BSIM3cbgb); - dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) { + if (model->BSIM3xpart < 0.5) { + sxpart = 0.4; + } else if (model->BSIM3xpart > 0.5) { + sxpart = 0.0; + } else { + sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } else { + sxpart = here->BSIM3qdrn / qcheq; + Css = here->BSIM3cddb; + Cds = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3cdgb; + Cdg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; - Csd = here->BSIM3cdsb; - Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb - + here->BSIM3cbsb); - dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + Csd = here->BSIM3cdsb; + Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg - + dsxpart_dVs); - } - dxpart = 1.0 - sxpart; - ddxpart_dVd = -dsxpart_dVd; - ddxpart_dVg = -dsxpart_dVg; - ddxpart_dVs = -dsxpart_dVs; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); - } - } + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + } + } - T1 = *(ckt->CKTstate0 + here->BSIM3qdef) * here->BSIM3gtau; - gdpr = here->BSIM3drainConductance; - gspr = here->BSIM3sourceConductance; - gds = here->BSIM3gds; - gbd = here->BSIM3gbd; - gbs = here->BSIM3gbs; - capbd = here->BSIM3capbd; - capbs = here->BSIM3capbs; + T1 = *(ckt->CKTstate0 + here->BSIM3qdef) * here->BSIM3gtau; + gdpr = here->BSIM3drainConductance; + gspr = here->BSIM3sourceConductance; + gds = here->BSIM3gds; + gbd = here->BSIM3gbd; + gbs = here->BSIM3gbs; + capbd = here->BSIM3capbd; + capbs = here->BSIM3capbs; - GSoverlapCap = here->BSIM3cgso; - GDoverlapCap = here->BSIM3cgdo; - GBoverlapCap = here->pParam->BSIM3cgbo; + GSoverlapCap = here->BSIM3cgso; + GDoverlapCap = here->BSIM3cgdo; + GBoverlapCap = here->pParam->BSIM3cgbo; - xcdgb = (cdgb - GDoverlapCap) * omega; - xcddb = (cddb + capbd + GDoverlapCap) * omega; - xcdsb = cdsb * omega; - xcsgb = -(cggb + cbgb + cdgb + GSoverlapCap) * omega; - xcsdb = -(cgdb + cbdb + cddb) * omega; - xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)) * omega; - xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap) - * omega; - xcgdb = (cgdb - GDoverlapCap ) * omega; - xcgsb = (cgsb - GSoverlapCap) * omega; - xcbgb = (cbgb - GBoverlapCap) * omega; - xcbdb = (cbdb - capbd ) * omega; - xcbsb = (cbsb - capbs ) * omega; + xcdgb = (cdgb - GDoverlapCap) * omega; + xcddb = (cddb + capbd + GDoverlapCap) * omega; + xcdsb = cdsb * omega; + xcsgb = -(cggb + cbgb + cdgb + GSoverlapCap) * omega; + xcsdb = -(cgdb + cbdb + cddb) * omega; + xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)) * omega; + xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap) + * omega; + xcgdb = (cgdb - GDoverlapCap ) * omega; + xcgsb = (cgsb - GSoverlapCap) * omega; + xcbgb = (cbgb - GBoverlapCap) * omega; + xcbdb = (cbdb - capbd ) * omega; + xcbsb = (cbsb - capbs ) * omega; - m = here->BSIM3m; + m = here->BSIM3m; - *(here->BSIM3GgPtr +1) += m * xcggb; - *(here->BSIM3BbPtr +1) -= xcbgb + xcbdb + xcbsb; - *(here->BSIM3DPdpPtr +1) += m * xcddb; - *(here->BSIM3SPspPtr +1) += m * xcssb; - *(here->BSIM3GbPtr +1) -= xcggb + xcgdb + xcgsb; - *(here->BSIM3GdpPtr +1) += m * xcgdb; - *(here->BSIM3GspPtr +1) += m * xcgsb; - *(here->BSIM3BgPtr +1) += m * xcbgb; - *(here->BSIM3BdpPtr +1) += m * xcbdb; - *(here->BSIM3BspPtr +1) += m * xcbsb; - *(here->BSIM3DPgPtr +1) += m * xcdgb; - *(here->BSIM3DPbPtr +1) -= xcdgb + xcddb + xcdsb; - *(here->BSIM3DPspPtr +1) += m * xcdsb; - *(here->BSIM3SPgPtr +1) += m * xcsgb; - *(here->BSIM3SPbPtr +1) -= xcsgb + xcsdb + xcssb; - *(here->BSIM3SPdpPtr +1) += m * xcsdb; + *(here->BSIM3GgPtr +1) += m * xcggb; + *(here->BSIM3BbPtr +1) -= xcbgb + xcbdb + xcbsb; + *(here->BSIM3DPdpPtr +1) += m * xcddb; + *(here->BSIM3SPspPtr +1) += m * xcssb; + *(here->BSIM3GbPtr +1) -= xcggb + xcgdb + xcgsb; + *(here->BSIM3GdpPtr +1) += m * xcgdb; + *(here->BSIM3GspPtr +1) += m * xcgsb; + *(here->BSIM3BgPtr +1) += m * xcbgb; + *(here->BSIM3BdpPtr +1) += m * xcbdb; + *(here->BSIM3BspPtr +1) += m * xcbsb; + *(here->BSIM3DPgPtr +1) += m * xcdgb; + *(here->BSIM3DPbPtr +1) -= xcdgb + xcddb + xcdsb; + *(here->BSIM3DPspPtr +1) += m * xcdsb; + *(here->BSIM3SPgPtr +1) += m * xcsgb; + *(here->BSIM3SPbPtr +1) -= xcsgb + xcsdb + xcssb; + *(here->BSIM3SPdpPtr +1) += m * xcsdb; - *(here->BSIM3DdPtr) += m * gdpr; - *(here->BSIM3SsPtr) += m * gspr; - *(here->BSIM3BbPtr) += m * (gbd + gbs - here->BSIM3gbbs); - *(here->BSIM3DPdpPtr) += m * (gdpr + gds + gbd + RevSum - +dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp); - *(here->BSIM3SPspPtr) += m * (gspr + gds + gbs + FwdSum - +sxpart * xgts + T1 * dsxpart_dVs + gbspsp); + *(here->BSIM3DdPtr) += m * gdpr; + *(here->BSIM3SsPtr) += m * gspr; + *(here->BSIM3BbPtr) += m * (gbd + gbs - here->BSIM3gbbs); + *(here->BSIM3DPdpPtr) += m * (gdpr + gds + gbd + RevSum + +dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp); + *(here->BSIM3SPspPtr) += m * (gspr + gds + gbs + FwdSum + +sxpart * xgts + T1 * dsxpart_dVs + gbspsp); - *(here->BSIM3DdpPtr) -= m * gdpr; - *(here->BSIM3SspPtr) -= m * gspr; + *(here->BSIM3DdpPtr) -= m * gdpr; + *(here->BSIM3SspPtr) -= m * gspr; - *(here->BSIM3BgPtr) -= m * here->BSIM3gbgs; - *(here->BSIM3BdpPtr) -= m * (gbd - gbbdp); - *(here->BSIM3BspPtr) -= m * (gbs - gbbsp); + *(here->BSIM3BgPtr) -= m * here->BSIM3gbgs; + *(here->BSIM3BdpPtr) -= m * (gbd - gbbdp); + *(here->BSIM3BspPtr) -= m * (gbs - gbbsp); - *(here->BSIM3DPdPtr) -= m * gdpr; - *(here->BSIM3DPgPtr) += m * (Gm + dxpart * xgtg + T1 * ddxpart_dVg - + gbdpg); - *(here->BSIM3DPbPtr) -= m * (gbd - Gmbs - dxpart * xgtb - - T1 * ddxpart_dVb - gbdpb); - *(here->BSIM3DPspPtr) -= m * (gds + FwdSum - dxpart * xgts - - T1 * ddxpart_dVs - gbdpsp); + *(here->BSIM3DPdPtr) -= m * gdpr; + *(here->BSIM3DPgPtr) += m * (Gm + dxpart * xgtg + T1 * ddxpart_dVg + + gbdpg); + *(here->BSIM3DPbPtr) -= m * (gbd - Gmbs - dxpart * xgtb + - T1 * ddxpart_dVb - gbdpb); + *(here->BSIM3DPspPtr) -= m * (gds + FwdSum - dxpart * xgts + - T1 * ddxpart_dVs - gbdpsp); - *(here->BSIM3SPgPtr) -= m * (Gm - sxpart * xgtg - T1 * dsxpart_dVg - - gbspg); - *(here->BSIM3SPsPtr) -= m * gspr; - *(here->BSIM3SPbPtr) -= m * (gbs + Gmbs - sxpart * xgtb - - T1 * dsxpart_dVb - gbspb); - *(here->BSIM3SPdpPtr) -= m * (gds + RevSum - sxpart * xgtd - - T1 * dsxpart_dVd - gbspdp); + *(here->BSIM3SPgPtr) -= m * (Gm - sxpart * xgtg - T1 * dsxpart_dVg + - gbspg); + *(here->BSIM3SPsPtr) -= m * gspr; + *(here->BSIM3SPbPtr) -= m * (gbs + Gmbs - sxpart * xgtb + - T1 * dsxpart_dVb - gbspb); + *(here->BSIM3SPdpPtr) -= m * (gds + RevSum - sxpart * xgtd + - T1 * dsxpart_dVd - gbspdp); - *(here->BSIM3GgPtr) -= m * xgtg; - *(here->BSIM3GbPtr) -= m * xgtb; - *(here->BSIM3GdpPtr) -= m * xgtd; - *(here->BSIM3GspPtr) -= m * xgts; + *(here->BSIM3GgPtr) -= m * xgtg; + *(here->BSIM3GbPtr) -= m * xgtb; + *(here->BSIM3GdpPtr) -= m * xgtd; + *(here->BSIM3GspPtr) -= m * xgts; - if (here->BSIM3nqsMod) - { *(here->BSIM3QqPtr +1) += m * (omega * ScalingFactor); - *(here->BSIM3QgPtr +1) -= m * xcqgb; - *(here->BSIM3QdpPtr +1) -= m * xcqdb; - *(here->BSIM3QspPtr +1) -= m * xcqsb; - *(here->BSIM3QbPtr +1) -= m * xcqbb; + if (here->BSIM3nqsMod) { + *(here->BSIM3QqPtr +1) += m * (omega * ScalingFactor); + *(here->BSIM3QgPtr +1) -= m * xcqgb; + *(here->BSIM3QdpPtr +1) -= m * xcqdb; + *(here->BSIM3QspPtr +1) -= m * xcqsb; + *(here->BSIM3QbPtr +1) -= m * xcqbb; - *(here->BSIM3QqPtr) += m * here->BSIM3gtau; + *(here->BSIM3QqPtr) += m * here->BSIM3gtau; - *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); - *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); - *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; - *(here->BSIM3QgPtr) += m * xgtg; - *(here->BSIM3QdpPtr) += m * xgtd; - *(here->BSIM3QspPtr) += m * xgts; - *(here->BSIM3QbPtr) += m * xgtb; - } + *(here->BSIM3QgPtr) += m * xgtg; + *(here->BSIM3QdpPtr) += m * xgtd; + *(here->BSIM3QspPtr) += m * xgts; + *(here->BSIM3QbPtr) += m * xgtb; + } } } return(OK); diff --git a/src/spicelib/devices/bsim3/b3set.c b/src/spicelib/devices/bsim3/b3set.c index 4cab7307a..93a7d9142 100644 --- a/src/spicelib/devices/bsim3/b3set.c +++ b/src/spicelib/devices/bsim3/b3set.c @@ -851,9 +851,6 @@ CKTnode *tmp; if (here->BSIM3owner == ARCHme) { /* allocate a chunk of the state vector */ - CKTnode *tmpNode; - IFuid tmpName; - here->BSIM3states = *states; *states += BSIM3numStates; } @@ -891,10 +888,14 @@ CKTnode *tmp; if ((model->BSIM3sheetResistance > 0.0) && (here->BSIM3drainSquares > 0.0 ) && (here->BSIM3dNodePrime == 0)) - { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain"); + { + error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain"); if(error) return(error); here->BSIM3dNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; @@ -915,6 +916,9 @@ CKTnode *tmp; if(error) return(error); here->BSIM3sNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; diff --git a/src/spicelib/devices/bsim3/bsim3def.h b/src/spicelib/devices/bsim3/bsim3def.h index c9ff5120f..503760afe 100644 --- a/src/spicelib/devices/bsim3/bsim3def.h +++ b/src/spicelib/devices/bsim3/bsim3def.h @@ -21,7 +21,6 @@ typedef struct sBSIM3instance struct sBSIM3instance *BSIM3nextInstance; IFuid BSIM3name; int BSIM3owner; /* number of owner process */ - int BSIM3states; /* index into state table for this device */ int BSIM3dNode; int BSIM3gNode; int BSIM3sNode; @@ -44,6 +43,7 @@ typedef struct sBSIM3instance double BSIM3l; double BSIM3w; + double BSIM3m; double BSIM3drainArea; double BSIM3sourceArea; double BSIM3drainSquares; @@ -154,7 +154,7 @@ typedef struct sBSIM3instance double *BSIM3SPqPtr; double *BSIM3BqPtr; -int BSIM3states; /* index into state table for this device */ + int BSIM3states; /* index into state table for this device */ #define BSIM3vbd BSIM3states+ 0 #define BSIM3vbs BSIM3states+ 1 #define BSIM3vgs BSIM3states+ 2 diff --git a/src/spicelib/devices/csw/cswtrunc.c b/src/spicelib/devices/csw/cswtrunc.c index 47ca868a8..9a13a40bf 100644 --- a/src/spicelib/devices/csw/cswtrunc.c +++ b/src/spicelib/devices/csw/cswtrunc.c @@ -6,22 +6,19 @@ Modified: 2000 AlansFixes /* */ -#include "spice.h" +#include "ngspice.h" #include #include "cktdefs.h" -#include "csw\cswdefs.h" #include "sperror.h" #include "suffix.h" +#include "cswdefs.h" int -CSWtrunc(inModel,ckt,timeStep) - GENmodel *inModel; - register CKTcircuit *ckt; - register double *timeStep; +CSWtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) { - register CSWmodel *model = (CSWmodel*)inModel; - register CSWinstance *here; + CSWmodel *model = (CSWmodel*)inModel; + CSWinstance *here; double lastChange, maxChange, maxStep, ref; diff --git a/src/spicelib/devices/dio/diodset.c b/src/spicelib/devices/dio/diodset.c index cde4ca158..9c6e3637e 100644 --- a/src/spicelib/devices/dio/diodset.c +++ b/src/spicelib/devices/dio/diodset.c @@ -11,14 +11,11 @@ Author: 1988 Jaijeet S Roychowdhury #include "sperror.h" #include "suffix.h" -int -DIOdSetup(model,ckt) -DIOmodel *model; -CKTcircuit *ckt; -/* actually load the current resistance value into the - * sparse matrix previously provided - */ +/* actually load the current resistance value into the sparse matrix + * previously provided */ +int +DIOdSetup(DIOmodel *model, CKTcircuit *ckt) { DIOinstance *here; double arg; diff --git a/src/spicelib/devices/dio/dioinit.c b/src/spicelib/devices/dio/dioinit.c index 6da96e4c4..b1d673ac8 100644 --- a/src/spicelib/devices/dio/dioinit.c +++ b/src/spicelib/devices/dio/dioinit.c @@ -1,7 +1,9 @@ #include #include +#include +#include "diodefs.h" #include "dioitf.h" #include "dioext.h" #include "dioinit.h" diff --git a/src/spicelib/devices/jfet/jfetset.c b/src/spicelib/devices/jfet/jfetset.c index 5948c32ba..e0d592194 100644 --- a/src/spicelib/devices/jfet/jfetset.c +++ b/src/spicelib/devices/jfet/jfetset.c @@ -96,9 +96,6 @@ JFETsetup(matrix,inModel,ckt,states) here=here->JFETnextInstance) { if (here->JFETowner != ARCHme) goto matrixpointers; - CKTnode *tmpNode; - IFuid tmpName; - if(!here->JFETareaGiven) { here->JFETarea = 1; } @@ -112,6 +109,9 @@ matrixpointers: here->JFETsourcePrimeNode = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; @@ -129,6 +129,9 @@ matrixpointers: here->JFETdrainPrimeNode = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; diff --git a/src/spicelib/devices/mes/messetup.c b/src/spicelib/devices/mes/messetup.c index 3c9ce3ee6..b3ddd4bfd 100644 --- a/src/spicelib/devices/mes/messetup.c +++ b/src/spicelib/devices/mes/messetup.c @@ -82,9 +82,6 @@ MESsetup(matrix,inModel,ckt,states) here=here->MESnextInstance) { if (here->MESowner != ARCHme) goto matrixpointers; - CKTnode *tmpNode; - IFuid tmpName; - if(!here->MESareaGiven) { here->MESarea = 1; } @@ -98,6 +95,9 @@ matrixpointers: here->MESsourcePrimeNode = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; @@ -115,6 +115,9 @@ matrixpointers: here->MESdrainPrimeNode = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; diff --git a/src/spicelib/devices/mos1/mos1ask.c b/src/spicelib/devices/mos1/mos1ask.c index dd717cb19..ac6fb97b6 100644 --- a/src/spicelib/devices/mos1/mos1ask.c +++ b/src/spicelib/devices/mos1/mos1ask.c @@ -196,7 +196,7 @@ MOS1ask(ckt,inst,which,value,select) return(OK); case MOS1_CAPGD: value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgd); - * add overlap capacitance */ + /* add overlap capacitance */ value->rValue += (here->sMOS1modPtr->MOS1gateSourceOverlapCapFactor) * here->MOS1m * (here->MOS1w); diff --git a/src/spicelib/devices/mos1/mos1set.c b/src/spicelib/devices/mos1/mos1set.c index bad23675b..1377fcb44 100644 --- a/src/spicelib/devices/mos1/mos1set.c +++ b/src/spicelib/devices/mos1/mos1set.c @@ -105,9 +105,6 @@ MOS1setup(matrix,inModel,ckt,states) } } - CKTnode *tmpNode; - IFuid tmpName; - if(!here->MOS1drainPerimiterGiven) { here->MOS1drainPerimiter = 0; } @@ -145,6 +142,9 @@ MOS1setup(matrix,inModel,ckt,states) here->MOS1dNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; @@ -166,6 +166,9 @@ MOS1setup(matrix,inModel,ckt,states) here->MOS1sNodePrime = tmp->number; if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { if (tmpNode->nsGiven) { tmp->nodeset=tmpNode->nodeset; diff --git a/src/spicelib/devices/mos1/mos1temp.c b/src/spicelib/devices/mos1/mos1temp.c index 6dcf255df..cb94f6157 100644 --- a/src/spicelib/devices/mos1/mos1temp.c +++ b/src/spicelib/devices/mos1/mos1temp.c @@ -311,7 +311,6 @@ MOS1temp(inModel,ckt) } else if (model->MOS1sheetResistanceGiven) { if ((model->MOS1sheetResistance != 0) && (here->MOS1sourceSquares != 0)) { -#else here->MOS1sourceConductance = here->MOS1m / (model->MOS1sheetResistance*here->MOS1sourceSquares); diff --git a/src/spicelib/devices/mos3/mos3load.c b/src/spicelib/devices/mos3/mos3load.c index 71474b55d..8dedb5de2 100644 --- a/src/spicelib/devices/mos3/mos3load.c +++ b/src/spicelib/devices/mos3/mos3load.c @@ -14,13 +14,10 @@ Modified: 2000 AlansFixes #include "sperror.h" #include "suffix.h" +/* actually load the current value into the sparse matrix previously + * provided */ int -MOS3load(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; - /* actually load the current value into the - * sparse matrix previously provided - */ +MOS3load(GENmodel *inModel, CKTcircuit *ckt) { MOS3model *model = (MOS3model *)inModel; MOS3instance *here; @@ -85,19 +82,19 @@ MOS3load(inModel,ckt) if(ckt->CKTsenInfo){ if(ckt->CKTsenInfo->SENstatus == PERTURBATION) { if((ckt->CKTsenInfo->SENmode == ACSEN)|| - (ckt->CKTsenInfo->SENmode == TRANSEN)){ + (ckt->CKTsenInfo->SENmode == TRANSEN)){ } goto next; } } /* loop through all the MOS3 device models */ -next: + next: for( ; model != NULL; model = model->MOS3nextModel ) { /* loop through all the instances of the model */ for (here = model->MOS3instances; here != NULL ; - here=here->MOS3nextInstance) { + here=here->MOS3nextInstance) { if (here->MOS3owner != ARCHme) continue; vt = CONSTKoverQ * here->MOS3temp; @@ -116,42 +113,42 @@ next: /* first, we compute a few useful values - these could be * pre-computed, but for historical reasons are still done - * here. They may be moved at the expense of instance size - */ + * here. They may be moved at the expense of instance + * size */ EffectiveWidth=here->MOS3w-2*model->MOS3widthNarrow+ - model->MOS3widthAdjust; + model->MOS3widthAdjust; EffectiveLength=here->MOS3l - 2*model->MOS3latDiff+ - model->MOS3lengthAdjust; + model->MOS3lengthAdjust; - if( (here->MOS3tSatCurDens == 0) || - (here->MOS3drainArea == 0) || - (here->MOS3sourceArea == 0)) { + if( (here->MOS3tSatCurDens == 0) || + (here->MOS3drainArea == 0) || + (here->MOS3sourceArea == 0)) { DrainSatCur = here->MOS3m * here->MOS3tSatCur; SourceSatCur = here->MOS3m * here->MOS3tSatCur; } else { DrainSatCur = here->MOS3m * here->MOS3tSatCurDens * - here->MOS3drainArea; + here->MOS3drainArea; SourceSatCur = here->MOS3m * here->MOS3tSatCurDens * - here->MOS3sourceArea; + here->MOS3sourceArea; } GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * - here->MOS3m * EffectiveWidth; + here->MOS3m * EffectiveWidth; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * - here->MOS3m * EffectiveWidth; + here->MOS3m * EffectiveWidth; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * - here->MOS3m * EffectiveLength; + here->MOS3m * EffectiveLength; Beta = here->MOS3tTransconductance * - here->MOS3m * EffectiveWidth/EffectiveLength; + here->MOS3m * EffectiveWidth/EffectiveLength; OxideCap = model->MOS3oxideCapFactor * EffectiveLength * - here->MOS3m * EffectiveWidth; + here->MOS3m * EffectiveWidth; if(SenCond){ #ifdef SENSDEBUG printf("MOS3senPertFlag = ON \n"); #endif /* SENSDEBUG */ if((ckt->CKTsenInfo->SENmode == TRANSEN) && - (ckt->CKTmode & MODEINITTRAN)) { + (ckt->CKTmode & MODEINITTRAN)) { vgs = *(ckt->CKTstate1 + here->MOS3vgs); vds = *(ckt->CKTstate1 + here->MOS3vds); vbs = *(ckt->CKTstate1 + here->MOS3vbs); @@ -189,15 +186,15 @@ next: * ok - now to do the start-up operations * * we must get values for vbs, vds, and vgs from somewhere - * so we either predict them or recover them from last iteration - * These are the two most common cases - either a prediction - * step or the general iteration step and they - * share some code, so we put them first - others later on - */ + * so we either predict them or recover them from last + * iteration These are the two most common cases - either + * a prediction step or the general iteration step and + * they share some code, so we put them first - others + * later on */ if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED | MODEINITSMSIG | - MODEINITTRAN)) || - ( (ckt->CKTmode & MODEINITFIX) && (!here->MOS3off) ) ) { + MODEINITTRAN)) || + ( (ckt->CKTmode & MODEINITFIX) && (!here->MOS3off) ) ) { #ifndef PREDICTOR if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { @@ -205,20 +202,20 @@ next: xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->MOS3vbs) = - *(ckt->CKTstate1 + here->MOS3vbs); + *(ckt->CKTstate1 + here->MOS3vbs); vbs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS3vbs)) - -(xfact * (*(ckt->CKTstate2 + here->MOS3vbs))); + -(xfact * (*(ckt->CKTstate2 + here->MOS3vbs))); *(ckt->CKTstate0 + here->MOS3vgs) = - *(ckt->CKTstate1 + here->MOS3vgs); + *(ckt->CKTstate1 + here->MOS3vgs); vgs = (1+xfact)* (*(ckt->CKTstate1 + here->MOS3vgs)) - -(xfact * (*(ckt->CKTstate2 + here->MOS3vgs))); + -(xfact * (*(ckt->CKTstate2 + here->MOS3vgs))); *(ckt->CKTstate0 + here->MOS3vds) = - *(ckt->CKTstate1 + here->MOS3vds); + *(ckt->CKTstate1 + here->MOS3vds); vds = (1+xfact)* (*(ckt->CKTstate1 + here->MOS3vds)) - -(xfact * (*(ckt->CKTstate2 + here->MOS3vds))); + -(xfact * (*(ckt->CKTstate2 + here->MOS3vds))); *(ckt->CKTstate0 + here->MOS3vbd) = - *(ckt->CKTstate0 + here->MOS3vbs)- - *(ckt->CKTstate0 + here->MOS3vds); + *(ckt->CKTstate0 + here->MOS3vbs)- + *(ckt->CKTstate0 + here->MOS3vds); } else { #endif /*PREDICTOR*/ @@ -242,7 +239,7 @@ next: vbd=vbs-vds; vgd=vgs-vds; vgdo = *(ckt->CKTstate0 + here->MOS3vgs) - - *(ckt->CKTstate0 + here->MOS3vds); + *(ckt->CKTstate0 + here->MOS3vds); delvbs = vbs - *(ckt->CKTstate0 + here->MOS3vbs); delvbd = vbd - *(ckt->CKTstate0 + here->MOS3vbd); delvgs = vgs - *(ckt->CKTstate0 + here->MOS3vgs); @@ -262,7 +259,7 @@ next: cdhat= here->MOS3cd - ( here->MOS3gbd - - here->MOS3gmbs) * delvbd - + here->MOS3gmbs) * delvbd - here->MOS3gm * delvgd + here->MOS3gds * delvds ; } @@ -278,53 +275,53 @@ next: * is split into several successive if statements */ tempv = MAX(fabs(cbhat),fabs(here->MOS3cbs - + here->MOS3cbd))+ckt->CKTabstol; + + here->MOS3cbd))+ckt->CKTabstol; if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) - )) && (ckt->CKTbypass) ) - if ( (fabs(cbhat-(here->MOS3cbs + - here->MOS3cbd)) < ckt->CKTreltol * - tempv)) - if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), - fabs(*(ckt->CKTstate0+here->MOS3vbs)))+ - ckt->CKTvoltTol))) - if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), - fabs(*(ckt->CKTstate0+here->MOS3vbd)))+ - ckt->CKTvoltTol)) ) - if( (fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs), - fabs(*(ckt->CKTstate0+here->MOS3vgs)))+ - ckt->CKTvoltTol))) - if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), - fabs(*(ckt->CKTstate0+here->MOS3vds)))+ - ckt->CKTvoltTol)) ) - if( (fabs(cdhat- here->MOS3cd) < - ckt->CKTreltol * MAX(fabs(cdhat),fabs( - here->MOS3cd)) + ckt->CKTabstol) ) { - /* bypass code */ - /* nothing interesting has changed since last - * iteration on this device, so we just - * copy all the values computed last iteration out - * and keep going - */ - vbs = *(ckt->CKTstate0 + here->MOS3vbs); - vbd = *(ckt->CKTstate0 + here->MOS3vbd); - vgs = *(ckt->CKTstate0 + here->MOS3vgs); - vds = *(ckt->CKTstate0 + here->MOS3vds); - vgd = vgs - vds; - vgb = vgs - vbs; - cdrain = here->MOS3mode * (here->MOS3cd + here->MOS3cbd); - if(ckt->CKTmode & (MODETRAN | MODETRANOP)) { - capgs = ( *(ckt->CKTstate0+here->MOS3capgs)+ - *(ckt->CKTstate1+here->MOS3capgs) + - GateSourceOverlapCap ); - capgd = ( *(ckt->CKTstate0+here->MOS3capgd)+ - *(ckt->CKTstate1+here->MOS3capgd) + - GateDrainOverlapCap ); - capgb = ( *(ckt->CKTstate0+here->MOS3capgb)+ - *(ckt->CKTstate1+here->MOS3capgb) + - GateBulkOverlapCap ); - } - goto bypass; - } + )) && (ckt->CKTbypass) ) + if ( (fabs(cbhat-(here->MOS3cbs + + here->MOS3cbd)) < ckt->CKTreltol * + tempv)) + if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), + fabs(*(ckt->CKTstate0+here->MOS3vbs)))+ + ckt->CKTvoltTol))) + if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), + fabs(*(ckt->CKTstate0+here->MOS3vbd)))+ + ckt->CKTvoltTol)) ) + if( (fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs), + fabs(*(ckt->CKTstate0+here->MOS3vgs)))+ + ckt->CKTvoltTol))) + if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), + fabs(*(ckt->CKTstate0+here->MOS3vds)))+ + ckt->CKTvoltTol)) ) + if( (fabs(cdhat- here->MOS3cd) < + ckt->CKTreltol * MAX(fabs(cdhat),fabs( + here->MOS3cd)) + ckt->CKTabstol) ) { + /* bypass code */ + /* nothing interesting has changed since last + * iteration on this device, so we just + * copy all the values computed last iteration out + * and keep going + */ + vbs = *(ckt->CKTstate0 + here->MOS3vbs); + vbd = *(ckt->CKTstate0 + here->MOS3vbd); + vgs = *(ckt->CKTstate0 + here->MOS3vgs); + vds = *(ckt->CKTstate0 + here->MOS3vds); + vgd = vgs - vds; + vgb = vgs - vbs; + cdrain = here->MOS3mode * (here->MOS3cd + here->MOS3cbd); + if(ckt->CKTmode & (MODETRAN | MODETRANOP)) { + capgs = ( *(ckt->CKTstate0+here->MOS3capgs)+ + *(ckt->CKTstate1+here->MOS3capgs) + + GateSourceOverlapCap ); + capgd = ( *(ckt->CKTstate0+here->MOS3capgd)+ + *(ckt->CKTstate1+here->MOS3capgd) + + GateDrainOverlapCap ); + capgb = ( *(ckt->CKTstate0+here->MOS3capgb)+ + *(ckt->CKTstate1+here->MOS3capgb) + + GateBulkOverlapCap ); + } + goto bypass; + } /* ok - bypass is out, do it the hard way */ @@ -340,7 +337,7 @@ next: if(*(ckt->CKTstate0 + here->MOS3vds) >=0) { vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->MOS3vgs) - ,von); + ,von); vds = vgs - vgd; vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->MOS3vds)); vgd = vgs - vds; @@ -349,17 +346,17 @@ next: vds = vgs - vgd; if(!(ckt->CKTfixLimit)) { vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 + - here->MOS3vds))); + here->MOS3vds))); } vgs = vgd + vds; } if(vds >= 0) { vbs = DEVpnjlim(vbs,*(ckt->CKTstate0 + here->MOS3vbs), - vt,here->MOS3sourceVcrit,&Check); + vt,here->MOS3sourceVcrit,&Check); vbd = vbs-vds; } else { vbd = DEVpnjlim(vbd,*(ckt->CKTstate0 + here->MOS3vbd), - vt,here->MOS3drainVcrit,&Check); + vt,here->MOS3drainVcrit,&Check); vbs = vbd + vds; } #endif /*NODELIMITING*/ @@ -376,9 +373,9 @@ next: vgs= model->MOS3type * here->MOS3icVGS; vbs= model->MOS3type * here->MOS3icVBS; if((vds==0) && (vgs==0) && (vbs==0) && - ((ckt->CKTmode & - (MODETRAN|MODEDCOP|MODEDCTRANCURVE)) || - (!(ckt->CKTmode & MODEUIC)))) { + ((ckt->CKTmode & + (MODETRAN|MODEDCOP|MODEDCTRANCURVE)) || + (!(ckt->CKTmode & MODEUIC)))) { vbs = -1; vgs = model->MOS3type * here->MOS3tVto; vds = 0; @@ -403,16 +400,16 @@ next: * corresponding derivative (conductance). */ -next1: if(vbs <= -3*vt) { - arg=3*vt/(vbs*CONSTe); - arg = arg * arg * arg; - here->MOS3cbs = -SourceSatCur*(1+arg)+ckt->CKTgmin*vbs; - here->MOS3gbs = SourceSatCur*3*arg/vbs+ckt->CKTgmin; - } else { - evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); - here->MOS3gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; - here->MOS3cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; - } + next1: if(vbs <= -3*vt) { + arg=3*vt/(vbs*CONSTe); + arg = arg * arg * arg; + here->MOS3cbs = -SourceSatCur*(1+arg)+ckt->CKTgmin*vbs; + here->MOS3gbs = SourceSatCur*3*arg/vbs+ckt->CKTgmin; + } else { + evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); + here->MOS3gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; + here->MOS3cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; + } if(vbd <= -3*vt) { arg=3*vt/(vbd*CONSTe); arg = arg * arg * arg; @@ -436,834 +433,814 @@ next1: if(vbs <= -3*vt) { } { - /* - * subroutine moseq3(vds,vbs,vgs,gm,gds,gmbs, - * qg,qc,qb,cggb,cgdb,cgsb,cbgb,cbdb,cbsb) - */ + /* + * subroutine moseq3(vds,vbs,vgs,gm,gds,gmbs, + * qg,qc,qb,cggb,cgdb,cgsb,cbgb,cbdb,cbsb) + */ - /* - * this routine evaluates the drain current, its derivatives and - * the charges associated with the gate, channel and bulk - * for mosfets based on semi-empirical equations - */ + /* this routine evaluates the drain current, its + * derivatives and the charges associated with the + * gate, channel and bulk for mosfets based on + * semi-empirical equations */ - /* - common /mosarg/ vto,beta,gamma,phi,phib,cox,xnsub,xnfs,xd,xj,xld, - 1 xlamda,uo,uexp,vbp,utra,vmax,xneff,xl,xw,vbi,von,vdsat,qspof, - 2 beta0,beta1,cdrain,xqco,xqc,fnarrw,fshort,lev - common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, - 1 xmu,sfactr,mode,modedc,icalc,initf,method,iord,maxord,noncon, - 2 iterno,itemno,nosolv,modac,ipiv,ivmflg,ipostp,iscrch,iofile - common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, - 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox, - 2 pivtol,pivrel - */ - - /* equivalence (xlamda,alpha),(vbp,theta),(uexp,eta),(utra,xkappa)*/ - - double coeff0 = 0.0631353e0; - double coeff1 = 0.8013292e0; - double coeff2 = -0.01110777e0; - double oneoverxl; /* 1/effective length */ - double eta; /* eta from model after length factor */ - double phibs; /* phi - vbs */ - double sqphbs; /* square root of phibs */ - double dsqdvb; /* */ - double sqphis; /* square root of phi */ - double sqphs3; /* square root of phi cubed */ - double wps; - double oneoverxj; /* 1/junction depth */ - double xjonxl; /* junction depth/effective length */ - double djonxj; - double wponxj; - double arga; - double argb; - double argc; - double dwpdvb; - double dadvb; - double dbdvb; - double gammas; - double fbodys; - double fbody; - double onfbdy; - double qbonco; - double vbix; - double wconxj; - double dfsdvb; - double dfbdvb; - double dqbdvb; - double vth; - double dvtdvb; - double csonco; - double cdonco; - double dxndvb; - double dvodvb; - double dvodvd; - double vgsx; - double dvtdvd; - double onfg; - double fgate; - double us; - double dfgdvg; - double dfgdvd; - double dfgdvb; - double dvsdvg; - double dvsdvb; - double dvsdvd; - double xn; - double vdsc; - double onvdsc; - double dvsdga; - double vdsx; - double dcodvb; - double cdnorm; - double cdo; - double cd1; - double fdrain; - double fd2; - double dfddvg; - double dfddvb; - double dfddvd; - double gdsat; - double cdsat; - double gdoncd; - double gdonfd; - double gdonfg; - double dgdvg; - double dgdvd; - double dgdvb; - double emax; - double emongd; - double demdvg; - double demdvd; - double demdvb; - double delxl; - double dldvd; - double dldem; - double ddldvg; - double ddldvd; - double ddldvb; - double dlonxl; - double xlfact; - double diddl; - double gds0; - double emoncd; - double ondvt; - double onxn; - double wfact; - double gms; - double gmw; - double fshort; - - /* - * bypasses the computation of charges - */ - - /* - * reference cdrain equations to source and - * charge equations to bulk - */ - vdsat = 0.0; - oneoverxl = 1.0/EffectiveLength; - eta = model->MOS3eta * 8.15e-22/(model->MOS3oxideCapFactor* - EffectiveLength*EffectiveLength*EffectiveLength); - /* - *.....square root term - */ - if ( (here->MOS3mode==1?vbs:vbd) <= 0.0 ) { - phibs = here->MOS3tPhi-(here->MOS3mode==1?vbs:vbd); - sqphbs = sqrt(phibs); - dsqdvb = -0.5/sqphbs; - } else { - sqphis = sqrt(here->MOS3tPhi); - sqphs3 = here->MOS3tPhi*sqphis; - sqphbs = sqphis/(1.0+(here->MOS3mode==1?vbs:vbd)/ - (here->MOS3tPhi+here->MOS3tPhi)); - phibs = sqphbs*sqphbs; - dsqdvb = -phibs/(sqphs3+sqphs3); - } - /* - *.....short channel effect factor - */ - if ( (model->MOS3junctionDepth != 0.0) && - (model->MOS3coeffDepLayWidth != 0.0) ) { - wps = model->MOS3coeffDepLayWidth*sqphbs; - oneoverxj = 1.0/model->MOS3junctionDepth; - xjonxl = model->MOS3junctionDepth*oneoverxl; - djonxj = model->MOS3latDiff*oneoverxj; - wponxj = wps*oneoverxj; - wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj; - arga = wconxj+djonxj; - argc = wponxj/(1.0+wponxj); - argb = sqrt(1.0-argc*argc); - fshort = 1.0-xjonxl*(arga*argb-djonxj); - dwpdvb = model->MOS3coeffDepLayWidth*dsqdvb; - dadvb = (coeff1+coeff2*(wponxj+wponxj))*dwpdvb*oneoverxj; - dbdvb = -argc*argc*(1.0-argc)*dwpdvb/(argb*wps); - dfsdvb = -xjonxl*(dadvb*argb+arga*dbdvb); - } else { - fshort = 1.0; - dfsdvb = 0.0; - } - /* - *.....body effect - */ - gammas = model->MOS3gamma*fshort; - fbodys = 0.5*gammas/(sqphbs+sqphbs); - fbody = fbodys+model->MOS3narrowFactor/EffectiveWidth; - onfbdy = 1.0/(1.0+fbody); - dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort; - qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/EffectiveWidth; - dqbdvb = gammas*dsqdvb+model->MOS3gamma*dfsdvb*sqphbs- - model->MOS3narrowFactor/EffectiveWidth; - /* - *.....static feedback effect - */ - vbix = here->MOS3tVbi*model->MOS3type-eta*(here->MOS3mode*vds); - /* - *.....threshold voltage - */ - vth = vbix+qbonco; - dvtdvd = -eta; - dvtdvb = dqbdvb; - /* - *.....joint weak inversion and strong inversion - */ - von = vth; - if ( model->MOS3fastSurfaceStateDensity != 0.0 ) { - csonco = CHARGE*model->MOS3fastSurfaceStateDensity * - 1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * - here->MOS3m/OxideCap; - cdonco = qbonco/(phibs+phibs); - xn = 1.0+csonco+cdonco; - von = vth+vt*xn; - dxndvb = dqbdvb/(phibs+phibs)-qbonco*dsqdvb/(phibs*sqphbs); - dvodvd = dvtdvd; - dvodvb = dvtdvb+vt*dxndvb; - } else { - /* - *.....cutoff region - */ - if ( (here->MOS3mode==1?vgs:vgd) <= von ) { - cdrain = 0.0; - here->MOS3gm = 0.0; - here->MOS3gds = 0.0; - here->MOS3gmbs = 0.0; - goto innerline1000; - } - } - /* - *.....device is on - */ - vgsx = MAX((here->MOS3mode==1?vgs:vgd),von); - /* - *.....mobility modulation by gate voltage - */ - onfg = 1.0+model->MOS3theta*(vgsx-vth); - fgate = 1.0/onfg; - us = here->MOS3tSurfMob * 1e-4 /*(m**2/cm**2)*/ *fgate; - dfgdvg = -model->MOS3theta*fgate*fgate; - dfgdvd = -dfgdvg*dvtdvd; - dfgdvb = -dfgdvg*dvtdvb; - /* - *.....saturation voltage - */ - vdsat = (vgsx-vth)*onfbdy; - if ( model->MOS3maxDriftVel <= 0.0 ) { - dvsdvg = onfbdy; - dvsdvd = -dvsdvg*dvtdvd; - dvsdvb = -dvsdvg*dvtdvb-vdsat*dfbdvb*onfbdy; - } else { - vdsc = EffectiveLength*model->MOS3maxDriftVel/us; - onvdsc = 1.0/vdsc; - arga = (vgsx-vth)*onfbdy; - argb = sqrt(arga*arga+vdsc*vdsc); - vdsat = arga+vdsc-argb; - dvsdga = (1.0-arga/argb)*onfbdy; - dvsdvg = dvsdga-(1.0-vdsc/argb)*vdsc*dfgdvg*onfg; - dvsdvd = -dvsdvg*dvtdvd; - dvsdvb = -dvsdvg*dvtdvb-arga*dvsdga*dfbdvb; - } - /* - *.....current factors in linear region - */ - vdsx = MIN((here->MOS3mode*vds),vdsat); - if ( vdsx == 0.0 ) goto line900; - cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx; - dcodvb = -dvtdvb-0.5*dfbdvb*vdsx; - /* - *.....normalized drain current - */ - cdnorm = cdo*vdsx; - here->MOS3gm = vdsx; - if ((here->MOS3mode*vds) > vdsat) here->MOS3gds = -dvtdvd*vdsx; - else here->MOS3gds = vgsx-vth-(1.0+fbody+dvtdvd)*vdsx; - here->MOS3gmbs = dcodvb*vdsx; - /* - *.....drain current without velocity saturation effect - */ - cd1 = Beta*cdnorm; - Beta = Beta*fgate; - cdrain = Beta*cdnorm; - here->MOS3gm = Beta*here->MOS3gm+dfgdvg*cd1; - here->MOS3gds = Beta*here->MOS3gds+dfgdvd*cd1; - here->MOS3gmbs = Beta*here->MOS3gmbs+dfgdvb*cd1; - /* - *.....velocity saturation factor - */ - if ( model->MOS3maxDriftVel > 0.0 ) { - fdrain = 1.0/(1.0+vdsx*onvdsc); - fd2 = fdrain*fdrain; - arga = fd2*vdsx*onvdsc*onfg; - dfddvg = -dfgdvg*arga; - if ((here->MOS3mode*vds) > vdsat) dfddvd = -dfgdvd*arga; - else dfddvd = -dfgdvd*arga-fd2*onvdsc; - dfddvb = -dfgdvb*arga; - /* - *.....drain current - */ - here->MOS3gm = fdrain*here->MOS3gm+dfddvg*cdrain; - here->MOS3gds = fdrain*here->MOS3gds+dfddvd*cdrain; - here->MOS3gmbs = fdrain*here->MOS3gmbs+dfddvb*cdrain; - cdrain = fdrain*cdrain; - Beta = Beta*fdrain; - } - /* - *.....channel length modulation - */ - - if ( (here->MOS3mode*vds) <= vdsat ) { - if ( (model->MOS3maxDriftVel > 0.0) || - (model->MOS3alpha == 0.0) || - (ckt->CKTbadMos3) ) goto line700; - else { - arga = (here->MOS3mode*vds)/vdsat; - delxl = sqrt(model->MOS3kappa*model->MOS3alpha*vdsat/8); - dldvd = 4*delxl*arga*arga*arga/vdsat; - arga *= arga; - arga *= arga; - delxl *= arga; - ddldvg = 0.0; - ddldvd = -dldvd; - ddldvb = 0.0; - goto line520; - }; - - if ( model->MOS3maxDriftVel <= 0.0 ) goto line510; - if (model->MOS3alpha == 0.0) goto line700; - cdsat = cdrain; - gdsat = cdsat*(1.0-fdrain)*onvdsc; - gdsat = MAX(1.0e-12,gdsat); - gdoncd = gdsat/cdsat; - gdonfd = gdsat/(1.0-fdrain); - gdonfg = gdsat*onfg; - dgdvg = gdoncd*here->MOS3gm-gdonfd*dfddvg+gdonfg*dfgdvg; - dgdvd = gdoncd*here->MOS3gds-gdonfd*dfddvd+gdonfg*dfgdvd; - dgdvb = gdoncd*here->MOS3gmbs-gdonfd*dfddvb+gdonfg*dfgdvb; - - if (ckt->CKTbadMos3) - emax = cdsat*oneoverxl/gdsat; - else - emax = model->MOS3kappa * cdsat*oneoverxl/gdsat; - emoncd = emax/cdsat; - emongd = emax/gdsat; - demdvg = emoncd*here->MOS3gm-emongd*dgdvg; - demdvd = emoncd*here->MOS3gds-emongd*dgdvd; - demdvb = emoncd*here->MOS3gmbs-emongd*dgdvb; - - arga = 0.5*emax*model->MOS3alpha; - argc = model->MOS3kappa*model->MOS3alpha; - argb = sqrt(arga*arga+argc*((here->MOS3mode*vds)-vdsat)); - delxl = argb-arga; - if (argb != 0.0) { - dldvd = argc/(argb+argb); - dldem = 0.5*(arga/argb-1.0)*model->MOS3alpha; - } else { - dldvd = 0.0; - dldem = 0.0; - } - ddldvg = dldem*demdvg; - ddldvd = dldem*demdvd-dldvd; - ddldvb = dldem*demdvb; - goto line520; -line510: - if (ckt->CKTbadMos3) { - delxl = sqrt(model->MOS3kappa*((here->MOS3mode*vds)-vdsat)* - model->MOS3alpha); - dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat); - } else { - delxl = sqrt(model->MOS3kappa*model->MOS3alpha* - ((here->MOS3mode*vds)-vdsat+(vdsat/8))); - dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat+(vdsat/8)); - }; - ddldvg = 0.0; - ddldvd = -dldvd; - ddldvb = 0.0; - /* - *.....punch through approximation - */ -line520: - if ( delxl > (0.5*EffectiveLength) ) { - delxl = EffectiveLength-(EffectiveLength*EffectiveLength/ - (4.0*delxl)); - arga = 4.0*(EffectiveLength-delxl)*(EffectiveLength-delxl)/ - (EffectiveLength*EffectiveLength); - ddldvg = ddldvg*arga; - ddldvd = ddldvd*arga; - ddldvb = ddldvb*arga; - dldvd = dldvd*arga; - } - /* - *.....saturation region - */ - dlonxl = delxl*oneoverxl; - xlfact = 1.0/(1.0-dlonxl); - - cd1 = cdrain; - cdrain = cdrain*xlfact; - diddl = cdrain/(EffectiveLength-delxl); - here->MOS3gm = here->MOS3gm*xlfact+diddl*ddldvg; - here->MOS3gmbs = here->MOS3gmbs*xlfact+diddl*ddldvb; - gds0 = diddl*ddldvd; - here->MOS3gm = here->MOS3gm+gds0*dvsdvg; - here->MOS3gmbs = here->MOS3gmbs+gds0*dvsdvb; - here->MOS3gds = here->MOS3gds*xlfact+diddl*dldvd+gds0*dvsdvd; + double coeff0 = 0.0631353e0; + double coeff1 = 0.8013292e0; + double coeff2 = -0.01110777e0; + double oneoverxl; /* 1/effective length */ + double eta; /* eta from model after length factor */ + double phibs; /* phi - vbs */ + double sqphbs; /* square root of phibs */ + double dsqdvb; /* */ + double sqphis; /* square root of phi */ + double sqphs3; /* square root of phi cubed */ + double wps; + double oneoverxj; /* 1/junction depth */ + double xjonxl; /* junction depth/effective length */ + double djonxj; + double wponxj; + double arga; + double argb; + double argc; + double dwpdvb; + double dadvb; + double dbdvb; + double gammas; + double fbodys; + double fbody; + double onfbdy; + double qbonco; + double vbix; + double wconxj; + double dfsdvb; + double dfbdvb; + double dqbdvb; + double vth; + double dvtdvb; + double csonco; + double cdonco; + double dxndvb; + double dvodvb; + double dvodvd; + double vgsx; + double dvtdvd; + double onfg; + double fgate; + double us; + double dfgdvg; + double dfgdvd; + double dfgdvb; + double dvsdvg; + double dvsdvb; + double dvsdvd; + double xn; + double vdsc; + double onvdsc; + double dvsdga; + double vdsx; + double dcodvb; + double cdnorm; + double cdo; + double cd1; + double fdrain; + double fd2; + double dfddvg; + double dfddvb; + double dfddvd; + double gdsat; + double cdsat; + double gdoncd; + double gdonfd; + double gdonfg; + double dgdvg; + double dgdvd; + double dgdvb; + double emax; + double emongd; + double demdvg; + double demdvd; + double demdvb; + double delxl; + double dldvd; + double dldem; + double ddldvg; + double ddldvd; + double ddldvb; + double dlonxl; + double xlfact; + double diddl; + double gds0; + double emoncd; + double ondvt; + double onxn; + double wfact; + double gms; + double gmw; + double fshort; + + /* + * bypasses the computation of charges + */ + + /* + * reference cdrain equations to source and + * charge equations to bulk + */ + vdsat = 0.0; + oneoverxl = 1.0/EffectiveLength; + eta = model->MOS3eta * 8.15e-22/(model->MOS3oxideCapFactor* + EffectiveLength*EffectiveLength*EffectiveLength); + /* + *.....square root term + */ + if ( (here->MOS3mode==1?vbs:vbd) <= 0.0 ) { + phibs = here->MOS3tPhi-(here->MOS3mode==1?vbs:vbd); + sqphbs = sqrt(phibs); + dsqdvb = -0.5/sqphbs; + } else { + sqphis = sqrt(here->MOS3tPhi); + sqphs3 = here->MOS3tPhi*sqphis; + sqphbs = sqphis/(1.0+(here->MOS3mode==1?vbs:vbd)/ + (here->MOS3tPhi+here->MOS3tPhi)); + phibs = sqphbs*sqphbs; + dsqdvb = -phibs/(sqphs3+sqphs3); + } + /* + *.....short channel effect factor + */ + if ( (model->MOS3junctionDepth != 0.0) && + (model->MOS3coeffDepLayWidth != 0.0) ) { + wps = model->MOS3coeffDepLayWidth*sqphbs; + oneoverxj = 1.0/model->MOS3junctionDepth; + xjonxl = model->MOS3junctionDepth*oneoverxl; + djonxj = model->MOS3latDiff*oneoverxj; + wponxj = wps*oneoverxj; + wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj; + arga = wconxj+djonxj; + argc = wponxj/(1.0+wponxj); + argb = sqrt(1.0-argc*argc); + fshort = 1.0-xjonxl*(arga*argb-djonxj); + dwpdvb = model->MOS3coeffDepLayWidth*dsqdvb; + dadvb = (coeff1+coeff2*(wponxj+wponxj))*dwpdvb*oneoverxj; + dbdvb = -argc*argc*(1.0-argc)*dwpdvb/(argb*wps); + dfsdvb = -xjonxl*(dadvb*argb+arga*dbdvb); + } else { + fshort = 1.0; + dfsdvb = 0.0; + } + /* + *.....body effect + */ + gammas = model->MOS3gamma*fshort; + fbodys = 0.5*gammas/(sqphbs+sqphbs); + fbody = fbodys+model->MOS3narrowFactor/EffectiveWidth; + onfbdy = 1.0/(1.0+fbody); + dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort; + qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/EffectiveWidth; + dqbdvb = gammas*dsqdvb+model->MOS3gamma*dfsdvb*sqphbs- + model->MOS3narrowFactor/EffectiveWidth; + /* + *.....static feedback effect + */ + vbix = here->MOS3tVbi*model->MOS3type-eta*(here->MOS3mode*vds); + /* + *.....threshold voltage + */ + vth = vbix+qbonco; + dvtdvd = -eta; + dvtdvb = dqbdvb; + /* + *.....joint weak inversion and strong inversion + */ + von = vth; + if ( model->MOS3fastSurfaceStateDensity != 0.0 ) { + csonco = CHARGE*model->MOS3fastSurfaceStateDensity * + 1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * + here->MOS3m/OxideCap; + cdonco = qbonco/(phibs+phibs); + xn = 1.0+csonco+cdonco; + von = vth+vt*xn; + dxndvb = dqbdvb/(phibs+phibs)-qbonco*dsqdvb/(phibs*sqphbs); + dvodvd = dvtdvd; + dvodvb = dvtdvb+vt*dxndvb; + } else { + /* + *.....cutoff region + */ + if ( (here->MOS3mode==1?vgs:vgd) <= von ) { + cdrain = 0.0; + here->MOS3gm = 0.0; + here->MOS3gds = 0.0; + here->MOS3gmbs = 0.0; + goto innerline1000; + } + } + /* + *.....device is on + */ + vgsx = MAX((here->MOS3mode==1?vgs:vgd),von); + /* + *.....mobility modulation by gate voltage + */ + onfg = 1.0+model->MOS3theta*(vgsx-vth); + fgate = 1.0/onfg; + us = here->MOS3tSurfMob * 1e-4 /*(m**2/cm**2)*/ *fgate; + dfgdvg = -model->MOS3theta*fgate*fgate; + dfgdvd = -dfgdvg*dvtdvd; + dfgdvb = -dfgdvg*dvtdvb; + /* + *.....saturation voltage + */ + vdsat = (vgsx-vth)*onfbdy; + if ( model->MOS3maxDriftVel <= 0.0 ) { + dvsdvg = onfbdy; + dvsdvd = -dvsdvg*dvtdvd; + dvsdvb = -dvsdvg*dvtdvb-vdsat*dfbdvb*onfbdy; + } else { + vdsc = EffectiveLength*model->MOS3maxDriftVel/us; + onvdsc = 1.0/vdsc; + arga = (vgsx-vth)*onfbdy; + argb = sqrt(arga*arga+vdsc*vdsc); + vdsat = arga+vdsc-argb; + dvsdga = (1.0-arga/argb)*onfbdy; + dvsdvg = dvsdga-(1.0-vdsc/argb)*vdsc*dfgdvg*onfg; + dvsdvd = -dvsdvg*dvtdvd; + dvsdvb = -dvsdvg*dvtdvb-arga*dvsdga*dfbdvb; + } + /* + *.....current factors in linear region + */ + vdsx = MIN((here->MOS3mode*vds),vdsat); + if ( vdsx == 0.0 ) goto line900; + cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx; + dcodvb = -dvtdvb-0.5*dfbdvb*vdsx; + /* + *.....normalized drain current + */ + cdnorm = cdo*vdsx; + here->MOS3gm = vdsx; + if ((here->MOS3mode*vds) > vdsat) here->MOS3gds = -dvtdvd*vdsx; + else here->MOS3gds = vgsx-vth-(1.0+fbody+dvtdvd)*vdsx; + here->MOS3gmbs = dcodvb*vdsx; + /* + *.....drain current without velocity saturation effect + */ + cd1 = Beta*cdnorm; + Beta = Beta*fgate; + cdrain = Beta*cdnorm; + here->MOS3gm = Beta*here->MOS3gm+dfgdvg*cd1; + here->MOS3gds = Beta*here->MOS3gds+dfgdvd*cd1; + here->MOS3gmbs = Beta*here->MOS3gmbs+dfgdvb*cd1; + /* + *.....velocity saturation factor + */ + if ( model->MOS3maxDriftVel > 0.0 ) { + fdrain = 1.0/(1.0+vdsx*onvdsc); + fd2 = fdrain*fdrain; + arga = fd2*vdsx*onvdsc*onfg; + dfddvg = -dfgdvg*arga; + if ((here->MOS3mode*vds) > vdsat) dfddvd = -dfgdvd*arga; + else dfddvd = -dfgdvd*arga-fd2*onvdsc; + dfddvb = -dfgdvb*arga; + /* + *.....drain current + */ + here->MOS3gm = fdrain*here->MOS3gm+dfddvg*cdrain; + here->MOS3gds = fdrain*here->MOS3gds+dfddvd*cdrain; + here->MOS3gmbs = fdrain*here->MOS3gmbs+dfddvb*cdrain; + cdrain = fdrain*cdrain; + Beta = Beta*fdrain; + } + /* + *.....channel length modulation + */ + + if ( (here->MOS3mode*vds) <= vdsat ) { + if ( (model->MOS3maxDriftVel > 0.0) || + (model->MOS3alpha == 0.0) || + (ckt->CKTbadMos3) ) goto line700; + else { + arga = (here->MOS3mode*vds)/vdsat; + delxl = sqrt(model->MOS3kappa*model->MOS3alpha*vdsat/8); + dldvd = 4*delxl*arga*arga*arga/vdsat; + arga *= arga; + arga *= arga; + delxl *= arga; + ddldvg = 0.0; + ddldvd = -dldvd; + ddldvb = 0.0; + goto line520; + }; + + if ( model->MOS3maxDriftVel <= 0.0 ) goto line510; + if (model->MOS3alpha == 0.0) goto line700; + cdsat = cdrain; + gdsat = cdsat*(1.0-fdrain)*onvdsc; + gdsat = MAX(1.0e-12,gdsat); + gdoncd = gdsat/cdsat; + gdonfd = gdsat/(1.0-fdrain); + gdonfg = gdsat*onfg; + dgdvg = gdoncd*here->MOS3gm-gdonfd*dfddvg+gdonfg*dfgdvg; + dgdvd = gdoncd*here->MOS3gds-gdonfd*dfddvd+gdonfg*dfgdvd; + dgdvb = gdoncd*here->MOS3gmbs-gdonfd*dfddvb+gdonfg*dfgdvb; + + if (ckt->CKTbadMos3) + emax = cdsat*oneoverxl/gdsat; + else + emax = model->MOS3kappa * cdsat*oneoverxl/gdsat; + emoncd = emax/cdsat; + emongd = emax/gdsat; + demdvg = emoncd*here->MOS3gm-emongd*dgdvg; + demdvd = emoncd*here->MOS3gds-emongd*dgdvd; + demdvb = emoncd*here->MOS3gmbs-emongd*dgdvb; + + arga = 0.5*emax*model->MOS3alpha; + argc = model->MOS3kappa*model->MOS3alpha; + argb = sqrt(arga*arga+argc*((here->MOS3mode*vds)-vdsat)); + delxl = argb-arga; + if (argb != 0.0) { + dldvd = argc/(argb+argb); + dldem = 0.5*(arga/argb-1.0)*model->MOS3alpha; + } else { + dldvd = 0.0; + dldem = 0.0; + } + ddldvg = dldem*demdvg; + ddldvd = dldem*demdvd-dldvd; + ddldvb = dldem*demdvb; + goto line520; + line510: + if (ckt->CKTbadMos3) { + delxl = sqrt(model->MOS3kappa*((here->MOS3mode*vds)-vdsat)* + model->MOS3alpha); + dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat); + } else { + delxl = sqrt(model->MOS3kappa*model->MOS3alpha* + ((here->MOS3mode*vds)-vdsat+(vdsat/8))); + dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat+(vdsat/8)); + }; + ddldvg = 0.0; + ddldvd = -dldvd; + ddldvb = 0.0; + /* + *.....punch through approximation + */ + line520: + if ( delxl > (0.5*EffectiveLength) ) { + delxl = EffectiveLength-(EffectiveLength*EffectiveLength/ + (4.0*delxl)); + arga = 4.0*(EffectiveLength-delxl)*(EffectiveLength-delxl)/ + (EffectiveLength*EffectiveLength); + ddldvg = ddldvg*arga; + ddldvd = ddldvd*arga; + ddldvb = ddldvb*arga; + dldvd = dldvd*arga; + } + /* + *.....saturation region + */ + dlonxl = delxl*oneoverxl; + xlfact = 1.0/(1.0-dlonxl); + + cd1 = cdrain; + cdrain = cdrain*xlfact; + diddl = cdrain/(EffectiveLength-delxl); + here->MOS3gm = here->MOS3gm*xlfact+diddl*ddldvg; + here->MOS3gmbs = here->MOS3gmbs*xlfact+diddl*ddldvb; + gds0 = diddl*ddldvd; + here->MOS3gm = here->MOS3gm+gds0*dvsdvg; + here->MOS3gmbs = here->MOS3gmbs+gds0*dvsdvb; + here->MOS3gds = here->MOS3gds*xlfact+diddl*dldvd+gds0*dvsdvd; /* here->MOS3gds = (here->MOS3gds*xlfact)+gds0*dvsdvd- - (cd1*ddldvd/(EffectiveLength*(1-2*dlonxl+dlonxl*dlonxl)));*/ - - /* - *.....finish strong inversion case - */ -line700: - if ( (here->MOS3mode==1?vgs:vgd) < von ) { - /* - *.....weak inversion - */ - onxn = 1.0/xn; - ondvt = onxn/vt; - wfact = exp( ((here->MOS3mode==1?vgs:vgd)-von)*ondvt ); - cdrain = cdrain*wfact; - gms = here->MOS3gm*wfact; - gmw = cdrain*ondvt; - here->MOS3gm = gmw; - if ((here->MOS3mode*vds) > vdsat) { - here->MOS3gm = here->MOS3gm+gds0*dvsdvg*wfact; - } - here->MOS3gds = here->MOS3gds*wfact+(gms-gmw)*dvodvd; - here->MOS3gmbs = here->MOS3gmbs*wfact+(gms-gmw)*dvodvb-gmw* - ((here->MOS3mode==1?vgs:vgd)-von)*onxn*dxndvb; - } - /* - *.....charge computation - */ - goto innerline1000; - /* - *.....special case of vds = 0.0d0 - */ -line900: - Beta = Beta*fgate; - cdrain = 0.0; - here->MOS3gm = 0.0; - here->MOS3gds = Beta*(vgsx-vth); - here->MOS3gmbs = 0.0; - if ( (model->MOS3fastSurfaceStateDensity != 0.0) && - ((here->MOS3mode==1?vgs:vgd) < von) ) { - here->MOS3gds *=exp(((here->MOS3mode==1?vgs:vgd)-von)/(vt*xn)); - } -innerline1000:; - /* - *.....done - */ - } - - - /* now deal with n vs p polarity */ - - here->MOS3von = model->MOS3type * von; - here->MOS3vdsat = model->MOS3type * vdsat; - /* line 490 */ - /* - * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE - */ - here->MOS3cd=here->MOS3mode * cdrain - here->MOS3cbd; - - if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { - /* - * now we do the hard part of the bulk-drain and bulk-source - * diode - we evaluate the non-linear capacitance and - * charge - * - * the basic equations are not hard, but the implementation - * is somewhat long in an attempt to avoid log/exponential - * evaluations - */ - /* - * charge storage elements - * - *.. bulk-drain and bulk-source depletion capacitances - */ - { - /* can't bypass the diode capacitance calculations */ - if(here->MOS3Cbs != 0 || here->MOS3Cbssw != 0 ) { - if (vbs < here->MOS3tDepCap){ - arg=1-vbs/here->MOS3tBulkPot; - /* - * the following block looks somewhat long and messy, - * but since most users use the default grading - * coefficients of .5, and sqrt is MUCH faster than an - * exp(log()) we use this special case code to buy time. - * (as much as 10% of total job time!) - */ + (cd1*ddldvd/(EffectiveLength*(1-2*dlonxl+dlonxl*dlonxl)));*/ + + /* + *.....finish strong inversion case + */ + line700: + if ( (here->MOS3mode==1?vgs:vgd) < von ) { + /* + *.....weak inversion + */ + onxn = 1.0/xn; + ondvt = onxn/vt; + wfact = exp( ((here->MOS3mode==1?vgs:vgd)-von)*ondvt ); + cdrain = cdrain*wfact; + gms = here->MOS3gm*wfact; + gmw = cdrain*ondvt; + here->MOS3gm = gmw; + if ((here->MOS3mode*vds) > vdsat) { + here->MOS3gm = here->MOS3gm+gds0*dvsdvg*wfact; + } + here->MOS3gds = here->MOS3gds*wfact+(gms-gmw)*dvodvd; + here->MOS3gmbs = here->MOS3gmbs*wfact+(gms-gmw)*dvodvb-gmw* + ((here->MOS3mode==1?vgs:vgd)-von)*onxn*dxndvb; + } + /* + *.....charge computation + */ + goto innerline1000; + /* + *.....special case of vds = 0.0d0 + */ + line900: + Beta = Beta*fgate; + cdrain = 0.0; + here->MOS3gm = 0.0; + here->MOS3gds = Beta*(vgsx-vth); + here->MOS3gmbs = 0.0; + if ( (model->MOS3fastSurfaceStateDensity != 0.0) && + ((here->MOS3mode==1?vgs:vgd) < von) ) { + here->MOS3gds *=exp(((here->MOS3mode==1?vgs:vgd)-von)/(vt*xn)); + } + innerline1000:; + /* + *.....done + */ + } + + + /* now deal with n vs p polarity */ + + here->MOS3von = model->MOS3type * von; + here->MOS3vdsat = model->MOS3type * vdsat; + /* line 490 */ + /* + * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE + */ + here->MOS3cd=here->MOS3mode * cdrain - here->MOS3cbd; + + if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { + /* + * now we do the hard part of the bulk-drain and bulk-source + * diode - we evaluate the non-linear capacitance and + * charge + * + * the basic equations are not hard, but the implementation + * is somewhat long in an attempt to avoid log/exponential + * evaluations + */ + /* + * charge storage elements + * + *.. bulk-drain and bulk-source depletion capacitances + */ + { + /* can't bypass the diode capacitance calculations */ + if(here->MOS3Cbs != 0 || here->MOS3Cbssw != 0 ) { + if (vbs < here->MOS3tDepCap){ + arg=1-vbs/here->MOS3tBulkPot; + /* + * the following block looks somewhat long and messy, + * but since most users use the default grading + * coefficients of .5, and sqrt is MUCH faster than an + * exp(log()) we use this special case code to buy time. + * (as much as 10% of total job time!) + */ #ifndef NOSQRT - if(model->MOS3bulkJctBotGradingCoeff == - model->MOS3bulkJctSideGradingCoeff) { - if(model->MOS3bulkJctBotGradingCoeff == .5) { - sarg = sargsw = 1/sqrt(arg); - } else { - sarg = sargsw = - exp(-model->MOS3bulkJctBotGradingCoeff* - log(arg)); - } - } else { - if(model->MOS3bulkJctBotGradingCoeff == .5) { - sarg = 1/sqrt(arg); - } else { + if(model->MOS3bulkJctBotGradingCoeff == + model->MOS3bulkJctSideGradingCoeff) { + if(model->MOS3bulkJctBotGradingCoeff == .5) { + sarg = sargsw = 1/sqrt(arg); + } else { + sarg = sargsw = + exp(-model->MOS3bulkJctBotGradingCoeff* + log(arg)); + } + } else { + if(model->MOS3bulkJctBotGradingCoeff == .5) { + sarg = 1/sqrt(arg); + } else { #endif /*NOSQRT*/ - sarg = exp(-model->MOS3bulkJctBotGradingCoeff* - log(arg)); + sarg = exp(-model->MOS3bulkJctBotGradingCoeff* + log(arg)); #ifndef NOSQRT - } - if(model->MOS3bulkJctSideGradingCoeff == .5) { - sargsw = 1/sqrt(arg); - } else { + } + if(model->MOS3bulkJctSideGradingCoeff == .5) { + sargsw = 1/sqrt(arg); + } else { #endif /*NOSQRT*/ - sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* - log(arg)); + sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* + log(arg)); #ifndef NOSQRT - } - } + } + } #endif /*NOSQRT*/ - *(ckt->CKTstate0 + here->MOS3qbs) = - here->MOS3tBulkPot*(here->MOS3Cbs* - (1-arg*sarg)/(1-model->MOS3bulkJctBotGradingCoeff) - +here->MOS3Cbssw* - (1-arg*sargsw)/ - (1-model->MOS3bulkJctSideGradingCoeff)); - here->MOS3capbs=here->MOS3Cbs*sarg+ - here->MOS3Cbssw*sargsw; - } else { - *(ckt->CKTstate0 + here->MOS3qbs) = here->MOS3f4s + - vbs*(here->MOS3f2s+vbs*(here->MOS3f3s/2)); - here->MOS3capbs=here->MOS3f2s+here->MOS3f3s*vbs; - } - } else { - *(ckt->CKTstate0 + here->MOS3qbs) = 0; - here->MOS3capbs=0; - } - } - /* can't bypass the diode capacitance calculations */ - { - if(here->MOS3Cbd != 0 || here->MOS3Cbdsw != 0 ) { - if (vbd < here->MOS3tDepCap) { - arg=1-vbd/here->MOS3tBulkPot; - /* - * the following block looks somewhat long and messy, - * but since most users use the default grading - * coefficients of .5, and sqrt is MUCH faster than an - * exp(log()) we use this special case code to buy time. - * (as much as 10% of total job time!) - */ + *(ckt->CKTstate0 + here->MOS3qbs) = + here->MOS3tBulkPot*(here->MOS3Cbs* + (1-arg*sarg)/(1-model->MOS3bulkJctBotGradingCoeff) + +here->MOS3Cbssw* + (1-arg*sargsw)/ + (1-model->MOS3bulkJctSideGradingCoeff)); + here->MOS3capbs=here->MOS3Cbs*sarg+ + here->MOS3Cbssw*sargsw; + } else { + *(ckt->CKTstate0 + here->MOS3qbs) = here->MOS3f4s + + vbs*(here->MOS3f2s+vbs*(here->MOS3f3s/2)); + here->MOS3capbs=here->MOS3f2s+here->MOS3f3s*vbs; + } + } else { + *(ckt->CKTstate0 + here->MOS3qbs) = 0; + here->MOS3capbs=0; + } + } + /* can't bypass the diode capacitance calculations */ + { + if(here->MOS3Cbd != 0 || here->MOS3Cbdsw != 0 ) { + if (vbd < here->MOS3tDepCap) { + arg=1-vbd/here->MOS3tBulkPot; + /* + * the following block looks somewhat long and messy, + * but since most users use the default grading + * coefficients of .5, and sqrt is MUCH faster than an + * exp(log()) we use this special case code to buy time. + * (as much as 10% of total job time!) + */ #ifndef NOSQRT - if(model->MOS3bulkJctBotGradingCoeff == .5 && - model->MOS3bulkJctSideGradingCoeff == .5) { - sarg = sargsw = 1/sqrt(arg); - } else { - if(model->MOS3bulkJctBotGradingCoeff == .5) { - sarg = 1/sqrt(arg); - } else { + if(model->MOS3bulkJctBotGradingCoeff == .5 && + model->MOS3bulkJctSideGradingCoeff == .5) { + sarg = sargsw = 1/sqrt(arg); + } else { + if(model->MOS3bulkJctBotGradingCoeff == .5) { + sarg = 1/sqrt(arg); + } else { #endif /*NOSQRT*/ - sarg = exp(-model->MOS3bulkJctBotGradingCoeff* - log(arg)); + sarg = exp(-model->MOS3bulkJctBotGradingCoeff* + log(arg)); #ifndef NOSQRT - } - if(model->MOS3bulkJctSideGradingCoeff == .5) { - sargsw = 1/sqrt(arg); - } else { + } + if(model->MOS3bulkJctSideGradingCoeff == .5) { + sargsw = 1/sqrt(arg); + } else { #endif /*NOSQRT*/ - sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* - log(arg)); + sargsw =exp(-model->MOS3bulkJctSideGradingCoeff* + log(arg)); #ifndef NOSQRT - } - } + } + } #endif /*NOSQRT*/ - *(ckt->CKTstate0 + here->MOS3qbd) = - here->MOS3tBulkPot*(here->MOS3Cbd* - (1-arg*sarg) - /(1-model->MOS3bulkJctBotGradingCoeff) - +here->MOS3Cbdsw* - (1-arg*sargsw) - /(1-model->MOS3bulkJctSideGradingCoeff)); - here->MOS3capbd=here->MOS3Cbd*sarg+ - here->MOS3Cbdsw*sargsw; - } else { - *(ckt->CKTstate0 + here->MOS3qbd) = here->MOS3f4d + - vbd * (here->MOS3f2d + vbd * here->MOS3f3d/2); - here->MOS3capbd=here->MOS3f2d + vbd * here->MOS3f3d; - } - } else { - *(ckt->CKTstate0 + here->MOS3qbd) = 0; - here->MOS3capbd = 0; - } - } - if(SenCond && (ckt->CKTsenInfo->SENmode==TRANSEN)) goto next2; - - if ( ckt->CKTmode & MODETRAN ) { - /* (above only excludes tranop, since we're only at this - * point if tran or tranop ) - */ - - /* - * calculate equivalent conductances and currents for - * depletion capacitors - */ - - /* integrate the capacitors and save results */ - - error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbd, - here->MOS3qbd); - if(error) return(error); - here->MOS3gbd += geq; - here->MOS3cbd += *(ckt->CKTstate0 + here->MOS3cqbd); - here->MOS3cd -= *(ckt->CKTstate0 + here->MOS3cqbd); - error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbs, - here->MOS3qbs); - if(error) return(error); - here->MOS3gbs += geq; - here->MOS3cbs += *(ckt->CKTstate0 + here->MOS3cqbs); - } - } - if(SenCond) goto next2; - - /* - * check convergence - */ - if ( (here->MOS3off == 0) || - (!(ckt->CKTmode & (MODEINITFIX|MODEINITSMSIG))) ){ - if (Check == 1) { - ckt->CKTnoncon++; - ckt->CKTtroubleElt = (GENinstance *) here; - } - } - - - /* save things away for next time */ - -next2: *(ckt->CKTstate0 + here->MOS3vbs) = vbs; - *(ckt->CKTstate0 + here->MOS3vbd) = vbd; - *(ckt->CKTstate0 + here->MOS3vgs) = vgs; - *(ckt->CKTstate0 + here->MOS3vds) = vds; - - - /* - * meyer's capacitor model - */ - if ( ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG) ) { - /* - * calculate meyer's capacitors - */ - /* - * new cmeyer - this just evaluates at the current time, - * expects you to remember values from previous time - * returns 1/2 of non-constant portion of capacitance - * you must add in the other half from previous time - * and the constant part - */ - if (here->MOS3mode > 0){ - DEVqmeyer (vgs,vgd,vgb,von,vdsat, - (ckt->CKTstate0 + here->MOS3capgs), - (ckt->CKTstate0 + here->MOS3capgd), - (ckt->CKTstate0 + here->MOS3capgb), - here->MOS3tPhi,OxideCap); - } else { - DEVqmeyer (vgd,vgs,vgb,von,vdsat, - (ckt->CKTstate0 + here->MOS3capgd), - (ckt->CKTstate0 + here->MOS3capgs), - (ckt->CKTstate0 + here->MOS3capgb), - here->MOS3tPhi,OxideCap); - } - vgs1 = *(ckt->CKTstate1 + here->MOS3vgs); - vgd1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vds); - vgb1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vbs); - if(ckt->CKTmode & MODETRANOP) { - capgs = 2 * *(ckt->CKTstate0+here->MOS3capgs)+ - GateSourceOverlapCap ; - capgd = 2 * *(ckt->CKTstate0+here->MOS3capgd)+ - GateDrainOverlapCap ; - capgb = 2 * *(ckt->CKTstate0+here->MOS3capgb)+ - GateBulkOverlapCap ; - } else { - capgs = ( *(ckt->CKTstate0+here->MOS3capgs)+ - *(ckt->CKTstate1+here->MOS3capgs) + - GateSourceOverlapCap ); - capgd = ( *(ckt->CKTstate0+here->MOS3capgd)+ - *(ckt->CKTstate1+here->MOS3capgd) + - GateDrainOverlapCap ); - capgb = ( *(ckt->CKTstate0+here->MOS3capgb)+ - *(ckt->CKTstate1+here->MOS3capgb) + - GateBulkOverlapCap ); - } - if(ckt->CKTsenInfo){ - here->MOS3cgs = capgs; - here->MOS3cgd = capgd; - here->MOS3cgb = capgb; - } - - /* - * store small-signal parameters (for meyer's model) - * all parameters already stored, so done... - */ - - - if(SenCond){ - if(ckt->CKTsenInfo->SENmode & (DCSEN|ACSEN)) { - continue; - } - } + *(ckt->CKTstate0 + here->MOS3qbd) = + here->MOS3tBulkPot*(here->MOS3Cbd* + (1-arg*sarg) + /(1-model->MOS3bulkJctBotGradingCoeff) + +here->MOS3Cbdsw* + (1-arg*sargsw) + /(1-model->MOS3bulkJctSideGradingCoeff)); + here->MOS3capbd=here->MOS3Cbd*sarg+ + here->MOS3Cbdsw*sargsw; + } else { + *(ckt->CKTstate0 + here->MOS3qbd) = here->MOS3f4d + + vbd * (here->MOS3f2d + vbd * here->MOS3f3d/2); + here->MOS3capbd=here->MOS3f2d + vbd * here->MOS3f3d; + } + } else { + *(ckt->CKTstate0 + here->MOS3qbd) = 0; + here->MOS3capbd = 0; + } + } + if(SenCond && (ckt->CKTsenInfo->SENmode==TRANSEN)) goto next2; + + if ( ckt->CKTmode & MODETRAN ) { + /* (above only excludes tranop, since we're only at this + * point if tran or tranop ) + */ + + /* + * calculate equivalent conductances and currents for + * depletion capacitors + */ + + /* integrate the capacitors and save results */ + + error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbd, + here->MOS3qbd); + if(error) return(error); + here->MOS3gbd += geq; + here->MOS3cbd += *(ckt->CKTstate0 + here->MOS3cqbd); + here->MOS3cd -= *(ckt->CKTstate0 + here->MOS3cqbd); + error = NIintegrate(ckt,&geq,&ceq,here->MOS3capbs, + here->MOS3qbs); + if(error) return(error); + here->MOS3gbs += geq; + here->MOS3cbs += *(ckt->CKTstate0 + here->MOS3cqbs); + } + } + if(SenCond) goto next2; + + /* + * check convergence + */ + if ( (here->MOS3off == 0) || + (!(ckt->CKTmode & (MODEINITFIX|MODEINITSMSIG))) ){ + if (Check == 1) { + ckt->CKTnoncon++; + ckt->CKTtroubleElt = (GENinstance *) here; + } + } + + + /* save things away for next time */ + + next2: *(ckt->CKTstate0 + here->MOS3vbs) = vbs; + *(ckt->CKTstate0 + here->MOS3vbd) = vbd; + *(ckt->CKTstate0 + here->MOS3vgs) = vgs; + *(ckt->CKTstate0 + here->MOS3vds) = vds; + + + /* + * meyer's capacitor model + */ + if ( ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG) ) { + /* + * calculate meyer's capacitors + */ + /* + * new cmeyer - this just evaluates at the current time, + * expects you to remember values from previous time + * returns 1/2 of non-constant portion of capacitance + * you must add in the other half from previous time + * and the constant part + */ + if (here->MOS3mode > 0){ + DEVqmeyer (vgs,vgd,vgb,von,vdsat, + (ckt->CKTstate0 + here->MOS3capgs), + (ckt->CKTstate0 + here->MOS3capgd), + (ckt->CKTstate0 + here->MOS3capgb), + here->MOS3tPhi,OxideCap); + } else { + DEVqmeyer (vgd,vgs,vgb,von,vdsat, + (ckt->CKTstate0 + here->MOS3capgd), + (ckt->CKTstate0 + here->MOS3capgs), + (ckt->CKTstate0 + here->MOS3capgb), + here->MOS3tPhi,OxideCap); + } + vgs1 = *(ckt->CKTstate1 + here->MOS3vgs); + vgd1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vds); + vgb1 = vgs1 - *(ckt->CKTstate1 + here->MOS3vbs); + if(ckt->CKTmode & MODETRANOP) { + capgs = 2 * *(ckt->CKTstate0+here->MOS3capgs)+ + GateSourceOverlapCap ; + capgd = 2 * *(ckt->CKTstate0+here->MOS3capgd)+ + GateDrainOverlapCap ; + capgb = 2 * *(ckt->CKTstate0+here->MOS3capgb)+ + GateBulkOverlapCap ; + } else { + capgs = ( *(ckt->CKTstate0+here->MOS3capgs)+ + *(ckt->CKTstate1+here->MOS3capgs) + + GateSourceOverlapCap ); + capgd = ( *(ckt->CKTstate0+here->MOS3capgd)+ + *(ckt->CKTstate1+here->MOS3capgd) + + GateDrainOverlapCap ); + capgb = ( *(ckt->CKTstate0+here->MOS3capgb)+ + *(ckt->CKTstate1+here->MOS3capgb) + + GateBulkOverlapCap ); + } + if(ckt->CKTsenInfo){ + here->MOS3cgs = capgs; + here->MOS3cgd = capgd; + here->MOS3cgb = capgb; + } + + /* + * store small-signal parameters (for meyer's model) + * all parameters already stored, so done... + */ + + + if(SenCond){ + if(ckt->CKTsenInfo->SENmode & (DCSEN|ACSEN)) { + continue; + } + } #ifndef PREDICTOR - if (ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { - *(ckt->CKTstate0 + here->MOS3qgs) = - (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgs) - - xfact * *(ckt->CKTstate2 + here->MOS3qgs); - *(ckt->CKTstate0 + here->MOS3qgd) = - (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgd) - - xfact * *(ckt->CKTstate2 + here->MOS3qgd); - *(ckt->CKTstate0 + here->MOS3qgb) = - (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgb) - - xfact * *(ckt->CKTstate2 + here->MOS3qgb); - } else { + if (ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) { + *(ckt->CKTstate0 + here->MOS3qgs) = + (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgs) + - xfact * *(ckt->CKTstate2 + here->MOS3qgs); + *(ckt->CKTstate0 + here->MOS3qgd) = + (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgd) + - xfact * *(ckt->CKTstate2 + here->MOS3qgd); + *(ckt->CKTstate0 + here->MOS3qgb) = + (1+xfact) * *(ckt->CKTstate1 + here->MOS3qgb) + - xfact * *(ckt->CKTstate2 + here->MOS3qgb); + } else { #endif /*PREDICTOR*/ - if(ckt->CKTmode & MODETRAN) { - *(ckt->CKTstate0 + here->MOS3qgs) = (vgs-vgs1)*capgs + - *(ckt->CKTstate1 + here->MOS3qgs) ; - *(ckt->CKTstate0 + here->MOS3qgd) = (vgd-vgd1)*capgd + - *(ckt->CKTstate1 + here->MOS3qgd) ; - *(ckt->CKTstate0 + here->MOS3qgb) = (vgb-vgb1)*capgb + - *(ckt->CKTstate1 + here->MOS3qgb) ; - } else { - /* TRANOP only */ - *(ckt->CKTstate0 + here->MOS3qgs) = vgs*capgs; - *(ckt->CKTstate0 + here->MOS3qgd) = vgd*capgd; - *(ckt->CKTstate0 + here->MOS3qgb) = vgb*capgb; - } + if(ckt->CKTmode & MODETRAN) { + *(ckt->CKTstate0 + here->MOS3qgs) = (vgs-vgs1)*capgs + + *(ckt->CKTstate1 + here->MOS3qgs) ; + *(ckt->CKTstate0 + here->MOS3qgd) = (vgd-vgd1)*capgd + + *(ckt->CKTstate1 + here->MOS3qgd) ; + *(ckt->CKTstate0 + here->MOS3qgb) = (vgb-vgb1)*capgb + + *(ckt->CKTstate1 + here->MOS3qgb) ; + } else { + /* TRANOP only */ + *(ckt->CKTstate0 + here->MOS3qgs) = vgs*capgs; + *(ckt->CKTstate0 + here->MOS3qgd) = vgd*capgd; + *(ckt->CKTstate0 + here->MOS3qgb) = vgb*capgb; + } #ifndef PREDICTOR - } + } #endif /*PREDICTOR*/ - } -bypass: - if(SenCond) continue; - - if ( (ckt->CKTmode & (MODEINITTRAN)) || - (! (ckt->CKTmode & (MODETRAN)) ) ) { - /* - * initialize to zero charge conductances - * and current - */ - gcgs=0; - ceqgs=0; - gcgd=0; - ceqgd=0; - gcgb=0; - ceqgb=0; - } else { - if(capgs == 0) *(ckt->CKTstate0 + here->MOS3cqgs) =0; - if(capgd == 0) *(ckt->CKTstate0 + here->MOS3cqgd) =0; - if(capgb == 0) *(ckt->CKTstate0 + here->MOS3cqgb) =0; - /* - * calculate equivalent conductances and currents for - * meyer"s capacitors - */ - error = NIintegrate(ckt,&gcgs,&ceqgs,capgs,here->MOS3qgs); - if(error) return(error); - error = NIintegrate(ckt,&gcgd,&ceqgd,capgd,here->MOS3qgd); - if(error) return(error); - error = NIintegrate(ckt,&gcgb,&ceqgb,capgb,here->MOS3qgb); - if(error) return(error); - ceqgs=ceqgs-gcgs*vgs+ckt->CKTag[0]* - *(ckt->CKTstate0 + here->MOS3qgs); - ceqgd=ceqgd-gcgd*vgd+ckt->CKTag[0]* - *(ckt->CKTstate0 + here->MOS3qgd); - ceqgb=ceqgb-gcgb*vgb+ckt->CKTag[0]* - *(ckt->CKTstate0 + here->MOS3qgb); - } - /* - * store charge storage info for meyer's cap in lx table - */ - - /* - * load current vector - */ - ceqbs = model->MOS3type * - (here->MOS3cbs-(here->MOS3gbs)*vbs); - ceqbd = model->MOS3type * - (here->MOS3cbd-(here->MOS3gbd)*vbd); - if (here->MOS3mode >= 0) { - xnrm=1; - xrev=0; - cdreq=model->MOS3type*(cdrain-here->MOS3gds*vds- - here->MOS3gm*vgs-here->MOS3gmbs*vbs); - } else { - xnrm=0; - xrev=1; - cdreq = -(model->MOS3type)*(cdrain-here->MOS3gds*(-vds)- - here->MOS3gm*vgd-here->MOS3gmbs*vbd); - } - *(ckt->CKTrhs + here->MOS3gNode) -= - (model->MOS3type * (ceqgs + ceqgb + ceqgd)); - *(ckt->CKTrhs + here->MOS3bNode) -= - (ceqbs + ceqbd - model->MOS3type * ceqgb); - *(ckt->CKTrhs + here->MOS3dNodePrime) += - (ceqbd - cdreq + model->MOS3type * ceqgd); - *(ckt->CKTrhs + here->MOS3sNodePrime) += - cdreq + ceqbs + model->MOS3type * ceqgs; - /* - * load y matrix - */ -/*printf(" loading %s at time %g\n",here->MOS3name,ckt->CKTtime);*/ -/*printf("%g %g %g %g %g\n", here->MOS3drainConductance,gcgd+gcgs+gcgb, - here->MOS3sourceConductance,here->MOS3gbd,here->MOS3gbs);*/ -/*printf("%g %g %g %g %g\n",-gcgb,0.0,0.0,here->MOS3gds,here->MOS3gm);*/ -/*printf("%g %g %g %g %g\n", here->MOS3gds,here->MOS3gmbs,gcgd,-gcgs,-gcgd);*/ -/*printf("%g %g %g %g %g\n", -gcgs,-gcgd,0.0,-gcgs,0.0);*/ - - *(here->MOS3DdPtr) += (here->MOS3drainConductance); - *(here->MOS3GgPtr) += ((gcgd+gcgs+gcgb)); - *(here->MOS3SsPtr) += (here->MOS3sourceConductance); - *(here->MOS3BbPtr) += (here->MOS3gbd+here->MOS3gbs+gcgb); - *(here->MOS3DPdpPtr) += - (here->MOS3drainConductance+here->MOS3gds+ - here->MOS3gbd+xrev*(here->MOS3gm+here->MOS3gmbs)+gcgd); - *(here->MOS3SPspPtr) += - (here->MOS3sourceConductance+here->MOS3gds+ - here->MOS3gbs+xnrm*(here->MOS3gm+here->MOS3gmbs)+gcgs); - *(here->MOS3DdpPtr) += (-here->MOS3drainConductance); - *(here->MOS3GbPtr) -= gcgb; - *(here->MOS3GdpPtr) -= gcgd; - *(here->MOS3GspPtr) -= gcgs; - *(here->MOS3SspPtr) += (-here->MOS3sourceConductance); - *(here->MOS3BgPtr) -= gcgb; - *(here->MOS3BdpPtr) -= here->MOS3gbd; - *(here->MOS3BspPtr) -= here->MOS3gbs; - *(here->MOS3DPdPtr) += (-here->MOS3drainConductance); - *(here->MOS3DPgPtr) += ((xnrm-xrev)*here->MOS3gm-gcgd); - *(here->MOS3DPbPtr) += (-here->MOS3gbd+(xnrm-xrev)*here->MOS3gmbs); - *(here->MOS3DPspPtr) += (-here->MOS3gds- - xnrm*(here->MOS3gm+here->MOS3gmbs)); - *(here->MOS3SPgPtr) += (-(xnrm-xrev)*here->MOS3gm-gcgs); - *(here->MOS3SPsPtr) += (-here->MOS3sourceConductance); - *(here->MOS3SPbPtr) += (-here->MOS3gbs-(xnrm-xrev)*here->MOS3gmbs); - *(here->MOS3SPdpPtr) += (-here->MOS3gds- - xrev*(here->MOS3gm+here->MOS3gmbs)); - } + } + bypass: + if(SenCond) continue; + + if ( (ckt->CKTmode & (MODEINITTRAN)) || + (! (ckt->CKTmode & (MODETRAN)) ) ) { + /* + * initialize to zero charge conductances + * and current + */ + gcgs=0; + ceqgs=0; + gcgd=0; + ceqgd=0; + gcgb=0; + ceqgb=0; + } else { + if(capgs == 0) *(ckt->CKTstate0 + here->MOS3cqgs) =0; + if(capgd == 0) *(ckt->CKTstate0 + here->MOS3cqgd) =0; + if(capgb == 0) *(ckt->CKTstate0 + here->MOS3cqgb) =0; + /* + * calculate equivalent conductances and currents for + * meyer"s capacitors + */ + error = NIintegrate(ckt,&gcgs,&ceqgs,capgs,here->MOS3qgs); + if(error) return(error); + error = NIintegrate(ckt,&gcgd,&ceqgd,capgd,here->MOS3qgd); + if(error) return(error); + error = NIintegrate(ckt,&gcgb,&ceqgb,capgb,here->MOS3qgb); + if(error) return(error); + ceqgs=ceqgs-gcgs*vgs+ckt->CKTag[0]* + *(ckt->CKTstate0 + here->MOS3qgs); + ceqgd=ceqgd-gcgd*vgd+ckt->CKTag[0]* + *(ckt->CKTstate0 + here->MOS3qgd); + ceqgb=ceqgb-gcgb*vgb+ckt->CKTag[0]* + *(ckt->CKTstate0 + here->MOS3qgb); + } + /* + * store charge storage info for meyer's cap in lx table + */ + + /* + * load current vector + */ + ceqbs = model->MOS3type * + (here->MOS3cbs-(here->MOS3gbs)*vbs); + ceqbd = model->MOS3type * + (here->MOS3cbd-(here->MOS3gbd)*vbd); + if (here->MOS3mode >= 0) { + xnrm=1; + xrev=0; + cdreq=model->MOS3type*(cdrain-here->MOS3gds*vds- + here->MOS3gm*vgs-here->MOS3gmbs*vbs); + } else { + xnrm=0; + xrev=1; + cdreq = -(model->MOS3type)*(cdrain-here->MOS3gds*(-vds)- + here->MOS3gm*vgd-here->MOS3gmbs*vbd); + } + *(ckt->CKTrhs + here->MOS3gNode) -= + (model->MOS3type * (ceqgs + ceqgb + ceqgd)); + *(ckt->CKTrhs + here->MOS3bNode) -= + (ceqbs + ceqbd - model->MOS3type * ceqgb); + *(ckt->CKTrhs + here->MOS3dNodePrime) += + (ceqbd - cdreq + model->MOS3type * ceqgd); + *(ckt->CKTrhs + here->MOS3sNodePrime) += + cdreq + ceqbs + model->MOS3type * ceqgs; + /* + * load y matrix + */ + *(here->MOS3DdPtr) += (here->MOS3drainConductance); + *(here->MOS3GgPtr) += ((gcgd+gcgs+gcgb)); + *(here->MOS3SsPtr) += (here->MOS3sourceConductance); + *(here->MOS3BbPtr) += (here->MOS3gbd+here->MOS3gbs+gcgb); + *(here->MOS3DPdpPtr) += + (here->MOS3drainConductance+here->MOS3gds+ + here->MOS3gbd+xrev*(here->MOS3gm+here->MOS3gmbs)+gcgd); + *(here->MOS3SPspPtr) += + (here->MOS3sourceConductance+here->MOS3gds+ + here->MOS3gbs+xnrm*(here->MOS3gm+here->MOS3gmbs)+gcgs); + *(here->MOS3DdpPtr) += (-here->MOS3drainConductance); + *(here->MOS3GbPtr) -= gcgb; + *(here->MOS3GdpPtr) -= gcgd; + *(here->MOS3GspPtr) -= gcgs; + *(here->MOS3SspPtr) += (-here->MOS3sourceConductance); + *(here->MOS3BgPtr) -= gcgb; + *(here->MOS3BdpPtr) -= here->MOS3gbd; + *(here->MOS3BspPtr) -= here->MOS3gbs; + *(here->MOS3DPdPtr) += (-here->MOS3drainConductance); + *(here->MOS3DPgPtr) += ((xnrm-xrev)*here->MOS3gm-gcgd); + *(here->MOS3DPbPtr) += (-here->MOS3gbd+(xnrm-xrev)*here->MOS3gmbs); + *(here->MOS3DPspPtr) += (-here->MOS3gds- + xnrm*(here->MOS3gm+here->MOS3gmbs)); + *(here->MOS3SPgPtr) += (-(xnrm-xrev)*here->MOS3gm-gcgs); + *(here->MOS3SPsPtr) += (-here->MOS3sourceConductance); + *(here->MOS3SPbPtr) += (-here->MOS3gbs-(xnrm-xrev)*here->MOS3gmbs); + *(here->MOS3SPdpPtr) += (-here->MOS3gds- + xrev*(here->MOS3gm+here->MOS3gmbs)); + } + } } return(OK); } + diff --git a/src/spicelib/devices/mos6/mos6set.c b/src/spicelib/devices/mos6/mos6set.c index 1bc793dc3..705c5dcf5 100644 --- a/src/spicelib/devices/mos6/mos6set.c +++ b/src/spicelib/devices/mos6/mos6set.c @@ -116,11 +116,11 @@ MOS6setup(matrix,inModel,ckt,states) /* loop through all the instances of the model */ for (here = model->MOS6instances; here != NULL ; here=here->MOS6nextInstance) { - if (here->MOS6owner != ARCHme) goto matrixpointers; - CKTnode *tmpNode; IFuid tmpName; + if (here->MOS6owner != ARCHme) goto matrixpointers; + if(!here->MOS6drainPerimiterGiven) { here->MOS6drainPerimiter = 0; } diff --git a/src/spicelib/devices/sw/swtrunc.c b/src/spicelib/devices/sw/swtrunc.c index c75b0e92d..150a34182 100644 --- a/src/spicelib/devices/sw/swtrunc.c +++ b/src/spicelib/devices/sw/swtrunc.c @@ -6,13 +6,13 @@ Modified: 2000 AlansFixes /* */ -#include "spice.h" +#include "ngspice.h" #include #include "cktdefs.h" -#include "sw\swdefs.h" #include "sperror.h" #include "suffix.h" +#include "swdefs.h" int SWtrunc(inModel,ckt,timeStep) diff --git a/src/spicelib/parser/inppas2.c b/src/spicelib/parser/inppas2.c index 41bf7b52f..278883153 100644 --- a/src/spicelib/parser/inppas2.c +++ b/src/spicelib/parser/inppas2.c @@ -10,9 +10,8 @@ Author: 1985 Thomas L. Quarles #include "inppas2.h" -/* pass 2 - Scan through the lines. ".model" cards have processed - * in pass1 and are ignored here. - */ +/* pass 2 - Scan through the lines. ".model" cards have processed in + * pass1 and are ignored here. */ void INPpas2(void *ckt, card * data, INPtables * tab, void *task) { @@ -45,103 +44,133 @@ void INPpas2(void *ckt, card * data, INPtables * tab, void *task) switch (c) { - case ' ': /* blank line (space leading) */ - case '\t': /* blank line (tab leading) */ + case ' ': + /* blank line (space leading) */ + case '\t': + /* blank line (tab leading) */ break; - case 'R': /* Rname [][][w=][l=] */ + case 'R': + /* Rname [][][w=][l=] */ INP2R(ckt, tab, current); break; - case 'C': /* Cname [IC=] */ + + case 'C': + /* Cname [IC=] */ INP2C(ckt, tab, current); break; - case 'L': /* Lname [IC=] */ + + case 'L': + /* Lname [IC=] */ INP2L(ckt, tab, current); break; - case 'G': /* Gname */ + + case 'G': + /* Gname */ INP2G(ckt, tab, current); break; - case 'E': /* Ename */ + + case 'E': + /* Ename */ INP2E(ckt, tab, current); break; - case 'F': /* Fname */ + + case 'F': + /* Fname */ INP2F(ckt, tab, current); break; - case 'H': /* Hname */ + + case 'H': + /* Hname */ INP2H(ckt, tab, current); break; - case 'D': /* Dname [] [OFF] [IC=] */ + + case 'D': + /* Dname [] [OFF] [IC=] */ INP2D(ckt, tab, current); break; - case 'J': /* Jname [] [OFF] - * [IC=,] */ + + case 'J': + /* Jname [] [OFF] + [IC=,] */ INP2J(ckt, tab, current); break; - case 'Z': /* Zname [] [OFF] - * [IC=,] */ + + case 'Z': + /* Zname [] [OFF] + [IC=,] */ INP2Z(ckt, tab, current); break; - case 'M': /* Mname [L=] - * [W=] [AD=] [AS=] [PD=] - * [PS=] [NRD=] [NRS=] [OFF] - * [IC=,,] */ + + case 'M': + /* Mname [L=] + [W=] [AD=] [AS=] [PD=] + [PS=] [NRD=] [NRS=] [OFF] + [IC=,,] */ INP2M(ckt, tab, current); break; - case 'O': /* Oname - * [IC=,,,] */ + case 'O': + /* Oname + [IC=,,,] */ INP2O(ckt, tab, current); break; - case 'V': /* Vname [ [DC] ] [AC [ [ ] ] ] - * [] */ + case 'V': + /* Vname [ [DC] ] [AC [ [ ] ] ] + [] */ INP2V(ckt, tab, current); break; - case 'I': /* Iname [ [DC] ] [AC [ [ ] ] ] - * [] */ + + case 'I': + /* Iname [ [DC] ] [AC [ [ ] ] ] + [] */ INP2I(ckt, tab, current); break; - case 'Q': /* Qname [] [] [OFF] - * [IC=,] */ + case 'Q': + /* Qname [] [] [OFF] + [IC=,] */ INP2Q(ckt, tab, current, gnode); break; - case 'T': /* Tname [TD=] - * [F= [NL=]][IC=,,,] */ + case 'T': + /* Tname [TD=] + [F= [NL=]][IC=,,,] */ INP2T(ckt, tab, current); break; - case 'S': /* Sname [] [IC] */ + case 'S': + /* Sname [] [IC] */ INP2S(ckt, tab, current); break; - case 'W': /* Wname [] [IC] */ + case 'W': + /* Wname [] [IC] */ /* CURRENT CONTROLLED SWITCH */ INP2W(ckt, tab, current); break; - case 'U': /* Uname [l=] [n=] */ + case 'U': + /* Uname [l=] [n=] */ INP2U(ckt, tab, current); break; - case 'K': /* Kname Lname Lname */ + case 'K': + /* Kname Lname Lname */ INP2K(ckt, tab, current); break; - case '*': /* * - a comment - ignore */ + case '*': + /* * - a comment - ignore */ break; - case 'B': /* Bname [V=expr] [I=expr] */ + case 'B': + /* Bname [V=expr] [I=expr] */ /* Arbitrary source. */ INP2B(ckt, tab, current); break; - case '.': /* . Many possibilities */ - if (INP2dot(ckt, tab, current, task, gnode)) - goto end; - break; - case 0: break; @@ -151,6 +180,6 @@ void INPpas2(void *ckt, card * data, INPtables * tab, void *task) break; } } - end: + return; } diff --git a/src/spicelib/parser/inppas3.c b/src/spicelib/parser/inppas3.c index d675ea259..db8b2bf1d 100644 --- a/src/spicelib/parser/inppas3.c +++ b/src/spicelib/parser/inppas3.c @@ -7,100 +7,112 @@ Modified: AlansFixes #include #include #include +#include #include #include "inppas3.h" +extern IFsimulator *ft_sim; -/* pass 3 - Read all nodeset and IC lines. All circuit nodes will have been - * created by now, (except for internal device nodes), so any nodeset or IC - * nodes which have to be created are flagged with a warning. - */ + +/* pass 3 - Read all nodeset and IC lines. All circuit nodes will have + * been created by now, (except for internal device nodes), so any + * nodeset or IC nodes which have to be created are flagged with a + * warning. */ void -INPpas3(void *ckt, card *data, INPtables *tab, void *task) +INPpas3(void *ckt, card *data, INPtables *tab, void *task, + IFparm *nodeParms, int numNodeParms) { -card *current; -int error; /* used by the macros defined above */ -char *line; /* the part of the current line left to parse */ -char *name; /* the node's name */ -char *token; /* a token from the line */ -IFparm *prm; /* pointer to parameter to search through array */ -IFvalue ptemp; /* a value structure to package resistance into */ -int which; /* which analysis we are performing */ -int length; /* length of a name */ -void *node1; /* the first node's node pointer */ + card *current; + int error; /* used by the macros defined above */ + char *line; /* the part of the current line left + to parse */ + char *name; /* the node's name */ + char *token; /* a token from the line */ + IFparm *prm; /* pointer to parameter to search + through array */ + IFvalue ptemp; /* a value structure to package + resistance into */ + int which; /* which analysis we are performing */ + int length; /* length of a name */ + void *node1; /* the first node's node pointer */ for(current = data; current != NULL; current = current->nextcard) { + line = current->line; + INPgetTok(&line,&token,1); - line = current->line; - INPgetTok(&line,&token,1); + if (strcmp(token,".nodeset")==0) { + which = -1; - if (strcmp(token,".nodeset")==0) { - which = -1; - for(prm=ft_sim->nodeParms; - prmnodeParms+ft_sim->numNodeParms;prm++) { - if(strcmp(prm->keyword,"nodeset")==0) { - which=prm->id; - break; - } - } - if(which == -1) { - LITERR("nodeset unknown to simulator. \n") - return; - } - for(;;) { /* loop until we run out of data */ - INPgetTok(&line,&name,1); - /* check to see if in the form V(xxx) and grab the xxx */ - if( *name == (char)NULL) break; /* end of line */ - length = strlen(name); - if( (*name == 'V' || *(name) == 'v') && (length == 1)){ - /* looks like V - must be V(xx) - get xx now*/ - INPgetTok(&line,&name,1); - if (INPtermInsert(ckt,&name,tab,&node1)!=E_EXISTS) - fprintf(stderr, - "Warning : Nodeset on non-existant node - %s\n", name); - ptemp.rValue = INPevaluate(&line,&error,1); - IFC(setNodeParm,(ckt,node1,which,&ptemp,(IFvalue*)NULL)) - continue; - } - LITERR(" Error: .nodeset syntax error.\n") - break; - } - } else if ( (strcmp(token,".ic")==0)){ - /* .ic */ - which = -1; - for(prm=ft_sim->nodeParms; - prmnodeParms+ft_sim->numNodeParms;prm++) { - if(strcmp(prm->keyword,"ic")==0) { - which=prm->id; - break; - } - } - if(which==-1) { - LITERR("ic unknown to simulator. \n") - return; - } - for(;;) { /* loop until we run out of data */ - INPgetTok(&line,&name,1); - /* check to see if in the form V(xxx) and grab the xxx */ - if( *name == 0) break; /* end of line */ - length = strlen(name); - if( (*name == 'V' || *(name) == 'v') && (length == 1)){ - /* looks like V - must be V(xx) - get xx now*/ - INPgetTok(&line,&name,1); - if (INPtermInsert(ckt,&name,tab,&node1)!=E_EXISTS) - fprintf(stderr, - "Warning : IC on non-existant node - %s\n", name); - ptemp.rValue = INPevaluate(&line,&error,1); - IFC(setNodeParm,(ckt,node1,which,&ptemp,(IFvalue*)NULL)) - continue; - } - LITERR(" Error: .ic syntax error.\n") - break; - } - } + for(prm = nodeParms; prm < nodeParms + numNodeParms; prm++) { + if(strcmp(prm->keyword,"nodeset")==0) { + which = prm->id; + break; + } + } + + if(which == -1) { + LITERR("nodeset unknown to simulator. \n") + return; + } + + for(;;) { + /* loop until we run out of data */ + INPgetTok(&line,&name,1); + + /* check to see if in the form V(xxx) and grab the xxx */ + if( *name == (char)NULL) break; /* end of line */ + length = strlen(name); + if( (*name == 'V' || *(name) == 'v') && (length == 1)){ + /* looks like V - must be V(xx) - get xx now*/ + INPgetTok(&line,&name,1); + if (INPtermInsert(ckt,&name,tab,&node1)!=E_EXISTS) + fprintf(stderr, + "Warning : Nodeset on non-existant node - %s\n", name); + ptemp.rValue = INPevaluate(&line,&error,1); + IFC(setNodeParm,(ckt,node1,which,&ptemp,(IFvalue*)NULL)); + continue; + } + LITERR(" Error: .nodeset syntax error.\n") + break; + } + } else if ((strcmp(token,".ic") == 0)) { + /* .ic */ + which = -1; + for(prm = nodeParms; prm < nodeParms + numNodeParms; prm++) { + if(strcmp(prm->keyword,"ic")==0) { + which = prm->id; + break; + } + } + + if(which==-1) { + LITERR("ic unknown to simulator. \n") + return; + } + + for(;;) { + /* loop until we run out of data */ + INPgetTok(&line,&name,1); + /* check to see if in the form V(xxx) and grab the xxx */ + if( *name == 0) break; /* end of line */ + length = strlen(name); + if( (*name == 'V' || *(name) == 'v') && (length == 1)){ + /* looks like V - must be V(xx) - get xx now*/ + INPgetTok(&line,&name,1); + if (INPtermInsert(ckt,&name,tab,&node1)!=E_EXISTS) + fprintf(stderr, + "Warning : IC on non-existant node - %s\n", name); + ptemp.rValue = INPevaluate(&line,&error,1); + IFC(setNodeParm,(ckt,node1,which,&ptemp,(IFvalue*)NULL)) + continue; + } + LITERR(" Error: .ic syntax error.\n") + break; + } + } } return; } diff --git a/src/spicelib/parser/inppas3.h b/src/spicelib/parser/inppas3.h index 27b46885a..c58fb12a5 100644 --- a/src/spicelib/parser/inppas3.h +++ b/src/spicelib/parser/inppas3.h @@ -4,7 +4,8 @@ #include -void INPpas3(void *ckt, card *data, INPtables *tab, void *task); +void INPpas3(void *ckt, card *data, INPtables *tab, void *task, + IFparm *nodeParms, int numNodeParams); #endif