From 0875108157a3d380577ba31b33f85773db66737b Mon Sep 17 00:00:00 2001 From: pnenzi Date: Sun, 3 Sep 2000 09:00:08 +0000 Subject: [PATCH] Added patches extracted from Alan Gillespie's code. Documentation and author's file not updated. --- src/frontend/device.c | 72 +++-- src/frontend/device.h | 4 + src/frontend/dotcards.c | 30 +- src/frontend/outitf.c | 439 +++++++++++++++++++++++--- src/frontend/runcoms.c | 19 +- src/frontend/spiceif.c | 10 + src/frontend/subckt.c | 9 + src/include/cktdefs.h | 9 +- src/include/cpextern.h | 2 + src/include/devdefs.h | 2 +- src/include/distodef.h | 25 +- src/include/fteext.h | 29 +- src/include/hlpdefs.h | 3 +- src/include/inpdefs.h | 2 + src/include/optdefs.h | 12 + src/include/sensgen.h | 1 + src/include/smpdefs.h | 2 + src/include/tskdefs.h | 8 + src/misc/dup2.c | 3 +- src/spicelib/analysis/cktdojob.c | 8 + src/spicelib/analysis/cktload.c | 18 +- src/spicelib/analysis/cktntask.c | 10 + src/spicelib/analysis/cktop.c | 296 +++++++++++++++-- src/spicelib/analysis/cktsens.c | 5 +- src/spicelib/analysis/cktsopt.c | 35 +- src/spicelib/analysis/ckttyplk.c | 2 +- src/spicelib/analysis/dcop.c | 44 ++- src/spicelib/analysis/dctran.c | 65 +++- src/spicelib/analysis/traninit.c | 5 +- src/spicelib/devices/bjt/bjtdisto.c | 3 +- src/spicelib/devices/bjt/bjtext.h | 4 + src/spicelib/devices/bjt/bjtload.c | 77 +++-- src/spicelib/devices/bjt/bjtsetup.c | 41 +++ src/spicelib/devices/bjt/bjttemp.c | 4 +- src/spicelib/devices/bsim1/b1disto.c | 3 +- src/spicelib/devices/bsim1/b1set.c | 19 ++ src/spicelib/devices/bsim1/bsim1ext.h | 2 + src/spicelib/devices/bsim2/b2set.c | 16 + src/spicelib/devices/bsim3/b3.c | 2 + src/spicelib/devices/bsim3/b3acld.c | 114 +++---- src/spicelib/devices/bsim3/b3ask.c | 68 ++-- src/spicelib/devices/bsim3/b3ld.c | 125 ++++---- src/spicelib/devices/bsim3/b3par.c | 5 + src/spicelib/devices/bsim3/b3set.c | 27 +- src/spicelib/devices/bsim3/bsim3def.h | 5 +- src/spicelib/devices/cap/capask.c | 6 +- src/spicelib/devices/cktinit.c | 8 +- src/spicelib/devices/csw/Makefile.am | 3 +- src/spicelib/devices/csw/cswdefs.h | 3 +- src/spicelib/devices/csw/cswext.h | 5 + src/spicelib/devices/csw/cswinit.c | 4 +- src/spicelib/devices/csw/cswload.c | 8 + src/spicelib/devices/devsup.c | 25 +- src/spicelib/devices/dio/dioext.h | 4 + src/spicelib/devices/dio/dioload.c | 13 +- src/spicelib/devices/dio/diosetup.c | 13 + src/spicelib/devices/dio/diotemp.c | 10 +- src/spicelib/devices/isrc/isrcload.c | 2 + src/spicelib/devices/isrc/isrcpar.c | 12 + src/spicelib/devices/jfet/jfetext.h | 3 + src/spicelib/devices/jfet/jfetload.c | 31 +- src/spicelib/devices/jfet/jfetset.c | 24 ++ src/spicelib/devices/ltra/ltraext.h | 3 + src/spicelib/devices/mes/mesext.h | 3 + src/spicelib/devices/mes/mesload.c | 20 +- src/spicelib/devices/mes/messetup.c | 24 ++ src/spicelib/devices/mos1/mos1.c | 2 + src/spicelib/devices/mos1/mos1acld.c | 9 +- src/spicelib/devices/mos1/mos1ask.c | 29 +- src/spicelib/devices/mos1/mos1defs.h | 6 +- src/spicelib/devices/mos1/mos1dset.c | 22 +- src/spicelib/devices/mos1/mos1ext.h | 2 + src/spicelib/devices/mos1/mos1load.c | 59 ++-- src/spicelib/devices/mos1/mos1noi.c | 2 + src/spicelib/devices/mos1/mos1par.c | 5 + src/spicelib/devices/mos1/mos1pzld.c | 9 +- src/spicelib/devices/mos1/mos1set.c | 24 ++ src/spicelib/devices/mos1/mos1sprt.c | 6 +- src/spicelib/devices/mos1/mos1temp.c | 40 ++- src/spicelib/devices/mos2/mos2.c | 2 + src/spicelib/devices/mos2/mos2acld.c | 7 +- src/spicelib/devices/mos2/mos2ask.c | 29 +- src/spicelib/devices/mos2/mos2defs.h | 6 + src/spicelib/devices/mos2/mos2dset.c | 25 +- src/spicelib/devices/mos2/mos2ext.h | 4 + src/spicelib/devices/mos2/mos2load.c | 66 ++-- src/spicelib/devices/mos2/mos2noi.c | 4 +- src/spicelib/devices/mos2/mos2par.c | 5 + src/spicelib/devices/mos2/mos2pzld.c | 9 +- src/spicelib/devices/mos2/mos2set.c | 26 +- src/spicelib/devices/mos2/mos2sprt.c | 5 +- src/spicelib/devices/mos2/mos2temp.c | 40 ++- src/spicelib/devices/mos3/mos3.c | 7 + src/spicelib/devices/mos3/mos3acld.c | 14 +- src/spicelib/devices/mos3/mos3ask.c | 32 +- src/spicelib/devices/mos3/mos3defs.h | 17 + src/spicelib/devices/mos3/mos3dset.c | 39 ++- src/spicelib/devices/mos3/mos3ext.h | 2 + src/spicelib/devices/mos3/mos3load.c | 119 ++++--- src/spicelib/devices/mos3/mos3mask.c | 19 ++ src/spicelib/devices/mos3/mos3mpar.c | 17 + src/spicelib/devices/mos3/mos3noi.c | 4 +- src/spicelib/devices/mos3/mos3par.c | 6 + src/spicelib/devices/mos3/mos3pzld.c | 13 +- src/spicelib/devices/mos3/mos3set.c | 34 +- src/spicelib/devices/mos3/mos3sld.c | 14 +- src/spicelib/devices/mos3/mos3sprt.c | 5 +- src/spicelib/devices/mos3/mos3temp.c | 91 ++++-- src/spicelib/devices/mos6/mos6ask.c | 21 +- src/spicelib/devices/mos6/mos6load.c | 29 +- src/spicelib/devices/mos6/mos6set.c | 20 ++ src/spicelib/devices/res/res.c | 2 + src/spicelib/devices/res/resdefs.h | 4 + src/spicelib/devices/res/resmask.c | 4 + src/spicelib/devices/res/resmpar.c | 5 + src/spicelib/devices/res/restemp.c | 4 +- src/spicelib/devices/sw/Makefile.am | 3 +- src/spicelib/devices/sw/swdefs.h | 3 +- src/spicelib/devices/sw/swext.h | 3 + src/spicelib/devices/sw/swinit.c | 3 +- src/spicelib/devices/sw/swload.c | 11 +- src/spicelib/devices/vsrc/vsrcload.c | 51 ++- src/spicelib/devices/vsrc/vsrcpar.c | 11 + src/spicelib/parser/ChangeLog | 4 + src/spicelib/parser/Makefile.am | 3 + src/spicelib/parser/inp2dot.c | 5 +- src/spicelib/parser/inpgtok.c | 11 +- 127 files changed, 2313 insertions(+), 668 deletions(-) diff --git a/src/frontend/device.c b/src/frontend/device.c index 736cb59f8..07edaefda 100644 --- a/src/frontend/device.c +++ b/src/frontend/device.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -76,7 +77,7 @@ all_show(wordlist *wl, int mode) if (!cp_getvar("width", VT_NUM, (char *) &screen_width)) screen_width = DEF_WIDTH; - count = screen_width / 11 - 1; + count = (screen_width - LEFT_WIDTH) / (DEV_WIDTH + 1); n = 0; do { @@ -168,7 +169,7 @@ all_show(wordlist *wl, int mode) i = 0; do { - printf(" device "); + printf("%*s", LEFT_WIDTH, "device"); j = dgen_for_n(dg, count, printstr, "n", i); i += 1; printf("\n"); @@ -177,7 +178,7 @@ all_show(wordlist *wl, int mode) if (ft_sim->devices[dg->dev_type_no]->numModelParms) { i = 0; do { - printf(" model "); + printf("%*s", LEFT_WIDTH, "model"); j = dgen_for_n(dg, count, printstr, "m", i); i += 1; printf("\n"); @@ -200,7 +201,7 @@ all_show(wordlist *wl, int mode) n += 1; i = 0; do { - printf(" model "); + printf("%*s", LEFT_WIDTH, "model"); j = dgen_for_n(dg, count, printstr, "m", i); i += 1; printf("\n"); @@ -236,16 +237,16 @@ printstr(dgen *dg, char *name) { if (*name == 'n') { if (dg->instance) - printf(" %9.9s", dg->instance->GENname); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, dg->instance->GENname); else - printf(" "); + printf(" %*s", DEV_WIDTH, ""); } else if (*name == 'm') { if (dg->model) - printf(" %9.9s", dg->model->GENmodName); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, dg->model->GENmodName); else - printf(" "); + printf(" %*s", DEV_WIDTH, ""); } else - printf(" "); + printf(" %*s", DEV_WIDTH, ""); return 0; } @@ -278,9 +279,10 @@ param_forall(dgen *dg, int flags) j = 0; do { if (!j) - printf("%10.10s", plist[i].keyword); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, + plist[i].keyword); else - printf(" "); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, " "); k = dgen_for_n(dg, count, printvals, (char *) (plist + i), j); printf("\n"); @@ -323,9 +325,9 @@ listparam(wordlist *p, dgen *dg) j = 0; do { if (!j) - printf("%10.10s", p->wl_word); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word); else - printf(" "); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, " "); k = dgen_for_n(dg, count, printvals, plist + i, j); printf("\n"); j += 1; @@ -334,9 +336,9 @@ listparam(wordlist *p, dgen *dg) j = 0; do { if (!j) - printf("%10.10s", p->wl_word); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word); else - printf(" "); + printf("%*s", LEFT_WIDTH, " "); k = dgen_for_n(dg, count, bogus1, 0, j); printf("\n"); j += 1; @@ -346,9 +348,9 @@ listparam(wordlist *p, dgen *dg) j = 0; do { if (!j) - printf("%10.10s", p->wl_word); + printf("%*.*s", LEFT_WIDTH, LEFT_WIDTH, p->wl_word); else - printf(" "); + printf("%*s", LEFT_WIDTH, " "); k = dgen_for_n(dg, count, bogus2, 0, j); printf("\n"); j += 1; @@ -358,13 +360,13 @@ listparam(wordlist *p, dgen *dg) int bogus1(dgen *dg) { - printf(" ---------"); + printf(" %*s", DEV_WIDTH, "---------"); return 0; } int bogus2(dgen *dg) { - printf(" ?????????"); + printf(" %*s", DEV_WIDTH, "?????????"); return 0; } @@ -400,54 +402,54 @@ printvals(dgen *dg, IFparm *p, int i) if (p->dataType & IF_VECTOR) { switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) { case IF_FLAG: - printf(" % 9d", val.v.vec.iVec[i]); + printf(" % *d", DEV_WIDTH, val.v.vec.iVec[i]); break; case IF_INTEGER: - printf(" % 9d", val.v.vec.iVec[i]); + printf(" % *d", DEV_WIDTH, val.v.vec.iVec[i]); break; case IF_REAL: - printf(" % 9.3g", val.v.vec.rVec[i]); + printf(" % *.6g", DEV_WIDTH, val.v.vec.rVec[i]); break; case IF_COMPLEX: if (!(i % 2)) - printf(" % 9.3g", val.v.vec.cVec[i / 2].real); + printf(" % *.6g", DEV_WIDTH, val.v.vec.cVec[i / 2].real); else - printf(" % 9.3g", val.v.vec.cVec[i / 2].imag); + printf(" % *.6g", DEV_WIDTH, val.v.vec.cVec[i / 2].imag); break; case IF_STRING: - printf(" %9.9s", val.v.vec.sVec[i]); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, val.v.vec.sVec[i]); break; case IF_INSTANCE: - printf(" %9.9s", val.v.vec.uVec[i]); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, val.v.vec.uVec[i]); break; default: - printf(" ******** "); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, " ******** "); } } else { switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) { case IF_FLAG: - printf(" % 9d", val.iValue); + printf(" % *d", DEV_WIDTH, val.iValue); break; case IF_INTEGER: - printf(" % 9d", val.iValue); + printf(" % *d", DEV_WIDTH, val.iValue); break; case IF_REAL: - printf(" % 9.3g", val.rValue); + printf(" % *.6g", DEV_WIDTH, val.rValue); break; case IF_COMPLEX: if (i % 2) - printf(" % 9.3g", val.cValue.real); + printf(" % *.6g", DEV_WIDTH, val.cValue.real); else - printf(" % 9.3g", val.cValue.imag); + printf(" % *.6g", DEV_WIDTH, val.cValue.imag); break; case IF_STRING: - printf(" %9.9s", val.sValue); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, val.sValue); break; case IF_INSTANCE: - printf(" %9.9s ", val.uValue); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, val.uValue); break; default: - printf(" ******** "); + printf(" % *.*s", DEV_WIDTH, DEV_WIDTH, " ******** "); } } diff --git a/src/frontend/device.h b/src/frontend/device.h index 4899e7d8f..3daf76c69 100644 --- a/src/frontend/device.h +++ b/src/frontend/device.h @@ -1,11 +1,15 @@ /************* * Header file for device.c * 1999 E. Rouat + * Modified: 2000 AlansFixes ************/ #ifndef DEVICE_H_INCLUDED #define DEVICE_H_INCLUDED +#define LEFT_WIDTH 11 +#define DEV_WIDTH 21 + void com_showmod(wordlist *wl); void com_show(wordlist *wl); int printstr(dgen *dg, char *name); diff --git a/src/frontend/dotcards.c b/src/frontend/dotcards.c index e28857f6d..b291684b3 100644 --- a/src/frontend/dotcards.c +++ b/src/frontend/dotcards.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -154,19 +155,14 @@ ft_cktcoms(bool terse) if (!ft_curckt) return 1; - if (!ft_curckt->ci_commands) + if (!ft_curckt->ci_commands && !setcplot("op")) goto nocmds; coms = ft_curckt->ci_commands; cp_interactive = FALSE; - /* Circuit name */ - fprintf(cp_out, "Circuit: %s\nDate: %s\n\n", ft_curckt->ci_name, - datestring()); - fprintf(cp_out, "\n"); - /* Listing */ if (ft_listprint) { - if (terse) + if (FALSE) fprintf(cp_err, ".options: no listing, rawfile was generated.\n"); else inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options, @@ -174,12 +170,12 @@ ft_cktcoms(bool terse) } /* If there was a .op line, then we have to do the .op output. */ - if (setcplot("op")) { - if (terse) { + if (setcplot("op") && (plot_cur->pl_dvecs->v_realdata!=NULL)) { + if (FALSE) { fprintf(cp_out, "OP information in rawfile.\n"); } else { - fprintf(cp_out, "\nOperating point information:\n\n"); - fprintf(cp_out, "\tNode\tVoltage\n"); + fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage"); + fprintf(cp_out, "\t%-30s%15s\n", "----", "-------"); fprintf(cp_out, "\t----\t-------\n"); for (v = plot_cur->pl_dvecs; v; v = v->v_next) { if (!isreal(v)) { @@ -188,17 +184,17 @@ ft_cktcoms(bool terse) v->v_name); continue; } - if (v->v_type == SV_VOLTAGE) - fprintf(cp_out, "\t%s\t%s\n", v->v_name, + if ((v->v_type == SV_VOLTAGE) && (*(v->v_name)!='@')) + fprintf(cp_out, "\t%-30s%15s\n", v->v_name, printnum(v->v_realdata[0])); } fprintf(cp_out, "\n\tSource\tCurrent\n"); fprintf(cp_out, "\t------\t-------\n\n"); for (v = plot_cur->pl_dvecs; v; v = v->v_next) if (v->v_type == SV_CURRENT) - fprintf(cp_out, "\t%s\t%s\n", v->v_name, - printnum(v->v_realdata[0])); - fprintf(cp_out, "\n"); + fprintf(cp_out, "\t%-30s%15s\n", v->v_name, + printnum(v->v_realdata[0])); + fprintf(cp_out, "\n"); if (!ft_nomod) com_showmod(&all); @@ -320,7 +316,7 @@ nocmds: /* The options */ if (ft_optsprint) { - fprintf(cp_err, "Options:\n\n"); + fprintf(cp_out, "Options:\n\n"); cp_vprint(); (void) putc('\n', cp_out); } diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 025599da8..9f12b0504 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -20,10 +21,12 @@ Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ifsim.h" #include "jobdefs.h" #include "iferrmsg.h" - #include "circuits.h" #include "outitf.h" #include "variable.h" +#include +#include +#include "cktdefs.h" extern void gr_end_iplot(void); @@ -56,11 +59,14 @@ static void freeRun(runDesc *run); #define DOUBLE_PRECISION 15 - +static clock_t lastclock, currclock; +static float *rowbuf; +static int column, rowbuflen; static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */ static bool printinfo = FALSE; /* Print informational "error messages". */ + /* The two "begin plot" routines share all their internals... */ @@ -110,7 +116,9 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch int numsaves; int i, j, depind; char namebuf[BSIZE_SP], parambuf[BSIZE_SP], depbuf[BSIZE_SP]; - bool saveall = TRUE; + char *ch, tmpname[BSIZE_SP]; + bool saveall = TRUE; + bool savealli = FALSE; char *an_name; /* Check to see if we want to print informational data. */ @@ -144,12 +152,18 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch savesused[i] = TRUE; continue; } - if (cieq(saves[i].name, "all")) { + if (cieq(saves[i].name, "all") || cieq(saves[i].name, "allv")) { saveall = TRUE; savesused[i] = TRUE; saves[i].used = 1; continue; } + if (cieq(saves[i].name, "alli")) { + savealli = true; + savesused[i] = true; + saves[i].used = 1; + continue; + } } } @@ -183,10 +197,73 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch } else { for (i = 0; i < numNames; i++) if (!refName || !name_eq(dataNames[i], refName)) { - addDataDesc(run, dataNames[i], dataType, i); + if (!strstr(dataNames[i], "#internal") && + !strstr(dataNames[i], "#source") && + !strstr(dataNames[i], "#drain") && + !strstr(dataNames[i], "#collector") && + !strstr(dataNames[i], "#emitter") && + !strstr(dataNames[i], "#base")) { + } } } + /* Pass 1 and a bit. */ + if (savealli) { + depind=0; + for (i = 0; i < numNames; i++) { + if (strstr(dataNames[i], "#internal") || + strstr(dataNames[i], "#source") || + strstr(dataNames[i], "#drain") || + strstr(dataNames[i], "#collector") || + strstr(dataNames[i], "#emitter") || + strstr(dataNames[i], "#base")) { + tmpname[0]='@'; + tmpname[1]='\0'; + strncat(tmpname, dataNames[i], BSIZE_SP-1); + ch=strchr(tmpname, '#'); + + if (strstr(ch, "#collector")!=NULL) { + strcpy(ch, "[ic]"); + } else if (strstr(ch, "#base")!=NULL) { + strcpy(ch, "[ib]"); + } else if (strstr(ch, "#emitter")!=NULL) { + strcpy(ch, "[ie]"); + if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { + addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + }; + strcpy(ch, "[is]"); + } else if (strstr(ch, "#drain")!=NULL) { + strcpy(ch, "[id]"); + if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { + addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + }; + strcpy(ch, "[ig]"); + } else if (strstr(ch, "#source")!=NULL) { + strcpy(ch, "[is]"); + if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { + addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + }; + strcpy(ch, "[ib]"); + } else + if ((strstr(ch, "#internal")!=NULL)&&(tmpname[1]=='d')) { + strcpy(ch, "[id]"); + } else { + fprintf(cp_err, + "Debug: could output current for %s\n", tmpname); + continue; + }; + if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { + if (*depbuf) { fprintf( stderr, + "Warning : unexpected dependant variable on %s\n", tmpname); + } else { + addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + } + } + } + } + } + + /* Pass 2. */ for (i = 0; i < numsaves; i++) { if (savesused[i]) @@ -265,7 +342,9 @@ addDataDesc(runDesc *run, char *name, int type, int ind) dataDesc *data; if (!run->numData) - run->data = (dataDesc *) tmalloc(sizeof (dataDesc)); + {run->data = (dataDesc *) tmalloc(32768); + run->data = (dataDesc *) trealloc(run->data, sizeof (dataDesc)); + } else run->data = (dataDesc *) trealloc((char *) run->data, sizeof (dataDesc) * (run->numData + 1)); @@ -296,7 +375,8 @@ addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind) char *unique; /* unique char * from back-end */ if (!run->numData) - run->data = (dataDesc *) tmalloc(sizeof (dataDesc)); + {run->data = (dataDesc *) tmalloc(32768); + run->data = (dataDesc *) trealloc(run->data, sizeof (dataDesc));} else run->data = (dataDesc *) trealloc((char *) run->data, sizeof (dataDesc) * (run->numData + 1)); @@ -344,12 +424,23 @@ OUTpData(void *plotPtr, IFvalue *refValue, IFvalue *valuePtr) fileStartPoint(run->fp, run->binary, run->pointCount); if (run->refIndex != -1) { - if (run->isComplex) + if (run->isComplex){ fileAddComplexValue(run->fp, run->binary, refValue->cValue); - else + currclock = clock(); + if ((currclock-lastclock)>(0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", + refValue->cValue.real); + lastclock = currclock; + } + } else { fileAddRealValue(run->fp, run->binary, refValue->rValue); + currclock = clock(); + if ((currclock-lastclock)>(0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", refValue->rValue); + lastclock = currclock; + } } - + } for (i = 0; i < run->numData; i++) { /* we've already printed reference vec first */ if (run->data[i].outIndex == -1) continue; @@ -368,7 +459,22 @@ OUTpData(void *plotPtr, IFvalue *refValue, IFvalue *valuePtr) } else { /* should pre-check instance */ if (!getSpecial(&run->data[i], run, &val)) + { + if (run->pointCount==1) + fprintf(stderr, "Warning: unrecognized variable - %s\n", + run->data[i].name); + if (run->isComplex) { + val.cValue.real=0; + val.cValue.imag=0; + fileAddComplexValue(run->fp, run->binary, + val.cValue); + } else { + val.rValue=0; + fileAddRealValue(run->fp, run->binary, + val.rValue); + }; continue; + }; if (run->data[i].type == IF_REAL) fileAddRealValue(run->fp, run->binary, val.rValue); @@ -380,6 +486,10 @@ 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; + }; } else { for (i = 0; i < run->numData; i++) { if (run->data[i].outIndex == -1) { @@ -529,7 +639,12 @@ static void fileInit(runDesc *run) { char buf[513]; - int i; + int i, tmp, sweep; + float ftmp; + time_t time_of_day; + CKTcircuit *ckt; + + lastclock = clock(); /* This is a hack. */ run->isComplex = FALSE; @@ -538,34 +653,163 @@ fileInit(runDesc *run) run->isComplex = TRUE; i = 0; + + /* Write PROBE version marker */ + + tmp=0xFFFFFFFF; + fwrite((char *)&tmp,sizeof(tmp),1,run->fp); + i += sizeof(tmp); + tmp=0xF3FFFFFF; + fwrite((char *)&tmp,sizeof(tmp),1,run->fp); + i += sizeof(tmp); + + /* Write Title String */ + sprintf(buf, "Title: %s\n", run->name); i += strlen(buf); fputs(buf, run->fp); - sprintf(buf, "Date: %s\n", datestring()); + + /* Write \0 for Title string and \0 for empty SubTitle string */ + + tmp=0; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + + /* get the time and date */ + + time_of_day = time( NULL ); + +/* Write Time String */ + + strftime( buf, 9, "%H:%M:%S", + localtime( &time_of_day ) ); + i += strlen(buf); fputs(buf, run->fp); - sprintf(buf, "Plotname: %s\n", run->type); + tmp=0; + fwrite((char *)&tmp,1,1,run->fp); + i += 1; + + /* Write Date String */ + + strftime( buf, 9, "%d/%m/%y", + localtime( &time_of_day ) ); + i += strlen(buf); fputs(buf, run->fp); - sprintf(buf, "Flags: %s\n", run->isComplex ? "complex" : "real"); - i += strlen(buf); - fputs(buf, run->fp); - sprintf(buf, "No. Variables: %d\n", run->numData); - i += strlen(buf); - fputs(buf, run->fp); - sprintf(buf, "No. Points: "); + tmp=0; + fwrite((char *)&tmp,1,1,run->fp); + i += 1; + + /* Write Temperature */ + + ckt=run->circuit; + ftmp=ckt->CKTtemp-273.15; + fwrite((char *)&ftmp,sizeof(ftmp),1,run->fp); + i += sizeof(ftmp); + + + /* Write Analysis Type */ + + if (strnicmp(run->type,"AC",2)==0) { + sprintf(buf, "AC Sweep"); + sweep=2; + } else if (strnicmp(run->type,"DC",2)==0) { + sprintf(buf, "DC Sweep"); + sweep=1; + } else if (strnicmp(run->type,"Tran",4)==0) { + sprintf(buf, "Transient Analysis"); + sweep=4; + }; i += strlen(buf); fputs(buf, run->fp); +/* Write \0 for Analysis Type string and \0 for empty Comment string */ + + tmp=0; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + +/* Write Program ID */ + + tmp=0x00011A22; + fwrite((char *)&tmp,sizeof(tmp),1,run->fp); + i += sizeof(tmp); + +/* Write All-Columns Flag */ + + tmp=0; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + +/* Write Complex-Data Flag */ + + tmp = run->isComplex ? 2 : 1; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + +/* Write Datatype Flag (PROBE_ANALOG) */ + + tmp = 0; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + +/* Write Digital Data Length (meaningless if analogue data) */ + + tmp=0; + fwrite((char *)&tmp,sizeof(tmp),1,run->fp); + i += sizeof(tmp); + +/* Write space for no. of rows */ + fflush(run->fp); /* Gotta do this for LATTICE. */ if (run->fp == stdout || (run->pointPos = ftell(run->fp)) <= 0) run->pointPos = i; - fprintf(run->fp, "0 \n"); /* Save 8 spaces here. */ + tmp=0; + fwrite((char *)&tmp,sizeof(tmp),1,run->fp); + i += sizeof(tmp); - fprintf(run->fp, "Command: version %s\n", ft_sim->version); - fprintf(run->fp, "Variables:\n"); +/* Write no. of cols */ + + fwrite(&(run->numData),2,1,run->fp); + i += 2; +#ifdef AlansFixes + fprintf(stderr, "No. of Data Columns : %d \n", run->numData); +#endif + +/* Write Sweep Mode Flag */ + + fwrite((char *)&sweep,2,1,run->fp); + i += 2; + +/* Write sweep variable start value */ + + ftmp=0; + fwrite((char *)&ftmp,sizeof(ftmp),1,run->fp); + i += sizeof(ftmp); + +/* Write sweep variable end value */ + + ftmp=0; + fwrite((char *)&ftmp,sizeof(ftmp),1,run->fp); + i += sizeof(ftmp); + +/* Write Secondary Sweep Variable name (null string) */ + + tmp=0; + fwrite((char *)&tmp,1,1,run->fp); + i += 1; + +/* Write Digital Section Flag */ + + tmp = 0; + fwrite((char *)&tmp,2,1,run->fp); + i += 2; + + fflush(run->fp); /* Make sure this gets to disk */ return; + } static void @@ -573,34 +817,88 @@ fileInit_pass2(runDesc *run) { int i, type; char *name, buf[BSIZE_SP]; + char *ch, *end; for (i = 0; i < run->numData; i++) { - if (isdigit(*run->data[i].name)) { - (void) sprintf(buf, "V(%s)", run->data[i].name); - name = buf; - } else { - name = run->data[i].name; - } - if (substring("#branch", name)) + + 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); + else + (void) sprintf(name, "V(%s)", run->data[i].name); + + 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")) type = SV_FREQUENCY; 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); + }; - fprintf(run->fp, "\t%d\t%s\t%s", i, name, - ft_typenames(type)); - if (run->data[i].gtype == GRID_XLOG) - fprintf(run->fp, "\tgrid=3"); - fprintf(run->fp, "\n"); + 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++; + }; + }; + + fprintf(run->fp, "%s", name); + tmp=0; + fwrite((char*)&tmp,1,1,run->fp); } - fprintf(run->fp, "%s:\n", run->binary ? "Binary" : "Values"); + fflush(run->fp); /* Make all sure this gets to disk */ + +/* Allocate Row buffer */ + + rowbuflen=(run->numData)*sizeof(float); + if (run->isComplex) rowbuflen *=2; + rowbuf=(float *)tmalloc(rowbuflen); return; + } static void @@ -608,6 +906,11 @@ fileStartPoint(FILE *fp, bool bin, int num) { if (!bin) fprintf(fp, "%d\t", num - 1); + + /* reset set buffer pointer to zero */ + + column = 0; + return; } @@ -615,23 +918,53 @@ fileStartPoint(FILE *fp, bool bin, int num) static void fileAddRealValue(FILE *fp, bool bin, double value) { - if (bin) - fwrite((char *) &value, sizeof (double), 1, fp); - else - fprintf(fp, "\t%.*e\n", DOUBLE_PRECISION, value); - - return; + if (bin) { + if (value<(-FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=(-FLT_MAX); + } else if (value>(FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=FLT_MAX; + } else { + rowbuf[column++]=value; + }; + } else + fprintf(fp, "\t%.*e\n", DOUBLE_PRECISION, value); + + return; } static void fileAddComplexValue(FILE *fp, bool bin, IFcomplex value) { - if (bin) { - fwrite((char *) &value.real, sizeof (double), 1, fp); - fwrite((char *) &value.imag, sizeof (double), 1, fp); - } else { - fprintf(fp, "\t%.*e,%.*e\n", DOUBLE_PRECISION, value.real, + if (bin) { + if (value.real<(-FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=(-FLT_MAX); + } else if (value.real>(FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=FLT_MAX; + } else { + rowbuf[column++]=value.real; + }; + if (value.imag<(-FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=(-FLT_MAX); + } else if (value.imag>(FLT_MAX)) { + fprintf(stderr, + "Warning, double to float conversion overflow !\n"); + rowbuf[column++]=FLT_MAX; + } else { + rowbuf[column++]=value.imag; + }; + } else { + fprintf(fp, "\t%.*e,%.*e\n", DOUBLE_PRECISION, value.real, DOUBLE_PRECISION, value.imag); } @@ -641,6 +974,8 @@ fileAddComplexValue(FILE *fp, bool bin, IFcomplex value) static void fileEndPoint(FILE *fp, bool bin) { + /* write row buffer to file */ + fwrite((char *)rowbuf, rowbuflen, 1, fp); return; } @@ -650,11 +985,15 @@ static void fileEnd(runDesc *run) { long place; + int nrows; + if (run->fp != stdout) { place = ftell(run->fp); fseek(run->fp, run->pointPos, 0); - fprintf(run->fp, "%d", run->pointCount); + nrows=run->pointCount; + fprintf(stderr, "\nNo. of Data Rows : %d\n", nrows); + fwrite(&nrows,sizeof(nrows),1,run->fp); fseek(run->fp, place, 0); } else { /* Yet another hack-around */ @@ -662,6 +1001,10 @@ fileEnd(runDesc *run) } fflush(run->fp); +/* deallocate row buffer */ + + tfree(rowbuf); + return; } diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index 5a9d93a9a..ba98e0bbc 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -34,6 +35,8 @@ extern struct dbcomm *dbs; FILE *rawfileFp; bool rawfileBinary; +#define RAWBUF_SIZE 32768 +char rawfileBuf[RAWBUF_SIZE]; void com_scirc(wordlist *wl) @@ -212,6 +215,7 @@ dosim(char *what, wordlist *wl) if (!*wl->wl_word) rawfileFp = stdout; else if (!(rawfileFp = fopen(wl->wl_word, "w"))) { + setvbuf(rawfileFp, rawfileBuf, _IOFBF, RAWBUF_SIZE); perror(wl->wl_word); ft_setflag = FALSE; return 1; @@ -249,7 +253,12 @@ dosim(char *what, wordlist *wl) ft_curckt->ci_inprogress = FALSE; } if (rawfileFp) - (void) fclose(rawfileFp); + if (ftell(rawfileFp)==0) { + (void) fclose(rawfileFp); + (void) remove(wl->wl_word); + } else { + (void) fclose(rawfileFp); + }; ft_curckt->ci_runonce = TRUE; ft_setflag = FALSE; return err; @@ -284,6 +293,14 @@ bool ft_getOutReq(FILE **fpp, struct plot **plotp, bool *binp, char *name, char *title) { /*struct plot *pl;*/ +#ifndef BATCH +struct plot *pl; + + if ( (strcmp(name, "Operating Point")==0) || + (strcmp(name, "AC Operating Point")==0) ) { + return (false); + }; +#endif if (rawfileFp) { *fpp = rawfileFp; diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index 54dfeef31..92e89bceb 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -92,6 +93,15 @@ if_inpdeck(struct line *deck, 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. + */ + + INPpas3((GENERIC *) ckt, (card *) deck->li_next, + (INPtables *) *tab,ft_curckt->ci_defTask); + return (ckt); } diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 3758011ff..81c5da794 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -114,6 +115,14 @@ inp_subcktexpand(struct line *deck) ll = doit(deck); + /* Now check to see if there are still subckt instances undefined... */ + if (ll!=NULL) for (c = ll; c; c = c->li_next) + if (ciprefix(invoke, c->li_line)) { + fprintf(cp_err, "Error: unknown subckt: %s\n", + c->li_line); + return NULL; + } + return (ll); } diff --git a/src/include/cktdefs.h b/src/include/cktdefs.h index d36fa710b..dfd4f3c81 100644 --- a/src/include/cktdefs.h +++ b/src/include/cktdefs.h @@ -1,6 +1,7 @@ /* * Copyright (c) 1985 Thomas L. Quarles * Modified 1999 Paolo Nenzi - Removed non STDC definitions + * Modified 2000 AlansFixes */ #ifndef CKT #define CKT "CKTdefs.h $Revision$ on $Date$ " @@ -173,6 +174,7 @@ typedef struct { double CKTlteAbstol; #endif /* NEWTRUNC */ double CKTgmin; /* Parallel Conductance --- */ + double CKTgshunt; double CKTdelmin; /* ??? */ double CKTtrtol; /* ??? */ double CKTfinalTime; /* ??? */ @@ -184,7 +186,9 @@ typedef struct { 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 */ @@ -211,6 +215,7 @@ typedef struct { 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 */ @@ -289,7 +294,7 @@ extern int CKTsetBreak( CKTcircuit *, double ); extern int CKTsetNodPm( void *, void *, int , IFvalue *, IFvalue *); extern int CKTsetOpt( void *, void *, int , IFvalue *); extern int CKTsetup( CKTcircuit *); -extern int CKTunsetup(CKTcircuit *ckt); +extern int CKTunsetup(CKTcircuit *); extern int CKTtemp( CKTcircuit *); extern char *CKTtrouble(void *, char *); extern void CKTterr( int , CKTcircuit *, double *); @@ -333,6 +338,8 @@ extern int NIpzSym(PZtrial **, PZtrial *); 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/cpextern.h b/src/include/cpextern.h index 10746a330..8d676b257 100644 --- a/src/include/cpextern.h +++ b/src/include/cpextern.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group +Modified: 2000 AlansFixes **********/ /* @@ -128,6 +129,7 @@ extern bool out_isatty; extern void out_init(); #ifndef out_printf /* don't want to declare it if we have #define'ed it */ + extern void out_printf(); #endif extern void out_send(); diff --git a/src/include/devdefs.h b/src/include/devdefs.h index dcf1e7b29..d776fe14e 100644 --- a/src/include/devdefs.h +++ b/src/include/devdefs.h @@ -86,7 +86,7 @@ typedef struct SPICEdev { } SPICEdev; /* instance of structure for each possible type of device */ -/* IOP( ) Input/output parameter +/* IOP( ) Input/output parameter * IOPP( ) IO parameter which the principle value of a device (used * for naming output variables in sensetivity) * IOPA( ) IO parameter significant for time-varying (non-dc) analyses diff --git a/src/include/distodef.h b/src/include/distodef.h index cf5bfcbec..6d7c5947d 100644 --- a/src/include/distodef.h +++ b/src/include/distodef.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified: 2000 AlansFixes **********/ #ifndef DISTODEF @@ -198,18 +199,18 @@ extern double DFiF12(double, double, double, double, extern double DFn2F12(DpassStr*); extern double DFi2F12(DpassStr*); -extern void EqualDeriv(Dderivs *new, Dderivs *old); -extern void TimesDeriv(Dderivs *new, Dderivs *old, double k); -extern void InvDeriv(Dderivs *new, Dderivs *old); -extern void MultDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2); -extern void CubeDeriv(Dderivs *new, Dderivs *old); -extern void PlusDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2); -extern void SqrtDeriv(Dderivs *new, Dderivs *old); -extern void DivDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2); -extern void PowDeriv(Dderivs *new, Dderivs *old, double emm); -extern void AtanDeriv(Dderivs *new, Dderivs *old); -extern void CosDeriv(Dderivs *new, Dderivs *old); -extern void ExpDeriv(Dderivs *new, Dderivs *old); +extern void EqualDeriv(Dderivs *, Dderivs *); +extern void TimesDeriv(Dderivs *, Dderivs *, double); +extern void InvDeriv(Dderivs *, Dderivs *); +extern void MultDeriv(Dderivs *, Dderivs *, Dderivs *); +extern void CubeDeriv(Dderivs *, Dderivs *); +extern void PlusDeriv(Dderivs *, Dderivs *, Dderivs *); +extern void SqrtDeriv(Dderivs *, Dderivs *); +extern void DivDeriv(Dderivs *, Dderivs *, Dderivs *); +extern void PowDeriv(Dderivs *, Dderivs *, double); +extern void AtanDeriv(Dderivs *, Dderivs *); +extern void CosDeriv(Dderivs *, Dderivs *); +extern void ExpDeriv(Dderivs *, Dderivs *); diff --git a/src/include/fteext.h b/src/include/fteext.h index 6cef7d383..a98e6f9ce 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group -Modified: 1999 Paolo Nenzi +Modified: 1999 Paolo Nenzi - 2000 AlansFixes **********/ /* @@ -49,6 +49,7 @@ extern bool ft_bpcheck(); extern void com_delete(); extern void com_iplot(); extern void com_save(); +extern void com_save2(wordlist *, char *); /* AlansFixes */ extern void com_step(); extern void com_stop(); extern void com_sttus(); @@ -56,6 +57,12 @@ extern void com_trce(); extern void ft_trquery(); extern void dbfree( ); + +/* breakp2.c */ + +extern int ft_getSaves(struct save_info **); /* AlanFixes */ + + /* circuits.c */ extern struct circ *ft_curckt; @@ -180,6 +187,10 @@ extern void fatal(); extern void fperror(); extern void ft_sperror(); extern char ErrorMessage[]; +extern int internalerror(char *); +extern int externalerror(char *); + + /* evaluate.c */ @@ -309,6 +320,7 @@ extern void com_ghelp(); extern void com_help(); extern void com_quit(); extern void com_version(); +extern int hcomp(); extern void com_where(); /* numparse.c */ @@ -337,14 +349,14 @@ extern int cp_userset(); extern struct func ft_funcs[]; extern struct func func_not; extern struct func func_uminus; -struct pnode * ft_getpnames(wordlist *wl, bool check); +struct struct pnode * ft_getpnames(wordlist *wl, bool check); extern void free_pnode(); /* plotcurve.c */ - -int ft_findpoint(double pt, double *lims, int maxp, int minp, bool islog); -double * ft_minmax(struct dvec *v, bool real); -void ft_graf(struct dvec *v, struct dvec *xs, bool nostart); +/* AlansFixes */ +extern int ft_findpoint(double pt, double *lims, int maxp, int minp, bool islog); +extern double * ft_minmax(struct dvec *v, bool real); +extern void ft_graf(struct dvec *v, struct dvec *xs, bool nostart); /* plotinterface.c */ @@ -374,9 +386,8 @@ extern void com_setscale(); extern void com_transpose(); /* rawfile.c */ - extern int raw_prec; -void raw_write(char *name, struct plot *pl, bool app, bool binary); +extern void raw_write(char *name, struct plot *pl, bool app, bool binary); extern struct plot *raw_read(); /* resource.c */ @@ -402,6 +413,8 @@ extern void com_disto(); extern void com_noise(); extern int ft_dorun(); +extern bool ft_getOutReq(FILE **, struct plot **, bool *, char *, char *); + /* spice.c & nutmeg.c */ extern bool ft_nutmeg; diff --git a/src/include/hlpdefs.h b/src/include/hlpdefs.h index d539cbc17..c2ff3f004 100644 --- a/src/include/hlpdefs.h +++ b/src/include/hlpdefs.h @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group -Modified 1999 Emmanuel Rouat +Modified 1999 Emmanuel Rouat - 2000 AlansFixes **********/ /* @@ -118,6 +118,7 @@ extern void hlp_pathfix(char *buf); extern topic *hlp_read(fplace *place); extern void hlp_free(void); extern long findsubject(char *filename, char *subject); +extern bool hlp_approvedfile(); /* provide.c */ diff --git a/src/include/inpdefs.h b/src/include/inpdefs.h index c898be798..788e3be2a 100644 --- a/src/include/inpdefs.h +++ b/src/include/inpdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifndef INP @@ -103,6 +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 *); int INPpName(char*,IFvalue*,void*,int,void*); int INPtermInsert(void*,char**,INPtables*,void**); int INPmkTerm(void*,char**,INPtables*,void**); diff --git a/src/include/optdefs.h b/src/include/optdefs.h index d31eb690a..0b83067ff 100644 --- a/src/include/optdefs.h +++ b/src/include/optdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifndef OPT @@ -104,4 +105,15 @@ typedef struct { #define OPT_TRANSYNC 59 #define OPT_ACSYNC 60 +/* AlansFixes: It is not possible to use the same numbers of the + original Alan code. The following options are all AlansFixes */ + +#define OPT_GSHUNT 61 /* Original: 48 */ +#define OPT_DEFM 62 /* Original: 46 */ +#define OPT_GMINFACT 63 /* Original: 47 */ +#define OPT_COPYNODESETS 64 /* Original: 49 (NodesetFix) */ +#define OPT_NODEDAMPING 65 /* Original: 50 (Node_Damping) */ +#define OPT_ABSDV 66 /* Original: 51 (Node_Damping) */ +#define OPT_RELDV 67 /* Original: 52 (Node_Damping) */ + #endif /*OPT*/ diff --git a/src/include/sensgen.h b/src/include/sensgen.h index 60aaa76cd..fe3a4e004 100644 --- a/src/include/sensgen.h +++ b/src/include/sensgen.h @@ -18,3 +18,4 @@ struct s_sgen { extern sgen *sgen_init( ); extern int sgen_next( ); +extern int sgen_setp(sgen*, CKTcircuit*, IFvalue* ); /* AlansFixes */ diff --git a/src/include/smpdefs.h b/src/include/smpdefs.h index 38694cf71..a051b2ad0 100644 --- a/src/include/smpdefs.h +++ b/src/include/smpdefs.h @@ -7,6 +7,7 @@ typedef struct MatrixElement *SMPelement; /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "complex.h" @@ -36,6 +37,7 @@ SMPelement * SMPfindElt( SMPmatrix *, int , int , int ); int SMPcZeroCol(SMPmatrix *eMatrix, int Col); int SMPcAddCol(SMPmatrix *eMatrix, int Accum_Col, int Addend_Col); int SMPzeroRow(SMPmatrix *eMatrix, int Row); +void spConstMult(SMPmatrix*, double); #ifdef PARALLEL_ARCH void SMPcombine(SMPmatrix *Matrix, double RHS[], double Spare[]); void SMPcCombine(SMPmatrix *Matrix, double RHS[], double Spare[], diff --git a/src/include/tskdefs.h b/src/include/tskdefs.h index f009e8744..e1c2b1d7d 100644 --- a/src/include/tskdefs.h +++ b/src/include/tskdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -45,8 +46,10 @@ typedef struct { double TSKlteAbstol; #endif /* NEWTRUNC */ double TSKgmin; + double TSKgshunt; /* shunt conductance (CKTdiagGmin) */ double TSKdelmin; double TSKtrtol; + double TSKdefaultMosM; double TSKdefaultMosL; double TSKdefaultMosW; double TSKdefaultMosAD; @@ -56,6 +59,11 @@ typedef struct { unsigned int TSKtryToCompact:1; /* flag for LTRA lines */ unsigned int TSKbadMos3:1; /* flag for MOS3 models */ unsigned int TSKkeepOpInfo:1; /* flag for small signal analyses */ + unsigned int TSKcopyNodesets:1; /* flag for nodeset copy */ + unsigned int TSKnodeDamping:1; /* flag for node damping */ + double TSKabsDv; /* abs limit for iter-iter voltage change */ + double TSKrelDv; /* rel limit for iter-iter voltage change */ + }TSKtask; #endif /*TSK*/ diff --git a/src/misc/dup2.c b/src/misc/dup2.c index b25bd8861..5b343b091 100644 --- a/src/misc/dup2.c +++ b/src/misc/dup2.c @@ -1,3 +1,4 @@ +/* Modified: 2000 AlansFixes */ #include #include "ngspice.h" #include "dup2.h" @@ -16,5 +17,5 @@ dup2(int oldd, int newd) return 0; } #else -int Dummy_Symbol; +int Dummy_Symbol_2; #endif diff --git a/src/spicelib/analysis/cktdojob.c b/src/spicelib/analysis/cktdojob.c index 5a124e915..d1d454016 100644 --- a/src/spicelib/analysis/cktdojob.c +++ b/src/spicelib/analysis/cktdojob.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -47,6 +48,7 @@ CKTdoJob(void *inCkt, int reset, void *inTask) ckt->CKTtranMaxIter = task->TSKtranMaxIter; ckt->CKTnumSrcSteps = task->TSKnumSrcSteps; ckt->CKTnumGminSteps = task->TSKnumGminSteps; + ckt->CKTgminFactor = task->TSKgminFactor; ckt->CKTminBreak = task->TSKminBreak; ckt->CKTabstol = task->TSKabstol; ckt->CKTpivotAbsTol = task->TSKpivotAbsTol; @@ -55,8 +57,10 @@ CKTdoJob(void *inCkt, int reset, void *inTask) ckt->CKTchgtol = task->TSKchgtol; ckt->CKTvoltTol = task->TSKvoltTol; ckt->CKTgmin = task->TSKgmin; + ckt->CKTgshunt = task->TSKgshunt; ckt->CKTdelmin = task->TSKdelmin; ckt->CKTtrtol = task->TSKtrtol; + ckt->CKTdefaultMosM = task->TSKdefaultMosM; ckt->CKTdefaultMosL = task->TSKdefaultMosL; ckt->CKTdefaultMosW = task->TSKdefaultMosW; ckt->CKTdefaultMosAD = task->TSKdefaultMosAD; @@ -66,6 +70,10 @@ CKTdoJob(void *inCkt, int reset, void *inTask) ckt->CKTtryToCompact = task->TSKtryToCompact; ckt->CKTbadMos3 = task->TSKbadMos3; ckt->CKTkeepOpInfo = task->TSKkeepOpInfo; + ckt->CKTcopyNodesets = task->TSKcopyNodesets; + ckt->CKTnodeDamping = task->TSKnodeDamping; + ckt->CKTabsDv = task->TSKabsDv; + ckt->CKTrelDv = task->TSKrelDv; ckt->CKTtroubleNode = 0; ckt->CKTtroubleElt = NULL; #ifdef NEWTRUNC diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index 8510b8b02..2d200681e 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFIxes **********/ /* */ @@ -76,10 +77,12 @@ CKTload(CKTcircuit *ckt) if (ZeroNoncurRow(ckt->CKTmatrix, ckt->CKTnodes, node->number)) { - *(ckt->CKTrhs+node->number) = 1.0e10 * node->nodeset; + *(ckt->CKTrhs+node->number) = 1.0e10 * node->nodeset * + ckt->CKTsrcFact; *(node->ptr) = 1e10; } else { - *(ckt->CKTrhs+node->number) = node->nodeset; + *(ckt->CKTrhs+node->number) = node->nodeset * + ckt->CKTsrcFact; *(node->ptr) = 1; } /* DAG: Original CIDER fix. If above fix doesn't work, @@ -98,10 +101,17 @@ CKTload(CKTcircuit *ckt) if (ZeroNoncurRow(ckt->CKTmatrix, ckt->CKTnodes, node->number)) { - *(ckt->CKTrhs+node->number) += 1.0e10 * node->ic; + /* Original code: + *(ckt->CKTrhs+node->number) += 1.0e10 * node->ic; + */ + *(ckt->CKTrhs+node->number) = 1.0e10 * node->ic * + ckt->CKTsrcFact; /* AlansFixes */ *(node->ptr) += 1.0e10; } else { - *(ckt->CKTrhs+node->number) = node->ic; + /* Original code: + *(ckt->CKTrhs+node->number) = node->ic; + */ + *(ckt->CKTrhs+node->number) = node->ic*ckt->CKTsrcFact; /* AlansFixes */ *(node->ptr) = 1; } /* DAG: Original CIDER fix. If above fix doesn't work, diff --git a/src/spicelib/analysis/cktntask.c b/src/spicelib/analysis/cktntask.c index 1281df12a..606ccfdaf 100644 --- a/src/spicelib/analysis/cktntask.c +++ b/src/spicelib/analysis/cktntask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -24,6 +25,7 @@ CKTnewTask(void *ckt, void **taskPtr, IFuid taskName) tsk = *(TSKtask **)taskPtr; tsk->TSKname = taskName; tsk->TSKgmin = 1e-12; + tsk->TSKgshunt = 0; tsk->TSKabstol = 1e-12; tsk->TSKreltol = 1e-3; tsk->TSKchgtol = 1e-14; @@ -39,12 +41,16 @@ CKTnewTask(void *ckt, void **taskPtr, IFuid taskName) tsk->TSKdcTrcvMaxIter = 50; tsk->TSKintegrateMethod = TRAPEZOIDAL; tsk->TSKmaxOrder = 2; + tsk->TSKnumSrcSteps = 1; + tsk->TSKnumGminSteps = 1; tsk->TSKnumSrcSteps = 10; tsk->TSKnumGminSteps = 10; + tsk->TSKgminFactor = 10; tsk->TSKpivotAbsTol = 1e-13; tsk->TSKpivotRelTol = 1e-3; tsk->TSKtemp = 300.15; tsk->TSKnomTemp = 300.15; + tsk->TSKdefaultMosM = 1; tsk->TSKdefaultMosL = 1e-4; tsk->TSKdefaultMosW = 1e-4; tsk->TSKdefaultMosAD = 0; @@ -53,5 +59,9 @@ CKTnewTask(void *ckt, void **taskPtr, IFuid taskName) tsk->TSKtryToCompact=0; tsk->TSKbadMos3=0; tsk->TSKkeepOpInfo=0; + tsk->TSKcopyNodesets=0; + tsk->TSKnodeDamping=0; + tsk->TSKabsDv=0.5; + tsk->TSKrelDv=2.0; return(OK); } diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 7eba90df2..a98d24770 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -15,7 +16,11 @@ CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) { int converged; int i; - + CKTnode *n; /* AlansFixes */ + double raise, ConvFact, NumNodes; /* AlansFixes */ + double *OldRhsOld, *OldCKTstate0; /* AlansFixes */ + int iters; + ckt->CKTmode = firstmode; if(!ckt->CKTnoOpIter) { converged = NIiter(ckt,iterlim); @@ -28,29 +33,138 @@ CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) /* note that no path out of this code allows ckt->CKTdiagGmin to be * anything but 0.000000000 */ - if(ckt->CKTnumGminSteps >1) { + + if(ckt->CKTnumGminSteps ==1) { + + double OldGmin, gtarget, factor; + int success, failed; + + ckt->CKTmode = firstmode; + (*(SPfrontEnd->IFerror))(ERR_INFO, + "trying dynamic Gmin stepping",(IFuid *)NULL); + NumNodes=0; + for (n = ckt->CKTnodes; n; n = n->next) { + NumNodes++; + }; + OldRhsOld=(double *)MALLOC((NumNodes+1)*sizeof(double)); + OldCKTstate0=(double *) + MALLOC((ckt->CKTnumStates+1)*sizeof(double)); + for (n = ckt->CKTnodes; n; n = n->next) { + *(ckt->CKTrhsOld+n->number)=0; + }; + for(i=0;iCKTnumStates;i++) { + *(ckt->CKTstate0+i) = 0; + }; + factor = ckt->CKTgminFactor; + OldGmin = 1e-2; + ckt->CKTdiagGmin = OldGmin / factor; + gtarget = MAX(ckt->CKTgmin,ckt->CKTgshunt); + success = failed = 0; + + while ( (!success) && (!failed) ) { + fprintf(stderr, "\rTrying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon =1; + iters = ckt->CKTstat->STATnumIter; + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + iters = (ckt->CKTstat->STATnumIter)-iters; + if(converged == 0) { + ckt->CKTmode=continuemode; + (*(SPfrontEnd->IFerror))(ERR_INFO, + "One successful Gmin step",(IFuid *)NULL); + if (ckt->CKTdiagGmin <= gtarget) { + success = 1; + } else { + i=0; + for (n = ckt->CKTnodes; n; n = n->next) { + OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); + i++; + }; + for(i=0;iCKTnumStates;i++) { + *(OldCKTstate0+i) = *(ckt->CKTstate0+i); + }; + if (iters <= (ckt->CKTdcTrcvMaxIter/4)) { + factor *= sqrt(factor); + if (factor > ckt->CKTgminFactor) + factor = ckt->CKTgminFactor; + }; + if (iters > (3*ckt->CKTdcTrcvMaxIter/4)) { + factor = sqrt(factor); + }; + OldGmin = ckt->CKTdiagGmin; + if ((ckt->CKTdiagGmin) < (factor*gtarget)) { + factor = ckt->CKTdiagGmin / gtarget; + ckt->CKTdiagGmin = gtarget; + } else { + ckt->CKTdiagGmin /= factor; + }; + }; + } else { + if (factor < 1.00005) { + failed = 1; + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "last gmin step failed",(IFuid *)NULL); + } else { + factor=sqrt(sqrt(factor)); + ckt->CKTdiagGmin = OldGmin / factor; + i=0; + for (n = ckt->CKTnodes; n; n = n->next) { + *(ckt->CKTrhsOld+n->number)=OldRhsOld[i]; + i++; + }; + for(i=0;iCKTnumStates;i++) { + *(ckt->CKTstate0+i) = *(OldCKTstate0+i); + }; + }; + } + } + ckt->CKTdiagGmin=ckt->CKTgshunt; + FREE(OldRhsOld); + FREE(OldCKTstate0); + converged = NIiter(ckt,iterlim); + if (converged!=0) { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "dynamic gmin stepping failed",(IFuid *)NULL); + } else { + (*(SPfrontEnd->IFerror))(ERR_INFO, + "Dynamic gmin stepping completed",(IFuid *)NULL); + return(0); + }; + + } else if(ckt->CKTnumGminSteps >1) { + ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror))(ERR_INFO, "starting Gmin stepping",(IFuid *)NULL); - ckt->CKTdiagGmin = ckt->CKTgmin; + + if (ckt->CKTgshunt==0) { + ckt->CKTdiagGmin = ckt->CKTgmin; + } else { + ckt->CKTdiagGmin = ckt->CKTgshunt; + }; + + for(i=0;iCKTnumGminSteps;i++) { - ckt->CKTdiagGmin *= 10; + ckt->CKTdiagGmin *= ckt->CKTgminFactor; + + } for(i=0;i<=ckt->CKTnumGminSteps;i++) { + fprintf(stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); ckt->CKTnoncon =1; - converged = NIiter(ckt,iterlim); + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); if(converged != 0) { - ckt->CKTdiagGmin = 0; + ckt->CKTdiagGmin = ckt->CKTgshunt; + (*(SPfrontEnd->IFerror))(ERR_WARNING, "Gmin step failed",(IFuid *)NULL); break; } - ckt->CKTdiagGmin /= 10; + ckt->CKTdiagGmin /= ckt->CKTgminFactor; ckt->CKTmode=continuemode; (*(SPfrontEnd->IFerror))(ERR_INFO, "One successful Gmin step",(IFuid *)NULL); } - ckt->CKTdiagGmin = 0; + ckt->CKTdiagGmin = ckt->CKTgshunt; converged = NIiter(ckt,iterlim); if(converged == 0) { (*(SPfrontEnd->IFerror))(ERR_INFO, @@ -68,28 +182,162 @@ CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) * note that no path out of this code allows ckt->CKTsrcFact to be * anything but 1.000000000 */ - if(ckt->CKTnumSrcSteps >1) { + + + if(ckt->CKTnumSrcSteps >=1) { ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror))(ERR_INFO, "starting source stepping",(IFuid *)NULL); - for(i=0;i<=ckt->CKTnumSrcSteps;i++) { - ckt->CKTsrcFact = ((double)i)/((double)ckt->CKTnumSrcSteps); - converged = NIiter(ckt,iterlim); - ckt->CKTmode = continuemode; + if(ckt->CKTnumSrcSteps==1) { + ckt->CKTsrcFact=0; raise=0.001; ConvFact=0; + NumNodes=0; + for (n = ckt->CKTnodes; n; n = n->next) { + NumNodes++; + }; + OldRhsOld=(double *)MALLOC((NumNodes+1)*sizeof(double)); + OldCKTstate0=(double *) + MALLOC((ckt->CKTnumStates+1)*sizeof(double)); + for (n = ckt->CKTnodes; n; n = n->next) { + *(ckt->CKTrhsOld+n->number)=0; + }; + for(i=0;iCKTnumStates;i++) { + *(ckt->CKTstate0+i) = 0; + }; + +/* First, try a straight solution with all sources at zero */ + + fprintf(stderr, "\rSupplies reduced to %8.4f%% ", + ckt->CKTsrcFact*100); + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + +/* If this doesn't work, try gmin stepping as well for the first solution */ + if(converged != 0) { - ckt->CKTsrcFact = 1; - ckt->CKTcurrentAnalysis = DOING_TRAN; - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "source stepping failed",(IFuid *)NULL); - return(converged); + fprintf(stderr, "\n"); + if (ckt->CKTgshunt<=0) { + ckt->CKTdiagGmin = ckt->CKTgmin; + } else { + ckt->CKTdiagGmin = ckt->CKTgshunt; + }; + for(i=0;i<10;i++) { + ckt->CKTdiagGmin *= 10; + } + for(i=0;i<=10;i++) { + fprintf(stderr, "Trying gmin = %12.4E ", + ckt->CKTdiagGmin); + ckt->CKTnoncon =1; + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + if(converged != 0) { + ckt->CKTdiagGmin = ckt->CKTgshunt; + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "Gmin step failed",(IFuid *)NULL); + break; + } + + ckt->CKTdiagGmin /= 10; + ckt->CKTmode=continuemode; + (*(SPfrontEnd->IFerror))(ERR_INFO, + "One successful Gmin step",(IFuid *)NULL); + } + ckt->CKTdiagGmin = ckt->CKTgshunt; + }; + +/* If we've got convergence, then try stepping up the sources */ + + if(converged == 0) { + i=0; + for (n = ckt->CKTnodes; n; n = n->next) { + OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); + i++; + }; + for(i=0;iCKTnumStates;i++) { + *(OldCKTstate0+i) = *(ckt->CKTstate0+i); + }; + (*(SPfrontEnd->IFerror))(ERR_INFO, + "One successful source step",(IFuid *)NULL); + ckt->CKTsrcFact=ConvFact+raise; + }; + + if(converged == 0) do { + fprintf(stderr, "\rSupplies reduced to %8.4f%% ", + ckt->CKTsrcFact*100); + + iters = ckt->CKTstat->STATnumIter; + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + iters = (ckt->CKTstat->STATnumIter)-iters; + + ckt->CKTmode = continuemode; + if (converged == 0) { + ConvFact=ckt->CKTsrcFact; + i=0; + for (n = ckt->CKTnodes; n; n = n->next) { + OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); + i++; + }; + for(i=0;iCKTnumStates;i++) { + *(OldCKTstate0+i) = *(ckt->CKTstate0+i); + }; + (*(SPfrontEnd->IFerror))(ERR_INFO, + "One successful source step",(IFuid *)NULL); + ckt->CKTsrcFact=ConvFact+raise; + if (iters <= (ckt->CKTdcTrcvMaxIter/4)) { + raise=raise*1.5; + }; + if (iters > (3*ckt->CKTdcTrcvMaxIter/4)) { + raise=raise*0.5; + }; +/* if (raise>0.01) raise=0.01; */ + } else { + if ((ckt->CKTsrcFact-ConvFact)<1e-8) break; + raise=raise/10; + if (raise>0.01) raise=0.01; + ckt->CKTsrcFact=ConvFact; + i=0; + for (n = ckt->CKTnodes; n; n = n->next) { + *(ckt->CKTrhsOld+n->number)=OldRhsOld[i]; + i++; + }; + for(i=0;iCKTnumStates;i++) { + *(ckt->CKTstate0+i) = *(OldCKTstate0+i); + }; + }; + if ((ckt->CKTsrcFact)>1) ckt->CKTsrcFact=1; + } while ((raise>=1e-7) && (ConvFact<1)); + + FREE(OldRhsOld); + FREE(OldCKTstate0); + ckt->CKTsrcFact = 1; + if (ConvFact!=1) { + ckt->CKTsrcFact = 1; + ckt->CKTcurrentAnalysis = DOING_TRAN; + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "source stepping failed",(IFuid *)NULL); + return(E_ITERLIM); + } else { + (*(SPfrontEnd->IFerror))(ERR_INFO, + "Source stepping completed",(IFuid *)NULL); + return(0); + }; + } else { + for(i=0;i<=ckt->CKTnumSrcSteps;i++) { + ckt->CKTsrcFact = ((double)i)/((double)ckt->CKTnumSrcSteps); + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + ckt->CKTmode = continuemode; + if(converged != 0) { + ckt->CKTsrcFact = 1; + ckt->CKTcurrentAnalysis = DOING_TRAN; + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "source stepping failed",(IFuid *)NULL); + return(converged); + } + (*(SPfrontEnd->IFerror))(ERR_INFO, + "One successful source step",(IFuid *)NULL); } (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful source step",(IFuid *)NULL); - } - (*(SPfrontEnd->IFerror))(ERR_INFO, - "Source stepping completed",(IFuid *)NULL); - ckt->CKTsrcFact = 1; - return(0); + "Source stepping completed",(IFuid *)NULL); + ckt->CKTsrcFact = 1; + return(0); + }; } else { return(converged); } diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 38a43418b..7efd971ef 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -1,5 +1,6 @@ /********** Copyright 1991 Regents of the University of California. All rights reserved. +Modified: 2000 AlanFixes **********/ #include "ngspice.h" @@ -549,7 +550,9 @@ int sens_sens(CKTcircuit *ckt, int restart) nvalue.v.vec.cVec = output_cvalues; value.rValue = freq; - OUTpData(sen_data, &value, &nvalue); + + (*(SPfrontEnd->OUTpData))(sen_data, &value, &nvalue); + freq = inc_freq(freq, sen_info->step_type, step_size); } diff --git a/src/spicelib/analysis/cktsopt.c b/src/spicelib/analysis/cktsopt.c index 2e95da846..226bd07f9 100644 --- a/src/spicelib/analysis/cktsopt.c +++ b/src/spicelib/analysis/cktsopt.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* @@ -33,6 +34,9 @@ CKTsetOpt(void *ckt, void *anal, int opt, IFvalue *val) case OPT_GMIN: task->TSKgmin = val->rValue; break; + case OPT_GSHUNT: + task->TSKgshunt = val->rValue; + break; case OPT_RELTOL: task->TSKreltol = val->rValue; break; @@ -79,6 +83,12 @@ CKTsetOpt(void *ckt, void *anal, int opt, IFvalue *val) case OPT_GMINSTEPS: task->TSKnumGminSteps = val->iValue; break; + case OPT_GMINFACT: + task->TSKgminFactor = val->rValue; + break; + case OPT_DEFM: + task->TSKdefaultMosM = val->rValue; + break; case OPT_DEFL: task->TSKdefaultMosL = val->rValue; break; @@ -119,6 +129,18 @@ CKTsetOpt(void *ckt, void *anal, int opt, IFvalue *val) case OPT_KEEPOPINFO: task->TSKkeepOpInfo = val->iValue; break; + case OPT_COPYNODESETS: + task->TSKcopyNodesets = val->iValue; + break; + case OPT_NODEDAMPING: + task->TSKnodeDamping = val->iValue; + break; + case OPT_ABSDV: + task->TSKabsDv = val->rValue; + break; + case OPT_RELDV: + task->TSKrelDv = val->rValue; + break; default: return(-1); } @@ -127,6 +149,7 @@ CKTsetOpt(void *ckt, void *anal, int opt, IFvalue *val) static IFparm OPTtbl[] = { { "noopiter", OPT_NOOPITER,IF_SET|IF_FLAG,"Go directly to gmin stepping" }, { "gmin", OPT_GMIN,IF_SET|IF_REAL,"Minimum conductance" }, + { "gshunt", OPT_GSHUNT,IF_SET|IF_REAL,"Shunt conductance" }, { "reltol", OPT_RELTOL,IF_SET|IF_REAL ,"Relative error tolerence"}, { "abstol", OPT_ABSTOL,IF_SET|IF_REAL,"Absolute error tolerence" }, { "vntol", OPT_VNTOL,IF_SET|IF_REAL,"Voltage error tolerence" }, @@ -144,6 +167,7 @@ static IFparm OPTtbl[] = { { "itl6", OPT_SRCSTEPS, IF_SET|IF_INTEGER,"number of source steps"}, { "srcsteps", OPT_SRCSTEPS, IF_SET|IF_INTEGER,"number of source steps"}, { "gminsteps", OPT_GMINSTEPS, IF_SET|IF_INTEGER,"number of Gmin steps"}, + { "gminfactor", OPT_GMINFACT, IF_SET|IF_REAL,"factor per Gmin step"}, { "acct", 0, IF_FLAG ,"Print accounting"}, { "list", 0, IF_FLAG, "Print a listing" }, { "nomod", 0, IF_FLAG, "Don't print a model summary" }, @@ -159,6 +183,7 @@ static IFparm OPTtbl[] = { { "lvltim", 0, IF_INTEGER,"Type of timestep control" }, { "method", OPT_METHOD, IF_SET|IF_STRING,"Integration method" }, { "maxord", OPT_MAXORD, IF_SET|IF_INTEGER,"Maximum integration order" }, + { "defm", OPT_DEFM,IF_SET|IF_REAL,"Default MOSfet Multiplier" }, { "defl", OPT_DEFL,IF_SET|IF_REAL,"Default MOSfet length" }, { "defw", OPT_DEFW,IF_SET|IF_REAL,"Default MOSfet width" }, { "minbreak", OPT_MINBREAK,IF_SET|IF_REAL,"Minimum time between breakpoints" }, @@ -201,7 +226,15 @@ static IFparm OPTtbl[] = { { "badmos3", OPT_BADMOS3, IF_SET|IF_FLAG, "use old mos3 model (discontinuous with respect to kappa)" }, { "keepopinfo", OPT_KEEPOPINFO, IF_SET|IF_FLAG, - "Record operating point for each small-signal analysis" } + "Record operating point for each small-signal analysis" }, + { "copynodesets", OPT_COPYNODESETS, IF_SET|IF_FLAG, + "Copy nodesets from device terminals to internal nodes" }, + { "nodedamping", OPT_NODEDAMPING, IF_SET|IF_FLAG, + "Limit iter-iter change in node voltages" }, + { "absdv", OPT_ABSDV, IF_SET|IF_REAL, + "Maximum absolute iter-iter node voltage change" }, + { "reldv", OPT_RELDV, IF_SET|IF_REAL, + "Maximum relative iter-iter node voltage change" } }; int OPTcount = sizeof(OPTtbl)/sizeof(IFparm); diff --git a/src/spicelib/analysis/ckttyplk.c b/src/spicelib/analysis/ckttyplk.c index acd136426..2c7655dfc 100644 --- a/src/spicelib/analysis/ckttyplk.c +++ b/src/spicelib/analysis/ckttyplk.c @@ -4,7 +4,7 @@ Author: 1985 Thomas L. Quarles **********/ /* look up the 'type' in the device description struct and return the - * appropriatestrchr for the device found, or -1 for not found + * appropriate strchr for the device found, or -1 for not found */ #include "ngspice.h" diff --git a/src/spicelib/analysis/dcop.c b/src/spicelib/analysis/dcop.c index 183b682c0..4f2a173df 100644 --- a/src/spicelib/analysis/dcop.c +++ b/src/spicelib/analysis/dcop.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -31,7 +32,42 @@ DCop(CKTcircuit *ckt) (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); - if(converged != 0) return(converged); + if(converged != 0) { + + CKTnode *node; + double new, old, tol; + int i=1; + + fprintf(stdout,"\nDC solution failed -\n\n"); + fprintf(stdout,"Last Node Voltages\n"); + fprintf(stdout,"------------------\n\n"); + fprintf(stdout,"%-30s %20s %20s\n", "Node", "Last Voltage", + "Previous Iter"); + fprintf(stdout,"%-30s %20s %20s\n", "----", "------------", + "-------------"); + for(node=ckt->CKTnodes->next;node;node=node->next) { + if (strstr(node->name, "#branch") || !strstr(node->name, "#")) { + new = *((ckt->CKTrhsOld) + i ) ; + old = *((ckt->CKTrhs) + i ) ; + fprintf(stdout,"%-30s %20g %20g", node->name, new, old); + if(node->type == 3) { + tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + + ckt->CKTvoltTol; + } else { + tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + + ckt->CKTabstol; + } + if (fabs(new-old) >tol ) { + fprintf(stdout," *"); + } + fprintf(stdout,"\n"); + }; + i++; + }; + fprintf(stdout,"\n"); + (*(SPfrontEnd->OUTendPlot))(plot); + return(converged); + }; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; @@ -57,7 +93,11 @@ DCop(CKTcircuit *ckt) } #endif converged = CKTload(ckt); - CKTdump(ckt,(double)0,plot); + if(converged == 0) { + CKTdump(ckt,(double)0,plot); + } else { + fprintf(stderr,"error: circuit reload failed.\n"); + }; (*(SPfrontEnd->OUTendPlot))(plot); return(converged); } diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index e4176cfcb..427c53ee6 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* subroutine to do DC TRANSIENT analysis @@ -44,12 +45,13 @@ DCtran(CKTcircuit *ckt, double maxstepsize=0.0; int ltra_num; + CKTnode *node; #ifdef PARALLEL_ARCH long type = MT_TRANAN, length = 1; #endif /* PARALLEL_ARCH */ if(restart || ckt->CKTtime == 0) { - delta=MIN(ckt->CKTfinalTime/50,ckt->CKTstep)/10; + delta=MIN(ckt->CKTfinalTime/100,ckt->CKTstep)/10; /* begin LTRA code addition */ if (ckt->CKTtimePoints != NULL) @@ -96,6 +98,52 @@ DCtran(CKTcircuit *ckt, (ckt->CKTmode & MODEUIC)|MODETRANOP| MODEINITJCT, (ckt->CKTmode & MODEUIC)|MODETRANOP| MODEINITFLOAT, ckt->CKTdcMaxIter); + + if(converged != 0) { + + CKTnode *node; + double new, old, tol; + int i=1; + + fprintf(stdout,"\nTransient solution failed -\n\n"); + fprintf(stdout,"Last Node Voltages\n"); + fprintf(stdout,"------------------\n\n"); + fprintf(stdout,"%-30s %20s %20s\n", "Node", "Last Voltage", + "Previous Iter"); + fprintf(stdout,"%-30s %20s %20s\n", "----", "------------", + "-------------"); + for(node=ckt->CKTnodes->next;node;node=node->next) { + if (strstr(node->name, "#branch") || !strstr(node->name, "#")) { + new = *((ckt->CKTrhsOld) + i ) ; + old = *((ckt->CKTrhs) + i ) ; + fprintf(stdout,"%-30s %20g %20g", node->name, new, old); + if(node->type == 3) { + tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + + ckt->CKTvoltTol; + } else { + tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + + ckt->CKTabstol; + } + if (fabs(new-old) >tol ) { + fprintf(stdout," *"); + } + fprintf(stdout,"\n"); + }; + i++; + } + } else { + fprintf(stdout,"\nInitial Transient Solution\n"); + fprintf(stdout,"--------------------------\n\n"); + fprintf(stdout,"%-30s %15s\n", "Node", "Voltage"); + fprintf(stdout,"%-30s %15s\n", "----", "-------"); + for(node=ckt->CKTnodes->next;node;node=node->next) { + if (strstr(node->name, "#branch") || !strstr(node->name, "#")) + fprintf(stdout,"%-30s %15g\n", node->name, + *(ckt->CKTrhsOld+node->number)); + }; + }; + fprintf(stdout,"\n"); + fflush(stdout); if(converged != 0) return(converged); ckt->CKTstat->STATtimePts ++; ckt->CKTorder=1; @@ -198,7 +246,8 @@ nextTime: */ #ifdef STEPDEBUG - printf("accepted at %g\n",ckt->CKTtime); + printf("Delta %g accepted at time %g\n",ckt->CKTdelta,ckt->CKTtime); + fflush(stdout); #endif /* STEPDEBUG */ ckt->CKTstat->STATaccepted ++; ckt->CKTbreak=0; @@ -317,7 +366,8 @@ resume: ckt->CKTsaveDelta = ckt->CKTdelta; ckt->CKTdelta = *(ckt->CKTbreaks) - ckt->CKTtime; #ifdef STEPDEBUG - (void)printf("delta cut to hit breakpoint\n"); + (void)printf("delta cut to %g to hit breakpoint\n",ckt->CKTdelta); + fflush(stdout); #endif ckt->CKTbreak = 1; /* why? the current pt. is not a bkpt. */ } @@ -363,7 +413,8 @@ resume: ckt->CKTstat->STATrejected ++; ckt->CKTdelta = ckt->CKTdelta/8; #ifdef STEPDEBUG - (void)printf("delta cut for non-convergence\n"); + (void)printf("delta cut to %g for non-convergance\n",ckt->CKTdelta); + fflush(stdout); #endif if(firsttime) { ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITTRAN; @@ -437,8 +488,10 @@ resume: /* time point OK - 630*/ ckt->CKTdelta = new; #ifdef STEPDEBUG - (void)printf( - "delta set to truncation error result:point accepted\n"); + (void)printf( + "delta set to truncation error result: %g. Point accepted\n", + ckt->CKTdelta); + fflush(stdout); #endif #ifdef WANT_SENSE2 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){ diff --git a/src/spicelib/analysis/traninit.c b/src/spicelib/analysis/traninit.c index 3b1c05f8e..eb497d62e 100644 --- a/src/spicelib/analysis/traninit.c +++ b/src/spicelib/analysis/traninit.c @@ -1,5 +1,6 @@ /********** Copyright 1991 Regents of the University of California. All rights reserved. +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -39,12 +40,12 @@ int TRANinit(CKTcircuit *ckt, JOB *job) #else /* The original spice code */ if(ckt->CKTmaxStep == 0) { - ckt->CKTmaxStep = (ckt->CKTfinalTime-ckt->CKTinitTime)/50; + ckt->CKTmaxStep = (ckt->CKTfinalTime-ckt->CKTinitTime)/100; } #endif - ckt->CKTdelmin = 1e-9*ckt->CKTmaxStep; /* XXX */ + ckt->CKTdelmin = 1e-11*ckt->CKTmaxStep; /* XXX */ ckt->CKTmode = ((TRANan*)job)->TRANmode; return OK; diff --git a/src/spicelib/devices/bjt/bjtdisto.c b/src/spicelib/devices/bjt/bjtdisto.c index 7266ba00c..a5bfc39bd 100644 --- a/src/spicelib/devices/bjt/bjtdisto.c +++ b/src/spicelib/devices/bjt/bjtdisto.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -45,7 +46,7 @@ BJTdisto(int mode, GENmodel *genmodel, CKTcircuit *ckt) #endif if (mode == D_SETUP) - return(BJTdSetup(model,ckt)); + return(BJTdSetup((GENmodel *)model,ckt)); if ((mode == D_TWOF1) || (mode == D_THRF1) || (mode == D_F1PF2) || (mode == D_F1MF2) || diff --git a/src/spicelib/devices/bjt/bjtext.h b/src/spicelib/devices/bjt/bjtext.h index 8e48adc2e..18b675bf5 100644 --- a/src/spicelib/devices/bjt/bjtext.h +++ b/src/spicelib/devices/bjt/bjtext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AnalsFixes **********/ #ifdef __STDC__ @@ -27,6 +28,9 @@ extern int BJTtemp(GENmodel*,CKTcircuit*); extern int BJTtrunc(GENmodel*,CKTcircuit*,double*); extern int BJTdisto(int,GENmodel*,CKTcircuit*); extern int BJTnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); + +extern int BJTdSetup(GENmodel*, register CKTcircuit*); + #else /* stdc */ extern int BJTacLoad(); extern int BJTask(); diff --git a/src/spicelib/devices/bjt/bjtload.c b/src/spicelib/devices/bjt/bjtload.c index e66d1e9de..8868fa7b4 100644 --- a/src/spicelib/devices/bjt/bjtload.c +++ b/src/spicelib/devices/bjt/bjtload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* @@ -369,43 +370,65 @@ BJTload(inModel,ckt) * determine dc current and derivitives */ next1: vtn=vt*model->BJTemissionCoeffF; - if(vbe > -5*vtn){ + + if(vbe >= -3*vtn){ evbe=exp(vbe/vtn); - cbe=csat*(evbe-1)+ckt->CKTgmin*vbe; - gbe=csat*evbe/vtn+ckt->CKTgmin; - if (c2 == 0) { - cben=0; - gben=0; - } else { + cbe=csat*(evbe-1); + gbe=csat*evbe/vtn; + } else { + arg=3*vtn/(vbe*CONSTe); + arg = arg * arg * arg; + cbe = -csat*(1+arg); + gbe = csat*3*arg/vbe; + } + if (c2 == 0) { + cben=0; + gben=0; + } else { + if(vbe >= -3*vte){ evben=exp(vbe/vte); cben=c2*(evben-1); gben=c2*evben/vte; - } - } else { - gbe = -csat/vbe+ckt->CKTgmin; - cbe=gbe*vbe; - gben = -c2/vbe; - cben=gben*vbe; - } - vtn=vt*model->BJTemissionCoeffR; - if(vbc > -5*vtn) { - evbc=exp(vbc/vtn); - cbc=csat*(evbc-1)+ckt->CKTgmin*vbc; - gbc=csat*evbc/vtn+ckt->CKTgmin; - if (c4 == 0) { - cbcn=0; - gbcn=0; } else { + arg=3*vte/(vbe*CONSTe); + arg = arg * arg * arg; + cben = -c2*(1+arg); + gben = c2*3*arg/vbe; + } + } + gben+=ckt->CKTgmin; + cben+=ckt->CKTgmin*vbe; + + vtn=vt*model->BJTemissionCoeffR; + + if(vbc >= -3*vtn) { + evbc=exp(vbc/vtn); + cbc=csat*(evbc-1); + gbc=csat*evbc/vtn; + } else { + arg=3*vtn/(vbc*CONSTe); + arg = arg * arg * arg; + cbc = -csat*(1+arg); + gbc = csat*3*arg/vbc; + } + if (c4 == 0) { + cbcn=0; + gbcn=0; + } else { + if(vbc >= -3*vtc) { evbcn=exp(vbc/vtc); cbcn=c4*(evbcn-1); gbcn=c4*evbcn/vtc; + } else { + arg=3*vtc/(vbc*CONSTe); + arg = arg * arg * arg; + cbcn = -c4*(1+arg); + gbcn = c4*3*arg/vbc; } - } else { - gbc = -csat/vbc+ckt->CKTgmin; - cbc = gbc*vbc; - gbcn = -c4/vbc; - cbcn=gbcn*vbc; } + gbcn+=ckt->CKTgmin; + cbcn+=ckt->CKTgmin*vbc; + /* * determine base charge terms */ diff --git a/src/spicelib/devices/bjt/bjtsetup.c b/src/spicelib/devices/bjt/bjtsetup.c index 7ed68cee1..3fb4bb39e 100644 --- a/src/spicelib/devices/bjt/bjtsetup.c +++ b/src/spicelib/devices/bjt/bjtsetup.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* @@ -149,6 +150,9 @@ BJTsetup(matrix,inModel,ckt,states) for (here = model->BJTinstances; here != NULL ; here=here->BJTnextInstance) { if (here->BJTowner != ARCHme) goto matrixpointers; + + CKTnode *tmpNode; + IFuid tmpName; if(!here->BJTareaGiven) { here->BJTarea = 1; @@ -166,6 +170,18 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->BJTname,"collector"); if(error) return(error); here->BJTcolPrimeNode = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; +/* fprintf(stderr, "Nodeset copied from %s\n", tmpName); + fprintf(stderr, " to %s\n", tmp->name); + fprintf(stderr, " value %g\n", + tmp->nodeset);*/ + } + } + } } if(model->BJTbaseResist == 0) { here->BJTbasePrimeNode = here->BJTbaseNode; @@ -173,6 +189,18 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->BJTname, "base"); if(error) return(error); here->BJTbasePrimeNode = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,2,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; +/* fprintf(stderr, "Nodeset copied from %s\n", tmpName); + fprintf(stderr, " to %s\n", tmp->name); + fprintf(stderr, " value %g\n", + tmp->nodeset);*/ + } + } + } } if(model->BJTemitterResist == 0) { here->BJTemitPrimeNode = here->BJTemitNode; @@ -180,6 +208,19 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->BJTname, "emitter"); if(error) return(error); here->BJTemitPrimeNode = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; +/* fprintf(stderr, "Nodeset copied from %s\n", tmpName); + fprintf(stderr, " to %s\n", tmp->name); + fprintf(stderr, " value %g\n", + tmp->nodeset);*/ + } + } + } + } /* macro to make elements with built in test for out of memory */ diff --git a/src/spicelib/devices/bjt/bjttemp.c b/src/spicelib/devices/bjt/bjttemp.c index 2c117efd1..1cb254df6 100644 --- a/src/spicelib/devices/bjt/bjttemp.c +++ b/src/spicelib/devices/bjt/bjttemp.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -185,7 +186,8 @@ BJTtemp(inModel,ckt) here->BJTtf5 = here->BJTtBCpot * (1 - exp((1 - model->BJTjunctionExpBC) * xfc)) / (1 - model->BJTjunctionExpBC); - here->BJTtVcrit = vt * log(vt / (CONSTroot2*model->BJTsatCur)); + here->BJTtVcrit = vt * + log(vt / (CONSTroot2*here->BJTtSatCur*here->BJTarea)); } } diff --git a/src/spicelib/devices/bsim1/b1disto.c b/src/spicelib/devices/bsim1/b1disto.c index 0deaa93be..6855800d7 100644 --- a/src/spicelib/devices/bsim1/b1disto.c +++ b/src/spicelib/devices/bsim1/b1disto.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified: AlansFixes **********/ #include "ngspice.h" @@ -43,7 +44,7 @@ B1disto(mode,genmodel,ckt) B1instance *here; if (mode == D_SETUP) - return(B1dSetup(model,ckt)); + return(B1dSetup((GENmodel *)model,ckt)); if ((mode == D_TWOF1) || (mode == D_THRF1) || (mode == D_F1PF2) || (mode == D_F1MF2) || diff --git a/src/spicelib/devices/bsim1/b1set.c b/src/spicelib/devices/bsim1/b1set.c index b3574ef3c..2a697fbd8 100644 --- a/src/spicelib/devices/bsim1/b1set.c +++ b/src/spicelib/devices/bsim1/b1set.c @@ -271,6 +271,9 @@ B1setup(matrix,inModel,ckt,states) for (here = model->B1instances; here != NULL ; here=here->B1nextInstance) { + CKTnode *tmpNode; + IFuid tmpName; + if (here->B1owner == ARCHme) { /* allocate a chunk of the state vector */ here->B1states = *states; @@ -325,6 +328,14 @@ B1setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->B1name,"drain"); if(error) return(error); here->B1dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->B1dNodePrime = here->B1dNode; } @@ -337,6 +348,14 @@ B1setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->B1name,"source"); if(error) return(error); here->B1sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } } else { here->B1sNodePrime = here->B1sNode; diff --git a/src/spicelib/devices/bsim1/bsim1ext.h b/src/spicelib/devices/bsim1/bsim1ext.h index 97a13b41c..96f6b43b7 100644 --- a/src/spicelib/devices/bsim1/bsim1ext.h +++ b/src/spicelib/devices/bsim1/bsim1ext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Hong June Park, Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -26,6 +27,7 @@ extern int B1unsetup(GENmodel*,CKTcircuit*); extern int B1temp(GENmodel*,CKTcircuit*); extern int B1trunc(GENmodel*,CKTcircuit*,double*); extern int B1disto(int,GENmodel*,CKTcircuit*); +extern int B1dSetup(GENmodel*, register CKTcircuit*); #else /* stdc */ extern int B1acLoad(); extern int B1ask(); diff --git a/src/spicelib/devices/bsim2/b2set.c b/src/spicelib/devices/bsim2/b2set.c index 2ed32673b..002f6ad99 100644 --- a/src/spicelib/devices/bsim2/b2set.c +++ b/src/spicelib/devices/bsim2/b2set.c @@ -494,6 +494,14 @@ B2setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->B2name,"drain"); 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; + } + } + } } else { here->B2dNodePrime = here->B2dNode; } @@ -506,6 +514,14 @@ B2setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->B2name,"source"); 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; + } + } + } } } else { here->B2sNodePrime = here->B2sNode; diff --git a/src/spicelib/devices/bsim3/b3.c b/src/spicelib/devices/bsim3/b3.c index 3e698488c..4d78e07e6 100644 --- a/src/spicelib/devices/bsim3/b3.c +++ b/src/spicelib/devices/bsim3/b3.c @@ -2,6 +2,7 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. +Modified: 2000 AlansFixes File: b3.c **********/ @@ -14,6 +15,7 @@ File: b3.c IFparm BSIM3pTable[] = { /* parameters */ IOP( "l", BSIM3_L, IF_REAL , "Length"), IOP( "w", BSIM3_W, IF_REAL , "Width"), +IOP( "m", BSIM3_M, IF_REAL , "Parallel multiplier"), IOP( "ad", BSIM3_AD, IF_REAL , "Drain area"), IOP( "as", BSIM3_AS, IF_REAL , "Source area"), IOP( "pd", BSIM3_PD, IF_REAL , "Drain perimeter"), diff --git a/src/spicelib/devices/bsim3/b3acld.c b/src/spicelib/devices/bsim3/b3acld.c index ac9591cee..e064f6397 100644 --- a/src/spicelib/devices/bsim3/b3acld.c +++ b/src/spicelib/devices/bsim3/b3acld.c @@ -2,6 +2,7 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. +Modified: 2000 AlansFixes File: b3acld.c **********/ @@ -259,76 +260,79 @@ double ScalingFactor = 1.0e-9; xcbdb = (cbdb - capbd ) * omega; xcbsb = (cbsb - capbs ) * omega; - *(here->BSIM3GgPtr +1) += xcggb; + + m = here->BSIM3m; + + *(here->BSIM3GgPtr +1) += m * xcggb; *(here->BSIM3BbPtr +1) -= xcbgb + xcbdb + xcbsb; - *(here->BSIM3DPdpPtr +1) += xcddb; - *(here->BSIM3SPspPtr +1) += xcssb; + *(here->BSIM3DPdpPtr +1) += m * xcddb; + *(here->BSIM3SPspPtr +1) += m * xcssb; *(here->BSIM3GbPtr +1) -= xcggb + xcgdb + xcgsb; - *(here->BSIM3GdpPtr +1) += xcgdb; - *(here->BSIM3GspPtr +1) += xcgsb; - *(here->BSIM3BgPtr +1) += xcbgb; - *(here->BSIM3BdpPtr +1) += xcbdb; - *(here->BSIM3BspPtr +1) += xcbsb; - *(here->BSIM3DPgPtr +1) += xcdgb; + *(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) += xcdsb; - *(here->BSIM3SPgPtr +1) += xcsgb; + *(here->BSIM3DPspPtr +1) += m * xcdsb; + *(here->BSIM3SPgPtr +1) += m * xcsgb; *(here->BSIM3SPbPtr +1) -= xcsgb + xcsdb + xcssb; - *(here->BSIM3SPdpPtr +1) += xcsdb; + *(here->BSIM3SPdpPtr +1) += m * xcsdb; - *(here->BSIM3DdPtr) += gdpr; - *(here->BSIM3SsPtr) += gspr; - *(here->BSIM3BbPtr) += gbd + gbs - here->BSIM3gbbs; - *(here->BSIM3DPdpPtr) += gdpr + gds + gbd + RevSum - + dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp; - *(here->BSIM3SPspPtr) += 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) -= gdpr; - *(here->BSIM3SspPtr) -= gspr; + *(here->BSIM3DdpPtr) -= m * gdpr; + *(here->BSIM3SspPtr) -= m * gspr; - *(here->BSIM3BgPtr) -= here->BSIM3gbgs; - *(here->BSIM3BdpPtr) -= gbd - gbbdp; - *(here->BSIM3BspPtr) -= gbs - gbbsp; + *(here->BSIM3BgPtr) -= m * here->BSIM3gbgs; + *(here->BSIM3BdpPtr) -= m * (gbd - gbbdp); + *(here->BSIM3BspPtr) -= m * (gbs - gbbsp); - *(here->BSIM3DPdPtr) -= gdpr; - *(here->BSIM3DPgPtr) += Gm + dxpart * xgtg + T1 * ddxpart_dVg - + gbdpg; - *(here->BSIM3DPbPtr) -= gbd - Gmbs - dxpart * xgtb - - T1 * ddxpart_dVb - gbdpb; - *(here->BSIM3DPspPtr) -= 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) -= Gm - sxpart * xgtg - T1 * dsxpart_dVg - - gbspg; - *(here->BSIM3SPsPtr) -= gspr; - *(here->BSIM3SPbPtr) -= gbs + Gmbs - sxpart * xgtb - - T1 * dsxpart_dVb - gbspb; - *(here->BSIM3SPdpPtr) -= 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) -= xgtg; - *(here->BSIM3GbPtr) -= xgtb; - *(here->BSIM3GdpPtr) -= xgtd; - *(here->BSIM3GspPtr) -= xgts; + *(here->BSIM3GgPtr) -= m * xgtg; + *(here->BSIM3GbPtr) -= m * xgtb; + *(here->BSIM3GdpPtr) -= m * xgtd; + *(here->BSIM3GspPtr) -= m * xgts; if (here->BSIM3nqsMod) - { *(here->BSIM3QqPtr +1) += omega * ScalingFactor; - *(here->BSIM3QgPtr +1) -= xcqgb; - *(here->BSIM3QdpPtr +1) -= xcqdb; - *(here->BSIM3QspPtr +1) -= xcqsb; - *(here->BSIM3QbPtr +1) -= xcqbb; + { *(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) += here->BSIM3gtau; + *(here->BSIM3QqPtr) += m * here->BSIM3gtau; - *(here->BSIM3DPqPtr) += dxpart * here->BSIM3gtau; - *(here->BSIM3SPqPtr) += sxpart * here->BSIM3gtau; - *(here->BSIM3GqPtr) -= here->BSIM3gtau; + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; - *(here->BSIM3QgPtr) += xgtg; - *(here->BSIM3QdpPtr) += xgtd; - *(here->BSIM3QspPtr) += xgts; - *(here->BSIM3QbPtr) += xgtb; + *(here->BSIM3QgPtr) += m * xgtg; + *(here->BSIM3QdpPtr) += m * xgtd; + *(here->BSIM3QspPtr) += m * xgts; + *(here->BSIM3QbPtr) += m * xgtb; } } } diff --git a/src/spicelib/devices/bsim3/b3ask.c b/src/spicelib/devices/bsim3/b3ask.c index 23b2785a0..16c903c67 100644 --- a/src/spicelib/devices/bsim3/b3ask.c +++ b/src/spicelib/devices/bsim3/b3ask.c @@ -32,6 +32,9 @@ BSIM3instance *here = (BSIM3instance*)inst; case BSIM3_W: value->rValue = here->BSIM3w; return(OK); + case BSIM3_M: + value->rValue = here->BSIM3m; + return(OK); case BSIM3_AS: value->rValue = here->BSIM3sourceArea; return(OK); @@ -85,9 +88,11 @@ BSIM3instance *here = (BSIM3instance*)inst; return(OK); case BSIM3_SOURCECONDUCT: value->rValue = here->BSIM3sourceConductance; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_DRAINCONDUCT: value->rValue = here->BSIM3drainConductance; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_VBD: value->rValue = *(ckt->CKTstate0 + here->BSIM3vbd); @@ -103,78 +108,103 @@ BSIM3instance *here = (BSIM3instance*)inst; return(OK); case BSIM3_CD: value->rValue = here->BSIM3cd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBS: - value->rValue = here->BSIM3cbs; + value->rValue = here->BSIM3cbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBD: - value->rValue = here->BSIM3cbd; + value->rValue = here->BSIM3cbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GM: - value->rValue = here->BSIM3gm; + value->rValue = here->BSIM3gm; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GDS: - value->rValue = here->BSIM3gds; + value->rValue = here->BSIM3gds; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GMBS: value->rValue = here->BSIM3gmbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GBD: - value->rValue = here->BSIM3gbd; + value->rValue = here->BSIM3gbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GBS: - value->rValue = here->BSIM3gbs; + value->rValue = here->BSIM3gbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QB: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qb); + value->rValue = *(ckt->CKTstate0 + here->BSIM3qb); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CQB: value->rValue = *(ckt->CKTstate0 + here->BSIM3cqb); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qg); + value->rValue = *(ckt->CKTstate0 + here->BSIM3qg); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CQG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3cqg); + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqg); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qd); + value->rValue = *(ckt->CKTstate0 + here->BSIM3qd); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CQD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3cqd); + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqd); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGG: - value->rValue = here->BSIM3cggb; + value->rValue = here->BSIM3cggb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGD: value->rValue = here->BSIM3cgdb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGS: value->rValue = here->BSIM3cgsb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDG: - value->rValue = here->BSIM3cdgb; + value->rValue = here->BSIM3cdgb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDD: - value->rValue = here->BSIM3cddb; + value->rValue = here->BSIM3cddb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDS: - value->rValue = here->BSIM3cdsb; + value->rValue = here->BSIM3cdsb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBG: value->rValue = here->BSIM3cbgb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBDB: value->rValue = here->BSIM3cbdb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBSB: value->rValue = here->BSIM3cbsb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CAPBD: - value->rValue = here->BSIM3capbd; + value->rValue = here->BSIM3capbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CAPBS: value->rValue = here->BSIM3capbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_VON: value->rValue = here->BSIM3von; @@ -183,10 +213,12 @@ BSIM3instance *here = (BSIM3instance*)inst; value->rValue = here->BSIM3vdsat; return(OK); case BSIM3_QBS: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qbs); + value->rValue = *(ckt->CKTstate0 + here->BSIM3qbs); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QBD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qbd); + value->rValue = *(ckt->CKTstate0 + here->BSIM3qbd); + value->rValue *= here->BSIM3m; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/bsim3/b3ld.c b/src/spicelib/devices/bsim3/b3ld.c index 1ea076330..64b1c6198 100644 --- a/src/spicelib/devices/bsim3/b3ld.c +++ b/src/spicelib/devices/bsim3/b3ld.c @@ -3,6 +3,7 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1991 JianHui Huang and Min-Chie Jeng. Modified by Mansun Chan (1995). Author: 1997-1999 Weidong Liu. +Modified: 2000 AlansFixes File: b3ld.c **********/ @@ -118,6 +119,8 @@ double Cgg, Cgd, Cgb, Cdg, Cdd, Cds; double Csg, Csd, Css, Csb, Cbg, Cbd, Cbb; double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0; double dQac0_dVg, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; + +double m; struct bsim3SizeDependParam *pParam; int ByPass, Check, ChargeComputationNeeded, error; @@ -318,6 +321,8 @@ for (; model != NULL; model = model->BSIM3nextModel) vbd = vbs - vds; vgd = vgs - vds; vgb = vgs - vbs; + + m=here->BSIM3m; /* Source/drain junction diode DC model begins */ Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; @@ -331,29 +336,29 @@ for (; model != NULL; model = model->BSIM3nextModel) * model->BSIM3jctSidewallTempSatCurDensity; } if (SourceSatCurrent <= 0.0) - { here->BSIM3gbs = ckt->CKTgmin; + { here->BSIM3gbs = ckt->CKTgmin/m; here->BSIM3cbs = here->BSIM3gbs * vbs; } else { if (model->BSIM3ijth == 0.0) { evbs = exp(vbs / Nvtm); - here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + (ckt->CKTgmin/m); here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) - + ckt->CKTgmin * vbs; + + (ckt->CKTgmin/m) * vbs; } else { if (vbs < here->BSIM3vjsm) { evbs = exp(vbs / Nvtm); - here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + (ckt->CKTgmin/m); here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) - + ckt->CKTgmin * vbs; + + (ckt->CKTgmin/m) * vbs; } else { T0 = here->BSIM3IsEvjsm / Nvtm; - here->BSIM3gbs = T0 + ckt->CKTgmin; + here->BSIM3gbs = T0 + (ckt->CKTgmin/m); here->BSIM3cbs = here->BSIM3IsEvjsm - SourceSatCurrent + T0 * (vbs - here->BSIM3vjsm) - + ckt->CKTgmin * vbs; + + (ckt->CKTgmin/m) * vbs; } } } @@ -368,29 +373,29 @@ for (; model != NULL; model = model->BSIM3nextModel) * model->BSIM3jctSidewallTempSatCurDensity; } if (DrainSatCurrent <= 0.0) - { here->BSIM3gbd = ckt->CKTgmin; + { here->BSIM3gbd = (ckt->CKTgmin/m); here->BSIM3cbd = here->BSIM3gbd * vbd; } else { if (model->BSIM3ijth == 0.0) { evbd = exp(vbd / Nvtm); - here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + (ckt->CKTgmin/m); here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) - + ckt->CKTgmin * vbd; + + (ckt->CKTgmin/m) * vbd; } else { if (vbd < here->BSIM3vjdm) { evbd = exp(vbd / Nvtm); - here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + (ckt->CKTgmin/m); here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) - + ckt->CKTgmin * vbd; + + (ckt->CKTgmin/m) * vbd; } else { T0 = here->BSIM3IsEvjdm / Nvtm; - here->BSIM3gbd = T0 + ckt->CKTgmin; + here->BSIM3gbd = T0 + (ckt->CKTgmin/m); here->BSIM3cbd = here->BSIM3IsEvjdm - DrainSatCurrent + T0 * (vbd - here->BSIM3vjdm) - + ckt->CKTgmin * vbd; + + (ckt->CKTgmin/m) * vbd; } } } @@ -2833,71 +2838,71 @@ line900: cqdef = -cqdef; cqcheq = -cqcheq; } - - (*(ckt->CKTrhs + here->BSIM3gNode) -= ceqqg); - (*(ckt->CKTrhs + here->BSIM3bNode) -=(ceqbs + ceqbd + ceqqb)); - (*(ckt->CKTrhs + here->BSIM3dNodePrime) += (ceqbd - cdreq - ceqqd)); - (*(ckt->CKTrhs + here->BSIM3sNodePrime) += (cdreq + ceqbs + ceqqg + + (*(ckt->CKTrhs + here->BSIM3gNode) -= m*ceqqg); + (*(ckt->CKTrhs + here->BSIM3bNode) -= m*(ceqbs + ceqbd + ceqqb)); + (*(ckt->CKTrhs + here->BSIM3dNodePrime) +=m*(ceqbd - cdreq - ceqqd)); + (*(ckt->CKTrhs + here->BSIM3sNodePrime) += m*(cdreq + ceqbs + ceqqg + ceqqb + ceqqd)); if (here->BSIM3nqsMod) - *(ckt->CKTrhs + here->BSIM3qNode) += (cqcheq - cqdef); + *(ckt->CKTrhs + here->BSIM3qNode) += m*(cqcheq - cqdef); /* * load y matrix */ T1 = qdef * here->BSIM3gtau; - (*(here->BSIM3DdPtr) += here->BSIM3drainConductance); - (*(here->BSIM3GgPtr) += gcggb - ggtg); - (*(here->BSIM3SsPtr) += here->BSIM3sourceConductance); - (*(here->BSIM3BbPtr) += here->BSIM3gbd + here->BSIM3gbs - - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs); - (*(here->BSIM3DPdpPtr) += here->BSIM3drainConductance + (*(here->BSIM3DdPtr) += m*here->BSIM3drainConductance); + (*(here->BSIM3GgPtr) += m*(gcggb - ggtg)); + (*(here->BSIM3SsPtr) += m*here->BSIM3sourceConductance); + (*(here->BSIM3BbPtr) += m*(here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs)); + (*(here->BSIM3DPdpPtr) += m*(here->BSIM3drainConductance + here->BSIM3gds + here->BSIM3gbd + RevSum + gcddb + dxpart * ggtd - + T1 * ddxpart_dVd + gbdpdp); - (*(here->BSIM3SPspPtr) += here->BSIM3sourceConductance + + T1 * ddxpart_dVd + gbdpdp)); + (*(here->BSIM3SPspPtr) += m*(here->BSIM3sourceConductance + here->BSIM3gds + here->BSIM3gbs + FwdSum + gcssb + sxpart * ggts - + T1 * dsxpart_dVs + gbspsp); - (*(here->BSIM3DdpPtr) -= here->BSIM3drainConductance); - (*(here->BSIM3GbPtr) -= gcggb + gcgdb + gcgsb + ggtb); - (*(here->BSIM3GdpPtr) += gcgdb - ggtd); - (*(here->BSIM3GspPtr) += gcgsb - ggts); - (*(here->BSIM3SspPtr) -= here->BSIM3sourceConductance); - (*(here->BSIM3BgPtr) += gcbgb - here->BSIM3gbgs); - (*(here->BSIM3BdpPtr) += gcbdb - here->BSIM3gbd + gbbdp); - (*(here->BSIM3BspPtr) += gcbsb - here->BSIM3gbs + gbbsp); - (*(here->BSIM3DPdPtr) -= here->BSIM3drainConductance); - (*(here->BSIM3DPgPtr) += Gm + gcdgb + dxpart * ggtg - + T1 * ddxpart_dVg + gbdpg); - (*(here->BSIM3DPbPtr) -= here->BSIM3gbd - Gmbs + gcdgb + gcddb + + T1 * dsxpart_dVs + gbspsp)); + (*(here->BSIM3DdpPtr) -= m*here->BSIM3drainConductance); + (*(here->BSIM3GbPtr) -= m*(gcggb + gcgdb + gcgsb + ggtb)); + (*(here->BSIM3GdpPtr) += m*(gcgdb - ggtd)); + (*(here->BSIM3GspPtr) += m*(gcgsb - ggts)); + (*(here->BSIM3SspPtr) -= m*here->BSIM3sourceConductance); + (*(here->BSIM3BgPtr) += m*(gcbgb - here->BSIM3gbgs)); + (*(here->BSIM3BdpPtr) += m*(gcbdb - here->BSIM3gbd + gbbdp)); + (*(here->BSIM3BspPtr) += m*(gcbsb - here->BSIM3gbs + gbbsp)); + (*(here->BSIM3DPdPtr) -= m*here->BSIM3drainConductance); + (*(here->BSIM3DPgPtr) += m*(Gm + gcdgb + dxpart * ggtg + + T1 * ddxpart_dVg + gbdpg)); + (*(here->BSIM3DPbPtr) -= m*(here->BSIM3gbd - Gmbs + gcdgb + gcddb + gcdsb - dxpart * ggtb - - T1 * ddxpart_dVb - gbdpb); - (*(here->BSIM3DPspPtr) -= here->BSIM3gds + FwdSum - gcdsb - - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp); - (*(here->BSIM3SPgPtr) += gcsgb - Gm + sxpart * ggtg - + T1 * dsxpart_dVg + gbspg); - (*(here->BSIM3SPsPtr) -= here->BSIM3sourceConductance); - (*(here->BSIM3SPbPtr) -= here->BSIM3gbs + Gmbs + gcsgb + gcsdb + - T1 * ddxpart_dVb - gbdpb)); + (*(here->BSIM3DPspPtr) -= m*(here->BSIM3gds + FwdSum - gcdsb + - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp)); + (*(here->BSIM3SPgPtr) += m*(gcsgb - Gm + sxpart * ggtg + + T1 * dsxpart_dVg + gbspg)); + (*(here->BSIM3SPsPtr) -= m*here->BSIM3sourceConductance); + (*(here->BSIM3SPbPtr) -= m*(here->BSIM3gbs + Gmbs + gcsgb + gcsdb + gcssb - sxpart * ggtb - - T1 * dsxpart_dVb - gbspb); - (*(here->BSIM3SPdpPtr) -= here->BSIM3gds + RevSum - gcsdb - - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp); + - T1 * dsxpart_dVb - gbspb)); + (*(here->BSIM3SPdpPtr) -= m*(here->BSIM3gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); if (here->BSIM3nqsMod) - { *(here->BSIM3QqPtr) += (gqdef + here->BSIM3gtau); + { *(here->BSIM3QqPtr) += m*(gqdef + here->BSIM3gtau); - *(here->BSIM3DPqPtr) += (dxpart * here->BSIM3gtau); - *(here->BSIM3SPqPtr) += (sxpart * here->BSIM3gtau); - *(here->BSIM3GqPtr) -= here->BSIM3gtau; + *(here->BSIM3DPqPtr) += m*(dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m*(sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m*here->BSIM3gtau; - *(here->BSIM3QgPtr) += (ggtg - gcqgb); - *(here->BSIM3QdpPtr) += (ggtd - gcqdb); - *(here->BSIM3QspPtr) += (ggts - gcqsb); - *(here->BSIM3QbPtr) += (ggtb - gcqbb); + *(here->BSIM3QgPtr) += m*(ggtg - gcqgb); + *(here->BSIM3QdpPtr) += m*(ggtd - gcqdb); + *(here->BSIM3QspPtr) += m*(ggts - gcqsb); + *(here->BSIM3QbPtr) += m*(ggtb - gcqbb); } - + line1000: ; } /* End of Mosfet Instance */ diff --git a/src/spicelib/devices/bsim3/b3par.c b/src/spicelib/devices/bsim3/b3par.c index a5c944362..7761ebfcb 100644 --- a/src/spicelib/devices/bsim3/b3par.c +++ b/src/spicelib/devices/bsim3/b3par.c @@ -2,6 +2,7 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. +Modified: 2000 AlansFixes File: b3par.c **********/ @@ -29,6 +30,10 @@ IFvalue *select; here->BSIM3l = value->rValue; here->BSIM3lGiven = TRUE; break; + case BSIM3_M: + here->BSIM3m = value->rValue; + here->BSIM3mGiven = TRUE; + break; case BSIM3_AS: here->BSIM3sourceArea = value->rValue; here->BSIM3sourceAreaGiven = TRUE; diff --git a/src/spicelib/devices/bsim3/b3set.c b/src/spicelib/devices/bsim3/b3set.c index c5ac11a50..4cab7307a 100644 --- a/src/spicelib/devices/bsim3/b3set.c +++ b/src/spicelib/devices/bsim3/b3set.c @@ -2,6 +2,8 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. + +Modified: 2000 AlansFixes File: b3set.c **********/ @@ -848,6 +850,10 @@ CKTnode *tmp; { if (here->BSIM3owner == ARCHme) { /* allocate a chunk of the state vector */ + + CKTnode *tmpNode; + IFuid tmpName; + here->BSIM3states = *states; *states += BSIM3numStates; } @@ -877,7 +883,10 @@ CKTnode *tmp; here->BSIM3w = 5.0e-6; if (!here->BSIM3nqsModGiven) here->BSIM3nqsMod = 0; - + + if (!here->BSIM3mGiven) + here->BSIM3m = 1; + /* process drain series resistance */ if ((model->BSIM3sheetResistance > 0.0) && (here->BSIM3drainSquares > 0.0 ) && @@ -885,6 +894,14 @@ CKTnode *tmp; { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain"); if(error) return(error); here->BSIM3dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->BSIM3dNodePrime = here->BSIM3dNode; @@ -897,6 +914,14 @@ CKTnode *tmp; { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"source"); if(error) return(error); here->BSIM3sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->BSIM3sNodePrime = here->BSIM3sNode; diff --git a/src/spicelib/devices/bsim3/bsim3def.h b/src/spicelib/devices/bsim3/bsim3def.h index 8270edb91..c9ff5120f 100644 --- a/src/spicelib/devices/bsim3/bsim3def.h +++ b/src/spicelib/devices/bsim3/bsim3def.h @@ -2,6 +2,7 @@ Copyright 1999 Regents of the University of California. All rights reserved. Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. +Modified: 2000 AlansFixes File: bsim3def.h **********/ @@ -106,6 +107,7 @@ typedef struct sBSIM3instance unsigned BSIM3lGiven :1; unsigned BSIM3wGiven :1; + unsigned BSIM3mGiven :1; unsigned BSIM3drainAreaGiven :1; unsigned BSIM3sourceAreaGiven :1; unsigned BSIM3drainSquaresGiven :1; @@ -152,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 @@ -1213,6 +1215,7 @@ typedef struct sBSIM3model /* device parameters */ #define BSIM3_W 1 #define BSIM3_L 2 +#define BSIM3_M 15 #define BSIM3_AS 3 #define BSIM3_AD 4 #define BSIM3_PS 5 diff --git a/src/spicelib/devices/cap/capask.c b/src/spicelib/devices/cap/capask.c index d1b7b81d7..74af35722 100644 --- a/src/spicelib/devices/cap/capask.c +++ b/src/spicelib/devices/cap/capask.c @@ -56,7 +56,7 @@ CAPask(ckt,inst, which, value, select) } else { value->rValue = *(ckt->CKTstate0 + here->CAPccap); } - } + } else value->rValue = *(ckt->CKTstate0 + here->CAPccap); return(OK); case CAP_POWER: if (ckt->CKTcurrentAnalysis & DOING_AC) { @@ -74,7 +74,9 @@ CAPask(ckt,inst, which, value, select) (*(ckt->CKTrhsOld + here->CAPposNode) - *(ckt->CKTrhsOld + here->CAPnegNode)); } - } + } else value->rValue = *(ckt->CKTstate0 + here->CAPccap) * + (*(ckt->CKTrhsOld + here->CAPposNode) - + *(ckt->CKTrhsOld + here->CAPnegNode)); return(OK); case CAP_QUEST_SENS_DC: if(ckt->CKTsenInfo){ diff --git a/src/spicelib/devices/cktinit.c b/src/spicelib/devices/cktinit.c index 088eaf8e7..3590fb2b2 100644 --- a/src/spicelib/devices/cktinit.c +++ b/src/spicelib/devices/cktinit.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modifed: 2000 AlansFixes **********/ #include @@ -30,12 +31,13 @@ CKTinit(void **ckt) /* new circuit to create */ sckt->CKTmatrix = NULL; sckt->CKTgmin = 1e-12; + sckt->CKTgshunt=0; sckt->CKTabstol = 1e-12; sckt->CKTreltol = 1e-3; sckt->CKTchgtol = 1e-14; sckt->CKTvoltTol = 1e-6; sckt->CKTtrtol = 7; - sckt->CKTbypass = 1; + sckt->CKTbypass = 0; sckt->CKTisSetup = 0; sckt->CKTtranMaxIter = 10; sckt->CKTdcMaxIter = 100; @@ -47,6 +49,7 @@ CKTinit(void **ckt) /* new circuit to create */ sckt->CKTpivotRelTol = 1e-3; sckt->CKTtemp = 300.15; sckt->CKTnomTemp = 300.15; + sckt->CKTdefaultMosM = 1; sckt->CKTdefaultMosL = 1e-4; sckt->CKTdefaultMosW = 1e-4; sckt->CKTdefaultMosAD = 0; @@ -59,6 +62,9 @@ CKTinit(void **ckt) /* new circuit to create */ sckt->CKTtimePoints = NULL; if (sckt->CKTstat == (STATistics *)NULL) return E_NOMEM; + sckt->CKTnodeDamping = 0; + sckt->CKTabsDv = 0.5; + sckt->CKTrelDv = 2.0; return OK; } diff --git a/src/spicelib/devices/csw/Makefile.am b/src/spicelib/devices/csw/Makefile.am index 4445d8e42..ba1cf6364 100644 --- a/src/spicelib/devices/csw/Makefile.am +++ b/src/spicelib/devices/csw/Makefile.am @@ -20,7 +20,8 @@ libcsw_la_SOURCES = \ cswnoise.c \ cswparam.c \ cswpzld.c \ - cswsetup.c + cswsetup.c \ + cswtrunc.c diff --git a/src/spicelib/devices/csw/cswdefs.h b/src/spicelib/devices/csw/cswdefs.h index 4d288160c..5f6b4f62d 100644 --- a/src/spicelib/devices/csw/cswdefs.h +++ b/src/spicelib/devices/csw/cswdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon M. Jacobs +Modified: 2000 AlansFixes **********/ #ifndef CSW @@ -54,7 +55,7 @@ typedef struct sCSWinstance { #define CSW_ON_CONDUCTANCE 1.0 /* default on conductance = 1 mho */ #define CSW_OFF_CONDUCTANCE ckt->CKTgmin /* default off conductance */ -#define CSW_NUM_STATES 1 +#define CSW_NUM_STATES 2 typedef struct sCSWmodel { /* model structure for a switch */ int CSWmodType; /* type index of this device type */ diff --git a/src/spicelib/devices/csw/cswext.h b/src/spicelib/devices/csw/cswext.h index 0f3f50dea..0eefa4570 100644 --- a/src/spicelib/devices/csw/cswext.h +++ b/src/spicelib/devices/csw/cswext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon M. Jacobs +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -16,6 +17,9 @@ extern int CSWparam(int,IFvalue*,GENinstance*,IFvalue*); extern int CSWpzLoad(GENmodel*,CKTcircuit*,SPcomplex*); extern int CSWsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int CSWnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); + +extern int CSWtrunc(GENmodel*,CKTcircuit*,double*); + #else /* stdc */ extern int CSWask(); extern int CSWacLoad(); @@ -29,5 +33,6 @@ extern int CSWparam(); extern int CSWpzLoad(); extern int CSWsetup(); extern int CSWnoise(); +extern int CSWtrunc(); #endif /* stdc */ diff --git a/src/spicelib/devices/csw/cswinit.c b/src/spicelib/devices/csw/cswinit.c index 595ab865b..ee8d05852 100644 --- a/src/spicelib/devices/csw/cswinit.c +++ b/src/spicelib/devices/csw/cswinit.c @@ -1,3 +1,5 @@ +/* Modified: 2000 AlansFixes */ + #include #include @@ -31,7 +33,7 @@ SPICEdev CSWinfo = { DEVunsetup : NULL, DEVpzSetup : CSWsetup, DEVtemperature: NULL, - DEVtrunc : NULL, + DEVtrunc :CSWtrunc, DEVfindBranch : NULL, DEVacLoad : CSWacLoad, DEVaccept : NULL, diff --git a/src/spicelib/devices/csw/cswload.c b/src/spicelib/devices/csw/cswload.c index 6a5f5eafc..44b23d46d 100644 --- a/src/spicelib/devices/csw/cswload.c +++ b/src/spicelib/devices/csw/cswload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon Jacobs +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -47,6 +48,9 @@ CSWload(inModel,ckt) *(ckt->CKTstate0 + here->CSWstate) = 0.0; current_state = 0.0; } + + *(ckt->CKTstate0 + (here->CSWstate+1)) = 0; + } else if (ckt->CKTmode & (MODEINITSMSIG)) { previous_state = *(ckt->CKTstate0 + here->CSWstate); @@ -70,6 +74,8 @@ CSWload(inModel,ckt) current_state = previous_state; } + *(ckt->CKTstate0 + (here->CSWstate+1)) = i_ctrl; + if(current_state != previous_state) { ckt->CKTnoncon++; /* ensure one more iteration */ ckt->CKTtroubleElt = (GENinstance *) here; @@ -96,6 +102,8 @@ CSWload(inModel,ckt) *(ckt->CKTstate0 + here->CSWstate) = 1.0; } + *(ckt->CKTstate0 + (here->CSWstate+1)) = i_ctrl; + } g_now = current_state?(model->CSWonConduct):(model->CSWoffConduct); diff --git a/src/spicelib/devices/devsup.c b/src/spicelib/devices/devsup.c index 294c02d0a..901623cff 100644 --- a/src/spicelib/devices/devsup.c +++ b/src/spicelib/devices/devsup.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* support routines for device models */ @@ -47,18 +48,32 @@ DEVpnjlim(double vnew, if((vnew > vcrit) && (fabs(vnew - vold) > (vt + vt))) { if(vold > 0) { - arg = 1 + (vnew - vold) / vt; + arg = (vnew - vold) / vt; if(arg > 0) { - vnew = vold + vt * log(arg); + vnew = vold + vt * (2+log(arg-2)); } else { - vnew = vcrit; + vnew = vold - vt * (2+log(2-arg)); } } else { vnew = vt *log(vnew/vt); } *icheck = 1; } else { - *icheck = 0; + if (vnew < 0) { + if (vold > 0) { + arg = -1*vold-1; + } else { + arg = 2*vold-1; + } + if (vnew < arg) { + vnew = arg; + *icheck = 1; + } else { + *icheck = 0; + }; + } else { + *icheck = 0; + } } return(vnew); } @@ -76,7 +91,7 @@ DEVfetlim(double vnew, double vtemp; vtsthi = fabs(2*(vold-vto))+2; - vtstlo = vtsthi/2 +2; + vtstlo = fabs(vold-vto)*1; vtox = vto + 3.5; delv = vnew-vold; diff --git a/src/spicelib/devices/dio/dioext.h b/src/spicelib/devices/dio/dioext.h index eb2f91926..86109c14e 100644 --- a/src/spicelib/devices/dio/dioext.h +++ b/src/spicelib/devices/dio/dioext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -29,6 +30,9 @@ extern int DIOtrunc(GENmodel*,CKTcircuit*,double*); extern int DIOdisto(int,GENmodel*,CKTcircuit*); extern int DIOnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int DIOdSetup(DIOmodel*,CKTcircuit*); + + #else /* stdc */ extern int DIOacLoad(); diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index 47c84fc30..deeb7d9c9 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -176,7 +177,7 @@ next1: if (vd >= -3*vte) { evd = exp(vd/vte); cd = csat*(evd-1)+ckt->CKTgmin*vd; gd = csat*evd/vte+ckt->CKTgmin; - } else if((!(here->DIOtBrkdwnV))|| + } else if((!(model->DIObreakdownVoltageGiven)) || vd >= -here->DIOtBrkdwnV) { arg=3*vte/(vd*CONSTe); arg = arg * arg * arg; @@ -194,10 +195,10 @@ next1: if (vd >= -3*vte) { */ czero=here->DIOtJctCap*here->DIOarea; if (vd < here->DIOtDepCap){ - arg=1-vd/model->DIOjunctionPot; + arg=1-vd/here->DIOtJctPot; sarg=exp(-model->DIOgradingCoeff*log(arg)); *(ckt->CKTstate0 + here->DIOcapCharge) = - model->DIOtransitTime*cd+model->DIOjunctionPot* + model->DIOtransitTime*cd+here->DIOtJctPot* czero* (1-arg*sarg)/(1-model->DIOgradingCoeff); capd=model->DIOtransitTime*gd+czero*sarg; } else { @@ -205,11 +206,11 @@ next1: if (vd >= -3*vte) { *(ckt->CKTstate0 + here->DIOcapCharge) = model->DIOtransitTime*cd+czero*here->DIOtF1+czof2* (model->DIOf3*(vd-here->DIOtDepCap)+ - (model->DIOgradingCoeff/(model->DIOjunctionPot+ - model->DIOjunctionPot))*(vd*vd-here->DIOtDepCap* + (model->DIOgradingCoeff/(here->DIOtJctPot+ + here->DIOtJctPot))*(vd*vd-here->DIOtDepCap* here->DIOtDepCap)); capd=model->DIOtransitTime*gd+czof2*(model->DIOf3+ - model->DIOgradingCoeff*vd/model->DIOjunctionPot); + model->DIOgradingCoeff*vd/here->DIOtJctPot); } here->DIOcap = capd; diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index 5e3996c73..7c8d08a40 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* load the diode structure with those pointers needed later @@ -86,9 +87,21 @@ matrixpointers: if(model->DIOresist == 0) { here->DIOposPrimeNode = here->DIOposNode; } else if(here->DIOposPrimeNode == 0) { + + CKTnode *tmpNode; + IFuid tmpName; + error = CKTmkVolt(ckt,&tmp,here->DIOname,"internal"); if(error) return(error); here->DIOposPrimeNode = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } /* macro to make elements with built in test for out of memory */ diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index 6cb7b03b4..742b7fda0 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* perform the temperature update to the diode */ @@ -111,7 +112,10 @@ DIOtemp(inModel,ckt) here->DIOtJctPot; /* and Vcrit */ vte=model->DIOemissionCoeff*vt; - here->DIOtVcrit=vte*log(vte/(CONSTroot2*here->DIOtSatCur)); + + here->DIOtVcrit=vte* + log(vte/(CONSTroot2*here->DIOtSatCur*here->DIOarea)); + /* and now to copute the breakdown voltage, again, using * temperature adjusted basic parameters */ if (model->DIObreakdownVoltageGiven){ @@ -121,12 +125,12 @@ DIOtemp(inModel,ckt) emsg = MALLOC(100); if(emsg == (char *)NULL) return(E_NOMEM); (void)sprintf(emsg, - "%%s: breakdown current increased to %g to resolve incompatability", + "%%s: breakdown current increased to %g to resolve", cbv); (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&(here->DIOname)); FREE(emsg); (*(SPfrontEnd->IFerror))(ERR_WARNING, - "with specified saturation current",(IFuid*)NULL); + "incompatibility with specified saturation current",(IFuid*)NULL); xbv=model->DIObreakdownVoltage; } else { tol=ckt->CKTreltol*cbv; diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index ea22be165..9652e0171 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 Alansfixes **********/ #include "ngspice.h" @@ -187,6 +188,7 @@ ISRCload(inModel,ckt) } } loadDone: + if (ckt->CKTmode & MODETRANOP) value *= ckt->CKTsrcFact; *(ckt->CKTrhs + (here->ISRCposNode)) += value; *(ckt->CKTrhs + (here->ISRCnegNode)) -= value; } diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 9ccc71be3..84fd48a70 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -21,6 +22,8 @@ ISRCparam(param,value,inst,select) GENinstance *inst; IFvalue *select; { + +int i; ISRCinstance *here = (ISRCinstance*)inst; switch(param) { case ISRC_DC: @@ -83,6 +86,15 @@ ISRCparam(param,value,inst,select) here->ISRCcoeffs = value->v.vec.rVec; here->ISRCfunctionOrder = value->v.numValue; here->ISRCcoeffsGiven = TRUE; + + for (i=0;i<((here->ISRCfunctionOrder/2)-1);i++) { + if (*(here->ISRCcoeffs+2*(i+1))<=*(here->ISRCcoeffs+2*i)) { + fprintf(stderr, "Warning : current source %s", + here->ISRCname); + fprintf(stderr, " has non-increasing PWL time points.\n"); + } + } + break; case ISRC_SFFM: if(value->v.numValue <2) return(E_BADPARM); diff --git a/src/spicelib/devices/jfet/jfetext.h b/src/spicelib/devices/jfet/jfetext.h index 9da1e4ea0..3a685d319 100644 --- a/src/spicelib/devices/jfet/jfetext.h +++ b/src/spicelib/devices/jfet/jfetext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -22,6 +23,8 @@ extern int JFETtrunc(GENmodel*,CKTcircuit*,double*); extern int JFETdisto(int,GENmodel*,CKTcircuit*); extern int JFETnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int JFETdSetup(GENmodel*,CKTcircuit*); + #else /* stdc */ extern int JFETacLoad(); extern int JFETask(); diff --git a/src/spicelib/devices/jfet/jfetload.c b/src/spicelib/devices/jfet/jfetload.c index cd959d1fb..e7a6835c0 100644 --- a/src/spicelib/devices/jfet/jfetload.c +++ b/src/spicelib/devices/jfet/jfetload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes Sydney University mods Copyright(c) 1989 Anthony E. Parker, David J. Skellern Laboratory for Communication Science Engineering Sydney University Department of Electrical Engineering, Australia @@ -74,6 +75,8 @@ JFETload(inModel,ckt) int icheck; int ichk1; int error; + + double arg, vt_temp; /* loop through all the models */ for( ; model != NULL; model = model->JFETnextModel ) { @@ -219,22 +222,30 @@ JFETload(inModel,ckt) * determine dc current and derivatives */ vds=vgs-vgd; - if (vgs <= -5*here->JFETtemp*CONSTKoverQ) { - ggs = -csat/vgs+ckt->CKTgmin; - cg = ggs*vgs; + + vt_temp=here->JFETtemp*CONSTKoverQ; + if (vgs < -3*vt_temp) { + arg=3*vt_temp/(vgs*CONSTe); + arg = arg * arg * arg; + cg = -csat*(1+arg)+ckt->CKTgmin*vgs; + ggs = csat*3*arg/vgs+ckt->CKTgmin; } else { - evgs = exp(vgs/(here->JFETtemp*CONSTKoverQ)); - ggs = csat*evgs/(here->JFETtemp*CONSTKoverQ)+ckt->CKTgmin; + evgs = exp(vgs/vt_temp); + ggs = csat*evgs/vt_temp+ckt->CKTgmin; cg = csat*(evgs-1)+ckt->CKTgmin*vgs; } - if (vgd <= -5*(here->JFETtemp*CONSTKoverQ)) { - ggd = -csat/vgd+ckt->CKTgmin; - cgd = ggd*vgd; + + if (vgd < -3*vt_temp) { + arg=3*vt_temp/(vgd*CONSTe); + arg = arg * arg * arg; + cgd = -csat*(1+arg)+ckt->CKTgmin*vgd; + ggd = csat*3*arg/vgd+ckt->CKTgmin; } else { - evgd = exp(vgd/(here->JFETtemp*CONSTKoverQ)); - ggd = csat*evgd/(here->JFETtemp*CONSTKoverQ)+ckt->CKTgmin; + evgd = exp(vgd/vt_temp); + ggd = csat*evgd/vt_temp+ckt->CKTgmin; cgd = csat*(evgd-1)+ckt->CKTgmin*vgd; } + cg = cg+cgd; /* Modification for Sydney University JFET model */ diff --git a/src/spicelib/devices/jfet/jfetset.c b/src/spicelib/devices/jfet/jfetset.c index 725b0f5cc..5948c32ba 100644 --- a/src/spicelib/devices/jfet/jfetset.c +++ b/src/spicelib/devices/jfet/jfetset.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes Sydney University mods Copyright(c) 1989 Anthony E. Parker, David J. Skellern Laboratory for Communication Science Engineering Sydney University Department of Electrical Engineering, Australia @@ -95,6 +96,9 @@ JFETsetup(matrix,inModel,ckt,states) here=here->JFETnextInstance) { if (here->JFETowner != ARCHme) goto matrixpointers; + CKTnode *tmpNode; + IFuid tmpName; + if(!here->JFETareaGiven) { here->JFETarea = 1; } @@ -106,6 +110,16 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->JFETname,"source"); if(error) return(error); here->JFETsourcePrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->JFETsourcePrimeNode = here->JFETsourceNode; } @@ -113,6 +127,16 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->JFETname,"drain"); if(error) return(error); here->JFETdrainPrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->JFETdrainPrimeNode = here->JFETdrainNode; } diff --git a/src/spicelib/devices/ltra/ltraext.h b/src/spicelib/devices/ltra/ltraext.h index 5cd0a5625..58aa13e9c 100644 --- a/src/spicelib/devices/ltra/ltraext.h +++ b/src/spicelib/devices/ltra/ltraext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1990 Jaijeet S. Roychowdhury +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -19,6 +20,8 @@ extern int LTRAunsetup(GENmodel*,CKTcircuit*); extern int LTRAtemp(GENmodel*,CKTcircuit*); extern int LTRAtrunc(GENmodel*,CKTcircuit*,double*); +extern int LTRAlinInterp(double,double,double,double*,double*); + extern int LTRAquadInterp(double,double,double,double,double*,double*,double*); /* extern double LTRAcoeffSetup(double*,int,double,double,double*,double,double*,int,int*); diff --git a/src/spicelib/devices/mes/mesext.h b/src/spicelib/devices/mes/mesext.h index 7185d6867..0a9a9005b 100644 --- a/src/spicelib/devices/mes/mesext.h +++ b/src/spicelib/devices/mes/mesext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 S. Hwang +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -22,6 +23,8 @@ extern int MEStrunc(GENmodel*,CKTcircuit*,double*); extern int MESdisto(int,GENmodel*,CKTcircuit*); extern int MESnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int MESdSetup(GENmodel*,CKTcircuit*); + #else /* stdc */ extern int MESacLoad(); extern int MESask(); diff --git a/src/spicelib/devices/mes/mesload.c b/src/spicelib/devices/mes/mesload.c index 6cf322ee3..0e81c0fe6 100644 --- a/src/spicelib/devices/mes/mesload.c +++ b/src/spicelib/devices/mes/mesload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 S. Hwang +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -80,6 +81,7 @@ MESload(inModel,ckt) double vgst; double vto; double xfact; + double arg; int icheck; int ichk1; int error; @@ -230,22 +232,28 @@ MESload(inModel,ckt) * determine dc current and derivatives */ vds = vgs-vgd; - if (vgs <= -5*CONSTvt0) { - ggs = -csat/vgs+ckt->CKTgmin; - cg = ggs*vgs; + + if (vgs <= -3*CONSTvt0) { + arg=3*CONSTvt0/(vgs*CONSTe); + arg = arg * arg * arg; + cg = -csat*(1+arg)+ckt->CKTgmin*vgs; + ggs = csat*3*arg/vgs+ckt->CKTgmin; } else { evgs = exp(vgs/CONSTvt0); ggs = csat*evgs/CONSTvt0+ckt->CKTgmin; cg = csat*(evgs-1)+ckt->CKTgmin*vgs; } - if (vgd <= -5*CONSTvt0) { - ggd = -csat/vgd+ckt->CKTgmin; - cgd = ggd*vgd; + if (vgd <= -3*CONSTvt0) { + arg=3*CONSTvt0/(vgd*CONSTe); + arg = arg * arg * arg; + cgd = -csat*(1+arg)+ckt->CKTgmin*vgd; + ggd = csat*3*arg/vgd+ckt->CKTgmin; } else { evgd = exp(vgd/CONSTvt0); ggd = csat*evgd/CONSTvt0+ckt->CKTgmin; cgd = csat*(evgd-1)+ckt->CKTgmin*vgd; } + cg = cg+cgd; /* * compute drain current and derivitives for normal mode diff --git a/src/spicelib/devices/mes/messetup.c b/src/spicelib/devices/mes/messetup.c index 489864f57..3c9ce3ee6 100644 --- a/src/spicelib/devices/mes/messetup.c +++ b/src/spicelib/devices/mes/messetup.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 S. Hwang +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -81,6 +82,9 @@ MESsetup(matrix,inModel,ckt,states) here=here->MESnextInstance) { if (here->MESowner != ARCHme) goto matrixpointers; + CKTnode *tmpNode; + IFuid tmpName; + if(!here->MESareaGiven) { here->MESarea = 1; } @@ -92,6 +96,16 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->MESname,"source"); if(error) return(error); here->MESsourcePrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MESsourcePrimeNode = here->MESsourceNode; } @@ -99,6 +113,16 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->MESname,"drain"); if(error) return(error); here->MESdrainPrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MESdrainPrimeNode = here->MESdrainNode; } diff --git a/src/spicelib/devices/mos1/mos1.c b/src/spicelib/devices/mos1/mos1.c index 82f74bcf5..cdad2144e 100644 --- a/src/spicelib/devices/mos1/mos1.c +++ b/src/spicelib/devices/mos1/mos1.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -11,6 +12,7 @@ Author: 1987 Thomas L. Quarles #include "suffix.h" IFparm MOS1pTable[] = { /* parameters */ + IOPU("m", MOS1_M, IF_REAL , "Multiplier"), IOPU("l", MOS1_L, IF_REAL , "Length"), IOPU("w", MOS1_W, IF_REAL , "Width"), IOPU("ad", MOS1_AD, IF_REAL , "Drain area"), diff --git a/src/spicelib/devices/mos1/mos1acld.c b/src/spicelib/devices/mos1/mos1acld.c index ba2053429..b6edf7785 100644 --- a/src/spicelib/devices/mos1/mos1acld.c +++ b/src/spicelib/devices/mos1/mos1acld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -51,12 +52,14 @@ MOS1acLoad(inModel,ckt) * meyer's model parameters */ EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; + GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS1m * EffectiveLength; + capgs = ( *(ckt->CKTstate0+here->MOS1capgs)+ *(ckt->CKTstate0+here->MOS1capgs) + GateSourceOverlapCap ); diff --git a/src/spicelib/devices/mos1/mos1ask.c b/src/spicelib/devices/mos1/mos1ask.c index 2b471061b..dd717cb19 100644 --- a/src/spicelib/devices/mos1/mos1ask.c +++ b/src/spicelib/devices/mos1/mos1ask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -34,11 +35,14 @@ MOS1ask(ckt,inst,which,value,select) value->rValue = here->MOS1temp-CONSTCtoK; return(OK); case MOS1_CGS: - value->rValue = *(ckt->CKTstate0 + here->MOS1capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgs); return(OK); case MOS1_CGD: - value->rValue = *(ckt->CKTstate0 + here->MOS1capgd); - return(OK); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgd); + return(OK); + case MOS1_M: + value->rValue = here->MOS1m; + return(OK); case MOS1_L: value->rValue = here->MOS1l; return(OK); @@ -178,7 +182,11 @@ MOS1ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS1vds); return(OK); case MOS1_CAPGS: - value->rValue = *(ckt->CKTstate0 + here->MOS1capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgs); + /* add overlap capacitance */ + value->rValue += (here->sMOS1modPtr->MOS1gateSourceOverlapCapFactor) + * here->MOS1m + * (here->MOS1w); return(OK); case MOS1_QGS: value->rValue = *(ckt->CKTstate0 + here->MOS1qgs); @@ -187,7 +195,11 @@ MOS1ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS1cqgs); return(OK); case MOS1_CAPGD: - value->rValue = *(ckt->CKTstate0 + here->MOS1capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgd); + * add overlap capacitance */ + value->rValue += (here->sMOS1modPtr->MOS1gateSourceOverlapCapFactor) + * here->MOS1m + * (here->MOS1w); return(OK); case MOS1_QGD: value->rValue = *(ckt->CKTstate0 + here->MOS1qgd); @@ -196,7 +208,12 @@ MOS1ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS1cqgd); return(OK); case MOS1_CAPGB: - value->rValue = *(ckt->CKTstate0 + here->MOS1capgb); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS1capgb); + /* add overlap capacitance */ + value->rValue += (here->sMOS1modPtr->MOS1gateBulkOverlapCapFactor) + * here->MOS1m + * (here->MOS1l + -2*(here->sMOS1modPtr->MOS1latDiff)); return(OK); case MOS1_QGB: value->rValue = *(ckt->CKTstate0 + here->MOS1qgb); diff --git a/src/spicelib/devices/mos1/mos1defs.h b/src/spicelib/devices/mos1/mos1defs.h index fd1a254b0..1d47a28dd 100644 --- a/src/spicelib/devices/mos1/mos1defs.h +++ b/src/spicelib/devices/mos1/mos1defs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifndef MOS1 @@ -30,6 +31,8 @@ typedef struct sMOS1instance { int MOS1bNode; /* number of the bulk node of the mosfet */ int MOS1dNodePrime; /* number of the internal drain node of the mosfet */ int MOS1sNodePrime; /* number of the internal source node of the mosfet */ + + double MOS1m; /* parallel device multiplier */ double MOS1l; /* the length of the channel region */ double MOS1w; /* the width of the channel region */ @@ -156,6 +159,7 @@ typedef struct sMOS1instance { unsigned MOS1off:1; /* non-zero to indicate device is off for dc analysis*/ unsigned MOS1tempGiven :1; /* instance temperature specified */ + unsigned MOS1mGiven :1; unsigned MOS1lGiven :1; unsigned MOS1wGiven :1; unsigned MOS1drainAreaGiven :1; @@ -406,7 +410,7 @@ typedef struct sMOS1model { /* model structure for a resistor */ #define MOS1_CS 18 #define MOS1_POWER 19 #define MOS1_TEMP 20 - +#define MOS1_M 21 /* model paramerers */ #define MOS1_MOD_VTO 101 #define MOS1_MOD_KP 102 diff --git a/src/spicelib/devices/mos1/mos1dset.c b/src/spicelib/devices/mos1/mos1dset.c index e16c9f8d9..8278f01ad 100644 --- a/src/spicelib/devices/mos1/mos1dset.c +++ b/src/spicelib/devices/mos1/mos1dset.c @@ -91,26 +91,28 @@ MOS1dSetup(inModel,ckt) vt = CONSTKoverQ * here->MOS1temp; EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; - if( (here->MOS1tSatCurDens == 0) || + + if( (here->MOS1tSatCurDens == 0) || (here->MOS1drainArea == 0) || (here->MOS1sourceArea == 0)) { - DrainSatCur = here->MOS1tSatCur; - SourceSatCur = here->MOS1tSatCur; + DrainSatCur = here->MOS1m * here->MOS1tSatCur; + SourceSatCur = here->MOS1m * here->MOS1tSatCur; } else { DrainSatCur = here->MOS1tSatCurDens * - here->MOS1drainArea; + here->MOS1m * here->MOS1drainArea; SourceSatCur = here->MOS1tSatCurDens * - here->MOS1sourceArea; + here->MOS1m * here->MOS1sourceArea; } GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS1tTransconductance * here->MOS1w/EffectiveLength; + here->MOS1m * EffectiveLength; + Beta = here->MOS1tTransconductance * here->MOS1m * + here->MOS1w/EffectiveLength; OxideCap = model->MOS1oxideCapFactor * EffectiveLength * - here->MOS1w; + here->MOS1m * here->MOS1w; vbs = model->MOS1type * ( *(ckt->CKTrhsOld+here->MOS1bNode) - diff --git a/src/spicelib/devices/mos1/mos1ext.h b/src/spicelib/devices/mos1/mos1ext.h index 94306a507..5a4514b42 100644 --- a/src/spicelib/devices/mos1/mos1ext.h +++ b/src/spicelib/devices/mos1/mos1ext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -27,6 +28,7 @@ extern int MOS1trunc(GENmodel*,CKTcircuit*,double*); extern int MOS1convTest(GENmodel*,CKTcircuit*); extern int MOS1disto(int,GENmodel*,CKTcircuit*); extern int MOS1noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int MOS1dSetup(GENmodel*,CKTcircuit*); #else /* stdc */ extern int MOS1acLoad(); diff --git a/src/spicelib/devices/mos1/mos1load.c b/src/spicelib/devices/mos1/mos1load.c index 8623f5fb4..be0bd20f1 100644 --- a/src/spicelib/devices/mos1/mos1load.c +++ b/src/spicelib/devices/mos1/mos1load.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -111,26 +112,29 @@ MOS1load(inModel,ckt) */ EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; + if( (here->MOS1tSatCurDens == 0) || - (here->MOS1drainArea == 0) || - (here->MOS1sourceArea == 0)) { - DrainSatCur = here->MOS1tSatCur; - SourceSatCur = here->MOS1tSatCur; + (here->MOS1drainArea == 0) || + (here->MOS1sourceArea == 0)) { + DrainSatCur = here->MOS1m * here->MOS1tSatCur; + SourceSatCur = here->MOS1m * here->MOS1tSatCur; } else { DrainSatCur = here->MOS1tSatCurDens * - here->MOS1drainArea; + here->MOS1m * here->MOS1drainArea; SourceSatCur = here->MOS1tSatCurDens * - here->MOS1sourceArea; + here->MOS1m * here->MOS1sourceArea; } GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS1tTransconductance * here->MOS1w/EffectiveLength; + here->MOS1m * EffectiveLength; + Beta = here->MOS1tTransconductance * here->MOS1m * + here->MOS1w/EffectiveLength; OxideCap = model->MOS1oxideCapFactor * EffectiveLength * - here->MOS1w; + here->MOS1m * here->MOS1w; + /* * ok - now to do the start-up operations * @@ -412,25 +416,22 @@ MOS1load(inModel,ckt) * here we just evaluate the ideal diode current and the * corresponding derivative (conductance). */ - next1: if(vbs <= 0) { - here->MOS1gbs = SourceSatCur/vt; - here->MOS1cbs = here->MOS1gbs*vbs; - here->MOS1gbs += ckt->CKTgmin; - } else { - evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); - here->MOS1gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; - here->MOS1cbs = SourceSatCur * (evbs-1); - } - if(vbd <= 0) { - here->MOS1gbd = DrainSatCur/vt; - here->MOS1cbd = here->MOS1gbd *vbd; - here->MOS1gbd += ckt->CKTgmin; +next1: if(vbs <= -3*vt) { + here->MOS1gbs = ckt->CKTgmin; + here->MOS1cbs = here->MOS1gbs*vbs-SourceSatCur; + } else { + evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); + here->MOS1gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; + here->MOS1cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; + } + if(vbd <= -3*vt) { + here->MOS1gbd = ckt->CKTgmin; + here->MOS1cbd = here->MOS1gbd*vbd-DrainSatCur; } else { evbd = exp(MIN(MAX_EXP_ARG,vbd/vt)); - here->MOS1gbd = DrainSatCur*evbd/vt +ckt->CKTgmin; - here->MOS1cbd = DrainSatCur *(evbd-1); + here->MOS1gbd = DrainSatCur*evbd/vt + ckt->CKTgmin; + here->MOS1cbd = DrainSatCur*(evbd-1) + ckt->CKTgmin*vbd; } - /* now to determine whether the user was able to correctly * identify the source and drain of his device */ @@ -861,9 +862,9 @@ MOS1load(inModel,ckt) * load current vector */ ceqbs = model->MOS1type * - (here->MOS1cbs-(here->MOS1gbs-ckt->CKTgmin)*vbs); + (here->MOS1cbs-(here->MOS1gbs)*vbs); ceqbd = model->MOS1type * - (here->MOS1cbd-(here->MOS1gbd-ckt->CKTgmin)*vbd); + (here->MOS1cbd-(here->MOS1gbd)*vbd); if (here->MOS1mode >= 0) { xnrm=1; xrev=0; diff --git a/src/spicelib/devices/mos1/mos1noi.c b/src/spicelib/devices/mos1/mos1noi.c index 58b4b5d77..1da24d77e 100644 --- a/src/spicelib/devices/mos1/mos1noi.c +++ b/src/spicelib/devices/mos1/mos1noi.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Gary W. Ng +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -145,6 +146,7 @@ if (!data->namelist) return(E_NOMEM); exp(model->MOS1fNexp * log(MAX(fabs(inst->MOS1cd),N_MINLOG))) / (data->freq * inst->MOS1w * + inst->MOS1m * (inst->MOS1l - 2*model->MOS1latDiff) * coxSquared); lnNdens[MOS1FLNOIZ] = log(MAX(noizDens[MOS1FLNOIZ],N_MINLOG)); diff --git a/src/spicelib/devices/mos1/mos1par.c b/src/spicelib/devices/mos1/mos1par.c index a8dbce338..c0b137da7 100644 --- a/src/spicelib/devices/mos1/mos1par.c +++ b/src/spicelib/devices/mos1/mos1par.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -28,6 +29,10 @@ MOS1param(param,value,inst,select) here->MOS1temp = value->rValue+CONSTCtoK; here->MOS1tempGiven = TRUE; break; + case MOS1_M: + here->MOS1m = value->rValue; + here->MOS1mGiven = TRUE; + break; case MOS1_W: here->MOS1w = value->rValue; here->MOS1wGiven = TRUE; diff --git a/src/spicelib/devices/mos1/mos1pzld.c b/src/spicelib/devices/mos1/mos1pzld.c index 7be6fd345..0f8d2f7d0 100644 --- a/src/spicelib/devices/mos1/mos1pzld.c +++ b/src/spicelib/devices/mos1/mos1pzld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -53,12 +54,14 @@ MOS1pzLoad(inModel,ckt,s) * meyer's model parameters */ EffectiveLength=here->MOS1l - 2*model->MOS1latDiff; + GateSourceOverlapCap = model->MOS1gateSourceOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateDrainOverlapCap = model->MOS1gateDrainOverlapCapFactor * - here->MOS1w; + here->MOS1m * here->MOS1w; GateBulkOverlapCap = model->MOS1gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS1m * EffectiveLength; + capgs = ( 2* *(ckt->CKTstate0+here->MOS1capgs)+ GateSourceOverlapCap ); capgd = ( 2* *(ckt->CKTstate0+here->MOS1capgd)+ diff --git a/src/spicelib/devices/mos1/mos1set.c b/src/spicelib/devices/mos1/mos1set.c index 480da45dc..bad23675b 100644 --- a/src/spicelib/devices/mos1/mos1set.c +++ b/src/spicelib/devices/mos1/mos1set.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* load the MOS1 device structure with those pointers needed later @@ -104,6 +105,9 @@ MOS1setup(matrix,inModel,ckt,states) } } + CKTnode *tmpNode; + IFuid tmpName; + if(!here->MOS1drainPerimiterGiven) { here->MOS1drainPerimiter = 0; } @@ -139,6 +143,16 @@ MOS1setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS1name,"drain"); if(error) return(error); here->MOS1dNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MOS1dNodePrime = here->MOS1dNode; } @@ -150,6 +164,16 @@ MOS1setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS1name,"source"); if(error) return(error); here->MOS1sNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MOS1sNodePrime = here->MOS1sNode; } diff --git a/src/spicelib/devices/mos1/mos1sprt.c b/src/spicelib/devices/mos1/mos1sprt.c index 57469bffc..818ea38e3 100644 --- a/src/spicelib/devices/mos1/mos1sprt.c +++ b/src/spicelib/devices/mos1/mos1sprt.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* Pretty print the sensitivity info for all @@ -41,7 +42,10 @@ CKTcircuit *ckt; printf(" Drain, Gate , Source nodes: %s, %s ,%s\n", CKTnodName(ckt,here->MOS1dNode),CKTnodName(ckt,here->MOS1gNode), CKTnodName(ckt,here->MOS1sNode)); - + + printf(" Multiplier: %g ",here->MOS1m); + printf(here->MOS1mGiven ? "(specified)\n" : "(default)\n"); + printf(" Length: %g ",here->MOS1l); printf(here->MOS1lGiven ? "(specified)\n" : "(default)\n"); printf(" Width: %g ",here->MOS1w); diff --git a/src/spicelib/devices/mos1/mos1temp.c b/src/spicelib/devices/mos1/mos1temp.c index 72cf5d7f0..6dcf255df 100644 --- a/src/spicelib/devices/mos1/mos1temp.c +++ b/src/spicelib/devices/mos1/mos1temp.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -137,6 +138,9 @@ MOS1temp(inModel,ckt) if(!here->MOS1drainAreaGiven) { here->MOS1drainArea = ckt->CKTdefaultMosAD; } + if(!here->MOS1mGiven) { + here->MOS1m = ckt->CKTdefaultMosM; + } if(!here->MOS1lGiven) { here->MOS1l = ckt->CKTdefaultMosL; } @@ -193,27 +197,30 @@ MOS1temp(inModel,ckt) (here->MOS1drainArea == 0) || (here->MOS1sourceArea == 0) ) { here->MOS1sourceVcrit = here->MOS1drainVcrit = - vt*log(vt/(CONSTroot2*here->MOS1tSatCur)); + vt*log(vt/(CONSTroot2*here->MOS1m*here->MOS1tSatCur)); } else { here->MOS1drainVcrit = vt * log( vt / (CONSTroot2 * + here->MOS1m * here->MOS1tSatCurDens * here->MOS1drainArea)); here->MOS1sourceVcrit = vt * log( vt / (CONSTroot2 * + here->MOS1m * here->MOS1tSatCurDens * here->MOS1sourceArea)); } if(model->MOS1capBDGiven) { - czbd = here->MOS1tCbd; + czbd = here->MOS1tCbd * here->MOS1m; } else { - if(model->MOS1bulkCapFactorGiven) { - czbd=here->MOS1tCj*here->MOS1drainArea; + if(model->MOS1bulkCapFactorGiven) { + czbd=here->MOS1tCj*here->MOS1m*here->MOS1drainArea; } else { czbd=0; } } if(model->MOS1sideWallCapFactorGiven) { - czbdsw= here->MOS1tCjsw * here->MOS1drainPerimiter; + czbdsw= here->MOS1tCjsw * here->MOS1drainPerimiter * + here->MOS1m; } else { czbdsw=0; } @@ -239,16 +246,17 @@ MOS1temp(inModel,ckt) (here->MOS1tDepCap*here->MOS1tDepCap) -here->MOS1tDepCap * here->MOS1f2d; if(model->MOS1capBSGiven) { - czbs=here->MOS1tCbs; + czbs=here->MOS1tCbs * here->MOS1m; } else { if(model->MOS1bulkCapFactorGiven) { - czbs=here->MOS1tCj*here->MOS1sourceArea; + czbs=here->MOS1tCj*here->MOS1sourceArea * here->MOS1m; } else { czbs=0; } } if(model->MOS1sideWallCapFactorGiven) { - czbssw = here->MOS1tCjsw * here->MOS1sourcePerimiter; + czbssw = here->MOS1tCjsw * here->MOS1sourcePerimiter * + here->MOS1m; } else { czbssw=0; } @@ -277,14 +285,16 @@ MOS1temp(inModel,ckt) if(model->MOS1drainResistanceGiven) { if(model->MOS1drainResistance != 0) { - here->MOS1drainConductance = 1/model->MOS1drainResistance; + here->MOS1drainConductance = here->MOS1m / + model->MOS1drainResistance; } else { here->MOS1drainConductance = 0; } } else if (model->MOS1sheetResistanceGiven) { if(model->MOS1sheetResistance != 0) { here->MOS1drainConductance = - 1/(model->MOS1sheetResistance*here->MOS1drainSquares); + here->MOS1m / + (model->MOS1sheetResistance*here->MOS1drainSquares); } else { here->MOS1drainConductance = 0; } @@ -293,14 +303,18 @@ MOS1temp(inModel,ckt) } if(model->MOS1sourceResistanceGiven) { if(model->MOS1sourceResistance != 0) { - here->MOS1sourceConductance = 1/model->MOS1sourceResistance; + here->MOS1sourceConductance = here->MOS1m / + model->MOS1sourceResistance; } else { here->MOS1sourceConductance = 0; } } else if (model->MOS1sheetResistanceGiven) { - if(model->MOS1sheetResistance != 0) { + if ((model->MOS1sheetResistance != 0) && + (here->MOS1sourceSquares != 0)) { +#else here->MOS1sourceConductance = - 1/(model->MOS1sheetResistance*here->MOS1sourceSquares); + here->MOS1m / + (model->MOS1sheetResistance*here->MOS1sourceSquares); } else { here->MOS1sourceConductance = 0; } diff --git a/src/spicelib/devices/mos2/mos2.c b/src/spicelib/devices/mos2/mos2.c index 706db5ea3..b51c7b011 100644 --- a/src/spicelib/devices/mos2/mos2.c +++ b/src/spicelib/devices/mos2/mos2.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFIxes **********/ #include "ngspice.h" @@ -11,6 +12,7 @@ Author: 1985 Thomas L. Quarles #include "suffix.h" IFparm MOS2pTable[] = { /* parameters */ + IOPU("m", MOS2_M, IF_REAL , "Multiplier"), IOPU("l", MOS2_L, IF_REAL , "Length"), IOPU("w", MOS2_W, IF_REAL , "Width"), IOPU("ad", MOS2_AD, IF_REAL , "Drain area"), diff --git a/src/spicelib/devices/mos2/mos2acld.c b/src/spicelib/devices/mos2/mos2acld.c index 520c13e93..f773ed78e 100644 --- a/src/spicelib/devices/mos2/mos2acld.c +++ b/src/spicelib/devices/mos2/mos2acld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -52,11 +53,11 @@ MOS2acLoad(inModel,ckt) */ EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS2m * EffectiveLength; capgs = ( *(ckt->CKTstate0+here->MOS2capgs)+ *(ckt->CKTstate0+here->MOS2capgs) + GateSourceOverlapCap ); diff --git a/src/spicelib/devices/mos2/mos2ask.c b/src/spicelib/devices/mos2/mos2ask.c index 14e05377a..1849e9344 100644 --- a/src/spicelib/devices/mos2/mos2ask.c +++ b/src/spicelib/devices/mos2/mos2ask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Mathew Lew and Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -34,14 +35,17 @@ MOS2ask(ckt,inst,which,value,select) value->rValue = here->MOS2temp-CONSTCtoK; return(OK); case MOS2_CGS: - value->rValue = *(ckt->CKTstate0 + here->MOS2capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS2capgs); return(OK); case MOS2_CGD: - value->rValue = *(ckt->CKTstate0 + here->MOS2capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS2capgd); + return(OK); + case MOS2_M: + value->rValue = here->MOS2m; return(OK); case MOS2_L: value->rValue = here->MOS2l; - return(OK); + return(OK); case MOS2_W: value->rValue = here->MOS2w; return(OK); @@ -178,7 +182,11 @@ MOS2ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS2vds); return(OK); case MOS2_CAPGS: - value->rValue = *(ckt->CKTstate0 + here->MOS2capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS2capgs); +/* add overlap capacitance */ + value->rValue += (here->MOS2modPtr->MOS2gateSourceOverlapCapFactor) + * here->MOS2m + * (here->MOS2w); return(OK); case MOS2_QGS: value->rValue = *(ckt->CKTstate0 + here->MOS2qgs); @@ -187,7 +195,11 @@ MOS2ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS2cqgs); return(OK); case MOS2_CAPGD: - value->rValue = *(ckt->CKTstate0 + here->MOS2capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS2capgd); +/* add overlap capacitance */ + value->rValue += (here->MOS2modPtr->MOS2gateSourceOverlapCapFactor) + * here->MOS2m + * (here->MOS2w); return(OK); case MOS2_QGD: value->rValue = *(ckt->CKTstate0 + here->MOS2qgd); @@ -196,7 +208,12 @@ MOS2ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS2cqgd); return(OK); case MOS2_CAPGB: - value->rValue = *(ckt->CKTstate0 + here->MOS2capgb); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS2capgb); +/* add overlap capacitance */ + value->rValue += (here->MOS2modPtr->MOS2gateBulkOverlapCapFactor) + * here->MOS2m + * (here->MOS2l + -2*(here->MOS2modPtr->MOS2latDiff)); return(OK); case MOS2_QGB: value->rValue = *(ckt->CKTstate0 + here->MOS2qgb); diff --git a/src/spicelib/devices/mos2/mos2defs.h b/src/spicelib/devices/mos2/mos2defs.h index 5bec7c8eb..c35efb417 100644 --- a/src/spicelib/devices/mos2/mos2defs.h +++ b/src/spicelib/devices/mos2/mos2defs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFIxes **********/ #ifndef MOS2 @@ -33,6 +34,8 @@ typedef struct sMOS2instance { int MOS2mode; /* device mode : 1 = normal, -1 = inverse */ + unsigned MOS2mGiven :1; + unsigned MOS2off :1;/* non-zero to indicate device is off for dc analysis*/ unsigned MOS2lGiven :1; unsigned MOS2wGiven :1; @@ -151,6 +154,8 @@ typedef struct sMOS2instance { /* the cureve matching Fc * Vj */ double MOS2tVbi; /* temperature adjusted Vbi */ + double MOS2m; /* parallel device multiplier */ + double MOS2l; /* the length of the channel region */ double MOS2w; /* the width of the channel region */ double MOS2drainArea; /* the area of the drain diffusion */ @@ -489,6 +494,7 @@ typedef struct sMOS2model { /* model structure for a resistor */ #define MOS2_TEMP 77 #define MOS2_SOURCERESIST 78 #define MOS2_DRAINRESIST 79 +#define MOS2_M 80 /* model paramerers */ #define MOS2_MOD_VTO 101 diff --git a/src/spicelib/devices/mos2/mos2dset.c b/src/spicelib/devices/mos2/mos2dset.c index 22d3fce14..409c613db 100644 --- a/src/spicelib/devices/mos2/mos2dset.c +++ b/src/spicelib/devices/mos2/mos2dset.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified: 2000 AlansFixes **********/ #include @@ -82,26 +83,28 @@ double gmbds; vt = CONSTKoverQ * here->MOS2temp; EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; - if( (here->MOS2tSatCurDens == 0) || + + if( (here->MOS2tSatCurDens == 0) || (here->MOS2drainArea == 0) || (here->MOS2sourceArea == 0)) { - DrainSatCur = here->MOS2tSatCur; - SourceSatCur = here->MOS2tSatCur; + DrainSatCur = here->MOS2m * here->MOS2tSatCur; + SourceSatCur = here->MOS2m * here->MOS2tSatCur; } else { DrainSatCur = here->MOS2tSatCurDens * - here->MOS2drainArea; + here->MOS2m * here->MOS2drainArea; SourceSatCur = here->MOS2tSatCurDens * - here->MOS2sourceArea; + here->MOS2m * here->MOS2sourceArea; } GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS2tTransconductance * here->MOS2w/EffectiveLength; + here->MOS2m * EffectiveLength; + Beta = here->MOS2tTransconductance * here->MOS2m * + here->MOS2w/EffectiveLength; OxideCap = model->MOS2oxideCapFactor * EffectiveLength * - here->MOS2w; + here->MOS2m * here->MOS2w; @@ -481,7 +484,7 @@ d_p.d3_pqr = 0.0; PlusDeriv(&d_cdonco,&d_cdonco,&d_dummy); TimesDeriv(&d_cdonco,&d_cdonco,-1.0); d_cdonco.value += factor; - xn = 1.0+cfs/OxideCap*here->MOS2w*EffectiveLength+cdonco; + xn = 1.0+cfs/OxideCap*here->MOS2m*here->MOS2w*EffectiveLength+cdonco; EqualDeriv(&d_xn,&d_cdonco); d_xn.value = xn; tmp = vt*xn; diff --git a/src/spicelib/devices/mos2/mos2ext.h b/src/spicelib/devices/mos2/mos2ext.h index fd472fc5b..a82c0b38a 100644 --- a/src/spicelib/devices/mos2/mos2ext.h +++ b/src/spicelib/devices/mos2/mos2ext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -27,6 +28,9 @@ extern int MOS2temp(GENmodel*,CKTcircuit*); extern int MOS2trunc(GENmodel*,CKTcircuit*,double*); extern int MOS2disto(int,GENmodel*,CKTcircuit*); extern int MOS2noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); + +extern int MOS2dSetup(GENmodel*,CKTcircuit*); + #else /* stdc */ extern int MOS2acLoad(); extern int MOS2ask(); diff --git a/src/spicelib/devices/mos2/mos2load.c b/src/spicelib/devices/mos2/mos2load.c index c66f4901a..6ccda5825 100644 --- a/src/spicelib/devices/mos2/mos2load.c +++ b/src/spicelib/devices/mos2/mos2load.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 alansFixes **********/ #include "ngspice.h" @@ -108,26 +109,28 @@ MOS2load(inModel,ckt) } EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; + if( (here->MOS2tSatCurDens == 0) || (here->MOS2drainArea == 0) || (here->MOS2sourceArea == 0)) { - DrainSatCur = here->MOS2tSatCur; - SourceSatCur = here->MOS2tSatCur; + DrainSatCur = here->MOS2m * here->MOS2tSatCur; + SourceSatCur = here->MOS2m * here->MOS2tSatCur; } else { - DrainSatCur = here->MOS2tSatCurDens * + DrainSatCur = here->MOS2m * here->MOS2tSatCurDens * here->MOS2drainArea; - SourceSatCur = here->MOS2tSatCurDens * + SourceSatCur = here->MOS2m * here->MOS2tSatCurDens * here->MOS2sourceArea; } GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS2tTransconductance * here->MOS2w/EffectiveLength; + here->MOS2m * EffectiveLength; + Beta = here->MOS2tTransconductance * here->MOS2w * + here->MOS2m/EffectiveLength; OxideCap = model->MOS2oxideCapFactor * EffectiveLength * - here->MOS2w; + here->MOS2m * here->MOS2w; if(SenCond){ @@ -374,24 +377,23 @@ MOS2load(inModel,ckt) * correspoinding derivative (conductance). */ -next1: if(vbs <= 0) { - here->MOS2gbs = SourceSatCur/vt; - here->MOS2cbs = here->MOS2gbs*vbs; - here->MOS2gbs += ckt->CKTgmin; +next1: if(vbs <= -3*vt) { + here->MOS2gbs = ckt->CKTgmin; + here->MOS2cbs = here->MOS2gbs*vbs-SourceSatCur; } else { - evbs = exp(vbs/vt); + evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); here->MOS2gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; - here->MOS2cbs = SourceSatCur * (evbs-1); + here->MOS2cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; } - if(vbd <= 0) { - here->MOS2gbd = DrainSatCur/vt; - here->MOS2cbd = here->MOS2gbd *vbd; - here->MOS2gbd += ckt->CKTgmin; + if(vbd <= -3*vt) { + here->MOS2gbd = ckt->CKTgmin; + here->MOS2cbd = here->MOS2gbd*vbd-DrainSatCur; } else { - evbd = exp(vbd/vt); - here->MOS2gbd = DrainSatCur*evbd/vt +ckt->CKTgmin; - here->MOS2cbd = DrainSatCur *(evbd-1); + evbd = exp(MIN(MAX_EXP_ARG,vbd/vt)); + here->MOS2gbd = DrainSatCur*evbd/vt + ckt->CKTgmin; + here->MOS2cbd = DrainSatCur*(evbd-1) + ckt->CKTgmin*vbd; } + if(vds >= 0) { /* normal mode */ here->MOS2mode = 1; @@ -561,7 +563,7 @@ next1: if(vbs <= 0) { dsrgdb = -0.5*sarg*tmp; d2sdb2 = -dsrgdb*tmp; } - if ((lvds-lvbs) >= 0) { + if ((lvbs-lvds) <= 0) { barg = sqrt(phiMinVbs+lvds); dbrgdb = -0.5/barg; d2bdb2 = 0.5*dbrgdb/(phiMinVbs+lvds); @@ -642,14 +644,17 @@ next1: if(vbs <= 0) { cfs = CHARGE*model->MOS2fastSurfaceStateDensity* 1e4 /*(cm**2/m**2)*/; cdonco = -(gamasd*dsrgdb+dgddvb*sarg)+factor; - xn = 1.0+cfs/OxideCap*here->MOS2w*EffectiveLength+cdonco; + + xn = 1.0+cfs/OxideCap*here->MOS2m* + here->MOS2w*EffectiveLength+cdonco; + tmp = vt*xn; von = von+tmp; argg = 1.0/tmp; vgst = lvgs-von; } else { vgst = lvgs-von; - if (lvgs <= von) { + if (lvgs <= vbin) { /* * cutoff region */ @@ -899,6 +904,13 @@ line610: goto line1050; } + if (model->MOS2fastSurfaceStateDensity != 0 && OxideCap != 0) { + if (lvgs > von) goto line900; + } else { + if (lvgs > vbin) goto line900; + goto doneval; + } + if (lvgs > von) goto line900; /* * subthreshold region @@ -1285,9 +1297,9 @@ bypass: * load current vector */ ceqbs = model->MOS2type * - (here->MOS2cbs-(here->MOS2gbs-ckt->CKTgmin)*vbs); + (here->MOS2cbs-(here->MOS2gbs)*vbs); ceqbd = model->MOS2type * - (here->MOS2cbd-(here->MOS2gbd-ckt->CKTgmin)*vbd); + (here->MOS2cbd-(here->MOS2gbd)*vbd); if (here->MOS2mode >= 0) { xnrm=1; xrev=0; diff --git a/src/spicelib/devices/mos2/mos2noi.c b/src/spicelib/devices/mos2/mos2noi.c index b97553eda..9e9a6fa18 100644 --- a/src/spicelib/devices/mos2/mos2noi.c +++ b/src/spicelib/devices/mos2/mos2noi.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Gary W. Ng +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -134,7 +135,8 @@ if (!data->namelist) return(E_NOMEM); noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef * exp(model->MOS2fNexp * log(MAX(fabs(inst->MOS2cd),N_MINLOG))) / - (data->freq * inst->MOS2w * + (data->freq * inst->MOS2w * + inst->MOS2m * (inst->MOS2l - 2*model->MOS2latDiff) * model->MOS2oxideCapFactor * model->MOS2oxideCapFactor); lnNdens[MOS2FLNOIZ] = diff --git a/src/spicelib/devices/mos2/mos2par.c b/src/spicelib/devices/mos2/mos2par.c index 24e002e2b..c661095f8 100644 --- a/src/spicelib/devices/mos2/mos2par.c +++ b/src/spicelib/devices/mos2/mos2par.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -28,6 +29,10 @@ MOS2param(param,value,inst,select) here->MOS2temp = value->rValue+CONSTCtoK; here->MOS2tempGiven = TRUE; break; + case MOS2_M: + here->MOS2m = value->rValue; + here->MOS2mGiven = TRUE; + break; case MOS2_W: here->MOS2w = value->rValue; here->MOS2wGiven = TRUE; diff --git a/src/spicelib/devices/mos2/mos2pzld.c b/src/spicelib/devices/mos2/mos2pzld.c index 738126d43..73495230e 100644 --- a/src/spicelib/devices/mos2/mos2pzld.c +++ b/src/spicelib/devices/mos2/mos2pzld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -53,12 +54,14 @@ MOS2pzLoad(inModel,ckt,s) * meyer's model parameters */ EffectiveLength=here->MOS2l - 2*model->MOS2latDiff; + GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor * - here->MOS2w; + here->MOS2m * here->MOS2w; GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS2m * EffectiveLength; + capgs = ( 2* *(ckt->CKTstate0+here->MOS2capgs)+ GateSourceOverlapCap ); capgd = ( 2* *(ckt->CKTstate0+here->MOS2capgd)+ diff --git a/src/spicelib/devices/mos2/mos2set.c b/src/spicelib/devices/mos2/mos2set.c index 6bfc43890..3b1e8afe2 100644 --- a/src/spicelib/devices/mos2/mos2set.c +++ b/src/spicelib/devices/mos2/mos2set.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -124,7 +125,10 @@ MOS2setup(matrix,inModel,ckt,states) /* loop through all the instances of the model */ for (here = model->MOS2instances; here != NULL ; here=here->MOS2nextInstance) { - + + CKTnode *tmpNode; + IFuid tmpName; + if (here->MOS2owner == ARCHme) { /* allocate a chunk of the state vector */ here->MOS2states = *states; @@ -165,6 +169,16 @@ MOS2setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#drain"); if(error) return(error); here->MOS2dNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MOS2dNodePrime = here->MOS2dNode; } @@ -176,6 +190,16 @@ MOS2setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#source"); if(error) return(error); here->MOS2sNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } else { here->MOS2sNodePrime = here->MOS2sNode; } diff --git a/src/spicelib/devices/mos2/mos2sprt.c b/src/spicelib/devices/mos2/mos2sprt.c index 2dade4a63..c4a5820c1 100644 --- a/src/spicelib/devices/mos2/mos2sprt.c +++ b/src/spicelib/devices/mos2/mos2sprt.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -22,7 +23,7 @@ MOS2sPrint(inModel,ckt) MOS2model *model = (MOS2model *)inModel; MOS2instance *here; - printf("LEVEL 1 MOSFETS-----------------\n"); + printf("LEVEL 2 MOSFETS-----------------\n"); /* loop through all the MOS2 models */ for( ; model != NULL; model = model->MOS2nextModel ) { @@ -38,6 +39,8 @@ MOS2sPrint(inModel,ckt) CKTnodName(ckt,here->MOS2dNode),CKTnodName(ckt,here->MOS2gNode), CKTnodName(ckt,here->MOS2sNode)); + printf(" Multiplier: %g ",here->MOS2m); + printf(here->MOS2mGiven ? "(specified)\n" : "(default)\n"); printf(" Length: %g ",here->MOS2l); printf(here->MOS2lGiven ? "(specified)\n" : "(default)\n"); printf(" Width: %g ",here->MOS2w); diff --git a/src/spicelib/devices/mos2/mos2temp.c b/src/spicelib/devices/mos2/mos2temp.c index 9b12482ca..f72f93345 100644 --- a/src/spicelib/devices/mos2/mos2temp.c +++ b/src/spicelib/devices/mos2/mos2temp.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -147,6 +148,9 @@ MOS2temp(inModel,ckt) if(!here->MOS2drainAreaGiven) { here->MOS2drainArea = ckt->CKTdefaultMosAD; + } + if(!here->MOS2mGiven) { + here->MOS2m = ckt->CKTdefaultMosM; } if(!here->MOS2lGiven) { here->MOS2l = ckt->CKTdefaultMosL; @@ -159,14 +163,17 @@ MOS2temp(inModel,ckt) } if(model->MOS2drainResistanceGiven) { if(model->MOS2drainResistance != 0) { - here->MOS2drainConductance = 1/model->MOS2drainResistance; + here->MOS2drainConductance = here->MOS2m / + model->MOS2drainResistance; } else { here->MOS2drainConductance = 0; } } else if (model->MOS2sheetResistanceGiven) { - if(model->MOS2sheetResistance != 0) { + if((model->MOS2sheetResistance != 0) && + (here->MOS2drainSquares != 0)) { here->MOS2drainConductance = - 1/(model->MOS2sheetResistance*here->MOS2drainSquares); + here->MOS2m / + (model->MOS2sheetResistance*here->MOS2drainSquares); } else { here->MOS2drainConductance = 0; } @@ -175,14 +182,17 @@ MOS2temp(inModel,ckt) } if(model->MOS2sourceResistanceGiven) { if(model->MOS2sourceResistance != 0) { - here->MOS2sourceConductance = 1/model->MOS2sourceResistance; + here->MOS2sourceConductance = here->MOS2m / + model->MOS2sourceResistance; } else { here->MOS2sourceConductance = 0; } } else if (model->MOS2sheetResistanceGiven) { - if(model->MOS2sheetResistance != 0) { + if ((model->MOS2sheetResistance != 0) && + (here->MOS2sourceSquares != 0)) { here->MOS2sourceConductance = - 1/(model->MOS2sheetResistance*here->MOS2sourceSquares); + here->MOS2m / + (model->MOS2sheetResistance*here->MOS2sourceSquares); } else { here->MOS2sourceConductance = 0; } @@ -238,26 +248,29 @@ MOS2temp(inModel,ckt) (here->MOS2drainArea == 0) || (here->MOS2sourceArea == 0) ) { here->MOS2sourceVcrit = here->MOS2drainVcrit = - vt*log(vt/(CONSTroot2*here->MOS2tSatCur)); + vt*log(vt/(CONSTroot2*here->MOS2m*here->MOS2tSatCur)); } else { here->MOS2drainVcrit = vt * log( vt / (CONSTroot2 * + here->MOS2m * here->MOS2tSatCurDens * here->MOS2drainArea)); here->MOS2sourceVcrit = vt * log( vt / (CONSTroot2 * + here->MOS2m * here->MOS2tSatCurDens * here->MOS2sourceArea)); } if(model->MOS2capBDGiven) { - czbd = here->MOS2tCbd; + czbd = here->MOS2tCbd * here->MOS2m; } else { if(model->MOS2bulkCapFactorGiven) { - czbd=here->MOS2tCj*here->MOS2drainArea; + czbd=here->MOS2tCj*here->MOS2drainArea * here->MOS2m; } else { czbd=0; } } if(model->MOS2sideWallCapFactorGiven) { - czbdsw= here->MOS2tCjsw * here->MOS2drainPerimiter; + czbdsw= here->MOS2tCjsw * here->MOS2drainPerimiter * + here->MOS2m;; } else { czbdsw=0; } @@ -283,16 +296,17 @@ MOS2temp(inModel,ckt) (here->MOS2tDepCap*here->MOS2tDepCap) -here->MOS2tDepCap * here->MOS2f2d; if(model->MOS2capBSGiven) { - czbs=here->MOS2tCbs; + czbs=here->MOS2tCbs * here->MOS2m; } else { if(model->MOS2bulkCapFactorGiven) { - czbs=here->MOS2tCj*here->MOS2sourceArea; + czbs=here->MOS2tCj*here->MOS2sourceArea * here->MOS2m; } else { czbs=0; } } if(model->MOS2sideWallCapFactorGiven) { - czbssw = here->MOS2tCjsw * here->MOS2sourcePerimiter; + czbssw = here->MOS2tCjsw * here->MOS2sourcePerimiter * + here->MOS2m; } else { czbssw=0; } diff --git a/src/spicelib/devices/mos3/mos3.c b/src/spicelib/devices/mos3/mos3.c index 04c1566cb..faea44dfd 100644 --- a/src/spicelib/devices/mos3/mos3.c +++ b/src/spicelib/devices/mos3/mos3.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -11,6 +12,7 @@ Author: 1987 Thomas L. Quarles #include "suffix.h" IFparm MOS3pTable[] = { /* parameters */ + IOPU("m", MOS3_M, IF_REAL , "Multiplier"), IOPU("l", MOS3_L, IF_REAL , "Length"), IOPU("w", MOS3_W, IF_REAL , "Width"), IOPU("ad", MOS3_AD, IF_REAL , "Drain area"), @@ -131,6 +133,11 @@ IFparm MOS3mPTable[] = { /* model parameters */ IOPU("js", MOS3_MOD_JS, IF_REAL ,"Bulk jct. sat. current density"), IOP("tox", MOS3_MOD_TOX, IF_REAL ,"Oxide thickness"), IOP("ld", MOS3_MOD_LD, IF_REAL ,"Lateral diffusion"), + IOP("xl", MOS3_MOD_XL, IF_REAL ,"Length mask adjustment"), + IOP("wd", MOS3_MOD_WD, IF_REAL ,"Width Narrowing (Diffusion)"), + IOP("xw", MOS3_MOD_XW, IF_REAL ,"Width mask adjustment"), + IOPU("delvto", MOS3_MOD_DELVTO, IF_REAL ,"Threshold voltage Adjust"), + IOPR("delvt0", MOS3_MOD_DELVTO, IF_REAL ,"Threshold voltage Adjust"), IOP("u0", MOS3_MOD_U0, IF_REAL ,"Surface mobility"), IOPR("uo", MOS3_MOD_U0, IF_REAL ,"Surface mobility"), IOP("fc", MOS3_MOD_FC, IF_REAL ,"Forward bias jct. fit parm."), diff --git a/src/spicelib/devices/mos3/mos3acld.c b/src/spicelib/devices/mos3/mos3acld.c index b45d24878..7e439c55d 100644 --- a/src/spicelib/devices/mos3/mos3acld.c +++ b/src/spicelib/devices/mos3/mos3acld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -23,6 +24,7 @@ MOS3acLoad(inModel,ckt) int xnrm; int xrev; double EffectiveLength; + double EffectiveWidth; double xgs; double xgd; double xgb; @@ -50,13 +52,17 @@ MOS3acLoad(inModel,ckt) /* * charge oriented model parameters */ - EffectiveLength=here->MOS3l-2*model->MOS3latDiff; + EffectiveWidth=here->MOS3w-2*model->MOS3widthNarrow+ + model->MOS3widthAdjust; + EffectiveLength=here->MOS3l - 2*model->MOS3latDiff+ + model->MOS3lengthAdjust; + GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS3m * EffectiveLength; /* * meyer"s model parameters */ diff --git a/src/spicelib/devices/mos3/mos3ask.c b/src/spicelib/devices/mos3/mos3ask.c index 03f35a8b7..4da324cf7 100644 --- a/src/spicelib/devices/mos3/mos3ask.c +++ b/src/spicelib/devices/mos3/mos3ask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Mathew Lew and Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -34,10 +35,13 @@ MOS3ask(ckt,inst,which,value,select) value->rValue = here->MOS3temp-CONSTCtoK; return(OK); case MOS3_CGS: - value->rValue = *(ckt->CKTstate0 + here->MOS3capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS3capgs); return(OK); case MOS3_CGD: - value->rValue = *(ckt->CKTstate0 + here->MOS3capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS3capgd); + return(OK); + case MOS3_M: + value->rValue = here->MOS3m; return(OK); case MOS3_L: value->rValue = here->MOS3l; @@ -178,7 +182,13 @@ MOS3ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS3vds); return(OK); case MOS3_CAPGS: - value->rValue = *(ckt->CKTstate0 + here->MOS3capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS3capgs); +/* add overlap capacitance */ + value->rValue += (here->MOS3modPtr->MOS3gateSourceOverlapCapFactor) + * here->MOS3m + * (here->MOS3w + +here->MOS3modPtr->MOS3widthAdjust + -2*(here->MOS3modPtr->MOS3widthNarrow)); return(OK); case MOS3_QGS: value->rValue = *(ckt->CKTstate0 + here->MOS3qgs); @@ -187,7 +197,13 @@ MOS3ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS3cqgs); return(OK); case MOS3_CAPGD: - value->rValue = *(ckt->CKTstate0 + here->MOS3capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS3capgd); +/* add overlap capacitance */ + value->rValue += (here->MOS3modPtr->MOS3gateDrainOverlapCapFactor) + * here->MOS3m + * (here->MOS3w + +here->MOS3modPtr->MOS3widthAdjust + -2*(here->MOS3modPtr->MOS3widthNarrow)); return(OK); case MOS3_QGD: value->rValue = *(ckt->CKTstate0 + here->MOS3qgd); @@ -196,7 +212,13 @@ MOS3ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS3cqgd); return(OK); case MOS3_CAPGB: - value->rValue = *(ckt->CKTstate0 + here->MOS3capgb); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS3capgb); +/* add overlap capacitance */ + value->rValue += (here->MOS3modPtr->MOS3gateBulkOverlapCapFactor) + * here->MOS3m + * (here->MOS3l + +here->MOS3modPtr->MOS3lengthAdjust + -2*(here->MOS3modPtr->MOS3latDiff)); return(OK); case MOS3_QGB: value->rValue = *(ckt->CKTstate0 + here->MOS3qgb); diff --git a/src/spicelib/devices/mos3/mos3defs.h b/src/spicelib/devices/mos3/mos3defs.h index 70dfab657..8569eb597 100644 --- a/src/spicelib/devices/mos3/mos3defs.h +++ b/src/spicelib/devices/mos3/mos3defs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlanFixes **********/ #ifndef MOS3 @@ -30,6 +31,7 @@ typedef struct sMOS3instance { int MOS3dNodePrime; /* number of the internal drain node of the mosfet */ int MOS3sNodePrime; /* number of the internal source node of the mosfet */ + double MOS3m; /* parallel device multiplier */ double MOS3l; /* the length of the channel region */ double MOS3w; /* the width of the channel region */ double MOS3drainArea; /* the area of the drain diffusion */ @@ -89,6 +91,7 @@ typedef struct sMOS3instance { unsigned MOS3off :1;/* non-zero to indicate device is off for dc analysis*/ unsigned MOS3tempGiven :1; /* instance temperature specified */ + unsigned MOS3mGiven :1; unsigned MOS3lGiven :1; unsigned MOS3wGiven :1; unsigned MOS3drainAreaGiven :1; @@ -321,6 +324,10 @@ typedef struct sMOS3model { /* model structure for a resistor */ int MOS3type; /* device type : 1 = nmos, -1 = pmos */ double MOS3tnom; /* temperature at which parameters measured */ double MOS3latDiff; + double MOS3lengthAdjust; /* New parm: mask adjustment to length */ + double MOS3widthNarrow; /* New parm to reduce effective width */ + double MOS3widthAdjust; /* New parm: mask adjustment to width */ + double MOS3delvt0; /* New parm: adjustment calculated vtO */ double MOS3jctSatCurDensity; /* input - use tSatCurDens*/ double MOS3jctSatCur; /* input - use tSatCur instead */ double MOS3drainResistance; @@ -362,6 +369,10 @@ typedef struct sMOS3model { /* model structure for a resistor */ unsigned MOS3typeGiven :1; unsigned MOS3latDiffGiven :1; + unsigned MOS3lengthAdjustGiven :1; + unsigned MOS3widthNarrowGiven :1; + unsigned MOS3widthAdjustGiven :1; + unsigned MOS3delvt0Given :1; unsigned MOS3jctSatCurDensityGiven :1; unsigned MOS3jctSatCurGiven :1; unsigned MOS3drainResistanceGiven :1; @@ -485,6 +496,7 @@ typedef struct sMOS3model { /* model structure for a resistor */ #define MOS3_TEMP 77 #define MOS3_SOURCERESIST 78 #define MOS3_DRAINRESIST 79 +#define MOS3_M 80 /* model parameters */ #define MOS3_MOD_VTO 101 @@ -532,6 +544,11 @@ typedef struct sMOS3model { /* model structure for a resistor */ #define MOS3_MOD_AF 143 #define MOS3_MOD_TYPE 144 +#define MOS3_MOD_XL 145 +#define MOS3_MOD_WD 146 +#define MOS3_MOD_XW 147 +#define MOS3_MOD_DELVTO 148 + /* device questions */ diff --git a/src/spicelib/devices/mos3/mos3dset.c b/src/spicelib/devices/mos3/mos3dset.c index 985d5d1be..fe05c5f01 100644 --- a/src/spicelib/devices/mos3/mos3dset.c +++ b/src/spicelib/devices/mos3/mos3dset.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -27,6 +28,7 @@ MOS3dSetup(inModel,ckt) double Beta; double DrainSatCur; double EffectiveLength; + double EffectiveWidth; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; @@ -76,29 +78,32 @@ MOS3dSetup(inModel,ckt) * here. They may be moved at the expense of instance size */ - EffectiveLength=here->MOS3l - 2*model->MOS3latDiff; + EffectiveWidth=here->MOS3w-2*model->MOS3widthNarrow+ + model->MOS3widthAdjust; + EffectiveLength=here->MOS3l - 2*model->MOS3latDiff+ + model->MOS3lengthAdjust; + if( (here->MOS3tSatCurDens == 0) || (here->MOS3drainArea == 0) || (here->MOS3sourceArea == 0)) { - DrainSatCur = here->MOS3tSatCur; - SourceSatCur = here->MOS3tSatCur; + DrainSatCur = here->MOS3m * here->MOS3tSatCur; + SourceSatCur = here->MOS3m * here->MOS3tSatCur; } else { DrainSatCur = here->MOS3tSatCurDens * - here->MOS3drainArea; + here->MOS3m * here->MOS3drainArea; SourceSatCur = here->MOS3tSatCurDens * - here->MOS3sourceArea; + here->MOS3m * here->MOS3sourceArea; } GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS3tTransconductance * here->MOS3w/EffectiveLength; + here->MOS3m * EffectiveLength; + Beta = here->MOS3tTransconductance * here->MOS3m * + EffectiveWidth/EffectiveLength; OxideCap = model->MOS3oxideCapFactor * EffectiveLength * - here->MOS3w; - - + here->MOS3m * EffectiveWidth; /* * ok - now to do the start-up operations @@ -381,7 +386,7 @@ d_p.d3_pqr = 0.0; fbodys = 0.5*gammas/(sqphbs+sqphbs); DivDeriv(&d_fbodys,&d_gammas,&d_sqphbs); TimesDeriv(&d_fbodys,&d_fbodys,0.25); - fbody = fbodys+model->MOS3narrowFactor/here->MOS3w; + fbody = fbodys+model->MOS3narrowFactor/EffectiveWidth; EqualDeriv(&d_fbody,&d_fbodys); d_fbody.value += fbody - fbodys; @@ -389,9 +394,10 @@ d_p.d3_pqr = 0.0; EqualDeriv(&d_onfbdy,&d_fbody); d_onfbdy.value += 1.0; InvDeriv(&d_onfbdy,&d_onfbdy); - qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/here->MOS3w; + qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/EffectiveWidth; EqualDeriv(&d_dummy,&d_phibs); - TimesDeriv(&d_dummy,&d_dummy,model->MOS3narrowFactor*here->MOS3w); + TimesDeriv(&d_dummy,&d_dummy,model-> + MOS3narrowFactor*EffectiveWidth); MultDeriv(&d_qbonco,&d_gammas,&d_sqphbs); PlusDeriv(&d_qbonco,&d_qbonco,&d_dummy); /* @@ -412,7 +418,8 @@ d_p.d3_pqr = 0.0; EqualDeriv(&d_von,&d_vth); if ( model->MOS3fastSurfaceStateDensity != 0.0 ) { csonco = CHARGE*model->MOS3fastSurfaceStateDensity * - 1e4 /*(cm**2/m**2)*/ *EffectiveLength*here->MOS3w/OxideCap;/*const*/ + 1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * + here->MOS3m/OxideCap; /*const*/ cdonco = 0.5*qbonco/phibs; DivDeriv(&d_cdonco,&d_qbonco,&d_phibs); TimesDeriv(&d_cdonco,&d_cdonco,0.5); diff --git a/src/spicelib/devices/mos3/mos3ext.h b/src/spicelib/devices/mos3/mos3ext.h index 06aa589a4..4807683a0 100644 --- a/src/spicelib/devices/mos3/mos3ext.h +++ b/src/spicelib/devices/mos3/mos3ext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -27,6 +28,7 @@ extern int MOS3temp(GENmodel*,CKTcircuit*); extern int MOS3trunc(GENmodel*,CKTcircuit*,double*); extern int MOS3disto(int,GENmodel*,CKTcircuit*); extern int MOS3noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int MOS3dSetup(GENmodel*,CKTcircuit*); #else /* stdc */ extern int MOS3acLoad(); extern int MOS3ask(); diff --git a/src/spicelib/devices/mos3/mos3load.c b/src/spicelib/devices/mos3/mos3load.c index 250fd154f..71474b55d 100644 --- a/src/spicelib/devices/mos3/mos3load.c +++ b/src/spicelib/devices/mos3/mos3load.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -26,6 +27,7 @@ MOS3load(inModel,ckt) double Beta; double DrainSatCur; double EffectiveLength; + double EffectiveWidth; double GateBulkOverlapCap; double GateDrainOverlapCap; double GateSourceOverlapCap; @@ -117,28 +119,33 @@ next: * here. They may be moved at the expense of instance size */ - EffectiveLength=here->MOS3l - 2*model->MOS3latDiff; - if( (here->MOS3tSatCurDens == 0) || + EffectiveWidth=here->MOS3w-2*model->MOS3widthNarrow+ + model->MOS3widthAdjust; + EffectiveLength=here->MOS3l - 2*model->MOS3latDiff+ + model->MOS3lengthAdjust; + + if( (here->MOS3tSatCurDens == 0) || (here->MOS3drainArea == 0) || (here->MOS3sourceArea == 0)) { - DrainSatCur = here->MOS3tSatCur; - SourceSatCur = here->MOS3tSatCur; + DrainSatCur = here->MOS3m * here->MOS3tSatCur; + SourceSatCur = here->MOS3m * here->MOS3tSatCur; } else { - DrainSatCur = here->MOS3tSatCurDens * + DrainSatCur = here->MOS3m * here->MOS3tSatCurDens * here->MOS3drainArea; - SourceSatCur = here->MOS3tSatCurDens * + SourceSatCur = here->MOS3m * here->MOS3tSatCurDens * here->MOS3sourceArea; } GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * - EffectiveLength; - Beta = here->MOS3tTransconductance * here->MOS3w/EffectiveLength; + here->MOS3m * EffectiveLength; + Beta = here->MOS3tTransconductance * + here->MOS3m * EffectiveWidth/EffectiveLength; OxideCap = model->MOS3oxideCapFactor * EffectiveLength * - here->MOS3w; - + here->MOS3m * EffectiveWidth; + if(SenCond){ #ifdef SENSDEBUG printf("MOS3senPertFlag = ON \n"); @@ -395,23 +402,26 @@ next: * here we just evaluate the ideal diode current and the * corresponding derivative (conductance). */ -next1: if(vbs <= 0) { - here->MOS3gbs = SourceSatCur/vt; - here->MOS3cbs = here->MOS3gbs*vbs; - here->MOS3gbs += ckt->CKTgmin; + +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); + here->MOS3cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; } - if(vbd <= 0) { - here->MOS3gbd = DrainSatCur/vt; - here->MOS3cbd = here->MOS3gbd *vbd; - here->MOS3gbd += ckt->CKTgmin; + if(vbd <= -3*vt) { + arg=3*vt/(vbd*CONSTe); + arg = arg * arg * arg; + here->MOS3cbd = -DrainSatCur*(1+arg)+ckt->CKTgmin*vbd; + here->MOS3gbd = DrainSatCur*3*arg/vbd+ckt->CKTgmin; } else { evbd = exp(MIN(MAX_EXP_ARG,vbd/vt)); - here->MOS3gbd = DrainSatCur*evbd/vt +ckt->CKTgmin; - here->MOS3cbd = DrainSatCur *(evbd-1); + here->MOS3gbd = DrainSatCur*evbd/vt + ckt->CKTgmin; + here->MOS3cbd = DrainSatCur*(evbd-1) + ckt->CKTgmin*vbd; } /* now to determine whether the user was able to correctly @@ -600,12 +610,12 @@ next1: if(vbs <= 0) { */ gammas = model->MOS3gamma*fshort; fbodys = 0.5*gammas/(sqphbs+sqphbs); - fbody = fbodys+model->MOS3narrowFactor/here->MOS3w; + fbody = fbodys+model->MOS3narrowFactor/EffectiveWidth; onfbdy = 1.0/(1.0+fbody); dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort; - qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/here->MOS3w; + qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/EffectiveWidth; dqbdvb = gammas*dsqdvb+model->MOS3gamma*dfsdvb*sqphbs- - model->MOS3narrowFactor/here->MOS3w; + model->MOS3narrowFactor/EffectiveWidth; /* *.....static feedback effect */ @@ -622,7 +632,8 @@ next1: if(vbs <= 0) { von = vth; if ( model->MOS3fastSurfaceStateDensity != 0.0 ) { csonco = CHARGE*model->MOS3fastSurfaceStateDensity * - 1e4 /*(cm**2/m**2)*/ *EffectiveLength*here->MOS3w/OxideCap; + 1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * + here->MOS3m/OxideCap; cdonco = qbonco/(phibs+phibs); xn = 1.0+csonco+cdonco; von = vth+vt*xn; @@ -685,7 +696,8 @@ next1: if(vbs <= 0) { */ cdnorm = cdo*vdsx; here->MOS3gm = vdsx; - here->MOS3gds = vgsx-vth-(1.0+fbody+dvtdvd)*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 @@ -695,16 +707,17 @@ next1: if(vbs <= 0) { cdrain = Beta*cdnorm; here->MOS3gm = Beta*here->MOS3gm+dfgdvg*cd1; here->MOS3gds = Beta*here->MOS3gds+dfgdvd*cd1; - here->MOS3gmbs = Beta*here->MOS3gmbs; + here->MOS3gmbs = Beta*here->MOS3gmbs+dfgdvb*cd1; /* *.....velocity saturation factor */ - if ( model->MOS3maxDriftVel != 0.0 ) { + if ( model->MOS3maxDriftVel > 0.0 ) { fdrain = 1.0/(1.0+vdsx*onvdsc); fd2 = fdrain*fdrain; arga = fd2*vdsx*onvdsc*onfg; dfddvg = -dfgdvg*arga; - dfddvd = -dfgdvd*arga-fd2*onvdsc; + if ((here->MOS3mode*vds) > vdsat) dfddvd = -dfgdvd*arga; + else dfddvd = -dfgdvd*arga-fd2*onvdsc; dfddvb = -dfgdvb*arga; /* *.....drain current @@ -718,7 +731,24 @@ next1: if(vbs <= 0) { /* *.....channel length modulation */ - if ( (here->MOS3mode*vds) <= vdsat ) goto line700; + + 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; @@ -757,9 +787,15 @@ next1: if(vbs <= 0) { ddldvb = dldem*demdvb; goto line520; line510: - delxl = sqrt(model->MOS3kappa*((here->MOS3mode*vds)-vdsat)* - model->MOS3alpha); - dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat); + 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; @@ -782,14 +818,19 @@ line520: */ 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; - gds0 = here->MOS3gds*xlfact+diddl*ddldvd; here->MOS3gmbs = here->MOS3gmbs*xlfact+diddl*ddldvb; + gds0 = diddl*ddldvd; here->MOS3gm = here->MOS3gm+gds0*dvsdvg; here->MOS3gmbs = here->MOS3gmbs+gds0*dvsdvb; - here->MOS3gds = gds0*dvsdvd+diddl*dldvd; + 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 */ @@ -1162,9 +1203,9 @@ bypass: * load current vector */ ceqbs = model->MOS3type * - (here->MOS3cbs-(here->MOS3gbs-ckt->CKTgmin)*vbs); + (here->MOS3cbs-(here->MOS3gbs)*vbs); ceqbd = model->MOS3type * - (here->MOS3cbd-(here->MOS3gbd-ckt->CKTgmin)*vbd); + (here->MOS3cbd-(here->MOS3gbd)*vbd); if (here->MOS3mode >= 0) { xnrm=1; xrev=0; diff --git a/src/spicelib/devices/mos3/mos3mask.c b/src/spicelib/devices/mos3/mos3mask.c index f316110a1..ec9584929 100644 --- a/src/spicelib/devices/mos3/mos3mask.c +++ b/src/spicelib/devices/mos3/mos3mask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -89,6 +90,18 @@ MOS3mAsk(ckt,inst,which,value) case MOS3_MOD_LD: value->rValue = here->MOS3latDiff; return(OK); + case MOS3_MOD_XL: + value->rValue = here->MOS3lengthAdjust; + return(OK); + case MOS3_MOD_WD: + value->rValue = here->MOS3widthNarrow; + return(OK); + case MOS3_MOD_XW: + value->rValue = here->MOS3widthAdjust; + return(OK); + case MOS3_MOD_DELVTO: + value->rValue = here->MOS3delvt0; + return(OK); case MOS3_MOD_RSH: value->rValue = here->MOS3sheetResistance; return(OK); @@ -136,7 +149,13 @@ MOS3mAsk(ckt,inst,which,value) return(OK); case MOS3_MOD_KAPPA: value->rValue = here->MOS3kappa; + return(OK); + case MOS3_MOD_KF: + value->rValue = here->MOS3fNcoef; return(OK); + case MOS3_MOD_AF: + value->rValue = here->MOS3fNexp; + return(OK); case MOS3_MOD_TYPE: if (here->MOS3type > 0) value->sValue = "nmos"; diff --git a/src/spicelib/devices/mos3/mos3mpar.c b/src/spicelib/devices/mos3/mos3mpar.c index 271985637..8176d1108 100644 --- a/src/spicelib/devices/mos3/mos3mpar.c +++ b/src/spicelib/devices/mos3/mos3mpar.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -106,6 +107,22 @@ MOS3mParam(param,value,inModel) model->MOS3latDiff = value->rValue; model->MOS3latDiffGiven = TRUE; break; + case MOS3_MOD_XL: + model->MOS3lengthAdjust = value->rValue; + model->MOS3lengthAdjustGiven = TRUE; + break; + case MOS3_MOD_WD: + model->MOS3widthNarrow = value->rValue; + model->MOS3widthNarrowGiven = TRUE; + break; + case MOS3_MOD_XW: + model->MOS3widthAdjust = value->rValue; + model->MOS3widthAdjustGiven = TRUE; + break; + case MOS3_MOD_DELVTO: + model->MOS3delvt0 = value->rValue; + model->MOS3delvt0Given = TRUE; + break; case MOS3_MOD_U0: model->MOS3surfaceMobility = value->rValue; model->MOS3surfaceMobilityGiven = TRUE; diff --git a/src/spicelib/devices/mos3/mos3noi.c b/src/spicelib/devices/mos3/mos3noi.c index 3b9546658..e8704efa8 100644 --- a/src/spicelib/devices/mos3/mos3noi.c +++ b/src/spicelib/devices/mos3/mos3noi.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Gary W. Ng +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -135,7 +136,8 @@ if (!data->namelist) return(E_NOMEM); noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef * exp(model->MOS3fNexp * log(MAX(fabs(inst->MOS3cd),N_MINLOG))) / - (data->freq * inst->MOS3w * + (data->freq * + (inst->MOS3w - 2*model->MOS3widthNarrow) * (inst->MOS3l - 2*model->MOS3latDiff) * model->MOS3oxideCapFactor * model->MOS3oxideCapFactor); lnNdens[MOS3FLNOIZ] = diff --git a/src/spicelib/devices/mos3/mos3par.c b/src/spicelib/devices/mos3/mos3par.c index 7723975f4..b2f2ddf76 100644 --- a/src/spicelib/devices/mos3/mos3par.c +++ b/src/spicelib/devices/mos3/mos3par.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -24,6 +25,11 @@ MOS3param(param,value,inst,select) { MOS3instance *here = (MOS3instance *)inst; switch(param) { + + case MOS3_M: + here->MOS3m = value->rValue; + here->MOS3mGiven = TRUE; + break; case MOS3_W: here->MOS3w = value->rValue; here->MOS3wGiven = TRUE; diff --git a/src/spicelib/devices/mos3/mos3pzld.c b/src/spicelib/devices/mos3/mos3pzld.c index 2710a3458..7a1f886f6 100644 --- a/src/spicelib/devices/mos3/mos3pzld.c +++ b/src/spicelib/devices/mos3/mos3pzld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -36,6 +37,7 @@ MOS3pzLoad(inModel,ckt,s) double GateDrainOverlapCap; double GateSourceOverlapCap; double EffectiveLength; + double EffectiveWidth; for( ; model != NULL; model = model->MOS3nextModel) { for(here = model->MOS3instances; here!= NULL; @@ -52,13 +54,16 @@ MOS3pzLoad(inModel,ckt,s) /* * meyer's model parameters */ - EffectiveLength=here->MOS3l - 2*model->MOS3latDiff; + EffectiveWidth=here->MOS3w-2*model->MOS3widthNarrow+ + model->MOS3widthAdjust; + EffectiveLength=here->MOS3l - 2*model->MOS3latDiff+ + model->MOS3lengthAdjust; GateSourceOverlapCap = model->MOS3gateSourceOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateDrainOverlapCap = model->MOS3gateDrainOverlapCapFactor * - here->MOS3w; + here->MOS3m * EffectiveWidth; GateBulkOverlapCap = model->MOS3gateBulkOverlapCapFactor * - EffectiveLength; + here->MOS3m * EffectiveLength; capgs = ( 2* *(ckt->CKTstate0+here->MOS3capgs)+ GateSourceOverlapCap ); capgd = ( 2* *(ckt->CKTstate0+here->MOS3capgd)+ diff --git a/src/spicelib/devices/mos3/mos3set.c b/src/spicelib/devices/mos3/mos3set.c index 271e4ca38..e2b5f9ed7 100644 --- a/src/spicelib/devices/mos3/mos3set.c +++ b/src/spicelib/devices/mos3/mos3set.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1985 Thomas L. Quarles +Author: 1985 Thomas L. Quarlesł +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -41,6 +42,18 @@ MOS3setup(matrix,inModel,ckt,states) if(!model->MOS3latDiffGiven) { model->MOS3latDiff = 0; } + if(!model->MOS3lengthAdjustGiven) { + model->MOS3lengthAdjust = 0; + } + if(!model->MOS3widthNarrowGiven) { + model->MOS3widthNarrow = 0; + } + if(!model->MOS3widthAdjustGiven) { + model->MOS3widthAdjust = 0; + } + if(!model->MOS3delvt0Given) { + model->MOS3delvt0 = 0; + } if(!model->MOS3jctSatCurDensityGiven) { model->MOS3jctSatCurDensity = 0; } @@ -136,6 +149,9 @@ MOS3setup(matrix,inModel,ckt,states) for (here = model->MOS3instances; here != NULL ; here=here->MOS3nextInstance) { + CKTnode *tmpNode; + IFuid tmpName; + if (here->MOS3owner == ARCHme) { /* allocate a chunk of the state vector */ here->MOS3states = *states; @@ -183,6 +199,14 @@ MOS3setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#drain"); if(error) return(error); here->MOS3dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->MOS3dNodePrime = here->MOS3dNode; } @@ -194,6 +218,14 @@ MOS3setup(matrix,inModel,ckt,states) error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#source"); if(error) return(error); here->MOS3sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->MOS3sNodePrime = here->MOS3sNode; } diff --git a/src/spicelib/devices/mos3/mos3sld.c b/src/spicelib/devices/mos3/mos3sld.c index c6bbf1cf4..26edd8198 100644 --- a/src/spicelib/devices/mos3/mos3sld.c +++ b/src/spicelib/devices/mos3/mos3sld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* actually load the current sensitivity @@ -76,6 +77,7 @@ CKTcircuit *ckt; double sargsw; int offset; double EffectiveLength; + double EffectiveWidth; SENstruct *info; #ifdef SENSDEBUG @@ -315,8 +317,8 @@ CKTcircuit *ckt; DcsprmDp = ( - DcbsDp - DcdDp - DcbdDp - DcsprDp); if(flag == 0){ - EffectiveLength = here->MOS3l - - 2*model->MOS3latDiff; + EffectiveLength = here->MOS3l + - 2*model->MOS3latDiff + model->MOS3lengthAdjust; if(EffectiveLength == 0){ DqgsDp = 0; DqgdDp = 0; @@ -329,9 +331,11 @@ CKTcircuit *ckt; } } else{ - DqgsDp = model->MOS3type * qgs0 / here->MOS3w; - DqgdDp = model->MOS3type * qgd0 / here->MOS3w; - DqgbDp = model->MOS3type * qgb0 / here->MOS3w; + EffectiveWidth = here->MOS3w + - 2*model->MOS3widthNarrow + model->MOS3widthAdjust; + DqgsDp = model->MOS3type * qgs0 / EffectiveWidth; + DqgdDp = model->MOS3type * qgd0 / EffectiveWidth; + DqgbDp = model->MOS3type * qgb0 / EffectiveWidth; } diff --git a/src/spicelib/devices/mos3/mos3sprt.c b/src/spicelib/devices/mos3/mos3sprt.c index 09e916635..20e133666 100644 --- a/src/spicelib/devices/mos3/mos3sprt.c +++ b/src/spicelib/devices/mos3/mos3sprt.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* Pretty print the sensitivity info for all the MOS3 @@ -23,7 +24,7 @@ MOS3sPrint(inModel,ckt) MOS3model *model = (MOS3model *)inModel; MOS3instance *here; - printf("LEVEL 1 MOSFETS-----------------\n"); + printf("LEVEL 3 MOSFETS-----------------\n"); /* loop through all the MOS3 models */ for( ; model != NULL; model = model->MOS3nextModel ) { @@ -39,6 +40,8 @@ MOS3sPrint(inModel,ckt) CKTnodName(ckt,here->MOS3dNode),CKTnodName(ckt,here->MOS3gNode), CKTnodName(ckt,here->MOS3sNode)); + printf(" Multiplier: %g ",here->MOS3m); + printf(here->MOS3mGiven ? "(specified)\n" : "(default)\n"); printf(" Length: %g ",here->MOS3l); printf(here->MOS3lGiven ? "(specified)\n" : "(default)\n"); printf(" Width: %g ",here->MOS3w); diff --git a/src/spicelib/devices/mos3/mos3temp.c b/src/spicelib/devices/mos3/mos3temp.c index 5dd598cf1..6ceec8b4e 100644 --- a/src/spicelib/devices/mos3/mos3temp.c +++ b/src/spicelib/devices/mos3/mos3temp.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -36,6 +37,7 @@ MOS3temp(inModel,ckt) double arg1; double capfact; double gmanew,gmaold; + double ni_temp, nifact; /* loop through all the mosfet models */ for( ; model != NULL; model = model->MOS3nextModel) { @@ -49,7 +51,10 @@ MOS3temp(inModel,ckt) (model->MOS3tnom+1108); arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); - + nifact=(model->MOS3tnom/300)*sqrt(model->MOS3tnom/300); + nifact*=exp(0.5*egfet1*((1/(double)300)-(1/model->MOS3tnom))/ + CONSTKoverQ); + ni_temp=1.45e16*nifact; model->MOS3oxideCapFactor = 3.9 * 8.854214871e-12/ model->MOS3oxideThickness; @@ -59,11 +64,11 @@ MOS3temp(inModel,ckt) model->MOS3oxideCapFactor * 1e-4; } if(model->MOS3substrateDopingGiven) { - if(model->MOS3substrateDoping*1e6 /*(cm**3/m**3)*/ >1.45e16) { + if(model->MOS3substrateDoping*1e6 /*(cm**3/m**3)*/ >ni_temp) { if(!model->MOS3phiGiven) { model->MOS3phi = 2*vtnom* log(model->MOS3substrateDoping* - 1e6/*(cm**3/m**3)*//1.45e16); + 1e6/*(cm**3/m**3)*//ni_temp); model->MOS3phi = MAX(.1,model->MOS3phi); } fermis = model->MOS3type * .5 * model->MOS3phi; @@ -134,7 +139,9 @@ MOS3temp(inModel,ckt) arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg); - + if(!here->MOS3mGiven) { + here->MOS3m = ckt->CKTdefaultMosM; + } if(!here->MOS3lGiven) { here->MOS3l = ckt->CKTdefaultMosL; } @@ -146,14 +153,17 @@ MOS3temp(inModel,ckt) } if(model->MOS3drainResistanceGiven) { if(model->MOS3drainResistance != 0) { - here->MOS3drainConductance = 1/model->MOS3drainResistance; + here->MOS3drainConductance = here->MOS3m / + model->MOS3drainResistance; } else { here->MOS3drainConductance = 0; } } else if (model->MOS3sheetResistanceGiven) { - if(model->MOS3sheetResistance != 0) { + if ((model->MOS3sheetResistance != 0) && + (here->MOS3drainSquares != 0)) { here->MOS3drainConductance = - 1/(model->MOS3sheetResistance*here->MOS3drainSquares); + here->MOS3m / + (model->MOS3sheetResistance*here->MOS3drainSquares); } else { here->MOS3drainConductance = 0; } @@ -162,14 +172,17 @@ MOS3temp(inModel,ckt) } if(model->MOS3sourceResistanceGiven) { if(model->MOS3sourceResistance != 0) { - here->MOS3sourceConductance = 1/model->MOS3sourceResistance; + here->MOS3sourceConductance = here->MOS3m / + model->MOS3sourceResistance; } else { here->MOS3sourceConductance = 0; } } else if (model->MOS3sheetResistanceGiven) { - if(model->MOS3sheetResistance != 0) { + if ((model->MOS3sheetResistance != 0) && + (here->MOS3sourceSquares != 0)) { here->MOS3sourceConductance = - 1/(model->MOS3sheetResistance*here->MOS3sourceSquares); + here->MOS3m / + (model->MOS3sheetResistance*here->MOS3sourceSquares); } else { here->MOS3sourceConductance = 0; } @@ -177,11 +190,20 @@ MOS3temp(inModel,ckt) here->MOS3sourceConductance = 0; } - if(here->MOS3l - 2 * model->MOS3latDiff <=0) { + if(here->MOS3l - 2 * model->MOS3latDiff + + model->MOS3lengthAdjust <1e-6) { (*(SPfrontEnd->IFerror))(ERR_FATAL, "%s: effective channel length less than zero", &(here->MOS3name)); - return(E_BADPARM); + return(E_PARMVAL); + } + + if(here->MOS3w - 2 * model->MOS3widthNarrow + + model->MOS3widthAdjust <1e-6) { + (*(SPfrontEnd->IFerror))(ERR_FATAL, + "%s: effective channel width less than zero", + &(here->MOS3name)); + return(E_PARMVAL); } ratio4 = ratio * sqrt(ratio); @@ -189,7 +211,8 @@ MOS3temp(inModel,ckt) here->MOS3tSurfMob = model->MOS3surfaceMobility/ratio4; phio= (model->MOS3phi-pbfact1)/fact1; here->MOS3tPhi = fact2 * phio + pbfact; - here->MOS3tVbi = + here->MOS3tVbi = + model->MOS3delvt0 + model->MOS3vt0 - model->MOS3type * (model->MOS3gamma* sqrt(model->MOS3phi)) +.5*(egfet1-egfet) @@ -226,26 +249,29 @@ MOS3temp(inModel,ckt) (here->MOS3drainArea == 0) || (here->MOS3sourceArea == 0) ) { here->MOS3sourceVcrit = here->MOS3drainVcrit = - vt*log(vt/(CONSTroot2*model->MOS3jctSatCur)); + vt*log(vt/(CONSTroot2*here->MOS3m*here->MOS3tSatCur)); } else { here->MOS3drainVcrit = vt * log( vt / (CONSTroot2 * - model->MOS3jctSatCurDensity * here->MOS3drainArea)); + here->MOS3m * + here->MOS3tSatCurDens * here->MOS3drainArea)); here->MOS3sourceVcrit = vt * log( vt / (CONSTroot2 * - model->MOS3jctSatCurDensity * here->MOS3sourceArea)); + here->MOS3m * + here->MOS3tSatCurDens * here->MOS3sourceArea)); } if(model->MOS3capBDGiven) { - czbd = here->MOS3tCbd; + czbd = here->MOS3tCbd * here->MOS3m; } else { if(model->MOS3bulkCapFactorGiven) { - czbd=here->MOS3tCj*here->MOS3drainArea; + czbd=here->MOS3tCj*here->MOS3drainArea * here->MOS3m; } else { czbd=0; } } if(model->MOS3sideWallCapFactorGiven) { - czbdsw= here->MOS3tCjsw * here->MOS3drainPerimiter; + czbdsw= here->MOS3tCjsw * here->MOS3drainPerimiter * + here->MOS3m; } else { czbdsw=0; } @@ -260,27 +286,28 @@ MOS3temp(inModel,ckt) (1+model->MOS3bulkJctSideGradingCoeff))* sargsw/arg; here->MOS3f3d = czbd * model->MOS3bulkJctBotGradingCoeff * sarg/arg/ - model->MOS3bulkJctPotential + here->MOS3tBulkPot + czbdsw * model->MOS3bulkJctSideGradingCoeff * sargsw/arg / - model->MOS3bulkJctPotential; - here->MOS3f4d = czbd*model->MOS3bulkJctPotential*(1-arg*sarg)/ + here->MOS3tBulkPot; + here->MOS3f4d = czbd*here->MOS3tBulkPot*(1-arg*sarg)/ (1-model->MOS3bulkJctBotGradingCoeff) - + czbdsw*model->MOS3bulkJctPotential*(1-arg*sargsw)/ + + czbdsw*here->MOS3tBulkPot*(1-arg*sargsw)/ (1-model->MOS3bulkJctSideGradingCoeff) -here->MOS3f3d/2* (here->MOS3tDepCap*here->MOS3tDepCap) -here->MOS3tDepCap * here->MOS3f2d; if(model->MOS3capBSGiven) { - czbs=here->MOS3tCbs; + czbs = here->MOS3tCbs * here->MOS3m; } else { if(model->MOS3bulkCapFactorGiven) { - czbs=here->MOS3tCj*here->MOS3sourceArea; + czbs=here->MOS3tCj*here->MOS3sourceArea * here->MOS3m; } else { czbs=0; } } if(model->MOS3sideWallCapFactorGiven) { - czbssw = here->MOS3tCjsw * here->MOS3sourcePerimiter; + czbssw = here->MOS3tCjsw * here->MOS3sourcePerimiter * + here->MOS3m; } else { czbssw=0; } @@ -295,16 +322,16 @@ MOS3temp(inModel,ckt) (1+model->MOS3bulkJctSideGradingCoeff))* sargsw/arg; here->MOS3f3s = czbs * model->MOS3bulkJctBotGradingCoeff * sarg/arg/ - model->MOS3bulkJctPotential + here->MOS3tBulkPot + czbssw * model->MOS3bulkJctSideGradingCoeff * sargsw/arg / - model->MOS3bulkJctPotential; - here->MOS3f4s = czbs*model->MOS3bulkJctPotential*(1-arg*sarg)/ + here->MOS3tBulkPot; + here->MOS3f4s = czbs*here->MOS3tBulkPot*(1-arg*sarg)/ (1-model->MOS3bulkJctBotGradingCoeff) - + czbssw*model->MOS3bulkJctPotential*(1-arg*sargsw)/ + + czbssw*here->MOS3tBulkPot*(1-arg*sargsw)/ (1-model->MOS3bulkJctSideGradingCoeff) -here->MOS3f3s/2* - (here->MOS3tBulkPot*here->MOS3tBulkPot) - -here->MOS3tBulkPot * here->MOS3f2s; + (here->MOS3tDepCap*here->MOS3tDepCap) + -here->MOS3tDepCap * here->MOS3f2s; } } return(OK); diff --git a/src/spicelib/devices/mos6/mos6ask.c b/src/spicelib/devices/mos6/mos6ask.c index e9d465c18..272145034 100644 --- a/src/spicelib/devices/mos6/mos6ask.c +++ b/src/spicelib/devices/mos6/mos6ask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1989 Takayasu Sakurai +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -34,10 +35,10 @@ MOS6ask(ckt,inst,which,value,select) value->rValue = here->MOS6temp-CONSTCtoK; return(OK); case MOS6_CGS: - value->rValue = *(ckt->CKTstate0 + here->MOS6capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS6capgs); return(OK); case MOS6_CGD: - value->rValue = *(ckt->CKTstate0 + here->MOS6capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS6capgd); return(OK); case MOS6_L: value->rValue = here->MOS6l; @@ -178,7 +179,10 @@ MOS6ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS6vds); return(OK); case MOS6_CAPGS: - value->rValue = *(ckt->CKTstate0 + here->MOS6capgs); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS6capgs); + /* add overlap capacitance */ + value->rValue += (here->sMOS6modPtr->MOS6gateSourceOverlapCapFactor) + * (here->MOS6w); return(OK); case MOS6_QGS: value->rValue = *(ckt->CKTstate0 + here->MOS6qgs); @@ -187,7 +191,10 @@ MOS6ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS6cqgs); return(OK); case MOS6_CAPGD: - value->rValue = *(ckt->CKTstate0 + here->MOS6capgd); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS6capgd); + /* add overlap capacitance */ + value->rValue += (here->sMOS6modPtr->MOS6gateSourceOverlapCapFactor) + * (here->MOS6w); return(OK); case MOS6_QGD: value->rValue = *(ckt->CKTstate0 + here->MOS6qgd); @@ -196,7 +203,11 @@ MOS6ask(ckt,inst,which,value,select) value->rValue = *(ckt->CKTstate0 + here->MOS6cqgd); return(OK); case MOS6_CAPGB: - value->rValue = *(ckt->CKTstate0 + here->MOS6capgb); + value->rValue = 2* *(ckt->CKTstate0 + here->MOS6capgb); + /* add overlap capacitance */ + value->rValue += (here->sMOS6modPtr->MOS6gateBulkOverlapCapFactor) + * (here->MOS6l + -2*(here->sMOS6modPtr->MOS6latDiff)); return(OK); case MOS6_QGB: value->rValue = *(ckt->CKTstate0 + here->MOS6qgb); diff --git a/src/spicelib/devices/mos6/mos6load.c b/src/spicelib/devices/mos6/mos6load.c index c3f4dc477..597740882 100644 --- a/src/spicelib/devices/mos6/mos6load.c +++ b/src/spicelib/devices/mos6/mos6load.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1989 Takayasu Sakurai +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -407,23 +408,21 @@ MOS6load(inModel,ckt) * here we just evaluate the ideal diode current and the * corresponding derivative (conductance). */ -next1: if(vbs <= 0) { - here->MOS6gbs = SourceSatCur/vt; - here->MOS6cbs = here->MOS6gbs*vbs; - here->MOS6gbs += ckt->CKTgmin; +next1: if(vbs <= -3*vt) { + here->MOS6gbs = ckt->CKTgmin; + here->MOS6cbs = here->MOS6gbs*vbs-SourceSatCur; } else { evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); here->MOS6gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; - here->MOS6cbs = SourceSatCur * (evbs-1); + here->MOS6cbs = SourceSatCur*(evbs-1) + ckt->CKTgmin*vbs; } - if(vbd <= 0) { - here->MOS6gbd = DrainSatCur/vt; - here->MOS6cbd = here->MOS6gbd *vbd; - here->MOS6gbd += ckt->CKTgmin; + if(vbd <= -3*vt) { + here->MOS6gbd = ckt->CKTgmin; + here->MOS6cbd = here->MOS6gbd*vbd-DrainSatCur; } else { evbd = exp(MIN(MAX_EXP_ARG,vbd/vt)); - here->MOS6gbd = DrainSatCur*evbd/vt +ckt->CKTgmin; - here->MOS6cbd = DrainSatCur *(evbd-1); + here->MOS6gbd = DrainSatCur*evbd/vt + ckt->CKTgmin; + here->MOS6cbd = DrainSatCur*(evbd-1) + ckt->CKTgmin*vbd; } /* now to determine whether the user was able to correctly @@ -469,10 +468,8 @@ next1: if(vbs <= 0) { } vdshere = vds * here->MOS6mode; von=(here->MOS6tVbi*model->MOS6type)+model->MOS6gamma*sarg - - model->MOS6gamma1 * vbsvbd; -#if 0 + - model->MOS6gamma1 * vbsvbd - model->MOS6sigma * vdshere; -#endif vgon = (here->MOS6mode==1?vgs:vgd) - von; if (vgon <= 0) { @@ -881,9 +878,9 @@ bypass: * load current vector */ ceqbs = model->MOS6type * - (here->MOS6cbs-(here->MOS6gbs-ckt->CKTgmin)*vbs); + (here->MOS6cbs-(here->MOS6gbs)*vbs); ceqbd = model->MOS6type * - (here->MOS6cbd-(here->MOS6gbd-ckt->CKTgmin)*vbd); + (here->MOS6cbd-(here->MOS6gbd)*vbd); if (here->MOS6mode >= 0) { xnrm=1; xrev=0; diff --git a/src/spicelib/devices/mos6/mos6set.c b/src/spicelib/devices/mos6/mos6set.c index e0a199a95..1bc793dc3 100644 --- a/src/spicelib/devices/mos6/mos6set.c +++ b/src/spicelib/devices/mos6/mos6set.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1989 Takayasu Sakurai +Modified: 2000 AlansFixes **********/ /* load the MOS6 device structure with those pointers needed later @@ -117,6 +118,9 @@ MOS6setup(matrix,inModel,ckt,states) here=here->MOS6nextInstance) { if (here->MOS6owner != ARCHme) goto matrixpointers; + CKTnode *tmpNode; + IFuid tmpName; + if(!here->MOS6drainPerimiterGiven) { here->MOS6drainPerimiter = 0; } @@ -155,6 +159,14 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->MOS6name,"drain"); if(error) return(error); here->MOS6dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->MOS6dNodePrime = here->MOS6dNode; } @@ -166,6 +178,14 @@ matrixpointers: error = CKTmkVolt(ckt,&tmp,here->MOS6name,"source"); if(error) return(error); here->MOS6sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->MOS6sNodePrime = here->MOS6sNode; } diff --git a/src/spicelib/devices/res/res.c b/src/spicelib/devices/res/res.c index 9a4cdc936..4ba865909 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: Apr 2000 - Paolo Nenzi +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -35,6 +36,7 @@ IFparm RESpTable[] = { /* parameters */ IFparm RESmPTable[] = { /* model parameters */ IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"), IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"), + IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"), IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"), IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"), IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index 49164f986..b6b3ccfbe 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #ifndef RES @@ -81,12 +82,14 @@ typedef struct sRESmodel { /* model structure for a resistor */ double RESsheetRes; /* sheet resistance of devices in ohms/square */ double RESdefWidth; /* default width of a resistor */ double RESnarrow; /* amount by which device is narrower than drawn */ + double RESshort; /* amount by which device is shorter than drawn */ unsigned REStnomGiven: 1; /* flag to indicate nominal temp. was given */ unsigned REStc1Given : 1; /* flag to indicate tc1 was specified */ unsigned REStc2Given : 1; /* flag to indicate tc2 was specified */ unsigned RESsheetResGiven :1; /* flag to indicate sheet resistance given*/ unsigned RESdefWidthGiven :1; /* flag to indicate default width given */ unsigned RESnarrowGiven :1; /* flag to indicate narrow effect given */ + unsigned RESshortGiven :1; /* flag to indicate short effect given */ } RESmodel; /* device parameters */ @@ -113,6 +116,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ #define RES_MOD_NARROW 105 #define RES_MOD_R 106 #define RES_MOD_TNOM 107 +#define RES_MOD_SHORT 108 /* device questions */ #define RES_QUEST_SENS_REAL 201 diff --git a/src/spicelib/devices/res/resmask.c b/src/spicelib/devices/res/resmask.c index 101dc2863..20421723e 100644 --- a/src/spicelib/devices/res/resmask.c +++ b/src/spicelib/devices/res/resmask.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: Apr 2000 - Paolo Nenzi +Modified: 2000 AlansFixes **********/ @@ -38,6 +39,9 @@ RESmodAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case RES_MOD_NARROW: value->rValue = model->RESnarrow; return(OK); + case RES_MOD_SHORT: + value->rValue = model->RESshort; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index 5350fdeb8..8af8fb906 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: Apr 2000 - Paolo Nenzi +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -42,6 +43,10 @@ RESmParam(int param, IFvalue *value, GENmodel *inModel) model->RESnarrow = value->rValue; model->RESnarrowGiven = TRUE; break; + case RES_MOD_SHORT: + model->RESshort = value->rValue; + model->RESshortGiven = TRUE; + break; case RES_MOD_R: /* just being reassured by user that this is a resistor model */ /* no-op */ diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index b4785e04b..c03c94b82 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified Apr 2000 - Paolo Nenzi +Modified: 2000 AlanSfixes **********/ #include "ngspice.h" @@ -36,6 +37,7 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) if(!model->REStc1Given) model->REStempCoeff1 = 0; if(!model->REStc2Given) model->REStempCoeff2 = 0; if(!model->RESnarrowGiven) model->RESnarrow = 0; + if(!model->RESshortGiven) model->RESshort = 0; /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; @@ -52,7 +54,7 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) if(model->RESsheetResGiven && (model->RESsheetRes != 0) && (here->RESlength != 0)) { here->RESresist = model->RESsheetRes * (here->RESlength - - model->RESnarrow) / (here->RESwidth - model->RESnarrow); + model->RESshort) / (here->RESwidth - model->RESnarrow); } else { (*(SPfrontEnd->IFerror))(ERR_WARNING, "%s: resistance=0, set to 1000",&(here->RESname)); diff --git a/src/spicelib/devices/sw/Makefile.am b/src/spicelib/devices/sw/Makefile.am index 0802f8cb6..f4236ee5c 100644 --- a/src/spicelib/devices/sw/Makefile.am +++ b/src/spicelib/devices/sw/Makefile.am @@ -20,7 +20,8 @@ libsw_la_SOURCES = \ swnoise.c \ swparam.c \ swpzload.c \ - swsetup.c + swsetup.c \ + swtrunc.c diff --git a/src/spicelib/devices/sw/swdefs.h b/src/spicelib/devices/sw/swdefs.h index db50cb932..540d7934e 100644 --- a/src/spicelib/devices/sw/swdefs.h +++ b/src/spicelib/devices/sw/swdefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon M. Jacobs +Modified: 2000 AlansFixes **********/ #ifndef SW @@ -53,7 +54,7 @@ typedef struct sSWinstance { #define SW_ON_CONDUCTANCE 1.0 /* default on conductance = 1 mho */ #define SW_OFF_CONDUCTANCE ckt->CKTgmin /* default off conductance */ -#define SW_NUM_STATES 1 +#define SW_NUM_STATES 2 typedef struct sSWmodel { /* model structure for a switch */ int SWmodType; /* type index of this device type */ diff --git a/src/spicelib/devices/sw/swext.h b/src/spicelib/devices/sw/swext.h index 492a540fd..08fb3543b 100644 --- a/src/spicelib/devices/sw/swext.h +++ b/src/spicelib/devices/sw/swext.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon M. Jacobs +Modified: 2000 AlansFixes **********/ #ifdef __STDC__ @@ -16,6 +17,7 @@ extern int SWparam(int,IFvalue*,GENinstance*,IFvalue*); extern int SWpzLoad(GENmodel*,CKTcircuit*,SPcomplex*); extern int SWsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int SWnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int SWtrunc(GENmodel*,CKTcircuit*,double*); #else /* stdc */ extern int SWacLoad(); extern int SWask(); @@ -29,5 +31,6 @@ extern int SWparam(); extern int SWpzLoad(); extern int SWsetup(); extern int SWnoise(); +extern int SWtrunc(); #endif /* stdc */ diff --git a/src/spicelib/devices/sw/swinit.c b/src/spicelib/devices/sw/swinit.c index 8e3473f28..0e2bdd381 100644 --- a/src/spicelib/devices/sw/swinit.c +++ b/src/spicelib/devices/sw/swinit.c @@ -1,3 +1,4 @@ +/* Modified: Alansfixes */ #include #include @@ -31,7 +32,7 @@ SPICEdev SWinfo = { DEVunsetup : NULL, DEVpzSetup : SWsetup, DEVtemperature: NULL, - DEVtrunc : NULL, + DEVtrunc : SWtrunc, DEVfindBranch : NULL, DEVacLoad : SWacLoad, DEVaccept : NULL, diff --git a/src/spicelib/devices/sw/swload.c b/src/spicelib/devices/sw/swload.c index 34b12feb8..de335cef0 100644 --- a/src/spicelib/devices/sw/swload.c +++ b/src/spicelib/devices/sw/swload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Gordon Jacobs +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -47,6 +48,8 @@ SWload(inModel,ckt) current_state = 0.0; } + *(ckt->CKTstate0 + (here->SWstate+1)) = 0; + } else if (ckt->CKTmode & (MODEINITSMSIG)) { previous_state = *(ckt->CKTstate0 + here->SWstate); @@ -68,7 +71,9 @@ SWload(inModel,ckt) } else { current_state = previous_state; } - + + *(ckt->CKTstate0 + (here->SWstate+1)) = v_ctrl; + if(current_state != previous_state) { ckt->CKTnoncon++; /* ensure one more iteration */ ckt->CKTtroubleElt = (GENinstance *) here; @@ -95,7 +100,9 @@ SWload(inModel,ckt) } else { *(ckt->CKTstate0 + here->SWstate) = 1.0; } - + + *(ckt->CKTstate0 + (here->SWstate+1)) = v_ctrl; + } g_now = current_state?(model->SWonConduct):(model->SWoffConduct); diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 3e0baedc9..2da813789 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -22,6 +23,7 @@ VSRCload(inModel,ckt) VSRCmodel *model = (VSRCmodel *)inModel; VSRCinstance *here; double time; + double value; /* loop through all the voltage source models */ for( ; model != NULL; model = model->VSRCnextModel ) { @@ -38,8 +40,7 @@ VSRCload(inModel,ckt) if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->VSRCdcGiven ) { /* grab dc value */ - *(ckt->CKTrhs + (here->VSRCbranch)) += ckt->CKTsrcFact * - here->VSRCdcValue; + value = ckt->CKTsrcFact * here->VSRCdcValue; } else { if(ckt->CKTmode & (MODEDC)) { time = 0; @@ -49,7 +50,7 @@ VSRCload(inModel,ckt) /* use the transient functions */ switch(here->VSRCfunctionType) { default: { /* no function specified: use the DC value */ - *(ckt->CKTrhs + (here->VSRCbranch)) += here->VSRCdcValue; + value = here->VSRCdcValue; break; } @@ -82,15 +83,13 @@ VSRCload(inModel,ckt) time -= basetime; } if (time <= 0 || time >= TR + PW + TF) { - ckt->CKTrhs[here->VSRCbranch] += V1; + value = V1; } else if (time >= TR && time <= TR + PW) { - ckt->CKTrhs[here->VSRCbranch] += V2; + value = V2; } else if (time > 0 && time < TR) { - ckt->CKTrhs[here->VSRCbranch] += - V1 + (V2 - V1) * (time) / TR; + value = V1 + (V2 - V1) * (time) / TR; } else { /* time > TR + PW && < TR + PW + TF */ - ckt->CKTrhs[here->VSRCbranch] += - V2 + (V1 - V2) * (time - (TR + PW)) / TF; + value = V2 + (V1 - V2) * (time - (TR + PW)) / TF; } } @@ -105,12 +104,10 @@ VSRCload(inModel,ckt) #define THETA ((here->VSRCfunctionOrder >=5)?(*(here->VSRCcoeffs+4)):(0.0)) time -= TD; if (time <= 0) { - *(ckt->CKTrhs + (here->VSRCbranch)) += VO; + value = VO; } else { - *(ckt->CKTrhs + (here->VSRCbranch)) += - VO + VA * sin(FREQ * time * 2.0 * M_PI) * + value = VO + VA * sin(FREQ * time * 2.0 * M_PI) * exp(-(time*THETA)); - /* 2PI to convert from hz to radians/sec*/ } #undef VO #undef VA @@ -136,13 +133,11 @@ VSRCload(inModel,ckt) td1 = TD1; td2 = TD2; if(time <= td1) { - *(ckt->CKTrhs + (here->VSRCbranch)) += V1; + value = V1; } else if (time <= td2) { - *(ckt->CKTrhs + (here->VSRCbranch)) += - V1 + (V2-V1)*(1-exp(-(time-td1)/TAU1)); + value = V1 + (V2-V1)*(1-exp(-(time-td1)/TAU1)); } else { - *(ckt->CKTrhs + (here->VSRCbranch)) += - V1 + (V2-V1)*(1-exp(-(time-td1)/TAU1)) + + value = V1 + (V2-V1)*(1-exp(-(time-td1)/TAU1)) + (V1-V2)*(1-exp(-(time-td2)/TAU2)) ; } #undef V1 @@ -163,9 +158,9 @@ VSRCload(inModel,ckt) 0.0) #define FS (((here->VSRCfunctionOrder >=5) && (*(here->VSRCcoeffs+4)))? \ (*(here->VSRCcoeffs+4)):(1/ckt->CKTfinalTime)) - *(ckt->CKTrhs + (here->VSRCbranch)) += VO + VA * - sin((2 * 3.141592654 * FC * time) + - MDI * sin(2 * 3.141592654 * FS * time)); + value = VO + VA * + sin((2 * 3.141592654 * FC * time) + + MDI * sin(2 * 3.141592654 * FS * time)); #undef VO #undef VA #undef FC @@ -179,14 +174,13 @@ VSRCload(inModel,ckt) double foo; if(time < *(here->VSRCcoeffs)) { foo = *(here->VSRCcoeffs + 1) ; - *(ckt->CKTrhs + (here->VSRCbranch)) += foo; + value = foo; goto loadDone; } for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) { if((*(here->VSRCcoeffs+2*i)==time)) { foo = *(here->VSRCcoeffs+2*i+1); - *(ckt->CKTrhs + (here->VSRCbranch)) += - foo; + value = foo; goto loadDone; } else if((*(here->VSRCcoeffs+2*i)VSRCcoeffs+2*(i+1)) >time)) { @@ -196,18 +190,19 @@ VSRCload(inModel,ckt) *(here->VSRCcoeffs+2*i))) * (*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1))); - *(ckt->CKTrhs + (here->VSRCbranch)) += - foo; + value = foo; goto loadDone; } } foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ; - *(ckt->CKTrhs + (here->VSRCbranch)) += foo; + value = foo; break; } } } -loadDone: ; +loadDone: +if (ckt->CKTmode & MODETRANOP) value *= ckt->CKTsrcFact; + *(ckt->CKTrhs + (here->VSRCbranch)) += value; } } return(OK); diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index b7447a895..37d0e90f8 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* */ @@ -21,6 +22,7 @@ VSRCparam(param,value,inst,select) GENinstance *inst; IFvalue *select; { + int i; VSRCinstance *here = (VSRCinstance *)inst; switch(param) { case VSRC_DC: @@ -79,6 +81,15 @@ VSRCparam(param,value,inst,select) here->VSRCcoeffs = value->v.vec.rVec; here->VSRCfunctionOrder = value->v.numValue; here->VSRCcoeffsGiven = TRUE; + + for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) { + if(*(here->VSRCcoeffs+2*(i+1))<=*(here->VSRCcoeffs+2*i)) { + fprintf(stderr, "Warning : voltage source %s", + here->VSRCname); + fprintf(stderr, " has non-increasing PWL time points.\n"); + } + } + break; case VSRC_SFFM: here->VSRCfunctionType = SFFM; diff --git a/src/spicelib/parser/ChangeLog b/src/spicelib/parser/ChangeLog index 8d60ca548..28ded0967 100644 --- a/src/spicelib/parser/ChangeLog +++ b/src/spicelib/parser/ChangeLog @@ -1,3 +1,7 @@ +2000-09-02 Paolo Nenzi + * Patched with code sent by Alan Gillespie. See more on top + level ChangeLog. + 2000-07-07 Arno W. Peters * circuit/inp2b.c, circuit/inp2c.c, circuit/inp2d.c, diff --git a/src/spicelib/parser/Makefile.am b/src/spicelib/parser/Makefile.am index c389dc7c7..04336fd86 100644 --- a/src/spicelib/parser/Makefile.am +++ b/src/spicelib/parser/Makefile.am @@ -31,6 +31,7 @@ libinp_a_SOURCES = \ inpapnam.c \ inpcfix.c \ inpdomod.c \ + inpdoopt.c \ inpdpar.c \ inperrc.c \ inperror.c \ @@ -50,6 +51,8 @@ libinp_a_SOURCES = \ inppas1.h \ inppas2.c \ inppas2.h \ + inppas3.c \ + inppas3.h \ inppname.c \ inpptree.c \ inpsymt.c \ diff --git a/src/spicelib/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c index ab4bedfcc..d27b0663f 100644 --- a/src/spicelib/parser/inp2dot.c +++ b/src/spicelib/parser/inp2dot.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ #include "ngspice.h" @@ -742,7 +743,7 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode) } else if ((strcmp(token, ".op") == 0)) { return dot_op(line, ckt, tab, current, task, gnode, foo); } else if ((strcmp(token, ".nodeset") == 0)) { - return dot_nodeset(line, ckt, tab, current, task, gnode); + return(0); } else if ((strcmp(token, ".disto") == 0)) { return dot_disto(line, ckt, tab, current, task, gnode, foo); } else if ((strcmp(token, ".noise") == 0)) { @@ -754,7 +755,7 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode) LITERR("Use fourier command to obtain fourier analysis\n"); return (0); } else if ((strcmp(token, ".ic") == 0)) { - return dot_ic(line, ckt, tab, current, task, gnode, foo); + return (0); } else if ((strcmp(token, ".ac") == 0)) { return dot_ac(line, ckt, tab, current, task, gnode, foo); } else if ((strcmp(token, ".pz") == 0)) { diff --git a/src/spicelib/parser/inpgtok.c b/src/spicelib/parser/inpgtok.c index c00ae28fe..ecc423d28 100644 --- a/src/spicelib/parser/inpgtok.c +++ b/src/spicelib/parser/inpgtok.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified: 2000 AlansFixes **********/ /* get input token from 'line', @@ -58,10 +59,12 @@ int INPgetTok(char **line, char **token, int gobble) if (*point == ',') break; /* This is not complex enough to catch all errors, but it will get the "good" parses */ - if (*point == '+' && (signstate == 1 || signstate == 3)) - break; - if (*point == '-' && (signstate == 1 || signstate == 3)) - break; + if ((*point == '+') || (*point == '-')){ + /* Treat '+' signs same as '-' signs */ + if (signstate == 1 || signstate == 3) break; + signstate += 1; + continue; + } if (*point == '*') break; if (*point == '/')