diff --git a/INSTALL b/INSTALL index 93ed9f4a6..5a4566b32 100644 --- a/INSTALL +++ b/INSTALL @@ -250,6 +250,14 @@ Most of the options now following are not well maintained, are not tested or eve "tclspice" is compiled and installed instead of plain ngspice. + --with-ngshared + This option let you compile ngspice as a shared + library or dll, allowing an application controlling + ngspice. This option excludes using --with-x or + --with-wingui. Useful additional options are + --enable-xspice --enable-cider --enable-openmp. + No graphics inetrface is provided, this has to be + handled by the controlling application. 1.4.3 Options Useful for Debugging Ngspice @@ -538,7 +546,7 @@ Most of the options now following are not well maintained, are not tested or eve 9.2 make ngspice with MS Visual Studio 2008 - ngspice may be compiled with MS Visual Studio 2008. + ngspice may be compiled with MS Visual Studio 2008 or 2010. CIDER and XSPICE are included, but the code models for XSPICE (*.cm) are not (yet) made. You may however use the code models diff --git a/README.adms b/README.adms index c7218009d..ef23bd6e0 100644 --- a/README.adms +++ b/README.adms @@ -22,6 +22,20 @@ * 02110-1301 USA * *************************************************************************** +WARNING! + +The text in this document has been prepared in 2006 and is outdated. It is +provided here only for reference and may provide some (historical) +information. + +Please refer to the ngspice adms web page at +http://ngspice.sourceforge.net/admshowto.html +for actual information on how to integrate Verilog A device models into +ngspice. + +Holger Vogt, May 2013 + + INTRODUCTION diff --git a/configure.ac b/configure.ac index c32b98d98..cd9799793 100644 --- a/configure.ac +++ b/configure.ac @@ -182,6 +182,10 @@ AC_ARG_WITH([tcl], AC_ARG_WITH([ngshared], [AS_HELP_STRING([--with-ngshared], [Compiles ngspice as shared library (dll)])]) +# --enable-kirchhoff: enable KCL +AC_ARG_ENABLE([kirchhoff], + [AS_HELP_STRING([--enable-kirchhoff], [Enables the Kirchhoff Current Law Verification])]) + # readline and editline cannot both be enabled if test "x$with_editline" = xyes; then if test "x$with_readline" = xyes; then @@ -801,6 +805,7 @@ AC_MSG_RESULT([Settings which were chosen:]) if test "x$enable_sense2" = xyes; then AC_DEFINE([WANT_SENSE2], [], [Define if we want spice2 sensitivity analysis]) AC_MSG_RESULT([Spice2 sensitivity analysis enabled]) + AC_MSG_WARN([This feature is UNSUPPORTED]) fi if test "x$enable_nobypass" = xyes; then AC_DEFINE([NOBYPASS], [], [Define if we want NOBYPASS]) @@ -856,7 +861,7 @@ if test "x$enable_pzdebug" = xyes; then fi if test "x$enable_pss" = xyes; then AC_DEFINE([WITH_PSS], [], [Define if you want PSS analysis]) - AC_MSG_RESULT(WARNING: PSS analysis enabled) + AC_MSG_RESULT([WARNING: PSS analysis enabled]) fi if test "x$enable_blktmsdebug" = xyes; then AC_DEFINE([D_DBG_BLOCKTIMES], [], [Define if we want debug distortion analysis (BLOCKTIMES)]) @@ -879,6 +884,12 @@ fi AC_SUBST([XGRAPHDIR]) AC_SUBST([NOTXGRAPH]) +if test "x$enable_kirchhoff" = xyes; then + AC_DEFINE([KIRCHHOFF], [], [Define if we want to enable the Kirchhoff Current Law Verification]) + AC_MSG_RESULT([WARNING: Kirchhoff Current Law Verification Enabled (experimental)]) +fi +AM_CONDITIONAL([KIRCHHOFF_WANTED], [test "x$enable_kirchhoff" = xyes]) + AC_CHECK_PROGS([YACC], ['bison -y' byacc yacc]) ################# XSPICE ################################################## @@ -945,6 +956,8 @@ AM_CONDITIONAL([NUMDEV_WANTED], [test "x$enable_cider" = xyes]) AM_CONDITIONAL([PSS_WANTED], [test "x$enable_pss" = xyes]) +AM_CONDITIONAL([SENSE2_WANTED], [test "x$enable_sense2" = xyes]) + # adms option if test "x$enable_adms" = xyes ; then AC_MSG_RESULT([********************************** @@ -1216,6 +1229,7 @@ AC_CONFIG_FILES([Makefile src/xspice/enh/Makefile src/xspice/ipc/Makefile src/xspice/idn/Makefile + src/unsupported/Makefile tests/Makefile tests/bsim1/Makefile tests/bsim2/Makefile diff --git a/examples/kirchhoff/2_gidlgisl_n.net b/examples/kirchhoff/2_gidlgisl_n.net new file mode 100644 index 000000000..bd1dc2271 --- /dev/null +++ b/examples/kirchhoff/2_gidlgisl_n.net @@ -0,0 +1,22 @@ +DBj_gidl_n + +.INCLUDE 45nm_MGK_car2_gidlgisl.pm +.OPTIONS GMIN=1e-18 abstol=1e-19 + +*Definizione dei parametri +.PARAM Lmin=45n +.PARAM Wmin=45n +.PARAM Ldiff=90n + +*Descrizione della cella +Mp drain gate source body nmos W={Wmin} L={Lmin} AS={Wmin*Ldiff} AD={Wmin*Ldiff} PS={2*(Ldiff+Wmin)} PD={2*(Ldiff+Wmin)} +Vd drain alim 0V +Vg gate 0 0V +Vs source alim 0V +Vb body 0 0V +Vdd alim 0 0.05V + +*Definizione del tipo di analisi +.dc Vdd 0.0 1.2 0.1 +.print all +.END diff --git a/examples/kirchhoff/2_gidlgisl_p.net b/examples/kirchhoff/2_gidlgisl_p.net new file mode 100644 index 000000000..dd6019cfb --- /dev/null +++ b/examples/kirchhoff/2_gidlgisl_p.net @@ -0,0 +1,22 @@ +DBj_gidl_p + +.INCLUDE 45nm_MGK_car2_gidlgisl.pm +.OPTIONS GMIN=1e-18 abstol=1e-24 vntol=1e-24 + +*Definizione dei parametri +.PARAM Lmin=45n +.PARAM Wmin=45n +.PARAM Ldiff=90n + +*Descrizione della cella +Mp drain gate source body pmos W={Wmin} L={Lmin} AS={Wmin*Ldiff} AD={Wmin*Ldiff} PS={2*(Ldiff+Wmin)} PD={2*(Ldiff+Wmin)} +Vd drain 0 0V +Vg gate alim 0V +Vs source 0 0V +Vb body alim 0V +Vdd alim 0 0.05V + +*Definizione del tipo di analisi +.dc Vdd 0.0 1.2 0.1 +.print all +.END diff --git a/examples/kirchhoff/2_gidlgisl_p_shift.net b/examples/kirchhoff/2_gidlgisl_p_shift.net new file mode 100644 index 000000000..4d17ca53f --- /dev/null +++ b/examples/kirchhoff/2_gidlgisl_p_shift.net @@ -0,0 +1,22 @@ +DBj_gidl_p + +.INCLUDE 45nm_MGK_car2_gidlgisl.pm +.OPTIONS GMIN=1e-18 abstol=1e-19 + +*Definizione dei parametri +.PARAM Lmin=45n +.PARAM Wmin=45n +.PARAM Ldiff=90n + +*Descrizione della cella +Mp drain gate source body pmos W={Wmin} L={Lmin} AS={Wmin*Ldiff} AD={Wmin*Ldiff} PS={2*(Ldiff+Wmin)} PD={2*(Ldiff+Wmin)} +Vd drain 0 -1V +Vg gate alim 0V +Vs source 0 -1V +Vb body alim 0V +Vdd alim 0 -1.05V + +*Definizione del tipo di analisi +.dc Vdd 0.0 1.2 0.1 +.print all +.END diff --git a/examples/kirchhoff/45nm_MGK_car2_gidlgisl.pm b/examples/kirchhoff/45nm_MGK_car2_gidlgisl.pm new file mode 100644 index 000000000..2ed9cbcc8 --- /dev/null +++ b/examples/kirchhoff/45nm_MGK_car2_gidlgisl.pm @@ -0,0 +1,120 @@ +.model nmos nmos level=54 ++version = 4.7.0 binunit = 1 paramchk= 1 mobmod = 0 ++capmod = 2 igcmod = 0 igbmod = 0 geomod = 1 ++diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1 ++permod = 1 acnqsmod= 0 trnqsmod= 0 ++tnom = 27 toxe = 9e-010 toxp = 6.5e-010 toxm = 9e-010 ++dtox = 2.5e-010 epsrox = 3.9 wint = 5e-009 lint = 2.7e-009 ++ll = 0 wl = 0 lln = 1 wln = 1 ++lw = 0 ww = 0 lwn = 1 wwn = 1 ++lwl = 0 wwl = 0 xpart = 0 toxref = 9e-010 xl = -20e-9 ++dlcig = 2.7e-009 ++vth0 = 0.3423 k1 = 0.2 k2 = 0 k3 = 0 ++k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2 ++dvt2 = 0 dvt0w = 0 dvt1w = 0 dvt2w = 0 ++dsub = 0.078 minv = 0.05 voffl = 0 dvtp0 = 1e-010 ++dvtp1 = 0.1 lpe0 = 0 lpeb = 0 xj = 1.4e-008 ++ngate = 1e+023 ndep = 6.5e+018 nsd = 2e+020 phin = 0 ++cdsc = 0 cdscb = 0 cdscd = 0 cit = 0 ++voff = -0.13 nfactor = 1.9 eta0 = 0.0055 etab = 0 ++vfb = -1.058 u0 = 0.02947 ua = -5e-010 ub = 1.7e-018 ++uc = 0 vsat = 159550 a0 = 1 ags = 0 ++a1 = 0 a2 = 1 b0 = 0 b1 = 0 ++keta = 0.04 dwg = 0 dwb = 0 pclm = 0.06 ++pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = -0.005 drout = 0.5 ++pvag = 1e-020 delta = 0.01 pscbe1 = 2.0e+009 pscbe2 = 1e-007 ++fprout = 0.2 pdits = 0.01 pditsd = 0.23 pditsl = 2300000 ++rsh = 5 rdsw = 105 rsw = 52.5 rdw = 52.5 ++rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0 ++prwb = 0 wr = 1 alpha0 = 0.0 alpha1 = 0.00 ++beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002 ++egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002 ++nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004 ++eigbinv = 1.1 nigbinv = 3 aigc = 0.018029 bigc = 0.0029 ++cigc = 0.002 aigsd = 0.018029 bigsd = 0.0029 cigsd = 0.002 ++nigc = 1 poxedge = 1 pigcd = 1 ntox = 1 ++xrcrg1 = 12 xrcrg2 = 5 ++cgso = 1e-010 cgdo = 1e-010 cgbo = 0 cgdl = 7.5e-013 ++cgsl = 7.5e-013 clc = 1e-007 cle = 0.6 cf = 1.1e-010 ++ckappas = 0.6 ckappad = 0.6 vfbcv = -1 acde = 1 ++moin = 15 noff = 1 voffcv = 0 ++kt1 = -0.154 kt1l = 0 kt2 = 0.022 ute = -1.1 ++ua1 = 1e-009 ub1 = -1e-018 uc1 = -5.6e-011 prt = 0 ++at = 33000 ++fnoimod = 1 tnoimod = 0 noia = 6.25e+041 noib = 3.125e+026 ++noic = 8.75e+009 em = 41000000 af = 1 ef = 1 ++kf = 0 tnoia = 1.5 tnoib = 3.5 ntnoi = 1 ++jss = 0.0 jsws = 0.0 jswgs = 0.0 njs = 1 ++ijthsfwd= 0.1 ijthsrev= 0.1 bvs = 10 xjbvs = 1 ++jsd = 0.0 jswd = 0.0 jswgd = 0.0 xjbvd = 1 ++pbs = 1 cjs = 0.0018 mjs = 0.5 pbsws = 1 ++cjsws = 1.2e-010 mjsws = 0.33 cjswgs = 2.1e-010 cjd = 0.0018 ++cjswd = 1.2e-010 mjswd = 0.33 pbswgd = 1 cjswgd = 2.1e-010 ++mjswgd = 0.33 tpb = 0 tcj = 0 tpbsw = 0 ++tcjsw = 0 tpbswg = 0 tcjswg = 0 xtis = 3 ++dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0 ++dwj = 0 xgw = 0 xgl = 0 ++rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15 ++rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1 + + + +.model pmos pmos level = 54 ++version = 4.7.0 binunit = 1 paramchk= 1 mobmod = 0 ++capmod = 2 igcmod = 0 igbmod = 0 geomod = 1 ++diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1 ++permod = 1 acnqsmod= 0 trnqsmod= 0 ++tnom = 27 toxe = 9.2e-010 toxp = 6.5e-010 toxm = 9.2e-010 ++dtox = 2.7e-010 epsrox = 3.9 wint = 5e-009 lint = 2.7e-009 ++ll = 0 wl = 0 lln = 1 wln = 1 ++lw = 0 ww = 0 lwn = 1 wwn = 1 ++lwl = 0 wwl = 0 xpart = 0 toxref = 9.2e-010 xl = -20e-9 ++dlcig = 2.7e-009 ++vth0 = -0.23122 k1 = 0.2 k2 = -0.01 k3 = 0 ++k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2 ++dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0 ++dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-011 ++dvtp1 = 0.05 lpe0 = 0 lpeb = 0 xj = 1.4e-008 ++ngate = 1e+023 ndep = 2.8e+018 nsd = 2e+020 phin = 0 ++cdsc = 0 cdscb = 0 cdscd = 0 cit = 0 ++voff = -0.13 nfactor = 1.9 eta0 = 0.0049 etab = 0 ++vfb = -1.058 u0 = 0.00391 ua = -5e-010 ub = 1.6e-018 ++uc = 0 vsat = 78000 a0 = 1 ags = 1e-020 ++a1 = 0 a2 = 1 b0 = 0 b1 = 0 ++keta = -0.047 dwg = 0 dwb = 0 pclm = 0.1 ++pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = 3.4e-008 drout = 0.6 ++pvag = 1e-020 delta = 0.01 pscbe1 = 2e+009 pscbe2 = 9.58e-007 ++fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000 ++rsh = 5 rdsw = 105 rsw = 52.5 rdw = 52.5 ++rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0 ++prwb = 0 wr = 1 alpha0 = 0.0 alpha1 = 0.00 ++beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002 ++egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002 ++nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004 ++eigbinv = 1.1 nigbinv = 3 aigc = 0.010687 bigc = 0.0012607 ++cigc = 0.0008 aigsd = 0.010687 bigsd = 0.0012607 cigsd = 0.0008 ++nigc = 1 poxedge = 1 pigcd = 1 ntox = 1 ++xrcrg1 = 12 xrcrg2 = 5 ++cgso = 1e-010 cgdo = 1e-010 cgbo = 0 cgdl = 3e-011 ++cgsl = 3e-011 clc = 1e-007 cle = 0.6 cf = 1.1e-010 ++ckappas = 0.6 ckappad = 0.6 vfbcv = -1 acde = 1 ++moin = 15 noff = 1 voffcv = 0 ++kt1 = -0.14 kt1l = 0 kt2 = 0.022 ute = -1.1 ++ua1 = 1e-009 ub1 = -1e-018 uc1 = -5.6e-011 prt = 0 ++at = 33000 ++fnoimod = 1 tnoimod = 0 noia = 6.25e+041 noib = 3.125e+026 ++noic = 8.75e+009 em = 41000000 af = 1 ef = 1 ++kf = 0 tnoia = 1.5 tnoib = 3.5 ntnoi = 1 ++jss = 0.0 jsws = 0.0 jswgs = 0.0 njs = 1 ++ijthsfwd= 0.1 ijthsrev= 0.1 bvs = 10 xjbvs = 1 ++jsd = 0.0 jswd = 0.0 jswgd = 0.0 xjbvd = 1 ++pbs = 1 cjs = 0.0015 mjs = 0.5 pbsws = 1 ++cjsws = 9.4e-011 mjsws = 0.33 cjswgs = 2e-010 cjd = 0.0015 ++cjswd = 9.4e-011 mjswd = 0.33 pbswgd = 1 cjswgd = 2e-010 ++mjswgd = 0.33 tpb = 0 tcj = 0 tpbsw = 0 ++tcjsw = 0 tpbswg = 0 tcjswg = 0 xtis = 3 ++dmcg = 0 dmdg = 0 dmcgt = 0 xgw = 0 ++xgl = 0 ++rshg = 0.1 gbmin = 1e-012 rbpb = 50 rbpd = 50 ++rbps = 50 rbdb = 50 rbsb = 50 ngcon = 1 + diff --git a/src/Makefile.am b/src/Makefile.am index bba586a3c..ae9155bf9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in SUBDIRS = misc maths frontend spicelib include/ngspice -DIST_SUBDIRS = misc maths frontend spicelib include/ngspice xspice ciderlib +DIST_SUBDIRS = misc maths frontend spicelib include/ngspice xspice ciderlib unsupported if XSPICE_WANTED SUBDIRS += xspice @@ -11,6 +11,10 @@ if CIDER_WANTED SUBDIRS += ciderlib endif +if SENSE2_WANTED +SUBDIRS += unsupported +endif + if !TCL_MODULE if !SHARED_MODULE bin_PROGRAMS = ngspice ngnutmeg @@ -27,7 +31,7 @@ endif !SHARED_MODULE endif !TCL_MODULE EXTRA_DIST = ngspice.txt setplot spectrum \ - devload devaxis ciderinit winmain.c winmain.h unsupported \ + devload devaxis ciderinit winmain.c winmain.h \ tclspice.c tclspice.map pkgIndex.tcl.in spinit.in tclspinit.in \ main.c sharedspice.c @@ -137,6 +141,10 @@ ngspice_LDADD += \ spicelib/analysis/libckt.la \ spicelib/devices/libdev.la +if SENSE2_WANTED +ngspice_LDADD += unsupported/libunsupported.la +endif + if XSPICE_WANTED ngspice_LDADD += \ xspice/cm/libcmxsp.la \ diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 00ba77153..33f6d106a 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -50,9 +50,10 @@ static char *upper(register char *string); static bool doedit(char *filename); static struct line *com_options = NULL; static void cktislinear(CKTcircuit *ckt, struct line *deck); +static void dotifeval(struct line *deck); void line_free_x(struct line *deck, bool recurse); - +void create_circbyline(char *line); /* @@ -547,6 +548,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) } } + /* handle .if ... .elseif ... .else ... .endif statements. */ + dotifeval(deck); + /*merge the two option line structs*/ if (!options && com_options) options = com_options; @@ -1199,3 +1203,71 @@ com_circbyline(wordlist *wl) char *newline = wl_flatten(wl); create_circbyline(newline); } + +/* handle .if('expr') ... .elseif('expr') ... .else ... .endif statements. + numparam has evaluated .if('boolean expression') to + .if ( 1.000000000e+000 ) or .elseif ( 0.000000000e+000 ) */ +static void +dotifeval(struct line *deck) +{ + int iftrue = 0, elseiftrue = 0, elsetrue = 0, iffound = 0, elseiffound = 0, elsefound = 0; + struct line *dd; + char *dottoken; + char *s, *t; + + /* skip the first line (title line) */ + for (dd = deck->li_next; dd; dd = dd->li_next) { + + s = t = dd->li_line; + + if (*s == '*') + continue; + + dottoken = gettok(&t); + /* find '.if' and read its parameter */ + if (cieq(dottoken, ".if")) { + elsefound = 0; + elseiffound = 0; + iffound = 1; + *s = '*'; + s = dd->li_line + 3; + iftrue = atoi(s); + } + else if (cieq(dottoken, ".elseif")) { + elsefound = 0; + elseiffound = 1; + iffound = 0; + *s = '*'; + if (!iftrue) { + s = dd->li_line + 7; + elseiftrue = atoi(s); + } + } + else if (cieq(dottoken, ".else")) { + elsefound = 1; + elseiffound = 0; + iffound = 0; + if (!iftrue && !elseiftrue) + elsetrue = 1; + *s = '*'; + } + else if (cieq(dottoken, ".endif")) { + elsefound = elseiffound = iffound = 0; + elsetrue = elseiftrue = iftrue = 0; + *s = '*'; +// inp_subcktexpand(dd); + } + else { + if (iffound && !iftrue) { + *s = '*'; + } + else if (elseiffound && !elseiftrue) { + *s = '*'; + } + else if (elsefound && !elsetrue) { + *s = '*'; + } + } + tfree(dottoken); + } +} diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 50c3fc399..54230527c 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -4,10 +4,10 @@ Author: 1985 Wayne A. Christopher **********/ /* - For dealing with spice input decks and command scripts + For dealing with spice input decks and command scripts - Central function is inp_readall() - */ + Central function is inp_readall() +*/ #include "ngspice/ngspice.h" @@ -20,6 +20,7 @@ Author: 1985 Wayne A. Christopher #include "inpcom.h" #include "variable.h" +#include "subckt.h" #include "../misc/util.h" /* ngdirname() */ #include "ngspice/stringutil.h" #include "ngspice/wordlist.h" @@ -35,20 +36,37 @@ Author: 1985 Wayne A. Christopher /*#define TRACE*/ /* globals -- wanted to avoid complicating inp_readall interface */ -static char *library_name[1000]; -static char *section_name[1000][1000]; -static struct line *section_ref[1000][1000]; -static struct line *library_deck[1000]; +#define N_LIBRARIES 1000 +#define N_SECTIONS 1000 +#define N_PARAMS 1000 +#define N_SUBCKT_W_PARAMS 4000 + +static struct library { + char *name; + struct line *deck; +} libraries[N_LIBRARIES]; + static int num_libraries; -static int num_sections[1000]; -static char *global; -static char *subckt_w_params[1000]; -static int num_subckt_w_params; -static char *func_names[1000]; -static char *func_params[1000][1000]; -static char *func_macro[5000]; -static int num_functions; -static int num_parameters[1000]; + +struct names { + char *names[N_SUBCKT_W_PARAMS]; + int num_names; +}; + +struct function_env +{ + struct function_env *up; + + struct function { + struct function *next; + char *name; + char *macro; + char *params[N_PARAMS]; + int num_parameters; + } *functions; +}; + + static COMPATMODE_T inp_compat_mode; /* Collect information for dynamic allocation of numparam arrays */ @@ -64,21 +82,21 @@ static char *readline(FILE *fd); static int get_number_terminals(char *c); static void inp_stripcomments_deck(struct line *deck); static void inp_stripcomments_line(char *s); -static void inp_fix_for_numparam(struct line *deck); +static void inp_fix_for_numparam(struct names *subckt_w_params, struct line *deck); static void inp_remove_excess_ws(struct line *deck); -static void collect_section_references(struct line *deck, char *section_name_); -static void inp_init_lib_data(void); -static void inp_grab_func(struct line *deck); -static void inp_fix_inst_calls_for_numparam(struct line *deck); -static void inp_expand_macros_in_func(void); -static void inp_expand_macros_in_deck(struct line *deck); +static void expand_section_references(struct line *deck, int call_depth, char *dir_name); +static void inp_grab_func(struct function_env *, struct line *deck); +static void inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck); +static void inp_expand_macros_in_func(struct function_env *); +static struct line *inp_expand_macros_in_deck(struct function_env *, struct line *deck); static void inp_fix_param_values(struct line *deck); -static void inp_reorder_params(struct line *deck, struct line *list_head, struct line *end); +static void inp_reorder_params(struct names *subckt_w_params, struct line *deck, struct line *list_head, struct line *end); static int inp_split_multi_param_lines(struct line *deck, int line_number); static void inp_sort_params(struct line *start_card, struct line *end_card, struct line *card_bf_start, struct line *s_c, struct line *e_c); static char *inp_remove_ws(char *s); static void inp_compat(struct line *deck); static void inp_bsource_compat(struct line *deck); +static void inp_dot_if(struct line *deck); static bool chk_for_line_continuation(char *line); static void comment_out_unused_subckt_models(struct line *start_card, int no_of_lines); @@ -92,42 +110,99 @@ static char *get_quoted_token(char *string, char **token); static void replace_token(char *string, char *token, int where, int total); static void inp_add_series_resistor(struct line *deck); -static char *skip_back_non_ws(char *d) { while (*d && !isspace(*d)) d--; return d; } +static char *skip_back_non_ws(char *d) { while (d[-1] && !isspace(d[-1])) d--; return d; } +static char *skip_back_ws(char *d) { while (isspace(d[-1])) d--; return d; } static char *skip_non_ws(char *d) { while (*d && !isspace(*d)) d++; return d; } -static char *skip_back_ws(char *d) { while (isspace(*d)) d--; return d; } static char *skip_ws(char *d) { while (isspace(*d)) d++; return d; } +static char *skip_back_non_ws_(char *d, char *start) { while (d > start && !isspace(d[-1])) d--; return d; } +static char *skip_back_ws_(char *d, char *start) { while (d > start && isspace(d[-1])) d--; return d; } + +static void tprint(struct line *deck); + #ifndef XSPICE static void inp_poly_err(struct line *deck); #endif -static int +static struct line * +xx_new_line(struct line *next, char *line, int linenum, int linenum_orig) +{ + struct line *x = TMALLOC(struct line, 1); + + x->li_next = next; + x->li_error = NULL; + x->li_actual = NULL; + x->li_line = line; + x->li_linenum = linenum; + x->li_linenum_orig = linenum_orig; + + return x; +} + + +static struct library * +new_lib(void) +{ + if (num_libraries >= N_LIBRARIES) { + fprintf(stderr, "ERROR, N_LIBRARIES overflow\n"); + controlled_exit(EXIT_FAILURE); + } + + return & libraries[num_libraries++]; +} + + +static struct library * find_lib(char *name) { int i; + for (i = 0; i < num_libraries; i++) - if (cieq(library_name[i], name)) - return i; - return -1; + if (cieq(libraries[i].name, name)) + return & libraries[i]; + + return NULL; } -static int -find_section(int lib_idx, char *section_name_) { - int j; - for (j = 0; j < num_sections[lib_idx]; j++) - if (strcmp(section_name[lib_idx][j], section_name_) == 0) - return j; - return -1; -} +static struct line * +find_section_definition(struct line *c, char *name) +{ + for (; c; c = c->li_next) { + char *line = c->li_line; -static void -remember_section_ref(int lib_idx, char *section_name_, struct line *deck) { - int section_idx = num_sections[lib_idx]++; - section_ref[lib_idx][section_idx] = deck; - section_name[lib_idx][section_idx] = strdup(section_name_); + if (ciprefix(".lib", line)) { + + char *s, *t, *y; + + s = skip_non_ws(line); + while (isspace(*s) || isquote(*s)) + s++; + for (t = s; *t && !isspace(*t) && !isquote(*t); t++) + ; + y = t; + while (isspace(*y) || isquote(*y)) + y++; + + if (!*y) { + /* library section definition: `.lib ' .. `.endl' */ + + char keep_char = *t; + *t = '\0'; + + if (strcasecmp(name, s) == 0) { + *t = keep_char; + return c; + } + + *t = keep_char; + } + } + } + + return NULL; } @@ -142,7 +217,9 @@ read_a_lib(char *y, int call_depth, char *dir_name) y = copyy; /* reuse y, but remember, buffer still points to allocated memory */ } - if (find_lib(y) < 0) { + if (!find_lib(y)) { + + struct library *lib; bool dir_name_flag = FALSE; FILE *newfp = inp_pathopen(y, "r"); @@ -158,179 +235,181 @@ read_a_lib(char *y, int call_depth, char *dir_name) newfp = inp_pathopen(big_buff2, "r"); if (!newfp) { fprintf(cp_err, "Error: Could not find library file %s\n", y); - if (copyy) - tfree(copyy); /* allocated by the cp_tildexpand() above */ + tfree(copyy); /* allocated by the cp_tildexpand() above */ return FALSE; } dir_name_flag = TRUE; } - library_name[num_libraries++] = strdup(y); + lib = new_lib(); + + lib->name = strdup(y); if (dir_name_flag == FALSE) { char *y_dir_name = ngdirname(y); - library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, y_dir_name, FALSE, FALSE); + lib->deck = inp_readall(newfp, call_depth+1, y_dir_name, FALSE, FALSE); tfree(y_dir_name); } else { - library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, dir_name, FALSE, FALSE); + lib->deck = inp_readall(newfp, call_depth+1, dir_name, FALSE, FALSE); } fclose(newfp); } - if (copyy) - tfree(copyy); /* allocated by the cp_tildexpand() above */ + tfree(copyy); /* allocated by the cp_tildexpand() above */ return TRUE; } -static int -expand_section_references(int line_number) +static struct names * +new_names(void) { - struct line *tmp_ptr = NULL, *next; - int lib_idx; + struct names *p = TMALLOC(struct names, 1); + p -> num_names = 0; - for (lib_idx = 0; lib_idx < num_libraries; lib_idx++) { - bool found_section = FALSE; - struct line *working = library_deck[lib_idx]; - while (working) { - char *buffer = working->li_line; + return p; +} - if (found_section && ciprefix(".endl", buffer)) { - struct line *next = working->li_next; +static void +delete_names(struct names *p) +{ + tfree(p); +} - /* Make the .endl a comment */ - *buffer = '*'; - found_section = FALSE; - /* append the line following the library section reference */ - working->li_next = tmp_ptr; +static void +inp_stitch_continuation_lines(struct line *working) +{ + struct line *prev = NULL; - /* and continue with the line following */ - /* the .endl of this section definition */ - working = next; + while (working) { + char *s, c, *buffer; + + for (s = working->li_line; (c = *s) != '\0' && c <= ' '; s++) + ; + +#ifdef TRACE + /* SDB debug statement */ + printf("In inp_readall, processing linked list element line = %d, s = %s . . . \n", working->li_linenum, s); +#endif + + switch (c) { + case '#': + case '$': + case '*': + case '\0': + /* this used to be commented out. Why? */ + /* prev = NULL; */ + working = working->li_next; /* for these chars, go to next card */ + break; + + case '+': /* handle continuation */ + if (!prev) { + working->li_error = copy("Illegal continuation line: ignored."); + working = working->li_next; + break; + } + + /* create buffer and write last and current line into it. */ + buffer = TMALLOC(char, strlen(prev->li_line) + strlen(s) + 2); + (void) sprintf(buffer, "%s %s", prev->li_line, s + 1); + + s = prev->li_line; + prev->li_line = buffer; + prev->li_next = working->li_next; + working->li_next = NULL; + if (prev->li_actual) { + struct line *end; + for (end = prev->li_actual; end->li_next; end = end->li_next) + ; + end->li_next = working; + tfree(s); + } else { + prev->li_actual = xx_new_line(working, s, prev->li_linenum, 0); + } + working = prev->li_next; + break; + + default: /* regular one-line card */ + prev = working; + working = working->li_next; + break; + } + } +} + + +/* + * search for `=' assignment operator + * take care of `!=' `<=' `==' and `>=' + */ + +static char * +find_assignment(char *str) +{ + char *p = str; + + while ((p = strchr(p, '=')) != NULL) { + + // check for equality '==' + if (p[1] == '=') { + p += 2; + continue; + } + + // check for '!=', '<=', '>=' + if (p > str) + if (p[-1] == '!' || p[-1] == '<' || p[-1] == '>') { + p += 1; continue; } - if (ciprefix(".lib", buffer)) { - - /* here we expect a libray section definition */ - /* library section definition: `.lib ' .. `.endl' */ - - char keep_char; - int section_idx; - char *s, *t; - - if (found_section) { - fprintf(stderr, "ERROR: .lib is missing .endl!\n"); - controlled_exit(EXIT_FAILURE); - } - - s = skip_non_ws(buffer); /* skip over .lib */ - while (isspace(*s) || isquote(*s)) - s++; /* advance past space chars */ - for (t = s; *t && !isspace(*t) && !isquote(*t); t++) - ; /* skip to end of word */ - keep_char = *t; - *t = '\0'; - - /* check if we remember this section having been referenced somewhere */ - section_idx = find_section(lib_idx, s); - - *t = keep_char; - - found_section = (section_idx >= 0); - - if (found_section) { - - struct line *c; - int line_number_lib; - - /* make the .lib of this library section definition a comment */ - *buffer = '*'; - - /* tmp_ptr is the line following the library section reference */ - tmp_ptr = section_ref[lib_idx][section_idx]->li_next; - - /* insert the section definition here, */ - /* just behind the remembered section reference */ - section_ref[lib_idx][section_idx]->li_next = working; - - /* renumber lines */ - line_number_lib = 1; - for (c = working; !ciprefix(".endl", c->li_line); c = c->li_next) { - c->li_linenum = line_number++; - c->li_linenum_orig = line_number_lib++; - } - c->li_linenum = line_number++; // renumber endl line - c->li_linenum_orig = line_number_lib++; - } - } - - next = working->li_next; - - /* drop this line in the current library file, if - * it is outside a library section definition - * or - * it is part of an unused library section definition - */ - - if (!found_section) { - tfree(working->li_line); - tfree(working); - } - - working = next; - } - - if (found_section) { - fprintf(stderr, "ERROR: .lib is missing .endl!\n"); - controlled_exit(EXIT_FAILURE); - } + return p; } - return line_number; + return NULL; } /*------------------------------------------------------------------------- - Read the entire input file and return a pointer to the first line of - the linked list of 'card' records in data. The pointer is stored in - *data. - Called from fcn inp_spsource() in inp.c to load circuit or command files. - Called from fcn com_alter_mod() in device.c to load model files. - Called from here to load .library or .include files. + Read the entire input file and return a pointer to the first line of + the linked list of 'card' records in data. The pointer is stored in + *data. + Called from fcn inp_spsource() in inp.c to load circuit or command files. + Called from fcn com_alter_mod() in device.c to load model files. + Called from here to load .library or .include files. + + Procedure: + read in all lines & put them in the struct cc + read next line + process .TITLE line + store contents in string new_title + process .lib lines + read file and library name, open file using fcn inp_pathopen() + read file contents and put into struct libraries[].deck, one entry per .lib line + process .inc lines + read file and library name, open file using fcn inp_pathopen() + read file contents and add lines to cc + make line entry lower case + allow for shell end of line continuation (\\) + add '+' to beginning of next line + add line entry to list cc + add '.global gnd' + add libraries + find library section + add lines + add .end card + strip end-of-line comments + make continuation lines a single line + *** end of processing for command files *** + start preparation of input deck for numparam + ... + debug printout to debug-out.txt + *-------------------------------------------------------------------------*/ - Procedure: - read in all lines & put them in the struct cc - read next line - process .TITLE line - store contents in string new_title - process .lib lines - read file and library name, open file using fcn inp_pathopen() - read file contents and put into struct library_deck[], one entry per .lib line - process .inc lines - read file and library name, open file using fcn inp_pathopen() - read file contents and add lines to cc - make line entry lower case - allow for shell end of line continuation (\\) - add '+' to beginning of next line - add line entry to list cc - add '.global gnd' - add libraries - find library section - add lines - add .end card - strip end-of-line comments - make continuation lines a single line -*** end of processing for command files *** - start preparation of input deck for numparam - ... - debug printout to debug-out.txt - *-------------------------------------------------------------------------*/ struct line * inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile) /* fp: in, pointer to file to be read, @@ -340,8 +419,8 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile intfile: in, TRUE if deck is generated from internal circarray */ { - struct line *end = NULL, *cc = NULL, *prev, *working, *newcard, *global_card; - char *buffer = NULL, c; + struct line *end = NULL, *cc = NULL, *working; + char *buffer = NULL; /* segfault fix */ #ifdef XSPICE char big_buff[5000]; @@ -352,21 +431,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile #endif char *new_title = NULL; int line_number = 1; /* sjb - renamed to avoid confusion with struct line */ - int line_number_orig = 1, line_number_inc = 1; - unsigned int no_braces = 0; /* number of '{' */ + int line_number_orig = 1; int cirlinecount = 0; /* length of circarray */ - size_t max_line_length; /* max. line length in input deck */ - - struct line *tmp_ptr1 = NULL; - bool found_end = FALSE, shell_eol_continuation = FALSE; if (call_depth == 0) { - num_subckt_w_params = 0; num_libraries = 0; - num_functions = 0; - global = NULL; found_end = FALSE; inp_compat_mode = ngspice_compat_mode(); } @@ -415,7 +486,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile } } - /* gtri - end - 12/12/90 */ + /* gtri - end - 12/12/90 */ #else buffer = readline(fp); if(!buffer) @@ -451,8 +522,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile s = skip_ws(s); /* advance past space chars */ /* only the last title line remains valid */ - if (new_title != NULL) - tfree(new_title); + tfree(new_title); new_title = copy(s); if ((s = strchr(new_title, '\n')) != NULL) *s = ' '; @@ -461,50 +531,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile /* now handle .lib statements */ if (ciprefix(".lib", buffer)) { - - char *y = NULL; /* filename */ - char *z = NULL; /* libname */ - char *s, *t; - - inp_stripcomments_line(buffer); - s = skip_non_ws(buffer); /* skip over .lib */ - - s = strdup(s); - - t = get_quoted_token(s, &y); - - if (!y) { - fprintf(cp_err, "Error: .lib filename missing\n"); - tfree(buffer); /* was allocated by readline() */ - controlled_exit(EXIT_FAILURE); - } - - t = get_quoted_token(t, &z); - - if (z && (inp_compat_mode == COMPATMODE_ALL || - inp_compat_mode == COMPATMODE_HS || - inp_compat_mode == COMPATMODE_NATIVE)) - { - /* here we have a */ - /* library section reference: `.lib ' */ - - if(!read_a_lib(y, call_depth, dir_name)) { - tfree(s); - tfree(buffer); - controlled_exit(EXIT_FAILURE); - } - - tfree(s); - - /* Make the .lib a comment */ - *buffer = '*'; - } else if (inp_compat_mode == COMPATMODE_PS) { + if (inp_compat_mode == COMPATMODE_PS) { /* compatibility mode, * this is neither a libray section definition nor a reference * interpret as old style * .lib (no lib name given) */ - fprintf(cp_err, "Warning: library name missing in line\n %s", buffer); + char *s = skip_non_ws(buffer); /* skip over .lib */ fprintf(cp_err, " File included as: .inc %s\n", s); memcpy(buffer, ".inc", 4); } @@ -518,6 +551,8 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile char *y = NULL; char *s, *t; + struct line *newcard; + inp_stripcomments_line(buffer); s = skip_non_ws(buffer); /* advance past non-space chars */ @@ -552,8 +587,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile newfp = inp_pathopen(big_buff2, "r"); if (!newfp) { perror(y); - if (copyy) - tfree(copyy); /* allocated by the cp_tildexpand() above */ + tfree(copyy); /* allocated by the cp_tildexpand() above */ fprintf(cp_err, "Error: .include statement failed.\n"); tfree(buffer); /* allocated by readline() above */ controlled_exit(EXIT_FAILURE); @@ -573,32 +607,29 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile (void) fclose(newfp); } - if (copyy) - tfree(copyy); /* allocated by the cp_tildexpand() above */ + tfree(copyy); /* allocated by the cp_tildexpand() above */ /* Make the .include a comment */ *buffer = '*'; - /* now check if this is the first pass (i.e. end points to null) */ - if (end) { /* end already exists */ - end->li_next = alloc(struct line); /* create next card */ - end = end->li_next; /* make end point to next card */ - } else { - end = cc = alloc(struct line); /* create the deck & end. cc will - point to beginning of deck, end to - the end */ + /* append `buffer' to the (cc, end) chain of decks */ + { + struct line *x = xx_new_line(NULL, copy(buffer), line_number, line_number); + + if (end) + end->li_next = x; + else + cc = x; + + end = x; + + line_number++; } - /* now fill out rest of struct end. */ - end->li_next = NULL; - end->li_error = NULL; - end->li_actual = NULL; - end->li_line = copy(buffer); - end->li_linenum = end->li_linenum_orig = line_number++; if (newcard) { + int line_number_inc = 1; end->li_next = newcard; /* Renumber the lines */ - line_number_inc = 1; for (end = newcard; end && end->li_next; end = end->li_next) { end->li_linenum = line_number++; end->li_linenum_orig = line_number_inc++; @@ -612,12 +643,26 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile } /* end of .include handling */ /* loop through 'buffer' until end is reached. Then test for - premature end. If premature end is reached, spew - error and zap the line. */ - if (!ciprefix("write", buffer)) { // exclude 'write' command so filename case preserved + premature end. If premature end is reached, spew + error and zap the line. */ + { char *s; - for (s = buffer; *s && (*s != '\n'); s++) - *s = (char) tolower(*s); + + if ( !ciprefix("write", buffer) && + !ciprefix(".lib", buffer) && + !ciprefix("codemodel", buffer) && + !ciprefix("use", buffer) && + !ciprefix("load", buffer) + ) + { + for (s = buffer; *s && (*s != '\n'); s++) + *s = (char) tolower(*s); + } else { + // exclude some commands to preserve filename case + for (s = buffer; *s && (*s != '\n'); s++) + ; + } + if (!*s) { // fprintf(cp_err, "Warning: premature EOF\n"); } @@ -629,7 +674,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile /* find the true .end command out of .endc, .ends, .endl, .end (comments may follow) */ if (ciprefix(".end", buffer)) - if ((buffer[4] == '\0') || (isspace(buffer[4]))) { + if ((buffer[4] == '\0') || isspace(buffer[4])) { found_end = TRUE; *buffer = '*'; } @@ -644,22 +689,17 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile shell_eol_continuation = chk_for_line_continuation(buffer); - /* now check if this is the first pass (i.e. end points to null) */ - if (end) { /* end already exists */ - end->li_next = alloc(struct line); /* create next card */ - end = end->li_next; /* point to next card */ - } else { /* End doesn't exist. Create it. */ - end = cc = alloc(struct line); /* note that cc points to beginning - of deck, end to the end */ + { + struct line *x = xx_new_line(NULL, copy(buffer), line_number++, line_number_orig++); + + if (end) + end->li_next = x; + else + cc = x; + + end = x; } - /* now put buffer into li */ - end->li_next = NULL; - end->li_error = NULL; - end->li_actual = NULL; - end->li_line = copy(buffer); - end->li_linenum = line_number++; - end->li_linenum_orig = line_number_orig++; tfree(buffer); } /* end while ((buffer = readline(fp)) != NULL) */ @@ -667,31 +707,15 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile return NULL; if (call_depth == 0 && found_end == TRUE) { - struct line *prev; - if (global == NULL) { - global = TMALLOC(char, strlen(".global gnd") + 1); - sprintf(global, ".global gnd"); + cc->li_next = xx_new_line(cc->li_next, copy(".global gnd"), 1, 0); + + if (inp_compat_mode == COMPATMODE_ALL || + inp_compat_mode == COMPATMODE_HS || + inp_compat_mode == COMPATMODE_NATIVE) + { + /* process all library section references */ + expand_section_references(cc, call_depth, dir_name); } - global_card = alloc(struct line); - global_card->li_error = NULL; - global_card->li_actual = NULL; - global_card->li_line = global; - global_card->li_linenum = 1; - - prev = cc->li_next; - cc->li_next = global_card; - global_card->li_next = prev; - - inp_init_lib_data(); - collect_section_references(cc, NULL); - } - - /* - add libraries - */ - - if (call_depth == 0) { - line_number = expand_section_references(line_number); } /* @@ -700,96 +724,28 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile if (call_depth == 0) { if (found_end == TRUE) { - end->li_next = alloc(struct line); /* create next card */ - end = end->li_next; /* point to next card */ - - /* now put buffer into li */ - end->li_next = NULL; - end->li_error = NULL; - end->li_actual = NULL; - end->li_line = copy(".end"); - end->li_linenum = end->li_linenum_orig = line_number++; - end->li_linenum_orig = line_number_orig++; + struct line *x = xx_new_line(NULL, copy(".end"), line_number++, line_number_orig++); + end->li_next = x; + end = x; } } /* Replace first line with the new title, if available */ if (new_title != NULL) { - if (cc->li_line) tfree(cc->li_line); + tfree(cc->li_line); cc->li_line = new_title; } /* Now clean up li: remove comments & stitch together continuation lines. */ - working = cc->li_next; /* cc points to head of deck. Start with the - next card. */ /* sjb - strip or convert end-of-line comments. - This must be cone before stitching continuation lines. - If the line only contains an end-of-line comment then it is converted - into a normal comment with a '*' at the start. This will then get - stripped in the following code. */ - inp_stripcomments_deck(working); + This must be cone before stitching continuation lines. + If the line only contains an end-of-line comment then it is converted + into a normal comment with a '*' at the start. This will then get + stripped in the following code. */ + inp_stripcomments_deck(cc->li_next); - prev = NULL; - while (working) { - char *s; - - for (s = working->li_line; (c = *s) != '\0' && c <= ' '; s++) - ; - -#ifdef TRACE - /* SDB debug statement */ - printf("In inp_readall, processing linked list element line = %d, s = %s . . . \n", working->li_linenum, s); -#endif - - switch (c) { - case '#': - case '$': - case '*': - case '\0': - /* this used to be commented out. Why? */ - /* prev = NULL; */ - working = working->li_next; /* for these chars, go to next card */ - break; - - case '+': /* handle continuation */ - if (!prev) { - working->li_error = copy("Illegal continuation line: ignored."); - working = working->li_next; - break; - } - - /* create buffer and write last and current line into it. */ - buffer = TMALLOC(char, strlen(prev->li_line) + strlen(s) + 2); - (void) sprintf(buffer, "%s %s", prev->li_line, s + 1); - - s = prev->li_line; - prev->li_line = buffer; - prev->li_next = working->li_next; - working->li_next = NULL; - if (prev->li_actual) { - for (end = prev->li_actual; end->li_next; end = end->li_next) - ; - end->li_next = working; - tfree(s); - } else { - newcard = alloc(struct line); - newcard->li_linenum = prev->li_linenum; - newcard->li_line = s; - newcard->li_next = working; - newcard->li_error = NULL; - newcard->li_actual = NULL; - prev->li_actual = newcard; - } - working = prev->li_next; - break; - - default: /* regular one-line card */ - prev = working; - working = working->li_next; - break; - } - } + inp_stitch_continuation_lines(cc->li_next); /* The following processing of an input file is not required for command files like spinit or .spiceinit, so return command files here. */ @@ -798,30 +754,41 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile working = cc->li_next; - inp_fix_for_numparam(working); - inp_remove_excess_ws(working); - if (call_depth == 0) { + unsigned int no_braces; /* number of '{' */ + size_t max_line_length; /* max. line length in input deck */ + + struct line *tmp_ptr1; + + struct names *subckt_w_params = new_names(); + + inp_fix_for_numparam(subckt_w_params, working); + inp_remove_excess_ws(working); + comment_out_unused_subckt_models(working, line_number); line_number = inp_split_multi_param_lines(working, line_number); inp_fix_macro_param_func_paren_io(working); inp_fix_ternary_operator(working); - inp_grab_func(working); - inp_expand_macros_in_func(); - inp_expand_macros_in_deck(working); + inp_expand_macros_in_deck(NULL, working); inp_fix_param_values(working); /* get end card as last card in list; end card pntr does not appear to always be correct at this point */ - for (newcard = working; newcard != NULL; newcard = newcard->li_next) - end = newcard; + if (working) + for (end = working; end->li_next; end = end->li_next) + ; +// tprint(cc); + inp_reorder_params(subckt_w_params, working, cc, end); + + inp_fix_inst_calls_for_numparam(subckt_w_params, working); + + delete_names(subckt_w_params); + subckt_w_params = NULL; - inp_reorder_params(working, cc, end); - inp_fix_inst_calls_for_numparam(working); inp_fix_gnd_name(working); inp_chk_for_multi_in_vcvs(working, &line_number); @@ -838,44 +805,46 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile working = cc->li_next; /* B source numparam compatibility transformation */ inp_bsource_compat(working); + inp_dot_if(working); } inp_add_series_resistor(working); - } - /* get max. line length and number of lines in input deck, - and renumber the lines, - count the number of '{' per line as an upper estimate of the number - of parameter substitutions in a line*/ - dynmaxline = 0; - max_line_length = 0; - for (tmp_ptr1 = cc; tmp_ptr1 != NULL; tmp_ptr1 = tmp_ptr1->li_next) { - char *s; - unsigned int braces_per_line = 0; - /* count number of lines */ - dynmaxline++; - /* renumber the lines of the processed input deck */ - tmp_ptr1->li_linenum = dynmaxline; - if (max_line_length < strlen(tmp_ptr1->li_line)) - max_line_length = strlen(tmp_ptr1->li_line); - /* count '{' */ - for (s = tmp_ptr1->li_line; *s; s++) - if (*s == '{') - braces_per_line++; - if (no_braces < braces_per_line) - no_braces = braces_per_line; - } + /* get max. line length and number of lines in input deck, + and renumber the lines, + count the number of '{' per line as an upper estimate of the number + of parameter substitutions in a line*/ + dynmaxline = 0; + max_line_length = 0; + no_braces = 0; + for (tmp_ptr1 = cc; tmp_ptr1; tmp_ptr1 = tmp_ptr1->li_next) { + char *s; + unsigned int braces_per_line = 0; + /* count number of lines */ + dynmaxline++; + /* renumber the lines of the processed input deck */ + tmp_ptr1->li_linenum = dynmaxline; + if (max_line_length < strlen(tmp_ptr1->li_line)) + max_line_length = strlen(tmp_ptr1->li_line); + /* count '{' */ + for (s = tmp_ptr1->li_line; *s; s++) + if (*s == '{') + braces_per_line++; + if (no_braces < braces_per_line) + no_braces = braces_per_line; + } - if (ft_ngdebug) { - /*debug: print into file*/ - FILE *fd = fopen("debug-out.txt", "w"); - struct line *t; - for (t = cc; t; t = t->li_next) - fprintf(fd, "%d %d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); - fclose(fd); + if (ft_ngdebug) { + /*debug: print into file*/ + FILE *fd = fopen("debug-out.txt", "w"); + struct line *t; + for (t = cc; t; t = t->li_next) + fprintf(fd, "%d %d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); + fclose(fd); - fprintf(stdout, "max line length %d, max subst. per line %d, number of lines %d\n", - (int) max_line_length, no_braces, dynmaxline); + fprintf(stdout, "max line length %d, max subst. per line %d, number of lines %d\n", + (int) max_line_length, no_braces, dynmaxline); + } } return cc; @@ -886,7 +855,8 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile Look up the variable sourcepath and try everything in the list in order if the file isn't in . and it isn't an abs path name. For MS Windows: First try the path of the source file. - *-------------------------------------------------------------------------*/ + *-------------------------------------------------------------------------*/ + FILE * inp_pathopen(char *name, char *mode) { @@ -896,11 +866,12 @@ inp_pathopen(char *name, char *mode) #if defined(HAS_WINGUI) char buf2[BSIZE_SP]; + /* search in the path where the source (input) file has been found, but only if "name" is just a file name */ if (!strchr(name, DIR_TERM) && !strchr(name, DIR_TERM_LINUX) && cp_getvar("sourcefile", CP_STRING, buf2)) { /* If pathname is found, get path. - (char *dirname(const char *name) might have been used here) */ + (char *dirname(const char *name) might have been used here) */ if (substring(DIR_PATHSEP, buf2) || substring(DIR_PATHSEP_LINUX, buf2)) { int i, j = 0; for (i = 0; i < BSIZE_SP-1; i++) { @@ -917,6 +888,7 @@ inp_pathopen(char *name, char *mode) if ((fp = fopen(buf2, mode)) != NULL) return (fp); } + /* If this is an abs pathname, or there is no sourcepath var, just * do an fopen. */ @@ -925,15 +897,16 @@ inp_pathopen(char *name, char *mode) return (fopen(name, mode)); #else - /* If this is an abs pathname, or there is no sourcepath var, just * do an fopen. */ if (strchr(name, DIR_TERM) || !cp_getvar("sourcepath", CP_LIST, &v)) return (fopen(name, mode)); + #endif - while (v) { + for (; v; v = v->va_next) { + switch (v->va_type) { case CP_STRING: cp_wstrip(v->va_string); @@ -945,18 +918,20 @@ inp_pathopen(char *name, char *mode) case CP_REAL: /* This is foolish */ (void) sprintf(buf, "%g%s%s", v->va_real, DIR_PATHSEP, name); break; - default: { + default: fprintf(stderr, "ERROR: enumeration value `CP_BOOL' or `CP_LIST' not handled in inp_pathopen\nAborting...\n"); controlled_exit(EXIT_FAILURE); + break; } - } + if ((fp = fopen(buf, mode)) != NULL) return (fp); - v = v->va_next; } + return (NULL); } + /*-------------------------------------------------------------------------* * This routine reads a line (of arbitrary length), up to a '\n' or 'EOF' * * and returns a pointer to the resulting null terminated string. * @@ -964,6 +939,7 @@ inp_pathopen(char *name, char *mode) * From: jason@ucbopal.BERKELEY.EDU (Jason Venner) * * Newsgroups: net.sources * *-------------------------------------------------------------------------*/ + #define STRGROW 256 static char * @@ -974,51 +950,56 @@ readline(FILE *fd) char *strptr; int strlen; - strptr = NULL; strlen = 0; memlen = STRGROW; strptr = TMALLOC(char, memlen); memlen -= 1; /* Save constant -1's in while loop */ + while ((c = getc(fd)) != EOF) { + if (strlen == 0 && (c == '\t' || c == ' ')) /* Leading spaces away */ continue; - strptr[strlen] = (char) c; - strlen++; + + strptr[strlen++] = (char) c; + if (strlen >= memlen) { memlen += STRGROW; if ((strptr = TREALLOC(char, strptr, memlen + 1)) == NULL) return (NULL); } + if (c == '\n') break; } + if (!strlen) { tfree(strptr); return (NULL); } + // strptr[strlen] = '\0'; /* Trim the string */ strptr = TREALLOC(char, strptr, strlen + 1); strptr[strlen] = '\0'; + return (strptr); } /* replace "gnd" by " 0 " Delimiters of gnd may be ' ' or ',' or '(' or ')' */ -static void -inp_fix_gnd_name(struct line *deck) -{ - struct line *c = deck; - char *gnd; - while (c != NULL) { - gnd = c->li_line; +static void +inp_fix_gnd_name(struct line *c) +{ + for (; c; c = c->li_next) { + + char *gnd = c->li_line; + // if there is a comment or no gnd, go to next line - if ((*gnd == '*') || (strstr(gnd, "gnd") == NULL)) { - c = c->li_next; + if ((*gnd == '*') || !strstr(gnd, "gnd")) continue; - } + // replace "?gnd?" by "? 0 ?", ? being a ' ' ',' '(' ')'. while ((gnd = strstr(gnd, "gnd")) != NULL) { if ((isspace(gnd[-1]) || gnd[-1] == '(' || gnd[-1] == ',') && @@ -1027,39 +1008,21 @@ inp_fix_gnd_name(struct line *deck) } gnd += 3; } + // now remove the extra white spaces around 0 c->li_line = inp_remove_ws(c->li_line); - c = c->li_next; } } -static struct line* -create_new_card(char *card_str, int *line_number) { - char *str = strdup(card_str); - struct line *newcard = alloc(struct line); - - newcard->li_line = str; - newcard->li_linenum = *line_number; - newcard->li_error = NULL; - newcard->li_actual = NULL; - - *line_number = *line_number + 1; - - return newcard; -} - static void -inp_chk_for_multi_in_vcvs(struct line *deck, int *line_number) +inp_chk_for_multi_in_vcvs(struct line *c, int *line_number) { - struct line *c, *a_card, *model_card, *next_card; - char *line, *bool_ptr, *str_ptr1, *str_ptr2, keep, *comma_ptr, *xy_values1[5], *xy_values2[5]; - char *node_str, *ctrl_node_str, *xy_str1, *model_name, *fcn_name; - char big_buf[1000]; - int xy_count1 = 0, xy_count2 = 0, skip_control = 0; + int skip_control = 0; - for (c = deck; c != NULL; c = c->li_next) { - line = c->li_line; + for (; c; c = c->li_next) { + + char *line = c->li_line; /* there is no e source inside .control ... .endc */ if (ciprefix(".control", line)) { @@ -1073,43 +1036,49 @@ inp_chk_for_multi_in_vcvs(struct line *deck, int *line_number) } if (*line == 'e') { + + char *bool_ptr; + if ((bool_ptr = strstr(line, "nand(")) != NULL || (bool_ptr = strstr(line, "and(")) != NULL || (bool_ptr = strstr(line, "nor(")) != NULL || (bool_ptr = strstr(line, "or(")) != NULL) { + struct line *a_card, *model_card, *next_card; + char *str_ptr1, *str_ptr2, keep, *comma_ptr, *xy_values1[5], *xy_values2[5]; + char *node_str, *ctrl_node_str, *xy_str1, *model_name, *fcn_name; + char big_buf[1000]; + int xy_count1, xy_count2; + str_ptr1 = skip_non_ws(line); model_name = copy_substring(line, str_ptr1); str_ptr1 = skip_ws(str_ptr1); - str_ptr2 = skip_back_ws(bool_ptr - 1) + 1; + str_ptr2 = skip_back_ws(bool_ptr); keep = *str_ptr2; *str_ptr2 = '\0'; node_str = strdup(str_ptr1); *str_ptr2 = keep; - str_ptr1 = bool_ptr + 1; - while (*str_ptr1 != '(') - str_ptr1++; + str_ptr1 = bool_ptr; + while (*++str_ptr1 != '(') + ; fcn_name = copy_substring(bool_ptr, str_ptr1); str_ptr1 = strchr(str_ptr1, ')'); - comma_ptr = str_ptr2 = strchr(line, ','); - if ((str_ptr1 == NULL)|| (str_ptr1 == NULL)) { + comma_ptr = strchr(line, ','); + if (!str_ptr1 || !comma_ptr) { fprintf(stderr, "ERROR: mal formed line: %s\n", line); controlled_exit(EXIT_FAILURE); } - str_ptr2 = skip_back_ws(str_ptr2 - 1); str_ptr1 = skip_ws(str_ptr1 + 1); - if (*str_ptr2 == '}') { - while (*str_ptr2 != '{') - str_ptr2--; - xy_str1 = str_ptr2; - str_ptr2 = skip_back_ws(str_ptr2 - 1) + 1; + xy_str1 = skip_back_ws(comma_ptr); + if (xy_str1[-1] == '}') { + while (*--xy_str1 != '{') + ; } else { - str_ptr2 = skip_back_non_ws(str_ptr2); - xy_str1 = str_ptr2 + 1; - str_ptr2 = skip_back_ws(str_ptr2) + 1; + xy_str1 = skip_back_non_ws(xy_str1); } + str_ptr2 = skip_back_ws(xy_str1); keep = *str_ptr2; *str_ptr2 = '\0'; ctrl_node_str = strdup(str_ptr1); @@ -1117,9 +1086,8 @@ inp_chk_for_multi_in_vcvs(struct line *deck, int *line_number) str_ptr1 = skip_ws(comma_ptr + 1); if (*str_ptr1 == '{') { - while (*str_ptr1 != '}') - str_ptr1++; - str_ptr1++; + while (*str_ptr1++ != '}') + ; } else { str_ptr1 = skip_non_ws(str_ptr1); } @@ -1137,13 +1105,13 @@ inp_chk_for_multi_in_vcvs(struct line *deck, int *line_number) sprintf(big_buf, "%s %%vd[ %s ] %%vd( %s ) %s", model_name, ctrl_node_str, node_str, model_name); - a_card = create_new_card(big_buf, line_number); + a_card = xx_new_line(NULL, copy(big_buf), *(line_number)++, 0); *a_card->li_line = 'a'; sprintf(big_buf, ".model %s multi_input_pwl ( x = [%s %s] y = [%s %s] model = \"%s\" )", - model_name, xy_values1[0], xy_values2[0], - xy_values1[1], xy_values2[1], fcn_name); - model_card = create_new_card(big_buf, line_number); + model_name, xy_values1[0], xy_values2[0], + xy_values1[1], xy_values2[1], fcn_name); + model_card = xx_new_line(NULL, copy(big_buf), (*line_number)++, 0); tfree(model_name); tfree(node_str); @@ -1168,96 +1136,83 @@ inp_chk_for_multi_in_vcvs(struct line *deck, int *line_number) static void inp_add_control_section(struct line *deck, int *line_number) { - struct line *c, *newcard, *prev_card = NULL; + struct line *c, *prev_card = NULL; bool found_control = FALSE, found_run = FALSE; bool found_end = FALSE; char *op_line = NULL, rawfile[1000], *line; - for (c = deck; c != NULL; c = c->li_next) { + for (c = deck; c; c = c->li_next) { + if (*c->li_line == '*') continue; + if (ciprefix(".op ", c->li_line)) { *c->li_line = '*'; op_line = c->li_line + 1; } + if (ciprefix(".end", c->li_line)) found_end = TRUE; + if (found_control && ciprefix("run", c->li_line)) found_run = TRUE; if (ciprefix(".control", c->li_line)) found_control = TRUE; + if (ciprefix(".endc", c->li_line)) { found_control = FALSE; if (!found_run) { - newcard = create_new_card("run", line_number); - prev_card->li_next = newcard; - newcard->li_next = c; - prev_card = newcard; - found_run = TRUE; + prev_card->li_next = xx_new_line(c, copy("run"), (*line_number)++, 0); + prev_card = prev_card->li_next; + found_run = TRUE; } + if (cp_getvar("rawfile", CP_STRING, rawfile)) { line = TMALLOC(char, strlen("write") + strlen(rawfile) + 2); sprintf(line, "write %s", rawfile); - newcard = create_new_card(line, line_number); - prev_card->li_next = newcard; - newcard->li_next = c; - prev_card = newcard; - tfree(line); + prev_card->li_next = xx_new_line(c, line, (*line_number)++, 0); + prev_card = prev_card->li_next; } } + prev_card = c; } + // check if need to add control section if (!found_run && found_end) { - prev_card = deck->li_next; - newcard = create_new_card(".endc", line_number); - deck->li_next = newcard; - newcard->li_next = prev_card; + + deck->li_next = xx_new_line(deck->li_next, copy(".endc"), (*line_number)++, 0); if (cp_getvar("rawfile", CP_STRING, rawfile)) { line = TMALLOC(char, strlen("write") + strlen(rawfile) + 2); sprintf(line, "write %s", rawfile); - prev_card = deck->li_next; - newcard = create_new_card(line, line_number); - deck->li_next = newcard; - newcard->li_next = prev_card; - tfree(line); - } - if (op_line != NULL) { - prev_card = deck->li_next; - newcard = create_new_card(op_line, line_number); - deck->li_next = newcard; - newcard->li_next = prev_card; + deck->li_next = xx_new_line(deck->li_next, line, (*line_number)++, 0); } - prev_card = deck->li_next; - newcard = create_new_card("run", line_number); - deck->li_next = newcard; - newcard->li_next = prev_card; + if (op_line) + deck->li_next = xx_new_line(deck->li_next, copy(op_line), (*line_number)++, 0); - prev_card = deck->li_next; - newcard = create_new_card(".control", line_number); - deck->li_next = newcard; - newcard->li_next = prev_card; + deck->li_next = xx_new_line(deck->li_next, copy("run"), (*line_number)++, 0); + + deck->li_next = xx_new_line(deck->li_next, copy(".control"), (*line_number)++, 0); } } // look for shell-style end-of-line continuation '\\' + static bool chk_for_line_continuation(char *line) { - char *ptr = line + strlen(line) - 1; - if (*line != '*' && *line != '$') { - while (ptr >= line && *ptr && isspace(*ptr)) - ptr--; - if ((ptr-1) >= line && *ptr == '\\' && *(ptr-1) && *(ptr-1) == '\\') { - *ptr = ' '; - *(ptr-1) = ' '; + char *ptr = skip_back_ws_(strchr(line, '\0'), line); + + if ((ptr - 2 >= line) && (ptr[-1] == '\\') && (ptr[-2] == '\\')) { + ptr[-1] = ' '; + ptr[-2] = ' '; return TRUE; } } @@ -1275,13 +1230,11 @@ chk_for_line_continuation(char *line) // .param func1(x,y) = {x*y} --> .func func1(x,y) {x*y} static void -inp_fix_macro_param_func_paren_io(struct line *begin_card) +inp_fix_macro_param_func_paren_io(struct line *card) { - struct line *card; char *str_ptr, *new_str; - bool is_func = FALSE; - for (card = begin_card; card != NULL; card = card->li_next) { + for (; card; card = card->li_next) { if (*card->li_line == '*') continue; @@ -1311,7 +1264,7 @@ inp_fix_macro_param_func_paren_io(struct line *begin_card) } if (*str_ptr == '(') { *str_ptr = ' '; - while (*str_ptr && *str_ptr != '\0') { + while (*str_ptr != '\0') { if (*str_ptr == ')') { *str_ptr = ' '; break; @@ -1321,8 +1274,9 @@ inp_fix_macro_param_func_paren_io(struct line *begin_card) card->li_line = inp_remove_ws(card->li_line); /* remove the extra white spaces just introduced */ } } - is_func = FALSE; + if (ciprefix(".param", card->li_line)) { + bool is_func = FALSE; str_ptr = skip_non_ws(card->li_line); // skip over .param str_ptr = skip_ws(str_ptr); while (!isspace(*str_ptr) && *str_ptr != '=') { @@ -1355,15 +1309,16 @@ get_instance_subckt(char *line) // see if instance has parameters if (equal_ptr) { - end_ptr = skip_back_ws(equal_ptr - 1); - end_ptr = skip_back_non_ws(end_ptr) + 1; + end_ptr = skip_back_ws_(equal_ptr, line); + end_ptr = skip_back_non_ws_(end_ptr, line); } else { - end_ptr = line + strlen(line); + end_ptr = strchr(line, '\0'); } - end_ptr = skip_back_ws(end_ptr - 1) + 1; + end_ptr = skip_back_ws_(end_ptr, line); + + inst_name_ptr = skip_back_non_ws_(end_ptr, line); - inst_name_ptr = skip_back_non_ws(end_ptr - 1) + 1; return copy_substring(inst_name_ptr, end_ptr); } @@ -1377,6 +1332,7 @@ get_subckt_model_name(char *line) name = skip_ws(name); end_ptr = skip_non_ws(name); + return copy_substring(name, end_ptr); } @@ -1394,6 +1350,7 @@ get_model_name(char *line, int num_terminals) beg_ptr = skip_non_ws(beg_ptr); beg_ptr = skip_ws(beg_ptr); } + if (*line == 'r') /* special dealing for r models */ if ((*beg_ptr == '+') || (*beg_ptr == '-') || isdigit(*beg_ptr)) { /* looking for a value before model */ beg_ptr = skip_non_ws(beg_ptr); /* skip the value */ @@ -1401,6 +1358,7 @@ get_model_name(char *line, int num_terminals) } end_ptr = skip_non_ws(beg_ptr); + return copy_substring(beg_ptr, end_ptr); } @@ -1408,15 +1366,18 @@ get_model_name(char *line, int num_terminals) static char* get_model_type(char *line) { - char *model_type, *beg_ptr; - if (!(ciprefix(".model", line))) + char *beg_ptr; + + if (!ciprefix(".model", line)) return NULL; + beg_ptr = skip_non_ws(line); /* eat .model */ beg_ptr = skip_ws(beg_ptr); + beg_ptr = skip_non_ws(beg_ptr); /* eat model name */ beg_ptr = skip_ws(beg_ptr); - model_type = gettok(&beg_ptr); - return model_type; + + return gettok(&beg_ptr); } @@ -1425,25 +1386,27 @@ get_adevice_model_name(char *line) { char *ptr_end, *ptr_beg; - ptr_end = skip_back_ws(line + strlen(line) - 1) + 1; - ptr_beg = skip_back_non_ws(ptr_end - 1) + 1; + ptr_end = skip_back_ws_(strchr(line, '\0'), line); + ptr_beg = skip_back_non_ws_(ptr_end, line); + return copy_substring(ptr_beg, ptr_end); } static void get_subckts_for_subckt(struct line *start_card, char *subckt_name, - char *used_subckt_names[], int *num_used_subckt_names, - char *used_model_names[], int *num_used_model_names, - bool has_models) + char *used_subckt_names[], int *num_used_subckt_names, + char *used_model_names[], int *num_used_model_names, + bool has_models) { struct line *card; - char *line = NULL, *curr_subckt_name, *inst_subckt_name, *model_name, *new_names[100]; + char *curr_subckt_name, *inst_subckt_name, *model_name, *new_names[100]; bool found_subckt = FALSE, have_subckt = FALSE, found_model = FALSE; int i, num_terminals = 0, tmp_cnt = 0; - for (card = start_card; card != NULL; card = card->li_next) { - line = card->li_line; + for (card = start_card; card; card = card->li_next) { + + char *line = card->li_line; if (*line == '*') continue; @@ -1459,6 +1422,7 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, tfree(curr_subckt_name); } + if (found_subckt) { if (*line == 'x') { inst_subckt_name = get_instance_subckt(line); @@ -1468,7 +1432,7 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, have_subckt = TRUE; if (!have_subckt) { new_names[tmp_cnt++] = used_subckt_names[*num_used_subckt_names] = inst_subckt_name; - *num_used_subckt_names = *num_used_subckt_names + 1; + *num_used_subckt_names += 1; } else { tfree(inst_subckt_name); } @@ -1480,7 +1444,7 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, found_model = TRUE; if (!found_model) { used_model_names[*num_used_model_names] = model_name; - *num_used_model_names = *num_used_model_names + 1; + *num_used_model_names += 1; } else { tfree(model_name); } @@ -1492,20 +1456,20 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, tmp_name1 = tmp_name = model_name = get_model_name(line, num_terminals); if (isalpha(*model_name) || - /* first character is digit, second is alpha, third is digit, - e.g. 1N4002 */ - ((strlen(model_name) > 2) && isdigit(*tmp_name) && - isalpha(*(++tmp_name)) && isdigit(*(++tmp_name))) || - /* first character is is digit, second is alpha, third is alpha, fourth is digit - e.g. 2SK456 */ - ((strlen(model_name) > 3) && isdigit(*tmp_name1) && isalpha(*(++tmp_name1)) && - isalpha(*(++tmp_name1)) && isdigit(*(++tmp_name1)))) { + /* first character is digit, second is alpha, third is digit, + e.g. 1N4002 */ + ((strlen(model_name) > 2) && isdigit(*tmp_name) && + isalpha(*(++tmp_name)) && isdigit(*(++tmp_name))) || + /* first character is is digit, second is alpha, third is alpha, fourth is digit + e.g. 2SK456 */ + ((strlen(model_name) > 3) && isdigit(*tmp_name1) && isalpha(*(++tmp_name1)) && + isalpha(*(++tmp_name1)) && isdigit(*(++tmp_name1)))) { found_model = FALSE; for (i = 0; i < *num_used_model_names; i++) if (strcmp(used_model_names[i], model_name) == 0) found_model = TRUE; if (!found_model) { used_model_names[*num_used_model_names] = model_name; - *num_used_model_names = *num_used_model_names + 1; + *num_used_model_names += 1; } else { tfree(model_name); } @@ -1516,16 +1480,18 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, } } } + // now make recursive call on instances just found above for (i = 0; i < tmp_cnt; i++) get_subckts_for_subckt(start_card, new_names[i], used_subckt_names, num_used_subckt_names, - used_model_names, num_used_model_names, has_models); + used_model_names, num_used_model_names, has_models); } /* check if current token matches model bin name -- .[0-9]+ - */ +*/ + static bool model_bin_match(char *token, char *model_name) { @@ -1553,24 +1519,26 @@ model_bin_match(char *token, char *model_name) iterate through the deck and comment out unused subckts, models (don't want to waste time processing everything) also comment out .param lines with no parameters defined - */ +*/ + static void comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) { struct line *card; - char **used_subckt_names, **used_model_names, *line = NULL, *subckt_name, *model_name; + char **used_subckt_names, **used_model_names, *subckt_name, *model_name; int num_used_subckt_names = 0, num_used_model_names = 0, i = 0, num_terminals = 0, tmp_cnt = 0; bool processing_subckt = FALSE, found_subckt = FALSE, remove_subckt = FALSE, found_model = FALSE, has_models = FALSE; int skip_control = 0, nested_subckt = 0; /* generate arrays of *char for subckt or model names. Start - with 1000, but increase, if number of lines in deck is larger */ + with 1000, but increase, if number of lines in deck is larger */ if (no_of_lines < 1000) no_of_lines = 1000; + used_subckt_names = TMALLOC(char*, no_of_lines); used_model_names = TMALLOC(char*, no_of_lines); - for (card = start_card; card != NULL; card = card->li_next) { + for (card = start_card; card; card = card->li_next) { if (ciprefix(".model", card->li_line)) has_models = TRUE; if (ciprefix(".cmodel", card->li_line)) @@ -1579,8 +1547,9 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) *card->li_line = '*'; } - for (card = start_card; card != NULL; card = card->li_next) { - line = card->li_line; + for (card = start_card; card; card = card->li_next) { + + char *line = card->li_line; if (*line == '*') continue; @@ -1624,8 +1593,8 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) tfree(model_name); } else if (has_models) { /* This is a preliminary version, until we have found a reliable - method to detect the model name out of the input line (Many - options have to be taken into account.). */ + method to detect the model name out of the input line (Many + options have to be taken into account.). */ num_terminals = get_number_terminals(line); if (num_terminals != 0) { bool model_ok = FALSE; @@ -1635,18 +1604,18 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) if (isalpha(*model_name)) model_ok = TRUE; /* first character is digit, second is alpha, third is digit, - e.g. 1N4002 */ + e.g. 1N4002 */ else if ((strlen(model_name) > 2) && isdigit(*tmp_name) && isalpha(*(++tmp_name)) && isdigit(*(++tmp_name))) model_ok = TRUE; /* first character is is digit, second is alpha, third is alpha, fourth is digit - e.g. 2SK456 */ + e.g. 2SK456 */ else if ((strlen(model_name) > 3) && isdigit(*tmp_name1) && isalpha(*(++tmp_name1)) && isalpha(*(++tmp_name1)) && isdigit(*(++tmp_name1))) model_ok = TRUE; /* Check if model has already been recognized, if not, add its name to - list used_model_names[i] */ + list used_model_names[i] */ if (model_ok) { found_model = FALSE; for (i = 0; i < num_used_model_names; i++) @@ -1663,6 +1632,7 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) } /* if (has_models) */ } /* if (!processing_subckt) */ } /* for loop through all cards */ + for (i = 0; i < tmp_cnt; i++) get_subckts_for_subckt (start_card, used_subckt_names[i], @@ -1670,8 +1640,9 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) used_model_names, &num_used_model_names, has_models); /* comment out any unused subckts, currently only at top level */ - for (card = start_card; card != NULL; card = card->li_next) { - line = card->li_line; + for (card = start_card; card; card = card->li_next) { + + char *line = card->li_line; if (*line == '*') continue; @@ -1688,6 +1659,7 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) } tfree(subckt_name); } + if (ciprefix(".ends", line) || ciprefix(".eom", line)) { nested_subckt--; if (remove_subckt) @@ -1695,6 +1667,7 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) if (nested_subckt == 0) remove_subckt = FALSE; } + if (remove_subckt) *line = '*'; else if (has_models && @@ -1717,13 +1690,13 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) model_bin_match(used_model_names[i], model_name)) found_model = TRUE; } - if (model_type) - tfree(model_type); + tfree(model_type); if (!found_model) *line = '*'; tfree(model_name); } } + for (i = 0; i < num_used_subckt_names; i++) tfree(used_subckt_names[i]); for (i = 0; i < num_used_model_names; i++) @@ -1735,6 +1708,7 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) /* replace ternary operator ? : by fcn ternary_fcn() in .param, .func, and .meas lines, if all is FALSE, for all lines if all is TRUE */ + static char* inp_fix_ternary_operator_str(char *line, bool all) { @@ -1753,12 +1727,12 @@ inp_fix_ternary_operator_str(char *line, bool all) else str_ptr = strchr(line, ')'); - if ((str_ptr == NULL) && all == FALSE) { + if (!str_ptr && all == FALSE) { fprintf(stderr, "ERROR: mal formed .param, .func or .meas line:\n %s\n", line); controlled_exit(EXIT_FAILURE); } - if ((str_ptr == NULL) && all == TRUE) { + if (!str_ptr && all == TRUE) { fprintf(stderr, "ERROR: mal formed expression in line:\n %s\n", line); fprintf(stderr, " We need parentheses around 'if' clause and nested ternary functions\n"); fprintf(stderr, " like: Rtern4 1 0 '(ut > 0.7) ? 2k : ((ut < 0.3) ? 500 : 1k)'\n"); @@ -1772,12 +1746,13 @@ inp_fix_ternary_operator_str(char *line, bool all) return line; } + all = TRUE; // get conditional question = strchr(str_ptr, '?'); - str_ptr2 = skip_back_ws(question - 1); - if (*str_ptr2 == ')') { + str_ptr2 = skip_back_ws(question); + if (str_ptr2[-1] == ')') { count = 1; - str_ptr = str_ptr2; + str_ptr = str_ptr2 - 1; while ((count != 0) && (str_ptr != line)) { str_ptr--; if (*str_ptr == '(') @@ -1786,7 +1761,6 @@ inp_fix_ternary_operator_str(char *line, bool all) count++; } } - str_ptr2++; keep = *str_ptr2; *str_ptr2 = '\0'; conditional = strdup(str_ptr); @@ -1822,14 +1796,13 @@ inp_fix_ternary_operator_str(char *line, bool all) fprintf(stderr, "ERROR: problem parsing ternary string (finding ':') %s!\n", line); controlled_exit(EXIT_FAILURE); } - str_ptr2 = skip_back_ws(colon - 1); + str_ptr2 = skip_back_ws(colon); } else if ((colon = strchr(str_ptr, ':')) != NULL) { - str_ptr2 = skip_back_ws(colon - 1); + str_ptr2 = skip_back_ws(colon); } else { fprintf(stderr, "ERROR: problem parsing ternary string (missing ':') %s!\n", line); controlled_exit(EXIT_FAILURE); } - str_ptr2++; keep = *str_ptr2; *str_ptr2 = '\0'; if_str = inp_fix_ternary_operator_str(strdup(str_ptr), all); @@ -1858,6 +1831,8 @@ inp_fix_ternary_operator_str(char *line, bool all) fprintf(stderr, "ERROR: problem parsing ternary line %s!\n", line); controlled_exit(EXIT_FAILURE); } + if (*str_ptr2 == '\0') + str_ptr2--; else_str = inp_fix_ternary_operator_str(copy_substring(str_ptr, str_ptr2), all); if (*str_ptr2 != '}') end_str = inp_fix_ternary_operator_str(strdup(str_ptr2+1), all); @@ -1894,38 +1869,38 @@ inp_fix_ternary_operator_str(char *line, bool all) tfree(conditional); tfree(if_str); tfree(else_str); - if (beg_str != NULL) - tfree(beg_str); - if (end_str != NULL) - tfree(end_str); + tfree(beg_str); + tfree(end_str); return new_str; } static void -inp_fix_ternary_operator(struct line *start_card) +inp_fix_ternary_operator(struct line *card) { - struct line *card; - char *line; bool found_control = FALSE; - for (card = start_card; card != NULL; card = card->li_next) { - line = card->li_line; + for (; card; card = card->li_next) { + + char *line = card->li_line; + + if (*line == '*') + continue; /* exclude replacement of ternary function between .control and .endc */ if (ciprefix(".control", line)) found_control = TRUE; if (ciprefix(".endc", line)) found_control = FALSE; + if (found_control) continue; /* ternary operator for B source done elsewhere */ if (*line == 'B' || *line == 'b') continue; - if (*line == '*') - continue; + /* .param, .func, and .meas lines handled here (2nd argument FALSE) */ if (strchr(line, '?') && strchr(line, ':')) card->li_line = inp_fix_ternary_operator_str(line, FALSE); @@ -1934,9 +1909,10 @@ inp_fix_ternary_operator(struct line *start_card) /*-------------------------------------------------------------------------* - removes " " quotes, returns lower case letters, - replaces non-printable characterss with '_' * - *-------------------------------------------------------------------------*/ + removes " " quotes, returns lower case letters, + replaces non-printable characterss with '_' * + *-------------------------------------------------------------------------*/ + void inp_casefix(char *string) { @@ -1968,13 +1944,10 @@ inp_casefix(char *string) /* Strip all end-of-line comments from a deck */ static void -inp_stripcomments_deck(struct line *deck) +inp_stripcomments_deck(struct line *c) { - struct line *c = deck; - while (c != NULL) { + for (; c; c = c->li_next) inp_stripcomments_line(c->li_line); - c = c->li_next; - } } @@ -1993,10 +1966,11 @@ inp_stripcomments_deck(struct line *deck) * Lines that contain only an end-of-line comment with or without leading white * space are also allowed. - If there is only white space before the end-of-line comment the - the whole line is converted to a normal comment line (i.e. one that - begins with a '*'). - BUG: comment characters in side of string literals are not ignored. */ + If there is only white space before the end-of-line comment the + the whole line is converted to a normal comment line (i.e. one that + begins with a '*'). + BUG: comment characters in side of string literals are not ignored. */ + static void inp_stripcomments_line(char *s) { @@ -2027,7 +2001,7 @@ inp_stripcomments_line(char *s) return; } - if (d>s) { + if (d > s) { d--; /* d now points to character just before comment */ @@ -2059,7 +2033,7 @@ inp_change_quotes(char *s) { bool first_quote = FALSE; - while (*s) { + for (; *s; s++) if (*s == '\'') { if (first_quote == FALSE) { *s = '{'; @@ -2069,16 +2043,39 @@ inp_change_quotes(char *s) first_quote = FALSE; } } - s++; +} + + +static void +add_name(struct names *p, char *name) +{ + if (p->num_names >= N_SUBCKT_W_PARAMS) { + fprintf(stderr, "ERROR, N_SUBCKT_W_PARMS overflow\n"); + controlled_exit(EXIT_FAILURE); } + + p->names[p->num_names++] = name; +} + + +static char ** +find_name(struct names *p, char *name) +{ + int i; + + for (i = 0; i < p->num_names; i++) + if (strcmp(p->names[i], name) == 0) + return & p->names[i]; + + return NULL; } static char* -inp_fix_subckt(char *s) +inp_fix_subckt(struct names *subckt_w_params, char *s) { - struct line *head = NULL, *newcard = NULL, *start_card = NULL, *end_card = NULL, *prev_card = NULL, *c = NULL; - char *equal, *beg, *buffer, *ptr1, *ptr2, *str, *new_str = NULL; + struct line *head = NULL, *start_card = NULL, *end_card = NULL, *prev_card = NULL, *c = NULL; + char *equal, *beg, *buffer, *ptr1, *ptr2, *new_str = NULL; char keep; int num_params = 0, i = 0, bracedepth = 0; /* find first '=' */ @@ -2090,25 +2087,24 @@ inp_fix_subckt(char *s) for (ptr2 = ptr1; *ptr2 && !isspace(*ptr2) && !isquote(*ptr2); ptr2++) ; - subckt_w_params[num_subckt_w_params++] = copy_substring(ptr1, ptr2); + add_name(subckt_w_params, copy_substring(ptr1, ptr2)); /* go to beginning of first parameter word */ /* s will contain only subckt definition */ /* beg will point to start of param list */ - beg = skip_back_ws(equal - 1); - beg = skip_back_non_ws(beg); - *beg = '\0'; - beg++; + beg = skip_back_ws_(equal, s); + beg = skip_back_non_ws_(beg, s); + beg[-1] = '\0'; /* fixme can be < s */ - head = alloc(struct line); + head = xx_new_line(NULL, NULL, 0, 0); /* create list of parameters that need to get sorted */ while (*beg && (ptr1 = strchr(beg, '=')) != NULL) { #ifndef NOBRACE /* alternative patch to cope with spaces: get expression between braces {...} */ ptr2 = skip_ws(ptr1 + 1); - ptr1 = skip_back_ws(ptr1 - 1); - ptr1 = skip_back_non_ws(ptr1) + 1; + ptr1 = skip_back_ws_(ptr1, beg); + ptr1 = skip_back_non_ws_(ptr1, beg); /* ptr1 points to beginning of parameter */ /* if parameter is an expression and starts with '{', find closing '}' @@ -2129,7 +2125,7 @@ inp_fix_subckt(char *s) ptr2++;/* ptr2 points past end of parameter {...} */ } else - /* take only the next token (separated by space) as the parameter */ + /* take only the next token (separated by space) as the parameter */ ptr2 = skip_non_ws(ptr2); /* ptr2 points past end of parameter */ keep = *ptr2; @@ -2138,23 +2134,18 @@ inp_fix_subckt(char *s) beg = ptr2; } else { *ptr2 = '\0'; - beg = ptr2+1; + beg = ptr2 + 1; } - newcard = alloc(struct line); - str = strdup(ptr1); - - newcard->li_line = str; - newcard->li_next = NULL; + end_card = xx_new_line(NULL, strdup(ptr1), 0, 0); if (start_card == NULL) - head->li_next = start_card = newcard; + head->li_next = start_card = end_card; else - prev_card->li_next = newcard; + prev_card->li_next = end_card; - prev_card = end_card = newcard; + prev_card = end_card; num_params++; - } #else /* patch provided by Ivan Riis Nielsen */ bool done = FALSE; @@ -2179,18 +2170,14 @@ inp_fix_subckt(char *s) buf[buf_idx++] = '\0'; beg = p1; - newcard = alloc(struct line); - str = buf; - - newcard->li_line = str; - newcard->li_next = NULL; + end_card = xx_new_line(NULL, buf, 0, 0); if (start_card == NULL) - head->li_next = start_card = newcard; + head->li_next = start_card = end_card; else - prev_card->li_next = newcard; + prev_card->li_next = end_card; - prev_card = end_card = newcard; + prev_card = end_card; num_params++; done = TRUE; @@ -2198,8 +2185,8 @@ inp_fix_subckt(char *s) else p2 = p1; } - } #endif + } /* now sort parameters in order of dependencies */ inp_sort_params(start_card, end_card, head, start_card, end_card); @@ -2210,10 +2197,10 @@ inp_fix_subckt(char *s) if (new_str == NULL) { new_str = strdup(c->li_line); } else { - str = new_str; - new_str = TMALLOC(char, strlen(str) + strlen(c->li_line) + 2); - sprintf(new_str, "%s %s", str, c->li_line); - tfree(str); + char *x = TMALLOC(char, strlen(new_str) + strlen(c->li_line) + 2); + sprintf(x, "%s %s", new_str, c->li_line); + tfree(new_str); + new_str = x; } tfree(c->li_line); head = c; @@ -2230,6 +2217,7 @@ inp_fix_subckt(char *s) s = buffer; } + return s; } @@ -2290,79 +2278,72 @@ inp_remove_ws(char *s) /* change quotes from '' to {} .subckt name 1 2 3 params: l=1 w=2 --> .subckt name 1 2 3 l=1 w=2 - x1 1 2 3 params: l=1 w=2 --> x1 1 2 3 l=1 w=2 - modify .subckt lines by calling inp_fix_subckt() - No changes to lines in .control section ! + x1 1 2 3 params: l=1 w=2 --> x1 1 2 3 l=1 w=2 + modify .subckt lines by calling inp_fix_subckt() + No changes to lines in .control section ! */ + static void -inp_fix_for_numparam(struct line *deck) +inp_fix_for_numparam(struct names *subckt_w_params, struct line *c) { bool found_control = FALSE; - struct line *c = deck; - char *str_ptr; - while (c != NULL) { - if (ciprefix("*lib", c->li_line) || ciprefix("*inc", c->li_line)) { - c = c->li_next; + for (; c; c = c->li_next) { + + if (ciprefix(".lib", c->li_line) || ciprefix("*lib", c->li_line) || ciprefix("*inc", c->li_line)) continue; - } /* exclude lines between .control and .endc from getting quotes changed */ if (ciprefix(".control", c->li_line)) found_control = TRUE; if (ciprefix(".endc", c->li_line)) found_control = FALSE; - if (found_control) { - c = c->li_next; + + if (found_control) continue; - } inp_change_quotes(c->li_line); if ((inp_compat_mode == COMPATMODE_ALL) || (inp_compat_mode == COMPATMODE_PS)) if (ciprefix(".subckt", c->li_line) || ciprefix("x", c->li_line)) { - /* remove params: */ - str_ptr = strstr(c->li_line, "params:"); + /* remove params: */ + char *str_ptr = strstr(c->li_line, "params:"); if (str_ptr) memcpy(str_ptr, " ", 7); } if (ciprefix(".subckt", c->li_line)) - c->li_line = inp_fix_subckt(c->li_line); - - c = c->li_next; + c->li_line = inp_fix_subckt(subckt_w_params, c->li_line); } } static void -inp_remove_excess_ws(struct line *deck) +inp_remove_excess_ws(struct line *c) { - struct line *c = deck; bool found_control = FALSE; - while (c != NULL) { - if (*c->li_line == '*') { - c = c->li_next; + + for (; c; c = c->li_next) { + + if (*c->li_line == '*') continue; - } /* exclude echo lines between .control and .endc from removing white spaces */ if (ciprefix(".control", c->li_line)) found_control = TRUE; if (ciprefix(".endc", c->li_line)) found_control = FALSE; - if ((found_control) && (ciprefix("echo", c->li_line))) { - c = c->li_next; + + if (found_control && ciprefix("echo", c->li_line)) continue; - } + c->li_line = inp_remove_ws(c->li_line); /* freed in fcn */ - c = c->li_next; } } /* - * recursively collect library section references, + * recursively expand library section references, * either * every library section reference (when the given section_name_ === NULL) * or @@ -2370,20 +2351,13 @@ inp_remove_excess_ws(struct line *deck) */ static void -collect_section_references(struct line *deck, char *section_name_) +expand_section_references(struct line *c, int call_depth, char *dir_name) { - bool read_line = (section_name_ == NULL); - - struct line *c; - - for (c = deck; c; c = c->li_next) { + for (; c; c = c->li_next) { char *line = c->li_line; - if (ciprefix(".endl", line) && section_name_ != NULL) - read_line = FALSE; - - if (ciprefix("*lib", line) || ciprefix(".lib", line)) { + if (ciprefix(".lib", line)) { char *s, *t, *y; @@ -2396,22 +2370,13 @@ collect_section_references(struct line *deck, char *section_name_) while (isspace(*y) || isquote(*y)) y++; - if (!*y) { - /* library section definition: `.lib ' .. `.endl' */ - - char keep_char = *t; - *t = '\0'; - - if (section_name_ != NULL && strcmp(section_name_, s) == 0) - read_line = TRUE; - *t = keep_char; - } - else if (read_line == TRUE) { + if (*y) { /* library section reference: `.lib ' */ + struct line *section_def; char keep_char1, keep_char2; char *z, *copys = NULL; - int lib_idx; + struct library *lib; for (z = y; *z && !isspace(*z) && !isquote(*z); z++) ; @@ -2425,14 +2390,48 @@ collect_section_references(struct line *deck, char *section_name_) if (copys) s = copys; } - lib_idx = find_lib(s); - if (lib_idx >= 0) - if (find_section(lib_idx, y) < 0) { - /* remember this section having been referenced */ - remember_section_ref(lib_idx, y, c); - /* recursively check for nested section references */ - collect_section_references(library_deck[lib_idx], y); + + lib = find_lib(s); + + if (!lib) { + + if(!read_a_lib(s, call_depth, dir_name)) + controlled_exit(EXIT_FAILURE); + + lib = find_lib(s); + } + + if (!lib) { + fprintf(stderr, "ERROR, library file %s not found\n", s); + controlled_exit(EXIT_FAILURE); + } + + section_def = find_section_definition(lib->deck, y); + + if (!section_def) { + fprintf(stderr, "ERROR, library file %s, section definition %s not found\n", s, y); + controlled_exit(EXIT_FAILURE); + } + + /* insert the library section definition into `c' */ + { + struct line *t = inp_deckcopy(section_def); + struct line *rest = c->li_next; + c->li_next = t; + t->li_line[0] = '*'; + t->li_line[1] = '<'; + for (; t; t=t->li_next) + if(ciprefix(".endl", t->li_line)) + break; + if (!t) { + fprintf(stderr, "ERROR, .endl not found\n"); + controlled_exit(EXIT_FAILURE); } + t->li_line[0] = '*'; + t->li_line[1] = '>'; + t->li_next = rest; + } + *line = '*'; /* comment out .lib line */ *t = keep_char1; *z = keep_char2; @@ -2444,30 +2443,20 @@ collect_section_references(struct line *deck, char *section_name_) } -static void -inp_init_lib_data(void) -{ - int i; - - for (i = 0; i < num_libraries; i++) - num_sections[i] = 0; -} - - static char* inp_get_subckt_name(char *s) { char *subckt_name, *end_ptr = strchr(s, '='); if (end_ptr) { - end_ptr = skip_back_ws(end_ptr - 1); - end_ptr = skip_back_non_ws(end_ptr) + 1; + end_ptr = skip_back_ws_(end_ptr, s); + end_ptr = skip_back_non_ws_(end_ptr, s); } else { - end_ptr = s + strlen(s); + end_ptr = strchr(s, '\0'); } - end_ptr = skip_back_ws(end_ptr - 1) + 1; - subckt_name = skip_back_non_ws(end_ptr - 1) + 1; + end_ptr = skip_back_ws_(end_ptr, s); + subckt_name = skip_back_non_ws_(end_ptr, s); return copy_substring(subckt_name, end_ptr); } @@ -2483,25 +2472,13 @@ inp_get_params(char *line, char *param_names[], char *param_values[]) char keep; bool is_expression = FALSE; - while ((equal_ptr = strchr(line, '=')) != NULL) { - - // check for equality '==' - if (equal_ptr[1] == '=') { - line = equal_ptr+2; - continue; - } - // check for '!=', '<=', '>=' - if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - line = equal_ptr+1; - continue; - } + while ((equal_ptr = find_assignment(line)) != NULL) { is_expression = FALSE; /* get parameter name */ - name = skip_back_ws(equal_ptr - 1); - end = name + 1; - name = skip_back_non_ws(name) + 1; + end = skip_back_ws_(equal_ptr, line); + name = skip_back_non_ws_(end, line); param_names[num_params++] = copy_substring(name, end); @@ -2539,8 +2516,8 @@ inp_get_params(char *line, char *param_names[], char *param_values[]) static char* inp_fix_inst_line(char *inst_line, - int num_subckt_params, char *subckt_param_names[], char *subckt_param_values[], - int num_inst_params, char *inst_param_names[], char *inst_param_values[]) + int num_subckt_params, char *subckt_param_names[], char *subckt_param_values[], + int num_inst_params, char *inst_param_names[], char *inst_param_values[]) { char *end, *inst_name, *inst_name_end; char *curr_line = inst_line, *new_line = NULL; @@ -2551,9 +2528,9 @@ inp_fix_inst_line(char *inst_line, end = strchr(inst_line, '='); if (end) { - end = skip_back_ws(end - 1); - end = skip_back_non_ws(end); - *end = '\0'; + end = skip_back_ws_(end, inst_line); + end = skip_back_non_ws_(end, inst_line); + end[-1] = '\0'; /* fixme can be < inst_line */ } for (i = 0; i < num_subckt_params; i++) @@ -2585,22 +2562,33 @@ inp_fix_inst_line(char *inst_line, } +/* If multiplier parameter 'm' is found on a X line, flag is set + to TRUE. + Function is called from inp_fix_inst_calls_for_numparam()*/ + static bool found_mult_param(int num_params, char *param_names[]) { - bool found_mult = FALSE; int i; for (i = 0; i < num_params; i++) if (strcmp(param_names[i], "m") == 0) - found_mult = TRUE; + return TRUE; - return found_mult; + return FALSE; } +/* If a subcircuit invocation (X-line) is found, which contains the + multiplier parameter 'm', m is added to all lines inside + the corresponding subcircuit except of some excluded in the code below + (FIXME: It may be necessary to exclude more of them, at least + for all devices that are not supporting the 'm' parameter). + + Function is called from inp_fix_inst_calls_for_numparam()*/ + static int -inp_fix_subckt_multiplier(struct line *subckt_card, +inp_fix_subckt_multiplier(struct names *subckt_w_params, struct line *subckt_card, int num_subckt_params, char *subckt_param_names[], char *subckt_param_values[]) { struct line *card; @@ -2608,12 +2596,12 @@ inp_fix_subckt_multiplier(struct line *subckt_card, subckt_param_names[num_subckt_params] = strdup("m"); subckt_param_values[num_subckt_params] = strdup("1"); - num_subckt_params = num_subckt_params + 1; + num_subckt_params ++; if (!strstr(subckt_card->li_line, "params:")) { new_str = TMALLOC(char, strlen(subckt_card->li_line) + 13); sprintf(new_str, "%s params: m=1", subckt_card->li_line); - subckt_w_params[num_subckt_w_params++] = get_subckt_model_name(subckt_card->li_line); + add_name(subckt_w_params, get_subckt_model_name(subckt_card->li_line)); } else { new_str = TMALLOC(char, strlen(subckt_card->li_line) + 5); sprintf(new_str, "%s m=1", subckt_card->li_line); @@ -2623,10 +2611,11 @@ inp_fix_subckt_multiplier(struct line *subckt_card, subckt_card->li_line = new_str; for (card = subckt_card->li_next; - card != NULL && !ciprefix(".ends", card->li_line); + card && !ciprefix(".ends", card->li_line); card = card->li_next) { - /* no 'm' for B line or comment line */ - if ((*(card->li_line) == '*') || (*(card->li_line) == 'b')) + /* no 'm' for B, V, E, H or comment line */ + if ((*(card->li_line) == '*') || (*(card->li_line) == 'b') || (*(card->li_line) == 'v') || + (*(card->li_line) == 'e') || (*(card->li_line) == 'h')) continue; /* no 'm' for model cards */ if (ciprefix(".model", card->li_line)) @@ -2643,12 +2632,10 @@ inp_fix_subckt_multiplier(struct line *subckt_card, static void -inp_fix_inst_calls_for_numparam(struct line *deck) +inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck) { - struct line *c = deck; + struct line *c; struct line *d, *p = NULL; - char *inst_line; - char *subckt_line; char *subckt_name; char *subckt_param_names[1000]; char *subckt_param_values[1000]; @@ -2664,8 +2651,8 @@ inp_fix_inst_calls_for_numparam(struct line *deck) // first iterate through instances and find occurences where 'm' multiplier needs to be // added to the subcircuit -- subsequent instances will then need this parameter as well - for (c = deck; c != NULL; c = c->li_next) { - inst_line = c->li_line; + for (c = deck; c; c = c->li_next) { + char *inst_line = c->li_line; if (*inst_line == '*') continue; @@ -2677,9 +2664,9 @@ inp_fix_inst_calls_for_numparam(struct line *deck) if (found_mult_param(num_inst_params, inst_param_names)) { flag = FALSE; // iterate through the deck to find the subckt (last one defined wins) - d = deck; - while (d != NULL) { - subckt_line = d->li_line; + + for (d = deck; d; d = d->li_next) { + char *subckt_line = d->li_line; if (ciprefix(".subckt", subckt_line)) { subckt_line = skip_non_ws(subckt_line); subckt_line = skip_ws(subckt_line); @@ -2690,13 +2677,12 @@ inp_fix_inst_calls_for_numparam(struct line *deck) flag = TRUE; } } - d = d->li_next; } if (flag) { num_subckt_params = inp_get_params(p->li_line, subckt_param_names, subckt_param_values); if (num_subckt_params == 0 || !found_mult_param(num_subckt_params, subckt_param_names)) - inp_fix_subckt_multiplier(p, num_subckt_params, subckt_param_names, subckt_param_values); + inp_fix_subckt_multiplier(subckt_w_params, p, num_subckt_params, subckt_param_names, subckt_param_values); } } tfree(subckt_name); @@ -2712,213 +2698,246 @@ inp_fix_inst_calls_for_numparam(struct line *deck) } } - c = deck; - while (c != NULL) { - inst_line = c->li_line; + for (c = deck; c; c = c->li_next) { + char *inst_line = c->li_line; - if (*inst_line == '*') { - c = c->li_next; + if (*inst_line == '*') continue; - } + if (ciprefix("x", inst_line)) { subckt_name = inp_get_subckt_name(inst_line); - for (i = 0; i < num_subckt_w_params; i++) { - if (strcmp(subckt_w_params[i], subckt_name) == 0) { - sprintf(name_w_space, "%s ", subckt_name); - /* find .subckt line */ - found_subckt = FALSE; + if (find_name(subckt_w_params, subckt_name)) { + sprintf(name_w_space, "%s ", subckt_name); - d = deck; - while (d != NULL) { - subckt_line = d->li_line; - if (ciprefix(".subckt", subckt_line)) { - subckt_line = skip_non_ws(subckt_line); - subckt_line = skip_ws(subckt_line); + /* find .subckt line */ + found_subckt = FALSE; - if (strncmp(subckt_line, name_w_space, strlen(name_w_space)) == 0) { - num_subckt_params = inp_get_params(subckt_line, subckt_param_names, subckt_param_values); - num_inst_params = inp_get_params(inst_line, inst_param_names, inst_param_values); + d = deck; + while (d != NULL) { + char *subckt_line = d->li_line; + if (ciprefix(".subckt", subckt_line)) { + subckt_line = skip_non_ws(subckt_line); + subckt_line = skip_ws(subckt_line); - // make sure that if have inst params that one matches subckt - found_param_match = FALSE; - if (num_inst_params == 0) { - found_param_match = TRUE; - } else { - for (j = 0; j < num_inst_params; j++) { - for (k = 0; k < num_subckt_params; k++) - if (strcmp(subckt_param_names[k], inst_param_names[j]) == 0) { - found_param_match = TRUE; - break; - } - if (found_param_match) + if (strncmp(subckt_line, name_w_space, strlen(name_w_space)) == 0) { + num_subckt_params = inp_get_params(subckt_line, subckt_param_names, subckt_param_values); + num_inst_params = inp_get_params(inst_line, inst_param_names, inst_param_values); + + // make sure that if have inst params that one matches subckt + found_param_match = FALSE; + if (num_inst_params == 0) { + found_param_match = TRUE; + } else { + for (j = 0; j < num_inst_params; j++) { + for (k = 0; k < num_subckt_params; k++) + if (strcmp(subckt_param_names[k], inst_param_names[j]) == 0) { + found_param_match = TRUE; break; - } - } - - if (!found_param_match) { - // comment out .subckt and continue - while (d != NULL && !ciprefix(".ends", d->li_line)) { - *(d->li_line) = '*'; - d = d->li_next; - } - *(d->li_line) = '*'; - d = d->li_next; - continue; - } - - c->li_line = inp_fix_inst_line(inst_line, num_subckt_params, subckt_param_names, subckt_param_values, num_inst_params, inst_param_names, inst_param_values); - found_subckt = TRUE; - for (i = 0; i < num_subckt_params; i++) { - tfree(subckt_param_names[i]); - tfree(subckt_param_values[i]); - } - for (i = 0; i < num_inst_params; i++) { - tfree(inst_param_names[i]); - tfree(inst_param_values[i]); + } + if (found_param_match) + break; } } + + if (!found_param_match) { + // comment out .subckt and continue + while (d != NULL && !ciprefix(".ends", d->li_line)) { + *(d->li_line) = '*'; + d = d->li_next; + } + *(d->li_line) = '*'; + d = d->li_next; + continue; + } + + c->li_line = inp_fix_inst_line(inst_line, num_subckt_params, subckt_param_names, subckt_param_values, num_inst_params, inst_param_names, inst_param_values); + found_subckt = TRUE; + for (i = 0; i < num_subckt_params; i++) { + tfree(subckt_param_names[i]); + tfree(subckt_param_values[i]); + } + for (i = 0; i < num_inst_params; i++) { + tfree(inst_param_names[i]); + tfree(inst_param_values[i]); + } } - if (found_subckt) - break; - d = d->li_next; } - break; + if (found_subckt) + break; + d = d->li_next; } } tfree(subckt_name); } - c = c->li_next; } } -static void -inp_get_func_from_line(char *line) +static struct function * +new_function(struct function_env *env, char *name) { - char *ptr, *end; - char keep; - char temp_buf[5000]; - int num_params = 0; - int str_len = 0; - int i = 0; + struct function *f = TMALLOC(struct function, 1); - /* get function name */ + f -> name = name; + f -> num_parameters = 0; + + f -> next = env->functions; + env -> functions = f; + + return f; +} + + +static struct function * +find_function(struct function_env *env, char *name) +{ + struct function *f; + + for (; env; env = env->up) + for (f = env->functions; f; f = f->next) + if (strcmp(f->name, name) == 0) + return f; + + return NULL; +} + + +static void +free_function(struct function *fcn) +{ + int i; + + tfree(fcn->name); + tfree(fcn->macro); + + for (i = 0; i < fcn->num_parameters; i++) + tfree(fcn->params[i]); +} + + +static void +new_function_parameter(struct function *fcn, char *parameter) +{ + if (fcn->num_parameters >= N_PARAMS) { + fprintf(stderr, "ERROR, N_PARAMS overflow\n"); + controlled_exit(EXIT_FAILURE); + } + + fcn->params[fcn->num_parameters++] = parameter; +} + + +static void +inp_get_func_from_line(struct function_env *env, char *line) +{ + char *end; + char temp_buf[5000]; + int str_len = 0; + struct function *function; + + /* skip `.func' */ line = skip_non_ws(line); line = skip_ws(line); + + /* get function name */ end = line; - while (!isspace(*end) && *end != '(') + while (*end && !isspace(*end) && *end != '(') end++; - keep = *end; - *end = '\0'; - /* see if already encountered this function */ - for (i = 0; i < num_functions; i++) - if (strcmp(func_names[i], line) == 0) - break; + function = new_function(env, copy_substring(line, end)); - func_names[num_functions++] = strdup(line); - *end = keep; - - num_params = 0; + while (*end && *end != '(') + end++; /* get function parameters */ - while (*end != '(') - end++; - while (*end != ')') { - end = skip_ws(end + 1); - ptr = end; - while (!isspace(*end) && *end != ',' && *end != ')') + while (*end && *end != ')') { + char *beg = skip_ws(end + 1); + end = beg; + while (*end && !isspace(*end) && *end != ',' && *end != ')') end++; - if (end > ptr) - func_params[num_functions-1][num_params++] = copy_substring(ptr, end); + if (end > beg) + new_function_parameter(function, copy_substring(beg, end)); } - num_parameters[num_functions-1] = num_params; - /* get function macro */ + + /* skip to the beinning of the function body */ + while (*end && *end++ != '{') + ; + + /* get function body */ str_len = 0; - while (*end != '{') - end++; - end++; - while (*end && *end != '}') { + while (*end && *end != '}') { if (!isspace(*end)) temp_buf[str_len++] = *end; end++; } temp_buf[str_len++] = '\0'; - func_macro[num_functions-1] = strdup(temp_buf); + function->macro = strdup(temp_buf); } -// -// only grab global functions; skip subckt functions -// -static void -inp_grab_func(struct line *deck) -{ - struct line *c = deck; - bool is_subckt = FALSE; +/* + * grab functions at the current .subckt nesting level + */ - while (c != NULL) { - if (*c->li_line == '*') { - c = c->li_next; +static void +inp_grab_func(struct function_env *env, struct line *c) +{ + int nesting = 0; + + for (; c; c = c->li_next) { + + if (*c->li_line == '*') continue; - } + if (ciprefix(".subckt", c->li_line)) - is_subckt = TRUE; + nesting++; if (ciprefix(".ends", c->li_line)) - is_subckt = FALSE; + nesting--; - if (!is_subckt && ciprefix(".func", c->li_line)) { - inp_get_func_from_line(c->li_line); - *c->li_line = '*'; - } - c = c->li_next; - } -} + if (nesting < 0) + break; + if (nesting > 0) + continue; -static void -inp_grab_subckt_func(struct line *subckt) -{ - struct line *c = subckt; - - while (!ciprefix(".ends", c->li_line)) { if (ciprefix(".func", c->li_line)) { - inp_get_func_from_line(c->li_line); + inp_get_func_from_line(env, c->li_line); *c->li_line = '*'; } - c = c->li_next; } } static char* -inp_do_macro_param_replace(int fcn_number, char *params[]) +inp_do_macro_param_replace(struct function *fcn, char *params[]) { char *param_ptr, *curr_ptr, *new_str, *curr_str = NULL, *search_ptr; char keep, before, after; int i; - if (num_parameters[fcn_number] == 0) - return strdup(func_macro[fcn_number]); + if (fcn->num_parameters == 0) + return strdup(fcn->macro); + + for (i = 0; i < fcn->num_parameters; i++) { - for (i = 0; i < num_parameters[fcn_number]; i++) { if (curr_str == NULL) { - search_ptr = curr_ptr = func_macro[fcn_number]; + search_ptr = curr_ptr = fcn->macro; } else { search_ptr = curr_ptr = curr_str; curr_str = NULL; } - while ((param_ptr = strstr(search_ptr, func_params[fcn_number][i])) != NULL) { + + while ((param_ptr = strstr(search_ptr, fcn->params[i])) != NULL) { /* make sure actually have the parameter name */ if (param_ptr == search_ptr) /* no valid 'before' */ before = '\0'; else before = *(param_ptr-1); - after = param_ptr [ strlen(func_params[fcn_number][i]) ]; + after = param_ptr [ strlen(fcn->params[i]) ]; if (!(is_arith_char(before) || isspace(before) || before == ',' || before == '=' || (param_ptr-1) < curr_ptr) || !(is_arith_char(after) || isspace(after) || @@ -2944,8 +2963,9 @@ inp_do_macro_param_replace(int fcn_number, char *params[]) } *param_ptr = keep; - search_ptr = curr_ptr = param_ptr + strlen(func_params[fcn_number][i]); + search_ptr = curr_ptr = param_ptr + strlen(fcn->params[i]); } + if (param_ptr == NULL) { if (curr_str == NULL) { curr_str = curr_ptr; @@ -2957,14 +2977,15 @@ inp_do_macro_param_replace(int fcn_number, char *params[]) } } } + return curr_str; } static char* -inp_expand_macro_in_str(char *str) +inp_expand_macro_in_str(struct function_env *env, char *str) { - int i; + struct function *function; char *c; char *open_paren_ptr, *close_paren_ptr, *fcn_name, *params[1000]; char *curr_ptr, *macro_str, *curr_str = NULL; @@ -2987,13 +3008,11 @@ inp_expand_macro_in_str(char *str) *open_paren_ptr = '\0'; - for (i = 0; i < num_functions; i++) - if (strcmp(func_names[i], fcn_name) == 0) - break; + function = find_function(env, fcn_name); *open_paren_ptr = '('; - if (i >= num_functions) + if (!function) continue; /* find the closing paren */ @@ -3043,15 +3062,15 @@ inp_expand_macro_in_str(char *str) break; } params[num_params++] = - inp_expand_macro_in_str(copy_substring(beg_parameter, curr_ptr)); + inp_expand_macro_in_str(env, copy_substring(beg_parameter, curr_ptr)); } - if (num_parameters[i] != num_params) { + if (function->num_parameters != num_params) { fprintf(stderr, "ERROR: parameter mismatch for function call in str: %s\n", orig_str); controlled_exit(EXIT_FAILURE); } - macro_str = inp_do_macro_param_replace(i, params); + macro_str = inp_do_macro_param_replace(function, params); keep = *fcn_name; *fcn_name = '\0'; { @@ -3085,48 +3104,74 @@ inp_expand_macro_in_str(char *str) static void -inp_expand_macros_in_func(void) +inp_expand_macros_in_func(struct function_env *env) { - int i; + struct function *f; - for (i = 0; i < num_functions; i++) - func_macro[i] = inp_expand_macro_in_str(func_macro[i]); + for (f = env->functions; f ; f = f->next) + f->macro = inp_expand_macro_in_str(env, f->macro); } -static void -inp_expand_macros_in_deck(struct line *deck) +static struct function_env * +new_function_env(struct function_env *up) { - struct line *c = deck; - int prev_num_functions = 0, i, j; + struct function_env *env = TMALLOC(struct function_env, 1); - while (c != NULL) { - if (*c->li_line == '*') { - c = c->li_next; + env -> up = up; + env -> functions = NULL; + + return env; +} + + +static struct function_env * +delete_function_env(struct function_env *env) +{ + struct function_env *up = env -> up; + struct function *f; + + for (f = env -> functions; f; ) { + struct function *here = f; + f = f -> next; + free_function(here); + } + + tfree(env -> functions); + tfree(env); + + return up; +} + + +static struct line * +inp_expand_macros_in_deck(struct function_env *env, struct line *c) +{ + env = new_function_env(env); + + inp_grab_func(env, c); + + inp_expand_macros_in_func(env); + + for (; c; c = c->li_next) { + + if (*c->li_line == '*') + continue; + + if (ciprefix(".subckt", c->li_line)) { + c = inp_expand_macros_in_deck(env, c->li_next); continue; } - if (ciprefix(".subckt", c->li_line)) { - prev_num_functions = num_functions; - inp_grab_subckt_func(c); - if (prev_num_functions != num_functions) - inp_expand_macros_in_func(); - } - if (ciprefix(".ends", c->li_line)) { - if (prev_num_functions != num_functions) { - for (i = prev_num_functions; i < num_functions; i++) { - tfree(func_names[i]); - tfree(func_macro[i]); - for (j = 0; j < num_parameters[i]; j++) - tfree(func_params[i][j]); - num_functions = prev_num_functions; - } - } - } - if (*c->li_line != '*') - c->li_line = inp_expand_macro_in_str(c->li_line); - c = c->li_next; + if (ciprefix(".ends", c->li_line)) + break; + + c->li_line = inp_expand_macro_in_str(env, c->li_line); } + + env = delete_function_env(env); + + return c; } @@ -3137,52 +3182,49 @@ inp_expand_macros_in_deck(struct line *deck) Special handling of vectors with [] and complex values with < > h_vogt 20 April 2008 - * For xspice and num_pram compatibility .cmodel added - * .cmodel will be replaced by .model in inp_fix_param_values() - * and then the entire line is skipped (will not be changed by this function). - * Usage of numparam requires {} around the parameters in the .cmodel line. - * May be obsolete? - */ + * For xspice and num_pram compatibility .cmodel added + * .cmodel will be replaced by .model in inp_fix_param_values() + * and then the entire line is skipped (will not be changed by this function). + * Usage of numparam requires {} around the parameters in the .cmodel line. + * May be obsolete? + */ + static void -inp_fix_param_values(struct line *deck) +inp_fix_param_values(struct line *c) { - struct line *c = deck; - char *line, *beg_of_str, *end_of_str, *old_str, *equal_ptr, *new_str; + char *beg_of_str, *end_of_str, *old_str, *equal_ptr, *new_str; char *vec_str, *tmp_str, *natok, *buffer, *newvec, *whereisgt; bool control_section = FALSE; wordlist *nwl; int parens; - while (c != NULL) { - line = c->li_line; + for (; c; c = c->li_next) { + char *line = c->li_line; - if (*line == '*' || (ciprefix(".param", line) && strchr(line, '{'))) { - c = c->li_next; + if (*line == '*' || (ciprefix(".param", line) && strchr(line, '{'))) continue; - } if (ciprefix(".control", line)) { control_section = TRUE; - c = c->li_next; continue; } + if (ciprefix(".endc", line)) { control_section = FALSE; - c = c->li_next; continue; } - if (control_section || ciprefix(".option", line)) { - c = c->li_next; /* no handling of params in "option" lines */ + + /* no handling of params in "option" lines */ + if (control_section || ciprefix(".option", line)) continue; - } - if (ciprefix("set", line)) { - c = c->li_next; /* no handling of params in "set" lines */ + + /* no handling of params in "set" lines */ + if (ciprefix("set", line)) continue; - } - if (*line == 'b') { - c = c->li_next; /* no handling of params in B source lines */ + + /* no handling of params in B source lines */ + if (*line == 'b') continue; - } /* for xspice .cmodel: replace .cmodel with .model and skip entire line) */ if (ciprefix(".cmodel", line)) { @@ -3192,24 +3234,22 @@ inp_fix_param_values(struct line *deck) *(++line) = 'e'; *(++line) = 'l'; *(++line) = ' '; - c = c->li_next; continue; } /* exclude CIDER models */ if (ciprefix(".model", line) && (strstr(line, "numos") || strstr(line, "numd") || strstr(line, "nbjt") || strstr(line, "nbjt2") || - strstr(line, "numd2"))) { - c = c->li_next; - continue; - } - /* exclude CIDER devices with ic.file parameter */ - if (strstr(line, "ic.file")) { - c = c->li_next; + strstr(line, "numd2"))) + { continue; } - while ((equal_ptr = strchr(line, '=')) != NULL) { + /* exclude CIDER devices with ic.file parameter */ + if (strstr(line, "ic.file")) + continue; + + while ((equal_ptr = find_assignment(line)) != NULL) { // special case: .MEASURE {DC|AC|TRAN} result FIND out_variable WHEN out_variable2=out_variable3 // no braces around out_variable3. out_variable3 may be v(...) or i(...) @@ -3224,18 +3264,6 @@ inp_fix_param_values(struct line *deck) continue; } - // skip over equality '==' - if (equal_ptr[1] == '=') { - line += 2; - continue; - } - // check for '!=', '<=', '>=' - if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') - { - line += 1; - continue; - } - beg_of_str = skip_ws(equal_ptr + 1); /* all cases where no {} have to be put around selected token */ if (isdigit(*beg_of_str) || @@ -3250,7 +3278,7 @@ inp_fix_param_values(struct line *deck) line = equal_ptr + 1; } else if (*beg_of_str == '[') { /* A vector following the '=' token: code to put curly brackets around all params - inside a pair of square brackets */ + inside a pair of square brackets */ end_of_str = beg_of_str; while (*end_of_str != ']') end_of_str++; @@ -3317,7 +3345,7 @@ inp_fix_param_values(struct line *deck) tfree(old_str); } else if (*beg_of_str == '<') { /* A complex value following the '=' token: code to put curly brackets around all params - inside a pair < > */ + inside a pair < > */ end_of_str = beg_of_str; while (*end_of_str != '>') end_of_str++; @@ -3390,7 +3418,6 @@ inp_fix_param_values(struct line *deck) tfree(old_str); } } - c = c->li_next; } } @@ -3398,26 +3425,20 @@ inp_fix_param_values(struct line *deck) static char* get_param_name(char *line) { - char *name = NULL, *equal_ptr, *beg; - char keep; + char *beg; + char *equal_ptr = strchr(line, '='); - if ((equal_ptr = strchr(line, '=')) != NULL) { - equal_ptr = skip_back_ws(equal_ptr - 1) + 1; - - beg = equal_ptr - 1; - while (!isspace(*beg) && beg != line) - beg--; - if (beg != line) - beg++; - keep = *equal_ptr; - *equal_ptr = '\0'; - name = strdup(beg); - *equal_ptr = keep; - } else { + if (!equal_ptr) { fprintf(stderr, "ERROR: could not find '=' on parameter line '%s'!\n", line); controlled_exit(EXIT_FAILURE); + return NULL; } - return name; + + equal_ptr = skip_back_ws_(equal_ptr, line); + + beg = skip_back_non_ws_(equal_ptr, line); + + return copy_substring(beg, equal_ptr); } @@ -3434,7 +3455,6 @@ get_param_str(char *line) static int -//inp_get_param_level(int param_num, char *depends_on[12000][100], char *param_names[12000], char *param_strs[12000], int total_params, int *level) inp_get_param_level(int param_num, char ***depends_on, char **param_names, char **param_strs, int total_params, int *level) { int index1 = 0, comp_level = 0, temp_level = 0; @@ -3460,7 +3480,9 @@ inp_get_param_level(int param_num, char ***depends_on, char **param_names, char comp_level = temp_level; index1++; } + level[param_num] = comp_level; + return comp_level; } @@ -3551,8 +3573,8 @@ get_number_terminals(char *c) bool only_digits = TRUE; char *nametmp = name[k]; /* MNAME has to contain at least one alpha character. AREA may be assumed - if we have a token with only digits, and where the previous token does not - end with a ',' */ + if we have a token with only digits, and where the previous token does not + end with a ',' */ while (*nametmp) { if (isalpha(*nametmp) || (*nametmp == ',')) only_digits = FALSE; @@ -3577,6 +3599,7 @@ get_number_terminals(char *c) /* sort parameters based on parameter dependencies */ + static void inp_sort_params(struct line *start_card, struct line *end_card, struct line *card_bf_start, struct line *s_c, struct line *e_c) { @@ -3587,7 +3610,6 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car bool found_in_list = FALSE; struct line *ptr; - char *curr_line; char *str_ptr, *beg, *end, *new_str; int skipped = 0; int arr_size = 12000; @@ -3606,12 +3628,10 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car return; /* determine the number of lines with .param */ - ptr = start_card; - while (ptr != NULL) { + + for (ptr = start_card; ptr; ptr = ptr->li_next) if (strchr(ptr->li_line, '=')) num_params++; - ptr = ptr->li_next; - } arr_size = num_params; num_params = 0; /* This is just to keep the code in row 2907ff. */ @@ -3633,7 +3653,7 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car ptr_array_ordered = TMALLOC(struct line *, arr_size); ptr = start_card; - while (ptr != NULL) { + for (ptr = start_card; ptr; ptr = ptr->li_next) // ignore .param lines without '=' if (strchr(ptr->li_line, '=')) { depends_on[num_params][0] = NULL; @@ -3643,8 +3663,7 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car ptr_array[num_params++] = ptr; } - ptr = ptr->li_next; - } + // look for duplicately defined parameters and mark earlier one to skip // param list is ordered as defined in netlist for (i = 0; i < num_params; i++) @@ -3704,32 +3723,29 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car } /* look for unquoted parameters and quote them */ - ptr = s_c; + in_control = FALSE; - while (ptr != NULL && ptr != e_c) { - curr_line = ptr->li_line; + for (ptr = s_c; ptr && ptr != e_c; ptr = ptr->li_next) { + + char *curr_line = ptr->li_line; if (ciprefix(".control", curr_line)) { in_control = TRUE; - ptr = ptr->li_next; continue; } + if (ciprefix(".endc", curr_line)) { in_control = FALSE; - ptr = ptr->li_next; continue; } - if (in_control || curr_line[0] == '.' || curr_line[0] == '*') { - ptr = ptr->li_next; + + if (in_control || curr_line[0] == '.' || curr_line[0] == '*') continue; - } num_terminals = get_number_terminals(curr_line); - if (num_terminals <= 0) { - ptr = ptr->li_next; + if (num_terminals <= 0) continue; - } for (i = 0; i < num_params; i++) { str_ptr = curr_line; @@ -3744,8 +3760,8 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car char before = *(str_ptr-1); char after = *(str_ptr+strlen(param_names[i])); if (!(is_arith_char(before) || isspace(before) || (str_ptr-1) < curr_line) || - !(is_arith_char(after) || isspace(after) || after == '\0')) { - str_ptr = str_ptr + 1; + !(is_arith_char(after) || isspace(after) || after == '\0')) { + str_ptr ++; continue; } beg = str_ptr - 1; @@ -3769,7 +3785,6 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car str_ptr++; } } - ptr = ptr->li_next; } ind = 0; @@ -3814,14 +3829,19 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car static void -inp_add_params_to_subckt(struct line *subckt_card) +inp_add_params_to_subckt(struct names *subckt_w_params, struct line *subckt_card) { struct line *card = subckt_card->li_next; - char *curr_line = card->li_line; char *subckt_line = subckt_card->li_line; char *new_line, *param_ptr, *subckt_name, *end_ptr; - while (card != NULL && ciprefix(".param", curr_line)) { + for (; card; card = card->li_next) { + + char *curr_line = card->li_line; + + if (!ciprefix(".param", curr_line)) + break; + param_ptr = strchr(curr_line, ' '); param_ptr = skip_ws(param_ptr); @@ -3829,23 +3849,22 @@ inp_add_params_to_subckt(struct line *subckt_card) new_line = TMALLOC(char, strlen(subckt_line) + strlen("params: ") + strlen(param_ptr) + 2); sprintf(new_line, "%s params: %s", subckt_line, param_ptr); - subckt_name = skip_non_ws(subckt_card->li_line); + subckt_name = skip_non_ws(subckt_line); subckt_name = skip_ws(subckt_name); end_ptr = skip_non_ws(subckt_name); - subckt_w_params[num_subckt_w_params++] = copy_substring(subckt_name, end_ptr); + add_name(subckt_w_params, copy_substring(subckt_name, end_ptr)); } else { new_line = TMALLOC(char, strlen(subckt_line) + strlen(param_ptr) + 2); sprintf(new_line, "%s %s", subckt_line, param_ptr); } tfree(subckt_line); - subckt_card->li_line = subckt_line = new_line; + subckt_line = new_line; *curr_line = '*'; - - card = card->li_next; - curr_line = card->li_line; } + + subckt_card->li_line = subckt_line; } @@ -3865,7 +3884,7 @@ inp_add_params_to_subckt(struct line *subckt_card) */ static struct line * -inp_reorder_params_subckt(struct line *subckt_card) +inp_reorder_params_subckt(struct names *subckt_w_params, struct line *subckt_card) { struct line *first_param_card = NULL; struct line *last_param_card = NULL; @@ -3884,7 +3903,7 @@ inp_reorder_params_subckt(struct line *subckt_card) } if (ciprefix(".subckt", curr_line)) { - prev_card = inp_reorder_params_subckt(c); + prev_card = inp_reorder_params_subckt(subckt_w_params, c); c = prev_card->li_next; continue; } @@ -3892,7 +3911,7 @@ inp_reorder_params_subckt(struct line *subckt_card) if (ciprefix(".ends", curr_line)) { if (first_param_card) { inp_sort_params(first_param_card, last_param_card, subckt_card, subckt_card, c); - inp_add_params_to_subckt(subckt_card); + inp_add_params_to_subckt(subckt_w_params, subckt_card); } return c; } @@ -3922,7 +3941,7 @@ inp_reorder_params_subckt(struct line *subckt_card) static void -inp_reorder_params(struct line *deck, struct line *list_head, struct line *end) +inp_reorder_params(struct names *subckt_w_params, struct line *deck, struct line *list_head, struct line *end) { struct line *first_param_card = NULL; struct line *last_param_card = NULL; @@ -3941,7 +3960,7 @@ inp_reorder_params(struct line *deck, struct line *list_head, struct line *end) } if (ciprefix(".subckt", curr_line)) { - prev_card = inp_reorder_params_subckt(c); + prev_card = inp_reorder_params_subckt(subckt_w_params, c); c = prev_card->li_next; continue; } @@ -3978,62 +3997,43 @@ inp_reorder_params(struct line *deck, struct line *list_head, struct line *end) // // split line up into multiple lines and place those new lines immediately // afetr the current multi-param line in the deck + static int -inp_split_multi_param_lines(struct line *deck, int line_num) +inp_split_multi_param_lines(struct line *card, int line_num) { - struct line *card = deck, *param_end = NULL, *param_beg = NULL, *prev = NULL, *tmp_ptr; - char *curr_line, *equal_ptr, *beg_param, *end_param, *new_line; - char *array[5000]; - int counter = 0, i; - bool get_expression = FALSE, get_paren_expression = FALSE; - char keep; + for (; card; card = card->li_next) { - while (card != NULL) { - curr_line = card->li_line; + char *curr_line = card->li_line; - if (*curr_line == '*') { - card = card->li_next; + if (*curr_line == '*') continue; - } if (ciprefix(".param", curr_line)) { - counter = 0; - while ((equal_ptr = strchr(curr_line, '=')) != NULL) { - // check for equality '==' - if (equal_ptr[1] == '=') { - curr_line = equal_ptr+2; - continue; - } - // check for '!=', '<=', '>=' - if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - curr_line = equal_ptr+1; - continue; - } + + struct line *param_end, *param_beg; + char *equal_ptr, *array[5000]; + int i, counter = 0; + + while ((equal_ptr = find_assignment(curr_line)) != NULL) { counter++; curr_line = equal_ptr + 1; } - if (counter <= 1) { - card = card->li_next; + + if (counter <= 1) continue; - } // need to split multi param line curr_line = card->li_line; counter = 0; - while (curr_line < card->li_line+strlen(card->li_line) && (equal_ptr = strchr(curr_line, '=')) != NULL) { - // check for equality '==' - if (equal_ptr[1] == '=') { - curr_line = equal_ptr+2; - continue; - } - // check for '!=', '<=', '>=' - if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - curr_line = equal_ptr+1; - continue; - } + while ((equal_ptr = find_assignment(curr_line)) != NULL) { - beg_param = skip_back_ws(equal_ptr - 1); - beg_param = skip_back_non_ws(beg_param); + char keep, *beg_param, *end_param, *new_line; + + bool get_expression = FALSE; + bool get_paren_expression = FALSE; + + beg_param = skip_back_ws_(equal_ptr, curr_line); + beg_param = skip_back_non_ws_(beg_param, curr_line); end_param = skip_ws(equal_ptr + 1); while (*end_param != '\0' && (!isspace(*end_param) || get_expression || get_paren_expression)) { if (*end_param == '{') @@ -4046,7 +4046,6 @@ inp_split_multi_param_lines(struct line *deck, int line_num) get_paren_expression = FALSE; end_param++; } - beg_param++; keep = *end_param; *end_param = '\0'; new_line = TMALLOC(char, strlen(".param ") + strlen(beg_param) + 1); @@ -4055,38 +4054,30 @@ inp_split_multi_param_lines(struct line *deck, int line_num) *end_param = keep; curr_line = end_param; } - tmp_ptr = card->li_next; + + param_beg = param_end = NULL; + for (i = 0; i < counter; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = array[i]; - param_end->li_linenum = line_num++; + struct line *x = xx_new_line(NULL, array[i], line_num++, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } + // comment out current multi-param line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; - - param_beg = param_end = NULL; - } // if (ciprefix(".param", curr_line)) - prev = card; - card = card->li_next; - } // while (card != NULL) - if (param_end) { - prev->li_next = param_beg; - prev = param_end; + } } + return line_num; } @@ -4132,36 +4123,36 @@ inp_split_multi_param_lines(struct line *deck, int line_num) resistance may be lost. Cxxx n1 n2 C = {equation} or Cxxx n1 n2 {equation} - --> - Exxx n-aux 0 n1 n2 1 - Cxxx n-aux 0 1 - Bxxx n2 n1 I = i(Exxx) * equation + --> + Exxx n-aux 0 n1 n2 1 + Cxxx n-aux 0 1 + Bxxx n2 n1 I = i(Exxx) * equation Lxxx n1 n2 L = {equation} or Lxxx n1 n2 {equation} - --> - Fxxx n-aux 0 Bxxx -1 - Lxxx n-aux 0 1 - Bxxx n1 n2 V = v(n-aux) * 1e-16 + --> + Fxxx n-aux 0 Bxxx -1 + Lxxx n-aux 0 1 + Bxxx n1 n2 V = v(n-aux) * 1e-16 + +*/ - */ static void -inp_compat(struct line *deck) +inp_compat(struct line *card) { char *str_ptr, *cut_line, *title_tok, *node1, *node2; char *out_ptr, *exp_ptr, *beg_ptr, *end_ptr, *copy_ptr, *del_ptr; char *xline; size_t xlen, i, pai = 0, paui = 0, ii; char *ckt_array[100]; - struct line *new_line, *tmp_ptr; + struct line *new_line; struct line *param_end = NULL, *param_beg = NULL; - struct line *card; int skip_control = 0; char *equation, *tc1_ptr = NULL, *tc2_ptr = NULL; double tc1 = 0.0, tc2 = 0.0; - for (card = deck; card; card = card->li_next) { + for (; card; card = card->li_next) { char *curr_line = card->li_line; @@ -4198,7 +4189,7 @@ inp_compat(struct line *deck) --> Exxx n1 n2 int1 0 1 BExxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) - */ + */ if ((str_ptr = strstr(curr_line, "table")) != NULL) { char *expression, *firstno, *ffirstno, *secondno, *midline, *lastno, *lastlastno; double fnumber, lnumber, delta; @@ -4210,28 +4201,26 @@ inp_compat(struct line *deck) node2 = gettok(&cut_line); // Exxx n1 n2 int1 0 1 xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) - + 20 - 4*2 + 1; + + 20 - 4*2 + 1; ckt_array[0] = TMALLOC(char, xlen); sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", title_tok, node1, node2, title_tok); // get the expression str_ptr = gettok(&cut_line); /* ignore 'table' */ - if (cieq(str_ptr, "table")) { - tfree(str_ptr); - } else { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + if (!cieq(str_ptr, "table")) { + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } + tfree(str_ptr); str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE); expression = gettok_char(&cut_line, '}', TRUE, TRUE); /* expression */ - if ((!expression) || (!str_ptr)) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + if (!expression || !str_ptr) { + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } - else - tfree(str_ptr); + tfree(str_ptr); /* remove '{' and '}' from expression */ if ((str_ptr = strchr(expression, '{')) != NULL) *str_ptr = ' '; @@ -4249,8 +4238,8 @@ inp_compat(struct line *deck) str_ptr = cut_line; ffirstno = gettok_node(&cut_line); if (!ffirstno) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } firstno = copy(ffirstno); @@ -4271,8 +4260,8 @@ inp_compat(struct line *deck) delta = (lnumber-fnumber)/2.; lastlastno = gettok_node(&cut_line); if (!secondno || (*midline == 0) || (delta <= 0.) || !lastlastno) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } xlen = 2*strlen(title_tok) + strlen(expression) + 14 + strlen(firstno) + @@ -4284,26 +4273,21 @@ inp_compat(struct line *deck) midline, lnumber + delta, lastlastno); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 2; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable e line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -4334,38 +4318,33 @@ inp_compat(struct line *deck) // Exxx n1 n2 int1 0 1 xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) - + 20 - 4*2 + 1; + + 20 - 4*2 + 1; ckt_array[0] = TMALLOC(char, xlen); sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", title_tok, node1, node2, title_tok); // BExxx int1 0 V = {equation} xlen = 2*strlen(title_tok) + strlen(str_ptr) - + 20 - 3*2 + 1; + + 20 - 3*2 + 1; ckt_array[1] = TMALLOC(char, xlen); sprintf(ckt_array[1], "b%s %s_int1 0 v = %s", title_tok, title_tok, str_ptr); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 2; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable e line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -4391,9 +4370,10 @@ inp_compat(struct line *deck) --> Gxxx n1 n2 int1 0 1 BGxxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) - */ + */ if ((str_ptr = strstr(curr_line, "table")) != NULL) { char *expression, *firstno, *ffirstno, *secondno, *midline, *lastno, *lastlastno; + char *m_ptr, *m_token; double fnumber, lnumber, delta; int nerror; cut_line = curr_line; @@ -4402,29 +4382,37 @@ inp_compat(struct line *deck) node1 = gettok(&cut_line); node2 = gettok(&cut_line); // Gxxx n1 n2 int1 0 1 - xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) - + 20 - 4*2 + 1; - ckt_array[0] = TMALLOC(char, xlen); - sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", - title_tok, node1, node2, title_tok); - // get the expression - str_ptr = gettok(&cut_line); /* ignore 'table' */ - if (cieq(str_ptr, "table")) { - tfree(str_ptr); - } else { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); - controlled_exit(EXIT_BAD); - } - str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE); - expression = gettok_char(&cut_line, '}', TRUE, TRUE); /* expression */ - if ((!expression) || (!str_ptr)) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); - controlled_exit(EXIT_BAD); + // or + // Gxxx n1 n2 int1 0 m='expr' + /* find multiplier m at end of line */ + m_ptr = strstr(cut_line, "m="); + if (m_ptr) { + m_token = copy(m_ptr+2); //get only the expression + *m_ptr = '\0'; } else - tfree(str_ptr); + m_token = copy("1"); + xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) + + 20 - 4*2 + strlen(m_token); + ckt_array[0] = TMALLOC(char, xlen); + sprintf(ckt_array[0], "%s %s %s %s_int1 0 %s", + title_tok, node1, node2, title_tok, m_token); + // get the expression + str_ptr = gettok(&cut_line); /* ignore 'table' */ + if (!cieq(str_ptr, "table")) { + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + tfree(str_ptr); + str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE); + expression = gettok_char(&cut_line, '}', TRUE, TRUE); /* expression */ + if (!expression || !str_ptr) { + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + tfree(str_ptr); /* remove '{' and '}' from expression */ if ((str_ptr = strchr(expression, '{')) != NULL) *str_ptr = ' '; @@ -4442,8 +4430,8 @@ inp_compat(struct line *deck) str_ptr = cut_line; ffirstno = gettok_node(&cut_line); if (!ffirstno) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } firstno = copy(ffirstno); @@ -4464,8 +4452,8 @@ inp_compat(struct line *deck) delta = (lnumber-fnumber)/2.; lastlastno = gettok_node(&cut_line); if (!secondno || (*midline == 0) || (delta <= 0.) || !lastlastno) { - fprintf(stderr, "Error: bad sytax in line %d\n %s\n", - card->li_linenum_orig, card->li_line); + fprintf(stderr, "Error: bad syntax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); controlled_exit(EXIT_BAD); } /* BGxxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) */ @@ -4478,26 +4466,21 @@ inp_compat(struct line *deck) midline, lnumber + delta, lastlastno); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 2; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable e line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -4507,14 +4490,16 @@ inp_compat(struct line *deck) tfree(title_tok); tfree(node1); tfree(node2); + tfree(m_token); } /* - Gxxx n1 n2 CUR = {equation} - --> - Gxxx n1 n2 int1 0 1 - BGxxx int1 0 V = {equation} + Gxxx n1 n2 CUR = {equation} + --> + Gxxx n1 n2 int1 0 1 + BGxxx int1 0 V = {equation} */ if ((str_ptr = strstr(curr_line, "cur")) != NULL) { + char *m_ptr, *m_token; cut_line = curr_line; /* title and nodes */ title_tok = gettok(&cut_line); @@ -4526,45 +4511,51 @@ inp_compat(struct line *deck) fprintf(stderr, "ERROR: mal formed G line: %s\n", curr_line); controlled_exit(EXIT_FAILURE); } + /* find multiplier m at end of line */ + m_ptr = strstr(cut_line, "m="); + if (m_ptr) { + m_token = copy(m_ptr + 2); //get only the expression + *m_ptr = '\0'; + } + else + m_token = copy("1"); // Gxxx n1 n2 int1 0 1 + // or + // Gxxx n1 n2 int1 0 m='expr' xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) - + 20 - 4*2 + 1; + + 20 - 4*2 + strlen(m_token); ckt_array[0] = TMALLOC(char, xlen); - sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", - title_tok, node1, node2, title_tok); + sprintf(ckt_array[0], "%s %s %s %s_int1 0 %s", + title_tok, node1, node2, title_tok, m_token); // BGxxx int1 0 V = {equation} xlen = 2*strlen(title_tok) + strlen(str_ptr) - + 20 - 3*2 + 1; + + 20 - 3*2 + 1; ckt_array[1] = TMALLOC(char, xlen); sprintf(ckt_array[1], "b%s %s_int1 0 v = %s", title_tok, title_tok, str_ptr); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 2; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable g line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; param_beg = param_end = NULL; tfree(title_tok); + tfree(m_token); tfree(node1); tfree(node2); } @@ -4634,40 +4625,34 @@ inp_compat(struct line *deck) } if ((tc1_ptr == NULL) && (tc2_ptr == NULL)) { xlen = strlen(title_tok) + strlen(node1) + strlen(node2) + - strlen(node1) + strlen(node2) + strlen(equation) + - 28 - 6*2 + 1; + strlen(node1) + strlen(node2) + strlen(equation) + + 28 - 6*2 + 1; xline = TMALLOC(char, xlen); sprintf(xline, "b%s %s %s i = v(%s, %s)/(%s)", title_tok, node1, node2, node1, node2, equation); } else if (tc2_ptr == NULL) { xlen = strlen(title_tok) + strlen(node1) + strlen(node2) + - strlen(node1) + strlen(node2) + strlen(equation) + - 28 - 6*2 + 1 + 21 + 13; + strlen(node1) + strlen(node2) + strlen(equation) + + 28 - 6*2 + 1 + 21 + 13; xline = TMALLOC(char, xlen); sprintf(xline, "b%s %s %s i = v(%s, %s)/(%s) tc1=%15.8e reciproctc=1", title_tok, node1, node2, node1, node2, equation, tc1); } else { xlen = strlen(title_tok) + strlen(node1) + strlen(node2) + - strlen(node1) + strlen(node2) + strlen(equation) + - 28 - 6*2 + 1 + 21 + 21 + 13; + strlen(node1) + strlen(node2) + strlen(equation) + + 28 - 6*2 + 1 + 21 + 21 + 13; xline = TMALLOC(char, xlen); sprintf(xline, "b%s %s %s i = v(%s, %s)/(%s) tc1=%15.8e tc2=%15.8e reciproctc=1", title_tok, node1, node2, node1, node2, equation, tc1, tc2); } tc1_ptr = NULL; tc2_ptr = NULL; - new_line = alloc(struct line); - new_line->li_next = NULL; - new_line->li_error = NULL; - new_line->li_actual = NULL; - new_line->li_line = xline; - new_line->li_linenum = 0; + new_line = xx_new_line(card->li_next, xline, 0, 0); + // comment out current old R line *(card->li_line) = '*'; // insert new B source line immediately after current line - tmp_ptr = card->li_next; card->li_next = new_line; - new_line->li_next = tmp_ptr; // point 'card' pointer to the new line card = new_line; tfree(title_tok); @@ -4680,7 +4665,7 @@ inp_compat(struct line *deck) Exxx n-aux 0 n1 n2 1 Cxxx n-aux 0 1 Bxxx n2 n1 I = i(Exxx) * equation - */ + */ else if (*curr_line == 'c') { cut_line = curr_line; title_tok = gettok(&cut_line); @@ -4728,31 +4713,31 @@ inp_compat(struct line *deck) } // Exxx n-aux 0 n1 n2 1 xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) - + 21 - 4*2 + 1; + + 21 - 4*2 + 1; ckt_array[0] = TMALLOC(char, xlen); sprintf(ckt_array[0], "e%s %s_int2 0 %s %s 1", title_tok, title_tok, node1, node2); // Cxxx n-aux 0 1 xlen = 2*strlen(title_tok) - + 15 - 2*2 + 1; + + 15 - 2*2 + 1; ckt_array[1] = TMALLOC(char, xlen); sprintf(ckt_array[1], "c%s %s_int2 0 1", title_tok, title_tok); // Bxxx n2 n1 I = i(Exxx) * equation if ((tc1_ptr == NULL) && (tc2_ptr == NULL)) { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 27 - 2*5 + 1; + + strlen(equation) + 27 - 2*5 + 1; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s i = i(e%s) * (%s)", title_tok, node2, node1, title_tok, equation); } else if (tc2_ptr == NULL) { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 27 - 2*5 + 1 + 21 + 13; + + strlen(equation) + 27 - 2*5 + 1 + 21 + 13; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s i = i(e%s) * (%s) tc1=%15.8e reciproctc=1", title_tok, node2, node1, title_tok, equation, tc1); } else { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 27 - 2*5 + 1 + 21 + 21 + 13; + + strlen(equation) + 27 - 2*5 + 1 + 21 + 21 + 13; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s i = i(e%s) * (%s) tc1=%15.8e tc2=%15.8e reciproctc=1", title_tok, node2, node1, title_tok, equation, tc1, tc2); @@ -4760,26 +4745,21 @@ inp_compat(struct line *deck) tc1_ptr = NULL; tc2_ptr = NULL; // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 3; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable capacitor line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -4795,7 +4775,7 @@ inp_compat(struct line *deck) Fxxx n-aux 0 Bxxx -1 Lxxx n-aux 0 1 Bxxx n1 n2 V = v(n-aux) * equation - */ + */ else if (*curr_line == 'l') { cut_line = curr_line; /* title and nodes */ @@ -4843,31 +4823,31 @@ inp_compat(struct line *deck) } // Fxxx n-aux 0 Bxxx 1 xlen = 3*strlen(title_tok) - + 20 - 3*2 + 1; + + 20 - 3*2 + 1; ckt_array[0] = TMALLOC(char, xlen); sprintf(ckt_array[0], "f%s %s_int2 0 b%s -1", title_tok, title_tok, title_tok); // Lxxx n-aux 0 1 xlen = 2*strlen(title_tok) - + 15 - 2*2 + 1; + + 15 - 2*2 + 1; ckt_array[1] = TMALLOC(char, xlen); sprintf(ckt_array[1], "l%s %s_int2 0 1", title_tok, title_tok); // Bxxx n1 n2 V = v(n-aux) * equation if ((tc1_ptr == NULL) && (tc2_ptr == NULL)) { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 31 - 2*5 + 1; + + strlen(equation) + 31 - 2*5 + 1; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s v = v(%s_int2) * (%s)", title_tok, node1, node2, title_tok, equation); } else if (tc2_ptr == NULL) { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 31 - 2*5 + 1 + 21 + 13; + + strlen(equation) + 31 - 2*5 + 1 + 21 + 13; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s v = v(%s_int2) * (%s) tc1=%15.8e reciproctc=0", title_tok, node2, node1, title_tok, equation, tc1); } else { xlen = 2*strlen(title_tok) + strlen(node2) + strlen(node1) - + strlen(equation) + 31 - 2*5 + 1 + 21 + 21 + 13; + + strlen(equation) + 31 - 2*5 + 1 + 21 + 21 + 13; ckt_array[2] = TMALLOC(char, xlen); sprintf(ckt_array[2], "b%s %s %s v = v(%s_int2) * (%s) tc1=%15.8e tc2=%15.8e reciproctc=0", title_tok, node2, node1, title_tok, equation, tc1, tc2); @@ -4875,26 +4855,21 @@ inp_compat(struct line *deck) tc1_ptr = NULL; tc2_ptr = NULL; // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (i = 0; i < 3; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable inductor line *(card->li_line) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -5049,25 +5024,20 @@ inp_compat(struct line *deck) // remove white spaces card->li_line = inp_remove_ws(curr_line); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (ii = paui; ii < pai; ii++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[ii]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[ii], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -5170,26 +5140,21 @@ inp_compat(struct line *deck) // remove white spaces card->li_line = inp_remove_ws(curr_line); // insert new B source line immediately after current line - tmp_ptr = card->li_next; for (ii = paui; ii < pai; ii++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[ii]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[ii], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current variable capacitor line // *(ckt_array[0]) = '*'; // insert new param lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; @@ -5201,8 +5166,10 @@ inp_compat(struct line *deck) } } + /* replace a token (length 4 char) in string by spaces, if it is found - at the correct position and the total number of tokens is o.k. */ + at the correct position and the total number of tokens is o.k. */ + static void replace_token(char *string, char *token, int wherereplace, int total) { @@ -5246,18 +5213,18 @@ replace_token(char *string, char *token, int wherereplace, int total) */ static void -inp_bsource_compat(struct line *deck) +inp_bsource_compat(struct line *card) { char *equal_ptr, *str_ptr, *tmp_char, *new_str, *final_str; char actchar; - struct line *card, *new_line, *tmp_ptr; + struct line *new_line; wordlist *wl = NULL, *wlist = NULL; char buf[512]; size_t i, xlen, ustate = 0; int skip_control = 0; int error1; - for (card = deck; card; card = card->li_next) { + for (; card; card = card->li_next) { char *curr_line = card->li_line; @@ -5384,8 +5351,8 @@ inp_bsource_compat(struct line *deck) Put braces around tokens and around expressions, use ',' as separator like: pwl(i(Vin), {x0-1},{y0}, - {x0},{y0},{x1},{y1}, {x2},{y2},{x3},{y3}, - {x3+1},{y3}) + {x0},{y0},{x1},{y1}, {x2},{y2},{x3},{y3}, + {x3+1},{y3}) */ /* * if (cieq(buf, "pwl")) { @@ -5463,7 +5430,7 @@ inp_bsource_compat(struct line *deck) } } ustate = 0; /* we have a number */ - } else if (isdigit(actchar)) { + } else if (isdigit(actchar) || (actchar == '.')) { /* allow .5 format too */ /* allow 100p, 5MEG etc. */ double dvalue = INPevaluate(&str_ptr, &error1, 0); char cvalue[19]; @@ -5502,20 +5469,13 @@ inp_bsource_compat(struct line *deck) final_str = TMALLOC(char, xlen); sprintf(final_str, "%s %s", tmp_char, new_str); - new_line = alloc(struct line); - new_line->li_next = NULL; - new_line->li_error = NULL; - new_line->li_actual = NULL; - new_line->li_line = final_str; /* Copy old line numbers into new B source line */ - new_line->li_linenum = card->li_linenum; - new_line->li_linenum_orig = card->li_linenum_orig; + new_line = xx_new_line(card->li_next, final_str, card->li_linenum, card->li_linenum_orig); + // comment out current line (old B source line) *(card->li_line) = '*'; // insert new B source line immediately after current line - tmp_ptr = card->li_next; card->li_next = new_line; - new_line->li_next = tmp_ptr; // point 'card' pointer to the new line card = new_line; @@ -5580,7 +5540,7 @@ get_quoted_token(char *string, char **token) * --> * Lxxx n1 n2_intern__ Lval * RLxxx_n2_intern__ n2_intern__ n2 rval -*/ + */ static void inp_add_series_resistor(struct line *deck) @@ -5590,7 +5550,7 @@ inp_add_series_resistor(struct line *deck) struct line *card; char *tmp_p, *title_tok, *node1, *node2, *rval = NULL; char *ckt_array[10]; - struct line *tmp_ptr, *param_end = NULL, *param_beg = NULL; + struct line *param_end = NULL, *param_beg = NULL; for (card = deck; card; card = card->li_next) { char *curr_line = card->li_line; @@ -5648,26 +5608,21 @@ inp_add_series_resistor(struct line *deck) sprintf(ckt_array[1], "R%s_intern__ %s_intern__ %s %s", title_tok, node2, node2, rval); /* assemble new L and R lines */ - tmp_ptr = card->li_next; for (i = 0; i < 2; i++) { - if (param_end) { - param_end->li_next = alloc(struct line); - param_end = param_end->li_next; - } else { - param_end = param_beg = alloc(struct line); - } - param_end->li_next = NULL; - param_end->li_error = NULL; - param_end->li_actual = NULL; - param_end->li_line = ckt_array[i]; - param_end->li_linenum = 0; + struct line *x = xx_new_line(NULL, ckt_array[i], 0, 0); + + if (param_end) + param_end->li_next = x; + else + param_beg = x; + + param_end = x; } // comment out current L line *(card->li_line) = '*'; // insert new new L and R lines immediately after current line - tmp_ptr = card->li_next; + param_end->li_next = card->li_next; card->li_next = param_beg; - param_end->li_next = tmp_ptr; // point 'card' pointer to last in scalar list card = param_end; param_beg = param_end = NULL; @@ -5680,20 +5635,24 @@ inp_add_series_resistor(struct line *deck) tfree(rval); } + /* If XSPICE option is not selected, run this function to alert and exit if the 'poly' option is found in e, g, f, or h controlled sources. */ #ifndef XSPICE -static void -inp_poly_err(struct line *deck) -{ - struct line *card; +static void +inp_poly_err(struct line *card) +{ size_t skip_control = 0; - for (card = deck; card; card = card->li_next) { + + for (; card; card = card->li_next) { + char *curr_line = card->li_line; + if (*curr_line == '*') continue; + /* exclude any command inside .control ... .endc */ if (ciprefix(".control", curr_line)) { skip_control ++; @@ -5704,17 +5663,19 @@ inp_poly_err(struct line *deck) } else if (skip_control > 0) { continue; } + /* get the fourth token in a controlled source line and exit, - if it is 'poly' */ + if it is 'poly' */ if ((ciprefix("e", curr_line)) || (ciprefix("g", curr_line)) || - (ciprefix("f", curr_line)) || (ciprefix("h", curr_line))) { + (ciprefix("f", curr_line)) || (ciprefix("h", curr_line))) + { txfree(gettok(&curr_line)); txfree(gettok(&curr_line)); txfree(gettok(&curr_line)); if (ciprefix("poly", curr_line)) { fprintf(stderr, - "\nError: XSPICE is required to run the 'poly' option in line %d\n", - card->li_linenum_orig); + "\nError: XSPICE is required to run the 'poly' option in line %d\n", + card->li_linenum_orig); fprintf(stderr, " %s\n", card->li_line); fprintf(stderr, "\nSee manual chapt. 31 for installation instructions\n"); controlled_exit(EXIT_BAD); @@ -5722,4 +5683,46 @@ inp_poly_err(struct line *deck) } } } + #endif + + +static void +tprint(struct line *t) +{ + /*debug: print into file*/ + FILE *fd = fopen("tprint-out.txt", "w"); + + for (; t; t = t->li_next) + fprintf(fd, "%d %d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); + + fclose(fd); +} + + +/* prepare .if and .elseif for numparam + .if(expression) --> .if{expression} */ + +static void +inp_dot_if(struct line *card) +{ + for (; card; card = card->li_next) { + + char *curr_line = card->li_line; + + if (*curr_line == '*') + continue; + + if (ciprefix(".if", curr_line) || ciprefix(".elseif", curr_line)) { + char* firstbr = strchr(curr_line, '('); + char* lastbr = strrchr(curr_line, ')'); + if ((!firstbr) || (!lastbr)) { + fprintf(cp_err, "Error in netlist line %d\n", card->li_linenum_orig); + fprintf(cp_err, " Bad syntax: %s\n\n", curr_line); + controlled_exit(EXIT_BAD); + } + *firstbr = '{'; + *lastbr = '}'; + } + } +} diff --git a/src/frontend/measure.c b/src/frontend/measure.c index f74fb821c..546bf92d3 100644 --- a/src/frontend/measure.c +++ b/src/frontend/measure.c @@ -239,6 +239,14 @@ do_measure( return (measures_passed); } + /* don't allow autostop if no .meas commands are given in the input file */ + if ((cp_getvar("autostop", CP_BOOL, NULL)) && (ft_curckt->ci_meas == NULL)) { + fprintf(cp_err, "\nWarning: No .meas commands found!\n"); + fprintf(cp_err, " Option autostop is not available, ignored!\n\n"); + cp_remvar("autostop"); + return (FALSE); + } + /* Evaluating the linked list of .meas cards, assembled from the input deck by fcn inp_spsource() in inp.c:575. A typical .meas card will contain: diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index b6902e78a..844d96481 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -189,6 +189,11 @@ com_version(wordlist *wl) fprintf(cp_out, "** %s\n", Spice_Notice); if (Spice_Build_Date != NULL && *Spice_Build_Date != 0) fprintf(cp_out, "** Creation Date: %s\n", Spice_Build_Date); + +#ifdef KIRCHHOFF + fprintf(cp_out, "** KCL Verification enabled.\n"); +#endif + fprintf(cp_out, "******\n"); } else { @@ -279,6 +284,9 @@ com_version(wordlist *wl) #endif #ifdef EXP_DEV fprintf(cp_out, "** Experimental devices enabled.\n"); +#endif +#ifdef KIRCHHOFF + fprintf(cp_out, "** KCL Verification enabled.\n"); #endif fprintf(cp_out, "******\n"); diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 85d9c99a2..71c1df6c2 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -16,7 +16,7 @@ typedef enum {Nodekey = '#'} _nNodekey; /* Introduces node symbol */ typedef enum {Intro = '&'} _nIntro; /* Introduces preprocessor tokens */ typedef enum {Comment = '*'} _nComment; /* Spice Comment lines */ typedef enum {Psp = '{'} _nPsp; /* Ps expression */ -typedef enum {Defd = 15} _nDefd; /* serial numb. of 'defined' keyword. +typedef enum {Defd = 6} _nDefd; /* serial numb. of 'defined' keyword. The others are not used (yet) */ typedef char *auxtable; /* dummy */ diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index 5010c6470..4b98d5062 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -243,6 +243,11 @@ modernizeex(SPICE_DSTRINGPTR dstr_p) state = 0; ls = spice_dstring_length(dstr_p); s = spice_dstring_value(dstr_p); + + /* check if string might need modernizing */ + if (!memchr(s, Intro, (size_t) ls)) + return; + spice_dstring_init(&t); while (i < ls) { diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 20855b8e8..77c51b81a 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -88,8 +88,7 @@ initkeys(void) { spice_dstring_init(&keyS); scopy_up(&keyS, - "and or not div mod if else end while macro funct defined" - " include for to downto is var"); + "and or not div mod defined"); scopy_up(&fmathS, "sqr sqrt sin cos exp ln arctan abs pow pwr max min int log sinh cosh" " tanh ternary_fcn v agauss sgn gauss unif aunif limit ceil floor"); @@ -935,7 +934,7 @@ opfunctkey(tdico *dico, /*if kw operator keyword, c=token*/ switch (kw) { - /* & | ~ DIV MOD Defined */ + /* & | ~ DIV MOD Defined */ case 1: c = '&'; state = 2; diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index 08c81ad4d..ae78087db 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -81,10 +81,10 @@ static IFvalue *doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel IFparm *opt, int ind); static int doset(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, IFparm *opt, struct dvec *val); -static int finddev(CKTcircuit *ck, char *name, GENinstance **devptr, GENmodel **modptr); +static int finddev(CKTcircuit *ckt, char *name, GENinstance **devptr, GENmodel **modptr); /* espice fix integration */ -static int finddev_special(CKTcircuit *ck, char *name, GENinstance **devptr, GENmodel **modptr, int *device_or_model); +static int finddev_special(CKTcircuit *ckt, char *name, GENinstance **devptr, GENmodel **modptr, int *device_or_model); /* Input a single deck, and return a pointer to the circuit. */ @@ -252,8 +252,7 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab) /*CDHW Create an interactive task AAA with a new UID. ci_specTask will point to it CDHW*/ - err = IFnewUid(ft_curckt->ci_ckt, &specUid, NULL, "special", - UID_TASK, NULL); + err = IFnewUid(ft_curckt->ci_ckt, &specUid, NULL, "special", UID_TASK, NULL); if (err) { ft_sperror(err, "newUid"); return (2); @@ -281,8 +280,7 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab) } if (which != -1) { /*CDHW options are available CDHW*/ - err = IFnewUid(ft_curckt->ci_ckt, &optUid, NULL, "options", - UID_ANALYSIS, NULL); + err = IFnewUid(ft_curckt->ci_ckt, &optUid, NULL, "options", UID_ANALYSIS, NULL); if (err) { ft_sperror(err, "newUid"); return (2); @@ -616,7 +614,7 @@ finddev_special( int err; int type = -1; - err = ft_sim->findInstance (ckt, &type, devptr, name, NULL, NULL); + err = ft_sim->findInstance (ckt, &type, devptr, name, NULL); if (err == OK) { *device_or_model = 0; return (type); @@ -1212,19 +1210,19 @@ doset(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, IFparm *op */ static int -finddev(CKTcircuit *ck, char *name, GENinstance **devptr, GENmodel **modptr) +finddev(CKTcircuit *ckt, char *name, GENinstance **devptr, GENmodel **modptr) { int err; int type = -1; - err = ft_sim->findInstance (ck, &type, devptr, name, NULL, NULL); + err = ft_sim->findInstance (ckt, &type, devptr, name, NULL); if (err == OK) return (type); type = -1; *devptr = NULL; - err = ft_sim->findModel (ck, &type, modptr, name); + err = ft_sim->findModel (ckt, &type, modptr, name); if (err == OK) return (type); @@ -1273,8 +1271,7 @@ if_tranparams(struct circ *ci, double *start, double *stop, double *step) if (which == -1) return (FALSE); - err = IFnewUid(ci->ci_ckt, &tranUid, NULL, "Transient Analysis", - UID_ANALYSIS, NULL); + err = IFnewUid(ci->ci_ckt, &tranUid, NULL, "Transient Analysis", UID_ANALYSIS, NULL); if (err != OK) return (FALSE); @@ -1616,11 +1613,11 @@ void com_snload(wordlist *wl) return; } SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, "time", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - timeUid, IF_REAL, - numNames, nameList, IF_REAL, &(((TRANan*)ckt->CKTcurJob)->TRANplot)); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + timeUid, IF_REAL, + numNames, nameList, IF_REAL, + &(((TRANan*)ckt->CKTcurJob)->TRANplot)); if (error) { fprintf(cp_err, "error in CKTnames\n"); return; diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index b819b1904..278f510d6 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -1815,6 +1815,7 @@ devmodtranslate(struct line *deck, char *subname, wordlist * const submod) case 'r': case 'c': + case 'l': name = gettok(&t); /* get refdes */ (void) sprintf(buffer, "%s ", name); tfree(name); @@ -1967,7 +1968,7 @@ devmodtranslate(struct line *deck, char *subname, wordlist * const submod) name = gettok(&t); found = 0; - while (*t && !found) { + while (!found) { /* Now, is this a subcircuit model? */ for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) { /* FIXME, probably too unspecific */ @@ -1994,6 +1995,10 @@ devmodtranslate(struct line *deck, char *subname, wordlist * const submod) (void) sprintf(buffer + strlen(buffer), "%s ", name); tfree(name); name = gettok(&t); + if (name == NULL) { + name = copy(""); /* allow 'tfree' */ + break; + } } } /* while */ diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 452787130..8f131219a 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -56,6 +56,12 @@ struct CKTnode { #define PARM_IC 2 #define PARM_NODETYPE 3 +#ifdef KIRCHHOFF +typedef struct sCKTmkCurKCLnode { + double KCLcurrent ; + struct sCKTmkCurKCLnode *next ; +} CKTmkCurKCLnode ; +#endif struct CKTcircuit { @@ -110,6 +116,13 @@ struct CKTcircuit { double *CKTrhs; /* current rhs value - being loaded */ double *CKTrhsOld; /* previous rhs value for convergence testing */ + +#ifdef KIRCHHOFF + double *CKTfvk ; /* KCL Verification array */ + int *CKTnodeIsLinear ; /* Flag to indicate if a node is linear or non-linear */ + CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */ +#endif + double *CKTrhsSpare; /* spare rhs value for reordering */ double *CKTirhs; /* current rhs value - being loaded (imag) */ @@ -289,7 +302,11 @@ struct CKTcircuit { }; -/* Now function prottypes */ +/* Now function prototypes */ + +#ifdef KIRCHHOFF +extern int CKTmkCurKCL (CKTcircuit *, int, double **) ; +#endif extern int ACan(CKTcircuit *, int); extern int ACaskQuest(CKTcircuit *, JOB *, int , IFvalue *); @@ -321,7 +338,7 @@ extern void NDEVacct(CKTcircuit *ckt, FILE *file); extern void CKTncDump(CKTcircuit *); extern int CKTfndAnal(CKTcircuit *, int *, JOB **, IFuid , TSKtask *, IFuid); extern int CKTfndBranch(CKTcircuit *, IFuid); -extern int CKTfndDev(CKTcircuit *, int *, GENinstance **, IFuid , GENmodel *, IFuid); +extern int CKTfndDev(CKTcircuit *, int *, GENinstance **, IFuid , GENmodel *); extern int CKTfndMod(CKTcircuit *, int *, GENmodel **, IFuid); extern int CKTfndNode(CKTcircuit *, CKTnode **, IFuid); extern int CKTfndTask(CKTcircuit *, TSKtask **, IFuid ); @@ -387,10 +404,14 @@ extern int PZinit(CKTcircuit *); extern int PZpost(CKTcircuit *); extern int PZaskQuest(CKTcircuit *, JOB *, int , IFvalue *); extern int PZsetParm(CKTcircuit *, JOB *, int , IFvalue *); + +#ifdef WANT_SENSE2 extern int SENaskQuest(CKTcircuit *, JOB *, int , IFvalue *); extern void SENdestroy(SENstruct *); extern int SENsetParm(CKTcircuit *, JOB *, int , IFvalue *); -extern int SENstartup(CKTcircuit *); +extern int SENstartup(CKTcircuit *, int); +#endif + extern int SPIinit(IFfrontEnd *, IFsimulator **); extern int TFanal(CKTcircuit *, int); extern int TFaskQuest(CKTcircuit *, JOB *, int , IFvalue *); diff --git a/src/include/ngspice/defines.h b/src/include/ngspice/defines.h index 98663e245..99c28c302 100644 --- a/src/include/ngspice/defines.h +++ b/src/include/ngspice/defines.h @@ -74,7 +74,7 @@ /* Alternate initialisation file name */ #define ALT_INITSTR "spice.rc" -#if defined(__MINGW32__) || defined(_MSC_VER) +#if defined(__MINGW32__) || defined(_MSC_VER) || defined (HAS_WINGUI) #define DIR_PATHSEP "\\" #define DIR_TERM '\\' #define DIR_PATHSEP_LINUX "/" diff --git a/src/include/ngspice/devdefs.h b/src/include/ngspice/devdefs.h index be17f58e4..c5934f258 100644 --- a/src/include/ngspice/devdefs.h +++ b/src/include/ngspice/devdefs.h @@ -28,10 +28,21 @@ double limitJunctionVoltage( double, double, int * ); double limitVbe( double, double, int * ); double limitVce( double, double, int * ); double limitVgb( double, double, int * ); - - - +/* Area Calculation Method (ACM) for MOS models (devsup.c) */ +int +ACM_SourceDrainResistances(int, double, double, double, double, double, + double, double, int, double, double, double, + int, double, double, double, double *, double *); +int +ACM_saturationCurrents(int, int, int, double, double, double, double, double, + double, int, double, int, double, int, double, int, + double, double *, double *); +int +ACM_junctionCapacitances(int, int, int, double, double, double, double, int, + double, int, double, int, double, int, double, + double, double, double, double *, double *, + double *, double *, double *, double *); typedef struct SPICEdev { IFdevice DEVpublic; @@ -110,6 +121,12 @@ typedef struct SPICEdev { /* routine to convert Complex CSC array to Real CSC array */ #endif +#ifdef KIRCHHOFF + /* Francesco Lannutti */ + int (*DEVnodeIsNonLinear)(GENmodel *, CKTcircuit *) ; + /* Routine to declare a node as NonLinear */ +#endif + } SPICEdev; /* instance of structure for each possible type of device */ diff --git a/src/include/ngspice/ifsim.h b/src/include/ngspice/ifsim.h index 47b328435..e24f4f111 100644 --- a/src/include/ngspice/ifsim.h +++ b/src/include/ngspice/ifsim.h @@ -370,7 +370,7 @@ struct IFsimulator { /* set a parameter on an instance */ int (*askInstanceQuest) (CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); /* ask a question about an instance */ - int (*findInstance) (CKTcircuit *, int *, GENinstance **, IFuid, GENmodel *, IFuid); + int (*findInstance) (CKTcircuit *, int *, GENinstance **, IFuid, GENmodel *); /* find a specific instance */ int (*deleteInstance) (CKTcircuit *, void *); /* delete an instance from the circuit */ diff --git a/src/include/ngspice/inpmacs.h b/src/include/ngspice/inpmacs.h index 02aaa7604..dd5799e32 100644 --- a/src/include/ngspice/inpmacs.h +++ b/src/include/ngspice/inpmacs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. **********/ + /* a couple of macros to make much of the input code * much much shorter and easier to handle. * @@ -9,25 +10,42 @@ Copyright 1990 Regents of the University of California. All rights reserved. * If necessary, get the proper error message and tack it on the current * error */ -#define IFC(func,args)\ -error=(*(ft_sim->func))args;\ -if(error)current->error = INPerrCat(current->error,INPerror(error)); + +#define IFC(func, args) \ + do { \ + error = (*(ft_sim->func)) args; \ + if (error) \ + current->error = INPerrCat(current->error, INPerror(error)); \ + } while(0) + /* and one for calling more General functions that still return an * error code as above */ -#define GCA(func,args)\ -error=func args;\ -if(error)current->error = INPerrCat(current->error,INPerror(error)); -/* and one for putting our own error messages onto the current +#define GCA(func, args) \ + do { \ + error = func args; \ + if (error) \ + current->error = INPerrCat(current->error, INPerror(error)); \ + } while(0) + + +/* and one for putting our own error messages onto the current * line's error string */ -#define LITERR(text) current->error=INPerrCat(current->error,INPmkTemp(text)); + +#define LITERR(text) \ + do { \ + current->error = INPerrCat(current->error, INPmkTemp(text)); \ + } while(0) /* and now a special one for calling INPdevParse which returns an * already concatenated list of error messages or NUL */ -#define PARSECALL(args)\ -current->error = INPerrCat(current->error,INPdevParse args ); + +#define PARSECALL(args) \ + do { \ + current->error = INPerrCat(current->error, INPdevParse args); \ + } while(0) diff --git a/src/include/ngspice/inpptree.h b/src/include/ngspice/inpptree.h index 53781d2af..77804890d 100644 --- a/src/include/ngspice/inpptree.h +++ b/src/include/ngspice/inpptree.h @@ -123,10 +123,11 @@ void INPptPrint(char *str, IFparseTree * ptree); #define PTF_GE0 28 #define PTF_LE0 29 #define PTF_POW 30 -#define PTF_MIN 31 -#define PTF_MAX 32 -#define PTF_CEIL 33 -#define PTF_FLOOR 34 +#define PTF_PWR 31 +#define PTF_MIN 32 +#define PTF_MAX 33 +#define PTF_CEIL 34 +#define PTF_FLOOR 35 /* The following things are used by the parser -- these are the token types the * lexer returns. diff --git a/src/include/ngspice/macros.h b/src/include/ngspice/macros.h index 284edab31..c485517cf 100644 --- a/src/include/ngspice/macros.h +++ b/src/include/ngspice/macros.h @@ -43,11 +43,12 @@ #define NIL(type) ((type *)0) #define ABORT() fflush(stderr);fflush(stdout);abort(); -#define MERROR(CODE,MESSAGE) { \ - errMsg = TMALLOC(char, strlen(MESSAGE) + 1); \ - strcpy(errMsg, (MESSAGE)); \ - return (CODE); \ - } +#define MERROR(CODE, MESSAGE) \ + do { \ + errMsg = TMALLOC(char, strlen(MESSAGE) + 1); \ + strcpy(errMsg, (MESSAGE)); \ + return (CODE); \ + } while(0) #define NEW(TYPE) (TMALLOC(TYPE, 1)) #define NEWN(TYPE,COUNT) (TMALLOC(TYPE, COUNT)) diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index f5852abe5..efdc6ff60 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -112,7 +112,9 @@ struct ngcomplex { typedef struct ngcomplex ngcomplex_t; #endif -/* vector info obtained from any vector in ngspice.dll */ +/* vector info obtained from any vector in ngspice.dll. + Allows direct access to the ngspice internal vector structure, + as defined in include/ngspice/devc.h .*/ typedef struct vector_info { char *v_name; /* Same as so_vname. */ int v_type; /* Same as so_vtype. */ @@ -123,16 +125,17 @@ typedef struct vector_info { } vector_info, *pvector_info; typedef struct vecvalues { - char* name; - double creal; - double cimag; - bool is_scale; - bool is_complex; + char* name; /* name of a specific vector */ + double creal; /* actual data value */ + double cimag; /* actual data value */ + bool is_scale;/* if 'name' is the scale vector */ + bool is_complex;/* if the data are complex numbers */ } vecvalues, *pvecvalues; typedef struct vecvaluesall { - int veccount; - pvecvalues *vecsa; + int veccount; /* number of vectors in plot */ + int vecindex; /* index of actual set of vectors. i.e. the number of accepted data points */ + pvecvalues *vecsa; /* values of actual set of vectors, indexed from 0 to veccount - 1 */ } vecvaluesall, *pvecvaluesall; /* info for a specific vector */ @@ -206,6 +209,18 @@ typedef int (BGThreadRunning)(bool, void*); void* return pointer received from caller */ +/* callback functions +addresses received from caller with ngSpice_Init_Sync() function +*/ + +/* ask for VSRC EXTERNAL value */ +typedef int (GetVSRCData)(double*, double, char*, void*); +/* + double* return voltage value + double actual time + char* node name + void* return pointer received from caller +*/ /* ngspice initialization, printfcn: pointer to callback function for reading printf, fprintf @@ -220,6 +235,12 @@ IMPEXP int ngSpice_Init(SendChar* printfcn, SendStat* statfcn, ControlledExit* ngexit, SendData* sdata, SendInitData* sinitdata, BGThreadRunning* bgtrun, void* userData); +/* initialization of synchronizing functions +vsrcdat: pointer to callback function for retrieving a voltage source value +ident: pointer to integer unique to this shared library (defaults to 0) +*/ +IMPEXP +int ngSpice_Init_Sync(GetVSRCData* vsrcdat, int* ident, void* userData); /* Caller may send ngspice commands to ngspice.dll. Commands are executed immediately */ @@ -260,6 +281,10 @@ char** ngSpice_AllVecs(char* plotname); IMPEXP bool ngSpice_running(void); +/* set a breakpoint in ngspice */ +IMPEXP +bool ngSpice_SetBkpt(double time); + #ifdef __cplusplus } diff --git a/src/include/ngspice/smpdefs.h b/src/include/ngspice/smpdefs.h index cde5d0610..3a8be515c 100644 --- a/src/include/ngspice/smpdefs.h +++ b/src/include/ngspice/smpdefs.h @@ -122,8 +122,8 @@ void SMPgetError( SMPmatrix *, int *, int *); int SMPcProdDiag( SMPmatrix *, SPcomplex *, int *); int SMPcDProd(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent); 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); +int SMPcZeroCol(SMPmatrix *Matrix, int Col); +int SMPcAddCol(SMPmatrix *Matrix, int Accum_Col, int Addend_Col); +int SMPzeroRow(SMPmatrix *Matrix, int Row); #endif diff --git a/src/include/ngspice/spmatrix.h b/src/include/ngspice/spmatrix.h index b3ceabfb3..77ecc2ad9 100644 --- a/src/include/ngspice/spmatrix.h +++ b/src/include/ngspice/spmatrix.h @@ -263,7 +263,7 @@ extern int spFileMatrix( MatrixPtr, char *, char *, int, int, int ); extern int spFileStats( MatrixPtr, char *, char * ); extern int spFillinCount( MatrixPtr ); extern int spGetAdmittance( MatrixPtr, int, int, struct spTemplate* ); -extern spREAL *spFindElement(MatrixPtr eMatrix, int Row, int Col ); +extern spREAL *spFindElement(MatrixPtr Matrix, int Row, int Col ); extern spREAL *spGetElement(MatrixPtr, int, int ); extern void *spGetInitInfo( spREAL* ); extern int spGetOnes( MatrixPtr, int, int, int, struct spTemplate* ); diff --git a/src/maths/misc/equality.c b/src/maths/misc/equality.c index 83c4ad3c5..f16380431 100644 --- a/src/maths/misc/equality.c +++ b/src/maths/misc/equality.c @@ -24,6 +24,11 @@ bool AlmostEqualUlps(double A, double B, int maxUlps) { int64_t aInt, bInt, intDiff; + union { + double d; + int64_t i; + } uA, uB; + if (A == B) return TRUE; @@ -34,12 +39,14 @@ bool AlmostEqualUlps(double A, double B, int maxUlps) /* default NAN won't compare as equal to anything. */ assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); - aInt = *(int64_t*)&A; + uA.d = A; + aInt = uA.i; /* Make aInt lexicographically ordered as a twos-complement int */ if (aInt < 0) aInt = int64_min - aInt; - bInt = *(int64_t*)&B; + uB.d = B; + bInt = uB.i; /* Make bInt lexicographically ordered as a twos-complement int */ if (bInt < 0) bInt = int64_min - bInt; diff --git a/src/maths/ni/nicomcof.c b/src/maths/ni/nicomcof.c index 7dcd7ed38..4fde133e8 100644 --- a/src/maths/ni/nicomcof.c +++ b/src/maths/ni/nicomcof.c @@ -7,6 +7,9 @@ Author: 1985 Thomas L. Quarles #include "ngspice/cktdefs.h" #include "ngspice/sperror.h" +/* xmu=0: Backward Euler, xmu=0.5: trapezoidal (standard), + xmu=0.48: good damping of current ringing, e.g. in R.O.s. */ +#define xmu 0.5 int NIcomCof(CKTcircuit *ckt) @@ -17,6 +20,7 @@ NIcomCof(CKTcircuit *ckt) double arg; double arg1; + /* this routine calculates the timestep-dependent terms used in the * numerical integration. */ @@ -35,10 +39,8 @@ NIcomCof(CKTcircuit *ckt) break; case 2: - ckt->CKTag[0]=1.0/ckt->CKTdelta/(1.0-0.5) ; - ckt->CKTag[1]=0.5/(1.0 - 0.5) ; - /* above lines should have 'xmu' instead of .5 eventually */ - /* (in all three places) */ + ckt->CKTag[0] = 1.0 / ckt->CKTdelta/(1.0 - xmu) ; + ckt->CKTag[1] = xmu / (1.0 - xmu) ; break; default: diff --git a/src/maths/ni/niconv.c b/src/maths/ni/niconv.c index 988fd30f2..8c4c8c6a9 100644 --- a/src/maths/ni/niconv.c +++ b/src/maths/ni/niconv.c @@ -15,62 +15,124 @@ Author: 1985 Thomas L. Quarles #include "ngspice/smpdefs.h" -int -NIconvTest(CKTcircuit *ckt) -{ - int i; /* generic loop variable */ - int size; /* size of the matrix */ - CKTnode *node; /* current matrix entry */ - double old; - double new; - double tol; - node = ckt->CKTnodes; - size = SMPmatSize(ckt->CKTmatrix); +int +NIconvTest (CKTcircuit *ckt) +{ + int i ; /* generic loop variable */ + int size ; /* size of the matrix */ + CKTnode *node ; /* current matrix entry */ + +#ifdef KIRCHHOFF + double maximum ; + CKTmkCurKCLnode *ptr ; + #ifdef STEPDEBUG - for (i=1;i<=size;i++) { - new = ckt->CKTrhs [i] ; - old = ckt->CKTrhsOld [i] ; - printf("chk for convergence: %s new: %g old: %g\n",CKTnodName(ckt,i),new,old); + int j ; +#endif +#else + double old, new, tol ; +#endif + + size = SMPmatSize (ckt->CKTmatrix) ; + node = ckt->CKTnodes ; + +#ifndef KIRCHHOFF +#ifdef STEPDEBUG + for (i = 1 ; i <= size ; i++) + { + new = ckt->CKTrhs [i] ; + old = ckt->CKTrhsOld [i] ; + fprintf (err, "chk for convergence: %s new: %g old: %g\n", CKTnodName (ckt, i), new, old) ; } #endif /* STEPDEBUG */ - for (i=1;i<=size;i++) { - node = node->next; - new = ckt->CKTrhs [i] ; - old = ckt->CKTrhsOld [i] ; - if(node->type == SP_VOLTAGE) { - tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + - ckt->CKTvoltTol; - if (fabs(new-old) >tol ) { +#endif + + for (i = 1 ; i <= size ; i++) + { + node = node->next ; + +#ifdef KIRCHHOFF + /* KCL Verification */ + if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i])) + { + maximum = 0 ; + ptr = ckt->CKTmkCurKCLarray [i] ; + #ifdef STEPDEBUG - printf(" non-convergence at node (type=3) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",CKTnodName(ckt,i),new,old,tol); - printf(" reltol: %g voltTol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + voltTol)\n",ckt->CKTreltol,ckt->CKTvoltTol); + j = 0 ; +#endif + + while (ptr != NULL) + { + if (maximum < fabs (ptr->KCLcurrent)) + maximum = fabs (ptr->KCLcurrent) ; + +#ifdef STEPDEBUG + fprintf (stderr, "Index KCL Array: %d\tValue: %-.9g\tMaximum: %-.9g\n", j, fabs (ptr->KCLcurrent), maximum) ; + j++ ; +#endif + + ptr = ptr->next ; + } + +#ifdef STEPDEBUG + fprintf (stderr, "Index: %d\tValue: %-.9g\tThreshold: %-.9g\tMaximum: %-.9g\n", i, fabs (ckt->CKTfvk [i]), + ckt->CKTreltol * maximum + ckt->CKTabstol, maximum) ; +#endif + + /* Check Convergence */ + if (fabs (ckt->CKTfvk [i]) > (ckt->CKTreltol * maximum + ckt->CKTabstol)) + return 1 ; + } +#else + new = ckt->CKTrhs [i] ; + old = ckt->CKTrhsOld [i] ; + if (node->type == SP_VOLTAGE) + { + tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTvoltTol ; + if (fabs (new - old) > tol) + { + +#ifdef STEPDEBUG + fprintf (err, " non-convergence at node (type=3) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n", CKTnodName (ckt, i), new, old, tol) ; + fprintf (err, " reltol: %g voltTol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + voltTol)\n", ckt->CKTreltol, ckt->CKTvoltTol) ; #endif /* STEPDEBUG */ - ckt->CKTtroubleNode = i; - ckt->CKTtroubleElt = NULL; - return(1); + + ckt->CKTtroubleNode = i ; + ckt->CKTtroubleElt = NULL ; + return 1 ; } } else { - tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + - ckt->CKTabstol; - if (fabs(new-old) >tol ) { + tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTabstol ; + if (fabs (new - old) > tol) + { + #ifdef STEPDEBUG - printf(" non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",node->type,CKTnodName(ckt,i),new,old,tol); - printf(" reltol: %g abstol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + abstol)\n",ckt->CKTreltol,ckt->CKTabstol); + fprintf (err, " non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n", node->type, + CKTnodName (ckt, i), new, old, tol) ; + fprintf (err, " reltol: %g abstol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + abstol)\n", ckt->CKTreltol, ckt->CKTabstol) ; #endif /* STEPDEBUG */ - ckt->CKTtroubleNode = i; - ckt->CKTtroubleElt = NULL; - return(1); + + ckt->CKTtroubleNode = i ; + ckt->CKTtroubleElt = NULL ; + return 1 ; } } +#endif + } +#ifdef KIRCHHOFF + return 0 ; +#else #ifdef NEWCONV - i = CKTconvTest(ckt); + i = CKTconvTest (ckt) ; if (i) - ckt->CKTtroubleNode = 0; - return(i); + ckt->CKTtroubleNode = 0 ; + return i ; #else /* NEWCONV */ - return(0); + return 0 ; #endif /* NEWCONV */ +#endif /* KIRCHHOFF */ } diff --git a/src/maths/ni/nireinit.c b/src/maths/ni/nireinit.c index cc14aee53..17a114f90 100644 --- a/src/maths/ni/nireinit.c +++ b/src/maths/ni/nireinit.c @@ -22,9 +22,10 @@ int NIreinit( CKTcircuit *ckt) { int size; -#ifdef PREDICTOR + +#if defined(PREDICTOR) || defined(KIRCHHOFF) int i; -#endif +#endif size = SMPmatSize(ckt->CKTmatrix); CKALLOC(CKTrhs,size+1,double); @@ -33,6 +34,17 @@ NIreinit( CKTcircuit *ckt) CKALLOC(CKTirhs,size+1,double); CKALLOC(CKTirhsOld,size+1,double); CKALLOC(CKTirhsSpare,size+1,double); + +#ifdef KIRCHHOFF + CKALLOC(CKTfvk,size+1,double); + CKALLOC(CKTnodeIsLinear,size+1,int); + for (i = 0 ; i <= size ; i++) + ckt->CKTnodeIsLinear [i] = 1 ; + CKALLOC(CKTmkCurKCLarray,size+1,CKTmkCurKCLnode*); + for (i = 0 ; i <= size ; i++) + ckt->CKTmkCurKCLarray [i] = NULL ; +#endif + #ifdef PREDICTOR CKALLOC(CKTpred,size+1,double); for( i=0;i<8;i++) { diff --git a/src/maths/sparse/spalloc.c b/src/maths/sparse/spalloc.c index fe8713e8b..b70031cbd 100644 --- a/src/maths/sparse/spalloc.c +++ b/src/maths/sparse/spalloc.c @@ -190,7 +190,7 @@ spCreate(int Size, int Complex, int *pError) Matrix->ElementsRemaining = 0; Matrix->FillinsRemaining = 0; - RecordAllocation( Matrix, (void *)Matrix ); + RecordAllocation( Matrix, Matrix ); if (Matrix->Error == spNO_MEMORY) goto MemoryError; /* Take out the trash. */ @@ -311,7 +311,7 @@ spcGetElement(MatrixPtr Matrix) /* Allocate block of MatrixElements if necessary. */ if (Matrix->ElementsRemaining == 0) { pElements = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); - RecordAllocation( Matrix, (void *)pElements ); + RecordAllocation( Matrix, pElements ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailElement = pElements; @@ -331,14 +331,14 @@ spcGetElement(MatrixPtr Matrix) } else { /* Allocate block of elements. */ pElements = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); - RecordAllocation( Matrix, (void *)pElements ); + RecordAllocation( Matrix, pElements ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailElement = pElements; /* Allocate an element list structure. */ pListNode->Next = SP_MALLOC(struct ElementListNodeStruct,1); - RecordAllocation( Matrix, (void *)pListNode->Next ); + RecordAllocation( Matrix, pListNode->Next ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->LastElementListNode = pListNode = pListNode->Next; @@ -402,14 +402,14 @@ InitializeElementBlocks(MatrixPtr Matrix, int InitialNumberOfElements, /* Allocate block of MatrixElements for elements. */ pElement = SP_MALLOC(struct MatrixElement, InitialNumberOfElements); - RecordAllocation( Matrix, (void *)pElement ); + RecordAllocation( Matrix, pElement ); if (Matrix->Error == spNO_MEMORY) return; Matrix->ElementsRemaining = InitialNumberOfElements; Matrix->NextAvailElement = pElement; /* Allocate an element list structure. */ Matrix->FirstElementListNode = SP_MALLOC(struct ElementListNodeStruct,1); - RecordAllocation( Matrix, (void *)Matrix->FirstElementListNode ); + RecordAllocation( Matrix, Matrix->FirstElementListNode ); if (Matrix->Error == spNO_MEMORY) return; Matrix->LastElementListNode = Matrix->FirstElementListNode; @@ -420,14 +420,14 @@ InitializeElementBlocks(MatrixPtr Matrix, int InitialNumberOfElements, /* Allocate block of MatrixElements for fill-ins. */ pElement = SP_MALLOC(struct MatrixElement, NumberOfFillinsExpected); - RecordAllocation( Matrix, (void *)pElement ); + RecordAllocation( Matrix, pElement ); if (Matrix->Error == spNO_MEMORY) return; Matrix->FillinsRemaining = NumberOfFillinsExpected; Matrix->NextAvailFillin = pElement; /* Allocate a fill-in list structure. */ Matrix->FirstFillinListNode = SP_MALLOC(struct FillinListNodeStruct,1); - RecordAllocation( Matrix, (void *)Matrix->FirstFillinListNode ); + RecordAllocation( Matrix, Matrix->FirstFillinListNode ); if (Matrix->Error == spNO_MEMORY) return; Matrix->LastFillinListNode = Matrix->FirstFillinListNode; @@ -487,14 +487,14 @@ spcGetFillin(MatrixPtr Matrix) } else { /* Allocate block of fill-ins. */ pFillins = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); - RecordAllocation( Matrix, (void *)pFillins ); + RecordAllocation( Matrix, pFillins ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailFillin = pFillins; /* Allocate a fill-in list structure. */ pListNode->Next = SP_MALLOC(struct FillinListNodeStruct,1); - RecordAllocation( Matrix, (void *)pListNode->Next ); + RecordAllocation( Matrix, pListNode->Next ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->LastFillinListNode = pListNode = pListNode->Next; @@ -646,9 +646,8 @@ AllocateBlockOfAllocationList(MatrixPtr Matrix) */ void -spDestroy(MatrixPtr eMatrix) +spDestroy(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; AllocationListPtr ListPtr, NextListPtr; @@ -701,16 +700,16 @@ spDestroy(MatrixPtr eMatrix) * The error status of the given matrix. * * >>> Arguments: - * eMatrix (void *) + * Matrix (void *) * The matrix for which the error status is desired. */ int -spError(MatrixPtr eMatrix ) +spError(MatrixPtr Matrix ) { /* Begin `spError'. */ - if (eMatrix != NULL) { - assert(eMatrix->ID == SPARSE_ID); - return eMatrix->Error; + if (Matrix != NULL) { + assert(Matrix->ID == SPARSE_ID); + return Matrix->Error; } else { /* This error may actually be spPANIC, no way to tell. */ return spNO_MEMORY; @@ -732,7 +731,7 @@ spError(MatrixPtr eMatrix ) * detected as singular or where a zero was detected on the diagonal. * * >>> Arguments: - * eMatrix (void *) + * Matrix (void *) * The matrix for which the error status is desired. * pRow (int *) * The row number. @@ -741,10 +740,8 @@ spError(MatrixPtr eMatrix ) */ void -spWhereSingular(MatrixPtr eMatrix, int *pRow, int *pCol) +spWhereSingular(MatrixPtr Matrix, int *pRow, int *pCol) { - MatrixPtr Matrix = eMatrix; - /* Begin `spWhereSingular'. */ assert( IS_SPARSE( Matrix ) ); @@ -769,7 +766,7 @@ spWhereSingular(MatrixPtr eMatrix, int *pRow, int *pCol) * the matrix is returned. * * >>> Arguments: - * eMatrix (void *) + * Matrix (void *) * Pointer to matrix. * External (int) * If External is set TRUE, the external size , i.e., the value of the @@ -779,10 +776,8 @@ spWhereSingular(MatrixPtr eMatrix, int *pRow, int *pCol) */ int -spGetSize(MatrixPtr eMatrix, int External) +spGetSize(MatrixPtr Matrix, int External) { - MatrixPtr Matrix = eMatrix; - /* Begin `spGetSize'. */ assert( IS_SPARSE( Matrix ) ); @@ -809,28 +804,28 @@ spGetSize(MatrixPtr eMatrix, int External) * Forces matrix to be either real or complex. * * >>> Arguments: - * eMatrix (void *) + * Matrix (void *) * Pointer to matrix. */ void -spSetReal(MatrixPtr eMatrix) +spSetReal(MatrixPtr Matrix) { /* Begin `spSetReal'. */ - assert( IS_SPARSE( eMatrix )); - eMatrix->Complex = NO; + assert( IS_SPARSE( Matrix )); + Matrix->Complex = NO; return; } void -spSetComplex(MatrixPtr eMatrix) +spSetComplex(MatrixPtr Matrix) { /* Begin `spSetComplex'. */ - assert( IS_SPARSE( eMatrix )); - eMatrix->Complex = YES; + assert( IS_SPARSE( Matrix )); + Matrix->Complex = YES; return; } @@ -850,34 +845,34 @@ spSetComplex(MatrixPtr eMatrix) * of original elements can be returned. * * >>> Arguments: - * eMatrix (void *) + * Matrix (void *) * Pointer to matrix. */ int -spFillinCount(MatrixPtr eMatrix) +spFillinCount(MatrixPtr Matrix) { /* Begin `spFillinCount'. */ - assert( IS_SPARSE( eMatrix ) ); - return eMatrix->Fillins; + assert( IS_SPARSE( Matrix ) ); + return Matrix->Fillins; } int -spElementCount(MatrixPtr eMatrix) +spElementCount(MatrixPtr Matrix) { /* Begin `spElementCount'. */ - assert( IS_SPARSE( eMatrix ) ); - return eMatrix->Elements; + assert( IS_SPARSE( Matrix ) ); + return Matrix->Elements; } int -spOriginalCount(MatrixPtr eMatrix) +spOriginalCount(MatrixPtr Matrix) { /* Begin `spOriginalCount'. */ - assert( IS_SPARSE( eMatrix ) ); - return eMatrix->Originals; + assert( IS_SPARSE( Matrix ) ); + return Matrix->Originals; } diff --git a/src/maths/sparse/spbuild.c b/src/maths/sparse/spbuild.c index bcafa6c2d..c8fddcbf5 100644 --- a/src/maths/sparse/spbuild.c +++ b/src/maths/sparse/spbuild.c @@ -93,9 +93,8 @@ static void ExpandTranslationArrays( MatrixPtr, int ); */ void -spClear(MatrixPtr eMatrix) +spClear(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; int I; @@ -180,10 +179,9 @@ spClear(MatrixPtr eMatrix) */ RealNumber * -spFindElement(MatrixPtr eMatrix, int Row, int Col) +spFindElement(MatrixPtr Matrix, int Row, int Col) { -MatrixPtr Matrix = eMatrix; -RealNumber *pElement; +ElementPtr pElement; /* Begin `spFindElement'. */ assert( IS_SPARSE( Matrix ) && Row >= 0 && Col >= 0 ); @@ -210,7 +208,7 @@ RealNumber *pElement; * is the first record in the MatrixElement structure. */ - if ((Row != Col) || ((pElement = (RealNumber *)Matrix->Diag[Row]) == NULL)) + if ((Row != Col) || ((pElement = Matrix->Diag[Row]) == NULL)) { /* * Element does not exist or does not reside along diagonal. Search @@ -218,11 +216,11 @@ RealNumber *pElement; * element which is returned by spcFindElementInCol is cast into a * pointer to Real, a RealNumber. */ - pElement = (RealNumber*)spcFindElementInCol( Matrix, + pElement = spcFindElementInCol( Matrix, &(Matrix->FirstInCol[Col]), Row, Col, NO ); } - return pElement; + return & pElement->Real; } @@ -263,10 +261,9 @@ RealNumber *pElement; */ RealNumber * -spGetElement(MatrixPtr eMatrix, int Row, int Col) +spGetElement(MatrixPtr Matrix, int Row, int Col) { - MatrixPtr Matrix = eMatrix; - RealNumber *pElement; + ElementPtr pElement; /* Begin `spGetElement'. */ assert( IS_SPARSE( Matrix ) && Row >= 0 && Col >= 0 ); @@ -305,18 +302,18 @@ spGetElement(MatrixPtr eMatrix, int Row, int Col) * statement depends on the fact that Real is the first record in * the MatrixElement structure. */ - if ((Row != Col) || ((pElement = (RealNumber *)Matrix->Diag[Row]) == NULL)) + if ((Row != Col) || ((pElement = Matrix->Diag[Row]) == NULL)) { /* Element does not exist or does not reside along diagonal. * Search column for element. As in the if statement above, * the pointer to the element which is returned by * spcFindElementInCol is cast into a pointer to Real, a * RealNumber. */ - pElement = (RealNumber*)spcFindElementInCol( Matrix, + pElement = spcFindElementInCol( Matrix, &(Matrix->FirstInCol[Col]), Row, Col, YES ); } - return pElement; + return & pElement->Real; } @@ -644,7 +641,7 @@ spGetQuad(MatrixPtr Matrix, int Row1, int Row2, int Col1, int Col2, (Template->Element4Negated == NULL)) return spNO_MEMORY; - if (Template->Element1 == &((MatrixPtr)Matrix)->TrashCan.Real) + if (Template->Element1 == & Matrix->TrashCan.Real) SWAP( RealNumber *, Template->Element1, Template->Element2 ); return spOKAY; @@ -1145,9 +1142,8 @@ spGetInitInfo(RealNumber *pElement) int -spInitialize(MatrixPtr eMatrix, int (*pInit)(RealNumber*, void *InitInfo, int , int Col)) +spInitialize(MatrixPtr Matrix, int (*pInit)(RealNumber*, void *InitInfo, int , int Col)) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; int J, Error, Col; @@ -1182,7 +1178,7 @@ spInitialize(MatrixPtr eMatrix, int (*pInit)(RealNumber*, void *InitInfo, int , } else { - Error = pInit ((RealNumber *)pElement, pElement->pInitInfo, + Error = pInit (& pElement->Real, pElement->pInitInfo, Matrix->IntToExtRowMap[pElement->Row], Col); if (Error) { diff --git a/src/maths/sparse/spfactor.c b/src/maths/sparse/spfactor.c index 25008ad04..bd72a9788 100644 --- a/src/maths/sparse/spfactor.c +++ b/src/maths/sparse/spfactor.c @@ -189,10 +189,9 @@ static int ZeroPivot( MatrixPtr, int ); */ int -spOrderAndFactor(MatrixPtr eMatrix, RealNumber RHS[], RealNumber RelThreshold, +spOrderAndFactor(MatrixPtr Matrix, RealNumber RHS[], RealNumber RelThreshold, RealNumber AbsThreshold, int DiagPivoting) { - MatrixPtr Matrix = eMatrix; ElementPtr pPivot; int Step, Size, ReorderingRequired; RealNumber LargestInCol; @@ -321,9 +320,8 @@ Done: * Error is cleared in this function. */ int -spFactor(MatrixPtr eMatrix) +spFactor(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; ElementPtr pColumn; int Step, Size; @@ -333,10 +331,10 @@ spFactor(MatrixPtr eMatrix) assert( IS_VALID(Matrix) && !Matrix->Factored); if (Matrix->NeedsOrdering) { - return spOrderAndFactor( eMatrix, NULL, + return spOrderAndFactor( Matrix, NULL, 0.0, 0.0, DIAG_PIVOTING_AS_DEFAULT ); } - if (!Matrix->Partitioned) spPartition( eMatrix, spDEFAULT_PARTITION ); + if (!Matrix->Partitioned) spPartition( Matrix, spDEFAULT_PARTITION ); if (Matrix->Complex) return FactorComplexMatrix( Matrix ); @@ -569,9 +567,8 @@ FactorComplexMatrix( MatrixPtr Matrix ) * spINDIRECT_PARTITION, or spAUTO_PARTITION. */ void -spPartition(MatrixPtr eMatrix, int Mode) +spPartition(MatrixPtr Matrix, int Mode) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement, pColumn; int Step, Size; int *Nc, *No, *Nm; @@ -603,8 +600,8 @@ spPartition(MatrixPtr eMatrix, int Mode) assert( Mode == spAUTO_PARTITION ); /* Otherwise, count all operations needed in when factoring matrix. */ - Nc = (int *)Matrix->MarkowitzRow; - No = (int *)Matrix->MarkowitzCol; + Nc = Matrix->MarkowitzRow; + No = Matrix->MarkowitzCol; Nm = (int *)Matrix->MarkowitzProd; /* Start mock-factorization. */ diff --git a/src/maths/sparse/spoutput.c b/src/maths/sparse/spoutput.c index 921c4a9a4..4248bbe12 100644 --- a/src/maths/sparse/spoutput.c +++ b/src/maths/sparse/spoutput.c @@ -133,9 +133,8 @@ int Printer_Width = PRINTER_WIDTH; */ void -spPrint(MatrixPtr eMatrix, int PrintReordered, int Data, int Header) +spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header) { - MatrixPtr Matrix = eMatrix; int J = 0; int I, Row, Col, Size, Top; int StartCol = 1, StopCol, Columns, ElementCount = 0; @@ -295,7 +294,7 @@ spPrint(MatrixPtr eMatrix, int PrintReordered, int Data, int Header) { /* Case where element exists */ if (Data) - printf(" %9.3g", (double)pElement->Real); + printf(" %9.3g", pElement->Real); else putchar('x'); @@ -326,7 +325,7 @@ spPrint(MatrixPtr eMatrix, int PrintReordered, int Data, int Header) if (pImagElements[J - StartCol] != NULL) { printf(" %8.2gj", - (double)pImagElements[J-StartCol]->Imag); + pImagElements[J-StartCol]->Imag); } else printf(" "); } @@ -436,10 +435,9 @@ spPrint(MatrixPtr eMatrix, int PrintReordered, int Data, int Header) */ int -spFileMatrix(MatrixPtr eMatrix, char *File, char *Label, int Reordered, +spFileMatrix(MatrixPtr Matrix, char *File, char *Label, int Reordered, int Data, int Header) { - MatrixPtr Matrix = eMatrix; int I, Size; ElementPtr pElement; int Row, Col, Err; @@ -518,7 +516,7 @@ spFileMatrix(MatrixPtr eMatrix, char *File, char *Label, int Reordered, } Err = fprintf ( pMatrixFile,"%d\t%d\t%-.15g\t%-.15g\n", - Row, Col, (double)pElement->Real, (double)pElement->Imag + Row, Col, pElement->Real, pElement->Imag ); if (Err < 0) return 0; pElement = pElement->NextInCol; @@ -541,7 +539,7 @@ spFileMatrix(MatrixPtr eMatrix, char *File, char *Label, int Reordered, Col = Matrix->IntToExtColMap[I]; Err = fprintf ( pMatrixFile,"%d\t%d\t%-.15g\n", - Row, Col, (double)pElement->Real + Row, Col, pElement->Real ); if (Err < 0) return 0; pElement = pElement->NextInCol; @@ -595,9 +593,8 @@ spFileMatrix(MatrixPtr eMatrix, char *File, char *Label, int Reordered, */ int -spFileVector(MatrixPtr eMatrix, char *File, RealVector RHS, RealVector iRHS) +spFileVector(MatrixPtr Matrix, char *File, RealVector RHS, RealVector iRHS) { - MatrixPtr Matrix = eMatrix; int I, Size, Err; FILE *pMatrixFile; @@ -621,7 +618,7 @@ spFileVector(MatrixPtr eMatrix, char *File, RealVector RHS, RealVector iRHS) { Err = fprintf ( pMatrixFile, "%-.15g\t%-.15g\n", - (double)RHS[I], (double)iRHS[I] + RHS[I], iRHS[I] ); if (Err < 0) return 0; } @@ -630,7 +627,7 @@ spFileVector(MatrixPtr eMatrix, char *File, RealVector RHS, RealVector iRHS) { for (I = 1; I <= Size; I++) { - if (fprintf(pMatrixFile, "%-.15g\n", (double)RHS[I]) < 0) + if (fprintf(pMatrixFile, "%-.15g\n", RHS[I]) < 0) return 0; } } @@ -686,9 +683,8 @@ spFileVector(MatrixPtr eMatrix, char *File, RealVector RHS, RealVector iRHS) */ int -spFileStats(MatrixPtr eMatrix, char *File, char *Label) +spFileStats(MatrixPtr Matrix, char *File, char *Label) { - MatrixPtr Matrix = eMatrix; int Size, I; ElementPtr pElement; int NumberOfElements; diff --git a/src/maths/sparse/spsmp.c b/src/maths/sparse/spsmp.c index e453d944d..54d8eb459 100644 --- a/src/maths/sparse/spsmp.c +++ b/src/maths/sparse/spsmp.c @@ -106,7 +106,7 @@ extern double scalbn(double, int); extern double logb(double); #endif -static void LoadGmin(SMPmatrix *eMatrix, double Gmin); +static void LoadGmin(SMPmatrix *Matrix, double Gmin); /* * SMPaddElt() @@ -183,7 +183,7 @@ SMPcReorder(SMPmatrix *Matrix, double PivTol, double PivRel, *NumSwaps = 1; spSetComplex( Matrix->SPmatrix ); return spOrderAndFactor( Matrix->SPmatrix, NULL, - (spREAL)PivRel, (spREAL)PivTol, YES ); + PivRel, PivTol, YES ); } /* @@ -195,7 +195,7 @@ SMPreorder(SMPmatrix *Matrix, double PivTol, double PivRel, double Gmin) spSetReal( Matrix->SPmatrix ); LoadGmin( Matrix, Gmin ); return spOrderAndFactor( Matrix->SPmatrix, NULL, - (spREAL)PivRel, (spREAL)PivTol, YES ); + PivRel, PivTol, YES ); } /* @@ -504,7 +504,7 @@ SMPcAddCol(SMPmatrix *eMatrix, int Accum_Col, int Addend_Col) Addend = Matrix->FirstInCol[Addend_Col]; Prev = &Matrix->FirstInCol[Accum_Col]; - Accum = *Prev;; + Accum = *Prev; while (Addend != NULL) { while (Accum && Accum->Row < Addend->Row) { diff --git a/src/maths/sparse/spsolve.c b/src/maths/sparse/spsolve.c index ca78f7133..e24ebd09d 100644 --- a/src/maths/sparse/spsolve.c +++ b/src/maths/sparse/spsolve.c @@ -124,10 +124,9 @@ static void SolveComplexTransposedMatrix( MatrixPtr, /*VARARGS3*/ void -spSolve(MatrixPtr eMatrix, RealVector RHS, RealVector Solution, +spSolve(MatrixPtr Matrix, RealVector RHS, RealVector Solution, RealVector iRHS, RealVector iSolution) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; RealVector Intermediate; RealNumber Temp; @@ -400,10 +399,9 @@ SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution , Real /*VARARGS3*/ void -spSolveTransposed(MatrixPtr eMatrix, RealVector RHS, RealVector Solution, +spSolveTransposed(MatrixPtr Matrix, RealVector RHS, RealVector Solution, RealVector iRHS, RealVector iSolution) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; RealVector Intermediate; int I, *pExtOrder, Size; diff --git a/src/maths/sparse/sputils.c b/src/maths/sparse/sputils.c index 5b767460d..32e7e9f5b 100644 --- a/src/maths/sparse/sputils.c +++ b/src/maths/sparse/sputils.c @@ -151,7 +151,7 @@ static void ComplexTransposedMatrixMultiply( MatrixPtr, RealVector, RealVector, * Tom Quarles. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix to be preordered. * * >>> Local variables; @@ -174,9 +174,8 @@ static void ComplexTransposedMatrixMultiply( MatrixPtr, RealVector, RealVector, */ void -spMNA_Preorder(MatrixPtr eMatrix) +spMNA_Preorder(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; int J, Size; ElementPtr pTwin1, pTwin2; int Twins, StartAt = 1; @@ -346,7 +345,7 @@ SwapCols( MatrixPtr Matrix, ElementPtr pTwin1, ElementPtr pTwin2 ) * should not be executed before the function spMNA_Preorder. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix to be scaled. * SolutionScaleFactors (RealVector) * The array of Solution scale factors. These factors scale the columns. @@ -368,9 +367,8 @@ SwapCols( MatrixPtr Matrix, ElementPtr pTwin1, ElementPtr pTwin2 ) */ void -spScale(MatrixPtr eMatrix, RealVector RHS_ScaleFactors, RealVector SolutionScaleFactors) +spScale(MatrixPtr Matrix, RealVector RHS_ScaleFactors, RealVector SolutionScaleFactors) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; int I, lSize, *pExtOrder; RealNumber ScaleFactor; @@ -556,7 +554,7 @@ MatrixPtr Matrix; * before spMNA_Preorder(). * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. * RHS (RealVector) * RHS is the right hand side. This is what is being solved for. @@ -571,14 +569,13 @@ MatrixPtr Matrix; */ void -spMultiply(MatrixPtr eMatrix, RealVector RHS, RealVector Solution, +spMultiply(MatrixPtr Matrix, RealVector RHS, RealVector Solution, RealVector iRHS, RealVector iSolution) { ElementPtr pElement; RealVector Vector; RealNumber Sum; int I, *pExtOrder; - MatrixPtr Matrix = eMatrix; /* Begin `spMultiply'. */ assert( IS_SPARSE( Matrix ) && !Matrix->Factored ); @@ -702,7 +699,7 @@ ComplexMatrixMultiply( MatrixPtr Matrix, RealVector RHS, RealVector Solution , R * before spMNA_Preorder(). * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. * RHS (RealVector) * RHS is the right hand side. This is what is being solved for. @@ -717,14 +714,13 @@ ComplexMatrixMultiply( MatrixPtr Matrix, RealVector RHS, RealVector Solution , R */ void -spMultTransposed(MatrixPtr eMatrix, RealVector RHS, RealVector Solution, +spMultTransposed(MatrixPtr Matrix, RealVector RHS, RealVector Solution, RealVector iRHS, RealVector iSolution) { ElementPtr pElement; RealVector Vector; RealNumber Sum; int I, *pExtOrder; - MatrixPtr Matrix = eMatrix; /* Begin `spMultTransposed'. */ assert( IS_SPARSE( Matrix ) && !Matrix->Factored ); @@ -854,7 +850,7 @@ ComplexTransposedMatrixMultiply( MatrixPtr Matrix, RealVector RHS, RealVector So * reasonable value and the logarithm of the scale factor is returned. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * A pointer to the matrix for which the determinant is desired. * pExponent (int *) * The logarithm base 10 of the scale factor for the determinant. To find @@ -878,10 +874,9 @@ ComplexTransposedMatrixMultiply( MatrixPtr Matrix, RealVector RHS, RealVector So */ void -spDeterminant(MatrixPtr eMatrix, int *pExponent, RealNumber *pDeterminant, +spDeterminant(MatrixPtr Matrix, int *pExponent, RealNumber *pDeterminant, RealNumber *piDeterminant) { - MatrixPtr Matrix = eMatrix; int I, Size; RealNumber Norm, nr, ni; ComplexNumber Pivot, cDeterminant; @@ -1037,9 +1032,8 @@ spDeterminant(MatrixPtr eMatrix, int *pExponent, RealNumber *pDeterminant, */ void -spStripFills(MatrixPtr eMatrix) +spStripFills(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; struct FillinListNodeStruct *pListNode; /* Begin `spStripFills'. */ @@ -1109,10 +1103,8 @@ spStripFills(MatrixPtr eMatrix) * frame. This assumes that the matrix will be replaced with one of * the same size. */ void -spStripMatrix(MatrixPtr eMatrix) +spStripMatrix(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; - /* Begin `spStripMatrix'. */ assert( IS_SPARSE( Matrix ) ); if (Matrix->Elements == 0) return; @@ -1124,7 +1116,6 @@ spStripMatrix(MatrixPtr eMatrix) /* Reset the element lists. */ { - ElementPtr pElement; struct ElementListNodeStruct *pListNode; pListNode = Matrix->LastElementListNode = Matrix->FirstElementListNode; @@ -1134,7 +1125,6 @@ spStripMatrix(MatrixPtr eMatrix) /* Reset the fill-in lists. */ { - ElementPtr pFillin; struct FillinListNodeStruct *pListNode; pListNode = Matrix->LastFillinListNode = Matrix->FirstFillinListNode; @@ -1171,7 +1161,7 @@ spStripMatrix(MatrixPtr eMatrix) * doesn't exist. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix in which the row and column are to be deleted. * Row (int) * Row to be deleted. @@ -1197,9 +1187,8 @@ spStripMatrix(MatrixPtr eMatrix) */ void -spDeleteRowAndCol(MatrixPtr eMatrix, int Row, int Col) +spDeleteRowAndCol(MatrixPtr Matrix, int Row, int Col) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement, *ppElement, pLastElement; int Size, ExtRow, ExtCol; ElementPtr spcFindElementInCol(); @@ -1306,13 +1295,12 @@ spDeleteRowAndCol(MatrixPtr eMatrix, int Row, int Col) * previous factorization. If the matrix was singular, zero is returned. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. */ RealNumber -spPseudoCondition(MatrixPtr eMatrix) +spPseudoCondition(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; int I; ArrayOfElementPtrs Diag; RealNumber MaxPivot, MinPivot, Mag; @@ -1388,7 +1376,7 @@ spPseudoCondition(MatrixPtr eMatrix) * zero is returned. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. * NormOfMatrix (RealNumber) * The L-infinity norm of the unfactored matrix as computed by @@ -1401,9 +1389,8 @@ spPseudoCondition(MatrixPtr eMatrix) * spNO_MEMORY */ RealNumber -spCondition(MatrixPtr eMatrix, RealNumber NormOfMatrix, int *pError) +spCondition(MatrixPtr Matrix, RealNumber NormOfMatrix, int *pError) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; RealVector T, Tm; int I, K, Row; @@ -1824,14 +1811,13 @@ int *pError; * The largest absolute row sum of matrix. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. */ RealNumber -spNorm(MatrixPtr eMatrix) +spNorm(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; int I; RealNumber Max = 0.0, AbsRowSum; @@ -1942,14 +1928,13 @@ spNorm(MatrixPtr eMatrix) * largest element in any of the reduced submatrices is returned. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. */ RealNumber -spLargestElement(MatrixPtr eMatrix) +spLargestElement(MatrixPtr Matrix) { - MatrixPtr Matrix = eMatrix; int I; RealNumber Mag, AbsColSum, Max = 0.0, MaxRow = 0.0, MaxCol = 0.0; RealNumber Pivot; @@ -2066,7 +2051,7 @@ spLargestElement(MatrixPtr eMatrix) * Returns a bound on the magnitude of the largest element in E = A - LU. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Pointer to the matrix. * Rho (RealNumber) * The bound on the magnitude of the largest element in any of the @@ -2076,9 +2061,8 @@ spLargestElement(MatrixPtr eMatrix) */ RealNumber -spRoundoff(MatrixPtr eMatrix, RealNumber Rho) +spRoundoff(MatrixPtr Matrix, RealNumber Rho) { - MatrixPtr Matrix = eMatrix; ElementPtr pElement; int Count, I, MaxCount = 0; RealNumber Reid, Gear; @@ -2087,7 +2071,7 @@ spRoundoff(MatrixPtr eMatrix, RealNumber Rho) assert( IS_SPARSE(Matrix) && IS_FACTORED(Matrix) ); /* Compute Barlow's bound if it is not given. */ - if (Rho < 0.0) Rho = spLargestElement( eMatrix ); + if (Rho < 0.0) Rho = spLargestElement( Matrix ); /* Find the maximum number of off-diagonals in L if not previously computed. */ if (Matrix->MaxRowCountInLowerTri < 0) @@ -2133,7 +2117,7 @@ spRoundoff(MatrixPtr eMatrix, RealNumber Rho) * error state of sparse. No message is produced if there is no error. * * >>> Arguments: - * eMatrix (char *) + * Matrix (char *) * Matrix for which the error message is to be printed. * Stream (FILE *) * Stream to which the error message is to be printed. @@ -2143,17 +2127,17 @@ spRoundoff(MatrixPtr eMatrix, RealNumber Rho) */ void -spErrorMessage(MatrixPtr eMatrix, FILE *Stream, char *Originator) +spErrorMessage(MatrixPtr Matrix, FILE *Stream, char *Originator) { int Row, Col, Error; /* Begin `spErrorMessage'. */ - if (eMatrix == NULL) + if (Matrix == NULL) Error = spNO_MEMORY; else { - assert(eMatrix->ID == SPARSE_ID); - Error = eMatrix->Error; + assert(Matrix->ID == SPARSE_ID); + Error = Matrix->Error; } if (Error == spOKAY) return; @@ -2172,13 +2156,13 @@ spErrorMessage(MatrixPtr eMatrix, FILE *Stream, char *Originator) fprintf( Stream, "insufficient memory available.\n"); else if (Error == spSINGULAR) { - spWhereSingular( eMatrix, &Row, &Col ); + spWhereSingular( Matrix, &Row, &Col ); fprintf( Stream, "singular matrix detected at row %d and column %d.\n", Row, Col); } else if (Error == spZERO_DIAG) { - spWhereSingular( eMatrix, &Row, &Col ); + spWhereSingular( Matrix, &Row, &Col ); fprintf( Stream, "zero diagonal detected at row %d and column %d.\n", Row, Col); } diff --git a/src/misc/misc_time.c b/src/misc/misc_time.c index 9df4367ce..1300735cb 100644 --- a/src/misc/misc_time.c +++ b/src/misc/misc_time.c @@ -32,6 +32,9 @@ Copyright 1990 Regents of the University of California. All rights reserved. # endif #endif +#ifdef HAVE_FTIME +# include +#endif /* Return the date. Return value is static data. */ @@ -65,8 +68,6 @@ datestring(void) /* return time interval in seconds and milliseconds */ -#ifndef HAVE_GETRUSAGE -#ifndef HAVE_TIMES #ifdef HAVE_FTIME struct timeb timebegin; @@ -84,8 +85,6 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec) } -#endif -#endif #endif /* diff --git a/src/misc/misc_time.h b/src/misc/misc_time.h index 0424554a0..95cc1bcb2 100644 --- a/src/misc/misc_time.h +++ b/src/misc/misc_time.h @@ -9,16 +9,12 @@ char * datestring(void); double seconds(void); -#ifndef HAVE_GETRUSAGE -#ifndef HAVE_TIMES #ifdef HAVE_FTIME extern struct timeb timebegin; void timediff(struct timeb *, struct timeb *, int *, int *); -#endif -#endif #endif #endif diff --git a/src/sharedspice.c b/src/sharedspice.c index 941db8386..adc6579ea 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -16,7 +16,12 @@ #define STDERR_FILENO 2 #endif -//#define low_latency + +/* If a calling function has high latency times during printing, + causing memory access errors, you may undef the following line. + Printing messages are assembled in a wordlist, and sent to the caller + via a new thread. Delays may occur. */ +#define low_latency /**********************************************************************/ /* Header files for C functions */ @@ -131,11 +136,9 @@ typedef pthread_t threadId_t; #include #include -#ifndef HAVE_GETRUSAGE #ifdef HAVE_FTIME #include #endif -#endif /* To interupt a spice run */ #include @@ -195,6 +198,7 @@ int sh_vfprintf(FILE *f, const char *fmt, va_list args); int sh_fputsll(const char *input, FILE* outf); int sh_ExecutePerLoop(void); +double getvsrcval(double, char*); int sh_vecinit(runDesc *run); void shared_exit(int status); @@ -203,6 +207,8 @@ void sighandler_sharedspice(int num); void wl_delete_first(wordlist **wlstart, wordlist **wlend); +int add_bkpt(void); + #if !defined(low_latency) static char* outstorage(char*, bool); static void printsend(void); @@ -217,6 +223,7 @@ static ControlledExit* ngexit; static SendData* datfcn; static SendInitData* datinitfcn; static BGThreadRunning* bgtr; +static GetVSRCData* getvdat; static pvector_info myvec = NULL; char **allvecs = NULL; char **allplots = NULL; @@ -225,6 +232,7 @@ static bool nostatuswanted = FALSE; static bool nodatawanted = FALSE; static bool nodatainitwanted = FALSE; static bool nobgtrwanted = FALSE; +static bool wantvdat = FALSE; static bool immediate = FALSE; static bool coquit = FALSE; static jmp_buf errbufm, errbufc; @@ -244,7 +252,9 @@ mutexType fputsMutex; static bool is_initialized = FALSE; static char* no_init = "Error: ngspice is not initialized!\n Run ngSpice_Init first"; -static bool printstopp = FALSE; +/* identifier for this ngspice invocation */ +static int ng_ident = 0; + /*helper function*//* static struct plot * @@ -293,12 +303,16 @@ static threadId_t tid, printtid, bgtid = (threadId_t) 0; static bool fl_running = FALSE; static bool fl_exited = TRUE; +static bool printstopp = FALSE; +static bool ps_exited = TRUE; + #if defined(__MINGW32__) || defined(_MSC_VER) #define EXPORT_FLAVOR WINAPI #else #define EXPORT_FLAVOR #endif +/* starts a background thread, e.g. from command bg_run */ static void * EXPORT_FLAVOR _thread_run(void *string) { @@ -324,7 +338,7 @@ _thread_run(void *string) } -/*Stops a running thread, hopefully */ +/*Stops a running background thread, hopefully */ static int EXPORT_FLAVOR _thread_stop(void) { @@ -374,13 +388,16 @@ sighandler_sharedspice(int num) #endif /*THREADS*/ - +/* run a ngspice command */ static int runc(char* command) { char buf[1024] = ""; sighandler oldHandler; #ifdef THREADS +#ifndef low_latency + int timeout = 0; +#endif char *string; bool fl_bg = FALSE; command_id = threadid_self(); @@ -392,12 +409,24 @@ runc(char* command) #ifndef low_latency /* stop the printf thread 'printsend()' */ else if (cieq("bg_pstop", command)) { - printstopp = TRUE; + while (!ps_exited && timeout < 100) { + printstopp = TRUE; + #if defined(__MINGW32__) || defined(_MSC_VER) - Sleep(100); // va: windows native + Sleep(100); // va: windows native #else - usleep(10000); + usleep(10000); #endif + timeout++; + } + if (!ps_exited) { + fprintf(stderr, "Error: Couldn't stop printsend thread\n"); + return EXIT_BAD; + } + else + fprintf(stdout, "Printsend thread stopped with timeout = %d\n", timeout); + + printstopp = FALSE; return 2; } #endif @@ -408,7 +437,7 @@ runc(char* command) #endif /* Catch Ctrl-C to break simulations */ -#if !defined(_MSC_VER) /*&& !defined(__MINGW32__) */ +#if 1 //!defined(_MSC_VER) /*&& !defined(__MINGW32__) */ oldHandler = signal(SIGINT, (SIGNAL_FUNCTION) ft_sigintr); if (SETJMP(jbuf, 1) != 0) { signal(SIGINT, oldHandler); @@ -469,7 +498,7 @@ runc(char* command) #ifdef THREADS -/* Checks if spice is running in the background */ +/* Checks if ngspice is running in the background */ IMPEXP bool ngSpice_running (void) @@ -478,8 +507,27 @@ ngSpice_running (void) } #endif +/* Initialise external voltage source */ +IMPEXP +int +ngSpice_Init_Sync(GetVSRCData* vsrcdat, int* ident, void* userData) +{ + getvdat = vsrcdat; + /* set userdata, but don't overwrite with NULL */ + if (userData) + userptr = userData; + /* set ngspice shared lib identification number */ + ng_ident = *ident; + /* if caller sends NULL, don't try to retrieve voltage */ + if (getvdat) { + wantvdat = TRUE; + return 0; + } + return 1; +} -/* Initialise spice and setup native methods */ + +/* Initialise ngspice and setup native methods */ IMPEXP int ngSpice_Init(SendChar* printfcn, SendStat* statusfcn, ControlledExit* ngspiceexit, @@ -578,12 +626,9 @@ ngSpice_Init(SendChar* printfcn, SendStat* statusfcn, ControlledExit* ngspiceexi struct passwd *pw; pw = getpwuid(getuid()); -#ifdef HAVE_ASPRINTF - asprintf(&s, "%s%s", pw->pw_dir, INITSTR); -#else s = TMALLOC(char, 1 + strlen(pw->pw_dir) + strlen(INITSTR)); sprintf(s, "%s%s", pw->pw_dir, INITSTR); -#endif + if (access(s, 0) == 0) inp_source(s); } @@ -627,7 +672,14 @@ bot: } #endif - com_version(NULL); +// com_version(NULL); + fprintf(cp_out, + "******\n" + "** %s-%s shared library\n", + ft_sim->simulator, ft_sim->version); + if (Spice_Build_Date != NULL && *Spice_Build_Date != 0) + fprintf(cp_out, "** Creation Date: %s\n", Spice_Build_Date); + fprintf(cp_out, "******\n"); is_initialized = TRUE; @@ -638,7 +690,7 @@ bot: /* If caller has sent valid address for pfcn */ if (!noprintfwanted) #ifdef HAVE_LIBPTHREAD - pthread_create(&tid, NULL, (void * (*)(void *))printsend, (void *)NULL); + pthread_create(&printtid, NULL, (void * (*)(void *))printsend, (void *)NULL); #elif defined _MSC_VER || defined __MINGW32__ printtid = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (__stdcall *)(void *))printsend, (void*) NULL, 0, NULL); @@ -659,7 +711,6 @@ IMPEXP int ngSpice_Command(char* comexec) { if ( ! setjmp(errbufc) ) { -// HANDLE tid2; immediate = FALSE; intermj = 1; @@ -668,12 +719,9 @@ int ngSpice_Command(char* comexec) fprintf(stderr, no_init); return 1; } -// tid2 = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START_ROUTINE)runc, (void*)comexec, -// 0, NULL); + runc(comexec); - /* main thread prepares immediate detaching of dll, - in case of controlled_exit from tid2 thread, caller is asked - to detach dll via fcn ngexit() */ + /* main thread prepares immediate detaching of dll */ immediate = TRUE; return 0; } @@ -722,6 +770,7 @@ int ngSpice_Circ(char** circa){ if ( ! setjmp(errbufm) ) { intermj = 0; + immediate = FALSE; /* count the entries */ while (circa[entries]) { entries++; @@ -747,7 +796,7 @@ char* ngSpice_CurPlot(void) } /* return to the caller a pointer to an array of all plots created -by ngspice.dll */ +by ngspice. Last entry in the array is NULL. */ IMPEXP char** ngSpice_AllPlots(void) { @@ -771,7 +820,7 @@ char** ngSpice_AllPlots(void) } /* return to the caller a pointer to an array of vector names in the plot -named by plotname */ +named by plotname. Last entry in the array is NULL. */ IMPEXP char** ngSpice_AllVecs(char* plotname) { @@ -805,12 +854,71 @@ char** ngSpice_AllVecs(char* plotname) } +static double *bkpttmp = NULL; +static int bkpttmpsize = 0; + +/* set a breakpoint in ngspice */ +IMPEXP +bool ngSpice_SetBkpt(double time) +{ + int error; + CKTcircuit *ckt = NULL; + + if (!ft_curckt || !ft_curckt->ci_ckt) { + fprintf(cp_err, "Error: no circuit loaded.\n"); + return(FALSE); + } + + ckt = ft_curckt->ci_ckt; + if (ckt->CKTbreakSize == 0) { + /* breakpoints have not yet been set up, so store here preliminary + and add with fcn add_bkpt() called from DCTran()*/ + if (bkpttmp == NULL) { + bkpttmp = TMALLOC(double, bkpttmpsize + 1); + if(bkpttmp == NULL) + return(FALSE); + bkpttmpsize++; + } + else { + bkpttmp = TREALLOC(double, bkpttmp, bkpttmpsize + 1); + bkpttmpsize++; + } + bkpttmp[bkpttmpsize-1] = time; + error = 0; + } + else + error = CKTsetBreak(ckt, time); + if(error) + return(FALSE); + return(TRUE); +} + +/* add the preliminary breakpoints to the list. + called from dctran.c */ +int +add_bkpt(void) +{ + int i; + int error = 0; + CKTcircuit *ckt = ft_curckt->ci_ckt; + + if((bkpttmp) && (bkpttmpsize > 0)) { + for (i = 0; i < bkpttmpsize; i++) + error = CKTsetBreak(ckt, bkpttmp[i]); + FREE(bkpttmp); + bkpttmpsize = 0; + } + if(error) + return(error); + return(OK); +} + /*------------------------------------------------------*/ /* Redefine the vfprintf() functions for callback */ /*------------------------------------------------------*/ -/* handling of escape characters (extra \ added) is removed, may be added by - un-commenting some lines */ +/* handling of escape characters (extra \ added) only, if + 'set addescape' is given in .spiceinit */ int sh_vfprintf(FILE *f, const char *fmt, va_list args) @@ -889,7 +997,7 @@ sh_vfprintf(FILE *f, const char *fmt, va_list args) } } - /* use sharedspice implementation of fputs (sh_fputs) + /* use sharedspice.c implementation of fputs (sh_fputs) to assess callback function derived from address printfcn received via Spice_Init() from caller of ngspice.dll */ @@ -903,9 +1011,10 @@ sh_vfprintf(FILE *f, const char *fmt, va_list args) } -/*----------------------------------------------------------------------*/ -/* Reimplement fprintf() as a call to callback function pfcn */ -/*----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + Reimplement fprintf() as a call to callback function pfcn + via sh_vfprintf, sh_fputs, and sh_fputsll + ----------------------------------------------------------------------*/ int sh_fprintf(FILE *f, const char *format, ...) @@ -921,9 +1030,10 @@ sh_fprintf(FILE *f, const char *format, ...) } -/*----------------------------------------------------------------------*/ -/* Reimplement printf() as a call to callback function pfcn */ -/*----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + Reimplement printf() as a call to callback function pfcn + via sh_vfprintf, sh_fputs, and sh_fputsll + ----------------------------------------------------------------------*/ int sh_printf(const char *format, ...) @@ -975,9 +1085,9 @@ sh_fputc(const char inp, FILE* f) static char* outstringerr = NULL; static char* outstringout = NULL; -#ifdef low_latency -/* using the strings by the caller sent directly to the caller - has to fast enough (low latency) */ +#if defined (low_latency) || !defined(THREADS) +/* The strings issued by printf etc. are sent directly to the caller. + The callback has to be fast enough (low latency). */ int sh_fputsll(const char *input, FILE* outf) { @@ -1065,7 +1175,8 @@ sh_fputsll(const char *input, FILE* outf) return 0; } -/* provide a lock around printing function */ +/* provide a lock around printing function. + May become critical if latency of callback is too high.*/ int sh_fputs(const char *input, FILE* outf) { @@ -1187,6 +1298,8 @@ static char *outsend = NULL; static void printsend(void) { + ps_exited = FALSE; + printstopp = FALSE; for (;;) { #if defined(__MINGW32__) || defined(_MSC_VER) Sleep(50); // loop delay @@ -1198,6 +1311,7 @@ printsend(void) mutex_lock(&fputsMutex); outsend = outstorage(NULL, FALSE); mutex_unlock(&fputsMutex); + break; } mutex_lock(&fputsMutex); @@ -1210,6 +1324,7 @@ printsend(void) tfree(outsend); } } + ps_exited = TRUE; } /* remove the first entry of a wordlist, but keep wl->wl_word */ @@ -1251,13 +1366,14 @@ char* outstorage(char* wordin, bool write) /* New progress report to statfcn(). - Update only every DELTATIME milliseconds */ + An update occurs only every DELTATIME milliseconds. */ #define DELTATIME 150 void SetAnalyse( char * Analyse, /*in: analysis type */ int DecaPercent /*in: 10 times the progress [%]*/ /*HWND hwAnalyse, in: global handle to analysis window */ ) { +#ifdef HAVE_FTIME static int OldPercent = -2; /* Previous progress value */ static char OldAn[128]; /* Previous analysis type */ char* s; /* outputs to callback function */ @@ -1321,10 +1437,21 @@ void SetAnalyse( result = statfcn(s, userptr); } tfree(s); +#else + char* s; + int result; + static bool havesent = FALSE; + if (!havesent) { + s = copy("No usage info available"); + result = statfcn(s, userptr); + tfree(s); + havesent = TRUE; + } +#endif } -/* a dll or shared library should never exit, but ask for graceful shutdown - (e.g. being detached) via a callback function*/ +/* a dll or shared library should never exit, if loaded dynamically, + but ask for graceful shutdown (e.g. being detached) via a callback function*/ void shared_exit(int status) { /* alert caller to detach dll (if we are in the main thread), @@ -1364,8 +1491,23 @@ void shared_exit(int status) tfree(outsend); } #endif + // if we are in a worker thread, we exit it here + // detaching then has to be done explicitely by the caller + if (fl_running && !fl_exited) { + fl_exited = TRUE; + bgtr(fl_exited, userptr); + // set a flag that ngspice wants to be detached + ngexit(status, FALSE, coquit, userptr); + // finish and exit the worker thread +#ifdef HAVE_LIBPTHREAD + pthread_exit(1); +#elif defined _MSC_VER || defined __MINGW32__ + _endthreadex(1); +#endif + } // set a flag in caller to detach ngspice.dll ngexit(status, immediate, coquit, userptr); + // jump back to finish the calling function if (!intermj) longjmp(errbufm,1); /* jump back to ngSpice_Circ() */ @@ -1448,7 +1590,7 @@ int sh_ExecutePerLoop(void) { struct dvec *d; int i, veclen; - double testval; +// double testval; struct plot *pl = plot_cur; /* return immediately if callback not wanted */ if (nodatawanted) @@ -1456,11 +1598,12 @@ int sh_ExecutePerLoop(void) /* get the data of the last entry to the plot vector */ veclen = pl->pl_dvecs->v_length - 1; + curvecvalsall->vecindex = veclen; for (d = pl->pl_dvecs, i = 0; d; d = d->v_next, i++) { /* test if real */ if (d->v_flags & VF_REAL) { curvecvalsall->vecsa[i]->is_complex = FALSE; - testval = d->v_realdata[veclen]; +// testval = d->v_realdata[veclen]; curvecvalsall->vecsa[i]->creal = d->v_realdata[veclen]; curvecvalsall->vecsa[i]->cimag = 0.; } @@ -1478,7 +1621,7 @@ int sh_ExecutePerLoop(void) /* called once for a new plot from beginPlot() in outitf.c, - after the vectors in ngspice have been set. + after the vectors in ngspice for this plot have been set. Transfers vector information to the caller via callback datinitfcn() and sets transfer structure for use in sh_ExecutePerLoop() */ int sh_vecinit(runDesc *run) @@ -1536,14 +1679,13 @@ int sh_vecinit(runDesc *run) data will be sent from sh_ExecutePerLoop() via datfcn() */ if (!curvecvalsall) { curvecvalsall = TMALLOC(vecvaluesall, 1); - curvecvalsall->veccount = veccount; } else { for (i = 0; i < curvecvalsall->veccount; i++) tfree(curvecvalsall->vecsa[i]); tfree(curvecvalsall->vecsa); } - + curvecvalsall->veccount = veccount; curvecvalsall->vecsa = TMALLOC(pvecvalues, veccount); for (i = 0, d = cur_run->runPlot->pl_dvecs; i < veccount; i++, d = d->v_next) { @@ -1557,3 +1699,18 @@ int sh_vecinit(runDesc *run) return 0; } +/* issue callback to request external voltage data for source vname*/ +double getvsrcval(double time, char* vname) +{ + double vval; + if (!wantvdat) { + fprintf(stderr, "Error: No callback supplied for source %s\n", vname); + shared_exit(EXIT_BAD); + return(EXIT_BAD); + } + else { + /* callback fcn */ + getvdat(&vval, time, vname, userptr); + return vval; + } +} diff --git a/src/spicelib/analysis/Makefile.am b/src/spicelib/analysis/Makefile.am index 86d6b7371..03d8f1ab0 100644 --- a/src/spicelib/analysis/Makefile.am +++ b/src/spicelib/analysis/Makefile.am @@ -107,6 +107,10 @@ libckt_la_SOURCES += \ endif +if KIRCHHOFF_WANTED +libckt_la_SOURCES += cktmkcurKCL.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices AM_CFLAGS = $(STATIC) MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/analysis/acan.c b/src/spicelib/analysis/acan.c index fe87c68d5..b28714127 100644 --- a/src/spicelib/analysis/acan.c +++ b/src/spicelib/analysis/acan.c @@ -149,11 +149,11 @@ ACan(CKTcircuit *ckt, int restart) * Moreover the begin plot has not even been done yet at this * point... */ - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - NULL, IF_REAL, - numNames, nameList, IF_REAL, &acPlot); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &acPlot); tfree(nameList); ipc_send_dcop_prefix(); @@ -174,30 +174,28 @@ ACan(CKTcircuit *ckt, int restart) if (ckt->CKTkeepOpInfo) { /* Dump operating point. */ - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "AC Operating Point", - NULL, IF_REAL, - numNames, nameList, IF_REAL, &plot); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "AC Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); if(error) return(error); CKTdump(ckt, 0.0, plot); SPfrontEnd->OUTendPlot (plot); plot = NULL; } - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); tfree(nameList); if(error) return(error); if (job->ACstepType != LINEAR) { - SPfrontEnd->OUTattributes (acPlot, NULL, - OUT_SCALE_LOG, NULL); + SPfrontEnd->OUTattributes (acPlot, NULL, OUT_SCALE_LOG, NULL); } freq = job->ACstartFreq; @@ -205,11 +203,11 @@ ACan(CKTcircuit *ckt, int restart) freq = job->ACsaveFreq; job->ACsaveFreq = 0; /* clear the 'old' frequency */ /* fix resume? saj, indeed !*/ - error = SPfrontEnd->OUTpBeginPlot ( - NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, &acPlot); + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &acPlot); /* saj*/ } diff --git a/src/spicelib/analysis/analysis.c b/src/spicelib/analysis/analysis.c index cbb3bd4ec..ecb9279a6 100644 --- a/src/spicelib/analysis/analysis.c +++ b/src/spicelib/analysis/analysis.c @@ -20,6 +20,10 @@ extern SPICEanalysis SENSinfo; extern SPICEanalysis PSSinfo; #endif +#ifdef WANT_SENSE2 +extern SPICEanalysis SEN2info; +#endif + SPICEanalysis *analInfo[] = { &OPTinfo, &ACinfo, @@ -34,6 +38,9 @@ SPICEanalysis *analInfo[] = { #ifdef WITH_PSS &PSSinfo, #endif +#ifdef WANT_SENSE2 + &SEN2info, +#endif }; diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index 62b6f2a47..c8ec1a666 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -52,6 +52,11 @@ CKTload(CKTcircuit *ckt) size = SMPmatSize(ckt->CKTmatrix); for (i = 0; i <= size; i++) { ckt->CKTrhs[i] = 0; + +#ifdef KIRCHHOFF + ckt->CKTfvk[i] = 0; +#endif + } SMPclear(ckt->CKTmatrix); #ifdef STEPDEBUG diff --git a/src/spicelib/analysis/cktmapn.c b/src/spicelib/analysis/cktmapn.c index 96e0abe66..c9564160b 100644 --- a/src/spicelib/analysis/cktmapn.c +++ b/src/spicelib/analysis/cktmapn.c @@ -35,12 +35,8 @@ CKTmapNode(CKTcircuit *ckt, CKTnode **node, IFuid name) /* not found, so must be a new one */ error = CKTmkNode(ckt,&mynode); /*allocate the node*/ if(error) return(error); - error = SPfrontEnd->IFnewUid (ckt, - &uid, - NULL, - name, - UID_SIGNAL, - &mynode); /* get a uid for it */ + /* get a uid for it */ + error = SPfrontEnd->IFnewUid (ckt, &uid, NULL, name, UID_SIGNAL, &mynode); if(error) return(error); mynode->name = uid; /* set the info we have */ mynode->type = SP_VOLTAGE; diff --git a/src/spicelib/analysis/cktmkcur.c b/src/spicelib/analysis/cktmkcur.c index 029dd694b..b014fb007 100644 --- a/src/spicelib/analysis/cktmkcur.c +++ b/src/spicelib/analysis/cktmkcur.c @@ -29,8 +29,7 @@ CKTmkCur(CKTcircuit *ckt, CKTnode **node, IFuid basename, char *suffix) error = CKTmkNode(ckt,&mynode); if(error) return(error); checknode = mynode; - error = SPfrontEnd->IFnewUid (ckt, &uid, basename, - suffix, UID_SIGNAL, &checknode); + error = SPfrontEnd->IFnewUid (ckt, &uid, basename, suffix, UID_SIGNAL, &checknode); if(error) { FREE(mynode); if(node) *node = checknode; diff --git a/src/spicelib/analysis/cktmkcurKCL.c b/src/spicelib/analysis/cktmkcurKCL.c new file mode 100644 index 000000000..4506af60c --- /dev/null +++ b/src/spicelib/analysis/cktmkcurKCL.c @@ -0,0 +1,21 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/sperror.h" +#include "ngspice/cktdefs.h" + +int +CKTmkCurKCL (CKTcircuit *ckt, int i, double **node) +{ + CKTmkCurKCLnode *tempNode ; + + tempNode = TMALLOC (CKTmkCurKCLnode, 1) ; + tempNode->KCLcurrent = 0.0 ; + tempNode->next = ckt->CKTmkCurKCLarray [i] ; + ckt->CKTmkCurKCLarray [i] = tempNode ; + *node = &(tempNode->KCLcurrent) ; + + return (OK) ; +} diff --git a/src/spicelib/analysis/cktmknod.c b/src/spicelib/analysis/cktmknod.c index 114f5b9e6..9e6d54066 100644 --- a/src/spicelib/analysis/cktmknod.c +++ b/src/spicelib/analysis/cktmknod.c @@ -26,7 +26,7 @@ CKTmkNode(CKTcircuit *ckt, CKTnode **node) mynode = TMALLOC(CKTnode, 1); if(mynode == NULL) return(E_NOMEM); mynode->next = NULL; - mynode->name = (IFuid) 0; + mynode->name = NULL; if(node) *node = mynode; return(OK); diff --git a/src/spicelib/analysis/cktmkvol.c b/src/spicelib/analysis/cktmkvol.c index e3e821d49..74007547d 100644 --- a/src/spicelib/analysis/cktmkvol.c +++ b/src/spicelib/analysis/cktmkvol.c @@ -27,8 +27,7 @@ CKTmkVolt(CKTcircuit *ckt, CKTnode **node, IFuid basename, char *suffix) error = CKTmkNode(ckt,&mynode); if(error) return(error); checknode = mynode; - error = SPfrontEnd->IFnewUid (ckt, &uid, basename, - suffix, UID_SIGNAL, &checknode); + error = SPfrontEnd->IFnewUid (ckt, &uid, basename, suffix, UID_SIGNAL, &checknode); if(error) { FREE(mynode); if(node) *node = checknode; diff --git a/src/spicelib/analysis/cktnoise.c b/src/spicelib/analysis/cktnoise.c index a1f1f995f..d088c8bb5 100644 --- a/src/spicelib/analysis/cktnoise.c +++ b/src/spicelib/analysis/cktnoise.c @@ -56,12 +56,12 @@ CKTnoise (CKTcircuit *ckt, int mode, int operation, Ndata *data) data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), - NULL, "onoise_spectrum", UID_OTHER, NULL); + NULL, "onoise_spectrum", UID_OTHER, NULL); data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), - NULL, "inoise_spectrum", UID_OTHER, NULL); + NULL, "inoise_spectrum", UID_OTHER, NULL); /* we've added two more plots */ @@ -73,11 +73,11 @@ CKTnoise (CKTcircuit *ckt, int mode, int operation, Ndata *data) data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), - NULL, "onoise_total", UID_OTHER, NULL); + NULL, "onoise_total", UID_OTHER, NULL); data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), - NULL, "inoise_total", UID_OTHER, NULL); + NULL, "inoise_total", UID_OTHER, NULL); /* we've added two more plots */ data->outpVector = diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 403b2c389..35d2bc33b 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -21,62 +21,61 @@ int CKTop (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { - int converged; + int converged; #ifdef HAS_PROGREP - SetAnalyse("op", 0); + SetAnalyse("op", 0); #endif -ckt->CKTmode = firstmode; + ckt->CKTmode = firstmode; - if (!ckt->CKTnoOpIter){ + if (!ckt->CKTnoOpIter) { #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0)) - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; - else - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0)) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - converged = NIiter (ckt, iterlim); + converged = NIiter (ckt, iterlim); } else { - converged = 1; /* the 'go directly to gmin stepping' option */ - } + converged = 1; /* the 'go directly to gmin stepping' option */ + } - if (converged != 0) - { - /* no convergence on the first try, so we do something else */ - /* first, check if we should try gmin stepping */ + if (converged != 0) { + /* no convergence on the first try, so we do something else */ + /* first, check if we should try gmin stepping */ - if (ckt->CKTnumGminSteps >= 1){ - if (ckt->CKTnumGminSteps == 1) - converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); - else - converged = spice3_gmin(ckt, firstmode, continuemode, iterlim); - } - if (!converged) /* If gmin-stepping worked... move out */ - return (0); + if (ckt->CKTnumGminSteps >= 1) { + if (ckt->CKTnumGminSteps == 1) + converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); + else + converged = spice3_gmin(ckt, firstmode, continuemode, iterlim); + } + if (!converged) /* If gmin-stepping worked... move out */ + return (0); - /* ... otherwise try stepping sources ... - * now, we'll try source stepping - we scale the sources - * to 0, converge, then start stepping them up until they - * are at their normal values - */ + /* ... otherwise try stepping sources ... + * now, we'll try source stepping - we scale the sources + * to 0, converge, then start stepping them up until they + * are at their normal values + */ - if (ckt->CKTnumSrcSteps >= 1){ - if (ckt->CKTnumSrcSteps == 1) - converged = gillespie_src(ckt, firstmode, continuemode, iterlim); - else - converged = spice3_src(ckt, firstmode, continuemode, iterlim); - } + if (ckt->CKTnumSrcSteps >= 1) { + if (ckt->CKTnumSrcSteps == 1) + converged = gillespie_src(ckt, firstmode, continuemode, iterlim); + else + converged = spice3_src(ckt, firstmode, continuemode, iterlim); + } #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - } - return (converged); - + } + return (converged); + } @@ -84,7 +83,7 @@ ckt->CKTmode = firstmode; /* CKTconvTest(ckt) * this is a driver program to iterate through all the various * convTest functions provided for the circuit elements in the - * given circuit + * given circuit */ int @@ -93,18 +92,15 @@ CKTconvTest (CKTcircuit * ckt) int i; int error = OK; - for (i = 0; i < DEVmaxnum; i++) - { - if (DEVices[i] && DEVices[i]->DEVconvTest && ckt->CKThead[i]) - { + for (i = 0; i < DEVmaxnum; i++) { + if (DEVices[i] && DEVices[i]->DEVconvTest && ckt->CKThead[i]) { error = DEVices[i]->DEVconvTest (ckt->CKThead[i], ckt); } if (error) return (error); - if (ckt->CKTnoncon) - { + if (ckt->CKTnoncon) { /* printf("convTest: device %s failed\n", * DEVices[i]->DEVpublic.name); */ return (OK); @@ -118,505 +114,499 @@ CKTconvTest (CKTcircuit * ckt) /* Dynamic gmin stepping * Algorithm by Alan Gillespie * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) - * + * * return value: * 0 -> method converged * 1 -> method failed - * - * Note that no path out of this code allows ckt->CKTdiagGmin to be + * + * Note that no path out of this code allows ckt->CKTdiagGmin to be * anything but CKTgshunt. */ static int dynamic_gmin (CKTcircuit * ckt, long int firstmode, - long int continuemode, int iterlim) + long int continuemode, int iterlim) { - double OldGmin, gtarget, factor; - int success, failed, converged; + double OldGmin, gtarget, factor; + int success, failed, converged; - int NumNodes, iters, i; - double *OldRhsOld, *OldCKTstate0; - CKTnode *n; + int NumNodes, iters, i; + double *OldRhsOld, *OldCKTstate0; + CKTnode *n; - ckt->CKTmode = firstmode; - SPfrontEnd->IFerror (ERR_INFO, - "Starting dynamic gmin stepping", NULL); + ckt->CKTmode = firstmode; + SPfrontEnd->IFerror (ERR_INFO, + "Starting dynamic gmin stepping", NULL); - NumNodes = 0; - for (n = ckt->CKTnodes; n; n = n->next) - NumNodes++; - - OldRhsOld = TMALLOC(double, NumNodes + 1); - OldCKTstate0 = - TMALLOC(double, ckt->CKTnumStates + 1); + NumNodes = 0; + for (n = ckt->CKTnodes; n; n = n->next) + NumNodes++; - for (n = ckt->CKTnodes; n; n = n->next) - ckt->CKTrhsOld [n->number] = 0; + OldRhsOld = TMALLOC(double, NumNodes + 1); + OldCKTstate0 = + TMALLOC(double, ckt->CKTnumStates + 1); - for (i = 0; i < ckt->CKTnumStates; i++) - ckt->CKTstate0 [i] = 0; - - factor = ckt->CKTgminFactor; - OldGmin = 1e-2; - ckt->CKTdiagGmin = OldGmin / factor; - gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt); - success = failed = 0; + for (n = ckt->CKTnodes; n; n = n->next) + ckt->CKTrhsOld [n->number] = 0; - while ((!success) && (!failed)){ - fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); - ckt->CKTnoncon = 1; - iters = ckt->CKTstat->STATnumIter; + for (i = 0; i < ckt->CKTnumStates; i++) + ckt->CKTstate0 [i] = 0; - converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); - iters = (ckt->CKTstat->STATnumIter) - iters; + factor = ckt->CKTgminFactor; + OldGmin = 1e-2; + ckt->CKTdiagGmin = OldGmin / factor; + gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt); + success = failed = 0; - if (converged == 0){ - ckt->CKTmode = continuemode; - SPfrontEnd->IFerror (ERR_INFO, - "One successful gmin step", NULL); + while ((!success) && (!failed)) { + fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon = 1; + iters = ckt->CKTstat->STATnumIter; - 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; i < ckt->CKTnumStates; i++){ - OldCKTstate0[i] = ckt->CKTstate0[i]; - } + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + iters = (ckt->CKTstat->STATnumIter) - iters; - if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){ - factor *= sqrt (factor); - if (factor > ckt->CKTgminFactor) - factor = ckt->CKTgminFactor; - } + if (converged == 0) { + ckt->CKTmode = continuemode; + SPfrontEnd->IFerror (ERR_INFO, + "One successful gmin step", NULL); - if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) - factor = sqrt (factor); - - OldGmin = ckt->CKTdiagGmin; + if (ckt->CKTdiagGmin <= gtarget) { + success = 1; + } else { + i = 0; + for (n = ckt->CKTnodes; n; n = n->next) { + OldRhsOld[i] = ckt->CKTrhsOld[n->number]; + i++; + } - 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", - NULL); - } else { - SPfrontEnd->IFerror (ERR_WARNING, - "Further gmin increment", - NULL); - factor = sqrt (sqrt (factor)); - ckt->CKTdiagGmin = OldGmin / factor; + for (i = 0; i < ckt->CKTnumStates; i++) { + OldCKTstate0[i] = ckt->CKTstate0[i]; + } - i = 0; - for (n = ckt->CKTnodes; n; n = n->next){ - ckt->CKTrhsOld[n->number] = OldRhsOld[i]; - i++; - } + if (iters <= (ckt->CKTdcTrcvMaxIter / 4)) { + factor *= sqrt (factor); + if (factor > ckt->CKTgminFactor) + factor = ckt->CKTgminFactor; + } - for (i = 0; i < ckt->CKTnumStates; i++){ - ckt->CKTstate0[i] = OldCKTstate0[i]; - } - } - } - } + if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) + factor = sqrt (factor); - ckt->CKTdiagGmin = ckt->CKTgshunt; - FREE (OldRhsOld); - FREE (OldCKTstate0); + 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", + NULL); + } else { + SPfrontEnd->IFerror (ERR_WARNING, + "Further gmin increment", + NULL); + 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; i < ckt->CKTnumStates; i++) { + ckt->CKTstate0[i] = OldCKTstate0[i]; + } + } + } + } + + ckt->CKTdiagGmin = ckt->CKTgshunt; + FREE (OldRhsOld); + FREE (OldCKTstate0); #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - if (ckt->CKTnumSrcSteps <= 0) - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; - else - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + if (ckt->CKTnumSrcSteps <= 0) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - - converged = NIiter (ckt, iterlim); - if (converged != 0){ - SPfrontEnd->IFerror (ERR_WARNING, - "Dynamic gmin stepping failed", - NULL); + converged = NIiter (ckt, iterlim); + + if (converged != 0) { + SPfrontEnd->IFerror (ERR_WARNING, + "Dynamic gmin stepping failed", + NULL); } else { - SPfrontEnd->IFerror (ERR_INFO, - "Dynamic gmin stepping completed", - NULL); + SPfrontEnd->IFerror (ERR_INFO, + "Dynamic gmin stepping completed", + NULL); #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif } - return (converged); + return (converged); } /* Spice3 gmin stepping * Modified 2000 - Alan Gillespie (added gshunt) * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) - * + * * return value: * 0 -> method converged * 1 -> method failed * - * Note that no path out of this code allows ckt->CKTdiagGmin to be + * Note that no path out of this code allows ckt->CKTdiagGmin to be * anything but CKTgshunt. */ static int spice3_gmin (CKTcircuit * ckt, long int firstmode, - long int continuemode, int iterlim) + long int continuemode, int iterlim) { - int converged, i; + int converged, i; - ckt->CKTmode = firstmode; - SPfrontEnd->IFerror (ERR_INFO, - "Starting gmin stepping", NULL); + ckt->CKTmode = firstmode; + SPfrontEnd->IFerror (ERR_INFO, + "Starting gmin stepping", NULL); - if (ckt->CKTgshunt == 0) - ckt->CKTdiagGmin = ckt->CKTgmin; - else - ckt->CKTdiagGmin = ckt->CKTgshunt; + if (ckt->CKTgshunt == 0) + ckt->CKTdiagGmin = ckt->CKTgmin; + else + ckt->CKTdiagGmin = ckt->CKTgshunt; - for (i = 0; i < ckt->CKTnumGminSteps; i++) - ckt->CKTdiagGmin *= ckt->CKTgminFactor; - + for (i = 0; i < ckt->CKTnumGminSteps; i++) + 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, ckt->CKTdcTrcvMaxIter); - if (converged != 0){ - ckt->CKTdiagGmin = ckt->CKTgshunt; - SPfrontEnd->IFerror (ERR_WARNING, - "gmin step failed", NULL); - break; - } + for (i = 0; i <= ckt->CKTnumGminSteps; i++) { + fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon = 1; + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); - ckt->CKTdiagGmin /= ckt->CKTgminFactor; - ckt->CKTmode = continuemode; + if (converged != 0) { + ckt->CKTdiagGmin = ckt->CKTgshunt; + SPfrontEnd->IFerror (ERR_WARNING, + "gmin step failed", NULL); + break; + } - SPfrontEnd->IFerror (ERR_INFO, - "One successful gmin step", NULL); - } + ckt->CKTdiagGmin /= ckt->CKTgminFactor; + ckt->CKTmode = continuemode; - ckt->CKTdiagGmin = ckt->CKTgshunt; + SPfrontEnd->IFerror (ERR_INFO, + "One successful gmin step", NULL); + } + + ckt->CKTdiagGmin = ckt->CKTgshunt; #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - if (ckt->CKTnumSrcSteps <= 0) - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; - else - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + if (ckt->CKTnumSrcSteps <= 0) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - converged = NIiter (ckt, iterlim); + converged = NIiter (ckt, iterlim); - if (converged == 0){ - SPfrontEnd->IFerror (ERR_INFO, - "gmin stepping completed", NULL); + if (converged == 0) { + SPfrontEnd->IFerror (ERR_INFO, + "gmin stepping completed", NULL); #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif } else { - SPfrontEnd->IFerror (ERR_WARNING, - "gmin stepping failed", NULL); + SPfrontEnd->IFerror (ERR_WARNING, + "gmin stepping failed", NULL); } - return (converged); + return (converged); } /* Gillespie's Source stepping * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) - * + * * return value: * 0 -> method converged * 1 -> method failed * - * Note that no path out of this code allows ckt->CKTsrcFact to be + * Note that no path out of this code allows ckt->CKTsrcFact to be * anything but 1.00000. */ static int gillespie_src (CKTcircuit * ckt, long int firstmode, - long int continuemode, int iterlim) + long int continuemode, int iterlim) { - int converged, NumNodes, i, iters; - double raise, ConvFact; - double *OldRhsOld, *OldCKTstate0; - CKTnode *n; + int converged, NumNodes, i, iters; + double raise, ConvFact; + double *OldRhsOld, *OldCKTstate0; + CKTnode *n; - NG_IGNORE(iterlim); + NG_IGNORE(iterlim); - ckt->CKTmode = firstmode; - SPfrontEnd->IFerror (ERR_INFO, - "Starting source stepping", NULL); + ckt->CKTmode = firstmode; + SPfrontEnd->IFerror (ERR_INFO, + "Starting source stepping", NULL); - ckt->CKTsrcFact = 0; - raise = 0.001; - ConvFact = 0; + ckt->CKTsrcFact = 0; + raise = 0.001; + ConvFact = 0; - NumNodes = 0; - for (n = ckt->CKTnodes; n; n = n->next){ - NumNodes++; - } - - OldRhsOld = TMALLOC(double, NumNodes + 1); - OldCKTstate0 = - TMALLOC(double, ckt->CKTnumStates + 1); - - for (n = ckt->CKTnodes; n; n = n->next) - ckt->CKTrhsOld[n->number] = 0; - - for (i = 0; i < ckt->CKTnumStates; i++) - ckt->CKTstate0[i] = 0; - -/* First, try a straight solution with all sources at zero */ - - fprintf (stderr, "Supplies 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){ - 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; - -#ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; -/* gtri - end - wbk - add convergence problem reporting flags */ -#endif - - converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); - - if (converged != 0){ - ckt->CKTdiagGmin = ckt->CKTgshunt; - SPfrontEnd->IFerror (ERR_WARNING, - "gmin step failed", NULL); - #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ -#endif - break; - } - - ckt->CKTdiagGmin /= 10; - ckt->CKTmode = continuemode; - SPfrontEnd->IFerror (ERR_INFO, - "One successful gmin step", - 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; i < ckt->CKTnumStates; i++) - OldCKTstate0[i] = ckt->CKTstate0[i]; - - - SPfrontEnd->IFerror (ERR_INFO, - "One successful source step", NULL); - ckt->CKTsrcFact = ConvFact + raise; - } - - - if (converged == 0) - do { - fprintf (stderr, - "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); - - iters = ckt->CKTstat->STATnumIter; - -#ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; -/* gtri - end - wbk - add convergence problem reporting flags */ -#endif - 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; i < ckt->CKTnumStates; i++) - OldCKTstate0[i] = ckt->CKTstate0[i]; - - SPfrontEnd->IFerror (ERR_INFO, - "One successful source step", - 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; i < ckt->CKTnumStates; 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", NULL); - return (E_ITERLIM); + NumNodes = 0; + for (n = ckt->CKTnodes; n; n = n->next) { + NumNodes++; } - else - { - SPfrontEnd->IFerror (ERR_INFO, - "Source stepping completed", NULL); - return (0); + + OldRhsOld = TMALLOC(double, NumNodes + 1); + OldCKTstate0 = + TMALLOC(double, ckt->CKTnumStates + 1); + + for (n = ckt->CKTnodes; n; n = n->next) + ckt->CKTrhsOld[n->number] = 0; + + for (i = 0; i < ckt->CKTnumStates; i++) + ckt->CKTstate0[i] = 0; + + /* First, try a straight solution with all sources at zero */ + + fprintf (stderr, "Supplies 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) { + 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; + +#ifdef XSPICE + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + /* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + + if (converged != 0) { + ckt->CKTdiagGmin = ckt->CKTgshunt; + SPfrontEnd->IFerror (ERR_WARNING, + "gmin step failed", NULL); +#ifdef XSPICE + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ +#endif + break; + } + + ckt->CKTdiagGmin /= 10; + ckt->CKTmode = continuemode; + SPfrontEnd->IFerror (ERR_INFO, + "One successful gmin step", + 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; i < ckt->CKTnumStates; i++) + OldCKTstate0[i] = ckt->CKTstate0[i]; + + + SPfrontEnd->IFerror (ERR_INFO, + "One successful source step", NULL); + ckt->CKTsrcFact = ConvFact + raise; + } + + + if (converged == 0) + do { + fprintf (stderr, + "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); + + iters = ckt->CKTstat->STATnumIter; + +#ifdef XSPICE + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + /* gtri - end - wbk - add convergence problem reporting flags */ +#endif + 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; i < ckt->CKTnumStates; i++) + OldCKTstate0[i] = ckt->CKTstate0[i]; + + SPfrontEnd->IFerror (ERR_INFO, + "One successful source step", + 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; i < ckt->CKTnumStates; 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", NULL); + return (E_ITERLIM); + } else { + SPfrontEnd->IFerror (ERR_INFO, + "Source stepping completed", NULL); + return (0); } } /* Spice3 Source stepping * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) - * + * * return value: * 0 -> method converged * 1 -> method failed * - * Note that no path out of this code allows ckt->CKTsrcFact to be + * Note that no path out of this code allows ckt->CKTsrcFact to be * anything but 1.00000. */ static int spice3_src (CKTcircuit * ckt, long int firstmode, - long int continuemode, int iterlim) + long int continuemode, int iterlim) { - int converged, i; + int converged, i; - NG_IGNORE(iterlim); + NG_IGNORE(iterlim); - ckt->CKTmode = firstmode; - SPfrontEnd->IFerror (ERR_INFO, - "Starting source stepping", NULL); + ckt->CKTmode = firstmode; + SPfrontEnd->IFerror (ERR_INFO, + "Starting source stepping", NULL); - for (i = 0; i <= ckt->CKTnumSrcSteps; i++) - { - ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps); + for (i = 0; i <= ckt->CKTnumSrcSteps; i++) { + ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps); #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - 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", NULL); + 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", NULL); #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - return (converged); - } - SPfrontEnd->IFerror (ERR_INFO, - "One successful source step", NULL); + return (converged); + } + SPfrontEnd->IFerror (ERR_INFO, + "One successful source step", NULL); } - SPfrontEnd->IFerror (ERR_INFO, - "Source stepping completed", NULL); - ckt->CKTsrcFact = 1; + SPfrontEnd->IFerror (ERR_INFO, + "Source stepping completed", NULL); + ckt->CKTsrcFact = 1; #ifdef XSPICE -/* gtri - begin - wbk - add convergence problem reporting flags */ - ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; -/* gtri - end - wbk - add convergence problem reporting flags */ + /* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; + /* gtri - end - wbk - add convergence problem reporting flags */ #endif - return (0); + return (0); } diff --git a/src/spicelib/analysis/cktpzstr.c b/src/spicelib/analysis/cktpzstr.c index 4f5d12e97..479e26d04 100644 --- a/src/spicelib/analysis/cktpzstr.c +++ b/src/spicelib/analysis/cktpzstr.c @@ -635,12 +635,12 @@ CKTpzRunTrial(CKTcircuit *ckt, PZtrial **new_trialp, PZtrial **set) if (!(p->flags & ISAROOT) && CKTpzTrapped == 3 && NIpzK != 0.0 && NIpzK_mag > -10) { #ifdef notdef - if (p->flags & ISAROOT) { - /* Ugh! muller doesn't work right */ - new_trial->flags = ISAMINIMA; - new_trial->s.imag = scalb(NIpzK, (int) (NIpzK_mag / 2)); - pretest = 0; - } else { +// if (p->flags & ISAROOT) { +// /* Ugh! muller doesn't work right */ +// new_trial->flags = ISAMINIMA; +// new_trial->s.imag = scalb(NIpzK, (int) (NIpzK_mag / 2)); +// pretest = 0; +// } else { #endif p->flags |= ISAMINIMA; tfree(new_trial); diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 978513643..bb2682610 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -184,9 +184,7 @@ int sens_sens(CKTcircuit *ckt, int restart) sg->ptable[sg->param].keyword); } - SPfrontEnd->IFnewUid (ckt, - output_names + k, NULL, - namebuf, UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, output_names + k, NULL, namebuf, UID_OTHER, NULL); k += 1; } @@ -195,16 +193,14 @@ int sens_sens(CKTcircuit *ckt, int restart) freq_name = NULL; } else { type = IF_COMPLEX; - SPfrontEnd->IFnewUid (ckt, - &freq_name, NULL, - "frequency", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &freq_name, NULL, "frequency", UID_OTHER, NULL); } - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - freq_name, IF_REAL, - num_vars, output_names, type, &sen_data); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + freq_name, IF_REAL, + num_vars, output_names, type, + &sen_data); if (error) return error; @@ -216,8 +212,7 @@ int sens_sens(CKTcircuit *ckt, int restart) output_values = NULL; output_cvalues = NEWN(IFcomplex, num_vars); if (job->step_type != SENS_LINEAR) - SPfrontEnd->OUTattributes (sen_data, - NULL, OUT_SCALE_LOG, NULL); + SPfrontEnd->OUTattributes (sen_data, NULL, OUT_SCALE_LOG, NULL); } diff --git a/src/spicelib/analysis/cktsetup.c b/src/spicelib/analysis/cktsetup.c index 6e2512004..aa712091f 100644 --- a/src/spicelib/analysis/cktsetup.c +++ b/src/spicelib/analysis/cktsetup.c @@ -61,7 +61,9 @@ CKTsetup(CKTcircuit *ckt) #ifdef WANT_SENSE2 if(ckt->CKTsenInfo){ - if (error = CKTsenSetup(ckt)) return(error); + error = CKTsenSetup(ckt); + if (error) + return(error); } #endif @@ -269,6 +271,22 @@ CKTsetup(CKTcircuit *ckt) /* gtri - end - Setup for adding rshunt option resistors */ #endif + +#ifdef KIRCHHOFF + /** Marking node as Non-Linear when needed + * By default every node is Linear + */ + for (i = 0 ; i < DEVmaxnum ; i++) + { + if (DEVices[i] && DEVices[i]->DEVnodeIsNonLinear && ckt->CKThead[i]) + { + error = DEVices[i]->DEVnodeIsNonLinear (ckt->CKThead[i], ckt) ; + if (error) + return (error) ; + } + } +#endif + return(OK); } diff --git a/src/spicelib/analysis/cktsgen.c b/src/spicelib/analysis/cktsgen.c index b50e1e0b1..70cc4c13d 100644 --- a/src/spicelib/analysis/cktsgen.c +++ b/src/spicelib/analysis/cktsgen.c @@ -237,8 +237,8 @@ int set_param(sgen *sg) } #ifdef notdef -sgen_suspend(sg) - sgen *sg; +void +sgen_suspend(sgen *sg) { sg->devlist[sg->dev] = sg->first_model; sg->model->GENnextModel = sg->next_model; @@ -246,8 +246,8 @@ sgen_suspend(sg) sg->model->GENinstances = sg->first_instance; } -sgen_restore(sg) - sgen *sg; +void +sgen_restore(sgen *sg) { sg->devlist[sg->dev] = sg->model; sg->model->GENnextModel = NULL; diff --git a/src/spicelib/analysis/dcop.c b/src/spicelib/analysis/dcop.c index 64d5d85d2..1e33a6bfa 100644 --- a/src/spicelib/analysis/dcop.c +++ b/src/spicelib/analysis/dcop.c @@ -21,6 +21,11 @@ Modified: 2000 AlansFixes int DCop(CKTcircuit *ckt, int notused) { +#ifdef WANT_SENSE2 + int i, senmode, size; + long save; +#endif + int converged; int error; IFuid *nameList; /* va: tmalloc'ed list */ @@ -45,11 +50,11 @@ DCop(CKTcircuit *ckt, int notused) error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - NULL, IF_REAL, - numNames, nameList, IF_REAL, &plot); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); tfree(nameList); /* va: nameList not used any longer, it was a memory leak */ if(error) return(error); @@ -133,7 +138,10 @@ DCop(CKTcircuit *ckt, int notused) for(i = 1; i<=size ; i++){ ckt->CKTrhsOp[i] = ckt->CKTrhsOld[i]; } - if(error = CKTsenDCtran(ckt)) return(error); + error = CKTsenDCtran(ckt); + if (error) + return(error); + ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = senmode; diff --git a/src/spicelib/analysis/dcpss.c b/src/spicelib/analysis/dcpss.c index 1e64514d1..2afb2374f 100644 --- a/src/spicelib/analysis/dcpss.c +++ b/src/spicelib/analysis/dcpss.c @@ -237,13 +237,12 @@ DCpss(CKTcircuit *ckt, /* Time Domain plot start and prepared to be filled in later */ error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, - "time", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "Time Domain Periodic Steady State Analysis", - timeUid, IF_REAL, - numNames, nameList, IF_REAL, &(job->PSSplot_td)); + SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, "time", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Time Domain Periodic Steady State Analysis", + timeUid, IF_REAL, + numNames, nameList, IF_REAL, + &(job->PSSplot_td)); tfree(nameList); if(error) return(error); @@ -406,11 +405,11 @@ DCpss(CKTcircuit *ckt, if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5; firsttime=0; /* To get rawfile working saj*/ - error = SPfrontEnd->OUTpBeginPlot ( - NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, &(job->PSSplot_td)); + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &(job->PSSplot_td)); if(error) { fprintf(stderr, "Couldn't relink rawfile\n"); return error; @@ -1039,8 +1038,11 @@ DCpss(CKTcircuit *ckt, if (error) return (error) ; SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL) ; - error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, "Frequency Domain Periodic Steady State Analysis", - freqUid, IF_REAL, numNames, nameList, IF_REAL, &(job->PSSplot_fd)) ; + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Frequency Domain Periodic Steady State Analysis", + freqUid, IF_REAL, + numNames, nameList, IF_REAL, + &(job->PSSplot_fd)) ; tfree (nameList) ; SPfrontEnd->OUTattributes (job->PSSplot_fd, NULL, PLOT_COMB, NULL) ; @@ -1204,9 +1206,25 @@ resume: #endif } -#ifdef XSPICE +#ifndef XSPICE + /* don't want to get below delmin for no reason */ + ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0); +#endif + } +#ifndef XSPICE + else if(ckt->CKTtime + ckt->CKTdelta >= ckt->CKTbreaks[0]) { + ckt->CKTsaveDelta = ckt->CKTdelta; + ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime; + /* fprintf (stderr, "delta cut to %g to hit breakpoint\n" ,ckt->CKTdelta) ; */ + fflush(stdout); + ckt->CKTbreak = 1; /* why? the current pt. is not a bkpt. */ + } +#endif /* !XSPICE */ + + +#ifdef XSPICE /* gtri - begin - wbk - Add Breakpoint stuff */ if(ckt->CKTtime + ckt->CKTdelta >= g_mif_info.breakpoint.current) { @@ -1247,28 +1265,7 @@ resume: } /* gtri - end - wbk - Modify Breakpoint stuff */ -#else /* !XSPICE */ - /* don't want to get below delmin for no reason */ - ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0); - } - else if(ckt->CKTtime + ckt->CKTdelta >= ckt->CKTbreaks[0]) { - ckt->CKTsaveDelta = ckt->CKTdelta; - ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime; - /* fprintf (stderr, "delta cut to %g to hit breakpoint\n" ,ckt->CKTdelta) ; */ - fflush(stdout); - ckt->CKTbreak = 1; /* why? the current pt. is not a bkpt. */ - } -#ifdef CLUSTER - if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) { - fprintf (stderr, "Sync error!\n"); - exit(0); - } -#endif - -#endif /* XSPICE */ - -#ifdef XSPICE /* gtri - begin - wbk - Do event solution */ if(ckt->evt->counts.num_insts > 0) { @@ -1311,6 +1308,15 @@ resume: } /* end if there are event instances */ /* gtri - end - wbk - Do event solution */ +#else + +#ifdef CLUSTER + if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) { + fprintf (stderr, "Sync error!\n"); + exit(0); + } +#endif /* CLUSTER */ + #endif /* What is that??? */ diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index 708af9130..7652b95e2 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -34,6 +34,9 @@ extern struct dbcomm *dbs; #include "ngspice/cluster.h" #endif +#ifdef SHARED_MODULE +extern int add_bkpt(void); +#endif #define INIT_STATS() \ do { \ @@ -78,9 +81,8 @@ DCtran(CKTcircuit *ckt, int firsttime; int error; #ifdef WANT_SENSE2 -#ifdef SENSDEBUG - FILE *outsen; -#endif /* SENSDEBUG */ + int save, save2, size; + long save1; #endif int save_order; long save_mode; @@ -132,7 +134,9 @@ DCtran(CKTcircuit *ckt, ckt->CKTbreaks[0] = 0; ckt->CKTbreaks[1] = ckt->CKTfinalTime; ckt->CKTbreakSize = 2; - +#ifdef SHARED_MODULE + add_bkpt(); +#endif #ifdef XSPICE /* gtri - begin - wbk - 12/19/90 - Modify setting of CKTminBreak */ /* Set to 10 times delmin for ATESSE 1 compatibity */ @@ -155,13 +159,12 @@ DCtran(CKTcircuit *ckt, #endif error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, - "time", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - timeUid, IF_REAL, - numNames, nameList, IF_REAL, &(job->TRANplot)); + SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, "time", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + timeUid, IF_REAL, + numNames, nameList, IF_REAL, + &(job->TRANplot)); tfree(nameList); if(error) return(error); @@ -316,7 +319,10 @@ DCtran(CKTcircuit *ckt, save2 = ckt->CKTorder; ckt->CKTmode = save_mode; ckt->CKTorder = save_order; - if(error = CKTsenDCtran(ckt)) return(error); + error = CKTsenDCtran(ckt); + if (error) + return(error); + ckt->CKTmode = save1; ckt->CKTorder = save2; } @@ -348,11 +354,11 @@ DCtran(CKTcircuit *ckt, if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5; firsttime=0; /* To get rawfile working saj*/ - error = SPfrontEnd->OUTpBeginPlot ( - NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, &(job->TRANplot)); + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &(job->TRANplot)); if(error) { fprintf(stderr, "Couldn't relink rawfile\n"); return error; @@ -479,9 +485,6 @@ DCtran(CKTcircuit *ckt, #ifdef WANT_SENSE2 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){ ckt->CKTsenInfo->SENmode = save; -#ifdef SENSDEBUG - fclose(outsen); -#endif /* SENSDEBUG */ } #endif return(OK); @@ -508,7 +511,7 @@ resume: if (ckt->CKTtime == 0.) SetAnalyse( "tran init", 0); else - SetAnalyse( "tran", (int)((ckt->CKTtime * 1000.) / ckt->CKTfinalTime) + 0.5); + SetAnalyse( "tran", (int)((ckt->CKTtime * 1000.) / ckt->CKTfinalTime + 0.5)); #endif ckt->CKTdelta = MIN(ckt->CKTdelta,ckt->CKTmaxStep); @@ -546,15 +549,37 @@ resume: ckt->CKTbreaks[1] - ckt->CKTbreaks[0])); if(firsttime) { + /* set a breakpoint to reduce ringing of current in devices */ + if (ckt->CKTmode&MODEUIC) + CKTsetBreak(ckt,ckt->CKTstep); + ckt->CKTdelta /= 10; #ifdef STEPDEBUG (void)printf("delta cut for initial timepoint\n"); #endif } -#ifdef XSPICE +#ifndef XSPICE + /* don't want to get below delmin for no reason */ + ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0); +#endif + } +#ifndef XSPICE + else if(ckt->CKTtime + ckt->CKTdelta >= ckt->CKTbreaks[0]) { + ckt->CKTsaveDelta = ckt->CKTdelta; + ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime; +#ifdef STEPDEBUG + (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. */ + } +#endif /* !XSPICE */ + + +#ifdef XSPICE /* gtri - begin - wbk - Add Breakpoint stuff */ if(ckt->CKTtime + ckt->CKTdelta >= g_mif_info.breakpoint.current) { @@ -595,30 +620,7 @@ resume: } /* gtri - end - wbk - Modify Breakpoint stuff */ -#else /* !XSPICE */ - /* don't want to get below delmin for no reason */ - ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0); - } - else if(ckt->CKTtime + ckt->CKTdelta >= ckt->CKTbreaks[0]) { - ckt->CKTsaveDelta = ckt->CKTdelta; - ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime; -#ifdef STEPDEBUG - (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. */ - } -#ifdef CLUSTER - if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) { - printf("Sync error!\n"); - exit(0); - } -#endif - -#endif /* XSPICE */ - -#ifdef XSPICE /* gtri - begin - wbk - Do event solution */ if(ckt->evt->counts.num_insts > 0) { @@ -661,6 +663,15 @@ resume: } /* end if there are event instances */ /* gtri - end - wbk - Do event solution */ +#else + +#ifdef CLUSTER + if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) { + printf("Sync error!\n"); + exit(0); + } +#endif /* CLUSTER */ + #endif for(i=5; i>=0; i--) ckt->CKTdeltaOld[i+1] = ckt->CKTdeltaOld[i]; @@ -792,7 +803,10 @@ resume: save2 = ckt->CKTorder; ckt->CKTmode = save_mode; ckt->CKTorder = save_order; - if(error = CKTsenDCtran(ckt)) return(error); + error = CKTsenDCtran (ckt); + if (error) + return(error); + ckt->CKTmode = save1; ckt->CKTorder = save2; } @@ -852,7 +866,10 @@ resume: save2 = ckt->CKTorder; ckt->CKTmode = save_mode; ckt->CKTorder = save_order; - if(error = CKTsenDCtran(ckt)) return(error); + error = CKTsenDCtran(ckt); + if (error) + return (error); + ckt->CKTmode = save1; ckt->CKTorder = save2; } diff --git a/src/spicelib/analysis/dctrcurv.c b/src/spicelib/analysis/dctrcurv.c index 49e4742b9..0001f4024 100644 --- a/src/spicelib/analysis/dctrcurv.c +++ b/src/spicelib/analysis/dctrcurv.c @@ -50,6 +50,7 @@ DCtrCurv(CKTcircuit *ckt, int restart) static runDesc *plot = NULL; #ifdef WANT_SENSE2 + long save; #ifdef SENSDEBUG if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode&DCSEN) ){ printf("\nDC Sensitivity Results\n\n"); @@ -66,11 +67,11 @@ DCtrCurv(CKTcircuit *ckt, int restart) /* continuing */ i = job->TRCVnestState; /* resume to work? saj*/ - error = SPfrontEnd->OUTpBeginPlot ( - NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, &plot); + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &plot); goto resume; } ckt->CKTtime = 0; @@ -192,36 +193,31 @@ found:; if (job->TRCVvType[i] == vcode) - SPfrontEnd->IFnewUid (ckt, &varUid, NULL, - "v-sweep", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "v-sweep", UID_OTHER, NULL); else { if (job->TRCVvType[i] == icode) - SPfrontEnd->IFnewUid (ckt, &varUid, NULL, - "i-sweep", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "i-sweep", UID_OTHER, NULL); else { if (job->TRCVvType[i] == TEMP_CODE) - SPfrontEnd->IFnewUid (ckt, &varUid, NULL, - "temp-sweep", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL); else { if (job->TRCVvType[i] == rcode) - SPfrontEnd->IFnewUid (ckt, &varUid, NULL, - "res-sweep", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL); else - SPfrontEnd->IFnewUid (ckt, &varUid, NULL, - "?-sweep", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL); } /* icode */ } /* TEMP_CODE */ } /* rcode*/ - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - varUid, IF_REAL, - numNames, nameList, IF_REAL, &plot); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + varUid, IF_REAL, + numNames, nameList, IF_REAL, + &plot); tfree(nameList); if(error) return(error); @@ -450,7 +446,7 @@ resume: } if (job->TRCVvType[i] == TEMP_CODE) { /* Temperature */ printf("Current Circuit Temperature : %.5e C\n", - ckt-CKTtemp - CONSTCtoK); + ckt->CKTtemp - CONSTCtoK); } #endif /* SENSDEBUG */ @@ -458,7 +454,10 @@ resume: senmode = ckt->CKTsenInfo->SENmode; save = ckt->CKTmode; ckt->CKTsenInfo->SENmode = DCSEN; - if(error = CKTsenDCtran(ckt)) return (error); + error = CKTsenDCtran(ckt); + if (error) + return(error); + ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = senmode; diff --git a/src/spicelib/analysis/distoan.c b/src/spicelib/analysis/distoan.c index b28564230..c7c2aea10 100644 --- a/src/spicelib/analysis/distoan.c +++ b/src/spicelib/analysis/distoan.c @@ -107,11 +107,11 @@ time1 = SPfrontEnd->IFseconds(); if (ckt->CKTkeepOpInfo) { /* Dump operating point. */ - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "Distortion Operating Point", - NULL, IF_REAL, - numNames, nameList, IF_REAL, &acPlot); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Distortion Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &acPlot); if(error) return(error); CKTdump(ckt, 0.0, acPlot); SPfrontEnd->OUTendPlot (acPlot); @@ -516,16 +516,14 @@ time1 = SPfrontEnd->IFseconds(); if (! job->Df2wanted) { error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "DISTORTION - 2nd harmonic", - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "DISTORTION - 2nd harmonic", + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); if (job->DstepType != LINEAR) { - SPfrontEnd->OUTattributes (acPlot, NULL, - OUT_SCALE_LOG, NULL); + SPfrontEnd->OUTattributes (acPlot, NULL, OUT_SCALE_LOG, NULL); } for (i=0; i< displacement ; i++) { @@ -542,13 +540,12 @@ time1 = SPfrontEnd->IFseconds(); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "DISTORTION - 3rd harmonic", - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "DISTORTION - 3rd harmonic", + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); for (i=0; i< displacement ; i++) { DkerProc(D_THRF1,job->r3H11stor[i], @@ -566,13 +563,12 @@ time1 = SPfrontEnd->IFseconds(); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "DISTORTION - IM: f1+f2", - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "DISTORTION - IM: f1+f2", + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); for (i=0; i< displacement ; i++) { DkerProc(D_F1PF2,job->r2H12stor[i], @@ -588,13 +584,12 @@ time1 = SPfrontEnd->IFseconds(); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "DISTORTION - IM: f1-f2", - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "DISTORTION - IM: f1-f2", + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); for (i=0; i< displacement ; i++) { DkerProc(D_F1MF2, @@ -611,13 +606,12 @@ time1 = SPfrontEnd->IFseconds(); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "DISTORTION - IM: 2f1-f2", - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, &acPlot); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "DISTORTION - IM: 2f1-f2", + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); for (i=0; i< displacement ; i++) { DkerProc(D_2F1MF2, diff --git a/src/spicelib/analysis/noisean.c b/src/spicelib/analysis/noisean.c index 06a2ae81c..dbb68dc71 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -1,14 +1,15 @@ -/* Patch to noisean.c by Richard D. McRoberts. - * Patched with modifications from Weidong Liu (2000) - * Patched with modifications ftom Weidong Liu - * in bsim4.1.0 code - */ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Gary W. Ng Modified: 2001 AlansFixes **********/ +/* Patch to noisean.c by Richard D. McRoberts. + * Patched with modifications from Weidong Liu (2000) + * Patched with modifications ftom Weidong Liu + * in bsim4.1.0 code + */ + #include "ngspice/ngspice.h" #include "ngspice/acdefs.h" #include "ngspice/cktdefs.h" @@ -47,8 +48,7 @@ NOISEan (CKTcircuit *ckt, int restart) inst = NULL; code = CKTtypelook("Vsource"); if (code != -1) { - error = CKTfndDev(ckt, &code, &inst, - job->input, NULL, NULL); + error = CKTfndDev(ckt, &code, &inst, job->input, NULL); if (!error && !((VSRCinstance *)inst)->VSRCacGiven) { errMsg = TMALLOC(char, strlen(noacinput) + 1); strcpy(errMsg,noacinput); @@ -58,8 +58,7 @@ NOISEan (CKTcircuit *ckt, int restart) code = CKTtypelook("Isource"); if (code != -1 && inst==NULL) { - error = CKTfndDev(ckt, &code, &inst, - job->input, NULL, NULL); + error = CKTfndDev(ckt, &code, &inst, job->input, NULL); if (error) { /* XXX ??? */ SPfrontEnd->IFerror (ERR_WARNING, @@ -119,8 +118,7 @@ NOISEan (CKTcircuit *ckt, int restart) /* the current front-end needs the namelist to be fully declared before an OUTpBeginplot */ - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, - "frequency", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); data->numPlots = 0; /* we don't have any plots yet */ error = CKTnoise(ckt,N_DENS,N_OPEN,data); @@ -131,16 +129,15 @@ NOISEan (CKTcircuit *ckt, int restart) * plot */ - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "Noise Spectral Density Curves - (V^2 or A^2)/Hz", - freqUid, IF_REAL, - data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Noise Spectral Density Curves - (V^2 or A^2)/Hz", + freqUid, IF_REAL, + data->numPlots, data->namelist, IF_REAL, + &(data->NplotPtr)); if (error) return(error); if (job->NstpType != LINEAR) { - SPfrontEnd->OUTattributes (data->NplotPtr, NULL, - OUT_SCALE_LOG, NULL); + SPfrontEnd->OUTattributes (data->NplotPtr, NULL, OUT_SCALE_LOG, NULL); } } else { /* we must have paused before. pick up where we left off */ @@ -166,11 +163,11 @@ NOISEan (CKTcircuit *ckt, int restart) data->outNoiz = job->NsavOnoise; data->inNoise = job->NsavInoise; /* saj resume rawfile fix*/ - error = SPfrontEnd->OUTpBeginPlot ( - NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, &(data->NplotPtr)); + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &(data->NplotPtr)); /*saj*/ } @@ -278,11 +275,11 @@ NOISEan (CKTcircuit *ckt, int restart) if (error) return(error); - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "Integrated Noise - V^2 or A^2", - NULL, 0, - data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Integrated Noise - V^2 or A^2", + NULL, 0, + data->numPlots, data->namelist, IF_REAL, + &(data->NplotPtr)); error = CKTnoise(ckt,INT_NOIZ,N_CALC,data); if (error) return(error); diff --git a/src/spicelib/analysis/pzan.c b/src/spicelib/analysis/pzan.c index 6117f67df..9c975889e 100644 --- a/src/spicelib/analysis/pzan.c +++ b/src/spicelib/analysis/pzan.c @@ -46,11 +46,11 @@ PZan(CKTcircuit *ckt, int reset) /* Dump operating point. */ error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - "Distortion Operating Point", - NULL, IF_REAL, - numNames, nameList, IF_REAL, &plot); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "Distortion Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); if(error) return(error); CKTdump(ckt, 0.0, plot); SPfrontEnd->OUTendPlot (plot); @@ -94,7 +94,7 @@ PZinit(CKTcircuit *ckt) i = CKTtypelook("LTRA"); } if (i != -1 && ckt->CKThead[i] != NULL) - MERROR(E_XMISSIONLINE, "Transmission lines not supported") + MERROR(E_XMISSIONLINE, "Transmission lines not supported"); job->PZpoleList = NULL; job->PZzeroList = NULL; @@ -102,19 +102,19 @@ PZinit(CKTcircuit *ckt) job->PZnZeros = 0; if (job->PZin_pos == job->PZin_neg) - MERROR(E_SHORT, "Input is shorted") + MERROR(E_SHORT, "Input is shorted"); if (job->PZout_pos == job->PZout_neg) - MERROR(E_SHORT, "Output is shorted") + MERROR(E_SHORT, "Output is shorted"); if (job->PZin_pos == job->PZout_pos && job->PZin_neg == job->PZout_neg && job->PZinput_type == PZ_IN_VOL) - MERROR(E_INISOUT, "Transfer function is unity") + MERROR(E_INISOUT, "Transfer function is unity"); else if (job->PZin_pos == job->PZout_neg && job->PZin_neg == job->PZout_pos && job->PZinput_type == PZ_IN_VOL) - MERROR(E_INISOUT, "Transfer function is -1") + MERROR(E_INISOUT, "Transfer function is -1"); return(OK); } @@ -141,20 +141,18 @@ PZpost(CKTcircuit *ckt) j = 0; for (i = 0; i < job->PZnPoles; i++) { sprintf(name, "pole(%-u)", i+1); - SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, - name, UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, name, UID_OTHER, NULL); } for (i = 0; i < job->PZnZeros; i++) { sprintf(name, "zero(%-u)", i+1); - SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, - name, UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, name, UID_OTHER, NULL); } - SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - NULL, 0, - job->PZnPoles + job->PZnZeros, namelist, IF_COMPLEX, &pzPlotPtr); + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, 0, + job->PZnPoles + job->PZnZeros, namelist, IF_COMPLEX, + &pzPlotPtr); j = 0; if (job->PZnPoles > 0) { diff --git a/src/spicelib/analysis/tfanal.c b/src/spicelib/analysis/tfanal.c index aa7fa2439..2a611cbb1 100644 --- a/src/spicelib/analysis/tfanal.c +++ b/src/spicelib/analysis/tfanal.c @@ -51,8 +51,7 @@ TFanal(CKTcircuit *ckt, int restart) Itype = CKTtypelook("Isource"); Vtype = CKTtypelook("Vsource"); if(Itype != -1) { - error = CKTfndDev(ckt,&Itype,&ptr, - job->TFinSrc, NULL, NULL); + error = CKTfndDev(ckt, &Itype, &ptr, job->TFinSrc, NULL); if(error ==0) { job->TFinIsI = 1; job->TFinIsV = 0; @@ -62,9 +61,7 @@ TFanal(CKTcircuit *ckt, int restart) } if( (Vtype != -1) && (ptr==NULL) ) { - error = CKTfndDev(ckt,&Vtype,&ptr, - job->TFinSrc, NULL, - NULL); + error = CKTfndDev(ckt, &Vtype, &ptr, job->TFinSrc, NULL); job->TFinIsV = 1; job->TFinIsI = 0; if(error !=0) { @@ -94,30 +91,26 @@ TFanal(CKTcircuit *ckt, int restart) ckt->CKTrhs[0]=0; /* make a UID for the transfer function output */ - SPfrontEnd->IFnewUid (ckt, &tfuid, NULL, "Transfer_function", - UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &tfuid, NULL, "Transfer_function", UID_OTHER, NULL); /* make a UID for the input impedance */ - SPfrontEnd->IFnewUid (ckt, &inuid, job->TFinSrc, - "Input_impedance", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &inuid, job->TFinSrc, "Input_impedance", UID_OTHER, NULL); /* make a UID for the output impedance */ if (job->TFoutIsI) { - SPfrontEnd->IFnewUid (ckt, &outuid, job->TFoutSrc - ,"Output_impedance", UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &outuid, job->TFoutSrc ,"Output_impedance", UID_OTHER, NULL); } else { name = TMALLOC(char, strlen(job->TFoutName) + 22); (void)sprintf(name,"output_impedance_at_%s", job->TFoutName); - SPfrontEnd->IFnewUid (ckt, &outuid, NULL, - name, UID_OTHER, NULL); + SPfrontEnd->IFnewUid (ckt, &outuid, NULL, name, UID_OTHER, NULL); } - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - job->JOBname, - NULL, 0, - 3, uids, IF_REAL, &plotptr); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + job->JOBname, + NULL, 0, + 3, uids, IF_REAL, + &plotptr); if(error) return(error); /*find transfer function */ diff --git a/src/spicelib/analysis/traninit.c b/src/spicelib/analysis/traninit.c index cfca9426a..b25aa6cf4 100644 --- a/src/spicelib/analysis/traninit.c +++ b/src/spicelib/analysis/traninit.c @@ -21,25 +21,16 @@ int TRANinit(CKTcircuit *ckt, JOB *anal) ckt->CKTstep = job->TRANstep; ckt->CKTinitTime = job->TRANinitTime; ckt->CKTmaxStep = job->TRANmaxStep; - - - - /* The following code has been taken from macspice 3f4 (A. Wilson) - in the file traninit.new.c - Seems interesting */ - if(ckt->CKTmaxStep == 0) - { - if (ckt->CKTstep < ( ckt->CKTfinalTime - ckt->CKTinitTime )/50.0) - { - ckt->CKTmaxStep = ckt->CKTstep; - } - else - { - ckt->CKTmaxStep = ( ckt->CKTfinalTime - ckt->CKTinitTime )/50.0; - } -} - - + /* The following code has been taken from macspice 3f4 (A. Wilson) + in the file traninit.new.c - Seems interesting */ + if(ckt->CKTmaxStep == 0) { + if (ckt->CKTstep < ( ckt->CKTfinalTime - ckt->CKTinitTime )/50.0) + ckt->CKTmaxStep = ckt->CKTstep; + else + ckt->CKTmaxStep = ( ckt->CKTfinalTime - ckt->CKTinitTime )/50.0; + } + ckt->CKTdelmin = 1e-11*ckt->CKTmaxStep; /* XXX */ ckt->CKTmode = job->TRANmode; diff --git a/src/spicelib/devices/asrc/Makefile.am b/src/spicelib/devices/asrc/Makefile.am index 01f292d21..473ddf39c 100644 --- a/src/spicelib/devices/asrc/Makefile.am +++ b/src/spicelib/devices/asrc/Makefile.am @@ -19,10 +19,14 @@ libasrc_la_SOURCES = \ asrcmdel.c \ asrcpar.c \ asrcpzld.c \ - asrcset.c \ + asrcset.c \ asrctemp.c +if KIRCHHOFF_WANTED +libasrc_la_SOURCES += asrcnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/asrc/asrcext.h b/src/spicelib/devices/asrc/asrcext.h index a0a23f636..f9ad10052 100644 --- a/src/spicelib/devices/asrc/asrcext.h +++ b/src/spicelib/devices/asrc/asrcext.h @@ -16,3 +16,7 @@ extern int ASRCacLoad(GENmodel*,CKTcircuit*); extern int ASRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int ASRCunsetup(GENmodel*,CKTcircuit*); extern int ASRCtemp(GENmodel*,CKTcircuit*); + +#ifdef KIRCHHOFF +extern int ASRCnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/asrc/asrcinit.c b/src/spicelib/devices/asrc/asrcinit.c index 00701bb7b..8e5fd42c7 100644 --- a/src/spicelib/devices/asrc/asrcinit.c +++ b/src/spicelib/devices/asrc/asrcinit.c @@ -74,12 +74,17 @@ SPICEdev ASRCinfo = { #endif /* DEVinstSize */ &ASRCiSize, /* DEVmodSize */ &ASRCmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ NULL, /* DEVbindCSCComplex */ NULL, /* DEVbindCSCComplexToReal */ NULL, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ ASRCnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/asrc/asrcnode.c b/src/spicelib/devices/asrc/asrcnode.c new file mode 100644 index 000000000..d16066310 --- /dev/null +++ b/src/spicelib/devices/asrc/asrcnode.c @@ -0,0 +1,28 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "asrcdefs.h" +#include "ngspice/sperror.h" + +int +ASRCnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + ASRCmodel *model = (ASRCmodel *)inModel ; + ASRCinstance *here ; + + /* loop through all the ASRC models */ + for ( ; model != NULL ; model = model->ASRCnextModel) + { + /* loop through all the instances of the model */ + for (here = model->ASRCinstances ; here != NULL ; here = here->ASRCnextInstance) + { + ckt->CKTnodeIsLinear [here->ASRCposNode] = 0 ; + ckt->CKTnodeIsLinear [here->ASRCnegNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/asrc/asrcset.c b/src/spicelib/devices/asrc/asrcset.c index 8f4fb22a0..84ab66f69 100644 --- a/src/spicelib/devices/asrc/asrcset.c +++ b/src/spicelib/devices/asrc/asrcset.c @@ -54,14 +54,14 @@ ASRCsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) #define MY_TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, (second)->number)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, (second)->number)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) /* For each controlling variable set the entries in the vector of the positions of the SMP */ diff --git a/src/spicelib/devices/bjt/Makefile.am b/src/spicelib/devices/bjt/Makefile.am index a778542d7..719f903b6 100644 --- a/src/spicelib/devices/bjt/Makefile.am +++ b/src/spicelib/devices/bjt/Makefile.am @@ -47,6 +47,10 @@ if UMFPACK_WANTED libbjt_la_SOURCES += bjtbindCSC.c endif +if KIRCHHOFF_WANTED +libbjt_la_SOURCES += bjtnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bjt/bjtext.h b/src/spicelib/devices/bjt/bjtext.h index a02d2ad20..479ee5c05 100644 --- a/src/spicelib/devices/bjt/bjtext.h +++ b/src/spicelib/devices/bjt/bjtext.h @@ -32,6 +32,9 @@ extern int BJTdisto(int,GENmodel*,CKTcircuit*); extern int BJTnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BJTdSetup(GENmodel*, register CKTcircuit*); +#ifdef KIRCHHOFF +extern int BJTnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif #endif #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) diff --git a/src/spicelib/devices/bjt/bjtinit.c b/src/spicelib/devices/bjt/bjtinit.c index e75680938..266c768a8 100644 --- a/src/spicelib/devices/bjt/bjtinit.c +++ b/src/spicelib/devices/bjt/bjtinit.c @@ -73,12 +73,17 @@ SPICEdev BJTinfo = { /* description from struct IFdevice */ #endif /* DEVinstSize */ &BJTiSize, /* DEVmodSize */ &BJTmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ BJTbindCSC, /* DEVbindCSCComplex */ BJTbindCSCComplex, /* DEVbindCSCComplexToReal */ BJTbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ BJTnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bjt/bjtnode.c b/src/spicelib/devices/bjt/bjtnode.c new file mode 100644 index 000000000..69382e4cc --- /dev/null +++ b/src/spicelib/devices/bjt/bjtnode.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bjtdefs.h" +#include "ngspice/sperror.h" + +int +BJTnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BJTmodel *model = (BJTmodel *)inModel ; + BJTinstance *here ; + + /* loop through all the BJT models */ + for ( ; model != NULL ; model = model->BJTnextModel) + { + /* loop through all the instances of the model */ + for (here = model->BJTinstances ; here != NULL ; here = here->BJTnextInstance) + { + ckt->CKTnodeIsLinear [here->BJTcolPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->BJTbasePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->BJTemitPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->BJTsubstNode] = 0 ; + ckt->CKTnodeIsLinear [here->BJTsubstConNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bjt/bjtsacl.c b/src/spicelib/devices/bjt/bjtsacl.c index 46b957497..e083982f2 100644 --- a/src/spicelib/devices/bjt/bjtsacl.c +++ b/src/spicelib/devices/bjt/bjtsacl.c @@ -540,11 +540,11 @@ load: ,cbe,icbe,cce,icce); printf("cc = %.7e + j%.7e , ce = %.7e + j%.7e,", - ,cc,icc,ce,ice); + cc,icc,ce,ice); printf("ccprm = %.7e + j%.7e , ceprm = %.7e + j%.7e", ccprm,iccprm,ceprm,iceprm); printf("cb = %.7e + j%.7e , cbprm = %.7e + j%.7e , ", - cb,icb,cbprm,icbprm) + cb,icb,cbprm,icbprm); printf("cs = %.7e + j%.7e\n", cs,ics); #endif /* SENSDEBUG */ diff --git a/src/spicelib/devices/bjt/bjtsetup.c b/src/spicelib/devices/bjt/bjtsetup.c index 5c94f2edf..0ca183775 100644 --- a/src/spicelib/devices/bjt/bjtsetup.c +++ b/src/spicelib/devices/bjt/bjtsetup.c @@ -420,28 +420,28 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} - TSTALLOC(BJTcolColPrimePtr,BJTcolNode,BJTcolPrimeNode) - TSTALLOC(BJTbaseBasePrimePtr,BJTbaseNode,BJTbasePrimeNode) - TSTALLOC(BJTemitEmitPrimePtr,BJTemitNode,BJTemitPrimeNode) - TSTALLOC(BJTcolPrimeColPtr,BJTcolPrimeNode,BJTcolNode) - TSTALLOC(BJTcolPrimeBasePrimePtr,BJTcolPrimeNode,BJTbasePrimeNode) - TSTALLOC(BJTcolPrimeEmitPrimePtr,BJTcolPrimeNode,BJTemitPrimeNode) - TSTALLOC(BJTbasePrimeBasePtr,BJTbasePrimeNode,BJTbaseNode) - TSTALLOC(BJTbasePrimeColPrimePtr,BJTbasePrimeNode,BJTcolPrimeNode) - TSTALLOC(BJTbasePrimeEmitPrimePtr,BJTbasePrimeNode,BJTemitPrimeNode) - TSTALLOC(BJTemitPrimeEmitPtr,BJTemitPrimeNode,BJTemitNode) - TSTALLOC(BJTemitPrimeColPrimePtr,BJTemitPrimeNode,BJTcolPrimeNode) - TSTALLOC(BJTemitPrimeBasePrimePtr,BJTemitPrimeNode,BJTbasePrimeNode) - TSTALLOC(BJTcolColPtr,BJTcolNode,BJTcolNode) - TSTALLOC(BJTbaseBasePtr,BJTbaseNode,BJTbaseNode) - TSTALLOC(BJTemitEmitPtr,BJTemitNode,BJTemitNode) - TSTALLOC(BJTcolPrimeColPrimePtr,BJTcolPrimeNode,BJTcolPrimeNode) - TSTALLOC(BJTbasePrimeBasePrimePtr,BJTbasePrimeNode,BJTbasePrimeNode) - TSTALLOC(BJTemitPrimeEmitPrimePtr,BJTemitPrimeNode,BJTemitPrimeNode) - TSTALLOC(BJTsubstSubstPtr,BJTsubstNode,BJTsubstNode) +} } while(0) + TSTALLOC(BJTcolColPrimePtr,BJTcolNode,BJTcolPrimeNode); + TSTALLOC(BJTbaseBasePrimePtr,BJTbaseNode,BJTbasePrimeNode); + TSTALLOC(BJTemitEmitPrimePtr,BJTemitNode,BJTemitPrimeNode); + TSTALLOC(BJTcolPrimeColPtr,BJTcolPrimeNode,BJTcolNode); + TSTALLOC(BJTcolPrimeBasePrimePtr,BJTcolPrimeNode,BJTbasePrimeNode); + TSTALLOC(BJTcolPrimeEmitPrimePtr,BJTcolPrimeNode,BJTemitPrimeNode); + TSTALLOC(BJTbasePrimeBasePtr,BJTbasePrimeNode,BJTbaseNode); + TSTALLOC(BJTbasePrimeColPrimePtr,BJTbasePrimeNode,BJTcolPrimeNode); + TSTALLOC(BJTbasePrimeEmitPrimePtr,BJTbasePrimeNode,BJTemitPrimeNode); + TSTALLOC(BJTemitPrimeEmitPtr,BJTemitPrimeNode,BJTemitNode); + TSTALLOC(BJTemitPrimeColPrimePtr,BJTemitPrimeNode,BJTcolPrimeNode); + TSTALLOC(BJTemitPrimeBasePrimePtr,BJTemitPrimeNode,BJTbasePrimeNode); + TSTALLOC(BJTcolColPtr,BJTcolNode,BJTcolNode); + TSTALLOC(BJTbaseBasePtr,BJTbaseNode,BJTbaseNode); + TSTALLOC(BJTemitEmitPtr,BJTemitNode,BJTemitNode); + TSTALLOC(BJTcolPrimeColPrimePtr,BJTcolPrimeNode,BJTcolPrimeNode); + TSTALLOC(BJTbasePrimeBasePrimePtr,BJTbasePrimeNode,BJTbasePrimeNode); + TSTALLOC(BJTemitPrimeEmitPrimePtr,BJTemitPrimeNode,BJTemitPrimeNode); + TSTALLOC(BJTsubstSubstPtr,BJTsubstNode,BJTsubstNode); if (model -> BJTsubs == LATERAL) { here -> BJTsubstConNode = here -> BJTbasePrimeNode; here -> BJTsubstConSubstConPtr = here -> BJTbasePrimeBasePrimePtr; @@ -449,10 +449,10 @@ if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ here -> BJTsubstConNode = here -> BJTcolPrimeNode; here -> BJTsubstConSubstConPtr = here -> BJTcolPrimeColPrimePtr; } - TSTALLOC(BJTsubstConSubstPtr,BJTsubstConNode,BJTsubstNode) - TSTALLOC(BJTsubstSubstConPtr,BJTsubstNode,BJTsubstConNode) - TSTALLOC(BJTbaseColPrimePtr,BJTbaseNode,BJTcolPrimeNode) - TSTALLOC(BJTcolPrimeBasePtr,BJTcolPrimeNode,BJTbaseNode) + TSTALLOC(BJTsubstConSubstPtr,BJTsubstConNode,BJTsubstNode); + TSTALLOC(BJTsubstSubstConPtr,BJTsubstNode,BJTsubstConNode); + TSTALLOC(BJTbaseColPrimePtr,BJTbaseNode,BJTcolPrimeNode); + TSTALLOC(BJTcolPrimeBasePtr,BJTcolPrimeNode,BJTbaseNode); } } return(OK); diff --git a/src/spicelib/devices/bjt/bjtsupd.c b/src/spicelib/devices/bjt/bjtsupd.c index f2551e6c9..f76ef8f71 100644 --- a/src/spicelib/devices/bjt/bjtsupd.c +++ b/src/spicelib/devices/bjt/bjtsupd.c @@ -55,9 +55,8 @@ BJTsUpdate(GENmodel *inModel, CKTcircuit *ckt) sxpbx = 0; #ifdef SENSDEBUG printf("senupdate Instance name: %s\n",here->BJTname); - printf("iparmno = %d,CKTag[0] = %.2e,CKTag[1] = %.2e\n", - iparmno,ckt->CKTag[0],ckt->CKTag[1]); - + printf("CKTag[0] = %.2e,CKTag[1] = %.2e\n", + ckt->CKTag[0],ckt->CKTag[1]); printf("capbe = %.7e\n",here->BJTcapbe); printf("capbc = %.7e\n",here->BJTcapbc); printf("capsub = %.7e\n",here->BJTcapsub); diff --git a/src/spicelib/devices/bsim1/Makefile.am b/src/spicelib/devices/bsim1/Makefile.am index d544e4b67..b3750f778 100644 --- a/src/spicelib/devices/bsim1/Makefile.am +++ b/src/spicelib/devices/bsim1/Makefile.am @@ -43,6 +43,10 @@ if UMFPACK_WANTED libbsim1_la_SOURCES += b1bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim1_la_SOURCES += b1node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim1/b1node.c b/src/spicelib/devices/bsim1/b1node.c new file mode 100644 index 000000000..8e871531b --- /dev/null +++ b/src/spicelib/devices/bsim1/b1node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim1def.h" +#include "ngspice/sperror.h" + +int +B1nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B1model *model = (B1model *)inModel ; + B1instance *here ; + + /* loop through all the BSIM1 models */ + for ( ; model != NULL ; model = model->B1nextModel) + { + /* loop through all the instances of the model */ + for (here = model->B1instances ; here != NULL ; here = here->B1nextInstance) + { + ckt->CKTnodeIsLinear [here->B1dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B1sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B1gNode] = 0 ; + ckt->CKTnodeIsLinear [here->B1bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim1/b1set.c b/src/spicelib/devices/bsim1/b1set.c index ab29964ee..46ae6d5b2 100644 --- a/src/spicelib/devices/bsim1/b1set.c +++ b/src/spicelib/devices/bsim1/b1set.c @@ -368,32 +368,32 @@ B1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(B1DdPtr, B1dNode, B1dNode) - TSTALLOC(B1GgPtr, B1gNode, B1gNode) - TSTALLOC(B1SsPtr, B1sNode, B1sNode) - TSTALLOC(B1BbPtr, B1bNode, B1bNode) - TSTALLOC(B1DPdpPtr, B1dNodePrime, B1dNodePrime) - TSTALLOC(B1SPspPtr, B1sNodePrime, B1sNodePrime) - TSTALLOC(B1DdpPtr, B1dNode, B1dNodePrime) - TSTALLOC(B1GbPtr, B1gNode, B1bNode) - TSTALLOC(B1GdpPtr, B1gNode, B1dNodePrime) - TSTALLOC(B1GspPtr, B1gNode, B1sNodePrime) - TSTALLOC(B1SspPtr, B1sNode, B1sNodePrime) - TSTALLOC(B1BdpPtr, B1bNode, B1dNodePrime) - TSTALLOC(B1BspPtr, B1bNode, B1sNodePrime) - TSTALLOC(B1DPspPtr, B1dNodePrime, B1sNodePrime) - TSTALLOC(B1DPdPtr, B1dNodePrime, B1dNode) - TSTALLOC(B1BgPtr, B1bNode, B1gNode) - TSTALLOC(B1DPgPtr, B1dNodePrime, B1gNode) - TSTALLOC(B1SPgPtr, B1sNodePrime, B1gNode) - TSTALLOC(B1SPsPtr, B1sNodePrime, B1sNode) - TSTALLOC(B1DPbPtr, B1dNodePrime, B1bNode) - TSTALLOC(B1SPbPtr, B1sNodePrime, B1bNode) - TSTALLOC(B1SPdpPtr, B1sNodePrime, B1dNodePrime) + TSTALLOC(B1DdPtr, B1dNode, B1dNode); + TSTALLOC(B1GgPtr, B1gNode, B1gNode); + TSTALLOC(B1SsPtr, B1sNode, B1sNode); + TSTALLOC(B1BbPtr, B1bNode, B1bNode); + TSTALLOC(B1DPdpPtr, B1dNodePrime, B1dNodePrime); + TSTALLOC(B1SPspPtr, B1sNodePrime, B1sNodePrime); + TSTALLOC(B1DdpPtr, B1dNode, B1dNodePrime); + TSTALLOC(B1GbPtr, B1gNode, B1bNode); + TSTALLOC(B1GdpPtr, B1gNode, B1dNodePrime); + TSTALLOC(B1GspPtr, B1gNode, B1sNodePrime); + TSTALLOC(B1SspPtr, B1sNode, B1sNodePrime); + TSTALLOC(B1BdpPtr, B1bNode, B1dNodePrime); + TSTALLOC(B1BspPtr, B1bNode, B1sNodePrime); + TSTALLOC(B1DPspPtr, B1dNodePrime, B1sNodePrime); + TSTALLOC(B1DPdPtr, B1dNodePrime, B1dNode); + TSTALLOC(B1BgPtr, B1bNode, B1gNode); + TSTALLOC(B1DPgPtr, B1dNodePrime, B1gNode); + TSTALLOC(B1SPgPtr, B1sNodePrime, B1gNode); + TSTALLOC(B1SPsPtr, B1sNodePrime, B1sNode); + TSTALLOC(B1DPbPtr, B1dNodePrime, B1bNode); + TSTALLOC(B1SPbPtr, B1sNodePrime, B1bNode); + TSTALLOC(B1SPdpPtr, B1sNodePrime, B1dNodePrime); } } diff --git a/src/spicelib/devices/bsim1/bsim1ext.h b/src/spicelib/devices/bsim1/bsim1ext.h index ce3719a97..06b9ad9fb 100644 --- a/src/spicelib/devices/bsim1/bsim1ext.h +++ b/src/spicelib/devices/bsim1/bsim1ext.h @@ -35,3 +35,7 @@ extern int B1bindCSC (GENmodel*, CKTcircuit*) ; extern int B1bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B1bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B1nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim1/bsim1init.c b/src/spicelib/devices/bsim1/bsim1init.c index dc4941f25..23eb8e554 100644 --- a/src/spicelib/devices/bsim1/bsim1init.c +++ b/src/spicelib/devices/bsim1/bsim1init.c @@ -73,12 +73,17 @@ SPICEdev B1info = { #endif /* DEVinstSize */ &B1iSize, /* DEVmodSize */ &B1mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B1bindCSC, /* DEVbindCSCComplex */ B1bindCSCComplex, /* DEVbindCSCComplexToReal */ B1bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B1nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim2/Makefile.am b/src/spicelib/devices/bsim2/Makefile.am index 13d50b7b0..a382cced3 100644 --- a/src/spicelib/devices/bsim2/Makefile.am +++ b/src/spicelib/devices/bsim2/Makefile.am @@ -41,6 +41,10 @@ if UMFPACK_WANTED libbsim2_la_SOURCES += b2bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim2_la_SOURCES += b2node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim2/b2ld.c b/src/spicelib/devices/bsim2/b2ld.c index 1dca6b163..17b84d0bd 100644 --- a/src/spicelib/devices/bsim2/b2ld.c +++ b/src/spicelib/devices/bsim2/b2ld.c @@ -40,13 +40,13 @@ B2load(GENmodel *inModel, CKTcircuit *ckt) double cd; double cdrain; double cdhat; - double cdreq; + double cdreq, cdreq_fvk ; double ceq; - double ceqbd; - double ceqbs; - double ceqqb; - double ceqqd; - double ceqqg; + double ceqbd, ceqbd_fvk ; + double ceqbs, ceqbs_fvk ; + double ceqqb, ceqqb_fvk ; + double ceqqd, ceqqd_fvk ; + double ceqqg, ceqqg_fvk ; double czbd; double czbdsw; double czbs; @@ -628,7 +628,7 @@ line755: line850: /* initialize to zero charge conductance and current */ - ceqqg = ceqqb = ceqqd = 0.0; + ceqqg = ceqqg_fvk = ceqqb = ceqqb_fvk = ceqqd = ceqqd_fvk = 0.0; gcdgb = gcddb = gcdsb = 0.0; gcsgb = gcsdb = gcssb = 0.0; gcggb = gcgdb = gcgsb = 0.0; @@ -641,8 +641,11 @@ line860: cqbulk = *(ckt->CKTstate0 + here->B2iqb); cqdrn = *(ckt->CKTstate0 + here->B2iqd); ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs; + ceqqg_fvk = cqgate ; ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs; + ceqqb_fvk = cqbulk ; ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs; + ceqqd_fvk = cqdrn ; if(ckt->CKTmode & MODEINITTRAN ) { *(ckt->CKTstate1 + here->B2iqb) = @@ -661,19 +664,25 @@ line900: m = here->B2m; ceqbs = model->B2type * (cbs-(gbs-ckt->CKTgmin)*vbs); + ceqbs_fvk = model->B2type * (cbs + ckt->CKTgmin * vbs) ; ceqbd = model->B2type * (cbd-(gbd-ckt->CKTgmin)*vbd); - + ceqbd_fvk = model->B2type * (cbd + ckt->CKTgmin * vbd) ; ceqqg = model->B2type * ceqqg; + ceqqg_fvk = model->B2type * ceqqg_fvk ; ceqqb = model->B2type * ceqqb; + ceqqb_fvk = model->B2type * ceqqb_fvk ; ceqqd = model->B2type * ceqqd; + ceqqd_fvk = model->B2type * ceqqd_fvk ; if (here->B2mode >= 0) { xnrm=1; xrev=0; cdreq=model->B2type*(cdrain-gds*vds-gm*vgs-gmbs*vbs); + cdreq_fvk = model->B2type * cdrain ; } else { xnrm=0; xrev=1; cdreq = -(model->B2type)*(cdrain+gds*vds-gm*vgd-gmbs*vbd); + cdreq_fvk = - (model->B2type * cdrain) ; } *(ckt->CKTrhs + here->B2gNode) -= m * (ceqqg); @@ -712,6 +721,24 @@ line900: *(here->B2SPbPtr) += m * (-gbs-(xnrm-xrev)*gmbs-gcsgb-gcsdb-gcssb); *(here->B2SPdpPtr) += m * (-gds-xrev*(gm+gmbs)+gcsdb); +#ifdef KIRCHHOFF + /* KCL verification - Dynamic Part */ + *(ckt->CKTfvk + here->B2gNode) += m * ceqqg_fvk ; + *(ckt->CKTfvk + here->B2bNode) += m * (ceqbs_fvk + ceqbd_fvk + ceqqb_fvk) ; + *(ckt->CKTfvk + here->B2dNodePrime) -= m * (ceqbd_fvk - cdreq_fvk - ceqqd_fvk) ; + *(ckt->CKTfvk + here->B2sNodePrime) -= m * (cdreq_fvk + ceqbs_fvk + ceqqg_fvk + ceqqb_fvk + ceqqd_fvk) ; + + + /* KCL verification - Linear and Static Part */ + *(ckt->CKTfvk + here->B2dNode) += m * (here->B2drainConductance) * *(ckt->CKTrhsOld + here->B2dNode) ; + *(ckt->CKTfvk + here->B2sNode) += m * (here->B2sourceConductance) * *(ckt->CKTrhsOld + here->B2sNode) ; + *(ckt->CKTfvk + here->B2dNodePrime) += m * (here->B2drainConductance) * *(ckt->CKTrhsOld + here->B2dNodePrime) ; + *(ckt->CKTfvk + here->B2sNodePrime) += m * (here->B2sourceConductance) * *(ckt->CKTrhsOld + here->B2sNodePrime) ; + *(ckt->CKTfvk + here->B2dNode) += m * (-here->B2drainConductance) * *(ckt->CKTrhsOld + here->B2dNodePrime) ; + *(ckt->CKTfvk + here->B2sNode) += m * (-here->B2sourceConductance) * *(ckt->CKTrhsOld + here->B2sNodePrime) ; + *(ckt->CKTfvk + here->B2dNodePrime) += m * (-here->B2drainConductance) * *(ckt->CKTrhsOld + here->B2dNode) ; + *(ckt->CKTfvk + here->B2sNodePrime) += m * (-here->B2sourceConductance) * *(ckt->CKTrhsOld + here->B2sNode) ; +#endif line1000: ; diff --git a/src/spicelib/devices/bsim2/b2node.c b/src/spicelib/devices/bsim2/b2node.c new file mode 100644 index 000000000..51be6f94c --- /dev/null +++ b/src/spicelib/devices/bsim2/b2node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim2def.h" +#include "ngspice/sperror.h" + +int +B2nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B2model *model = (B2model *)inModel ; + B2instance *here ; + + /* loop through all the BSIM2 models */ + for ( ; model != NULL ; model = model->B2nextModel) + { + /* loop through all the instances of the model */ + for (here = model->B2instances ; here != NULL ; here = here->B2nextInstance) + { + ckt->CKTnodeIsLinear [here->B2dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B2sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B2gNode] = 0 ; + ckt->CKTnodeIsLinear [here->B2bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim2/b2set.c b/src/spicelib/devices/bsim2/b2set.c index 9721885d7..3c9dec9a3 100644 --- a/src/spicelib/devices/bsim2/b2set.c +++ b/src/spicelib/devices/bsim2/b2set.c @@ -535,32 +535,32 @@ B2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(B2DdPtr, B2dNode, B2dNode) - TSTALLOC(B2GgPtr, B2gNode, B2gNode) - TSTALLOC(B2SsPtr, B2sNode, B2sNode) - TSTALLOC(B2BbPtr, B2bNode, B2bNode) - TSTALLOC(B2DPdpPtr, B2dNodePrime, B2dNodePrime) - TSTALLOC(B2SPspPtr, B2sNodePrime, B2sNodePrime) - TSTALLOC(B2DdpPtr, B2dNode, B2dNodePrime) - TSTALLOC(B2GbPtr, B2gNode, B2bNode) - TSTALLOC(B2GdpPtr, B2gNode, B2dNodePrime) - TSTALLOC(B2GspPtr, B2gNode, B2sNodePrime) - TSTALLOC(B2SspPtr, B2sNode, B2sNodePrime) - TSTALLOC(B2BdpPtr, B2bNode, B2dNodePrime) - TSTALLOC(B2BspPtr, B2bNode, B2sNodePrime) - TSTALLOC(B2DPspPtr, B2dNodePrime, B2sNodePrime) - TSTALLOC(B2DPdPtr, B2dNodePrime, B2dNode) - TSTALLOC(B2BgPtr, B2bNode, B2gNode) - TSTALLOC(B2DPgPtr, B2dNodePrime, B2gNode) - TSTALLOC(B2SPgPtr, B2sNodePrime, B2gNode) - TSTALLOC(B2SPsPtr, B2sNodePrime, B2sNode) - TSTALLOC(B2DPbPtr, B2dNodePrime, B2bNode) - TSTALLOC(B2SPbPtr, B2sNodePrime, B2bNode) - TSTALLOC(B2SPdpPtr, B2sNodePrime, B2dNodePrime) + TSTALLOC(B2DdPtr, B2dNode, B2dNode); + TSTALLOC(B2GgPtr, B2gNode, B2gNode); + TSTALLOC(B2SsPtr, B2sNode, B2sNode); + TSTALLOC(B2BbPtr, B2bNode, B2bNode); + TSTALLOC(B2DPdpPtr, B2dNodePrime, B2dNodePrime); + TSTALLOC(B2SPspPtr, B2sNodePrime, B2sNodePrime); + TSTALLOC(B2DdpPtr, B2dNode, B2dNodePrime); + TSTALLOC(B2GbPtr, B2gNode, B2bNode); + TSTALLOC(B2GdpPtr, B2gNode, B2dNodePrime); + TSTALLOC(B2GspPtr, B2gNode, B2sNodePrime); + TSTALLOC(B2SspPtr, B2sNode, B2sNodePrime); + TSTALLOC(B2BdpPtr, B2bNode, B2dNodePrime); + TSTALLOC(B2BspPtr, B2bNode, B2sNodePrime); + TSTALLOC(B2DPspPtr, B2dNodePrime, B2sNodePrime); + TSTALLOC(B2DPdPtr, B2dNodePrime, B2dNode); + TSTALLOC(B2BgPtr, B2bNode, B2gNode); + TSTALLOC(B2DPgPtr, B2dNodePrime, B2gNode); + TSTALLOC(B2SPgPtr, B2sNodePrime, B2gNode); + TSTALLOC(B2SPsPtr, B2sNodePrime, B2sNode); + TSTALLOC(B2DPbPtr, B2dNodePrime, B2bNode); + TSTALLOC(B2SPbPtr, B2sNodePrime, B2bNode); + TSTALLOC(B2SPdpPtr, B2sNodePrime, B2dNodePrime); } } diff --git a/src/spicelib/devices/bsim2/bsim2ext.h b/src/spicelib/devices/bsim2/bsim2ext.h index 00acb8d38..eaf549188 100644 --- a/src/spicelib/devices/bsim2/bsim2ext.h +++ b/src/spicelib/devices/bsim2/bsim2ext.h @@ -31,3 +31,7 @@ extern int B2bindCSC (GENmodel*, CKTcircuit*) ; extern int B2bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B2bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B2nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim2/bsim2init.c b/src/spicelib/devices/bsim2/bsim2init.c index 1468099c7..52dc84b3a 100644 --- a/src/spicelib/devices/bsim2/bsim2init.c +++ b/src/spicelib/devices/bsim2/bsim2init.c @@ -73,12 +73,17 @@ SPICEdev B2info = { #endif /* DEVinstSize */ &B2iSize, /* DEVmodSize */ &B2mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B2bindCSC, /* DEVbindCSCComplex */ B2bindCSCComplex, /* DEVbindCSCComplexToReal */ B2bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B2nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim3/Makefile.am b/src/spicelib/devices/bsim3/Makefile.am index b3c02d946..a437219f0 100644 --- a/src/spicelib/devices/bsim3/Makefile.am +++ b/src/spicelib/devices/bsim3/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3_la_SOURCES += b3bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3_la_SOURCES += b3node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3/b3.c b/src/spicelib/devices/bsim3/b3.c index e5d288a79..ac2dbd20f 100644 --- a/src/spicelib/devices/bsim3/b3.c +++ b/src/spicelib/devices/bsim3/b3.c @@ -26,44 +26,50 @@ IOP( "nrs", BSIM3_NRS, IF_REAL , "Number of squares in source"), IOP( "off", BSIM3_OFF, IF_FLAG , "Device is initially off"), IOP( "nqsmod", BSIM3_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"), IOP( "acnqsmod", BSIM3_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), +IOP( "geo", BSIM3_GEO, IF_INTEGER, "ACM model drain/source connection"), +IOP( "delvto", BSIM3_DELVTO, IF_REAL, "Zero bias threshold voltage variation"), +IOP( "mulu0", BSIM3_MULU0, IF_REAL, "Low field mobility multiplier"), IP( "ic", BSIM3_IC, IF_REALVEC , "Vector of DS,GS,BS initial voltages"), -OP( "gmbs", BSIM3_GMBS, IF_REAL, "Gmb"), -OP( "gm", BSIM3_GM, IF_REAL, "Gm"), -OP( "gds", BSIM3_GDS, IF_REAL, "Gds"), -OP( "vdsat", BSIM3_VDSAT, IF_REAL, "Vdsat"), -OP( "vth", BSIM3_VON, IF_REAL, "Vth"), -OP( "id", BSIM3_CD, IF_REAL, "Ids"), -OP( "vbs", BSIM3_VBS, IF_REAL, "Vbs"), -OP( "vgs", BSIM3_VGS, IF_REAL, "Vgs"), -OP( "vds", BSIM3_VDS, IF_REAL, "Vds"), -OP( "ibd", BSIM3_CBD, IF_REAL, "Ibd"), /* newly added from here */ -OP( "ibs", BSIM3_CBS, IF_REAL, "Ibs"), -OP( "gbd", BSIM3_GBD, IF_REAL, "gbd"), -OP( "gbs", BSIM3_GBS, IF_REAL, "gbs"), -OP( "qb", BSIM3_QB, IF_REAL, "Qbulk"), -OP( "cqb", BSIM3_CQB, IF_REAL, "CQbulk"), -OP( "qg", BSIM3_QG, IF_REAL, "Qgate"), -OP( "cqg", BSIM3_CQG, IF_REAL, "CQgate"), -OP( "qd", BSIM3_QD, IF_REAL, "Qdrain"), -OP( "cqd", BSIM3_CQD, IF_REAL, "CQdrain"), -OP( "cgg", BSIM3_CGG, IF_REAL, "Cggb"), -OP( "cgd", BSIM3_CGD, IF_REAL, "Cgdb"), -OP( "cgs", BSIM3_CGS, IF_REAL, "Cgsb"), -OP( "cdg", BSIM3_CDG, IF_REAL, "Cdgb"), -OP( "cdd", BSIM3_CDD, IF_REAL, "Cddb"), -OP( "cds", BSIM3_CDS, IF_REAL, "Cdsb"), -OP( "cbg", BSIM3_CBG, IF_REAL, "Cbgb"), -OP( "cbd", BSIM3_CBDB, IF_REAL, "Cbdb"), -OP( "cbs", BSIM3_CBSB, IF_REAL, "Cbsb"), -OP( "capbd", BSIM3_CAPBD, IF_REAL, "Capbd"), -OP( "capbs", BSIM3_CAPBS, IF_REAL, "Capbs"), +OP( "gmbs", BSIM3_GMBS, IF_REAL, "Gmb"), +OP( "gm", BSIM3_GM, IF_REAL, "Gm"), +OP( "gds", BSIM3_GDS, IF_REAL, "Gds"), +OP( "vdsat", BSIM3_VDSAT, IF_REAL, "Vdsat"), +OP( "vth", BSIM3_VON, IF_REAL, "Vth"), +OP( "id", BSIM3_CD, IF_REAL, "Ids"), +OP( "vbs", BSIM3_VBS, IF_REAL, "Vbs"), +OP( "vgs", BSIM3_VGS, IF_REAL, "Vgs"), +OP( "vds", BSIM3_VDS, IF_REAL, "Vds"), +OP( "ibd", BSIM3_CBD, IF_REAL, "Ibd"), /* newly added from here */ +OP( "ibs", BSIM3_CBS, IF_REAL, "Ibs"), +OP( "gbd", BSIM3_GBD, IF_REAL, "gbd"), +OP( "gbs", BSIM3_GBS, IF_REAL, "gbs"), +OP( "qb", BSIM3_QB, IF_REAL, "Qbulk"), +OP( "cqb", BSIM3_CQB, IF_REAL, "CQbulk"), +OP( "qg", BSIM3_QG, IF_REAL, "Qgate"), +OP( "cqg", BSIM3_CQG, IF_REAL, "CQgate"), +OP( "qd", BSIM3_QD, IF_REAL, "Qdrain"), +OP( "cqd", BSIM3_CQD, IF_REAL, "CQdrain"), +OP( "cgg", BSIM3_CGG, IF_REAL, "Cggb"), +OP( "cgd", BSIM3_CGD, IF_REAL, "Cgdb"), +OP( "cgs", BSIM3_CGS, IF_REAL, "Cgsb"), +OP( "cdg", BSIM3_CDG, IF_REAL, "Cdgb"), +OP( "cdd", BSIM3_CDD, IF_REAL, "Cddb"), +OP( "cds", BSIM3_CDS, IF_REAL, "Cdsb"), +OP( "cbg", BSIM3_CBG, IF_REAL, "Cbgb"), +OP( "cbd", BSIM3_CBDB, IF_REAL, "Cbdb"), +OP( "cbs", BSIM3_CBSB, IF_REAL, "Cbsb"), +OP( "capbd", BSIM3_CAPBD, IF_REAL, "Capbd"), +OP( "capbs", BSIM3_CAPBS, IF_REAL, "Capbs"), }; IFparm BSIM3mPTable[] = { /* model parameters */ IOP( "capmod", BSIM3_MOD_CAPMOD, IF_INTEGER, "Capacitance model selector"), IOP( "mobmod", BSIM3_MOD_MOBMOD, IF_INTEGER, "Mobility model selector"), IOP( "noimod", BSIM3_MOD_NOIMOD, IF_INTEGER, "Noise model selector"), +IOP( "nqsmod", BSIM3_MOD_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"), IOP( "acnqsmod", BSIM3_MOD_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), +IOP( "acm", BSIM3_MOD_ACMMOD, IF_INTEGER, "Area calculation method selector"), +IOP( "calcacm", BSIM3_MOD_CALCACM, IF_INTEGER, "Area calculation method ACM=12"), IOP( "paramchk", BSIM3_MOD_PARAMCHK, IF_INTEGER, "Model parameter checking selector"), IOP( "binunit", BSIM3_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"), IOP( "version", BSIM3_MOD_VERSION, IF_STRING, " parameter for model version"), @@ -71,15 +77,15 @@ IOP( "tox", BSIM3_MOD_TOX, IF_REAL, "Gate oxide thickness in meters"), IOP( "toxm", BSIM3_MOD_TOXM, IF_REAL, "Gate oxide thickness used in extraction"), IOP( "cdsc", BSIM3_MOD_CDSC, IF_REAL, "Drain/Source and channel coupling capacitance"), -IOP( "cdscb", BSIM3_MOD_CDSCB, IF_REAL, "Body-bias dependence of cdsc"), -IOP( "cdscd", BSIM3_MOD_CDSCD, IF_REAL, "Drain-bias dependence of cdsc"), +IOP( "cdscb", BSIM3_MOD_CDSCB, IF_REAL, "Body-bias dependence of cdsc"), +IOP( "cdscd", BSIM3_MOD_CDSCD, IF_REAL, "Drain-bias dependence of cdsc"), IOP( "cit", BSIM3_MOD_CIT, IF_REAL, "Interface state capacitance"), IOP( "nfactor", BSIM3_MOD_NFACTOR, IF_REAL, "Subthreshold swing Coefficient"), IOP( "xj", BSIM3_MOD_XJ, IF_REAL, "Junction depth in meters"), IOP( "vsat", BSIM3_MOD_VSAT, IF_REAL, "Saturation velocity at tnom"), IOP( "at", BSIM3_MOD_AT, IF_REAL, "Temperature coefficient of vsat"), -IOP( "a0", BSIM3_MOD_A0, IF_REAL, "Non-uniform depletion width effect coefficient."), -IOP( "ags", BSIM3_MOD_AGS, IF_REAL, "Gate bias coefficient of Abulk."), +IOP( "a0", BSIM3_MOD_A0, IF_REAL, "Non-uniform depletion width effect coefficient."), +IOP( "ags", BSIM3_MOD_AGS, IF_REAL, "Gate bias coefficient of Abulk."), IOP( "a1", BSIM3_MOD_A1, IF_REAL, "Non-saturation effect coefficient"), IOP( "a2", BSIM3_MOD_A2, IF_REAL, "Non-saturation effect coefficient"), IOP( "keta", BSIM3_MOD_KETA, IF_REAL, "Body-bias coefficient of non-uniform depletion width effect."), @@ -128,21 +134,21 @@ IOP( "xpart", BSIM3_MOD_XPART, IF_REAL, "Channel charge partitioning"), IOP( "elm", BSIM3_MOD_ELM, IF_REAL, "Non-quasi-static Elmore Constant Parameter"), IOP( "delta", BSIM3_MOD_DELTA, IF_REAL, "Effective Vds parameter"), IOP( "rsh", BSIM3_MOD_RSH, IF_REAL, "Source-drain sheet resistance"), -IOP( "rdsw", BSIM3_MOD_RDSW, IF_REAL, "Source-drain resistance per width"), +IOP( "rdsw", BSIM3_MOD_RDSW, IF_REAL, "Source-drain resistance per width"), -IOP( "prwg", BSIM3_MOD_PRWG, IF_REAL, "Gate-bias effect on parasitic resistance "), -IOP( "prwb", BSIM3_MOD_PRWB, IF_REAL, "Body-effect on parasitic resistance "), +IOP( "prwg", BSIM3_MOD_PRWG, IF_REAL, "Gate-bias effect on parasitic resistance "), +IOP( "prwb", BSIM3_MOD_PRWB, IF_REAL, "Body-effect on parasitic resistance "), -IOP( "prt", BSIM3_MOD_PRT, IF_REAL, "Temperature coefficient of parasitic resistance "), +IOP( "prt", BSIM3_MOD_PRT, IF_REAL, "Temperature coefficient of parasitic resistance "), IOP( "eta0", BSIM3_MOD_ETA0, IF_REAL, "Subthreshold region DIBL coefficient"), IOP( "etab", BSIM3_MOD_ETAB, IF_REAL, "Subthreshold region DIBL coefficient"), IOP( "pclm", BSIM3_MOD_PCLM, IF_REAL, "Channel length modulation Coefficient"), -IOP( "pdiblc1", BSIM3_MOD_PDIBL1, IF_REAL, "Drain-induced barrier lowering coefficient"), -IOP( "pdiblc2", BSIM3_MOD_PDIBL2, IF_REAL, "Drain-induced barrier lowering coefficient"), -IOP( "pdiblcb", BSIM3_MOD_PDIBLB, IF_REAL, "Body-effect on drain-induced barrier lowering"), -IOP( "pscbe1", BSIM3_MOD_PSCBE1, IF_REAL, "Substrate current body-effect coefficient"), -IOP( "pscbe2", BSIM3_MOD_PSCBE2, IF_REAL, "Substrate current body-effect coefficient"), -IOP( "pvag", BSIM3_MOD_PVAG, IF_REAL, "Gate dependence of output resistance parameter"), +IOP( "pdiblc1", BSIM3_MOD_PDIBL1, IF_REAL, "Drain-induced barrier lowering coefficient"), +IOP( "pdiblc2", BSIM3_MOD_PDIBL2, IF_REAL, "Drain-induced barrier lowering coefficient"), +IOP( "pdiblcb", BSIM3_MOD_PDIBLB, IF_REAL, "Body-effect on drain-induced barrier lowering"), +IOP( "pscbe1", BSIM3_MOD_PSCBE1, IF_REAL, "Substrate current body-effect coefficient"), +IOP( "pscbe2", BSIM3_MOD_PSCBE2, IF_REAL, "Substrate current body-effect coefficient"), +IOP( "pvag", BSIM3_MOD_PVAG, IF_REAL, "Gate dependence of output resistance parameter"), IOP( "js", BSIM3_MOD_JS, IF_REAL, "Source/drain junction reverse saturation current density"), IOP( "jsw", BSIM3_MOD_JSW, IF_REAL, "Sidewall junction reverse saturation current density"), IOP( "pb", BSIM3_MOD_PB, IF_REAL, "Source/drain junction built-in potential"), @@ -180,6 +186,10 @@ IOP( "lwl", BSIM3_MOD_LWL, IF_REAL, "Length reduction parameter"), IOP( "lwlc", BSIM3_MOD_LWLC, IF_REAL, "Length reduction parameter for CV"), IOP( "lmin", BSIM3_MOD_LMIN, IF_REAL, "Minimum length for the model"), IOP( "lmax", BSIM3_MOD_LMAX, IF_REAL, "Maximum length for the model"), + +IOP( "xl", BSIM3_MOD_XL, IF_REAL, "Length correction parameter"), +IOP( "xw", BSIM3_MOD_XW, IF_REAL, "Width correction parameter"), + IOP( "wr", BSIM3_MOD_WR, IF_REAL, "Width dependence of rds"), IOP( "wint", BSIM3_MOD_WINT, IF_REAL, "Width reduction parameter"), IOP( "dwg", BSIM3_MOD_DWG, IF_REAL, "Width reduction parameter"), @@ -208,6 +218,15 @@ IOP( "cle", BSIM3_MOD_CLE, IF_REAL, "Vdsat parameter for C-V model"), IOP( "dwc", BSIM3_MOD_DWC, IF_REAL, "Delta W for C-V model"), IOP( "dlc", BSIM3_MOD_DLC, IF_REAL, "Delta L for C-V model"), +IOP( "hdif", BSIM3_MOD_HDIF, IF_REAL, "ACM Parameter: Distance Gate - contact"), +IOP( "ldif", BSIM3_MOD_LDIF, IF_REAL, "ACM Parameter: Length of LDD Gate-Source/Drain"), +IOP( "ld", BSIM3_MOD_LD, IF_REAL, "ACM Parameter: Length of LDD under Gate"), +IOP( "rd", BSIM3_MOD_RD, IF_REAL, "ACM Parameter: Resistance of LDD drain side"), +IOP( "rs", BSIM3_MOD_RS, IF_REAL, "ACM Parameter: Resistance of LDD source side"), +IOP( "rdc", BSIM3_MOD_RDC, IF_REAL, "ACM Parameter: Resistance contact drain side"), +IOP( "rsc", BSIM3_MOD_RSC, IF_REAL, "ACM Parameter: Resistance contact source side"), +IOP( "wmlt", BSIM3_MOD_WMLT, IF_REAL, "ACM Parameter: Width shrink factor"), + IOP( "alpha0", BSIM3_MOD_ALPHA0, IF_REAL, "substrate current model parameter"), IOP( "alpha1", BSIM3_MOD_ALPHA1, IF_REAL, "substrate current model parameter"), IOP( "beta0", BSIM3_MOD_BETA0, IF_REAL, "substrate current model parameter"), @@ -221,8 +240,8 @@ IOP( "lnfactor", BSIM3_MOD_LNFACTOR, IF_REAL, "Length dependence of nfactor"), IOP( "lxj", BSIM3_MOD_LXJ, IF_REAL, "Length dependence of xj"), IOP( "lvsat", BSIM3_MOD_LVSAT, IF_REAL, "Length dependence of vsat"), IOP( "lat", BSIM3_MOD_LAT, IF_REAL, "Length dependence of at"), -IOP( "la0", BSIM3_MOD_LA0, IF_REAL, "Length dependence of a0"), -IOP( "lags", BSIM3_MOD_LAGS, IF_REAL, "Length dependence of ags"), +IOP( "la0", BSIM3_MOD_LA0, IF_REAL, "Length dependence of a0"), +IOP( "lags", BSIM3_MOD_LAGS, IF_REAL, "Length dependence of ags"), IOP( "la1", BSIM3_MOD_LA1, IF_REAL, "Length dependence of a1"), IOP( "la2", BSIM3_MOD_LA2, IF_REAL, "Length dependence of a2"), IOP( "lketa", BSIM3_MOD_LKETA, IF_REAL, "Length dependence of keta"), @@ -264,21 +283,21 @@ IOP( "lute", BSIM3_MOD_LUTE, IF_REAL, "Length dependence of ute"), IOP( "lvoff", BSIM3_MOD_LVOFF, IF_REAL, "Length dependence of voff"), IOP( "lelm", BSIM3_MOD_LELM, IF_REAL, "Length dependence of elm"), IOP( "ldelta", BSIM3_MOD_LDELTA, IF_REAL, "Length dependence of delta"), -IOP( "lrdsw", BSIM3_MOD_LRDSW, IF_REAL, "Length dependence of rdsw "), +IOP( "lrdsw", BSIM3_MOD_LRDSW, IF_REAL, "Length dependence of rdsw "), -IOP( "lprwg", BSIM3_MOD_LPRWG, IF_REAL, "Length dependence of prwg "), -IOP( "lprwb", BSIM3_MOD_LPRWB, IF_REAL, "Length dependence of prwb "), +IOP( "lprwg", BSIM3_MOD_LPRWG, IF_REAL, "Length dependence of prwg "), +IOP( "lprwb", BSIM3_MOD_LPRWB, IF_REAL, "Length dependence of prwb "), -IOP( "lprt", BSIM3_MOD_LPRT, IF_REAL, "Length dependence of prt "), -IOP( "leta0", BSIM3_MOD_LETA0, IF_REAL, "Length dependence of eta0"), -IOP( "letab", BSIM3_MOD_LETAB, IF_REAL, "Length dependence of etab"), -IOP( "lpclm", BSIM3_MOD_LPCLM, IF_REAL, "Length dependence of pclm"), -IOP( "lpdiblc1", BSIM3_MOD_LPDIBL1, IF_REAL, "Length dependence of pdiblc1"), -IOP( "lpdiblc2", BSIM3_MOD_LPDIBL2, IF_REAL, "Length dependence of pdiblc2"), -IOP( "lpdiblcb", BSIM3_MOD_LPDIBLB, IF_REAL, "Length dependence of pdiblcb"), -IOP( "lpscbe1", BSIM3_MOD_LPSCBE1, IF_REAL, "Length dependence of pscbe1"), -IOP( "lpscbe2", BSIM3_MOD_LPSCBE2, IF_REAL, "Length dependence of pscbe2"), -IOP( "lpvag", BSIM3_MOD_LPVAG, IF_REAL, "Length dependence of pvag"), +IOP( "lprt", BSIM3_MOD_LPRT, IF_REAL, "Length dependence of prt "), +IOP( "leta0", BSIM3_MOD_LETA0, IF_REAL, "Length dependence of eta0"), +IOP( "letab", BSIM3_MOD_LETAB, IF_REAL, "Length dependence of etab"), +IOP( "lpclm", BSIM3_MOD_LPCLM, IF_REAL, "Length dependence of pclm"), +IOP( "lpdiblc1", BSIM3_MOD_LPDIBL1, IF_REAL, "Length dependence of pdiblc1"), +IOP( "lpdiblc2", BSIM3_MOD_LPDIBL2, IF_REAL, "Length dependence of pdiblc2"), +IOP( "lpdiblcb", BSIM3_MOD_LPDIBLB, IF_REAL, "Length dependence of pdiblcb"), +IOP( "lpscbe1", BSIM3_MOD_LPSCBE1, IF_REAL, "Length dependence of pscbe1"), +IOP( "lpscbe2", BSIM3_MOD_LPSCBE2, IF_REAL, "Length dependence of pscbe2"), +IOP( "lpvag", BSIM3_MOD_LPVAG, IF_REAL, "Length dependence of pvag"), IOP( "lwr", BSIM3_MOD_LWR, IF_REAL, "Length dependence of wr"), IOP( "ldwg", BSIM3_MOD_LDWG, IF_REAL, "Length dependence of dwg"), IOP( "ldwb", BSIM3_MOD_LDWB, IF_REAL, "Length dependence of dwb"), @@ -300,15 +319,15 @@ IOP( "lmoin", BSIM3_MOD_LMOIN, IF_REAL, "Length dependence of moin"), IOP( "lnoff", BSIM3_MOD_LNOFF, IF_REAL, "Length dependence of noff"), IOP( "lvoffcv", BSIM3_MOD_LVOFFCV, IF_REAL, "Length dependence of voffcv"), IOP( "wcdsc", BSIM3_MOD_WCDSC, IF_REAL, "Width dependence of cdsc"), -IOP( "wcdscb", BSIM3_MOD_WCDSCB, IF_REAL, "Width dependence of cdscb"), -IOP( "wcdscd", BSIM3_MOD_WCDSCD, IF_REAL, "Width dependence of cdscd"), +IOP( "wcdscb", BSIM3_MOD_WCDSCB, IF_REAL, "Width dependence of cdscb"), +IOP( "wcdscd", BSIM3_MOD_WCDSCD, IF_REAL, "Width dependence of cdscd"), IOP( "wcit", BSIM3_MOD_WCIT, IF_REAL, "Width dependence of cit"), IOP( "wnfactor", BSIM3_MOD_WNFACTOR, IF_REAL, "Width dependence of nfactor"), IOP( "wxj", BSIM3_MOD_WXJ, IF_REAL, "Width dependence of xj"), IOP( "wvsat", BSIM3_MOD_WVSAT, IF_REAL, "Width dependence of vsat"), IOP( "wat", BSIM3_MOD_WAT, IF_REAL, "Width dependence of at"), -IOP( "wa0", BSIM3_MOD_WA0, IF_REAL, "Width dependence of a0"), -IOP( "wags", BSIM3_MOD_WAGS, IF_REAL, "Width dependence of ags"), +IOP( "wa0", BSIM3_MOD_WA0, IF_REAL, "Width dependence of a0"), +IOP( "wags", BSIM3_MOD_WAGS, IF_REAL, "Width dependence of ags"), IOP( "wa1", BSIM3_MOD_WA1, IF_REAL, "Width dependence of a1"), IOP( "wa2", BSIM3_MOD_WA2, IF_REAL, "Width dependence of a2"), IOP( "wketa", BSIM3_MOD_WKETA, IF_REAL, "Width dependence of keta"), @@ -356,15 +375,15 @@ IOP( "wprwg", BSIM3_MOD_WPRWG, IF_REAL, "Width dependence of prwg "), IOP( "wprwb", BSIM3_MOD_WPRWB, IF_REAL, "Width dependence of prwb "), IOP( "wprt", BSIM3_MOD_WPRT, IF_REAL, "Width dependence of prt"), -IOP( "weta0", BSIM3_MOD_WETA0, IF_REAL, "Width dependence of eta0"), -IOP( "wetab", BSIM3_MOD_WETAB, IF_REAL, "Width dependence of etab"), -IOP( "wpclm", BSIM3_MOD_WPCLM, IF_REAL, "Width dependence of pclm"), -IOP( "wpdiblc1", BSIM3_MOD_WPDIBL1, IF_REAL, "Width dependence of pdiblc1"), -IOP( "wpdiblc2", BSIM3_MOD_WPDIBL2, IF_REAL, "Width dependence of pdiblc2"), -IOP( "wpdiblcb", BSIM3_MOD_WPDIBLB, IF_REAL, "Width dependence of pdiblcb"), -IOP( "wpscbe1", BSIM3_MOD_WPSCBE1, IF_REAL, "Width dependence of pscbe1"), -IOP( "wpscbe2", BSIM3_MOD_WPSCBE2, IF_REAL, "Width dependence of pscbe2"), -IOP( "wpvag", BSIM3_MOD_WPVAG, IF_REAL, "Width dependence of pvag"), +IOP( "weta0", BSIM3_MOD_WETA0, IF_REAL, "Width dependence of eta0"), +IOP( "wetab", BSIM3_MOD_WETAB, IF_REAL, "Width dependence of etab"), +IOP( "wpclm", BSIM3_MOD_WPCLM, IF_REAL, "Width dependence of pclm"), +IOP( "wpdiblc1", BSIM3_MOD_WPDIBL1, IF_REAL, "Width dependence of pdiblc1"), +IOP( "wpdiblc2", BSIM3_MOD_WPDIBL2, IF_REAL, "Width dependence of pdiblc2"), +IOP( "wpdiblcb", BSIM3_MOD_WPDIBLB, IF_REAL, "Width dependence of pdiblcb"), +IOP( "wpscbe1", BSIM3_MOD_WPSCBE1, IF_REAL, "Width dependence of pscbe1"), +IOP( "wpscbe2", BSIM3_MOD_WPSCBE2, IF_REAL, "Width dependence of pscbe2"), +IOP( "wpvag", BSIM3_MOD_WPVAG, IF_REAL, "Width dependence of pvag"), IOP( "wwr", BSIM3_MOD_WWR, IF_REAL, "Width dependence of wr"), IOP( "wdwg", BSIM3_MOD_WDWG, IF_REAL, "Width dependence of dwg"), IOP( "wdwb", BSIM3_MOD_WDWB, IF_REAL, "Width dependence of dwb"), @@ -387,14 +406,14 @@ IOP( "wnoff", BSIM3_MOD_WNOFF, IF_REAL, "Width dependence of noff"), IOP( "wvoffcv", BSIM3_MOD_WVOFFCV, IF_REAL, "Width dependence of voffcv"), IOP( "pcdsc", BSIM3_MOD_PCDSC, IF_REAL, "Cross-term dependence of cdsc"), -IOP( "pcdscb", BSIM3_MOD_PCDSCB, IF_REAL, "Cross-term dependence of cdscb"), +IOP( "pcdscb", BSIM3_MOD_PCDSCB, IF_REAL, "Cross-term dependence of cdscb"), IOP( "pcdscd", BSIM3_MOD_PCDSCD, IF_REAL, "Cross-term dependence of cdscd"), IOP( "pcit", BSIM3_MOD_PCIT, IF_REAL, "Cross-term dependence of cit"), IOP( "pnfactor", BSIM3_MOD_PNFACTOR, IF_REAL, "Cross-term dependence of nfactor"), IOP( "pxj", BSIM3_MOD_PXJ, IF_REAL, "Cross-term dependence of xj"), IOP( "pvsat", BSIM3_MOD_PVSAT, IF_REAL, "Cross-term dependence of vsat"), IOP( "pat", BSIM3_MOD_PAT, IF_REAL, "Cross-term dependence of at"), -IOP( "pa0", BSIM3_MOD_PA0, IF_REAL, "Cross-term dependence of a0"), +IOP( "pa0", BSIM3_MOD_PA0, IF_REAL, "Cross-term dependence of a0"), IOP( "pags", BSIM3_MOD_PAGS, IF_REAL, "Cross-term dependence of ags"), IOP( "pa1", BSIM3_MOD_PA1, IF_REAL, "Cross-term dependence of a1"), IOP( "pa2", BSIM3_MOD_PA2, IF_REAL, "Cross-term dependence of a2"), @@ -437,10 +456,10 @@ IOP( "pute", BSIM3_MOD_PUTE, IF_REAL, "Cross-term dependence of ute"), IOP( "pvoff", BSIM3_MOD_PVOFF, IF_REAL, "Cross-term dependence of voff"), IOP( "pelm", BSIM3_MOD_PELM, IF_REAL, "Cross-term dependence of elm"), IOP( "pdelta", BSIM3_MOD_PDELTA, IF_REAL, "Cross-term dependence of delta"), -IOP( "prdsw", BSIM3_MOD_PRDSW, IF_REAL, "Cross-term dependence of rdsw "), +IOP( "prdsw", BSIM3_MOD_PRDSW, IF_REAL, "Cross-term dependence of rdsw "), -IOP( "pprwg", BSIM3_MOD_PPRWG, IF_REAL, "Cross-term dependence of prwg "), -IOP( "pprwb", BSIM3_MOD_PPRWB, IF_REAL, "Cross-term dependence of prwb "), +IOP( "pprwg", BSIM3_MOD_PPRWG, IF_REAL, "Cross-term dependence of prwg "), +IOP( "pprwb", BSIM3_MOD_PPRWB, IF_REAL, "Cross-term dependence of prwb "), IOP( "pprt", BSIM3_MOD_PPRT, IF_REAL, "Cross-term dependence of prt "), IOP( "peta0", BSIM3_MOD_PETA0, IF_REAL, "Cross-term dependence of eta0"), @@ -451,7 +470,7 @@ IOP( "ppdiblc2", BSIM3_MOD_PPDIBL2, IF_REAL, "Cross-term dependence of pdiblc2") IOP( "ppdiblcb", BSIM3_MOD_PPDIBLB, IF_REAL, "Cross-term dependence of pdiblcb"), IOP( "ppscbe1", BSIM3_MOD_PPSCBE1, IF_REAL, "Cross-term dependence of pscbe1"), IOP( "ppscbe2", BSIM3_MOD_PPSCBE2, IF_REAL, "Cross-term dependence of pscbe2"), -IOP( "ppvag", BSIM3_MOD_PPVAG, IF_REAL, "Cross-term dependence of pvag"), +IOP( "ppvag", BSIM3_MOD_PPVAG, IF_REAL, "Cross-term dependence of pvag"), IOP( "pwr", BSIM3_MOD_PWR, IF_REAL, "Cross-term dependence of wr"), IOP( "pdwg", BSIM3_MOD_PDWG, IF_REAL, "Cross-term dependence of dwg"), IOP( "pdwb", BSIM3_MOD_PDWB, IF_REAL, "Cross-term dependence of dwb"), @@ -493,11 +512,11 @@ char *BSIM3names[] = { "Charge" }; -int BSIM3nSize = NUMELEMS(BSIM3names); -int BSIM3pTSize = NUMELEMS(BSIM3pTable); -int BSIM3mPTSize = NUMELEMS(BSIM3mPTable); -int BSIM3iSize = sizeof(BSIM3instance); -int BSIM3mSize = sizeof(BSIM3model); +int BSIM3nSize = NUMELEMS(BSIM3names); +int BSIM3pTSize = NUMELEMS(BSIM3pTable); +int BSIM3mPTSize = NUMELEMS(BSIM3mPTable); +int BSIM3iSize = sizeof(BSIM3instance); +int BSIM3mSize = sizeof(BSIM3model); diff --git a/src/spicelib/devices/bsim3/b3ask.c b/src/spicelib/devices/bsim3/b3ask.c index 5ff21ecf2..21c1775b6 100644 --- a/src/spicelib/devices/bsim3/b3ask.c +++ b/src/spicelib/devices/bsim3/b3ask.c @@ -28,7 +28,7 @@ BSIM3instance *here = (BSIM3instance*)inst; NG_IGNORE(select); - switch(which) + switch(which) { case BSIM3_L: value->rValue = here->BSIM3l; return(OK); @@ -65,6 +65,15 @@ BSIM3instance *here = (BSIM3instance*)inst; case BSIM3_ACNQSMOD: value->iValue = here->BSIM3acnqsMod; return(OK); + case BSIM3_GEO: + value->iValue = here->BSIM3geo; + return(OK); + case BSIM3_DELVTO: + value->rValue = here->BSIM3delvto; + return(OK); + case BSIM3_MULU0: + value->rValue = here->BSIM3mulu0; + return(OK); case BSIM3_IC_VBS: value->rValue = here->BSIM3icVBS; return(OK); @@ -94,11 +103,11 @@ BSIM3instance *here = (BSIM3instance*)inst; return(OK); case BSIM3_SOURCECONDUCT: value->rValue = here->BSIM3sourceConductance; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_DRAINCONDUCT: value->rValue = here->BSIM3drainConductance; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_VBD: value->rValue = *(ckt->CKTstate0 + here->BSIM3vbd); @@ -113,118 +122,118 @@ BSIM3instance *here = (BSIM3instance*)inst; value->rValue = *(ckt->CKTstate0 + here->BSIM3vds); return(OK); case BSIM3_CD: - value->rValue = here->BSIM3cd; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBS: - value->rValue = here->BSIM3cbs; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBD: - value->rValue = here->BSIM3cbd; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GM: - value->rValue = here->BSIM3gm; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3gm; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GDS: - value->rValue = here->BSIM3gds; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3gds; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GMBS: - value->rValue = here->BSIM3gmbs; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3gmbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GBD: - value->rValue = here->BSIM3gbd; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3gbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_GBS: - value->rValue = here->BSIM3gbs; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3gbs; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QB: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qb); - value->rValue *= here->BSIM3m; + 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; + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqb); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qg); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3qg); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CQG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3cqg); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqg); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qd); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3qd); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CQD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3cqd); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqd); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGG: - value->rValue = here->BSIM3cggb; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cggb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGD: value->rValue = here->BSIM3cgdb; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CGS: value->rValue = here->BSIM3cgsb; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDG: - value->rValue = here->BSIM3cdgb; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cdgb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDD: - value->rValue = here->BSIM3cddb; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cddb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CDS: - value->rValue = here->BSIM3cdsb; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3cdsb; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBG: value->rValue = here->BSIM3cbgb; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBDB: value->rValue = here->BSIM3cbdb; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CBSB: value->rValue = here->BSIM3cbsb; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CAPBD: - value->rValue = here->BSIM3capbd; - value->rValue *= here->BSIM3m; + value->rValue = here->BSIM3capbd; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_CAPBS: value->rValue = here->BSIM3capbs; - value->rValue *= here->BSIM3m; + value->rValue *= here->BSIM3m; return(OK); case BSIM3_VON: - value->rValue = here->BSIM3von; + value->rValue = here->BSIM3von; return(OK); case BSIM3_VDSAT: - value->rValue = here->BSIM3vdsat; + value->rValue = here->BSIM3vdsat; return(OK); case BSIM3_QBS: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qbs); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3qbs); + value->rValue *= here->BSIM3m; return(OK); case BSIM3_QBD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3qbd); - value->rValue *= here->BSIM3m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3qbd); + value->rValue *= here->BSIM3m; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/bsim3/b3check.c b/src/spicelib/devices/bsim3/b3check.c index 1951cdf95..2ec2aad54 100644 --- a/src/spicelib/devices/bsim3/b3check.c +++ b/src/spicelib/devices/bsim3/b3check.c @@ -31,29 +31,29 @@ FILE *fplog; NG_IGNORE(ckt); - if ((fplog = fopen("b3v3check.log", "w")) != NULL) + if ((fplog = fopen("b3v33check.log", "w")) != NULL) { pParam = here->pParam; fprintf(fplog, "BSIM3v3.3.0 Parameter Checking.\n"); - if ((strcmp(model->BSIM3version, "3.3.0")) && (strcmp(model->BSIM3version, "3.30")) && (strcmp(model->BSIM3version, "3.3"))) + if ((strncmp(model->BSIM3version, "3.3.0", 5)) && (strncmp(model->BSIM3version, "3.30", 4)) && (strncmp(model->BSIM3version, "3.3", 3))) { fprintf(fplog, "Warning: This model is BSIM3v3.3.0; you specified a wrong version number.\n"); printf("Warning: This model is BSIM3v3.3.0; you specified a wrong version number.\n"); } fprintf(fplog, "Model = %s\n", model->BSIM3modName); if (pParam->BSIM3nlx < -pParam->BSIM3leff) - { fprintf(fplog, "Fatal: Nlx = %g is less than -Leff.\n", - pParam->BSIM3nlx); - printf("Fatal: Nlx = %g is less than -Leff.\n", - pParam->BSIM3nlx); - Fatal_Flag = 1; + { fprintf(fplog, "Fatal: Nlx = %g is less than -Leff.\n", + pParam->BSIM3nlx); + printf("Fatal: Nlx = %g is less than -Leff.\n", + pParam->BSIM3nlx); + Fatal_Flag = 1; } - if (model->BSIM3tox <= 0.0) - { fprintf(fplog, "Fatal: Tox = %g is not positive.\n", - model->BSIM3tox); - printf("Fatal: Tox = %g is not positive.\n", model->BSIM3tox); - Fatal_Flag = 1; - } + if (model->BSIM3tox <= 0.0) + { fprintf(fplog, "Fatal: Tox = %g is not positive.\n", + model->BSIM3tox); + printf("Fatal: Tox = %g is not positive.\n", model->BSIM3tox); + Fatal_Flag = 1; + } if (model->BSIM3toxm <= 0.0) { fprintf(fplog, "Fatal: Toxm = %g is not positive.\n", @@ -70,104 +70,104 @@ FILE *fplog; Fatal_Flag = 1; } - if (pParam->BSIM3npeak <= 0.0) - { fprintf(fplog, "Fatal: Nch = %g is not positive.\n", - pParam->BSIM3npeak); - printf("Fatal: Nch = %g is not positive.\n", - pParam->BSIM3npeak); - Fatal_Flag = 1; - } - if (pParam->BSIM3nsub <= 0.0) - { fprintf(fplog, "Fatal: Nsub = %g is not positive.\n", - pParam->BSIM3nsub); - printf("Fatal: Nsub = %g is not positive.\n", - pParam->BSIM3nsub); - Fatal_Flag = 1; - } - if (pParam->BSIM3ngate < 0.0) - { fprintf(fplog, "Fatal: Ngate = %g is not positive.\n", - pParam->BSIM3ngate); - printf("Fatal: Ngate = %g Ngate is not positive.\n", - pParam->BSIM3ngate); - Fatal_Flag = 1; - } - if (pParam->BSIM3ngate > 1.e25) - { fprintf(fplog, "Fatal: Ngate = %g is too high.\n", - pParam->BSIM3ngate); - printf("Fatal: Ngate = %g Ngate is too high\n", - pParam->BSIM3ngate); - Fatal_Flag = 1; - } - if (pParam->BSIM3xj <= 0.0) - { fprintf(fplog, "Fatal: Xj = %g is not positive.\n", - pParam->BSIM3xj); - printf("Fatal: Xj = %g is not positive.\n", pParam->BSIM3xj); - Fatal_Flag = 1; - } + if (pParam->BSIM3npeak <= 0.0) + { fprintf(fplog, "Fatal: Nch = %g is not positive.\n", + pParam->BSIM3npeak); + printf("Fatal: Nch = %g is not positive.\n", + pParam->BSIM3npeak); + Fatal_Flag = 1; + } + if (pParam->BSIM3nsub <= 0.0) + { fprintf(fplog, "Fatal: Nsub = %g is not positive.\n", + pParam->BSIM3nsub); + printf("Fatal: Nsub = %g is not positive.\n", + pParam->BSIM3nsub); + Fatal_Flag = 1; + } + if (pParam->BSIM3ngate < 0.0) + { fprintf(fplog, "Fatal: Ngate = %g is not positive.\n", + pParam->BSIM3ngate); + printf("Fatal: Ngate = %g Ngate is not positive.\n", + pParam->BSIM3ngate); + Fatal_Flag = 1; + } + if (pParam->BSIM3ngate > 1.e25) + { fprintf(fplog, "Fatal: Ngate = %g is too high.\n", + pParam->BSIM3ngate); + printf("Fatal: Ngate = %g Ngate is too high\n", + pParam->BSIM3ngate); + Fatal_Flag = 1; + } + if (pParam->BSIM3xj <= 0.0) + { fprintf(fplog, "Fatal: Xj = %g is not positive.\n", + pParam->BSIM3xj); + printf("Fatal: Xj = %g is not positive.\n", pParam->BSIM3xj); + Fatal_Flag = 1; + } - if (pParam->BSIM3dvt1 < 0.0) - { fprintf(fplog, "Fatal: Dvt1 = %g is negative.\n", - pParam->BSIM3dvt1); - printf("Fatal: Dvt1 = %g is negative.\n", pParam->BSIM3dvt1); - Fatal_Flag = 1; - } - - if (pParam->BSIM3dvt1w < 0.0) - { fprintf(fplog, "Fatal: Dvt1w = %g is negative.\n", - pParam->BSIM3dvt1w); - printf("Fatal: Dvt1w = %g is negative.\n", pParam->BSIM3dvt1w); - Fatal_Flag = 1; - } - - if (pParam->BSIM3w0 == -pParam->BSIM3weff) - { fprintf(fplog, "Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); - printf("Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); - Fatal_Flag = 1; + if (pParam->BSIM3dvt1 < 0.0) + { fprintf(fplog, "Fatal: Dvt1 = %g is negative.\n", + pParam->BSIM3dvt1); + printf("Fatal: Dvt1 = %g is negative.\n", pParam->BSIM3dvt1); + Fatal_Flag = 1; + } + + if (pParam->BSIM3dvt1w < 0.0) + { fprintf(fplog, "Fatal: Dvt1w = %g is negative.\n", + pParam->BSIM3dvt1w); + printf("Fatal: Dvt1w = %g is negative.\n", pParam->BSIM3dvt1w); + Fatal_Flag = 1; + } + + if (pParam->BSIM3w0 == -pParam->BSIM3weff) + { fprintf(fplog, "Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); + printf("Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); + Fatal_Flag = 1; } - if (pParam->BSIM3dsub < 0.0) - { fprintf(fplog, "Fatal: Dsub = %g is negative.\n", pParam->BSIM3dsub); - printf("Fatal: Dsub = %g is negative.\n", pParam->BSIM3dsub); - Fatal_Flag = 1; - } - if (pParam->BSIM3b1 == -pParam->BSIM3weff) - { fprintf(fplog, "Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); - printf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); - Fatal_Flag = 1; + if (pParam->BSIM3dsub < 0.0) + { fprintf(fplog, "Fatal: Dsub = %g is negative.\n", pParam->BSIM3dsub); + printf("Fatal: Dsub = %g is negative.\n", pParam->BSIM3dsub); + Fatal_Flag = 1; + } + if (pParam->BSIM3b1 == -pParam->BSIM3weff) + { fprintf(fplog, "Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); + printf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); + Fatal_Flag = 1; } if (pParam->BSIM3u0temp <= 0.0) - { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", pParam->BSIM3u0temp); - printf("Fatal: u0 at current temperature = %g is not positive.\n", - pParam->BSIM3u0temp); - Fatal_Flag = 1; + { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", pParam->BSIM3u0temp); + printf("Fatal: u0 at current temperature = %g is not positive.\n", + pParam->BSIM3u0temp); + Fatal_Flag = 1; } /* Check delta parameter */ if (pParam->BSIM3delta < 0.0) - { fprintf(fplog, "Fatal: Delta = %g is less than zero.\n", - pParam->BSIM3delta); - printf("Fatal: Delta = %g is less than zero.\n", pParam->BSIM3delta); - Fatal_Flag = 1; + { fprintf(fplog, "Fatal: Delta = %g is less than zero.\n", + pParam->BSIM3delta); + printf("Fatal: Delta = %g is less than zero.\n", pParam->BSIM3delta); + Fatal_Flag = 1; } - if (pParam->BSIM3vsattemp <= 0.0) - { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", pParam->BSIM3vsattemp); - printf("Fatal: Vsat at current temperature = %g is not positive.\n", - pParam->BSIM3vsattemp); - Fatal_Flag = 1; - } + if (pParam->BSIM3vsattemp <= 0.0) + { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", pParam->BSIM3vsattemp); + printf("Fatal: Vsat at current temperature = %g is not positive.\n", + pParam->BSIM3vsattemp); + Fatal_Flag = 1; + } /* Check Rout parameters */ - if (pParam->BSIM3pclm <= 0.0) - { fprintf(fplog, "Fatal: Pclm = %g is not positive.\n", pParam->BSIM3pclm); - printf("Fatal: Pclm = %g is not positive.\n", pParam->BSIM3pclm); - Fatal_Flag = 1; - } + if (pParam->BSIM3pclm <= 0.0) + { fprintf(fplog, "Fatal: Pclm = %g is not positive.\n", pParam->BSIM3pclm); + printf("Fatal: Pclm = %g is not positive.\n", pParam->BSIM3pclm); + Fatal_Flag = 1; + } - if (pParam->BSIM3drout < 0.0) - { fprintf(fplog, "Fatal: Drout = %g is negative.\n", pParam->BSIM3drout); - printf("Fatal: Drout = %g is negative.\n", pParam->BSIM3drout); - Fatal_Flag = 1; - } + if (pParam->BSIM3drout < 0.0) + { fprintf(fplog, "Fatal: Drout = %g is negative.\n", pParam->BSIM3drout); + printf("Fatal: Drout = %g is negative.\n", pParam->BSIM3drout); + Fatal_Flag = 1; + } if (pParam->BSIM3pscbe2 <= 0.0) { fprintf(fplog, "Warning: Pscbe2 = %g is not positive.\n", @@ -175,22 +175,31 @@ FILE *fplog; printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3pscbe2); } - if (model->BSIM3unitLengthSidewallJctCap > 0.0 || - model->BSIM3unitLengthGateSidewallJctCap > 0.0) - { - if (here->BSIM3drainPerimeter < pParam->BSIM3weff) - { fprintf(fplog, "Warning: Pd = %g is less than W.\n", - here->BSIM3drainPerimeter); - printf("Warning: Pd = %g is less than W.\n", - here->BSIM3drainPerimeter); - } - if (here->BSIM3sourcePerimeter < pParam->BSIM3weff) - { fprintf(fplog, "Warning: Ps = %g is less than W.\n", - here->BSIM3sourcePerimeter); - printf("Warning: Ps = %g is less than W.\n", - here->BSIM3sourcePerimeter); - } - } + /* ACM model */ + if (model->BSIM3acmMod == 0) { + if (model->BSIM3unitLengthSidewallJctCap > 0.0 || + model->BSIM3unitLengthGateSidewallJctCap > 0.0) + { + if (here->BSIM3drainPerimeter < pParam->BSIM3weff) + { fprintf(fplog, "Warning: Pd = %g is less than W.\n", + here->BSIM3drainPerimeter); + printf("Warning: Pd = %g is less than W.\n", + here->BSIM3drainPerimeter); + } + if (here->BSIM3sourcePerimeter < pParam->BSIM3weff) + { fprintf(fplog, "Warning: Ps = %g is less than W.\n", + here->BSIM3sourcePerimeter); + printf("Warning: Ps = %g is less than W.\n", + here->BSIM3sourcePerimeter); + } + } + } + if ((model->BSIM3calcacm > 0) && (model->BSIM3acmMod != 12)) + { fprintf(fplog, "Warning: CALCACM = %d is wrong. Set back to 0.\n", + model->BSIM3calcacm); + printf("Warning: CALCACM = %d is wrong. Set back to 0.\n", model->BSIM3calcacm); + model->BSIM3calcacm = 0; + } if (pParam->BSIM3noff < 0.1) { fprintf(fplog, "Warning: Noff = %g is too small.\n", @@ -223,9 +232,9 @@ FILE *fplog; /* Check capacitance parameters */ if (pParam->BSIM3clc < 0.0) - { fprintf(fplog, "Fatal: Clc = %g is negative.\n", pParam->BSIM3clc); - printf("Fatal: Clc = %g is negative.\n", pParam->BSIM3clc); - Fatal_Flag = 1; + { fprintf(fplog, "Fatal: Clc = %g is negative.\n", pParam->BSIM3clc); + printf("Fatal: Clc = %g is negative.\n", pParam->BSIM3clc); + Fatal_Flag = 1; } if (pParam->BSIM3moin < 5.0) @@ -239,160 +248,160 @@ FILE *fplog; printf("Warning: Moin = %g is too large.\n", pParam->BSIM3moin); } - if(model->BSIM3capMod ==3) { - if (pParam->BSIM3acde < 0.4) - { fprintf(fplog, "Warning: Acde = %g is too small.\n", - pParam->BSIM3acde); - printf("Warning: Acde = %g is too small.\n", pParam->BSIM3acde); - } - if (pParam->BSIM3acde > 1.6) - { fprintf(fplog, "Warning: Acde = %g is too large.\n", - pParam->BSIM3acde); - printf("Warning: Acde = %g is too large.\n", pParam->BSIM3acde); - } - } + if(model->BSIM3capMod ==3) { + if (pParam->BSIM3acde < 0.4) + { fprintf(fplog, "Warning: Acde = %g is too small.\n", + pParam->BSIM3acde); + printf("Warning: Acde = %g is too small.\n", pParam->BSIM3acde); + } + if (pParam->BSIM3acde > 1.6) + { fprintf(fplog, "Warning: Acde = %g is too large.\n", + pParam->BSIM3acde); + printf("Warning: Acde = %g is too large.\n", pParam->BSIM3acde); + } + } if (model->BSIM3paramChk ==1) { /* Check L and W parameters */ - if (pParam->BSIM3leff <= 5.0e-8) - { fprintf(fplog, "Warning: Leff = %g may be too small.\n", - pParam->BSIM3leff); - printf("Warning: Leff = %g may be too small.\n", - pParam->BSIM3leff); - } - - if (pParam->BSIM3leffCV <= 5.0e-8) - { fprintf(fplog, "Warning: Leff for CV = %g may be too small.\n", - pParam->BSIM3leffCV); - printf("Warning: Leff for CV = %g may be too small.\n", - pParam->BSIM3leffCV); - } - + if (pParam->BSIM3leff <= 5.0e-8) + { fprintf(fplog, "Warning: Leff = %g may be too small.\n", + pParam->BSIM3leff); + printf("Warning: Leff = %g may be too small.\n", + pParam->BSIM3leff); + } + + if (pParam->BSIM3leffCV <= 5.0e-8) + { fprintf(fplog, "Warning: Leff for CV = %g may be too small.\n", + pParam->BSIM3leffCV); + printf("Warning: Leff for CV = %g may be too small.\n", + pParam->BSIM3leffCV); + } + if (pParam->BSIM3weff <= 1.0e-7) - { fprintf(fplog, "Warning: Weff = %g may be too small.\n", - pParam->BSIM3weff); - printf("Warning: Weff = %g may be too small.\n", - pParam->BSIM3weff); - } - - if (pParam->BSIM3weffCV <= 1.0e-7) - { fprintf(fplog, "Warning: Weff for CV = %g may be too small.\n", - pParam->BSIM3weffCV); - printf("Warning: Weff for CV = %g may be too small.\n", - pParam->BSIM3weffCV); - } - + { fprintf(fplog, "Warning: Weff = %g may be too small.\n", + pParam->BSIM3weff); + printf("Warning: Weff = %g may be too small.\n", + pParam->BSIM3weff); + } + + if (pParam->BSIM3weffCV <= 1.0e-7) + { fprintf(fplog, "Warning: Weff for CV = %g may be too small.\n", + pParam->BSIM3weffCV); + printf("Warning: Weff for CV = %g may be too small.\n", + pParam->BSIM3weffCV); + } + /* Check threshold voltage parameters */ - if (pParam->BSIM3nlx < 0.0) - { fprintf(fplog, "Warning: Nlx = %g is negative.\n", pParam->BSIM3nlx); - printf("Warning: Nlx = %g is negative.\n", pParam->BSIM3nlx); + if (pParam->BSIM3nlx < 0.0) + { fprintf(fplog, "Warning: Nlx = %g is negative.\n", pParam->BSIM3nlx); + printf("Warning: Nlx = %g is negative.\n", pParam->BSIM3nlx); } - if (model->BSIM3tox < 1.0e-9) - { fprintf(fplog, "Warning: Tox = %g is less than 10A.\n", - model->BSIM3tox); - printf("Warning: Tox = %g is less than 10A.\n", model->BSIM3tox); + if (model->BSIM3tox < 1.0e-9) + { fprintf(fplog, "Warning: Tox = %g is less than 10A.\n", + model->BSIM3tox); + printf("Warning: Tox = %g is less than 10A.\n", model->BSIM3tox); } if (pParam->BSIM3npeak <= 1.0e15) - { fprintf(fplog, "Warning: Nch = %g may be too small.\n", - pParam->BSIM3npeak); - printf("Warning: Nch = %g may be too small.\n", - pParam->BSIM3npeak); - } - else if (pParam->BSIM3npeak >= 1.0e21) - { fprintf(fplog, "Warning: Nch = %g may be too large.\n", - pParam->BSIM3npeak); - printf("Warning: Nch = %g may be too large.\n", - pParam->BSIM3npeak); - } + { fprintf(fplog, "Warning: Nch = %g may be too small.\n", + pParam->BSIM3npeak); + printf("Warning: Nch = %g may be too small.\n", + pParam->BSIM3npeak); + } + else if (pParam->BSIM3npeak >= 1.0e21) + { fprintf(fplog, "Warning: Nch = %g may be too large.\n", + pParam->BSIM3npeak); + printf("Warning: Nch = %g may be too large.\n", + pParam->BSIM3npeak); + } - if (pParam->BSIM3nsub <= 1.0e14) - { fprintf(fplog, "Warning: Nsub = %g may be too small.\n", - pParam->BSIM3nsub); - printf("Warning: Nsub = %g may be too small.\n", - pParam->BSIM3nsub); - } - else if (pParam->BSIM3nsub >= 1.0e21) - { fprintf(fplog, "Warning: Nsub = %g may be too large.\n", - pParam->BSIM3nsub); - printf("Warning: Nsub = %g may be too large.\n", - pParam->BSIM3nsub); - } + if (pParam->BSIM3nsub <= 1.0e14) + { fprintf(fplog, "Warning: Nsub = %g may be too small.\n", + pParam->BSIM3nsub); + printf("Warning: Nsub = %g may be too small.\n", + pParam->BSIM3nsub); + } + else if (pParam->BSIM3nsub >= 1.0e21) + { fprintf(fplog, "Warning: Nsub = %g may be too large.\n", + pParam->BSIM3nsub); + printf("Warning: Nsub = %g may be too large.\n", + pParam->BSIM3nsub); + } - if ((pParam->BSIM3ngate > 0.0) && - (pParam->BSIM3ngate <= 1.e18)) - { fprintf(fplog, "Warning: Ngate = %g is less than 1.E18cm^-3.\n", - pParam->BSIM3ngate); - printf("Warning: Ngate = %g is less than 1.E18cm^-3.\n", - pParam->BSIM3ngate); - } + if ((pParam->BSIM3ngate > 0.0) && + (pParam->BSIM3ngate <= 1.e18)) + { fprintf(fplog, "Warning: Ngate = %g is less than 1.E18cm^-3.\n", + pParam->BSIM3ngate); + printf("Warning: Ngate = %g is less than 1.E18cm^-3.\n", + pParam->BSIM3ngate); + } if (pParam->BSIM3dvt0 < 0.0) - { fprintf(fplog, "Warning: Dvt0 = %g is negative.\n", - pParam->BSIM3dvt0); - printf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM3dvt0); - } - - if (fabs(1.0e-6 / (pParam->BSIM3w0 + pParam->BSIM3weff)) > 10.0) - { fprintf(fplog, "Warning: (W0 + Weff) may be too small.\n"); - printf("Warning: (W0 + Weff) may be too small.\n"); + { fprintf(fplog, "Warning: Dvt0 = %g is negative.\n", + pParam->BSIM3dvt0); + printf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM3dvt0); + } + + if (fabs(1.0e-6 / (pParam->BSIM3w0 + pParam->BSIM3weff)) > 10.0) + { fprintf(fplog, "Warning: (W0 + Weff) may be too small.\n"); + printf("Warning: (W0 + Weff) may be too small.\n"); } /* Check subthreshold parameters */ - if (pParam->BSIM3nfactor < 0.0) - { fprintf(fplog, "Warning: Nfactor = %g is negative.\n", - pParam->BSIM3nfactor); - printf("Warning: Nfactor = %g is negative.\n", pParam->BSIM3nfactor); - } - if (pParam->BSIM3cdsc < 0.0) - { fprintf(fplog, "Warning: Cdsc = %g is negative.\n", - pParam->BSIM3cdsc); - printf("Warning: Cdsc = %g is negative.\n", pParam->BSIM3cdsc); - } - if (pParam->BSIM3cdscd < 0.0) - { fprintf(fplog, "Warning: Cdscd = %g is negative.\n", - pParam->BSIM3cdscd); - printf("Warning: Cdscd = %g is negative.\n", pParam->BSIM3cdscd); - } + if (pParam->BSIM3nfactor < 0.0) + { fprintf(fplog, "Warning: Nfactor = %g is negative.\n", + pParam->BSIM3nfactor); + printf("Warning: Nfactor = %g is negative.\n", pParam->BSIM3nfactor); + } + if (pParam->BSIM3cdsc < 0.0) + { fprintf(fplog, "Warning: Cdsc = %g is negative.\n", + pParam->BSIM3cdsc); + printf("Warning: Cdsc = %g is negative.\n", pParam->BSIM3cdsc); + } + if (pParam->BSIM3cdscd < 0.0) + { fprintf(fplog, "Warning: Cdscd = %g is negative.\n", + pParam->BSIM3cdscd); + printf("Warning: Cdscd = %g is negative.\n", pParam->BSIM3cdscd); + } /* Check DIBL parameters */ - if (pParam->BSIM3eta0 < 0.0) - { fprintf(fplog, "Warning: Eta0 = %g is negative.\n", - pParam->BSIM3eta0); - printf("Warning: Eta0 = %g is negative.\n", pParam->BSIM3eta0); - } - -/* Check Abulk parameters */ - if (fabs(1.0e-6 / (pParam->BSIM3b1 + pParam->BSIM3weff)) > 10.0) - { fprintf(fplog, "Warning: (B1 + Weff) may be too small.\n"); - printf("Warning: (B1 + Weff) may be too small.\n"); + if (pParam->BSIM3eta0 < 0.0) + { fprintf(fplog, "Warning: Eta0 = %g is negative.\n", + pParam->BSIM3eta0); + printf("Warning: Eta0 = %g is negative.\n", pParam->BSIM3eta0); + } + +/* Check Abulk parameters */ + if (fabs(1.0e-6 / (pParam->BSIM3b1 + pParam->BSIM3weff)) > 10.0) + { fprintf(fplog, "Warning: (B1 + Weff) may be too small.\n"); + printf("Warning: (B1 + Weff) may be too small.\n"); } /* Check Saturation parameters */ - if (pParam->BSIM3a2 < 0.01) - { fprintf(fplog, "Warning: A2 = %g is too small. Set to 0.01.\n", pParam->BSIM3a2); - printf("Warning: A2 = %g is too small. Set to 0.01.\n", - pParam->BSIM3a2); - pParam->BSIM3a2 = 0.01; - } - else if (pParam->BSIM3a2 > 1.0) - { fprintf(fplog, "Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", - pParam->BSIM3a2); - printf("Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", - pParam->BSIM3a2); - pParam->BSIM3a2 = 1.0; - pParam->BSIM3a1 = 0.0; - } + if (pParam->BSIM3a2 < 0.01) + { fprintf(fplog, "Warning: A2 = %g is too small. Set to 0.01.\n", pParam->BSIM3a2); + printf("Warning: A2 = %g is too small. Set to 0.01.\n", + pParam->BSIM3a2); + pParam->BSIM3a2 = 0.01; + } + else if (pParam->BSIM3a2 > 1.0) + { fprintf(fplog, "Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", + pParam->BSIM3a2); + printf("Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", + pParam->BSIM3a2); + pParam->BSIM3a2 = 1.0; + pParam->BSIM3a1 = 0.0; + } - if (pParam->BSIM3rdsw < 0.0) - { fprintf(fplog, "Warning: Rdsw = %g is negative. Set to zero.\n", - pParam->BSIM3rdsw); - printf("Warning: Rdsw = %g is negative. Set to zero.\n", - pParam->BSIM3rdsw); - pParam->BSIM3rdsw = 0.0; - pParam->BSIM3rds0 = 0.0; - } + if (pParam->BSIM3rdsw < 0.0) + { fprintf(fplog, "Warning: Rdsw = %g is negative. Set to zero.\n", + pParam->BSIM3rdsw); + printf("Warning: Rdsw = %g is negative. Set to zero.\n", + pParam->BSIM3rdsw); + pParam->BSIM3rdsw = 0.0; + pParam->BSIM3rds0 = 0.0; + } if (pParam->BSIM3rds0 < 0.0) { fprintf(fplog, "Warning: Rds at current temperature = %g is negative. Set to zero.\n", pParam->BSIM3rds0); @@ -401,40 +410,40 @@ FILE *fplog; pParam->BSIM3rds0 = 0.0; } - if (pParam->BSIM3vsattemp < 1.0e3) - { fprintf(fplog, "Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3vsattemp); - printf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3vsattemp); - } + if (pParam->BSIM3vsattemp < 1.0e3) + { fprintf(fplog, "Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3vsattemp); + printf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3vsattemp); + } - if (pParam->BSIM3pdibl1 < 0.0) - { fprintf(fplog, "Warning: Pdibl1 = %g is negative.\n", - pParam->BSIM3pdibl1); - printf("Warning: Pdibl1 = %g is negative.\n", pParam->BSIM3pdibl1); - } - if (pParam->BSIM3pdibl2 < 0.0) - { fprintf(fplog, "Warning: Pdibl2 = %g is negative.\n", - pParam->BSIM3pdibl2); - printf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM3pdibl2); - } + if (pParam->BSIM3pdibl1 < 0.0) + { fprintf(fplog, "Warning: Pdibl1 = %g is negative.\n", + pParam->BSIM3pdibl1); + printf("Warning: Pdibl1 = %g is negative.\n", pParam->BSIM3pdibl1); + } + if (pParam->BSIM3pdibl2 < 0.0) + { fprintf(fplog, "Warning: Pdibl2 = %g is negative.\n", + pParam->BSIM3pdibl2); + printf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM3pdibl2); + } /* Check overlap capacitance parameters */ if (model->BSIM3cgdo < 0.0) - { fprintf(fplog, "Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3cgdo); - printf("Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3cgdo); - model->BSIM3cgdo = 0.0; + { fprintf(fplog, "Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3cgdo); + printf("Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3cgdo); + model->BSIM3cgdo = 0.0; } if (model->BSIM3cgso < 0.0) - { fprintf(fplog, "Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3cgso); - printf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3cgso); - model->BSIM3cgso = 0.0; + { fprintf(fplog, "Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3cgso); + printf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3cgso); + model->BSIM3cgso = 0.0; } if (model->BSIM3cgbo < 0.0) - { fprintf(fplog, "Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3cgbo); - printf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3cgbo); - model->BSIM3cgbo = 0.0; + { fprintf(fplog, "Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3cgbo); + printf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3cgbo); + model->BSIM3cgbo = 0.0; } }/* loop for the parameter check for warning messages */ - fclose(fplog); + fclose(fplog); } else { fprintf(stderr, "Warning: Can't open log file. Parameter checking skipped.\n"); diff --git a/src/spicelib/devices/bsim3/b3ld.c b/src/spicelib/devices/bsim3/b3ld.c index c044e99ac..532658981 100644 --- a/src/spicelib/devices/bsim3/b3ld.c +++ b/src/spicelib/devices/bsim3/b3ld.c @@ -58,7 +58,7 @@ CKTcircuit *ckt) } BSIM3LoadRhsMat(inModel, ckt); - + return good; } @@ -71,7 +71,8 @@ BSIM3instance *here; #endif double SourceSatCurrent, DrainSatCurrent; double ag0, qgd, qgs, qgb, von, cbhat, VgstNVt, ExpVgst; -double cdrain, cdhat, cdreq, ceqbd, ceqbs, ceqqb, ceqqd, ceqqg, ceq, geq; +double cdrain, cdhat, cdreq, cdreq_fvk, ceqbd, ceqbd_fvk, ceqbs, ceqbs_fvk, ceqqb, ceqqd, ceqqg, ceq, geq; +double ceqqb_fvk, ceqqb_SnodePrime_fvk, ceqqd_fvk, ceqqd_SnodePrime_fvk, ceqqg_fvk, ceqqg_SnodePrime_fvk ; double czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; double delvbd, delvbs, delvds, delvgd, delvgs; double Vfbeff, dVfbeff_dVg, dVfbeff_dVb, V3, V4; @@ -96,14 +97,14 @@ double DeltaPhi, dDeltaPhi_dVg, VgDP, dVgDP_dVg; double Cox, Tox, Tcen, dTcen_dVg, dTcen_dVd, dTcen_dVb; double Ccen, Coxeff, dCoxeff_dVg, dCoxeff_dVd, dCoxeff_dVb; double Denomi, dDenomi_dVg, dDenomi_dVd, dDenomi_dVb; -double ueff, dueff_dVg, dueff_dVd, dueff_dVb; +double ueff, dueff_dVg, dueff_dVd, dueff_dVb; double Esat, Vdsat; double EsatL, dEsatL_dVg, dEsatL_dVd, dEsatL_dVb; -double dVdsat_dVg, dVdsat_dVb, dVdsat_dVd, Vasat, dAlphaz_dVg, dAlphaz_dVb; -double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, dVa_dVd, dVa_dVg, dVa_dVb; -double Vbseff, dVbseff_dVb, VbseffCV, dVbseffCV_dVb; -double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; +double dVdsat_dVg, dVdsat_dVb, dVdsat_dVd, Vasat, dAlphaz_dVg, dAlphaz_dVb; +double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, dVa_dVd, dVa_dVg, dVa_dVb; +double Vbseff, dVbseff_dVb, VbseffCV, dVbseffCV_dVb; +double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; double T0, dT0_dVg, dT0_dVd, dT0_dVb; double T1, dT1_dVg, dT1_dVd, dT1_dVb; @@ -115,7 +116,7 @@ double T6; double T7; double T8; double T9; -double T10; +double T10; double T11, T12; double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb; @@ -133,9 +134,9 @@ double tempv; #endif double a1, ScalingFactor; -double Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb; -double Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; -double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; +double Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb; +double Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; +double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; double diffVds, dAbulk_dVg; double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; double gche, dgche_dVg, dgche_dVd, dgche_dVb; @@ -153,19 +154,19 @@ double Leff, Weff, dWeff_dVg, dWeff_dVb; double AbulkCV, dAbulkCV_dVb; double qgdo, qgso, cgdo, cgso; -double qcheq=0.0, qdef, gqdef=0.0, cqdef, cqcheq, gtau_diff, gtau_drift; +double qcheq=0.0, qdef, gqdef=0.0, cqdef, cqdef_fvk, cqcheq, cqcheq_fvk, gtau_diff, gtau_drift; double gcqdb=0.0,gcqsb=0.0,gcqgb=0.0,gcqbb=0.0; double dxpart, sxpart, ggtg, ggtd, ggts, ggtb; double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; -double gbspsp, gbbdp, gbbsp, gbspg, gbspb, gbspdp; -double gbdpdp, gbdpg, gbdpb, gbdpsp; +double gbspsp, gbbdp, gbbsp, gbspg, gbspb, gbspdp; +double gbdpdp, gbdpg, gbdpb, gbdpsp; 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; @@ -177,67 +178,67 @@ model = here->BSIM3modPtr; #endif ScalingFactor = 1.0e-9; -ChargeComputationNeeded = +ChargeComputationNeeded = ((ckt->CKTmode & (MODEDCTRANCURVE | MODEAC | MODETRAN | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? 1 : 0; #ifndef USE_OMP for (; model != NULL; model = model->BSIM3nextModel) -{ for (here = model->BSIM3instances; here != NULL; +{ for (here = model->BSIM3instances; here != NULL; here = here->BSIM3nextInstance) { #endif Check = 1; ByPass = 0; - pParam = here->pParam; + pParam = here->pParam; if ((ckt->CKTmode & MODEINITSMSIG)) - { vbs = *(ckt->CKTstate0 + here->BSIM3vbs); + { vbs = *(ckt->CKTstate0 + here->BSIM3vbs); vgs = *(ckt->CKTstate0 + here->BSIM3vgs); vds = *(ckt->CKTstate0 + here->BSIM3vds); qdef = *(ckt->CKTstate0 + here->BSIM3qdef); } - else if ((ckt->CKTmode & MODEINITTRAN)) - { vbs = *(ckt->CKTstate1 + here->BSIM3vbs); + else if ((ckt->CKTmode & MODEINITTRAN)) + { vbs = *(ckt->CKTstate1 + here->BSIM3vbs); vgs = *(ckt->CKTstate1 + here->BSIM3vgs); vds = *(ckt->CKTstate1 + here->BSIM3vds); qdef = *(ckt->CKTstate1 + here->BSIM3qdef); } - else if ((ckt->CKTmode & MODEINITJCT) && !here->BSIM3off) - { vds = model->BSIM3type * here->BSIM3icVDS; + else if ((ckt->CKTmode & MODEINITJCT) && !here->BSIM3off) + { vds = model->BSIM3type * here->BSIM3icVDS; vgs = model->BSIM3type * here->BSIM3icVGS; vbs = model->BSIM3type * here->BSIM3icVBS; qdef = 0.0; - if ((vds == 0.0) && (vgs == 0.0) && (vbs == 0.0) && + if ((vds == 0.0) && (vgs == 0.0) && (vbs == 0.0) && ((ckt->CKTmode & (MODETRAN | MODEAC|MODEDCOP | MODEDCTRANCURVE)) || (!(ckt->CKTmode & MODEUIC)))) - { vbs = 0.0; - vgs = model->BSIM3type * pParam->BSIM3vth0 + 0.1; + { vbs = 0.0; + vgs = model->BSIM3type * here->BSIM3vth0 + 0.1; vds = 0.1; } } - else if ((ckt->CKTmode & (MODEINITJCT | MODEINITFIX)) && - (here->BSIM3off)) + else if ((ckt->CKTmode & (MODEINITJCT | MODEINITFIX)) && + (here->BSIM3off)) { qdef = vbs = vgs = vds = 0.0; - } + } else - { + { #ifndef PREDICTOR if ((ckt->CKTmode & MODEINITPRED)) - { xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; - *(ckt->CKTstate0 + here->BSIM3vbs) = + { xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; + *(ckt->CKTstate0 + here->BSIM3vbs) = *(ckt->CKTstate1 + here->BSIM3vbs); vbs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vbs)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3vbs))); - *(ckt->CKTstate0 + here->BSIM3vgs) = + *(ckt->CKTstate0 + here->BSIM3vgs) = *(ckt->CKTstate1 + here->BSIM3vgs); vgs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vgs)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3vgs))); - *(ckt->CKTstate0 + here->BSIM3vds) = + *(ckt->CKTstate0 + here->BSIM3vds) = *(ckt->CKTstate1 + here->BSIM3vds); vds = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vds)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3vds))); - *(ckt->CKTstate0 + here->BSIM3vbd) = + *(ckt->CKTstate0 + here->BSIM3vbd) = *(ckt->CKTstate0 + here->BSIM3vbs) - *(ckt->CKTstate0 + here->BSIM3vds); *(ckt->CKTstate0 + here->BSIM3qdef) = @@ -245,14 +246,14 @@ for (; model != NULL; model = model->BSIM3nextModel) qdef = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3qdef)) -(xfact * (*(ckt->CKTstate2 + here->BSIM3qdef))); } - else - { + else + { #endif /* PREDICTOR */ vbs = model->BSIM3type * (*(ckt->CKTrhsOld + here->BSIM3bNode) - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); vgs = model->BSIM3type - * (*(ckt->CKTrhsOld + here->BSIM3gNode) + * (*(ckt->CKTrhsOld + here->BSIM3gNode) - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); vds = model->BSIM3type * (*(ckt->CKTrhsOld + here->BSIM3dNodePrime) @@ -316,7 +317,7 @@ for (; model != NULL; model = model->BSIM3nextModel) * MAX(fabs(cdhat),fabs(Idtot)) + ckt->CKTabstol)) { tempv = MAX(fabs(cbhat),fabs(Ibtot)) + ckt->CKTabstol; if ((fabs(cbhat - Ibtot)) < ckt->CKTreltol * tempv) - { /* bypass code */ + { /* bypass code */ vbs = *(ckt->CKTstate0 + here->BSIM3vbs); vbd = *(ckt->CKTstate0 + here->BSIM3vbd); vgs = *(ckt->CKTstate0 + here->BSIM3vgs); @@ -327,46 +328,46 @@ for (; model != NULL; model = model->BSIM3nextModel) vgb = vgs - vbs; cdrain = here->BSIM3cd; - if ((ckt->CKTmode & (MODETRAN | MODEAC)) || - ((ckt->CKTmode & MODETRANOP) && + if ((ckt->CKTmode & (MODETRAN | MODEAC)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) - { ByPass = 1; + { ByPass = 1; qgate = here->BSIM3qgate; qbulk = here->BSIM3qbulk; qdrn = here->BSIM3qdrn; - goto line755; + goto line755; + } + else + { goto line850; } - else - { goto line850; - } } } #endif /*NOBYPASS*/ von = here->BSIM3von; if (*(ckt->CKTstate0 + here->BSIM3vds) >= 0.0) - { vgs = DEVfetlim(vgs, *(ckt->CKTstate0+here->BSIM3vgs), von); + { vgs = DEVfetlim(vgs, *(ckt->CKTstate0+here->BSIM3vgs), von); vds = vgs - vgd; vds = DEVlimvds(vds, *(ckt->CKTstate0 + here->BSIM3vds)); vgd = vgs - vds; } - else - { vgd = DEVfetlim(vgd, vgdo, von); + else + { vgd = DEVfetlim(vgd, vgdo, von); vds = vgs - vgd; vds = -DEVlimvds(-vds, -(*(ckt->CKTstate0+here->BSIM3vds))); vgs = vgd + vds; } if (vds >= 0.0) - { vbs = DEVpnjlim(vbs, *(ckt->CKTstate0 + here->BSIM3vbs), + { vbs = DEVpnjlim(vbs, *(ckt->CKTstate0 + here->BSIM3vbs), CONSTvt0, model->BSIM3vcrit, &Check); vbd = vbs - vds; } - else - { vbd = DEVpnjlim(vbd, *(ckt->CKTstate0 + here->BSIM3vbd), - CONSTvt0, model->BSIM3vcrit, &Check); + else + { vbd = DEVpnjlim(vbd, *(ckt->CKTstate0 + here->BSIM3vbd), + CONSTvt0, model->BSIM3vcrit, &Check); vbs = vbd + vds; } } @@ -378,17 +379,57 @@ for (; model != NULL; model = model->BSIM3nextModel) /* Source/drain junction diode DC model begins */ Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; - if ((here->BSIM3sourceArea <= 0.0) && (here->BSIM3sourcePerimeter <= 0.0)) - { SourceSatCurrent = 1.0e-14; - } - else - { SourceSatCurrent = here->BSIM3sourceArea - * model->BSIM3jctTempSatCurDensity - + here->BSIM3sourcePerimeter - * model->BSIM3jctSidewallTempSatCurDensity; - } - if (SourceSatCurrent <= 0.0) - { here->BSIM3gbs = ckt->CKTgmin; + /* acm model */ + if (model->BSIM3acmMod == 0) + { + if ((here->BSIM3sourceArea <= 0.0) && (here->BSIM3sourcePerimeter <= 0.0)) + { SourceSatCurrent = 1.0e-14; + } + else + { SourceSatCurrent = here->BSIM3sourceArea + * model->BSIM3jctTempSatCurDensity + + here->BSIM3sourcePerimeter + * model->BSIM3jctSidewallTempSatCurDensity; + } + if ((here->BSIM3drainArea <= 0.0) && (here->BSIM3drainPerimeter <= 0.0)) + { DrainSatCurrent = 1.0e-14; + } + else + { DrainSatCurrent = here->BSIM3drainArea + * model->BSIM3jctTempSatCurDensity + + here->BSIM3drainPerimeter + * model->BSIM3jctSidewallTempSatCurDensity; + } + } + else + { + error = ACM_saturationCurrents( + model->BSIM3acmMod, + model->BSIM3calcacm, + here->BSIM3geo, + model->BSIM3hdif, + model->BSIM3wmlt, + here->BSIM3w, + model->BSIM3xw, + model->BSIM3jctTempSatCurDensity, + model->BSIM3jctSidewallTempSatCurDensity, + here->BSIM3drainAreaGiven, + here->BSIM3drainArea, + here->BSIM3drainPerimeterGiven, + here->BSIM3drainPerimeter, + here->BSIM3sourceAreaGiven, + here->BSIM3sourceArea, + here->BSIM3sourcePerimeterGiven, + here->BSIM3sourcePerimeter, + &DrainSatCurrent, + &SourceSatCurrent + ); + if (error) + return(error); + } + + if (SourceSatCurrent <= 0.0) + { here->BSIM3gbs = ckt->CKTgmin; here->BSIM3cbs = here->BSIM3gbs * vbs; } else @@ -396,7 +437,7 @@ for (; model != NULL; model = model->BSIM3nextModel) { evbs = exp(vbs / Nvtm); here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) - + ckt->CKTgmin * vbs; + + ckt->CKTgmin * vbs; } else { if (vbs < here->BSIM3vjsm) @@ -415,17 +456,8 @@ for (; model != NULL; model = model->BSIM3nextModel) } } - if ((here->BSIM3drainArea <= 0.0) && (here->BSIM3drainPerimeter <= 0.0)) - { DrainSatCurrent = 1.0e-14; - } - else - { DrainSatCurrent = here->BSIM3drainArea - * model->BSIM3jctTempSatCurDensity - + here->BSIM3drainPerimeter - * model->BSIM3jctSidewallTempSatCurDensity; - } - if (DrainSatCurrent <= 0.0) - { here->BSIM3gbd = ckt->CKTgmin; + if (DrainSatCurrent <= 0.0) + { here->BSIM3gbd = ckt->CKTgmin; here->BSIM3cbd = here->BSIM3gbd * vbd; } else @@ -454,44 +486,44 @@ for (; model != NULL; model = model->BSIM3nextModel) /* End of diode DC model */ if (vds >= 0.0) - { /* normal mode */ + { /* normal mode */ here->BSIM3mode = 1; Vds = vds; Vgs = vgs; Vbs = vbs; } - else - { /* inverse mode */ + else + { /* inverse mode */ here->BSIM3mode = -1; Vds = -vds; Vgs = vgd; Vbs = vbd; } - T0 = Vbs - pParam->BSIM3vbsc - 0.001; - T1 = sqrt(T0 * T0 - 0.004 * pParam->BSIM3vbsc); - Vbseff = pParam->BSIM3vbsc + 0.5 * (T0 + T1); - dVbseff_dVb = 0.5 * (1.0 + T0 / T1); + T0 = Vbs - pParam->BSIM3vbsc - 0.001; + T1 = sqrt(T0 * T0 - 0.004 * pParam->BSIM3vbsc); + Vbseff = pParam->BSIM3vbsc + 0.5 * (T0 + T1); + dVbseff_dVb = 0.5 * (1.0 + T0 / T1); if (Vbseff < Vbs) { Vbseff = Vbs; } if (Vbseff > 0.0) - { T0 = pParam->BSIM3phi / (pParam->BSIM3phi + Vbseff); + { T0 = pParam->BSIM3phi / (pParam->BSIM3phi + Vbseff); Phis = pParam->BSIM3phi * T0; dPhis_dVb = -T0 * T0; sqrtPhis = pParam->BSIM3phis3 / (pParam->BSIM3phi + 0.5 * Vbseff); dsqrtPhis_dVb = -0.5 * sqrtPhis * sqrtPhis / pParam->BSIM3phis3; } - else - { Phis = pParam->BSIM3phi - Vbseff; + else + { Phis = pParam->BSIM3phi - Vbseff; dPhis_dVb = -1.0; sqrtPhis = sqrt(Phis); - dsqrtPhis_dVb = -0.5 / sqrtPhis; + dsqrtPhis_dVb = -0.5 / sqrtPhis; } Xdep = pParam->BSIM3Xdep0 * sqrtPhis / pParam->BSIM3sqrtPhi; dXdep_dVb = (pParam->BSIM3Xdep0 / pParam->BSIM3sqrtPhi) - * dsqrtPhis_dVb; + * dsqrtPhis_dVb; Leff = pParam->BSIM3leff; Vtm = model->BSIM3vtm; @@ -501,27 +533,27 @@ for (; model != NULL; model = model->BSIM3nextModel) T0 = pParam->BSIM3dvt2 * Vbseff; if (T0 >= - 0.5) - { T1 = 1.0 + T0; - T2 = pParam->BSIM3dvt2; - } - else /* Added to avoid any discontinuity problems caused by dvt2 */ - { T4 = 1.0 / (3.0 + 8.0 * T0); - T1 = (1.0 + 3.0 * T0) * T4; - T2 = pParam->BSIM3dvt2 * T4 * T4; - } + { T1 = 1.0 + T0; + T2 = pParam->BSIM3dvt2; + } + else /* Added to avoid any discontinuity problems caused by dvt2 */ + { T4 = 1.0 / (3.0 + 8.0 * T0); + T1 = (1.0 + 3.0 * T0) * T4; + T2 = pParam->BSIM3dvt2 * T4 * T4; + } lt1 = model->BSIM3factor1 * T3 * T1; dlt1_dVb = model->BSIM3factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); T0 = pParam->BSIM3dvt2w * Vbseff; if (T0 >= - 0.5) - { T1 = 1.0 + T0; - T2 = pParam->BSIM3dvt2w; - } - else /* Added to avoid any discontinuity problems caused by dvt2w */ - { T4 = 1.0 / (3.0 + 8.0 * T0); - T1 = (1.0 + 3.0 * T0) * T4; - T2 = pParam->BSIM3dvt2w * T4 * T4; - } + { T1 = 1.0 + T0; + T2 = pParam->BSIM3dvt2w; + } + else /* Added to avoid any discontinuity problems caused by dvt2w */ + { T4 = 1.0 / (3.0 + 8.0 * T0); + T1 = (1.0 + 3.0 * T0) * T4; + T2 = pParam->BSIM3dvt2w * T4 * T4; + } ltw = model->BSIM3factor1 * T3 * T1; dltw_dVb = model->BSIM3factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); @@ -565,26 +597,26 @@ for (; model != NULL; model = model->BSIM3nextModel) + (pParam->BSIM3kt1 + pParam->BSIM3kt1l / Leff + pParam->BSIM3kt2 * Vbseff) * TempRatio; tmp2 = model->BSIM3tox * pParam->BSIM3phi - / (pParam->BSIM3weff + pParam->BSIM3w0); + / (pParam->BSIM3weff + pParam->BSIM3w0); - T3 = pParam->BSIM3eta0 + pParam->BSIM3etab * Vbseff; - if (T3 < 1.0e-4) /* avoid discontinuity problems caused by etab */ - { T9 = 1.0 / (3.0 - 2.0e4 * T3); - T3 = (2.0e-4 - T3) * T9; - T4 = T9 * T9; - } - else - { T4 = 1.0; - } - dDIBL_Sft_dVd = T3 * pParam->BSIM3theta0vb0; + T3 = pParam->BSIM3eta0 + pParam->BSIM3etab * Vbseff; + if (T3 < 1.0e-4) /* avoid discontinuity problems caused by etab */ + { T9 = 1.0 / (3.0 - 2.0e4 * T3); + T3 = (2.0e-4 - T3) * T9; + T4 = T9 * T9; + } + else + { T4 = 1.0; + } + dDIBL_Sft_dVd = T3 * pParam->BSIM3theta0vb0; DIBL_Sft = dDIBL_Sft_dVd * Vds; - Vth = model->BSIM3type * pParam->BSIM3vth0 - pParam->BSIM3k1 + Vth = model->BSIM3type * here->BSIM3vth0 - pParam->BSIM3k1 * pParam->BSIM3sqrtPhi + pParam->BSIM3k1ox * sqrtPhis - pParam->BSIM3k2ox * Vbseff - Delt_vth - T2 + (pParam->BSIM3k3 + pParam->BSIM3k3b * Vbseff) * tmp2 + T1 - DIBL_Sft; - here->BSIM3von = Vth; + here->BSIM3von = Vth; dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb - pParam->BSIM3k2ox - dDelt_vth_dVb - dT2_dVb + pParam->BSIM3k3b * tmp2 @@ -596,28 +628,28 @@ for (; model != NULL; model = model->BSIM3nextModel) tmp2 = pParam->BSIM3nfactor * EPSSI / Xdep; tmp3 = pParam->BSIM3cdsc + pParam->BSIM3cdscb * Vbseff + pParam->BSIM3cdscd * Vds; - tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM3cit) / model->BSIM3cox; - if (tmp4 >= -0.5) - { n = 1.0 + tmp4; - dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM3cit) / model->BSIM3cox; + if (tmp4 >= -0.5) + { n = 1.0 + tmp4; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + pParam->BSIM3cdscb * Theta0) / model->BSIM3cox; dn_dVd = pParam->BSIM3cdscd * Theta0 / model->BSIM3cox; - } - else - /* avoid discontinuity problems caused by tmp4 */ - { T0 = 1.0 / (3.0 + 8.0 * tmp4); - n = (1.0 + 3.0 * tmp4) * T0; - T0 *= T0; - dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + } + else + /* avoid discontinuity problems caused by tmp4 */ + { T0 = 1.0 / (3.0 + 8.0 * tmp4); + n = (1.0 + 3.0 * tmp4) * T0; + T0 *= T0; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + pParam->BSIM3cdscb * Theta0) / model->BSIM3cox * T0; dn_dVd = pParam->BSIM3cdscd * Theta0 / model->BSIM3cox * T0; - } + } /* Poly Gate Si Depletion Effect */ - T0 = pParam->BSIM3vfb + pParam->BSIM3phi; - if ((pParam->BSIM3ngate > 1.e18) && (pParam->BSIM3ngate < 1.e25) + T0 = here->BSIM3vfb + pParam->BSIM3phi; + if ((pParam->BSIM3ngate > 1.e18) && (pParam->BSIM3ngate < 1.e25) && (Vgs > T0)) - /* added to avoid the problem caused by ngate */ + /* added to avoid the problem caused by ngate */ { T1 = 1.0e6 * Charge_q * EPSSI * pParam->BSIM3ngate / (model->BSIM3cox * model->BSIM3cox); T4 = sqrt(1.0 + 2.0 * (Vgs - T0) / T1); @@ -627,10 +659,10 @@ for (; model != NULL; model = model->BSIM3nextModel) T6 = sqrt(T7 * T7 + 0.224); T5 = 1.12 - 0.5 * (T7 + T6); Vgs_eff = Vgs - T5; - dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6); + dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6); } - else - { Vgs_eff = Vgs; + else + { Vgs_eff = Vgs; dVgs_eff_dVg = 1.0; } Vgst = Vgs_eff - Vth; @@ -641,140 +673,140 @@ for (; model != NULL; model = model->BSIM3nextModel) VgstNVt = Vgst / T10; ExpArg = (2.0 * pParam->BSIM3voff - Vgst) / T10; - /* MCJ: Very small Vgst */ + /* MCJ: Very small Vgst */ if (VgstNVt > EXP_THRESHOLD) - { Vgsteff = Vgst; + { Vgsteff = Vgst; dVgsteff_dVg = dVgs_eff_dVg; dVgsteff_dVd = -dVth_dVd; dVgsteff_dVb = -dVth_dVb; - } - else if (ExpArg > EXP_THRESHOLD) - { T0 = (Vgst - pParam->BSIM3voff) / (n * Vtm); - ExpVgst = exp(T0); - Vgsteff = Vtm * pParam->BSIM3cdep0 / model->BSIM3cox * ExpVgst; + } + else if (ExpArg > EXP_THRESHOLD) + { T0 = (Vgst - pParam->BSIM3voff) / (n * Vtm); + ExpVgst = exp(T0); + Vgsteff = Vtm * pParam->BSIM3cdep0 / model->BSIM3cox * ExpVgst; dVgsteff_dVg = Vgsteff / (n * Vtm); dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + T0 * Vtm * dn_dVd); dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + T0 * Vtm * dn_dVb); - dVgsteff_dVg *= dVgs_eff_dVg; - } - else - { ExpVgst = exp(VgstNVt); + dVgsteff_dVg *= dVgs_eff_dVg; + } + else + { ExpVgst = exp(VgstNVt); T1 = T10 * log(1.0 + ExpVgst); dT1_dVg = ExpVgst / (1.0 + ExpVgst); dT1_dVb = -dT1_dVg * (dVth_dVb + Vgst / n * dn_dVb) - + T1 / n * dn_dVb; - dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd) - + T1 / n * dn_dVd; + + T1 / n * dn_dVb; + dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd) + + T1 / n * dn_dVd; - dT2_dVg = -model->BSIM3cox / (Vtm * pParam->BSIM3cdep0) - * exp(ExpArg); + dT2_dVg = -model->BSIM3cox / (Vtm * pParam->BSIM3cdep0) + * exp(ExpArg); T2 = 1.0 - T10 * dT2_dVg; dT2_dVd = -dT2_dVg * (dVth_dVd - 2.0 * Vtm * ExpArg * dn_dVd) - + (T2 - 1.0) / n * dn_dVd; + + (T2 - 1.0) / n * dn_dVd; dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * Vtm * ExpArg * dn_dVb) - + (T2 - 1.0) / n * dn_dVb; + + (T2 - 1.0) / n * dn_dVb; Vgsteff = T1 / T2; - T3 = T2 * T2; + T3 = T2 * T2; dVgsteff_dVg = (T2 * dT1_dVg - T1 * dT2_dVg) / T3 * dVgs_eff_dVg; dVgsteff_dVd = (T2 * dT1_dVd - T1 * dT2_dVd) / T3; dVgsteff_dVb = (T2 * dT1_dVb - T1 * dT2_dVb) / T3; - } - here->BSIM3Vgsteff = Vgsteff; + } + here->BSIM3Vgsteff = Vgsteff; /* Calculate Effective Channel Geometry */ T9 = sqrtPhis - pParam->BSIM3sqrtPhi; - Weff = pParam->BSIM3weff - 2.0 * (pParam->BSIM3dwg * Vgsteff - + pParam->BSIM3dwb * T9); + Weff = pParam->BSIM3weff - 2.0 * (pParam->BSIM3dwg * Vgsteff + + pParam->BSIM3dwb * T9); dWeff_dVg = -2.0 * pParam->BSIM3dwg; dWeff_dVb = -2.0 * pParam->BSIM3dwb * dsqrtPhis_dVb; if (Weff < 2.0e-8) /* to avoid the discontinuity problem due to Weff*/ - { T0 = 1.0 / (6.0e-8 - 2.0 * Weff); - Weff = 2.0e-8 * (4.0e-8 - Weff) * T0; - T0 *= T0 * 4.0e-16; + { T0 = 1.0 / (6.0e-8 - 2.0 * Weff); + Weff = 2.0e-8 * (4.0e-8 - Weff) * T0; + T0 *= T0 * 4.0e-16; dWeff_dVg *= T0; - dWeff_dVb *= T0; + dWeff_dVb *= T0; } T0 = pParam->BSIM3prwg * Vgsteff + pParam->BSIM3prwb * T9; - if (T0 >= -0.9) - { Rds = pParam->BSIM3rds0 * (1.0 + T0); - dRds_dVg = pParam->BSIM3rds0 * pParam->BSIM3prwg; + if (T0 >= -0.9) + { Rds = pParam->BSIM3rds0 * (1.0 + T0); + dRds_dVg = pParam->BSIM3rds0 * pParam->BSIM3prwg; dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb; - } - else + } + else /* to avoid the discontinuity problem due to prwg and prwb*/ - { T1 = 1.0 / (17.0 + 20.0 * T0); - Rds = pParam->BSIM3rds0 * (0.8 + T0) * T1; - T1 *= T1; - dRds_dVg = pParam->BSIM3rds0 * pParam->BSIM3prwg * T1; + { T1 = 1.0 / (17.0 + 20.0 * T0); + Rds = pParam->BSIM3rds0 * (0.8 + T0) * T1; + T1 *= T1; + dRds_dVg = pParam->BSIM3rds0 * pParam->BSIM3prwg * T1; dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb - * T1; - } - here->BSIM3rds = Rds; /* Noise Bugfix */ - + * T1; + } + here->BSIM3rds = Rds; /* Noise Bugfix */ + /* Calculate Abulk */ T1 = 0.5 * pParam->BSIM3k1ox / sqrtPhis; dT1_dVb = -T1 / sqrtPhis * dsqrtPhis_dVb; T9 = sqrt(pParam->BSIM3xj * Xdep); tmp1 = Leff + 2.0 * T9; - T5 = Leff / tmp1; + T5 = Leff / tmp1; tmp2 = pParam->BSIM3a0 * T5; - tmp3 = pParam->BSIM3weff + pParam->BSIM3b1; + tmp3 = pParam->BSIM3weff + pParam->BSIM3b1; tmp4 = pParam->BSIM3b0 / tmp3; T2 = tmp2 + tmp4; dT2_dVb = -T9 / tmp1 / Xdep * dXdep_dVb; T6 = T5 * T5; T7 = T5 * T6; - Abulk0 = 1.0 + T1 * T2; + Abulk0 = 1.0 + T1 * T2; dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb; T8 = pParam->BSIM3ags * pParam->BSIM3a0 * T7; dAbulk_dVg = -T1 * T8; - Abulk = Abulk0 + dAbulk_dVg * Vgsteff; + Abulk = Abulk0 + dAbulk_dVg * Vgsteff; dAbulk_dVb = dAbulk0_dVb - T8 * Vgsteff * (dT1_dVb - + 3.0 * T1 * dT2_dVb); + + 3.0 * T1 * dT2_dVb); if (Abulk0 < 0.1) /* added to avoid the problems caused by Abulk0 */ - { T9 = 1.0 / (3.0 - 20.0 * Abulk0); - Abulk0 = (0.2 - Abulk0) * T9; - dAbulk0_dVb *= T9 * T9; - } + { T9 = 1.0 / (3.0 - 20.0 * Abulk0); + Abulk0 = (0.2 - Abulk0) * T9; + dAbulk0_dVb *= T9 * T9; + } if (Abulk < 0.1) /* added to avoid the problems caused by Abulk */ - { T9 = 1.0 / (3.0 - 20.0 * Abulk); - Abulk = (0.2 - Abulk) * T9; + { T9 = 1.0 / (3.0 - 20.0 * Abulk); + Abulk = (0.2 - Abulk) * T9; T10 = T9 * T9; - dAbulk_dVb *= T10; + dAbulk_dVb *= T10; dAbulk_dVg *= T10; - } - here->BSIM3Abulk = Abulk; + } + here->BSIM3Abulk = Abulk; T2 = pParam->BSIM3keta * Vbseff; - if (T2 >= -0.9) - { T0 = 1.0 / (1.0 + T2); + if (T2 >= -0.9) + { T0 = 1.0 / (1.0 + T2); dT0_dVb = -pParam->BSIM3keta * T0 * T0; - } - else + } + else /* added to avoid the problems caused by Keta */ - { T1 = 1.0 / (0.8 + T2); - T0 = (17.0 + 20.0 * T2) * T1; + { T1 = 1.0 / (0.8 + T2); + T0 = (17.0 + 20.0 * T2) * T1; dT0_dVb = -pParam->BSIM3keta * T1 * T1; - } - dAbulk_dVg *= T0; - dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb; - dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb; - Abulk *= T0; - Abulk0 *= T0; + } + dAbulk_dVg *= T0; + dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb; + dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb; + Abulk *= T0; + Abulk0 *= T0; /* Mobility calculation */ if (model->BSIM3mobMod == 1) - { T0 = Vgsteff + Vth + Vth; + { T0 = Vgsteff + Vth + Vth; T2 = pParam->BSIM3ua + pParam->BSIM3uc * Vbseff; T3 = T0 / model->BSIM3tox; T5 = T3 * (T2 + pParam->BSIM3ub * T3); @@ -782,49 +814,49 @@ for (; model != NULL; model = model->BSIM3nextModel) dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM3uc * T3; } - else if (model->BSIM3mobMod == 2) - { T5 = Vgsteff / model->BSIM3tox * (pParam->BSIM3ua - + pParam->BSIM3uc * Vbseff + pParam->BSIM3ub * Vgsteff + else if (model->BSIM3mobMod == 2) + { T5 = Vgsteff / model->BSIM3tox * (pParam->BSIM3ua + + pParam->BSIM3uc * Vbseff + pParam->BSIM3ub * Vgsteff / model->BSIM3tox); dDenomi_dVg = (pParam->BSIM3ua + pParam->BSIM3uc * Vbseff - + 2.0 * pParam->BSIM3ub * Vgsteff / model->BSIM3tox) - / model->BSIM3tox; + + 2.0 * pParam->BSIM3ub * Vgsteff / model->BSIM3tox) + / model->BSIM3tox; dDenomi_dVd = 0.0; - dDenomi_dVb = Vgsteff * pParam->BSIM3uc / model->BSIM3tox; + dDenomi_dVb = Vgsteff * pParam->BSIM3uc / model->BSIM3tox; } - else - { T0 = Vgsteff + Vth + Vth; + else + { T0 = Vgsteff + Vth + Vth; T2 = 1.0 + pParam->BSIM3uc * Vbseff; T3 = T0 / model->BSIM3tox; T4 = T3 * (pParam->BSIM3ua + pParam->BSIM3ub * T3); - T5 = T4 * T2; + T5 = T4 * T2; dDenomi_dVg = (pParam->BSIM3ua + 2.0 * pParam->BSIM3ub * T3) * T2 - / model->BSIM3tox; + / model->BSIM3tox; dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM3uc * T4; } - if (T5 >= -0.8) - { Denomi = 1.0 + T5; - } - else /* Added to avoid the discontinuity problem caused by ua and ub*/ - { T9 = 1.0 / (7.0 + 10.0 * T5); - Denomi = (0.6 + T5) * T9; - T9 *= T9; + if (T5 >= -0.8) + { Denomi = 1.0 + T5; + } + else /* Added to avoid the discontinuity problem caused by ua and ub*/ + { T9 = 1.0 / (7.0 + 10.0 * T5); + Denomi = (0.6 + T5) * T9; + T9 *= T9; dDenomi_dVg *= T9; dDenomi_dVd *= T9; dDenomi_dVb *= T9; - } + } - here->BSIM3ueff = ueff = pParam->BSIM3u0temp / Denomi; - T9 = -ueff / Denomi; + here->BSIM3ueff = ueff = here->BSIM3u0temp / Denomi; + T9 = -ueff / Denomi; dueff_dVg = T9 * dDenomi_dVg; dueff_dVd = T9 * dDenomi_dVd; dueff_dVb = T9 * dDenomi_dVb; /* Saturation Drain Voltage Vdsat */ WVCox = Weff * pParam->BSIM3vsattemp * model->BSIM3cox; - WVCoxRds = WVCox * Rds; + WVCoxRds = WVCox * Rds; Esat = 2.0 * pParam->BSIM3vsattemp / ueff; EsatL = Esat * Leff; @@ -832,28 +864,28 @@ for (; model != NULL; model = model->BSIM3nextModel) dEsatL_dVg = T0 * dueff_dVg; dEsatL_dVd = T0 * dueff_dVd; dEsatL_dVb = T0 * dueff_dVb; - - /* Sqrt() */ + + /* Sqrt() */ a1 = pParam->BSIM3a1; - if (a1 == 0.0) - { Lambda = pParam->BSIM3a2; - dLambda_dVg = 0.0; - } - else if (a1 > 0.0) + if (a1 == 0.0) + { Lambda = pParam->BSIM3a2; + dLambda_dVg = 0.0; + } + else if (a1 > 0.0) /* Added to avoid the discontinuity problem caused by a1 and a2 (Lambda) */ - { T0 = 1.0 - pParam->BSIM3a2; - T1 = T0 - pParam->BSIM3a1 * Vgsteff - 0.0001; - T2 = sqrt(T1 * T1 + 0.0004 * T0); - Lambda = pParam->BSIM3a2 + T0 - 0.5 * (T1 + T2); - dLambda_dVg = 0.5 * pParam->BSIM3a1 * (1.0 + T1 / T2); - } - else - { T1 = pParam->BSIM3a2 + pParam->BSIM3a1 * Vgsteff - 0.0001; - T2 = sqrt(T1 * T1 + 0.0004 * pParam->BSIM3a2); - Lambda = 0.5 * (T1 + T2); - dLambda_dVg = 0.5 * pParam->BSIM3a1 * (1.0 + T1 / T2); - } + { T0 = 1.0 - pParam->BSIM3a2; + T1 = T0 - pParam->BSIM3a1 * Vgsteff - 0.0001; + T2 = sqrt(T1 * T1 + 0.0004 * T0); + Lambda = pParam->BSIM3a2 + T0 - 0.5 * (T1 + T2); + dLambda_dVg = 0.5 * pParam->BSIM3a1 * (1.0 + T1 / T2); + } + else + { T1 = pParam->BSIM3a2 + pParam->BSIM3a1 * Vgsteff - 0.0001; + T2 = sqrt(T1 * T1 + 0.0004 * pParam->BSIM3a2); + Lambda = 0.5 * (T1 + T2); + dLambda_dVg = 0.5 * pParam->BSIM3a1 * (1.0 + T1 / T2); + } Vgst2Vtm = Vgsteff + 2.0 * Vtm; here->BSIM3AbovVgst2Vtm = Abulk / Vgst2Vtm; @@ -865,48 +897,48 @@ for (; model != NULL; model = model->BSIM3nextModel) else { tmp2 = dWeff_dVg / Weff; tmp3 = dWeff_dVb / Weff; - } + } if ((Rds == 0.0) && (Lambda == 1.0)) { T0 = 1.0 / (Abulk * EsatL + Vgst2Vtm); tmp1 = 0.0; - T1 = T0 * T0; - T2 = Vgst2Vtm * T0; + T1 = T0 * T0; + T2 = Vgst2Vtm * T0; T3 = EsatL * Vgst2Vtm; Vdsat = T3 * T0; - + dT0_dVg = -(Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 1.0) * T1; - dT0_dVd = -(Abulk * dEsatL_dVd) * T1; - dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1; + dT0_dVd = -(Abulk * dEsatL_dVd) * T1; + dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1; dVdsat_dVg = T3 * dT0_dVg + T2 * dEsatL_dVg + EsatL * T0; dVdsat_dVd = T3 * dT0_dVd + T2 * dEsatL_dVd; - dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb; + dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb; } else { tmp1 = dLambda_dVg / (Lambda * Lambda); T9 = Abulk * WVCoxRds; - T8 = Abulk * T9; - T7 = Vgst2Vtm * T9; + T8 = Abulk * T9; + T7 = Vgst2Vtm * T9; T6 = Vgst2Vtm * WVCoxRds; - T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda); + T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda); dT0_dVg = 2.0 * (T8 * tmp2 - Abulk * tmp1 - + (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg); - + + (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg); + dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3) - + (1.0 / Lambda - 1.0) * dAbulk_dVb); - dT0_dVd = 0.0; + + (1.0 / Lambda - 1.0) * dAbulk_dVb); + dT0_dVd = 0.0; T1 = Vgst2Vtm * (2.0 / Lambda - 1.0) + Abulk * EsatL + 3.0 * T7; - + dT1_dVg = (2.0 / Lambda - 1.0) - 2.0 * Vgst2Vtm * tmp1 - + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 3.0 * (T9 - + T7 * tmp2 + T6 * dAbulk_dVg); + + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 3.0 * (T9 + + T7 * tmp2 + T6 * dAbulk_dVg); dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb - + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3); + + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3); dT1_dVd = Abulk * dEsatL_dVd; T2 = Vgst2Vtm * (EsatL + 2.0 * T6); dT2_dVg = EsatL + Vgst2Vtm * dEsatL_dVg - + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2); + + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2); dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3); dT2_dVd = Vgst2Vtm * dEsatL_dVd; @@ -914,16 +946,16 @@ for (; model != NULL; model = model->BSIM3nextModel) Vdsat = (T1 - T3) / T0; dT3_dVg = (T1 * dT1_dVg - 2.0 * (T0 * dT2_dVg + T2 * dT0_dVg)) - / T3; + / T3; dT3_dVd = (T1 * dT1_dVd - 2.0 * (T0 * dT2_dVd + T2 * dT0_dVd)) - / T3; + / T3; dT3_dVb = (T1 * dT1_dVb - 2.0 * (T0 * dT2_dVb + T2 * dT0_dVb)) - / T3; + / T3; dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2 - - T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0; + - T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0; dVdsat_dVb = (dT1_dVb - (T1 * dT1_dVb - dT0_dVb * T2 - - T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0; + - T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0; dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0; } here->BSIM3vdsat = Vdsat; @@ -935,40 +967,40 @@ for (; model != NULL; model = model->BSIM3nextModel) dT1_dVb = dVdsat_dVb; T2 = sqrt(T1 * T1 + 4.0 * pParam->BSIM3delta * Vdsat); - T0 = T1 / T2; - T3 = 2.0 * pParam->BSIM3delta / T2; + T0 = T1 / T2; + T3 = 2.0 * pParam->BSIM3delta / T2; dT2_dVg = T0 * dT1_dVg + T3 * dVdsat_dVg; dT2_dVd = T0 * dT1_dVd + T3 * dVdsat_dVd; dT2_dVb = T0 * dT1_dVb + T3 * dVdsat_dVb; Vdseff = Vdsat - 0.5 * (T1 + T2); - dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg); - dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd); - dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb); + dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg); + dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd); + dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb); /* Added to eliminate non-zero Vdseff at Vds=0.0 */ if (Vds == 0.0) { Vdseff = 0.0; dVdseff_dVg = 0.0; - dVdseff_dVb = 0.0; + dVdseff_dVb = 0.0; } /* Calculate VAsat */ tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; T9 = WVCoxRds * Vgsteff; - T8 = T9 / Vgst2Vtm; + T8 = T9 / Vgst2Vtm; T0 = EsatL + Vdsat + 2.0 * T9 * tmp4; - + T7 = 2.0 * WVCoxRds * tmp4; dT0_dVg = dEsatL_dVg + dVdsat_dVg + T7 * (1.0 + tmp2 * Vgsteff) - - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm - + Vdsat * dAbulk_dVg); - + - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm + + Vdsat * dAbulk_dVg); + dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * Vgsteff - - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); + - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); dT0_dVd = dEsatL_dVd + dVdsat_dVd - T8 * Abulk * dVdsat_dVd; - T9 = WVCoxRds * Abulk; - T1 = 2.0 / Lambda - 1.0 + T9; + T9 = WVCoxRds * Abulk; + T1 = 2.0 / Lambda - 1.0 + T9; dT1_dVg = -2.0 * tmp1 + WVCoxRds * (Abulk * tmp2 + dAbulk_dVg); dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3; @@ -980,39 +1012,39 @@ for (; model != NULL; model = model->BSIM3nextModel) if (Vdseff > Vds) Vdseff = Vds; diffVds = Vds - Vdseff; - here->BSIM3Vdseff = Vdseff; + here->BSIM3Vdseff = Vdseff; /* Calculate VACLM */ if ((pParam->BSIM3pclm > 0.0) && (diffVds > 1.0e-10)) - { T0 = 1.0 / (pParam->BSIM3pclm * Abulk * pParam->BSIM3litl); + { T0 = 1.0 / (pParam->BSIM3pclm * Abulk * pParam->BSIM3litl); dT0_dVb = -T0 / Abulk * dAbulk_dVb; - dT0_dVg = -T0 / Abulk * dAbulk_dVg; - - T2 = Vgsteff / EsatL; - T1 = Leff * (Abulk + T2); + dT0_dVg = -T0 / Abulk * dAbulk_dVg; + + T2 = Vgsteff / EsatL; + T1 = Leff * (Abulk + T2); dT1_dVg = Leff * ((1.0 - T2 * dEsatL_dVg) / EsatL + dAbulk_dVg); dT1_dVb = Leff * (dAbulk_dVb - T2 * dEsatL_dVb / EsatL); dT1_dVd = -T2 * dEsatL_dVd / Esat; - T9 = T0 * T1; + T9 = T0 * T1; VACLM = T9 * diffVds; dVACLM_dVg = T0 * dT1_dVg * diffVds - T9 * dVdseff_dVg + T1 * diffVds * dT0_dVg; dVACLM_dVb = (dT0_dVb * T1 + T0 * dT1_dVb) * diffVds - - T9 * dVdseff_dVb; + - T9 * dVdseff_dVb; dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd); } - else - { VACLM = MAX_EXP; + else + { VACLM = MAX_EXP; dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0; } /* Calculate VADIBL */ if (pParam->BSIM3thetaRout > 0.0) - { T8 = Abulk * Vdsat; - T0 = Vgst2Vtm * T8; + { T8 = Abulk * Vdsat; + T0 = Vgst2Vtm * T8; dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 - + Vgst2Vtm * Vdsat * dAbulk_dVg; + + Vgst2Vtm * Vdsat * dAbulk_dVg; dT0_dVb = Vgst2Vtm * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd; @@ -1021,59 +1053,59 @@ for (; model != NULL; model = model->BSIM3nextModel) dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat; dT1_dVd = Abulk * dVdsat_dVd; - T9 = T1 * T1; - T2 = pParam->BSIM3thetaRout; + T9 = T1 * T1; + T2 = pParam->BSIM3thetaRout; VADIBL = (Vgst2Vtm - T0 / T1) / T2; dVADIBL_dVg = (1.0 - dT0_dVg / T1 + T0 * dT1_dVg / T9) / T2; dVADIBL_dVb = (-dT0_dVb / T1 + T0 * dT1_dVb / T9) / T2; dVADIBL_dVd = (-dT0_dVd / T1 + T0 * dT1_dVd / T9) / T2; - T7 = pParam->BSIM3pdiblb * Vbseff; - if (T7 >= -0.9) - { T3 = 1.0 / (1.0 + T7); + T7 = pParam->BSIM3pdiblb * Vbseff; + if (T7 >= -0.9) + { T3 = 1.0 / (1.0 + T7); VADIBL *= T3; dVADIBL_dVg *= T3; dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM3pdiblb) - * T3; + * T3; dVADIBL_dVd *= T3; - } - else + } + else /* Added to avoid the discontinuity problem caused by pdiblcb */ - { T4 = 1.0 / (0.8 + T7); - T3 = (17.0 + 20.0 * T7) * T4; + { T4 = 1.0 / (0.8 + T7); + T3 = (17.0 + 20.0 * T7) * T4; dVADIBL_dVg *= T3; dVADIBL_dVb = dVADIBL_dVb * T3 - - VADIBL * pParam->BSIM3pdiblb * T4 * T4; + - VADIBL * pParam->BSIM3pdiblb * T4 * T4; dVADIBL_dVd *= T3; VADIBL *= T3; - } + } } - else - { VADIBL = MAX_EXP; + else + { VADIBL = MAX_EXP; dVADIBL_dVd = dVADIBL_dVg = dVADIBL_dVb = 0.0; } /* Calculate VA */ - - T8 = pParam->BSIM3pvag / EsatL; - T9 = T8 * Vgsteff; - if (T9 > -0.9) - { T0 = 1.0 + T9; + + T8 = pParam->BSIM3pvag / EsatL; + T9 = T8 * Vgsteff; + if (T9 > -0.9) + { T0 = 1.0 + T9; dT0_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL); dT0_dVb = -T9 * dEsatL_dVb / EsatL; dT0_dVd = -T9 * dEsatL_dVd / EsatL; - } - else /* Added to avoid the discontinuity problems caused by pvag */ - { T1 = 1.0 / (17.0 + 20.0 * T9); - T0 = (0.8 + T9) * T1; - T1 *= T1; + } + else /* Added to avoid the discontinuity problems caused by pvag */ + { T1 = 1.0 / (17.0 + 20.0 * T9); + T0 = (0.8 + T9) * T1; + T1 *= T1; dT0_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL) * T1; T9 *= T1 / EsatL; dT0_dVb = -T9 * dEsatL_dVb; dT0_dVd = -T9 * dEsatL_dVd; - } - + } + tmp1 = VACLM * VACLM; tmp2 = VADIBL * VADIBL; tmp3 = VACLM + VADIBL; @@ -1090,25 +1122,25 @@ for (; model != NULL; model = model->BSIM3nextModel) dVa_dVb = dVasat_dVb + T1 * dT0_dVb + T0 * dT1_dVb; /* Calculate VASCBE */ - if (pParam->BSIM3pscbe2 > 0.0) - { if (diffVds > pParam->BSIM3pscbe1 * pParam->BSIM3litl - / EXP_THRESHOLD) - { T0 = pParam->BSIM3pscbe1 * pParam->BSIM3litl / diffVds; - VASCBE = Leff * exp(T0) / pParam->BSIM3pscbe2; + if (pParam->BSIM3pscbe2 > 0.0) + { if (diffVds > pParam->BSIM3pscbe1 * pParam->BSIM3litl + / EXP_THRESHOLD) + { T0 = pParam->BSIM3pscbe1 * pParam->BSIM3litl / diffVds; + VASCBE = Leff * exp(T0) / pParam->BSIM3pscbe2; T1 = T0 * VASCBE / diffVds; dVASCBE_dVg = T1 * dVdseff_dVg; dVASCBE_dVd = -T1 * (1.0 - dVdseff_dVd); dVASCBE_dVb = T1 * dVdseff_dVb; } - else - { VASCBE = MAX_EXP * Leff/pParam->BSIM3pscbe2; + else + { VASCBE = MAX_EXP * Leff/pParam->BSIM3pscbe2; dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; } - } - else - { VASCBE = MAX_EXP; + } + else + { VASCBE = MAX_EXP; dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; - } + } /* Calculate Ids */ CoxWovL = model->BSIM3cox * Weff / Leff; @@ -1118,48 +1150,48 @@ for (; model != NULL; model = model->BSIM3nextModel) dbeta_dVb = CoxWovL * dueff_dVb + beta * dWeff_dVb / Weff; T0 = 1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm; - dT0_dVg = -0.5 * (Abulk * dVdseff_dVg - - Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm; + dT0_dVg = -0.5 * (Abulk * dVdseff_dVg + - Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm; dT0_dVd = -0.5 * Abulk * dVdseff_dVd / Vgst2Vtm; dT0_dVb = -0.5 * (Abulk * dVdseff_dVb + dAbulk_dVb * Vdseff) / Vgst2Vtm; fgche1 = Vgsteff * T0; - dfgche1_dVg = Vgsteff * dT0_dVg + T0; - dfgche1_dVd = Vgsteff * dT0_dVd; - dfgche1_dVb = Vgsteff * dT0_dVb; + dfgche1_dVg = Vgsteff * dT0_dVg + T0; + dfgche1_dVd = Vgsteff * dT0_dVd; + dfgche1_dVb = Vgsteff * dT0_dVb; T9 = Vdseff / EsatL; fgche2 = 1.0 + T9; dfgche2_dVg = (dVdseff_dVg - T9 * dEsatL_dVg) / EsatL; dfgche2_dVd = (dVdseff_dVd - T9 * dEsatL_dVd) / EsatL; dfgche2_dVb = (dVdseff_dVb - T9 * dEsatL_dVb) / EsatL; - + gche = beta * fgche1 / fgche2; dgche_dVg = (beta * dfgche1_dVg + fgche1 * dbeta_dVg - - gche * dfgche2_dVg) / fgche2; + - gche * dfgche2_dVg) / fgche2; dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd - - gche * dfgche2_dVd) / fgche2; + - gche * dfgche2_dVd) / fgche2; dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb - - gche * dfgche2_dVb) / fgche2; + - gche * dfgche2_dVb) / fgche2; T0 = 1.0 + gche * Rds; T9 = Vdseff / T0; Idl = gche * T9; dIdl_dVg = (gche * dVdseff_dVg + T9 * dgche_dVg) / T0 - - Idl * gche / T0 * dRds_dVg ; + - Idl * gche / T0 * dRds_dVg ; - dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0; - dIdl_dVb = (gche * dVdseff_dVb + T9 * dgche_dVb - - Idl * dRds_dVb * gche) / T0; + dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0; + dIdl_dVb = (gche * dVdseff_dVb + T9 * dgche_dVb + - Idl * dRds_dVb * gche) / T0; T9 = diffVds / Va; T0 = 1.0 + T9; Idsa = Idl * T0; dIdsa_dVg = T0 * dIdl_dVg - Idl * (dVdseff_dVg + T9 * dVa_dVg) / Va; dIdsa_dVd = T0 * dIdl_dVd + Idl * (1.0 - dVdseff_dVd - - T9 * dVa_dVd) / Va; + - T9 * dVa_dVd) / Va; dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va; T9 = diffVds / VASCBE; @@ -1168,33 +1200,33 @@ for (; model != NULL; model = model->BSIM3nextModel) Gm = T0 * dIdsa_dVg - Idsa * (dVdseff_dVg + T9 * dVASCBE_dVg) / VASCBE; Gds = T0 * dIdsa_dVd + Idsa * (1.0 - dVdseff_dVd - - T9 * dVASCBE_dVd) / VASCBE; + - T9 * dVASCBE_dVd) / VASCBE; Gmb = T0 * dIdsa_dVb - Idsa * (dVdseff_dVb - + T9 * dVASCBE_dVb) / VASCBE; + + T9 * dVASCBE_dVb) / VASCBE; Gds += Gm * dVgsteff_dVd; - Gmb += Gm * dVgsteff_dVb; - Gm *= dVgsteff_dVg; - Gmb *= dVbseff_dVb; + Gmb += Gm * dVgsteff_dVb; + Gm *= dVgsteff_dVg; + Gmb *= dVbseff_dVb; /* Substrate current begins */ tmp = pParam->BSIM3alpha0 + pParam->BSIM3alpha1 * Leff; if ((tmp <= 0.0) || (pParam->BSIM3beta0 <= 0.0)) - { Isub = Gbd = Gbb = Gbg = 0.0; + { Isub = Gbd = Gbb = Gbg = 0.0; } - else - { T2 = tmp / Leff; - if (diffVds > pParam->BSIM3beta0 / EXP_THRESHOLD) - { T0 = -pParam->BSIM3beta0 / diffVds; - T1 = T2 * diffVds * exp(T0); - T3 = T1 / diffVds * (T0 - 1.0); + else + { T2 = tmp / Leff; + if (diffVds > pParam->BSIM3beta0 / EXP_THRESHOLD) + { T0 = -pParam->BSIM3beta0 / diffVds; + T1 = T2 * diffVds * exp(T0); + T3 = T1 / diffVds * (T0 - 1.0); dT1_dVg = T3 * dVdseff_dVg; dT1_dVd = T3 * (dVdseff_dVd - 1.0); dT1_dVb = T3 * dVdseff_dVb; } - else - { T3 = T2 * MIN_EXP; - T1 = T3 * diffVds; + else + { T3 = T2 * MIN_EXP; + T1 = T3 * diffVds; dT1_dVg = -T3 * dVdseff_dVg; dT1_dVd = T3 * (1.0 - dVdseff_dVd); dT1_dVb = -T3 * dVdseff_dVb; @@ -1205,59 +1237,59 @@ for (; model != NULL; model = model->BSIM3nextModel) Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb; Gbd += Gbg * dVgsteff_dVd; - Gbb += Gbg * dVgsteff_dVb; - Gbg *= dVgsteff_dVg; - Gbb *= dVbseff_dVb; /* bug fixing */ + Gbb += Gbg * dVgsteff_dVb; + Gbg *= dVgsteff_dVg; + Gbb *= dVbseff_dVb; /* bug fixing */ } - + cdrain = Ids; here->BSIM3gds = Gds; here->BSIM3gm = Gm; here->BSIM3gmbs = Gmb; - + here->BSIM3gbbs = Gbb; here->BSIM3gbgs = Gbg; here->BSIM3gbds = Gbd; here->BSIM3csub = Isub; - /* BSIM3 thermal noise Qinv calculated from all capMod + /* BSIM3 thermal noise Qinv calculated from all capMod * 0, 1, 2 & 3 stored in here->BSIM3qinv 1/1998 */ if ((model->BSIM3xpart < 0) || (!ChargeComputationNeeded)) - { qgate = qdrn = qsrc = qbulk = 0.0; + { qgate = qdrn = qsrc = qbulk = 0.0; here->BSIM3cggb = here->BSIM3cgsb = here->BSIM3cgdb = 0.0; here->BSIM3cdgb = here->BSIM3cdsb = here->BSIM3cddb = 0.0; here->BSIM3cbgb = here->BSIM3cbsb = here->BSIM3cbdb = 0.0; - here->BSIM3cqdb = here->BSIM3cqsb = here->BSIM3cqgb + here->BSIM3cqdb = here->BSIM3cqsb = here->BSIM3cqgb = here->BSIM3cqbb = 0.0; here->BSIM3gtau = 0.0; goto finished; } - else if (model->BSIM3capMod == 0) - { + else if (model->BSIM3capMod == 0) + { if (Vbseff < 0.0) - { Vbseff = Vbs; + { Vbseff = Vbs; dVbseff_dVb = 1.0; } - else - { Vbseff = pParam->BSIM3phi - Phis; + else + { Vbseff = pParam->BSIM3phi - Phis; dVbseff_dVb = -dPhis_dVb; } Vfb = pParam->BSIM3vfbcv; - Vth = Vfb + pParam->BSIM3phi + pParam->BSIM3k1ox * sqrtPhis; + Vth = Vfb + pParam->BSIM3phi + pParam->BSIM3k1ox * sqrtPhis; Vgst = Vgs_eff - Vth; - dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb; + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb; dVgst_dVb = -dVth_dVb; - dVgst_dVg = dVgs_eff_dVg; + dVgst_dVg = dVgs_eff_dVg; CoxWL = model->BSIM3cox * pParam->BSIM3weffCV * pParam->BSIM3leffCV; Arg1 = Vgs_eff - Vbseff - Vfb; if (Arg1 <= 0.0) - { qgate = CoxWL * Arg1; + { qgate = CoxWL * Arg1; qbulk = -qgate; qdrn = 0.0; @@ -1274,18 +1306,18 @@ for (; model != NULL; model = model->BSIM3nextModel) here->BSIM3cbsb = -here->BSIM3cgsb; here->BSIM3qinv = 0.0; } - else if (Vgst <= 0.0) - { T1 = 0.5 * pParam->BSIM3k1ox; - T2 = sqrt(T1 * T1 + Arg1); - qgate = CoxWL * pParam->BSIM3k1ox * (T2 - T1); + else if (Vgst <= 0.0) + { T1 = 0.5 * pParam->BSIM3k1ox; + T2 = sqrt(T1 * T1 + Arg1); + qgate = CoxWL * pParam->BSIM3k1ox * (T2 - T1); qbulk = -qgate; qdrn = 0.0; - T0 = CoxWL * T1 / T2; - here->BSIM3cggb = T0 * dVgs_eff_dVg; - here->BSIM3cgdb = 0.0; + T0 = CoxWL * T1 / T2; + here->BSIM3cggb = T0 * dVgs_eff_dVg; + here->BSIM3cgdb = 0.0; here->BSIM3cgsb = T0 * (dVbseff_dVb - dVgs_eff_dVg); - + here->BSIM3cdgb = 0.0; here->BSIM3cddb = 0.0; here->BSIM3cdsb = 0.0; @@ -1295,63 +1327,63 @@ for (; model != NULL; model = model->BSIM3nextModel) here->BSIM3cbsb = -here->BSIM3cgsb; here->BSIM3qinv = 0.0; } - else - { One_Third_CoxWL = CoxWL / 3.0; + else + { One_Third_CoxWL = CoxWL / 3.0; Two_Third_CoxWL = 2.0 * One_Third_CoxWL; AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; - Vdsat = Vgst / AbulkCV; - dVdsat_dVg = dVgs_eff_dVg / AbulkCV; - dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV; + Vdsat = Vgst / AbulkCV; + dVdsat_dVg = dVgs_eff_dVg / AbulkCV; + dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV; if (model->BSIM3xpart > 0.5) - { /* 0/100 Charge partition model */ - if (Vdsat <= Vds) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.0; + { /* 0/100 Charge partition model */ + if (Vdsat <= Vds) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.0; - here->BSIM3cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3cgsb = -(here->BSIM3cggb + T2); + here->BSIM3cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3cgsb = -(here->BSIM3cggb + T2); here->BSIM3cgdb = 0.0; - + here->BSIM3cdgb = 0.0; here->BSIM3cddb = 0.0; here->BSIM3cdsb = 0.0; - here->BSIM3cbgb = -(here->BSIM3cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3cbsb = -(here->BSIM3cbgb + T3); + here->BSIM3cbgb = -(here->BSIM3cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3cbsb = -(here->BSIM3cbgb + T3); here->BSIM3cbdb = 0.0; here->BSIM3qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - T7 = 2.0 * Vds - T1 - 3.0 * T3; - T8 = T3 - T1 - 2.0 * Vds; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3phi - 0.5 * (Vds - T3)); - T10 = T4 * T8; - qdrn = T4 * T7; - qbulk = -(qgate + qdrn + T10); - + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + T7 = 2.0 * Vds - T1 - 3.0 * T3; + T8 = T3 - T1 - 2.0 * Vds; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3phi - 0.5 * (Vds - T3)); + T10 = T4 * T8; + qdrn = T4 * T7; + qbulk = -(qgate + qdrn + T10); + T5 = T3 / T1; here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; T11 = -CoxWL * T5 * dVdsat_dVb; here->BSIM3cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); here->BSIM3cgsb = -(here->BSIM3cggb + T11 @@ -1363,7 +1395,7 @@ for (; model != NULL; model = model->BSIM3nextModel) T8 = T9 * T8; T9 = 2.0 * T4 * (1.0 - 3.0 * T5); here->BSIM3cdgb = (T7 * dAlphaz_dVg - T9 - * dVdsat_dVg) * dVgs_eff_dVg; + * dVdsat_dVg) * dVgs_eff_dVg; T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb; here->BSIM3cddb = T4 * (3.0 - 6.0 * T2 - 3.0 * T5); here->BSIM3cdsb = -(here->BSIM3cdgb + T12 @@ -1371,200 +1403,200 @@ for (; model != NULL; model = model->BSIM3nextModel) T9 = 2.0 * T4 * (1.0 + T5); T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb; - T12 = T4 * (2.0 * T2 + T5 - 1.0); + T12 = T4 * (2.0 * T2 + T5 - 1.0); T0 = -(T10 + T11 + T12); here->BSIM3cbgb = -(here->BSIM3cggb - + here->BSIM3cdgb + T10); - here->BSIM3cbdb = -(here->BSIM3cgdb - + here->BSIM3cddb + T12); + + here->BSIM3cdgb + T10); + here->BSIM3cbdb = -(here->BSIM3cgdb + + here->BSIM3cddb + T12); here->BSIM3cbsb = -(here->BSIM3cgsb - + here->BSIM3cdsb + T0); + + here->BSIM3cdsb + T0); here->BSIM3qinv = -(qgate + qbulk); } } - else if (model->BSIM3xpart < 0.5) - { /* 40/60 Charge partition model */ - if (Vds >= Vdsat) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.4 * T2; + else if (model->BSIM3xpart < 0.5) + { /* 40/60 Charge partition model */ + if (Vds >= Vdsat) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.4 * T2; - here->BSIM3cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3cgsb = -(here->BSIM3cggb + T2); - here->BSIM3cgdb = 0.0; - - T3 = 0.4 * Two_Third_CoxWL; + here->BSIM3cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3cgsb = -(here->BSIM3cggb + T2); + here->BSIM3cgdb = 0.0; + + T3 = 0.4 * Two_Third_CoxWL; here->BSIM3cdgb = -T3 * dVgs_eff_dVg; here->BSIM3cddb = 0.0; - T4 = T3 * dVth_dVb; + T4 = T3 * dVth_dVb; here->BSIM3cdsb = -(T4 + here->BSIM3cdgb); - here->BSIM3cbgb = -(here->BSIM3cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3cbsb = -(here->BSIM3cbgb + T3); + here->BSIM3cbgb = -(here->BSIM3cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3cbsb = -(here->BSIM3cbgb + T3); here->BSIM3cbdb = 0.0; here->BSIM3qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3phi - - 0.5 * (Vds - T3)); + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3phi + - 0.5 * (Vds - T3)); - T5 = T3 / T1; + T5 = T3 / T1; here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; tmp = -CoxWL * T5 * dVdsat_dVb; here->BSIM3cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); - here->BSIM3cgsb = -(here->BSIM3cggb - + here->BSIM3cgdb + tmp); + here->BSIM3cgsb = -(here->BSIM3cggb + + here->BSIM3cgdb + tmp); - T6 = 1.0 / Vdsat; + T6 = 1.0 / Vdsat; dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); - T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * Vds - + 1.2 * Vds * Vds; - T8 = T2 / T1; - T7 = Vds - T1 - T8 * T6; - qdrn = T4 * T7; - T7 *= T9; - tmp = T8 / T1; - tmp1 = T4 * (2.0 - 4.0 * tmp * T6 - + T8 * (16.0 * Vdsat - 6.0 * Vds)); + T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * Vds + + 1.2 * Vds * Vds; + T8 = T2 / T1; + T7 = Vds - T1 - T8 * T6; + qdrn = T4 * T7; + T7 *= T9; + tmp = T8 / T1; + tmp1 = T4 * (2.0 - 4.0 * tmp * T6 + + T8 * (16.0 * Vdsat - 6.0 * Vds)); here->BSIM3cdgb = (T7 * dAlphaz_dVg - tmp1 - * dVdsat_dVg) * dVgs_eff_dVg; + * dVdsat_dVg) * dVgs_eff_dVg; T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb; here->BSIM3cddb = T4 * (2.0 - (1.0 / (3.0 * T1 - * T1) + 2.0 * tmp) * T6 + T8 - * (6.0 * Vdsat - 2.4 * Vds)); - here->BSIM3cdsb = -(here->BSIM3cdgb - + T10 + here->BSIM3cddb); + * T1) + 2.0 * tmp) * T6 + T8 + * (6.0 * Vdsat - 2.4 * Vds)); + here->BSIM3cdsb = -(here->BSIM3cdgb + + T10 + here->BSIM3cddb); - T7 = 2.0 * (T1 + T3); - qbulk = -(qgate - T4 * T7); - T7 *= T9; - T0 = 4.0 * T4 * (1.0 - T5); - T12 = (-T7 * dAlphaz_dVg - here->BSIM3cdgb - - T0 * dVdsat_dVg) * dVgs_eff_dVg; - T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb; - T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - - here->BSIM3cddb; + T7 = 2.0 * (T1 + T3); + qbulk = -(qgate - T4 * T7); + T7 *= T9; + T0 = 4.0 * T4 * (1.0 - T5); + T12 = (-T7 * dAlphaz_dVg - here->BSIM3cdgb + - T0 * dVdsat_dVg) * dVgs_eff_dVg; + T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb; + T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) + - here->BSIM3cddb; tmp = -(T10 + T11 + T12); - here->BSIM3cbgb = -(here->BSIM3cggb - + here->BSIM3cdgb + T12); + here->BSIM3cbgb = -(here->BSIM3cggb + + here->BSIM3cdgb + T12); here->BSIM3cbdb = -(here->BSIM3cgdb - + here->BSIM3cddb + T10); /* bug fix */ + + here->BSIM3cddb + T10); /* bug fix */ here->BSIM3cbsb = -(here->BSIM3cgsb - + here->BSIM3cdsb + tmp); + + here->BSIM3cdsb + tmp); here->BSIM3qinv = -(qgate + qbulk); } } - else - { /* 50/50 partitioning */ - if (Vds >= Vdsat) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.5 * T2; + else + { /* 50/50 partitioning */ + if (Vds >= Vdsat) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.5 * T2; + + here->BSIM3cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3cgsb = -(here->BSIM3cggb + T2); + here->BSIM3cgdb = 0.0; - here->BSIM3cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3cgsb = -(here->BSIM3cggb + T2); - here->BSIM3cgdb = 0.0; - here->BSIM3cdgb = -One_Third_CoxWL * dVgs_eff_dVg; here->BSIM3cddb = 0.0; - T4 = One_Third_CoxWL * dVth_dVb; + T4 = One_Third_CoxWL * dVth_dVb; here->BSIM3cdsb = -(T4 + here->BSIM3cdgb); - here->BSIM3cbgb = -(here->BSIM3cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3cbsb = -(here->BSIM3cbgb + T3); + here->BSIM3cbgb = -(here->BSIM3cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3cbsb = -(here->BSIM3cbgb + T3); here->BSIM3cbdb = 0.0; here->BSIM3qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3phi - - 0.5 * (Vds - T3)); + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3phi + - 0.5 * (Vds - T3)); - T5 = T3 / T1; + T5 = T3 / T1; here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; tmp = -CoxWL * T5 * dVdsat_dVb; here->BSIM3cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); - here->BSIM3cgsb = -(here->BSIM3cggb - + here->BSIM3cgdb + tmp); + here->BSIM3cgsb = -(here->BSIM3cggb + + here->BSIM3cgdb + tmp); - T6 = 1.0 / Vdsat; + T6 = 1.0 / Vdsat; dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); - T7 = T1 + T3; - qdrn = -T4 * T7; - qbulk = - (qgate + qdrn + qdrn); - T7 *= T9; - T0 = T4 * (2.0 * T5 - 2.0); + T7 = T1 + T3; + qdrn = -T4 * T7; + qbulk = - (qgate + qdrn + qdrn); + T7 *= T9; + T0 = T4 * (2.0 * T5 - 2.0); here->BSIM3cdgb = (T0 * dVdsat_dVg - T7 - * dAlphaz_dVg) * dVgs_eff_dVg; - T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb; + * dAlphaz_dVg) * dVgs_eff_dVg; + T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb; here->BSIM3cddb = T4 * (1.0 - 2.0 * T2 - T5); here->BSIM3cdsb = -(here->BSIM3cdgb + T12 + here->BSIM3cddb); here->BSIM3cbgb = -(here->BSIM3cggb - + 2.0 * here->BSIM3cdgb); + + 2.0 * here->BSIM3cdgb); here->BSIM3cbdb = -(here->BSIM3cgdb - + 2.0 * here->BSIM3cddb); + + 2.0 * here->BSIM3cddb); here->BSIM3cbsb = -(here->BSIM3cgsb - + 2.0 * here->BSIM3cdsb); + + 2.0 * here->BSIM3cdsb); here->BSIM3qinv = -(qgate + qbulk); } - } - } - } - else - { if (Vbseff < 0.0) - { VbseffCV = Vbseff; + } + } + } + else + { if (Vbseff < 0.0) + { VbseffCV = Vbseff; dVbseffCV_dVb = 1.0; } - else - { VbseffCV = pParam->BSIM3phi - Phis; + else + { VbseffCV = pParam->BSIM3phi - Phis; dVbseffCV_dVb = -dPhis_dVb; } CoxWL = model->BSIM3cox * pParam->BSIM3weffCV - * pParam->BSIM3leffCV; + * pParam->BSIM3leffCV; /* Seperate VgsteffCV with noff and voffcv */ noff = n * pParam->BSIM3noff; @@ -1598,84 +1630,84 @@ for (; model != NULL; model = model->BSIM3nextModel) dVgsteff_dVg *= dVgs_eff_dVg; } /* End of VgsteffCV */ - if (model->BSIM3capMod == 1) - { Vfb = pParam->BSIM3vfbzb; + if (model->BSIM3capMod == 1) + { Vfb = here->BSIM3vfbzb; Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff; if (Arg1 <= 0.0) - { qgate = CoxWL * Arg1; + { qgate = CoxWL * Arg1; Cgg = CoxWL * (dVgs_eff_dVg - dVgsteff_dVg); Cgd = -CoxWL * dVgsteff_dVd; Cgb = -CoxWL * (dVbseffCV_dVb + dVgsteff_dVb); } - else - { T0 = 0.5 * pParam->BSIM3k1ox; - T1 = sqrt(T0 * T0 + Arg1); + else + { T0 = 0.5 * pParam->BSIM3k1ox; + T1 = sqrt(T0 * T0 + Arg1); T2 = CoxWL * T0 / T1; - + qgate = CoxWL * pParam->BSIM3k1ox * (T1 - T0); Cgg = T2 * (dVgs_eff_dVg - dVgsteff_dVg); Cgd = -T2 * dVgsteff_dVd; Cgb = -T2 * (dVbseffCV_dVb + dVgsteff_dVb); } - qbulk = -qgate; - Cbg = -Cgg; - Cbd = -Cgd; - Cbb = -Cgb; + qbulk = -qgate; + Cbg = -Cgg; + Cbd = -Cgd; + Cbb = -Cgb; One_Third_CoxWL = CoxWL / 3.0; Two_Third_CoxWL = 2.0 * One_Third_CoxWL; AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; - VdsatCV = Vgsteff / AbulkCV; + VdsatCV = Vgsteff / AbulkCV; if (VdsatCV < Vds) - { dVdsatCV_dVg = 1.0 / AbulkCV; - dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; - T0 = Vgsteff - VdsatCV / 3.0; + { dVdsatCV_dVg = 1.0 / AbulkCV; + dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; + T0 = Vgsteff - VdsatCV / 3.0; dT0_dVg = 1.0 - dVdsatCV_dVg / 3.0; dT0_dVb = -dVdsatCV_dVb / 3.0; qgate += CoxWL * T0; - Cgg1 = CoxWL * dT0_dVg; + Cgg1 = CoxWL * dT0_dVg; Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb; Cgd1 = Cgg1 * dVgsteff_dVd; - Cgg1 *= dVgsteff_dVg; - Cgg += Cgg1; - Cgb += Cgb1; - Cgd += Cgd1; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; - T0 = VdsatCV - Vgsteff; - dT0_dVg = dVdsatCV_dVg - 1.0; - dT0_dVb = dVdsatCV_dVb; + T0 = VdsatCV - Vgsteff; + dT0_dVg = dVdsatCV_dVg - 1.0; + dT0_dVb = dVdsatCV_dVb; qbulk += One_Third_CoxWL * T0; Cbg1 = One_Third_CoxWL * dT0_dVg; - Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb; - Cbd1 = Cbg1 * dVgsteff_dVd; - Cbg1 *= dVgsteff_dVg; - Cbg += Cbg1; - Cbb += Cbb1; + Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb; + Cbd1 = Cbg1 * dVgsteff_dVd; + Cbg1 *= dVgsteff_dVg; + Cbg += Cbg1; + Cbb += Cbb1; Cbd += Cbd1; if (model->BSIM3xpart > 0.5) - T0 = -Two_Third_CoxWL; + T0 = -Two_Third_CoxWL; else if (model->BSIM3xpart < 0.5) - T0 = -0.4 * CoxWL; + T0 = -0.4 * CoxWL; else - T0 = -One_Third_CoxWL; + T0 = -One_Third_CoxWL; qsrc = T0 * Vgsteff; Csg = T0 * dVgsteff_dVg; Csb = T0 * dVgsteff_dVb; Csd = T0 * dVgsteff_dVd; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; } - else - { T0 = AbulkCV * Vds; + else + { T0 = AbulkCV * Vds; T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20); - T2 = Vds / T1; - T3 = T0 * T2; + T2 = Vds / T1; + T3 = T0 * T2; dT3_dVg = -12.0 * T2 * T2 * AbulkCV; dT3_dVd = 6.0 * T0 * (4.0 * Vgsteff - T0) / T1 / T1 - 0.5; dT3_dVb = 12.0 * T2 * T2 * dAbulkCV_dVb * Vgsteff; @@ -1684,137 +1716,137 @@ for (; model != NULL; model = model->BSIM3nextModel) Cgg1 = CoxWL * (1.0 + dT3_dVg); Cgb1 = CoxWL * dT3_dVb + Cgg1 * dVgsteff_dVb; Cgd1 = CoxWL * dT3_dVd + Cgg1 * dVgsteff_dVd; - Cgg1 *= dVgsteff_dVg; - Cgg += Cgg1; - Cgb += Cgb1; - Cgd += Cgd1; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; qbulk += CoxWL * (1.0 - AbulkCV) * (0.5 * Vds - T3); - Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg); - Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb - + (0.5 * Vds - T3) * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb; - Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd - + Cbg1 * dVgsteff_dVd; - Cbg1 *= dVgsteff_dVg; - Cbg += Cbg1; - Cbb += Cbb1; - Cbd += Cbd1; + Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg); + Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb + + (0.5 * Vds - T3) * dAbulkCV_dVb) + + Cbg1 * dVgsteff_dVb; + Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd + + Cbg1 * dVgsteff_dVd; + Cbg1 *= dVgsteff_dVg; + Cbg += Cbg1; + Cbb += Cbb1; + Cbd += Cbd1; if (model->BSIM3xpart > 0.5) - { /* 0/100 Charge petition model */ - T1 = T1 + T1; + { /* 0/100 Charge petition model */ + T1 = T1 + T1; qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - - T0 * T0 / T1); - Csg = -CoxWL * (0.5 + 24.0 * T0 * Vds / T1 / T1 - * AbulkCV); + - T0 * T0 / T1); + Csg = -CoxWL * (0.5 + 24.0 * T0 * Vds / T1 / T1 + * AbulkCV); Csb = -CoxWL * (0.25 * Vds * dAbulkCV_dVb - - 12.0 * T0 * Vds / T1 / T1 * (4.0 * Vgsteff - T0) - * dAbulkCV_dVb) + Csg * dVgsteff_dVb; - Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0 - / T1 / T1 * (4.0 * Vgsteff - T0)) - + Csg * dVgsteff_dVd; - Csg *= dVgsteff_dVg; + - 12.0 * T0 * Vds / T1 / T1 * (4.0 * Vgsteff - T0) + * dAbulkCV_dVb) + Csg * dVgsteff_dVb; + Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0 + / T1 / T1 * (4.0 * Vgsteff - T0)) + + Csg * dVgsteff_dVd; + Csg *= dVgsteff_dVg; } - else if (model->BSIM3xpart < 0.5) - { /* 40/60 Charge petition model */ - T1 = T1 / 12.0; - T2 = 0.5 * CoxWL / (T1 * T1); - T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff - * (Vgsteff - 4.0 * T0 / 3.0)) - - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T2 * T3; - T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) - + 0.4 * T0 * T0; - Csg = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 - * Vgsteff - 8.0 * T0 / 3.0) - + 2.0 * T0 * T0 / 3.0); - Csb = (qsrc / T1 * Vds + T2 * T4 * Vds) * dAbulkCV_dVb - + Csg * dVgsteff_dVb; - Csd = (qsrc / T1 + T2 * T4) * AbulkCV - + Csg * dVgsteff_dVd; - Csg *= dVgsteff_dVg; + else if (model->BSIM3xpart < 0.5) + { /* 40/60 Charge petition model */ + T1 = T1 / 12.0; + T2 = 0.5 * CoxWL / (T1 * T1); + T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff + * (Vgsteff - 4.0 * T0 / 3.0)) + - 2.0 * T0 * T0 * T0 / 15.0; + qsrc = -T2 * T3; + T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + + 0.4 * T0 * T0; + Csg = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 + * Vgsteff - 8.0 * T0 / 3.0) + + 2.0 * T0 * T0 / 3.0); + Csb = (qsrc / T1 * Vds + T2 * T4 * Vds) * dAbulkCV_dVb + + Csg * dVgsteff_dVb; + Csd = (qsrc / T1 + T2 * T4) * AbulkCV + + Csg * dVgsteff_dVd; + Csg *= dVgsteff_dVg; } - else - { /* 50/50 Charge petition model */ + else + { /* 50/50 Charge petition model */ qsrc = -0.5 * (qgate + qbulk); Csg = -0.5 * (Cgg1 + Cbg1); - Csb = -0.5 * (Cgb1 + Cbb1); - Csd = -0.5 * (Cgd1 + Cbd1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); } - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; } qdrn = -(qgate + qbulk + qsrc); here->BSIM3cggb = Cgg; - here->BSIM3cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3cgdb = Cgd; + here->BSIM3cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3cgdb = Cgd; here->BSIM3cdgb = -(Cgg + Cbg + Csg); - here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3cddb = -(Cgd + Cbd + Csd); + here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3cddb = -(Cgd + Cbd + Csd); here->BSIM3cbgb = Cbg; - here->BSIM3cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3cbdb = Cbd; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; here->BSIM3qinv = -(qgate + qbulk); - } + } - else if (model->BSIM3capMod == 2) - { Vfb = pParam->BSIM3vfbzb; + else if (model->BSIM3capMod == 2) + { Vfb = here->BSIM3vfbzb; V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3; - if (Vfb <= 0.0) - { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); - T2 = -DELTA_3 / T0; - } - else - { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb); - T2 = DELTA_3 / T0; - } + if (Vfb <= 0.0) + { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); + T2 = -DELTA_3 / T0; + } + else + { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb); + T2 = DELTA_3 / T0; + } - T1 = 0.5 * (1.0 + V3 / T0); - Vfbeff = Vfb - 0.5 * (V3 + T0); - dVfbeff_dVg = T1 * dVgs_eff_dVg; - dVfbeff_dVb = -T1 * dVbseffCV_dVb; - Qac0 = CoxWL * (Vfbeff - Vfb); - dQac0_dVg = CoxWL * dVfbeff_dVg; - dQac0_dVb = CoxWL * dVfbeff_dVb; + T1 = 0.5 * (1.0 + V3 / T0); + Vfbeff = Vfb - 0.5 * (V3 + T0); + dVfbeff_dVg = T1 * dVgs_eff_dVg; + dVfbeff_dVb = -T1 * dVbseffCV_dVb; + Qac0 = CoxWL * (Vfbeff - Vfb); + dQac0_dVg = CoxWL * dVfbeff_dVg; + dQac0_dVb = CoxWL * dVfbeff_dVb; T0 = 0.5 * pParam->BSIM3k1ox; - T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; if (pParam->BSIM3k1ox == 0.0) { T1 = 0.0; T2 = 0.0; } - else if (T3 < 0.0) - { T1 = T0 + T3 / pParam->BSIM3k1ox; + else if (T3 < 0.0) + { T1 = T0 + T3 / pParam->BSIM3k1ox; T2 = CoxWL; - } - else - { T1 = sqrt(T0 * T0 + T3); + } + else + { T1 = sqrt(T0 * T0 + T3); T2 = CoxWL * T0 / T1; - } + } - Qsub0 = CoxWL * pParam->BSIM3k1ox * (T1 - T0); + Qsub0 = CoxWL * pParam->BSIM3k1ox * (T1 - T0); dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg); dQsub0_dVd = -T2 * dVgsteff_dVd; - dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + dVgsteff_dVb); AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; - VdsatCV = Vgsteff / AbulkCV; + VdsatCV = Vgsteff / AbulkCV; - V4 = VdsatCV - Vds - DELTA_4; - T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); - VdseffCV = VdsatCV - 0.5 * (V4 + T0); - T1 = 0.5 * (1.0 + V4 / T0); - T2 = DELTA_4 / T0; - T3 = (1.0 - T1 - T2) / AbulkCV; - dVdseffCV_dVg = T3; - dVdseffCV_dVd = T1; - dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; + V4 = VdsatCV - Vds - DELTA_4; + T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); + VdseffCV = VdsatCV - 0.5 * (V4 + T0); + T1 = 0.5 * (1.0 + V4 / T0); + T2 = DELTA_4 / T0; + T3 = (1.0 - T1 - T2) / AbulkCV; + dVdseffCV_dVg = T3; + dVdseffCV_dVd = T1; + dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; /* Added to eliminate non-zero VdseffCV at Vds=0.0 */ if (Vds == 0.0) { VdseffCV = 0.0; @@ -1822,10 +1854,10 @@ for (; model != NULL; model = model->BSIM3nextModel) dVdseffCV_dVb = 0.0; } - T0 = AbulkCV * VdseffCV; + T0 = AbulkCV * VdseffCV; T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20); - T2 = VdseffCV / T1; - T3 = T0 * T2; + T2 = VdseffCV / T1; + T3 = T0 * T2; T4 = (1.0 - 12.0 * T2 * T2 * AbulkCV); T5 = (6.0 * T0 * (4.0 * Vgsteff - T0) / (T1 * T1) - 0.5); @@ -1836,113 +1868,113 @@ for (; model != NULL; model = model->BSIM3nextModel) Cgg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); Cgd1 = CoxWL * T5 * dVdseffCV_dVd + Cgg1 * dVgsteff_dVd; Cgb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cgg1 * dVgsteff_dVb; - Cgg1 *= dVgsteff_dVg; + + Cgg1 * dVgsteff_dVb; + Cgg1 *= dVgsteff_dVg; - T7 = 1.0 - AbulkCV; + T7 = 1.0 - AbulkCV; qbulk = CoxWL * T7 * (0.5 * VdseffCV - T3); - T4 = -T7 * (T4 - 1.0); - T5 = -T7 * T5; - T6 = -(T7 * T6 + (0.5 * VdseffCV - T3)); + T4 = -T7 * (T4 - 1.0); + T5 = -T7 * T5; + T6 = -(T7 * T6 + (0.5 * VdseffCV - T3)); Cbg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); Cbd1 = CoxWL * T5 * dVdseffCV_dVd + Cbg1 * dVgsteff_dVd; Cbb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb; - Cbg1 *= dVgsteff_dVg; + + Cbg1 * dVgsteff_dVb; + Cbg1 *= dVgsteff_dVg; if (model->BSIM3xpart > 0.5) - { /* 0/100 Charge petition model */ - T1 = T1 + T1; + { /* 0/100 Charge petition model */ + T1 = T1 + T1; qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - - T0 * T0 / T1); - T7 = (4.0 * Vgsteff - T0) / (T1 * T1); - T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1)); - T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7); + - T0 * T0 / T1); + T7 = (4.0 * Vgsteff - T0) / (T1 * T1); + T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1)); + T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7); T6 = -(0.25 * VdseffCV - 12.0 * T0 * VdseffCV * T7); Csg = CoxWL * (T4 + T5 * dVdseffCV_dVg); Csd = CoxWL * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; Csb = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb; - Csg *= dVgsteff_dVg; + + Csg * dVgsteff_dVb; + Csg *= dVgsteff_dVg; } - else if (model->BSIM3xpart < 0.5) - { /* 40/60 Charge petition model */ - T1 = T1 / 12.0; - T2 = 0.5 * CoxWL / (T1 * T1); - T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff - * (Vgsteff - 4.0 * T0 / 3.0)) - - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T2 * T3; - T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) - + 0.4 * T0 * T0; - T4 = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 - * Vgsteff - 8.0 * T0 / 3.0) - + 2.0 * T0 * T0 / 3.0); - T5 = (qsrc / T1 + T2 * T7) * AbulkCV; - T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV); + else if (model->BSIM3xpart < 0.5) + { /* 40/60 Charge petition model */ + T1 = T1 / 12.0; + T2 = 0.5 * CoxWL / (T1 * T1); + T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff + * (Vgsteff - 4.0 * T0 / 3.0)) + - 2.0 * T0 * T0 * T0 / 15.0; + qsrc = -T2 * T3; + T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + + 0.4 * T0 * T0; + T4 = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 + * Vgsteff - 8.0 * T0 / 3.0) + + 2.0 * T0 * T0 / 3.0); + T5 = (qsrc / T1 + T2 * T7) * AbulkCV; + T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV); Csg = (T4 + T5 * dVdseffCV_dVg); Csd = T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; Csb = (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb; - Csg *= dVgsteff_dVg; + + Csg * dVgsteff_dVb; + Csg *= dVgsteff_dVg; } - else - { /* 50/50 Charge petition model */ + else + { /* 50/50 Charge petition model */ qsrc = -0.5 * (qgate + qbulk); Csg = -0.5 * (Cgg1 + Cbg1); - Csb = -0.5 * (Cgb1 + Cbb1); - Csd = -0.5 * (Cgd1 + Cbd1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); } - qgate += Qac0 + Qsub0; - qbulk -= (Qac0 + Qsub0); + qgate += Qac0 + Qsub0; + qbulk -= (Qac0 + Qsub0); qdrn = -(qgate + qbulk + qsrc); - Cgg = dQac0_dVg + dQsub0_dVg + Cgg1; - Cgd = dQsub0_dVd + Cgd1; - Cgb = dQac0_dVb + dQsub0_dVb + Cgb1; + Cgg = dQac0_dVg + dQsub0_dVg + Cgg1; + Cgd = dQsub0_dVd + Cgd1; + Cgb = dQac0_dVb + dQsub0_dVb + Cgb1; - Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; - Cbd = Cbd1 - dQsub0_dVd; - Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; + Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; + Cbd = Cbd1 - dQsub0_dVd; + Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; here->BSIM3cggb = Cgg; - here->BSIM3cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3cgdb = Cgd; + here->BSIM3cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3cgdb = Cgd; here->BSIM3cdgb = -(Cgg + Cbg + Csg); - here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3cddb = -(Cgd + Cbd + Csd); + here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3cddb = -(Cgd + Cbd + Csd); here->BSIM3cbgb = Cbg; - here->BSIM3cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3cbdb = Cbd; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; here->BSIM3qinv = qinoi; - } + } /* New Charge-Thickness capMod (CTM) begins */ - else if (model->BSIM3capMod == 3) - { V3 = pParam->BSIM3vfbzb - Vgs_eff + VbseffCV - DELTA_3; - if (pParam->BSIM3vfbzb <= 0.0) - { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * pParam->BSIM3vfbzb); - T2 = -DELTA_3 / T0; - } - else - { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * pParam->BSIM3vfbzb); - T2 = DELTA_3 / T0; - } + else if (model->BSIM3capMod == 3) + { V3 = here->BSIM3vfbzb - Vgs_eff + VbseffCV - DELTA_3; + if (here->BSIM3vfbzb <= 0.0) + { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * here->BSIM3vfbzb); + T2 = -DELTA_3 / T0; + } + else + { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * here->BSIM3vfbzb); + T2 = DELTA_3 / T0; + } - T1 = 0.5 * (1.0 + V3 / T0); - Vfbeff = pParam->BSIM3vfbzb - 0.5 * (V3 + T0); - dVfbeff_dVg = T1 * dVgs_eff_dVg; - dVfbeff_dVb = -T1 * dVbseffCV_dVb; + T1 = 0.5 * (1.0 + V3 / T0); + Vfbeff = here->BSIM3vfbzb - 0.5 * (V3 + T0); + dVfbeff_dVg = T1 * dVgs_eff_dVg; + dVfbeff_dVb = -T1 * dVbseffCV_dVb; Cox = model->BSIM3cox; Tox = 1.0e8 * model->BSIM3tox; - T0 = (Vgs_eff - VbseffCV - pParam->BSIM3vfbzb) / Tox; + T0 = (Vgs_eff - VbseffCV - here->BSIM3vfbzb) / Tox; dT0_dVg = dVgs_eff_dVg / Tox; dT0_dVb = -dVbseffCV_dVb / Tox; @@ -1979,12 +2011,12 @@ for (; model != NULL; model = model->BSIM3nextModel) dCoxeff_dVg *= dTcen_dVg; CoxWLcen = CoxWL * Coxeff / Cox; - Qac0 = CoxWLcen * (Vfbeff - pParam->BSIM3vfbzb); + Qac0 = CoxWLcen * (Vfbeff - here->BSIM3vfbzb); QovCox = Qac0 / Coxeff; dQac0_dVg = CoxWLcen * dVfbeff_dVg + QovCox * dCoxeff_dVg; - dQac0_dVb = CoxWLcen * dVfbeff_dVb - + QovCox * dCoxeff_dVb; + dQac0_dVb = CoxWLcen * dVfbeff_dVb + + QovCox * dCoxeff_dVb; T0 = 0.5 * pParam->BSIM3k1ox; T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; @@ -2009,21 +2041,21 @@ for (; model != NULL; model = model->BSIM3nextModel) dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + dVgsteff_dVb) + QovCox * dCoxeff_dVb; - /* Gate-bias dependent delta Phis begins */ - if (pParam->BSIM3k1ox <= 0.0) - { Denomi = 0.25 * pParam->BSIM3moin * Vtm; + /* Gate-bias dependent delta Phis begins */ + if (pParam->BSIM3k1ox <= 0.0) + { Denomi = 0.25 * pParam->BSIM3moin * Vtm; T0 = 0.5 * pParam->BSIM3sqrtPhi; - } - else - { Denomi = pParam->BSIM3moin * Vtm - * pParam->BSIM3k1ox * pParam->BSIM3k1ox; + } + else + { Denomi = pParam->BSIM3moin * Vtm + * pParam->BSIM3k1ox * pParam->BSIM3k1ox; T0 = pParam->BSIM3k1ox * pParam->BSIM3sqrtPhi; - } + } T1 = 2.0 * T0 + Vgsteff; - DeltaPhi = Vtm * log(1.0 + T1 * Vgsteff / Denomi); - dDeltaPhi_dVg = 2.0 * Vtm * (T1 -T0) / (Denomi + T1 * Vgsteff); - /* End of delta Phis */ + DeltaPhi = Vtm * log(1.0 + T1 * Vgsteff / Denomi); + dDeltaPhi_dVg = 2.0 * Vtm * (T1 -T0) / (Denomi + T1 * Vgsteff); + /* End of delta Phis */ /* VgDP = Vgsteff - DeltaPhi */ T0 = Vgsteff - DeltaPhi - 0.001; @@ -2032,7 +2064,7 @@ for (; model != NULL; model = model->BSIM3nextModel) VgDP = 0.5 * (T0 + T1); dVgDP_dVg = 0.5 * (dT0_dVg + (T0 * dT0_dVg + 0.002) / T1); - T3 = 4.0 * (Vth - pParam->BSIM3vfbzb - pParam->BSIM3phi); + T3 = 4.0 * (Vth - here->BSIM3vfbzb - pParam->BSIM3phi); Tox += Tox; if (T3 >= 0.0) { T0 = (Vgsteff + T3) / Tox; @@ -2054,19 +2086,19 @@ for (; model != NULL; model = model->BSIM3nextModel) dTcen_dVd *= dT0_dVd; dTcen_dVg *= dVgsteff_dVg; - Ccen = EPSSI / Tcen; - T0 = Cox / (Cox + Ccen); - Coxeff = T0 * Ccen; - T1 = -Ccen / Tcen; - dCoxeff_dVg = T0 * T0 * T1; - dCoxeff_dVd = dCoxeff_dVg * dTcen_dVd; - dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; - dCoxeff_dVg *= dTcen_dVg; - CoxWLcen = CoxWL * Coxeff / Cox; + Ccen = EPSSI / Tcen; + T0 = Cox / (Cox + Ccen); + Coxeff = T0 * Ccen; + T1 = -Ccen / Tcen; + dCoxeff_dVg = T0 * T0 * T1; + dCoxeff_dVd = dCoxeff_dVg * dTcen_dVd; + dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; + dCoxeff_dVg *= dTcen_dVg; + CoxWLcen = CoxWL * Coxeff / Cox; - AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; - dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; - VdsatCV = VgDP / AbulkCV; + AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; + VdsatCV = VgDP / AbulkCV; T0 = VdsatCV - Vds - DELTA_4; dT0_dVg = dVgDP_dVg / AbulkCV; dT0_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; @@ -2099,22 +2131,22 @@ for (; model != NULL; model = model->BSIM3nextModel) } T0 = AbulkCV * VdseffCV; - T1 = VgDP; + T1 = VgDP; T2 = 12.0 * (T1 - 0.5 * T0 + 1.0e-20); T3 = T0 / T2; T4 = 1.0 - 12.0 * T3 * T3; T5 = AbulkCV * (6.0 * T0 * (4.0 * T1 - T0) / (T2 * T2) - 0.5); - T6 = T5 * VdseffCV / AbulkCV; + T6 = T5 * VdseffCV / AbulkCV; qgate = qinoi = CoxWLcen * (T1 - T0 * (0.5 - T3)); - QovCox = qgate / Coxeff; - Cgg1 = CoxWLcen * (T4 * dVgDP_dVg - + T5 * dVdseffCV_dVg); - Cgd1 = CoxWLcen * T5 * dVdseffCV_dVd + Cgg1 - * dVgsteff_dVd + QovCox * dCoxeff_dVd; - Cgb1 = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cgg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Cgg1 = Cgg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; + QovCox = qgate / Coxeff; + Cgg1 = CoxWLcen * (T4 * dVgDP_dVg + + T5 * dVdseffCV_dVg); + Cgd1 = CoxWLcen * T5 * dVdseffCV_dVd + Cgg1 + * dVgsteff_dVd + QovCox * dCoxeff_dVd; + Cgb1 = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) + + Cgg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Cgg1 = Cgg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; T7 = 1.0 - AbulkCV; @@ -2124,95 +2156,95 @@ for (; model != NULL; model = model->BSIM3nextModel) T11 = -T7 * T5 / AbulkCV; T12 = -(T9 * T1 / AbulkCV + VdseffCV * (0.5 - T0 / T2)); - qbulk = CoxWLcen * T7 * (0.5 * VdseffCV - T0 * VdseffCV / T2); - QovCox = qbulk / Coxeff; - Cbg1 = CoxWLcen * (T10 + T11 * dVdseffCV_dVg); - Cbd1 = CoxWLcen * T11 * dVdseffCV_dVd + Cbg1 - * dVgsteff_dVd + QovCox * dCoxeff_dVd; - Cbb1 = CoxWLcen * (T11 * dVdseffCV_dVb + T12 * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Cbg1 = Cbg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; + qbulk = CoxWLcen * T7 * (0.5 * VdseffCV - T0 * VdseffCV / T2); + QovCox = qbulk / Coxeff; + Cbg1 = CoxWLcen * (T10 + T11 * dVdseffCV_dVg); + Cbd1 = CoxWLcen * T11 * dVdseffCV_dVd + Cbg1 + * dVgsteff_dVd + QovCox * dCoxeff_dVd; + Cbb1 = CoxWLcen * (T11 * dVdseffCV_dVb + T12 * dAbulkCV_dVb) + + Cbg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Cbg1 = Cbg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; if (model->BSIM3xpart > 0.5) - { /* 0/100 partition */ - qsrc = -CoxWLcen * (T1 / 2.0 + T0 / 4.0 - - 0.5 * T0 * T0 / T2); - QovCox = qsrc / Coxeff; - T2 += T2; - T3 = T2 * T2; - T7 = -(0.25 - 12.0 * T0 * (4.0 * T1 - T0) / T3); - T4 = -(0.5 + 24.0 * T0 * T0 / T3) * dVgDP_dVg; - T5 = T7 * AbulkCV; - T6 = T7 * VdseffCV; + { /* 0/100 partition */ + qsrc = -CoxWLcen * (T1 / 2.0 + T0 / 4.0 + - 0.5 * T0 * T0 / T2); + QovCox = qsrc / Coxeff; + T2 += T2; + T3 = T2 * T2; + T7 = -(0.25 - 12.0 * T0 * (4.0 * T1 - T0) / T3); + T4 = -(0.5 + 24.0 * T0 * T0 / T3) * dVgDP_dVg; + T5 = T7 * AbulkCV; + T6 = T7 * VdseffCV; - Csg = CoxWLcen * (T4 + T5 * dVdseffCV_dVg); - Csd = CoxWLcen * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd - + QovCox * dCoxeff_dVd; - Csb = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; + Csg = CoxWLcen * (T4 + T5 * dVdseffCV_dVg); + Csd = CoxWLcen * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd + + QovCox * dCoxeff_dVd; + Csb = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) + + Csg * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; } - else if (model->BSIM3xpart < 0.5) - { /* 40/60 partition */ - T2 = T2 / 12.0; - T3 = 0.5 * CoxWLcen / (T2 * T2); - T4 = T1 * (2.0 * T0 * T0 / 3.0 + T1 * (T1 - 4.0 + else if (model->BSIM3xpart < 0.5) + { /* 40/60 partition */ + T2 = T2 / 12.0; + T3 = 0.5 * CoxWLcen / (T2 * T2); + T4 = T1 * (2.0 * T0 * T0 / 3.0 + T1 * (T1 - 4.0 * T0 / 3.0)) - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T3 * T4; - QovCox = qsrc / Coxeff; - T8 = 4.0 / 3.0 * T1 * (T1 - T0) + 0.4 * T0 * T0; - T5 = -2.0 * qsrc / T2 - T3 * (T1 * (3.0 * T1 - 8.0 - * T0 / 3.0) + 2.0 * T0 * T0 / 3.0); - T6 = AbulkCV * (qsrc / T2 + T3 * T8); - T7 = T6 * VdseffCV / AbulkCV; + qsrc = -T3 * T4; + QovCox = qsrc / Coxeff; + T8 = 4.0 / 3.0 * T1 * (T1 - T0) + 0.4 * T0 * T0; + T5 = -2.0 * qsrc / T2 - T3 * (T1 * (3.0 * T1 - 8.0 + * T0 / 3.0) + 2.0 * T0 * T0 / 3.0); + T6 = AbulkCV * (qsrc / T2 + T3 * T8); + T7 = T6 * VdseffCV / AbulkCV; - Csg = T5 * dVgDP_dVg + T6 * dVdseffCV_dVg; - Csd = Csg * dVgsteff_dVd + T6 * dVdseffCV_dVd - + QovCox * dCoxeff_dVd; - Csb = Csg * dVgsteff_dVb + T6 * dVdseffCV_dVb - + T7 * dAbulkCV_dVb + QovCox * dCoxeff_dVb; - Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; + Csg = T5 * dVgDP_dVg + T6 * dVdseffCV_dVg; + Csd = Csg * dVgsteff_dVd + T6 * dVdseffCV_dVd + + QovCox * dCoxeff_dVd; + Csb = Csg * dVgsteff_dVb + T6 * dVdseffCV_dVb + + T7 * dAbulkCV_dVb + QovCox * dCoxeff_dVb; + Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; } - else - { /* 50/50 partition */ + else + { /* 50/50 partition */ qsrc = -0.5 * qgate; Csg = -0.5 * Cgg1; - Csd = -0.5 * Cgd1; - Csb = -0.5 * Cgb1; + Csd = -0.5 * Cgd1; + Csb = -0.5 * Cgb1; } - qgate += Qac0 + Qsub0 - qbulk; - qbulk -= (Qac0 + Qsub0); + qgate += Qac0 + Qsub0 - qbulk; + qbulk -= (Qac0 + Qsub0); qdrn = -(qgate + qbulk + qsrc); - Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; - Cbd = Cbd1 - dQsub0_dVd; - Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; + Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; + Cbd = Cbd1 - dQsub0_dVd; + Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; Cgg = Cgg1 - Cbg; Cgd = Cgd1 - Cbd; Cgb = Cgb1 - Cbb; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; here->BSIM3cggb = Cgg; - here->BSIM3cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3cgdb = Cgd; + here->BSIM3cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3cgdb = Cgd; here->BSIM3cdgb = -(Cgg + Cbg + Csg); - here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3cddb = -(Cgd + Cbd + Csd); + here->BSIM3cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3cddb = -(Cgd + Cbd + Csd); here->BSIM3cbgb = Cbg; - here->BSIM3cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3cbdb = Cbd; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; here->BSIM3qinv = -qinoi; - } /* End of CTM */ + } /* End of CTM */ } -finished: - /* Returning Values to Calling Routine */ +finished: + /* Returning Values to Calling Routine */ /* * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE */ @@ -2223,150 +2255,182 @@ finished: here->BSIM3cd = cdrain; if (ChargeComputationNeeded) - { /* charge storage elements + { /* charge storage elements * bulk-drain and bulk-source depletion capacitances * czbd : zero bias drain junction capacitance * czbs : zero bias source junction capacitance * czbdsw: zero bias drain junction sidewall capacitance - along field oxide + along field oxide * czbssw: zero bias source junction sidewall capacitance - along field oxide - * czbdswg: zero bias drain junction sidewall capacitance - along gate side - * czbsswg: zero bias source junction sidewall capacitance - along gate side + along field oxide + * czbdswg: zero bias drain junction sidewall capacitance + along gate side + * czbsswg: zero bias source junction sidewall capacitance + along gate side */ - czbd = model->BSIM3unitAreaTempJctCap * here->BSIM3drainArea; /*bug fix */ - czbs = model->BSIM3unitAreaTempJctCap * here->BSIM3sourceArea; - if (here->BSIM3drainPerimeter < pParam->BSIM3weff) - { - czbdswg = model->BSIM3unitLengthGateSidewallTempJctCap - * here->BSIM3drainPerimeter; - czbdsw = 0.0; - } - else + if (model->BSIM3acmMod == 0) { - czbdsw = model->BSIM3unitLengthSidewallTempJctCap - * (here->BSIM3drainPerimeter - pParam->BSIM3weff); - czbdswg = model->BSIM3unitLengthGateSidewallTempJctCap - * pParam->BSIM3weff; - } - if (here->BSIM3sourcePerimeter < pParam->BSIM3weff) - { - czbssw = 0.0; - czbsswg = model->BSIM3unitLengthGateSidewallTempJctCap - * here->BSIM3sourcePerimeter; - } - else - { - czbssw = model->BSIM3unitLengthSidewallTempJctCap - * (here->BSIM3sourcePerimeter - pParam->BSIM3weff); - czbsswg = model->BSIM3unitLengthGateSidewallTempJctCap - * pParam->BSIM3weff; + czbd = model->BSIM3unitAreaTempJctCap * here->BSIM3drainArea; /*bug fix */ + czbs = model->BSIM3unitAreaTempJctCap * here->BSIM3sourceArea; + if (here->BSIM3drainPerimeter < pParam->BSIM3weff) + { + czbdswg = model->BSIM3unitLengthGateSidewallTempJctCap + * here->BSIM3drainPerimeter; + czbdsw = 0.0; + } + else + { + czbdsw = model->BSIM3unitLengthSidewallTempJctCap + * (here->BSIM3drainPerimeter - pParam->BSIM3weff); + czbdswg = model->BSIM3unitLengthGateSidewallTempJctCap + * pParam->BSIM3weff; + } + if (here->BSIM3sourcePerimeter < pParam->BSIM3weff) + { + czbssw = 0.0; + czbsswg = model->BSIM3unitLengthGateSidewallTempJctCap + * here->BSIM3sourcePerimeter; + } + else + { + czbssw = model->BSIM3unitLengthSidewallTempJctCap + * (here->BSIM3sourcePerimeter - pParam->BSIM3weff); + czbsswg = model->BSIM3unitLengthGateSidewallTempJctCap + * pParam->BSIM3weff; + } + } else { + error = ACM_junctionCapacitances( + model->BSIM3acmMod, + model->BSIM3calcacm, + here->BSIM3geo, + model->BSIM3hdif, + model->BSIM3wmlt, + here->BSIM3w, + model->BSIM3xw, + here->BSIM3drainAreaGiven, + here->BSIM3drainArea, + here->BSIM3drainPerimeterGiven, + here->BSIM3drainPerimeter, + here->BSIM3sourceAreaGiven, + here->BSIM3sourceArea, + here->BSIM3sourcePerimeterGiven, + here->BSIM3sourcePerimeter, + model->BSIM3unitAreaTempJctCap, + model->BSIM3unitLengthSidewallTempJctCap, + model->BSIM3unitLengthGateSidewallJctCap, + &czbd, + &czbdsw, + &czbdswg, + &czbs, + &czbssw, + &czbsswg + ); + if (error) + return(error); } MJ = model->BSIM3bulkJctBotGradingCoeff; MJSW = model->BSIM3bulkJctSideGradingCoeff; - MJSWG = model->BSIM3bulkJctGateSideGradingCoeff; + MJSWG = model->BSIM3bulkJctGateSideGradingCoeff; /* Source Bulk Junction */ - if (vbs == 0.0) - { *(ckt->CKTstate0 + here->BSIM3qbs) = 0.0; + if (vbs == 0.0) + { *(ckt->CKTstate0 + here->BSIM3qbs) = 0.0; here->BSIM3capbs = czbs + czbssw + czbsswg; - } - else if (vbs < 0.0) - { if (czbs > 0.0) - { arg = 1.0 - vbs / model->BSIM3PhiB; - if (MJ == 0.5) + } + else if (vbs < 0.0) + { if (czbs > 0.0) + { arg = 1.0 - vbs / model->BSIM3PhiB; + if (MJ == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJ * log(arg)); - *(ckt->CKTstate0 + here->BSIM3qbs) = model->BSIM3PhiB * czbs - * (1.0 - arg * sarg) / (1.0 - MJ); - here->BSIM3capbs = czbs * sarg; - } - else - { *(ckt->CKTstate0 + here->BSIM3qbs) = 0.0; - here->BSIM3capbs = 0.0; - } - if (czbssw > 0.0) - { arg = 1.0 - vbs / model->BSIM3PhiBSW; - if (MJSW == 0.5) + *(ckt->CKTstate0 + here->BSIM3qbs) = model->BSIM3PhiB * czbs + * (1.0 - arg * sarg) / (1.0 - MJ); + here->BSIM3capbs = czbs * sarg; + } + else + { *(ckt->CKTstate0 + here->BSIM3qbs) = 0.0; + here->BSIM3capbs = 0.0; + } + if (czbssw > 0.0) + { arg = 1.0 - vbs / model->BSIM3PhiBSW; + if (MJSW == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSW * log(arg)); *(ckt->CKTstate0 + here->BSIM3qbs) += model->BSIM3PhiBSW * czbssw - * (1.0 - arg * sarg) / (1.0 - MJSW); + * (1.0 - arg * sarg) / (1.0 - MJSW); here->BSIM3capbs += czbssw * sarg; - } - if (czbsswg > 0.0) - { arg = 1.0 - vbs / model->BSIM3PhiBSWG; - if (MJSWG == 0.5) + } + if (czbsswg > 0.0) + { arg = 1.0 - vbs / model->BSIM3PhiBSWG; + if (MJSWG == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSWG * log(arg)); *(ckt->CKTstate0 + here->BSIM3qbs) += model->BSIM3PhiBSWG * czbsswg - * (1.0 - arg * sarg) / (1.0 - MJSWG); + * (1.0 - arg * sarg) / (1.0 - MJSWG); here->BSIM3capbs += czbsswg * sarg; - } + } } - else - { T0 = czbs + czbssw + czbsswg; - T1 = vbs * (czbs * MJ / model->BSIM3PhiB + czbssw * MJSW - / model->BSIM3PhiBSW + czbsswg * MJSWG / model->BSIM3PhiBSWG); + else + { T0 = czbs + czbssw + czbsswg; + T1 = vbs * (czbs * MJ / model->BSIM3PhiB + czbssw * MJSW + / model->BSIM3PhiBSW + czbsswg * MJSWG / model->BSIM3PhiBSWG); *(ckt->CKTstate0 + here->BSIM3qbs) = vbs * (T0 + 0.5 * T1); here->BSIM3capbs = T0 + T1; } /* Drain Bulk Junction */ - if (vbd == 0.0) - { *(ckt->CKTstate0 + here->BSIM3qbd) = 0.0; + if (vbd == 0.0) + { *(ckt->CKTstate0 + here->BSIM3qbd) = 0.0; here->BSIM3capbd = czbd + czbdsw + czbdswg; - } - else if (vbd < 0.0) - { if (czbd > 0.0) - { arg = 1.0 - vbd / model->BSIM3PhiB; - if (MJ == 0.5) + } + else if (vbd < 0.0) + { if (czbd > 0.0) + { arg = 1.0 - vbd / model->BSIM3PhiB; + if (MJ == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJ * log(arg)); - *(ckt->CKTstate0 + here->BSIM3qbd) = model->BSIM3PhiB * czbd - * (1.0 - arg * sarg) / (1.0 - MJ); + *(ckt->CKTstate0 + here->BSIM3qbd) = model->BSIM3PhiB * czbd + * (1.0 - arg * sarg) / (1.0 - MJ); here->BSIM3capbd = czbd * sarg; - } - else - { *(ckt->CKTstate0 + here->BSIM3qbd) = 0.0; + } + else + { *(ckt->CKTstate0 + here->BSIM3qbd) = 0.0; here->BSIM3capbd = 0.0; - } - if (czbdsw > 0.0) - { arg = 1.0 - vbd / model->BSIM3PhiBSW; - if (MJSW == 0.5) + } + if (czbdsw > 0.0) + { arg = 1.0 - vbd / model->BSIM3PhiBSW; + if (MJSW == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSW * log(arg)); - *(ckt->CKTstate0 + here->BSIM3qbd) += model->BSIM3PhiBSW * czbdsw - * (1.0 - arg * sarg) / (1.0 - MJSW); + *(ckt->CKTstate0 + here->BSIM3qbd) += model->BSIM3PhiBSW * czbdsw + * (1.0 - arg * sarg) / (1.0 - MJSW); here->BSIM3capbd += czbdsw * sarg; - } - if (czbdswg > 0.0) - { arg = 1.0 - vbd / model->BSIM3PhiBSWG; - if (MJSWG == 0.5) + } + if (czbdswg > 0.0) + { arg = 1.0 - vbd / model->BSIM3PhiBSWG; + if (MJSWG == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSWG * log(arg)); *(ckt->CKTstate0 + here->BSIM3qbd) += model->BSIM3PhiBSWG * czbdswg - * (1.0 - arg * sarg) / (1.0 - MJSWG); + * (1.0 - arg * sarg) / (1.0 - MJSWG); here->BSIM3capbd += czbdswg * sarg; - } + } } - else - { T0 = czbd + czbdsw + czbdswg; + else + { T0 = czbd + czbdsw + czbdswg; T1 = vbd * (czbd * MJ / model->BSIM3PhiB + czbdsw * MJSW / model->BSIM3PhiBSW + czbdswg * MJSWG / model->BSIM3PhiBSWG); *(ckt->CKTstate0 + here->BSIM3qbd) = vbd * (T0 + 0.5 * T1); - here->BSIM3capbd = T0 + T1; + here->BSIM3capbd = T0 + T1; } } @@ -2374,11 +2438,11 @@ finished: * check convergence */ if ((here->BSIM3off == 0) || (!(ckt->CKTmode & MODEINITFIX))) - { if (Check == 1) - { ckt->CKTnoncon++; + { if (Check == 1) + { ckt->CKTnoncon++; #ifndef NEWCONV - } - else + } + else { if (here->BSIM3mode >= 0) { Idtot = here->BSIM3cd + here->BSIM3csub - here->BSIM3cbd; } @@ -2395,7 +2459,7 @@ finished: tol = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + ckt->CKTabstol; if (fabs(cbhat - Ibtot) > tol) - { ckt->CKTnoncon++; + { ckt->CKTnoncon++; } } #endif /* NEWCONV */ @@ -2410,7 +2474,7 @@ finished: /* bulk and channel charge plus overlaps */ if (!ChargeComputationNeeded) - goto line850; + goto line850; #ifndef NOBYPASS line755: #endif @@ -2424,74 +2488,74 @@ line755: here->BSIM3cqbb = -(here->BSIM3cqgb + here->BSIM3cqdb + here->BSIM3cqsb); - gtau_drift = fabs(pParam->BSIM3tconst * qcheq) * ScalingFactor; + gtau_drift = fabs(here->BSIM3tconst * qcheq) * ScalingFactor; T0 = pParam->BSIM3leffCV * pParam->BSIM3leffCV; - gtau_diff = 16.0 * pParam->BSIM3u0temp * model->BSIM3vtm / T0 - * ScalingFactor; + gtau_diff = 16.0 * here->BSIM3u0temp * model->BSIM3vtm / T0 + * ScalingFactor; here->BSIM3gtau = gtau_drift + gtau_diff; if (here->BSIM3acnqsMod) here->BSIM3taunet = ScalingFactor / here->BSIM3gtau; } - if (model->BSIM3capMod == 0) /* code merge -JX */ - { - cgdo = pParam->BSIM3cgdo; - qgdo = pParam->BSIM3cgdo * vgd; - cgso = pParam->BSIM3cgso; - qgso = pParam->BSIM3cgso * vgs; - } - else if (model->BSIM3capMod == 1) - { if (vgd < 0.0) - { T1 = sqrt(1.0 - 4.0 * vgd / pParam->BSIM3ckappa); - cgdo = pParam->BSIM3cgdo + pParam->BSIM3weffCV - * pParam->BSIM3cgdl / T1; - qgdo = pParam->BSIM3cgdo * vgd - pParam->BSIM3weffCV * 0.5 - * pParam->BSIM3cgdl * pParam->BSIM3ckappa * (T1 - 1.0); - } - else - { cgdo = pParam->BSIM3cgdo + pParam->BSIM3weffCV - * pParam->BSIM3cgdl; - qgdo = (pParam->BSIM3weffCV * pParam->BSIM3cgdl - + pParam->BSIM3cgdo) * vgd; - } + if (model->BSIM3capMod == 0) /* code merge -JX */ + { + cgdo = pParam->BSIM3cgdo; + qgdo = pParam->BSIM3cgdo * vgd; + cgso = pParam->BSIM3cgso; + qgso = pParam->BSIM3cgso * vgs; + } + else if (model->BSIM3capMod == 1) + { if (vgd < 0.0) + { T1 = sqrt(1.0 - 4.0 * vgd / pParam->BSIM3ckappa); + cgdo = pParam->BSIM3cgdo + pParam->BSIM3weffCV + * pParam->BSIM3cgdl / T1; + qgdo = pParam->BSIM3cgdo * vgd - pParam->BSIM3weffCV * 0.5 + * pParam->BSIM3cgdl * pParam->BSIM3ckappa * (T1 - 1.0); + } + else + { cgdo = pParam->BSIM3cgdo + pParam->BSIM3weffCV + * pParam->BSIM3cgdl; + qgdo = (pParam->BSIM3weffCV * pParam->BSIM3cgdl + + pParam->BSIM3cgdo) * vgd; + } - if (vgs < 0.0) - { T1 = sqrt(1.0 - 4.0 * vgs / pParam->BSIM3ckappa); - cgso = pParam->BSIM3cgso + pParam->BSIM3weffCV - * pParam->BSIM3cgsl / T1; - qgso = pParam->BSIM3cgso * vgs - pParam->BSIM3weffCV * 0.5 - * pParam->BSIM3cgsl * pParam->BSIM3ckappa * (T1 - 1.0); - } - else - { cgso = pParam->BSIM3cgso + pParam->BSIM3weffCV - * pParam->BSIM3cgsl; - qgso = (pParam->BSIM3weffCV * pParam->BSIM3cgsl - + pParam->BSIM3cgso) * vgs; - } - } - else - { T0 = vgd + DELTA_1; - T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); - T2 = 0.5 * (T0 - T1); + if (vgs < 0.0) + { T1 = sqrt(1.0 - 4.0 * vgs / pParam->BSIM3ckappa); + cgso = pParam->BSIM3cgso + pParam->BSIM3weffCV + * pParam->BSIM3cgsl / T1; + qgso = pParam->BSIM3cgso * vgs - pParam->BSIM3weffCV * 0.5 + * pParam->BSIM3cgsl * pParam->BSIM3ckappa * (T1 - 1.0); + } + else + { cgso = pParam->BSIM3cgso + pParam->BSIM3weffCV + * pParam->BSIM3cgsl; + qgso = (pParam->BSIM3weffCV * pParam->BSIM3cgsl + + pParam->BSIM3cgso) * vgs; + } + } + else + { T0 = vgd + DELTA_1; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); + T2 = 0.5 * (T0 - T1); - T3 = pParam->BSIM3weffCV * pParam->BSIM3cgdl; - T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3ckappa); - cgdo = pParam->BSIM3cgdo + T3 - T3 * (1.0 - 1.0 / T4) - * (0.5 - 0.5 * T0 / T1); - qgdo = (pParam->BSIM3cgdo + T3) * vgd - T3 * (T2 - + 0.5 * pParam->BSIM3ckappa * (T4 - 1.0)); + T3 = pParam->BSIM3weffCV * pParam->BSIM3cgdl; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3ckappa); + cgdo = pParam->BSIM3cgdo + T3 - T3 * (1.0 - 1.0 / T4) + * (0.5 - 0.5 * T0 / T1); + qgdo = (pParam->BSIM3cgdo + T3) * vgd - T3 * (T2 + + 0.5 * pParam->BSIM3ckappa * (T4 - 1.0)); - T0 = vgs + DELTA_1; - T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); - T2 = 0.5 * (T0 - T1); - T3 = pParam->BSIM3weffCV * pParam->BSIM3cgsl; - T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3ckappa); - cgso = pParam->BSIM3cgso + T3 - T3 * (1.0 - 1.0 / T4) - * (0.5 - 0.5 * T0 / T1); - qgso = (pParam->BSIM3cgso + T3) * vgs - T3 * (T2 - + 0.5 * pParam->BSIM3ckappa * (T4 - 1.0)); - } + T0 = vgs + DELTA_1; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); + T2 = 0.5 * (T0 - T1); + T3 = pParam->BSIM3weffCV * pParam->BSIM3cgsl; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3ckappa); + cgso = pParam->BSIM3cgso + T3 - T3 * (1.0 - 1.0 / T4) + * (0.5 - 0.5 * T0 / T1); + qgso = (pParam->BSIM3cgso + T3) * vgs - T3 * (T2 + + 0.5 * pParam->BSIM3ckappa * (T4 - 1.0)); + } here->BSIM3cgdo = cgdo; here->BSIM3cgso = cgso; @@ -2528,21 +2592,21 @@ line755: qsrc = -(qgate + qbulk + qdrn); ggtg = ggtd = ggtb = ggts = 0.0; - sxpart = 0.6; + sxpart = 0.6; dxpart = 0.4; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; } else { if (qcheq > 0.0) - T0 = pParam->BSIM3tconst * qdef * ScalingFactor; + T0 = here->BSIM3tconst * qdef * ScalingFactor; else - T0 = -pParam->BSIM3tconst * qdef * ScalingFactor; + T0 = -here->BSIM3tconst * qdef * ScalingFactor; ggtg = here->BSIM3gtg = T0 * here->BSIM3cqgb; ggtd = here->BSIM3gtd = T0 * here->BSIM3cqdb; ggts = here->BSIM3gts = T0 * here->BSIM3cqsb; ggtb = here->BSIM3gtb = T0 * here->BSIM3cqbb; - gqdef = ScalingFactor * ag0; + gqdef = ScalingFactor * ag0; gcqgb = here->BSIM3cqgb * ag0; gcqdb = here->BSIM3cqdb * ag0; @@ -2565,44 +2629,44 @@ line755: gcbdb = -here->BSIM3capbd * ag0; gcbsb = -here->BSIM3capbs * ag0; - CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV * pParam->BSIM3leffCV; - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3xpart < 0.5) - { dxpart = 0.4; - } - else if (model->BSIM3xpart > 0.5) - { dxpart = 0.0; - } - else - { dxpart = 0.5; - } - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - } - else - { dxpart = qdrn / qcheq; - Cdd = here->BSIM3cddb; - Csd = -(here->BSIM3cgdb + here->BSIM3cddb - + here->BSIM3cbdb); - ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; - Cdg = here->BSIM3cdgb; - Csg = -(here->BSIM3cggb + here->BSIM3cdgb - + here->BSIM3cbgb); - ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = qdrn / qcheq; + Cdd = here->BSIM3cddb; + Csd = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3cdgb; + Csg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; - Cds = here->BSIM3cdsb; - Css = -(here->BSIM3cgsb + here->BSIM3cdsb - + here->BSIM3cbsb); - ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + Cds = here->BSIM3cdsb; + Css = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); - } - sxpart = 1.0 - dxpart; - dsxpart_dVd = -ddxpart_dVd; - dsxpart_dVg = -ddxpart_dVg; - dsxpart_dVs = -ddxpart_dVs; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); qgd = qgdo; qgs = qgso; @@ -2644,21 +2708,21 @@ line755: qdrn = -(qgate + qbulk + qsrc); ggtg = ggtd = ggtb = ggts = 0.0; - sxpart = 0.4; + sxpart = 0.4; dxpart = 0.6; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; } else { if (qcheq > 0.0) - T0 = pParam->BSIM3tconst * qdef * ScalingFactor; + T0 = here->BSIM3tconst * qdef * ScalingFactor; else - T0 = -pParam->BSIM3tconst * qdef * ScalingFactor; + T0 = -here->BSIM3tconst * qdef * ScalingFactor; ggtg = here->BSIM3gtg = T0 * here->BSIM3cqgb; ggts = here->BSIM3gtd = T0 * here->BSIM3cqdb; ggtd = here->BSIM3gts = T0 * here->BSIM3cqsb; ggtb = here->BSIM3gtb = T0 * here->BSIM3cqbb; - gqdef = ScalingFactor * ag0; + gqdef = ScalingFactor * ag0; gcqgb = here->BSIM3cqgb * ag0; gcqdb = here->BSIM3cqsb * ag0; @@ -2681,44 +2745,44 @@ line755: gcbdb = -here->BSIM3capbd * ag0; gcbsb = -here->BSIM3capbs * ag0; - CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV * pParam->BSIM3leffCV; - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3xpart < 0.5) - { sxpart = 0.4; - } - else if (model->BSIM3xpart > 0.5) - { sxpart = 0.0; - } - else - { sxpart = 0.5; - } - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { sxpart = qdrn / qcheq; - Css = here->BSIM3cddb; - Cds = -(here->BSIM3cgdb + here->BSIM3cddb - + here->BSIM3cbdb); - dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; - Csg = here->BSIM3cdgb; - Cdg = -(here->BSIM3cggb + here->BSIM3cdgb - + here->BSIM3cbgb); - dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = qdrn / qcheq; + Css = here->BSIM3cddb; + Cds = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3cdgb; + Cdg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; - Csd = here->BSIM3cdsb; - Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb - + here->BSIM3cbsb); - dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + Csd = here->BSIM3cdsb; + Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); - } - dxpart = 1.0 - sxpart; - ddxpart_dVd = -dsxpart_dVd; - ddxpart_dVg = -dsxpart_dVg; - ddxpart_dVs = -dsxpart_dVs; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); qgd = qgdo; qgs = qgso; @@ -2730,7 +2794,8 @@ line755: } } - cqdef = cqcheq = 0.0; + cqdef = cqdef_fvk = cqcheq = cqcheq_fvk = 0.0; + if (ByPass) goto line860; *(ckt->CKTstate0 + here->BSIM3qg) = qgate; @@ -2789,29 +2854,29 @@ line755: line850: /* initialize to zero charge conductance and current */ - ceqqg = ceqqb = ceqqd = 0.0; - cqcheq = cqdef = 0.0; + ceqqg = ceqqg_fvk = ceqqg_SnodePrime_fvk = ceqqb = ceqqb_fvk = ceqqb_SnodePrime_fvk = ceqqd = ceqqd_fvk = ceqqd_SnodePrime_fvk = 0.0; + cqcheq = cqcheq_fvk = cqdef = cqdef_fvk = 0.0; gcdgb = gcddb = gcdsb = 0.0; gcsgb = gcsdb = gcssb = 0.0; gcggb = gcgdb = gcgsb = 0.0; gcbgb = gcbdb = gcbsb = 0.0; - gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; + gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; ggtg = ggtd = ggtb = ggts = 0.0; sxpart = (1.0 - (dxpart = (here->BSIM3mode > 0) ? 0.4 : 0.6)); - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; if (here->BSIM3nqsMod) - here->BSIM3gtau = 16.0 * pParam->BSIM3u0temp * model->BSIM3vtm + here->BSIM3gtau = 16.0 * here->BSIM3u0temp * model->BSIM3vtm / pParam->BSIM3leffCV / pParam->BSIM3leffCV - * ScalingFactor; - else + * ScalingFactor; + else here->BSIM3gtau = 0.0; goto line900; - + line860: /* evaluate equivalent charge current */ @@ -2820,18 +2885,26 @@ line860: cqdrn = *(ckt->CKTstate0 + here->BSIM3cqd); ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs; + ceqqg_fvk = cqgate ; + ceqqg_SnodePrime_fvk = ceqqg ; ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs; + ceqqb_fvk = cqbulk ; + ceqqb_SnodePrime_fvk = ceqqb ; ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs; + ceqqd_fvk = cqdrn ; + ceqqd_SnodePrime_fvk = ceqqd ; if (here->BSIM3nqsMod) { T0 = ggtg * vgb - ggtd * vbd - ggts * vbs; ceqqg += T0; - T1 = qdef * here->BSIM3gtau; + T1 = qdef * here->BSIM3gtau; ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd - * vbd - ddxpart_dVs * vbs); + * vbd - ddxpart_dVs * vbs); cqdef = *(ckt->CKTstate0 + here->BSIM3cqcdump) - gqdef * qdef; + cqdef_fvk = *(ckt->CKTstate0 + here->BSIM3cqcdump) ; cqcheq = *(ckt->CKTstate0 + here->BSIM3cqcheq) - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0; + cqcheq_fvk = *(ckt->CKTstate0 + here->BSIM3cqcheq) ; } if (ckt->CKTmode & MODEINITTRAN) @@ -2856,17 +2929,18 @@ line860: line900: if (here->BSIM3mode >= 0) - { Gm = here->BSIM3gm; + { Gm = here->BSIM3gm; Gmbs = here->BSIM3gmbs; FwdSum = Gm + Gmbs; RevSum = 0.0; cdreq = model->BSIM3type * (cdrain - here->BSIM3gds * vds - Gm * vgs - Gmbs * vbs); - + cdreq_fvk = model->BSIM3type * cdrain ; ceqbd = -model->BSIM3type * (here->BSIM3csub - here->BSIM3gbds * vds - here->BSIM3gbgs * vgs - here->BSIM3gbbs * vbs); - ceqbs = 0.0; + ceqbd_fvk = - (model->BSIM3type * here->BSIM3csub) ; + ceqbs = ceqbs_fvk = 0.0; gbbdp = -here->BSIM3gbds; gbbsp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); @@ -2881,18 +2955,19 @@ line900: gbspb = 0.0; gbspsp = 0.0; } - else - { Gm = -here->BSIM3gm; + else + { Gm = -here->BSIM3gm; Gmbs = -here->BSIM3gmbs; FwdSum = 0.0; RevSum = -(Gm + Gmbs); cdreq = -model->BSIM3type * (cdrain + here->BSIM3gds * vds + Gm * vgd + Gmbs * vbd); - + cdreq_fvk = - (model->BSIM3type * cdrain) ; ceqbs = -model->BSIM3type * (here->BSIM3csub + here->BSIM3gbds * vds - here->BSIM3gbgs * vgd - here->BSIM3gbbs * vbd); - ceqbd = 0.0; + ceqbs_fvk = - (model->BSIM3type * here->BSIM3csub) ; + ceqbd = ceqbd_fvk = 0.0; gbbsp = -here->BSIM3gbds; gbbdp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); @@ -2910,7 +2985,9 @@ line900: if (model->BSIM3type > 0) { ceqbs += (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbs_fvk += here->BSIM3cbs ; ceqbd += (here->BSIM3cbd - here->BSIM3gbd * vbd); + ceqbd_fvk += here->BSIM3cbd ; /* ceqqg = ceqqg; ceqqb = ceqqb; @@ -2921,12 +2998,22 @@ line900: } else { ceqbs -= (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbs_fvk -= here->BSIM3cbs ; ceqbd -= (here->BSIM3cbd - here->BSIM3gbd * vbd); + ceqbd_fvk -= here->BSIM3cbd ; ceqqg = -ceqqg; + ceqqg_fvk = - ceqqg_fvk ; + ceqqg_SnodePrime_fvk = - ceqqg_SnodePrime_fvk ; ceqqb = -ceqqb; + ceqqb_fvk = - ceqqb_fvk ; + ceqqb_SnodePrime_fvk = - ceqqb_SnodePrime_fvk ; ceqqd = -ceqqd; + ceqqd_fvk = - ceqqd_fvk ; + ceqqd_SnodePrime_fvk = - ceqqd_SnodePrime_fvk ; cqdef = -cqdef; + cqdef_fvk = - cqdef_fvk ; cqcheq = -cqcheq; + cqcheq_fvk = - cqcheq_fvk ; } m = here->BSIM3m; @@ -2935,7 +3022,7 @@ line900: here->BSIM3rhsB = m * (ceqbs + ceqbd + ceqqb); here->BSIM3rhsD = m * (ceqbd - cdreq - ceqqd); here->BSIM3rhsS = m * (cdreq + ceqbs + ceqqg - + ceqqb + ceqqd); + + ceqqb + ceqqd); if (here->BSIM3nqsMod) here->BSIM3rhsQ = m * (cqcheq - cqdef); #else @@ -2943,7 +3030,7 @@ line900: (*(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)); + + ceqqb + ceqqd)); if (here->BSIM3nqsMod) *(ckt->CKTrhs + here->BSIM3qNode) += m * (cqcheq - cqdef); #endif @@ -2951,7 +3038,7 @@ line900: * load y matrix */ - T1 = qdef * here->BSIM3gtau; + T1 = qdef * here->BSIM3gtau; #ifdef USE_OMP here->BSIM3DdPt = m * here->BSIM3drainConductance; here->BSIM3GgPt = m * (gcggb - ggtg); @@ -2960,12 +3047,12 @@ line900: - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs); here->BSIM3DPdpPt = m * (here->BSIM3drainConductance + here->BSIM3gds + here->BSIM3gbd - + RevSum + gcddb + dxpart * ggtd - + T1 * ddxpart_dVd + gbdpdp); + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp); here->BSIM3SPspPt = m * (here->BSIM3sourceConductance + here->BSIM3gds + here->BSIM3gbs + FwdSum + gcssb + sxpart * ggts - + T1 * dsxpart_dVs + gbspsp); + + T1 * dsxpart_dVs + gbspsp); here->BSIM3DdpPt = m * here->BSIM3drainConductance; here->BSIM3GbPt = m * (gcggb + gcgdb + gcgsb + ggtb); here->BSIM3GdpPt = m * (gcgdb - ggtd); @@ -2975,19 +3062,19 @@ line900: here->BSIM3BdpPt = m * (gcbdb - here->BSIM3gbd + gbbdp); here->BSIM3BspPt = m * (gcbsb - here->BSIM3gbs + gbbsp); here->BSIM3DPdPt = m * here->BSIM3drainConductance; - here->BSIM3DPgPt = m * (Gm + gcdgb + dxpart * ggtg - + T1 * ddxpart_dVg + gbdpg); + here->BSIM3DPgPt = m * (Gm + gcdgb + dxpart * ggtg + + T1 * ddxpart_dVg + gbdpg); here->BSIM3DPbPt = m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + gcdsb - dxpart * ggtb - - T1 * ddxpart_dVb - gbdpb); + - T1 * ddxpart_dVb - gbdpb); here->BSIM3DPspPt = m * (here->BSIM3gds + FwdSum - gcdsb - - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp); - here->BSIM3SPgPt = m * (gcsgb - Gm + sxpart * ggtg - + T1 * dsxpart_dVg + gbspg); + - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp); + here->BSIM3SPgPt = m * (gcsgb - Gm + sxpart * ggtg + + T1 * dsxpart_dVg + gbspg); here->BSIM3SPsPt = m * here->BSIM3sourceConductance; here->BSIM3SPbPt = m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + gcssb - sxpart * ggtb - - T1 * dsxpart_dVb - gbspb); + - T1 * dsxpart_dVb - gbspb); here->BSIM3SPdpPt = m * (here->BSIM3gds + RevSum - gcsdb - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp); @@ -3011,12 +3098,12 @@ line900: - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs)); (*(here->BSIM3DPdpPtr) += m * (here->BSIM3drainConductance + here->BSIM3gds + here->BSIM3gbd - + RevSum + gcddb + dxpart * ggtd - + T1 * ddxpart_dVd + gbdpdp)); + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp)); (*(here->BSIM3SPspPtr) += m * (here->BSIM3sourceConductance + here->BSIM3gds + here->BSIM3gbs + FwdSum + gcssb + sxpart * ggts - + T1 * dsxpart_dVs + gbspsp)); + + T1 * dsxpart_dVs + gbspsp)); (*(here->BSIM3DdpPtr) -= m * here->BSIM3drainConductance); (*(here->BSIM3GbPtr) -= m * (gcggb + gcgdb + gcgsb + ggtb)); (*(here->BSIM3GdpPtr) += m * (gcgdb - ggtd)); @@ -3026,19 +3113,19 @@ line900: (*(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->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)); + - 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)); + - 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)); + - T1 * dsxpart_dVb - gbspb)); (*(here->BSIM3SPdpPtr) -= m * (here->BSIM3gds + RevSum - gcsdb - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); @@ -3054,6 +3141,93 @@ line900: *(here->BSIM3QspPtr) += m * (ggts - gcqsb); *(here->BSIM3QbPtr) += m * (ggtb - gcqbb); } + +#ifdef KIRCHHOFF +/////////////////////////////////////////////////////////////////////////////////// +/* + *(ckt->CKTfvk + here->BSIM3gNode) += m * ceqqg ; + *(ckt->CKTfvk + here->BSIM3bNode) += m * (ceqbs + ceqbd + ceqqb) ; + *(ckt->CKTfvk + here->BSIM3dNodePrime) -= m * (ceqbd - cdreq - ceqqd) ; + *(ckt->CKTfvk + here->BSIM3sNodePrime) -= m * (cdreq + ceqbs + ceqqg + ceqqb + ceqqd) ; + + + *(ckt->CKTfvk+here->BSIM3dNode) += m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNode) ; + *(ckt->CKTfvk+here->BSIM3gNode) += m * (gcggb - ggtg) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3sNode) += m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNode) ; + *(ckt->CKTfvk+here->BSIM3bNode) += m * (here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) += m * (here->BSIM3drainConductance + here->BSIM3gds + here->BSIM3gbd + RevSum + gcddb + + dxpart * ggtd + T1 * ddxpart_dVd + gbdpdp) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) += m * (here->BSIM3sourceConductance + here->BSIM3gds + here->BSIM3gbs + FwdSum + gcssb + + sxpart * ggts + T1 * dsxpart_dVs + gbspsp) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3dNode) -= m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3gNode) -= m * (gcggb + gcgdb + gcgsb + ggtb) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3gNode) += m * (gcgdb - ggtd) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3gNode) += m * (gcgsb - ggts) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNode) -= m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3bNode) += m * (gcbgb - here->BSIM3gbgs) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3bNode) += m * (gcbdb - here->BSIM3gbd + gbbdp) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3bNode) += m * (gcbsb - here->BSIM3gbs + gbbsp) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) += m * (Gm + gcdgb + dxpart * ggtg + T1 * ddxpart_dVg + gbdpg) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + gcdsb - dxpart * ggtb + - T1 * ddxpart_dVb - gbdpb) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * (here->BSIM3gds + FwdSum - gcdsb - dxpart * ggts + - T1 * ddxpart_dVs - gbdpsp) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) += m * (gcsgb - Gm + sxpart * ggtg + T1 * dsxpart_dVg + gbspg) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * (here->BSIM3gds + RevSum - gcsdb - sxpart * ggtd + - T1 * dsxpart_dVd - gbspdp) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; +*/ + + + /* KCL verification - Dynamic Part */ + *(ckt->CKTfvk+here->BSIM3gNode) += m * ceqqg_fvk ; + *(ckt->CKTfvk+here->BSIM3bNode) += m * (ceqbs_fvk + ceqbd_fvk + ceqqb_fvk) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * (ceqbd_fvk - cdreq_fvk - ceqqd_fvk) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * (cdreq_fvk + ceqbs_fvk + ceqqg_SnodePrime_fvk + ceqqb_SnodePrime_fvk + ceqqd_SnodePrime_fvk) ; + if (here->BSIM3nqsMod) + *(ckt->CKTfvk+here->BSIM3qNode) -= m * (cqcheq_fvk - cqdef_fvk) ; + + + /* KCL verification - Linear and Static Part */ + *(ckt->CKTfvk+here->BSIM3dNode) += m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNode) ; + *(ckt->CKTfvk+here->BSIM3sNode) += m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) += m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) += m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3dNode) -= m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNode) -= m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * here->BSIM3drainConductance * *(ckt->CKTrhsOld+here->BSIM3dNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * here->BSIM3sourceConductance * *(ckt->CKTrhsOld+here->BSIM3sNode) ; + + if (here->BSIM3nqsMod) //DA RIVEDERE + { + *(here->BSIM3QqPtr) += m * (gqdef + here->BSIM3gtau); + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + } + + + /* KCL verification - Linear and Dynamic Part ??? */ + *(ckt->CKTfvk+here->BSIM3gNode) -= m * ggtg * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3gNode) -= m * ggtb * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3gNode) -= m * ggtd * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3gNode) -= m * ggts * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + + *(ckt->CKTfvk+here->BSIM3dNodePrime) += m * (dxpart * ggtd + T1 * ddxpart_dVd) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) += m * (dxpart * ggtg + T1 * ddxpart_dVg) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * (- dxpart * ggtb - T1 * ddxpart_dVb) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3dNodePrime) -= m * (- dxpart * ggts - T1 * ddxpart_dVs) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + + *(ckt->CKTfvk+here->BSIM3sNodePrime) += m * (gcssb + sxpart * ggts + T1 * dsxpart_dVs) * *(ckt->CKTrhsOld+here->BSIM3sNodePrime) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) += m * (gcsgb + sxpart * ggtg + T1 * dsxpart_dVg) * *(ckt->CKTrhsOld+here->BSIM3gNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * (gcsgb + gcsdb + gcssb - sxpart * ggtb - T1 * dsxpart_dVb) * *(ckt->CKTrhsOld+here->BSIM3bNode) ; + *(ckt->CKTfvk+here->BSIM3sNodePrime) -= m * (- gcsdb - sxpart * ggtd - T1 * dsxpart_dVd) * *(ckt->CKTrhsOld+here->BSIM3dNodePrime) ; +#endif + #endif line1000: ; #ifndef USE_OMP diff --git a/src/spicelib/devices/bsim3/b3mask.c b/src/spicelib/devices/bsim3/b3mask.c index c90e15aec..3ca862033 100644 --- a/src/spicelib/devices/bsim3/b3mask.c +++ b/src/spicelib/devices/bsim3/b3mask.c @@ -43,9 +43,18 @@ IFvalue *value) case BSIM3_MOD_NOIMOD: value->iValue = model->BSIM3noiMod; return(OK); + case BSIM3_MOD_NQSMOD: + value->iValue = model->BSIM3nqsMod; + return(OK); case BSIM3_MOD_ACNQSMOD: value->iValue = model->BSIM3acnqsMod; return(OK); + case BSIM3_MOD_ACMMOD: + value->iValue = model->BSIM3acmMod; + return(OK); + case BSIM3_MOD_CALCACM: + value->iValue = model->BSIM3calcacm; + return(OK); case BSIM3_MOD_VERSION : value->sValue = model->BSIM3version; return(OK); @@ -337,6 +346,32 @@ IFvalue *value) value->rValue = model->BSIM3tpbswg; return(OK); + /* ACM model */ + case BSIM3_MOD_HDIF: + value->rValue = model->BSIM3hdif; + return(OK); + case BSIM3_MOD_LDIF: + value->rValue = model->BSIM3ldif; + return(OK); + case BSIM3_MOD_LD: + value->rValue = model->BSIM3ld; + return(OK); + case BSIM3_MOD_RD: + value->rValue = model->BSIM3rd; + return(OK); + case BSIM3_MOD_RS: + value->rValue = model->BSIM3rs; + return(OK); + case BSIM3_MOD_RDC: + value->rValue = model->BSIM3rdc; + return(OK); + case BSIM3_MOD_RSC: + value->rValue = model->BSIM3rsc; + return(OK); + case BSIM3_MOD_WMLT: + value->rValue = model->BSIM3wmlt; + return(OK); + /* Length dependence */ case BSIM3_MOD_LCDSC : value->rValue = model->BSIM3lcdsc; @@ -1219,6 +1254,14 @@ IFvalue *value) case BSIM3_MOD_WMAX: value->rValue = model->BSIM3Wmax; return(OK); + + case BSIM3_MOD_XL: + value->rValue = model->BSIM3xl; + return(OK); + case BSIM3_MOD_XW: + value->rValue = model->BSIM3xw; + return(OK); + case BSIM3_MOD_NOIA: value->rValue = model->BSIM3oxideTrapDensityA; return(OK); diff --git a/src/spicelib/devices/bsim3/b3mpar.c b/src/spicelib/devices/bsim3/b3mpar.c index 1d81c7de3..3cd3dc4a9 100644 --- a/src/spicelib/devices/bsim3/b3mpar.c +++ b/src/spicelib/devices/bsim3/b3mpar.c @@ -39,15 +39,27 @@ GENmodel *inMod) mod->BSIM3capMod = value->iValue; mod->BSIM3capModGiven = TRUE; break; + case BSIM3_MOD_ACMMOD: + mod->BSIM3acmMod = value->iValue; + mod->BSIM3acmModGiven = TRUE; + break; + case BSIM3_MOD_CALCACM: + mod->BSIM3calcacm = value->iValue; + mod->BSIM3calcacmGiven = TRUE; + break; case BSIM3_MOD_NOIMOD : mod->BSIM3noiMod = value->iValue; mod->BSIM3noiModGiven = TRUE; break; + case BSIM3_MOD_NQSMOD : + mod->BSIM3nqsMod = value->iValue; + mod->BSIM3nqsModGiven = TRUE; + break; case BSIM3_MOD_ACNQSMOD : mod->BSIM3acnqsMod = value->iValue; mod->BSIM3acnqsModGiven = TRUE; break; - case BSIM3_MOD_VERSION : + case BSIM3_MOD_VERSION : mod->BSIM3version = value->sValue; mod->BSIM3versionGiven = TRUE; break; @@ -123,14 +135,14 @@ GENmodel *inMod) case BSIM3_MOD_NPEAK: mod->BSIM3npeak = value->rValue; mod->BSIM3npeakGiven = TRUE; - if (mod->BSIM3npeak > 1.0e20) - mod->BSIM3npeak *= 1.0e-6; + if (mod->BSIM3npeak > 1.0e20) + mod->BSIM3npeak *= 1.0e-6; break; case BSIM3_MOD_NGATE: mod->BSIM3ngate = value->rValue; mod->BSIM3ngateGiven = TRUE; - if (mod->BSIM3ngate > 1.0e23) - mod->BSIM3ngate *= 1.0e-6; + if (mod->BSIM3ngate > 1.0e23) + mod->BSIM3ngate *= 1.0e-6; break; case BSIM3_MOD_GAMMA1: mod->BSIM3gamma1 = value->rValue; @@ -438,7 +450,41 @@ GENmodel *inMod) mod->BSIM3tpbswgGiven = TRUE; break; - /* Length dependence */ + /* acm model */ + case BSIM3_MOD_HDIF: + mod->BSIM3hdif = value->rValue; + mod->BSIM3hdifGiven = TRUE; + break; + case BSIM3_MOD_LDIF: + mod->BSIM3ldif = value->rValue; + mod->BSIM3ldifGiven = TRUE; + break; + case BSIM3_MOD_LD: + mod->BSIM3ld = value->rValue; + mod->BSIM3ldGiven = TRUE; + break; + case BSIM3_MOD_RD: + mod->BSIM3rd = value->rValue; + mod->BSIM3rdGiven = TRUE; + break; + case BSIM3_MOD_RS: + mod->BSIM3rs = value->rValue; + mod->BSIM3rsGiven = TRUE; + break; + case BSIM3_MOD_RDC: + mod->BSIM3rdc = value->rValue; + mod->BSIM3rdcGiven = TRUE; + break; + case BSIM3_MOD_RSC: + mod->BSIM3rsc = value->rValue; + mod->BSIM3rscGiven = TRUE; + break; + case BSIM3_MOD_WMLT: + mod->BSIM3wmlt = value->rValue; + mod->BSIM3wmltGiven = TRUE; + break; + + /* Length dependence */ case BSIM3_MOD_LCDSC : mod->BSIM3lcdsc = value->rValue; mod->BSIM3lcdscGiven = TRUE; @@ -502,14 +548,14 @@ GENmodel *inMod) case BSIM3_MOD_LNPEAK: mod->BSIM3lnpeak = value->rValue; mod->BSIM3lnpeakGiven = TRUE; - if (mod->BSIM3lnpeak > 1.0e20) - mod->BSIM3lnpeak *= 1.0e-6; + if (mod->BSIM3lnpeak > 1.0e20) + mod->BSIM3lnpeak *= 1.0e-6; break; case BSIM3_MOD_LNGATE: mod->BSIM3lngate = value->rValue; mod->BSIM3lngateGiven = TRUE; - if (mod->BSIM3lngate > 1.0e23) - mod->BSIM3lngate *= 1.0e-6; + if (mod->BSIM3lngate > 1.0e23) + mod->BSIM3lngate *= 1.0e-6; break; case BSIM3_MOD_LGAMMA1: mod->BSIM3lgamma1 = value->rValue; @@ -781,7 +827,7 @@ GENmodel *inMod) mod->BSIM3lvoffcvGiven = TRUE; break; - /* Width dependence */ + /* Width dependence */ case BSIM3_MOD_WCDSC : mod->BSIM3wcdsc = value->rValue; mod->BSIM3wcdscGiven = TRUE; @@ -845,14 +891,14 @@ GENmodel *inMod) case BSIM3_MOD_WNPEAK: mod->BSIM3wnpeak = value->rValue; mod->BSIM3wnpeakGiven = TRUE; - if (mod->BSIM3wnpeak > 1.0e20) - mod->BSIM3wnpeak *= 1.0e-6; + if (mod->BSIM3wnpeak > 1.0e20) + mod->BSIM3wnpeak *= 1.0e-6; break; case BSIM3_MOD_WNGATE: mod->BSIM3wngate = value->rValue; mod->BSIM3wngateGiven = TRUE; - if (mod->BSIM3wngate > 1.0e23) - mod->BSIM3wngate *= 1.0e-6; + if (mod->BSIM3wngate > 1.0e23) + mod->BSIM3wngate *= 1.0e-6; break; case BSIM3_MOD_WGAMMA1: mod->BSIM3wgamma1 = value->rValue; @@ -1124,7 +1170,7 @@ GENmodel *inMod) mod->BSIM3wvoffcvGiven = TRUE; break; - /* Cross-term dependence */ + /* Cross-term dependence */ case BSIM3_MOD_PCDSC : mod->BSIM3pcdsc = value->rValue; mod->BSIM3pcdscGiven = TRUE; @@ -1188,14 +1234,14 @@ GENmodel *inMod) case BSIM3_MOD_PNPEAK: mod->BSIM3pnpeak = value->rValue; mod->BSIM3pnpeakGiven = TRUE; - if (mod->BSIM3pnpeak > 1.0e20) - mod->BSIM3pnpeak *= 1.0e-6; + if (mod->BSIM3pnpeak > 1.0e20) + mod->BSIM3pnpeak *= 1.0e-6; break; case BSIM3_MOD_PNGATE: mod->BSIM3pngate = value->rValue; mod->BSIM3pngateGiven = TRUE; - if (mod->BSIM3pngate > 1.0e23) - mod->BSIM3pngate *= 1.0e-6; + if (mod->BSIM3pngate > 1.0e23) + mod->BSIM3pngate *= 1.0e-6; break; case BSIM3_MOD_PGAMMA1: mod->BSIM3pgamma1 = value->rValue; @@ -1636,6 +1682,15 @@ GENmodel *inMod) mod->BSIM3WmaxGiven = TRUE; break; + case BSIM3_MOD_XL: + mod->BSIM3xl = value->rValue; + mod->BSIM3xlGiven = TRUE; + break; + case BSIM3_MOD_XW: + mod->BSIM3xw = value->rValue; + mod->BSIM3xwGiven = TRUE; + break; + case BSIM3_MOD_NOIA : mod->BSIM3oxideTrapDensityA = value->rValue; mod->BSIM3oxideTrapDensityAGiven = TRUE; diff --git a/src/spicelib/devices/bsim3/b3node.c b/src/spicelib/devices/bsim3/b3node.c new file mode 100644 index 000000000..85624d864 --- /dev/null +++ b/src/spicelib/devices/bsim3/b3node.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" + +int +BSIM3nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM3model *model = (BSIM3model *)inModel ; + BSIM3instance *here ; + + /* loop through all the BSIM3 models */ + for ( ; model != NULL ; model = model->BSIM3nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM3instances ; here != NULL ; here = here->BSIM3nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM3dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3qNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3/b3par.c b/src/spicelib/devices/bsim3/b3par.c index 555376443..c9c7ddfc1 100644 --- a/src/spicelib/devices/bsim3/b3par.c +++ b/src/spicelib/devices/bsim3/b3par.c @@ -31,7 +31,7 @@ IFvalue *select) if (!cp_getvar("scale", CP_REAL, &scale)) scale = 1; - switch(param) + switch(param) { case BSIM3_W: here->BSIM3w = value->rValue*scale; here->BSIM3wGiven = TRUE; @@ -40,10 +40,10 @@ IFvalue *select) here->BSIM3l = value->rValue*scale; here->BSIM3lGiven = TRUE; break; - case BSIM3_M: - here->BSIM3m = value->rValue; - here->BSIM3mGiven = TRUE; - break; + case BSIM3_M: + here->BSIM3m = value->rValue; + here->BSIM3mGiven = TRUE; + break; case BSIM3_AS: here->BSIM3sourceArea = value->rValue*scale*scale; here->BSIM3sourceAreaGiven = TRUE; @@ -91,6 +91,18 @@ IFvalue *select) here->BSIM3acnqsMod = value->iValue; here->BSIM3acnqsModGiven = TRUE; break; + case BSIM3_GEO: + here->BSIM3geo = value->iValue; + here->BSIM3geoGiven = TRUE; + break; + case BSIM3_DELVTO: + here->BSIM3delvto = value->rValue; + here->BSIM3delvtoGiven = TRUE; + break; + case BSIM3_MULU0: + here->BSIM3mulu0 = value->rValue; + here->BSIM3mulu0Given = TRUE; + break; case BSIM3_IC: switch(value->v.numValue){ case 3: diff --git a/src/spicelib/devices/bsim3/b3set.c b/src/spicelib/devices/bsim3/b3set.c index 857e85395..f85c73e04 100644 --- a/src/spicelib/devices/bsim3/b3set.c +++ b/src/spicelib/devices/bsim3/b3set.c @@ -61,8 +61,18 @@ BSIM3instance **InstArray; model->BSIM3paramChk = 0; if (!model->BSIM3capModGiven) model->BSIM3capMod = 3; + if (!model->BSIM3acmModGiven) + model->BSIM3acmMod = 0; + if (!model->BSIM3calcacmGiven) + model->BSIM3calcacm = 0; if (!model->BSIM3noiModGiven) model->BSIM3noiMod = 1; + if (!model->BSIM3nqsModGiven) + model->BSIM3nqsMod = 0; + else if ((model->BSIM3nqsMod != 0) && (model->BSIM3nqsMod != 1)) + { model->BSIM3nqsMod = 0; + printf("Warning: nqsMod has been set to its default value: 0.\n"); + } if (!model->BSIM3acnqsModGiven) model->BSIM3acnqsMod = 0; else if ((model->BSIM3acnqsMod != 0) && (model->BSIM3acnqsMod != 1)) @@ -247,6 +257,24 @@ BSIM3instance **InstArray; if (!model->BSIM3tpbswgGiven) model->BSIM3tpbswg = 0.0; + /* ACM model */ + if (!model->BSIM3hdifGiven) + model->BSIM3hdif = 0.0; + if (!model->BSIM3ldifGiven) + model->BSIM3ldif = 0.0; + if (!model->BSIM3ldGiven) + model->BSIM3ld = 0.0; + if (!model->BSIM3rdGiven) + model->BSIM3rd = 0.0; + if (!model->BSIM3rsGiven) + model->BSIM3rs = 0.0; + if (!model->BSIM3rdcGiven) + model->BSIM3rdc = 0.0; + if (!model->BSIM3rscGiven) + model->BSIM3rsc = 0.0; + if (!model->BSIM3wmltGiven) + model->BSIM3wmlt = 1.0; + /* Length dependence */ if (!model->BSIM3lcdscGiven) model->BSIM3lcdsc = 0.0; @@ -780,6 +808,12 @@ BSIM3instance **InstArray; model->BSIM3dwc = model->BSIM3Wint; if (!model->BSIM3dlcGiven) model->BSIM3dlc = model->BSIM3Lint; + + if (!model->BSIM3xlGiven) + model->BSIM3xl = 0.0; + if (!model->BSIM3xwGiven) + model->BSIM3xw = 0.0; + if (!model->BSIM3cfGiven) model->BSIM3cf = 2.0 * EPSOX / PI * log(1.0 + 0.4e-6 / model->BSIM3tox); @@ -874,7 +908,16 @@ BSIM3instance **InstArray; if (!here->BSIM3drainPerimeterGiven) here->BSIM3drainPerimeter = 0.0; if (!here->BSIM3drainSquaresGiven) - here->BSIM3drainSquares = 1.0; + { + if (model->BSIM3acmMod == 0) + here->BSIM3drainSquares = 1.0; + else + here->BSIM3drainSquares = 0.0; + } + if (!here->BSIM3delvtoGiven) + here->BSIM3delvto = 0.0; + if (!here->BSIM3mulu0Given) + here->BSIM3mulu0 = 1.0; if (!here->BSIM3icVBSGiven) here->BSIM3icVBS = 0.0; if (!here->BSIM3icVDSGiven) @@ -888,11 +931,21 @@ BSIM3instance **InstArray; if (!here->BSIM3sourcePerimeterGiven) here->BSIM3sourcePerimeter = 0.0; if (!here->BSIM3sourceSquaresGiven) - here->BSIM3sourceSquares = 1.0; + { + if (model->BSIM3acmMod == 0) + here->BSIM3sourceSquares = 1.0; + else + here->BSIM3sourceSquares = 0.0; + } if (!here->BSIM3wGiven) here->BSIM3w = 5.0e-6; if (!here->BSIM3nqsModGiven) - here->BSIM3nqsMod = 0; + here->BSIM3nqsMod = model->BSIM3nqsMod; + else if ((here->BSIM3nqsMod != 0) && (here->BSIM3nqsMod != 1)) + { here->BSIM3nqsMod = model->BSIM3nqsMod; + printf("Warning: nqsMod has been set to its global value %d.\n", + model->BSIM3nqsMod); + } if (!here->BSIM3acnqsModGiven) here->BSIM3acnqsMod = model->BSIM3acnqsMod; else if ((here->BSIM3acnqsMod != 0) && (here->BSIM3acnqsMod != 1)) @@ -900,14 +953,19 @@ BSIM3instance **InstArray; printf("Warning: acnqsMod has been set to its global value %d.\n", model->BSIM3acnqsMod); } - + if (!here->BSIM3geoGiven) + here->BSIM3geo = 0; if (!here->BSIM3mGiven) here->BSIM3m = 1; /* process drain series resistance */ - if ((model->BSIM3sheetResistance > 0.0) && - (here->BSIM3drainSquares > 0.0 )) + if ( ((model->BSIM3sheetResistance > 0.0) && (here->BSIM3drainSquares > 0.0)) + ||((model->BSIM3sheetResistance > 0.0) && (model->BSIM3hdif > 0.0)) + ||((model->BSIM3rd > 0.0) && (model->BSIM3ldif > 0.0)) + ||((model->BSIM3rd > 0.0) && (model->BSIM3ld > 0.0)) + ||((model->BSIM3rdc > 0.0)) + ) { if(here->BSIM3dNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain"); @@ -928,8 +986,12 @@ BSIM3instance **InstArray; } /* process source series resistance */ - if ((model->BSIM3sheetResistance > 0.0) && - (here->BSIM3sourceSquares > 0.0 )) + if ( ((model->BSIM3sheetResistance > 0.0) && (here->BSIM3sourceSquares > 0.0)) + ||((model->BSIM3sheetResistance > 0.0) && (model->BSIM3hdif > 0.0)) + ||((model->BSIM3rs > 0.0) && (model->BSIM3ldif > 0.0)) + ||((model->BSIM3rs > 0.0) && (model->BSIM3ld > 0.0)) + ||((model->BSIM3rsc > 0.0)) + ) { if(here->BSIM3sNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"source"); @@ -967,43 +1029,43 @@ BSIM3instance **InstArray; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM3DdPtr, BSIM3dNode, BSIM3dNode) - TSTALLOC(BSIM3GgPtr, BSIM3gNode, BSIM3gNode) - TSTALLOC(BSIM3SsPtr, BSIM3sNode, BSIM3sNode) - TSTALLOC(BSIM3BbPtr, BSIM3bNode, BSIM3bNode) - TSTALLOC(BSIM3DPdpPtr, BSIM3dNodePrime, BSIM3dNodePrime) - TSTALLOC(BSIM3SPspPtr, BSIM3sNodePrime, BSIM3sNodePrime) - TSTALLOC(BSIM3DdpPtr, BSIM3dNode, BSIM3dNodePrime) - TSTALLOC(BSIM3GbPtr, BSIM3gNode, BSIM3bNode) - TSTALLOC(BSIM3GdpPtr, BSIM3gNode, BSIM3dNodePrime) - TSTALLOC(BSIM3GspPtr, BSIM3gNode, BSIM3sNodePrime) - TSTALLOC(BSIM3SspPtr, BSIM3sNode, BSIM3sNodePrime) - TSTALLOC(BSIM3BdpPtr, BSIM3bNode, BSIM3dNodePrime) - TSTALLOC(BSIM3BspPtr, BSIM3bNode, BSIM3sNodePrime) - TSTALLOC(BSIM3DPspPtr, BSIM3dNodePrime, BSIM3sNodePrime) - TSTALLOC(BSIM3DPdPtr, BSIM3dNodePrime, BSIM3dNode) - TSTALLOC(BSIM3BgPtr, BSIM3bNode, BSIM3gNode) - TSTALLOC(BSIM3DPgPtr, BSIM3dNodePrime, BSIM3gNode) - TSTALLOC(BSIM3SPgPtr, BSIM3sNodePrime, BSIM3gNode) - TSTALLOC(BSIM3SPsPtr, BSIM3sNodePrime, BSIM3sNode) - TSTALLOC(BSIM3DPbPtr, BSIM3dNodePrime, BSIM3bNode) - TSTALLOC(BSIM3SPbPtr, BSIM3sNodePrime, BSIM3bNode) - TSTALLOC(BSIM3SPdpPtr, BSIM3sNodePrime, BSIM3dNodePrime) + TSTALLOC(BSIM3DdPtr, BSIM3dNode, BSIM3dNode); + TSTALLOC(BSIM3GgPtr, BSIM3gNode, BSIM3gNode); + TSTALLOC(BSIM3SsPtr, BSIM3sNode, BSIM3sNode); + TSTALLOC(BSIM3BbPtr, BSIM3bNode, BSIM3bNode); + TSTALLOC(BSIM3DPdpPtr, BSIM3dNodePrime, BSIM3dNodePrime); + TSTALLOC(BSIM3SPspPtr, BSIM3sNodePrime, BSIM3sNodePrime); + TSTALLOC(BSIM3DdpPtr, BSIM3dNode, BSIM3dNodePrime); + TSTALLOC(BSIM3GbPtr, BSIM3gNode, BSIM3bNode); + TSTALLOC(BSIM3GdpPtr, BSIM3gNode, BSIM3dNodePrime); + TSTALLOC(BSIM3GspPtr, BSIM3gNode, BSIM3sNodePrime); + TSTALLOC(BSIM3SspPtr, BSIM3sNode, BSIM3sNodePrime); + TSTALLOC(BSIM3BdpPtr, BSIM3bNode, BSIM3dNodePrime); + TSTALLOC(BSIM3BspPtr, BSIM3bNode, BSIM3sNodePrime); + TSTALLOC(BSIM3DPspPtr, BSIM3dNodePrime, BSIM3sNodePrime); + TSTALLOC(BSIM3DPdPtr, BSIM3dNodePrime, BSIM3dNode); + TSTALLOC(BSIM3BgPtr, BSIM3bNode, BSIM3gNode); + TSTALLOC(BSIM3DPgPtr, BSIM3dNodePrime, BSIM3gNode); + TSTALLOC(BSIM3SPgPtr, BSIM3sNodePrime, BSIM3gNode); + TSTALLOC(BSIM3SPsPtr, BSIM3sNodePrime, BSIM3sNode); + TSTALLOC(BSIM3DPbPtr, BSIM3dNodePrime, BSIM3bNode); + TSTALLOC(BSIM3SPbPtr, BSIM3sNodePrime, BSIM3bNode); + TSTALLOC(BSIM3SPdpPtr, BSIM3sNodePrime, BSIM3dNodePrime); - TSTALLOC(BSIM3QqPtr, BSIM3qNode, BSIM3qNode) + TSTALLOC(BSIM3QqPtr, BSIM3qNode, BSIM3qNode); - TSTALLOC(BSIM3QdpPtr, BSIM3qNode, BSIM3dNodePrime) - TSTALLOC(BSIM3QspPtr, BSIM3qNode, BSIM3sNodePrime) - TSTALLOC(BSIM3QgPtr, BSIM3qNode, BSIM3gNode) - TSTALLOC(BSIM3QbPtr, BSIM3qNode, BSIM3bNode) - TSTALLOC(BSIM3DPqPtr, BSIM3dNodePrime, BSIM3qNode) - TSTALLOC(BSIM3SPqPtr, BSIM3sNodePrime, BSIM3qNode) - TSTALLOC(BSIM3GqPtr, BSIM3gNode, BSIM3qNode) - TSTALLOC(BSIM3BqPtr, BSIM3bNode, BSIM3qNode) + TSTALLOC(BSIM3QdpPtr, BSIM3qNode, BSIM3dNodePrime); + TSTALLOC(BSIM3QspPtr, BSIM3qNode, BSIM3sNodePrime); + TSTALLOC(BSIM3QgPtr, BSIM3qNode, BSIM3gNode); + TSTALLOC(BSIM3QbPtr, BSIM3qNode, BSIM3bNode); + TSTALLOC(BSIM3DPqPtr, BSIM3dNodePrime, BSIM3qNode); + TSTALLOC(BSIM3SPqPtr, BSIM3sNodePrime, BSIM3qNode); + TSTALLOC(BSIM3GqPtr, BSIM3gNode, BSIM3qNode); + TSTALLOC(BSIM3BqPtr, BSIM3bNode, BSIM3qNode); } } diff --git a/src/spicelib/devices/bsim3/b3temp.c b/src/spicelib/devices/bsim3/b3temp.c index 9ac4d396b..b8632e1a6 100644 --- a/src/spicelib/devices/bsim3/b3temp.c +++ b/src/spicelib/devices/bsim3/b3temp.c @@ -3,7 +3,7 @@ /********** * Copyright 2004 Regents of the University of California. All rights reserved. * File: b3temp.c of BSIM3v3.3.0 - * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi **********/ @@ -16,6 +16,7 @@ #include "bsim3def.h" #include "ngspice/const.h" #include "ngspice/sperror.h" +#include "ngspice/devdefs.h" #include "ngspice/suffix.h" #define Kb 1.3806226e-23 @@ -40,140 +41,140 @@ struct bsim3SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam=NULL; double tmp, tmp1, tmp2, tmp3, Eg, Eg0, ni, T0, T1, T2, T3, T4, T5, Ldrn, Wdrn; double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom; double Nvtm, SourceSatCurrent, DrainSatCurrent; -int Size_Not_Found; +int Size_Not_Found, error; /* loop through all the BSIM3 device models */ for (; model != NULL; model = model->BSIM3nextModel) { Temp = ckt->CKTtemp; - if (model->BSIM3bulkJctPotential < 0.1) - { model->BSIM3bulkJctPotential = 0.1; - fprintf(stderr, "Given pb is less than 0.1. Pb is set to 0.1.\n"); - } + if (model->BSIM3bulkJctPotential < 0.1) + { model->BSIM3bulkJctPotential = 0.1; + fprintf(stderr, "Given pb is less than 0.1. Pb is set to 0.1.\n"); + } if (model->BSIM3sidewallJctPotential < 0.1) - { model->BSIM3sidewallJctPotential = 0.1; - fprintf(stderr, "Given pbsw is less than 0.1. Pbsw is set to 0.1.\n"); - } + { model->BSIM3sidewallJctPotential = 0.1; + fprintf(stderr, "Given pbsw is less than 0.1. Pbsw is set to 0.1.\n"); + } if (model->BSIM3GatesidewallJctPotential < 0.1) - { model->BSIM3GatesidewallJctPotential = 0.1; - fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); - } + { model->BSIM3GatesidewallJctPotential = 0.1; + fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); + } model->pSizeDependParamKnot = NULL; - pLastKnot = NULL; + pLastKnot = NULL; - Tnom = model->BSIM3tnom; - TRatio = Temp / Tnom; + Tnom = model->BSIM3tnom; + TRatio = Temp / Tnom; - model->BSIM3vcrit = CONSTvt0 * log(CONSTvt0 / (CONSTroot2 * 1.0e-14)); + model->BSIM3vcrit = CONSTvt0 * log(CONSTvt0 / (CONSTroot2 * 1.0e-14)); model->BSIM3factor1 = sqrt(EPSSI / EPSOX * model->BSIM3tox); Vtm0 = KboQ * Tnom; Eg0 = 1.16 - 7.02e-4 * Tnom * Tnom / (Tnom + 1108.0); - ni = 1.45e10 * (Tnom / 300.15) * sqrt(Tnom / 300.15) + ni = 1.45e10 * (Tnom / 300.15) * sqrt(Tnom / 300.15) * exp(21.5565981 - Eg0 / (2.0 * Vtm0)); model->BSIM3vtm = KboQ * Temp; Eg = 1.16 - 7.02e-4 * Temp * Temp / (Temp + 1108.0); - if (Temp != Tnom) - { T0 = Eg0 / Vtm0 - Eg / model->BSIM3vtm + model->BSIM3jctTempExponent - * log(Temp / Tnom); - T1 = exp(T0 / model->BSIM3jctEmissionCoeff); - model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity - * T1; - model->BSIM3jctSidewallTempSatCurDensity - = model->BSIM3jctSidewallSatCurDensity * T1; - } - else - { model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity; - model->BSIM3jctSidewallTempSatCurDensity - = model->BSIM3jctSidewallSatCurDensity; - } + if (Temp != Tnom) + { T0 = Eg0 / Vtm0 - Eg / model->BSIM3vtm + model->BSIM3jctTempExponent + * log(Temp / Tnom); + T1 = exp(T0 / model->BSIM3jctEmissionCoeff); + model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity + * T1; + model->BSIM3jctSidewallTempSatCurDensity + = model->BSIM3jctSidewallSatCurDensity * T1; + } + else + { model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity; + model->BSIM3jctSidewallTempSatCurDensity + = model->BSIM3jctSidewallSatCurDensity; + } - if (model->BSIM3jctTempSatCurDensity < 0.0) - model->BSIM3jctTempSatCurDensity = 0.0; - if (model->BSIM3jctSidewallTempSatCurDensity < 0.0) - model->BSIM3jctSidewallTempSatCurDensity = 0.0; + if (model->BSIM3jctTempSatCurDensity < 0.0) + model->BSIM3jctTempSatCurDensity = 0.0; + if (model->BSIM3jctSidewallTempSatCurDensity < 0.0) + model->BSIM3jctSidewallTempSatCurDensity = 0.0; - /* Temperature dependence of D/B and S/B diode capacitance begins */ - delTemp = ckt->CKTtemp - model->BSIM3tnom; - T0 = model->BSIM3tcj * delTemp; - if (T0 >= -1.0) - { model->BSIM3unitAreaTempJctCap = model->BSIM3unitAreaJctCap * (1.0 + T0); - } - else if (model->BSIM3unitAreaJctCap > 0.0) - { model->BSIM3unitAreaTempJctCap = 0.0; - fprintf(stderr, "Temperature effect has caused cj to be negative. Cj is clamped to zero.\n"); - } + /* Temperature dependence of D/B and S/B diode capacitance begins */ + delTemp = ckt->CKTtemp - model->BSIM3tnom; + T0 = model->BSIM3tcj * delTemp; + if (T0 >= -1.0) + { model->BSIM3unitAreaTempJctCap = model->BSIM3unitAreaJctCap * (1.0 + T0); + } + else if (model->BSIM3unitAreaJctCap > 0.0) + { model->BSIM3unitAreaTempJctCap = 0.0; + fprintf(stderr, "Temperature effect has caused cj to be negative. Cj is clamped to zero.\n"); + } T0 = model->BSIM3tcjsw * delTemp; - if (T0 >= -1.0) - { model->BSIM3unitLengthSidewallTempJctCap = model->BSIM3unitLengthSidewallJctCap * (1.0 + T0); - } - else if (model->BSIM3unitLengthSidewallJctCap > 0.0) - { model->BSIM3unitLengthSidewallTempJctCap = 0.0; - fprintf(stderr, "Temperature effect has caused cjsw to be negative. Cjsw is clamped to zero.\n"); - } + if (T0 >= -1.0) + { model->BSIM3unitLengthSidewallTempJctCap = model->BSIM3unitLengthSidewallJctCap * (1.0 + T0); + } + else if (model->BSIM3unitLengthSidewallJctCap > 0.0) + { model->BSIM3unitLengthSidewallTempJctCap = 0.0; + fprintf(stderr, "Temperature effect has caused cjsw to be negative. Cjsw is clamped to zero.\n"); + } T0 = model->BSIM3tcjswg * delTemp; - if (T0 >= -1.0) - { model->BSIM3unitLengthGateSidewallTempJctCap = model->BSIM3unitLengthGateSidewallJctCap * (1.0 + T0); - } - else if (model->BSIM3unitLengthGateSidewallJctCap > 0.0) - { model->BSIM3unitLengthGateSidewallTempJctCap = 0.0; - fprintf(stderr, "Temperature effect has caused cjswg to be negative. Cjswg is clamped to zero.\n"); - } + if (T0 >= -1.0) + { model->BSIM3unitLengthGateSidewallTempJctCap = model->BSIM3unitLengthGateSidewallJctCap * (1.0 + T0); + } + else if (model->BSIM3unitLengthGateSidewallJctCap > 0.0) + { model->BSIM3unitLengthGateSidewallTempJctCap = 0.0; + fprintf(stderr, "Temperature effect has caused cjswg to be negative. Cjswg is clamped to zero.\n"); + } model->BSIM3PhiB = model->BSIM3bulkJctPotential - - model->BSIM3tpb * delTemp; + - model->BSIM3tpb * delTemp; if (model->BSIM3PhiB < 0.01) - { model->BSIM3PhiB = 0.01; - fprintf(stderr, "Temperature effect has caused pb to be less than 0.01. Pb is clamped to 0.01.\n"); - } + { model->BSIM3PhiB = 0.01; + fprintf(stderr, "Temperature effect has caused pb to be less than 0.01. Pb is clamped to 0.01.\n"); + } model->BSIM3PhiBSW = model->BSIM3sidewallJctPotential - model->BSIM3tpbsw * delTemp; if (model->BSIM3PhiBSW <= 0.01) - { model->BSIM3PhiBSW = 0.01; - fprintf(stderr, "Temperature effect has caused pbsw to be less than 0.01. Pbsw is clamped to 0.01.\n"); - } - model->BSIM3PhiBSWG = model->BSIM3GatesidewallJctPotential + { model->BSIM3PhiBSW = 0.01; + fprintf(stderr, "Temperature effect has caused pbsw to be less than 0.01. Pbsw is clamped to 0.01.\n"); + } + model->BSIM3PhiBSWG = model->BSIM3GatesidewallJctPotential - model->BSIM3tpbswg * delTemp; if (model->BSIM3PhiBSWG <= 0.01) - { model->BSIM3PhiBSWG = 0.01; - fprintf(stderr, "Temperature effect has caused pbswg to be less than 0.01. Pbswg is clamped to 0.01.\n"); - } + { model->BSIM3PhiBSWG = 0.01; + fprintf(stderr, "Temperature effect has caused pbswg to be less than 0.01. Pbswg is clamped to 0.01.\n"); + } /* End of junction capacitance */ /* loop through all the instances of the model */ - /* MCJ: Length and Width not initialized */ + /* MCJ: Length and Width not initialized */ for (here = model->BSIM3instances; here != NULL; - here = here->BSIM3nextInstance) - { + here = here->BSIM3nextInstance) + { pSizeDependParamKnot = model->pSizeDependParamKnot; - Size_Not_Found = 1; - while ((pSizeDependParamKnot != NULL) && Size_Not_Found) - { if ((here->BSIM3l == pSizeDependParamKnot->Length) - && (here->BSIM3w == pSizeDependParamKnot->Width)) + Size_Not_Found = 1; + while ((pSizeDependParamKnot != NULL) && Size_Not_Found) + { if ((here->BSIM3l == pSizeDependParamKnot->Length) + && (here->BSIM3w == pSizeDependParamKnot->Width)) { Size_Not_Found = 0; - here->pParam = pSizeDependParamKnot; - pParam = here->pParam; /*bug-fix */ - } - else - { pLastKnot = pSizeDependParamKnot; - pSizeDependParamKnot = pSizeDependParamKnot->pNext; - } + here->pParam = pSizeDependParamKnot; + pParam = here->pParam; /*bug-fix */ + } + else + { pLastKnot = pSizeDependParamKnot; + pSizeDependParamKnot = pSizeDependParamKnot->pNext; + } } - if (Size_Not_Found) - { pParam = TMALLOC(struct bsim3SizeDependParam, 1); + if (Size_Not_Found) + { pParam = TMALLOC(struct bsim3SizeDependParam, 1); if (pLastKnot == NULL) - model->pSizeDependParamKnot = pParam; + model->pSizeDependParamKnot = pParam; else - pLastKnot->pNext = pParam; + pLastKnot->pNext = pParam; pParam->pNext = NULL; here->pParam = pParam; - Ldrn = here->BSIM3l; - Wdrn = here->BSIM3w; + Ldrn = here->BSIM3l; + Wdrn = here->BSIM3w; pParam->Length = Ldrn; pParam->Width = Wdrn; - + T0 = pow(Ldrn, model->BSIM3Lln); T1 = pow(Wdrn, model->BSIM3Lwn); tmp1 = model->BSIM3Ll / T0 + model->BSIM3Lw / T1 @@ -192,9 +193,9 @@ int Size_Not_Found; + model->BSIM3Wwlc / (T2 * T3); pParam->BSIM3dwc = model->BSIM3dwc + tmp2; - pParam->BSIM3leff = here->BSIM3l - 2.0 * pParam->BSIM3dl; + pParam->BSIM3leff = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dl; if (pParam->BSIM3leff <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; SPfrontEnd->IFerror (ERR_FATAL, @@ -203,9 +204,9 @@ int Size_Not_Found; return(E_BADPARM); } - pParam->BSIM3weff = here->BSIM3w - 2.0 * pParam->BSIM3dw; + pParam->BSIM3weff = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dw; if (pParam->BSIM3weff <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; SPfrontEnd->IFerror (ERR_FATAL, @@ -214,9 +215,9 @@ int Size_Not_Found; return(E_BADPARM); } - pParam->BSIM3leffCV = here->BSIM3l - 2.0 * pParam->BSIM3dlc; + pParam->BSIM3leffCV = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dlc; if (pParam->BSIM3leffCV <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; SPfrontEnd->IFerror (ERR_FATAL, @@ -225,9 +226,9 @@ int Size_Not_Found; return(E_BADPARM); } - pParam->BSIM3weffCV = here->BSIM3w - 2.0 * pParam->BSIM3dwc; + pParam->BSIM3weffCV = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dwc; if (pParam->BSIM3weffCV <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; SPfrontEnd->IFerror (ERR_FATAL, @@ -237,339 +238,339 @@ int Size_Not_Found; } - if (model->BSIM3binUnit == 1) - { Inv_L = 1.0e-6 / pParam->BSIM3leff; - Inv_W = 1.0e-6 / pParam->BSIM3weff; - Inv_LW = 1.0e-12 / (pParam->BSIM3leff - * pParam->BSIM3weff); - } - else - { Inv_L = 1.0 / pParam->BSIM3leff; - Inv_W = 1.0 / pParam->BSIM3weff; - Inv_LW = 1.0 / (pParam->BSIM3leff - * pParam->BSIM3weff); - } - pParam->BSIM3cdsc = model->BSIM3cdsc - + model->BSIM3lcdsc * Inv_L - + model->BSIM3wcdsc * Inv_W - + model->BSIM3pcdsc * Inv_LW; - pParam->BSIM3cdscb = model->BSIM3cdscb - + model->BSIM3lcdscb * Inv_L - + model->BSIM3wcdscb * Inv_W - + model->BSIM3pcdscb * Inv_LW; - - pParam->BSIM3cdscd = model->BSIM3cdscd - + model->BSIM3lcdscd * Inv_L - + model->BSIM3wcdscd * Inv_W - + model->BSIM3pcdscd * Inv_LW; - - pParam->BSIM3cit = model->BSIM3cit - + model->BSIM3lcit * Inv_L - + model->BSIM3wcit * Inv_W - + model->BSIM3pcit * Inv_LW; - pParam->BSIM3nfactor = model->BSIM3nfactor - + model->BSIM3lnfactor * Inv_L - + model->BSIM3wnfactor * Inv_W - + model->BSIM3pnfactor * Inv_LW; - pParam->BSIM3xj = model->BSIM3xj - + model->BSIM3lxj * Inv_L - + model->BSIM3wxj * Inv_W - + model->BSIM3pxj * Inv_LW; - pParam->BSIM3vsat = model->BSIM3vsat - + model->BSIM3lvsat * Inv_L - + model->BSIM3wvsat * Inv_W - + model->BSIM3pvsat * Inv_LW; - pParam->BSIM3at = model->BSIM3at - + model->BSIM3lat * Inv_L - + model->BSIM3wat * Inv_W - + model->BSIM3pat * Inv_LW; - pParam->BSIM3a0 = model->BSIM3a0 - + model->BSIM3la0 * Inv_L - + model->BSIM3wa0 * Inv_W - + model->BSIM3pa0 * Inv_LW; - - pParam->BSIM3ags = model->BSIM3ags - + model->BSIM3lags * Inv_L - + model->BSIM3wags * Inv_W - + model->BSIM3pags * Inv_LW; - - pParam->BSIM3a1 = model->BSIM3a1 - + model->BSIM3la1 * Inv_L - + model->BSIM3wa1 * Inv_W - + model->BSIM3pa1 * Inv_LW; - pParam->BSIM3a2 = model->BSIM3a2 - + model->BSIM3la2 * Inv_L - + model->BSIM3wa2 * Inv_W - + model->BSIM3pa2 * Inv_LW; - pParam->BSIM3keta = model->BSIM3keta - + model->BSIM3lketa * Inv_L - + model->BSIM3wketa * Inv_W - + model->BSIM3pketa * Inv_LW; - pParam->BSIM3nsub = model->BSIM3nsub - + model->BSIM3lnsub * Inv_L - + model->BSIM3wnsub * Inv_W - + model->BSIM3pnsub * Inv_LW; - pParam->BSIM3npeak = model->BSIM3npeak - + model->BSIM3lnpeak * Inv_L - + model->BSIM3wnpeak * Inv_W - + model->BSIM3pnpeak * Inv_LW; - pParam->BSIM3ngate = model->BSIM3ngate - + model->BSIM3lngate * Inv_L - + model->BSIM3wngate * Inv_W - + model->BSIM3pngate * Inv_LW; - pParam->BSIM3gamma1 = model->BSIM3gamma1 - + model->BSIM3lgamma1 * Inv_L - + model->BSIM3wgamma1 * Inv_W - + model->BSIM3pgamma1 * Inv_LW; - pParam->BSIM3gamma2 = model->BSIM3gamma2 - + model->BSIM3lgamma2 * Inv_L - + model->BSIM3wgamma2 * Inv_W - + model->BSIM3pgamma2 * Inv_LW; - pParam->BSIM3vbx = model->BSIM3vbx - + model->BSIM3lvbx * Inv_L - + model->BSIM3wvbx * Inv_W - + model->BSIM3pvbx * Inv_LW; - pParam->BSIM3vbm = model->BSIM3vbm - + model->BSIM3lvbm * Inv_L - + model->BSIM3wvbm * Inv_W - + model->BSIM3pvbm * Inv_LW; - pParam->BSIM3xt = model->BSIM3xt - + model->BSIM3lxt * Inv_L - + model->BSIM3wxt * Inv_W - + model->BSIM3pxt * Inv_LW; + if (model->BSIM3binUnit == 1) + { Inv_L = 1.0e-6 / pParam->BSIM3leff; + Inv_W = 1.0e-6 / pParam->BSIM3weff; + Inv_LW = 1.0e-12 / (pParam->BSIM3leff + * pParam->BSIM3weff); + } + else + { Inv_L = 1.0 / pParam->BSIM3leff; + Inv_W = 1.0 / pParam->BSIM3weff; + Inv_LW = 1.0 / (pParam->BSIM3leff + * pParam->BSIM3weff); + } + pParam->BSIM3cdsc = model->BSIM3cdsc + + model->BSIM3lcdsc * Inv_L + + model->BSIM3wcdsc * Inv_W + + model->BSIM3pcdsc * Inv_LW; + pParam->BSIM3cdscb = model->BSIM3cdscb + + model->BSIM3lcdscb * Inv_L + + model->BSIM3wcdscb * Inv_W + + model->BSIM3pcdscb * Inv_LW; + + pParam->BSIM3cdscd = model->BSIM3cdscd + + model->BSIM3lcdscd * Inv_L + + model->BSIM3wcdscd * Inv_W + + model->BSIM3pcdscd * Inv_LW; + + pParam->BSIM3cit = model->BSIM3cit + + model->BSIM3lcit * Inv_L + + model->BSIM3wcit * Inv_W + + model->BSIM3pcit * Inv_LW; + pParam->BSIM3nfactor = model->BSIM3nfactor + + model->BSIM3lnfactor * Inv_L + + model->BSIM3wnfactor * Inv_W + + model->BSIM3pnfactor * Inv_LW; + pParam->BSIM3xj = model->BSIM3xj + + model->BSIM3lxj * Inv_L + + model->BSIM3wxj * Inv_W + + model->BSIM3pxj * Inv_LW; + pParam->BSIM3vsat = model->BSIM3vsat + + model->BSIM3lvsat * Inv_L + + model->BSIM3wvsat * Inv_W + + model->BSIM3pvsat * Inv_LW; + pParam->BSIM3at = model->BSIM3at + + model->BSIM3lat * Inv_L + + model->BSIM3wat * Inv_W + + model->BSIM3pat * Inv_LW; + pParam->BSIM3a0 = model->BSIM3a0 + + model->BSIM3la0 * Inv_L + + model->BSIM3wa0 * Inv_W + + model->BSIM3pa0 * Inv_LW; + + pParam->BSIM3ags = model->BSIM3ags + + model->BSIM3lags * Inv_L + + model->BSIM3wags * Inv_W + + model->BSIM3pags * Inv_LW; + + pParam->BSIM3a1 = model->BSIM3a1 + + model->BSIM3la1 * Inv_L + + model->BSIM3wa1 * Inv_W + + model->BSIM3pa1 * Inv_LW; + pParam->BSIM3a2 = model->BSIM3a2 + + model->BSIM3la2 * Inv_L + + model->BSIM3wa2 * Inv_W + + model->BSIM3pa2 * Inv_LW; + pParam->BSIM3keta = model->BSIM3keta + + model->BSIM3lketa * Inv_L + + model->BSIM3wketa * Inv_W + + model->BSIM3pketa * Inv_LW; + pParam->BSIM3nsub = model->BSIM3nsub + + model->BSIM3lnsub * Inv_L + + model->BSIM3wnsub * Inv_W + + model->BSIM3pnsub * Inv_LW; + pParam->BSIM3npeak = model->BSIM3npeak + + model->BSIM3lnpeak * Inv_L + + model->BSIM3wnpeak * Inv_W + + model->BSIM3pnpeak * Inv_LW; + pParam->BSIM3ngate = model->BSIM3ngate + + model->BSIM3lngate * Inv_L + + model->BSIM3wngate * Inv_W + + model->BSIM3pngate * Inv_LW; + pParam->BSIM3gamma1 = model->BSIM3gamma1 + + model->BSIM3lgamma1 * Inv_L + + model->BSIM3wgamma1 * Inv_W + + model->BSIM3pgamma1 * Inv_LW; + pParam->BSIM3gamma2 = model->BSIM3gamma2 + + model->BSIM3lgamma2 * Inv_L + + model->BSIM3wgamma2 * Inv_W + + model->BSIM3pgamma2 * Inv_LW; + pParam->BSIM3vbx = model->BSIM3vbx + + model->BSIM3lvbx * Inv_L + + model->BSIM3wvbx * Inv_W + + model->BSIM3pvbx * Inv_LW; + pParam->BSIM3vbm = model->BSIM3vbm + + model->BSIM3lvbm * Inv_L + + model->BSIM3wvbm * Inv_W + + model->BSIM3pvbm * Inv_LW; + pParam->BSIM3xt = model->BSIM3xt + + model->BSIM3lxt * Inv_L + + model->BSIM3wxt * Inv_W + + model->BSIM3pxt * Inv_LW; pParam->BSIM3vfb = model->BSIM3vfb + model->BSIM3lvfb * Inv_L + model->BSIM3wvfb * Inv_W + model->BSIM3pvfb * Inv_LW; - pParam->BSIM3k1 = model->BSIM3k1 - + model->BSIM3lk1 * Inv_L - + model->BSIM3wk1 * Inv_W - + model->BSIM3pk1 * Inv_LW; - pParam->BSIM3kt1 = model->BSIM3kt1 - + model->BSIM3lkt1 * Inv_L - + model->BSIM3wkt1 * Inv_W - + model->BSIM3pkt1 * Inv_LW; - pParam->BSIM3kt1l = model->BSIM3kt1l - + model->BSIM3lkt1l * Inv_L - + model->BSIM3wkt1l * Inv_W - + model->BSIM3pkt1l * Inv_LW; - pParam->BSIM3k2 = model->BSIM3k2 - + model->BSIM3lk2 * Inv_L - + model->BSIM3wk2 * Inv_W - + model->BSIM3pk2 * Inv_LW; - pParam->BSIM3kt2 = model->BSIM3kt2 - + model->BSIM3lkt2 * Inv_L - + model->BSIM3wkt2 * Inv_W - + model->BSIM3pkt2 * Inv_LW; - pParam->BSIM3k3 = model->BSIM3k3 - + model->BSIM3lk3 * Inv_L - + model->BSIM3wk3 * Inv_W - + model->BSIM3pk3 * Inv_LW; - pParam->BSIM3k3b = model->BSIM3k3b - + model->BSIM3lk3b * Inv_L - + model->BSIM3wk3b * Inv_W - + model->BSIM3pk3b * Inv_LW; - pParam->BSIM3w0 = model->BSIM3w0 - + model->BSIM3lw0 * Inv_L - + model->BSIM3ww0 * Inv_W - + model->BSIM3pw0 * Inv_LW; - pParam->BSIM3nlx = model->BSIM3nlx - + model->BSIM3lnlx * Inv_L - + model->BSIM3wnlx * Inv_W - + model->BSIM3pnlx * Inv_LW; - pParam->BSIM3dvt0 = model->BSIM3dvt0 - + model->BSIM3ldvt0 * Inv_L - + model->BSIM3wdvt0 * Inv_W - + model->BSIM3pdvt0 * Inv_LW; - pParam->BSIM3dvt1 = model->BSIM3dvt1 - + model->BSIM3ldvt1 * Inv_L - + model->BSIM3wdvt1 * Inv_W - + model->BSIM3pdvt1 * Inv_LW; - pParam->BSIM3dvt2 = model->BSIM3dvt2 - + model->BSIM3ldvt2 * Inv_L - + model->BSIM3wdvt2 * Inv_W - + model->BSIM3pdvt2 * Inv_LW; - pParam->BSIM3dvt0w = model->BSIM3dvt0w - + model->BSIM3ldvt0w * Inv_L - + model->BSIM3wdvt0w * Inv_W - + model->BSIM3pdvt0w * Inv_LW; - pParam->BSIM3dvt1w = model->BSIM3dvt1w - + model->BSIM3ldvt1w * Inv_L - + model->BSIM3wdvt1w * Inv_W - + model->BSIM3pdvt1w * Inv_LW; - pParam->BSIM3dvt2w = model->BSIM3dvt2w - + model->BSIM3ldvt2w * Inv_L - + model->BSIM3wdvt2w * Inv_W - + model->BSIM3pdvt2w * Inv_LW; - pParam->BSIM3drout = model->BSIM3drout - + model->BSIM3ldrout * Inv_L - + model->BSIM3wdrout * Inv_W - + model->BSIM3pdrout * Inv_LW; - pParam->BSIM3dsub = model->BSIM3dsub - + model->BSIM3ldsub * Inv_L - + model->BSIM3wdsub * Inv_W - + model->BSIM3pdsub * Inv_LW; - pParam->BSIM3vth0 = model->BSIM3vth0 - + model->BSIM3lvth0 * Inv_L - + model->BSIM3wvth0 * Inv_W - + model->BSIM3pvth0 * Inv_LW; - pParam->BSIM3ua = model->BSIM3ua - + model->BSIM3lua * Inv_L - + model->BSIM3wua * Inv_W - + model->BSIM3pua * Inv_LW; - pParam->BSIM3ua1 = model->BSIM3ua1 - + model->BSIM3lua1 * Inv_L - + model->BSIM3wua1 * Inv_W - + model->BSIM3pua1 * Inv_LW; - pParam->BSIM3ub = model->BSIM3ub - + model->BSIM3lub * Inv_L - + model->BSIM3wub * Inv_W - + model->BSIM3pub * Inv_LW; - pParam->BSIM3ub1 = model->BSIM3ub1 - + model->BSIM3lub1 * Inv_L - + model->BSIM3wub1 * Inv_W - + model->BSIM3pub1 * Inv_LW; - pParam->BSIM3uc = model->BSIM3uc - + model->BSIM3luc * Inv_L - + model->BSIM3wuc * Inv_W - + model->BSIM3puc * Inv_LW; - pParam->BSIM3uc1 = model->BSIM3uc1 - + model->BSIM3luc1 * Inv_L - + model->BSIM3wuc1 * Inv_W - + model->BSIM3puc1 * Inv_LW; - pParam->BSIM3u0 = model->BSIM3u0 - + model->BSIM3lu0 * Inv_L - + model->BSIM3wu0 * Inv_W - + model->BSIM3pu0 * Inv_LW; - pParam->BSIM3ute = model->BSIM3ute - + model->BSIM3lute * Inv_L - + model->BSIM3wute * Inv_W - + model->BSIM3pute * Inv_LW; - pParam->BSIM3voff = model->BSIM3voff - + model->BSIM3lvoff * Inv_L - + model->BSIM3wvoff * Inv_W - + model->BSIM3pvoff * Inv_LW; - pParam->BSIM3delta = model->BSIM3delta - + model->BSIM3ldelta * Inv_L - + model->BSIM3wdelta * Inv_W - + model->BSIM3pdelta * Inv_LW; - pParam->BSIM3rdsw = model->BSIM3rdsw - + model->BSIM3lrdsw * Inv_L - + model->BSIM3wrdsw * Inv_W - + model->BSIM3prdsw * Inv_LW; - pParam->BSIM3prwg = model->BSIM3prwg - + model->BSIM3lprwg * Inv_L - + model->BSIM3wprwg * Inv_W - + model->BSIM3pprwg * Inv_LW; - pParam->BSIM3prwb = model->BSIM3prwb - + model->BSIM3lprwb * Inv_L - + model->BSIM3wprwb * Inv_W - + model->BSIM3pprwb * Inv_LW; - pParam->BSIM3prt = model->BSIM3prt - + model->BSIM3lprt * Inv_L - + model->BSIM3wprt * Inv_W - + model->BSIM3pprt * Inv_LW; - pParam->BSIM3eta0 = model->BSIM3eta0 - + model->BSIM3leta0 * Inv_L - + model->BSIM3weta0 * Inv_W - + model->BSIM3peta0 * Inv_LW; - pParam->BSIM3etab = model->BSIM3etab - + model->BSIM3letab * Inv_L - + model->BSIM3wetab * Inv_W - + model->BSIM3petab * Inv_LW; - pParam->BSIM3pclm = model->BSIM3pclm - + model->BSIM3lpclm * Inv_L - + model->BSIM3wpclm * Inv_W - + model->BSIM3ppclm * Inv_LW; - pParam->BSIM3pdibl1 = model->BSIM3pdibl1 - + model->BSIM3lpdibl1 * Inv_L - + model->BSIM3wpdibl1 * Inv_W - + model->BSIM3ppdibl1 * Inv_LW; - pParam->BSIM3pdibl2 = model->BSIM3pdibl2 - + model->BSIM3lpdibl2 * Inv_L - + model->BSIM3wpdibl2 * Inv_W - + model->BSIM3ppdibl2 * Inv_LW; - pParam->BSIM3pdiblb = model->BSIM3pdiblb - + model->BSIM3lpdiblb * Inv_L - + model->BSIM3wpdiblb * Inv_W - + model->BSIM3ppdiblb * Inv_LW; - pParam->BSIM3pscbe1 = model->BSIM3pscbe1 - + model->BSIM3lpscbe1 * Inv_L - + model->BSIM3wpscbe1 * Inv_W - + model->BSIM3ppscbe1 * Inv_LW; - pParam->BSIM3pscbe2 = model->BSIM3pscbe2 - + model->BSIM3lpscbe2 * Inv_L - + model->BSIM3wpscbe2 * Inv_W - + model->BSIM3ppscbe2 * Inv_LW; - pParam->BSIM3pvag = model->BSIM3pvag - + model->BSIM3lpvag * Inv_L - + model->BSIM3wpvag * Inv_W - + model->BSIM3ppvag * Inv_LW; - pParam->BSIM3wr = model->BSIM3wr - + model->BSIM3lwr * Inv_L - + model->BSIM3wwr * Inv_W - + model->BSIM3pwr * Inv_LW; - pParam->BSIM3dwg = model->BSIM3dwg - + model->BSIM3ldwg * Inv_L - + model->BSIM3wdwg * Inv_W - + model->BSIM3pdwg * Inv_LW; - pParam->BSIM3dwb = model->BSIM3dwb - + model->BSIM3ldwb * Inv_L - + model->BSIM3wdwb * Inv_W - + model->BSIM3pdwb * Inv_LW; - pParam->BSIM3b0 = model->BSIM3b0 - + model->BSIM3lb0 * Inv_L - + model->BSIM3wb0 * Inv_W - + model->BSIM3pb0 * Inv_LW; - pParam->BSIM3b1 = model->BSIM3b1 - + model->BSIM3lb1 * Inv_L - + model->BSIM3wb1 * Inv_W - + model->BSIM3pb1 * Inv_LW; - pParam->BSIM3alpha0 = model->BSIM3alpha0 - + model->BSIM3lalpha0 * Inv_L - + model->BSIM3walpha0 * Inv_W - + model->BSIM3palpha0 * Inv_LW; + pParam->BSIM3k1 = model->BSIM3k1 + + model->BSIM3lk1 * Inv_L + + model->BSIM3wk1 * Inv_W + + model->BSIM3pk1 * Inv_LW; + pParam->BSIM3kt1 = model->BSIM3kt1 + + model->BSIM3lkt1 * Inv_L + + model->BSIM3wkt1 * Inv_W + + model->BSIM3pkt1 * Inv_LW; + pParam->BSIM3kt1l = model->BSIM3kt1l + + model->BSIM3lkt1l * Inv_L + + model->BSIM3wkt1l * Inv_W + + model->BSIM3pkt1l * Inv_LW; + pParam->BSIM3k2 = model->BSIM3k2 + + model->BSIM3lk2 * Inv_L + + model->BSIM3wk2 * Inv_W + + model->BSIM3pk2 * Inv_LW; + pParam->BSIM3kt2 = model->BSIM3kt2 + + model->BSIM3lkt2 * Inv_L + + model->BSIM3wkt2 * Inv_W + + model->BSIM3pkt2 * Inv_LW; + pParam->BSIM3k3 = model->BSIM3k3 + + model->BSIM3lk3 * Inv_L + + model->BSIM3wk3 * Inv_W + + model->BSIM3pk3 * Inv_LW; + pParam->BSIM3k3b = model->BSIM3k3b + + model->BSIM3lk3b * Inv_L + + model->BSIM3wk3b * Inv_W + + model->BSIM3pk3b * Inv_LW; + pParam->BSIM3w0 = model->BSIM3w0 + + model->BSIM3lw0 * Inv_L + + model->BSIM3ww0 * Inv_W + + model->BSIM3pw0 * Inv_LW; + pParam->BSIM3nlx = model->BSIM3nlx + + model->BSIM3lnlx * Inv_L + + model->BSIM3wnlx * Inv_W + + model->BSIM3pnlx * Inv_LW; + pParam->BSIM3dvt0 = model->BSIM3dvt0 + + model->BSIM3ldvt0 * Inv_L + + model->BSIM3wdvt0 * Inv_W + + model->BSIM3pdvt0 * Inv_LW; + pParam->BSIM3dvt1 = model->BSIM3dvt1 + + model->BSIM3ldvt1 * Inv_L + + model->BSIM3wdvt1 * Inv_W + + model->BSIM3pdvt1 * Inv_LW; + pParam->BSIM3dvt2 = model->BSIM3dvt2 + + model->BSIM3ldvt2 * Inv_L + + model->BSIM3wdvt2 * Inv_W + + model->BSIM3pdvt2 * Inv_LW; + pParam->BSIM3dvt0w = model->BSIM3dvt0w + + model->BSIM3ldvt0w * Inv_L + + model->BSIM3wdvt0w * Inv_W + + model->BSIM3pdvt0w * Inv_LW; + pParam->BSIM3dvt1w = model->BSIM3dvt1w + + model->BSIM3ldvt1w * Inv_L + + model->BSIM3wdvt1w * Inv_W + + model->BSIM3pdvt1w * Inv_LW; + pParam->BSIM3dvt2w = model->BSIM3dvt2w + + model->BSIM3ldvt2w * Inv_L + + model->BSIM3wdvt2w * Inv_W + + model->BSIM3pdvt2w * Inv_LW; + pParam->BSIM3drout = model->BSIM3drout + + model->BSIM3ldrout * Inv_L + + model->BSIM3wdrout * Inv_W + + model->BSIM3pdrout * Inv_LW; + pParam->BSIM3dsub = model->BSIM3dsub + + model->BSIM3ldsub * Inv_L + + model->BSIM3wdsub * Inv_W + + model->BSIM3pdsub * Inv_LW; + pParam->BSIM3vth0 = model->BSIM3vth0 + + model->BSIM3lvth0 * Inv_L + + model->BSIM3wvth0 * Inv_W + + model->BSIM3pvth0 * Inv_LW; + pParam->BSIM3ua = model->BSIM3ua + + model->BSIM3lua * Inv_L + + model->BSIM3wua * Inv_W + + model->BSIM3pua * Inv_LW; + pParam->BSIM3ua1 = model->BSIM3ua1 + + model->BSIM3lua1 * Inv_L + + model->BSIM3wua1 * Inv_W + + model->BSIM3pua1 * Inv_LW; + pParam->BSIM3ub = model->BSIM3ub + + model->BSIM3lub * Inv_L + + model->BSIM3wub * Inv_W + + model->BSIM3pub * Inv_LW; + pParam->BSIM3ub1 = model->BSIM3ub1 + + model->BSIM3lub1 * Inv_L + + model->BSIM3wub1 * Inv_W + + model->BSIM3pub1 * Inv_LW; + pParam->BSIM3uc = model->BSIM3uc + + model->BSIM3luc * Inv_L + + model->BSIM3wuc * Inv_W + + model->BSIM3puc * Inv_LW; + pParam->BSIM3uc1 = model->BSIM3uc1 + + model->BSIM3luc1 * Inv_L + + model->BSIM3wuc1 * Inv_W + + model->BSIM3puc1 * Inv_LW; + pParam->BSIM3u0 = model->BSIM3u0 + + model->BSIM3lu0 * Inv_L + + model->BSIM3wu0 * Inv_W + + model->BSIM3pu0 * Inv_LW; + pParam->BSIM3ute = model->BSIM3ute + + model->BSIM3lute * Inv_L + + model->BSIM3wute * Inv_W + + model->BSIM3pute * Inv_LW; + pParam->BSIM3voff = model->BSIM3voff + + model->BSIM3lvoff * Inv_L + + model->BSIM3wvoff * Inv_W + + model->BSIM3pvoff * Inv_LW; + pParam->BSIM3delta = model->BSIM3delta + + model->BSIM3ldelta * Inv_L + + model->BSIM3wdelta * Inv_W + + model->BSIM3pdelta * Inv_LW; + pParam->BSIM3rdsw = model->BSIM3rdsw + + model->BSIM3lrdsw * Inv_L + + model->BSIM3wrdsw * Inv_W + + model->BSIM3prdsw * Inv_LW; + pParam->BSIM3prwg = model->BSIM3prwg + + model->BSIM3lprwg * Inv_L + + model->BSIM3wprwg * Inv_W + + model->BSIM3pprwg * Inv_LW; + pParam->BSIM3prwb = model->BSIM3prwb + + model->BSIM3lprwb * Inv_L + + model->BSIM3wprwb * Inv_W + + model->BSIM3pprwb * Inv_LW; + pParam->BSIM3prt = model->BSIM3prt + + model->BSIM3lprt * Inv_L + + model->BSIM3wprt * Inv_W + + model->BSIM3pprt * Inv_LW; + pParam->BSIM3eta0 = model->BSIM3eta0 + + model->BSIM3leta0 * Inv_L + + model->BSIM3weta0 * Inv_W + + model->BSIM3peta0 * Inv_LW; + pParam->BSIM3etab = model->BSIM3etab + + model->BSIM3letab * Inv_L + + model->BSIM3wetab * Inv_W + + model->BSIM3petab * Inv_LW; + pParam->BSIM3pclm = model->BSIM3pclm + + model->BSIM3lpclm * Inv_L + + model->BSIM3wpclm * Inv_W + + model->BSIM3ppclm * Inv_LW; + pParam->BSIM3pdibl1 = model->BSIM3pdibl1 + + model->BSIM3lpdibl1 * Inv_L + + model->BSIM3wpdibl1 * Inv_W + + model->BSIM3ppdibl1 * Inv_LW; + pParam->BSIM3pdibl2 = model->BSIM3pdibl2 + + model->BSIM3lpdibl2 * Inv_L + + model->BSIM3wpdibl2 * Inv_W + + model->BSIM3ppdibl2 * Inv_LW; + pParam->BSIM3pdiblb = model->BSIM3pdiblb + + model->BSIM3lpdiblb * Inv_L + + model->BSIM3wpdiblb * Inv_W + + model->BSIM3ppdiblb * Inv_LW; + pParam->BSIM3pscbe1 = model->BSIM3pscbe1 + + model->BSIM3lpscbe1 * Inv_L + + model->BSIM3wpscbe1 * Inv_W + + model->BSIM3ppscbe1 * Inv_LW; + pParam->BSIM3pscbe2 = model->BSIM3pscbe2 + + model->BSIM3lpscbe2 * Inv_L + + model->BSIM3wpscbe2 * Inv_W + + model->BSIM3ppscbe2 * Inv_LW; + pParam->BSIM3pvag = model->BSIM3pvag + + model->BSIM3lpvag * Inv_L + + model->BSIM3wpvag * Inv_W + + model->BSIM3ppvag * Inv_LW; + pParam->BSIM3wr = model->BSIM3wr + + model->BSIM3lwr * Inv_L + + model->BSIM3wwr * Inv_W + + model->BSIM3pwr * Inv_LW; + pParam->BSIM3dwg = model->BSIM3dwg + + model->BSIM3ldwg * Inv_L + + model->BSIM3wdwg * Inv_W + + model->BSIM3pdwg * Inv_LW; + pParam->BSIM3dwb = model->BSIM3dwb + + model->BSIM3ldwb * Inv_L + + model->BSIM3wdwb * Inv_W + + model->BSIM3pdwb * Inv_LW; + pParam->BSIM3b0 = model->BSIM3b0 + + model->BSIM3lb0 * Inv_L + + model->BSIM3wb0 * Inv_W + + model->BSIM3pb0 * Inv_LW; + pParam->BSIM3b1 = model->BSIM3b1 + + model->BSIM3lb1 * Inv_L + + model->BSIM3wb1 * Inv_W + + model->BSIM3pb1 * Inv_LW; + pParam->BSIM3alpha0 = model->BSIM3alpha0 + + model->BSIM3lalpha0 * Inv_L + + model->BSIM3walpha0 * Inv_W + + model->BSIM3palpha0 * Inv_LW; pParam->BSIM3alpha1 = model->BSIM3alpha1 + model->BSIM3lalpha1 * Inv_L + model->BSIM3walpha1 * Inv_W + model->BSIM3palpha1 * Inv_LW; - pParam->BSIM3beta0 = model->BSIM3beta0 - + model->BSIM3lbeta0 * Inv_L - + model->BSIM3wbeta0 * Inv_W - + model->BSIM3pbeta0 * Inv_LW; - /* CV model */ - pParam->BSIM3elm = model->BSIM3elm - + model->BSIM3lelm * Inv_L - + model->BSIM3welm * Inv_W - + model->BSIM3pelm * Inv_LW; - pParam->BSIM3cgsl = model->BSIM3cgsl - + model->BSIM3lcgsl * Inv_L - + model->BSIM3wcgsl * Inv_W - + model->BSIM3pcgsl * Inv_LW; - pParam->BSIM3cgdl = model->BSIM3cgdl - + model->BSIM3lcgdl * Inv_L - + model->BSIM3wcgdl * Inv_W - + model->BSIM3pcgdl * Inv_LW; - pParam->BSIM3ckappa = model->BSIM3ckappa - + model->BSIM3lckappa * Inv_L - + model->BSIM3wckappa * Inv_W - + model->BSIM3pckappa * Inv_LW; - pParam->BSIM3cf = model->BSIM3cf - + model->BSIM3lcf * Inv_L - + model->BSIM3wcf * Inv_W - + model->BSIM3pcf * Inv_LW; - pParam->BSIM3clc = model->BSIM3clc - + model->BSIM3lclc * Inv_L - + model->BSIM3wclc * Inv_W - + model->BSIM3pclc * Inv_LW; - pParam->BSIM3cle = model->BSIM3cle - + model->BSIM3lcle * Inv_L - + model->BSIM3wcle * Inv_W - + model->BSIM3pcle * Inv_LW; - pParam->BSIM3vfbcv = model->BSIM3vfbcv - + model->BSIM3lvfbcv * Inv_L - + model->BSIM3wvfbcv * Inv_W - + model->BSIM3pvfbcv * Inv_LW; + pParam->BSIM3beta0 = model->BSIM3beta0 + + model->BSIM3lbeta0 * Inv_L + + model->BSIM3wbeta0 * Inv_W + + model->BSIM3pbeta0 * Inv_LW; + /* CV model */ + pParam->BSIM3elm = model->BSIM3elm + + model->BSIM3lelm * Inv_L + + model->BSIM3welm * Inv_W + + model->BSIM3pelm * Inv_LW; + pParam->BSIM3cgsl = model->BSIM3cgsl + + model->BSIM3lcgsl * Inv_L + + model->BSIM3wcgsl * Inv_W + + model->BSIM3pcgsl * Inv_LW; + pParam->BSIM3cgdl = model->BSIM3cgdl + + model->BSIM3lcgdl * Inv_L + + model->BSIM3wcgdl * Inv_W + + model->BSIM3pcgdl * Inv_LW; + pParam->BSIM3ckappa = model->BSIM3ckappa + + model->BSIM3lckappa * Inv_L + + model->BSIM3wckappa * Inv_W + + model->BSIM3pckappa * Inv_LW; + pParam->BSIM3cf = model->BSIM3cf + + model->BSIM3lcf * Inv_L + + model->BSIM3wcf * Inv_W + + model->BSIM3pcf * Inv_LW; + pParam->BSIM3clc = model->BSIM3clc + + model->BSIM3lclc * Inv_L + + model->BSIM3wclc * Inv_W + + model->BSIM3pclc * Inv_LW; + pParam->BSIM3cle = model->BSIM3cle + + model->BSIM3lcle * Inv_L + + model->BSIM3wcle * Inv_W + + model->BSIM3pcle * Inv_LW; + pParam->BSIM3vfbcv = model->BSIM3vfbcv + + model->BSIM3lvfbcv * Inv_L + + model->BSIM3wvfbcv * Inv_W + + model->BSIM3pvfbcv * Inv_LW; pParam->BSIM3acde = model->BSIM3acde + model->BSIM3lacde * Inv_L + model->BSIM3wacde * Inv_W @@ -588,35 +589,35 @@ int Size_Not_Found; + model->BSIM3pvoffcv * Inv_LW; pParam->BSIM3abulkCVfactor = 1.0 + pow((pParam->BSIM3clc - / pParam->BSIM3leffCV), - pParam->BSIM3cle); + / pParam->BSIM3leffCV), + pParam->BSIM3cle); - T0 = (TRatio - 1.0); - pParam->BSIM3ua = pParam->BSIM3ua + pParam->BSIM3ua1 * T0; - pParam->BSIM3ub = pParam->BSIM3ub + pParam->BSIM3ub1 * T0; - pParam->BSIM3uc = pParam->BSIM3uc + pParam->BSIM3uc1 * T0; - if (pParam->BSIM3u0 > 1.0) + T0 = (TRatio - 1.0); + pParam->BSIM3ua = pParam->BSIM3ua + pParam->BSIM3ua1 * T0; + pParam->BSIM3ub = pParam->BSIM3ub + pParam->BSIM3ub1 * T0; + pParam->BSIM3uc = pParam->BSIM3uc + pParam->BSIM3uc1 * T0; + if (pParam->BSIM3u0 > 1.0) pParam->BSIM3u0 = pParam->BSIM3u0 / 1.0e4; pParam->BSIM3u0temp = pParam->BSIM3u0 - * pow(TRatio, pParam->BSIM3ute); - pParam->BSIM3vsattemp = pParam->BSIM3vsat - pParam->BSIM3at - * T0; - pParam->BSIM3rds0 = (pParam->BSIM3rdsw + pParam->BSIM3prt * T0) + * pow(TRatio, pParam->BSIM3ute); + pParam->BSIM3vsattemp = pParam->BSIM3vsat - pParam->BSIM3at + * T0; + pParam->BSIM3rds0 = (pParam->BSIM3rdsw + pParam->BSIM3prt * T0) / pow(pParam->BSIM3weff * 1E6, pParam->BSIM3wr); - if (BSIM3checkModel(model, here, ckt)) - { IFuid namarray[2]; + if (BSIM3checkModel(model, here, ckt)) + { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; - SPfrontEnd->IFerror (ERR_FATAL, "Fatal error(s) detected during BSIM3V3.2 parameter checking for %s in model %s", namarray); - return(E_BADPARM); - } + SPfrontEnd->IFerror (ERR_FATAL, "Fatal error(s) detected during BSIM3V3.3 parameter checking for %s in model %s", namarray); + return(E_BADPARM); + } pParam->BSIM3cgdo = (model->BSIM3cgdo + pParam->BSIM3cf) - * pParam->BSIM3weffCV; + * pParam->BSIM3weffCV; pParam->BSIM3cgso = (model->BSIM3cgso + pParam->BSIM3cf) - * pParam->BSIM3weffCV; + * pParam->BSIM3weffCV; pParam->BSIM3cgbo = model->BSIM3cgbo * pParam->BSIM3leffCV; T0 = pParam->BSIM3leffCV * pParam->BSIM3leffCV; @@ -628,23 +629,23 @@ int Size_Not_Found; pParam->BSIM3npeak = 3.021E22 * T0 * T0; } - pParam->BSIM3phi = 2.0 * Vtm0 - * log(pParam->BSIM3npeak / ni); + pParam->BSIM3phi = 2.0 * Vtm0 + * log(pParam->BSIM3npeak / ni); - pParam->BSIM3sqrtPhi = sqrt(pParam->BSIM3phi); - pParam->BSIM3phis3 = pParam->BSIM3sqrtPhi * pParam->BSIM3phi; + pParam->BSIM3sqrtPhi = sqrt(pParam->BSIM3phi); + pParam->BSIM3phis3 = pParam->BSIM3sqrtPhi * pParam->BSIM3phi; pParam->BSIM3Xdep0 = sqrt(2.0 * EPSSI / (Charge_q - * pParam->BSIM3npeak * 1.0e6)) - * pParam->BSIM3sqrtPhi; + * pParam->BSIM3npeak * 1.0e6)) + * pParam->BSIM3sqrtPhi; pParam->BSIM3sqrtXdep0 = sqrt(pParam->BSIM3Xdep0); pParam->BSIM3litl = sqrt(3.0 * pParam->BSIM3xj - * model->BSIM3tox); + * model->BSIM3tox); pParam->BSIM3vbi = Vtm0 * log(1.0e20 - * pParam->BSIM3npeak / (ni * ni)); + * pParam->BSIM3npeak / (ni * ni)); pParam->BSIM3cdep0 = sqrt(Charge_q * EPSSI - * pParam->BSIM3npeak * 1.0e6 / 2.0 - / pParam->BSIM3phi); + * pParam->BSIM3npeak * 1.0e6 / 2.0 + / pParam->BSIM3phi); pParam->BSIM3ldeb = sqrt(EPSSI * Vtm0 / (Charge_q * pParam->BSIM3npeak * 1.0e6)) / 3.0; @@ -678,48 +679,48 @@ int Size_Not_Found; } } else - { if (!model->BSIM3vbxGiven) - pParam->BSIM3vbx = pParam->BSIM3phi - 7.7348e-4 + { if (!model->BSIM3vbxGiven) + pParam->BSIM3vbx = pParam->BSIM3phi - 7.7348e-4 * pParam->BSIM3npeak - * pParam->BSIM3xt * pParam->BSIM3xt; - if (pParam->BSIM3vbx > 0.0) - pParam->BSIM3vbx = -pParam->BSIM3vbx; - if (pParam->BSIM3vbm > 0.0) + * pParam->BSIM3xt * pParam->BSIM3xt; + if (pParam->BSIM3vbx > 0.0) + pParam->BSIM3vbx = -pParam->BSIM3vbx; + if (pParam->BSIM3vbm > 0.0) pParam->BSIM3vbm = -pParam->BSIM3vbm; - + if (!model->BSIM3gamma1Given) pParam->BSIM3gamma1 = 5.753e-12 - * sqrt(pParam->BSIM3npeak) + * sqrt(pParam->BSIM3npeak) / model->BSIM3cox; if (!model->BSIM3gamma2Given) pParam->BSIM3gamma2 = 5.753e-12 - * sqrt(pParam->BSIM3nsub) + * sqrt(pParam->BSIM3nsub) / model->BSIM3cox; T0 = pParam->BSIM3gamma1 - pParam->BSIM3gamma2; T1 = sqrt(pParam->BSIM3phi - pParam->BSIM3vbx) - - pParam->BSIM3sqrtPhi; + - pParam->BSIM3sqrtPhi; T2 = sqrt(pParam->BSIM3phi * (pParam->BSIM3phi - - pParam->BSIM3vbm)) - pParam->BSIM3phi; + - pParam->BSIM3vbm)) - pParam->BSIM3phi; pParam->BSIM3k2 = T0 * T1 / (2.0 * T2 + pParam->BSIM3vbm); pParam->BSIM3k1 = pParam->BSIM3gamma2 - 2.0 - * pParam->BSIM3k2 * sqrt(pParam->BSIM3phi - - pParam->BSIM3vbm); + * pParam->BSIM3k2 * sqrt(pParam->BSIM3phi + - pParam->BSIM3vbm); } - - if (pParam->BSIM3k2 < 0.0) - { T0 = 0.5 * pParam->BSIM3k1 / pParam->BSIM3k2; + + if (pParam->BSIM3k2 < 0.0) + { T0 = 0.5 * pParam->BSIM3k1 / pParam->BSIM3k2; pParam->BSIM3vbsc = 0.9 * (pParam->BSIM3phi - T0 * T0); - if (pParam->BSIM3vbsc > -3.0) - pParam->BSIM3vbsc = -3.0; - else if (pParam->BSIM3vbsc < -30.0) - pParam->BSIM3vbsc = -30.0; - } - else - { pParam->BSIM3vbsc = -30.0; - } - if (pParam->BSIM3vbsc > pParam->BSIM3vbm) - pParam->BSIM3vbsc = pParam->BSIM3vbm; + if (pParam->BSIM3vbsc > -3.0) + pParam->BSIM3vbsc = -3.0; + else if (pParam->BSIM3vbsc < -30.0) + pParam->BSIM3vbsc = -30.0; + } + else + { pParam->BSIM3vbsc = -30.0; + } + if (pParam->BSIM3vbsc > pParam->BSIM3vbm) + pParam->BSIM3vbsc = pParam->BSIM3vbm; if (!model->BSIM3vfbGiven) { if (model->BSIM3vth0Given) @@ -743,14 +744,14 @@ int Size_Not_Found; / model->BSIM3toxm; T1 = sqrt(EPSSI / EPSOX * model->BSIM3tox - * pParam->BSIM3Xdep0); + * pParam->BSIM3Xdep0); T0 = exp(-0.5 * pParam->BSIM3dsub * pParam->BSIM3leff / T1); pParam->BSIM3theta0vb0 = (T0 + 2.0 * T0 * T0); T0 = exp(-0.5 * pParam->BSIM3drout * pParam->BSIM3leff / T1); T2 = (T0 + 2.0 * T0 * T0); pParam->BSIM3thetaRout = pParam->BSIM3pdibl1 * T2 - + pParam->BSIM3pdibl2; + + pParam->BSIM3pdibl2; tmp = sqrt(pParam->BSIM3Xdep0); tmp1 = pParam->BSIM3vbi - pParam->BSIM3phi; @@ -795,24 +796,63 @@ int Size_Not_Found; /* End of vfbzb */ } + /* adding delvto */ + here->BSIM3vth0 = pParam->BSIM3vth0 + here->BSIM3delvto; + here->BSIM3vfb = pParam->BSIM3vfb + model->BSIM3type * here->BSIM3delvto; + here->BSIM3vfbzb = pParam->BSIM3vfbzb + model->BSIM3type * here->BSIM3delvto; + + /* low field mobility multiplier */ + here->BSIM3u0temp = pParam->BSIM3u0temp * here->BSIM3mulu0; + here->BSIM3tconst = here->BSIM3u0temp * pParam->BSIM3elm / (model->BSIM3cox + * pParam->BSIM3weffCV * pParam->BSIM3leffCV * T0); + /* process source/drain series resistance */ - here->BSIM3drainConductance = model->BSIM3sheetResistance - * here->BSIM3drainSquares; + /* ACM model */ + if (model->BSIM3acmMod == 0) + { + here->BSIM3drainConductance = model->BSIM3sheetResistance + * here->BSIM3drainSquares; + here->BSIM3sourceConductance = model->BSIM3sheetResistance + * here->BSIM3sourceSquares; + } + else /* ACM > 0 */ + { + error = ACM_SourceDrainResistances( + model->BSIM3acmMod, + model->BSIM3ld, + model->BSIM3ldif, + model->BSIM3hdif, + model->BSIM3wmlt, + here->BSIM3w, + model->BSIM3xw, + model->BSIM3sheetResistance, + here->BSIM3drainSquaresGiven, + model->BSIM3rd, + model->BSIM3rdc, + here->BSIM3drainSquares, + here->BSIM3sourceSquaresGiven, + model->BSIM3rs, + model->BSIM3rsc, + here->BSIM3sourceSquares, + &(here->BSIM3drainConductance), + &(here->BSIM3sourceConductance) + ); + if (error) + return(error); + } if (here->BSIM3drainConductance > 0.0) here->BSIM3drainConductance = 1.0 - / here->BSIM3drainConductance; - else + / here->BSIM3drainConductance; + else here->BSIM3drainConductance = 0.0; - - here->BSIM3sourceConductance = model->BSIM3sheetResistance - * here->BSIM3sourceSquares; - if (here->BSIM3sourceConductance > 0.0) + + if (here->BSIM3sourceConductance > 0.0) here->BSIM3sourceConductance = 1.0 - / here->BSIM3sourceConductance; - else + / here->BSIM3sourceConductance; + else here->BSIM3sourceConductance = 0.0; - here->BSIM3cgso = pParam->BSIM3cgso; - here->BSIM3cgdo = pParam->BSIM3cgdo; + here->BSIM3cgso = pParam->BSIM3cgso; + here->BSIM3cgdo = pParam->BSIM3cgdo; Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; if ((here->BSIM3sourceArea <= 0.0) && diff --git a/src/spicelib/devices/bsim3/bsim3def.h b/src/spicelib/devices/bsim3/bsim3def.h index b92b49621..6418abf9f 100644 --- a/src/spicelib/devices/bsim3/bsim3def.h +++ b/src/spicelib/devices/bsim3/bsim3def.h @@ -14,7 +14,7 @@ File: bsim3def.h #include "ngspice/gendefs.h" #include "ngspice/cktdefs.h" #include "ngspice/complex.h" -#include "ngspice/noisedef.h" +#include "ngspice/noisedef.h" typedef struct sBSIM3instance { @@ -32,7 +32,7 @@ typedef struct sBSIM3instance /* MCJ */ double BSIM3ueff; - double BSIM3thetavth; + double BSIM3thetavth; double BSIM3von; double BSIM3vdsat; double BSIM3cgdo; @@ -44,7 +44,7 @@ typedef struct sBSIM3instance double BSIM3l; double BSIM3w; - double BSIM3m; + double BSIM3m; double BSIM3drainArea; double BSIM3sourceArea; double BSIM3drainSquares; @@ -53,6 +53,13 @@ typedef struct sBSIM3instance double BSIM3sourcePerimeter; double BSIM3sourceConductance; double BSIM3drainConductance; + double BSIM3delvto; + double BSIM3mulu0; + double BSIM3vth0; + double BSIM3vfb; + double BSIM3vfbzb; + double BSIM3u0temp; + double BSIM3tconst; double BSIM3icVBS; double BSIM3icVDS; @@ -61,6 +68,7 @@ typedef struct sBSIM3instance int BSIM3mode; int BSIM3nqsMod; int BSIM3acnqsMod; + int BSIM3geo; /* OP point */ double BSIM3qinv; @@ -115,13 +123,15 @@ typedef struct sBSIM3instance unsigned BSIM3lGiven :1; unsigned BSIM3wGiven :1; - unsigned BSIM3mGiven :1; + unsigned BSIM3mGiven :1; unsigned BSIM3drainAreaGiven :1; unsigned BSIM3sourceAreaGiven :1; unsigned BSIM3drainSquaresGiven :1; unsigned BSIM3sourceSquaresGiven :1; unsigned BSIM3drainPerimeterGiven :1; unsigned BSIM3sourcePerimeterGiven :1; + unsigned BSIM3delvtoGiven :1; + unsigned BSIM3mulu0Given :1; unsigned BSIM3dNodePrimeSet :1; unsigned BSIM3sNodePrimeSet :1; unsigned BSIM3icVBSGiven :1; @@ -129,6 +139,7 @@ typedef struct sBSIM3instance unsigned BSIM3icVGSGiven :1; unsigned BSIM3nqsModGiven :1; unsigned BSIM3acnqsModGiven :1; + unsigned BSIM3geoGiven :1; double *BSIM3DdPtr; double *BSIM3GgPtr; @@ -287,29 +298,29 @@ struct bsim3SizeDependParam double Width; double Length; - double BSIM3cdsc; - double BSIM3cdscb; - double BSIM3cdscd; - double BSIM3cit; - double BSIM3nfactor; + double BSIM3cdsc; + double BSIM3cdscb; + double BSIM3cdscd; + double BSIM3cit; + double BSIM3nfactor; double BSIM3xj; - double BSIM3vsat; - double BSIM3at; - double BSIM3a0; - double BSIM3ags; - double BSIM3a1; - double BSIM3a2; - double BSIM3keta; + double BSIM3vsat; + double BSIM3at; + double BSIM3a0; + double BSIM3ags; + double BSIM3a1; + double BSIM3a2; + double BSIM3keta; double BSIM3nsub; - double BSIM3npeak; - double BSIM3ngate; - double BSIM3gamma1; - double BSIM3gamma2; - double BSIM3vbx; - double BSIM3vbi; - double BSIM3vbm; - double BSIM3vbsc; - double BSIM3xt; + double BSIM3npeak; + double BSIM3ngate; + double BSIM3gamma1; + double BSIM3gamma2; + double BSIM3vbx; + double BSIM3vbi; + double BSIM3vbm; + double BSIM3vbsc; + double BSIM3xt; double BSIM3phi; double BSIM3litl; double BSIM3k1; @@ -321,14 +332,14 @@ struct bsim3SizeDependParam double BSIM3k3b; double BSIM3w0; double BSIM3nlx; - double BSIM3dvt0; - double BSIM3dvt1; - double BSIM3dvt2; - double BSIM3dvt0w; - double BSIM3dvt1w; - double BSIM3dvt2w; - double BSIM3drout; - double BSIM3dsub; + double BSIM3dvt0; + double BSIM3dvt1; + double BSIM3dvt2; + double BSIM3dvt0w; + double BSIM3dvt1w; + double BSIM3dvt2w; + double BSIM3drout; + double BSIM3dsub; double BSIM3vth0; double BSIM3ua; double BSIM3ua1; @@ -341,20 +352,20 @@ struct bsim3SizeDependParam double BSIM3voff; double BSIM3vfb; double BSIM3delta; - double BSIM3rdsw; - double BSIM3rds0; - double BSIM3prwg; - double BSIM3prwb; - double BSIM3prt; - double BSIM3eta0; - double BSIM3etab; - double BSIM3pclm; - double BSIM3pdibl1; - double BSIM3pdibl2; - double BSIM3pdiblb; - double BSIM3pscbe1; - double BSIM3pscbe2; - double BSIM3pvag; + double BSIM3rdsw; + double BSIM3rds0; + double BSIM3prwg; + double BSIM3prwb; + double BSIM3prt; + double BSIM3eta0; + double BSIM3etab; + double BSIM3pclm; + double BSIM3pdibl1; + double BSIM3pdibl2; + double BSIM3pdiblb; + double BSIM3pscbe1; + double BSIM3pscbe2; + double BSIM3pvag; double BSIM3wr; double BSIM3dwg; double BSIM3dwb; @@ -397,14 +408,14 @@ struct bsim3SizeDependParam double BSIM3cgbo; double BSIM3tconst; - double BSIM3u0temp; - double BSIM3vsattemp; - double BSIM3sqrtPhi; - double BSIM3phis3; - double BSIM3Xdep0; - double BSIM3sqrtXdep0; + double BSIM3u0temp; + double BSIM3vsattemp; + double BSIM3sqrtPhi; + double BSIM3phis3; + double BSIM3Xdep0; + double BSIM3sqrtXdep0; double BSIM3theta0vb0; - double BSIM3thetaRout; + double BSIM3thetaRout; double BSIM3cof1; double BSIM3cof2; @@ -420,44 +431,47 @@ struct bsim3SizeDependParam }; -typedef struct sBSIM3model +typedef struct sBSIM3model { int BSIM3modType; struct sBSIM3model *BSIM3nextModel; BSIM3instance *BSIM3instances; - IFuid BSIM3modName; + IFuid BSIM3modName; int BSIM3type; int BSIM3mobMod; int BSIM3capMod; + int BSIM3acmMod; + int BSIM3calcacm; int BSIM3noiMod; + int BSIM3nqsMod; int BSIM3acnqsMod; int BSIM3binUnit; int BSIM3paramChk; - char *BSIM3version; - double BSIM3tox; + char *BSIM3version; + double BSIM3tox; double BSIM3toxm; - double BSIM3cdsc; - double BSIM3cdscb; - double BSIM3cdscd; - double BSIM3cit; - double BSIM3nfactor; + double BSIM3cdsc; + double BSIM3cdscb; + double BSIM3cdscd; + double BSIM3cit; + double BSIM3nfactor; double BSIM3xj; - double BSIM3vsat; - double BSIM3at; - double BSIM3a0; - double BSIM3ags; - double BSIM3a1; - double BSIM3a2; - double BSIM3keta; + double BSIM3vsat; + double BSIM3at; + double BSIM3a0; + double BSIM3ags; + double BSIM3a1; + double BSIM3a2; + double BSIM3keta; double BSIM3nsub; - double BSIM3npeak; - double BSIM3ngate; - double BSIM3gamma1; - double BSIM3gamma2; - double BSIM3vbx; - double BSIM3vbm; - double BSIM3xt; + double BSIM3npeak; + double BSIM3ngate; + double BSIM3gamma1; + double BSIM3gamma2; + double BSIM3vbx; + double BSIM3vbm; + double BSIM3xt; double BSIM3k1; double BSIM3kt1; double BSIM3kt1l; @@ -467,14 +481,14 @@ typedef struct sBSIM3model double BSIM3k3b; double BSIM3w0; double BSIM3nlx; - double BSIM3dvt0; - double BSIM3dvt1; - double BSIM3dvt2; - double BSIM3dvt0w; - double BSIM3dvt1w; - double BSIM3dvt2w; - double BSIM3drout; - double BSIM3dsub; + double BSIM3dvt0; + double BSIM3dvt1; + double BSIM3dvt2; + double BSIM3dvt0w; + double BSIM3dvt1w; + double BSIM3dvt2w; + double BSIM3drout; + double BSIM3dsub; double BSIM3vth0; double BSIM3ua; double BSIM3ua1; @@ -486,19 +500,19 @@ typedef struct sBSIM3model double BSIM3ute; double BSIM3voff; double BSIM3delta; - double BSIM3rdsw; + double BSIM3rdsw; double BSIM3prwg; double BSIM3prwb; - double BSIM3prt; - double BSIM3eta0; - double BSIM3etab; - double BSIM3pclm; - double BSIM3pdibl1; - double BSIM3pdibl2; + double BSIM3prt; + double BSIM3eta0; + double BSIM3etab; + double BSIM3pclm; + double BSIM3pdibl1; + double BSIM3pdibl2; double BSIM3pdiblb; - double BSIM3pscbe1; - double BSIM3pscbe2; - double BSIM3pvag; + double BSIM3pscbe1; + double BSIM3pscbe2; + double BSIM3pvag; double BSIM3wr; double BSIM3dwg; double BSIM3dwb; @@ -532,28 +546,40 @@ typedef struct sBSIM3model double BSIM3tpbsw; double BSIM3tpbswg; + /* ACM model */ + double BSIM3xl; + double BSIM3xw; + double BSIM3hdif; + double BSIM3ldif; + double BSIM3ld; + double BSIM3rd; + double BSIM3rs; + double BSIM3rdc; + double BSIM3rsc; + double BSIM3wmlt; + /* Length Dependence */ - double BSIM3lcdsc; - double BSIM3lcdscb; - double BSIM3lcdscd; - double BSIM3lcit; - double BSIM3lnfactor; + double BSIM3lcdsc; + double BSIM3lcdscb; + double BSIM3lcdscd; + double BSIM3lcit; + double BSIM3lnfactor; double BSIM3lxj; - double BSIM3lvsat; - double BSIM3lat; - double BSIM3la0; - double BSIM3lags; - double BSIM3la1; - double BSIM3la2; - double BSIM3lketa; + double BSIM3lvsat; + double BSIM3lat; + double BSIM3la0; + double BSIM3lags; + double BSIM3la1; + double BSIM3la2; + double BSIM3lketa; double BSIM3lnsub; - double BSIM3lnpeak; - double BSIM3lngate; - double BSIM3lgamma1; - double BSIM3lgamma2; - double BSIM3lvbx; - double BSIM3lvbm; - double BSIM3lxt; + double BSIM3lnpeak; + double BSIM3lngate; + double BSIM3lgamma1; + double BSIM3lgamma2; + double BSIM3lvbx; + double BSIM3lvbm; + double BSIM3lxt; double BSIM3lk1; double BSIM3lkt1; double BSIM3lkt1l; @@ -563,14 +589,14 @@ typedef struct sBSIM3model double BSIM3lk3b; double BSIM3lw0; double BSIM3lnlx; - double BSIM3ldvt0; - double BSIM3ldvt1; - double BSIM3ldvt2; - double BSIM3ldvt0w; - double BSIM3ldvt1w; - double BSIM3ldvt2w; - double BSIM3ldrout; - double BSIM3ldsub; + double BSIM3ldvt0; + double BSIM3ldvt1; + double BSIM3ldvt2; + double BSIM3ldvt0w; + double BSIM3ldvt1w; + double BSIM3ldvt2w; + double BSIM3ldrout; + double BSIM3ldsub; double BSIM3lvth0; double BSIM3lua; double BSIM3lua1; @@ -582,19 +608,19 @@ typedef struct sBSIM3model double BSIM3lute; double BSIM3lvoff; double BSIM3ldelta; - double BSIM3lrdsw; + double BSIM3lrdsw; double BSIM3lprwg; double BSIM3lprwb; - double BSIM3lprt; - double BSIM3leta0; - double BSIM3letab; - double BSIM3lpclm; - double BSIM3lpdibl1; - double BSIM3lpdibl2; + double BSIM3lprt; + double BSIM3leta0; + double BSIM3letab; + double BSIM3lpclm; + double BSIM3lpdibl1; + double BSIM3lpdibl2; double BSIM3lpdiblb; - double BSIM3lpscbe1; - double BSIM3lpscbe2; - double BSIM3lpvag; + double BSIM3lpscbe1; + double BSIM3lpscbe2; + double BSIM3lpvag; double BSIM3lwr; double BSIM3ldwg; double BSIM3ldwb; @@ -620,27 +646,27 @@ typedef struct sBSIM3model double BSIM3lmoin; /* Width Dependence */ - double BSIM3wcdsc; - double BSIM3wcdscb; - double BSIM3wcdscd; - double BSIM3wcit; - double BSIM3wnfactor; + double BSIM3wcdsc; + double BSIM3wcdscb; + double BSIM3wcdscd; + double BSIM3wcit; + double BSIM3wnfactor; double BSIM3wxj; - double BSIM3wvsat; - double BSIM3wat; - double BSIM3wa0; - double BSIM3wags; - double BSIM3wa1; - double BSIM3wa2; - double BSIM3wketa; + double BSIM3wvsat; + double BSIM3wat; + double BSIM3wa0; + double BSIM3wags; + double BSIM3wa1; + double BSIM3wa2; + double BSIM3wketa; double BSIM3wnsub; - double BSIM3wnpeak; - double BSIM3wngate; - double BSIM3wgamma1; - double BSIM3wgamma2; - double BSIM3wvbx; - double BSIM3wvbm; - double BSIM3wxt; + double BSIM3wnpeak; + double BSIM3wngate; + double BSIM3wgamma1; + double BSIM3wgamma2; + double BSIM3wvbx; + double BSIM3wvbm; + double BSIM3wxt; double BSIM3wk1; double BSIM3wkt1; double BSIM3wkt1l; @@ -650,14 +676,14 @@ typedef struct sBSIM3model double BSIM3wk3b; double BSIM3ww0; double BSIM3wnlx; - double BSIM3wdvt0; - double BSIM3wdvt1; - double BSIM3wdvt2; - double BSIM3wdvt0w; - double BSIM3wdvt1w; - double BSIM3wdvt2w; - double BSIM3wdrout; - double BSIM3wdsub; + double BSIM3wdvt0; + double BSIM3wdvt1; + double BSIM3wdvt2; + double BSIM3wdvt0w; + double BSIM3wdvt1w; + double BSIM3wdvt2w; + double BSIM3wdrout; + double BSIM3wdsub; double BSIM3wvth0; double BSIM3wua; double BSIM3wua1; @@ -669,19 +695,19 @@ typedef struct sBSIM3model double BSIM3wute; double BSIM3wvoff; double BSIM3wdelta; - double BSIM3wrdsw; + double BSIM3wrdsw; double BSIM3wprwg; double BSIM3wprwb; - double BSIM3wprt; - double BSIM3weta0; - double BSIM3wetab; - double BSIM3wpclm; - double BSIM3wpdibl1; - double BSIM3wpdibl2; + double BSIM3wprt; + double BSIM3weta0; + double BSIM3wetab; + double BSIM3wpclm; + double BSIM3wpdibl1; + double BSIM3wpdibl2; double BSIM3wpdiblb; - double BSIM3wpscbe1; - double BSIM3wpscbe2; - double BSIM3wpvag; + double BSIM3wpscbe1; + double BSIM3wpscbe2; + double BSIM3wpvag; double BSIM3wwr; double BSIM3wdwg; double BSIM3wdwb; @@ -707,27 +733,27 @@ typedef struct sBSIM3model double BSIM3wmoin; /* Cross-term Dependence */ - double BSIM3pcdsc; - double BSIM3pcdscb; - double BSIM3pcdscd; - double BSIM3pcit; - double BSIM3pnfactor; + double BSIM3pcdsc; + double BSIM3pcdscb; + double BSIM3pcdscd; + double BSIM3pcit; + double BSIM3pnfactor; double BSIM3pxj; - double BSIM3pvsat; - double BSIM3pat; - double BSIM3pa0; - double BSIM3pags; - double BSIM3pa1; - double BSIM3pa2; - double BSIM3pketa; + double BSIM3pvsat; + double BSIM3pat; + double BSIM3pa0; + double BSIM3pags; + double BSIM3pa1; + double BSIM3pa2; + double BSIM3pketa; double BSIM3pnsub; - double BSIM3pnpeak; - double BSIM3pngate; - double BSIM3pgamma1; - double BSIM3pgamma2; - double BSIM3pvbx; - double BSIM3pvbm; - double BSIM3pxt; + double BSIM3pnpeak; + double BSIM3pngate; + double BSIM3pgamma1; + double BSIM3pgamma2; + double BSIM3pvbx; + double BSIM3pvbm; + double BSIM3pxt; double BSIM3pk1; double BSIM3pkt1; double BSIM3pkt1l; @@ -737,14 +763,14 @@ typedef struct sBSIM3model double BSIM3pk3b; double BSIM3pw0; double BSIM3pnlx; - double BSIM3pdvt0; - double BSIM3pdvt1; - double BSIM3pdvt2; - double BSIM3pdvt0w; - double BSIM3pdvt1w; - double BSIM3pdvt2w; - double BSIM3pdrout; - double BSIM3pdsub; + double BSIM3pdvt0; + double BSIM3pdvt1; + double BSIM3pdvt2; + double BSIM3pdvt0w; + double BSIM3pdvt1w; + double BSIM3pdvt2w; + double BSIM3pdrout; + double BSIM3pdsub; double BSIM3pvth0; double BSIM3pua; double BSIM3pua1; @@ -759,16 +785,16 @@ typedef struct sBSIM3model double BSIM3prdsw; double BSIM3pprwg; double BSIM3pprwb; - double BSIM3pprt; - double BSIM3peta0; - double BSIM3petab; - double BSIM3ppclm; - double BSIM3ppdibl1; - double BSIM3ppdibl2; + double BSIM3pprt; + double BSIM3peta0; + double BSIM3petab; + double BSIM3ppclm; + double BSIM3ppdibl1; + double BSIM3ppdibl2; double BSIM3ppdiblb; - double BSIM3ppscbe1; - double BSIM3ppscbe2; - double BSIM3ppvag; + double BSIM3ppscbe1; + double BSIM3ppscbe2; + double BSIM3ppvag; double BSIM3pwr; double BSIM3pdwg; double BSIM3pdwb; @@ -843,7 +869,7 @@ typedef struct sBSIM3model /* Pre-calculated constants */ /* MCJ: move to size-dependent param. */ - double BSIM3vtm; + double BSIM3vtm; double BSIM3cox; double BSIM3cof1; double BSIM3cof2; @@ -860,18 +886,18 @@ typedef struct sBSIM3model double BSIM3unitLengthSidewallTempJctCap; double BSIM3unitLengthGateSidewallTempJctCap; - double BSIM3oxideTrapDensityA; - double BSIM3oxideTrapDensityB; - double BSIM3oxideTrapDensityC; - double BSIM3em; - double BSIM3ef; - double BSIM3af; - double BSIM3kf; + double BSIM3oxideTrapDensityA; + double BSIM3oxideTrapDensityB; + double BSIM3oxideTrapDensityC; + double BSIM3em; + double BSIM3ef; + double BSIM3af; + double BSIM3kf; double BSIM3lintnoi; /* lint offset for noise calculation */ struct bsim3SizeDependParam *pSizeDependParamKnot; - + #ifdef USE_OMP int BSIM3InstCount; struct sBSIM3instance **BSIM3InstanceArray; @@ -881,8 +907,11 @@ typedef struct sBSIM3model unsigned BSIM3mobModGiven :1; unsigned BSIM3binUnitGiven :1; unsigned BSIM3capModGiven :1; + unsigned BSIM3acmModGiven :1; + unsigned BSIM3calcacmGiven :1; unsigned BSIM3paramChkGiven :1; unsigned BSIM3noiModGiven :1; + unsigned BSIM3nqsModGiven :1; unsigned BSIM3acnqsModGiven :1; unsigned BSIM3typeGiven :1; unsigned BSIM3toxGiven :1; @@ -900,7 +929,7 @@ typedef struct sBSIM3model unsigned BSIM3agsGiven :1; unsigned BSIM3a1Given :1; unsigned BSIM3a2Given :1; - unsigned BSIM3ketaGiven :1; + unsigned BSIM3ketaGiven :1; unsigned BSIM3nsubGiven :1; unsigned BSIM3npeakGiven :1; unsigned BSIM3ngateGiven :1; @@ -918,14 +947,14 @@ typedef struct sBSIM3model unsigned BSIM3k3bGiven :1; unsigned BSIM3w0Given :1; unsigned BSIM3nlxGiven :1; - unsigned BSIM3dvt0Given :1; - unsigned BSIM3dvt1Given :1; - unsigned BSIM3dvt2Given :1; - unsigned BSIM3dvt0wGiven :1; - unsigned BSIM3dvt1wGiven :1; - unsigned BSIM3dvt2wGiven :1; - unsigned BSIM3droutGiven :1; - unsigned BSIM3dsubGiven :1; + unsigned BSIM3dvt0Given :1; + unsigned BSIM3dvt1Given :1; + unsigned BSIM3dvt2Given :1; + unsigned BSIM3dvt0wGiven :1; + unsigned BSIM3dvt1wGiven :1; + unsigned BSIM3dvt2wGiven :1; + unsigned BSIM3droutGiven :1; + unsigned BSIM3dsubGiven :1; unsigned BSIM3vth0Given :1; unsigned BSIM3uaGiven :1; unsigned BSIM3ua1Given :1; @@ -936,20 +965,20 @@ typedef struct sBSIM3model unsigned BSIM3u0Given :1; unsigned BSIM3uteGiven :1; unsigned BSIM3voffGiven :1; - unsigned BSIM3rdswGiven :1; - unsigned BSIM3prwgGiven :1; - unsigned BSIM3prwbGiven :1; - unsigned BSIM3prtGiven :1; - unsigned BSIM3eta0Given :1; - unsigned BSIM3etabGiven :1; - unsigned BSIM3pclmGiven :1; - unsigned BSIM3pdibl1Given :1; - unsigned BSIM3pdibl2Given :1; - unsigned BSIM3pdiblbGiven :1; - unsigned BSIM3pscbe1Given :1; - unsigned BSIM3pscbe2Given :1; - unsigned BSIM3pvagGiven :1; - unsigned BSIM3deltaGiven :1; + unsigned BSIM3rdswGiven :1; + unsigned BSIM3prwgGiven :1; + unsigned BSIM3prwbGiven :1; + unsigned BSIM3prtGiven :1; + unsigned BSIM3eta0Given :1; + unsigned BSIM3etabGiven :1; + unsigned BSIM3pclmGiven :1; + unsigned BSIM3pdibl1Given :1; + unsigned BSIM3pdibl2Given :1; + unsigned BSIM3pdiblbGiven :1; + unsigned BSIM3pscbe1Given :1; + unsigned BSIM3pscbe2Given :1; + unsigned BSIM3pvagGiven :1; + unsigned BSIM3deltaGiven :1; unsigned BSIM3wrGiven :1; unsigned BSIM3dwgGiven :1; unsigned BSIM3dwbGiven :1; @@ -962,7 +991,7 @@ typedef struct sBSIM3model unsigned BSIM3vfbGiven :1; /* CV model */ - unsigned BSIM3elmGiven :1; + unsigned BSIM3elmGiven :1; unsigned BSIM3cgslGiven :1; unsigned BSIM3cgdlGiven :1; unsigned BSIM3ckappaGiven :1; @@ -983,6 +1012,17 @@ typedef struct sBSIM3model unsigned BSIM3tpbswGiven :1; unsigned BSIM3tpbswgGiven :1; + /* ACM model */ + unsigned BSIM3xlGiven :1; + unsigned BSIM3xwGiven :1; + unsigned BSIM3hdifGiven :1; + unsigned BSIM3ldifGiven :1; + unsigned BSIM3ldGiven :1; + unsigned BSIM3rdGiven :1; + unsigned BSIM3rsGiven :1; + unsigned BSIM3rdcGiven :1; + unsigned BSIM3rscGiven :1; + unsigned BSIM3wmltGiven :1; /* Length dependence */ unsigned BSIM3lcdscGiven :1; @@ -997,7 +1037,7 @@ typedef struct sBSIM3model unsigned BSIM3lagsGiven :1; unsigned BSIM3la1Given :1; unsigned BSIM3la2Given :1; - unsigned BSIM3lketaGiven :1; + unsigned BSIM3lketaGiven :1; unsigned BSIM3lnsubGiven :1; unsigned BSIM3lnpeakGiven :1; unsigned BSIM3lngateGiven :1; @@ -1015,14 +1055,14 @@ typedef struct sBSIM3model unsigned BSIM3lk3bGiven :1; unsigned BSIM3lw0Given :1; unsigned BSIM3lnlxGiven :1; - unsigned BSIM3ldvt0Given :1; - unsigned BSIM3ldvt1Given :1; - unsigned BSIM3ldvt2Given :1; - unsigned BSIM3ldvt0wGiven :1; - unsigned BSIM3ldvt1wGiven :1; - unsigned BSIM3ldvt2wGiven :1; - unsigned BSIM3ldroutGiven :1; - unsigned BSIM3ldsubGiven :1; + unsigned BSIM3ldvt0Given :1; + unsigned BSIM3ldvt1Given :1; + unsigned BSIM3ldvt2Given :1; + unsigned BSIM3ldvt0wGiven :1; + unsigned BSIM3ldvt1wGiven :1; + unsigned BSIM3ldvt2wGiven :1; + unsigned BSIM3ldroutGiven :1; + unsigned BSIM3ldsubGiven :1; unsigned BSIM3lvth0Given :1; unsigned BSIM3luaGiven :1; unsigned BSIM3lua1Given :1; @@ -1033,20 +1073,20 @@ typedef struct sBSIM3model unsigned BSIM3lu0Given :1; unsigned BSIM3luteGiven :1; unsigned BSIM3lvoffGiven :1; - unsigned BSIM3lrdswGiven :1; - unsigned BSIM3lprwgGiven :1; - unsigned BSIM3lprwbGiven :1; - unsigned BSIM3lprtGiven :1; - unsigned BSIM3leta0Given :1; - unsigned BSIM3letabGiven :1; - unsigned BSIM3lpclmGiven :1; - unsigned BSIM3lpdibl1Given :1; - unsigned BSIM3lpdibl2Given :1; - unsigned BSIM3lpdiblbGiven :1; - unsigned BSIM3lpscbe1Given :1; - unsigned BSIM3lpscbe2Given :1; - unsigned BSIM3lpvagGiven :1; - unsigned BSIM3ldeltaGiven :1; + unsigned BSIM3lrdswGiven :1; + unsigned BSIM3lprwgGiven :1; + unsigned BSIM3lprwbGiven :1; + unsigned BSIM3lprtGiven :1; + unsigned BSIM3leta0Given :1; + unsigned BSIM3letabGiven :1; + unsigned BSIM3lpclmGiven :1; + unsigned BSIM3lpdibl1Given :1; + unsigned BSIM3lpdibl2Given :1; + unsigned BSIM3lpdiblbGiven :1; + unsigned BSIM3lpscbe1Given :1; + unsigned BSIM3lpscbe2Given :1; + unsigned BSIM3lpvagGiven :1; + unsigned BSIM3ldeltaGiven :1; unsigned BSIM3lwrGiven :1; unsigned BSIM3ldwgGiven :1; unsigned BSIM3ldwbGiven :1; @@ -1058,7 +1098,7 @@ typedef struct sBSIM3model unsigned BSIM3lvfbGiven :1; /* CV model */ - unsigned BSIM3lelmGiven :1; + unsigned BSIM3lelmGiven :1; unsigned BSIM3lcgslGiven :1; unsigned BSIM3lcgdlGiven :1; unsigned BSIM3lckappaGiven :1; @@ -1084,7 +1124,7 @@ typedef struct sBSIM3model unsigned BSIM3wagsGiven :1; unsigned BSIM3wa1Given :1; unsigned BSIM3wa2Given :1; - unsigned BSIM3wketaGiven :1; + unsigned BSIM3wketaGiven :1; unsigned BSIM3wnsubGiven :1; unsigned BSIM3wnpeakGiven :1; unsigned BSIM3wngateGiven :1; @@ -1102,14 +1142,14 @@ typedef struct sBSIM3model unsigned BSIM3wk3bGiven :1; unsigned BSIM3ww0Given :1; unsigned BSIM3wnlxGiven :1; - unsigned BSIM3wdvt0Given :1; - unsigned BSIM3wdvt1Given :1; - unsigned BSIM3wdvt2Given :1; - unsigned BSIM3wdvt0wGiven :1; - unsigned BSIM3wdvt1wGiven :1; - unsigned BSIM3wdvt2wGiven :1; - unsigned BSIM3wdroutGiven :1; - unsigned BSIM3wdsubGiven :1; + unsigned BSIM3wdvt0Given :1; + unsigned BSIM3wdvt1Given :1; + unsigned BSIM3wdvt2Given :1; + unsigned BSIM3wdvt0wGiven :1; + unsigned BSIM3wdvt1wGiven :1; + unsigned BSIM3wdvt2wGiven :1; + unsigned BSIM3wdroutGiven :1; + unsigned BSIM3wdsubGiven :1; unsigned BSIM3wvth0Given :1; unsigned BSIM3wuaGiven :1; unsigned BSIM3wua1Given :1; @@ -1120,20 +1160,20 @@ typedef struct sBSIM3model unsigned BSIM3wu0Given :1; unsigned BSIM3wuteGiven :1; unsigned BSIM3wvoffGiven :1; - unsigned BSIM3wrdswGiven :1; - unsigned BSIM3wprwgGiven :1; - unsigned BSIM3wprwbGiven :1; - unsigned BSIM3wprtGiven :1; - unsigned BSIM3weta0Given :1; - unsigned BSIM3wetabGiven :1; - unsigned BSIM3wpclmGiven :1; - unsigned BSIM3wpdibl1Given :1; - unsigned BSIM3wpdibl2Given :1; - unsigned BSIM3wpdiblbGiven :1; - unsigned BSIM3wpscbe1Given :1; - unsigned BSIM3wpscbe2Given :1; - unsigned BSIM3wpvagGiven :1; - unsigned BSIM3wdeltaGiven :1; + unsigned BSIM3wrdswGiven :1; + unsigned BSIM3wprwgGiven :1; + unsigned BSIM3wprwbGiven :1; + unsigned BSIM3wprtGiven :1; + unsigned BSIM3weta0Given :1; + unsigned BSIM3wetabGiven :1; + unsigned BSIM3wpclmGiven :1; + unsigned BSIM3wpdibl1Given :1; + unsigned BSIM3wpdibl2Given :1; + unsigned BSIM3wpdiblbGiven :1; + unsigned BSIM3wpscbe1Given :1; + unsigned BSIM3wpscbe2Given :1; + unsigned BSIM3wpvagGiven :1; + unsigned BSIM3wdeltaGiven :1; unsigned BSIM3wwrGiven :1; unsigned BSIM3wdwgGiven :1; unsigned BSIM3wdwbGiven :1; @@ -1145,7 +1185,7 @@ typedef struct sBSIM3model unsigned BSIM3wvfbGiven :1; /* CV model */ - unsigned BSIM3welmGiven :1; + unsigned BSIM3welmGiven :1; unsigned BSIM3wcgslGiven :1; unsigned BSIM3wcgdlGiven :1; unsigned BSIM3wckappaGiven :1; @@ -1171,7 +1211,7 @@ typedef struct sBSIM3model unsigned BSIM3pagsGiven :1; unsigned BSIM3pa1Given :1; unsigned BSIM3pa2Given :1; - unsigned BSIM3pketaGiven :1; + unsigned BSIM3pketaGiven :1; unsigned BSIM3pnsubGiven :1; unsigned BSIM3pnpeakGiven :1; unsigned BSIM3pngateGiven :1; @@ -1189,14 +1229,14 @@ typedef struct sBSIM3model unsigned BSIM3pk3bGiven :1; unsigned BSIM3pw0Given :1; unsigned BSIM3pnlxGiven :1; - unsigned BSIM3pdvt0Given :1; - unsigned BSIM3pdvt1Given :1; - unsigned BSIM3pdvt2Given :1; - unsigned BSIM3pdvt0wGiven :1; - unsigned BSIM3pdvt1wGiven :1; - unsigned BSIM3pdvt2wGiven :1; - unsigned BSIM3pdroutGiven :1; - unsigned BSIM3pdsubGiven :1; + unsigned BSIM3pdvt0Given :1; + unsigned BSIM3pdvt1Given :1; + unsigned BSIM3pdvt2Given :1; + unsigned BSIM3pdvt0wGiven :1; + unsigned BSIM3pdvt1wGiven :1; + unsigned BSIM3pdvt2wGiven :1; + unsigned BSIM3pdroutGiven :1; + unsigned BSIM3pdsubGiven :1; unsigned BSIM3pvth0Given :1; unsigned BSIM3puaGiven :1; unsigned BSIM3pua1Given :1; @@ -1207,20 +1247,20 @@ typedef struct sBSIM3model unsigned BSIM3pu0Given :1; unsigned BSIM3puteGiven :1; unsigned BSIM3pvoffGiven :1; - unsigned BSIM3prdswGiven :1; - unsigned BSIM3pprwgGiven :1; - unsigned BSIM3pprwbGiven :1; - unsigned BSIM3pprtGiven :1; - unsigned BSIM3peta0Given :1; - unsigned BSIM3petabGiven :1; - unsigned BSIM3ppclmGiven :1; - unsigned BSIM3ppdibl1Given :1; - unsigned BSIM3ppdibl2Given :1; - unsigned BSIM3ppdiblbGiven :1; - unsigned BSIM3ppscbe1Given :1; - unsigned BSIM3ppscbe2Given :1; - unsigned BSIM3ppvagGiven :1; - unsigned BSIM3pdeltaGiven :1; + unsigned BSIM3prdswGiven :1; + unsigned BSIM3pprwgGiven :1; + unsigned BSIM3pprwbGiven :1; + unsigned BSIM3pprtGiven :1; + unsigned BSIM3peta0Given :1; + unsigned BSIM3petabGiven :1; + unsigned BSIM3ppclmGiven :1; + unsigned BSIM3ppdibl1Given :1; + unsigned BSIM3ppdibl2Given :1; + unsigned BSIM3ppdiblbGiven :1; + unsigned BSIM3ppscbe1Given :1; + unsigned BSIM3ppscbe2Given :1; + unsigned BSIM3ppvagGiven :1; + unsigned BSIM3pdeltaGiven :1; unsigned BSIM3pwrGiven :1; unsigned BSIM3pdwgGiven :1; unsigned BSIM3pdwbGiven :1; @@ -1232,7 +1272,7 @@ typedef struct sBSIM3model unsigned BSIM3pvfbGiven :1; /* CV model */ - unsigned BSIM3pelmGiven :1; + unsigned BSIM3pelmGiven :1; unsigned BSIM3pcgslGiven :1; unsigned BSIM3pcgdlGiven :1; unsigned BSIM3pckappaGiven :1; @@ -1265,15 +1305,15 @@ typedef struct sBSIM3model unsigned BSIM3bulkJctGateSideGradingCoeffGiven :1; unsigned BSIM3unitLengthGateSidewallJctCapGiven :1; unsigned BSIM3jctEmissionCoeffGiven :1; - unsigned BSIM3jctTempExponentGiven :1; + unsigned BSIM3jctTempExponentGiven :1; - unsigned BSIM3oxideTrapDensityAGiven :1; - unsigned BSIM3oxideTrapDensityBGiven :1; - unsigned BSIM3oxideTrapDensityCGiven :1; - unsigned BSIM3emGiven :1; - unsigned BSIM3efGiven :1; - unsigned BSIM3afGiven :1; - unsigned BSIM3kfGiven :1; + unsigned BSIM3oxideTrapDensityAGiven :1; + unsigned BSIM3oxideTrapDensityBGiven :1; + unsigned BSIM3oxideTrapDensityCGiven :1; + unsigned BSIM3emGiven :1; + unsigned BSIM3efGiven :1; + unsigned BSIM3afGiven :1; + unsigned BSIM3kfGiven :1; unsigned BSIM3lintnoiGiven :1; unsigned BSIM3LintGiven :1; @@ -1312,7 +1352,6 @@ typedef struct sBSIM3model /* device parameters */ #define BSIM3_W 1 #define BSIM3_L 2 -#define BSIM3_M 16 #define BSIM3_AS 3 #define BSIM3_AD 4 #define BSIM3_PS 5 @@ -1326,11 +1365,17 @@ typedef struct sBSIM3model #define BSIM3_IC 13 #define BSIM3_NQSMOD 14 #define BSIM3_ACNQSMOD 15 +#define BSIM3_M 16 +#define BSIM3_DELVTO 17 +#define BSIM3_MULU0 18 +#define BSIM3_GEO 19 /* model parameters */ -#define BSIM3_MOD_CAPMOD 101 -#define BSIM3_MOD_MOBMOD 103 -#define BSIM3_MOD_NOIMOD 104 +#define BSIM3_MOD_CAPMOD 100 +#define BSIM3_MOD_ACMMOD 101 +#define BSIM3_MOD_CALCACM 102 +#define BSIM3_MOD_MOBMOD 103 +#define BSIM3_MOD_NOIMOD 104 #define BSIM3_MOD_TOX 105 @@ -1344,14 +1389,14 @@ typedef struct sBSIM3model #define BSIM3_MOD_A0 113 #define BSIM3_MOD_A1 114 #define BSIM3_MOD_A2 115 -#define BSIM3_MOD_KETA 116 +#define BSIM3_MOD_KETA 116 #define BSIM3_MOD_NSUB 117 #define BSIM3_MOD_NPEAK 118 #define BSIM3_MOD_NGATE 120 #define BSIM3_MOD_GAMMA1 121 #define BSIM3_MOD_GAMMA2 122 #define BSIM3_MOD_VBX 123 -#define BSIM3_MOD_BINUNIT 124 +#define BSIM3_MOD_BINUNIT 124 #define BSIM3_MOD_VBM 125 @@ -1440,7 +1485,8 @@ typedef struct sBSIM3model #define BSIM3_MOD_TPBSWG 207 #define BSIM3_MOD_VOFFCV 208 #define BSIM3_MOD_LINTNOI 209 -#define BSIM3_MOD_ACNQSMOD 210 +#define BSIM3_MOD_NQSMOD 210 +#define BSIM3_MOD_ACNQSMOD 211 /* Length dependence */ #define BSIM3_MOD_LCDSC 251 @@ -1453,7 +1499,7 @@ typedef struct sBSIM3model #define BSIM3_MOD_LA0 258 #define BSIM3_MOD_LA1 259 #define BSIM3_MOD_LA2 260 -#define BSIM3_MOD_LKETA 261 +#define BSIM3_MOD_LKETA 261 #define BSIM3_MOD_LNSUB 262 #define BSIM3_MOD_LNPEAK 263 #define BSIM3_MOD_LNGATE 265 @@ -1521,7 +1567,7 @@ typedef struct sBSIM3model #define BSIM3_MOD_LCDSCD 327 #define BSIM3_MOD_LAGS 328 - + #define BSIM3_MOD_LFRINGE 331 #define BSIM3_MOD_LELM 332 @@ -1550,7 +1596,7 @@ typedef struct sBSIM3model #define BSIM3_MOD_WA0 388 #define BSIM3_MOD_WA1 389 #define BSIM3_MOD_WA2 390 -#define BSIM3_MOD_WKETA 391 +#define BSIM3_MOD_WKETA 391 #define BSIM3_MOD_WNSUB 392 #define BSIM3_MOD_WNPEAK 393 #define BSIM3_MOD_WNGATE 395 @@ -1647,7 +1693,7 @@ typedef struct sBSIM3model #define BSIM3_MOD_PA0 518 #define BSIM3_MOD_PA1 519 #define BSIM3_MOD_PA2 520 -#define BSIM3_MOD_PKETA 521 +#define BSIM3_MOD_PKETA 521 #define BSIM3_MOD_PNSUB 522 #define BSIM3_MOD_PNPEAK 523 #define BSIM3_MOD_PNGATE 525 @@ -1795,6 +1841,18 @@ typedef struct sBSIM3model #define BSIM3_MOD_WWC 701 #define BSIM3_MOD_WWLC 702 +/* ACM parameters */ +#define BSIM3_MOD_XL 703 +#define BSIM3_MOD_XW 704 +#define BSIM3_MOD_HDIF 711 +#define BSIM3_MOD_LDIF 712 +#define BSIM3_MOD_LD 713 +#define BSIM3_MOD_RD 714 +#define BSIM3_MOD_RS 715 +#define BSIM3_MOD_RDC 716 +#define BSIM3_MOD_RSC 717 +#define BSIM3_MOD_WMLT 718 + /* device questions */ #define BSIM3_DNODE 751 #define BSIM3_GNODE 752 @@ -1844,8 +1902,8 @@ typedef struct sBSIM3model #include "bsim3ext.h" extern void BSIM3evaluate(double,double,double,BSIM3instance*,BSIM3model*, - double*,double*,double*, double*, double*, double*, double*, - double*, double*, double*, double*, double*, double*, double*, + double*,double*,double*, double*, double*, double*, double*, + double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, CKTcircuit*); extern int BSIM3debug(BSIM3model*, BSIM3instance*, CKTcircuit*, int); extern int BSIM3checkModel(BSIM3model*, BSIM3instance*, CKTcircuit*); diff --git a/src/spicelib/devices/bsim3/bsim3ext.h b/src/spicelib/devices/bsim3/bsim3ext.h index 968a18a99..faa24d859 100644 --- a/src/spicelib/devices/bsim3/bsim3ext.h +++ b/src/spicelib/devices/bsim3/bsim3ext.h @@ -34,3 +34,7 @@ extern int BSIM3bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM3bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM3bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM3nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3/bsim3init.c b/src/spicelib/devices/bsim3/bsim3init.c index 82359c40a..dcbaa6c2b 100644 --- a/src/spicelib/devices/bsim3/bsim3init.c +++ b/src/spicelib/devices/bsim3/bsim3init.c @@ -72,12 +72,17 @@ SPICEdev BSIM3info = { #endif /* DEVinstSize */ &BSIM3iSize, /* DEVmodSize */ &BSIM3mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ BSIM3bindCSC, /* DEVbindCSCComplex */ BSIM3bindCSCComplex, /* DEVbindCSCComplexToReal */ BSIM3bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ BSIM3nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim3soi_dd/Makefile.am b/src/spicelib/devices/bsim3soi_dd/Makefile.am index 1c9a830d9..9f5166be8 100644 --- a/src/spicelib/devices/bsim3soi_dd/Makefile.am +++ b/src/spicelib/devices/bsim3soi_dd/Makefile.am @@ -2,29 +2,29 @@ noinst_LTLIBRARIES = libbsim3soidd.la -libbsim3soidd_la_SOURCES = \ - b3soidd.c \ - b3soiddacld.c \ - b3soiddask.c \ - b3soiddcheck.c \ - b3soiddcvtest.c \ - b3soidddel.c \ - b3soidddest.c \ - b3soiddgetic.c \ - b3soiddld.c \ - b3soiddmask.c \ - b3soiddmdel.c \ - b3soiddmpar.c \ - b3soiddnoi.c \ - b3soiddpar.c \ - b3soiddpzld.c \ - b3soiddset.c \ - b3soiddtemp.c \ - b3soiddtrunc.c \ - b3soidddef.h \ - b3soiddext.h \ - b3soiddinit.c \ - b3soiddinit.h \ +libbsim3soidd_la_SOURCES = \ + b3soidd.c \ + b3soiddacld.c \ + b3soiddask.c \ + b3soiddcheck.c \ + b3soiddcvtest.c \ + b3soidddel.c \ + b3soidddest.c \ + b3soiddgetic.c \ + b3soiddld.c \ + b3soiddmask.c \ + b3soiddmdel.c \ + b3soiddmpar.c \ + b3soiddnoi.c \ + b3soiddpar.c \ + b3soiddpzld.c \ + b3soiddset.c \ + b3soiddtemp.c \ + b3soiddtrunc.c \ + b3soidddef.h \ + b3soiddext.h \ + b3soiddinit.c \ + b3soiddinit.h \ b3soidditf.h @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3soidd_la_SOURCES += b3soiddbindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3soidd_la_SOURCES += b3soiddnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3soi_dd/b3soiddext.h b/src/spicelib/devices/bsim3soi_dd/b3soiddext.h index 2fab26622..774e16cd7 100644 --- a/src/spicelib/devices/bsim3soi_dd/b3soiddext.h +++ b/src/spicelib/devices/bsim3soi_dd/b3soiddext.h @@ -34,3 +34,7 @@ extern int B3SOIDDbindCSC (GENmodel*, CKTcircuit*) ; extern int B3SOIDDbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B3SOIDDbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B3SOIDDnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c b/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c index 3832bae04..3ff813ffa 100644 --- a/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c +++ b/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c @@ -70,12 +70,17 @@ SPICEdev B3SOIDDinfo = { #endif /* DEVinstSize */ &B3SOIDDiSize, /* DEVmodSize */ &B3SOIDDmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B3SOIDDbindCSC, /* DEVbindCSCComplex */ B3SOIDDbindCSCComplex, /* DEVbindCSCComplexToReal */ B3SOIDDbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B3SOIDDnodeIsNonLinear +#endif + }; SPICEdev * diff --git a/src/spicelib/devices/bsim3soi_dd/b3soiddnode.c b/src/spicelib/devices/bsim3soi_dd/b3soiddnode.c new file mode 100644 index 000000000..f993ddc82 --- /dev/null +++ b/src/spicelib/devices/bsim3soi_dd/b3soiddnode.c @@ -0,0 +1,79 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "b3soidddef.h" +#include "ngspice/sperror.h" + +int +B3SOIDDnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B3SOIDDmodel *model = (B3SOIDDmodel *)inModel ; + B3SOIDDinstance *here ; + + /* loop through all the B3SOIDD models */ + for ( ; model != NULL ; model = model->B3SOIDDnextModel) + { + /* loop through all the instances of the model */ + for (here = model->B3SOIDDinstances ; here != NULL ; here = here->B3SOIDDnextInstance) + { + ckt->CKTnodeIsLinear [here->B3SOIDDdNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDsNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDtempNode] = 0 ; + if ((here->B3SOIDDdebugMod > 1) || (here->B3SOIDDdebugMod == -1)) + { + ckt->CKTnodeIsLinear [here->B3SOIDDvbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDidsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDicNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDibsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDibdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDiiiNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDigidlNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDitunNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDibpNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDabeffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvbs0effNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvbseffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDxcNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDcbbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDcbdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDcbgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqbfNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqjsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqjdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDgmNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDgmbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDgdsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDgmeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvbs0teffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvthNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvgsteffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDxcsatNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqaccNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqsub0Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqsubs1Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqsubs2Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDqgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvdscvNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDvcscvNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDcbeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDdum1Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDdum2Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDdum3Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDdum4Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDdum5Node] = 0 ; + } + ckt->CKTnodeIsLinear [here->B3SOIDDgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIDDpNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3soi_dd/b3soiddset.c b/src/spicelib/devices/bsim3soi_dd/b3soiddset.c index f103ddff1..3fed81aae 100644 --- a/src/spicelib/devices/bsim3soi_dd/b3soiddset.c +++ b/src/spicelib/devices/bsim3soi_dd/b3soiddset.c @@ -1215,129 +1215,129 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) if ((model->B3SOIDDshMod == 1) && (here->B3SOIDDrth0!=0.0)) { - TSTALLOC(B3SOIDDTemptempPtr, B3SOIDDtempNode, B3SOIDDtempNode) - TSTALLOC(B3SOIDDTempdpPtr, B3SOIDDtempNode, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDTempspPtr, B3SOIDDtempNode, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDTempgPtr, B3SOIDDtempNode, B3SOIDDgNode) - TSTALLOC(B3SOIDDTempbPtr, B3SOIDDtempNode, B3SOIDDbNode) - TSTALLOC(B3SOIDDTempePtr, B3SOIDDtempNode, B3SOIDDeNode) + TSTALLOC(B3SOIDDTemptempPtr, B3SOIDDtempNode, B3SOIDDtempNode); + TSTALLOC(B3SOIDDTempdpPtr, B3SOIDDtempNode, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDTempspPtr, B3SOIDDtempNode, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDTempgPtr, B3SOIDDtempNode, B3SOIDDgNode); + TSTALLOC(B3SOIDDTempbPtr, B3SOIDDtempNode, B3SOIDDbNode); + TSTALLOC(B3SOIDDTempePtr, B3SOIDDtempNode, B3SOIDDeNode); - TSTALLOC(B3SOIDDGtempPtr, B3SOIDDgNode, B3SOIDDtempNode) - TSTALLOC(B3SOIDDDPtempPtr, B3SOIDDdNodePrime, B3SOIDDtempNode) - TSTALLOC(B3SOIDDSPtempPtr, B3SOIDDsNodePrime, B3SOIDDtempNode) - TSTALLOC(B3SOIDDEtempPtr, B3SOIDDeNode, B3SOIDDtempNode) - TSTALLOC(B3SOIDDBtempPtr, B3SOIDDbNode, B3SOIDDtempNode) + TSTALLOC(B3SOIDDGtempPtr, B3SOIDDgNode, B3SOIDDtempNode); + TSTALLOC(B3SOIDDDPtempPtr, B3SOIDDdNodePrime, B3SOIDDtempNode); + TSTALLOC(B3SOIDDSPtempPtr, B3SOIDDsNodePrime, B3SOIDDtempNode); + TSTALLOC(B3SOIDDEtempPtr, B3SOIDDeNode, B3SOIDDtempNode); + TSTALLOC(B3SOIDDBtempPtr, B3SOIDDbNode, B3SOIDDtempNode); if (here->B3SOIDDbodyMod == 1) { - TSTALLOC(B3SOIDDPtempPtr, B3SOIDDpNode, B3SOIDDtempNode) + TSTALLOC(B3SOIDDPtempPtr, B3SOIDDpNode, B3SOIDDtempNode); } } if (here->B3SOIDDbodyMod == 2) { /* Don't create any Jacobian entry for pNode */ } else if (here->B3SOIDDbodyMod == 1) { - TSTALLOC(B3SOIDDBpPtr, B3SOIDDbNode, B3SOIDDpNode) - TSTALLOC(B3SOIDDPbPtr, B3SOIDDpNode, B3SOIDDbNode) - TSTALLOC(B3SOIDDPpPtr, B3SOIDDpNode, B3SOIDDpNode) - TSTALLOC(B3SOIDDPgPtr, B3SOIDDpNode, B3SOIDDgNode) - TSTALLOC(B3SOIDDPdpPtr, B3SOIDDpNode, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDPspPtr, B3SOIDDpNode, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDPePtr, B3SOIDDpNode, B3SOIDDeNode) + TSTALLOC(B3SOIDDBpPtr, B3SOIDDbNode, B3SOIDDpNode); + TSTALLOC(B3SOIDDPbPtr, B3SOIDDpNode, B3SOIDDbNode); + TSTALLOC(B3SOIDDPpPtr, B3SOIDDpNode, B3SOIDDpNode); + TSTALLOC(B3SOIDDPgPtr, B3SOIDDpNode, B3SOIDDgNode); + TSTALLOC(B3SOIDDPdpPtr, B3SOIDDpNode, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDPspPtr, B3SOIDDpNode, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDPePtr, B3SOIDDpNode, B3SOIDDeNode); } - TSTALLOC(B3SOIDDEgPtr, B3SOIDDeNode, B3SOIDDgNode) - TSTALLOC(B3SOIDDEdpPtr, B3SOIDDeNode, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDEspPtr, B3SOIDDeNode, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDGePtr, B3SOIDDgNode, B3SOIDDeNode) - TSTALLOC(B3SOIDDDPePtr, B3SOIDDdNodePrime, B3SOIDDeNode) - TSTALLOC(B3SOIDDSPePtr, B3SOIDDsNodePrime, B3SOIDDeNode) + TSTALLOC(B3SOIDDEgPtr, B3SOIDDeNode, B3SOIDDgNode); + TSTALLOC(B3SOIDDEdpPtr, B3SOIDDeNode, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDEspPtr, B3SOIDDeNode, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDGePtr, B3SOIDDgNode, B3SOIDDeNode); + TSTALLOC(B3SOIDDDPePtr, B3SOIDDdNodePrime, B3SOIDDeNode); + TSTALLOC(B3SOIDDSPePtr, B3SOIDDsNodePrime, B3SOIDDeNode); - TSTALLOC(B3SOIDDEbPtr, B3SOIDDeNode, B3SOIDDbNode) - TSTALLOC(B3SOIDDGbPtr, B3SOIDDgNode, B3SOIDDbNode) - TSTALLOC(B3SOIDDDPbPtr, B3SOIDDdNodePrime, B3SOIDDbNode) - TSTALLOC(B3SOIDDSPbPtr, B3SOIDDsNodePrime, B3SOIDDbNode) - TSTALLOC(B3SOIDDBePtr, B3SOIDDbNode, B3SOIDDeNode) - TSTALLOC(B3SOIDDBgPtr, B3SOIDDbNode, B3SOIDDgNode) - TSTALLOC(B3SOIDDBdpPtr, B3SOIDDbNode, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDBspPtr, B3SOIDDbNode, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDBbPtr, B3SOIDDbNode, B3SOIDDbNode) + TSTALLOC(B3SOIDDEbPtr, B3SOIDDeNode, B3SOIDDbNode); + TSTALLOC(B3SOIDDGbPtr, B3SOIDDgNode, B3SOIDDbNode); + TSTALLOC(B3SOIDDDPbPtr, B3SOIDDdNodePrime, B3SOIDDbNode); + TSTALLOC(B3SOIDDSPbPtr, B3SOIDDsNodePrime, B3SOIDDbNode); + TSTALLOC(B3SOIDDBePtr, B3SOIDDbNode, B3SOIDDeNode); + TSTALLOC(B3SOIDDBgPtr, B3SOIDDbNode, B3SOIDDgNode); + TSTALLOC(B3SOIDDBdpPtr, B3SOIDDbNode, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDBspPtr, B3SOIDDbNode, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDBbPtr, B3SOIDDbNode, B3SOIDDbNode); - TSTALLOC(B3SOIDDEePtr, B3SOIDDeNode, B3SOIDDeNode) + TSTALLOC(B3SOIDDEePtr, B3SOIDDeNode, B3SOIDDeNode); - TSTALLOC(B3SOIDDGgPtr, B3SOIDDgNode, B3SOIDDgNode) - TSTALLOC(B3SOIDDGdpPtr, B3SOIDDgNode, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDGspPtr, B3SOIDDgNode, B3SOIDDsNodePrime) + TSTALLOC(B3SOIDDGgPtr, B3SOIDDgNode, B3SOIDDgNode); + TSTALLOC(B3SOIDDGdpPtr, B3SOIDDgNode, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDGspPtr, B3SOIDDgNode, B3SOIDDsNodePrime); - TSTALLOC(B3SOIDDDPgPtr, B3SOIDDdNodePrime, B3SOIDDgNode) - TSTALLOC(B3SOIDDDPdpPtr, B3SOIDDdNodePrime, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDDPspPtr, B3SOIDDdNodePrime, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDDPdPtr, B3SOIDDdNodePrime, B3SOIDDdNode) + TSTALLOC(B3SOIDDDPgPtr, B3SOIDDdNodePrime, B3SOIDDgNode); + TSTALLOC(B3SOIDDDPdpPtr, B3SOIDDdNodePrime, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDDPspPtr, B3SOIDDdNodePrime, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDDPdPtr, B3SOIDDdNodePrime, B3SOIDDdNode); - TSTALLOC(B3SOIDDSPgPtr, B3SOIDDsNodePrime, B3SOIDDgNode) - TSTALLOC(B3SOIDDSPdpPtr, B3SOIDDsNodePrime, B3SOIDDdNodePrime) - TSTALLOC(B3SOIDDSPspPtr, B3SOIDDsNodePrime, B3SOIDDsNodePrime) - TSTALLOC(B3SOIDDSPsPtr, B3SOIDDsNodePrime, B3SOIDDsNode) + TSTALLOC(B3SOIDDSPgPtr, B3SOIDDsNodePrime, B3SOIDDgNode); + TSTALLOC(B3SOIDDSPdpPtr, B3SOIDDsNodePrime, B3SOIDDdNodePrime); + TSTALLOC(B3SOIDDSPspPtr, B3SOIDDsNodePrime, B3SOIDDsNodePrime); + TSTALLOC(B3SOIDDSPsPtr, B3SOIDDsNodePrime, B3SOIDDsNode); - TSTALLOC(B3SOIDDDdPtr, B3SOIDDdNode, B3SOIDDdNode) - TSTALLOC(B3SOIDDDdpPtr, B3SOIDDdNode, B3SOIDDdNodePrime) + TSTALLOC(B3SOIDDDdPtr, B3SOIDDdNode, B3SOIDDdNode); + TSTALLOC(B3SOIDDDdpPtr, B3SOIDDdNode, B3SOIDDdNodePrime); - TSTALLOC(B3SOIDDSsPtr, B3SOIDDsNode, B3SOIDDsNode) - TSTALLOC(B3SOIDDSspPtr, B3SOIDDsNode, B3SOIDDsNodePrime) + TSTALLOC(B3SOIDDSsPtr, B3SOIDDsNode, B3SOIDDsNode); + TSTALLOC(B3SOIDDSspPtr, B3SOIDDsNode, B3SOIDDsNodePrime); /* here for debugging purpose only */ if ((here->B3SOIDDdebugMod > 1) || (here->B3SOIDDdebugMod == -1)) { - TSTALLOC(B3SOIDDVbsPtr, B3SOIDDvbsNode, B3SOIDDvbsNode) - TSTALLOC(B3SOIDDIdsPtr, B3SOIDDidsNode, B3SOIDDidsNode) - TSTALLOC(B3SOIDDIcPtr, B3SOIDDicNode, B3SOIDDicNode) - TSTALLOC(B3SOIDDIbsPtr, B3SOIDDibsNode, B3SOIDDibsNode) - TSTALLOC(B3SOIDDIbdPtr, B3SOIDDibdNode, B3SOIDDibdNode) - TSTALLOC(B3SOIDDIiiPtr, B3SOIDDiiiNode, B3SOIDDiiiNode) - TSTALLOC(B3SOIDDIgidlPtr, B3SOIDDigidlNode, B3SOIDDigidlNode) - TSTALLOC(B3SOIDDItunPtr, B3SOIDDitunNode, B3SOIDDitunNode) - TSTALLOC(B3SOIDDIbpPtr, B3SOIDDibpNode, B3SOIDDibpNode) - TSTALLOC(B3SOIDDAbeffPtr, B3SOIDDabeffNode, B3SOIDDabeffNode) - TSTALLOC(B3SOIDDVbs0effPtr, B3SOIDDvbs0effNode, B3SOIDDvbs0effNode) - TSTALLOC(B3SOIDDVbseffPtr, B3SOIDDvbseffNode, B3SOIDDvbseffNode) - TSTALLOC(B3SOIDDXcPtr, B3SOIDDxcNode, B3SOIDDxcNode) - TSTALLOC(B3SOIDDCbbPtr, B3SOIDDcbbNode, B3SOIDDcbbNode) - TSTALLOC(B3SOIDDCbdPtr, B3SOIDDcbdNode, B3SOIDDcbdNode) - TSTALLOC(B3SOIDDCbgPtr, B3SOIDDcbgNode, B3SOIDDcbgNode) - TSTALLOC(B3SOIDDqbPtr, B3SOIDDqbNode, B3SOIDDqbNode) - TSTALLOC(B3SOIDDQbfPtr, B3SOIDDqbfNode, B3SOIDDqbfNode) - TSTALLOC(B3SOIDDQjsPtr, B3SOIDDqjsNode, B3SOIDDqjsNode) - TSTALLOC(B3SOIDDQjdPtr, B3SOIDDqjdNode, B3SOIDDqjdNode) + TSTALLOC(B3SOIDDVbsPtr, B3SOIDDvbsNode, B3SOIDDvbsNode) ; + TSTALLOC(B3SOIDDIdsPtr, B3SOIDDidsNode, B3SOIDDidsNode); + TSTALLOC(B3SOIDDIcPtr, B3SOIDDicNode, B3SOIDDicNode); + TSTALLOC(B3SOIDDIbsPtr, B3SOIDDibsNode, B3SOIDDibsNode); + TSTALLOC(B3SOIDDIbdPtr, B3SOIDDibdNode, B3SOIDDibdNode); + TSTALLOC(B3SOIDDIiiPtr, B3SOIDDiiiNode, B3SOIDDiiiNode); + TSTALLOC(B3SOIDDIgidlPtr, B3SOIDDigidlNode, B3SOIDDigidlNode); + TSTALLOC(B3SOIDDItunPtr, B3SOIDDitunNode, B3SOIDDitunNode); + TSTALLOC(B3SOIDDIbpPtr, B3SOIDDibpNode, B3SOIDDibpNode); + TSTALLOC(B3SOIDDAbeffPtr, B3SOIDDabeffNode, B3SOIDDabeffNode); + TSTALLOC(B3SOIDDVbs0effPtr, B3SOIDDvbs0effNode, B3SOIDDvbs0effNode); + TSTALLOC(B3SOIDDVbseffPtr, B3SOIDDvbseffNode, B3SOIDDvbseffNode); + TSTALLOC(B3SOIDDXcPtr, B3SOIDDxcNode, B3SOIDDxcNode); + TSTALLOC(B3SOIDDCbbPtr, B3SOIDDcbbNode, B3SOIDDcbbNode); + TSTALLOC(B3SOIDDCbdPtr, B3SOIDDcbdNode, B3SOIDDcbdNode); + TSTALLOC(B3SOIDDCbgPtr, B3SOIDDcbgNode, B3SOIDDcbgNode); + TSTALLOC(B3SOIDDqbPtr, B3SOIDDqbNode, B3SOIDDqbNode); + TSTALLOC(B3SOIDDQbfPtr, B3SOIDDqbfNode, B3SOIDDqbfNode); + TSTALLOC(B3SOIDDQjsPtr, B3SOIDDqjsNode, B3SOIDDqjsNode); + TSTALLOC(B3SOIDDQjdPtr, B3SOIDDqjdNode, B3SOIDDqjdNode); /* clean up last */ - TSTALLOC(B3SOIDDGmPtr, B3SOIDDgmNode, B3SOIDDgmNode) - TSTALLOC(B3SOIDDGmbsPtr, B3SOIDDgmbsNode, B3SOIDDgmbsNode) - TSTALLOC(B3SOIDDGdsPtr, B3SOIDDgdsNode, B3SOIDDgdsNode) - TSTALLOC(B3SOIDDGmePtr, B3SOIDDgmeNode, B3SOIDDgmeNode) - TSTALLOC(B3SOIDDVbs0teffPtr, B3SOIDDvbs0teffNode, B3SOIDDvbs0teffNode) - TSTALLOC(B3SOIDDVthPtr, B3SOIDDvthNode, B3SOIDDvthNode) - TSTALLOC(B3SOIDDVgsteffPtr, B3SOIDDvgsteffNode, B3SOIDDvgsteffNode) - TSTALLOC(B3SOIDDXcsatPtr, B3SOIDDxcsatNode, B3SOIDDxcsatNode) - TSTALLOC(B3SOIDDVcscvPtr, B3SOIDDvcscvNode, B3SOIDDvcscvNode) - TSTALLOC(B3SOIDDVdscvPtr, B3SOIDDvdscvNode, B3SOIDDvdscvNode) - TSTALLOC(B3SOIDDCbePtr, B3SOIDDcbeNode, B3SOIDDcbeNode) - TSTALLOC(B3SOIDDDum1Ptr, B3SOIDDdum1Node, B3SOIDDdum1Node) - TSTALLOC(B3SOIDDDum2Ptr, B3SOIDDdum2Node, B3SOIDDdum2Node) - TSTALLOC(B3SOIDDDum3Ptr, B3SOIDDdum3Node, B3SOIDDdum3Node) - TSTALLOC(B3SOIDDDum4Ptr, B3SOIDDdum4Node, B3SOIDDdum4Node) - TSTALLOC(B3SOIDDDum5Ptr, B3SOIDDdum5Node, B3SOIDDdum5Node) - TSTALLOC(B3SOIDDQaccPtr, B3SOIDDqaccNode, B3SOIDDqaccNode) - TSTALLOC(B3SOIDDQsub0Ptr, B3SOIDDqsub0Node, B3SOIDDqsub0Node) - TSTALLOC(B3SOIDDQsubs1Ptr, B3SOIDDqsubs1Node, B3SOIDDqsubs1Node) - TSTALLOC(B3SOIDDQsubs2Ptr, B3SOIDDqsubs2Node, B3SOIDDqsubs2Node) - TSTALLOC(B3SOIDDqePtr, B3SOIDDqeNode, B3SOIDDqeNode) - TSTALLOC(B3SOIDDqdPtr, B3SOIDDqdNode, B3SOIDDqdNode) - TSTALLOC(B3SOIDDqgPtr, B3SOIDDqgNode, B3SOIDDqgNode) + TSTALLOC(B3SOIDDGmPtr, B3SOIDDgmNode, B3SOIDDgmNode); + TSTALLOC(B3SOIDDGmbsPtr, B3SOIDDgmbsNode, B3SOIDDgmbsNode); + TSTALLOC(B3SOIDDGdsPtr, B3SOIDDgdsNode, B3SOIDDgdsNode); + TSTALLOC(B3SOIDDGmePtr, B3SOIDDgmeNode, B3SOIDDgmeNode); + TSTALLOC(B3SOIDDVbs0teffPtr, B3SOIDDvbs0teffNode, B3SOIDDvbs0teffNode); + TSTALLOC(B3SOIDDVthPtr, B3SOIDDvthNode, B3SOIDDvthNode); + TSTALLOC(B3SOIDDVgsteffPtr, B3SOIDDvgsteffNode, B3SOIDDvgsteffNode); + TSTALLOC(B3SOIDDXcsatPtr, B3SOIDDxcsatNode, B3SOIDDxcsatNode); + TSTALLOC(B3SOIDDVcscvPtr, B3SOIDDvcscvNode, B3SOIDDvcscvNode); + TSTALLOC(B3SOIDDVdscvPtr, B3SOIDDvdscvNode, B3SOIDDvdscvNode); + TSTALLOC(B3SOIDDCbePtr, B3SOIDDcbeNode, B3SOIDDcbeNode); + TSTALLOC(B3SOIDDDum1Ptr, B3SOIDDdum1Node, B3SOIDDdum1Node); + TSTALLOC(B3SOIDDDum2Ptr, B3SOIDDdum2Node, B3SOIDDdum2Node); + TSTALLOC(B3SOIDDDum3Ptr, B3SOIDDdum3Node, B3SOIDDdum3Node); + TSTALLOC(B3SOIDDDum4Ptr, B3SOIDDdum4Node, B3SOIDDdum4Node); + TSTALLOC(B3SOIDDDum5Ptr, B3SOIDDdum5Node, B3SOIDDdum5Node); + TSTALLOC(B3SOIDDQaccPtr, B3SOIDDqaccNode, B3SOIDDqaccNode); + TSTALLOC(B3SOIDDQsub0Ptr, B3SOIDDqsub0Node, B3SOIDDqsub0Node); + TSTALLOC(B3SOIDDQsubs1Ptr, B3SOIDDqsubs1Node, B3SOIDDqsubs1Node); + TSTALLOC(B3SOIDDQsubs2Ptr, B3SOIDDqsubs2Node, B3SOIDDqsubs2Node); + TSTALLOC(B3SOIDDqePtr, B3SOIDDqeNode, B3SOIDDqeNode); + TSTALLOC(B3SOIDDqdPtr, B3SOIDDqdNode, B3SOIDDqdNode); + TSTALLOC(B3SOIDDqgPtr, B3SOIDDqgNode, B3SOIDDqgNode); } } diff --git a/src/spicelib/devices/bsim3soi_fd/Makefile.am b/src/spicelib/devices/bsim3soi_fd/Makefile.am index c3e94a1d3..679732bed 100644 --- a/src/spicelib/devices/bsim3soi_fd/Makefile.am +++ b/src/spicelib/devices/bsim3soi_fd/Makefile.am @@ -2,29 +2,29 @@ noinst_LTLIBRARIES = libbsim3soifd.la -libbsim3soifd_la_SOURCES = \ - b3soifd.c \ - b3soifdacld.c \ - b3soifdask.c \ - b3soifdcheck.c \ - b3soifdcvtest.c \ - b3soifddel.c \ - b3soifddest.c \ - b3soifdgetic.c \ - b3soifdld.c \ - b3soifdmask.c \ - b3soifdmdel.c \ - b3soifdmpar.c \ - b3soifdnoi.c \ - b3soifdpar.c \ - b3soifdpzld.c \ - b3soifdset.c \ - b3soifdtemp.c \ - b3soifdtrunc.c \ - b3soifddef.h \ - b3soifdext.h \ - b3soifdinit.c \ - b3soifdinit.h \ +libbsim3soifd_la_SOURCES = \ + b3soifd.c \ + b3soifdacld.c \ + b3soifdask.c \ + b3soifdcheck.c \ + b3soifdcvtest.c \ + b3soifddel.c \ + b3soifddest.c \ + b3soifdgetic.c \ + b3soifdld.c \ + b3soifdmask.c \ + b3soifdmdel.c \ + b3soifdmpar.c \ + b3soifdnoi.c \ + b3soifdpar.c \ + b3soifdpzld.c \ + b3soifdset.c \ + b3soifdtemp.c \ + b3soifdtrunc.c \ + b3soifddef.h \ + b3soifdext.h \ + b3soifdinit.c \ + b3soifdinit.h \ b3soifditf.h @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3soifd_la_SOURCES += b3soifdbindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3soifd_la_SOURCES += b3soifdnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3soi_fd/b3soifdext.h b/src/spicelib/devices/bsim3soi_fd/b3soifdext.h index 8be71ed72..8dc9ccded 100644 --- a/src/spicelib/devices/bsim3soi_fd/b3soifdext.h +++ b/src/spicelib/devices/bsim3soi_fd/b3soifdext.h @@ -29,9 +29,12 @@ extern int B3SOIFDtrunc(GENmodel*,CKTcircuit*,double*); extern int B3SOIFDnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int B3SOIFDunsetup(GENmodel*,CKTcircuit*); - #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int B3SOIFDbindCSC (GENmodel*, CKTcircuit*) ; extern int B3SOIFDbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B3SOIFDbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B3SOIFDnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c b/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c index f23acd7f9..5645c674e 100644 --- a/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c +++ b/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c @@ -71,12 +71,17 @@ SPICEdev B3SOIFDinfo = { #endif /* DEVinstSize*/ &B3SOIFDiSize, /* DEVmodSize*/ &B3SOIFDmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B3SOIFDbindCSC, /* DEVbindCSCComplex */ B3SOIFDbindCSCComplex, /* DEVbindCSCComplexToReal */ B3SOIFDbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B3SOIFDnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim3soi_fd/b3soifdnode.c b/src/spicelib/devices/bsim3soi_fd/b3soifdnode.c new file mode 100644 index 000000000..cd4280763 --- /dev/null +++ b/src/spicelib/devices/bsim3soi_fd/b3soifdnode.c @@ -0,0 +1,79 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "b3soifddef.h" +#include "ngspice/sperror.h" + +int +B3SOIFDnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B3SOIFDmodel *model = (B3SOIFDmodel *)inModel ; + B3SOIFDinstance *here ; + + /* loop through all the B3SOIFD models */ + for ( ; model != NULL ; model = model->B3SOIFDnextModel) + { + /* loop through all the instances of the model */ + for (here = model->B3SOIFDinstances ; here != NULL ; here = here->B3SOIFDnextInstance) + { + ckt->CKTnodeIsLinear [here->B3SOIFDdNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDsNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDtempNode] = 0 ; + if ((here->B3SOIFDdebugMod > 1) || (here->B3SOIFDdebugMod == -1)) + { + ckt->CKTnodeIsLinear [here->B3SOIFDvbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDidsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDicNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDibsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDibdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDiiiNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDigidlNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDitunNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDibpNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDabeffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvbs0effNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvbseffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDxcNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDcbbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDcbdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDcbgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqbfNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqjsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqjdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDgmNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDgmbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDgdsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDgmeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvbs0teffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvthNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvgsteffNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDxcsatNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqaccNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqsub0Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqsubs1Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqsubs2Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDqgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvdscvNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDvcscvNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDcbeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDdum1Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDdum2Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDdum3Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDdum4Node] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDdum5Node] = 0 ; + } + ckt->CKTnodeIsLinear [here->B3SOIFDgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIFDpNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3soi_fd/b3soifdset.c b/src/spicelib/devices/bsim3soi_fd/b3soifdset.c index 6e6c8ebdb..242aa1517 100644 --- a/src/spicelib/devices/bsim3soi_fd/b3soifdset.c +++ b/src/spicelib/devices/bsim3soi_fd/b3soifdset.c @@ -1213,120 +1213,120 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) if ((model->B3SOIFDshMod == 1) && (here->B3SOIFDrth0!=0.0)) { - TSTALLOC(B3SOIFDTemptempPtr, B3SOIFDtempNode, B3SOIFDtempNode) - TSTALLOC(B3SOIFDTempdpPtr, B3SOIFDtempNode, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDTempspPtr, B3SOIFDtempNode, B3SOIFDsNodePrime) - TSTALLOC(B3SOIFDTempgPtr, B3SOIFDtempNode, B3SOIFDgNode) - TSTALLOC(B3SOIFDTempbPtr, B3SOIFDtempNode, B3SOIFDbNode) - TSTALLOC(B3SOIFDTempePtr, B3SOIFDtempNode, B3SOIFDeNode) + TSTALLOC(B3SOIFDTemptempPtr, B3SOIFDtempNode, B3SOIFDtempNode); + TSTALLOC(B3SOIFDTempdpPtr, B3SOIFDtempNode, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDTempspPtr, B3SOIFDtempNode, B3SOIFDsNodePrime); + TSTALLOC(B3SOIFDTempgPtr, B3SOIFDtempNode, B3SOIFDgNode); + TSTALLOC(B3SOIFDTempbPtr, B3SOIFDtempNode, B3SOIFDbNode); + TSTALLOC(B3SOIFDTempePtr, B3SOIFDtempNode, B3SOIFDeNode); - TSTALLOC(B3SOIFDGtempPtr, B3SOIFDgNode, B3SOIFDtempNode) - TSTALLOC(B3SOIFDDPtempPtr, B3SOIFDdNodePrime, B3SOIFDtempNode) - TSTALLOC(B3SOIFDSPtempPtr, B3SOIFDsNodePrime, B3SOIFDtempNode) - TSTALLOC(B3SOIFDEtempPtr, B3SOIFDeNode, B3SOIFDtempNode) - TSTALLOC(B3SOIFDBtempPtr, B3SOIFDbNode, B3SOIFDtempNode) + TSTALLOC(B3SOIFDGtempPtr, B3SOIFDgNode, B3SOIFDtempNode); + TSTALLOC(B3SOIFDDPtempPtr, B3SOIFDdNodePrime, B3SOIFDtempNode); + TSTALLOC(B3SOIFDSPtempPtr, B3SOIFDsNodePrime, B3SOIFDtempNode); + TSTALLOC(B3SOIFDEtempPtr, B3SOIFDeNode, B3SOIFDtempNode); + TSTALLOC(B3SOIFDBtempPtr, B3SOIFDbNode, B3SOIFDtempNode); if (here->B3SOIFDbodyMod == 1) { - TSTALLOC(B3SOIFDPtempPtr, B3SOIFDpNode, B3SOIFDtempNode) + TSTALLOC(B3SOIFDPtempPtr, B3SOIFDpNode, B3SOIFDtempNode); } } if (here->B3SOIFDbodyMod == 2) { /* Don't create any Jacobian entry for pNode */ } else if (here->B3SOIFDbodyMod == 1) { - TSTALLOC(B3SOIFDBpPtr, B3SOIFDbNode, B3SOIFDpNode) - TSTALLOC(B3SOIFDPbPtr, B3SOIFDpNode, B3SOIFDbNode) - TSTALLOC(B3SOIFDPpPtr, B3SOIFDpNode, B3SOIFDpNode) - TSTALLOC(B3SOIFDPgPtr, B3SOIFDpNode, B3SOIFDgNode) - TSTALLOC(B3SOIFDPdpPtr, B3SOIFDpNode, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDPspPtr, B3SOIFDpNode, B3SOIFDsNodePrime) - TSTALLOC(B3SOIFDPePtr, B3SOIFDpNode, B3SOIFDeNode) + TSTALLOC(B3SOIFDBpPtr, B3SOIFDbNode, B3SOIFDpNode); + TSTALLOC(B3SOIFDPbPtr, B3SOIFDpNode, B3SOIFDbNode); + TSTALLOC(B3SOIFDPpPtr, B3SOIFDpNode, B3SOIFDpNode); + TSTALLOC(B3SOIFDPgPtr, B3SOIFDpNode, B3SOIFDgNode); + TSTALLOC(B3SOIFDPdpPtr, B3SOIFDpNode, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDPspPtr, B3SOIFDpNode, B3SOIFDsNodePrime); + TSTALLOC(B3SOIFDPePtr, B3SOIFDpNode, B3SOIFDeNode); } - TSTALLOC(B3SOIFDEgPtr, B3SOIFDeNode, B3SOIFDgNode) - TSTALLOC(B3SOIFDEdpPtr, B3SOIFDeNode, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDEspPtr, B3SOIFDeNode, B3SOIFDsNodePrime) - TSTALLOC(B3SOIFDGePtr, B3SOIFDgNode, B3SOIFDeNode) - TSTALLOC(B3SOIFDDPePtr, B3SOIFDdNodePrime, B3SOIFDeNode) - TSTALLOC(B3SOIFDSPePtr, B3SOIFDsNodePrime, B3SOIFDeNode) + TSTALLOC(B3SOIFDEgPtr, B3SOIFDeNode, B3SOIFDgNode); + TSTALLOC(B3SOIFDEdpPtr, B3SOIFDeNode, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDEspPtr, B3SOIFDeNode, B3SOIFDsNodePrime); + TSTALLOC(B3SOIFDGePtr, B3SOIFDgNode, B3SOIFDeNode); + TSTALLOC(B3SOIFDDPePtr, B3SOIFDdNodePrime, B3SOIFDeNode); + TSTALLOC(B3SOIFDSPePtr, B3SOIFDsNodePrime, B3SOIFDeNode); - TSTALLOC(B3SOIFDEbPtr, B3SOIFDeNode, B3SOIFDbNode) - TSTALLOC(B3SOIFDEePtr, B3SOIFDeNode, B3SOIFDeNode) + TSTALLOC(B3SOIFDEbPtr, B3SOIFDeNode, B3SOIFDbNode); + TSTALLOC(B3SOIFDEePtr, B3SOIFDeNode, B3SOIFDeNode); - TSTALLOC(B3SOIFDGgPtr, B3SOIFDgNode, B3SOIFDgNode) - TSTALLOC(B3SOIFDGdpPtr, B3SOIFDgNode, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDGspPtr, B3SOIFDgNode, B3SOIFDsNodePrime) + TSTALLOC(B3SOIFDGgPtr, B3SOIFDgNode, B3SOIFDgNode); + TSTALLOC(B3SOIFDGdpPtr, B3SOIFDgNode, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDGspPtr, B3SOIFDgNode, B3SOIFDsNodePrime); - TSTALLOC(B3SOIFDDPgPtr, B3SOIFDdNodePrime, B3SOIFDgNode) - TSTALLOC(B3SOIFDDPdpPtr, B3SOIFDdNodePrime, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDDPspPtr, B3SOIFDdNodePrime, B3SOIFDsNodePrime) - TSTALLOC(B3SOIFDDPdPtr, B3SOIFDdNodePrime, B3SOIFDdNode) + TSTALLOC(B3SOIFDDPgPtr, B3SOIFDdNodePrime, B3SOIFDgNode); + TSTALLOC(B3SOIFDDPdpPtr, B3SOIFDdNodePrime, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDDPspPtr, B3SOIFDdNodePrime, B3SOIFDsNodePrime); + TSTALLOC(B3SOIFDDPdPtr, B3SOIFDdNodePrime, B3SOIFDdNode); - TSTALLOC(B3SOIFDSPgPtr, B3SOIFDsNodePrime, B3SOIFDgNode) - TSTALLOC(B3SOIFDSPdpPtr, B3SOIFDsNodePrime, B3SOIFDdNodePrime) - TSTALLOC(B3SOIFDSPspPtr, B3SOIFDsNodePrime, B3SOIFDsNodePrime) - TSTALLOC(B3SOIFDSPsPtr, B3SOIFDsNodePrime, B3SOIFDsNode) + TSTALLOC(B3SOIFDSPgPtr, B3SOIFDsNodePrime, B3SOIFDgNode); + TSTALLOC(B3SOIFDSPdpPtr, B3SOIFDsNodePrime, B3SOIFDdNodePrime); + TSTALLOC(B3SOIFDSPspPtr, B3SOIFDsNodePrime, B3SOIFDsNodePrime); + TSTALLOC(B3SOIFDSPsPtr, B3SOIFDsNodePrime, B3SOIFDsNode); - TSTALLOC(B3SOIFDDdPtr, B3SOIFDdNode, B3SOIFDdNode) - TSTALLOC(B3SOIFDDdpPtr, B3SOIFDdNode, B3SOIFDdNodePrime) + TSTALLOC(B3SOIFDDdPtr, B3SOIFDdNode, B3SOIFDdNode); + TSTALLOC(B3SOIFDDdpPtr, B3SOIFDdNode, B3SOIFDdNodePrime); - TSTALLOC(B3SOIFDSsPtr, B3SOIFDsNode, B3SOIFDsNode) - TSTALLOC(B3SOIFDSspPtr, B3SOIFDsNode, B3SOIFDsNodePrime) + TSTALLOC(B3SOIFDSsPtr, B3SOIFDsNode, B3SOIFDsNode); + TSTALLOC(B3SOIFDSspPtr, B3SOIFDsNode, B3SOIFDsNodePrime); /* here for debugging purpose only */ if ((here->B3SOIFDdebugMod > 1) || (here->B3SOIFDdebugMod == -1)) { - TSTALLOC(B3SOIFDVbsPtr, B3SOIFDvbsNode, B3SOIFDvbsNode) - TSTALLOC(B3SOIFDIdsPtr, B3SOIFDidsNode, B3SOIFDidsNode) - TSTALLOC(B3SOIFDIcPtr, B3SOIFDicNode, B3SOIFDicNode) - TSTALLOC(B3SOIFDIbsPtr, B3SOIFDibsNode, B3SOIFDibsNode) - TSTALLOC(B3SOIFDIbdPtr, B3SOIFDibdNode, B3SOIFDibdNode) - TSTALLOC(B3SOIFDIiiPtr, B3SOIFDiiiNode, B3SOIFDiiiNode) - TSTALLOC(B3SOIFDIgidlPtr, B3SOIFDigidlNode, B3SOIFDigidlNode) - TSTALLOC(B3SOIFDItunPtr, B3SOIFDitunNode, B3SOIFDitunNode) - TSTALLOC(B3SOIFDIbpPtr, B3SOIFDibpNode, B3SOIFDibpNode) - TSTALLOC(B3SOIFDAbeffPtr, B3SOIFDabeffNode, B3SOIFDabeffNode) - TSTALLOC(B3SOIFDVbs0effPtr, B3SOIFDvbs0effNode, B3SOIFDvbs0effNode) - TSTALLOC(B3SOIFDVbseffPtr, B3SOIFDvbseffNode, B3SOIFDvbseffNode) - TSTALLOC(B3SOIFDXcPtr, B3SOIFDxcNode, B3SOIFDxcNode) - TSTALLOC(B3SOIFDCbbPtr, B3SOIFDcbbNode, B3SOIFDcbbNode) - TSTALLOC(B3SOIFDCbdPtr, B3SOIFDcbdNode, B3SOIFDcbdNode) - TSTALLOC(B3SOIFDCbgPtr, B3SOIFDcbgNode, B3SOIFDcbgNode) - TSTALLOC(B3SOIFDqbPtr, B3SOIFDqbNode, B3SOIFDqbNode) - TSTALLOC(B3SOIFDQbfPtr, B3SOIFDqbfNode, B3SOIFDqbfNode) - TSTALLOC(B3SOIFDQjsPtr, B3SOIFDqjsNode, B3SOIFDqjsNode) - TSTALLOC(B3SOIFDQjdPtr, B3SOIFDqjdNode, B3SOIFDqjdNode) + TSTALLOC(B3SOIFDVbsPtr, B3SOIFDvbsNode, B3SOIFDvbsNode) ; + TSTALLOC(B3SOIFDIdsPtr, B3SOIFDidsNode, B3SOIFDidsNode); + TSTALLOC(B3SOIFDIcPtr, B3SOIFDicNode, B3SOIFDicNode); + TSTALLOC(B3SOIFDIbsPtr, B3SOIFDibsNode, B3SOIFDibsNode); + TSTALLOC(B3SOIFDIbdPtr, B3SOIFDibdNode, B3SOIFDibdNode); + TSTALLOC(B3SOIFDIiiPtr, B3SOIFDiiiNode, B3SOIFDiiiNode); + TSTALLOC(B3SOIFDIgidlPtr, B3SOIFDigidlNode, B3SOIFDigidlNode); + TSTALLOC(B3SOIFDItunPtr, B3SOIFDitunNode, B3SOIFDitunNode); + TSTALLOC(B3SOIFDIbpPtr, B3SOIFDibpNode, B3SOIFDibpNode); + TSTALLOC(B3SOIFDAbeffPtr, B3SOIFDabeffNode, B3SOIFDabeffNode); + TSTALLOC(B3SOIFDVbs0effPtr, B3SOIFDvbs0effNode, B3SOIFDvbs0effNode); + TSTALLOC(B3SOIFDVbseffPtr, B3SOIFDvbseffNode, B3SOIFDvbseffNode); + TSTALLOC(B3SOIFDXcPtr, B3SOIFDxcNode, B3SOIFDxcNode); + TSTALLOC(B3SOIFDCbbPtr, B3SOIFDcbbNode, B3SOIFDcbbNode); + TSTALLOC(B3SOIFDCbdPtr, B3SOIFDcbdNode, B3SOIFDcbdNode); + TSTALLOC(B3SOIFDCbgPtr, B3SOIFDcbgNode, B3SOIFDcbgNode); + TSTALLOC(B3SOIFDqbPtr, B3SOIFDqbNode, B3SOIFDqbNode); + TSTALLOC(B3SOIFDQbfPtr, B3SOIFDqbfNode, B3SOIFDqbfNode); + TSTALLOC(B3SOIFDQjsPtr, B3SOIFDqjsNode, B3SOIFDqjsNode); + TSTALLOC(B3SOIFDQjdPtr, B3SOIFDqjdNode, B3SOIFDqjdNode); /* clean up last */ - TSTALLOC(B3SOIFDGmPtr, B3SOIFDgmNode, B3SOIFDgmNode) - TSTALLOC(B3SOIFDGmbsPtr, B3SOIFDgmbsNode, B3SOIFDgmbsNode) - TSTALLOC(B3SOIFDGdsPtr, B3SOIFDgdsNode, B3SOIFDgdsNode) - TSTALLOC(B3SOIFDGmePtr, B3SOIFDgmeNode, B3SOIFDgmeNode) - TSTALLOC(B3SOIFDVbs0teffPtr, B3SOIFDvbs0teffNode, B3SOIFDvbs0teffNode) - TSTALLOC(B3SOIFDVthPtr, B3SOIFDvthNode, B3SOIFDvthNode) - TSTALLOC(B3SOIFDVgsteffPtr, B3SOIFDvgsteffNode, B3SOIFDvgsteffNode) - TSTALLOC(B3SOIFDXcsatPtr, B3SOIFDxcsatNode, B3SOIFDxcsatNode) - TSTALLOC(B3SOIFDVcscvPtr, B3SOIFDvcscvNode, B3SOIFDvcscvNode) - TSTALLOC(B3SOIFDVdscvPtr, B3SOIFDvdscvNode, B3SOIFDvdscvNode) - TSTALLOC(B3SOIFDCbePtr, B3SOIFDcbeNode, B3SOIFDcbeNode) - TSTALLOC(B3SOIFDDum1Ptr, B3SOIFDdum1Node, B3SOIFDdum1Node) - TSTALLOC(B3SOIFDDum2Ptr, B3SOIFDdum2Node, B3SOIFDdum2Node) - TSTALLOC(B3SOIFDDum3Ptr, B3SOIFDdum3Node, B3SOIFDdum3Node) - TSTALLOC(B3SOIFDDum4Ptr, B3SOIFDdum4Node, B3SOIFDdum4Node) - TSTALLOC(B3SOIFDDum5Ptr, B3SOIFDdum5Node, B3SOIFDdum5Node) - TSTALLOC(B3SOIFDQaccPtr, B3SOIFDqaccNode, B3SOIFDqaccNode) - TSTALLOC(B3SOIFDQsub0Ptr, B3SOIFDqsub0Node, B3SOIFDqsub0Node) - TSTALLOC(B3SOIFDQsubs1Ptr, B3SOIFDqsubs1Node, B3SOIFDqsubs1Node) - TSTALLOC(B3SOIFDQsubs2Ptr, B3SOIFDqsubs2Node, B3SOIFDqsubs2Node) - TSTALLOC(B3SOIFDqePtr, B3SOIFDqeNode, B3SOIFDqeNode) - TSTALLOC(B3SOIFDqdPtr, B3SOIFDqdNode, B3SOIFDqdNode) - TSTALLOC(B3SOIFDqgPtr, B3SOIFDqgNode, B3SOIFDqgNode) + TSTALLOC(B3SOIFDGmPtr, B3SOIFDgmNode, B3SOIFDgmNode); + TSTALLOC(B3SOIFDGmbsPtr, B3SOIFDgmbsNode, B3SOIFDgmbsNode); + TSTALLOC(B3SOIFDGdsPtr, B3SOIFDgdsNode, B3SOIFDgdsNode); + TSTALLOC(B3SOIFDGmePtr, B3SOIFDgmeNode, B3SOIFDgmeNode); + TSTALLOC(B3SOIFDVbs0teffPtr, B3SOIFDvbs0teffNode, B3SOIFDvbs0teffNode); + TSTALLOC(B3SOIFDVthPtr, B3SOIFDvthNode, B3SOIFDvthNode); + TSTALLOC(B3SOIFDVgsteffPtr, B3SOIFDvgsteffNode, B3SOIFDvgsteffNode); + TSTALLOC(B3SOIFDXcsatPtr, B3SOIFDxcsatNode, B3SOIFDxcsatNode); + TSTALLOC(B3SOIFDVcscvPtr, B3SOIFDvcscvNode, B3SOIFDvcscvNode); + TSTALLOC(B3SOIFDVdscvPtr, B3SOIFDvdscvNode, B3SOIFDvdscvNode); + TSTALLOC(B3SOIFDCbePtr, B3SOIFDcbeNode, B3SOIFDcbeNode); + TSTALLOC(B3SOIFDDum1Ptr, B3SOIFDdum1Node, B3SOIFDdum1Node); + TSTALLOC(B3SOIFDDum2Ptr, B3SOIFDdum2Node, B3SOIFDdum2Node); + TSTALLOC(B3SOIFDDum3Ptr, B3SOIFDdum3Node, B3SOIFDdum3Node); + TSTALLOC(B3SOIFDDum4Ptr, B3SOIFDdum4Node, B3SOIFDdum4Node); + TSTALLOC(B3SOIFDDum5Ptr, B3SOIFDdum5Node, B3SOIFDdum5Node); + TSTALLOC(B3SOIFDQaccPtr, B3SOIFDqaccNode, B3SOIFDqaccNode); + TSTALLOC(B3SOIFDQsub0Ptr, B3SOIFDqsub0Node, B3SOIFDqsub0Node); + TSTALLOC(B3SOIFDQsubs1Ptr, B3SOIFDqsubs1Node, B3SOIFDqsubs1Node); + TSTALLOC(B3SOIFDQsubs2Ptr, B3SOIFDqsubs2Node, B3SOIFDqsubs2Node); + TSTALLOC(B3SOIFDqePtr, B3SOIFDqeNode, B3SOIFDqeNode); + TSTALLOC(B3SOIFDqdPtr, B3SOIFDqdNode, B3SOIFDqdNode); + TSTALLOC(B3SOIFDqgPtr, B3SOIFDqgNode, B3SOIFDqgNode); } } diff --git a/src/spicelib/devices/bsim3soi_pd/Makefile.am b/src/spicelib/devices/bsim3soi_pd/Makefile.am index dbcd2869c..fef4dd6c5 100644 --- a/src/spicelib/devices/bsim3soi_pd/Makefile.am +++ b/src/spicelib/devices/bsim3soi_pd/Makefile.am @@ -2,29 +2,29 @@ noinst_LTLIBRARIES = libbsim3soipd.la -libbsim3soipd_la_SOURCES = \ - b3soipd.c \ - b3soipdacld.c \ - b3soipdask.c \ - b3soipdcheck.c \ - b3soipdcvtest.c \ - b3soipddel.c \ - b3soipddest.c \ - b3soipdgetic.c \ - b3soipdld.c \ - b3soipdmask.c \ - b3soipdmdel.c \ - b3soipdmpar.c \ - b3soipdnoi.c \ - b3soipdpar.c \ - b3soipdpzld.c \ - b3soipdset.c \ - b3soipdtemp.c \ - b3soipdtrunc.c \ - b3soipddef.h \ - b3soipdext.h \ - b3soipdinit.c \ - b3soipdinit.h \ +libbsim3soipd_la_SOURCES = \ + b3soipd.c \ + b3soipdacld.c \ + b3soipdask.c \ + b3soipdcheck.c \ + b3soipdcvtest.c \ + b3soipddel.c \ + b3soipddest.c \ + b3soipdgetic.c \ + b3soipdld.c \ + b3soipdmask.c \ + b3soipdmdel.c \ + b3soipdmpar.c \ + b3soipdnoi.c \ + b3soipdpar.c \ + b3soipdpzld.c \ + b3soipdset.c \ + b3soipdtemp.c \ + b3soipdtrunc.c \ + b3soipddef.h \ + b3soipdext.h \ + b3soipdinit.c \ + b3soipdinit.h \ b3soipditf.h @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3soipd_la_SOURCES += b3soipdbindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3soipd_la_SOURCES += b3soipdnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3soi_pd/b3soipdext.h b/src/spicelib/devices/bsim3soi_pd/b3soipdext.h index f8661c4f8..00915e890 100644 --- a/src/spicelib/devices/bsim3soi_pd/b3soipdext.h +++ b/src/spicelib/devices/bsim3soi_pd/b3soipdext.h @@ -34,3 +34,7 @@ extern int B3SOIPDbindCSC (GENmodel*, CKTcircuit*) ; extern int B3SOIPDbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B3SOIPDbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B3SOIPDnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c b/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c index 02f987ad1..ec318a5d7 100644 --- a/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c +++ b/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c @@ -72,12 +72,17 @@ SPICEdev B3SOIPDinfo = { #endif /* DEVinstSize*/ &B3SOIPDiSize, /* DEVmodSize*/ &B3SOIPDmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B3SOIPDbindCSC, /* DEVbindCSCComplex */ B3SOIPDbindCSCComplex, /* DEVbindCSCComplexToReal */ B3SOIPDbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B3SOIPDnodeIsNonLinear +#endif + }; SPICEdev * diff --git a/src/spicelib/devices/bsim3soi_pd/b3soipdnode.c b/src/spicelib/devices/bsim3soi_pd/b3soipdnode.c new file mode 100644 index 000000000..3c448e0b3 --- /dev/null +++ b/src/spicelib/devices/bsim3soi_pd/b3soipdnode.c @@ -0,0 +1,55 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "b3soipddef.h" +#include "ngspice/sperror.h" + +int +B3SOIPDnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B3SOIPDmodel *model = (B3SOIPDmodel *)inModel ; + B3SOIPDinstance *here ; + + /* loop through all the B3SOIPD models */ + for ( ; model != NULL ; model = model->B3SOIPDnextModel) + { + /* loop through all the instances of the model */ + for (here = model->B3SOIPDinstances ; here != NULL ; here = here->B3SOIPDnextInstance) + { + ckt->CKTnodeIsLinear [here->B3SOIPDdNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDsNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDtempNode] = 0 ; + if (here->B3SOIPDdebugMod != 0) + { + ckt->CKTnodeIsLinear [here->B3SOIPDvbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDidsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDicNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDibsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDibdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDiiiNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDigNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDgiggNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDgigdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDgigbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDigidlNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDitunNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDibpNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDcbbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDcbdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDcbgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDqbfNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDqjsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDqjdNode] = 0 ; + } + ckt->CKTnodeIsLinear [here->B3SOIPDgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B3SOIPDpNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3soi_pd/b3soipdset.c b/src/spicelib/devices/bsim3soi_pd/b3soipdset.c index eeb731037..8a4e3b047 100644 --- a/src/spicelib/devices/bsim3soi_pd/b3soipdset.c +++ b/src/spicelib/devices/bsim3soi_pd/b3soipdset.c @@ -1347,98 +1347,98 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) if ((model->B3SOIPDshMod == 1) && (here->B3SOIPDrth0!=0.0)) { - TSTALLOC(B3SOIPDTemptempPtr, B3SOIPDtempNode, B3SOIPDtempNode) - TSTALLOC(B3SOIPDTempdpPtr, B3SOIPDtempNode, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDTempspPtr, B3SOIPDtempNode, B3SOIPDsNodePrime) - TSTALLOC(B3SOIPDTempgPtr, B3SOIPDtempNode, B3SOIPDgNode) - TSTALLOC(B3SOIPDTempbPtr, B3SOIPDtempNode, B3SOIPDbNode) + TSTALLOC(B3SOIPDTemptempPtr, B3SOIPDtempNode, B3SOIPDtempNode); + TSTALLOC(B3SOIPDTempdpPtr, B3SOIPDtempNode, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDTempspPtr, B3SOIPDtempNode, B3SOIPDsNodePrime); + TSTALLOC(B3SOIPDTempgPtr, B3SOIPDtempNode, B3SOIPDgNode); + TSTALLOC(B3SOIPDTempbPtr, B3SOIPDtempNode, B3SOIPDbNode); - TSTALLOC(B3SOIPDGtempPtr, B3SOIPDgNode, B3SOIPDtempNode) - TSTALLOC(B3SOIPDDPtempPtr, B3SOIPDdNodePrime, B3SOIPDtempNode) - TSTALLOC(B3SOIPDSPtempPtr, B3SOIPDsNodePrime, B3SOIPDtempNode) - TSTALLOC(B3SOIPDEtempPtr, B3SOIPDeNode, B3SOIPDtempNode) - TSTALLOC(B3SOIPDBtempPtr, B3SOIPDbNode, B3SOIPDtempNode) + TSTALLOC(B3SOIPDGtempPtr, B3SOIPDgNode, B3SOIPDtempNode); + TSTALLOC(B3SOIPDDPtempPtr, B3SOIPDdNodePrime, B3SOIPDtempNode); + TSTALLOC(B3SOIPDSPtempPtr, B3SOIPDsNodePrime, B3SOIPDtempNode); + TSTALLOC(B3SOIPDEtempPtr, B3SOIPDeNode, B3SOIPDtempNode); + TSTALLOC(B3SOIPDBtempPtr, B3SOIPDbNode, B3SOIPDtempNode); if (here->B3SOIPDbodyMod == 1) { - TSTALLOC(B3SOIPDPtempPtr, B3SOIPDpNode, B3SOIPDtempNode) + TSTALLOC(B3SOIPDPtempPtr, B3SOIPDpNode, B3SOIPDtempNode); } } if (here->B3SOIPDbodyMod == 2) { /* Don't create any Jacobian entry for pNode */ } else if (here->B3SOIPDbodyMod == 1) { - TSTALLOC(B3SOIPDBpPtr, B3SOIPDbNode, B3SOIPDpNode) - TSTALLOC(B3SOIPDPbPtr, B3SOIPDpNode, B3SOIPDbNode) - TSTALLOC(B3SOIPDPpPtr, B3SOIPDpNode, B3SOIPDpNode) + TSTALLOC(B3SOIPDBpPtr, B3SOIPDbNode, B3SOIPDpNode); + TSTALLOC(B3SOIPDPbPtr, B3SOIPDpNode, B3SOIPDbNode); + TSTALLOC(B3SOIPDPpPtr, B3SOIPDpNode, B3SOIPDpNode); } - TSTALLOC(B3SOIPDEbPtr, B3SOIPDeNode, B3SOIPDbNode) - TSTALLOC(B3SOIPDGbPtr, B3SOIPDgNode, B3SOIPDbNode) - TSTALLOC(B3SOIPDDPbPtr, B3SOIPDdNodePrime, B3SOIPDbNode) - TSTALLOC(B3SOIPDSPbPtr, B3SOIPDsNodePrime, B3SOIPDbNode) - TSTALLOC(B3SOIPDBePtr, B3SOIPDbNode, B3SOIPDeNode) - TSTALLOC(B3SOIPDBgPtr, B3SOIPDbNode, B3SOIPDgNode) - TSTALLOC(B3SOIPDBdpPtr, B3SOIPDbNode, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDBspPtr, B3SOIPDbNode, B3SOIPDsNodePrime) - TSTALLOC(B3SOIPDBbPtr, B3SOIPDbNode, B3SOIPDbNode) + TSTALLOC(B3SOIPDEbPtr, B3SOIPDeNode, B3SOIPDbNode); + TSTALLOC(B3SOIPDGbPtr, B3SOIPDgNode, B3SOIPDbNode); + TSTALLOC(B3SOIPDDPbPtr, B3SOIPDdNodePrime, B3SOIPDbNode); + TSTALLOC(B3SOIPDSPbPtr, B3SOIPDsNodePrime, B3SOIPDbNode); + TSTALLOC(B3SOIPDBePtr, B3SOIPDbNode, B3SOIPDeNode); + TSTALLOC(B3SOIPDBgPtr, B3SOIPDbNode, B3SOIPDgNode); + TSTALLOC(B3SOIPDBdpPtr, B3SOIPDbNode, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDBspPtr, B3SOIPDbNode, B3SOIPDsNodePrime); + TSTALLOC(B3SOIPDBbPtr, B3SOIPDbNode, B3SOIPDbNode); - TSTALLOC(B3SOIPDEgPtr, B3SOIPDeNode, B3SOIPDgNode) - TSTALLOC(B3SOIPDEdpPtr, B3SOIPDeNode, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDEspPtr, B3SOIPDeNode, B3SOIPDsNodePrime) - TSTALLOC(B3SOIPDGePtr, B3SOIPDgNode, B3SOIPDeNode) - TSTALLOC(B3SOIPDDPePtr, B3SOIPDdNodePrime, B3SOIPDeNode) - TSTALLOC(B3SOIPDSPePtr, B3SOIPDsNodePrime, B3SOIPDeNode) + TSTALLOC(B3SOIPDEgPtr, B3SOIPDeNode, B3SOIPDgNode); + TSTALLOC(B3SOIPDEdpPtr, B3SOIPDeNode, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDEspPtr, B3SOIPDeNode, B3SOIPDsNodePrime); + TSTALLOC(B3SOIPDGePtr, B3SOIPDgNode, B3SOIPDeNode); + TSTALLOC(B3SOIPDDPePtr, B3SOIPDdNodePrime, B3SOIPDeNode); + TSTALLOC(B3SOIPDSPePtr, B3SOIPDsNodePrime, B3SOIPDeNode); - TSTALLOC(B3SOIPDEePtr, B3SOIPDeNode, B3SOIPDeNode) + TSTALLOC(B3SOIPDEePtr, B3SOIPDeNode, B3SOIPDeNode); - TSTALLOC(B3SOIPDGgPtr, B3SOIPDgNode, B3SOIPDgNode) - TSTALLOC(B3SOIPDGdpPtr, B3SOIPDgNode, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDGspPtr, B3SOIPDgNode, B3SOIPDsNodePrime) + TSTALLOC(B3SOIPDGgPtr, B3SOIPDgNode, B3SOIPDgNode); + TSTALLOC(B3SOIPDGdpPtr, B3SOIPDgNode, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDGspPtr, B3SOIPDgNode, B3SOIPDsNodePrime); - TSTALLOC(B3SOIPDDPgPtr, B3SOIPDdNodePrime, B3SOIPDgNode) - TSTALLOC(B3SOIPDDPdpPtr, B3SOIPDdNodePrime, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDDPspPtr, B3SOIPDdNodePrime, B3SOIPDsNodePrime) - TSTALLOC(B3SOIPDDPdPtr, B3SOIPDdNodePrime, B3SOIPDdNode) + TSTALLOC(B3SOIPDDPgPtr, B3SOIPDdNodePrime, B3SOIPDgNode); + TSTALLOC(B3SOIPDDPdpPtr, B3SOIPDdNodePrime, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDDPspPtr, B3SOIPDdNodePrime, B3SOIPDsNodePrime); + TSTALLOC(B3SOIPDDPdPtr, B3SOIPDdNodePrime, B3SOIPDdNode); - TSTALLOC(B3SOIPDSPgPtr, B3SOIPDsNodePrime, B3SOIPDgNode) - TSTALLOC(B3SOIPDSPdpPtr, B3SOIPDsNodePrime, B3SOIPDdNodePrime) - TSTALLOC(B3SOIPDSPspPtr, B3SOIPDsNodePrime, B3SOIPDsNodePrime) - TSTALLOC(B3SOIPDSPsPtr, B3SOIPDsNodePrime, B3SOIPDsNode) + TSTALLOC(B3SOIPDSPgPtr, B3SOIPDsNodePrime, B3SOIPDgNode); + TSTALLOC(B3SOIPDSPdpPtr, B3SOIPDsNodePrime, B3SOIPDdNodePrime); + TSTALLOC(B3SOIPDSPspPtr, B3SOIPDsNodePrime, B3SOIPDsNodePrime); + TSTALLOC(B3SOIPDSPsPtr, B3SOIPDsNodePrime, B3SOIPDsNode); - TSTALLOC(B3SOIPDDdPtr, B3SOIPDdNode, B3SOIPDdNode) - TSTALLOC(B3SOIPDDdpPtr, B3SOIPDdNode, B3SOIPDdNodePrime) + TSTALLOC(B3SOIPDDdPtr, B3SOIPDdNode, B3SOIPDdNode); + TSTALLOC(B3SOIPDDdpPtr, B3SOIPDdNode, B3SOIPDdNodePrime); - TSTALLOC(B3SOIPDSsPtr, B3SOIPDsNode, B3SOIPDsNode) - TSTALLOC(B3SOIPDSspPtr, B3SOIPDsNode, B3SOIPDsNodePrime) + TSTALLOC(B3SOIPDSsPtr, B3SOIPDsNode, B3SOIPDsNode); + TSTALLOC(B3SOIPDSspPtr, B3SOIPDsNode, B3SOIPDsNodePrime); /* here for debugging purpose only */ if (here->B3SOIPDdebugMod != 0) { - TSTALLOC(B3SOIPDVbsPtr, B3SOIPDvbsNode, B3SOIPDvbsNode) - TSTALLOC(B3SOIPDIdsPtr, B3SOIPDidsNode, B3SOIPDidsNode) - TSTALLOC(B3SOIPDIcPtr, B3SOIPDicNode, B3SOIPDicNode) - TSTALLOC(B3SOIPDIbsPtr, B3SOIPDibsNode, B3SOIPDibsNode) - TSTALLOC(B3SOIPDIbdPtr, B3SOIPDibdNode, B3SOIPDibdNode) - TSTALLOC(B3SOIPDIiiPtr, B3SOIPDiiiNode, B3SOIPDiiiNode) - TSTALLOC(B3SOIPDIgPtr, B3SOIPDigNode, B3SOIPDigNode) - TSTALLOC(B3SOIPDGiggPtr, B3SOIPDgiggNode, B3SOIPDgiggNode) - TSTALLOC(B3SOIPDGigdPtr, B3SOIPDgigdNode, B3SOIPDgigdNode) - TSTALLOC(B3SOIPDGigbPtr, B3SOIPDgigbNode, B3SOIPDgigbNode) - TSTALLOC(B3SOIPDIgidlPtr, B3SOIPDigidlNode, B3SOIPDigidlNode) - TSTALLOC(B3SOIPDItunPtr, B3SOIPDitunNode, B3SOIPDitunNode) - TSTALLOC(B3SOIPDIbpPtr, B3SOIPDibpNode, B3SOIPDibpNode) - TSTALLOC(B3SOIPDCbbPtr, B3SOIPDcbbNode, B3SOIPDcbbNode) - TSTALLOC(B3SOIPDCbdPtr, B3SOIPDcbdNode, B3SOIPDcbdNode) - TSTALLOC(B3SOIPDCbgPtr, B3SOIPDcbgNode, B3SOIPDcbgNode) - TSTALLOC(B3SOIPDQbfPtr, B3SOIPDqbfNode, B3SOIPDqbfNode) - TSTALLOC(B3SOIPDQjsPtr, B3SOIPDqjsNode, B3SOIPDqjsNode) - TSTALLOC(B3SOIPDQjdPtr, B3SOIPDqjdNode, B3SOIPDqjdNode) + TSTALLOC(B3SOIPDVbsPtr, B3SOIPDvbsNode, B3SOIPDvbsNode); + TSTALLOC(B3SOIPDIdsPtr, B3SOIPDidsNode, B3SOIPDidsNode); + TSTALLOC(B3SOIPDIcPtr, B3SOIPDicNode, B3SOIPDicNode); + TSTALLOC(B3SOIPDIbsPtr, B3SOIPDibsNode, B3SOIPDibsNode); + TSTALLOC(B3SOIPDIbdPtr, B3SOIPDibdNode, B3SOIPDibdNode); + TSTALLOC(B3SOIPDIiiPtr, B3SOIPDiiiNode, B3SOIPDiiiNode); + TSTALLOC(B3SOIPDIgPtr, B3SOIPDigNode, B3SOIPDigNode); + TSTALLOC(B3SOIPDGiggPtr, B3SOIPDgiggNode, B3SOIPDgiggNode); + TSTALLOC(B3SOIPDGigdPtr, B3SOIPDgigdNode, B3SOIPDgigdNode); + TSTALLOC(B3SOIPDGigbPtr, B3SOIPDgigbNode, B3SOIPDgigbNode); + TSTALLOC(B3SOIPDIgidlPtr, B3SOIPDigidlNode, B3SOIPDigidlNode); + TSTALLOC(B3SOIPDItunPtr, B3SOIPDitunNode, B3SOIPDitunNode); + TSTALLOC(B3SOIPDIbpPtr, B3SOIPDibpNode, B3SOIPDibpNode); + TSTALLOC(B3SOIPDCbbPtr, B3SOIPDcbbNode, B3SOIPDcbbNode); + TSTALLOC(B3SOIPDCbdPtr, B3SOIPDcbdNode, B3SOIPDcbdNode); + TSTALLOC(B3SOIPDCbgPtr, B3SOIPDcbgNode, B3SOIPDcbgNode); + TSTALLOC(B3SOIPDQbfPtr, B3SOIPDqbfNode, B3SOIPDqbfNode); + TSTALLOC(B3SOIPDQjsPtr, B3SOIPDqjsNode, B3SOIPDqjsNode); + TSTALLOC(B3SOIPDQjdPtr, B3SOIPDqjdNode, B3SOIPDqjdNode); } diff --git a/src/spicelib/devices/bsim3v0/Makefile.am b/src/spicelib/devices/bsim3v0/Makefile.am index 5a953f630..959a94a75 100644 --- a/src/spicelib/devices/bsim3v0/Makefile.am +++ b/src/spicelib/devices/bsim3v0/Makefile.am @@ -39,6 +39,10 @@ if UMFPACK_WANTED libbsim3v0_la_SOURCES += b3v0bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3v0_la_SOURCES += b3v0node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3v0/b3v0node.c b/src/spicelib/devices/bsim3v0/b3v0node.c new file mode 100644 index 000000000..6feab17db --- /dev/null +++ b/src/spicelib/devices/bsim3v0/b3v0node.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3v0def.h" +#include "ngspice/sperror.h" + +int +BSIM3v0nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM3v0model *model = (BSIM3v0model *)inModel ; + BSIM3v0instance *here ; + + /* loop through all the BSIM3v0 models */ + for ( ; model != NULL ; model = model->BSIM3v0nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM3v0instances ; here != NULL ; here = here->BSIM3v0nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM3v0dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v0sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v0qNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v0gNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v0bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3v0/b3v0set.c b/src/spicelib/devices/bsim3v0/b3v0set.c index 8016aa937..4243b7456 100644 --- a/src/spicelib/devices/bsim3v0/b3v0set.c +++ b/src/spicelib/devices/bsim3v0/b3v0set.c @@ -848,43 +848,43 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM3v0DdPtr, BSIM3v0dNode, BSIM3v0dNode) - TSTALLOC(BSIM3v0GgPtr, BSIM3v0gNode, BSIM3v0gNode) - TSTALLOC(BSIM3v0SsPtr, BSIM3v0sNode, BSIM3v0sNode) - TSTALLOC(BSIM3v0BbPtr, BSIM3v0bNode, BSIM3v0bNode) - TSTALLOC(BSIM3v0DPdpPtr, BSIM3v0dNodePrime, BSIM3v0dNodePrime) - TSTALLOC(BSIM3v0SPspPtr, BSIM3v0sNodePrime, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0DdpPtr, BSIM3v0dNode, BSIM3v0dNodePrime) - TSTALLOC(BSIM3v0GbPtr, BSIM3v0gNode, BSIM3v0bNode) - TSTALLOC(BSIM3v0GdpPtr, BSIM3v0gNode, BSIM3v0dNodePrime) - TSTALLOC(BSIM3v0GspPtr, BSIM3v0gNode, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0SspPtr, BSIM3v0sNode, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0BdpPtr, BSIM3v0bNode, BSIM3v0dNodePrime) - TSTALLOC(BSIM3v0BspPtr, BSIM3v0bNode, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0DPspPtr, BSIM3v0dNodePrime, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0DPdPtr, BSIM3v0dNodePrime, BSIM3v0dNode) - TSTALLOC(BSIM3v0BgPtr, BSIM3v0bNode, BSIM3v0gNode) - TSTALLOC(BSIM3v0DPgPtr, BSIM3v0dNodePrime, BSIM3v0gNode) - TSTALLOC(BSIM3v0SPgPtr, BSIM3v0sNodePrime, BSIM3v0gNode) - TSTALLOC(BSIM3v0SPsPtr, BSIM3v0sNodePrime, BSIM3v0sNode) - TSTALLOC(BSIM3v0DPbPtr, BSIM3v0dNodePrime, BSIM3v0bNode) - TSTALLOC(BSIM3v0SPbPtr, BSIM3v0sNodePrime, BSIM3v0bNode) - TSTALLOC(BSIM3v0SPdpPtr, BSIM3v0sNodePrime, BSIM3v0dNodePrime) + TSTALLOC(BSIM3v0DdPtr, BSIM3v0dNode, BSIM3v0dNode); + TSTALLOC(BSIM3v0GgPtr, BSIM3v0gNode, BSIM3v0gNode); + TSTALLOC(BSIM3v0SsPtr, BSIM3v0sNode, BSIM3v0sNode); + TSTALLOC(BSIM3v0BbPtr, BSIM3v0bNode, BSIM3v0bNode); + TSTALLOC(BSIM3v0DPdpPtr, BSIM3v0dNodePrime, BSIM3v0dNodePrime); + TSTALLOC(BSIM3v0SPspPtr, BSIM3v0sNodePrime, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0DdpPtr, BSIM3v0dNode, BSIM3v0dNodePrime); + TSTALLOC(BSIM3v0GbPtr, BSIM3v0gNode, BSIM3v0bNode); + TSTALLOC(BSIM3v0GdpPtr, BSIM3v0gNode, BSIM3v0dNodePrime); + TSTALLOC(BSIM3v0GspPtr, BSIM3v0gNode, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0SspPtr, BSIM3v0sNode, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0BdpPtr, BSIM3v0bNode, BSIM3v0dNodePrime); + TSTALLOC(BSIM3v0BspPtr, BSIM3v0bNode, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0DPspPtr, BSIM3v0dNodePrime, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0DPdPtr, BSIM3v0dNodePrime, BSIM3v0dNode); + TSTALLOC(BSIM3v0BgPtr, BSIM3v0bNode, BSIM3v0gNode); + TSTALLOC(BSIM3v0DPgPtr, BSIM3v0dNodePrime, BSIM3v0gNode); + TSTALLOC(BSIM3v0SPgPtr, BSIM3v0sNodePrime, BSIM3v0gNode); + TSTALLOC(BSIM3v0SPsPtr, BSIM3v0sNodePrime, BSIM3v0sNode); + TSTALLOC(BSIM3v0DPbPtr, BSIM3v0dNodePrime, BSIM3v0bNode); + TSTALLOC(BSIM3v0SPbPtr, BSIM3v0sNodePrime, BSIM3v0bNode); + TSTALLOC(BSIM3v0SPdpPtr, BSIM3v0sNodePrime, BSIM3v0dNodePrime); - TSTALLOC(BSIM3v0QqPtr, BSIM3v0qNode, BSIM3v0qNode) + TSTALLOC(BSIM3v0QqPtr, BSIM3v0qNode, BSIM3v0qNode); - TSTALLOC(BSIM3v0QdpPtr, BSIM3v0qNode, BSIM3v0dNodePrime) - TSTALLOC(BSIM3v0QspPtr, BSIM3v0qNode, BSIM3v0sNodePrime) - TSTALLOC(BSIM3v0QgPtr, BSIM3v0qNode, BSIM3v0gNode) - TSTALLOC(BSIM3v0QbPtr, BSIM3v0qNode, BSIM3v0bNode) - TSTALLOC(BSIM3v0DPqPtr, BSIM3v0dNodePrime, BSIM3v0qNode) - TSTALLOC(BSIM3v0SPqPtr, BSIM3v0sNodePrime, BSIM3v0qNode) - TSTALLOC(BSIM3v0GqPtr, BSIM3v0gNode, BSIM3v0qNode) - TSTALLOC(BSIM3v0BqPtr, BSIM3v0bNode, BSIM3v0qNode) + TSTALLOC(BSIM3v0QdpPtr, BSIM3v0qNode, BSIM3v0dNodePrime); + TSTALLOC(BSIM3v0QspPtr, BSIM3v0qNode, BSIM3v0sNodePrime); + TSTALLOC(BSIM3v0QgPtr, BSIM3v0qNode, BSIM3v0gNode); + TSTALLOC(BSIM3v0QbPtr, BSIM3v0qNode, BSIM3v0bNode); + TSTALLOC(BSIM3v0DPqPtr, BSIM3v0dNodePrime, BSIM3v0qNode); + TSTALLOC(BSIM3v0SPqPtr, BSIM3v0sNodePrime, BSIM3v0qNode); + TSTALLOC(BSIM3v0GqPtr, BSIM3v0gNode, BSIM3v0qNode); + TSTALLOC(BSIM3v0BqPtr, BSIM3v0bNode, BSIM3v0qNode); } } diff --git a/src/spicelib/devices/bsim3v0/bsim3v0ext.h b/src/spicelib/devices/bsim3v0/bsim3v0ext.h index c49bcdaf6..d4df585f3 100644 --- a/src/spicelib/devices/bsim3v0/bsim3v0ext.h +++ b/src/spicelib/devices/bsim3v0/bsim3v0ext.h @@ -26,11 +26,14 @@ extern int BSIM3v0setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int BSIM3v0temp(GENmodel*,CKTcircuit*); extern int BSIM3v0trunc(GENmodel*,CKTcircuit*,double*); extern int BSIM3v0noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); -extern int BSIM3v0unsetup(GENmodel *, CKTcircuit *); - +extern int BSIM3v0unsetup(GENmodel *, CKTcircuit *); #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int BSIM3v0bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM3v0bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM3v0bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM3v0nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3v0/bsim3v0init.c b/src/spicelib/devices/bsim3v0/bsim3v0init.c index 161ac2e20..c494f7039 100644 --- a/src/spicelib/devices/bsim3v0/bsim3v0init.c +++ b/src/spicelib/devices/bsim3v0/bsim3v0init.c @@ -71,12 +71,17 @@ SPICEdev B3v0info = { #endif /* DEVinstSize */ &BSIM3v0iSize, /* DEVmodSize */ &BSIM3v0mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ BSIM3v0bindCSC, /* DEVbindCSCComplex */ BSIM3v0bindCSCComplex, /* DEVbindCSCComplexToReal */ BSIM3v0bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ BSIM3v0nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim3v1/Makefile.am b/src/spicelib/devices/bsim3v1/Makefile.am index ff7ae9f81..3e3ecaedf 100644 --- a/src/spicelib/devices/bsim3v1/Makefile.am +++ b/src/spicelib/devices/bsim3v1/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3v1_la_SOURCES += b3v1bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3v1_la_SOURCES += b3v1node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3v1/b3v1node.c b/src/spicelib/devices/bsim3v1/b3v1node.c new file mode 100644 index 000000000..2349d7e11 --- /dev/null +++ b/src/spicelib/devices/bsim3v1/b3v1node.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3v1def.h" +#include "ngspice/sperror.h" + +int +BSIM3v1nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM3v1model *model = (BSIM3v1model *)inModel ; + BSIM3v1instance *here ; + + /* loop through all the BSIM3v1 models */ + for ( ; model != NULL ; model = model->BSIM3v1nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM3v1instances ; here != NULL ; here = here->BSIM3v1nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM3v1dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v1sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v1qNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v1gNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v1bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3v1/b3v1set.c b/src/spicelib/devices/bsim3v1/b3v1set.c index e87a372a1..e3bedcbb9 100644 --- a/src/spicelib/devices/bsim3v1/b3v1set.c +++ b/src/spicelib/devices/bsim3v1/b3v1set.c @@ -908,43 +908,43 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM3v1DdPtr, BSIM3v1dNode, BSIM3v1dNode) - TSTALLOC(BSIM3v1GgPtr, BSIM3v1gNode, BSIM3v1gNode) - TSTALLOC(BSIM3v1SsPtr, BSIM3v1sNode, BSIM3v1sNode) - TSTALLOC(BSIM3v1BbPtr, BSIM3v1bNode, BSIM3v1bNode) - TSTALLOC(BSIM3v1DPdpPtr, BSIM3v1dNodePrime, BSIM3v1dNodePrime) - TSTALLOC(BSIM3v1SPspPtr, BSIM3v1sNodePrime, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1DdpPtr, BSIM3v1dNode, BSIM3v1dNodePrime) - TSTALLOC(BSIM3v1GbPtr, BSIM3v1gNode, BSIM3v1bNode) - TSTALLOC(BSIM3v1GdpPtr, BSIM3v1gNode, BSIM3v1dNodePrime) - TSTALLOC(BSIM3v1GspPtr, BSIM3v1gNode, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1SspPtr, BSIM3v1sNode, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1BdpPtr, BSIM3v1bNode, BSIM3v1dNodePrime) - TSTALLOC(BSIM3v1BspPtr, BSIM3v1bNode, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1DPspPtr, BSIM3v1dNodePrime, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1DPdPtr, BSIM3v1dNodePrime, BSIM3v1dNode) - TSTALLOC(BSIM3v1BgPtr, BSIM3v1bNode, BSIM3v1gNode) - TSTALLOC(BSIM3v1DPgPtr, BSIM3v1dNodePrime, BSIM3v1gNode) - TSTALLOC(BSIM3v1SPgPtr, BSIM3v1sNodePrime, BSIM3v1gNode) - TSTALLOC(BSIM3v1SPsPtr, BSIM3v1sNodePrime, BSIM3v1sNode) - TSTALLOC(BSIM3v1DPbPtr, BSIM3v1dNodePrime, BSIM3v1bNode) - TSTALLOC(BSIM3v1SPbPtr, BSIM3v1sNodePrime, BSIM3v1bNode) - TSTALLOC(BSIM3v1SPdpPtr, BSIM3v1sNodePrime, BSIM3v1dNodePrime) + TSTALLOC(BSIM3v1DdPtr, BSIM3v1dNode, BSIM3v1dNode); + TSTALLOC(BSIM3v1GgPtr, BSIM3v1gNode, BSIM3v1gNode); + TSTALLOC(BSIM3v1SsPtr, BSIM3v1sNode, BSIM3v1sNode); + TSTALLOC(BSIM3v1BbPtr, BSIM3v1bNode, BSIM3v1bNode); + TSTALLOC(BSIM3v1DPdpPtr, BSIM3v1dNodePrime, BSIM3v1dNodePrime); + TSTALLOC(BSIM3v1SPspPtr, BSIM3v1sNodePrime, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1DdpPtr, BSIM3v1dNode, BSIM3v1dNodePrime); + TSTALLOC(BSIM3v1GbPtr, BSIM3v1gNode, BSIM3v1bNode); + TSTALLOC(BSIM3v1GdpPtr, BSIM3v1gNode, BSIM3v1dNodePrime); + TSTALLOC(BSIM3v1GspPtr, BSIM3v1gNode, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1SspPtr, BSIM3v1sNode, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1BdpPtr, BSIM3v1bNode, BSIM3v1dNodePrime); + TSTALLOC(BSIM3v1BspPtr, BSIM3v1bNode, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1DPspPtr, BSIM3v1dNodePrime, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1DPdPtr, BSIM3v1dNodePrime, BSIM3v1dNode); + TSTALLOC(BSIM3v1BgPtr, BSIM3v1bNode, BSIM3v1gNode); + TSTALLOC(BSIM3v1DPgPtr, BSIM3v1dNodePrime, BSIM3v1gNode); + TSTALLOC(BSIM3v1SPgPtr, BSIM3v1sNodePrime, BSIM3v1gNode); + TSTALLOC(BSIM3v1SPsPtr, BSIM3v1sNodePrime, BSIM3v1sNode); + TSTALLOC(BSIM3v1DPbPtr, BSIM3v1dNodePrime, BSIM3v1bNode); + TSTALLOC(BSIM3v1SPbPtr, BSIM3v1sNodePrime, BSIM3v1bNode); + TSTALLOC(BSIM3v1SPdpPtr, BSIM3v1sNodePrime, BSIM3v1dNodePrime); - TSTALLOC(BSIM3v1QqPtr, BSIM3v1qNode, BSIM3v1qNode) + TSTALLOC(BSIM3v1QqPtr, BSIM3v1qNode, BSIM3v1qNode); - TSTALLOC(BSIM3v1QdpPtr, BSIM3v1qNode, BSIM3v1dNodePrime) - TSTALLOC(BSIM3v1QspPtr, BSIM3v1qNode, BSIM3v1sNodePrime) - TSTALLOC(BSIM3v1QgPtr, BSIM3v1qNode, BSIM3v1gNode) - TSTALLOC(BSIM3v1QbPtr, BSIM3v1qNode, BSIM3v1bNode) - TSTALLOC(BSIM3v1DPqPtr, BSIM3v1dNodePrime, BSIM3v1qNode) - TSTALLOC(BSIM3v1SPqPtr, BSIM3v1sNodePrime, BSIM3v1qNode) - TSTALLOC(BSIM3v1GqPtr, BSIM3v1gNode, BSIM3v1qNode) - TSTALLOC(BSIM3v1BqPtr, BSIM3v1bNode, BSIM3v1qNode) + TSTALLOC(BSIM3v1QdpPtr, BSIM3v1qNode, BSIM3v1dNodePrime); + TSTALLOC(BSIM3v1QspPtr, BSIM3v1qNode, BSIM3v1sNodePrime); + TSTALLOC(BSIM3v1QgPtr, BSIM3v1qNode, BSIM3v1gNode); + TSTALLOC(BSIM3v1QbPtr, BSIM3v1qNode, BSIM3v1bNode); + TSTALLOC(BSIM3v1DPqPtr, BSIM3v1dNodePrime, BSIM3v1qNode); + TSTALLOC(BSIM3v1SPqPtr, BSIM3v1sNodePrime, BSIM3v1qNode); + TSTALLOC(BSIM3v1GqPtr, BSIM3v1gNode, BSIM3v1qNode); + TSTALLOC(BSIM3v1BqPtr, BSIM3v1bNode, BSIM3v1qNode); } } diff --git a/src/spicelib/devices/bsim3v1/bsim3v1ext.h b/src/spicelib/devices/bsim3v1/bsim3v1ext.h index 7a4a911c7..74ae60e39 100644 --- a/src/spicelib/devices/bsim3v1/bsim3v1ext.h +++ b/src/spicelib/devices/bsim3v1/bsim3v1ext.h @@ -29,9 +29,12 @@ extern int BSIM3v1trunc(GENmodel *, CKTcircuit *, double *); extern int BSIM3v1noise(int, int, GENmodel *, CKTcircuit *, Ndata *, double *); extern int BSIM3v1unsetup(GENmodel *, CKTcircuit *); - #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int BSIM3v1bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM3v1bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM3v1bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM3v1nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3v1/bsim3v1init.c b/src/spicelib/devices/bsim3v1/bsim3v1init.c index d60cb4fb4..c938325d8 100644 --- a/src/spicelib/devices/bsim3v1/bsim3v1init.c +++ b/src/spicelib/devices/bsim3v1/bsim3v1init.c @@ -71,12 +71,17 @@ SPICEdev BSIM3v1info = { #endif /* DEVinstSize */ &BSIM3v1iSize, /* DEVmodSize */ &BSIM3v1mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ BSIM3v1bindCSC, /* DEVbindCSCComplex */ BSIM3v1bindCSCComplex, /* DEVbindCSCComplexToReal */ BSIM3v1bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ BSIM3v1nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim3v32/Makefile.am b/src/spicelib/devices/bsim3v32/Makefile.am index 0bc8be73f..8a8bba422 100644 --- a/src/spicelib/devices/bsim3v32/Makefile.am +++ b/src/spicelib/devices/bsim3v32/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim3v32_la_SOURCES += b3v32bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim3v32_la_SOURCES += b3v32node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim3v32/b3v32.c b/src/spicelib/devices/bsim3v32/b3v32.c index 2ab53bf2e..b2d17ba94 100644 --- a/src/spicelib/devices/bsim3v32/b3v32.c +++ b/src/spicelib/devices/bsim3v32/b3v32.c @@ -26,6 +26,7 @@ IOP( "nrd", BSIM3v32_NRD, IF_REAL , "Number of squares in drain"), IOP( "nrs", BSIM3v32_NRS, IF_REAL , "Number of squares in source"), IOP( "off", BSIM3v32_OFF, IF_FLAG , "Device is initially off"), IOP( "nqsmod", BSIM3v32_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"), +IOP( "geo", BSIM3v32_GEO, IF_INTEGER, "ACM model drain/source connection"), IOP( "delvto", BSIM3v32_DELVTO, IF_REAL , "Zero bias threshold voltage variation"), IOP( "mulu0", BSIM3v32_MULU0, IF_REAL , "Low field mobility multiplier"), IP( "ic", BSIM3v32_IC, IF_REALVEC , "Vector of DS,GS,BS initial voltages"), @@ -65,7 +66,9 @@ IFparm BSIM3v32mPTable[] = { /* model parameters */ IOP( "capmod", BSIM3v32_MOD_CAPMOD, IF_INTEGER, "Capacitance model selector"), IOP( "mobmod", BSIM3v32_MOD_MOBMOD, IF_INTEGER, "Mobility model selector"), IOP( "noimod", BSIM3v32_MOD_NOIMOD, IF_INTEGER, "Noise model selector"), +IOP( "nqsmod", BSIM3v32_MOD_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"), IOP( "acm", BSIM3v32_MOD_ACMMOD, IF_INTEGER, "Area calculation method selector"), +IOP( "calcacm", BSIM3v32_MOD_CALCACM, IF_INTEGER, "Area calculation method ACM=12"), IOP( "paramchk", BSIM3v32_MOD_PARAMCHK, IF_INTEGER, "Model parameter checking selector"), IOP( "binunit", BSIM3v32_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"), IOP( "version", BSIM3v32_MOD_VERSION, IF_STRING, " parameter for model version"), @@ -73,15 +76,15 @@ IOP( "tox", BSIM3v32_MOD_TOX, IF_REAL, "Gate oxide thickness in meters"), IOP( "toxm", BSIM3v32_MOD_TOXM, IF_REAL, "Gate oxide thickness used in extraction"), IOP( "cdsc", BSIM3v32_MOD_CDSC, IF_REAL, "Drain/Source and channel coupling capacitance"), -IOP( "cdscb", BSIM3v32_MOD_CDSCB, IF_REAL, "Body-bias dependence of cdsc"), -IOP( "cdscd", BSIM3v32_MOD_CDSCD, IF_REAL, "Drain-bias dependence of cdsc"), +IOP( "cdscb", BSIM3v32_MOD_CDSCB, IF_REAL, "Body-bias dependence of cdsc"), +IOP( "cdscd", BSIM3v32_MOD_CDSCD, IF_REAL, "Drain-bias dependence of cdsc"), IOP( "cit", BSIM3v32_MOD_CIT, IF_REAL, "Interface state capacitance"), IOP( "nfactor", BSIM3v32_MOD_NFACTOR, IF_REAL, "Subthreshold swing Coefficient"), IOP( "xj", BSIM3v32_MOD_XJ, IF_REAL, "Junction depth in meters"), IOP( "vsat", BSIM3v32_MOD_VSAT, IF_REAL, "Saturation velocity at tnom"), IOP( "at", BSIM3v32_MOD_AT, IF_REAL, "Temperature coefficient of vsat"), -IOP( "a0", BSIM3v32_MOD_A0, IF_REAL, "Non-uniform depletion width effect coefficient."), -IOP( "ags", BSIM3v32_MOD_AGS, IF_REAL, "Gate bias coefficient of Abulk."), +IOP( "a0", BSIM3v32_MOD_A0, IF_REAL, "Non-uniform depletion width effect coefficient."), +IOP( "ags", BSIM3v32_MOD_AGS, IF_REAL, "Gate bias coefficient of Abulk."), IOP( "a1", BSIM3v32_MOD_A1, IF_REAL, "Non-saturation effect coefficient"), IOP( "a2", BSIM3v32_MOD_A2, IF_REAL, "Non-saturation effect coefficient"), IOP( "keta", BSIM3v32_MOD_KETA, IF_REAL, "Body-bias coefficient of non-uniform depletion width effect."), @@ -130,21 +133,21 @@ IOP( "xpart", BSIM3v32_MOD_XPART, IF_REAL, "Channel charge partitioning"), IOP( "elm", BSIM3v32_MOD_ELM, IF_REAL, "Non-quasi-static Elmore Constant Parameter"), IOP( "delta", BSIM3v32_MOD_DELTA, IF_REAL, "Effective Vds parameter"), IOP( "rsh", BSIM3v32_MOD_RSH, IF_REAL, "Source-drain sheet resistance"), -IOP( "rdsw", BSIM3v32_MOD_RDSW, IF_REAL, "Source-drain resistance per width"), +IOP( "rdsw", BSIM3v32_MOD_RDSW, IF_REAL, "Source-drain resistance per width"), -IOP( "prwg", BSIM3v32_MOD_PRWG, IF_REAL, "Gate-bias effect on parasitic resistance "), -IOP( "prwb", BSIM3v32_MOD_PRWB, IF_REAL, "Body-effect on parasitic resistance "), +IOP( "prwg", BSIM3v32_MOD_PRWG, IF_REAL, "Gate-bias effect on parasitic resistance "), +IOP( "prwb", BSIM3v32_MOD_PRWB, IF_REAL, "Body-effect on parasitic resistance "), -IOP( "prt", BSIM3v32_MOD_PRT, IF_REAL, "Temperature coefficient of parasitic resistance "), +IOP( "prt", BSIM3v32_MOD_PRT, IF_REAL, "Temperature coefficient of parasitic resistance "), IOP( "eta0", BSIM3v32_MOD_ETA0, IF_REAL, "Subthreshold region DIBL coefficient"), IOP( "etab", BSIM3v32_MOD_ETAB, IF_REAL, "Subthreshold region DIBL coefficient"), IOP( "pclm", BSIM3v32_MOD_PCLM, IF_REAL, "Channel length modulation Coefficient"), -IOP( "pdiblc1", BSIM3v32_MOD_PDIBL1, IF_REAL, "Drain-induced barrier lowering coefficient"), -IOP( "pdiblc2", BSIM3v32_MOD_PDIBL2, IF_REAL, "Drain-induced barrier lowering coefficient"), -IOP( "pdiblcb", BSIM3v32_MOD_PDIBLB, IF_REAL, "Body-effect on drain-induced barrier lowering"), -IOP( "pscbe1", BSIM3v32_MOD_PSCBE1, IF_REAL, "Substrate current body-effect coefficient"), -IOP( "pscbe2", BSIM3v32_MOD_PSCBE2, IF_REAL, "Substrate current body-effect coefficient"), -IOP( "pvag", BSIM3v32_MOD_PVAG, IF_REAL, "Gate dependence of output resistance parameter"), +IOP( "pdiblc1", BSIM3v32_MOD_PDIBL1, IF_REAL, "Drain-induced barrier lowering coefficient"), +IOP( "pdiblc2", BSIM3v32_MOD_PDIBL2, IF_REAL, "Drain-induced barrier lowering coefficient"), +IOP( "pdiblcb", BSIM3v32_MOD_PDIBLB, IF_REAL, "Body-effect on drain-induced barrier lowering"), +IOP( "pscbe1", BSIM3v32_MOD_PSCBE1, IF_REAL, "Substrate current body-effect coefficient"), +IOP( "pscbe2", BSIM3v32_MOD_PSCBE2, IF_REAL, "Substrate current body-effect coefficient"), +IOP( "pvag", BSIM3v32_MOD_PVAG, IF_REAL, "Gate dependence of output resistance parameter"), IOP( "js", BSIM3v32_MOD_JS, IF_REAL, "Source/drain junction reverse saturation current density"), IOP( "jsw", BSIM3v32_MOD_JSW, IF_REAL, "Sidewall junction reverse saturation current density"), IOP( "pb", BSIM3v32_MOD_PB, IF_REAL, "Source/drain junction built-in potential"), @@ -218,8 +221,9 @@ IOP( "ldif", BSIM3v32_MOD_LDIF, IF_REAL, "ACM Parameter: Length of LDD Gate-Sour IOP( "ld", BSIM3v32_MOD_LD, IF_REAL, "ACM Parameter: Length of LDD under Gate"), IOP( "rd", BSIM3v32_MOD_RD, IF_REAL, "ACM Parameter: Resistance of LDD drain side"), IOP( "rs", BSIM3v32_MOD_RS, IF_REAL, "ACM Parameter: Resistance of LDD source side"), -IOP( "rdc", BSIM3v32_MOD_RS, IF_REAL, "ACM Parameter: Resistance contact drain side"), -IOP( "rsc", BSIM3v32_MOD_RS, IF_REAL, "ACM Parameter: Resistance contact source side"), +IOP( "rdc", BSIM3v32_MOD_RDC, IF_REAL, "ACM Parameter: Resistance contact drain side"), +IOP( "rsc", BSIM3v32_MOD_RSC, IF_REAL, "ACM Parameter: Resistance contact source side"), +IOP( "wmlt", BSIM3v32_MOD_WMLT, IF_REAL, "ACM Parameter: Width shrink factor"), IOP( "alpha0", BSIM3v32_MOD_ALPHA0, IF_REAL, "substrate current model parameter"), IOP( "alpha1", BSIM3v32_MOD_ALPHA1, IF_REAL, "substrate current model parameter"), @@ -234,8 +238,8 @@ IOP( "lnfactor", BSIM3v32_MOD_LNFACTOR, IF_REAL, "Length dependence of nfactor") IOP( "lxj", BSIM3v32_MOD_LXJ, IF_REAL, "Length dependence of xj"), IOP( "lvsat", BSIM3v32_MOD_LVSAT, IF_REAL, "Length dependence of vsat"), IOP( "lat", BSIM3v32_MOD_LAT, IF_REAL, "Length dependence of at"), -IOP( "la0", BSIM3v32_MOD_LA0, IF_REAL, "Length dependence of a0"), -IOP( "lags", BSIM3v32_MOD_LAGS, IF_REAL, "Length dependence of ags"), +IOP( "la0", BSIM3v32_MOD_LA0, IF_REAL, "Length dependence of a0"), +IOP( "lags", BSIM3v32_MOD_LAGS, IF_REAL, "Length dependence of ags"), IOP( "la1", BSIM3v32_MOD_LA1, IF_REAL, "Length dependence of a1"), IOP( "la2", BSIM3v32_MOD_LA2, IF_REAL, "Length dependence of a2"), IOP( "lketa", BSIM3v32_MOD_LKETA, IF_REAL, "Length dependence of keta"), @@ -277,21 +281,21 @@ IOP( "lute", BSIM3v32_MOD_LUTE, IF_REAL, "Length dependence of ute"), IOP( "lvoff", BSIM3v32_MOD_LVOFF, IF_REAL, "Length dependence of voff"), IOP( "lelm", BSIM3v32_MOD_LELM, IF_REAL, "Length dependence of elm"), IOP( "ldelta", BSIM3v32_MOD_LDELTA, IF_REAL, "Length dependence of delta"), -IOP( "lrdsw", BSIM3v32_MOD_LRDSW, IF_REAL, "Length dependence of rdsw "), +IOP( "lrdsw", BSIM3v32_MOD_LRDSW, IF_REAL, "Length dependence of rdsw "), -IOP( "lprwg", BSIM3v32_MOD_LPRWG, IF_REAL, "Length dependence of prwg "), -IOP( "lprwb", BSIM3v32_MOD_LPRWB, IF_REAL, "Length dependence of prwb "), +IOP( "lprwg", BSIM3v32_MOD_LPRWG, IF_REAL, "Length dependence of prwg "), +IOP( "lprwb", BSIM3v32_MOD_LPRWB, IF_REAL, "Length dependence of prwb "), -IOP( "lprt", BSIM3v32_MOD_LPRT, IF_REAL, "Length dependence of prt "), -IOP( "leta0", BSIM3v32_MOD_LETA0, IF_REAL, "Length dependence of eta0"), -IOP( "letab", BSIM3v32_MOD_LETAB, IF_REAL, "Length dependence of etab"), -IOP( "lpclm", BSIM3v32_MOD_LPCLM, IF_REAL, "Length dependence of pclm"), -IOP( "lpdiblc1", BSIM3v32_MOD_LPDIBL1, IF_REAL, "Length dependence of pdiblc1"), -IOP( "lpdiblc2", BSIM3v32_MOD_LPDIBL2, IF_REAL, "Length dependence of pdiblc2"), -IOP( "lpdiblcb", BSIM3v32_MOD_LPDIBLB, IF_REAL, "Length dependence of pdiblcb"), -IOP( "lpscbe1", BSIM3v32_MOD_LPSCBE1, IF_REAL, "Length dependence of pscbe1"), -IOP( "lpscbe2", BSIM3v32_MOD_LPSCBE2, IF_REAL, "Length dependence of pscbe2"), -IOP( "lpvag", BSIM3v32_MOD_LPVAG, IF_REAL, "Length dependence of pvag"), +IOP( "lprt", BSIM3v32_MOD_LPRT, IF_REAL, "Length dependence of prt "), +IOP( "leta0", BSIM3v32_MOD_LETA0, IF_REAL, "Length dependence of eta0"), +IOP( "letab", BSIM3v32_MOD_LETAB, IF_REAL, "Length dependence of etab"), +IOP( "lpclm", BSIM3v32_MOD_LPCLM, IF_REAL, "Length dependence of pclm"), +IOP( "lpdiblc1", BSIM3v32_MOD_LPDIBL1, IF_REAL, "Length dependence of pdiblc1"), +IOP( "lpdiblc2", BSIM3v32_MOD_LPDIBL2, IF_REAL, "Length dependence of pdiblc2"), +IOP( "lpdiblcb", BSIM3v32_MOD_LPDIBLB, IF_REAL, "Length dependence of pdiblcb"), +IOP( "lpscbe1", BSIM3v32_MOD_LPSCBE1, IF_REAL, "Length dependence of pscbe1"), +IOP( "lpscbe2", BSIM3v32_MOD_LPSCBE2, IF_REAL, "Length dependence of pscbe2"), +IOP( "lpvag", BSIM3v32_MOD_LPVAG, IF_REAL, "Length dependence of pvag"), IOP( "lwr", BSIM3v32_MOD_LWR, IF_REAL, "Length dependence of wr"), IOP( "ldwg", BSIM3v32_MOD_LDWG, IF_REAL, "Length dependence of dwg"), IOP( "ldwb", BSIM3v32_MOD_LDWB, IF_REAL, "Length dependence of dwb"), @@ -313,15 +317,15 @@ IOP( "lmoin", BSIM3v32_MOD_LMOIN, IF_REAL, "Length dependence of moin"), IOP( "lnoff", BSIM3v32_MOD_LNOFF, IF_REAL, "Length dependence of noff"), IOP( "lvoffcv", BSIM3v32_MOD_LVOFFCV, IF_REAL, "Length dependence of voffcv"), IOP( "wcdsc", BSIM3v32_MOD_WCDSC, IF_REAL, "Width dependence of cdsc"), -IOP( "wcdscb", BSIM3v32_MOD_WCDSCB, IF_REAL, "Width dependence of cdscb"), -IOP( "wcdscd", BSIM3v32_MOD_WCDSCD, IF_REAL, "Width dependence of cdscd"), +IOP( "wcdscb", BSIM3v32_MOD_WCDSCB, IF_REAL, "Width dependence of cdscb"), +IOP( "wcdscd", BSIM3v32_MOD_WCDSCD, IF_REAL, "Width dependence of cdscd"), IOP( "wcit", BSIM3v32_MOD_WCIT, IF_REAL, "Width dependence of cit"), IOP( "wnfactor", BSIM3v32_MOD_WNFACTOR, IF_REAL, "Width dependence of nfactor"), IOP( "wxj", BSIM3v32_MOD_WXJ, IF_REAL, "Width dependence of xj"), IOP( "wvsat", BSIM3v32_MOD_WVSAT, IF_REAL, "Width dependence of vsat"), IOP( "wat", BSIM3v32_MOD_WAT, IF_REAL, "Width dependence of at"), -IOP( "wa0", BSIM3v32_MOD_WA0, IF_REAL, "Width dependence of a0"), -IOP( "wags", BSIM3v32_MOD_WAGS, IF_REAL, "Width dependence of ags"), +IOP( "wa0", BSIM3v32_MOD_WA0, IF_REAL, "Width dependence of a0"), +IOP( "wags", BSIM3v32_MOD_WAGS, IF_REAL, "Width dependence of ags"), IOP( "wa1", BSIM3v32_MOD_WA1, IF_REAL, "Width dependence of a1"), IOP( "wa2", BSIM3v32_MOD_WA2, IF_REAL, "Width dependence of a2"), IOP( "wketa", BSIM3v32_MOD_WKETA, IF_REAL, "Width dependence of keta"), @@ -369,15 +373,15 @@ IOP( "wprwg", BSIM3v32_MOD_WPRWG, IF_REAL, "Width dependence of prwg "), IOP( "wprwb", BSIM3v32_MOD_WPRWB, IF_REAL, "Width dependence of prwb "), IOP( "wprt", BSIM3v32_MOD_WPRT, IF_REAL, "Width dependence of prt"), -IOP( "weta0", BSIM3v32_MOD_WETA0, IF_REAL, "Width dependence of eta0"), -IOP( "wetab", BSIM3v32_MOD_WETAB, IF_REAL, "Width dependence of etab"), -IOP( "wpclm", BSIM3v32_MOD_WPCLM, IF_REAL, "Width dependence of pclm"), -IOP( "wpdiblc1", BSIM3v32_MOD_WPDIBL1, IF_REAL, "Width dependence of pdiblc1"), -IOP( "wpdiblc2", BSIM3v32_MOD_WPDIBL2, IF_REAL, "Width dependence of pdiblc2"), -IOP( "wpdiblcb", BSIM3v32_MOD_WPDIBLB, IF_REAL, "Width dependence of pdiblcb"), -IOP( "wpscbe1", BSIM3v32_MOD_WPSCBE1, IF_REAL, "Width dependence of pscbe1"), -IOP( "wpscbe2", BSIM3v32_MOD_WPSCBE2, IF_REAL, "Width dependence of pscbe2"), -IOP( "wpvag", BSIM3v32_MOD_WPVAG, IF_REAL, "Width dependence of pvag"), +IOP( "weta0", BSIM3v32_MOD_WETA0, IF_REAL, "Width dependence of eta0"), +IOP( "wetab", BSIM3v32_MOD_WETAB, IF_REAL, "Width dependence of etab"), +IOP( "wpclm", BSIM3v32_MOD_WPCLM, IF_REAL, "Width dependence of pclm"), +IOP( "wpdiblc1", BSIM3v32_MOD_WPDIBL1, IF_REAL, "Width dependence of pdiblc1"), +IOP( "wpdiblc2", BSIM3v32_MOD_WPDIBL2, IF_REAL, "Width dependence of pdiblc2"), +IOP( "wpdiblcb", BSIM3v32_MOD_WPDIBLB, IF_REAL, "Width dependence of pdiblcb"), +IOP( "wpscbe1", BSIM3v32_MOD_WPSCBE1, IF_REAL, "Width dependence of pscbe1"), +IOP( "wpscbe2", BSIM3v32_MOD_WPSCBE2, IF_REAL, "Width dependence of pscbe2"), +IOP( "wpvag", BSIM3v32_MOD_WPVAG, IF_REAL, "Width dependence of pvag"), IOP( "wwr", BSIM3v32_MOD_WWR, IF_REAL, "Width dependence of wr"), IOP( "wdwg", BSIM3v32_MOD_WDWG, IF_REAL, "Width dependence of dwg"), IOP( "wdwb", BSIM3v32_MOD_WDWB, IF_REAL, "Width dependence of dwb"), @@ -400,14 +404,14 @@ IOP( "wnoff", BSIM3v32_MOD_WNOFF, IF_REAL, "Width dependence of noff"), IOP( "wvoffcv", BSIM3v32_MOD_WVOFFCV, IF_REAL, "Width dependence of voffcv"), IOP( "pcdsc", BSIM3v32_MOD_PCDSC, IF_REAL, "Cross-term dependence of cdsc"), -IOP( "pcdscb", BSIM3v32_MOD_PCDSCB, IF_REAL, "Cross-term dependence of cdscb"), +IOP( "pcdscb", BSIM3v32_MOD_PCDSCB, IF_REAL, "Cross-term dependence of cdscb"), IOP( "pcdscd", BSIM3v32_MOD_PCDSCD, IF_REAL, "Cross-term dependence of cdscd"), IOP( "pcit", BSIM3v32_MOD_PCIT, IF_REAL, "Cross-term dependence of cit"), IOP( "pnfactor", BSIM3v32_MOD_PNFACTOR, IF_REAL, "Cross-term dependence of nfactor"), IOP( "pxj", BSIM3v32_MOD_PXJ, IF_REAL, "Cross-term dependence of xj"), IOP( "pvsat", BSIM3v32_MOD_PVSAT, IF_REAL, "Cross-term dependence of vsat"), IOP( "pat", BSIM3v32_MOD_PAT, IF_REAL, "Cross-term dependence of at"), -IOP( "pa0", BSIM3v32_MOD_PA0, IF_REAL, "Cross-term dependence of a0"), +IOP( "pa0", BSIM3v32_MOD_PA0, IF_REAL, "Cross-term dependence of a0"), IOP( "pags", BSIM3v32_MOD_PAGS, IF_REAL, "Cross-term dependence of ags"), IOP( "pa1", BSIM3v32_MOD_PA1, IF_REAL, "Cross-term dependence of a1"), IOP( "pa2", BSIM3v32_MOD_PA2, IF_REAL, "Cross-term dependence of a2"), @@ -450,10 +454,10 @@ IOP( "pute", BSIM3v32_MOD_PUTE, IF_REAL, "Cross-term dependence of ute"), IOP( "pvoff", BSIM3v32_MOD_PVOFF, IF_REAL, "Cross-term dependence of voff"), IOP( "pelm", BSIM3v32_MOD_PELM, IF_REAL, "Cross-term dependence of elm"), IOP( "pdelta", BSIM3v32_MOD_PDELTA, IF_REAL, "Cross-term dependence of delta"), -IOP( "prdsw", BSIM3v32_MOD_PRDSW, IF_REAL, "Cross-term dependence of rdsw "), +IOP( "prdsw", BSIM3v32_MOD_PRDSW, IF_REAL, "Cross-term dependence of rdsw "), -IOP( "pprwg", BSIM3v32_MOD_PPRWG, IF_REAL, "Cross-term dependence of prwg "), -IOP( "pprwb", BSIM3v32_MOD_PPRWB, IF_REAL, "Cross-term dependence of prwb "), +IOP( "pprwg", BSIM3v32_MOD_PPRWG, IF_REAL, "Cross-term dependence of prwg "), +IOP( "pprwb", BSIM3v32_MOD_PPRWB, IF_REAL, "Cross-term dependence of prwb "), IOP( "pprt", BSIM3v32_MOD_PPRT, IF_REAL, "Cross-term dependence of prt "), IOP( "peta0", BSIM3v32_MOD_PETA0, IF_REAL, "Cross-term dependence of eta0"), @@ -464,7 +468,7 @@ IOP( "ppdiblc2", BSIM3v32_MOD_PPDIBL2, IF_REAL, "Cross-term dependence of pdiblc IOP( "ppdiblcb", BSIM3v32_MOD_PPDIBLB, IF_REAL, "Cross-term dependence of pdiblcb"), IOP( "ppscbe1", BSIM3v32_MOD_PPSCBE1, IF_REAL, "Cross-term dependence of pscbe1"), IOP( "ppscbe2", BSIM3v32_MOD_PPSCBE2, IF_REAL, "Cross-term dependence of pscbe2"), -IOP( "ppvag", BSIM3v32_MOD_PPVAG, IF_REAL, "Cross-term dependence of pvag"), +IOP( "ppvag", BSIM3v32_MOD_PPVAG, IF_REAL, "Cross-term dependence of pvag"), IOP( "pwr", BSIM3v32_MOD_PWR, IF_REAL, "Cross-term dependence of wr"), IOP( "pdwg", BSIM3v32_MOD_PDWG, IF_REAL, "Cross-term dependence of dwg"), IOP( "pdwb", BSIM3v32_MOD_PDWB, IF_REAL, "Cross-term dependence of dwb"), @@ -506,11 +510,11 @@ char *BSIM3v32names[] = { "Charge" }; -int BSIM3v32nSize = NUMELEMS(BSIM3v32names); -int BSIM3v32pTSize = NUMELEMS(BSIM3v32pTable); -int BSIM3v32mPTSize = NUMELEMS(BSIM3v32mPTable); -int BSIM3v32iSize = sizeof(BSIM3v32instance); -int BSIM3v32mSize = sizeof(BSIM3v32model); +int BSIM3v32nSize = NUMELEMS(BSIM3v32names); +int BSIM3v32pTSize = NUMELEMS(BSIM3v32pTable); +int BSIM3v32mPTSize = NUMELEMS(BSIM3v32mPTable); +int BSIM3v32iSize = sizeof(BSIM3v32instance); +int BSIM3v32mSize = sizeof(BSIM3v32model); diff --git a/src/spicelib/devices/bsim3v32/b3v32acld.c b/src/spicelib/devices/bsim3v32/b3v32acld.c index 28992b5f3..e7870a4e5 100644 --- a/src/spicelib/devices/bsim3v32/b3v32acld.c +++ b/src/spicelib/devices/bsim3v32/b3v32acld.c @@ -36,12 +36,12 @@ double ScalingFactor = 1.0e-9; double m; omega = ckt->CKTomega; - for (; model != NULL; model = model->BSIM3v32nextModel) + for (; model != NULL; model = model->BSIM3v32nextModel) { for (here = model->BSIM3v32instances; here!= NULL; - here = here->BSIM3v32nextInstance) - { - if (here->BSIM3v32mode >= 0) - { Gm = here->BSIM3v32gm; + here = here->BSIM3v32nextInstance) + { + if (here->BSIM3v32mode >= 0) + { Gm = here->BSIM3v32gm; Gmbs = here->BSIM3v32gmbs; FwdSum = Gm + Gmbs; RevSum = 0.0; @@ -59,7 +59,7 @@ double m; gbspb = 0.0; gbspsp = 0.0; - if (here->BSIM3v32nqsMod == 0) + if (here->BSIM3v32nqsMod == 0) { cggb = here->BSIM3v32cggb; cgsb = here->BSIM3v32cgsb; cgdb = here->BSIM3v32cgdb; @@ -73,70 +73,70 @@ double m; cddb = here->BSIM3v32cddb; xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.6; + sxpart = 0.6; dxpart = 0.4; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } else { cggb = cgdb = cgsb = 0.0; cbgb = cbdb = cbsb = 0.0; cdgb = cddb = cdsb = 0.0; - xgtg = here->BSIM3v32gtg; + xgtg = here->BSIM3v32gtg; xgtd = here->BSIM3v32gtd; xgts = here->BSIM3v32gts; - xgtb = here->BSIM3v32gtb; - + xgtb = here->BSIM3v32gtb; + xcqgb = here->BSIM3v32cqgb * omega; xcqdb = here->BSIM3v32cqdb * omega; xcqsb = here->BSIM3v32cqsb * omega; xcqbb = here->BSIM3v32cqbb * omega; - CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV * here->pParam->BSIM3v32leffCV; - qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { dxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { dxpart = 0.0; - } - else - { dxpart = 0.5; - } - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - } - else - { dxpart = here->BSIM3v32qdrn / qcheq; - Cdd = here->BSIM3v32cddb; - Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; - Cdg = here->BSIM3v32cdgb; - Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = here->BSIM3v32qdrn / qcheq; + Cdd = here->BSIM3v32cddb; + Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3v32cdgb; + Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; - Cds = here->BSIM3v32cdsb; - Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + Cds = here->BSIM3v32cdsb; + Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg - + ddxpart_dVs); - } - sxpart = 1.0 - dxpart; - dsxpart_dVd = -ddxpart_dVd; - dsxpart_dVg = -ddxpart_dVg; - dsxpart_dVs = -ddxpart_dVs; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); } - } + } else { Gm = -here->BSIM3v32gm; Gmbs = -here->BSIM3v32gmbs; @@ -156,7 +156,7 @@ double m; gbspb = here->BSIM3v32gbbs; gbspdp = -(gbspg + gbspsp + gbspb); - if (here->BSIM3v32nqsMod == 0) + if (here->BSIM3v32nqsMod == 0) { cggb = here->BSIM3v32cggb; cgsb = here->BSIM3v32cgdb; cgdb = here->BSIM3v32cgsb; @@ -170,19 +170,19 @@ double m; cddb = -(here->BSIM3v32cdsb + cgdb + cbdb); xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.4; + sxpart = 0.4; dxpart = 0.6; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; } else { cggb = cgdb = cgsb = 0.0; cbgb = cbdb = cbsb = 0.0; cdgb = cddb = cdsb = 0.0; - xgtg = here->BSIM3v32gtg; + xgtg = here->BSIM3v32gtg; xgtd = here->BSIM3v32gts; xgts = here->BSIM3v32gtd; xgtb = here->BSIM3v32gtb; @@ -192,50 +192,50 @@ double m; xcqsb = here->BSIM3v32cqdb * omega; xcqbb = here->BSIM3v32cqbb * omega; - CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV * here->pParam->BSIM3v32leffCV; - qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { sxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { sxpart = 0.0; - } - else - { sxpart = 0.5; - } - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { sxpart = here->BSIM3v32qdrn / qcheq; - Css = here->BSIM3v32cddb; - Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; - Csg = here->BSIM3v32cdgb; - Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = here->BSIM3v32qdrn / qcheq; + Css = here->BSIM3v32cddb; + Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3v32cdgb; + Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; - Csd = here->BSIM3v32cdsb; - Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + Csd = here->BSIM3v32cdsb; + Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg - + dsxpart_dVs); - } - dxpart = 1.0 - sxpart; - ddxpart_dVd = -dsxpart_dVd; - ddxpart_dVg = -dsxpart_dVg; - ddxpart_dVs = -dsxpart_dVs; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); } } - T1 = *(ckt->CKTstate0 + here->BSIM3v32qdef) * here->BSIM3v32gtau; + T1 = *(ckt->CKTstate0 + here->BSIM3v32qdef) * here->BSIM3v32gtau; gdpr = here->BSIM3v32drainConductance; gspr = here->BSIM3v32sourceConductance; gds = here->BSIM3v32gds; @@ -244,9 +244,9 @@ double m; capbd = here->BSIM3v32capbd; capbs = here->BSIM3v32capbs; - GSoverlapCap = here->BSIM3v32cgso; - GDoverlapCap = here->BSIM3v32cgdo; - GBoverlapCap = here->pParam->BSIM3v32cgbo; + GSoverlapCap = here->BSIM3v32cgso; + GDoverlapCap = here->BSIM3v32cgdo; + GBoverlapCap = here->pParam->BSIM3v32cgbo; xcdgb = (cdgb - GDoverlapCap) * omega; xcddb = (cddb + capbd + GDoverlapCap) * omega; @@ -255,106 +255,106 @@ double m; xcsdb = -(cgdb + cbdb + cddb) * omega; xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)) * omega; xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap) - * omega; + * omega; xcgdb = (cgdb - GDoverlapCap ) * omega; xcgsb = (cgsb - GSoverlapCap) * omega; xcbgb = (cbgb - GBoverlapCap) * omega; xcbdb = (cbdb - capbd ) * omega; xcbsb = (cbsb - capbs ) * omega; - m = here->BSIM3v32m; + m = here->BSIM3v32m; - *(here->BSIM3v32GgPtr + 1) += m * xcggb; - *(here->BSIM3v32BbPtr + 1) -= - m * (xcbgb + xcbdb + xcbsb); - *(here->BSIM3v32DPdpPtr + 1) += m * xcddb; - *(here->BSIM3v32SPspPtr + 1) += m * xcssb; - *(here->BSIM3v32GbPtr + 1) -= - m * (xcggb + xcgdb + xcgsb); - *(here->BSIM3v32GdpPtr + 1) += m * xcgdb; - *(here->BSIM3v32GspPtr + 1) += m * xcgsb; - *(here->BSIM3v32BgPtr + 1) += m * xcbgb; - *(here->BSIM3v32BdpPtr + 1) += m * xcbdb; - *(here->BSIM3v32BspPtr + 1) += m * xcbsb; - *(here->BSIM3v32DPgPtr + 1) += m * xcdgb; - *(here->BSIM3v32DPbPtr + 1) -= - m * (xcdgb + xcddb + xcdsb); - *(here->BSIM3v32DPspPtr + 1) += m * xcdsb; - *(here->BSIM3v32SPgPtr + 1) += m * xcsgb; - *(here->BSIM3v32SPbPtr + 1) -= - m * (xcsgb + xcsdb + xcssb); - *(here->BSIM3v32SPdpPtr + 1) += m * xcsdb; - - *(here->BSIM3v32DdPtr) += m * gdpr; - *(here->BSIM3v32SsPtr) += m * gspr; - *(here->BSIM3v32BbPtr) += - m * (gbd + gbs - here->BSIM3v32gbbs); - *(here->BSIM3v32DPdpPtr) += - m * (gdpr + gds + gbd + RevSum + - dxpart * xgtd + T1 * ddxpart_dVd + - gbdpdp); - *(here->BSIM3v32SPspPtr) += - m * (gspr + gds + gbs + FwdSum + - sxpart * xgts + T1 * dsxpart_dVs + - gbspsp); - - *(here->BSIM3v32DdpPtr) -= m * gdpr; - *(here->BSIM3v32SspPtr) -= m * gspr; - - *(here->BSIM3v32BgPtr) -= m * here->BSIM3v32gbgs; - *(here->BSIM3v32BdpPtr) -= m * (gbd - gbbdp); - *(here->BSIM3v32BspPtr) -= m * (gbs - gbbsp); - - *(here->BSIM3v32DPdPtr) -= m * gdpr; - *(here->BSIM3v32DPgPtr) += - m * (Gm + dxpart * xgtg + T1 * ddxpart_dVg + - gbdpg); - *(here->BSIM3v32DPbPtr) -= - m * (gbd - Gmbs - dxpart * xgtb - - T1 * ddxpart_dVb - gbdpb); - *(here->BSIM3v32DPspPtr) -= - m * (gds + FwdSum - dxpart * xgts - - T1 * ddxpart_dVs - gbdpsp); - - *(here->BSIM3v32SPgPtr) -= - m * (Gm - sxpart * xgtg - T1 * dsxpart_dVg - - gbspg); - *(here->BSIM3v32SPsPtr) -= m * gspr; - *(here->BSIM3v32SPbPtr) -= - m * (gbs + Gmbs - sxpart * xgtb - - T1 * dsxpart_dVb - gbspb); - *(here->BSIM3v32SPdpPtr) -= - m * (gds + RevSum - sxpart * xgtd - - T1 * dsxpart_dVd - gbspdp); - - *(here->BSIM3v32GgPtr) -= m * xgtg; - *(here->BSIM3v32GbPtr) -= m * xgtb; - *(here->BSIM3v32GdpPtr) -= m * xgtd; - *(here->BSIM3v32GspPtr) -= m * xgts; - - if (here->BSIM3v32nqsMod) - { - *(here->BSIM3v32QqPtr + 1) += - m * omega * ScalingFactor; - *(here->BSIM3v32QgPtr + 1) -= m * xcqgb; - *(here->BSIM3v32QdpPtr + 1) -= m * xcqdb; - *(here->BSIM3v32QspPtr + 1) -= m * xcqsb; - *(here->BSIM3v32QbPtr + 1) -= m * xcqbb; - - *(here->BSIM3v32QqPtr) += m * here->BSIM3v32gtau; - - *(here->BSIM3v32DPqPtr) += - m * (dxpart * here->BSIM3v32gtau); - *(here->BSIM3v32SPqPtr) += - m * (sxpart * here->BSIM3v32gtau); - *(here->BSIM3v32GqPtr) -= m * here->BSIM3v32gtau; - - *(here->BSIM3v32QgPtr) += m * xgtg; - *(here->BSIM3v32QdpPtr) += m * xgtd; - *(here->BSIM3v32QspPtr) += m * xgts; - *(here->BSIM3v32QbPtr) += m * xgtb; - } - } + *(here->BSIM3v32GgPtr + 1) += m * xcggb; + *(here->BSIM3v32BbPtr + 1) -= + m * (xcbgb + xcbdb + xcbsb); + *(here->BSIM3v32DPdpPtr + 1) += m * xcddb; + *(here->BSIM3v32SPspPtr + 1) += m * xcssb; + *(here->BSIM3v32GbPtr + 1) -= + m * (xcggb + xcgdb + xcgsb); + *(here->BSIM3v32GdpPtr + 1) += m * xcgdb; + *(here->BSIM3v32GspPtr + 1) += m * xcgsb; + *(here->BSIM3v32BgPtr + 1) += m * xcbgb; + *(here->BSIM3v32BdpPtr + 1) += m * xcbdb; + *(here->BSIM3v32BspPtr + 1) += m * xcbsb; + *(here->BSIM3v32DPgPtr + 1) += m * xcdgb; + *(here->BSIM3v32DPbPtr + 1) -= + m * (xcdgb + xcddb + xcdsb); + *(here->BSIM3v32DPspPtr + 1) += m * xcdsb; + *(here->BSIM3v32SPgPtr + 1) += m * xcsgb; + *(here->BSIM3v32SPbPtr + 1) -= + m * (xcsgb + xcsdb + xcssb); + *(here->BSIM3v32SPdpPtr + 1) += m * xcsdb; + + *(here->BSIM3v32DdPtr) += m * gdpr; + *(here->BSIM3v32SsPtr) += m * gspr; + *(here->BSIM3v32BbPtr) += + m * (gbd + gbs - here->BSIM3v32gbbs); + *(here->BSIM3v32DPdpPtr) += + m * (gdpr + gds + gbd + RevSum + + dxpart * xgtd + T1 * ddxpart_dVd + + gbdpdp); + *(here->BSIM3v32SPspPtr) += + m * (gspr + gds + gbs + FwdSum + + sxpart * xgts + T1 * dsxpart_dVs + + gbspsp); + + *(here->BSIM3v32DdpPtr) -= m * gdpr; + *(here->BSIM3v32SspPtr) -= m * gspr; + + *(here->BSIM3v32BgPtr) -= m * here->BSIM3v32gbgs; + *(here->BSIM3v32BdpPtr) -= m * (gbd - gbbdp); + *(here->BSIM3v32BspPtr) -= m * (gbs - gbbsp); + + *(here->BSIM3v32DPdPtr) -= m * gdpr; + *(here->BSIM3v32DPgPtr) += + m * (Gm + dxpart * xgtg + T1 * ddxpart_dVg + + gbdpg); + *(here->BSIM3v32DPbPtr) -= + m * (gbd - Gmbs - dxpart * xgtb - + T1 * ddxpart_dVb - gbdpb); + *(here->BSIM3v32DPspPtr) -= + m * (gds + FwdSum - dxpart * xgts - + T1 * ddxpart_dVs - gbdpsp); + + *(here->BSIM3v32SPgPtr) -= + m * (Gm - sxpart * xgtg - T1 * dsxpart_dVg - + gbspg); + *(here->BSIM3v32SPsPtr) -= m * gspr; + *(here->BSIM3v32SPbPtr) -= + m * (gbs + Gmbs - sxpart * xgtb - + T1 * dsxpart_dVb - gbspb); + *(here->BSIM3v32SPdpPtr) -= + m * (gds + RevSum - sxpart * xgtd - + T1 * dsxpart_dVd - gbspdp); + + *(here->BSIM3v32GgPtr) -= m * xgtg; + *(here->BSIM3v32GbPtr) -= m * xgtb; + *(here->BSIM3v32GdpPtr) -= m * xgtd; + *(here->BSIM3v32GspPtr) -= m * xgts; + + if (here->BSIM3v32nqsMod) + { + *(here->BSIM3v32QqPtr + 1) += + m * omega * ScalingFactor; + *(here->BSIM3v32QgPtr + 1) -= m * xcqgb; + *(here->BSIM3v32QdpPtr + 1) -= m * xcqdb; + *(here->BSIM3v32QspPtr + 1) -= m * xcqsb; + *(here->BSIM3v32QbPtr + 1) -= m * xcqbb; + + *(here->BSIM3v32QqPtr) += m * here->BSIM3v32gtau; + + *(here->BSIM3v32DPqPtr) += + m * (dxpart * here->BSIM3v32gtau); + *(here->BSIM3v32SPqPtr) += + m * (sxpart * here->BSIM3v32gtau); + *(here->BSIM3v32GqPtr) -= m * here->BSIM3v32gtau; + + *(here->BSIM3v32QgPtr) += m * xgtg; + *(here->BSIM3v32QdpPtr) += m * xgtd; + *(here->BSIM3v32QspPtr) += m * xgts; + *(here->BSIM3v32QbPtr) += m * xgtb; + } + } } return(OK); } diff --git a/src/spicelib/devices/bsim3v32/b3v32ask.c b/src/spicelib/devices/bsim3v32/b3v32ask.c index 27796a9a6..7d405a936 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ask.c +++ b/src/spicelib/devices/bsim3v32/b3v32ask.c @@ -19,22 +19,22 @@ int BSIM3v32ask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, - IFvalue *select) + IFvalue *select) { BSIM3v32instance *here = (BSIM3v32instance*)inst; NG_IGNORE(select); - switch(which) + switch(which) { case BSIM3v32_L: value->rValue = here->BSIM3v32l; return(OK); case BSIM3v32_W: value->rValue = here->BSIM3v32w; return(OK); - case BSIM3v32_M: - value->rValue = here->BSIM3v32m; - return (OK); + case BSIM3v32_M: + value->rValue = here->BSIM3v32m; + return (OK); case BSIM3v32_AS: value->rValue = here->BSIM3v32sourceArea; return(OK); @@ -59,6 +59,9 @@ BSIM3v32instance *here = (BSIM3v32instance*)inst; case BSIM3v32_NQSMOD: value->iValue = here->BSIM3v32nqsMod; return(OK); + case BSIM3v32_GEO: + value->iValue = here->BSIM3v32geo; + return(OK); case BSIM3v32_DELVTO: value->rValue = here->BSIM3v32delvto; return(OK); @@ -94,11 +97,11 @@ BSIM3v32instance *here = (BSIM3v32instance*)inst; return(OK); case BSIM3v32_SOURCECONDUCT: value->rValue = here->BSIM3v32sourceConductance; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_DRAINCONDUCT: value->rValue = here->BSIM3v32drainConductance; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_VBD: value->rValue = *(ckt->CKTstate0 + here->BSIM3v32vbd); @@ -113,118 +116,118 @@ BSIM3v32instance *here = (BSIM3v32instance*)inst; value->rValue = *(ckt->CKTstate0 + here->BSIM3v32vds); return(OK); case BSIM3v32_CD: - value->rValue = here->BSIM3v32cd; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cd; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CBS: - value->rValue = here->BSIM3v32cbs; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cbs; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CBD: - value->rValue = here->BSIM3v32cbd; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cbd; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_GM: - value->rValue = here->BSIM3v32gm; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32gm; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_GDS: - value->rValue = here->BSIM3v32gds; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32gds; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_GMBS: - value->rValue = here->BSIM3v32gmbs; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32gmbs; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_GBD: - value->rValue = here->BSIM3v32gbd; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32gbd; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_GBS: - value->rValue = here->BSIM3v32gbs; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32gbs; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_QB: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qb); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qb); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CQB: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqb); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqb); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_QG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qg); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qg); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CQG: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqg); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqg); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_QD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qd); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qd); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CQD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqd); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32cqd); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CGG: - value->rValue = here->BSIM3v32cggb; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cggb; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CGD: value->rValue = here->BSIM3v32cgdb; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CGS: value->rValue = here->BSIM3v32cgsb; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CDG: - value->rValue = here->BSIM3v32cdgb; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cdgb; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CDD: - value->rValue = here->BSIM3v32cddb; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cddb; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CDS: - value->rValue = here->BSIM3v32cdsb; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32cdsb; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CBG: value->rValue = here->BSIM3v32cbgb; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CBDB: value->rValue = here->BSIM3v32cbdb; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CBSB: value->rValue = here->BSIM3v32cbsb; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CAPBD: - value->rValue = here->BSIM3v32capbd; - value->rValue *= here->BSIM3v32m; + value->rValue = here->BSIM3v32capbd; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_CAPBS: value->rValue = here->BSIM3v32capbs; - value->rValue *= here->BSIM3v32m; + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_VON: - value->rValue = here->BSIM3v32von; + value->rValue = here->BSIM3v32von; return(OK); case BSIM3v32_VDSAT: - value->rValue = here->BSIM3v32vdsat; + value->rValue = here->BSIM3v32vdsat; return(OK); case BSIM3v32_QBS: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qbs); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qbs); + value->rValue *= here->BSIM3v32m; return(OK); case BSIM3v32_QBD: - value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qbd); - value->rValue *= here->BSIM3v32m; + value->rValue = *(ckt->CKTstate0 + here->BSIM3v32qbd); + value->rValue *= here->BSIM3v32m; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/bsim3v32/b3v32check.c b/src/spicelib/devices/bsim3v32/b3v32check.c index 7f85e07a5..86f4fabd0 100644 --- a/src/spicelib/devices/bsim3v32/b3v32check.c +++ b/src/spicelib/devices/bsim3v32/b3v32check.c @@ -28,419 +28,425 @@ FILE *fplog; NG_IGNORE(ckt); - if ((fplog = fopen("b3v3check.log", "w")) != NULL) + if ((fplog = fopen("b3v32check.log", "w")) != NULL) { pParam = here->pParam; - fprintf (fplog, - "BSIM3 Model (Supports: v3.2, v3.2.2, v3.2.3, v3.2.4)\n"); - fprintf (fplog, "Parameter Checking.\n"); - fprintf (fplog, "Model = %s\n", model->BSIM3v32modName); - fprintf (fplog, "W = %g, L = %g, M = %g\n", here->BSIM3v32w, - here->BSIM3v32l, here->BSIM3v32m); + fprintf (fplog, + "BSIM3 Model (Supports: v3.2, v3.2.2, v3.2.3, v3.2.4)\n"); + fprintf (fplog, "Parameter Checking.\n"); + fprintf (fplog, "Model = %s\n", model->BSIM3v32modName); + fprintf (fplog, "W = %g, L = %g, M = %g\n", here->BSIM3v32w, + here->BSIM3v32l, here->BSIM3v32m); - if ((strcmp(model->BSIM3v32version, "3.2.4")) && (strcmp(model->BSIM3v32version, "3.24")) - && (strcmp(model->BSIM3v32version, "3.2.3")) && (strcmp(model->BSIM3v32version, "3.23")) - && (strcmp(model->BSIM3v32version, "3.2.2")) && (strcmp(model->BSIM3v32version, "3.22")) - && (strcmp(model->BSIM3v32version, "3.2")) && (strcmp(model->BSIM3v32version, "3.20"))) - { - fprintf (fplog, - "Warning: This model supports BSIM3v3.2, BSIM3v3.2.2, BSIM3v3.2.3, BSIM3v3.2.4\n"); - fprintf (fplog, - "You specified a wrong version number. Working now with BSIM3v3.2.4.\n"); - printf ("Warning: This model supports BSIM3v3.2, BSIM3v3.2.2, BSIM3v3.2.3, BSIM3v3.2.4\n"); - printf ("You specified a wrong version number. Working now with BSIM3v3.2.4.\n"); - } + if ((strcmp(model->BSIM3v32version, "3.2.4")) && (strcmp(model->BSIM3v32version, "3.24")) + && (strcmp(model->BSIM3v32version, "3.2.3")) && (strcmp(model->BSIM3v32version, "3.23")) + && (strcmp(model->BSIM3v32version, "3.2.2")) && (strcmp(model->BSIM3v32version, "3.22")) + && (strcmp(model->BSIM3v32version, "3.2")) && (strcmp(model->BSIM3v32version, "3.20"))) + { + fprintf (fplog, + "Warning: This model supports BSIM3v3.2, BSIM3v3.2.2, BSIM3v3.2.3, BSIM3v3.2.4\n"); + fprintf (fplog, + "You specified a wrong version number. Working now with BSIM3v3.2.4.\n"); + printf ("Warning: This model supports BSIM3v3.2, BSIM3v3.2.2, BSIM3v3.2.3, BSIM3v3.2.4\n"); + printf ("You specified a wrong version number. Working now with BSIM3v3.2.4.\n"); + } - if (pParam->BSIM3v32nlx < -pParam->BSIM3v32leff) - { fprintf(fplog, "Fatal: Nlx = %g is less than -Leff.\n", - pParam->BSIM3v32nlx); - printf("Fatal: Nlx = %g is less than -Leff.\n", - pParam->BSIM3v32nlx); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32nlx < -pParam->BSIM3v32leff) + { fprintf(fplog, "Fatal: Nlx = %g is less than -Leff.\n", + pParam->BSIM3v32nlx); + printf("Fatal: Nlx = %g is less than -Leff.\n", + pParam->BSIM3v32nlx); + Fatal_Flag = 1; + } - if (model->BSIM3v32tox <= 0.0) - { fprintf(fplog, "Fatal: Tox = %g is not positive.\n", - model->BSIM3v32tox); - printf("Fatal: Tox = %g is not positive.\n", model->BSIM3v32tox); - Fatal_Flag = 1; - } + if (model->BSIM3v32tox <= 0.0) + { fprintf(fplog, "Fatal: Tox = %g is not positive.\n", + model->BSIM3v32tox); + printf("Fatal: Tox = %g is not positive.\n", model->BSIM3v32tox); + Fatal_Flag = 1; + } - if (model->BSIM3v32toxm <= 0.0) - { fprintf(fplog, "Fatal: Toxm = %g is not positive.\n", - model->BSIM3v32toxm); - printf("Fatal: Toxm = %g is not positive.\n", model->BSIM3v32toxm); - Fatal_Flag = 1; - } + if (model->BSIM3v32toxm <= 0.0) + { fprintf(fplog, "Fatal: Toxm = %g is not positive.\n", + model->BSIM3v32toxm); + printf("Fatal: Toxm = %g is not positive.\n", model->BSIM3v32toxm); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32npeak <= 0.0) - { fprintf(fplog, "Fatal: Nch = %g is not positive.\n", - pParam->BSIM3v32npeak); - printf("Fatal: Nch = %g is not positive.\n", - pParam->BSIM3v32npeak); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32nsub <= 0.0) - { fprintf(fplog, "Fatal: Nsub = %g is not positive.\n", - pParam->BSIM3v32nsub); - printf("Fatal: Nsub = %g is not positive.\n", - pParam->BSIM3v32nsub); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32ngate < 0.0) - { fprintf(fplog, "Fatal: Ngate = %g is not positive.\n", - pParam->BSIM3v32ngate); - printf("Fatal: Ngate = %g Ngate is not positive.\n", - pParam->BSIM3v32ngate); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32ngate > 1.e25) - { fprintf(fplog, "Fatal: Ngate = %g is too high.\n", - pParam->BSIM3v32ngate); - printf("Fatal: Ngate = %g Ngate is too high\n", - pParam->BSIM3v32ngate); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32xj <= 0.0) - { fprintf(fplog, "Fatal: Xj = %g is not positive.\n", - pParam->BSIM3v32xj); - printf("Fatal: Xj = %g is not positive.\n", pParam->BSIM3v32xj); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32npeak <= 0.0) + { fprintf(fplog, "Fatal: Nch = %g is not positive.\n", + pParam->BSIM3v32npeak); + printf("Fatal: Nch = %g is not positive.\n", + pParam->BSIM3v32npeak); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32nsub <= 0.0) + { fprintf(fplog, "Fatal: Nsub = %g is not positive.\n", + pParam->BSIM3v32nsub); + printf("Fatal: Nsub = %g is not positive.\n", + pParam->BSIM3v32nsub); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32ngate < 0.0) + { fprintf(fplog, "Fatal: Ngate = %g is not positive.\n", + pParam->BSIM3v32ngate); + printf("Fatal: Ngate = %g Ngate is not positive.\n", + pParam->BSIM3v32ngate); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32ngate > 1.e25) + { fprintf(fplog, "Fatal: Ngate = %g is too high.\n", + pParam->BSIM3v32ngate); + printf("Fatal: Ngate = %g Ngate is too high\n", + pParam->BSIM3v32ngate); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32xj <= 0.0) + { fprintf(fplog, "Fatal: Xj = %g is not positive.\n", + pParam->BSIM3v32xj); + printf("Fatal: Xj = %g is not positive.\n", pParam->BSIM3v32xj); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32dvt1 < 0.0) - { fprintf(fplog, "Fatal: Dvt1 = %g is negative.\n", - pParam->BSIM3v32dvt1); - printf("Fatal: Dvt1 = %g is negative.\n", pParam->BSIM3v32dvt1); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32dvt1 < 0.0) + { fprintf(fplog, "Fatal: Dvt1 = %g is negative.\n", + pParam->BSIM3v32dvt1); + printf("Fatal: Dvt1 = %g is negative.\n", pParam->BSIM3v32dvt1); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32dvt1w < 0.0) - { fprintf(fplog, "Fatal: Dvt1w = %g is negative.\n", - pParam->BSIM3v32dvt1w); - printf("Fatal: Dvt1w = %g is negative.\n", pParam->BSIM3v32dvt1w); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32dvt1w < 0.0) + { fprintf(fplog, "Fatal: Dvt1w = %g is negative.\n", + pParam->BSIM3v32dvt1w); + printf("Fatal: Dvt1w = %g is negative.\n", pParam->BSIM3v32dvt1w); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32w0 == -pParam->BSIM3v32weff) - { fprintf(fplog, "Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); - printf("Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32w0 == -pParam->BSIM3v32weff) + { fprintf(fplog, "Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); + printf("Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32dsub < 0.0) - { fprintf(fplog, "Fatal: Dsub = %g is negative.\n", pParam->BSIM3v32dsub); - printf("Fatal: Dsub = %g is negative.\n", pParam->BSIM3v32dsub); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32b1 == -pParam->BSIM3v32weff) - { fprintf(fplog, "Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); - printf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); - Fatal_Flag = 1; - } - if (pParam->BSIM3v32u0temp <= 0.0) - { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", pParam->BSIM3v32u0temp); - printf("Fatal: u0 at current temperature = %g is not positive.\n", - pParam->BSIM3v32u0temp); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32dsub < 0.0) + { fprintf(fplog, "Fatal: Dsub = %g is negative.\n", pParam->BSIM3v32dsub); + printf("Fatal: Dsub = %g is negative.\n", pParam->BSIM3v32dsub); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32b1 == -pParam->BSIM3v32weff) + { fprintf(fplog, "Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); + printf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); + Fatal_Flag = 1; + } + if (pParam->BSIM3v32u0temp <= 0.0) + { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", pParam->BSIM3v32u0temp); + printf("Fatal: u0 at current temperature = %g is not positive.\n", + pParam->BSIM3v32u0temp); + Fatal_Flag = 1; + } /* Check delta parameter */ - if (pParam->BSIM3v32delta < 0.0) - { fprintf(fplog, "Fatal: Delta = %g is less than zero.\n", - pParam->BSIM3v32delta); - printf("Fatal: Delta = %g is less than zero.\n", pParam->BSIM3v32delta); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32delta < 0.0) + { fprintf(fplog, "Fatal: Delta = %g is less than zero.\n", + pParam->BSIM3v32delta); + printf("Fatal: Delta = %g is less than zero.\n", pParam->BSIM3v32delta); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32vsattemp <= 0.0) - { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", pParam->BSIM3v32vsattemp); - printf("Fatal: Vsat at current temperature = %g is not positive.\n", - pParam->BSIM3v32vsattemp); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32vsattemp <= 0.0) + { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", pParam->BSIM3v32vsattemp); + printf("Fatal: Vsat at current temperature = %g is not positive.\n", + pParam->BSIM3v32vsattemp); + Fatal_Flag = 1; + } /* Check Rout parameters */ - if (pParam->BSIM3v32pclm <= 0.0) - { fprintf(fplog, "Fatal: Pclm = %g is not positive.\n", pParam->BSIM3v32pclm); - printf("Fatal: Pclm = %g is not positive.\n", pParam->BSIM3v32pclm); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32pclm <= 0.0) + { fprintf(fplog, "Fatal: Pclm = %g is not positive.\n", pParam->BSIM3v32pclm); + printf("Fatal: Pclm = %g is not positive.\n", pParam->BSIM3v32pclm); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32drout < 0.0) - { fprintf(fplog, "Fatal: Drout = %g is negative.\n", pParam->BSIM3v32drout); - printf("Fatal: Drout = %g is negative.\n", pParam->BSIM3v32drout); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32drout < 0.0) + { fprintf(fplog, "Fatal: Drout = %g is negative.\n", pParam->BSIM3v32drout); + printf("Fatal: Drout = %g is negative.\n", pParam->BSIM3v32drout); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32pscbe2 <= 0.0) - { fprintf(fplog, "Warning: Pscbe2 = %g is not positive.\n", - pParam->BSIM3v32pscbe2); - printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3v32pscbe2); - } + if (pParam->BSIM3v32pscbe2 <= 0.0) + { fprintf(fplog, "Warning: Pscbe2 = %g is not positive.\n", + pParam->BSIM3v32pscbe2); + printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3v32pscbe2); + } - /* acm model */ - if (model->BSIM3v32acmMod == 0) { - if (model->BSIM3v32unitLengthSidewallJctCap > 0.0 || - model->BSIM3v32unitLengthGateSidewallJctCap > 0.0) - { - if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) - { fprintf(fplog, "Warning: Pd = %g is less than W.\n", - here->BSIM3v32drainPerimeter); - printf("Warning: Pd = %g is less than W.\n", - here->BSIM3v32drainPerimeter); - } - if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) - { fprintf(fplog, "Warning: Ps = %g is less than W.\n", - here->BSIM3v32sourcePerimeter); - printf("Warning: Ps = %g is less than W.\n", - here->BSIM3v32sourcePerimeter); - } - } - } + /* ACM model */ + if (model->BSIM3v32acmMod == 0) { + if (model->BSIM3v32unitLengthSidewallJctCap > 0.0 || + model->BSIM3v32unitLengthGateSidewallJctCap > 0.0) + { + if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) + { fprintf(fplog, "Warning: Pd = %g is less than W.\n", + here->BSIM3v32drainPerimeter); + printf("Warning: Pd = %g is less than W.\n", + here->BSIM3v32drainPerimeter); + } + if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) + { fprintf(fplog, "Warning: Ps = %g is less than W.\n", + here->BSIM3v32sourcePerimeter); + printf("Warning: Ps = %g is less than W.\n", + here->BSIM3v32sourcePerimeter); + } + } + } + if ((model->BSIM3v32calcacm > 0) && (model->BSIM3v32acmMod != 12)) + { fprintf(fplog, "Warning: CALCACM = %d is wrong. Set back to 0.\n", + model->BSIM3v32calcacm); + printf("Warning: CALCACM = %d is wrong. Set back to 0.\n", model->BSIM3v32calcacm); + model->BSIM3v32calcacm = 0; + } - if (pParam->BSIM3v32noff < 0.1) - { fprintf(fplog, "Warning: Noff = %g is too small.\n", - pParam->BSIM3v32noff); - printf("Warning: Noff = %g is too small.\n", pParam->BSIM3v32noff); - } - if (pParam->BSIM3v32noff > 4.0) - { fprintf(fplog, "Warning: Noff = %g is too large.\n", - pParam->BSIM3v32noff); - printf("Warning: Noff = %g is too large.\n", pParam->BSIM3v32noff); - } + if (pParam->BSIM3v32noff < 0.1) + { fprintf(fplog, "Warning: Noff = %g is too small.\n", + pParam->BSIM3v32noff); + printf("Warning: Noff = %g is too small.\n", pParam->BSIM3v32noff); + } + if (pParam->BSIM3v32noff > 4.0) + { fprintf(fplog, "Warning: Noff = %g is too large.\n", + pParam->BSIM3v32noff); + printf("Warning: Noff = %g is too large.\n", pParam->BSIM3v32noff); + } - if (pParam->BSIM3v32voffcv < -0.5) - { fprintf(fplog, "Warning: Voffcv = %g is too small.\n", - pParam->BSIM3v32voffcv); - printf("Warning: Voffcv = %g is too small.\n", pParam->BSIM3v32voffcv); - } - if (pParam->BSIM3v32voffcv > 0.5) - { fprintf(fplog, "Warning: Voffcv = %g is too large.\n", - pParam->BSIM3v32voffcv); - printf("Warning: Voffcv = %g is too large.\n", pParam->BSIM3v32voffcv); - } + if (pParam->BSIM3v32voffcv < -0.5) + { fprintf(fplog, "Warning: Voffcv = %g is too small.\n", + pParam->BSIM3v32voffcv); + printf("Warning: Voffcv = %g is too small.\n", pParam->BSIM3v32voffcv); + } + if (pParam->BSIM3v32voffcv > 0.5) + { fprintf(fplog, "Warning: Voffcv = %g is too large.\n", + pParam->BSIM3v32voffcv); + printf("Warning: Voffcv = %g is too large.\n", pParam->BSIM3v32voffcv); + } - if (model->BSIM3v32ijth < 0.0) - { fprintf(fplog, "Fatal: Ijth = %g cannot be negative.\n", - model->BSIM3v32ijth); - printf("Fatal: Ijth = %g cannot be negative.\n", model->BSIM3v32ijth); - Fatal_Flag = 1; - } + if (model->BSIM3v32ijth < 0.0) + { fprintf(fplog, "Fatal: Ijth = %g cannot be negative.\n", + model->BSIM3v32ijth); + printf("Fatal: Ijth = %g cannot be negative.\n", model->BSIM3v32ijth); + Fatal_Flag = 1; + } /* Check capacitance parameters */ - if (pParam->BSIM3v32clc < 0.0) - { fprintf(fplog, "Fatal: Clc = %g is negative.\n", pParam->BSIM3v32clc); - printf("Fatal: Clc = %g is negative.\n", pParam->BSIM3v32clc); - Fatal_Flag = 1; - } + if (pParam->BSIM3v32clc < 0.0) + { fprintf(fplog, "Fatal: Clc = %g is negative.\n", pParam->BSIM3v32clc); + printf("Fatal: Clc = %g is negative.\n", pParam->BSIM3v32clc); + Fatal_Flag = 1; + } - if (pParam->BSIM3v32moin < 5.0) - { fprintf(fplog, "Warning: Moin = %g is too small.\n", - pParam->BSIM3v32moin); - printf("Warning: Moin = %g is too small.\n", pParam->BSIM3v32moin); - } - if (pParam->BSIM3v32moin > 25.0) - { fprintf(fplog, "Warning: Moin = %g is too large.\n", - pParam->BSIM3v32moin); - printf("Warning: Moin = %g is too large.\n", pParam->BSIM3v32moin); - } + if (pParam->BSIM3v32moin < 5.0) + { fprintf(fplog, "Warning: Moin = %g is too small.\n", + pParam->BSIM3v32moin); + printf("Warning: Moin = %g is too small.\n", pParam->BSIM3v32moin); + } + if (pParam->BSIM3v32moin > 25.0) + { fprintf(fplog, "Warning: Moin = %g is too large.\n", + pParam->BSIM3v32moin); + printf("Warning: Moin = %g is too large.\n", pParam->BSIM3v32moin); + } - if(model->BSIM3v32capMod ==3) { - if (pParam->BSIM3v32acde < 0.4) - { fprintf(fplog, "Warning: Acde = %g is too small.\n", - pParam->BSIM3v32acde); - printf("Warning: Acde = %g is too small.\n", pParam->BSIM3v32acde); - } - if (pParam->BSIM3v32acde > 1.6) - { fprintf(fplog, "Warning: Acde = %g is too large.\n", - pParam->BSIM3v32acde); - printf("Warning: Acde = %g is too large.\n", pParam->BSIM3v32acde); - } - } + if(model->BSIM3v32capMod ==3) { + if (pParam->BSIM3v32acde < 0.4) + { fprintf(fplog, "Warning: Acde = %g is too small.\n", + pParam->BSIM3v32acde); + printf("Warning: Acde = %g is too small.\n", pParam->BSIM3v32acde); + } + if (pParam->BSIM3v32acde > 1.6) + { fprintf(fplog, "Warning: Acde = %g is too large.\n", + pParam->BSIM3v32acde); + printf("Warning: Acde = %g is too large.\n", pParam->BSIM3v32acde); + } + } - if (model->BSIM3v32paramChk ==1) - { -/* Check L and W parameters */ - if (pParam->BSIM3v32leff <= 5.0e-8) - { fprintf(fplog, "Warning: Leff = %g may be too small.\n", - pParam->BSIM3v32leff); - printf("Warning: Leff = %g may be too small.\n", - pParam->BSIM3v32leff); - } + if (model->BSIM3v32paramChk ==1) + { + /* Check L and W parameters */ + if (pParam->BSIM3v32leff <= 5.0e-8) + { fprintf(fplog, "Warning: Leff = %g may be too small.\n", + pParam->BSIM3v32leff); + printf("Warning: Leff = %g may be too small.\n", + pParam->BSIM3v32leff); + } - if (pParam->BSIM3v32leffCV <= 5.0e-8) - { fprintf(fplog, "Warning: Leff for CV = %g may be too small.\n", - pParam->BSIM3v32leffCV); - printf("Warning: Leff for CV = %g may be too small.\n", - pParam->BSIM3v32leffCV); - } + if (pParam->BSIM3v32leffCV <= 5.0e-8) + { fprintf(fplog, "Warning: Leff for CV = %g may be too small.\n", + pParam->BSIM3v32leffCV); + printf("Warning: Leff for CV = %g may be too small.\n", + pParam->BSIM3v32leffCV); + } - if (pParam->BSIM3v32weff <= 1.0e-7) - { fprintf(fplog, "Warning: Weff = %g may be too small.\n", - pParam->BSIM3v32weff); - printf("Warning: Weff = %g may be too small.\n", - pParam->BSIM3v32weff); - } + if (pParam->BSIM3v32weff <= 1.0e-7) + { fprintf(fplog, "Warning: Weff = %g may be too small.\n", + pParam->BSIM3v32weff); + printf("Warning: Weff = %g may be too small.\n", + pParam->BSIM3v32weff); + } - if (pParam->BSIM3v32weffCV <= 1.0e-7) - { fprintf(fplog, "Warning: Weff for CV = %g may be too small.\n", - pParam->BSIM3v32weffCV); - printf("Warning: Weff for CV = %g may be too small.\n", - pParam->BSIM3v32weffCV); - } + if (pParam->BSIM3v32weffCV <= 1.0e-7) + { fprintf(fplog, "Warning: Weff for CV = %g may be too small.\n", + pParam->BSIM3v32weffCV); + printf("Warning: Weff for CV = %g may be too small.\n", + pParam->BSIM3v32weffCV); + } -/* Check threshold voltage parameters */ - if (pParam->BSIM3v32nlx < 0.0) - { fprintf(fplog, "Warning: Nlx = %g is negative.\n", pParam->BSIM3v32nlx); - printf("Warning: Nlx = %g is negative.\n", pParam->BSIM3v32nlx); - } - if (model->BSIM3v32tox < 1.0e-9) - { fprintf(fplog, "Warning: Tox = %g is less than 10A.\n", - model->BSIM3v32tox); - printf("Warning: Tox = %g is less than 10A.\n", model->BSIM3v32tox); - } + /* Check threshold voltage parameters */ + if (pParam->BSIM3v32nlx < 0.0) + { fprintf(fplog, "Warning: Nlx = %g is negative.\n", pParam->BSIM3v32nlx); + printf("Warning: Nlx = %g is negative.\n", pParam->BSIM3v32nlx); + } + if (model->BSIM3v32tox < 1.0e-9) + { fprintf(fplog, "Warning: Tox = %g is less than 10A.\n", + model->BSIM3v32tox); + printf("Warning: Tox = %g is less than 10A.\n", model->BSIM3v32tox); + } - if (pParam->BSIM3v32npeak <= 1.0e15) - { fprintf(fplog, "Warning: Nch = %g may be too small.\n", - pParam->BSIM3v32npeak); - printf("Warning: Nch = %g may be too small.\n", - pParam->BSIM3v32npeak); - } - else if (pParam->BSIM3v32npeak >= 1.0e21) - { fprintf(fplog, "Warning: Nch = %g may be too large.\n", - pParam->BSIM3v32npeak); - printf("Warning: Nch = %g may be too large.\n", - pParam->BSIM3v32npeak); - } + if (pParam->BSIM3v32npeak <= 1.0e15) + { fprintf(fplog, "Warning: Nch = %g may be too small.\n", + pParam->BSIM3v32npeak); + printf("Warning: Nch = %g may be too small.\n", + pParam->BSIM3v32npeak); + } + else if (pParam->BSIM3v32npeak >= 1.0e21) + { fprintf(fplog, "Warning: Nch = %g may be too large.\n", + pParam->BSIM3v32npeak); + printf("Warning: Nch = %g may be too large.\n", + pParam->BSIM3v32npeak); + } - if (pParam->BSIM3v32nsub <= 1.0e14) - { fprintf(fplog, "Warning: Nsub = %g may be too small.\n", - pParam->BSIM3v32nsub); - printf("Warning: Nsub = %g may be too small.\n", - pParam->BSIM3v32nsub); - } - else if (pParam->BSIM3v32nsub >= 1.0e21) - { fprintf(fplog, "Warning: Nsub = %g may be too large.\n", - pParam->BSIM3v32nsub); - printf("Warning: Nsub = %g may be too large.\n", - pParam->BSIM3v32nsub); - } + if (pParam->BSIM3v32nsub <= 1.0e14) + { fprintf(fplog, "Warning: Nsub = %g may be too small.\n", + pParam->BSIM3v32nsub); + printf("Warning: Nsub = %g may be too small.\n", + pParam->BSIM3v32nsub); + } + else if (pParam->BSIM3v32nsub >= 1.0e21) + { fprintf(fplog, "Warning: Nsub = %g may be too large.\n", + pParam->BSIM3v32nsub); + printf("Warning: Nsub = %g may be too large.\n", + pParam->BSIM3v32nsub); + } - if ((pParam->BSIM3v32ngate > 0.0) && - (pParam->BSIM3v32ngate <= 1.e18)) - { fprintf(fplog, "Warning: Ngate = %g is less than 1.E18cm^-3.\n", - pParam->BSIM3v32ngate); - printf("Warning: Ngate = %g is less than 1.E18cm^-3.\n", - pParam->BSIM3v32ngate); - } + if ((pParam->BSIM3v32ngate > 0.0) && + (pParam->BSIM3v32ngate <= 1.e18)) + { fprintf(fplog, "Warning: Ngate = %g is less than 1.E18cm^-3.\n", + pParam->BSIM3v32ngate); + printf("Warning: Ngate = %g is less than 1.E18cm^-3.\n", + pParam->BSIM3v32ngate); + } - if (pParam->BSIM3v32dvt0 < 0.0) - { fprintf(fplog, "Warning: Dvt0 = %g is negative.\n", - pParam->BSIM3v32dvt0); - printf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM3v32dvt0); - } + if (pParam->BSIM3v32dvt0 < 0.0) + { fprintf(fplog, "Warning: Dvt0 = %g is negative.\n", + pParam->BSIM3v32dvt0); + printf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM3v32dvt0); + } - if (fabs(1.0e-6 / (pParam->BSIM3v32w0 + pParam->BSIM3v32weff)) > 10.0) - { fprintf(fplog, "Warning: (W0 + Weff) may be too small.\n"); - printf("Warning: (W0 + Weff) may be too small.\n"); - } + if (fabs(1.0e-6 / (pParam->BSIM3v32w0 + pParam->BSIM3v32weff)) > 10.0) + { fprintf(fplog, "Warning: (W0 + Weff) may be too small.\n"); + printf("Warning: (W0 + Weff) may be too small.\n"); + } -/* Check subthreshold parameters */ - if (pParam->BSIM3v32nfactor < 0.0) - { fprintf(fplog, "Warning: Nfactor = %g is negative.\n", - pParam->BSIM3v32nfactor); - printf("Warning: Nfactor = %g is negative.\n", pParam->BSIM3v32nfactor); - } - if (pParam->BSIM3v32cdsc < 0.0) - { fprintf(fplog, "Warning: Cdsc = %g is negative.\n", - pParam->BSIM3v32cdsc); - printf("Warning: Cdsc = %g is negative.\n", pParam->BSIM3v32cdsc); - } - if (pParam->BSIM3v32cdscd < 0.0) - { fprintf(fplog, "Warning: Cdscd = %g is negative.\n", - pParam->BSIM3v32cdscd); - printf("Warning: Cdscd = %g is negative.\n", pParam->BSIM3v32cdscd); - } -/* Check DIBL parameters */ - if (pParam->BSIM3v32eta0 < 0.0) - { fprintf(fplog, "Warning: Eta0 = %g is negative.\n", - pParam->BSIM3v32eta0); - printf("Warning: Eta0 = %g is negative.\n", pParam->BSIM3v32eta0); - } + /* Check subthreshold parameters */ + if (pParam->BSIM3v32nfactor < 0.0) + { fprintf(fplog, "Warning: Nfactor = %g is negative.\n", + pParam->BSIM3v32nfactor); + printf("Warning: Nfactor = %g is negative.\n", pParam->BSIM3v32nfactor); + } + if (pParam->BSIM3v32cdsc < 0.0) + { fprintf(fplog, "Warning: Cdsc = %g is negative.\n", + pParam->BSIM3v32cdsc); + printf("Warning: Cdsc = %g is negative.\n", pParam->BSIM3v32cdsc); + } + if (pParam->BSIM3v32cdscd < 0.0) + { fprintf(fplog, "Warning: Cdscd = %g is negative.\n", + pParam->BSIM3v32cdscd); + printf("Warning: Cdscd = %g is negative.\n", pParam->BSIM3v32cdscd); + } + /* Check DIBL parameters */ + if (pParam->BSIM3v32eta0 < 0.0) + { fprintf(fplog, "Warning: Eta0 = %g is negative.\n", + pParam->BSIM3v32eta0); + printf("Warning: Eta0 = %g is negative.\n", pParam->BSIM3v32eta0); + } -/* Check Abulk parameters */ - if (fabs(1.0e-6 / (pParam->BSIM3v32b1 + pParam->BSIM3v32weff)) > 10.0) - { fprintf(fplog, "Warning: (B1 + Weff) may be too small.\n"); - printf("Warning: (B1 + Weff) may be too small.\n"); - } + /* Check Abulk parameters */ + if (fabs(1.0e-6 / (pParam->BSIM3v32b1 + pParam->BSIM3v32weff)) > 10.0) + { fprintf(fplog, "Warning: (B1 + Weff) may be too small.\n"); + printf("Warning: (B1 + Weff) may be too small.\n"); + } -/* Check Saturation parameters */ - if (pParam->BSIM3v32a2 < 0.01) - { fprintf(fplog, "Warning: A2 = %g is too small. Set to 0.01.\n", pParam->BSIM3v32a2); - printf("Warning: A2 = %g is too small. Set to 0.01.\n", - pParam->BSIM3v32a2); - pParam->BSIM3v32a2 = 0.01; - } - else if (pParam->BSIM3v32a2 > 1.0) - { fprintf(fplog, "Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", - pParam->BSIM3v32a2); - printf("Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", - pParam->BSIM3v32a2); - pParam->BSIM3v32a2 = 1.0; - pParam->BSIM3v32a1 = 0.0; + /* Check Saturation parameters */ + if (pParam->BSIM3v32a2 < 0.01) + { fprintf(fplog, "Warning: A2 = %g is too small. Set to 0.01.\n", pParam->BSIM3v32a2); + printf("Warning: A2 = %g is too small. Set to 0.01.\n", + pParam->BSIM3v32a2); + pParam->BSIM3v32a2 = 0.01; + } + else if (pParam->BSIM3v32a2 > 1.0) + { fprintf(fplog, "Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", + pParam->BSIM3v32a2); + printf("Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n", + pParam->BSIM3v32a2); + pParam->BSIM3v32a2 = 1.0; + pParam->BSIM3v32a1 = 0.0; - } + } - if (pParam->BSIM3v32rdsw < 0.0) - { fprintf(fplog, "Warning: Rdsw = %g is negative. Set to zero.\n", - pParam->BSIM3v32rdsw); - printf("Warning: Rdsw = %g is negative. Set to zero.\n", - pParam->BSIM3v32rdsw); - pParam->BSIM3v32rdsw = 0.0; - pParam->BSIM3v32rds0 = 0.0; - } - else if ((pParam->BSIM3v32rds0 > 0.0) && (pParam->BSIM3v32rds0 < 0.001)) - { fprintf(fplog, "Warning: Rds at current temperature = %g is less than 0.001 ohm. Set to zero.\n", - pParam->BSIM3v32rds0); - printf("Warning: Rds at current temperature = %g is less than 0.001 ohm. Set to zero.\n", - pParam->BSIM3v32rds0); - pParam->BSIM3v32rds0 = 0.0; - } - if (pParam->BSIM3v32vsattemp < 1.0e3) - { fprintf(fplog, "Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3v32vsattemp); - printf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3v32vsattemp); - } + if (pParam->BSIM3v32rdsw < 0.0) + { fprintf(fplog, "Warning: Rdsw = %g is negative. Set to zero.\n", + pParam->BSIM3v32rdsw); + printf("Warning: Rdsw = %g is negative. Set to zero.\n", + pParam->BSIM3v32rdsw); + pParam->BSIM3v32rdsw = 0.0; + pParam->BSIM3v32rds0 = 0.0; + } + else if ((pParam->BSIM3v32rds0 > 0.0) && (pParam->BSIM3v32rds0 < 0.001)) + { fprintf(fplog, "Warning: Rds at current temperature = %g is less than 0.001 ohm. Set to zero.\n", + pParam->BSIM3v32rds0); + printf("Warning: Rds at current temperature = %g is less than 0.001 ohm. Set to zero.\n", + pParam->BSIM3v32rds0); + pParam->BSIM3v32rds0 = 0.0; + } + if (pParam->BSIM3v32vsattemp < 1.0e3) + { fprintf(fplog, "Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3v32vsattemp); + printf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM3v32vsattemp); + } - if (pParam->BSIM3v32pdibl1 < 0.0) - { fprintf(fplog, "Warning: Pdibl1 = %g is negative.\n", - pParam->BSIM3v32pdibl1); - printf("Warning: Pdibl1 = %g is negative.\n", pParam->BSIM3v32pdibl1); - } - if (pParam->BSIM3v32pdibl2 < 0.0) - { fprintf(fplog, "Warning: Pdibl2 = %g is negative.\n", - pParam->BSIM3v32pdibl2); - printf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM3v32pdibl2); - } -/* Check overlap capacitance parameters */ - if (model->BSIM3v32cgdo < 0.0) - { fprintf(fplog, "Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3v32cgdo); - printf("Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3v32cgdo); - model->BSIM3v32cgdo = 0.0; - } - if (model->BSIM3v32cgso < 0.0) - { fprintf(fplog, "Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3v32cgso); - printf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3v32cgso); - model->BSIM3v32cgso = 0.0; - } - if (model->BSIM3v32cgbo < 0.0) - { fprintf(fplog, "Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3v32cgbo); - printf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3v32cgbo); - model->BSIM3v32cgbo = 0.0; - } + if (pParam->BSIM3v32pdibl1 < 0.0) + { fprintf(fplog, "Warning: Pdibl1 = %g is negative.\n", + pParam->BSIM3v32pdibl1); + printf("Warning: Pdibl1 = %g is negative.\n", pParam->BSIM3v32pdibl1); + } + if (pParam->BSIM3v32pdibl2 < 0.0) + { fprintf(fplog, "Warning: Pdibl2 = %g is negative.\n", + pParam->BSIM3v32pdibl2); + printf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM3v32pdibl2); + } + /* Check overlap capacitance parameters */ + if (model->BSIM3v32cgdo < 0.0) + { fprintf(fplog, "Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3v32cgdo); + printf("Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM3v32cgdo); + model->BSIM3v32cgdo = 0.0; + } + if (model->BSIM3v32cgso < 0.0) + { fprintf(fplog, "Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3v32cgso); + printf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM3v32cgso); + model->BSIM3v32cgso = 0.0; + } + if (model->BSIM3v32cgbo < 0.0) + { fprintf(fplog, "Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3v32cgbo); + printf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM3v32cgbo); + model->BSIM3v32cgbo = 0.0; + } - }/* loop for the parameter check for warning messages */ - fclose(fplog); + }/* loop for the parameter check for warning messages */ + fclose(fplog); } else { fprintf(stderr, "Warning: Can't open log file. Parameter checking skipped.\n"); diff --git a/src/spicelib/devices/bsim3v32/b3v32cvtest.c b/src/spicelib/devices/bsim3v32/b3v32cvtest.c index 52c162c37..8d0f717fe 100644 --- a/src/spicelib/devices/bsim3v32/b3v32cvtest.c +++ b/src/spicelib/devices/bsim3v32/b3v32cvtest.c @@ -31,21 +31,21 @@ double cbd, cbhat, cbs, cd, cdhat, tol, vgd, vgdo, vgs; for (; model != NULL; model = model->BSIM3v32nextModel) { /* loop through all the instances of the model */ for (here = model->BSIM3v32instances; here != NULL ; - here=here->BSIM3v32nextInstance) - { - vbs = model->BSIM3v32type - * (*(ckt->CKTrhsOld+here->BSIM3v32bNode) - - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); + here=here->BSIM3v32nextInstance) + { + vbs = model->BSIM3v32type + * (*(ckt->CKTrhsOld+here->BSIM3v32bNode) + - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); vgs = model->BSIM3v32type - * (*(ckt->CKTrhsOld+here->BSIM3v32gNode) - - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); + * (*(ckt->CKTrhsOld+here->BSIM3v32gNode) + - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); vds = model->BSIM3v32type - * (*(ckt->CKTrhsOld+here->BSIM3v32dNodePrime) - - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); + * (*(ckt->CKTrhsOld+here->BSIM3v32dNodePrime) + - *(ckt->CKTrhsOld+here->BSIM3v32sNodePrime)); vbd = vbs - vds; vgd = vgs - vds; - vgdo = *(ckt->CKTstate0 + here->BSIM3v32vgs) - - *(ckt->CKTstate0 + here->BSIM3v32vds); + vgdo = *(ckt->CKTstate0 + here->BSIM3v32vgs) + - *(ckt->CKTstate0 + here->BSIM3v32vds); delvbs = vbs - *(ckt->CKTstate0 + here->BSIM3v32vbs); delvbd = vbd - *(ckt->CKTstate0 + here->BSIM3v32vbd); delvgs = vgs - *(ckt->CKTstate0 + here->BSIM3v32vgs); @@ -54,47 +54,47 @@ double cbd, cbhat, cbs, cd, cdhat, tol, vgd, vgdo, vgs; cd = here->BSIM3v32cd - here->BSIM3v32cbd; if (here->BSIM3v32mode >= 0) - { cd += here->BSIM3v32csub; - cdhat = cd - here->BSIM3v32gbd * delvbd - + (here->BSIM3v32gmbs + here->BSIM3v32gbbs) * delvbs - + (here->BSIM3v32gm + here->BSIM3v32gbgs) * delvgs - + (here->BSIM3v32gds + here->BSIM3v32gbds) * delvds; + { cd += here->BSIM3v32csub; + cdhat = cd - here->BSIM3v32gbd * delvbd + + (here->BSIM3v32gmbs + here->BSIM3v32gbbs) * delvbs + + (here->BSIM3v32gm + here->BSIM3v32gbgs) * delvgs + + (here->BSIM3v32gds + here->BSIM3v32gbds) * delvds; } - else - { cdhat = cd + (here->BSIM3v32gmbs - here->BSIM3v32gbd) * delvbd - + here->BSIM3v32gm * delvgd - here->BSIM3v32gds * delvds; + else + { cdhat = cd + (here->BSIM3v32gmbs - here->BSIM3v32gbd) * delvbd + + here->BSIM3v32gm * delvgd - here->BSIM3v32gds * delvds; } /* * check convergence */ if ((here->BSIM3v32off == 0) || (!(ckt->CKTmode & MODEINITFIX))) - { tol = ckt->CKTreltol * MAX(fabs(cdhat), fabs(cd)) - + ckt->CKTabstol; + { tol = ckt->CKTreltol * MAX(fabs(cdhat), fabs(cd)) + + ckt->CKTabstol; if (fabs(cdhat - cd) >= tol) - { ckt->CKTnoncon++; + { ckt->CKTnoncon++; return(OK); - } + } cbs = here->BSIM3v32cbs; cbd = here->BSIM3v32cbd; if (here->BSIM3v32mode >= 0) - { cbhat = cbs + cbd - here->BSIM3v32csub - + here->BSIM3v32gbd * delvbd - + (here->BSIM3v32gbs - here->BSIM3v32gbbs) * delvbs - - here->BSIM3v32gbgs * delvgs - - here->BSIM3v32gbds * delvds; - } - else - { cbhat = cbs + cbd - here->BSIM3v32csub - + here->BSIM3v32gbs * delvbs - + (here->BSIM3v32gbd - here->BSIM3v32gbbs) * delvbd - - here->BSIM3v32gbgs * delvgd - + here->BSIM3v32gbds * delvds; - } - tol = ckt->CKTreltol * MAX(fabs(cbhat), - fabs(cbs + cbd - here->BSIM3v32csub)) + ckt->CKTabstol; - if (fabs(cbhat - (cbs + cbd - here->BSIM3v32csub)) > tol) - { ckt->CKTnoncon++; + { cbhat = cbs + cbd - here->BSIM3v32csub + + here->BSIM3v32gbd * delvbd + + (here->BSIM3v32gbs - here->BSIM3v32gbbs) * delvbs + - here->BSIM3v32gbgs * delvgs + - here->BSIM3v32gbds * delvds; + } + else + { cbhat = cbs + cbd - here->BSIM3v32csub + + here->BSIM3v32gbs * delvbs + + (here->BSIM3v32gbd - here->BSIM3v32gbbs) * delvbd + - here->BSIM3v32gbgs * delvgd + + here->BSIM3v32gbds * delvds; + } + tol = ckt->CKTreltol * MAX(fabs(cbhat), + fabs(cbs + cbd - here->BSIM3v32csub)) + ckt->CKTabstol; + if (fabs(cbhat - (cbs + cbd - here->BSIM3v32csub)) > tol) + { ckt->CKTnoncon++; return(OK); } } diff --git a/src/spicelib/devices/bsim3v32/b3v32del.c b/src/spicelib/devices/bsim3v32/b3v32del.c index f6b9d15b8..4b5227540 100644 --- a/src/spicelib/devices/bsim3v32/b3v32del.c +++ b/src/spicelib/devices/bsim3v32/b3v32del.c @@ -25,11 +25,11 @@ BSIM3v32model *model = (BSIM3v32model*)inModel; BSIM3v32instance **prev = NULL; BSIM3v32instance *here; - for (; model ; model = model->BSIM3v32nextModel) + for (; model ; model = model->BSIM3v32nextModel) { prev = &(model->BSIM3v32instances); - for (here = *prev; here ; here = *prev) - { if (here->BSIM3v32name == name || (fast && here==*fast)) - { *prev= here->BSIM3v32nextInstance; + for (here = *prev; here ; here = *prev) + { if (here->BSIM3v32name == name || (fast && here==*fast)) + { *prev= here->BSIM3v32nextInstance; FREE(here); return(OK); } diff --git a/src/spicelib/devices/bsim3v32/b3v32dest.c b/src/spicelib/devices/bsim3v32/b3v32dest.c index b3e05f67b..8858e547f 100644 --- a/src/spicelib/devices/bsim3v32/b3v32dest.c +++ b/src/spicelib/devices/bsim3v32/b3v32dest.c @@ -23,7 +23,7 @@ BSIM3v32destroy (GENmodel **inModel) BSIM3v32model *oldmod = NULL; for (; mod ; mod = mod->BSIM3v32nextModel) { - /** added to get rid of link list pSizeDependParamKnot **/ + /** added to get rid of link list pSizeDependParamKnot **/ struct bsim3v32SizeDependParam *pParam, *pParamOld=NULL; pParam = mod->pSizeDependParamKnot; diff --git a/src/spicelib/devices/bsim3v32/b3v32getic.c b/src/spicelib/devices/bsim3v32/b3v32getic.c index 4f7798bd8..5c7bab523 100644 --- a/src/spicelib/devices/bsim3v32/b3v32getic.c +++ b/src/spicelib/devices/bsim3v32/b3v32getic.c @@ -21,20 +21,20 @@ BSIM3v32getic (GENmodel *inModel, CKTcircuit *ckt) BSIM3v32model *model = (BSIM3v32model*)inModel; BSIM3v32instance *here; - for (; model ; model = model->BSIM3v32nextModel) + for (; model ; model = model->BSIM3v32nextModel) { for (here = model->BSIM3v32instances; here; here = here->BSIM3v32nextInstance) - { - if (!here->BSIM3v32icVBSGiven) - { here->BSIM3v32icVBS = *(ckt->CKTrhs + here->BSIM3v32bNode) - - *(ckt->CKTrhs + here->BSIM3v32sNode); + { + if (!here->BSIM3v32icVBSGiven) + { here->BSIM3v32icVBS = *(ckt->CKTrhs + here->BSIM3v32bNode) + - *(ckt->CKTrhs + here->BSIM3v32sNode); } - if (!here->BSIM3v32icVDSGiven) - { here->BSIM3v32icVDS = *(ckt->CKTrhs + here->BSIM3v32dNode) - - *(ckt->CKTrhs + here->BSIM3v32sNode); + if (!here->BSIM3v32icVDSGiven) + { here->BSIM3v32icVDS = *(ckt->CKTrhs + here->BSIM3v32dNode) + - *(ckt->CKTrhs + here->BSIM3v32sNode); } - if (!here->BSIM3v32icVGSGiven) - { here->BSIM3v32icVGS = *(ckt->CKTrhs + here->BSIM3v32gNode) - - *(ckt->CKTrhs + here->BSIM3v32sNode); + if (!here->BSIM3v32icVGSGiven) + { here->BSIM3v32icVGS = *(ckt->CKTrhs + here->BSIM3v32gNode) + - *(ckt->CKTrhs + here->BSIM3v32sNode); } } } diff --git a/src/spicelib/devices/bsim3v32/b3v32ld.c b/src/spicelib/devices/bsim3v32/b3v32ld.c index 650a0c499..22c2646d6 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ld.c +++ b/src/spicelib/devices/bsim3v32/b3v32ld.c @@ -65,13 +65,13 @@ double DeltaPhi, dDeltaPhi_dVg, dDeltaPhi_dVd, dDeltaPhi_dVb; double Cox, Tox, Tcen, dTcen_dVg, dTcen_dVd, dTcen_dVb; double Ccen, Coxeff, dCoxeff_dVg, dCoxeff_dVd, dCoxeff_dVb; double Denomi, dDenomi_dVg, dDenomi_dVd, dDenomi_dVb; -double ueff, dueff_dVg, dueff_dVd, dueff_dVb; +double ueff, dueff_dVg, dueff_dVd, dueff_dVb; double Esat, Vdsat; double EsatL, dEsatL_dVg, dEsatL_dVd, dEsatL_dVb; -double dVdsat_dVg, dVdsat_dVb, dVdsat_dVd, Vasat, dAlphaz_dVg, dAlphaz_dVb; -double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, dVa_dVd, dVa_dVg, dVa_dVb; -double Vbseff, dVbseff_dVb, VbseffCV, dVbseffCV_dVb; -double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; +double dVdsat_dVg, dVdsat_dVb, dVdsat_dVd, Vasat, dAlphaz_dVg, dAlphaz_dVb; +double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, dVa_dVd, dVa_dVg, dVa_dVb; +double Vbseff, dVbseff_dVb, VbseffCV, dVbseffCV_dVb; +double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; double T0, dT0_dVg, dT0_dVd, dT0_dVb; double T1, dT1_dVg, dT1_dVd, dT1_dVb; double T2, dT2_dVg, dT2_dVd, dT2_dVb; @@ -82,7 +82,7 @@ double T6; double T7; double T8; double T9; -double T10; +double T10; double T11, T12; double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb; double VACLM, dVACLM_dVg, dVACLM_dVd, dVACLM_dVb; @@ -97,9 +97,9 @@ double tempv; #endif double a1, ScalingFactor; -double Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb; -double Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; -double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; +double Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb; +double Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; +double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; double diffVds, dAbulk_dVg; double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; double gche, dgche_dVg, dgche_dVd, dgche_dVb; @@ -123,79 +123,79 @@ double dxpart, sxpart, ggtg, ggtd, ggts, ggtb; double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; -double gbspsp, gbbdp, gbbsp, gbspg, gbspb, gbspdp; -double gbdpdp, gbdpg, gbdpb, gbdpsp; +double gbspsp, gbbdp, gbbsp, gbspg, gbspb, gbspdp; +double gbdpdp, gbdpg, gbdpb, gbdpsp; 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_dVd = 0.0, dQac0_dVb, dQsub0_dVg; double dQsub0_dVd, dQsub0_dVb; - + double m; struct bsim3v32SizeDependParam *pParam; int ByPass, Check, ChargeComputationNeeded, error; ScalingFactor = 1.0e-9; -ChargeComputationNeeded = +ChargeComputationNeeded = ((ckt->CKTmode & (MODEDCTRANCURVE | MODEAC | MODETRAN | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? 1 : 0; for (; model != NULL; model = model->BSIM3v32nextModel) -{ for (here = model->BSIM3v32instances; here != NULL; +{ for (here = model->BSIM3v32instances; here != NULL; here = here->BSIM3v32nextInstance) - { - Check = 1; + { + Check = 1; ByPass = 0; - pParam = here->pParam; + pParam = here->pParam; if ((ckt->CKTmode & MODEINITSMSIG)) - { vbs = *(ckt->CKTstate0 + here->BSIM3v32vbs); + { vbs = *(ckt->CKTstate0 + here->BSIM3v32vbs); vgs = *(ckt->CKTstate0 + here->BSIM3v32vgs); vds = *(ckt->CKTstate0 + here->BSIM3v32vds); qdef = *(ckt->CKTstate0 + here->BSIM3v32qdef); } - else if ((ckt->CKTmode & MODEINITTRAN)) - { vbs = *(ckt->CKTstate1 + here->BSIM3v32vbs); + else if ((ckt->CKTmode & MODEINITTRAN)) + { vbs = *(ckt->CKTstate1 + here->BSIM3v32vbs); vgs = *(ckt->CKTstate1 + here->BSIM3v32vgs); vds = *(ckt->CKTstate1 + here->BSIM3v32vds); qdef = *(ckt->CKTstate1 + here->BSIM3v32qdef); } - else if ((ckt->CKTmode & MODEINITJCT) && !here->BSIM3v32off) - { vds = model->BSIM3v32type * here->BSIM3v32icVDS; + else if ((ckt->CKTmode & MODEINITJCT) && !here->BSIM3v32off) + { vds = model->BSIM3v32type * here->BSIM3v32icVDS; vgs = model->BSIM3v32type * here->BSIM3v32icVGS; vbs = model->BSIM3v32type * here->BSIM3v32icVBS; qdef = 0.0; - if ((vds == 0.0) && (vgs == 0.0) && (vbs == 0.0) && + if ((vds == 0.0) && (vgs == 0.0) && (vbs == 0.0) && ((ckt->CKTmode & (MODETRAN | MODEAC|MODEDCOP | MODEDCTRANCURVE)) || (!(ckt->CKTmode & MODEUIC)))) - { vbs = 0.0; + { vbs = 0.0; vgs = model->BSIM3v32type * here->BSIM3v32vth0 + 0.1; vds = 0.1; } } - else if ((ckt->CKTmode & (MODEINITJCT | MODEINITFIX)) && - (here->BSIM3v32off)) + else if ((ckt->CKTmode & (MODEINITJCT | MODEINITFIX)) && + (here->BSIM3v32off)) { qdef = vbs = vgs = vds = 0.0; - } + } else - { + { #ifndef PREDICTOR if ((ckt->CKTmode & MODEINITPRED)) - { xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; - *(ckt->CKTstate0 + here->BSIM3v32vbs) = + { xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; + *(ckt->CKTstate0 + here->BSIM3v32vbs) = *(ckt->CKTstate1 + here->BSIM3v32vbs); vbs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3v32vbs)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3v32vbs))); - *(ckt->CKTstate0 + here->BSIM3v32vgs) = + *(ckt->CKTstate0 + here->BSIM3v32vgs) = *(ckt->CKTstate1 + here->BSIM3v32vgs); vgs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3v32vgs)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3v32vgs))); - *(ckt->CKTstate0 + here->BSIM3v32vds) = + *(ckt->CKTstate0 + here->BSIM3v32vds) = *(ckt->CKTstate1 + here->BSIM3v32vds); vds = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3v32vds)) - (xfact * (*(ckt->CKTstate2 + here->BSIM3v32vds))); - *(ckt->CKTstate0 + here->BSIM3v32vbd) = + *(ckt->CKTstate0 + here->BSIM3v32vbd) = *(ckt->CKTstate0 + here->BSIM3v32vbs) - *(ckt->CKTstate0 + here->BSIM3v32vds); *(ckt->CKTstate0 + here->BSIM3v32qdef) = @@ -203,14 +203,14 @@ for (; model != NULL; model = model->BSIM3v32nextModel) qdef = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3v32qdef)) -(xfact * (*(ckt->CKTstate2 + here->BSIM3v32qdef))); } - else - { + else + { #endif /* PREDICTOR */ vbs = model->BSIM3v32type * (*(ckt->CKTrhsOld + here->BSIM3v32bNode) - *(ckt->CKTrhsOld + here->BSIM3v32sNodePrime)); vgs = model->BSIM3v32type - * (*(ckt->CKTrhsOld + here->BSIM3v32gNode) + * (*(ckt->CKTrhsOld + here->BSIM3v32gNode) - *(ckt->CKTrhsOld + here->BSIM3v32sNodePrime)); vds = model->BSIM3v32type * (*(ckt->CKTrhsOld + here->BSIM3v32dNodePrime) @@ -274,7 +274,7 @@ for (; model != NULL; model = model->BSIM3v32nextModel) * MAX(fabs(cdhat),fabs(Idtot)) + ckt->CKTabstol)) { tempv = MAX(fabs(cbhat),fabs(Ibtot)) + ckt->CKTabstol; if ((fabs(cbhat - Ibtot)) < ckt->CKTreltol * tempv) - { /* bypass code */ + { /* bypass code */ vbs = *(ckt->CKTstate0 + here->BSIM3v32vbs); vbd = *(ckt->CKTstate0 + here->BSIM3v32vbd); vgs = *(ckt->CKTstate0 + here->BSIM3v32vgs); @@ -285,46 +285,46 @@ for (; model != NULL; model = model->BSIM3v32nextModel) vgb = vgs - vbs; cdrain = here->BSIM3v32cd; - if ((ckt->CKTmode & (MODETRAN | MODEAC)) || - ((ckt->CKTmode & MODETRANOP) && + if ((ckt->CKTmode & (MODETRAN | MODEAC)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) - { ByPass = 1; + { ByPass = 1; qgate = here->BSIM3v32qgate; qbulk = here->BSIM3v32qbulk; qdrn = here->BSIM3v32qdrn; - goto line755; + goto line755; + } + else + { goto line850; } - else - { goto line850; - } } } #endif /*NOBYPASS*/ von = here->BSIM3v32von; if (*(ckt->CKTstate0 + here->BSIM3v32vds) >= 0.0) - { vgs = DEVfetlim(vgs, *(ckt->CKTstate0+here->BSIM3v32vgs), von); + { vgs = DEVfetlim(vgs, *(ckt->CKTstate0+here->BSIM3v32vgs), von); vds = vgs - vgd; vds = DEVlimvds(vds, *(ckt->CKTstate0 + here->BSIM3v32vds)); vgd = vgs - vds; } - else - { vgd = DEVfetlim(vgd, vgdo, von); + else + { vgd = DEVfetlim(vgd, vgdo, von); vds = vgs - vgd; vds = -DEVlimvds(-vds, -(*(ckt->CKTstate0+here->BSIM3v32vds))); vgs = vgd + vds; } if (vds >= 0.0) - { vbs = DEVpnjlim(vbs, *(ckt->CKTstate0 + here->BSIM3v32vbs), + { vbs = DEVpnjlim(vbs, *(ckt->CKTstate0 + here->BSIM3v32vbs), CONSTvt0, model->BSIM3v32vcrit, &Check); vbd = vbs - vds; } - else - { vbd = DEVpnjlim(vbd, *(ckt->CKTstate0 + here->BSIM3v32vbd), - CONSTvt0, model->BSIM3v32vcrit, &Check); + else + { vbd = DEVpnjlim(vbd, *(ckt->CKTstate0 + here->BSIM3v32vbd), + CONSTvt0, model->BSIM3v32vcrit, &Check); vbs = vbd + vds; } } @@ -339,78 +339,18 @@ for (; model != NULL; model = model->BSIM3v32nextModel) /* acm model */ if (model->BSIM3v32acmMod == 0) { - if ((here->BSIM3v32sourceArea <= 0.0) - && (here->BSIM3v32sourcePerimeter <= 0.0)) - { - SourceSatCurrent = 1.0e-14; - } - else - { - SourceSatCurrent = here->BSIM3v32sourceArea - * model->BSIM3v32jctTempSatCurDensity - + here->BSIM3v32sourcePerimeter - * model->BSIM3v32jctSidewallTempSatCurDensity; - } - } - else - { - SourceSatCurrent = 0.0; - if (!here->BSIM3v32sourceAreaGiven) - { - here->BSIM3v32sourceArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff; - } - SourceSatCurrent = here->BSIM3v32sourceArea * model->BSIM3v32jctTempSatCurDensity; - if (!here->BSIM3v32sourcePerimeterGiven) - { - here->BSIM3v32sourcePerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff; - } - SourceSatCurrent = SourceSatCurrent + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; - if (SourceSatCurrent <= 0.0) SourceSatCurrent = 1.0e-14; - } - if (SourceSatCurrent <= 0.0) - { here->BSIM3v32gbs = ckt->CKTgmin; - here->BSIM3v32cbs = here->BSIM3v32gbs * vbs; - } - else - { if (model->BSIM3v32ijth == 0.0) - { evbs = exp(vbs / Nvtm); - here->BSIM3v32gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; - here->BSIM3v32cbs = SourceSatCurrent * (evbs - 1.0) - + ckt->CKTgmin * vbs; + if ((here->BSIM3v32sourceArea <= 0.0) + && (here->BSIM3v32sourcePerimeter <= 0.0)) + { + SourceSatCurrent = 1.0e-14; } - else - { if (vbs < here->BSIM3v32vjsm) - { evbs = exp(vbs / Nvtm); - here->BSIM3v32gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; - here->BSIM3v32cbs = SourceSatCurrent * (evbs - 1.0) - + ckt->CKTgmin * vbs; - } - else - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - T0 = here->BSIM3v32IsEvjsm / Nvtm; - here->BSIM3v32gbs = T0 + (ckt->CKTgmin); - here->BSIM3v32cbs = here->BSIM3v32IsEvjsm - SourceSatCurrent - + T0 * (vbs - here->BSIM3v32vjsm) + (ckt->CKTgmin) * vbs; - break; - case BSIM3v32V32: - default: - T0 = (SourceSatCurrent + model->BSIM3v32ijth) / Nvtm; - here->BSIM3v32gbs = T0 + (ckt->CKTgmin); - here->BSIM3v32cbs = model->BSIM3v32ijth + (ckt->CKTgmin) * vbs - + T0 * (vbs - here->BSIM3v32vjsm); - } - } + else + { + SourceSatCurrent = here->BSIM3v32sourceArea + * model->BSIM3v32jctTempSatCurDensity + + here->BSIM3v32sourcePerimeter + * model->BSIM3v32jctSidewallTempSatCurDensity; } - } - - /* acm model */ - if (model->BSIM3v32acmMod == 0) - { if ((here->BSIM3v32drainArea <= 0.0) && (here->BSIM3v32drainPerimeter <= 0.0)) { DrainSatCurrent = 1.0e-14; } @@ -423,21 +363,73 @@ for (; model != NULL; model = model->BSIM3v32nextModel) } else { - DrainSatCurrent = 0.0; - if (!here->BSIM3v32drainAreaGiven) - { - here->BSIM3v32drainArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff; - } - DrainSatCurrent = here->BSIM3v32drainArea * model->BSIM3v32jctTempSatCurDensity; - if (!here->BSIM3v32drainPerimeterGiven) - { - here->BSIM3v32drainPerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff; - } - DrainSatCurrent = DrainSatCurrent + here->BSIM3v32drainPerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; - if (DrainSatCurrent <= 0.0) DrainSatCurrent = 1.0e-14; + error = ACM_saturationCurrents( + model->BSIM3v32acmMod, + model->BSIM3v32calcacm, + here->BSIM3v32geo, + model->BSIM3v32hdif, + model->BSIM3v32wmlt, + here->BSIM3v32w, + model->BSIM3v32xw, + model->BSIM3v32jctTempSatCurDensity, + model->BSIM3v32jctSidewallTempSatCurDensity, + here->BSIM3v32drainAreaGiven, + here->BSIM3v32drainArea, + here->BSIM3v32drainPerimeterGiven, + here->BSIM3v32drainPerimeter, + here->BSIM3v32sourceAreaGiven, + here->BSIM3v32sourceArea, + here->BSIM3v32sourcePerimeterGiven, + here->BSIM3v32sourcePerimeter, + &DrainSatCurrent, + &SourceSatCurrent + ); + if (error) + return(error); } - if (DrainSatCurrent <= 0.0) - { here->BSIM3v32gbd = ckt->CKTgmin; + if (SourceSatCurrent <= 0.0) + { here->BSIM3v32gbs = ckt->CKTgmin; + here->BSIM3v32cbs = here->BSIM3v32gbs * vbs; + } + else + { if (model->BSIM3v32ijth == 0.0) + { evbs = exp(vbs / Nvtm); + here->BSIM3v32gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3v32cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { if (vbs < here->BSIM3v32vjsm) + { evbs = exp(vbs / Nvtm); + here->BSIM3v32gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3v32cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + T0 = here->BSIM3v32IsEvjsm / Nvtm; + here->BSIM3v32gbs = T0 + (ckt->CKTgmin); + here->BSIM3v32cbs = here->BSIM3v32IsEvjsm - SourceSatCurrent + + T0 * (vbs - here->BSIM3v32vjsm) + (ckt->CKTgmin) * vbs; + break; + case BSIM3v32V32: + default: + T0 = (SourceSatCurrent + model->BSIM3v32ijth) / Nvtm; + here->BSIM3v32gbs = T0 + (ckt->CKTgmin); + here->BSIM3v32cbs = model->BSIM3v32ijth + (ckt->CKTgmin) * vbs + + T0 * (vbs - here->BSIM3v32vjsm); + } + } + } + } + + if (DrainSatCurrent <= 0.0) + { here->BSIM3v32gbd = ckt->CKTgmin; here->BSIM3v32cbd = here->BSIM3v32gbd * vbd; } else @@ -455,68 +447,68 @@ for (; model != NULL; model = model->BSIM3v32nextModel) + ckt->CKTgmin * vbd; } else - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - T0 = here->BSIM3v32IsEvjdm / Nvtm; - here->BSIM3v32gbd = T0 + (ckt->CKTgmin); - here->BSIM3v32cbd = here->BSIM3v32IsEvjdm - DrainSatCurrent - + T0 * (vbd - here->BSIM3v32vjdm) + (ckt->CKTgmin) * vbd; - break; - case BSIM3v32V32: - default: - T0 = (DrainSatCurrent + model->BSIM3v32ijth) / Nvtm; - here->BSIM3v32gbd = T0 + (ckt->CKTgmin); - here->BSIM3v32cbd = model->BSIM3v32ijth + (ckt->CKTgmin) * vbd - + T0 * (vbd - here->BSIM3v32vjdm); - } + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + T0 = here->BSIM3v32IsEvjdm / Nvtm; + here->BSIM3v32gbd = T0 + (ckt->CKTgmin); + here->BSIM3v32cbd = here->BSIM3v32IsEvjdm - DrainSatCurrent + + T0 * (vbd - here->BSIM3v32vjdm) + (ckt->CKTgmin) * vbd; + break; + case BSIM3v32V32: + default: + T0 = (DrainSatCurrent + model->BSIM3v32ijth) / Nvtm; + here->BSIM3v32gbd = T0 + (ckt->CKTgmin); + here->BSIM3v32cbd = model->BSIM3v32ijth + (ckt->CKTgmin) * vbd + + T0 * (vbd - here->BSIM3v32vjdm); + } } } } /* End of diode DC model */ if (vds >= 0.0) - { /* normal mode */ + { /* normal mode */ here->BSIM3v32mode = 1; Vds = vds; Vgs = vgs; Vbs = vbs; } - else - { /* inverse mode */ + else + { /* inverse mode */ here->BSIM3v32mode = -1; Vds = -vds; Vgs = vgd; Vbs = vbd; } - T0 = Vbs - pParam->BSIM3v32vbsc - 0.001; - T1 = sqrt(T0 * T0 - 0.004 * pParam->BSIM3v32vbsc); - Vbseff = pParam->BSIM3v32vbsc + 0.5 * (T0 + T1); - dVbseff_dVb = 0.5 * (1.0 + T0 / T1); + T0 = Vbs - pParam->BSIM3v32vbsc - 0.001; + T1 = sqrt(T0 * T0 - 0.004 * pParam->BSIM3v32vbsc); + Vbseff = pParam->BSIM3v32vbsc + 0.5 * (T0 + T1); + dVbseff_dVb = 0.5 * (1.0 + T0 / T1); if (Vbseff < Vbs) { Vbseff = Vbs; } if (Vbseff > 0.0) - { T0 = pParam->BSIM3v32phi / (pParam->BSIM3v32phi + Vbseff); + { T0 = pParam->BSIM3v32phi / (pParam->BSIM3v32phi + Vbseff); Phis = pParam->BSIM3v32phi * T0; dPhis_dVb = -T0 * T0; sqrtPhis = pParam->BSIM3v32phis3 / (pParam->BSIM3v32phi + 0.5 * Vbseff); dsqrtPhis_dVb = -0.5 * sqrtPhis * sqrtPhis / pParam->BSIM3v32phis3; } - else - { Phis = pParam->BSIM3v32phi - Vbseff; + else + { Phis = pParam->BSIM3v32phi - Vbseff; dPhis_dVb = -1.0; sqrtPhis = sqrt(Phis); - dsqrtPhis_dVb = -0.5 / sqrtPhis; + dsqrtPhis_dVb = -0.5 / sqrtPhis; } Xdep = pParam->BSIM3v32Xdep0 * sqrtPhis / pParam->BSIM3v32sqrtPhi; dXdep_dVb = (pParam->BSIM3v32Xdep0 / pParam->BSIM3v32sqrtPhi) - * dsqrtPhis_dVb; + * dsqrtPhis_dVb; Leff = pParam->BSIM3v32leff; Vtm = model->BSIM3v32vtm; @@ -526,27 +518,27 @@ for (; model != NULL; model = model->BSIM3v32nextModel) T0 = pParam->BSIM3v32dvt2 * Vbseff; if (T0 >= - 0.5) - { T1 = 1.0 + T0; - T2 = pParam->BSIM3v32dvt2; - } - else /* Added to avoid any discontinuity problems caused by dvt2 */ - { T4 = 1.0 / (3.0 + 8.0 * T0); - T1 = (1.0 + 3.0 * T0) * T4; - T2 = pParam->BSIM3v32dvt2 * T4 * T4; - } + { T1 = 1.0 + T0; + T2 = pParam->BSIM3v32dvt2; + } + else /* Added to avoid any discontinuity problems caused by dvt2 */ + { T4 = 1.0 / (3.0 + 8.0 * T0); + T1 = (1.0 + 3.0 * T0) * T4; + T2 = pParam->BSIM3v32dvt2 * T4 * T4; + } lt1 = model->BSIM3v32factor1 * T3 * T1; dlt1_dVb = model->BSIM3v32factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); T0 = pParam->BSIM3v32dvt2w * Vbseff; if (T0 >= - 0.5) - { T1 = 1.0 + T0; - T2 = pParam->BSIM3v32dvt2w; - } - else /* Added to avoid any discontinuity problems caused by dvt2w */ - { T4 = 1.0 / (3.0 + 8.0 * T0); - T1 = (1.0 + 3.0 * T0) * T4; - T2 = pParam->BSIM3v32dvt2w * T4 * T4; - } + { T1 = 1.0 + T0; + T2 = pParam->BSIM3v32dvt2w; + } + else /* Added to avoid any discontinuity problems caused by dvt2w */ + { T4 = 1.0 / (3.0 + 8.0 * T0); + T1 = (1.0 + 3.0 * T0) * T4; + T2 = pParam->BSIM3v32dvt2w * T4 * T4; + } ltw = model->BSIM3v32factor1 * T3 * T1; dltw_dVb = model->BSIM3v32factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); @@ -590,18 +582,18 @@ for (; model != NULL; model = model->BSIM3v32nextModel) + (pParam->BSIM3v32kt1 + pParam->BSIM3v32kt1l / Leff + pParam->BSIM3v32kt2 * Vbseff) * TempRatio; tmp2 = model->BSIM3v32tox * pParam->BSIM3v32phi - / (pParam->BSIM3v32weff + pParam->BSIM3v32w0); + / (pParam->BSIM3v32weff + pParam->BSIM3v32w0); - T3 = pParam->BSIM3v32eta0 + pParam->BSIM3v32etab * Vbseff; - if (T3 < 1.0e-4) /* avoid discontinuity problems caused by etab */ - { T9 = 1.0 / (3.0 - 2.0e4 * T3); - T3 = (2.0e-4 - T3) * T9; - T4 = T9 * T9; - } - else - { T4 = 1.0; - } - dDIBL_Sft_dVd = T3 * pParam->BSIM3v32theta0vb0; + T3 = pParam->BSIM3v32eta0 + pParam->BSIM3v32etab * Vbseff; + if (T3 < 1.0e-4) /* avoid discontinuity problems caused by etab */ + { T9 = 1.0 / (3.0 - 2.0e4 * T3); + T3 = (2.0e-4 - T3) * T9; + T4 = T9 * T9; + } + else + { T4 = 1.0; + } + dDIBL_Sft_dVd = T3 * pParam->BSIM3v32theta0vb0; DIBL_Sft = dDIBL_Sft_dVd * Vds; Vth = model->BSIM3v32type * here->BSIM3v32vth0 - pParam->BSIM3v32k1 @@ -609,7 +601,7 @@ for (; model != NULL; model = model->BSIM3v32nextModel) - pParam->BSIM3v32k2ox * Vbseff - Delt_vth - T2 + (pParam->BSIM3v32k3 + pParam->BSIM3v32k3b * Vbseff) * tmp2 + T1 - DIBL_Sft; - here->BSIM3v32von = Vth; + here->BSIM3v32von = Vth; dVth_dVb = pParam->BSIM3v32k1ox * dsqrtPhis_dVb - pParam->BSIM3v32k2ox - dDelt_vth_dVb - dT2_dVb + pParam->BSIM3v32k3b * tmp2 @@ -621,28 +613,28 @@ for (; model != NULL; model = model->BSIM3v32nextModel) tmp2 = pParam->BSIM3v32nfactor * EPSSI / Xdep; tmp3 = pParam->BSIM3v32cdsc + pParam->BSIM3v32cdscb * Vbseff + pParam->BSIM3v32cdscd * Vds; - tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM3v32cit) / model->BSIM3v32cox; - if (tmp4 >= -0.5) - { n = 1.0 + tmp4; - dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM3v32cit) / model->BSIM3v32cox; + if (tmp4 >= -0.5) + { n = 1.0 + tmp4; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + pParam->BSIM3v32cdscb * Theta0) / model->BSIM3v32cox; dn_dVd = pParam->BSIM3v32cdscd * Theta0 / model->BSIM3v32cox; - } - else - /* avoid discontinuity problems caused by tmp4 */ - { T0 = 1.0 / (3.0 + 8.0 * tmp4); - n = (1.0 + 3.0 * tmp4) * T0; - T0 *= T0; - dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + } + else + /* avoid discontinuity problems caused by tmp4 */ + { T0 = 1.0 / (3.0 + 8.0 * tmp4); + n = (1.0 + 3.0 * tmp4) * T0; + T0 *= T0; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb + pParam->BSIM3v32cdscb * Theta0) / model->BSIM3v32cox * T0; dn_dVd = pParam->BSIM3v32cdscd * Theta0 / model->BSIM3v32cox * T0; - } + } /* Poly Gate Si Depletion Effect */ - T0 = here->BSIM3v32vfb + pParam->BSIM3v32phi; - if ((pParam->BSIM3v32ngate > 1.e18) && (pParam->BSIM3v32ngate < 1.e25) + T0 = here->BSIM3v32vfb + pParam->BSIM3v32phi; + if ((pParam->BSIM3v32ngate > 1.e18) && (pParam->BSIM3v32ngate < 1.e25) && (Vgs > T0)) - /* added to avoid the problem caused by ngate */ + /* added to avoid the problem caused by ngate */ { T1 = 1.0e6 * Charge_q * EPSSI * pParam->BSIM3v32ngate / (model->BSIM3v32cox * model->BSIM3v32cox); T4 = sqrt(1.0 + 2.0 * (Vgs - T0) / T1); @@ -652,10 +644,10 @@ for (; model != NULL; model = model->BSIM3v32nextModel) T6 = sqrt(T7 * T7 + 0.224); T5 = 1.12 - 0.5 * (T7 + T6); Vgs_eff = Vgs - T5; - dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6); + dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6); } - else - { Vgs_eff = Vgs; + else + { Vgs_eff = Vgs; dVgs_eff_dVg = 1.0; } Vgst = Vgs_eff - Vth; @@ -666,154 +658,154 @@ for (; model != NULL; model = model->BSIM3v32nextModel) VgstNVt = Vgst / T10; ExpArg = (2.0 * pParam->BSIM3v32voff - Vgst) / T10; - /* MCJ: Very small Vgst */ + /* MCJ: Very small Vgst */ if (VgstNVt > EXP_THRESHOLD) - { Vgsteff = Vgst; + { Vgsteff = Vgst; dVgsteff_dVg = dVgs_eff_dVg; dVgsteff_dVd = -dVth_dVd; dVgsteff_dVb = -dVth_dVb; - } - else if (ExpArg > EXP_THRESHOLD) - { T0 = (Vgst - pParam->BSIM3v32voff) / (n * Vtm); - ExpVgst = exp(T0); - Vgsteff = Vtm * pParam->BSIM3v32cdep0 / model->BSIM3v32cox * ExpVgst; + } + else if (ExpArg > EXP_THRESHOLD) + { T0 = (Vgst - pParam->BSIM3v32voff) / (n * Vtm); + ExpVgst = exp(T0); + Vgsteff = Vtm * pParam->BSIM3v32cdep0 / model->BSIM3v32cox * ExpVgst; dVgsteff_dVg = Vgsteff / (n * Vtm); dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + T0 * Vtm * dn_dVd); dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + T0 * Vtm * dn_dVb); - dVgsteff_dVg *= dVgs_eff_dVg; - } - else - { ExpVgst = exp(VgstNVt); + dVgsteff_dVg *= dVgs_eff_dVg; + } + else + { ExpVgst = exp(VgstNVt); T1 = T10 * log(1.0 + ExpVgst); dT1_dVg = ExpVgst / (1.0 + ExpVgst); dT1_dVb = -dT1_dVg * (dVth_dVb + Vgst / n * dn_dVb) - + T1 / n * dn_dVb; - dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd) - + T1 / n * dn_dVd; + + T1 / n * dn_dVb; + dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd) + + T1 / n * dn_dVd; - dT2_dVg = -model->BSIM3v32cox / (Vtm * pParam->BSIM3v32cdep0) - * exp(ExpArg); + dT2_dVg = -model->BSIM3v32cox / (Vtm * pParam->BSIM3v32cdep0) + * exp(ExpArg); T2 = 1.0 - T10 * dT2_dVg; dT2_dVd = -dT2_dVg * (dVth_dVd - 2.0 * Vtm * ExpArg * dn_dVd) - + (T2 - 1.0) / n * dn_dVd; + + (T2 - 1.0) / n * dn_dVd; dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * Vtm * ExpArg * dn_dVb) - + (T2 - 1.0) / n * dn_dVb; + + (T2 - 1.0) / n * dn_dVb; Vgsteff = T1 / T2; - T3 = T2 * T2; + T3 = T2 * T2; dVgsteff_dVg = (T2 * dT1_dVg - T1 * dT2_dVg) / T3 * dVgs_eff_dVg; dVgsteff_dVd = (T2 * dT1_dVd - T1 * dT2_dVd) / T3; dVgsteff_dVb = (T2 * dT1_dVb - T1 * dT2_dVb) / T3; - } - /* Added revision dependent code */ + } + /* Added revision dependent code */ if (model->BSIM3v32intVersion > BSIM3v32V323) { - here->BSIM3v32Vgsteff = Vgsteff; - } + here->BSIM3v32Vgsteff = Vgsteff; + } /* Calculate Effective Channel Geometry */ T9 = sqrtPhis - pParam->BSIM3v32sqrtPhi; - Weff = pParam->BSIM3v32weff - 2.0 * (pParam->BSIM3v32dwg * Vgsteff - + pParam->BSIM3v32dwb * T9); + Weff = pParam->BSIM3v32weff - 2.0 * (pParam->BSIM3v32dwg * Vgsteff + + pParam->BSIM3v32dwb * T9); dWeff_dVg = -2.0 * pParam->BSIM3v32dwg; dWeff_dVb = -2.0 * pParam->BSIM3v32dwb * dsqrtPhis_dVb; if (Weff < 2.0e-8) /* to avoid the discontinuity problem due to Weff*/ - { T0 = 1.0 / (6.0e-8 - 2.0 * Weff); - Weff = 2.0e-8 * (4.0e-8 - Weff) * T0; - T0 *= T0 * 4.0e-16; + { T0 = 1.0 / (6.0e-8 - 2.0 * Weff); + Weff = 2.0e-8 * (4.0e-8 - Weff) * T0; + T0 *= T0 * 4.0e-16; dWeff_dVg *= T0; - dWeff_dVb *= T0; + dWeff_dVb *= T0; } T0 = pParam->BSIM3v32prwg * Vgsteff + pParam->BSIM3v32prwb * T9; - if (T0 >= -0.9) - { Rds = pParam->BSIM3v32rds0 * (1.0 + T0); - dRds_dVg = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwg; + if (T0 >= -0.9) + { Rds = pParam->BSIM3v32rds0 * (1.0 + T0); + dRds_dVg = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwg; dRds_dVb = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwb * dsqrtPhis_dVb; - } - else - /* to avoid the discontinuity problem due to prwg and prwb*/ - { T1 = 1.0 / (17.0 + 20.0 * T0); - Rds = pParam->BSIM3v32rds0 * (0.8 + T0) * T1; - T1 *= T1; - dRds_dVg = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwg * T1; - dRds_dVb = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwb * dsqrtPhis_dVb - * T1; - } - /* Added revision dependent code */ - if (model->BSIM3v32intVersion > BSIM3v32V323) { - here->BSIM3v32rds = Rds; /* Noise Bugfix */ } - + else + /* to avoid the discontinuity problem due to prwg and prwb*/ + { T1 = 1.0 / (17.0 + 20.0 * T0); + Rds = pParam->BSIM3v32rds0 * (0.8 + T0) * T1; + T1 *= T1; + dRds_dVg = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwg * T1; + dRds_dVb = pParam->BSIM3v32rds0 * pParam->BSIM3v32prwb * dsqrtPhis_dVb + * T1; + } + /* Added revision dependent code */ + if (model->BSIM3v32intVersion > BSIM3v32V323) { + here->BSIM3v32rds = Rds; /* Noise Bugfix */ + } + /* Calculate Abulk */ T1 = 0.5 * pParam->BSIM3v32k1ox / sqrtPhis; dT1_dVb = -T1 / sqrtPhis * dsqrtPhis_dVb; T9 = sqrt(pParam->BSIM3v32xj * Xdep); tmp1 = Leff + 2.0 * T9; - T5 = Leff / tmp1; + T5 = Leff / tmp1; tmp2 = pParam->BSIM3v32a0 * T5; - tmp3 = pParam->BSIM3v32weff + pParam->BSIM3v32b1; + tmp3 = pParam->BSIM3v32weff + pParam->BSIM3v32b1; tmp4 = pParam->BSIM3v32b0 / tmp3; T2 = tmp2 + tmp4; dT2_dVb = -T9 / tmp1 / Xdep * dXdep_dVb; T6 = T5 * T5; T7 = T5 * T6; - Abulk0 = 1.0 + T1 * T2; + Abulk0 = 1.0 + T1 * T2; dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb; T8 = pParam->BSIM3v32ags * pParam->BSIM3v32a0 * T7; dAbulk_dVg = -T1 * T8; - Abulk = Abulk0 + dAbulk_dVg * Vgsteff; + Abulk = Abulk0 + dAbulk_dVg * Vgsteff; dAbulk_dVb = dAbulk0_dVb - T8 * Vgsteff * (dT1_dVb - + 3.0 * T1 * dT2_dVb); + + 3.0 * T1 * dT2_dVb); if (Abulk0 < 0.1) /* added to avoid the problems caused by Abulk0 */ - { T9 = 1.0 / (3.0 - 20.0 * Abulk0); - Abulk0 = (0.2 - Abulk0) * T9; - dAbulk0_dVb *= T9 * T9; - } + { T9 = 1.0 / (3.0 - 20.0 * Abulk0); + Abulk0 = (0.2 - Abulk0) * T9; + dAbulk0_dVb *= T9 * T9; + } if (Abulk < 0.1) /* added to avoid the problems caused by Abulk */ - { T9 = 1.0 / (3.0 - 20.0 * Abulk); - Abulk = (0.2 - Abulk) * T9; - /* Added revision dependent code */ + { T9 = 1.0 / (3.0 - 20.0 * Abulk); + Abulk = (0.2 - Abulk) * T9; + /* Added revision dependent code */ if (model->BSIM3v32intVersion > BSIM3v32V32) { - T10 = T9 * T9; - dAbulk_dVb *= T10; - dAbulk_dVg *= T10; - } else { - dAbulk_dVb *= T9 * T9; - } - } - /* Added revision dependent code */ + T10 = T9 * T9; + dAbulk_dVb *= T10; + dAbulk_dVg *= T10; + } else { + dAbulk_dVb *= T9 * T9; + } + } + /* Added revision dependent code */ if (model->BSIM3v32intVersion > BSIM3v32V323) { - here->BSIM3v32Abulk = Abulk; + here->BSIM3v32Abulk = Abulk; } T2 = pParam->BSIM3v32keta * Vbseff; - if (T2 >= -0.9) - { T0 = 1.0 / (1.0 + T2); + if (T2 >= -0.9) + { T0 = 1.0 / (1.0 + T2); dT0_dVb = -pParam->BSIM3v32keta * T0 * T0; - } - else + } + else /* added to avoid the problems caused by Keta */ - { T1 = 1.0 / (0.8 + T2); - T0 = (17.0 + 20.0 * T2) * T1; + { T1 = 1.0 / (0.8 + T2); + T0 = (17.0 + 20.0 * T2) * T1; dT0_dVb = -pParam->BSIM3v32keta * T1 * T1; - } - dAbulk_dVg *= T0; - dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb; - dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb; - Abulk *= T0; - Abulk0 *= T0; + } + dAbulk_dVg *= T0; + dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb; + dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb; + Abulk *= T0; + Abulk0 *= T0; /* Mobility calculation */ if (model->BSIM3v32mobMod == 1) - { T0 = Vgsteff + Vth + Vth; + { T0 = Vgsteff + Vth + Vth; T2 = pParam->BSIM3v32ua + pParam->BSIM3v32uc * Vbseff; T3 = T0 / model->BSIM3v32tox; T5 = T3 * (T2 + pParam->BSIM3v32ub * T3); @@ -821,49 +813,49 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM3v32uc * T3; } - else if (model->BSIM3v32mobMod == 2) - { T5 = Vgsteff / model->BSIM3v32tox * (pParam->BSIM3v32ua - + pParam->BSIM3v32uc * Vbseff + pParam->BSIM3v32ub * Vgsteff + else if (model->BSIM3v32mobMod == 2) + { T5 = Vgsteff / model->BSIM3v32tox * (pParam->BSIM3v32ua + + pParam->BSIM3v32uc * Vbseff + pParam->BSIM3v32ub * Vgsteff / model->BSIM3v32tox); dDenomi_dVg = (pParam->BSIM3v32ua + pParam->BSIM3v32uc * Vbseff - + 2.0 * pParam->BSIM3v32ub * Vgsteff / model->BSIM3v32tox) - / model->BSIM3v32tox; + + 2.0 * pParam->BSIM3v32ub * Vgsteff / model->BSIM3v32tox) + / model->BSIM3v32tox; dDenomi_dVd = 0.0; - dDenomi_dVb = Vgsteff * pParam->BSIM3v32uc / model->BSIM3v32tox; + dDenomi_dVb = Vgsteff * pParam->BSIM3v32uc / model->BSIM3v32tox; } - else - { T0 = Vgsteff + Vth + Vth; + else + { T0 = Vgsteff + Vth + Vth; T2 = 1.0 + pParam->BSIM3v32uc * Vbseff; T3 = T0 / model->BSIM3v32tox; T4 = T3 * (pParam->BSIM3v32ua + pParam->BSIM3v32ub * T3); - T5 = T4 * T2; + T5 = T4 * T2; dDenomi_dVg = (pParam->BSIM3v32ua + 2.0 * pParam->BSIM3v32ub * T3) * T2 - / model->BSIM3v32tox; + / model->BSIM3v32tox; dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM3v32uc * T4; } - if (T5 >= -0.8) - { Denomi = 1.0 + T5; - } - else /* Added to avoid the discontinuity problem caused by ua and ub*/ - { T9 = 1.0 / (7.0 + 10.0 * T5); - Denomi = (0.6 + T5) * T9; - T9 *= T9; + if (T5 >= -0.8) + { Denomi = 1.0 + T5; + } + else /* Added to avoid the discontinuity problem caused by ua and ub*/ + { T9 = 1.0 / (7.0 + 10.0 * T5); + Denomi = (0.6 + T5) * T9; + T9 *= T9; dDenomi_dVg *= T9; dDenomi_dVd *= T9; dDenomi_dVb *= T9; - } + } here->BSIM3v32ueff = ueff = here->BSIM3v32u0temp / Denomi; - T9 = -ueff / Denomi; + T9 = -ueff / Denomi; dueff_dVg = T9 * dDenomi_dVg; dueff_dVd = T9 * dDenomi_dVd; dueff_dVb = T9 * dDenomi_dVb; /* Saturation Drain Voltage Vdsat */ WVCox = Weff * pParam->BSIM3v32vsattemp * model->BSIM3v32cox; - WVCoxRds = WVCox * Rds; + WVCoxRds = WVCox * Rds; Esat = 2.0 * pParam->BSIM3v32vsattemp / ueff; EsatL = Esat * Leff; @@ -871,31 +863,31 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dEsatL_dVg = T0 * dueff_dVg; dEsatL_dVd = T0 * dueff_dVd; dEsatL_dVb = T0 * dueff_dVb; - - /* Sqrt() */ + + /* Sqrt() */ a1 = pParam->BSIM3v32a1; - if (a1 == 0.0) - { Lambda = pParam->BSIM3v32a2; - dLambda_dVg = 0.0; - } - else if (a1 > 0.0) + if (a1 == 0.0) + { Lambda = pParam->BSIM3v32a2; + dLambda_dVg = 0.0; + } + else if (a1 > 0.0) /* Added to avoid the discontinuity problem caused by a1 and a2 (Lambda) */ - { T0 = 1.0 - pParam->BSIM3v32a2; - T1 = T0 - pParam->BSIM3v32a1 * Vgsteff - 0.0001; - T2 = sqrt(T1 * T1 + 0.0004 * T0); - Lambda = pParam->BSIM3v32a2 + T0 - 0.5 * (T1 + T2); - dLambda_dVg = 0.5 * pParam->BSIM3v32a1 * (1.0 + T1 / T2); - } - else - { T1 = pParam->BSIM3v32a2 + pParam->BSIM3v32a1 * Vgsteff - 0.0001; - T2 = sqrt(T1 * T1 + 0.0004 * pParam->BSIM3v32a2); - Lambda = 0.5 * (T1 + T2); - dLambda_dVg = 0.5 * pParam->BSIM3v32a1 * (1.0 + T1 / T2); - } + { T0 = 1.0 - pParam->BSIM3v32a2; + T1 = T0 - pParam->BSIM3v32a1 * Vgsteff - 0.0001; + T2 = sqrt(T1 * T1 + 0.0004 * T0); + Lambda = pParam->BSIM3v32a2 + T0 - 0.5 * (T1 + T2); + dLambda_dVg = 0.5 * pParam->BSIM3v32a1 * (1.0 + T1 / T2); + } + else + { T1 = pParam->BSIM3v32a2 + pParam->BSIM3v32a1 * Vgsteff - 0.0001; + T2 = sqrt(T1 * T1 + 0.0004 * pParam->BSIM3v32a2); + Lambda = 0.5 * (T1 + T2); + dLambda_dVg = 0.5 * pParam->BSIM3v32a1 * (1.0 + T1 / T2); + } Vgst2Vtm = Vgsteff + 2.0 * Vtm; - /* Added revision dependent code */ + /* Added revision dependent code */ if (model->BSIM3v32intVersion > BSIM3v32V323) { here->BSIM3v32AbovVgst2Vtm = Abulk / Vgst2Vtm; } @@ -907,48 +899,48 @@ for (; model != NULL; model = model->BSIM3v32nextModel) else { tmp2 = dWeff_dVg / Weff; tmp3 = dWeff_dVb / Weff; - } + } if ((Rds == 0.0) && (Lambda == 1.0)) { T0 = 1.0 / (Abulk * EsatL + Vgst2Vtm); tmp1 = 0.0; - T1 = T0 * T0; - T2 = Vgst2Vtm * T0; + T1 = T0 * T0; + T2 = Vgst2Vtm * T0; T3 = EsatL * Vgst2Vtm; Vdsat = T3 * T0; - + dT0_dVg = -(Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 1.0) * T1; - dT0_dVd = -(Abulk * dEsatL_dVd) * T1; - dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1; + dT0_dVd = -(Abulk * dEsatL_dVd) * T1; + dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1; dVdsat_dVg = T3 * dT0_dVg + T2 * dEsatL_dVg + EsatL * T0; dVdsat_dVd = T3 * dT0_dVd + T2 * dEsatL_dVd; - dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb; + dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb; } else { tmp1 = dLambda_dVg / (Lambda * Lambda); T9 = Abulk * WVCoxRds; - T8 = Abulk * T9; - T7 = Vgst2Vtm * T9; + T8 = Abulk * T9; + T7 = Vgst2Vtm * T9; T6 = Vgst2Vtm * WVCoxRds; - T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda); + T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda); dT0_dVg = 2.0 * (T8 * tmp2 - Abulk * tmp1 - + (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg); - + + (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg); + dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3) - + (1.0 / Lambda - 1.0) * dAbulk_dVb); - dT0_dVd = 0.0; + + (1.0 / Lambda - 1.0) * dAbulk_dVb); + dT0_dVd = 0.0; T1 = Vgst2Vtm * (2.0 / Lambda - 1.0) + Abulk * EsatL + 3.0 * T7; - + dT1_dVg = (2.0 / Lambda - 1.0) - 2.0 * Vgst2Vtm * tmp1 - + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 3.0 * (T9 - + T7 * tmp2 + T6 * dAbulk_dVg); + + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 3.0 * (T9 + + T7 * tmp2 + T6 * dAbulk_dVg); dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb - + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3); + + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3); dT1_dVd = Abulk * dEsatL_dVd; T2 = Vgst2Vtm * (EsatL + 2.0 * T6); dT2_dVg = EsatL + Vgst2Vtm * dEsatL_dVg - + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2); + + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2); dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3); dT2_dVd = Vgst2Vtm * dEsatL_dVd; @@ -956,16 +948,16 @@ for (; model != NULL; model = model->BSIM3v32nextModel) Vdsat = (T1 - T3) / T0; dT3_dVg = (T1 * dT1_dVg - 2.0 * (T0 * dT2_dVg + T2 * dT0_dVg)) - / T3; + / T3; dT3_dVd = (T1 * dT1_dVd - 2.0 * (T0 * dT2_dVd + T2 * dT0_dVd)) - / T3; + / T3; dT3_dVb = (T1 * dT1_dVb - 2.0 * (T0 * dT2_dVb + T2 * dT0_dVb)) - / T3; + / T3; dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2 - - T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0; + - T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0; dVdsat_dVb = (dT1_dVb - (T1 * dT1_dVb - dT0_dVb * T2 - - T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0; + - T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0; dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0; } here->BSIM3v32vdsat = Vdsat; @@ -977,52 +969,52 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dT1_dVb = dVdsat_dVb; T2 = sqrt(T1 * T1 + 4.0 * pParam->BSIM3v32delta * Vdsat); - T0 = T1 / T2; - T3 = 2.0 * pParam->BSIM3v32delta / T2; + T0 = T1 / T2; + T3 = 2.0 * pParam->BSIM3v32delta / T2; dT2_dVg = T0 * dT1_dVg + T3 * dVdsat_dVg; dT2_dVd = T0 * dT1_dVd + T3 * dVdsat_dVd; dT2_dVb = T0 * dT1_dVb + T3 * dVdsat_dVb; Vdseff = Vdsat - 0.5 * (T1 + T2); - dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg); - dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd); - dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - /* Added to eliminate non-zero Vdseff at Vds=0.0 */ - if (Vds == 0.0) - { - Vdseff = 0.0; - dVdseff_dVg = 0.0; - dVdseff_dVb = 0.0; - } - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } + dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg); + dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd); + dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + /* Added to eliminate non-zero Vdseff at Vds=0.0 */ + if (Vds == 0.0) + { + Vdseff = 0.0; + dVdseff_dVg = 0.0; + dVdseff_dVb = 0.0; + } + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } /* Calculate VAsat */ tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; T9 = WVCoxRds * Vgsteff; - T8 = T9 / Vgst2Vtm; + T8 = T9 / Vgst2Vtm; T0 = EsatL + Vdsat + 2.0 * T9 * tmp4; - + T7 = 2.0 * WVCoxRds * tmp4; dT0_dVg = dEsatL_dVg + dVdsat_dVg + T7 * (1.0 + tmp2 * Vgsteff) - - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm - + Vdsat * dAbulk_dVg); - + - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm + + Vdsat * dAbulk_dVg); + dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * Vgsteff - - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); + - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); dT0_dVd = dEsatL_dVd + dVdsat_dVd - T8 * Abulk * dVdsat_dVd; - T9 = WVCoxRds * Abulk; - T1 = 2.0 / Lambda - 1.0 + T9; + T9 = WVCoxRds * Abulk; + T1 = 2.0 / Lambda - 1.0 + T9; dT1_dVg = -2.0 * tmp1 + WVCoxRds * (Abulk * tmp2 + dAbulk_dVg); dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3; @@ -1034,42 +1026,42 @@ for (; model != NULL; model = model->BSIM3v32nextModel) if (Vdseff > Vds) Vdseff = Vds; diffVds = Vds - Vdseff; - /* Added revision dependent code */ + /* Added revision dependent code */ if (model->BSIM3v32intVersion > BSIM3v32V323) { - here->BSIM3v32Vdseff = Vdseff; - } + here->BSIM3v32Vdseff = Vdseff; + } /* Calculate VACLM */ if ((pParam->BSIM3v32pclm > 0.0) && (diffVds > 1.0e-10)) - { T0 = 1.0 / (pParam->BSIM3v32pclm * Abulk * pParam->BSIM3v32litl); + { T0 = 1.0 / (pParam->BSIM3v32pclm * Abulk * pParam->BSIM3v32litl); dT0_dVb = -T0 / Abulk * dAbulk_dVb; - dT0_dVg = -T0 / Abulk * dAbulk_dVg; - - T2 = Vgsteff / EsatL; - T1 = Leff * (Abulk + T2); + dT0_dVg = -T0 / Abulk * dAbulk_dVg; + + T2 = Vgsteff / EsatL; + T1 = Leff * (Abulk + T2); dT1_dVg = Leff * ((1.0 - T2 * dEsatL_dVg) / EsatL + dAbulk_dVg); dT1_dVb = Leff * (dAbulk_dVb - T2 * dEsatL_dVb / EsatL); dT1_dVd = -T2 * dEsatL_dVd / Esat; - T9 = T0 * T1; + T9 = T0 * T1; VACLM = T9 * diffVds; dVACLM_dVg = T0 * dT1_dVg * diffVds - T9 * dVdseff_dVg + T1 * diffVds * dT0_dVg; dVACLM_dVb = (dT0_dVb * T1 + T0 * dT1_dVb) * diffVds - - T9 * dVdseff_dVb; + - T9 * dVdseff_dVb; dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd); } - else - { VACLM = MAX_EXP; + else + { VACLM = MAX_EXP; dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0; } /* Calculate VADIBL */ if (pParam->BSIM3v32thetaRout > 0.0) - { T8 = Abulk * Vdsat; - T0 = Vgst2Vtm * T8; + { T8 = Abulk * Vdsat; + T0 = Vgst2Vtm * T8; dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 - + Vgst2Vtm * Vdsat * dAbulk_dVg; + + Vgst2Vtm * Vdsat * dAbulk_dVg; dT0_dVb = Vgst2Vtm * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd; @@ -1078,59 +1070,59 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat; dT1_dVd = Abulk * dVdsat_dVd; - T9 = T1 * T1; - T2 = pParam->BSIM3v32thetaRout; + T9 = T1 * T1; + T2 = pParam->BSIM3v32thetaRout; VADIBL = (Vgst2Vtm - T0 / T1) / T2; dVADIBL_dVg = (1.0 - dT0_dVg / T1 + T0 * dT1_dVg / T9) / T2; dVADIBL_dVb = (-dT0_dVb / T1 + T0 * dT1_dVb / T9) / T2; dVADIBL_dVd = (-dT0_dVd / T1 + T0 * dT1_dVd / T9) / T2; - T7 = pParam->BSIM3v32pdiblb * Vbseff; - if (T7 >= -0.9) - { T3 = 1.0 / (1.0 + T7); + T7 = pParam->BSIM3v32pdiblb * Vbseff; + if (T7 >= -0.9) + { T3 = 1.0 / (1.0 + T7); VADIBL *= T3; dVADIBL_dVg *= T3; dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM3v32pdiblb) - * T3; + * T3; dVADIBL_dVd *= T3; - } - else + } + else /* Added to avoid the discontinuity problem caused by pdiblcb */ - { T4 = 1.0 / (0.8 + T7); - T3 = (17.0 + 20.0 * T7) * T4; + { T4 = 1.0 / (0.8 + T7); + T3 = (17.0 + 20.0 * T7) * T4; dVADIBL_dVg *= T3; dVADIBL_dVb = dVADIBL_dVb * T3 - - VADIBL * pParam->BSIM3v32pdiblb * T4 * T4; + - VADIBL * pParam->BSIM3v32pdiblb * T4 * T4; dVADIBL_dVd *= T3; VADIBL *= T3; - } + } } - else - { VADIBL = MAX_EXP; + else + { VADIBL = MAX_EXP; dVADIBL_dVd = dVADIBL_dVg = dVADIBL_dVb = 0.0; } /* Calculate VA */ - - T8 = pParam->BSIM3v32pvag / EsatL; - T9 = T8 * Vgsteff; - if (T9 > -0.9) - { T0 = 1.0 + T9; + + T8 = pParam->BSIM3v32pvag / EsatL; + T9 = T8 * Vgsteff; + if (T9 > -0.9) + { T0 = 1.0 + T9; dT0_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL); dT0_dVb = -T9 * dEsatL_dVb / EsatL; dT0_dVd = -T9 * dEsatL_dVd / EsatL; - } - else /* Added to avoid the discontinuity problems caused by pvag */ - { T1 = 1.0 / (17.0 + 20.0 * T9); - T0 = (0.8 + T9) * T1; - T1 *= T1; + } + else /* Added to avoid the discontinuity problems caused by pvag */ + { T1 = 1.0 / (17.0 + 20.0 * T9); + T0 = (0.8 + T9) * T1; + T1 *= T1; dT0_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL) * T1; T9 *= T1 / EsatL; dT0_dVb = -T9 * dEsatL_dVb; dT0_dVd = -T9 * dEsatL_dVd; - } - + } + tmp1 = VACLM * VACLM; tmp2 = VADIBL * VADIBL; tmp3 = VACLM + VADIBL; @@ -1147,25 +1139,25 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dVa_dVb = dVasat_dVb + T1 * dT0_dVb + T0 * dT1_dVb; /* Calculate VASCBE */ - if (pParam->BSIM3v32pscbe2 > 0.0) - { if (diffVds > pParam->BSIM3v32pscbe1 * pParam->BSIM3v32litl - / EXP_THRESHOLD) - { T0 = pParam->BSIM3v32pscbe1 * pParam->BSIM3v32litl / diffVds; - VASCBE = Leff * exp(T0) / pParam->BSIM3v32pscbe2; + if (pParam->BSIM3v32pscbe2 > 0.0) + { if (diffVds > pParam->BSIM3v32pscbe1 * pParam->BSIM3v32litl + / EXP_THRESHOLD) + { T0 = pParam->BSIM3v32pscbe1 * pParam->BSIM3v32litl / diffVds; + VASCBE = Leff * exp(T0) / pParam->BSIM3v32pscbe2; T1 = T0 * VASCBE / diffVds; dVASCBE_dVg = T1 * dVdseff_dVg; dVASCBE_dVd = -T1 * (1.0 - dVdseff_dVd); dVASCBE_dVb = T1 * dVdseff_dVb; } - else - { VASCBE = MAX_EXP * Leff/pParam->BSIM3v32pscbe2; + else + { VASCBE = MAX_EXP * Leff/pParam->BSIM3v32pscbe2; dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; } - } - else - { VASCBE = MAX_EXP; + } + else + { VASCBE = MAX_EXP; dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; - } + } /* Calculate Ids */ CoxWovL = model->BSIM3v32cox * Weff / Leff; @@ -1175,48 +1167,48 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dbeta_dVb = CoxWovL * dueff_dVb + beta * dWeff_dVb / Weff; T0 = 1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm; - dT0_dVg = -0.5 * (Abulk * dVdseff_dVg - - Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm; + dT0_dVg = -0.5 * (Abulk * dVdseff_dVg + - Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm; dT0_dVd = -0.5 * Abulk * dVdseff_dVd / Vgst2Vtm; dT0_dVb = -0.5 * (Abulk * dVdseff_dVb + dAbulk_dVb * Vdseff) / Vgst2Vtm; fgche1 = Vgsteff * T0; - dfgche1_dVg = Vgsteff * dT0_dVg + T0; - dfgche1_dVd = Vgsteff * dT0_dVd; - dfgche1_dVb = Vgsteff * dT0_dVb; + dfgche1_dVg = Vgsteff * dT0_dVg + T0; + dfgche1_dVd = Vgsteff * dT0_dVd; + dfgche1_dVb = Vgsteff * dT0_dVb; T9 = Vdseff / EsatL; fgche2 = 1.0 + T9; dfgche2_dVg = (dVdseff_dVg - T9 * dEsatL_dVg) / EsatL; dfgche2_dVd = (dVdseff_dVd - T9 * dEsatL_dVd) / EsatL; dfgche2_dVb = (dVdseff_dVb - T9 * dEsatL_dVb) / EsatL; - + gche = beta * fgche1 / fgche2; dgche_dVg = (beta * dfgche1_dVg + fgche1 * dbeta_dVg - - gche * dfgche2_dVg) / fgche2; + - gche * dfgche2_dVg) / fgche2; dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd - - gche * dfgche2_dVd) / fgche2; + - gche * dfgche2_dVd) / fgche2; dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb - - gche * dfgche2_dVb) / fgche2; + - gche * dfgche2_dVb) / fgche2; T0 = 1.0 + gche * Rds; T9 = Vdseff / T0; Idl = gche * T9; dIdl_dVg = (gche * dVdseff_dVg + T9 * dgche_dVg) / T0 - - Idl * gche / T0 * dRds_dVg ; + - Idl * gche / T0 * dRds_dVg ; - dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0; - dIdl_dVb = (gche * dVdseff_dVb + T9 * dgche_dVb - - Idl * dRds_dVb * gche) / T0; + dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0; + dIdl_dVb = (gche * dVdseff_dVb + T9 * dgche_dVb + - Idl * dRds_dVb * gche) / T0; T9 = diffVds / Va; T0 = 1.0 + T9; Idsa = Idl * T0; dIdsa_dVg = T0 * dIdl_dVg - Idl * (dVdseff_dVg + T9 * dVa_dVg) / Va; dIdsa_dVd = T0 * dIdl_dVd + Idl * (1.0 - dVdseff_dVd - - T9 * dVa_dVd) / Va; + - T9 * dVa_dVd) / Va; dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va; T9 = diffVds / VASCBE; @@ -1225,33 +1217,33 @@ for (; model != NULL; model = model->BSIM3v32nextModel) Gm = T0 * dIdsa_dVg - Idsa * (dVdseff_dVg + T9 * dVASCBE_dVg) / VASCBE; Gds = T0 * dIdsa_dVd + Idsa * (1.0 - dVdseff_dVd - - T9 * dVASCBE_dVd) / VASCBE; + - T9 * dVASCBE_dVd) / VASCBE; Gmb = T0 * dIdsa_dVb - Idsa * (dVdseff_dVb - + T9 * dVASCBE_dVb) / VASCBE; + + T9 * dVASCBE_dVb) / VASCBE; Gds += Gm * dVgsteff_dVd; - Gmb += Gm * dVgsteff_dVb; - Gm *= dVgsteff_dVg; - Gmb *= dVbseff_dVb; + Gmb += Gm * dVgsteff_dVb; + Gm *= dVgsteff_dVg; + Gmb *= dVbseff_dVb; /* Substrate current begins */ tmp = pParam->BSIM3v32alpha0 + pParam->BSIM3v32alpha1 * Leff; if ((tmp <= 0.0) || (pParam->BSIM3v32beta0 <= 0.0)) - { Isub = Gbd = Gbb = Gbg = 0.0; + { Isub = Gbd = Gbb = Gbg = 0.0; } - else - { T2 = tmp / Leff; - if (diffVds > pParam->BSIM3v32beta0 / EXP_THRESHOLD) - { T0 = -pParam->BSIM3v32beta0 / diffVds; - T1 = T2 * diffVds * exp(T0); - T3 = T1 / diffVds * (T0 - 1.0); + else + { T2 = tmp / Leff; + if (diffVds > pParam->BSIM3v32beta0 / EXP_THRESHOLD) + { T0 = -pParam->BSIM3v32beta0 / diffVds; + T1 = T2 * diffVds * exp(T0); + T3 = T1 / diffVds * (T0 - 1.0); dT1_dVg = T3 * dVdseff_dVg; dT1_dVd = T3 * (dVdseff_dVd - 1.0); dT1_dVb = T3 * dVdseff_dVb; } - else - { T3 = T2 * MIN_EXP; - T1 = T3 * diffVds; + else + { T3 = T2 * MIN_EXP; + T1 = T3 * diffVds; dT1_dVg = -T3 * dVdseff_dVg; dT1_dVd = T3 * (1.0 - dVdseff_dVd); dT1_dVb = -T3 * dVdseff_dVb; @@ -1262,59 +1254,59 @@ for (; model != NULL; model = model->BSIM3v32nextModel) Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb; Gbd += Gbg * dVgsteff_dVd; - Gbb += Gbg * dVgsteff_dVb; - Gbg *= dVgsteff_dVg; - Gbb *= dVbseff_dVb; /* bug fixing */ + Gbb += Gbg * dVgsteff_dVb; + Gbg *= dVgsteff_dVg; + Gbb *= dVbseff_dVb; /* bug fixing */ } - + cdrain = Ids; here->BSIM3v32gds = Gds; here->BSIM3v32gm = Gm; here->BSIM3v32gmbs = Gmb; - + here->BSIM3v32gbbs = Gbb; here->BSIM3v32gbgs = Gbg; here->BSIM3v32gbds = Gbd; here->BSIM3v32csub = Isub; - /* BSIM3v32 thermal noise Qinv calculated from all capMod + /* BSIM3v32 thermal noise Qinv calculated from all capMod * 0, 1, 2 & 3 stored in here->BSIM3v32qinv 1/1998 */ if ((model->BSIM3v32xpart < 0) || (!ChargeComputationNeeded)) - { qgate = qdrn = qsrc = qbulk = 0.0; + { qgate = qdrn = qsrc = qbulk = 0.0; here->BSIM3v32cggb = here->BSIM3v32cgsb = here->BSIM3v32cgdb = 0.0; here->BSIM3v32cdgb = here->BSIM3v32cdsb = here->BSIM3v32cddb = 0.0; here->BSIM3v32cbgb = here->BSIM3v32cbsb = here->BSIM3v32cbdb = 0.0; - here->BSIM3v32cqdb = here->BSIM3v32cqsb = here->BSIM3v32cqgb + here->BSIM3v32cqdb = here->BSIM3v32cqsb = here->BSIM3v32cqgb = here->BSIM3v32cqbb = 0.0; here->BSIM3v32gtau = 0.0; goto finished; } - else if (model->BSIM3v32capMod == 0) - { + else if (model->BSIM3v32capMod == 0) + { if (Vbseff < 0.0) - { Vbseff = Vbs; + { Vbseff = Vbs; dVbseff_dVb = 1.0; } - else - { Vbseff = pParam->BSIM3v32phi - Phis; + else + { Vbseff = pParam->BSIM3v32phi - Phis; dVbseff_dVb = -dPhis_dVb; } Vfb = pParam->BSIM3v32vfbcv; - Vth = Vfb + pParam->BSIM3v32phi + pParam->BSIM3v32k1ox * sqrtPhis; + Vth = Vfb + pParam->BSIM3v32phi + pParam->BSIM3v32k1ox * sqrtPhis; Vgst = Vgs_eff - Vth; - dVth_dVb = pParam->BSIM3v32k1ox * dsqrtPhis_dVb; + dVth_dVb = pParam->BSIM3v32k1ox * dsqrtPhis_dVb; dVgst_dVb = -dVth_dVb; - dVgst_dVg = dVgs_eff_dVg; + dVgst_dVg = dVgs_eff_dVg; CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV; Arg1 = Vgs_eff - Vbseff - Vfb; if (Arg1 <= 0.0) - { qgate = CoxWL * Arg1; + { qgate = CoxWL * Arg1; qbulk = -qgate; qdrn = 0.0; @@ -1331,18 +1323,18 @@ for (; model != NULL; model = model->BSIM3v32nextModel) here->BSIM3v32cbsb = -here->BSIM3v32cgsb; here->BSIM3v32qinv = 0.0; } - else if (Vgst <= 0.0) - { T1 = 0.5 * pParam->BSIM3v32k1ox; - T2 = sqrt(T1 * T1 + Arg1); - qgate = CoxWL * pParam->BSIM3v32k1ox * (T2 - T1); + else if (Vgst <= 0.0) + { T1 = 0.5 * pParam->BSIM3v32k1ox; + T2 = sqrt(T1 * T1 + Arg1); + qgate = CoxWL * pParam->BSIM3v32k1ox * (T2 - T1); qbulk = -qgate; qdrn = 0.0; - T0 = CoxWL * T1 / T2; - here->BSIM3v32cggb = T0 * dVgs_eff_dVg; - here->BSIM3v32cgdb = 0.0; + T0 = CoxWL * T1 / T2; + here->BSIM3v32cggb = T0 * dVgs_eff_dVg; + here->BSIM3v32cgdb = 0.0; here->BSIM3v32cgsb = T0 * (dVbseff_dVb - dVgs_eff_dVg); - + here->BSIM3v32cdgb = 0.0; here->BSIM3v32cddb = 0.0; here->BSIM3v32cdsb = 0.0; @@ -1352,63 +1344,63 @@ for (; model != NULL; model = model->BSIM3v32nextModel) here->BSIM3v32cbsb = -here->BSIM3v32cgsb; here->BSIM3v32qinv = 0.0; } - else - { One_Third_CoxWL = CoxWL / 3.0; + else + { One_Third_CoxWL = CoxWL / 3.0; Two_Third_CoxWL = 2.0 * One_Third_CoxWL; AbulkCV = Abulk0 * pParam->BSIM3v32abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3v32abulkCVfactor * dAbulk0_dVb; - Vdsat = Vgst / AbulkCV; - dVdsat_dVg = dVgs_eff_dVg / AbulkCV; - dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV; + Vdsat = Vgst / AbulkCV; + dVdsat_dVg = dVgs_eff_dVg / AbulkCV; + dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV; if (model->BSIM3v32xpart > 0.5) - { /* 0/100 Charge partition model */ - if (Vdsat <= Vds) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3v32phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.0; + { /* 0/100 Charge partition model */ + if (Vdsat <= Vds) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3v32phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.0; - here->BSIM3v32cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); + here->BSIM3v32cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); here->BSIM3v32cgdb = 0.0; - + here->BSIM3v32cdgb = 0.0; here->BSIM3v32cddb = 0.0; here->BSIM3v32cdsb = 0.0; - here->BSIM3v32cbgb = -(here->BSIM3v32cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); + here->BSIM3v32cbgb = -(here->BSIM3v32cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); here->BSIM3v32cbdb = 0.0; here->BSIM3v32qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - T7 = 2.0 * Vds - T1 - 3.0 * T3; - T8 = T3 - T1 - 2.0 * Vds; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3v32phi - 0.5 * (Vds - T3)); - T10 = T4 * T8; - qdrn = T4 * T7; - qbulk = -(qgate + qdrn + T10); - + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + T7 = 2.0 * Vds - T1 - 3.0 * T3; + T8 = T3 - T1 - 2.0 * Vds; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3v32phi - 0.5 * (Vds - T3)); + T10 = T4 * T8; + qdrn = T4 * T7; + qbulk = -(qgate + qdrn + T10); + T5 = T3 / T1; here->BSIM3v32cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; T11 = -CoxWL * T5 * dVdsat_dVb; here->BSIM3v32cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T11 @@ -1420,7 +1412,7 @@ for (; model != NULL; model = model->BSIM3v32nextModel) T8 = T9 * T8; T9 = 2.0 * T4 * (1.0 - 3.0 * T5); here->BSIM3v32cdgb = (T7 * dAlphaz_dVg - T9 - * dVdsat_dVg) * dVgs_eff_dVg; + * dVdsat_dVg) * dVgs_eff_dVg; T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb; here->BSIM3v32cddb = T4 * (3.0 - 6.0 * T2 - 3.0 * T5); here->BSIM3v32cdsb = -(here->BSIM3v32cdgb + T12 @@ -1428,200 +1420,200 @@ for (; model != NULL; model = model->BSIM3v32nextModel) T9 = 2.0 * T4 * (1.0 + T5); T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb; - T12 = T4 * (2.0 * T2 + T5 - 1.0); + T12 = T4 * (2.0 * T2 + T5 - 1.0); T0 = -(T10 + T11 + T12); here->BSIM3v32cbgb = -(here->BSIM3v32cggb - + here->BSIM3v32cdgb + T10); - here->BSIM3v32cbdb = -(here->BSIM3v32cgdb - + here->BSIM3v32cddb + T12); + + here->BSIM3v32cdgb + T10); + here->BSIM3v32cbdb = -(here->BSIM3v32cgdb + + here->BSIM3v32cddb + T12); here->BSIM3v32cbsb = -(here->BSIM3v32cgsb - + here->BSIM3v32cdsb + T0); + + here->BSIM3v32cdsb + T0); here->BSIM3v32qinv = -(qgate + qbulk); } } - else if (model->BSIM3v32xpart < 0.5) - { /* 40/60 Charge partition model */ - if (Vds >= Vdsat) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3v32phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.4 * T2; + else if (model->BSIM3v32xpart < 0.5) + { /* 40/60 Charge partition model */ + if (Vds >= Vdsat) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3v32phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.4 * T2; - here->BSIM3v32cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); - here->BSIM3v32cgdb = 0.0; - - T3 = 0.4 * Two_Third_CoxWL; + here->BSIM3v32cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); + here->BSIM3v32cgdb = 0.0; + + T3 = 0.4 * Two_Third_CoxWL; here->BSIM3v32cdgb = -T3 * dVgs_eff_dVg; here->BSIM3v32cddb = 0.0; - T4 = T3 * dVth_dVb; + T4 = T3 * dVth_dVb; here->BSIM3v32cdsb = -(T4 + here->BSIM3v32cdgb); - here->BSIM3v32cbgb = -(here->BSIM3v32cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); + here->BSIM3v32cbgb = -(here->BSIM3v32cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); here->BSIM3v32cbdb = 0.0; here->BSIM3v32qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3v32phi - - 0.5 * (Vds - T3)); + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3v32phi + - 0.5 * (Vds - T3)); - T5 = T3 / T1; + T5 = T3 / T1; here->BSIM3v32cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; tmp = -CoxWL * T5 * dVdsat_dVb; here->BSIM3v32cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); - here->BSIM3v32cgsb = -(here->BSIM3v32cggb - + here->BSIM3v32cgdb + tmp); + here->BSIM3v32cgsb = -(here->BSIM3v32cggb + + here->BSIM3v32cgdb + tmp); - T6 = 1.0 / Vdsat; + T6 = 1.0 / Vdsat; dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); - T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * Vds - + 1.2 * Vds * Vds; - T8 = T2 / T1; - T7 = Vds - T1 - T8 * T6; - qdrn = T4 * T7; - T7 *= T9; - tmp = T8 / T1; - tmp1 = T4 * (2.0 - 4.0 * tmp * T6 - + T8 * (16.0 * Vdsat - 6.0 * Vds)); + T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * Vds + + 1.2 * Vds * Vds; + T8 = T2 / T1; + T7 = Vds - T1 - T8 * T6; + qdrn = T4 * T7; + T7 *= T9; + tmp = T8 / T1; + tmp1 = T4 * (2.0 - 4.0 * tmp * T6 + + T8 * (16.0 * Vdsat - 6.0 * Vds)); here->BSIM3v32cdgb = (T7 * dAlphaz_dVg - tmp1 - * dVdsat_dVg) * dVgs_eff_dVg; + * dVdsat_dVg) * dVgs_eff_dVg; T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb; here->BSIM3v32cddb = T4 * (2.0 - (1.0 / (3.0 * T1 - * T1) + 2.0 * tmp) * T6 + T8 - * (6.0 * Vdsat - 2.4 * Vds)); - here->BSIM3v32cdsb = -(here->BSIM3v32cdgb - + T10 + here->BSIM3v32cddb); + * T1) + 2.0 * tmp) * T6 + T8 + * (6.0 * Vdsat - 2.4 * Vds)); + here->BSIM3v32cdsb = -(here->BSIM3v32cdgb + + T10 + here->BSIM3v32cddb); - T7 = 2.0 * (T1 + T3); - qbulk = -(qgate - T4 * T7); - T7 *= T9; - T0 = 4.0 * T4 * (1.0 - T5); - T12 = (-T7 * dAlphaz_dVg - here->BSIM3v32cdgb - - T0 * dVdsat_dVg) * dVgs_eff_dVg; - T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb; - T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - - here->BSIM3v32cddb; + T7 = 2.0 * (T1 + T3); + qbulk = -(qgate - T4 * T7); + T7 *= T9; + T0 = 4.0 * T4 * (1.0 - T5); + T12 = (-T7 * dAlphaz_dVg - here->BSIM3v32cdgb + - T0 * dVdsat_dVg) * dVgs_eff_dVg; + T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb; + T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) + - here->BSIM3v32cddb; tmp = -(T10 + T11 + T12); - here->BSIM3v32cbgb = -(here->BSIM3v32cggb - + here->BSIM3v32cdgb + T12); + here->BSIM3v32cbgb = -(here->BSIM3v32cggb + + here->BSIM3v32cdgb + T12); here->BSIM3v32cbdb = -(here->BSIM3v32cgdb - + here->BSIM3v32cddb + T10); /* bug fix */ + + here->BSIM3v32cddb + T10); /* bug fix */ here->BSIM3v32cbsb = -(here->BSIM3v32cgsb - + here->BSIM3v32cdsb + tmp); + + here->BSIM3v32cdsb + tmp); here->BSIM3v32qinv = -(qgate + qbulk); } } - else - { /* 50/50 partitioning */ - if (Vds >= Vdsat) - { /* saturation region */ - T1 = Vdsat / 3.0; - qgate = CoxWL * (Vgs_eff - Vfb - - pParam->BSIM3v32phi - T1); - T2 = -Two_Third_CoxWL * Vgst; - qbulk = -(qgate + T2); - qdrn = 0.5 * T2; + else + { /* 50/50 partitioning */ + if (Vds >= Vdsat) + { /* saturation region */ + T1 = Vdsat / 3.0; + qgate = CoxWL * (Vgs_eff - Vfb + - pParam->BSIM3v32phi - T1); + T2 = -Two_Third_CoxWL * Vgst; + qbulk = -(qgate + T2); + qdrn = 0.5 * T2; + + here->BSIM3v32cggb = One_Third_CoxWL * (3.0 + - dVdsat_dVg) * dVgs_eff_dVg; + T2 = -One_Third_CoxWL * dVdsat_dVb; + here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); + here->BSIM3v32cgdb = 0.0; - here->BSIM3v32cggb = One_Third_CoxWL * (3.0 - - dVdsat_dVg) * dVgs_eff_dVg; - T2 = -One_Third_CoxWL * dVdsat_dVb; - here->BSIM3v32cgsb = -(here->BSIM3v32cggb + T2); - here->BSIM3v32cgdb = 0.0; - here->BSIM3v32cdgb = -One_Third_CoxWL * dVgs_eff_dVg; here->BSIM3v32cddb = 0.0; - T4 = One_Third_CoxWL * dVth_dVb; + T4 = One_Third_CoxWL * dVth_dVb; here->BSIM3v32cdsb = -(T4 + here->BSIM3v32cdgb); - here->BSIM3v32cbgb = -(here->BSIM3v32cggb - - Two_Third_CoxWL * dVgs_eff_dVg); - T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); - here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); + here->BSIM3v32cbgb = -(here->BSIM3v32cggb + - Two_Third_CoxWL * dVgs_eff_dVg); + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); + here->BSIM3v32cbsb = -(here->BSIM3v32cbgb + T3); here->BSIM3v32cbdb = 0.0; here->BSIM3v32qinv = -(qgate + qbulk); - } - else - { /* linear region */ - Alphaz = Vgst / Vdsat; - T1 = 2.0 * Vdsat - Vds; - T2 = Vds / (3.0 * T1); - T3 = T2 * Vds; - T9 = 0.25 * CoxWL; - T4 = T9 * Alphaz; - qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3v32phi - - 0.5 * (Vds - T3)); + } + else + { /* linear region */ + Alphaz = Vgst / Vdsat; + T1 = 2.0 * Vdsat - Vds; + T2 = Vds / (3.0 * T1); + T3 = T2 * Vds; + T9 = 0.25 * CoxWL; + T4 = T9 * Alphaz; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM3v32phi + - 0.5 * (Vds - T3)); - T5 = T3 / T1; + T5 = T3 / T1; here->BSIM3v32cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) - * dVgs_eff_dVg; + * dVgs_eff_dVg; tmp = -CoxWL * T5 * dVdsat_dVb; here->BSIM3v32cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); - here->BSIM3v32cgsb = -(here->BSIM3v32cggb - + here->BSIM3v32cgdb + tmp); + here->BSIM3v32cgsb = -(here->BSIM3v32cggb + + here->BSIM3v32cgdb + tmp); - T6 = 1.0 / Vdsat; + T6 = 1.0 / Vdsat; dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); - T7 = T1 + T3; - qdrn = -T4 * T7; - qbulk = - (qgate + qdrn + qdrn); - T7 *= T9; - T0 = T4 * (2.0 * T5 - 2.0); + T7 = T1 + T3; + qdrn = -T4 * T7; + qbulk = - (qgate + qdrn + qdrn); + T7 *= T9; + T0 = T4 * (2.0 * T5 - 2.0); here->BSIM3v32cdgb = (T0 * dVdsat_dVg - T7 - * dAlphaz_dVg) * dVgs_eff_dVg; - T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb; + * dAlphaz_dVg) * dVgs_eff_dVg; + T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb; here->BSIM3v32cddb = T4 * (1.0 - 2.0 * T2 - T5); here->BSIM3v32cdsb = -(here->BSIM3v32cdgb + T12 + here->BSIM3v32cddb); here->BSIM3v32cbgb = -(here->BSIM3v32cggb - + 2.0 * here->BSIM3v32cdgb); + + 2.0 * here->BSIM3v32cdgb); here->BSIM3v32cbdb = -(here->BSIM3v32cgdb - + 2.0 * here->BSIM3v32cddb); + + 2.0 * here->BSIM3v32cddb); here->BSIM3v32cbsb = -(here->BSIM3v32cgsb - + 2.0 * here->BSIM3v32cdsb); + + 2.0 * here->BSIM3v32cdsb); here->BSIM3v32qinv = -(qgate + qbulk); } - } - } - } - else - { if (Vbseff < 0.0) - { VbseffCV = Vbseff; + } + } + } + else + { if (Vbseff < 0.0) + { VbseffCV = Vbseff; dVbseffCV_dVb = 1.0; } - else - { VbseffCV = pParam->BSIM3v32phi - Phis; + else + { VbseffCV = pParam->BSIM3v32phi - Phis; dVbseffCV_dVb = -dPhis_dVb; } CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV - * pParam->BSIM3v32leffCV; + * pParam->BSIM3v32leffCV; /* Seperate VgsteffCV with noff and voffcv */ noff = n * pParam->BSIM3v32noff; @@ -1655,123 +1647,123 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dVgsteff_dVg *= dVgs_eff_dVg; } /* End of VgsteffCV */ - if (model->BSIM3v32capMod == 1) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Vfb = here->BSIM3v32vfbzb; - break; - case BSIM3v32V32: - Vfb = here->BSIM3v32vfbzb; - dVfb_dVb = dVfb_dVd = 0.0; - break; - default: - Vfb = Vth - pParam->BSIM3v32phi - pParam->BSIM3v32k1ox * sqrtPhis; - dVfb_dVb = dVth_dVb - pParam->BSIM3v32k1ox * dsqrtPhis_dVb; - dVfb_dVd = dVth_dVd; - } + if (model->BSIM3v32capMod == 1) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Vfb = here->BSIM3v32vfbzb; + break; + case BSIM3v32V32: + Vfb = here->BSIM3v32vfbzb; + dVfb_dVb = dVfb_dVd = 0.0; + break; + default: + Vfb = Vth - pParam->BSIM3v32phi - pParam->BSIM3v32k1ox * sqrtPhis; + dVfb_dVb = dVth_dVb - pParam->BSIM3v32k1ox * dsqrtPhis_dVb; + dVfb_dVd = dVth_dVd; + } Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff; if (Arg1 <= 0.0) - { qgate = CoxWL * Arg1; + { qgate = CoxWL * Arg1; Cgg = CoxWL * (dVgs_eff_dVg - dVgsteff_dVg); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Cgd = -CoxWL * dVgsteff_dVd; - Cgb = -CoxWL * (dVbseffCV_dVb + dVgsteff_dVb); - break; - case BSIM3v32V32: - default: - Cgd = -CoxWL * (dVfb_dVd + dVgsteff_dVd); - Cgb = -CoxWL * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); - } + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Cgd = -CoxWL * dVgsteff_dVd; + Cgb = -CoxWL * (dVbseffCV_dVb + dVgsteff_dVb); + break; + case BSIM3v32V32: + default: + Cgd = -CoxWL * (dVfb_dVd + dVgsteff_dVd); + Cgb = -CoxWL * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); + } } - else - { T0 = 0.5 * pParam->BSIM3v32k1ox; - T1 = sqrt(T0 * T0 + Arg1); + else + { T0 = 0.5 * pParam->BSIM3v32k1ox; + T1 = sqrt(T0 * T0 + Arg1); T2 = CoxWL * T0 / T1; - + qgate = CoxWL * pParam->BSIM3v32k1ox * (T1 - T0); Cgg = T2 * (dVgs_eff_dVg - dVgsteff_dVg); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Cgd = -T2 * dVgsteff_dVd; - Cgb = -T2 * (dVbseffCV_dVb + dVgsteff_dVb); - break; - case BSIM3v32V32: - default: - Cgd = -T2 * (dVfb_dVd + dVgsteff_dVd); - Cgb = -T2 * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); - } + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Cgd = -T2 * dVgsteff_dVd; + Cgb = -T2 * (dVbseffCV_dVb + dVgsteff_dVb); + break; + case BSIM3v32V32: + default: + Cgd = -T2 * (dVfb_dVd + dVgsteff_dVd); + Cgb = -T2 * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); + } } - qbulk = -qgate; - Cbg = -Cgg; - Cbd = -Cgd; - Cbb = -Cgb; + qbulk = -qgate; + Cbg = -Cgg; + Cbd = -Cgd; + Cbb = -Cgb; One_Third_CoxWL = CoxWL / 3.0; Two_Third_CoxWL = 2.0 * One_Third_CoxWL; AbulkCV = Abulk0 * pParam->BSIM3v32abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3v32abulkCVfactor * dAbulk0_dVb; - VdsatCV = Vgsteff / AbulkCV; + VdsatCV = Vgsteff / AbulkCV; if (VdsatCV < Vds) - { dVdsatCV_dVg = 1.0 / AbulkCV; - dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; - T0 = Vgsteff - VdsatCV / 3.0; + { dVdsatCV_dVg = 1.0 / AbulkCV; + dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; + T0 = Vgsteff - VdsatCV / 3.0; dT0_dVg = 1.0 - dVdsatCV_dVg / 3.0; dT0_dVb = -dVdsatCV_dVb / 3.0; qgate += CoxWL * T0; - Cgg1 = CoxWL * dT0_dVg; + Cgg1 = CoxWL * dT0_dVg; Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb; Cgd1 = Cgg1 * dVgsteff_dVd; - Cgg1 *= dVgsteff_dVg; - Cgg += Cgg1; - Cgb += Cgb1; - Cgd += Cgd1; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; - T0 = VdsatCV - Vgsteff; - dT0_dVg = dVdsatCV_dVg - 1.0; - dT0_dVb = dVdsatCV_dVb; + T0 = VdsatCV - Vgsteff; + dT0_dVg = dVdsatCV_dVg - 1.0; + dT0_dVb = dVdsatCV_dVb; qbulk += One_Third_CoxWL * T0; Cbg1 = One_Third_CoxWL * dT0_dVg; - Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb; - Cbd1 = Cbg1 * dVgsteff_dVd; - Cbg1 *= dVgsteff_dVg; - Cbg += Cbg1; - Cbb += Cbb1; + Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb; + Cbd1 = Cbg1 * dVgsteff_dVd; + Cbg1 *= dVgsteff_dVg; + Cbg += Cbg1; + Cbb += Cbb1; Cbd += Cbd1; if (model->BSIM3v32xpart > 0.5) - T0 = -Two_Third_CoxWL; + T0 = -Two_Third_CoxWL; else if (model->BSIM3v32xpart < 0.5) - T0 = -0.4 * CoxWL; + T0 = -0.4 * CoxWL; else - T0 = -One_Third_CoxWL; + T0 = -One_Third_CoxWL; qsrc = T0 * Vgsteff; Csg = T0 * dVgsteff_dVg; Csb = T0 * dVgsteff_dVb; Csd = T0 * dVgsteff_dVd; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; } - else - { T0 = AbulkCV * Vds; + else + { T0 = AbulkCV * Vds; T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20); - T2 = Vds / T1; - T3 = T0 * T2; + T2 = Vds / T1; + T3 = T0 * T2; dT3_dVg = -12.0 * T2 * T2 * AbulkCV; dT3_dVd = 6.0 * T0 * (4.0 * Vgsteff - T0) / T1 / T1 - 0.5; dT3_dVb = 12.0 * T2 * T2 * dAbulkCV_dVb * Vgsteff; @@ -1780,229 +1772,229 @@ for (; model != NULL; model = model->BSIM3v32nextModel) Cgg1 = CoxWL * (1.0 + dT3_dVg); Cgb1 = CoxWL * dT3_dVb + Cgg1 * dVgsteff_dVb; Cgd1 = CoxWL * dT3_dVd + Cgg1 * dVgsteff_dVd; - Cgg1 *= dVgsteff_dVg; - Cgg += Cgg1; - Cgb += Cgb1; - Cgd += Cgd1; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; qbulk += CoxWL * (1.0 - AbulkCV) * (0.5 * Vds - T3); - Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg); - Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb - + (0.5 * Vds - T3) * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb; - Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd - + Cbg1 * dVgsteff_dVd; - Cbg1 *= dVgsteff_dVg; - Cbg += Cbg1; - Cbb += Cbb1; - Cbd += Cbd1; + Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg); + Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb + + (0.5 * Vds - T3) * dAbulkCV_dVb) + + Cbg1 * dVgsteff_dVb; + Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd + + Cbg1 * dVgsteff_dVd; + Cbg1 *= dVgsteff_dVg; + Cbg += Cbg1; + Cbb += Cbb1; + Cbd += Cbd1; if (model->BSIM3v32xpart > 0.5) - { /* 0/100 Charge petition model */ - T1 = T1 + T1; + { /* 0/100 Charge petition model */ + T1 = T1 + T1; qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - - T0 * T0 / T1); - Csg = -CoxWL * (0.5 + 24.0 * T0 * Vds / T1 / T1 - * AbulkCV); + - T0 * T0 / T1); + Csg = -CoxWL * (0.5 + 24.0 * T0 * Vds / T1 / T1 + * AbulkCV); Csb = -CoxWL * (0.25 * Vds * dAbulkCV_dVb - - 12.0 * T0 * Vds / T1 / T1 * (4.0 * Vgsteff - T0) - * dAbulkCV_dVb) + Csg * dVgsteff_dVb; - Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0 - / T1 / T1 * (4.0 * Vgsteff - T0)) - + Csg * dVgsteff_dVd; - Csg *= dVgsteff_dVg; + - 12.0 * T0 * Vds / T1 / T1 * (4.0 * Vgsteff - T0) + * dAbulkCV_dVb) + Csg * dVgsteff_dVb; + Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0 + / T1 / T1 * (4.0 * Vgsteff - T0)) + + Csg * dVgsteff_dVd; + Csg *= dVgsteff_dVg; } - else if (model->BSIM3v32xpart < 0.5) - { /* 40/60 Charge petition model */ - T1 = T1 / 12.0; - T2 = 0.5 * CoxWL / (T1 * T1); - T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff - * (Vgsteff - 4.0 * T0 / 3.0)) - - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T2 * T3; - T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) - + 0.4 * T0 * T0; - Csg = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 - * Vgsteff - 8.0 * T0 / 3.0) - + 2.0 * T0 * T0 / 3.0); - Csb = (qsrc / T1 * Vds + T2 * T4 * Vds) * dAbulkCV_dVb - + Csg * dVgsteff_dVb; - Csd = (qsrc / T1 + T2 * T4) * AbulkCV - + Csg * dVgsteff_dVd; - Csg *= dVgsteff_dVg; + else if (model->BSIM3v32xpart < 0.5) + { /* 40/60 Charge petition model */ + T1 = T1 / 12.0; + T2 = 0.5 * CoxWL / (T1 * T1); + T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff + * (Vgsteff - 4.0 * T0 / 3.0)) + - 2.0 * T0 * T0 * T0 / 15.0; + qsrc = -T2 * T3; + T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + + 0.4 * T0 * T0; + Csg = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 + * Vgsteff - 8.0 * T0 / 3.0) + + 2.0 * T0 * T0 / 3.0); + Csb = (qsrc / T1 * Vds + T2 * T4 * Vds) * dAbulkCV_dVb + + Csg * dVgsteff_dVb; + Csd = (qsrc / T1 + T2 * T4) * AbulkCV + + Csg * dVgsteff_dVd; + Csg *= dVgsteff_dVg; } - else - { /* 50/50 Charge petition model */ + else + { /* 50/50 Charge petition model */ qsrc = -0.5 * (qgate + qbulk); Csg = -0.5 * (Cgg1 + Cbg1); - Csb = -0.5 * (Cgb1 + Cbb1); - Csd = -0.5 * (Cgd1 + Cbd1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); } - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; } qdrn = -(qgate + qbulk + qsrc); here->BSIM3v32cggb = Cgg; - here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3v32cgdb = Cgd; + here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3v32cgdb = Cgd; here->BSIM3v32cdgb = -(Cgg + Cbg + Csg); - here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3v32cddb = -(Cgd + Cbd + Csd); + here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3v32cddb = -(Cgd + Cbd + Csd); here->BSIM3v32cbgb = Cbg; - here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3v32cbdb = Cbd; + here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3v32cbdb = Cbd; here->BSIM3v32qinv = -(qgate + qbulk); - } + } - else if (model->BSIM3v32capMod == 2) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Vfb = here->BSIM3v32vfbzb; - break; - case BSIM3v32V32: - Vfb = here->BSIM3v32vfbzb; - dVfb_dVb = dVfb_dVd = 0.0; - break; - default: /* old code prior to v3.2 */ - Vfb = Vth - pParam->BSIM3v32phi - pParam->BSIM3v32k1ox * sqrtPhis; - dVfb_dVb = dVth_dVb - pParam->BSIM3v32k1ox * dsqrtPhis_dVb; - dVfb_dVd = dVth_dVd; - } + else if (model->BSIM3v32capMod == 2) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Vfb = here->BSIM3v32vfbzb; + break; + case BSIM3v32V32: + Vfb = here->BSIM3v32vfbzb; + dVfb_dVb = dVfb_dVd = 0.0; + break; + default: /* old code prior to v3.2 */ + Vfb = Vth - pParam->BSIM3v32phi - pParam->BSIM3v32k1ox * sqrtPhis; + dVfb_dVb = dVth_dVb - pParam->BSIM3v32k1ox * dsqrtPhis_dVb; + dVfb_dVd = dVth_dVd; + } V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3; - if (Vfb <= 0.0) - { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); - T2 = -DELTA_3 / T0; - } - else - { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb); - T2 = DELTA_3 / T0; - } + if (Vfb <= 0.0) + { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); + T2 = -DELTA_3 / T0; + } + else + { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb); + T2 = DELTA_3 / T0; + } - T1 = 0.5 * (1.0 + V3 / T0); - Vfbeff = Vfb - 0.5 * (V3 + T0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - /* Do nothing */ - break; - case BSIM3v32V32: - default: - dVfbeff_dVd = (1.0 - T1 - T2) * dVfb_dVd; - } - dVfbeff_dVg = T1 * dVgs_eff_dVg; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - dVfbeff_dVb = -T1 * dVbseffCV_dVb; - break; - case BSIM3v32V32: - default: - dVfbeff_dVb = (1.0 - T1 - T2) * dVfb_dVb - T1 * dVbseffCV_dVb; - } - Qac0 = CoxWL * (Vfbeff - Vfb); - dQac0_dVg = CoxWL * dVfbeff_dVg; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - /* Do nothing */ - break; - case BSIM3v32V32: - default: - dQac0_dVd = CoxWL * (dVfbeff_dVd - dVfb_dVd); - } - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - dQac0_dVb = CoxWL * dVfbeff_dVb; - break; - case BSIM3v32V32: - default: - dQac0_dVb = CoxWL * (dVfbeff_dVb - dVfb_dVb); - } + T1 = 0.5 * (1.0 + V3 / T0); + Vfbeff = Vfb - 0.5 * (V3 + T0); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + /* Do nothing */ + break; + case BSIM3v32V32: + default: + dVfbeff_dVd = (1.0 - T1 - T2) * dVfb_dVd; + } + dVfbeff_dVg = T1 * dVgs_eff_dVg; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + dVfbeff_dVb = -T1 * dVbseffCV_dVb; + break; + case BSIM3v32V32: + default: + dVfbeff_dVb = (1.0 - T1 - T2) * dVfb_dVb - T1 * dVbseffCV_dVb; + } + Qac0 = CoxWL * (Vfbeff - Vfb); + dQac0_dVg = CoxWL * dVfbeff_dVg; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + /* Do nothing */ + break; + case BSIM3v32V32: + default: + dQac0_dVd = CoxWL * (dVfbeff_dVd - dVfb_dVd); + } + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + dQac0_dVb = CoxWL * dVfbeff_dVb; + break; + case BSIM3v32V32: + default: + dQac0_dVb = CoxWL * (dVfbeff_dVb - dVfb_dVb); + } T0 = 0.5 * pParam->BSIM3v32k1ox; - T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; if (pParam->BSIM3v32k1ox == 0.0) { T1 = 0.0; T2 = 0.0; } - else if (T3 < 0.0) - { T1 = T0 + T3 / pParam->BSIM3v32k1ox; + else if (T3 < 0.0) + { T1 = T0 + T3 / pParam->BSIM3v32k1ox; T2 = CoxWL; - } - else - { T1 = sqrt(T0 * T0 + T3); + } + else + { T1 = sqrt(T0 * T0 + T3); T2 = CoxWL * T0 / T1; - } + } - Qsub0 = CoxWL * pParam->BSIM3v32k1ox * (T1 - T0); + Qsub0 = CoxWL * pParam->BSIM3v32k1ox * (T1 - T0); dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - dQsub0_dVd = -T2 * dVgsteff_dVd; - break; - case BSIM3v32V32: - default: - dQsub0_dVd = -T2 * (dVfbeff_dVd + dVgsteff_dVd); - } - dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + dQsub0_dVd = -T2 * dVgsteff_dVd; + break; + case BSIM3v32V32: + default: + dQsub0_dVd = -T2 * (dVfbeff_dVd + dVgsteff_dVd); + } + dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + dVgsteff_dVb); AbulkCV = Abulk0 * pParam->BSIM3v32abulkCVfactor; dAbulkCV_dVb = pParam->BSIM3v32abulkCVfactor * dAbulk0_dVb; - VdsatCV = Vgsteff / AbulkCV; + VdsatCV = Vgsteff / AbulkCV; - V4 = VdsatCV - Vds - DELTA_4; - T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); - VdseffCV = VdsatCV - 0.5 * (V4 + T0); - T1 = 0.5 * (1.0 + V4 / T0); - T2 = DELTA_4 / T0; - T3 = (1.0 - T1 - T2) / AbulkCV; - dVdseffCV_dVg = T3; - dVdseffCV_dVd = T1; - dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - /* Added to eliminate non-zero VdseffCV at Vds=0.0 */ - if (Vds == 0.0) - { - VdseffCV = 0.0; - dVdseffCV_dVg = 0.0; - dVdseffCV_dVb = 0.0; - } - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } + V4 = VdsatCV - Vds - DELTA_4; + T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); + VdseffCV = VdsatCV - 0.5 * (V4 + T0); + T1 = 0.5 * (1.0 + V4 / T0); + T2 = DELTA_4 / T0; + T3 = (1.0 - T1 - T2) / AbulkCV; + dVdseffCV_dVg = T3; + dVdseffCV_dVd = T1; + dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + /* Added to eliminate non-zero VdseffCV at Vds=0.0 */ + if (Vds == 0.0) + { + VdseffCV = 0.0; + dVdseffCV_dVg = 0.0; + dVdseffCV_dVb = 0.0; + } + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } - T0 = AbulkCV * VdseffCV; + T0 = AbulkCV * VdseffCV; T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20); - T2 = VdseffCV / T1; - T3 = T0 * T2; + T2 = VdseffCV / T1; + T3 = T0 * T2; T4 = (1.0 - 12.0 * T2 * T2 * AbulkCV); T5 = (6.0 * T0 * (4.0 * Vgsteff - T0) / (T1 * T1) - 0.5); @@ -2013,129 +2005,129 @@ for (; model != NULL; model = model->BSIM3v32nextModel) Cgg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); Cgd1 = CoxWL * T5 * dVdseffCV_dVd + Cgg1 * dVgsteff_dVd; Cgb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cgg1 * dVgsteff_dVb; - Cgg1 *= dVgsteff_dVg; + + Cgg1 * dVgsteff_dVb; + Cgg1 *= dVgsteff_dVg; - T7 = 1.0 - AbulkCV; + T7 = 1.0 - AbulkCV; qbulk = CoxWL * T7 * (0.5 * VdseffCV - T3); - T4 = -T7 * (T4 - 1.0); - T5 = -T7 * T5; - T6 = -(T7 * T6 + (0.5 * VdseffCV - T3)); + T4 = -T7 * (T4 - 1.0); + T5 = -T7 * T5; + T6 = -(T7 * T6 + (0.5 * VdseffCV - T3)); Cbg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); Cbd1 = CoxWL * T5 * dVdseffCV_dVd + Cbg1 * dVgsteff_dVd; Cbb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb; - Cbg1 *= dVgsteff_dVg; + + Cbg1 * dVgsteff_dVb; + Cbg1 *= dVgsteff_dVg; if (model->BSIM3v32xpart > 0.5) - { /* 0/100 Charge petition model */ - T1 = T1 + T1; + { /* 0/100 Charge petition model */ + T1 = T1 + T1; qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - - T0 * T0 / T1); - T7 = (4.0 * Vgsteff - T0) / (T1 * T1); - T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1)); - T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7); + - T0 * T0 / T1); + T7 = (4.0 * Vgsteff - T0) / (T1 * T1); + T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1)); + T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7); T6 = -(0.25 * VdseffCV - 12.0 * T0 * VdseffCV * T7); Csg = CoxWL * (T4 + T5 * dVdseffCV_dVg); Csd = CoxWL * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; Csb = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb; - Csg *= dVgsteff_dVg; + + Csg * dVgsteff_dVb; + Csg *= dVgsteff_dVg; } - else if (model->BSIM3v32xpart < 0.5) - { /* 40/60 Charge petition model */ - T1 = T1 / 12.0; - T2 = 0.5 * CoxWL / (T1 * T1); - T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff - * (Vgsteff - 4.0 * T0 / 3.0)) - - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T2 * T3; - T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) - + 0.4 * T0 * T0; - T4 = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 - * Vgsteff - 8.0 * T0 / 3.0) - + 2.0 * T0 * T0 / 3.0); - T5 = (qsrc / T1 + T2 * T7) * AbulkCV; - T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV); + else if (model->BSIM3v32xpart < 0.5) + { /* 40/60 Charge petition model */ + T1 = T1 / 12.0; + T2 = 0.5 * CoxWL / (T1 * T1); + T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff + * (Vgsteff - 4.0 * T0 / 3.0)) + - 2.0 * T0 * T0 * T0 / 15.0; + qsrc = -T2 * T3; + T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + + 0.4 * T0 * T0; + T4 = -2.0 * qsrc / T1 - T2 * (Vgsteff * (3.0 + * Vgsteff - 8.0 * T0 / 3.0) + + 2.0 * T0 * T0 / 3.0); + T5 = (qsrc / T1 + T2 * T7) * AbulkCV; + T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV); Csg = (T4 + T5 * dVdseffCV_dVg); Csd = T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; Csb = (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb; - Csg *= dVgsteff_dVg; + + Csg * dVgsteff_dVb; + Csg *= dVgsteff_dVg; } - else - { /* 50/50 Charge petition model */ + else + { /* 50/50 Charge petition model */ qsrc = -0.5 * (qgate + qbulk); Csg = -0.5 * (Cgg1 + Cbg1); - Csb = -0.5 * (Cgb1 + Cbb1); - Csd = -0.5 * (Cgd1 + Cbd1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); } - qgate += Qac0 + Qsub0; - qbulk -= (Qac0 + Qsub0); + qgate += Qac0 + Qsub0; + qbulk -= (Qac0 + Qsub0); qdrn = -(qgate + qbulk + qsrc); - Cgg = dQac0_dVg + dQsub0_dVg + Cgg1; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Cgd = dQsub0_dVd + Cgd1; - break; - case BSIM3v32V32: - default: - Cgd = dQac0_dVd + dQsub0_dVd + Cgd1; - } - Cgb = dQac0_dVb + dQsub0_dVb + Cgb1; + Cgg = dQac0_dVg + dQsub0_dVg + Cgg1; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Cgd = dQsub0_dVd + Cgd1; + break; + case BSIM3v32V32: + default: + Cgd = dQac0_dVd + dQsub0_dVd + Cgd1; + } + Cgb = dQac0_dVb + dQsub0_dVb + Cgb1; - Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - Cbd = Cbd1 - dQsub0_dVd; - break; - case BSIM3v32V32: - default: - Cbd = Cbd1 - dQac0_dVd - dQsub0_dVd; - } - Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; + Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + Cbd = Cbd1 - dQsub0_dVd; + break; + case BSIM3v32V32: + default: + Cbd = Cbd1 - dQac0_dVd - dQsub0_dVd; + } + Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; here->BSIM3v32cggb = Cgg; - here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3v32cgdb = Cgd; + here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3v32cgdb = Cgd; here->BSIM3v32cdgb = -(Cgg + Cbg + Csg); - here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3v32cddb = -(Cgd + Cbd + Csd); + here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3v32cddb = -(Cgd + Cbd + Csd); here->BSIM3v32cbgb = Cbg; - here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3v32cbdb = Cbd; + here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3v32cbdb = Cbd; here->BSIM3v32qinv = qinoi; - } + } /* New Charge-Thickness capMod (CTM) begins */ - else if (model->BSIM3v32capMod == 3) - { V3 = here->BSIM3v32vfbzb - Vgs_eff + VbseffCV - DELTA_3; - if (here->BSIM3v32vfbzb <= 0.0) - { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * here->BSIM3v32vfbzb); - T2 = -DELTA_3 / T0; - } - else - { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * here->BSIM3v32vfbzb); - T2 = DELTA_3 / T0; - } + else if (model->BSIM3v32capMod == 3) + { V3 = here->BSIM3v32vfbzb - Vgs_eff + VbseffCV - DELTA_3; + if (here->BSIM3v32vfbzb <= 0.0) + { T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * here->BSIM3v32vfbzb); + T2 = -DELTA_3 / T0; + } + else + { T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * here->BSIM3v32vfbzb); + T2 = DELTA_3 / T0; + } - T1 = 0.5 * (1.0 + V3 / T0); - Vfbeff = here->BSIM3v32vfbzb - 0.5 * (V3 + T0); - dVfbeff_dVg = T1 * dVgs_eff_dVg; - dVfbeff_dVb = -T1 * dVbseffCV_dVb; + T1 = 0.5 * (1.0 + V3 / T0); + Vfbeff = here->BSIM3v32vfbzb - 0.5 * (V3 + T0); + dVfbeff_dVg = T1 * dVgs_eff_dVg; + dVfbeff_dVb = -T1 * dVbseffCV_dVb; Cox = model->BSIM3v32cox; Tox = 1.0e8 * model->BSIM3v32tox; @@ -2180,8 +2172,8 @@ for (; model != NULL; model = model->BSIM3v32nextModel) QovCox = Qac0 / Coxeff; dQac0_dVg = CoxWLcen * dVfbeff_dVg + QovCox * dCoxeff_dVg; - dQac0_dVb = CoxWLcen * dVfbeff_dVb - + QovCox * dCoxeff_dVb; + dQac0_dVb = CoxWLcen * dVfbeff_dVb + + QovCox * dCoxeff_dVb; T0 = 0.5 * pParam->BSIM3v32k1ox; T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; @@ -2206,138 +2198,138 @@ for (; model != NULL; model = model->BSIM3v32nextModel) dQsub0_dVb = -T2 * (dVfbeff_dVb + dVbseffCV_dVb + dVgsteff_dVb) + QovCox * dCoxeff_dVb; - /* Gate-bias dependent delta Phis begins */ - if (pParam->BSIM3v32k1ox <= 0.0) - { Denomi = 0.25 * pParam->BSIM3v32moin * Vtm; + /* Gate-bias dependent delta Phis begins */ + if (pParam->BSIM3v32k1ox <= 0.0) + { Denomi = 0.25 * pParam->BSIM3v32moin * Vtm; T0 = 0.5 * pParam->BSIM3v32sqrtPhi; - } - else - { Denomi = pParam->BSIM3v32moin * Vtm - * pParam->BSIM3v32k1ox * pParam->BSIM3v32k1ox; + } + else + { Denomi = pParam->BSIM3v32moin * Vtm + * pParam->BSIM3v32k1ox * pParam->BSIM3v32k1ox; T0 = pParam->BSIM3v32k1ox * pParam->BSIM3v32sqrtPhi; - } + } T1 = 2.0 * T0 + Vgsteff; - DeltaPhi = Vtm * log(1.0 + T1 * Vgsteff / Denomi); - dDeltaPhi_dVg = 2.0 * Vtm * (T1 -T0) / (Denomi + T1 * Vgsteff); - dDeltaPhi_dVd = dDeltaPhi_dVg * dVgsteff_dVd; - dDeltaPhi_dVb = dDeltaPhi_dVg * dVgsteff_dVb; - /* End of delta Phis */ + DeltaPhi = Vtm * log(1.0 + T1 * Vgsteff / Denomi); + dDeltaPhi_dVg = 2.0 * Vtm * (T1 -T0) / (Denomi + T1 * Vgsteff); + dDeltaPhi_dVd = dDeltaPhi_dVg * dVgsteff_dVd; + dDeltaPhi_dVb = dDeltaPhi_dVg * dVgsteff_dVb; + /* End of delta Phis */ T3 = 4.0 * (Vth - here->BSIM3v32vfbzb - pParam->BSIM3v32phi); Tox += Tox; if (T3 >= 0.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - T0 = (Vgsteff + T3) / Tox; - dT0_dVd = (dVgsteff_dVd + 4.0 * dVth_dVd) / Tox; - dT0_dVb = (dVgsteff_dVb + 4.0 * dVth_dVb) / Tox; - break; - case BSIM3v32V32: - default: - T0 = (Vgsteff + T3) / Tox; - } + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + T0 = (Vgsteff + T3) / Tox; + dT0_dVd = (dVgsteff_dVd + 4.0 * dVth_dVd) / Tox; + dT0_dVb = (dVgsteff_dVb + 4.0 * dVth_dVb) / Tox; + break; + case BSIM3v32V32: + default: + T0 = (Vgsteff + T3) / Tox; + } } else - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - T0 = (Vgsteff + 1.0e-20) / Tox; - dT0_dVd = dVgsteff_dVd / Tox; - dT0_dVb = dVgsteff_dVb / Tox; - break; - case BSIM3v32V32: - default: - T0 = (Vgsteff + 1.0e-20) / Tox; - } + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + T0 = (Vgsteff + 1.0e-20) / Tox; + dT0_dVd = dVgsteff_dVd / Tox; + dT0_dVb = dVgsteff_dVb / Tox; + break; + case BSIM3v32V32: + default: + T0 = (Vgsteff + 1.0e-20) / Tox; + } } tmp = exp(0.7 * log(T0)); T1 = 1.0 + tmp; T2 = 0.7 * tmp / (T0 * Tox); Tcen = 1.9e-9 / T1; dTcen_dVg = -1.9e-9 * T2 / T1 /T1; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - dTcen_dVd = Tox * dTcen_dVg; - dTcen_dVb = dTcen_dVd * dT0_dVb; - dTcen_dVd *= dT0_dVd; - break; - case BSIM3v32V32: - default: - dTcen_dVd = dTcen_dVg * (4.0 * dVth_dVd + dVgsteff_dVd); - dTcen_dVb = dTcen_dVg * (4.0 * dVth_dVb + dVgsteff_dVb); - } + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + dTcen_dVd = Tox * dTcen_dVg; + dTcen_dVb = dTcen_dVd * dT0_dVb; + dTcen_dVd *= dT0_dVd; + break; + case BSIM3v32V32: + default: + dTcen_dVd = dTcen_dVg * (4.0 * dVth_dVd + dVgsteff_dVd); + dTcen_dVb = dTcen_dVg * (4.0 * dVth_dVb + dVgsteff_dVb); + } dTcen_dVg *= dVgsteff_dVg; - Ccen = EPSSI / Tcen; - T0 = Cox / (Cox + Ccen); - Coxeff = T0 * Ccen; - T1 = -Ccen / Tcen; - dCoxeff_dVg = T0 * T0 * T1; - dCoxeff_dVd = dCoxeff_dVg * dTcen_dVd; - dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; - dCoxeff_dVg *= dTcen_dVg; - CoxWLcen = CoxWL * Coxeff / Cox; + Ccen = EPSSI / Tcen; + T0 = Cox / (Cox + Ccen); + Coxeff = T0 * Ccen; + T1 = -Ccen / Tcen; + dCoxeff_dVg = T0 * T0 * T1; + dCoxeff_dVd = dCoxeff_dVg * dTcen_dVd; + dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; + dCoxeff_dVg *= dTcen_dVg; + CoxWLcen = CoxWL * Coxeff / Cox; - AbulkCV = Abulk0 * pParam->BSIM3v32abulkCVfactor; - dAbulkCV_dVb = pParam->BSIM3v32abulkCVfactor * dAbulk0_dVb; - VdsatCV = (Vgsteff - DeltaPhi) / AbulkCV; - V4 = VdsatCV - Vds - DELTA_4; - T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); - VdseffCV = VdsatCV - 0.5 * (V4 + T0); - T1 = 0.5 * (1.0 + V4 / T0); - T2 = DELTA_4 / T0; - T3 = (1.0 - T1 - T2) / AbulkCV; - T4 = T3 * ( 1.0 - dDeltaPhi_dVg); - dVdseffCV_dVg = T4; - dVdseffCV_dVd = T1; - dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - /* Added to eliminate non-zero VdseffCV at Vds=0.0 */ - if (Vds == 0.0) - { - VdseffCV = 0.0; - dVdseffCV_dVg = 0.0; - dVdseffCV_dVb = 0.0; - } - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } + AbulkCV = Abulk0 * pParam->BSIM3v32abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3v32abulkCVfactor * dAbulk0_dVb; + VdsatCV = (Vgsteff - DeltaPhi) / AbulkCV; + V4 = VdsatCV - Vds - DELTA_4; + T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); + VdseffCV = VdsatCV - 0.5 * (V4 + T0); + T1 = 0.5 * (1.0 + V4 / T0); + T2 = DELTA_4 / T0; + T3 = (1.0 - T1 - T2) / AbulkCV; + T4 = T3 * ( 1.0 - dDeltaPhi_dVg); + dVdseffCV_dVg = T4; + dVdseffCV_dVd = T1; + dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + /* Added to eliminate non-zero VdseffCV at Vds=0.0 */ + if (Vds == 0.0) + { + VdseffCV = 0.0; + dVdseffCV_dVg = 0.0; + dVdseffCV_dVb = 0.0; + } + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } T0 = AbulkCV * VdseffCV; - T1 = Vgsteff - DeltaPhi; + T1 = Vgsteff - DeltaPhi; T2 = 12.0 * (T1 - 0.5 * T0 + 1.0e-20); T3 = T0 / T2; T4 = 1.0 - 12.0 * T3 * T3; T5 = AbulkCV * (6.0 * T0 * (4.0 * T1 - T0) / (T2 * T2) - 0.5); - T6 = T5 * VdseffCV / AbulkCV; + T6 = T5 * VdseffCV / AbulkCV; qgate = qinoi = CoxWLcen * (T1 - T0 * (0.5 - T3)); - QovCox = qgate / Coxeff; - Cgg1 = CoxWLcen * (T4 * (1.0 - dDeltaPhi_dVg) - + T5 * dVdseffCV_dVg); - Cgd1 = CoxWLcen * T5 * dVdseffCV_dVd + Cgg1 - * dVgsteff_dVd + QovCox * dCoxeff_dVd; - Cgb1 = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Cgg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Cgg1 = Cgg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; + QovCox = qgate / Coxeff; + Cgg1 = CoxWLcen * (T4 * (1.0 - dDeltaPhi_dVg) + + T5 * dVdseffCV_dVg); + Cgd1 = CoxWLcen * T5 * dVdseffCV_dVd + Cgg1 + * dVgsteff_dVd + QovCox * dCoxeff_dVd; + Cgb1 = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) + + Cgg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Cgg1 = Cgg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; T7 = 1.0 - AbulkCV; @@ -2347,95 +2339,95 @@ for (; model != NULL; model = model->BSIM3v32nextModel) T11 = -T7 * T5 / AbulkCV; T12 = -(T9 * T1 / AbulkCV + VdseffCV * (0.5 - T0 / T2)); - qbulk = CoxWLcen * T7 * (0.5 * VdseffCV - T0 * VdseffCV / T2); - QovCox = qbulk / Coxeff; - Cbg1 = CoxWLcen * (T10 + T11 * dVdseffCV_dVg); - Cbd1 = CoxWLcen * T11 * dVdseffCV_dVd + Cbg1 - * dVgsteff_dVd + QovCox * dCoxeff_dVd; - Cbb1 = CoxWLcen * (T11 * dVdseffCV_dVb + T12 * dAbulkCV_dVb) - + Cbg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Cbg1 = Cbg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; + qbulk = CoxWLcen * T7 * (0.5 * VdseffCV - T0 * VdseffCV / T2); + QovCox = qbulk / Coxeff; + Cbg1 = CoxWLcen * (T10 + T11 * dVdseffCV_dVg); + Cbd1 = CoxWLcen * T11 * dVdseffCV_dVd + Cbg1 + * dVgsteff_dVd + QovCox * dCoxeff_dVd; + Cbb1 = CoxWLcen * (T11 * dVdseffCV_dVb + T12 * dAbulkCV_dVb) + + Cbg1 * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Cbg1 = Cbg1 * dVgsteff_dVg + QovCox * dCoxeff_dVg; if (model->BSIM3v32xpart > 0.5) - { /* 0/100 partition */ - qsrc = -CoxWLcen * (T1 / 2.0 + T0 / 4.0 - - 0.5 * T0 * T0 / T2); - QovCox = qsrc / Coxeff; - T2 += T2; - T3 = T2 * T2; - T7 = -(0.25 - 12.0 * T0 * (4.0 * T1 - T0) / T3); - T4 = -(0.5 + 24.0 * T0 * T0 / T3) * (1.0 - dDeltaPhi_dVg); - T5 = T7 * AbulkCV; - T6 = T7 * VdseffCV; + { /* 0/100 partition */ + qsrc = -CoxWLcen * (T1 / 2.0 + T0 / 4.0 + - 0.5 * T0 * T0 / T2); + QovCox = qsrc / Coxeff; + T2 += T2; + T3 = T2 * T2; + T7 = -(0.25 - 12.0 * T0 * (4.0 * T1 - T0) / T3); + T4 = -(0.5 + 24.0 * T0 * T0 / T3) * (1.0 - dDeltaPhi_dVg); + T5 = T7 * AbulkCV; + T6 = T7 * VdseffCV; - Csg = CoxWLcen * (T4 + T5 * dVdseffCV_dVg); - Csd = CoxWLcen * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd - + QovCox * dCoxeff_dVd; - Csb = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) - + Csg * dVgsteff_dVb + QovCox * dCoxeff_dVb; - Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; + Csg = CoxWLcen * (T4 + T5 * dVdseffCV_dVg); + Csd = CoxWLcen * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd + + QovCox * dCoxeff_dVd; + Csb = CoxWLcen * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) + + Csg * dVgsteff_dVb + QovCox * dCoxeff_dVb; + Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; } - else if (model->BSIM3v32xpart < 0.5) - { /* 40/60 partition */ - T2 = T2 / 12.0; - T3 = 0.5 * CoxWLcen / (T2 * T2); - T4 = T1 * (2.0 * T0 * T0 / 3.0 + T1 * (T1 - 4.0 + else if (model->BSIM3v32xpart < 0.5) + { /* 40/60 partition */ + T2 = T2 / 12.0; + T3 = 0.5 * CoxWLcen / (T2 * T2); + T4 = T1 * (2.0 * T0 * T0 / 3.0 + T1 * (T1 - 4.0 * T0 / 3.0)) - 2.0 * T0 * T0 * T0 / 15.0; - qsrc = -T3 * T4; - QovCox = qsrc / Coxeff; - T8 = 4.0 / 3.0 * T1 * (T1 - T0) + 0.4 * T0 * T0; - T5 = -2.0 * qsrc / T2 - T3 * (T1 * (3.0 * T1 - 8.0 - * T0 / 3.0) + 2.0 * T0 * T0 / 3.0); - T6 = AbulkCV * (qsrc / T2 + T3 * T8); - T7 = T6 * VdseffCV / AbulkCV; + qsrc = -T3 * T4; + QovCox = qsrc / Coxeff; + T8 = 4.0 / 3.0 * T1 * (T1 - T0) + 0.4 * T0 * T0; + T5 = -2.0 * qsrc / T2 - T3 * (T1 * (3.0 * T1 - 8.0 + * T0 / 3.0) + 2.0 * T0 * T0 / 3.0); + T6 = AbulkCV * (qsrc / T2 + T3 * T8); + T7 = T6 * VdseffCV / AbulkCV; - Csg = T5 * (1.0 - dDeltaPhi_dVg) + T6 * dVdseffCV_dVg; - Csd = Csg * dVgsteff_dVd + T6 * dVdseffCV_dVd - + QovCox * dCoxeff_dVd; - Csb = Csg * dVgsteff_dVb + T6 * dVdseffCV_dVb - + T7 * dAbulkCV_dVb + QovCox * dCoxeff_dVb; - Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; + Csg = T5 * (1.0 - dDeltaPhi_dVg) + T6 * dVdseffCV_dVg; + Csd = Csg * dVgsteff_dVd + T6 * dVdseffCV_dVd + + QovCox * dCoxeff_dVd; + Csb = Csg * dVgsteff_dVb + T6 * dVdseffCV_dVb + + T7 * dAbulkCV_dVb + QovCox * dCoxeff_dVb; + Csg = Csg * dVgsteff_dVg + QovCox * dCoxeff_dVg; } - else - { /* 50/50 partition */ + else + { /* 50/50 partition */ qsrc = -0.5 * qgate; Csg = -0.5 * Cgg1; - Csd = -0.5 * Cgd1; - Csb = -0.5 * Cgb1; + Csd = -0.5 * Cgd1; + Csb = -0.5 * Cgb1; } - qgate += Qac0 + Qsub0 - qbulk; - qbulk -= (Qac0 + Qsub0); + qgate += Qac0 + Qsub0 - qbulk; + qbulk -= (Qac0 + Qsub0); qdrn = -(qgate + qbulk + qsrc); - Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; - Cbd = Cbd1 - dQsub0_dVd; - Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; + Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; + Cbd = Cbd1 - dQsub0_dVd; + Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; Cgg = Cgg1 - Cbg; Cgd = Cgd1 - Cbd; Cgb = Cgb1 - Cbb; - Cgb *= dVbseff_dVb; - Cbb *= dVbseff_dVb; - Csb *= dVbseff_dVb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; here->BSIM3v32cggb = Cgg; - here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); - here->BSIM3v32cgdb = Cgd; + here->BSIM3v32cgsb = -(Cgg + Cgd + Cgb); + here->BSIM3v32cgdb = Cgd; here->BSIM3v32cdgb = -(Cgg + Cbg + Csg); - here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb - + Csg + Csd + Csb); - here->BSIM3v32cddb = -(Cgd + Cbd + Csd); + here->BSIM3v32cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + + Csg + Csd + Csb); + here->BSIM3v32cddb = -(Cgd + Cbd + Csd); here->BSIM3v32cbgb = Cbg; - here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); - here->BSIM3v32cbdb = Cbd; + here->BSIM3v32cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3v32cbdb = Cbd; here->BSIM3v32qinv = -qinoi; - } /* End of CTM */ + } /* End of CTM */ } -finished: - /* Returning Values to Calling Routine */ +finished: + /* Returning Values to Calling Routine */ /* * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE */ @@ -2446,197 +2438,230 @@ finished: here->BSIM3v32cd = cdrain; if (ChargeComputationNeeded) - { /* charge storage elements + { /* charge storage elements * bulk-drain and bulk-source depletion capacitances * czbd : zero bias drain junction capacitance * czbs : zero bias source junction capacitance * czbdsw: zero bias drain junction sidewall capacitance - along field oxide + along field oxide * czbssw: zero bias source junction sidewall capacitance - along field oxide - * czbdswg: zero bias drain junction sidewall capacitance - along gate side - * czbsswg: zero bias source junction sidewall capacitance - along gate side + along field oxide + * czbdswg: zero bias drain junction sidewall capacitance + along gate side + * czbsswg: zero bias source junction sidewall capacitance + along gate side */ - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbd = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32drainArea; /*bug fix */ - czbs = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32sourceArea; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbd = model->BSIM3v32unitAreaJctCap * here->BSIM3v32drainArea; - czbs = model->BSIM3v32unitAreaJctCap * here->BSIM3v32sourceArea; - } + if (model->BSIM3v32acmMod == 0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbd = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32drainArea; /*bug fix */ + czbs = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32sourceArea; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbd = model->BSIM3v32unitAreaJctCap * here->BSIM3v32drainArea; + czbs = model->BSIM3v32unitAreaJctCap * here->BSIM3v32sourceArea; + } + + if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * here->BSIM3v32drainPerimeter; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbdswg = model->BSIM3v32unitLengthGateSidewallJctCap + * here->BSIM3v32drainPerimeter; + } + czbdsw = 0.0; + } + else + { + czbdsw = model->BSIM3v32unitLengthSidewallTempJctCap + * (here->BSIM3v32drainPerimeter - pParam->BSIM3v32weff); + czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * pParam->BSIM3v32weff; + } + if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) + { + czbssw = 0.0; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * here->BSIM3v32sourcePerimeter; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap + * here->BSIM3v32sourcePerimeter; + } + } + else + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbssw = model->BSIM3v32unitLengthSidewallTempJctCap + * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); + czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * pParam->BSIM3v32weff; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbssw = model->BSIM3v32unitLengthSidewallJctCap + * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); + czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap + * pParam->BSIM3v32weff; + } + } - if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * here->BSIM3v32drainPerimeter; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbdswg = model->BSIM3v32unitLengthGateSidewallJctCap - * here->BSIM3v32drainPerimeter; - } - czbdsw = 0.0; - } - else - { - czbdsw = model->BSIM3v32unitLengthSidewallTempJctCap - * (here->BSIM3v32drainPerimeter - pParam->BSIM3v32weff); - czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * pParam->BSIM3v32weff; - } - if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) - { - czbssw = 0.0; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * here->BSIM3v32sourcePerimeter; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap - * here->BSIM3v32sourcePerimeter; - } - } - else - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbssw = model->BSIM3v32unitLengthSidewallTempJctCap - * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); - czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * pParam->BSIM3v32weff; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbssw = model->BSIM3v32unitLengthSidewallJctCap - * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); - czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap - * pParam->BSIM3v32weff; - } + } else { + error = ACM_junctionCapacitances( + model->BSIM3v32acmMod, + model->BSIM3v32calcacm, + here->BSIM3v32geo, + model->BSIM3v32hdif, + model->BSIM3v32wmlt, + here->BSIM3v32w, + model->BSIM3v32xw, + here->BSIM3v32drainAreaGiven, + here->BSIM3v32drainArea, + here->BSIM3v32drainPerimeterGiven, + here->BSIM3v32drainPerimeter, + here->BSIM3v32sourceAreaGiven, + here->BSIM3v32sourceArea, + here->BSIM3v32sourcePerimeterGiven, + here->BSIM3v32sourcePerimeter, + model->BSIM3v32unitAreaTempJctCap, + model->BSIM3v32unitLengthSidewallTempJctCap, + model->BSIM3v32unitLengthGateSidewallJctCap, + &czbd, + &czbdsw, + &czbdswg, + &czbs, + &czbssw, + &czbsswg + ); + if (error) + return(error); } MJ = model->BSIM3v32bulkJctBotGradingCoeff; MJSW = model->BSIM3v32bulkJctSideGradingCoeff; - MJSWG = model->BSIM3v32bulkJctGateSideGradingCoeff; + MJSWG = model->BSIM3v32bulkJctGateSideGradingCoeff; /* Source Bulk Junction */ - if (vbs == 0.0) - { *(ckt->CKTstate0 + here->BSIM3v32qbs) = 0.0; + if (vbs == 0.0) + { *(ckt->CKTstate0 + here->BSIM3v32qbs) = 0.0; here->BSIM3v32capbs = czbs + czbssw + czbsswg; - } - else if (vbs < 0.0) - { if (czbs > 0.0) - { arg = 1.0 - vbs / model->BSIM3v32PhiB; - if (MJ == 0.5) + } + else if (vbs < 0.0) + { if (czbs > 0.0) + { arg = 1.0 - vbs / model->BSIM3v32PhiB; + if (MJ == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJ * log(arg)); - *(ckt->CKTstate0 + here->BSIM3v32qbs) = model->BSIM3v32PhiB * czbs - * (1.0 - arg * sarg) / (1.0 - MJ); - here->BSIM3v32capbs = czbs * sarg; - } - else - { *(ckt->CKTstate0 + here->BSIM3v32qbs) = 0.0; - here->BSIM3v32capbs = 0.0; - } - if (czbssw > 0.0) - { arg = 1.0 - vbs / model->BSIM3v32PhiBSW; - if (MJSW == 0.5) + *(ckt->CKTstate0 + here->BSIM3v32qbs) = model->BSIM3v32PhiB * czbs + * (1.0 - arg * sarg) / (1.0 - MJ); + here->BSIM3v32capbs = czbs * sarg; + } + else + { *(ckt->CKTstate0 + here->BSIM3v32qbs) = 0.0; + here->BSIM3v32capbs = 0.0; + } + if (czbssw > 0.0) + { arg = 1.0 - vbs / model->BSIM3v32PhiBSW; + if (MJSW == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSW * log(arg)); *(ckt->CKTstate0 + here->BSIM3v32qbs) += model->BSIM3v32PhiBSW * czbssw - * (1.0 - arg * sarg) / (1.0 - MJSW); + * (1.0 - arg * sarg) / (1.0 - MJSW); here->BSIM3v32capbs += czbssw * sarg; - } - if (czbsswg > 0.0) - { arg = 1.0 - vbs / model->BSIM3v32PhiBSWG; - if (MJSWG == 0.5) + } + if (czbsswg > 0.0) + { arg = 1.0 - vbs / model->BSIM3v32PhiBSWG; + if (MJSWG == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSWG * log(arg)); *(ckt->CKTstate0 + here->BSIM3v32qbs) += model->BSIM3v32PhiBSWG * czbsswg - * (1.0 - arg * sarg) / (1.0 - MJSWG); + * (1.0 - arg * sarg) / (1.0 - MJSWG); here->BSIM3v32capbs += czbsswg * sarg; - } + } } - else - { T0 = czbs + czbssw + czbsswg; - T1 = vbs * (czbs * MJ / model->BSIM3v32PhiB + czbssw * MJSW - / model->BSIM3v32PhiBSW + czbsswg * MJSWG / model->BSIM3v32PhiBSWG); + else + { T0 = czbs + czbssw + czbsswg; + T1 = vbs * (czbs * MJ / model->BSIM3v32PhiB + czbssw * MJSW + / model->BSIM3v32PhiBSW + czbsswg * MJSWG / model->BSIM3v32PhiBSWG); *(ckt->CKTstate0 + here->BSIM3v32qbs) = vbs * (T0 + 0.5 * T1); here->BSIM3v32capbs = T0 + T1; } /* Drain Bulk Junction */ - if (vbd == 0.0) - { *(ckt->CKTstate0 + here->BSIM3v32qbd) = 0.0; + if (vbd == 0.0) + { *(ckt->CKTstate0 + here->BSIM3v32qbd) = 0.0; here->BSIM3v32capbd = czbd + czbdsw + czbdswg; - } - else if (vbd < 0.0) - { if (czbd > 0.0) - { arg = 1.0 - vbd / model->BSIM3v32PhiB; - if (MJ == 0.5) + } + else if (vbd < 0.0) + { if (czbd > 0.0) + { arg = 1.0 - vbd / model->BSIM3v32PhiB; + if (MJ == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJ * log(arg)); - *(ckt->CKTstate0 + here->BSIM3v32qbd) = model->BSIM3v32PhiB * czbd - * (1.0 - arg * sarg) / (1.0 - MJ); + *(ckt->CKTstate0 + here->BSIM3v32qbd) = model->BSIM3v32PhiB * czbd + * (1.0 - arg * sarg) / (1.0 - MJ); here->BSIM3v32capbd = czbd * sarg; - } - else - { *(ckt->CKTstate0 + here->BSIM3v32qbd) = 0.0; + } + else + { *(ckt->CKTstate0 + here->BSIM3v32qbd) = 0.0; here->BSIM3v32capbd = 0.0; - } - if (czbdsw > 0.0) - { arg = 1.0 - vbd / model->BSIM3v32PhiBSW; - if (MJSW == 0.5) + } + if (czbdsw > 0.0) + { arg = 1.0 - vbd / model->BSIM3v32PhiBSW; + if (MJSW == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSW * log(arg)); - *(ckt->CKTstate0 + here->BSIM3v32qbd) += model->BSIM3v32PhiBSW * czbdsw - * (1.0 - arg * sarg) / (1.0 - MJSW); + *(ckt->CKTstate0 + here->BSIM3v32qbd) += model->BSIM3v32PhiBSW * czbdsw + * (1.0 - arg * sarg) / (1.0 - MJSW); here->BSIM3v32capbd += czbdsw * sarg; - } - if (czbdswg > 0.0) - { arg = 1.0 - vbd / model->BSIM3v32PhiBSWG; - if (MJSWG == 0.5) + } + if (czbdswg > 0.0) + { arg = 1.0 - vbd / model->BSIM3v32PhiBSWG; + if (MJSWG == 0.5) sarg = 1.0 / sqrt(arg); - else + else sarg = exp(-MJSWG * log(arg)); *(ckt->CKTstate0 + here->BSIM3v32qbd) += model->BSIM3v32PhiBSWG * czbdswg - * (1.0 - arg * sarg) / (1.0 - MJSWG); + * (1.0 - arg * sarg) / (1.0 - MJSWG); here->BSIM3v32capbd += czbdswg * sarg; - } + } } - else - { T0 = czbd + czbdsw + czbdswg; + else + { T0 = czbd + czbdsw + czbdswg; T1 = vbd * (czbd * MJ / model->BSIM3v32PhiB + czbdsw * MJSW / model->BSIM3v32PhiBSW + czbdswg * MJSWG / model->BSIM3v32PhiBSWG); *(ckt->CKTstate0 + here->BSIM3v32qbd) = vbd * (T0 + 0.5 * T1); - here->BSIM3v32capbd = T0 + T1; + here->BSIM3v32capbd = T0 + T1; } } @@ -2644,11 +2669,11 @@ finished: * check convergence */ if ((here->BSIM3v32off == 0) || (!(ckt->CKTmode & MODEINITFIX))) - { if (Check == 1) - { ckt->CKTnoncon++; + { if (Check == 1) + { ckt->CKTnoncon++; #ifndef NEWCONV - } - else + } + else { if (here->BSIM3v32mode >= 0) { Idtot = here->BSIM3v32cd + here->BSIM3v32csub - here->BSIM3v32cbd; } @@ -2665,7 +2690,7 @@ finished: tol = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + ckt->CKTabstol; if (fabs(cbhat - Ibtot) > tol) - { ckt->CKTnoncon++; + { ckt->CKTnoncon++; } } #endif /* NEWCONV */ @@ -2680,8 +2705,8 @@ finished: /* bulk and channel charge plus overlaps */ if (!ChargeComputationNeeded) - goto line850; - + goto line850; + #ifndef NOBYPASS line755: #endif @@ -2698,99 +2723,99 @@ line755: gtau_drift = fabs(here->BSIM3v32tconst * qcheq) * ScalingFactor; T0 = pParam->BSIM3v32leffCV * pParam->BSIM3v32leffCV; gtau_diff = 16.0 * here->BSIM3v32u0temp * model->BSIM3v32vtm / T0 - * ScalingFactor; + * ScalingFactor; here->BSIM3v32gtau = gtau_drift + gtau_diff; } - if (model->BSIM3v32capMod == 0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - /* code merge -JX */ - cgdo = pParam->BSIM3v32cgdo; - qgdo = pParam->BSIM3v32cgdo * vgd; - cgso = pParam->BSIM3v32cgso; - qgso = pParam->BSIM3v32cgso * vgs; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - if (vgd < 0.0) - { - cgdo = pParam->BSIM3v32cgdo; - qgdo = pParam->BSIM3v32cgdo * vgd; - } - else - { - cgdo = pParam->BSIM3v32cgdo; - qgdo = pParam->BSIM3v32cgdo * vgd; - } + if (model->BSIM3v32capMod == 0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + /* code merge -JX */ + cgdo = pParam->BSIM3v32cgdo; + qgdo = pParam->BSIM3v32cgdo * vgd; + cgso = pParam->BSIM3v32cgso; + qgso = pParam->BSIM3v32cgso * vgs; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + if (vgd < 0.0) + { + cgdo = pParam->BSIM3v32cgdo; + qgdo = pParam->BSIM3v32cgdo * vgd; + } + else + { + cgdo = pParam->BSIM3v32cgdo; + qgdo = pParam->BSIM3v32cgdo * vgd; + } - if (vgs < 0.0) - { - cgso = pParam->BSIM3v32cgso; - qgso = pParam->BSIM3v32cgso * vgs; - } - else - { - cgso = pParam->BSIM3v32cgso; - qgso = pParam->BSIM3v32cgso * vgs; - } - } - } - else if (model->BSIM3v32capMod == 1) - { if (vgd < 0.0) - { T1 = sqrt(1.0 - 4.0 * vgd / pParam->BSIM3v32ckappa); - cgdo = pParam->BSIM3v32cgdo + pParam->BSIM3v32weffCV - * pParam->BSIM3v32cgdl / T1; - qgdo = pParam->BSIM3v32cgdo * vgd - pParam->BSIM3v32weffCV * 0.5 - * pParam->BSIM3v32cgdl * pParam->BSIM3v32ckappa * (T1 - 1.0); - } - else - { cgdo = pParam->BSIM3v32cgdo + pParam->BSIM3v32weffCV - * pParam->BSIM3v32cgdl; - qgdo = (pParam->BSIM3v32weffCV * pParam->BSIM3v32cgdl - + pParam->BSIM3v32cgdo) * vgd; - } + if (vgs < 0.0) + { + cgso = pParam->BSIM3v32cgso; + qgso = pParam->BSIM3v32cgso * vgs; + } + else + { + cgso = pParam->BSIM3v32cgso; + qgso = pParam->BSIM3v32cgso * vgs; + } + } + } + else if (model->BSIM3v32capMod == 1) + { if (vgd < 0.0) + { T1 = sqrt(1.0 - 4.0 * vgd / pParam->BSIM3v32ckappa); + cgdo = pParam->BSIM3v32cgdo + pParam->BSIM3v32weffCV + * pParam->BSIM3v32cgdl / T1; + qgdo = pParam->BSIM3v32cgdo * vgd - pParam->BSIM3v32weffCV * 0.5 + * pParam->BSIM3v32cgdl * pParam->BSIM3v32ckappa * (T1 - 1.0); + } + else + { cgdo = pParam->BSIM3v32cgdo + pParam->BSIM3v32weffCV + * pParam->BSIM3v32cgdl; + qgdo = (pParam->BSIM3v32weffCV * pParam->BSIM3v32cgdl + + pParam->BSIM3v32cgdo) * vgd; + } - if (vgs < 0.0) - { T1 = sqrt(1.0 - 4.0 * vgs / pParam->BSIM3v32ckappa); - cgso = pParam->BSIM3v32cgso + pParam->BSIM3v32weffCV - * pParam->BSIM3v32cgsl / T1; - qgso = pParam->BSIM3v32cgso * vgs - pParam->BSIM3v32weffCV * 0.5 - * pParam->BSIM3v32cgsl * pParam->BSIM3v32ckappa * (T1 - 1.0); - } - else - { cgso = pParam->BSIM3v32cgso + pParam->BSIM3v32weffCV - * pParam->BSIM3v32cgsl; - qgso = (pParam->BSIM3v32weffCV * pParam->BSIM3v32cgsl - + pParam->BSIM3v32cgso) * vgs; - } - } - else - { T0 = vgd + DELTA_1; - T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); - T2 = 0.5 * (T0 - T1); + if (vgs < 0.0) + { T1 = sqrt(1.0 - 4.0 * vgs / pParam->BSIM3v32ckappa); + cgso = pParam->BSIM3v32cgso + pParam->BSIM3v32weffCV + * pParam->BSIM3v32cgsl / T1; + qgso = pParam->BSIM3v32cgso * vgs - pParam->BSIM3v32weffCV * 0.5 + * pParam->BSIM3v32cgsl * pParam->BSIM3v32ckappa * (T1 - 1.0); + } + else + { cgso = pParam->BSIM3v32cgso + pParam->BSIM3v32weffCV + * pParam->BSIM3v32cgsl; + qgso = (pParam->BSIM3v32weffCV * pParam->BSIM3v32cgsl + + pParam->BSIM3v32cgso) * vgs; + } + } + else + { T0 = vgd + DELTA_1; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); + T2 = 0.5 * (T0 - T1); - T3 = pParam->BSIM3v32weffCV * pParam->BSIM3v32cgdl; - T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3v32ckappa); - cgdo = pParam->BSIM3v32cgdo + T3 - T3 * (1.0 - 1.0 / T4) - * (0.5 - 0.5 * T0 / T1); - qgdo = (pParam->BSIM3v32cgdo + T3) * vgd - T3 * (T2 - + 0.5 * pParam->BSIM3v32ckappa * (T4 - 1.0)); + T3 = pParam->BSIM3v32weffCV * pParam->BSIM3v32cgdl; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3v32ckappa); + cgdo = pParam->BSIM3v32cgdo + T3 - T3 * (1.0 - 1.0 / T4) + * (0.5 - 0.5 * T0 / T1); + qgdo = (pParam->BSIM3v32cgdo + T3) * vgd - T3 * (T2 + + 0.5 * pParam->BSIM3v32ckappa * (T4 - 1.0)); - T0 = vgs + DELTA_1; - T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); - T2 = 0.5 * (T0 - T1); - T3 = pParam->BSIM3v32weffCV * pParam->BSIM3v32cgsl; - T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3v32ckappa); - cgso = pParam->BSIM3v32cgso + T3 - T3 * (1.0 - 1.0 / T4) - * (0.5 - 0.5 * T0 / T1); - qgso = (pParam->BSIM3v32cgso + T3) * vgs - T3 * (T2 - + 0.5 * pParam->BSIM3v32ckappa * (T4 - 1.0)); - } + T0 = vgs + DELTA_1; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); + T2 = 0.5 * (T0 - T1); + T3 = pParam->BSIM3v32weffCV * pParam->BSIM3v32cgsl; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM3v32ckappa); + cgso = pParam->BSIM3v32cgso + T3 - T3 * (1.0 - 1.0 / T4) + * (0.5 - 0.5 * T0 / T1); + qgso = (pParam->BSIM3v32cgso + T3) * vgs - T3 * (T2 + + 0.5 * pParam->BSIM3v32ckappa * (T4 - 1.0)); + } here->BSIM3v32cgdo = cgdo; here->BSIM3v32cgso = cgso; @@ -2827,10 +2852,10 @@ line755: qsrc = -(qgate + qbulk + qdrn); ggtg = ggtd = ggtb = ggts = 0.0; - sxpart = 0.6; + sxpart = 0.6; dxpart = 0.4; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; } else { if (qcheq > 0.0) @@ -2841,7 +2866,7 @@ line755: ggtd = here->BSIM3v32gtd = T0 * here->BSIM3v32cqdb; ggts = here->BSIM3v32gts = T0 * here->BSIM3v32cqsb; ggtb = here->BSIM3v32gtb = T0 * here->BSIM3v32cqbb; - gqdef = ScalingFactor * ag0; + gqdef = ScalingFactor * ag0; gcqgb = here->BSIM3v32cqgb * ag0; gcqdb = here->BSIM3v32cqdb * ag0; @@ -2864,44 +2889,44 @@ line755: gcbdb = -here->BSIM3v32capbd * ag0; gcbsb = -here->BSIM3v32capbs * ag0; - CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV; - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { dxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { dxpart = 0.0; - } - else - { dxpart = 0.5; - } - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - } - else - { dxpart = qdrn / qcheq; - Cdd = here->BSIM3v32cddb; - Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; - Cdg = here->BSIM3v32cdgb; - Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = qdrn / qcheq; + Cdd = here->BSIM3v32cddb; + Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3v32cdgb; + Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; - Cds = here->BSIM3v32cdsb; - Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + Cds = here->BSIM3v32cdsb; + Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); - } - sxpart = 1.0 - dxpart; - dsxpart_dVd = -ddxpart_dVd; - dsxpart_dVg = -ddxpart_dVg; - dsxpart_dVs = -ddxpart_dVs; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); qgd = qgdo; qgs = qgso; @@ -2943,10 +2968,10 @@ line755: qdrn = -(qgate + qbulk + qsrc); ggtg = ggtd = ggtb = ggts = 0.0; - sxpart = 0.4; + sxpart = 0.4; dxpart = 0.6; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; } else { if (qcheq > 0.0) @@ -2957,7 +2982,7 @@ line755: ggts = here->BSIM3v32gtd = T0 * here->BSIM3v32cqdb; ggtd = here->BSIM3v32gts = T0 * here->BSIM3v32cqsb; ggtb = here->BSIM3v32gtb = T0 * here->BSIM3v32cqbb; - gqdef = ScalingFactor * ag0; + gqdef = ScalingFactor * ag0; gcqgb = here->BSIM3v32cqgb * ag0; gcqdb = here->BSIM3v32cqsb * ag0; @@ -2980,44 +3005,44 @@ line755: gcbdb = -here->BSIM3v32capbd * ag0; gcbsb = -here->BSIM3v32capbs * ag0; - CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV; - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { sxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { sxpart = 0.0; - } - else - { sxpart = 0.5; - } - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { sxpart = qdrn / qcheq; - Css = here->BSIM3v32cddb; - Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; - Csg = here->BSIM3v32cdgb; - Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = qdrn / qcheq; + Css = here->BSIM3v32cddb; + Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3v32cdgb; + Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; - Csd = here->BSIM3v32cdsb; - Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + Csd = here->BSIM3v32cdsb; + Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); - } - dxpart = 1.0 - sxpart; - ddxpart_dVd = -dsxpart_dVd; - ddxpart_dVg = -dsxpart_dVg; - ddxpart_dVs = -dsxpart_dVs; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); qgd = qgdo; qgs = qgso; @@ -3029,7 +3054,7 @@ line755: } } - cqdef = cqcheq = 0.0; + cqdef = cqcheq = 0.0; if (ByPass) goto line860; *(ckt->CKTstate0 + here->BSIM3v32qg) = qgate; @@ -3096,21 +3121,21 @@ line850: gcggb = gcgdb = gcgsb = 0.0; gcbgb = gcbdb = gcbsb = 0.0; - gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; + gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; ggtg = ggtd = ggtb = ggts = 0.0; sxpart = (1.0 - (dxpart = (here->BSIM3v32mode > 0) ? 0.4 : 0.6)); - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; if (here->BSIM3v32nqsMod) - here->BSIM3v32gtau = 16.0 * here->BSIM3v32u0temp * model->BSIM3v32vtm + here->BSIM3v32gtau = 16.0 * here->BSIM3v32u0temp * model->BSIM3v32vtm / pParam->BSIM3v32leffCV / pParam->BSIM3v32leffCV - * ScalingFactor; - else + * ScalingFactor; + else here->BSIM3v32gtau = 0.0; goto line900; - + line860: /* evaluate equivalent charge current */ @@ -3125,9 +3150,9 @@ line860: if (here->BSIM3v32nqsMod) { T0 = ggtg * vgb - ggtd * vbd - ggts * vbs; ceqqg += T0; - T1 = qdef * here->BSIM3v32gtau; + T1 = qdef * here->BSIM3v32gtau; ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd - * vbd - ddxpart_dVs * vbs); + * vbd - ddxpart_dVs * vbs); cqdef = *(ckt->CKTstate0 + here->BSIM3v32cqcdump) - gqdef * qdef; cqcheq = *(ckt->CKTstate0 + here->BSIM3v32cqcheq) - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0; @@ -3155,16 +3180,16 @@ line860: line900: if (here->BSIM3v32mode >= 0) - { Gm = here->BSIM3v32gm; + { Gm = here->BSIM3v32gm; Gmbs = here->BSIM3v32gmbs; FwdSum = Gm + Gmbs; RevSum = 0.0; cdreq = model->BSIM3v32type * (cdrain - here->BSIM3v32gds * vds - - Gm * vgs - Gmbs * vbs); + - Gm * vgs - Gmbs * vbs); - ceqbd = -model->BSIM3v32type * (here->BSIM3v32csub - - here->BSIM3v32gbds * vds - here->BSIM3v32gbgs * vgs - - here->BSIM3v32gbbs * vbs); + ceqbd = -model->BSIM3v32type * (here->BSIM3v32csub + - here->BSIM3v32gbds * vds - here->BSIM3v32gbgs * vgs + - here->BSIM3v32gbbs * vbs); ceqbs = 0.0; gbbdp = -here->BSIM3v32gbds; @@ -3180,17 +3205,17 @@ line900: gbspb = 0.0; gbspsp = 0.0; } - else - { Gm = -here->BSIM3v32gm; + else + { Gm = -here->BSIM3v32gm; Gmbs = -here->BSIM3v32gmbs; FwdSum = 0.0; RevSum = -(Gm + Gmbs); cdreq = -model->BSIM3v32type * (cdrain + here->BSIM3v32gds * vds + Gm * vgd + Gmbs * vbd); - ceqbs = -model->BSIM3v32type * (here->BSIM3v32csub - + here->BSIM3v32gbds * vds - here->BSIM3v32gbgs * vgd - - here->BSIM3v32gbbs * vbd); + ceqbs = -model->BSIM3v32type * (here->BSIM3v32csub + + here->BSIM3v32gbds * vds - here->BSIM3v32gbgs * vgd + - here->BSIM3v32gbbs * vbd); ceqbd = 0.0; gbbsp = -here->BSIM3v32gbds; @@ -3207,93 +3232,93 @@ line900: gbspdp = -(gbspg + gbspsp + gbspb); } - if (model->BSIM3v32type > 0) - { ceqbs += (here->BSIM3v32cbs - here->BSIM3v32gbs * vbs); + if (model->BSIM3v32type > 0) + { ceqbs += (here->BSIM3v32cbs - here->BSIM3v32gbs * vbs); ceqbd += (here->BSIM3v32cbd - here->BSIM3v32gbd * vbd); - /* + /* ceqqg = ceqqg; ceqqb = ceqqb; ceqqd = ceqqd; cqdef = cqdef; cqcheq = cqcheq; - */ - } - else - { ceqbs -= (here->BSIM3v32cbs - here->BSIM3v32gbs * vbs); + */ + } + else + { ceqbs -= (here->BSIM3v32cbs - here->BSIM3v32gbs * vbs); ceqbd -= (here->BSIM3v32cbd - here->BSIM3v32gbd * vbd); ceqqg = -ceqqg; ceqqb = -ceqqb; ceqqd = -ceqqd; cqdef = -cqdef; cqcheq = -cqcheq; - } + } - m = here->BSIM3v32m; + m = here->BSIM3v32m; - (*(ckt->CKTrhs + here->BSIM3v32gNode) -= m * ceqqg); - (*(ckt->CKTrhs + here->BSIM3v32bNode) -= m * (ceqbs + ceqbd + ceqqb)); - (*(ckt->CKTrhs + here->BSIM3v32dNodePrime) += m * (ceqbd - cdreq - ceqqd)); - (*(ckt->CKTrhs + here->BSIM3v32sNodePrime) += m * (cdreq + ceqbs + ceqqg - + ceqqb + ceqqd)); - if (here->BSIM3v32nqsMod) - *(ckt->CKTrhs + here->BSIM3v32qNode) += m * (cqcheq - cqdef); + (*(ckt->CKTrhs + here->BSIM3v32gNode) -= m * ceqqg); + (*(ckt->CKTrhs + here->BSIM3v32bNode) -= m * (ceqbs + ceqbd + ceqqb)); + (*(ckt->CKTrhs + here->BSIM3v32dNodePrime) += m * (ceqbd - cdreq - ceqqd)); + (*(ckt->CKTrhs + here->BSIM3v32sNodePrime) += m * (cdreq + ceqbs + ceqqg + + ceqqb + ceqqd)); + if (here->BSIM3v32nqsMod) + *(ckt->CKTrhs + here->BSIM3v32qNode) += m * (cqcheq - cqdef); - /* - * load y matrix - */ + /* + * load y matrix + */ - T1 = qdef * here->BSIM3v32gtau; - (*(here->BSIM3v32DdPtr) += m * here->BSIM3v32drainConductance); - (*(here->BSIM3v32GgPtr) += m * (gcggb - ggtg)); - (*(here->BSIM3v32SsPtr) += m * here->BSIM3v32sourceConductance); - (*(here->BSIM3v32BbPtr) += m * (here->BSIM3v32gbd + here->BSIM3v32gbs - - gcbgb - gcbdb - gcbsb - here->BSIM3v32gbbs)); - (*(here->BSIM3v32DPdpPtr) += m * (here->BSIM3v32drainConductance - + here->BSIM3v32gds + here->BSIM3v32gbd - + RevSum + gcddb + dxpart * ggtd - + T1 * ddxpart_dVd + gbdpdp)); - (*(here->BSIM3v32SPspPtr) += m * (here->BSIM3v32sourceConductance - + here->BSIM3v32gds + here->BSIM3v32gbs - + FwdSum + gcssb + sxpart * ggts - + T1 * dsxpart_dVs + gbspsp)); - (*(here->BSIM3v32DdpPtr) -= m * here->BSIM3v32drainConductance); - (*(here->BSIM3v32GbPtr) -= m * (gcggb + gcgdb + gcgsb + ggtb)); - (*(here->BSIM3v32GdpPtr) += m * (gcgdb - ggtd)); - (*(here->BSIM3v32GspPtr) += m * (gcgsb - ggts)); - (*(here->BSIM3v32SspPtr) -= m * here->BSIM3v32sourceConductance); - (*(here->BSIM3v32BgPtr) += m * (gcbgb - here->BSIM3v32gbgs)); - (*(here->BSIM3v32BdpPtr) += m * (gcbdb - here->BSIM3v32gbd + gbbdp)); - (*(here->BSIM3v32BspPtr) += m * (gcbsb - here->BSIM3v32gbs + gbbsp)); - (*(here->BSIM3v32DPdPtr) -= m * here->BSIM3v32drainConductance); - (*(here->BSIM3v32DPgPtr) += m * (Gm + gcdgb + dxpart * ggtg - + T1 * ddxpart_dVg + gbdpg)); - (*(here->BSIM3v32DPbPtr) -= m * (here->BSIM3v32gbd - Gmbs + gcdgb + gcddb - + gcdsb - dxpart * ggtb - - T1 * ddxpart_dVb - gbdpb)); - (*(here->BSIM3v32DPspPtr) -= m * (here->BSIM3v32gds + FwdSum - gcdsb - - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp)); - (*(here->BSIM3v32SPgPtr) += m * (gcsgb - Gm + sxpart * ggtg - + T1 * dsxpart_dVg + gbspg)); - (*(here->BSIM3v32SPsPtr) -= m * here->BSIM3v32sourceConductance); - (*(here->BSIM3v32SPbPtr) -= m * (here->BSIM3v32gbs + Gmbs + gcsgb + gcsdb - + gcssb - sxpart * ggtb - - T1 * dsxpart_dVb - gbspb)); - (*(here->BSIM3v32SPdpPtr) -= m * (here->BSIM3v32gds + RevSum - gcsdb - - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); + T1 = qdef * here->BSIM3v32gtau; + (*(here->BSIM3v32DdPtr) += m * here->BSIM3v32drainConductance); + (*(here->BSIM3v32GgPtr) += m * (gcggb - ggtg)); + (*(here->BSIM3v32SsPtr) += m * here->BSIM3v32sourceConductance); + (*(here->BSIM3v32BbPtr) += m * (here->BSIM3v32gbd + here->BSIM3v32gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3v32gbbs)); + (*(here->BSIM3v32DPdpPtr) += m * (here->BSIM3v32drainConductance + + here->BSIM3v32gds + here->BSIM3v32gbd + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp)); + (*(here->BSIM3v32SPspPtr) += m * (here->BSIM3v32sourceConductance + + here->BSIM3v32gds + here->BSIM3v32gbs + + FwdSum + gcssb + sxpart * ggts + + T1 * dsxpart_dVs + gbspsp)); + (*(here->BSIM3v32DdpPtr) -= m * here->BSIM3v32drainConductance); + (*(here->BSIM3v32GbPtr) -= m * (gcggb + gcgdb + gcgsb + ggtb)); + (*(here->BSIM3v32GdpPtr) += m * (gcgdb - ggtd)); + (*(here->BSIM3v32GspPtr) += m * (gcgsb - ggts)); + (*(here->BSIM3v32SspPtr) -= m * here->BSIM3v32sourceConductance); + (*(here->BSIM3v32BgPtr) += m * (gcbgb - here->BSIM3v32gbgs)); + (*(here->BSIM3v32BdpPtr) += m * (gcbdb - here->BSIM3v32gbd + gbbdp)); + (*(here->BSIM3v32BspPtr) += m * (gcbsb - here->BSIM3v32gbs + gbbsp)); + (*(here->BSIM3v32DPdPtr) -= m * here->BSIM3v32drainConductance); + (*(here->BSIM3v32DPgPtr) += m * (Gm + gcdgb + dxpart * ggtg + + T1 * ddxpart_dVg + gbdpg)); + (*(here->BSIM3v32DPbPtr) -= m * (here->BSIM3v32gbd - Gmbs + gcdgb + gcddb + + gcdsb - dxpart * ggtb + - T1 * ddxpart_dVb - gbdpb)); + (*(here->BSIM3v32DPspPtr) -= m * (here->BSIM3v32gds + FwdSum - gcdsb + - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp)); + (*(here->BSIM3v32SPgPtr) += m * (gcsgb - Gm + sxpart * ggtg + + T1 * dsxpart_dVg + gbspg)); + (*(here->BSIM3v32SPsPtr) -= m * here->BSIM3v32sourceConductance); + (*(here->BSIM3v32SPbPtr) -= m * (here->BSIM3v32gbs + Gmbs + gcsgb + gcsdb + + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb)); + (*(here->BSIM3v32SPdpPtr) -= m * (here->BSIM3v32gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); - if (here->BSIM3v32nqsMod) - { - *(here->BSIM3v32QqPtr) += m * (gqdef + here->BSIM3v32gtau); + if (here->BSIM3v32nqsMod) + { + *(here->BSIM3v32QqPtr) += m * (gqdef + here->BSIM3v32gtau); - *(here->BSIM3v32DPqPtr) += m * (dxpart * here->BSIM3v32gtau); - *(here->BSIM3v32SPqPtr) += m * (sxpart * here->BSIM3v32gtau); - *(here->BSIM3v32GqPtr) -= m * here->BSIM3v32gtau; + *(here->BSIM3v32DPqPtr) += m * (dxpart * here->BSIM3v32gtau); + *(here->BSIM3v32SPqPtr) += m * (sxpart * here->BSIM3v32gtau); + *(here->BSIM3v32GqPtr) -= m * here->BSIM3v32gtau; - *(here->BSIM3v32QgPtr) += m * (ggtg - gcqgb); - *(here->BSIM3v32QdpPtr) += m * (ggtd - gcqdb); - *(here->BSIM3v32QspPtr) += m * (ggts - gcqsb); - *(here->BSIM3v32QbPtr) += m * (ggtb - gcqbb); - } + *(here->BSIM3v32QgPtr) += m * (ggtg - gcqgb); + *(here->BSIM3v32QdpPtr) += m * (ggtd - gcqdb); + *(here->BSIM3v32QspPtr) += m * (ggts - gcqsb); + *(here->BSIM3v32QbPtr) += m * (ggtb - gcqbb); + } line1000: ; diff --git a/src/spicelib/devices/bsim3v32/b3v32mask.c b/src/spicelib/devices/bsim3v32/b3v32mask.c index 70775ab49..f90beb13b 100644 --- a/src/spicelib/devices/bsim3v32/b3v32mask.c +++ b/src/spicelib/devices/bsim3v32/b3v32mask.c @@ -24,24 +24,30 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) NG_IGNORE(ckt); - switch(which) + switch(which) { case BSIM3v32_MOD_MOBMOD: - value->iValue = model->BSIM3v32mobMod; + value->iValue = model->BSIM3v32mobMod; return(OK); case BSIM3v32_MOD_PARAMCHK: - value->iValue = model->BSIM3v32paramChk; + value->iValue = model->BSIM3v32paramChk; return(OK); case BSIM3v32_MOD_BINUNIT: - value->iValue = model->BSIM3v32binUnit; + value->iValue = model->BSIM3v32binUnit; return(OK); case BSIM3v32_MOD_CAPMOD: - value->iValue = model->BSIM3v32capMod; + value->iValue = model->BSIM3v32capMod; return(OK); case BSIM3v32_MOD_NOIMOD: - value->iValue = model->BSIM3v32noiMod; + value->iValue = model->BSIM3v32noiMod; + return(OK); + case BSIM3v32_MOD_NQSMOD: + value->iValue = model->BSIM3v32nqsMod; return(OK); case BSIM3v32_MOD_ACMMOD: - value->iValue = model->BSIM3v32acmMod; + value->iValue = model->BSIM3v32acmMod; + return(OK); + case BSIM3v32_MOD_CALCACM: + value->iValue = model->BSIM3v32calcacm; return(OK); case BSIM3v32_MOD_VERSION : value->sValue = model->BSIM3v32version; @@ -94,7 +100,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_KETA: value->rValue = model->BSIM3v32keta; - return(OK); + return(OK); case BSIM3v32_MOD_NSUB: value->rValue = model->BSIM3v32nsub; return(OK); @@ -146,50 +152,50 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case BSIM3v32_MOD_NLX: value->rValue = model->BSIM3v32nlx; return(OK); - case BSIM3v32_MOD_DVT0 : + case BSIM3v32_MOD_DVT0 : value->rValue = model->BSIM3v32dvt0; return(OK); - case BSIM3v32_MOD_DVT1 : + case BSIM3v32_MOD_DVT1 : value->rValue = model->BSIM3v32dvt1; return(OK); - case BSIM3v32_MOD_DVT2 : + case BSIM3v32_MOD_DVT2 : value->rValue = model->BSIM3v32dvt2; return(OK); - case BSIM3v32_MOD_DVT0W : + case BSIM3v32_MOD_DVT0W : value->rValue = model->BSIM3v32dvt0w; return(OK); - case BSIM3v32_MOD_DVT1W : + case BSIM3v32_MOD_DVT1W : value->rValue = model->BSIM3v32dvt1w; return(OK); - case BSIM3v32_MOD_DVT2W : + case BSIM3v32_MOD_DVT2W : value->rValue = model->BSIM3v32dvt2w; return(OK); - case BSIM3v32_MOD_DROUT : + case BSIM3v32_MOD_DROUT : value->rValue = model->BSIM3v32drout; return(OK); - case BSIM3v32_MOD_DSUB : + case BSIM3v32_MOD_DSUB : value->rValue = model->BSIM3v32dsub; return(OK); case BSIM3v32_MOD_VTH0: - value->rValue = model->BSIM3v32vth0; + value->rValue = model->BSIM3v32vth0; return(OK); case BSIM3v32_MOD_UA: - value->rValue = model->BSIM3v32ua; + value->rValue = model->BSIM3v32ua; return(OK); case BSIM3v32_MOD_UA1: - value->rValue = model->BSIM3v32ua1; + value->rValue = model->BSIM3v32ua1; return(OK); case BSIM3v32_MOD_UB: - value->rValue = model->BSIM3v32ub; + value->rValue = model->BSIM3v32ub; return(OK); case BSIM3v32_MOD_UB1: - value->rValue = model->BSIM3v32ub1; + value->rValue = model->BSIM3v32ub1; return(OK); case BSIM3v32_MOD_UC: - value->rValue = model->BSIM3v32uc; + value->rValue = model->BSIM3v32uc; return(OK); case BSIM3v32_MOD_UC1: - value->rValue = model->BSIM3v32uc1; + value->rValue = model->BSIM3v32uc1; return(OK); case BSIM3v32_MOD_U0: value->rValue = model->BSIM3v32u0; @@ -204,44 +210,44 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32delta; return(OK); case BSIM3v32_MOD_RDSW: - value->rValue = model->BSIM3v32rdsw; - return(OK); + value->rValue = model->BSIM3v32rdsw; + return(OK); case BSIM3v32_MOD_PRWG: - value->rValue = model->BSIM3v32prwg; - return(OK); + value->rValue = model->BSIM3v32prwg; + return(OK); case BSIM3v32_MOD_PRWB: - value->rValue = model->BSIM3v32prwb; - return(OK); + value->rValue = model->BSIM3v32prwb; + return(OK); case BSIM3v32_MOD_PRT: - value->rValue = model->BSIM3v32prt; - return(OK); + value->rValue = model->BSIM3v32prt; + return(OK); case BSIM3v32_MOD_ETA0: - value->rValue = model->BSIM3v32eta0; - return(OK); + value->rValue = model->BSIM3v32eta0; + return(OK); case BSIM3v32_MOD_ETAB: - value->rValue = model->BSIM3v32etab; - return(OK); + value->rValue = model->BSIM3v32etab; + return(OK); case BSIM3v32_MOD_PCLM: - value->rValue = model->BSIM3v32pclm; - return(OK); + value->rValue = model->BSIM3v32pclm; + return(OK); case BSIM3v32_MOD_PDIBL1: - value->rValue = model->BSIM3v32pdibl1; - return(OK); + value->rValue = model->BSIM3v32pdibl1; + return(OK); case BSIM3v32_MOD_PDIBL2: - value->rValue = model->BSIM3v32pdibl2; - return(OK); + value->rValue = model->BSIM3v32pdibl2; + return(OK); case BSIM3v32_MOD_PDIBLB: - value->rValue = model->BSIM3v32pdiblb; - return(OK); + value->rValue = model->BSIM3v32pdiblb; + return(OK); case BSIM3v32_MOD_PSCBE1: - value->rValue = model->BSIM3v32pscbe1; - return(OK); + value->rValue = model->BSIM3v32pscbe1; + return(OK); case BSIM3v32_MOD_PSCBE2: - value->rValue = model->BSIM3v32pscbe2; - return(OK); + value->rValue = model->BSIM3v32pscbe2; + return(OK); case BSIM3v32_MOD_PVAG: - value->rValue = model->BSIM3v32pvag; - return(OK); + value->rValue = model->BSIM3v32pvag; + return(OK); case BSIM3v32_MOD_WR: value->rValue = model->BSIM3v32wr; return(OK); @@ -301,7 +307,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32dlc; return(OK); case BSIM3v32_MOD_VFBCV: - value->rValue = model->BSIM3v32vfbcv; + value->rValue = model->BSIM3v32vfbcv; return(OK); case BSIM3v32_MOD_ACDE: value->rValue = model->BSIM3v32acde; @@ -334,30 +340,33 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32tpbswg; return(OK); - /* acm model */ - case BSIM3v32_MOD_HDIF: - value->rValue = model->BSIM3v32hdif; - return(OK); - case BSIM3v32_MOD_LDIF: - value->rValue = model->BSIM3v32ldif; - return(OK); - case BSIM3v32_MOD_LD: - value->rValue = model->BSIM3v32ld; - return(OK); - case BSIM3v32_MOD_RD: - value->rValue = model->BSIM3v32rd; - return(OK); - case BSIM3v32_MOD_RS: - value->rValue = model->BSIM3v32rs; - return(OK); - case BSIM3v32_MOD_RDC: - value->rValue = model->BSIM3v32rdc; - return(OK); - case BSIM3v32_MOD_RSC: - value->rValue = model->BSIM3v32rsc; - return(OK); + /* ACM model */ + case BSIM3v32_MOD_HDIF: + value->rValue = model->BSIM3v32hdif; + return(OK); + case BSIM3v32_MOD_LDIF: + value->rValue = model->BSIM3v32ldif; + return(OK); + case BSIM3v32_MOD_LD: + value->rValue = model->BSIM3v32ld; + return(OK); + case BSIM3v32_MOD_RD: + value->rValue = model->BSIM3v32rd; + return(OK); + case BSIM3v32_MOD_RS: + value->rValue = model->BSIM3v32rs; + return(OK); + case BSIM3v32_MOD_RDC: + value->rValue = model->BSIM3v32rdc; + return(OK); + case BSIM3v32_MOD_RSC: + value->rValue = model->BSIM3v32rsc; + return(OK); + case BSIM3v32_MOD_WMLT: + value->rValue = model->BSIM3v32wmlt; + return(OK); - /* Length dependence */ + /* Length dependence */ case BSIM3v32_MOD_LCDSC : value->rValue = model->BSIM3v32lcdsc; return(OK); @@ -396,7 +405,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_LKETA: value->rValue = model->BSIM3v32lketa; - return(OK); + return(OK); case BSIM3v32_MOD_LNSUB: value->rValue = model->BSIM3v32lnsub; return(OK); @@ -448,50 +457,50 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case BSIM3v32_MOD_LNLX: value->rValue = model->BSIM3v32lnlx; return(OK); - case BSIM3v32_MOD_LDVT0: + case BSIM3v32_MOD_LDVT0: value->rValue = model->BSIM3v32ldvt0; return(OK); - case BSIM3v32_MOD_LDVT1 : + case BSIM3v32_MOD_LDVT1 : value->rValue = model->BSIM3v32ldvt1; return(OK); - case BSIM3v32_MOD_LDVT2 : + case BSIM3v32_MOD_LDVT2 : value->rValue = model->BSIM3v32ldvt2; return(OK); - case BSIM3v32_MOD_LDVT0W : + case BSIM3v32_MOD_LDVT0W : value->rValue = model->BSIM3v32ldvt0w; return(OK); - case BSIM3v32_MOD_LDVT1W : + case BSIM3v32_MOD_LDVT1W : value->rValue = model->BSIM3v32ldvt1w; return(OK); - case BSIM3v32_MOD_LDVT2W : + case BSIM3v32_MOD_LDVT2W : value->rValue = model->BSIM3v32ldvt2w; return(OK); - case BSIM3v32_MOD_LDROUT : + case BSIM3v32_MOD_LDROUT : value->rValue = model->BSIM3v32ldrout; return(OK); - case BSIM3v32_MOD_LDSUB : + case BSIM3v32_MOD_LDSUB : value->rValue = model->BSIM3v32ldsub; return(OK); case BSIM3v32_MOD_LVTH0: - value->rValue = model->BSIM3v32lvth0; + value->rValue = model->BSIM3v32lvth0; return(OK); case BSIM3v32_MOD_LUA: - value->rValue = model->BSIM3v32lua; + value->rValue = model->BSIM3v32lua; return(OK); case BSIM3v32_MOD_LUA1: - value->rValue = model->BSIM3v32lua1; + value->rValue = model->BSIM3v32lua1; return(OK); case BSIM3v32_MOD_LUB: - value->rValue = model->BSIM3v32lub; + value->rValue = model->BSIM3v32lub; return(OK); case BSIM3v32_MOD_LUB1: - value->rValue = model->BSIM3v32lub1; + value->rValue = model->BSIM3v32lub1; return(OK); case BSIM3v32_MOD_LUC: - value->rValue = model->BSIM3v32luc; + value->rValue = model->BSIM3v32luc; return(OK); case BSIM3v32_MOD_LUC1: - value->rValue = model->BSIM3v32luc1; + value->rValue = model->BSIM3v32luc1; return(OK); case BSIM3v32_MOD_LU0: value->rValue = model->BSIM3v32lu0; @@ -506,44 +515,44 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32ldelta; return(OK); case BSIM3v32_MOD_LRDSW: - value->rValue = model->BSIM3v32lrdsw; - return(OK); + value->rValue = model->BSIM3v32lrdsw; + return(OK); case BSIM3v32_MOD_LPRWB: - value->rValue = model->BSIM3v32lprwb; - return(OK); + value->rValue = model->BSIM3v32lprwb; + return(OK); case BSIM3v32_MOD_LPRWG: - value->rValue = model->BSIM3v32lprwg; - return(OK); + value->rValue = model->BSIM3v32lprwg; + return(OK); case BSIM3v32_MOD_LPRT: - value->rValue = model->BSIM3v32lprt; - return(OK); + value->rValue = model->BSIM3v32lprt; + return(OK); case BSIM3v32_MOD_LETA0: - value->rValue = model->BSIM3v32leta0; - return(OK); + value->rValue = model->BSIM3v32leta0; + return(OK); case BSIM3v32_MOD_LETAB: - value->rValue = model->BSIM3v32letab; - return(OK); + value->rValue = model->BSIM3v32letab; + return(OK); case BSIM3v32_MOD_LPCLM: - value->rValue = model->BSIM3v32lpclm; - return(OK); + value->rValue = model->BSIM3v32lpclm; + return(OK); case BSIM3v32_MOD_LPDIBL1: - value->rValue = model->BSIM3v32lpdibl1; - return(OK); + value->rValue = model->BSIM3v32lpdibl1; + return(OK); case BSIM3v32_MOD_LPDIBL2: - value->rValue = model->BSIM3v32lpdibl2; - return(OK); + value->rValue = model->BSIM3v32lpdibl2; + return(OK); case BSIM3v32_MOD_LPDIBLB: - value->rValue = model->BSIM3v32lpdiblb; - return(OK); + value->rValue = model->BSIM3v32lpdiblb; + return(OK); case BSIM3v32_MOD_LPSCBE1: - value->rValue = model->BSIM3v32lpscbe1; - return(OK); + value->rValue = model->BSIM3v32lpscbe1; + return(OK); case BSIM3v32_MOD_LPSCBE2: - value->rValue = model->BSIM3v32lpscbe2; - return(OK); + value->rValue = model->BSIM3v32lpscbe2; + return(OK); case BSIM3v32_MOD_LPVAG: - value->rValue = model->BSIM3v32lpvag; - return(OK); + value->rValue = model->BSIM3v32lpvag; + return(OK); case BSIM3v32_MOD_LWR: value->rValue = model->BSIM3v32lwr; return(OK); @@ -609,7 +618,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32lvoffcv; return(OK); - /* Width dependence */ + /* Width dependence */ case BSIM3v32_MOD_WCDSC : value->rValue = model->BSIM3v32wcdsc; return(OK); @@ -648,7 +657,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_WKETA: value->rValue = model->BSIM3v32wketa; - return(OK); + return(OK); case BSIM3v32_MOD_WNSUB: value->rValue = model->BSIM3v32wnsub; return(OK); @@ -700,50 +709,50 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case BSIM3v32_MOD_WNLX: value->rValue = model->BSIM3v32wnlx; return(OK); - case BSIM3v32_MOD_WDVT0: + case BSIM3v32_MOD_WDVT0: value->rValue = model->BSIM3v32wdvt0; return(OK); - case BSIM3v32_MOD_WDVT1 : + case BSIM3v32_MOD_WDVT1 : value->rValue = model->BSIM3v32wdvt1; return(OK); - case BSIM3v32_MOD_WDVT2 : + case BSIM3v32_MOD_WDVT2 : value->rValue = model->BSIM3v32wdvt2; return(OK); - case BSIM3v32_MOD_WDVT0W : + case BSIM3v32_MOD_WDVT0W : value->rValue = model->BSIM3v32wdvt0w; return(OK); - case BSIM3v32_MOD_WDVT1W : + case BSIM3v32_MOD_WDVT1W : value->rValue = model->BSIM3v32wdvt1w; return(OK); - case BSIM3v32_MOD_WDVT2W : + case BSIM3v32_MOD_WDVT2W : value->rValue = model->BSIM3v32wdvt2w; return(OK); - case BSIM3v32_MOD_WDROUT : + case BSIM3v32_MOD_WDROUT : value->rValue = model->BSIM3v32wdrout; return(OK); - case BSIM3v32_MOD_WDSUB : + case BSIM3v32_MOD_WDSUB : value->rValue = model->BSIM3v32wdsub; return(OK); case BSIM3v32_MOD_WVTH0: - value->rValue = model->BSIM3v32wvth0; + value->rValue = model->BSIM3v32wvth0; return(OK); case BSIM3v32_MOD_WUA: - value->rValue = model->BSIM3v32wua; + value->rValue = model->BSIM3v32wua; return(OK); case BSIM3v32_MOD_WUA1: - value->rValue = model->BSIM3v32wua1; + value->rValue = model->BSIM3v32wua1; return(OK); case BSIM3v32_MOD_WUB: - value->rValue = model->BSIM3v32wub; + value->rValue = model->BSIM3v32wub; return(OK); case BSIM3v32_MOD_WUB1: - value->rValue = model->BSIM3v32wub1; + value->rValue = model->BSIM3v32wub1; return(OK); case BSIM3v32_MOD_WUC: - value->rValue = model->BSIM3v32wuc; + value->rValue = model->BSIM3v32wuc; return(OK); case BSIM3v32_MOD_WUC1: - value->rValue = model->BSIM3v32wuc1; + value->rValue = model->BSIM3v32wuc1; return(OK); case BSIM3v32_MOD_WU0: value->rValue = model->BSIM3v32wu0; @@ -758,44 +767,44 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32wdelta; return(OK); case BSIM3v32_MOD_WRDSW: - value->rValue = model->BSIM3v32wrdsw; - return(OK); + value->rValue = model->BSIM3v32wrdsw; + return(OK); case BSIM3v32_MOD_WPRWB: - value->rValue = model->BSIM3v32wprwb; - return(OK); + value->rValue = model->BSIM3v32wprwb; + return(OK); case BSIM3v32_MOD_WPRWG: - value->rValue = model->BSIM3v32wprwg; - return(OK); + value->rValue = model->BSIM3v32wprwg; + return(OK); case BSIM3v32_MOD_WPRT: - value->rValue = model->BSIM3v32wprt; - return(OK); + value->rValue = model->BSIM3v32wprt; + return(OK); case BSIM3v32_MOD_WETA0: - value->rValue = model->BSIM3v32weta0; - return(OK); + value->rValue = model->BSIM3v32weta0; + return(OK); case BSIM3v32_MOD_WETAB: - value->rValue = model->BSIM3v32wetab; - return(OK); + value->rValue = model->BSIM3v32wetab; + return(OK); case BSIM3v32_MOD_WPCLM: - value->rValue = model->BSIM3v32wpclm; - return(OK); + value->rValue = model->BSIM3v32wpclm; + return(OK); case BSIM3v32_MOD_WPDIBL1: - value->rValue = model->BSIM3v32wpdibl1; - return(OK); + value->rValue = model->BSIM3v32wpdibl1; + return(OK); case BSIM3v32_MOD_WPDIBL2: - value->rValue = model->BSIM3v32wpdibl2; - return(OK); + value->rValue = model->BSIM3v32wpdibl2; + return(OK); case BSIM3v32_MOD_WPDIBLB: - value->rValue = model->BSIM3v32wpdiblb; - return(OK); + value->rValue = model->BSIM3v32wpdiblb; + return(OK); case BSIM3v32_MOD_WPSCBE1: - value->rValue = model->BSIM3v32wpscbe1; - return(OK); + value->rValue = model->BSIM3v32wpscbe1; + return(OK); case BSIM3v32_MOD_WPSCBE2: - value->rValue = model->BSIM3v32wpscbe2; - return(OK); + value->rValue = model->BSIM3v32wpscbe2; + return(OK); case BSIM3v32_MOD_WPVAG: - value->rValue = model->BSIM3v32wpvag; - return(OK); + value->rValue = model->BSIM3v32wpvag; + return(OK); case BSIM3v32_MOD_WWR: value->rValue = model->BSIM3v32wwr; return(OK); @@ -861,7 +870,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32wvoffcv; return(OK); - /* Cross-term dependence */ + /* Cross-term dependence */ case BSIM3v32_MOD_PCDSC : value->rValue = model->BSIM3v32pcdsc; return(OK); @@ -900,7 +909,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_PKETA: value->rValue = model->BSIM3v32pketa; - return(OK); + return(OK); case BSIM3v32_MOD_PNSUB: value->rValue = model->BSIM3v32pnsub; return(OK); @@ -952,50 +961,50 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case BSIM3v32_MOD_PNLX: value->rValue = model->BSIM3v32pnlx; return(OK); - case BSIM3v32_MOD_PDVT0 : + case BSIM3v32_MOD_PDVT0 : value->rValue = model->BSIM3v32pdvt0; return(OK); - case BSIM3v32_MOD_PDVT1 : + case BSIM3v32_MOD_PDVT1 : value->rValue = model->BSIM3v32pdvt1; return(OK); - case BSIM3v32_MOD_PDVT2 : + case BSIM3v32_MOD_PDVT2 : value->rValue = model->BSIM3v32pdvt2; return(OK); - case BSIM3v32_MOD_PDVT0W : + case BSIM3v32_MOD_PDVT0W : value->rValue = model->BSIM3v32pdvt0w; return(OK); - case BSIM3v32_MOD_PDVT1W : + case BSIM3v32_MOD_PDVT1W : value->rValue = model->BSIM3v32pdvt1w; return(OK); - case BSIM3v32_MOD_PDVT2W : - value->rValue = model->BSIM3v32pdvt2w; + case BSIM3v32_MOD_PDVT2W : + value->rValue = model->BSIM3v32pdvt2w; return(OK); - case BSIM3v32_MOD_PDROUT : - value->rValue = model->BSIM3v32pdrout; + case BSIM3v32_MOD_PDROUT : + value->rValue = model->BSIM3v32pdrout; return(OK); - case BSIM3v32_MOD_PDSUB : - value->rValue = model->BSIM3v32pdsub; + case BSIM3v32_MOD_PDSUB : + value->rValue = model->BSIM3v32pdsub; return(OK); case BSIM3v32_MOD_PVTH0: - value->rValue = model->BSIM3v32pvth0; + value->rValue = model->BSIM3v32pvth0; return(OK); case BSIM3v32_MOD_PUA: - value->rValue = model->BSIM3v32pua; + value->rValue = model->BSIM3v32pua; return(OK); case BSIM3v32_MOD_PUA1: - value->rValue = model->BSIM3v32pua1; + value->rValue = model->BSIM3v32pua1; return(OK); case BSIM3v32_MOD_PUB: - value->rValue = model->BSIM3v32pub; + value->rValue = model->BSIM3v32pub; return(OK); case BSIM3v32_MOD_PUB1: - value->rValue = model->BSIM3v32pub1; + value->rValue = model->BSIM3v32pub1; return(OK); case BSIM3v32_MOD_PUC: - value->rValue = model->BSIM3v32puc; + value->rValue = model->BSIM3v32puc; return(OK); case BSIM3v32_MOD_PUC1: - value->rValue = model->BSIM3v32puc1; + value->rValue = model->BSIM3v32puc1; return(OK); case BSIM3v32_MOD_PU0: value->rValue = model->BSIM3v32pu0; @@ -1010,44 +1019,44 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) value->rValue = model->BSIM3v32pdelta; return(OK); case BSIM3v32_MOD_PRDSW: - value->rValue = model->BSIM3v32prdsw; - return(OK); + value->rValue = model->BSIM3v32prdsw; + return(OK); case BSIM3v32_MOD_PPRWB: - value->rValue = model->BSIM3v32pprwb; - return(OK); + value->rValue = model->BSIM3v32pprwb; + return(OK); case BSIM3v32_MOD_PPRWG: - value->rValue = model->BSIM3v32pprwg; - return(OK); + value->rValue = model->BSIM3v32pprwg; + return(OK); case BSIM3v32_MOD_PPRT: - value->rValue = model->BSIM3v32pprt; - return(OK); + value->rValue = model->BSIM3v32pprt; + return(OK); case BSIM3v32_MOD_PETA0: - value->rValue = model->BSIM3v32peta0; - return(OK); + value->rValue = model->BSIM3v32peta0; + return(OK); case BSIM3v32_MOD_PETAB: - value->rValue = model->BSIM3v32petab; - return(OK); + value->rValue = model->BSIM3v32petab; + return(OK); case BSIM3v32_MOD_PPCLM: - value->rValue = model->BSIM3v32ppclm; - return(OK); + value->rValue = model->BSIM3v32ppclm; + return(OK); case BSIM3v32_MOD_PPDIBL1: - value->rValue = model->BSIM3v32ppdibl1; - return(OK); + value->rValue = model->BSIM3v32ppdibl1; + return(OK); case BSIM3v32_MOD_PPDIBL2: - value->rValue = model->BSIM3v32ppdibl2; - return(OK); + value->rValue = model->BSIM3v32ppdibl2; + return(OK); case BSIM3v32_MOD_PPDIBLB: - value->rValue = model->BSIM3v32ppdiblb; - return(OK); + value->rValue = model->BSIM3v32ppdiblb; + return(OK); case BSIM3v32_MOD_PPSCBE1: - value->rValue = model->BSIM3v32ppscbe1; - return(OK); + value->rValue = model->BSIM3v32ppscbe1; + return(OK); case BSIM3v32_MOD_PPSCBE2: - value->rValue = model->BSIM3v32ppscbe2; - return(OK); + value->rValue = model->BSIM3v32ppscbe2; + return(OK); case BSIM3v32_MOD_PPVAG: - value->rValue = model->BSIM3v32ppvag; - return(OK); + value->rValue = model->BSIM3v32ppvag; + return(OK); case BSIM3v32_MOD_PWR: value->rValue = model->BSIM3v32pwr; return(OK); @@ -1114,64 +1123,64 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_TNOM : - value->rValue = model->BSIM3v32tnom; + value->rValue = model->BSIM3v32tnom; return(OK); case BSIM3v32_MOD_CGSO: - value->rValue = model->BSIM3v32cgso; + value->rValue = model->BSIM3v32cgso; return(OK); case BSIM3v32_MOD_CGDO: - value->rValue = model->BSIM3v32cgdo; + value->rValue = model->BSIM3v32cgdo; return(OK); case BSIM3v32_MOD_CGBO: - value->rValue = model->BSIM3v32cgbo; + value->rValue = model->BSIM3v32cgbo; return(OK); case BSIM3v32_MOD_XPART: - value->rValue = model->BSIM3v32xpart; + value->rValue = model->BSIM3v32xpart; return(OK); case BSIM3v32_MOD_RSH: - value->rValue = model->BSIM3v32sheetResistance; + value->rValue = model->BSIM3v32sheetResistance; return(OK); case BSIM3v32_MOD_JS: - value->rValue = model->BSIM3v32jctSatCurDensity; + value->rValue = model->BSIM3v32jctSatCurDensity; return(OK); case BSIM3v32_MOD_JSW: - value->rValue = model->BSIM3v32jctSidewallSatCurDensity; + value->rValue = model->BSIM3v32jctSidewallSatCurDensity; return(OK); case BSIM3v32_MOD_PB: - value->rValue = model->BSIM3v32bulkJctPotential; + value->rValue = model->BSIM3v32bulkJctPotential; return(OK); case BSIM3v32_MOD_MJ: - value->rValue = model->BSIM3v32bulkJctBotGradingCoeff; + value->rValue = model->BSIM3v32bulkJctBotGradingCoeff; return(OK); case BSIM3v32_MOD_PBSW: - value->rValue = model->BSIM3v32sidewallJctPotential; + value->rValue = model->BSIM3v32sidewallJctPotential; return(OK); case BSIM3v32_MOD_MJSW: - value->rValue = model->BSIM3v32bulkJctSideGradingCoeff; + value->rValue = model->BSIM3v32bulkJctSideGradingCoeff; return(OK); case BSIM3v32_MOD_CJ: - value->rValue = model->BSIM3v32unitAreaJctCap; + value->rValue = model->BSIM3v32unitAreaJctCap; return(OK); case BSIM3v32_MOD_CJSW: - value->rValue = model->BSIM3v32unitLengthSidewallJctCap; + value->rValue = model->BSIM3v32unitLengthSidewallJctCap; return(OK); case BSIM3v32_MOD_PBSWG: - value->rValue = model->BSIM3v32GatesidewallJctPotential; + value->rValue = model->BSIM3v32GatesidewallJctPotential; return(OK); case BSIM3v32_MOD_MJSWG: - value->rValue = model->BSIM3v32bulkJctGateSideGradingCoeff; + value->rValue = model->BSIM3v32bulkJctGateSideGradingCoeff; return(OK); case BSIM3v32_MOD_CJSWG: - value->rValue = model->BSIM3v32unitLengthGateSidewallJctCap; + value->rValue = model->BSIM3v32unitLengthGateSidewallJctCap; return(OK); case BSIM3v32_MOD_NJ: - value->rValue = model->BSIM3v32jctEmissionCoeff; + value->rValue = model->BSIM3v32jctEmissionCoeff; return(OK); case BSIM3v32_MOD_XTI: - value->rValue = model->BSIM3v32jctTempExponent; + value->rValue = model->BSIM3v32jctTempExponent; return(OK); case BSIM3v32_MOD_LINT: - value->rValue = model->BSIM3v32Lint; + value->rValue = model->BSIM3v32Lint; return(OK); case BSIM3v32_MOD_LL: value->rValue = model->BSIM3v32Ll; @@ -1238,11 +1247,11 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) return(OK); case BSIM3v32_MOD_XL: - value->rValue = model->BSIM3v32xl; - return(OK); + value->rValue = model->BSIM3v32xl; + return(OK); case BSIM3v32_MOD_XW: - value->rValue = model->BSIM3v32xw; - return(OK); + value->rValue = model->BSIM3v32xw; + return(OK); case BSIM3v32_MOD_NOIA: value->rValue = model->BSIM3v32oxideTrapDensityA; diff --git a/src/spicelib/devices/bsim3v32/b3v32mdel.c b/src/spicelib/devices/bsim3v32/b3v32mdel.c index 27f437819..2558d7bfe 100644 --- a/src/spicelib/devices/bsim3v32/b3v32mdel.c +++ b/src/spicelib/devices/bsim3v32/b3v32mdel.c @@ -3,7 +3,7 @@ /********** * Copyright 2001 Regents of the University of California. All rights reserved. * File: b3mdel.c of BSIM3v3.2.4 - * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi * Modified by Paolo Nenzi 2002 @@ -24,10 +24,10 @@ BSIM3v32instance *prev = NULL; BSIM3v32model **oldmod; oldmod = model; - for (; *model ; model = &((*model)->BSIM3v32nextModel)) - { if ((*model)->BSIM3v32modName == modname || + for (; *model ; model = &((*model)->BSIM3v32nextModel)) + { if ((*model)->BSIM3v32modName == modname || (modfast && *model == modfast)) - goto delgot; + goto delgot; oldmod = model; } return(E_NOMOD); @@ -44,4 +44,3 @@ delgot: } - diff --git a/src/spicelib/devices/bsim3v32/b3v32mpar.c b/src/spicelib/devices/bsim3v32/b3v32mpar.c index d35d51ba4..353f6320d 100644 --- a/src/spicelib/devices/bsim3v32/b3v32mpar.c +++ b/src/spicelib/devices/bsim3v32/b3v32mpar.c @@ -3,7 +3,7 @@ /********** * Copyright 2001 Regents of the University of California. All rights reserved. * File: b3mpar.c of BSIM3v3.2.4 - * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi * Modified by Paolo Nenzi 2002 and Dietmar Warning 2003 @@ -41,10 +41,18 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32acmMod = value->iValue; mod->BSIM3v32acmModGiven = TRUE; break; + case BSIM3v32_MOD_CALCACM: + mod->BSIM3v32calcacm = value->iValue; + mod->BSIM3v32calcacmGiven = TRUE; + break; case BSIM3v32_MOD_NOIMOD : mod->BSIM3v32noiMod = value->iValue; mod->BSIM3v32noiModGiven = TRUE; break; + case BSIM3v32_MOD_NQSMOD : + mod->BSIM3v32nqsMod = value->iValue; + mod->BSIM3v32nqsModGiven = TRUE; + break; case BSIM3v32_MOD_VERSION : mod->BSIM3v32version = value->sValue; mod->BSIM3v32versionGiven = TRUE; @@ -92,12 +100,12 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32a0 = value->rValue; mod->BSIM3v32a0Given = TRUE; break; - + case BSIM3v32_MOD_AGS: mod->BSIM3v32ags= value->rValue; mod->BSIM3v32agsGiven = TRUE; break; - + case BSIM3v32_MOD_A1: mod->BSIM3v32a1 = value->rValue; mod->BSIM3v32a1Given = TRUE; @@ -113,7 +121,7 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_KETA: mod->BSIM3v32keta = value->rValue; mod->BSIM3v32ketaGiven = TRUE; - break; + break; case BSIM3v32_MOD_NSUB: mod->BSIM3v32nsub = value->rValue; mod->BSIM3v32nsubGiven = TRUE; @@ -121,14 +129,14 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_NPEAK: mod->BSIM3v32npeak = value->rValue; mod->BSIM3v32npeakGiven = TRUE; - if (mod->BSIM3v32npeak > 1.0e20) - mod->BSIM3v32npeak *= 1.0e-6; + if (mod->BSIM3v32npeak > 1.0e20) + mod->BSIM3v32npeak *= 1.0e-6; break; case BSIM3v32_MOD_NGATE: mod->BSIM3v32ngate = value->rValue; mod->BSIM3v32ngateGiven = TRUE; - if (mod->BSIM3v32ngate > 1.0e23) - mod->BSIM3v32ngate *= 1.0e-6; + if (mod->BSIM3v32ngate > 1.0e23) + mod->BSIM3v32ngate *= 1.0e-6; break; case BSIM3v32_MOD_GAMMA1: mod->BSIM3v32gamma1 = value->rValue; @@ -186,35 +194,35 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32w0 = value->rValue; mod->BSIM3v32w0Given = TRUE; break; - case BSIM3v32_MOD_DVT0: + case BSIM3v32_MOD_DVT0: mod->BSIM3v32dvt0 = value->rValue; mod->BSIM3v32dvt0Given = TRUE; break; - case BSIM3v32_MOD_DVT1: + case BSIM3v32_MOD_DVT1: mod->BSIM3v32dvt1 = value->rValue; mod->BSIM3v32dvt1Given = TRUE; break; - case BSIM3v32_MOD_DVT2: + case BSIM3v32_MOD_DVT2: mod->BSIM3v32dvt2 = value->rValue; mod->BSIM3v32dvt2Given = TRUE; break; - case BSIM3v32_MOD_DVT0W: + case BSIM3v32_MOD_DVT0W: mod->BSIM3v32dvt0w = value->rValue; mod->BSIM3v32dvt0wGiven = TRUE; break; - case BSIM3v32_MOD_DVT1W: + case BSIM3v32_MOD_DVT1W: mod->BSIM3v32dvt1w = value->rValue; mod->BSIM3v32dvt1wGiven = TRUE; break; - case BSIM3v32_MOD_DVT2W: + case BSIM3v32_MOD_DVT2W: mod->BSIM3v32dvt2w = value->rValue; mod->BSIM3v32dvt2wGiven = TRUE; break; - case BSIM3v32_MOD_DROUT: + case BSIM3v32_MOD_DROUT: mod->BSIM3v32drout = value->rValue; mod->BSIM3v32droutGiven = TRUE; break; - case BSIM3v32_MOD_DSUB: + case BSIM3v32_MOD_DSUB: mod->BSIM3v32dsub = value->rValue; mod->BSIM3v32dsubGiven = TRUE; break; @@ -265,55 +273,55 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_RDSW: mod->BSIM3v32rdsw = value->rValue; mod->BSIM3v32rdswGiven = TRUE; - break; + break; case BSIM3v32_MOD_PRWG: mod->BSIM3v32prwg = value->rValue; mod->BSIM3v32prwgGiven = TRUE; - break; + break; case BSIM3v32_MOD_PRWB: mod->BSIM3v32prwb = value->rValue; mod->BSIM3v32prwbGiven = TRUE; - break; + break; case BSIM3v32_MOD_PRT: mod->BSIM3v32prt = value->rValue; mod->BSIM3v32prtGiven = TRUE; - break; + break; case BSIM3v32_MOD_ETA0: mod->BSIM3v32eta0 = value->rValue; mod->BSIM3v32eta0Given = TRUE; - break; + break; case BSIM3v32_MOD_ETAB: mod->BSIM3v32etab = value->rValue; mod->BSIM3v32etabGiven = TRUE; - break; + break; case BSIM3v32_MOD_PCLM: mod->BSIM3v32pclm = value->rValue; mod->BSIM3v32pclmGiven = TRUE; - break; + break; case BSIM3v32_MOD_PDIBL1: mod->BSIM3v32pdibl1 = value->rValue; mod->BSIM3v32pdibl1Given = TRUE; - break; + break; case BSIM3v32_MOD_PDIBL2: mod->BSIM3v32pdibl2 = value->rValue; mod->BSIM3v32pdibl2Given = TRUE; - break; + break; case BSIM3v32_MOD_PDIBLB: mod->BSIM3v32pdiblb = value->rValue; mod->BSIM3v32pdiblbGiven = TRUE; - break; + break; case BSIM3v32_MOD_PSCBE1: mod->BSIM3v32pscbe1 = value->rValue; mod->BSIM3v32pscbe1Given = TRUE; - break; + break; case BSIM3v32_MOD_PSCBE2: mod->BSIM3v32pscbe2 = value->rValue; mod->BSIM3v32pscbe2Given = TRUE; - break; + break; case BSIM3v32_MOD_PVAG: mod->BSIM3v32pvag = value->rValue; mod->BSIM3v32pvagGiven = TRUE; - break; + break; case BSIM3v32_MOD_WR : mod->BSIM3v32wr = value->rValue; mod->BSIM3v32wrGiven = TRUE; @@ -465,8 +473,12 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32rsc = value->rValue; mod->BSIM3v32rscGiven = TRUE; break; + case BSIM3v32_MOD_WMLT: + mod->BSIM3v32wmlt = value->rValue; + mod->BSIM3v32wmltGiven = TRUE; + break; - /* Length dependence */ + /* Length dependence */ case BSIM3v32_MOD_LCDSC : mod->BSIM3v32lcdsc = value->rValue; mod->BSIM3v32lcdscGiven = TRUE; @@ -497,8 +509,8 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32lvsat = value->rValue; mod->BSIM3v32lvsatGiven = TRUE; break; - - + + case BSIM3v32_MOD_LA0: mod->BSIM3v32la0 = value->rValue; mod->BSIM3v32la0Given = TRUE; @@ -522,7 +534,7 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_LKETA: mod->BSIM3v32lketa = value->rValue; mod->BSIM3v32lketaGiven = TRUE; - break; + break; case BSIM3v32_MOD_LNSUB: mod->BSIM3v32lnsub = value->rValue; mod->BSIM3v32lnsubGiven = TRUE; @@ -530,14 +542,14 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_LNPEAK: mod->BSIM3v32lnpeak = value->rValue; mod->BSIM3v32lnpeakGiven = TRUE; - if (mod->BSIM3v32lnpeak > 1.0e20) - mod->BSIM3v32lnpeak *= 1.0e-6; + if (mod->BSIM3v32lnpeak > 1.0e20) + mod->BSIM3v32lnpeak *= 1.0e-6; break; case BSIM3v32_MOD_LNGATE: mod->BSIM3v32lngate = value->rValue; mod->BSIM3v32lngateGiven = TRUE; - if (mod->BSIM3v32lngate > 1.0e23) - mod->BSIM3v32lngate *= 1.0e-6; + if (mod->BSIM3v32lngate > 1.0e23) + mod->BSIM3v32lngate *= 1.0e-6; break; case BSIM3v32_MOD_LGAMMA1: mod->BSIM3v32lgamma1 = value->rValue; @@ -595,35 +607,35 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32lw0 = value->rValue; mod->BSIM3v32lw0Given = TRUE; break; - case BSIM3v32_MOD_LDVT0: + case BSIM3v32_MOD_LDVT0: mod->BSIM3v32ldvt0 = value->rValue; mod->BSIM3v32ldvt0Given = TRUE; break; - case BSIM3v32_MOD_LDVT1: + case BSIM3v32_MOD_LDVT1: mod->BSIM3v32ldvt1 = value->rValue; mod->BSIM3v32ldvt1Given = TRUE; break; - case BSIM3v32_MOD_LDVT2: + case BSIM3v32_MOD_LDVT2: mod->BSIM3v32ldvt2 = value->rValue; mod->BSIM3v32ldvt2Given = TRUE; break; - case BSIM3v32_MOD_LDVT0W: + case BSIM3v32_MOD_LDVT0W: mod->BSIM3v32ldvt0w = value->rValue; mod->BSIM3v32ldvt0wGiven = TRUE; break; - case BSIM3v32_MOD_LDVT1W: + case BSIM3v32_MOD_LDVT1W: mod->BSIM3v32ldvt1w = value->rValue; mod->BSIM3v32ldvt1wGiven = TRUE; break; - case BSIM3v32_MOD_LDVT2W: + case BSIM3v32_MOD_LDVT2W: mod->BSIM3v32ldvt2w = value->rValue; mod->BSIM3v32ldvt2wGiven = TRUE; break; - case BSIM3v32_MOD_LDROUT: + case BSIM3v32_MOD_LDROUT: mod->BSIM3v32ldrout = value->rValue; mod->BSIM3v32ldroutGiven = TRUE; break; - case BSIM3v32_MOD_LDSUB: + case BSIM3v32_MOD_LDSUB: mod->BSIM3v32ldsub = value->rValue; mod->BSIM3v32ldsubGiven = TRUE; break; @@ -674,55 +686,55 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_LRDSW: mod->BSIM3v32lrdsw = value->rValue; mod->BSIM3v32lrdswGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPRWB: mod->BSIM3v32lprwb = value->rValue; mod->BSIM3v32lprwbGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPRWG: mod->BSIM3v32lprwg = value->rValue; mod->BSIM3v32lprwgGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPRT: mod->BSIM3v32lprt = value->rValue; mod->BSIM3v32lprtGiven = TRUE; - break; + break; case BSIM3v32_MOD_LETA0: mod->BSIM3v32leta0 = value->rValue; mod->BSIM3v32leta0Given = TRUE; - break; + break; case BSIM3v32_MOD_LETAB: mod->BSIM3v32letab = value->rValue; mod->BSIM3v32letabGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPCLM: mod->BSIM3v32lpclm = value->rValue; mod->BSIM3v32lpclmGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPDIBL1: mod->BSIM3v32lpdibl1 = value->rValue; mod->BSIM3v32lpdibl1Given = TRUE; - break; + break; case BSIM3v32_MOD_LPDIBL2: mod->BSIM3v32lpdibl2 = value->rValue; mod->BSIM3v32lpdibl2Given = TRUE; - break; + break; case BSIM3v32_MOD_LPDIBLB: mod->BSIM3v32lpdiblb = value->rValue; mod->BSIM3v32lpdiblbGiven = TRUE; - break; + break; case BSIM3v32_MOD_LPSCBE1: mod->BSIM3v32lpscbe1 = value->rValue; mod->BSIM3v32lpscbe1Given = TRUE; - break; + break; case BSIM3v32_MOD_LPSCBE2: mod->BSIM3v32lpscbe2 = value->rValue; mod->BSIM3v32lpscbe2Given = TRUE; - break; + break; case BSIM3v32_MOD_LPVAG: mod->BSIM3v32lpvag = value->rValue; mod->BSIM3v32lpvagGiven = TRUE; - break; + break; case BSIM3v32_MOD_LWR : mod->BSIM3v32lwr = value->rValue; mod->BSIM3v32lwrGiven = TRUE; @@ -809,13 +821,13 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32lvoffcvGiven = TRUE; break; - /* Width dependence */ + /* Width dependence */ case BSIM3v32_MOD_WCDSC : mod->BSIM3v32wcdsc = value->rValue; mod->BSIM3v32wcdscGiven = TRUE; break; - - + + case BSIM3v32_MOD_WCDSCB : mod->BSIM3v32wcdscb = value->rValue; mod->BSIM3v32wcdscbGiven = TRUE; @@ -865,7 +877,7 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_WKETA: mod->BSIM3v32wketa = value->rValue; mod->BSIM3v32wketaGiven = TRUE; - break; + break; case BSIM3v32_MOD_WNSUB: mod->BSIM3v32wnsub = value->rValue; mod->BSIM3v32wnsubGiven = TRUE; @@ -873,14 +885,14 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_WNPEAK: mod->BSIM3v32wnpeak = value->rValue; mod->BSIM3v32wnpeakGiven = TRUE; - if (mod->BSIM3v32wnpeak > 1.0e20) - mod->BSIM3v32wnpeak *= 1.0e-6; + if (mod->BSIM3v32wnpeak > 1.0e20) + mod->BSIM3v32wnpeak *= 1.0e-6; break; case BSIM3v32_MOD_WNGATE: mod->BSIM3v32wngate = value->rValue; mod->BSIM3v32wngateGiven = TRUE; - if (mod->BSIM3v32wngate > 1.0e23) - mod->BSIM3v32wngate *= 1.0e-6; + if (mod->BSIM3v32wngate > 1.0e23) + mod->BSIM3v32wngate *= 1.0e-6; break; case BSIM3v32_MOD_WGAMMA1: mod->BSIM3v32wgamma1 = value->rValue; @@ -938,35 +950,35 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32ww0 = value->rValue; mod->BSIM3v32ww0Given = TRUE; break; - case BSIM3v32_MOD_WDVT0: + case BSIM3v32_MOD_WDVT0: mod->BSIM3v32wdvt0 = value->rValue; mod->BSIM3v32wdvt0Given = TRUE; break; - case BSIM3v32_MOD_WDVT1: + case BSIM3v32_MOD_WDVT1: mod->BSIM3v32wdvt1 = value->rValue; mod->BSIM3v32wdvt1Given = TRUE; break; - case BSIM3v32_MOD_WDVT2: + case BSIM3v32_MOD_WDVT2: mod->BSIM3v32wdvt2 = value->rValue; mod->BSIM3v32wdvt2Given = TRUE; break; - case BSIM3v32_MOD_WDVT0W: + case BSIM3v32_MOD_WDVT0W: mod->BSIM3v32wdvt0w = value->rValue; mod->BSIM3v32wdvt0wGiven = TRUE; break; - case BSIM3v32_MOD_WDVT1W: + case BSIM3v32_MOD_WDVT1W: mod->BSIM3v32wdvt1w = value->rValue; mod->BSIM3v32wdvt1wGiven = TRUE; break; - case BSIM3v32_MOD_WDVT2W: + case BSIM3v32_MOD_WDVT2W: mod->BSIM3v32wdvt2w = value->rValue; mod->BSIM3v32wdvt2wGiven = TRUE; break; - case BSIM3v32_MOD_WDROUT: + case BSIM3v32_MOD_WDROUT: mod->BSIM3v32wdrout = value->rValue; mod->BSIM3v32wdroutGiven = TRUE; break; - case BSIM3v32_MOD_WDSUB: + case BSIM3v32_MOD_WDSUB: mod->BSIM3v32wdsub = value->rValue; mod->BSIM3v32wdsubGiven = TRUE; break; @@ -1017,55 +1029,55 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_WRDSW: mod->BSIM3v32wrdsw = value->rValue; mod->BSIM3v32wrdswGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPRWB: mod->BSIM3v32wprwb = value->rValue; mod->BSIM3v32wprwbGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPRWG: mod->BSIM3v32wprwg = value->rValue; mod->BSIM3v32wprwgGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPRT: mod->BSIM3v32wprt = value->rValue; mod->BSIM3v32wprtGiven = TRUE; - break; + break; case BSIM3v32_MOD_WETA0: mod->BSIM3v32weta0 = value->rValue; mod->BSIM3v32weta0Given = TRUE; - break; + break; case BSIM3v32_MOD_WETAB: mod->BSIM3v32wetab = value->rValue; mod->BSIM3v32wetabGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPCLM: mod->BSIM3v32wpclm = value->rValue; mod->BSIM3v32wpclmGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPDIBL1: mod->BSIM3v32wpdibl1 = value->rValue; mod->BSIM3v32wpdibl1Given = TRUE; - break; + break; case BSIM3v32_MOD_WPDIBL2: mod->BSIM3v32wpdibl2 = value->rValue; mod->BSIM3v32wpdibl2Given = TRUE; - break; + break; case BSIM3v32_MOD_WPDIBLB: mod->BSIM3v32wpdiblb = value->rValue; mod->BSIM3v32wpdiblbGiven = TRUE; - break; + break; case BSIM3v32_MOD_WPSCBE1: mod->BSIM3v32wpscbe1 = value->rValue; mod->BSIM3v32wpscbe1Given = TRUE; - break; + break; case BSIM3v32_MOD_WPSCBE2: mod->BSIM3v32wpscbe2 = value->rValue; mod->BSIM3v32wpscbe2Given = TRUE; - break; + break; case BSIM3v32_MOD_WPVAG: mod->BSIM3v32wpvag = value->rValue; mod->BSIM3v32wpvagGiven = TRUE; - break; + break; case BSIM3v32_MOD_WWR : mod->BSIM3v32wwr = value->rValue; mod->BSIM3v32wwrGiven = TRUE; @@ -1152,7 +1164,7 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32wvoffcvGiven = TRUE; break; - /* Cross-term dependence */ + /* Cross-term dependence */ case BSIM3v32_MOD_PCDSC : mod->BSIM3v32pcdsc = value->rValue; mod->BSIM3v32pcdscGiven = TRUE; @@ -1208,7 +1220,7 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_PKETA: mod->BSIM3v32pketa = value->rValue; mod->BSIM3v32pketaGiven = TRUE; - break; + break; case BSIM3v32_MOD_PNSUB: mod->BSIM3v32pnsub = value->rValue; mod->BSIM3v32pnsubGiven = TRUE; @@ -1216,14 +1228,14 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_PNPEAK: mod->BSIM3v32pnpeak = value->rValue; mod->BSIM3v32pnpeakGiven = TRUE; - if (mod->BSIM3v32pnpeak > 1.0e20) - mod->BSIM3v32pnpeak *= 1.0e-6; + if (mod->BSIM3v32pnpeak > 1.0e20) + mod->BSIM3v32pnpeak *= 1.0e-6; break; case BSIM3v32_MOD_PNGATE: mod->BSIM3v32pngate = value->rValue; mod->BSIM3v32pngateGiven = TRUE; - if (mod->BSIM3v32pngate > 1.0e23) - mod->BSIM3v32pngate *= 1.0e-6; + if (mod->BSIM3v32pngate > 1.0e23) + mod->BSIM3v32pngate *= 1.0e-6; break; case BSIM3v32_MOD_PGAMMA1: mod->BSIM3v32pgamma1 = value->rValue; @@ -1281,35 +1293,35 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) mod->BSIM3v32pw0 = value->rValue; mod->BSIM3v32pw0Given = TRUE; break; - case BSIM3v32_MOD_PDVT0: + case BSIM3v32_MOD_PDVT0: mod->BSIM3v32pdvt0 = value->rValue; mod->BSIM3v32pdvt0Given = TRUE; break; - case BSIM3v32_MOD_PDVT1: + case BSIM3v32_MOD_PDVT1: mod->BSIM3v32pdvt1 = value->rValue; mod->BSIM3v32pdvt1Given = TRUE; break; - case BSIM3v32_MOD_PDVT2: + case BSIM3v32_MOD_PDVT2: mod->BSIM3v32pdvt2 = value->rValue; mod->BSIM3v32pdvt2Given = TRUE; break; - case BSIM3v32_MOD_PDVT0W: + case BSIM3v32_MOD_PDVT0W: mod->BSIM3v32pdvt0w = value->rValue; mod->BSIM3v32pdvt0wGiven = TRUE; break; - case BSIM3v32_MOD_PDVT1W: + case BSIM3v32_MOD_PDVT1W: mod->BSIM3v32pdvt1w = value->rValue; mod->BSIM3v32pdvt1wGiven = TRUE; break; - case BSIM3v32_MOD_PDVT2W: + case BSIM3v32_MOD_PDVT2W: mod->BSIM3v32pdvt2w = value->rValue; mod->BSIM3v32pdvt2wGiven = TRUE; break; - case BSIM3v32_MOD_PDROUT: + case BSIM3v32_MOD_PDROUT: mod->BSIM3v32pdrout = value->rValue; mod->BSIM3v32pdroutGiven = TRUE; break; - case BSIM3v32_MOD_PDSUB: + case BSIM3v32_MOD_PDSUB: mod->BSIM3v32pdsub = value->rValue; mod->BSIM3v32pdsubGiven = TRUE; break; @@ -1360,55 +1372,55 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod) case BSIM3v32_MOD_PRDSW: mod->BSIM3v32prdsw = value->rValue; mod->BSIM3v32prdswGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPRWB: mod->BSIM3v32pprwb = value->rValue; mod->BSIM3v32pprwbGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPRWG: mod->BSIM3v32pprwg = value->rValue; mod->BSIM3v32pprwgGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPRT: mod->BSIM3v32pprt = value->rValue; mod->BSIM3v32pprtGiven = TRUE; - break; + break; case BSIM3v32_MOD_PETA0: mod->BSIM3v32peta0 = value->rValue; mod->BSIM3v32peta0Given = TRUE; - break; + break; case BSIM3v32_MOD_PETAB: mod->BSIM3v32petab = value->rValue; mod->BSIM3v32petabGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPCLM: mod->BSIM3v32ppclm = value->rValue; mod->BSIM3v32ppclmGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPDIBL1: mod->BSIM3v32ppdibl1 = value->rValue; mod->BSIM3v32ppdibl1Given = TRUE; - break; + break; case BSIM3v32_MOD_PPDIBL2: mod->BSIM3v32ppdibl2 = value->rValue; mod->BSIM3v32ppdibl2Given = TRUE; - break; + break; case BSIM3v32_MOD_PPDIBLB: mod->BSIM3v32ppdiblb = value->rValue; mod->BSIM3v32ppdiblbGiven = TRUE; - break; + break; case BSIM3v32_MOD_PPSCBE1: mod->BSIM3v32ppscbe1 = value->rValue; mod->BSIM3v32ppscbe1Given = TRUE; - break; + break; case BSIM3v32_MOD_PPSCBE2: mod->BSIM3v32ppscbe2 = value->rValue; mod->BSIM3v32ppscbe2Given = TRUE; - break; + break; case BSIM3v32_MOD_PPVAG: mod->BSIM3v32ppvag = value->rValue; mod->BSIM3v32ppvagGiven = TRUE; - break; + break; case BSIM3v32_MOD_PWR : mod->BSIM3v32pwr = value->rValue; mod->BSIM3v32pwrGiven = TRUE; diff --git a/src/spicelib/devices/bsim3v32/b3v32node.c b/src/spicelib/devices/bsim3v32/b3v32node.c new file mode 100644 index 000000000..8cdba132d --- /dev/null +++ b/src/spicelib/devices/bsim3v32/b3v32node.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3v32def.h" +#include "ngspice/sperror.h" + +int +BSIM3v32nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM3v32model *model = (BSIM3v32model *)inModel ; + BSIM3v32instance *here ; + + /* loop through all the BSIM3v32 models */ + for ( ; model != NULL ; model = model->BSIM3v32nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM3v32instances ; here != NULL ; here = here->BSIM3v32nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM3v32dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v32sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v32qNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v32gNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM3v32bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim3v32/b3v32noi.c b/src/spicelib/devices/bsim3v32/b3v32noi.c index 5f56aedf6..7351a535e 100644 --- a/src/spicelib/devices/bsim3v32/b3v32noi.c +++ b/src/spicelib/devices/bsim3v32/b3v32noi.c @@ -45,7 +45,7 @@ */ -/* +/* * The StrongInversionNoiseEval function has been modified in * the release 3.2.4 of BSIM3v32 model. To accomodate both the old * and the new code, I have renamed according to the following: @@ -63,7 +63,7 @@ static double StrongInversionNoiseEvalNew(double Vds, BSIM3v32model *model, - BSIM3v32instance *here, double freq, double temp) + BSIM3v32instance *here, double freq, double temp) { struct bsim3v32SizeDependParam *pParam; double cd, esat, DelClm, EffFreq, N0, Nl; @@ -72,10 +72,10 @@ double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; pParam = here->pParam; cd = fabs(here->BSIM3v32cd); esat = 2.0 * pParam->BSIM3v32vsattemp / here->BSIM3v32ueff; - if(model->BSIM3v32em<=0.0) DelClm = 0.0; - else { - T0 = ((((Vds - here->BSIM3v32Vdseff) / pParam->BSIM3v32litl) - + model->BSIM3v32em) / esat); + if(model->BSIM3v32em<=0.0) DelClm = 0.0; + else { + T0 = ((((Vds - here->BSIM3v32Vdseff) / pParam->BSIM3v32litl) + + model->BSIM3v32em) / esat); DelClm = pParam->BSIM3v32litl * log (MAX(T0, N_MINLOG)); } EffFreq = pow(freq, model->BSIM3v32ef); @@ -84,7 +84,7 @@ double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; * pParam->BSIM3v32leff * pParam->BSIM3v32leff; N0 = model->BSIM3v32cox * here->BSIM3v32Vgsteff / CHARGE; Nl = model->BSIM3v32cox * here->BSIM3v32Vgsteff - * (1.0 - here->BSIM3v32AbovVgst2Vtm * here->BSIM3v32Vdseff) / CHARGE; + * (1.0 - here->BSIM3v32AbovVgst2Vtm * here->BSIM3v32Vdseff) / CHARGE; T3 = model->BSIM3v32oxideTrapDensityA * log(MAX(((N0 + 2.0e14) / (Nl + 2.0e14)), N_MINLOG)); @@ -109,7 +109,7 @@ double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; static double StrongInversionNoiseEvalOld(double vgs, double vds, BSIM3v32model *model, - BSIM3v32instance *here, double freq, double temp) + BSIM3v32instance *here, double freq, double temp) { struct bsim3v32SizeDependParam *pParam; double cd, esat, DelClm, EffFreq, N0, Nl, Vgst; @@ -124,7 +124,7 @@ StrongInversionNoiseEvalOld(double vgs, double vds, BSIM3v32model *model, { esat = 2.0 * pParam->BSIM3v32vsattemp / here->BSIM3v32ueff; T0 = ((((vds - here->BSIM3v32vdsat) / pParam->BSIM3v32litl) + - model->BSIM3v32em) / esat); + model->BSIM3v32em) / esat); DelClm = pParam->BSIM3v32litl * log (MAX (T0, N_MINLOG)); } else @@ -132,13 +132,13 @@ StrongInversionNoiseEvalOld(double vgs, double vds, BSIM3v32model *model, } else { - if (model->BSIM3v32em <= 0.0) /* flicker noise modified -JX */ + if (model->BSIM3v32em <= 0.0) /* flicker noise modified -JX */ DelClm = 0.0; else if (vds > here->BSIM3v32vdsat) { esat = 2.0 * pParam->BSIM3v32vsattemp / here->BSIM3v32ueff; T0 = ((((vds - here->BSIM3v32vdsat) / pParam->BSIM3v32litl) + - model->BSIM3v32em) / esat); + model->BSIM3v32em) / esat); DelClm = pParam->BSIM3v32litl * log (MAX (T0, N_MINLOG)); } else @@ -176,7 +176,7 @@ StrongInversionNoiseEvalOld(double vgs, double vds, BSIM3v32model *model, int BSIM3v32noise (int mode, int operation, GENmodel *inModel, CKTcircuit *ckt, - Ndata *data, double *OnDens) + Ndata *data, double *OnDens) { NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; @@ -200,292 +200,292 @@ int i; /* define the names of the noise sources */ static char *BSIM3v32nNames[BSIM3v32NSRCS] = { /* Note that we have to keep the order */ - ".rd", /* noise due to rd */ - /* consistent with the index definitions */ - ".rs", /* noise due to rs */ - /* in BSIM3v32defs.h */ - ".id", /* noise due to id */ - ".1overf", /* flicker (1/f) noise */ - "" /* total transistor noise */ + ".rd", /* noise due to rd */ + /* consistent with the index definitions */ + ".rs", /* noise due to rs */ + /* in BSIM3v32defs.h */ + ".id", /* noise due to id */ + ".1overf", /* flicker (1/f) noise */ + "" /* total transistor noise */ }; for (; model != NULL; model = model->BSIM3v32nextModel) { for (here = model->BSIM3v32instances; here != NULL; - here = here->BSIM3v32nextInstance) - { pParam = here->pParam; - switch (operation) - { case N_OPEN: - /* see if we have to to produce a summary report */ - /* if so, name all the noise generators */ + here = here->BSIM3v32nextInstance) + { pParam = here->pParam; + switch (operation) + { case N_OPEN: + /* see if we have to to produce a summary report */ + /* if so, name all the noise generators */ - if (job->NStpsSm != 0) - { switch (mode) - { case N_DENS: - for (i = 0; i < BSIM3v32NSRCS; i++) - { (void) sprintf(name, "onoise.%s%s", - here->BSIM3v32name, - BSIM3v32nNames[i]); + if (job->NStpsSm != 0) + { switch (mode) + { case N_DENS: + for (i = 0; i < BSIM3v32NSRCS; i++) + { (void) sprintf(name, "onoise.%s%s", + here->BSIM3v32name, + BSIM3v32nNames[i]); data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); if (!data->namelist) - return(E_NOMEM); - SPfrontEnd->IFnewUid (ckt, - &(data->namelist[data->numPlots++]), - NULL, name, UID_OTHER, - NULL); - /* we've added one more plot */ - } - break; - case INT_NOIZ: - for (i = 0; i < BSIM3v32NSRCS; i++) - { (void) sprintf(name, "onoise_total.%s%s", - here->BSIM3v32name, - BSIM3v32nNames[i]); + return(E_NOMEM); + SPfrontEnd->IFnewUid (ckt, + &(data->namelist[data->numPlots++]), + NULL, name, UID_OTHER, + NULL); + /* we've added one more plot */ + } + break; + case INT_NOIZ: + for (i = 0; i < BSIM3v32NSRCS; i++) + { (void) sprintf(name, "onoise_total.%s%s", + here->BSIM3v32name, + BSIM3v32nNames[i]); data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); if (!data->namelist) - return(E_NOMEM); - SPfrontEnd->IFnewUid (ckt, - &(data->namelist[data->numPlots++]), - NULL, name, UID_OTHER, - NULL); - /* we've added one more plot */ + return(E_NOMEM); + SPfrontEnd->IFnewUid (ckt, + &(data->namelist[data->numPlots++]), + NULL, name, UID_OTHER, + NULL); + /* we've added one more plot */ - (void) sprintf(name, "inoise_total.%s%s", - here->BSIM3v32name, - BSIM3v32nNames[i]); + (void) sprintf(name, "inoise_total.%s%s", + here->BSIM3v32name, + BSIM3v32nNames[i]); data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); if (!data->namelist) - return(E_NOMEM); - SPfrontEnd->IFnewUid (ckt, - &(data->namelist[data->numPlots++]), - NULL, name, UID_OTHER, - NULL); - /* we've added one more plot */ - } - break; - } - } - break; - case N_CALC: - m = here->BSIM3v32m; - switch (mode) - { case N_DENS: - NevalSrc(&noizDens[BSIM3v32RDNOIZ], - &lnNdens[BSIM3v32RDNOIZ], ckt, THERMNOISE, - here->BSIM3v32dNodePrime, here->BSIM3v32dNode, - here->BSIM3v32drainConductance * m); + return(E_NOMEM); + SPfrontEnd->IFnewUid (ckt, + &(data->namelist[data->numPlots++]), + NULL, name, UID_OTHER, + NULL); + /* we've added one more plot */ + } + break; + } + } + break; + case N_CALC: + m = here->BSIM3v32m; + switch (mode) + { case N_DENS: + NevalSrc(&noizDens[BSIM3v32RDNOIZ], + &lnNdens[BSIM3v32RDNOIZ], ckt, THERMNOISE, + here->BSIM3v32dNodePrime, here->BSIM3v32dNode, + here->BSIM3v32drainConductance * m); - NevalSrc(&noizDens[BSIM3v32RSNOIZ], - &lnNdens[BSIM3v32RSNOIZ], ckt, THERMNOISE, - here->BSIM3v32sNodePrime, here->BSIM3v32sNode, - here->BSIM3v32sourceConductance * m); + NevalSrc(&noizDens[BSIM3v32RSNOIZ], + &lnNdens[BSIM3v32RSNOIZ], ckt, THERMNOISE, + here->BSIM3v32sNodePrime, here->BSIM3v32sNode, + here->BSIM3v32sourceConductance * m); switch( model->BSIM3v32noiMod ) - { case 1: - case 3: - NevalSrc(&noizDens[BSIM3v32IDNOIZ], - &lnNdens[BSIM3v32IDNOIZ], ckt, - THERMNOISE, here->BSIM3v32dNodePrime, - here->BSIM3v32sNodePrime, + { case 1: + case 3: + NevalSrc(&noizDens[BSIM3v32IDNOIZ], + &lnNdens[BSIM3v32IDNOIZ], ckt, + THERMNOISE, here->BSIM3v32dNodePrime, + here->BSIM3v32sNodePrime, (2.0 / 3.0 * fabs(here->BSIM3v32gm - + here->BSIM3v32gds - + here->BSIM3v32gmbs)) * m); - break; - case 2: - case 4: - /* Added revision dependent code */ - if (model->BSIM3v32intVersion == BSIM3v32V324) - { - NevalSrc(&noizDens[BSIM3v32IDNOIZ], - &lnNdens[BSIM3v32IDNOIZ], ckt, - THERMNOISE, here->BSIM3v32dNodePrime, + + here->BSIM3v32gds + + here->BSIM3v32gmbs)) * m); + break; + case 2: + case 4: + /* Added revision dependent code */ + if (model->BSIM3v32intVersion == BSIM3v32V324) + { + NevalSrc(&noizDens[BSIM3v32IDNOIZ], + &lnNdens[BSIM3v32IDNOIZ], ckt, + THERMNOISE, here->BSIM3v32dNodePrime, here->BSIM3v32sNodePrime, - (m * here->BSIM3v32ueff - * fabs(here->BSIM3v32qinv) - / (pParam->BSIM3v32leff * pParam->BSIM3v32leff - + here->BSIM3v32ueff * fabs(here->BSIM3v32qinv) - * here->BSIM3v32rds))); /* bugfix */ - } - else - { /* for all versions lower then 3.2.4 */ - NevalSrc(&noizDens[BSIM3v32IDNOIZ], - &lnNdens[BSIM3v32IDNOIZ], ckt, - THERMNOISE, here->BSIM3v32dNodePrime, + (m * here->BSIM3v32ueff + * fabs(here->BSIM3v32qinv) + / (pParam->BSIM3v32leff * pParam->BSIM3v32leff + + here->BSIM3v32ueff * fabs(here->BSIM3v32qinv) + * here->BSIM3v32rds))); /* bugfix */ + } + else + { /* for all versions lower then 3.2.4 */ + NevalSrc(&noizDens[BSIM3v32IDNOIZ], + &lnNdens[BSIM3v32IDNOIZ], ckt, + THERMNOISE, here->BSIM3v32dNodePrime, here->BSIM3v32sNodePrime, - (m * here->BSIM3v32ueff - * fabs(here->BSIM3v32qinv - / (pParam->BSIM3v32leff - * pParam->BSIM3v32leff)))); - } - break; - } - NevalSrc(&noizDens[BSIM3v32FLNOIZ], NULL, - ckt, N_GAIN, here->BSIM3v32dNodePrime, - here->BSIM3v32sNodePrime, (double) 0.0); + (m * here->BSIM3v32ueff + * fabs(here->BSIM3v32qinv + / (pParam->BSIM3v32leff + * pParam->BSIM3v32leff)))); + } + break; + } + NevalSrc(&noizDens[BSIM3v32FLNOIZ], NULL, + ckt, N_GAIN, here->BSIM3v32dNodePrime, + here->BSIM3v32sNodePrime, (double) 0.0); switch( model->BSIM3v32noiMod ) - { case 1: - case 4: - noizDens[BSIM3v32FLNOIZ] *= m * model->BSIM3v32kf - * exp(model->BSIM3v32af - * log(MAX(fabs(here->BSIM3v32cd), - N_MINLOG))) - / (pow(data->freq, model->BSIM3v32ef) - * pParam->BSIM3v32leff - * pParam->BSIM3v32leff - * model->BSIM3v32cox); - break; - case 2: - case 3: - vgs = *(ckt->CKTstates[0] + here->BSIM3v32vgs); - vds = *(ckt->CKTstates[0] + here->BSIM3v32vds); - if (vds < 0.0) - { vds = -vds; - vgs = vgs + vds; - } - /* Added revision dependent code */ - if (model->BSIM3v32intVersion == BSIM3v32V324) - { - Ssi = StrongInversionNoiseEvalNew(vds, model, - here, data->freq, ckt->CKTtemp); - T10 = model->BSIM3v32oxideTrapDensityA - * 8.62e-5 * ckt->CKTtemp; - T11 = pParam->BSIM3v32weff - * pParam->BSIM3v32leff - * pow(data->freq, model->BSIM3v32ef) - * 4.0e36; - Swi = T10 / T11 * here->BSIM3v32cd - * here->BSIM3v32cd; - T1 = Swi + Ssi; - if (T1 > 0.0) - noizDens[BSIM3v32FLNOIZ] *= m * (Ssi * Swi) / T1; - else + { case 1: + case 4: + noizDens[BSIM3v32FLNOIZ] *= m * model->BSIM3v32kf + * exp(model->BSIM3v32af + * log(MAX(fabs(here->BSIM3v32cd), + N_MINLOG))) + / (pow(data->freq, model->BSIM3v32ef) + * pParam->BSIM3v32leff + * pParam->BSIM3v32leff + * model->BSIM3v32cox); + break; + case 2: + case 3: + vgs = *(ckt->CKTstates[0] + here->BSIM3v32vgs); + vds = *(ckt->CKTstates[0] + here->BSIM3v32vds); + if (vds < 0.0) + { vds = -vds; + vgs = vgs + vds; + } + /* Added revision dependent code */ + if (model->BSIM3v32intVersion == BSIM3v32V324) + { + Ssi = StrongInversionNoiseEvalNew(vds, model, + here, data->freq, ckt->CKTtemp); + T10 = model->BSIM3v32oxideTrapDensityA + * 8.62e-5 * ckt->CKTtemp; + T11 = pParam->BSIM3v32weff + * pParam->BSIM3v32leff + * pow(data->freq, model->BSIM3v32ef) + * 4.0e36; + Swi = T10 / T11 * here->BSIM3v32cd + * here->BSIM3v32cd; + T1 = Swi + Ssi; + if (T1 > 0.0) + noizDens[BSIM3v32FLNOIZ] *= m * (Ssi * Swi) / T1; + else noizDens[BSIM3v32FLNOIZ] *= 0.0; - } - else - { /* for all versions lower then 3.2.4 */ - if (vgs >= here->BSIM3v32von + 0.1) - { - Ssi = StrongInversionNoiseEvalOld(vgs, vds, model, - here, data->freq, ckt->CKTtemp); - noizDens[BSIM3v32FLNOIZ] *= m * Ssi; - } - else - { - pParam = here->pParam; - T10 = model->BSIM3v32oxideTrapDensityA - * 8.62e-5 * ckt->CKTtemp; - T11 = pParam->BSIM3v32weff - * pParam-> BSIM3v32leff - * pow (data->freq, model->BSIM3v32ef) - * 4.0e36; - Swi = T10 / T11 * here->BSIM3v32cd * here->BSIM3v32cd; + } + else + { /* for all versions lower then 3.2.4 */ + if (vgs >= here->BSIM3v32von + 0.1) + { + Ssi = StrongInversionNoiseEvalOld(vgs, vds, model, + here, data->freq, ckt->CKTtemp); + noizDens[BSIM3v32FLNOIZ] *= m * Ssi; + } + else + { + pParam = here->pParam; + T10 = model->BSIM3v32oxideTrapDensityA + * 8.62e-5 * ckt->CKTtemp; + T11 = pParam->BSIM3v32weff + * pParam-> BSIM3v32leff + * pow (data->freq, model->BSIM3v32ef) + * 4.0e36; + Swi = T10 / T11 * here->BSIM3v32cd * here->BSIM3v32cd; - Slimit = StrongInversionNoiseEvalOld( - here->BSIM3v32von + 0.1, vds, model, - here, data->freq, ckt->CKTtemp); - T1 = Swi + Slimit; - if (T1 > 0.0) - noizDens[BSIM3v32FLNOIZ] *= m * (Slimit * Swi) / T1; - else - noizDens[BSIM3v32FLNOIZ] *= 0.0; - } - } - break; - } - - lnNdens[BSIM3v32FLNOIZ] = - log(MAX(noizDens[BSIM3v32FLNOIZ], N_MINLOG)); - - noizDens[BSIM3v32TOTNOIZ] = noizDens[BSIM3v32RDNOIZ] - + noizDens[BSIM3v32RSNOIZ] - + noizDens[BSIM3v32IDNOIZ] - + noizDens[BSIM3v32FLNOIZ]; - lnNdens[BSIM3v32TOTNOIZ] = - log(MAX(noizDens[BSIM3v32TOTNOIZ], N_MINLOG)); + Slimit = StrongInversionNoiseEvalOld( + here->BSIM3v32von + 0.1, vds, model, + here, data->freq, ckt->CKTtemp); + T1 = Swi + Slimit; + if (T1 > 0.0) + noizDens[BSIM3v32FLNOIZ] *= m * (Slimit * Swi) / T1; + else + noizDens[BSIM3v32FLNOIZ] *= 0.0; + } + } + break; + } - *OnDens += noizDens[BSIM3v32TOTNOIZ]; + lnNdens[BSIM3v32FLNOIZ] = + log(MAX(noizDens[BSIM3v32FLNOIZ], N_MINLOG)); - if (data->delFreq == 0.0) - { /* if we haven't done any previous - integration, we need to initialize our - "history" variables. - */ + noizDens[BSIM3v32TOTNOIZ] = noizDens[BSIM3v32RDNOIZ] + + noizDens[BSIM3v32RSNOIZ] + + noizDens[BSIM3v32IDNOIZ] + + noizDens[BSIM3v32FLNOIZ]; + lnNdens[BSIM3v32TOTNOIZ] = + log(MAX(noizDens[BSIM3v32TOTNOIZ], N_MINLOG)); - for (i = 0; i < BSIM3v32NSRCS; i++) - { here->BSIM3v32nVar[LNLSTDENS][i] = - lnNdens[i]; - } + *OnDens += noizDens[BSIM3v32TOTNOIZ]; - /* clear out our integration variables - if it's the first pass - */ - if (data->freq == - job->NstartFreq) - { for (i = 0; i < BSIM3v32NSRCS; i++) - { here->BSIM3v32nVar[OUTNOIZ][i] = 0.0; - here->BSIM3v32nVar[INNOIZ][i] = 0.0; - } - } - } - else - { /* data->delFreq != 0.0, - we have to integrate. - */ - for (i = 0; i < BSIM3v32NSRCS; i++) - { if (i != BSIM3v32TOTNOIZ) - { tempOnoise = Nintegrate(noizDens[i], - lnNdens[i], - here->BSIM3v32nVar[LNLSTDENS][i], - data); - tempInoise = Nintegrate(noizDens[i] - * data->GainSqInv, lnNdens[i] - + data->lnGainInv, - here->BSIM3v32nVar[LNLSTDENS][i] - + data->lnGainInv, data); - here->BSIM3v32nVar[LNLSTDENS][i] = - lnNdens[i]; - data->outNoiz += tempOnoise; - data->inNoise += tempInoise; - if (job->NStpsSm != 0) - { here->BSIM3v32nVar[OUTNOIZ][i] - += tempOnoise; - here->BSIM3v32nVar[OUTNOIZ][BSIM3v32TOTNOIZ] - += tempOnoise; - here->BSIM3v32nVar[INNOIZ][i] - += tempInoise; - here->BSIM3v32nVar[INNOIZ][BSIM3v32TOTNOIZ] - += tempInoise; + if (data->delFreq == 0.0) + { /* if we haven't done any previous + integration, we need to initialize our + "history" variables. + */ + + for (i = 0; i < BSIM3v32NSRCS; i++) + { here->BSIM3v32nVar[LNLSTDENS][i] = + lnNdens[i]; + } + + /* clear out our integration variables + if it's the first pass + */ + if (data->freq == + job->NstartFreq) + { for (i = 0; i < BSIM3v32NSRCS; i++) + { here->BSIM3v32nVar[OUTNOIZ][i] = 0.0; + here->BSIM3v32nVar[INNOIZ][i] = 0.0; + } + } + } + else + { /* data->delFreq != 0.0, + we have to integrate. + */ + for (i = 0; i < BSIM3v32NSRCS; i++) + { if (i != BSIM3v32TOTNOIZ) + { tempOnoise = Nintegrate(noizDens[i], + lnNdens[i], + here->BSIM3v32nVar[LNLSTDENS][i], + data); + tempInoise = Nintegrate(noizDens[i] + * data->GainSqInv, lnNdens[i] + + data->lnGainInv, + here->BSIM3v32nVar[LNLSTDENS][i] + + data->lnGainInv, data); + here->BSIM3v32nVar[LNLSTDENS][i] = + lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (job->NStpsSm != 0) + { here->BSIM3v32nVar[OUTNOIZ][i] + += tempOnoise; + here->BSIM3v32nVar[OUTNOIZ][BSIM3v32TOTNOIZ] + += tempOnoise; + here->BSIM3v32nVar[INNOIZ][i] + += tempInoise; + here->BSIM3v32nVar[INNOIZ][BSIM3v32TOTNOIZ] + += tempInoise; } - } - } - } - if (data->prtSummary) - { for (i = 0; i < BSIM3v32NSRCS; i++) - { /* print a summary report */ - data->outpVector[data->outNumber++] - = noizDens[i]; - } - } - break; - case INT_NOIZ: - /* already calculated, just output */ - if (job->NStpsSm != 0) - { for (i = 0; i < BSIM3v32NSRCS; i++) - { data->outpVector[data->outNumber++] - = here->BSIM3v32nVar[OUTNOIZ][i]; - data->outpVector[data->outNumber++] - = here->BSIM3v32nVar[INNOIZ][i]; - } - } - break; - } - break; - case N_CLOSE: - /* do nothing, the main calling routine will close */ - return (OK); - break; /* the plots */ - } /* switch (operation) */ - } /* for here */ + } + } + } + if (data->prtSummary) + { for (i = 0; i < BSIM3v32NSRCS; i++) + { /* print a summary report */ + data->outpVector[data->outNumber++] + = noizDens[i]; + } + } + break; + case INT_NOIZ: + /* already calculated, just output */ + if (job->NStpsSm != 0) + { for (i = 0; i < BSIM3v32NSRCS; i++) + { data->outpVector[data->outNumber++] + = here->BSIM3v32nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] + = here->BSIM3v32nVar[INNOIZ][i]; + } + } + break; + } + break; + case N_CLOSE: + /* do nothing, the main calling routine will close */ + return (OK); + break; /* the plots */ + } /* switch (operation) */ + } /* for here */ } /* for model */ return(OK); diff --git a/src/spicelib/devices/bsim3v32/b3v32par.c b/src/spicelib/devices/bsim3v32/b3v32par.c index 3f3a489b7..425eb4489 100644 --- a/src/spicelib/devices/bsim3v32/b3v32par.c +++ b/src/spicelib/devices/bsim3v32/b3v32par.c @@ -28,7 +28,7 @@ BSIM3v32param (int param, IFvalue *value, GENinstance *inst, IFvalue *select) if (!cp_getvar("scale", CP_REAL, &scale)) scale = 1; - switch(param) + switch(param) { case BSIM3v32_W: here->BSIM3v32w = value->rValue*scale; here->BSIM3v32wGiven = TRUE; @@ -84,6 +84,10 @@ BSIM3v32param (int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->BSIM3v32nqsMod = value->iValue; here->BSIM3v32nqsModGiven = TRUE; break; + case BSIM3v32_GEO: + here->BSIM3v32geo = value->iValue; + here->BSIM3v32geoGiven = TRUE; + break; case BSIM3v32_DELVTO: here->BSIM3v32delvto = value->rValue; here->BSIM3v32delvtoGiven = TRUE; diff --git a/src/spicelib/devices/bsim3v32/b3v32pzld.c b/src/spicelib/devices/bsim3v32/b3v32pzld.c index f775c1ea4..ddadb53af 100644 --- a/src/spicelib/devices/bsim3v32/b3v32pzld.c +++ b/src/spicelib/devices/bsim3v32/b3v32pzld.c @@ -3,7 +3,7 @@ /********** * Copyright 2001 Regents of the University of California. All rights reserved. * File: b3pzld.c of BSIM3v3.2.4 - * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi * Modified by Paolo Nenzi 2002 @@ -36,11 +36,11 @@ double T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; double ScalingFactor = 1.0e-9; double m; - for (; model != NULL; model = model->BSIM3v32nextModel) + for (; model != NULL; model = model->BSIM3v32nextModel) { for (here = model->BSIM3v32instances; here!= NULL; - here = here->BSIM3v32nextInstance) - { - if (here->BSIM3v32mode >= 0) + here = here->BSIM3v32nextInstance) + { + if (here->BSIM3v32mode >= 0) { Gm = here->BSIM3v32gm; Gmbs = here->BSIM3v32gmbs; FwdSum = Gm + Gmbs; @@ -73,19 +73,19 @@ double m; cddb = here->BSIM3v32cddb; xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.6; + sxpart = 0.6; dxpart = 0.4; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; } else { cggb = cgdb = cgsb = 0.0; cbgb = cbdb = cbsb = 0.0; cdgb = cddb = cdsb = 0.0; - xgtg = here->BSIM3v32gtg; + xgtg = here->BSIM3v32gtg; xgtd = here->BSIM3v32gtd; xgts = here->BSIM3v32gts; xgtb = here->BSIM3v32gtb; @@ -95,46 +95,46 @@ double m; xcqsb = here->BSIM3v32cqsb; xcqbb = here->BSIM3v32cqbb; - CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV * here->pParam->BSIM3v32leffCV; - qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { dxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { dxpart = 0.0; - } - else - { dxpart = 0.5; - } - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - } - else - { dxpart = here->BSIM3v32qdrn / qcheq; - Cdd = here->BSIM3v32cddb; - Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; - Cdg = here->BSIM3v32cdgb; - Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = here->BSIM3v32qdrn / qcheq; + Cdd = here->BSIM3v32cddb; + Csd = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3v32cdgb; + Csg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; - Cds = here->BSIM3v32cdsb; - Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + Cds = here->BSIM3v32cdsb; + Css = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg - + ddxpart_dVs); - } - sxpart = 1.0 - dxpart; - dsxpart_dVd = -ddxpart_dVd; - dsxpart_dVg = -ddxpart_dVg; - dsxpart_dVs = -ddxpart_dVs; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); } } else @@ -156,7 +156,7 @@ double m; gbspb = here->BSIM3v32gbbs; gbspdp = -(gbspg + gbspsp + gbspb); - if (here->BSIM3v32nqsMod == 0) + if (here->BSIM3v32nqsMod == 0) { cggb = here->BSIM3v32cggb; cgsb = here->BSIM3v32cgdb; cgdb = here->BSIM3v32cgsb; @@ -170,19 +170,19 @@ double m; cddb = -(here->BSIM3v32cdsb + cgdb + cbdb); xgtg = xgtd = xgts = xgtb = 0.0; - sxpart = 0.4; + sxpart = 0.4; dxpart = 0.6; - ddxpart_dVd = ddxpart_dVg = ddxpart_dVb - = ddxpart_dVs = 0.0; - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; } else { cggb = cgdb = cgsb = 0.0; cbgb = cbdb = cbsb = 0.0; cdgb = cddb = cdsb = 0.0; - xgtg = here->BSIM3v32gtg; + xgtg = here->BSIM3v32gtg; xgtd = here->BSIM3v32gts; xgts = here->BSIM3v32gtd; xgtb = here->BSIM3v32gtb; @@ -192,51 +192,51 @@ double m; xcqsb = here->BSIM3v32cqdb; xcqbb = here->BSIM3v32cqbb; - CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV + CoxWL = model->BSIM3v32cox * here->pParam->BSIM3v32weffCV * here->pParam->BSIM3v32leffCV; - qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); - if (fabs(qcheq) <= 1.0e-5 * CoxWL) - { if (model->BSIM3v32xpart < 0.5) - { sxpart = 0.4; - } - else if (model->BSIM3v32xpart > 0.5) - { sxpart = 0.0; - } - else - { sxpart = 0.5; - } - dsxpart_dVd = dsxpart_dVg = dsxpart_dVb - = dsxpart_dVs = 0.0; - } - else - { sxpart = here->BSIM3v32qdrn / qcheq; - Css = here->BSIM3v32cddb; - Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb - + here->BSIM3v32cbdb); - dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; - Csg = here->BSIM3v32cdgb; - Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb - + here->BSIM3v32cbgb); - dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + qcheq = -(here->BSIM3v32qgate + here->BSIM3v32qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3v32xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3v32xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = here->BSIM3v32qdrn / qcheq; + Css = here->BSIM3v32cddb; + Cds = -(here->BSIM3v32cgdb + here->BSIM3v32cddb + + here->BSIM3v32cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3v32cdgb; + Cdg = -(here->BSIM3v32cggb + here->BSIM3v32cdgb + + here->BSIM3v32cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; - Csd = here->BSIM3v32cdsb; - Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb - + here->BSIM3v32cbsb); - dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + Csd = here->BSIM3v32cdsb; + Cdd = -(here->BSIM3v32cgsb + here->BSIM3v32cdsb + + here->BSIM3v32cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; - dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg - + dsxpart_dVs); - } - dxpart = 1.0 - sxpart; - ddxpart_dVd = -dsxpart_dVd; - ddxpart_dVg = -dsxpart_dVg; - ddxpart_dVs = -dsxpart_dVs; - ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); } } - T1 = *(ckt->CKTstate0 + here->BSIM3v32qdef) * here->BSIM3v32gtau; + T1 = *(ckt->CKTstate0 + here->BSIM3v32qdef) * here->BSIM3v32gtau; gdpr = here->BSIM3v32drainConductance; gspr = here->BSIM3v32sourceConductance; gds = here->BSIM3v32gds; @@ -245,9 +245,9 @@ double m; capbd = here->BSIM3v32capbd; capbs = here->BSIM3v32capbs; - GSoverlapCap = here->BSIM3v32cgso; - GDoverlapCap = here->BSIM3v32cgdo; - GBoverlapCap = here->pParam->BSIM3v32cgbo; + GSoverlapCap = here->BSIM3v32cgso; + GDoverlapCap = here->BSIM3v32cgdo; + GBoverlapCap = here->pParam->BSIM3v32cgbo; xcdgb = (cdgb - GDoverlapCap); xcddb = (cddb + capbd + GDoverlapCap); @@ -256,7 +256,7 @@ double m; xcsgb = -(cggb + cbgb + cdgb + GSoverlapCap); xcsdb = -(cgdb + cbdb + cddb); xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)); - xcsbb = -(xcsgb + xcsdb + xcssb); + xcsbb = -(xcsgb + xcsdb + xcssb); xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap); xcgdb = (cgdb - GDoverlapCap); xcgsb = (cgsb - GSoverlapCap); @@ -266,7 +266,7 @@ double m; xcbsb = (cbsb - capbs); xcbbb = -(xcbgb + xcbdb + xcbsb); - m = here->BSIM3v32m; + m = here->BSIM3v32m; *(here->BSIM3v32GgPtr ) += m * (xcggb * s->real); *(here->BSIM3v32GgPtr +1) += m * (xcggb * s->imag); @@ -318,23 +318,23 @@ double m; *(here->BSIM3v32BdpPtr) -= m * (gbd - gbbdp); *(here->BSIM3v32BspPtr) -= m * (gbs - gbbsp); - *(here->BSIM3v32DPgPtr) += Gm + dxpart * xgtg - + T1 * ddxpart_dVg + gbdpg; + *(here->BSIM3v32DPgPtr) += Gm + dxpart * xgtg + + T1 * ddxpart_dVg + gbdpg; *(here->BSIM3v32DPdpPtr) += gdpr + gds + gbd + RevSum + dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp; *(here->BSIM3v32DPspPtr) -= gds + FwdSum - dxpart * xgts - - T1 * ddxpart_dVs - gbdpsp; + - T1 * ddxpart_dVs - gbdpsp; *(here->BSIM3v32DPbPtr) -= gbd - Gmbs - dxpart * xgtb - - T1 * ddxpart_dVb - gbdpb; + - T1 * ddxpart_dVb - gbdpb; *(here->BSIM3v32SPgPtr) -= Gm - sxpart * xgtg - - T1 * dsxpart_dVg - gbspg; + - T1 * dsxpart_dVg - gbspg; *(here->BSIM3v32SPspPtr) += gspr + gds + gbs + FwdSum + sxpart * xgts + T1 * dsxpart_dVs + gbspsp; *(here->BSIM3v32SPbPtr) -= gbs + Gmbs - sxpart * xgtb - - T1 * dsxpart_dVb - gbspb; + - T1 * dsxpart_dVb - gbspb; *(here->BSIM3v32SPdpPtr) -= gds + RevSum - sxpart * xgtd - - T1 * dsxpart_dVd - gbspdp; + - T1 * dsxpart_dVd - gbspdp; *(here->BSIM3v32GgPtr) -= xgtg; *(here->BSIM3v32GbPtr) -= xgtb; diff --git a/src/spicelib/devices/bsim3v32/b3v32set.c b/src/spicelib/devices/bsim3v32/b3v32set.c index df50109ca..e558536e3 100644 --- a/src/spicelib/devices/bsim3v32/b3v32set.c +++ b/src/spicelib/devices/bsim3v32/b3v32set.c @@ -54,8 +54,16 @@ IFuid tmpName; model->BSIM3v32capMod = 3; if (!model->BSIM3v32acmModGiven) model->BSIM3v32acmMod = 0; + if (!model->BSIM3v32calcacmGiven) + model->BSIM3v32calcacm = 0; if (!model->BSIM3v32noiModGiven) model->BSIM3v32noiMod = 1; + if (!model->BSIM3v32nqsModGiven) + model->BSIM3v32nqsMod = 0; + else if ((model->BSIM3v32nqsMod != 0) && (model->BSIM3v32nqsMod != 1)) + { model->BSIM3v32nqsMod = 0; + printf("Warning: nqsMod has been set to its default value: 0.\n"); + } /* If the user does not provide the model revision, * we always choose the most recent. @@ -259,7 +267,7 @@ IFuid tmpName; if (!model->BSIM3v32tpbswgGiven) model->BSIM3v32tpbswg = 0.0; - /* acm model */ + /* ACM model */ if (!model->BSIM3v32hdifGiven) model->BSIM3v32hdif = 0.0; if (!model->BSIM3v32ldifGiven) @@ -274,6 +282,8 @@ IFuid tmpName; model->BSIM3v32rdc = 0.0; if (!model->BSIM3v32rscGiven) model->BSIM3v32rsc = 0.0; + if (!model->BSIM3v32wmltGiven) + model->BSIM3v32wmlt = 1.0; /* Length dependence */ if (!model->BSIM3v32lcdscGiven) @@ -938,7 +948,14 @@ IFuid tmpName; if (!here->BSIM3v32wGiven) here->BSIM3v32w = 5.0e-6; if (!here->BSIM3v32nqsModGiven) - here->BSIM3v32nqsMod = 0; + here->BSIM3v32nqsMod = model->BSIM3v32nqsMod; + else if ((here->BSIM3v32nqsMod != 0) && (here->BSIM3v32nqsMod != 1)) + { here->BSIM3v32nqsMod = model->BSIM3v32nqsMod; + printf("Warning: nqsMod has been set to its global value %d.\n", + model->BSIM3v32nqsMod); + } + if (!here->BSIM3v32geoGiven) + here->BSIM3v32geo = 0; if (!here->BSIM3v32mGiven) here->BSIM3v32m = 1; @@ -995,14 +1012,14 @@ IFuid tmpName; { here->BSIM3v32sNodePrime = here->BSIM3v32sNode; } - /* internal charge node */ + /* internal charge node */ if (here->BSIM3v32nqsMod) { if(here->BSIM3v32qNode == 0) - { error = CKTmkVolt(ckt,&tmp,here->BSIM3v32name,"charge"); - if(error) return(error); - here->BSIM3v32qNode = tmp->number; - } + { error = CKTmkVolt(ckt,&tmp,here->BSIM3v32name,"charge"); + if(error) return(error); + here->BSIM3v32qNode = tmp->number; + } } else { here->BSIM3v32qNode = 0; @@ -1012,43 +1029,43 @@ IFuid tmpName; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM3v32DdPtr, BSIM3v32dNode, BSIM3v32dNode) - TSTALLOC(BSIM3v32GgPtr, BSIM3v32gNode, BSIM3v32gNode) - TSTALLOC(BSIM3v32SsPtr, BSIM3v32sNode, BSIM3v32sNode) - TSTALLOC(BSIM3v32BbPtr, BSIM3v32bNode, BSIM3v32bNode) - TSTALLOC(BSIM3v32DPdpPtr, BSIM3v32dNodePrime, BSIM3v32dNodePrime) - TSTALLOC(BSIM3v32SPspPtr, BSIM3v32sNodePrime, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32DdpPtr, BSIM3v32dNode, BSIM3v32dNodePrime) - TSTALLOC(BSIM3v32GbPtr, BSIM3v32gNode, BSIM3v32bNode) - TSTALLOC(BSIM3v32GdpPtr, BSIM3v32gNode, BSIM3v32dNodePrime) - TSTALLOC(BSIM3v32GspPtr, BSIM3v32gNode, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32SspPtr, BSIM3v32sNode, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32BdpPtr, BSIM3v32bNode, BSIM3v32dNodePrime) - TSTALLOC(BSIM3v32BspPtr, BSIM3v32bNode, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32DPspPtr, BSIM3v32dNodePrime, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32DPdPtr, BSIM3v32dNodePrime, BSIM3v32dNode) - TSTALLOC(BSIM3v32BgPtr, BSIM3v32bNode, BSIM3v32gNode) - TSTALLOC(BSIM3v32DPgPtr, BSIM3v32dNodePrime, BSIM3v32gNode) - TSTALLOC(BSIM3v32SPgPtr, BSIM3v32sNodePrime, BSIM3v32gNode) - TSTALLOC(BSIM3v32SPsPtr, BSIM3v32sNodePrime, BSIM3v32sNode) - TSTALLOC(BSIM3v32DPbPtr, BSIM3v32dNodePrime, BSIM3v32bNode) - TSTALLOC(BSIM3v32SPbPtr, BSIM3v32sNodePrime, BSIM3v32bNode) - TSTALLOC(BSIM3v32SPdpPtr, BSIM3v32sNodePrime, BSIM3v32dNodePrime) + TSTALLOC(BSIM3v32DdPtr, BSIM3v32dNode, BSIM3v32dNode); + TSTALLOC(BSIM3v32GgPtr, BSIM3v32gNode, BSIM3v32gNode); + TSTALLOC(BSIM3v32SsPtr, BSIM3v32sNode, BSIM3v32sNode); + TSTALLOC(BSIM3v32BbPtr, BSIM3v32bNode, BSIM3v32bNode); + TSTALLOC(BSIM3v32DPdpPtr, BSIM3v32dNodePrime, BSIM3v32dNodePrime); + TSTALLOC(BSIM3v32SPspPtr, BSIM3v32sNodePrime, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32DdpPtr, BSIM3v32dNode, BSIM3v32dNodePrime); + TSTALLOC(BSIM3v32GbPtr, BSIM3v32gNode, BSIM3v32bNode); + TSTALLOC(BSIM3v32GdpPtr, BSIM3v32gNode, BSIM3v32dNodePrime); + TSTALLOC(BSIM3v32GspPtr, BSIM3v32gNode, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32SspPtr, BSIM3v32sNode, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32BdpPtr, BSIM3v32bNode, BSIM3v32dNodePrime); + TSTALLOC(BSIM3v32BspPtr, BSIM3v32bNode, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32DPspPtr, BSIM3v32dNodePrime, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32DPdPtr, BSIM3v32dNodePrime, BSIM3v32dNode); + TSTALLOC(BSIM3v32BgPtr, BSIM3v32bNode, BSIM3v32gNode); + TSTALLOC(BSIM3v32DPgPtr, BSIM3v32dNodePrime, BSIM3v32gNode); + TSTALLOC(BSIM3v32SPgPtr, BSIM3v32sNodePrime, BSIM3v32gNode); + TSTALLOC(BSIM3v32SPsPtr, BSIM3v32sNodePrime, BSIM3v32sNode); + TSTALLOC(BSIM3v32DPbPtr, BSIM3v32dNodePrime, BSIM3v32bNode); + TSTALLOC(BSIM3v32SPbPtr, BSIM3v32sNodePrime, BSIM3v32bNode); + TSTALLOC(BSIM3v32SPdpPtr, BSIM3v32sNodePrime, BSIM3v32dNodePrime); - TSTALLOC(BSIM3v32QqPtr, BSIM3v32qNode, BSIM3v32qNode) + TSTALLOC(BSIM3v32QqPtr, BSIM3v32qNode, BSIM3v32qNode); - TSTALLOC(BSIM3v32QdpPtr, BSIM3v32qNode, BSIM3v32dNodePrime) - TSTALLOC(BSIM3v32QspPtr, BSIM3v32qNode, BSIM3v32sNodePrime) - TSTALLOC(BSIM3v32QgPtr, BSIM3v32qNode, BSIM3v32gNode) - TSTALLOC(BSIM3v32QbPtr, BSIM3v32qNode, BSIM3v32bNode) - TSTALLOC(BSIM3v32DPqPtr, BSIM3v32dNodePrime, BSIM3v32qNode) - TSTALLOC(BSIM3v32SPqPtr, BSIM3v32sNodePrime, BSIM3v32qNode) - TSTALLOC(BSIM3v32GqPtr, BSIM3v32gNode, BSIM3v32qNode) - TSTALLOC(BSIM3v32BqPtr, BSIM3v32bNode, BSIM3v32qNode) + TSTALLOC(BSIM3v32QdpPtr, BSIM3v32qNode, BSIM3v32dNodePrime); + TSTALLOC(BSIM3v32QspPtr, BSIM3v32qNode, BSIM3v32sNodePrime); + TSTALLOC(BSIM3v32QgPtr, BSIM3v32qNode, BSIM3v32gNode); + TSTALLOC(BSIM3v32QbPtr, BSIM3v32qNode, BSIM3v32bNode); + TSTALLOC(BSIM3v32DPqPtr, BSIM3v32dNodePrime, BSIM3v32qNode); + TSTALLOC(BSIM3v32SPqPtr, BSIM3v32sNodePrime, BSIM3v32qNode); + TSTALLOC(BSIM3v32GqPtr, BSIM3v32gNode, BSIM3v32qNode); + TSTALLOC(BSIM3v32BqPtr, BSIM3v32bNode, BSIM3v32qNode); } } diff --git a/src/spicelib/devices/bsim3v32/b3v32temp.c b/src/spicelib/devices/bsim3v32/b3v32temp.c index 612b2789d..42ea5f275 100644 --- a/src/spicelib/devices/bsim3v32/b3v32temp.c +++ b/src/spicelib/devices/bsim3v32/b3v32temp.c @@ -15,6 +15,7 @@ #include "bsim3v32def.h" #include "ngspice/const.h" #include "ngspice/sperror.h" +#include "ngspice/devdefs.h" #include "ngspice/suffix.h" #define Kb 1.3806226e-23 @@ -37,30 +38,30 @@ struct bsim3v32SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam=NULL; double tmp, tmp1, tmp2, tmp3, Eg, Eg0, ni, T0, T1, T2, T3, T4, T5, Ldrn, Wdrn; double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom; double Nvtm, SourceSatCurrent, DrainSatCurrent; -int Size_Not_Found; +int Size_Not_Found, error; /* loop through all the BSIM3v32 device models */ for (; model != NULL; model = model->BSIM3v32nextModel) { Temp = ckt->CKTtemp; if (model->BSIM3v32bulkJctPotential < 0.1) - { model->BSIM3v32bulkJctPotential = 0.1; - fprintf(stderr, "Given pb is less than 0.1. Pb is set to 0.1.\n"); - } + { model->BSIM3v32bulkJctPotential = 0.1; + fprintf(stderr, "Given pb is less than 0.1. Pb is set to 0.1.\n"); + } if (model->BSIM3v32sidewallJctPotential < 0.1) - { model->BSIM3v32sidewallJctPotential = 0.1; - fprintf(stderr, "Given pbsw is less than 0.1. Pbsw is set to 0.1.\n"); - } + { model->BSIM3v32sidewallJctPotential = 0.1; + fprintf(stderr, "Given pbsw is less than 0.1. Pbsw is set to 0.1.\n"); + } if (model->BSIM3v32GatesidewallJctPotential < 0.1) - { model->BSIM3v32GatesidewallJctPotential = 0.1; - fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); - } + { model->BSIM3v32GatesidewallJctPotential = 0.1; + fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); + } model->pSizeDependParamKnot = NULL; - pLastKnot = NULL; + pLastKnot = NULL; - Tnom = model->BSIM3v32tnom; - TRatio = Temp / Tnom; + Tnom = model->BSIM3v32tnom; + TRatio = Temp / Tnom; - model->BSIM3v32vcrit = CONSTvt0 * log(CONSTvt0 / (CONSTroot2 * 1.0e-14)); + model->BSIM3v32vcrit = CONSTvt0 * log(CONSTvt0 / (CONSTroot2 * 1.0e-14)); model->BSIM3v32factor1 = sqrt(EPSSI / EPSOX * model->BSIM3v32tox); Vtm0 = KboQ * Tnom; @@ -70,167 +71,167 @@ int Size_Not_Found; model->BSIM3v32vtm = KboQ * Temp; Eg = 1.16 - 7.02e-4 * Temp * Temp / (Temp + 1108.0); - if (Temp != Tnom) - { T0 = Eg0 / Vtm0 - Eg / model->BSIM3v32vtm + model->BSIM3v32jctTempExponent - * log(Temp / Tnom); - T1 = exp(T0 / model->BSIM3v32jctEmissionCoeff); - model->BSIM3v32jctTempSatCurDensity = model->BSIM3v32jctSatCurDensity - * T1; - model->BSIM3v32jctSidewallTempSatCurDensity - = model->BSIM3v32jctSidewallSatCurDensity * T1; - } - else - { model->BSIM3v32jctTempSatCurDensity = model->BSIM3v32jctSatCurDensity; - model->BSIM3v32jctSidewallTempSatCurDensity - = model->BSIM3v32jctSidewallSatCurDensity; - } + if (Temp != Tnom) + { T0 = Eg0 / Vtm0 - Eg / model->BSIM3v32vtm + model->BSIM3v32jctTempExponent + * log(Temp / Tnom); + T1 = exp(T0 / model->BSIM3v32jctEmissionCoeff); + model->BSIM3v32jctTempSatCurDensity = model->BSIM3v32jctSatCurDensity + * T1; + model->BSIM3v32jctSidewallTempSatCurDensity + = model->BSIM3v32jctSidewallSatCurDensity * T1; + } + else + { model->BSIM3v32jctTempSatCurDensity = model->BSIM3v32jctSatCurDensity; + model->BSIM3v32jctSidewallTempSatCurDensity + = model->BSIM3v32jctSidewallSatCurDensity; + } - if (model->BSIM3v32jctTempSatCurDensity < 0.0) - model->BSIM3v32jctTempSatCurDensity = 0.0; - if (model->BSIM3v32jctSidewallTempSatCurDensity < 0.0) - model->BSIM3v32jctSidewallTempSatCurDensity = 0.0; + if (model->BSIM3v32jctTempSatCurDensity < 0.0) + model->BSIM3v32jctTempSatCurDensity = 0.0; + if (model->BSIM3v32jctSidewallTempSatCurDensity < 0.0) + model->BSIM3v32jctSidewallTempSatCurDensity = 0.0; - /* Temperature dependence of D/B and S/B diode capacitance begins */ - delTemp = ckt->CKTtemp - model->BSIM3v32tnom; - T0 = model->BSIM3v32tcj * delTemp; - if (T0 >= -1.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitAreaTempJctCap = - model->BSIM3v32unitAreaJctCap * (1.0 + T0); - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitAreaJctCap *= 1.0 + T0; - } - } - else if (model->BSIM3v32unitAreaJctCap > 0.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitAreaTempJctCap = 0.0; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitAreaJctCap = 0.0; - } - fprintf(stderr, "Temperature effect has caused cj to be negative. Cj is clamped to zero.\n"); - } + /* Temperature dependence of D/B and S/B diode capacitance begins */ + delTemp = ckt->CKTtemp - model->BSIM3v32tnom; + T0 = model->BSIM3v32tcj * delTemp; + if (T0 >= -1.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitAreaTempJctCap = + model->BSIM3v32unitAreaJctCap * (1.0 + T0); + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitAreaJctCap *= 1.0 + T0; + } + } + else if (model->BSIM3v32unitAreaJctCap > 0.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitAreaTempJctCap = 0.0; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitAreaJctCap = 0.0; + } + fprintf(stderr, "Temperature effect has caused cj to be negative. Cj is clamped to zero.\n"); + } T0 = model->BSIM3v32tcjsw * delTemp; - if (T0 >= -1.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitLengthSidewallTempJctCap = - model->BSIM3v32unitLengthSidewallJctCap * (1.0 + T0); - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitLengthSidewallJctCap *= 1.0 + T0; - } - } - else if (model->BSIM3v32unitLengthSidewallJctCap > 0.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitLengthSidewallTempJctCap = 0.0; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitLengthSidewallJctCap = 0.0; - } - fprintf(stderr, "Temperature effect has caused cjsw to be negative. Cjsw is clamped to zero.\n"); - } + if (T0 >= -1.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitLengthSidewallTempJctCap = + model->BSIM3v32unitLengthSidewallJctCap * (1.0 + T0); + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitLengthSidewallJctCap *= 1.0 + T0; + } + } + else if (model->BSIM3v32unitLengthSidewallJctCap > 0.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitLengthSidewallTempJctCap = 0.0; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitLengthSidewallJctCap = 0.0; + } + fprintf(stderr, "Temperature effect has caused cjsw to be negative. Cjsw is clamped to zero.\n"); + } T0 = model->BSIM3v32tcjswg * delTemp; - if (T0 >= -1.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitLengthGateSidewallTempJctCap = - model->BSIM3v32unitLengthGateSidewallJctCap * (1.0 + T0); - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitLengthGateSidewallJctCap *= 1.0 + T0; - } - } - else if (model->BSIM3v32unitLengthGateSidewallJctCap > 0.0) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - model->BSIM3v32unitLengthGateSidewallTempJctCap = 0.0; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - model->BSIM3v32unitLengthGateSidewallJctCap = 0.0; - } - fprintf(stderr, "Temperature effect has caused cjswg to be negative. Cjswg is clamped to zero.\n"); - } + if (T0 >= -1.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitLengthGateSidewallTempJctCap = + model->BSIM3v32unitLengthGateSidewallJctCap * (1.0 + T0); + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitLengthGateSidewallJctCap *= 1.0 + T0; + } + } + else if (model->BSIM3v32unitLengthGateSidewallJctCap > 0.0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + model->BSIM3v32unitLengthGateSidewallTempJctCap = 0.0; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + model->BSIM3v32unitLengthGateSidewallJctCap = 0.0; + } + fprintf(stderr, "Temperature effect has caused cjswg to be negative. Cjswg is clamped to zero.\n"); + } model->BSIM3v32PhiB = model->BSIM3v32bulkJctPotential - - model->BSIM3v32tpb * delTemp; + - model->BSIM3v32tpb * delTemp; if (model->BSIM3v32PhiB < 0.01) - { model->BSIM3v32PhiB = 0.01; - fprintf(stderr, "Temperature effect has caused pb to be less than 0.01. Pb is clamped to 0.01.\n"); - } + { model->BSIM3v32PhiB = 0.01; + fprintf(stderr, "Temperature effect has caused pb to be less than 0.01. Pb is clamped to 0.01.\n"); + } model->BSIM3v32PhiBSW = model->BSIM3v32sidewallJctPotential - model->BSIM3v32tpbsw * delTemp; if (model->BSIM3v32PhiBSW <= 0.01) - { model->BSIM3v32PhiBSW = 0.01; - fprintf(stderr, "Temperature effect has caused pbsw to be less than 0.01. Pbsw is clamped to 0.01.\n"); - } - model->BSIM3v32PhiBSWG = model->BSIM3v32GatesidewallJctPotential + { model->BSIM3v32PhiBSW = 0.01; + fprintf(stderr, "Temperature effect has caused pbsw to be less than 0.01. Pbsw is clamped to 0.01.\n"); + } + model->BSIM3v32PhiBSWG = model->BSIM3v32GatesidewallJctPotential - model->BSIM3v32tpbswg * delTemp; if (model->BSIM3v32PhiBSWG <= 0.01) - { model->BSIM3v32PhiBSWG = 0.01; - fprintf(stderr, "Temperature effect has caused pbswg to be less than 0.01. Pbswg is clamped to 0.01.\n"); - } + { model->BSIM3v32PhiBSWG = 0.01; + fprintf(stderr, "Temperature effect has caused pbswg to be less than 0.01. Pbswg is clamped to 0.01.\n"); + } /* End of junction capacitance */ - /* loop through all the instances of the model */ - /* MCJ: Length and Width not initialized */ - for (here = model->BSIM3v32instances; here != NULL; + /* loop through all the instances of the model */ + /* MCJ: Length and Width not initialized */ + for (here = model->BSIM3v32instances; here != NULL; here = here->BSIM3v32nextInstance) - { - pSizeDependParamKnot = model->pSizeDependParamKnot; - Size_Not_Found = 1; - while ((pSizeDependParamKnot != NULL) && Size_Not_Found) - { if ((here->BSIM3v32l == pSizeDependParamKnot->Length) - && (here->BSIM3v32w == pSizeDependParamKnot->Width)) + { + pSizeDependParamKnot = model->pSizeDependParamKnot; + Size_Not_Found = 1; + while ((pSizeDependParamKnot != NULL) && Size_Not_Found) + { if ((here->BSIM3v32l == pSizeDependParamKnot->Length) + && (here->BSIM3v32w == pSizeDependParamKnot->Width)) { Size_Not_Found = 0; - here->pParam = pSizeDependParamKnot; - if (model->BSIM3v32intVersion > BSIM3v32V322) + here->pParam = pSizeDependParamKnot; + if (model->BSIM3v32intVersion > BSIM3v32V322) { - pParam = here->pParam; /*bug-fix */ - } - } - else - { pLastKnot = pSizeDependParamKnot; - pSizeDependParamKnot = pSizeDependParamKnot->pNext; - } + pParam = here->pParam; /*bug-fix */ + } + } + else + { pLastKnot = pSizeDependParamKnot; + pSizeDependParamKnot = pSizeDependParamKnot->pNext; + } } - if (Size_Not_Found) - { pParam = TMALLOC(struct bsim3v32SizeDependParam, 1); + if (Size_Not_Found) + { pParam = TMALLOC(struct bsim3v32SizeDependParam, 1); if (pLastKnot == NULL) model->pSizeDependParamKnot = pParam; else @@ -263,7 +264,7 @@ int Size_Not_Found; pParam->BSIM3v32leff = here->BSIM3v32l + model->BSIM3v32xl - 2.0 * pParam->BSIM3v32dl; if (pParam->BSIM3v32leff <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3v32modName; namarray[1] = here->BSIM3v32name; SPfrontEnd->IFerror (ERR_FATAL, @@ -274,7 +275,7 @@ int Size_Not_Found; pParam->BSIM3v32weff = here->BSIM3v32w + model->BSIM3v32xw - 2.0 * pParam->BSIM3v32dw; if (pParam->BSIM3v32weff <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3v32modName; namarray[1] = here->BSIM3v32name; SPfrontEnd->IFerror (ERR_FATAL, @@ -285,7 +286,7 @@ int Size_Not_Found; pParam->BSIM3v32leffCV = here->BSIM3v32l + model->BSIM3v32xl - 2.0 * pParam->BSIM3v32dlc; if (pParam->BSIM3v32leffCV <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3v32modName; namarray[1] = here->BSIM3v32name; SPfrontEnd->IFerror (ERR_FATAL, @@ -296,7 +297,7 @@ int Size_Not_Found; pParam->BSIM3v32weffCV = here->BSIM3v32w + model->BSIM3v32xw - 2.0 * pParam->BSIM3v32dwc; if (pParam->BSIM3v32weffCV <= 0.0) - { IFuid namarray[2]; + { IFuid namarray[2]; namarray[0] = model->BSIM3v32modName; namarray[1] = here->BSIM3v32name; SPfrontEnd->IFerror (ERR_FATAL, @@ -306,744 +307,711 @@ int Size_Not_Found; } - if (model->BSIM3v32binUnit == 1) - { Inv_L = 1.0e-6 / pParam->BSIM3v32leff; - Inv_W = 1.0e-6 / pParam->BSIM3v32weff; - Inv_LW = 1.0e-12 / (pParam->BSIM3v32leff - * pParam->BSIM3v32weff); - } - else - { Inv_L = 1.0 / pParam->BSIM3v32leff; - Inv_W = 1.0 / pParam->BSIM3v32weff; - Inv_LW = 1.0 / (pParam->BSIM3v32leff - * pParam->BSIM3v32weff); - } - pParam->BSIM3v32cdsc = model->BSIM3v32cdsc - + model->BSIM3v32lcdsc * Inv_L - + model->BSIM3v32wcdsc * Inv_W - + model->BSIM3v32pcdsc * Inv_LW; - pParam->BSIM3v32cdscb = model->BSIM3v32cdscb - + model->BSIM3v32lcdscb * Inv_L - + model->BSIM3v32wcdscb * Inv_W - + model->BSIM3v32pcdscb * Inv_LW; + if (model->BSIM3v32binUnit == 1) + { Inv_L = 1.0e-6 / pParam->BSIM3v32leff; + Inv_W = 1.0e-6 / pParam->BSIM3v32weff; + Inv_LW = 1.0e-12 / (pParam->BSIM3v32leff + * pParam->BSIM3v32weff); + } + else + { Inv_L = 1.0 / pParam->BSIM3v32leff; + Inv_W = 1.0 / pParam->BSIM3v32weff; + Inv_LW = 1.0 / (pParam->BSIM3v32leff + * pParam->BSIM3v32weff); + } + pParam->BSIM3v32cdsc = model->BSIM3v32cdsc + + model->BSIM3v32lcdsc * Inv_L + + model->BSIM3v32wcdsc * Inv_W + + model->BSIM3v32pcdsc * Inv_LW; + pParam->BSIM3v32cdscb = model->BSIM3v32cdscb + + model->BSIM3v32lcdscb * Inv_L + + model->BSIM3v32wcdscb * Inv_W + + model->BSIM3v32pcdscb * Inv_LW; - pParam->BSIM3v32cdscd = model->BSIM3v32cdscd - + model->BSIM3v32lcdscd * Inv_L - + model->BSIM3v32wcdscd * Inv_W - + model->BSIM3v32pcdscd * Inv_LW; + pParam->BSIM3v32cdscd = model->BSIM3v32cdscd + + model->BSIM3v32lcdscd * Inv_L + + model->BSIM3v32wcdscd * Inv_W + + model->BSIM3v32pcdscd * Inv_LW; - pParam->BSIM3v32cit = model->BSIM3v32cit - + model->BSIM3v32lcit * Inv_L - + model->BSIM3v32wcit * Inv_W - + model->BSIM3v32pcit * Inv_LW; - pParam->BSIM3v32nfactor = model->BSIM3v32nfactor - + model->BSIM3v32lnfactor * Inv_L - + model->BSIM3v32wnfactor * Inv_W - + model->BSIM3v32pnfactor * Inv_LW; - pParam->BSIM3v32xj = model->BSIM3v32xj - + model->BSIM3v32lxj * Inv_L - + model->BSIM3v32wxj * Inv_W - + model->BSIM3v32pxj * Inv_LW; - pParam->BSIM3v32vsat = model->BSIM3v32vsat - + model->BSIM3v32lvsat * Inv_L - + model->BSIM3v32wvsat * Inv_W - + model->BSIM3v32pvsat * Inv_LW; - pParam->BSIM3v32at = model->BSIM3v32at - + model->BSIM3v32lat * Inv_L - + model->BSIM3v32wat * Inv_W - + model->BSIM3v32pat * Inv_LW; - pParam->BSIM3v32a0 = model->BSIM3v32a0 - + model->BSIM3v32la0 * Inv_L - + model->BSIM3v32wa0 * Inv_W - + model->BSIM3v32pa0 * Inv_LW; + pParam->BSIM3v32cit = model->BSIM3v32cit + + model->BSIM3v32lcit * Inv_L + + model->BSIM3v32wcit * Inv_W + + model->BSIM3v32pcit * Inv_LW; + pParam->BSIM3v32nfactor = model->BSIM3v32nfactor + + model->BSIM3v32lnfactor * Inv_L + + model->BSIM3v32wnfactor * Inv_W + + model->BSIM3v32pnfactor * Inv_LW; + pParam->BSIM3v32xj = model->BSIM3v32xj + + model->BSIM3v32lxj * Inv_L + + model->BSIM3v32wxj * Inv_W + + model->BSIM3v32pxj * Inv_LW; + pParam->BSIM3v32vsat = model->BSIM3v32vsat + + model->BSIM3v32lvsat * Inv_L + + model->BSIM3v32wvsat * Inv_W + + model->BSIM3v32pvsat * Inv_LW; + pParam->BSIM3v32at = model->BSIM3v32at + + model->BSIM3v32lat * Inv_L + + model->BSIM3v32wat * Inv_W + + model->BSIM3v32pat * Inv_LW; + pParam->BSIM3v32a0 = model->BSIM3v32a0 + + model->BSIM3v32la0 * Inv_L + + model->BSIM3v32wa0 * Inv_W + + model->BSIM3v32pa0 * Inv_LW; - pParam->BSIM3v32ags = model->BSIM3v32ags - + model->BSIM3v32lags * Inv_L - + model->BSIM3v32wags * Inv_W - + model->BSIM3v32pags * Inv_LW; + pParam->BSIM3v32ags = model->BSIM3v32ags + + model->BSIM3v32lags * Inv_L + + model->BSIM3v32wags * Inv_W + + model->BSIM3v32pags * Inv_LW; - pParam->BSIM3v32a1 = model->BSIM3v32a1 - + model->BSIM3v32la1 * Inv_L - + model->BSIM3v32wa1 * Inv_W - + model->BSIM3v32pa1 * Inv_LW; - pParam->BSIM3v32a2 = model->BSIM3v32a2 - + model->BSIM3v32la2 * Inv_L - + model->BSIM3v32wa2 * Inv_W - + model->BSIM3v32pa2 * Inv_LW; - pParam->BSIM3v32keta = model->BSIM3v32keta - + model->BSIM3v32lketa * Inv_L - + model->BSIM3v32wketa * Inv_W - + model->BSIM3v32pketa * Inv_LW; - pParam->BSIM3v32nsub = model->BSIM3v32nsub - + model->BSIM3v32lnsub * Inv_L - + model->BSIM3v32wnsub * Inv_W - + model->BSIM3v32pnsub * Inv_LW; - pParam->BSIM3v32npeak = model->BSIM3v32npeak - + model->BSIM3v32lnpeak * Inv_L - + model->BSIM3v32wnpeak * Inv_W - + model->BSIM3v32pnpeak * Inv_LW; - pParam->BSIM3v32ngate = model->BSIM3v32ngate - + model->BSIM3v32lngate * Inv_L - + model->BSIM3v32wngate * Inv_W - + model->BSIM3v32pngate * Inv_LW; - pParam->BSIM3v32gamma1 = model->BSIM3v32gamma1 - + model->BSIM3v32lgamma1 * Inv_L - + model->BSIM3v32wgamma1 * Inv_W - + model->BSIM3v32pgamma1 * Inv_LW; - pParam->BSIM3v32gamma2 = model->BSIM3v32gamma2 - + model->BSIM3v32lgamma2 * Inv_L - + model->BSIM3v32wgamma2 * Inv_W - + model->BSIM3v32pgamma2 * Inv_LW; - pParam->BSIM3v32vbx = model->BSIM3v32vbx - + model->BSIM3v32lvbx * Inv_L - + model->BSIM3v32wvbx * Inv_W - + model->BSIM3v32pvbx * Inv_LW; - pParam->BSIM3v32vbm = model->BSIM3v32vbm - + model->BSIM3v32lvbm * Inv_L - + model->BSIM3v32wvbm * Inv_W - + model->BSIM3v32pvbm * Inv_LW; - pParam->BSIM3v32xt = model->BSIM3v32xt - + model->BSIM3v32lxt * Inv_L - + model->BSIM3v32wxt * Inv_W - + model->BSIM3v32pxt * Inv_LW; - pParam->BSIM3v32vfb = model->BSIM3v32vfb - + model->BSIM3v32lvfb * Inv_L - + model->BSIM3v32wvfb * Inv_W - + model->BSIM3v32pvfb * Inv_LW; - pParam->BSIM3v32k1 = model->BSIM3v32k1 - + model->BSIM3v32lk1 * Inv_L - + model->BSIM3v32wk1 * Inv_W - + model->BSIM3v32pk1 * Inv_LW; - pParam->BSIM3v32kt1 = model->BSIM3v32kt1 - + model->BSIM3v32lkt1 * Inv_L - + model->BSIM3v32wkt1 * Inv_W - + model->BSIM3v32pkt1 * Inv_LW; - pParam->BSIM3v32kt1l = model->BSIM3v32kt1l - + model->BSIM3v32lkt1l * Inv_L - + model->BSIM3v32wkt1l * Inv_W - + model->BSIM3v32pkt1l * Inv_LW; - pParam->BSIM3v32k2 = model->BSIM3v32k2 - + model->BSIM3v32lk2 * Inv_L - + model->BSIM3v32wk2 * Inv_W - + model->BSIM3v32pk2 * Inv_LW; - pParam->BSIM3v32kt2 = model->BSIM3v32kt2 - + model->BSIM3v32lkt2 * Inv_L - + model->BSIM3v32wkt2 * Inv_W - + model->BSIM3v32pkt2 * Inv_LW; - pParam->BSIM3v32k3 = model->BSIM3v32k3 - + model->BSIM3v32lk3 * Inv_L - + model->BSIM3v32wk3 * Inv_W - + model->BSIM3v32pk3 * Inv_LW; - pParam->BSIM3v32k3b = model->BSIM3v32k3b - + model->BSIM3v32lk3b * Inv_L - + model->BSIM3v32wk3b * Inv_W - + model->BSIM3v32pk3b * Inv_LW; - pParam->BSIM3v32w0 = model->BSIM3v32w0 - + model->BSIM3v32lw0 * Inv_L - + model->BSIM3v32ww0 * Inv_W - + model->BSIM3v32pw0 * Inv_LW; - pParam->BSIM3v32nlx = model->BSIM3v32nlx - + model->BSIM3v32lnlx * Inv_L - + model->BSIM3v32wnlx * Inv_W - + model->BSIM3v32pnlx * Inv_LW; - pParam->BSIM3v32dvt0 = model->BSIM3v32dvt0 - + model->BSIM3v32ldvt0 * Inv_L - + model->BSIM3v32wdvt0 * Inv_W - + model->BSIM3v32pdvt0 * Inv_LW; - pParam->BSIM3v32dvt1 = model->BSIM3v32dvt1 - + model->BSIM3v32ldvt1 * Inv_L - + model->BSIM3v32wdvt1 * Inv_W - + model->BSIM3v32pdvt1 * Inv_LW; - pParam->BSIM3v32dvt2 = model->BSIM3v32dvt2 - + model->BSIM3v32ldvt2 * Inv_L - + model->BSIM3v32wdvt2 * Inv_W - + model->BSIM3v32pdvt2 * Inv_LW; - pParam->BSIM3v32dvt0w = model->BSIM3v32dvt0w - + model->BSIM3v32ldvt0w * Inv_L - + model->BSIM3v32wdvt0w * Inv_W - + model->BSIM3v32pdvt0w * Inv_LW; - pParam->BSIM3v32dvt1w = model->BSIM3v32dvt1w - + model->BSIM3v32ldvt1w * Inv_L - + model->BSIM3v32wdvt1w * Inv_W - + model->BSIM3v32pdvt1w * Inv_LW; - pParam->BSIM3v32dvt2w = model->BSIM3v32dvt2w - + model->BSIM3v32ldvt2w * Inv_L - + model->BSIM3v32wdvt2w * Inv_W - + model->BSIM3v32pdvt2w * Inv_LW; - pParam->BSIM3v32drout = model->BSIM3v32drout - + model->BSIM3v32ldrout * Inv_L - + model->BSIM3v32wdrout * Inv_W - + model->BSIM3v32pdrout * Inv_LW; - pParam->BSIM3v32dsub = model->BSIM3v32dsub - + model->BSIM3v32ldsub * Inv_L - + model->BSIM3v32wdsub * Inv_W - + model->BSIM3v32pdsub * Inv_LW; - pParam->BSIM3v32vth0 = model->BSIM3v32vth0 - + model->BSIM3v32lvth0 * Inv_L - + model->BSIM3v32wvth0 * Inv_W - + model->BSIM3v32pvth0 * Inv_LW; - pParam->BSIM3v32ua = model->BSIM3v32ua - + model->BSIM3v32lua * Inv_L - + model->BSIM3v32wua * Inv_W - + model->BSIM3v32pua * Inv_LW; - pParam->BSIM3v32ua1 = model->BSIM3v32ua1 - + model->BSIM3v32lua1 * Inv_L - + model->BSIM3v32wua1 * Inv_W - + model->BSIM3v32pua1 * Inv_LW; - pParam->BSIM3v32ub = model->BSIM3v32ub - + model->BSIM3v32lub * Inv_L - + model->BSIM3v32wub * Inv_W - + model->BSIM3v32pub * Inv_LW; - pParam->BSIM3v32ub1 = model->BSIM3v32ub1 - + model->BSIM3v32lub1 * Inv_L - + model->BSIM3v32wub1 * Inv_W - + model->BSIM3v32pub1 * Inv_LW; - pParam->BSIM3v32uc = model->BSIM3v32uc - + model->BSIM3v32luc * Inv_L - + model->BSIM3v32wuc * Inv_W - + model->BSIM3v32puc * Inv_LW; - pParam->BSIM3v32uc1 = model->BSIM3v32uc1 - + model->BSIM3v32luc1 * Inv_L - + model->BSIM3v32wuc1 * Inv_W - + model->BSIM3v32puc1 * Inv_LW; - pParam->BSIM3v32u0 = model->BSIM3v32u0 - + model->BSIM3v32lu0 * Inv_L - + model->BSIM3v32wu0 * Inv_W - + model->BSIM3v32pu0 * Inv_LW; - pParam->BSIM3v32ute = model->BSIM3v32ute - + model->BSIM3v32lute * Inv_L - + model->BSIM3v32wute * Inv_W - + model->BSIM3v32pute * Inv_LW; - pParam->BSIM3v32voff = model->BSIM3v32voff - + model->BSIM3v32lvoff * Inv_L - + model->BSIM3v32wvoff * Inv_W - + model->BSIM3v32pvoff * Inv_LW; - pParam->BSIM3v32delta = model->BSIM3v32delta - + model->BSIM3v32ldelta * Inv_L - + model->BSIM3v32wdelta * Inv_W - + model->BSIM3v32pdelta * Inv_LW; - pParam->BSIM3v32rdsw = model->BSIM3v32rdsw - + model->BSIM3v32lrdsw * Inv_L - + model->BSIM3v32wrdsw * Inv_W - + model->BSIM3v32prdsw * Inv_LW; - pParam->BSIM3v32prwg = model->BSIM3v32prwg - + model->BSIM3v32lprwg * Inv_L - + model->BSIM3v32wprwg * Inv_W - + model->BSIM3v32pprwg * Inv_LW; - pParam->BSIM3v32prwb = model->BSIM3v32prwb - + model->BSIM3v32lprwb * Inv_L - + model->BSIM3v32wprwb * Inv_W - + model->BSIM3v32pprwb * Inv_LW; - pParam->BSIM3v32prt = model->BSIM3v32prt - + model->BSIM3v32lprt * Inv_L - + model->BSIM3v32wprt * Inv_W - + model->BSIM3v32pprt * Inv_LW; - pParam->BSIM3v32eta0 = model->BSIM3v32eta0 - + model->BSIM3v32leta0 * Inv_L - + model->BSIM3v32weta0 * Inv_W - + model->BSIM3v32peta0 * Inv_LW; - pParam->BSIM3v32etab = model->BSIM3v32etab - + model->BSIM3v32letab * Inv_L - + model->BSIM3v32wetab * Inv_W - + model->BSIM3v32petab * Inv_LW; - pParam->BSIM3v32pclm = model->BSIM3v32pclm - + model->BSIM3v32lpclm * Inv_L - + model->BSIM3v32wpclm * Inv_W - + model->BSIM3v32ppclm * Inv_LW; - pParam->BSIM3v32pdibl1 = model->BSIM3v32pdibl1 - + model->BSIM3v32lpdibl1 * Inv_L - + model->BSIM3v32wpdibl1 * Inv_W - + model->BSIM3v32ppdibl1 * Inv_LW; - pParam->BSIM3v32pdibl2 = model->BSIM3v32pdibl2 - + model->BSIM3v32lpdibl2 * Inv_L - + model->BSIM3v32wpdibl2 * Inv_W - + model->BSIM3v32ppdibl2 * Inv_LW; - pParam->BSIM3v32pdiblb = model->BSIM3v32pdiblb - + model->BSIM3v32lpdiblb * Inv_L - + model->BSIM3v32wpdiblb * Inv_W - + model->BSIM3v32ppdiblb * Inv_LW; - pParam->BSIM3v32pscbe1 = model->BSIM3v32pscbe1 - + model->BSIM3v32lpscbe1 * Inv_L - + model->BSIM3v32wpscbe1 * Inv_W - + model->BSIM3v32ppscbe1 * Inv_LW; - pParam->BSIM3v32pscbe2 = model->BSIM3v32pscbe2 - + model->BSIM3v32lpscbe2 * Inv_L - + model->BSIM3v32wpscbe2 * Inv_W - + model->BSIM3v32ppscbe2 * Inv_LW; - pParam->BSIM3v32pvag = model->BSIM3v32pvag - + model->BSIM3v32lpvag * Inv_L - + model->BSIM3v32wpvag * Inv_W - + model->BSIM3v32ppvag * Inv_LW; - pParam->BSIM3v32wr = model->BSIM3v32wr - + model->BSIM3v32lwr * Inv_L - + model->BSIM3v32wwr * Inv_W - + model->BSIM3v32pwr * Inv_LW; - pParam->BSIM3v32dwg = model->BSIM3v32dwg - + model->BSIM3v32ldwg * Inv_L - + model->BSIM3v32wdwg * Inv_W - + model->BSIM3v32pdwg * Inv_LW; - pParam->BSIM3v32dwb = model->BSIM3v32dwb - + model->BSIM3v32ldwb * Inv_L - + model->BSIM3v32wdwb * Inv_W - + model->BSIM3v32pdwb * Inv_LW; - pParam->BSIM3v32b0 = model->BSIM3v32b0 - + model->BSIM3v32lb0 * Inv_L - + model->BSIM3v32wb0 * Inv_W - + model->BSIM3v32pb0 * Inv_LW; - pParam->BSIM3v32b1 = model->BSIM3v32b1 - + model->BSIM3v32lb1 * Inv_L - + model->BSIM3v32wb1 * Inv_W - + model->BSIM3v32pb1 * Inv_LW; - pParam->BSIM3v32alpha0 = model->BSIM3v32alpha0 - + model->BSIM3v32lalpha0 * Inv_L - + model->BSIM3v32walpha0 * Inv_W - + model->BSIM3v32palpha0 * Inv_LW; - pParam->BSIM3v32alpha1 = model->BSIM3v32alpha1 - + model->BSIM3v32lalpha1 * Inv_L - + model->BSIM3v32walpha1 * Inv_W - + model->BSIM3v32palpha1 * Inv_LW; - pParam->BSIM3v32beta0 = model->BSIM3v32beta0 - + model->BSIM3v32lbeta0 * Inv_L - + model->BSIM3v32wbeta0 * Inv_W - + model->BSIM3v32pbeta0 * Inv_LW; - /* CV model */ - pParam->BSIM3v32elm = model->BSIM3v32elm - + model->BSIM3v32lelm * Inv_L - + model->BSIM3v32welm * Inv_W - + model->BSIM3v32pelm * Inv_LW; - pParam->BSIM3v32cgsl = model->BSIM3v32cgsl - + model->BSIM3v32lcgsl * Inv_L - + model->BSIM3v32wcgsl * Inv_W - + model->BSIM3v32pcgsl * Inv_LW; - pParam->BSIM3v32cgdl = model->BSIM3v32cgdl - + model->BSIM3v32lcgdl * Inv_L - + model->BSIM3v32wcgdl * Inv_W - + model->BSIM3v32pcgdl * Inv_LW; - pParam->BSIM3v32ckappa = model->BSIM3v32ckappa - + model->BSIM3v32lckappa * Inv_L - + model->BSIM3v32wckappa * Inv_W - + model->BSIM3v32pckappa * Inv_LW; - pParam->BSIM3v32cf = model->BSIM3v32cf - + model->BSIM3v32lcf * Inv_L - + model->BSIM3v32wcf * Inv_W - + model->BSIM3v32pcf * Inv_LW; - pParam->BSIM3v32clc = model->BSIM3v32clc - + model->BSIM3v32lclc * Inv_L - + model->BSIM3v32wclc * Inv_W - + model->BSIM3v32pclc * Inv_LW; - pParam->BSIM3v32cle = model->BSIM3v32cle - + model->BSIM3v32lcle * Inv_L - + model->BSIM3v32wcle * Inv_W - + model->BSIM3v32pcle * Inv_LW; - pParam->BSIM3v32vfbcv = model->BSIM3v32vfbcv - + model->BSIM3v32lvfbcv * Inv_L - + model->BSIM3v32wvfbcv * Inv_W - + model->BSIM3v32pvfbcv * Inv_LW; - pParam->BSIM3v32acde = model->BSIM3v32acde - + model->BSIM3v32lacde * Inv_L - + model->BSIM3v32wacde * Inv_W - + model->BSIM3v32pacde * Inv_LW; - pParam->BSIM3v32moin = model->BSIM3v32moin - + model->BSIM3v32lmoin * Inv_L - + model->BSIM3v32wmoin * Inv_W - + model->BSIM3v32pmoin * Inv_LW; - pParam->BSIM3v32noff = model->BSIM3v32noff - + model->BSIM3v32lnoff * Inv_L - + model->BSIM3v32wnoff * Inv_W - + model->BSIM3v32pnoff * Inv_LW; - pParam->BSIM3v32voffcv = model->BSIM3v32voffcv - + model->BSIM3v32lvoffcv * Inv_L - + model->BSIM3v32wvoffcv * Inv_W - + model->BSIM3v32pvoffcv * Inv_LW; + pParam->BSIM3v32a1 = model->BSIM3v32a1 + + model->BSIM3v32la1 * Inv_L + + model->BSIM3v32wa1 * Inv_W + + model->BSIM3v32pa1 * Inv_LW; + pParam->BSIM3v32a2 = model->BSIM3v32a2 + + model->BSIM3v32la2 * Inv_L + + model->BSIM3v32wa2 * Inv_W + + model->BSIM3v32pa2 * Inv_LW; + pParam->BSIM3v32keta = model->BSIM3v32keta + + model->BSIM3v32lketa * Inv_L + + model->BSIM3v32wketa * Inv_W + + model->BSIM3v32pketa * Inv_LW; + pParam->BSIM3v32nsub = model->BSIM3v32nsub + + model->BSIM3v32lnsub * Inv_L + + model->BSIM3v32wnsub * Inv_W + + model->BSIM3v32pnsub * Inv_LW; + pParam->BSIM3v32npeak = model->BSIM3v32npeak + + model->BSIM3v32lnpeak * Inv_L + + model->BSIM3v32wnpeak * Inv_W + + model->BSIM3v32pnpeak * Inv_LW; + pParam->BSIM3v32ngate = model->BSIM3v32ngate + + model->BSIM3v32lngate * Inv_L + + model->BSIM3v32wngate * Inv_W + + model->BSIM3v32pngate * Inv_LW; + pParam->BSIM3v32gamma1 = model->BSIM3v32gamma1 + + model->BSIM3v32lgamma1 * Inv_L + + model->BSIM3v32wgamma1 * Inv_W + + model->BSIM3v32pgamma1 * Inv_LW; + pParam->BSIM3v32gamma2 = model->BSIM3v32gamma2 + + model->BSIM3v32lgamma2 * Inv_L + + model->BSIM3v32wgamma2 * Inv_W + + model->BSIM3v32pgamma2 * Inv_LW; + pParam->BSIM3v32vbx = model->BSIM3v32vbx + + model->BSIM3v32lvbx * Inv_L + + model->BSIM3v32wvbx * Inv_W + + model->BSIM3v32pvbx * Inv_LW; + pParam->BSIM3v32vbm = model->BSIM3v32vbm + + model->BSIM3v32lvbm * Inv_L + + model->BSIM3v32wvbm * Inv_W + + model->BSIM3v32pvbm * Inv_LW; + pParam->BSIM3v32xt = model->BSIM3v32xt + + model->BSIM3v32lxt * Inv_L + + model->BSIM3v32wxt * Inv_W + + model->BSIM3v32pxt * Inv_LW; + pParam->BSIM3v32vfb = model->BSIM3v32vfb + + model->BSIM3v32lvfb * Inv_L + + model->BSIM3v32wvfb * Inv_W + + model->BSIM3v32pvfb * Inv_LW; + pParam->BSIM3v32k1 = model->BSIM3v32k1 + + model->BSIM3v32lk1 * Inv_L + + model->BSIM3v32wk1 * Inv_W + + model->BSIM3v32pk1 * Inv_LW; + pParam->BSIM3v32kt1 = model->BSIM3v32kt1 + + model->BSIM3v32lkt1 * Inv_L + + model->BSIM3v32wkt1 * Inv_W + + model->BSIM3v32pkt1 * Inv_LW; + pParam->BSIM3v32kt1l = model->BSIM3v32kt1l + + model->BSIM3v32lkt1l * Inv_L + + model->BSIM3v32wkt1l * Inv_W + + model->BSIM3v32pkt1l * Inv_LW; + pParam->BSIM3v32k2 = model->BSIM3v32k2 + + model->BSIM3v32lk2 * Inv_L + + model->BSIM3v32wk2 * Inv_W + + model->BSIM3v32pk2 * Inv_LW; + pParam->BSIM3v32kt2 = model->BSIM3v32kt2 + + model->BSIM3v32lkt2 * Inv_L + + model->BSIM3v32wkt2 * Inv_W + + model->BSIM3v32pkt2 * Inv_LW; + pParam->BSIM3v32k3 = model->BSIM3v32k3 + + model->BSIM3v32lk3 * Inv_L + + model->BSIM3v32wk3 * Inv_W + + model->BSIM3v32pk3 * Inv_LW; + pParam->BSIM3v32k3b = model->BSIM3v32k3b + + model->BSIM3v32lk3b * Inv_L + + model->BSIM3v32wk3b * Inv_W + + model->BSIM3v32pk3b * Inv_LW; + pParam->BSIM3v32w0 = model->BSIM3v32w0 + + model->BSIM3v32lw0 * Inv_L + + model->BSIM3v32ww0 * Inv_W + + model->BSIM3v32pw0 * Inv_LW; + pParam->BSIM3v32nlx = model->BSIM3v32nlx + + model->BSIM3v32lnlx * Inv_L + + model->BSIM3v32wnlx * Inv_W + + model->BSIM3v32pnlx * Inv_LW; + pParam->BSIM3v32dvt0 = model->BSIM3v32dvt0 + + model->BSIM3v32ldvt0 * Inv_L + + model->BSIM3v32wdvt0 * Inv_W + + model->BSIM3v32pdvt0 * Inv_LW; + pParam->BSIM3v32dvt1 = model->BSIM3v32dvt1 + + model->BSIM3v32ldvt1 * Inv_L + + model->BSIM3v32wdvt1 * Inv_W + + model->BSIM3v32pdvt1 * Inv_LW; + pParam->BSIM3v32dvt2 = model->BSIM3v32dvt2 + + model->BSIM3v32ldvt2 * Inv_L + + model->BSIM3v32wdvt2 * Inv_W + + model->BSIM3v32pdvt2 * Inv_LW; + pParam->BSIM3v32dvt0w = model->BSIM3v32dvt0w + + model->BSIM3v32ldvt0w * Inv_L + + model->BSIM3v32wdvt0w * Inv_W + + model->BSIM3v32pdvt0w * Inv_LW; + pParam->BSIM3v32dvt1w = model->BSIM3v32dvt1w + + model->BSIM3v32ldvt1w * Inv_L + + model->BSIM3v32wdvt1w * Inv_W + + model->BSIM3v32pdvt1w * Inv_LW; + pParam->BSIM3v32dvt2w = model->BSIM3v32dvt2w + + model->BSIM3v32ldvt2w * Inv_L + + model->BSIM3v32wdvt2w * Inv_W + + model->BSIM3v32pdvt2w * Inv_LW; + pParam->BSIM3v32drout = model->BSIM3v32drout + + model->BSIM3v32ldrout * Inv_L + + model->BSIM3v32wdrout * Inv_W + + model->BSIM3v32pdrout * Inv_LW; + pParam->BSIM3v32dsub = model->BSIM3v32dsub + + model->BSIM3v32ldsub * Inv_L + + model->BSIM3v32wdsub * Inv_W + + model->BSIM3v32pdsub * Inv_LW; + pParam->BSIM3v32vth0 = model->BSIM3v32vth0 + + model->BSIM3v32lvth0 * Inv_L + + model->BSIM3v32wvth0 * Inv_W + + model->BSIM3v32pvth0 * Inv_LW; + pParam->BSIM3v32ua = model->BSIM3v32ua + + model->BSIM3v32lua * Inv_L + + model->BSIM3v32wua * Inv_W + + model->BSIM3v32pua * Inv_LW; + pParam->BSIM3v32ua1 = model->BSIM3v32ua1 + + model->BSIM3v32lua1 * Inv_L + + model->BSIM3v32wua1 * Inv_W + + model->BSIM3v32pua1 * Inv_LW; + pParam->BSIM3v32ub = model->BSIM3v32ub + + model->BSIM3v32lub * Inv_L + + model->BSIM3v32wub * Inv_W + + model->BSIM3v32pub * Inv_LW; + pParam->BSIM3v32ub1 = model->BSIM3v32ub1 + + model->BSIM3v32lub1 * Inv_L + + model->BSIM3v32wub1 * Inv_W + + model->BSIM3v32pub1 * Inv_LW; + pParam->BSIM3v32uc = model->BSIM3v32uc + + model->BSIM3v32luc * Inv_L + + model->BSIM3v32wuc * Inv_W + + model->BSIM3v32puc * Inv_LW; + pParam->BSIM3v32uc1 = model->BSIM3v32uc1 + + model->BSIM3v32luc1 * Inv_L + + model->BSIM3v32wuc1 * Inv_W + + model->BSIM3v32puc1 * Inv_LW; + pParam->BSIM3v32u0 = model->BSIM3v32u0 + + model->BSIM3v32lu0 * Inv_L + + model->BSIM3v32wu0 * Inv_W + + model->BSIM3v32pu0 * Inv_LW; + pParam->BSIM3v32ute = model->BSIM3v32ute + + model->BSIM3v32lute * Inv_L + + model->BSIM3v32wute * Inv_W + + model->BSIM3v32pute * Inv_LW; + pParam->BSIM3v32voff = model->BSIM3v32voff + + model->BSIM3v32lvoff * Inv_L + + model->BSIM3v32wvoff * Inv_W + + model->BSIM3v32pvoff * Inv_LW; + pParam->BSIM3v32delta = model->BSIM3v32delta + + model->BSIM3v32ldelta * Inv_L + + model->BSIM3v32wdelta * Inv_W + + model->BSIM3v32pdelta * Inv_LW; + pParam->BSIM3v32rdsw = model->BSIM3v32rdsw + + model->BSIM3v32lrdsw * Inv_L + + model->BSIM3v32wrdsw * Inv_W + + model->BSIM3v32prdsw * Inv_LW; + pParam->BSIM3v32prwg = model->BSIM3v32prwg + + model->BSIM3v32lprwg * Inv_L + + model->BSIM3v32wprwg * Inv_W + + model->BSIM3v32pprwg * Inv_LW; + pParam->BSIM3v32prwb = model->BSIM3v32prwb + + model->BSIM3v32lprwb * Inv_L + + model->BSIM3v32wprwb * Inv_W + + model->BSIM3v32pprwb * Inv_LW; + pParam->BSIM3v32prt = model->BSIM3v32prt + + model->BSIM3v32lprt * Inv_L + + model->BSIM3v32wprt * Inv_W + + model->BSIM3v32pprt * Inv_LW; + pParam->BSIM3v32eta0 = model->BSIM3v32eta0 + + model->BSIM3v32leta0 * Inv_L + + model->BSIM3v32weta0 * Inv_W + + model->BSIM3v32peta0 * Inv_LW; + pParam->BSIM3v32etab = model->BSIM3v32etab + + model->BSIM3v32letab * Inv_L + + model->BSIM3v32wetab * Inv_W + + model->BSIM3v32petab * Inv_LW; + pParam->BSIM3v32pclm = model->BSIM3v32pclm + + model->BSIM3v32lpclm * Inv_L + + model->BSIM3v32wpclm * Inv_W + + model->BSIM3v32ppclm * Inv_LW; + pParam->BSIM3v32pdibl1 = model->BSIM3v32pdibl1 + + model->BSIM3v32lpdibl1 * Inv_L + + model->BSIM3v32wpdibl1 * Inv_W + + model->BSIM3v32ppdibl1 * Inv_LW; + pParam->BSIM3v32pdibl2 = model->BSIM3v32pdibl2 + + model->BSIM3v32lpdibl2 * Inv_L + + model->BSIM3v32wpdibl2 * Inv_W + + model->BSIM3v32ppdibl2 * Inv_LW; + pParam->BSIM3v32pdiblb = model->BSIM3v32pdiblb + + model->BSIM3v32lpdiblb * Inv_L + + model->BSIM3v32wpdiblb * Inv_W + + model->BSIM3v32ppdiblb * Inv_LW; + pParam->BSIM3v32pscbe1 = model->BSIM3v32pscbe1 + + model->BSIM3v32lpscbe1 * Inv_L + + model->BSIM3v32wpscbe1 * Inv_W + + model->BSIM3v32ppscbe1 * Inv_LW; + pParam->BSIM3v32pscbe2 = model->BSIM3v32pscbe2 + + model->BSIM3v32lpscbe2 * Inv_L + + model->BSIM3v32wpscbe2 * Inv_W + + model->BSIM3v32ppscbe2 * Inv_LW; + pParam->BSIM3v32pvag = model->BSIM3v32pvag + + model->BSIM3v32lpvag * Inv_L + + model->BSIM3v32wpvag * Inv_W + + model->BSIM3v32ppvag * Inv_LW; + pParam->BSIM3v32wr = model->BSIM3v32wr + + model->BSIM3v32lwr * Inv_L + + model->BSIM3v32wwr * Inv_W + + model->BSIM3v32pwr * Inv_LW; + pParam->BSIM3v32dwg = model->BSIM3v32dwg + + model->BSIM3v32ldwg * Inv_L + + model->BSIM3v32wdwg * Inv_W + + model->BSIM3v32pdwg * Inv_LW; + pParam->BSIM3v32dwb = model->BSIM3v32dwb + + model->BSIM3v32ldwb * Inv_L + + model->BSIM3v32wdwb * Inv_W + + model->BSIM3v32pdwb * Inv_LW; + pParam->BSIM3v32b0 = model->BSIM3v32b0 + + model->BSIM3v32lb0 * Inv_L + + model->BSIM3v32wb0 * Inv_W + + model->BSIM3v32pb0 * Inv_LW; + pParam->BSIM3v32b1 = model->BSIM3v32b1 + + model->BSIM3v32lb1 * Inv_L + + model->BSIM3v32wb1 * Inv_W + + model->BSIM3v32pb1 * Inv_LW; + pParam->BSIM3v32alpha0 = model->BSIM3v32alpha0 + + model->BSIM3v32lalpha0 * Inv_L + + model->BSIM3v32walpha0 * Inv_W + + model->BSIM3v32palpha0 * Inv_LW; + pParam->BSIM3v32alpha1 = model->BSIM3v32alpha1 + + model->BSIM3v32lalpha1 * Inv_L + + model->BSIM3v32walpha1 * Inv_W + + model->BSIM3v32palpha1 * Inv_LW; + pParam->BSIM3v32beta0 = model->BSIM3v32beta0 + + model->BSIM3v32lbeta0 * Inv_L + + model->BSIM3v32wbeta0 * Inv_W + + model->BSIM3v32pbeta0 * Inv_LW; + /* CV model */ + pParam->BSIM3v32elm = model->BSIM3v32elm + + model->BSIM3v32lelm * Inv_L + + model->BSIM3v32welm * Inv_W + + model->BSIM3v32pelm * Inv_LW; + pParam->BSIM3v32cgsl = model->BSIM3v32cgsl + + model->BSIM3v32lcgsl * Inv_L + + model->BSIM3v32wcgsl * Inv_W + + model->BSIM3v32pcgsl * Inv_LW; + pParam->BSIM3v32cgdl = model->BSIM3v32cgdl + + model->BSIM3v32lcgdl * Inv_L + + model->BSIM3v32wcgdl * Inv_W + + model->BSIM3v32pcgdl * Inv_LW; + pParam->BSIM3v32ckappa = model->BSIM3v32ckappa + + model->BSIM3v32lckappa * Inv_L + + model->BSIM3v32wckappa * Inv_W + + model->BSIM3v32pckappa * Inv_LW; + pParam->BSIM3v32cf = model->BSIM3v32cf + + model->BSIM3v32lcf * Inv_L + + model->BSIM3v32wcf * Inv_W + + model->BSIM3v32pcf * Inv_LW; + pParam->BSIM3v32clc = model->BSIM3v32clc + + model->BSIM3v32lclc * Inv_L + + model->BSIM3v32wclc * Inv_W + + model->BSIM3v32pclc * Inv_LW; + pParam->BSIM3v32cle = model->BSIM3v32cle + + model->BSIM3v32lcle * Inv_L + + model->BSIM3v32wcle * Inv_W + + model->BSIM3v32pcle * Inv_LW; + pParam->BSIM3v32vfbcv = model->BSIM3v32vfbcv + + model->BSIM3v32lvfbcv * Inv_L + + model->BSIM3v32wvfbcv * Inv_W + + model->BSIM3v32pvfbcv * Inv_LW; + pParam->BSIM3v32acde = model->BSIM3v32acde + + model->BSIM3v32lacde * Inv_L + + model->BSIM3v32wacde * Inv_W + + model->BSIM3v32pacde * Inv_LW; + pParam->BSIM3v32moin = model->BSIM3v32moin + + model->BSIM3v32lmoin * Inv_L + + model->BSIM3v32wmoin * Inv_W + + model->BSIM3v32pmoin * Inv_LW; + pParam->BSIM3v32noff = model->BSIM3v32noff + + model->BSIM3v32lnoff * Inv_L + + model->BSIM3v32wnoff * Inv_W + + model->BSIM3v32pnoff * Inv_LW; + pParam->BSIM3v32voffcv = model->BSIM3v32voffcv + + model->BSIM3v32lvoffcv * Inv_L + + model->BSIM3v32wvoffcv * Inv_W + + model->BSIM3v32pvoffcv * Inv_LW; - pParam->BSIM3v32abulkCVfactor = 1.0 + pow((pParam->BSIM3v32clc - / pParam->BSIM3v32leffCV), - pParam->BSIM3v32cle); + pParam->BSIM3v32abulkCVfactor = 1.0 + pow((pParam->BSIM3v32clc + / pParam->BSIM3v32leffCV), + pParam->BSIM3v32cle); - T0 = (TRatio - 1.0); - pParam->BSIM3v32ua = pParam->BSIM3v32ua + pParam->BSIM3v32ua1 * T0; - pParam->BSIM3v32ub = pParam->BSIM3v32ub + pParam->BSIM3v32ub1 * T0; - pParam->BSIM3v32uc = pParam->BSIM3v32uc + pParam->BSIM3v32uc1 * T0; - if (pParam->BSIM3v32u0 > 1.0) - pParam->BSIM3v32u0 = pParam->BSIM3v32u0 / 1.0e4; + T0 = (TRatio - 1.0); + pParam->BSIM3v32ua = pParam->BSIM3v32ua + pParam->BSIM3v32ua1 * T0; + pParam->BSIM3v32ub = pParam->BSIM3v32ub + pParam->BSIM3v32ub1 * T0; + pParam->BSIM3v32uc = pParam->BSIM3v32uc + pParam->BSIM3v32uc1 * T0; + if (pParam->BSIM3v32u0 > 1.0) + pParam->BSIM3v32u0 = pParam->BSIM3v32u0 / 1.0e4; - pParam->BSIM3v32u0temp = pParam->BSIM3v32u0 - * pow(TRatio, pParam->BSIM3v32ute); - pParam->BSIM3v32vsattemp = pParam->BSIM3v32vsat - pParam->BSIM3v32at - * T0; - pParam->BSIM3v32rds0 = (pParam->BSIM3v32rdsw + pParam->BSIM3v32prt * T0) - / pow(pParam->BSIM3v32weff * 1E6, pParam->BSIM3v32wr); + pParam->BSIM3v32u0temp = pParam->BSIM3v32u0 + * pow(TRatio, pParam->BSIM3v32ute); + pParam->BSIM3v32vsattemp = pParam->BSIM3v32vsat - pParam->BSIM3v32at + * T0; + pParam->BSIM3v32rds0 = (pParam->BSIM3v32rdsw + pParam->BSIM3v32prt * T0) + / pow(pParam->BSIM3v32weff * 1E6, pParam->BSIM3v32wr); - if (BSIM3v32checkModel(model, here, ckt)) - { IFuid namarray[2]; - namarray[0] = model->BSIM3v32modName; - namarray[1] = here->BSIM3v32name; - SPfrontEnd->IFerror (ERR_FATAL, "Fatal error(s) detected during BSIM3v32V3.2 parameter checking for %s in model %s", namarray); - return(E_BADPARM); - } + if (BSIM3v32checkModel(model, here, ckt)) + { IFuid namarray[2]; + namarray[0] = model->BSIM3v32modName; + namarray[1] = here->BSIM3v32name; + SPfrontEnd->IFerror (ERR_FATAL, "Fatal error(s) detected during BSIM3v32V3.2 parameter checking for %s in model %s", namarray); + return(E_BADPARM); + } - pParam->BSIM3v32cgdo = (model->BSIM3v32cgdo + pParam->BSIM3v32cf) - * pParam->BSIM3v32weffCV; - pParam->BSIM3v32cgso = (model->BSIM3v32cgso + pParam->BSIM3v32cf) - * pParam->BSIM3v32weffCV; - pParam->BSIM3v32cgbo = model->BSIM3v32cgbo * pParam->BSIM3v32leffCV; + pParam->BSIM3v32cgdo = (model->BSIM3v32cgdo + pParam->BSIM3v32cf) + * pParam->BSIM3v32weffCV; + pParam->BSIM3v32cgso = (model->BSIM3v32cgso + pParam->BSIM3v32cf) + * pParam->BSIM3v32weffCV; + pParam->BSIM3v32cgbo = model->BSIM3v32cgbo * pParam->BSIM3v32leffCV; - T0 = pParam->BSIM3v32leffCV * pParam->BSIM3v32leffCV; - pParam->BSIM3v32tconst = pParam->BSIM3v32u0temp * pParam->BSIM3v32elm / (model->BSIM3v32cox - * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0); + T0 = pParam->BSIM3v32leffCV * pParam->BSIM3v32leffCV; + pParam->BSIM3v32tconst = pParam->BSIM3v32u0temp * pParam->BSIM3v32elm / (model->BSIM3v32cox + * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0); - if (!model->BSIM3v32npeakGiven && model->BSIM3v32gamma1Given) - { T0 = pParam->BSIM3v32gamma1 * model->BSIM3v32cox; - pParam->BSIM3v32npeak = 3.021E22 * T0 * T0; - } + if (!model->BSIM3v32npeakGiven && model->BSIM3v32gamma1Given) + { T0 = pParam->BSIM3v32gamma1 * model->BSIM3v32cox; + pParam->BSIM3v32npeak = 3.021E22 * T0 * T0; + } - pParam->BSIM3v32phi = 2.0 * Vtm0 - * log(pParam->BSIM3v32npeak / ni); + pParam->BSIM3v32phi = 2.0 * Vtm0 + * log(pParam->BSIM3v32npeak / ni); - pParam->BSIM3v32sqrtPhi = sqrt(pParam->BSIM3v32phi); - pParam->BSIM3v32phis3 = pParam->BSIM3v32sqrtPhi * pParam->BSIM3v32phi; + pParam->BSIM3v32sqrtPhi = sqrt(pParam->BSIM3v32phi); + pParam->BSIM3v32phis3 = pParam->BSIM3v32sqrtPhi * pParam->BSIM3v32phi; - pParam->BSIM3v32Xdep0 = sqrt(2.0 * EPSSI / (Charge_q - * pParam->BSIM3v32npeak * 1.0e6)) - * pParam->BSIM3v32sqrtPhi; - pParam->BSIM3v32sqrtXdep0 = sqrt(pParam->BSIM3v32Xdep0); - pParam->BSIM3v32litl = sqrt(3.0 * pParam->BSIM3v32xj - * model->BSIM3v32tox); - pParam->BSIM3v32vbi = Vtm0 * log(1.0e20 - * pParam->BSIM3v32npeak / (ni * ni)); - pParam->BSIM3v32cdep0 = sqrt(Charge_q * EPSSI - * pParam->BSIM3v32npeak * 1.0e6 / 2.0 - / pParam->BSIM3v32phi); + pParam->BSIM3v32Xdep0 = sqrt(2.0 * EPSSI / (Charge_q + * pParam->BSIM3v32npeak * 1.0e6)) + * pParam->BSIM3v32sqrtPhi; + pParam->BSIM3v32sqrtXdep0 = sqrt(pParam->BSIM3v32Xdep0); + pParam->BSIM3v32litl = sqrt(3.0 * pParam->BSIM3v32xj + * model->BSIM3v32tox); + pParam->BSIM3v32vbi = Vtm0 * log(1.0e20 + * pParam->BSIM3v32npeak / (ni * ni)); + pParam->BSIM3v32cdep0 = sqrt(Charge_q * EPSSI + * pParam->BSIM3v32npeak * 1.0e6 / 2.0 + / pParam->BSIM3v32phi); - pParam->BSIM3v32ldeb = sqrt(EPSSI * Vtm0 / (Charge_q - * pParam->BSIM3v32npeak * 1.0e6)) / 3.0; - pParam->BSIM3v32acde *= pow((pParam->BSIM3v32npeak / 2.0e16), -0.25); + pParam->BSIM3v32ldeb = sqrt(EPSSI * Vtm0 / (Charge_q + * pParam->BSIM3v32npeak * 1.0e6)) / 3.0; + pParam->BSIM3v32acde *= pow((pParam->BSIM3v32npeak / 2.0e16), -0.25); - if (model->BSIM3v32k1Given || model->BSIM3v32k2Given) - { if (!model->BSIM3v32k1Given) - { - if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ - fprintf(stdout, "Warning: k1 should be specified with k2.\n"); - pParam->BSIM3v32k1 = 0.53; - } - if (!model->BSIM3v32k2Given) - { - if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ - fprintf(stdout, "Warning: k2 should be specified with k1.\n"); - pParam->BSIM3v32k2 = -0.0186; - } - if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) { /* don't print in sensitivity */ - if (model->BSIM3v32nsubGiven) - fprintf(stdout, "Warning: nsub is ignored because k1 or k2 is given.\n"); - if (model->BSIM3v32xtGiven) - fprintf(stdout, "Warning: xt is ignored because k1 or k2 is given.\n"); - if (model->BSIM3v32vbxGiven) - fprintf(stdout, "Warning: vbx is ignored because k1 or k2 is given.\n"); - if (model->BSIM3v32gamma1Given) - fprintf(stdout, "Warning: gamma1 is ignored because k1 or k2 is given.\n"); - if (model->BSIM3v32gamma2Given) - fprintf(stdout, "Warning: gamma2 is ignored because k1 or k2 is given.\n"); - } - } - else - { if (!model->BSIM3v32vbxGiven) - pParam->BSIM3v32vbx = pParam->BSIM3v32phi - 7.7348e-4 - * pParam->BSIM3v32npeak - * pParam->BSIM3v32xt * pParam->BSIM3v32xt; - if (pParam->BSIM3v32vbx > 0.0) - pParam->BSIM3v32vbx = -pParam->BSIM3v32vbx; - if (pParam->BSIM3v32vbm > 0.0) - pParam->BSIM3v32vbm = -pParam->BSIM3v32vbm; + if (model->BSIM3v32k1Given || model->BSIM3v32k2Given) + { if (!model->BSIM3v32k1Given) + { + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ + fprintf(stdout, "Warning: k1 should be specified with k2.\n"); + pParam->BSIM3v32k1 = 0.53; + } + if (!model->BSIM3v32k2Given) + { + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ + fprintf(stdout, "Warning: k2 should be specified with k1.\n"); + pParam->BSIM3v32k2 = -0.0186; + } + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) { /* don't print in sensitivity */ + if (model->BSIM3v32nsubGiven) + fprintf(stdout, "Warning: nsub is ignored because k1 or k2 is given.\n"); + if (model->BSIM3v32xtGiven) + fprintf(stdout, "Warning: xt is ignored because k1 or k2 is given.\n"); + if (model->BSIM3v32vbxGiven) + fprintf(stdout, "Warning: vbx is ignored because k1 or k2 is given.\n"); + if (model->BSIM3v32gamma1Given) + fprintf(stdout, "Warning: gamma1 is ignored because k1 or k2 is given.\n"); + if (model->BSIM3v32gamma2Given) + fprintf(stdout, "Warning: gamma2 is ignored because k1 or k2 is given.\n"); + } + } + else + { if (!model->BSIM3v32vbxGiven) + pParam->BSIM3v32vbx = pParam->BSIM3v32phi - 7.7348e-4 + * pParam->BSIM3v32npeak + * pParam->BSIM3v32xt * pParam->BSIM3v32xt; + if (pParam->BSIM3v32vbx > 0.0) + pParam->BSIM3v32vbx = -pParam->BSIM3v32vbx; + if (pParam->BSIM3v32vbm > 0.0) + pParam->BSIM3v32vbm = -pParam->BSIM3v32vbm; - if (!model->BSIM3v32gamma1Given) - pParam->BSIM3v32gamma1 = 5.753e-12 - * sqrt(pParam->BSIM3v32npeak) - / model->BSIM3v32cox; - if (!model->BSIM3v32gamma2Given) - pParam->BSIM3v32gamma2 = 5.753e-12 - * sqrt(pParam->BSIM3v32nsub) - / model->BSIM3v32cox; + if (!model->BSIM3v32gamma1Given) + pParam->BSIM3v32gamma1 = 5.753e-12 + * sqrt(pParam->BSIM3v32npeak) + / model->BSIM3v32cox; + if (!model->BSIM3v32gamma2Given) + pParam->BSIM3v32gamma2 = 5.753e-12 + * sqrt(pParam->BSIM3v32nsub) + / model->BSIM3v32cox; - T0 = pParam->BSIM3v32gamma1 - pParam->BSIM3v32gamma2; - T1 = sqrt(pParam->BSIM3v32phi - pParam->BSIM3v32vbx) - - pParam->BSIM3v32sqrtPhi; - T2 = sqrt(pParam->BSIM3v32phi * (pParam->BSIM3v32phi - - pParam->BSIM3v32vbm)) - pParam->BSIM3v32phi; - pParam->BSIM3v32k2 = T0 * T1 / (2.0 * T2 + pParam->BSIM3v32vbm); - pParam->BSIM3v32k1 = pParam->BSIM3v32gamma2 - 2.0 - * pParam->BSIM3v32k2 * sqrt(pParam->BSIM3v32phi - - pParam->BSIM3v32vbm); - } + T0 = pParam->BSIM3v32gamma1 - pParam->BSIM3v32gamma2; + T1 = sqrt(pParam->BSIM3v32phi - pParam->BSIM3v32vbx) + - pParam->BSIM3v32sqrtPhi; + T2 = sqrt(pParam->BSIM3v32phi * (pParam->BSIM3v32phi + - pParam->BSIM3v32vbm)) - pParam->BSIM3v32phi; + pParam->BSIM3v32k2 = T0 * T1 / (2.0 * T2 + pParam->BSIM3v32vbm); + pParam->BSIM3v32k1 = pParam->BSIM3v32gamma2 - 2.0 + * pParam->BSIM3v32k2 * sqrt(pParam->BSIM3v32phi + - pParam->BSIM3v32vbm); + } - if (pParam->BSIM3v32k2 < 0.0) - { T0 = 0.5 * pParam->BSIM3v32k1 / pParam->BSIM3v32k2; - pParam->BSIM3v32vbsc = 0.9 * (pParam->BSIM3v32phi - T0 * T0); - if (pParam->BSIM3v32vbsc > -3.0) - pParam->BSIM3v32vbsc = -3.0; - else if (pParam->BSIM3v32vbsc < -30.0) - pParam->BSIM3v32vbsc = -30.0; - } - else - { pParam->BSIM3v32vbsc = -30.0; - } - if (pParam->BSIM3v32vbsc > pParam->BSIM3v32vbm) - pParam->BSIM3v32vbsc = pParam->BSIM3v32vbm; + if (pParam->BSIM3v32k2 < 0.0) + { T0 = 0.5 * pParam->BSIM3v32k1 / pParam->BSIM3v32k2; + pParam->BSIM3v32vbsc = 0.9 * (pParam->BSIM3v32phi - T0 * T0); + if (pParam->BSIM3v32vbsc > -3.0) + pParam->BSIM3v32vbsc = -3.0; + else if (pParam->BSIM3v32vbsc < -30.0) + pParam->BSIM3v32vbsc = -30.0; + } + else + { pParam->BSIM3v32vbsc = -30.0; + } + if (pParam->BSIM3v32vbsc > pParam->BSIM3v32vbm) + pParam->BSIM3v32vbsc = pParam->BSIM3v32vbm; - if (!model->BSIM3v32vfbGiven) - { if (model->BSIM3v32vth0Given) - { pParam->BSIM3v32vfb = model->BSIM3v32type * pParam->BSIM3v32vth0 - - pParam->BSIM3v32phi - pParam->BSIM3v32k1 - * pParam->BSIM3v32sqrtPhi; - } - else - { pParam->BSIM3v32vfb = -1.0; - } - } - if (!model->BSIM3v32vth0Given) - { pParam->BSIM3v32vth0 = model->BSIM3v32type * (pParam->BSIM3v32vfb - + pParam->BSIM3v32phi + pParam->BSIM3v32k1 - * pParam->BSIM3v32sqrtPhi); - } + if (!model->BSIM3v32vfbGiven) + { if (model->BSIM3v32vth0Given) + { pParam->BSIM3v32vfb = model->BSIM3v32type * pParam->BSIM3v32vth0 + - pParam->BSIM3v32phi - pParam->BSIM3v32k1 + * pParam->BSIM3v32sqrtPhi; + } + else + { pParam->BSIM3v32vfb = -1.0; + } + } + if (!model->BSIM3v32vth0Given) + { pParam->BSIM3v32vth0 = model->BSIM3v32type * (pParam->BSIM3v32vfb + + pParam->BSIM3v32phi + pParam->BSIM3v32k1 + * pParam->BSIM3v32sqrtPhi); + } - pParam->BSIM3v32k1ox = pParam->BSIM3v32k1 * model->BSIM3v32tox - / model->BSIM3v32toxm; - pParam->BSIM3v32k2ox = pParam->BSIM3v32k2 * model->BSIM3v32tox - / model->BSIM3v32toxm; + pParam->BSIM3v32k1ox = pParam->BSIM3v32k1 * model->BSIM3v32tox + / model->BSIM3v32toxm; + pParam->BSIM3v32k2ox = pParam->BSIM3v32k2 * model->BSIM3v32tox + / model->BSIM3v32toxm; - T1 = sqrt(EPSSI / EPSOX * model->BSIM3v32tox - * pParam->BSIM3v32Xdep0); - T0 = exp(-0.5 * pParam->BSIM3v32dsub * pParam->BSIM3v32leff / T1); - pParam->BSIM3v32theta0vb0 = (T0 + 2.0 * T0 * T0); + T1 = sqrt(EPSSI / EPSOX * model->BSIM3v32tox + * pParam->BSIM3v32Xdep0); + T0 = exp(-0.5 * pParam->BSIM3v32dsub * pParam->BSIM3v32leff / T1); + pParam->BSIM3v32theta0vb0 = (T0 + 2.0 * T0 * T0); - T0 = exp(-0.5 * pParam->BSIM3v32drout * pParam->BSIM3v32leff / T1); - T2 = (T0 + 2.0 * T0 * T0); - pParam->BSIM3v32thetaRout = pParam->BSIM3v32pdibl1 * T2 - + pParam->BSIM3v32pdibl2; + T0 = exp(-0.5 * pParam->BSIM3v32drout * pParam->BSIM3v32leff / T1); + T2 = (T0 + 2.0 * T0 * T0); + pParam->BSIM3v32thetaRout = pParam->BSIM3v32pdibl1 * T2 + + pParam->BSIM3v32pdibl2; - tmp = sqrt(pParam->BSIM3v32Xdep0); - tmp1 = pParam->BSIM3v32vbi - pParam->BSIM3v32phi; - tmp2 = model->BSIM3v32factor1 * tmp; + tmp = sqrt(pParam->BSIM3v32Xdep0); + tmp1 = pParam->BSIM3v32vbi - pParam->BSIM3v32phi; + tmp2 = model->BSIM3v32factor1 * tmp; - T0 = -0.5 * pParam->BSIM3v32dvt1w * pParam->BSIM3v32weff - * pParam->BSIM3v32leff / tmp2; - if (T0 > -EXP_THRESHOLD) - { T1 = exp(T0); - T2 = T1 * (1.0 + 2.0 * T1); - } - else - { T1 = MIN_EXP; - T2 = T1 * (1.0 + 2.0 * T1); - } - T0 = pParam->BSIM3v32dvt0w * T2; - T2 = T0 * tmp1; + T0 = -0.5 * pParam->BSIM3v32dvt1w * pParam->BSIM3v32weff + * pParam->BSIM3v32leff / tmp2; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + T2 = T1 * (1.0 + 2.0 * T1); + } + else + { T1 = MIN_EXP; + T2 = T1 * (1.0 + 2.0 * T1); + } + T0 = pParam->BSIM3v32dvt0w * T2; + T2 = T0 * tmp1; - T0 = -0.5 * pParam->BSIM3v32dvt1 * pParam->BSIM3v32leff / tmp2; - if (T0 > -EXP_THRESHOLD) - { T1 = exp(T0); - T3 = T1 * (1.0 + 2.0 * T1); - } - else - { T1 = MIN_EXP; - T3 = T1 * (1.0 + 2.0 * T1); - } - T3 = pParam->BSIM3v32dvt0 * T3 * tmp1; + T0 = -0.5 * pParam->BSIM3v32dvt1 * pParam->BSIM3v32leff / tmp2; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + T3 = T1 * (1.0 + 2.0 * T1); + } + else + { T1 = MIN_EXP; + T3 = T1 * (1.0 + 2.0 * T1); + } + T3 = pParam->BSIM3v32dvt0 * T3 * tmp1; - T4 = model->BSIM3v32tox * pParam->BSIM3v32phi - / (pParam->BSIM3v32weff + pParam->BSIM3v32w0); + T4 = model->BSIM3v32tox * pParam->BSIM3v32phi + / (pParam->BSIM3v32weff + pParam->BSIM3v32w0); - T0 = sqrt(1.0 + pParam->BSIM3v32nlx / pParam->BSIM3v32leff); - T5 = pParam->BSIM3v32k1ox * (T0 - 1.0) * pParam->BSIM3v32sqrtPhi - + (pParam->BSIM3v32kt1 + pParam->BSIM3v32kt1l / pParam->BSIM3v32leff) - * (TRatio - 1.0); + T0 = sqrt(1.0 + pParam->BSIM3v32nlx / pParam->BSIM3v32leff); + T5 = pParam->BSIM3v32k1ox * (T0 - 1.0) * pParam->BSIM3v32sqrtPhi + + (pParam->BSIM3v32kt1 + pParam->BSIM3v32kt1l / pParam->BSIM3v32leff) + * (TRatio - 1.0); - tmp3 = model->BSIM3v32type * pParam->BSIM3v32vth0 - - T2 - T3 + pParam->BSIM3v32k3 * T4 + T5; - pParam->BSIM3v32vfbzb = tmp3 - pParam->BSIM3v32phi - pParam->BSIM3v32k1 - * pParam->BSIM3v32sqrtPhi; - /* End of vfbzb */ - } + tmp3 = model->BSIM3v32type * pParam->BSIM3v32vth0 + - T2 - T3 + pParam->BSIM3v32k3 * T4 + T5; + pParam->BSIM3v32vfbzb = tmp3 - pParam->BSIM3v32phi - pParam->BSIM3v32k1 + * pParam->BSIM3v32sqrtPhi; + /* End of vfbzb */ + } - /* adding delvto */ - here->BSIM3v32vth0 = pParam->BSIM3v32vth0 + here->BSIM3v32delvto; - here->BSIM3v32vfb = pParam->BSIM3v32vfb + model->BSIM3v32type * here->BSIM3v32delvto; - here->BSIM3v32vfbzb = pParam->BSIM3v32vfbzb + model->BSIM3v32type * here->BSIM3v32delvto; + /* adding delvto */ + here->BSIM3v32vth0 = pParam->BSIM3v32vth0 + here->BSIM3v32delvto; + here->BSIM3v32vfb = pParam->BSIM3v32vfb + model->BSIM3v32type * here->BSIM3v32delvto; + here->BSIM3v32vfbzb = pParam->BSIM3v32vfbzb + model->BSIM3v32type * here->BSIM3v32delvto; - /* low field mobility multiplier */ - here->BSIM3v32u0temp = pParam->BSIM3v32u0temp * here->BSIM3v32mulu0; + /* low field mobility multiplier */ + here->BSIM3v32u0temp = pParam->BSIM3v32u0temp * here->BSIM3v32mulu0; - here->BSIM3v32tconst = here->BSIM3v32u0temp * pParam->BSIM3v32elm / (model->BSIM3v32cox - * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0); + here->BSIM3v32tconst = here->BSIM3v32u0temp * pParam->BSIM3v32elm / (model->BSIM3v32cox + * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0); - /* process source/drain series resistance */ - /* acm model */ - if (model->BSIM3v32acmMod == 0) - { - here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance - * here->BSIM3v32drainSquares; - here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance - * here->BSIM3v32sourceSquares; - } - else - { - if (here->BSIM3v32drainSquaresGiven) - { - here->BSIM3v32drainConductance = (model->BSIM3v32ld + model->BSIM3v32ldif)/(here->BSIM3v32w + model->BSIM3v32xw)*model->BSIM3v32rd - + model->BSIM3v32sheetResistance * here->BSIM3v32drainSquares + model->BSIM3v32rdc; - } - else - { - here->BSIM3v32drainConductance = ((model->BSIM3v32ld + model->BSIM3v32ldif)*model->BSIM3v32rd - + model->BSIM3v32hdif*model->BSIM3v32sheetResistance)/(here->BSIM3v32w + model->BSIM3v32xw) + model->BSIM3v32rdc; - } - if (here->BSIM3v32sourceSquaresGiven) - { - here->BSIM3v32sourceConductance = (model->BSIM3v32ld + model->BSIM3v32ldif)/(here->BSIM3v32w + model->BSIM3v32xw)*model->BSIM3v32rs - + model->BSIM3v32sheetResistance * here->BSIM3v32sourceSquares + model->BSIM3v32rsc; - } - else - { - here->BSIM3v32sourceConductance = ((model->BSIM3v32ld + model->BSIM3v32ldif)*model->BSIM3v32rs - + model->BSIM3v32hdif*model->BSIM3v32sheetResistance)/(here->BSIM3v32w + model->BSIM3v32xw) + model->BSIM3v32rsc; - } - } - if (here->BSIM3v32drainConductance > 0.0) - here->BSIM3v32drainConductance = 1.0 - / here->BSIM3v32drainConductance; - else - here->BSIM3v32drainConductance = 0.0; + /* process source/drain series resistance */ + /* ACM model */ + if (model->BSIM3v32acmMod == 0) + { + here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance + * here->BSIM3v32drainSquares; + here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance + * here->BSIM3v32sourceSquares; + } + else /* ACM > 0 */ + { + error = ACM_SourceDrainResistances( + model->BSIM3v32acmMod, + model->BSIM3v32ld, + model->BSIM3v32ldif, + model->BSIM3v32hdif, + model->BSIM3v32wmlt, + here->BSIM3v32w, + model->BSIM3v32xw, + model->BSIM3v32sheetResistance, + here->BSIM3v32drainSquaresGiven, + model->BSIM3v32rd, + model->BSIM3v32rdc, + here->BSIM3v32drainSquares, + here->BSIM3v32sourceSquaresGiven, + model->BSIM3v32rs, + model->BSIM3v32rsc, + here->BSIM3v32sourceSquares, + &(here->BSIM3v32drainConductance), + &(here->BSIM3v32sourceConductance) + ); + if (error) + return(error); + } + if (here->BSIM3v32drainConductance > 0.0) + here->BSIM3v32drainConductance = 1.0 + / here->BSIM3v32drainConductance; + else + here->BSIM3v32drainConductance = 0.0; - if (here->BSIM3v32sourceConductance > 0.0) - here->BSIM3v32sourceConductance = 1.0 - / here->BSIM3v32sourceConductance; - else - here->BSIM3v32sourceConductance = 0.0; + if (here->BSIM3v32sourceConductance > 0.0) + here->BSIM3v32sourceConductance = 1.0 + / here->BSIM3v32sourceConductance; + else + here->BSIM3v32sourceConductance = 0.0; - here->BSIM3v32cgso = pParam->BSIM3v32cgso; - here->BSIM3v32cgdo = pParam->BSIM3v32cgdo; + here->BSIM3v32cgso = pParam->BSIM3v32cgso; + here->BSIM3v32cgdo = pParam->BSIM3v32cgdo; - Nvtm = model->BSIM3v32vtm * model->BSIM3v32jctEmissionCoeff; - if (model->BSIM3v32acmMod == 0) - { - if ((here->BSIM3v32sourceArea <= 0.0) && - (here->BSIM3v32sourcePerimeter <= 0.0)) - { SourceSatCurrent = 1.0e-14; - } - else - { SourceSatCurrent = here->BSIM3v32sourceArea - * model->BSIM3v32jctTempSatCurDensity - + here->BSIM3v32sourcePerimeter - * model->BSIM3v32jctSidewallTempSatCurDensity; - } - if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth - / SourceSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjsm = - SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } + Nvtm = model->BSIM3v32vtm * model->BSIM3v32jctEmissionCoeff; + if (model->BSIM3v32acmMod == 0) + { + if ((here->BSIM3v32sourceArea <= 0.0) && + (here->BSIM3v32sourcePerimeter <= 0.0)) + { SourceSatCurrent = 1.0e-14; + } + else + { SourceSatCurrent = here->BSIM3v32sourceArea + * model->BSIM3v32jctTempSatCurDensity + + here->BSIM3v32sourcePerimeter + * model->BSIM3v32jctSidewallTempSatCurDensity; + } - if ((here->BSIM3v32drainArea <= 0.0) && - (here->BSIM3v32drainPerimeter <= 0.0)) - { DrainSatCurrent = 1.0e-14; - } - else - { DrainSatCurrent = here->BSIM3v32drainArea - * model->BSIM3v32jctTempSatCurDensity - + here->BSIM3v32drainPerimeter - * model->BSIM3v32jctSidewallTempSatCurDensity; - } - if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth - / DrainSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjdm = - DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } - } - else - { - SourceSatCurrent = 0.0; - if (!here->BSIM3v32sourceAreaGiven) - { - here->BSIM3v32sourceArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff; - } - SourceSatCurrent = here->BSIM3v32sourceArea * model->BSIM3v32jctTempSatCurDensity; - if (!here->BSIM3v32sourcePerimeterGiven) - { - here->BSIM3v32sourcePerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff; - } - SourceSatCurrent = SourceSatCurrent + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; - if (SourceSatCurrent <= 0.0) SourceSatCurrent = 1.0e-14; - if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth - / SourceSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjsm = - SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } + if ((here->BSIM3v32drainArea <= 0.0) && + (here->BSIM3v32drainPerimeter <= 0.0)) + { DrainSatCurrent = 1.0e-14; + } + else + { DrainSatCurrent = here->BSIM3v32drainArea + * model->BSIM3v32jctTempSatCurDensity + + here->BSIM3v32drainPerimeter + * model->BSIM3v32jctSidewallTempSatCurDensity; + } + } + else /* ACM > 0 */ + { + error = ACM_saturationCurrents( + model->BSIM3v32acmMod, + model->BSIM3v32calcacm, + here->BSIM3v32geo, + model->BSIM3v32hdif, + model->BSIM3v32wmlt, + here->BSIM3v32w, + model->BSIM3v32xw, + model->BSIM3v32jctTempSatCurDensity, + model->BSIM3v32jctSidewallTempSatCurDensity, + here->BSIM3v32drainAreaGiven, + here->BSIM3v32drainArea, + here->BSIM3v32drainPerimeterGiven, + here->BSIM3v32drainPerimeter, + here->BSIM3v32sourceAreaGiven, + here->BSIM3v32sourceArea, + here->BSIM3v32sourcePerimeterGiven, + here->BSIM3v32sourcePerimeter, + &DrainSatCurrent, + &SourceSatCurrent + ); + if (error) + return(error); + } + if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) + { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth + / SourceSatCurrent + 1.0); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + here->BSIM3v32IsEvjsm = + SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } + } - DrainSatCurrent = 0.0; - if (!here->BSIM3v32drainAreaGiven) - { - here->BSIM3v32drainArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff; - } - DrainSatCurrent = here->BSIM3v32drainArea * model->BSIM3v32jctTempSatCurDensity; - if (!here->BSIM3v32drainPerimeterGiven) - { - here->BSIM3v32drainPerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff; - } - DrainSatCurrent = DrainSatCurrent + here->BSIM3v32drainPerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; - if (DrainSatCurrent <= 0.0) DrainSatCurrent = 1.0e-14; - if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth - / DrainSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjdm = - DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } - } - } + if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) + { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth + / DrainSatCurrent + 1.0); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + here->BSIM3v32IsEvjdm = + DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } + } + } } return(OK); } diff --git a/src/spicelib/devices/bsim3v32/b3v32trunc.c b/src/spicelib/devices/bsim3v32/b3v32trunc.c index f37510761..976377af6 100644 --- a/src/spicelib/devices/bsim3v32/b3v32trunc.c +++ b/src/spicelib/devices/bsim3v32/b3v32trunc.c @@ -3,7 +3,7 @@ /********** * Copyright 2001 Regents of the University of California. All rights reserved. * File: b3trunc.c of BSIM3v3.2.4 - * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi * Modified by Poalo Nenzi 2002 @@ -28,8 +28,8 @@ BSIM3v32instance *here; for (; model != NULL; model = model->BSIM3v32nextModel) { for (here = model->BSIM3v32instances; here != NULL; - here = here->BSIM3v32nextInstance) - { + here = here->BSIM3v32nextInstance) + { #ifdef STEPDEBUG debugtemp = *timeStep; #endif /* STEPDEBUG */ @@ -38,7 +38,7 @@ BSIM3v32instance *here; CKTterr(here->BSIM3v32qd,ckt,timeStep); #ifdef STEPDEBUG if(debugtemp != *timeStep) - { printf("device %s reduces step from %g to %g\n", + { printf("device %s reduces step from %g to %g\n", here->BSIM3v32name,debugtemp,*timeStep); } #endif /* STEPDEBUG */ diff --git a/src/spicelib/devices/bsim3v32/bsim3v32def.h b/src/spicelib/devices/bsim3v32/bsim3v32def.h index 10f1325d5..7b6ce2037 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32def.h +++ b/src/spicelib/devices/bsim3v32/bsim3v32def.h @@ -14,7 +14,7 @@ File: bsim3v32def.h #include "ngspice/gendefs.h" #include "ngspice/cktdefs.h" #include "ngspice/complex.h" -#include "ngspice/noisedef.h" +#include "ngspice/noisedef.h" typedef struct sBSIM3v32instance { @@ -32,7 +32,7 @@ typedef struct sBSIM3v32instance /* MCJ */ double BSIM3v32ueff; - double BSIM3v32thetavth; + double BSIM3v32thetavth; double BSIM3v32von; double BSIM3v32vdsat; double BSIM3v32cgdo; @@ -44,7 +44,7 @@ typedef struct sBSIM3v32instance double BSIM3v32l; double BSIM3v32w; - double BSIM3v32m; + double BSIM3v32m; double BSIM3v32drainArea; double BSIM3v32sourceArea; double BSIM3v32drainSquares; @@ -67,6 +67,7 @@ typedef struct sBSIM3v32instance int BSIM3v32off; int BSIM3v32mode; int BSIM3v32nqsMod; + int BSIM3v32geo; /* OP point */ double BSIM3v32qinv; @@ -120,7 +121,7 @@ typedef struct sBSIM3v32instance unsigned BSIM3v32lGiven :1; unsigned BSIM3v32wGiven :1; - unsigned BSIM3v32mGiven :1; + unsigned BSIM3v32mGiven :1; unsigned BSIM3v32drainAreaGiven :1; unsigned BSIM3v32sourceAreaGiven :1; unsigned BSIM3v32drainSquaresGiven :1; @@ -135,6 +136,7 @@ typedef struct sBSIM3v32instance unsigned BSIM3v32icVDSGiven :1; unsigned BSIM3v32icVGSGiven :1; unsigned BSIM3v32nqsModGiven :1; + unsigned BSIM3v32geoGiven :1; double *BSIM3v32DdPtr; double *BSIM3v32GgPtr; @@ -251,29 +253,29 @@ struct bsim3v32SizeDependParam double Width; double Length; - double BSIM3v32cdsc; - double BSIM3v32cdscb; - double BSIM3v32cdscd; - double BSIM3v32cit; - double BSIM3v32nfactor; + double BSIM3v32cdsc; + double BSIM3v32cdscb; + double BSIM3v32cdscd; + double BSIM3v32cit; + double BSIM3v32nfactor; double BSIM3v32xj; - double BSIM3v32vsat; - double BSIM3v32at; - double BSIM3v32a0; - double BSIM3v32ags; - double BSIM3v32a1; - double BSIM3v32a2; - double BSIM3v32keta; + double BSIM3v32vsat; + double BSIM3v32at; + double BSIM3v32a0; + double BSIM3v32ags; + double BSIM3v32a1; + double BSIM3v32a2; + double BSIM3v32keta; double BSIM3v32nsub; - double BSIM3v32npeak; - double BSIM3v32ngate; - double BSIM3v32gamma1; - double BSIM3v32gamma2; - double BSIM3v32vbx; - double BSIM3v32vbi; - double BSIM3v32vbm; - double BSIM3v32vbsc; - double BSIM3v32xt; + double BSIM3v32npeak; + double BSIM3v32ngate; + double BSIM3v32gamma1; + double BSIM3v32gamma2; + double BSIM3v32vbx; + double BSIM3v32vbi; + double BSIM3v32vbm; + double BSIM3v32vbsc; + double BSIM3v32xt; double BSIM3v32phi; double BSIM3v32litl; double BSIM3v32k1; @@ -285,14 +287,14 @@ struct bsim3v32SizeDependParam double BSIM3v32k3b; double BSIM3v32w0; double BSIM3v32nlx; - double BSIM3v32dvt0; - double BSIM3v32dvt1; - double BSIM3v32dvt2; - double BSIM3v32dvt0w; - double BSIM3v32dvt1w; - double BSIM3v32dvt2w; - double BSIM3v32drout; - double BSIM3v32dsub; + double BSIM3v32dvt0; + double BSIM3v32dvt1; + double BSIM3v32dvt2; + double BSIM3v32dvt0w; + double BSIM3v32dvt1w; + double BSIM3v32dvt2w; + double BSIM3v32drout; + double BSIM3v32dsub; double BSIM3v32vth0; double BSIM3v32ua; double BSIM3v32ua1; @@ -305,20 +307,20 @@ struct bsim3v32SizeDependParam double BSIM3v32voff; double BSIM3v32vfb; double BSIM3v32delta; - double BSIM3v32rdsw; - double BSIM3v32rds0; - double BSIM3v32prwg; - double BSIM3v32prwb; - double BSIM3v32prt; - double BSIM3v32eta0; - double BSIM3v32etab; - double BSIM3v32pclm; - double BSIM3v32pdibl1; - double BSIM3v32pdibl2; - double BSIM3v32pdiblb; - double BSIM3v32pscbe1; - double BSIM3v32pscbe2; - double BSIM3v32pvag; + double BSIM3v32rdsw; + double BSIM3v32rds0; + double BSIM3v32prwg; + double BSIM3v32prwb; + double BSIM3v32prt; + double BSIM3v32eta0; + double BSIM3v32etab; + double BSIM3v32pclm; + double BSIM3v32pdibl1; + double BSIM3v32pdibl2; + double BSIM3v32pdiblb; + double BSIM3v32pscbe1; + double BSIM3v32pscbe2; + double BSIM3v32pvag; double BSIM3v32wr; double BSIM3v32dwg; double BSIM3v32dwb; @@ -361,14 +363,14 @@ struct bsim3v32SizeDependParam double BSIM3v32cgbo; double BSIM3v32tconst; - double BSIM3v32u0temp; - double BSIM3v32vsattemp; - double BSIM3v32sqrtPhi; - double BSIM3v32phis3; - double BSIM3v32Xdep0; - double BSIM3v32sqrtXdep0; + double BSIM3v32u0temp; + double BSIM3v32vsattemp; + double BSIM3v32sqrtPhi; + double BSIM3v32phis3; + double BSIM3v32Xdep0; + double BSIM3v32sqrtXdep0; double BSIM3v32theta0vb0; - double BSIM3v32thetaRout; + double BSIM3v32thetaRout; double BSIM3v32cof1; double BSIM3v32cof2; @@ -384,53 +386,55 @@ struct bsim3v32SizeDependParam }; -typedef struct sBSIM3v32model +typedef struct sBSIM3v32model { int BSIM3v32modType; struct sBSIM3v32model *BSIM3v32nextModel; BSIM3v32instance *BSIM3v32instances; - IFuid BSIM3v32modName; + IFuid BSIM3v32modName; int BSIM3v32type; int BSIM3v32mobMod; int BSIM3v32capMod; int BSIM3v32acmMod; + int BSIM3v32calcacm; int BSIM3v32noiMod; + int BSIM3v32nqsMod; int BSIM3v32binUnit; int BSIM3v32paramChk; - char *BSIM3v32version; + char *BSIM3v32version; /* The following field is an integer coding * of BSIM3v32version. - */ - int BSIM3v32intVersion; + */ + int BSIM3v32intVersion; #define BSIM3v32V324 324 /* BSIM3v32 V3.2.4 */ #define BSIM3v32V323 323 /* BSIM3v32 V3.2.3 */ #define BSIM3v32V322 322 /* BSIM3v32 V3.2.2 */ #define BSIM3v32V32 32 /* BSIM3v32 V3.2 */ #define BSIM3v32V3OLD 0 /* Old model */ - double BSIM3v32tox; + double BSIM3v32tox; double BSIM3v32toxm; - double BSIM3v32cdsc; - double BSIM3v32cdscb; - double BSIM3v32cdscd; - double BSIM3v32cit; - double BSIM3v32nfactor; + double BSIM3v32cdsc; + double BSIM3v32cdscb; + double BSIM3v32cdscd; + double BSIM3v32cit; + double BSIM3v32nfactor; double BSIM3v32xj; - double BSIM3v32vsat; - double BSIM3v32at; - double BSIM3v32a0; - double BSIM3v32ags; - double BSIM3v32a1; - double BSIM3v32a2; - double BSIM3v32keta; + double BSIM3v32vsat; + double BSIM3v32at; + double BSIM3v32a0; + double BSIM3v32ags; + double BSIM3v32a1; + double BSIM3v32a2; + double BSIM3v32keta; double BSIM3v32nsub; - double BSIM3v32npeak; - double BSIM3v32ngate; - double BSIM3v32gamma1; - double BSIM3v32gamma2; - double BSIM3v32vbx; - double BSIM3v32vbm; - double BSIM3v32xt; + double BSIM3v32npeak; + double BSIM3v32ngate; + double BSIM3v32gamma1; + double BSIM3v32gamma2; + double BSIM3v32vbx; + double BSIM3v32vbm; + double BSIM3v32xt; double BSIM3v32k1; double BSIM3v32kt1; double BSIM3v32kt1l; @@ -440,14 +444,14 @@ typedef struct sBSIM3v32model double BSIM3v32k3b; double BSIM3v32w0; double BSIM3v32nlx; - double BSIM3v32dvt0; - double BSIM3v32dvt1; - double BSIM3v32dvt2; - double BSIM3v32dvt0w; - double BSIM3v32dvt1w; - double BSIM3v32dvt2w; - double BSIM3v32drout; - double BSIM3v32dsub; + double BSIM3v32dvt0; + double BSIM3v32dvt1; + double BSIM3v32dvt2; + double BSIM3v32dvt0w; + double BSIM3v32dvt1w; + double BSIM3v32dvt2w; + double BSIM3v32drout; + double BSIM3v32dsub; double BSIM3v32vth0; double BSIM3v32ua; double BSIM3v32ua1; @@ -459,19 +463,19 @@ typedef struct sBSIM3v32model double BSIM3v32ute; double BSIM3v32voff; double BSIM3v32delta; - double BSIM3v32rdsw; + double BSIM3v32rdsw; double BSIM3v32prwg; double BSIM3v32prwb; - double BSIM3v32prt; - double BSIM3v32eta0; - double BSIM3v32etab; - double BSIM3v32pclm; - double BSIM3v32pdibl1; - double BSIM3v32pdibl2; + double BSIM3v32prt; + double BSIM3v32eta0; + double BSIM3v32etab; + double BSIM3v32pclm; + double BSIM3v32pdibl1; + double BSIM3v32pdibl2; double BSIM3v32pdiblb; - double BSIM3v32pscbe1; - double BSIM3v32pscbe2; - double BSIM3v32pvag; + double BSIM3v32pscbe1; + double BSIM3v32pscbe2; + double BSIM3v32pvag; double BSIM3v32wr; double BSIM3v32dwg; double BSIM3v32dwb; @@ -505,7 +509,9 @@ typedef struct sBSIM3v32model double BSIM3v32tpbsw; double BSIM3v32tpbswg; - /* acm model */ + /* ACM model */ + double BSIM3v32xl; + double BSIM3v32xw; double BSIM3v32hdif; double BSIM3v32ldif; double BSIM3v32ld; @@ -513,29 +519,30 @@ typedef struct sBSIM3v32model double BSIM3v32rs; double BSIM3v32rdc; double BSIM3v32rsc; + double BSIM3v32wmlt; /* Length Dependence */ - double BSIM3v32lcdsc; - double BSIM3v32lcdscb; - double BSIM3v32lcdscd; - double BSIM3v32lcit; - double BSIM3v32lnfactor; + double BSIM3v32lcdsc; + double BSIM3v32lcdscb; + double BSIM3v32lcdscd; + double BSIM3v32lcit; + double BSIM3v32lnfactor; double BSIM3v32lxj; - double BSIM3v32lvsat; - double BSIM3v32lat; - double BSIM3v32la0; - double BSIM3v32lags; - double BSIM3v32la1; - double BSIM3v32la2; - double BSIM3v32lketa; + double BSIM3v32lvsat; + double BSIM3v32lat; + double BSIM3v32la0; + double BSIM3v32lags; + double BSIM3v32la1; + double BSIM3v32la2; + double BSIM3v32lketa; double BSIM3v32lnsub; - double BSIM3v32lnpeak; - double BSIM3v32lngate; - double BSIM3v32lgamma1; - double BSIM3v32lgamma2; - double BSIM3v32lvbx; - double BSIM3v32lvbm; - double BSIM3v32lxt; + double BSIM3v32lnpeak; + double BSIM3v32lngate; + double BSIM3v32lgamma1; + double BSIM3v32lgamma2; + double BSIM3v32lvbx; + double BSIM3v32lvbm; + double BSIM3v32lxt; double BSIM3v32lk1; double BSIM3v32lkt1; double BSIM3v32lkt1l; @@ -545,14 +552,14 @@ typedef struct sBSIM3v32model double BSIM3v32lk3b; double BSIM3v32lw0; double BSIM3v32lnlx; - double BSIM3v32ldvt0; - double BSIM3v32ldvt1; - double BSIM3v32ldvt2; - double BSIM3v32ldvt0w; - double BSIM3v32ldvt1w; - double BSIM3v32ldvt2w; - double BSIM3v32ldrout; - double BSIM3v32ldsub; + double BSIM3v32ldvt0; + double BSIM3v32ldvt1; + double BSIM3v32ldvt2; + double BSIM3v32ldvt0w; + double BSIM3v32ldvt1w; + double BSIM3v32ldvt2w; + double BSIM3v32ldrout; + double BSIM3v32ldsub; double BSIM3v32lvth0; double BSIM3v32lua; double BSIM3v32lua1; @@ -564,19 +571,19 @@ typedef struct sBSIM3v32model double BSIM3v32lute; double BSIM3v32lvoff; double BSIM3v32ldelta; - double BSIM3v32lrdsw; + double BSIM3v32lrdsw; double BSIM3v32lprwg; double BSIM3v32lprwb; - double BSIM3v32lprt; - double BSIM3v32leta0; - double BSIM3v32letab; - double BSIM3v32lpclm; - double BSIM3v32lpdibl1; - double BSIM3v32lpdibl2; + double BSIM3v32lprt; + double BSIM3v32leta0; + double BSIM3v32letab; + double BSIM3v32lpclm; + double BSIM3v32lpdibl1; + double BSIM3v32lpdibl2; double BSIM3v32lpdiblb; - double BSIM3v32lpscbe1; - double BSIM3v32lpscbe2; - double BSIM3v32lpvag; + double BSIM3v32lpscbe1; + double BSIM3v32lpscbe2; + double BSIM3v32lpvag; double BSIM3v32lwr; double BSIM3v32ldwg; double BSIM3v32ldwb; @@ -602,27 +609,27 @@ typedef struct sBSIM3v32model double BSIM3v32lmoin; /* Width Dependence */ - double BSIM3v32wcdsc; - double BSIM3v32wcdscb; - double BSIM3v32wcdscd; - double BSIM3v32wcit; - double BSIM3v32wnfactor; + double BSIM3v32wcdsc; + double BSIM3v32wcdscb; + double BSIM3v32wcdscd; + double BSIM3v32wcit; + double BSIM3v32wnfactor; double BSIM3v32wxj; - double BSIM3v32wvsat; - double BSIM3v32wat; - double BSIM3v32wa0; - double BSIM3v32wags; - double BSIM3v32wa1; - double BSIM3v32wa2; - double BSIM3v32wketa; + double BSIM3v32wvsat; + double BSIM3v32wat; + double BSIM3v32wa0; + double BSIM3v32wags; + double BSIM3v32wa1; + double BSIM3v32wa2; + double BSIM3v32wketa; double BSIM3v32wnsub; - double BSIM3v32wnpeak; - double BSIM3v32wngate; - double BSIM3v32wgamma1; - double BSIM3v32wgamma2; - double BSIM3v32wvbx; - double BSIM3v32wvbm; - double BSIM3v32wxt; + double BSIM3v32wnpeak; + double BSIM3v32wngate; + double BSIM3v32wgamma1; + double BSIM3v32wgamma2; + double BSIM3v32wvbx; + double BSIM3v32wvbm; + double BSIM3v32wxt; double BSIM3v32wk1; double BSIM3v32wkt1; double BSIM3v32wkt1l; @@ -632,14 +639,14 @@ typedef struct sBSIM3v32model double BSIM3v32wk3b; double BSIM3v32ww0; double BSIM3v32wnlx; - double BSIM3v32wdvt0; - double BSIM3v32wdvt1; - double BSIM3v32wdvt2; - double BSIM3v32wdvt0w; - double BSIM3v32wdvt1w; - double BSIM3v32wdvt2w; - double BSIM3v32wdrout; - double BSIM3v32wdsub; + double BSIM3v32wdvt0; + double BSIM3v32wdvt1; + double BSIM3v32wdvt2; + double BSIM3v32wdvt0w; + double BSIM3v32wdvt1w; + double BSIM3v32wdvt2w; + double BSIM3v32wdrout; + double BSIM3v32wdsub; double BSIM3v32wvth0; double BSIM3v32wua; double BSIM3v32wua1; @@ -651,19 +658,19 @@ typedef struct sBSIM3v32model double BSIM3v32wute; double BSIM3v32wvoff; double BSIM3v32wdelta; - double BSIM3v32wrdsw; + double BSIM3v32wrdsw; double BSIM3v32wprwg; double BSIM3v32wprwb; - double BSIM3v32wprt; - double BSIM3v32weta0; - double BSIM3v32wetab; - double BSIM3v32wpclm; - double BSIM3v32wpdibl1; - double BSIM3v32wpdibl2; + double BSIM3v32wprt; + double BSIM3v32weta0; + double BSIM3v32wetab; + double BSIM3v32wpclm; + double BSIM3v32wpdibl1; + double BSIM3v32wpdibl2; double BSIM3v32wpdiblb; - double BSIM3v32wpscbe1; - double BSIM3v32wpscbe2; - double BSIM3v32wpvag; + double BSIM3v32wpscbe1; + double BSIM3v32wpscbe2; + double BSIM3v32wpvag; double BSIM3v32wwr; double BSIM3v32wdwg; double BSIM3v32wdwb; @@ -689,27 +696,27 @@ typedef struct sBSIM3v32model double BSIM3v32wmoin; /* Cross-term Dependence */ - double BSIM3v32pcdsc; - double BSIM3v32pcdscb; - double BSIM3v32pcdscd; - double BSIM3v32pcit; - double BSIM3v32pnfactor; + double BSIM3v32pcdsc; + double BSIM3v32pcdscb; + double BSIM3v32pcdscd; + double BSIM3v32pcit; + double BSIM3v32pnfactor; double BSIM3v32pxj; - double BSIM3v32pvsat; - double BSIM3v32pat; - double BSIM3v32pa0; - double BSIM3v32pags; - double BSIM3v32pa1; - double BSIM3v32pa2; - double BSIM3v32pketa; + double BSIM3v32pvsat; + double BSIM3v32pat; + double BSIM3v32pa0; + double BSIM3v32pags; + double BSIM3v32pa1; + double BSIM3v32pa2; + double BSIM3v32pketa; double BSIM3v32pnsub; - double BSIM3v32pnpeak; - double BSIM3v32pngate; - double BSIM3v32pgamma1; - double BSIM3v32pgamma2; - double BSIM3v32pvbx; - double BSIM3v32pvbm; - double BSIM3v32pxt; + double BSIM3v32pnpeak; + double BSIM3v32pngate; + double BSIM3v32pgamma1; + double BSIM3v32pgamma2; + double BSIM3v32pvbx; + double BSIM3v32pvbm; + double BSIM3v32pxt; double BSIM3v32pk1; double BSIM3v32pkt1; double BSIM3v32pkt1l; @@ -719,14 +726,14 @@ typedef struct sBSIM3v32model double BSIM3v32pk3b; double BSIM3v32pw0; double BSIM3v32pnlx; - double BSIM3v32pdvt0; - double BSIM3v32pdvt1; - double BSIM3v32pdvt2; - double BSIM3v32pdvt0w; - double BSIM3v32pdvt1w; - double BSIM3v32pdvt2w; - double BSIM3v32pdrout; - double BSIM3v32pdsub; + double BSIM3v32pdvt0; + double BSIM3v32pdvt1; + double BSIM3v32pdvt2; + double BSIM3v32pdvt0w; + double BSIM3v32pdvt1w; + double BSIM3v32pdvt2w; + double BSIM3v32pdrout; + double BSIM3v32pdsub; double BSIM3v32pvth0; double BSIM3v32pua; double BSIM3v32pua1; @@ -741,16 +748,16 @@ typedef struct sBSIM3v32model double BSIM3v32prdsw; double BSIM3v32pprwg; double BSIM3v32pprwb; - double BSIM3v32pprt; - double BSIM3v32peta0; - double BSIM3v32petab; - double BSIM3v32ppclm; - double BSIM3v32ppdibl1; - double BSIM3v32ppdibl2; + double BSIM3v32pprt; + double BSIM3v32peta0; + double BSIM3v32petab; + double BSIM3v32ppclm; + double BSIM3v32ppdibl1; + double BSIM3v32ppdibl2; double BSIM3v32ppdiblb; - double BSIM3v32ppscbe1; - double BSIM3v32ppscbe2; - double BSIM3v32ppvag; + double BSIM3v32ppscbe1; + double BSIM3v32ppscbe2; + double BSIM3v32ppvag; double BSIM3v32pwr; double BSIM3v32pdwg; double BSIM3v32pdwb; @@ -822,13 +829,9 @@ typedef struct sBSIM3v32model double BSIM3v32Wmin; double BSIM3v32Wmax; - /* acm model */ - double BSIM3v32xl; - double BSIM3v32xw; - /* Pre-calculated constants */ /* MCJ: move to size-dependent param. */ - double BSIM3v32vtm; + double BSIM3v32vtm; double BSIM3v32cox; double BSIM3v32cof1; double BSIM3v32cof2; @@ -845,13 +848,13 @@ typedef struct sBSIM3v32model double BSIM3v32unitLengthSidewallTempJctCap; double BSIM3v32unitLengthGateSidewallTempJctCap; - double BSIM3v32oxideTrapDensityA; - double BSIM3v32oxideTrapDensityB; - double BSIM3v32oxideTrapDensityC; - double BSIM3v32em; - double BSIM3v32ef; - double BSIM3v32af; - double BSIM3v32kf; + double BSIM3v32oxideTrapDensityA; + double BSIM3v32oxideTrapDensityB; + double BSIM3v32oxideTrapDensityC; + double BSIM3v32em; + double BSIM3v32ef; + double BSIM3v32af; + double BSIM3v32kf; struct bsim3v32SizeDependParam *pSizeDependParamKnot; @@ -860,8 +863,10 @@ typedef struct sBSIM3v32model unsigned BSIM3v32binUnitGiven :1; unsigned BSIM3v32capModGiven :1; unsigned BSIM3v32acmModGiven :1; + unsigned BSIM3v32calcacmGiven :1; unsigned BSIM3v32paramChkGiven :1; unsigned BSIM3v32noiModGiven :1; + unsigned BSIM3v32nqsModGiven :1; unsigned BSIM3v32typeGiven :1; unsigned BSIM3v32toxGiven :1; unsigned BSIM3v32versionGiven :1; @@ -878,7 +883,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32agsGiven :1; unsigned BSIM3v32a1Given :1; unsigned BSIM3v32a2Given :1; - unsigned BSIM3v32ketaGiven :1; + unsigned BSIM3v32ketaGiven :1; unsigned BSIM3v32nsubGiven :1; unsigned BSIM3v32npeakGiven :1; unsigned BSIM3v32ngateGiven :1; @@ -896,14 +901,14 @@ typedef struct sBSIM3v32model unsigned BSIM3v32k3bGiven :1; unsigned BSIM3v32w0Given :1; unsigned BSIM3v32nlxGiven :1; - unsigned BSIM3v32dvt0Given :1; - unsigned BSIM3v32dvt1Given :1; - unsigned BSIM3v32dvt2Given :1; - unsigned BSIM3v32dvt0wGiven :1; - unsigned BSIM3v32dvt1wGiven :1; - unsigned BSIM3v32dvt2wGiven :1; - unsigned BSIM3v32droutGiven :1; - unsigned BSIM3v32dsubGiven :1; + unsigned BSIM3v32dvt0Given :1; + unsigned BSIM3v32dvt1Given :1; + unsigned BSIM3v32dvt2Given :1; + unsigned BSIM3v32dvt0wGiven :1; + unsigned BSIM3v32dvt1wGiven :1; + unsigned BSIM3v32dvt2wGiven :1; + unsigned BSIM3v32droutGiven :1; + unsigned BSIM3v32dsubGiven :1; unsigned BSIM3v32vth0Given :1; unsigned BSIM3v32uaGiven :1; unsigned BSIM3v32ua1Given :1; @@ -914,20 +919,20 @@ typedef struct sBSIM3v32model unsigned BSIM3v32u0Given :1; unsigned BSIM3v32uteGiven :1; unsigned BSIM3v32voffGiven :1; - unsigned BSIM3v32rdswGiven :1; - unsigned BSIM3v32prwgGiven :1; - unsigned BSIM3v32prwbGiven :1; - unsigned BSIM3v32prtGiven :1; - unsigned BSIM3v32eta0Given :1; - unsigned BSIM3v32etabGiven :1; - unsigned BSIM3v32pclmGiven :1; - unsigned BSIM3v32pdibl1Given :1; - unsigned BSIM3v32pdibl2Given :1; - unsigned BSIM3v32pdiblbGiven :1; - unsigned BSIM3v32pscbe1Given :1; - unsigned BSIM3v32pscbe2Given :1; - unsigned BSIM3v32pvagGiven :1; - unsigned BSIM3v32deltaGiven :1; + unsigned BSIM3v32rdswGiven :1; + unsigned BSIM3v32prwgGiven :1; + unsigned BSIM3v32prwbGiven :1; + unsigned BSIM3v32prtGiven :1; + unsigned BSIM3v32eta0Given :1; + unsigned BSIM3v32etabGiven :1; + unsigned BSIM3v32pclmGiven :1; + unsigned BSIM3v32pdibl1Given :1; + unsigned BSIM3v32pdibl2Given :1; + unsigned BSIM3v32pdiblbGiven :1; + unsigned BSIM3v32pscbe1Given :1; + unsigned BSIM3v32pscbe2Given :1; + unsigned BSIM3v32pvagGiven :1; + unsigned BSIM3v32deltaGiven :1; unsigned BSIM3v32wrGiven :1; unsigned BSIM3v32dwgGiven :1; unsigned BSIM3v32dwbGiven :1; @@ -940,7 +945,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32vfbGiven :1; /* CV model */ - unsigned BSIM3v32elmGiven :1; + unsigned BSIM3v32elmGiven :1; unsigned BSIM3v32cgslGiven :1; unsigned BSIM3v32cgdlGiven :1; unsigned BSIM3v32ckappaGiven :1; @@ -961,14 +966,17 @@ typedef struct sBSIM3v32model unsigned BSIM3v32tpbswGiven :1; unsigned BSIM3v32tpbswgGiven :1; - /* acm model */ - unsigned BSIM3v32hdifGiven :1; + /* ACM model */ + unsigned BSIM3v32xlGiven :1; + unsigned BSIM3v32xwGiven :1; + unsigned BSIM3v32hdifGiven :1; unsigned BSIM3v32ldifGiven :1; unsigned BSIM3v32ldGiven :1; unsigned BSIM3v32rdGiven :1; unsigned BSIM3v32rsGiven :1; unsigned BSIM3v32rdcGiven :1; unsigned BSIM3v32rscGiven :1; + unsigned BSIM3v32wmltGiven :1; /* Length dependence */ unsigned BSIM3v32lcdscGiven :1; @@ -983,7 +991,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32lagsGiven :1; unsigned BSIM3v32la1Given :1; unsigned BSIM3v32la2Given :1; - unsigned BSIM3v32lketaGiven :1; + unsigned BSIM3v32lketaGiven :1; unsigned BSIM3v32lnsubGiven :1; unsigned BSIM3v32lnpeakGiven :1; unsigned BSIM3v32lngateGiven :1; @@ -1001,14 +1009,14 @@ typedef struct sBSIM3v32model unsigned BSIM3v32lk3bGiven :1; unsigned BSIM3v32lw0Given :1; unsigned BSIM3v32lnlxGiven :1; - unsigned BSIM3v32ldvt0Given :1; - unsigned BSIM3v32ldvt1Given :1; - unsigned BSIM3v32ldvt2Given :1; - unsigned BSIM3v32ldvt0wGiven :1; - unsigned BSIM3v32ldvt1wGiven :1; - unsigned BSIM3v32ldvt2wGiven :1; - unsigned BSIM3v32ldroutGiven :1; - unsigned BSIM3v32ldsubGiven :1; + unsigned BSIM3v32ldvt0Given :1; + unsigned BSIM3v32ldvt1Given :1; + unsigned BSIM3v32ldvt2Given :1; + unsigned BSIM3v32ldvt0wGiven :1; + unsigned BSIM3v32ldvt1wGiven :1; + unsigned BSIM3v32ldvt2wGiven :1; + unsigned BSIM3v32ldroutGiven :1; + unsigned BSIM3v32ldsubGiven :1; unsigned BSIM3v32lvth0Given :1; unsigned BSIM3v32luaGiven :1; unsigned BSIM3v32lua1Given :1; @@ -1019,20 +1027,20 @@ typedef struct sBSIM3v32model unsigned BSIM3v32lu0Given :1; unsigned BSIM3v32luteGiven :1; unsigned BSIM3v32lvoffGiven :1; - unsigned BSIM3v32lrdswGiven :1; - unsigned BSIM3v32lprwgGiven :1; - unsigned BSIM3v32lprwbGiven :1; - unsigned BSIM3v32lprtGiven :1; - unsigned BSIM3v32leta0Given :1; - unsigned BSIM3v32letabGiven :1; - unsigned BSIM3v32lpclmGiven :1; - unsigned BSIM3v32lpdibl1Given :1; - unsigned BSIM3v32lpdibl2Given :1; - unsigned BSIM3v32lpdiblbGiven :1; - unsigned BSIM3v32lpscbe1Given :1; - unsigned BSIM3v32lpscbe2Given :1; - unsigned BSIM3v32lpvagGiven :1; - unsigned BSIM3v32ldeltaGiven :1; + unsigned BSIM3v32lrdswGiven :1; + unsigned BSIM3v32lprwgGiven :1; + unsigned BSIM3v32lprwbGiven :1; + unsigned BSIM3v32lprtGiven :1; + unsigned BSIM3v32leta0Given :1; + unsigned BSIM3v32letabGiven :1; + unsigned BSIM3v32lpclmGiven :1; + unsigned BSIM3v32lpdibl1Given :1; + unsigned BSIM3v32lpdibl2Given :1; + unsigned BSIM3v32lpdiblbGiven :1; + unsigned BSIM3v32lpscbe1Given :1; + unsigned BSIM3v32lpscbe2Given :1; + unsigned BSIM3v32lpvagGiven :1; + unsigned BSIM3v32ldeltaGiven :1; unsigned BSIM3v32lwrGiven :1; unsigned BSIM3v32ldwgGiven :1; unsigned BSIM3v32ldwbGiven :1; @@ -1044,7 +1052,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32lvfbGiven :1; /* CV model */ - unsigned BSIM3v32lelmGiven :1; + unsigned BSIM3v32lelmGiven :1; unsigned BSIM3v32lcgslGiven :1; unsigned BSIM3v32lcgdlGiven :1; unsigned BSIM3v32lckappaGiven :1; @@ -1070,7 +1078,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32wagsGiven :1; unsigned BSIM3v32wa1Given :1; unsigned BSIM3v32wa2Given :1; - unsigned BSIM3v32wketaGiven :1; + unsigned BSIM3v32wketaGiven :1; unsigned BSIM3v32wnsubGiven :1; unsigned BSIM3v32wnpeakGiven :1; unsigned BSIM3v32wngateGiven :1; @@ -1088,14 +1096,14 @@ typedef struct sBSIM3v32model unsigned BSIM3v32wk3bGiven :1; unsigned BSIM3v32ww0Given :1; unsigned BSIM3v32wnlxGiven :1; - unsigned BSIM3v32wdvt0Given :1; - unsigned BSIM3v32wdvt1Given :1; - unsigned BSIM3v32wdvt2Given :1; - unsigned BSIM3v32wdvt0wGiven :1; - unsigned BSIM3v32wdvt1wGiven :1; - unsigned BSIM3v32wdvt2wGiven :1; - unsigned BSIM3v32wdroutGiven :1; - unsigned BSIM3v32wdsubGiven :1; + unsigned BSIM3v32wdvt0Given :1; + unsigned BSIM3v32wdvt1Given :1; + unsigned BSIM3v32wdvt2Given :1; + unsigned BSIM3v32wdvt0wGiven :1; + unsigned BSIM3v32wdvt1wGiven :1; + unsigned BSIM3v32wdvt2wGiven :1; + unsigned BSIM3v32wdroutGiven :1; + unsigned BSIM3v32wdsubGiven :1; unsigned BSIM3v32wvth0Given :1; unsigned BSIM3v32wuaGiven :1; unsigned BSIM3v32wua1Given :1; @@ -1106,20 +1114,20 @@ typedef struct sBSIM3v32model unsigned BSIM3v32wu0Given :1; unsigned BSIM3v32wuteGiven :1; unsigned BSIM3v32wvoffGiven :1; - unsigned BSIM3v32wrdswGiven :1; - unsigned BSIM3v32wprwgGiven :1; - unsigned BSIM3v32wprwbGiven :1; - unsigned BSIM3v32wprtGiven :1; - unsigned BSIM3v32weta0Given :1; - unsigned BSIM3v32wetabGiven :1; - unsigned BSIM3v32wpclmGiven :1; - unsigned BSIM3v32wpdibl1Given :1; - unsigned BSIM3v32wpdibl2Given :1; - unsigned BSIM3v32wpdiblbGiven :1; - unsigned BSIM3v32wpscbe1Given :1; - unsigned BSIM3v32wpscbe2Given :1; - unsigned BSIM3v32wpvagGiven :1; - unsigned BSIM3v32wdeltaGiven :1; + unsigned BSIM3v32wrdswGiven :1; + unsigned BSIM3v32wprwgGiven :1; + unsigned BSIM3v32wprwbGiven :1; + unsigned BSIM3v32wprtGiven :1; + unsigned BSIM3v32weta0Given :1; + unsigned BSIM3v32wetabGiven :1; + unsigned BSIM3v32wpclmGiven :1; + unsigned BSIM3v32wpdibl1Given :1; + unsigned BSIM3v32wpdibl2Given :1; + unsigned BSIM3v32wpdiblbGiven :1; + unsigned BSIM3v32wpscbe1Given :1; + unsigned BSIM3v32wpscbe2Given :1; + unsigned BSIM3v32wpvagGiven :1; + unsigned BSIM3v32wdeltaGiven :1; unsigned BSIM3v32wwrGiven :1; unsigned BSIM3v32wdwgGiven :1; unsigned BSIM3v32wdwbGiven :1; @@ -1131,7 +1139,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32wvfbGiven :1; /* CV model */ - unsigned BSIM3v32welmGiven :1; + unsigned BSIM3v32welmGiven :1; unsigned BSIM3v32wcgslGiven :1; unsigned BSIM3v32wcgdlGiven :1; unsigned BSIM3v32wckappaGiven :1; @@ -1157,7 +1165,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32pagsGiven :1; unsigned BSIM3v32pa1Given :1; unsigned BSIM3v32pa2Given :1; - unsigned BSIM3v32pketaGiven :1; + unsigned BSIM3v32pketaGiven :1; unsigned BSIM3v32pnsubGiven :1; unsigned BSIM3v32pnpeakGiven :1; unsigned BSIM3v32pngateGiven :1; @@ -1175,14 +1183,14 @@ typedef struct sBSIM3v32model unsigned BSIM3v32pk3bGiven :1; unsigned BSIM3v32pw0Given :1; unsigned BSIM3v32pnlxGiven :1; - unsigned BSIM3v32pdvt0Given :1; - unsigned BSIM3v32pdvt1Given :1; - unsigned BSIM3v32pdvt2Given :1; - unsigned BSIM3v32pdvt0wGiven :1; - unsigned BSIM3v32pdvt1wGiven :1; - unsigned BSIM3v32pdvt2wGiven :1; - unsigned BSIM3v32pdroutGiven :1; - unsigned BSIM3v32pdsubGiven :1; + unsigned BSIM3v32pdvt0Given :1; + unsigned BSIM3v32pdvt1Given :1; + unsigned BSIM3v32pdvt2Given :1; + unsigned BSIM3v32pdvt0wGiven :1; + unsigned BSIM3v32pdvt1wGiven :1; + unsigned BSIM3v32pdvt2wGiven :1; + unsigned BSIM3v32pdroutGiven :1; + unsigned BSIM3v32pdsubGiven :1; unsigned BSIM3v32pvth0Given :1; unsigned BSIM3v32puaGiven :1; unsigned BSIM3v32pua1Given :1; @@ -1193,20 +1201,20 @@ typedef struct sBSIM3v32model unsigned BSIM3v32pu0Given :1; unsigned BSIM3v32puteGiven :1; unsigned BSIM3v32pvoffGiven :1; - unsigned BSIM3v32prdswGiven :1; - unsigned BSIM3v32pprwgGiven :1; - unsigned BSIM3v32pprwbGiven :1; - unsigned BSIM3v32pprtGiven :1; - unsigned BSIM3v32peta0Given :1; - unsigned BSIM3v32petabGiven :1; - unsigned BSIM3v32ppclmGiven :1; - unsigned BSIM3v32ppdibl1Given :1; - unsigned BSIM3v32ppdibl2Given :1; - unsigned BSIM3v32ppdiblbGiven :1; - unsigned BSIM3v32ppscbe1Given :1; - unsigned BSIM3v32ppscbe2Given :1; - unsigned BSIM3v32ppvagGiven :1; - unsigned BSIM3v32pdeltaGiven :1; + unsigned BSIM3v32prdswGiven :1; + unsigned BSIM3v32pprwgGiven :1; + unsigned BSIM3v32pprwbGiven :1; + unsigned BSIM3v32pprtGiven :1; + unsigned BSIM3v32peta0Given :1; + unsigned BSIM3v32petabGiven :1; + unsigned BSIM3v32ppclmGiven :1; + unsigned BSIM3v32ppdibl1Given :1; + unsigned BSIM3v32ppdibl2Given :1; + unsigned BSIM3v32ppdiblbGiven :1; + unsigned BSIM3v32ppscbe1Given :1; + unsigned BSIM3v32ppscbe2Given :1; + unsigned BSIM3v32ppvagGiven :1; + unsigned BSIM3v32pdeltaGiven :1; unsigned BSIM3v32pwrGiven :1; unsigned BSIM3v32pdwgGiven :1; unsigned BSIM3v32pdwbGiven :1; @@ -1218,7 +1226,7 @@ typedef struct sBSIM3v32model unsigned BSIM3v32pvfbGiven :1; /* CV model */ - unsigned BSIM3v32pelmGiven :1; + unsigned BSIM3v32pelmGiven :1; unsigned BSIM3v32pcgslGiven :1; unsigned BSIM3v32pcgdlGiven :1; unsigned BSIM3v32pckappaGiven :1; @@ -1251,15 +1259,15 @@ typedef struct sBSIM3v32model unsigned BSIM3v32bulkJctGateSideGradingCoeffGiven :1; unsigned BSIM3v32unitLengthGateSidewallJctCapGiven :1; unsigned BSIM3v32jctEmissionCoeffGiven :1; - unsigned BSIM3v32jctTempExponentGiven :1; + unsigned BSIM3v32jctTempExponentGiven :1; - unsigned BSIM3v32oxideTrapDensityAGiven :1; - unsigned BSIM3v32oxideTrapDensityBGiven :1; - unsigned BSIM3v32oxideTrapDensityCGiven :1; - unsigned BSIM3v32emGiven :1; - unsigned BSIM3v32efGiven :1; - unsigned BSIM3v32afGiven :1; - unsigned BSIM3v32kfGiven :1; + unsigned BSIM3v32oxideTrapDensityAGiven :1; + unsigned BSIM3v32oxideTrapDensityBGiven :1; + unsigned BSIM3v32oxideTrapDensityCGiven :1; + unsigned BSIM3v32emGiven :1; + unsigned BSIM3v32efGiven :1; + unsigned BSIM3v32afGiven :1; + unsigned BSIM3v32kfGiven :1; unsigned BSIM3v32LintGiven :1; unsigned BSIM3v32LlGiven :1; @@ -1285,10 +1293,6 @@ typedef struct sBSIM3v32model unsigned BSIM3v32WminGiven :1; unsigned BSIM3v32WmaxGiven :1; - /* acm model */ - unsigned BSIM3v32xlGiven :1; - unsigned BSIM3v32xwGiven :1; - } BSIM3v32model; @@ -1316,37 +1320,40 @@ typedef struct sBSIM3v32model #define BSIM3v32_M 15 #define BSIM3v32_DELVTO 16 #define BSIM3v32_MULU0 17 +#define BSIM3v32_GEO 18 /* model parameters */ -#define BSIM3v32_MOD_CAPMOD 101 -#define BSIM3v32_MOD_ACMMOD 102 -#define BSIM3v32_MOD_MOBMOD 103 -#define BSIM3v32_MOD_NOIMOD 104 +#define BSIM3v32_MOD_CAPMOD 100 +#define BSIM3v32_MOD_ACMMOD 101 +#define BSIM3v32_MOD_CALCACM 102 +#define BSIM3v32_MOD_MOBMOD 103 +#define BSIM3v32_MOD_NOIMOD 104 +#define BSIM3v32_MOD_NQSMOD 105 -#define BSIM3v32_MOD_TOX 105 +#define BSIM3v32_MOD_TOX 106 -#define BSIM3v32_MOD_CDSC 106 -#define BSIM3v32_MOD_CDSCB 107 -#define BSIM3v32_MOD_CIT 108 -#define BSIM3v32_MOD_NFACTOR 109 -#define BSIM3v32_MOD_XJ 110 -#define BSIM3v32_MOD_VSAT 111 -#define BSIM3v32_MOD_AT 112 -#define BSIM3v32_MOD_A0 113 -#define BSIM3v32_MOD_A1 114 -#define BSIM3v32_MOD_A2 115 -#define BSIM3v32_MOD_KETA 116 -#define BSIM3v32_MOD_NSUB 117 -#define BSIM3v32_MOD_NPEAK 118 +#define BSIM3v32_MOD_CDSC 107 +#define BSIM3v32_MOD_CDSCB 108 +#define BSIM3v32_MOD_CIT 109 +#define BSIM3v32_MOD_NFACTOR 110 +#define BSIM3v32_MOD_XJ 111 +#define BSIM3v32_MOD_VSAT 112 +#define BSIM3v32_MOD_AT 113 +#define BSIM3v32_MOD_A0 114 +#define BSIM3v32_MOD_A1 115 +#define BSIM3v32_MOD_A2 116 +#define BSIM3v32_MOD_KETA 117 +#define BSIM3v32_MOD_NSUB 118 +#define BSIM3v32_MOD_NPEAK 119 #define BSIM3v32_MOD_NGATE 120 #define BSIM3v32_MOD_GAMMA1 121 #define BSIM3v32_MOD_GAMMA2 122 #define BSIM3v32_MOD_VBX 123 -#define BSIM3v32_MOD_BINUNIT 124 +#define BSIM3v32_MOD_BINUNIT 124 #define BSIM3v32_MOD_VBM 125 -#define BSIM3v32_MOD_XT 126 +#define BSIM3v32_MOD_XT 128 #define BSIM3v32_MOD_K1 129 #define BSIM3v32_MOD_KT1 130 #define BSIM3v32_MOD_KT1L 131 @@ -1442,7 +1449,7 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_LA0 258 #define BSIM3v32_MOD_LA1 259 #define BSIM3v32_MOD_LA2 260 -#define BSIM3v32_MOD_LKETA 261 +#define BSIM3v32_MOD_LKETA 261 #define BSIM3v32_MOD_LNSUB 262 #define BSIM3v32_MOD_LNPEAK 263 #define BSIM3v32_MOD_LNGATE 265 @@ -1510,7 +1517,7 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_LCDSCD 327 #define BSIM3v32_MOD_LAGS 328 - + #define BSIM3v32_MOD_LFRINGE 331 #define BSIM3v32_MOD_LELM 332 @@ -1539,7 +1546,7 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_WA0 388 #define BSIM3v32_MOD_WA1 389 #define BSIM3v32_MOD_WA2 390 -#define BSIM3v32_MOD_WKETA 391 +#define BSIM3v32_MOD_WKETA 391 #define BSIM3v32_MOD_WNSUB 392 #define BSIM3v32_MOD_WNPEAK 393 #define BSIM3v32_MOD_WNGATE 395 @@ -1636,7 +1643,7 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_PA0 518 #define BSIM3v32_MOD_PA1 519 #define BSIM3v32_MOD_PA2 520 -#define BSIM3v32_MOD_PKETA 521 +#define BSIM3v32_MOD_PKETA 521 #define BSIM3v32_MOD_PNSUB 522 #define BSIM3v32_MOD_PNPEAK 523 #define BSIM3v32_MOD_PNGATE 525 @@ -1784,10 +1791,9 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_WWC 701 #define BSIM3v32_MOD_WWLC 702 -/* acm parameters */ +/* ACM parameters */ #define BSIM3v32_MOD_XL 703 #define BSIM3v32_MOD_XW 704 - #define BSIM3v32_MOD_HDIF 711 #define BSIM3v32_MOD_LDIF 712 #define BSIM3v32_MOD_LD 713 @@ -1795,6 +1801,7 @@ typedef struct sBSIM3v32model #define BSIM3v32_MOD_RS 715 #define BSIM3v32_MOD_RDC 716 #define BSIM3v32_MOD_RSC 717 +#define BSIM3v32_MOD_WMLT 718 /* device questions */ #define BSIM3v32_DNODE 751 @@ -1845,8 +1852,8 @@ typedef struct sBSIM3v32model #include "bsim3v32ext.h" extern void BSIM3v32evaluate(double,double,double,BSIM3v32instance*,BSIM3v32model*, - double*,double*,double*, double*, double*, double*, double*, - double*, double*, double*, double*, double*, double*, double*, + double*,double*,double*, double*, double*, double*, double*, + double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, CKTcircuit*); extern int BSIM3v32debug(BSIM3v32model*, BSIM3v32instance*, CKTcircuit*, int); extern int BSIM3v32checkModel(BSIM3v32model*, BSIM3v32instance*, CKTcircuit*); diff --git a/src/spicelib/devices/bsim3v32/bsim3v32ext.h b/src/spicelib/devices/bsim3v32/bsim3v32ext.h index f607ee6b9..d25205115 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32ext.h +++ b/src/spicelib/devices/bsim3v32/bsim3v32ext.h @@ -20,7 +20,7 @@ extern void BSIM3v32mosCap(CKTcircuit*, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double*, double*, double*, double*, double*, double*, double*, double*, - double*, double*, double*, double*, double*, double*, double*, + double*, double*, double*, double*, double*, double*, double*, double*); extern int BSIM3v32param(int,IFvalue*,GENinstance*,IFvalue*); extern int BSIM3v32pzLoad(GENmodel*,CKTcircuit*,SPcomplex*); @@ -35,3 +35,7 @@ extern int BSIM3v32bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM3v32bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM3v32bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM3v32nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim3v32/bsim3v32init.c b/src/spicelib/devices/bsim3v32/bsim3v32init.c index 8fb9c48e7..94a5fe8e5 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32init.c +++ b/src/spicelib/devices/bsim3v32/bsim3v32init.c @@ -52,7 +52,7 @@ SPICEdev BSIM3v32info = { /* DEVaccept */ NULL, /* DEVdestroy */ BSIM3v32destroy, /* DEVmodDelete */ BSIM3v32mDelete, - /* DEVdelete */ BSIM3v32delete, + /* DEVdelete */ BSIM3v32delete, /* DEVsetic */ BSIM3v32getic, /* DEVask */ BSIM3v32ask, /* DEVmodAsk */ BSIM3v32mAsk, @@ -69,15 +69,20 @@ SPICEdev BSIM3v32info = { #ifdef CIDER /* DEVdump */ NULL, /* DEVacct */ NULL, -#endif +#endif /* DEVinstSize */ &BSIM3v32iSize, /* DEVmodSize */ &BSIM3v32mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ BSIM3v32bindCSC, /* DEVbindCSCComplex */ BSIM3v32bindCSCComplex, /* DEVbindCSCComplexToReal */ BSIM3v32bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ BSIM3v32nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/bsim4/Makefile.am b/src/spicelib/devices/bsim4/Makefile.am index 7a8421f5e..07275cdf6 100644 --- a/src/spicelib/devices/bsim4/Makefile.am +++ b/src/spicelib/devices/bsim4/Makefile.am @@ -41,6 +41,10 @@ if UMFPACK_WANTED libbsim4_la_SOURCES += b4bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim4_la_SOURCES += b4node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim4/b4.c b/src/spicelib/devices/bsim4/b4.c index b48168e14..3353b2133 100644 --- a/src/spicelib/devices/bsim4/b4.c +++ b/src/spicelib/devices/bsim4/b4.c @@ -124,6 +124,7 @@ IOP( "rbodymod", BSIM4_MOD_RBODYMOD, IF_INTEGER, "Distributed body R model selec IOP( "rgatemod", BSIM4_MOD_RGATEMOD, IF_INTEGER, "Gate R model selector"), IOP( "permod", BSIM4_MOD_PERMOD, IF_INTEGER, "Pd and Ps model selector"), IOP( "geomod", BSIM4_MOD_GEOMOD, IF_INTEGER, "Geometry dependent parasitics model selector"), +IOP( "rgeomod", BSIM4_MOD_RGEOMOD, IF_INTEGER, "S/D resistance and contact model selector"), IOP( "fnoimod", BSIM4_MOD_FNOIMOD, IF_INTEGER, "Flicker noise model selector"), IOP( "tnoimod", BSIM4_MOD_TNOIMOD, IF_INTEGER, "Thermal noise model selector"), IOP( "mtrlmod", BSIM4_MOD_MTRLMOD, IF_INTEGER, "parameter for non-silicon substrate or metal gate selector"), diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index 73b1a6909..c5f513e3c 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -114,7 +114,7 @@ double geltd, gcrg, gcrgg, gcrgd, gcrgs, gcrgb, ceqgcrg; double vges, vgms, vgedo, vgmdo, vged, vgmd, delvged, delvgmd; double delvges, delvgms, vgmb; double gcgmgmb=0.0, gcgmdb=0.0, gcgmsb=0.0, gcdgmb, gcsgmb; -double gcgmbb=0.0, gcbgmb, qgmb, qgmid=0.0, ceqqgmid; +double gcgmbb=0.0, gcbgmb, qgmb, qgmid=0.0, ceqqgmid, ceqqgmid_fvk ; double vbd, vbs, vds, vgb, vgd, vgs, vgdo; #ifndef PREDICTOR @@ -126,8 +126,8 @@ double delvbd_jct, delvbs_jct, vbs_jct, vbd_jct; double SourceSatCurrent, DrainSatCurrent; double ag0, qgb, von, cbhat, VgstNVt, ExpVgst; -double ceqqb, ceqqd, ceqqg, ceqqjd=0.0, ceqqjs=0.0, ceq, geq; -double cdrain, cdhat, ceqdrn, ceqbd, ceqbs, ceqjd, ceqjs, gjbd, gjbs; +double ceqqb, ceqqb_fvk, ceqqd, ceqqd_fvk, ceqqg, ceqqg_fvk, ceqqjd=0.0, ceqqjd_fvk = 0.0, ceqqjs=0.0, ceqqjs_fvk = 0.0, ceq, geq; +double cdrain, cdhat, ceqdrn, ceqdrn_fvk, ceqbd, ceqbd_fvk, ceqbs, ceqbs_fvk, ceqjd, ceqjd_fvk, ceqjs, ceqjs_fvk, gjbd, gjbs; double czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; double delvbd, delvbs, delvds, delvgd, delvgs; double Vfbeff, dVfbeff_dVg, dVfbeff_dVb, V3, V4; @@ -148,10 +148,10 @@ double Igs, dIgs_dVg, dIgs_dVs, Igd, dIgd_dVg, dIgd_dVd; double Igbacc, dIgbacc_dVg, dIgbacc_dVb; double Igbinv, dIgbinv_dVg, dIgbinv_dVd, dIgbinv_dVb; double Pigcd, dPigcd_dVg, dPigcd_dVd, dPigcd_dVb; -double Istoteq, gIstotg, gIstotd, gIstots, gIstotb; -double Idtoteq, gIdtotg, gIdtotd, gIdtots, gIdtotb; -double Ibtoteq, gIbtotg, gIbtotd, gIbtots, gIbtotb; -double Igtoteq, gIgtotg, gIgtotd, gIgtots, gIgtotb; +double Istoteq, Istoteq_fvk, gIstotg, gIstotd, gIstots, gIstotb; +double Idtoteq, Idtoteq_fvk, gIdtotg, gIdtotd, gIdtots, gIdtotb; +double Ibtoteq, Ibtoteq_fvk, gIbtotg, gIbtotd, gIbtots, gIbtotb; +double Igtoteq, Igtoteq_fvk, gIgtotg, gIgtotd, gIgtots, gIgtotb; double Igstot, cgshat, Igdtot, cgdhat, Igbtot, cgbhat; double Vgs_eff, Vfb=0.0, Vth_NarrowW; /* double Vgd_eff, dVgd_eff_dVg; v4.7.0 */ @@ -216,7 +216,7 @@ double Rds, dRds_dVg, dRds_dVb, WVCox, WVCoxRds; double Vgst2Vtm, VdsatCV; double Leff, Weff, dWeff_dVg, dWeff_dVb; double AbulkCV, dAbulkCV_dVb; -double qcheq, qdef, gqdef=0.0, cqdef=0.0, cqcheq=0.0; +double qcheq, qdef, gqdef=0.0, cqdef=0.0, cqdef_fvk = 0.0, cqcheq=0.0, cqcheq_fvk = 0.0 ; double gcqdb=0.0, gcqsb=0.0, gcqgb=0.0, gcqbb=0.0; double dxpart, sxpart, ggtg, ggtd, ggts, ggtb; double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; @@ -4573,9 +4573,9 @@ line755: line850: /* Zero gcap and ceqcap if (!ChargeComputationNeeded) */ - ceqqg = ceqqb = ceqqd = 0.0; - ceqqjd = ceqqjs = 0.0; - cqcheq = cqdef = 0.0; + ceqqg = ceqqg_fvk = ceqqb = ceqqb_fvk = ceqqd = ceqqd_fvk = 0.0; + ceqqjd = ceqqjd_fvk = ceqqjs = ceqqjs_fvk = 0.0; + cqcheq = cqcheq_fvk = cqdef = cqdef_fvk = 0.0; gcdgb = gcddb = gcdsb = gcdbb = 0.0; gcsgb = gcsdb = gcssb = gcsbb = 0.0; @@ -4583,7 +4583,7 @@ line850: gcbdb = gcbgb = gcbsb = gcbbb = 0.0; gcgmgmb = gcgmdb = gcgmsb = gcgmbb = 0.0; - gcdgmb = gcsgmb = gcbgmb = ceqqgmid = 0.0; + gcdgmb = gcsgmb = gcbgmb = ceqqgmid = ceqqgmid_fvk = 0.0; gcdbdb = gcsbsb = 0.0; gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; @@ -4612,21 +4612,28 @@ line860: cqdrn = *(ckt->CKTstate0 + here->BSIM4cqd); ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs; + ceqqg_fvk = cqgate ; ceqqd = cqdrn - gcdgb * vgb - gcdgmb * vgmb + (gcddb + gcdbdb) * vbd - gcdbdb * vbd_jct + gcdsb * vbs; + ceqqd_fvk = cqdrn ; ceqqb = cqbody - gcbgb * vgb - gcbgmb * vgmb + gcbdb * vbd + gcbsb * vbs; - + ceqqb_fvk = cqbody ; if (here->BSIM4rgateMod == 3) + { ceqqgmid = *(ckt->CKTstate0 + here->BSIM4cqgmid) + gcgmdb * vbd + gcgmsb * vbs - gcgmgmb * vgmb; - else - ceqqgmid = 0.0; + ceqqgmid_fvk = *(ckt->CKTstate0 + here->BSIM4cqgmid) ; + } else { + ceqqgmid = ceqqgmid_fvk = 0.0; + } if (here->BSIM4rbodyMod) { ceqqjs = *(ckt->CKTstate0 + here->BSIM4cqbs) + gcsbsb * vbs_jct; - ceqqjd = *(ckt->CKTstate0 + here->BSIM4cqbd) + gcdbdb * vbd_jct; + ceqqjs_fvk = *(ckt->CKTstate0 + here->BSIM4cqbs) ; + ceqqjd = *(ckt->CKTstate0 + here->BSIM4cqbd) + gcdbdb * vbd_jct; + ceqqjd_fvk = *(ckt->CKTstate0 + here->BSIM4cqbd) ; } if (here->BSIM4trnqsMod) @@ -4636,8 +4643,10 @@ line860: ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd * vbd - ddxpart_dVs * vbs); cqdef = *(ckt->CKTstate0 + here->BSIM4cqcdump) - gqdef * qdef; + cqdef_fvk = *(ckt->CKTstate0 + here->BSIM4cqcdump) ; cqcheq = *(ckt->CKTstate0 + here->BSIM4cqcheq) - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0; + cqcheq_fvk = *(ckt->CKTstate0 + here->BSIM4cqcheq) ; } if (ckt->CKTmode & MODEINITTRAN) @@ -4674,13 +4683,15 @@ line900: ceqdrn = model->BSIM4type * (cdrain - here->BSIM4gds * vds - Gm * vgs - Gmbs * vbs); + ceqdrn_fvk = model->BSIM4type * cdrain ; ceqbd = model->BSIM4type * (here->BSIM4csub + here->BSIM4Igidl - (here->BSIM4gbds + here->BSIM4ggidld) * vds - (here->BSIM4gbgs + here->BSIM4ggidlg) * vgs - (here->BSIM4gbbs + here->BSIM4ggidlb) * vbs); + ceqbd_fvk = model->BSIM4type * (here->BSIM4csub + here->BSIM4Igidl) ; ceqbs = model->BSIM4type * (here->BSIM4Igisl + here->BSIM4ggisls * vds - here->BSIM4ggislg * vgd - here->BSIM4ggislb * vbd); - + ceqbs_fvk = model->BSIM4type * here->BSIM4Igisl ; gbbdp = -(here->BSIM4gbds); gbbsp = here->BSIM4gbds + here->BSIM4gbgs + here->BSIM4gbbs; @@ -4699,10 +4710,10 @@ line900: gIstotd = here->BSIM4gIgcsd; gIstots = here->BSIM4gIgss + here->BSIM4gIgcss; gIstotb = here->BSIM4gIgcsb; - Istoteq = model->BSIM4type * (here->BSIM4Igs + here->BSIM4Igcs + Istoteq = model->BSIM4type * (here->BSIM4Igs + here->BSIM4Igcs - gIstotg * vgs - here->BSIM4gIgcsd * vds - - here->BSIM4gIgcsb * vbs); - + - here->BSIM4gIgcsb * vbs); + Istoteq_fvk = model->BSIM4type * (here->BSIM4Igs + here->BSIM4Igcs) ; gIdtotg = here->BSIM4gIgdg + here->BSIM4gIgcdg; gIdtotd = here->BSIM4gIgdd + here->BSIM4gIgcdd; gIdtots = here->BSIM4gIgcds; @@ -4710,10 +4721,11 @@ line900: Idtoteq = model->BSIM4type * (here->BSIM4Igd + here->BSIM4Igcd - here->BSIM4gIgdg * vgd - here->BSIM4gIgcdg * vgs - here->BSIM4gIgcdd * vds - here->BSIM4gIgcdb * vbs); + Idtoteq_fvk = model->BSIM4type * (here->BSIM4Igd + here->BSIM4Igcd) ; } else - { gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0; - gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0; + { gIstotg = gIstotd = gIstots = gIstotb = Istoteq = Istoteq_fvk = 0.0; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = Idtoteq_fvk = 0.0; } if (model->BSIM4igbMod) @@ -4724,19 +4736,21 @@ line900: Ibtoteq = model->BSIM4type * (here->BSIM4Igb - here->BSIM4gIgbg * vgs - here->BSIM4gIgbd * vds - here->BSIM4gIgbb * vbs); + Ibtoteq_fvk = model->BSIM4type * here->BSIM4Igb ; } else - gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0; + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = Ibtoteq_fvk = 0.0; if ((model->BSIM4igcMod != 0) || (model->BSIM4igbMod != 0)) { gIgtotg = gIstotg + gIdtotg + gIbtotg; gIgtotd = gIstotd + gIdtotd + gIbtotd ; gIgtots = gIstots + gIdtots + gIbtots; gIgtotb = gIstotb + gIdtotb + gIbtotb; - Igtoteq = Istoteq + Idtoteq + Ibtoteq; + Igtoteq = Istoteq + Idtoteq + Ibtoteq; + Igtoteq_fvk = Istoteq_fvk + Idtoteq_fvk + Ibtoteq_fvk ; } else - gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = 0.0; + gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = Igtoteq_fvk = 0.0; if (here->BSIM4rgateMod == 2) @@ -4764,14 +4778,15 @@ line900: ceqdrn = -model->BSIM4type * (cdrain + here->BSIM4gds * vds + Gm * vgd + Gmbs * vbd); - + ceqdrn_fvk = -model->BSIM4type * cdrain ; ceqbs = model->BSIM4type * (here->BSIM4csub + here->BSIM4Igisl + (here->BSIM4gbds + here->BSIM4ggisls) * vds - (here->BSIM4gbgs + here->BSIM4ggislg) * vgd - (here->BSIM4gbbs + here->BSIM4ggislb) * vbd); + ceqbs_fvk = model->BSIM4type * (here->BSIM4csub + here->BSIM4Igisl) ; ceqbd = model->BSIM4type * (here->BSIM4Igidl - here->BSIM4ggidld * vds - here->BSIM4ggidlg * vgs - here->BSIM4ggidlb * vbs); - + ceqbd_fvk = model->BSIM4type * here->BSIM4Igidl ; gbbsp = -(here->BSIM4gbds); gbbdp = here->BSIM4gbds + here->BSIM4gbgs + here->BSIM4gbbs; @@ -4791,20 +4806,21 @@ line900: gIstots = here->BSIM4gIgss + here->BSIM4gIgcdd; gIstotb = here->BSIM4gIgcdb; Istoteq = model->BSIM4type * (here->BSIM4Igs + here->BSIM4Igcd - - here->BSIM4gIgsg * vgs - here->BSIM4gIgcdg * vgd - + here->BSIM4gIgcdd * vds - here->BSIM4gIgcdb * vbd); - + - here->BSIM4gIgsg * vgs - here->BSIM4gIgcdg * vgd + + here->BSIM4gIgcdd * vds - here->BSIM4gIgcdb * vbd); + Istoteq_fvk = model->BSIM4type * (here->BSIM4Igs + here->BSIM4Igcd) ; gIdtotg = here->BSIM4gIgdg + here->BSIM4gIgcsg; gIdtotd = here->BSIM4gIgdd + here->BSIM4gIgcss; gIdtots = here->BSIM4gIgcsd; gIdtotb = here->BSIM4gIgcsb; Idtoteq = model->BSIM4type * (here->BSIM4Igd + here->BSIM4Igcs - - (here->BSIM4gIgdg + here->BSIM4gIgcsg) * vgd - + here->BSIM4gIgcsd * vds - here->BSIM4gIgcsb * vbd); + - (here->BSIM4gIgdg + here->BSIM4gIgcsg) * vgd + + here->BSIM4gIgcsd * vds - here->BSIM4gIgcsb * vbd); + Idtoteq_fvk = model->BSIM4type * (here->BSIM4Igd + here->BSIM4Igcs) ; } else - { gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0; - gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0; + { gIstotg = gIstotd = gIstots = gIstotb = Istoteq = Istoteq_fvk = 0.0; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = Idtoteq_fvk = 0.0; } if (model->BSIM4igbMod) @@ -4813,11 +4829,12 @@ line900: gIbtots = here->BSIM4gIgbd; gIbtotb = here->BSIM4gIgbb; Ibtoteq = model->BSIM4type * (here->BSIM4Igb - - here->BSIM4gIgbg * vgd + here->BSIM4gIgbd * vds - - here->BSIM4gIgbb * vbd); + - here->BSIM4gIgbg * vgd + here->BSIM4gIgbd * vds + - here->BSIM4gIgbb * vbd); + Ibtoteq_fvk = model->BSIM4type * here->BSIM4Igb ; } else - gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0; + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = Ibtoteq_fvk = 0.0; if ((model->BSIM4igcMod != 0) || (model->BSIM4igbMod != 0)) { gIgtotg = gIstotg + gIdtotg + gIbtotg; @@ -4825,9 +4842,10 @@ line900: gIgtots = gIstots + gIdtots + gIbtots; gIgtotb = gIstotb + gIdtotb + gIbtotb; Igtoteq = Istoteq + Idtoteq + Ibtoteq; + Igtoteq_fvk = Istoteq_fvk + Idtoteq_fvk + Ibtoteq_fvk ; } else - gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = 0.0; + gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = Igtoteq_fvk = 0.0; if (here->BSIM4rgateMod == 2) @@ -4874,28 +4892,42 @@ line900: if (model->BSIM4type > 0) { ceqjs = (here->BSIM4cbs - here->BSIM4gbs * vbs_jct); + ceqjs_fvk = here->BSIM4cbs ; ceqjd = (here->BSIM4cbd - here->BSIM4gbd * vbd_jct); + ceqjd_fvk = here->BSIM4cbd ; } else - { ceqjs = -(here->BSIM4cbs - here->BSIM4gbs * vbs_jct); + { ceqjs = -(here->BSIM4cbs - here->BSIM4gbs * vbs_jct); + ceqjs_fvk = -here->BSIM4cbs ; ceqjd = -(here->BSIM4cbd - here->BSIM4gbd * vbd_jct); + ceqjd_fvk = -here->BSIM4cbd ; ceqqg = -ceqqg; + ceqqg_fvk = -ceqqg_fvk ; ceqqd = -ceqqd; + ceqqd_fvk = -ceqqd_fvk ; ceqqb = -ceqqb; + ceqqb_fvk = -ceqqb_fvk ; ceqgcrg = -ceqgcrg; if (here->BSIM4trnqsMod) { cqdef = -cqdef; + cqdef_fvk = -cqdef_fvk ; cqcheq = -cqcheq; + cqcheq_fvk = -cqcheq_fvk ; } if (here->BSIM4rbodyMod) { ceqqjs = -ceqqjs; + ceqqjs_fvk = -ceqqjs_fvk ; ceqqjd = -ceqqjd; + ceqqjd_fvk = -ceqqjd_fvk ; } if (here->BSIM4rgateMod == 3) + { ceqqgmid = -ceqqgmid; + ceqqgmid_fvk = -ceqqgmid_fvk ; + } } @@ -4937,37 +4969,35 @@ line900: if (here->BSIM4trnqsMod) here->BSIM4rhsq = m * (cqcheq - cqdef); #else - (*(ckt->CKTrhs + here->BSIM4dNodePrime) += m * (ceqjd - ceqbd + ceqgdtot - - ceqdrn - ceqqd + Idtoteq)); - (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= m * (ceqqg - ceqgcrg + Igtoteq)); + (*(ckt->CKTrhs + here->BSIM4dNodePrime) += m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq)); /* NO ceqgdtot in FVK */ + + (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= m * (ceqqg - ceqgcrg + Igtoteq)); /* NO ceqgcrg in FVK */ if (here->BSIM4rgateMod == 2) - (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= m * ceqgcrg); + (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= m * ceqgcrg); /* NO ceqgcrg in FVK */ else if (here->BSIM4rgateMod == 3) - (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= m * (ceqqgmid + ceqgcrg)); + (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= m * (ceqqgmid + ceqgcrg)); /* NO ceqgcrg in FVK */ if (!here->BSIM4rbodyMod) - { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqjd - - ceqjs - ceqqb + Ibtoteq)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs - + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq)); + { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq)); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq)); /* NO ceqgstot in FVK */ } - else { (*(ckt->CKTrhs + here->BSIM4dbNode) -= m * (ceqjd + ceqqjd)); (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqqb + Ibtoteq)); (*(ckt->CKTrhs + here->BSIM4sbNode) -= m * (ceqjs + ceqqjs)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqd - + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq)); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqd + + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq)); /* NO ceqgstot in FVK */ } if (model->BSIM4rdsMod) - { (*(ckt->CKTrhs + here->BSIM4dNode) -= m * ceqgdtot); - (*(ckt->CKTrhs + here->BSIM4sNode) += m * ceqgstot); + { (*(ckt->CKTrhs + here->BSIM4dNode) -= m * ceqgdtot); /* NO ceqgdtot in FVK */ + (*(ckt->CKTrhs + here->BSIM4sNode) += m * ceqgstot); /* NO ceqgstot in FVK */ } if (here->BSIM4trnqsMod) - *(ckt->CKTrhs + here->BSIM4qNode) += m * (cqcheq - cqdef); + (*(ckt->CKTrhs + here->BSIM4qNode) += m * (cqcheq - cqdef)); #endif /* @@ -5167,7 +5197,7 @@ line900: (*(here->BSIM4GEbpPtr) += m * gcrgb); (*(here->BSIM4GPgePtr) -= m * gcrg); - (*(here->BSIM4GPgpPtr) += m * (gcggb - gcrgg - ggtg + gIgtotg)); + (*(here->BSIM4GPgpPtr) += m * (gcggb - gcrgg - ggtg + gIgtotg)); (*(here->BSIM4GPdpPtr) += m * (gcgdb - gcrgd - ggtd + gIgtotd)); (*(here->BSIM4GPspPtr) += m * (gcgsb - gcrgs - ggts + gIgtots)); (*(here->BSIM4GPbpPtr) += m * (gcgbb - gcrgb - ggtb + gIgtotb)); @@ -5309,8 +5339,167 @@ line900: (*(here->BSIM4SPqPtr) += m * sxpart * here->BSIM4gtau); (*(here->BSIM4GPqPtr) -= m * here->BSIM4gtau); } + +#ifdef KIRCHHOFF + + /* KCL - Non-Linear and Dynamic Linear Parts */ + *(ckt->CKTfvk+here->BSIM4dNodePrime) -= m * (ceqjd_fvk - ceqbd_fvk - ceqdrn_fvk - ceqqd_fvk + Idtoteq_fvk) ; + *(here->KCLcurrentdNodePrimeRHS_1) = -(m * ceqjd_fvk) ; + *(here->KCLcurrentdNodePrimeRHS_2) = m * ceqbd_fvk ; + *(here->KCLcurrentdNodePrimeRHS_3) = m * ceqdrn_fvk ; + *(here->KCLcurrentdNodePrimeRHS_4) = m * ceqqd_fvk ; + *(here->KCLcurrentdNodePrimeRHS_5) = -(m * Idtoteq_fvk) ; + + *(ckt->CKTfvk+here->BSIM4gNodePrime) += m * (ceqqg_fvk + Igtoteq_fvk) ; + *(here->KCLcurrentgNodePrimeRHS_1) = m * ceqqg_fvk ; + *(here->KCLcurrentgNodePrimeRHS_2) = m * Igtoteq_fvk ; + + if (here->BSIM4rgateMod == 3) + { + *(ckt->CKTfvk+here->BSIM4gNodeMid) += m * ceqqgmid_fvk ; + *(here->KCLcurrentgNodeMidRHS) = m * ceqqgmid_fvk ; + } + + if (!here->BSIM4rbodyMod) + { + *(ckt->CKTfvk+here->BSIM4bNodePrime) -= m * (ceqbd_fvk + ceqbs_fvk - ceqjd_fvk - ceqjs_fvk - ceqqb_fvk + Ibtoteq_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_1) = -(m * ceqbd_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_2) = -(m * ceqbs_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_3) = m * ceqjd_fvk ; + *(here->KCLcurrentbNodePrimeRHS_4) = m * ceqjs_fvk ; + *(here->KCLcurrentbNodePrimeRHS_5) = m * ceqqb_fvk ; + *(here->KCLcurrentbNodePrimeRHS_6) = -(m * Ibtoteq_fvk) ; + + *(ckt->CKTfvk+here->BSIM4sNodePrime) -= m * (ceqdrn_fvk - ceqbs_fvk + ceqjs_fvk + + ceqqg_fvk + ceqqb_fvk + ceqqd_fvk + + ceqqgmid_fvk + Istoteq_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_1) = -(m * ceqdrn_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_2) = m * ceqbs_fvk ; + *(here->KCLcurrentsNodePrimeRHS_3) = -(m * ceqjs_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_4) = -(m * ceqqg_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_5) = -(m * ceqqb_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_6) = -(m * ceqqd_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_7) = -(m * ceqqgmid_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_8) = -(m * Istoteq_fvk) ; + } else { + *(ckt->CKTfvk+here->BSIM4dbNode) += m * (ceqjd_fvk + ceqqjd_fvk) ; + *(here->KCLcurrentdbNodeRHS_1) = m * ceqjd_fvk ; + *(here->KCLcurrentdbNodeRHS_2) = m * ceqqjd_fvk ; + + *(ckt->CKTfvk+here->BSIM4bNodePrime) -= m * (ceqbd_fvk + ceqbs_fvk - ceqqb_fvk + Ibtoteq_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_1) = -(m * ceqbd_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_2) = -(m * ceqbs_fvk) ; + *(here->KCLcurrentbNodePrimeRHS_3) = m * ceqqb_fvk ; + *(here->KCLcurrentbNodePrimeRHS_4) = -(m * Ibtoteq_fvk) ; + + *(ckt->CKTfvk+here->BSIM4sbNode) += m * (ceqjs_fvk + ceqqjs_fvk) ; + *(here->KCLcurrentsbNodeRHS_1) = m * ceqjs_fvk ; + *(here->KCLcurrentsbNodeRHS_2) = m * ceqqjs_fvk ; + + *(ckt->CKTfvk+here->BSIM4sNodePrime) -= m * (ceqdrn_fvk - ceqbs_fvk + ceqjs_fvk + ceqqd_fvk + + ceqqg_fvk + ceqqb_fvk + ceqqjd_fvk + ceqqjs_fvk + + ceqqgmid_fvk + Istoteq_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_1) = -(m * ceqdrn_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_2) = m * ceqbs_fvk ; + *(here->KCLcurrentsNodePrimeRHS_3) = -(m * ceqjs_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_4) = -(m * ceqqd_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_5) = -(m * ceqqg_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_6) = -(m * ceqqb_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_7) = -(m * ceqqjd_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_8) = -(m * ceqqjs_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_9) = -(m * ceqqgmid_fvk) ; + *(here->KCLcurrentsNodePrimeRHS_10) = -(m * Istoteq_fvk) ; + } + + if (here->BSIM4trnqsMod) + { + *(ckt->CKTfvk+here->BSIM4qNode) -= m * (cqcheq_fvk - cqdef_fvk) ; + *(here->KCLcurrentqNodeRHS_1) = -(m * cqcheq_fvk) ; + *(here->KCLcurrentqNodeRHS_2) = m * cqdef_fvk ; + } + + + /* KCL - Static Linear Part */ + *(ckt->CKTfvk+here->BSIM4dNodePrime) += m * (gdpr + gdtot) * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode)) ; + *(here->KCLcurrentdNodePrime_1) = m * gdpr * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode)) ; + *(here->KCLcurrentdNodePrime_2) = m * gdtot * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode)) ; + + *(ckt->CKTfvk+here->BSIM4dNode) -= m * (gdpr + gdtot) * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode)) ; + *(here->KCLcurrentdNode_1) = -(m * gdpr * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode))) ; + *(here->KCLcurrentdNode_2) = -(m * gdtot * (*(ckt->CKTrhsOld+here->BSIM4dNodePrime) - *(ckt->CKTrhsOld+here->BSIM4dNode))) ; + + *(ckt->CKTfvk+here->BSIM4sNodePrime) += m * (gspr + gstot) * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode)) ; + *(here->KCLcurrentsNodePrime_1) = m * gspr * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode)) ; + *(here->KCLcurrentsNodePrime_2) = m * gstot * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode)) ; + + *(ckt->CKTfvk+here->BSIM4sNode) -= m * (gspr + gstot) * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode)) ; + *(here->KCLcurrentsNode_1) = -(m * gspr * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode))) ; + *(here->KCLcurrentsNode_2) = -(m * gstot * (*(ckt->CKTrhsOld+here->BSIM4sNodePrime) - *(ckt->CKTrhsOld+here->BSIM4sNode))) ; + + if (here->BSIM4rgateMod == 1) + { + *(ckt->CKTfvk+here->BSIM4gNodeExt) += m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodeExt) = m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4gNodePrime) -= m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodePrime) = -(m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime))) ; + } else if (here->BSIM4rgateMod == 2) { + *(ckt->CKTfvk+here->BSIM4gNodeExt) += m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodeExt) = m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4gNodePrime) -= m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodePrime) = -(m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime))) ; + } else if (here->BSIM4rgateMod == 3) { + *(ckt->CKTfvk+here->BSIM4gNodeExt) += m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodeMid)) ; + *(here->KCLcurrentgNodeExt) = m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodeMid)) ; + + *(ckt->CKTfvk+here->BSIM4gNodeMid) -= m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodeMid)) ; + *(here->KCLcurrentgNodeMid_1) = -(m * geltd * (*(ckt->CKTrhsOld+here->BSIM4gNodeExt) - *(ckt->CKTrhsOld+here->BSIM4gNodeMid))) ; + + *(ckt->CKTfvk+here->BSIM4gNodeMid) += m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeMid) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodeMid_2) = m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeMid) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4gNodePrime) -= m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeMid) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime)) ; + *(here->KCLcurrentgNodePrime) = -(m * gcrg * (*(ckt->CKTrhsOld+here->BSIM4gNodeMid) - *(ckt->CKTrhsOld+here->BSIM4gNodePrime))) ; + } + + if (here->BSIM4rbodyMod) + { + *(ckt->CKTfvk+here->BSIM4dbNode) += m * here->BSIM4grbpd * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentdbNode_1) = m * here->BSIM4grbpd * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4bNodePrime) -= m * here->BSIM4grbpd * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentbNodePrime_1) = -(m * here->BSIM4grbpd * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime))) ; + + *(ckt->CKTfvk+here->BSIM4dbNode) += m * here->BSIM4grbdb * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + *(here->KCLcurrentdbNode_2) = m * here->BSIM4grbdb * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + + *(ckt->CKTfvk+here->BSIM4bNode) -= m * here->BSIM4grbdb * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + *(here->KCLcurrentbNode_1) = -(m * here->BSIM4grbdb * (*(ckt->CKTrhsOld+here->BSIM4dbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode))) ; + + *(ckt->CKTfvk+here->BSIM4bNode) += m * here->BSIM4grbpb * (*(ckt->CKTrhsOld+here->BSIM4bNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentbNode_2) = m * here->BSIM4grbpb * (*(ckt->CKTrhsOld+here->BSIM4bNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4bNodePrime) -= m * here->BSIM4grbpb * (*(ckt->CKTrhsOld+here->BSIM4bNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentbNodePrime_2) = -(m * here->BSIM4grbpb * (*(ckt->CKTrhsOld+here->BSIM4bNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime))) ; + + *(ckt->CKTfvk+here->BSIM4sbNode) += m * here->BSIM4grbps * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentsbNode_1) = m * here->BSIM4grbps * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + + *(ckt->CKTfvk+here->BSIM4bNodePrime) -= m * here->BSIM4grbps * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime)) ; + *(here->KCLcurrentbNodePrime_3) = -(m * here->BSIM4grbps * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNodePrime))) ; + + *(ckt->CKTfvk+here->BSIM4sbNode) += m * here->BSIM4grbsb * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + *(here->KCLcurrentsbNode_2) = m * here->BSIM4grbsb * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + + *(ckt->CKTfvk+here->BSIM4bNode) -= m * here->BSIM4grbsb * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode)) ; + *(here->KCLcurrentbNode_3) = -(m * here->BSIM4grbsb * (*(ckt->CKTrhsOld+here->BSIM4sbNode) - *(ckt->CKTrhsOld+here->BSIM4bNode))) ; + } + +/////////////////////////////////////////// #endif +#endif line1000: ; #ifndef USE_OMP diff --git a/src/spicelib/devices/bsim4/b4mask.c b/src/spicelib/devices/bsim4/b4mask.c index 52fcd9a96..4b2487834 100644 --- a/src/spicelib/devices/bsim4/b4mask.c +++ b/src/spicelib/devices/bsim4/b4mask.c @@ -84,6 +84,9 @@ IFvalue *value) case BSIM4_MOD_GEOMOD : value->iValue = model->BSIM4geoMod; return(OK); + case BSIM4_MOD_RGEOMOD : + value->iValue = model->BSIM4rgeoMod; + return(OK); case BSIM4_MOD_MTRLMOD : value->iValue = model->BSIM4mtrlMod; return(OK); diff --git a/src/spicelib/devices/bsim4/b4mpar.c b/src/spicelib/devices/bsim4/b4mpar.c index bcf8d6cf8..ca3578a3c 100644 --- a/src/spicelib/devices/bsim4/b4mpar.c +++ b/src/spicelib/devices/bsim4/b4mpar.c @@ -88,6 +88,10 @@ GENmodel *inMod) mod->BSIM4geoMod = value->iValue; mod->BSIM4geoModGiven = TRUE; break; + case BSIM4_MOD_RGEOMOD : + mod->BSIM4rgeoMod = value->iValue; + mod->BSIM4rgeoModGiven = TRUE; + break; case BSIM4_MOD_FNOIMOD : mod->BSIM4fnoiMod = value->iValue; mod->BSIM4fnoiModGiven = TRUE; diff --git a/src/spicelib/devices/bsim4/b4node.c b/src/spicelib/devices/bsim4/b4node.c new file mode 100644 index 000000000..b131d22e1 --- /dev/null +++ b/src/spicelib/devices/bsim4/b4node.c @@ -0,0 +1,173 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim4def.h" +#include "ngspice/sperror.h" + +int +BSIM4nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM4model *model = (BSIM4model *)inModel ; + BSIM4instance *here ; + int error ; + + /* loop through all the BSIM4 models */ + for ( ; model != NULL ; model = model->BSIM4nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4instances ; here != NULL ; here = here->BSIM4nextInstance) + { + +#ifdef STEPDEBUG + fprintf (stderr, "here->BSIM4dNodePrime: %d\n", here->BSIM4dNodePrime) ; + fprintf (stderr, "here->BSIM4sNodePrime: %d\n", here->BSIM4sNodePrime) ; + fprintf (stderr, "here->BSIM4gNodePrime: %d\n", here->BSIM4gNodePrime) ; + fprintf (stderr, "here->BSIM4bNodePrime: %d\n", here->BSIM4bNodePrime) ; + fprintf (stderr, "here->BSIM4dNode: %d\n", here->BSIM4dNode) ; + fprintf (stderr, "here->BSIM4sNode: %d\n", here->BSIM4sNode) ; + fprintf (stderr, "here->BSIM4gNodeExt: %d\n", here->BSIM4gNodeExt) ; + fprintf (stderr, "here->BSIM4bNode: %d\n", here->BSIM4bNode) ; + fprintf (stderr, "here->BSIM4dbNode: %d\n", here->BSIM4dbNode) ; + fprintf (stderr, "here->BSIM4sbNode: %d\n", here->BSIM4sbNode) ; + fprintf (stderr, "here->BSIM4gNodeMid: %d\n", here->BSIM4gNodeMid) ; + fprintf (stderr, "here->BSIM4qNode: %d\n", here->BSIM4qNode) ; +#endif + + ckt->CKTnodeIsLinear [here->BSIM4dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4gNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4bNodePrime] = 0 ; + + if (here->BSIM4rgateMod == 2) + { + ckt->CKTnodeIsLinear [here->BSIM4gNodeExt] = 0 ; + } else if (here->BSIM4rgateMod == 3) { + ckt->CKTnodeIsLinear [here->BSIM4gNodeMid] = 0 ; + } + + if (here->BSIM4rbodyMod) + { + ckt->CKTnodeIsLinear [here->BSIM4dbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4sbNode] = 0 ; + } + + if (model->BSIM4rdsMod) + { + ckt->CKTnodeIsLinear [here->BSIM4dNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4sNode] = 0 ; + } + + if (here->BSIM4trnqsMod) + { + ckt->CKTnodeIsLinear [here->BSIM4qNode] = 0 ; + } + + + /* KCL - Non-Linear and Dynamic Linear Parts */ + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrimeRHS_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrimeRHS_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrimeRHS_4)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrimeRHS_5)) ; + + error = CKTmkCurKCL (ckt, here->BSIM4gNodePrime, &(here->KCLcurrentgNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodePrime, &(here->KCLcurrentgNodePrimeRHS_2)) ; + + if (here->BSIM4rgateMod == 3) + { + error = CKTmkCurKCL (ckt, here->BSIM4gNodeMid, &(here->KCLcurrentgNodeMidRHS)) ; + } + + if (!here->BSIM4rbodyMod) + { + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_4)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_5)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_6)) ; + + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_4)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_5)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_6)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_7)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_8)) ; + } else { + error = CKTmkCurKCL (ckt, here->BSIM4dbNode, &(here->KCLcurrentdbNodeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dbNode, &(here->KCLcurrentdbNodeRHS_2)) ; + + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrimeRHS_4)) ; + + error = CKTmkCurKCL (ckt, here->BSIM4sbNode, &(here->KCLcurrentsbNodeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sbNode, &(here->KCLcurrentsbNodeRHS_2)) ; + + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_4)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_5)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_6)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_7)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_8)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_9)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrimeRHS_10)) ; + } + + if (here->BSIM4trnqsMod) + { + error = CKTmkCurKCL (ckt, here->BSIM4qNode, &(here->KCLcurrentqNodeRHS_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4qNode, &(here->KCLcurrentqNodeRHS_2)) ; + } + + + /* KCL - Static Linear Part */ + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrime_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNodePrime, &(here->KCLcurrentdNodePrime_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNode, &(here->KCLcurrentdNode_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dNode, &(here->KCLcurrentdNode_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrime_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNodePrime, &(here->KCLcurrentsNodePrime_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNode, &(here->KCLcurrentsNode_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sNode, &(here->KCLcurrentsNode_2)) ; + + if (here->BSIM4rgateMod == 1) + { + error = CKTmkCurKCL (ckt, here->BSIM4gNodeExt, &(here->KCLcurrentgNodeExt)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodePrime, &(here->KCLcurrentgNodePrime)) ; + } else if (here->BSIM4rgateMod == 2) { + error = CKTmkCurKCL (ckt, here->BSIM4gNodeExt, &(here->KCLcurrentgNodeExt)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodePrime, &(here->KCLcurrentgNodePrime)) ; + } else if (here->BSIM4rgateMod == 3) { + error = CKTmkCurKCL (ckt, here->BSIM4gNodeExt, &(here->KCLcurrentgNodeExt)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodeMid, &(here->KCLcurrentgNodeMid_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodeMid, &(here->KCLcurrentgNodeMid_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4gNodePrime, &(here->KCLcurrentgNodePrime)) ; + } + + if (here->BSIM4rbodyMod) + { + error = CKTmkCurKCL (ckt, here->BSIM4dbNode, &(here->KCLcurrentdbNode_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4dbNode, &(here->KCLcurrentdbNode_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrime_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrime_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNodePrime, &(here->KCLcurrentbNodePrime_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNode, &(here->KCLcurrentbNode_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNode, &(here->KCLcurrentbNode_2)) ; + error = CKTmkCurKCL (ckt, here->BSIM4bNode, &(here->KCLcurrentbNode_3)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sbNode, &(here->KCLcurrentsbNode_1)) ; + error = CKTmkCurKCL (ckt, here->BSIM4sbNode, &(here->KCLcurrentsbNode_2)) ; + } + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 2c58e9693..20e935efb 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -139,6 +139,12 @@ BSIM4instance **InstArray; if (!model->BSIM4geoModGiven) model->BSIM4geoMod = 0; + if (!model->BSIM4rgeoModGiven) + model->BSIM4rgeoMod = 0; + else if ((model->BSIM4rgeoMod != 0) && (model->BSIM4rgeoMod != 1)) + { model->BSIM4rgeoMod = 1; + printf("Warning: rgeoMod has been set to its default value: 1.\n"); + } if (!model->BSIM4fnoiModGiven) model->BSIM4fnoiMod = 1; else if ((model->BSIM4fnoiMod != 0) && (model->BSIM4fnoiMod != 1)) @@ -2250,8 +2256,15 @@ BSIM4instance **InstArray; if (!here->BSIM4geoModGiven) here->BSIM4geoMod = model->BSIM4geoMod; + if (!here->BSIM4rgeoModGiven) - here->BSIM4rgeoMod = 0; + here->BSIM4rgeoMod = model->BSIM4rgeoMod; + else if ((here->BSIM4rgeoMod != 0) && (here->BSIM4rgeoMod != 1)) + { here->BSIM4rgeoMod = model->BSIM4rgeoMod; + printf("Warning: rgeoMod has been set to its global value %d.\n", + model->BSIM4rgeoMod); + } + if (!here->BSIM4trnqsModGiven) here->BSIM4trnqsMod = model->BSIM4trnqsMod; else if ((here->BSIM4trnqsMod != 0) && (here->BSIM4trnqsMod != 1)) @@ -2450,96 +2463,96 @@ BSIM4instance **InstArray; /* set Sparse Matrix Pointers * macro to make elements with built-in out-of-memory test */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ +do { if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM4DPbpPtr, BSIM4dNodePrime, BSIM4bNodePrime) - TSTALLOC(BSIM4GPbpPtr, BSIM4gNodePrime, BSIM4bNodePrime) - TSTALLOC(BSIM4SPbpPtr, BSIM4sNodePrime, BSIM4bNodePrime) + TSTALLOC(BSIM4DPbpPtr, BSIM4dNodePrime, BSIM4bNodePrime); + TSTALLOC(BSIM4GPbpPtr, BSIM4gNodePrime, BSIM4bNodePrime); + TSTALLOC(BSIM4SPbpPtr, BSIM4sNodePrime, BSIM4bNodePrime); - TSTALLOC(BSIM4BPdpPtr, BSIM4bNodePrime, BSIM4dNodePrime) - TSTALLOC(BSIM4BPgpPtr, BSIM4bNodePrime, BSIM4gNodePrime) - TSTALLOC(BSIM4BPspPtr, BSIM4bNodePrime, BSIM4sNodePrime) - TSTALLOC(BSIM4BPbpPtr, BSIM4bNodePrime, BSIM4bNodePrime) + TSTALLOC(BSIM4BPdpPtr, BSIM4bNodePrime, BSIM4dNodePrime); + TSTALLOC(BSIM4BPgpPtr, BSIM4bNodePrime, BSIM4gNodePrime); + TSTALLOC(BSIM4BPspPtr, BSIM4bNodePrime, BSIM4sNodePrime); + TSTALLOC(BSIM4BPbpPtr, BSIM4bNodePrime, BSIM4bNodePrime); - TSTALLOC(BSIM4DdPtr, BSIM4dNode, BSIM4dNode) - TSTALLOC(BSIM4GPgpPtr, BSIM4gNodePrime, BSIM4gNodePrime) - TSTALLOC(BSIM4SsPtr, BSIM4sNode, BSIM4sNode) - TSTALLOC(BSIM4DPdpPtr, BSIM4dNodePrime, BSIM4dNodePrime) - TSTALLOC(BSIM4SPspPtr, BSIM4sNodePrime, BSIM4sNodePrime) - TSTALLOC(BSIM4DdpPtr, BSIM4dNode, BSIM4dNodePrime) - TSTALLOC(BSIM4GPdpPtr, BSIM4gNodePrime, BSIM4dNodePrime) - TSTALLOC(BSIM4GPspPtr, BSIM4gNodePrime, BSIM4sNodePrime) - TSTALLOC(BSIM4SspPtr, BSIM4sNode, BSIM4sNodePrime) - TSTALLOC(BSIM4DPspPtr, BSIM4dNodePrime, BSIM4sNodePrime) - TSTALLOC(BSIM4DPdPtr, BSIM4dNodePrime, BSIM4dNode) - TSTALLOC(BSIM4DPgpPtr, BSIM4dNodePrime, BSIM4gNodePrime) - TSTALLOC(BSIM4SPgpPtr, BSIM4sNodePrime, BSIM4gNodePrime) - TSTALLOC(BSIM4SPsPtr, BSIM4sNodePrime, BSIM4sNode) - TSTALLOC(BSIM4SPdpPtr, BSIM4sNodePrime, BSIM4dNodePrime) + TSTALLOC(BSIM4DdPtr, BSIM4dNode, BSIM4dNode); + TSTALLOC(BSIM4GPgpPtr, BSIM4gNodePrime, BSIM4gNodePrime); + TSTALLOC(BSIM4SsPtr, BSIM4sNode, BSIM4sNode); + TSTALLOC(BSIM4DPdpPtr, BSIM4dNodePrime, BSIM4dNodePrime); + TSTALLOC(BSIM4SPspPtr, BSIM4sNodePrime, BSIM4sNodePrime); + TSTALLOC(BSIM4DdpPtr, BSIM4dNode, BSIM4dNodePrime); + TSTALLOC(BSIM4GPdpPtr, BSIM4gNodePrime, BSIM4dNodePrime); + TSTALLOC(BSIM4GPspPtr, BSIM4gNodePrime, BSIM4sNodePrime); + TSTALLOC(BSIM4SspPtr, BSIM4sNode, BSIM4sNodePrime); + TSTALLOC(BSIM4DPspPtr, BSIM4dNodePrime, BSIM4sNodePrime); + TSTALLOC(BSIM4DPdPtr, BSIM4dNodePrime, BSIM4dNode); + TSTALLOC(BSIM4DPgpPtr, BSIM4dNodePrime, BSIM4gNodePrime); + TSTALLOC(BSIM4SPgpPtr, BSIM4sNodePrime, BSIM4gNodePrime); + TSTALLOC(BSIM4SPsPtr, BSIM4sNodePrime, BSIM4sNode); + TSTALLOC(BSIM4SPdpPtr, BSIM4sNodePrime, BSIM4dNodePrime); - TSTALLOC(BSIM4QqPtr, BSIM4qNode, BSIM4qNode) - TSTALLOC(BSIM4QbpPtr, BSIM4qNode, BSIM4bNodePrime) - TSTALLOC(BSIM4QdpPtr, BSIM4qNode, BSIM4dNodePrime) - TSTALLOC(BSIM4QspPtr, BSIM4qNode, BSIM4sNodePrime) - TSTALLOC(BSIM4QgpPtr, BSIM4qNode, BSIM4gNodePrime) - TSTALLOC(BSIM4DPqPtr, BSIM4dNodePrime, BSIM4qNode) - TSTALLOC(BSIM4SPqPtr, BSIM4sNodePrime, BSIM4qNode) - TSTALLOC(BSIM4GPqPtr, BSIM4gNodePrime, BSIM4qNode) + TSTALLOC(BSIM4QqPtr, BSIM4qNode, BSIM4qNode); + TSTALLOC(BSIM4QbpPtr, BSIM4qNode, BSIM4bNodePrime) ; + TSTALLOC(BSIM4QdpPtr, BSIM4qNode, BSIM4dNodePrime); + TSTALLOC(BSIM4QspPtr, BSIM4qNode, BSIM4sNodePrime); + TSTALLOC(BSIM4QgpPtr, BSIM4qNode, BSIM4gNodePrime); + TSTALLOC(BSIM4DPqPtr, BSIM4dNodePrime, BSIM4qNode); + TSTALLOC(BSIM4SPqPtr, BSIM4sNodePrime, BSIM4qNode); + TSTALLOC(BSIM4GPqPtr, BSIM4gNodePrime, BSIM4qNode); if (here->BSIM4rgateMod != 0) - { TSTALLOC(BSIM4GEgePtr, BSIM4gNodeExt, BSIM4gNodeExt) - TSTALLOC(BSIM4GEgpPtr, BSIM4gNodeExt, BSIM4gNodePrime) - TSTALLOC(BSIM4GPgePtr, BSIM4gNodePrime, BSIM4gNodeExt) - TSTALLOC(BSIM4GEdpPtr, BSIM4gNodeExt, BSIM4dNodePrime) - TSTALLOC(BSIM4GEspPtr, BSIM4gNodeExt, BSIM4sNodePrime) - TSTALLOC(BSIM4GEbpPtr, BSIM4gNodeExt, BSIM4bNodePrime) + { TSTALLOC(BSIM4GEgePtr, BSIM4gNodeExt, BSIM4gNodeExt); + TSTALLOC(BSIM4GEgpPtr, BSIM4gNodeExt, BSIM4gNodePrime); + TSTALLOC(BSIM4GPgePtr, BSIM4gNodePrime, BSIM4gNodeExt); + TSTALLOC(BSIM4GEdpPtr, BSIM4gNodeExt, BSIM4dNodePrime); + TSTALLOC(BSIM4GEspPtr, BSIM4gNodeExt, BSIM4sNodePrime); + TSTALLOC(BSIM4GEbpPtr, BSIM4gNodeExt, BSIM4bNodePrime); - TSTALLOC(BSIM4GMdpPtr, BSIM4gNodeMid, BSIM4dNodePrime) - TSTALLOC(BSIM4GMgpPtr, BSIM4gNodeMid, BSIM4gNodePrime) - TSTALLOC(BSIM4GMgmPtr, BSIM4gNodeMid, BSIM4gNodeMid) - TSTALLOC(BSIM4GMgePtr, BSIM4gNodeMid, BSIM4gNodeExt) - TSTALLOC(BSIM4GMspPtr, BSIM4gNodeMid, BSIM4sNodePrime) - TSTALLOC(BSIM4GMbpPtr, BSIM4gNodeMid, BSIM4bNodePrime) - TSTALLOC(BSIM4DPgmPtr, BSIM4dNodePrime, BSIM4gNodeMid) - TSTALLOC(BSIM4GPgmPtr, BSIM4gNodePrime, BSIM4gNodeMid) - TSTALLOC(BSIM4GEgmPtr, BSIM4gNodeExt, BSIM4gNodeMid) - TSTALLOC(BSIM4SPgmPtr, BSIM4sNodePrime, BSIM4gNodeMid) - TSTALLOC(BSIM4BPgmPtr, BSIM4bNodePrime, BSIM4gNodeMid) + TSTALLOC(BSIM4GMdpPtr, BSIM4gNodeMid, BSIM4dNodePrime); + TSTALLOC(BSIM4GMgpPtr, BSIM4gNodeMid, BSIM4gNodePrime); + TSTALLOC(BSIM4GMgmPtr, BSIM4gNodeMid, BSIM4gNodeMid); + TSTALLOC(BSIM4GMgePtr, BSIM4gNodeMid, BSIM4gNodeExt); + TSTALLOC(BSIM4GMspPtr, BSIM4gNodeMid, BSIM4sNodePrime); + TSTALLOC(BSIM4GMbpPtr, BSIM4gNodeMid, BSIM4bNodePrime); + TSTALLOC(BSIM4DPgmPtr, BSIM4dNodePrime, BSIM4gNodeMid); + TSTALLOC(BSIM4GPgmPtr, BSIM4gNodePrime, BSIM4gNodeMid); + TSTALLOC(BSIM4GEgmPtr, BSIM4gNodeExt, BSIM4gNodeMid); + TSTALLOC(BSIM4SPgmPtr, BSIM4sNodePrime, BSIM4gNodeMid); + TSTALLOC(BSIM4BPgmPtr, BSIM4bNodePrime, BSIM4gNodeMid); } if ((here->BSIM4rbodyMod ==1) || (here->BSIM4rbodyMod ==2)) - { TSTALLOC(BSIM4DPdbPtr, BSIM4dNodePrime, BSIM4dbNode) - TSTALLOC(BSIM4SPsbPtr, BSIM4sNodePrime, BSIM4sbNode) + { TSTALLOC(BSIM4DPdbPtr, BSIM4dNodePrime, BSIM4dbNode); + TSTALLOC(BSIM4SPsbPtr, BSIM4sNodePrime, BSIM4sbNode); - TSTALLOC(BSIM4DBdpPtr, BSIM4dbNode, BSIM4dNodePrime) - TSTALLOC(BSIM4DBdbPtr, BSIM4dbNode, BSIM4dbNode) - TSTALLOC(BSIM4DBbpPtr, BSIM4dbNode, BSIM4bNodePrime) - TSTALLOC(BSIM4DBbPtr, BSIM4dbNode, BSIM4bNode) + TSTALLOC(BSIM4DBdpPtr, BSIM4dbNode, BSIM4dNodePrime); + TSTALLOC(BSIM4DBdbPtr, BSIM4dbNode, BSIM4dbNode); + TSTALLOC(BSIM4DBbpPtr, BSIM4dbNode, BSIM4bNodePrime); + TSTALLOC(BSIM4DBbPtr, BSIM4dbNode, BSIM4bNode); - TSTALLOC(BSIM4BPdbPtr, BSIM4bNodePrime, BSIM4dbNode) - TSTALLOC(BSIM4BPbPtr, BSIM4bNodePrime, BSIM4bNode) - TSTALLOC(BSIM4BPsbPtr, BSIM4bNodePrime, BSIM4sbNode) + TSTALLOC(BSIM4BPdbPtr, BSIM4bNodePrime, BSIM4dbNode); + TSTALLOC(BSIM4BPbPtr, BSIM4bNodePrime, BSIM4bNode); + TSTALLOC(BSIM4BPsbPtr, BSIM4bNodePrime, BSIM4sbNode); - TSTALLOC(BSIM4SBspPtr, BSIM4sbNode, BSIM4sNodePrime) - TSTALLOC(BSIM4SBbpPtr, BSIM4sbNode, BSIM4bNodePrime) - TSTALLOC(BSIM4SBbPtr, BSIM4sbNode, BSIM4bNode) - TSTALLOC(BSIM4SBsbPtr, BSIM4sbNode, BSIM4sbNode) + TSTALLOC(BSIM4SBspPtr, BSIM4sbNode, BSIM4sNodePrime); + TSTALLOC(BSIM4SBbpPtr, BSIM4sbNode, BSIM4bNodePrime); + TSTALLOC(BSIM4SBbPtr, BSIM4sbNode, BSIM4bNode); + TSTALLOC(BSIM4SBsbPtr, BSIM4sbNode, BSIM4sbNode); - TSTALLOC(BSIM4BdbPtr, BSIM4bNode, BSIM4dbNode) - TSTALLOC(BSIM4BbpPtr, BSIM4bNode, BSIM4bNodePrime) - TSTALLOC(BSIM4BsbPtr, BSIM4bNode, BSIM4sbNode) - TSTALLOC(BSIM4BbPtr, BSIM4bNode, BSIM4bNode) + TSTALLOC(BSIM4BdbPtr, BSIM4bNode, BSIM4dbNode); + TSTALLOC(BSIM4BbpPtr, BSIM4bNode, BSIM4bNodePrime); + TSTALLOC(BSIM4BsbPtr, BSIM4bNode, BSIM4sbNode); + TSTALLOC(BSIM4BbPtr, BSIM4bNode, BSIM4bNode); } if (model->BSIM4rdsMod) - { TSTALLOC(BSIM4DgpPtr, BSIM4dNode, BSIM4gNodePrime) - TSTALLOC(BSIM4DspPtr, BSIM4dNode, BSIM4sNodePrime) - TSTALLOC(BSIM4DbpPtr, BSIM4dNode, BSIM4bNodePrime) - TSTALLOC(BSIM4SdpPtr, BSIM4sNode, BSIM4dNodePrime) - TSTALLOC(BSIM4SgpPtr, BSIM4sNode, BSIM4gNodePrime) - TSTALLOC(BSIM4SbpPtr, BSIM4sNode, BSIM4bNodePrime) + { TSTALLOC(BSIM4DgpPtr, BSIM4dNode, BSIM4gNodePrime); + TSTALLOC(BSIM4DspPtr, BSIM4dNode, BSIM4sNodePrime); + TSTALLOC(BSIM4DbpPtr, BSIM4dNode, BSIM4bNodePrime); + TSTALLOC(BSIM4SdpPtr, BSIM4sNode, BSIM4dNodePrime); + TSTALLOC(BSIM4SgpPtr, BSIM4sNode, BSIM4gNodePrime); + TSTALLOC(BSIM4SbpPtr, BSIM4sNode, BSIM4bNodePrime); } } } diff --git a/src/spicelib/devices/bsim4/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index 17cfa335f..8b4ed6a4b 100644 --- a/src/spicelib/devices/bsim4/bsim4def.h +++ b/src/spicelib/devices/bsim4/bsim4def.h @@ -642,6 +642,87 @@ typedef struct sBSIM4instance BindElement *BSIM4SbpStructPtr ; #endif +#ifdef KIRCHHOFF +//RHS + double *KCLcurrentdNodePrimeRHS_1 ; + double *KCLcurrentdNodePrimeRHS_2 ; + double *KCLcurrentdNodePrimeRHS_3 ; + double *KCLcurrentdNodePrimeRHS_4 ; + double *KCLcurrentdNodePrimeRHS_5 ; + double *KCLcurrentdNodePrimeRHS_6 ; + + double *KCLcurrentgNodePrimeRHS_1 ; + double *KCLcurrentgNodePrimeRHS_2 ; + + double *KCLcurrentgNodeMidRHS ; + + double *KCLcurrentbNodePrimeRHS_1 ; + double *KCLcurrentbNodePrimeRHS_2 ; + double *KCLcurrentbNodePrimeRHS_3 ; + double *KCLcurrentbNodePrimeRHS_4 ; + double *KCLcurrentbNodePrimeRHS_5 ; + double *KCLcurrentbNodePrimeRHS_6 ; + + double *KCLcurrentsNodePrimeRHS_1 ; + double *KCLcurrentsNodePrimeRHS_2 ; + double *KCLcurrentsNodePrimeRHS_3 ; + double *KCLcurrentsNodePrimeRHS_4 ; + double *KCLcurrentsNodePrimeRHS_5 ; + double *KCLcurrentsNodePrimeRHS_6 ; + double *KCLcurrentsNodePrimeRHS_7 ; + double *KCLcurrentsNodePrimeRHS_8 ; + double *KCLcurrentsNodePrimeRHS_9 ; + double *KCLcurrentsNodePrimeRHS_10 ; + double *KCLcurrentsNodePrimeRHS_11 ; + + double *KCLcurrentdbNodeRHS_1 ; + double *KCLcurrentdbNodeRHS_2 ; + + double *KCLcurrentsbNodeRHS_1 ; + double *KCLcurrentsbNodeRHS_2 ; + + double *KCLcurrentdNodeRHS ; + + double *KCLcurrentsNodeRHS ; + + double *KCLcurrentqNodeRHS_1 ; + double *KCLcurrentqNodeRHS_2 ; + +//Matrix + double *KCLcurrentdNodePrime_1 ; + double *KCLcurrentdNodePrime_2 ; + + double *KCLcurrentdNode_1 ; + double *KCLcurrentdNode_2 ; + + double *KCLcurrentsNodePrime_1 ; + double *KCLcurrentsNodePrime_2 ; + + double *KCLcurrentsNode_1 ; + double *KCLcurrentsNode_2 ; + + double *KCLcurrentgNodeExt ; + + double *KCLcurrentgNodeMid_1 ; + double *KCLcurrentgNodeMid_2 ; + + double *KCLcurrentgNodePrime ; + + double *KCLcurrentdbNode_1 ; + double *KCLcurrentdbNode_2 ; + + double *KCLcurrentbNodePrime_1 ; + double *KCLcurrentbNodePrime_2 ; + double *KCLcurrentbNodePrime_3 ; + + double *KCLcurrentbNode_1 ; + double *KCLcurrentbNode_2 ; + double *KCLcurrentbNode_3 ; + + double *KCLcurrentsbNode_1 ; + double *KCLcurrentsbNode_2 ; +#endif + } BSIM4instance ; struct bsim4SizeDependParam @@ -903,6 +984,7 @@ typedef struct sBSIM4model int BSIM4rgateMod; int BSIM4perMod; int BSIM4geoMod; + int BSIM4rgeoMod; int BSIM4mtrlMod; int BSIM4mtrlCompatMod; /* v4.7 */ int BSIM4gidlMod; /* v4.7 New GIDL/GISL */ @@ -1854,6 +1936,7 @@ typedef struct sBSIM4model unsigned BSIM4rgateModGiven :1; unsigned BSIM4perModGiven :1; unsigned BSIM4geoModGiven :1; + unsigned BSIM4rgeoModGiven :1; unsigned BSIM4paramChkGiven :1; unsigned BSIM4trnqsModGiven :1; unsigned BSIM4acnqsModGiven :1; @@ -2805,30 +2888,31 @@ typedef struct sBSIM4model #define BSIM4_M 38 /* Global parameters */ -#define BSIM4_MOD_TEMPEOT 66 -#define BSIM4_MOD_LEFFEOT 67 -#define BSIM4_MOD_WEFFEOT 68 -#define BSIM4_MOD_UCSTE 69 -#define BSIM4_MOD_LUCSTE 70 -#define BSIM4_MOD_WUCSTE 71 -#define BSIM4_MOD_PUCSTE 72 -#define BSIM4_MOD_UCS 73 -#define BSIM4_MOD_LUCS 74 -#define BSIM4_MOD_WUCS 75 -#define BSIM4_MOD_PUCS 76 -#define BSIM4_MOD_CVCHARGEMOD 77 -#define BSIM4_MOD_ADOS 78 -#define BSIM4_MOD_BDOS 79 -#define BSIM4_MOD_TEMPMOD 80 -#define BSIM4_MOD_MTRLMOD 81 -#define BSIM4_MOD_IGCMOD 82 -#define BSIM4_MOD_IGBMOD 83 -#define BSIM4_MOD_ACNQSMOD 84 -#define BSIM4_MOD_FNOIMOD 85 -#define BSIM4_MOD_RDSMOD 86 -#define BSIM4_MOD_DIOMOD 87 -#define BSIM4_MOD_PERMOD 88 -#define BSIM4_MOD_GEOMOD 89 +#define BSIM4_MOD_TEMPEOT 65 +#define BSIM4_MOD_LEFFEOT 66 +#define BSIM4_MOD_WEFFEOT 67 +#define BSIM4_MOD_UCSTE 68 +#define BSIM4_MOD_LUCSTE 69 +#define BSIM4_MOD_WUCSTE 70 +#define BSIM4_MOD_PUCSTE 71 +#define BSIM4_MOD_UCS 72 +#define BSIM4_MOD_LUCS 73 +#define BSIM4_MOD_WUCS 74 +#define BSIM4_MOD_PUCS 75 +#define BSIM4_MOD_CVCHARGEMOD 76 +#define BSIM4_MOD_ADOS 77 +#define BSIM4_MOD_BDOS 78 +#define BSIM4_MOD_TEMPMOD 79 +#define BSIM4_MOD_MTRLMOD 80 +#define BSIM4_MOD_IGCMOD 81 +#define BSIM4_MOD_IGBMOD 82 +#define BSIM4_MOD_ACNQSMOD 83 +#define BSIM4_MOD_FNOIMOD 84 +#define BSIM4_MOD_RDSMOD 85 +#define BSIM4_MOD_DIOMOD 86 +#define BSIM4_MOD_PERMOD 87 +#define BSIM4_MOD_GEOMOD 88 +#define BSIM4_MOD_RGEOMOD 89 #define BSIM4_MOD_RGATEMOD 90 #define BSIM4_MOD_RBODYMOD 91 #define BSIM4_MOD_CAPMOD 92 diff --git a/src/spicelib/devices/bsim4/bsim4ext.h b/src/spicelib/devices/bsim4/bsim4ext.h index 99bf6ffbf..7c9923159 100644 --- a/src/spicelib/devices/bsim4/bsim4ext.h +++ b/src/spicelib/devices/bsim4/bsim4ext.h @@ -34,3 +34,7 @@ extern int BSIM4bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM4bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM4bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM4nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim4/bsim4init.c b/src/spicelib/devices/bsim4/bsim4init.c index eb2517171..ff7eea638 100644 --- a/src/spicelib/devices/bsim4/bsim4init.c +++ b/src/spicelib/devices/bsim4/bsim4init.c @@ -73,12 +73,17 @@ SPICEdev BSIM4info = { #endif &BSIM4iSize, /* DEVinstSize */ &BSIM4mSize, /* DEVmodSize */ + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) BSIM4bindCSC, /* DEVbindCSC */ BSIM4bindCSCComplex, /* DEVbindCSCComplex */ BSIM4bindCSCComplexToReal, /* DEVbindCSCComplexToReal */ #endif +#ifdef KIRCHHOFF + BSIM4nodeIsNonLinear /* DEVnodeIsNonLinear */ +#endif + }; diff --git a/src/spicelib/devices/bsim4v4/Makefile.am b/src/spicelib/devices/bsim4v4/Makefile.am index 45348b25c..63fcebd49 100644 --- a/src/spicelib/devices/bsim4v4/Makefile.am +++ b/src/spicelib/devices/bsim4v4/Makefile.am @@ -41,6 +41,10 @@ if UMFPACK_WANTED libbsim4v4_la_SOURCES += b4v4bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim4v4_la_SOURCES += b4v4node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim4v4/b4v4getic.c b/src/spicelib/devices/bsim4v4/b4v4getic.c index 0b6088dd8..808368e8a 100644 --- a/src/spicelib/devices/bsim4v4/b4v4getic.c +++ b/src/spicelib/devices/bsim4v4/b4v4getic.c @@ -17,28 +17,27 @@ int BSIM4v4getic( -GENmodel *inModel, -CKTcircuit *ckt) + GENmodel *inModel, + CKTcircuit *ckt) { -BSIM4v4model *model = (BSIM4v4model*)inModel; -BSIM4v4instance *here; + BSIM4v4model *model = (BSIM4v4model*)inModel; + BSIM4v4instance *here; - for (; model ; model = model->BSIM4v4nextModel) - { for (here = model->BSIM4v4instances; here; here = here->BSIM4v4nextInstance) - { - if (!here->BSIM4v4icVDSGiven) - { here->BSIM4v4icVDS = *(ckt->CKTrhs + here->BSIM4v4dNode) - - *(ckt->CKTrhs + here->BSIM4v4sNode); - } - if (!here->BSIM4v4icVGSGiven) - { here->BSIM4v4icVGS = *(ckt->CKTrhs + here->BSIM4v4gNodeExt) - - *(ckt->CKTrhs + here->BSIM4v4sNode); - } - if(!here->BSIM4v4icVBSGiven) - { here->BSIM4v4icVBS = *(ckt->CKTrhs + here->BSIM4v4bNode) - - *(ckt->CKTrhs + here->BSIM4v4sNode); - } - } + for (; model ; model = model->BSIM4v4nextModel) { + for (here = model->BSIM4v4instances; here; here = here->BSIM4v4nextInstance) { + if (!here->BSIM4v4icVDSGiven) { + here->BSIM4v4icVDS = *(ckt->CKTrhs + here->BSIM4v4dNode) + - *(ckt->CKTrhs + here->BSIM4v4sNode); + } + if (!here->BSIM4v4icVGSGiven) { + here->BSIM4v4icVGS = *(ckt->CKTrhs + here->BSIM4v4gNodeExt) + - *(ckt->CKTrhs + here->BSIM4v4sNode); + } + if(!here->BSIM4v4icVBSGiven) { + here->BSIM4v4icVBS = *(ckt->CKTrhs + here->BSIM4v4bNode) + - *(ckt->CKTrhs + here->BSIM4v4sNode); + } + } } return(OK); } diff --git a/src/spicelib/devices/bsim4v4/b4v4node.c b/src/spicelib/devices/bsim4v4/b4v4node.c new file mode 100644 index 000000000..a033750a0 --- /dev/null +++ b/src/spicelib/devices/bsim4v4/b4v4node.c @@ -0,0 +1,34 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim4v4def.h" +#include "ngspice/sperror.h" + +int +BSIM4v4nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM4v4model *model = (BSIM4v4model *)inModel ; + BSIM4v4instance *here ; + + /* loop through all the BSIM4v4 models */ + for ( ; model != NULL ; model = model->BSIM4v4nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4v4instances ; here != NULL ; here = here->BSIM4v4nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM4v4dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4gNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4gNodeMid] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4dbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4bNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4sbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v4qNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v4/b4v4set.c b/src/spicelib/devices/bsim4v4/b4v4set.c index a1f483973..cf01a4a80 100644 --- a/src/spicelib/devices/bsim4v4/b4v4set.c +++ b/src/spicelib/devices/bsim4v4/b4v4set.c @@ -1849,96 +1849,96 @@ JOB *job; /* set Sparse Matrix Pointers * macro to make elements with built-in out-of-memory test */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM4v4DPbpPtr, BSIM4v4dNodePrime, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4GPbpPtr, BSIM4v4gNodePrime, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4SPbpPtr, BSIM4v4sNodePrime, BSIM4v4bNodePrime) + TSTALLOC(BSIM4v4DPbpPtr, BSIM4v4dNodePrime, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4GPbpPtr, BSIM4v4gNodePrime, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4SPbpPtr, BSIM4v4sNodePrime, BSIM4v4bNodePrime); - TSTALLOC(BSIM4v4BPdpPtr, BSIM4v4bNodePrime, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4BPgpPtr, BSIM4v4bNodePrime, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4BPspPtr, BSIM4v4bNodePrime, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4BPbpPtr, BSIM4v4bNodePrime, BSIM4v4bNodePrime) + TSTALLOC(BSIM4v4BPdpPtr, BSIM4v4bNodePrime, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4BPgpPtr, BSIM4v4bNodePrime, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4BPspPtr, BSIM4v4bNodePrime, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4BPbpPtr, BSIM4v4bNodePrime, BSIM4v4bNodePrime); - TSTALLOC(BSIM4v4DdPtr, BSIM4v4dNode, BSIM4v4dNode) - TSTALLOC(BSIM4v4GPgpPtr, BSIM4v4gNodePrime, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4SsPtr, BSIM4v4sNode, BSIM4v4sNode) - TSTALLOC(BSIM4v4DPdpPtr, BSIM4v4dNodePrime, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4SPspPtr, BSIM4v4sNodePrime, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4DdpPtr, BSIM4v4dNode, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4GPdpPtr, BSIM4v4gNodePrime, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4GPspPtr, BSIM4v4gNodePrime, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4SspPtr, BSIM4v4sNode, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4DPspPtr, BSIM4v4dNodePrime, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4DPdPtr, BSIM4v4dNodePrime, BSIM4v4dNode) - TSTALLOC(BSIM4v4DPgpPtr, BSIM4v4dNodePrime, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4SPgpPtr, BSIM4v4sNodePrime, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4SPsPtr, BSIM4v4sNodePrime, BSIM4v4sNode) - TSTALLOC(BSIM4v4SPdpPtr, BSIM4v4sNodePrime, BSIM4v4dNodePrime) + TSTALLOC(BSIM4v4DdPtr, BSIM4v4dNode, BSIM4v4dNode); + TSTALLOC(BSIM4v4GPgpPtr, BSIM4v4gNodePrime, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4SsPtr, BSIM4v4sNode, BSIM4v4sNode); + TSTALLOC(BSIM4v4DPdpPtr, BSIM4v4dNodePrime, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4SPspPtr, BSIM4v4sNodePrime, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4DdpPtr, BSIM4v4dNode, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4GPdpPtr, BSIM4v4gNodePrime, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4GPspPtr, BSIM4v4gNodePrime, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4SspPtr, BSIM4v4sNode, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4DPspPtr, BSIM4v4dNodePrime, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4DPdPtr, BSIM4v4dNodePrime, BSIM4v4dNode); + TSTALLOC(BSIM4v4DPgpPtr, BSIM4v4dNodePrime, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4SPgpPtr, BSIM4v4sNodePrime, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4SPsPtr, BSIM4v4sNodePrime, BSIM4v4sNode); + TSTALLOC(BSIM4v4SPdpPtr, BSIM4v4sNodePrime, BSIM4v4dNodePrime); - TSTALLOC(BSIM4v4QqPtr, BSIM4v4qNode, BSIM4v4qNode) - TSTALLOC(BSIM4v4QbpPtr, BSIM4v4qNode, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4QdpPtr, BSIM4v4qNode, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4QspPtr, BSIM4v4qNode, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4QgpPtr, BSIM4v4qNode, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4DPqPtr, BSIM4v4dNodePrime, BSIM4v4qNode) - TSTALLOC(BSIM4v4SPqPtr, BSIM4v4sNodePrime, BSIM4v4qNode) - TSTALLOC(BSIM4v4GPqPtr, BSIM4v4gNodePrime, BSIM4v4qNode) + TSTALLOC(BSIM4v4QqPtr, BSIM4v4qNode, BSIM4v4qNode); + TSTALLOC(BSIM4v4QbpPtr, BSIM4v4qNode, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4QdpPtr, BSIM4v4qNode, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4QspPtr, BSIM4v4qNode, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4QgpPtr, BSIM4v4qNode, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4DPqPtr, BSIM4v4dNodePrime, BSIM4v4qNode); + TSTALLOC(BSIM4v4SPqPtr, BSIM4v4sNodePrime, BSIM4v4qNode); + TSTALLOC(BSIM4v4GPqPtr, BSIM4v4gNodePrime, BSIM4v4qNode); if (here->BSIM4v4rgateMod != 0) - { TSTALLOC(BSIM4v4GEgePtr, BSIM4v4gNodeExt, BSIM4v4gNodeExt) - TSTALLOC(BSIM4v4GEgpPtr, BSIM4v4gNodeExt, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4GPgePtr, BSIM4v4gNodePrime, BSIM4v4gNodeExt) - TSTALLOC(BSIM4v4GEdpPtr, BSIM4v4gNodeExt, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4GEspPtr, BSIM4v4gNodeExt, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4GEbpPtr, BSIM4v4gNodeExt, BSIM4v4bNodePrime) + { TSTALLOC(BSIM4v4GEgePtr, BSIM4v4gNodeExt, BSIM4v4gNodeExt); + TSTALLOC(BSIM4v4GEgpPtr, BSIM4v4gNodeExt, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4GPgePtr, BSIM4v4gNodePrime, BSIM4v4gNodeExt); + TSTALLOC(BSIM4v4GEdpPtr, BSIM4v4gNodeExt, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4GEspPtr, BSIM4v4gNodeExt, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4GEbpPtr, BSIM4v4gNodeExt, BSIM4v4bNodePrime); - TSTALLOC(BSIM4v4GMdpPtr, BSIM4v4gNodeMid, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4GMgpPtr, BSIM4v4gNodeMid, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4GMgmPtr, BSIM4v4gNodeMid, BSIM4v4gNodeMid) - TSTALLOC(BSIM4v4GMgePtr, BSIM4v4gNodeMid, BSIM4v4gNodeExt) - TSTALLOC(BSIM4v4GMspPtr, BSIM4v4gNodeMid, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4GMbpPtr, BSIM4v4gNodeMid, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4DPgmPtr, BSIM4v4dNodePrime, BSIM4v4gNodeMid) - TSTALLOC(BSIM4v4GPgmPtr, BSIM4v4gNodePrime, BSIM4v4gNodeMid) - TSTALLOC(BSIM4v4GEgmPtr, BSIM4v4gNodeExt, BSIM4v4gNodeMid) - TSTALLOC(BSIM4v4SPgmPtr, BSIM4v4sNodePrime, BSIM4v4gNodeMid) - TSTALLOC(BSIM4v4BPgmPtr, BSIM4v4bNodePrime, BSIM4v4gNodeMid) + TSTALLOC(BSIM4v4GMdpPtr, BSIM4v4gNodeMid, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4GMgpPtr, BSIM4v4gNodeMid, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4GMgmPtr, BSIM4v4gNodeMid, BSIM4v4gNodeMid); + TSTALLOC(BSIM4v4GMgePtr, BSIM4v4gNodeMid, BSIM4v4gNodeExt); + TSTALLOC(BSIM4v4GMspPtr, BSIM4v4gNodeMid, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4GMbpPtr, BSIM4v4gNodeMid, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4DPgmPtr, BSIM4v4dNodePrime, BSIM4v4gNodeMid); + TSTALLOC(BSIM4v4GPgmPtr, BSIM4v4gNodePrime, BSIM4v4gNodeMid); + TSTALLOC(BSIM4v4GEgmPtr, BSIM4v4gNodeExt, BSIM4v4gNodeMid); + TSTALLOC(BSIM4v4SPgmPtr, BSIM4v4sNodePrime, BSIM4v4gNodeMid); + TSTALLOC(BSIM4v4BPgmPtr, BSIM4v4bNodePrime, BSIM4v4gNodeMid); } if (here->BSIM4v4rbodyMod) - { TSTALLOC(BSIM4v4DPdbPtr, BSIM4v4dNodePrime, BSIM4v4dbNode) - TSTALLOC(BSIM4v4SPsbPtr, BSIM4v4sNodePrime, BSIM4v4sbNode) + { TSTALLOC(BSIM4v4DPdbPtr, BSIM4v4dNodePrime, BSIM4v4dbNode); + TSTALLOC(BSIM4v4SPsbPtr, BSIM4v4sNodePrime, BSIM4v4sbNode); - TSTALLOC(BSIM4v4DBdpPtr, BSIM4v4dbNode, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4DBdbPtr, BSIM4v4dbNode, BSIM4v4dbNode) - TSTALLOC(BSIM4v4DBbpPtr, BSIM4v4dbNode, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4DBbPtr, BSIM4v4dbNode, BSIM4v4bNode) + TSTALLOC(BSIM4v4DBdpPtr, BSIM4v4dbNode, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4DBdbPtr, BSIM4v4dbNode, BSIM4v4dbNode); + TSTALLOC(BSIM4v4DBbpPtr, BSIM4v4dbNode, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4DBbPtr, BSIM4v4dbNode, BSIM4v4bNode); - TSTALLOC(BSIM4v4BPdbPtr, BSIM4v4bNodePrime, BSIM4v4dbNode) - TSTALLOC(BSIM4v4BPbPtr, BSIM4v4bNodePrime, BSIM4v4bNode) - TSTALLOC(BSIM4v4BPsbPtr, BSIM4v4bNodePrime, BSIM4v4sbNode) + TSTALLOC(BSIM4v4BPdbPtr, BSIM4v4bNodePrime, BSIM4v4dbNode); + TSTALLOC(BSIM4v4BPbPtr, BSIM4v4bNodePrime, BSIM4v4bNode); + TSTALLOC(BSIM4v4BPsbPtr, BSIM4v4bNodePrime, BSIM4v4sbNode); - TSTALLOC(BSIM4v4SBspPtr, BSIM4v4sbNode, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4SBbpPtr, BSIM4v4sbNode, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4SBbPtr, BSIM4v4sbNode, BSIM4v4bNode) - TSTALLOC(BSIM4v4SBsbPtr, BSIM4v4sbNode, BSIM4v4sbNode) + TSTALLOC(BSIM4v4SBspPtr, BSIM4v4sbNode, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4SBbpPtr, BSIM4v4sbNode, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4SBbPtr, BSIM4v4sbNode, BSIM4v4bNode); + TSTALLOC(BSIM4v4SBsbPtr, BSIM4v4sbNode, BSIM4v4sbNode); - TSTALLOC(BSIM4v4BdbPtr, BSIM4v4bNode, BSIM4v4dbNode) - TSTALLOC(BSIM4v4BbpPtr, BSIM4v4bNode, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4BsbPtr, BSIM4v4bNode, BSIM4v4sbNode) - TSTALLOC(BSIM4v4BbPtr, BSIM4v4bNode, BSIM4v4bNode) + TSTALLOC(BSIM4v4BdbPtr, BSIM4v4bNode, BSIM4v4dbNode); + TSTALLOC(BSIM4v4BbpPtr, BSIM4v4bNode, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4BsbPtr, BSIM4v4bNode, BSIM4v4sbNode); + TSTALLOC(BSIM4v4BbPtr, BSIM4v4bNode, BSIM4v4bNode); } if (model->BSIM4v4rdsMod) - { TSTALLOC(BSIM4v4DgpPtr, BSIM4v4dNode, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4DspPtr, BSIM4v4dNode, BSIM4v4sNodePrime) - TSTALLOC(BSIM4v4DbpPtr, BSIM4v4dNode, BSIM4v4bNodePrime) - TSTALLOC(BSIM4v4SdpPtr, BSIM4v4sNode, BSIM4v4dNodePrime) - TSTALLOC(BSIM4v4SgpPtr, BSIM4v4sNode, BSIM4v4gNodePrime) - TSTALLOC(BSIM4v4SbpPtr, BSIM4v4sNode, BSIM4v4bNodePrime) + { TSTALLOC(BSIM4v4DgpPtr, BSIM4v4dNode, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4DspPtr, BSIM4v4dNode, BSIM4v4sNodePrime); + TSTALLOC(BSIM4v4DbpPtr, BSIM4v4dNode, BSIM4v4bNodePrime); + TSTALLOC(BSIM4v4SdpPtr, BSIM4v4sNode, BSIM4v4dNodePrime); + TSTALLOC(BSIM4v4SgpPtr, BSIM4v4sNode, BSIM4v4gNodePrime); + TSTALLOC(BSIM4v4SbpPtr, BSIM4v4sNode, BSIM4v4bNodePrime); } } } diff --git a/src/spicelib/devices/bsim4v4/bsim4v4ext.h b/src/spicelib/devices/bsim4v4/bsim4v4ext.h index 21223d096..78838b902 100644 --- a/src/spicelib/devices/bsim4v4/bsim4v4ext.h +++ b/src/spicelib/devices/bsim4v4/bsim4v4ext.h @@ -30,10 +30,12 @@ extern int BSIM4v4trunc(GENmodel*,CKTcircuit*,double*); extern int BSIM4v4noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BSIM4v4unsetup(GENmodel*,CKTcircuit*); - - #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int BSIM4v4bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM4v4bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM4v4bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM4v4nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim4v4/bsim4v4init.c b/src/spicelib/devices/bsim4v4/bsim4v4init.c index e9a53c6cb..6699bc793 100644 --- a/src/spicelib/devices/bsim4v4/bsim4v4init.c +++ b/src/spicelib/devices/bsim4v4/bsim4v4init.c @@ -73,12 +73,17 @@ SPICEdev BSIM4v4info = { #endif &BSIM4v4iSize, /* DEVinstSize */ &BSIM4v4mSize, /* DEVmodSize */ + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) BSIM4v4bindCSC, /* DEVbindCSC */ BSIM4v4bindCSCComplex, /* DEVbindCSCComplex */ BSIM4v4bindCSCComplexToReal, /* DEVbindCSCComplexToReal */ #endif +#ifdef KIRCHHOFF + BSIM4v4nodeIsNonLinear /* DEVnodeIsNonLinear */ +#endif + }; diff --git a/src/spicelib/devices/bsim4v5/Makefile.am b/src/spicelib/devices/bsim4v5/Makefile.am index 87cc8be1d..99c61737f 100644 --- a/src/spicelib/devices/bsim4v5/Makefile.am +++ b/src/spicelib/devices/bsim4v5/Makefile.am @@ -41,6 +41,10 @@ if UMFPACK_WANTED libbsim4v5_la_SOURCES += b4v5bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim4v5_la_SOURCES += b4v5node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim4v5/b4v5.c b/src/spicelib/devices/bsim4v5/b4v5.c index c32892bb4..2f6ecea14 100644 --- a/src/spicelib/devices/bsim4v5/b4v5.c +++ b/src/spicelib/devices/bsim4v5/b4v5.c @@ -116,6 +116,7 @@ IOP( "rbodymod", BSIM4v5_MOD_RBODYMOD, IF_INTEGER, "Distributed body R model sel IOP( "rgatemod", BSIM4v5_MOD_RGATEMOD, IF_INTEGER, "Gate R model selector"), IOP( "permod", BSIM4v5_MOD_PERMOD, IF_INTEGER, "Pd and Ps model selector"), IOP( "geomod", BSIM4v5_MOD_GEOMOD, IF_INTEGER, "Geometry dependent parasitics model selector"), +IOP( "rgeomod", BSIM4v5_MOD_RGEOMOD, IF_INTEGER, "S/D resistance and contact model selector"), IOP( "fnoimod", BSIM4v5_MOD_FNOIMOD, IF_INTEGER, "Flicker noise model selector"), IOP( "tnoimod", BSIM4v5_MOD_TNOIMOD, IF_INTEGER, "Thermal noise model selector"), IOP( "igcmod", BSIM4v5_MOD_IGCMOD, IF_INTEGER, "Gate-to-channel Ig model selector"), diff --git a/src/spicelib/devices/bsim4v5/b4v5mask.c b/src/spicelib/devices/bsim4v5/b4v5mask.c index c5be19b88..909f2fa14 100644 --- a/src/spicelib/devices/bsim4v5/b4v5mask.c +++ b/src/spicelib/devices/bsim4v5/b4v5mask.c @@ -76,6 +76,9 @@ IFvalue *value) case BSIM4v5_MOD_GEOMOD : value->iValue = model->BSIM4v5geoMod; return(OK); + case BSIM4v5_MOD_RGEOMOD : + value->iValue = model->BSIM4v5rgeoMod; + return(OK); case BSIM4v5_MOD_IGCMOD : value->iValue = model->BSIM4v5igcMod; return(OK); diff --git a/src/spicelib/devices/bsim4v5/b4v5mpar.c b/src/spicelib/devices/bsim4v5/b4v5mpar.c index 750e24de3..7b138f18d 100644 --- a/src/spicelib/devices/bsim4v5/b4v5mpar.c +++ b/src/spicelib/devices/bsim4v5/b4v5mpar.c @@ -77,6 +77,10 @@ GENmodel *inMod) mod->BSIM4v5geoMod = value->iValue; mod->BSIM4v5geoModGiven = TRUE; break; + case BSIM4v5_MOD_RGEOMOD : + mod->BSIM4v5rgeoMod = value->iValue; + mod->BSIM4v5rgeoModGiven = TRUE; + break; case BSIM4v5_MOD_FNOIMOD : mod->BSIM4v5fnoiMod = value->iValue; mod->BSIM4v5fnoiModGiven = TRUE; diff --git a/src/spicelib/devices/bsim4v5/b4v5node.c b/src/spicelib/devices/bsim4v5/b4v5node.c new file mode 100644 index 000000000..c344a6167 --- /dev/null +++ b/src/spicelib/devices/bsim4v5/b4v5node.c @@ -0,0 +1,34 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim4v5def.h" +#include "ngspice/sperror.h" + +int +BSIM4v5nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM4v5model *model = (BSIM4v5model *)inModel ; + BSIM4v5instance *here ; + + /* loop through all the BSIM4v5 models */ + for ( ; model != NULL ; model = model->BSIM4v5nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4v5instances ; here != NULL ; here = here->BSIM4v5nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM4v5dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5gNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5gNodeMid] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5dbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5bNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5sbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v5qNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v5/b4v5set.c b/src/spicelib/devices/bsim4v5/b4v5set.c index 3d23a91a8..667a86c7c 100644 --- a/src/spicelib/devices/bsim4v5/b4v5set.c +++ b/src/spicelib/devices/bsim4v5/b4v5set.c @@ -122,6 +122,13 @@ JOB *job; if (!model->BSIM4v5geoModGiven) model->BSIM4v5geoMod = 0; + if (!model->BSIM4v5rgeoModGiven) + model->BSIM4v5rgeoMod = 0; + else if ((model->BSIM4v5rgeoMod != 0) && (model->BSIM4v5rgeoMod != 1)) + { model->BSIM4v5rgeoMod = 1; + printf("Warning: rgeoMod has been set to its default value: 1.\n"); + } + if (!model->BSIM4v5fnoiModGiven) model->BSIM4v5fnoiMod = 1; else if ((model->BSIM4v5fnoiMod != 0) && (model->BSIM4v5fnoiMod != 1)) @@ -1735,8 +1742,14 @@ JOB *job; if (!here->BSIM4v5geoModGiven) here->BSIM4v5geoMod = model->BSIM4v5geoMod; + if (!here->BSIM4v5rgeoModGiven) - here->BSIM4v5rgeoMod = 0; + here->BSIM4v5rgeoMod = model->BSIM4v5rgeoMod; + else if ((here->BSIM4v5rgeoMod != 0) && (here->BSIM4v5rgeoMod != 1)) + { here->BSIM4v5rgeoMod = model->BSIM4v5rgeoMod; + printf("Warning: rgeoMod has been set to its global value %d.\n", + model->BSIM4v5rgeoMod); + } if (!here->BSIM4v5trnqsModGiven) here->BSIM4v5trnqsMod = model->BSIM4v5trnqsMod; else if ((here->BSIM4v5trnqsMod != 0) && (here->BSIM4v5trnqsMod != 1)) @@ -1953,96 +1966,96 @@ JOB *job; /* set Sparse Matrix Pointers * macro to make elements with built-in out-of-memory test */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM4v5DPbpPtr, BSIM4v5dNodePrime, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5GPbpPtr, BSIM4v5gNodePrime, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5SPbpPtr, BSIM4v5sNodePrime, BSIM4v5bNodePrime) + TSTALLOC(BSIM4v5DPbpPtr, BSIM4v5dNodePrime, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5GPbpPtr, BSIM4v5gNodePrime, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5SPbpPtr, BSIM4v5sNodePrime, BSIM4v5bNodePrime); - TSTALLOC(BSIM4v5BPdpPtr, BSIM4v5bNodePrime, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5BPgpPtr, BSIM4v5bNodePrime, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5BPspPtr, BSIM4v5bNodePrime, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5BPbpPtr, BSIM4v5bNodePrime, BSIM4v5bNodePrime) + TSTALLOC(BSIM4v5BPdpPtr, BSIM4v5bNodePrime, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5BPgpPtr, BSIM4v5bNodePrime, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5BPspPtr, BSIM4v5bNodePrime, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5BPbpPtr, BSIM4v5bNodePrime, BSIM4v5bNodePrime); - TSTALLOC(BSIM4v5DdPtr, BSIM4v5dNode, BSIM4v5dNode) - TSTALLOC(BSIM4v5GPgpPtr, BSIM4v5gNodePrime, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5SsPtr, BSIM4v5sNode, BSIM4v5sNode) - TSTALLOC(BSIM4v5DPdpPtr, BSIM4v5dNodePrime, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5SPspPtr, BSIM4v5sNodePrime, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5DdpPtr, BSIM4v5dNode, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5GPdpPtr, BSIM4v5gNodePrime, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5GPspPtr, BSIM4v5gNodePrime, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5SspPtr, BSIM4v5sNode, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5DPspPtr, BSIM4v5dNodePrime, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5DPdPtr, BSIM4v5dNodePrime, BSIM4v5dNode) - TSTALLOC(BSIM4v5DPgpPtr, BSIM4v5dNodePrime, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5SPgpPtr, BSIM4v5sNodePrime, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5SPsPtr, BSIM4v5sNodePrime, BSIM4v5sNode) - TSTALLOC(BSIM4v5SPdpPtr, BSIM4v5sNodePrime, BSIM4v5dNodePrime) + TSTALLOC(BSIM4v5DdPtr, BSIM4v5dNode, BSIM4v5dNode); + TSTALLOC(BSIM4v5GPgpPtr, BSIM4v5gNodePrime, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5SsPtr, BSIM4v5sNode, BSIM4v5sNode); + TSTALLOC(BSIM4v5DPdpPtr, BSIM4v5dNodePrime, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5SPspPtr, BSIM4v5sNodePrime, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5DdpPtr, BSIM4v5dNode, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5GPdpPtr, BSIM4v5gNodePrime, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5GPspPtr, BSIM4v5gNodePrime, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5SspPtr, BSIM4v5sNode, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5DPspPtr, BSIM4v5dNodePrime, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5DPdPtr, BSIM4v5dNodePrime, BSIM4v5dNode); + TSTALLOC(BSIM4v5DPgpPtr, BSIM4v5dNodePrime, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5SPgpPtr, BSIM4v5sNodePrime, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5SPsPtr, BSIM4v5sNodePrime, BSIM4v5sNode); + TSTALLOC(BSIM4v5SPdpPtr, BSIM4v5sNodePrime, BSIM4v5dNodePrime); - TSTALLOC(BSIM4v5QqPtr, BSIM4v5qNode, BSIM4v5qNode) - TSTALLOC(BSIM4v5QbpPtr, BSIM4v5qNode, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5QdpPtr, BSIM4v5qNode, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5QspPtr, BSIM4v5qNode, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5QgpPtr, BSIM4v5qNode, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5DPqPtr, BSIM4v5dNodePrime, BSIM4v5qNode) - TSTALLOC(BSIM4v5SPqPtr, BSIM4v5sNodePrime, BSIM4v5qNode) - TSTALLOC(BSIM4v5GPqPtr, BSIM4v5gNodePrime, BSIM4v5qNode) + TSTALLOC(BSIM4v5QqPtr, BSIM4v5qNode, BSIM4v5qNode); + TSTALLOC(BSIM4v5QbpPtr, BSIM4v5qNode, BSIM4v5bNodePrime) ; + TSTALLOC(BSIM4v5QdpPtr, BSIM4v5qNode, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5QspPtr, BSIM4v5qNode, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5QgpPtr, BSIM4v5qNode, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5DPqPtr, BSIM4v5dNodePrime, BSIM4v5qNode); + TSTALLOC(BSIM4v5SPqPtr, BSIM4v5sNodePrime, BSIM4v5qNode); + TSTALLOC(BSIM4v5GPqPtr, BSIM4v5gNodePrime, BSIM4v5qNode); if (here->BSIM4v5rgateMod != 0) - { TSTALLOC(BSIM4v5GEgePtr, BSIM4v5gNodeExt, BSIM4v5gNodeExt) - TSTALLOC(BSIM4v5GEgpPtr, BSIM4v5gNodeExt, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5GPgePtr, BSIM4v5gNodePrime, BSIM4v5gNodeExt) - TSTALLOC(BSIM4v5GEdpPtr, BSIM4v5gNodeExt, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5GEspPtr, BSIM4v5gNodeExt, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5GEbpPtr, BSIM4v5gNodeExt, BSIM4v5bNodePrime) + { TSTALLOC(BSIM4v5GEgePtr, BSIM4v5gNodeExt, BSIM4v5gNodeExt); + TSTALLOC(BSIM4v5GEgpPtr, BSIM4v5gNodeExt, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5GPgePtr, BSIM4v5gNodePrime, BSIM4v5gNodeExt); + TSTALLOC(BSIM4v5GEdpPtr, BSIM4v5gNodeExt, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5GEspPtr, BSIM4v5gNodeExt, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5GEbpPtr, BSIM4v5gNodeExt, BSIM4v5bNodePrime); - TSTALLOC(BSIM4v5GMdpPtr, BSIM4v5gNodeMid, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5GMgpPtr, BSIM4v5gNodeMid, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5GMgmPtr, BSIM4v5gNodeMid, BSIM4v5gNodeMid) - TSTALLOC(BSIM4v5GMgePtr, BSIM4v5gNodeMid, BSIM4v5gNodeExt) - TSTALLOC(BSIM4v5GMspPtr, BSIM4v5gNodeMid, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5GMbpPtr, BSIM4v5gNodeMid, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5DPgmPtr, BSIM4v5dNodePrime, BSIM4v5gNodeMid) - TSTALLOC(BSIM4v5GPgmPtr, BSIM4v5gNodePrime, BSIM4v5gNodeMid) - TSTALLOC(BSIM4v5GEgmPtr, BSIM4v5gNodeExt, BSIM4v5gNodeMid) - TSTALLOC(BSIM4v5SPgmPtr, BSIM4v5sNodePrime, BSIM4v5gNodeMid) - TSTALLOC(BSIM4v5BPgmPtr, BSIM4v5bNodePrime, BSIM4v5gNodeMid) + TSTALLOC(BSIM4v5GMdpPtr, BSIM4v5gNodeMid, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5GMgpPtr, BSIM4v5gNodeMid, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5GMgmPtr, BSIM4v5gNodeMid, BSIM4v5gNodeMid); + TSTALLOC(BSIM4v5GMgePtr, BSIM4v5gNodeMid, BSIM4v5gNodeExt); + TSTALLOC(BSIM4v5GMspPtr, BSIM4v5gNodeMid, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5GMbpPtr, BSIM4v5gNodeMid, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5DPgmPtr, BSIM4v5dNodePrime, BSIM4v5gNodeMid); + TSTALLOC(BSIM4v5GPgmPtr, BSIM4v5gNodePrime, BSIM4v5gNodeMid); + TSTALLOC(BSIM4v5GEgmPtr, BSIM4v5gNodeExt, BSIM4v5gNodeMid); + TSTALLOC(BSIM4v5SPgmPtr, BSIM4v5sNodePrime, BSIM4v5gNodeMid); + TSTALLOC(BSIM4v5BPgmPtr, BSIM4v5bNodePrime, BSIM4v5gNodeMid); } if ((here->BSIM4v5rbodyMod ==1) || (here->BSIM4v5rbodyMod ==2)) - { TSTALLOC(BSIM4v5DPdbPtr, BSIM4v5dNodePrime, BSIM4v5dbNode) - TSTALLOC(BSIM4v5SPsbPtr, BSIM4v5sNodePrime, BSIM4v5sbNode) + { TSTALLOC(BSIM4v5DPdbPtr, BSIM4v5dNodePrime, BSIM4v5dbNode); + TSTALLOC(BSIM4v5SPsbPtr, BSIM4v5sNodePrime, BSIM4v5sbNode); - TSTALLOC(BSIM4v5DBdpPtr, BSIM4v5dbNode, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5DBdbPtr, BSIM4v5dbNode, BSIM4v5dbNode) - TSTALLOC(BSIM4v5DBbpPtr, BSIM4v5dbNode, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5DBbPtr, BSIM4v5dbNode, BSIM4v5bNode) + TSTALLOC(BSIM4v5DBdpPtr, BSIM4v5dbNode, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5DBdbPtr, BSIM4v5dbNode, BSIM4v5dbNode); + TSTALLOC(BSIM4v5DBbpPtr, BSIM4v5dbNode, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5DBbPtr, BSIM4v5dbNode, BSIM4v5bNode); - TSTALLOC(BSIM4v5BPdbPtr, BSIM4v5bNodePrime, BSIM4v5dbNode) - TSTALLOC(BSIM4v5BPbPtr, BSIM4v5bNodePrime, BSIM4v5bNode) - TSTALLOC(BSIM4v5BPsbPtr, BSIM4v5bNodePrime, BSIM4v5sbNode) + TSTALLOC(BSIM4v5BPdbPtr, BSIM4v5bNodePrime, BSIM4v5dbNode); + TSTALLOC(BSIM4v5BPbPtr, BSIM4v5bNodePrime, BSIM4v5bNode); + TSTALLOC(BSIM4v5BPsbPtr, BSIM4v5bNodePrime, BSIM4v5sbNode); - TSTALLOC(BSIM4v5SBspPtr, BSIM4v5sbNode, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5SBbpPtr, BSIM4v5sbNode, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5SBbPtr, BSIM4v5sbNode, BSIM4v5bNode) - TSTALLOC(BSIM4v5SBsbPtr, BSIM4v5sbNode, BSIM4v5sbNode) + TSTALLOC(BSIM4v5SBspPtr, BSIM4v5sbNode, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5SBbpPtr, BSIM4v5sbNode, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5SBbPtr, BSIM4v5sbNode, BSIM4v5bNode); + TSTALLOC(BSIM4v5SBsbPtr, BSIM4v5sbNode, BSIM4v5sbNode); - TSTALLOC(BSIM4v5BdbPtr, BSIM4v5bNode, BSIM4v5dbNode) - TSTALLOC(BSIM4v5BbpPtr, BSIM4v5bNode, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5BsbPtr, BSIM4v5bNode, BSIM4v5sbNode) - TSTALLOC(BSIM4v5BbPtr, BSIM4v5bNode, BSIM4v5bNode) + TSTALLOC(BSIM4v5BdbPtr, BSIM4v5bNode, BSIM4v5dbNode); + TSTALLOC(BSIM4v5BbpPtr, BSIM4v5bNode, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5BsbPtr, BSIM4v5bNode, BSIM4v5sbNode); + TSTALLOC(BSIM4v5BbPtr, BSIM4v5bNode, BSIM4v5bNode); } if (model->BSIM4v5rdsMod) - { TSTALLOC(BSIM4v5DgpPtr, BSIM4v5dNode, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5DspPtr, BSIM4v5dNode, BSIM4v5sNodePrime) - TSTALLOC(BSIM4v5DbpPtr, BSIM4v5dNode, BSIM4v5bNodePrime) - TSTALLOC(BSIM4v5SdpPtr, BSIM4v5sNode, BSIM4v5dNodePrime) - TSTALLOC(BSIM4v5SgpPtr, BSIM4v5sNode, BSIM4v5gNodePrime) - TSTALLOC(BSIM4v5SbpPtr, BSIM4v5sNode, BSIM4v5bNodePrime) + { TSTALLOC(BSIM4v5DgpPtr, BSIM4v5dNode, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5DspPtr, BSIM4v5dNode, BSIM4v5sNodePrime); + TSTALLOC(BSIM4v5DbpPtr, BSIM4v5dNode, BSIM4v5bNodePrime); + TSTALLOC(BSIM4v5SdpPtr, BSIM4v5sNode, BSIM4v5dNodePrime); + TSTALLOC(BSIM4v5SgpPtr, BSIM4v5sNode, BSIM4v5gNodePrime); + TSTALLOC(BSIM4v5SbpPtr, BSIM4v5sNode, BSIM4v5bNodePrime); } } } diff --git a/src/spicelib/devices/bsim4v5/bsim4v5def.h b/src/spicelib/devices/bsim4v5/bsim4v5def.h index 59ef5ceaa..f2e3e8ab0 100644 --- a/src/spicelib/devices/bsim4v5/bsim4v5def.h +++ b/src/spicelib/devices/bsim4v5/bsim4v5def.h @@ -746,6 +746,7 @@ typedef struct sBSIM4v5model int BSIM4v5rgateMod; int BSIM4v5perMod; int BSIM4v5geoMod; + int BSIM4v5rgeoMod; int BSIM4v5igcMod; int BSIM4v5igbMod; int BSIM4v5tempMod; @@ -1559,6 +1560,7 @@ typedef struct sBSIM4v5model unsigned BSIM4v5rgateModGiven :1; unsigned BSIM4v5perModGiven :1; unsigned BSIM4v5geoModGiven :1; + unsigned BSIM4v5rgeoModGiven :1; unsigned BSIM4v5paramChkGiven :1; unsigned BSIM4v5trnqsModGiven :1; unsigned BSIM4v5acnqsModGiven :1; @@ -2383,9 +2385,10 @@ typedef struct sBSIM4v5model #define BSIM4v5_MOD_ACNQSMOD 92 #define BSIM4v5_MOD_FNOIMOD 93 #define BSIM4v5_MOD_RDSMOD 94 -#define BSIM4v5_MOD_DIOMOD 96 -#define BSIM4v5_MOD_PERMOD 97 -#define BSIM4v5_MOD_GEOMOD 98 +#define BSIM4v5_MOD_DIOMOD 95 +#define BSIM4v5_MOD_PERMOD 96 +#define BSIM4v5_MOD_GEOMOD 97 +#define BSIM4v5_MOD_RGEOMOD 98 #define BSIM4v5_MOD_RGATEMOD 99 #define BSIM4v5_MOD_RBODYMOD 100 #define BSIM4v5_MOD_CAPMOD 101 diff --git a/src/spicelib/devices/bsim4v5/bsim4v5ext.h b/src/spicelib/devices/bsim4v5/bsim4v5ext.h index 4d74624c4..95be9fe63 100644 --- a/src/spicelib/devices/bsim4v5/bsim4v5ext.h +++ b/src/spicelib/devices/bsim4v5/bsim4v5ext.h @@ -34,3 +34,7 @@ extern int BSIM4v5bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM4v5bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM4v5bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM4v5nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim4v5/bsim4v5init.c b/src/spicelib/devices/bsim4v5/bsim4v5init.c index fcd3653bd..2d15b878b 100644 --- a/src/spicelib/devices/bsim4v5/bsim4v5init.c +++ b/src/spicelib/devices/bsim4v5/bsim4v5init.c @@ -73,12 +73,17 @@ SPICEdev BSIM4v5info = { #endif &BSIM4v5iSize, /* DEVinstSize */ &BSIM4v5mSize, /* DEVmodSize */ + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) BSIM4v5bindCSC, /* DEVbindCSC */ BSIM4v5bindCSCComplex, /* DEVbindCSCComplex */ BSIM4v5bindCSCComplexToReal, /* DEVbindCSCComplexToReal */ #endif +#ifdef KIRCHHOFF + BSIM4v5nodeIsNonLinear /* DEVnodeIsNonLinear */ +#endif + }; diff --git a/src/spicelib/devices/bsim4v6/Makefile.am b/src/spicelib/devices/bsim4v6/Makefile.am index fe53eee52..9904fb8ef 100644 --- a/src/spicelib/devices/bsim4v6/Makefile.am +++ b/src/spicelib/devices/bsim4v6/Makefile.am @@ -5,21 +5,21 @@ noinst_LTLIBRARIES = libbsim4v6.la libbsim4v6_la_SOURCES = \ b4v6.c \ b4v6acld.c \ - b4v6ask.c \ + b4v6ask.c \ b4v6check.c \ b4v6cvtest.c \ - b4v6del.c \ + b4v6del.c \ b4v6dest.c \ - b4v6geo.c \ + b4v6geo.c \ b4v6getic.c \ - b4v6ld.c \ + b4v6ld.c \ b4v6mask.c \ b4v6mdel.c \ b4v6mpar.c \ - b4v6noi.c \ - b4v6par.c \ + b4v6noi.c \ + b4v6par.c \ b4v6pzld.c \ - b4v6set.c \ + b4v6set.c \ b4v6temp.c \ b4v6trunc.c \ bsim4v6def.h \ @@ -28,6 +28,7 @@ libbsim4v6_la_SOURCES = \ bsim4v6init.h \ bsim4v6itf.h + if KLU_WANTED libbsim4v6_la_SOURCES += b4v6bindCSC.c endif @@ -40,6 +41,10 @@ if UMFPACK_WANTED libbsim4v6_la_SOURCES += b4v6bindCSC.c endif +if KIRCHHOFF_WANTED +libbsim4v6_la_SOURCES += b4v6node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsim4v6/b4v6.c b/src/spicelib/devices/bsim4v6/b4v6.c index 5b422cf1f..acb95ab00 100644 --- a/src/spicelib/devices/bsim4v6/b4v6.c +++ b/src/spicelib/devices/bsim4v6/b4v6.c @@ -123,6 +123,7 @@ IOP( "rbodymod", BSIM4v6_MOD_RBODYMOD, IF_INTEGER, "Distributed body R model sel IOP( "rgatemod", BSIM4v6_MOD_RGATEMOD, IF_INTEGER, "Gate R model selector"), IOP( "permod", BSIM4v6_MOD_PERMOD, IF_INTEGER, "Pd and Ps model selector"), IOP( "geomod", BSIM4v6_MOD_GEOMOD, IF_INTEGER, "Geometry dependent parasitics model selector"), +IOP( "rgeomod", BSIM4v6_MOD_RGEOMOD, IF_INTEGER, "S/D resistance and contact model selector"), IOP( "fnoimod", BSIM4v6_MOD_FNOIMOD, IF_INTEGER, "Flicker noise model selector"), IOP( "tnoimod", BSIM4v6_MOD_TNOIMOD, IF_INTEGER, "Thermal noise model selector"), IOP( "mtrlmod", BSIM4v6_MOD_MTRLMOD, IF_INTEGER, "parameter for non-silicon substrate or metal gate selector"), diff --git a/src/spicelib/devices/bsim4v6/b4v6mask.c b/src/spicelib/devices/bsim4v6/b4v6mask.c index 626b43388..39bb05a0a 100644 --- a/src/spicelib/devices/bsim4v6/b4v6mask.c +++ b/src/spicelib/devices/bsim4v6/b4v6mask.c @@ -83,6 +83,9 @@ IFvalue *value) case BSIM4v6_MOD_GEOMOD : value->iValue = model->BSIM4v6geoMod; return(OK); + case BSIM4v6_MOD_RGEOMOD : + value->iValue = model->BSIM4v6rgeoMod; + return(OK); case BSIM4v6_MOD_MTRLMOD : value->iValue = model->BSIM4v6mtrlMod; return(OK); diff --git a/src/spicelib/devices/bsim4v6/b4v6mpar.c b/src/spicelib/devices/bsim4v6/b4v6mpar.c index 0d70ae64e..181139846 100644 --- a/src/spicelib/devices/bsim4v6/b4v6mpar.c +++ b/src/spicelib/devices/bsim4v6/b4v6mpar.c @@ -87,6 +87,10 @@ GENmodel *inMod) mod->BSIM4v6geoMod = value->iValue; mod->BSIM4v6geoModGiven = TRUE; break; + case BSIM4v6_MOD_RGEOMOD : + mod->BSIM4v6rgeoMod = value->iValue; + mod->BSIM4v6rgeoModGiven = TRUE; + break; case BSIM4v6_MOD_FNOIMOD : mod->BSIM4v6fnoiMod = value->iValue; mod->BSIM4v6fnoiModGiven = TRUE; diff --git a/src/spicelib/devices/bsim4v6/b4v6node.c b/src/spicelib/devices/bsim4v6/b4v6node.c new file mode 100644 index 000000000..f63e4cf38 --- /dev/null +++ b/src/spicelib/devices/bsim4v6/b4v6node.c @@ -0,0 +1,34 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim4v6def.h" +#include "ngspice/sperror.h" + +int +BSIM4v6nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + BSIM4v6model *model = (BSIM4v6model *)inModel ; + BSIM4v6instance *here ; + + /* loop through all the BSIM4v6 models */ + for ( ; model != NULL ; model = model->BSIM4v6nextModel) + { + /* loop through all the instances of the model */ + for (here = model->BSIM4v6instances ; here != NULL ; here = here->BSIM4v6nextInstance) + { + ckt->CKTnodeIsLinear [here->BSIM4v6dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6gNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6gNodeMid] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6dbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6bNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6sbNode] = 0 ; + ckt->CKTnodeIsLinear [here->BSIM4v6qNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v6/b4v6set.c b/src/spicelib/devices/bsim4v6/b4v6set.c index 6cd97e4cc..93e573eaf 100644 --- a/src/spicelib/devices/bsim4v6/b4v6set.c +++ b/src/spicelib/devices/bsim4v6/b4v6set.c @@ -140,6 +140,12 @@ BSIM4v6instance **InstArray; if (!model->BSIM4v6geoModGiven) model->BSIM4v6geoMod = 0; + if (!model->BSIM4v6rgeoModGiven) + model->BSIM4v6rgeoMod = 0; + else if ((model->BSIM4v6rgeoMod != 0) && (model->BSIM4v6rgeoMod != 1)) + { model->BSIM4v6rgeoMod = 1; + printf("Warning: rgeoMod has been set to its default value: 1.\n"); + } if (!model->BSIM4v6fnoiModGiven) model->BSIM4v6fnoiMod = 1; else if ((model->BSIM4v6fnoiMod != 0) && (model->BSIM4v6fnoiMod != 1)) @@ -2099,8 +2105,14 @@ BSIM4v6instance **InstArray; if (!here->BSIM4v6geoModGiven) here->BSIM4v6geoMod = model->BSIM4v6geoMod; + if (!here->BSIM4v6rgeoModGiven) - here->BSIM4v6rgeoMod = 0; + here->BSIM4v6rgeoMod = model->BSIM4v6rgeoMod; + else if ((here->BSIM4v6rgeoMod != 0) && (here->BSIM4v6rgeoMod != 1)) + { here->BSIM4v6rgeoMod = model->BSIM4v6rgeoMod; + printf("Warning: rgeoMod has been set to its global value %d.\n", + model->BSIM4v6rgeoMod); + } if (!here->BSIM4v6trnqsModGiven) here->BSIM4v6trnqsMod = model->BSIM4v6trnqsMod; else if ((here->BSIM4v6trnqsMod != 0) && (here->BSIM4v6trnqsMod != 1)) @@ -2298,96 +2310,96 @@ BSIM4v6instance **InstArray; /* set Sparse Matrix Pointers * macro to make elements with built-in out-of-memory test */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(BSIM4v6DPbpPtr, BSIM4v6dNodePrime, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6GPbpPtr, BSIM4v6gNodePrime, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6SPbpPtr, BSIM4v6sNodePrime, BSIM4v6bNodePrime) + TSTALLOC(BSIM4v6DPbpPtr, BSIM4v6dNodePrime, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6GPbpPtr, BSIM4v6gNodePrime, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6SPbpPtr, BSIM4v6sNodePrime, BSIM4v6bNodePrime); - TSTALLOC(BSIM4v6BPdpPtr, BSIM4v6bNodePrime, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6BPgpPtr, BSIM4v6bNodePrime, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6BPspPtr, BSIM4v6bNodePrime, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6BPbpPtr, BSIM4v6bNodePrime, BSIM4v6bNodePrime) + TSTALLOC(BSIM4v6BPdpPtr, BSIM4v6bNodePrime, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6BPgpPtr, BSIM4v6bNodePrime, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6BPspPtr, BSIM4v6bNodePrime, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6BPbpPtr, BSIM4v6bNodePrime, BSIM4v6bNodePrime); - TSTALLOC(BSIM4v6DdPtr, BSIM4v6dNode, BSIM4v6dNode) - TSTALLOC(BSIM4v6GPgpPtr, BSIM4v6gNodePrime, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6SsPtr, BSIM4v6sNode, BSIM4v6sNode) - TSTALLOC(BSIM4v6DPdpPtr, BSIM4v6dNodePrime, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6SPspPtr, BSIM4v6sNodePrime, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6DdpPtr, BSIM4v6dNode, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6GPdpPtr, BSIM4v6gNodePrime, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6GPspPtr, BSIM4v6gNodePrime, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6SspPtr, BSIM4v6sNode, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6DPspPtr, BSIM4v6dNodePrime, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6DPdPtr, BSIM4v6dNodePrime, BSIM4v6dNode) - TSTALLOC(BSIM4v6DPgpPtr, BSIM4v6dNodePrime, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6SPgpPtr, BSIM4v6sNodePrime, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6SPsPtr, BSIM4v6sNodePrime, BSIM4v6sNode) - TSTALLOC(BSIM4v6SPdpPtr, BSIM4v6sNodePrime, BSIM4v6dNodePrime) + TSTALLOC(BSIM4v6DdPtr, BSIM4v6dNode, BSIM4v6dNode); + TSTALLOC(BSIM4v6GPgpPtr, BSIM4v6gNodePrime, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6SsPtr, BSIM4v6sNode, BSIM4v6sNode); + TSTALLOC(BSIM4v6DPdpPtr, BSIM4v6dNodePrime, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6SPspPtr, BSIM4v6sNodePrime, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6DdpPtr, BSIM4v6dNode, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6GPdpPtr, BSIM4v6gNodePrime, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6GPspPtr, BSIM4v6gNodePrime, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6SspPtr, BSIM4v6sNode, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6DPspPtr, BSIM4v6dNodePrime, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6DPdPtr, BSIM4v6dNodePrime, BSIM4v6dNode); + TSTALLOC(BSIM4v6DPgpPtr, BSIM4v6dNodePrime, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6SPgpPtr, BSIM4v6sNodePrime, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6SPsPtr, BSIM4v6sNodePrime, BSIM4v6sNode); + TSTALLOC(BSIM4v6SPdpPtr, BSIM4v6sNodePrime, BSIM4v6dNodePrime); - TSTALLOC(BSIM4v6QqPtr, BSIM4v6qNode, BSIM4v6qNode) - TSTALLOC(BSIM4v6QbpPtr, BSIM4v6qNode, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6QdpPtr, BSIM4v6qNode, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6QspPtr, BSIM4v6qNode, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6QgpPtr, BSIM4v6qNode, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6DPqPtr, BSIM4v6dNodePrime, BSIM4v6qNode) - TSTALLOC(BSIM4v6SPqPtr, BSIM4v6sNodePrime, BSIM4v6qNode) - TSTALLOC(BSIM4v6GPqPtr, BSIM4v6gNodePrime, BSIM4v6qNode) + TSTALLOC(BSIM4v6QqPtr, BSIM4v6qNode, BSIM4v6qNode); + TSTALLOC(BSIM4v6QbpPtr, BSIM4v6qNode, BSIM4v6bNodePrime) ; + TSTALLOC(BSIM4v6QdpPtr, BSIM4v6qNode, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6QspPtr, BSIM4v6qNode, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6QgpPtr, BSIM4v6qNode, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6DPqPtr, BSIM4v6dNodePrime, BSIM4v6qNode); + TSTALLOC(BSIM4v6SPqPtr, BSIM4v6sNodePrime, BSIM4v6qNode); + TSTALLOC(BSIM4v6GPqPtr, BSIM4v6gNodePrime, BSIM4v6qNode); if (here->BSIM4v6rgateMod != 0) - { TSTALLOC(BSIM4v6GEgePtr, BSIM4v6gNodeExt, BSIM4v6gNodeExt) - TSTALLOC(BSIM4v6GEgpPtr, BSIM4v6gNodeExt, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6GPgePtr, BSIM4v6gNodePrime, BSIM4v6gNodeExt) - TSTALLOC(BSIM4v6GEdpPtr, BSIM4v6gNodeExt, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6GEspPtr, BSIM4v6gNodeExt, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6GEbpPtr, BSIM4v6gNodeExt, BSIM4v6bNodePrime) + { TSTALLOC(BSIM4v6GEgePtr, BSIM4v6gNodeExt, BSIM4v6gNodeExt); + TSTALLOC(BSIM4v6GEgpPtr, BSIM4v6gNodeExt, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6GPgePtr, BSIM4v6gNodePrime, BSIM4v6gNodeExt); + TSTALLOC(BSIM4v6GEdpPtr, BSIM4v6gNodeExt, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6GEspPtr, BSIM4v6gNodeExt, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6GEbpPtr, BSIM4v6gNodeExt, BSIM4v6bNodePrime); - TSTALLOC(BSIM4v6GMdpPtr, BSIM4v6gNodeMid, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6GMgpPtr, BSIM4v6gNodeMid, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6GMgmPtr, BSIM4v6gNodeMid, BSIM4v6gNodeMid) - TSTALLOC(BSIM4v6GMgePtr, BSIM4v6gNodeMid, BSIM4v6gNodeExt) - TSTALLOC(BSIM4v6GMspPtr, BSIM4v6gNodeMid, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6GMbpPtr, BSIM4v6gNodeMid, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6DPgmPtr, BSIM4v6dNodePrime, BSIM4v6gNodeMid) - TSTALLOC(BSIM4v6GPgmPtr, BSIM4v6gNodePrime, BSIM4v6gNodeMid) - TSTALLOC(BSIM4v6GEgmPtr, BSIM4v6gNodeExt, BSIM4v6gNodeMid) - TSTALLOC(BSIM4v6SPgmPtr, BSIM4v6sNodePrime, BSIM4v6gNodeMid) - TSTALLOC(BSIM4v6BPgmPtr, BSIM4v6bNodePrime, BSIM4v6gNodeMid) + TSTALLOC(BSIM4v6GMdpPtr, BSIM4v6gNodeMid, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6GMgpPtr, BSIM4v6gNodeMid, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6GMgmPtr, BSIM4v6gNodeMid, BSIM4v6gNodeMid); + TSTALLOC(BSIM4v6GMgePtr, BSIM4v6gNodeMid, BSIM4v6gNodeExt); + TSTALLOC(BSIM4v6GMspPtr, BSIM4v6gNodeMid, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6GMbpPtr, BSIM4v6gNodeMid, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6DPgmPtr, BSIM4v6dNodePrime, BSIM4v6gNodeMid); + TSTALLOC(BSIM4v6GPgmPtr, BSIM4v6gNodePrime, BSIM4v6gNodeMid); + TSTALLOC(BSIM4v6GEgmPtr, BSIM4v6gNodeExt, BSIM4v6gNodeMid); + TSTALLOC(BSIM4v6SPgmPtr, BSIM4v6sNodePrime, BSIM4v6gNodeMid); + TSTALLOC(BSIM4v6BPgmPtr, BSIM4v6bNodePrime, BSIM4v6gNodeMid); } if ((here->BSIM4v6rbodyMod ==1) || (here->BSIM4v6rbodyMod ==2)) - { TSTALLOC(BSIM4v6DPdbPtr, BSIM4v6dNodePrime, BSIM4v6dbNode) - TSTALLOC(BSIM4v6SPsbPtr, BSIM4v6sNodePrime, BSIM4v6sbNode) + { TSTALLOC(BSIM4v6DPdbPtr, BSIM4v6dNodePrime, BSIM4v6dbNode); + TSTALLOC(BSIM4v6SPsbPtr, BSIM4v6sNodePrime, BSIM4v6sbNode); - TSTALLOC(BSIM4v6DBdpPtr, BSIM4v6dbNode, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6DBdbPtr, BSIM4v6dbNode, BSIM4v6dbNode) - TSTALLOC(BSIM4v6DBbpPtr, BSIM4v6dbNode, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6DBbPtr, BSIM4v6dbNode, BSIM4v6bNode) + TSTALLOC(BSIM4v6DBdpPtr, BSIM4v6dbNode, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6DBdbPtr, BSIM4v6dbNode, BSIM4v6dbNode); + TSTALLOC(BSIM4v6DBbpPtr, BSIM4v6dbNode, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6DBbPtr, BSIM4v6dbNode, BSIM4v6bNode); - TSTALLOC(BSIM4v6BPdbPtr, BSIM4v6bNodePrime, BSIM4v6dbNode) - TSTALLOC(BSIM4v6BPbPtr, BSIM4v6bNodePrime, BSIM4v6bNode) - TSTALLOC(BSIM4v6BPsbPtr, BSIM4v6bNodePrime, BSIM4v6sbNode) + TSTALLOC(BSIM4v6BPdbPtr, BSIM4v6bNodePrime, BSIM4v6dbNode); + TSTALLOC(BSIM4v6BPbPtr, BSIM4v6bNodePrime, BSIM4v6bNode); + TSTALLOC(BSIM4v6BPsbPtr, BSIM4v6bNodePrime, BSIM4v6sbNode); - TSTALLOC(BSIM4v6SBspPtr, BSIM4v6sbNode, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6SBbpPtr, BSIM4v6sbNode, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6SBbPtr, BSIM4v6sbNode, BSIM4v6bNode) - TSTALLOC(BSIM4v6SBsbPtr, BSIM4v6sbNode, BSIM4v6sbNode) + TSTALLOC(BSIM4v6SBspPtr, BSIM4v6sbNode, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6SBbpPtr, BSIM4v6sbNode, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6SBbPtr, BSIM4v6sbNode, BSIM4v6bNode); + TSTALLOC(BSIM4v6SBsbPtr, BSIM4v6sbNode, BSIM4v6sbNode); - TSTALLOC(BSIM4v6BdbPtr, BSIM4v6bNode, BSIM4v6dbNode) - TSTALLOC(BSIM4v6BbpPtr, BSIM4v6bNode, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6BsbPtr, BSIM4v6bNode, BSIM4v6sbNode) - TSTALLOC(BSIM4v6BbPtr, BSIM4v6bNode, BSIM4v6bNode) + TSTALLOC(BSIM4v6BdbPtr, BSIM4v6bNode, BSIM4v6dbNode); + TSTALLOC(BSIM4v6BbpPtr, BSIM4v6bNode, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6BsbPtr, BSIM4v6bNode, BSIM4v6sbNode); + TSTALLOC(BSIM4v6BbPtr, BSIM4v6bNode, BSIM4v6bNode); } if (model->BSIM4v6rdsMod) - { TSTALLOC(BSIM4v6DgpPtr, BSIM4v6dNode, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6DspPtr, BSIM4v6dNode, BSIM4v6sNodePrime) - TSTALLOC(BSIM4v6DbpPtr, BSIM4v6dNode, BSIM4v6bNodePrime) - TSTALLOC(BSIM4v6SdpPtr, BSIM4v6sNode, BSIM4v6dNodePrime) - TSTALLOC(BSIM4v6SgpPtr, BSIM4v6sNode, BSIM4v6gNodePrime) - TSTALLOC(BSIM4v6SbpPtr, BSIM4v6sNode, BSIM4v6bNodePrime) + { TSTALLOC(BSIM4v6DgpPtr, BSIM4v6dNode, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6DspPtr, BSIM4v6dNode, BSIM4v6sNodePrime); + TSTALLOC(BSIM4v6DbpPtr, BSIM4v6dNode, BSIM4v6bNodePrime); + TSTALLOC(BSIM4v6SdpPtr, BSIM4v6sNode, BSIM4v6dNodePrime); + TSTALLOC(BSIM4v6SgpPtr, BSIM4v6sNode, BSIM4v6gNodePrime); + TSTALLOC(BSIM4v6SbpPtr, BSIM4v6sNode, BSIM4v6bNodePrime); } } } /* end of loop through all the BSIM4v6 device models */ diff --git a/src/spicelib/devices/bsim4v6/bsim4v6def.h b/src/spicelib/devices/bsim4v6/bsim4v6def.h index d75bd7b35..cc0c981d3 100644 --- a/src/spicelib/devices/bsim4v6/bsim4v6def.h +++ b/src/spicelib/devices/bsim4v6/bsim4v6def.h @@ -887,6 +887,7 @@ typedef struct sBSIM4v6model int BSIM4v6rgateMod; int BSIM4v6perMod; int BSIM4v6geoMod; + int BSIM4v6rgeoMod; int BSIM4v6mtrlMod; int BSIM4v6igcMod; int BSIM4v6igbMod; @@ -1783,6 +1784,7 @@ typedef struct sBSIM4v6model unsigned BSIM4v6rgateModGiven :1; unsigned BSIM4v6perModGiven :1; unsigned BSIM4v6geoModGiven :1; + unsigned BSIM4v6rgeoModGiven :1; unsigned BSIM4v6paramChkGiven :1; unsigned BSIM4v6trnqsModGiven :1; unsigned BSIM4v6acnqsModGiven :1; @@ -2678,30 +2680,31 @@ typedef struct sBSIM4v6model #define BSIM4v6_M 38 /* Global parameters */ -#define BSIM4v6_MOD_TEMPEOT 66 -#define BSIM4v6_MOD_LEFFEOT 67 -#define BSIM4v6_MOD_WEFFEOT 68 -#define BSIM4v6_MOD_UCSTE 69 -#define BSIM4v6_MOD_LUCSTE 70 -#define BSIM4v6_MOD_WUCSTE 71 -#define BSIM4v6_MOD_PUCSTE 72 -#define BSIM4v6_MOD_UCS 73 -#define BSIM4v6_MOD_LUCS 74 -#define BSIM4v6_MOD_WUCS 75 -#define BSIM4v6_MOD_PUCS 76 -#define BSIM4v6_MOD_CVCHARGEMOD 77 -#define BSIM4v6_MOD_ADOS 78 -#define BSIM4v6_MOD_BDOS 79 -#define BSIM4v6_MOD_TEMPMOD 80 -#define BSIM4v6_MOD_MTRLMOD 81 -#define BSIM4v6_MOD_IGCMOD 82 -#define BSIM4v6_MOD_IGBMOD 83 -#define BSIM4v6_MOD_ACNQSMOD 84 -#define BSIM4v6_MOD_FNOIMOD 85 -#define BSIM4v6_MOD_RDSMOD 86 -#define BSIM4v6_MOD_DIOMOD 87 -#define BSIM4v6_MOD_PERMOD 88 -#define BSIM4v6_MOD_GEOMOD 89 +#define BSIM4v6_MOD_TEMPEOT 65 +#define BSIM4v6_MOD_LEFFEOT 66 +#define BSIM4v6_MOD_WEFFEOT 67 +#define BSIM4v6_MOD_UCSTE 68 +#define BSIM4v6_MOD_LUCSTE 69 +#define BSIM4v6_MOD_WUCSTE 70 +#define BSIM4v6_MOD_PUCSTE 71 +#define BSIM4v6_MOD_UCS 72 +#define BSIM4v6_MOD_LUCS 73 +#define BSIM4v6_MOD_WUCS 74 +#define BSIM4v6_MOD_PUCS 75 +#define BSIM4v6_MOD_CVCHARGEMOD 76 +#define BSIM4v6_MOD_ADOS 77 +#define BSIM4v6_MOD_BDOS 78 +#define BSIM4v6_MOD_TEMPMOD 79 +#define BSIM4v6_MOD_MTRLMOD 80 +#define BSIM4v6_MOD_IGCMOD 81 +#define BSIM4v6_MOD_IGBMOD 82 +#define BSIM4v6_MOD_ACNQSMOD 83 +#define BSIM4v6_MOD_FNOIMOD 84 +#define BSIM4v6_MOD_RDSMOD 85 +#define BSIM4v6_MOD_DIOMOD 86 +#define BSIM4v6_MOD_PERMOD 87 +#define BSIM4v6_MOD_GEOMOD 88 +#define BSIM4v6_MOD_RGEOMOD 89 #define BSIM4v6_MOD_RGATEMOD 90 #define BSIM4v6_MOD_RBODYMOD 91 #define BSIM4v6_MOD_CAPMOD 92 diff --git a/src/spicelib/devices/bsim4v6/bsim4v6ext.h b/src/spicelib/devices/bsim4v6/bsim4v6ext.h index 3d95f0990..0cf3fc29c 100644 --- a/src/spicelib/devices/bsim4v6/bsim4v6ext.h +++ b/src/spicelib/devices/bsim4v6/bsim4v6ext.h @@ -34,3 +34,7 @@ extern int BSIM4v6bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM4v6bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM4v6bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int BSIM4v6nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsim4v6/bsim4v6init.c b/src/spicelib/devices/bsim4v6/bsim4v6init.c index fce866659..4e077f848 100644 --- a/src/spicelib/devices/bsim4v6/bsim4v6init.c +++ b/src/spicelib/devices/bsim4v6/bsim4v6init.c @@ -73,12 +73,17 @@ SPICEdev BSIM4v6info = { #endif &BSIM4v6iSize, /* DEVinstSize */ &BSIM4v6mSize, /* DEVmodSize */ + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) BSIM4v6bindCSC, /* DEVbindCSC */ BSIM4v6bindCSCComplex, /* DEVbindCSCComplex */ BSIM4v6bindCSCComplexToReal, /* DEVbindCSCComplexToReal */ #endif +#ifdef KIRCHHOFF + BSIM4v6nodeIsNonLinear /* DEVnodeIsNonLinear */ +#endif + }; diff --git a/src/spicelib/devices/bsimsoi/Makefile.am b/src/spicelib/devices/bsimsoi/Makefile.am index 6c57b7bdc..4b8272302 100644 --- a/src/spicelib/devices/bsimsoi/Makefile.am +++ b/src/spicelib/devices/bsimsoi/Makefile.am @@ -2,30 +2,30 @@ noinst_LTLIBRARIES = libbsim4soi.la -libbsim4soi_la_SOURCES = \ - b4soi.c \ - b4soiacld.c \ - b4soiask.c \ - b4soicheck.c \ - b4soicvtest.c \ - b4soidel.c \ - b4soidest.c \ - b4soigetic.c \ - b4soild.c \ - b4soimask.c \ - b4soimdel.c \ - b4soimpar.c \ - b4soinoi.c \ - b4soipar.c \ - b4soipzld.c \ - b4soiset.c \ - b4soitemp.c \ - b4soitrunc.c \ - b4soidef.h \ - b4soiext.h \ - b4soiinit.c \ - b4soiinit.h \ - b4soiitf.h +libbsim4soi_la_SOURCES = \ + b4soi.c \ + b4soiacld.c \ + b4soiask.c \ + b4soicheck.c \ + b4soicvtest.c \ + b4soidel.c \ + b4soidest.c \ + b4soigetic.c \ + b4soild.c \ + b4soimask.c \ + b4soimdel.c \ + b4soimpar.c \ + b4soinoi.c \ + b4soipar.c \ + b4soipzld.c \ + b4soiset.c \ + b4soitemp.c \ + b4soitrunc.c \ + b4soidef.h \ + b4soiext.h \ + b4soiinit.c \ + b4soiinit.h \ + b4soiitf.h if KLU_WANTED @@ -40,6 +40,10 @@ if UMFPACK_WANTED libbsim4soi_la_SOURCES += b4soibindCSC.c endif +if KIRCHHOFF_WANTED +libbsim4soi_la_SOURCES += b4soinode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/bsimsoi/b4soiext.h b/src/spicelib/devices/bsimsoi/b4soiext.h index d04e0514e..3b5be049b 100644 --- a/src/spicelib/devices/bsimsoi/b4soiext.h +++ b/src/spicelib/devices/bsimsoi/b4soiext.h @@ -36,3 +36,7 @@ extern int B4SOIbindCSC (GENmodel*, CKTcircuit*) ; extern int B4SOIbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int B4SOIbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int B4SOInodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/bsimsoi/b4soiinit.c b/src/spicelib/devices/bsimsoi/b4soiinit.c index ee9c1e082..f789009fc 100644 --- a/src/spicelib/devices/bsimsoi/b4soiinit.c +++ b/src/spicelib/devices/bsimsoi/b4soiinit.c @@ -71,12 +71,17 @@ SPICEdev B4SOIinfo = { #endif /* DEVinstSize */ &B4SOIiSize, /* DEVmodSize */ &B4SOImSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ B4SOIbindCSC, /* DEVbindCSCComplex */ B4SOIbindCSCComplex, /* DEVbindCSCComplexToReal */ B4SOIbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ B4SOInodeIsNonLinear +#endif + }; SPICEdev * diff --git a/src/spicelib/devices/bsimsoi/b4soinode.c b/src/spicelib/devices/bsimsoi/b4soinode.c new file mode 100644 index 000000000..7b6b8c9b1 --- /dev/null +++ b/src/spicelib/devices/bsimsoi/b4soinode.c @@ -0,0 +1,58 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "b4soidef.h" +#include "ngspice/sperror.h" + +int +B4SOInodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + B4SOImodel *model = (B4SOImodel *)inModel ; + B4SOIinstance *here ; + + /* loop through all the BSIMSOI models */ + for ( ; model != NULL ; model = model->B4SOInextModel) + { + /* loop through all the instances of the model */ + for (here = model->B4SOIinstances ; here != NULL ; here = here->B4SOInextInstance) + { + ckt->CKTnodeIsLinear [here->B4SOIdNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIsNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOItempNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIgNodeMid] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIdbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIsbNode] = 0 ; + if (here->B4SOIdebugMod != 0) + { + ckt->CKTnodeIsLinear [here->B4SOIvbsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIidsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIicNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIibsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIibdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIiiiNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIigNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIgiggNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIgigdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIgigbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIigidlNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIitunNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIibpNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIcbbNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIcbdNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIcbgNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIqbfNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIqjsNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIqjdNode] = 0 ; + } + ckt->CKTnodeIsLinear [here->B4SOIeNode] = 0 ; + ckt->CKTnodeIsLinear [here->B4SOIpNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsimsoi/b4soiset.c b/src/spicelib/devices/bsimsoi/b4soiset.c index 7c3af06d6..29d6df025 100644 --- a/src/spicelib/devices/bsimsoi/b4soiset.c +++ b/src/spicelib/devices/bsimsoi/b4soiset.c @@ -2515,32 +2515,32 @@ B4SOIinstance **InstArray; /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ +do { if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ return(E_NOMEM);\ -} +} } while(0) if ((model->B4SOIshMod == 1) && (here->B4SOIrth0!=0.0)) { - TSTALLOC(B4SOITemptempPtr, B4SOItempNode, B4SOItempNode) - TSTALLOC(B4SOITempdpPtr, B4SOItempNode, B4SOIdNodePrime) - TSTALLOC(B4SOITempspPtr, B4SOItempNode, B4SOIsNodePrime) - TSTALLOC(B4SOITempgPtr, B4SOItempNode, B4SOIgNode) - TSTALLOC(B4SOITempbPtr, B4SOItempNode, B4SOIbNode) + TSTALLOC(B4SOITemptempPtr, B4SOItempNode, B4SOItempNode); + TSTALLOC(B4SOITempdpPtr, B4SOItempNode, B4SOIdNodePrime); + TSTALLOC(B4SOITempspPtr, B4SOItempNode, B4SOIsNodePrime); + TSTALLOC(B4SOITempgPtr, B4SOItempNode, B4SOIgNode); + TSTALLOC(B4SOITempbPtr, B4SOItempNode, B4SOIbNode); - TSTALLOC(B4SOIGtempPtr, B4SOIgNode, B4SOItempNode) + TSTALLOC(B4SOIGtempPtr, B4SOIgNode, B4SOItempNode); - TSTALLOC(B4SOIDPtempPtr, B4SOIdNodePrime, B4SOItempNode) - TSTALLOC(B4SOISPtempPtr, B4SOIsNodePrime, B4SOItempNode) - TSTALLOC(B4SOIEtempPtr, B4SOIeNode, B4SOItempNode) - TSTALLOC(B4SOIBtempPtr, B4SOIbNode, B4SOItempNode) + TSTALLOC(B4SOIDPtempPtr, B4SOIdNodePrime, B4SOItempNode); + TSTALLOC(B4SOISPtempPtr, B4SOIsNodePrime, B4SOItempNode); + TSTALLOC(B4SOIEtempPtr, B4SOIeNode, B4SOItempNode); + TSTALLOC(B4SOIBtempPtr, B4SOIbNode, B4SOItempNode); if (here->B4SOIbodyMod == 1) { - TSTALLOC(B4SOIPtempPtr, B4SOIpNode, B4SOItempNode) + TSTALLOC(B4SOIPtempPtr, B4SOIpNode, B4SOItempNode); } /* v3.0 */ if (here->B4SOIsoiMod != 0) { /* v3.2 */ - TSTALLOC(B4SOITempePtr, B4SOItempNode, B4SOIeNode) + TSTALLOC(B4SOITempePtr, B4SOItempNode, B4SOIeNode); } } @@ -2548,42 +2548,40 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ /* Don't create any Jacobian entry for pNode */ } else if (here->B4SOIbodyMod == 1) { - TSTALLOC(B4SOIBpPtr, B4SOIbNode, B4SOIpNode) - TSTALLOC(B4SOIPbPtr, B4SOIpNode, B4SOIbNode) - TSTALLOC(B4SOIPpPtr, B4SOIpNode, B4SOIpNode) + TSTALLOC(B4SOIBpPtr, B4SOIbNode, B4SOIpNode); + TSTALLOC(B4SOIPbPtr, B4SOIpNode, B4SOIbNode); + TSTALLOC(B4SOIPpPtr, B4SOIpNode, B4SOIpNode); /* 4.1 for Igb2_agbcp2 */ - TSTALLOC(B4SOIPgPtr , B4SOIpNode, B4SOIgNode) - TSTALLOC(B4SOIGpPtr , B4SOIgNode, B4SOIpNode) + TSTALLOC(B4SOIPgPtr , B4SOIpNode, B4SOIgNode); + TSTALLOC(B4SOIGpPtr , B4SOIgNode, B4SOIpNode); } /* v3.1 added for RF */ if (here->B4SOIrgateMod != 0) - { TSTALLOC(B4SOIGEgePtr, B4SOIgNodeExt, B4SOIgNodeExt) - TSTALLOC(B4SOIGEgPtr, B4SOIgNodeExt, B4SOIgNode) - TSTALLOC(B4SOIGgePtr, B4SOIgNode, B4SOIgNodeExt) - TSTALLOC(B4SOIGEdpPtr, B4SOIgNodeExt, B4SOIdNodePrime) - TSTALLOC(B4SOIGEspPtr, B4SOIgNodeExt, B4SOIsNodePrime) - if (here->B4SOIsoiMod !=2) {/* v3.2 */ - TSTALLOC(B4SOIGEbPtr, B4SOIgNodeExt, B4SOIbNode) - } + { TSTALLOC(B4SOIGEgePtr, B4SOIgNodeExt, B4SOIgNodeExt); + TSTALLOC(B4SOIGEgPtr, B4SOIgNodeExt, B4SOIgNode); + TSTALLOC(B4SOIGgePtr, B4SOIgNode, B4SOIgNodeExt); + TSTALLOC(B4SOIGEdpPtr, B4SOIgNodeExt, B4SOIdNodePrime); + TSTALLOC(B4SOIGEspPtr, B4SOIgNodeExt, B4SOIsNodePrime); + if (here->B4SOIsoiMod !=2) /* v3.2 */ + TSTALLOC(B4SOIGEbPtr, B4SOIgNodeExt, B4SOIbNode); - TSTALLOC(B4SOIGMdpPtr, B4SOIgNodeMid, B4SOIdNodePrime) - TSTALLOC(B4SOIGMgPtr, B4SOIgNodeMid, B4SOIgNode) - TSTALLOC(B4SOIGMgmPtr, B4SOIgNodeMid, B4SOIgNodeMid) - TSTALLOC(B4SOIGMgePtr, B4SOIgNodeMid, B4SOIgNodeExt) - TSTALLOC(B4SOIGMspPtr, B4SOIgNodeMid, B4SOIsNodePrime) - if (here->B4SOIsoiMod !=2) {/* v3.2 */ - TSTALLOC(B4SOIGMbPtr, B4SOIgNodeMid, B4SOIbNode) - } + TSTALLOC(B4SOIGMdpPtr, B4SOIgNodeMid, B4SOIdNodePrime); + TSTALLOC(B4SOIGMgPtr, B4SOIgNodeMid, B4SOIgNode); + TSTALLOC(B4SOIGMgmPtr, B4SOIgNodeMid, B4SOIgNodeMid); + TSTALLOC(B4SOIGMgePtr, B4SOIgNodeMid, B4SOIgNodeExt); + TSTALLOC(B4SOIGMspPtr, B4SOIgNodeMid, B4SOIsNodePrime); + if (here->B4SOIsoiMod !=2) /* v3.2 */ + TSTALLOC(B4SOIGMbPtr, B4SOIgNodeMid, B4SOIbNode); - TSTALLOC(B4SOIGMePtr, B4SOIgNodeMid, B4SOIeNode) - TSTALLOC(B4SOIDPgmPtr, B4SOIdNodePrime, B4SOIgNodeMid) - TSTALLOC(B4SOIGgmPtr, B4SOIgNode, B4SOIgNodeMid) - TSTALLOC(B4SOIGEgmPtr, B4SOIgNodeExt, B4SOIgNodeMid) - TSTALLOC(B4SOISPgmPtr, B4SOIsNodePrime, B4SOIgNodeMid) - TSTALLOC(B4SOIEgmPtr, B4SOIeNode, B4SOIgNodeMid) + TSTALLOC(B4SOIGMePtr, B4SOIgNodeMid, B4SOIeNode); + TSTALLOC(B4SOIDPgmPtr, B4SOIdNodePrime, B4SOIgNodeMid); + TSTALLOC(B4SOIGgmPtr, B4SOIgNode, B4SOIgNodeMid); + TSTALLOC(B4SOIGEgmPtr, B4SOIgNodeExt, B4SOIgNodeMid); + TSTALLOC(B4SOISPgmPtr, B4SOIsNodePrime, B4SOIgNodeMid); + TSTALLOC(B4SOIEgmPtr, B4SOIeNode, B4SOIgNodeMid); } /* v3.1 added for RF end */ @@ -2591,74 +2589,74 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ /* v3.1 */ if (here->B4SOIsoiMod != 2) /* v3.2 */ { - TSTALLOC(B4SOIEbPtr, B4SOIeNode, B4SOIbNode) - TSTALLOC(B4SOIGbPtr, B4SOIgNode, B4SOIbNode) - TSTALLOC(B4SOIDPbPtr, B4SOIdNodePrime, B4SOIbNode) - TSTALLOC(B4SOISPbPtr, B4SOIsNodePrime, B4SOIbNode) - TSTALLOC(B4SOIBePtr, B4SOIbNode, B4SOIeNode) - TSTALLOC(B4SOIBgPtr, B4SOIbNode, B4SOIgNode) - TSTALLOC(B4SOIBdpPtr, B4SOIbNode, B4SOIdNodePrime) - TSTALLOC(B4SOIBspPtr, B4SOIbNode, B4SOIsNodePrime) - TSTALLOC(B4SOIBbPtr, B4SOIbNode, B4SOIbNode) + TSTALLOC(B4SOIEbPtr, B4SOIeNode, B4SOIbNode); + TSTALLOC(B4SOIGbPtr, B4SOIgNode, B4SOIbNode); + TSTALLOC(B4SOIDPbPtr, B4SOIdNodePrime, B4SOIbNode); + TSTALLOC(B4SOISPbPtr, B4SOIsNodePrime, B4SOIbNode); + TSTALLOC(B4SOIBePtr, B4SOIbNode, B4SOIeNode); + TSTALLOC(B4SOIBgPtr, B4SOIbNode, B4SOIgNode); + TSTALLOC(B4SOIBdpPtr, B4SOIbNode, B4SOIdNodePrime); + TSTALLOC(B4SOIBspPtr, B4SOIbNode, B4SOIsNodePrime); + TSTALLOC(B4SOIBbPtr, B4SOIbNode, B4SOIbNode); } /* v3.1 */ - TSTALLOC(B4SOIEgPtr, B4SOIeNode, B4SOIgNode) - TSTALLOC(B4SOIEdpPtr, B4SOIeNode, B4SOIdNodePrime) - TSTALLOC(B4SOIEspPtr, B4SOIeNode, B4SOIsNodePrime) - TSTALLOC(B4SOIGePtr, B4SOIgNode, B4SOIeNode) - TSTALLOC(B4SOIDPePtr, B4SOIdNodePrime, B4SOIeNode) - TSTALLOC(B4SOISPePtr, B4SOIsNodePrime, B4SOIeNode) + TSTALLOC(B4SOIEgPtr, B4SOIeNode, B4SOIgNode); + TSTALLOC(B4SOIEdpPtr, B4SOIeNode, B4SOIdNodePrime); + TSTALLOC(B4SOIEspPtr, B4SOIeNode, B4SOIsNodePrime); + TSTALLOC(B4SOIGePtr, B4SOIgNode, B4SOIeNode); + TSTALLOC(B4SOIDPePtr, B4SOIdNodePrime, B4SOIeNode); + TSTALLOC(B4SOISPePtr, B4SOIsNodePrime, B4SOIeNode); - TSTALLOC(B4SOIEbPtr, B4SOIeNode, B4SOIbNode) - TSTALLOC(B4SOIEePtr, B4SOIeNode, B4SOIeNode) + TSTALLOC(B4SOIEbPtr, B4SOIeNode, B4SOIbNode); + TSTALLOC(B4SOIEePtr, B4SOIeNode, B4SOIeNode); - TSTALLOC(B4SOIGgPtr, B4SOIgNode, B4SOIgNode) - TSTALLOC(B4SOIGdpPtr, B4SOIgNode, B4SOIdNodePrime) - TSTALLOC(B4SOIGspPtr, B4SOIgNode, B4SOIsNodePrime) + TSTALLOC(B4SOIGgPtr, B4SOIgNode, B4SOIgNode); + TSTALLOC(B4SOIGdpPtr, B4SOIgNode, B4SOIdNodePrime); + TSTALLOC(B4SOIGspPtr, B4SOIgNode, B4SOIsNodePrime); - TSTALLOC(B4SOIDPgPtr, B4SOIdNodePrime, B4SOIgNode) - TSTALLOC(B4SOIDPdpPtr, B4SOIdNodePrime, B4SOIdNodePrime) - TSTALLOC(B4SOIDPspPtr, B4SOIdNodePrime, B4SOIsNodePrime) - TSTALLOC(B4SOIDPdPtr, B4SOIdNodePrime, B4SOIdNode) + TSTALLOC(B4SOIDPgPtr, B4SOIdNodePrime, B4SOIgNode); + TSTALLOC(B4SOIDPdpPtr, B4SOIdNodePrime, B4SOIdNodePrime); + TSTALLOC(B4SOIDPspPtr, B4SOIdNodePrime, B4SOIsNodePrime); + TSTALLOC(B4SOIDPdPtr, B4SOIdNodePrime, B4SOIdNode); - TSTALLOC(B4SOISPgPtr, B4SOIsNodePrime, B4SOIgNode) - TSTALLOC(B4SOISPdpPtr, B4SOIsNodePrime, B4SOIdNodePrime) - TSTALLOC(B4SOISPspPtr, B4SOIsNodePrime, B4SOIsNodePrime) - TSTALLOC(B4SOISPsPtr, B4SOIsNodePrime, B4SOIsNode) + TSTALLOC(B4SOISPgPtr, B4SOIsNodePrime, B4SOIgNode); + TSTALLOC(B4SOISPdpPtr, B4SOIsNodePrime, B4SOIdNodePrime); + TSTALLOC(B4SOISPspPtr, B4SOIsNodePrime, B4SOIsNodePrime); + TSTALLOC(B4SOISPsPtr, B4SOIsNodePrime, B4SOIsNode); - TSTALLOC(B4SOIDdPtr, B4SOIdNode, B4SOIdNode) - TSTALLOC(B4SOIDdpPtr, B4SOIdNode, B4SOIdNodePrime) + TSTALLOC(B4SOIDdPtr, B4SOIdNode, B4SOIdNode); + TSTALLOC(B4SOIDdpPtr, B4SOIdNode, B4SOIdNodePrime); - TSTALLOC(B4SOISsPtr, B4SOIsNode, B4SOIsNode) - TSTALLOC(B4SOISspPtr, B4SOIsNode, B4SOIsNodePrime) + TSTALLOC(B4SOISsPtr, B4SOIsNode, B4SOIsNode); + TSTALLOC(B4SOISspPtr, B4SOIsNode, B4SOIsNodePrime); /* v4.0 */ if (here->B4SOIrbodyMod == 1) - { TSTALLOC(B4SOIDPdbPtr, B4SOIdNodePrime, B4SOIdbNode) - TSTALLOC(B4SOISPsbPtr, B4SOIsNodePrime, B4SOIsbNode) + { TSTALLOC(B4SOIDPdbPtr, B4SOIdNodePrime, B4SOIdbNode); + TSTALLOC(B4SOISPsbPtr, B4SOIsNodePrime, B4SOIsbNode); - TSTALLOC(B4SOIDBdpPtr, B4SOIdbNode, B4SOIdNodePrime) - TSTALLOC(B4SOIDBdbPtr, B4SOIdbNode, B4SOIdbNode) - TSTALLOC(B4SOIDBbPtr, B4SOIdbNode, B4SOIbNode) + TSTALLOC(B4SOIDBdpPtr, B4SOIdbNode, B4SOIdNodePrime); + TSTALLOC(B4SOIDBdbPtr, B4SOIdbNode, B4SOIdbNode); + TSTALLOC(B4SOIDBbPtr, B4SOIdbNode, B4SOIbNode); - TSTALLOC(B4SOISBspPtr, B4SOIsbNode, B4SOIsNodePrime) - TSTALLOC(B4SOISBsbPtr, B4SOIsbNode, B4SOIsbNode) - TSTALLOC(B4SOISBbPtr, B4SOIsbNode, B4SOIbNode) + TSTALLOC(B4SOISBspPtr, B4SOIsbNode, B4SOIsNodePrime); + TSTALLOC(B4SOISBsbPtr, B4SOIsbNode, B4SOIsbNode); + TSTALLOC(B4SOISBbPtr, B4SOIsbNode, B4SOIbNode); - TSTALLOC(B4SOIBdbPtr, B4SOIbNode, B4SOIdbNode) - TSTALLOC(B4SOIBsbPtr, B4SOIbNode, B4SOIsbNode) + TSTALLOC(B4SOIBdbPtr, B4SOIbNode, B4SOIdbNode); + TSTALLOC(B4SOIBsbPtr, B4SOIbNode, B4SOIsbNode); } if (model->B4SOIrdsMod) - { TSTALLOC(B4SOIDgPtr, B4SOIdNode, B4SOIgNode) - TSTALLOC(B4SOIDspPtr, B4SOIdNode, B4SOIsNodePrime) - TSTALLOC(B4SOISdpPtr, B4SOIsNode, B4SOIdNodePrime) - TSTALLOC(B4SOISgPtr, B4SOIsNode, B4SOIgNode) + { TSTALLOC(B4SOIDgPtr, B4SOIdNode, B4SOIgNode); + TSTALLOC(B4SOIDspPtr, B4SOIdNode, B4SOIsNodePrime); + TSTALLOC(B4SOISdpPtr, B4SOIsNode, B4SOIdNodePrime); + TSTALLOC(B4SOISgPtr, B4SOIsNode, B4SOIgNode); if (model->B4SOIsoiMod != 2) { - TSTALLOC(B4SOIDbPtr, B4SOIdNode, B4SOIbNode) - TSTALLOC(B4SOISbPtr, B4SOIsNode, B4SOIbNode) + TSTALLOC(B4SOIDbPtr, B4SOIdNode, B4SOIbNode); + TSTALLOC(B4SOISbPtr, B4SOIsNode, B4SOIbNode); } } @@ -2668,25 +2666,25 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ /* here for debugging purpose only */ if (here->B4SOIdebugMod != 0) { - TSTALLOC(B4SOIVbsPtr, B4SOIvbsNode, B4SOIvbsNode) - TSTALLOC(B4SOIIdsPtr, B4SOIidsNode, B4SOIidsNode) - TSTALLOC(B4SOIIcPtr, B4SOIicNode, B4SOIicNode) - TSTALLOC(B4SOIIbsPtr, B4SOIibsNode, B4SOIibsNode) - TSTALLOC(B4SOIIbdPtr, B4SOIibdNode, B4SOIibdNode) - TSTALLOC(B4SOIIiiPtr, B4SOIiiiNode, B4SOIiiiNode) - TSTALLOC(B4SOIIgPtr, B4SOIigNode, B4SOIigNode) - TSTALLOC(B4SOIGiggPtr, B4SOIgiggNode, B4SOIgiggNode) - TSTALLOC(B4SOIGigdPtr, B4SOIgigdNode, B4SOIgigdNode) - TSTALLOC(B4SOIGigbPtr, B4SOIgigbNode, B4SOIgigbNode) - TSTALLOC(B4SOIIgidlPtr, B4SOIigidlNode, B4SOIigidlNode) - TSTALLOC(B4SOIItunPtr, B4SOIitunNode, B4SOIitunNode) - TSTALLOC(B4SOIIbpPtr, B4SOIibpNode, B4SOIibpNode) - TSTALLOC(B4SOICbbPtr, B4SOIcbbNode, B4SOIcbbNode) - TSTALLOC(B4SOICbdPtr, B4SOIcbdNode, B4SOIcbdNode) - TSTALLOC(B4SOICbgPtr, B4SOIcbgNode, B4SOIcbgNode) - TSTALLOC(B4SOIQbfPtr, B4SOIqbfNode, B4SOIqbfNode) - TSTALLOC(B4SOIQjsPtr, B4SOIqjsNode, B4SOIqjsNode) - TSTALLOC(B4SOIQjdPtr, B4SOIqjdNode, B4SOIqjdNode) + TSTALLOC(B4SOIVbsPtr, B4SOIvbsNode, B4SOIvbsNode); + TSTALLOC(B4SOIIdsPtr, B4SOIidsNode, B4SOIidsNode); + TSTALLOC(B4SOIIcPtr, B4SOIicNode, B4SOIicNode); + TSTALLOC(B4SOIIbsPtr, B4SOIibsNode, B4SOIibsNode); + TSTALLOC(B4SOIIbdPtr, B4SOIibdNode, B4SOIibdNode); + TSTALLOC(B4SOIIiiPtr, B4SOIiiiNode, B4SOIiiiNode); + TSTALLOC(B4SOIIgPtr, B4SOIigNode, B4SOIigNode); + TSTALLOC(B4SOIGiggPtr, B4SOIgiggNode, B4SOIgiggNode); + TSTALLOC(B4SOIGigdPtr, B4SOIgigdNode, B4SOIgigdNode); + TSTALLOC(B4SOIGigbPtr, B4SOIgigbNode, B4SOIgigbNode); + TSTALLOC(B4SOIIgidlPtr, B4SOIigidlNode, B4SOIigidlNode); + TSTALLOC(B4SOIItunPtr, B4SOIitunNode, B4SOIitunNode); + TSTALLOC(B4SOIIbpPtr, B4SOIibpNode, B4SOIibpNode); + TSTALLOC(B4SOICbbPtr, B4SOIcbbNode, B4SOIcbbNode); + TSTALLOC(B4SOICbdPtr, B4SOIcbdNode, B4SOIcbdNode); + TSTALLOC(B4SOICbgPtr, B4SOIcbgNode, B4SOIcbgNode); + TSTALLOC(B4SOIQbfPtr, B4SOIqbfNode, B4SOIqbfNode); + TSTALLOC(B4SOIQjsPtr, B4SOIqjsNode, B4SOIqjsNode); + TSTALLOC(B4SOIQjdPtr, B4SOIqjdNode, B4SOIqjdNode); } diff --git a/src/spicelib/devices/cap/Makefile.am b/src/spicelib/devices/cap/Makefile.am index b84dc02b8..e6f184836 100644 --- a/src/spicelib/devices/cap/Makefile.am +++ b/src/spicelib/devices/cap/Makefile.am @@ -29,6 +29,7 @@ libcap_la_SOURCES = \ captemp.c \ captrunc.c + if KLU_WANTED libcap_la_SOURCES += capbindCSC.c endif @@ -41,6 +42,10 @@ if UMFPACK_WANTED libcap_la_SOURCES += capbindCSC.c endif +if KIRCHHOFF_WANTED +libcap_la_SOURCES += capnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/cap/cap.c b/src/spicelib/devices/cap/cap.c index 2da2e549c..370ae170d 100644 --- a/src/spicelib/devices/cap/cap.c +++ b/src/spicelib/devices/cap/cap.c @@ -9,44 +9,51 @@ Modified: September 2003 - Paolo Nenzi #include "capdefs.h" #include "ngspice/suffix.h" -IFparm CAPpTable[] = { /* parameters */ - IOPAP("capacitance", CAP_CAP, IF_REAL, "Device capacitance"), - IOPAP("cap", CAP_CAP, IF_REAL, "Device capacitance"), - IOPAP("c", CAP_CAP, IF_REAL, "Device capacitance"), - IOPAU("ic", CAP_IC, IF_REAL, "Initial capacitor voltage"), - IOPZU("temp", CAP_TEMP, IF_REAL, "Instance operating temperature"), - IOPZ( "dtemp", CAP_DTEMP, IF_REAL, - "Instance temperature difference from the rest of the circuit"), - IOPAU("w", CAP_WIDTH, IF_REAL, "Device width"), - IOPAU("l", CAP_LENGTH, IF_REAL, "Device length"), - IOPU( "m", CAP_M, IF_REAL, "Parallel multiplier"), - IOPU( "scale", CAP_SCALE, IF_REAL, "Scale factor"), - IP( "sens_cap", CAP_CAP_SENS, IF_FLAG, "flag to request sens. WRT cap."), - OP( "i", CAP_CURRENT, IF_REAL, "Device current"), - OP( "p", CAP_POWER, IF_REAL, "Instantaneous device power"), - OPU( "sens_dc", CAP_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), - OPU( "sens_real", CAP_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), - OPU( "sens_imag", CAP_QUEST_SENS_IMAG, IF_REAL, - "dc sens. & imag part of ac sens."), - OPU( "sens_mag", CAP_QUEST_SENS_MAG, IF_REAL, "sensitivity of ac magnitude"), - OPU( "sens_ph", CAP_QUEST_SENS_PH, IF_REAL, "sensitivity of ac phase"), - OPU( "sens_cplx", CAP_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") +IFparm CAPpTable[] = { /* parameters */ + IOPAP("capacitance", CAP_CAP, IF_REAL, "Device capacitance"), + IOPAP("cap", CAP_CAP, IF_REAL, "Device capacitance"), + IOPAP("c", CAP_CAP, IF_REAL, "Device capacitance"), + IOPAU("ic", CAP_IC, IF_REAL, "Initial capacitor voltage"), + IOPZU("temp", CAP_TEMP, IF_REAL, "Instance operating temperature"), + IOPZ( "dtemp", CAP_DTEMP, IF_REAL, + "Instance temperature difference from the rest of the circuit"), + IOPAU("w", CAP_WIDTH, IF_REAL, "Device width"), + IOPAU("l", CAP_LENGTH, IF_REAL, "Device length"), + IOPU( "m", CAP_M, IF_REAL, "Parallel multiplier"), + IOPU( "tc1", CAP_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc2", CAP_TC2, IF_REAL, "Second order temp. coefficient"), + IOPU( "scale", CAP_SCALE, IF_REAL, "Scale factor"), + IP( "sens_cap", CAP_CAP_SENS, IF_FLAG, "flag to request sens. WRT cap."), + OP( "i", CAP_CURRENT, IF_REAL, "Device current"), + OP( "p", CAP_POWER, IF_REAL, "Instantaneous device power"), + OPU( "sens_dc", CAP_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), + OPU( "sens_real", CAP_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), + OPU( "sens_imag", CAP_QUEST_SENS_IMAG, IF_REAL, + "dc sens. & imag part of ac sens."), + OPU( "sens_mag", CAP_QUEST_SENS_MAG, IF_REAL, "sensitivity of ac magnitude"), + OPU( "sens_ph", CAP_QUEST_SENS_PH, IF_REAL, "sensitivity of ac phase"), + OPU( "sens_cplx", CAP_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") }; IFparm CAPmPTable[] = { /* names of model parameters */ - IOPA( "cap", CAP_MOD_CAP, IF_REAL, "Model capacitance"), - IOPA( "cj", CAP_MOD_CJ, IF_REAL, "Bottom Capacitance per area"), - IOPA( "cjsw", CAP_MOD_CJSW, IF_REAL, "Sidewall capacitance per meter"), - IOPX( "defw", CAP_MOD_DEFWIDTH, IF_REAL, "Default width"), - IOPX( "defl", CAP_MOD_DEFLENGTH,IF_REAL, "Default length"), - IOPA( "narrow", CAP_MOD_NARROW, IF_REAL, "width correction factor"), - IOPA( "short", CAP_MOD_SHORT, IF_REAL, "length correction factor"), - IOPA( "tc1", CAP_MOD_TC1, IF_REAL, "First order temp. coefficient"), - IOPA( "tc2", CAP_MOD_TC2, IF_REAL, "Second order temp. coefficient"), - IOPXU("tnom", CAP_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), - IOPA( "di", CAP_MOD_DI, IF_REAL, "Relative dielectric constant"), - IOPA( "thick", CAP_MOD_THICK, IF_REAL, "Insulator thickness"), - IP( "c", CAP_MOD_C, IF_FLAG, "Capacitor model") + IOPA( "cap", CAP_MOD_CAP, IF_REAL, "Model capacitance"), + IOPA( "cj", CAP_MOD_CJ, IF_REAL, "Bottom Capacitance per area"), + IOPR( "cox", CAP_MOD_CJ, IF_REAL, "Bottom Capacitance per area"), + IOPA( "cjsw", CAP_MOD_CJSW, IF_REAL, "Sidewall capacitance per meter"), + IOPR( "capsw", CAP_MOD_CJSW, IF_REAL, "Sidewall capacitance per meter"), + IOPX( "defw", CAP_MOD_DEFWIDTH, IF_REAL, "Default width"), + IOPR( "w", CAP_MOD_DEFWIDTH, IF_REAL, "Default width"), + IOPX( "defl", CAP_MOD_DEFLENGTH,IF_REAL, "Default length"), + IOPR( "l", CAP_MOD_DEFLENGTH,IF_REAL, "Default length"), + IOPA( "narrow", CAP_MOD_NARROW, IF_REAL, "width correction factor"), + IOPA( "short", CAP_MOD_SHORT, IF_REAL, "length correction factor"), + IOPA( "del", CAP_MOD_DEL, IF_REAL, "length and width correction factor"), + IOPA( "tc1", CAP_MOD_TC1, IF_REAL, "First order temp. coefficient"), + IOPA( "tc2", CAP_MOD_TC2, IF_REAL, "Second order temp. coefficient"), + IOPXU("tnom", CAP_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), + IOPA( "di", CAP_MOD_DI, IF_REAL, "Relative dielectric constant"), + IOPA( "thick", CAP_MOD_THICK, IF_REAL, "Insulator thickness"), + IP( "c", CAP_MOD_C, IF_FLAG, "Capacitor model") }; char *CAPnames[] = { diff --git a/src/spicelib/devices/cap/capacld.c b/src/spicelib/devices/cap/capacld.c index 4c1598f96..63a70bd0b 100644 --- a/src/spicelib/devices/cap/capacld.c +++ b/src/spicelib/devices/cap/capacld.c @@ -19,16 +19,17 @@ CAPacLoad(GENmodel *inModel, CKTcircuit *ckt) CAPmodel *model = (CAPmodel*)inModel; double val; double m; + CAPinstance *here; for( ; model != NULL; model = model->CAPnextModel) { - for( here = model->CAPinstances;here != NULL; + for( here = model->CAPinstances; here != NULL; here = here->CAPnextInstance) { - - m = here -> CAPm; - + + m = here->CAPm; + val = ckt->CKTomega * here->CAPcapac; - + *(here->CAPposPosptr +1) += m * val; *(here->CAPnegNegptr +1) += m * val; *(here->CAPposNegptr +1) -= m * val; diff --git a/src/spicelib/devices/cap/capdefs.h b/src/spicelib/devices/cap/capdefs.h index 20e8c2863..9fbc760dd 100644 --- a/src/spicelib/devices/cap/capdefs.h +++ b/src/spicelib/devices/cap/capdefs.h @@ -13,20 +13,20 @@ Modified: September 2003 Paolo Nenzi #include "ngspice/gendefs.h" #include "ngspice/cktdefs.h" - /* structures used to describe capacitors */ +/* structures used to describe capacitors */ /* information to describe each instance */ typedef struct sCAPinstance { struct sCAPmodel *CAPmodPtr; /* backpointer to model */ - struct sCAPinstance *CAPnextInstance; /* pointer to next instance of + struct sCAPinstance *CAPnextInstance; /* pointer to next instance of * current model*/ IFuid CAPname; /* pointer to character string naming this instance */ int CAPstate; /* pointer to start of capacitor state vector */ int CAPposNode; /* number of positive node of capacitor */ int CAPnegNode; /* number of negative node of capacitor */ - + double CAPtemp; /* temperature at which this capacitor operates */ double CAPdtemp; /* delta-temperature of this instance */ double CAPcapac; /* capacitance */ @@ -35,14 +35,16 @@ typedef struct sCAPinstance { double CAPlength; /* length of the capacitor */ double CAPscale; /* scale factor */ double CAPm; /* parallel multiplier */ + double CAPtc1; /* first temperature coefficient of capacitors */ + double CAPtc2; /* second temperature coefficient of capacitors */ - double *CAPposPosptr; /* pointer to sparse matrix diagonal at + double *CAPposPosptr; /* pointer to sparse matrix diagonal at * (positive,positive) */ - double *CAPnegNegptr; /* pointer to sparse matrix diagonal at + double *CAPnegNegptr; /* pointer to sparse matrix diagonal at * (negative,negative) */ - double *CAPposNegptr; /* pointer to sparse matrix offdiagonal at + double *CAPposNegptr; /* pointer to sparse matrix offdiagonal at * (positive,negative) */ - double *CAPnegPosptr; /* pointer to sparse matrix offdiagonal at + double *CAPnegPosptr; /* pointer to sparse matrix offdiagonal at * (negative,positive) */ unsigned CAPcapGiven : 1; /* flag to indicate capacitance was specified */ unsigned CAPicGiven : 1; /* flag to indicate init. cond. was specified */ @@ -51,7 +53,9 @@ typedef struct sCAPinstance { unsigned CAPtempGiven : 1; /* flag to indicate operating temp given */ unsigned CAPdtempGiven : 1; /* flag to indicate delta temp given */ unsigned CAPscaleGiven : 1; /* flag to indicate scale factor given */ - unsigned CAPmGiven : 1; /* flag to indicate parallel multiplier given */ + unsigned CAPmGiven : 1; /* flag to indicate parallel multiplier given */ + unsigned CAPtc1Given : 1; /* flag indicates tc1 was specified */ + unsigned CAPtc2Given : 1; /* flag indicates tc2 was specified */ int CAPsenParmNo; /* parameter # for sensitivity use; set equal to 0 if not a design parameter*/ @@ -62,25 +66,30 @@ typedef struct sCAPinstance { BindElement *CAPnegPosptrStructPtr ; #endif +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } CAPinstance ; #define CAPqcap CAPstate /* charge on the capacitor */ #define CAPccap CAPstate+1 /* current through the capacitor */ #define CAPsensxp CAPstate+2 /* charge sensitivities and their derivatives. - +3 for the derivatives - pointer to the - beginning of the array */ - ++3 for the derivatives - pointer to the +beginning of the array */ + /* data per model */ typedef struct sCAPmodel { /* model structure for a capacitor */ int CAPmodType; /* type index of this device type */ - struct sCAPmodel *CAPnextModel; /* pointer to next possible model in + struct sCAPmodel *CAPnextModel; /* pointer to next possible model in * linked list */ CAPinstance * CAPinstances; /* pointer to list of instances that have this * model */ IFuid CAPmodName; /* pointer to character string naming this model */ - + double CAPtnom; /* temperature at which capacitance measured */ double CAPtempCoeff1; /* linear temperature coefficient */ double CAPtempCoeff2; /* quadratic temperature coefficient */ @@ -91,6 +100,7 @@ typedef struct sCAPmodel { /* model structure for a capacitor */ double CAPdefLength; /* the default length of a capacitor */ double CAPnarrow; /* amount by which width are less than drawn */ double CAPshort; /* amount by which length are less than drawn */ + double CAPdel; /* amount by which length and width are less than drawn */ double CAPdi; /* Relative dielectric constant */ double CAPthick; /* Insulator thickness */ unsigned CAPmCapGiven : 1; /* flag indicates default capacitance given */ @@ -100,12 +110,13 @@ typedef struct sCAPmodel { /* model structure for a capacitor */ unsigned CAPdefLengthGiven : 1; /* flag indicates deafult lenght given */ unsigned CAPnarrowGiven : 1; /* flag indicates narrowing factor given */ unsigned CAPshortGiven : 1; /* flag indicates shortening factor given */ + unsigned CAPdelGiven : 1; /* flag indicates del factor given */ unsigned CAPtnomGiven : 1; /* flag indicates nominal temp. given */ unsigned CAPtc1Given : 1; /* flag indicates tc1 was specified */ unsigned CAPtc2Given : 1; /* flag indicates tc2 was specified */ unsigned CAPdiGiven : 1; /* flag indicates epsilon-ins given */ unsigned CAPthickGiven : 1; /* flags indicates insulator thickness given */ - + } CAPmodel; /* device parameters */ @@ -118,8 +129,10 @@ typedef struct sCAPmodel { /* model structure for a capacitor */ #define CAP_POWER 7 #define CAP_TEMP 8 #define CAP_DTEMP 9 -#define CAP_SCALE 10 +#define CAP_SCALE 10 #define CAP_M 11 +#define CAP_TC1 12 +#define CAP_TC2 13 /* model parameters */ #define CAP_MOD_CJ 101 @@ -128,13 +141,14 @@ typedef struct sCAPmodel { /* model structure for a capacitor */ #define CAP_MOD_C 104 #define CAP_MOD_NARROW 105 #define CAP_MOD_SHORT 106 -#define CAP_MOD_TC1 107 -#define CAP_MOD_TC2 108 -#define CAP_MOD_TNOM 109 -#define CAP_MOD_DI 110 -#define CAP_MOD_THICK 111 -#define CAP_MOD_CAP 112 -#define CAP_MOD_DEFLENGTH 113 +#define CAP_MOD_DEL 107 +#define CAP_MOD_TC1 108 +#define CAP_MOD_TC2 109 +#define CAP_MOD_TNOM 110 +#define CAP_MOD_DI 111 +#define CAP_MOD_THICK 112 +#define CAP_MOD_CAP 113 +#define CAP_MOD_DEFLENGTH 114 /* device questions */ #define CAP_QUEST_SENS_REAL 201 diff --git a/src/spicelib/devices/cap/capext.h b/src/spicelib/devices/cap/capext.h index d06724161..c00584e8a 100644 --- a/src/spicelib/devices/cap/capext.h +++ b/src/spicelib/devices/cap/capext.h @@ -28,3 +28,7 @@ extern int CAPbindCSC (GENmodel*, CKTcircuit*) ; extern int CAPbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int CAPbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int CAPnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/cap/capinit.c b/src/spicelib/devices/cap/capinit.c index 780c81a5a..5d748332c 100644 --- a/src/spicelib/devices/cap/capinit.c +++ b/src/spicelib/devices/cap/capinit.c @@ -72,12 +72,17 @@ SPICEdev CAPinfo = { #endif /* DEVinstSize */ &CAPiSize, /* DEVmodSize */ &CAPmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ CAPbindCSC, /* DEVbindCSCComplex */ CAPbindCSCComplex, /* DEVbindCSCComplexToReal */ CAPbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ CAPnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/cap/capload.c b/src/spicelib/devices/cap/capload.c index da61c7349..bbfc2e4ed 100644 --- a/src/spicelib/devices/cap/capload.c +++ b/src/spicelib/devices/cap/capload.c @@ -13,9 +13,9 @@ Modified: September 2003 Paolo Nenzi int CAPload(GENmodel *inModel, CKTcircuit *ckt) - /* actually load the current capacitance value into the - * sparse matrix previously provided - */ +/* actually load the current capacitance value into the + * sparse matrix previously provided + */ { CAPmodel *model = (CAPmodel*)inModel; CAPinstance *here; @@ -29,46 +29,46 @@ CAPload(GENmodel *inModel, CKTcircuit *ckt) /* check if capacitors are in the circuit or are open circuited */ if(ckt->CKTmode & (MODETRAN|MODEAC|MODETRANOP) ) { /* evaluate device independent analysis conditions */ - cond1= - ( ( (ckt->CKTmode & MODEDC) && + cond1= + ( ( (ckt->CKTmode & MODEDC) && (ckt->CKTmode & MODEINITJCT) ) - || ( ( ckt->CKTmode & MODEUIC) && - ( ckt->CKTmode & MODEINITTRAN) ) ) ; + || ( ( ckt->CKTmode & MODEUIC) && + ( ckt->CKTmode & MODEINITTRAN) ) ) ; /* loop through all the capacitor models */ for( ; model != NULL; model = model->CAPnextModel ) { /* loop through all the instances of the model */ for (here = model->CAPinstances; here != NULL ; here=here->CAPnextInstance) { - - m = here->CAPm; - + + m = here->CAPm; + if(cond1) { vcap = here->CAPinitCond; } else { - vcap = *(ckt->CKTrhsOld+here->CAPposNode) - - *(ckt->CKTrhsOld+here->CAPnegNode) ; + vcap = *(ckt->CKTrhsOld+here->CAPposNode) - + *(ckt->CKTrhsOld+here->CAPnegNode) ; } if(ckt->CKTmode & (MODETRAN | MODEAC)) { #ifndef PREDICTOR if(ckt->CKTmode & MODEINITPRED) { - *(ckt->CKTstate0+here->CAPqcap) = + *(ckt->CKTstate0+here->CAPqcap) = *(ckt->CKTstate1+here->CAPqcap); } else { /* only const caps - no poly's */ #endif /* PREDICTOR */ *(ckt->CKTstate0+here->CAPqcap) = here->CAPcapac * vcap; if((ckt->CKTmode & MODEINITTRAN)) { - *(ckt->CKTstate1+here->CAPqcap) = + *(ckt->CKTstate1+here->CAPqcap) = *(ckt->CKTstate0+here->CAPqcap); } #ifndef PREDICTOR } #endif /* PREDICTOR */ error = NIintegrate(ckt,&geq,&ceq,here->CAPcapac, - here->CAPqcap); + here->CAPqcap); if(error) return(error); if(ckt->CKTmode & MODEINITTRAN) { - *(ckt->CKTstate1+here->CAPccap) = + *(ckt->CKTstate1+here->CAPccap) = *(ckt->CKTstate0+here->CAPccap); } *(here->CAPposPosptr) += m * geq; @@ -77,8 +77,17 @@ CAPload(GENmodel *inModel, CKTcircuit *ckt) *(here->CAPnegPosptr) -= m * geq; *(ckt->CKTrhs+here->CAPposNode) -= m * ceq; *(ckt->CKTrhs+here->CAPnegNode) += m * ceq; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->CAPposNode) += m * *(ckt->CKTstate0+here->CAPccap) ; + *(ckt->CKTfvk+here->CAPnegNode) -= m * *(ckt->CKTstate0+here->CAPccap) ; + + *(here->KCLcurrentPos) = m * *(ckt->CKTstate0+here->CAPccap) ; + *(here->KCLcurrentNeg) = -(m * *(ckt->CKTstate0+here->CAPccap)) ; +#endif + } else - *(ckt->CKTstate0+here->CAPqcap) = here->CAPcapac * vcap; + *(ckt->CKTstate0+here->CAPqcap) = here->CAPcapac * vcap; } } } diff --git a/src/spicelib/devices/cap/capmask.c b/src/spicelib/devices/cap/capmask.c index 498094e3c..8f8c5ebe4 100644 --- a/src/spicelib/devices/cap/capmask.c +++ b/src/spicelib/devices/cap/capmask.c @@ -24,43 +24,46 @@ CAPmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) NG_IGNORE(ckt); switch(which) { - case CAP_MOD_TNOM: - value->rValue = here->CAPtnom-CONSTCtoK; - return(OK); - case CAP_MOD_TC1: - value->rValue = here->CAPtempCoeff1; - return(OK); - case CAP_MOD_TC2: - value->rValue = here->CAPtempCoeff2; - return(OK); - case CAP_MOD_CAP: - value->rValue = here->CAPmCap; - return(OK); - case CAP_MOD_CJ: - value->rValue = here->CAPcj; - return(OK); - case CAP_MOD_CJSW: - value->rValue = here->CAPcjsw; - return(OK); - case CAP_MOD_DEFWIDTH: - value->rValue = here->CAPdefWidth; - return(OK); - case CAP_MOD_DEFLENGTH: - value->rValue = here->CAPdefLength; - return(OK); - case CAP_MOD_NARROW: - value->rValue = here->CAPnarrow; - return(OK); - case CAP_MOD_SHORT: - value->rValue = here->CAPshort; - return(OK); - case CAP_MOD_DI: - value->rValue = here->CAPdi; - return(OK); - case CAP_MOD_THICK: - value->rValue = here->CAPthick; - return(OK); - default: - return(E_BADPARM); + case CAP_MOD_TNOM: + value->rValue = here->CAPtnom-CONSTCtoK; + return(OK); + case CAP_MOD_TC1: + value->rValue = here->CAPtempCoeff1; + return(OK); + case CAP_MOD_TC2: + value->rValue = here->CAPtempCoeff2; + return(OK); + case CAP_MOD_CAP: + value->rValue = here->CAPmCap; + return(OK); + case CAP_MOD_CJ: + value->rValue = here->CAPcj; + return(OK); + case CAP_MOD_CJSW: + value->rValue = here->CAPcjsw; + return(OK); + case CAP_MOD_DEFWIDTH: + value->rValue = here->CAPdefWidth; + return(OK); + case CAP_MOD_DEFLENGTH: + value->rValue = here->CAPdefLength; + return(OK); + case CAP_MOD_NARROW: + value->rValue = here->CAPnarrow; + return(OK); + case CAP_MOD_SHORT: + value->rValue = here->CAPshort; + return(OK); + case CAP_MOD_DEL: + value->rValue = here->CAPdel; + return(OK); + case CAP_MOD_DI: + value->rValue = here->CAPdi; + return(OK); + case CAP_MOD_THICK: + value->rValue = here->CAPthick; + return(OK); + default: + return(E_BADPARM); } } diff --git a/src/spicelib/devices/cap/capmpar.c b/src/spicelib/devices/cap/capmpar.c index 64a37fd70..f7fefd1d9 100644 --- a/src/spicelib/devices/cap/capmpar.c +++ b/src/spicelib/devices/cap/capmpar.c @@ -18,60 +18,64 @@ CAPmParam(int param, IFvalue *value, GENmodel *inModel) { CAPmodel *mod = (CAPmodel*)inModel; switch(param) { - case CAP_MOD_TNOM: - mod->CAPtnom = value->rValue+CONSTCtoK; - mod->CAPtnomGiven = TRUE; - break; - case CAP_MOD_TC1: - mod->CAPtempCoeff1 = value->rValue; - mod->CAPtc1Given = TRUE; - break; - case CAP_MOD_TC2: - mod->CAPtempCoeff2 = value->rValue; - mod->CAPtc2Given = TRUE; - break; - case CAP_MOD_CAP: - mod->CAPmCap = value->rValue; - mod->CAPmCapGiven = TRUE; - break; - case CAP_MOD_CJ : - mod->CAPcj = value->rValue; - mod->CAPcjGiven = TRUE; - break; - case CAP_MOD_CJSW : - mod->CAPcjsw = value->rValue; - mod->CAPcjswGiven = TRUE; - break; - case CAP_MOD_DEFWIDTH: - mod->CAPdefWidth = value->rValue; - mod->CAPdefWidthGiven = TRUE; - break; - case CAP_MOD_DEFLENGTH: - mod->CAPdefLength = value->rValue; - mod->CAPdefLengthGiven = TRUE; - break; - case CAP_MOD_NARROW: - mod->CAPnarrow = value->rValue; - mod->CAPnarrowGiven = TRUE; - break; - case CAP_MOD_SHORT: - mod->CAPshort = value->rValue; - mod->CAPshortGiven = TRUE; - break; - case CAP_MOD_DI: - mod->CAPdi = value->rValue; - mod->CAPdiGiven = TRUE; - break; - case CAP_MOD_THICK: - mod->CAPthick = value->rValue; - mod->CAPthickGiven = TRUE; - break; - case CAP_MOD_C: - /* just being reassured by the user that we are a capacitor */ - /* no-op */ - break; - default: - return(E_BADPARM); + case CAP_MOD_TNOM: + mod->CAPtnom = value->rValue+CONSTCtoK; + mod->CAPtnomGiven = TRUE; + break; + case CAP_MOD_TC1: + mod->CAPtempCoeff1 = value->rValue; + mod->CAPtc1Given = TRUE; + break; + case CAP_MOD_TC2: + mod->CAPtempCoeff2 = value->rValue; + mod->CAPtc2Given = TRUE; + break; + case CAP_MOD_CAP: + mod->CAPmCap = value->rValue; + mod->CAPmCapGiven = TRUE; + break; + case CAP_MOD_CJ : + mod->CAPcj = value->rValue; + mod->CAPcjGiven = TRUE; + break; + case CAP_MOD_CJSW : + mod->CAPcjsw = value->rValue; + mod->CAPcjswGiven = TRUE; + break; + case CAP_MOD_DEFWIDTH: + mod->CAPdefWidth = value->rValue; + mod->CAPdefWidthGiven = TRUE; + break; + case CAP_MOD_DEFLENGTH: + mod->CAPdefLength = value->rValue; + mod->CAPdefLengthGiven = TRUE; + break; + case CAP_MOD_NARROW: + mod->CAPnarrow = value->rValue; + mod->CAPnarrowGiven = TRUE; + break; + case CAP_MOD_SHORT: + mod->CAPshort = value->rValue; + mod->CAPshortGiven = TRUE; + break; + case CAP_MOD_DEL: + mod->CAPdel = value->rValue; + mod->CAPdelGiven = TRUE; + break; + case CAP_MOD_DI: + mod->CAPdi = value->rValue; + mod->CAPdiGiven = TRUE; + break; + case CAP_MOD_THICK: + mod->CAPthick = value->rValue; + mod->CAPthickGiven = TRUE; + break; + case CAP_MOD_C: + /* just being reassured by the user that we are a capacitor */ + /* no-op */ + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/cap/capnode.c b/src/spicelib/devices/cap/capnode.c new file mode 100644 index 000000000..2b37003eb --- /dev/null +++ b/src/spicelib/devices/cap/capnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "capdefs.h" +#include "ngspice/sperror.h" + +int +CAPnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + CAPmodel *model = (CAPmodel *)inModel ; + CAPinstance *here ; + int error ; + + /* loop through all the CAP models */ + for ( ; model != NULL ; model = model->CAPnextModel) + { + /* loop through all the instances of the model */ + for (here = model->CAPinstances ; here != NULL ; here = here->CAPnextInstance) + { + error = CKTmkCurKCL (ckt, here->CAPposNode, &(here->KCLcurrentPos)) ; + error = CKTmkCurKCL (ckt, here->CAPnegNode, &(here->KCLcurrentNeg)) ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/capparam.c b/src/spicelib/devices/cap/capparam.c index 1a11fd5c4..7f7dacafd 100644 --- a/src/spicelib/devices/cap/capparam.c +++ b/src/spicelib/devices/cap/capparam.c @@ -22,45 +22,53 @@ CAPparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) NG_IGNORE(select); switch(param) { - case CAP_CAP: - here->CAPcapac = value->rValue; - if (!here->CAPmGiven) - here->CAPm = 1.0; - here->CAPcapGiven = TRUE; - break; - case CAP_IC: - here->CAPinitCond = value->rValue; - here->CAPicGiven = TRUE; - break; - case CAP_TEMP: - here->CAPtemp = value->rValue + CONSTCtoK; - here->CAPtempGiven = TRUE; - break; - case CAP_DTEMP: - here->CAPdtemp = value->rValue; - here->CAPdtempGiven = TRUE; - break; - case CAP_WIDTH: - here->CAPwidth = value->rValue; - here->CAPwidthGiven = TRUE; - break; - case CAP_LENGTH: - here->CAPlength = value->rValue; - here->CAPlengthGiven = TRUE; - break; - case CAP_M: - here->CAPm = value->rValue; - here->CAPmGiven = TRUE; - break; - case CAP_SCALE: - here->CAPscale = value->rValue; - here->CAPscaleGiven = TRUE; - break; - case CAP_CAP_SENS: - here->CAPsenParmNo = value->iValue; - break; - default: - return(E_BADPARM); + case CAP_CAP: + here->CAPcapac = value->rValue; + if (!here->CAPmGiven) + here->CAPm = 1.0; + here->CAPcapGiven = TRUE; + break; + case CAP_IC: + here->CAPinitCond = value->rValue; + here->CAPicGiven = TRUE; + break; + case CAP_TEMP: + here->CAPtemp = value->rValue + CONSTCtoK; + here->CAPtempGiven = TRUE; + break; + case CAP_DTEMP: + here->CAPdtemp = value->rValue; + here->CAPdtempGiven = TRUE; + break; + case CAP_WIDTH: + here->CAPwidth = value->rValue; + here->CAPwidthGiven = TRUE; + break; + case CAP_LENGTH: + here->CAPlength = value->rValue; + here->CAPlengthGiven = TRUE; + break; + case CAP_M: + here->CAPm = value->rValue; + here->CAPmGiven = TRUE; + break; + case CAP_SCALE: + here->CAPscale = value->rValue; + here->CAPscaleGiven = TRUE; + break; + case CAP_CAP_SENS: + here->CAPsenParmNo = value->iValue; + break; + case CAP_TC1: + here->CAPtc1 = value->rValue; + here->CAPtc1Given = TRUE; + break; + case CAP_TC2: + here->CAPtc2 = value->rValue; + here->CAPtc2Given = TRUE; + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/cap/capsetup.c b/src/spicelib/devices/cap/capsetup.c index dea2a6e3a..f41c85fdf 100644 --- a/src/spicelib/devices/cap/capsetup.c +++ b/src/spicelib/devices/cap/capsetup.c @@ -16,8 +16,8 @@ Modified: September 2003 Paolo Nenzi /*ARGSUSED*/ int CAPsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) - /* load the capacitor structure with those pointers needed later - * for fast matrix loading + /* load the capacitor structure with those pointers needed later + * for fast matrix loading */ { @@ -28,7 +28,7 @@ CAPsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) for( ; model != NULL; model = model->CAPnextModel ) { /*Default Value Processing for Model Parameters */ - if (!model->CAPmCapGiven) { + if (!model->CAPmCapGiven) { model->CAPmCap = 0.0; } if (!model->CAPcjswGiven){ @@ -37,7 +37,7 @@ CAPsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if (!model->CAPdefWidthGiven) { model->CAPdefWidth = 10.e-6; } - if (!model->CAPdefLengthGiven) { + if (!model->CAPdefLengthGiven) { model->CAPdefLength = 0.0; } if (!model->CAPnarrowGiven) { @@ -46,35 +46,44 @@ CAPsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if (!model->CAPshortGiven) { model->CAPshort = 0.0; } + if (!model->CAPdelGiven) { + model->CAPdel = 0.0; + } if (!model->CAPtc1Given) { model->CAPtempCoeff1 = 0.0; } if (!model->CAPtc2Given) { model->CAPtempCoeff2 = 0.0; } - if (!model->CAPtnomGiven) { + if (!model->CAPtnomGiven) { model->CAPtnom = ckt->CKTnomTemp; } - if (!model->CAPdiGiven) { + if (!model->CAPdiGiven) { model->CAPdi = 0.0; } - if (!model->CAPthickGiven) { + if (!model->CAPthickGiven) { model->CAPthick = 0.0; } - - if (!model->CAPcjGiven) { - if((model->CAPthickGiven) - && (model->CAPthick > 0.0)) { - - if (model->CAPdiGiven) - model->CAPcj = (model->CAPdi * CONSTepsZero) / model->CAPthick; - else - model->CAPcj = CONSTepsSiO2 / model->CAPthick; - } else { - model->CAPcj = 0.0; - } + + if (!model->CAPcjGiven) { + if((model->CAPthickGiven) + && (model->CAPthick > 0.0)) { + if (model->CAPdiGiven) + model->CAPcj = (model->CAPdi * CONSTepsZero) / model->CAPthick; + else + model->CAPcj = CONSTepsSiO2 / model->CAPthick; + } else { + model->CAPcj = 0.0; + } } - + + if (model->CAPdelGiven) { + if (!model->CAPnarrowGiven) + model->CAPnarrow = 2 * model->CAPdel; + if (!model->CAPshortGiven) + model->CAPshort = 2 * model->CAPdel; + } + /* loop through all the instances of the model */ for (here = model->CAPinstances; here != NULL ; here=here->CAPnextInstance) { @@ -92,14 +101,14 @@ CAPsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(CAPposPosptr,CAPposNode,CAPposNode) - TSTALLOC(CAPnegNegptr,CAPnegNode,CAPnegNode) - TSTALLOC(CAPposNegptr,CAPposNode,CAPnegNode) - TSTALLOC(CAPnegPosptr,CAPnegNode,CAPposNode) + TSTALLOC(CAPposPosptr,CAPposNode,CAPposNode); + TSTALLOC(CAPnegNegptr,CAPnegNode,CAPnegNode); + TSTALLOC(CAPposNegptr,CAPposNode,CAPnegNode); + TSTALLOC(CAPnegPosptr,CAPnegNode,CAPposNode); } } return(OK); diff --git a/src/spicelib/devices/cap/captemp.c b/src/spicelib/devices/cap/captemp.c index 03f196461..f6dcc371d 100644 --- a/src/spicelib/devices/cap/captemp.c +++ b/src/spicelib/devices/cap/captemp.c @@ -6,9 +6,9 @@ Modified: September 2003 Paolo Nenzi /* */ - /* load the capacitor structure with those pointers needed later - * for fast matrix loading - */ +/* load the capacitor structure with those pointers needed later + * for fast matrix loading + */ #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" @@ -26,6 +26,7 @@ CAPtemp(GENmodel *inModel, CKTcircuit *ckt) CAPinstance *here; double difference; double factor; + double tc1, tc2; /* loop through all the capacitor models */ for( ; model != NULL; model = model->CAPnextModel ) { @@ -35,44 +36,56 @@ CAPtemp(GENmodel *inModel, CKTcircuit *ckt) here=here->CAPnextInstance) { /* Default Value Processing for Capacitor Instance */ - if(!here->CAPtempGiven) { - here->CAPtemp = ckt->CKTtemp; - if(!here->CAPdtempGiven) here->CAPdtemp = 0.0; - } else { /* CAPtempGiven */ - here->CAPdtemp = 0.0; - if (here->CAPdtempGiven) - printf("%s: Instance temperature specified, dtemp ignored\n", - here->CAPname); - } + if(!here->CAPtempGiven) { + here->CAPtemp = ckt->CKTtemp; + if(!here->CAPdtempGiven) here->CAPdtemp = 0.0; + } else { /* CAPtempGiven */ + here->CAPdtemp = 0.0; + if (here->CAPdtempGiven) + printf("%s: Instance temperature specified, dtemp ignored\n", + here->CAPname); + } if (!here->CAPwidthGiven) { here->CAPwidth = model->CAPdefWidth; } - if (!here->CAPscaleGiven) here->CAPscale = 1.0; - if (!here->CAPmGiven) here->CAPm = 1.0; - - if (!here->CAPcapGiven) { /* No instance capacitance given */ - if (!model->CAPmCapGiven){ /* No model capacitange given */ - here->CAPcapac = - model->CAPcj * - (here->CAPwidth - model->CAPnarrow) * - (here->CAPlength - model->CAPshort) + + if (!here->CAPscaleGiven) here->CAPscale = 1.0; + if (!here->CAPmGiven) here->CAPm = 1.0; + + if (!here->CAPcapGiven) { /* No instance capacitance given */ + if (!model->CAPmCapGiven) { /* No model capacitange given */ + here->CAPcapac = + model->CAPcj * + (here->CAPwidth - model->CAPnarrow) * + (here->CAPlength - model->CAPshort) + model->CAPcjsw * 2 * ( (here->CAPlength - model->CAPshort) + (here->CAPwidth - model->CAPnarrow) ); - } else { - here->CAPcapac = model->CAPmCap; - } - } - - difference = (here->CAPtemp + here->CAPdtemp) - model->CAPtnom; - - factor = 1.0 + (model->CAPtempCoeff1)*difference + - (model->CAPtempCoeff2)*difference*difference; - - here->CAPcapac = here->CAPcapac * factor * here->CAPscale; - - } + } else { + here->CAPcapac = model->CAPmCap; + } + } + + difference = (here->CAPtemp + here->CAPdtemp) - model->CAPtnom; + + /* instance parameters tc1 and tc2 will override + model parameters tc1 and tc2 */ + if (here->CAPtc1Given) + tc1 = here->CAPtc1; /* instance */ + else + tc1 = model->CAPtempCoeff1; /* model */ + + if (here->CAPtc2Given) + tc2 = here->CAPtc2; + else + tc2 = model->CAPtempCoeff2; + + factor = 1.0 + tc1*difference + + tc2*difference*difference; + + here->CAPcapac = here->CAPcapac * factor * here->CAPscale; + + } } return(OK); } diff --git a/src/spicelib/devices/cccs/cccs.c b/src/spicelib/devices/cccs/cccs.c index 79560bfb1..a24ccf9f9 100644 --- a/src/spicelib/devices/cccs/cccs.c +++ b/src/spicelib/devices/cccs/cccs.c @@ -12,6 +12,7 @@ Author: 1987 Thomas L. Quarles IFparm CCCSpTable[] = { /* parameters */ IOPU("gain", CCCS_GAIN, IF_REAL ,"Gain of source"), IOPU("control", CCCS_CONTROL, IF_INSTANCE,"Name of controlling source"), + IOP ( "m", CCCS_M, IF_REAL , "Parallel multiplier"), IP("sens_gain",CCCS_GAIN_SENS,IF_FLAG, "flag to request sensitivity WRT gain"), OPU("neg_node", CCCS_NEG_NODE,IF_INTEGER, "Negative node of source"), OPU("pos_node", CCCS_POS_NODE,IF_INTEGER, "Positive node of source"), diff --git a/src/spicelib/devices/cccs/cccsask.c b/src/spicelib/devices/cccs/cccsask.c index 70303f095..bd0d65777 100644 --- a/src/spicelib/devices/cccs/cccsask.c +++ b/src/spicelib/devices/cccs/cccsask.c @@ -36,6 +36,8 @@ CCCSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue * case CCCS_CONTROL: value->uValue = here->CCCScontName; return (OK); + case CCCS_M: + value->rValue = here->CCCSmValue; case CCCS_POS_NODE: value->iValue = here->CCCSposNode; return (OK); diff --git a/src/spicelib/devices/cccs/cccsdefs.h b/src/spicelib/devices/cccs/cccsdefs.h index 18abe5b55..d54733187 100644 --- a/src/spicelib/devices/cccs/cccsdefs.h +++ b/src/spicelib/devices/cccs/cccsdefs.h @@ -30,11 +30,14 @@ typedef struct sCCCSinstance { double CCCScoeff; /* coefficient */ + double CCCSmValue; /* Parallel multiplier */ + double *CCCSposContBrptr; /* pointer to sparse matrix element at *(positive node, control branch eq)*/ double *CCCSnegContBrptr; /* pointer to sparse matrix element at *(negative node, control branch eq)*/ unsigned CCCScoeffGiven :1 ; /* flag to indicate coeff given */ + unsigned CCCSmGiven :1 ; /* flag to indicate multiplier given */ int CCCSsenParmNo; /* parameter # for sensitivity use; set equal to 0 if not a design parameter*/ @@ -67,6 +70,7 @@ typedef struct sCCCSmodel { /* model structure for a source */ #define CCCS_CURRENT 7 #define CCCS_POWER 8 #define CCCS_VOLTS 9 +#define CCCS_M 10 /* model parameters */ diff --git a/src/spicelib/devices/cccs/cccsext.h b/src/spicelib/devices/cccs/cccsext.h index 0a9c32b8b..48f62a719 100644 --- a/src/spicelib/devices/cccs/cccsext.h +++ b/src/spicelib/devices/cccs/cccsext.h @@ -17,7 +17,6 @@ extern void CCCSsPrint(GENmodel*,CKTcircuit*); extern int CCCSsSetup(SENstruct*,GENmodel*); extern int CCCSsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); - #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int CCCSbindCSC (GENmodel*, CKTcircuit*) ; extern int CCCSbindCSCComplex (GENmodel*, CKTcircuit*) ; diff --git a/src/spicelib/devices/cccs/cccsinit.c b/src/spicelib/devices/cccs/cccsinit.c index ba9476245..9b38c8b60 100644 --- a/src/spicelib/devices/cccs/cccsinit.c +++ b/src/spicelib/devices/cccs/cccsinit.c @@ -72,12 +72,17 @@ SPICEdev CCCSinfo = { #endif /* DEVinstSize */ &CCCSiSize, /* DEVmodSize */ &CCCSmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ CCCSbindCSC, /* DEVbindCSCComplex */ CCCSbindCSCComplex, /* DEVbindCSCComplexToReal */ CCCSbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/cccs/cccsload.c b/src/spicelib/devices/cccs/cccsload.c index fcf823c85..39bfec9d0 100644 --- a/src/spicelib/devices/cccs/cccsload.c +++ b/src/spicelib/devices/cccs/cccsload.c @@ -34,6 +34,12 @@ CCCSload(GENmodel *inModel, CKTcircuit *ckt) *(here->CCCSposContBrptr) += here->CCCScoeff ; *(here->CCCSnegContBrptr) -= here->CCCScoeff ; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->CCCSposNode) += here->CCCScoeff * *(ckt->CKTrhsOld+here->CCCScontBranch) ; + *(ckt->CKTfvk+here->CCCSnegNode) -= here->CCCScoeff * *(ckt->CKTrhsOld+here->CCCScontBranch) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/cccs/cccspar.c b/src/spicelib/devices/cccs/cccspar.c index 077d85f0e..4f10557ca 100644 --- a/src/spicelib/devices/cccs/cccspar.c +++ b/src/spicelib/devices/cccs/cccspar.c @@ -23,11 +23,17 @@ CCCSparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) switch(param) { case CCCS_GAIN: here->CCCScoeff = value->rValue; + if (here->CCCSmGiven) + here->CCCScoeff *= here->CCCSmValue; here->CCCScoeffGiven = TRUE; break; case CCCS_CONTROL: here->CCCScontName = value->uValue; break; + case CCCS_M: + here->CCCSmValue = value->rValue; + here->CCCSmGiven = TRUE; + break; case CCCS_GAIN_SENS: here->CCCSsenParmNo = value->iValue; break; diff --git a/src/spicelib/devices/cccs/cccsset.c b/src/spicelib/devices/cccs/cccsset.c index baaeea27e..99087d9eb 100644 --- a/src/spicelib/devices/cccs/cccsset.c +++ b/src/spicelib/devices/cccs/cccsset.c @@ -45,12 +45,12 @@ CCCSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(CCCSposContBrptr,CCCSposNode,CCCScontBranch) - TSTALLOC(CCCSnegContBrptr,CCCSnegNode,CCCScontBranch) + TSTALLOC(CCCSposContBrptr,CCCSposNode,CCCScontBranch); + TSTALLOC(CCCSnegContBrptr,CCCSnegNode,CCCScontBranch); } } return(OK); diff --git a/src/spicelib/devices/ccvs/ccvsinit.c b/src/spicelib/devices/ccvs/ccvsinit.c index a63f2d1dc..47b36b8de 100644 --- a/src/spicelib/devices/ccvs/ccvsinit.c +++ b/src/spicelib/devices/ccvs/ccvsinit.c @@ -73,12 +73,17 @@ SPICEdev CCVSinfo = { #endif /* DEVinstSize */ &CCVSiSize, /* DEVmodSize */ &CCVSmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ CCVSbindCSC, /* DEVbindCSCComplex */ CCVSbindCSCComplex, /* DEVbindCSCComplexToReal */ CCVSbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/ccvs/ccvsload.c b/src/spicelib/devices/ccvs/ccvsload.c index 1c101f81b..53d2b280e 100644 --- a/src/spicelib/devices/ccvs/ccvsload.c +++ b/src/spicelib/devices/ccvs/ccvsload.c @@ -37,6 +37,12 @@ CCVSload(GENmodel *inModel, CKTcircuit *ckt) *(here->CCVSibrPosptr) += 1.0 ; *(here->CCVSibrNegptr) -= 1.0 ; *(here->CCVSibrContBrptr) -= here->CCVScoeff ; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->CCVSposNode) += *(ckt->CKTrhsOld+here->CCVSbranch) ; + *(ckt->CKTfvk+here->CCVSnegNode) -= *(ckt->CKTrhsOld+here->CCVSbranch) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/ccvs/ccvsset.c b/src/spicelib/devices/ccvs/ccvsset.c index 3cedc4fec..5edea19dd 100644 --- a/src/spicelib/devices/ccvs/ccvsset.c +++ b/src/spicelib/devices/ccvs/ccvsset.c @@ -54,15 +54,15 @@ CCVSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(CCVSposIbrptr, CCVSposNode, CCVSbranch) - TSTALLOC(CCVSnegIbrptr, CCVSnegNode, CCVSbranch) - TSTALLOC(CCVSibrNegptr, CCVSbranch, CCVSnegNode) - TSTALLOC(CCVSibrPosptr, CCVSbranch, CCVSposNode) - TSTALLOC(CCVSibrContBrptr, CCVSbranch, CCVScontBranch) + TSTALLOC(CCVSposIbrptr, CCVSposNode, CCVSbranch); + TSTALLOC(CCVSnegIbrptr, CCVSnegNode, CCVSbranch); + TSTALLOC(CCVSibrNegptr, CCVSbranch, CCVSnegNode); + TSTALLOC(CCVSibrPosptr, CCVSbranch, CCVSposNode); + TSTALLOC(CCVSibrContBrptr, CCVSbranch, CCVScontBranch); } } return(OK); diff --git a/src/spicelib/devices/cktcrte.c b/src/spicelib/devices/cktcrte.c index 6a9bb0ddc..549287d9c 100644 --- a/src/spicelib/devices/cktcrte.c +++ b/src/spicelib/devices/cktcrte.c @@ -31,7 +31,7 @@ CKTcrtElt(CKTcircuit *ckt, GENmodel *modPtr, GENinstance **inInstPtr, IFuid name type = modPtr->GENmodType; - error = CKTfndDev(ckt, &type, &instPtr, name, modPtr, NULL); + error = CKTfndDev(ckt, &type, &instPtr, name, modPtr); if (error == OK) { if (inInstPtr) diff --git a/src/spicelib/devices/cktfinddev.c b/src/spicelib/devices/cktfinddev.c index 2db4ff231..19359fe69 100644 --- a/src/spicelib/devices/cktfinddev.c +++ b/src/spicelib/devices/cktfinddev.c @@ -10,91 +10,81 @@ Author: 1985 Thomas L. Quarles #include "string.h" -int -CKTfndDev(CKTcircuit *ckt, int *type, GENinstance **fast, IFuid name, GENmodel *modfast, IFuid modname) +static GENinstance * +find_instance(GENinstance *here, IFuid name) { - GENinstance *here; - GENmodel *mods; + for (; here; here = here->GENnextInstance) + if (here->GENname == name) + return here; - if(fast != NULL && - *fast != NULL) - { - /* already have fast, so nothing much to do just get & set type */ - if (type) - *type = (*fast)->GENmodPtr->GENmodType; - return(OK); - } + return NULL; +} - if(modfast) { - /* have model, just need device */ - mods = modfast; - for (here = mods->GENinstances; here != NULL; here = here->GENnextInstance) { - if (here->GENname == name) { - if (fast != NULL) - *fast = here; + +int +CKTfndDev(CKTcircuit *ckt, int *type, GENinstance **fast, IFuid name, GENmodel *modfast) +{ + GENinstance *here; + GENmodel *mods; + + /* we know the device instance `fast' */ + if (fast && *fast) { + if (type) + *type = (*fast)->GENmodPtr->GENmodType; + return OK; + } + + /* we know the model `modfast', but need to find the device instance */ + if (modfast) { + here = find_instance(modfast->GENinstances, name); + if (here) { + if (fast) + *fast = here; if (type) - *type = mods->GENmodType; + *type = modfast->GENmodType; return OK; - } - } - return E_NODEV; - } + } + return E_NODEV; + } - if (*type >= 0 && *type < DEVmaxnum) { - /* have device type, need to find model & device */ - /* look through all models */ - for (mods = ckt->CKThead[*type]; - mods != NULL ; - mods = mods->GENnextModel) - { - /* and all instances */ - if (modname == NULL || mods->GENmodName == modname) { - for (here = mods->GENinstances; - here != NULL; - here = here->GENnextInstance) - { - if (here->GENname == name) { - if (fast != 0) - *fast = here; - return OK; - } - } - if(mods->GENmodName == modname) { - return E_NODEV; - } - } - } - return E_NOMOD; - } else if (*type == -1) { - /* look through all types (UGH - worst case - take forever) */ - for(*type = 0; *type < DEVmaxnum; (*type)++) { - /* need to find model & device */ - /* look through all models */ - for(mods = ckt->CKThead[*type]; mods != NULL; - mods = mods->GENnextModel) - { + /* we know device `type', but need to find model and device instance */ + if (*type >= 0 && *type < DEVmaxnum) { + /* look through all models */ + for (mods = ckt->CKThead[*type]; mods ; mods = mods->GENnextModel) { /* and all instances */ - if(modname == NULL || mods->GENmodName == modname) { - for (here = mods->GENinstances; - here != NULL; - here = here->GENnextInstance) - { - if (here->GENname == name) { - if(fast != 0) + here = find_instance(mods->GENinstances, name); + if (here) { + if (fast) *fast = here; - return OK; - } - } - if(mods->GENmodName == modname) { - return E_NODEV; - } + return OK; + } + if (mods->GENmodName == NULL) + return E_NODEV; + } + return E_NOMOD; + } + + /* we don't even know `type', search all of them */ + if (*type == -1) { + for (*type = 0; *type < DEVmaxnum; (*type)++) { + /* look through all models */ + for (mods = ckt->CKThead[*type]; mods; mods = mods->GENnextModel) { + /* and all instances */ + here = find_instance(mods->GENinstances, name); + if (here) { + if (fast) + *fast = here; + return OK; + } + if (mods->GENmodName == NULL) + return E_NODEV; } - } - } - *type = -1; - return E_NODEV; - } else - return E_BADPARM; + } + *type = -1; + return E_NODEV; + } + + return E_BADPARM; } diff --git a/src/spicelib/devices/cpl/cplinit.c b/src/spicelib/devices/cpl/cplinit.c index bc59e4503..1465ac11f 100644 --- a/src/spicelib/devices/cpl/cplinit.c +++ b/src/spicelib/devices/cpl/cplinit.c @@ -73,12 +73,17 @@ SPICEdev CPLinfo = { #endif /* DEVinstSize */ &CPLiSize, /* DEVmodSize */ &CPLmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ NULL, /* DEVbindCSCComplex */ NULL, /* DEVbindCSCComplexToReal */ NULL, #endif +#ifdef KIRCHHOFF +/* DEVnodeIsNonLinear */ NULL +#endif + }; SPICEdev * diff --git a/src/spicelib/devices/cpl/cplsetup.c b/src/spicelib/devices/cpl/cplsetup.c index f936bd374..37fc7d732 100644 --- a/src/spicelib/devices/cpl/cplsetup.c +++ b/src/spicelib/devices/cpl/cplsetup.c @@ -185,9 +185,9 @@ CPLsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) noL = here->dimension; diff --git a/src/spicelib/devices/csw/cswinit.c b/src/spicelib/devices/csw/cswinit.c index c084af693..5c35b636f 100644 --- a/src/spicelib/devices/csw/cswinit.c +++ b/src/spicelib/devices/csw/cswinit.c @@ -75,12 +75,17 @@ SPICEdev CSWinfo = { #endif /* DEVinstSize */ &CSWiSize, /* DEVmodSize */ &CSWmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ CSWbindCSC, /* DEVbindCSCComplex */ CSWbindCSCComplex, /* DEVbindCSCComplexToReal */ CSWbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/csw/cswsetup.c b/src/spicelib/devices/csw/cswsetup.c index f2fd38fa5..5794a33d7 100644 --- a/src/spicelib/devices/csw/cswsetup.c +++ b/src/spicelib/devices/csw/cswsetup.c @@ -60,14 +60,14 @@ CSWsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(CSWposPosptr, CSWposNode, CSWposNode) - TSTALLOC(CSWposNegptr, CSWposNode, CSWnegNode) - TSTALLOC(CSWnegPosptr, CSWnegNode, CSWposNode) - TSTALLOC(CSWnegNegptr, CSWnegNode, CSWnegNode) + TSTALLOC(CSWposPosptr, CSWposNode, CSWposNode); + TSTALLOC(CSWposNegptr, CSWposNode, CSWnegNode); + TSTALLOC(CSWnegPosptr, CSWnegNode, CSWposNode); + TSTALLOC(CSWnegNegptr, CSWnegNode, CSWnegNode); } } return(OK); diff --git a/src/spicelib/devices/devsup.c b/src/spicelib/devices/devsup.c index edd1abeda..8d6d4c517 100644 --- a/src/spicelib/devices/devsup.c +++ b/src/spicelib/devices/devsup.c @@ -147,6 +147,379 @@ DEVfetlim(double vnew, double vold, double vto) return(vnew); } +int +ACM_SourceDrainResistances( +int ACM, +double LD, +double LDIF, +double HDIF, +double WMLT, +double w, +double XW, +double RSH, +int drainSquaresGiven, +double RD, +double RDC, +double drainSquares, +int sourceSquaresGiven, +double RS, +double RSC, +double sourceSquares, +double *drainConductance, +double *sourceConductance +) +{ + switch (ACM) + { + case 1: + case 11: + *drainConductance = (LD + LDIF)/(w * WMLT + XW)*RD + RSH*drainSquares + RDC; + *sourceConductance = (LD + LDIF)/(w * WMLT + XW)*RS + RSH*sourceSquares + RSC; + + break; + + case 2: + case 12: + case 3: + case 13: + if (drainSquaresGiven) + *drainConductance = (LD + LDIF)/(w * WMLT + XW)*RD + RSH*drainSquares + RDC; + else + *drainConductance = ((LD + LDIF)*RD + (HDIF * WMLT)*RSH)/(w * WMLT + XW) + RDC; + if (sourceSquaresGiven) + *sourceConductance = (LD + LDIF)/(w * WMLT + XW)*RS + RSH*sourceSquares + RSC; + else + *sourceConductance = ((LD + LDIF)*RS + (HDIF * WMLT)*RSH)/(w * WMLT + XW) + RSC; + + break; + + default: + break; + } +return 0; +} + +/* Area Calculation Method (ACM) for MOS models */ +int +ACM_saturationCurrents( +int ACM, +int CALCACM, +int GEO, +double HDIF, +double WMLT, +double w, +double XW, +double jctTempSatCurDensity, +double jctSidewallTempSatCurDensity, +int drainAreaGiven, +double drainArea, +int drainPerimeterGiven, +double drainPerimeter, +int sourceAreaGiven, +double sourceArea, +int sourcePerimeterGiven, +double sourcePerimeter, +double *DrainSatCurrent, +double *SourceSatCurrent +) +{ + switch (ACM) + { + case 1: + case 11: + drainArea = (w * WMLT + XW) * WMLT; + drainPerimeter = (w * WMLT + XW); + *DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity; + if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14; + + sourceArea = (w * WMLT + XW) * WMLT; + sourcePerimeter = (w * WMLT + XW); + *SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity; + if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14; + + break; + + case 2: + case 12: + if ((ACM == 2) || ((ACM == 12) && (CALCACM == 1))) { + if (!drainAreaGiven) + drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = drainArea * WMLT * WMLT; + if (!drainPerimeterGiven) + drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + drainPerimeter = drainPerimeter * WMLT; + } + *DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity; + if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14; + + if ((ACM == 2) || ((ACM == 12) && (CALCACM == 1))) { + if (!sourceAreaGiven) + sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = sourceArea * WMLT * WMLT; + if (!sourcePerimeterGiven) + sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + sourcePerimeter = sourcePerimeter * WMLT; + } + *SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity; + if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14; + + break; + + case 3: + case 13: + if (!drainAreaGiven) + if ((GEO == 0) || (GEO == 2)) + drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = drainArea * WMLT * WMLT; + if (!drainPerimeterGiven) + if ((GEO == 0) || (GEO == 2)) + drainPerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW); + else + drainPerimeter = 2.0 * (HDIF * WMLT); + else + drainPerimeter = drainPerimeter * WMLT; + *DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity; + if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14; + + if (!sourceAreaGiven) + if ((GEO == 0) || (GEO == 1)) + sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = sourceArea * WMLT * WMLT; + if (!sourcePerimeterGiven) + if ((GEO == 0) || (GEO == 1)) + sourcePerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW); + else + sourcePerimeter = 2.0 * (HDIF * WMLT); + else + sourcePerimeter = sourcePerimeter * WMLT; + *SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity; + if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14; + + break; + + default: + break; + } +return 0; +} + +int +ACM_junctionCapacitances( +int ACM, +int CALCACM, +int GEO, +double HDIF, +double WMLT, +double w, +double XW, +int drainAreaGiven, +double drainArea, +int drainPerimeterGiven, +double drainPerimeter, +int sourceAreaGiven, +double sourceArea, +int sourcePerimeterGiven, +double sourcePerimeter, +double CJ, +double CJSW, +double CJGATE, +double *areaDrainBulkCapacitance, +double *periDrainBulkCapacitance, +double *gateDrainBulkCapacitance, +double *areaSourceBulkCapacitance, +double *periSourceBulkCapacitance, +double *gateSourceBulkCapacitance +) +{ + switch (ACM) + { + case 1: + drainArea = (w * WMLT + XW) * WMLT; + drainPerimeter = (w * WMLT + XW); + *areaDrainBulkCapacitance = drainArea * CJ; + *periDrainBulkCapacitance = drainPerimeter * CJSW; + *gateDrainBulkCapacitance = 0.0; + + sourceArea = (w * WMLT + XW) * WMLT; + sourcePerimeter = (w * WMLT + XW); + *areaSourceBulkCapacitance = sourceArea * CJ; + *periSourceBulkCapacitance = sourcePerimeter * CJSW; + *gateSourceBulkCapacitance = 0.0; + + break; + + case 2: + if (!drainAreaGiven) + drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = drainArea * WMLT * WMLT; + if (!drainPerimeterGiven) + drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + drainPerimeter = drainPerimeter * WMLT; + *areaDrainBulkCapacitance = drainArea * CJ; + if (drainPerimeter > (w * WMLT + XW)) { + *periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW; + *gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periDrainBulkCapacitance = drainPerimeter * CJGATE; + *gateDrainBulkCapacitance = 0.0; + } + + if (!sourceAreaGiven) + sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = sourceArea * WMLT * WMLT; + if (!sourcePerimeterGiven) + sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + sourcePerimeter = sourcePerimeter * WMLT; + *areaSourceBulkCapacitance = sourceArea * CJ; + if (sourcePerimeter > (w * WMLT + XW)) { + *periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW; + *gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periSourceBulkCapacitance = sourcePerimeter * CJGATE; + *gateSourceBulkCapacitance = 0.0; + } + + break; + + case 3: + if (!drainAreaGiven) + if ((GEO == 0) || (GEO == 2)) + drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = drainArea * WMLT * WMLT; + if (!drainPerimeterGiven) + if ((GEO == 0) || (GEO == 2)) + drainPerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW); + else + drainPerimeter = 2.0 * (HDIF * WMLT); + else + drainPerimeter = drainPerimeter * WMLT; + *areaDrainBulkCapacitance = drainArea * CJ; + *periDrainBulkCapacitance = drainPerimeter * CJSW ; + *gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE; + + if (!sourceAreaGiven) + if ((GEO == 0) || (GEO == 1)) + sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = sourceArea * WMLT * WMLT; + if (!sourcePerimeterGiven) + if ((GEO == 0) || (GEO == 1)) + sourcePerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW); + else + sourcePerimeter = 2.0 * (HDIF * WMLT); + else + sourcePerimeter = sourcePerimeter * WMLT; + *areaSourceBulkCapacitance = sourceArea * CJ; + *periSourceBulkCapacitance = sourcePerimeter * CJSW; + *gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE; + + break; + + case 11: + drainArea = (w * WMLT + XW) * WMLT; + drainPerimeter = (w * WMLT + XW); + *areaDrainBulkCapacitance = drainArea * CJ; + *periDrainBulkCapacitance = drainPerimeter * CJSW; + *gateDrainBulkCapacitance = 0.0; + + sourceArea = (w * WMLT + XW) * WMLT; + sourcePerimeter = (w * WMLT + XW); + *areaSourceBulkCapacitance = sourceArea * CJ; + *periSourceBulkCapacitance = sourcePerimeter * CJSW; + *gateSourceBulkCapacitance = 0.0; + + break; + + case 12: + if (CALCACM == 1) { + if (!drainAreaGiven) + drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + drainArea = drainArea * WMLT * WMLT; + if (!drainPerimeterGiven) + drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + drainPerimeter = drainPerimeter * WMLT; + } + *areaDrainBulkCapacitance = drainArea * CJ; + if (drainPerimeter > (w * WMLT + XW)) { + *periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW; + *gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periDrainBulkCapacitance = 0.0; + *gateDrainBulkCapacitance = drainPerimeter * CJGATE; + } + + if (CALCACM == 1) { + if (!sourceAreaGiven) + sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW); + else + sourceArea = sourceArea * WMLT * WMLT; + if (!sourcePerimeterGiven) + sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW); + else + sourcePerimeter = sourcePerimeter * WMLT; + } + *areaSourceBulkCapacitance = sourceArea * CJ; + if (sourcePerimeter > (w * WMLT + XW)) { + *periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW; + *gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periSourceBulkCapacitance = 0.0; + *gateSourceBulkCapacitance = sourcePerimeter * CJGATE; + } + + break; + + case 13: + drainArea = drainArea * WMLT * WMLT; + drainPerimeter = drainPerimeter * WMLT; + *areaDrainBulkCapacitance = drainArea * CJ; + if (drainPerimeter > (w * WMLT + XW)) { + *periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW; + *gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periDrainBulkCapacitance = 0.0; + *gateDrainBulkCapacitance = drainPerimeter * CJGATE; + } + + sourceArea = sourceArea * WMLT * WMLT; + sourcePerimeter = sourcePerimeter * WMLT; + *areaSourceBulkCapacitance = sourceArea * CJ; + if (sourcePerimeter > (w * WMLT + XW)) { + *periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW; + *gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE; + } else { + *periSourceBulkCapacitance = 0.0; + *gateSourceBulkCapacitance = sourcePerimeter * CJGATE; + } + + break; + + default: + break; + } +return 0; +} /* Compute the MOS overlap capacitances as functions of the device * terminal voltages diff --git a/src/spicelib/devices/dio/Makefile.am b/src/spicelib/devices/dio/Makefile.am index e5c6bc32f..4b63ed53e 100644 --- a/src/spicelib/devices/dio/Makefile.am +++ b/src/spicelib/devices/dio/Makefile.am @@ -46,6 +46,10 @@ if UMFPACK_WANTED libdio_la_SOURCES += diobindCSC.c endif +if KIRCHHOFF_WANTED +libdio_la_SOURCES += dionode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index ca92b1e7b..6ee411373 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -152,6 +152,12 @@ typedef struct sDIOinstance { BindElement *DIOposPrimePosPrimeStructPtr ; #endif +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; + double *KCLcurrentPosPrime ; +#endif + } DIOinstance ; #define DIOsenGeq DIOsens /* stores the perturbed values of geq */ diff --git a/src/spicelib/devices/dio/dioext.h b/src/spicelib/devices/dio/dioext.h index 4923c78a5..5460217a5 100644 --- a/src/spicelib/devices/dio/dioext.h +++ b/src/spicelib/devices/dio/dioext.h @@ -34,3 +34,7 @@ extern int DIObindCSC (GENmodel*, CKTcircuit*) ; extern int DIObindCSCComplex (GENmodel*, CKTcircuit*) ; extern int DIObindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int DIOnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/dio/dioinit.c b/src/spicelib/devices/dio/dioinit.c index 5dfaa573b..acbe76dd5 100644 --- a/src/spicelib/devices/dio/dioinit.c +++ b/src/spicelib/devices/dio/dioinit.c @@ -74,12 +74,17 @@ SPICEdev DIOinfo = { #endif /* DEVinstSize */ &DIOiSize, /* DEVmodSize */ &DIOmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ DIObindCSC, /* DEVbindCSCComplex */ DIObindCSCComplex, /* DEVbindCSCComplexToReal */ DIObindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ DIOnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index 801de12da..b6d69eb35 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -272,8 +272,11 @@ next1: if (model->DIOsatSWCurGiven) { /* sidewall current */ if( (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { ikf_area_m = here->DIOforwardKneeCurrent; sqrt_ikf = sqrt(cd/ikf_area_m); - gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf + cd/ikf_area_m) + ckt->CKTgmin*vd; - cd = cd/(1+sqrt_ikf) + ckt->CKTgmin; + gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf + cd/ikf_area_m) + ckt->CKTgmin; + cd = cd/(1+sqrt_ikf) + ckt->CKTgmin*vd; + } else { + gd = gd + ckt->CKTgmin; + cd = cd + ckt->CKTgmin*vd; } } else { /* limit reverse */ @@ -281,8 +284,11 @@ next1: if (model->DIOsatSWCurGiven) { /* sidewall current */ if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { ikr_area_m = here->DIOreverseKneeCurrent; sqrt_ikr = sqrt(cd/(-ikr_area_m)); - gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m) + ckt->CKTgmin*vd; - cd = cd/(1+sqrt_ikr) + ckt->CKTgmin; + gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m) + ckt->CKTgmin; + cd = cd/(1+sqrt_ikr) + ckt->CKTgmin*vd; + } else { + gd = gd + ckt->CKTgmin; + cd = cd + ckt->CKTgmin*vd; } } @@ -402,6 +408,17 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd; *(here->DIOnegPosPrimePtr) -= gd; *(here->DIOposPrimePosPtr) -= gspr; *(here->DIOposPrimeNegPtr) -= gd; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->DIOposNode) += gspr * (*(ckt->CKTrhsOld+here->DIOposNode) - *(ckt->CKTrhsOld+here->DIOposPrimeNode)) ; + *(ckt->CKTfvk+here->DIOnegNode) -= cd ; + *(ckt->CKTfvk+here->DIOposPrimeNode) += (cd - gspr * (*(ckt->CKTrhsOld+here->DIOposNode) - *(ckt->CKTrhsOld+here->DIOposPrimeNode))) ; + + *(here->KCLcurrentPos) = gspr * (*(ckt->CKTrhsOld+here->DIOposNode) - *(ckt->CKTrhsOld+here->DIOposPrimeNode)) ; + *(here->KCLcurrentNeg) = -cd ; + *(here->KCLcurrentPosPrime) = cd - gspr * (*(ckt->CKTrhsOld+here->DIOposNode) - *(ckt->CKTrhsOld+here->DIOposPrimeNode)) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/dio/dionode.c b/src/spicelib/devices/dio/dionode.c new file mode 100644 index 000000000..5c5aef3fc --- /dev/null +++ b/src/spicelib/devices/dio/dionode.c @@ -0,0 +1,33 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "diodefs.h" +#include "ngspice/sperror.h" + +int +DIOnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + DIOmodel *model = (DIOmodel *)inModel ; + DIOinstance *here ; + int error ; + + /* loop through all the DIO models */ + for ( ; model != NULL ; model = model->DIOnextModel) + { + /* loop through all the instances of the model */ + for (here = model->DIOinstances ; here != NULL ; here = here->DIOnextInstance) + { + ckt->CKTnodeIsLinear [here->DIOposPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->DIOnegNode] = 0 ; + + error = CKTmkCurKCL (ckt, here->DIOposNode, &(here->KCLcurrentPos)) ; + error = CKTmkCurKCL (ckt, here->DIOnegNode, &(here->KCLcurrentNeg)) ; + error = CKTmkCurKCL (ckt, here->DIOposPrimeNode, &(here->KCLcurrentPosPrime)) ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index 8f39b2933..fc0d37b16 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -219,17 +219,17 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(DIOposPosPrimePtr,DIOposNode,DIOposPrimeNode) - TSTALLOC(DIOnegPosPrimePtr,DIOnegNode,DIOposPrimeNode) - TSTALLOC(DIOposPrimePosPtr,DIOposPrimeNode,DIOposNode) - TSTALLOC(DIOposPrimeNegPtr,DIOposPrimeNode,DIOnegNode) - TSTALLOC(DIOposPosPtr,DIOposNode,DIOposNode) - TSTALLOC(DIOnegNegPtr,DIOnegNode,DIOnegNode) - TSTALLOC(DIOposPrimePosPrimePtr,DIOposPrimeNode,DIOposPrimeNode) + TSTALLOC(DIOposPosPrimePtr,DIOposNode,DIOposPrimeNode); + TSTALLOC(DIOnegPosPrimePtr,DIOnegNode,DIOposPrimeNode); + TSTALLOC(DIOposPrimePosPtr,DIOposPrimeNode,DIOposNode); + TSTALLOC(DIOposPrimeNegPtr,DIOposPrimeNode,DIOnegNode); + TSTALLOC(DIOposPosPtr,DIOposNode,DIOposNode); + TSTALLOC(DIOnegNegPtr,DIOnegNode,DIOnegNode); + TSTALLOC(DIOposPrimePosPrimePtr,DIOposPrimeNode,DIOposPrimeNode); } } return(OK); diff --git a/src/spicelib/devices/dio/diosload.c b/src/spicelib/devices/dio/diosload.c index 032358dc7..2a173501e 100644 --- a/src/spicelib/devices/dio/diosload.c +++ b/src/spicelib/devices/dio/diosload.c @@ -56,10 +56,10 @@ DIOsLoad(GENmodel *inModel, CKTcircuit *ckt) #ifdef SENSDEBUG printf("DIOsenload\n"); - fprintf(file,"DIOsenload\n"); - fprintf(file,"CKTtime = %.5e\n",ckt->CKTtime); - fprintf(file,"CKTorder = %.5e\n",ckt->CKTorder); - fprintf(file,"tag0 = %.5e tag1 = %.5e\n",tag0,tag1); + fprintf(stdout,"DIOsenload\n"); + fprintf(stdout,"CKTtime = %.5e\n",ckt->CKTtime); + fprintf(stdout,"CKTorder = %.5e\n",ckt->CKTorder); + fprintf(stdout,"tag0 = %.5e tag1 = %.5e\n",tag0,tag1); #endif /* SENSDEBUG */ /* loop through all the diode models */ @@ -70,7 +70,7 @@ DIOsLoad(GENmodel *inModel, CKTcircuit *ckt) here=here->DIOnextInstance) { #ifdef SENSDEBUG - fprintf(file,"pos = %d , posprm = %d ,neg = %d, senparmno = %d\n", + fprintf(stdout,"pos = %d , posprm = %d ,neg = %d, senparmno = %d\n", here->DIOposNode ,here->DIOposPrimeNode,here->DIOnegNode, here->DIOsenParmNo); #endif /* SENSDEBUG */ @@ -94,7 +94,7 @@ DIOsLoad(GENmodel *inModel, CKTcircuit *ckt) #ifdef SENSDEBUG - fprintf(file,"cd0 = %.7e \n",cd0); + fprintf(stdout,"cd0 = %.7e \n",cd0); #endif /* SENSDEBUG */ A0 = here->DIOarea; @@ -120,9 +120,9 @@ DIOsLoad(GENmodel *inModel, CKTcircuit *ckt) *(here->DIOdphidp) = DqdDp; #ifdef SENSDEBUG - fprintf(file,"cd0 = %.7e ,cd = %.7e,DcdDp=%.7e\n", cd0,cd,DcdDp); - fprintf(file,"cspr0 = %.7e ,DcsprDp=%.7e\n", cspr0,DcsprDp); - fprintf(file,"qd0 = %.7e ,qd = %.7e,DqdDp=%.7e\n", qd0,qd,DqdDp); + fprintf(stdout,"cd0 = %.7e ,cd = %.7e,DcdDp=%.7e\n", cd0,cd,DcdDp); + fprintf(stdout,"cspr0 = %.7e ,DcsprDp=%.7e\n", cspr0,DcsprDp); + fprintf(stdout,"qd0 = %.7e ,qd = %.7e,DqdDp=%.7e\n", qd0,qd,DqdDp); #endif /* SENSDEBUG */ if((info->SENmode == TRANSEN) && @@ -152,12 +152,12 @@ next: 2*(iparmno - 1) + 1); #ifdef SENSDEBUG - fprintf(file,"\n iparmno=%d,Osxp=%.7e\n",iparmno,Osxp); + fprintf(stdout,"\n iparmno=%d,Osxp=%.7e\n",iparmno,Osxp); #endif /* SENSDEBUG */ if(iparmno == here->DIOsenParmNo) Osxp = Osxp - tag0 * DqdDp; #ifdef SENSDEBUG - fprintf(file,"Osxp=%.7e\n",Osxp); + fprintf(stdout,"Osxp=%.7e\n",Osxp); #endif /* SENSDEBUG */ *(info->SEN_RHS[here->DIOposPrimeNode] + iparmno) += Osxp; diff --git a/src/spicelib/devices/hfet1/Makefile.am b/src/spicelib/devices/hfet1/Makefile.am index d8ec0b15f..2aa17f47f 100644 --- a/src/spicelib/devices/hfet1/Makefile.am +++ b/src/spicelib/devices/hfet1/Makefile.am @@ -37,6 +37,10 @@ if UMFPACK_WANTED libhfet_la_SOURCES += hfetbindCSC.c endif +if KIRCHHOFF_WANTED +libhfet_la_SOURCES += hfetnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/hfet1/hfetext.h b/src/spicelib/devices/hfet1/hfetext.h index 221a092b8..ef8e455e9 100644 --- a/src/spicelib/devices/hfet1/hfetext.h +++ b/src/spicelib/devices/hfet1/hfetext.h @@ -24,3 +24,7 @@ extern int HFETAbindCSC (GENmodel*, CKTcircuit*) ; extern int HFETAbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int HFETAbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int HFETAnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/hfet1/hfetinit.c b/src/spicelib/devices/hfet1/hfetinit.c index c82a865d4..04e53c55a 100644 --- a/src/spicelib/devices/hfet1/hfetinit.c +++ b/src/spicelib/devices/hfet1/hfetinit.c @@ -73,12 +73,17 @@ SPICEdev HFETAinfo = { #endif /* DEVinstSize */ &HFETAiSize, /* DEVmodSize */ &HFETAmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ HFETAbindCSC, /* DEVbindCSCComplex */ HFETAbindCSC, /* DEVbindCSCComplexToReal */ HFETAbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ HFETAnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/hfet1/hfetnode.c b/src/spicelib/devices/hfet1/hfetnode.c new file mode 100644 index 000000000..90c5612ab --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetnode.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "hfetdefs.h" +#include "ngspice/sperror.h" + +int +HFETAnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + HFETAmodel *model = (HFETAmodel *)inModel ; + HFETAinstance *here ; + + /* loop through all the HFETA models */ + for ( ; model != NULL ; model = model->HFETAnextModel) + { + /* loop through all the instances of the model */ + for (here = model->HFETAinstances ; here != NULL ; here = here->HFETAnextInstance) + { + ckt->CKTnodeIsLinear [here->HFETAsourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFETAdrainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFETAgatePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFETAdrainPrmPrmNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFETAsourcePrmPrmNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/hfet1/hfetsetup.c b/src/spicelib/devices/hfet1/hfetsetup.c index 26c0174a4..410ccedfd 100644 --- a/src/spicelib/devices/hfet1/hfetsetup.c +++ b/src/spicelib/devices/hfet1/hfetsetup.c @@ -363,38 +363,38 @@ HFETAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(HFETAdrainDrainPrimePtr,HFETAdrainNode,HFETAdrainPrimeNode) - TSTALLOC(HFETAgatePrimeDrainPrimePtr,HFETAgatePrimeNode,HFETAdrainPrimeNode) - TSTALLOC(HFETAgatePrimeSourcePrimePtr,HFETAgatePrimeNode,HFETAsourcePrimeNode) - TSTALLOC(HFETAsourceSourcePrimePtr,HFETAsourceNode,HFETAsourcePrimeNode) - TSTALLOC(HFETAdrainPrimeDrainPtr,HFETAdrainPrimeNode,HFETAdrainNode) - TSTALLOC(HFETAdrainPrimeGatePrimePtr,HFETAdrainPrimeNode,HFETAgatePrimeNode) - TSTALLOC(HFETAdrainPrimeSourcePrimePtr,HFETAdrainPrimeNode,HFETAsourcePrimeNode) - TSTALLOC(HFETAsourcePrimeGatePrimePtr,HFETAsourcePrimeNode,HFETAgatePrimeNode) - TSTALLOC(HFETAsourcePrimeSourcePtr,HFETAsourcePrimeNode,HFETAsourceNode) - TSTALLOC(HFETAsourcePrimeDrainPrimePtr,HFETAsourcePrimeNode,HFETAdrainPrimeNode) - TSTALLOC(HFETAdrainDrainPtr,HFETAdrainNode,HFETAdrainNode) - TSTALLOC(HFETAgatePrimeGatePrimePtr,HFETAgatePrimeNode,HFETAgatePrimeNode) - TSTALLOC(HFETAsourceSourcePtr,HFETAsourceNode,HFETAsourceNode) - TSTALLOC(HFETAdrainPrimeDrainPrimePtr,HFETAdrainPrimeNode,HFETAdrainPrimeNode) - TSTALLOC(HFETAsourcePrimeSourcePrimePtr,HFETAsourcePrimeNode,HFETAsourcePrimeNode) - TSTALLOC(HFETAdrainPrimeDrainPrmPrmPtr,HFETAdrainPrimeNode,HFETAdrainPrmPrmNode) - TSTALLOC(HFETAdrainPrmPrmDrainPrimePtr,HFETAdrainPrmPrmNode,HFETAdrainPrimeNode) - TSTALLOC(HFETAdrainPrmPrmGatePrimePtr,HFETAdrainPrmPrmNode,HFETAgatePrimeNode) - TSTALLOC(HFETAgatePrimeDrainPrmPrmPtr,HFETAgatePrimeNode,HFETAdrainPrmPrmNode) - TSTALLOC(HFETAdrainPrmPrmDrainPrmPrmPtr,HFETAdrainPrmPrmNode,HFETAdrainPrmPrmNode) - TSTALLOC(HFETAsourcePrimeSourcePrmPrmPtr,HFETAsourcePrimeNode,HFETAsourcePrmPrmNode) - TSTALLOC(HFETAsourcePrmPrmSourcePrimePtr,HFETAsourcePrmPrmNode,HFETAsourcePrimeNode) - TSTALLOC(HFETAsourcePrmPrmGatePrimePtr,HFETAsourcePrmPrmNode,HFETAgatePrimeNode) - TSTALLOC(HFETAgatePrimeSourcePrmPrmPtr,HFETAgatePrimeNode,HFETAsourcePrmPrmNode) - TSTALLOC(HFETAsourcePrmPrmSourcePrmPrmPtr,HFETAsourcePrmPrmNode,HFETAsourcePrmPrmNode) - TSTALLOC(HFETAgateGatePtr,HFETAgateNode,HFETAgateNode) - TSTALLOC(HFETAgateGatePrimePtr,HFETAgateNode,HFETAgatePrimeNode) - TSTALLOC(HFETAgatePrimeGatePtr,HFETAgatePrimeNode,HFETAgateNode) + TSTALLOC(HFETAdrainDrainPrimePtr,HFETAdrainNode,HFETAdrainPrimeNode); + TSTALLOC(HFETAgatePrimeDrainPrimePtr,HFETAgatePrimeNode,HFETAdrainPrimeNode); + TSTALLOC(HFETAgatePrimeSourcePrimePtr,HFETAgatePrimeNode,HFETAsourcePrimeNode); + TSTALLOC(HFETAsourceSourcePrimePtr,HFETAsourceNode,HFETAsourcePrimeNode); + TSTALLOC(HFETAdrainPrimeDrainPtr,HFETAdrainPrimeNode,HFETAdrainNode); + TSTALLOC(HFETAdrainPrimeGatePrimePtr,HFETAdrainPrimeNode,HFETAgatePrimeNode); + TSTALLOC(HFETAdrainPrimeSourcePrimePtr,HFETAdrainPrimeNode,HFETAsourcePrimeNode); + TSTALLOC(HFETAsourcePrimeGatePrimePtr,HFETAsourcePrimeNode,HFETAgatePrimeNode); + TSTALLOC(HFETAsourcePrimeSourcePtr,HFETAsourcePrimeNode,HFETAsourceNode); + TSTALLOC(HFETAsourcePrimeDrainPrimePtr,HFETAsourcePrimeNode,HFETAdrainPrimeNode); + TSTALLOC(HFETAdrainDrainPtr,HFETAdrainNode,HFETAdrainNode); + TSTALLOC(HFETAgatePrimeGatePrimePtr,HFETAgatePrimeNode,HFETAgatePrimeNode); + TSTALLOC(HFETAsourceSourcePtr,HFETAsourceNode,HFETAsourceNode); + TSTALLOC(HFETAdrainPrimeDrainPrimePtr,HFETAdrainPrimeNode,HFETAdrainPrimeNode); + TSTALLOC(HFETAsourcePrimeSourcePrimePtr,HFETAsourcePrimeNode,HFETAsourcePrimeNode); + TSTALLOC(HFETAdrainPrimeDrainPrmPrmPtr,HFETAdrainPrimeNode,HFETAdrainPrmPrmNode); + TSTALLOC(HFETAdrainPrmPrmDrainPrimePtr,HFETAdrainPrmPrmNode,HFETAdrainPrimeNode); + TSTALLOC(HFETAdrainPrmPrmGatePrimePtr,HFETAdrainPrmPrmNode,HFETAgatePrimeNode); + TSTALLOC(HFETAgatePrimeDrainPrmPrmPtr,HFETAgatePrimeNode,HFETAdrainPrmPrmNode); + TSTALLOC(HFETAdrainPrmPrmDrainPrmPrmPtr,HFETAdrainPrmPrmNode,HFETAdrainPrmPrmNode); + TSTALLOC(HFETAsourcePrimeSourcePrmPrmPtr,HFETAsourcePrimeNode,HFETAsourcePrmPrmNode); + TSTALLOC(HFETAsourcePrmPrmSourcePrimePtr,HFETAsourcePrmPrmNode,HFETAsourcePrimeNode); + TSTALLOC(HFETAsourcePrmPrmGatePrimePtr,HFETAsourcePrmPrmNode,HFETAgatePrimeNode); + TSTALLOC(HFETAgatePrimeSourcePrmPrmPtr,HFETAgatePrimeNode,HFETAsourcePrmPrmNode); + TSTALLOC(HFETAsourcePrmPrmSourcePrmPrmPtr,HFETAsourcePrmPrmNode,HFETAsourcePrmPrmNode); + TSTALLOC(HFETAgateGatePtr,HFETAgateNode,HFETAgateNode); + TSTALLOC(HFETAgateGatePrimePtr,HFETAgateNode,HFETAgatePrimeNode); + TSTALLOC(HFETAgatePrimeGatePtr,HFETAgatePrimeNode,HFETAgateNode); } } return(OK); diff --git a/src/spicelib/devices/hfet2/Makefile.am b/src/spicelib/devices/hfet2/Makefile.am index 32910a47f..b34379c89 100644 --- a/src/spicelib/devices/hfet2/Makefile.am +++ b/src/spicelib/devices/hfet2/Makefile.am @@ -37,6 +37,10 @@ if UMFPACK_WANTED libhfet2_la_SOURCES += hfet2bindCSC.c endif +if KIRCHHOFF_WANTED +libhfet2_la_SOURCES += hfet2node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/hfet2/hfet2ext.h b/src/spicelib/devices/hfet2/hfet2ext.h index f2f8d98e7..e8b335bf0 100644 --- a/src/spicelib/devices/hfet2/hfet2ext.h +++ b/src/spicelib/devices/hfet2/hfet2ext.h @@ -3,24 +3,28 @@ Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reser Author: Trond Ytterdal **********/ -extern int HFET2acLoad(GENmodel*,CKTcircuit*); -extern int HFET2ask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); -extern int HFET2delete(GENmodel*,IFuid,GENinstance**); +extern int HFET2acLoad(GENmodel*,CKTcircuit*); +extern int HFET2ask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); +extern int HFET2delete(GENmodel*,IFuid,GENinstance**); extern void HFET2destroy(GENmodel**); -extern int HFET2getic(GENmodel*,CKTcircuit*); -extern int HFET2load(GENmodel*,CKTcircuit*); -extern int HFET2mAsk(CKTcircuit*,GENmodel*,int,IFvalue*); -extern int HFET2mDelete(GENmodel**,IFuid,GENmodel*); -extern int HFET2mParam(int,IFvalue*,GENmodel*); -extern int HFET2param(int,IFvalue*,GENinstance*,IFvalue*); -extern int HFET2pzLoad(GENmodel*, CKTcircuit*, SPcomplex*); -extern int HFET2setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); -extern int HFET2temp(GENmodel*,CKTcircuit*); -extern int HFET2trunc(GENmodel*,CKTcircuit*,double*); -extern int HFET2unsetup( GENmodel*,CKTcircuit*); +extern int HFET2getic(GENmodel*,CKTcircuit*); +extern int HFET2load(GENmodel*,CKTcircuit*); +extern int HFET2mAsk(CKTcircuit*,GENmodel*,int,IFvalue*); +extern int HFET2mDelete(GENmodel**,IFuid,GENmodel*); +extern int HFET2mParam(int,IFvalue*,GENmodel*); +extern int HFET2param(int,IFvalue*,GENinstance*,IFvalue*); +extern int HFET2pzLoad(GENmodel*, CKTcircuit*, SPcomplex*); +extern int HFET2setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int HFET2temp(GENmodel*,CKTcircuit*); +extern int HFET2trunc(GENmodel*,CKTcircuit*,double*); +extern int HFET2unsetup( GENmodel*,CKTcircuit*); #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int HFET2bindCSC (GENmodel*, CKTcircuit*) ; extern int HFET2bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int HFET2bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int HFET2nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/hfet2/hfet2init.c b/src/spicelib/devices/hfet2/hfet2init.c index 04ad87d72..5cb05f336 100644 --- a/src/spicelib/devices/hfet2/hfet2init.c +++ b/src/spicelib/devices/hfet2/hfet2init.c @@ -73,12 +73,17 @@ SPICEdev HFET2info = { #endif /* DEVinstSize */ &HFET2iSize, /* DEVmodSize */ &HFET2mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ HFET2bindCSC, /* DEVbindCSCComplex */ HFET2bindCSCComplex, /* DEVbindCSCComplexToReal */ HFET2bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ HFET2nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/hfet2/hfet2node.c b/src/spicelib/devices/hfet2/hfet2node.c new file mode 100644 index 000000000..30bcaeec4 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2node.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "hfet2defs.h" +#include "ngspice/sperror.h" + +int +HFET2nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + HFET2model *model = (HFET2model *)inModel ; + HFET2instance *here ; + + /* loop through all the HFET2 models */ + for ( ; model != NULL ; model = model->HFET2nextModel) + { + /* loop through all the instances of the model */ + for (here = model->HFET2instances ; here != NULL ; here = here->HFET2nextInstance) + { + ckt->CKTnodeIsLinear [here->HFET2sourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFET2drainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->HFET2gateNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/hfet2/hfet2setup.c b/src/spicelib/devices/hfet2/hfet2setup.c index 72bf46852..96044f989 100644 --- a/src/spicelib/devices/hfet2/hfet2setup.c +++ b/src/spicelib/devices/hfet2/hfet2setup.c @@ -177,25 +177,25 @@ int HFET2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(HFET2drainDrainPrimePtr,HFET2drainNode,HFET2drainPrimeNode) - TSTALLOC(HFET2gateDrainPrimePtr,HFET2gateNode,HFET2drainPrimeNode) - TSTALLOC(HFET2gateSourcePrimePtr,HFET2gateNode,HFET2sourcePrimeNode) - TSTALLOC(HFET2sourceSourcePrimePtr,HFET2sourceNode,HFET2sourcePrimeNode) - TSTALLOC(HFET2drainPrimeDrainPtr,HFET2drainPrimeNode,HFET2drainNode) - TSTALLOC(HFET2drainPrimeGatePtr,HFET2drainPrimeNode,HFET2gateNode) - TSTALLOC(HFET2drainPriHFET2ourcePrimePtr,HFET2drainPrimeNode,HFET2sourcePrimeNode) - TSTALLOC(HFET2sourcePrimeGatePtr,HFET2sourcePrimeNode,HFET2gateNode) - TSTALLOC(HFET2sourcePriHFET2ourcePtr,HFET2sourcePrimeNode,HFET2sourceNode) - TSTALLOC(HFET2sourcePrimeDrainPrimePtr,HFET2sourcePrimeNode,HFET2drainPrimeNode) - TSTALLOC(HFET2drainDrainPtr,HFET2drainNode,HFET2drainNode) - TSTALLOC(HFET2gateGatePtr,HFET2gateNode,HFET2gateNode) - TSTALLOC(HFET2sourceSourcePtr,HFET2sourceNode,HFET2sourceNode) - TSTALLOC(HFET2drainPrimeDrainPrimePtr,HFET2drainPrimeNode,HFET2drainPrimeNode) - TSTALLOC(HFET2sourcePriHFET2ourcePrimePtr,HFET2sourcePrimeNode,HFET2sourcePrimeNode) + TSTALLOC(HFET2drainDrainPrimePtr,HFET2drainNode,HFET2drainPrimeNode); + TSTALLOC(HFET2gateDrainPrimePtr,HFET2gateNode,HFET2drainPrimeNode); + TSTALLOC(HFET2gateSourcePrimePtr,HFET2gateNode,HFET2sourcePrimeNode); + TSTALLOC(HFET2sourceSourcePrimePtr,HFET2sourceNode,HFET2sourcePrimeNode); + TSTALLOC(HFET2drainPrimeDrainPtr,HFET2drainPrimeNode,HFET2drainNode); + TSTALLOC(HFET2drainPrimeGatePtr,HFET2drainPrimeNode,HFET2gateNode); + TSTALLOC(HFET2drainPriHFET2ourcePrimePtr,HFET2drainPrimeNode,HFET2sourcePrimeNode); + TSTALLOC(HFET2sourcePrimeGatePtr,HFET2sourcePrimeNode,HFET2gateNode); + TSTALLOC(HFET2sourcePriHFET2ourcePtr,HFET2sourcePrimeNode,HFET2sourceNode); + TSTALLOC(HFET2sourcePrimeDrainPrimePtr,HFET2sourcePrimeNode,HFET2drainPrimeNode); + TSTALLOC(HFET2drainDrainPtr,HFET2drainNode,HFET2drainNode); + TSTALLOC(HFET2gateGatePtr,HFET2gateNode,HFET2gateNode); + TSTALLOC(HFET2sourceSourcePtr,HFET2sourceNode,HFET2sourceNode); + TSTALLOC(HFET2drainPrimeDrainPrimePtr,HFET2drainPrimeNode,HFET2drainPrimeNode); + TSTALLOC(HFET2sourcePriHFET2ourcePrimePtr,HFET2sourcePrimeNode,HFET2sourcePrimeNode); } } diff --git a/src/spicelib/devices/hisim2/Makefile.am b/src/spicelib/devices/hisim2/Makefile.am index 85bb5c429..4343bb43a 100644 --- a/src/spicelib/devices/hisim2/Makefile.am +++ b/src/spicelib/devices/hisim2/Makefile.am @@ -4,31 +4,32 @@ EXTRA_DIST = noinst_LTLIBRARIES = libhisim2.la -libhisim2_la_SOURCES = hisim2.h \ - hsm2.c \ - hsm2acld.c \ - hsm2ask.c \ - hsm2cvtest.c \ - hsm2def.h \ - hsm2del.c \ - hsm2dest.c \ - hsm2eval.c \ - hsm2evalenv.h \ - hsm2ext.h \ - hsm2getic.c \ - hsm2init.c \ - hsm2init.h \ - hsm2itf.h \ - hsm2ld.c \ - hsm2mask.c \ - hsm2mdel.c \ - hsm2mpar.c \ - hsm2noi.c \ - hsm2par.c \ - hsm2pzld.c \ - hsm2set.c \ - hsm2temp.c \ - hsm2trunc.c +libhisim2_la_SOURCES = \ + hisim2.h \ + hsm2.c \ + hsm2acld.c \ + hsm2ask.c \ + hsm2cvtest.c \ + hsm2def.h \ + hsm2del.c \ + hsm2dest.c \ + hsm2eval.c \ + hsm2evalenv.h \ + hsm2ext.h \ + hsm2getic.c \ + hsm2init.c \ + hsm2init.h \ + hsm2itf.h \ + hsm2ld.c \ + hsm2mask.c \ + hsm2mdel.c \ + hsm2mpar.c \ + hsm2noi.c \ + hsm2par.c \ + hsm2pzld.c \ + hsm2set.c \ + hsm2temp.c \ + hsm2trunc.c if KLU_WANTED @@ -43,6 +44,10 @@ if UMFPACK_WANTED libhisim2_la_SOURCES += hsm2bindCSC.c endif +if KIRCHHOFF_WANTED +libhisim2_la_SOURCES += hsm2node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/hisim2/hsm2ext.h b/src/spicelib/devices/hisim2/hsm2ext.h index 35bd423d5..381067aee 100644 --- a/src/spicelib/devices/hisim2/hsm2ext.h +++ b/src/spicelib/devices/hisim2/hsm2ext.h @@ -43,3 +43,7 @@ extern int HSM2bindCSC (GENmodel*, CKTcircuit*) ; extern int HSM2bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int HSM2bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int HSM2nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/hisim2/hsm2init.c b/src/spicelib/devices/hisim2/hsm2init.c index bb859e9c7..1662a5d07 100644 --- a/src/spicelib/devices/hisim2/hsm2init.c +++ b/src/spicelib/devices/hisim2/hsm2init.c @@ -71,12 +71,17 @@ SPICEdev HSM2info = { #endif /* DEVinstSize */ &HSM2iSize, /* DEVmodSize */ &HSM2mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ HSM2bindCSC, /* DEVbindCSCComplex */ HSM2bindCSCComplex, /* DEVbindCSCComplexToReal */ HSM2bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ HSM2nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/hisim2/hsm2node.c b/src/spicelib/devices/hisim2/hsm2node.c new file mode 100644 index 000000000..9dd8c8ca1 --- /dev/null +++ b/src/spicelib/devices/hisim2/hsm2node.c @@ -0,0 +1,32 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "hsm2def.h" +#include "ngspice/sperror.h" + +int +HSM2nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + HSM2model *model = (HSM2model *)inModel ; + HSM2instance *here ; + + /* loop through all the HSM2 models */ + for ( ; model != NULL ; model = model->HSM2nextModel) + { + /* loop through all the instances of the model */ + for (here = model->HSM2instances ; here != NULL ; here = here->HSM2nextInstance) + { + ckt->CKTnodeIsLinear [here->HSM2dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSM2sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSM2gNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSM2dbNode] = 0 ; + ckt->CKTnodeIsLinear [here->HSM2bNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSM2sbNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/hisim2/hsm2set.c b/src/spicelib/devices/hisim2/hsm2set.c index 6e6b214c0..7b7412a5c 100644 --- a/src/spicelib/devices/hisim2/hsm2set.c +++ b/src/spicelib/devices/hisim2/hsm2set.c @@ -87,7 +87,7 @@ int HSM2setup( } else { if (model->HSM2_version != 270) { model->HSM2_version = 270; /* default 270 */ - printf(" 270 is only available for VERSION. \n"); + printf(" 270 is the only available VERSION. \n"); printf(" 270 is selected for VERSION. (default) \n"); } else { printf(" %d is selected for VERSION \n", (int)model->HSM2_version); @@ -774,33 +774,33 @@ int HSM2setup( /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ +do { if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(HSM2DPbpPtr, HSM2dNodePrime, HSM2bNodePrime) - TSTALLOC(HSM2SPbpPtr, HSM2sNodePrime, HSM2bNodePrime) - TSTALLOC(HSM2GPbpPtr, HSM2gNodePrime, HSM2bNodePrime) + TSTALLOC(HSM2DPbpPtr, HSM2dNodePrime, HSM2bNodePrime); + TSTALLOC(HSM2SPbpPtr, HSM2sNodePrime, HSM2bNodePrime); + TSTALLOC(HSM2GPbpPtr, HSM2gNodePrime, HSM2bNodePrime); - TSTALLOC(HSM2BPdpPtr, HSM2bNodePrime, HSM2dNodePrime) - TSTALLOC(HSM2BPspPtr, HSM2bNodePrime, HSM2sNodePrime) - TSTALLOC(HSM2BPgpPtr, HSM2bNodePrime, HSM2gNodePrime) - TSTALLOC(HSM2BPbpPtr, HSM2bNodePrime, HSM2bNodePrime) + TSTALLOC(HSM2BPdpPtr, HSM2bNodePrime, HSM2dNodePrime); + TSTALLOC(HSM2BPspPtr, HSM2bNodePrime, HSM2sNodePrime); + TSTALLOC(HSM2BPgpPtr, HSM2bNodePrime, HSM2gNodePrime); + TSTALLOC(HSM2BPbpPtr, HSM2bNodePrime, HSM2bNodePrime); - TSTALLOC(HSM2DdPtr, HSM2dNode, HSM2dNode) - TSTALLOC(HSM2GPgpPtr, HSM2gNodePrime, HSM2gNodePrime) - TSTALLOC(HSM2SsPtr, HSM2sNode, HSM2sNode) - TSTALLOC(HSM2DPdpPtr, HSM2dNodePrime, HSM2dNodePrime) - TSTALLOC(HSM2SPspPtr, HSM2sNodePrime, HSM2sNodePrime) - TSTALLOC(HSM2DdpPtr, HSM2dNode, HSM2dNodePrime) - TSTALLOC(HSM2GPdpPtr, HSM2gNodePrime, HSM2dNodePrime) - TSTALLOC(HSM2GPspPtr, HSM2gNodePrime, HSM2sNodePrime) - TSTALLOC(HSM2SspPtr, HSM2sNode, HSM2sNodePrime) - TSTALLOC(HSM2DPspPtr, HSM2dNodePrime, HSM2sNodePrime) - TSTALLOC(HSM2DPdPtr, HSM2dNodePrime, HSM2dNode) - TSTALLOC(HSM2DPgpPtr, HSM2dNodePrime, HSM2gNodePrime) - TSTALLOC(HSM2SPgpPtr, HSM2sNodePrime, HSM2gNodePrime) - TSTALLOC(HSM2SPsPtr, HSM2sNodePrime, HSM2sNode) + TSTALLOC(HSM2DdPtr, HSM2dNode, HSM2dNode); + TSTALLOC(HSM2GPgpPtr, HSM2gNodePrime, HSM2gNodePrime); + TSTALLOC(HSM2SsPtr, HSM2sNode, HSM2sNode); + TSTALLOC(HSM2DPdpPtr, HSM2dNodePrime, HSM2dNodePrime); + TSTALLOC(HSM2SPspPtr, HSM2sNodePrime, HSM2sNodePrime); + TSTALLOC(HSM2DdpPtr, HSM2dNode, HSM2dNodePrime); + TSTALLOC(HSM2GPdpPtr, HSM2gNodePrime, HSM2dNodePrime); + TSTALLOC(HSM2GPspPtr, HSM2gNodePrime, HSM2sNodePrime); + TSTALLOC(HSM2SspPtr, HSM2sNode, HSM2sNodePrime); + TSTALLOC(HSM2DPspPtr, HSM2dNodePrime, HSM2sNodePrime); + TSTALLOC(HSM2DPdPtr, HSM2dNodePrime, HSM2dNode); + TSTALLOC(HSM2DPgpPtr, HSM2dNodePrime, HSM2gNodePrime); + TSTALLOC(HSM2SPgpPtr, HSM2sNodePrime, HSM2gNodePrime); + TSTALLOC(HSM2SPsPtr, HSM2sNodePrime, HSM2sNode); TSTALLOC(HSM2SPdpPtr, HSM2sNodePrime, HSM2dNodePrime); if ( here->HSM2_corg == 1 ) { diff --git a/src/spicelib/devices/hisimhv1/Makefile.am b/src/spicelib/devices/hisimhv1/Makefile.am index 6a5dfe079..36d3f1aa8 100644 --- a/src/spicelib/devices/hisimhv1/Makefile.am +++ b/src/spicelib/devices/hisimhv1/Makefile.am @@ -2,34 +2,40 @@ noinst_LTLIBRARIES = libhisimhv1.la -libhisimhv1_la_SOURCES = hisimhv.h \ - hsmhv.c \ - hsmhvacld.c \ - hsmhvask.c \ - hsmhvcvtest.c \ - hsmhvdef.h \ - hsmhvdel.c \ - hsmhvdest.c \ - hsmhveval.c \ - hsmhveval_qover.h \ - hsmhvevalenv.h \ - hsmhvext.h \ - hsmhvgetic.c \ - hsmhvinit.c \ - hsmhvinit.h \ - hsmhvitf.h \ - hsmhvld.c \ - hsmhvld_info_eval.h \ - hsmhvmask.c \ - hsmhvmdel.c \ - hsmhvmpar.c \ - hsmhvnoi.c \ - hsmhvpar.c \ - hsmhvpzld.c \ - hsmhvset.c \ - hsmhvtemp.c \ - hsmhvtemp_eval.h \ - hsmhvtrunc.c +libhisimhv1_la_SOURCES = \ + hisimhv.h \ + hsmhv.c \ + hsmhvacld.c \ + hsmhvask.c \ + hsmhvcvtest.c \ + hsmhvdef.h \ + hsmhvdel.c \ + hsmhvdest.c \ + hsmhveval.c \ + hsmhveval_qover.h \ + hsmhvevalenv.h \ + hsmhvext.h \ + hsmhvgetic.c \ + hsmhvinit.c \ + hsmhvinit.h \ + hsmhvitf.h \ + hsmhvld.c \ + hsmhvld_info_eval.h \ + hsmhvmask.c \ + hsmhvmdel.c \ + hsmhvmpar.c \ + hsmhvnoi.c \ + hsmhvpar.c \ + hsmhvpzld.c \ + hsmhvset.c \ + hsmhvtemp.c \ + hsmhvtemp_eval.h \ + hsmhvtrunc.c + + +if KIRCHHOFF_WANTED +libhisimhv1_la_SOURCES += hsmhvnode.c +endif if KLU_WANTED diff --git a/src/spicelib/devices/hisimhv1/hsmhvext.h b/src/spicelib/devices/hisimhv1/hsmhvext.h index f19a4a0ab..5af945e33 100644 --- a/src/spicelib/devices/hisimhv1/hsmhvext.h +++ b/src/spicelib/devices/hisimhv1/hsmhvext.h @@ -43,3 +43,7 @@ extern int HSMHVbindCSC (GENmodel*, CKTcircuit*); extern int HSMHVbindCSCComplex (GENmodel*, CKTcircuit*); extern int HSMHVbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int HSMHVnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/hisimhv1/hsmhvinit.c b/src/spicelib/devices/hisimhv1/hsmhvinit.c index 5843f3f24..307f3608c 100644 --- a/src/spicelib/devices/hisimhv1/hsmhvinit.c +++ b/src/spicelib/devices/hisimhv1/hsmhvinit.c @@ -71,12 +71,17 @@ SPICEdev HSMHVinfo = { #endif /* DEVinstSize */ &HSMHViSize, /* DEVmodSize */ &HSMHVmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ HSMHVbindCSC, /* DEVbindCSCComplex */ HSMHVbindCSCComplex, /* DEVbindCSCComplexToReal */ HSMHVbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ HSMHVnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/hisimhv1/hsmhvnode.c b/src/spicelib/devices/hisimhv1/hsmhvnode.c new file mode 100644 index 000000000..ded982f1c --- /dev/null +++ b/src/spicelib/devices/hisimhv1/hsmhvnode.c @@ -0,0 +1,35 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "hsmhvdef.h" +#include "ngspice/sperror.h" + +int +HSMHVnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + HSMHVmodel *model = (HSMHVmodel *)inModel ; + HSMHVinstance *here ; + + /* loop through all the HSMHV models */ + for ( ; model != NULL ; model = model->HSMHVnextModel) + { + /* loop through all the instances of the model */ + for (here = model->HSMHVinstances ; here != NULL ; here = here->HSMHVnextInstance) + { + ckt->CKTnodeIsLinear [here->HSMHVdNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVsNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVgNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVdbNode] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVbNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVsbNode] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVtempNode] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVqiNode] = 0 ; + ckt->CKTnodeIsLinear [here->HSMHVqbNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/hisimhv1/hsmhvset.c b/src/spicelib/devices/hisimhv1/hsmhvset.c index f8d6cf8fe..a3bd0db4e 100644 --- a/src/spicelib/devices/hisimhv1/hsmhvset.c +++ b/src/spicelib/devices/hisimhv1/hsmhvset.c @@ -79,7 +79,7 @@ int HSMHVsetup( } else { if (strcmp(model->HSMHV_version,"1.23") != 0 ) { model->HSMHV_version = "1.23" ; - printf(" 1.23 is only available for VERSION. \n"); + printf(" 1.23 is the only available VERSION. \n"); printf(" 1.23 is selected for VERSION. (default) \n"); } else { printf(" %s is selected for VERSION \n", model->HSMHV_version); @@ -938,35 +938,35 @@ int HSMHVsetup( /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ +do { if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(HSMHVDPbpPtr, HSMHVdNodePrime, HSMHVbNodePrime) - TSTALLOC(HSMHVSPbpPtr, HSMHVsNodePrime, HSMHVbNodePrime) - TSTALLOC(HSMHVGPbpPtr, HSMHVgNodePrime, HSMHVbNodePrime) + TSTALLOC(HSMHVDPbpPtr, HSMHVdNodePrime, HSMHVbNodePrime); + TSTALLOC(HSMHVSPbpPtr, HSMHVsNodePrime, HSMHVbNodePrime); + TSTALLOC(HSMHVGPbpPtr, HSMHVgNodePrime, HSMHVbNodePrime); - TSTALLOC(HSMHVBPdPtr, HSMHVbNodePrime, HSMHVdNode) - TSTALLOC(HSMHVBPsPtr, HSMHVbNodePrime, HSMHVsNode) - TSTALLOC(HSMHVBPdpPtr, HSMHVbNodePrime, HSMHVdNodePrime) - TSTALLOC(HSMHVBPspPtr, HSMHVbNodePrime, HSMHVsNodePrime) - TSTALLOC(HSMHVBPgpPtr, HSMHVbNodePrime, HSMHVgNodePrime) - TSTALLOC(HSMHVBPbpPtr, HSMHVbNodePrime, HSMHVbNodePrime) + TSTALLOC(HSMHVBPdPtr, HSMHVbNodePrime, HSMHVdNode); + TSTALLOC(HSMHVBPsPtr, HSMHVbNodePrime, HSMHVsNode); + TSTALLOC(HSMHVBPdpPtr, HSMHVbNodePrime, HSMHVdNodePrime); + TSTALLOC(HSMHVBPspPtr, HSMHVbNodePrime, HSMHVsNodePrime); + TSTALLOC(HSMHVBPgpPtr, HSMHVbNodePrime, HSMHVgNodePrime); + TSTALLOC(HSMHVBPbpPtr, HSMHVbNodePrime, HSMHVbNodePrime); - TSTALLOC(HSMHVDdPtr, HSMHVdNode, HSMHVdNode) - TSTALLOC(HSMHVGPgpPtr, HSMHVgNodePrime, HSMHVgNodePrime) - TSTALLOC(HSMHVSsPtr, HSMHVsNode, HSMHVsNode) - TSTALLOC(HSMHVDPdpPtr, HSMHVdNodePrime, HSMHVdNodePrime) - TSTALLOC(HSMHVSPspPtr, HSMHVsNodePrime, HSMHVsNodePrime) - TSTALLOC(HSMHVDdpPtr, HSMHVdNode, HSMHVdNodePrime) - TSTALLOC(HSMHVGPdpPtr, HSMHVgNodePrime, HSMHVdNodePrime) - TSTALLOC(HSMHVGPspPtr, HSMHVgNodePrime, HSMHVsNodePrime) - TSTALLOC(HSMHVSspPtr, HSMHVsNode, HSMHVsNodePrime) - TSTALLOC(HSMHVDPspPtr, HSMHVdNodePrime, HSMHVsNodePrime) - TSTALLOC(HSMHVDPdPtr, HSMHVdNodePrime, HSMHVdNode) - TSTALLOC(HSMHVDPgpPtr, HSMHVdNodePrime, HSMHVgNodePrime) - TSTALLOC(HSMHVSPgpPtr, HSMHVsNodePrime, HSMHVgNodePrime) - TSTALLOC(HSMHVSPsPtr, HSMHVsNodePrime, HSMHVsNode) + TSTALLOC(HSMHVDdPtr, HSMHVdNode, HSMHVdNode); + TSTALLOC(HSMHVGPgpPtr, HSMHVgNodePrime, HSMHVgNodePrime); + TSTALLOC(HSMHVSsPtr, HSMHVsNode, HSMHVsNode); + TSTALLOC(HSMHVDPdpPtr, HSMHVdNodePrime, HSMHVdNodePrime); + TSTALLOC(HSMHVSPspPtr, HSMHVsNodePrime, HSMHVsNodePrime); + TSTALLOC(HSMHVDdpPtr, HSMHVdNode, HSMHVdNodePrime); + TSTALLOC(HSMHVGPdpPtr, HSMHVgNodePrime, HSMHVdNodePrime); + TSTALLOC(HSMHVGPspPtr, HSMHVgNodePrime, HSMHVsNodePrime); + TSTALLOC(HSMHVSspPtr, HSMHVsNode, HSMHVsNodePrime); + TSTALLOC(HSMHVDPspPtr, HSMHVdNodePrime, HSMHVsNodePrime); + TSTALLOC(HSMHVDPdPtr, HSMHVdNodePrime, HSMHVdNode); + TSTALLOC(HSMHVDPgpPtr, HSMHVdNodePrime, HSMHVgNodePrime); + TSTALLOC(HSMHVSPgpPtr, HSMHVsNodePrime, HSMHVgNodePrime); + TSTALLOC(HSMHVSPsPtr, HSMHVsNodePrime, HSMHVsNode); TSTALLOC(HSMHVSPdpPtr, HSMHVsNodePrime, HSMHVdNodePrime); TSTALLOC(HSMHVGgPtr, HSMHVgNode, HSMHVgNode); @@ -1019,44 +1019,44 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ TSTALLOC(HSMHVSPsubPtr, HSMHVsNodePrime, HSMHVsubNode); } if ( here->HSMHV_coselfheat > 0 ) { /* self heating */ - TSTALLOC(HSMHVTemptempPtr, HSMHVtempNode, HSMHVtempNode) - TSTALLOC(HSMHVTempdPtr, HSMHVtempNode, HSMHVdNode) - TSTALLOC(HSMHVTempdpPtr, HSMHVtempNode, HSMHVdNodePrime) - TSTALLOC(HSMHVTempsPtr, HSMHVtempNode, HSMHVsNode) - TSTALLOC(HSMHVTempspPtr, HSMHVtempNode, HSMHVsNodePrime) - TSTALLOC(HSMHVDPtempPtr, HSMHVdNodePrime, HSMHVtempNode) - TSTALLOC(HSMHVSPtempPtr, HSMHVsNodePrime, HSMHVtempNode) + TSTALLOC(HSMHVTemptempPtr, HSMHVtempNode, HSMHVtempNode); + TSTALLOC(HSMHVTempdPtr, HSMHVtempNode, HSMHVdNode); + TSTALLOC(HSMHVTempdpPtr, HSMHVtempNode, HSMHVdNodePrime); + TSTALLOC(HSMHVTempsPtr, HSMHVtempNode, HSMHVsNode); + TSTALLOC(HSMHVTempspPtr, HSMHVtempNode, HSMHVsNodePrime); + TSTALLOC(HSMHVDPtempPtr, HSMHVdNodePrime, HSMHVtempNode); + TSTALLOC(HSMHVSPtempPtr, HSMHVsNodePrime, HSMHVtempNode); - TSTALLOC(HSMHVTempgpPtr, HSMHVtempNode, HSMHVgNodePrime) - TSTALLOC(HSMHVTempbpPtr, HSMHVtempNode, HSMHVbNodePrime) + TSTALLOC(HSMHVTempgpPtr, HSMHVtempNode, HSMHVgNodePrime); + TSTALLOC(HSMHVTempbpPtr, HSMHVtempNode, HSMHVbNodePrime); - TSTALLOC(HSMHVGPtempPtr, HSMHVgNodePrime, HSMHVtempNode) - TSTALLOC(HSMHVBPtempPtr, HSMHVbNodePrime, HSMHVtempNode) + TSTALLOC(HSMHVGPtempPtr, HSMHVgNodePrime, HSMHVtempNode); + TSTALLOC(HSMHVBPtempPtr, HSMHVbNodePrime, HSMHVtempNode); - TSTALLOC(HSMHVDBtempPtr, HSMHVdbNode, HSMHVtempNode) - TSTALLOC(HSMHVSBtempPtr, HSMHVsbNode, HSMHVtempNode) + TSTALLOC(HSMHVDBtempPtr, HSMHVdbNode, HSMHVtempNode); + TSTALLOC(HSMHVSBtempPtr, HSMHVsbNode, HSMHVtempNode); TSTALLOC(HSMHVDtempPtr, HSMHVdNode, HSMHVtempNode); TSTALLOC(HSMHVStempPtr, HSMHVsNode, HSMHVtempNode); } if ( model->HSMHV_conqs ) { /* flat handling of NQS */ - TSTALLOC(HSMHVDPqiPtr, HSMHVdNodePrime, HSMHVqiNode) - TSTALLOC(HSMHVGPqiPtr, HSMHVgNodePrime, HSMHVqiNode) - TSTALLOC(HSMHVGPqbPtr, HSMHVgNodePrime, HSMHVqbNode) - TSTALLOC(HSMHVSPqiPtr, HSMHVsNodePrime, HSMHVqiNode) - TSTALLOC(HSMHVBPqbPtr, HSMHVbNodePrime, HSMHVqbNode) - TSTALLOC(HSMHVQIdpPtr, HSMHVqiNode, HSMHVdNodePrime) - TSTALLOC(HSMHVQIgpPtr, HSMHVqiNode, HSMHVgNodePrime) - TSTALLOC(HSMHVQIspPtr, HSMHVqiNode, HSMHVsNodePrime) - TSTALLOC(HSMHVQIbpPtr, HSMHVqiNode, HSMHVbNodePrime) - TSTALLOC(HSMHVQIqiPtr, HSMHVqiNode, HSMHVqiNode) - TSTALLOC(HSMHVQBdpPtr, HSMHVqbNode, HSMHVdNodePrime) - TSTALLOC(HSMHVQBgpPtr, HSMHVqbNode, HSMHVgNodePrime) - TSTALLOC(HSMHVQBspPtr, HSMHVqbNode, HSMHVsNodePrime) - TSTALLOC(HSMHVQBbpPtr, HSMHVqbNode, HSMHVbNodePrime) - TSTALLOC(HSMHVQBqbPtr, HSMHVqbNode, HSMHVqbNode) + TSTALLOC(HSMHVDPqiPtr, HSMHVdNodePrime, HSMHVqiNode); + TSTALLOC(HSMHVGPqiPtr, HSMHVgNodePrime, HSMHVqiNode); + TSTALLOC(HSMHVGPqbPtr, HSMHVgNodePrime, HSMHVqbNode); + TSTALLOC(HSMHVSPqiPtr, HSMHVsNodePrime, HSMHVqiNode); + TSTALLOC(HSMHVBPqbPtr, HSMHVbNodePrime, HSMHVqbNode); + TSTALLOC(HSMHVQIdpPtr, HSMHVqiNode, HSMHVdNodePrime); + TSTALLOC(HSMHVQIgpPtr, HSMHVqiNode, HSMHVgNodePrime); + TSTALLOC(HSMHVQIspPtr, HSMHVqiNode, HSMHVsNodePrime); + TSTALLOC(HSMHVQIbpPtr, HSMHVqiNode, HSMHVbNodePrime); + TSTALLOC(HSMHVQIqiPtr, HSMHVqiNode, HSMHVqiNode); + TSTALLOC(HSMHVQBdpPtr, HSMHVqbNode, HSMHVdNodePrime); + TSTALLOC(HSMHVQBgpPtr, HSMHVqbNode, HSMHVgNodePrime); + TSTALLOC(HSMHVQBspPtr, HSMHVqbNode, HSMHVsNodePrime); + TSTALLOC(HSMHVQBbpPtr, HSMHVqbNode, HSMHVbNodePrime); + TSTALLOC(HSMHVQBqbPtr, HSMHVqbNode, HSMHVqbNode); if ( here->HSMHV_coselfheat > 0 ) { /* self heating */ - TSTALLOC(HSMHVQItempPtr, HSMHVqiNode, HSMHVtempNode) - TSTALLOC(HSMHVQBtempPtr, HSMHVqbNode, HSMHVtempNode) + TSTALLOC(HSMHVQItempPtr, HSMHVqiNode, HSMHVtempNode); + TSTALLOC(HSMHVQBtempPtr, HSMHVqbNode, HSMHVtempNode); } } @@ -1313,7 +1313,7 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ RANGECHECK(model->HSMHV_sub2l, 0.0, 1.0, "SUB2L") ; RANGECHECK(model->HSMHV_voverp, 0.0, 2.0, "VOVERP") ; RANGECHECK(model->HSMHV_qme1, 0.0, 300.0e-9, "QME1") ; - RANGECHECK(model->HSMHV_qme2, 0.0, 0.0, "QME2") ; + RANGECHECK(model->HSMHV_qme2, 0.0, 2.0, "QME2") ; RANGECHECK(model->HSMHV_qme3, 0.0,800.0e-12, "QME3") ; RANGECHECK(model->HSMHV_glpart1, 0.0, 1.0, "GLPART1") ; RANGECHECK(model->HSMHV_tnom, 22.0, 32.0, "TNOM") ; diff --git a/src/spicelib/devices/ind/Makefile.am b/src/spicelib/devices/ind/Makefile.am index ff223a2ce..78347037e 100644 --- a/src/spicelib/devices/ind/Makefile.am +++ b/src/spicelib/devices/ind/Makefile.am @@ -55,6 +55,10 @@ libind_la_SOURCES += indbindCSC.c libind_la_SOURCES += mutbindCSC.c endif +if KIRCHHOFF_WANTED +libind_la_SOURCES += indnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/ind/ind.c b/src/spicelib/devices/ind/ind.c index 9b83bf868..430b46b78 100644 --- a/src/spicelib/devices/ind/ind.c +++ b/src/spicelib/devices/ind/ind.c @@ -9,43 +9,45 @@ Author: 1985 Thomas L. Quarles #include "inddefs.h" #include "ngspice/suffix.h" -IFparm INDpTable[] = { /* parameters */ - IOPAP("inductance",IND_IND, IF_REAL, "Inductance of inductor"), - IOPAU("ic", IND_IC, IF_REAL, "Initial current through inductor"), - IP( "sens_ind", IND_IND_SENS, IF_FLAG, - "flag to request sensitivity WRT inductance"), - IOPZU("temp", IND_TEMP, IF_REAL, "Instance operating temperature"), - IOPZ( "dtemp", IND_DTEMP, IF_REAL, - "Instance temperature difference with the rest of the circuit"), - IOPU( "m", IND_M, IF_REAL, "Multiplication Factor"), - IOPU( "scale", IND_SCALE, IF_REAL, "Scale factor"), - IOP( "nt", IND_NT, IF_REAL, "Number of turns"), - OP( "flux", IND_FLUX, IF_REAL, "Flux through inductor"), - OP( "v", IND_VOLT, IF_REAL, "Terminal voltage of inductor"), - OPR( "volt", IND_VOLT, IF_REAL, ""), - OP( "i", IND_CURRENT, IF_REAL, "Current through the inductor"), - OPR( "current", IND_CURRENT, IF_REAL, ""), - OP( "p", IND_POWER, IF_REAL, - "instantaneous power dissipated by the inductor"), - OPU( "sens_dc", IND_QUEST_SENS_DC, IF_REAL, "dc sensitivity sensitivity"), - OPU( "sens_real", IND_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), - OPU( "sens_imag", IND_QUEST_SENS_IMAG, IF_REAL, - "dc sensitivity and imag part of ac sensitivty"), - OPU( "sens_mag", IND_QUEST_SENS_MAG, IF_REAL, "sensitivity of AC magnitude"), - OPU( "sens_ph", IND_QUEST_SENS_PH, IF_REAL, "sensitivity of AC phase"), - OPU( "sens_cplx", IND_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") +IFparm INDpTable[] = { /* parameters */ + IOPAP("inductance",IND_IND, IF_REAL, "Inductance of inductor"), + IOPAU("ic", IND_IC, IF_REAL, "Initial current through inductor"), + IP( "sens_ind", IND_IND_SENS, IF_FLAG, + "flag to request sensitivity WRT inductance"), + IOPZU("temp", IND_TEMP, IF_REAL, "Instance operating temperature"), + IOPZ( "dtemp", IND_DTEMP, IF_REAL, + "Instance temperature difference with the rest of the circuit"), + IOPU( "m", IND_M, IF_REAL, "Multiplication Factor"), + IOPU( "tc1", IND_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc2", IND_TC2, IF_REAL, "Second order temp. coefficient"), + IOPU( "scale", IND_SCALE, IF_REAL, "Scale factor"), + IOP( "nt", IND_NT, IF_REAL, "Number of turns"), + OP( "flux", IND_FLUX, IF_REAL, "Flux through inductor"), + OP( "v", IND_VOLT, IF_REAL, "Terminal voltage of inductor"), + OPR( "volt", IND_VOLT, IF_REAL, ""), + OP( "i", IND_CURRENT, IF_REAL, "Current through the inductor"), + OPR( "current", IND_CURRENT, IF_REAL, ""), + OP( "p", IND_POWER, IF_REAL, + "instantaneous power dissipated by the inductor"), + OPU( "sens_dc", IND_QUEST_SENS_DC, IF_REAL, "dc sensitivity sensitivity"), + OPU( "sens_real", IND_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), + OPU( "sens_imag", IND_QUEST_SENS_IMAG, IF_REAL, + "dc sensitivity and imag part of ac sensitivty"), + OPU( "sens_mag", IND_QUEST_SENS_MAG, IF_REAL, "sensitivity of AC magnitude"), + OPU( "sens_ph", IND_QUEST_SENS_PH, IF_REAL, "sensitivity of AC phase"), + OPU( "sens_cplx", IND_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") }; IFparm INDmPTable[] = { /* model parameters */ - IOPA( "ind", IND_MOD_IND, IF_REAL,"Model inductance"), - IOPA( "tc1", IND_MOD_TC1, IF_REAL,"First order temp. coefficient"), - IOPA( "tc2", IND_MOD_TC2, IF_REAL,"Second order temp. coefficient"), - IOPXU( "tnom", IND_MOD_TNOM, IF_REAL,"Parameter measurement temperature"), - IOPA( "csect", IND_MOD_CSECT, IF_REAL,"Inductor cross section"), - IOPA( "length", IND_MOD_LENGTH, IF_REAL,"Inductor length"), - IOPA( "nt", IND_MOD_NT, IF_REAL,"Model number of turns"), - IOPA( "mu", IND_MOD_MU, IF_REAL,"Relative magnetic permeability"), - IP( "l", IND_MOD_L, IF_FLAG,"Inductor model") + IOPA( "ind", IND_MOD_IND, IF_REAL,"Model inductance"), + IOPA( "tc1", IND_MOD_TC1, IF_REAL,"First order temp. coefficient"), + IOPA( "tc2", IND_MOD_TC2, IF_REAL,"Second order temp. coefficient"), + IOPXU( "tnom", IND_MOD_TNOM, IF_REAL,"Parameter measurement temperature"), + IOPA( "csect", IND_MOD_CSECT, IF_REAL,"Inductor cross section"), + IOPA( "length", IND_MOD_LENGTH, IF_REAL,"Inductor length"), + IOPA( "nt", IND_MOD_NT, IF_REAL,"Model number of turns"), + IOPA( "mu", IND_MOD_MU, IF_REAL,"Relative magnetic permeability"), + IP( "l", IND_MOD_L, IF_FLAG,"Inductor model") }; @@ -63,20 +65,20 @@ int INDmSize = sizeof(INDmodel); #ifdef MUTUAL -IFparm MUTpTable[] = { /* parameters */ - IOPAP( "k", MUT_COEFF, IF_REAL , "Mutual inductance"), - IOPR( "coefficient", MUT_COEFF, IF_REAL , ""), - IOP( "inductor1", MUT_IND1, IF_INSTANCE, "First coupled inductor"), - IOP( "inductor2", MUT_IND2, IF_INSTANCE, "Second coupled inductor"), - IP( "sens_coeff", MUT_COEFF_SENS, IF_FLAG, - "flag to request sensitivity WRT coupling factor"), - OPU( "sens_dc", MUT_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), - OPU( "sens_real", MUT_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), - OPU( "sens_imag", MUT_QUEST_SENS_IMAG, IF_REAL, - "dc sensitivity and imag part of ac sensitivty"), - OPU( "sens_mag", MUT_QUEST_SENS_MAG, IF_REAL, "sensitivity of AC magnitude"), - OPU( "sens_ph", MUT_QUEST_SENS_PH, IF_REAL, "sensitivity of AC phase"), - OPU( "sens_cplx", MUT_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") +IFparm MUTpTable[] = { /* parameters */ + IOPAP( "k", MUT_COEFF, IF_REAL , "Mutual inductance"), + IOPR( "coefficient", MUT_COEFF, IF_REAL , ""), + IOP( "inductor1", MUT_IND1, IF_INSTANCE, "First coupled inductor"), + IOP( "inductor2", MUT_IND2, IF_INSTANCE, "Second coupled inductor"), + IP( "sens_coeff", MUT_COEFF_SENS, IF_FLAG, + "flag to request sensitivity WRT coupling factor"), + OPU( "sens_dc", MUT_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), + OPU( "sens_real", MUT_QUEST_SENS_REAL, IF_REAL, "real part of ac sensitivity"), + OPU( "sens_imag", MUT_QUEST_SENS_IMAG, IF_REAL, + "dc sensitivity and imag part of ac sensitivty"), + OPU( "sens_mag", MUT_QUEST_SENS_MAG, IF_REAL, "sensitivity of AC magnitude"), + OPU( "sens_ph", MUT_QUEST_SENS_PH, IF_REAL, "sensitivity of AC phase"), + OPU( "sens_cplx", MUT_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") }; int MUTnSize = NUMELEMS(INDnames); diff --git a/src/spicelib/devices/ind/indacld.c b/src/spicelib/devices/ind/indacld.c index 5ab7f769f..6a910d4fd 100644 --- a/src/spicelib/devices/ind/indacld.c +++ b/src/spicelib/devices/ind/indacld.c @@ -17,13 +17,16 @@ INDacLoad(GENmodel *inModel, CKTcircuit *ckt) { INDmodel *model = (INDmodel*)inModel; double val; + double m; INDinstance *here; for( ; model != NULL; model = model->INDnextModel) { for( here = model->INDinstances;here != NULL; here = here->INDnextInstance) { - val = ckt->CKTomega * here->INDinduct; + m = (here->INDm); + + val = ckt->CKTomega * here->INDinduct / m; *(here->INDposIbrptr) += 1; *(here->INDnegIbrptr) -= 1; diff --git a/src/spicelib/devices/ind/inddefs.h b/src/spicelib/devices/ind/inddefs.h index 16ae6bfda..856667a58 100644 --- a/src/spicelib/devices/ind/inddefs.h +++ b/src/spicelib/devices/ind/inddefs.h @@ -15,14 +15,14 @@ Author: 1985 Thomas L. Quarles #include "ngspice/gendefs.h" #include "ngspice/cktdefs.h" - /* structures used to descrive inductors */ +/* structures used to descrive inductors */ /* information needed for each instance */ typedef struct sINDinstance { struct sINDmodel *INDmodPtr; /* backpointer to model */ - struct sINDinstance *INDnextInstance; /* pointer to next instance of + struct sINDinstance *INDnextInstance; /* pointer to next instance of * current model*/ IFuid INDname; /* pointer to character string naming this instance */ int INDstate; /* pointer to beginning of state vector for inductor */ @@ -32,26 +32,30 @@ typedef struct sINDinstance { int INDbrEq; /* number of the branch equation added for current */ double INDinduct; /* inductance */ double INDm; /* Parallel multiplier */ + double INDtc1; /* first temperature coefficient of resistors */ + double INDtc2; /* second temperature coefficient of resistors */ double INDtemp; /* Instance operating temperature */ double INDdtemp; /* Delta temp. of instance */ double INDscale; /* Scale factor */ double INDnt; /* Number of turns */ double INDinitCond; /* initial inductor voltage if specified */ - double *INDposIbrptr; /* pointer to sparse matrix diagonal at + double *INDposIbrptr; /* pointer to sparse matrix diagonal at * (positive,branch eq) */ - double *INDnegIbrptr; /* pointer to sparse matrix diagonal at + double *INDnegIbrptr; /* pointer to sparse matrix diagonal at * (negative,branch eq) */ - double *INDibrNegptr; /* pointer to sparse matrix offdiagonal at + double *INDibrNegptr; /* pointer to sparse matrix offdiagonal at * (branch eq,negative) */ - double *INDibrPosptr; /* pointer to sparse matrix offdiagonal at + double *INDibrPosptr; /* pointer to sparse matrix offdiagonal at * (branch eq,positive) */ - double *INDibrIbrptr; /* pointer to sparse matrix offdiagonal at + double *INDibrIbrptr; /* pointer to sparse matrix offdiagonal at * (branch eq,branch eq) */ - + unsigned INDindGiven : 1; /* flag to indicate inductance was specified */ unsigned INDicGiven : 1; /* flag to indicate init. cond. was specified */ unsigned INDmGiven : 1; /* flag to indicate multiplier given */ + unsigned INDtc1Given : 1; /* indicates tc1 parameter specified */ + unsigned INDtc2Given : 1; /* indicates tc2 parameter specified */ unsigned INDtempGiven : 1; /* flag to indicate operating temp. given */ unsigned INDdtempGiven : 1; /* flag to indicate delta temp. given */ unsigned INDscaleGiven : 1; /* flag to indicate scale factor given */ @@ -67,25 +71,30 @@ typedef struct sINDinstance { BindElement *INDibrIbrptrStructPtr ; #endif +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } INDinstance ; #define INDflux INDstate /* flux in the inductor */ #define INDvolt INDstate+1 /* voltage - save an entry in table */ #define INDsensxp INDstate+2 /* charge sensitivities and their derivatives. - +3 for the derivatives - pointer to the - beginning of the array */ ++3 for the derivatives - pointer to the +beginning of the array */ /* per model data */ typedef struct sINDmodel { /* model structure for an inductor */ int INDmodType; /* type index of this device type */ - struct sINDmodel *INDnextModel; /* pointer to next possible model in + struct sINDmodel *INDnextModel; /* pointer to next possible model in * linked list */ INDinstance * INDinstances; /* pointer to list of instances that have this * model */ IFuid INDmodName; /* pointer to character string naming this model */ - + double INDmInd; /* Model inductance */ double INDtnom; /* temperature at which inductance measured */ double INDtempCoeff1; /* first temperature coefficient */ @@ -94,8 +103,8 @@ typedef struct sINDmodel { /* model structure for an inductor */ double INDlength; /* Mean length of magnetic path */ double INDmodNt; /* Model number of turns */ double INDmu; /* Relative magnetic permeability */ - - unsigned INDtnomGiven : 1; /* flag to indicate nominal temp was given */ + + unsigned INDtnomGiven : 1; /* flag to indicate nominal temp was given */ unsigned INDtc1Given : 1; /* flag to indicate tc1 was specified */ unsigned INDtc2Given : 1; /* flag to indicate tc2 was specified */ unsigned INDcsectGiven : 1; /* flag to indicate cross section given */ @@ -110,27 +119,27 @@ typedef struct sINDmodel { /* model structure for an inductor */ #ifdef MUTUAL - /* structures used to describe mutual inductors */ +/* structures used to describe mutual inductors */ /* information needed for each instance */ typedef struct sMUTinstance { - struct sMUTmodel *MUTmodPtr; /* backpointer to model */ - struct sMUTinstance *MUTnextInstance; /* pointer to next instance of +struct sMUTmodel *MUTmodPtr; /* backpointer to model */ +struct sMUTinstance *MUTnextInstance; /* pointer to next instance of * current model*/ - IFuid MUTname; /* pointer to character string naming this instance */ - double MUTcoupling; /* mutual inductance input by user */ - double MUTfactor; /* mutual inductance scaled for internal use */ - IFuid MUTindName1; /* name of coupled inductor 1 */ - IFuid MUTindName2; /* name of coupled inductor 2 */ - INDinstance *MUTind1; /* pointer to coupled inductor 1 */ - INDinstance *MUTind2; /* pointer to coupled inductor 2 */ - double *MUTbr1br2; /* pointers to off-diagonal intersections of */ - double *MUTbr2br1; /* current branch equations in matrix */ +IFuid MUTname; /* pointer to character string naming this instance */ +double MUTcoupling; /* mutual inductance input by user */ +double MUTfactor; /* mutual inductance scaled for internal use */ +IFuid MUTindName1; /* name of coupled inductor 1 */ +IFuid MUTindName2; /* name of coupled inductor 2 */ +INDinstance *MUTind1; /* pointer to coupled inductor 1 */ +INDinstance *MUTind2; /* pointer to coupled inductor 2 */ +double *MUTbr1br2; /* pointers to off-diagonal intersections of */ +double *MUTbr2br1; /* current branch equations in matrix */ - unsigned MUTindGiven : 1; /* flag to indicate inductance was specified */ - int MUTsenParmNo; /* parameter # for sensitivity use; +unsigned MUTindGiven : 1; /* flag to indicate inductance was specified */ +int MUTsenParmNo; /* parameter # for sensitivity use; set equal to 0 if not a design parameter*/ #ifdef KLU @@ -144,12 +153,12 @@ typedef struct sMUTinstance { /* per model data */ typedef struct sMUTmodel { /* model structure for a mutual inductor */ - int MUTmodType; /* type index of this device type */ - struct sMUTmodel *MUTnextModel; /* pointer to next possible model in +int MUTmodType; /* type index of this device type */ +struct sMUTmodel *MUTnextModel; /* pointer to next possible model in * linked list */ - MUTinstance * MUTinstances; /* pointer to list of instances that have this +MUTinstance * MUTinstances; /* pointer to list of instances that have this * model */ - IFuid MUTmodName; /* pointer to character string naming this model */ +IFuid MUTmodName; /* pointer to character string naming this model */ } MUTmodel; #endif /*MUTUAL*/ @@ -167,6 +176,8 @@ typedef struct sMUTmodel { /* model structure for a mutual inductor */ #define IND_DTEMP 10 #define IND_SCALE 11 #define IND_NT 12 +#define IND_TC1 13 +#define IND_TC2 14 /* model parameters */ #define IND_MOD_IND 100 diff --git a/src/spicelib/devices/ind/indext.h b/src/spicelib/devices/ind/indext.h index b386cd446..e8ac7b970 100644 --- a/src/spicelib/devices/ind/indext.h +++ b/src/spicelib/devices/ind/indext.h @@ -25,6 +25,10 @@ extern int INDunsetup(GENmodel*,CKTcircuit*); extern int INDtemp(GENmodel*, CKTcircuit*); extern int INDtrunc(GENmodel*,CKTcircuit*,double*); +#ifdef KIRCHHOFF +extern int INDnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif + extern int MUTacLoad(GENmodel*,CKTcircuit*); extern int MUTask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); extern int MUTdelete(GENmodel*,IFuid,GENinstance**); diff --git a/src/spicelib/devices/ind/indinit.c b/src/spicelib/devices/ind/indinit.c index 5fd375b2d..623c7e05a 100644 --- a/src/spicelib/devices/ind/indinit.c +++ b/src/spicelib/devices/ind/indinit.c @@ -72,12 +72,17 @@ SPICEdev INDinfo = { #endif /* DEVinstSize */ &INDiSize, /* DEVmodSize */ &INDmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ INDbindCSC, /* DEVbindCSCComplex */ INDbindCSCComplex, /* DEVbindCSCComplexToReal */ INDbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ INDnodeIsNonLinear +#endif + }; @@ -144,14 +149,19 @@ SPICEdev MUTinfo = { /* DEVdump */ NULL, /* DEVacct */ NULL, #endif - &MUTiSize, - &MUTmSize, + /* DEVinstSize */ &MUTiSize, + /* DEVmodSize */ &MUTmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MUTbindCSC, /* DEVbindCSCComplex */ MUTbindCSCComplex, /* DEVbindCSCComplexToReal */ MUTbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/ind/indload.c b/src/spicelib/devices/ind/indload.c index 9ee8574a6..eb0433d16 100644 --- a/src/spicelib/devices/ind/indload.c +++ b/src/spicelib/devices/ind/indload.c @@ -3,9 +3,9 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ - /* actually load the current inductance value into the - * sparse matrix previously provided - */ +/* actually load the current inductance value into the + * sparse matrix previously provided + */ #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" @@ -21,8 +21,9 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) INDinstance *here; double veq; double req; + double m; int error; - + #ifdef MUTUAL MUTinstance *muthere; MUTmodel *mutmodel; @@ -37,13 +38,15 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) for (here = model->INDinstances; here != NULL ; here=here->INDnextInstance) { + m = (here->INDm); + if(!(ckt->CKTmode & (MODEDC|MODEINITPRED))) { if(ckt->CKTmode & MODEUIC && ckt->CKTmode & MODEINITTRAN) { - *(ckt->CKTstate0 + here->INDflux) = here->INDinduct * - here->INDinitCond; + *(ckt->CKTstate0 + here->INDflux) = here->INDinduct / m * + here->INDinitCond; } else { - *(ckt->CKTstate0 + here->INDflux) = here->INDinduct * - *(ckt->CKTrhsOld + here->INDbrEq); + *(ckt->CKTstate0 + here->INDflux) = here->INDinduct / m * + *(ckt->CKTrhsOld + here->INDbrEq); } } #ifdef MUTUAL @@ -61,13 +64,13 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) if(!(ckt->CKTmode& (MODEDC|MODEINITPRED))) { *(ckt->CKTstate0 + muthere->MUTind1->INDflux) += muthere->MUTfactor * *(ckt->CKTrhsOld + - muthere->MUTind2->INDbrEq); - + muthere->MUTind2->INDbrEq); + *(ckt->CKTstate0 + muthere->MUTind2->INDflux) += muthere->MUTfactor * *(ckt->CKTrhsOld + - muthere->MUTind1->INDbrEq); + muthere->MUTind1->INDbrEq); } - + *(muthere->MUTbr1br2) -= muthere->MUTfactor*ckt->CKTag[0]; *(muthere->MUTbr2br1) -= muthere->MUTfactor*ckt->CKTag[0]; } @@ -86,6 +89,7 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) req = 0.0; veq = 0.0; } else { + double newmind; #ifndef PREDICTOR if(ckt->CKTmode & MODEINITPRED) { *(ckt->CKTstate0 + here->INDflux) = @@ -94,27 +98,38 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) #endif /*PREDICTOR*/ if (ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate1 + here->INDflux) = - *(ckt->CKTstate0 + here->INDflux); + *(ckt->CKTstate0 + here->INDflux); } #ifndef PREDICTOR } #endif /*PREDICTOR*/ - error=NIintegrate(ckt,&req,&veq,here->INDinduct,here->INDflux); + m = (here->INDm); + newmind = here->INDinduct/m; + error=NIintegrate(ckt,&req,&veq,newmind,here->INDflux); if(error) return(error); } - + *(ckt->CKTrhs+here->INDbrEq) += veq; - - if(ckt->CKTmode & MODEINITTRAN) { - *(ckt->CKTstate1+here->INDvolt) = + + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1+here->INDvolt) = *(ckt->CKTstate0+here->INDvolt); } - + *(here->INDposIbrptr) += 1; *(here->INDnegIbrptr) -= 1; *(here->INDibrPosptr) += 1; *(here->INDibrNegptr) -= 1; *(here->INDibrIbrptr) -= req; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->INDposNode) += *(ckt->CKTrhsOld+here->INDbrEq) ; + *(ckt->CKTfvk+here->INDnegNode) -= *(ckt->CKTrhsOld+here->INDbrEq) ; + + *(here->KCLcurrentPos) = *(ckt->CKTrhsOld+here->INDbrEq) ; + *(here->KCLcurrentNeg) = -(*(ckt->CKTrhsOld+here->INDbrEq)) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/ind/indmpar.c b/src/spicelib/devices/ind/indmpar.c index 12b5b0444..ee641d5af 100644 --- a/src/spicelib/devices/ind/indmpar.c +++ b/src/spicelib/devices/ind/indmpar.c @@ -17,44 +17,44 @@ INDmParam(int param, IFvalue *value, GENmodel *inModel) { INDmodel *mod = (INDmodel*)inModel; switch(param) { - case IND_MOD_IND: - mod->INDmInd = value->rValue; - mod->INDmIndGiven = TRUE; - break; - case IND_MOD_TNOM: - mod->INDtnom = value->rValue+CONSTCtoK; - mod->INDtnomGiven = TRUE; - break; - case IND_MOD_TC1: - mod->INDtempCoeff1 = value->rValue; - mod->INDtc1Given = TRUE; - break; - case IND_MOD_TC2: - mod->INDtempCoeff2 = value->rValue; - mod->INDtc2Given = TRUE; - break; - case IND_MOD_CSECT: - mod->INDcsect = value->rValue; - mod->INDcsectGiven = TRUE; - break; - case IND_MOD_LENGTH : - mod->INDlength = value->rValue; - mod->INDlengthGiven = TRUE; - break; - case IND_MOD_NT : - mod->INDmodNt = value->rValue; - mod->INDmodNtGiven = TRUE; - break; - case IND_MOD_MU: - mod->INDmu = value->rValue; - mod->INDmuGiven = TRUE; - break; - case IND_MOD_L: - /* just being reassured by the user that we are an inductor */ - /* no-op */ - break; - default: - return(E_BADPARM); + case IND_MOD_IND: + mod->INDmInd = value->rValue; + mod->INDmIndGiven = TRUE; + break; + case IND_MOD_TNOM: + mod->INDtnom = value->rValue+CONSTCtoK; + mod->INDtnomGiven = TRUE; + break; + case IND_MOD_TC1: + mod->INDtempCoeff1 = value->rValue; + mod->INDtc1Given = TRUE; + break; + case IND_MOD_TC2: + mod->INDtempCoeff2 = value->rValue; + mod->INDtc2Given = TRUE; + break; + case IND_MOD_CSECT: + mod->INDcsect = value->rValue; + mod->INDcsectGiven = TRUE; + break; + case IND_MOD_LENGTH : + mod->INDlength = value->rValue; + mod->INDlengthGiven = TRUE; + break; + case IND_MOD_NT : + mod->INDmodNt = value->rValue; + mod->INDmodNtGiven = TRUE; + break; + case IND_MOD_MU: + mod->INDmu = value->rValue; + mod->INDmuGiven = TRUE; + break; + case IND_MOD_L: + /* just being reassured by the user that we are an inductor */ + /* no-op */ + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/ind/indnode.c b/src/spicelib/devices/ind/indnode.c new file mode 100644 index 000000000..bb1203981 --- /dev/null +++ b/src/spicelib/devices/ind/indnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "inddefs.h" +#include "ngspice/sperror.h" + +int +INDnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + INDmodel *model = (INDmodel *)inModel ; + INDinstance *here ; + int error ; + + /* loop through all the IND models */ + for ( ; model != NULL ; model = model->INDnextModel) + { + /* loop through all the instances of the model */ + for (here = model->INDinstances ; here != NULL ; here = here->INDnextInstance) + { + error = CKTmkCurKCL (ckt, here->INDposNode, &(here->KCLcurrentPos)) ; + error = CKTmkCurKCL (ckt, here->INDnegNode, &(here->KCLcurrentNeg)) ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/indparam.c b/src/spicelib/devices/ind/indparam.c index 6b7a0fbac..e39584c6f 100644 --- a/src/spicelib/devices/ind/indparam.c +++ b/src/spicelib/devices/ind/indparam.c @@ -21,41 +21,49 @@ INDparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) NG_IGNORE(select); switch(param) { - case IND_IND: - here->INDinduct = value->rValue; - if (!here->INDmGiven) - here->INDm =1.0; - here->INDindGiven = TRUE; - break; - case IND_TEMP: - here->INDtemp = value->rValue + CONSTCtoK; - here->INDtempGiven = TRUE; - break; - case IND_DTEMP: - here->INDdtemp = value->rValue; - here->INDdtempGiven = TRUE; - break; - case IND_M: - here->INDm = value->rValue; - here->INDmGiven = TRUE; - break; - case IND_SCALE: - here->INDscale = value->rValue; - here->INDscaleGiven = TRUE; - break; - case IND_NT: - here->INDnt = value->rValue; - here->INDntGiven = TRUE; - break; - case IND_IC: - here->INDinitCond = value->rValue; - here->INDicGiven = TRUE; - break; - case IND_IND_SENS: - here->INDsenParmNo = value->iValue; - break; - default: - return(E_BADPARM); + case IND_IND: + here->INDinduct = value->rValue; + if (!here->INDmGiven) + here->INDm =1.0; + here->INDindGiven = TRUE; + break; + case IND_TEMP: + here->INDtemp = value->rValue + CONSTCtoK; + here->INDtempGiven = TRUE; + break; + case IND_DTEMP: + here->INDdtemp = value->rValue; + here->INDdtempGiven = TRUE; + break; + case IND_M: + here->INDm = value->rValue; + here->INDmGiven = TRUE; + break; + case IND_TC1: + here->INDtc1 = value->rValue; + here->INDtc1Given = TRUE; + break; + case IND_TC2: + here->INDtc2 = value->rValue; + here->INDtc2Given = TRUE; + break; + case IND_SCALE: + here->INDscale = value->rValue; + here->INDscaleGiven = TRUE; + break; + case IND_NT: + here->INDnt = value->rValue; + here->INDntGiven = TRUE; + break; + case IND_IC: + here->INDinitCond = value->rValue; + here->INDicGiven = TRUE; + break; + case IND_IND_SENS: + here->INDsenParmNo = value->iValue; + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/ind/indsacl.c b/src/spicelib/devices/ind/indsacl.c index e344973f0..78fc36cc5 100644 --- a/src/spicelib/devices/ind/indsacl.c +++ b/src/spicelib/devices/ind/indsacl.c @@ -150,9 +150,9 @@ INDsAcLoad(GENmodel *inModel, CKTcircuit *ckt) ival = cind * ckt->CKTomega ; #ifdef SENSDEBUG - fprintf(file,"cind = %.5e,icind = %.5e\n",cind,icind); - fprintf(file,"val = %.5e,ival = %.5e\n",val,ival); - fprintf(file,"brEq = %.5e,senparmno = %.5e\n", + fprintf(stdout,"cind = %.5e,icind = %.5e\n",cind,icind); + fprintf(stdout,"val = %.5e,ival = %.5e\n",val,ival); + fprintf(stdout,"brEq = %.5e,senparmno = %.5e\n", here->INDbrEq,here->INDsenParmNo); #endif /* SENSDEBUG */ diff --git a/src/spicelib/devices/ind/indsetup.c b/src/spicelib/devices/ind/indsetup.c index d686adbe7..b42bb9fbe 100644 --- a/src/spicelib/devices/ind/indsetup.c +++ b/src/spicelib/devices/ind/indsetup.c @@ -89,15 +89,15 @@ INDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(INDposIbrptr,INDposNode,INDbrEq) - TSTALLOC(INDnegIbrptr,INDnegNode,INDbrEq) - TSTALLOC(INDibrNegptr,INDbrEq,INDnegNode) - TSTALLOC(INDibrPosptr,INDbrEq,INDposNode) - TSTALLOC(INDibrIbrptr,INDbrEq,INDbrEq) + TSTALLOC(INDposIbrptr,INDposNode,INDbrEq); + TSTALLOC(INDnegIbrptr,INDnegNode,INDbrEq); + TSTALLOC(INDibrNegptr,INDbrEq,INDnegNode); + TSTALLOC(INDibrPosptr,INDbrEq,INDposNode); + TSTALLOC(INDibrIbrptr,INDbrEq,INDbrEq); } } return(OK); diff --git a/src/spicelib/devices/ind/indsload.c b/src/spicelib/devices/ind/indsload.c index 3a8e1c4ac..74f9f99cd 100644 --- a/src/spicelib/devices/ind/indsload.c +++ b/src/spicelib/devices/ind/indsload.c @@ -47,8 +47,8 @@ INDsLoad(GENmodel *inModel, CKTcircuit *ckt) if((info->SENmode == TRANSEN) && (ckt->CKTmode & MODEINITTRAN)) return(OK); #ifdef SENSDEBUG - fprintf(file,"INDsenLoad\n"); - fprintf(file,"time = %.5e\n",ckt->CKTtime); + fprintf(stdout,"INDsenLoad\n"); + fprintf(stdout,"time = %.5e\n",ckt->CKTtime); #endif /* SENSDEBUG */ @@ -109,7 +109,7 @@ INDsLoad(GENmodel *inModel, CKTcircuit *ckt) } #ifdef SENSDEBUG - fprintf(file,"cind1 = %.5e,cind2 = %.5e\n",cind1,cind2); + fprintf(stdout,"cind1 = %.5e,cind2 = %.5e\n",cind1,cind2); #endif /* SENSDEBUG */ } @@ -125,8 +125,8 @@ INDsLoad(GENmodel *inModel, CKTcircuit *ckt) #endif /* MUTUAL */ cind = *(ckt->CKTrhsOld + here->INDbrEq); #ifdef SENSDEBUG - fprintf(file,"\n cind=%.5e\n",cind); - fprintf(file,"\n tag0=%.5e,tag1=%.5e\n",tag0,tag1); + fprintf(stdout,"\n cind=%.5e\n",cind); + fprintf(stdout,"\n tag0=%.5e,tag1=%.5e\n",tag0,tag1); #endif /* SENSDEBUG */ for(iparmno = 1;iparmno<=info->SENparms;iparmno++){ Osxp = tag0 * *(ckt->CKTstate1 + here->INDsensxp @@ -135,7 +135,7 @@ INDsLoad(GENmodel *inModel, CKTcircuit *ckt) + 2*(iparmno - 1) + 1); if(iparmno == here->INDsenParmNo) Osxp = Osxp - tag0 * cind; #ifdef SENSDEBUG - fprintf(file,"\n Osxp=%.5e\n",Osxp); + fprintf(stdout,"\n Osxp=%.5e\n",Osxp); #endif /* SENSDEBUG */ *(info->SEN_RHS[here->INDbrEq] + iparmno) -= Osxp; diff --git a/src/spicelib/devices/ind/indtemp.c b/src/spicelib/devices/ind/indtemp.c index 5201d5df5..94dac8865 100644 --- a/src/spicelib/devices/ind/indtemp.c +++ b/src/spicelib/devices/ind/indtemp.c @@ -21,6 +21,7 @@ INDtemp(GENmodel *inModel, CKTcircuit *ckt) INDinstance *here; double difference; double factor; + double tc1, tc2; /* loop through all the inductor models */ for( ; model != NULL; model = model->INDnextModel ) { @@ -30,36 +31,47 @@ INDtemp(GENmodel *inModel, CKTcircuit *ckt) here=here->INDnextInstance) { /* Default Value Processing for Inductor Instance */ - - if(!here->INDtempGiven) { - here->INDtemp = ckt->CKTtemp; - if(!here->INDdtempGiven) here->INDdtemp = 0.0; - } else { /* INDtempGiven */ - here->INDdtemp = 0.0; - if (here->INDdtempGiven) - printf("%s: Instance temperature specified, dtemp ignored\n", - here->INDname); - } - - if (!here->INDscaleGiven) here->INDscale = 1.0; - if (!here->INDmGiven) here->INDm = 1.0; - if (!here->INDntGiven) here->INDnt = 0.0; - - if (!here->INDindGiven) { /* No instance inductance given */ - if (here->INDntGiven) - here->INDinduct = model->INDspecInd * here->INDnt * here->INDnt; - else - here->INDinduct = model->INDmInd; + + if(!here->INDtempGiven) { + here->INDtemp = ckt->CKTtemp; + if(!here->INDdtempGiven) here->INDdtemp = 0.0; + } else { /* INDtempGiven */ + here->INDdtemp = 0.0; + if (here->INDdtempGiven) + printf("%s: Instance temperature specified, dtemp ignored\n", + here->INDname); } - difference = (here->INDtemp + here->INDdtemp) - model->INDtnom; - - factor = 1.0 + (model->INDtempCoeff1)*difference + - (model->INDtempCoeff2)*difference*difference; - - here->INDinduct = here->INDinduct * factor * here->INDscale; - here->INDinduct = here->INDinduct / here->INDm; - - } + + if (!here->INDscaleGiven) here->INDscale = 1.0; + if (!here->INDmGiven) here->INDm = 1.0; + if (!here->INDntGiven) here->INDnt = 0.0; + + if (!here->INDindGiven) { /* No instance inductance given */ + if (here->INDntGiven) + here->INDinduct = model->INDspecInd * here->INDnt * here->INDnt; + else + here->INDinduct = model->INDmInd; + } + difference = (here->INDtemp + here->INDdtemp) - model->INDtnom; + + /* instance parameters tc1 and tc2 will override + model parameters tc1 and tc2 */ + if (here->INDtc1Given) + tc1 = here->INDtc1; /* instance */ + else + tc1 = model->INDtempCoeff1; /* model */ + + if (here->INDtc2Given) + tc2 = here->INDtc2; + else + tc2 = model->INDtempCoeff2; + + factor = 1.0 + tc1*difference + tc2*difference*difference; + + here->INDinduct = here->INDinduct * factor * here->INDscale; + here->INDinduct = here->INDinduct / here->INDm; + + } } return(OK); } diff --git a/src/spicelib/devices/ind/mutsetup.c b/src/spicelib/devices/ind/mutsetup.c index 096f8d5b4..ae7fc1cab 100644 --- a/src/spicelib/devices/ind/mutsetup.c +++ b/src/spicelib/devices/ind/mutsetup.c @@ -43,8 +43,7 @@ MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) return(E_INTERN); } - error = CKTfndDev(ckt,&ktype,(GENinstance **)&(here->MUTind1), - here->MUTindName1, NULL, NULL); + error = CKTfndDev(ckt, &ktype, (GENinstance **) &(here->MUTind1), here->MUTindName1, NULL); if(error && error!= E_NODEV && error != E_NOMOD) return(error); if(error) { IFuid namarray[2]; @@ -54,8 +53,7 @@ MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) "%s: coupling to non-existant inductor %s.", namarray); } - error = CKTfndDev(ckt,&ktype,(GENinstance **)&(here->MUTind2), - here->MUTindName2, NULL, NULL); + error = CKTfndDev(ckt, &ktype, (GENinstance **) &(here->MUTind2), here->MUTindName2, NULL); if(error && error!= E_NODEV && error != E_NOMOD) return(error); if(error) { IFuid namarray[2]; @@ -69,12 +67,12 @@ MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MUTbr1br2,MUTind1->INDbrEq,MUTind2->INDbrEq) - TSTALLOC(MUTbr2br1,MUTind2->INDbrEq,MUTind1->INDbrEq) + TSTALLOC(MUTbr1br2,MUTind1->INDbrEq,MUTind2->INDbrEq); + TSTALLOC(MUTbr2br1,MUTind2->INDbrEq,MUTind1->INDbrEq); } } return(OK); diff --git a/src/spicelib/devices/isrc/isrc.c b/src/spicelib/devices/isrc/isrc.c index e872642ae..65dce66d8 100644 --- a/src/spicelib/devices/isrc/isrc.c +++ b/src/spicelib/devices/isrc/isrc.c @@ -11,6 +11,7 @@ Author: 1987 Thomas L. Quarles IFparm ISRCpTable[] = { /* parameters */ IOPP("dc", ISRC_DC, IF_REAL ,"DC value of source"), + IOP ( "m", ISRC_M, IF_REAL , "Parallel multiplier"), IOPPA("acmag", ISRC_AC_MAG, IF_REAL ,"AC Magnitude"), IOPAAU("acphase", ISRC_AC_PHASE, IF_REAL ,"AC Phase"), /* Modified to allow print @Iin[sin] A.Roldan */ diff --git a/src/spicelib/devices/isrc/isrcacld.c b/src/spicelib/devices/isrc/isrcacld.c index 5e2ba34be..ef6e2f730 100644 --- a/src/spicelib/devices/isrc/isrcacld.c +++ b/src/spicelib/devices/isrc/isrcacld.c @@ -15,6 +15,7 @@ ISRCacLoad(GENmodel *inModel, CKTcircuit *ckt) { ISRCmodel *model = (ISRCmodel *) inModel; ISRCinstance *here; + double m; for( ; model != NULL; model = model->ISRCnextModel ) { @@ -22,14 +23,16 @@ ISRCacLoad(GENmodel *inModel, CKTcircuit *ckt) for (here = model->ISRCinstances; here != NULL ; here=here->ISRCnextInstance) { + m = here->ISRCmValue; + *(ckt->CKTrhs + (here->ISRCposNode)) += - here->ISRCacReal; + m * here->ISRCacReal; *(ckt->CKTrhs + (here->ISRCnegNode)) -= - here->ISRCacReal; + m * here->ISRCacReal; *(ckt->CKTirhs + (here->ISRCposNode)) += - here->ISRCacImag; + m * here->ISRCacImag; *(ckt->CKTirhs + (here->ISRCnegNode)) -= - here->ISRCacImag; + m * here->ISRCacImag; } } diff --git a/src/spicelib/devices/isrc/isrcask.c b/src/spicelib/devices/isrc/isrcask.c index 3740ab331..1d7171352 100644 --- a/src/spicelib/devices/isrc/isrcask.c +++ b/src/spicelib/devices/isrc/isrcask.c @@ -34,6 +34,9 @@ ISRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue * case ISRC_DC: value->rValue = here->ISRCdcValue; return (OK); + case ISRC_M: + value->rValue = here->ISRCmValue; + return (OK); case ISRC_AC_MAG: value->rValue = here->ISRCacMag; return (OK); diff --git a/src/spicelib/devices/isrc/isrcdefs.h b/src/spicelib/devices/isrc/isrcdefs.h index 53939074e..a7851a68f 100644 --- a/src/spicelib/devices/isrc/isrcdefs.h +++ b/src/spicelib/devices/isrc/isrcdefs.h @@ -33,6 +33,7 @@ typedef struct sISRCinstance { double *ISRCcoeffs; /* pointer to array of coefficients */ double ISRCdcValue; /* DC and TRANSIENT value of source */ + double ISRCmValue; /* Parallel multiplier */ double ISRCacPhase; /* AC phase angle */ double ISRCacMag; /* AC magnitude */ @@ -56,6 +57,7 @@ typedef struct sISRCinstance { /* gtri - end - add member to hold current source value */ unsigned ISRCdcGiven :1 ; /* flag to indicate dc value given */ + unsigned ISRCmGiven :1 ; /* flag to indicate multiplier given */ unsigned ISRCacGiven :1 ; /* flag to indicate ac keyword given */ unsigned ISRCacMGiven :1 ; /* flag to indicate ac magnitude given */ unsigned ISRCacPGiven :1 ; /* flag to indicate ac phase given */ @@ -94,31 +96,32 @@ typedef struct sISRCmodel { /* device parameters */ #define ISRC_DC 1 -#define ISRC_AC_MAG 2 -#define ISRC_AC_PHASE 3 -#define ISRC_AC 4 -#define ISRC_PULSE 5 -#define ISRC_SINE 6 -#define ISRC_EXP 7 -#define ISRC_PWL 8 -#define ISRC_SFFM 9 -#define ISRC_NEG_NODE 10 -#define ISRC_POS_NODE 11 -#define ISRC_AC_REAL 12 -#define ISRC_AC_IMAG 13 -#define ISRC_FCN_TYPE 14 -#define ISRC_FCN_ORDER 15 -#define ISRC_FCN_COEFFS 16 -#define ISRC_POWER 17 -#define ISRC_D_F1 18 -#define ISRC_D_F2 19 -#define ISRC_VOLTS 20 +#define ISRC_M 2 +#define ISRC_AC_MAG 3 +#define ISRC_AC_PHASE 4 +#define ISRC_AC 5 +#define ISRC_PULSE 6 +#define ISRC_SINE 7 +#define ISRC_EXP 8 +#define ISRC_PWL 9 +#define ISRC_SFFM 10 +#define ISRC_NEG_NODE 11 +#define ISRC_POS_NODE 12 +#define ISRC_AC_REAL 13 +#define ISRC_AC_IMAG 14 +#define ISRC_FCN_TYPE 15 +#define ISRC_FCN_ORDER 16 +#define ISRC_FCN_COEFFS 17 +#define ISRC_POWER 18 +#define ISRC_D_F1 19 +#define ISRC_D_F2 20 +#define ISRC_VOLTS 21 -#define ISRC_AM 21 +#define ISRC_AM 22 /* gtri - begin - add define for current source value */ #ifdef XSPICE /* needed for outputting results */ -#define ISRC_CURRENT 22 +#define ISRC_CURRENT 23 #endif /* gtri - end - add define for current source value */ #define ISRC_TRNOISE 25 diff --git a/src/spicelib/devices/isrc/isrcinit.c b/src/spicelib/devices/isrc/isrcinit.c index 4442b53ca..3c1bf6691 100644 --- a/src/spicelib/devices/isrc/isrcinit.c +++ b/src/spicelib/devices/isrc/isrcinit.c @@ -73,12 +73,17 @@ SPICEdev ISRCinfo = { #endif /* DEVinstSize */ &ISRCiSize, /* DEVmodSize */ &ISRCmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ NULL, /* DEVbindCSCComplex */ NULL, /* DEVbindCSCComplexToReal */ NULL, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/isrc/isrcload.c b/src/spicelib/devices/isrc/isrcload.c index 04017585c..a2c15b65c 100644 --- a/src/spicelib/devices/isrc/isrcload.c +++ b/src/spicelib/devices/isrc/isrcload.c @@ -28,6 +28,7 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) ISRCinstance *here; double value; double time; + double m; /* loop through all the source models */ for( ; model != NULL; model = model->ISRCnextModel ) { @@ -36,6 +37,8 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt) for (here = model->ISRCinstances; here != NULL ; here=here->ISRCnextInstance) { + m = here->ISRCmValue; + if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->ISRCdcGiven ) { /* load using DC value */ @@ -380,14 +383,19 @@ loadDone: #endif /* gtri - end - wbk - modify for supply ramping option */ - *(ckt->CKTrhs + (here->ISRCposNode)) += value; - *(ckt->CKTrhs + (here->ISRCnegNode)) -= value; + *(ckt->CKTrhs + (here->ISRCposNode)) += m * value; + *(ckt->CKTrhs + (here->ISRCnegNode)) -= m * value; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk + (here->ISRCposNode)) -= value; + *(ckt->CKTfvk + (here->ISRCnegNode)) += value; +#endif /* gtri - end - wbk - modify to process srcFact, etc. for all sources */ #ifdef XSPICE /* gtri - begin - wbk - record value so it can be output if requested */ - here->ISRCcurrent = value; + here->ISRCcurrent = m * value; /* gtri - end - wbk - record value so it can be output if requested */ #endif } // for loop instances diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 2ce4c2580..1a62f6814 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -45,6 +45,11 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->ISRCdcGiven = TRUE; break; + case ISRC_M: + here->ISRCmValue = value->rValue; + here->ISRCmGiven = TRUE; + break; + case ISRC_AC_MAG: here->ISRCacMag = value->rValue; here->ISRCacMGiven = TRUE; diff --git a/src/spicelib/devices/isrc/isrctemp.c b/src/spicelib/devices/isrc/isrctemp.c index 0bae229ec..dbbf9de26 100644 --- a/src/spicelib/devices/isrc/isrctemp.c +++ b/src/spicelib/devices/isrc/isrctemp.c @@ -47,6 +47,8 @@ ISRCtemp(GENmodel *inModel, CKTcircuit *ckt) &(here->ISRCname)); } } + if(!here->ISRCmGiven) + here->ISRCmValue = 1; radians = here->ISRCacPhase * M_PI / 180.0; here->ISRCacReal = here->ISRCacMag * cos(radians); here->ISRCacImag = here->ISRCacMag * sin(radians); diff --git a/src/spicelib/devices/jfet/Makefile.am b/src/spicelib/devices/jfet/Makefile.am index a7e31a217..e0b77a299 100644 --- a/src/spicelib/devices/jfet/Makefile.am +++ b/src/spicelib/devices/jfet/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libjfet_la_SOURCES += jfetbindCSC.c endif +if KIRCHHOFF_WANTED +libjfet_la_SOURCES += jfetnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/jfet/jfetext.h b/src/spicelib/devices/jfet/jfetext.h index 1b09a5e68..e6911da79 100644 --- a/src/spicelib/devices/jfet/jfetext.h +++ b/src/spicelib/devices/jfet/jfetext.h @@ -28,3 +28,7 @@ extern int JFETbindCSC (GENmodel*, CKTcircuit*) ; extern int JFETbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int JFETbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int JFETnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/jfet/jfetinit.c b/src/spicelib/devices/jfet/jfetinit.c index 01ddc256a..ada63217b 100644 --- a/src/spicelib/devices/jfet/jfetinit.c +++ b/src/spicelib/devices/jfet/jfetinit.c @@ -73,12 +73,17 @@ SPICEdev JFETinfo = { #endif /* DEVinstSize */ &JFETiSize, /* DEVmodSize */ &JFETmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ JFETbindCSC, /* DEVbindCSCComplex */ JFETbindCSCComplex, /* DEVbindCSCComplexToReal */ JFETbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ JFETnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/jfet/jfetnode.c b/src/spicelib/devices/jfet/jfetnode.c new file mode 100644 index 000000000..5a88f79ae --- /dev/null +++ b/src/spicelib/devices/jfet/jfetnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "jfetdefs.h" +#include "ngspice/sperror.h" + +int +JFETnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + JFETmodel *model = (JFETmodel *)inModel ; + JFETinstance *here ; + + /* loop through all the JFET models */ + for ( ; model != NULL ; model = model->JFETnextModel) + { + /* loop through all the instances of the model */ + for (here = model->JFETinstances ; here != NULL ; here = here->JFETnextInstance) + { + ckt->CKTnodeIsLinear [here->JFETsourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->JFETdrainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->JFETgateNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/jfet/jfetset.c b/src/spicelib/devices/jfet/jfetset.c index 4bcf17d70..026595d85 100644 --- a/src/spicelib/devices/jfet/jfetset.c +++ b/src/spicelib/devices/jfet/jfetset.c @@ -159,25 +159,25 @@ JFETsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(JFETdrainDrainPrimePtr,JFETdrainNode,JFETdrainPrimeNode) - TSTALLOC(JFETgateDrainPrimePtr,JFETgateNode,JFETdrainPrimeNode) - TSTALLOC(JFETgateSourcePrimePtr,JFETgateNode,JFETsourcePrimeNode) - TSTALLOC(JFETsourceSourcePrimePtr,JFETsourceNode,JFETsourcePrimeNode) - TSTALLOC(JFETdrainPrimeDrainPtr,JFETdrainPrimeNode,JFETdrainNode) - TSTALLOC(JFETdrainPrimeGatePtr,JFETdrainPrimeNode,JFETgateNode) - TSTALLOC(JFETdrainPrimeSourcePrimePtr,JFETdrainPrimeNode,JFETsourcePrimeNode) - TSTALLOC(JFETsourcePrimeGatePtr,JFETsourcePrimeNode,JFETgateNode) - TSTALLOC(JFETsourcePrimeSourcePtr,JFETsourcePrimeNode,JFETsourceNode) - TSTALLOC(JFETsourcePrimeDrainPrimePtr,JFETsourcePrimeNode,JFETdrainPrimeNode) - TSTALLOC(JFETdrainDrainPtr,JFETdrainNode,JFETdrainNode) - TSTALLOC(JFETgateGatePtr,JFETgateNode,JFETgateNode) - TSTALLOC(JFETsourceSourcePtr,JFETsourceNode,JFETsourceNode) - TSTALLOC(JFETdrainPrimeDrainPrimePtr,JFETdrainPrimeNode,JFETdrainPrimeNode) - TSTALLOC(JFETsourcePrimeSourcePrimePtr,JFETsourcePrimeNode,JFETsourcePrimeNode) + TSTALLOC(JFETdrainDrainPrimePtr,JFETdrainNode,JFETdrainPrimeNode); + TSTALLOC(JFETgateDrainPrimePtr,JFETgateNode,JFETdrainPrimeNode); + TSTALLOC(JFETgateSourcePrimePtr,JFETgateNode,JFETsourcePrimeNode); + TSTALLOC(JFETsourceSourcePrimePtr,JFETsourceNode,JFETsourcePrimeNode); + TSTALLOC(JFETdrainPrimeDrainPtr,JFETdrainPrimeNode,JFETdrainNode); + TSTALLOC(JFETdrainPrimeGatePtr,JFETdrainPrimeNode,JFETgateNode); + TSTALLOC(JFETdrainPrimeSourcePrimePtr,JFETdrainPrimeNode,JFETsourcePrimeNode); + TSTALLOC(JFETsourcePrimeGatePtr,JFETsourcePrimeNode,JFETgateNode); + TSTALLOC(JFETsourcePrimeSourcePtr,JFETsourcePrimeNode,JFETsourceNode); + TSTALLOC(JFETsourcePrimeDrainPrimePtr,JFETsourcePrimeNode,JFETdrainPrimeNode); + TSTALLOC(JFETdrainDrainPtr,JFETdrainNode,JFETdrainNode); + TSTALLOC(JFETgateGatePtr,JFETgateNode,JFETgateNode); + TSTALLOC(JFETsourceSourcePtr,JFETsourceNode,JFETsourceNode); + TSTALLOC(JFETdrainPrimeDrainPrimePtr,JFETdrainPrimeNode,JFETdrainPrimeNode); + TSTALLOC(JFETsourcePrimeSourcePrimePtr,JFETsourcePrimeNode,JFETsourcePrimeNode); } } return(OK); diff --git a/src/spicelib/devices/jfet2/Makefile.am b/src/spicelib/devices/jfet2/Makefile.am index eecc662df..f7fc40d57 100644 --- a/src/spicelib/devices/jfet2/Makefile.am +++ b/src/spicelib/devices/jfet2/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libjfet2_la_SOURCES += jfet2bindCSC.c endif +if KIRCHHOFF_WANTED +libjfet2_la_SOURCES += jfet2node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/jfet2/jfet2ext.h b/src/spicelib/devices/jfet2/jfet2ext.h index 2379d9aa5..478bbc350 100644 --- a/src/spicelib/devices/jfet2/jfet2ext.h +++ b/src/spicelib/devices/jfet2/jfet2ext.h @@ -28,3 +28,7 @@ extern int JFET2bindCSC (GENmodel*, CKTcircuit*) ; extern int JFET2bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int JFET2bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int JFET2nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/jfet2/jfet2init.c b/src/spicelib/devices/jfet2/jfet2init.c index 261a60a51..ca62e4d8e 100644 --- a/src/spicelib/devices/jfet2/jfet2init.c +++ b/src/spicelib/devices/jfet2/jfet2init.c @@ -73,12 +73,17 @@ SPICEdev JFET2info = { #endif /* DEVinstSize */ &JFET2iSize, /* DEVmodSize */ &JFET2mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ JFET2bindCSC, /* DEVbindCSCComplex */ JFET2bindCSCComplex, /* DEVbindCSCComplexToReal */ JFET2bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ JFET2nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/jfet2/jfet2node.c b/src/spicelib/devices/jfet2/jfet2node.c new file mode 100644 index 000000000..0b41bc3ac --- /dev/null +++ b/src/spicelib/devices/jfet2/jfet2node.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "jfet2defs.h" +#include "ngspice/sperror.h" + +int +JFET2nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + JFET2model *model = (JFET2model *)inModel ; + JFET2instance *here ; + + /* loop through all the JFET2 models */ + for ( ; model != NULL ; model = model->JFET2nextModel) + { + /* loop through all the instances of the model */ + for (here = model->JFET2instances ; here != NULL ; here = here->JFET2nextInstance) + { + ckt->CKTnodeIsLinear [here->JFET2sourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->JFET2drainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->JFET2gateNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/jfet2/jfet2set.c b/src/spicelib/devices/jfet2/jfet2set.c index af6964496..ece5ef269 100644 --- a/src/spicelib/devices/jfet2/jfet2set.c +++ b/src/spicelib/devices/jfet2/jfet2set.c @@ -99,25 +99,25 @@ JFET2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(JFET2drainDrainPrimePtr,JFET2drainNode,JFET2drainPrimeNode) - TSTALLOC(JFET2gateDrainPrimePtr,JFET2gateNode,JFET2drainPrimeNode) - TSTALLOC(JFET2gateSourcePrimePtr,JFET2gateNode,JFET2sourcePrimeNode) - TSTALLOC(JFET2sourceSourcePrimePtr,JFET2sourceNode,JFET2sourcePrimeNode) - TSTALLOC(JFET2drainPrimeDrainPtr,JFET2drainPrimeNode,JFET2drainNode) - TSTALLOC(JFET2drainPrimeGatePtr,JFET2drainPrimeNode,JFET2gateNode) - TSTALLOC(JFET2drainPrimeSourcePrimePtr,JFET2drainPrimeNode,JFET2sourcePrimeNode) - TSTALLOC(JFET2sourcePrimeGatePtr,JFET2sourcePrimeNode,JFET2gateNode) - TSTALLOC(JFET2sourcePrimeSourcePtr,JFET2sourcePrimeNode,JFET2sourceNode) - TSTALLOC(JFET2sourcePrimeDrainPrimePtr,JFET2sourcePrimeNode,JFET2drainPrimeNode) - TSTALLOC(JFET2drainDrainPtr,JFET2drainNode,JFET2drainNode) - TSTALLOC(JFET2gateGatePtr,JFET2gateNode,JFET2gateNode) - TSTALLOC(JFET2sourceSourcePtr,JFET2sourceNode,JFET2sourceNode) - TSTALLOC(JFET2drainPrimeDrainPrimePtr,JFET2drainPrimeNode,JFET2drainPrimeNode) - TSTALLOC(JFET2sourcePrimeSourcePrimePtr,JFET2sourcePrimeNode,JFET2sourcePrimeNode) + TSTALLOC(JFET2drainDrainPrimePtr,JFET2drainNode,JFET2drainPrimeNode); + TSTALLOC(JFET2gateDrainPrimePtr,JFET2gateNode,JFET2drainPrimeNode); + TSTALLOC(JFET2gateSourcePrimePtr,JFET2gateNode,JFET2sourcePrimeNode); + TSTALLOC(JFET2sourceSourcePrimePtr,JFET2sourceNode,JFET2sourcePrimeNode); + TSTALLOC(JFET2drainPrimeDrainPtr,JFET2drainPrimeNode,JFET2drainNode); + TSTALLOC(JFET2drainPrimeGatePtr,JFET2drainPrimeNode,JFET2gateNode); + TSTALLOC(JFET2drainPrimeSourcePrimePtr,JFET2drainPrimeNode,JFET2sourcePrimeNode); + TSTALLOC(JFET2sourcePrimeGatePtr,JFET2sourcePrimeNode,JFET2gateNode); + TSTALLOC(JFET2sourcePrimeSourcePtr,JFET2sourcePrimeNode,JFET2sourceNode); + TSTALLOC(JFET2sourcePrimeDrainPrimePtr,JFET2sourcePrimeNode,JFET2drainPrimeNode); + TSTALLOC(JFET2drainDrainPtr,JFET2drainNode,JFET2drainNode); + TSTALLOC(JFET2gateGatePtr,JFET2gateNode,JFET2gateNode); + TSTALLOC(JFET2sourceSourcePtr,JFET2sourceNode,JFET2sourceNode); + TSTALLOC(JFET2drainPrimeDrainPrimePtr,JFET2drainPrimeNode,JFET2drainPrimeNode); + TSTALLOC(JFET2sourcePrimeSourcePrimePtr,JFET2sourcePrimeNode,JFET2sourcePrimeNode); } } return(OK); diff --git a/src/spicelib/devices/ltra/ltrainit.c b/src/spicelib/devices/ltra/ltrainit.c index 40a41955d..db15f65b3 100644 --- a/src/spicelib/devices/ltra/ltrainit.c +++ b/src/spicelib/devices/ltra/ltrainit.c @@ -73,12 +73,17 @@ SPICEdev LTRAinfo = { #endif /* DEVinstSize */ <RAiSize, /* DEVmodSize */ <RAmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ LTRAbindCSC, /* DEVbindCSCComplex */ LTRAbindCSCComplex, /* DEVbindCSCComplexToReal */ LTRAbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/ltra/ltraset.c b/src/spicelib/devices/ltra/ltraset.c index 408a90dc5..273fc38ef 100644 --- a/src/spicelib/devices/ltra/ltraset.c +++ b/src/spicelib/devices/ltra/ltraset.c @@ -186,34 +186,34 @@ LTRAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) } /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(LTRAibr1Pos1Ptr, LTRAbrEq1, LTRAposNode1) - TSTALLOC(LTRAibr1Neg1Ptr, LTRAbrEq1, LTRAnegNode1) - TSTALLOC(LTRAibr1Pos2Ptr, LTRAbrEq1, LTRAposNode2) - TSTALLOC(LTRAibr1Neg2Ptr, LTRAbrEq1, LTRAnegNode2) - TSTALLOC(LTRAibr1Ibr1Ptr, LTRAbrEq1, LTRAbrEq1) - TSTALLOC(LTRAibr1Ibr2Ptr, LTRAbrEq1, LTRAbrEq2) - TSTALLOC(LTRAibr2Pos1Ptr, LTRAbrEq2, LTRAposNode1) - TSTALLOC(LTRAibr2Neg1Ptr, LTRAbrEq2, LTRAnegNode1) - TSTALLOC(LTRAibr2Pos2Ptr, LTRAbrEq2, LTRAposNode2) - TSTALLOC(LTRAibr2Neg2Ptr, LTRAbrEq2, LTRAnegNode2) - TSTALLOC(LTRAibr2Ibr1Ptr, LTRAbrEq2, LTRAbrEq1) - TSTALLOC(LTRAibr2Ibr2Ptr, LTRAbrEq2, LTRAbrEq2) - TSTALLOC(LTRApos1Ibr1Ptr, LTRAposNode1, LTRAbrEq1) - TSTALLOC(LTRAneg1Ibr1Ptr, LTRAnegNode1, LTRAbrEq1) - TSTALLOC(LTRApos2Ibr2Ptr, LTRAposNode2, LTRAbrEq2) - TSTALLOC(LTRAneg2Ibr2Ptr, LTRAnegNode2, LTRAbrEq2) + TSTALLOC(LTRAibr1Pos1Ptr, LTRAbrEq1, LTRAposNode1); + TSTALLOC(LTRAibr1Neg1Ptr, LTRAbrEq1, LTRAnegNode1); + TSTALLOC(LTRAibr1Pos2Ptr, LTRAbrEq1, LTRAposNode2); + TSTALLOC(LTRAibr1Neg2Ptr, LTRAbrEq1, LTRAnegNode2); + TSTALLOC(LTRAibr1Ibr1Ptr, LTRAbrEq1, LTRAbrEq1); + TSTALLOC(LTRAibr1Ibr2Ptr, LTRAbrEq1, LTRAbrEq2); + TSTALLOC(LTRAibr2Pos1Ptr, LTRAbrEq2, LTRAposNode1); + TSTALLOC(LTRAibr2Neg1Ptr, LTRAbrEq2, LTRAnegNode1); + TSTALLOC(LTRAibr2Pos2Ptr, LTRAbrEq2, LTRAposNode2); + TSTALLOC(LTRAibr2Neg2Ptr, LTRAbrEq2, LTRAnegNode2); + TSTALLOC(LTRAibr2Ibr1Ptr, LTRAbrEq2, LTRAbrEq1); + TSTALLOC(LTRAibr2Ibr2Ptr, LTRAbrEq2, LTRAbrEq2); + TSTALLOC(LTRApos1Ibr1Ptr, LTRAposNode1, LTRAbrEq1); + TSTALLOC(LTRAneg1Ibr1Ptr, LTRAnegNode1, LTRAbrEq1); + TSTALLOC(LTRApos2Ibr2Ptr, LTRAposNode2, LTRAbrEq2); + TSTALLOC(LTRAneg2Ibr2Ptr, LTRAnegNode2, LTRAbrEq2); /* * the following are done so that SMPpreOrder does not screw up on * occasion - for example, when one end of the lossy line is hanging */ - TSTALLOC(LTRApos1Pos1Ptr, LTRAposNode1, LTRAposNode1) - TSTALLOC(LTRAneg1Neg1Ptr, LTRAnegNode1, LTRAnegNode1) - TSTALLOC(LTRApos2Pos2Ptr, LTRAposNode2, LTRAposNode2) - TSTALLOC(LTRAneg2Neg2Ptr, LTRAnegNode2, LTRAnegNode2) + TSTALLOC(LTRApos1Pos1Ptr, LTRAposNode1, LTRAposNode1); + TSTALLOC(LTRAneg1Neg1Ptr, LTRAnegNode1, LTRAnegNode1); + TSTALLOC(LTRApos2Pos2Ptr, LTRAposNode2, LTRAposNode2); + TSTALLOC(LTRAneg2Neg2Ptr, LTRAnegNode2, LTRAnegNode2); } } return (OK); diff --git a/src/spicelib/devices/mes/Makefile.am b/src/spicelib/devices/mes/Makefile.am index 521751738..a005ee625 100644 --- a/src/spicelib/devices/mes/Makefile.am +++ b/src/spicelib/devices/mes/Makefile.am @@ -40,6 +40,10 @@ if UMFPACK_WANTED libmes_la_SOURCES += mesbindCSC.c endif +if KIRCHHOFF_WANTED +libmes_la_SOURCES += mesnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mes/mesext.h b/src/spicelib/devices/mes/mesext.h index f2d0a9c3b..f186b869a 100644 --- a/src/spicelib/devices/mes/mesext.h +++ b/src/spicelib/devices/mes/mesext.h @@ -23,9 +23,12 @@ extern int MESdisto(int,GENmodel*,CKTcircuit*); extern int MESnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int MESdSetup(GENmodel*,CKTcircuit*); - #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) extern int MESbindCSC (GENmodel*, CKTcircuit*) ; extern int MESbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MESbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MESnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mes/mesinit.c b/src/spicelib/devices/mes/mesinit.c index 062dbe0e6..ebab18176 100644 --- a/src/spicelib/devices/mes/mesinit.c +++ b/src/spicelib/devices/mes/mesinit.c @@ -73,12 +73,17 @@ SPICEdev MESinfo = { #endif /* DEVinstSize */ &MESiSize, /* DEVmodSize */ &MESmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MESbindCSC, /* DEVbindCSCComplex */ MESbindCSCComplex, /* DEVbindCSCComplexToReal */ MESbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MESnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mes/mesnode.c b/src/spicelib/devices/mes/mesnode.c new file mode 100644 index 000000000..4e546167d --- /dev/null +++ b/src/spicelib/devices/mes/mesnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mesdefs.h" +#include "ngspice/sperror.h" + +int +MESnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MESmodel *model = (MESmodel *)inModel ; + MESinstance *here ; + + /* loop through all the MES models */ + for ( ; model != NULL ; model = model->MESnextModel) + { + /* loop through all the instances of the model */ + for (here = model->MESinstances ; here != NULL ; here = here->MESnextInstance) + { + ckt->CKTnodeIsLinear [here->MESsourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESdrainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESgateNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mes/messetup.c b/src/spicelib/devices/mes/messetup.c index 129b93da6..a65449159 100644 --- a/src/spicelib/devices/mes/messetup.c +++ b/src/spicelib/devices/mes/messetup.c @@ -132,25 +132,25 @@ MESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MESdrainDrainPrimePtr,MESdrainNode,MESdrainPrimeNode) - TSTALLOC(MESgateDrainPrimePtr,MESgateNode,MESdrainPrimeNode) - TSTALLOC(MESgateSourcePrimePtr,MESgateNode,MESsourcePrimeNode) - TSTALLOC(MESsourceSourcePrimePtr,MESsourceNode,MESsourcePrimeNode) - TSTALLOC(MESdrainPrimeDrainPtr,MESdrainPrimeNode,MESdrainNode) - TSTALLOC(MESdrainPrimeGatePtr,MESdrainPrimeNode,MESgateNode) - TSTALLOC(MESdrainPrimeSourcePrimePtr,MESdrainPrimeNode,MESsourcePrimeNode) - TSTALLOC(MESsourcePrimeGatePtr,MESsourcePrimeNode,MESgateNode) - TSTALLOC(MESsourcePrimeSourcePtr,MESsourcePrimeNode,MESsourceNode) - TSTALLOC(MESsourcePrimeDrainPrimePtr,MESsourcePrimeNode,MESdrainPrimeNode) - TSTALLOC(MESdrainDrainPtr,MESdrainNode,MESdrainNode) - TSTALLOC(MESgateGatePtr,MESgateNode,MESgateNode) - TSTALLOC(MESsourceSourcePtr,MESsourceNode,MESsourceNode) - TSTALLOC(MESdrainPrimeDrainPrimePtr,MESdrainPrimeNode,MESdrainPrimeNode) - TSTALLOC(MESsourcePrimeSourcePrimePtr,MESsourcePrimeNode,MESsourcePrimeNode) + TSTALLOC(MESdrainDrainPrimePtr,MESdrainNode,MESdrainPrimeNode); + TSTALLOC(MESgateDrainPrimePtr,MESgateNode,MESdrainPrimeNode); + TSTALLOC(MESgateSourcePrimePtr,MESgateNode,MESsourcePrimeNode); + TSTALLOC(MESsourceSourcePrimePtr,MESsourceNode,MESsourcePrimeNode); + TSTALLOC(MESdrainPrimeDrainPtr,MESdrainPrimeNode,MESdrainNode); + TSTALLOC(MESdrainPrimeGatePtr,MESdrainPrimeNode,MESgateNode); + TSTALLOC(MESdrainPrimeSourcePrimePtr,MESdrainPrimeNode,MESsourcePrimeNode); + TSTALLOC(MESsourcePrimeGatePtr,MESsourcePrimeNode,MESgateNode); + TSTALLOC(MESsourcePrimeSourcePtr,MESsourcePrimeNode,MESsourceNode); + TSTALLOC(MESsourcePrimeDrainPrimePtr,MESsourcePrimeNode,MESdrainPrimeNode); + TSTALLOC(MESdrainDrainPtr,MESdrainNode,MESdrainNode); + TSTALLOC(MESgateGatePtr,MESgateNode,MESgateNode); + TSTALLOC(MESsourceSourcePtr,MESsourceNode,MESsourceNode); + TSTALLOC(MESdrainPrimeDrainPrimePtr,MESdrainPrimeNode,MESdrainPrimeNode); + TSTALLOC(MESsourcePrimeSourcePrimePtr,MESsourcePrimeNode,MESsourcePrimeNode); } } return(OK); diff --git a/src/spicelib/devices/mesa/Makefile.am b/src/spicelib/devices/mesa/Makefile.am index 825485bff..ae5c75c58 100644 --- a/src/spicelib/devices/mesa/Makefile.am +++ b/src/spicelib/devices/mesa/Makefile.am @@ -37,6 +37,10 @@ if UMFPACK_WANTED libmesa_la_SOURCES += mesabindCSC.c endif +if KIRCHHOFF_WANTED +libmesa_la_SOURCES += mesanode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mesa/mesaext.h b/src/spicelib/devices/mesa/mesaext.h index fba7871bd..effa1bac5 100644 --- a/src/spicelib/devices/mesa/mesaext.h +++ b/src/spicelib/devices/mesa/mesaext.h @@ -24,3 +24,7 @@ extern int MESAbindCSC (GENmodel*, CKTcircuit*) ; extern int MESAbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MESAbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MESAnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mesa/mesainit.c b/src/spicelib/devices/mesa/mesainit.c index d887e89d4..750ce4db5 100644 --- a/src/spicelib/devices/mesa/mesainit.c +++ b/src/spicelib/devices/mesa/mesainit.c @@ -73,12 +73,17 @@ SPICEdev MESAinfo = { #endif /* DEVinstSize */ &MESAiSize, /* DEVmodSize */ &MESAmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MESAbindCSC, /* DEVbindCSCComplex */ MESAbindCSCComplex, /* DEVbindCSCComplexToReal */ MESAbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MESAnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mesa/mesanode.c b/src/spicelib/devices/mesa/mesanode.c new file mode 100644 index 000000000..857282738 --- /dev/null +++ b/src/spicelib/devices/mesa/mesanode.c @@ -0,0 +1,31 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mesadefs.h" +#include "ngspice/sperror.h" + +int +MESAnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MESAmodel *model = (MESAmodel *)inModel ; + MESAinstance *here ; + + /* loop through all the MESA models */ + for ( ; model != NULL ; model = model->MESAnextModel) + { + /* loop through all the instances of the model */ + for (here = model->MESAinstances ; here != NULL ; here = here->MESAnextInstance) + { + ckt->CKTnodeIsLinear [here->MESAsourcePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESAdrainPrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESAgatePrimeNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESAsourcePrmPrmNode] = 0 ; + ckt->CKTnodeIsLinear [here->MESAdrainPrmPrmNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mesa/mesasetup.c b/src/spicelib/devices/mesa/mesasetup.c index c13cdf4eb..ed775721c 100644 --- a/src/spicelib/devices/mesa/mesasetup.c +++ b/src/spicelib/devices/mesa/mesasetup.c @@ -369,38 +369,38 @@ MESAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MESAdrainDrainPtr,MESAdrainNode,MESAdrainNode) - TSTALLOC(MESAdrainPrimeDrainPrimePtr,MESAdrainPrimeNode,MESAdrainPrimeNode) - TSTALLOC(MESAdrainPrmPrmDrainPrmPrmPtr,MESAdrainPrmPrmNode,MESAdrainPrmPrmNode) - TSTALLOC(MESAgateGatePtr,MESAgateNode,MESAgateNode) - TSTALLOC(MESAgatePrimeGatePrimePtr,MESAgatePrimeNode,MESAgatePrimeNode) - TSTALLOC(MESAsourceSourcePtr,MESAsourceNode,MESAsourceNode) - TSTALLOC(MESAsourcePrimeSourcePrimePtr,MESAsourcePrimeNode,MESAsourcePrimeNode) - TSTALLOC(MESAsourcePrmPrmSourcePrmPrmPtr,MESAsourcePrmPrmNode,MESAsourcePrmPrmNode) - TSTALLOC(MESAdrainDrainPrimePtr,MESAdrainNode,MESAdrainPrimeNode) - TSTALLOC(MESAdrainPrimeDrainPtr,MESAdrainPrimeNode,MESAdrainNode) - TSTALLOC(MESAgatePrimeDrainPrimePtr,MESAgatePrimeNode,MESAdrainPrimeNode) - TSTALLOC(MESAdrainPrimeGatePrimePtr,MESAdrainPrimeNode,MESAgatePrimeNode) - TSTALLOC(MESAgatePrimeSourcePrimePtr,MESAgatePrimeNode,MESAsourcePrimeNode) - TSTALLOC(MESAsourcePrimeGatePrimePtr,MESAsourcePrimeNode,MESAgatePrimeNode) - TSTALLOC(MESAsourceSourcePrimePtr,MESAsourceNode,MESAsourcePrimeNode) - TSTALLOC(MESAsourcePrimeSourcePtr,MESAsourcePrimeNode,MESAsourceNode) - TSTALLOC(MESAdrainPrimeSourcePrimePtr,MESAdrainPrimeNode,MESAsourcePrimeNode) - TSTALLOC(MESAsourcePrimeDrainPrimePtr,MESAsourcePrimeNode,MESAdrainPrimeNode) - TSTALLOC(MESAgatePrimeGatePtr,MESAgatePrimeNode,MESAgateNode) - TSTALLOC(MESAgateGatePrimePtr,MESAgateNode,MESAgatePrimeNode) - TSTALLOC(MESAsourcePrmPrmSourcePrimePtr,MESAsourcePrmPrmNode,MESAsourcePrimeNode) - TSTALLOC(MESAsourcePrimeSourcePrmPrmPtr,MESAsourcePrimeNode,MESAsourcePrmPrmNode) - TSTALLOC(MESAsourcePrmPrmGatePrimePtr,MESAsourcePrmPrmNode,MESAgatePrimeNode) - TSTALLOC(MESAgatePrimeSourcePrmPrmPtr,MESAgatePrimeNode,MESAsourcePrmPrmNode) - TSTALLOC(MESAdrainPrmPrmDrainPrimePtr,MESAdrainPrmPrmNode,MESAdrainPrimeNode) - TSTALLOC(MESAdrainPrimeDrainPrmPrmPtr,MESAdrainPrimeNode,MESAdrainPrmPrmNode) - TSTALLOC(MESAdrainPrmPrmGatePrimePtr,MESAdrainPrmPrmNode,MESAgatePrimeNode) - TSTALLOC(MESAgatePrimeDrainPrmPrmPtr,MESAgatePrimeNode,MESAdrainPrmPrmNode) + TSTALLOC(MESAdrainDrainPtr,MESAdrainNode,MESAdrainNode); + TSTALLOC(MESAdrainPrimeDrainPrimePtr,MESAdrainPrimeNode,MESAdrainPrimeNode); + TSTALLOC(MESAdrainPrmPrmDrainPrmPrmPtr,MESAdrainPrmPrmNode,MESAdrainPrmPrmNode); + TSTALLOC(MESAgateGatePtr,MESAgateNode,MESAgateNode); + TSTALLOC(MESAgatePrimeGatePrimePtr,MESAgatePrimeNode,MESAgatePrimeNode); + TSTALLOC(MESAsourceSourcePtr,MESAsourceNode,MESAsourceNode); + TSTALLOC(MESAsourcePrimeSourcePrimePtr,MESAsourcePrimeNode,MESAsourcePrimeNode); + TSTALLOC(MESAsourcePrmPrmSourcePrmPrmPtr,MESAsourcePrmPrmNode,MESAsourcePrmPrmNode); + TSTALLOC(MESAdrainDrainPrimePtr,MESAdrainNode,MESAdrainPrimeNode); + TSTALLOC(MESAdrainPrimeDrainPtr,MESAdrainPrimeNode,MESAdrainNode); + TSTALLOC(MESAgatePrimeDrainPrimePtr,MESAgatePrimeNode,MESAdrainPrimeNode); + TSTALLOC(MESAdrainPrimeGatePrimePtr,MESAdrainPrimeNode,MESAgatePrimeNode); + TSTALLOC(MESAgatePrimeSourcePrimePtr,MESAgatePrimeNode,MESAsourcePrimeNode); + TSTALLOC(MESAsourcePrimeGatePrimePtr,MESAsourcePrimeNode,MESAgatePrimeNode) ; + TSTALLOC(MESAsourceSourcePrimePtr,MESAsourceNode,MESAsourcePrimeNode); + TSTALLOC(MESAsourcePrimeSourcePtr,MESAsourcePrimeNode,MESAsourceNode); + TSTALLOC(MESAdrainPrimeSourcePrimePtr,MESAdrainPrimeNode,MESAsourcePrimeNode); + TSTALLOC(MESAsourcePrimeDrainPrimePtr,MESAsourcePrimeNode,MESAdrainPrimeNode); + TSTALLOC(MESAgatePrimeGatePtr,MESAgatePrimeNode,MESAgateNode); + TSTALLOC(MESAgateGatePrimePtr,MESAgateNode,MESAgatePrimeNode); + TSTALLOC(MESAsourcePrmPrmSourcePrimePtr,MESAsourcePrmPrmNode,MESAsourcePrimeNode); + TSTALLOC(MESAsourcePrimeSourcePrmPrmPtr,MESAsourcePrimeNode,MESAsourcePrmPrmNode); + TSTALLOC(MESAsourcePrmPrmGatePrimePtr,MESAsourcePrmPrmNode,MESAgatePrimeNode); + TSTALLOC(MESAgatePrimeSourcePrmPrmPtr,MESAgatePrimeNode,MESAsourcePrmPrmNode); + TSTALLOC(MESAdrainPrmPrmDrainPrimePtr,MESAdrainPrmPrmNode,MESAdrainPrimeNode); + TSTALLOC(MESAdrainPrimeDrainPrmPrmPtr,MESAdrainPrimeNode,MESAdrainPrmPrmNode); + TSTALLOC(MESAdrainPrmPrmGatePrimePtr,MESAdrainPrmPrmNode,MESAgatePrimeNode); + TSTALLOC(MESAgatePrimeDrainPrmPrmPtr,MESAgatePrimeNode,MESAdrainPrmPrmNode); } } return(OK); diff --git a/src/spicelib/devices/mos1/Makefile.am b/src/spicelib/devices/mos1/Makefile.am index 3a6e4725c..2896ee125 100644 --- a/src/spicelib/devices/mos1/Makefile.am +++ b/src/spicelib/devices/mos1/Makefile.am @@ -46,6 +46,10 @@ if UMFPACK_WANTED libmos1_la_SOURCES += mos1bindCSC.c endif +if KIRCHHOFF_WANTED +libmos1_la_SOURCES += mos1node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mos1/mos1ext.h b/src/spicelib/devices/mos1/mos1ext.h index d2eeb7faf..64ffc7589 100644 --- a/src/spicelib/devices/mos1/mos1ext.h +++ b/src/spicelib/devices/mos1/mos1ext.h @@ -34,3 +34,7 @@ extern int MOS1bindCSC (GENmodel*, CKTcircuit*) ; extern int MOS1bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MOS1bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MOS1nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mos1/mos1init.c b/src/spicelib/devices/mos1/mos1init.c index c88444c9c..87a237ed1 100644 --- a/src/spicelib/devices/mos1/mos1init.c +++ b/src/spicelib/devices/mos1/mos1init.c @@ -73,12 +73,17 @@ SPICEdev MOS1info = { #endif /* DEVinstSize */ &MOS1iSize, /* DEVmodSize */ &MOS1mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MOS1bindCSC, /* DEVbindCSCComplex */ MOS1bindCSCComplex, /* DEVbindCSCComplexToReal */ MOS1bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MOS1nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mos1/mos1load.c b/src/spicelib/devices/mos1/mos1load.c index 78904c25a..fbec07e76 100644 --- a/src/spicelib/devices/mos1/mos1load.c +++ b/src/spicelib/devices/mos1/mos1load.c @@ -33,13 +33,13 @@ MOS1load(GENmodel *inModel, CKTcircuit *ckt) double cbhat; double cdhat; double cdrain; - double cdreq; + double cdreq, cdreq_fvk ; double ceq; - double ceqbd; - double ceqbs; - double ceqgb; - double ceqgd; - double ceqgs; + double ceqbd, ceqbd_fvk ; + double ceqbs, ceqbs_fvk ; + double ceqgb, ceqgb_fvk ; + double ceqgd, ceqgd_fvk ; + double ceqgs, ceqgs_fvk ; double delvbd; double delvbs; double delvds; @@ -847,10 +847,13 @@ next1: if(vbs <= -3*vt) { */ gcgs=0; ceqgs=0; + ceqgs_fvk = 0 ; gcgd=0; ceqgd=0; + ceqgd_fvk = 0 ; gcgb=0; ceqgb=0; + ceqgb_fvk = 0 ; } else { if(capgs == 0) *(ckt->CKTstate0 + here->MOS1cqgs) =0; if(capgd == 0) *(ckt->CKTstate0 + here->MOS1cqgd) =0; @@ -867,10 +870,13 @@ next1: if(vbs <= -3*vt) { if(error) return(error); ceqgs=ceqgs-gcgs*vgs+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS1qgs); + ceqgs_fvk = *(ckt->CKTstate0 + here->MOS1cqgs) ; ceqgd=ceqgd-gcgd*vgd+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS1qgd); + ceqgd_fvk = *(ckt->CKTstate0 + here->MOS1cqgd) ; ceqgb=ceqgb-gcgb*vgb+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS1qgb); + ceqgb_fvk = *(ckt->CKTstate0 + here->MOS1cqgb) ; } /* * store charge storage info for meyer's cap in lx table @@ -881,18 +887,22 @@ next1: if(vbs <= -3*vt) { */ ceqbs = model->MOS1type * (here->MOS1cbs-(here->MOS1gbs)*vbs); + ceqbs_fvk = model->MOS1type * here->MOS1cbs ; ceqbd = model->MOS1type * (here->MOS1cbd-(here->MOS1gbd)*vbd); + ceqbd_fvk = model->MOS1type * here->MOS1cbd ; if (here->MOS1mode >= 0) { xnrm=1; xrev=0; cdreq=model->MOS1type*(cdrain-here->MOS1gds*vds- here->MOS1gm*vgs-here->MOS1gmbs*vbs); + cdreq_fvk = model->MOS1type * cdrain ; } else { xnrm=0; xrev=1; cdreq = -(model->MOS1type)*(cdrain-here->MOS1gds*(-vds)- here->MOS1gm*vgd-here->MOS1gmbs*vbd); + cdreq_fvk = - model->MOS1type * cdrain ; } *(ckt->CKTrhs + here->MOS1gNode) -= (model->MOS1type * (ceqgs + ceqgb + ceqgd)); @@ -934,6 +944,26 @@ next1: if(vbs <= -3*vt) { *(here->MOS1SPbPtr) += (-here->MOS1gbs-(xnrm-xrev)*here->MOS1gmbs); *(here->MOS1SPdpPtr) += (-here->MOS1gds-xrev* (here->MOS1gm+here->MOS1gmbs)); + +#ifdef KIRCHHOFF + /* KCL verification - Linear-Dynamic Part */ + *(ckt->CKTfvk+here->MOS1gNode) += model->MOS1type * (ceqgs_fvk + ceqgb_fvk + ceqgd_fvk) ; + *(ckt->CKTfvk+here->MOS1bNode) += ceqbs_fvk + ceqbd_fvk - model->MOS1type * ceqgb_fvk ; + *(ckt->CKTfvk+here->MOS1dNodePrime) -= (ceqbd_fvk - cdreq_fvk + model->MOS1type * ceqgd_fvk) ; + *(ckt->CKTfvk+here->MOS1sNodePrime) -= (cdreq_fvk + ceqbs_fvk + model->MOS1type * ceqgs_fvk) ; + + + /* KCL verification - Linear-Static Part */ + *(ckt->CKTfvk+here->MOS1dNode) += here->MOS1drainConductance * *(ckt->CKTrhsOld+here->MOS1dNode) ; + *(ckt->CKTfvk+here->MOS1sNode) += here->MOS1sourceConductance * *(ckt->CKTrhsOld+here->MOS1sNode) ; + *(ckt->CKTfvk+here->MOS1dNodePrime) += here->MOS1drainConductance * *(ckt->CKTrhsOld+here->MOS1dNodePrime) ; + *(ckt->CKTfvk+here->MOS1sNodePrime) += here->MOS1sourceConductance * *(ckt->CKTrhsOld+here->MOS1sNodePrime) ; + *(ckt->CKTfvk+here->MOS1dNode) -= here->MOS1drainConductance * *(ckt->CKTrhsOld+here->MOS1dNodePrime) ; + *(ckt->CKTfvk+here->MOS1sNode) -= here->MOS1sourceConductance * *(ckt->CKTrhsOld+here->MOS1sNodePrime) ; + *(ckt->CKTfvk+here->MOS1dNodePrime) -= here->MOS1drainConductance * *(ckt->CKTrhsOld+here->MOS1dNode) ; + *(ckt->CKTfvk+here->MOS1sNodePrime) -= here->MOS1sourceConductance * *(ckt->CKTrhsOld+here->MOS1sNode) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/mos1/mos1node.c b/src/spicelib/devices/mos1/mos1node.c new file mode 100644 index 000000000..787e09ee5 --- /dev/null +++ b/src/spicelib/devices/mos1/mos1node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mos1defs.h" +#include "ngspice/sperror.h" + +int +MOS1nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MOS1model *model = (MOS1model *)inModel ; + MOS1instance *here ; + + /* loop through all the MOS1 models */ + for ( ; model != NULL ; model = model->MOS1nextModel) + { + /* loop through all the instances of the model */ + for (here = model->MOS1instances ; here != NULL ; here = here->MOS1nextInstance) + { + ckt->CKTnodeIsLinear [here->MOS1dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS1sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS1gNode] = 0 ; + ckt->CKTnodeIsLinear [here->MOS1bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mos1/mos1set.c b/src/spicelib/devices/mos1/mos1set.c index 32a4c37b9..521ff3fbf 100644 --- a/src/spicelib/devices/mos1/mos1set.c +++ b/src/spicelib/devices/mos1/mos1set.c @@ -180,31 +180,31 @@ MOS1setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} - TSTALLOC(MOS1DdPtr,MOS1dNode,MOS1dNode) - TSTALLOC(MOS1GgPtr,MOS1gNode,MOS1gNode) - TSTALLOC(MOS1SsPtr,MOS1sNode,MOS1sNode) - TSTALLOC(MOS1BbPtr,MOS1bNode,MOS1bNode) - TSTALLOC(MOS1DPdpPtr,MOS1dNodePrime,MOS1dNodePrime) - TSTALLOC(MOS1SPspPtr,MOS1sNodePrime,MOS1sNodePrime) - TSTALLOC(MOS1DdpPtr,MOS1dNode,MOS1dNodePrime) - TSTALLOC(MOS1GbPtr,MOS1gNode,MOS1bNode) - TSTALLOC(MOS1GdpPtr,MOS1gNode,MOS1dNodePrime) - TSTALLOC(MOS1GspPtr,MOS1gNode,MOS1sNodePrime) - TSTALLOC(MOS1SspPtr,MOS1sNode,MOS1sNodePrime) - TSTALLOC(MOS1BdpPtr,MOS1bNode,MOS1dNodePrime) - TSTALLOC(MOS1BspPtr,MOS1bNode,MOS1sNodePrime) - TSTALLOC(MOS1DPspPtr,MOS1dNodePrime,MOS1sNodePrime) - TSTALLOC(MOS1DPdPtr,MOS1dNodePrime,MOS1dNode) - TSTALLOC(MOS1BgPtr,MOS1bNode,MOS1gNode) - TSTALLOC(MOS1DPgPtr,MOS1dNodePrime,MOS1gNode) - TSTALLOC(MOS1SPgPtr,MOS1sNodePrime,MOS1gNode) - TSTALLOC(MOS1SPsPtr,MOS1sNodePrime,MOS1sNode) - TSTALLOC(MOS1DPbPtr,MOS1dNodePrime,MOS1bNode) - TSTALLOC(MOS1SPbPtr,MOS1sNodePrime,MOS1bNode) - TSTALLOC(MOS1SPdpPtr,MOS1sNodePrime,MOS1dNodePrime) +} } while(0) + TSTALLOC(MOS1DdPtr,MOS1dNode,MOS1dNode); + TSTALLOC(MOS1GgPtr,MOS1gNode,MOS1gNode); + TSTALLOC(MOS1SsPtr,MOS1sNode,MOS1sNode); + TSTALLOC(MOS1BbPtr,MOS1bNode,MOS1bNode); + TSTALLOC(MOS1DPdpPtr,MOS1dNodePrime,MOS1dNodePrime); + TSTALLOC(MOS1SPspPtr,MOS1sNodePrime,MOS1sNodePrime); + TSTALLOC(MOS1DdpPtr,MOS1dNode,MOS1dNodePrime); + TSTALLOC(MOS1GbPtr,MOS1gNode,MOS1bNode); + TSTALLOC(MOS1GdpPtr,MOS1gNode,MOS1dNodePrime); + TSTALLOC(MOS1GspPtr,MOS1gNode,MOS1sNodePrime); + TSTALLOC(MOS1SspPtr,MOS1sNode,MOS1sNodePrime); + TSTALLOC(MOS1BdpPtr,MOS1bNode,MOS1dNodePrime); + TSTALLOC(MOS1BspPtr,MOS1bNode,MOS1sNodePrime); + TSTALLOC(MOS1DPspPtr,MOS1dNodePrime,MOS1sNodePrime); + TSTALLOC(MOS1DPdPtr,MOS1dNodePrime,MOS1dNode); + TSTALLOC(MOS1BgPtr,MOS1bNode,MOS1gNode); + TSTALLOC(MOS1DPgPtr,MOS1dNodePrime,MOS1gNode); + TSTALLOC(MOS1SPgPtr,MOS1sNodePrime,MOS1gNode); + TSTALLOC(MOS1SPsPtr,MOS1sNodePrime,MOS1sNode); + TSTALLOC(MOS1DPbPtr,MOS1dNodePrime,MOS1bNode); + TSTALLOC(MOS1SPbPtr,MOS1sNodePrime,MOS1bNode); + TSTALLOC(MOS1SPdpPtr,MOS1sNodePrime,MOS1dNodePrime); } } diff --git a/src/spicelib/devices/mos1/mos1temp.c b/src/spicelib/devices/mos1/mos1temp.c index 3764bc96a..e73b6dada 100644 --- a/src/spicelib/devices/mos1/mos1temp.c +++ b/src/spicelib/devices/mos1/mos1temp.c @@ -51,7 +51,11 @@ MOS1temp(GENmodel *inModel, CKTcircuit *ckt) pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); /* now model parameter preprocessing */ - + if (model->MOS1phi <= 0.0) { + SPfrontEnd->IFerror (ERR_FATAL, + "%s: Phi is not positive.",&model->MOS1modName); + return(E_BADPARM); + } if(!model->MOS1oxideThicknessGiven || model->MOS1oxideThickness == 0) { model->MOS1oxideCapFactor = 0; } else { diff --git a/src/spicelib/devices/mos2/Makefile.am b/src/spicelib/devices/mos2/Makefile.am index dd8e1f409..2a1b4a2c0 100644 --- a/src/spicelib/devices/mos2/Makefile.am +++ b/src/spicelib/devices/mos2/Makefile.am @@ -46,6 +46,10 @@ if UMFPACK_WANTED libmos2_la_SOURCES += mos2bindCSC.c endif +if KIRCHHOFF_WANTED +libmos2_la_SOURCES += mos2node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mos2/mos2ext.h b/src/spicelib/devices/mos2/mos2ext.h index e9a52ee7e..19ca56036 100644 --- a/src/spicelib/devices/mos2/mos2ext.h +++ b/src/spicelib/devices/mos2/mos2ext.h @@ -27,7 +27,6 @@ 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*); #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) @@ -35,3 +34,7 @@ extern int MOS2bindCSC (GENmodel*, CKTcircuit*) ; extern int MOS2bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MOS2bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MOS2nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mos2/mos2init.c b/src/spicelib/devices/mos2/mos2init.c index df9cf04be..fef78131f 100644 --- a/src/spicelib/devices/mos2/mos2init.c +++ b/src/spicelib/devices/mos2/mos2init.c @@ -73,12 +73,17 @@ SPICEdev MOS2info = { #endif /* DEVinstSize */ &MOS2iSize, /* DEVmodSize */ &MOS2mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MOS2bindCSC, /* DEVbindCSCComplex */ MOS2bindCSCComplex, /* DEVbindCSCComplexToReal */ MOS2bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MOS2nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mos2/mos2node.c b/src/spicelib/devices/mos2/mos2node.c new file mode 100644 index 000000000..287ab8156 --- /dev/null +++ b/src/spicelib/devices/mos2/mos2node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mos2defs.h" +#include "ngspice/sperror.h" + +int +MOS2nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MOS2model *model = (MOS2model *)inModel ; + MOS2instance *here ; + + /* loop through all the MOS2 models */ + for ( ; model != NULL ; model = model->MOS2nextModel) + { + /* loop through all the instances of the model */ + for (here = model->MOS2instances ; here != NULL ; here = here->MOS2nextInstance) + { + ckt->CKTnodeIsLinear [here->MOS2dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS2sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS2gNode] = 0 ; + ckt->CKTnodeIsLinear [here->MOS2bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mos2/mos2set.c b/src/spicelib/devices/mos2/mos2set.c index 3bf2fb4ba..c86daaf37 100644 --- a/src/spicelib/devices/mos2/mos2set.c +++ b/src/spicelib/devices/mos2/mos2set.c @@ -202,32 +202,32 @@ MOS2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MOS2DdPtr, MOS2dNode, MOS2dNode) - TSTALLOC(MOS2GgPtr, MOS2gNode, MOS2gNode) - TSTALLOC(MOS2SsPtr, MOS2sNode, MOS2sNode) - TSTALLOC(MOS2BbPtr, MOS2bNode, MOS2bNode) - TSTALLOC(MOS2DPdpPtr, MOS2dNodePrime, MOS2dNodePrime) - TSTALLOC(MOS2SPspPtr, MOS2sNodePrime, MOS2sNodePrime) - TSTALLOC(MOS2DdpPtr, MOS2dNode, MOS2dNodePrime) - TSTALLOC(MOS2GbPtr, MOS2gNode, MOS2bNode) - TSTALLOC(MOS2GdpPtr, MOS2gNode, MOS2dNodePrime) - TSTALLOC(MOS2GspPtr, MOS2gNode, MOS2sNodePrime) - TSTALLOC(MOS2SspPtr, MOS2sNode, MOS2sNodePrime) - TSTALLOC(MOS2BdpPtr, MOS2bNode, MOS2dNodePrime) - TSTALLOC(MOS2BspPtr, MOS2bNode, MOS2sNodePrime) - TSTALLOC(MOS2DPspPtr, MOS2dNodePrime, MOS2sNodePrime) - TSTALLOC(MOS2DPdPtr, MOS2dNodePrime, MOS2dNode) - TSTALLOC(MOS2BgPtr, MOS2bNode, MOS2gNode) - TSTALLOC(MOS2DPgPtr, MOS2dNodePrime, MOS2gNode) - TSTALLOC(MOS2SPgPtr, MOS2sNodePrime, MOS2gNode) - TSTALLOC(MOS2SPsPtr, MOS2sNodePrime, MOS2sNode) - TSTALLOC(MOS2DPbPtr, MOS2dNodePrime, MOS2bNode) - TSTALLOC(MOS2SPbPtr, MOS2sNodePrime, MOS2bNode) - TSTALLOC(MOS2SPdpPtr, MOS2sNodePrime, MOS2dNodePrime) + TSTALLOC(MOS2DdPtr, MOS2dNode, MOS2dNode); + TSTALLOC(MOS2GgPtr, MOS2gNode, MOS2gNode); + TSTALLOC(MOS2SsPtr, MOS2sNode, MOS2sNode); + TSTALLOC(MOS2BbPtr, MOS2bNode, MOS2bNode); + TSTALLOC(MOS2DPdpPtr, MOS2dNodePrime, MOS2dNodePrime); + TSTALLOC(MOS2SPspPtr, MOS2sNodePrime, MOS2sNodePrime); + TSTALLOC(MOS2DdpPtr, MOS2dNode, MOS2dNodePrime); + TSTALLOC(MOS2GbPtr, MOS2gNode, MOS2bNode); + TSTALLOC(MOS2GdpPtr, MOS2gNode, MOS2dNodePrime); + TSTALLOC(MOS2GspPtr, MOS2gNode, MOS2sNodePrime); + TSTALLOC(MOS2SspPtr, MOS2sNode, MOS2sNodePrime); + TSTALLOC(MOS2BdpPtr, MOS2bNode, MOS2dNodePrime); + TSTALLOC(MOS2BspPtr, MOS2bNode, MOS2sNodePrime); + TSTALLOC(MOS2DPspPtr, MOS2dNodePrime, MOS2sNodePrime); + TSTALLOC(MOS2DPdPtr, MOS2dNodePrime, MOS2dNode); + TSTALLOC(MOS2BgPtr, MOS2bNode, MOS2gNode); + TSTALLOC(MOS2DPgPtr, MOS2dNodePrime, MOS2gNode); + TSTALLOC(MOS2SPgPtr, MOS2sNodePrime, MOS2gNode); + TSTALLOC(MOS2SPsPtr, MOS2sNodePrime, MOS2sNode); + TSTALLOC(MOS2DPbPtr, MOS2dNodePrime, MOS2bNode); + TSTALLOC(MOS2SPbPtr, MOS2sNodePrime, MOS2bNode); + TSTALLOC(MOS2SPdpPtr, MOS2sNodePrime, MOS2dNodePrime); } } diff --git a/src/spicelib/devices/mos2/mos2temp.c b/src/spicelib/devices/mos2/mos2temp.c index 982c784dd..9f8b19a7e 100644 --- a/src/spicelib/devices/mos2/mos2temp.c +++ b/src/spicelib/devices/mos2/mos2temp.c @@ -53,7 +53,11 @@ MOS2temp(GENmodel *inModel, CKTcircuit *ckt) arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); - + if (model->MOS2phi <= 0.0) { + SPfrontEnd->IFerror (ERR_FATAL, + "%s: Phi is not positive.",&model->MOS2modName); + return(E_BADPARM); + } if(!model->MOS2oxideThicknessGiven) { model->MOS2oxideThickness = 1e-7; } diff --git a/src/spicelib/devices/mos3/Makefile.am b/src/spicelib/devices/mos3/Makefile.am index 32776ab94..574bdbc1c 100644 --- a/src/spicelib/devices/mos3/Makefile.am +++ b/src/spicelib/devices/mos3/Makefile.am @@ -46,6 +46,10 @@ if UMFPACK_WANTED libmos3_la_SOURCES += mos3bindCSC.c endif +if KIRCHHOFF_WANTED +libmos3_la_SOURCES += mos3node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mos3/mos3ext.h b/src/spicelib/devices/mos3/mos3ext.h index 39063695d..b8b8ae708 100644 --- a/src/spicelib/devices/mos3/mos3ext.h +++ b/src/spicelib/devices/mos3/mos3ext.h @@ -34,3 +34,7 @@ extern int MOS3bindCSC (GENmodel*, CKTcircuit*) ; extern int MOS3bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MOS3bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MOS3nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mos3/mos3init.c b/src/spicelib/devices/mos3/mos3init.c index b9d7f83cc..592fde86f 100644 --- a/src/spicelib/devices/mos3/mos3init.c +++ b/src/spicelib/devices/mos3/mos3init.c @@ -73,12 +73,17 @@ SPICEdev MOS3info = { #endif /* DEVinstSize */ &MOS3iSize, /* DEVmodSize */ &MOS3mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MOS3bindCSC, /* DEVbindCSCComplex */ MOS3bindCSCComplex, /* DEVbindCSCComplexToReal */ MOS3bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MOS3nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mos3/mos3node.c b/src/spicelib/devices/mos3/mos3node.c new file mode 100644 index 000000000..09a7c2efa --- /dev/null +++ b/src/spicelib/devices/mos3/mos3node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mos3defs.h" +#include "ngspice/sperror.h" + +int +MOS3nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MOS3model *model = (MOS3model *)inModel ; + MOS3instance *here ; + + /* loop through all the MOS3 models */ + for ( ; model != NULL ; model = model->MOS3nextModel) + { + /* loop through all the instances of the model */ + for (here = model->MOS3instances ; here != NULL ; here = here->MOS3nextInstance) + { + ckt->CKTnodeIsLinear [here->MOS3dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS3sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS3gNode] = 0 ; + ckt->CKTnodeIsLinear [here->MOS3bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mos3/mos3set.c b/src/spicelib/devices/mos3/mos3set.c index 334160723..5ff4ca879 100644 --- a/src/spicelib/devices/mos3/mos3set.c +++ b/src/spicelib/devices/mos3/mos3set.c @@ -227,32 +227,32 @@ MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MOS3DdPtr, MOS3dNode, MOS3dNode) - TSTALLOC(MOS3GgPtr, MOS3gNode, MOS3gNode) - TSTALLOC(MOS3SsPtr, MOS3sNode, MOS3sNode) - TSTALLOC(MOS3BbPtr, MOS3bNode, MOS3bNode) - TSTALLOC(MOS3DPdpPtr, MOS3dNodePrime, MOS3dNodePrime) - TSTALLOC(MOS3SPspPtr, MOS3sNodePrime, MOS3sNodePrime) - TSTALLOC(MOS3DdpPtr, MOS3dNode, MOS3dNodePrime) - TSTALLOC(MOS3GbPtr, MOS3gNode, MOS3bNode) - TSTALLOC(MOS3GdpPtr, MOS3gNode, MOS3dNodePrime) - TSTALLOC(MOS3GspPtr, MOS3gNode, MOS3sNodePrime) - TSTALLOC(MOS3SspPtr, MOS3sNode, MOS3sNodePrime) - TSTALLOC(MOS3BdpPtr, MOS3bNode, MOS3dNodePrime) - TSTALLOC(MOS3BspPtr, MOS3bNode, MOS3sNodePrime) - TSTALLOC(MOS3DPspPtr, MOS3dNodePrime, MOS3sNodePrime) - TSTALLOC(MOS3DPdPtr, MOS3dNodePrime, MOS3dNode) - TSTALLOC(MOS3BgPtr, MOS3bNode, MOS3gNode) - TSTALLOC(MOS3DPgPtr, MOS3dNodePrime, MOS3gNode) - TSTALLOC(MOS3SPgPtr, MOS3sNodePrime, MOS3gNode) - TSTALLOC(MOS3SPsPtr, MOS3sNodePrime, MOS3sNode) - TSTALLOC(MOS3DPbPtr, MOS3dNodePrime, MOS3bNode) - TSTALLOC(MOS3SPbPtr, MOS3sNodePrime, MOS3bNode) - TSTALLOC(MOS3SPdpPtr, MOS3sNodePrime, MOS3dNodePrime) + TSTALLOC(MOS3DdPtr, MOS3dNode, MOS3dNode); + TSTALLOC(MOS3GgPtr, MOS3gNode, MOS3gNode); + TSTALLOC(MOS3SsPtr, MOS3sNode, MOS3sNode); + TSTALLOC(MOS3BbPtr, MOS3bNode, MOS3bNode); + TSTALLOC(MOS3DPdpPtr, MOS3dNodePrime, MOS3dNodePrime); + TSTALLOC(MOS3SPspPtr, MOS3sNodePrime, MOS3sNodePrime); + TSTALLOC(MOS3DdpPtr, MOS3dNode, MOS3dNodePrime); + TSTALLOC(MOS3GbPtr, MOS3gNode, MOS3bNode); + TSTALLOC(MOS3GdpPtr, MOS3gNode, MOS3dNodePrime); + TSTALLOC(MOS3GspPtr, MOS3gNode, MOS3sNodePrime); + TSTALLOC(MOS3SspPtr, MOS3sNode, MOS3sNodePrime); + TSTALLOC(MOS3BdpPtr, MOS3bNode, MOS3dNodePrime); + TSTALLOC(MOS3BspPtr, MOS3bNode, MOS3sNodePrime); + TSTALLOC(MOS3DPspPtr, MOS3dNodePrime, MOS3sNodePrime); + TSTALLOC(MOS3DPdPtr, MOS3dNodePrime, MOS3dNode); + TSTALLOC(MOS3BgPtr, MOS3bNode, MOS3gNode); + TSTALLOC(MOS3DPgPtr, MOS3dNodePrime, MOS3gNode); + TSTALLOC(MOS3SPgPtr, MOS3sNodePrime, MOS3gNode); + TSTALLOC(MOS3SPsPtr, MOS3sNodePrime, MOS3sNode); + TSTALLOC(MOS3DPbPtr, MOS3dNodePrime, MOS3bNode); + TSTALLOC(MOS3SPbPtr, MOS3sNodePrime, MOS3bNode); + TSTALLOC(MOS3SPdpPtr, MOS3sNodePrime, MOS3dNodePrime); } } diff --git a/src/spicelib/devices/mos3/mos3temp.c b/src/spicelib/devices/mos3/mos3temp.c index 7357b47ae..e91523431 100644 --- a/src/spicelib/devices/mos3/mos3temp.c +++ b/src/spicelib/devices/mos3/mos3temp.c @@ -53,6 +53,11 @@ MOS3temp(GENmodel *inModel, CKTcircuit *ckt) CONSTKoverQ); ni_temp=1.45e16*nifact; + if (model->MOS3phi <= 0.0) { + SPfrontEnd->IFerror (ERR_FATAL, + "%s: Phi is not positive.",&model->MOS3modName); + return(E_BADPARM); + } model->MOS3oxideCapFactor = 3.9 * 8.854214871e-12/ model->MOS3oxideThickness; if(!model->MOS3surfaceMobilityGiven) model->MOS3surfaceMobility=600; diff --git a/src/spicelib/devices/mos6/Makefile.am b/src/spicelib/devices/mos6/Makefile.am index bfef9b3df..09b7dd9a6 100644 --- a/src/spicelib/devices/mos6/Makefile.am +++ b/src/spicelib/devices/mos6/Makefile.am @@ -34,6 +34,10 @@ if UMFPACK_WANTED libmos6_la_SOURCES += mos6bindCSC.c endif +if KIRCHHOFF_WANTED +libmos6_la_SOURCES += mos6node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mos6/mos6ext.h b/src/spicelib/devices/mos6/mos6ext.h index 35e11d77e..a6393189d 100644 --- a/src/spicelib/devices/mos6/mos6ext.h +++ b/src/spicelib/devices/mos6/mos6ext.h @@ -25,3 +25,7 @@ extern int MOS6bindCSC (GENmodel*, CKTcircuit*) ; extern int MOS6bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MOS6bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MOS6nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mos6/mos6init.c b/src/spicelib/devices/mos6/mos6init.c index 997915874..dfceb7b3c 100644 --- a/src/spicelib/devices/mos6/mos6init.c +++ b/src/spicelib/devices/mos6/mos6init.c @@ -73,12 +73,17 @@ SPICEdev MOS6info = { #endif /* DEVinstSize */ &MOS6iSize, /* DEVmodSize */ &MOS6mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MOS6bindCSC, /* DEVbindCSCComplex */ MOS6bindCSCComplex, /* DEVbindCSCComplexToReal */ MOS6bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MOS6nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mos6/mos6load.c b/src/spicelib/devices/mos6/mos6load.c index 0f1eea531..d07e6c56e 100644 --- a/src/spicelib/devices/mos6/mos6load.c +++ b/src/spicelib/devices/mos6/mos6load.c @@ -33,13 +33,13 @@ MOS6load(GENmodel *inModel, CKTcircuit *ckt) double cbhat; double cdhat; double cdrain; - double cdreq; + double cdreq, cdreq_fvk ; double ceq; - double ceqbd; - double ceqbs; - double ceqgb; - double ceqgd; - double ceqgs; + double ceqbd, ceqbd_fvk ; + double ceqbs, ceqbs_fvk ; + double ceqgb, ceqgb_fvk ; + double ceqgd, ceqgd_fvk ; + double ceqgs, ceqgs_fvk ; double delvbd; double delvbs; double delvds; @@ -860,10 +860,13 @@ bypass: */ gcgs=0; ceqgs=0; + ceqgs_fvk = 0 ; gcgd=0; ceqgd=0; + ceqgd_fvk = 0 ; gcgb=0; ceqgb=0; + ceqgb_fvk = 0 ; } else { if(capgs == 0) *(ckt->CKTstate0 + here->MOS6cqgs) =0; if(capgd == 0) *(ckt->CKTstate0 + here->MOS6cqgd) =0; @@ -880,10 +883,13 @@ bypass: if(error) return(error); ceqgs=ceqgs-gcgs*vgs+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS6qgs); + ceqgs_fvk = *(ckt->CKTstate0 + here->MOS6cqgs) ; ceqgd=ceqgd-gcgd*vgd+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS6qgd); + ceqgd_fvk = *(ckt->CKTstate0 + here->MOS6cqgd) ; ceqgb=ceqgb-gcgb*vgb+ckt->CKTag[0]* *(ckt->CKTstate0 + here->MOS6qgb); + ceqgb_fvk = *(ckt->CKTstate0 + here->MOS6cqgb) ; } /* * store charge storage info for meyer's cap in lx table @@ -897,18 +903,22 @@ bypass: ceqbs = model->MOS6type * (here->MOS6cbs-(here->MOS6gbs)*vbs); + ceqbs_fvk = model->MOS6type * here->MOS6cbs ; ceqbd = model->MOS6type * (here->MOS6cbd-(here->MOS6gbd)*vbd); + ceqbd_fvk = model->MOS6type * here->MOS6cbd ; if (here->MOS6mode >= 0) { xnrm=1; xrev=0; cdreq=model->MOS6type*(cdrain-here->MOS6gds*vds- here->MOS6gm*vgs-here->MOS6gmbs*vbs); + cdreq_fvk = model->MOS6type * cdrain ; } else { xnrm=0; xrev=1; cdreq = -(model->MOS6type)*(cdrain-here->MOS6gds*(-vds)- here->MOS6gm*vgd-here->MOS6gmbs*vbd); + cdreq_fvk = - (model->MOS6type * cdrain) ; } *(ckt->CKTrhs + here->MOS6gNode) -= m * (model->MOS6type * (ceqgs + ceqgb + ceqgd)); @@ -950,6 +960,26 @@ bypass: *(here->MOS6SPbPtr) += m * (-here->MOS6gbs-(xnrm-xrev)*here->MOS6gmbs); *(here->MOS6SPdpPtr) += m * (-here->MOS6gds-xrev* (here->MOS6gm+here->MOS6gmbs)); + +#ifdef KIRCHHOFF + /* KCL verification - Dynamic Part */ + *(ckt->CKTfvk+here->MOS6gNode) += model->MOS6type * (ceqgs_fvk + ceqgb_fvk + ceqgd_fvk) ; + *(ckt->CKTfvk+here->MOS6bNode) += ceqbs_fvk + ceqbd_fvk - model->MOS6type * ceqgb_fvk ; + *(ckt->CKTfvk+here->MOS6dNodePrime) -= (ceqbd_fvk - cdreq_fvk + model->MOS6type * ceqgd_fvk) ; + *(ckt->CKTfvk+here->MOS6sNodePrime) -= (cdreq_fvk + ceqbs_fvk + model->MOS6type * ceqgs_fvk) ; + + + /* KCL verification - Linear and Static Part */ + *(ckt->CKTfvk+here->MOS6dNode) += here->MOS6drainConductance * *(ckt->CKTrhsOld+here->MOS6dNode) ; + *(ckt->CKTfvk+here->MOS6sNode) += here->MOS6sourceConductance * *(ckt->CKTrhsOld+here->MOS6sNode) ; + *(ckt->CKTfvk+here->MOS6dNodePrime) += here->MOS6drainConductance * *(ckt->CKTrhsOld+here->MOS6dNodePrime) ; + *(ckt->CKTfvk+here->MOS6sNodePrime) += here->MOS6sourceConductance * *(ckt->CKTrhsOld+here->MOS6sNodePrime) ; + *(ckt->CKTfvk+here->MOS6dNode) -= here->MOS6drainConductance * *(ckt->CKTrhsOld+here->MOS6dNodePrime) ; + *(ckt->CKTfvk+here->MOS6sNode) -= here->MOS6sourceConductance * *(ckt->CKTrhsOld+here->MOS6sNodePrime) ; + *(ckt->CKTfvk+here->MOS6dNodePrime) -= here->MOS6drainConductance * *(ckt->CKTrhsOld+here->MOS6dNode) ; + *(ckt->CKTfvk+here->MOS6sNodePrime) -= here->MOS6sourceConductance * *(ckt->CKTrhsOld+here->MOS6sNode) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/mos6/mos6node.c b/src/spicelib/devices/mos6/mos6node.c new file mode 100644 index 000000000..a9bc47f09 --- /dev/null +++ b/src/spicelib/devices/mos6/mos6node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mos6defs.h" +#include "ngspice/sperror.h" + +int +MOS6nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MOS6model *model = (MOS6model *)inModel ; + MOS6instance *here ; + + /* loop through all the MOS6 models */ + for ( ; model != NULL ; model = model->MOS6nextModel) + { + /* loop through all the instances of the model */ + for (here = model->MOS6instances ; here != NULL ; here = here->MOS6nextInstance) + { + ckt->CKTnodeIsLinear [here->MOS6dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS6sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS6gNode] = 0 ; + ckt->CKTnodeIsLinear [here->MOS6bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mos6/mos6set.c b/src/spicelib/devices/mos6/mos6set.c index 28554c50f..8a1cd3d80 100644 --- a/src/spicelib/devices/mos6/mos6set.c +++ b/src/spicelib/devices/mos6/mos6set.c @@ -189,32 +189,32 @@ MOS6setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, } /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MOS6DdPtr,MOS6dNode,MOS6dNode) - TSTALLOC(MOS6GgPtr,MOS6gNode,MOS6gNode) - TSTALLOC(MOS6SsPtr,MOS6sNode,MOS6sNode) - TSTALLOC(MOS6BbPtr,MOS6bNode,MOS6bNode) - TSTALLOC(MOS6DPdpPtr,MOS6dNodePrime,MOS6dNodePrime) - TSTALLOC(MOS6SPspPtr,MOS6sNodePrime,MOS6sNodePrime) - TSTALLOC(MOS6DdpPtr,MOS6dNode,MOS6dNodePrime) - TSTALLOC(MOS6GbPtr,MOS6gNode,MOS6bNode) - TSTALLOC(MOS6GdpPtr,MOS6gNode,MOS6dNodePrime) - TSTALLOC(MOS6GspPtr,MOS6gNode,MOS6sNodePrime) - TSTALLOC(MOS6SspPtr,MOS6sNode,MOS6sNodePrime) - TSTALLOC(MOS6BdpPtr,MOS6bNode,MOS6dNodePrime) - TSTALLOC(MOS6BspPtr,MOS6bNode,MOS6sNodePrime) - TSTALLOC(MOS6DPspPtr,MOS6dNodePrime,MOS6sNodePrime) - TSTALLOC(MOS6DPdPtr,MOS6dNodePrime,MOS6dNode) - TSTALLOC(MOS6BgPtr,MOS6bNode,MOS6gNode) - TSTALLOC(MOS6DPgPtr,MOS6dNodePrime,MOS6gNode) - TSTALLOC(MOS6SPgPtr,MOS6sNodePrime,MOS6gNode) - TSTALLOC(MOS6SPsPtr,MOS6sNodePrime,MOS6sNode) - TSTALLOC(MOS6DPbPtr,MOS6dNodePrime,MOS6bNode) - TSTALLOC(MOS6SPbPtr,MOS6sNodePrime,MOS6bNode) - TSTALLOC(MOS6SPdpPtr,MOS6sNodePrime,MOS6dNodePrime) + TSTALLOC(MOS6DdPtr,MOS6dNode,MOS6dNode); + TSTALLOC(MOS6GgPtr,MOS6gNode,MOS6gNode); + TSTALLOC(MOS6SsPtr,MOS6sNode,MOS6sNode); + TSTALLOC(MOS6BbPtr,MOS6bNode,MOS6bNode); + TSTALLOC(MOS6DPdpPtr,MOS6dNodePrime,MOS6dNodePrime); + TSTALLOC(MOS6SPspPtr,MOS6sNodePrime,MOS6sNodePrime); + TSTALLOC(MOS6DdpPtr,MOS6dNode,MOS6dNodePrime); + TSTALLOC(MOS6GbPtr,MOS6gNode,MOS6bNode); + TSTALLOC(MOS6GdpPtr,MOS6gNode,MOS6dNodePrime); + TSTALLOC(MOS6GspPtr,MOS6gNode,MOS6sNodePrime); + TSTALLOC(MOS6SspPtr,MOS6sNode,MOS6sNodePrime); + TSTALLOC(MOS6BdpPtr,MOS6bNode,MOS6dNodePrime); + TSTALLOC(MOS6BspPtr,MOS6bNode,MOS6sNodePrime); + TSTALLOC(MOS6DPspPtr,MOS6dNodePrime,MOS6sNodePrime); + TSTALLOC(MOS6DPdPtr,MOS6dNodePrime,MOS6dNode); + TSTALLOC(MOS6BgPtr,MOS6bNode,MOS6gNode); + TSTALLOC(MOS6DPgPtr,MOS6dNodePrime,MOS6gNode); + TSTALLOC(MOS6SPgPtr,MOS6sNodePrime,MOS6gNode); + TSTALLOC(MOS6SPsPtr,MOS6sNodePrime,MOS6sNode); + TSTALLOC(MOS6DPbPtr,MOS6dNodePrime,MOS6bNode); + TSTALLOC(MOS6SPbPtr,MOS6sNodePrime,MOS6bNode); + TSTALLOC(MOS6SPdpPtr,MOS6sNodePrime,MOS6dNodePrime); } } diff --git a/src/spicelib/devices/mos6/mos6temp.c b/src/spicelib/devices/mos6/mos6temp.c index 046f62c79..a896700e1 100644 --- a/src/spicelib/devices/mos6/mos6temp.c +++ b/src/spicelib/devices/mos6/mos6temp.c @@ -50,7 +50,11 @@ MOS6temp(GENmodel *inModel, CKTcircuit *ckt) pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); /* now model parameter preprocessing */ - + if (model->MOS6phi <= 0.0) { + SPfrontEnd->IFerror (ERR_FATAL, + "%s: Phi is not positive.",&model->MOS6modName); + return(E_BADPARM); + } if(!model->MOS6oxideThicknessGiven || model->MOS6oxideThickness == 0) { model->MOS6oxideCapFactor = 0; } else { diff --git a/src/spicelib/devices/mos9/Makefile.am b/src/spicelib/devices/mos9/Makefile.am index 561720493..54578d652 100644 --- a/src/spicelib/devices/mos9/Makefile.am +++ b/src/spicelib/devices/mos9/Makefile.am @@ -46,6 +46,10 @@ if UMFPACK_WANTED libmos9_la_SOURCES += mos9bindCSC.c endif +if KIRCHHOFF_WANTED +libmos9_la_SOURCES += mos9node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/mos9/mos9ext.h b/src/spicelib/devices/mos9/mos9ext.h index d94b8c7e0..679c0fa9b 100644 --- a/src/spicelib/devices/mos9/mos9ext.h +++ b/src/spicelib/devices/mos9/mos9ext.h @@ -34,3 +34,7 @@ extern int MOS9bindCSC (GENmodel*, CKTcircuit*) ; extern int MOS9bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MOS9bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int MOS9nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/mos9/mos9init.c b/src/spicelib/devices/mos9/mos9init.c index 0aca14499..3e3084efd 100644 --- a/src/spicelib/devices/mos9/mos9init.c +++ b/src/spicelib/devices/mos9/mos9init.c @@ -73,12 +73,17 @@ SPICEdev MOS9info = { #endif /* DEVinstSize */ &MOS9iSize, /* DEVmodSize */ &MOS9mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ MOS9bindCSC, /* DEVbindCSCComplex */ MOS9bindCSCComplex, /* DEVbindCSCComplexToReal */ MOS9bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ MOS9nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/mos9/mos9node.c b/src/spicelib/devices/mos9/mos9node.c new file mode 100644 index 000000000..b03096a70 --- /dev/null +++ b/src/spicelib/devices/mos9/mos9node.c @@ -0,0 +1,30 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "mos9defs.h" +#include "ngspice/sperror.h" + +int +MOS9nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + MOS9model *model = (MOS9model *)inModel ; + MOS9instance *here ; + + /* loop through all the MOS9 models */ + for ( ; model != NULL ; model = model->MOS9nextModel) + { + /* loop through all the instances of the model */ + for (here = model->MOS9instances ; here != NULL ; here = here->MOS9nextInstance) + { + ckt->CKTnodeIsLinear [here->MOS9dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS9sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->MOS9gNode] = 0 ; + ckt->CKTnodeIsLinear [here->MOS9bNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/mos9/mos9set.c b/src/spicelib/devices/mos9/mos9set.c index 129ebccfe..b32c91b2a 100644 --- a/src/spicelib/devices/mos9/mos9set.c +++ b/src/spicelib/devices/mos9/mos9set.c @@ -227,32 +227,32 @@ MOS9setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(MOS9DdPtr, MOS9dNode, MOS9dNode) - TSTALLOC(MOS9GgPtr, MOS9gNode, MOS9gNode) - TSTALLOC(MOS9SsPtr, MOS9sNode, MOS9sNode) - TSTALLOC(MOS9BbPtr, MOS9bNode, MOS9bNode) - TSTALLOC(MOS9DPdpPtr, MOS9dNodePrime, MOS9dNodePrime) - TSTALLOC(MOS9SPspPtr, MOS9sNodePrime, MOS9sNodePrime) - TSTALLOC(MOS9DdpPtr, MOS9dNode, MOS9dNodePrime) - TSTALLOC(MOS9GbPtr, MOS9gNode, MOS9bNode) - TSTALLOC(MOS9GdpPtr, MOS9gNode, MOS9dNodePrime) - TSTALLOC(MOS9GspPtr, MOS9gNode, MOS9sNodePrime) - TSTALLOC(MOS9SspPtr, MOS9sNode, MOS9sNodePrime) - TSTALLOC(MOS9BdpPtr, MOS9bNode, MOS9dNodePrime) - TSTALLOC(MOS9BspPtr, MOS9bNode, MOS9sNodePrime) - TSTALLOC(MOS9DPspPtr, MOS9dNodePrime, MOS9sNodePrime) - TSTALLOC(MOS9DPdPtr, MOS9dNodePrime, MOS9dNode) - TSTALLOC(MOS9BgPtr, MOS9bNode, MOS9gNode) - TSTALLOC(MOS9DPgPtr, MOS9dNodePrime, MOS9gNode) - TSTALLOC(MOS9SPgPtr, MOS9sNodePrime, MOS9gNode) - TSTALLOC(MOS9SPsPtr, MOS9sNodePrime, MOS9sNode) - TSTALLOC(MOS9DPbPtr, MOS9dNodePrime, MOS9bNode) - TSTALLOC(MOS9SPbPtr, MOS9sNodePrime, MOS9bNode) - TSTALLOC(MOS9SPdpPtr, MOS9sNodePrime, MOS9dNodePrime) + TSTALLOC(MOS9DdPtr, MOS9dNode, MOS9dNode); + TSTALLOC(MOS9GgPtr, MOS9gNode, MOS9gNode); + TSTALLOC(MOS9SsPtr, MOS9sNode, MOS9sNode); + TSTALLOC(MOS9BbPtr, MOS9bNode, MOS9bNode); + TSTALLOC(MOS9DPdpPtr, MOS9dNodePrime, MOS9dNodePrime); + TSTALLOC(MOS9SPspPtr, MOS9sNodePrime, MOS9sNodePrime); + TSTALLOC(MOS9DdpPtr, MOS9dNode, MOS9dNodePrime); + TSTALLOC(MOS9GbPtr, MOS9gNode, MOS9bNode); + TSTALLOC(MOS9GdpPtr, MOS9gNode, MOS9dNodePrime); + TSTALLOC(MOS9GspPtr, MOS9gNode, MOS9sNodePrime); + TSTALLOC(MOS9SspPtr, MOS9sNode, MOS9sNodePrime); + TSTALLOC(MOS9BdpPtr, MOS9bNode, MOS9dNodePrime); + TSTALLOC(MOS9BspPtr, MOS9bNode, MOS9sNodePrime); + TSTALLOC(MOS9DPspPtr, MOS9dNodePrime, MOS9sNodePrime); + TSTALLOC(MOS9DPdPtr, MOS9dNodePrime, MOS9dNode); + TSTALLOC(MOS9BgPtr, MOS9bNode, MOS9gNode); + TSTALLOC(MOS9DPgPtr, MOS9dNodePrime, MOS9gNode); + TSTALLOC(MOS9SPgPtr, MOS9sNodePrime, MOS9gNode); + TSTALLOC(MOS9SPsPtr, MOS9sNodePrime, MOS9sNode); + TSTALLOC(MOS9DPbPtr, MOS9dNodePrime, MOS9bNode); + TSTALLOC(MOS9SPbPtr, MOS9sNodePrime, MOS9bNode); + TSTALLOC(MOS9SPdpPtr, MOS9sNodePrime, MOS9dNodePrime); } } diff --git a/src/spicelib/devices/mos9/mos9temp.c b/src/spicelib/devices/mos9/mos9temp.c index 0ffcd11df..f71aa6648 100644 --- a/src/spicelib/devices/mos9/mos9temp.c +++ b/src/spicelib/devices/mos9/mos9temp.c @@ -54,7 +54,11 @@ MOS9temp(GENmodel *inModel, CKTcircuit *ckt) CONSTKoverQ); ni_temp=1.45e16*nifact; - + if (model->MOS9phi <= 0.0) { + SPfrontEnd->IFerror (ERR_FATAL, + "%s: Phi is not positive.",&model->MOS9modName); + return(E_BADPARM); + } model->MOS9oxideCapFactor = 3.9 * 8.854214871e-12/ model->MOS9oxideThickness; if(!model->MOS9surfaceMobilityGiven) model->MOS9surfaceMobility=600; diff --git a/src/spicelib/devices/nbjt/nbjtset.c b/src/spicelib/devices/nbjt/nbjtset.c index b9da8fb7a..110a57a09 100644 --- a/src/spicelib/devices/nbjt/nbjtset.c +++ b/src/spicelib/devices/nbjt/nbjtset.c @@ -228,19 +228,19 @@ NBJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ +do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode) - TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode) - TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode) - TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode) - TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode) - TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode) - TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode) - TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode) - TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode) + TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode); + TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode); + TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode); + TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode); + TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode); + TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode); + TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode); + TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode); + TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode); } /* Clean up lists */ killCoordInfo(xCoordList); diff --git a/src/spicelib/devices/nbjt2/nbt2set.c b/src/spicelib/devices/nbjt2/nbt2set.c index 385fcc5b6..231ee561d 100644 --- a/src/spicelib/devices/nbjt2/nbt2set.c +++ b/src/spicelib/devices/nbjt2/nbt2set.c @@ -244,19 +244,19 @@ NBJT2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ +do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(NBJT2colColPtr, NBJT2colNode, NBJT2colNode) - TSTALLOC(NBJT2colBasePtr, NBJT2colNode, NBJT2baseNode) - TSTALLOC(NBJT2colEmitPtr, NBJT2colNode, NBJT2emitNode) - TSTALLOC(NBJT2baseColPtr, NBJT2baseNode, NBJT2colNode) - TSTALLOC(NBJT2baseBasePtr, NBJT2baseNode, NBJT2baseNode) - TSTALLOC(NBJT2baseEmitPtr, NBJT2baseNode, NBJT2emitNode) - TSTALLOC(NBJT2emitColPtr, NBJT2emitNode, NBJT2colNode) - TSTALLOC(NBJT2emitBasePtr, NBJT2emitNode, NBJT2baseNode) - TSTALLOC(NBJT2emitEmitPtr, NBJT2emitNode, NBJT2emitNode) + TSTALLOC(NBJT2colColPtr, NBJT2colNode, NBJT2colNode); + TSTALLOC(NBJT2colBasePtr, NBJT2colNode, NBJT2baseNode); + TSTALLOC(NBJT2colEmitPtr, NBJT2colNode, NBJT2emitNode); + TSTALLOC(NBJT2baseColPtr, NBJT2baseNode, NBJT2colNode); + TSTALLOC(NBJT2baseBasePtr, NBJT2baseNode, NBJT2baseNode); + TSTALLOC(NBJT2baseEmitPtr, NBJT2baseNode, NBJT2emitNode); + TSTALLOC(NBJT2emitColPtr, NBJT2emitNode, NBJT2colNode); + TSTALLOC(NBJT2emitBasePtr, NBJT2emitNode, NBJT2baseNode); + TSTALLOC(NBJT2emitEmitPtr, NBJT2emitNode, NBJT2emitNode); } /* Clean up lists */ killCoordInfo(xCoordList); diff --git a/src/spicelib/devices/ndev/ndevset.c b/src/spicelib/devices/ndev/ndevset.c index 9f7e0ecd4..b6fe6b484 100644 --- a/src/spicelib/devices/ndev/ndevset.c +++ b/src/spicelib/devices/ndev/ndevset.c @@ -51,9 +51,9 @@ int NDEVsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states send(model->sock,&(here->Ndevinfo),sizeof(here->Ndevinfo),0); /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) for(i=0;iterm;i++) for(j=0;jterm;j++) diff --git a/src/spicelib/devices/numd/numdset.c b/src/spicelib/devices/numd/numdset.c index 5e4108e91..027a68db7 100644 --- a/src/spicelib/devices/numd/numdset.c +++ b/src/spicelib/devices/numd/numdset.c @@ -217,14 +217,14 @@ NUMDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ +do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(NUMDposPosPtr, NUMDposNode, NUMDposNode) - TSTALLOC(NUMDnegNegPtr, NUMDnegNode, NUMDnegNode) - TSTALLOC(NUMDnegPosPtr, NUMDnegNode, NUMDposNode) - TSTALLOC(NUMDposNegPtr, NUMDposNode, NUMDnegNode) + TSTALLOC(NUMDposPosPtr, NUMDposNode, NUMDposNode); + TSTALLOC(NUMDnegNegPtr, NUMDnegNode, NUMDnegNode); + TSTALLOC(NUMDnegPosPtr, NUMDnegNode, NUMDposNode); + TSTALLOC(NUMDposNegPtr, NUMDposNode, NUMDnegNode); } /* Clean up lists */ killCoordInfo(xCoordList); diff --git a/src/spicelib/devices/numd2/nud2set.c b/src/spicelib/devices/numd2/nud2set.c index 521fec661..fde80d7ad 100644 --- a/src/spicelib/devices/numd2/nud2set.c +++ b/src/spicelib/devices/numd2/nud2set.c @@ -242,14 +242,14 @@ NUMD2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ +do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(NUMD2posPosPtr, NUMD2posNode, NUMD2posNode) - TSTALLOC(NUMD2negNegPtr, NUMD2negNode, NUMD2negNode) - TSTALLOC(NUMD2negPosPtr, NUMD2negNode, NUMD2posNode) - TSTALLOC(NUMD2posNegPtr, NUMD2posNode, NUMD2negNode) + TSTALLOC(NUMD2posPosPtr, NUMD2posNode, NUMD2posNode); + TSTALLOC(NUMD2negNegPtr, NUMD2negNode, NUMD2negNode); + TSTALLOC(NUMD2negPosPtr, NUMD2negNode, NUMD2posNode); + TSTALLOC(NUMD2posNegPtr, NUMD2posNode, NUMD2negNode); } /* Clean up lists */ killCoordInfo(xCoordList); diff --git a/src/spicelib/devices/numos/nummset.c b/src/spicelib/devices/numos/nummset.c index 895901ba8..4d1af7282 100644 --- a/src/spicelib/devices/numos/nummset.c +++ b/src/spicelib/devices/numos/nummset.c @@ -241,26 +241,26 @@ NUMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ +do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(NUMOSdrainDrainPtr, NUMOSdrainNode, NUMOSdrainNode) - TSTALLOC(NUMOSdrainSourcePtr, NUMOSdrainNode, NUMOSsourceNode) - TSTALLOC(NUMOSdrainGatePtr, NUMOSdrainNode, NUMOSgateNode) - TSTALLOC(NUMOSdrainBulkPtr, NUMOSdrainNode, NUMOSbulkNode) - TSTALLOC(NUMOSsourceDrainPtr, NUMOSsourceNode, NUMOSdrainNode) - TSTALLOC(NUMOSsourceSourcePtr, NUMOSsourceNode, NUMOSsourceNode) - TSTALLOC(NUMOSsourceGatePtr, NUMOSsourceNode, NUMOSgateNode) - TSTALLOC(NUMOSsourceBulkPtr, NUMOSsourceNode, NUMOSbulkNode) - TSTALLOC(NUMOSgateDrainPtr, NUMOSgateNode, NUMOSdrainNode) - TSTALLOC(NUMOSgateSourcePtr, NUMOSgateNode, NUMOSsourceNode) - TSTALLOC(NUMOSgateGatePtr, NUMOSgateNode, NUMOSgateNode) - TSTALLOC(NUMOSgateBulkPtr, NUMOSgateNode, NUMOSbulkNode) - TSTALLOC(NUMOSbulkDrainPtr, NUMOSbulkNode, NUMOSdrainNode) - TSTALLOC(NUMOSbulkSourcePtr, NUMOSbulkNode, NUMOSsourceNode) - TSTALLOC(NUMOSbulkGatePtr, NUMOSbulkNode, NUMOSgateNode) - TSTALLOC(NUMOSbulkBulkPtr, NUMOSbulkNode, NUMOSbulkNode) + TSTALLOC(NUMOSdrainDrainPtr, NUMOSdrainNode, NUMOSdrainNode); + TSTALLOC(NUMOSdrainSourcePtr, NUMOSdrainNode, NUMOSsourceNode); + TSTALLOC(NUMOSdrainGatePtr, NUMOSdrainNode, NUMOSgateNode); + TSTALLOC(NUMOSdrainBulkPtr, NUMOSdrainNode, NUMOSbulkNode); + TSTALLOC(NUMOSsourceDrainPtr, NUMOSsourceNode, NUMOSdrainNode); + TSTALLOC(NUMOSsourceSourcePtr, NUMOSsourceNode, NUMOSsourceNode); + TSTALLOC(NUMOSsourceGatePtr, NUMOSsourceNode, NUMOSgateNode); + TSTALLOC(NUMOSsourceBulkPtr, NUMOSsourceNode, NUMOSbulkNode); + TSTALLOC(NUMOSgateDrainPtr, NUMOSgateNode, NUMOSdrainNode); + TSTALLOC(NUMOSgateSourcePtr, NUMOSgateNode, NUMOSsourceNode); + TSTALLOC(NUMOSgateGatePtr, NUMOSgateNode, NUMOSgateNode); + TSTALLOC(NUMOSgateBulkPtr, NUMOSgateNode, NUMOSbulkNode); + TSTALLOC(NUMOSbulkDrainPtr, NUMOSbulkNode, NUMOSdrainNode); + TSTALLOC(NUMOSbulkSourcePtr, NUMOSbulkNode, NUMOSsourceNode); + TSTALLOC(NUMOSbulkGatePtr, NUMOSbulkNode, NUMOSgateNode); + TSTALLOC(NUMOSbulkBulkPtr, NUMOSbulkNode, NUMOSbulkNode); } /* Clean up lists */ killCoordInfo(xCoordList); diff --git a/src/spicelib/devices/res/Makefile.am b/src/spicelib/devices/res/Makefile.am index f5cc36087..a7acf5d85 100644 --- a/src/spicelib/devices/res/Makefile.am +++ b/src/spicelib/devices/res/Makefile.am @@ -39,6 +39,10 @@ if UMFPACK_WANTED libres_la_SOURCES += resbindCSC.c endif +if KIRCHHOFF_WANTED +libres_la_SOURCES += resnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/res/res.c b/src/spicelib/devices/res/res.c index 228c8b8f0..61449f300 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -10,48 +10,52 @@ Modified: 2000 AlansFixes #include "ngspice/devdefs.h" #include "ngspice/ifsim.h" -IFparm RESpTable[] = { /* parameters */ - IOPP( "resistance", RES_RESIST, IF_REAL, "Resistance"), - IOPAA( "ac", RES_ACRESIST, IF_REAL, "AC resistance value"), - IOPZU( "temp", RES_TEMP, IF_REAL, "Instance operating temperature"), - IOPZ( "dtemp", RES_DTEMP, IF_REAL, - "Instance temperature difference with the rest of the circuit"), - IOPQU( "l", RES_LENGTH, IF_REAL, "Length"), - IOPZU( "w", RES_WIDTH, IF_REAL, "Width"), - IOPU( "m", RES_M, IF_REAL, "Multiplication factor"), - IOPU( "tc", RES_TC1, IF_REAL, "First order temp. coefficient"), - IOPU( "tc1", RES_TC1, IF_REAL, "First order temp. coefficient"), - IOPU( "tc2", RES_TC2, IF_REAL, "Second order temp. coefficient"), - IOPU( "scale", RES_SCALE, IF_REAL, "Scale factor"), - IOP( "noisy", RES_NOISY, IF_INTEGER, "Resistor generate noise"), - IP( "sens_resist", RES_RESIST_SENS, IF_FLAG, - "flag to request sensitivity WRT resistance"), - OP( "i", RES_CURRENT, IF_REAL, "Current"), - OP( "p", RES_POWER, IF_REAL, "Power"), - OPU( "sens_dc", RES_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), - OPU( "sens_real", RES_QUEST_SENS_REAL, IF_REAL, - "dc sensitivity and real part of ac sensitivity"), - OPU( "sens_imag", RES_QUEST_SENS_IMAG, IF_REAL, - "dc sensitivity and imag part of ac sensitivity"), - OPU( "sens_mag", RES_QUEST_SENS_MAG, IF_REAL, "ac sensitivity of magnitude"), - OPU( "sens_ph", RES_QUEST_SENS_PH, IF_REAL, "ac sensitivity of phase"), - OPU( "sens_cplx", RES_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") +IFparm RESpTable[] = { /* parameters */ + IOPP( "resistance", RES_RESIST, IF_REAL, "Resistance"), + IOPAA( "ac", RES_ACRESIST, IF_REAL, "AC resistance value"), + IOPZU( "temp", RES_TEMP, IF_REAL, "Instance operating temperature"), + IOPZ( "dtemp", RES_DTEMP, IF_REAL, + "Instance temperature difference with the rest of the circuit"), + IOPQU( "l", RES_LENGTH, IF_REAL, "Length"), + IOPZU( "w", RES_WIDTH, IF_REAL, "Width"), + IOPU( "m", RES_M, IF_REAL, "Multiplication factor"), + IOPU( "tc", RES_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc1", RES_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc2", RES_TC2, IF_REAL, "Second order temp. coefficient"), + IOPU( "scale", RES_SCALE, IF_REAL, "Scale factor"), + IOP( "noisy", RES_NOISY, IF_INTEGER, "Resistor generate noise"), + IP( "sens_resist", RES_RESIST_SENS, IF_FLAG, + "flag to request sensitivity WRT resistance"), + OP( "i", RES_CURRENT, IF_REAL, "Current"), + OP( "p", RES_POWER, IF_REAL, "Power"), + OPU( "sens_dc", RES_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), + OPU( "sens_real", RES_QUEST_SENS_REAL, IF_REAL, + "dc sensitivity and real part of ac sensitivity"), + OPU( "sens_imag", RES_QUEST_SENS_IMAG, IF_REAL, + "dc sensitivity and imag part of ac sensitivity"), + OPU( "sens_mag", RES_QUEST_SENS_MAG, IF_REAL, "ac sensitivity of magnitude"), + OPU( "sens_ph", RES_QUEST_SENS_PH, IF_REAL, "ac sensitivity of phase"), + OPU( "sens_cplx", RES_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity") }; IFparm RESmPTable[] = { /* model parameters */ - IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"), - IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"), - IOPR( "dw", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"), - IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"), - IOPR( "dlr", 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"), - IOPR( "w", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), - IOPQ( "kf", RES_MOD_KF, IF_REAL,"Flicker noise coefficient"), - IOPQ( "af", RES_MOD_AF, IF_REAL,"Flicker noise exponent"), - IOPXU( "tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"), - IP( "r", RES_MOD_R, IF_FLAG,"Device is a resistor model") + IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"), + IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"), + IOPR( "dw", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"), + IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"), + IOPR( "dlr", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"), + IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"), + IOPR( "tc1r", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"), + IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"), + IOPR( "tc2r", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"), + IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), + IOPR( "w", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), + IOPX( "l", RES_MOD_DEFLENGTH,IF_REAL,"Default device length"), + IOPQ( "kf", RES_MOD_KF, IF_REAL,"Flicker noise coefficient"), + IOPQ( "af", RES_MOD_AF, IF_REAL,"Flicker noise exponent"), + IOPXU( "tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"), + IOP( "r", RES_MOD_R, IF_REAL,"Resistor model default value"), + IOPR( "res", RES_MOD_R, IF_REAL,"Resistor model default value") }; char *RESnames[] = { diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index 457acd1f7..cf007adc2 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -13,14 +13,14 @@ Modified: 2000 AlansFixes #include "ngspice/complex.h" #include "ngspice/noisedef.h" - /* definitions used to describe resistors */ +/* definitions used to describe resistors */ /* information used to describe a single instance */ typedef struct sRESinstance { struct sRESmodel *RESmodPtr; /* backpointer to model */ - struct sRESinstance *RESnextInstance; /* pointer to next instance of + struct sRESinstance *RESnextInstance; /* pointer to next instance of * current model*/ IFuid RESname; /* pointer to character string naming this instance */ @@ -33,7 +33,7 @@ typedef struct sRESinstance { double RESconduct; /* conductance at current analysis temperature */ double RESresist; /* resistance at temperature Tnom */ double REScurrent; /* The dc current in the resistor */ -/* serban */ + /* serban */ double RESacResist; /* AC resistance, useful for fancy .ac analyses */ double RESacConduct; /* AC conductance */ double RESwidth; /* width of the resistor */ @@ -43,13 +43,13 @@ typedef struct sRESinstance { double REStc1; /* first temperature coefficient of resistors */ double REStc2; /* second temperature coefficient of resistors */ int RESnoisy; /* Set if the resistor generates noise */ - double *RESposPosptr; /* pointer to sparse matrix diagonal at + double *RESposPosptr; /* pointer to sparse matrix diagonal at * (positive,positive) */ - double *RESnegNegptr; /* pointer to sparse matrix diagonal at + double *RESnegNegptr; /* pointer to sparse matrix diagonal at * (negative,negative) */ - double *RESposNegptr; /* pointer to sparse matrix offdiagonal at + double *RESposNegptr; /* pointer to sparse matrix offdiagonal at * (positive,negative) */ - double *RESnegPosptr; /* pointer to sparse matrix offdiagonal at + double *RESnegPosptr; /* pointer to sparse matrix offdiagonal at * (negative,positive) */ unsigned RESresGiven : 1; /* flag to indicate resistance was specified */ unsigned RESwidthGiven : 1; /* flag to indicate width given */ @@ -57,7 +57,7 @@ typedef struct sRESinstance { unsigned RESscaleGiven : 1; /* flag to indicate scale given */ unsigned REStempGiven : 1; /* indicates temperature specified */ unsigned RESdtempGiven : 1; /* indicates delta-temp specified */ -/* serban */ + /* serban */ unsigned RESacresGiven : 1; /* indicates AC value specified */ unsigned RESmGiven : 1; /* indicates M parameter specified */ unsigned REStc1Given : 1; /* indicates tc1 parameter specified */ @@ -66,7 +66,7 @@ typedef struct sRESinstance { int RESsenParmNo; /* parameter # for sensitivity use; * set equal to 0 if not a design parameter*/ -/* indices to array of RES noise sources */ + /* indices to array of RES noise sources */ #define RESTHNOIZ 0 /* Thermal noise source */ #define RESFLNOIZ 1 /* Flicker noise source */ @@ -88,6 +88,11 @@ typedef struct sRESinstance { BindElement *RESnegPosptrStructPtr ; #endif +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } RESinstance ; @@ -95,7 +100,7 @@ typedef struct sRESinstance { typedef struct sRESmodel { /* model structure for a resistor */ int RESmodType; /* type index of this device type */ - struct sRESmodel *RESnextModel; /* pointer to next possible model in + struct sRESmodel *RESnextModel; /* pointer to next possible model in * linked list */ RESinstance * RESinstances; /* pointer to list of instances that have this * model */ @@ -106,19 +111,23 @@ typedef struct sRESmodel { /* model structure for a resistor */ double REStempCoeff2; /* second temperature coefficient of resistors */ double RESsheetRes; /* sheet resistance of devices in ohms/square */ double RESdefWidth; /* default width of a resistor */ + double RESdefLength; /* default length of a resistor */ double RESnarrow; /* amount by which device is narrower than drawn */ double RESshort; /* amount by which device is shorter than drawn */ double RESfNcoef; /* Flicker noise coefficient */ double RESfNexp; /* Flicker noise exponent */ + double RESres; /* Default model resistance */ 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 RESdefLengthGiven :1; /* flag to indicate default length given */ unsigned RESnarrowGiven :1; /* flag to indicate narrow effect given */ unsigned RESshortGiven :1; /* flag to indicate short effect given */ unsigned RESfNcoefGiven :1; /* flag to indicate kf given */ unsigned RESfNexpGiven :1; /* flag to indicate af given */ + unsigned RESresGiven :1; /* flag to indicate model resistance given */ } RESmodel; /* device parameters */ @@ -146,12 +155,13 @@ typedef struct sRESmodel { /* model structure for a resistor */ #define RES_MOD_TC2 102 #define RES_MOD_RSH 103 #define RES_MOD_DEFWIDTH 104 -#define RES_MOD_NARROW 105 -#define RES_MOD_R 106 -#define RES_MOD_TNOM 107 -#define RES_MOD_SHORT 108 -#define RES_MOD_KF 109 -#define RES_MOD_AF 110 +#define RES_MOD_DEFLENGTH 105 +#define RES_MOD_NARROW 106 +#define RES_MOD_R 107 +#define RES_MOD_TNOM 108 +#define RES_MOD_SHORT 109 +#define RES_MOD_KF 110 +#define RES_MOD_AF 111 /* device questions */ #define RES_QUEST_SENS_REAL 201 diff --git a/src/spicelib/devices/res/resext.h b/src/spicelib/devices/res/resext.h index b96d7cd8e..352804002 100644 --- a/src/spicelib/devices/res/resext.h +++ b/src/spicelib/devices/res/resext.h @@ -26,3 +26,7 @@ extern int RESbindCSC (GENmodel*, CKTcircuit*) ; extern int RESbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int RESbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int RESnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/res/resinit.c b/src/spicelib/devices/res/resinit.c index 03524119a..08300145b 100644 --- a/src/spicelib/devices/res/resinit.c +++ b/src/spicelib/devices/res/resinit.c @@ -73,12 +73,17 @@ SPICEdev RESinfo = { #endif /* DEVinstSize */ &RESiSize, /* DEVmodSize */ &RESmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ RESbindCSC, /* DEVbindCSCComplex */ RESbindCSCComplex, /* DEVbindCSCComplexToReal */ RESbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ RESnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/res/resload.c b/src/spicelib/devices/res/resload.c index f9ee09a31..8356c4472 100644 --- a/src/spicelib/devices/res/resload.c +++ b/src/spicelib/devices/res/resload.c @@ -17,35 +17,32 @@ RESload(GENmodel *inModel, CKTcircuit *ckt) { RESmodel *model = (RESmodel *)inModel; double m; - double difference; - double factor; - /* loop through all the resistor models */ for( ; model != NULL; model = model->RESnextModel ) { - RESinstance *here; + RESinstance *here; /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; - here = here->RESnextInstance) { - - if(!here->REStc1Given) here->REStc1 = 0.0; - if(!here->REStc2Given) here->REStc2 = 0.0; - if(!here->RESmGiven) here->RESm = 1.0; + here = here->RESnextInstance) { - here->REScurrent = (*(ckt->CKTrhsOld+here->RESposNode) - - *(ckt->CKTrhsOld+here->RESnegNode)) * here->RESconduct; - - difference = (here->REStemp + here->RESdtemp) - 300.15; - factor = 1.0 + (here->REStc1)*difference + - (here->REStc2)*difference*difference; - - m = (here->RESm)/factor; + here->REScurrent = (*(ckt->CKTrhsOld+here->RESposNode) - + *(ckt->CKTrhsOld+here->RESnegNode)) * here->RESconduct; + m = (here->RESm); *(here->RESposPosptr) += m * here->RESconduct; *(here->RESnegNegptr) += m * here->RESconduct; *(here->RESposNegptr) -= m * here->RESconduct; *(here->RESnegPosptr) -= m * here->RESconduct; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->RESposNode) += here->REScurrent ; + *(ckt->CKTfvk+here->RESnegNode) -= here->REScurrent ; + + *(here->KCLcurrentPos) = here->REScurrent ; + *(here->KCLcurrentNeg) = -(here->REScurrent) ; +#endif + } } return(OK); @@ -59,29 +56,18 @@ RESacload(GENmodel *inModel, CKTcircuit *ckt) { RESmodel *model = (RESmodel *)inModel; double m; - double difference; - double factor; NG_IGNORE(ckt); /* loop through all the resistor models */ for( ; model != NULL; model = model->RESnextModel ) { - RESinstance *here; + RESinstance *here; /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; - here = here->RESnextInstance) { - - if(!here->REStc1Given) here->REStc1 = 0.0; - if(!here->REStc2Given) here->REStc2 = 0.0; - if(!here->RESmGiven) here->RESm = 1.0; + here = here->RESnextInstance) { - difference = (here->REStemp + here->RESdtemp) - 300.15; - factor = 1.0 + (here->REStc1)*difference + - (here->REStc2)*difference*difference; - - m = (here->RESm)/factor; - + m = (here->RESm); if(here->RESacresGiven) { *(here->RESposPosptr) += m * here->RESacConduct; *(here->RESnegNegptr) += m * here->RESacConduct; diff --git a/src/spicelib/devices/res/resmask.c b/src/spicelib/devices/res/resmask.c index 4b541f737..28af7fc82 100644 --- a/src/spicelib/devices/res/resmask.c +++ b/src/spicelib/devices/res/resmask.c @@ -39,24 +39,30 @@ RESmodAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case RES_MOD_DEFWIDTH: value->rValue = model->RESdefWidth; return(OK); + case RES_MOD_DEFLENGTH: + value->rValue = model->RESdefLength; + return(OK); case RES_MOD_NARROW: value->rValue = model->RESnarrow; return(OK); case RES_MOD_SHORT: value->rValue = model->RESshort; return(OK); - case RES_MOD_KF: - if (model->RESfNcoefGiven) - value->rValue = model->RESfNcoef; - else - value->rValue = 0.0; - return(OK); - case RES_MOD_AF: - if (model->RESfNexpGiven) - value->rValue = model->RESfNexp; - else - value->rValue = 0.0; - return(OK); + case RES_MOD_KF: + if (model->RESfNcoefGiven) + value->rValue = model->RESfNcoef; + else + value->rValue = 0.0; + return(OK); + case RES_MOD_AF: + if (model->RESfNexpGiven) + value->rValue = model->RESfNexp; + else + value->rValue = 0.0; + return(OK); + case RES_MOD_R: + value->rValue = model->RESres; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index a08efceeb..d47e36202 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -16,51 +16,56 @@ int RESmParam(int param, IFvalue *value, GENmodel *inModel) { RESmodel *model = (RESmodel *)inModel; - + switch(param) { - case RES_MOD_TNOM: - model->REStnom = value->rValue+CONSTCtoK; - model->REStnomGiven = TRUE; - break; - case RES_MOD_TC1: - model->REStempCoeff1 = value->rValue; - model->REStc1Given = TRUE; - break; - case RES_MOD_TC2: - model->REStempCoeff2 = value->rValue; - model->REStc2Given = TRUE; - break; - case RES_MOD_RSH: - model->RESsheetRes = value->rValue; - model->RESsheetResGiven = TRUE; - break; - case RES_MOD_DEFWIDTH: - model->RESdefWidth = value->rValue; - model->RESdefWidthGiven = TRUE; - break; - case RES_MOD_NARROW: - model->RESnarrow = value->rValue; - model->RESnarrowGiven = TRUE; - break; - case RES_MOD_SHORT: - model->RESshort = value->rValue; - model->RESshortGiven = TRUE; - break; - case RES_MOD_KF: - model->RESfNcoef = value->rValue; - model->RESfNcoefGiven = TRUE; - break; - case RES_MOD_AF: - model->RESfNexp = value->rValue; - model->RESfNexpGiven = TRUE; - break; - - case RES_MOD_R: - /* just being reassured by user that this is a resistor model */ - /* no-op */ - break; - default: - return(E_BADPARM); + case RES_MOD_TNOM: + model->REStnom = value->rValue+CONSTCtoK; + model->REStnomGiven = TRUE; + break; + case RES_MOD_TC1: + model->REStempCoeff1 = value->rValue; + model->REStc1Given = TRUE; + break; + case RES_MOD_TC2: + model->REStempCoeff2 = value->rValue; + model->REStc2Given = TRUE; + break; + case RES_MOD_RSH: + model->RESsheetRes = value->rValue; + model->RESsheetResGiven = TRUE; + break; + case RES_MOD_DEFWIDTH: + model->RESdefWidth = value->rValue; + model->RESdefWidthGiven = TRUE; + break; + case RES_MOD_DEFLENGTH: + model->RESdefLength = value->rValue; + model->RESdefLengthGiven = TRUE; + break; + case RES_MOD_NARROW: + model->RESnarrow = value->rValue; + model->RESnarrowGiven = TRUE; + break; + case RES_MOD_SHORT: + model->RESshort = value->rValue; + model->RESshortGiven = TRUE; + break; + case RES_MOD_KF: + model->RESfNcoef = value->rValue; + model->RESfNcoefGiven = TRUE; + break; + case RES_MOD_AF: + model->RESfNexp = value->rValue; + model->RESfNexpGiven = TRUE; + break; + case RES_MOD_R: + if ( value->rValue > 1e-03 ) { + model->RESres = value->rValue; + model->RESresGiven = TRUE; + } + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/res/resnode.c b/src/spicelib/devices/res/resnode.c new file mode 100644 index 000000000..9e6cbbf60 --- /dev/null +++ b/src/spicelib/devices/res/resnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "resdefs.h" +#include "ngspice/sperror.h" + +int +RESnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + RESmodel *model = (RESmodel *)inModel ; + RESinstance *here ; + int error ; + + /* loop through all the RES models */ + for ( ; model != NULL ; model = model->RESnextModel) + { + /* loop through all the instances of the model */ + for (here = model->RESinstances ; here != NULL ; here = here->RESnextInstance) + { + error = CKTmkCurKCL (ckt, here->RESposNode, &(here->KCLcurrentPos)) ; + error = CKTmkCurKCL (ckt, here->RESnegNode, &(here->KCLcurrentNeg)) ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/res/resparam.c b/src/spicelib/devices/res/resparam.c index 8156a8160..d00ff04a6 100644 --- a/src/spicelib/devices/res/resparam.c +++ b/src/spicelib/devices/res/resparam.c @@ -19,59 +19,57 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) NG_IGNORE(select); switch(param) { - case RES_TEMP: - here->REStemp = value->rValue + CONSTCtoK; - here->REStempGiven = TRUE; - break; - case RES_DTEMP: - here->RESdtemp = value->rValue; - here->RESdtempGiven = TRUE; - break; - case RES_RESIST: - /* 0 valued resistor causes ngspice to hang -- can't solve for initial voltage */ - if ( AlmostEqualUlps( value->rValue, 0, 3 ) ) value->rValue = 0.001; /* 0.0001 should be sufficiently small */ - /* it's the value that smartspice uses */ - - here->RESresist = value->rValue; - here->RESresGiven = TRUE; - break; - case RES_ACRESIST: - here->RESacResist = value->rValue; - here->RESacresGiven = TRUE; - break; - case RES_WIDTH: - here->RESwidth = value->rValue; - here->RESwidthGiven = TRUE; - break; - case RES_LENGTH: - here->RESlength = value->rValue; - here->RESlengthGiven = TRUE; - break; - case RES_SCALE: - here->RESscale = value->rValue; - here->RESscaleGiven = TRUE; - break; - case RES_RESIST_SENS: - here->RESsenParmNo = value->iValue; - break; - case RES_M: - here->RESm = value->rValue; - here->RESmGiven = TRUE; - break; - case RES_TC1: - here->REStc1 = value->rValue; - here->REStc1Given = TRUE; - break; - case RES_TC2: - here->REStc2 = value->rValue; - here->REStc2Given = TRUE; - break; - case RES_NOISY: - here->RESnoisy = value->iValue; - here->RESnoisyGiven = TRUE; - break; - default: - return(E_BADPARM); + case RES_TEMP: + here->REStemp = value->rValue + CONSTCtoK; + here->REStempGiven = TRUE; + break; + case RES_DTEMP: + here->RESdtemp = value->rValue; + here->RESdtempGiven = TRUE; + break; + case RES_RESIST: + /* 0 valued resistor causes ngspice to hang -- can't solve for initial voltage */ + if ( AlmostEqualUlps( value->rValue, 0, 3 ) ) value->rValue = 0.001; /* 0.001 should be sufficiently small */ + here->RESresist = value->rValue; + here->RESresGiven = TRUE; + break; + case RES_ACRESIST: + here->RESacResist = value->rValue; + here->RESacresGiven = TRUE; + break; + case RES_WIDTH: + here->RESwidth = value->rValue; + here->RESwidthGiven = TRUE; + break; + case RES_LENGTH: + here->RESlength = value->rValue; + here->RESlengthGiven = TRUE; + break; + case RES_SCALE: + here->RESscale = value->rValue; + here->RESscaleGiven = TRUE; + break; + case RES_RESIST_SENS: + here->RESsenParmNo = value->iValue; + break; + case RES_M: + here->RESm = value->rValue; + here->RESmGiven = TRUE; + break; + case RES_TC1: + here->REStc1 = value->rValue; + here->REStc1Given = TRUE; + break; + case RES_TC2: + here->REStc2 = value->rValue; + here->REStc2Given = TRUE; + break; + case RES_NOISY: + here->RESnoisy = value->iValue; + here->RESnoisyGiven = TRUE; + break; + default: + return(E_BADPARM); } return(OK); } diff --git a/src/spicelib/devices/res/ressetup.c b/src/spicelib/devices/res/ressetup.c index d9b1f148a..0b70e4e7d 100644 --- a/src/spicelib/devices/res/ressetup.c +++ b/src/spicelib/devices/res/ressetup.c @@ -28,27 +28,15 @@ RESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state) /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; here=here->RESnextInstance) { - -/* - * Paolo Nenzi 2003 - * The following lines are needed if I will move the defaulting code - * from REStemp to RESsetup, as in other (more recent ?) spice devices - * - * ------------------------------------------LEGACY CODE - Francesco Lannutti - October 22, 2012 - * if (here->RESowner != ARCHme) - * goto matrixpointers; - * - * matrixpointers: - * ------------------------------------------ - * - * put here instance parameter defaulting. - */ - + + if(!here->RESmGiven) + here->RESm = 1.0; + /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) TSTALLOC(RESposPosptr, RESposNode, RESposNode); TSTALLOC(RESnegNegptr, RESnegNode, RESnegNode); diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index df227a7d7..9a93c9a7b 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified Apr 2000 - Paolo Nenzi +Modified Apr 2000 - Paolo Nenzi Modified: 2000 AlanSfixes **********/ @@ -12,17 +12,18 @@ Modified: 2000 AlanSfixes int REStemp(GENmodel *inModel, CKTcircuit *ckt) - /* perform the temperature update to the resistors - * calculate the conductance as a function of the - * given nominal and current temperatures - the - * resistance given in the struct is the nominal - * temperature resistance - */ +/* perform the temperature update to the resistors + * calculate the conductance as a function of the + * given nominal and current temperatures - the + * resistance given in the struct is the nominal + * temperature resistance + */ { RESmodel *model = (RESmodel *)inModel; RESinstance *here; double factor; double difference; + double tc1, tc2; /* loop through all the resistor models */ @@ -31,61 +32,76 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) /* Default Value Processing for Resistor Models */ if(!model->REStnomGiven) model->REStnom = ckt->CKTnomTemp; if(!model->RESsheetResGiven) model->RESsheetRes = 0.0; - if(!model->RESdefWidthGiven) model->RESdefWidth = 10.e-6; /*M*/ + if(!model->RESdefWidthGiven) model->RESdefWidth = 10e-6; /*M*/ + if(!model->RESdefLengthGiven) model->RESdefLength = 10e-6; if(!model->REStc1Given) model->REStempCoeff1 = 0.0; if(!model->REStc2Given) model->REStempCoeff2 = 0.0; if(!model->RESnarrowGiven) model->RESnarrow = 0.0; if(!model->RESshortGiven) model->RESshort = 0.0; - if(!model->RESfNcoefGiven) model->RESfNcoef = 0.0; - if(!model->RESfNexpGiven) model->RESfNexp = 1.0; + if(!model->RESfNcoefGiven) model->RESfNcoef = 0.0; + if(!model->RESfNexpGiven) model->RESfNexp = 1.0; /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; here=here->RESnextInstance) { /* Default Value Processing for Resistor Instance */ - - if(!here->REStempGiven) { - here->REStemp = ckt->CKTtemp; - if(!here->RESdtempGiven) here->RESdtemp = 0.0; - } else { /* REStempGiven */ - here->RESdtemp = 0.0; - if (here->RESdtempGiven) - printf("%s: Instance temperature specified, dtemp ignored\n", here->RESname); - } - - if(!here->RESwidthGiven) here->RESwidth = model->RESdefWidth; - if(!here->RESlengthGiven) here->RESlength = 0.0; - if(!here->RESscaleGiven) here->RESscale = 1.0; - if(!here->RESmGiven) here->RESm = 1.0; + + if(!here->REStempGiven) { + here->REStemp = ckt->CKTtemp; + if(!here->RESdtempGiven) here->RESdtemp = 0.0; + } else { /* REStempGiven */ + here->RESdtemp = 0.0; + if (here->RESdtempGiven) + printf("%s: Instance temperature specified, dtemp ignored\n", here->RESname); + } + + if(!here->RESwidthGiven) here->RESwidth = model->RESdefWidth; + if(!here->RESlengthGiven) here->RESlength = model->RESdefLength; + if(!here->RESscaleGiven) here->RESscale = 1.0; + if(!here->RESmGiven) here->RESm = 1.0; if(!here->RESnoisyGiven) here->RESnoisy = 1; if(!here->RESresGiven) { - if(model->RESsheetResGiven && (model->RESsheetRes != 0) && - (here->RESlength != 0)) { + if(here->RESlength * here->RESwidth * model->RESsheetRes > 0.0) { here->RESresist = model->RESsheetRes * (here->RESlength - - model->RESshort) / (here->RESwidth - model->RESnarrow); + model->RESshort) / (here->RESwidth - model->RESnarrow); } else { - SPfrontEnd->IFerror (ERR_WARNING, - "%s: resistance = 0 ohm, set to 1000 ohm",&(here->RESname)); - here->RESresist=1000; + if(model->RESresGiven) { + here->RESresist = model->RESres; + } else { + SPfrontEnd->IFerror (ERR_WARNING, + "%s: resistance to low, set to 1 mOhm",&(here->RESname)); + here->RESresist=1e-03; + } } } difference = (here->REStemp + here->RESdtemp) - model->REStnom; - - factor = 1.0 + (model->REStempCoeff1)*difference + - (model->REStempCoeff2)*difference*difference; + + /* instance parameters tc1 and tc2 will override + model parameters tc1 and tc2 */ + if (here->REStc1Given) + tc1 = here->REStc1; /* instance */ + else + tc1 = model->REStempCoeff1; /* model */ + + if (here->REStc2Given) + tc2 = here->REStc2; + else + tc2 = model->REStempCoeff2; + + factor = 1.0 + tc1*difference + + tc2*difference*difference; here -> RESconduct = (1.0/(here->RESresist * factor * here->RESscale)); - - - /* Paolo Nenzi: AC value */ - if(here->RESacresGiven) - here->RESacConduct = (1.0/(here->RESacResist * factor * here->RESscale)); - else { - here -> RESacConduct = here -> RESconduct; - here -> RESacResist = here -> RESresist; - } + + /* Paolo Nenzi: AC value */ + if(here->RESacresGiven) + here->RESacConduct = (1.0/(here->RESacResist * factor * here->RESscale)); + else { + here -> RESacConduct = here -> RESconduct; + here -> RESacResist = here -> RESresist; + } } } return(OK); diff --git a/src/spicelib/devices/soi3/Makefile.am b/src/spicelib/devices/soi3/Makefile.am index 105890491..6fd4237d5 100644 --- a/src/spicelib/devices/soi3/Makefile.am +++ b/src/spicelib/devices/soi3/Makefile.am @@ -39,6 +39,10 @@ if UMFPACK_WANTED libsoi3_la_SOURCES += soi3bindCSC.c endif +if KIRCHHOFF_WANTED +libsoi3_la_SOURCES += soi3node.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/soi3/soi3ext.h b/src/spicelib/devices/soi3/soi3ext.h index 8f1b4b8fe..7c5aea452 100644 --- a/src/spicelib/devices/soi3/soi3ext.h +++ b/src/spicelib/devices/soi3/soi3ext.h @@ -71,3 +71,7 @@ extern int SOI3bindCSC (GENmodel*, CKTcircuit*) ; extern int SOI3bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int SOI3bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int SOI3nodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/soi3/soi3init.c b/src/spicelib/devices/soi3/soi3init.c index c37b6bd48..f0842f68d 100644 --- a/src/spicelib/devices/soi3/soi3init.c +++ b/src/spicelib/devices/soi3/soi3init.c @@ -73,12 +73,17 @@ SPICEdev SOI3info = { #endif /* DEVinstSize */ &SOI3iSize, /* DEVmodSize */ &SOI3mSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ SOI3bindCSC, /* DEVbindCSCComplex */ SOI3bindCSCComplex, /* DEVbindCSCComplexToReal */ SOI3bindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ SOI3nodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/soi3/soi3node.c b/src/spicelib/devices/soi3/soi3node.c new file mode 100644 index 000000000..5f15572e5 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3node.c @@ -0,0 +1,36 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "soi3defs.h" +#include "ngspice/sperror.h" + +int +SOI3nodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + SOI3model *model = (SOI3model *)inModel ; + SOI3instance *here ; + + /* loop through all the SOI3 models */ + for ( ; model != NULL ; model = model->SOI3nextModel) + { + /* loop through all the instances of the model */ + for (here = model->SOI3instances ; here != NULL ; here = here->SOI3nextInstance) + { + ckt->CKTnodeIsLinear [here->SOI3dNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3sNodePrime] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3tout1Node] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3tout2Node] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3tout3Node] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3tout4Node] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3gfNode] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3gbNode] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3bNode] = 0 ; + ckt->CKTnodeIsLinear [here->SOI3toutNode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/soi3/soi3set.c b/src/spicelib/devices/soi3/soi3set.c index 4eb10b95b..879852314 100644 --- a/src/spicelib/devices/soi3/soi3set.c +++ b/src/spicelib/devices/soi3/soi3set.c @@ -566,94 +566,94 @@ SOI3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(SOI3D_dPtr,SOI3dNode,SOI3dNode) - TSTALLOC(SOI3D_dpPtr,SOI3dNode,SOI3dNodePrime) - TSTALLOC(SOI3DP_dPtr,SOI3dNodePrime,SOI3dNode) + TSTALLOC(SOI3D_dPtr,SOI3dNode,SOI3dNode); + TSTALLOC(SOI3D_dpPtr,SOI3dNode,SOI3dNodePrime); + TSTALLOC(SOI3DP_dPtr,SOI3dNodePrime,SOI3dNode); - TSTALLOC(SOI3S_sPtr,SOI3sNode,SOI3sNode) - TSTALLOC(SOI3S_spPtr,SOI3sNode,SOI3sNodePrime) - TSTALLOC(SOI3SP_sPtr,SOI3sNodePrime,SOI3sNode) + TSTALLOC(SOI3S_sPtr,SOI3sNode,SOI3sNode); + TSTALLOC(SOI3S_spPtr,SOI3sNode,SOI3sNodePrime); + TSTALLOC(SOI3SP_sPtr,SOI3sNodePrime,SOI3sNode); - TSTALLOC(SOI3GF_gfPtr,SOI3gfNode,SOI3gfNode) - TSTALLOC(SOI3GF_gbPtr,SOI3gfNode,SOI3gbNode) - TSTALLOC(SOI3GF_dpPtr,SOI3gfNode,SOI3dNodePrime) - TSTALLOC(SOI3GF_spPtr,SOI3gfNode,SOI3sNodePrime) - TSTALLOC(SOI3GF_bPtr,SOI3gfNode,SOI3bNode) + TSTALLOC(SOI3GF_gfPtr,SOI3gfNode,SOI3gfNode); + TSTALLOC(SOI3GF_gbPtr,SOI3gfNode,SOI3gbNode); + TSTALLOC(SOI3GF_dpPtr,SOI3gfNode,SOI3dNodePrime); + TSTALLOC(SOI3GF_spPtr,SOI3gfNode,SOI3sNodePrime); + TSTALLOC(SOI3GF_bPtr,SOI3gfNode,SOI3bNode); - TSTALLOC(SOI3GB_gfPtr,SOI3gbNode,SOI3gfNode) - TSTALLOC(SOI3GB_gbPtr,SOI3gbNode,SOI3gbNode) - TSTALLOC(SOI3GB_dpPtr,SOI3gbNode,SOI3dNodePrime) - TSTALLOC(SOI3GB_spPtr,SOI3gbNode,SOI3sNodePrime) - TSTALLOC(SOI3GB_bPtr,SOI3gbNode,SOI3bNode) + TSTALLOC(SOI3GB_gfPtr,SOI3gbNode,SOI3gfNode); + TSTALLOC(SOI3GB_gbPtr,SOI3gbNode,SOI3gbNode); + TSTALLOC(SOI3GB_dpPtr,SOI3gbNode,SOI3dNodePrime); + TSTALLOC(SOI3GB_spPtr,SOI3gbNode,SOI3sNodePrime); + TSTALLOC(SOI3GB_bPtr,SOI3gbNode,SOI3bNode); - TSTALLOC(SOI3B_gfPtr,SOI3bNode,SOI3gfNode) - TSTALLOC(SOI3B_gbPtr,SOI3bNode,SOI3gbNode) - TSTALLOC(SOI3B_dpPtr,SOI3bNode,SOI3dNodePrime) - TSTALLOC(SOI3B_spPtr,SOI3bNode,SOI3sNodePrime) - TSTALLOC(SOI3B_bPtr,SOI3bNode,SOI3bNode) + TSTALLOC(SOI3B_gfPtr,SOI3bNode,SOI3gfNode); + TSTALLOC(SOI3B_gbPtr,SOI3bNode,SOI3gbNode); + TSTALLOC(SOI3B_dpPtr,SOI3bNode,SOI3dNodePrime); + TSTALLOC(SOI3B_spPtr,SOI3bNode,SOI3sNodePrime); + TSTALLOC(SOI3B_bPtr,SOI3bNode,SOI3bNode); - TSTALLOC(SOI3DP_gfPtr,SOI3dNodePrime,SOI3gfNode) - TSTALLOC(SOI3DP_gbPtr,SOI3dNodePrime,SOI3gbNode) - TSTALLOC(SOI3DP_dpPtr,SOI3dNodePrime,SOI3dNodePrime) - TSTALLOC(SOI3DP_spPtr,SOI3dNodePrime,SOI3sNodePrime) - TSTALLOC(SOI3DP_bPtr,SOI3dNodePrime,SOI3bNode) + TSTALLOC(SOI3DP_gfPtr,SOI3dNodePrime,SOI3gfNode); + TSTALLOC(SOI3DP_gbPtr,SOI3dNodePrime,SOI3gbNode); + TSTALLOC(SOI3DP_dpPtr,SOI3dNodePrime,SOI3dNodePrime); + TSTALLOC(SOI3DP_spPtr,SOI3dNodePrime,SOI3sNodePrime); + TSTALLOC(SOI3DP_bPtr,SOI3dNodePrime,SOI3bNode); - TSTALLOC(SOI3SP_gfPtr,SOI3sNodePrime,SOI3gfNode) - TSTALLOC(SOI3SP_gbPtr,SOI3sNodePrime,SOI3gbNode) - TSTALLOC(SOI3SP_dpPtr,SOI3sNodePrime,SOI3dNodePrime) - TSTALLOC(SOI3SP_spPtr,SOI3sNodePrime,SOI3sNodePrime) - TSTALLOC(SOI3SP_bPtr,SOI3sNodePrime,SOI3bNode) + TSTALLOC(SOI3SP_gfPtr,SOI3sNodePrime,SOI3gfNode); + TSTALLOC(SOI3SP_gbPtr,SOI3sNodePrime,SOI3gbNode); + TSTALLOC(SOI3SP_dpPtr,SOI3sNodePrime,SOI3dNodePrime); + TSTALLOC(SOI3SP_spPtr,SOI3sNodePrime,SOI3sNodePrime); + TSTALLOC(SOI3SP_bPtr,SOI3sNodePrime,SOI3bNode); if (here->SOI3rt == 0) { - TSTALLOC(SOI3TOUT_ibrPtr,SOI3toutNode,SOI3branch) - TSTALLOC(SOI3IBR_toutPtr,SOI3branch,SOI3toutNode) + TSTALLOC(SOI3TOUT_ibrPtr,SOI3toutNode,SOI3branch); + TSTALLOC(SOI3IBR_toutPtr,SOI3branch,SOI3toutNode); } else { - TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode) + TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode); if (here->SOI3numThermalNodes > 1) { - TSTALLOC(SOI3TOUT_tout1Ptr,SOI3toutNode,SOI3tout1Node) - TSTALLOC(SOI3TOUT1_toutPtr,SOI3tout1Node,SOI3toutNode) - TSTALLOC(SOI3TOUT1_tout1Ptr,SOI3tout1Node,SOI3tout1Node) + TSTALLOC(SOI3TOUT_tout1Ptr,SOI3toutNode,SOI3tout1Node); + TSTALLOC(SOI3TOUT1_toutPtr,SOI3tout1Node,SOI3toutNode); + TSTALLOC(SOI3TOUT1_tout1Ptr,SOI3tout1Node,SOI3tout1Node); } if (here->SOI3numThermalNodes > 2) { - TSTALLOC(SOI3TOUT1_tout2Ptr,SOI3tout1Node,SOI3tout2Node) - TSTALLOC(SOI3TOUT2_tout1Ptr,SOI3tout2Node,SOI3tout1Node) - TSTALLOC(SOI3TOUT2_tout2Ptr,SOI3tout2Node,SOI3tout2Node) + TSTALLOC(SOI3TOUT1_tout2Ptr,SOI3tout1Node,SOI3tout2Node); + TSTALLOC(SOI3TOUT2_tout1Ptr,SOI3tout2Node,SOI3tout1Node); + TSTALLOC(SOI3TOUT2_tout2Ptr,SOI3tout2Node,SOI3tout2Node); } if (here->SOI3numThermalNodes > 3) { - TSTALLOC(SOI3TOUT2_tout3Ptr,SOI3tout2Node,SOI3tout3Node) - TSTALLOC(SOI3TOUT3_tout2Ptr,SOI3tout3Node,SOI3tout2Node) - TSTALLOC(SOI3TOUT3_tout3Ptr,SOI3tout3Node,SOI3tout3Node) + TSTALLOC(SOI3TOUT2_tout3Ptr,SOI3tout2Node,SOI3tout3Node); + TSTALLOC(SOI3TOUT3_tout2Ptr,SOI3tout3Node,SOI3tout2Node); + TSTALLOC(SOI3TOUT3_tout3Ptr,SOI3tout3Node,SOI3tout3Node); } if (here->SOI3numThermalNodes > 4) { - TSTALLOC(SOI3TOUT3_tout4Ptr,SOI3tout3Node,SOI3tout4Node) - TSTALLOC(SOI3TOUT4_tout3Ptr,SOI3tout4Node,SOI3tout3Node) - TSTALLOC(SOI3TOUT4_tout4Ptr,SOI3tout4Node,SOI3tout4Node) + TSTALLOC(SOI3TOUT3_tout4Ptr,SOI3tout3Node,SOI3tout4Node); + TSTALLOC(SOI3TOUT4_tout3Ptr,SOI3tout4Node,SOI3tout3Node); + TSTALLOC(SOI3TOUT4_tout4Ptr,SOI3tout4Node,SOI3tout4Node); } - TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode) - TSTALLOC(SOI3TOUT_gfPtr,SOI3toutNode,SOI3gfNode) - TSTALLOC(SOI3TOUT_gbPtr,SOI3toutNode,SOI3gbNode) - TSTALLOC(SOI3TOUT_dpPtr,SOI3toutNode,SOI3dNodePrime) - TSTALLOC(SOI3TOUT_spPtr,SOI3toutNode,SOI3sNodePrime) - TSTALLOC(SOI3TOUT_bPtr,SOI3toutNode,SOI3bNode) + TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode); + TSTALLOC(SOI3TOUT_gfPtr,SOI3toutNode,SOI3gfNode); + TSTALLOC(SOI3TOUT_gbPtr,SOI3toutNode,SOI3gbNode); + TSTALLOC(SOI3TOUT_dpPtr,SOI3toutNode,SOI3dNodePrime); + TSTALLOC(SOI3TOUT_spPtr,SOI3toutNode,SOI3sNodePrime); + TSTALLOC(SOI3TOUT_bPtr,SOI3toutNode,SOI3bNode); - TSTALLOC(SOI3GF_toutPtr,SOI3gfNode,SOI3toutNode) - TSTALLOC(SOI3GB_toutPtr,SOI3gbNode,SOI3toutNode) - TSTALLOC(SOI3DP_toutPtr,SOI3dNodePrime,SOI3toutNode) - TSTALLOC(SOI3SP_toutPtr,SOI3sNodePrime,SOI3toutNode) - TSTALLOC(SOI3B_toutPtr,SOI3bNode,SOI3toutNode) + TSTALLOC(SOI3GF_toutPtr,SOI3gfNode,SOI3toutNode); + TSTALLOC(SOI3GB_toutPtr,SOI3gbNode,SOI3toutNode); + TSTALLOC(SOI3DP_toutPtr,SOI3dNodePrime,SOI3toutNode); + TSTALLOC(SOI3SP_toutPtr,SOI3sNodePrime,SOI3toutNode); + TSTALLOC(SOI3B_toutPtr,SOI3bNode,SOI3toutNode); } } } diff --git a/src/spicelib/devices/sw/swinit.c b/src/spicelib/devices/sw/swinit.c index 0e833444f..8c5f99fb0 100644 --- a/src/spicelib/devices/sw/swinit.c +++ b/src/spicelib/devices/sw/swinit.c @@ -74,12 +74,17 @@ SPICEdev SWinfo = { #endif /* CIDER */ /* DEVinstSize */ &SWiSize, /* DEVmodSize */ &SWmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ SWbindCSC, /* DEVbindCSCComplex */ SWbindCSCComplex, /* DEVbindCSCComplexToReal */ SWbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/sw/swload.c b/src/spicelib/devices/sw/swload.c index 178cd8f98..72e16267f 100644 --- a/src/spicelib/devices/sw/swload.c +++ b/src/spicelib/devices/sw/swload.c @@ -138,6 +138,7 @@ SWload(GENmodel *inModel, CKTcircuit *ckt) // After analyzing the transient code, it seems that this is not a problem because state updating // occurs before the convergence loop in transient processing. *(ckt->CKTstates[0] + here->SWstate) = current_state; + *(ckt->CKTstates[0] + here->SWstate + 1) = v_ctrl; if ((current_state == REALLY_ON) || (current_state == HYST_ON)) g_now = model->SWonConduct; diff --git a/src/spicelib/devices/sw/swsetup.c b/src/spicelib/devices/sw/swsetup.c index 44b0f803e..384e05324 100644 --- a/src/spicelib/devices/sw/swsetup.c +++ b/src/spicelib/devices/sw/swsetup.c @@ -52,14 +52,14 @@ SWsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(SWposPosptr, SWposNode, SWposNode) - TSTALLOC(SWposNegptr, SWposNode, SWnegNode) - TSTALLOC(SWnegPosptr, SWnegNode, SWposNode) - TSTALLOC(SWnegNegptr, SWnegNode, SWnegNode) + TSTALLOC(SWposPosptr, SWposNode, SWposNode); + TSTALLOC(SWposNegptr, SWposNode, SWnegNode); + TSTALLOC(SWnegPosptr, SWnegNode, SWposNode); + TSTALLOC(SWnegNegptr, SWnegNode, SWnegNode); } } return(OK); diff --git a/src/spicelib/devices/tra/trainit.c b/src/spicelib/devices/tra/trainit.c index bf866743f..1d0cedc68 100644 --- a/src/spicelib/devices/tra/trainit.c +++ b/src/spicelib/devices/tra/trainit.c @@ -73,12 +73,17 @@ SPICEdev TRAinfo = { #endif /* DEVinstSize */ &TRAiSize, /* DEVmodSize */ &TRAmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ TRAbindCSC, /* DEVbindCSCComplex */ TRAbindCSCComplex, /* DEVbindCSCComplexToReal */ TRAbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/tra/trasetup.c b/src/spicelib/devices/tra/trasetup.c index 197dcda75..67d280a15 100644 --- a/src/spicelib/devices/tra/trasetup.c +++ b/src/spicelib/devices/tra/trasetup.c @@ -64,32 +64,32 @@ TRAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(TRAibr1Ibr2Ptr, TRAbrEq1, TRAbrEq2) - TSTALLOC(TRAibr1Int1Ptr, TRAbrEq1, TRAintNode1) - TSTALLOC(TRAibr1Neg1Ptr, TRAbrEq1, TRAnegNode1) - TSTALLOC(TRAibr1Neg2Ptr, TRAbrEq1, TRAnegNode2) - TSTALLOC(TRAibr1Pos2Ptr, TRAbrEq1, TRAposNode2) - TSTALLOC(TRAibr2Ibr1Ptr, TRAbrEq2, TRAbrEq1) - TSTALLOC(TRAibr2Int2Ptr, TRAbrEq2, TRAintNode2) - TSTALLOC(TRAibr2Neg1Ptr, TRAbrEq2, TRAnegNode1) - TSTALLOC(TRAibr2Neg2Ptr, TRAbrEq2, TRAnegNode2) - TSTALLOC(TRAibr2Pos1Ptr, TRAbrEq2, TRAposNode1) - TSTALLOC(TRAint1Ibr1Ptr, TRAintNode1, TRAbrEq1) - TSTALLOC(TRAint1Int1Ptr, TRAintNode1, TRAintNode1) - TSTALLOC(TRAint1Pos1Ptr, TRAintNode1, TRAposNode1) - TSTALLOC(TRAint2Ibr2Ptr, TRAintNode2, TRAbrEq2) - TSTALLOC(TRAint2Int2Ptr, TRAintNode2, TRAintNode2) - TSTALLOC(TRAint2Pos2Ptr, TRAintNode2, TRAposNode2) - TSTALLOC(TRAneg1Ibr1Ptr, TRAnegNode1, TRAbrEq1) - TSTALLOC(TRAneg2Ibr2Ptr, TRAnegNode2, TRAbrEq2) - TSTALLOC(TRApos1Int1Ptr, TRAposNode1, TRAintNode1) - TSTALLOC(TRApos1Pos1Ptr, TRAposNode1, TRAposNode1) - TSTALLOC(TRApos2Int2Ptr, TRAposNode2, TRAintNode2) - TSTALLOC(TRApos2Pos2Ptr, TRAposNode2, TRAposNode2) + TSTALLOC(TRAibr1Ibr2Ptr, TRAbrEq1, TRAbrEq2); + TSTALLOC(TRAibr1Int1Ptr, TRAbrEq1, TRAintNode1); + TSTALLOC(TRAibr1Neg1Ptr, TRAbrEq1, TRAnegNode1); + TSTALLOC(TRAibr1Neg2Ptr, TRAbrEq1, TRAnegNode2); + TSTALLOC(TRAibr1Pos2Ptr, TRAbrEq1, TRAposNode2); + TSTALLOC(TRAibr2Ibr1Ptr, TRAbrEq2, TRAbrEq1); + TSTALLOC(TRAibr2Int2Ptr, TRAbrEq2, TRAintNode2); + TSTALLOC(TRAibr2Neg1Ptr, TRAbrEq2, TRAnegNode1); + TSTALLOC(TRAibr2Neg2Ptr, TRAbrEq2, TRAnegNode2); + TSTALLOC(TRAibr2Pos1Ptr, TRAbrEq2, TRAposNode1); + TSTALLOC(TRAint1Ibr1Ptr, TRAintNode1, TRAbrEq1); + TSTALLOC(TRAint1Int1Ptr, TRAintNode1, TRAintNode1); + TSTALLOC(TRAint1Pos1Ptr, TRAintNode1, TRAposNode1); + TSTALLOC(TRAint2Ibr2Ptr, TRAintNode2, TRAbrEq2); + TSTALLOC(TRAint2Int2Ptr, TRAintNode2, TRAintNode2); + TSTALLOC(TRAint2Pos2Ptr, TRAintNode2, TRAposNode2); + TSTALLOC(TRAneg1Ibr1Ptr, TRAnegNode1, TRAbrEq1); + TSTALLOC(TRAneg2Ibr2Ptr, TRAnegNode2, TRAbrEq2); + TSTALLOC(TRApos1Int1Ptr, TRAposNode1, TRAintNode1); + TSTALLOC(TRApos1Pos1Ptr, TRAposNode1, TRAposNode1); + TSTALLOC(TRApos2Int2Ptr, TRAposNode2, TRAintNode2); + TSTALLOC(TRApos2Pos2Ptr, TRAposNode2, TRAposNode2); if(!here->TRAnlGiven) { here->TRAnl = .25; diff --git a/src/spicelib/devices/txl/txldefs.h b/src/spicelib/devices/txl/txldefs.h index abc620100..69e9e904a 100644 --- a/src/spicelib/devices/txl/txldefs.h +++ b/src/spicelib/devices/txl/txldefs.h @@ -47,7 +47,7 @@ typedef struct sTXLinstance { unsigned TXLibr1Given : 1; unsigned TXLibr2Given : 1; unsigned TXLdcGiven : 1; - unsigned TXLlengthgiven : 1; /* flag to indicate C was specified */ + unsigned TXLlengthgiven : 1; /* flag to indicate that instance parameter len is specified */ #ifdef KLU BindElement *TXLposPosptrStructPtr ; @@ -88,7 +88,7 @@ typedef struct sTXLmodel { /* model structure for a txl */ unsigned Lgiven : 1; /* flag to indicate L was specified */ unsigned Ggiven : 1; /* flag to indicate G was specified */ unsigned Cgiven : 1; /* flag to indicate C was specified */ - unsigned lengthgiven : 1; /* flag to indicate C was specified */ + unsigned lengthgiven : 1; /* flag to indicate length was specified */ } TXLmodel; diff --git a/src/spicelib/devices/txl/txlinit.c b/src/spicelib/devices/txl/txlinit.c index aa8ac7508..fd0b09261 100644 --- a/src/spicelib/devices/txl/txlinit.c +++ b/src/spicelib/devices/txl/txlinit.c @@ -76,14 +76,19 @@ SPICEdev TXLinfo = { /* DEVdump */ NULL, /* DEVacct */ NULL, #endif - &TXLiSize, - &TXLmSize, + /* DEVinstSize */ &TXLiSize, + /* DEVmodSize */ &TXLmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ TXLbindCSC, /* DEVbindCSCComplex */ TXLbindCSCComplex, /* DEVbindCSCComplexToReal */ TXLbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; SPICEdev * diff --git a/src/spicelib/devices/urc/urcinit.c b/src/spicelib/devices/urc/urcinit.c index 7d8746c6f..ccb2e76ff 100644 --- a/src/spicelib/devices/urc/urcinit.c +++ b/src/spicelib/devices/urc/urcinit.c @@ -73,12 +73,17 @@ SPICEdev URCinfo = { #endif /* DEVinstSize */ &URCiSize, /* DEVmodSize */ &URCmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ NULL, /* DEVbindCSCComplex */ NULL, /* DEVbindCSCComplexToReal */ NULL, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/vbic/Makefile.am b/src/spicelib/devices/vbic/Makefile.am index 09e93b51c..fde9320d6 100644 --- a/src/spicelib/devices/vbic/Makefile.am +++ b/src/spicelib/devices/vbic/Makefile.am @@ -39,6 +39,10 @@ if UMFPACK_WANTED libvbic_la_SOURCES += vbicbindCSC.c endif +if KIRCHHOFF_WANTED +libvbic_la_SOURCES += vbicnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/vbic/vbicext.h b/src/spicelib/devices/vbic/vbicext.h index c5f25d9c3..d6b100e45 100644 --- a/src/spicelib/devices/vbic/vbicext.h +++ b/src/spicelib/devices/vbic/vbicext.h @@ -26,6 +26,9 @@ extern int VBICtemp(GENmodel*,CKTcircuit*); extern int VBICtrunc(GENmodel*,CKTcircuit*,double*); extern int VBICnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +#ifdef KIRCHHOFF +extern int VBICnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif #endif #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) diff --git a/src/spicelib/devices/vbic/vbicinit.c b/src/spicelib/devices/vbic/vbicinit.c index e60138b87..d44aad3ba 100644 --- a/src/spicelib/devices/vbic/vbicinit.c +++ b/src/spicelib/devices/vbic/vbicinit.c @@ -78,12 +78,17 @@ SPICEdev VBICinfo = { #endif &VBICiSize, /* DEVinstSize */ &VBICmSize, /* DEVmodSize */ + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ VBICbindCSC, /* DEVbindCSCComplex */ VBICbindCSCComplex, /* DEVbindCSCComplexToReal */ VBICbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + VBICnodeIsNonLinear /* DEVnodeIsNonLinear */ +#endif + }; diff --git a/src/spicelib/devices/vbic/vbicload.c b/src/spicelib/devices/vbic/vbicload.c index 2a1890cc8..0a3f7ee5c 100644 --- a/src/spicelib/devices/vbic/vbicload.c +++ b/src/spicelib/devices/vbic/vbicload.c @@ -873,7 +873,6 @@ next1: printf("gpi = %.7e\n", Ibe_Vbei); printf("gmu = %.7e, gm = %.7e\n", Ibc_Vbci, Itzf_Vbei); printf("go = %.7e, gx = %.7e\n", Itzf_Vbci, Irbi_Vrbi); - printf("geqcb = %.7e, geqbx = %.7e\n", geqcb, geqbx); printf("cc = %.7e, cb = %.7e\n", Ibe+Itzf, Ibe); #endif /* SENSDEBUG */ continue; /* go to 1000 */ diff --git a/src/spicelib/devices/vbic/vbicnode.c b/src/spicelib/devices/vbic/vbicnode.c new file mode 100644 index 000000000..447ae8a66 --- /dev/null +++ b/src/spicelib/devices/vbic/vbicnode.c @@ -0,0 +1,33 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "vbicdefs.h" +#include "ngspice/sperror.h" + +int +VBICnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + VBICmodel *model = (VBICmodel *)inModel ; + VBICinstance *here ; + + /* loop through all the VBIC models */ + for ( ; model != NULL ; model = model->VBICnextModel) + { + /* loop through all the instances of the model */ + for (here = model->VBICinstances ; here != NULL ; here = here->VBICnextInstance) + { + ckt->CKTnodeIsLinear [here->VBICcollCXNode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICbaseBXNode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICemitEINode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICsubsSINode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICcollCINode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICbaseBPNode] = 0 ; + ckt->CKTnodeIsLinear [here->VBICbaseBINode] = 0 ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/vbic/vbicsetup.c b/src/spicelib/devices/vbic/vbicsetup.c index b233105c5..248a98b8c 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -472,62 +472,62 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} - TSTALLOC(VBICcollCollPtr,VBICcollNode,VBICcollNode) - TSTALLOC(VBICbaseBasePtr,VBICbaseNode,VBICbaseNode) - TSTALLOC(VBICemitEmitPtr,VBICemitNode,VBICemitNode) - TSTALLOC(VBICsubsSubsPtr,VBICsubsNode,VBICsubsNode) - TSTALLOC(VBICcollCXCollCXPtr,VBICcollCXNode,VBICcollCXNode) - TSTALLOC(VBICcollCICollCIPtr,VBICcollCINode,VBICcollCINode) - TSTALLOC(VBICbaseBXBaseBXPtr,VBICbaseBXNode,VBICbaseBXNode) - TSTALLOC(VBICbaseBIBaseBIPtr,VBICbaseBINode,VBICbaseBINode) - TSTALLOC(VBICemitEIEmitEIPtr,VBICemitEINode,VBICemitEINode) - TSTALLOC(VBICbaseBPBaseBPPtr,VBICbaseBPNode,VBICbaseBPNode) - TSTALLOC(VBICsubsSISubsSIPtr,VBICsubsSINode,VBICsubsSINode) +} } while(0) + TSTALLOC(VBICcollCollPtr,VBICcollNode,VBICcollNode); + TSTALLOC(VBICbaseBasePtr,VBICbaseNode,VBICbaseNode); + TSTALLOC(VBICemitEmitPtr,VBICemitNode,VBICemitNode); + TSTALLOC(VBICsubsSubsPtr,VBICsubsNode,VBICsubsNode); + TSTALLOC(VBICcollCXCollCXPtr,VBICcollCXNode,VBICcollCXNode); + TSTALLOC(VBICcollCICollCIPtr,VBICcollCINode,VBICcollCINode); + TSTALLOC(VBICbaseBXBaseBXPtr,VBICbaseBXNode,VBICbaseBXNode); + TSTALLOC(VBICbaseBIBaseBIPtr,VBICbaseBINode,VBICbaseBINode); + TSTALLOC(VBICemitEIEmitEIPtr,VBICemitEINode,VBICemitEINode); + TSTALLOC(VBICbaseBPBaseBPPtr,VBICbaseBPNode,VBICbaseBPNode); + TSTALLOC(VBICsubsSISubsSIPtr,VBICsubsSINode,VBICsubsSINode); - TSTALLOC(VBICbaseEmitPtr,VBICbaseNode,VBICemitNode) - TSTALLOC(VBICemitBasePtr,VBICemitNode,VBICbaseNode) - TSTALLOC(VBICbaseCollPtr,VBICbaseNode,VBICcollNode) - TSTALLOC(VBICcollBasePtr,VBICcollNode,VBICbaseNode) - TSTALLOC(VBICcollCollCXPtr,VBICcollNode,VBICcollCXNode) - TSTALLOC(VBICbaseBaseBXPtr,VBICbaseNode,VBICbaseBXNode) - TSTALLOC(VBICemitEmitEIPtr,VBICemitNode,VBICemitEINode) - TSTALLOC(VBICsubsSubsSIPtr,VBICsubsNode,VBICsubsSINode) - TSTALLOC(VBICcollCXCollCIPtr,VBICcollCXNode,VBICcollCINode) - TSTALLOC(VBICcollCXBaseBXPtr,VBICcollCXNode,VBICbaseBXNode) - TSTALLOC(VBICcollCXBaseBIPtr,VBICcollCXNode,VBICbaseBINode) - TSTALLOC(VBICcollCXBaseBPPtr,VBICcollCXNode,VBICbaseBPNode) - TSTALLOC(VBICcollCIBaseBIPtr,VBICcollCINode,VBICbaseBINode) - TSTALLOC(VBICcollCIEmitEIPtr,VBICcollCINode,VBICemitEINode) - TSTALLOC(VBICbaseBXBaseBIPtr,VBICbaseBXNode,VBICbaseBINode) - TSTALLOC(VBICbaseBXEmitEIPtr,VBICbaseBXNode,VBICemitEINode) - TSTALLOC(VBICbaseBXBaseBPPtr,VBICbaseBXNode,VBICbaseBPNode) - TSTALLOC(VBICbaseBXSubsSIPtr,VBICbaseBXNode,VBICsubsSINode) - TSTALLOC(VBICbaseBIEmitEIPtr,VBICbaseBINode,VBICemitEINode) - TSTALLOC(VBICbaseBPSubsSIPtr,VBICbaseBPNode,VBICsubsSINode) + TSTALLOC(VBICbaseEmitPtr,VBICbaseNode,VBICemitNode); + TSTALLOC(VBICemitBasePtr,VBICemitNode,VBICbaseNode); + TSTALLOC(VBICbaseCollPtr,VBICbaseNode,VBICcollNode); + TSTALLOC(VBICcollBasePtr,VBICcollNode,VBICbaseNode); + TSTALLOC(VBICcollCollCXPtr,VBICcollNode,VBICcollCXNode); + TSTALLOC(VBICbaseBaseBXPtr,VBICbaseNode,VBICbaseBXNode); + TSTALLOC(VBICemitEmitEIPtr,VBICemitNode,VBICemitEINode); + TSTALLOC(VBICsubsSubsSIPtr,VBICsubsNode,VBICsubsSINode); + TSTALLOC(VBICcollCXCollCIPtr,VBICcollCXNode,VBICcollCINode); + TSTALLOC(VBICcollCXBaseBXPtr,VBICcollCXNode,VBICbaseBXNode); + TSTALLOC(VBICcollCXBaseBIPtr,VBICcollCXNode,VBICbaseBINode); + TSTALLOC(VBICcollCXBaseBPPtr,VBICcollCXNode,VBICbaseBPNode); + TSTALLOC(VBICcollCIBaseBIPtr,VBICcollCINode,VBICbaseBINode); + TSTALLOC(VBICcollCIEmitEIPtr,VBICcollCINode,VBICemitEINode); + TSTALLOC(VBICbaseBXBaseBIPtr,VBICbaseBXNode,VBICbaseBINode); + TSTALLOC(VBICbaseBXEmitEIPtr,VBICbaseBXNode,VBICemitEINode); + TSTALLOC(VBICbaseBXBaseBPPtr,VBICbaseBXNode,VBICbaseBPNode); + TSTALLOC(VBICbaseBXSubsSIPtr,VBICbaseBXNode,VBICsubsSINode); + TSTALLOC(VBICbaseBIEmitEIPtr,VBICbaseBINode,VBICemitEINode); + TSTALLOC(VBICbaseBPSubsSIPtr,VBICbaseBPNode,VBICsubsSINode); - TSTALLOC(VBICcollCXCollPtr,VBICcollCXNode,VBICcollNode) - TSTALLOC(VBICbaseBXBasePtr,VBICbaseBXNode,VBICbaseNode) - TSTALLOC(VBICemitEIEmitPtr,VBICemitEINode,VBICemitNode) - TSTALLOC(VBICsubsSISubsPtr,VBICsubsSINode,VBICsubsNode) - TSTALLOC(VBICcollCICollCXPtr,VBICcollCINode,VBICcollCXNode) - TSTALLOC(VBICbaseBICollCXPtr,VBICbaseBINode,VBICcollCXNode) - TSTALLOC(VBICbaseBPCollCXPtr,VBICbaseBPNode,VBICcollCXNode) - TSTALLOC(VBICbaseBXCollCIPtr,VBICbaseBXNode,VBICcollCINode) - TSTALLOC(VBICbaseBICollCIPtr,VBICbaseBINode,VBICcollCINode) - TSTALLOC(VBICemitEICollCIPtr,VBICemitEINode,VBICcollCINode) - TSTALLOC(VBICbaseBPCollCIPtr,VBICbaseBPNode,VBICcollCINode) - TSTALLOC(VBICbaseBIBaseBXPtr,VBICbaseBINode,VBICbaseBXNode) - TSTALLOC(VBICemitEIBaseBXPtr,VBICemitEINode,VBICbaseBXNode) - TSTALLOC(VBICbaseBPBaseBXPtr,VBICbaseBPNode,VBICbaseBXNode) - TSTALLOC(VBICsubsSIBaseBXPtr,VBICsubsSINode,VBICbaseBXNode) - TSTALLOC(VBICemitEIBaseBIPtr,VBICemitEINode,VBICbaseBINode) - TSTALLOC(VBICbaseBPBaseBIPtr,VBICbaseBPNode,VBICbaseBINode) - TSTALLOC(VBICsubsSICollCIPtr,VBICsubsSINode,VBICcollCINode) - TSTALLOC(VBICsubsSIBaseBIPtr,VBICsubsSINode,VBICbaseBINode) - TSTALLOC(VBICsubsSIBaseBPPtr,VBICsubsSINode,VBICbaseBPNode) + TSTALLOC(VBICcollCXCollPtr,VBICcollCXNode,VBICcollNode); + TSTALLOC(VBICbaseBXBasePtr,VBICbaseBXNode,VBICbaseNode); + TSTALLOC(VBICemitEIEmitPtr,VBICemitEINode,VBICemitNode); + TSTALLOC(VBICsubsSISubsPtr,VBICsubsSINode,VBICsubsNode); + TSTALLOC(VBICcollCICollCXPtr,VBICcollCINode,VBICcollCXNode); + TSTALLOC(VBICbaseBICollCXPtr,VBICbaseBINode,VBICcollCXNode); + TSTALLOC(VBICbaseBPCollCXPtr,VBICbaseBPNode,VBICcollCXNode); + TSTALLOC(VBICbaseBXCollCIPtr,VBICbaseBXNode,VBICcollCINode); + TSTALLOC(VBICbaseBICollCIPtr,VBICbaseBINode,VBICcollCINode); + TSTALLOC(VBICemitEICollCIPtr,VBICemitEINode,VBICcollCINode); + TSTALLOC(VBICbaseBPCollCIPtr,VBICbaseBPNode,VBICcollCINode); + TSTALLOC(VBICbaseBIBaseBXPtr,VBICbaseBINode,VBICbaseBXNode); + TSTALLOC(VBICemitEIBaseBXPtr,VBICemitEINode,VBICbaseBXNode); + TSTALLOC(VBICbaseBPBaseBXPtr,VBICbaseBPNode,VBICbaseBXNode); + TSTALLOC(VBICsubsSIBaseBXPtr,VBICsubsSINode,VBICbaseBXNode); + TSTALLOC(VBICemitEIBaseBIPtr,VBICemitEINode,VBICbaseBINode); + TSTALLOC(VBICbaseBPBaseBIPtr,VBICbaseBPNode,VBICbaseBINode); + TSTALLOC(VBICsubsSICollCIPtr,VBICsubsSINode,VBICcollCINode); + TSTALLOC(VBICsubsSIBaseBIPtr,VBICsubsSINode,VBICbaseBINode); + TSTALLOC(VBICsubsSIBaseBPPtr,VBICsubsSINode,VBICbaseBPNode); } } diff --git a/src/spicelib/devices/vccs/vccs.c b/src/spicelib/devices/vccs/vccs.c index 313f730b5..087f3cc28 100644 --- a/src/spicelib/devices/vccs/vccs.c +++ b/src/spicelib/devices/vccs/vccs.c @@ -11,6 +11,7 @@ Author: 1987 Thomas L. Quarles IFparm VCCSpTable[] = { /* parameters */ IOPU("gain", VCCS_TRANS, IF_REAL, "Transconductance of source (gain)"), + IOP ( "m", VCCS_M, IF_REAL , "Parallel multiplier"), IP("sens_trans", VCCS_TRANS_SENS,IF_FLAG, "flag to request sensitivity WRT transconductance"), OPU("pos_node", VCCS_POS_NODE, IF_INTEGER, "Positive node of source"), diff --git a/src/spicelib/devices/vccs/vccsask.c b/src/spicelib/devices/vccs/vccsask.c index 2a5b369a4..64eef29af 100644 --- a/src/spicelib/devices/vccs/vccsask.c +++ b/src/spicelib/devices/vccs/vccsask.c @@ -31,6 +31,9 @@ VCCSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue * case VCCS_TRANS: value->rValue = here->VCCScoeff; return (OK); + case VCCS_M: + value->rValue = here->VCCSmValue; + return (OK); case VCCS_POS_NODE: value->iValue = here->VCCSposNode; return (OK); diff --git a/src/spicelib/devices/vccs/vccsdefs.h b/src/spicelib/devices/vccs/vccsdefs.h index ba6f011b9..f804ac953 100644 --- a/src/spicelib/devices/vccs/vccsdefs.h +++ b/src/spicelib/devices/vccs/vccsdefs.h @@ -31,6 +31,7 @@ typedef struct sVCCSinstance { double VCCSinitCond; /* initial condition (of controlling source) */ double VCCScoeff; /* coefficient */ + double VCCSmValue; /* Parallel multiplier */ double *VCCSposContPosptr; /* pointer to sparse matrix element at * (positive node, control positive node) */ @@ -41,6 +42,7 @@ typedef struct sVCCSinstance { double *VCCSnegContNegptr; /* pointer to sparse matrix element at * (negative node, control negative node) */ unsigned VCCScoeffGiven :1 ;/* flag to indicate function coeffs given */ + unsigned VCCSmGiven :1 ;/* flag to indicate multiplier given */ int VCCSsenParmNo; /* parameter # for sensitivity use; set equal to 0 if not a design parameter*/ @@ -80,6 +82,7 @@ typedef struct sVCCSmodel { /* model structure for a source */ #define VCCS_CURRENT 9 #define VCCS_POWER 10 #define VCCS_VOLTS 11 +#define VCCS_M 12 /* model parameters */ diff --git a/src/spicelib/devices/vccs/vccsinit.c b/src/spicelib/devices/vccs/vccsinit.c index 6b7aa0083..33b6caf59 100644 --- a/src/spicelib/devices/vccs/vccsinit.c +++ b/src/spicelib/devices/vccs/vccsinit.c @@ -73,12 +73,17 @@ SPICEdev VCCSinfo = { #endif /* DEVinstSize */ &VCCSiSize, /* DEVmodSize */ &VCCSmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ VCCSbindCSC, /* DEVbindCSCComplex */ VCCSbindCSCComplex, /* DEVbindCSCComplexToReal */ VCCSbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/vccs/vccsload.c b/src/spicelib/devices/vccs/vccsload.c index a647d4f1a..6be9fce00 100644 --- a/src/spicelib/devices/vccs/vccsload.c +++ b/src/spicelib/devices/vccs/vccsload.c @@ -35,6 +35,14 @@ VCCSload(GENmodel *inModel, CKTcircuit *ckt) *(here->VCCSposContNegptr) -= here->VCCScoeff ; *(here->VCCSnegContPosptr) -= here->VCCScoeff ; *(here->VCCSnegContNegptr) += here->VCCScoeff ; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->VCCSposNode) += here->VCCScoeff * *(ckt->CKTrhsOld+here->VCCScontPosNode) ; + *(ckt->CKTfvk+here->VCCSposNode) -= here->VCCScoeff * *(ckt->CKTrhsOld+here->VCCScontNegNode) ; + *(ckt->CKTfvk+here->VCCSnegNode) -= here->VCCScoeff * *(ckt->CKTrhsOld+here->VCCScontPosNode) ; + *(ckt->CKTfvk+here->VCCSnegNode) += here->VCCScoeff * *(ckt->CKTrhsOld+here->VCCScontNegNode) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/vccs/vccspar.c b/src/spicelib/devices/vccs/vccspar.c index 7f7b51a76..98c88279a 100644 --- a/src/spicelib/devices/vccs/vccspar.c +++ b/src/spicelib/devices/vccs/vccspar.c @@ -24,6 +24,12 @@ VCCSparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) case VCCS_TRANS: here->VCCScoeff = value->rValue; here->VCCScoeffGiven = TRUE; + if (here->VCCSmGiven) + here->VCCScoeff *= here->VCCSmValue; + break; + case VCCS_M: + here->VCCSmValue = value->rValue; + here->VCCSmGiven = TRUE; break; case VCCS_TRANS_SENS: here->VCCSsenParmNo = value->iValue; diff --git a/src/spicelib/devices/vccs/vccsset.c b/src/spicelib/devices/vccs/vccsset.c index 16e951218..0399385e2 100644 --- a/src/spicelib/devices/vccs/vccsset.c +++ b/src/spicelib/devices/vccs/vccsset.c @@ -36,14 +36,14 @@ VCCSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(VCCSposContPosptr, VCCSposNode, VCCScontPosNode) - TSTALLOC(VCCSposContNegptr, VCCSposNode, VCCScontNegNode) - TSTALLOC(VCCSnegContPosptr, VCCSnegNode, VCCScontPosNode) - TSTALLOC(VCCSnegContNegptr, VCCSnegNode, VCCScontNegNode) + TSTALLOC(VCCSposContPosptr, VCCSposNode, VCCScontPosNode); + TSTALLOC(VCCSposContNegptr, VCCSposNode, VCCScontNegNode); + TSTALLOC(VCCSnegContPosptr, VCCSnegNode, VCCScontPosNode); + TSTALLOC(VCCSnegContNegptr, VCCSnegNode, VCCScontNegNode); } } return(OK); diff --git a/src/spicelib/devices/vcvs/vcvsinit.c b/src/spicelib/devices/vcvs/vcvsinit.c index 4508f4800..268c83950 100644 --- a/src/spicelib/devices/vcvs/vcvsinit.c +++ b/src/spicelib/devices/vcvs/vcvsinit.c @@ -73,12 +73,17 @@ SPICEdev VCVSinfo = { #endif /* DEVinstSize */ &VCVSiSize, /* DEVmodSize */ &VCVSmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ VCVSbindCSC, /* DEVbindCSCComplex */ VCVSbindCSCComplex, /* DEVbindCSCComplexToReal */ VCVSbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ NULL +#endif + }; diff --git a/src/spicelib/devices/vcvs/vcvsload.c b/src/spicelib/devices/vcvs/vcvsload.c index 81a154b80..b2e345912 100644 --- a/src/spicelib/devices/vcvs/vcvsload.c +++ b/src/spicelib/devices/vcvs/vcvsload.c @@ -37,6 +37,12 @@ VCVSload(GENmodel *inModel, CKTcircuit *ckt) *(here->VCVSibrNegptr) -= 1.0 ; *(here->VCVSibrContPosptr) -= here->VCVScoeff ; *(here->VCVSibrContNegptr) += here->VCVScoeff ; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->VCVSposNode) += *(ckt->CKTrhsOld+here->VCVSbranch) ; + *(ckt->CKTfvk+here->VCVSnegNode) -= *(ckt->CKTrhsOld+here->VCVSbranch) ; +#endif + } } return(OK); diff --git a/src/spicelib/devices/vcvs/vcvsset.c b/src/spicelib/devices/vcvs/vcvsset.c index 3faef1625..33ad194d2 100644 --- a/src/spicelib/devices/vcvs/vcvsset.c +++ b/src/spicelib/devices/vcvs/vcvsset.c @@ -46,16 +46,16 @@ VCVSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(VCVSposIbrptr, VCVSposNode, VCVSbranch) - TSTALLOC(VCVSnegIbrptr, VCVSnegNode, VCVSbranch) - TSTALLOC(VCVSibrNegptr, VCVSbranch, VCVSnegNode) - TSTALLOC(VCVSibrPosptr, VCVSbranch, VCVSposNode) - TSTALLOC(VCVSibrContPosptr, VCVSbranch, VCVScontPosNode) - TSTALLOC(VCVSibrContNegptr, VCVSbranch, VCVScontNegNode) + TSTALLOC(VCVSposIbrptr, VCVSposNode, VCVSbranch); + TSTALLOC(VCVSnegIbrptr, VCVSnegNode, VCVSbranch); + TSTALLOC(VCVSibrPosptr, VCVSbranch, VCVSposNode); + TSTALLOC(VCVSibrNegptr, VCVSbranch, VCVSnegNode); + TSTALLOC(VCVSibrContPosptr, VCVSbranch, VCVScontPosNode); + TSTALLOC(VCVSibrContNegptr, VCVSbranch, VCVScontNegNode); } } return(OK); diff --git a/src/spicelib/devices/vsrc/Makefile.am b/src/spicelib/devices/vsrc/Makefile.am index d2468036c..cc450ca70 100644 --- a/src/spicelib/devices/vsrc/Makefile.am +++ b/src/spicelib/devices/vsrc/Makefile.am @@ -23,6 +23,7 @@ libvsrc_la_SOURCES = \ vsrcset.c \ vsrctemp.c + if KLU_WANTED libvsrc_la_SOURCES += vsrcbindCSC.c endif @@ -35,6 +36,10 @@ if UMFPACK_WANTED libvsrc_la_SOURCES += vsrcbindCSC.c endif +if KIRCHHOFF_WANTED +libvsrc_la_SOURCES += vsrcnode.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/vsrc/vsrc.c b/src/spicelib/devices/vsrc/vsrc.c index 88ae8eb3a..41bac74bd 100644 --- a/src/spicelib/devices/vsrc/vsrc.c +++ b/src/spicelib/devices/vsrc/vsrc.c @@ -23,7 +23,7 @@ IFparm VSRCpTable[] = { /* parameters */ IOP ("am", VSRC_AM, IF_REALVEC,"Amplitude modulation description"), IOP ("trnoise", VSRC_TRNOISE, IF_REALVEC,"Transient noise description"), IOP ("trrandom", VSRC_TRRANDOM, IF_REALVEC,"random source description"), - + IOP ("external", VSRC_EXTERNAL, IF_REALVEC,"external source description"), OPU ("pos_node",VSRC_POS_NODE, IF_INTEGER,"Positive node of source"), OPU ("neg_node",VSRC_NEG_NODE, IF_INTEGER,"Negative node of source"), OPU ("function",VSRC_FCN_TYPE, IF_INTEGER,"Function of the source"), diff --git a/src/spicelib/devices/vsrc/vsrcacct.c b/src/spicelib/devices/vsrc/vsrcacct.c index 7ce21fda4..0081ee918 100644 --- a/src/spicelib/devices/vsrc/vsrcacct.c +++ b/src/spicelib/devices/vsrc/vsrcacct.c @@ -290,7 +290,12 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel) } } break; - +#ifdef SHARED_MODULE + case EXTERNAL:{ + /* no breakpoints (yet) */ + } + break; +#endif } // switch } // if ... else bkptset: ; diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index 3c034a847..12a3533f6 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -83,6 +83,11 @@ typedef struct sVSRCinstance { BindElement *VSRCibrPosptrStructPtr ; #endif +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } VSRCinstance ; @@ -107,6 +112,7 @@ typedef struct sVSRCmodel { #define AM 6 #define TRNOISE 7 #define TRRANDOM 8 +#define EXTERNAL 9 #endif /*PULSE*/ /* device parameters */ @@ -137,6 +143,7 @@ typedef struct sVSRCmodel { #define VSRC_TD 24 #define VSRC_TRNOISE 25 #define VSRC_TRRANDOM 26 +#define VSRC_EXTERNAL 27 /* model parameters */ diff --git a/src/spicelib/devices/vsrc/vsrcext.h b/src/spicelib/devices/vsrc/vsrcext.h index ad65f8fa2..baf45e8d8 100644 --- a/src/spicelib/devices/vsrc/vsrcext.h +++ b/src/spicelib/devices/vsrc/vsrcext.h @@ -24,3 +24,7 @@ extern int VSRCbindCSC (GENmodel*, CKTcircuit*) ; extern int VSRCbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int VSRCbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef KIRCHHOFF +extern int VSRCnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/vsrc/vsrcinit.c b/src/spicelib/devices/vsrc/vsrcinit.c index 2fbb812e2..62358113a 100644 --- a/src/spicelib/devices/vsrc/vsrcinit.c +++ b/src/spicelib/devices/vsrc/vsrcinit.c @@ -73,12 +73,17 @@ SPICEdev VSRCinfo = { #endif /* DEVinstSize */ &VSRCiSize, /* DEVmodSize */ &VSRCmSize, + #if defined(KLU) || defined(SuperLU) || defined(UMFPACK) /* DEVbindCSC */ VSRCbindCSC, /* DEVbindCSCComplex */ VSRCbindCSCComplex, /* DEVbindCSCComplexToReal */ VSRCbindCSCComplexToReal, #endif +#ifdef KIRCHHOFF + /* DEVnodeIsNonLinear */ VSRCnodeIsNonLinear +#endif + }; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 28734b156..40c5d1d3f 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -18,6 +18,10 @@ Modified: 2000 AlansFixes /* gtri - end - wbk - modify for supply ramping option */ #endif +#ifdef SHARED_MODULE +extern double getvsrcval(double, char*); +#endif + int VSRCload(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current value into the @@ -40,6 +44,15 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) *(here->VSRCnegIbrptr) -= 1.0 ; *(here->VSRCibrPosptr) += 1.0 ; *(here->VSRCibrNegptr) -= 1.0 ; + +#ifdef KIRCHHOFF + *(ckt->CKTfvk+here->VSRCposNode) += *(ckt->CKTrhsOld+here->VSRCbranch) ; + *(ckt->CKTfvk+here->VSRCnegNode) -= *(ckt->CKTrhsOld+here->VSRCbranch) ; + + *(here->KCLcurrentPos) = *(ckt->CKTrhsOld+here->VSRCbranch) ; + *(here->KCLcurrentNeg) = -(*(ckt->CKTrhsOld+here->VSRCbranch)) ; +#endif + if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->VSRCdcGiven ) { /* load using DC value */ @@ -384,7 +397,14 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise value += here->VSRCdcValue; } break; - +#ifdef SHARED_MODULE + case EXTERNAL: { + value = getvsrcval(time, here->VSRCname); + if(here -> VSRCdcGiven) + value += here->VSRCdcValue; + } + break; +#endif } // switch } // else (line 48) loadDone: diff --git a/src/spicelib/devices/vsrc/vsrcnode.c b/src/spicelib/devices/vsrc/vsrcnode.c new file mode 100644 index 000000000..fe733593c --- /dev/null +++ b/src/spicelib/devices/vsrc/vsrcnode.c @@ -0,0 +1,29 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "vsrcdefs.h" +#include "ngspice/sperror.h" + +int +VSRCnodeIsNonLinear (GENmodel *inModel, CKTcircuit *ckt) +{ + VSRCmodel *model = (VSRCmodel *)inModel ; + VSRCinstance *here ; + int error ; + + /* loop through all the VSRC models */ + for ( ; model != NULL ; model = model->VSRCnextModel) + { + /* loop through all the instances of the model */ + for (here = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + error = CKTmkCurKCL (ckt, here->VSRCposNode, &(here->KCLcurrentPos)) ; + error = CKTmkCurKCL (ckt, here->VSRCnegNode, &(here->KCLcurrentNeg)) ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index e0db81974..f21ec4354 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -261,6 +261,17 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) } break; +#ifdef SHARED_MODULE + case VSRC_EXTERNAL: { + here->VSRCfunctionType = EXTERNAL; + here->VSRCfuncTGiven = TRUE; + /* no coefficients + copy_coeffs(here, value); + */ + } + break; +#endif + default: return(E_BADPARM); } diff --git a/src/spicelib/devices/vsrc/vsrcpzs.c b/src/spicelib/devices/vsrc/vsrcpzs.c index 616802832..42b125cbd 100644 --- a/src/spicelib/devices/vsrc/vsrcpzs.c +++ b/src/spicelib/devices/vsrc/vsrcpzs.c @@ -38,15 +38,15 @@ VSRCpzSetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(VSRCposIbrptr, VSRCposNode, VSRCbranch) - TSTALLOC(VSRCnegIbrptr, VSRCnegNode, VSRCbranch) - TSTALLOC(VSRCibrNegptr, VSRCbranch, VSRCnegNode) - TSTALLOC(VSRCibrPosptr, VSRCbranch, VSRCposNode) - TSTALLOC(VSRCibrIbrptr, VSRCbranch, VSRCbranch) + TSTALLOC(VSRCposIbrptr, VSRCposNode, VSRCbranch); + TSTALLOC(VSRCnegIbrptr, VSRCnegNode, VSRCbranch); + TSTALLOC(VSRCibrNegptr, VSRCbranch, VSRCnegNode); + TSTALLOC(VSRCibrPosptr, VSRCbranch, VSRCposNode); + TSTALLOC(VSRCibrIbrptr, VSRCbranch, VSRCbranch); } } return(OK); diff --git a/src/spicelib/devices/vsrc/vsrcset.c b/src/spicelib/devices/vsrc/vsrcset.c index 0428bbc86..79160d7a0 100644 --- a/src/spicelib/devices/vsrc/vsrcset.c +++ b/src/spicelib/devices/vsrc/vsrcset.c @@ -45,14 +45,14 @@ VSRCsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) /* macro to make elements with built in test for out of memory */ #define TSTALLOC(ptr,first,second) \ -if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ -} +} } while(0) - TSTALLOC(VSRCposIbrptr, VSRCposNode, VSRCbranch) - TSTALLOC(VSRCnegIbrptr, VSRCnegNode, VSRCbranch) - TSTALLOC(VSRCibrNegptr, VSRCbranch, VSRCnegNode) - TSTALLOC(VSRCibrPosptr, VSRCbranch, VSRCposNode) + TSTALLOC(VSRCposIbrptr, VSRCposNode, VSRCbranch); + TSTALLOC(VSRCnegIbrptr, VSRCnegNode, VSRCbranch); + TSTALLOC(VSRCibrNegptr, VSRCbranch, VSRCnegNode); + TSTALLOC(VSRCibrPosptr, VSRCbranch, VSRCposNode); } } return(OK); diff --git a/src/spicelib/parser/ifeval.c b/src/spicelib/parser/ifeval.c index e3fcca3da..eadb89ab2 100644 --- a/src/spicelib/parser/ifeval.c +++ b/src/spicelib/parser/ifeval.c @@ -29,7 +29,7 @@ IFeval(IFparseTree * tree, double gmin, double *result, double *vals, double *derivs) { int i, err; - INPparseTree *myTree = (INPparseTree *) tree;; + INPparseTree *myTree = (INPparseTree *) tree; #ifdef TRACE INPptPrint("calling PTeval, tree = ", tree); @@ -94,6 +94,7 @@ PTeval(INPparseNode * tree, double gmin, double *res, double *vals) switch(tree->funcnum) { case PTF_POW: + case PTF_PWR: case PTF_MIN: case PTF_MAX: err = PTeval(tree->left->left, gmin, &r1, vals); diff --git a/src/spicelib/parser/inp2c.c b/src/spicelib/parser/inp2c.c index b8aaac369..5a926ec45 100644 --- a/src/spicelib/parser/inp2c.c +++ b/src/spicelib/parser/inp2c.c @@ -16,7 +16,7 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, card * current) /* parse a capacitor card */ /* Cname [] [] [IC=] */ - int mytype; /* the type we determine capacitors are */ + static int mytype = -1; /* the type we determine capacitors are */ int type = 0; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *saveline; /* ... just in case we need to go back... */ @@ -41,10 +41,11 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, card * current) printf("In INP2C, Current line: %s\n", current->line); #endif - mytype = INPtypelook("Capacitor"); if (mytype < 0) { - LITERR("Device type Capacitor not supported by this binary\n"); - return; + if ((mytype = INPtypelook("Capacitor")) < 0) { + LITERR("Device type Capacitor not supported by this binary\n"); + return; + } } line = current->line; INPgetTok(&line, &name, 1); @@ -80,8 +81,7 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, card * current) line = saveline; /* go back */ type = mytype; if (!tab->defCmod) { /* create default C model */ - IFnewUid(ckt, &uid, NULL, "C", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "C", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defCmod), uid)); } mdfast = tab->defCmod; @@ -93,8 +93,7 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defCmod) { /* create default C model */ - IFnewUid(ckt, &uid, NULL, "C", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "C", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defCmod), uid)); } IFC(newInstance, (ckt, tab->defCmod, &fast, name)); diff --git a/src/spicelib/parser/inp2d.c b/src/spicelib/parser/inp2d.c index 2a6489f2c..ea1c28242 100644 --- a/src/spicelib/parser/inp2d.c +++ b/src/spicelib/parser/inp2d.c @@ -67,8 +67,7 @@ void INP2D(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defDmod) { /* create default D model */ - IFnewUid(ckt, &uid, NULL, "D", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "D", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defDmod), uid)); } mdfast = tab->defDmod; @@ -81,7 +80,7 @@ void INP2D(CKTcircuit *ckt, INPtables * tab, card * current) #ifdef CIDER if( type == INPtypelook("NUMD2") ) { - LITERR(" error: no unlabelled parameter permitted on NUMD2\n") + LITERR(" error: no unlabelled parameter permitted on NUMD2\n"); } else { #endif ptemp.rValue = leadval; diff --git a/src/spicelib/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c index 206c534ba..3813bec70 100644 --- a/src/spicelib/parser/inp2dot.c +++ b/src/spicelib/parser/inp2dot.c @@ -58,7 +58,7 @@ dot_noise(char *line, CKTcircuit *ckt, INPtables *tab, card *current, INPgetNetTok(&line, &nname1, 0); INPtermInsert(ckt, &nname1, tab, &node1); ptemp.nValue = node1; - GCA(INPapName, (ckt, which, foo, "output", &ptemp)) + GCA(INPapName, (ckt, which, foo, "output", &ptemp)); if (*line != ')') { INPgetNetTok(&line, &nname2, 1); @@ -67,12 +67,12 @@ dot_noise(char *line, CKTcircuit *ckt, INPtables *tab, card *current, } else { ptemp.nValue = gnode; } - GCA(INPapName, (ckt, which, foo, "outputref", &ptemp)) + GCA(INPapName, (ckt, which, foo, "outputref", &ptemp)); INPgetTok(&line, &name, 1); INPinsert(&name, tab); ptemp.uValue = name; - GCA(INPapName, (ckt, which, foo, "input", &ptemp)) + GCA(INPapName, (ckt, which, foo, "input", &ptemp)); INPgetTok(&line, &steptype, 1); ptemp.iValue = 1; @@ -501,7 +501,7 @@ dot_sens(char *line, CKTcircuit *ckt, INPtables *tab, card *current, INPgetNetTok(&line, &nname1, 0); INPtermInsert(ckt, &nname1, tab, &node1); ptemp.nValue = node1; - GCA(INPapName, (ckt, which, foo, "outpos", &ptemp)) + GCA(INPapName, (ckt, which, foo, "outpos", &ptemp)); if (*line != ')') { INPgetNetTok(&line, &nname2, 1); @@ -532,7 +532,7 @@ dot_sens(char *line, CKTcircuit *ckt, INPtables *tab, card *current, INPgetTok(&line, &name, 1); if (name && !strcmp(name, "pct")) { ptemp.iValue = 1; - GCA(INPapName, (ckt, which, foo, "pct", &ptemp)) + GCA(INPapName, (ckt, which, foo, "pct", &ptemp)); INPgetTok(&line, &name, 1); } if (name && !strcmp(name, "ac")) { @@ -567,6 +567,8 @@ dot_sens2(char *line, CKTcircuit *ckt, INPtables *tab, card *current, int i; /* generic loop variable */ char *token; /* a token from the line */ + NG_IGNORE(gnode); + /* .sens {AC} {DC} {TRAN} [dev=nnn parm=nnn]* */ which = -1; for (i = 0; i < ft_sim->numAnalyses; i++) { @@ -667,7 +669,7 @@ dot_pss(char *line, void *ckt, INPtables *tab, card *current, INPgetNetTok(&line, &nname, 0); INPtermInsert(ckt, &nname, tab, &nnode); ptemp.nValue = nnode; - GCA(INPapName, (ckt, which, foo, "oscnode", &ptemp)) /* OscNode given as string */ + GCA(INPapName, (ckt, which, foo, "oscnode", &ptemp)); /* OscNode given as string */ parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* PSS points */ GCA(INPapName, (ckt, which, foo, "points", parm)); diff --git a/src/spicelib/parser/inp2i.c b/src/spicelib/parser/inp2i.c index 8895eb5fe..644e174b5 100644 --- a/src/spicelib/parser/inp2i.c +++ b/src/spicelib/parser/inp2i.c @@ -17,7 +17,7 @@ void INP2I(CKTcircuit *ckt, INPtables * tab, card * current) /* Iname [ [DC] ] [AC [ [ ] ] ] * [] */ - int type; /* the type the model says it is */ + static int type = -1; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *name; /* the resistor's name */ char *nname1; /* the first node's name */ @@ -31,10 +31,11 @@ void INP2I(CKTcircuit *ckt, INPtables * tab, card * current) double leadval; /* actual value of unlabeled number */ IFuid uid; /* uid for default model */ - type = INPtypelook("Isource"); if (type < 0) { - LITERR("Device type Isource not supported by this binary\n"); - return; + if ((type = INPtypelook("Isource")) < 0) { + LITERR("Device type Isource not supported by this binary\n"); + return; + } } line = current->line; INPgetTok(&line, &name, 1); diff --git a/src/spicelib/parser/inp2j.c b/src/spicelib/parser/inp2j.c index 5dcd3be41..39dacd03c 100644 --- a/src/spicelib/parser/inp2j.c +++ b/src/spicelib/parser/inp2j.c @@ -65,8 +65,7 @@ void INP2J(CKTcircuit *ckt, INPtables * tab, card * current) } if (!tab->defJmod) { /* create default J model */ - IFnewUid(ckt, &uid, NULL, "J", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "J", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defJmod), uid)); } mdfast = tab->defJmod; diff --git a/src/spicelib/parser/inp2l.c b/src/spicelib/parser/inp2l.c index d72330a6e..ea466c9e5 100644 --- a/src/spicelib/parser/inp2l.c +++ b/src/spicelib/parser/inp2l.c @@ -16,7 +16,7 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, card * current) /* parse an inductor card */ /* Lname [] [] [IC=] */ - int mytype; /* the type we determine inductors are */ + int mytype = -1; /* the type we determine inductors are */ int type = 0; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *saveline; /* ... just in case we need to go back... */ @@ -41,10 +41,11 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, card * current) printf("In INP2L, Current line: %s\n", current->line); #endif - mytype = INPtypelook("Inductor"); if (mytype < 0) { - LITERR("Device type Inductor not supported by this binary\n"); - return; + if ((mytype = INPtypelook("Inductor")) < 0) { + LITERR("Device type Inductor not supported by this binary\n"); + return; + } } line = current->line; INPgetTok(&line, &name, 1); @@ -80,8 +81,7 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, card * current) line = saveline; /* go back */ type = mytype; if (!tab->defLmod) { /* create default L model */ - IFnewUid(ckt, &uid, NULL, "L", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "L", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defLmod), uid)); } mdfast = tab->defLmod; @@ -93,8 +93,7 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defLmod) { /* create default L model */ - IFnewUid(ckt, &uid, NULL, "L", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "L", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defLmod), uid)); } IFC(newInstance, (ckt, tab->defLmod, &fast, name)); diff --git a/src/spicelib/parser/inp2m.c b/src/spicelib/parser/inp2m.c index 29c03657a..f9492e346 100644 --- a/src/spicelib/parser/inp2m.c +++ b/src/spicelib/parser/inp2m.c @@ -124,7 +124,8 @@ INP2M (CKTcircuit *ckt, INPtables * tab, card * current) ) { /* if model is not variable node B3SOIPD/FD/DD model, error! */ - LITERR ("only level 55-58: B3SOI(PD|FD|DD) and B4SOI can have 7 nodes") return; + LITERR ("only level 55-58: B3SOI(PD|FD|DD) and B4SOI can have 7 nodes"); + return; } else { /* if looking at B3SOIPD/FD/DD or B4SOI model, allocate the 7th node */ @@ -155,7 +156,8 @@ INP2M (CKTcircuit *ckt, INPtables * tab, card * current) ) { /* if model is not variable node B3SOIPD/FD/DD or STAG model, error! */ - LITERR ("only level 55-58,61,62: B3SOI(PD|FD|DD), B4SOI, STAG (SOI3) and HiSIMHV can have 6 nodes") return; + LITERR ("only level 55-58,61,62: B3SOI(PD|FD|DD), B4SOI, STAG (SOI3) and HiSIMHV can have 6 nodes"); + return; } else { /* if looking at B3SOIPD/FD/DD, B4SOI, STAG (SOI3) or HiSIMHV model, allocate the 6th node */ @@ -176,7 +178,8 @@ INP2M (CKTcircuit *ckt, INPtables * tab, card * current) ) { /* if model is not variable node B3SOIPD/FD/DD model, error! */ - LITERR ("only level 55-58,61,62: B3SOI(PD|FD|DD), B4SOI, STAG (SOI3) and HiSIMHV can have 5 nodes") return; + LITERR ("only level 55-58,61,62: B3SOI(PD|FD|DD), B4SOI, STAG (SOI3) and HiSIMHV can have 5 nodes"); + return; } else { /* if looking at B3SOIPD/FD/DD, B4SOI, STAG (SOI3) or HiSIMHV model, allocate the 5th node */ @@ -282,19 +285,19 @@ INP2M (CKTcircuit *ckt, INPtables * tab, card * current) fast->GENnode7 = -1; break; case 1: - IFC (bindNode, (ckt, fast, 5, node5)) + IFC (bindNode, (ckt, fast, 5, node5)); fast->GENnode6 = -1; fast->GENnode7 = -1; break; case 2: - IFC (bindNode, (ckt, fast, 5, node5)) - IFC (bindNode, (ckt, fast, 6, node6)) + IFC (bindNode, (ckt, fast, 5, node5)); + IFC (bindNode, (ckt, fast, 6, node6)); fast->GENnode7 = -1; break; case 3: - IFC (bindNode, (ckt, fast, 5, node5)) - IFC (bindNode, (ckt, fast, 6, node6)) - IFC (bindNode, (ckt, fast, 7, node7)) + IFC (bindNode, (ckt, fast, 5, node5)); + IFC (bindNode, (ckt, fast, 6, node6)); + IFC (bindNode, (ckt, fast, 7, node7)); break; default: break; diff --git a/src/spicelib/parser/inp2o.c b/src/spicelib/parser/inp2o.c index d401d5aed..d2ea82b9c 100644 --- a/src/spicelib/parser/inp2o.c +++ b/src/spicelib/parser/inp2o.c @@ -76,8 +76,7 @@ void INP2O(CKTcircuit *ckt, INPtables * tab, card * current) } else { if (!tab->defOmod) { /* create default O model */ - IFnewUid(ckt, &uid, NULL, "O", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "O", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defOmod), uid)); } mdfast = tab->defOmod; diff --git a/src/spicelib/parser/inp2p.c b/src/spicelib/parser/inp2p.c index da733acfa..da5cc4928 100644 --- a/src/spicelib/parser/inp2p.c +++ b/src/spicelib/parser/inp2p.c @@ -43,7 +43,7 @@ int num, i; mytype = INPtypelook("CplLines"); if(mytype < 0 ) { - LITERR("Device type CplLines not supported by this binary\n") + LITERR("Device type CplLines not supported by this binary\n"); return; } line = current->line; @@ -87,7 +87,7 @@ int num, i; current->error = INPgetMod(ckt,model,&thismodel,tab); if(thismodel != NULL) { if(mytype != thismodel->INPmodType) { - LITERR("incorrect model type") + LITERR("incorrect model type"); return; } mdfast = thismodel->INPmodfast; @@ -97,32 +97,32 @@ int num, i; if(!tab->defPmod) { /* create default P model */ IFnewUid(ckt, &uid, NULL, "P", UID_MODEL, NULL); - IFC(newModel, (ckt,type,&(tab->defPmod),uid)) + IFC(newModel, (ckt,type,&(tab->defPmod),uid)); } mdfast = tab->defPmod; } - IFC(newInstance,(ckt,mdfast,&fast,name)) + IFC(newInstance,(ckt,mdfast,&fast,name)); INPgetTok(&line,&model,1); if ((strcmp(model, "length") == 0) || (strcmp(model, "len") == 0)) { lenval = INPevaluate(&line,&error1,1); lenvalgiven = 1; } } else { - LITERR("model name is not found") + LITERR("model name is not found"); return; } - /* IFC(bindNode,(ckt,fast,1,fakename)) */ + /* IFC(bindNode,(ckt,fast,1,fakename)); */ ptemp.iValue = num; - GCA(INPpName,("dimension", &ptemp,ckt,type,fast)) + GCA(INPpName,("dimension", &ptemp,ckt,type,fast)); ptemp.v.vec.sVec = nname1; - GCA(INPpName,("pos_nodes", &ptemp,ckt,type,fast)) + GCA(INPpName,("pos_nodes", &ptemp,ckt,type,fast)); ptemp.v.vec.sVec = nname2; - GCA(INPpName,("neg_nodes", &ptemp,ckt,type,fast)) + GCA(INPpName,("neg_nodes", &ptemp,ckt,type,fast)); if (error1 == 0 && lenvalgiven) { ptemp.rValue = lenval; - GCA(INPpName,("length",&ptemp,ckt,type,fast)) + GCA(INPpName,("length",&ptemp,ckt,type,fast)); } return; diff --git a/src/spicelib/parser/inp2q.c b/src/spicelib/parser/inp2q.c index d3f859bec..d114b8e60 100644 --- a/src/spicelib/parser/inp2q.c +++ b/src/spicelib/parser/inp2q.c @@ -129,7 +129,7 @@ void INP2Q(CKTcircuit *ckt, INPtables * tab, card * current, CKTnode *gnode) #endif && (thismodel->INPmodType != INPtypelook("VBIC"))) { - LITERR("incorrect model type") + LITERR("incorrect model type"); return; } #ifdef ADMS @@ -137,7 +137,7 @@ void INP2Q(CKTcircuit *ckt, INPtables * tab, card * current, CKTnode *gnode) && (nodeflag && (thismodel->INPmodType != INPtypelook("hicum2"))) && (nodeflag && (thismodel->INPmodType != INPtypelook("bjt504t")))) { - LITERR("Too much nodes for this model type") + LITERR("Too much nodes for this model type"); return; } #endif @@ -182,7 +182,7 @@ void INP2Q(CKTcircuit *ckt, INPtables * tab, card * current, CKTnode *gnode) if (waslead) { #ifdef CIDER if( type == INPtypelook("NBJT2") ) { - LITERR(" error: no unlabeled parameter permitted on NBJT2\n") + LITERR(" error: no unlabeled parameter permitted on NBJT2\n"); } else { #endif ptemp.rValue = leadval; diff --git a/src/spicelib/parser/inp2r.c b/src/spicelib/parser/inp2r.c index 29c5b6db3..da0d370aa 100644 --- a/src/spicelib/parser/inp2r.c +++ b/src/spicelib/parser/inp2r.c @@ -22,7 +22,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, card * current) /* parse a resistor card */ /* Rname [][][w=][l=][ac=] */ - int mytype; /* the type we determine resistors are */ + static int mytype = -1; /* the type we determine resistors are */ int type = 0; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *saveline; /* ... just in case we need to go back... */ @@ -49,10 +49,11 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, card * current) printf("In INP2R, Current line: %s\n", current->line); #endif - mytype = INPtypelook("Resistor"); if (mytype < 0) { - LITERR("Device type Resistor not supported by this binary\n"); - return; + if ((mytype = INPtypelook("Resistor")) < 0) { + LITERR("Device type Resistor not supported by this binary\n"); + return; + } } line = current->line; INPgetTok(&line, &name, 1); /* Rname */ @@ -171,8 +172,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, card * current) line = saveline; /* go back */ type = mytype; if (!tab->defRmod) { /* create default R model */ - IFnewUid(ckt, &uid, NULL, "R", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "R", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defRmod), uid)); } mdfast = tab->defRmod; @@ -184,8 +184,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defRmod) { /* create default R model */ - IFnewUid(ckt, &uid, NULL, "R", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "R", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defRmod), uid)); } IFC(newInstance, (ckt, tab->defRmod, &fast, name)); @@ -199,7 +198,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, card * current) if (error1 == 0) { /* got a resistance above */ ptemp.rValue = val; - GCA(INPpName, ("resistance", &ptemp, ckt, type, fast)) + GCA(INPpName, ("resistance", &ptemp, ckt, type, fast)); } IFC(bindNode, (ckt, fast, 1, node1)); diff --git a/src/spicelib/parser/inp2s.c b/src/spicelib/parser/inp2s.c index 720241609..bcd3c2cda 100644 --- a/src/spicelib/parser/inp2s.c +++ b/src/spicelib/parser/inp2s.c @@ -68,8 +68,7 @@ void INP2S(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defSmod) { /* create deafult S model */ - IFnewUid(ckt, &uid, NULL, "S", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "S", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defSmod), uid)); } mdfast = tab->defSmod; diff --git a/src/spicelib/parser/inp2u.c b/src/spicelib/parser/inp2u.c index 8505b5513..5e6bb6275 100644 --- a/src/spicelib/parser/inp2u.c +++ b/src/spicelib/parser/inp2u.c @@ -62,8 +62,7 @@ void INP2U(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defUmod) { /* create deafult U model */ - IFnewUid(ckt, &uid, NULL, "U", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "U", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defUmod), uid)); } mdfast = tab->defUmod; diff --git a/src/spicelib/parser/inp2v.c b/src/spicelib/parser/inp2v.c index 01ce5ddf8..0c726ad18 100644 --- a/src/spicelib/parser/inp2v.c +++ b/src/spicelib/parser/inp2v.c @@ -17,7 +17,7 @@ void INP2V(CKTcircuit *ckt, INPtables * tab, card * current) /* Vname [ [DC] ] [AC [ [ ] ] ] * [] */ - int type; /* the type the model says it is */ + static int type = -1; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *name; /* the resistor's name */ char *nname1; /* the first node's name */ @@ -31,10 +31,11 @@ void INP2V(CKTcircuit *ckt, INPtables * tab, card * current) double leadval; /* actual value of unlabeled number */ IFuid uid; /* uid for default model */ - type = INPtypelook("Vsource"); if (type < 0) { - LITERR("Device type Vsource not supported by this binary\n"); - return; + if ((type = INPtypelook("Vsource")) < 0) { + LITERR("Device type Vsource not supported by this binary\n"); + return; + } } line = current->line; INPgetTok(&line, &name, 1); diff --git a/src/spicelib/parser/inp2w.c b/src/spicelib/parser/inp2w.c index 813e6439f..78046fde1 100644 --- a/src/spicelib/parser/inp2w.c +++ b/src/spicelib/parser/inp2w.c @@ -65,8 +65,7 @@ void INP2W(CKTcircuit *ckt, INPtables * tab, card * current) type = mytype; if (!tab->defWmod) { /* create deafult W model */ - IFnewUid(ckt, &uid, NULL, "W", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "W", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defWmod), uid)); } mdfast = tab->defWmod; diff --git a/src/spicelib/parser/inp2y.c b/src/spicelib/parser/inp2y.c index 49545098d..ea7b01a44 100644 --- a/src/spicelib/parser/inp2y.c +++ b/src/spicelib/parser/inp2y.c @@ -30,8 +30,8 @@ char *buf; /* temporary buffer for parsing */ char *model; /* the name of the resistor's model */ char *nname1; /* the first node's name */ char *nname2; /* the second node's name */ -char rname1[10], rname2[10], rname3[10]; -char cname1[10], cname2[10], cname3[10], cname4[10]; +char *rname1, *rname2, *rname3; +char *cname1, *cname2, *cname3, *cname4; char *internal1, *internal2; char *ground1, *ground2; CKTnode *node1; /* the first node's node pointer */ @@ -54,7 +54,7 @@ int lenvalgiven = 0; mytype2 = INPtypelook("CplLines"); if(mytype < 0 ) { - LITERR("Device type TransLine not supported by this binary\n") + LITERR("Device type TransLine not supported by this binary\n"); return; } line = current->line; @@ -85,7 +85,7 @@ int lenvalgiven = 0; return; } else if (mytype != thismodel->INPmodType) { - LITERR("incorrect model type") + LITERR("incorrect model type"); return; } line = thismodel->INPmodLine->line; @@ -115,90 +115,113 @@ int lenvalgiven = 0; INPgetTok(&line,&buf,1); } if (lenval && rval && lval && rval/lval > 1.6e10) { - /* use 3-pi model */ + /* use 3-pi model for high resistance as fall back */ rval = 3.0 / (rval * lenval); cval = cval * lenval / 6.0; type = INPtypelook("Resistor"); /* resistor between node1 and internal1 */ - internal1 = TMALLOC(char, 10); + internal1 = TMALLOC(char, 10 + strlen(name)); strcpy(internal1, "txlnd1"); + strcat(internal1, name); INPtermInsert(ckt, &internal1, tab, &inode1); if(!tab->defRmod) { /* create default R model */ IFnewUid(ckt, &uid, NULL, "R", UID_MODEL, NULL); - IFC(newModel, (ckt,type,&(tab->defRmod),uid)) + IFC(newModel, (ckt,type,&(tab->defRmod),uid)); } mdfast = tab->defRmod; + rname1 = TMALLOC(char, 10 + strlen(name)); strcpy(rname1, "txlres1"); - IFC(newInstance,(ckt,mdfast,&fast,rname1)) - IFC(bindNode,(ckt,fast,1,node1)) - IFC(bindNode,(ckt,fast,2,inode1)) + strcat(rname1, name); + INPinsert(&rname1, tab); + IFC(newInstance,(ckt,mdfast,&fast,rname1)); + IFC(bindNode,(ckt,fast,1,node1)); + IFC(bindNode,(ckt,fast,2,inode1)); ptemp.rValue = rval; - GCA(INPpName,("resistance",&ptemp,ckt,type,fast)) + GCA(INPpName,("resistance",&ptemp,ckt,type,fast)); /* resistor between internal1 and internal2 */ - internal2 = TMALLOC(char, 10); + internal2 = TMALLOC(char, 10 + strlen(name)); strcpy(internal2, "txlnd2"); + strcat(internal2, name); INPtermInsert(ckt, &internal2, tab, &inode2); + rname2 = TMALLOC(char, 10 + strlen(name)); strcpy(rname2, "txlres2"); + strcat(rname2, name); + INPinsert(&rname2, tab); mdfast2 = tab->defRmod; - IFC(newInstance,(ckt,mdfast2,&fast2,rname2)) - IFC(bindNode,(ckt,fast2,1,inode1)) - IFC(bindNode,(ckt,fast2,2,inode2)) + IFC(newInstance,(ckt,mdfast2,&fast2,rname2)); + IFC(bindNode,(ckt,fast2,1,inode1)); + IFC(bindNode,(ckt,fast2,2,inode2)); ptemp.rValue = rval; - GCA(INPpName,("resistance",&ptemp,ckt,type,fast2)) + GCA(INPpName,("resistance",&ptemp,ckt,type,fast2)); /* resistor between internal2 and node2 */ + rname3 = TMALLOC(char, 10 + strlen(name)); strcpy(rname3, "txlres3"); + strcat(rname3, name); + INPinsert(&rname3, tab); mdfast3 = tab->defRmod; - IFC(newInstance,(ckt,mdfast3,&fast3,rname3)) - IFC(bindNode,(ckt,fast3,1,inode2)) - IFC(bindNode,(ckt,fast3,2,node2)) + IFC(newInstance,(ckt,mdfast3,&fast3,rname3)); + IFC(bindNode,(ckt,fast3,1,inode2)); + IFC(bindNode,(ckt,fast3,2,node2)); ptemp.rValue = rval; - GCA(INPpName,("resistance",&ptemp,ckt,type,fast3)) + GCA(INPpName,("resistance",&ptemp,ckt,type,fast3)); /* capacitor on node1 */ type = INPtypelook("Capacitor"); if(!tab->defCmod) { IFnewUid(ckt, &uid, NULL, "C", UID_MODEL, NULL); - IFC(newModel,(ckt,type,&(tab->defCmod),uid)) + IFC(newModel,(ckt,type,&(tab->defCmod),uid)); } mdfast4 = tab->defCmod; + cname1 = TMALLOC(char, 10 + strlen(name)); strcpy(cname1, "txlcap1"); - IFC(newInstance,(ckt,mdfast4,&fast4,cname1)) - IFC(bindNode,(ckt,fast4,1,node1)) - IFC(bindNode,(ckt,fast4,2,gnode1)) + strcat(cname1, name); + INPinsert(&cname1, tab); + IFC(newInstance,(ckt,mdfast4,&fast4,cname1)); + IFC(bindNode,(ckt,fast4,1,node1)); + IFC(bindNode,(ckt,fast4,2,gnode1)); ptemp.rValue = cval; - GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) + GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)); /* capacitor on internal1 */ + cname2 = TMALLOC(char, 10 + strlen(name)); strcpy(cname2, "txlcap2"); + strcat(cname2, name); + INPinsert(&cname2, tab); mdfast4 = tab->defCmod; - IFC(newInstance,(ckt,mdfast4,&fast4,cname2)) - IFC(bindNode,(ckt,fast4,1,inode1)) - IFC(bindNode,(ckt,fast4,2,gnode1)) + IFC(newInstance,(ckt,mdfast4,&fast4,cname2)); + IFC(bindNode,(ckt,fast4,1,inode1)); + IFC(bindNode,(ckt,fast4,2,gnode1)); ptemp.rValue = cval * 2; - GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) + GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)); /* capacitor on internal2 */ + cname3 = TMALLOC(char, 10 + strlen(name)); strcpy(cname3, "txlcap3"); + strcat(cname3, name); + INPinsert(&cname3, tab); mdfast5 = tab->defCmod; - IFC(newInstance,(ckt,mdfast5,&fast5,cname3)) - IFC(bindNode,(ckt,fast5,1,inode2)) - IFC(bindNode,(ckt,fast5,2,gnode1)) + IFC(newInstance,(ckt,mdfast5,&fast5,cname3)); + IFC(bindNode,(ckt,fast5,1,inode2)); + IFC(bindNode,(ckt,fast5,2,gnode1)); ptemp.rValue = cval * 2; - GCA(INPpName,("capacitance",&ptemp,ckt,type,fast5)) + GCA(INPpName,("capacitance",&ptemp,ckt,type,fast5)); /* capacitor on node2 */ + cname4 = TMALLOC(char, 10 + strlen(name)); strcpy(cname4, "txlcap4"); + strcat(cname4, name); + INPinsert(&cname4, tab); mdfast6 = tab->defCmod; - IFC(newInstance,(ckt,mdfast6,&fast6,cname4)) - IFC(bindNode,(ckt,fast6,1,node2)) - IFC(bindNode,(ckt,fast6,2,gnode1)) + IFC(newInstance,(ckt,mdfast6,&fast6,cname4)); + IFC(bindNode,(ckt,fast6,1,node2)); + IFC(bindNode,(ckt,fast6,2,gnode1)); ptemp.rValue = cval; - GCA(INPpName,("capacitance",&ptemp,ckt,type,fast6)) + GCA(INPpName,("capacitance",&ptemp,ckt,type,fast6)); return; } @@ -211,23 +234,23 @@ int lenvalgiven = 0; if(!tab->defYmod) { /* create default Y model */ IFnewUid(ckt, &uid, NULL, "Y", UID_MODEL, NULL); - IFC(newModel, (ckt,type,&(tab->defYmod),uid)) + IFC(newModel, (ckt,type,&(tab->defYmod),uid)); } mdfast = tab->defYmod; } - IFC(newInstance,(ckt,mdfast,&fast,name)) + IFC(newInstance,(ckt,mdfast,&fast,name)); } else { - LITERR("model name is not found") + LITERR("model name is not found"); return; } if (error1 == 0 && lenvalgiven) { ptemp.rValue = lenval; - GCA(INPpName,("length",&ptemp,ckt,type,fast)) + GCA(INPpName,("length",&ptemp,ckt,type,fast)); } - IFC(bindNode,(ckt,fast,1,node1)) - IFC(bindNode,(ckt,fast,2,node2)) + IFC(bindNode,(ckt,fast,1,node1)); + IFC(bindNode,(ckt,fast,2,node2)); txl = /*fixme*/ fast; diff --git a/src/spicelib/parser/inp2z.c b/src/spicelib/parser/inp2z.c index fc50ab3b8..24a25e21c 100644 --- a/src/spicelib/parser/inp2z.c +++ b/src/spicelib/parser/inp2z.c @@ -62,7 +62,7 @@ void INP2Z(CKTcircuit *ckt, INPtables * tab, card * current) && thismodel->INPmodType != INPtypelook("HFET1") && thismodel->INPmodType != INPtypelook("HFET2")) { - LITERR("incorrect model type") + LITERR("incorrect model type"); return; } @@ -79,8 +79,7 @@ void INP2Z(CKTcircuit *ckt, INPtables * tab, card * current) if (!tab->defZmod) { /* create default Z model */ - IFnewUid(ckt, &uid, NULL, "Z", UID_MODEL, - NULL); + IFnewUid(ckt, &uid, NULL, "Z", UID_MODEL, NULL); IFC(newModel, (ckt, type, &(tab->defZmod), uid)); } mdfast = tab->defZmod; diff --git a/src/spicelib/parser/inpaname.c b/src/spicelib/parser/inpaname.c index 5a251f916..ed8f65d45 100644 --- a/src/spicelib/parser/inpaname.c +++ b/src/spicelib/parser/inpaname.c @@ -40,8 +40,7 @@ INPaName(char *parm, IFvalue * val, CKTcircuit *ckt, int *dev, char *devnam, * (name, type, direct pointer) - the type and direct pointer * WILL be set on return unless error is not OK */ - error = sim->findInstance (ckt, dev, fast, devnam, NULL, - NULL); + error = sim->findInstance (ckt, dev, fast, devnam, NULL); if (error) return (error); diff --git a/src/spicelib/parser/inppas3.c b/src/spicelib/parser/inppas3.c index 35bcaf4a5..10eb40c28 100644 --- a/src/spicelib/parser/inppas3.c +++ b/src/spicelib/parser/inppas3.c @@ -61,7 +61,7 @@ INPpas3(CKTcircuit *ckt, card *data, INPtables *tab, TSKtask *task, } if(which == -1) { - LITERR("nodeset unknown to simulator. \n") + LITERR("nodeset unknown to simulator. \n"); goto quit; } @@ -91,7 +91,7 @@ INPpas3(CKTcircuit *ckt, card *data, INPtables *tab, TSKtask *task, IFC(setNodeParm, (ckt, node1, which, &ptemp, NULL)); continue; } - LITERR(" Error: .nodeset syntax error.\n") + LITERR(" Error: .nodeset syntax error.\n"); break; } } else if ((strcmp(token,".ic") == 0)) { @@ -105,7 +105,7 @@ INPpas3(CKTcircuit *ckt, card *data, INPtables *tab, TSKtask *task, } if(which==-1) { - LITERR("ic unknown to simulator. \n") + LITERR("ic unknown to simulator. \n"); goto quit; } @@ -124,10 +124,10 @@ INPpas3(CKTcircuit *ckt, card *data, INPtables *tab, TSKtask *task, fprintf(stderr, "Warning : IC on non-existant node - %s\n", name); ptemp.rValue = INPevaluate(&line,&error,1); - IFC(setNodeParm, (ckt, node1, which, &ptemp, NULL)) + IFC(setNodeParm, (ckt, node1, which, &ptemp, NULL)); continue; } - LITERR(" Error: .ic syntax error.\n") + LITERR(" Error: .ic syntax error.\n"); break; } } diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 110036bdc..3533b7cd5 100644 --- a/src/spicelib/parser/inpptree.c +++ b/src/spicelib/parser/inpptree.c @@ -1,6 +1,6 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group +Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ //#define TRACE @@ -15,11 +15,11 @@ extern void controlled_exit(int status); static INPparseNode *mkcon(double value); static INPparseNode *mkb(int type, INPparseNode * left, - INPparseNode * right); + INPparseNode * right); static INPparseNode *mkf(int type, INPparseNode * arg); static int PTcheck(INPparseNode * p); static INPparseNode *mkbnode(const char *opstr, INPparseNode * arg1, - INPparseNode * arg2); + INPparseNode * arg2); static INPparseNode *mkfnode(const char *fname, INPparseNode * arg); static INPparseNode *mkvnode(char *name); static INPparseNode *mkinode(char *name); @@ -30,6 +30,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum); static void free_tree(INPparseNode *); +static void printTree(INPparseNode *); /* * LAW for INPparseNode* generator and consumer functions: @@ -108,7 +109,7 @@ static INPtables *tables; # define __func__ __FUNCTION__ /* __func__ is C99, but MSC can't */ #endif -extern IFsimulator *ft_sim; /* XXX */ +extern IFsimulator *ft_sim; /* XXX */ /* Some tables that the parser uses. */ @@ -167,6 +168,7 @@ static struct func { { "ge0", PTF_GE0, (void(*)(void)) PTge0}, { "le0", PTF_LE0, (void(*)(void)) PTle0}, { "pow", PTF_POW, (void(*)(void)) PTpower}, + { "pwr", PTF_PWR, (void(*)(void)) PTpwr}, { "min", PTF_MIN, (void(*)(void)) PTmin}, { "max", PTF_MAX, (void(*)(void)) PTmax}, } ; @@ -212,8 +214,8 @@ INPgetTree(char **line, INPparseTree ** pt, CKTcircuit *ckt, INPtables * tab) if (rv || !p || !PTcheck(p)) { - *pt = NULL; - release_tree(p); + *pt = NULL; + release_tree(p); } else { @@ -258,248 +260,248 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) case PT_TEMPERATURE: case PT_FREQUENCY: case PT_CONSTANT: - newp = mkcon(0.0); - break; + newp = mkcon(0.0); + break; case PT_VAR: - /* Is this the variable we're differentiating wrt? */ - if (p->valueIndex == varnum) - newp = mkcon(1.0); - else - newp = mkcon(0.0); - break; + /* Is this the variable we're differentiating wrt? */ + if (p->valueIndex == varnum) + newp = mkcon(1.0); + else + newp = mkcon(0.0); + break; case PT_PLUS: case PT_MINUS: - arg1 = PTdifferentiate(p->left, varnum); - arg2 = PTdifferentiate(p->right, varnum); - newp = mkb(p->type, arg1, arg2); - break; + arg1 = PTdifferentiate(p->left, varnum); + arg2 = PTdifferentiate(p->right, varnum); + newp = mkb(p->type, arg1, arg2); + break; case PT_TIMES: - /* d(a * b) = d(a) * b + d(b) * a */ - arg1 = PTdifferentiate(p->left, varnum); - arg2 = PTdifferentiate(p->right, varnum); + /* d(a * b) = d(a) * b + d(b) * a */ + arg1 = PTdifferentiate(p->left, varnum); + arg2 = PTdifferentiate(p->right, varnum); - newp = mkb(PT_PLUS, mkb(PT_TIMES, arg1, p->right), - mkb(PT_TIMES, p->left, arg2)); - break; + newp = mkb(PT_PLUS, mkb(PT_TIMES, arg1, p->right), + mkb(PT_TIMES, p->left, arg2)); + break; case PT_DIVIDE: - /* d(a / b) = (d(a) * b - d(b) * a) / b^2 */ - arg1 = PTdifferentiate(p->left, varnum); - arg2 = PTdifferentiate(p->right, varnum); + /* d(a / b) = (d(a) * b - d(b) * a) / b^2 */ + arg1 = PTdifferentiate(p->left, varnum); + arg2 = PTdifferentiate(p->right, varnum); - newp = mkb(PT_DIVIDE, mkb(PT_MINUS, mkb(PT_TIMES, arg1, - p->right), mkb(PT_TIMES, - p->left, - arg2)), - mkb(PT_POWER, p->right, mkcon(2.0))); - break; + newp = mkb(PT_DIVIDE, mkb(PT_MINUS, mkb(PT_TIMES, arg1, + p->right), mkb(PT_TIMES, + p->left, + arg2)), + mkb(PT_POWER, p->right, mkcon(2.0))); + break; case PT_POWER: - if (p->right->type == PT_CONSTANT) { - /* - * D(f^C) = C * f^(C-1) * D(f) - */ - arg1 = PTdifferentiate(p->left, varnum); + if (p->right->type == PT_CONSTANT) { + /* + * D(f^C) = C * f^(C-1) * D(f) + */ + arg1 = PTdifferentiate(p->left, varnum); + + newp = mkb(PT_TIMES, mkb(PT_TIMES, + mkcon(p->right->constant), + mkb(PT_POWER, p->left, + mkcon(p->right->constant - 1))), + arg1); + } else { + /* + * D(f^g) = D(exp(g*ln(f))) + * = exp(g*ln(f)) * D(g*ln(f)) + * = exp(g*ln(f)) * (D(g)*ln(f) + g*D(f)/f) + */ + arg1 = PTdifferentiate(p->left, varnum); + arg2 = PTdifferentiate(p->right, varnum); + newp = mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES, + p->right, mkf(PTF_LN, + p->left))), + mkb(PT_PLUS, + mkb(PT_TIMES, p->right, + mkb(PT_DIVIDE, arg1, p->left)), + mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left)))); + } + break; - newp = mkb(PT_TIMES, mkb(PT_TIMES, - mkcon(p->right->constant), - mkb(PT_POWER, p->left, - mkcon(p->right->constant - 1))), - arg1); - } else { - /* - * D(f^g) = D(exp(g*ln(f))) - * = exp(g*ln(f)) * D(g*ln(f)) - * = exp(g*ln(f)) * (D(g)*ln(f) + g*D(f)/f) - */ - arg1 = PTdifferentiate(p->left, varnum); - arg2 = PTdifferentiate(p->right, varnum); - newp = mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES, - p->right, mkf(PTF_LN, - p->left))), - mkb(PT_PLUS, - mkb(PT_TIMES, p->right, - mkb(PT_DIVIDE, arg1, p->left)), - mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left)))); - } - break; - case PT_TERN: /* ternary_fcn(cond,exp1,exp2) */ // naive: // d/d ternary_fcn(cond,exp1,exp2) --> ternary_fcn(cond, d/d exp1, d/d exp2) { - INPparseNode *arg1 = p->left; - INPparseNode *arg2 = p->right->left; - INPparseNode *arg3 = p->right->right; + INPparseNode *arg1 = p->left; + INPparseNode *arg2 = p->right->left; + INPparseNode *arg3 = p->right->right; -// extern void printTree(INPparseNode *); +// extern void printTree(INPparseNode *); // -// printf("debug: %s, PT_TERN: ", __func__); -// printTree(p); -// printf("\n"); +// printf("debug: %s, PT_TERN: ", __func__); +// printTree(p); +// printf("\n"); - newp = mkb(PT_TERN, arg1, mkb(PT_COMMA, - PTdifferentiate(arg2, varnum), - PTdifferentiate(arg3, varnum))); + newp = mkb(PT_TERN, arg1, mkb(PT_COMMA, + PTdifferentiate(arg2, varnum), + PTdifferentiate(arg3, varnum))); -// printf("debug, %s, returns; ", __func__); -// printTree(newp); -// printf("\n"); +// printf("debug, %s, returns; ", __func__); +// printTree(newp); +// printf("\n"); - return mkfirst(newp, p); + return mkfirst(newp, p); } case PT_FUNCTION: - /* Many cases. Set arg1 to the derivative of the function, - * and arg2 to the derivative of the argument. - */ - switch (p->funcnum) { - case PTF_ABS: /* sgn(u) */ - arg1 = mkf(PTF_SGN, p->left); - break; + /* Many cases. Set arg1 to the derivative of the function, + * and arg2 to the derivative of the argument. + */ + switch (p->funcnum) { + case PTF_ABS: /* sgn(u) */ + arg1 = mkf(PTF_SGN, p->left); + break; - case PTF_SGN: - arg1 = mkcon(0.0); - break; + case PTF_SGN: + arg1 = mkcon(0.0); + break; - case PTF_ACOS: /* - 1 / sqrt(1 - u^2) */ - arg1 = mkb(PT_DIVIDE, mkcon(-1.0), mkf(PTF_SQRT, - mkb(PT_MINUS, - mkcon(1.0), - mkb(PT_POWER, - p->left, - mkcon(2.0))))); - break; + case PTF_ACOS: /* - 1 / sqrt(1 - u^2) */ + arg1 = mkb(PT_DIVIDE, mkcon(-1.0), mkf(PTF_SQRT, + mkb(PT_MINUS, + mkcon(1.0), + mkb(PT_POWER, + p->left, + mkcon(2.0))))); + break; - case PTF_ACOSH: /* 1 / sqrt(u^2 - 1) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, - mkb(PT_MINUS, - mkb(PT_POWER, - p->left, - mkcon(2.0)), - mkcon(1.0)))); + case PTF_ACOSH: /* 1 / sqrt(u^2 - 1) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, + mkb(PT_MINUS, + mkb(PT_POWER, + p->left, + mkcon(2.0)), + mkcon(1.0)))); - break; + break; - case PTF_ASIN: /* 1 / sqrt(1 - u^2) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, - mkb(PT_MINUS, - mkcon(1.0), - mkb(PT_POWER, - p->left, - mkcon(2.0))))); - break; + case PTF_ASIN: /* 1 / sqrt(1 - u^2) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, + mkb(PT_MINUS, + mkcon(1.0), + mkb(PT_POWER, + p->left, + mkcon(2.0))))); + break; - case PTF_ASINH: /* 1 / sqrt(u^2 + 1) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, - mkb(PT_PLUS, - mkb(PT_POWER, - p->left, - mkcon(2.0)), - mkcon(1.0)))); - break; + case PTF_ASINH: /* 1 / sqrt(u^2 + 1) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkf(PTF_SQRT, + mkb(PT_PLUS, + mkb(PT_POWER, + p->left, + mkcon(2.0)), + mkcon(1.0)))); + break; - case PTF_ATAN: /* 1 / (1 + u^2) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_PLUS, - mkb(PT_POWER, - p->left, - mkcon(2.0)), - mkcon(1.0))); - break; + case PTF_ATAN: /* 1 / (1 + u^2) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_PLUS, + mkb(PT_POWER, + p->left, + mkcon(2.0)), + mkcon(1.0))); + break; - case PTF_ATANH: /* 1 / (1 - u^2) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_MINUS, - mkcon(1.0), - mkb(PT_POWER, - p->left, - mkcon(2.0)))); - break; + case PTF_ATANH: /* 1 / (1 - u^2) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_MINUS, + mkcon(1.0), + mkb(PT_POWER, + p->left, + mkcon(2.0)))); + break; - case PTF_COS: /* - sin(u) */ - arg1 = mkf(PTF_UMINUS, mkf(PTF_SIN, p->left)); - break; + case PTF_COS: /* - sin(u) */ + arg1 = mkf(PTF_UMINUS, mkf(PTF_SIN, p->left)); + break; - case PTF_COSH: /* sinh(u) */ - arg1 = mkf(PTF_SINH, p->left); - break; + case PTF_COSH: /* sinh(u) */ + arg1 = mkf(PTF_SINH, p->left); + break; - case PTF_EXP: /* exp(u) */ - arg1 = mkf(PTF_EXP, p->left); - break; + case PTF_EXP: /* exp(u) */ + arg1 = mkf(PTF_EXP, p->left); + break; - case PTF_LN: /* 1 / u */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), p->left); - break; + case PTF_LN: /* 1 / u */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), p->left); + break; - case PTF_LOG: /* log(e) / u */ - arg1 = mkb(PT_DIVIDE, mkcon(M_LOG10E), p->left); - break; + case PTF_LOG: /* log(e) / u */ + arg1 = mkb(PT_DIVIDE, mkcon(M_LOG10E), p->left); + break; - case PTF_SIN: /* cos(u) */ - arg1 = mkf(PTF_COS, p->left); - break; + case PTF_SIN: /* cos(u) */ + arg1 = mkf(PTF_COS, p->left); + break; - case PTF_SINH: /* cosh(u) */ - arg1 = mkf(PTF_COSH, p->left); - break; + case PTF_SINH: /* cosh(u) */ + arg1 = mkf(PTF_COSH, p->left); + break; - case PTF_SQRT: /* 1 / (2 * sqrt(u)) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_TIMES, - mkcon(2.0), - mkf(PTF_SQRT, - p->left))); - break; + case PTF_SQRT: /* 1 / (2 * sqrt(u)) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_TIMES, + mkcon(2.0), + mkf(PTF_SQRT, + p->left))); + break; - case PTF_TAN: /* 1 / (cos(u) ^ 2) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_POWER, - mkf(PTF_COS, - p->left), - mkcon(2.0))); - break; + case PTF_TAN: /* 1 / (cos(u) ^ 2) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_POWER, + mkf(PTF_COS, + p->left), + mkcon(2.0))); + break; - case PTF_TANH: /* 1 / (cosh(u) ^ 2) */ - arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_POWER, - mkf(PTF_COSH, - p->left), - mkcon(2.0))); - break; + case PTF_TANH: /* 1 / (cosh(u) ^ 2) */ + arg1 = mkb(PT_DIVIDE, mkcon(1.0), mkb(PT_POWER, + mkf(PTF_COSH, + p->left), + mkcon(2.0))); + break; - case PTF_USTEP: - case PTF_EQ0: - case PTF_NE0: - case PTF_GT0: - case PTF_LT0: - case PTF_GE0: - case PTF_LE0: - arg1 = mkcon(0.0); - break; + case PTF_USTEP: + case PTF_EQ0: + case PTF_NE0: + case PTF_GT0: + case PTF_LT0: + case PTF_GE0: + case PTF_LE0: + arg1 = mkcon(0.0); + break; - case PTF_URAMP: - arg1 = mkf(PTF_USTEP, p->left); - break; + case PTF_URAMP: + arg1 = mkf(PTF_USTEP, p->left); + break; - case PTF_FLOOR: /* naive: D(floor(u)) = 0 */ - arg1 = mkcon(0.0); - break; + case PTF_FLOOR: /* naive: D(floor(u)) = 0 */ + arg1 = mkcon(0.0); + break; - case PTF_CEIL: /* naive: D(ceil(u)) = 0 */ - arg1 = mkcon(0.0); - break; + case PTF_CEIL: /* naive: D(ceil(u)) = 0 */ + arg1 = mkcon(0.0); + break; - /* MW. PTF_CIF for new cif function */ - case PTF_USTEP2: /* ustep2=uramp(x)-uramp(x-1) ustep2'=ustep(x)-ustep(x-1) */ + /* MW. PTF_CIF for new cif function */ + case PTF_USTEP2: /* ustep2=uramp(x)-uramp(x-1) ustep2'=ustep(x)-ustep(x-1) */ arg1 = mkb(PT_MINUS, mkf(PTF_USTEP, p->left), mkf(PTF_USTEP, mkb(PT_MINUS, p->left, mkcon(1.0)))); - break; - + break; + case PTF_UMINUS: /* - 1 ; like a constant (was 0 !) */ arg1 = mkcon(-1.0); break; @@ -513,8 +515,8 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) arg1 = mkcon(0.0); break; - case PTF_MIN: - case PTF_MAX: + case PTF_MIN: + case PTF_MAX: /* min(a,b) --> (a ((a-b) < 0) ? a : b */ @@ -523,8 +525,6 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) INPparseNode *b = p->left->right; int comparison = (p->funcnum == PTF_MIN) ? PTF_LT0 : PTF_GT0; #ifdef TRACE - extern void printTree(INPparseNode *); - printf("debug: %s, PTF_MIN: ", __func__); printTree(p); printf("\n"); @@ -554,55 +554,133 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) { /* pow(a,b) - p->left: ',' p->left->left: a p->left->right: b + p->left: ',' p->left->left: a p->left->right: b */ if (p->left->right->type == PT_CONSTANT) { - /* - * D(f^C) = C * f^(C-1) * D(f) - */ + /* + * D(f^C) = C * f^(C-1) * D(f) + */ arg1 = PTdifferentiate(p->left->left, varnum); newp = mkb(PT_TIMES, mkb(PT_TIMES, - mkcon(p->left->right->constant), - mkb(PT_POWER, p->left->left, - mkcon(p->left->right->constant - 1))), - arg1); + mkcon(p->left->right->constant), + mkb(PT_POWER, p->left->left, + mkcon(p->left->right->constant - 1))), + arg1); +#ifdef TRACE + printf("pow, %s, returns; ", __func__); + printTree(newp); + printf("\n"); +#endif } else { - /* - * D(f^g) = D(exp(g*ln(f))) - * = exp(g*ln(f)) * D(g*ln(f)) - * = exp(g*ln(f)) * (D(g)*ln(f) + g*D(f)/f) - */ + /* + * D(f^g) = D(exp(g*ln(f))) + * = exp(g*ln(f)) * D(g*ln(f)) + * = exp(g*ln(f)) * (D(g)*ln(f) + g*D(f)/f) + */ arg1 = PTdifferentiate(p->left->left, varnum); arg2 = PTdifferentiate(p->left->right, varnum); newp = mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES, - p->left->right, mkf(PTF_LN, - p->left->left))), - mkb(PT_PLUS, - mkb(PT_TIMES, p->left->right, - mkb(PT_DIVIDE, arg1, p->left->left)), - mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left->left)))); + p->left->right, mkf(PTF_LN, + p->left->left))), + mkb(PT_PLUS, + mkb(PT_TIMES, p->left->right, + mkb(PT_DIVIDE, arg1, p->left->left)), + mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left->left)))); } return mkfirst(newp, p); } - default: - fprintf(stderr, "Internal Error: bad function # %d\n", - p->funcnum); - return mkfirst(NULL, p); - } + break; - arg2 = PTdifferentiate(p->left, varnum); + case PTF_PWR: + { + /* + pwr(a,b) + p->left: ',' p->left->left: a p->left->right: b + */ +#define a p->left->left +#define b p->left->right + if (b->type == PT_CONSTANT) { + /* b is a constant + * + * f(a,b) = signum(a) * abs(a)^b + * = signum(a) * exp(b*ln(abs(a))) + * D(f) = signum(a) * D(exp(b*ln(abs(a)))) + * = signum(a) * exp(b*ln(abs(a))) * D(b*ln(abs(a))) + * = signum(a) * abs(a)^b * D(b*ln(abs(a))) + * = signum(a) * abs(a)^b * b * 1/abs(a) * D(abs(a)) + * = signum(a) * abs(a)^(b-1) * b * D(abs(a)) + * = signum(a) * abs(a)^(b-1) * b * signum(a) * D(a) + * = abs(a)^(b-1) * b * D(a) + */ + arg1 = PTdifferentiate(a, varnum); - newp = mkb(PT_TIMES, arg1, arg2); + newp = mkb(PT_TIMES, + mkb(PT_TIMES, + mkcon(b->constant), + mkb(PT_POWER, + mkf(PTF_ABS, a), + mkcon(b->constant - 1.0))), + arg1); +#ifdef TRACE + printf("pwr, %s, returns; ", __func__); + printTree(newp); + printf("\n"); +#endif + } else { + /* b is a function + * + * f(a,b) = signum(a) * abs(a)^b + * = signum(a) * exp(b*ln(abs(a))) + * D(f) = signum(a) * D(exp(b*ln(abs(a)))) + * = signum(a) * exp(b*ln(abs(a))) * D(b*ln(abs(a))) + * = signum(a) * exp(b*ln(abs(a))) * (D(b) * ln(abs(a)) + b * D(ln(abs(a)))) + * = signum(a) * exp(b*ln(abs(a))) * (D(b) * ln(abs(a)) + b * 1/abs(a) * D(abs(a))) + * = signum(a) * exp(b*ln(abs(a))) * (D(b) * ln(abs(a)) + b * 1/abs(a) * signum(a)*D(a)) + * = signum(a) * exp(b*ln(abs(a))) * (D(b) * ln(abs(a)) + b/a*D(a)) + * = signum(a) * exp(b*ln(abs(a))) * D(b) * ln(abs(a) + signum(a) * exp(b*ln(abs(a))) / a * b * D(a) + * = signum(a) * exp(b*ln(abs(a))) * D(b) * ln(abs(a) + abs(a)^(b-1) * b * D(a) + */ + arg1 = PTdifferentiate(a, varnum); + arg2 = PTdifferentiate(b, varnum); + newp = mkb(PT_PLUS, + mkb(PT_TIMES, + mkf(PTF_SGN, a), + mkb(PT_TIMES, + mkb(PT_POWER, mkf(PTF_ABS, a), b), + mkb(PT_TIMES, arg2, + mkf(PTF_LN, mkf(PTF_ABS, a))))), + mkb(PT_TIMES, + mkb(PT_TIMES, + mkb(PT_POWER, + mkf(PTF_ABS, a), + mkb(PT_MINUS, b, mkcon(1.0))), + b), + arg1)); + } + return mkfirst(newp, p); +#undef b +#undef a + } - break; + default: + fprintf(stderr, "Internal Error: bad function # %d\n", + p->funcnum); + return mkfirst(NULL, p); + } + + arg2 = PTdifferentiate(p->left, varnum); + + newp = mkb(PT_TIMES, arg1, arg2); + + break; default: - fprintf(stderr, "Internal error: bad node type %d\n", p->type); - newp = NULL; - break; + fprintf(stderr, "Internal error: bad node type %d\n", p->type); + newp = NULL; + break; } return mkfirst(newp, p); @@ -620,90 +698,90 @@ static INPparseNode *mkcon(double value) } static INPparseNode *mkb(int type, INPparseNode * left, - INPparseNode * right) + INPparseNode * right) { INPparseNode *p; int i; if ((right->type == PT_CONSTANT) && (left->type == PT_CONSTANT)) { - double value; - switch (type) { - case PT_TIMES: - value = left->constant * right->constant; - return mkfirst(mkcon(value), mkfirst(left, right)); + double value; + switch (type) { + case PT_TIMES: + value = left->constant * right->constant; + return mkfirst(mkcon(value), mkfirst(left, right)); - case PT_DIVIDE: - value = left->constant / right->constant; - return mkfirst(mkcon(value), mkfirst(left, right)); + case PT_DIVIDE: + value = left->constant / right->constant; + return mkfirst(mkcon(value), mkfirst(left, right)); - case PT_PLUS: - value = left->constant + right->constant; - return mkfirst(mkcon(value), mkfirst(left, right)); + case PT_PLUS: + value = left->constant + right->constant; + return mkfirst(mkcon(value), mkfirst(left, right)); - case PT_MINUS: - value = left->constant - right->constant; - return mkfirst(mkcon(value), mkfirst(left, right)); + case PT_MINUS: + value = left->constant - right->constant; + return mkfirst(mkcon(value), mkfirst(left, right)); - case PT_POWER: - value = pow(left->constant, right->constant); - return mkfirst(mkcon(value), mkfirst(left, right)); - } + case PT_POWER: + value = pow(left->constant, right->constant); + return mkfirst(mkcon(value), mkfirst(left, right)); + } } switch (type) { case PT_TIMES: - if ((left->type == PT_CONSTANT) && (left->constant == 0)) - return mkfirst(left, right); - else if ((right->type == PT_CONSTANT) && (right->constant == 0)) - return mkfirst(right, left); - else if ((left->type == PT_CONSTANT) && (left->constant == 1)) - return mkfirst(right, left); - else if ((right->type == PT_CONSTANT) && (right->constant == 1)) - return mkfirst(left, right); - break; + if ((left->type == PT_CONSTANT) && (left->constant == 0)) + return mkfirst(left, right); + else if ((right->type == PT_CONSTANT) && (right->constant == 0)) + return mkfirst(right, left); + else if ((left->type == PT_CONSTANT) && (left->constant == 1)) + return mkfirst(right, left); + else if ((right->type == PT_CONSTANT) && (right->constant == 1)) + return mkfirst(left, right); + break; case PT_DIVIDE: - if ((left->type == PT_CONSTANT) && (left->constant == 0)) - return mkfirst(left, right); - else if ((right->type == PT_CONSTANT) && (right->constant == 1)) - return mkfirst(left, right); - break; + if ((left->type == PT_CONSTANT) && (left->constant == 0)) + return mkfirst(left, right); + else if ((right->type == PT_CONSTANT) && (right->constant == 1)) + return mkfirst(left, right); + break; case PT_PLUS: - if ((left->type == PT_CONSTANT) && (left->constant == 0)) - return mkfirst(right, left); - else if ((right->type == PT_CONSTANT) && (right->constant == 0)) - return mkfirst(left, right); - break; + if ((left->type == PT_CONSTANT) && (left->constant == 0)) + return mkfirst(right, left); + else if ((right->type == PT_CONSTANT) && (right->constant == 0)) + return mkfirst(left, right); + break; case PT_MINUS: - if ((right->type == PT_CONSTANT) && (right->constant == 0)) - return mkfirst(left, right); - else if ((left->type == PT_CONSTANT) && (left->constant == 0)) - return mkfirst(mkf(PTF_UMINUS, right), left); - break; + if ((right->type == PT_CONSTANT) && (right->constant == 0)) + return mkfirst(left, right); + else if ((left->type == PT_CONSTANT) && (left->constant == 0)) + return mkfirst(mkf(PTF_UMINUS, right), left); + break; case PT_POWER: - if (right->type == PT_CONSTANT) { - if (right->constant == 0) - return mkfirst(mkcon(1.0), mkfirst(left, right)); - else if (right->constant == 1) - return mkfirst(left, right); - } - break; + if (right->type == PT_CONSTANT) { + if (right->constant == 0) + return mkfirst(mkcon(1.0), mkfirst(left, right)); + else if (right->constant == 1) + return mkfirst(left, right); + } + break; case PT_TERN: - if (left->type == PT_CONSTANT) { - /*FIXME > 0.0, >= 0.5, != 0.0 or what ? */ - p = (left->constant != 0.0) ? right->left : right->right; - return mkfirst(p, mkfirst(right, left)); - } - if((right->left->type == PT_CONSTANT) && - (right->right->type == PT_CONSTANT) && - (right->left->constant == right->right->constant)) - return mkfirst(right->left, mkfirst(right, left)); - break; + if (left->type == PT_CONSTANT) { + /*FIXME > 0.0, >= 0.5, != 0.0 or what ? */ + p = (left->constant != 0.0) ? right->left : right->right; + return mkfirst(p, mkfirst(right, left)); + } + if((right->left->type == PT_CONSTANT) && + (right->right->type == PT_CONSTANT) && + (right->left->constant == right->right->constant)) + return mkfirst(right->left, mkfirst(right, left)); + break; } - + p = TMALLOC(INPparseNode, 1); p->type = type; @@ -711,20 +789,20 @@ static INPparseNode *mkb(int type, INPparseNode * left, p->left = inc_usage(left); p->right = inc_usage(right); - + if(type == PT_TERN) { - p->function = NULL; - p->funcname = NULL; - return (p); + p->function = NULL; + p->funcname = NULL; + return (p); } for (i = 0; i < NUM_OPS; i++) - if (ops[i].number == type) - break; + if (ops[i].number == type) + break; if (i == NUM_OPS) { - fprintf(stderr, "Internal Error: bad type %d\n", type); - return (NULL); + fprintf(stderr, "Internal Error: bad type %d\n", type); + return (NULL); } p->function = ops[i].funcptr; p->funcname = ops[i].name; @@ -738,16 +816,16 @@ static INPparseNode *mkf(int type, INPparseNode * arg) int i; for (i = 0; i < NUM_FUNCS; i++) - if (funcs[i].number == type) - break; + if (funcs[i].number == type) + break; if (i == NUM_FUNCS) { - fprintf(stderr, "Internal Error: bad type %d\n", type); - return (NULL); + fprintf(stderr, "Internal Error: bad type %d\n", type); + return (NULL); } if (arg->type == PT_CONSTANT) { - double constval = PTunary(funcs[i].funcptr) (arg->constant); - return mkfirst(mkcon(constval), arg); + double constval = PTunary(funcs[i].funcptr) (arg->constant); + return mkfirst(mkcon(constval), arg); } p = TMALLOC(INPparseNode, 1); @@ -772,17 +850,17 @@ static int PTcheck(INPparseNode * p) { switch (p->type) { case PT_PLACEHOLDER: - return (0); + return (0); case PT_TIME: case PT_TEMPERATURE: case PT_FREQUENCY: case PT_CONSTANT: case PT_VAR: - return (1); + return (1); case PT_FUNCTION: - return (PTcheck(p->left)); + return (PTcheck(p->left)); case PT_PLUS: case PT_MINUS: @@ -790,31 +868,31 @@ static int PTcheck(INPparseNode * p) case PT_DIVIDE: case PT_POWER: case PT_COMMA: - return (PTcheck(p->left) && PTcheck(p->right)); + return (PTcheck(p->left) && PTcheck(p->right)); case PT_TERN: - return (PTcheck(p->left) && PTcheck(p->right->left) && PTcheck(p->right->right)); + return (PTcheck(p->left) && PTcheck(p->right->left) && PTcheck(p->right->right)); default: - fprintf(stderr, "Internal error: bad node type %d\n", p->type); - return (0); + fprintf(stderr, "Internal error: bad node type %d\n", p->type); + return (0); } } /* Binop node. */ static INPparseNode *mkbnode(const char *opstr, INPparseNode * arg1, - INPparseNode * arg2) + INPparseNode * arg2) { INPparseNode *p; int i; for (i = 0; i < NUM_OPS; i++) - if (!strcmp(ops[i].name, opstr)) - break; + if (!strcmp(ops[i].name, opstr)) + break; if (i == NUM_OPS) { - fprintf(stderr, "Internal Error: no such op num %s\n", opstr); - return mkfirst(NULL, mkfirst(arg1, arg2)); + fprintf(stderr, "Internal Error: no such op num %s\n", opstr); + return mkfirst(NULL, mkfirst(arg1, arg2)); } p = TMALLOC(INPparseNode, 1); @@ -931,25 +1009,25 @@ static INPparseNode *mkfnode(const char *fname, INPparseNode * arg) if(!strcmp("ternary_fcn", buf)) { - if(arg->type == PT_COMMA && arg->left->type == PT_COMMA) { + if(arg->type == PT_COMMA && arg->left->type == PT_COMMA) { - INPparseNode *arg1 = arg->left->left; - INPparseNode *arg2 = arg->left->right; - INPparseNode *arg3 = arg->right; + INPparseNode *arg1 = arg->left->left; + INPparseNode *arg2 = arg->left->right; + INPparseNode *arg3 = arg->right; - p = TMALLOC(INPparseNode, 1); + p = TMALLOC(INPparseNode, 1); - p->type = PT_TERN; - p->usecnt = 0; + p->type = PT_TERN; + p->usecnt = 0; - p->left = inc_usage(arg1); - p->right = inc_usage(mkb(PT_COMMA, arg2, arg3)); + p->left = inc_usage(arg1); + p->right = inc_usage(mkb(PT_COMMA, arg2, arg3)); - return mkfirst(p, arg); - } + return mkfirst(p, arg); + } - fprintf(stderr, "Error: bogus ternary_fcn form\n"); - return mkfirst(NULL, arg); + fprintf(stderr, "Error: bogus ternary_fcn form\n"); + return mkfirst(NULL, arg); } for (i = 0; i < NUM_FUNCS; i++) @@ -1089,41 +1167,41 @@ static INPparseNode *mksnode(const char *string, void *ckt) /* First see if it's something special. */ for (i = 0; i < ft_sim->numSpecSigs; i++) - if (!strcmp(ft_sim->specSigs[i], buf)) - break; + if (!strcmp(ft_sim->specSigs[i], buf)) + break; if (i < ft_sim->numSpecSigs) { - for (j = 0; j < numvalues; j++) - if ((types[j] == IF_STRING) && !strcmp(buf, values[i].sValue)) - break; - if (j == numvalues) { - if (numvalues) { - values = TREALLOC(IFvalue, values, numvalues + 1); - types = TREALLOC(int, types, numvalues + 1); - } else { - values = TMALLOC(IFvalue, 1); - types = TMALLOC(int, 1); - } - values[i].sValue = TMALLOC(char, strlen(buf) + 1); - strcpy(values[i].sValue, buf); - types[i] = IF_STRING; - numvalues++; - } - p->valueIndex = i; - p->type = PT_VAR; - return (p); + for (j = 0; j < numvalues; j++) + if ((types[j] == IF_STRING) && !strcmp(buf, values[i].sValue)) + break; + if (j == numvalues) { + if (numvalues) { + values = TREALLOC(IFvalue, values, numvalues + 1); + types = TREALLOC(int, types, numvalues + 1); + } else { + values = TMALLOC(IFvalue, 1); + types = TMALLOC(int, 1); + } + values[i].sValue = TMALLOC(char, strlen(buf) + 1); + strcpy(values[i].sValue, buf); + types[i] = IF_STRING; + numvalues++; + } + p->valueIndex = i; + p->type = PT_VAR; + return (p); } for (i = 0; i < NUM_CONSTANTS; i++) - if (!strcmp(constants[i].name, buf)) - break; + if (!strcmp(constants[i].name, buf)) + break; if (i == NUM_CONSTANTS) { - /* We'd better save this in case it's part of i(something). */ - p->type = PT_PLACEHOLDER; - p->funcname = copy(string); + /* We'd better save this in case it's part of i(something). */ + p->type = PT_PLACEHOLDER; + p->funcname = copy(string); } else { - p->type = PT_CONSTANT; - p->constant = constants[i].value; + p->type = PT_CONSTANT; + p->constant = constants[i].value; } return (p); @@ -1141,18 +1219,18 @@ int PTlex (YYSTYPE *lvalp, struct PTltype *llocp, char **line) sbuf = *line; #ifdef TRACE -// printf("entering lexer, sbuf = '%s', lastoken = %d, lasttype = %d\n", +// printf("entering lexer, sbuf = '%s', lastoken = %d, lasttype = %d\n", // sbuf, lasttoken, lasttype); #endif while ((*sbuf == ' ') || (*sbuf == '\t')) - sbuf++; + sbuf++; llocp->start = sbuf; switch (*sbuf) { case '\0': - token = 0; - break; + token = 0; + break; case '?': case ':': @@ -1163,8 +1241,8 @@ int PTlex (YYSTYPE *lvalp, struct PTltype *llocp, char **line) case '^': case '(': case ')': - token = *sbuf++; - break; + token = *sbuf++; + break; case '*': if(sbuf[1] == '*') { @@ -1291,28 +1369,28 @@ int PTlex (YYSTYPE *lvalp, struct PTltype *llocp, char **line) } } - td = INPevaluate(&sbuf, &err, 1); - if (err == OK) { - token = TOK_NUM; - lvalp->num = td; - } else { + td = INPevaluate(&sbuf, &err, 1); + if (err == OK) { + token = TOK_NUM; + lvalp->num = td; + } else { char *tmp; - token = TOK_STR; - for (s = sbuf; *s; s++) - if (strchr(specials, *s)) - break; - tmp = TMALLOC(char, s - sbuf + 1); - strncpy(tmp, sbuf, (size_t) (s - sbuf)); - tmp[s - sbuf] = '\0'; - lvalp->str = tmp; - sbuf = s; - } + token = TOK_STR; + for (s = sbuf; *s; s++) + if (strchr(specials, *s)) + break; + tmp = TMALLOC(char, s - sbuf + 1); + strncpy(tmp, sbuf, (size_t) (s - sbuf)); + tmp[s - sbuf] = '\0'; + lvalp->str = tmp; + sbuf = s; + } } *line = sbuf; #ifdef TRACE -// printf("PTlexer: token = %d, type = %d, left = '%s'\n", +// printf("PTlexer: token = %d, type = %d, left = '%s'\n", // el.token, el.type, sbuf); */ #endif llocp->stop = sbuf; @@ -1327,7 +1405,7 @@ void INPfreeTree(IFparseTree *ptree) int i; for (i = 0; i < pt->p.numVars; i++) - dec_usage(pt->derivs[i]); + dec_usage(pt->derivs[i]); dec_usage(pt->tree); @@ -1354,7 +1432,7 @@ void free_tree(INPparseNode *pt) case PT_FREQUENCY: case PT_CONSTANT: case PT_VAR: - break; + break; case PT_PLUS: case PT_MINUS: @@ -1363,14 +1441,14 @@ void free_tree(INPparseNode *pt) case PT_POWER: case PT_COMMA: case PT_TERN: - dec_usage(pt->right); + dec_usage(pt->right); case PT_FUNCTION: - dec_usage(pt->left); - break; + dec_usage(pt->left); + break; default: - printf("oops"); - break; + printf("oops"); + break; } if(pt->type == PT_FUNCTION && pt->funcnum == PTF_PWL) { @@ -1387,8 +1465,6 @@ void free_tree(INPparseNode *pt) /* Debugging stuff. */ -void printTree(INPparseNode *); - void INPptPrint(char *str, IFparseTree * ptree) { int i; @@ -1397,9 +1473,9 @@ void INPptPrint(char *str, IFparseTree * ptree) printTree(((INPparseTree *) ptree)->tree); printf("\n"); for (i = 0; i < ptree->numVars; i++) { - printf("d / d v%d : ", i); - printTree(((INPparseTree *) ptree)->derivs[i]); - printf("\n"); + printf("d / d v%d : ", i); + printTree(((INPparseTree *) ptree)->derivs[i]); + printf("\n"); } return; } @@ -1409,90 +1485,89 @@ void printTree(INPparseNode * pt) switch (pt->type) { case PT_TIME: printf("time(ckt = %p)", pt->data); - break; + break; case PT_TEMPERATURE: printf("temperature(ckt = %p)", pt->data); - break; + break; case PT_FREQUENCY: printf("frequency(ckt = %p)", pt->data); - break; + break; case PT_CONSTANT: - printf("%g", pt->constant); - break; + printf("%g", pt->constant); + break; case PT_VAR: - printf("v%d", pt->valueIndex); - break; + printf("v%d", pt->valueIndex); + break; case PT_PLUS: - printf("("); - printTree(pt->left); - printf(") + ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") + ("); + printTree(pt->right); + printf(")"); + break; case PT_MINUS: - printf("("); - printTree(pt->left); - printf(") - ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") - ("); + printTree(pt->right); + printf(")"); + break; case PT_TIMES: - printf("("); - printTree(pt->left); - printf(") * ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") * ("); + printTree(pt->right); + printf(")"); + break; case PT_DIVIDE: - printf("("); - printTree(pt->left); - printf(") / ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") / ("); + printTree(pt->right); + printf(")"); + break; case PT_POWER: - printf("("); - printTree(pt->left); - printf(") ^ ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") ^ ("); + printTree(pt->right); + printf(")"); + break; - case PT_COMMA: - printf("("); - printTree(pt->left); - printf(") , ("); - printTree(pt->right); - printf(")"); - break; + printf("("); + printTree(pt->left); + printf(") , ("); + printTree(pt->right); + printf(")"); + break; case PT_FUNCTION: - printf("%s (", pt->funcname); - printTree(pt->left); - printf(")"); - break; - + printf("%s (", pt->funcname); + printTree(pt->left); + printf(")"); + break; + case PT_TERN: - printf("ternary_fcn ("); - printTree(pt->left); - printf(") , ("); - printTree(pt->right); - printf(")"); - break; + printf("ternary_fcn ("); + printTree(pt->left); + printf(") , ("); + printTree(pt->right); + printf(")"); + break; default: - printf("oops"); - break; + printf("oops"); + break; } return; } diff --git a/src/spicelib/parser/inpsymt.c b/src/spicelib/parser/inpsymt.c index c56f0779d..d77b23265 100644 --- a/src/spicelib/parser/inpsymt.c +++ b/src/spicelib/parser/inpsymt.c @@ -273,10 +273,11 @@ void INPtabEnd(INPtables * tab) static int hash(char *name, int tsize) { - char *s; - register int i = 0; + unsigned int hash = 5381; + char c; - for (s = name; *s; s++) - i += *s; - return (i % tsize); + while ((c = *name++) != '\0') + hash = (hash * 33) ^ (unsigned) c; + + return (int) (hash % (unsigned) tsize); } diff --git a/src/spicelib/parser/inpxx.h b/src/spicelib/parser/inpxx.h index 1a26ed4a1..491e3b42c 100644 --- a/src/spicelib/parser/inpxx.h +++ b/src/spicelib/parser/inpxx.h @@ -43,6 +43,7 @@ double PTminus(double arg1, double arg2); double PTtimes(double arg1, double arg2); double PTdivide(double arg1, double arg2); double PTpower(double arg1, double arg2); +double PTpwr(double arg1, double arg2); double PTacos(double arg); double PTacosh(double arg); double PTasin(double arg); diff --git a/src/spicelib/parser/ptfuncs.c b/src/spicelib/parser/ptfuncs.c index 5ae64ae4c..2eef347c1 100644 --- a/src/spicelib/parser/ptfuncs.c +++ b/src/spicelib/parser/ptfuncs.c @@ -1,6 +1,6 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group +Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ /* @@ -20,11 +20,11 @@ Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group #ifndef HAVE_ATANH extern double asinh(), acosh(), atanh(); -#endif +#endif double PTfudge_factor; -#define MODULUS(NUM,LIMIT) ((NUM) - ((int) ((NUM) / (LIMIT))) * (LIMIT)) +#define MODULUS(NUM,LIMIT) ((NUM) - ((int) ((NUM) / (LIMIT))) * (LIMIT)) double PTabs(double arg) @@ -56,13 +56,13 @@ PTtimes(double arg1, double arg2) return (arg1 * arg2); } -double +double PTdivide(double arg1, double arg2) { if (arg2 >= 0.0) - arg2 += PTfudge_factor; + arg2 += PTfudge_factor; else - arg2 -= PTfudge_factor; + arg2 -= PTfudge_factor; if (arg2 == 0.0) return (HUGE); @@ -74,15 +74,24 @@ double PTpower(double arg1, double arg2) { if (arg1 < 0.0) { - if (fabs(arg2 - ((int) arg2)) / (arg2 + 0.001) < 0.000001) { - arg2 = (int) arg2; - } else { - arg1 = -arg1; - } + if (fabs(arg2 - ((int) arg2)) / (arg2 + 0.001) < 0.000001) { + arg2 = (int) arg2; + } else { + arg1 = -arg1; + } } return (pow(arg1, arg2)); } +double +PTpwr(double arg1, double arg2) +{ + if (arg1 < 0.0) + return (-pow(-arg1, arg2)); + else + return (pow(arg1, arg2)); +} + double PTmin(double arg1, double arg2) { @@ -108,9 +117,9 @@ PTacosh(double arg) return (acosh(arg)); #else if (arg < 1.0) - arg = 1.0; + arg = 1.0; return (log(arg + sqrt(arg*arg-1.0))); -#endif +#endif } double @@ -126,7 +135,7 @@ PTasinh(double arg) return (asinh(arg)); #else return log(arg + sqrt(arg * arg + 1.0)); -#endif +#endif } double @@ -142,22 +151,22 @@ PTatanh(double arg) return (atanh(arg)); #else if (arg < -1.0) - arg = -1.0 + PTfudge_factor + 1e-10; + arg = -1.0 + PTfudge_factor + 1e-10; else if (arg > 1.0) - arg = 1.0 - PTfudge_factor - 1e-10; + arg = 1.0 - PTfudge_factor - 1e-10; return (log((1.0 + arg) / (1.0 - arg)) / 2.0); -#endif +#endif } double PTustep(double arg) { if (arg < 0.0) - return 0.0; + return 0.0; else if (arg > 0.0) - return 1.0; + return 1.0; else - return 0.5; /* Ick! */ + return 0.5; /* Ick! */ } /* MW. PTcif is like "C" if - 0 for (arg<=0), 1 elsewhere */ @@ -165,12 +174,12 @@ PTustep(double arg) double PTustep2(double arg) { - if (arg <= 0.0) - return 0.0; + if (arg <= 0.0) + return 0.0; else if (arg <= 1.0) - return arg; + return arg; else /* if (arg > 1.0) */ - return 1.0; + return 1.0; } double @@ -213,9 +222,9 @@ double PTuramp(double arg) { if (arg < 0.0) - return 0.0; + return 0.0; else - return arg; + return arg; } double diff --git a/src/tclspice.c b/src/tclspice.c index 4c3201c55..a5b323c2e 100644 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -1394,7 +1394,7 @@ get_mod_param TCL_CMDPROCARGS(clientData, interp, argc, argv) /* get the unique IFuid for name (device/model) */ INPretrieve(&name, ft_curckt->ci_symtab); - err = ft_sim->findInstance (ft_curckt->ci_ckt, &typecode, &devptr, name, NULL, NULL); + err = ft_sim->findInstance (ft_curckt->ci_ckt, &typecode, &devptr, name, NULL); if (err != OK) { typecode = -1; devptr = NULL; diff --git a/src/unsupported/Makefile.am b/src/unsupported/Makefile.am new file mode 100644 index 000000000..1c9ca4c06 --- /dev/null +++ b/src/unsupported/Makefile.am @@ -0,0 +1,21 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libunsupported.la + +libunsupported_la_SOURCES = \ + cktsenac.c \ + cktsenup.c \ + cktsncom.c \ + cktsndct.c \ + cktsnset.c \ + cktsnld.c \ + cktsnprt.c \ + sen2dest.c \ + sen2setp.c \ + snaskq.c \ + snstart.c + + +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include +AM_CFLAGS = $(STATIC) +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/unsupported/cktsenac.c b/src/unsupported/cktsenac.c index 07b18e71a..dd7d5a618 100644 --- a/src/unsupported/cktsenac.c +++ b/src/unsupported/cktsenac.c @@ -2,10 +2,8 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -20,28 +18,29 @@ Author: 1985 Thomas L. Quarles */ int -CKTsenAC(ckt) -register CKTcircuit *ckt; +CKTsenAC(CKTcircuit *ckt) { int error; #ifdef SENSDEBUG printf("CKTsenAC\n"); -#endif /* SENSDEBUG */ +#endif - - if(error = CKTsenLoad(ckt)) return(error); + error = CKTsenLoad(ckt); + if (error) + return error; #ifdef SENSDEBUG printf("after CKTsenLoad\n"); -#endif /* SENSDEBUG */ +#endif - if(error = CKTsenComp(ckt)) return(error); + error = CKTsenComp(ckt); + if (error) + return error; #ifdef SENSDEBUG printf("after CKTsenComp\n"); -#endif /* SENSDEBUG */ +#endif - return(OK); + return OK; } - diff --git a/src/unsupported/cktsenup.c b/src/unsupported/cktsenup.c index 830370f4c..0ce1acfbd 100644 --- a/src/unsupported/cktsenup.c +++ b/src/unsupported/cktsenup.c @@ -2,16 +2,14 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ /* CKTsenUpdate(ckt) * this is a driver program to iterate through all the various - * sensitivity update functions provided for the circuit elements - * in the given circuit + * sensitivity update functions provided for the circuit elements + * in the given circuit */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -22,18 +20,17 @@ Author: 1985 Thomas L. Quarles int -CKTsenUpdate(ckt) -register CKTcircuit *ckt; +CKTsenUpdate(CKTcircuit *ckt) { - register int i; + int i; int error; - - for (i=0;iDEVsenUpdate && ckt->CKThead[i] ) { + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVsenUpdate && ckt->CKThead[i]) { error = DEVices[i]->DEVsenUpdate (ckt->CKThead[i], ckt); - if(error) return(error); + if (error) + return error; } - } - return(OK); + + return OK; } diff --git a/src/unsupported/cktsncom.c b/src/unsupported/cktsncom.c index 619b31f40..ec18e13c1 100644 --- a/src/unsupported/cktsncom.c +++ b/src/unsupported/cktsncom.c @@ -2,15 +2,13 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ /* CKTsenComp(ckt) - * this is a program to solve the sensitivity equation - * of the given circuit + * this is a program to solve the sensitivity equation + * of the given circuit */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -19,151 +17,165 @@ Author: 1985 Thomas L. Quarles #include "ngspice/trandefs.h" #include "ngspice/suffix.h" +// #include "../maths/sparse/spdefs.h" +// +// this include file from `sparse' is incompatible +// with the rest of ngspice +// so we can unfortunatly not include here +// instead we cheat a bit and +// introduce the opaque struct MatrixElement here +// (only the first struct members which are of importance to us) + +struct MatrixElement +{ + double Real; + double Imag; + // ... +}; int -CKTsenComp(ckt) -register CKTcircuit *ckt; +CKTsenComp(CKTcircuit *ckt) { - register int size; + int size; int row; int col; SENstruct *info; + #ifdef SENSDEBUG char *rowe; SMPelement *elt; -#endif /* SENSDEBUG */ +#endif #ifdef SENSDEBUG printf("CKTsenComp\n"); -#endif /* SENSDEBUG */ +#endif size = SMPmatSize(ckt->CKTmatrix); info = ckt->CKTsenInfo; - if((info->SENmode == DCSEN)|| - (info->SENmode == TRANSEN)) - { + if ((info->SENmode == DCSEN) || (info->SENmode == TRANSEN)) { /* loop throgh all the columns of RHS matrix - each column corresponding to a design parameter */ - for (col=1;col<=info->SENparms;col++) { - for(row=1;row<=size;row++){ + for (col = 1; col <= info->SENparms; col++) { + + for (row = 1; row <= size; row++) { ckt->CKTsenRhs[row] = info->SEN_RHS[row][col]; } + /* solve for the sensitivity values */ - SMPsolve(ckt->CKTmatrix,ckt->CKTsenRhs,ckt->CKTrhsSpare); + SMPsolve(ckt->CKTmatrix, ckt->CKTsenRhs, ckt->CKTrhsSpare); /* store the sensitivity values */ - for(row=1;row<=size;row++){ + for (row = 1; row <= size; row++) { info->SEN_Sap[row][col] = ckt->CKTsenRhs[row]; info->SEN_RHS[row][col] = ckt->CKTsenRhs[row]; } } + #ifdef SENSDEBUG printf("\n"); printf("Sensitivity matrix :\n"); - for(row=1;row<=size;row++){ - rowe=CKTnodName(ckt,row) ; - if(strcmp("4",rowe)==0){ - for (col=1;col<=info->SENparms;col++) { + for (row = 1; row <= size; row++) { + rowe = CKTnodName(ckt, row); +// if (strcmp("4", rowe) == 0) { + for (col = 1; col <= info->SENparms; col++) { printf("\t"); - printf("Sap(%s,%d) = %.5e\t",rowe,col, - info->SEN_Sap[row][col]); + printf("Sap(%s,%d) = %.5e\t", rowe, col, + info->SEN_Sap[row][col]); } printf("\n\n"); - } +// } } printf(" RHS matrix :\n"); - for(row=1;row<=size;row++){ - for (col=1;col<=info->SENparms;col++) { + for (row = 1; row <= size; row++) { + for (col = 1; col <= info->SENparms; col++) { printf(" "); - printf("RHS(%d,%d) = %.7e ",row,col, - info->SEN_RHS[row][col]); + printf("RHS(%d,%d) = %.7e ", row, col, + info->SEN_RHS[row][col]); } printf("\n"); } printf(" Jacobian matrix :\n"); - for(row=1; row<=size; row++){ - for(col=1; col<=size; col++){ - if(elt = SMPfindElt(ckt->CKTmatrix, row , col , 0)){ - printf("%.7e ",elt->SMPvalue); - } - else{ + for (row = 1; row <= size; row++) { + for (col = 1; col <= size; col++) { + elt = SMPfindElt(ckt->CKTmatrix, row , col , 0); + if (elt) + printf("%.7e ", elt->Real); + else printf("0.0000000e+00 "); - } } printf("\n"); } -#endif +#endif } - if(info->SENmode == ACSEN){ + if (info->SENmode == ACSEN) { /* loop throgh all the columns of RHS matrix - each column corresponding to a design parameter */ - for (col=1;col<=info->SENparms;col++) { + for (col = 1; col <= info->SENparms; col++) { - for(row=1;row<=size;row++){ - ckt->CKTsenRhs[row] = info->SEN_RHS[row][col]; + for (row = 1; row <= size; row++) { + ckt->CKTsenRhs[row] = info->SEN_RHS[row][col]; ckt->CKTseniRhs[row] = info->SEN_iRHS[row][col]; } /* solve for the sensitivity values ( both real and imag parts)*/ - SMPcSolve(ckt->CKTmatrix,ckt->CKTsenRhs,ckt->CKTseniRhs, - ckt->CKTrhsSpare,ckt->CKTirhsSpare); + SMPcSolve(ckt->CKTmatrix, ckt->CKTsenRhs, ckt->CKTseniRhs, + ckt->CKTrhsSpare, ckt->CKTirhsSpare); /* store the sensitivity values ( both real and imag parts)*/ - for(row=1;row<=size;row++){ - info->SEN_RHS[row][col] = ckt->CKTsenRhs[row]; + for (row = 1; row <= size; row++) { + info->SEN_RHS[row][col] = ckt->CKTsenRhs[row]; info->SEN_iRHS[row][col] = ckt->CKTseniRhs[row]; - } + } } + #ifdef SENSDEBUG printf("\n"); - printf("CKTomega = %.7e rad/sec\t\n",ckt->CKTomega); + printf("CKTomega = %.7e rad/sec\t\n", ckt->CKTomega); printf("Sensitivity matrix :\n"); - for(row=1;row<=size;row++){ - rowe=CKTnodName(ckt,row); - for (col=1;col<=info->SENparms;col++) { + for (row = 1; row <= size; row++) { + rowe = CKTnodName(ckt, row); + for (col = 1; col <= info->SENparms; col++) { printf("\t"); - printf("RHS(%s,%d) = %.5e",rowe,col, - info->SEN_RHS[row][col]); - printf(" + j %.5e\t",info->SEN_iRHS[row][col]); + printf("RHS(%s,%d) = %.5e", rowe, col, + info->SEN_RHS[row][col]); + printf(" + j %.5e\t", info->SEN_iRHS[row][col]); printf("\n\n"); - } printf("\n"); } - - printf("CKTomega = %.7e rad/sec\t\n",ckt->CKTomega); + printf("CKTomega = %.7e rad/sec\t\n", ckt->CKTomega); printf(" RHS matrix :\n"); - for(row=1;row<=size;row++){ - for (col=1;col<=info->SENparms;col++) { + for (row = 1; row <= size; row++) { + for (col = 1; col <= info->SENparms; col++) { printf(" "); - printf("RHS(%d,%d) = %.7e ",row,col, - info->SEN_RHS[row][col]); - printf("+j %.7e ",info->SEN_iRHS[row][col]); + printf("RHS(%d,%d) = %.7e ", row, col, + info->SEN_RHS[row][col]); + printf("+j %.7e ", info->SEN_iRHS[row][col]); } printf("\n"); } printf(" Jacobian matrix for AC :\n"); - for(row=1; row<=size; row++){ - for(col=1; col<=size; col++){ - if(elt = SMPfindElt(ckt->CKTmatrix, row , col , 0)){ - printf("%.7e ",elt->SMPvalue); - printf("+j%.7e\t",elt->SMPiValue); - } - else{ + for (row = 1; row <= size; row++) { + for (col = 1; col <= size; col++) { + elt = SMPfindElt(ckt->CKTmatrix, row , col , 0); + if (elt) { + printf("%.7e ", elt->Real); + printf("+j%.7e\t", elt->Imag); + } else{ printf("0.0000000e+00 "); printf("+j0.0000000e+00\t"); } @@ -173,6 +185,6 @@ register CKTcircuit *ckt; #endif } - return(OK); -} + return OK; +} diff --git a/src/unsupported/cktsndct.c b/src/unsupported/cktsndct.c index 195c0e7be..fbb697c50 100644 --- a/src/unsupported/cktsndct.c +++ b/src/unsupported/cktsndct.c @@ -2,15 +2,13 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ -/* +/* * This routine performs the DC and Transient sensitivity * calculations */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -21,58 +19,67 @@ Author: 1985 Thomas L. Quarles int -CKTsenDCtran(ckt) -register CKTcircuit *ckt; +CKTsenDCtran(CKTcircuit *ckt) { int error; #ifdef SENSDEBUG - printf("time = %.7e\n",ckt->CKTtime); + printf("time = %.7e\n", ckt->CKTtime); printf("CKTsenDCtran\n"); -#endif /* SENSDEBUG */ - - if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) && - (ckt->CKTmode & MODEINITTRAN)){ +#endif + if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) && + (ckt->CKTmode & MODEINITTRAN)) + { error = CKTsenLoad(ckt); - if(error) return(error); + if (error) + return error; + #ifdef SENSDEBUG printf("after inittran senload\n"); -#endif /* SENSDEBUG */ +#endif error = CKTsenUpdate(ckt); - if(error) return(error); + if (error) + return error; + #ifdef SENSDEBUG printf("after inittran senupdate\n"); -#endif /* SENSDEBUG */ +#endif + + } + + if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) && + !(ckt->CKTmode & MODETRANOP)) + { + ckt->CKTmode = (ckt->CKTmode & (~INITF)) | MODEINITFLOAT; } - if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)&& - !(ckt->CKTmode&MODETRANOP)) - ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFLOAT; error = CKTsenLoad(ckt); - if(error) return(error); + if (error) + return error; #ifdef SENSDEBUG printf("after CKTsenLoad\n"); -#endif /* SENSDEBUG */ +#endif error = CKTsenComp(ckt); - if(error) return(error); + if (error) + return error; #ifdef SENSDEBUG printf("after CKTsenComp\n"); -#endif /* SENSDEBUG */ +#endif - if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode&TRANSEN) ){ + if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)) { error = CKTsenUpdate(ckt); - if(error) return(error); + if (error) + return error; #ifdef SENSDEBUG printf("after CKTsenUpdate\n"); -#endif /* SENSDEBUG */ +#endif } - - return(OK); + return OK; } diff --git a/src/unsupported/cktsnld.c b/src/unsupported/cktsnld.c index 57e7ce436..7afeaf3a5 100644 --- a/src/unsupported/cktsnld.c +++ b/src/unsupported/cktsnld.c @@ -2,17 +2,15 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ -/* +/* * CKTsenLoad(ckt) * this is a driver program to iterate through all the various - * sensitivity load functions provided for the circuit elements - * in the given circuit + * sensitivity load functions provided for the circuit elements + * in the given circuit */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -23,44 +21,47 @@ Author: 1985 Thomas L. Quarles int -CKTsenLoad(ckt) -register CKTcircuit *ckt; +CKTsenLoad(CKTcircuit *ckt) { - register int i; + int i; int size,row,col; int error; size = SMPmatSize(ckt->CKTmatrix); + #ifdef SENSDEBUG printf("CKTsenLoad\n"); -#endif /* SENSDEBUG */ +#endif - if((ckt->CKTsenInfo->SENmode == DCSEN)|| - (ckt->CKTsenInfo->SENmode == TRANSEN)) { - for (col=0;col<=ckt->CKTsenInfo->SENparms;col++) { - for(row=0;row<=size;row++){ - ckt->CKTsenInfo->SEN_RHS[row][col]= 0; - } - } - for (i=0;iDEVsenLoad && ckt->CKThead[i] ) { + if ((ckt->CKTsenInfo->SENmode == DCSEN) || + (ckt->CKTsenInfo->SENmode == TRANSEN)) + { + for (col = 0; col <= ckt->CKTsenInfo->SENparms; col++) + for (row = 0; row <= size; row++) + ckt->CKTsenInfo->SEN_RHS[row][col] = 0; + + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVsenLoad && ckt->CKThead[i]) { error = DEVices[i]->DEVsenLoad (ckt->CKThead[i], ckt); - if(error) return(error); + if (error) + return error; } - } - } else{ - for (col=0;col<=ckt->CKTsenInfo->SENparms;col++) { - for(row=0;row<=size;row++){ - ckt->CKTsenInfo->SEN_RHS[row][col]= 0; - ckt->CKTsenInfo->SEN_iRHS[row][col]= 0; + + } else { + + for (col = 0; col <= ckt->CKTsenInfo->SENparms; col++) + for (row = 0; row <= size; row++) { + ckt->CKTsenInfo->SEN_RHS[row][col] = 0; + ckt->CKTsenInfo->SEN_iRHS[row][col] = 0; } - } - for (i=0;iDEVsenAcLoad && ckt->CKThead[i] ) { + + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVsenAcLoad && ckt->CKThead[i]) { error = DEVices[i]->DEVsenAcLoad (ckt->CKThead[i], ckt); - if(error) return(error); + if (error) + return error; } - } } - return(OK); + + return OK; } diff --git a/src/unsupported/cktsnprt.c b/src/unsupported/cktsnprt.c index fb6b1b3c6..c0a6801c8 100644 --- a/src/unsupported/cktsnprt.c +++ b/src/unsupported/cktsnprt.c @@ -2,10 +2,8 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -15,21 +13,18 @@ Author: 1985 Thomas L. Quarles #include "ngspice/suffix.h" - /* CKTsenPrint(ckt) - * this is a driver program to iterate through all the - * various sensitivity print functions provided for - * the circuit elements in the given circuit - */ +/* CKTsenPrint(ckt) + * this is a driver program to iterate through all the + * various sensitivity print functions provided for + * the circuit elements in the given circuit + */ void -CKTsenPrint(ckt) -register CKTcircuit *ckt; +CKTsenPrint(CKTcircuit *ckt) { - register int i; + int i; - for (i=0;iDEVsenPrint && ckt->CKThead[i] ) { + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVsenPrint && ckt->CKThead[i]) DEVices[i]->DEVsenPrint (ckt->CKThead[i], ckt); - } - } } diff --git a/src/unsupported/cktsnset.c b/src/unsupported/cktsnset.c index 2cb344b60..d2984acce 100644 --- a/src/unsupported/cktsnset.c +++ b/src/unsupported/cktsnset.c @@ -2,18 +2,16 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -/* - */ /* * CKTsenSetup(ckt) * this is a driver program to iterate through all the various - * sensitivity setup functions provided for the circuit elements - * in the given circuit + * sensitivity setup functions provided for the circuit elements + * in the given circuit */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/smpdefs.h" #include "ngspice/cktdefs.h" @@ -24,29 +22,29 @@ Author: 1985 Thomas L. Quarles int -CKTsenSetup(ckt) -register CKTcircuit *ckt; - +CKTsenSetup(CKTcircuit *ckt) { - register int i; + int i; int error; - register SENstruct *info; + SENstruct *info; + #ifdef SENSDEBUG printf("CKTsenSetup\n"); -#endif /* SENSDEBUG */ - info = ckt->CKTsenInfo; - info->SENparms = 0; +#endif - for (i=0;iDEVsenSetup && ckt->CKThead[i] ) { + info = ckt->CKTsenInfo; + info->SENparms = 0; + + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVsenSetup && ckt->CKThead[i]) { error = DEVices[i]->DEVsenSetup (info, ckt->CKThead[i]); - if(error) return(error); + if (error) + return error; } - } + #ifdef SENSDEBUG printf("CKTsenSetup end\n"); -#endif /* SENSDEBUG */ - return(OK); +#endif + + return OK; } - - diff --git a/src/unsupported/sen2dest.c b/src/unsupported/sen2dest.c index 583871016..fa9f4be7d 100644 --- a/src/unsupported/sen2dest.c +++ b/src/unsupported/sen2dest.c @@ -3,65 +3,71 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ - /* SENdestroy(ckt) - * this is a driver program to iterate through all the various - * destroy functions provided for the circuit elements in the - * given circuit - */ +/* SENdestroy(ckt) + * this is a driver program to iterate through all the various + * destroy functions provided for the circuit elements in the + * given circuit + */ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/cktdefs.h" #include "ngspice/devdefs.h" -#include "util.h" #include "ngspice/ifsim.h" #include "ngspice/sperror.h" #include "ngspice/suffix.h" void -SENdestroy(info) - SENstruct *info; +SENdestroy(SENstruct *info) { - register int i; + int i; int size; + size = info->SENsize; - size = info->SENsize; #ifdef SENSDEBUG - printf("size = %d\n",size); - printf("freeing sensitivity structure in SENdestroy\n"); -#endif /* SENSDEBUG */ - /* - if(info->SENdevices) FREE(info->SENdevices); - if(info->SENparmNames) FREE(info->SENparmNames); - */ - if(info->SEN_Sap){ + printf("size = %d\n", size); + printf("freeing sensitivity structure in SENdestroy\n"); +#endif + + /* + if (info->SENdevices) FREE(info->SENdevices); + if (info->SENparmNames) FREE(info->SENparmNames); + */ + + if (info->SEN_Sap) { + #ifdef SENSDEBUG - printf("freeing SEN_Sap in SENdestroy\n"); -#endif /* SENSDEBUG */ - for(i=0;i<=size;i++){ - if(info->SEN_Sap[i]) FREE(info->SEN_Sap[i]); - } - FREE(info->SEN_Sap); - } - if(info->SEN_RHS){ - for(i=0;i<=size;i++){ - if(info->SEN_RHS[i]) FREE(info->SEN_RHS[i]); - } - FREE(info->SEN_RHS); - } - if(info->SEN_iRHS){ - for(i=0;i<=size;i++){ - if(info->SEN_iRHS[i]) FREE(info->SEN_iRHS[i]); - } - FREE(info->SEN_Sap); - } - /* - FREE(info); - */ + printf("freeing SEN_Sap in SENdestroy\n"); +#endif + + for (i = 0; i <= size; i++) + if (info->SEN_Sap[i]) + FREE(info->SEN_Sap[i]); + FREE(info->SEN_Sap); + } + + if (info->SEN_RHS) { + for (i = 0; i <= size; i++) + if (info->SEN_RHS[i]) + FREE(info->SEN_RHS[i]); + FREE(info->SEN_RHS); + } + + if (info->SEN_iRHS) { + for (i = 0; i <= size; i++) + if (info->SEN_iRHS[i]) + FREE(info->SEN_iRHS[i]); + FREE(info->SEN_Sap); + } + + /* + FREE(info); + */ + #ifdef SENSDEBUG - printf("SENdestroy end\n"); -#endif /* SENSDEBUG */ + printf("SENdestroy end\n"); +#endif return; } diff --git a/src/unsupported/sen2setp.c b/src/unsupported/sen2setp.c index b407e3b4d..a571afea1 100644 --- a/src/unsupported/sen2setp.c +++ b/src/unsupported/sen2setp.c @@ -3,79 +3,83 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/ifsim.h" #include "ngspice/iferrmsg.h" #include "ngspice/sen2defs.h" #include "ngspice/cktdefs.h" -#include "util.h" #include "ngspice/suffix.h" +#include "../spicelib/analysis/analysis.h" -/* ARGSUSED */ -int -SENsetParm(ckt,anal,which,value) - CKTcircuit *ckt; - JOB *anal; - int which; - IFvalue *value; + +int +SENsetParm(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value) { + SENstruct *job = (SENstruct *) anal; + + NG_IGNORE(ckt); + switch(which) { case SEN_DC: - if(value->iValue) { - ((SENstruct *)anal)->SENmode |= DCSEN; - } + if (value->iValue) + job->SENmode |= DCSEN; break; + case SEN_AC: - if(value->iValue) { - ((SENstruct *)anal)->SENmode |= ACSEN; - } + if (value->iValue) + job->SENmode |= ACSEN; break; + case SEN_TRAN: - if(value->iValue) { - ((SENstruct *)anal)->SENmode |= TRANSEN; - } + if (value->iValue) + job->SENmode |= TRANSEN; break; + case SEN_DEV: - ((SENstruct *)anal)->SENnumVal += 1; - if( ! ((SENstruct *)anal)->SENdevices ) { - ((SENstruct *)anal)->SENdevices = TMALLOC(char *, ((SENstruct *)anal)->SENnumVal); - if( ((SENstruct *)anal)->SENdevices == NULL) return(E_NOMEM); - ((SENstruct *)anal)->SENparmNames = TMALLOC(char *, ((SENstruct *)anal)->SENnumVal); - if( ((SENstruct *)anal)->SENparmNames == NULL) return(E_NOMEM); + job->SENnumVal += 1; + if (!job->SENdevices) { + job->SENdevices = TMALLOC(char *, job->SENnumVal); + if (job->SENdevices == NULL) + return E_NOMEM; + job->SENparmNames = TMALLOC(char *, job->SENnumVal); + if (job->SENparmNames == NULL) + return E_NOMEM; } else { - ((SENstruct *)anal)->SENdevices = TREALLOC(char *, ((SENstruct *)anal)->SENdevices, ((SENstruct *)anal)->SENnumVal); - if( ((SENstruct *)anal)->SENdevices == NULL) return(E_NOMEM); - ((SENstruct *)anal)->SENparmNames = TREALLOC(char *, ((SENstruct *)anal)->SENparmNames, ((SENstruct *)anal)->SENnumVal) ; - if( ((SENstruct *)anal)->SENparmNames == NULL) return(E_NOMEM); + job->SENdevices = TREALLOC(char *, job->SENdevices, job->SENnumVal); + if (job->SENdevices == NULL) + return E_NOMEM; + job->SENparmNames = TREALLOC(char *, job->SENparmNames, job->SENnumVal); + if (job->SENparmNames == NULL) + return E_NOMEM; } - ((SENstruct *)anal)->SENdevices [ ((SENstruct *)anal)->SENnumVal - 1 ] = - value->sValue; + job->SENdevices [job->SENnumVal - 1] = value->sValue; break; + case SEN_PARM: - ((SENstruct *)anal)->SENparmNames [ ((SENstruct *)anal)->SENnumVal - 1 ] = - value->sValue; + job->SENparmNames [job->SENnumVal - 1] = value->sValue; break; default: - return(E_BADPARM); + return E_BADPARM; } - return(OK); + + return OK; } static IFparm SENparms[] = { - { "dc", SEN_DC, IF_SET|IF_FLAG, "sensitivity in DC analysis" }, - { "op", SEN_DC, IF_SET|IF_FLAG, "sensitivity in DCop analysis" }, - { "ac", SEN_AC, IF_SET|IF_FLAG, "sensitivity in AC analysis" }, - { "tran", SEN_TRAN, IF_SET|IF_FLAG, "sensitivity in transient analysis"}, + { "dc", SEN_DC, IF_SET|IF_FLAG, "sensitivity in DC analysis" }, + { "op", SEN_DC, IF_SET|IF_FLAG, "sensitivity in DCop analysis" }, + { "ac", SEN_AC, IF_SET|IF_FLAG, "sensitivity in AC analysis" }, + { "tran", SEN_TRAN, IF_SET|IF_FLAG, "sensitivity in transient analysis"}, { "dev", SEN_DEV, IF_SET|IF_INSTANCE, "instance with design param." }, - { "parm", SEN_PARM, IF_SET|IF_STRING, "name of design parameter" }, + { "parm", SEN_PARM, IF_SET|IF_STRING, "name of design parameter" }, }; -SPICEanalysis SEN2info = { - { +SPICEanalysis SEN2info = { + { "SENS2", "Sensitivity analysis", diff --git a/src/unsupported/snaskq.c b/src/unsupported/snaskq.c index ddaf0d75c..adb123315 100644 --- a/src/unsupported/snaskq.c +++ b/src/unsupported/snaskq.c @@ -3,7 +3,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/ifsim.h" #include "ngspice/iferrmsg.h" @@ -11,19 +11,19 @@ Author: 1985 Thomas L. Quarles #include "ngspice/cktdefs.h" #include "ngspice/suffix.h" -/* ARGSUSED */ -int -SENaskQuest(ckt,anal,which,value) - CKTcircuit *ckt; - JOB *anal; - int which; - IFvalue *value; + +int +SENaskQuest(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value) { + NG_IGNORE(ckt); + NG_IGNORE(anal); + NG_IGNORE(value); + switch(which) { default: break; } - return(E_BADPARM); -} + return E_BADPARM; +} diff --git a/src/unsupported/snstart.c b/src/unsupported/snstart.c index 79449259c..c12af4560 100644 --- a/src/unsupported/snstart.c +++ b/src/unsupported/snstart.c @@ -3,11 +3,10 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -#include "spice.h" +#include "ngspice/ngspice.h" #include #include "ngspice/ifsim.h" #include "ngspice/cktdefs.h" -#include "util.h" #include "ngspice/const.h" #include "ngspice/sperror.h" #include "ngspice/suffix.h" @@ -17,8 +16,7 @@ Author: 1985 Thomas L. Quarles */ int -SENstartup(ckt) - CKTcircuit *ckt; +SENstartup(CKTcircuit *ckt, int restart) { int i; int err; @@ -26,31 +24,45 @@ SENstartup(ckt) int type; GENinstance *fast; -#ifdef SENSDEBUG + if (restart) { + fprintf(stdout, "Sensitivity-2 analysis: unsupported code\n"); + } + +#ifdef SENSDEBUG printf("SENstartup\n"); -#endif /* SENSDEBUG */ +#endif + ckt->CKTsenInfo->SENstatus = NORMAL; ckt->CKTsenInfo->SENpertfac = 1e-4; - ckt->CKTsenInfo->SENinitflag = ON;/* allocate memory in - NIsenReinit */ + ckt->CKTsenInfo->SENinitflag = ON; /* allocate memory in NIsenReinit */ parmtemp.iValue = 1; - for(i=0;iCKTsenInfo->SENnumVal;i++) { + parmtemp.rValue = 1.0; + + for (i = 0; i < ckt->CKTsenInfo->SENnumVal; i++) { type = -1; fast = NULL; - err = CKTfndDev((GENERIC*)ckt,&type,(GENERIC**)&fast, - ((ckt->CKTsenInfo->SENdevices)[i]), - NULL, NULL); - if(err != OK) return(err); + + err = CKTfndDev(ckt, &type, &fast, ckt->CKTsenInfo->SENdevices[i], NULL); + if (err != OK) + return err; + +#ifdef SENSDEBUG + printf("SENstartup Instance: %s Design parameter: %s\n", ckt->CKTsenInfo->SENdevices[i], + ckt->CKTsenInfo->SENparmNames[i]); +#endif err = CKTpName( - ((ckt->CKTsenInfo->SENparmNames)[i]), - &parmtemp,ckt ,type, - ((ckt->CKTsenInfo->SENdevices)[i]), + ckt->CKTsenInfo->SENparmNames[i], + &parmtemp, ckt, type, + ckt->CKTsenInfo->SENdevices[i], &fast); - if(err != OK) return(err); + if (err != OK) + return err; } -#ifdef SENSDEBUG + +#ifdef SENSDEBUG printf("SENstartup end\n"); -#endif /* SENSDEBUG */ - return(OK); +#endif + + return OK; } diff --git a/src/winmain.c b/src/winmain.c index cf36fdbf8..5fe1d01b9 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -1384,8 +1384,9 @@ int system( const char * command) } // system Windows95 #endif */ +#ifdef __CYGWIN__ /* Strip leading spaces, return a copy of s */ -/*static char* rlead(char *s) +static char* rlead(char *s) { int i,j=0; static char temp[512]; @@ -1406,7 +1407,7 @@ int system( const char * command) temp[j] = '\0'; return copy(temp); } -*/ +#endif void winmessage(char* new_msg) { diff --git a/src/winmain.h b/src/winmain.h index fc4944b7a..657a3c41d 100644 --- a/src/winmain.h +++ b/src/winmain.h @@ -5,7 +5,9 @@ /* Forward definition of main() */ int xmain( int argc, char * argv[]); /* forward of Update function */ -//static char* rlead(char*); +#ifdef __CYGWIN__ +static char* rlead(char*); +#endif void winmessage(char*); static void HistoryInit(void); diff --git a/src/xspice/icm/makedefs.in b/src/xspice/icm/makedefs.in index ffc488f30..151e37367 100644 --- a/src/xspice/icm/makedefs.in +++ b/src/xspice/icm/makedefs.in @@ -42,7 +42,7 @@ endif CMPP = $(top_builddir)/src/xspice/cmpp/cmpp # Flags to use when linking shared library -LDFLAGS = -shared +LDFLAGS = -shared -lm ifeq ($(ISMINGW), 1) LDFLAGS = -shared @LDFLAGS@ endif diff --git a/src/xspice/icm/xtradev/potentiometer/cfunc.mod b/src/xspice/icm/xtradev/potentiometer/cfunc.mod index c4bd69b34..955aaabe6 100644 --- a/src/xspice/icm/xtradev/potentiometer/cfunc.mod +++ b/src/xspice/icm/xtradev/potentiometer/cfunc.mod @@ -171,7 +171,7 @@ void cm_potentiometer (ARGS) PARTIAL(r0,wiper) = -1.0 / r_lower; PARTIAL(r1,r0) = 0.0; - PARTIAL(r1,r1) = 1.0 / r_upper;; + PARTIAL(r1,r1) = 1.0 / r_upper; PARTIAL(r1,wiper) = -1.0 / r_upper; PARTIAL(wiper,r0) = -1.0 / r_lower; diff --git a/src/xspice/mif/mif_inp2.c b/src/xspice/mif/mif_inp2.c index 62e9ece87..a31de88f7 100644 --- a/src/xspice/mif/mif_inp2.c +++ b/src/xspice/mif/mif_inp2.c @@ -219,7 +219,7 @@ MIF_INP2A ( /* create a new structure for this instance in ckt */ mdfast = (MIFmodel*) thismodel->INPmodfast; - IFC(newInstance, (ckt, (GENmodel*)mdfast, (GENinstance **)fast, name)) + IFC(newInstance, (ckt, (GENmodel*)mdfast, (GENinstance **)fast, name)); /* initialize the code model specific elements of the inst struct */ @@ -746,9 +746,6 @@ MIFget_port_type( *status = MIF_OK; } - - if (temp) - tfree(temp); } diff --git a/src/xspice/mif/mifsetup.c b/src/xspice/mif/mifsetup.c index cd9a3b365..5e10ad61c 100644 --- a/src/xspice/mif/mifsetup.c +++ b/src/xspice/mif/mifsetup.c @@ -56,17 +56,17 @@ NON-STANDARD FEATURES /* define macro for easy creation of matrix entries/pointers for outputs */ #define TSTALLOC(ptr,first,second) \ - if((smp_data_out->ptr = \ + do { if((smp_data_out->ptr = \ SMPmakeElt(matrix, smp_data_out->first, smp_data_out->second)) == NULL) { \ return(E_NOMEM); \ - } + } } while(0) /* define macro for easy creation of matrix entries/pointers for inputs */ #define CTSTALLOC(ptr,first,second) \ - if((smp_data_out->input[k].port[l].ptr = \ + do { if((smp_data_out->input[k].port[l].ptr = \ SMPmakeElt(matrix, smp_data_out->first, smp_data_cntl->second)) == NULL) { \ return(E_NOMEM); \ - } + } } while(0) diff --git a/tests/bsim3/dc_sim/modelcard.nmos b/tests/bsim3/dc_sim/modelcard.nmos index e09340b3a..31d9349cb 100644 --- a/tests/bsim3/dc_sim/modelcard.nmos +++ b/tests/bsim3/dc_sim/modelcard.nmos @@ -2,7 +2,7 @@ *Berkeley Spice Compatibility * Lmin= .35 Lmax= 20 Wmin= .6 Wmax= 20 .model N1 NMOS -+Level= 8 version=3.2.2 ++Level= 8 version=3.3.0 +Tnom=27.0 +Nch= 2.498E+17 Tox=9E-09 Xj=1.00000E-07 +Lint=9.36e-8 Wint=1.47e-7 @@ -33,9 +33,3 @@ +Ute=-1.48 +Ua1= 3.31E-10 Ub1= 2.61E-19 Uc1= -3.42e-10 +Kt1l=0 Prt=764.3 - - - - - - diff --git a/tests/bsim3/dc_sim/modelcard.pmos b/tests/bsim3/dc_sim/modelcard.pmos index dfd8522d0..28dac9eea 100644 --- a/tests/bsim3/dc_sim/modelcard.pmos +++ b/tests/bsim3/dc_sim/modelcard.pmos @@ -1,5 +1,5 @@ .model P1 PMOS -+Level= 8 version=3.2.2 ++Level= 8 version=3.3.0 +Tnom=27.0 +Nch= 3.533024E+17 Tox=9E-09 Xj=1.00000E-07 +Lint=6.23e-8 Wint=1.22e-7 @@ -25,7 +25,3 @@ +Ute= -1.5 +Ua1= 4.312e-9 Ub1= 6.65e-19 Uc1= 0 +Kt1l=0 - - - - diff --git a/tests/bsim3/tran_sim/comparator.cir b/tests/bsim3/tran_sim/comparator.cir index 8e44a171b..d9c17228d 100644 --- a/tests/bsim3/tran_sim/comparator.cir +++ b/tests/bsim3/tran_sim/comparator.cir @@ -28,8 +28,8 @@ Vdd Vdd 0 5 Va A 0 pulse 0 5 10ns .1ns .1ns 15ns 30ns Vb B 0 0 -.model nmos nmos level=8 version=3.2.2 -.model pmos pmos level=8 version=3.2.2 +.model nmos nmos level=8 version=3.3.0 +.model pmos pmos level=8 version=3.3.0 * transient analysis .tran 1ns 60ns @@ -37,4 +37,3 @@ Vb B 0 0 .print tran a b v(9) v(8) .END - diff --git a/tests/bsim3/tran_sim/one-shot.cir b/tests/bsim3/tran_sim/one-shot.cir index 4e75736bb..c5ff697ca 100644 --- a/tests/bsim3/tran_sim/one-shot.cir +++ b/tests/bsim3/tran_sim/one-shot.cir @@ -34,20 +34,11 @@ M13 3 Lnot 0 0 NMOS w=1.8u l=1.2u Vcc vdd 0 5 vin in 0 pulse 0 5 1ns .1ns .1ns .8ns 5ns -.model nmos nmos level=8 version=3.2.2 -.model pmos pmos level=8 version=3.2.2 +.model nmos nmos level=8 version=3.3.0 +.model pmos pmos level=8 version=3.3.0 .tran 1ns 10ns .print tran in out .options noacct .END - - - - - - - - - diff --git a/visualc-shared/sharedspice.vcproj b/visualc-shared/sharedspice.vcproj index 5ba6c21fc..95442db6c 100644 --- a/visualc-shared/sharedspice.vcproj +++ b/visualc-shared/sharedspice.vcproj @@ -26,6 +26,9 @@ /> - - @@ -2188,6 +2184,10 @@ RelativePath="..\src\frontend\parser\input.h" > + + @@ -3216,6 +3216,10 @@ RelativePath="..\src\spicelib\devices\asrc\asrcmdel.c" > + + @@ -3296,6 +3300,10 @@ RelativePath="..\src\spicelib\devices\bsim1\b1mpar.c" > + + @@ -3372,6 +3380,10 @@ RelativePath="..\src\spicelib\devices\bsim2\b2mpar.c" > + + @@ -3444,6 +3456,10 @@ RelativePath="..\src\spicelib\devices\bsim3\b3mpar.c" > + + @@ -3512,6 +3528,10 @@ RelativePath="..\src\spicelib\devices\bsim3soi_dd\b3soiddmpar.c" > + + @@ -3588,6 +3608,10 @@ RelativePath="..\src\spicelib\devices\bsim3soi_fd\b3soifdmpar.c" > + + @@ -3664,6 +3688,10 @@ RelativePath="..\src\spicelib\devices\bsim3soi_pd\b3soipdmpar.c" > + + @@ -3740,6 +3768,10 @@ RelativePath="..\src\spicelib\devices\bsim3v0\b3v0mpar.c" > + + @@ -3812,6 +3844,10 @@ RelativePath="..\src\spicelib\devices\bsim3v1\b3v1mpar.c" > + + @@ -3884,6 +3920,10 @@ RelativePath="..\src\spicelib\devices\bsim3v32\b3v32mpar.c" > + + @@ -3960,6 +4000,10 @@ RelativePath="..\src\spicelib\devices\bsim4\b4mpar.c" > + + @@ -4028,6 +4072,10 @@ RelativePath="..\src\spicelib\devices\bsimsoi\b4soimpar.c" > + + @@ -4112,6 +4160,10 @@ RelativePath="..\src\spicelib\devices\bsim4v4\b4v4mpar.c" > + + @@ -4188,6 +4240,10 @@ RelativePath="..\src\spicelib\devices\bsim4v5\b4v5mpar.c" > + + @@ -4264,6 +4320,10 @@ RelativePath="..\src\spicelib\devices\bsim4v6\b4v6mpar.c" > + + @@ -4356,6 +4416,10 @@ RelativePath="..\src\spicelib\devices\bjt\bjtmpar.c" > + + @@ -4496,6 +4560,10 @@ RelativePath="..\src\spicelib\devices\cap\capmpar.c" > + + @@ -4796,6 +4864,10 @@ RelativePath="..\src\spicelib\analysis\cktmkcur.c" > + + @@ -5352,6 +5424,10 @@ RelativePath="..\src\spicelib\devices\dio\diompar.c" > + + @@ -5668,6 +5744,10 @@ RelativePath="..\src\spicelib\devices\hfet2\hfet2mpar.c" > + + @@ -5728,6 +5808,10 @@ RelativePath="..\src\spicelib\devices\hfet1\hfetmpar.c" > + + @@ -5804,6 +5888,10 @@ RelativePath="..\src\spicelib\devices\hisim2\hsm2mpar.c" > + + @@ -5880,6 +5968,10 @@ RelativePath="..\src\spicelib\devices\hisimhv1\hsmhvmpar.c" > + + @@ -5956,6 +6048,10 @@ RelativePath="..\src\spicelib\devices\ind\indmpar.c" > + + @@ -6364,6 +6460,10 @@ RelativePath="..\src\spicelib\devices\jfet2\jfet2mpar.c" > + + @@ -6432,6 +6532,10 @@ RelativePath="..\src\spicelib\devices\jfet\jfetmpar.c" > + + @@ -6616,6 +6720,10 @@ RelativePath="..\src\spicelib\devices\mesa\mesamparam.c" > + + @@ -6688,6 +6796,10 @@ RelativePath="..\src\spicelib\devices\mes\mesmpar.c" > + + @@ -6872,6 +6984,10 @@ RelativePath="..\src\spicelib\devices\mos1\mos1mpar.c" > + + @@ -6972,6 +7088,10 @@ RelativePath="..\src\spicelib\devices\mos2\mos2mpar.c" > + + @@ -7072,6 +7192,10 @@ RelativePath="..\src\spicelib\devices\mos3\mos3mpar.c" > + + @@ -7152,6 +7276,10 @@ RelativePath="..\src\spicelib\devices\mos6\mos6mpar.c" > + + @@ -7224,6 +7352,10 @@ RelativePath="..\src\spicelib\devices\mos9\mos9mpar.c" > + + @@ -7948,6 +8080,10 @@ RelativePath="..\src\spicelib\devices\res\resmpar.c" > + + @@ -8068,6 +8204,10 @@ RelativePath="..\src\spicelib\devices\soi3\soi3mpar.c" > + + @@ -8564,6 +8704,10 @@ RelativePath="..\src\spicelib\devices\vbic\vbicmpar.c" > + + @@ -8748,6 +8892,10 @@ RelativePath="..\src\spicelib\devices\vsrc\vsrcmdel.c" > + +