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..551d3c4b9 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -52,7 +52,7 @@ static struct line *com_options = NULL; static void cktislinear(CKTcircuit *ckt, struct line *deck); void line_free_x(struct line *deck, bool recurse); - +void create_circbyline(char *line); /* diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 50c3fc399..284f77b6d 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -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 char *subckt_w_params[N_SUBCKT_W_PARAMS]; 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 function_env +{ + struct function_env *up; + + struct function { + struct function *next; + char *name; + char *macro; + char *params[N_PARAMS]; + int num_parameters; + } *functions; +}; + + +static char *global; + static COMPATMODE_T inp_compat_mode; /* Collect information for dynamic allocation of numparam arrays */ @@ -66,12 +84,11 @@ 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_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 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 line *deck); -static void inp_expand_macros_in_func(void); -static void inp_expand_macros_in_deck(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 int inp_split_multi_param_lines(struct line *deck, int line_number); @@ -92,42 +109,76 @@ 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) { --d; while (*d && !isspace(*d)) d--; return d + 1; } +static char *skip_back_ws(char *d) { --d; while (isspace(*d)) d--; return d + 1; } 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 void tprint(struct line *deck); + #ifndef XSPICE static void inp_poly_err(struct line *deck); #endif -static int +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 *deck, char *name) +{ + struct line *c; + for (c = deck; c; c = c->li_next) { + char *line = c->li_line; + 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++; -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 (!*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 +193,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"); @@ -166,14 +219,16 @@ read_a_lib(char *y, int call_depth, char *dir_name) 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); @@ -186,116 +241,6 @@ read_a_lib(char *y, int call_depth, char *dir_name) } -static int -expand_section_references(int line_number) -{ - struct line *tmp_ptr = NULL, *next; - int lib_idx; - - 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; - - if (found_section && ciprefix(".endl", buffer)) { - - struct line *next = working->li_next; - - /* Make the .endl a comment */ - *buffer = '*'; - found_section = FALSE; - - /* append the line following the library section reference */ - working->li_next = tmp_ptr; - - /* and continue with the line following */ - /* the .endl of this section definition */ - working = next; - 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 line_number; -} - - /*------------------------------------------------------------------------- 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 @@ -311,7 +256,7 @@ expand_section_references(int line_number) 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 + 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 @@ -356,7 +301,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile unsigned int no_braces = 0; /* number of '{' */ int cirlinecount = 0; /* length of circarray */ - size_t max_line_length; /* max. line length in input deck */ + size_t max_line_length = 0; /* max. line length in input deck */ struct line *tmp_ptr1 = NULL; @@ -365,7 +310,6 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile 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(); @@ -461,50 +405,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); } @@ -614,10 +521,24 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile /* 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 + { 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"); } @@ -682,16 +603,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile 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); + 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); + } } /* @@ -809,15 +727,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile 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); +//tprint(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) + for (newcard = working; newcard; newcard = newcard->li_next) end = newcard; inp_reorder_params(working, cc, end); @@ -841,43 +757,42 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile } 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; 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); + + fprintf(stdout, "max line length %d, max subst. per line %d, number of lines %d\n", + (int) max_line_length, no_braces, dynmaxline); + } } - - /* 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; - } - - 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); - } - return cc; } @@ -1007,18 +922,16 @@ readline(FILE *fd) /* replace "gnd" by " 0 " Delimiters of gnd may be ' ' or ',' or '(' or ')' */ static void -inp_fix_gnd_name(struct line *deck) +inp_fix_gnd_name(struct line *c) { - struct line *c = deck; char *gnd; - while (c != NULL) { + for (; c; c = c->li_next) { 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") == NULL)) continue; - } + // replace "?gnd?" by "? 0 ?", ? being a ' ' ',' '(' ')'. while ((gnd = strstr(gnd, "gnd")) != NULL) { if ((isspace(gnd[-1]) || gnd[-1] == '(' || gnd[-1] == ',') && @@ -1029,7 +942,6 @@ inp_fix_gnd_name(struct line *deck) } // now remove the extra white spaces around 0 c->li_line = inp_remove_ws(c->li_line); - c = c->li_next; } } @@ -1043,23 +955,19 @@ create_new_card(char *card_str, int *line_number) { newcard->li_error = NULL; newcard->li_actual = NULL; - *line_number = *line_number + 1; + *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 +981,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 +1031,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); } @@ -1173,7 +1086,7 @@ inp_add_control_section(struct line *deck, int *line_number) 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)) { @@ -1275,13 +1188,12 @@ 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; @@ -1355,15 +1267,15 @@ 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); + end_ptr = skip_back_non_ws(end_ptr); } else { end_ptr = line + strlen(line); } - end_ptr = skip_back_ws(end_ptr - 1) + 1; + end_ptr = skip_back_ws(end_ptr); - inst_name_ptr = skip_back_non_ws(end_ptr - 1) + 1; + inst_name_ptr = skip_back_non_ws(end_ptr); return copy_substring(inst_name_ptr, end_ptr); } @@ -1425,8 +1337,8 @@ 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(line + strlen(line)); + ptr_beg = skip_back_non_ws(ptr_end); return copy_substring(ptr_beg, ptr_end); } @@ -1442,7 +1354,7 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, 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) { + for (card = start_card; card; card = card->li_next) { line = card->li_line; if (*line == '*') @@ -1468,7 +1380,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 +1392,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); } @@ -1505,7 +1417,7 @@ get_subckts_for_subckt(struct line *start_card, char *subckt_name, 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); } @@ -1570,7 +1482,7 @@ comment_out_unused_subckt_models(struct line *start_card, int no_of_lines) 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,7 +1491,7 @@ 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) { + for (card = start_card; card; card = card->li_next) { line = card->li_line; if (*line == '*') @@ -1670,7 +1582,7 @@ 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) { + for (card = start_card; card; card = card->li_next) { line = card->li_line; if (*line == '*') @@ -1771,13 +1683,13 @@ inp_fix_ternary_operator_str(char *line, bool all) } else { 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 +1698,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 +1733,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 +1768,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); @@ -1904,13 +1816,12 @@ inp_fix_ternary_operator_str(char *line, bool all) 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) { + for (; card; card = card->li_next) { line = card->li_line; /* exclude replacement of ternary function between .control and .endc */ @@ -1968,13 +1879,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; - } } @@ -2027,7 +1935,7 @@ inp_stripcomments_line(char *s) return; } - if (d>s) { + if (d > s) { d--; /* d now points to character just before comment */ @@ -2074,6 +1982,31 @@ inp_change_quotes(char *s) } +static void +new_subckt_w_params(char *str) +{ + if (num_subckt_w_params >= N_SUBCKT_W_PARAMS) { + fprintf(stderr, "ERROR, N_SUBCKT_W_PARMS overflow\n"); + controlled_exit(EXIT_FAILURE); + } + + subckt_w_params[num_subckt_w_params++] = str; +} + + +static char ** +find_subckt_w_params(char *subckt_name) +{ + int i; + + for (i = 0; i < num_subckt_w_params; i++) + if (strcmp(subckt_w_params[i], subckt_name) == 0) + return & subckt_w_params[i]; + + return NULL; +} + + static char* inp_fix_subckt(char *s) { @@ -2090,15 +2023,14 @@ 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); + new_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_ws(equal); beg = skip_back_non_ws(beg); - *beg = '\0'; - beg++; + beg[-1] = '\0'; head = alloc(struct line); /* create list of parameters that need to get sorted */ @@ -2107,8 +2039,8 @@ inp_fix_subckt(char *s) /* 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); + ptr1 = skip_back_non_ws(ptr1); /* ptr1 points to beginning of parameter */ /* if parameter is an expression and starts with '{', find closing '}' @@ -2138,7 +2070,7 @@ inp_fix_subckt(char *s) beg = ptr2; } else { *ptr2 = '\0'; - beg = ptr2+1; + beg = ptr2 + 1; } newcard = alloc(struct line); @@ -2295,27 +2227,22 @@ inp_remove_ws(char *s) No changes to lines in .control section ! */ static void -inp_fix_for_numparam(struct line *deck) +inp_fix_for_numparam(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); @@ -2329,40 +2256,33 @@ inp_fix_for_numparam(struct line *deck) if (ciprefix(".subckt", c->li_line)) c->li_line = inp_fix_subckt(c->li_line); - - c = c->li_next; } } 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 +2290,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 +2309,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 +2329,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 +2382,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); + end_ptr = skip_back_non_ws(end_ptr); } else { end_ptr = s + strlen(s); } - 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); + subckt_name = skip_back_non_ws(end_ptr); return copy_substring(subckt_name, end_ptr); } @@ -2487,21 +2415,20 @@ inp_get_params(char *line, char *param_names[], char *param_values[]) // check for equality '==' if (equal_ptr[1] == '=') { - line = equal_ptr+2; + line = equal_ptr + 2; continue; } // check for '!=', '<=', '>=' if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - line = equal_ptr+1; + line = equal_ptr + 1; continue; } 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); + name = skip_back_non_ws(end); param_names[num_params++] = copy_substring(name, end); @@ -2551,9 +2478,9 @@ inp_fix_inst_line(char *inst_line, end = strchr(inst_line, '='); if (end) { - end = skip_back_ws(end - 1); + end = skip_back_ws(end); end = skip_back_non_ws(end); - *end = '\0'; + end[-1] = '\0'; } for (i = 0; i < num_subckt_params; i++) @@ -2584,7 +2511,9 @@ inp_fix_inst_line(char *inst_line, return curr_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[]) { @@ -2598,7 +2527,13 @@ found_mult_param(int num_params, char *param_names[]) return found_mult; } +/* 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, int num_subckt_params, char *subckt_param_names[], char *subckt_param_values[]) @@ -2608,12 +2543,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); + new_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 +2558,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)) @@ -2664,7 +2600,7 @@ 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) { + for (c = deck; c; c = c->li_next) { inst_line = c->li_line; if (*inst_line == '*') @@ -2677,8 +2613,7 @@ 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) { + for (d = deck; d; d = d->li_next) { subckt_line = d->li_line; if (ciprefix(".subckt", subckt_line)) { subckt_line = skip_non_ws(subckt_line); @@ -2690,7 +2625,6 @@ 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); @@ -2722,8 +2656,8 @@ inp_fix_inst_calls_for_numparam(struct line *deck) } 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) { + + if (find_subckt_w_params(subckt_name)) { sprintf(name_w_space, "%s ", subckt_name); /* find .subckt line */ @@ -2783,8 +2717,6 @@ inp_fix_inst_calls_for_numparam(struct line *deck) break; d = d->li_next; } - break; - } } tfree(subckt_name); } @@ -2793,132 +2725,168 @@ inp_fix_inst_calls_for_numparam(struct line *deck) } -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 < num_parameters[fcn_number]; i++) { + for (i = 0; i < fcn->num_parameters; 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,7 +2912,7 @@ 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) { @@ -2962,9 +2930,9 @@ inp_do_macro_param_replace(int fcn_number, char *params[]) 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 +2955,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 +3009,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 +3051,73 @@ 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; } @@ -3153,36 +3144,32 @@ inp_fix_param_values(struct line *deck) wordlist *nwl; int parens; - while (c != NULL) { + for (; c; c = c->li_next) { 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,22 +3179,20 @@ 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; + strstr(line, "numd2"))) + { continue; } + /* exclude CIDER devices with ic.file parameter */ - if (strstr(line, "ic.file")) { - c = c->li_next; + if (strstr(line, "ic.file")) continue; - } while ((equal_ptr = strchr(line, '=')) != NULL) { @@ -3390,7 +3375,6 @@ inp_fix_param_values(struct line *deck) tfree(old_str); } } - c = c->li_next; } } @@ -3402,7 +3386,7 @@ get_param_name(char *line) char keep; if ((equal_ptr = strchr(line, '=')) != NULL) { - equal_ptr = skip_back_ws(equal_ptr - 1) + 1; + equal_ptr = skip_back_ws(equal_ptr); beg = equal_ptr - 1; while (!isspace(*beg) && beg != line) @@ -3606,12 +3590,9 @@ 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 +3614,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 +3624,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++) @@ -3745,7 +3725,7 @@ inp_sort_params(struct line *start_card, struct line *end_card, struct line *car 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; + str_ptr ++; continue; } beg = str_ptr - 1; @@ -3832,7 +3812,7 @@ inp_add_params_to_subckt(struct line *subckt_card) subckt_name = skip_non_ws(subckt_card->li_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); + new_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); @@ -4001,12 +3981,12 @@ inp_split_multi_param_lines(struct line *deck, int line_num) while ((equal_ptr = strchr(curr_line, '=')) != NULL) { // check for equality '==' if (equal_ptr[1] == '=') { - curr_line = equal_ptr+2; + curr_line = equal_ptr + 2; continue; } // check for '!=', '<=', '>=' if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - curr_line = equal_ptr+1; + curr_line = equal_ptr + 1; continue; } counter++; @@ -4023,16 +4003,16 @@ inp_split_multi_param_lines(struct line *deck, int line_num) 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; + curr_line = equal_ptr + 2; continue; } // check for '!=', '<=', '>=' if (*(equal_ptr-1) == '!' || *(equal_ptr-1) == '<' || *(equal_ptr-1) == '>') { - curr_line = equal_ptr+1; + curr_line = equal_ptr + 1; continue; } - beg_param = skip_back_ws(equal_ptr - 1); + beg_param = skip_back_ws(equal_ptr); beg_param = skip_back_non_ws(beg_param); end_param = skip_ws(equal_ptr + 1); while (*end_param != '\0' && (!isspace(*end_param) || get_expression || get_paren_expression)) { @@ -4046,7 +4026,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); @@ -4145,7 +4124,7 @@ inp_split_multi_param_lines(struct line *deck, int line_num) */ 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; @@ -4155,13 +4134,12 @@ inp_compat(struct line *deck) struct line *new_line, *tmp_ptr; 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; @@ -5246,18 +5224,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, *tmp_ptr; 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; @@ -5685,12 +5663,10 @@ inp_add_series_resistor(struct line *deck) #ifndef XSPICE static void -inp_poly_err(struct line *deck) +inp_poly_err(struct line *card) { - 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; @@ -5723,3 +5699,12 @@ 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); +} 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/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/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/subckt.c b/src/frontend/subckt.c index b819b1904..032c93e30 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); diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 452787130..99a85d951 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,14 @@ 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 */ + int *CKTvoltCurNode ; /* Flag to indicate if a node contains some direct unknown currents */ + CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */ +#endif + double *CKTrhsSpare; /* spare rhs value for reordering */ double *CKTirhs; /* current rhs value - being loaded (imag) */ @@ -289,7 +303,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 *); @@ -387,10 +405,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/sharedspice.h b/src/include/ngspice/sharedspice.h index f5852abe5..ca8f4b71e 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 */ 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/ni/niconv.c b/src/maths/ni/niconv.c index 988fd30f2..87174ae72 100644 --- a/src/maths/ni/niconv.c +++ b/src/maths/ni/niconv.c @@ -15,6 +15,7 @@ Author: 1985 Thomas L. Quarles #include "ngspice/smpdefs.h" + int NIconvTest(CKTcircuit *ckt) { @@ -25,8 +26,19 @@ NIconvTest(CKTcircuit *ckt) double new; double tol; - node = ckt->CKTnodes; +#ifdef KIRCHHOFF +#ifdef STEPDEBUG + int j ; +#endif + + double maximum ; + CKTmkCurKCLnode *ptr ; + +#endif + size = SMPmatSize(ckt->CKTmatrix); + node = ckt->CKTnodes; + #ifdef STEPDEBUG for (i=1;i<=size;i++) { new = ckt->CKTrhs [i] ; @@ -34,6 +46,7 @@ NIconvTest(CKTcircuit *ckt) printf("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] ; @@ -42,26 +55,66 @@ NIconvTest(CKTcircuit *ckt) tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + ckt->CKTvoltTol; if (fabs(new-old) >tol ) { + #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); #endif /* STEPDEBUG */ + ckt->CKTtroubleNode = i; ckt->CKTtroubleElt = NULL; return(1); } + +#ifndef KIRCHHOFF } else { 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); #endif /* STEPDEBUG */ + ckt->CKTtroubleNode = i; ckt->CKTtroubleElt = NULL; return(1); } +#else + /* KCL Verification */ + } + if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i]) && (ckt->CKTvoltCurNode [i])) + { + maximum = 0 ; + ptr = ckt->CKTmkCurKCLarray [i] ; + +#ifdef STEPDEBUG + 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 + + if (fabs (ckt->CKTfvk [i]) > (ckt->CKTreltol * maximum + ckt->CKTabstol)) + return 1 ; +#endif + } } diff --git a/src/maths/ni/nireinit.c b/src/maths/ni/nireinit.c index cc14aee53..805e2ea5f 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,20 @@ 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(CKTvoltCurNode,size+1,int); + for (i = 0 ; i <= size ; i++) + ckt->CKTvoltCurNode [i] = 0 ; + 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..29491a42d 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 ); } /* 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/sharedspice.c b/src/sharedspice.c index 941db8386..fcad3a18a 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 */ @@ -244,7 +249,6 @@ 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; /*helper function*//* static struct plot * @@ -293,12 +297,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 +332,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 +382,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 +403,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 +431,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 +492,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) @@ -479,7 +502,7 @@ ngSpice_running (void) #endif -/* Initialise spice and setup native methods */ +/* Initialise ngspice and setup native methods */ IMPEXP int ngSpice_Init(SendChar* printfcn, SendStat* statusfcn, ControlledExit* ngspiceexit, @@ -578,12 +601,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 +647,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 +665,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 +686,6 @@ IMPEXP int ngSpice_Command(char* comexec) { if ( ! setjmp(errbufc) ) { -// HANDLE tid2; immediate = FALSE; intermj = 1; @@ -668,12 +694,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 +745,7 @@ int ngSpice_Circ(char** circa){ if ( ! setjmp(errbufm) ) { intermj = 0; + immediate = FALSE; /* count the entries */ while (circa[entries]) { entries++; @@ -747,7 +771,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 +795,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) { @@ -809,8 +833,8 @@ char** ngSpice_AllVecs(char* plotname) /* 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 +913,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 +927,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 +946,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 +1001,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 +1091,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 +1214,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 +1227,7 @@ printsend(void) mutex_lock(&fputsMutex); outsend = outstorage(NULL, FALSE); mutex_unlock(&fputsMutex); + break; } mutex_lock(&fputsMutex); @@ -1210,6 +1240,7 @@ printsend(void) tfree(outsend); } } + ps_exited = TRUE; } /* remove the first entry of a wordlist, but keep wl->wl_word */ @@ -1251,7 +1282,7 @@ 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 */ @@ -1323,8 +1354,8 @@ void SetAnalyse( tfree(s); } -/* 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), @@ -1448,7 +1479,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 +1487,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 +1510,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 +1568,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) { 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/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/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/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/dcop.c b/src/spicelib/analysis/dcop.c index 64d5d85d2..55c79d90e 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 */ @@ -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/dctran.c b/src/spicelib/analysis/dctran.c index 708af9130..f90493f76 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -78,9 +78,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; @@ -316,7 +315,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; } @@ -479,9 +481,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 +507,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,6 +545,10 @@ 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"); @@ -792,7 +795,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 +858,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..b847f1649 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"); @@ -450,7 +451,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 +459,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/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..9b99b26d0 100644 --- a/src/spicelib/devices/asrc/asrcext.h +++ b/src/spicelib/devices/asrc/asrcext.h @@ -16,3 +16,4 @@ extern int ASRCacLoad(GENmodel*,CKTcircuit*); extern int ASRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int ASRCunsetup(GENmodel*,CKTcircuit*); extern int ASRCtemp(GENmodel*,CKTcircuit*); +extern int ASRCnodeIsNonLinear (GENmodel *, CKTcircuit *) ; 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/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..429c614e2 100644 --- a/src/spicelib/devices/bjt/bjtext.h +++ b/src/spicelib/devices/bjt/bjtext.h @@ -31,6 +31,7 @@ extern int BJTtrunc(GENmodel*,CKTcircuit*,double*); extern int BJTdisto(int,GENmodel*,CKTcircuit*); extern int BJTnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BJTdSetup(GENmodel*, register CKTcircuit*); +extern int BJTnodeIsNonLinear (GENmodel *, CKTcircuit *) ; #endif 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/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/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/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..7a59dc334 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"); 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_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_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/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/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/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..185681c77 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; 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/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/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/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index 17cfa335f..4de975ce3 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 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/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/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/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/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/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/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..e37e4136d 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) { 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/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/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/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/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/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/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/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..9d40ab9c2 100644 --- a/src/spicelib/devices/hfet2/hfet2ext.h +++ b/src/spicelib/devices/hfet2/hfet2ext.h @@ -24,3 +24,7 @@ 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/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..305b18105 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); 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..12b000329 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); @@ -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..2e386a529 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 + }; @@ -143,15 +148,20 @@ SPICEdev MUTinfo = { #ifdef CIDER /* DEVdump */ NULL, /* DEVacct */ NULL, -#endif - &MUTiSize, - &MUTmSize, +#endif + /* 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..e763cf4a7 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,41 @@ 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) ; + + *(ckt->CKTvoltCurNode+here->INDposNode) = 1 ; + *(ckt->CKTvoltCurNode+here->INDnegNode) = 1 ; + + *(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/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/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/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/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/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/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/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/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/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/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/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/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..693489766 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -10,48 +10,51 @@ 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"), + IP( "r", RES_MOD_R, IF_FLAG,"Device is a resistor model") }; char *RESnames[] = { diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index 457acd1f7..3f3603b7b 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,6 +111,7 @@ 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 */ @@ -115,6 +121,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ 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 */ @@ -146,12 +153,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..437e0e504 100644 --- a/src/spicelib/devices/res/resmask.c +++ b/src/spicelib/devices/res/resmask.c @@ -39,6 +39,9 @@ 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); diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index a08efceeb..c5c5896e4 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -16,51 +16,55 @@ 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: + /* just being reassured by user that this is a resistor model */ + /* no-op */ + 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..a11505f2e 100644 --- a/src/spicelib/devices/res/resparam.c +++ b/src/spicelib/devices/res/resparam.c @@ -19,59 +19,59 @@ 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 */ + 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); + 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..80c7c0e5b 100644 --- a/src/spicelib/devices/res/ressetup.c +++ b/src/spicelib/devices/res/ressetup.c @@ -28,22 +28,10 @@ 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){\ diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index df227a7d7..bd19bd03b 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,73 @@ 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)) { 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)); + "%s: resistance = 0 ohm, set to 1000 ohm",&(here->RESname)); here->RESresist=1000; } } 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/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/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/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..a62a87838 100644 --- a/src/spicelib/devices/vbic/vbicext.h +++ b/src/spicelib/devices/vbic/vbicext.h @@ -25,6 +25,7 @@ extern int VBICunsetup(GENmodel*,CKTcircuit*); extern int VBICtemp(GENmodel*,CKTcircuit*); extern int VBICtrunc(GENmodel*,CKTcircuit*,double*); extern int VBICnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int VBICnodeIsNonLinear (GENmodel *, CKTcircuit *) ; #endif 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/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/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..b34db5d5e 100644 --- a/src/spicelib/devices/vcvs/vcvsset.c +++ b/src/spicelib/devices/vcvs/vcvsset.c @@ -52,8 +52,8 @@ if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ TSTALLOC(VCVSposIbrptr, VCVSposNode, VCVSbranch) TSTALLOC(VCVSnegIbrptr, VCVSnegNode, VCVSbranch) - TSTALLOC(VCVSibrNegptr, VCVSbranch, VCVSnegNode) TSTALLOC(VCVSibrPosptr, VCVSbranch, VCVSposNode) + TSTALLOC(VCVSibrNegptr, VCVSbranch, VCVSnegNode) TSTALLOC(VCVSibrContPosptr, VCVSbranch, VCVScontPosNode) TSTALLOC(VCVSibrContNegptr, VCVSbranch, VCVScontNegNode) } 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/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index 3c034a847..fe803c1a2 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 ; 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..61e7aa635 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -40,6 +40,18 @@ 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) ; + + *(ckt->CKTvoltCurNode+here->VSRCposNode) = 1 ; + *(ckt->CKTvoltCurNode+here->VSRCnegNode) = 1 ; + + *(here->KCLcurrentPos) = *(ckt->CKTrhsOld+here->VSRCbranch) ; + *(here->KCLcurrentNeg) = -(*(ckt->CKTrhsOld+here->VSRCbranch)) ; +#endif + if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->VSRCdcGiven ) { /* load using DC value */ 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/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c index 206c534ba..69b1ab283 100644 --- a/src/spicelib/parser/inp2dot.c +++ b/src/spicelib/parser/inp2dot.c @@ -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++) { diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 110036bdc..0e1af9648 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); @@ -108,7 +108,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. */ @@ -212,8 +212,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 +258,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 +513,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 */ @@ -554,55 +554,55 @@ 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); } 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); - } + default: + fprintf(stderr, "Internal Error: bad function # %d\n", + p->funcnum); + return mkfirst(NULL, p); + } - arg2 = PTdifferentiate(p->left, varnum); + arg2 = PTdifferentiate(p->left, varnum); - newp = mkb(PT_TIMES, arg1, arg2); + newp = mkb(PT_TIMES, arg1, arg2); - break; + 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 +620,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 +711,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 +738,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 +772,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 +790,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 +931,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 +1089,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 +1141,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 +1163,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 +1291,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 +1327,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 +1354,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 +1363,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) { @@ -1397,9 +1397,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 +1409,90 @@ 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/ptfuncs.c b/src/spicelib/parser/ptfuncs.c index 5ae64ae4c..9ff1dbcb8 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,11 +74,11 @@ 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)); } @@ -108,9 +108,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 +126,7 @@ PTasinh(double arg) return (asinh(arg)); #else return log(arg + sqrt(arg * arg + 1.0)); -#endif +#endif } double @@ -142,22 +142,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 +165,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 +213,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/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..9d812494a 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,47 @@ 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, 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/mif/mif_inp2.c b/src/xspice/mif/mif_inp2.c index 62e9ece87..c1240e1b1 100644 --- a/src/xspice/mif/mif_inp2.c +++ b/src/xspice/mif/mif_inp2.c @@ -746,9 +746,6 @@ MIFget_port_type( *status = MIF_OK; } - - if (temp) - tfree(temp); } 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" > + + @@ -5352,6 +5416,10 @@ RelativePath="..\src\spicelib\devices\dio\diompar.c" > + + @@ -5668,6 +5736,10 @@ RelativePath="..\src\spicelib\devices\hfet2\hfet2mpar.c" > + + @@ -5728,6 +5800,10 @@ RelativePath="..\src\spicelib\devices\hfet1\hfetmpar.c" > + + @@ -5804,6 +5880,10 @@ RelativePath="..\src\spicelib\devices\hisim2\hsm2mpar.c" > + + @@ -5880,6 +5960,10 @@ RelativePath="..\src\spicelib\devices\hisimhv1\hsmhvmpar.c" > + + @@ -6364,6 +6448,10 @@ RelativePath="..\src\spicelib\devices\jfet2\jfet2mpar.c" > + + @@ -6432,6 +6520,10 @@ RelativePath="..\src\spicelib\devices\jfet\jfetmpar.c" > + + @@ -6616,6 +6708,10 @@ RelativePath="..\src\spicelib\devices\mesa\mesamparam.c" > + + @@ -6688,6 +6784,10 @@ RelativePath="..\src\spicelib\devices\mes\mesmpar.c" > + + @@ -6872,6 +6972,10 @@ RelativePath="..\src\spicelib\devices\mos1\mos1mpar.c" > + + @@ -6972,6 +7076,10 @@ RelativePath="..\src\spicelib\devices\mos2\mos2mpar.c" > + + @@ -7072,6 +7180,10 @@ RelativePath="..\src\spicelib\devices\mos3\mos3mpar.c" > + + @@ -7152,6 +7264,10 @@ RelativePath="..\src\spicelib\devices\mos6\mos6mpar.c" > + + @@ -7224,6 +7340,10 @@ RelativePath="..\src\spicelib\devices\mos9\mos9mpar.c" > + + @@ -8068,6 +8188,10 @@ RelativePath="..\src\spicelib\devices\soi3\soi3mpar.c" > + + @@ -8564,6 +8688,10 @@ RelativePath="..\src\spicelib\devices\vbic\vbicmpar.c" > + +