diff --git a/configure.ac b/configure.ac index af6e120bc..0a09bfce3 100644 --- a/configure.ac +++ b/configure.ac @@ -1304,6 +1304,7 @@ fi if test "x$enable_modsimd" = xyes; then AC_DEFINE([BSIM3v32SIMD], [1], [simd acceleration for BSIM3V32 device]) + AC_DEFINE([MODSIMD], [1], [simd acceleration for some device models]) if test "x$have_intrinsics" = xyes; then AC_DEFINE([USEX86INTRINSICS], [1], [can use x86 simd intrinsics]) @@ -1344,6 +1345,7 @@ AC_CONFIG_FILES([Makefile src/spicelib/devices/bsim1/Makefile src/spicelib/devices/bsim2/Makefile src/spicelib/devices/bsim3/Makefile + src/spicelib/devices/bsim3simd/Makefile src/spicelib/devices/bsim3v0/Makefile src/spicelib/devices/bsim3v1/Makefile src/spicelib/devices/bsim3v32/Makefile @@ -1415,6 +1417,7 @@ AC_CONFIG_FILES([Makefile src/maths/fft/Makefile src/maths/misc/Makefile src/maths/ni/Makefile + src/maths/ni/SIMD/Makefile src/maths/deriv/Makefile src/maths/poly/Makefile src/maths/sparse/Makefile diff --git a/examples/digital/adder_mos.cir b/examples/digital/adder_mos.cir index 6458cf997..3dd574347 100644 --- a/examples/digital/adder_mos.cir +++ b/examples/digital/adder_mos.cir @@ -58,8 +58,8 @@ X1 1 2 3 4 5 6 7 8 9 10 11 12 0 13 99 FOURBIT .save V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) * use BSIM3 model with default parameters -.model n1 nmos level=49 version=3.2.4simd -.model p1 pmos level=49 version=3.2.4simd +.model n1 nmos level=49 version=3.3.0 +.model p1 pmos level=49 version=3.3.0 *.include ./Modelcards/modelcard32.nmos *.include ./Modelcards/modelcard32.pmos diff --git a/src/Makefile.am b/src/Makefile.am index a4f8e480f..f0c7e9ed3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -135,7 +135,8 @@ ngspice_LDADD += spicelib/devices/ndev/libndev.la endif if WANT_MODSIMD -ngspice_LDADD += spicelib/devices/bsim3v32simd/libbsim3v32simd.la +ngspice_LDADD += spicelib/devices/bsim3v32simd/libbsim3v32simd.la \ + spicelib/devices/bsim3simd/libbsim3simd.la endif if NUMDEV_WANTED @@ -153,7 +154,8 @@ ngspice_LDADD += \ if WANT_MODSIMD ngspice_LDADD += \ - spicelib/analysis/SIMD/libcktsimd.la + spicelib/analysis/SIMD/libcktsimd.la \ + maths/ni/SIMD/libnisimd.la endif if SENSE2_WANTED @@ -424,7 +426,8 @@ endif if WANT_MODSIMD libspice_la_LIBADD += \ - spicelib/devices/bsim3v32simd/libbsim3v32simd.la + spicelib/devices/bsim3v32simd/libbsim3v32simd.la \ + spicelib/devices/bsim3simd/libbsim3simd.la endif if NUMDEV_WANTED @@ -442,7 +445,8 @@ libspice_la_LIBADD += \ if WANT_MODSIMD libspice_la_LIBADD += \ - spicelib/analysis/SIMD/libcktsimd.la + spicelib/analysis/SIMD/libcktsimd.la \ + maths/ni/SIMD/libnisimd.la endif if XSPICE_WANTED @@ -549,7 +553,8 @@ endif if WANT_MODSIMD libngspice_la_LIBADD += \ - spicelib/devices/bsim3v32simd/libbsim3v32simd.la + spicelib/devices/bsim3v32simd/libbsim3v32simd.la \ + spicelib/devices/bsim3simd/libbsim3simd.la endif if NUMDEV_WANTED @@ -567,7 +572,8 @@ libngspice_la_LIBADD += \ if WANT_MODSIMD libngspice_la_LIBADD += \ - spicelib/analysis/SIMD/libcktsimd.la + spicelib/analysis/SIMD/libcktsimd.la \ + maths/ni/SIMD/libnisimd.la endif if XSPICE_WANTED diff --git a/src/include/ngspice/SIMD/simdniinteg.h b/src/include/ngspice/SIMD/simdniinteg.h new file mode 100644 index 000000000..58c8224a8 --- /dev/null +++ b/src/include/ngspice/SIMD/simdniinteg.h @@ -0,0 +1,9 @@ +#ifndef NG_SIMD_NIINTEG_H +#define NG_SIMD_NIINTEG_H + +#include "ngspice/SIMD/simdvector.h" + +int +vecN_NIintegrate(CKTcircuit *ckt, double *geq, double *ceq, double cap, VecNm qcap); + +#endif diff --git a/src/include/ngspice/SIMD/simdop.h b/src/include/ngspice/SIMD/simdop.h index 6743a40b7..6ee45b9e8 100644 --- a/src/include/ngspice/SIMD/simdop.h +++ b/src/include/ngspice/SIMD/simdop.h @@ -33,9 +33,28 @@ #include "ngspice/SIMD/simdvector.h" +/* first include vector functions specialized for specific NSIMD */ + +#if NSIMD==4 +#include "ngspice/SIMD/simdop4.h" +#endif /* NSIMD==4 */ + +#if NSIMD==8 +#include "ngspice/SIMD/simdop8.h" +#endif /* NSIMD==8 */ + +#if NSIMD==2 +#include "ngspice/SIMD/simdop2.h" +#endif /* NSIMD==2 */ + +/* now define missing vector functions in a generic manner */ + inline VecNd vecN_broadcast(double x) { VecNd res; + #ifdef USE_OMPSIMD + #pragma omp simd simdlen(NSIMD) + #endif for(int i=0;i b[i]) ? a[i] : b[i]; return res; } +#endif +#ifndef vecN_fabs inline VecNd vecN_fabs(VecNd x) { VecNd res; + #ifdef USE_OMPSIMD + #pragma omp simd simdlen(NSIMD) + #endif for(int i=0;i +#define vec4_MAX(a,b) _mm256_max_pd(a,b) +#define vecN_MAX vec4_MAX +#define vec4_sqrt(a) _mm256_sqrt_pd(a) +#define vecN_sqrt vec4_sqrt +static inline Vec4d vec4_blend(Vec4d fa, Vec4d tr, Vec4m mask) +{ + return _mm256_blendv_pd(fa,tr, (Vec4d) mask); +} +#define vecN_blend vec4_blend +#else +#define vec4_blend vecN_blend +#endif + +#ifdef HAVE_LIBSLEEF +#include +#define vec4_exp(a) Sleef_expd4_u10(a) +#define vecN_exp vec4_exp +#define vec4_log(a) Sleef_logd4_u35(a) +#define vecN_log vec4_log +#ifndef USEX86INTRINSICS +#define vec4_MAX(a,b) Sleef_fmaxd4(a,b) +#define vecN_MAX vec4_MAX +#define vec4_sqrt(a) Sleef_sqrtd4_u35(a) +#define vecN_sqrt vec4_sqrt +#endif +#define vec4_fabs(a) Sleef_fabsd4(a) +#define vecN_fabs vec4_fabs +#define vec4_pow(a,b) Sleef_powd4_u10(a,vec4_SIMDTOVECTOR(b)) +#define vecN_pow vec4_pow + +#else + +#ifdef HAS_LIBMVEC +Vec4d _ZGVdN4v_exp(Vec4d); +Vec4d _ZGVdN4v_log(Vec4d); +Vec4d _ZGVdN4vv_pow(Vec4d, Vec4d); + +#define vec4_exp(a) _ZGVdN4v_exp(a) +#define vecN_exp vec4_exp +#define vec4_log(a) _ZGVdN4v_log(a) +#define vecN_log vec4_log +#define vec4_pow(a,b) _ZGVdN4vv_pow(a,b) +#define vecN_pow vec4_pow +#define vec4_fabs vecN_fabs + +#endif /* HAS_LIBMVEC */ +#endif /* not HAVE_LIBSLEEF */ + +#ifdef USE_SERIAL_FORM + +#define vec4_SIMDTOVECTOR vecN_SIMDTOVECTOR +#define vec4_SIMDTOVECTORMASK vecN_SIMDTOVECTORMASK +#define vec4_StateAccess vecN_StateAccess +#define vec4_SIMDCOUNT vecN_SIMDCOUNT + +#else + +static inline Vec4d vec4_SIMDTOVECTOR(double val) +{ + return (Vec4d) {val,val,val,val}; +} +static inline Vec4m vec4_SIMDTOVECTORMASK(int val) +{ + return (Vec4m) {val,val,val,val}; +} +static inline Vec4d vec4_StateAccess(double* cktstate, Vec4m stateindexes) +{ + return (Vec4d) { + cktstate[stateindexes[0]], + cktstate[stateindexes[1]], + cktstate[stateindexes[2]], + cktstate[stateindexes[3]] + }; +} +static inline int vec4_SIMDCOUNT(Vec4m mask) { + return (mask[0] ? 1 : 0) + (mask[1] ? 1 : 0) + (mask[2] ? 1 : 0) + (mask[3] ? 1 : 0); +} +#define vecN_SIMDTOVECTOR vec4_SIMDTOVECTOR +#define vecN_SIMDTOVECTORMASK vec4_SIMDTOVECTORMASK +#define vecN_StateAccess vec4_StateAccess +#define vecN_SIMDCOUNT vec4_SIMDCOUNT + +#endif + +#define vec4_StateStore vecN_StateStore +#define vec4_StateAdd vecN_StateAdd +#define vec4_StateSub vecN_StateSub + diff --git a/src/maths/ni/Makefile.am b/src/maths/ni/Makefile.am index a6fb60f98..42876705c 100644 --- a/src/maths/ni/Makefile.am +++ b/src/maths/ni/Makefile.am @@ -1,5 +1,10 @@ ## Process this file with automake to produce Makefile.in +DIST_SUBDIRS = SIMD +if WANT_MODSIMD +SUBDIRS = SIMD +endif + noinst_LTLIBRARIES = libni.la libni_la_SOURCES = \ diff --git a/src/maths/ni/SIMD/Makefile.am b/src/maths/ni/SIMD/Makefile.am new file mode 100644 index 000000000..7fa5d2376 --- /dev/null +++ b/src/maths/ni/SIMD/Makefile.am @@ -0,0 +1,10 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libnisimd.la + +libnisimd_la_SOURCES = \ + simdniinteg.c + +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices +AM_CFLAGS = $(STATIC) $(SIMD_CFLAGS) +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/maths/ni/SIMD/simdniinteg.c b/src/maths/ni/SIMD/simdniinteg.c new file mode 100644 index 000000000..424714766 --- /dev/null +++ b/src/maths/ni/SIMD/simdniinteg.c @@ -0,0 +1,88 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 Thomas L. Quarles +**********/ +/********** +SIMD version: +Copyright 2020 Anamosic Ballenegger Design. +Author: 2020 Florian Ballenegger +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" + +#include "ngspice/SIMD/simdniinteg.h" +#include "ngspice/SIMD/simdop.h" + +int +vecN_NIintegrate(CKTcircuit *ckt, double *geq, double *ceq, double cap, VecNm qcap) +{ + static char *ordmsg = "Illegal integration order"; + static char *methodmsg = "Unknown integration method"; + + VecNm ccap = qcap + 1; + + switch(ckt->CKTintegrateMethod) { + + case TRAPEZOIDAL: + switch(ckt->CKTorder) { + case 1: + vecN_StateStore(ckt->CKTstate0, ccap, ckt->CKTag[0] * vecN_StateAccess(ckt->CKTstate0,qcap) + + ckt->CKTag[1] * vecN_StateAccess(ckt->CKTstate1,qcap)); + break; + case 2: + vecN_StateStore(ckt->CKTstate0, ccap, - vecN_StateAccess(ckt->CKTstate1,ccap) * ckt->CKTag[1] + + ckt->CKTag[0] * + ( vecN_StateAccess(ckt->CKTstate0,qcap) - vecN_StateAccess(ckt->CKTstate1,qcap) ) ); + break; + default: + errMsg = TMALLOC(char, strlen(ordmsg) + 1); + strcpy(errMsg,ordmsg); + return(E_ORDER); + } + break; + case GEAR: + { + VecNd nstateccap = vecN_SIMDTOVECTOR(0); + switch(ckt->CKTorder) { + + case 6: + nstateccap += ckt->CKTag[6]* vecN_StateAccess(ckt->CKTstate6,qcap); + /* fall through */ + case 5: + nstateccap += ckt->CKTag[5]* vecN_StateAccess(ckt->CKTstate5,qcap); + /* fall through */ + case 4: + nstateccap += ckt->CKTag[4]* vecN_StateAccess(ckt->CKTstate4,qcap); + /* fall through */ + case 3: + nstateccap += ckt->CKTag[3]* vecN_StateAccess(ckt->CKTstate3,qcap); + /* fall through */ + case 2: + nstateccap += ckt->CKTag[2]* vecN_StateAccess(ckt->CKTstate2,qcap); + /* fall through */ + case 1: + nstateccap += ckt->CKTag[1]* vecN_StateAccess(ckt->CKTstate1,qcap); + nstateccap += ckt->CKTag[0]* vecN_StateAccess(ckt->CKTstate0,qcap); + break; + + default: + return(E_ORDER); + + } + vecN_StateStore(ckt->CKTstate0,ccap,nstateccap); + } + break; + + default: + errMsg = TMALLOC(char, strlen(methodmsg) + 1); + strcpy(errMsg,methodmsg); + return(E_METHOD); + } + /* not used + *ceq = ckt->CKTstate0[ccap] - ckt->CKTag[0] * ckt->CKTstate0[qcap]; + *geq = ckt->CKTag[0] * cap; + */ + return(OK); +} diff --git a/src/spicelib/devices/Makefile.am b/src/spicelib/devices/Makefile.am index 8431d184a..b659d9c6e 100644 --- a/src/spicelib/devices/Makefile.am +++ b/src/spicelib/devices/Makefile.am @@ -62,7 +62,8 @@ SUBDIRS += nbjt nbjt2 numd numd2 numos endif if WANT_MODSIMD -SUBDIRS += bsim3v32simd +SUBDIRS += bsim3v32simd \ + bsim3simd endif DIST_SUBDIRS = \ @@ -71,6 +72,7 @@ DIST_SUBDIRS = \ bsim1 \ bsim2 \ bsim3 \ + bsim3simd \ bsimsoi \ bsim4 \ bsim4v5 \ diff --git a/src/spicelib/devices/bsim3simd/B3TERMS_OF_USE b/src/spicelib/devices/bsim3simd/B3TERMS_OF_USE new file mode 100644 index 000000000..bc4a61beb --- /dev/null +++ b/src/spicelib/devices/bsim3simd/B3TERMS_OF_USE @@ -0,0 +1,30 @@ + +The terms under which the software is provided are as the following. + +Software is distributed as is, completely without warranty or service +support. The University of California and its employees are not liable +for the condition or performance of the software. + +The University owns the copyright but shall not be liable for any +infringement of copyright or other proprietary rights brought by third +parties against the users of the software. + +The University of California hereby disclaims all implied warranties. + +The University of California grants the users the right to modify, copy, +and redistribute the software and documentation, both within the user's +organization and externally, subject to the following restrictions: + +1. The users agree not to charge for the University of California code + itself but may charge for additions, extensions, or support. + +2. In any product based on the software, the users agree to acknowledge + the UC Berkeley BSIM Research Group that developed the software. This + acknowledgment shall appear in the product documentation. + +3. The users agree to obey all U.S. Government restrictions governing + redistribution or export of the software. + +4. The users agree to reproduce any copyright notice which appears on + the software on any copy or modification of such made available + to others. diff --git a/src/spicelib/devices/bsim3simd/ChangeLog b/src/spicelib/devices/bsim3simd/ChangeLog new file mode 100644 index 000000000..6d1ab39da --- /dev/null +++ b/src/spicelib/devices/bsim3simd/ChangeLog @@ -0,0 +1,4 @@ +1999-09-06 Arno Peters + + * b3ld.c: Removed unused variable. + diff --git a/src/spicelib/devices/bsim3simd/Makefile.am b/src/spicelib/devices/bsim3simd/Makefile.am new file mode 100644 index 000000000..a0dfb6b67 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/Makefile.am @@ -0,0 +1,40 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libbsim3simd.la + +libbsim3simd_la_SOURCES = \ + b3.c \ + b3acld.c \ + b3ask.c \ + b3check.c \ + b3cvtest.c \ + b3getic.c \ + b3ld.c \ + b3mask.c \ + b3mdel.c \ + b3mpar.c \ + b3noi.c \ + b3par.c \ + b3pzld.c \ + b3set.c \ + b3soachk.c \ + b3temp.c \ + b3trunc.c \ + bsim3def.h \ + bsim3ext.h \ + bsim3init.c \ + bsim3init.h \ + bsim3itf.h \ + b3ldseq.c \ + b3ldsel.c \ + b3ldsimd.c + + + + +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include +AM_CFLAGS = $(STATIC) $(SIMD_CFLAGS) + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = B3TERMS_OF_USE diff --git a/src/spicelib/devices/bsim3simd/b3.c b/src/spicelib/devices/bsim3simd/b3.c new file mode 100644 index 000000000..1e8c89897 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3.c @@ -0,0 +1,531 @@ +/**** BSIM3v3.3.0 beta, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/devdefs.h" +#include "bsim3def.h" +#include "ngspice/suffix.h" + +IFparm BSIM3SIMDpTable[] = { /* parameters */ +IOP( "l", BSIM3_L, IF_REAL , "Length"), +IOP( "w", BSIM3_W, IF_REAL , "Width"), +IOP( "m", BSIM3_M, IF_REAL , "Parallel multiplier"), +IOP( "ad", BSIM3_AD, IF_REAL , "Drain area"), +IOP( "as", BSIM3_AS, IF_REAL , "Source area"), +IOP( "pd", BSIM3_PD, IF_REAL , "Drain perimeter"), +IOP( "ps", BSIM3_PS, IF_REAL , "Source perimeter"), +IOP( "nrd", BSIM3_NRD, IF_REAL , "Number of squares in drain"), +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"), +}; + +IFparm BSIM3SIMDmPTable[] = { /* 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"), +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( "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( "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."), +IOP( "nsub", BSIM3_MOD_NSUB, IF_REAL, "Substrate doping concentration"), +IOP( "nch", BSIM3_MOD_NPEAK, IF_REAL, "Channel doping concentration"), +IOP( "ngate", BSIM3_MOD_NGATE, IF_REAL, "Poly-gate doping concentration"), +IOP( "gamma1", BSIM3_MOD_GAMMA1, IF_REAL, "Vth body coefficient"), +IOP( "gamma2", BSIM3_MOD_GAMMA2, IF_REAL, "Vth body coefficient"), +IOP( "vbx", BSIM3_MOD_VBX, IF_REAL, "Vth transition body Voltage"), +IOP( "vbm", BSIM3_MOD_VBM, IF_REAL, "Maximum body voltage"), + +IOP( "xt", BSIM3_MOD_XT, IF_REAL, "Doping depth"), +IOP( "k1", BSIM3_MOD_K1, IF_REAL, "Bulk effect coefficient 1"), +IOP( "kt1", BSIM3_MOD_KT1, IF_REAL, "Temperature coefficient of Vth"), +IOP( "kt1l", BSIM3_MOD_KT1L, IF_REAL, "Temperature coefficient of Vth"), +IOP( "kt2", BSIM3_MOD_KT2, IF_REAL, "Body-coefficient of kt1"), +IOP( "k2", BSIM3_MOD_K2, IF_REAL, "Bulk effect coefficient 2"), +IOP( "k3", BSIM3_MOD_K3, IF_REAL, "Narrow width effect coefficient"), +IOP( "k3b", BSIM3_MOD_K3B, IF_REAL, "Body effect coefficient of k3"), +IOP( "w0", BSIM3_MOD_W0, IF_REAL, "Narrow width effect parameter"), +IOP( "nlx", BSIM3_MOD_NLX, IF_REAL, "Lateral non-uniform doping effect"), +IOP( "dvt0", BSIM3_MOD_DVT0, IF_REAL, "Short channel effect coeff. 0"), +IOP( "dvt1", BSIM3_MOD_DVT1, IF_REAL, "Short channel effect coeff. 1"), +IOP( "dvt2", BSIM3_MOD_DVT2, IF_REAL, "Short channel effect coeff. 2"), +IOP( "dvt0w", BSIM3_MOD_DVT0W, IF_REAL, "Narrow Width coeff. 0"), +IOP( "dvt1w", BSIM3_MOD_DVT1W, IF_REAL, "Narrow Width effect coeff. 1"), +IOP( "dvt2w", BSIM3_MOD_DVT2W, IF_REAL, "Narrow Width effect coeff. 2"), +IOP( "drout", BSIM3_MOD_DROUT, IF_REAL, "DIBL coefficient of output resistance"), +IOP( "dsub", BSIM3_MOD_DSUB, IF_REAL, "DIBL coefficient in the subthreshold region"), +IOP( "vth0", BSIM3_MOD_VTH0, IF_REAL,"Threshold voltage"), +IOPR("vtho", BSIM3_MOD_VTH0, IF_REAL,"Threshold voltage"), +IOP( "ua", BSIM3_MOD_UA, IF_REAL, "Linear gate dependence of mobility"), +IOP( "ua1", BSIM3_MOD_UA1, IF_REAL, "Temperature coefficient of ua"), +IOP( "ub", BSIM3_MOD_UB, IF_REAL, "Quadratic gate dependence of mobility"), +IOP( "ub1", BSIM3_MOD_UB1, IF_REAL, "Temperature coefficient of ub"), +IOP( "uc", BSIM3_MOD_UC, IF_REAL, "Body-bias dependence of mobility"), +IOP( "uc1", BSIM3_MOD_UC1, IF_REAL, "Temperature coefficient of uc"), +IOP( "u0", BSIM3_MOD_U0, IF_REAL, "Low-field mobility at Tnom"), +IOP( "ute", BSIM3_MOD_UTE, IF_REAL, "Temperature coefficient of mobility"), +IOP( "voff", BSIM3_MOD_VOFF, IF_REAL, "Threshold voltage offset"), +IOP( "tnom", BSIM3_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), +IOP( "cgso", BSIM3_MOD_CGSO, IF_REAL, "Gate-source overlap capacitance per width"), +IOP( "cgdo", BSIM3_MOD_CGDO, IF_REAL, "Gate-drain overlap capacitance per width"), +IOP( "cgbo", BSIM3_MOD_CGBO, IF_REAL, "Gate-bulk overlap capacitance per length"), +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( "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( "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( "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"), +IOP( "nj", BSIM3_MOD_NJ, IF_REAL, "Source/drain junction emission coefficient"), +IOP( "xti", BSIM3_MOD_XTI, IF_REAL, "Junction current temperature exponent"), +IOP( "mj", BSIM3_MOD_MJ, IF_REAL, "Source/drain bottom junction capacitance grading coefficient"), +IOP( "pbsw", BSIM3_MOD_PBSW, IF_REAL, "Source/drain sidewall junction capacitance built in potential"), +IOP( "mjsw", BSIM3_MOD_MJSW, IF_REAL, "Source/drain sidewall junction capacitance grading coefficient"), +IOP( "pbswg", BSIM3_MOD_PBSWG, IF_REAL, "Source/drain (gate side) sidewall junction capacitance built in potential"), +IOP( "mjswg", BSIM3_MOD_MJSWG, IF_REAL, "Source/drain (gate side) sidewall junction capacitance grading coefficient"), +IOP( "cj", BSIM3_MOD_CJ, IF_REAL, "Source/drain bottom junction capacitance per unit area"), +IOP( "vfbcv", BSIM3_MOD_VFBCV, IF_REAL, "Flat Band Voltage parameter for capmod=0 only"), +IOP( "vfb", BSIM3_MOD_VFB, IF_REAL, "Flat Band Voltage"), +IOP( "cjsw", BSIM3_MOD_CJSW, IF_REAL, "Source/drain sidewall junction capacitance per unit periphery"), +IOP( "cjswg", BSIM3_MOD_CJSWG, IF_REAL, "Source/drain (gate side) sidewall junction capacitance per unit width"), +IOP( "tpb", BSIM3_MOD_TPB, IF_REAL, "Temperature coefficient of pb"), +IOP( "tcj", BSIM3_MOD_TCJ, IF_REAL, "Temperature coefficient of cj"), +IOP( "tpbsw", BSIM3_MOD_TPBSW, IF_REAL, "Temperature coefficient of pbsw"), +IOP( "tcjsw", BSIM3_MOD_TCJSW, IF_REAL, "Temperature coefficient of cjsw"), +IOP( "tpbswg", BSIM3_MOD_TPBSWG, IF_REAL, "Temperature coefficient of pbswg"), +IOP( "tcjswg", BSIM3_MOD_TCJSWG, IF_REAL, "Temperature coefficient of cjswg"), +IOP( "acde", BSIM3_MOD_ACDE, IF_REAL, "Exponential coefficient for finite charge thickness"), +IOP( "moin", BSIM3_MOD_MOIN, IF_REAL, "Coefficient for gate-bias dependent surface potential"), +IOP( "noff", BSIM3_MOD_NOFF, IF_REAL, "C-V turn-on/off parameter"), +IOP( "voffcv", BSIM3_MOD_VOFFCV, IF_REAL, "C-V lateral-shift parameter"), +IOP( "lintnoi", BSIM3_MOD_LINTNOI, IF_REAL, "lint offset for noise calculation"), +IOP( "lint", BSIM3_MOD_LINT, IF_REAL, "Length reduction parameter"), +IOP( "ll", BSIM3_MOD_LL, IF_REAL, "Length reduction parameter"), +IOP( "llc", BSIM3_MOD_LLC, IF_REAL, "Length reduction parameter for CV"), +IOP( "lln", BSIM3_MOD_LLN, IF_REAL, "Length reduction parameter"), +IOP( "lw", BSIM3_MOD_LW, IF_REAL, "Length reduction parameter"), +IOP( "lwc", BSIM3_MOD_LWC, IF_REAL, "Length reduction parameter for CV"), +IOP( "lwn", BSIM3_MOD_LWN, IF_REAL, "Length reduction parameter"), +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"), +IOP( "dwb", BSIM3_MOD_DWB, IF_REAL, "Width reduction parameter"), + +IOP( "wl", BSIM3_MOD_WL, IF_REAL, "Width reduction parameter"), +IOP( "wlc", BSIM3_MOD_WLC, IF_REAL, "Width reduction parameter for CV"), +IOP( "wln", BSIM3_MOD_WLN, IF_REAL, "Width reduction parameter"), +IOP( "ww", BSIM3_MOD_WW, IF_REAL, "Width reduction parameter"), +IOP( "wwc", BSIM3_MOD_WWC, IF_REAL, "Width reduction parameter for CV"), +IOP( "wwn", BSIM3_MOD_WWN, IF_REAL, "Width reduction parameter"), +IOP( "wwl", BSIM3_MOD_WWL, IF_REAL, "Width reduction parameter"), +IOP( "wwlc", BSIM3_MOD_WWLC, IF_REAL, "Width reduction parameter for CV"), +IOP( "wmin", BSIM3_MOD_WMIN, IF_REAL, "Minimum width for the model"), +IOP( "wmax", BSIM3_MOD_WMAX, IF_REAL, "Maximum width for the model"), + +IOP( "b0", BSIM3_MOD_B0, IF_REAL, "Abulk narrow width parameter"), +IOP( "b1", BSIM3_MOD_B1, IF_REAL, "Abulk narrow width parameter"), + +IOP( "cgsl", BSIM3_MOD_CGSL, IF_REAL, "New C-V model parameter"), +IOP( "cgdl", BSIM3_MOD_CGDL, IF_REAL, "New C-V model parameter"), +IOP( "ckappa", BSIM3_MOD_CKAPPA, IF_REAL, "New C-V model parameter"), +IOP( "cf", BSIM3_MOD_CF, IF_REAL, "Fringe capacitance parameter"), +IOP( "clc", BSIM3_MOD_CLC, IF_REAL, "Vdsat parameter for C-V model"), +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"), +IOP( "ijth", BSIM3_MOD_IJTH, IF_REAL, "Diode limiting current"), + +IOP( "lcdsc", BSIM3_MOD_LCDSC, IF_REAL, "Length dependence of cdsc"), +IOP( "lcdscb", BSIM3_MOD_LCDSCB, IF_REAL, "Length dependence of cdscb"), +IOP( "lcdscd", BSIM3_MOD_LCDSCD, IF_REAL, "Length dependence of cdscd"), +IOP( "lcit", BSIM3_MOD_LCIT, IF_REAL, "Length dependence of cit"), +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( "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"), +IOP( "lnsub", BSIM3_MOD_LNSUB, IF_REAL, "Length dependence of nsub"), +IOP( "lnch", BSIM3_MOD_LNPEAK, IF_REAL, "Length dependence of nch"), +IOP( "lngate", BSIM3_MOD_LNGATE, IF_REAL, "Length dependence of ngate"), +IOP( "lgamma1", BSIM3_MOD_LGAMMA1, IF_REAL, "Length dependence of gamma1"), +IOP( "lgamma2", BSIM3_MOD_LGAMMA2, IF_REAL, "Length dependence of gamma2"), +IOP( "lvbx", BSIM3_MOD_LVBX, IF_REAL, "Length dependence of vbx"), +IOP( "lvbm", BSIM3_MOD_LVBM, IF_REAL, "Length dependence of vbm"), +IOP( "lxt", BSIM3_MOD_LXT, IF_REAL, "Length dependence of xt"), +IOP( "lk1", BSIM3_MOD_LK1, IF_REAL, "Length dependence of k1"), +IOP( "lkt1", BSIM3_MOD_LKT1, IF_REAL, "Length dependence of kt1"), +IOP( "lkt1l", BSIM3_MOD_LKT1L, IF_REAL, "Length dependence of kt1l"), +IOP( "lkt2", BSIM3_MOD_LKT2, IF_REAL, "Length dependence of kt2"), +IOP( "lk2", BSIM3_MOD_LK2, IF_REAL, "Length dependence of k2"), +IOP( "lk3", BSIM3_MOD_LK3, IF_REAL, "Length dependence of k3"), +IOP( "lk3b", BSIM3_MOD_LK3B, IF_REAL, "Length dependence of k3b"), +IOP( "lw0", BSIM3_MOD_LW0, IF_REAL, "Length dependence of w0"), +IOP( "lnlx", BSIM3_MOD_LNLX, IF_REAL, "Length dependence of nlx"), +IOP( "ldvt0", BSIM3_MOD_LDVT0, IF_REAL, "Length dependence of dvt0"), +IOP( "ldvt1", BSIM3_MOD_LDVT1, IF_REAL, "Length dependence of dvt1"), +IOP( "ldvt2", BSIM3_MOD_LDVT2, IF_REAL, "Length dependence of dvt2"), +IOP( "ldvt0w", BSIM3_MOD_LDVT0W, IF_REAL, "Length dependence of dvt0w"), +IOP( "ldvt1w", BSIM3_MOD_LDVT1W, IF_REAL, "Length dependence of dvt1w"), +IOP( "ldvt2w", BSIM3_MOD_LDVT2W, IF_REAL, "Length dependence of dvt2w"), +IOP( "ldrout", BSIM3_MOD_LDROUT, IF_REAL, "Length dependence of drout"), +IOP( "ldsub", BSIM3_MOD_LDSUB, IF_REAL, "Length dependence of dsub"), +IOP( "lvth0", BSIM3_MOD_LVTH0, IF_REAL,"Length dependence of vth0"), +IOPR("lvtho", BSIM3_MOD_LVTH0, IF_REAL,"Length dependence of vtho"), +IOP( "lua", BSIM3_MOD_LUA, IF_REAL, "Length dependence of ua"), +IOP( "lua1", BSIM3_MOD_LUA1, IF_REAL, "Length dependence of ua1"), +IOP( "lub", BSIM3_MOD_LUB, IF_REAL, "Length dependence of ub"), +IOP( "lub1", BSIM3_MOD_LUB1, IF_REAL, "Length dependence of ub1"), +IOP( "luc", BSIM3_MOD_LUC, IF_REAL, "Length dependence of uc"), +IOP( "luc1", BSIM3_MOD_LUC1, IF_REAL, "Length dependence of uc1"), +IOP( "lu0", BSIM3_MOD_LU0, IF_REAL, "Length dependence of u0"), +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( "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( "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"), +IOP( "lb0", BSIM3_MOD_LB0, IF_REAL, "Length dependence of b0"), +IOP( "lb1", BSIM3_MOD_LB1, IF_REAL, "Length dependence of b1"), +IOP( "lcgsl", BSIM3_MOD_LCGSL, IF_REAL, "Length dependence of cgsl"), +IOP( "lcgdl", BSIM3_MOD_LCGDL, IF_REAL, "Length dependence of cgdl"), +IOP( "lckappa", BSIM3_MOD_LCKAPPA, IF_REAL, "Length dependence of ckappa"), +IOP( "lcf", BSIM3_MOD_LCF, IF_REAL, "Length dependence of cf"), +IOP( "lclc", BSIM3_MOD_LCLC, IF_REAL, "Length dependence of clc"), +IOP( "lcle", BSIM3_MOD_LCLE, IF_REAL, "Length dependence of cle"), +IOP( "lalpha0", BSIM3_MOD_LALPHA0, IF_REAL, "Length dependence of alpha0"), +IOP( "lalpha1", BSIM3_MOD_LALPHA1, IF_REAL, "Length dependence of alpha1"), +IOP( "lbeta0", BSIM3_MOD_LBETA0, IF_REAL, "Length dependence of beta0"), +IOP( "lvfbcv", BSIM3_MOD_LVFBCV, IF_REAL, "Length dependence of vfbcv"), +IOP( "lvfb", BSIM3_MOD_LVFB, IF_REAL, "Length dependence of vfb"), +IOP( "lacde", BSIM3_MOD_LACDE, IF_REAL, "Length dependence of acde"), +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( "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( "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"), +IOP( "wnsub", BSIM3_MOD_WNSUB, IF_REAL, "Width dependence of nsub"), +IOP( "wnch", BSIM3_MOD_WNPEAK, IF_REAL, "Width dependence of nch"), +IOP( "wngate", BSIM3_MOD_WNGATE, IF_REAL, "Width dependence of ngate"), +IOP( "wgamma1", BSIM3_MOD_WGAMMA1, IF_REAL, "Width dependence of gamma1"), +IOP( "wgamma2", BSIM3_MOD_WGAMMA2, IF_REAL, "Width dependence of gamma2"), +IOP( "wvbx", BSIM3_MOD_WVBX, IF_REAL, "Width dependence of vbx"), +IOP( "wvbm", BSIM3_MOD_WVBM, IF_REAL, "Width dependence of vbm"), +IOP( "wxt", BSIM3_MOD_WXT, IF_REAL, "Width dependence of xt"), +IOP( "wk1", BSIM3_MOD_WK1, IF_REAL, "Width dependence of k1"), +IOP( "wkt1", BSIM3_MOD_WKT1, IF_REAL, "Width dependence of kt1"), +IOP( "wkt1l", BSIM3_MOD_WKT1L, IF_REAL, "Width dependence of kt1l"), +IOP( "wkt2", BSIM3_MOD_WKT2, IF_REAL, "Width dependence of kt2"), +IOP( "wk2", BSIM3_MOD_WK2, IF_REAL, "Width dependence of k2"), +IOP( "wk3", BSIM3_MOD_WK3, IF_REAL, "Width dependence of k3"), +IOP( "wk3b", BSIM3_MOD_WK3B, IF_REAL, "Width dependence of k3b"), +IOP( "ww0", BSIM3_MOD_WW0, IF_REAL, "Width dependence of w0"), +IOP( "wnlx", BSIM3_MOD_WNLX, IF_REAL, "Width dependence of nlx"), +IOP( "wdvt0", BSIM3_MOD_WDVT0, IF_REAL, "Width dependence of dvt0"), +IOP( "wdvt1", BSIM3_MOD_WDVT1, IF_REAL, "Width dependence of dvt1"), +IOP( "wdvt2", BSIM3_MOD_WDVT2, IF_REAL, "Width dependence of dvt2"), +IOP( "wdvt0w", BSIM3_MOD_WDVT0W, IF_REAL, "Width dependence of dvt0w"), +IOP( "wdvt1w", BSIM3_MOD_WDVT1W, IF_REAL, "Width dependence of dvt1w"), +IOP( "wdvt2w", BSIM3_MOD_WDVT2W, IF_REAL, "Width dependence of dvt2w"), +IOP( "wdrout", BSIM3_MOD_WDROUT, IF_REAL, "Width dependence of drout"), +IOP( "wdsub", BSIM3_MOD_WDSUB, IF_REAL, "Width dependence of dsub"), +IOP( "wvth0", BSIM3_MOD_WVTH0, IF_REAL,"Width dependence of vth0"), +IOPR("wvtho", BSIM3_MOD_WVTH0, IF_REAL,"Width dependence of vtho"), +IOP( "wua", BSIM3_MOD_WUA, IF_REAL, "Width dependence of ua"), +IOP( "wua1", BSIM3_MOD_WUA1, IF_REAL, "Width dependence of ua1"), +IOP( "wub", BSIM3_MOD_WUB, IF_REAL, "Width dependence of ub"), +IOP( "wub1", BSIM3_MOD_WUB1, IF_REAL, "Width dependence of ub1"), +IOP( "wuc", BSIM3_MOD_WUC, IF_REAL, "Width dependence of uc"), +IOP( "wuc1", BSIM3_MOD_WUC1, IF_REAL, "Width dependence of uc1"), +IOP( "wu0", BSIM3_MOD_WU0, IF_REAL, "Width dependence of u0"), +IOP( "wute", BSIM3_MOD_WUTE, IF_REAL, "Width dependence of ute"), +IOP( "wvoff", BSIM3_MOD_WVOFF, IF_REAL, "Width dependence of voff"), +IOP( "welm", BSIM3_MOD_WELM, IF_REAL, "Width dependence of elm"), +IOP( "wdelta", BSIM3_MOD_WDELTA, IF_REAL, "Width dependence of delta"), +IOP( "wrdsw", BSIM3_MOD_WRDSW, IF_REAL, "Width dependence of rdsw "), + +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( "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"), +IOP( "wb0", BSIM3_MOD_WB0, IF_REAL, "Width dependence of b0"), +IOP( "wb1", BSIM3_MOD_WB1, IF_REAL, "Width dependence of b1"), +IOP( "wcgsl", BSIM3_MOD_WCGSL, IF_REAL, "Width dependence of cgsl"), +IOP( "wcgdl", BSIM3_MOD_WCGDL, IF_REAL, "Width dependence of cgdl"), +IOP( "wckappa", BSIM3_MOD_WCKAPPA, IF_REAL, "Width dependence of ckappa"), +IOP( "wcf", BSIM3_MOD_WCF, IF_REAL, "Width dependence of cf"), +IOP( "wclc", BSIM3_MOD_WCLC, IF_REAL, "Width dependence of clc"), +IOP( "wcle", BSIM3_MOD_WCLE, IF_REAL, "Width dependence of cle"), +IOP( "walpha0", BSIM3_MOD_WALPHA0, IF_REAL, "Width dependence of alpha0"), +IOP( "walpha1", BSIM3_MOD_WALPHA1, IF_REAL, "Width dependence of alpha1"), +IOP( "wbeta0", BSIM3_MOD_WBETA0, IF_REAL, "Width dependence of beta0"), +IOP( "wvfbcv", BSIM3_MOD_WVFBCV, IF_REAL, "Width dependence of vfbcv"), +IOP( "wvfb", BSIM3_MOD_WVFB, IF_REAL, "Width dependence of vfb"), +IOP( "wacde", BSIM3_MOD_WACDE, IF_REAL, "Width dependence of acde"), +IOP( "wmoin", BSIM3_MOD_WMOIN, IF_REAL, "Width dependence of moin"), +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( "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( "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"), +IOP( "pketa", BSIM3_MOD_PKETA, IF_REAL, "Cross-term dependence of keta"), +IOP( "pnsub", BSIM3_MOD_PNSUB, IF_REAL, "Cross-term dependence of nsub"), +IOP( "pnch", BSIM3_MOD_PNPEAK, IF_REAL, "Cross-term dependence of nch"), +IOP( "pngate", BSIM3_MOD_PNGATE, IF_REAL, "Cross-term dependence of ngate"), +IOP( "pgamma1", BSIM3_MOD_PGAMMA1, IF_REAL, "Cross-term dependence of gamma1"), +IOP( "pgamma2", BSIM3_MOD_PGAMMA2, IF_REAL, "Cross-term dependence of gamma2"), +IOP( "pvbx", BSIM3_MOD_PVBX, IF_REAL, "Cross-term dependence of vbx"), +IOP( "pvbm", BSIM3_MOD_PVBM, IF_REAL, "Cross-term dependence of vbm"), +IOP( "pxt", BSIM3_MOD_PXT, IF_REAL, "Cross-term dependence of xt"), +IOP( "pk1", BSIM3_MOD_PK1, IF_REAL, "Cross-term dependence of k1"), +IOP( "pkt1", BSIM3_MOD_PKT1, IF_REAL, "Cross-term dependence of kt1"), +IOP( "pkt1l", BSIM3_MOD_PKT1L, IF_REAL, "Cross-term dependence of kt1l"), +IOP( "pkt2", BSIM3_MOD_PKT2, IF_REAL, "Cross-term dependence of kt2"), +IOP( "pk2", BSIM3_MOD_PK2, IF_REAL, "Cross-term dependence of k2"), +IOP( "pk3", BSIM3_MOD_PK3, IF_REAL, "Cross-term dependence of k3"), +IOP( "pk3b", BSIM3_MOD_PK3B, IF_REAL, "Cross-term dependence of k3b"), +IOP( "pw0", BSIM3_MOD_PW0, IF_REAL, "Cross-term dependence of w0"), +IOP( "pnlx", BSIM3_MOD_PNLX, IF_REAL, "Cross-term dependence of nlx"), +IOP( "pdvt0", BSIM3_MOD_PDVT0, IF_REAL, "Cross-term dependence of dvt0"), +IOP( "pdvt1", BSIM3_MOD_PDVT1, IF_REAL, "Cross-term dependence of dvt1"), +IOP( "pdvt2", BSIM3_MOD_PDVT2, IF_REAL, "Cross-term dependence of dvt2"), +IOP( "pdvt0w", BSIM3_MOD_PDVT0W, IF_REAL, "Cross-term dependence of dvt0w"), +IOP( "pdvt1w", BSIM3_MOD_PDVT1W, IF_REAL, "Cross-term dependence of dvt1w"), +IOP( "pdvt2w", BSIM3_MOD_PDVT2W, IF_REAL, "Cross-term dependence of dvt2w"), +IOP( "pdrout", BSIM3_MOD_PDROUT, IF_REAL, "Cross-term dependence of drout"), +IOP( "pdsub", BSIM3_MOD_PDSUB, IF_REAL, "Cross-term dependence of dsub"), +IOP( "pvth0", BSIM3_MOD_PVTH0, IF_REAL,"Cross-term dependence of vth0"), +IOPR("pvtho", BSIM3_MOD_PVTH0, IF_REAL,"Cross-term dependence of vtho"), +IOP( "pua", BSIM3_MOD_PUA, IF_REAL, "Cross-term dependence of ua"), +IOP( "pua1", BSIM3_MOD_PUA1, IF_REAL, "Cross-term dependence of ua1"), +IOP( "pub", BSIM3_MOD_PUB, IF_REAL, "Cross-term dependence of ub"), +IOP( "pub1", BSIM3_MOD_PUB1, IF_REAL, "Cross-term dependence of ub1"), +IOP( "puc", BSIM3_MOD_PUC, IF_REAL, "Cross-term dependence of uc"), +IOP( "puc1", BSIM3_MOD_PUC1, IF_REAL, "Cross-term dependence of uc1"), +IOP( "pu0", BSIM3_MOD_PU0, IF_REAL, "Cross-term dependence of u0"), +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( "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"), +IOP( "petab", BSIM3_MOD_PETAB, IF_REAL, "Cross-term dependence of etab"), +IOP( "ppclm", BSIM3_MOD_PPCLM, IF_REAL, "Cross-term dependence of pclm"), +IOP( "ppdiblc1", BSIM3_MOD_PPDIBL1, IF_REAL, "Cross-term dependence of pdiblc1"), +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( "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"), +IOP( "pb0", BSIM3_MOD_PB0, IF_REAL, "Cross-term dependence of b0"), +IOP( "pb1", BSIM3_MOD_PB1, IF_REAL, "Cross-term dependence of b1"), +IOP( "pcgsl", BSIM3_MOD_PCGSL, IF_REAL, "Cross-term dependence of cgsl"), +IOP( "pcgdl", BSIM3_MOD_PCGDL, IF_REAL, "Cross-term dependence of cgdl"), +IOP( "pckappa", BSIM3_MOD_PCKAPPA, IF_REAL, "Cross-term dependence of ckappa"), +IOP( "pcf", BSIM3_MOD_PCF, IF_REAL, "Cross-term dependence of cf"), +IOP( "pclc", BSIM3_MOD_PCLC, IF_REAL, "Cross-term dependence of clc"), +IOP( "pcle", BSIM3_MOD_PCLE, IF_REAL, "Cross-term dependence of cle"), +IOP( "palpha0", BSIM3_MOD_PALPHA0, IF_REAL, "Cross-term dependence of alpha0"), +IOP( "palpha1", BSIM3_MOD_PALPHA1, IF_REAL, "Cross-term dependence of alpha1"), +IOP( "pbeta0", BSIM3_MOD_PBETA0, IF_REAL, "Cross-term dependence of beta0"), +IOP( "pvfbcv", BSIM3_MOD_PVFBCV, IF_REAL, "Cross-term dependence of vfbcv"), +IOP( "pvfb", BSIM3_MOD_PVFB, IF_REAL, "Cross-term dependence of vfb"), +IOP( "pacde", BSIM3_MOD_PACDE, IF_REAL, "Cross-term dependence of acde"), +IOP( "pmoin", BSIM3_MOD_PMOIN, IF_REAL, "Cross-term dependence of moin"), +IOP( "pnoff", BSIM3_MOD_PNOFF, IF_REAL, "Cross-term dependence of noff"), +IOP( "pvoffcv", BSIM3_MOD_PVOFFCV, IF_REAL, "Cross-term dependence of voffcv"), + +IOP( "noia", BSIM3_MOD_NOIA, IF_REAL, "Flicker noise parameter"), +IOP( "noib", BSIM3_MOD_NOIB, IF_REAL, "Flicker noise parameter"), +IOP( "noic", BSIM3_MOD_NOIC, IF_REAL, "Flicker noise parameter"), +IOP( "em", BSIM3_MOD_EM, IF_REAL, "Flicker noise parameter"), +IOP( "ef", BSIM3_MOD_EF, IF_REAL, "Flicker noise frequency exponent"), +IOP( "af", BSIM3_MOD_AF, IF_REAL, "Flicker noise exponent"), +IOP( "kf", BSIM3_MOD_KF, IF_REAL, "Flicker noise coefficient"), + +IOP("vgs_max", BSIM3_MOD_VGS_MAX, IF_REAL, "maximum voltage G-S branch"), +IOP("vgd_max", BSIM3_MOD_VGD_MAX, IF_REAL, "maximum voltage G-D branch"), +IOP("vgb_max", BSIM3_MOD_VGB_MAX, IF_REAL, "maximum voltage G-B branch"), +IOP("vds_max", BSIM3_MOD_VDS_MAX, IF_REAL, "maximum voltage D-S branch"), +IOP("vbs_max", BSIM3_MOD_VBS_MAX, IF_REAL, "maximum voltage B-S branch"), +IOP("vbd_max", BSIM3_MOD_VBD_MAX, IF_REAL, "maximum voltage B-D branch"), +IOP("vgsr_max", BSIM3_MOD_VGSR_MAX, IF_REAL, "maximum voltage G-S branch"), +IOP("vgdr_max", BSIM3_MOD_VGDR_MAX, IF_REAL, "maximum voltage G-D branch"), +IOP("vgbr_max", BSIM3_MOD_VGBR_MAX, IF_REAL, "maximum voltage G-B branch"), +IOP("vbsr_max", BSIM3_MOD_VBSR_MAX, IF_REAL, "maximum voltage B-S branch"), +IOP("vbdr_max", BSIM3_MOD_VBDR_MAX, IF_REAL, "maximum voltage B-D branch"), + +IP( "nmos", BSIM3_MOD_NMOS, IF_FLAG, "Flag to indicate NMOS"), +IP( "pmos", BSIM3_MOD_PMOS, IF_FLAG, "Flag to indicate PMOS"), +}; + +char *BSIM3SIMDnames[] = { + "Drain", + "Gate", + "Source", + "Bulk", + "Charge" +}; + +int BSIM3SIMDnSize = NUMELEMS(BSIM3SIMDnames); +int BSIM3SIMDpTSize = NUMELEMS(BSIM3SIMDpTable); +int BSIM3SIMDmPTSize = NUMELEMS(BSIM3SIMDmPTable); +int BSIM3SIMDiSize = sizeof(BSIM3instance); +int BSIM3SIMDmSize = sizeof(BSIM3model); diff --git a/src/spicelib/devices/bsim3simd/b3acld.c b/src/spicelib/devices/bsim3simd/b3acld.c new file mode 100644 index 000000000..c5678bc5b --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3acld.c @@ -0,0 +1,460 @@ +/**** BSIM3v3.3.0 beta, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3acld.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDacLoad( +GENmodel *inModel, +CKTcircuit *ckt) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; +double xcggb, xcgdb, xcgsb, xcbgb, xcbdb, xcbsb, xcddb, xcssb, xcdgb; +double gdpr, gspr, gds, gbd, gbs, capbd, capbs, xcsgb, xcdsb, xcsdb; +double cggb, cgdb, cgsb, cbgb, cbdb, cbsb, cddb, cdgb, cdsb, omega; +double GSoverlapCap, GDoverlapCap, GBoverlapCap, FwdSum, RevSum, Gm, Gmbs; +double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb=0.0, xcqdb=0.0, xcqsb=0.0, xcqbb=0.0; +double gbspsp, gbbdp, gbbsp, gbspg, gbspb; +double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; +double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; +double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; +double T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; +double ScalingFactor = 1.0e-9; +/* For ACNQSMOD */ +double T0, T2, T3, gmr, gmbsr, gmi, gmbsi, gdsi; +double Cddr, Cdgr, Cdsr, Csdr, Csgr, Cssr, Cgdr, Cggr, Cgsr; +double Cddi, Cdgi, Cdsi, Cdbi, Csdi, Csgi, Cssi, Csbi; +double Cgdi, Cggi, Cgsi, Cgbi, Gmi, Gmbsi, FwdSumi, RevSumi; +double xcdgbi, xcsgbi, xcddbi, xcdsbi, xcsdbi, xcssbi, xcdbbi; +double xcsbbi, xcggbi, xcgdbi, xcgsbi, xcgbbi; +double m; + + omega = ckt->CKTomega; + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { for (here = BSIM3SIMDinstances(model); here!= NULL; + here = BSIM3SIMDnextInstance(here)) + { + Csd = -(here->BSIM3cddb + here->BSIM3cgdb + here->BSIM3cbdb); + Csg = -(here->BSIM3cdgb + here->BSIM3cggb + here->BSIM3cbgb); + Css = -(here->BSIM3cdsb + here->BSIM3cgsb + here->BSIM3cbsb); + + if (here->BSIM3acnqsMod) + { T0 = omega * here->BSIM3taunet; + T1 = T0 * T0; + T2 = 1.0 / (1.0 + T1); + T3 = T0 * T2; + + gmr = here->BSIM3gm * T2; + gmbsr = here->BSIM3gmbs * T2; + gds = here->BSIM3gds * T2; + + gmi = -here->BSIM3gm * T3; + gmbsi = -here->BSIM3gmbs * T3; + gdsi = -here->BSIM3gds * T3; + + Cddr = here->BSIM3cddb * T2; + Cdgr = here->BSIM3cdgb * T2; + Cdsr = here->BSIM3cdsb * T2; + + Cddi = here->BSIM3cddb * T3 * omega; + Cdgi = here->BSIM3cdgb * T3 * omega; + Cdsi = here->BSIM3cdsb * T3 * omega; + Cdbi = -(Cddi + Cdgi + Cdsi); + + Csdr = Csd * T2; + Csgr = Csg * T2; + Cssr = Css * T2; + + Csdi = Csd * T3 * omega; + Csgi = Csg * T3 * omega; + Cssi = Css * T3 * omega; + Csbi = -(Csdi + Csgi + Cssi); + + Cgdr = -(Cddr + Csdr + here->BSIM3cbdb); + Cggr = -(Cdgr + Csgr + here->BSIM3cbgb); + Cgsr = -(Cdsr + Cssr + here->BSIM3cbsb); + + Cgdi = -(Cddi + Csdi); + Cggi = -(Cdgi + Csgi); + Cgsi = -(Cdsi + Cssi); + Cgbi = -(Cgdi + Cggi + Cgsi); + } + else /* QS */ + { gmr = here->BSIM3gm; + gmbsr = here->BSIM3gmbs; + gds = here->BSIM3gds; + gmi = gmbsi = gdsi = 0.0; + + Cddr = here->BSIM3cddb; + Cdgr = here->BSIM3cdgb; + Cdsr = here->BSIM3cdsb; + Cddi = Cdgi = Cdsi = Cdbi = 0.0; + + Csdr = Csd; + Csgr = Csg; + Cssr = Css; + Csdi = Csgi = Cssi = Csbi = 0.0; + + Cgdr = here->BSIM3cgdb; + Cggr = here->BSIM3cggb; + Cgsr = here->BSIM3cgsb; + Cgdi = Cggi = Cgsi = Cgbi = 0.0; + } + + if (here->BSIM3mode >= 0) + { Gm = gmr; + Gmbs = gmbsr; + FwdSum = Gm + Gmbs; + RevSum = 0.0; + Gmi = gmi; + Gmbsi = gmbsi; + FwdSumi = Gmi + Gmbsi; + RevSumi = 0.0; + + gbbdp = -here->BSIM3gbds; + gbbsp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + + gbdpg = here->BSIM3gbgs; + gbdpb = here->BSIM3gbbs; + gbdpdp = here->BSIM3gbds; + gbdpsp = -(gbdpg + gbdpb + gbdpdp); + + gbspdp = 0.0; + gbspg = 0.0; + gbspb = 0.0; + gbspsp = 0.0; + + if (here->BSIM3nqsMod == 0 || here->BSIM3acnqsMod == 1) + { cggb = Cggr; + cgsb = Cgsr; + cgdb = Cgdr; + + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbsb; + cbdb = here->BSIM3cbdb; + + cdgb = Cdgr; + cdsb = Cdsr; + cddb = Cddr; + + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.6; + dxpart = 0.4; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; + + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gtd; + xgts = here->BSIM3gts; + xgtb = here->BSIM3gtb; + + xcqgb = here->BSIM3cqgb * omega; + xcqdb = here->BSIM3cqdb * omega; + xcqsb = here->BSIM3cqsb * omega; + xcqbb = here->BSIM3cqbb * omega; + + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = here->BSIM3qdrn / qcheq; + Cdd = here->BSIM3cddb; + Csd = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3cdgb; + Csg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + + 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); + } + xcdgbi = Cdgi; + xcsgbi = Csgi; + xcddbi = Cddi; + xcdsbi = Cdsi; + xcsdbi = Csdi; + xcssbi = Cssi; + xcdbbi = Cdbi; + xcsbbi = Csbi; + xcggbi = Cggi; + xcgdbi = Cgdi; + xcgsbi = Cgsi; + xcgbbi = Cgbi; + } + else + { Gm = -gmr; + Gmbs = -gmbsr; + FwdSum = 0.0; + RevSum = -(Gm + Gmbs); + Gmi = -gmi; + Gmbsi = -gmbsi; + FwdSumi = 0.0; + RevSumi = -(Gmi + Gmbsi); + + gbbsp = -here->BSIM3gbds; + gbbdp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + + gbdpg = 0.0; + gbdpsp = 0.0; + gbdpb = 0.0; + gbdpdp = 0.0; + + gbspg = here->BSIM3gbgs; + gbspsp = here->BSIM3gbds; + gbspb = here->BSIM3gbbs; + gbspdp = -(gbspg + gbspsp + gbspb); + + if (here->BSIM3nqsMod == 0 || here->BSIM3acnqsMod == 1) + { cggb = Cggr; + cgsb = Cgdr; + cgdb = Cgsr; + + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbdb; + cbdb = here->BSIM3cbsb; + + cdgb = -(Cdgr + cggb + cbgb); + cdsb = -(Cddr + cgsb + cbsb); + cddb = -(Cdsr + cgdb + cbdb); + + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.4; + dxpart = 0.6; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; + + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gts; + xgts = here->BSIM3gtd; + xgtb = here->BSIM3gtb; + + xcqgb = here->BSIM3cqgb * omega; + xcqdb = here->BSIM3cqsb * omega; + xcqsb = here->BSIM3cqdb * omega; + xcqbb = here->BSIM3cqbb * omega; + + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = here->BSIM3qdrn / qcheq; + Css = here->BSIM3cddb; + Cds = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3cdgb; + Cdg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + + Csd = here->BSIM3cdsb; + Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + + 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); + } + xcdgbi = Csgi; + xcsgbi = Cdgi; + xcddbi = Cssi; + xcdsbi = Csdi; + xcsdbi = Cdsi; + xcssbi = Cddi; + xcdbbi = Csbi; + xcsbbi = Cdbi; + xcggbi = Cggi; + xcgdbi = Cgsi; + xcgsbi = Cgdi; + xcgbbi = Cgbi; + } + + T1 = *(ckt->CKTstate0 + here->BSIM3qdef) * here->BSIM3gtau; + gdpr = here->BSIM3drainConductance; + gspr = here->BSIM3sourceConductance; + gbd = here->BSIM3gbd; + gbs = here->BSIM3gbs; + capbd = here->BSIM3capbd; + capbs = here->BSIM3capbs; + + GSoverlapCap = here->BSIM3cgso; + GDoverlapCap = here->BSIM3cgdo; + GBoverlapCap = here->pParam->BSIM3cgbo; + + xcdgb = (cdgb - GDoverlapCap) * omega; + xcddb = (cddb + capbd + GDoverlapCap) * omega; + xcdsb = cdsb * omega; + xcsgb = -(cggb + cbgb + cdgb + GSoverlapCap) * omega; + xcsdb = -(cgdb + cbdb + cddb) * omega; + xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)) * omega; + xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap) + * omega; + xcgdb = (cgdb - GDoverlapCap ) * omega; + xcgsb = (cgsb - GSoverlapCap) * omega; + xcbgb = (cbgb - GBoverlapCap) * omega; + xcbdb = (cbdb - capbd ) * omega; + xcbsb = (cbsb - capbs ) * omega; + + m = here->BSIM3m; + + *(here->BSIM3GgPtr +1) += m * xcggb; + *(here->BSIM3BbPtr +1) -= m * (xcbgb + xcbdb + xcbsb); + *(here->BSIM3DPdpPtr +1) += m * (xcddb + gdsi + RevSumi); + *(here->BSIM3SPspPtr +1) += m * (xcssb + gdsi + FwdSumi); + *(here->BSIM3GbPtr +1) -= m * (xcggb + xcgdb + xcgsb); + *(here->BSIM3GdpPtr +1) += m * xcgdb; + *(here->BSIM3GspPtr +1) += m * xcgsb; + *(here->BSIM3BgPtr +1) += m * xcbgb; + *(here->BSIM3BdpPtr +1) += m * xcbdb; + *(here->BSIM3BspPtr +1) += m * xcbsb; + *(here->BSIM3DPgPtr +1) += m * (xcdgb + Gmi); + *(here->BSIM3DPbPtr +1) -= m * (xcdgb + xcddb + xcdsb + Gmbsi); + *(here->BSIM3DPspPtr +1) += m * (xcdsb - gdsi - FwdSumi); + *(here->BSIM3SPgPtr +1) += m * (xcsgb - Gmi); + *(here->BSIM3SPbPtr +1) -= m * (xcsgb + xcsdb + xcssb - Gmbsi); + *(here->BSIM3SPdpPtr +1) += m * (xcsdb - gdsi - RevSumi); + + *(here->BSIM3DdPtr) += m * gdpr; + *(here->BSIM3SsPtr) += m * gspr; + *(here->BSIM3BbPtr) += m * (gbd + gbs - here->BSIM3gbbs); + *(here->BSIM3DPdpPtr) += m * (gdpr + gds + gbd + RevSum + xcddbi + + dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp); + *(here->BSIM3SPspPtr) += m * (gspr + gds + gbs + FwdSum + xcssbi + + sxpart * xgts + T1 * dsxpart_dVs + gbspsp); + + *(here->BSIM3DdpPtr) -= m * gdpr; + *(here->BSIM3SspPtr) -= m * gspr; + + *(here->BSIM3BgPtr) -= m * here->BSIM3gbgs; + *(here->BSIM3BdpPtr) -= m * (gbd - gbbdp); + *(here->BSIM3BspPtr) -= m * (gbs - gbbsp); + + *(here->BSIM3DPdPtr) -= m * gdpr; + *(here->BSIM3DPgPtr) += m * (Gm + dxpart * xgtg + T1 * ddxpart_dVg + + gbdpg + xcdgbi); + *(here->BSIM3DPbPtr) -= m * (gbd - Gmbs - dxpart * xgtb + - T1 * ddxpart_dVb - gbdpb - xcdbbi); + *(here->BSIM3DPspPtr) -= m * (gds + FwdSum - dxpart * xgts + - T1 * ddxpart_dVs - gbdpsp - xcdsbi); + + *(here->BSIM3SPgPtr) -= m * (Gm - sxpart * xgtg - T1 * dsxpart_dVg + - gbspg - xcsgbi); + *(here->BSIM3SPsPtr) -= m * gspr; + *(here->BSIM3SPbPtr) -= m * (gbs + Gmbs - sxpart * xgtb + - T1 * dsxpart_dVb - gbspb - xcsbbi); + *(here->BSIM3SPdpPtr) -= m * (gds + RevSum - sxpart * xgtd + - T1 * dsxpart_dVd - gbspdp - xcsdbi); + + *(here->BSIM3GgPtr) -= m * (xgtg - xcggbi); + *(here->BSIM3GbPtr) -= m * (xgtb - xcgbbi); + *(here->BSIM3GdpPtr) -= m * (xgtd - xcgdbi); + *(here->BSIM3GspPtr) -= m * (xgts - xcgsbi); + + if (here->BSIM3nqsMod) + { if (here->BSIM3acnqsMod) + { (*(here->BSIM3QqPtr) += m * 1.0); + (*(here->BSIM3QgPtr) += 0.0); + (*(here->BSIM3QdpPtr) += 0.0); + (*(here->BSIM3QspPtr) += 0.0); + (*(here->BSIM3QbPtr) += 0.0); + + (*(here->BSIM3DPqPtr) += 0.0); + (*(here->BSIM3SPqPtr) += 0.0); + (*(here->BSIM3GqPtr) += 0.0); + + } else { + *(here->BSIM3QqPtr +1) += m * omega * ScalingFactor; + *(here->BSIM3QgPtr +1) -= m * xcqgb; + *(here->BSIM3QdpPtr +1) -= m * xcqdb; + *(here->BSIM3QspPtr +1) -= m * xcqsb; + *(here->BSIM3QbPtr +1) -= m * xcqbb; + + *(here->BSIM3QqPtr) += m * here->BSIM3gtau; + + *(here->BSIM3DPqPtr) += m * dxpart * here->BSIM3gtau; + *(here->BSIM3SPqPtr) += m * sxpart * here->BSIM3gtau; + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + + *(here->BSIM3QgPtr) += m * xgtg; + *(here->BSIM3QdpPtr) += m * xgtd; + *(here->BSIM3QspPtr) += m * xgts; + *(here->BSIM3QbPtr) += m * xgtb; + } + } + } + } + return(OK); +} + diff --git a/src/spicelib/devices/bsim3simd/b3ask.c b/src/spicelib/devices/bsim3simd/b3ask.c new file mode 100644 index 000000000..fb26aa507 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ask.c @@ -0,0 +1,243 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3ask.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/ifsim.h" +#include "ngspice/cktdefs.h" +#include "ngspice/devdefs.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + +int +BSIM3SIMDask( +CKTcircuit *ckt, +GENinstance *inst, +int which, +IFvalue *value, +IFvalue *select) +{ +BSIM3instance *here = (BSIM3instance*)inst; + + NG_IGNORE(select); + + switch(which) + { case BSIM3_L: + value->rValue = here->BSIM3l; + return(OK); + case BSIM3_W: + value->rValue = here->BSIM3w; + return(OK); + case BSIM3_M: + value->rValue = here->BSIM3m; + return(OK); + case BSIM3_AS: + value->rValue = here->BSIM3sourceArea; + return(OK); + case BSIM3_AD: + value->rValue = here->BSIM3drainArea; + return(OK); + case BSIM3_PS: + value->rValue = here->BSIM3sourcePerimeter; + return(OK); + case BSIM3_PD: + value->rValue = here->BSIM3drainPerimeter; + return(OK); + case BSIM3_NRS: + value->rValue = here->BSIM3sourceSquares; + return(OK); + case BSIM3_NRD: + value->rValue = here->BSIM3drainSquares; + return(OK); + case BSIM3_OFF: + value->rValue = here->BSIM3off; + return(OK); + case BSIM3_NQSMOD: + value->iValue = here->BSIM3nqsMod; + return(OK); + 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); + case BSIM3_IC_VDS: + value->rValue = here->BSIM3icVDS; + return(OK); + case BSIM3_IC_VGS: + value->rValue = here->BSIM3icVGS; + return(OK); + case BSIM3_DNODE: + value->iValue = here->BSIM3dNode; + return(OK); + case BSIM3_GNODE: + value->iValue = here->BSIM3gNode; + return(OK); + case BSIM3_SNODE: + value->iValue = here->BSIM3sNode; + return(OK); + case BSIM3_BNODE: + value->iValue = here->BSIM3bNode; + return(OK); + case BSIM3_DNODEPRIME: + value->iValue = here->BSIM3dNodePrime; + return(OK); + case BSIM3_SNODEPRIME: + value->iValue = here->BSIM3sNodePrime; + return(OK); + case BSIM3_SOURCECONDUCT: + value->rValue = here->BSIM3sourceConductance; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_DRAINCONDUCT: + value->rValue = here->BSIM3drainConductance; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_VBD: + value->rValue = *(ckt->CKTstate0 + here->BSIM3vbd); + return(OK); + case BSIM3_VBS: + value->rValue = *(ckt->CKTstate0 + here->BSIM3vbs); + return(OK); + case BSIM3_VGS: + value->rValue = *(ckt->CKTstate0 + here->BSIM3vgs); + return(OK); + case BSIM3_VDS: + value->rValue = *(ckt->CKTstate0 + here->BSIM3vds); + return(OK); + case BSIM3_CD: + value->rValue = here->BSIM3cd; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CBS: + value->rValue = here->BSIM3cbs; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CBD: + value->rValue = here->BSIM3cbd; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_GM: + value->rValue = here->BSIM3gm; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_GDS: + value->rValue = here->BSIM3gds; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_GMBS: + value->rValue = here->BSIM3gmbs; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_GBD: + value->rValue = here->BSIM3gbd; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_GBS: + value->rValue = here->BSIM3gbs; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_QB: + value->rValue = *(ckt->CKTstate0 + here->BSIM3qb); + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CQB: + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqb); + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_QG: + value->rValue = *(ckt->CKTstate0 + here->BSIM3qg); + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CQG: + 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; + return(OK); + case BSIM3_CQD: + value->rValue = *(ckt->CKTstate0 + here->BSIM3cqd); + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CGG: + value->rValue = here->BSIM3cggb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CGD: + value->rValue = here->BSIM3cgdb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CGS: + value->rValue = here->BSIM3cgsb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CDG: + value->rValue = here->BSIM3cdgb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CDD: + value->rValue = here->BSIM3cddb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CDS: + value->rValue = here->BSIM3cdsb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CBG: + value->rValue = here->BSIM3cbgb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CBDB: + value->rValue = here->BSIM3cbdb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CBSB: + value->rValue = here->BSIM3cbsb; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CAPBD: + value->rValue = here->BSIM3capbd; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_CAPBS: + value->rValue = here->BSIM3capbs; + value->rValue *= here->BSIM3m; + return(OK); + case BSIM3_VON: + value->rValue = here->BSIM3von; + return(OK); + case BSIM3_VDSAT: + value->rValue = here->BSIM3vdsat; + return(OK); + case BSIM3_QBS: + 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; + return(OK); + default: + return(E_BADPARM); + } + /* NOTREACHED */ +} + diff --git a/src/spicelib/devices/bsim3simd/b3check.c b/src/spicelib/devices/bsim3simd/b3check.c new file mode 100644 index 000000000..219678a03 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3check.c @@ -0,0 +1,455 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3check.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi. + * Modified by Xuemei Xi, 10/05, 12/14, 2001. + * Modified by Xuemei Xi, 07/29/2005. + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +int +BSIM3SIMDcheckModel( +BSIM3model *model, +BSIM3instance *here, +CKTcircuit *ckt) +{ +struct bsim3SizeDependParam *pParam; +int Fatal_Flag = 0; +FILE *fplog; + + NG_IGNORE(ckt); + + if ((fplog = fopen("b3v33check.log", "w")) != NULL) + { pParam = here->pParam; + fprintf(fplog, "BSIM3v3.3.0 Parameter Checking.\n"); + 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; + } + + 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", + model->BSIM3toxm); + printf("Fatal: Toxm = %g is not positive.\n", model->BSIM3toxm); + Fatal_Flag = 1; + } + + if (model->BSIM3lintnoi > pParam->BSIM3leff/2) + { fprintf(fplog, "Fatal: Lintnoi = %g is too large - Leff for noise is negative.\n", + model->BSIM3lintnoi); + printf("Fatal: Lintnoi = %g is too large - Leff for noise is negative.\n", + model->BSIM3lintnoi); + 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->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; + } + +/* 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; + } + + 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->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", + pParam->BSIM3pscbe2); + printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3pscbe2); + } + + /* 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", + pParam->BSIM3noff); + printf("Warning: Noff = %g is too small.\n", pParam->BSIM3noff); + } + if (pParam->BSIM3noff > 4.0) + { fprintf(fplog, "Warning: Noff = %g is too large.\n", + pParam->BSIM3noff); + printf("Warning: Noff = %g is too large.\n", pParam->BSIM3noff); + } + + if (pParam->BSIM3voffcv < -0.5) + { fprintf(fplog, "Warning: Voffcv = %g is too small.\n", + pParam->BSIM3voffcv); + printf("Warning: Voffcv = %g is too small.\n", pParam->BSIM3voffcv); + } + if (pParam->BSIM3voffcv > 0.5) + { fprintf(fplog, "Warning: Voffcv = %g is too large.\n", + pParam->BSIM3voffcv); + printf("Warning: Voffcv = %g is too large.\n", pParam->BSIM3voffcv); + } + + if (model->BSIM3ijth < 0.0) + { fprintf(fplog, "Fatal: Ijth = %g cannot be negative.\n", + model->BSIM3ijth); + printf("Fatal: Ijth = %g cannot be negative.\n", model->BSIM3ijth); + Fatal_Flag = 1; + } + +/* 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; + } + + if (pParam->BSIM3moin < 5.0) + { fprintf(fplog, "Warning: Moin = %g is too small.\n", + pParam->BSIM3moin); + printf("Warning: Moin = %g is too small.\n", pParam->BSIM3moin); + } + if (pParam->BSIM3moin > 25.0) + { fprintf(fplog, "Warning: Moin = %g is too large.\n", + pParam->BSIM3moin); + 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->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->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); + } + +/* 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 (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); + } + + 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->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"); + } + +/* 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); + } +/* 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"); + } + + +/* 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->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); + printf("Warning: Rds at current temperature = %g is negative. Set to zero.\n", + pParam->BSIM3rds0); + 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->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; + } + 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; + } + 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; + } + + }/* loop for the parameter check for warning messages */ + fclose(fplog); + } + else + { fprintf(stderr, "Warning: Can't open log file. Parameter checking skipped.\n"); + } + + return(Fatal_Flag); +} + diff --git a/src/spicelib/devices/bsim3simd/b3cvtest.c b/src/spicelib/devices/bsim3simd/b3cvtest.c new file mode 100644 index 000000000..7b544fdfc --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3cvtest.c @@ -0,0 +1,107 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3cvtest.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/const.h" +#include "ngspice/devdefs.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDconvTest( +GENmodel *inModel, +CKTcircuit *ckt) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; +double delvbd, delvbs, delvds, delvgd, delvgs, vbd, vbs, vds; +double cbd, cbhat, cbs, cd, cdhat, tol, vgd, vgdo, vgs; + + /* loop through all the BSIM3 device models */ + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { /* loop through all the instances of the model */ + for (here = BSIM3SIMDinstances(model); here != NULL ; + here=BSIM3SIMDnextInstance(here)) + { + vbs = model->BSIM3type + * (*(ckt->CKTrhsOld+here->BSIM3bNode) + - *(ckt->CKTrhsOld+here->BSIM3sNodePrime)); + vgs = model->BSIM3type + * (*(ckt->CKTrhsOld+here->BSIM3gNode) + - *(ckt->CKTrhsOld+here->BSIM3sNodePrime)); + vds = model->BSIM3type + * (*(ckt->CKTrhsOld+here->BSIM3dNodePrime) + - *(ckt->CKTrhsOld+here->BSIM3sNodePrime)); + vbd = vbs - vds; + vgd = vgs - vds; + vgdo = *(ckt->CKTstate0 + here->BSIM3vgs) + - *(ckt->CKTstate0 + here->BSIM3vds); + delvbs = vbs - *(ckt->CKTstate0 + here->BSIM3vbs); + delvbd = vbd - *(ckt->CKTstate0 + here->BSIM3vbd); + delvgs = vgs - *(ckt->CKTstate0 + here->BSIM3vgs); + delvds = vds - *(ckt->CKTstate0 + here->BSIM3vds); + delvgd = vgd-vgdo; + + cd = here->BSIM3cd - here->BSIM3cbd; + if (here->BSIM3mode >= 0) + { cd += here->BSIM3csub; + cdhat = cd - here->BSIM3gbd * delvbd + + (here->BSIM3gmbs + here->BSIM3gbbs) * delvbs + + (here->BSIM3gm + here->BSIM3gbgs) * delvgs + + (here->BSIM3gds + here->BSIM3gbds) * delvds; + } + else + { cdhat = cd + (here->BSIM3gmbs - here->BSIM3gbd) * delvbd + + here->BSIM3gm * delvgd - here->BSIM3gds * delvds; + } + + /* + * check convergence + */ + if ((here->BSIM3off == 0) || (!(ckt->CKTmode & MODEINITFIX))) + { tol = ckt->CKTreltol * MAX(fabs(cdhat), fabs(cd)) + + ckt->CKTabstol; + if (fabs(cdhat - cd) >= tol) + { ckt->CKTnoncon++; + return(OK); + } + cbs = here->BSIM3cbs; + cbd = here->BSIM3cbd; + if (here->BSIM3mode >= 0) + { cbhat = cbs + cbd - here->BSIM3csub + + here->BSIM3gbd * delvbd + + (here->BSIM3gbs - here->BSIM3gbbs) * delvbs + - here->BSIM3gbgs * delvgs + - here->BSIM3gbds * delvds; + } + else + { cbhat = cbs + cbd - here->BSIM3csub + + here->BSIM3gbs * delvbs + + (here->BSIM3gbd - here->BSIM3gbbs) * delvbd + - here->BSIM3gbgs * delvgd + + here->BSIM3gbds * delvds; + } + tol = ckt->CKTreltol * MAX(fabs(cbhat), + fabs(cbs + cbd - here->BSIM3csub)) + ckt->CKTabstol; + if (fabs(cbhat - (cbs + cbd - here->BSIM3csub)) > tol) + { ckt->CKTnoncon++; + return(OK); + } + } + } + } + return(OK); +} + + diff --git a/src/spicelib/devices/bsim3simd/b3getic.c b/src/spicelib/devices/bsim3simd/b3getic.c new file mode 100644 index 000000000..06cda308b --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3getic.c @@ -0,0 +1,44 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3getic.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDgetic( +GENmodel *inModel, +CKTcircuit *ckt) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; + + for (; model ; model = BSIM3SIMDnextModel(model)) + { for (here = BSIM3SIMDinstances(model); here; here = BSIM3SIMDnextInstance(here)) + { + if (!here->BSIM3icVBSGiven) + { here->BSIM3icVBS = *(ckt->CKTrhs + here->BSIM3bNode) + - *(ckt->CKTrhs + here->BSIM3sNode); + } + if (!here->BSIM3icVDSGiven) + { here->BSIM3icVDS = *(ckt->CKTrhs + here->BSIM3dNode) + - *(ckt->CKTrhs + here->BSIM3sNode); + } + if (!here->BSIM3icVGSGiven) + { here->BSIM3icVGS = *(ckt->CKTrhs + here->BSIM3gNode) + - *(ckt->CKTrhs + here->BSIM3sNode); + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/bsim3simd/b3ld.c b/src/spicelib/devices/bsim3simd/b3ld.c new file mode 100644 index 000000000..b48d197ee --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ld.c @@ -0,0 +1,3187 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3ld.c of BSIM3v3.3.0 + * Author: 1991 JianHui Huang and Min-Chie Jeng. + * Modified by Mansun Chan (1995). + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + * Modified by Xuemei Xi, 10/05, 12/21, 2001. + * Modified by Xuemei Xi, 07/29/2005. + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define EPSOX 3.453133e-11 +#define EPSSI 1.03594e-10 +#define Charge_q 1.60219e-19 +#define DELTA_1 0.02 +#define DELTA_2 0.02 +#define DELTA_3 0.02 +#define DELTA_4 0.02 + +#ifdef USE_OMP +int BSIM3SIMDLoadOMP(BSIM3instance *here, CKTcircuit *ckt); +void BSIM3SIMDLoadRhsMat(GENmodel *inModel, CKTcircuit *ckt); +#endif + + +int +BSIM3SIMDload( +GENmodel *inModel, +CKTcircuit *ckt) +{ +#ifdef USE_OMP + int idx; + BSIM3model *model = (BSIM3model*)inModel; + int error = 0; + BSIM3instance **InstArray; + InstArray = model->BSIM3InstanceArray; + +#pragma omp parallel for + for (idx = 0; idx < model->BSIM3InstCount; idx++) { + BSIM3instance *here = InstArray[idx]; + int local_error = BSIM3SIMDLoadOMP(here, ckt); + if (local_error) + error = local_error; + } + + BSIM3SIMDLoadRhsMat(inModel, ckt); + + return error; +} + + +int BSIM3SIMDLoadOMP(BSIM3instance *here, CKTcircuit *ckt) { +BSIM3model *model = BSIM3SIMDmodPtr(here); +#else +BSIM3model *model = (BSIM3model*)inModel; +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 czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; +double delvbd, delvbs, delvds, delvgd, delvgs; +double Vfbeff, dVfbeff_dVg, dVfbeff_dVb, V3, V4; +double gcbdb, gcbgb, gcbsb, gcddb, gcdgb, gcdsb, gcgdb, gcggb, gcgsb, gcsdb; +#ifndef NEWCONV +double tol; +#endif +double gcsgb, gcssb, MJ, MJSW, MJSWG; +double vbd, vbs, vds, vgb, vgd, vgs, vgdo; +#ifndef PREDICTOR +double xfact; +#endif +double qgate=0.0, qbulk=0.0, qdrn=0.0, qsrc, qinoi, cqgate, cqbulk, cqdrn; +double Vds, Vgs, Vbs, Gmbs, FwdSum, RevSum; +double Vgs_eff, Vfb; +double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb, Vth, dVth_dVb, dVth_dVd; +double Vgst, dVgst_dVg, dVgst_dVb, dVgs_eff_dVg, Nvtm; +double Vtm; +double n, dn_dVb, dn_dVd, voffcv, noff, dnoff_dVd, dnoff_dVb; +double ExpArg, V0, CoxWLcen, QovCox, LINK; +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 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 T0, dT0_dVg, dT0_dVd, dT0_dVb; +double T1, dT1_dVg, dT1_dVd, dT1_dVb; +double T2, dT2_dVg, dT2_dVd, dT2_dVb; +double T3, dT3_dVg, dT3_dVd, dT3_dVb; +double T4; +double T5; +double T6; +double T7; +double T8; +double T9; +double T10; +double T11, T12; +double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb; + +double VACLM, dVACLM_dVg, dVACLM_dVd, dVACLM_dVb; +double VADIBL, dVADIBL_dVg, dVADIBL_dVd, dVADIBL_dVb; + +double Xdep, dXdep_dVb, lt1, dlt1_dVb, ltw, dltw_dVb, Delt_vth, dDelt_vth_dVb; +double Theta0, dTheta0_dVb; +double TempRatio, tmp1, tmp2, tmp3, tmp4; +double DIBL_Sft, dDIBL_Sft_dVd, Lambda, dLambda_dVg; + +double Idtot, Ibtot; +#ifndef NOBYPASS +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 diffVds, dAbulk_dVg; +double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; +double gche, dgche_dVg, dgche_dVd, dgche_dVb; +double fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb; +double fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb; +double Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb; +double Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb; +double Ids, Gm, Gds, Gmb; +double Isub, Gbd, Gbg, Gbb; +double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb; +double CoxWovL; +double Rds, dRds_dVg, dRds_dVb, WVCox, WVCoxRds; +double Vgst2Vtm, VdsatCV, dVdsatCV_dVg, dVdsatCV_dVb; +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 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 Cgg, Cgd, Cgb, Cdg, Cdd, Cds; +double Csg, Csd, Css, Csb, Cbg, Cbd, Cbb; +double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0; +double dQac0_dVg, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; + +double m; + +struct bsim3SizeDependParam *pParam; +int ByPass, Check, ChargeComputationNeeded, error; +/* double junk[50]; */ + +ScalingFactor = 1.0e-9; +ChargeComputationNeeded = + ((ckt->CKTmode & (MODEDCTRANCURVE | MODEAC | MODETRAN | MODEINITSMSIG)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) + ? 1 : 0; +#ifndef USE_OMP +for (; model != NULL; model = BSIM3SIMDnextModel(model)) +{ for (here = BSIM3SIMDinstances(model); here != NULL; + here = BSIM3SIMDnextInstance(here)) + { +#endif + Check = 1; + ByPass = 0; + pParam = here->pParam; + if ((ckt->CKTmode & MODEINITSMSIG)) + { 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); + 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; + vgs = model->BSIM3type * here->BSIM3icVGS; + vbs = model->BSIM3type * here->BSIM3icVBS; + qdef = 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 * here->BSIM3vth0 + 0.1; + vds = 0.1; + } + } + 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) = + *(ckt->CKTstate1 + here->BSIM3vbs); + vbs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vbs)) + - (xfact * (*(ckt->CKTstate2 + here->BSIM3vbs))); + *(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->CKTstate1 + here->BSIM3vds); + vds = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vds)) + - (xfact * (*(ckt->CKTstate2 + here->BSIM3vds))); + *(ckt->CKTstate0 + here->BSIM3vbd) = + *(ckt->CKTstate0 + here->BSIM3vbs) + - *(ckt->CKTstate0 + here->BSIM3vds); + *(ckt->CKTstate0 + here->BSIM3qdef) = + *(ckt->CKTstate1 + here->BSIM3qdef); + qdef = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3qdef)) + -(xfact * (*(ckt->CKTstate2 + here->BSIM3qdef))); + } + else + { +#endif /* PREDICTOR */ + vbs = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3bNode) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + vgs = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3gNode) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + vds = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3dNodePrime) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + qdef = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3qNode)); +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + + vbd = vbs - vds; + vgd = vgs - vds; + vgdo = *(ckt->CKTstate0 + here->BSIM3vgs) + - *(ckt->CKTstate0 + here->BSIM3vds); + delvbs = vbs - *(ckt->CKTstate0 + here->BSIM3vbs); + delvbd = vbd - *(ckt->CKTstate0 + here->BSIM3vbd); + delvgs = vgs - *(ckt->CKTstate0 + here->BSIM3vgs); + delvds = vds - *(ckt->CKTstate0 + here->BSIM3vds); + delvgd = vgd - vgdo; + + if (here->BSIM3mode >= 0) + { Idtot = here->BSIM3cd + here->BSIM3csub - here->BSIM3cbd; + cdhat = Idtot - here->BSIM3gbd * delvbd + + (here->BSIM3gmbs + here->BSIM3gbbs) * delvbs + + (here->BSIM3gm + here->BSIM3gbgs) * delvgs + + (here->BSIM3gds + here->BSIM3gbds) * delvds; + Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + cbhat = Ibtot + here->BSIM3gbd * delvbd + + (here->BSIM3gbs - here->BSIM3gbbs) * delvbs + - here->BSIM3gbgs * delvgs + - here->BSIM3gbds * delvds; + } + else + { Idtot = here->BSIM3cd - here->BSIM3cbd; + cdhat = Idtot - (here->BSIM3gbd - here->BSIM3gmbs) * delvbd + + here->BSIM3gm * delvgd + - here->BSIM3gds * delvds; + Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + cbhat = Ibtot + here->BSIM3gbs * delvbs + + (here->BSIM3gbd - here->BSIM3gbbs) * delvbd + - here->BSIM3gbgs * delvgd + + here->BSIM3gbds * delvds; + } + +#ifndef NOBYPASS + /* following should be one big if connected by && all over + * the place, but some C compilers can't handle that, so + * we split it up here to let them digest it in stages + */ + + if ((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass)) + if ((fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), + fabs(*(ckt->CKTstate0+here->BSIM3vbs))) + ckt->CKTvoltTol))) + if ((fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), + fabs(*(ckt->CKTstate0+here->BSIM3vbd))) + ckt->CKTvoltTol))) + if ((fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs), + fabs(*(ckt->CKTstate0+here->BSIM3vgs))) + ckt->CKTvoltTol))) + if ((fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), + fabs(*(ckt->CKTstate0+here->BSIM3vds))) + ckt->CKTvoltTol))) + if ((fabs(cdhat - Idtot) < ckt->CKTreltol + * MAX(fabs(cdhat),fabs(Idtot)) + ckt->CKTabstol)) + { tempv = MAX(fabs(cbhat),fabs(Ibtot)) + ckt->CKTabstol; + if ((fabs(cbhat - Ibtot)) < ckt->CKTreltol * tempv) + { /* bypass code */ + vbs = *(ckt->CKTstate0 + here->BSIM3vbs); + vbd = *(ckt->CKTstate0 + here->BSIM3vbd); + vgs = *(ckt->CKTstate0 + here->BSIM3vgs); + vds = *(ckt->CKTstate0 + here->BSIM3vds); + qdef = *(ckt->CKTstate0 + here->BSIM3qdef); + + vgd = vgs - vds; + vgb = vgs - vbs; + + cdrain = here->BSIM3cd; + if ((ckt->CKTmode & (MODETRAN | MODEAC)) || + ((ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC))) + { ByPass = 1; + qgate = here->BSIM3qgate; + qbulk = here->BSIM3qbulk; + qdrn = here->BSIM3qdrn; + goto line755; + } + else + { goto line850; + } + } + } + +#endif /*NOBYPASS*/ + von = here->BSIM3von; + if (*(ckt->CKTstate0 + here->BSIM3vds) >= 0.0) + { 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); + vds = vgs - vgd; + vds = -DEVlimvds(-vds, -(*(ckt->CKTstate0+here->BSIM3vds))); + vgs = vgd + vds; + } + + if (vds >= 0.0) + { 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); + vbs = vbd + vds; + } + } + + /* determine DC current and derivatives */ + vbd = vbs - vds; + vgd = vgs - vds; + vgb = vgs - vbs; + + /* Source/drain junction diode DC model begins */ + Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; + /* 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 + { if (model->BSIM3ijth == 0.0) + { evbs = exp(vbs / Nvtm); + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { if (vbs < here->BSIM3vjsm) + { evbs = exp(vbs / Nvtm); + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { T0 = here->BSIM3IsEvjsm / Nvtm; + here->BSIM3gbs = T0 + ckt->CKTgmin; + here->BSIM3cbs = here->BSIM3IsEvjsm - SourceSatCurrent + + T0 * (vbs - here->BSIM3vjsm) + + ckt->CKTgmin * vbs; + } + } + } + + if (DrainSatCurrent <= 0.0) + { here->BSIM3gbd = ckt->CKTgmin; + here->BSIM3cbd = here->BSIM3gbd * vbd; + } + else + { if (model->BSIM3ijth == 0.0) + { evbd = exp(vbd / Nvtm); + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) + + ckt->CKTgmin * vbd; + } + else + { if (vbd < here->BSIM3vjdm) + { evbd = exp(vbd / Nvtm); + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) + + ckt->CKTgmin * vbd; + } + else + { T0 = here->BSIM3IsEvjdm / Nvtm; + here->BSIM3gbd = T0 + ckt->CKTgmin; + here->BSIM3cbd = here->BSIM3IsEvjdm - DrainSatCurrent + + T0 * (vbd - here->BSIM3vjdm) + + ckt->CKTgmin * vbd; + } + } + } + /* End of diode DC model */ + + if (vds >= 0.0) + { /* normal mode */ + here->BSIM3mode = 1; + Vds = vds; + Vgs = vgs; + Vbs = vbs; + } + 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); + if (Vbseff < Vbs) + { Vbseff = Vbs; + } + + if (Vbseff > 0.0) + { 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; + dPhis_dVb = -1.0; + sqrtPhis = sqrt(Phis); + dsqrtPhis_dVb = -0.5 / sqrtPhis; + } + Xdep = pParam->BSIM3Xdep0 * sqrtPhis / pParam->BSIM3sqrtPhi; + dXdep_dVb = (pParam->BSIM3Xdep0 / pParam->BSIM3sqrtPhi) + * dsqrtPhis_dVb; + + Leff = pParam->BSIM3leff; + Vtm = model->BSIM3vtm; +/* Vth Calculation */ + T3 = sqrt(Xdep); + V0 = pParam->BSIM3vbi - pParam->BSIM3phi; + + 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; + } + 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; + } + ltw = model->BSIM3factor1 * T3 * T1; + dltw_dVb = model->BSIM3factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); + + T0 = -0.5 * pParam->BSIM3dvt1 * Leff / lt1; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + Theta0 = T1 * (1.0 + 2.0 * T1); + dT1_dVb = -T0 / lt1 * T1 * dlt1_dVb; + dTheta0_dVb = (1.0 + 4.0 * T1) * dT1_dVb; + } + else + { T1 = MIN_EXP; + Theta0 = T1 * (1.0 + 2.0 * T1); + dTheta0_dVb = 0.0; + } + + here->BSIM3thetavth = pParam->BSIM3dvt0 * Theta0; + Delt_vth = here->BSIM3thetavth * V0; + dDelt_vth_dVb = pParam->BSIM3dvt0 * dTheta0_dVb * V0; + + T0 = -0.5 * pParam->BSIM3dvt1w * pParam->BSIM3weff * Leff / ltw; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + T2 = T1 * (1.0 + 2.0 * T1); + dT1_dVb = -T0 / ltw * T1 * dltw_dVb; + dT2_dVb = (1.0 + 4.0 * T1) * dT1_dVb; + } + else + { T1 = MIN_EXP; + T2 = T1 * (1.0 + 2.0 * T1); + dT2_dVb = 0.0; + } + + T0 = pParam->BSIM3dvt0w * T2; + T2 = T0 * V0; + dT2_dVb = pParam->BSIM3dvt0w * dT2_dVb * V0; + + TempRatio = ckt->CKTtemp / model->BSIM3tnom - 1.0; + T0 = sqrt(1.0 + pParam->BSIM3nlx / Leff); + T1 = pParam->BSIM3k1ox * (T0 - 1.0) * pParam->BSIM3sqrtPhi + + (pParam->BSIM3kt1 + pParam->BSIM3kt1l / Leff + + pParam->BSIM3kt2 * Vbseff) * TempRatio; + tmp2 = model->BSIM3tox * pParam->BSIM3phi + / (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; + DIBL_Sft = dDIBL_Sft_dVd * Vds; + + 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; + + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb - pParam->BSIM3k2ox + - dDelt_vth_dVb - dT2_dVb + pParam->BSIM3k3b * tmp2 + - pParam->BSIM3etab * Vds * pParam->BSIM3theta0vb0 * T4 + + pParam->BSIM3kt2 * TempRatio; + dVth_dVd = -dDIBL_Sft_dVd; + +/* Calculate n */ + 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 + + 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 + + pParam->BSIM3cdscb * Theta0) / model->BSIM3cox * T0; + dn_dVd = pParam->BSIM3cdscd * Theta0 / model->BSIM3cox * T0; + } + +/* Poly Gate Si Depletion Effect */ + T0 = here->BSIM3vfb + pParam->BSIM3phi; + if ((pParam->BSIM3ngate > 1.e18) && (pParam->BSIM3ngate < 1.e25) + && (Vgs > T0)) + /* 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); + T2 = T1 * (T4 - 1.0); + T3 = 0.5 * T2 * T2 / T1; /* T3 = Vpoly */ + T7 = 1.12 - T3 - 0.05; + 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); + } + else + { Vgs_eff = Vgs; + dVgs_eff_dVg = 1.0; + } + Vgst = Vgs_eff - Vth; + +/* Effective Vgst (Vgsteff) Calculation */ + + T10 = 2.0 * n * Vtm; + VgstNVt = Vgst / T10; + ExpArg = (2.0 * pParam->BSIM3voff - Vgst) / T10; + + /* MCJ: Very small Vgst */ + if (VgstNVt > EXP_THRESHOLD) + { 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; + 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); + 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; + + 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; + dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * Vtm * ExpArg * dn_dVb) + + (T2 - 1.0) / n * dn_dVb; + + Vgsteff = T1 / 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; + +/* Calculate Effective Channel Geometry */ + T9 = sqrtPhis - pParam->BSIM3sqrtPhi; + 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; + dWeff_dVg *= 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; + dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb; + } + 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; + dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb + * 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; + tmp2 = pParam->BSIM3a0 * T5; + 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; + dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb; + + T8 = pParam->BSIM3ags * pParam->BSIM3a0 * T7; + dAbulk_dVg = -T1 * T8; + Abulk = Abulk0 + dAbulk_dVg * Vgsteff; + dAbulk_dVb = dAbulk0_dVb - T8 * Vgsteff * (dT1_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; + } + + 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; + T10 = T9 * T9; + dAbulk_dVb *= T10; + dAbulk_dVg *= T10; + } + here->BSIM3Abulk = Abulk; + + T2 = pParam->BSIM3keta * Vbseff; + if (T2 >= -0.9) + { T0 = 1.0 / (1.0 + T2); + dT0_dVb = -pParam->BSIM3keta * T0 * T0; + } + else + /* added to avoid the problems caused by Keta */ + { 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; + + +/* Mobility calculation */ + if (model->BSIM3mobMod == 1) + { T0 = Vgsteff + Vth + Vth; + T2 = pParam->BSIM3ua + pParam->BSIM3uc * Vbseff; + T3 = T0 / model->BSIM3tox; + T5 = T3 * (T2 + pParam->BSIM3ub * T3); + dDenomi_dVg = (T2 + 2.0 * pParam->BSIM3ub * T3) / model->BSIM3tox; + 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 + / model->BSIM3tox); + dDenomi_dVg = (pParam->BSIM3ua + pParam->BSIM3uc * Vbseff + + 2.0 * pParam->BSIM3ub * Vgsteff / model->BSIM3tox) + / model->BSIM3tox; + dDenomi_dVd = 0.0; + dDenomi_dVb = Vgsteff * pParam->BSIM3uc / model->BSIM3tox; + } + 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; + dDenomi_dVg = (pParam->BSIM3ua + 2.0 * pParam->BSIM3ub * T3) * T2 + / 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; + dDenomi_dVg *= T9; + dDenomi_dVd *= T9; + dDenomi_dVb *= T9; + } + + 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; + + Esat = 2.0 * pParam->BSIM3vsattemp / ueff; + EsatL = Esat * Leff; + T0 = -EsatL /ueff; + dEsatL_dVg = T0 * dueff_dVg; + dEsatL_dVd = T0 * dueff_dVd; + dEsatL_dVb = T0 * dueff_dVb; + + /* Sqrt() */ + a1 = pParam->BSIM3a1; + 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); + } + + Vgst2Vtm = Vgsteff + 2.0 * Vtm; + here->BSIM3AbovVgst2Vtm = Abulk / Vgst2Vtm; + + if (Rds > 0) + { tmp2 = dRds_dVg / Rds + dWeff_dVg / Weff; + tmp3 = dRds_dVb / Rds + dWeff_dVb / Weff; + } + 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; + 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; + + 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; + } + else + { tmp1 = dLambda_dVg / (Lambda * Lambda); + T9 = Abulk * WVCoxRds; + T8 = Abulk * T9; + T7 = Vgst2Vtm * T9; + T6 = Vgst2Vtm * WVCoxRds; + 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); + + dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3) + + (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); + dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb + + 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); + dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3); + dT2_dVd = Vgst2Vtm * dEsatL_dVd; + + T3 = sqrt(T1 * T1 - 2.0 * T0 * T2); + Vdsat = (T1 - T3) / T0; + + dT3_dVg = (T1 * dT1_dVg - 2.0 * (T0 * dT2_dVg + T2 * dT0_dVg)) + / T3; + dT3_dVd = (T1 * dT1_dVd - 2.0 * (T0 * dT2_dVd + T2 * dT0_dVd)) + / T3; + dT3_dVb = (T1 * dT1_dVb - 2.0 * (T0 * dT2_dVb + T2 * dT0_dVb)) + / T3; + + dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2 + - 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; + dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0; + } + here->BSIM3vdsat = Vdsat; + +/* Effective Vds (Vdseff) Calculation */ + T1 = Vdsat - Vds - pParam->BSIM3delta; + dT1_dVg = dVdsat_dVg; + dT1_dVd = dVdsat_dVd - 1.0; + dT1_dVb = dVdsat_dVb; + + T2 = sqrt(T1 * T1 + 4.0 * pParam->BSIM3delta * Vdsat); + 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); + /* 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; + } + +/* Calculate VAsat */ + tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; + T9 = WVCoxRds * Vgsteff; + 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); + + dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * Vgsteff + - 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; + dT1_dVg = -2.0 * tmp1 + WVCoxRds * (Abulk * tmp2 + dAbulk_dVg); + dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3; + + Vasat = T0 / T1; + dVasat_dVg = (dT0_dVg - Vasat * dT1_dVg) / T1; + dVasat_dVb = (dT0_dVb - Vasat * dT1_dVb) / T1; + dVasat_dVd = dT0_dVd / T1; + + if (Vdseff > Vds) + Vdseff = Vds; + diffVds = Vds - Vdseff; + here->BSIM3Vdseff = Vdseff; + +/* Calculate VACLM */ + if ((pParam->BSIM3pclm > 0.0) && (diffVds > 1.0e-10)) + { 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); + 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; + 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; + dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd); + } + 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; + dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 + + Vgst2Vtm * Vdsat * dAbulk_dVg; + dT0_dVb = Vgst2Vtm * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); + dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd; + + T1 = Vgst2Vtm + T8; + dT1_dVg = 1.0 + Abulk * dVdsat_dVg + Vdsat * dAbulk_dVg; + dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat; + dT1_dVd = Abulk * dVdsat_dVd; + + 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); + VADIBL *= T3; + dVADIBL_dVg *= T3; + dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM3pdiblb) + * T3; + dVADIBL_dVd *= T3; + } + else +/* Added to avoid the discontinuity problem caused by pdiblcb */ + { 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; + dVADIBL_dVd *= T3; + VADIBL *= T3; + } + } + 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; + 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; + 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; + + T1 = VACLM * VADIBL / tmp3; + tmp3 *= tmp3; + dT1_dVg = (tmp1 * dVADIBL_dVg + tmp2 * dVACLM_dVg) / tmp3; + dT1_dVd = (tmp1 * dVADIBL_dVd + tmp2 * dVACLM_dVd) / tmp3; + dT1_dVb = (tmp1 * dVADIBL_dVb + tmp2 * dVACLM_dVb) / tmp3; + + Va = Vasat + T0 * T1; + dVa_dVg = dVasat_dVg + T1 * dT0_dVg + T0 * dT1_dVg; + dVa_dVd = dVasat_dVd + T1 * dT0_dVd + T0 * dT1_dVd; + 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; + 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; + dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; + } + } + else + { VASCBE = MAX_EXP; + dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; + } + +/* Calculate Ids */ + CoxWovL = model->BSIM3cox * Weff / Leff; + beta = ueff * CoxWovL; + dbeta_dVg = CoxWovL * dueff_dVg + beta * dWeff_dVg / Weff; + dbeta_dVd = CoxWovL * dueff_dVd; + 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_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; + + 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; + dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd + - gche * dfgche2_dVd) / fgche2; + dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb + - 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 ; + + 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; + dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va; + + T9 = diffVds / VASCBE; + T0 = 1.0 + T9; + Ids = Idsa * T0; + + Gm = T0 * dIdsa_dVg - Idsa * (dVdseff_dVg + T9 * dVASCBE_dVg) / VASCBE; + Gds = T0 * dIdsa_dVd + Idsa * (1.0 - dVdseff_dVd + - T9 * dVASCBE_dVd) / VASCBE; + Gmb = T0 * dIdsa_dVb - Idsa * (dVdseff_dVb + + T9 * dVASCBE_dVb) / VASCBE; + + Gds += Gm * dVgsteff_dVd; + 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; + } + 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; + dT1_dVg = -T3 * dVdseff_dVg; + dT1_dVd = T3 * (1.0 - dVdseff_dVd); + dT1_dVb = -T3 * dVdseff_dVb; + } + Isub = T1 * Idsa; + Gbg = T1 * dIdsa_dVg + Idsa * dT1_dVg; + Gbd = T1 * dIdsa_dVd + Idsa * dT1_dVd; + Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb; + + Gbd += Gbg * dVgsteff_dVd; + 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 + * 0, 1, 2 & 3 stored in here->BSIM3qinv 1/1998 */ + + if ((model->BSIM3xpart < 0) || (!ChargeComputationNeeded)) + { 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->BSIM3cqbb = 0.0; + here->BSIM3gtau = 0.0; + goto finished; + } + else if (model->BSIM3capMod == 0) + { + if (Vbseff < 0.0) + { Vbseff = Vbs; + dVbseff_dVb = 1.0; + } + else + { Vbseff = pParam->BSIM3phi - Phis; + dVbseff_dVb = -dPhis_dVb; + } + + Vfb = pParam->BSIM3vfbcv; + Vth = Vfb + pParam->BSIM3phi + pParam->BSIM3k1ox * sqrtPhis; + Vgst = Vgs_eff - Vth; + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb; + dVgst_dVb = -dVth_dVb; + dVgst_dVg = dVgs_eff_dVg; + + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + * pParam->BSIM3leffCV; + Arg1 = Vgs_eff - Vbseff - Vfb; + + if (Arg1 <= 0.0) + { qgate = CoxWL * Arg1; + qbulk = -qgate; + qdrn = 0.0; + + here->BSIM3cggb = CoxWL * dVgs_eff_dVg; + here->BSIM3cgdb = 0.0; + here->BSIM3cgsb = CoxWL * (dVbseff_dVb - dVgs_eff_dVg); + + here->BSIM3cdgb = 0.0; + here->BSIM3cddb = 0.0; + here->BSIM3cdsb = 0.0; + + here->BSIM3cbgb = -CoxWL * dVgs_eff_dVg; + here->BSIM3cbdb = 0.0; + 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); + qbulk = -qgate; + qdrn = 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; + + here->BSIM3cbgb = -here->BSIM3cggb; + here->BSIM3cbdb = 0.0; + here->BSIM3cbsb = -here->BSIM3cgsb; + here->BSIM3qinv = 0.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; + + 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; + + 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->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); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) + * dVgs_eff_dVg; + T11 = -CoxWL * T5 * dVdsat_dVb; + here->BSIM3cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); + here->BSIM3cgsb = -(here->BSIM3cggb + T11 + + here->BSIM3cgdb); + T6 = 1.0 / Vdsat; + dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); + dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); + T7 = T9 * T7; + T8 = T9 * T8; + T9 = 2.0 * T4 * (1.0 - 3.0 * T5); + here->BSIM3cdgb = (T7 * dAlphaz_dVg - T9 + * 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 + + here->BSIM3cddb); + + T9 = 2.0 * T4 * (1.0 + T5); + T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) + * dVgs_eff_dVg; + T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb; + 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->BSIM3cbsb = -(here->BSIM3cgsb + + 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; + + 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; + 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->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)); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_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); + + 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)); + + here->BSIM3cdgb = (T7 * dAlphaz_dVg - tmp1 + * 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); + + 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->BSIM3cbdb = -(here->BSIM3cgdb + + here->BSIM3cddb + T10); /* bug fix */ + here->BSIM3cbsb = -(here->BSIM3cgsb + + 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; + + 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; + 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->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)); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_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); + + 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); + + here->BSIM3cdgb = (T0 * dVdsat_dVg - T7 + * 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); + here->BSIM3cbdb = -(here->BSIM3cgdb + + 2.0 * here->BSIM3cddb); + here->BSIM3cbsb = -(here->BSIM3cgsb + + 2.0 * here->BSIM3cdsb); + here->BSIM3qinv = -(qgate + qbulk); + } + } + } + } + else + { if (Vbseff < 0.0) + { VbseffCV = Vbseff; + dVbseffCV_dVb = 1.0; + } + else + { VbseffCV = pParam->BSIM3phi - Phis; + dVbseffCV_dVb = -dPhis_dVb; + } + + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + * pParam->BSIM3leffCV; + + /* Seperate VgsteffCV with noff and voffcv */ + noff = n * pParam->BSIM3noff; + dnoff_dVd = pParam->BSIM3noff * dn_dVd; + dnoff_dVb = pParam->BSIM3noff * dn_dVb; + T0 = Vtm * noff; + voffcv = pParam->BSIM3voffcv; + VgstNVt = (Vgst - voffcv) / T0; + + if (VgstNVt > EXP_THRESHOLD) + { Vgsteff = Vgst - voffcv; + dVgsteff_dVg = dVgs_eff_dVg; + dVgsteff_dVd = -dVth_dVd; + dVgsteff_dVb = -dVth_dVb; + } + else if (VgstNVt < -EXP_THRESHOLD) + { Vgsteff = T0 * log(1.0 + MIN_EXP); + dVgsteff_dVg = 0.0; + dVgsteff_dVd = Vgsteff / noff; + dVgsteff_dVb = dVgsteff_dVd * dnoff_dVb; + dVgsteff_dVd *= dnoff_dVd; + } + else + { ExpVgst = exp(VgstNVt); + Vgsteff = T0 * log(1.0 + ExpVgst); + dVgsteff_dVg = ExpVgst / (1.0 + ExpVgst); + dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + (Vgst - voffcv) + / noff * dnoff_dVd) + Vgsteff / noff * dnoff_dVd; + dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + (Vgst - voffcv) + / noff * dnoff_dVb) + Vgsteff / noff * dnoff_dVb; + dVgsteff_dVg *= dVgs_eff_dVg; + } /* End of VgsteffCV */ + + if (model->BSIM3capMod == 1) + { Vfb = here->BSIM3vfbzb; + Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff; + + if (Arg1 <= 0.0) + { 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); + 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; + + 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; + if (VdsatCV < Vds) + { 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; + Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb; + Cgd1 = Cgg1 * dVgsteff_dVd; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; + + 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; + Cbd += Cbd1; + + if (model->BSIM3xpart > 0.5) + T0 = -Two_Third_CoxWL; + else if (model->BSIM3xpart < 0.5) + T0 = -0.4 * CoxWL; + else + 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; + } + else + { T0 = AbulkCV * Vds; + T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20); + 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; + + qgate += CoxWL * (Vgsteff - 0.5 * Vds + T3); + 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; + + 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; + + if (model->BSIM3xpart > 0.5) + { /* 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); + 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; + } + 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 */ + qsrc = -0.5 * (qgate + qbulk); + Csg = -0.5 * (Cgg1 + Cbg1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); + } + 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->BSIM3cdgb = -(Cgg + Cbg + Csg); + 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->BSIM3qinv = -(qgate + qbulk); + } + + 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; + } + + 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; + if (pParam->BSIM3k1ox == 0.0) + { T1 = 0.0; + T2 = 0.0; + } + else if (T3 < 0.0) + { T1 = T0 + T3 / pParam->BSIM3k1ox; + T2 = CoxWL; + } + else + { T1 = sqrt(T0 * T0 + T3); + T2 = CoxWL * T0 / T1; + } + + 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 + + dVgsteff_dVb); + + AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; + 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 to eliminate non-zero VdseffCV at Vds=0.0 */ + if (Vds == 0.0) + { VdseffCV = 0.0; + dVdseffCV_dVg = 0.0; + dVdseffCV_dVb = 0.0; + } + + T0 = AbulkCV * VdseffCV; + T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20); + 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); + T6 = 12.0 * T2 * T2 * Vgsteff; + + qinoi = -CoxWL * (Vgsteff - 0.5 * T0 + AbulkCV * T3); + qgate = CoxWL * (Vgsteff - 0.5 * VdseffCV + T3); + 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; + + 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)); + 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; + + if (model->BSIM3xpart > 0.5) + { /* 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); + 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; + } + 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; + } + 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); + } + + 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; + + 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; + + here->BSIM3cggb = Cgg; + 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->BSIM3cbgb = Cbg; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; + here->BSIM3qinv = qinoi; + } + + /* New Charge-Thickness capMod (CTM) begins */ + 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 = 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 - here->BSIM3vfbzb) / Tox; + dT0_dVg = dVgs_eff_dVg / Tox; + dT0_dVb = -dVbseffCV_dVb / Tox; + + tmp = T0 * pParam->BSIM3acde; + if ((-EXP_THRESHOLD < tmp) && (tmp < EXP_THRESHOLD)) + { Tcen = pParam->BSIM3ldeb * exp(tmp); + dTcen_dVg = pParam->BSIM3acde * Tcen; + dTcen_dVb = dTcen_dVg * dT0_dVb; + dTcen_dVg *= dT0_dVg; + } + else if (tmp <= -EXP_THRESHOLD) + { Tcen = pParam->BSIM3ldeb * MIN_EXP; + dTcen_dVg = dTcen_dVb = 0.0; + } + else + { Tcen = pParam->BSIM3ldeb * MAX_EXP; + dTcen_dVg = dTcen_dVb = 0.0; + } + + LINK = 1.0e-3 * model->BSIM3tox; + V3 = pParam->BSIM3ldeb - Tcen - LINK; + V4 = sqrt(V3 * V3 + 4.0 * LINK * pParam->BSIM3ldeb); + Tcen = pParam->BSIM3ldeb - 0.5 * (V3 + V4); + T1 = 0.5 * (1.0 + V3 / V4); + dTcen_dVg *= T1; + dTcen_dVb *= T1; + + Ccen = EPSSI / Tcen; + T2 = Cox / (Cox + Ccen); + Coxeff = T2 * Ccen; + T3 = -Ccen / Tcen; + dCoxeff_dVg = T2 * T2 * T3; + dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; + dCoxeff_dVg *= dTcen_dVg; + CoxWLcen = CoxWL * Coxeff / Cox; + + Qac0 = CoxWLcen * (Vfbeff - here->BSIM3vfbzb); + QovCox = Qac0 / Coxeff; + dQac0_dVg = CoxWLcen * dVfbeff_dVg + + QovCox * dCoxeff_dVg; + dQac0_dVb = CoxWLcen * dVfbeff_dVb + + QovCox * dCoxeff_dVb; + + T0 = 0.5 * pParam->BSIM3k1ox; + 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; + T2 = CoxWLcen; + } + else + { T1 = sqrt(T0 * T0 + T3); + T2 = CoxWLcen * T0 / T1; + } + + Qsub0 = CoxWLcen * pParam->BSIM3k1ox * (T1 - T0); + QovCox = Qsub0 / Coxeff; + dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg) + + QovCox * dCoxeff_dVg; + dQsub0_dVd = -T2 * dVgsteff_dVd; + 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; + T0 = 0.5 * pParam->BSIM3sqrtPhi; + } + 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 */ + + /* VgDP = Vgsteff - DeltaPhi */ + T0 = Vgsteff - DeltaPhi - 0.001; + dT0_dVg = 1.0 - dDeltaPhi_dVg; + T1 = sqrt(T0 * T0 + Vgsteff * 0.004); + VgDP = 0.5 * (T0 + T1); + dVgDP_dVg = 0.5 * (dT0_dVg + (T0 * dT0_dVg + 0.002) / T1); + + T3 = 4.0 * (Vth - here->BSIM3vfbzb - pParam->BSIM3phi); + Tox += Tox; + if (T3 >= 0.0) + { T0 = (Vgsteff + T3) / Tox; + dT0_dVd = (dVgsteff_dVd + 4.0 * dVth_dVd) / Tox; + dT0_dVb = (dVgsteff_dVb + 4.0 * dVth_dVb) / Tox; + } + else + { T0 = (Vgsteff + 1.0e-20) / Tox; + dT0_dVd = dVgsteff_dVd / Tox; + dT0_dVb = dVgsteff_dVb / 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; + dTcen_dVd = Tox * dTcen_dVg; + dTcen_dVb = dTcen_dVd * dT0_dVb; + 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; + + 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; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_4 * VdsatCV); + dT1_dVg = (T0 + DELTA_4 + DELTA_4) / T1; + dT1_dVd = -T0 / T1; + dT1_dVb = dT1_dVg * dT0_dVb; + dT1_dVg *= dT0_dVg; + if (T0 >= 0.0) + { VdseffCV = VdsatCV - 0.5 * (T0 + T1); + dVdseffCV_dVg = 0.5 * (dT0_dVg - dT1_dVg); + dVdseffCV_dVd = 0.5 * (1.0 - dT1_dVd); + dVdseffCV_dVb = 0.5 * (dT0_dVb - dT1_dVb); + } + else + { T3 = (DELTA_4 + DELTA_4) / (T1 - T0); + T4 = 1.0 - T3; + T5 = VdsatCV * T3 / (T1 - T0); + VdseffCV = VdsatCV * T4; + dVdseffCV_dVg = dT0_dVg * T4 + T5 * (dT1_dVg - dT0_dVg); + dVdseffCV_dVd = T5 * (dT1_dVd + 1.0); + dVdseffCV_dVb = dT0_dVb * (1.0 - T5) + T5 * dT1_dVb; + } + + /* 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; + } + + T0 = AbulkCV * VdseffCV; + 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; + + 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; + + + T7 = 1.0 - AbulkCV; + T8 = T2 * T2; + T9 = 12.0 * T7 * T0 * T0 / (T8 * AbulkCV); + T10 = T9 * dVgDP_dVg; + 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; + + 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; + + 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 + * 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; + + 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 */ + qsrc = -0.5 * qgate; + Csg = -0.5 * Cgg1; + Csd = -0.5 * Cgd1; + Csb = -0.5 * Cgb1; + } + + 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; + + Cgg = Cgg1 - Cbg; + Cgd = Cgd1 - Cbd; + Cgb = Cgb1 - Cbb; + + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; + + here->BSIM3cggb = Cgg; + 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->BSIM3cbgb = Cbg; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; + here->BSIM3qinv = -qinoi; + } /* End of CTM */ + } + +finished: + /* Returning Values to Calling Routine */ + /* + * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE + */ + + here->BSIM3qgate = qgate; + here->BSIM3qbulk = qbulk; + here->BSIM3qdrn = qdrn; + here->BSIM3cd = cdrain; + + if (ChargeComputationNeeded) + { /* 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 + * 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 + */ + + if (model->BSIM3acmMod == 0) + { + 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; + + /* Source Bulk Junction */ + 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) + sarg = 1.0 / sqrt(arg); + 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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSW * log(arg)); + *(ckt->CKTstate0 + here->BSIM3qbs) += model->BSIM3PhiBSW * czbssw + * (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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSWG * log(arg)); + *(ckt->CKTstate0 + here->BSIM3qbs) += model->BSIM3PhiBSWG * czbsswg + * (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); + *(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; + here->BSIM3capbd = czbd + czbdsw + czbdswg; + } + 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 + sarg = exp(-MJ * log(arg)); + *(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; + here->BSIM3capbd = 0.0; + } + if (czbdsw > 0.0) + { arg = 1.0 - vbd / model->BSIM3PhiBSW; + if (MJSW == 0.5) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSW * log(arg)); + *(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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSWG * log(arg)); + *(ckt->CKTstate0 + here->BSIM3qbd) += model->BSIM3PhiBSWG * czbdswg + * (1.0 - arg * sarg) / (1.0 - MJSWG); + here->BSIM3capbd += czbdswg * sarg; + } + } + 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; + } + } + + /* + * check convergence + */ + if ((here->BSIM3off == 0) || (!(ckt->CKTmode & MODEINITFIX))) + { if (Check == 1) + { ckt->CKTnoncon++; +#ifndef NEWCONV + } + else + { if (here->BSIM3mode >= 0) + { Idtot = here->BSIM3cd + here->BSIM3csub - here->BSIM3cbd; + } + else + { Idtot = here->BSIM3cd - here->BSIM3cbd; + } + tol = ckt->CKTreltol * MAX(fabs(cdhat), fabs(Idtot)) + + ckt->CKTabstol; + if (fabs(cdhat - Idtot) >= tol) + { ckt->CKTnoncon++; + } + else + { Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + tol = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + + ckt->CKTabstol; + if (fabs(cbhat - Ibtot) > tol) + { ckt->CKTnoncon++; + } + } +#endif /* NEWCONV */ + } + } + *(ckt->CKTstate0 + here->BSIM3vbs) = vbs; + *(ckt->CKTstate0 + here->BSIM3vbd) = vbd; + *(ckt->CKTstate0 + here->BSIM3vgs) = vgs; + *(ckt->CKTstate0 + here->BSIM3vds) = vds; + *(ckt->CKTstate0 + here->BSIM3qdef) = qdef; + + /* bulk and channel charge plus overlaps */ + + if (!ChargeComputationNeeded) + goto line850; +#ifndef NOBYPASS +line755: +#endif + /* NQS begins */ + if ((here->BSIM3nqsMod) || (here->BSIM3acnqsMod)) + { qcheq = -(qbulk + qgate); + + here->BSIM3cqgb = -(here->BSIM3cggb + here->BSIM3cbgb); + here->BSIM3cqdb = -(here->BSIM3cgdb + here->BSIM3cbdb); + here->BSIM3cqsb = -(here->BSIM3cgsb + here->BSIM3cbsb); + here->BSIM3cqbb = -(here->BSIM3cqgb + here->BSIM3cqdb + + here->BSIM3cqsb); + + gtau_drift = fabs(here->BSIM3tconst * qcheq) * ScalingFactor; + T0 = pParam->BSIM3leffCV * pParam->BSIM3leffCV; + 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 (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)); + + 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; + + ag0 = ckt->CKTag[0]; + if (here->BSIM3mode > 0) + { if (here->BSIM3nqsMod == 0) + { gcggb = (here->BSIM3cggb + cgdo + cgso + + pParam->BSIM3cgbo ) * ag0; + gcgdb = (here->BSIM3cgdb - cgdo) * ag0; + gcgsb = (here->BSIM3cgsb - cgso) * ag0; + + gcdgb = (here->BSIM3cdgb - cgdo) * ag0; + gcddb = (here->BSIM3cddb + here->BSIM3capbd + cgdo) * ag0; + gcdsb = here->BSIM3cdsb * ag0; + + gcsgb = -(here->BSIM3cggb + here->BSIM3cbgb + + here->BSIM3cdgb + cgso) * ag0; + gcsdb = -(here->BSIM3cgdb + here->BSIM3cbdb + + here->BSIM3cddb) * ag0; + gcssb = (here->BSIM3capbs + cgso - (here->BSIM3cgsb + + here->BSIM3cbsb + here->BSIM3cdsb)) * ag0; + + gcbgb = (here->BSIM3cbgb - pParam->BSIM3cgbo) * ag0; + gcbdb = (here->BSIM3cbdb - here->BSIM3capbd) * ag0; + gcbsb = (here->BSIM3cbsb - here->BSIM3capbs) * ag0; + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate += qgd + qgs + qgb; + qbulk -= qgb; + qdrn -= qgd; + qsrc = -(qgate + qbulk + qdrn); + + ggtg = ggtd = ggtb = ggts = 0.0; + sxpart = 0.6; + dxpart = 0.4; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + } + else + { if (qcheq > 0.0) + T0 = here->BSIM3tconst * qdef * ScalingFactor; + else + 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; + + gcqgb = here->BSIM3cqgb * ag0; + gcqdb = here->BSIM3cqdb * ag0; + gcqsb = here->BSIM3cqsb * ag0; + gcqbb = here->BSIM3cqbb * ag0; + + gcggb = (cgdo + cgso + pParam->BSIM3cgbo ) * ag0; + gcgdb = -cgdo * ag0; + gcgsb = -cgso * ag0; + + gcdgb = -cgdo * ag0; + gcddb = (here->BSIM3capbd + cgdo) * ag0; + gcdsb = 0.0; + + gcsgb = -cgso * ag0; + gcsdb = 0.0; + gcssb = (here->BSIM3capbs + cgso) * ag0; + + gcbgb = -pParam->BSIM3cgbo * ag0; + gcbdb = -here->BSIM3capbd * ag0; + gcbsb = -here->BSIM3capbs * ag0; + + 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; + + 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); + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate = qgd + qgs + qgb; + qbulk = -qgb; + qdrn = -qgd; + qsrc = -(qgate + qbulk + qdrn); + } + } + else + { if (here->BSIM3nqsMod == 0) + { gcggb = (here->BSIM3cggb + cgdo + cgso + + pParam->BSIM3cgbo ) * ag0; + gcgdb = (here->BSIM3cgsb - cgdo) * ag0; + gcgsb = (here->BSIM3cgdb - cgso) * ag0; + + gcdgb = -(here->BSIM3cggb + here->BSIM3cbgb + + here->BSIM3cdgb + cgdo) * ag0; + gcddb = (here->BSIM3capbd + cgdo - (here->BSIM3cgsb + + here->BSIM3cbsb + here->BSIM3cdsb)) * ag0; + gcdsb = -(here->BSIM3cgdb + here->BSIM3cbdb + + here->BSIM3cddb) * ag0; + + gcsgb = (here->BSIM3cdgb - cgso) * ag0; + gcsdb = here->BSIM3cdsb * ag0; + gcssb = (here->BSIM3cddb + here->BSIM3capbs + cgso) * ag0; + + gcbgb = (here->BSIM3cbgb - pParam->BSIM3cgbo) * ag0; + gcbdb = (here->BSIM3cbsb - here->BSIM3capbd) * ag0; + gcbsb = (here->BSIM3cbdb - here->BSIM3capbs) * ag0; + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate += qgd + qgs + qgb; + qbulk -= qgb; + qsrc = qdrn - qgs; + qdrn = -(qgate + qbulk + qsrc); + + ggtg = ggtd = ggtb = ggts = 0.0; + sxpart = 0.4; + dxpart = 0.6; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + } + else + { if (qcheq > 0.0) + T0 = here->BSIM3tconst * qdef * ScalingFactor; + else + 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; + + gcqgb = here->BSIM3cqgb * ag0; + gcqdb = here->BSIM3cqsb * ag0; + gcqsb = here->BSIM3cqdb * ag0; + gcqbb = here->BSIM3cqbb * ag0; + + gcggb = (cgdo + cgso + pParam->BSIM3cgbo) * ag0; + gcgdb = -cgdo * ag0; + gcgsb = -cgso * ag0; + + gcdgb = -cgdo * ag0; + gcddb = (here->BSIM3capbd + cgdo) * ag0; + gcdsb = 0.0; + + gcsgb = -cgso * ag0; + gcsdb = 0.0; + gcssb = (here->BSIM3capbs + cgso) * ag0; + + gcbgb = -pParam->BSIM3cgbo * ag0; + gcbdb = -here->BSIM3capbd * ag0; + gcbsb = -here->BSIM3capbs * ag0; + + 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; + + 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); + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate = qgd + qgs + qgb; + qbulk = -qgb; + qsrc = -qgs; + qdrn = -(qgate + qbulk + qsrc); + } + } + + cqdef = cqcheq = 0.0; + if (ByPass) goto line860; + + *(ckt->CKTstate0 + here->BSIM3qg) = qgate; + *(ckt->CKTstate0 + here->BSIM3qd) = qdrn + - *(ckt->CKTstate0 + here->BSIM3qbd); + *(ckt->CKTstate0 + here->BSIM3qb) = qbulk + + *(ckt->CKTstate0 + here->BSIM3qbd) + + *(ckt->CKTstate0 + here->BSIM3qbs); + + if (here->BSIM3nqsMod) + { *(ckt->CKTstate0 + here->BSIM3qcdump) = qdef * ScalingFactor; + *(ckt->CKTstate0 + here->BSIM3qcheq) = qcheq; + } + + /* store small signal parameters */ + if (ckt->CKTmode & MODEINITSMSIG) + { goto line1000; + } + if (!ChargeComputationNeeded) + goto line850; + + if (ckt->CKTmode & MODEINITTRAN) + { *(ckt->CKTstate1 + here->BSIM3qb) = + *(ckt->CKTstate0 + here->BSIM3qb); + *(ckt->CKTstate1 + here->BSIM3qg) = + *(ckt->CKTstate0 + here->BSIM3qg); + *(ckt->CKTstate1 + here->BSIM3qd) = + *(ckt->CKTstate0 + here->BSIM3qd); + if (here->BSIM3nqsMod) + { *(ckt->CKTstate1 + here->BSIM3qcheq) = + *(ckt->CKTstate0 + here->BSIM3qcheq); + *(ckt->CKTstate1 + here->BSIM3qcdump) = + *(ckt->CKTstate0 + here->BSIM3qcdump); + } + } + + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qb); + if (error) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qg); + if (error) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qd); + if (error) + return(error); + if (here->BSIM3nqsMod) + { error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qcdump); + if (error) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qcheq); + if (error) + return(error); + } + + goto line860; + +line850: + /* initialize to zero charge conductance and current */ + ceqqg = ceqqb = ceqqd = 0.0; + cqcheq = cqdef = 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; + 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; + + if (here->BSIM3nqsMod) + here->BSIM3gtau = 16.0 * here->BSIM3u0temp * model->BSIM3vtm + / pParam->BSIM3leffCV / pParam->BSIM3leffCV + * ScalingFactor; + else + here->BSIM3gtau = 0.0; + + goto line900; + +line860: + /* evaluate equivalent charge current */ + + cqgate = *(ckt->CKTstate0 + here->BSIM3cqg); + cqbulk = *(ckt->CKTstate0 + here->BSIM3cqb); + cqdrn = *(ckt->CKTstate0 + here->BSIM3cqd); + + ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs; + ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs; + ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs; + + if (here->BSIM3nqsMod) + { T0 = ggtg * vgb - ggtd * vbd - ggts * vbs; + ceqqg += T0; + T1 = qdef * here->BSIM3gtau; + ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd + * vbd - ddxpart_dVs * vbs); + cqdef = *(ckt->CKTstate0 + here->BSIM3cqcdump) - gqdef * qdef; + cqcheq = *(ckt->CKTstate0 + here->BSIM3cqcheq) + - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0; + } + + if (ckt->CKTmode & MODEINITTRAN) + { *(ckt->CKTstate1 + here->BSIM3cqb) = + *(ckt->CKTstate0 + here->BSIM3cqb); + *(ckt->CKTstate1 + here->BSIM3cqg) = + *(ckt->CKTstate0 + here->BSIM3cqg); + *(ckt->CKTstate1 + here->BSIM3cqd) = + *(ckt->CKTstate0 + here->BSIM3cqd); + + if (here->BSIM3nqsMod) + { *(ckt->CKTstate1 + here->BSIM3cqcheq) = + *(ckt->CKTstate0 + here->BSIM3cqcheq); + *(ckt->CKTstate1 + here->BSIM3cqcdump) = + *(ckt->CKTstate0 + here->BSIM3cqcdump); + } + } + + /* + * load current vector + */ +line900: + + if (here->BSIM3mode >= 0) + { Gm = here->BSIM3gm; + Gmbs = here->BSIM3gmbs; + FwdSum = Gm + Gmbs; + RevSum = 0.0; + cdreq = model->BSIM3type * (cdrain - here->BSIM3gds * vds + - Gm * vgs - Gmbs * vbs); + + ceqbd = -model->BSIM3type * (here->BSIM3csub + - here->BSIM3gbds * vds - here->BSIM3gbgs * vgs + - here->BSIM3gbbs * vbs); + ceqbs = 0.0; + + gbbdp = -here->BSIM3gbds; + gbbsp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); + + gbdpg = here->BSIM3gbgs; + gbdpdp = here->BSIM3gbds; + gbdpb = here->BSIM3gbbs; + gbdpsp = -(gbdpg + gbdpdp + gbdpb); + + gbspg = 0.0; + gbspdp = 0.0; + gbspb = 0.0; + gbspsp = 0.0; + } + else + { Gm = -here->BSIM3gm; + Gmbs = -here->BSIM3gmbs; + FwdSum = 0.0; + RevSum = -(Gm + Gmbs); + cdreq = -model->BSIM3type * (cdrain + here->BSIM3gds * vds + + Gm * vgd + Gmbs * vbd); + + ceqbs = -model->BSIM3type * (here->BSIM3csub + + here->BSIM3gbds * vds - here->BSIM3gbgs * vgd + - here->BSIM3gbbs * vbd); + ceqbd = 0.0; + + gbbsp = -here->BSIM3gbds; + gbbdp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); + + gbdpg = 0.0; + gbdpsp = 0.0; + gbdpb = 0.0; + gbdpdp = 0.0; + + gbspg = here->BSIM3gbgs; + gbspsp = here->BSIM3gbds; + gbspb = here->BSIM3gbbs; + gbspdp = -(gbspg + gbspsp + gbspb); + } + + if (model->BSIM3type > 0) + { ceqbs += (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbd += (here->BSIM3cbd - here->BSIM3gbd * vbd); + /* + ceqqg = ceqqg; + ceqqb = ceqqb; + ceqqd = ceqqd; + cqdef = cqdef; + cqcheq = cqcheq; + */ + } + else + { ceqbs -= (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbd -= (here->BSIM3cbd - here->BSIM3gbd * vbd); + ceqqg = -ceqqg; + ceqqb = -ceqqb; + ceqqd = -ceqqd; + cqdef = -cqdef; + cqcheq = -cqcheq; + } + + m = here->BSIM3m; +#ifdef USE_OMP + here->BSIM3rhsG = m * ceqqg; + here->BSIM3rhsB = m * (ceqbs + ceqbd + ceqqb); + here->BSIM3rhsD = m * (ceqbd - cdreq - ceqqd); + here->BSIM3rhsS = m * (cdreq + ceqbs + ceqqg + + ceqqb + ceqqd); + if (here->BSIM3nqsMod) + here->BSIM3rhsQ = m * (cqcheq - cqdef); +#else + (*(ckt->CKTrhs + here->BSIM3gNode) -= m * ceqqg); + (*(ckt->CKTrhs + here->BSIM3bNode) -= m * (ceqbs + ceqbd + ceqqb)); + (*(ckt->CKTrhs + here->BSIM3dNodePrime) += m * (ceqbd - cdreq - ceqqd)); + (*(ckt->CKTrhs + here->BSIM3sNodePrime) += m * (cdreq + ceqbs + ceqqg + + ceqqb + ceqqd)); + if (here->BSIM3nqsMod) + *(ckt->CKTrhs + here->BSIM3qNode) += m * (cqcheq - cqdef); +#endif + /* + * load y matrix + */ + + T1 = qdef * here->BSIM3gtau; +#ifdef USE_OMP + here->BSIM3DdPt = m * here->BSIM3drainConductance; + here->BSIM3GgPt = m * (gcggb - ggtg); + here->BSIM3SsPt = m * here->BSIM3sourceConductance; + here->BSIM3BbPt = m * (here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs); + here->BSIM3DPdpPt = m * (here->BSIM3drainConductance + + here->BSIM3gds + here->BSIM3gbd + + 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); + here->BSIM3DdpPt = m * here->BSIM3drainConductance; + here->BSIM3GbPt = m * (gcggb + gcgdb + gcgsb + ggtb); + here->BSIM3GdpPt = m * (gcgdb - ggtd); + here->BSIM3GspPt = m * (gcgsb - ggts); + here->BSIM3SspPt = m * here->BSIM3sourceConductance; + here->BSIM3BgPt = m * (gcbgb - here->BSIM3gbgs); + 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->BSIM3DPbPt = m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + + gcdsb - dxpart * ggtb + - 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); + here->BSIM3SPsPt = m * here->BSIM3sourceConductance; + here->BSIM3SPbPt = m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb); + here->BSIM3SPdpPt = m * (here->BSIM3gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp); + + if (here->BSIM3nqsMod) + { here->BSIM3QqPt = m * (gqdef + here->BSIM3gtau); + + here->BSIM3DPqPt = m * (dxpart * here->BSIM3gtau); + here->BSIM3SPqPt = m * (sxpart * here->BSIM3gtau); + here->BSIM3GqPt = m * here->BSIM3gtau; + + here->BSIM3QgPt = m * (ggtg - gcqgb); + here->BSIM3QdpPt = m * (ggtd - gcqdb); + here->BSIM3QspPt = m * (ggts - gcqsb); + here->BSIM3QbPt = m * (ggtb - gcqbb); + } +#else + (*(here->BSIM3DdPtr) += m * here->BSIM3drainConductance); + (*(here->BSIM3GgPtr) += m * (gcggb - ggtg)); + (*(here->BSIM3SsPtr) += m * here->BSIM3sourceConductance); + (*(here->BSIM3BbPtr) += m * (here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs)); + (*(here->BSIM3DPdpPtr) += m * (here->BSIM3drainConductance + + here->BSIM3gds + here->BSIM3gbd + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp)); + (*(here->BSIM3SPspPtr) += m * (here->BSIM3sourceConductance + + here->BSIM3gds + here->BSIM3gbs + + FwdSum + gcssb + sxpart * ggts + + T1 * dsxpart_dVs + gbspsp)); + (*(here->BSIM3DdpPtr) -= m * here->BSIM3drainConductance); + (*(here->BSIM3GbPtr) -= m * (gcggb + gcgdb + gcgsb + ggtb)); + (*(here->BSIM3GdpPtr) += m * (gcgdb - ggtd)); + (*(here->BSIM3GspPtr) += m * (gcgsb - ggts)); + (*(here->BSIM3SspPtr) -= m * here->BSIM3sourceConductance); + (*(here->BSIM3BgPtr) += m * (gcbgb - here->BSIM3gbgs)); + (*(here->BSIM3BdpPtr) += m * (gcbdb - here->BSIM3gbd + gbbdp)); + (*(here->BSIM3BspPtr) += m * (gcbsb - here->BSIM3gbs + gbbsp)); + (*(here->BSIM3DPdPtr) -= m * here->BSIM3drainConductance); + (*(here->BSIM3DPgPtr) += m * (Gm + gcdgb + dxpart * ggtg + + T1 * ddxpart_dVg + gbdpg)); + (*(here->BSIM3DPbPtr) -= m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + + gcdsb - dxpart * ggtb + - T1 * ddxpart_dVb - gbdpb)); + (*(here->BSIM3DPspPtr) -= m * (here->BSIM3gds + FwdSum - gcdsb + - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp)); + (*(here->BSIM3SPgPtr) += m * (gcsgb - Gm + sxpart * ggtg + + T1 * dsxpart_dVg + gbspg)); + (*(here->BSIM3SPsPtr) -= m * here->BSIM3sourceConductance); + (*(here->BSIM3SPbPtr) -= m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb)); + (*(here->BSIM3SPdpPtr) -= m * (here->BSIM3gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); + + if (here->BSIM3nqsMod) + { *(here->BSIM3QqPtr) += m * (gqdef + here->BSIM3gtau); + + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + + *(here->BSIM3QgPtr) += m * (ggtg - gcqgb); + *(here->BSIM3QdpPtr) += m * (ggtd - gcqdb); + *(here->BSIM3QspPtr) += m * (ggts - gcqsb); + *(here->BSIM3QbPtr) += m * (ggtb - gcqbb); + } +#endif +line1000: ; +#ifndef USE_OMP + } /* End of Mosfet Instance */ +} /* End of Model Instance */ +#endif +return(OK); +} + +#ifdef USE_OMP +void BSIM3SIMDLoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) +{ + int InstCount, idx; + BSIM3instance **InstArray; + BSIM3instance *here; + BSIM3model *model = (BSIM3model*)inModel; + + InstArray = model->BSIM3InstanceArray; + InstCount = model->BSIM3InstCount; + + for(idx = 0; idx < InstCount; idx++) { + here = InstArray[idx]; + model = BSIM3SIMDmodPtr(here); + /* Update b for Ax = b */ + (*(ckt->CKTrhs + here->BSIM3gNode) -= here->BSIM3rhsG); + (*(ckt->CKTrhs + here->BSIM3bNode) -= here->BSIM3rhsB); + (*(ckt->CKTrhs + here->BSIM3dNodePrime) += here->BSIM3rhsD); + (*(ckt->CKTrhs + here->BSIM3sNodePrime) += here->BSIM3rhsS); + if (here->BSIM3nqsMod) + (*(ckt->CKTrhs + here->BSIM3qNode) += here->BSIM3rhsQ); + + /* Update A for Ax = b */ + (*(here->BSIM3DdPtr) += here->BSIM3DdPt); + (*(here->BSIM3GgPtr) += here->BSIM3GgPt); + (*(here->BSIM3SsPtr) += here->BSIM3SsPt); + (*(here->BSIM3BbPtr) += here->BSIM3BbPt); + (*(here->BSIM3DPdpPtr) += here->BSIM3DPdpPt); + (*(here->BSIM3SPspPtr) += here->BSIM3SPspPt); + (*(here->BSIM3DdpPtr) -= here->BSIM3DdpPt); + (*(here->BSIM3GbPtr) -= here->BSIM3GbPt); + (*(here->BSIM3GdpPtr) += here->BSIM3GdpPt); + (*(here->BSIM3GspPtr) += here->BSIM3GspPt); + (*(here->BSIM3SspPtr) -= here->BSIM3SspPt); + (*(here->BSIM3BgPtr) += here->BSIM3BgPt); + (*(here->BSIM3BdpPtr) += here->BSIM3BdpPt); + (*(here->BSIM3BspPtr) += here->BSIM3BspPt); + (*(here->BSIM3DPdPtr) -= here->BSIM3DPdPt); + (*(here->BSIM3DPgPtr) += here->BSIM3DPgPt); + (*(here->BSIM3DPbPtr) -= here->BSIM3DPbPt); + (*(here->BSIM3DPspPtr) -= here->BSIM3DPspPt); + (*(here->BSIM3SPgPtr) += here->BSIM3SPgPt); + (*(here->BSIM3SPsPtr) -= here->BSIM3SPsPt); + (*(here->BSIM3SPbPtr) -= here->BSIM3SPbPt); + (*(here->BSIM3SPdpPtr) -= here->BSIM3SPdpPt); + + if (here->BSIM3nqsMod) + { *(here->BSIM3QqPtr) += here->BSIM3QqPt; + + *(here->BSIM3DPqPtr) += here->BSIM3DPqPt; + *(here->BSIM3SPqPtr) += here->BSIM3SPqPt; + *(here->BSIM3GqPtr) -= here->BSIM3GqPt; + + *(here->BSIM3QgPtr) += here->BSIM3QgPt; + *(here->BSIM3QdpPtr) += here->BSIM3QdpPt; + *(here->BSIM3QspPtr) += here->BSIM3QspPt; + *(here->BSIM3QbPtr) += here->BSIM3QbPt; + } + + } +} +#endif diff --git a/src/spicelib/devices/bsim3simd/b3ldsel.c b/src/spicelib/devices/bsim3simd/b3ldsel.c new file mode 100644 index 000000000..b482ca326 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ldsel.c @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright 2020 Florian Ballenegger, Anamosic Ballenegger Design + ******************************************************************************* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "ngspice/ngspice.h" +#include "bsim3def.h" + +#define NDATASIMD 7 + +#ifndef USE_OMP +extern int BSIM3SIMDLoadSeq(BSIM3instance *here, CKTcircuit *ckt, double* data, int stride); +extern int BSIM3LoadSIMD(BSIM3instance **heres, CKTcircuit *ckt, double data[7][NSIMD]); +#else +extern void BSIM3SIMDLoadRhsMat(GENmodel *inModel, CKTcircuit *ckt); +extern int BSIM3SIMDLoadSeq(BSIM3instance *here, CKTcircuit *ckt, int); +extern int BSIM3LoadSIMD(BSIM3instance **heres, CKTcircuit *ckt); +#endif + + +#ifndef USE_OMP +int +BSIM3SIMDloadSel (GENmodel *inModel, CKTcircuit *ckt) +{ + #ifndef USE_OMP + double data[NDATASIMD][NSIMD]; + #endif + BSIM3group *group; /* a group of instance of same model, same pParam, same nqsMode, same geo and same off */ + BSIM3model *model = (BSIM3model*)inModel; + BSIM3instance* heres[NSIMD]; + + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + for (group=model->groupHead; group!=NULL; group=group->next) + { + int idx=0; + while(idx+NSIMD <= group->InstCount) + { + int count=0; + while((countInstCount)) + { + data[0][count]=NAN; + heres[count] = group->InstArray[idx]; + int local_error = BSIM3SIMDLoadSeq(group->InstArray[idx++],ckt, + &data[0][count],NSIMD + ); + if (local_error) return local_error; + if(!isnan(data[0][count])) + { + count++; + } + } + if(count==NSIMD) + { + int local_error; + /* process NSIMD instances at once */ + local_error = BSIM3LoadSIMD(heres, ckt, data); + if (local_error) return local_error; + } + else for(int i=0;iInstCount; idx++) { + int local_error = BSIM3SIMDLoadSeq(group->InstArray[idx], ckt, + NULL, 0); + if (local_error) return local_error; + } + } + + return 0; /* no error */ +} +#endif + + +#ifdef USE_OMP +int +BSIM3SIMDloadSel (GENmodel *inModel, CKTcircuit *ckt) +{ + /* + This version do omp parallel only inside groups + */ + BSIM3group *group; + BSIM3model *model = (BSIM3model*)inModel; + int error=0; + int idx=0; + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + for (group=model->groupHead; group!=NULL; group=group->next) + { + + #pragma omp parallel for + for (idx=0; idx <= group->InstCount-NSIMD; idx+=NSIMD) + { + int local_error; + int i; + int needeval=0; + for(i=0;iInstArray[idx+i]->BSIM3SIMDCheck=-1; + local_error = BSIM3SIMDLoadSeq(group->InstArray[idx+i], ckt, 1); + if (local_error) error = local_error; + + if(group->InstArray[idx+i]->BSIM3SIMDCheck!=-1) + needeval=1; + } + if(!needeval) + continue; /* all NSIMD instances are bypassed */ + local_error = BSIM3LoadSIMD(&group->InstArray[idx], ckt); + if (local_error) error = local_error; + } + /* omp mess with idx val after the for loop above, so we recalc it */ + idx = NSIMD*(group->InstCount/NSIMD); + for (; idx < group->InstCount; idx++) { + int local_error = BSIM3SIMDLoadSeq(group->InstArray[idx], ckt, 2); + if (local_error) error = local_error; + } + } + + BSIM3SIMDLoadRhsMat(inModel, ckt); + return error; +} + +#endif + + diff --git a/src/spicelib/devices/bsim3simd/b3ldseq.c b/src/spicelib/devices/bsim3simd/b3ldseq.c new file mode 100644 index 000000000..88f762b55 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ldseq.c @@ -0,0 +1,3325 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3ld.c of BSIM3v3.3.0 + * Author: 1991 JianHui Huang and Min-Chie Jeng. + * Modified by Mansun Chan (1995). + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + * Modified by Xuemei Xi, 10/05, 12/21, 2001. + * Modified by Xuemei Xi, 07/29/2005. + **********/ + + /********** + * Modified 2020 by Florian Ballenegger, Anamosic Ballenegger Design + * Distributed under the same license terms as the original code, + * see file "B3TERMS_OF_USE" + **********/ + +#ifdef SIMDIFYCPP + +/* simdify parser need to know that those names are C types + (however the actual type don't matter for this tool) */ +typedef int GENmodel; +typedef int CKTcircuit; +typedef int BSIM3instance; +typedef int BSIM3model; + +#else + +#define SIMDIFYCMD(cmd) +#define SIMDANY(err) err /* normal error handling when not SIMD */ +#define SIMDCOUNT(val) (val) + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define EPSOX 3.453133e-11 +#define EPSSI 1.03594e-10 +#define Charge_q 1.60219e-19 +#define DELTA_1 0.02 +#define DELTA_2 0.02 +#define DELTA_3 0.02 +#define DELTA_4 0.02 + +int BSIM3_ACM_saturationCurrents +( + BSIM3model *model, + BSIM3instance *here, + double *DrainSatCurrent, + double *SourceSatCurrent +) +{ + return 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 + ); +} + + +int BSIM3_ACM_junctionCapacitances +( + BSIM3model *model, + BSIM3instance *here, + double *areaDrainBulkCapacitance, + double *periDrainBulkCapacitance, + double *gateDrainBulkCapacitance, + double *areaSourceBulkCapacitance, + double *periSourceBulkCapacitance, + double *gateSourceBulkCapacitance +) +{ + return 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, + + areaDrainBulkCapacitance, + periDrainBulkCapacitance, + gateDrainBulkCapacitance, + areaSourceBulkCapacitance, + periSourceBulkCapacitance, + gateSourceBulkCapacitance + ); +} + +#endif + + +int +BSIM3SIMDLoadSeq( +BSIM3instance *here, +CKTcircuit *ckt, +#ifndef USE_OMP +double* data, +int stride +#else +int prelim +#endif +) + +{ +#ifndef SIMDIFYCPP + BSIM3model *model; +#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 czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; +double delvbd, delvbs, delvds, delvgd, delvgs; +double Vfbeff, dVfbeff_dVg, dVfbeff_dVb, V3, V4; +double gcbdb, gcbgb, gcbsb, gcddb, gcdgb, gcdsb, gcgdb, gcggb, gcgsb, gcsdb; +#ifndef NEWCONV +double tol; +#endif +double gcsgb, gcssb, MJ, MJSW, MJSWG; +double vbd, vbs, vds, vgb, vgd, vgs, vgdo; +#ifndef PREDICTOR +double xfact; +#endif +double qgate=0.0, qbulk=0.0, qdrn=0.0, qsrc, qinoi, cqgate, cqbulk, cqdrn; +double Vds, Vgs, Vbs, Gmbs, FwdSum, RevSum; +double Vgs_eff, Vfb; +double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb, Vth, dVth_dVb, dVth_dVd; +double Vgst, dVgst_dVg, dVgst_dVb, dVgs_eff_dVg, Nvtm; +double Vtm; +double n, dn_dVb, dn_dVd, voffcv, noff, dnoff_dVd, dnoff_dVb; +double ExpArg, V0, CoxWLcen, QovCox, LINK; +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 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 T0, dT0_dVg, dT0_dVd, dT0_dVb; +double T1, dT1_dVg, dT1_dVd, dT1_dVb; +double T2, dT2_dVg, dT2_dVd, dT2_dVb; +double T3, dT3_dVg, dT3_dVd, dT3_dVb; +double T4; +double T5; +double T6; +double T7; +double T8; +double T9; +double T10; +double T11, T12; +double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb; +double tmpuni; /* F.B. */ + +double VACLM, dVACLM_dVg, dVACLM_dVd, dVACLM_dVb; +double VADIBL, dVADIBL_dVg, dVADIBL_dVd, dVADIBL_dVb; + +double Xdep, dXdep_dVb, lt1, dlt1_dVb, ltw, dltw_dVb, Delt_vth, dDelt_vth_dVb; +double Theta0, dTheta0_dVb; +double TempRatio, tmp1, tmp2, tmp3, tmp4; +double DIBL_Sft, dDIBL_Sft_dVd, Lambda, dLambda_dVg; + +double Idtot, Ibtot; +#ifndef NOBYPASS +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 diffVds, dAbulk_dVg; +double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; +double gche, dgche_dVg, dgche_dVd, dgche_dVb; +double fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb; +double fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb; +double Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb; +double Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb; +double Ids, Gm, Gds, Gmb; +double Isub, Gbd, Gbg, Gbb; +double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb; +double CoxWovL; +double Rds, dRds_dVg, dRds_dVb, WVCox, WVCoxRds; +double Vgst2Vtm, VdsatCV, dVdsatCV_dVg, dVdsatCV_dVb; +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 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 Cgg, Cgd, Cgb, Cdg, Cdd, Cds; +double Csg, Csd, Css, Csb, Cbg, Cbd, Cbb; +double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0; +double dQac0_dVg, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; + +double m; + +struct bsim3SizeDependParam *pParam; +int ByPass, Check, ChargeComputationNeeded, error; +int nonconcount; +int BSIM3mode; + +ScalingFactor = 1.0e-9; +ChargeComputationNeeded = + ((ckt->CKTmode & (MODEDCTRANCURVE | MODEAC | MODETRAN | MODEINITSMSIG)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) + ? 1 : 0; + + pParam = here->pParam; + +#ifndef SIMDIFYCPP + model = BSIM3SIMDmodPtr(here); + Check = 1; + ByPass = 0; + + #ifdef USE_OMP + if(prelim==0) + goto prelimskip; + #endif + + if ((ckt->CKTmode & MODEINITSMSIG)) + { 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); + 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; + vgs = model->BSIM3type * here->BSIM3icVGS; + vbs = model->BSIM3type * here->BSIM3icVBS; + qdef = 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 * here->BSIM3vth0 + 0.1; + vds = 0.1; + } + } + 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) = + *(ckt->CKTstate1 + here->BSIM3vbs); + vbs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vbs)) + - (xfact * (*(ckt->CKTstate2 + here->BSIM3vbs))); + *(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->CKTstate1 + here->BSIM3vds); + vds = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3vds)) + - (xfact * (*(ckt->CKTstate2 + here->BSIM3vds))); + *(ckt->CKTstate0 + here->BSIM3vbd) = + *(ckt->CKTstate0 + here->BSIM3vbs) + - *(ckt->CKTstate0 + here->BSIM3vds); + *(ckt->CKTstate0 + here->BSIM3qdef) = + *(ckt->CKTstate1 + here->BSIM3qdef); + qdef = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3qdef)) + -(xfact * (*(ckt->CKTstate2 + here->BSIM3qdef))); + } + else + { +#endif /* PREDICTOR */ + vbs = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3bNode) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + vgs = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3gNode) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + vds = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3dNodePrime) + - *(ckt->CKTrhsOld + here->BSIM3sNodePrime)); + qdef = model->BSIM3type + * (*(ckt->CKTrhsOld + here->BSIM3qNode)); +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + + vbd = vbs - vds; + vgd = vgs - vds; + vgdo = *(ckt->CKTstate0 + here->BSIM3vgs) + - *(ckt->CKTstate0 + here->BSIM3vds); + delvbs = vbs - *(ckt->CKTstate0 + here->BSIM3vbs); + delvbd = vbd - *(ckt->CKTstate0 + here->BSIM3vbd); + delvgs = vgs - *(ckt->CKTstate0 + here->BSIM3vgs); + delvds = vds - *(ckt->CKTstate0 + here->BSIM3vds); + delvgd = vgd - vgdo; + + if (here->BSIM3mode >= 0) + { Idtot = here->BSIM3cd + here->BSIM3csub - here->BSIM3cbd; + cdhat = Idtot - here->BSIM3gbd * delvbd + + (here->BSIM3gmbs + here->BSIM3gbbs) * delvbs + + (here->BSIM3gm + here->BSIM3gbgs) * delvgs + + (here->BSIM3gds + here->BSIM3gbds) * delvds; + Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + cbhat = Ibtot + here->BSIM3gbd * delvbd + + (here->BSIM3gbs - here->BSIM3gbbs) * delvbs + - here->BSIM3gbgs * delvgs + - here->BSIM3gbds * delvds; + } + else + { Idtot = here->BSIM3cd - here->BSIM3cbd; + cdhat = Idtot - (here->BSIM3gbd - here->BSIM3gmbs) * delvbd + + here->BSIM3gm * delvgd + - here->BSIM3gds * delvds; + Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + cbhat = Ibtot + here->BSIM3gbs * delvbs + + (here->BSIM3gbd - here->BSIM3gbbs) * delvbd + - here->BSIM3gbgs * delvgd + + here->BSIM3gbds * delvds; + } + +#ifndef NOBYPASS + /* following should be one big if connected by && all over + * the place, but some C compilers can't handle that, so + * we split it up here to let them digest it in stages + */ + + if ((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass)) + if ((fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), + fabs(*(ckt->CKTstate0+here->BSIM3vbs))) + ckt->CKTvoltTol))) + if ((fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), + fabs(*(ckt->CKTstate0+here->BSIM3vbd))) + ckt->CKTvoltTol))) + if ((fabs(delvgs) < (ckt->CKTreltol * MAX(fabs(vgs), + fabs(*(ckt->CKTstate0+here->BSIM3vgs))) + ckt->CKTvoltTol))) + if ((fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), + fabs(*(ckt->CKTstate0+here->BSIM3vds))) + ckt->CKTvoltTol))) + if ((fabs(cdhat - Idtot) < ckt->CKTreltol + * MAX(fabs(cdhat),fabs(Idtot)) + ckt->CKTabstol)) + { tempv = MAX(fabs(cbhat),fabs(Ibtot)) + ckt->CKTabstol; + if ((fabs(cbhat - Ibtot)) < ckt->CKTreltol * tempv) + { /* bypass code */ + vbs = *(ckt->CKTstate0 + here->BSIM3vbs); + vbd = *(ckt->CKTstate0 + here->BSIM3vbd); + vgs = *(ckt->CKTstate0 + here->BSIM3vgs); + vds = *(ckt->CKTstate0 + here->BSIM3vds); + qdef = *(ckt->CKTstate0 + here->BSIM3qdef); + + vgd = vgs - vds; + vgb = vgs - vbs; + + cdrain = here->BSIM3cd; + if ((ckt->CKTmode & (MODETRAN | MODEAC)) || + ((ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC))) + { ByPass = 1; + qgate = here->BSIM3qgate; + qbulk = here->BSIM3qbulk; + qdrn = here->BSIM3qdrn; + goto line755; + } + else + { goto line850; + } + } + } + +#endif /*NOBYPASS*/ + von = here->BSIM3von; + if (*(ckt->CKTstate0 + here->BSIM3vds) >= 0.0) + { 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); + vds = vgs - vgd; + vds = -DEVlimvds(-vds, -(*(ckt->CKTstate0+here->BSIM3vds))); + vgs = vgd + vds; + } + + if (vds >= 0.0) + { 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); + vbs = vbd + vds; + } + } + + /* FB: store calculated data so far and return for SIMD processing */ + #ifndef USE_OMP + if(data && stride>0) + { + data[0*stride] = vbs; + data[1*stride] = vgs; + data[2*stride] = vds; + data[3*stride] = qdef; + data[4*stride] = cdhat; + data[5*stride] = cbhat; + data[6*stride] = Check ? 1.0 : 0.0; + if(0) + printf("ldseq return for SIMD !, %g %g %g %g %g %g, check=%d\n",vbs,vgs,vds,qdef,cdhat,cbhat,Check); + return OK; + } + #else + prelimskip: + if(prelim==1) + { + here->BSIM3SIMDvbs = vbs; + here->BSIM3SIMDvgs = vgs; + here->BSIM3SIMDvds = vds; + here->BSIM3SIMDqdef = qdef; + here->BSIM3SIMDcdhat = cdhat; + here->BSIM3SIMDcbhat = cbhat; + here->BSIM3SIMDCheck = Check; + return OK; + } + else if (prelim==0) + { + if(here->BSIM3SIMDCheck==-1) + printf("error load unitilized data\n"); + vbs = here->BSIM3SIMDvbs; + vgs = here->BSIM3SIMDvgs; + vds = here->BSIM3SIMDvds; + qdef = here->BSIM3SIMDqdef; + cdhat = here->BSIM3SIMDcdhat; + cbhat = here->BSIM3SIMDcbhat; + Check = here->BSIM3SIMDCheck; + } + #endif +#endif /* ifndef SIMDIFYCPP */ + +#ifdef SIMDIFYCPP +#ifndef USE_OMP + vbs = SIMDLOADDATA(0,data); + vgs = SIMDLOADDATA(1,data); + vds = SIMDLOADDATA(2,data); + qdef = SIMDLOADDATA(3,data); + cdhat = SIMDLOADDATA(4,data); + cbhat = SIMDLOADDATA(5,data); + Check = ((SIMDLOADDATA(6,data))>0.5); +#else + vbs = here->BSIM3SIMDvbs; + vgs = here->BSIM3SIMDvgs; + vds = here->BSIM3SIMDvds; + qdef = here->BSIM3SIMDqdef; + cdhat = here->BSIM3SIMDcdhat; + cbhat = here->BSIM3SIMDcbhat; + Check = here->BSIM3SIMDCheck; +#endif /* USE_OMP */ +#endif /* SIMDIFYCPP */ + + + /* determine DC current and derivatives */ + vbd = vbs - vds; + vgd = vgs - vds; + vgb = vgs - vbs; + + /* Source/drain junction diode DC model begins */ + Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; + /* acm model */ + if (model->BSIM3acmMod == 0) + { + SourceSatCurrent = 1.0e-14; + if ((here->BSIM3sourceArea <= 0.0) & (here->BSIM3sourcePerimeter <= 0.0)) + { ; /* F.B. SourceSatCurrent = 1.0e-14; moved above */ + } + else + { SourceSatCurrent = here->BSIM3sourceArea + * model->BSIM3jctTempSatCurDensity + + here->BSIM3sourcePerimeter + * model->BSIM3jctSidewallTempSatCurDensity; + } + DrainSatCurrent = 1.0e-14; + if ((here->BSIM3drainArea <= 0.0) & (here->BSIM3drainPerimeter <= 0.0)) + { ; /*F.B. DrainSatCurrent = 1.0e-14; moved above */ + } + else + { DrainSatCurrent = here->BSIM3drainArea + * model->BSIM3jctTempSatCurDensity + + here->BSIM3drainPerimeter + * model->BSIM3jctSidewallTempSatCurDensity; + } + } + else + { + /* F.B. made inline helper function easier to vectorize */ + error = BSIM3_ACM_saturationCurrents( + model, + here, + &DrainSatCurrent, + &SourceSatCurrent + ); + if (SIMDANY(error)) + return(error); + } + + if (SourceSatCurrent <= 0.0) + { here->BSIM3gbs = ckt->CKTgmin; + here->BSIM3cbs = here->BSIM3gbs * vbs; + } + else + { if (model->BSIM3ijth == 0.0) + { evbs = exp(vbs / Nvtm); + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { if (vbs < here->BSIM3vjsm) + { evbs = exp(vbs / Nvtm); + here->BSIM3gbs = SourceSatCurrent * evbs / Nvtm + ckt->CKTgmin; + here->BSIM3cbs = SourceSatCurrent * (evbs - 1.0) + + ckt->CKTgmin * vbs; + } + else + { T0 = here->BSIM3IsEvjsm / Nvtm; + here->BSIM3gbs = T0 + ckt->CKTgmin; + here->BSIM3cbs = here->BSIM3IsEvjsm - SourceSatCurrent + + T0 * (vbs - here->BSIM3vjsm) + + ckt->CKTgmin * vbs; + } + } + } + + if (DrainSatCurrent <= 0.0) + { here->BSIM3gbd = ckt->CKTgmin; + here->BSIM3cbd = here->BSIM3gbd * vbd; + } + else + { if (model->BSIM3ijth == 0.0) + { evbd = exp(vbd / Nvtm); + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) + + ckt->CKTgmin * vbd; + } + else + { if (vbd < here->BSIM3vjdm) + { evbd = exp(vbd / Nvtm); + here->BSIM3gbd = DrainSatCurrent * evbd / Nvtm + ckt->CKTgmin; + here->BSIM3cbd = DrainSatCurrent * (evbd - 1.0) + + ckt->CKTgmin * vbd; + } + else + { T0 = here->BSIM3IsEvjdm / Nvtm; + here->BSIM3gbd = T0 + ckt->CKTgmin; + here->BSIM3cbd = here->BSIM3IsEvjdm - DrainSatCurrent + + T0 * (vbd - here->BSIM3vjdm) + + ckt->CKTgmin * vbd; + } + } + } + /* End of diode DC model */ + + BSIM3mode = (vds >= 0.0); + if (vds >= 0.0) + { /* normal mode */ + Vds = vds; + Vgs = vgs; + Vbs = vbs; + } + else + { /* inverse mode */ + Vds = -vds; + Vgs = vgd; + Vbs = vbd; + } + int modesym; + modesym = 2*(BSIM3mode&0x1)-1; + here->BSIM3mode = modesym; /* restore +/- 1 */ + /* F.B. all subsequents here->BSIM3mode are replaced by local BSIM3mode +1/0 */ + + 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); + 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; + dPhis_dVb = -1.0; + sqrtPhis = sqrt(Phis); + dsqrtPhis_dVb = -0.5 / sqrtPhis; + } + Xdep = pParam->BSIM3Xdep0 * sqrtPhis / pParam->BSIM3sqrtPhi; + dXdep_dVb = (pParam->BSIM3Xdep0 / pParam->BSIM3sqrtPhi) + * dsqrtPhis_dVb; + + Leff = pParam->BSIM3leff; + Vtm = model->BSIM3vtm; +/* Vth Calculation */ + T3 = sqrt(Xdep); + V0 = pParam->BSIM3vbi - pParam->BSIM3phi; + + T0 = pParam->BSIM3dvt2 * Vbseff; + T2 = pParam->BSIM3dvt2; /* F.B. */ + if (T0 >= - 0.5) + { T1 = 1.0 + T0; + /* T2 = pParam->BSIM3dvt2; F.B. */ + } + 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 = T2 * T4 * T4; /* F.B. */ + } + 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; + } + ltw = model->BSIM3factor1 * T3 * T1; + dltw_dVb = model->BSIM3factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); + + T0 = -0.5 * pParam->BSIM3dvt1 * Leff / lt1; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + Theta0 = T1 * (1.0 + 2.0 * T1); + dT1_dVb = -T0 / lt1 * T1 * dlt1_dVb; + dTheta0_dVb = (1.0 + 4.0 * T1) * dT1_dVb; + } + else + { T1 = MIN_EXP; + Theta0 = T1 * (1.0 + 2.0 * T1); + dTheta0_dVb = 0.0; + } + + here->BSIM3thetavth = pParam->BSIM3dvt0 * Theta0; + Delt_vth = pParam->BSIM3dvt0 * Theta0 * V0; /* F.B. */ + dDelt_vth_dVb = pParam->BSIM3dvt0 * dTheta0_dVb * V0; + + T0 = -0.5 * pParam->BSIM3dvt1w * pParam->BSIM3weff * Leff / ltw; + if (T0 > -EXP_THRESHOLD) + { T1 = exp(T0); + T2 = T1 * (1.0 + 2.0 * T1); + dT1_dVb = -T0 / ltw * T1 * dltw_dVb; + dT2_dVb = (1.0 + 4.0 * T1) * dT1_dVb; + } + else + { T1 = MIN_EXP; + T2 = T1 * (1.0 + 2.0 * T1); + dT2_dVb = 0.0; + } + + T0 = pParam->BSIM3dvt0w * T2; + T2 = T0 * V0; + dT2_dVb = pParam->BSIM3dvt0w * dT2_dVb * V0; + + TempRatio = ckt->CKTtemp / model->BSIM3tnom - 1.0; + T0 = sqrt(1.0 + pParam->BSIM3nlx / Leff); + T1 = pParam->BSIM3k1ox * (T0 - 1.0) * pParam->BSIM3sqrtPhi + + (pParam->BSIM3kt1 + pParam->BSIM3kt1l / Leff + + pParam->BSIM3kt2 * Vbseff) * TempRatio; + tmp2 = model->BSIM3tox * pParam->BSIM3phi + / (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; + DIBL_Sft = dDIBL_Sft_dVd * Vds; + + 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; + + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb - pParam->BSIM3k2ox + - dDelt_vth_dVb - dT2_dVb + pParam->BSIM3k3b * tmp2 + - pParam->BSIM3etab * Vds * pParam->BSIM3theta0vb0 * T4 + + pParam->BSIM3kt2 * TempRatio; + dVth_dVd = -dDIBL_Sft_dVd; + +/* Calculate n */ + 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 + + 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 + + pParam->BSIM3cdscb * Theta0) / model->BSIM3cox * T0; + dn_dVd = pParam->BSIM3cdscd * Theta0 / model->BSIM3cox * T0; + } + +/* Poly Gate Si Depletion Effect */ + T0 = here->BSIM3vfb + pParam->BSIM3phi; + /* F.B. moved else into default */ + Vgs_eff = Vgs; + dVgs_eff_dVg = 1.0; + if ((pParam->BSIM3ngate > 1.e18) && (pParam->BSIM3ngate < 1.e25)) + if (Vgs > T0) + /* 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); + T2 = T1 * (T4 - 1.0); + T3 = 0.5 * T2 * T2 / T1; /* T3 = Vpoly */ + T7 = 1.12 - T3 - 0.05; + 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); + } + /*else + { Vgs_eff = Vgs; + dVgs_eff_dVg = 1.0; + }*/ + Vgst = Vgs_eff - Vth; + +/* Effective Vgst (Vgsteff) Calculation */ + + T10 = 2.0 * n * Vtm; + VgstNVt = Vgst / T10; + ExpArg = (2.0 * pParam->BSIM3voff - Vgst) / T10; + + #ifdef SIMDIFYCPP + /* F.B. Simd version use call exp only once */ + T0 = VgstNVt; + if (ExpArg > EXP_THRESHOLD) + T0 = (Vgst - pParam->BSIM3voff) / (n * Vtm); + ExpVgst = exp(T0); + #endif + + /* MCJ: Very small Vgst */ + if (VgstNVt > EXP_THRESHOLD) + { Vgsteff = Vgst; + dVgsteff_dVg = dVgs_eff_dVg; + dVgsteff_dVd = -dVth_dVd; + dVgsteff_dVb = -dVth_dVb; + } + else if (ExpArg > EXP_THRESHOLD) + { + #ifndef SIMDIFYCPP + T0 = (Vgst - pParam->BSIM3voff) / (n * Vtm); + ExpVgst = exp(T0); + #endif + 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 + { + #ifndef SIMDIFYCPP + ExpVgst = exp(VgstNVt); + #endif + 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; + + 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; + dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * Vtm * ExpArg * dn_dVb) + + (T2 - 1.0) / n * dn_dVb; + + Vgsteff = T1 / 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; + +/* Calculate Effective Channel Geometry */ + T9 = sqrtPhis - pParam->BSIM3sqrtPhi; + 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; + dWeff_dVg *= 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; + dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb; + } + 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; + dRds_dVb = pParam->BSIM3rds0 * pParam->BSIM3prwb * dsqrtPhis_dVb + * 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; + tmp2 = pParam->BSIM3a0 * T5; + 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; + dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb; + + T8 = pParam->BSIM3ags * pParam->BSIM3a0 * T7; + dAbulk_dVg = -T1 * T8; + Abulk = Abulk0 + dAbulk_dVg * Vgsteff; + dAbulk_dVb = dAbulk0_dVb - T8 * Vgsteff * (dT1_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; + } + + 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; + T10 = T9 * T9; + dAbulk_dVb *= T10; + dAbulk_dVg *= T10; + } + here->BSIM3Abulk = Abulk; + + T2 = pParam->BSIM3keta * Vbseff; + if (T2 >= -0.9) + { T0 = 1.0 / (1.0 + T2); + dT0_dVb = -pParam->BSIM3keta * T0 * T0; + } + else + /* added to avoid the problems caused by Keta */ + { 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; + + +/* Mobility calculation */ + if (model->BSIM3mobMod == 1) + { T0 = Vgsteff + Vth + Vth; + T2 = pParam->BSIM3ua + pParam->BSIM3uc * Vbseff; + T3 = T0 / model->BSIM3tox; + T5 = T3 * (T2 + pParam->BSIM3ub * T3); + dDenomi_dVg = (T2 + 2.0 * pParam->BSIM3ub * T3) / model->BSIM3tox; + 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 + / model->BSIM3tox); + dDenomi_dVg = (pParam->BSIM3ua + pParam->BSIM3uc * Vbseff + + 2.0 * pParam->BSIM3ub * Vgsteff / model->BSIM3tox) + / model->BSIM3tox; + dDenomi_dVd = 0.0; + dDenomi_dVb = Vgsteff * pParam->BSIM3uc / model->BSIM3tox; + } + 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; + dDenomi_dVg = (pParam->BSIM3ua + 2.0 * pParam->BSIM3ub * T3) * T2 + / 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; + dDenomi_dVg *= T9; + dDenomi_dVd *= T9; + dDenomi_dVb *= T9; + } + + 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; + + Esat = 2.0 * pParam->BSIM3vsattemp / ueff; + EsatL = Esat * Leff; + T0 = -EsatL /ueff; + dEsatL_dVg = T0 * dueff_dVg; + dEsatL_dVd = T0 * dueff_dVd; + dEsatL_dVb = T0 * dueff_dVb; + + /* Sqrt() */ + a1 = pParam->BSIM3a1; + 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); + } + + Vgst2Vtm = Vgsteff + 2.0 * Vtm; + here->BSIM3AbovVgst2Vtm = Abulk / Vgst2Vtm; + + if (Rds > 0) + { tmp2 = dRds_dVg / Rds + dWeff_dVg / Weff; + tmp3 = dRds_dVb / Rds + dWeff_dVb / Weff; + } + 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; + 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; + + 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; + } + else + { tmp1 = dLambda_dVg / (Lambda * Lambda); + T9 = Abulk * WVCoxRds; + T8 = Abulk * T9; + T7 = Vgst2Vtm * T9; + T6 = Vgst2Vtm * WVCoxRds; + 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); + + dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3) + + (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); + dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb + + 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); + dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3); + dT2_dVd = Vgst2Vtm * dEsatL_dVd; + + T3 = sqrt(T1 * T1 - 2.0 * T0 * T2); + Vdsat = (T1 - T3) / T0; + + dT3_dVg = (T1 * dT1_dVg - 2.0 * (T0 * dT2_dVg + T2 * dT0_dVg)) + / T3; + dT3_dVd = (T1 * dT1_dVd - 2.0 * (T0 * dT2_dVd + T2 * dT0_dVd)) + / T3; + dT3_dVb = (T1 * dT1_dVb - 2.0 * (T0 * dT2_dVb + T2 * dT0_dVb)) + / T3; + + dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2 + - 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; + dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0; + } + here->BSIM3vdsat = Vdsat; + +/* Effective Vds (Vdseff) Calculation */ + T1 = Vdsat - Vds - pParam->BSIM3delta; + dT1_dVg = dVdsat_dVg; + dT1_dVd = dVdsat_dVd - 1.0; + dT1_dVb = dVdsat_dVb; + + T2 = sqrt(T1 * T1 + 4.0 * pParam->BSIM3delta * Vdsat); + 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); + /* 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; + } + +/* Calculate VAsat */ + tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; + T9 = WVCoxRds * Vgsteff; + 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); + + dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * Vgsteff + - 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; + dT1_dVg = -2.0 * tmp1 + WVCoxRds * (Abulk * tmp2 + dAbulk_dVg); + dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3; + + Vasat = T0 / T1; + dVasat_dVg = (dT0_dVg - Vasat * dT1_dVg) / T1; + dVasat_dVb = (dT0_dVb - Vasat * dT1_dVb) / T1; + dVasat_dVd = dT0_dVd / T1; + + if (Vdseff > Vds) + Vdseff = Vds; + diffVds = Vds - Vdseff; + here->BSIM3Vdseff = Vdseff; + +/* Calculate VACLM */ + /* F.B. moved else clause into default values */ + VACLM = MAX_EXP; + dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0; + if (pParam->BSIM3pclm > 0.0) + if (diffVds > 1.0e-10) + { 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); + 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; + 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; + dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd); + } + +/* Calculate VADIBL */ + if (pParam->BSIM3thetaRout > 0.0) + { T8 = Abulk * Vdsat; + T0 = Vgst2Vtm * T8; + dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 + + Vgst2Vtm * Vdsat * dAbulk_dVg; + dT0_dVb = Vgst2Vtm * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); + dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd; + + T1 = Vgst2Vtm + T8; + dT1_dVg = 1.0 + Abulk * dVdsat_dVg + Vdsat * dAbulk_dVg; + dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat; + dT1_dVd = Abulk * dVdsat_dVd; + + 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); + VADIBL *= T3; + dVADIBL_dVg *= T3; + dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM3pdiblb) + * T3; + dVADIBL_dVd *= T3; + } + else +/* Added to avoid the discontinuity problem caused by pdiblcb */ + { 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; + dVADIBL_dVd *= T3; + VADIBL *= T3; + } + } + 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; + 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; + 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; + + T1 = VACLM * VADIBL / tmp3; + tmp3 *= tmp3; + dT1_dVg = (tmp1 * dVADIBL_dVg + tmp2 * dVACLM_dVg) / tmp3; + dT1_dVd = (tmp1 * dVADIBL_dVd + tmp2 * dVACLM_dVd) / tmp3; + dT1_dVb = (tmp1 * dVADIBL_dVb + tmp2 * dVACLM_dVb) / tmp3; + + Va = Vasat + T0 * T1; + dVa_dVg = dVasat_dVg + T1 * dT0_dVg + T0 * dT1_dVg; + dVa_dVd = dVasat_dVd + T1 * dT0_dVd + T0 * dT1_dVd; + dVa_dVb = dVasat_dVb + T1 * dT0_dVb + T0 * dT1_dVb; + +/* Calculate VASCBE */ + /* F.B. moved from else clauses to default val*/ + VASCBE = MAX_EXP; + dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; + 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; + /*dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0;*/ + } + } + +/* Calculate Ids */ + CoxWovL = model->BSIM3cox * Weff / Leff; + beta = ueff * CoxWovL; + dbeta_dVg = CoxWovL * dueff_dVg + beta * dWeff_dVg / Weff; + dbeta_dVd = CoxWovL * dueff_dVd; + 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_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; + + 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; + dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd + - gche * dfgche2_dVd) / fgche2; + dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb + - 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 ; + + 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; + dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va; + + T9 = diffVds / VASCBE; + T0 = 1.0 + T9; + Ids = Idsa * T0; + + Gm = T0 * dIdsa_dVg - Idsa * (dVdseff_dVg + T9 * dVASCBE_dVg) / VASCBE; + Gds = T0 * dIdsa_dVd + Idsa * (1.0 - dVdseff_dVd + - T9 * dVASCBE_dVd) / VASCBE; + Gmb = T0 * dIdsa_dVb - Idsa * (dVdseff_dVb + + T9 * dVASCBE_dVb) / VASCBE; + + Gds += Gm * dVgsteff_dVd; + Gmb += Gm * dVgsteff_dVb; + Gm *= dVgsteff_dVg; + Gmb *= dVbseff_dVb; + + /* Substrate current begins */ + tmpuni = pParam->BSIM3alpha0 + pParam->BSIM3alpha1 * Leff; + if ((tmpuni <= 0.0) || (pParam->BSIM3beta0 <= 0.0)) + { Isub = Gbd = Gbb = Gbg = 0.0; + } + else + { T2 = tmpuni / 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; + dT1_dVg = -T3 * dVdseff_dVg; + dT1_dVd = T3 * (1.0 - dVdseff_dVd); + dT1_dVb = -T3 * dVdseff_dVb; + } + Isub = T1 * Idsa; + Gbg = T1 * dIdsa_dVg + Idsa * dT1_dVg; + Gbd = T1 * dIdsa_dVd + Idsa * dT1_dVd; + Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb; + + Gbd += Gbg * dVgsteff_dVd; + 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 + * 0, 1, 2 & 3 stored in here->BSIM3qinv 1/1998 */ + + if ((model->BSIM3xpart < 0) || (!ChargeComputationNeeded)) + { qgate = qdrn = qsrc = qbulk = 0.0; + here->BSIM3cggb = 0.0; + here->BSIM3cgsb = 0.0; + here->BSIM3cgdb = 0.0; + here->BSIM3cdgb = 0.0; + here->BSIM3cdsb = 0.0; + here->BSIM3cddb = 0.0; + here->BSIM3cbgb = 0.0; + here->BSIM3cbsb = 0.0; + here->BSIM3cbdb = 0.0; + here->BSIM3cqdb = 0.0; + here->BSIM3cqsb = 0.0; + here->BSIM3cqgb = 0.0; + here->BSIM3cqbb = 0.0; + here->BSIM3gtau = 0.0; + goto finished; + } + else if (model->BSIM3capMod == 0) + { + if (Vbseff < 0.0) + { Vbseff = Vbs; + dVbseff_dVb = 1.0; + } + else + { Vbseff = pParam->BSIM3phi - Phis; + dVbseff_dVb = -dPhis_dVb; + } + + Vfb = pParam->BSIM3vfbcv; + Vth = Vfb + pParam->BSIM3phi + pParam->BSIM3k1ox * sqrtPhis; + Vgst = Vgs_eff - Vth; + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb; + dVgst_dVb = -dVth_dVb; + dVgst_dVg = dVgs_eff_dVg; + + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + * pParam->BSIM3leffCV; + Arg1 = Vgs_eff - Vbseff - Vfb; + + + /* F.B. rewrite for simd */ + T1 = 0.5 * pParam->BSIM3k1ox; + T2 = sqrt(T1 * T1 + Arg1); + T0 = CoxWL * T1 / T2; + if (Arg1 <= 0.0) + { + qgate = Arg1; + T0 = CoxWL; + here->BSIM3cbgb = -CoxWL * dVgs_eff_dVg; + } + else + { + qgate = pParam->BSIM3k1ox * (T2 - T1); + if(Vgst <= 0.0) + here->BSIM3cbgb = -here->BSIM3cggb; + } + qgate = CoxWL * qgate; + qbulk = -qgate; + qdrn = 0.0; + if((Arg1 <= 0.0) | (Vgst <= 0.0)) + { + 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; + + here->BSIM3cbdb = 0.0; + here->BSIM3cbsb = -here->BSIM3cgsb; + here->BSIM3qinv = 0.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; + + 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; + + 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->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); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) + * dVgs_eff_dVg; + T11 = -CoxWL * T5 * dVdsat_dVb; + here->BSIM3cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); + here->BSIM3cgsb = -(here->BSIM3cggb + T11 + + here->BSIM3cgdb); + T6 = 1.0 / Vdsat; + dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); + dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); + T7 = T9 * T7; + T8 = T9 * T8; + T9 = 2.0 * T4 * (1.0 - 3.0 * T5); + here->BSIM3cdgb = (T7 * dAlphaz_dVg - T9 + * 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 + + here->BSIM3cddb); + + T9 = 2.0 * T4 * (1.0 + T5); + T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) + * dVgs_eff_dVg; + T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb; + 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->BSIM3cbsb = -(here->BSIM3cgsb + + 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; + + 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; + 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->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)); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_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); + + 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)); + + here->BSIM3cdgb = (T7 * dAlphaz_dVg - tmp1 + * 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); + + 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->BSIM3cbdb = -(here->BSIM3cgdb + + here->BSIM3cddb + T10); /* bug fix */ + here->BSIM3cbsb = -(here->BSIM3cgsb + + 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; + + 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; + 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->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)); + + T5 = T3 / T1; + here->BSIM3cggb = CoxWL * (1.0 - T5 * dVdsat_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); + + 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); + + here->BSIM3cdgb = (T0 * dVdsat_dVg - T7 + * 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); + here->BSIM3cbdb = -(here->BSIM3cgdb + + 2.0 * here->BSIM3cddb); + here->BSIM3cbsb = -(here->BSIM3cgsb + + 2.0 * here->BSIM3cdsb); + here->BSIM3qinv = -(qgate + qbulk); + } + } + } + } + else + { if (Vbseff < 0.0) + { VbseffCV = Vbseff; + dVbseffCV_dVb = 1.0; + } + else + { VbseffCV = pParam->BSIM3phi - Phis; + dVbseffCV_dVb = -dPhis_dVb; + } + + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + * pParam->BSIM3leffCV; + + /* Seperate VgsteffCV with noff and voffcv */ + noff = n * pParam->BSIM3noff; + dnoff_dVd = pParam->BSIM3noff * dn_dVd; + dnoff_dVb = pParam->BSIM3noff * dn_dVb; + T0 = Vtm * noff; + voffcv = pParam->BSIM3voffcv; + VgstNVt = (Vgst - voffcv) / T0; + + /* F.B. rewrite */ + ExpVgst = exp(VgstNVt); + if (VgstNVt < -EXP_THRESHOLD) + ExpVgst = MIN_EXP; + Vgsteff = T0 * log(1.0 + ExpVgst); + + if (VgstNVt > EXP_THRESHOLD) + { Vgsteff = Vgst - voffcv; + dVgsteff_dVg = dVgs_eff_dVg; + dVgsteff_dVd = -dVth_dVd; + dVgsteff_dVb = -dVth_dVb; + } + else if (VgstNVt < -EXP_THRESHOLD) + { /* Vgsteff = T0 * log(1.0 + MIN_EXP); */ + dVgsteff_dVg = 0.0; + dVgsteff_dVd = Vgsteff / noff; + dVgsteff_dVb = dVgsteff_dVd * dnoff_dVb; + dVgsteff_dVd *= dnoff_dVd; + } + else + { /* ExpVgst = exp(VgstNVt); + Vgsteff = T0 * log(1.0 + ExpVgst); */ + dVgsteff_dVg = ExpVgst / (1.0 + ExpVgst); + dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + (Vgst - voffcv) + / noff * dnoff_dVd) + Vgsteff / noff * dnoff_dVd; + dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + (Vgst - voffcv) + / noff * dnoff_dVb) + Vgsteff / noff * dnoff_dVb; + dVgsteff_dVg *= dVgs_eff_dVg; + } /* End of VgsteffCV */ + + if (model->BSIM3capMod == 1) + { Vfb = here->BSIM3vfbzb; + Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff; + + if (Arg1 <= 0.0) + { 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); + 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; + + 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; + if (VdsatCV < Vds) + { 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; + Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb; + Cgd1 = Cgg1 * dVgsteff_dVd; + Cgg1 *= dVgsteff_dVg; + Cgg += Cgg1; + Cgb += Cgb1; + Cgd += Cgd1; + + 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; + Cbd += Cbd1; + + if (model->BSIM3xpart > 0.5) + T0 = -Two_Third_CoxWL; + else if (model->BSIM3xpart < 0.5) + T0 = -0.4 * CoxWL; + else + 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; + } + else + { T0 = AbulkCV * Vds; + T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20); + 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; + + qgate += CoxWL * (Vgsteff - 0.5 * Vds + T3); + 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; + + 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; + + if (model->BSIM3xpart > 0.5) + { /* 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); + 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; + } + 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 */ + qsrc = -0.5 * (qgate + qbulk); + Csg = -0.5 * (Cgg1 + Cbg1); + Csb = -0.5 * (Cgb1 + Cbb1); + Csd = -0.5 * (Cgd1 + Cbd1); + } + 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->BSIM3cdgb = -(Cgg + Cbg + Csg); + 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->BSIM3qinv = -(qgate + qbulk); + } + + else if (model->BSIM3capMod == 2) + { Vfb = here->BSIM3vfbzb; + V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3; + T0 = V3 * V3; /* F.B.*/ + T2 = 4.0 * DELTA_3 * Vfb; /* F.B.*/ + if (Vfb <= 0.0) + { T0 = T0 - T2; /* F.B. */ + T2 = -DELTA_3; /* F.B. */ + } + else + { T0 = T0 + T2; /* F.B. */ + T2 = DELTA_3; /* F.B. */ + } + T0 = sqrt(T0); /* F.B. */ + T2 = T2 / T0; /* F.B. */ + + 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; + if (pParam->BSIM3k1ox == 0.0) + { T1 = 0.0; + T2 = 0.0; + } + else if (T3 < 0.0) + { T1 = T0 + T3 / pParam->BSIM3k1ox; + T2 = CoxWL; + } + else + { T1 = sqrt(T0 * T0 + T3); + T2 = CoxWL * T0 / T1; + } + + 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 + + dVgsteff_dVb); + + AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; + 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 to eliminate non-zero VdseffCV at Vds=0.0 */ + if (Vds == 0.0) + { VdseffCV = 0.0; + dVdseffCV_dVg = 0.0; + dVdseffCV_dVb = 0.0; + } + + T0 = AbulkCV * VdseffCV; + T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20); + 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); + T6 = 12.0 * T2 * T2 * Vgsteff; + + qinoi = -CoxWL * (Vgsteff - 0.5 * T0 + AbulkCV * T3); + qgate = CoxWL * (Vgsteff - 0.5 * VdseffCV + T3); + 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; + + 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)); + 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; + + if (model->BSIM3xpart > 0.5) + { /* 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); + 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; + } + 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; + } + 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); + } + + 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; + + 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; + + here->BSIM3cggb = Cgg; + 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->BSIM3cbgb = Cbg; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; + here->BSIM3qinv = qinoi; + } + + /* New Charge-Thickness capMod (CTM) begins */ + 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 = 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 - here->BSIM3vfbzb) / Tox; + dT0_dVg = dVgs_eff_dVg / Tox; + dT0_dVb = -dVbseffCV_dVb / Tox; + + tmp = T0 * pParam->BSIM3acde; + /* F.B: moved from else clauses to default val */ + dTcen_dVg = dTcen_dVb = 0.0; + if ((-EXP_THRESHOLD < tmp) & (tmp < EXP_THRESHOLD)) + { Tcen = pParam->BSIM3ldeb * exp(tmp); + dTcen_dVg = pParam->BSIM3acde * Tcen; + dTcen_dVb = dTcen_dVg * dT0_dVb; + dTcen_dVg *= dT0_dVg; + } + if (tmp <= -EXP_THRESHOLD) + { Tcen = pParam->BSIM3ldeb * MIN_EXP; + /* dTcen_dVg = dTcen_dVb = 0.0; */ + } + if (tmp >= EXP_THRESHOLD) + { Tcen = pParam->BSIM3ldeb * MAX_EXP; + } + + LINK = 1.0e-3 * model->BSIM3tox; + V3 = pParam->BSIM3ldeb - Tcen - LINK; + V4 = sqrt(V3 * V3 + 4.0 * LINK * pParam->BSIM3ldeb); + Tcen = pParam->BSIM3ldeb - 0.5 * (V3 + V4); + T1 = 0.5 * (1.0 + V3 / V4); + dTcen_dVg *= T1; + dTcen_dVb *= T1; + + Ccen = EPSSI / Tcen; + T2 = Cox / (Cox + Ccen); + Coxeff = T2 * Ccen; + T3 = -Ccen / Tcen; + dCoxeff_dVg = T2 * T2 * T3; + dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; + dCoxeff_dVg *= dTcen_dVg; + CoxWLcen = CoxWL * Coxeff / Cox; + + Qac0 = CoxWLcen * (Vfbeff - here->BSIM3vfbzb); + QovCox = Qac0 / Coxeff; + dQac0_dVg = CoxWLcen * dVfbeff_dVg + + QovCox * dCoxeff_dVg; + dQac0_dVb = CoxWLcen * dVfbeff_dVb + + QovCox * dCoxeff_dVb; + + T0 = 0.5 * pParam->BSIM3k1ox; + 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; + T2 = CoxWLcen; + } + else + { T1 = sqrt(T0 * T0 + T3); + T2 = CoxWLcen * T0 / T1; + } + + Qsub0 = CoxWLcen * pParam->BSIM3k1ox * (T1 - T0); + QovCox = Qsub0 / Coxeff; + dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg) + + QovCox * dCoxeff_dVg; + dQsub0_dVd = -T2 * dVgsteff_dVd; + 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; + T0 = 0.5 * pParam->BSIM3sqrtPhi; + } + 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 */ + + /* VgDP = Vgsteff - DeltaPhi */ + T0 = Vgsteff - DeltaPhi - 0.001; + dT0_dVg = 1.0 - dDeltaPhi_dVg; + T1 = sqrt(T0 * T0 + Vgsteff * 0.004); + VgDP = 0.5 * (T0 + T1); + dVgDP_dVg = 0.5 * (dT0_dVg + (T0 * dT0_dVg + 0.002) / T1); + + T3 = 4.0 * (Vth - here->BSIM3vfbzb - pParam->BSIM3phi); + Tox += Tox; + if (T3 >= 0.0) + { T0 = (Vgsteff + T3) / Tox; + dT0_dVd = (dVgsteff_dVd + 4.0 * dVth_dVd) / Tox; + dT0_dVb = (dVgsteff_dVb + 4.0 * dVth_dVb) / Tox; + } + else + { T0 = (Vgsteff + 1.0e-20) / Tox; + dT0_dVd = dVgsteff_dVd / Tox; + dT0_dVb = dVgsteff_dVb / 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; + dTcen_dVd = Tox * dTcen_dVg; + dTcen_dVb = dTcen_dVd * dT0_dVb; + 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; + + 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; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_4 * VdsatCV); + dT1_dVg = (T0 + DELTA_4 + DELTA_4) / T1; + dT1_dVd = -T0 / T1; + dT1_dVb = dT1_dVg * dT0_dVb; + dT1_dVg *= dT0_dVg; + if (T0 >= 0.0) + { VdseffCV = VdsatCV - 0.5 * (T0 + T1); + dVdseffCV_dVg = 0.5 * (dT0_dVg - dT1_dVg); + dVdseffCV_dVd = 0.5 * (1.0 - dT1_dVd); + dVdseffCV_dVb = 0.5 * (dT0_dVb - dT1_dVb); + } + else + { T3 = (DELTA_4 + DELTA_4) / (T1 - T0); + T4 = 1.0 - T3; + T5 = VdsatCV * T3 / (T1 - T0); + VdseffCV = VdsatCV * T4; + dVdseffCV_dVg = dT0_dVg * T4 + T5 * (dT1_dVg - dT0_dVg); + dVdseffCV_dVd = T5 * (dT1_dVd + 1.0); + dVdseffCV_dVb = dT0_dVb * (1.0 - T5) + T5 * dT1_dVb; + } + + /* 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; + } + + T0 = AbulkCV * VdseffCV; + 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; + + 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; + + + T7 = 1.0 - AbulkCV; + T8 = T2 * T2; + T9 = 12.0 * T7 * T0 * T0 / (T8 * AbulkCV); + T10 = T9 * dVgDP_dVg; + 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; + + 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; + + 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 + * 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; + + 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 */ + qsrc = -0.5 * qgate; + Csg = -0.5 * Cgg1; + Csd = -0.5 * Cgd1; + Csb = -0.5 * Cgb1; + } + + 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; + + Cgg = Cgg1 - Cbg; + Cgd = Cgd1 - Cbd; + Cgb = Cgb1 - Cbb; + + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; + + here->BSIM3cggb = Cgg; + 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->BSIM3cbgb = Cbg; + here->BSIM3cbsb = -(Cbg + Cbd + Cbb); + here->BSIM3cbdb = Cbd; + here->BSIM3qinv = -qinoi; + } /* End of CTM */ + } + +finished: + /* Returning Values to Calling Routine */ + /* + * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE + */ + + here->BSIM3qgate = qgate; + here->BSIM3qbulk = qbulk; + here->BSIM3qdrn = qdrn; + here->BSIM3cd = cdrain; + + if (ChargeComputationNeeded) + { /* 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 + * 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 + */ + + double nstate_qbs = *(ckt->CKTstate0 + here->BSIM3qbs); /* F.B. */ + double nstate_qbd = *(ckt->CKTstate0 + here->BSIM3qbd); /* F.B. */ + + if (model->BSIM3acmMod == 0) + { + 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 { + /* F.B. made inline helper function easier to vectorize */ + error = BSIM3_ACM_junctionCapacitances( + model, + here, + &czbd, + &czbdsw, + &czbdswg, + &czbs, + &czbssw, + &czbsswg + ); + if (SIMDANY(error)) + return(error); + } + + MJ = model->BSIM3bulkJctBotGradingCoeff; + MJSW = model->BSIM3bulkJctSideGradingCoeff; + MJSWG = model->BSIM3bulkJctGateSideGradingCoeff; + + /* Source Bulk Junction */ + if (vbs == 0.0) + { nstate_qbs = 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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJ * log(arg)); + nstate_qbs = model->BSIM3PhiB * czbs + * (1.0 - arg * sarg) / (1.0 - MJ); + here->BSIM3capbs = czbs * sarg; + } + else + { nstate_qbs = 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 + sarg = exp(-MJSW * log(arg)); + nstate_qbs += model->BSIM3PhiBSW * czbssw + * (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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSWG * log(arg)); + nstate_qbs += model->BSIM3PhiBSWG * czbsswg + * (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); + nstate_qbs = vbs * (T0 + 0.5 * T1); + here->BSIM3capbs = T0 + T1; + } + /* F.B. moved memory write outside ifs */ + *(ckt->CKTstate0 + here->BSIM3qbs) = nstate_qbs; + + /* Drain Bulk Junction */ + if (vbd == 0.0) + { nstate_qbd = 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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJ * log(arg)); + nstate_qbd = model->BSIM3PhiB * czbd + * (1.0 - arg * sarg) / (1.0 - MJ); + here->BSIM3capbd = czbd * sarg; + } + else + { nstate_qbd = 0.0; + here->BSIM3capbd = 0.0; + } + if (czbdsw > 0.0) + { arg = 1.0 - vbd / model->BSIM3PhiBSW; + if (MJSW == 0.5) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSW * log(arg)); + nstate_qbd += 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) + sarg = 1.0 / sqrt(arg); + else + sarg = exp(-MJSWG * log(arg)); + nstate_qbd += model->BSIM3PhiBSWG * czbdswg + * (1.0 - arg * sarg) / (1.0 - MJSWG); + here->BSIM3capbd += czbdswg * sarg; + } + } + else + { T0 = czbd + czbdsw + czbdswg; + T1 = vbd * (czbd * MJ / model->BSIM3PhiB + czbdsw * MJSW + / model->BSIM3PhiBSW + czbdswg * MJSWG / model->BSIM3PhiBSWG); + nstate_qbd = vbd * (T0 + 0.5 * T1); + here->BSIM3capbd = T0 + T1; + } + /* F.B. moved memory write outside ifs */ + *(ckt->CKTstate0 + here->BSIM3qbd) = nstate_qbd; + } + + /* + * check convergence + */ + if ((here->BSIM3off == 0) || (!(ckt->CKTmode & MODEINITFIX))) + { + int nonconcount; + nonconcount = Check; + +#ifndef NEWCONV + { + Idtot = here->BSIM3cd - here->BSIM3cbd; + if (BSIM3mode) + { Idtot += here->BSIM3csub; + } + + tol = ckt->CKTreltol * MAX(fabs(cdhat), fabs(Idtot)) + + ckt->CKTabstol; + /* F.B. rewrite for simd */ + nonconcount = nonconcount | (fabs(cdhat - Idtot) >= tol); + Ibtot = here->BSIM3cbs + here->BSIM3cbd - here->BSIM3csub; + tol = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + + ckt->CKTabstol; + nonconcount = nonconcount | (fabs(cbhat - Ibtot) > tol); + } +#endif /* NEWCONV */ + #ifdef USE_OMP + nonconcount = nonconcount & 1; + here->BSIM3noncon = nonconcount; + #else + ckt->CKTnoncon += SIMDCOUNT(nonconcount); + #endif + } + #ifdef USE_OMP + else + here->BSIM3noncon=0; + #endif + + *(ckt->CKTstate0 + here->BSIM3vbs) = vbs; + *(ckt->CKTstate0 + here->BSIM3vbd) = vbd; + *(ckt->CKTstate0 + here->BSIM3vgs) = vgs; + *(ckt->CKTstate0 + here->BSIM3vds) = vds; + *(ckt->CKTstate0 + here->BSIM3qdef) = qdef; + + /* bulk and channel charge plus overlaps */ + + if (!ChargeComputationNeeded) + goto line850; +#ifndef NOBYPASS +line755: +#endif + /* NQS begins */ + if ((here->BSIM3nqsMod) || (here->BSIM3acnqsMod)) + { qcheq = -(qbulk + qgate); + + here->BSIM3cqgb = -(here->BSIM3cggb + here->BSIM3cbgb); + here->BSIM3cqdb = -(here->BSIM3cgdb + here->BSIM3cbdb); + here->BSIM3cqsb = -(here->BSIM3cgsb + here->BSIM3cbsb); + here->BSIM3cqbb = -(here->BSIM3cqgb + here->BSIM3cqdb + + here->BSIM3cqsb); + + gtau_drift = fabs(here->BSIM3tconst * qcheq) * ScalingFactor; + T0 = pParam->BSIM3leffCV * pParam->BSIM3leffCV; + 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 (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)); + + 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; + + ag0 = ckt->CKTag[0]; + /* F.B. moved from if/else arms to default val */ + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; + ggtg = ggtd = ggtb = ggts = 0.0; + CoxWL = model->BSIM3cox * pParam->BSIM3weffCV + * pParam->BSIM3leffCV; + if (BSIM3mode) /* F.B. > 0 removed */ + { if (here->BSIM3nqsMod == 0) + { gcggb = (here->BSIM3cggb + cgdo + cgso + + pParam->BSIM3cgbo ) * ag0; + gcgdb = (here->BSIM3cgdb - cgdo) * ag0; + gcgsb = (here->BSIM3cgsb - cgso) * ag0; + + gcdgb = (here->BSIM3cdgb - cgdo) * ag0; + gcddb = (here->BSIM3cddb + here->BSIM3capbd + cgdo) * ag0; + gcdsb = here->BSIM3cdsb * ag0; + + gcsgb = -(here->BSIM3cggb + here->BSIM3cbgb + + here->BSIM3cdgb + cgso) * ag0; + gcsdb = -(here->BSIM3cgdb + here->BSIM3cbdb + + here->BSIM3cddb) * ag0; + gcssb = (here->BSIM3capbs + cgso - (here->BSIM3cgsb + + here->BSIM3cbsb + here->BSIM3cdsb)) * ag0; + + gcbgb = (here->BSIM3cbgb - pParam->BSIM3cgbo) * ag0; + gcbdb = (here->BSIM3cbdb - here->BSIM3capbd) * ag0; + gcbsb = (here->BSIM3cbsb - here->BSIM3capbs) * ag0; + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate += qgd + qgs + qgb; + qbulk -= qgb; + qdrn -= qgd; + qsrc = -(qgate + qbulk + qdrn); + + /*ggtg = ggtd = ggtb = ggts = 0.0;*/ + sxpart = 0.6; + dxpart = 0.4; + /* ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; */ + } + else + { if (qcheq > 0.0) + T0 = here->BSIM3tconst * qdef * ScalingFactor; + else + T0 = -here->BSIM3tconst * qdef * ScalingFactor; + ggtg = T0 * here->BSIM3cqgb; + here->BSIM3gtg = ggtg; + ggtd = T0 * here->BSIM3cqdb; + here->BSIM3gtd = ggtd; + ggts = T0 * here->BSIM3cqsb; + here->BSIM3gts = ggts; + ggtb = T0 * here->BSIM3cqbb; + here->BSIM3gtb = ggtb; + gqdef = ScalingFactor * ag0; + + gcqgb = here->BSIM3cqgb * ag0; + gcqdb = here->BSIM3cqdb * ag0; + gcqsb = here->BSIM3cqsb * ag0; + gcqbb = here->BSIM3cqbb * ag0; + + gcggb = (cgdo + cgso + pParam->BSIM3cgbo ) * ag0; + gcgdb = -cgdo * ag0; + gcgsb = -cgso * ag0; + + gcdgb = -cgdo * ag0; + gcddb = (here->BSIM3capbd + cgdo) * ag0; + gcdsb = 0.0; + + gcsgb = -cgso * ag0; + gcsdb = 0.0; + gcssb = (here->BSIM3capbs + cgso) * ag0; + + gcbgb = -pParam->BSIM3cgbo * ag0; + gcbdb = -here->BSIM3capbd * ag0; + gcbsb = -here->BSIM3capbs * ag0; + + /*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; + + 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); + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate = qgd + qgs + qgb; + qbulk = -qgb; + qdrn = -qgd; + qsrc = -(qgate + qbulk + qdrn); + } + } + else + { if (here->BSIM3nqsMod == 0) + { gcggb = (here->BSIM3cggb + cgdo + cgso + + pParam->BSIM3cgbo ) * ag0; + gcgdb = (here->BSIM3cgsb - cgdo) * ag0; + gcgsb = (here->BSIM3cgdb - cgso) * ag0; + + gcdgb = -(here->BSIM3cggb + here->BSIM3cbgb + + here->BSIM3cdgb + cgdo) * ag0; + gcddb = (here->BSIM3capbd + cgdo - (here->BSIM3cgsb + + here->BSIM3cbsb + here->BSIM3cdsb)) * ag0; + gcdsb = -(here->BSIM3cgdb + here->BSIM3cbdb + + here->BSIM3cddb) * ag0; + + gcsgb = (here->BSIM3cdgb - cgso) * ag0; + gcsdb = here->BSIM3cdsb * ag0; + gcssb = (here->BSIM3cddb + here->BSIM3capbs + cgso) * ag0; + + gcbgb = (here->BSIM3cbgb - pParam->BSIM3cgbo) * ag0; + gcbdb = (here->BSIM3cbsb - here->BSIM3capbd) * ag0; + gcbsb = (here->BSIM3cbdb - here->BSIM3capbs) * ag0; + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate += qgd + qgs + qgb; + qbulk -= qgb; + qsrc = qdrn - qgs; + qdrn = -(qgate + qbulk + qsrc); + + /*ggtg = ggtd = ggtb = ggts = 0.0;*/ + sxpart = 0.4; + dxpart = 0.6; + /*ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0;*/ + } + else + { if (qcheq > 0.0) + T0 = here->BSIM3tconst * qdef * ScalingFactor; + else + T0 = -here->BSIM3tconst * qdef * ScalingFactor; + ggtg = T0 * here->BSIM3cqgb; + here->BSIM3gtg = ggtg; + ggts = T0 * here->BSIM3cqdb; + here->BSIM3gtd = ggts; + ggtd = T0 * here->BSIM3cqsb; + here->BSIM3gts = ggtd; + ggtb = T0 * here->BSIM3cqbb; + here->BSIM3gtb = ggtb; + gqdef = ScalingFactor * ag0; + + gcqgb = here->BSIM3cqgb * ag0; + gcqdb = here->BSIM3cqsb * ag0; + gcqsb = here->BSIM3cqdb * ag0; + gcqbb = here->BSIM3cqbb * ag0; + + gcggb = (cgdo + cgso + pParam->BSIM3cgbo) * ag0; + gcgdb = -cgdo * ag0; + gcgsb = -cgso * ag0; + + gcdgb = -cgdo * ag0; + gcddb = (here->BSIM3capbd + cgdo) * ag0; + gcdsb = 0.0; + + gcsgb = -cgso * ag0; + gcsdb = 0.0; + gcssb = (here->BSIM3capbs + cgso) * ag0; + + gcbgb = -pParam->BSIM3cgbo * ag0; + gcbdb = -here->BSIM3capbd * ag0; + gcbsb = -here->BSIM3capbs * ag0; + + /*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; + + 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); + + qgd = qgdo; + qgs = qgso; + qgb = pParam->BSIM3cgbo * vgb; + qgate = qgd + qgs + qgb; + qbulk = -qgb; + qsrc = -qgs; + qdrn = -(qgate + qbulk + qsrc); + } + } + + cqdef = cqcheq = 0.0; +#ifndef SIMDIFYCPP /* FB: no bypass in SIMD */ + if (ByPass) goto line860; +#endif + *(ckt->CKTstate0 + here->BSIM3qg) = qgate; + *(ckt->CKTstate0 + here->BSIM3qd) = qdrn + - *(ckt->CKTstate0 + here->BSIM3qbd); + *(ckt->CKTstate0 + here->BSIM3qb) = qbulk + + *(ckt->CKTstate0 + here->BSIM3qbd) + + *(ckt->CKTstate0 + here->BSIM3qbs); + + if (here->BSIM3nqsMod) + { *(ckt->CKTstate0 + here->BSIM3qcdump) = qdef * ScalingFactor; + *(ckt->CKTstate0 + here->BSIM3qcheq) = qcheq; + } + + /* store small signal parameters */ + if (ckt->CKTmode & MODEINITSMSIG) + { goto line1000; + } + if (!ChargeComputationNeeded) + goto line850; + + if (ckt->CKTmode & MODEINITTRAN) + { *(ckt->CKTstate1 + here->BSIM3qb) = + *(ckt->CKTstate0 + here->BSIM3qb); + *(ckt->CKTstate1 + here->BSIM3qg) = + *(ckt->CKTstate0 + here->BSIM3qg); + *(ckt->CKTstate1 + here->BSIM3qd) = + *(ckt->CKTstate0 + here->BSIM3qd); + if (here->BSIM3nqsMod) + { *(ckt->CKTstate1 + here->BSIM3qcheq) = + *(ckt->CKTstate0 + here->BSIM3qcheq); + *(ckt->CKTstate1 + here->BSIM3qcdump) = + *(ckt->CKTstate0 + here->BSIM3qcdump); + } + } + + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qb); + if (SIMDANY(error)) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qg); + if (SIMDANY(error)) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qd); + if (SIMDANY(error)) + return(error); + if (here->BSIM3nqsMod) + { error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qcdump); + if (SIMDANY(error)) + return(error); + error = NIintegrate(ckt, &geq, &ceq, 0.0, here->BSIM3qcheq); + if (SIMDANY(error)) + return(error); + } + + goto line860; + +line850: + /* initialize to zero charge conductance and current */ + ceqqg = ceqqb = ceqqd = 0.0; + cqcheq = cqdef = 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; + ggtg = ggtd = ggtb = ggts = 0.0; + /* F.B. moved dxpart assignment outside sxpart rhs */ + dxpart=0.6; + if(BSIM3mode) + dxpart=0.4; + sxpart = (1.0 - dxpart); + 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 * here->BSIM3u0temp * model->BSIM3vtm + / pParam->BSIM3leffCV / pParam->BSIM3leffCV + * ScalingFactor; + else + here->BSIM3gtau = 0.0; + + goto line900; + +line860: + /* evaluate equivalent charge current */ + + cqgate = *(ckt->CKTstate0 + here->BSIM3cqg); + cqbulk = *(ckt->CKTstate0 + here->BSIM3cqb); + cqdrn = *(ckt->CKTstate0 + here->BSIM3cqd); + + ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs; + ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs; + ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs; + + if (here->BSIM3nqsMod) + { T0 = ggtg * vgb - ggtd * vbd - ggts * vbs; + ceqqg += T0; + T1 = qdef * here->BSIM3gtau; + ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd + * vbd - ddxpart_dVs * vbs); + cqdef = *(ckt->CKTstate0 + here->BSIM3cqcdump) - gqdef * qdef; + cqcheq = *(ckt->CKTstate0 + here->BSIM3cqcheq) + - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0; + } + + if (ckt->CKTmode & MODEINITTRAN) + { *(ckt->CKTstate1 + here->BSIM3cqb) = + *(ckt->CKTstate0 + here->BSIM3cqb); + *(ckt->CKTstate1 + here->BSIM3cqg) = + *(ckt->CKTstate0 + here->BSIM3cqg); + *(ckt->CKTstate1 + here->BSIM3cqd) = + *(ckt->CKTstate0 + here->BSIM3cqd); + + if (here->BSIM3nqsMod) + { *(ckt->CKTstate1 + here->BSIM3cqcheq) = + *(ckt->CKTstate0 + here->BSIM3cqcheq); + *(ckt->CKTstate1 + here->BSIM3cqcdump) = + *(ckt->CKTstate0 + here->BSIM3cqcdump); + } + } + + /* + * load current vector + */ +line900: + + if (BSIM3mode) /* F.B. >= 0 removed */ + { Gm = here->BSIM3gm; + Gmbs = here->BSIM3gmbs; + FwdSum = Gm + Gmbs; + RevSum = 0.0; + cdreq = model->BSIM3type * (cdrain - here->BSIM3gds * vds + - Gm * vgs - Gmbs * vbs); + + ceqbd = -model->BSIM3type * (here->BSIM3csub + - here->BSIM3gbds * vds - here->BSIM3gbgs * vgs + - here->BSIM3gbbs * vbs); + ceqbs = 0.0; + + gbbdp = -here->BSIM3gbds; + gbbsp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); + + gbdpg = here->BSIM3gbgs; + gbdpdp = here->BSIM3gbds; + gbdpb = here->BSIM3gbbs; + gbdpsp = -(gbdpg + gbdpdp + gbdpb); + + gbspg = 0.0; + gbspdp = 0.0; + gbspb = 0.0; + gbspsp = 0.0; + } + else + { Gm = -here->BSIM3gm; + Gmbs = -here->BSIM3gmbs; + FwdSum = 0.0; + RevSum = -(Gm + Gmbs); + cdreq = -model->BSIM3type * (cdrain + here->BSIM3gds * vds + + Gm * vgd + Gmbs * vbd); + + ceqbs = -model->BSIM3type * (here->BSIM3csub + + here->BSIM3gbds * vds - here->BSIM3gbgs * vgd + - here->BSIM3gbbs * vbd); + ceqbd = 0.0; + + gbbsp = -here->BSIM3gbds; + gbbdp = (here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs); + + gbdpg = 0.0; + gbdpsp = 0.0; + gbdpb = 0.0; + gbdpdp = 0.0; + + gbspg = here->BSIM3gbgs; + gbspsp = here->BSIM3gbds; + gbspb = here->BSIM3gbbs; + gbspdp = -(gbspg + gbspsp + gbspb); + } + + if (model->BSIM3type > 0) + { ceqbs += (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbd += (here->BSIM3cbd - here->BSIM3gbd * vbd); + /* + ceqqg = ceqqg; + ceqqb = ceqqb; + ceqqd = ceqqd; + cqdef = cqdef; + cqcheq = cqcheq; + */ + } + else + { ceqbs -= (here->BSIM3cbs - here->BSIM3gbs * vbs); + ceqbd -= (here->BSIM3cbd - here->BSIM3gbd * vbd); + ceqqg = -ceqqg; + ceqqb = -ceqqb; + ceqqd = -ceqqd; + cqdef = -cqdef; + cqcheq = -cqcheq; + } + + m = here->BSIM3m; +#ifdef USE_OMP + here->BSIM3rhsG = m * ceqqg; + here->BSIM3rhsB = m * (ceqbs + ceqbd + ceqqb); + here->BSIM3rhsD = m * (ceqbd - cdreq - ceqqd); + here->BSIM3rhsS = m * (cdreq + ceqbs + ceqqg + + ceqqb + ceqqd); + #ifndef OMP_EFFMEM + if (here->BSIM3nqsMod) + here->BSIM3rhsQ = m * (cqcheq - cqdef); + #else + if (here->BSIM3nqsMod) + *(ckt->CKTrhs + here->BSIM3qNode) += m * (cqcheq - cqdef); + #endif +#else + (*(ckt->CKTrhs + here->BSIM3gNode) -= m * ceqqg); + (*(ckt->CKTrhs + here->BSIM3bNode) -= m * (ceqbs + ceqbd + ceqqb)); + (*(ckt->CKTrhs + here->BSIM3dNodePrime) += m * (ceqbd - cdreq - ceqqd)); + (*(ckt->CKTrhs + here->BSIM3sNodePrime) += m * (cdreq + ceqbs + ceqqg + + ceqqb + ceqqd)); + if (here->BSIM3nqsMod) + *(ckt->CKTrhs + here->BSIM3qNode) += m * (cqcheq - cqdef); +#endif + /* + * load y matrix + */ + + T1 = qdef * here->BSIM3gtau; +#ifdef USE_OMP + here->BSIM3DdPt = m * here->BSIM3drainConductance; + here->BSIM3GgPt = m * (gcggb - ggtg); + here->BSIM3SsPt = m * here->BSIM3sourceConductance; + here->BSIM3BbPt = m * (here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs); + here->BSIM3DPdpPt = m * (here->BSIM3drainConductance + + here->BSIM3gds + here->BSIM3gbd + + 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); + here->BSIM3DdpPt = m * here->BSIM3drainConductance; + here->BSIM3GbPt = m * (gcggb + gcgdb + gcgsb + ggtb); + here->BSIM3GdpPt = m * (gcgdb - ggtd); + here->BSIM3GspPt = m * (gcgsb - ggts); + here->BSIM3SspPt = m * here->BSIM3sourceConductance; + here->BSIM3BgPt = m * (gcbgb - here->BSIM3gbgs); + 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->BSIM3DPbPt = m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + + gcdsb - dxpart * ggtb + - 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); + here->BSIM3SPsPt = m * here->BSIM3sourceConductance; + here->BSIM3SPbPt = m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb); + here->BSIM3SPdpPt = m * (here->BSIM3gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp); + + #ifndef OMP_EFFMEM + if (here->BSIM3nqsMod) + { here->BSIM3QqPt = m * (gqdef + here->BSIM3gtau); + + here->BSIM3DPqPt = m * (dxpart * here->BSIM3gtau); + here->BSIM3SPqPt = m * (sxpart * here->BSIM3gtau); + here->BSIM3GqPt = m * here->BSIM3gtau; + + here->BSIM3QgPt = m * (ggtg - gcqgb); + here->BSIM3QdpPt = m * (ggtd - gcqdb); + here->BSIM3QspPt = m * (ggts - gcqsb); + here->BSIM3QbPt = m * (ggtb - gcqbb); + } + #else + if (here->BSIM3nqsMod) + { *(here->BSIM3QqPtr) += m * (gqdef + here->BSIM3gtau); + + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + + *(here->BSIM3QgPtr) += m * (ggtg - gcqgb); + *(here->BSIM3QdpPtr) += m * (ggtd - gcqdb); + *(here->BSIM3QspPtr) += m * (ggts - gcqsb); + *(here->BSIM3QbPtr) += m * (ggtb - gcqbb); + } + #endif +#else + (*(here->BSIM3DdPtr) += m * here->BSIM3drainConductance); + (*(here->BSIM3GgPtr) += m * (gcggb - ggtg)); + (*(here->BSIM3SsPtr) += m * here->BSIM3sourceConductance); + (*(here->BSIM3BbPtr) += m * (here->BSIM3gbd + here->BSIM3gbs + - gcbgb - gcbdb - gcbsb - here->BSIM3gbbs)); + (*(here->BSIM3DPdpPtr) += m * (here->BSIM3drainConductance + + here->BSIM3gds + here->BSIM3gbd + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp)); + (*(here->BSIM3SPspPtr) += m * (here->BSIM3sourceConductance + + here->BSIM3gds + here->BSIM3gbs + + FwdSum + gcssb + sxpart * ggts + + T1 * dsxpart_dVs + gbspsp)); + (*(here->BSIM3DdpPtr) -= m * here->BSIM3drainConductance); + (*(here->BSIM3GbPtr) -= m * (gcggb + gcgdb + gcgsb + ggtb)); + (*(here->BSIM3GdpPtr) += m * (gcgdb - ggtd)); + (*(here->BSIM3GspPtr) += m * (gcgsb - ggts)); + (*(here->BSIM3SspPtr) -= m * here->BSIM3sourceConductance); + (*(here->BSIM3BgPtr) += m * (gcbgb - here->BSIM3gbgs)); + (*(here->BSIM3BdpPtr) += m * (gcbdb - here->BSIM3gbd + gbbdp)); + (*(here->BSIM3BspPtr) += m * (gcbsb - here->BSIM3gbs + gbbsp)); + (*(here->BSIM3DPdPtr) -= m * here->BSIM3drainConductance); + (*(here->BSIM3DPgPtr) += m * (Gm + gcdgb + dxpart * ggtg + + T1 * ddxpart_dVg + gbdpg)); + (*(here->BSIM3DPbPtr) -= m * (here->BSIM3gbd - Gmbs + gcdgb + gcddb + + gcdsb - dxpart * ggtb + - T1 * ddxpart_dVb - gbdpb)); + (*(here->BSIM3DPspPtr) -= m * (here->BSIM3gds + FwdSum - gcdsb + - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp)); + (*(here->BSIM3SPgPtr) += m * (gcsgb - Gm + sxpart * ggtg + + T1 * dsxpart_dVg + gbspg)); + (*(here->BSIM3SPsPtr) -= m * here->BSIM3sourceConductance); + (*(here->BSIM3SPbPtr) -= m * (here->BSIM3gbs + Gmbs + gcsgb + gcsdb + + gcssb - sxpart * ggtb + - T1 * dsxpart_dVb - gbspb)); + (*(here->BSIM3SPdpPtr) -= m * (here->BSIM3gds + RevSum - gcsdb + - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp)); + + if (here->BSIM3nqsMod) + { *(here->BSIM3QqPtr) += m * (gqdef + here->BSIM3gtau); + + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + *(here->BSIM3GqPtr) -= m * here->BSIM3gtau; + + *(here->BSIM3QgPtr) += m * (ggtg - gcqgb); + *(here->BSIM3QdpPtr) += m * (ggtd - gcqdb); + *(here->BSIM3QspPtr) += m * (ggts - gcqsb); + *(here->BSIM3QbPtr) += m * (ggtb - gcqbb); + } +#endif +line1000: ; +return(OK); +} + diff --git a/src/spicelib/devices/bsim3simd/b3ldseq_simd4d.c b/src/spicelib/devices/bsim3simd/b3ldseq_simd4d.c new file mode 100644 index 000000000..dd668a80c --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ldseq_simd4d.c @@ -0,0 +1,5142 @@ + +/********** + * Copyright 2001 Regents of the University of California. All rights reserved. + * Original File: b3ld.c of BSIM3v3.2.4 + * Author: 1991 JianHui Huang and Min-Chie Jeng. + * Modified by Mansun Chan (1995). + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + * Modified by Xuemei Xi, 10/05, 12/21, 2001. + * Modified by Paolo Nenzi 2002 and Dietmar Warning 2003 + * Modified by Florian Ballenegger 2020 for SIMD version generation + **********/ + + /********** + * Modified 2020 by Florian Ballenegger, Anamosic Ballenegger Design + * Distributed under the same license terms as the original code, + * see file "B3TERMS_OF_USE" + **********/ +#ifdef USE_OMP +#pragma message "Warning: simd configured without USE_OMP but compiled with - ignored" +#endif +#ifndef NEWCONV +#pragma message "Warning: simd configured for NEWCONV but compiled without - use anyway" +#endif +#ifndef OMP_EFFMEM +#pragma message "Warning: simd configured for OMP_EFFMEM but compiled without - use anyway" +#endif +#ifdef NOBYPASS +#pragma message "Warning: simd configured without NOBYPASS but compiled with - ignored" +#endif +#ifdef PREDICTOR +#pragma message "Warning: simd configured without PREDICTOR but compiled with - ignored" +#endif + +{ + Vec4d SourceSatCurrent; + Vec4d DrainSatCurrent; + double ag0; + Vec4d qgd; + Vec4d qgs; + Vec4d qgb; + double von; + Vec4d cbhat; + Vec4d VgstNVt; + Vec4d ExpVgst; + Vec4d cdrain; + Vec4d cdhat; + Vec4d cdreq; + Vec4d ceqbd; + Vec4d ceqbs; + Vec4d ceqqb; + Vec4d ceqqd; + Vec4d ceqqg; + double ceq; + double geq; + Vec4d czbd; + Vec4d czbdsw; + Vec4d czbdswg; + Vec4d czbs; + Vec4d czbssw; + Vec4d czbsswg; + Vec4d evbd; + Vec4d evbs; + Vec4d arg; + Vec4d sarg; + double delvbd; + double delvbs; + double delvds; + double delvgd; + double delvgs; + Vec4d Vfbeff; + Vec4d dVfbeff_dVg; + Vec4d dVfbeff_dVb; + Vec4d V3; + Vec4d V4; + Vec4d gcbdb; + Vec4d gcbgb; + Vec4d gcbsb; + Vec4d gcddb; + Vec4d gcdgb; + Vec4d gcdsb; + Vec4d gcgdb; + Vec4d gcggb; + Vec4d gcgsb; + Vec4d gcsdb; + Vec4d gcsgb; + Vec4d gcssb; + double MJ; + double MJSW; + double MJSWG; + Vec4d vbd; + Vec4d vbs; + Vec4d vds; + Vec4d vgb; + Vec4d vgd; + Vec4d vgs; + double vgdo; + double xfact; + Vec4d qgate = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d qbulk = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d qdrn = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d qsrc; + Vec4d qinoi; + Vec4d cqgate; + Vec4d cqbulk; + Vec4d cqdrn; + Vec4d Vds; + Vec4d Vgs; + Vec4d Vbs; + Vec4d Gmbs; + Vec4d FwdSum; + Vec4d RevSum; + Vec4d Vgs_eff; + Vec4d Vfb; + Vec4d Phis; + Vec4d dPhis_dVb; + Vec4d sqrtPhis; + Vec4d dsqrtPhis_dVb; + Vec4d Vth; + Vec4d dVth_dVb; + Vec4d dVth_dVd; + Vec4d Vgst; + Vec4d dVgst_dVg; + Vec4d dVgst_dVb; + Vec4d dVgs_eff_dVg; + double Nvtm; + double Vtm; + Vec4d n; + Vec4d dn_dVb; + Vec4d dn_dVd; + double voffcv; + Vec4d noff; + Vec4d dnoff_dVd; + Vec4d dnoff_dVb; + Vec4d ExpArg; + double V0; + Vec4d CoxWLcen; + Vec4d QovCox; + double LINK; + Vec4d DeltaPhi; + Vec4d dDeltaPhi_dVg; + Vec4d VgDP; + Vec4d dVgDP_dVg; + double Cox; + double Tox; + Vec4d Tcen; + Vec4d dTcen_dVg; + Vec4d dTcen_dVd; + Vec4d dTcen_dVb; + Vec4d Ccen; + Vec4d Coxeff; + Vec4d dCoxeff_dVg; + Vec4d dCoxeff_dVd; + Vec4d dCoxeff_dVb; + Vec4d Denomi; + Vec4d dDenomi_dVg; + Vec4d dDenomi_dVd; + Vec4d dDenomi_dVb; + Vec4d ueff; + Vec4d dueff_dVg; + Vec4d dueff_dVd; + Vec4d dueff_dVb; + Vec4d Esat; + Vec4d Vdsat; + Vec4d EsatL; + Vec4d dEsatL_dVg; + Vec4d dEsatL_dVd; + Vec4d dEsatL_dVb; + Vec4d dVdsat_dVg; + Vec4d dVdsat_dVb; + Vec4d dVdsat_dVd; + Vec4d Vasat; + Vec4d dAlphaz_dVg; + Vec4d dAlphaz_dVb; + Vec4d dVasat_dVg; + Vec4d dVasat_dVb; + Vec4d dVasat_dVd; + Vec4d Va; + Vec4d dVa_dVd; + Vec4d dVa_dVg; + Vec4d dVa_dVb; + Vec4d Vbseff; + Vec4d dVbseff_dVb; + Vec4d VbseffCV; + Vec4d dVbseffCV_dVb; + Vec4d Arg1; + Vec4d One_Third_CoxWL; + Vec4d Two_Third_CoxWL; + Vec4d Alphaz; + double CoxWL; + Vec4d T0; + Vec4d dT0_dVg; + Vec4d dT0_dVd; + Vec4d dT0_dVb; + Vec4d T1; + Vec4d dT1_dVg; + Vec4d dT1_dVd; + Vec4d dT1_dVb; + Vec4d T2; + Vec4d dT2_dVg; + Vec4d dT2_dVd; + Vec4d dT2_dVb; + Vec4d T3; + Vec4d dT3_dVg; + Vec4d dT3_dVd; + Vec4d dT3_dVb; + Vec4d T4; + Vec4d T5; + Vec4d T6; + Vec4d T7; + Vec4d T8; + Vec4d T9; + Vec4d T10; + Vec4d T11; + Vec4d T12; + Vec4d tmp; + Vec4d Abulk; + Vec4d dAbulk_dVb; + Vec4d Abulk0; + Vec4d dAbulk0_dVb; + double tmpuni; + Vec4d VACLM; + Vec4d dVACLM_dVg; + Vec4d dVACLM_dVd; + Vec4d dVACLM_dVb; + Vec4d VADIBL; + Vec4d dVADIBL_dVg; + Vec4d dVADIBL_dVd; + Vec4d dVADIBL_dVb; + Vec4d Xdep; + Vec4d dXdep_dVb; + Vec4d lt1; + Vec4d dlt1_dVb; + Vec4d ltw; + Vec4d dltw_dVb; + Vec4d Delt_vth; + Vec4d dDelt_vth_dVb; + Vec4d Theta0; + Vec4d dTheta0_dVb; + double TempRatio; + Vec4d tmp1; + Vec4d tmp2; + Vec4d tmp3; + Vec4d tmp4; + Vec4d DIBL_Sft; + Vec4d dDIBL_Sft_dVd; + Vec4d Lambda; + Vec4d dLambda_dVg; + double Idtot; + double Ibtot; + double tempv; + double a1; + double ScalingFactor; + Vec4d Vgsteff; + Vec4d dVgsteff_dVg; + Vec4d dVgsteff_dVd; + Vec4d dVgsteff_dVb; + Vec4d Vdseff; + Vec4d dVdseff_dVg; + Vec4d dVdseff_dVd; + Vec4d dVdseff_dVb; + Vec4d VdseffCV; + Vec4d dVdseffCV_dVg; + Vec4d dVdseffCV_dVd; + Vec4d dVdseffCV_dVb; + Vec4d diffVds; + Vec4d dAbulk_dVg; + Vec4d beta; + Vec4d dbeta_dVg; + Vec4d dbeta_dVd; + Vec4d dbeta_dVb; + Vec4d gche; + Vec4d dgche_dVg; + Vec4d dgche_dVd; + Vec4d dgche_dVb; + Vec4d fgche1; + Vec4d dfgche1_dVg; + Vec4d dfgche1_dVd; + Vec4d dfgche1_dVb; + Vec4d fgche2; + Vec4d dfgche2_dVg; + Vec4d dfgche2_dVd; + Vec4d dfgche2_dVb; + Vec4d Idl; + Vec4d dIdl_dVg; + Vec4d dIdl_dVd; + Vec4d dIdl_dVb; + Vec4d Idsa; + Vec4d dIdsa_dVg; + Vec4d dIdsa_dVd; + Vec4d dIdsa_dVb; + Vec4d Ids; + Vec4d Gm; + Vec4d Gds; + Vec4d Gmb; + Vec4d Isub; + Vec4d Gbd; + Vec4d Gbg; + Vec4d Gbb; + Vec4d VASCBE; + Vec4d dVASCBE_dVg; + Vec4d dVASCBE_dVd; + Vec4d dVASCBE_dVb; + Vec4d CoxWovL; + Vec4d Rds; + Vec4d dRds_dVg; + Vec4d dRds_dVb; + Vec4d WVCox; + Vec4d WVCoxRds; + Vec4d Vgst2Vtm; + Vec4d VdsatCV; + Vec4d dVdsatCV_dVg; + Vec4d dVdsatCV_dVb; + double Leff; + Vec4d Weff; + Vec4d dWeff_dVg; + Vec4d dWeff_dVb; + Vec4d AbulkCV; + Vec4d dAbulkCV_dVb; + Vec4d qgdo; + Vec4d qgso; + Vec4d cgdo; + Vec4d cgso; + Vec4d qcheq = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d qdef; + Vec4d gqdef = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d cqdef; + Vec4d cqcheq; + Vec4d gtau_diff; + Vec4d gtau_drift; + Vec4d gcqdb = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d gcqsb = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d gcqgb = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d gcqbb = (Vec4d ){0.0, 0.0, 0.0, 0.0}; + Vec4d dxpart; + Vec4d sxpart; + Vec4d ggtg; + Vec4d ggtd; + Vec4d ggts; + Vec4d ggtb; + Vec4d ddxpart_dVd; + Vec4d ddxpart_dVg; + Vec4d ddxpart_dVb; + Vec4d ddxpart_dVs; + Vec4d dsxpart_dVd; + Vec4d dsxpart_dVg; + Vec4d dsxpart_dVb; + Vec4d dsxpart_dVs; + Vec4d gbspsp; + Vec4d gbbdp; + Vec4d gbbsp; + Vec4d gbspg; + Vec4d gbspb; + Vec4d gbspdp; + Vec4d gbdpdp; + Vec4d gbdpg; + Vec4d gbdpb; + Vec4d gbdpsp; + Vec4d Cgg; + Vec4d Cgd; + Vec4d Cgb; + Vec4d Cdg; + Vec4d Cdd; + Vec4d Cds; + Vec4d Csg; + Vec4d Csd; + Vec4d Css; + Vec4d Csb; + Vec4d Cbg; + Vec4d Cbd; + Vec4d Cbb; + Vec4d Cgg1; + Vec4d Cgb1; + Vec4d Cgd1; + Vec4d Cbg1; + Vec4d Cbb1; + Vec4d Cbd1; + Vec4d Qac0; + Vec4d Qsub0; + Vec4d dQac0_dVg; + Vec4d dQac0_dVb; + Vec4d dQsub0_dVg; + Vec4d dQsub0_dVd; + Vec4d dQsub0_dVb; + Vec4d m; + struct bsim3SizeDependParam *pParam; + int ByPass; + Vec4m Check; + int ChargeComputationNeeded; + int error; + Vec4m nonconcount; + Vec4m BSIM3mode; + ScalingFactor = 1.0e-9; + ChargeComputationNeeded = ((ckt->CKTmode & (((MODEDCTRANCURVE | MODEAC) | MODETRAN) | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? (1) : (0); + pParam = heres[0]->pParam; + vbs = vec4_SIMDLOADDATA(0, data); + vgs = vec4_SIMDLOADDATA(1, data); + vds = vec4_SIMDLOADDATA(2, data); + qdef = vec4_SIMDLOADDATA(3, data); + cdhat = vec4_SIMDLOADDATA(4, data); + cbhat = vec4_SIMDLOADDATA(5, data); + Check = vec4_SIMDLOADDATA(6, data) > 0.5; + vbd = vbs - vds; + vgd = vgs - vds; + vgb = vgs - vbs; + Nvtm = model->BSIM3vtm * model->BSIM3jctEmissionCoeff; + if (model->BSIM3acmMod == 0) + { + SourceSatCurrent = vec4_SIMDTOVECTOR(1.0e-14); + if (1) + { + Vec4m condmask0 = (((Vec4d ){heres[0]->BSIM3sourceArea, heres[1]->BSIM3sourceArea, heres[2]->BSIM3sourceArea, heres[3]->BSIM3sourceArea}) <= 0.0) & (((Vec4d ){heres[0]->BSIM3sourcePerimeter, heres[1]->BSIM3sourcePerimeter, heres[2]->BSIM3sourcePerimeter, heres[3]->BSIM3sourcePerimeter}) <= 0.0); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + ; + } + { + SourceSatCurrent = vec4_blend(SourceSatCurrent, (((Vec4d ){heres[0]->BSIM3sourceArea, heres[1]->BSIM3sourceArea, heres[2]->BSIM3sourceArea, heres[3]->BSIM3sourceArea}) * model->BSIM3jctTempSatCurDensity) + (((Vec4d ){heres[0]->BSIM3sourcePerimeter, heres[1]->BSIM3sourcePerimeter, heres[2]->BSIM3sourcePerimeter, heres[3]->BSIM3sourcePerimeter}) * model->BSIM3jctSidewallTempSatCurDensity), condmask_false0); + } + } + + DrainSatCurrent = vec4_SIMDTOVECTOR(1.0e-14); + if (1) + { + Vec4m condmask0 = (((Vec4d ){heres[0]->BSIM3drainArea, heres[1]->BSIM3drainArea, heres[2]->BSIM3drainArea, heres[3]->BSIM3drainArea}) <= 0.0) & (((Vec4d ){heres[0]->BSIM3drainPerimeter, heres[1]->BSIM3drainPerimeter, heres[2]->BSIM3drainPerimeter, heres[3]->BSIM3drainPerimeter}) <= 0.0); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + ; + } + { + DrainSatCurrent = vec4_blend(DrainSatCurrent, (((Vec4d ){heres[0]->BSIM3drainArea, heres[1]->BSIM3drainArea, heres[2]->BSIM3drainArea, heres[3]->BSIM3drainArea}) * model->BSIM3jctTempSatCurDensity) + (((Vec4d ){heres[0]->BSIM3drainPerimeter, heres[1]->BSIM3drainPerimeter, heres[2]->BSIM3drainPerimeter, heres[3]->BSIM3drainPerimeter}) * model->BSIM3jctSidewallTempSatCurDensity), condmask_false0); + } + } + + } + else + { + error = vec4_BSIM3_ACM_saturationCurrents(model, heres, &DrainSatCurrent, &SourceSatCurrent); + if (SIMDANY(error)) + return error; + + } + + if (1) + { + Vec4m condmask0 = SourceSatCurrent <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + { + if (condmask_true0[0]) + heres[0]->BSIM3gbs = ckt->CKTgmin; + + if (condmask_true0[1]) + heres[1]->BSIM3gbs = ckt->CKTgmin; + + if (condmask_true0[2]) + heres[2]->BSIM3gbs = ckt->CKTgmin; + + if (condmask_true0[3]) + heres[3]->BSIM3gbs = ckt->CKTgmin; + + } + { + Vec4d val = ((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs}) * vbs; + if (condmask_true0[0]) + heres[0]->BSIM3cbs = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cbs = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cbs = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cbs = val[3]; + + } + } + { + if (model->BSIM3ijth == 0.0) + { + evbs = vec4_blend(evbs, vec4_exp(vbs / Nvtm), condmask_false0); + { + Vec4d val = ((SourceSatCurrent * evbs) / Nvtm) + ckt->CKTgmin; + if (condmask_false0[0]) + heres[0]->BSIM3gbs = val[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gbs = val[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gbs = val[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gbs = val[3]; + + } + { + Vec4d val = (SourceSatCurrent * (evbs - 1.0)) + (ckt->CKTgmin * vbs); + if (condmask_false0[0]) + heres[0]->BSIM3cbs = val[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3cbs = val[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3cbs = val[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3cbs = val[3]; + + } + } + else + { + if (1) + { + Vec4m condmask1 = vbs < ((Vec4d ){heres[0]->BSIM3vjsm, heres[1]->BSIM3vjsm, heres[2]->BSIM3vjsm, heres[3]->BSIM3vjsm}); + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + evbs = vec4_blend(evbs, vec4_exp(vbs / Nvtm), condmask_true1); + { + Vec4d val = ((SourceSatCurrent * evbs) / Nvtm) + ckt->CKTgmin; + if (condmask_true1[0]) + heres[0]->BSIM3gbs = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3gbs = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3gbs = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3gbs = val[3]; + + } + { + Vec4d val = (SourceSatCurrent * (evbs - 1.0)) + (ckt->CKTgmin * vbs); + if (condmask_true1[0]) + heres[0]->BSIM3cbs = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbs = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbs = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbs = val[3]; + + } + } + { + T0 = vec4_blend(T0, ((Vec4d ){heres[0]->BSIM3IsEvjsm, heres[1]->BSIM3IsEvjsm, heres[2]->BSIM3IsEvjsm, heres[3]->BSIM3IsEvjsm}) / Nvtm, condmask_false1); + { + Vec4d val = T0 + ckt->CKTgmin; + if (condmask_false1[0]) + heres[0]->BSIM3gbs = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3gbs = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3gbs = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3gbs = val[3]; + + } + { + Vec4d val = ((((Vec4d ){heres[0]->BSIM3IsEvjsm, heres[1]->BSIM3IsEvjsm, heres[2]->BSIM3IsEvjsm, heres[3]->BSIM3IsEvjsm}) - SourceSatCurrent) + (T0 * (vbs - ((Vec4d ){heres[0]->BSIM3vjsm, heres[1]->BSIM3vjsm, heres[2]->BSIM3vjsm, heres[3]->BSIM3vjsm})))) + (ckt->CKTgmin * vbs); + if (condmask_false1[0]) + heres[0]->BSIM3cbs = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbs = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbs = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbs = val[3]; + + } + } + } + + } + + } + } + + if (1) + { + Vec4m condmask0 = DrainSatCurrent <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + { + if (condmask_true0[0]) + heres[0]->BSIM3gbd = ckt->CKTgmin; + + if (condmask_true0[1]) + heres[1]->BSIM3gbd = ckt->CKTgmin; + + if (condmask_true0[2]) + heres[2]->BSIM3gbd = ckt->CKTgmin; + + if (condmask_true0[3]) + heres[3]->BSIM3gbd = ckt->CKTgmin; + + } + { + Vec4d val = ((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd}) * vbd; + if (condmask_true0[0]) + heres[0]->BSIM3cbd = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cbd = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cbd = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cbd = val[3]; + + } + } + { + if (model->BSIM3ijth == 0.0) + { + evbd = vec4_blend(evbd, vec4_exp(vbd / Nvtm), condmask_false0); + { + Vec4d val = ((DrainSatCurrent * evbd) / Nvtm) + ckt->CKTgmin; + if (condmask_false0[0]) + heres[0]->BSIM3gbd = val[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gbd = val[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gbd = val[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gbd = val[3]; + + } + { + Vec4d val = (DrainSatCurrent * (evbd - 1.0)) + (ckt->CKTgmin * vbd); + if (condmask_false0[0]) + heres[0]->BSIM3cbd = val[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3cbd = val[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3cbd = val[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3cbd = val[3]; + + } + } + else + { + if (1) + { + Vec4m condmask1 = vbd < ((Vec4d ){heres[0]->BSIM3vjdm, heres[1]->BSIM3vjdm, heres[2]->BSIM3vjdm, heres[3]->BSIM3vjdm}); + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + evbd = vec4_blend(evbd, vec4_exp(vbd / Nvtm), condmask_true1); + { + Vec4d val = ((DrainSatCurrent * evbd) / Nvtm) + ckt->CKTgmin; + if (condmask_true1[0]) + heres[0]->BSIM3gbd = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3gbd = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3gbd = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3gbd = val[3]; + + } + { + Vec4d val = (DrainSatCurrent * (evbd - 1.0)) + (ckt->CKTgmin * vbd); + if (condmask_true1[0]) + heres[0]->BSIM3cbd = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbd = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbd = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbd = val[3]; + + } + } + { + T0 = vec4_blend(T0, ((Vec4d ){heres[0]->BSIM3IsEvjdm, heres[1]->BSIM3IsEvjdm, heres[2]->BSIM3IsEvjdm, heres[3]->BSIM3IsEvjdm}) / Nvtm, condmask_false1); + { + Vec4d val = T0 + ckt->CKTgmin; + if (condmask_false1[0]) + heres[0]->BSIM3gbd = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3gbd = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3gbd = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3gbd = val[3]; + + } + { + Vec4d val = ((((Vec4d ){heres[0]->BSIM3IsEvjdm, heres[1]->BSIM3IsEvjdm, heres[2]->BSIM3IsEvjdm, heres[3]->BSIM3IsEvjdm}) - DrainSatCurrent) + (T0 * (vbd - ((Vec4d ){heres[0]->BSIM3vjdm, heres[1]->BSIM3vjdm, heres[2]->BSIM3vjdm, heres[3]->BSIM3vjdm})))) + (ckt->CKTgmin * vbd); + if (condmask_false1[0]) + heres[0]->BSIM3cbd = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbd = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbd = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbd = val[3]; + + } + } + } + + } + + } + } + + BSIM3mode = vds >= 0.0; + if (1) + { + Vec4m condmask0 = vds >= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Vds = vec4_blend(Vds, vds, condmask_true0); + Vgs = vec4_blend(Vgs, vgs, condmask_true0); + Vbs = vec4_blend(Vbs, vbs, condmask_true0); + } + { + Vds = vec4_blend(Vds, -vds, condmask_false0); + Vgs = vec4_blend(Vgs, vgd, condmask_false0); + Vbs = vec4_blend(Vbs, vbd, condmask_false0); + } + } + + Vec4m modesym; + modesym = (2 * (BSIM3mode & 0x1)) - 1; + { + heres[0]->BSIM3mode = modesym[0]; + heres[1]->BSIM3mode = modesym[1]; + heres[2]->BSIM3mode = modesym[2]; + heres[3]->BSIM3mode = modesym[3]; + } + T0 = (Vbs - pParam->BSIM3vbsc) - 0.001; + T1 = vec4_sqrt((T0 * T0) - (0.004 * pParam->BSIM3vbsc)); + Vbseff = pParam->BSIM3vbsc + (0.5 * (T0 + T1)); + dVbseff_dVb = 0.5 * (1.0 + (T0 / T1)); + if (1) + { + Vec4m condmask0 = Vbseff < Vbs; + Vec4m condmask_true0 = condmask0; + { + Vbseff = vec4_blend(Vbseff, Vbs, condmask_true0); + } + } + + if (1) + { + Vec4m condmask0 = Vbseff > 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, pParam->BSIM3phi / (pParam->BSIM3phi + Vbseff), condmask_true0); + Phis = vec4_blend(Phis, pParam->BSIM3phi * T0, condmask_true0); + dPhis_dVb = vec4_blend(dPhis_dVb, (-T0) * T0, condmask_true0); + sqrtPhis = vec4_blend(sqrtPhis, pParam->BSIM3phis3 / (pParam->BSIM3phi + (0.5 * Vbseff)), condmask_true0); + dsqrtPhis_dVb = vec4_blend(dsqrtPhis_dVb, (((-0.5) * sqrtPhis) * sqrtPhis) / pParam->BSIM3phis3, condmask_true0); + } + { + Phis = vec4_blend(Phis, pParam->BSIM3phi - Vbseff, condmask_false0); + dPhis_dVb = vec4_blend(dPhis_dVb, vec4_SIMDTOVECTOR(-1.0), condmask_false0); + sqrtPhis = vec4_blend(sqrtPhis, vec4_sqrt(Phis), condmask_false0); + dsqrtPhis_dVb = vec4_blend(dsqrtPhis_dVb, (-0.5) / sqrtPhis, condmask_false0); + } + } + + Xdep = (pParam->BSIM3Xdep0 * sqrtPhis) / pParam->BSIM3sqrtPhi; + dXdep_dVb = (pParam->BSIM3Xdep0 / pParam->BSIM3sqrtPhi) * dsqrtPhis_dVb; + Leff = pParam->BSIM3leff; + Vtm = model->BSIM3vtm; + T3 = vec4_sqrt(Xdep); + V0 = pParam->BSIM3vbi - pParam->BSIM3phi; + T0 = pParam->BSIM3dvt2 * Vbseff; + T2 = vec4_SIMDTOVECTOR(pParam->BSIM3dvt2); + if (1) + { + Vec4m condmask0 = T0 >= (-0.5); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, 1.0 + T0, condmask_true0); + } + { + T4 = vec4_blend(T4, 1.0 / (3.0 + (8.0 * T0)), condmask_false0); + T1 = vec4_blend(T1, (1.0 + (3.0 * T0)) * T4, condmask_false0); + T2 = vec4_blend(T2, (T2 * T4) * T4, condmask_false0); + } + } + + lt1 = (model->BSIM3factor1 * T3) * T1; + dlt1_dVb = model->BSIM3factor1 * ((((0.5 / T3) * T1) * dXdep_dVb) + (T3 * T2)); + T0 = pParam->BSIM3dvt2w * Vbseff; + if (1) + { + Vec4m condmask0 = T0 >= (-0.5); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, 1.0 + T0, condmask_true0); + T2 = vec4_blend(T2, vec4_SIMDTOVECTOR(pParam->BSIM3dvt2w), condmask_true0); + } + { + T4 = vec4_blend(T4, 1.0 / (3.0 + (8.0 * T0)), condmask_false0); + T1 = vec4_blend(T1, (1.0 + (3.0 * T0)) * T4, condmask_false0); + T2 = vec4_blend(T2, (pParam->BSIM3dvt2w * T4) * T4, condmask_false0); + } + } + + ltw = (model->BSIM3factor1 * T3) * T1; + dltw_dVb = model->BSIM3factor1 * ((((0.5 / T3) * T1) * dXdep_dVb) + (T3 * T2)); + T0 = (((-0.5) * pParam->BSIM3dvt1) * Leff) / lt1; + if (1) + { + Vec4m condmask0 = T0 > (-EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, vec4_exp(T0), condmask_true0); + Theta0 = vec4_blend(Theta0, T1 * (1.0 + (2.0 * T1)), condmask_true0); + dT1_dVb = vec4_blend(dT1_dVb, (((-T0) / lt1) * T1) * dlt1_dVb, condmask_true0); + dTheta0_dVb = vec4_blend(dTheta0_dVb, (1.0 + (4.0 * T1)) * dT1_dVb, condmask_true0); + } + { + T1 = vec4_blend(T1, vec4_SIMDTOVECTOR(MIN_EXP), condmask_false0); + Theta0 = vec4_blend(Theta0, T1 * (1.0 + (2.0 * T1)), condmask_false0); + dTheta0_dVb = vec4_blend(dTheta0_dVb, vec4_SIMDTOVECTOR(0.0), condmask_false0); + } + } + + { + Vec4d val = pParam->BSIM3dvt0 * Theta0; + heres[0]->BSIM3thetavth = val[0]; + heres[1]->BSIM3thetavth = val[1]; + heres[2]->BSIM3thetavth = val[2]; + heres[3]->BSIM3thetavth = val[3]; + } + Delt_vth = (pParam->BSIM3dvt0 * Theta0) * V0; + dDelt_vth_dVb = (pParam->BSIM3dvt0 * dTheta0_dVb) * V0; + T0 = ((((-0.5) * pParam->BSIM3dvt1w) * pParam->BSIM3weff) * Leff) / ltw; + if (1) + { + Vec4m condmask0 = T0 > (-EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, vec4_exp(T0), condmask_true0); + T2 = vec4_blend(T2, T1 * (1.0 + (2.0 * T1)), condmask_true0); + dT1_dVb = vec4_blend(dT1_dVb, (((-T0) / ltw) * T1) * dltw_dVb, condmask_true0); + dT2_dVb = vec4_blend(dT2_dVb, (1.0 + (4.0 * T1)) * dT1_dVb, condmask_true0); + } + { + T1 = vec4_blend(T1, vec4_SIMDTOVECTOR(MIN_EXP), condmask_false0); + T2 = vec4_blend(T2, T1 * (1.0 + (2.0 * T1)), condmask_false0); + dT2_dVb = vec4_blend(dT2_dVb, vec4_SIMDTOVECTOR(0.0), condmask_false0); + } + } + + T0 = pParam->BSIM3dvt0w * T2; + T2 = T0 * V0; + dT2_dVb = (pParam->BSIM3dvt0w * dT2_dVb) * V0; + TempRatio = (ckt->CKTtemp / model->BSIM3tnom) - 1.0; + T0 = vec4_SIMDTOVECTOR(sqrt(1.0 + (pParam->BSIM3nlx / Leff))); + T1 = ((pParam->BSIM3k1ox * (T0 - 1.0)) * pParam->BSIM3sqrtPhi) + (((pParam->BSIM3kt1 + (pParam->BSIM3kt1l / Leff)) + (pParam->BSIM3kt2 * Vbseff)) * TempRatio); + tmp2 = vec4_SIMDTOVECTOR((model->BSIM3tox * pParam->BSIM3phi) / (pParam->BSIM3weff + pParam->BSIM3w0)); + T3 = pParam->BSIM3eta0 + (pParam->BSIM3etab * Vbseff); + if (1) + { + Vec4m condmask0 = T3 < 1.0e-4; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T9 = vec4_blend(T9, 1.0 / (3.0 - (2.0e4 * T3)), condmask_true0); + T3 = vec4_blend(T3, (2.0e-4 - T3) * T9, condmask_true0); + T4 = vec4_blend(T4, T9 * T9, condmask_true0); + } + { + T4 = vec4_blend(T4, vec4_SIMDTOVECTOR(1.0), condmask_false0); + } + } + + dDIBL_Sft_dVd = T3 * pParam->BSIM3theta0vb0; + DIBL_Sft = dDIBL_Sft_dVd * Vds; + Vth = ((((((((model->BSIM3type * ((Vec4d ){heres[0]->BSIM3vth0, heres[1]->BSIM3vth0, heres[2]->BSIM3vth0, heres[3]->BSIM3vth0})) - (pParam->BSIM3k1 * pParam->BSIM3sqrtPhi)) + (pParam->BSIM3k1ox * sqrtPhis)) - (pParam->BSIM3k2ox * Vbseff)) - Delt_vth) - T2) + ((pParam->BSIM3k3 + (pParam->BSIM3k3b * Vbseff)) * tmp2)) + T1) - DIBL_Sft; + { + heres[0]->BSIM3von = Vth[0]; + heres[1]->BSIM3von = Vth[1]; + heres[2]->BSIM3von = Vth[2]; + heres[3]->BSIM3von = Vth[3]; + } + dVth_dVb = ((((((pParam->BSIM3k1ox * dsqrtPhis_dVb) - pParam->BSIM3k2ox) - dDelt_vth_dVb) - dT2_dVb) + (pParam->BSIM3k3b * tmp2)) - (((pParam->BSIM3etab * Vds) * pParam->BSIM3theta0vb0) * T4)) + (pParam->BSIM3kt2 * TempRatio); + dVth_dVd = -dDIBL_Sft_dVd; + tmp2 = (pParam->BSIM3nfactor * EPSSI) / Xdep; + tmp3 = (pParam->BSIM3cdsc + (pParam->BSIM3cdscb * Vbseff)) + (pParam->BSIM3cdscd * Vds); + tmp4 = ((tmp2 + (tmp3 * Theta0)) + pParam->BSIM3cit) / model->BSIM3cox; + if (1) + { + Vec4m condmask0 = tmp4 >= (-0.5); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + n = vec4_blend(n, 1.0 + tmp4, condmask_true0); + dn_dVb = vec4_blend(dn_dVb, (((((-tmp2) / Xdep) * dXdep_dVb) + (tmp3 * dTheta0_dVb)) + (pParam->BSIM3cdscb * Theta0)) / model->BSIM3cox, condmask_true0); + dn_dVd = vec4_blend(dn_dVd, (pParam->BSIM3cdscd * Theta0) / model->BSIM3cox, condmask_true0); + } + { + T0 = vec4_blend(T0, 1.0 / (3.0 + (8.0 * tmp4)), condmask_false0); + n = vec4_blend(n, (1.0 + (3.0 * tmp4)) * T0, condmask_false0); + T0 = vec4_blend(T0, T0 * T0, condmask_false0); + dn_dVb = vec4_blend(dn_dVb, ((((((-tmp2) / Xdep) * dXdep_dVb) + (tmp3 * dTheta0_dVb)) + (pParam->BSIM3cdscb * Theta0)) / model->BSIM3cox) * T0, condmask_false0); + dn_dVd = vec4_blend(dn_dVd, ((pParam->BSIM3cdscd * Theta0) / model->BSIM3cox) * T0, condmask_false0); + } + } + + T0 = ((Vec4d ){heres[0]->BSIM3vfb, heres[1]->BSIM3vfb, heres[2]->BSIM3vfb, heres[3]->BSIM3vfb}) + pParam->BSIM3phi; + Vgs_eff = Vgs; + dVgs_eff_dVg = vec4_SIMDTOVECTOR(1.0); + if ((pParam->BSIM3ngate > 1.e18) && (pParam->BSIM3ngate < 1.e25)) + if (1) + { + Vec4m condmask0 = Vgs > T0; + Vec4m condmask_true0 = condmask0; + { + T1 = vec4_blend(T1, vec4_SIMDTOVECTOR((((1.0e6 * Charge_q) * EPSSI) * pParam->BSIM3ngate) / (model->BSIM3cox * model->BSIM3cox)), condmask_true0); + T4 = vec4_blend(T4, vec4_sqrt(1.0 + ((2.0 * (Vgs - T0)) / T1)), condmask_true0); + T2 = vec4_blend(T2, T1 * (T4 - 1.0), condmask_true0); + T3 = vec4_blend(T3, ((0.5 * T2) * T2) / T1, condmask_true0); + T7 = vec4_blend(T7, (1.12 - T3) - 0.05, condmask_true0); + T6 = vec4_blend(T6, vec4_sqrt((T7 * T7) + 0.224), condmask_true0); + T5 = vec4_blend(T5, 1.12 - (0.5 * (T7 + T6)), condmask_true0); + Vgs_eff = vec4_blend(Vgs_eff, Vgs - T5, condmask_true0); + dVgs_eff_dVg = vec4_blend(dVgs_eff_dVg, 1.0 - ((0.5 - (0.5 / T4)) * (1.0 + (T7 / T6))), condmask_true0); + } + } + + + Vgst = Vgs_eff - Vth; + T10 = (2.0 * n) * Vtm; + VgstNVt = Vgst / T10; + ExpArg = ((2.0 * pParam->BSIM3voff) - Vgst) / T10; + T0 = VgstNVt; + if (1) + { + Vec4m condmask0 = ExpArg > EXP_THRESHOLD; + Vec4m condmask_true0 = condmask0; + T0 = vec4_blend(T0, (Vgst - pParam->BSIM3voff) / (n * Vtm), condmask_true0); + } + + ExpVgst = vec4_exp(T0); + if (1) + { + Vec4m condmask0 = VgstNVt > EXP_THRESHOLD; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Vgsteff = vec4_blend(Vgsteff, Vgst, condmask_true0); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, dVgs_eff_dVg, condmask_true0); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, -dVth_dVd, condmask_true0); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, -dVth_dVb, condmask_true0); + } + if (1) + { + Vec4m condmask1 = ExpArg > EXP_THRESHOLD; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + Vgsteff = vec4_blend(Vgsteff, ((Vtm * pParam->BSIM3cdep0) / model->BSIM3cox) * ExpVgst, condmask_true1); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, Vgsteff / (n * Vtm), condmask_true1); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, (-dVgsteff_dVg) * (dVth_dVd + ((T0 * Vtm) * dn_dVd)), condmask_true1); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, (-dVgsteff_dVg) * (dVth_dVb + ((T0 * Vtm) * dn_dVb)), condmask_true1); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, dVgsteff_dVg * dVgs_eff_dVg, condmask_true1); + } + { + T1 = vec4_blend(T1, T10 * vec4_log(1.0 + ExpVgst), condmask_false1); + dT1_dVg = vec4_blend(dT1_dVg, ExpVgst / (1.0 + ExpVgst), condmask_false1); + dT1_dVb = vec4_blend(dT1_dVb, ((-dT1_dVg) * (dVth_dVb + ((Vgst / n) * dn_dVb))) + ((T1 / n) * dn_dVb), condmask_false1); + dT1_dVd = vec4_blend(dT1_dVd, ((-dT1_dVg) * (dVth_dVd + ((Vgst / n) * dn_dVd))) + ((T1 / n) * dn_dVd), condmask_false1); + dT2_dVg = vec4_blend(dT2_dVg, ((-model->BSIM3cox) / (Vtm * pParam->BSIM3cdep0)) * vec4_exp(ExpArg), condmask_false1); + T2 = vec4_blend(T2, 1.0 - (T10 * dT2_dVg), condmask_false1); + dT2_dVd = vec4_blend(dT2_dVd, ((-dT2_dVg) * (dVth_dVd - (((2.0 * Vtm) * ExpArg) * dn_dVd))) + (((T2 - 1.0) / n) * dn_dVd), condmask_false1); + dT2_dVb = vec4_blend(dT2_dVb, ((-dT2_dVg) * (dVth_dVb - (((2.0 * Vtm) * ExpArg) * dn_dVb))) + (((T2 - 1.0) / n) * dn_dVb), condmask_false1); + Vgsteff = vec4_blend(Vgsteff, T1 / T2, condmask_false1); + T3 = vec4_blend(T3, T2 * T2, condmask_false1); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, (((T2 * dT1_dVg) - (T1 * dT2_dVg)) / T3) * dVgs_eff_dVg, condmask_false1); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, ((T2 * dT1_dVd) - (T1 * dT2_dVd)) / T3, condmask_false1); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, ((T2 * dT1_dVb) - (T1 * dT2_dVb)) / T3, condmask_false1); + } + } + + } + + { + heres[0]->BSIM3Vgsteff = Vgsteff[0]; + heres[1]->BSIM3Vgsteff = Vgsteff[1]; + heres[2]->BSIM3Vgsteff = Vgsteff[2]; + heres[3]->BSIM3Vgsteff = Vgsteff[3]; + } + T9 = sqrtPhis - pParam->BSIM3sqrtPhi; + Weff = pParam->BSIM3weff - (2.0 * ((pParam->BSIM3dwg * Vgsteff) + (pParam->BSIM3dwb * T9))); + dWeff_dVg = vec4_SIMDTOVECTOR((-2.0) * pParam->BSIM3dwg); + dWeff_dVb = ((-2.0) * pParam->BSIM3dwb) * dsqrtPhis_dVb; + if (1) + { + Vec4m condmask0 = Weff < 2.0e-8; + Vec4m condmask_true0 = condmask0; + { + T0 = vec4_blend(T0, 1.0 / (6.0e-8 - (2.0 * Weff)), condmask_true0); + Weff = vec4_blend(Weff, (2.0e-8 * (4.0e-8 - Weff)) * T0, condmask_true0); + T0 = vec4_blend(T0, T0 * (T0 * 4.0e-16), condmask_true0); + dWeff_dVg = vec4_blend(dWeff_dVg, dWeff_dVg * T0, condmask_true0); + dWeff_dVb = vec4_blend(dWeff_dVb, dWeff_dVb * T0, condmask_true0); + } + } + + T0 = (pParam->BSIM3prwg * Vgsteff) + (pParam->BSIM3prwb * T9); + if (1) + { + Vec4m condmask0 = T0 >= (-0.9); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Rds = vec4_blend(Rds, pParam->BSIM3rds0 * (1.0 + T0), condmask_true0); + dRds_dVg = vec4_blend(dRds_dVg, vec4_SIMDTOVECTOR(pParam->BSIM3rds0 * pParam->BSIM3prwg), condmask_true0); + dRds_dVb = vec4_blend(dRds_dVb, (pParam->BSIM3rds0 * pParam->BSIM3prwb) * dsqrtPhis_dVb, condmask_true0); + } + { + T1 = vec4_blend(T1, 1.0 / (17.0 + (20.0 * T0)), condmask_false0); + Rds = vec4_blend(Rds, (pParam->BSIM3rds0 * (0.8 + T0)) * T1, condmask_false0); + T1 = vec4_blend(T1, T1 * T1, condmask_false0); + dRds_dVg = vec4_blend(dRds_dVg, (pParam->BSIM3rds0 * pParam->BSIM3prwg) * T1, condmask_false0); + dRds_dVb = vec4_blend(dRds_dVb, ((pParam->BSIM3rds0 * pParam->BSIM3prwb) * dsqrtPhis_dVb) * T1, condmask_false0); + } + } + + { + heres[0]->BSIM3rds = Rds[0]; + heres[1]->BSIM3rds = Rds[1]; + heres[2]->BSIM3rds = Rds[2]; + heres[3]->BSIM3rds = Rds[3]; + } + T1 = (0.5 * pParam->BSIM3k1ox) / sqrtPhis; + dT1_dVb = ((-T1) / sqrtPhis) * dsqrtPhis_dVb; + T9 = vec4_sqrt(pParam->BSIM3xj * Xdep); + tmp1 = Leff + (2.0 * T9); + T5 = Leff / tmp1; + tmp2 = pParam->BSIM3a0 * T5; + tmp3 = vec4_SIMDTOVECTOR(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); + dAbulk0_dVb = ((T1 * tmp2) * dT2_dVb) + (T2 * dT1_dVb); + T8 = (pParam->BSIM3ags * pParam->BSIM3a0) * T7; + dAbulk_dVg = (-T1) * T8; + Abulk = Abulk0 + (dAbulk_dVg * Vgsteff); + dAbulk_dVb = dAbulk0_dVb - ((T8 * Vgsteff) * (dT1_dVb + ((3.0 * T1) * dT2_dVb))); + if (1) + { + Vec4m condmask0 = Abulk0 < 0.1; + Vec4m condmask_true0 = condmask0; + { + T9 = vec4_blend(T9, 1.0 / (3.0 - (20.0 * Abulk0)), condmask_true0); + Abulk0 = vec4_blend(Abulk0, (0.2 - Abulk0) * T9, condmask_true0); + dAbulk0_dVb = vec4_blend(dAbulk0_dVb, dAbulk0_dVb * (T9 * T9), condmask_true0); + } + } + + if (1) + { + Vec4m condmask0 = Abulk < 0.1; + Vec4m condmask_true0 = condmask0; + { + T9 = vec4_blend(T9, 1.0 / (3.0 - (20.0 * Abulk)), condmask_true0); + Abulk = vec4_blend(Abulk, (0.2 - Abulk) * T9, condmask_true0); + T10 = vec4_blend(T10, T9 * T9, condmask_true0); + dAbulk_dVb = vec4_blend(dAbulk_dVb, dAbulk_dVb * T10, condmask_true0); + dAbulk_dVg = vec4_blend(dAbulk_dVg, dAbulk_dVg * T10, condmask_true0); + } + } + + { + heres[0]->BSIM3Abulk = Abulk[0]; + heres[1]->BSIM3Abulk = Abulk[1]; + heres[2]->BSIM3Abulk = Abulk[2]; + heres[3]->BSIM3Abulk = Abulk[3]; + } + T2 = pParam->BSIM3keta * Vbseff; + if (1) + { + Vec4m condmask0 = T2 >= (-0.9); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, 1.0 / (1.0 + T2), condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, ((-pParam->BSIM3keta) * T0) * T0, condmask_true0); + } + { + T1 = vec4_blend(T1, 1.0 / (0.8 + T2), condmask_false0); + T0 = vec4_blend(T0, (17.0 + (20.0 * T2)) * T1, condmask_false0); + dT0_dVb = vec4_blend(dT0_dVb, ((-pParam->BSIM3keta) * T1) * T1, condmask_false0); + } + } + + dAbulk_dVg *= T0; + dAbulk_dVb = (dAbulk_dVb * T0) + (Abulk * dT0_dVb); + dAbulk0_dVb = (dAbulk0_dVb * T0) + (Abulk0 * dT0_dVb); + Abulk *= T0; + Abulk0 *= T0; + if (model->BSIM3mobMod == 1) + { + T0 = (Vgsteff + Vth) + Vth; + T2 = pParam->BSIM3ua + (pParam->BSIM3uc * Vbseff); + T3 = T0 / model->BSIM3tox; + T5 = T3 * (T2 + (pParam->BSIM3ub * T3)); + dDenomi_dVg = (T2 + ((2.0 * pParam->BSIM3ub) * T3)) / model->BSIM3tox; + 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) / model->BSIM3tox)); + dDenomi_dVg = ((pParam->BSIM3ua + (pParam->BSIM3uc * Vbseff)) + (((2.0 * pParam->BSIM3ub) * Vgsteff) / model->BSIM3tox)) / model->BSIM3tox; + dDenomi_dVd = vec4_SIMDTOVECTOR(0.0); + dDenomi_dVb = (Vgsteff * pParam->BSIM3uc) / model->BSIM3tox; + } + 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; + dDenomi_dVg = ((pParam->BSIM3ua + ((2.0 * pParam->BSIM3ub) * T3)) * T2) / model->BSIM3tox; + dDenomi_dVd = (dDenomi_dVg * 2.0) * dVth_dVd; + dDenomi_dVb = ((dDenomi_dVg * 2.0) * dVth_dVb) + (pParam->BSIM3uc * T4); + } + + + if (1) + { + Vec4m condmask0 = T5 >= (-0.8); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Denomi = vec4_blend(Denomi, 1.0 + T5, condmask_true0); + } + { + T9 = vec4_blend(T9, 1.0 / (7.0 + (10.0 * T5)), condmask_false0); + Denomi = vec4_blend(Denomi, (0.6 + T5) * T9, condmask_false0); + T9 = vec4_blend(T9, T9 * T9, condmask_false0); + dDenomi_dVg = vec4_blend(dDenomi_dVg, dDenomi_dVg * T9, condmask_false0); + dDenomi_dVd = vec4_blend(dDenomi_dVd, dDenomi_dVd * T9, condmask_false0); + dDenomi_dVb = vec4_blend(dDenomi_dVb, dDenomi_dVb * T9, condmask_false0); + } + } + + { + Vec4d val = ueff = ((Vec4d ){heres[0]->BSIM3u0temp, heres[1]->BSIM3u0temp, heres[2]->BSIM3u0temp, heres[3]->BSIM3u0temp}) / Denomi; + heres[0]->BSIM3ueff = val[0]; + heres[1]->BSIM3ueff = val[1]; + heres[2]->BSIM3ueff = val[2]; + heres[3]->BSIM3ueff = val[3]; + } + T9 = (-ueff) / Denomi; + dueff_dVg = T9 * dDenomi_dVg; + dueff_dVd = T9 * dDenomi_dVd; + dueff_dVb = T9 * dDenomi_dVb; + WVCox = (Weff * pParam->BSIM3vsattemp) * model->BSIM3cox; + WVCoxRds = WVCox * Rds; + Esat = (2.0 * pParam->BSIM3vsattemp) / ueff; + EsatL = Esat * Leff; + T0 = (-EsatL) / ueff; + dEsatL_dVg = T0 * dueff_dVg; + dEsatL_dVd = T0 * dueff_dVd; + dEsatL_dVb = T0 * dueff_dVb; + a1 = pParam->BSIM3a1; + if (a1 == 0.0) + { + Lambda = vec4_SIMDTOVECTOR(pParam->BSIM3a2); + dLambda_dVg = vec4_SIMDTOVECTOR(0.0); + } + else + if (a1 > 0.0) + { + T0 = vec4_SIMDTOVECTOR(1.0 - pParam->BSIM3a2); + T1 = (T0 - (pParam->BSIM3a1 * Vgsteff)) - 0.0001; + T2 = vec4_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 = vec4_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); + { + Vec4d val = Abulk / Vgst2Vtm; + heres[0]->BSIM3AbovVgst2Vtm = val[0]; + heres[1]->BSIM3AbovVgst2Vtm = val[1]; + heres[2]->BSIM3AbovVgst2Vtm = val[2]; + heres[3]->BSIM3AbovVgst2Vtm = val[3]; + } + if (1) + { + Vec4m condmask0 = Rds > 0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + tmp2 = vec4_blend(tmp2, (dRds_dVg / Rds) + (dWeff_dVg / Weff), condmask_true0); + tmp3 = vec4_blend(tmp3, (dRds_dVb / Rds) + (dWeff_dVb / Weff), condmask_true0); + } + { + tmp2 = vec4_blend(tmp2, dWeff_dVg / Weff, condmask_false0); + tmp3 = vec4_blend(tmp3, dWeff_dVb / Weff, condmask_false0); + } + } + + if (1) + { + Vec4m condmask0 = (Rds == 0.0) & (Lambda == 1.0); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, 1.0 / ((Abulk * EsatL) + Vgst2Vtm), condmask_true0); + tmp1 = vec4_blend(tmp1, vec4_SIMDTOVECTOR(0.0), condmask_true0); + T1 = vec4_blend(T1, T0 * T0, condmask_true0); + T2 = vec4_blend(T2, Vgst2Vtm * T0, condmask_true0); + T3 = vec4_blend(T3, EsatL * Vgst2Vtm, condmask_true0); + Vdsat = vec4_blend(Vdsat, T3 * T0, condmask_true0); + dT0_dVg = vec4_blend(dT0_dVg, (-(((Abulk * dEsatL_dVg) + (EsatL * dAbulk_dVg)) + 1.0)) * T1, condmask_true0); + dT0_dVd = vec4_blend(dT0_dVd, (-(Abulk * dEsatL_dVd)) * T1, condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, (-((Abulk * dEsatL_dVb) + (dAbulk_dVb * EsatL))) * T1, condmask_true0); + dVdsat_dVg = vec4_blend(dVdsat_dVg, ((T3 * dT0_dVg) + (T2 * dEsatL_dVg)) + (EsatL * T0), condmask_true0); + dVdsat_dVd = vec4_blend(dVdsat_dVd, (T3 * dT0_dVd) + (T2 * dEsatL_dVd), condmask_true0); + dVdsat_dVb = vec4_blend(dVdsat_dVb, (T3 * dT0_dVb) + (T2 * dEsatL_dVb), condmask_true0); + } + { + tmp1 = vec4_blend(tmp1, dLambda_dVg / (Lambda * Lambda), condmask_false0); + T9 = vec4_blend(T9, Abulk * WVCoxRds, condmask_false0); + T8 = vec4_blend(T8, Abulk * T9, condmask_false0); + T7 = vec4_blend(T7, Vgst2Vtm * T9, condmask_false0); + T6 = vec4_blend(T6, Vgst2Vtm * WVCoxRds, condmask_false0); + T0 = vec4_blend(T0, (2.0 * Abulk) * ((T9 - 1.0) + (1.0 / Lambda)), condmask_false0); + dT0_dVg = vec4_blend(dT0_dVg, 2.0 * (((T8 * tmp2) - (Abulk * tmp1)) + ((((2.0 * T9) + (1.0 / Lambda)) - 1.0) * dAbulk_dVg)), condmask_false0); + dT0_dVb = vec4_blend(dT0_dVb, 2.0 * ((T8 * (((2.0 / Abulk) * dAbulk_dVb) + tmp3)) + (((1.0 / Lambda) - 1.0) * dAbulk_dVb)), condmask_false0); + dT0_dVd = vec4_blend(dT0_dVd, vec4_SIMDTOVECTOR(0.0), condmask_false0); + T1 = vec4_blend(T1, ((Vgst2Vtm * ((2.0 / Lambda) - 1.0)) + (Abulk * EsatL)) + (3.0 * T7), condmask_false0); + dT1_dVg = vec4_blend(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))), condmask_false0); + dT1_dVb = vec4_blend(dT1_dVb, ((Abulk * dEsatL_dVb) + (EsatL * dAbulk_dVb)) + (3.0 * ((T6 * dAbulk_dVb) + (T7 * tmp3))), condmask_false0); + dT1_dVd = vec4_blend(dT1_dVd, Abulk * dEsatL_dVd, condmask_false0); + T2 = vec4_blend(T2, Vgst2Vtm * (EsatL + (2.0 * T6)), condmask_false0); + dT2_dVg = vec4_blend(dT2_dVg, (EsatL + (Vgst2Vtm * dEsatL_dVg)) + (T6 * (4.0 + ((2.0 * Vgst2Vtm) * tmp2))), condmask_false0); + dT2_dVb = vec4_blend(dT2_dVb, Vgst2Vtm * (dEsatL_dVb + ((2.0 * T6) * tmp3)), condmask_false0); + dT2_dVd = vec4_blend(dT2_dVd, Vgst2Vtm * dEsatL_dVd, condmask_false0); + T3 = vec4_blend(T3, vec4_sqrt((T1 * T1) - ((2.0 * T0) * T2)), condmask_false0); + Vdsat = vec4_blend(Vdsat, (T1 - T3) / T0, condmask_false0); + dT3_dVg = vec4_blend(dT3_dVg, ((T1 * dT1_dVg) - (2.0 * ((T0 * dT2_dVg) + (T2 * dT0_dVg)))) / T3, condmask_false0); + dT3_dVd = vec4_blend(dT3_dVd, ((T1 * dT1_dVd) - (2.0 * ((T0 * dT2_dVd) + (T2 * dT0_dVd)))) / T3, condmask_false0); + dT3_dVb = vec4_blend(dT3_dVb, ((T1 * dT1_dVb) - (2.0 * ((T0 * dT2_dVb) + (T2 * dT0_dVb)))) / T3, condmask_false0); + dVdsat_dVg = vec4_blend(dVdsat_dVg, ((dT1_dVg - ((((T1 * dT1_dVg) - (dT0_dVg * T2)) - (T0 * dT2_dVg)) / T3)) - (Vdsat * dT0_dVg)) / T0, condmask_false0); + dVdsat_dVb = vec4_blend(dVdsat_dVb, ((dT1_dVb - ((((T1 * dT1_dVb) - (dT0_dVb * T2)) - (T0 * dT2_dVb)) / T3)) - (Vdsat * dT0_dVb)) / T0, condmask_false0); + dVdsat_dVd = vec4_blend(dVdsat_dVd, (dT1_dVd - (((T1 * dT1_dVd) - (T0 * dT2_dVd)) / T3)) / T0, condmask_false0); + } + } + + { + heres[0]->BSIM3vdsat = Vdsat[0]; + heres[1]->BSIM3vdsat = Vdsat[1]; + heres[2]->BSIM3vdsat = Vdsat[2]; + heres[3]->BSIM3vdsat = Vdsat[3]; + } + T1 = (Vdsat - Vds) - pParam->BSIM3delta; + dT1_dVg = dVdsat_dVg; + dT1_dVd = dVdsat_dVd - 1.0; + dT1_dVb = dVdsat_dVb; + T2 = vec4_sqrt((T1 * T1) + ((4.0 * pParam->BSIM3delta) * Vdsat)); + 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)); + if (1) + { + Vec4m condmask0 = Vds == 0.0; + Vec4m condmask_true0 = condmask0; + { + Vdseff = vec4_blend(Vdseff, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseff_dVg = vec4_blend(dVdseff_dVg, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseff_dVb = vec4_blend(dVdseff_dVb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + } + } + + tmp4 = 1.0 - (((0.5 * Abulk) * Vdsat) / Vgst2Vtm); + T9 = WVCoxRds * Vgsteff; + 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))); + dT0_dVb = ((dEsatL_dVb + dVdsat_dVb) + ((T7 * tmp3) * Vgsteff)) - (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; + dT1_dVg = ((-2.0) * tmp1) + (WVCoxRds * ((Abulk * tmp2) + dAbulk_dVg)); + dT1_dVb = (dAbulk_dVb * WVCoxRds) + (T9 * tmp3); + Vasat = T0 / T1; + dVasat_dVg = (dT0_dVg - (Vasat * dT1_dVg)) / T1; + dVasat_dVb = (dT0_dVb - (Vasat * dT1_dVb)) / T1; + dVasat_dVd = dT0_dVd / T1; + if (1) + { + Vec4m condmask0 = Vdseff > Vds; + Vec4m condmask_true0 = condmask0; + Vdseff = vec4_blend(Vdseff, Vds, condmask_true0); + } + + diffVds = Vds - Vdseff; + { + heres[0]->BSIM3Vdseff = Vdseff[0]; + heres[1]->BSIM3Vdseff = Vdseff[1]; + heres[2]->BSIM3Vdseff = Vdseff[2]; + heres[3]->BSIM3Vdseff = Vdseff[3]; + } + VACLM = vec4_SIMDTOVECTOR(MAX_EXP); + dVACLM_dVd = (dVACLM_dVg = (dVACLM_dVb = vec4_SIMDTOVECTOR(0.0))); + if (pParam->BSIM3pclm > 0.0) + if (1) + { + Vec4m condmask0 = diffVds > 1.0e-10; + Vec4m condmask_true0 = condmask0; + { + T0 = vec4_blend(T0, 1.0 / ((pParam->BSIM3pclm * Abulk) * pParam->BSIM3litl), condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, ((-T0) / Abulk) * dAbulk_dVb, condmask_true0); + dT0_dVg = vec4_blend(dT0_dVg, ((-T0) / Abulk) * dAbulk_dVg, condmask_true0); + T2 = vec4_blend(T2, Vgsteff / EsatL, condmask_true0); + T1 = vec4_blend(T1, Leff * (Abulk + T2), condmask_true0); + dT1_dVg = vec4_blend(dT1_dVg, Leff * (((1.0 - (T2 * dEsatL_dVg)) / EsatL) + dAbulk_dVg), condmask_true0); + dT1_dVb = vec4_blend(dT1_dVb, Leff * (dAbulk_dVb - ((T2 * dEsatL_dVb) / EsatL)), condmask_true0); + dT1_dVd = vec4_blend(dT1_dVd, ((-T2) * dEsatL_dVd) / Esat, condmask_true0); + T9 = vec4_blend(T9, T0 * T1, condmask_true0); + VACLM = vec4_blend(VACLM, T9 * diffVds, condmask_true0); + dVACLM_dVg = vec4_blend(dVACLM_dVg, (((T0 * dT1_dVg) * diffVds) - (T9 * dVdseff_dVg)) + ((T1 * diffVds) * dT0_dVg), condmask_true0); + dVACLM_dVb = vec4_blend(dVACLM_dVb, (((dT0_dVb * T1) + (T0 * dT1_dVb)) * diffVds) - (T9 * dVdseff_dVb), condmask_true0); + dVACLM_dVd = vec4_blend(dVACLM_dVd, ((T0 * dT1_dVd) * diffVds) + (T9 * (1.0 - dVdseff_dVd)), condmask_true0); + } + } + + + if (pParam->BSIM3thetaRout > 0.0) + { + T8 = Abulk * Vdsat; + T0 = Vgst2Vtm * T8; + dT0_dVg = (((Vgst2Vtm * Abulk) * dVdsat_dVg) + T8) + ((Vgst2Vtm * Vdsat) * dAbulk_dVg); + dT0_dVb = Vgst2Vtm * ((dAbulk_dVb * Vdsat) + (Abulk * dVdsat_dVb)); + dT0_dVd = (Vgst2Vtm * Abulk) * dVdsat_dVd; + T1 = Vgst2Vtm + T8; + dT1_dVg = (1.0 + (Abulk * dVdsat_dVg)) + (Vdsat * dAbulk_dVg); + dT1_dVb = (Abulk * dVdsat_dVb) + (dAbulk_dVb * Vdsat); + dT1_dVd = Abulk * dVdsat_dVd; + T9 = T1 * T1; + T2 = vec4_SIMDTOVECTOR(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 (1) + { + Vec4m condmask0 = T7 >= (-0.9); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T3 = vec4_blend(T3, 1.0 / (1.0 + T7), condmask_true0); + VADIBL = vec4_blend(VADIBL, VADIBL * T3, condmask_true0); + dVADIBL_dVg = vec4_blend(dVADIBL_dVg, dVADIBL_dVg * T3, condmask_true0); + dVADIBL_dVb = vec4_blend(dVADIBL_dVb, (dVADIBL_dVb - (VADIBL * pParam->BSIM3pdiblb)) * T3, condmask_true0); + dVADIBL_dVd = vec4_blend(dVADIBL_dVd, dVADIBL_dVd * T3, condmask_true0); + } + { + T4 = vec4_blend(T4, 1.0 / (0.8 + T7), condmask_false0); + T3 = vec4_blend(T3, (17.0 + (20.0 * T7)) * T4, condmask_false0); + dVADIBL_dVg = vec4_blend(dVADIBL_dVg, dVADIBL_dVg * T3, condmask_false0); + dVADIBL_dVb = vec4_blend(dVADIBL_dVb, (dVADIBL_dVb * T3) - (((VADIBL * pParam->BSIM3pdiblb) * T4) * T4), condmask_false0); + dVADIBL_dVd = vec4_blend(dVADIBL_dVd, dVADIBL_dVd * T3, condmask_false0); + VADIBL = vec4_blend(VADIBL, VADIBL * T3, condmask_false0); + } + } + + } + else + { + VADIBL = vec4_SIMDTOVECTOR(MAX_EXP); + dVADIBL_dVd = (dVADIBL_dVg = (dVADIBL_dVb = vec4_SIMDTOVECTOR(0.0))); + } + + T8 = pParam->BSIM3pvag / EsatL; + T9 = T8 * Vgsteff; + if (1) + { + Vec4m condmask0 = T9 > (-0.9); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, 1.0 + T9, condmask_true0); + dT0_dVg = vec4_blend(dT0_dVg, T8 * (1.0 - ((Vgsteff * dEsatL_dVg) / EsatL)), condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, ((-T9) * dEsatL_dVb) / EsatL, condmask_true0); + dT0_dVd = vec4_blend(dT0_dVd, ((-T9) * dEsatL_dVd) / EsatL, condmask_true0); + } + { + T1 = vec4_blend(T1, 1.0 / (17.0 + (20.0 * T9)), condmask_false0); + T0 = vec4_blend(T0, (0.8 + T9) * T1, condmask_false0); + T1 = vec4_blend(T1, T1 * T1, condmask_false0); + dT0_dVg = vec4_blend(dT0_dVg, (T8 * (1.0 - ((Vgsteff * dEsatL_dVg) / EsatL))) * T1, condmask_false0); + T9 = vec4_blend(T9, T9 * (T1 / EsatL), condmask_false0); + dT0_dVb = vec4_blend(dT0_dVb, (-T9) * dEsatL_dVb, condmask_false0); + dT0_dVd = vec4_blend(dT0_dVd, (-T9) * dEsatL_dVd, condmask_false0); + } + } + + tmp1 = VACLM * VACLM; + tmp2 = VADIBL * VADIBL; + tmp3 = VACLM + VADIBL; + T1 = (VACLM * VADIBL) / tmp3; + tmp3 *= tmp3; + dT1_dVg = ((tmp1 * dVADIBL_dVg) + (tmp2 * dVACLM_dVg)) / tmp3; + dT1_dVd = ((tmp1 * dVADIBL_dVd) + (tmp2 * dVACLM_dVd)) / tmp3; + dT1_dVb = ((tmp1 * dVADIBL_dVb) + (tmp2 * dVACLM_dVb)) / tmp3; + Va = Vasat + (T0 * T1); + dVa_dVg = (dVasat_dVg + (T1 * dT0_dVg)) + (T0 * dT1_dVg); + dVa_dVd = (dVasat_dVd + (T1 * dT0_dVd)) + (T0 * dT1_dVd); + dVa_dVb = (dVasat_dVb + (T1 * dT0_dVb)) + (T0 * dT1_dVb); + VASCBE = vec4_SIMDTOVECTOR(MAX_EXP); + dVASCBE_dVg = (dVASCBE_dVd = (dVASCBE_dVb = vec4_SIMDTOVECTOR(0.0))); + if (pParam->BSIM3pscbe2 > 0.0) + { + if (1) + { + Vec4m condmask0 = diffVds > ((pParam->BSIM3pscbe1 * pParam->BSIM3litl) / EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, (pParam->BSIM3pscbe1 * pParam->BSIM3litl) / diffVds, condmask_true0); + VASCBE = vec4_blend(VASCBE, (Leff * vec4_exp(T0)) / pParam->BSIM3pscbe2, condmask_true0); + T1 = vec4_blend(T1, (T0 * VASCBE) / diffVds, condmask_true0); + dVASCBE_dVg = vec4_blend(dVASCBE_dVg, T1 * dVdseff_dVg, condmask_true0); + dVASCBE_dVd = vec4_blend(dVASCBE_dVd, (-T1) * (1.0 - dVdseff_dVd), condmask_true0); + dVASCBE_dVb = vec4_blend(dVASCBE_dVb, T1 * dVdseff_dVb, condmask_true0); + } + { + VASCBE = vec4_blend(VASCBE, vec4_SIMDTOVECTOR((MAX_EXP * Leff) / pParam->BSIM3pscbe2), condmask_false0); + } + } + + } + + CoxWovL = (model->BSIM3cox * Weff) / Leff; + beta = ueff * CoxWovL; + dbeta_dVg = (CoxWovL * dueff_dVg) + ((beta * dWeff_dVg) / Weff); + dbeta_dVd = CoxWovL * dueff_dVd; + 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_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; + 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; + dgche_dVd = (((beta * dfgche1_dVd) + (fgche1 * dbeta_dVd)) - (gche * dfgche2_dVd)) / fgche2; + dgche_dVb = (((beta * dfgche1_dVb) + (fgche1 * dbeta_dVb)) - (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); + 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); + dIdsa_dVb = (T0 * dIdl_dVb) - ((Idl * (dVdseff_dVb + (T9 * dVa_dVb))) / Va); + T9 = diffVds / VASCBE; + T0 = 1.0 + T9; + Ids = Idsa * T0; + Gm = (T0 * dIdsa_dVg) - ((Idsa * (dVdseff_dVg + (T9 * dVASCBE_dVg))) / VASCBE); + Gds = (T0 * dIdsa_dVd) + ((Idsa * ((1.0 - dVdseff_dVd) - (T9 * dVASCBE_dVd))) / VASCBE); + Gmb = (T0 * dIdsa_dVb) - ((Idsa * (dVdseff_dVb + (T9 * dVASCBE_dVb))) / VASCBE); + Gds += Gm * dVgsteff_dVd; + Gmb += Gm * dVgsteff_dVb; + Gm *= dVgsteff_dVg; + Gmb *= dVbseff_dVb; + tmpuni = pParam->BSIM3alpha0 + (pParam->BSIM3alpha1 * Leff); + if ((tmpuni <= 0.0) || (pParam->BSIM3beta0 <= 0.0)) + { + Isub = (Gbd = (Gbb = (Gbg = vec4_SIMDTOVECTOR(0.0)))); + } + else + { + T2 = vec4_SIMDTOVECTOR(tmpuni / Leff); + if (1) + { + Vec4m condmask0 = diffVds > (pParam->BSIM3beta0 / EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, (-pParam->BSIM3beta0) / diffVds, condmask_true0); + T1 = vec4_blend(T1, (T2 * diffVds) * vec4_exp(T0), condmask_true0); + T3 = vec4_blend(T3, (T1 / diffVds) * (T0 - 1.0), condmask_true0); + dT1_dVg = vec4_blend(dT1_dVg, T3 * dVdseff_dVg, condmask_true0); + dT1_dVd = vec4_blend(dT1_dVd, T3 * (dVdseff_dVd - 1.0), condmask_true0); + dT1_dVb = vec4_blend(dT1_dVb, T3 * dVdseff_dVb, condmask_true0); + } + { + T3 = vec4_blend(T3, T2 * MIN_EXP, condmask_false0); + T1 = vec4_blend(T1, T3 * diffVds, condmask_false0); + dT1_dVg = vec4_blend(dT1_dVg, (-T3) * dVdseff_dVg, condmask_false0); + dT1_dVd = vec4_blend(dT1_dVd, T3 * (1.0 - dVdseff_dVd), condmask_false0); + dT1_dVb = vec4_blend(dT1_dVb, (-T3) * dVdseff_dVb, condmask_false0); + } + } + + Isub = T1 * Idsa; + Gbg = (T1 * dIdsa_dVg) + (Idsa * dT1_dVg); + Gbd = (T1 * dIdsa_dVd) + (Idsa * dT1_dVd); + Gbb = (T1 * dIdsa_dVb) + (Idsa * dT1_dVb); + Gbd += Gbg * dVgsteff_dVd; + Gbb += Gbg * dVgsteff_dVb; + Gbg *= dVgsteff_dVg; + Gbb *= dVbseff_dVb; + } + + cdrain = Ids; + { + heres[0]->BSIM3gds = Gds[0]; + heres[1]->BSIM3gds = Gds[1]; + heres[2]->BSIM3gds = Gds[2]; + heres[3]->BSIM3gds = Gds[3]; + } + { + heres[0]->BSIM3gm = Gm[0]; + heres[1]->BSIM3gm = Gm[1]; + heres[2]->BSIM3gm = Gm[2]; + heres[3]->BSIM3gm = Gm[3]; + } + { + heres[0]->BSIM3gmbs = Gmb[0]; + heres[1]->BSIM3gmbs = Gmb[1]; + heres[2]->BSIM3gmbs = Gmb[2]; + heres[3]->BSIM3gmbs = Gmb[3]; + } + { + heres[0]->BSIM3gbbs = Gbb[0]; + heres[1]->BSIM3gbbs = Gbb[1]; + heres[2]->BSIM3gbbs = Gbb[2]; + heres[3]->BSIM3gbbs = Gbb[3]; + } + { + heres[0]->BSIM3gbgs = Gbg[0]; + heres[1]->BSIM3gbgs = Gbg[1]; + heres[2]->BSIM3gbgs = Gbg[2]; + heres[3]->BSIM3gbgs = Gbg[3]; + } + { + heres[0]->BSIM3gbds = Gbd[0]; + heres[1]->BSIM3gbds = Gbd[1]; + heres[2]->BSIM3gbds = Gbd[2]; + heres[3]->BSIM3gbds = Gbd[3]; + } + { + heres[0]->BSIM3csub = Isub[0]; + heres[1]->BSIM3csub = Isub[1]; + heres[2]->BSIM3csub = Isub[2]; + heres[3]->BSIM3csub = Isub[3]; + } + if ((model->BSIM3xpart < 0) || (!ChargeComputationNeeded)) + { + qgate = (qdrn = (qsrc = (qbulk = vec4_SIMDTOVECTOR(0.0)))); + { + heres[0]->BSIM3cggb = 0.0; + heres[1]->BSIM3cggb = 0.0; + heres[2]->BSIM3cggb = 0.0; + heres[3]->BSIM3cggb = 0.0; + } + { + heres[0]->BSIM3cgsb = 0.0; + heres[1]->BSIM3cgsb = 0.0; + heres[2]->BSIM3cgsb = 0.0; + heres[3]->BSIM3cgsb = 0.0; + } + { + heres[0]->BSIM3cgdb = 0.0; + heres[1]->BSIM3cgdb = 0.0; + heres[2]->BSIM3cgdb = 0.0; + heres[3]->BSIM3cgdb = 0.0; + } + { + heres[0]->BSIM3cdgb = 0.0; + heres[1]->BSIM3cdgb = 0.0; + heres[2]->BSIM3cdgb = 0.0; + heres[3]->BSIM3cdgb = 0.0; + } + { + heres[0]->BSIM3cdsb = 0.0; + heres[1]->BSIM3cdsb = 0.0; + heres[2]->BSIM3cdsb = 0.0; + heres[3]->BSIM3cdsb = 0.0; + } + { + heres[0]->BSIM3cddb = 0.0; + heres[1]->BSIM3cddb = 0.0; + heres[2]->BSIM3cddb = 0.0; + heres[3]->BSIM3cddb = 0.0; + } + { + heres[0]->BSIM3cbgb = 0.0; + heres[1]->BSIM3cbgb = 0.0; + heres[2]->BSIM3cbgb = 0.0; + heres[3]->BSIM3cbgb = 0.0; + } + { + heres[0]->BSIM3cbsb = 0.0; + heres[1]->BSIM3cbsb = 0.0; + heres[2]->BSIM3cbsb = 0.0; + heres[3]->BSIM3cbsb = 0.0; + } + { + heres[0]->BSIM3cbdb = 0.0; + heres[1]->BSIM3cbdb = 0.0; + heres[2]->BSIM3cbdb = 0.0; + heres[3]->BSIM3cbdb = 0.0; + } + { + heres[0]->BSIM3cqdb = 0.0; + heres[1]->BSIM3cqdb = 0.0; + heres[2]->BSIM3cqdb = 0.0; + heres[3]->BSIM3cqdb = 0.0; + } + { + heres[0]->BSIM3cqsb = 0.0; + heres[1]->BSIM3cqsb = 0.0; + heres[2]->BSIM3cqsb = 0.0; + heres[3]->BSIM3cqsb = 0.0; + } + { + heres[0]->BSIM3cqgb = 0.0; + heres[1]->BSIM3cqgb = 0.0; + heres[2]->BSIM3cqgb = 0.0; + heres[3]->BSIM3cqgb = 0.0; + } + { + heres[0]->BSIM3cqbb = 0.0; + heres[1]->BSIM3cqbb = 0.0; + heres[2]->BSIM3cqbb = 0.0; + heres[3]->BSIM3cqbb = 0.0; + } + { + heres[0]->BSIM3gtau = 0.0; + heres[1]->BSIM3gtau = 0.0; + heres[2]->BSIM3gtau = 0.0; + heres[3]->BSIM3gtau = 0.0; + } + goto finished; + } + else + if (model->BSIM3capMod == 0) + { + if (1) + { + Vec4m condmask0 = Vbseff < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Vbseff = vec4_blend(Vbseff, Vbs, condmask_true0); + dVbseff_dVb = vec4_blend(dVbseff_dVb, vec4_SIMDTOVECTOR(1.0), condmask_true0); + } + { + Vbseff = vec4_blend(Vbseff, pParam->BSIM3phi - Phis, condmask_false0); + dVbseff_dVb = vec4_blend(dVbseff_dVb, -dPhis_dVb, condmask_false0); + } + } + + Vfb = vec4_SIMDTOVECTOR(pParam->BSIM3vfbcv); + Vth = (Vfb + pParam->BSIM3phi) + (pParam->BSIM3k1ox * sqrtPhis); + Vgst = Vgs_eff - Vth; + dVth_dVb = pParam->BSIM3k1ox * dsqrtPhis_dVb; + dVgst_dVb = -dVth_dVb; + dVgst_dVg = dVgs_eff_dVg; + CoxWL = (model->BSIM3cox * pParam->BSIM3weffCV) * pParam->BSIM3leffCV; + Arg1 = (Vgs_eff - Vbseff) - Vfb; + T1 = vec4_SIMDTOVECTOR(0.5 * pParam->BSIM3k1ox); + T2 = vec4_sqrt((T1 * T1) + Arg1); + T0 = (CoxWL * T1) / T2; + if (1) + { + Vec4m condmask0 = Arg1 <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + qgate = vec4_blend(qgate, Arg1, condmask_true0); + T0 = vec4_blend(T0, vec4_SIMDTOVECTOR(CoxWL), condmask_true0); + { + Vec4d val = (-CoxWL) * dVgs_eff_dVg; + if (condmask_true0[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + } + { + qgate = vec4_blend(qgate, pParam->BSIM3k1ox * (T2 - T1), condmask_false0); + if (1) + { + Vec4m condmask1 = Vgst <= 0.0; + Vec4m condmask_true1 = condmask_false0 & condmask1; + { + Vec4d val = -((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}); + if (condmask_false0[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + } + + } + } + + qgate = CoxWL * qgate; + qbulk = -qgate; + qdrn = vec4_SIMDTOVECTOR(0.0); + if (1) + { + Vec4m condmask0 = (Arg1 <= 0.0) | (Vgst <= 0.0); + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + { + Vec4d val = T0 * dVgs_eff_dVg; + if (condmask_true0[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cggb = val[3]; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3cgdb = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3cgdb = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3cgdb = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3cgdb = 0.0; + + } + { + Vec4d val = T0 * (dVbseff_dVb - dVgs_eff_dVg); + if (condmask_true0[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3cdgb = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3cdgb = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3cdgb = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3cdgb = 0.0; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3cddb = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3cddb = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3cddb = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3cddb = 0.0; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3cdsb = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3cdsb = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3cdsb = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3cdsb = 0.0; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3cbdb = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3cbdb = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3cbdb = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3cbdb = 0.0; + + } + { + Vec4d val = -((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}); + if (condmask_true0[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + if (condmask_true0[0]) + heres[0]->BSIM3qinv = 0.0; + + if (condmask_true0[1]) + heres[1]->BSIM3qinv = 0.0; + + if (condmask_true0[2]) + heres[2]->BSIM3qinv = 0.0; + + if (condmask_true0[3]) + heres[3]->BSIM3qinv = 0.0; + + } + } + { + One_Third_CoxWL = vec4_blend(One_Third_CoxWL, vec4_SIMDTOVECTOR(CoxWL / 3.0), condmask_false0); + Two_Third_CoxWL = vec4_blend(Two_Third_CoxWL, 2.0 * One_Third_CoxWL, condmask_false0); + AbulkCV = vec4_blend(AbulkCV, Abulk0 * pParam->BSIM3abulkCVfactor, condmask_false0); + dAbulkCV_dVb = vec4_blend(dAbulkCV_dVb, pParam->BSIM3abulkCVfactor * dAbulk0_dVb, condmask_false0); + Vdsat = vec4_blend(Vdsat, Vgst / AbulkCV, condmask_false0); + dVdsat_dVg = vec4_blend(dVdsat_dVg, dVgs_eff_dVg / AbulkCV, condmask_false0); + dVdsat_dVb = vec4_blend(dVdsat_dVb, (-((Vdsat * dAbulkCV_dVb) + dVth_dVb)) / AbulkCV, condmask_false0); + if (model->BSIM3xpart > 0.5) + { + if (1) + { + Vec4m condmask1 = Vdsat <= Vds; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + T1 = vec4_blend(T1, Vdsat / 3.0, condmask_true1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - T1), condmask_true1); + T2 = vec4_blend(T2, (-Two_Third_CoxWL) * Vgst, condmask_true1); + qbulk = vec4_blend(qbulk, -(qgate + T2), condmask_true1); + qdrn = vec4_blend(qdrn, vec4_SIMDTOVECTOR(0.0), condmask_true1); + { + Vec4d val = (One_Third_CoxWL * (3.0 - dVdsat_dVg)) * dVgs_eff_dVg; + if (condmask_true1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + T2 = vec4_blend(T2, (-One_Third_CoxWL) * dVdsat_dVb, condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + T2); + if (condmask_true1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cgdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cgdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cgdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cgdb = 0.0; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cdgb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cdgb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cdgb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cdgb = 0.0; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cddb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cddb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cddb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cddb = 0.0; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cdsb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cdsb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cdsb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cdsb = 0.0; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) - (Two_Third_CoxWL * dVgs_eff_dVg)); + if (condmask_true1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + T3 = vec4_blend(T3, -(T2 + (Two_Third_CoxWL * dVth_dVb)), condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb}) + T3); + if (condmask_true1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cbdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cbdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cbdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cbdb = 0.0; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_true1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + { + Alphaz = vec4_blend(Alphaz, Vgst / Vdsat, condmask_false1); + T1 = vec4_blend(T1, (2.0 * Vdsat) - Vds, condmask_false1); + T2 = vec4_blend(T2, Vds / (3.0 * T1), condmask_false1); + T3 = vec4_blend(T3, T2 * Vds, condmask_false1); + T9 = vec4_blend(T9, vec4_SIMDTOVECTOR(0.25 * CoxWL), condmask_false1); + T4 = vec4_blend(T4, T9 * Alphaz, condmask_false1); + T7 = vec4_blend(T7, ((2.0 * Vds) - T1) - (3.0 * T3), condmask_false1); + T8 = vec4_blend(T8, (T3 - T1) - (2.0 * Vds), condmask_false1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - (0.5 * (Vds - T3))), condmask_false1); + T10 = vec4_blend(T10, T4 * T8, condmask_false1); + qdrn = vec4_blend(qdrn, T4 * T7, condmask_false1); + qbulk = vec4_blend(qbulk, -((qgate + qdrn) + T10), condmask_false1); + T5 = vec4_blend(T5, T3 / T1, condmask_false1); + { + Vec4d val = (CoxWL * (1.0 - (T5 * dVdsat_dVg))) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + T11 = vec4_blend(T11, ((-CoxWL) * T5) * dVdsat_dVb, condmask_false1); + { + Vec4d val = CoxWL * ((T2 - 0.5) + (0.5 * T5)); + if (condmask_false1[0]) + heres[0]->BSIM3cgdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgdb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + T11) + ((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb})); + if (condmask_false1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + T6 = vec4_blend(T6, 1.0 / Vdsat, condmask_false1); + dAlphaz_dVg = vec4_blend(dAlphaz_dVg, T6 * (1.0 - (Alphaz * dVdsat_dVg)), condmask_false1); + dAlphaz_dVb = vec4_blend(dAlphaz_dVb, (-T6) * (dVth_dVb + (Alphaz * dVdsat_dVb)), condmask_false1); + T7 = vec4_blend(T7, T9 * T7, condmask_false1); + T8 = vec4_blend(T8, T9 * T8, condmask_false1); + T9 = vec4_blend(T9, (2.0 * T4) * (1.0 - (3.0 * T5)), condmask_false1); + { + Vec4d val = ((T7 * dAlphaz_dVg) - (T9 * dVdsat_dVg)) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cdgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdgb = val[3]; + + } + T12 = vec4_blend(T12, (T7 * dAlphaz_dVb) - (T9 * dVdsat_dVb), condmask_false1); + { + Vec4d val = T4 * ((3.0 - (6.0 * T2)) - (3.0 * T5)); + if (condmask_false1[0]) + heres[0]->BSIM3cddb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cddb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cddb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cddb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}) + T12) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})); + if (condmask_false1[0]) + heres[0]->BSIM3cdsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdsb = val[3]; + + } + T9 = vec4_blend(T9, (2.0 * T4) * (1.0 + T5), condmask_false1); + T10 = vec4_blend(T10, ((T8 * dAlphaz_dVg) - (T9 * dVdsat_dVg)) * dVgs_eff_dVg, condmask_false1); + T11 = vec4_blend(T11, (T8 * dAlphaz_dVb) - (T9 * dVdsat_dVb), condmask_false1); + T12 = vec4_blend(T12, T4 * (((2.0 * T2) + T5) - 1.0), condmask_false1); + T0 = vec4_blend(T0, -((T10 + T11) + T12), condmask_false1); + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + T10); + if (condmask_false1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})) + T12); + if (condmask_false1[0]) + heres[0]->BSIM3cbdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbdb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb})) + T0); + if (condmask_false1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_false1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + } + + } + else + if (model->BSIM3xpart < 0.5) + { + if (1) + { + Vec4m condmask1 = Vds >= Vdsat; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + T1 = vec4_blend(T1, Vdsat / 3.0, condmask_true1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - T1), condmask_true1); + T2 = vec4_blend(T2, (-Two_Third_CoxWL) * Vgst, condmask_true1); + qbulk = vec4_blend(qbulk, -(qgate + T2), condmask_true1); + qdrn = vec4_blend(qdrn, 0.4 * T2, condmask_true1); + { + Vec4d val = (One_Third_CoxWL * (3.0 - dVdsat_dVg)) * dVgs_eff_dVg; + if (condmask_true1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + T2 = vec4_blend(T2, (-One_Third_CoxWL) * dVdsat_dVb, condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + T2); + if (condmask_true1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cgdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cgdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cgdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cgdb = 0.0; + + } + T3 = vec4_blend(T3, 0.4 * Two_Third_CoxWL, condmask_true1); + { + Vec4d val = (-T3) * dVgs_eff_dVg; + if (condmask_true1[0]) + heres[0]->BSIM3cdgb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cdgb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cdgb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cdgb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cddb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cddb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cddb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cddb = 0.0; + + } + T4 = vec4_blend(T4, T3 * dVth_dVb, condmask_true1); + { + Vec4d val = -(T4 + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})); + if (condmask_true1[0]) + heres[0]->BSIM3cdsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cdsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cdsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cdsb = val[3]; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) - (Two_Third_CoxWL * dVgs_eff_dVg)); + if (condmask_true1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + T3 = vec4_blend(T3, -(T2 + (Two_Third_CoxWL * dVth_dVb)), condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb}) + T3); + if (condmask_true1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cbdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cbdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cbdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cbdb = 0.0; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_true1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + { + Alphaz = vec4_blend(Alphaz, Vgst / Vdsat, condmask_false1); + T1 = vec4_blend(T1, (2.0 * Vdsat) - Vds, condmask_false1); + T2 = vec4_blend(T2, Vds / (3.0 * T1), condmask_false1); + T3 = vec4_blend(T3, T2 * Vds, condmask_false1); + T9 = vec4_blend(T9, vec4_SIMDTOVECTOR(0.25 * CoxWL), condmask_false1); + T4 = vec4_blend(T4, T9 * Alphaz, condmask_false1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - (0.5 * (Vds - T3))), condmask_false1); + T5 = vec4_blend(T5, T3 / T1, condmask_false1); + { + Vec4d val = (CoxWL * (1.0 - (T5 * dVdsat_dVg))) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + tmp = vec4_blend(tmp, ((-CoxWL) * T5) * dVdsat_dVb, condmask_false1); + { + Vec4d val = CoxWL * ((T2 - 0.5) + (0.5 * T5)); + if (condmask_false1[0]) + heres[0]->BSIM3cgdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgdb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb})) + tmp); + if (condmask_false1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + T6 = vec4_blend(T6, 1.0 / Vdsat, condmask_false1); + dAlphaz_dVg = vec4_blend(dAlphaz_dVg, T6 * (1.0 - (Alphaz * dVdsat_dVg)), condmask_false1); + dAlphaz_dVb = vec4_blend(dAlphaz_dVb, (-T6) * (dVth_dVb + (Alphaz * dVdsat_dVb)), condmask_false1); + T6 = vec4_blend(T6, (((8.0 * Vdsat) * Vdsat) - ((6.0 * Vdsat) * Vds)) + ((1.2 * Vds) * Vds), condmask_false1); + T8 = vec4_blend(T8, T2 / T1, condmask_false1); + T7 = vec4_blend(T7, (Vds - T1) - (T8 * T6), condmask_false1); + qdrn = vec4_blend(qdrn, T4 * T7, condmask_false1); + T7 = vec4_blend(T7, T7 * T9, condmask_false1); + tmp = vec4_blend(tmp, T8 / T1, condmask_false1); + tmp1 = vec4_blend(tmp1, T4 * ((2.0 - ((4.0 * tmp) * T6)) + (T8 * ((16.0 * Vdsat) - (6.0 * Vds)))), condmask_false1); + { + Vec4d val = ((T7 * dAlphaz_dVg) - (tmp1 * dVdsat_dVg)) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cdgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdgb = val[3]; + + } + T10 = vec4_blend(T10, (T7 * dAlphaz_dVb) - (tmp1 * dVdsat_dVb), condmask_false1); + { + Vec4d val = T4 * ((2.0 - (((1.0 / ((3.0 * T1) * T1)) + (2.0 * tmp)) * T6)) + (T8 * ((6.0 * Vdsat) - (2.4 * Vds)))); + if (condmask_false1[0]) + heres[0]->BSIM3cddb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cddb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cddb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cddb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}) + T10) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})); + if (condmask_false1[0]) + heres[0]->BSIM3cdsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdsb = val[3]; + + } + T7 = vec4_blend(T7, 2.0 * (T1 + T3), condmask_false1); + qbulk = vec4_blend(qbulk, -(qgate - (T4 * T7)), condmask_false1); + T7 = vec4_blend(T7, T7 * T9, condmask_false1); + T0 = vec4_blend(T0, (4.0 * T4) * (1.0 - T5), condmask_false1); + T12 = vec4_blend(T12, ((((-T7) * dAlphaz_dVg) - ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) - (T0 * dVdsat_dVg)) * dVgs_eff_dVg, condmask_false1); + T11 = vec4_blend(T11, (((-T7) * dAlphaz_dVb) - T10) - (T0 * dVdsat_dVb), condmask_false1); + T10 = vec4_blend(T10, (((-4.0) * T4) * ((T2 - 0.5) + (0.5 * T5))) - ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}), condmask_false1); + tmp = vec4_blend(tmp, -((T10 + T11) + T12), condmask_false1); + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + T12); + if (condmask_false1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})) + T10); + if (condmask_false1[0]) + heres[0]->BSIM3cbdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbdb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb})) + tmp); + if (condmask_false1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_false1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + } + + } + else + { + if (1) + { + Vec4m condmask1 = Vds >= Vdsat; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + T1 = vec4_blend(T1, Vdsat / 3.0, condmask_true1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - T1), condmask_true1); + T2 = vec4_blend(T2, (-Two_Third_CoxWL) * Vgst, condmask_true1); + qbulk = vec4_blend(qbulk, -(qgate + T2), condmask_true1); + qdrn = vec4_blend(qdrn, 0.5 * T2, condmask_true1); + { + Vec4d val = (One_Third_CoxWL * (3.0 - dVdsat_dVg)) * dVgs_eff_dVg; + if (condmask_true1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + T2 = vec4_blend(T2, (-One_Third_CoxWL) * dVdsat_dVb, condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + T2); + if (condmask_true1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cgdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cgdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cgdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cgdb = 0.0; + + } + { + Vec4d val = (-One_Third_CoxWL) * dVgs_eff_dVg; + if (condmask_true1[0]) + heres[0]->BSIM3cdgb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cdgb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cdgb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cdgb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cddb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cddb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cddb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cddb = 0.0; + + } + T4 = vec4_blend(T4, One_Third_CoxWL * dVth_dVb, condmask_true1); + { + Vec4d val = -(T4 + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})); + if (condmask_true1[0]) + heres[0]->BSIM3cdsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cdsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cdsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cdsb = val[3]; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) - (Two_Third_CoxWL * dVgs_eff_dVg)); + if (condmask_true1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + T3 = vec4_blend(T3, -(T2 + (Two_Third_CoxWL * dVth_dVb)), condmask_true1); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb}) + T3); + if (condmask_true1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + if (condmask_true1[0]) + heres[0]->BSIM3cbdb = 0.0; + + if (condmask_true1[1]) + heres[1]->BSIM3cbdb = 0.0; + + if (condmask_true1[2]) + heres[2]->BSIM3cbdb = 0.0; + + if (condmask_true1[3]) + heres[3]->BSIM3cbdb = 0.0; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_true1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_true1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_true1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_true1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + { + Alphaz = vec4_blend(Alphaz, Vgst / Vdsat, condmask_false1); + T1 = vec4_blend(T1, (2.0 * Vdsat) - Vds, condmask_false1); + T2 = vec4_blend(T2, Vds / (3.0 * T1), condmask_false1); + T3 = vec4_blend(T3, T2 * Vds, condmask_false1); + T9 = vec4_blend(T9, vec4_SIMDTOVECTOR(0.25 * CoxWL), condmask_false1); + T4 = vec4_blend(T4, T9 * Alphaz, condmask_false1); + qgate = vec4_blend(qgate, CoxWL * (((Vgs_eff - Vfb) - pParam->BSIM3phi) - (0.5 * (Vds - T3))), condmask_false1); + T5 = vec4_blend(T5, T3 / T1, condmask_false1); + { + Vec4d val = (CoxWL * (1.0 - (T5 * dVdsat_dVg))) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cggb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cggb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cggb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cggb = val[3]; + + } + tmp = vec4_blend(tmp, ((-CoxWL) * T5) * dVdsat_dVb, condmask_false1); + { + Vec4d val = CoxWL * ((T2 - 0.5) + (0.5 * T5)); + if (condmask_false1[0]) + heres[0]->BSIM3cgdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgdb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb})) + tmp); + if (condmask_false1[0]) + heres[0]->BSIM3cgsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cgsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cgsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cgsb = val[3]; + + } + T6 = vec4_blend(T6, 1.0 / Vdsat, condmask_false1); + dAlphaz_dVg = vec4_blend(dAlphaz_dVg, T6 * (1.0 - (Alphaz * dVdsat_dVg)), condmask_false1); + dAlphaz_dVb = vec4_blend(dAlphaz_dVb, (-T6) * (dVth_dVb + (Alphaz * dVdsat_dVb)), condmask_false1); + T7 = vec4_blend(T7, T1 + T3, condmask_false1); + qdrn = vec4_blend(qdrn, (-T4) * T7, condmask_false1); + qbulk = vec4_blend(qbulk, -((qgate + qdrn) + qdrn), condmask_false1); + T7 = vec4_blend(T7, T7 * T9, condmask_false1); + T0 = vec4_blend(T0, T4 * ((2.0 * T5) - 2.0), condmask_false1); + { + Vec4d val = ((T0 * dVdsat_dVg) - (T7 * dAlphaz_dVg)) * dVgs_eff_dVg; + if (condmask_false1[0]) + heres[0]->BSIM3cdgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdgb = val[3]; + + } + T12 = vec4_blend(T12, (T0 * dVdsat_dVb) - (T7 * dAlphaz_dVb), condmask_false1); + { + Vec4d val = T4 * ((1.0 - (2.0 * T2)) - T5); + if (condmask_false1[0]) + heres[0]->BSIM3cddb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cddb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cddb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cddb = val[3]; + + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}) + T12) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})); + if (condmask_false1[0]) + heres[0]->BSIM3cdsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cdsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cdsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cdsb = val[3]; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + (2.0 * ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}))); + if (condmask_false1[0]) + heres[0]->BSIM3cbgb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbgb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbgb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbgb = val[3]; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + (2.0 * ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}))); + if (condmask_false1[0]) + heres[0]->BSIM3cbdb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbdb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbdb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbdb = val[3]; + + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + (2.0 * ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}))); + if (condmask_false1[0]) + heres[0]->BSIM3cbsb = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3cbsb = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3cbsb = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3cbsb = val[3]; + + } + { + Vec4d val = -(qgate + qbulk); + if (condmask_false1[0]) + heres[0]->BSIM3qinv = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3qinv = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3qinv = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3qinv = val[3]; + + } + } + } + + } + + + } + } + + } + else + { + if (1) + { + Vec4m condmask0 = Vbseff < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + VbseffCV = vec4_blend(VbseffCV, Vbseff, condmask_true0); + dVbseffCV_dVb = vec4_blend(dVbseffCV_dVb, vec4_SIMDTOVECTOR(1.0), condmask_true0); + } + { + VbseffCV = vec4_blend(VbseffCV, pParam->BSIM3phi - Phis, condmask_false0); + dVbseffCV_dVb = vec4_blend(dVbseffCV_dVb, -dPhis_dVb, condmask_false0); + } + } + + CoxWL = (model->BSIM3cox * pParam->BSIM3weffCV) * pParam->BSIM3leffCV; + noff = n * pParam->BSIM3noff; + dnoff_dVd = pParam->BSIM3noff * dn_dVd; + dnoff_dVb = pParam->BSIM3noff * dn_dVb; + T0 = Vtm * noff; + voffcv = pParam->BSIM3voffcv; + VgstNVt = (Vgst - voffcv) / T0; + ExpVgst = vec4_exp(VgstNVt); + if (1) + { + Vec4m condmask0 = VgstNVt < (-EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + ExpVgst = vec4_blend(ExpVgst, vec4_SIMDTOVECTOR(MIN_EXP), condmask_true0); + } + + Vgsteff = T0 * vec4_log(1.0 + ExpVgst); + if (1) + { + Vec4m condmask0 = VgstNVt > EXP_THRESHOLD; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Vgsteff = vec4_blend(Vgsteff, Vgst - voffcv, condmask_true0); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, dVgs_eff_dVg, condmask_true0); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, -dVth_dVd, condmask_true0); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, -dVth_dVb, condmask_true0); + } + if (1) + { + Vec4m condmask1 = VgstNVt < (-EXP_THRESHOLD); + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, vec4_SIMDTOVECTOR(0.0), condmask_true1); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, Vgsteff / noff, condmask_true1); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, dVgsteff_dVd * dnoff_dVb, condmask_true1); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, dVgsteff_dVd * dnoff_dVd, condmask_true1); + } + { + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, ExpVgst / (1.0 + ExpVgst), condmask_false1); + dVgsteff_dVd = vec4_blend(dVgsteff_dVd, ((-dVgsteff_dVg) * (dVth_dVd + (((Vgst - voffcv) / noff) * dnoff_dVd))) + ((Vgsteff / noff) * dnoff_dVd), condmask_false1); + dVgsteff_dVb = vec4_blend(dVgsteff_dVb, ((-dVgsteff_dVg) * (dVth_dVb + (((Vgst - voffcv) / noff) * dnoff_dVb))) + ((Vgsteff / noff) * dnoff_dVb), condmask_false1); + dVgsteff_dVg = vec4_blend(dVgsteff_dVg, dVgsteff_dVg * dVgs_eff_dVg, condmask_false1); + } + } + + } + + if (model->BSIM3capMod == 1) + { + Vfb = (Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}; + Arg1 = ((Vgs_eff - VbseffCV) - Vfb) - Vgsteff; + if (1) + { + Vec4m condmask0 = Arg1 <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + qgate = vec4_blend(qgate, CoxWL * Arg1, condmask_true0); + Cgg = vec4_blend(Cgg, CoxWL * (dVgs_eff_dVg - dVgsteff_dVg), condmask_true0); + Cgd = vec4_blend(Cgd, (-CoxWL) * dVgsteff_dVd, condmask_true0); + Cgb = vec4_blend(Cgb, (-CoxWL) * (dVbseffCV_dVb + dVgsteff_dVb), condmask_true0); + } + { + T0 = vec4_blend(T0, vec4_SIMDTOVECTOR(0.5 * pParam->BSIM3k1ox), condmask_false0); + T1 = vec4_blend(T1, vec4_sqrt((T0 * T0) + Arg1), condmask_false0); + T2 = vec4_blend(T2, (CoxWL * T0) / T1, condmask_false0); + qgate = vec4_blend(qgate, (CoxWL * pParam->BSIM3k1ox) * (T1 - T0), condmask_false0); + Cgg = vec4_blend(Cgg, T2 * (dVgs_eff_dVg - dVgsteff_dVg), condmask_false0); + Cgd = vec4_blend(Cgd, (-T2) * dVgsteff_dVd, condmask_false0); + Cgb = vec4_blend(Cgb, (-T2) * (dVbseffCV_dVb + dVgsteff_dVb), condmask_false0); + } + } + + qbulk = -qgate; + Cbg = -Cgg; + Cbd = -Cgd; + Cbb = -Cgb; + One_Third_CoxWL = vec4_SIMDTOVECTOR(CoxWL / 3.0); + Two_Third_CoxWL = 2.0 * One_Third_CoxWL; + AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; + VdsatCV = Vgsteff / AbulkCV; + if (1) + { + Vec4m condmask0 = VdsatCV < Vds; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + dVdsatCV_dVg = vec4_blend(dVdsatCV_dVg, 1.0 / AbulkCV, condmask_true0); + dVdsatCV_dVb = vec4_blend(dVdsatCV_dVb, ((-VdsatCV) * dAbulkCV_dVb) / AbulkCV, condmask_true0); + T0 = vec4_blend(T0, Vgsteff - (VdsatCV / 3.0), condmask_true0); + dT0_dVg = vec4_blend(dT0_dVg, 1.0 - (dVdsatCV_dVg / 3.0), condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, (-dVdsatCV_dVb) / 3.0, condmask_true0); + qgate = vec4_blend(qgate, qgate + (CoxWL * T0), condmask_true0); + Cgg1 = vec4_blend(Cgg1, CoxWL * dT0_dVg, condmask_true0); + Cgb1 = vec4_blend(Cgb1, (CoxWL * dT0_dVb) + (Cgg1 * dVgsteff_dVb), condmask_true0); + Cgd1 = vec4_blend(Cgd1, Cgg1 * dVgsteff_dVd, condmask_true0); + Cgg1 = vec4_blend(Cgg1, Cgg1 * dVgsteff_dVg, condmask_true0); + Cgg = vec4_blend(Cgg, Cgg + Cgg1, condmask_true0); + Cgb = vec4_blend(Cgb, Cgb + Cgb1, condmask_true0); + Cgd = vec4_blend(Cgd, Cgd + Cgd1, condmask_true0); + T0 = vec4_blend(T0, VdsatCV - Vgsteff, condmask_true0); + dT0_dVg = vec4_blend(dT0_dVg, dVdsatCV_dVg - 1.0, condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, dVdsatCV_dVb, condmask_true0); + qbulk = vec4_blend(qbulk, qbulk + (One_Third_CoxWL * T0), condmask_true0); + Cbg1 = vec4_blend(Cbg1, One_Third_CoxWL * dT0_dVg, condmask_true0); + Cbb1 = vec4_blend(Cbb1, (One_Third_CoxWL * dT0_dVb) + (Cbg1 * dVgsteff_dVb), condmask_true0); + Cbd1 = vec4_blend(Cbd1, Cbg1 * dVgsteff_dVd, condmask_true0); + Cbg1 = vec4_blend(Cbg1, Cbg1 * dVgsteff_dVg, condmask_true0); + Cbg = vec4_blend(Cbg, Cbg + Cbg1, condmask_true0); + Cbb = vec4_blend(Cbb, Cbb + Cbb1, condmask_true0); + Cbd = vec4_blend(Cbd, Cbd + Cbd1, condmask_true0); + if (model->BSIM3xpart > 0.5) + T0 = vec4_blend(T0, -Two_Third_CoxWL, condmask_true0); + else + if (model->BSIM3xpart < 0.5) + T0 = vec4_blend(T0, vec4_SIMDTOVECTOR((-0.4) * CoxWL), condmask_true0); + else + T0 = vec4_blend(T0, -One_Third_CoxWL, condmask_true0); + + + qsrc = vec4_blend(qsrc, T0 * Vgsteff, condmask_true0); + Csg = vec4_blend(Csg, T0 * dVgsteff_dVg, condmask_true0); + Csb = vec4_blend(Csb, T0 * dVgsteff_dVb, condmask_true0); + Csd = vec4_blend(Csd, T0 * dVgsteff_dVd, condmask_true0); + Cgb = vec4_blend(Cgb, Cgb * dVbseff_dVb, condmask_true0); + Cbb = vec4_blend(Cbb, Cbb * dVbseff_dVb, condmask_true0); + Csb = vec4_blend(Csb, Csb * dVbseff_dVb, condmask_true0); + } + { + T0 = vec4_blend(T0, AbulkCV * Vds, condmask_false0); + T1 = vec4_blend(T1, 12.0 * ((Vgsteff - (0.5 * T0)) + 1.e-20), condmask_false0); + T2 = vec4_blend(T2, Vds / T1, condmask_false0); + T3 = vec4_blend(T3, T0 * T2, condmask_false0); + dT3_dVg = vec4_blend(dT3_dVg, (((-12.0) * T2) * T2) * AbulkCV, condmask_false0); + dT3_dVd = vec4_blend(dT3_dVd, ((((6.0 * T0) * ((4.0 * Vgsteff) - T0)) / T1) / T1) - 0.5, condmask_false0); + dT3_dVb = vec4_blend(dT3_dVb, (((12.0 * T2) * T2) * dAbulkCV_dVb) * Vgsteff, condmask_false0); + qgate = vec4_blend(qgate, qgate + (CoxWL * ((Vgsteff - (0.5 * Vds)) + T3)), condmask_false0); + Cgg1 = vec4_blend(Cgg1, CoxWL * (1.0 + dT3_dVg), condmask_false0); + Cgb1 = vec4_blend(Cgb1, (CoxWL * dT3_dVb) + (Cgg1 * dVgsteff_dVb), condmask_false0); + Cgd1 = vec4_blend(Cgd1, (CoxWL * dT3_dVd) + (Cgg1 * dVgsteff_dVd), condmask_false0); + Cgg1 = vec4_blend(Cgg1, Cgg1 * dVgsteff_dVg, condmask_false0); + Cgg = vec4_blend(Cgg, Cgg + Cgg1, condmask_false0); + Cgb = vec4_blend(Cgb, Cgb + Cgb1, condmask_false0); + Cgd = vec4_blend(Cgd, Cgd + Cgd1, condmask_false0); + qbulk = vec4_blend(qbulk, qbulk + ((CoxWL * (1.0 - AbulkCV)) * ((0.5 * Vds) - T3)), condmask_false0); + Cbg1 = vec4_blend(Cbg1, (-CoxWL) * ((1.0 - AbulkCV) * dT3_dVg), condmask_false0); + Cbb1 = vec4_blend(Cbb1, ((-CoxWL) * (((1.0 - AbulkCV) * dT3_dVb) + (((0.5 * Vds) - T3) * dAbulkCV_dVb))) + (Cbg1 * dVgsteff_dVb), condmask_false0); + Cbd1 = vec4_blend(Cbd1, (((-CoxWL) * (1.0 - AbulkCV)) * dT3_dVd) + (Cbg1 * dVgsteff_dVd), condmask_false0); + Cbg1 = vec4_blend(Cbg1, Cbg1 * dVgsteff_dVg, condmask_false0); + Cbg = vec4_blend(Cbg, Cbg + Cbg1, condmask_false0); + Cbb = vec4_blend(Cbb, Cbb + Cbb1, condmask_false0); + Cbd = vec4_blend(Cbd, Cbd + Cbd1, condmask_false0); + if (model->BSIM3xpart > 0.5) + { + T1 = vec4_blend(T1, T1 + T1, condmask_false0); + qsrc = vec4_blend(qsrc, (-CoxWL) * (((0.5 * Vgsteff) + (0.25 * T0)) - ((T0 * T0) / T1)), condmask_false0); + Csg = vec4_blend(Csg, (-CoxWL) * (0.5 + (((((24.0 * T0) * Vds) / T1) / T1) * AbulkCV)), condmask_false0); + Csb = vec4_blend(Csb, ((-CoxWL) * (((0.25 * Vds) * dAbulkCV_dVb) - ((((((12.0 * T0) * Vds) / T1) / T1) * ((4.0 * Vgsteff) - T0)) * dAbulkCV_dVb))) + (Csg * dVgsteff_dVb), condmask_false0); + Csd = vec4_blend(Csd, ((-CoxWL) * ((0.25 * AbulkCV) - (((((12.0 * AbulkCV) * T0) / T1) / T1) * ((4.0 * Vgsteff) - T0)))) + (Csg * dVgsteff_dVd), condmask_false0); + Csg = vec4_blend(Csg, Csg * dVgsteff_dVg, condmask_false0); + } + else + if (model->BSIM3xpart < 0.5) + { + T1 = vec4_blend(T1, T1 / 12.0, condmask_false0); + T2 = vec4_blend(T2, (0.5 * CoxWL) / (T1 * T1), condmask_false0); + T3 = vec4_blend(T3, (Vgsteff * ((((2.0 * T0) * T0) / 3.0) + (Vgsteff * (Vgsteff - ((4.0 * T0) / 3.0))))) - ((((2.0 * T0) * T0) * T0) / 15.0), condmask_false0); + qsrc = vec4_blend(qsrc, (-T2) * T3, condmask_false0); + T4 = vec4_blend(T4, (((4.0 / 3.0) * Vgsteff) * (Vgsteff - T0)) + ((0.4 * T0) * T0), condmask_false0); + Csg = vec4_blend(Csg, (((-2.0) * qsrc) / T1) - (T2 * ((Vgsteff * ((3.0 * Vgsteff) - ((8.0 * T0) / 3.0))) + (((2.0 * T0) * T0) / 3.0))), condmask_false0); + Csb = vec4_blend(Csb, ((((qsrc / T1) * Vds) + ((T2 * T4) * Vds)) * dAbulkCV_dVb) + (Csg * dVgsteff_dVb), condmask_false0); + Csd = vec4_blend(Csd, (((qsrc / T1) + (T2 * T4)) * AbulkCV) + (Csg * dVgsteff_dVd), condmask_false0); + Csg = vec4_blend(Csg, Csg * dVgsteff_dVg, condmask_false0); + } + else + { + qsrc = vec4_blend(qsrc, (-0.5) * (qgate + qbulk), condmask_false0); + Csg = vec4_blend(Csg, (-0.5) * (Cgg1 + Cbg1), condmask_false0); + Csb = vec4_blend(Csb, (-0.5) * (Cgb1 + Cbb1), condmask_false0); + Csd = vec4_blend(Csd, (-0.5) * (Cgd1 + Cbd1), condmask_false0); + } + + + Cgb = vec4_blend(Cgb, Cgb * dVbseff_dVb, condmask_false0); + Cbb = vec4_blend(Cbb, Cbb * dVbseff_dVb, condmask_false0); + Csb = vec4_blend(Csb, Csb * dVbseff_dVb, condmask_false0); + } + } + + qdrn = -((qgate + qbulk) + qsrc); + { + heres[0]->BSIM3cggb = Cgg[0]; + heres[1]->BSIM3cggb = Cgg[1]; + heres[2]->BSIM3cggb = Cgg[2]; + heres[3]->BSIM3cggb = Cgg[3]; + } + { + Vec4d val = -((Cgg + Cgd) + Cgb); + heres[0]->BSIM3cgsb = val[0]; + heres[1]->BSIM3cgsb = val[1]; + heres[2]->BSIM3cgsb = val[2]; + heres[3]->BSIM3cgsb = val[3]; + } + { + heres[0]->BSIM3cgdb = Cgd[0]; + heres[1]->BSIM3cgdb = Cgd[1]; + heres[2]->BSIM3cgdb = Cgd[2]; + heres[3]->BSIM3cgdb = Cgd[3]; + } + { + Vec4d val = -((Cgg + Cbg) + Csg); + heres[0]->BSIM3cdgb = val[0]; + heres[1]->BSIM3cdgb = val[1]; + heres[2]->BSIM3cdgb = val[2]; + heres[3]->BSIM3cdgb = val[3]; + } + { + Vec4d val = (((((((Cgg + Cgd) + Cgb) + Cbg) + Cbd) + Cbb) + Csg) + Csd) + Csb; + heres[0]->BSIM3cdsb = val[0]; + heres[1]->BSIM3cdsb = val[1]; + heres[2]->BSIM3cdsb = val[2]; + heres[3]->BSIM3cdsb = val[3]; + } + { + Vec4d val = -((Cgd + Cbd) + Csd); + heres[0]->BSIM3cddb = val[0]; + heres[1]->BSIM3cddb = val[1]; + heres[2]->BSIM3cddb = val[2]; + heres[3]->BSIM3cddb = val[3]; + } + { + heres[0]->BSIM3cbgb = Cbg[0]; + heres[1]->BSIM3cbgb = Cbg[1]; + heres[2]->BSIM3cbgb = Cbg[2]; + heres[3]->BSIM3cbgb = Cbg[3]; + } + { + Vec4d val = -((Cbg + Cbd) + Cbb); + heres[0]->BSIM3cbsb = val[0]; + heres[1]->BSIM3cbsb = val[1]; + heres[2]->BSIM3cbsb = val[2]; + heres[3]->BSIM3cbsb = val[3]; + } + { + heres[0]->BSIM3cbdb = Cbd[0]; + heres[1]->BSIM3cbdb = Cbd[1]; + heres[2]->BSIM3cbdb = Cbd[2]; + heres[3]->BSIM3cbdb = Cbd[3]; + } + { + Vec4d val = -(qgate + qbulk); + heres[0]->BSIM3qinv = val[0]; + heres[1]->BSIM3qinv = val[1]; + heres[2]->BSIM3qinv = val[2]; + heres[3]->BSIM3qinv = val[3]; + } + } + else + if (model->BSIM3capMod == 2) + { + Vfb = (Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}; + V3 = ((Vfb - Vgs_eff) + VbseffCV) - DELTA_3; + T0 = V3 * V3; + T2 = (4.0 * DELTA_3) * Vfb; + if (1) + { + Vec4m condmask0 = Vfb <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, T0 - T2, condmask_true0); + T2 = vec4_blend(T2, vec4_SIMDTOVECTOR(-DELTA_3), condmask_true0); + } + { + T0 = vec4_blend(T0, T0 + T2, condmask_false0); + T2 = vec4_blend(T2, vec4_SIMDTOVECTOR(DELTA_3), condmask_false0); + } + } + + T0 = vec4_sqrt(T0); + T2 = T2 / 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; + T0 = vec4_SIMDTOVECTOR(0.5 * pParam->BSIM3k1ox); + T3 = ((Vgs_eff - Vfbeff) - VbseffCV) - Vgsteff; + if (pParam->BSIM3k1ox == 0.0) + { + T1 = vec4_SIMDTOVECTOR(0.0); + T2 = vec4_SIMDTOVECTOR(0.0); + } + else + if (1) + { + Vec4m condmask0 = T3 < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, T0 + (T3 / pParam->BSIM3k1ox), condmask_true0); + T2 = vec4_blend(T2, vec4_SIMDTOVECTOR(CoxWL), condmask_true0); + } + { + T1 = vec4_blend(T1, vec4_sqrt((T0 * T0) + T3), condmask_false0); + T2 = vec4_blend(T2, (CoxWL * T0) / T1, condmask_false0); + } + } + + + 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) + dVgsteff_dVb); + AbulkCV = Abulk0 * pParam->BSIM3abulkCVfactor; + dAbulkCV_dVb = pParam->BSIM3abulkCVfactor * dAbulk0_dVb; + VdsatCV = Vgsteff / AbulkCV; + V4 = (VdsatCV - Vds) - DELTA_4; + T0 = vec4_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; + if (1) + { + Vec4m condmask0 = Vds == 0.0; + Vec4m condmask_true0 = condmask0; + { + VdseffCV = vec4_blend(VdseffCV, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseffCV_dVg = vec4_blend(dVdseffCV_dVg, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseffCV_dVb = vec4_blend(dVdseffCV_dVb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + } + } + + T0 = AbulkCV * VdseffCV; + T1 = 12.0 * ((Vgsteff - (0.5 * T0)) + 1e-20); + 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; + T6 = ((12.0 * T2) * T2) * Vgsteff; + qinoi = (-CoxWL) * ((Vgsteff - (0.5 * T0)) + (AbulkCV * T3)); + qgate = CoxWL * ((Vgsteff - (0.5 * VdseffCV)) + T3); + 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; + 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)); + 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; + if (model->BSIM3xpart > 0.5) + { + 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)); + 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; + } + else + if (model->BSIM3xpart < 0.5) + { + 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; + } + else + { + qsrc = (-0.5) * (qgate + qbulk); + Csg = (-0.5) * (Cgg1 + Cbg1); + Csb = (-0.5) * (Cgb1 + Cbb1); + Csd = (-0.5) * (Cgd1 + Cbd1); + } + + + 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; + 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; + { + heres[0]->BSIM3cggb = Cgg[0]; + heres[1]->BSIM3cggb = Cgg[1]; + heres[2]->BSIM3cggb = Cgg[2]; + heres[3]->BSIM3cggb = Cgg[3]; + } + { + Vec4d val = -((Cgg + Cgd) + Cgb); + heres[0]->BSIM3cgsb = val[0]; + heres[1]->BSIM3cgsb = val[1]; + heres[2]->BSIM3cgsb = val[2]; + heres[3]->BSIM3cgsb = val[3]; + } + { + heres[0]->BSIM3cgdb = Cgd[0]; + heres[1]->BSIM3cgdb = Cgd[1]; + heres[2]->BSIM3cgdb = Cgd[2]; + heres[3]->BSIM3cgdb = Cgd[3]; + } + { + Vec4d val = -((Cgg + Cbg) + Csg); + heres[0]->BSIM3cdgb = val[0]; + heres[1]->BSIM3cdgb = val[1]; + heres[2]->BSIM3cdgb = val[2]; + heres[3]->BSIM3cdgb = val[3]; + } + { + Vec4d val = (((((((Cgg + Cgd) + Cgb) + Cbg) + Cbd) + Cbb) + Csg) + Csd) + Csb; + heres[0]->BSIM3cdsb = val[0]; + heres[1]->BSIM3cdsb = val[1]; + heres[2]->BSIM3cdsb = val[2]; + heres[3]->BSIM3cdsb = val[3]; + } + { + Vec4d val = -((Cgd + Cbd) + Csd); + heres[0]->BSIM3cddb = val[0]; + heres[1]->BSIM3cddb = val[1]; + heres[2]->BSIM3cddb = val[2]; + heres[3]->BSIM3cddb = val[3]; + } + { + heres[0]->BSIM3cbgb = Cbg[0]; + heres[1]->BSIM3cbgb = Cbg[1]; + heres[2]->BSIM3cbgb = Cbg[2]; + heres[3]->BSIM3cbgb = Cbg[3]; + } + { + Vec4d val = -((Cbg + Cbd) + Cbb); + heres[0]->BSIM3cbsb = val[0]; + heres[1]->BSIM3cbsb = val[1]; + heres[2]->BSIM3cbsb = val[2]; + heres[3]->BSIM3cbsb = val[3]; + } + { + heres[0]->BSIM3cbdb = Cbd[0]; + heres[1]->BSIM3cbdb = Cbd[1]; + heres[2]->BSIM3cbdb = Cbd[2]; + heres[3]->BSIM3cbdb = Cbd[3]; + } + { + heres[0]->BSIM3qinv = qinoi[0]; + heres[1]->BSIM3qinv = qinoi[1]; + heres[2]->BSIM3qinv = qinoi[2]; + heres[3]->BSIM3qinv = qinoi[3]; + } + } + else + if (model->BSIM3capMod == 3) + { + V3 = ((((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}) - Vgs_eff) + VbseffCV) - DELTA_3; + if (1) + { + Vec4m condmask0 = ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}) <= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, vec4_sqrt((V3 * V3) - ((4.0 * DELTA_3) * ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}))), condmask_true0); + T2 = vec4_blend(T2, (-DELTA_3) / T0, condmask_true0); + } + { + T0 = vec4_blend(T0, vec4_sqrt((V3 * V3) + ((4.0 * DELTA_3) * ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb}))), condmask_false0); + T2 = vec4_blend(T2, DELTA_3 / T0, condmask_false0); + } + } + + T1 = 0.5 * (1.0 + (V3 / T0)); + Vfbeff = ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->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) - ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb})) / Tox; + dT0_dVg = dVgs_eff_dVg / Tox; + dT0_dVb = (-dVbseffCV_dVb) / Tox; + tmp = T0 * pParam->BSIM3acde; + dTcen_dVg = (dTcen_dVb = vec4_SIMDTOVECTOR(0.0)); + if (1) + { + Vec4m condmask0 = ((-EXP_THRESHOLD) < tmp) & (tmp < EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + { + Tcen = vec4_blend(Tcen, pParam->BSIM3ldeb * vec4_exp(tmp), condmask_true0); + dTcen_dVg = vec4_blend(dTcen_dVg, pParam->BSIM3acde * Tcen, condmask_true0); + dTcen_dVb = vec4_blend(dTcen_dVb, dTcen_dVg * dT0_dVb, condmask_true0); + dTcen_dVg = vec4_blend(dTcen_dVg, dTcen_dVg * dT0_dVg, condmask_true0); + } + } + + if (1) + { + Vec4m condmask0 = tmp <= (-EXP_THRESHOLD); + Vec4m condmask_true0 = condmask0; + { + Tcen = vec4_blend(Tcen, vec4_SIMDTOVECTOR(pParam->BSIM3ldeb * MIN_EXP), condmask_true0); + } + } + + if (1) + { + Vec4m condmask0 = tmp >= EXP_THRESHOLD; + Vec4m condmask_true0 = condmask0; + { + Tcen = vec4_blend(Tcen, vec4_SIMDTOVECTOR(pParam->BSIM3ldeb * MAX_EXP), condmask_true0); + } + } + + LINK = 1.0e-3 * model->BSIM3tox; + V3 = (pParam->BSIM3ldeb - Tcen) - LINK; + V4 = vec4_sqrt((V3 * V3) + ((4.0 * LINK) * pParam->BSIM3ldeb)); + Tcen = pParam->BSIM3ldeb - (0.5 * (V3 + V4)); + T1 = 0.5 * (1.0 + (V3 / V4)); + dTcen_dVg *= T1; + dTcen_dVb *= T1; + Ccen = EPSSI / Tcen; + T2 = Cox / (Cox + Ccen); + Coxeff = T2 * Ccen; + T3 = (-Ccen) / Tcen; + dCoxeff_dVg = (T2 * T2) * T3; + dCoxeff_dVb = dCoxeff_dVg * dTcen_dVb; + dCoxeff_dVg *= dTcen_dVg; + CoxWLcen = (CoxWL * Coxeff) / Cox; + Qac0 = CoxWLcen * (Vfbeff - ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb})); + QovCox = Qac0 / Coxeff; + dQac0_dVg = (CoxWLcen * dVfbeff_dVg) + (QovCox * dCoxeff_dVg); + dQac0_dVb = (CoxWLcen * dVfbeff_dVb) + (QovCox * dCoxeff_dVb); + T0 = vec4_SIMDTOVECTOR(0.5 * pParam->BSIM3k1ox); + T3 = ((Vgs_eff - Vfbeff) - VbseffCV) - Vgsteff; + if (pParam->BSIM3k1ox == 0.0) + { + T1 = vec4_SIMDTOVECTOR(0.0); + T2 = vec4_SIMDTOVECTOR(0.0); + } + else + if (1) + { + Vec4m condmask0 = T3 < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, T0 + (T3 / pParam->BSIM3k1ox), condmask_true0); + T2 = vec4_blend(T2, CoxWLcen, condmask_true0); + } + { + T1 = vec4_blend(T1, vec4_sqrt((T0 * T0) + T3), condmask_false0); + T2 = vec4_blend(T2, (CoxWLcen * T0) / T1, condmask_false0); + } + } + + + Qsub0 = (CoxWLcen * pParam->BSIM3k1ox) * (T1 - T0); + QovCox = Qsub0 / Coxeff; + dQsub0_dVg = (T2 * ((dVgs_eff_dVg - dVfbeff_dVg) - dVgsteff_dVg)) + (QovCox * dCoxeff_dVg); + dQsub0_dVd = (-T2) * dVgsteff_dVd; + dQsub0_dVb = ((-T2) * ((dVfbeff_dVb + dVbseffCV_dVb) + dVgsteff_dVb)) + (QovCox * dCoxeff_dVb); + if (pParam->BSIM3k1ox <= 0.0) + { + Denomi = vec4_SIMDTOVECTOR((0.25 * pParam->BSIM3moin) * Vtm); + T0 = vec4_SIMDTOVECTOR(0.5 * pParam->BSIM3sqrtPhi); + } + else + { + Denomi = vec4_SIMDTOVECTOR(((pParam->BSIM3moin * Vtm) * pParam->BSIM3k1ox) * pParam->BSIM3k1ox); + T0 = vec4_SIMDTOVECTOR(pParam->BSIM3k1ox * pParam->BSIM3sqrtPhi); + } + + T1 = (2.0 * T0) + Vgsteff; + DeltaPhi = Vtm * vec4_log(1.0 + ((T1 * Vgsteff) / Denomi)); + dDeltaPhi_dVg = ((2.0 * Vtm) * (T1 - T0)) / (Denomi + (T1 * Vgsteff)); + T0 = (Vgsteff - DeltaPhi) - 0.001; + dT0_dVg = 1.0 - dDeltaPhi_dVg; + T1 = vec4_sqrt((T0 * T0) + (Vgsteff * 0.004)); + VgDP = 0.5 * (T0 + T1); + dVgDP_dVg = 0.5 * (dT0_dVg + (((T0 * dT0_dVg) + 0.002) / T1)); + T3 = 4.0 * ((Vth - ((Vec4d ){heres[0]->BSIM3vfbzb, heres[1]->BSIM3vfbzb, heres[2]->BSIM3vfbzb, heres[3]->BSIM3vfbzb})) - pParam->BSIM3phi); + Tox += Tox; + if (1) + { + Vec4m condmask0 = T3 >= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T0 = vec4_blend(T0, (Vgsteff + T3) / Tox, condmask_true0); + dT0_dVd = vec4_blend(dT0_dVd, (dVgsteff_dVd + (4.0 * dVth_dVd)) / Tox, condmask_true0); + dT0_dVb = vec4_blend(dT0_dVb, (dVgsteff_dVb + (4.0 * dVth_dVb)) / Tox, condmask_true0); + } + { + T0 = vec4_blend(T0, (Vgsteff + 1.0e-20) / Tox, condmask_false0); + dT0_dVd = vec4_blend(dT0_dVd, dVgsteff_dVd / Tox, condmask_false0); + dT0_dVb = vec4_blend(dT0_dVb, dVgsteff_dVb / Tox, condmask_false0); + } + } + + tmp = vec4_exp(0.7 * vec4_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; + dTcen_dVd = Tox * dTcen_dVg; + dTcen_dVb = dTcen_dVd * dT0_dVb; + 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; + 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; + T1 = vec4_sqrt((T0 * T0) + ((4.0 * DELTA_4) * VdsatCV)); + dT1_dVg = ((T0 + DELTA_4) + DELTA_4) / T1; + dT1_dVd = (-T0) / T1; + dT1_dVb = dT1_dVg * dT0_dVb; + dT1_dVg *= dT0_dVg; + if (1) + { + Vec4m condmask0 = T0 >= 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + VdseffCV = vec4_blend(VdseffCV, VdsatCV - (0.5 * (T0 + T1)), condmask_true0); + dVdseffCV_dVg = vec4_blend(dVdseffCV_dVg, 0.5 * (dT0_dVg - dT1_dVg), condmask_true0); + dVdseffCV_dVd = vec4_blend(dVdseffCV_dVd, 0.5 * (1.0 - dT1_dVd), condmask_true0); + dVdseffCV_dVb = vec4_blend(dVdseffCV_dVb, 0.5 * (dT0_dVb - dT1_dVb), condmask_true0); + } + { + T3 = vec4_blend(T3, (DELTA_4 + DELTA_4) / (T1 - T0), condmask_false0); + T4 = vec4_blend(T4, 1.0 - T3, condmask_false0); + T5 = vec4_blend(T5, (VdsatCV * T3) / (T1 - T0), condmask_false0); + VdseffCV = vec4_blend(VdseffCV, VdsatCV * T4, condmask_false0); + dVdseffCV_dVg = vec4_blend(dVdseffCV_dVg, (dT0_dVg * T4) + (T5 * (dT1_dVg - dT0_dVg)), condmask_false0); + dVdseffCV_dVd = vec4_blend(dVdseffCV_dVd, T5 * (dT1_dVd + 1.0), condmask_false0); + dVdseffCV_dVb = vec4_blend(dVdseffCV_dVb, (dT0_dVb * (1.0 - T5)) + (T5 * dT1_dVb), condmask_false0); + } + } + + if (1) + { + Vec4m condmask0 = Vds == 0.0; + Vec4m condmask_true0 = condmask0; + { + VdseffCV = vec4_blend(VdseffCV, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseffCV_dVg = vec4_blend(dVdseffCV_dVg, vec4_SIMDTOVECTOR(0.0), condmask_true0); + dVdseffCV_dVb = vec4_blend(dVdseffCV_dVb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + } + } + + T0 = AbulkCV * VdseffCV; + 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; + 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); + T7 = 1.0 - AbulkCV; + T8 = T2 * T2; + T9 = (((12.0 * T7) * T0) * T0) / (T8 * AbulkCV); + T10 = T9 * dVgDP_dVg; + 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); + if (model->BSIM3xpart > 0.5) + { + 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); + } + else + if (model->BSIM3xpart < 0.5) + { + 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; + 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 + { + qsrc = (-0.5) * qgate; + Csg = (-0.5) * Cgg1; + Csd = (-0.5) * Cgd1; + Csb = (-0.5) * Cgb1; + } + + + 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; + Cgg = Cgg1 - Cbg; + Cgd = Cgd1 - Cbd; + Cgb = Cgb1 - Cbb; + Cgb *= dVbseff_dVb; + Cbb *= dVbseff_dVb; + Csb *= dVbseff_dVb; + { + heres[0]->BSIM3cggb = Cgg[0]; + heres[1]->BSIM3cggb = Cgg[1]; + heres[2]->BSIM3cggb = Cgg[2]; + heres[3]->BSIM3cggb = Cgg[3]; + } + { + Vec4d val = -((Cgg + Cgd) + Cgb); + heres[0]->BSIM3cgsb = val[0]; + heres[1]->BSIM3cgsb = val[1]; + heres[2]->BSIM3cgsb = val[2]; + heres[3]->BSIM3cgsb = val[3]; + } + { + heres[0]->BSIM3cgdb = Cgd[0]; + heres[1]->BSIM3cgdb = Cgd[1]; + heres[2]->BSIM3cgdb = Cgd[2]; + heres[3]->BSIM3cgdb = Cgd[3]; + } + { + Vec4d val = -((Cgg + Cbg) + Csg); + heres[0]->BSIM3cdgb = val[0]; + heres[1]->BSIM3cdgb = val[1]; + heres[2]->BSIM3cdgb = val[2]; + heres[3]->BSIM3cdgb = val[3]; + } + { + Vec4d val = (((((((Cgg + Cgd) + Cgb) + Cbg) + Cbd) + Cbb) + Csg) + Csd) + Csb; + heres[0]->BSIM3cdsb = val[0]; + heres[1]->BSIM3cdsb = val[1]; + heres[2]->BSIM3cdsb = val[2]; + heres[3]->BSIM3cdsb = val[3]; + } + { + Vec4d val = -((Cgd + Cbd) + Csd); + heres[0]->BSIM3cddb = val[0]; + heres[1]->BSIM3cddb = val[1]; + heres[2]->BSIM3cddb = val[2]; + heres[3]->BSIM3cddb = val[3]; + } + { + heres[0]->BSIM3cbgb = Cbg[0]; + heres[1]->BSIM3cbgb = Cbg[1]; + heres[2]->BSIM3cbgb = Cbg[2]; + heres[3]->BSIM3cbgb = Cbg[3]; + } + { + Vec4d val = -((Cbg + Cbd) + Cbb); + heres[0]->BSIM3cbsb = val[0]; + heres[1]->BSIM3cbsb = val[1]; + heres[2]->BSIM3cbsb = val[2]; + heres[3]->BSIM3cbsb = val[3]; + } + { + heres[0]->BSIM3cbdb = Cbd[0]; + heres[1]->BSIM3cbdb = Cbd[1]; + heres[2]->BSIM3cbdb = Cbd[2]; + heres[3]->BSIM3cbdb = Cbd[3]; + } + { + Vec4d val = -qinoi; + heres[0]->BSIM3qinv = val[0]; + heres[1]->BSIM3qinv = val[1]; + heres[2]->BSIM3qinv = val[2]; + heres[3]->BSIM3qinv = val[3]; + } + } + + + + } + + + finished: + { + heres[0]->BSIM3qgate = qgate[0]; + heres[1]->BSIM3qgate = qgate[1]; + heres[2]->BSIM3qgate = qgate[2]; + heres[3]->BSIM3qgate = qgate[3]; + } + + { + heres[0]->BSIM3qbulk = qbulk[0]; + heres[1]->BSIM3qbulk = qbulk[1]; + heres[2]->BSIM3qbulk = qbulk[2]; + heres[3]->BSIM3qbulk = qbulk[3]; + } + { + heres[0]->BSIM3qdrn = qdrn[0]; + heres[1]->BSIM3qdrn = qdrn[1]; + heres[2]->BSIM3qdrn = qdrn[2]; + heres[3]->BSIM3qdrn = qdrn[3]; + } + { + heres[0]->BSIM3cd = cdrain[0]; + heres[1]->BSIM3cd = cdrain[1]; + heres[2]->BSIM3cd = cdrain[2]; + heres[3]->BSIM3cd = cdrain[3]; + } + if (ChargeComputationNeeded) + { + Vec4d nstate_qbs = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbs, heres[1]->BSIM3qbs, heres[2]->BSIM3qbs, heres[3]->BSIM3qbs}); + Vec4d nstate_qbd = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbd, heres[1]->BSIM3qbd, heres[2]->BSIM3qbd, heres[3]->BSIM3qbd}); + if (model->BSIM3acmMod == 0) + { + czbd = model->BSIM3unitAreaTempJctCap * ((Vec4d ){heres[0]->BSIM3drainArea, heres[1]->BSIM3drainArea, heres[2]->BSIM3drainArea, heres[3]->BSIM3drainArea}); + czbs = model->BSIM3unitAreaTempJctCap * ((Vec4d ){heres[0]->BSIM3sourceArea, heres[1]->BSIM3sourceArea, heres[2]->BSIM3sourceArea, heres[3]->BSIM3sourceArea}); + if (1) + { + Vec4m condmask0 = ((Vec4d ){heres[0]->BSIM3drainPerimeter, heres[1]->BSIM3drainPerimeter, heres[2]->BSIM3drainPerimeter, heres[3]->BSIM3drainPerimeter}) < pParam->BSIM3weff; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + czbdswg = vec4_blend(czbdswg, model->BSIM3unitLengthGateSidewallTempJctCap * ((Vec4d ){heres[0]->BSIM3drainPerimeter, heres[1]->BSIM3drainPerimeter, heres[2]->BSIM3drainPerimeter, heres[3]->BSIM3drainPerimeter}), condmask_true0); + czbdsw = vec4_blend(czbdsw, vec4_SIMDTOVECTOR(0.0), condmask_true0); + } + { + czbdsw = vec4_blend(czbdsw, model->BSIM3unitLengthSidewallTempJctCap * (((Vec4d ){heres[0]->BSIM3drainPerimeter, heres[1]->BSIM3drainPerimeter, heres[2]->BSIM3drainPerimeter, heres[3]->BSIM3drainPerimeter}) - pParam->BSIM3weff), condmask_false0); + czbdswg = vec4_blend(czbdswg, vec4_SIMDTOVECTOR(model->BSIM3unitLengthGateSidewallTempJctCap * pParam->BSIM3weff), condmask_false0); + } + } + + if (1) + { + Vec4m condmask0 = ((Vec4d ){heres[0]->BSIM3sourcePerimeter, heres[1]->BSIM3sourcePerimeter, heres[2]->BSIM3sourcePerimeter, heres[3]->BSIM3sourcePerimeter}) < pParam->BSIM3weff; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + czbssw = vec4_blend(czbssw, vec4_SIMDTOVECTOR(0.0), condmask_true0); + czbsswg = vec4_blend(czbsswg, model->BSIM3unitLengthGateSidewallTempJctCap * ((Vec4d ){heres[0]->BSIM3sourcePerimeter, heres[1]->BSIM3sourcePerimeter, heres[2]->BSIM3sourcePerimeter, heres[3]->BSIM3sourcePerimeter}), condmask_true0); + } + { + czbssw = vec4_blend(czbssw, model->BSIM3unitLengthSidewallTempJctCap * (((Vec4d ){heres[0]->BSIM3sourcePerimeter, heres[1]->BSIM3sourcePerimeter, heres[2]->BSIM3sourcePerimeter, heres[3]->BSIM3sourcePerimeter}) - pParam->BSIM3weff), condmask_false0); + czbsswg = vec4_blend(czbsswg, vec4_SIMDTOVECTOR(model->BSIM3unitLengthGateSidewallTempJctCap * pParam->BSIM3weff), condmask_false0); + } + } + + } + else + { + error = vec4_BSIM3_ACM_junctionCapacitances(model, heres, &czbd, &czbdsw, &czbdswg, &czbs, &czbssw, &czbsswg); + if (SIMDANY(error)) + return error; + + } + + MJ = model->BSIM3bulkJctBotGradingCoeff; + MJSW = model->BSIM3bulkJctSideGradingCoeff; + MJSWG = model->BSIM3bulkJctGateSideGradingCoeff; + if (1) + { + Vec4m condmask0 = vbs == 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + nstate_qbs = vec4_blend(nstate_qbs, vec4_SIMDTOVECTOR(0.0), condmask_true0); + { + Vec4d val = (czbs + czbssw) + czbsswg; + if (condmask_true0[0]) + heres[0]->BSIM3capbs = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3capbs = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3capbs = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3capbs = val[3]; + + } + } + if (1) + { + Vec4m condmask1 = vbs < 0.0; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + if (1) + { + Vec4m condmask2 = czbs > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + Vec4m condmask_false2 = condmask_true1 & (~condmask2); + { + arg = vec4_blend(arg, 1.0 - (vbs / model->BSIM3PhiB), condmask_true2); + if (MJ == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJ) * vec4_log(arg)), condmask_true2); + + nstate_qbs = vec4_blend(nstate_qbs, ((model->BSIM3PhiB * czbs) * (1.0 - (arg * sarg))) / (1.0 - MJ), condmask_true2); + { + Vec4d val = czbs * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbs = val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbs = val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbs = val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbs = val[3]; + + } + } + { + nstate_qbs = vec4_blend(nstate_qbs, vec4_SIMDTOVECTOR(0.0), condmask_false2); + { + if (condmask_false2[0]) + heres[0]->BSIM3capbs = 0.0; + + if (condmask_false2[1]) + heres[1]->BSIM3capbs = 0.0; + + if (condmask_false2[2]) + heres[2]->BSIM3capbs = 0.0; + + if (condmask_false2[3]) + heres[3]->BSIM3capbs = 0.0; + + } + } + } + + if (1) + { + Vec4m condmask2 = czbssw > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + { + arg = vec4_blend(arg, 1.0 - (vbs / model->BSIM3PhiBSW), condmask_true2); + if (MJSW == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJSW) * vec4_log(arg)), condmask_true2); + + nstate_qbs = vec4_blend(nstate_qbs, nstate_qbs + (((model->BSIM3PhiBSW * czbssw) * (1.0 - (arg * sarg))) / (1.0 - MJSW)), condmask_true2); + { + Vec4d val = czbssw * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbs += val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbs += val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbs += val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbs += val[3]; + + } + } + } + + if (1) + { + Vec4m condmask2 = czbsswg > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + { + arg = vec4_blend(arg, 1.0 - (vbs / model->BSIM3PhiBSWG), condmask_true2); + if (MJSWG == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJSWG) * vec4_log(arg)), condmask_true2); + + nstate_qbs = vec4_blend(nstate_qbs, nstate_qbs + (((model->BSIM3PhiBSWG * czbsswg) * (1.0 - (arg * sarg))) / (1.0 - MJSWG)), condmask_true2); + { + Vec4d val = czbsswg * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbs += val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbs += val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbs += val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbs += val[3]; + + } + } + } + + } + { + T0 = vec4_blend(T0, (czbs + czbssw) + czbsswg, condmask_false1); + T1 = vec4_blend(T1, vbs * ((((czbs * MJ) / model->BSIM3PhiB) + ((czbssw * MJSW) / model->BSIM3PhiBSW)) + ((czbsswg * MJSWG) / model->BSIM3PhiBSWG)), condmask_false1); + nstate_qbs = vec4_blend(nstate_qbs, vbs * (T0 + (0.5 * T1)), condmask_false1); + { + Vec4d val = T0 + T1; + if (condmask_false1[0]) + heres[0]->BSIM3capbs = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3capbs = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3capbs = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3capbs = val[3]; + + } + } + } + + } + + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbs, heres[1]->BSIM3qbs, heres[2]->BSIM3qbs, heres[3]->BSIM3qbs}, nstate_qbs); + if (1) + { + Vec4m condmask0 = vbd == 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + nstate_qbd = vec4_blend(nstate_qbd, vec4_SIMDTOVECTOR(0.0), condmask_true0); + { + Vec4d val = (czbd + czbdsw) + czbdswg; + if (condmask_true0[0]) + heres[0]->BSIM3capbd = val[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3capbd = val[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3capbd = val[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3capbd = val[3]; + + } + } + if (1) + { + Vec4m condmask1 = vbd < 0.0; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + if (1) + { + Vec4m condmask2 = czbd > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + Vec4m condmask_false2 = condmask_true1 & (~condmask2); + { + arg = vec4_blend(arg, 1.0 - (vbd / model->BSIM3PhiB), condmask_true2); + if (MJ == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJ) * vec4_log(arg)), condmask_true2); + + nstate_qbd = vec4_blend(nstate_qbd, ((model->BSIM3PhiB * czbd) * (1.0 - (arg * sarg))) / (1.0 - MJ), condmask_true2); + { + Vec4d val = czbd * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbd = val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbd = val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbd = val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbd = val[3]; + + } + } + { + nstate_qbd = vec4_blend(nstate_qbd, vec4_SIMDTOVECTOR(0.0), condmask_false2); + { + if (condmask_false2[0]) + heres[0]->BSIM3capbd = 0.0; + + if (condmask_false2[1]) + heres[1]->BSIM3capbd = 0.0; + + if (condmask_false2[2]) + heres[2]->BSIM3capbd = 0.0; + + if (condmask_false2[3]) + heres[3]->BSIM3capbd = 0.0; + + } + } + } + + if (1) + { + Vec4m condmask2 = czbdsw > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + { + arg = vec4_blend(arg, 1.0 - (vbd / model->BSIM3PhiBSW), condmask_true2); + if (MJSW == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJSW) * vec4_log(arg)), condmask_true2); + + nstate_qbd = vec4_blend(nstate_qbd, nstate_qbd + (((model->BSIM3PhiBSW * czbdsw) * (1.0 - (arg * sarg))) / (1.0 - MJSW)), condmask_true2); + { + Vec4d val = czbdsw * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbd += val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbd += val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbd += val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbd += val[3]; + + } + } + } + + if (1) + { + Vec4m condmask2 = czbdswg > 0.0; + Vec4m condmask_true2 = condmask_true1 & condmask2; + { + arg = vec4_blend(arg, 1.0 - (vbd / model->BSIM3PhiBSWG), condmask_true2); + if (MJSWG == 0.5) + sarg = vec4_blend(sarg, 1.0 / vec4_sqrt(arg), condmask_true2); + else + sarg = vec4_blend(sarg, vec4_exp((-MJSWG) * vec4_log(arg)), condmask_true2); + + nstate_qbd = vec4_blend(nstate_qbd, nstate_qbd + (((model->BSIM3PhiBSWG * czbdswg) * (1.0 - (arg * sarg))) / (1.0 - MJSWG)), condmask_true2); + { + Vec4d val = czbdswg * sarg; + if (condmask_true2[0]) + heres[0]->BSIM3capbd += val[0]; + + if (condmask_true2[1]) + heres[1]->BSIM3capbd += val[1]; + + if (condmask_true2[2]) + heres[2]->BSIM3capbd += val[2]; + + if (condmask_true2[3]) + heres[3]->BSIM3capbd += val[3]; + + } + } + } + + } + { + T0 = vec4_blend(T0, (czbd + czbdsw) + czbdswg, condmask_false1); + T1 = vec4_blend(T1, vbd * ((((czbd * MJ) / model->BSIM3PhiB) + ((czbdsw * MJSW) / model->BSIM3PhiBSW)) + ((czbdswg * MJSWG) / model->BSIM3PhiBSWG)), condmask_false1); + nstate_qbd = vec4_blend(nstate_qbd, vbd * (T0 + (0.5 * T1)), condmask_false1); + { + Vec4d val = T0 + T1; + if (condmask_false1[0]) + heres[0]->BSIM3capbd = val[0]; + + if (condmask_false1[1]) + heres[1]->BSIM3capbd = val[1]; + + if (condmask_false1[2]) + heres[2]->BSIM3capbd = val[2]; + + if (condmask_false1[3]) + heres[3]->BSIM3capbd = val[3]; + + } + } + } + + } + + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbd, heres[1]->BSIM3qbd, heres[2]->BSIM3qbd, heres[3]->BSIM3qbd}, nstate_qbd); + } + + if ((heres[0]->BSIM3off == 0) || (!(ckt->CKTmode & MODEINITFIX))) + { + Vec4m nonconcount; + nonconcount = Check; + ckt->CKTnoncon += vec4_SIMDCOUNT(nonconcount); + } + + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3vbs, heres[1]->BSIM3vbs, heres[2]->BSIM3vbs, heres[3]->BSIM3vbs}, vbs); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3vbd, heres[1]->BSIM3vbd, heres[2]->BSIM3vbd, heres[3]->BSIM3vbd}, vbd); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3vgs, heres[1]->BSIM3vgs, heres[2]->BSIM3vgs, heres[3]->BSIM3vgs}, vgs); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3vds, heres[1]->BSIM3vds, heres[2]->BSIM3vds, heres[3]->BSIM3vds}, vds); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qdef, heres[1]->BSIM3qdef, heres[2]->BSIM3qdef, heres[3]->BSIM3qdef}, qdef); + if (!ChargeComputationNeeded) + goto line850; + + line755: + if (heres[0]->BSIM3nqsMod || heres[0]->BSIM3acnqsMod) + { + qcheq = -(qbulk + qgate); + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb})); + heres[0]->BSIM3cqgb = val[0]; + heres[1]->BSIM3cqgb = val[1]; + heres[2]->BSIM3cqgb = val[2]; + heres[3]->BSIM3cqgb = val[3]; + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb})); + heres[0]->BSIM3cqdb = val[0]; + heres[1]->BSIM3cqdb = val[1]; + heres[2]->BSIM3cqdb = val[2]; + heres[3]->BSIM3cqdb = val[3]; + } + { + Vec4d val = -(((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb})); + heres[0]->BSIM3cqsb = val[0]; + heres[1]->BSIM3cqsb = val[1]; + heres[2]->BSIM3cqsb = val[2]; + heres[3]->BSIM3cqsb = val[3]; + } + { + Vec4d val = -((((Vec4d ){heres[0]->BSIM3cqgb, heres[1]->BSIM3cqgb, heres[2]->BSIM3cqgb, heres[3]->BSIM3cqgb}) + ((Vec4d ){heres[0]->BSIM3cqdb, heres[1]->BSIM3cqdb, heres[2]->BSIM3cqdb, heres[3]->BSIM3cqdb})) + ((Vec4d ){heres[0]->BSIM3cqsb, heres[1]->BSIM3cqsb, heres[2]->BSIM3cqsb, heres[3]->BSIM3cqsb})); + heres[0]->BSIM3cqbb = val[0]; + heres[1]->BSIM3cqbb = val[1]; + heres[2]->BSIM3cqbb = val[2]; + heres[3]->BSIM3cqbb = val[3]; + } + gtau_drift = vec4_fabs(((Vec4d ){heres[0]->BSIM3tconst, heres[1]->BSIM3tconst, heres[2]->BSIM3tconst, heres[3]->BSIM3tconst}) * qcheq) * ScalingFactor; + T0 = vec4_SIMDTOVECTOR(pParam->BSIM3leffCV * pParam->BSIM3leffCV); + gtau_diff = (((16.0 * ((Vec4d ){heres[0]->BSIM3u0temp, heres[1]->BSIM3u0temp, heres[2]->BSIM3u0temp, heres[3]->BSIM3u0temp})) * model->BSIM3vtm) / T0) * ScalingFactor; + { + Vec4d val = gtau_drift + gtau_diff; + heres[0]->BSIM3gtau = val[0]; + heres[1]->BSIM3gtau = val[1]; + heres[2]->BSIM3gtau = val[2]; + heres[3]->BSIM3gtau = val[3]; + } + if (heres[0]->BSIM3acnqsMod) + { + Vec4d val = ScalingFactor / ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau}); + heres[0]->BSIM3taunet = val[0]; + heres[1]->BSIM3taunet = val[1]; + heres[2]->BSIM3taunet = val[2]; + heres[3]->BSIM3taunet = val[3]; + } + + } + + + if (model->BSIM3capMod == 0) + { + cgdo = vec4_SIMDTOVECTOR(pParam->BSIM3cgdo); + qgdo = pParam->BSIM3cgdo * vgd; + cgso = vec4_SIMDTOVECTOR(pParam->BSIM3cgso); + qgso = pParam->BSIM3cgso * vgs; + } + else + if (model->BSIM3capMod == 1) + { + if (1) + { + Vec4m condmask0 = vgd < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, vec4_sqrt(1.0 - ((4.0 * vgd) / pParam->BSIM3ckappa)), condmask_true0); + cgdo = vec4_blend(cgdo, pParam->BSIM3cgdo + ((pParam->BSIM3weffCV * pParam->BSIM3cgdl) / T1), condmask_true0); + qgdo = vec4_blend(qgdo, (pParam->BSIM3cgdo * vgd) - ((((pParam->BSIM3weffCV * 0.5) * pParam->BSIM3cgdl) * pParam->BSIM3ckappa) * (T1 - 1.0)), condmask_true0); + } + { + cgdo = vec4_blend(cgdo, vec4_SIMDTOVECTOR(pParam->BSIM3cgdo + (pParam->BSIM3weffCV * pParam->BSIM3cgdl)), condmask_false0); + qgdo = vec4_blend(qgdo, ((pParam->BSIM3weffCV * pParam->BSIM3cgdl) + pParam->BSIM3cgdo) * vgd, condmask_false0); + } + } + + if (1) + { + Vec4m condmask0 = vgs < 0.0; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + T1 = vec4_blend(T1, vec4_sqrt(1.0 - ((4.0 * vgs) / pParam->BSIM3ckappa)), condmask_true0); + cgso = vec4_blend(cgso, pParam->BSIM3cgso + ((pParam->BSIM3weffCV * pParam->BSIM3cgsl) / T1), condmask_true0); + qgso = vec4_blend(qgso, (pParam->BSIM3cgso * vgs) - ((((pParam->BSIM3weffCV * 0.5) * pParam->BSIM3cgsl) * pParam->BSIM3ckappa) * (T1 - 1.0)), condmask_true0); + } + { + cgso = vec4_blend(cgso, vec4_SIMDTOVECTOR(pParam->BSIM3cgso + (pParam->BSIM3weffCV * pParam->BSIM3cgsl)), condmask_false0); + qgso = vec4_blend(qgso, ((pParam->BSIM3weffCV * pParam->BSIM3cgsl) + pParam->BSIM3cgso) * vgs, condmask_false0); + } + } + + } + else + { + T0 = vgd + DELTA_1; + T1 = vec4_sqrt((T0 * T0) + (4.0 * DELTA_1)); + T2 = 0.5 * (T0 - T1); + T3 = vec4_SIMDTOVECTOR(pParam->BSIM3weffCV * pParam->BSIM3cgdl); + T4 = vec4_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 = vec4_sqrt((T0 * T0) + (4.0 * DELTA_1)); + T2 = 0.5 * (T0 - T1); + T3 = vec4_SIMDTOVECTOR(pParam->BSIM3weffCV * pParam->BSIM3cgsl); + T4 = vec4_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)))); + } + + + { + heres[0]->BSIM3cgdo = cgdo[0]; + heres[1]->BSIM3cgdo = cgdo[1]; + heres[2]->BSIM3cgdo = cgdo[2]; + heres[3]->BSIM3cgdo = cgdo[3]; + } + { + heres[0]->BSIM3cgso = cgso[0]; + heres[1]->BSIM3cgso = cgso[1]; + heres[2]->BSIM3cgso = cgso[2]; + heres[3]->BSIM3cgso = cgso[3]; + } + ag0 = ckt->CKTag[0]; + ddxpart_dVd = (ddxpart_dVg = (ddxpart_dVb = (ddxpart_dVs = vec4_SIMDTOVECTOR(0.0)))); + dsxpart_dVd = (dsxpart_dVg = (dsxpart_dVb = (dsxpart_dVs = vec4_SIMDTOVECTOR(0.0)))); + ggtg = (ggtd = (ggtb = (ggts = vec4_SIMDTOVECTOR(0.0)))); + CoxWL = (model->BSIM3cox * pParam->BSIM3weffCV) * pParam->BSIM3leffCV; + if (1) + { + Vec4m condmask0 = BSIM3mode; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + if (heres[0]->BSIM3nqsMod == 0) + { + gcggb = vec4_blend(gcggb, (((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + cgdo) + cgso) + pParam->BSIM3cgbo) * ag0, condmask_true0); + gcgdb = vec4_blend(gcgdb, (((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) - cgdo) * ag0, condmask_true0); + gcgsb = vec4_blend(gcgsb, (((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) - cgso) * ag0, condmask_true0); + gcdgb = vec4_blend(gcdgb, (((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}) - cgdo) * ag0, condmask_true0); + gcddb = vec4_blend(gcddb, ((((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}) + ((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd})) + cgdo) * ag0, condmask_true0); + gcdsb = vec4_blend(gcdsb, ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}) * ag0, condmask_true0); + gcsgb = vec4_blend(gcsgb, (-(((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb})) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + cgso)) * ag0, condmask_true0); + gcsdb = vec4_blend(gcsdb, (-((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb})) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}))) * ag0, condmask_true0); + gcssb = vec4_blend(gcssb, ((((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs}) + cgso) - ((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb})) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}))) * ag0, condmask_true0); + gcbgb = vec4_blend(gcbgb, (((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb}) - pParam->BSIM3cgbo) * ag0, condmask_true0); + gcbdb = vec4_blend(gcbdb, (((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb}) - ((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd})) * ag0, condmask_true0); + gcbsb = vec4_blend(gcbsb, (((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb}) - ((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs})) * ag0, condmask_true0); + qgd = vec4_blend(qgd, qgdo, condmask_true0); + qgs = vec4_blend(qgs, qgso, condmask_true0); + qgb = vec4_blend(qgb, pParam->BSIM3cgbo * vgb, condmask_true0); + qgate = vec4_blend(qgate, qgate + ((qgd + qgs) + qgb), condmask_true0); + qbulk = vec4_blend(qbulk, qbulk - qgb, condmask_true0); + qdrn = vec4_blend(qdrn, qdrn - qgd, condmask_true0); + qsrc = vec4_blend(qsrc, -((qgate + qbulk) + qdrn), condmask_true0); + sxpart = vec4_blend(sxpart, vec4_SIMDTOVECTOR(0.6), condmask_true0); + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.4), condmask_true0); + } + else + { + if (1) + { + Vec4m condmask1 = qcheq > 0.0; + Vec4m condmask_true1 = condmask_true0 & condmask1; + Vec4m condmask_false1 = condmask_true0 & (~condmask1); + T0 = vec4_blend(T0, (((Vec4d ){heres[0]->BSIM3tconst, heres[1]->BSIM3tconst, heres[2]->BSIM3tconst, heres[3]->BSIM3tconst}) * qdef) * ScalingFactor, condmask_true1); + T0 = vec4_blend(T0, ((-((Vec4d ){heres[0]->BSIM3tconst, heres[1]->BSIM3tconst, heres[2]->BSIM3tconst, heres[3]->BSIM3tconst})) * qdef) * ScalingFactor, condmask_false1); + } + + ggtg = vec4_blend(ggtg, T0 * ((Vec4d ){heres[0]->BSIM3cqgb, heres[1]->BSIM3cqgb, heres[2]->BSIM3cqgb, heres[3]->BSIM3cqgb}), condmask_true0); + { + if (condmask_true0[0]) + heres[0]->BSIM3gtg = ggtg[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3gtg = ggtg[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3gtg = ggtg[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3gtg = ggtg[3]; + + } + ggtd = vec4_blend(ggtd, T0 * ((Vec4d ){heres[0]->BSIM3cqdb, heres[1]->BSIM3cqdb, heres[2]->BSIM3cqdb, heres[3]->BSIM3cqdb}), condmask_true0); + { + if (condmask_true0[0]) + heres[0]->BSIM3gtd = ggtd[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3gtd = ggtd[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3gtd = ggtd[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3gtd = ggtd[3]; + + } + ggts = vec4_blend(ggts, T0 * ((Vec4d ){heres[0]->BSIM3cqsb, heres[1]->BSIM3cqsb, heres[2]->BSIM3cqsb, heres[3]->BSIM3cqsb}), condmask_true0); + { + if (condmask_true0[0]) + heres[0]->BSIM3gts = ggts[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3gts = ggts[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3gts = ggts[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3gts = ggts[3]; + + } + ggtb = vec4_blend(ggtb, T0 * ((Vec4d ){heres[0]->BSIM3cqbb, heres[1]->BSIM3cqbb, heres[2]->BSIM3cqbb, heres[3]->BSIM3cqbb}), condmask_true0); + { + if (condmask_true0[0]) + heres[0]->BSIM3gtb = ggtb[0]; + + if (condmask_true0[1]) + heres[1]->BSIM3gtb = ggtb[1]; + + if (condmask_true0[2]) + heres[2]->BSIM3gtb = ggtb[2]; + + if (condmask_true0[3]) + heres[3]->BSIM3gtb = ggtb[3]; + + } + gqdef = vec4_blend(gqdef, vec4_SIMDTOVECTOR(ScalingFactor * ag0), condmask_true0); + gcqgb = vec4_blend(gcqgb, ((Vec4d ){heres[0]->BSIM3cqgb, heres[1]->BSIM3cqgb, heres[2]->BSIM3cqgb, heres[3]->BSIM3cqgb}) * ag0, condmask_true0); + gcqdb = vec4_blend(gcqdb, ((Vec4d ){heres[0]->BSIM3cqdb, heres[1]->BSIM3cqdb, heres[2]->BSIM3cqdb, heres[3]->BSIM3cqdb}) * ag0, condmask_true0); + gcqsb = vec4_blend(gcqsb, ((Vec4d ){heres[0]->BSIM3cqsb, heres[1]->BSIM3cqsb, heres[2]->BSIM3cqsb, heres[3]->BSIM3cqsb}) * ag0, condmask_true0); + gcqbb = vec4_blend(gcqbb, ((Vec4d ){heres[0]->BSIM3cqbb, heres[1]->BSIM3cqbb, heres[2]->BSIM3cqbb, heres[3]->BSIM3cqbb}) * ag0, condmask_true0); + gcggb = vec4_blend(gcggb, ((cgdo + cgso) + pParam->BSIM3cgbo) * ag0, condmask_true0); + gcgdb = vec4_blend(gcgdb, (-cgdo) * ag0, condmask_true0); + gcgsb = vec4_blend(gcgsb, (-cgso) * ag0, condmask_true0); + gcdgb = vec4_blend(gcdgb, (-cgdo) * ag0, condmask_true0); + gcddb = vec4_blend(gcddb, (((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd}) + cgdo) * ag0, condmask_true0); + gcdsb = vec4_blend(gcdsb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gcsgb = vec4_blend(gcsgb, (-cgso) * ag0, condmask_true0); + gcsdb = vec4_blend(gcsdb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gcssb = vec4_blend(gcssb, (((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs}) + cgso) * ag0, condmask_true0); + gcbgb = vec4_blend(gcbgb, vec4_SIMDTOVECTOR((-pParam->BSIM3cgbo) * ag0), condmask_true0); + gcbdb = vec4_blend(gcbdb, (-((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd})) * ag0, condmask_true0); + gcbsb = vec4_blend(gcbsb, (-((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs})) * ag0, condmask_true0); + if (1) + { + Vec4m condmask1 = vec4_fabs(qcheq) <= (1.0e-5 * CoxWL); + Vec4m condmask_true1 = condmask_true0 & condmask1; + Vec4m condmask_false1 = condmask_true0 & (~condmask1); + { + if (model->BSIM3xpart < 0.5) + { + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.4), condmask_true1); + } + else + if (model->BSIM3xpart > 0.5) + { + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.0), condmask_true1); + } + else + { + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.5), condmask_true1); + } + + + } + { + dxpart = vec4_blend(dxpart, qdrn / qcheq, condmask_false1); + Cdd = vec4_blend(Cdd, (Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}, condmask_false1); + Csd = vec4_blend(Csd, -((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})) + ((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb})), condmask_false1); + ddxpart_dVd = vec4_blend(ddxpart_dVd, (Cdd - (dxpart * (Cdd + Csd))) / qcheq, condmask_false1); + Cdg = vec4_blend(Cdg, (Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}, condmask_false1); + Csg = vec4_blend(Csg, -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + ((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb})), condmask_false1); + ddxpart_dVg = vec4_blend(ddxpart_dVg, (Cdg - (dxpart * (Cdg + Csg))) / qcheq, condmask_false1); + Cds = vec4_blend(Cds, (Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}, condmask_false1); + Css = vec4_blend(Css, -((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb})) + ((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb})), condmask_false1); + ddxpart_dVs = vec4_blend(ddxpart_dVs, (Cds - (dxpart * (Cds + Css))) / qcheq, condmask_false1); + ddxpart_dVb = vec4_blend(ddxpart_dVb, -((ddxpart_dVd + ddxpart_dVg) + ddxpart_dVs), condmask_false1); + } + } + + sxpart = vec4_blend(sxpart, 1.0 - dxpart, condmask_true0); + dsxpart_dVd = vec4_blend(dsxpart_dVd, -ddxpart_dVd, condmask_true0); + dsxpart_dVg = vec4_blend(dsxpart_dVg, -ddxpart_dVg, condmask_true0); + dsxpart_dVs = vec4_blend(dsxpart_dVs, -ddxpart_dVs, condmask_true0); + dsxpart_dVb = vec4_blend(dsxpart_dVb, -((dsxpart_dVd + dsxpart_dVg) + dsxpart_dVs), condmask_true0); + qgd = vec4_blend(qgd, qgdo, condmask_true0); + qgs = vec4_blend(qgs, qgso, condmask_true0); + qgb = vec4_blend(qgb, pParam->BSIM3cgbo * vgb, condmask_true0); + qgate = vec4_blend(qgate, (qgd + qgs) + qgb, condmask_true0); + qbulk = vec4_blend(qbulk, -qgb, condmask_true0); + qdrn = vec4_blend(qdrn, -qgd, condmask_true0); + qsrc = vec4_blend(qsrc, -((qgate + qbulk) + qdrn), condmask_true0); + } + + } + { + if (heres[0]->BSIM3nqsMod == 0) + { + gcggb = vec4_blend(gcggb, (((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + cgdo) + cgso) + pParam->BSIM3cgbo) * ag0, condmask_false0); + gcgdb = vec4_blend(gcgdb, (((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) - cgdo) * ag0, condmask_false0); + gcgsb = vec4_blend(gcgsb, (((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) - cgso) * ag0, condmask_false0); + gcdgb = vec4_blend(gcdgb, (-(((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb})) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + cgdo)) * ag0, condmask_false0); + gcddb = vec4_blend(gcddb, ((((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd}) + cgdo) - ((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb})) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}))) * ag0, condmask_false0); + gcdsb = vec4_blend(gcdsb, (-((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb})) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}))) * ag0, condmask_false0); + gcsgb = vec4_blend(gcsgb, (((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}) - cgso) * ag0, condmask_false0); + gcsdb = vec4_blend(gcsdb, ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}) * ag0, condmask_false0); + gcssb = vec4_blend(gcssb, ((((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}) + ((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs})) + cgso) * ag0, condmask_false0); + gcbgb = vec4_blend(gcbgb, (((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb}) - pParam->BSIM3cgbo) * ag0, condmask_false0); + gcbdb = vec4_blend(gcbdb, (((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb}) - ((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd})) * ag0, condmask_false0); + gcbsb = vec4_blend(gcbsb, (((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb}) - ((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs})) * ag0, condmask_false0); + qgd = vec4_blend(qgd, qgdo, condmask_false0); + qgs = vec4_blend(qgs, qgso, condmask_false0); + qgb = vec4_blend(qgb, pParam->BSIM3cgbo * vgb, condmask_false0); + qgate = vec4_blend(qgate, qgate + ((qgd + qgs) + qgb), condmask_false0); + qbulk = vec4_blend(qbulk, qbulk - qgb, condmask_false0); + qsrc = vec4_blend(qsrc, qdrn - qgs, condmask_false0); + qdrn = vec4_blend(qdrn, -((qgate + qbulk) + qsrc), condmask_false0); + sxpart = vec4_blend(sxpart, vec4_SIMDTOVECTOR(0.4), condmask_false0); + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.6), condmask_false0); + } + else + { + if (1) + { + Vec4m condmask1 = qcheq > 0.0; + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + T0 = vec4_blend(T0, (((Vec4d ){heres[0]->BSIM3tconst, heres[1]->BSIM3tconst, heres[2]->BSIM3tconst, heres[3]->BSIM3tconst}) * qdef) * ScalingFactor, condmask_true1); + T0 = vec4_blend(T0, ((-((Vec4d ){heres[0]->BSIM3tconst, heres[1]->BSIM3tconst, heres[2]->BSIM3tconst, heres[3]->BSIM3tconst})) * qdef) * ScalingFactor, condmask_false1); + } + + ggtg = vec4_blend(ggtg, T0 * ((Vec4d ){heres[0]->BSIM3cqgb, heres[1]->BSIM3cqgb, heres[2]->BSIM3cqgb, heres[3]->BSIM3cqgb}), condmask_false0); + { + if (condmask_false0[0]) + heres[0]->BSIM3gtg = ggtg[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gtg = ggtg[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gtg = ggtg[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gtg = ggtg[3]; + + } + ggts = vec4_blend(ggts, T0 * ((Vec4d ){heres[0]->BSIM3cqdb, heres[1]->BSIM3cqdb, heres[2]->BSIM3cqdb, heres[3]->BSIM3cqdb}), condmask_false0); + { + if (condmask_false0[0]) + heres[0]->BSIM3gtd = ggts[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gtd = ggts[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gtd = ggts[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gtd = ggts[3]; + + } + ggtd = vec4_blend(ggtd, T0 * ((Vec4d ){heres[0]->BSIM3cqsb, heres[1]->BSIM3cqsb, heres[2]->BSIM3cqsb, heres[3]->BSIM3cqsb}), condmask_false0); + { + if (condmask_false0[0]) + heres[0]->BSIM3gts = ggtd[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gts = ggtd[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gts = ggtd[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gts = ggtd[3]; + + } + ggtb = vec4_blend(ggtb, T0 * ((Vec4d ){heres[0]->BSIM3cqbb, heres[1]->BSIM3cqbb, heres[2]->BSIM3cqbb, heres[3]->BSIM3cqbb}), condmask_false0); + { + if (condmask_false0[0]) + heres[0]->BSIM3gtb = ggtb[0]; + + if (condmask_false0[1]) + heres[1]->BSIM3gtb = ggtb[1]; + + if (condmask_false0[2]) + heres[2]->BSIM3gtb = ggtb[2]; + + if (condmask_false0[3]) + heres[3]->BSIM3gtb = ggtb[3]; + + } + gqdef = vec4_blend(gqdef, vec4_SIMDTOVECTOR(ScalingFactor * ag0), condmask_false0); + gcqgb = vec4_blend(gcqgb, ((Vec4d ){heres[0]->BSIM3cqgb, heres[1]->BSIM3cqgb, heres[2]->BSIM3cqgb, heres[3]->BSIM3cqgb}) * ag0, condmask_false0); + gcqdb = vec4_blend(gcqdb, ((Vec4d ){heres[0]->BSIM3cqsb, heres[1]->BSIM3cqsb, heres[2]->BSIM3cqsb, heres[3]->BSIM3cqsb}) * ag0, condmask_false0); + gcqsb = vec4_blend(gcqsb, ((Vec4d ){heres[0]->BSIM3cqdb, heres[1]->BSIM3cqdb, heres[2]->BSIM3cqdb, heres[3]->BSIM3cqdb}) * ag0, condmask_false0); + gcqbb = vec4_blend(gcqbb, ((Vec4d ){heres[0]->BSIM3cqbb, heres[1]->BSIM3cqbb, heres[2]->BSIM3cqbb, heres[3]->BSIM3cqbb}) * ag0, condmask_false0); + gcggb = vec4_blend(gcggb, ((cgdo + cgso) + pParam->BSIM3cgbo) * ag0, condmask_false0); + gcgdb = vec4_blend(gcgdb, (-cgdo) * ag0, condmask_false0); + gcgsb = vec4_blend(gcgsb, (-cgso) * ag0, condmask_false0); + gcdgb = vec4_blend(gcdgb, (-cgdo) * ag0, condmask_false0); + gcddb = vec4_blend(gcddb, (((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd}) + cgdo) * ag0, condmask_false0); + gcdsb = vec4_blend(gcdsb, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gcsgb = vec4_blend(gcsgb, (-cgso) * ag0, condmask_false0); + gcsdb = vec4_blend(gcsdb, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gcssb = vec4_blend(gcssb, (((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs}) + cgso) * ag0, condmask_false0); + gcbgb = vec4_blend(gcbgb, vec4_SIMDTOVECTOR((-pParam->BSIM3cgbo) * ag0), condmask_false0); + gcbdb = vec4_blend(gcbdb, (-((Vec4d ){heres[0]->BSIM3capbd, heres[1]->BSIM3capbd, heres[2]->BSIM3capbd, heres[3]->BSIM3capbd})) * ag0, condmask_false0); + gcbsb = vec4_blend(gcbsb, (-((Vec4d ){heres[0]->BSIM3capbs, heres[1]->BSIM3capbs, heres[2]->BSIM3capbs, heres[3]->BSIM3capbs})) * ag0, condmask_false0); + if (1) + { + Vec4m condmask1 = vec4_fabs(qcheq) <= (1.0e-5 * CoxWL); + Vec4m condmask_true1 = condmask_false0 & condmask1; + Vec4m condmask_false1 = condmask_false0 & (~condmask1); + { + if (model->BSIM3xpart < 0.5) + { + sxpart = vec4_blend(sxpart, vec4_SIMDTOVECTOR(0.4), condmask_true1); + } + else + if (model->BSIM3xpart > 0.5) + { + sxpart = vec4_blend(sxpart, vec4_SIMDTOVECTOR(0.0), condmask_true1); + } + else + { + sxpart = vec4_blend(sxpart, vec4_SIMDTOVECTOR(0.5), condmask_true1); + } + + + } + { + sxpart = vec4_blend(sxpart, qdrn / qcheq, condmask_false1); + Css = vec4_blend(Css, (Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb}, condmask_false1); + Cds = vec4_blend(Cds, -((((Vec4d ){heres[0]->BSIM3cgdb, heres[1]->BSIM3cgdb, heres[2]->BSIM3cgdb, heres[3]->BSIM3cgdb}) + ((Vec4d ){heres[0]->BSIM3cddb, heres[1]->BSIM3cddb, heres[2]->BSIM3cddb, heres[3]->BSIM3cddb})) + ((Vec4d ){heres[0]->BSIM3cbdb, heres[1]->BSIM3cbdb, heres[2]->BSIM3cbdb, heres[3]->BSIM3cbdb})), condmask_false1); + dsxpart_dVs = vec4_blend(dsxpart_dVs, (Css - (sxpart * (Css + Cds))) / qcheq, condmask_false1); + Csg = vec4_blend(Csg, (Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb}, condmask_false1); + Cdg = vec4_blend(Cdg, -((((Vec4d ){heres[0]->BSIM3cggb, heres[1]->BSIM3cggb, heres[2]->BSIM3cggb, heres[3]->BSIM3cggb}) + ((Vec4d ){heres[0]->BSIM3cdgb, heres[1]->BSIM3cdgb, heres[2]->BSIM3cdgb, heres[3]->BSIM3cdgb})) + ((Vec4d ){heres[0]->BSIM3cbgb, heres[1]->BSIM3cbgb, heres[2]->BSIM3cbgb, heres[3]->BSIM3cbgb})), condmask_false1); + dsxpart_dVg = vec4_blend(dsxpart_dVg, (Csg - (sxpart * (Csg + Cdg))) / qcheq, condmask_false1); + Csd = vec4_blend(Csd, (Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb}, condmask_false1); + Cdd = vec4_blend(Cdd, -((((Vec4d ){heres[0]->BSIM3cgsb, heres[1]->BSIM3cgsb, heres[2]->BSIM3cgsb, heres[3]->BSIM3cgsb}) + ((Vec4d ){heres[0]->BSIM3cdsb, heres[1]->BSIM3cdsb, heres[2]->BSIM3cdsb, heres[3]->BSIM3cdsb})) + ((Vec4d ){heres[0]->BSIM3cbsb, heres[1]->BSIM3cbsb, heres[2]->BSIM3cbsb, heres[3]->BSIM3cbsb})), condmask_false1); + dsxpart_dVd = vec4_blend(dsxpart_dVd, (Csd - (sxpart * (Csd + Cdd))) / qcheq, condmask_false1); + dsxpart_dVb = vec4_blend(dsxpart_dVb, -((dsxpart_dVd + dsxpart_dVg) + dsxpart_dVs), condmask_false1); + } + } + + dxpart = vec4_blend(dxpart, 1.0 - sxpart, condmask_false0); + ddxpart_dVd = vec4_blend(ddxpart_dVd, -dsxpart_dVd, condmask_false0); + ddxpart_dVg = vec4_blend(ddxpart_dVg, -dsxpart_dVg, condmask_false0); + ddxpart_dVs = vec4_blend(ddxpart_dVs, -dsxpart_dVs, condmask_false0); + ddxpart_dVb = vec4_blend(ddxpart_dVb, -((ddxpart_dVd + ddxpart_dVg) + ddxpart_dVs), condmask_false0); + qgd = vec4_blend(qgd, qgdo, condmask_false0); + qgs = vec4_blend(qgs, qgso, condmask_false0); + qgb = vec4_blend(qgb, pParam->BSIM3cgbo * vgb, condmask_false0); + qgate = vec4_blend(qgate, (qgd + qgs) + qgb, condmask_false0); + qbulk = vec4_blend(qbulk, -qgb, condmask_false0); + qsrc = vec4_blend(qsrc, -qgs, condmask_false0); + qdrn = vec4_blend(qdrn, -((qgate + qbulk) + qsrc), condmask_false0); + } + + } + } + + cqdef = (cqcheq = vec4_SIMDTOVECTOR(0.0)); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qg, heres[1]->BSIM3qg, heres[2]->BSIM3qg, heres[3]->BSIM3qg}, qgate); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qd, heres[1]->BSIM3qd, heres[2]->BSIM3qd, heres[3]->BSIM3qd}, qdrn - vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbd, heres[1]->BSIM3qbd, heres[2]->BSIM3qbd, heres[3]->BSIM3qbd})); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qb, heres[1]->BSIM3qb, heres[2]->BSIM3qb, heres[3]->BSIM3qb}, (qbulk + vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbd, heres[1]->BSIM3qbd, heres[2]->BSIM3qbd, heres[3]->BSIM3qbd})) + vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qbs, heres[1]->BSIM3qbs, heres[2]->BSIM3qbs, heres[3]->BSIM3qbs})); + if (heres[0]->BSIM3nqsMod) + { + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qcdump, heres[1]->BSIM3qcdump, heres[2]->BSIM3qcdump, heres[3]->BSIM3qcdump}, qdef * ScalingFactor); + vec4_StateStore(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qcheq, heres[1]->BSIM3qcheq, heres[2]->BSIM3qcheq, heres[3]->BSIM3qcheq}, qcheq); + } + + if (ckt->CKTmode & MODEINITSMSIG) + { + goto line1000; + } + + if (!ChargeComputationNeeded) + goto line850; + + if (ckt->CKTmode & MODEINITTRAN) + { + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3qb, heres[1]->BSIM3qb, heres[2]->BSIM3qb, heres[3]->BSIM3qb}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qb, heres[1]->BSIM3qb, heres[2]->BSIM3qb, heres[3]->BSIM3qb})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3qg, heres[1]->BSIM3qg, heres[2]->BSIM3qg, heres[3]->BSIM3qg}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qg, heres[1]->BSIM3qg, heres[2]->BSIM3qg, heres[3]->BSIM3qg})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3qd, heres[1]->BSIM3qd, heres[2]->BSIM3qd, heres[3]->BSIM3qd}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qd, heres[1]->BSIM3qd, heres[2]->BSIM3qd, heres[3]->BSIM3qd})); + if (heres[0]->BSIM3nqsMod) + { + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3qcheq, heres[1]->BSIM3qcheq, heres[2]->BSIM3qcheq, heres[3]->BSIM3qcheq}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qcheq, heres[1]->BSIM3qcheq, heres[2]->BSIM3qcheq, heres[3]->BSIM3qcheq})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3qcdump, heres[1]->BSIM3qcdump, heres[2]->BSIM3qcdump, heres[3]->BSIM3qcdump}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3qcdump, heres[1]->BSIM3qcdump, heres[2]->BSIM3qcdump, heres[3]->BSIM3qcdump})); + } + + } + + error = vec4_NIintegrate(ckt, &geq, &ceq, 0.0, (Vec4m ){heres[0]->BSIM3qb, heres[1]->BSIM3qb, heres[2]->BSIM3qb, heres[3]->BSIM3qb}); + if (SIMDANY(error)) + return error; + + error = vec4_NIintegrate(ckt, &geq, &ceq, 0.0, (Vec4m ){heres[0]->BSIM3qg, heres[1]->BSIM3qg, heres[2]->BSIM3qg, heres[3]->BSIM3qg}); + if (SIMDANY(error)) + return error; + + error = vec4_NIintegrate(ckt, &geq, &ceq, 0.0, (Vec4m ){heres[0]->BSIM3qd, heres[1]->BSIM3qd, heres[2]->BSIM3qd, heres[3]->BSIM3qd}); + if (SIMDANY(error)) + return error; + + if (heres[0]->BSIM3nqsMod) + { + error = vec4_NIintegrate(ckt, &geq, &ceq, 0.0, (Vec4m ){heres[0]->BSIM3qcdump, heres[1]->BSIM3qcdump, heres[2]->BSIM3qcdump, heres[3]->BSIM3qcdump}); + if (SIMDANY(error)) + return error; + + error = vec4_NIintegrate(ckt, &geq, &ceq, 0.0, (Vec4m ){heres[0]->BSIM3qcheq, heres[1]->BSIM3qcheq, heres[2]->BSIM3qcheq, heres[3]->BSIM3qcheq}); + if (SIMDANY(error)) + return error; + + } + + goto line860; + line850: + ceqqg = (ceqqb = (ceqqd = vec4_SIMDTOVECTOR(0.0))); + + cqcheq = (cqdef = vec4_SIMDTOVECTOR(0.0)); + gcdgb = (gcddb = (gcdsb = vec4_SIMDTOVECTOR(0.0))); + gcsgb = (gcsdb = (gcssb = vec4_SIMDTOVECTOR(0.0))); + gcggb = (gcgdb = (gcgsb = vec4_SIMDTOVECTOR(0.0))); + gcbgb = (gcbdb = (gcbsb = vec4_SIMDTOVECTOR(0.0))); + gqdef = (gcqgb = (gcqdb = (gcqsb = (gcqbb = vec4_SIMDTOVECTOR(0.0))))); + ggtg = (ggtd = (ggtb = (ggts = vec4_SIMDTOVECTOR(0.0)))); + dxpart = vec4_SIMDTOVECTOR(0.6); + if (1) + { + Vec4m condmask0 = BSIM3mode; + Vec4m condmask_true0 = condmask0; + dxpart = vec4_blend(dxpart, vec4_SIMDTOVECTOR(0.4), condmask_true0); + } + + sxpart = 1.0 - dxpart; + ddxpart_dVd = (ddxpart_dVg = (ddxpart_dVb = (ddxpart_dVs = vec4_SIMDTOVECTOR(0.0)))); + dsxpart_dVd = (dsxpart_dVg = (dsxpart_dVb = (dsxpart_dVs = vec4_SIMDTOVECTOR(0.0)))); + if (heres[0]->BSIM3nqsMod) + { + Vec4d val = ((((16.0 * ((Vec4d ){heres[0]->BSIM3u0temp, heres[1]->BSIM3u0temp, heres[2]->BSIM3u0temp, heres[3]->BSIM3u0temp})) * model->BSIM3vtm) / pParam->BSIM3leffCV) / pParam->BSIM3leffCV) * ScalingFactor; + heres[0]->BSIM3gtau = val[0]; + heres[1]->BSIM3gtau = val[1]; + heres[2]->BSIM3gtau = val[2]; + heres[3]->BSIM3gtau = val[3]; + } + else + { + heres[0]->BSIM3gtau = 0.0; + heres[1]->BSIM3gtau = 0.0; + heres[2]->BSIM3gtau = 0.0; + heres[3]->BSIM3gtau = 0.0; + } + + goto line900; + line860: + cqgate = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqg, heres[1]->BSIM3cqg, heres[2]->BSIM3cqg, heres[3]->BSIM3cqg}); + + cqbulk = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqb, heres[1]->BSIM3cqb, heres[2]->BSIM3cqb, heres[3]->BSIM3cqb}); + cqdrn = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqd, heres[1]->BSIM3cqd, heres[2]->BSIM3cqd, heres[3]->BSIM3cqd}); + ceqqg = ((cqgate - (gcggb * vgb)) + (gcgdb * vbd)) + (gcgsb * vbs); + ceqqb = ((cqbulk - (gcbgb * vgb)) + (gcbdb * vbd)) + (gcbsb * vbs); + ceqqd = ((cqdrn - (gcdgb * vgb)) + (gcddb * vbd)) + (gcdsb * vbs); + if (heres[0]->BSIM3nqsMod) + { + T0 = ((ggtg * vgb) - (ggtd * vbd)) - (ggts * vbs); + ceqqg += T0; + T1 = qdef * ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau}); + ceqqd -= (dxpart * T0) + (T1 * (((ddxpart_dVg * vgb) - (ddxpart_dVd * vbd)) - (ddxpart_dVs * vbs))); + cqdef = vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqcdump, heres[1]->BSIM3cqcdump, heres[2]->BSIM3cqcdump, heres[3]->BSIM3cqcdump}) - (gqdef * qdef); + cqcheq = (vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqcheq, heres[1]->BSIM3cqcheq, heres[2]->BSIM3cqcheq, heres[3]->BSIM3cqcheq}) - (((gcqgb * vgb) - (gcqdb * vbd)) - (gcqsb * vbs))) + T0; + } + + if (ckt->CKTmode & MODEINITTRAN) + { + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3cqb, heres[1]->BSIM3cqb, heres[2]->BSIM3cqb, heres[3]->BSIM3cqb}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqb, heres[1]->BSIM3cqb, heres[2]->BSIM3cqb, heres[3]->BSIM3cqb})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3cqg, heres[1]->BSIM3cqg, heres[2]->BSIM3cqg, heres[3]->BSIM3cqg}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqg, heres[1]->BSIM3cqg, heres[2]->BSIM3cqg, heres[3]->BSIM3cqg})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3cqd, heres[1]->BSIM3cqd, heres[2]->BSIM3cqd, heres[3]->BSIM3cqd}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqd, heres[1]->BSIM3cqd, heres[2]->BSIM3cqd, heres[3]->BSIM3cqd})); + if (heres[0]->BSIM3nqsMod) + { + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3cqcheq, heres[1]->BSIM3cqcheq, heres[2]->BSIM3cqcheq, heres[3]->BSIM3cqcheq}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqcheq, heres[1]->BSIM3cqcheq, heres[2]->BSIM3cqcheq, heres[3]->BSIM3cqcheq})); + vec4_StateStore(ckt->CKTstate1, (Vec4m ){heres[0]->BSIM3cqcdump, heres[1]->BSIM3cqcdump, heres[2]->BSIM3cqcdump, heres[3]->BSIM3cqcdump}, vec4_StateAccess(ckt->CKTstate0, (Vec4m ){heres[0]->BSIM3cqcdump, heres[1]->BSIM3cqcdump, heres[2]->BSIM3cqcdump, heres[3]->BSIM3cqcdump})); + } + + } + + line900: + if (1) + { + Vec4m condmask0 = BSIM3mode; + Vec4m condmask_true0 = condmask0; + Vec4m condmask_false0 = ~condmask0; + { + Gm = vec4_blend(Gm, (Vec4d ){heres[0]->BSIM3gm, heres[1]->BSIM3gm, heres[2]->BSIM3gm, heres[3]->BSIM3gm}, condmask_true0); + Gmbs = vec4_blend(Gmbs, (Vec4d ){heres[0]->BSIM3gmbs, heres[1]->BSIM3gmbs, heres[2]->BSIM3gmbs, heres[3]->BSIM3gmbs}, condmask_true0); + FwdSum = vec4_blend(FwdSum, Gm + Gmbs, condmask_true0); + RevSum = vec4_blend(RevSum, vec4_SIMDTOVECTOR(0.0), condmask_true0); + cdreq = vec4_blend(cdreq, model->BSIM3type * (((cdrain - (((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds}) * vds)) - (Gm * vgs)) - (Gmbs * vbs)), condmask_true0); + ceqbd = vec4_blend(ceqbd, (-model->BSIM3type) * (((((Vec4d ){heres[0]->BSIM3csub, heres[1]->BSIM3csub, heres[2]->BSIM3csub, heres[3]->BSIM3csub}) - (((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}) * vds)) - (((Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs}) * vgs)) - (((Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}) * vbs)), condmask_true0); + ceqbs = vec4_blend(ceqbs, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gbbdp = vec4_blend(gbbdp, -((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}), condmask_true0); + gbbsp = vec4_blend(gbbsp, (((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}) + ((Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs})) + ((Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}), condmask_true0); + gbdpg = vec4_blend(gbdpg, (Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs}, condmask_true0); + gbdpdp = vec4_blend(gbdpdp, (Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}, condmask_true0); + gbdpb = vec4_blend(gbdpb, (Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}, condmask_true0); + gbdpsp = vec4_blend(gbdpsp, -((gbdpg + gbdpdp) + gbdpb), condmask_true0); + gbspg = vec4_blend(gbspg, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gbspdp = vec4_blend(gbspdp, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gbspb = vec4_blend(gbspb, vec4_SIMDTOVECTOR(0.0), condmask_true0); + gbspsp = vec4_blend(gbspsp, vec4_SIMDTOVECTOR(0.0), condmask_true0); + } + { + Gm = vec4_blend(Gm, -((Vec4d ){heres[0]->BSIM3gm, heres[1]->BSIM3gm, heres[2]->BSIM3gm, heres[3]->BSIM3gm}), condmask_false0); + Gmbs = vec4_blend(Gmbs, -((Vec4d ){heres[0]->BSIM3gmbs, heres[1]->BSIM3gmbs, heres[2]->BSIM3gmbs, heres[3]->BSIM3gmbs}), condmask_false0); + FwdSum = vec4_blend(FwdSum, vec4_SIMDTOVECTOR(0.0), condmask_false0); + RevSum = vec4_blend(RevSum, -(Gm + Gmbs), condmask_false0); + cdreq = vec4_blend(cdreq, (-model->BSIM3type) * (((cdrain + (((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds}) * vds)) + (Gm * vgd)) + (Gmbs * vbd)), condmask_false0); + ceqbs = vec4_blend(ceqbs, (-model->BSIM3type) * (((((Vec4d ){heres[0]->BSIM3csub, heres[1]->BSIM3csub, heres[2]->BSIM3csub, heres[3]->BSIM3csub}) + (((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}) * vds)) - (((Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs}) * vgd)) - (((Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}) * vbd)), condmask_false0); + ceqbd = vec4_blend(ceqbd, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gbbsp = vec4_blend(gbbsp, -((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}), condmask_false0); + gbbdp = vec4_blend(gbbdp, (((Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}) + ((Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs})) + ((Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}), condmask_false0); + gbdpg = vec4_blend(gbdpg, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gbdpsp = vec4_blend(gbdpsp, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gbdpb = vec4_blend(gbdpb, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gbdpdp = vec4_blend(gbdpdp, vec4_SIMDTOVECTOR(0.0), condmask_false0); + gbspg = vec4_blend(gbspg, (Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs}, condmask_false0); + gbspsp = vec4_blend(gbspsp, (Vec4d ){heres[0]->BSIM3gbds, heres[1]->BSIM3gbds, heres[2]->BSIM3gbds, heres[3]->BSIM3gbds}, condmask_false0); + gbspb = vec4_blend(gbspb, (Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs}, condmask_false0); + gbspdp = vec4_blend(gbspdp, -((gbspg + gbspsp) + gbspb), condmask_false0); + } + } + + + if (model->BSIM3type > 0) + { + ceqbs += ((Vec4d ){heres[0]->BSIM3cbs, heres[1]->BSIM3cbs, heres[2]->BSIM3cbs, heres[3]->BSIM3cbs}) - (((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs}) * vbs); + ceqbd += ((Vec4d ){heres[0]->BSIM3cbd, heres[1]->BSIM3cbd, heres[2]->BSIM3cbd, heres[3]->BSIM3cbd}) - (((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd}) * vbd); + } + else + { + ceqbs -= ((Vec4d ){heres[0]->BSIM3cbs, heres[1]->BSIM3cbs, heres[2]->BSIM3cbs, heres[3]->BSIM3cbs}) - (((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs}) * vbs); + ceqbd -= ((Vec4d ){heres[0]->BSIM3cbd, heres[1]->BSIM3cbd, heres[2]->BSIM3cbd, heres[3]->BSIM3cbd}) - (((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd}) * vbd); + ceqqg = -ceqqg; + ceqqb = -ceqqb; + ceqqd = -ceqqd; + cqdef = -cqdef; + cqcheq = -cqcheq; + } + + m = (Vec4d ){heres[0]->BSIM3m, heres[1]->BSIM3m, heres[2]->BSIM3m, heres[3]->BSIM3m}; + vec4_StateSub(ckt->CKTrhs, (Vec4m ){heres[0]->BSIM3gNode, heres[1]->BSIM3gNode, heres[2]->BSIM3gNode, heres[3]->BSIM3gNode}, m * ceqqg); + vec4_StateSub(ckt->CKTrhs, (Vec4m ){heres[0]->BSIM3bNode, heres[1]->BSIM3bNode, heres[2]->BSIM3bNode, heres[3]->BSIM3bNode}, m * ((ceqbs + ceqbd) + ceqqb)); + vec4_StateAdd(ckt->CKTrhs, (Vec4m ){heres[0]->BSIM3dNodePrime, heres[1]->BSIM3dNodePrime, heres[2]->BSIM3dNodePrime, heres[3]->BSIM3dNodePrime}, m * ((ceqbd - cdreq) - ceqqd)); + vec4_StateAdd(ckt->CKTrhs, (Vec4m ){heres[0]->BSIM3sNodePrime, heres[1]->BSIM3sNodePrime, heres[2]->BSIM3sNodePrime, heres[3]->BSIM3sNodePrime}, m * ((((cdreq + ceqbs) + ceqqg) + ceqqb) + ceqqd)); + if (heres[0]->BSIM3nqsMod) + vec4_StateAdd(ckt->CKTrhs, (Vec4m ){heres[0]->BSIM3qNode, heres[1]->BSIM3qNode, heres[2]->BSIM3qNode, heres[3]->BSIM3qNode}, m * (cqcheq - cqdef)); + + T1 = qdef * ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau}); + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3drainConductance, heres[1]->BSIM3drainConductance, heres[2]->BSIM3drainConductance, heres[3]->BSIM3drainConductance}); + *heres[0]->BSIM3DdPtr += val[0]; + *heres[1]->BSIM3DdPtr += val[1]; + *heres[2]->BSIM3DdPtr += val[2]; + *heres[3]->BSIM3DdPtr += val[3]; + } + { + Vec4d val = m * (gcggb - ggtg); + *heres[0]->BSIM3GgPtr += val[0]; + *heres[1]->BSIM3GgPtr += val[1]; + *heres[2]->BSIM3GgPtr += val[2]; + *heres[3]->BSIM3GgPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3sourceConductance, heres[1]->BSIM3sourceConductance, heres[2]->BSIM3sourceConductance, heres[3]->BSIM3sourceConductance}); + *heres[0]->BSIM3SsPtr += val[0]; + *heres[1]->BSIM3SsPtr += val[1]; + *heres[2]->BSIM3SsPtr += val[2]; + *heres[3]->BSIM3SsPtr += val[3]; + } + { + Vec4d val = m * (((((((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd}) + ((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs})) - gcbgb) - gcbdb) - gcbsb) - ((Vec4d ){heres[0]->BSIM3gbbs, heres[1]->BSIM3gbbs, heres[2]->BSIM3gbbs, heres[3]->BSIM3gbbs})); + *heres[0]->BSIM3BbPtr += val[0]; + *heres[1]->BSIM3BbPtr += val[1]; + *heres[2]->BSIM3BbPtr += val[2]; + *heres[3]->BSIM3BbPtr += val[3]; + } + { + Vec4d val = m * (((((((((Vec4d ){heres[0]->BSIM3drainConductance, heres[1]->BSIM3drainConductance, heres[2]->BSIM3drainConductance, heres[3]->BSIM3drainConductance}) + ((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds})) + ((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd})) + RevSum) + gcddb) + (dxpart * ggtd)) + (T1 * ddxpart_dVd)) + gbdpdp); + *heres[0]->BSIM3DPdpPtr += val[0]; + *heres[1]->BSIM3DPdpPtr += val[1]; + *heres[2]->BSIM3DPdpPtr += val[2]; + *heres[3]->BSIM3DPdpPtr += val[3]; + } + { + Vec4d val = m * (((((((((Vec4d ){heres[0]->BSIM3sourceConductance, heres[1]->BSIM3sourceConductance, heres[2]->BSIM3sourceConductance, heres[3]->BSIM3sourceConductance}) + ((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds})) + ((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs})) + FwdSum) + gcssb) + (sxpart * ggts)) + (T1 * dsxpart_dVs)) + gbspsp); + *heres[0]->BSIM3SPspPtr += val[0]; + *heres[1]->BSIM3SPspPtr += val[1]; + *heres[2]->BSIM3SPspPtr += val[2]; + *heres[3]->BSIM3SPspPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3drainConductance, heres[1]->BSIM3drainConductance, heres[2]->BSIM3drainConductance, heres[3]->BSIM3drainConductance}); + *heres[0]->BSIM3DdpPtr -= val[0]; + *heres[1]->BSIM3DdpPtr -= val[1]; + *heres[2]->BSIM3DdpPtr -= val[2]; + *heres[3]->BSIM3DdpPtr -= val[3]; + } + { + Vec4d val = m * (((gcggb + gcgdb) + gcgsb) + ggtb); + *heres[0]->BSIM3GbPtr -= val[0]; + *heres[1]->BSIM3GbPtr -= val[1]; + *heres[2]->BSIM3GbPtr -= val[2]; + *heres[3]->BSIM3GbPtr -= val[3]; + } + { + Vec4d val = m * (gcgdb - ggtd); + *heres[0]->BSIM3GdpPtr += val[0]; + *heres[1]->BSIM3GdpPtr += val[1]; + *heres[2]->BSIM3GdpPtr += val[2]; + *heres[3]->BSIM3GdpPtr += val[3]; + } + { + Vec4d val = m * (gcgsb - ggts); + *heres[0]->BSIM3GspPtr += val[0]; + *heres[1]->BSIM3GspPtr += val[1]; + *heres[2]->BSIM3GspPtr += val[2]; + *heres[3]->BSIM3GspPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3sourceConductance, heres[1]->BSIM3sourceConductance, heres[2]->BSIM3sourceConductance, heres[3]->BSIM3sourceConductance}); + *heres[0]->BSIM3SspPtr -= val[0]; + *heres[1]->BSIM3SspPtr -= val[1]; + *heres[2]->BSIM3SspPtr -= val[2]; + *heres[3]->BSIM3SspPtr -= val[3]; + } + { + Vec4d val = m * (gcbgb - ((Vec4d ){heres[0]->BSIM3gbgs, heres[1]->BSIM3gbgs, heres[2]->BSIM3gbgs, heres[3]->BSIM3gbgs})); + *heres[0]->BSIM3BgPtr += val[0]; + *heres[1]->BSIM3BgPtr += val[1]; + *heres[2]->BSIM3BgPtr += val[2]; + *heres[3]->BSIM3BgPtr += val[3]; + } + { + Vec4d val = m * ((gcbdb - ((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd})) + gbbdp); + *heres[0]->BSIM3BdpPtr += val[0]; + *heres[1]->BSIM3BdpPtr += val[1]; + *heres[2]->BSIM3BdpPtr += val[2]; + *heres[3]->BSIM3BdpPtr += val[3]; + } + { + Vec4d val = m * ((gcbsb - ((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs})) + gbbsp); + *heres[0]->BSIM3BspPtr += val[0]; + *heres[1]->BSIM3BspPtr += val[1]; + *heres[2]->BSIM3BspPtr += val[2]; + *heres[3]->BSIM3BspPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3drainConductance, heres[1]->BSIM3drainConductance, heres[2]->BSIM3drainConductance, heres[3]->BSIM3drainConductance}); + *heres[0]->BSIM3DPdPtr -= val[0]; + *heres[1]->BSIM3DPdPtr -= val[1]; + *heres[2]->BSIM3DPdPtr -= val[2]; + *heres[3]->BSIM3DPdPtr -= val[3]; + } + { + Vec4d val = m * ((((Gm + gcdgb) + (dxpart * ggtg)) + (T1 * ddxpart_dVg)) + gbdpg); + *heres[0]->BSIM3DPgPtr += val[0]; + *heres[1]->BSIM3DPgPtr += val[1]; + *heres[2]->BSIM3DPgPtr += val[2]; + *heres[3]->BSIM3DPgPtr += val[3]; + } + { + Vec4d val = m * (((((((((Vec4d ){heres[0]->BSIM3gbd, heres[1]->BSIM3gbd, heres[2]->BSIM3gbd, heres[3]->BSIM3gbd}) - Gmbs) + gcdgb) + gcddb) + gcdsb) - (dxpart * ggtb)) - (T1 * ddxpart_dVb)) - gbdpb); + *heres[0]->BSIM3DPbPtr -= val[0]; + *heres[1]->BSIM3DPbPtr -= val[1]; + *heres[2]->BSIM3DPbPtr -= val[2]; + *heres[3]->BSIM3DPbPtr -= val[3]; + } + { + Vec4d val = m * (((((((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds}) + FwdSum) - gcdsb) - (dxpart * ggts)) - (T1 * ddxpart_dVs)) - gbdpsp); + *heres[0]->BSIM3DPspPtr -= val[0]; + *heres[1]->BSIM3DPspPtr -= val[1]; + *heres[2]->BSIM3DPspPtr -= val[2]; + *heres[3]->BSIM3DPspPtr -= val[3]; + } + { + Vec4d val = m * ((((gcsgb - Gm) + (sxpart * ggtg)) + (T1 * dsxpart_dVg)) + gbspg); + *heres[0]->BSIM3SPgPtr += val[0]; + *heres[1]->BSIM3SPgPtr += val[1]; + *heres[2]->BSIM3SPgPtr += val[2]; + *heres[3]->BSIM3SPgPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3sourceConductance, heres[1]->BSIM3sourceConductance, heres[2]->BSIM3sourceConductance, heres[3]->BSIM3sourceConductance}); + *heres[0]->BSIM3SPsPtr -= val[0]; + *heres[1]->BSIM3SPsPtr -= val[1]; + *heres[2]->BSIM3SPsPtr -= val[2]; + *heres[3]->BSIM3SPsPtr -= val[3]; + } + { + Vec4d val = m * (((((((((Vec4d ){heres[0]->BSIM3gbs, heres[1]->BSIM3gbs, heres[2]->BSIM3gbs, heres[3]->BSIM3gbs}) + Gmbs) + gcsgb) + gcsdb) + gcssb) - (sxpart * ggtb)) - (T1 * dsxpart_dVb)) - gbspb); + *heres[0]->BSIM3SPbPtr -= val[0]; + *heres[1]->BSIM3SPbPtr -= val[1]; + *heres[2]->BSIM3SPbPtr -= val[2]; + *heres[3]->BSIM3SPbPtr -= val[3]; + } + { + Vec4d val = m * (((((((Vec4d ){heres[0]->BSIM3gds, heres[1]->BSIM3gds, heres[2]->BSIM3gds, heres[3]->BSIM3gds}) + RevSum) - gcsdb) - (sxpart * ggtd)) - (T1 * dsxpart_dVd)) - gbspdp); + *heres[0]->BSIM3SPdpPtr -= val[0]; + *heres[1]->BSIM3SPdpPtr -= val[1]; + *heres[2]->BSIM3SPdpPtr -= val[2]; + *heres[3]->BSIM3SPdpPtr -= val[3]; + } + if (heres[0]->BSIM3nqsMod) + { + { + Vec4d val = m * (gqdef + ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau})); + *heres[0]->BSIM3QqPtr += val[0]; + *heres[1]->BSIM3QqPtr += val[1]; + *heres[2]->BSIM3QqPtr += val[2]; + *heres[3]->BSIM3QqPtr += val[3]; + } + { + Vec4d val = m * (dxpart * ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau})); + *heres[0]->BSIM3DPqPtr += val[0]; + *heres[1]->BSIM3DPqPtr += val[1]; + *heres[2]->BSIM3DPqPtr += val[2]; + *heres[3]->BSIM3DPqPtr += val[3]; + } + { + Vec4d val = m * (sxpart * ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau})); + *heres[0]->BSIM3SPqPtr += val[0]; + *heres[1]->BSIM3SPqPtr += val[1]; + *heres[2]->BSIM3SPqPtr += val[2]; + *heres[3]->BSIM3SPqPtr += val[3]; + } + { + Vec4d val = m * ((Vec4d ){heres[0]->BSIM3gtau, heres[1]->BSIM3gtau, heres[2]->BSIM3gtau, heres[3]->BSIM3gtau}); + *heres[0]->BSIM3GqPtr -= val[0]; + *heres[1]->BSIM3GqPtr -= val[1]; + *heres[2]->BSIM3GqPtr -= val[2]; + *heres[3]->BSIM3GqPtr -= val[3]; + } + { + Vec4d val = m * (ggtg - gcqgb); + *heres[0]->BSIM3QgPtr += val[0]; + *heres[1]->BSIM3QgPtr += val[1]; + *heres[2]->BSIM3QgPtr += val[2]; + *heres[3]->BSIM3QgPtr += val[3]; + } + { + Vec4d val = m * (ggtd - gcqdb); + *heres[0]->BSIM3QdpPtr += val[0]; + *heres[1]->BSIM3QdpPtr += val[1]; + *heres[2]->BSIM3QdpPtr += val[2]; + *heres[3]->BSIM3QdpPtr += val[3]; + } + { + Vec4d val = m * (ggts - gcqsb); + *heres[0]->BSIM3QspPtr += val[0]; + *heres[1]->BSIM3QspPtr += val[1]; + *heres[2]->BSIM3QspPtr += val[2]; + *heres[3]->BSIM3QspPtr += val[3]; + } + { + Vec4d val = m * (ggtb - gcqbb); + *heres[0]->BSIM3QbPtr += val[0]; + *heres[1]->BSIM3QbPtr += val[1]; + *heres[2]->BSIM3QbPtr += val[2]; + *heres[3]->BSIM3QbPtr += val[3]; + } + } + + line1000: + ; + + return OK; +} + diff --git a/src/spicelib/devices/bsim3simd/b3ldsimd.c b/src/spicelib/devices/bsim3simd/b3ldsimd.c new file mode 100644 index 000000000..43f155743 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3ldsimd.c @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright 2020 Florian Ballenegger, Anamosic Ballenegger Design + ******************************************************************************* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +#include "ngspice/SIMD/simdvector.h" +#include "ngspice/SIMD/simdop.h" +#include "ngspice/SIMD/simdniinteg.h" + +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define EPSOX 3.453133e-11 +#define EPSSI 1.03594e-10 +#define Charge_q 1.60219e-19 +#define DELTA_1 0.02 +#define DELTA_2 0.02 +#define DELTA_3 0.02 +#define DELTA_4 0.02 + +#define SIMDANY(err) (err!=0) +#define SIMDIFYCMD(cmd) /* empty */ +#define SIMDifySaveScope(sc) /* empty */ + +int BSIM3_ACM_saturationCurrents(BSIM3model*, BSIM3instance*, + double*, double*); +int BSIM3_ACM_junctionCapacitances(BSIM3model*, BSIM3instance*, + double*, double*,double*, double*,double*, double*); + +static inline VecNd vecN_SIMDLOADDATA(int idx, double data[7][NSIMD]) +{ + VecNd r; + for(int i=0;iiValue = model->BSIM3mobMod; + return(OK); + case BSIM3_MOD_PARAMCHK: + value->iValue = model->BSIM3paramChk; + return(OK); + case BSIM3_MOD_BINUNIT: + value->iValue = model->BSIM3binUnit; + return(OK); + case BSIM3_MOD_CAPMOD: + value->iValue = model->BSIM3capMod; + return(OK); + 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); + case BSIM3_MOD_TOX : + value->rValue = model->BSIM3tox; + return(OK); + case BSIM3_MOD_TOXM : + value->rValue = model->BSIM3toxm; + return(OK); + case BSIM3_MOD_CDSC : + value->rValue = model->BSIM3cdsc; + return(OK); + case BSIM3_MOD_CDSCB : + value->rValue = model->BSIM3cdscb; + return(OK); + + case BSIM3_MOD_CDSCD : + value->rValue = model->BSIM3cdscd; + return(OK); + + case BSIM3_MOD_CIT : + value->rValue = model->BSIM3cit; + return(OK); + case BSIM3_MOD_NFACTOR : + value->rValue = model->BSIM3nfactor; + return(OK); + case BSIM3_MOD_XJ: + value->rValue = model->BSIM3xj; + return(OK); + case BSIM3_MOD_VSAT: + value->rValue = model->BSIM3vsat; + return(OK); + case BSIM3_MOD_AT: + value->rValue = model->BSIM3at; + return(OK); + case BSIM3_MOD_A0: + value->rValue = model->BSIM3a0; + return(OK); + + case BSIM3_MOD_AGS: + value->rValue = model->BSIM3ags; + return(OK); + + case BSIM3_MOD_A1: + value->rValue = model->BSIM3a1; + return(OK); + case BSIM3_MOD_A2: + value->rValue = model->BSIM3a2; + return(OK); + case BSIM3_MOD_KETA: + value->rValue = model->BSIM3keta; + return(OK); + case BSIM3_MOD_NSUB: + value->rValue = model->BSIM3nsub; + return(OK); + case BSIM3_MOD_NPEAK: + value->rValue = model->BSIM3npeak; + return(OK); + case BSIM3_MOD_NGATE: + value->rValue = model->BSIM3ngate; + return(OK); + case BSIM3_MOD_GAMMA1: + value->rValue = model->BSIM3gamma1; + return(OK); + case BSIM3_MOD_GAMMA2: + value->rValue = model->BSIM3gamma2; + return(OK); + case BSIM3_MOD_VBX: + value->rValue = model->BSIM3vbx; + return(OK); + case BSIM3_MOD_VBM: + value->rValue = model->BSIM3vbm; + return(OK); + case BSIM3_MOD_XT: + value->rValue = model->BSIM3xt; + return(OK); + case BSIM3_MOD_K1: + value->rValue = model->BSIM3k1; + return(OK); + case BSIM3_MOD_KT1: + value->rValue = model->BSIM3kt1; + return(OK); + case BSIM3_MOD_KT1L: + value->rValue = model->BSIM3kt1l; + return(OK); + case BSIM3_MOD_KT2 : + value->rValue = model->BSIM3kt2; + return(OK); + case BSIM3_MOD_K2 : + value->rValue = model->BSIM3k2; + return(OK); + case BSIM3_MOD_K3: + value->rValue = model->BSIM3k3; + return(OK); + case BSIM3_MOD_K3B: + value->rValue = model->BSIM3k3b; + return(OK); + case BSIM3_MOD_W0: + value->rValue = model->BSIM3w0; + return(OK); + case BSIM3_MOD_NLX: + value->rValue = model->BSIM3nlx; + return(OK); + case BSIM3_MOD_DVT0 : + value->rValue = model->BSIM3dvt0; + return(OK); + case BSIM3_MOD_DVT1 : + value->rValue = model->BSIM3dvt1; + return(OK); + case BSIM3_MOD_DVT2 : + value->rValue = model->BSIM3dvt2; + return(OK); + case BSIM3_MOD_DVT0W : + value->rValue = model->BSIM3dvt0w; + return(OK); + case BSIM3_MOD_DVT1W : + value->rValue = model->BSIM3dvt1w; + return(OK); + case BSIM3_MOD_DVT2W : + value->rValue = model->BSIM3dvt2w; + return(OK); + case BSIM3_MOD_DROUT : + value->rValue = model->BSIM3drout; + return(OK); + case BSIM3_MOD_DSUB : + value->rValue = model->BSIM3dsub; + return(OK); + case BSIM3_MOD_VTH0: + value->rValue = model->BSIM3vth0; + return(OK); + case BSIM3_MOD_UA: + value->rValue = model->BSIM3ua; + return(OK); + case BSIM3_MOD_UA1: + value->rValue = model->BSIM3ua1; + return(OK); + case BSIM3_MOD_UB: + value->rValue = model->BSIM3ub; + return(OK); + case BSIM3_MOD_UB1: + value->rValue = model->BSIM3ub1; + return(OK); + case BSIM3_MOD_UC: + value->rValue = model->BSIM3uc; + return(OK); + case BSIM3_MOD_UC1: + value->rValue = model->BSIM3uc1; + return(OK); + case BSIM3_MOD_U0: + value->rValue = model->BSIM3u0; + return(OK); + case BSIM3_MOD_UTE: + value->rValue = model->BSIM3ute; + return(OK); + case BSIM3_MOD_VOFF: + value->rValue = model->BSIM3voff; + return(OK); + case BSIM3_MOD_DELTA: + value->rValue = model->BSIM3delta; + return(OK); + case BSIM3_MOD_RDSW: + value->rValue = model->BSIM3rdsw; + return(OK); + case BSIM3_MOD_PRWG: + value->rValue = model->BSIM3prwg; + return(OK); + case BSIM3_MOD_PRWB: + value->rValue = model->BSIM3prwb; + return(OK); + case BSIM3_MOD_PRT: + value->rValue = model->BSIM3prt; + return(OK); + case BSIM3_MOD_ETA0: + value->rValue = model->BSIM3eta0; + return(OK); + case BSIM3_MOD_ETAB: + value->rValue = model->BSIM3etab; + return(OK); + case BSIM3_MOD_PCLM: + value->rValue = model->BSIM3pclm; + return(OK); + case BSIM3_MOD_PDIBL1: + value->rValue = model->BSIM3pdibl1; + return(OK); + case BSIM3_MOD_PDIBL2: + value->rValue = model->BSIM3pdibl2; + return(OK); + case BSIM3_MOD_PDIBLB: + value->rValue = model->BSIM3pdiblb; + return(OK); + case BSIM3_MOD_PSCBE1: + value->rValue = model->BSIM3pscbe1; + return(OK); + case BSIM3_MOD_PSCBE2: + value->rValue = model->BSIM3pscbe2; + return(OK); + case BSIM3_MOD_PVAG: + value->rValue = model->BSIM3pvag; + return(OK); + case BSIM3_MOD_WR: + value->rValue = model->BSIM3wr; + return(OK); + case BSIM3_MOD_DWG: + value->rValue = model->BSIM3dwg; + return(OK); + case BSIM3_MOD_DWB: + value->rValue = model->BSIM3dwb; + return(OK); + case BSIM3_MOD_B0: + value->rValue = model->BSIM3b0; + return(OK); + case BSIM3_MOD_B1: + value->rValue = model->BSIM3b1; + return(OK); + case BSIM3_MOD_ALPHA0: + value->rValue = model->BSIM3alpha0; + return(OK); + case BSIM3_MOD_ALPHA1: + value->rValue = model->BSIM3alpha1; + return(OK); + case BSIM3_MOD_BETA0: + value->rValue = model->BSIM3beta0; + return(OK); + case BSIM3_MOD_IJTH: + value->rValue = model->BSIM3ijth; + return(OK); + case BSIM3_MOD_VFB: + value->rValue = model->BSIM3vfb; + return(OK); + + case BSIM3_MOD_ELM: + value->rValue = model->BSIM3elm; + return(OK); + case BSIM3_MOD_CGSL: + value->rValue = model->BSIM3cgsl; + return(OK); + case BSIM3_MOD_CGDL: + value->rValue = model->BSIM3cgdl; + return(OK); + case BSIM3_MOD_CKAPPA: + value->rValue = model->BSIM3ckappa; + return(OK); + case BSIM3_MOD_CF: + value->rValue = model->BSIM3cf; + return(OK); + case BSIM3_MOD_CLC: + value->rValue = model->BSIM3clc; + return(OK); + case BSIM3_MOD_CLE: + value->rValue = model->BSIM3cle; + return(OK); + case BSIM3_MOD_DWC: + value->rValue = model->BSIM3dwc; + return(OK); + case BSIM3_MOD_DLC: + value->rValue = model->BSIM3dlc; + return(OK); + case BSIM3_MOD_VFBCV: + value->rValue = model->BSIM3vfbcv; + return(OK); + case BSIM3_MOD_ACDE: + value->rValue = model->BSIM3acde; + return(OK); + case BSIM3_MOD_MOIN: + value->rValue = model->BSIM3moin; + return(OK); + case BSIM3_MOD_NOFF: + value->rValue = model->BSIM3noff; + return(OK); + case BSIM3_MOD_VOFFCV: + value->rValue = model->BSIM3voffcv; + return(OK); + case BSIM3_MOD_TCJ: + value->rValue = model->BSIM3tcj; + return(OK); + case BSIM3_MOD_TPB: + value->rValue = model->BSIM3tpb; + return(OK); + case BSIM3_MOD_TCJSW: + value->rValue = model->BSIM3tcjsw; + return(OK); + case BSIM3_MOD_TPBSW: + value->rValue = model->BSIM3tpbsw; + return(OK); + case BSIM3_MOD_TCJSWG: + value->rValue = model->BSIM3tcjswg; + return(OK); + case BSIM3_MOD_TPBSWG: + 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; + return(OK); + case BSIM3_MOD_LCDSCB : + value->rValue = model->BSIM3lcdscb; + return(OK); + case BSIM3_MOD_LCDSCD : + value->rValue = model->BSIM3lcdscd; + return(OK); + case BSIM3_MOD_LCIT : + value->rValue = model->BSIM3lcit; + return(OK); + case BSIM3_MOD_LNFACTOR : + value->rValue = model->BSIM3lnfactor; + return(OK); + case BSIM3_MOD_LXJ: + value->rValue = model->BSIM3lxj; + return(OK); + case BSIM3_MOD_LVSAT: + value->rValue = model->BSIM3lvsat; + return(OK); + case BSIM3_MOD_LAT: + value->rValue = model->BSIM3lat; + return(OK); + case BSIM3_MOD_LA0: + value->rValue = model->BSIM3la0; + return(OK); + case BSIM3_MOD_LAGS: + value->rValue = model->BSIM3lags; + return(OK); + case BSIM3_MOD_LA1: + value->rValue = model->BSIM3la1; + return(OK); + case BSIM3_MOD_LA2: + value->rValue = model->BSIM3la2; + return(OK); + case BSIM3_MOD_LKETA: + value->rValue = model->BSIM3lketa; + return(OK); + case BSIM3_MOD_LNSUB: + value->rValue = model->BSIM3lnsub; + return(OK); + case BSIM3_MOD_LNPEAK: + value->rValue = model->BSIM3lnpeak; + return(OK); + case BSIM3_MOD_LNGATE: + value->rValue = model->BSIM3lngate; + return(OK); + case BSIM3_MOD_LGAMMA1: + value->rValue = model->BSIM3lgamma1; + return(OK); + case BSIM3_MOD_LGAMMA2: + value->rValue = model->BSIM3lgamma2; + return(OK); + case BSIM3_MOD_LVBX: + value->rValue = model->BSIM3lvbx; + return(OK); + case BSIM3_MOD_LVBM: + value->rValue = model->BSIM3lvbm; + return(OK); + case BSIM3_MOD_LXT: + value->rValue = model->BSIM3lxt; + return(OK); + case BSIM3_MOD_LK1: + value->rValue = model->BSIM3lk1; + return(OK); + case BSIM3_MOD_LKT1: + value->rValue = model->BSIM3lkt1; + return(OK); + case BSIM3_MOD_LKT1L: + value->rValue = model->BSIM3lkt1l; + return(OK); + case BSIM3_MOD_LKT2 : + value->rValue = model->BSIM3lkt2; + return(OK); + case BSIM3_MOD_LK2 : + value->rValue = model->BSIM3lk2; + return(OK); + case BSIM3_MOD_LK3: + value->rValue = model->BSIM3lk3; + return(OK); + case BSIM3_MOD_LK3B: + value->rValue = model->BSIM3lk3b; + return(OK); + case BSIM3_MOD_LW0: + value->rValue = model->BSIM3lw0; + return(OK); + case BSIM3_MOD_LNLX: + value->rValue = model->BSIM3lnlx; + return(OK); + case BSIM3_MOD_LDVT0: + value->rValue = model->BSIM3ldvt0; + return(OK); + case BSIM3_MOD_LDVT1 : + value->rValue = model->BSIM3ldvt1; + return(OK); + case BSIM3_MOD_LDVT2 : + value->rValue = model->BSIM3ldvt2; + return(OK); + case BSIM3_MOD_LDVT0W : + value->rValue = model->BSIM3ldvt0w; + return(OK); + case BSIM3_MOD_LDVT1W : + value->rValue = model->BSIM3ldvt1w; + return(OK); + case BSIM3_MOD_LDVT2W : + value->rValue = model->BSIM3ldvt2w; + return(OK); + case BSIM3_MOD_LDROUT : + value->rValue = model->BSIM3ldrout; + return(OK); + case BSIM3_MOD_LDSUB : + value->rValue = model->BSIM3ldsub; + return(OK); + case BSIM3_MOD_LVTH0: + value->rValue = model->BSIM3lvth0; + return(OK); + case BSIM3_MOD_LUA: + value->rValue = model->BSIM3lua; + return(OK); + case BSIM3_MOD_LUA1: + value->rValue = model->BSIM3lua1; + return(OK); + case BSIM3_MOD_LUB: + value->rValue = model->BSIM3lub; + return(OK); + case BSIM3_MOD_LUB1: + value->rValue = model->BSIM3lub1; + return(OK); + case BSIM3_MOD_LUC: + value->rValue = model->BSIM3luc; + return(OK); + case BSIM3_MOD_LUC1: + value->rValue = model->BSIM3luc1; + return(OK); + case BSIM3_MOD_LU0: + value->rValue = model->BSIM3lu0; + return(OK); + case BSIM3_MOD_LUTE: + value->rValue = model->BSIM3lute; + return(OK); + case BSIM3_MOD_LVOFF: + value->rValue = model->BSIM3lvoff; + return(OK); + case BSIM3_MOD_LDELTA: + value->rValue = model->BSIM3ldelta; + return(OK); + case BSIM3_MOD_LRDSW: + value->rValue = model->BSIM3lrdsw; + return(OK); + case BSIM3_MOD_LPRWB: + value->rValue = model->BSIM3lprwb; + return(OK); + case BSIM3_MOD_LPRWG: + value->rValue = model->BSIM3lprwg; + return(OK); + case BSIM3_MOD_LPRT: + value->rValue = model->BSIM3lprt; + return(OK); + case BSIM3_MOD_LETA0: + value->rValue = model->BSIM3leta0; + return(OK); + case BSIM3_MOD_LETAB: + value->rValue = model->BSIM3letab; + return(OK); + case BSIM3_MOD_LPCLM: + value->rValue = model->BSIM3lpclm; + return(OK); + case BSIM3_MOD_LPDIBL1: + value->rValue = model->BSIM3lpdibl1; + return(OK); + case BSIM3_MOD_LPDIBL2: + value->rValue = model->BSIM3lpdibl2; + return(OK); + case BSIM3_MOD_LPDIBLB: + value->rValue = model->BSIM3lpdiblb; + return(OK); + case BSIM3_MOD_LPSCBE1: + value->rValue = model->BSIM3lpscbe1; + return(OK); + case BSIM3_MOD_LPSCBE2: + value->rValue = model->BSIM3lpscbe2; + return(OK); + case BSIM3_MOD_LPVAG: + value->rValue = model->BSIM3lpvag; + return(OK); + case BSIM3_MOD_LWR: + value->rValue = model->BSIM3lwr; + return(OK); + case BSIM3_MOD_LDWG: + value->rValue = model->BSIM3ldwg; + return(OK); + case BSIM3_MOD_LDWB: + value->rValue = model->BSIM3ldwb; + return(OK); + case BSIM3_MOD_LB0: + value->rValue = model->BSIM3lb0; + return(OK); + case BSIM3_MOD_LB1: + value->rValue = model->BSIM3lb1; + return(OK); + case BSIM3_MOD_LALPHA0: + value->rValue = model->BSIM3lalpha0; + return(OK); + case BSIM3_MOD_LALPHA1: + value->rValue = model->BSIM3lalpha1; + return(OK); + case BSIM3_MOD_LBETA0: + value->rValue = model->BSIM3lbeta0; + return(OK); + case BSIM3_MOD_LVFB: + value->rValue = model->BSIM3lvfb; + return(OK); + + case BSIM3_MOD_LELM: + value->rValue = model->BSIM3lelm; + return(OK); + case BSIM3_MOD_LCGSL: + value->rValue = model->BSIM3lcgsl; + return(OK); + case BSIM3_MOD_LCGDL: + value->rValue = model->BSIM3lcgdl; + return(OK); + case BSIM3_MOD_LCKAPPA: + value->rValue = model->BSIM3lckappa; + return(OK); + case BSIM3_MOD_LCF: + value->rValue = model->BSIM3lcf; + return(OK); + case BSIM3_MOD_LCLC: + value->rValue = model->BSIM3lclc; + return(OK); + case BSIM3_MOD_LCLE: + value->rValue = model->BSIM3lcle; + return(OK); + case BSIM3_MOD_LVFBCV: + value->rValue = model->BSIM3lvfbcv; + return(OK); + case BSIM3_MOD_LACDE: + value->rValue = model->BSIM3lacde; + return(OK); + case BSIM3_MOD_LMOIN: + value->rValue = model->BSIM3lmoin; + return(OK); + case BSIM3_MOD_LNOFF: + value->rValue = model->BSIM3lnoff; + return(OK); + case BSIM3_MOD_LVOFFCV: + value->rValue = model->BSIM3lvoffcv; + return(OK); + + /* Width dependence */ + case BSIM3_MOD_WCDSC : + value->rValue = model->BSIM3wcdsc; + return(OK); + case BSIM3_MOD_WCDSCB : + value->rValue = model->BSIM3wcdscb; + return(OK); + case BSIM3_MOD_WCDSCD : + value->rValue = model->BSIM3wcdscd; + return(OK); + case BSIM3_MOD_WCIT : + value->rValue = model->BSIM3wcit; + return(OK); + case BSIM3_MOD_WNFACTOR : + value->rValue = model->BSIM3wnfactor; + return(OK); + case BSIM3_MOD_WXJ: + value->rValue = model->BSIM3wxj; + return(OK); + case BSIM3_MOD_WVSAT: + value->rValue = model->BSIM3wvsat; + return(OK); + case BSIM3_MOD_WAT: + value->rValue = model->BSIM3wat; + return(OK); + case BSIM3_MOD_WA0: + value->rValue = model->BSIM3wa0; + return(OK); + case BSIM3_MOD_WAGS: + value->rValue = model->BSIM3wags; + return(OK); + case BSIM3_MOD_WA1: + value->rValue = model->BSIM3wa1; + return(OK); + case BSIM3_MOD_WA2: + value->rValue = model->BSIM3wa2; + return(OK); + case BSIM3_MOD_WKETA: + value->rValue = model->BSIM3wketa; + return(OK); + case BSIM3_MOD_WNSUB: + value->rValue = model->BSIM3wnsub; + return(OK); + case BSIM3_MOD_WNPEAK: + value->rValue = model->BSIM3wnpeak; + return(OK); + case BSIM3_MOD_WNGATE: + value->rValue = model->BSIM3wngate; + return(OK); + case BSIM3_MOD_WGAMMA1: + value->rValue = model->BSIM3wgamma1; + return(OK); + case BSIM3_MOD_WGAMMA2: + value->rValue = model->BSIM3wgamma2; + return(OK); + case BSIM3_MOD_WVBX: + value->rValue = model->BSIM3wvbx; + return(OK); + case BSIM3_MOD_WVBM: + value->rValue = model->BSIM3wvbm; + return(OK); + case BSIM3_MOD_WXT: + value->rValue = model->BSIM3wxt; + return(OK); + case BSIM3_MOD_WK1: + value->rValue = model->BSIM3wk1; + return(OK); + case BSIM3_MOD_WKT1: + value->rValue = model->BSIM3wkt1; + return(OK); + case BSIM3_MOD_WKT1L: + value->rValue = model->BSIM3wkt1l; + return(OK); + case BSIM3_MOD_WKT2 : + value->rValue = model->BSIM3wkt2; + return(OK); + case BSIM3_MOD_WK2 : + value->rValue = model->BSIM3wk2; + return(OK); + case BSIM3_MOD_WK3: + value->rValue = model->BSIM3wk3; + return(OK); + case BSIM3_MOD_WK3B: + value->rValue = model->BSIM3wk3b; + return(OK); + case BSIM3_MOD_WW0: + value->rValue = model->BSIM3ww0; + return(OK); + case BSIM3_MOD_WNLX: + value->rValue = model->BSIM3wnlx; + return(OK); + case BSIM3_MOD_WDVT0: + value->rValue = model->BSIM3wdvt0; + return(OK); + case BSIM3_MOD_WDVT1 : + value->rValue = model->BSIM3wdvt1; + return(OK); + case BSIM3_MOD_WDVT2 : + value->rValue = model->BSIM3wdvt2; + return(OK); + case BSIM3_MOD_WDVT0W : + value->rValue = model->BSIM3wdvt0w; + return(OK); + case BSIM3_MOD_WDVT1W : + value->rValue = model->BSIM3wdvt1w; + return(OK); + case BSIM3_MOD_WDVT2W : + value->rValue = model->BSIM3wdvt2w; + return(OK); + case BSIM3_MOD_WDROUT : + value->rValue = model->BSIM3wdrout; + return(OK); + case BSIM3_MOD_WDSUB : + value->rValue = model->BSIM3wdsub; + return(OK); + case BSIM3_MOD_WVTH0: + value->rValue = model->BSIM3wvth0; + return(OK); + case BSIM3_MOD_WUA: + value->rValue = model->BSIM3wua; + return(OK); + case BSIM3_MOD_WUA1: + value->rValue = model->BSIM3wua1; + return(OK); + case BSIM3_MOD_WUB: + value->rValue = model->BSIM3wub; + return(OK); + case BSIM3_MOD_WUB1: + value->rValue = model->BSIM3wub1; + return(OK); + case BSIM3_MOD_WUC: + value->rValue = model->BSIM3wuc; + return(OK); + case BSIM3_MOD_WUC1: + value->rValue = model->BSIM3wuc1; + return(OK); + case BSIM3_MOD_WU0: + value->rValue = model->BSIM3wu0; + return(OK); + case BSIM3_MOD_WUTE: + value->rValue = model->BSIM3wute; + return(OK); + case BSIM3_MOD_WVOFF: + value->rValue = model->BSIM3wvoff; + return(OK); + case BSIM3_MOD_WDELTA: + value->rValue = model->BSIM3wdelta; + return(OK); + case BSIM3_MOD_WRDSW: + value->rValue = model->BSIM3wrdsw; + return(OK); + case BSIM3_MOD_WPRWB: + value->rValue = model->BSIM3wprwb; + return(OK); + case BSIM3_MOD_WPRWG: + value->rValue = model->BSIM3wprwg; + return(OK); + case BSIM3_MOD_WPRT: + value->rValue = model->BSIM3wprt; + return(OK); + case BSIM3_MOD_WETA0: + value->rValue = model->BSIM3weta0; + return(OK); + case BSIM3_MOD_WETAB: + value->rValue = model->BSIM3wetab; + return(OK); + case BSIM3_MOD_WPCLM: + value->rValue = model->BSIM3wpclm; + return(OK); + case BSIM3_MOD_WPDIBL1: + value->rValue = model->BSIM3wpdibl1; + return(OK); + case BSIM3_MOD_WPDIBL2: + value->rValue = model->BSIM3wpdibl2; + return(OK); + case BSIM3_MOD_WPDIBLB: + value->rValue = model->BSIM3wpdiblb; + return(OK); + case BSIM3_MOD_WPSCBE1: + value->rValue = model->BSIM3wpscbe1; + return(OK); + case BSIM3_MOD_WPSCBE2: + value->rValue = model->BSIM3wpscbe2; + return(OK); + case BSIM3_MOD_WPVAG: + value->rValue = model->BSIM3wpvag; + return(OK); + case BSIM3_MOD_WWR: + value->rValue = model->BSIM3wwr; + return(OK); + case BSIM3_MOD_WDWG: + value->rValue = model->BSIM3wdwg; + return(OK); + case BSIM3_MOD_WDWB: + value->rValue = model->BSIM3wdwb; + return(OK); + case BSIM3_MOD_WB0: + value->rValue = model->BSIM3wb0; + return(OK); + case BSIM3_MOD_WB1: + value->rValue = model->BSIM3wb1; + return(OK); + case BSIM3_MOD_WALPHA0: + value->rValue = model->BSIM3walpha0; + return(OK); + case BSIM3_MOD_WALPHA1: + value->rValue = model->BSIM3walpha1; + return(OK); + case BSIM3_MOD_WBETA0: + value->rValue = model->BSIM3wbeta0; + return(OK); + case BSIM3_MOD_WVFB: + value->rValue = model->BSIM3wvfb; + return(OK); + + case BSIM3_MOD_WELM: + value->rValue = model->BSIM3welm; + return(OK); + case BSIM3_MOD_WCGSL: + value->rValue = model->BSIM3wcgsl; + return(OK); + case BSIM3_MOD_WCGDL: + value->rValue = model->BSIM3wcgdl; + return(OK); + case BSIM3_MOD_WCKAPPA: + value->rValue = model->BSIM3wckappa; + return(OK); + case BSIM3_MOD_WCF: + value->rValue = model->BSIM3wcf; + return(OK); + case BSIM3_MOD_WCLC: + value->rValue = model->BSIM3wclc; + return(OK); + case BSIM3_MOD_WCLE: + value->rValue = model->BSIM3wcle; + return(OK); + case BSIM3_MOD_WVFBCV: + value->rValue = model->BSIM3wvfbcv; + return(OK); + case BSIM3_MOD_WACDE: + value->rValue = model->BSIM3wacde; + return(OK); + case BSIM3_MOD_WMOIN: + value->rValue = model->BSIM3wmoin; + return(OK); + case BSIM3_MOD_WNOFF: + value->rValue = model->BSIM3wnoff; + return(OK); + case BSIM3_MOD_WVOFFCV: + value->rValue = model->BSIM3wvoffcv; + return(OK); + + /* Cross-term dependence */ + case BSIM3_MOD_PCDSC : + value->rValue = model->BSIM3pcdsc; + return(OK); + case BSIM3_MOD_PCDSCB : + value->rValue = model->BSIM3pcdscb; + return(OK); + case BSIM3_MOD_PCDSCD : + value->rValue = model->BSIM3pcdscd; + return(OK); + case BSIM3_MOD_PCIT : + value->rValue = model->BSIM3pcit; + return(OK); + case BSIM3_MOD_PNFACTOR : + value->rValue = model->BSIM3pnfactor; + return(OK); + case BSIM3_MOD_PXJ: + value->rValue = model->BSIM3pxj; + return(OK); + case BSIM3_MOD_PVSAT: + value->rValue = model->BSIM3pvsat; + return(OK); + case BSIM3_MOD_PAT: + value->rValue = model->BSIM3pat; + return(OK); + case BSIM3_MOD_PA0: + value->rValue = model->BSIM3pa0; + return(OK); + case BSIM3_MOD_PAGS: + value->rValue = model->BSIM3pags; + return(OK); + case BSIM3_MOD_PA1: + value->rValue = model->BSIM3pa1; + return(OK); + case BSIM3_MOD_PA2: + value->rValue = model->BSIM3pa2; + return(OK); + case BSIM3_MOD_PKETA: + value->rValue = model->BSIM3pketa; + return(OK); + case BSIM3_MOD_PNSUB: + value->rValue = model->BSIM3pnsub; + return(OK); + case BSIM3_MOD_PNPEAK: + value->rValue = model->BSIM3pnpeak; + return(OK); + case BSIM3_MOD_PNGATE: + value->rValue = model->BSIM3pngate; + return(OK); + case BSIM3_MOD_PGAMMA1: + value->rValue = model->BSIM3pgamma1; + return(OK); + case BSIM3_MOD_PGAMMA2: + value->rValue = model->BSIM3pgamma2; + return(OK); + case BSIM3_MOD_PVBX: + value->rValue = model->BSIM3pvbx; + return(OK); + case BSIM3_MOD_PVBM: + value->rValue = model->BSIM3pvbm; + return(OK); + case BSIM3_MOD_PXT: + value->rValue = model->BSIM3pxt; + return(OK); + case BSIM3_MOD_PK1: + value->rValue = model->BSIM3pk1; + return(OK); + case BSIM3_MOD_PKT1: + value->rValue = model->BSIM3pkt1; + return(OK); + case BSIM3_MOD_PKT1L: + value->rValue = model->BSIM3pkt1l; + return(OK); + case BSIM3_MOD_PKT2 : + value->rValue = model->BSIM3pkt2; + return(OK); + case BSIM3_MOD_PK2 : + value->rValue = model->BSIM3pk2; + return(OK); + case BSIM3_MOD_PK3: + value->rValue = model->BSIM3pk3; + return(OK); + case BSIM3_MOD_PK3B: + value->rValue = model->BSIM3pk3b; + return(OK); + case BSIM3_MOD_PW0: + value->rValue = model->BSIM3pw0; + return(OK); + case BSIM3_MOD_PNLX: + value->rValue = model->BSIM3pnlx; + return(OK); + case BSIM3_MOD_PDVT0 : + value->rValue = model->BSIM3pdvt0; + return(OK); + case BSIM3_MOD_PDVT1 : + value->rValue = model->BSIM3pdvt1; + return(OK); + case BSIM3_MOD_PDVT2 : + value->rValue = model->BSIM3pdvt2; + return(OK); + case BSIM3_MOD_PDVT0W : + value->rValue = model->BSIM3pdvt0w; + return(OK); + case BSIM3_MOD_PDVT1W : + value->rValue = model->BSIM3pdvt1w; + return(OK); + case BSIM3_MOD_PDVT2W : + value->rValue = model->BSIM3pdvt2w; + return(OK); + case BSIM3_MOD_PDROUT : + value->rValue = model->BSIM3pdrout; + return(OK); + case BSIM3_MOD_PDSUB : + value->rValue = model->BSIM3pdsub; + return(OK); + case BSIM3_MOD_PVTH0: + value->rValue = model->BSIM3pvth0; + return(OK); + case BSIM3_MOD_PUA: + value->rValue = model->BSIM3pua; + return(OK); + case BSIM3_MOD_PUA1: + value->rValue = model->BSIM3pua1; + return(OK); + case BSIM3_MOD_PUB: + value->rValue = model->BSIM3pub; + return(OK); + case BSIM3_MOD_PUB1: + value->rValue = model->BSIM3pub1; + return(OK); + case BSIM3_MOD_PUC: + value->rValue = model->BSIM3puc; + return(OK); + case BSIM3_MOD_PUC1: + value->rValue = model->BSIM3puc1; + return(OK); + case BSIM3_MOD_PU0: + value->rValue = model->BSIM3pu0; + return(OK); + case BSIM3_MOD_PUTE: + value->rValue = model->BSIM3pute; + return(OK); + case BSIM3_MOD_PVOFF: + value->rValue = model->BSIM3pvoff; + return(OK); + case BSIM3_MOD_PDELTA: + value->rValue = model->BSIM3pdelta; + return(OK); + case BSIM3_MOD_PRDSW: + value->rValue = model->BSIM3prdsw; + return(OK); + case BSIM3_MOD_PPRWB: + value->rValue = model->BSIM3pprwb; + return(OK); + case BSIM3_MOD_PPRWG: + value->rValue = model->BSIM3pprwg; + return(OK); + case BSIM3_MOD_PPRT: + value->rValue = model->BSIM3pprt; + return(OK); + case BSIM3_MOD_PETA0: + value->rValue = model->BSIM3peta0; + return(OK); + case BSIM3_MOD_PETAB: + value->rValue = model->BSIM3petab; + return(OK); + case BSIM3_MOD_PPCLM: + value->rValue = model->BSIM3ppclm; + return(OK); + case BSIM3_MOD_PPDIBL1: + value->rValue = model->BSIM3ppdibl1; + return(OK); + case BSIM3_MOD_PPDIBL2: + value->rValue = model->BSIM3ppdibl2; + return(OK); + case BSIM3_MOD_PPDIBLB: + value->rValue = model->BSIM3ppdiblb; + return(OK); + case BSIM3_MOD_PPSCBE1: + value->rValue = model->BSIM3ppscbe1; + return(OK); + case BSIM3_MOD_PPSCBE2: + value->rValue = model->BSIM3ppscbe2; + return(OK); + case BSIM3_MOD_PPVAG: + value->rValue = model->BSIM3ppvag; + return(OK); + case BSIM3_MOD_PWR: + value->rValue = model->BSIM3pwr; + return(OK); + case BSIM3_MOD_PDWG: + value->rValue = model->BSIM3pdwg; + return(OK); + case BSIM3_MOD_PDWB: + value->rValue = model->BSIM3pdwb; + return(OK); + case BSIM3_MOD_PB0: + value->rValue = model->BSIM3pb0; + return(OK); + case BSIM3_MOD_PB1: + value->rValue = model->BSIM3pb1; + return(OK); + case BSIM3_MOD_PALPHA0: + value->rValue = model->BSIM3palpha0; + return(OK); + case BSIM3_MOD_PALPHA1: + value->rValue = model->BSIM3palpha1; + return(OK); + case BSIM3_MOD_PBETA0: + value->rValue = model->BSIM3pbeta0; + return(OK); + case BSIM3_MOD_PVFB: + value->rValue = model->BSIM3pvfb; + return(OK); + + case BSIM3_MOD_PELM: + value->rValue = model->BSIM3pelm; + return(OK); + case BSIM3_MOD_PCGSL: + value->rValue = model->BSIM3pcgsl; + return(OK); + case BSIM3_MOD_PCGDL: + value->rValue = model->BSIM3pcgdl; + return(OK); + case BSIM3_MOD_PCKAPPA: + value->rValue = model->BSIM3pckappa; + return(OK); + case BSIM3_MOD_PCF: + value->rValue = model->BSIM3pcf; + return(OK); + case BSIM3_MOD_PCLC: + value->rValue = model->BSIM3pclc; + return(OK); + case BSIM3_MOD_PCLE: + value->rValue = model->BSIM3pcle; + return(OK); + case BSIM3_MOD_PVFBCV: + value->rValue = model->BSIM3pvfbcv; + return(OK); + case BSIM3_MOD_PACDE: + value->rValue = model->BSIM3pacde; + return(OK); + case BSIM3_MOD_PMOIN: + value->rValue = model->BSIM3pmoin; + return(OK); + case BSIM3_MOD_PNOFF: + value->rValue = model->BSIM3pnoff; + return(OK); + case BSIM3_MOD_PVOFFCV: + value->rValue = model->BSIM3pvoffcv; + return(OK); + + case BSIM3_MOD_TNOM : + value->rValue = model->BSIM3tnom; + return(OK); + case BSIM3_MOD_CGSO: + value->rValue = model->BSIM3cgso; + return(OK); + case BSIM3_MOD_CGDO: + value->rValue = model->BSIM3cgdo; + return(OK); + case BSIM3_MOD_CGBO: + value->rValue = model->BSIM3cgbo; + return(OK); + case BSIM3_MOD_XPART: + value->rValue = model->BSIM3xpart; + return(OK); + case BSIM3_MOD_RSH: + value->rValue = model->BSIM3sheetResistance; + return(OK); + case BSIM3_MOD_JS: + value->rValue = model->BSIM3jctSatCurDensity; + return(OK); + case BSIM3_MOD_JSW: + value->rValue = model->BSIM3jctSidewallSatCurDensity; + return(OK); + case BSIM3_MOD_PB: + value->rValue = model->BSIM3bulkJctPotential; + return(OK); + case BSIM3_MOD_MJ: + value->rValue = model->BSIM3bulkJctBotGradingCoeff; + return(OK); + case BSIM3_MOD_PBSW: + value->rValue = model->BSIM3sidewallJctPotential; + return(OK); + case BSIM3_MOD_MJSW: + value->rValue = model->BSIM3bulkJctSideGradingCoeff; + return(OK); + case BSIM3_MOD_CJ: + value->rValue = model->BSIM3unitAreaJctCap; + return(OK); + case BSIM3_MOD_CJSW: + value->rValue = model->BSIM3unitLengthSidewallJctCap; + return(OK); + case BSIM3_MOD_PBSWG: + value->rValue = model->BSIM3GatesidewallJctPotential; + return(OK); + case BSIM3_MOD_MJSWG: + value->rValue = model->BSIM3bulkJctGateSideGradingCoeff; + return(OK); + case BSIM3_MOD_CJSWG: + value->rValue = model->BSIM3unitLengthGateSidewallJctCap; + return(OK); + case BSIM3_MOD_NJ: + value->rValue = model->BSIM3jctEmissionCoeff; + return(OK); + case BSIM3_MOD_XTI: + value->rValue = model->BSIM3jctTempExponent; + return(OK); + case BSIM3_MOD_LINTNOI: + value->rValue = model->BSIM3lintnoi; + return(OK); + case BSIM3_MOD_LINT: + value->rValue = model->BSIM3Lint; + return(OK); + case BSIM3_MOD_LL: + value->rValue = model->BSIM3Ll; + return(OK); + case BSIM3_MOD_LLC: + value->rValue = model->BSIM3Llc; + return(OK); + case BSIM3_MOD_LLN: + value->rValue = model->BSIM3Lln; + return(OK); + case BSIM3_MOD_LW: + value->rValue = model->BSIM3Lw; + return(OK); + case BSIM3_MOD_LWC: + value->rValue = model->BSIM3Lwc; + return(OK); + case BSIM3_MOD_LWN: + value->rValue = model->BSIM3Lwn; + return(OK); + case BSIM3_MOD_LWL: + value->rValue = model->BSIM3Lwl; + return(OK); + case BSIM3_MOD_LWLC: + value->rValue = model->BSIM3Lwlc; + return(OK); + case BSIM3_MOD_LMIN: + value->rValue = model->BSIM3Lmin; + return(OK); + case BSIM3_MOD_LMAX: + value->rValue = model->BSIM3Lmax; + return(OK); + case BSIM3_MOD_WINT: + value->rValue = model->BSIM3Wint; + return(OK); + case BSIM3_MOD_WL: + value->rValue = model->BSIM3Wl; + return(OK); + case BSIM3_MOD_WLC: + value->rValue = model->BSIM3Wlc; + return(OK); + case BSIM3_MOD_WLN: + value->rValue = model->BSIM3Wln; + return(OK); + case BSIM3_MOD_WW: + value->rValue = model->BSIM3Ww; + return(OK); + case BSIM3_MOD_WWC: + value->rValue = model->BSIM3Wwc; + return(OK); + case BSIM3_MOD_WWN: + value->rValue = model->BSIM3Wwn; + return(OK); + case BSIM3_MOD_WWL: + value->rValue = model->BSIM3Wwl; + return(OK); + case BSIM3_MOD_WWLC: + value->rValue = model->BSIM3Wwlc; + return(OK); + case BSIM3_MOD_WMIN: + value->rValue = model->BSIM3Wmin; + return(OK); + 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); + case BSIM3_MOD_NOIB: + value->rValue = model->BSIM3oxideTrapDensityB; + return(OK); + case BSIM3_MOD_NOIC: + value->rValue = model->BSIM3oxideTrapDensityC; + return(OK); + case BSIM3_MOD_EM: + value->rValue = model->BSIM3em; + return(OK); + case BSIM3_MOD_EF: + value->rValue = model->BSIM3ef; + return(OK); + case BSIM3_MOD_AF: + value->rValue = model->BSIM3af; + return(OK); + case BSIM3_MOD_KF: + value->rValue = model->BSIM3kf; + return(OK); + + case BSIM3_MOD_VGS_MAX: + value->rValue = model->BSIM3vgsMax; + return(OK); + case BSIM3_MOD_VGD_MAX: + value->rValue = model->BSIM3vgdMax; + return(OK); + case BSIM3_MOD_VGB_MAX: + value->rValue = model->BSIM3vgbMax; + return(OK); + case BSIM3_MOD_VDS_MAX: + value->rValue = model->BSIM3vdsMax; + return(OK); + case BSIM3_MOD_VBS_MAX: + value->rValue = model->BSIM3vbsMax; + return(OK); + case BSIM3_MOD_VBD_MAX: + value->rValue = model->BSIM3vbdMax; + return(OK); + case BSIM3_MOD_VGSR_MAX: + value->rValue = model->BSIM3vgsrMax; + return(OK); + case BSIM3_MOD_VGDR_MAX: + value->rValue = model->BSIM3vgdrMax; + return(OK); + case BSIM3_MOD_VGBR_MAX: + value->rValue = model->BSIM3vgbrMax; + return(OK); + case BSIM3_MOD_VBSR_MAX: + value->rValue = model->BSIM3vbsrMax; + return(OK); + case BSIM3_MOD_VBDR_MAX: + value->rValue = model->BSIM3vbdrMax; + return(OK); + + default: + return(E_BADPARM); + } + /* NOTREACHED */ +} + + + diff --git a/src/spicelib/devices/bsim3simd/b3mdel.c b/src/spicelib/devices/bsim3simd/b3mdel.c new file mode 100644 index 000000000..2767840eb --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3mdel.c @@ -0,0 +1,37 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3mdel.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDmDelete(GENmodel *gen_model) +{ + BSIM3model *model = (BSIM3model*) gen_model; + +#ifdef USE_OMP + FREE(model->BSIM3InstanceArray); +#endif + + struct bsim3SizeDependParam *p = model->pSizeDependParamKnot; + while (p) { + struct bsim3SizeDependParam *next_p = p->pNext; + FREE(p); + p = next_p; + } + + /* model->BSIM3modName to be freed in INPtabEnd() */ + FREE(model->BSIM3version); + + return OK; +} diff --git a/src/spicelib/devices/bsim3simd/b3mpar.c b/src/spicelib/devices/bsim3simd/b3mpar.c new file mode 100644 index 000000000..3fce53368 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3mpar.c @@ -0,0 +1,1786 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3mpar.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "bsim3def.h" +#include "ngspice/ifsim.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDmParam( +int param, +IFvalue *value, +GENmodel *inMod) +{ + BSIM3model *mod = (BSIM3model*)inMod; + switch(param) + { case BSIM3_MOD_MOBMOD : + mod->BSIM3mobMod = value->iValue; + mod->BSIM3mobModGiven = TRUE; + break; + case BSIM3_MOD_BINUNIT : + mod->BSIM3binUnit = value->iValue; + mod->BSIM3binUnitGiven = TRUE; + break; + case BSIM3_MOD_PARAMCHK : + mod->BSIM3paramChk = value->iValue; + mod->BSIM3paramChkGiven = TRUE; + break; + case BSIM3_MOD_CAPMOD : + 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 : + mod->BSIM3version = value->sValue; + mod->BSIM3versionGiven = TRUE; + break; + case BSIM3_MOD_TOX : + mod->BSIM3tox = value->rValue; + mod->BSIM3toxGiven = TRUE; + break; + case BSIM3_MOD_TOXM : + mod->BSIM3toxm = value->rValue; + mod->BSIM3toxmGiven = TRUE; + break; + + case BSIM3_MOD_CDSC : + mod->BSIM3cdsc = value->rValue; + mod->BSIM3cdscGiven = TRUE; + break; + case BSIM3_MOD_CDSCB : + mod->BSIM3cdscb = value->rValue; + mod->BSIM3cdscbGiven = TRUE; + break; + + case BSIM3_MOD_CDSCD : + mod->BSIM3cdscd = value->rValue; + mod->BSIM3cdscdGiven = TRUE; + break; + + case BSIM3_MOD_CIT : + mod->BSIM3cit = value->rValue; + mod->BSIM3citGiven = TRUE; + break; + case BSIM3_MOD_NFACTOR : + mod->BSIM3nfactor = value->rValue; + mod->BSIM3nfactorGiven = TRUE; + break; + case BSIM3_MOD_XJ: + mod->BSIM3xj = value->rValue; + mod->BSIM3xjGiven = TRUE; + break; + case BSIM3_MOD_VSAT: + mod->BSIM3vsat = value->rValue; + mod->BSIM3vsatGiven = TRUE; + break; + case BSIM3_MOD_A0: + mod->BSIM3a0 = value->rValue; + mod->BSIM3a0Given = TRUE; + break; + + case BSIM3_MOD_AGS: + mod->BSIM3ags= value->rValue; + mod->BSIM3agsGiven = TRUE; + break; + + case BSIM3_MOD_A1: + mod->BSIM3a1 = value->rValue; + mod->BSIM3a1Given = TRUE; + break; + case BSIM3_MOD_A2: + mod->BSIM3a2 = value->rValue; + mod->BSIM3a2Given = TRUE; + break; + case BSIM3_MOD_AT: + mod->BSIM3at = value->rValue; + mod->BSIM3atGiven = TRUE; + break; + case BSIM3_MOD_KETA: + mod->BSIM3keta = value->rValue; + mod->BSIM3ketaGiven = TRUE; + break; + case BSIM3_MOD_NSUB: + mod->BSIM3nsub = value->rValue; + mod->BSIM3nsubGiven = TRUE; + break; + case BSIM3_MOD_NPEAK: + mod->BSIM3npeak = value->rValue; + mod->BSIM3npeakGiven = TRUE; + 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; + break; + case BSIM3_MOD_GAMMA1: + mod->BSIM3gamma1 = value->rValue; + mod->BSIM3gamma1Given = TRUE; + break; + case BSIM3_MOD_GAMMA2: + mod->BSIM3gamma2 = value->rValue; + mod->BSIM3gamma2Given = TRUE; + break; + case BSIM3_MOD_VBX: + mod->BSIM3vbx = value->rValue; + mod->BSIM3vbxGiven = TRUE; + break; + case BSIM3_MOD_VBM: + mod->BSIM3vbm = value->rValue; + mod->BSIM3vbmGiven = TRUE; + break; + case BSIM3_MOD_XT: + mod->BSIM3xt = value->rValue; + mod->BSIM3xtGiven = TRUE; + break; + case BSIM3_MOD_K1: + mod->BSIM3k1 = value->rValue; + mod->BSIM3k1Given = TRUE; + break; + case BSIM3_MOD_KT1: + mod->BSIM3kt1 = value->rValue; + mod->BSIM3kt1Given = TRUE; + break; + case BSIM3_MOD_KT1L: + mod->BSIM3kt1l = value->rValue; + mod->BSIM3kt1lGiven = TRUE; + break; + case BSIM3_MOD_KT2: + mod->BSIM3kt2 = value->rValue; + mod->BSIM3kt2Given = TRUE; + break; + case BSIM3_MOD_K2: + mod->BSIM3k2 = value->rValue; + mod->BSIM3k2Given = TRUE; + break; + case BSIM3_MOD_K3: + mod->BSIM3k3 = value->rValue; + mod->BSIM3k3Given = TRUE; + break; + case BSIM3_MOD_K3B: + mod->BSIM3k3b = value->rValue; + mod->BSIM3k3bGiven = TRUE; + break; + case BSIM3_MOD_NLX: + mod->BSIM3nlx = value->rValue; + mod->BSIM3nlxGiven = TRUE; + break; + case BSIM3_MOD_W0: + mod->BSIM3w0 = value->rValue; + mod->BSIM3w0Given = TRUE; + break; + case BSIM3_MOD_DVT0: + mod->BSIM3dvt0 = value->rValue; + mod->BSIM3dvt0Given = TRUE; + break; + case BSIM3_MOD_DVT1: + mod->BSIM3dvt1 = value->rValue; + mod->BSIM3dvt1Given = TRUE; + break; + case BSIM3_MOD_DVT2: + mod->BSIM3dvt2 = value->rValue; + mod->BSIM3dvt2Given = TRUE; + break; + case BSIM3_MOD_DVT0W: + mod->BSIM3dvt0w = value->rValue; + mod->BSIM3dvt0wGiven = TRUE; + break; + case BSIM3_MOD_DVT1W: + mod->BSIM3dvt1w = value->rValue; + mod->BSIM3dvt1wGiven = TRUE; + break; + case BSIM3_MOD_DVT2W: + mod->BSIM3dvt2w = value->rValue; + mod->BSIM3dvt2wGiven = TRUE; + break; + case BSIM3_MOD_DROUT: + mod->BSIM3drout = value->rValue; + mod->BSIM3droutGiven = TRUE; + break; + case BSIM3_MOD_DSUB: + mod->BSIM3dsub = value->rValue; + mod->BSIM3dsubGiven = TRUE; + break; + case BSIM3_MOD_VTH0: + mod->BSIM3vth0 = value->rValue; + mod->BSIM3vth0Given = TRUE; + break; + case BSIM3_MOD_UA: + mod->BSIM3ua = value->rValue; + mod->BSIM3uaGiven = TRUE; + break; + case BSIM3_MOD_UA1: + mod->BSIM3ua1 = value->rValue; + mod->BSIM3ua1Given = TRUE; + break; + case BSIM3_MOD_UB: + mod->BSIM3ub = value->rValue; + mod->BSIM3ubGiven = TRUE; + break; + case BSIM3_MOD_UB1: + mod->BSIM3ub1 = value->rValue; + mod->BSIM3ub1Given = TRUE; + break; + case BSIM3_MOD_UC: + mod->BSIM3uc = value->rValue; + mod->BSIM3ucGiven = TRUE; + break; + case BSIM3_MOD_UC1: + mod->BSIM3uc1 = value->rValue; + mod->BSIM3uc1Given = TRUE; + break; + case BSIM3_MOD_U0 : + mod->BSIM3u0 = value->rValue; + mod->BSIM3u0Given = TRUE; + break; + case BSIM3_MOD_UTE : + mod->BSIM3ute = value->rValue; + mod->BSIM3uteGiven = TRUE; + break; + case BSIM3_MOD_VOFF: + mod->BSIM3voff = value->rValue; + mod->BSIM3voffGiven = TRUE; + break; + case BSIM3_MOD_DELTA : + mod->BSIM3delta = value->rValue; + mod->BSIM3deltaGiven = TRUE; + break; + case BSIM3_MOD_RDSW: + mod->BSIM3rdsw = value->rValue; + mod->BSIM3rdswGiven = TRUE; + break; + case BSIM3_MOD_PRWG: + mod->BSIM3prwg = value->rValue; + mod->BSIM3prwgGiven = TRUE; + break; + case BSIM3_MOD_PRWB: + mod->BSIM3prwb = value->rValue; + mod->BSIM3prwbGiven = TRUE; + break; + case BSIM3_MOD_PRT: + mod->BSIM3prt = value->rValue; + mod->BSIM3prtGiven = TRUE; + break; + case BSIM3_MOD_ETA0: + mod->BSIM3eta0 = value->rValue; + mod->BSIM3eta0Given = TRUE; + break; + case BSIM3_MOD_ETAB: + mod->BSIM3etab = value->rValue; + mod->BSIM3etabGiven = TRUE; + break; + case BSIM3_MOD_PCLM: + mod->BSIM3pclm = value->rValue; + mod->BSIM3pclmGiven = TRUE; + break; + case BSIM3_MOD_PDIBL1: + mod->BSIM3pdibl1 = value->rValue; + mod->BSIM3pdibl1Given = TRUE; + break; + case BSIM3_MOD_PDIBL2: + mod->BSIM3pdibl2 = value->rValue; + mod->BSIM3pdibl2Given = TRUE; + break; + case BSIM3_MOD_PDIBLB: + mod->BSIM3pdiblb = value->rValue; + mod->BSIM3pdiblbGiven = TRUE; + break; + case BSIM3_MOD_PSCBE1: + mod->BSIM3pscbe1 = value->rValue; + mod->BSIM3pscbe1Given = TRUE; + break; + case BSIM3_MOD_PSCBE2: + mod->BSIM3pscbe2 = value->rValue; + mod->BSIM3pscbe2Given = TRUE; + break; + case BSIM3_MOD_PVAG: + mod->BSIM3pvag = value->rValue; + mod->BSIM3pvagGiven = TRUE; + break; + case BSIM3_MOD_WR : + mod->BSIM3wr = value->rValue; + mod->BSIM3wrGiven = TRUE; + break; + case BSIM3_MOD_DWG : + mod->BSIM3dwg = value->rValue; + mod->BSIM3dwgGiven = TRUE; + break; + case BSIM3_MOD_DWB : + mod->BSIM3dwb = value->rValue; + mod->BSIM3dwbGiven = TRUE; + break; + case BSIM3_MOD_B0 : + mod->BSIM3b0 = value->rValue; + mod->BSIM3b0Given = TRUE; + break; + case BSIM3_MOD_B1 : + mod->BSIM3b1 = value->rValue; + mod->BSIM3b1Given = TRUE; + break; + case BSIM3_MOD_ALPHA0 : + mod->BSIM3alpha0 = value->rValue; + mod->BSIM3alpha0Given = TRUE; + break; + case BSIM3_MOD_ALPHA1 : + mod->BSIM3alpha1 = value->rValue; + mod->BSIM3alpha1Given = TRUE; + break; + case BSIM3_MOD_BETA0 : + mod->BSIM3beta0 = value->rValue; + mod->BSIM3beta0Given = TRUE; + break; + case BSIM3_MOD_IJTH : + mod->BSIM3ijth = value->rValue; + mod->BSIM3ijthGiven = TRUE; + break; + case BSIM3_MOD_VFB : + mod->BSIM3vfb = value->rValue; + mod->BSIM3vfbGiven = TRUE; + break; + + case BSIM3_MOD_ELM : + mod->BSIM3elm = value->rValue; + mod->BSIM3elmGiven = TRUE; + break; + case BSIM3_MOD_CGSL : + mod->BSIM3cgsl = value->rValue; + mod->BSIM3cgslGiven = TRUE; + break; + case BSIM3_MOD_CGDL : + mod->BSIM3cgdl = value->rValue; + mod->BSIM3cgdlGiven = TRUE; + break; + case BSIM3_MOD_CKAPPA : + mod->BSIM3ckappa = value->rValue; + mod->BSIM3ckappaGiven = TRUE; + break; + case BSIM3_MOD_CF : + mod->BSIM3cf = value->rValue; + mod->BSIM3cfGiven = TRUE; + break; + case BSIM3_MOD_CLC : + mod->BSIM3clc = value->rValue; + mod->BSIM3clcGiven = TRUE; + break; + case BSIM3_MOD_CLE : + mod->BSIM3cle = value->rValue; + mod->BSIM3cleGiven = TRUE; + break; + case BSIM3_MOD_DWC : + mod->BSIM3dwc = value->rValue; + mod->BSIM3dwcGiven = TRUE; + break; + case BSIM3_MOD_DLC : + mod->BSIM3dlc = value->rValue; + mod->BSIM3dlcGiven = TRUE; + break; + case BSIM3_MOD_VFBCV : + mod->BSIM3vfbcv = value->rValue; + mod->BSIM3vfbcvGiven = TRUE; + break; + case BSIM3_MOD_ACDE : + mod->BSIM3acde = value->rValue; + mod->BSIM3acdeGiven = TRUE; + break; + case BSIM3_MOD_MOIN : + mod->BSIM3moin = value->rValue; + mod->BSIM3moinGiven = TRUE; + break; + case BSIM3_MOD_NOFF : + mod->BSIM3noff = value->rValue; + mod->BSIM3noffGiven = TRUE; + break; + case BSIM3_MOD_VOFFCV : + mod->BSIM3voffcv = value->rValue; + mod->BSIM3voffcvGiven = TRUE; + break; + case BSIM3_MOD_TCJ : + mod->BSIM3tcj = value->rValue; + mod->BSIM3tcjGiven = TRUE; + break; + case BSIM3_MOD_TPB : + mod->BSIM3tpb = value->rValue; + mod->BSIM3tpbGiven = TRUE; + break; + case BSIM3_MOD_TCJSW : + mod->BSIM3tcjsw = value->rValue; + mod->BSIM3tcjswGiven = TRUE; + break; + case BSIM3_MOD_TPBSW : + mod->BSIM3tpbsw = value->rValue; + mod->BSIM3tpbswGiven = TRUE; + break; + case BSIM3_MOD_TCJSWG : + mod->BSIM3tcjswg = value->rValue; + mod->BSIM3tcjswgGiven = TRUE; + break; + case BSIM3_MOD_TPBSWG : + mod->BSIM3tpbswg = value->rValue; + mod->BSIM3tpbswgGiven = TRUE; + break; + + /* 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; + break; + + + case BSIM3_MOD_LCDSCB : + mod->BSIM3lcdscb = value->rValue; + mod->BSIM3lcdscbGiven = TRUE; + break; + case BSIM3_MOD_LCDSCD : + mod->BSIM3lcdscd = value->rValue; + mod->BSIM3lcdscdGiven = TRUE; + break; + case BSIM3_MOD_LCIT : + mod->BSIM3lcit = value->rValue; + mod->BSIM3lcitGiven = TRUE; + break; + case BSIM3_MOD_LNFACTOR : + mod->BSIM3lnfactor = value->rValue; + mod->BSIM3lnfactorGiven = TRUE; + break; + case BSIM3_MOD_LXJ: + mod->BSIM3lxj = value->rValue; + mod->BSIM3lxjGiven = TRUE; + break; + case BSIM3_MOD_LVSAT: + mod->BSIM3lvsat = value->rValue; + mod->BSIM3lvsatGiven = TRUE; + break; + + + case BSIM3_MOD_LA0: + mod->BSIM3la0 = value->rValue; + mod->BSIM3la0Given = TRUE; + break; + case BSIM3_MOD_LAGS: + mod->BSIM3lags = value->rValue; + mod->BSIM3lagsGiven = TRUE; + break; + case BSIM3_MOD_LA1: + mod->BSIM3la1 = value->rValue; + mod->BSIM3la1Given = TRUE; + break; + case BSIM3_MOD_LA2: + mod->BSIM3la2 = value->rValue; + mod->BSIM3la2Given = TRUE; + break; + case BSIM3_MOD_LAT: + mod->BSIM3lat = value->rValue; + mod->BSIM3latGiven = TRUE; + break; + case BSIM3_MOD_LKETA: + mod->BSIM3lketa = value->rValue; + mod->BSIM3lketaGiven = TRUE; + break; + case BSIM3_MOD_LNSUB: + mod->BSIM3lnsub = value->rValue; + mod->BSIM3lnsubGiven = TRUE; + break; + case BSIM3_MOD_LNPEAK: + mod->BSIM3lnpeak = value->rValue; + mod->BSIM3lnpeakGiven = TRUE; + 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; + break; + case BSIM3_MOD_LGAMMA1: + mod->BSIM3lgamma1 = value->rValue; + mod->BSIM3lgamma1Given = TRUE; + break; + case BSIM3_MOD_LGAMMA2: + mod->BSIM3lgamma2 = value->rValue; + mod->BSIM3lgamma2Given = TRUE; + break; + case BSIM3_MOD_LVBX: + mod->BSIM3lvbx = value->rValue; + mod->BSIM3lvbxGiven = TRUE; + break; + case BSIM3_MOD_LVBM: + mod->BSIM3lvbm = value->rValue; + mod->BSIM3lvbmGiven = TRUE; + break; + case BSIM3_MOD_LXT: + mod->BSIM3lxt = value->rValue; + mod->BSIM3lxtGiven = TRUE; + break; + case BSIM3_MOD_LK1: + mod->BSIM3lk1 = value->rValue; + mod->BSIM3lk1Given = TRUE; + break; + case BSIM3_MOD_LKT1: + mod->BSIM3lkt1 = value->rValue; + mod->BSIM3lkt1Given = TRUE; + break; + case BSIM3_MOD_LKT1L: + mod->BSIM3lkt1l = value->rValue; + mod->BSIM3lkt1lGiven = TRUE; + break; + case BSIM3_MOD_LKT2: + mod->BSIM3lkt2 = value->rValue; + mod->BSIM3lkt2Given = TRUE; + break; + case BSIM3_MOD_LK2: + mod->BSIM3lk2 = value->rValue; + mod->BSIM3lk2Given = TRUE; + break; + case BSIM3_MOD_LK3: + mod->BSIM3lk3 = value->rValue; + mod->BSIM3lk3Given = TRUE; + break; + case BSIM3_MOD_LK3B: + mod->BSIM3lk3b = value->rValue; + mod->BSIM3lk3bGiven = TRUE; + break; + case BSIM3_MOD_LNLX: + mod->BSIM3lnlx = value->rValue; + mod->BSIM3lnlxGiven = TRUE; + break; + case BSIM3_MOD_LW0: + mod->BSIM3lw0 = value->rValue; + mod->BSIM3lw0Given = TRUE; + break; + case BSIM3_MOD_LDVT0: + mod->BSIM3ldvt0 = value->rValue; + mod->BSIM3ldvt0Given = TRUE; + break; + case BSIM3_MOD_LDVT1: + mod->BSIM3ldvt1 = value->rValue; + mod->BSIM3ldvt1Given = TRUE; + break; + case BSIM3_MOD_LDVT2: + mod->BSIM3ldvt2 = value->rValue; + mod->BSIM3ldvt2Given = TRUE; + break; + case BSIM3_MOD_LDVT0W: + mod->BSIM3ldvt0w = value->rValue; + mod->BSIM3ldvt0wGiven = TRUE; + break; + case BSIM3_MOD_LDVT1W: + mod->BSIM3ldvt1w = value->rValue; + mod->BSIM3ldvt1wGiven = TRUE; + break; + case BSIM3_MOD_LDVT2W: + mod->BSIM3ldvt2w = value->rValue; + mod->BSIM3ldvt2wGiven = TRUE; + break; + case BSIM3_MOD_LDROUT: + mod->BSIM3ldrout = value->rValue; + mod->BSIM3ldroutGiven = TRUE; + break; + case BSIM3_MOD_LDSUB: + mod->BSIM3ldsub = value->rValue; + mod->BSIM3ldsubGiven = TRUE; + break; + case BSIM3_MOD_LVTH0: + mod->BSIM3lvth0 = value->rValue; + mod->BSIM3lvth0Given = TRUE; + break; + case BSIM3_MOD_LUA: + mod->BSIM3lua = value->rValue; + mod->BSIM3luaGiven = TRUE; + break; + case BSIM3_MOD_LUA1: + mod->BSIM3lua1 = value->rValue; + mod->BSIM3lua1Given = TRUE; + break; + case BSIM3_MOD_LUB: + mod->BSIM3lub = value->rValue; + mod->BSIM3lubGiven = TRUE; + break; + case BSIM3_MOD_LUB1: + mod->BSIM3lub1 = value->rValue; + mod->BSIM3lub1Given = TRUE; + break; + case BSIM3_MOD_LUC: + mod->BSIM3luc = value->rValue; + mod->BSIM3lucGiven = TRUE; + break; + case BSIM3_MOD_LUC1: + mod->BSIM3luc1 = value->rValue; + mod->BSIM3luc1Given = TRUE; + break; + case BSIM3_MOD_LU0 : + mod->BSIM3lu0 = value->rValue; + mod->BSIM3lu0Given = TRUE; + break; + case BSIM3_MOD_LUTE : + mod->BSIM3lute = value->rValue; + mod->BSIM3luteGiven = TRUE; + break; + case BSIM3_MOD_LVOFF: + mod->BSIM3lvoff = value->rValue; + mod->BSIM3lvoffGiven = TRUE; + break; + case BSIM3_MOD_LDELTA : + mod->BSIM3ldelta = value->rValue; + mod->BSIM3ldeltaGiven = TRUE; + break; + case BSIM3_MOD_LRDSW: + mod->BSIM3lrdsw = value->rValue; + mod->BSIM3lrdswGiven = TRUE; + break; + case BSIM3_MOD_LPRWB: + mod->BSIM3lprwb = value->rValue; + mod->BSIM3lprwbGiven = TRUE; + break; + case BSIM3_MOD_LPRWG: + mod->BSIM3lprwg = value->rValue; + mod->BSIM3lprwgGiven = TRUE; + break; + case BSIM3_MOD_LPRT: + mod->BSIM3lprt = value->rValue; + mod->BSIM3lprtGiven = TRUE; + break; + case BSIM3_MOD_LETA0: + mod->BSIM3leta0 = value->rValue; + mod->BSIM3leta0Given = TRUE; + break; + case BSIM3_MOD_LETAB: + mod->BSIM3letab = value->rValue; + mod->BSIM3letabGiven = TRUE; + break; + case BSIM3_MOD_LPCLM: + mod->BSIM3lpclm = value->rValue; + mod->BSIM3lpclmGiven = TRUE; + break; + case BSIM3_MOD_LPDIBL1: + mod->BSIM3lpdibl1 = value->rValue; + mod->BSIM3lpdibl1Given = TRUE; + break; + case BSIM3_MOD_LPDIBL2: + mod->BSIM3lpdibl2 = value->rValue; + mod->BSIM3lpdibl2Given = TRUE; + break; + case BSIM3_MOD_LPDIBLB: + mod->BSIM3lpdiblb = value->rValue; + mod->BSIM3lpdiblbGiven = TRUE; + break; + case BSIM3_MOD_LPSCBE1: + mod->BSIM3lpscbe1 = value->rValue; + mod->BSIM3lpscbe1Given = TRUE; + break; + case BSIM3_MOD_LPSCBE2: + mod->BSIM3lpscbe2 = value->rValue; + mod->BSIM3lpscbe2Given = TRUE; + break; + case BSIM3_MOD_LPVAG: + mod->BSIM3lpvag = value->rValue; + mod->BSIM3lpvagGiven = TRUE; + break; + case BSIM3_MOD_LWR : + mod->BSIM3lwr = value->rValue; + mod->BSIM3lwrGiven = TRUE; + break; + case BSIM3_MOD_LDWG : + mod->BSIM3ldwg = value->rValue; + mod->BSIM3ldwgGiven = TRUE; + break; + case BSIM3_MOD_LDWB : + mod->BSIM3ldwb = value->rValue; + mod->BSIM3ldwbGiven = TRUE; + break; + case BSIM3_MOD_LB0 : + mod->BSIM3lb0 = value->rValue; + mod->BSIM3lb0Given = TRUE; + break; + case BSIM3_MOD_LB1 : + mod->BSIM3lb1 = value->rValue; + mod->BSIM3lb1Given = TRUE; + break; + case BSIM3_MOD_LALPHA0 : + mod->BSIM3lalpha0 = value->rValue; + mod->BSIM3lalpha0Given = TRUE; + break; + case BSIM3_MOD_LALPHA1 : + mod->BSIM3lalpha1 = value->rValue; + mod->BSIM3lalpha1Given = TRUE; + break; + case BSIM3_MOD_LBETA0 : + mod->BSIM3lbeta0 = value->rValue; + mod->BSIM3lbeta0Given = TRUE; + break; + case BSIM3_MOD_LVFB : + mod->BSIM3lvfb = value->rValue; + mod->BSIM3lvfbGiven = TRUE; + break; + + case BSIM3_MOD_LELM : + mod->BSIM3lelm = value->rValue; + mod->BSIM3lelmGiven = TRUE; + break; + case BSIM3_MOD_LCGSL : + mod->BSIM3lcgsl = value->rValue; + mod->BSIM3lcgslGiven = TRUE; + break; + case BSIM3_MOD_LCGDL : + mod->BSIM3lcgdl = value->rValue; + mod->BSIM3lcgdlGiven = TRUE; + break; + case BSIM3_MOD_LCKAPPA : + mod->BSIM3lckappa = value->rValue; + mod->BSIM3lckappaGiven = TRUE; + break; + case BSIM3_MOD_LCF : + mod->BSIM3lcf = value->rValue; + mod->BSIM3lcfGiven = TRUE; + break; + case BSIM3_MOD_LCLC : + mod->BSIM3lclc = value->rValue; + mod->BSIM3lclcGiven = TRUE; + break; + case BSIM3_MOD_LCLE : + mod->BSIM3lcle = value->rValue; + mod->BSIM3lcleGiven = TRUE; + break; + case BSIM3_MOD_LVFBCV : + mod->BSIM3lvfbcv = value->rValue; + mod->BSIM3lvfbcvGiven = TRUE; + break; + case BSIM3_MOD_LACDE : + mod->BSIM3lacde = value->rValue; + mod->BSIM3lacdeGiven = TRUE; + break; + case BSIM3_MOD_LMOIN : + mod->BSIM3lmoin = value->rValue; + mod->BSIM3lmoinGiven = TRUE; + break; + case BSIM3_MOD_LNOFF : + mod->BSIM3lnoff = value->rValue; + mod->BSIM3lnoffGiven = TRUE; + break; + case BSIM3_MOD_LVOFFCV : + mod->BSIM3lvoffcv = value->rValue; + mod->BSIM3lvoffcvGiven = TRUE; + break; + + /* Width dependence */ + case BSIM3_MOD_WCDSC : + mod->BSIM3wcdsc = value->rValue; + mod->BSIM3wcdscGiven = TRUE; + break; + + + case BSIM3_MOD_WCDSCB : + mod->BSIM3wcdscb = value->rValue; + mod->BSIM3wcdscbGiven = TRUE; + break; + case BSIM3_MOD_WCDSCD : + mod->BSIM3wcdscd = value->rValue; + mod->BSIM3wcdscdGiven = TRUE; + break; + case BSIM3_MOD_WCIT : + mod->BSIM3wcit = value->rValue; + mod->BSIM3wcitGiven = TRUE; + break; + case BSIM3_MOD_WNFACTOR : + mod->BSIM3wnfactor = value->rValue; + mod->BSIM3wnfactorGiven = TRUE; + break; + case BSIM3_MOD_WXJ: + mod->BSIM3wxj = value->rValue; + mod->BSIM3wxjGiven = TRUE; + break; + case BSIM3_MOD_WVSAT: + mod->BSIM3wvsat = value->rValue; + mod->BSIM3wvsatGiven = TRUE; + break; + + + case BSIM3_MOD_WA0: + mod->BSIM3wa0 = value->rValue; + mod->BSIM3wa0Given = TRUE; + break; + case BSIM3_MOD_WAGS: + mod->BSIM3wags = value->rValue; + mod->BSIM3wagsGiven = TRUE; + break; + case BSIM3_MOD_WA1: + mod->BSIM3wa1 = value->rValue; + mod->BSIM3wa1Given = TRUE; + break; + case BSIM3_MOD_WA2: + mod->BSIM3wa2 = value->rValue; + mod->BSIM3wa2Given = TRUE; + break; + case BSIM3_MOD_WAT: + mod->BSIM3wat = value->rValue; + mod->BSIM3watGiven = TRUE; + break; + case BSIM3_MOD_WKETA: + mod->BSIM3wketa = value->rValue; + mod->BSIM3wketaGiven = TRUE; + break; + case BSIM3_MOD_WNSUB: + mod->BSIM3wnsub = value->rValue; + mod->BSIM3wnsubGiven = TRUE; + break; + case BSIM3_MOD_WNPEAK: + mod->BSIM3wnpeak = value->rValue; + mod->BSIM3wnpeakGiven = TRUE; + 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; + break; + case BSIM3_MOD_WGAMMA1: + mod->BSIM3wgamma1 = value->rValue; + mod->BSIM3wgamma1Given = TRUE; + break; + case BSIM3_MOD_WGAMMA2: + mod->BSIM3wgamma2 = value->rValue; + mod->BSIM3wgamma2Given = TRUE; + break; + case BSIM3_MOD_WVBX: + mod->BSIM3wvbx = value->rValue; + mod->BSIM3wvbxGiven = TRUE; + break; + case BSIM3_MOD_WVBM: + mod->BSIM3wvbm = value->rValue; + mod->BSIM3wvbmGiven = TRUE; + break; + case BSIM3_MOD_WXT: + mod->BSIM3wxt = value->rValue; + mod->BSIM3wxtGiven = TRUE; + break; + case BSIM3_MOD_WK1: + mod->BSIM3wk1 = value->rValue; + mod->BSIM3wk1Given = TRUE; + break; + case BSIM3_MOD_WKT1: + mod->BSIM3wkt1 = value->rValue; + mod->BSIM3wkt1Given = TRUE; + break; + case BSIM3_MOD_WKT1L: + mod->BSIM3wkt1l = value->rValue; + mod->BSIM3wkt1lGiven = TRUE; + break; + case BSIM3_MOD_WKT2: + mod->BSIM3wkt2 = value->rValue; + mod->BSIM3wkt2Given = TRUE; + break; + case BSIM3_MOD_WK2: + mod->BSIM3wk2 = value->rValue; + mod->BSIM3wk2Given = TRUE; + break; + case BSIM3_MOD_WK3: + mod->BSIM3wk3 = value->rValue; + mod->BSIM3wk3Given = TRUE; + break; + case BSIM3_MOD_WK3B: + mod->BSIM3wk3b = value->rValue; + mod->BSIM3wk3bGiven = TRUE; + break; + case BSIM3_MOD_WNLX: + mod->BSIM3wnlx = value->rValue; + mod->BSIM3wnlxGiven = TRUE; + break; + case BSIM3_MOD_WW0: + mod->BSIM3ww0 = value->rValue; + mod->BSIM3ww0Given = TRUE; + break; + case BSIM3_MOD_WDVT0: + mod->BSIM3wdvt0 = value->rValue; + mod->BSIM3wdvt0Given = TRUE; + break; + case BSIM3_MOD_WDVT1: + mod->BSIM3wdvt1 = value->rValue; + mod->BSIM3wdvt1Given = TRUE; + break; + case BSIM3_MOD_WDVT2: + mod->BSIM3wdvt2 = value->rValue; + mod->BSIM3wdvt2Given = TRUE; + break; + case BSIM3_MOD_WDVT0W: + mod->BSIM3wdvt0w = value->rValue; + mod->BSIM3wdvt0wGiven = TRUE; + break; + case BSIM3_MOD_WDVT1W: + mod->BSIM3wdvt1w = value->rValue; + mod->BSIM3wdvt1wGiven = TRUE; + break; + case BSIM3_MOD_WDVT2W: + mod->BSIM3wdvt2w = value->rValue; + mod->BSIM3wdvt2wGiven = TRUE; + break; + case BSIM3_MOD_WDROUT: + mod->BSIM3wdrout = value->rValue; + mod->BSIM3wdroutGiven = TRUE; + break; + case BSIM3_MOD_WDSUB: + mod->BSIM3wdsub = value->rValue; + mod->BSIM3wdsubGiven = TRUE; + break; + case BSIM3_MOD_WVTH0: + mod->BSIM3wvth0 = value->rValue; + mod->BSIM3wvth0Given = TRUE; + break; + case BSIM3_MOD_WUA: + mod->BSIM3wua = value->rValue; + mod->BSIM3wuaGiven = TRUE; + break; + case BSIM3_MOD_WUA1: + mod->BSIM3wua1 = value->rValue; + mod->BSIM3wua1Given = TRUE; + break; + case BSIM3_MOD_WUB: + mod->BSIM3wub = value->rValue; + mod->BSIM3wubGiven = TRUE; + break; + case BSIM3_MOD_WUB1: + mod->BSIM3wub1 = value->rValue; + mod->BSIM3wub1Given = TRUE; + break; + case BSIM3_MOD_WUC: + mod->BSIM3wuc = value->rValue; + mod->BSIM3wucGiven = TRUE; + break; + case BSIM3_MOD_WUC1: + mod->BSIM3wuc1 = value->rValue; + mod->BSIM3wuc1Given = TRUE; + break; + case BSIM3_MOD_WU0 : + mod->BSIM3wu0 = value->rValue; + mod->BSIM3wu0Given = TRUE; + break; + case BSIM3_MOD_WUTE : + mod->BSIM3wute = value->rValue; + mod->BSIM3wuteGiven = TRUE; + break; + case BSIM3_MOD_WVOFF: + mod->BSIM3wvoff = value->rValue; + mod->BSIM3wvoffGiven = TRUE; + break; + case BSIM3_MOD_WDELTA : + mod->BSIM3wdelta = value->rValue; + mod->BSIM3wdeltaGiven = TRUE; + break; + case BSIM3_MOD_WRDSW: + mod->BSIM3wrdsw = value->rValue; + mod->BSIM3wrdswGiven = TRUE; + break; + case BSIM3_MOD_WPRWB: + mod->BSIM3wprwb = value->rValue; + mod->BSIM3wprwbGiven = TRUE; + break; + case BSIM3_MOD_WPRWG: + mod->BSIM3wprwg = value->rValue; + mod->BSIM3wprwgGiven = TRUE; + break; + case BSIM3_MOD_WPRT: + mod->BSIM3wprt = value->rValue; + mod->BSIM3wprtGiven = TRUE; + break; + case BSIM3_MOD_WETA0: + mod->BSIM3weta0 = value->rValue; + mod->BSIM3weta0Given = TRUE; + break; + case BSIM3_MOD_WETAB: + mod->BSIM3wetab = value->rValue; + mod->BSIM3wetabGiven = TRUE; + break; + case BSIM3_MOD_WPCLM: + mod->BSIM3wpclm = value->rValue; + mod->BSIM3wpclmGiven = TRUE; + break; + case BSIM3_MOD_WPDIBL1: + mod->BSIM3wpdibl1 = value->rValue; + mod->BSIM3wpdibl1Given = TRUE; + break; + case BSIM3_MOD_WPDIBL2: + mod->BSIM3wpdibl2 = value->rValue; + mod->BSIM3wpdibl2Given = TRUE; + break; + case BSIM3_MOD_WPDIBLB: + mod->BSIM3wpdiblb = value->rValue; + mod->BSIM3wpdiblbGiven = TRUE; + break; + case BSIM3_MOD_WPSCBE1: + mod->BSIM3wpscbe1 = value->rValue; + mod->BSIM3wpscbe1Given = TRUE; + break; + case BSIM3_MOD_WPSCBE2: + mod->BSIM3wpscbe2 = value->rValue; + mod->BSIM3wpscbe2Given = TRUE; + break; + case BSIM3_MOD_WPVAG: + mod->BSIM3wpvag = value->rValue; + mod->BSIM3wpvagGiven = TRUE; + break; + case BSIM3_MOD_WWR : + mod->BSIM3wwr = value->rValue; + mod->BSIM3wwrGiven = TRUE; + break; + case BSIM3_MOD_WDWG : + mod->BSIM3wdwg = value->rValue; + mod->BSIM3wdwgGiven = TRUE; + break; + case BSIM3_MOD_WDWB : + mod->BSIM3wdwb = value->rValue; + mod->BSIM3wdwbGiven = TRUE; + break; + case BSIM3_MOD_WB0 : + mod->BSIM3wb0 = value->rValue; + mod->BSIM3wb0Given = TRUE; + break; + case BSIM3_MOD_WB1 : + mod->BSIM3wb1 = value->rValue; + mod->BSIM3wb1Given = TRUE; + break; + case BSIM3_MOD_WALPHA0 : + mod->BSIM3walpha0 = value->rValue; + mod->BSIM3walpha0Given = TRUE; + break; + case BSIM3_MOD_WALPHA1 : + mod->BSIM3walpha1 = value->rValue; + mod->BSIM3walpha1Given = TRUE; + break; + case BSIM3_MOD_WBETA0 : + mod->BSIM3wbeta0 = value->rValue; + mod->BSIM3wbeta0Given = TRUE; + break; + case BSIM3_MOD_WVFB : + mod->BSIM3wvfb = value->rValue; + mod->BSIM3wvfbGiven = TRUE; + break; + + case BSIM3_MOD_WELM : + mod->BSIM3welm = value->rValue; + mod->BSIM3welmGiven = TRUE; + break; + case BSIM3_MOD_WCGSL : + mod->BSIM3wcgsl = value->rValue; + mod->BSIM3wcgslGiven = TRUE; + break; + case BSIM3_MOD_WCGDL : + mod->BSIM3wcgdl = value->rValue; + mod->BSIM3wcgdlGiven = TRUE; + break; + case BSIM3_MOD_WCKAPPA : + mod->BSIM3wckappa = value->rValue; + mod->BSIM3wckappaGiven = TRUE; + break; + case BSIM3_MOD_WCF : + mod->BSIM3wcf = value->rValue; + mod->BSIM3wcfGiven = TRUE; + break; + case BSIM3_MOD_WCLC : + mod->BSIM3wclc = value->rValue; + mod->BSIM3wclcGiven = TRUE; + break; + case BSIM3_MOD_WCLE : + mod->BSIM3wcle = value->rValue; + mod->BSIM3wcleGiven = TRUE; + break; + case BSIM3_MOD_WVFBCV : + mod->BSIM3wvfbcv = value->rValue; + mod->BSIM3wvfbcvGiven = TRUE; + break; + case BSIM3_MOD_WACDE : + mod->BSIM3wacde = value->rValue; + mod->BSIM3wacdeGiven = TRUE; + break; + case BSIM3_MOD_WMOIN : + mod->BSIM3wmoin = value->rValue; + mod->BSIM3wmoinGiven = TRUE; + break; + case BSIM3_MOD_WNOFF : + mod->BSIM3wnoff = value->rValue; + mod->BSIM3wnoffGiven = TRUE; + break; + case BSIM3_MOD_WVOFFCV : + mod->BSIM3wvoffcv = value->rValue; + mod->BSIM3wvoffcvGiven = TRUE; + break; + + /* Cross-term dependence */ + case BSIM3_MOD_PCDSC : + mod->BSIM3pcdsc = value->rValue; + mod->BSIM3pcdscGiven = TRUE; + break; + + + case BSIM3_MOD_PCDSCB : + mod->BSIM3pcdscb = value->rValue; + mod->BSIM3pcdscbGiven = TRUE; + break; + case BSIM3_MOD_PCDSCD : + mod->BSIM3pcdscd = value->rValue; + mod->BSIM3pcdscdGiven = TRUE; + break; + case BSIM3_MOD_PCIT : + mod->BSIM3pcit = value->rValue; + mod->BSIM3pcitGiven = TRUE; + break; + case BSIM3_MOD_PNFACTOR : + mod->BSIM3pnfactor = value->rValue; + mod->BSIM3pnfactorGiven = TRUE; + break; + case BSIM3_MOD_PXJ: + mod->BSIM3pxj = value->rValue; + mod->BSIM3pxjGiven = TRUE; + break; + case BSIM3_MOD_PVSAT: + mod->BSIM3pvsat = value->rValue; + mod->BSIM3pvsatGiven = TRUE; + break; + + + case BSIM3_MOD_PA0: + mod->BSIM3pa0 = value->rValue; + mod->BSIM3pa0Given = TRUE; + break; + case BSIM3_MOD_PAGS: + mod->BSIM3pags = value->rValue; + mod->BSIM3pagsGiven = TRUE; + break; + case BSIM3_MOD_PA1: + mod->BSIM3pa1 = value->rValue; + mod->BSIM3pa1Given = TRUE; + break; + case BSIM3_MOD_PA2: + mod->BSIM3pa2 = value->rValue; + mod->BSIM3pa2Given = TRUE; + break; + case BSIM3_MOD_PAT: + mod->BSIM3pat = value->rValue; + mod->BSIM3patGiven = TRUE; + break; + case BSIM3_MOD_PKETA: + mod->BSIM3pketa = value->rValue; + mod->BSIM3pketaGiven = TRUE; + break; + case BSIM3_MOD_PNSUB: + mod->BSIM3pnsub = value->rValue; + mod->BSIM3pnsubGiven = TRUE; + break; + case BSIM3_MOD_PNPEAK: + mod->BSIM3pnpeak = value->rValue; + mod->BSIM3pnpeakGiven = TRUE; + 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; + break; + case BSIM3_MOD_PGAMMA1: + mod->BSIM3pgamma1 = value->rValue; + mod->BSIM3pgamma1Given = TRUE; + break; + case BSIM3_MOD_PGAMMA2: + mod->BSIM3pgamma2 = value->rValue; + mod->BSIM3pgamma2Given = TRUE; + break; + case BSIM3_MOD_PVBX: + mod->BSIM3pvbx = value->rValue; + mod->BSIM3pvbxGiven = TRUE; + break; + case BSIM3_MOD_PVBM: + mod->BSIM3pvbm = value->rValue; + mod->BSIM3pvbmGiven = TRUE; + break; + case BSIM3_MOD_PXT: + mod->BSIM3pxt = value->rValue; + mod->BSIM3pxtGiven = TRUE; + break; + case BSIM3_MOD_PK1: + mod->BSIM3pk1 = value->rValue; + mod->BSIM3pk1Given = TRUE; + break; + case BSIM3_MOD_PKT1: + mod->BSIM3pkt1 = value->rValue; + mod->BSIM3pkt1Given = TRUE; + break; + case BSIM3_MOD_PKT1L: + mod->BSIM3pkt1l = value->rValue; + mod->BSIM3pkt1lGiven = TRUE; + break; + case BSIM3_MOD_PKT2: + mod->BSIM3pkt2 = value->rValue; + mod->BSIM3pkt2Given = TRUE; + break; + case BSIM3_MOD_PK2: + mod->BSIM3pk2 = value->rValue; + mod->BSIM3pk2Given = TRUE; + break; + case BSIM3_MOD_PK3: + mod->BSIM3pk3 = value->rValue; + mod->BSIM3pk3Given = TRUE; + break; + case BSIM3_MOD_PK3B: + mod->BSIM3pk3b = value->rValue; + mod->BSIM3pk3bGiven = TRUE; + break; + case BSIM3_MOD_PNLX: + mod->BSIM3pnlx = value->rValue; + mod->BSIM3pnlxGiven = TRUE; + break; + case BSIM3_MOD_PW0: + mod->BSIM3pw0 = value->rValue; + mod->BSIM3pw0Given = TRUE; + break; + case BSIM3_MOD_PDVT0: + mod->BSIM3pdvt0 = value->rValue; + mod->BSIM3pdvt0Given = TRUE; + break; + case BSIM3_MOD_PDVT1: + mod->BSIM3pdvt1 = value->rValue; + mod->BSIM3pdvt1Given = TRUE; + break; + case BSIM3_MOD_PDVT2: + mod->BSIM3pdvt2 = value->rValue; + mod->BSIM3pdvt2Given = TRUE; + break; + case BSIM3_MOD_PDVT0W: + mod->BSIM3pdvt0w = value->rValue; + mod->BSIM3pdvt0wGiven = TRUE; + break; + case BSIM3_MOD_PDVT1W: + mod->BSIM3pdvt1w = value->rValue; + mod->BSIM3pdvt1wGiven = TRUE; + break; + case BSIM3_MOD_PDVT2W: + mod->BSIM3pdvt2w = value->rValue; + mod->BSIM3pdvt2wGiven = TRUE; + break; + case BSIM3_MOD_PDROUT: + mod->BSIM3pdrout = value->rValue; + mod->BSIM3pdroutGiven = TRUE; + break; + case BSIM3_MOD_PDSUB: + mod->BSIM3pdsub = value->rValue; + mod->BSIM3pdsubGiven = TRUE; + break; + case BSIM3_MOD_PVTH0: + mod->BSIM3pvth0 = value->rValue; + mod->BSIM3pvth0Given = TRUE; + break; + case BSIM3_MOD_PUA: + mod->BSIM3pua = value->rValue; + mod->BSIM3puaGiven = TRUE; + break; + case BSIM3_MOD_PUA1: + mod->BSIM3pua1 = value->rValue; + mod->BSIM3pua1Given = TRUE; + break; + case BSIM3_MOD_PUB: + mod->BSIM3pub = value->rValue; + mod->BSIM3pubGiven = TRUE; + break; + case BSIM3_MOD_PUB1: + mod->BSIM3pub1 = value->rValue; + mod->BSIM3pub1Given = TRUE; + break; + case BSIM3_MOD_PUC: + mod->BSIM3puc = value->rValue; + mod->BSIM3pucGiven = TRUE; + break; + case BSIM3_MOD_PUC1: + mod->BSIM3puc1 = value->rValue; + mod->BSIM3puc1Given = TRUE; + break; + case BSIM3_MOD_PU0 : + mod->BSIM3pu0 = value->rValue; + mod->BSIM3pu0Given = TRUE; + break; + case BSIM3_MOD_PUTE : + mod->BSIM3pute = value->rValue; + mod->BSIM3puteGiven = TRUE; + break; + case BSIM3_MOD_PVOFF: + mod->BSIM3pvoff = value->rValue; + mod->BSIM3pvoffGiven = TRUE; + break; + case BSIM3_MOD_PDELTA : + mod->BSIM3pdelta = value->rValue; + mod->BSIM3pdeltaGiven = TRUE; + break; + case BSIM3_MOD_PRDSW: + mod->BSIM3prdsw = value->rValue; + mod->BSIM3prdswGiven = TRUE; + break; + case BSIM3_MOD_PPRWB: + mod->BSIM3pprwb = value->rValue; + mod->BSIM3pprwbGiven = TRUE; + break; + case BSIM3_MOD_PPRWG: + mod->BSIM3pprwg = value->rValue; + mod->BSIM3pprwgGiven = TRUE; + break; + case BSIM3_MOD_PPRT: + mod->BSIM3pprt = value->rValue; + mod->BSIM3pprtGiven = TRUE; + break; + case BSIM3_MOD_PETA0: + mod->BSIM3peta0 = value->rValue; + mod->BSIM3peta0Given = TRUE; + break; + case BSIM3_MOD_PETAB: + mod->BSIM3petab = value->rValue; + mod->BSIM3petabGiven = TRUE; + break; + case BSIM3_MOD_PPCLM: + mod->BSIM3ppclm = value->rValue; + mod->BSIM3ppclmGiven = TRUE; + break; + case BSIM3_MOD_PPDIBL1: + mod->BSIM3ppdibl1 = value->rValue; + mod->BSIM3ppdibl1Given = TRUE; + break; + case BSIM3_MOD_PPDIBL2: + mod->BSIM3ppdibl2 = value->rValue; + mod->BSIM3ppdibl2Given = TRUE; + break; + case BSIM3_MOD_PPDIBLB: + mod->BSIM3ppdiblb = value->rValue; + mod->BSIM3ppdiblbGiven = TRUE; + break; + case BSIM3_MOD_PPSCBE1: + mod->BSIM3ppscbe1 = value->rValue; + mod->BSIM3ppscbe1Given = TRUE; + break; + case BSIM3_MOD_PPSCBE2: + mod->BSIM3ppscbe2 = value->rValue; + mod->BSIM3ppscbe2Given = TRUE; + break; + case BSIM3_MOD_PPVAG: + mod->BSIM3ppvag = value->rValue; + mod->BSIM3ppvagGiven = TRUE; + break; + case BSIM3_MOD_PWR : + mod->BSIM3pwr = value->rValue; + mod->BSIM3pwrGiven = TRUE; + break; + case BSIM3_MOD_PDWG : + mod->BSIM3pdwg = value->rValue; + mod->BSIM3pdwgGiven = TRUE; + break; + case BSIM3_MOD_PDWB : + mod->BSIM3pdwb = value->rValue; + mod->BSIM3pdwbGiven = TRUE; + break; + case BSIM3_MOD_PB0 : + mod->BSIM3pb0 = value->rValue; + mod->BSIM3pb0Given = TRUE; + break; + case BSIM3_MOD_PB1 : + mod->BSIM3pb1 = value->rValue; + mod->BSIM3pb1Given = TRUE; + break; + case BSIM3_MOD_PALPHA0 : + mod->BSIM3palpha0 = value->rValue; + mod->BSIM3palpha0Given = TRUE; + break; + case BSIM3_MOD_PALPHA1 : + mod->BSIM3palpha1 = value->rValue; + mod->BSIM3palpha1Given = TRUE; + break; + case BSIM3_MOD_PBETA0 : + mod->BSIM3pbeta0 = value->rValue; + mod->BSIM3pbeta0Given = TRUE; + break; + case BSIM3_MOD_PVFB : + mod->BSIM3pvfb = value->rValue; + mod->BSIM3pvfbGiven = TRUE; + break; + + case BSIM3_MOD_PELM : + mod->BSIM3pelm = value->rValue; + mod->BSIM3pelmGiven = TRUE; + break; + case BSIM3_MOD_PCGSL : + mod->BSIM3pcgsl = value->rValue; + mod->BSIM3pcgslGiven = TRUE; + break; + case BSIM3_MOD_PCGDL : + mod->BSIM3pcgdl = value->rValue; + mod->BSIM3pcgdlGiven = TRUE; + break; + case BSIM3_MOD_PCKAPPA : + mod->BSIM3pckappa = value->rValue; + mod->BSIM3pckappaGiven = TRUE; + break; + case BSIM3_MOD_PCF : + mod->BSIM3pcf = value->rValue; + mod->BSIM3pcfGiven = TRUE; + break; + case BSIM3_MOD_PCLC : + mod->BSIM3pclc = value->rValue; + mod->BSIM3pclcGiven = TRUE; + break; + case BSIM3_MOD_PCLE : + mod->BSIM3pcle = value->rValue; + mod->BSIM3pcleGiven = TRUE; + break; + case BSIM3_MOD_PVFBCV : + mod->BSIM3pvfbcv = value->rValue; + mod->BSIM3pvfbcvGiven = TRUE; + break; + case BSIM3_MOD_PACDE : + mod->BSIM3pacde = value->rValue; + mod->BSIM3pacdeGiven = TRUE; + break; + case BSIM3_MOD_PMOIN : + mod->BSIM3pmoin = value->rValue; + mod->BSIM3pmoinGiven = TRUE; + break; + case BSIM3_MOD_PNOFF : + mod->BSIM3pnoff = value->rValue; + mod->BSIM3pnoffGiven = TRUE; + break; + case BSIM3_MOD_PVOFFCV : + mod->BSIM3pvoffcv = value->rValue; + mod->BSIM3pvoffcvGiven = TRUE; + break; + + case BSIM3_MOD_TNOM : + mod->BSIM3tnom = value->rValue + CONSTCtoK; + mod->BSIM3tnomGiven = TRUE; + break; + case BSIM3_MOD_CGSO : + mod->BSIM3cgso = value->rValue; + mod->BSIM3cgsoGiven = TRUE; + break; + case BSIM3_MOD_CGDO : + mod->BSIM3cgdo = value->rValue; + mod->BSIM3cgdoGiven = TRUE; + break; + case BSIM3_MOD_CGBO : + mod->BSIM3cgbo = value->rValue; + mod->BSIM3cgboGiven = TRUE; + break; + case BSIM3_MOD_XPART : + mod->BSIM3xpart = value->rValue; + mod->BSIM3xpartGiven = TRUE; + break; + case BSIM3_MOD_RSH : + mod->BSIM3sheetResistance = value->rValue; + mod->BSIM3sheetResistanceGiven = TRUE; + break; + case BSIM3_MOD_JS : + mod->BSIM3jctSatCurDensity = value->rValue; + mod->BSIM3jctSatCurDensityGiven = TRUE; + break; + case BSIM3_MOD_JSW : + mod->BSIM3jctSidewallSatCurDensity = value->rValue; + mod->BSIM3jctSidewallSatCurDensityGiven = TRUE; + break; + case BSIM3_MOD_PB : + mod->BSIM3bulkJctPotential = value->rValue; + mod->BSIM3bulkJctPotentialGiven = TRUE; + break; + case BSIM3_MOD_MJ : + mod->BSIM3bulkJctBotGradingCoeff = value->rValue; + mod->BSIM3bulkJctBotGradingCoeffGiven = TRUE; + break; + case BSIM3_MOD_PBSW : + mod->BSIM3sidewallJctPotential = value->rValue; + mod->BSIM3sidewallJctPotentialGiven = TRUE; + break; + case BSIM3_MOD_MJSW : + mod->BSIM3bulkJctSideGradingCoeff = value->rValue; + mod->BSIM3bulkJctSideGradingCoeffGiven = TRUE; + break; + case BSIM3_MOD_CJ : + mod->BSIM3unitAreaJctCap = value->rValue; + mod->BSIM3unitAreaJctCapGiven = TRUE; + break; + case BSIM3_MOD_CJSW : + mod->BSIM3unitLengthSidewallJctCap = value->rValue; + mod->BSIM3unitLengthSidewallJctCapGiven = TRUE; + break; + case BSIM3_MOD_NJ : + mod->BSIM3jctEmissionCoeff = value->rValue; + mod->BSIM3jctEmissionCoeffGiven = TRUE; + break; + case BSIM3_MOD_PBSWG : + mod->BSIM3GatesidewallJctPotential = value->rValue; + mod->BSIM3GatesidewallJctPotentialGiven = TRUE; + break; + case BSIM3_MOD_MJSWG : + mod->BSIM3bulkJctGateSideGradingCoeff = value->rValue; + mod->BSIM3bulkJctGateSideGradingCoeffGiven = TRUE; + break; + case BSIM3_MOD_CJSWG : + mod->BSIM3unitLengthGateSidewallJctCap = value->rValue; + mod->BSIM3unitLengthGateSidewallJctCapGiven = TRUE; + break; + case BSIM3_MOD_XTI : + mod->BSIM3jctTempExponent = value->rValue; + mod->BSIM3jctTempExponentGiven = TRUE; + break; + case BSIM3_MOD_LINTNOI: + mod->BSIM3lintnoi = value->rValue; + mod->BSIM3lintnoiGiven = TRUE; + break; + case BSIM3_MOD_LINT : + mod->BSIM3Lint = value->rValue; + mod->BSIM3LintGiven = TRUE; + break; + case BSIM3_MOD_LL : + mod->BSIM3Ll = value->rValue; + mod->BSIM3LlGiven = TRUE; + break; + case BSIM3_MOD_LLC : + mod->BSIM3Llc = value->rValue; + mod->BSIM3LlcGiven = TRUE; + break; + case BSIM3_MOD_LLN : + mod->BSIM3Lln = value->rValue; + mod->BSIM3LlnGiven = TRUE; + break; + case BSIM3_MOD_LW : + mod->BSIM3Lw = value->rValue; + mod->BSIM3LwGiven = TRUE; + break; + case BSIM3_MOD_LWC : + mod->BSIM3Lwc = value->rValue; + mod->BSIM3LwcGiven = TRUE; + break; + case BSIM3_MOD_LWN : + mod->BSIM3Lwn = value->rValue; + mod->BSIM3LwnGiven = TRUE; + break; + case BSIM3_MOD_LWL : + mod->BSIM3Lwl = value->rValue; + mod->BSIM3LwlGiven = TRUE; + break; + case BSIM3_MOD_LWLC : + mod->BSIM3Lwlc = value->rValue; + mod->BSIM3LwlcGiven = TRUE; + break; + case BSIM3_MOD_LMIN : + mod->BSIM3Lmin = value->rValue; + mod->BSIM3LminGiven = TRUE; + break; + case BSIM3_MOD_LMAX : + mod->BSIM3Lmax = value->rValue; + mod->BSIM3LmaxGiven = TRUE; + break; + case BSIM3_MOD_WINT : + mod->BSIM3Wint = value->rValue; + mod->BSIM3WintGiven = TRUE; + break; + case BSIM3_MOD_WL : + mod->BSIM3Wl = value->rValue; + mod->BSIM3WlGiven = TRUE; + break; + case BSIM3_MOD_WLC : + mod->BSIM3Wlc = value->rValue; + mod->BSIM3WlcGiven = TRUE; + break; + case BSIM3_MOD_WLN : + mod->BSIM3Wln = value->rValue; + mod->BSIM3WlnGiven = TRUE; + break; + case BSIM3_MOD_WW : + mod->BSIM3Ww = value->rValue; + mod->BSIM3WwGiven = TRUE; + break; + case BSIM3_MOD_WWC : + mod->BSIM3Wwc = value->rValue; + mod->BSIM3WwcGiven = TRUE; + break; + case BSIM3_MOD_WWN : + mod->BSIM3Wwn = value->rValue; + mod->BSIM3WwnGiven = TRUE; + break; + case BSIM3_MOD_WWL : + mod->BSIM3Wwl = value->rValue; + mod->BSIM3WwlGiven = TRUE; + break; + case BSIM3_MOD_WWLC : + mod->BSIM3Wwlc = value->rValue; + mod->BSIM3WwlcGiven = TRUE; + break; + case BSIM3_MOD_WMIN : + mod->BSIM3Wmin = value->rValue; + mod->BSIM3WminGiven = TRUE; + break; + case BSIM3_MOD_WMAX : + mod->BSIM3Wmax = value->rValue; + 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; + break; + case BSIM3_MOD_NOIB : + mod->BSIM3oxideTrapDensityB = value->rValue; + mod->BSIM3oxideTrapDensityBGiven = TRUE; + break; + case BSIM3_MOD_NOIC : + mod->BSIM3oxideTrapDensityC = value->rValue; + mod->BSIM3oxideTrapDensityCGiven = TRUE; + break; + case BSIM3_MOD_EM : + mod->BSIM3em = value->rValue; + mod->BSIM3emGiven = TRUE; + break; + case BSIM3_MOD_EF : + mod->BSIM3ef = value->rValue; + mod->BSIM3efGiven = TRUE; + break; + case BSIM3_MOD_AF : + mod->BSIM3af = value->rValue; + mod->BSIM3afGiven = TRUE; + break; + case BSIM3_MOD_KF : + mod->BSIM3kf = value->rValue; + mod->BSIM3kfGiven = TRUE; + break; + + case BSIM3_MOD_VGS_MAX: + mod->BSIM3vgsMax = value->rValue; + mod->BSIM3vgsMaxGiven = TRUE; + break; + case BSIM3_MOD_VGD_MAX: + mod->BSIM3vgdMax = value->rValue; + mod->BSIM3vgdMaxGiven = TRUE; + break; + case BSIM3_MOD_VGB_MAX: + mod->BSIM3vgbMax = value->rValue; + mod->BSIM3vgbMaxGiven = TRUE; + break; + case BSIM3_MOD_VDS_MAX: + mod->BSIM3vdsMax = value->rValue; + mod->BSIM3vdsMaxGiven = TRUE; + break; + case BSIM3_MOD_VBS_MAX: + mod->BSIM3vbsMax = value->rValue; + mod->BSIM3vbsMaxGiven = TRUE; + break; + case BSIM3_MOD_VBD_MAX: + mod->BSIM3vbdMax = value->rValue; + mod->BSIM3vbdMaxGiven = TRUE; + break; + case BSIM3_MOD_VGSR_MAX: + mod->BSIM3vgsrMax = value->rValue; + mod->BSIM3vgsrMaxGiven = TRUE; + break; + case BSIM3_MOD_VGDR_MAX: + mod->BSIM3vgdrMax = value->rValue; + mod->BSIM3vgdrMaxGiven = TRUE; + break; + case BSIM3_MOD_VGBR_MAX: + mod->BSIM3vgbrMax = value->rValue; + mod->BSIM3vgbrMaxGiven = TRUE; + break; + case BSIM3_MOD_VBSR_MAX: + mod->BSIM3vbsrMax = value->rValue; + mod->BSIM3vbsrMaxGiven = TRUE; + break; + case BSIM3_MOD_VBDR_MAX: + mod->BSIM3vbdrMax = value->rValue; + mod->BSIM3vbdrMaxGiven = TRUE; + break; + + case BSIM3_MOD_NMOS : + if(value->iValue) { + mod->BSIM3type = 1; + mod->BSIM3typeGiven = TRUE; + } + break; + case BSIM3_MOD_PMOS : + if(value->iValue) { + mod->BSIM3type = - 1; + mod->BSIM3typeGiven = TRUE; + } + break; + default: + return(E_BADPARM); + } + return(OK); +} + + diff --git a/src/spicelib/devices/bsim3simd/b3noi.c b/src/spicelib/devices/bsim3simd/b3noi.c new file mode 100644 index 000000000..92b473599 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3noi.c @@ -0,0 +1,360 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3noi.c of BSIM3v3.3.0 + * Author: 1995 Gary W. Ng and Min-Chie Jeng. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + * Modified by Xuemei Xi, 10/05/2001. + **********/ + +#include "ngspice/ngspice.h" +#include "bsim3def.h" +#include "ngspice/cktdefs.h" +#include "ngspice/iferrmsg.h" +#include "ngspice/noisedef.h" +#include "ngspice/suffix.h" +#include "ngspice/const.h" /* jwan */ + +/* + * BSIM3SIMDnoise (mode, operation, firstModel, ckt, data, OnDens) + * This routine names and evaluates all of the noise sources + * associated with MOSFET's. It starts with the model *firstModel and + * traverses all of its insts. It then proceeds to any other models + * on the linked list. The total output noise density generated by + * all of the MOSFET's is summed with the variable "OnDens". + */ + +/* + Channel thermal and flicker noises are calculated based on the value + of model->BSIM3noiMod. + If model->BSIM3noiMod = 1, + Channel thermal noise = SPICE2 model + Flicker noise = SPICE2 model + If model->BSIM3noiMod = 2, + Channel thermal noise = BSIM3 model + Flicker noise = BSIM3 model + If model->BSIM3noiMod = 3, + Channel thermal noise = SPICE2 model + Flicker noise = BSIM3 model + If model->BSIM3noiMod = 4, + Channel thermal noise = BSIM3 model + Flicker noise = SPICE2 model + If model->BSIM3noiMod = 5, + Channel thermal noise = SPICE2 model with linear/sat fix + Flicker noise = SPICE2 model + If model->BSIM3noiMod = 6, + Channel thermal noise = SPICE2 model with linear/sat fix + Flicker noise = BSIM3 model + */ + + +/* + * JX: 1/f noise model is smoothed out 12/18/01. + */ + + +static double +StrongInversionNoiseEval( +double Vds, +BSIM3model *model, +BSIM3instance *here, +double freq, double temp) +{ +struct bsim3SizeDependParam *pParam; +double cd, esat, DelClm, EffFreq, N0, Nl, Leff, Leffsq; +double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; + + pParam = here->pParam; + cd = fabs(here->BSIM3cd); + Leff = pParam->BSIM3leff - 2.0 * model->BSIM3lintnoi; + Leffsq = Leff * Leff; + esat = 2.0 * pParam->BSIM3vsattemp / here->BSIM3ueff; + if(model->BSIM3em<=0.0) DelClm = 0.0; + else { + T0 = ((((Vds - here->BSIM3Vdseff) / pParam->BSIM3litl) + + model->BSIM3em) / esat); + DelClm = pParam->BSIM3litl * log (MAX(T0, N_MINLOG)); + if (DelClm < 0.0) DelClm = 0.0; /* bugfix */ + } + EffFreq = pow(freq, model->BSIM3ef); + T1 = CHARGE * CHARGE * 8.62e-5 * cd * temp * here->BSIM3ueff; + T2 = 1.0e8 * EffFreq * here->BSIM3Abulk * model->BSIM3cox * Leffsq; + N0 = model->BSIM3cox * here->BSIM3Vgsteff / CHARGE; + Nl = model->BSIM3cox * here->BSIM3Vgsteff + * (1.0 - here->BSIM3AbovVgst2Vtm * here->BSIM3Vdseff) / CHARGE; + + T3 = model->BSIM3oxideTrapDensityA + * log(MAX(((N0 + 2.0e14) / (Nl + 2.0e14)), N_MINLOG)); + T4 = model->BSIM3oxideTrapDensityB * (N0 - Nl); + T5 = model->BSIM3oxideTrapDensityC * 0.5 * (N0 * N0 - Nl * Nl); + + T6 = 8.62e-5 * temp * cd * cd; + T7 = 1.0e8 * EffFreq * Leffsq * pParam->BSIM3weff; + T8 = model->BSIM3oxideTrapDensityA + model->BSIM3oxideTrapDensityB * Nl + + model->BSIM3oxideTrapDensityC * Nl * Nl; + T9 = (Nl + 2.0e14) * (Nl + 2.0e14); + + Ssi = T1 / T2 * (T3 + T4 + T5) + T6 / T7 * DelClm * T8 / T9; + return Ssi; +} + +int +BSIM3SIMDnoise ( +int mode, int operation, +GENmodel *inModel, +CKTcircuit *ckt, +Ndata *data, +double *OnDens) +{ +NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; + +BSIM3model *model = (BSIM3model *)inModel; +BSIM3instance *here; +struct bsim3SizeDependParam *pParam; +double tempOnoise; +double tempInoise; +double noizDens[BSIM3NSRCS]; +double lnNdens[BSIM3NSRCS]; + +double vds; + +double T1, T10, T11; +double Ssi, Swi; + +double m; + +int i; + + /* define the names of the noise sources */ + static char *BSIM3nNames[BSIM3NSRCS] = + { /* Note that we have to keep the order */ + ".rd", /* noise due to rd */ + /* consistent with the index definitions */ + ".rs", /* noise due to rs */ + /* in BSIM3defs.h */ + ".id", /* noise due to id */ + ".1overf", /* flicker (1/f) noise */ + "" /* total transistor noise */ + }; + + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { for (here = BSIM3SIMDinstances(model); here != NULL; + here = BSIM3SIMDnextInstance(here)) + { 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 < BSIM3NSRCS; i++) + { NOISE_ADD_OUTVAR(ckt, data, "onoise.%s%s", here->BSIM3name, BSIM3nNames[i]); + } + break; + case INT_NOIZ: + for (i = 0; i < BSIM3NSRCS; i++) + { NOISE_ADD_OUTVAR(ckt, data, "onoise_total.%s%s", here->BSIM3name, BSIM3nNames[i]); + NOISE_ADD_OUTVAR(ckt, data, "inoise_total.%s%s", here->BSIM3name, BSIM3nNames[i]); + } + break; + } + } + break; + case N_CALC: + m = here->BSIM3m; + switch (mode) + { case N_DENS: + NevalSrc(&noizDens[BSIM3RDNOIZ], + &lnNdens[BSIM3RDNOIZ], ckt, THERMNOISE, + here->BSIM3dNodePrime, here->BSIM3dNode, + here->BSIM3drainConductance * m); + + NevalSrc(&noizDens[BSIM3RSNOIZ], + &lnNdens[BSIM3RSNOIZ], ckt, THERMNOISE, + here->BSIM3sNodePrime, here->BSIM3sNode, + here->BSIM3sourceConductance * m); + + switch( model->BSIM3noiMod ) + { case 1: + case 3: + NevalSrc(&noizDens[BSIM3IDNOIZ], + &lnNdens[BSIM3IDNOIZ], ckt, + THERMNOISE, here->BSIM3dNodePrime, + here->BSIM3sNodePrime, + 2.0 * fabs(here->BSIM3gm + + here->BSIM3gds + + here->BSIM3gmbs) / 3.0 * m); + + break; + case 5: + case 6: + vds = MIN(*(ckt->CKTstates[0] + here->BSIM3vds), here->BSIM3vdsat); + NevalSrc(&noizDens[BSIM3IDNOIZ], + &lnNdens[BSIM3IDNOIZ], ckt, + THERMNOISE, here->BSIM3dNodePrime, + here->BSIM3sNodePrime, + (3.0 - vds / here->BSIM3vdsat) + * fabs(here->BSIM3gm + + here->BSIM3gds + + here->BSIM3gmbs) / 3.0 * m); + + break; + case 2: + case 4: + NevalSrc(&noizDens[BSIM3IDNOIZ], + &lnNdens[BSIM3IDNOIZ], ckt, + THERMNOISE, here->BSIM3dNodePrime, + here->BSIM3sNodePrime, + (m * here->BSIM3ueff + * fabs(here->BSIM3qinv) + / (pParam->BSIM3leff * pParam->BSIM3leff + + here->BSIM3ueff *fabs(here->BSIM3qinv) + * here->BSIM3rds))); /* bugfix */ + break; + } + NevalSrc(&noizDens[BSIM3FLNOIZ], NULL, + ckt, N_GAIN, here->BSIM3dNodePrime, + here->BSIM3sNodePrime, (double) 0.0); + + switch( model->BSIM3noiMod ) + { case 1: + case 4: + case 5: + noizDens[BSIM3FLNOIZ] *= m * model->BSIM3kf + * exp(model->BSIM3af + * log(MAX(fabs(here->BSIM3cd), + N_MINLOG))) + / (pow(data->freq, model->BSIM3ef) + * pParam->BSIM3leff + * pParam->BSIM3leff + * model->BSIM3cox); + break; + case 2: + case 3: + case 6: + vds = *(ckt->CKTstates[0] + here->BSIM3vds); + if (vds < 0.0) + { vds = -vds; + } + Ssi = StrongInversionNoiseEval(vds, model, + here, data->freq, ckt->CKTtemp); + T10 = model->BSIM3oxideTrapDensityA + * 8.62e-5 * ckt->CKTtemp; + T11 = pParam->BSIM3weff + * pParam->BSIM3leff + * pow(data->freq, model->BSIM3ef) + * 4.0e36; + Swi = T10 / T11 * here->BSIM3cd + * here->BSIM3cd; + T1 = Swi + Ssi; + if (T1 > 0.0) + noizDens[BSIM3FLNOIZ] *= m * (Ssi * Swi) / T1; + else + noizDens[BSIM3FLNOIZ] *= 0.0; + break; + } + + lnNdens[BSIM3FLNOIZ] = + log(MAX(noizDens[BSIM3FLNOIZ], N_MINLOG)); + + noizDens[BSIM3TOTNOIZ] = noizDens[BSIM3RDNOIZ] + + noizDens[BSIM3RSNOIZ] + + noizDens[BSIM3IDNOIZ] + + noizDens[BSIM3FLNOIZ]; + lnNdens[BSIM3TOTNOIZ] = + log(MAX(noizDens[BSIM3TOTNOIZ], N_MINLOG)); + + *OnDens += noizDens[BSIM3TOTNOIZ]; + + if (data->delFreq == 0.0) + { /* if we haven't done any previous + integration, we need to initialize our + "history" variables. + */ + + for (i = 0; i < BSIM3NSRCS; i++) + { here->BSIM3nVar[LNLSTDENS][i] = + lnNdens[i]; + } + + /* clear out our integration variables + if it's the first pass + */ + if (data->freq == + job->NstartFreq) + { for (i = 0; i < BSIM3NSRCS; i++) + { here->BSIM3nVar[OUTNOIZ][i] = 0.0; + here->BSIM3nVar[INNOIZ][i] = 0.0; + } + } + } + else + { /* data->delFreq != 0.0, + we have to integrate. + */ + for (i = 0; i < BSIM3NSRCS; i++) + { if (i != BSIM3TOTNOIZ) + { tempOnoise = Nintegrate(noizDens[i], + lnNdens[i], + here->BSIM3nVar[LNLSTDENS][i], + data); + tempInoise = Nintegrate(noizDens[i] + * data->GainSqInv, lnNdens[i] + + data->lnGainInv, + here->BSIM3nVar[LNLSTDENS][i] + + data->lnGainInv, data); + here->BSIM3nVar[LNLSTDENS][i] = + lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (job->NStpsSm != 0) + { here->BSIM3nVar[OUTNOIZ][i] + += tempOnoise; + here->BSIM3nVar[OUTNOIZ][BSIM3TOTNOIZ] + += tempOnoise; + here->BSIM3nVar[INNOIZ][i] + += tempInoise; + here->BSIM3nVar[INNOIZ][BSIM3TOTNOIZ] + += tempInoise; + } + } + } + } + if (data->prtSummary) + { for (i = 0; i < BSIM3NSRCS; 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 < BSIM3NSRCS; i++) + { data->outpVector[data->outNumber++] + = here->BSIM3nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] + = here->BSIM3nVar[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/bsim3simd/b3par.c b/src/spicelib/devices/bsim3simd/b3par.c new file mode 100644 index 000000000..0dfedf7fb --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3par.c @@ -0,0 +1,133 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3par.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/ifsim.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" +#include "ngspice/fteext.h" + +int +BSIM3SIMDparam ( +int param, +IFvalue *value, +GENinstance *inst, +IFvalue *select) +{ + double scale; + + BSIM3instance *here = (BSIM3instance*)inst; + + NG_IGNORE(select); + + if (!cp_getvar("scale", CP_REAL, &scale, 0)) + scale = 1; + + switch (param) { + case BSIM3_W: + here->BSIM3w = value->rValue*scale; + here->BSIM3wGiven = TRUE; + break; + case BSIM3_L: + here->BSIM3l = value->rValue*scale; + here->BSIM3lGiven = 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; + break; + case BSIM3_AD: + here->BSIM3drainArea = value->rValue*scale*scale; + here->BSIM3drainAreaGiven = TRUE; + break; + case BSIM3_PS: + here->BSIM3sourcePerimeter = value->rValue*scale; + here->BSIM3sourcePerimeterGiven = TRUE; + break; + case BSIM3_PD: + here->BSIM3drainPerimeter = value->rValue*scale; + here->BSIM3drainPerimeterGiven = TRUE; + break; + case BSIM3_NRS: + here->BSIM3sourceSquares = value->rValue; + here->BSIM3sourceSquaresGiven = TRUE; + break; + case BSIM3_NRD: + here->BSIM3drainSquares = value->rValue; + here->BSIM3drainSquaresGiven = TRUE; + break; + case BSIM3_OFF: + here->BSIM3off = value->iValue; + break; + case BSIM3_IC_VBS: + here->BSIM3icVBS = value->rValue; + here->BSIM3icVBSGiven = TRUE; + break; + case BSIM3_IC_VDS: + here->BSIM3icVDS = value->rValue; + here->BSIM3icVDSGiven = TRUE; + break; + case BSIM3_IC_VGS: + here->BSIM3icVGS = value->rValue; + here->BSIM3icVGSGiven = TRUE; + break; + case BSIM3_NQSMOD: + here->BSIM3nqsMod = value->iValue; + here->BSIM3nqsModGiven = TRUE; + break; + case BSIM3_ACNQSMOD: + 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: + /* FALLTHROUGH added to suppress GCC warning due to + * -Wimplicit-fallthrough flag */ + switch (value->v.numValue) { + case 3: + here->BSIM3icVBS = *(value->v.vec.rVec+2); + here->BSIM3icVBSGiven = TRUE; + /* FALLTHROUGH */ + case 2: + here->BSIM3icVGS = *(value->v.vec.rVec+1); + here->BSIM3icVGSGiven = TRUE; + /* FALLTHROUGH */ + case 1: + here->BSIM3icVDS = *(value->v.vec.rVec); + here->BSIM3icVDSGiven = TRUE; + break; + default: + return(E_BADPARM); + } + break; + default: + return(E_BADPARM); + } + return(OK); +} + + + diff --git a/src/spicelib/devices/bsim3simd/b3pzld.c b/src/spicelib/devices/bsim3simd/b3pzld.c new file mode 100644 index 000000000..58e2cd96c --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3pzld.c @@ -0,0 +1,371 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3pzld.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "ngspice/complex.h" +#include "ngspice/sperror.h" +#include "bsim3def.h" +#include "ngspice/suffix.h" + +int +BSIM3SIMDpzLoad( +GENmodel *inModel, +CKTcircuit *ckt, +SPcomplex *s) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; +double xcggb, xcgdb, xcgsb, xcgbb, xcbgb, xcbdb, xcbsb, xcbbb; +double xcdgb, xcddb, xcdsb, xcdbb, xcsgb, xcsdb, xcssb, xcsbb; +double gdpr, gspr, gds, gbd, gbs, capbd, capbs, FwdSum, RevSum, Gm, Gmbs; +double cggb, cgdb, cgsb, cbgb, cbdb, cbsb, cddb, cdgb, cdsb; +double GSoverlapCap, GDoverlapCap, GBoverlapCap; +double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb=0.0, xcqdb=0.0, xcqsb=0.0, xcqbb=0.0; +double gbspsp, gbbdp, gbbsp, gbspg, gbspb; +double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; +double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; +double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; +double T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; +double ScalingFactor = 1.0e-9; +double m; + + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { for (here = BSIM3SIMDinstances(model); here!= NULL; + here = BSIM3SIMDnextInstance(here)) + { + if (here->BSIM3mode >= 0) + { Gm = here->BSIM3gm; + Gmbs = here->BSIM3gmbs; + FwdSum = Gm + Gmbs; + RevSum = 0.0; + + gbbdp = -here->BSIM3gbds; + gbbsp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + + gbdpg = here->BSIM3gbgs; + gbdpdp = here->BSIM3gbds; + gbdpb = here->BSIM3gbbs; + gbdpsp = -(gbdpg + gbdpdp + gbdpb); + + gbspg = 0.0; + gbspdp = 0.0; + gbspb = 0.0; + gbspsp = 0.0; + + if (here->BSIM3nqsMod == 0 && here->BSIM3acnqsMod == 0) + { cggb = here->BSIM3cggb; + cgsb = here->BSIM3cgsb; + cgdb = here->BSIM3cgdb; + + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbsb; + cbdb = here->BSIM3cbdb; + + cdgb = here->BSIM3cdgb; + cdsb = here->BSIM3cdsb; + cddb = here->BSIM3cddb; + + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.6; + dxpart = 0.4; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; + + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gtd; + xgts = here->BSIM3gts; + xgtb = here->BSIM3gtb; + + xcqgb = here->BSIM3cqgb; + xcqdb = here->BSIM3cqdb; + xcqsb = here->BSIM3cqsb; + xcqbb = here->BSIM3cqbb; + + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { dxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { dxpart = 0.0; + } + else + { dxpart = 0.5; + } + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + } + else + { dxpart = here->BSIM3qdrn / qcheq; + Cdd = here->BSIM3cddb; + Csd = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq; + Cdg = here->BSIM3cdgb; + Csg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq; + + Cds = here->BSIM3cdsb; + Css = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq; + + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + + ddxpart_dVs); + } + sxpart = 1.0 - dxpart; + dsxpart_dVd = -ddxpart_dVd; + dsxpart_dVg = -ddxpart_dVg; + dsxpart_dVs = -ddxpart_dVs; + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs); + } + } + else + { Gm = -here->BSIM3gm; + Gmbs = -here->BSIM3gmbs; + FwdSum = 0.0; + RevSum = -(Gm + Gmbs); + + gbbsp = -here->BSIM3gbds; + gbbdp = here->BSIM3gbds + here->BSIM3gbgs + here->BSIM3gbbs; + + gbdpg = 0.0; + gbdpsp = 0.0; + gbdpb = 0.0; + gbdpdp = 0.0; + + gbspg = here->BSIM3gbgs; + gbspsp = here->BSIM3gbds; + gbspb = here->BSIM3gbbs; + gbspdp = -(gbspg + gbspsp + gbspb); + + if (here->BSIM3nqsMod == 0 && here->BSIM3acnqsMod == 0) + { cggb = here->BSIM3cggb; + cgsb = here->BSIM3cgdb; + cgdb = here->BSIM3cgsb; + + cbgb = here->BSIM3cbgb; + cbsb = here->BSIM3cbdb; + cbdb = here->BSIM3cbsb; + + cdgb = -(here->BSIM3cdgb + cggb + cbgb); + cdsb = -(here->BSIM3cddb + cgsb + cbsb); + cddb = -(here->BSIM3cdsb + cgdb + cbdb); + + xgtg = xgtd = xgts = xgtb = 0.0; + sxpart = 0.4; + dxpart = 0.6; + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb + = ddxpart_dVs = 0.0; + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { cggb = cgdb = cgsb = 0.0; + cbgb = cbdb = cbsb = 0.0; + cdgb = cddb = cdsb = 0.0; + + xgtg = here->BSIM3gtg; + xgtd = here->BSIM3gts; + xgts = here->BSIM3gtd; + xgtb = here->BSIM3gtb; + + xcqgb = here->BSIM3cqgb; + xcqdb = here->BSIM3cqsb; + xcqsb = here->BSIM3cqdb; + xcqbb = here->BSIM3cqbb; + + CoxWL = model->BSIM3cox * here->pParam->BSIM3weffCV + * here->pParam->BSIM3leffCV; + qcheq = -(here->BSIM3qgate + here->BSIM3qbulk); + if (fabs(qcheq) <= 1.0e-5 * CoxWL) + { if (model->BSIM3xpart < 0.5) + { sxpart = 0.4; + } + else if (model->BSIM3xpart > 0.5) + { sxpart = 0.0; + } + else + { sxpart = 0.5; + } + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb + = dsxpart_dVs = 0.0; + } + else + { sxpart = here->BSIM3qdrn / qcheq; + Css = here->BSIM3cddb; + Cds = -(here->BSIM3cgdb + here->BSIM3cddb + + here->BSIM3cbdb); + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq; + Csg = here->BSIM3cdgb; + Cdg = -(here->BSIM3cggb + here->BSIM3cdgb + + here->BSIM3cbgb); + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq; + + Csd = here->BSIM3cdsb; + Cdd = -(here->BSIM3cgsb + here->BSIM3cdsb + + here->BSIM3cbsb); + dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq; + + dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + + dsxpart_dVs); + } + dxpart = 1.0 - sxpart; + ddxpart_dVd = -dsxpart_dVd; + ddxpart_dVg = -dsxpart_dVg; + ddxpart_dVs = -dsxpart_dVs; + ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs); + } + } + + + T1 = *(ckt->CKTstate0 + here->BSIM3qdef) * here->BSIM3gtau; + gdpr = here->BSIM3drainConductance; + gspr = here->BSIM3sourceConductance; + gds = here->BSIM3gds; + gbd = here->BSIM3gbd; + gbs = here->BSIM3gbs; + capbd = here->BSIM3capbd; + capbs = here->BSIM3capbs; + + GSoverlapCap = here->BSIM3cgso; + GDoverlapCap = here->BSIM3cgdo; + GBoverlapCap = here->pParam->BSIM3cgbo; + + xcdgb = (cdgb - GDoverlapCap); + xcddb = (cddb + capbd + GDoverlapCap); + xcdsb = cdsb; + xcdbb = -(xcdgb + xcddb + xcdsb); + xcsgb = -(cggb + cbgb + cdgb + GSoverlapCap); + xcsdb = -(cgdb + cbdb + cddb); + xcssb = (capbs + GSoverlapCap - (cgsb + cbsb + cdsb)); + xcsbb = -(xcsgb + xcsdb + xcssb); + xcggb = (cggb + GDoverlapCap + GSoverlapCap + GBoverlapCap); + xcgdb = (cgdb - GDoverlapCap); + xcgsb = (cgsb - GSoverlapCap); + xcgbb = -(xcggb + xcgdb + xcgsb); + xcbgb = (cbgb - GBoverlapCap); + xcbdb = (cbdb - capbd); + xcbsb = (cbsb - capbs); + xcbbb = -(xcbgb + xcbdb + xcbsb); + + m = here->BSIM3m; + + *(here->BSIM3GgPtr ) += m * (xcggb * s->real); + *(here->BSIM3GgPtr +1) += m * (xcggb * s->imag); + *(here->BSIM3BbPtr ) += m * (xcbbb * s->real); + *(here->BSIM3BbPtr +1) += m * (xcbbb * s->imag); + *(here->BSIM3DPdpPtr ) += m * (xcddb * s->real); + *(here->BSIM3DPdpPtr +1) += m * (xcddb * s->imag); + *(here->BSIM3SPspPtr ) += m * (xcssb * s->real); + *(here->BSIM3SPspPtr +1) += m * (xcssb * s->imag); + + *(here->BSIM3GbPtr ) += m * (xcgbb * s->real); + *(here->BSIM3GbPtr +1) += m * (xcgbb * s->imag); + *(here->BSIM3GdpPtr ) += m * (xcgdb * s->real); + *(here->BSIM3GdpPtr +1) += m * (xcgdb * s->imag); + *(here->BSIM3GspPtr ) += m * (xcgsb * s->real); + *(here->BSIM3GspPtr +1) += m * (xcgsb * s->imag); + + *(here->BSIM3BgPtr ) += m * (xcbgb * s->real); + *(here->BSIM3BgPtr +1) += m * (xcbgb * s->imag); + *(here->BSIM3BdpPtr ) += m * (xcbdb * s->real); + *(here->BSIM3BdpPtr +1) += m * (xcbdb * s->imag); + *(here->BSIM3BspPtr ) += m * (xcbsb * s->real); + *(here->BSIM3BspPtr +1) += m * (xcbsb * s->imag); + + *(here->BSIM3DPgPtr ) += m * (xcdgb * s->real); + *(here->BSIM3DPgPtr +1) += m * (xcdgb * s->imag); + *(here->BSIM3DPbPtr ) += m * (xcdbb * s->real); + *(here->BSIM3DPbPtr +1) += m * (xcdbb * s->imag); + *(here->BSIM3DPspPtr ) += m * (xcdsb * s->real); + *(here->BSIM3DPspPtr +1) += m * (xcdsb * s->imag); + + *(here->BSIM3SPgPtr ) += m * (xcsgb * s->real); + *(here->BSIM3SPgPtr +1) += m * (xcsgb * s->imag); + *(here->BSIM3SPbPtr ) += m * (xcsbb * s->real); + *(here->BSIM3SPbPtr +1) += m * (xcsbb * s->imag); + *(here->BSIM3SPdpPtr ) += m * (xcsdb * s->real); + *(here->BSIM3SPdpPtr +1) += m * (xcsdb * s->imag); + + *(here->BSIM3DdPtr) += m * gdpr; + *(here->BSIM3DdpPtr) -= m * gdpr; + *(here->BSIM3DPdPtr) -= m * gdpr; + + *(here->BSIM3SsPtr) += m * gspr; + *(here->BSIM3SspPtr) -= m * gspr; + *(here->BSIM3SPsPtr) -= m * gspr; + + *(here->BSIM3BgPtr) -= m * here->BSIM3gbgs; + *(here->BSIM3BbPtr) += m * (gbd + gbs - here->BSIM3gbbs); + *(here->BSIM3BdpPtr) -= m * (gbd - gbbdp); + *(here->BSIM3BspPtr) -= m * (gbs - gbbsp); + + *(here->BSIM3DPgPtr) += m * (Gm + dxpart * xgtg + + T1 * ddxpart_dVg + gbdpg); + *(here->BSIM3DPdpPtr) += m * (gdpr + gds + gbd + RevSum + + dxpart * xgtd + T1 * ddxpart_dVd + gbdpdp); + *(here->BSIM3DPspPtr) -= m * (gds + FwdSum - dxpart * xgts + - T1 * ddxpart_dVs - gbdpsp); + *(here->BSIM3DPbPtr) -= m * (gbd - Gmbs - dxpart * xgtb + - T1 * ddxpart_dVb - gbdpb); + + *(here->BSIM3SPgPtr) -= m * (Gm - sxpart * xgtg + - T1 * dsxpart_dVg - gbspg); + *(here->BSIM3SPspPtr) += m * (gspr + gds + gbs + FwdSum + + sxpart * xgts + T1 * dsxpart_dVs + gbspsp); + *(here->BSIM3SPbPtr) -= m * (gbs + Gmbs - sxpart * xgtb + - T1 * dsxpart_dVb - gbspb); + *(here->BSIM3SPdpPtr) -= m * (gds + RevSum - sxpart * xgtd + - T1 * dsxpart_dVd - gbspdp); + + *(here->BSIM3GgPtr) -= m * xgtg; + *(here->BSIM3GbPtr) -= m * xgtb; + *(here->BSIM3GdpPtr) -= m * xgtd; + *(here->BSIM3GspPtr) -= m * xgts; + + if (here->BSIM3nqsMod || here->BSIM3acnqsMod) + { *(here->BSIM3QqPtr ) += m * (s->real * ScalingFactor); + *(here->BSIM3QqPtr +1) += m * (s->imag * ScalingFactor); + *(here->BSIM3QgPtr ) -= m * (xcqgb * s->real); + *(here->BSIM3QgPtr +1) -= m * (xcqgb * s->imag); + *(here->BSIM3QdpPtr ) -= m * (xcqdb * s->real); + *(here->BSIM3QdpPtr +1) -= m * (xcqdb * s->imag); + *(here->BSIM3QbPtr ) -= m * (xcqbb * s->real); + *(here->BSIM3QbPtr +1) -= m * (xcqbb * s->imag); + *(here->BSIM3QspPtr ) -= m * (xcqsb * s->real); + *(here->BSIM3QspPtr +1) -= m * (xcqsb * s->imag); + + *(here->BSIM3GqPtr) -= m * (here->BSIM3gtau); + *(here->BSIM3DPqPtr) += m * (dxpart * here->BSIM3gtau); + *(here->BSIM3SPqPtr) += m * (sxpart * here->BSIM3gtau); + + *(here->BSIM3QqPtr) += m * (here->BSIM3gtau); + *(here->BSIM3QgPtr) += m * xgtg; + *(here->BSIM3QdpPtr) += m * xgtd; + *(here->BSIM3QbPtr) += m * xgtb; + *(here->BSIM3QspPtr) += m * xgts; + } + } + } + return(OK); +} + diff --git a/src/spicelib/devices/bsim3simd/b3set.c b/src/spicelib/devices/bsim3simd/b3set.c new file mode 100644 index 000000000..20b190492 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3set.c @@ -0,0 +1,1269 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ +/**** OpenMP support for ngspice by Holger Vogt 06/28/2010 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3set.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/smpdefs.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +#include "ngspice/cpextern.h" + +extern SPICEdev BSIM3SIMDinfo; + +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define SMOOTHFACTOR 0.1 +#define EPSOX 3.453133e-11 +#define EPSSI 1.03594e-10 +#define PI 3.141592654 +#define Charge_q 1.60219e-19 +#define Meter2Micron 1.0e6 + +int +BSIM3SIMDsetup( +SMPmatrix *matrix, +GENmodel *inModel, +CKTcircuit *ckt, +int *states) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; +int error; +CKTnode *tmp; +CKTnode *tmpNode; +IFuid tmpName; + +#if 1 +int idx, InstCount; +BSIM3instance **InstArray; +#endif + + + /* loop through all the BSIM3 device models */ + for( ; model != NULL; model = BSIM3SIMDnextModel(model)) + { +/* Default value Processing for BSIM3 MOSFET Models */ + if (!model->BSIM3typeGiven) + model->BSIM3type = NMOS; + if (!model->BSIM3mobModGiven) + model->BSIM3mobMod = 1; + if (!model->BSIM3binUnitGiven) + model->BSIM3binUnit = 1; + if (!model->BSIM3paramChkGiven) + 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)) + { model->BSIM3acnqsMod = 0; + printf("Warning: acnqsMod has been set to its default value: 0.\n"); + } + if (!model->BSIM3versionGiven) + model->BSIM3version = copy("3.3.0"); + if (!model->BSIM3toxGiven) + model->BSIM3tox = 150.0e-10; + model->BSIM3cox = 3.453133e-11 / model->BSIM3tox; + if (!model->BSIM3toxmGiven) + model->BSIM3toxm = model->BSIM3tox; + + if (!model->BSIM3cdscGiven) + model->BSIM3cdsc = 2.4e-4; /* unit Q/V/m^2 */ + if (!model->BSIM3cdscbGiven) + model->BSIM3cdscb = 0.0; /* unit Q/V/m^2 */ + if (!model->BSIM3cdscdGiven) + model->BSIM3cdscd = 0.0; /* unit Q/V/m^2 */ + if (!model->BSIM3citGiven) + model->BSIM3cit = 0.0; /* unit Q/V/m^2 */ + if (!model->BSIM3nfactorGiven) + model->BSIM3nfactor = 1; + if (!model->BSIM3xjGiven) + model->BSIM3xj = .15e-6; + if (!model->BSIM3vsatGiven) + model->BSIM3vsat = 8.0e4; /* unit m/s */ + if (!model->BSIM3atGiven) + model->BSIM3at = 3.3e4; /* unit m/s */ + if (!model->BSIM3a0Given) + model->BSIM3a0 = 1.0; + if (!model->BSIM3agsGiven) + model->BSIM3ags = 0.0; + if (!model->BSIM3a1Given) + model->BSIM3a1 = 0.0; + if (!model->BSIM3a2Given) + model->BSIM3a2 = 1.0; + if (!model->BSIM3ketaGiven) + model->BSIM3keta = -0.047; /* unit / V */ + if (!model->BSIM3nsubGiven) + model->BSIM3nsub = 6.0e16; /* unit 1/cm3 */ + if (!model->BSIM3npeakGiven) + model->BSIM3npeak = 1.7e17; /* unit 1/cm3 */ + if (!model->BSIM3ngateGiven) + model->BSIM3ngate = 0; /* unit 1/cm3 */ + if (!model->BSIM3vbmGiven) + model->BSIM3vbm = -3.0; + if (!model->BSIM3xtGiven) + model->BSIM3xt = 1.55e-7; + if (!model->BSIM3kt1Given) + model->BSIM3kt1 = -0.11; /* unit V */ + if (!model->BSIM3kt1lGiven) + model->BSIM3kt1l = 0.0; /* unit V*m */ + if (!model->BSIM3kt2Given) + model->BSIM3kt2 = 0.022; /* No unit */ + if (!model->BSIM3k3Given) + model->BSIM3k3 = 80.0; + if (!model->BSIM3k3bGiven) + model->BSIM3k3b = 0.0; + if (!model->BSIM3w0Given) + model->BSIM3w0 = 2.5e-6; + if (!model->BSIM3nlxGiven) + model->BSIM3nlx = 1.74e-7; + if (!model->BSIM3dvt0Given) + model->BSIM3dvt0 = 2.2; + if (!model->BSIM3dvt1Given) + model->BSIM3dvt1 = 0.53; + if (!model->BSIM3dvt2Given) + model->BSIM3dvt2 = -0.032; /* unit 1 / V */ + + if (!model->BSIM3dvt0wGiven) + model->BSIM3dvt0w = 0.0; + if (!model->BSIM3dvt1wGiven) + model->BSIM3dvt1w = 5.3e6; + if (!model->BSIM3dvt2wGiven) + model->BSIM3dvt2w = -0.032; + + if (!model->BSIM3droutGiven) + model->BSIM3drout = 0.56; + if (!model->BSIM3dsubGiven) + model->BSIM3dsub = model->BSIM3drout; + if (!model->BSIM3vth0Given) + model->BSIM3vth0 = (model->BSIM3type == NMOS) ? 0.7 : -0.7; + if (!model->BSIM3uaGiven) + model->BSIM3ua = 2.25e-9; /* unit m/V */ + if (!model->BSIM3ua1Given) + model->BSIM3ua1 = 4.31e-9; /* unit m/V */ + if (!model->BSIM3ubGiven) + model->BSIM3ub = 5.87e-19; /* unit (m/V)**2 */ + if (!model->BSIM3ub1Given) + model->BSIM3ub1 = -7.61e-18; /* unit (m/V)**2 */ + if (!model->BSIM3ucGiven) + model->BSIM3uc = (model->BSIM3mobMod == 3) ? -0.0465 : -0.0465e-9; + if (!model->BSIM3uc1Given) + model->BSIM3uc1 = (model->BSIM3mobMod == 3) ? -0.056 : -0.056e-9; + if (!model->BSIM3u0Given) + model->BSIM3u0 = (model->BSIM3type == NMOS) ? 0.067 : 0.025; + if (!model->BSIM3uteGiven) + model->BSIM3ute = -1.5; + if (!model->BSIM3voffGiven) + model->BSIM3voff = -0.08; + if (!model->BSIM3deltaGiven) + model->BSIM3delta = 0.01; + if (!model->BSIM3rdswGiven) + model->BSIM3rdsw = 0; + if (!model->BSIM3prwgGiven) + model->BSIM3prwg = 0.0; /* unit 1/V */ + if (!model->BSIM3prwbGiven) + model->BSIM3prwb = 0.0; + if (!model->BSIM3prtGiven) + model->BSIM3prt = 0.0; + if (!model->BSIM3eta0Given) + model->BSIM3eta0 = 0.08; /* no unit */ + if (!model->BSIM3etabGiven) + model->BSIM3etab = -0.07; /* unit 1/V */ + if (!model->BSIM3pclmGiven) + model->BSIM3pclm = 1.3; /* no unit */ + if (!model->BSIM3pdibl1Given) + model->BSIM3pdibl1 = .39; /* no unit */ + if (!model->BSIM3pdibl2Given) + model->BSIM3pdibl2 = 0.0086; /* no unit */ + if (!model->BSIM3pdiblbGiven) + model->BSIM3pdiblb = 0.0; /* 1/V */ + if (!model->BSIM3pscbe1Given) + model->BSIM3pscbe1 = 4.24e8; + if (!model->BSIM3pscbe2Given) + model->BSIM3pscbe2 = 1.0e-5; + if (!model->BSIM3pvagGiven) + model->BSIM3pvag = 0.0; + if (!model->BSIM3wrGiven) + model->BSIM3wr = 1.0; + if (!model->BSIM3dwgGiven) + model->BSIM3dwg = 0.0; + if (!model->BSIM3dwbGiven) + model->BSIM3dwb = 0.0; + if (!model->BSIM3b0Given) + model->BSIM3b0 = 0.0; + if (!model->BSIM3b1Given) + model->BSIM3b1 = 0.0; + if (!model->BSIM3alpha0Given) + model->BSIM3alpha0 = 0.0; + if (!model->BSIM3alpha1Given) + model->BSIM3alpha1 = 0.0; + if (!model->BSIM3beta0Given) + model->BSIM3beta0 = 30.0; + if (!model->BSIM3ijthGiven) + model->BSIM3ijth = 0.1; /* unit A */ + + if (!model->BSIM3elmGiven) + model->BSIM3elm = 5.0; + if (!model->BSIM3cgslGiven) + model->BSIM3cgsl = 0.0; + if (!model->BSIM3cgdlGiven) + model->BSIM3cgdl = 0.0; + if (!model->BSIM3ckappaGiven) + model->BSIM3ckappa = 0.6; + if (!model->BSIM3clcGiven) + model->BSIM3clc = 0.1e-6; + if (!model->BSIM3cleGiven) + model->BSIM3cle = 0.6; + if (!model->BSIM3vfbcvGiven) + model->BSIM3vfbcv = -1.0; + if (!model->BSIM3acdeGiven) + model->BSIM3acde = 1.0; + if (!model->BSIM3moinGiven) + model->BSIM3moin = 15.0; + if (!model->BSIM3noffGiven) + model->BSIM3noff = 1.0; + if (!model->BSIM3voffcvGiven) + model->BSIM3voffcv = 0.0; + if (!model->BSIM3tcjGiven) + model->BSIM3tcj = 0.0; + if (!model->BSIM3tpbGiven) + model->BSIM3tpb = 0.0; + if (!model->BSIM3tcjswGiven) + model->BSIM3tcjsw = 0.0; + if (!model->BSIM3tpbswGiven) + model->BSIM3tpbsw = 0.0; + if (!model->BSIM3tcjswgGiven) + model->BSIM3tcjswg = 0.0; + 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; + if (!model->BSIM3lcdscbGiven) + model->BSIM3lcdscb = 0.0; + if (!model->BSIM3lcdscdGiven) + model->BSIM3lcdscd = 0.0; + if (!model->BSIM3lcitGiven) + model->BSIM3lcit = 0.0; + if (!model->BSIM3lnfactorGiven) + model->BSIM3lnfactor = 0.0; + if (!model->BSIM3lxjGiven) + model->BSIM3lxj = 0.0; + if (!model->BSIM3lvsatGiven) + model->BSIM3lvsat = 0.0; + if (!model->BSIM3latGiven) + model->BSIM3lat = 0.0; + if (!model->BSIM3la0Given) + model->BSIM3la0 = 0.0; + if (!model->BSIM3lagsGiven) + model->BSIM3lags = 0.0; + if (!model->BSIM3la1Given) + model->BSIM3la1 = 0.0; + if (!model->BSIM3la2Given) + model->BSIM3la2 = 0.0; + if (!model->BSIM3lketaGiven) + model->BSIM3lketa = 0.0; + if (!model->BSIM3lnsubGiven) + model->BSIM3lnsub = 0.0; + if (!model->BSIM3lnpeakGiven) + model->BSIM3lnpeak = 0.0; + if (!model->BSIM3lngateGiven) + model->BSIM3lngate = 0.0; + if (!model->BSIM3lvbmGiven) + model->BSIM3lvbm = 0.0; + if (!model->BSIM3lxtGiven) + model->BSIM3lxt = 0.0; + if (!model->BSIM3lkt1Given) + model->BSIM3lkt1 = 0.0; + if (!model->BSIM3lkt1lGiven) + model->BSIM3lkt1l = 0.0; + if (!model->BSIM3lkt2Given) + model->BSIM3lkt2 = 0.0; + if (!model->BSIM3lk3Given) + model->BSIM3lk3 = 0.0; + if (!model->BSIM3lk3bGiven) + model->BSIM3lk3b = 0.0; + if (!model->BSIM3lw0Given) + model->BSIM3lw0 = 0.0; + if (!model->BSIM3lnlxGiven) + model->BSIM3lnlx = 0.0; + if (!model->BSIM3ldvt0Given) + model->BSIM3ldvt0 = 0.0; + if (!model->BSIM3ldvt1Given) + model->BSIM3ldvt1 = 0.0; + if (!model->BSIM3ldvt2Given) + model->BSIM3ldvt2 = 0.0; + if (!model->BSIM3ldvt0wGiven) + model->BSIM3ldvt0w = 0.0; + if (!model->BSIM3ldvt1wGiven) + model->BSIM3ldvt1w = 0.0; + if (!model->BSIM3ldvt2wGiven) + model->BSIM3ldvt2w = 0.0; + if (!model->BSIM3ldroutGiven) + model->BSIM3ldrout = 0.0; + if (!model->BSIM3ldsubGiven) + model->BSIM3ldsub = 0.0; + if (!model->BSIM3lvth0Given) + model->BSIM3lvth0 = 0.0; + if (!model->BSIM3luaGiven) + model->BSIM3lua = 0.0; + if (!model->BSIM3lua1Given) + model->BSIM3lua1 = 0.0; + if (!model->BSIM3lubGiven) + model->BSIM3lub = 0.0; + if (!model->BSIM3lub1Given) + model->BSIM3lub1 = 0.0; + if (!model->BSIM3lucGiven) + model->BSIM3luc = 0.0; + if (!model->BSIM3luc1Given) + model->BSIM3luc1 = 0.0; + if (!model->BSIM3lu0Given) + model->BSIM3lu0 = 0.0; + if (!model->BSIM3luteGiven) + model->BSIM3lute = 0.0; + if (!model->BSIM3lvoffGiven) + model->BSIM3lvoff = 0.0; + if (!model->BSIM3ldeltaGiven) + model->BSIM3ldelta = 0.0; + if (!model->BSIM3lrdswGiven) + model->BSIM3lrdsw = 0.0; + if (!model->BSIM3lprwbGiven) + model->BSIM3lprwb = 0.0; + if (!model->BSIM3lprwgGiven) + model->BSIM3lprwg = 0.0; + if (!model->BSIM3lprtGiven) + model->BSIM3lprt = 0.0; + if (!model->BSIM3leta0Given) + model->BSIM3leta0 = 0.0; + if (!model->BSIM3letabGiven) + model->BSIM3letab = -0.0; + if (!model->BSIM3lpclmGiven) + model->BSIM3lpclm = 0.0; + if (!model->BSIM3lpdibl1Given) + model->BSIM3lpdibl1 = 0.0; + if (!model->BSIM3lpdibl2Given) + model->BSIM3lpdibl2 = 0.0; + if (!model->BSIM3lpdiblbGiven) + model->BSIM3lpdiblb = 0.0; + if (!model->BSIM3lpscbe1Given) + model->BSIM3lpscbe1 = 0.0; + if (!model->BSIM3lpscbe2Given) + model->BSIM3lpscbe2 = 0.0; + if (!model->BSIM3lpvagGiven) + model->BSIM3lpvag = 0.0; + if (!model->BSIM3lwrGiven) + model->BSIM3lwr = 0.0; + if (!model->BSIM3ldwgGiven) + model->BSIM3ldwg = 0.0; + if (!model->BSIM3ldwbGiven) + model->BSIM3ldwb = 0.0; + if (!model->BSIM3lb0Given) + model->BSIM3lb0 = 0.0; + if (!model->BSIM3lb1Given) + model->BSIM3lb1 = 0.0; + if (!model->BSIM3lalpha0Given) + model->BSIM3lalpha0 = 0.0; + if (!model->BSIM3lalpha1Given) + model->BSIM3lalpha1 = 0.0; + if (!model->BSIM3lbeta0Given) + model->BSIM3lbeta0 = 0.0; + if (!model->BSIM3lvfbGiven) + model->BSIM3lvfb = 0.0; + + if (!model->BSIM3lelmGiven) + model->BSIM3lelm = 0.0; + if (!model->BSIM3lcgslGiven) + model->BSIM3lcgsl = 0.0; + if (!model->BSIM3lcgdlGiven) + model->BSIM3lcgdl = 0.0; + if (!model->BSIM3lckappaGiven) + model->BSIM3lckappa = 0.0; + if (!model->BSIM3lclcGiven) + model->BSIM3lclc = 0.0; + if (!model->BSIM3lcleGiven) + model->BSIM3lcle = 0.0; + if (!model->BSIM3lcfGiven) + model->BSIM3lcf = 0.0; + if (!model->BSIM3lvfbcvGiven) + model->BSIM3lvfbcv = 0.0; + if (!model->BSIM3lacdeGiven) + model->BSIM3lacde = 0.0; + if (!model->BSIM3lmoinGiven) + model->BSIM3lmoin = 0.0; + if (!model->BSIM3lnoffGiven) + model->BSIM3lnoff = 0.0; + if (!model->BSIM3lvoffcvGiven) + model->BSIM3lvoffcv = 0.0; + + /* Width dependence */ + if (!model->BSIM3wcdscGiven) + model->BSIM3wcdsc = 0.0; + if (!model->BSIM3wcdscbGiven) + model->BSIM3wcdscb = 0.0; + if (!model->BSIM3wcdscdGiven) + model->BSIM3wcdscd = 0.0; + if (!model->BSIM3wcitGiven) + model->BSIM3wcit = 0.0; + if (!model->BSIM3wnfactorGiven) + model->BSIM3wnfactor = 0.0; + if (!model->BSIM3wxjGiven) + model->BSIM3wxj = 0.0; + if (!model->BSIM3wvsatGiven) + model->BSIM3wvsat = 0.0; + if (!model->BSIM3watGiven) + model->BSIM3wat = 0.0; + if (!model->BSIM3wa0Given) + model->BSIM3wa0 = 0.0; + if (!model->BSIM3wagsGiven) + model->BSIM3wags = 0.0; + if (!model->BSIM3wa1Given) + model->BSIM3wa1 = 0.0; + if (!model->BSIM3wa2Given) + model->BSIM3wa2 = 0.0; + if (!model->BSIM3wketaGiven) + model->BSIM3wketa = 0.0; + if (!model->BSIM3wnsubGiven) + model->BSIM3wnsub = 0.0; + if (!model->BSIM3wnpeakGiven) + model->BSIM3wnpeak = 0.0; + if (!model->BSIM3wngateGiven) + model->BSIM3wngate = 0.0; + if (!model->BSIM3wvbmGiven) + model->BSIM3wvbm = 0.0; + if (!model->BSIM3wxtGiven) + model->BSIM3wxt = 0.0; + if (!model->BSIM3wkt1Given) + model->BSIM3wkt1 = 0.0; + if (!model->BSIM3wkt1lGiven) + model->BSIM3wkt1l = 0.0; + if (!model->BSIM3wkt2Given) + model->BSIM3wkt2 = 0.0; + if (!model->BSIM3wk3Given) + model->BSIM3wk3 = 0.0; + if (!model->BSIM3wk3bGiven) + model->BSIM3wk3b = 0.0; + if (!model->BSIM3ww0Given) + model->BSIM3ww0 = 0.0; + if (!model->BSIM3wnlxGiven) + model->BSIM3wnlx = 0.0; + if (!model->BSIM3wdvt0Given) + model->BSIM3wdvt0 = 0.0; + if (!model->BSIM3wdvt1Given) + model->BSIM3wdvt1 = 0.0; + if (!model->BSIM3wdvt2Given) + model->BSIM3wdvt2 = 0.0; + if (!model->BSIM3wdvt0wGiven) + model->BSIM3wdvt0w = 0.0; + if (!model->BSIM3wdvt1wGiven) + model->BSIM3wdvt1w = 0.0; + if (!model->BSIM3wdvt2wGiven) + model->BSIM3wdvt2w = 0.0; + if (!model->BSIM3wdroutGiven) + model->BSIM3wdrout = 0.0; + if (!model->BSIM3wdsubGiven) + model->BSIM3wdsub = 0.0; + if (!model->BSIM3wvth0Given) + model->BSIM3wvth0 = 0.0; + if (!model->BSIM3wuaGiven) + model->BSIM3wua = 0.0; + if (!model->BSIM3wua1Given) + model->BSIM3wua1 = 0.0; + if (!model->BSIM3wubGiven) + model->BSIM3wub = 0.0; + if (!model->BSIM3wub1Given) + model->BSIM3wub1 = 0.0; + if (!model->BSIM3wucGiven) + model->BSIM3wuc = 0.0; + if (!model->BSIM3wuc1Given) + model->BSIM3wuc1 = 0.0; + if (!model->BSIM3wu0Given) + model->BSIM3wu0 = 0.0; + if (!model->BSIM3wuteGiven) + model->BSIM3wute = 0.0; + if (!model->BSIM3wvoffGiven) + model->BSIM3wvoff = 0.0; + if (!model->BSIM3wdeltaGiven) + model->BSIM3wdelta = 0.0; + if (!model->BSIM3wrdswGiven) + model->BSIM3wrdsw = 0.0; + if (!model->BSIM3wprwbGiven) + model->BSIM3wprwb = 0.0; + if (!model->BSIM3wprwgGiven) + model->BSIM3wprwg = 0.0; + if (!model->BSIM3wprtGiven) + model->BSIM3wprt = 0.0; + if (!model->BSIM3weta0Given) + model->BSIM3weta0 = 0.0; + if (!model->BSIM3wetabGiven) + model->BSIM3wetab = 0.0; + if (!model->BSIM3wpclmGiven) + model->BSIM3wpclm = 0.0; + if (!model->BSIM3wpdibl1Given) + model->BSIM3wpdibl1 = 0.0; + if (!model->BSIM3wpdibl2Given) + model->BSIM3wpdibl2 = 0.0; + if (!model->BSIM3wpdiblbGiven) + model->BSIM3wpdiblb = 0.0; + if (!model->BSIM3wpscbe1Given) + model->BSIM3wpscbe1 = 0.0; + if (!model->BSIM3wpscbe2Given) + model->BSIM3wpscbe2 = 0.0; + if (!model->BSIM3wpvagGiven) + model->BSIM3wpvag = 0.0; + if (!model->BSIM3wwrGiven) + model->BSIM3wwr = 0.0; + if (!model->BSIM3wdwgGiven) + model->BSIM3wdwg = 0.0; + if (!model->BSIM3wdwbGiven) + model->BSIM3wdwb = 0.0; + if (!model->BSIM3wb0Given) + model->BSIM3wb0 = 0.0; + if (!model->BSIM3wb1Given) + model->BSIM3wb1 = 0.0; + if (!model->BSIM3walpha0Given) + model->BSIM3walpha0 = 0.0; + if (!model->BSIM3walpha1Given) + model->BSIM3walpha1 = 0.0; + if (!model->BSIM3wbeta0Given) + model->BSIM3wbeta0 = 0.0; + if (!model->BSIM3wvfbGiven) + model->BSIM3wvfb = 0.0; + + if (!model->BSIM3welmGiven) + model->BSIM3welm = 0.0; + if (!model->BSIM3wcgslGiven) + model->BSIM3wcgsl = 0.0; + if (!model->BSIM3wcgdlGiven) + model->BSIM3wcgdl = 0.0; + if (!model->BSIM3wckappaGiven) + model->BSIM3wckappa = 0.0; + if (!model->BSIM3wcfGiven) + model->BSIM3wcf = 0.0; + if (!model->BSIM3wclcGiven) + model->BSIM3wclc = 0.0; + if (!model->BSIM3wcleGiven) + model->BSIM3wcle = 0.0; + if (!model->BSIM3wvfbcvGiven) + model->BSIM3wvfbcv = 0.0; + if (!model->BSIM3wacdeGiven) + model->BSIM3wacde = 0.0; + if (!model->BSIM3wmoinGiven) + model->BSIM3wmoin = 0.0; + if (!model->BSIM3wnoffGiven) + model->BSIM3wnoff = 0.0; + if (!model->BSIM3wvoffcvGiven) + model->BSIM3wvoffcv = 0.0; + + /* Cross-term dependence */ + if (!model->BSIM3pcdscGiven) + model->BSIM3pcdsc = 0.0; + if (!model->BSIM3pcdscbGiven) + model->BSIM3pcdscb = 0.0; + if (!model->BSIM3pcdscdGiven) + model->BSIM3pcdscd = 0.0; + if (!model->BSIM3pcitGiven) + model->BSIM3pcit = 0.0; + if (!model->BSIM3pnfactorGiven) + model->BSIM3pnfactor = 0.0; + if (!model->BSIM3pxjGiven) + model->BSIM3pxj = 0.0; + if (!model->BSIM3pvsatGiven) + model->BSIM3pvsat = 0.0; + if (!model->BSIM3patGiven) + model->BSIM3pat = 0.0; + if (!model->BSIM3pa0Given) + model->BSIM3pa0 = 0.0; + + if (!model->BSIM3pagsGiven) + model->BSIM3pags = 0.0; + if (!model->BSIM3pa1Given) + model->BSIM3pa1 = 0.0; + if (!model->BSIM3pa2Given) + model->BSIM3pa2 = 0.0; + if (!model->BSIM3pketaGiven) + model->BSIM3pketa = 0.0; + if (!model->BSIM3pnsubGiven) + model->BSIM3pnsub = 0.0; + if (!model->BSIM3pnpeakGiven) + model->BSIM3pnpeak = 0.0; + if (!model->BSIM3pngateGiven) + model->BSIM3pngate = 0.0; + if (!model->BSIM3pvbmGiven) + model->BSIM3pvbm = 0.0; + if (!model->BSIM3pxtGiven) + model->BSIM3pxt = 0.0; + if (!model->BSIM3pkt1Given) + model->BSIM3pkt1 = 0.0; + if (!model->BSIM3pkt1lGiven) + model->BSIM3pkt1l = 0.0; + if (!model->BSIM3pkt2Given) + model->BSIM3pkt2 = 0.0; + if (!model->BSIM3pk3Given) + model->BSIM3pk3 = 0.0; + if (!model->BSIM3pk3bGiven) + model->BSIM3pk3b = 0.0; + if (!model->BSIM3pw0Given) + model->BSIM3pw0 = 0.0; + if (!model->BSIM3pnlxGiven) + model->BSIM3pnlx = 0.0; + if (!model->BSIM3pdvt0Given) + model->BSIM3pdvt0 = 0.0; + if (!model->BSIM3pdvt1Given) + model->BSIM3pdvt1 = 0.0; + if (!model->BSIM3pdvt2Given) + model->BSIM3pdvt2 = 0.0; + if (!model->BSIM3pdvt0wGiven) + model->BSIM3pdvt0w = 0.0; + if (!model->BSIM3pdvt1wGiven) + model->BSIM3pdvt1w = 0.0; + if (!model->BSIM3pdvt2wGiven) + model->BSIM3pdvt2w = 0.0; + if (!model->BSIM3pdroutGiven) + model->BSIM3pdrout = 0.0; + if (!model->BSIM3pdsubGiven) + model->BSIM3pdsub = 0.0; + if (!model->BSIM3pvth0Given) + model->BSIM3pvth0 = 0.0; + if (!model->BSIM3puaGiven) + model->BSIM3pua = 0.0; + if (!model->BSIM3pua1Given) + model->BSIM3pua1 = 0.0; + if (!model->BSIM3pubGiven) + model->BSIM3pub = 0.0; + if (!model->BSIM3pub1Given) + model->BSIM3pub1 = 0.0; + if (!model->BSIM3pucGiven) + model->BSIM3puc = 0.0; + if (!model->BSIM3puc1Given) + model->BSIM3puc1 = 0.0; + if (!model->BSIM3pu0Given) + model->BSIM3pu0 = 0.0; + if (!model->BSIM3puteGiven) + model->BSIM3pute = 0.0; + if (!model->BSIM3pvoffGiven) + model->BSIM3pvoff = 0.0; + if (!model->BSIM3pdeltaGiven) + model->BSIM3pdelta = 0.0; + if (!model->BSIM3prdswGiven) + model->BSIM3prdsw = 0.0; + if (!model->BSIM3pprwbGiven) + model->BSIM3pprwb = 0.0; + if (!model->BSIM3pprwgGiven) + model->BSIM3pprwg = 0.0; + if (!model->BSIM3pprtGiven) + model->BSIM3pprt = 0.0; + if (!model->BSIM3peta0Given) + model->BSIM3peta0 = 0.0; + if (!model->BSIM3petabGiven) + model->BSIM3petab = 0.0; + if (!model->BSIM3ppclmGiven) + model->BSIM3ppclm = 0.0; + if (!model->BSIM3ppdibl1Given) + model->BSIM3ppdibl1 = 0.0; + if (!model->BSIM3ppdibl2Given) + model->BSIM3ppdibl2 = 0.0; + if (!model->BSIM3ppdiblbGiven) + model->BSIM3ppdiblb = 0.0; + if (!model->BSIM3ppscbe1Given) + model->BSIM3ppscbe1 = 0.0; + if (!model->BSIM3ppscbe2Given) + model->BSIM3ppscbe2 = 0.0; + if (!model->BSIM3ppvagGiven) + model->BSIM3ppvag = 0.0; + if (!model->BSIM3pwrGiven) + model->BSIM3pwr = 0.0; + if (!model->BSIM3pdwgGiven) + model->BSIM3pdwg = 0.0; + if (!model->BSIM3pdwbGiven) + model->BSIM3pdwb = 0.0; + if (!model->BSIM3pb0Given) + model->BSIM3pb0 = 0.0; + if (!model->BSIM3pb1Given) + model->BSIM3pb1 = 0.0; + if (!model->BSIM3palpha0Given) + model->BSIM3palpha0 = 0.0; + if (!model->BSIM3palpha1Given) + model->BSIM3palpha1 = 0.0; + if (!model->BSIM3pbeta0Given) + model->BSIM3pbeta0 = 0.0; + if (!model->BSIM3pvfbGiven) + model->BSIM3pvfb = 0.0; + + if (!model->BSIM3pelmGiven) + model->BSIM3pelm = 0.0; + if (!model->BSIM3pcgslGiven) + model->BSIM3pcgsl = 0.0; + if (!model->BSIM3pcgdlGiven) + model->BSIM3pcgdl = 0.0; + if (!model->BSIM3pckappaGiven) + model->BSIM3pckappa = 0.0; + if (!model->BSIM3pcfGiven) + model->BSIM3pcf = 0.0; + if (!model->BSIM3pclcGiven) + model->BSIM3pclc = 0.0; + if (!model->BSIM3pcleGiven) + model->BSIM3pcle = 0.0; + if (!model->BSIM3pvfbcvGiven) + model->BSIM3pvfbcv = 0.0; + if (!model->BSIM3pacdeGiven) + model->BSIM3pacde = 0.0; + if (!model->BSIM3pmoinGiven) + model->BSIM3pmoin = 0.0; + if (!model->BSIM3pnoffGiven) + model->BSIM3pnoff = 0.0; + if (!model->BSIM3pvoffcvGiven) + model->BSIM3pvoffcv = 0.0; + + /* unit degree celcius */ + if (!model->BSIM3tnomGiven) + model->BSIM3tnom = ckt->CKTnomTemp; +/* else + model->BSIM3tnom = model->BSIM3tnom + 273.15; we make this transform in b3mpar.c in the first run */ + if (!model->BSIM3lintnoiGiven) + model->BSIM3lintnoi = 0.0; /* unit m */ + if (!model->BSIM3LintGiven) + model->BSIM3Lint = 0.0; + if (!model->BSIM3LlGiven) + model->BSIM3Ll = 0.0; + if (!model->BSIM3LlcGiven) + model->BSIM3Llc = model->BSIM3Ll; + if (!model->BSIM3LlnGiven) + model->BSIM3Lln = 1.0; + if (!model->BSIM3LwGiven) + model->BSIM3Lw = 0.0; + if (!model->BSIM3LwcGiven) + model->BSIM3Lwc = model->BSIM3Lw; + if (!model->BSIM3LwnGiven) + model->BSIM3Lwn = 1.0; + if (!model->BSIM3LwlGiven) + model->BSIM3Lwl = 0.0; + if (!model->BSIM3LwlcGiven) + model->BSIM3Lwlc = model->BSIM3Lwl; + if (!model->BSIM3LminGiven) + model->BSIM3Lmin = 0.0; + if (!model->BSIM3LmaxGiven) + model->BSIM3Lmax = 1.0; + if (!model->BSIM3WintGiven) + model->BSIM3Wint = 0.0; + if (!model->BSIM3WlGiven) + model->BSIM3Wl = 0.0; + if (!model->BSIM3WlcGiven) + model->BSIM3Wlc = model->BSIM3Wl; + if (!model->BSIM3WlnGiven) + model->BSIM3Wln = 1.0; + if (!model->BSIM3WwGiven) + model->BSIM3Ww = 0.0; + if (!model->BSIM3WwcGiven) + model->BSIM3Wwc = model->BSIM3Ww; + if (!model->BSIM3WwnGiven) + model->BSIM3Wwn = 1.0; + if (!model->BSIM3WwlGiven) + model->BSIM3Wwl = 0.0; + if (!model->BSIM3WwlcGiven) + model->BSIM3Wwlc = model->BSIM3Wwl; + if (!model->BSIM3WminGiven) + model->BSIM3Wmin = 0.0; + if (!model->BSIM3WmaxGiven) + model->BSIM3Wmax = 1.0; + if (!model->BSIM3dwcGiven) + 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); + if (!model->BSIM3cgdoGiven) + { if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0)) + { model->BSIM3cgdo = model->BSIM3dlc * model->BSIM3cox + - model->BSIM3cgdl ; + } + else + model->BSIM3cgdo = 0.6 * model->BSIM3xj * model->BSIM3cox; + } + if (!model->BSIM3cgsoGiven) + { if (model->BSIM3dlcGiven && (model->BSIM3dlc > 0.0)) + { model->BSIM3cgso = model->BSIM3dlc * model->BSIM3cox + - model->BSIM3cgsl ; + } + else + model->BSIM3cgso = 0.6 * model->BSIM3xj * model->BSIM3cox; + } + + if (!model->BSIM3cgboGiven) + { model->BSIM3cgbo = 2.0 * model->BSIM3dwc * model->BSIM3cox; + } + if (!model->BSIM3xpartGiven) + model->BSIM3xpart = 0.0; + if (!model->BSIM3sheetResistanceGiven) + model->BSIM3sheetResistance = 0.0; + if (!model->BSIM3unitAreaJctCapGiven) + model->BSIM3unitAreaJctCap = 5.0E-4; + if (!model->BSIM3unitLengthSidewallJctCapGiven) + model->BSIM3unitLengthSidewallJctCap = 5.0E-10; + if (!model->BSIM3unitLengthGateSidewallJctCapGiven) + model->BSIM3unitLengthGateSidewallJctCap = model->BSIM3unitLengthSidewallJctCap ; + if (!model->BSIM3jctSatCurDensityGiven) + model->BSIM3jctSatCurDensity = 1.0E-4; + if (!model->BSIM3jctSidewallSatCurDensityGiven) + model->BSIM3jctSidewallSatCurDensity = 0.0; + if (!model->BSIM3bulkJctPotentialGiven) + model->BSIM3bulkJctPotential = 1.0; + if (!model->BSIM3sidewallJctPotentialGiven) + model->BSIM3sidewallJctPotential = 1.0; + if (!model->BSIM3GatesidewallJctPotentialGiven) + model->BSIM3GatesidewallJctPotential = model->BSIM3sidewallJctPotential; + if (!model->BSIM3bulkJctBotGradingCoeffGiven) + model->BSIM3bulkJctBotGradingCoeff = 0.5; + if (!model->BSIM3bulkJctSideGradingCoeffGiven) + model->BSIM3bulkJctSideGradingCoeff = 0.33; + if (!model->BSIM3bulkJctGateSideGradingCoeffGiven) + model->BSIM3bulkJctGateSideGradingCoeff = model->BSIM3bulkJctSideGradingCoeff; + if (!model->BSIM3jctEmissionCoeffGiven) + model->BSIM3jctEmissionCoeff = 1.0; + if (!model->BSIM3jctTempExponentGiven) + model->BSIM3jctTempExponent = 3.0; + if (!model->BSIM3oxideTrapDensityAGiven) + { if (model->BSIM3type == NMOS) + model->BSIM3oxideTrapDensityA = 1e20; + else + model->BSIM3oxideTrapDensityA=9.9e18; + } + if (!model->BSIM3oxideTrapDensityBGiven) + { if (model->BSIM3type == NMOS) + model->BSIM3oxideTrapDensityB = 5e4; + else + model->BSIM3oxideTrapDensityB = 2.4e3; + } + if (!model->BSIM3oxideTrapDensityCGiven) + { if (model->BSIM3type == NMOS) + model->BSIM3oxideTrapDensityC = -1.4e-12; + else + model->BSIM3oxideTrapDensityC = 1.4e-12; + + } + if (!model->BSIM3emGiven) + model->BSIM3em = 4.1e7; /* V/m */ + if (!model->BSIM3efGiven) + model->BSIM3ef = 1.0; + if (!model->BSIM3afGiven) + model->BSIM3af = 1.0; + if (!model->BSIM3kfGiven) + model->BSIM3kf = 0.0; + + if (!model->BSIM3vgsMaxGiven) + model->BSIM3vgsMax = 1e99; + if (!model->BSIM3vgdMaxGiven) + model->BSIM3vgdMax = 1e99; + if (!model->BSIM3vgbMaxGiven) + model->BSIM3vgbMax = 1e99; + if (!model->BSIM3vdsMaxGiven) + model->BSIM3vdsMax = 1e99; + if (!model->BSIM3vbsMaxGiven) + model->BSIM3vbsMax = 1e99; + if (!model->BSIM3vbdMaxGiven) + model->BSIM3vbdMax = 1e99; + if (!model->BSIM3vgsrMaxGiven) + model->BSIM3vgsrMax = 1e99; + if (!model->BSIM3vgdrMaxGiven) + model->BSIM3vgdrMax = 1e99; + if (!model->BSIM3vgbrMaxGiven) + model->BSIM3vgbrMax = 1e99; + if (!model->BSIM3vbsrMaxGiven) + model->BSIM3vbsrMax = 1e99; + if (!model->BSIM3vbdrMaxGiven) + model->BSIM3vbdrMax = 1e99; + + /* loop through all the instances of the model */ + for (here = BSIM3SIMDinstances(model); here != NULL ; + here=BSIM3SIMDnextInstance(here)) + { + /* allocate a chunk of the state vector */ + here->BSIM3states = *states; + *states += BSIM3numStates; + + /* perform the parameter defaulting */ + if (!here->BSIM3drainAreaGiven) + here->BSIM3drainArea = 0.0; + if (!here->BSIM3drainPerimeterGiven) + here->BSIM3drainPerimeter = 0.0; + if (!here->BSIM3drainSquaresGiven) + { + 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) + here->BSIM3icVDS = 0.0; + if (!here->BSIM3icVGSGiven) + here->BSIM3icVGS = 0.0; + if (!here->BSIM3lGiven) + here->BSIM3l = 5.0e-6; + if (!here->BSIM3sourceAreaGiven) + here->BSIM3sourceArea = 0.0; + if (!here->BSIM3sourcePerimeterGiven) + here->BSIM3sourcePerimeter = 0.0; + if (!here->BSIM3sourceSquaresGiven) + { + 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 = 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)) + { here->BSIM3acnqsMod = model->BSIM3acnqsMod; + 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 source/drain series resistance */ + /* ACM model */ + + double drainResistance, sourceResistance; + + if (model->BSIM3acmMod == 0) + { + drainResistance = model->BSIM3sheetResistance + * here->BSIM3drainSquares; + sourceResistance = 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, + &drainResistance, + &sourceResistance + ); + if (error) + return(error); + } + + /* process drain series resistance */ + if (drainResistance != 0.0) + { + if(here->BSIM3dNodePrime == 0) { + error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"drain"); + if(error) return(error); + here->BSIM3dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } + } + else + { here->BSIM3dNodePrime = here->BSIM3dNode; + } + + /* process source series resistance */ + if (sourceResistance != 0.0) + { + if(here->BSIM3sNodePrime == 0) { + error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"source"); + if(error) return(error); + here->BSIM3sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + } + } + else + { here->BSIM3sNodePrime = here->BSIM3sNode; + } + + /* internal charge node */ + + if (here->BSIM3nqsMod) + { if (here->BSIM3qNode == 0) + { error = CKTmkVolt(ckt,&tmp,here->BSIM3name,"charge"); + if(error) return(error); + here->BSIM3qNode = tmp->number; + } + } + else + { here->BSIM3qNode = 0; + } + + /* set Sparse Matrix Pointers */ + + +/* macro to make elements with built in test for out of memory */ +#define TSTALLOC(ptr,first,second) \ +do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ + return(E_NOMEM);\ +} } while(0) + + TSTALLOC(BSIM3DdPtr, BSIM3dNode, BSIM3dNode); + TSTALLOC(BSIM3GgPtr, BSIM3gNode, BSIM3gNode); + TSTALLOC(BSIM3SsPtr, BSIM3sNode, BSIM3sNode); + TSTALLOC(BSIM3BbPtr, BSIM3bNode, BSIM3bNode); + TSTALLOC(BSIM3DPdpPtr, BSIM3dNodePrime, BSIM3dNodePrime); + TSTALLOC(BSIM3SPspPtr, BSIM3sNodePrime, BSIM3sNodePrime); + TSTALLOC(BSIM3DdpPtr, BSIM3dNode, BSIM3dNodePrime); + TSTALLOC(BSIM3GbPtr, BSIM3gNode, BSIM3bNode); + TSTALLOC(BSIM3GdpPtr, BSIM3gNode, BSIM3dNodePrime); + TSTALLOC(BSIM3GspPtr, BSIM3gNode, BSIM3sNodePrime); + TSTALLOC(BSIM3SspPtr, BSIM3sNode, BSIM3sNodePrime); + TSTALLOC(BSIM3BdpPtr, BSIM3bNode, BSIM3dNodePrime); + TSTALLOC(BSIM3BspPtr, BSIM3bNode, BSIM3sNodePrime); + TSTALLOC(BSIM3DPspPtr, BSIM3dNodePrime, BSIM3sNodePrime); + TSTALLOC(BSIM3DPdPtr, BSIM3dNodePrime, BSIM3dNode); + TSTALLOC(BSIM3BgPtr, BSIM3bNode, BSIM3gNode); + TSTALLOC(BSIM3DPgPtr, BSIM3dNodePrime, BSIM3gNode); + TSTALLOC(BSIM3SPgPtr, BSIM3sNodePrime, BSIM3gNode); + TSTALLOC(BSIM3SPsPtr, BSIM3sNodePrime, BSIM3sNode); + TSTALLOC(BSIM3DPbPtr, BSIM3dNodePrime, BSIM3bNode); + TSTALLOC(BSIM3SPbPtr, BSIM3sNodePrime, BSIM3bNode); + TSTALLOC(BSIM3SPdpPtr, BSIM3sNodePrime, BSIM3dNodePrime); + + TSTALLOC(BSIM3QqPtr, BSIM3qNode, BSIM3qNode); + + TSTALLOC(BSIM3QdpPtr, BSIM3qNode, BSIM3dNodePrime); + TSTALLOC(BSIM3QspPtr, BSIM3qNode, BSIM3sNodePrime); + TSTALLOC(BSIM3QgPtr, BSIM3qNode, BSIM3gNode); + TSTALLOC(BSIM3QbPtr, BSIM3qNode, BSIM3bNode); + TSTALLOC(BSIM3DPqPtr, BSIM3dNodePrime, BSIM3qNode); + TSTALLOC(BSIM3SPqPtr, BSIM3sNodePrime, BSIM3qNode); + TSTALLOC(BSIM3GqPtr, BSIM3gNode, BSIM3qNode); + TSTALLOC(BSIM3BqPtr, BSIM3bNode, BSIM3qNode); + + } + } +#if 1 + InstCount = 0; + model = (BSIM3model*)inModel; + /* loop through all the BSIM3 device models + to count the number of instances */ + + for( ; model != NULL; model = BSIM3SIMDnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = BSIM3SIMDinstances(model); here != NULL ; + here=BSIM3SIMDnextInstance(here)) + { + InstCount++; + } + model->BSIM3InstCount = 0; + model->BSIM3InstanceArray = NULL; + } + InstArray = TMALLOC(BSIM3instance*, InstCount); + model = (BSIM3model*)inModel; + /* store this in the first model only */ + model->BSIM3InstCount = InstCount; + model->BSIM3InstanceArray = InstArray; + #if 0 + idx = 0; + for( ; model != NULL; model = BSIM3SIMDnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = BSIM3SIMDinstances(model); here != NULL ; + here=BSIM3SIMDnextInstance(here)) + { + InstArray[idx] = here; + idx++; + } + } + #endif + + idx=0; + int ngroups=0; + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { + BSIM3group *group; + BSIM3instance *first; + + model->groupHead=NULL; + first = BSIM3SIMDinstances(model); + while((idxInstArray=&InstArray[idx]; + group->InstArray[0] = first; + group->InstCount=0; + /* build linked list of groups */ + group->next = model->groupHead; + model->groupHead=group; + /* init the for loop below */ + here = first; first=NULL; + for (; here != NULL; here = BSIM3SIMDnextInstance(here)) + { + if((here->BSIM3nqsMod == group->InstArray[0]->BSIM3nqsMod) + && (here->BSIM3w == group->InstArray[0]->BSIM3w) + && (here->BSIM3l == group->InstArray[0]->BSIM3l) + && (here->BSIM3geo == group->InstArray[0]->BSIM3geo) + && (here->BSIM3off == group->InstArray[0]->BSIM3off) ) + { /* instance can be grouped with the current group */ + InstArray[idx++] = here; + group->InstCount++; + } + else if (first!=NULL) + first=here; /* first different instance, start from here at next while iteration */ + } + } + } + printf("BSIM3/SIMD has %d groups and %d instances total\n",ngroups, InstCount); + if (cp_getvar("no_modsimd", CP_BOOL, NULL, 0)) + { + printf("BSIM3 simd disabled at runtime\n"); + BSIM3SIMDinfo.DEVload = BSIM3SIMDload; /* use original load function */ + } + + + +#endif + return(OK); +} + +int +BSIM3SIMDunsetup( + GENmodel *inModel, + CKTcircuit *ckt) +{ + BSIM3model *model; + BSIM3instance *here; + + + for (model = (BSIM3model *)inModel; model != NULL; + model = BSIM3SIMDnextModel(model)) + { + /* free the group list */ + BSIM3group *group,*ngroup; + group=model->groupHead; + while(group) { + ngroup=group->next; + tfree(group); + group=ngroup; + } + + for (here = BSIM3SIMDinstances(model); here != NULL; + here=BSIM3SIMDnextInstance(here)) + { + if (here->BSIM3qNode > 0) + CKTdltNNum(ckt, here->BSIM3qNode); + here->BSIM3qNode = 0; + + if (here->BSIM3sNodePrime > 0 + && here->BSIM3sNodePrime != here->BSIM3sNode) + CKTdltNNum(ckt, here->BSIM3sNodePrime); + here->BSIM3sNodePrime = 0; + + if (here->BSIM3dNodePrime > 0 + && here->BSIM3dNodePrime != here->BSIM3dNode) + CKTdltNNum(ckt, here->BSIM3dNodePrime); + here->BSIM3dNodePrime = 0; + } + } + +#if 1 + model = (BSIM3model*)inModel; + tfree(model->BSIM3InstanceArray); +#endif + + + return OK; +} + + + + + + diff --git a/src/spicelib/devices/bsim3simd/b3soachk.c b/src/spicelib/devices/bsim3simd/b3soachk.c new file mode 100644 index 000000000..925fb5f68 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3soachk.c @@ -0,0 +1,341 @@ +/********** +Copyright 2013 Dietmar Warning. All rights reserved. +Author: 2013 Dietmar Warning +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/trandefs.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" +#include "ngspice/cpdefs.h" + + +int +BSIM3SIMDsoaCheck(CKTcircuit *ckt, GENmodel *inModel) +{ + BSIM3model *model = (BSIM3model *) inModel; + BSIM3instance *here; + double vgs, vgd, vgb, vds, vbs, vbd; /* actual mos voltages */ + int maxwarns; + static int warns_vgs = 0, warns_vgd = 0, warns_vgb = 0, warns_vds = 0, warns_vbs = 0, warns_vbd = 0; + + if (!ckt) { + warns_vgs = 0; + warns_vgd = 0; + warns_vgb = 0; + warns_vds = 0; + warns_vbs = 0; + warns_vbd = 0; + return OK; + } + + maxwarns = ckt->CKTsoaMaxWarns; + + for (; model; model = BSIM3SIMDnextModel(model)) { + + for (here = BSIM3SIMDinstances(model); here; here = BSIM3SIMDnextInstance(here)) { + + vgs = ckt->CKTrhsOld [here->BSIM3gNode] - + ckt->CKTrhsOld [here->BSIM3sNodePrime]; + + vgd = ckt->CKTrhsOld [here->BSIM3gNode] - + ckt->CKTrhsOld [here->BSIM3dNodePrime]; + + vgb = ckt->CKTrhsOld [here->BSIM3gNode] - + ckt->CKTrhsOld [here->BSIM3bNode]; + + vds = ckt->CKTrhsOld [here->BSIM3dNodePrime] - + ckt->CKTrhsOld [here->BSIM3sNodePrime]; + + vbs = ckt->CKTrhsOld [here->BSIM3bNode] - + ckt->CKTrhsOld [here->BSIM3sNodePrime]; + + vbd = ckt->CKTrhsOld [here->BSIM3bNode] - + ckt->CKTrhsOld [here->BSIM3dNodePrime]; + + if (!model->BSIM3vgsrMaxGiven) { + if (fabs(vgs) > model->BSIM3vgsMax) + if (warns_vgs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgs=%g has exceeded Vgs_max=%g\n", + vgs, model->BSIM3vgsMax); + warns_vgs++; + } + if (!model->BSIM3vgbMaxGiven) { + if (fabs(vgb) > model->BSIM3vgsMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgs_max=%g\n", + vgb, model->BSIM3vgsMax); + warns_vgb++; + } + } else { + if (fabs(vgb) > model->BSIM3vgbMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgb_max=%g\n", + vgb, model->BSIM3vgbMax); + warns_vgb++; + } + } + } else { + if (model->BSIM3type > 0) { + if (vgs > model->BSIM3vgsMax) + if (warns_vgs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgs=%g has exceeded Vgs_max=%g\n", + vgs, model->BSIM3vgsMax); + warns_vgs++; + } + if (-1*vgs > model->BSIM3vgsrMax) + if (warns_vgs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgs=%g has exceeded Vgsr_max=%g\n", + vgs, model->BSIM3vgsrMax); + warns_vgs++; + } + } else { + if (vgs > model->BSIM3vgsrMax) + if (warns_vgs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgs=%g has exceeded Vgsr_max=%g\n", + vgs, model->BSIM3vgsrMax); + warns_vgs++; + } + if (-1*vgs > model->BSIM3vgsMax) + if (warns_vgs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgs=%g has exceeded Vgs_max=%g\n", + vgs, model->BSIM3vgsMax); + warns_vgs++; + } + } + } + + if (!model->BSIM3vgdrMaxGiven) { + if (fabs(vgd) > model->BSIM3vgdMax) + if (warns_vgd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgd=%g has exceeded Vgd_max=%g\n", + vgd, model->BSIM3vgdMax); + warns_vgd++; + } + } else { + if (model->BSIM3type > 0) { + if (vgd > model->BSIM3vgdMax) + if (warns_vgd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgd=%g has exceeded Vgd_max=%g\n", + vgd, model->BSIM3vgdMax); + warns_vgd++; + } + if (-1*vgd > model->BSIM3vgdrMax) + if (warns_vgd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgd=%g has exceeded Vgdr_max=%g\n", + vgd, model->BSIM3vgdrMax); + warns_vgd++; + } + } else { + if (vgd > model->BSIM3vgdrMax) + if (warns_vgd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgd=%g has exceeded Vgdr_max=%g\n", + vgd, model->BSIM3vgdrMax); + warns_vgd++; + } + if (-1*vgd > model->BSIM3vgdMax) + if (warns_vgd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgd=%g has exceeded Vgd_max=%g\n", + vgd, model->BSIM3vgdMax); + warns_vgd++; + } + } + } + + if (fabs(vds) > model->BSIM3vdsMax) + if (warns_vds < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vds=%g has exceeded Vds_max=%g\n", + vds, model->BSIM3vdsMax); + warns_vds++; + } + + if (!model->BSIM3vgbrMaxGiven) { + if (fabs(vgb) > model->BSIM3vgbMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgb_max=%g\n", + vgb, model->BSIM3vgbMax); + warns_vgb++; + } + } else { + if (model->BSIM3type > 0) { + if (vgb > model->BSIM3vgbMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgb_max=%g\n", + vgb, model->BSIM3vgbMax); + warns_vgb++; + } + if (-1*vgb > model->BSIM3vgbrMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgbr_max=%g\n", + vgb, model->BSIM3vgbrMax); + warns_vgb++; + } + } else { + if (vgb > model->BSIM3vgbrMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgbr_max=%g\n", + vgb, model->BSIM3vgbrMax); + warns_vgb++; + } + if (-1*vgb > model->BSIM3vgbMax) + if (warns_vgb < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vgb=%g has exceeded Vgb_max=%g\n", + vgb, model->BSIM3vgbMax); + warns_vgb++; + } + } + } + + if (!model->BSIM3vbsrMaxGiven) { + if (!model->BSIM3vbsMaxGiven) { + if (fabs(vbs) > model->BSIM3vbdMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbd_max=%g\n", + vbs, model->BSIM3vbdMax); + warns_vbs++; + } + } else { + if (fabs(vbs) > model->BSIM3vbsMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbs_max=%g\n", + vbs, model->BSIM3vbsMax); + warns_vbs++; + } + } + } else { + if (!model->BSIM3vbsMaxGiven) { + if (model->BSIM3type > 0) { + if (vbs > model->BSIM3vbdMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbd_max=%g\n", + vbs, model->BSIM3vbdMax); + warns_vbs++; + } + if (-1*vbs > model->BSIM3vbsrMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbsr_max=%g\n", + vbs, model->BSIM3vbsrMax); + warns_vbs++; + } + } else { + if (vbs > model->BSIM3vbsrMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbsr_max=%g\n", + vbs, model->BSIM3vbsrMax); + warns_vbs++; + } + if (-1*vbs > model->BSIM3vbdMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbd_max=%g\n", + vbs, model->BSIM3vbdMax); + warns_vbs++; + } + } + } else { + if (model->BSIM3type > 0) { + if (vbs > model->BSIM3vbsMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbs_max=%g\n", + vbs, model->BSIM3vbsMax); + warns_vbs++; + } + if (-1*vbs > model->BSIM3vbsrMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbsr_max=%g\n", + vbs, model->BSIM3vbsrMax); + warns_vbs++; + } + } else { + if (vbs > model->BSIM3vbsrMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbsr_max=%g\n", + vbs, model->BSIM3vbsrMax); + warns_vbs++; + } + if (-1*vbs > model->BSIM3vbsMax) + if (warns_vbs < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbs=%g has exceeded Vbs_max=%g\n", + vbs, model->BSIM3vbsMax); + warns_vbs++; + } + } + } + } + + if (!model->BSIM3vbdrMaxGiven) { + if (fabs(vbd) > model->BSIM3vbdMax) + if (warns_vbd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbd=%g has exceeded Vbd_max=%g\n", + vbd, model->BSIM3vbdMax); + warns_vbd++; + } + } else { + if (model->BSIM3type > 0) { + if (vbd > model->BSIM3vbdMax) + if (warns_vbd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbd=%g has exceeded Vbd_max=%g\n", + vbd, model->BSIM3vbdMax); + warns_vbd++; + } + if (-1*vbd > model->BSIM3vbdrMax) + if (warns_vbd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbd=%g has exceeded Vbdr_max=%g\n", + vbd, model->BSIM3vbdrMax); + warns_vbd++; + } + } else { + if (vbd > model->BSIM3vbdrMax) + if (warns_vbd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbd=%g has exceeded Vbdr_max=%g\n", + vbd, model->BSIM3vbdrMax); + warns_vbd++; + } + if (-1*vbd > model->BSIM3vbdMax) + if (warns_vbd < maxwarns) { + soa_printf(ckt, (GENinstance*) here, + "Vbd=%g has exceeded Vbd_max=%g\n", + vbd, model->BSIM3vbdMax); + warns_vbd++; + } + } + } + + } + } + + return OK; +} diff --git a/src/spicelib/devices/bsim3simd/b3temp.c b/src/spicelib/devices/bsim3simd/b3temp.c new file mode 100644 index 000000000..afaef9f29 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3temp.c @@ -0,0 +1,894 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * 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: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +/* Lmin, Lmax, Wmin, Wmax */ + +#include "ngspice/ngspice.h" +#include "ngspice/smpdefs.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/const.h" +#include "ngspice/sperror.h" +#include "ngspice/devdefs.h" +#include "ngspice/suffix.h" + +#define Kb 1.3806226e-23 +#define KboQ 8.617087e-5 /* Kb / q where q = 1.60219e-19 */ +#define EPSOX 3.453133e-11 +#define EPSSI 1.03594e-10 +#define PI 3.141592654 +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define Charge_q 1.60219e-19 + +/* ARGSUSED */ +int +BSIM3SIMDtemp( +GENmodel *inModel, +CKTcircuit *ckt) +{ +BSIM3model *model = (BSIM3model*) inModel; +BSIM3instance *here; +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, error; + +/* loop through all the BSIM3 device models */ + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { 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->BSIM3sidewallJctPotential < 0.1) + { 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"); + } + + struct bsim3SizeDependParam *p = model->pSizeDependParamKnot; + while (p) { + struct bsim3SizeDependParam *next_p = p->pNext; + FREE(p); + p = next_p; + } + model->pSizeDependParamKnot = NULL; + pLastKnot = NULL; + + Tnom = model->BSIM3tnom; + TRatio = Temp / Tnom; + + 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) + * 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 (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"); + } + 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"); + } + 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"); + } + + model->BSIM3PhiB = model->BSIM3bulkJctPotential + - 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->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->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"); + } + /* End of junction capacitance */ + + /* loop through all the instances of the model */ + /* MCJ: Length and Width not initialized */ + for (here = BSIM3SIMDinstances(model); here != NULL; + here = BSIM3SIMDnextInstance(here)) + { + 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 = 0; + here->pParam = pSizeDependParamKnot; + pParam = here->pParam; /*bug-fix */ + } + else + { pLastKnot = pSizeDependParamKnot; + pSizeDependParamKnot = pSizeDependParamKnot->pNext; + } + } + + if (Size_Not_Found) + { pParam = TMALLOC(struct bsim3SizeDependParam, 1); + if (pLastKnot == NULL) + model->pSizeDependParamKnot = pParam; + else + pLastKnot->pNext = pParam; + pParam->pNext = NULL; + here->pParam = pParam; + + 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 + + model->BSIM3Lwl / (T0 * T1); + pParam->BSIM3dl = model->BSIM3Lint + tmp1; + tmp2 = model->BSIM3Llc / T0 + model->BSIM3Lwc / T1 + + model->BSIM3Lwlc / (T0 * T1); + pParam->BSIM3dlc = model->BSIM3dlc + tmp2; + + T2 = pow(Ldrn, model->BSIM3Wln); + T3 = pow(Wdrn, model->BSIM3Wwn); + tmp1 = model->BSIM3Wl / T2 + model->BSIM3Ww / T3 + + model->BSIM3Wwl / (T2 * T3); + pParam->BSIM3dw = model->BSIM3Wint + tmp1; + tmp2 = model->BSIM3Wlc / T2 + model->BSIM3Wwc / T3 + + model->BSIM3Wwlc / (T2 * T3); + pParam->BSIM3dwc = model->BSIM3dwc + tmp2; + + pParam->BSIM3leff = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dl; + if (pParam->BSIM3leff <= 0.0) + { + SPfrontEnd->IFerrorf (ERR_FATAL, + "BSIM3: mosfet %s, model %s: Effective channel length <= 0", + model->BSIM3modName, here->BSIM3name); + return(E_BADPARM); + } + + pParam->BSIM3weff = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dw; + if (pParam->BSIM3weff <= 0.0) + { + SPfrontEnd->IFerrorf (ERR_FATAL, + "BSIM3: mosfet %s, model %s: Effective channel width <= 0", + model->BSIM3modName, here->BSIM3name); + return(E_BADPARM); + } + + pParam->BSIM3leffCV = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dlc; + if (pParam->BSIM3leffCV <= 0.0) + { + SPfrontEnd->IFerrorf (ERR_FATAL, + "BSIM3: mosfet %s, model %s: Effective channel length for C-V <= 0", + model->BSIM3modName, here->BSIM3name); + return(E_BADPARM); + } + + pParam->BSIM3weffCV = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dwc; + if (pParam->BSIM3weffCV <= 0.0) + { + SPfrontEnd->IFerrorf (ERR_FATAL, + "BSIM3: mosfet %s, model %s: Effective channel width for C-V <= 0", + model->BSIM3modName, here->BSIM3name); + return(E_BADPARM); + } + + + 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->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->BSIM3acde = model->BSIM3acde + + model->BSIM3lacde * Inv_L + + model->BSIM3wacde * Inv_W + + model->BSIM3pacde * Inv_LW; + pParam->BSIM3moin = model->BSIM3moin + + model->BSIM3lmoin * Inv_L + + model->BSIM3wmoin * Inv_W + + model->BSIM3pmoin * Inv_LW; + pParam->BSIM3noff = model->BSIM3noff + + model->BSIM3lnoff * Inv_L + + model->BSIM3wnoff * Inv_W + + model->BSIM3pnoff * Inv_LW; + pParam->BSIM3voffcv = model->BSIM3voffcv + + model->BSIM3lvoffcv * Inv_L + + model->BSIM3wvoffcv * Inv_W + + model->BSIM3pvoffcv * Inv_LW; + + pParam->BSIM3abulkCVfactor = 1.0 + pow((pParam->BSIM3clc + / 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) + 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(pParam->BSIM3weff * 1E6, pParam->BSIM3wr); + + if (BSIM3SIMDcheckModel(model, here, ckt)) + { + SPfrontEnd->IFerrorf (ERR_FATAL, "Fatal error(s) detected during BSIM3V3.3 parameter checking for %s in model %s", model->BSIM3modName, here->BSIM3name); + return(E_BADPARM); + } + + pParam->BSIM3cgdo = (model->BSIM3cgdo + pParam->BSIM3cf) + * pParam->BSIM3weffCV; + pParam->BSIM3cgso = (model->BSIM3cgso + pParam->BSIM3cf) + * pParam->BSIM3weffCV; + pParam->BSIM3cgbo = model->BSIM3cgbo * pParam->BSIM3leffCV; + + T0 = pParam->BSIM3leffCV * pParam->BSIM3leffCV; + pParam->BSIM3tconst = pParam->BSIM3u0temp * pParam->BSIM3elm / (model->BSIM3cox + * pParam->BSIM3weffCV * pParam->BSIM3leffCV * T0); + + if (!model->BSIM3npeakGiven && model->BSIM3gamma1Given) + { T0 = pParam->BSIM3gamma1 * model->BSIM3cox; + pParam->BSIM3npeak = 3.021E22 * T0 * T0; + } + + pParam->BSIM3phi = 2.0 * Vtm0 + * log(pParam->BSIM3npeak / ni); + + 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->BSIM3sqrtXdep0 = sqrt(pParam->BSIM3Xdep0); + pParam->BSIM3litl = sqrt(3.0 * pParam->BSIM3xj + * model->BSIM3tox); + pParam->BSIM3vbi = Vtm0 * log(1.0e20 + * pParam->BSIM3npeak / (ni * ni)); + pParam->BSIM3cdep0 = sqrt(Charge_q * EPSSI + * pParam->BSIM3npeak * 1.0e6 / 2.0 + / pParam->BSIM3phi); + + pParam->BSIM3ldeb = sqrt(EPSSI * Vtm0 / (Charge_q + * pParam->BSIM3npeak * 1.0e6)) / 3.0; + pParam->BSIM3acde *= pow((pParam->BSIM3npeak / 2.0e16), -0.25); + + + if (model->BSIM3k1Given || model->BSIM3k2Given) + { if (!model->BSIM3k1Given) + { + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ + fprintf(stdout, "Warning: k1 should be specified with k2.\n"); + pParam->BSIM3k1 = 0.53; + } + if (!model->BSIM3k2Given) + { + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) /* don't print in sensitivity */ + fprintf(stdout, "Warning: k2 should be specified with k1.\n"); + pParam->BSIM3k2 = -0.0186; + } + if ((!ckt->CKTcurJob) || (ckt->CKTcurJob->JOBtype < 9)) { /* don't print in sensitivity */ + if (model->BSIM3nsubGiven) + fprintf(stdout, "Warning: nsub is ignored because k1 or k2 is given.\n"); + if (model->BSIM3xtGiven) + fprintf(stdout, "Warning: xt is ignored because k1 or k2 is given.\n"); + if (model->BSIM3vbxGiven) + fprintf(stdout, "Warning: vbx is ignored because k1 or k2 is given.\n"); + if (model->BSIM3gamma1Given) + fprintf(stdout, "Warning: gamma1 is ignored because k1 or k2 is given.\n"); + if (model->BSIM3gamma2Given) + fprintf(stdout, "Warning: gamma2 is ignored because k1 or k2 is given.\n"); + } + } + else + { 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->BSIM3vbm = -pParam->BSIM3vbm; + + if (!model->BSIM3gamma1Given) + pParam->BSIM3gamma1 = 5.753e-12 + * sqrt(pParam->BSIM3npeak) + / model->BSIM3cox; + if (!model->BSIM3gamma2Given) + pParam->BSIM3gamma2 = 5.753e-12 + * sqrt(pParam->BSIM3nsub) + / model->BSIM3cox; + + T0 = pParam->BSIM3gamma1 - pParam->BSIM3gamma2; + T1 = sqrt(pParam->BSIM3phi - pParam->BSIM3vbx) + - pParam->BSIM3sqrtPhi; + T2 = sqrt(pParam->BSIM3phi * (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); + } + + 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 (!model->BSIM3vfbGiven) + { if (model->BSIM3vth0Given) + { pParam->BSIM3vfb = model->BSIM3type * pParam->BSIM3vth0 + - pParam->BSIM3phi - pParam->BSIM3k1 + * pParam->BSIM3sqrtPhi; + } + else + { pParam->BSIM3vfb = -1.0; + } + } + if (!model->BSIM3vth0Given) + { pParam->BSIM3vth0 = model->BSIM3type * (pParam->BSIM3vfb + + pParam->BSIM3phi + pParam->BSIM3k1 + * pParam->BSIM3sqrtPhi); + } + + pParam->BSIM3k1ox = pParam->BSIM3k1 * model->BSIM3tox + / model->BSIM3toxm; + pParam->BSIM3k2ox = pParam->BSIM3k2 * model->BSIM3tox + / model->BSIM3toxm; + + T1 = sqrt(EPSSI / EPSOX * model->BSIM3tox + * 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; + + tmp = sqrt(pParam->BSIM3Xdep0); + tmp1 = pParam->BSIM3vbi - pParam->BSIM3phi; + tmp2 = model->BSIM3factor1 * tmp; + + T0 = -0.5 * pParam->BSIM3dvt1w * pParam->BSIM3weff + * pParam->BSIM3leff / 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->BSIM3dvt0w * T2; + T2 = T0 * tmp1; + + T0 = -0.5 * pParam->BSIM3dvt1 * pParam->BSIM3leff / 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->BSIM3dvt0 * T3 * tmp1; + + T4 = model->BSIM3tox * pParam->BSIM3phi + / (pParam->BSIM3weff + pParam->BSIM3w0); + + T0 = sqrt(1.0 + pParam->BSIM3nlx / pParam->BSIM3leff); + T5 = pParam->BSIM3k1ox * (T0 - 1.0) * pParam->BSIM3sqrtPhi + + (pParam->BSIM3kt1 + pParam->BSIM3kt1l / pParam->BSIM3leff) + * (TRatio - 1.0); + + tmp3 = model->BSIM3type * pParam->BSIM3vth0 + - T2 - T3 + pParam->BSIM3k3 * T4 + T5; + pParam->BSIM3vfbzb = tmp3 - pParam->BSIM3phi - pParam->BSIM3k1 + * pParam->BSIM3sqrtPhi; + /* 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 */ + /* ACM model */ + + double drainResistance, sourceResistance; + + if (model->BSIM3acmMod == 0) + { + drainResistance = model->BSIM3sheetResistance + * here->BSIM3drainSquares; + sourceResistance = 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, + &drainResistance, + &sourceResistance + ); + if (error) + return(error); + } + if (drainResistance > 0.0) + here->BSIM3drainConductance = 1.0 / drainResistance; + else + here->BSIM3drainConductance = 0.0; + + if (sourceResistance > 0.0) + here->BSIM3sourceConductance = 1.0 / sourceResistance; + else + here->BSIM3sourceConductance = 0.0; + + here->BSIM3cgso = pParam->BSIM3cgso; + here->BSIM3cgdo = pParam->BSIM3cgdo; + + 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) && (model->BSIM3ijth > 0.0)) + { here->BSIM3vjsm = Nvtm * log(model->BSIM3ijth + / SourceSatCurrent + 1.0); + here->BSIM3IsEvjsm = SourceSatCurrent * exp(here->BSIM3vjsm + / Nvtm); + } + + 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) && (model->BSIM3ijth > 0.0)) + { here->BSIM3vjdm = Nvtm * log(model->BSIM3ijth + / DrainSatCurrent + 1.0); + here->BSIM3IsEvjdm = DrainSatCurrent * exp(here->BSIM3vjdm + / Nvtm); + } + } + } + return(OK); +} + diff --git a/src/spicelib/devices/bsim3simd/b3trunc.c b/src/spicelib/devices/bsim3simd/b3trunc.c new file mode 100644 index 000000000..03b267c5a --- /dev/null +++ b/src/spicelib/devices/bsim3simd/b3trunc.c @@ -0,0 +1,50 @@ +/**** BSIM3v3.3.0, Released by Xuemei Xi 07/29/2005 ****/ + +/********** + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b3trunc.c of BSIM3v3.3.0 + * Author: 1995 Min-Chie Jeng and Mansun Chan. + * Author: 1997-1999 Weidong Liu. + * Author: 2001 Xuemei Xi + **********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "bsim3def.h" +#include "ngspice/sperror.h" +#include "ngspice/suffix.h" + + +int +BSIM3SIMDtrunc( +GENmodel *inModel, +CKTcircuit *ckt, +double *timeStep) +{ +BSIM3model *model = (BSIM3model*)inModel; +BSIM3instance *here; + +#ifdef STEPDEBUG + double debugtemp; +#endif /* STEPDEBUG */ + + for (; model != NULL; model = BSIM3SIMDnextModel(model)) + { for (here = BSIM3SIMDinstances(model); here != NULL; + here = BSIM3SIMDnextInstance(here)) + { +#ifdef STEPDEBUG + debugtemp = *timeStep; +#endif /* STEPDEBUG */ + CKTterr(here->BSIM3qb,ckt,timeStep); + CKTterr(here->BSIM3qg,ckt,timeStep); + CKTterr(here->BSIM3qd,ckt,timeStep); +#ifdef STEPDEBUG + if(debugtemp != *timeStep) + { printf("device %s reduces step from %g to %g\n", + here->BSIM3name,debugtemp,*timeStep); + } +#endif /* STEPDEBUG */ + } + } + return(OK); +} diff --git a/src/spicelib/devices/bsim3simd/bsim3def.h b/src/spicelib/devices/bsim3simd/bsim3def.h new file mode 100644 index 000000000..a6f1a1863 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/bsim3def.h @@ -0,0 +1,1949 @@ +/********** +Copyright 2004 Regents of the University of California. All rights reserved. +Author: 1995 Min-Chie Jeng and Mansun Chan. +Author: 1997-1999 Weidong Liu. +Author: 2001- Xuemei Xi +**** OpenMP support for ngspice by Holger Vogt 06/28/2010 **** +Modified by Florian Ballenegger 2020 (for SIMD evaluation) +File: bsim3def.h +**********/ + +#ifndef BSIM3SIMD +#define BSIM3SIMD + +#include "ngspice/ifsim.h" +#include "ngspice/gendefs.h" +#include "ngspice/cktdefs.h" +#include "ngspice/complex.h" +#include "ngspice/noisedef.h" + +#include "ngspice/SIMD/simddef.h" + +#define OMP_EFFMEM + +typedef struct sBSIM3instance +{ + + struct GENinstance gen; + +#define BSIM3SIMDmodPtr(inst) ((struct sBSIM3model *)((inst)->gen.GENmodPtr)) +#define BSIM3SIMDnextInstance(inst) ((struct sBSIM3instance *)((inst)->gen.GENnextInstance)) +#define BSIM3name gen.GENname +#define BSIM3states gen.GENstate + + const int BSIM3dNode; + const int BSIM3gNode; + const int BSIM3sNode; + const int BSIM3bNode; + int BSIM3dNodePrime; + int BSIM3sNodePrime; + int BSIM3qNode; /* MCJ */ + + /* MCJ */ + double BSIM3ueff; + double BSIM3thetavth; + double BSIM3von; + double BSIM3vdsat; + double BSIM3cgdo; + double BSIM3cgso; + double BSIM3vjsm; + double BSIM3IsEvjsm; + double BSIM3vjdm; + double BSIM3IsEvjdm; + + double BSIM3l; + double BSIM3w; + double BSIM3m; + double BSIM3drainArea; + double BSIM3sourceArea; + double BSIM3drainSquares; + double BSIM3sourceSquares; + double BSIM3drainPerimeter; + double BSIM3sourcePerimeter; + double BSIM3sourceConductance; + double BSIM3drainConductance; + double BSIM3delvto; + double BSIM3mulu0; + double BSIM3vth0; + double BSIM3vfb; + double BSIM3vfbzb; + double BSIM3u0temp; + double BSIM3tconst; + + double BSIM3icVBS; + double BSIM3icVDS; + double BSIM3icVGS; + int BSIM3off; + int BSIM3mode; + int BSIM3nqsMod; + int BSIM3acnqsMod; + int BSIM3geo; + + /* OP point */ + double BSIM3qinv; + double BSIM3cd; + double BSIM3cbs; + double BSIM3cbd; + double BSIM3csub; + double BSIM3gm; + double BSIM3gds; + double BSIM3gmbs; + double BSIM3gbd; + double BSIM3gbs; + + double BSIM3gbbs; + double BSIM3gbgs; + double BSIM3gbds; + + double BSIM3cggb; + double BSIM3cgdb; + double BSIM3cgsb; + double BSIM3cbgb; + double BSIM3cbdb; + double BSIM3cbsb; + double BSIM3cdgb; + double BSIM3cddb; + double BSIM3cdsb; + double BSIM3capbd; + double BSIM3capbs; + + double BSIM3cqgb; + double BSIM3cqdb; + double BSIM3cqsb; + double BSIM3cqbb; + + double BSIM3qgate; + double BSIM3qbulk; + double BSIM3qdrn; + + double BSIM3gtau; + double BSIM3gtg; + double BSIM3gtd; + double BSIM3gts; + double BSIM3gtb; + double BSIM3rds; /* Noise bugfix */ + double BSIM3Vgsteff; + double BSIM3Vdseff; + double BSIM3Abulk; + double BSIM3AbovVgst2Vtm; + double BSIM3taunet; + + struct bsim3SizeDependParam *pParam; + + unsigned BSIM3lGiven :1; + unsigned BSIM3wGiven :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; + unsigned BSIM3icVDSGiven :1; + unsigned BSIM3icVGSGiven :1; + unsigned BSIM3nqsModGiven :1; + unsigned BSIM3acnqsModGiven :1; + unsigned BSIM3geoGiven :1; + + double *BSIM3DdPtr; + double *BSIM3GgPtr; + double *BSIM3SsPtr; + double *BSIM3BbPtr; + double *BSIM3DPdpPtr; + double *BSIM3SPspPtr; + double *BSIM3DdpPtr; + double *BSIM3GbPtr; + double *BSIM3GdpPtr; + double *BSIM3GspPtr; + double *BSIM3SspPtr; + double *BSIM3BdpPtr; + double *BSIM3BspPtr; + double *BSIM3DPspPtr; + double *BSIM3DPdPtr; + double *BSIM3BgPtr; + double *BSIM3DPgPtr; + double *BSIM3SPgPtr; + double *BSIM3SPsPtr; + double *BSIM3DPbPtr; + double *BSIM3SPbPtr; + double *BSIM3SPdpPtr; + + double *BSIM3QqPtr; + double *BSIM3QdpPtr; + double *BSIM3QgPtr; + double *BSIM3QspPtr; + double *BSIM3QbPtr; + double *BSIM3DPqPtr; + double *BSIM3GqPtr; + double *BSIM3SPqPtr; + double *BSIM3BqPtr; + +#ifdef USE_OMP + /* store here values calculated before SIMD evaluation really start */ + double BSIM3SIMDvbs; + double BSIM3SIMDvgs; + double BSIM3SIMDvds; + double BSIM3SIMDqdef; + double BSIM3SIMDcdhat; + double BSIM3SIMDcbhat; + int BSIM3SIMDCheck; + + /* per instance storage of results, to update matrix at a later stge */ + double BSIM3rhsG; + double BSIM3rhsB; + double BSIM3rhsD; + double BSIM3rhsS; + #ifndef OMP_EFFMEM + double BSIM3rhsQ; + #endif + double BSIM3DdPt; + double BSIM3GgPt; + double BSIM3SsPt; + double BSIM3BbPt; + double BSIM3DPdpPt; + double BSIM3SPspPt; + double BSIM3DdpPt; + double BSIM3GbPt; + double BSIM3GdpPt; + double BSIM3GspPt; + double BSIM3SspPt; + double BSIM3BdpPt; + double BSIM3BspPt; + double BSIM3DPspPt; + double BSIM3DPdPt; + double BSIM3BgPt; + double BSIM3DPgPt; + double BSIM3SPgPt; + double BSIM3SPsPt; + double BSIM3DPbPt; + double BSIM3SPbPt; + double BSIM3SPdpPt; + + #ifndef OMP_EFFMEM + /* don't need intermediate NQS variable as those entry + are already private in the matrix */ + double BSIM3QqPt; + double BSIM3QdpPt; + double BSIM3QgPt; + double BSIM3QspPt; + double BSIM3QbPt; + double BSIM3DPqPt; + double BSIM3GqPt; + double BSIM3SPqPt; + double BSIM3BqPt; + #endif +#endif + +#define BSIM3vbd BSIM3states+ 0 +#define BSIM3vbs BSIM3states+ 1 +#define BSIM3vgs BSIM3states+ 2 +#define BSIM3vds BSIM3states+ 3 + +#define BSIM3qb BSIM3states+ 4 +#define BSIM3cqb BSIM3states+ 5 +#define BSIM3qg BSIM3states+ 6 +#define BSIM3cqg BSIM3states+ 7 +#define BSIM3qd BSIM3states+ 8 +#define BSIM3cqd BSIM3states+ 9 + +#define BSIM3qbs BSIM3states+ 10 +#define BSIM3qbd BSIM3states+ 11 + +#define BSIM3qcheq BSIM3states+ 12 +#define BSIM3cqcheq BSIM3states+ 13 +#define BSIM3qcdump BSIM3states+ 14 +#define BSIM3cqcdump BSIM3states+ 15 + +#define BSIM3qdef BSIM3states+ 16 + +#define BSIM3numStates 17 + + +/* indices to the array of BSIM3 NOISE SOURCES */ + +#define BSIM3RDNOIZ 0 +#define BSIM3RSNOIZ 1 +#define BSIM3IDNOIZ 2 +#define BSIM3FLNOIZ 3 +#define BSIM3TOTNOIZ 4 + +#define BSIM3NSRCS 5 /* the number of BSIM3 MOSFET noise sources */ + +#ifndef NONOISE + double BSIM3nVar[NSTATVARS][BSIM3NSRCS]; +#else /* NONOISE */ + double **BSIM3nVar; +#endif /* NONOISE */ + +} BSIM3instance ; + +struct bsim3SizeDependParam +{ + double Width; + double Length; + + 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 BSIM3nsub; + double BSIM3npeak; + double BSIM3ngate; + double BSIM3gamma1; + double BSIM3gamma2; + double BSIM3vbx; + double BSIM3vbi; + double BSIM3vbm; + double BSIM3vbsc; + double BSIM3xt; + double BSIM3phi; + double BSIM3litl; + double BSIM3k1; + double BSIM3kt1; + double BSIM3kt1l; + double BSIM3kt2; + double BSIM3k2; + double BSIM3k3; + double BSIM3k3b; + double BSIM3w0; + double BSIM3nlx; + double BSIM3dvt0; + double BSIM3dvt1; + double BSIM3dvt2; + double BSIM3dvt0w; + double BSIM3dvt1w; + double BSIM3dvt2w; + double BSIM3drout; + double BSIM3dsub; + double BSIM3vth0; + double BSIM3ua; + double BSIM3ua1; + double BSIM3ub; + double BSIM3ub1; + double BSIM3uc; + double BSIM3uc1; + double BSIM3u0; + double BSIM3ute; + 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 BSIM3wr; + double BSIM3dwg; + double BSIM3dwb; + double BSIM3b0; + double BSIM3b1; + double BSIM3alpha0; + double BSIM3alpha1; + double BSIM3beta0; + + + /* CV model */ + double BSIM3elm; + double BSIM3cgsl; + double BSIM3cgdl; + double BSIM3ckappa; + double BSIM3cf; + double BSIM3clc; + double BSIM3cle; + double BSIM3vfbcv; + double BSIM3noff; + double BSIM3voffcv; + double BSIM3acde; + double BSIM3moin; + + +/* Pre-calculated constants */ + + double BSIM3dw; + double BSIM3dl; + double BSIM3leff; + double BSIM3weff; + + double BSIM3dwc; + double BSIM3dlc; + double BSIM3leffCV; + double BSIM3weffCV; + double BSIM3abulkCVfactor; + double BSIM3cgso; + double BSIM3cgdo; + double BSIM3cgbo; + double BSIM3tconst; + + double BSIM3u0temp; + double BSIM3vsattemp; + double BSIM3sqrtPhi; + double BSIM3phis3; + double BSIM3Xdep0; + double BSIM3sqrtXdep0; + double BSIM3theta0vb0; + double BSIM3thetaRout; + + double BSIM3cof1; + double BSIM3cof2; + double BSIM3cof3; + double BSIM3cof4; + double BSIM3cdep0; + double BSIM3vfbzb; + double BSIM3ldeb; + double BSIM3k1ox; + double BSIM3k2ox; + + struct bsim3SizeDependParam *pNext; +}; + +/* Group by same pParam, nqsMode, geo, off for more efficient SIMD processing */ +typedef struct sBSIM3group { + int InstCount; + int EvalCount; + int SimdCount; + BSIM3instance** InstArray; /* actually sub-array of one allocated array globally */ + struct sBSIM3group* next; +} BSIM3group; + +typedef struct sBSIM3model +{ + + struct GENmodel gen; + +#define BSIM3modType gen.GENmodType +#define BSIM3SIMDnextModel(inst) ((struct sBSIM3model *)((inst)->gen.GENnextModel)) +#define BSIM3SIMDinstances(inst) ((BSIM3instance *)((inst)->gen.GENinstances)) +#define BSIM3modName gen.GENmodName + + int BSIM3type; + + int BSIM3mobMod; + int BSIM3capMod; + int BSIM3acmMod; + int BSIM3calcacm; + int BSIM3noiMod; + int BSIM3nqsMod; + int BSIM3acnqsMod; + int BSIM3binUnit; + int BSIM3paramChk; + char *BSIM3version; + double BSIM3tox; + double BSIM3toxm; + 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 BSIM3nsub; + double BSIM3npeak; + double BSIM3ngate; + double BSIM3gamma1; + double BSIM3gamma2; + double BSIM3vbx; + double BSIM3vbm; + double BSIM3xt; + double BSIM3k1; + double BSIM3kt1; + double BSIM3kt1l; + double BSIM3kt2; + double BSIM3k2; + double BSIM3k3; + double BSIM3k3b; + double BSIM3w0; + double BSIM3nlx; + double BSIM3dvt0; + double BSIM3dvt1; + double BSIM3dvt2; + double BSIM3dvt0w; + double BSIM3dvt1w; + double BSIM3dvt2w; + double BSIM3drout; + double BSIM3dsub; + double BSIM3vth0; + double BSIM3ua; + double BSIM3ua1; + double BSIM3ub; + double BSIM3ub1; + double BSIM3uc; + double BSIM3uc1; + double BSIM3u0; + double BSIM3ute; + double BSIM3voff; + double BSIM3delta; + double BSIM3rdsw; + 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; + double BSIM3b0; + double BSIM3b1; + double BSIM3alpha0; + double BSIM3alpha1; + double BSIM3beta0; + double BSIM3ijth; + double BSIM3vfb; + + /* CV model */ + double BSIM3elm; + double BSIM3cgsl; + double BSIM3cgdl; + double BSIM3ckappa; + double BSIM3cf; + double BSIM3vfbcv; + double BSIM3clc; + double BSIM3cle; + double BSIM3dwc; + double BSIM3dlc; + double BSIM3noff; + double BSIM3voffcv; + double BSIM3acde; + double BSIM3moin; + double BSIM3tcj; + double BSIM3tcjsw; + double BSIM3tcjswg; + double BSIM3tpb; + 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 BSIM3lxj; + 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 BSIM3lk1; + double BSIM3lkt1; + double BSIM3lkt1l; + double BSIM3lkt2; + double BSIM3lk2; + double BSIM3lk3; + double BSIM3lk3b; + double BSIM3lw0; + double BSIM3lnlx; + double BSIM3ldvt0; + double BSIM3ldvt1; + double BSIM3ldvt2; + double BSIM3ldvt0w; + double BSIM3ldvt1w; + double BSIM3ldvt2w; + double BSIM3ldrout; + double BSIM3ldsub; + double BSIM3lvth0; + double BSIM3lua; + double BSIM3lua1; + double BSIM3lub; + double BSIM3lub1; + double BSIM3luc; + double BSIM3luc1; + double BSIM3lu0; + double BSIM3lute; + double BSIM3lvoff; + double BSIM3ldelta; + double BSIM3lrdsw; + double BSIM3lprwg; + double BSIM3lprwb; + double BSIM3lprt; + double BSIM3leta0; + double BSIM3letab; + double BSIM3lpclm; + double BSIM3lpdibl1; + double BSIM3lpdibl2; + double BSIM3lpdiblb; + double BSIM3lpscbe1; + double BSIM3lpscbe2; + double BSIM3lpvag; + double BSIM3lwr; + double BSIM3ldwg; + double BSIM3ldwb; + double BSIM3lb0; + double BSIM3lb1; + double BSIM3lalpha0; + double BSIM3lalpha1; + double BSIM3lbeta0; + double BSIM3lvfb; + + /* CV model */ + double BSIM3lelm; + double BSIM3lcgsl; + double BSIM3lcgdl; + double BSIM3lckappa; + double BSIM3lcf; + double BSIM3lclc; + double BSIM3lcle; + double BSIM3lvfbcv; + double BSIM3lnoff; + double BSIM3lvoffcv; + double BSIM3lacde; + double BSIM3lmoin; + + /* Width Dependence */ + 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 BSIM3wnsub; + double BSIM3wnpeak; + double BSIM3wngate; + double BSIM3wgamma1; + double BSIM3wgamma2; + double BSIM3wvbx; + double BSIM3wvbm; + double BSIM3wxt; + double BSIM3wk1; + double BSIM3wkt1; + double BSIM3wkt1l; + double BSIM3wkt2; + double BSIM3wk2; + double BSIM3wk3; + double BSIM3wk3b; + double BSIM3ww0; + double BSIM3wnlx; + double BSIM3wdvt0; + double BSIM3wdvt1; + double BSIM3wdvt2; + double BSIM3wdvt0w; + double BSIM3wdvt1w; + double BSIM3wdvt2w; + double BSIM3wdrout; + double BSIM3wdsub; + double BSIM3wvth0; + double BSIM3wua; + double BSIM3wua1; + double BSIM3wub; + double BSIM3wub1; + double BSIM3wuc; + double BSIM3wuc1; + double BSIM3wu0; + double BSIM3wute; + double BSIM3wvoff; + double BSIM3wdelta; + double BSIM3wrdsw; + double BSIM3wprwg; + double BSIM3wprwb; + double BSIM3wprt; + double BSIM3weta0; + double BSIM3wetab; + double BSIM3wpclm; + double BSIM3wpdibl1; + double BSIM3wpdibl2; + double BSIM3wpdiblb; + double BSIM3wpscbe1; + double BSIM3wpscbe2; + double BSIM3wpvag; + double BSIM3wwr; + double BSIM3wdwg; + double BSIM3wdwb; + double BSIM3wb0; + double BSIM3wb1; + double BSIM3walpha0; + double BSIM3walpha1; + double BSIM3wbeta0; + double BSIM3wvfb; + + /* CV model */ + double BSIM3welm; + double BSIM3wcgsl; + double BSIM3wcgdl; + double BSIM3wckappa; + double BSIM3wcf; + double BSIM3wclc; + double BSIM3wcle; + double BSIM3wvfbcv; + double BSIM3wnoff; + double BSIM3wvoffcv; + double BSIM3wacde; + double BSIM3wmoin; + + /* Cross-term Dependence */ + 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 BSIM3pnsub; + double BSIM3pnpeak; + double BSIM3pngate; + double BSIM3pgamma1; + double BSIM3pgamma2; + double BSIM3pvbx; + double BSIM3pvbm; + double BSIM3pxt; + double BSIM3pk1; + double BSIM3pkt1; + double BSIM3pkt1l; + double BSIM3pkt2; + double BSIM3pk2; + double BSIM3pk3; + double BSIM3pk3b; + double BSIM3pw0; + double BSIM3pnlx; + double BSIM3pdvt0; + double BSIM3pdvt1; + double BSIM3pdvt2; + double BSIM3pdvt0w; + double BSIM3pdvt1w; + double BSIM3pdvt2w; + double BSIM3pdrout; + double BSIM3pdsub; + double BSIM3pvth0; + double BSIM3pua; + double BSIM3pua1; + double BSIM3pub; + double BSIM3pub1; + double BSIM3puc; + double BSIM3puc1; + double BSIM3pu0; + double BSIM3pute; + double BSIM3pvoff; + double BSIM3pdelta; + double BSIM3prdsw; + double BSIM3pprwg; + double BSIM3pprwb; + double BSIM3pprt; + double BSIM3peta0; + double BSIM3petab; + double BSIM3ppclm; + double BSIM3ppdibl1; + double BSIM3ppdibl2; + double BSIM3ppdiblb; + double BSIM3ppscbe1; + double BSIM3ppscbe2; + double BSIM3ppvag; + double BSIM3pwr; + double BSIM3pdwg; + double BSIM3pdwb; + double BSIM3pb0; + double BSIM3pb1; + double BSIM3palpha0; + double BSIM3palpha1; + double BSIM3pbeta0; + double BSIM3pvfb; + + /* CV model */ + double BSIM3pelm; + double BSIM3pcgsl; + double BSIM3pcgdl; + double BSIM3pckappa; + double BSIM3pcf; + double BSIM3pclc; + double BSIM3pcle; + double BSIM3pvfbcv; + double BSIM3pnoff; + double BSIM3pvoffcv; + double BSIM3pacde; + double BSIM3pmoin; + + double BSIM3tnom; + double BSIM3cgso; + double BSIM3cgdo; + double BSIM3cgbo; + double BSIM3xpart; + double BSIM3cFringOut; + double BSIM3cFringMax; + + double BSIM3sheetResistance; + double BSIM3jctSatCurDensity; + double BSIM3jctSidewallSatCurDensity; + double BSIM3bulkJctPotential; + double BSIM3bulkJctBotGradingCoeff; + double BSIM3bulkJctSideGradingCoeff; + double BSIM3bulkJctGateSideGradingCoeff; + double BSIM3sidewallJctPotential; + double BSIM3GatesidewallJctPotential; + double BSIM3unitAreaJctCap; + double BSIM3unitLengthSidewallJctCap; + double BSIM3unitLengthGateSidewallJctCap; + double BSIM3jctEmissionCoeff; + double BSIM3jctTempExponent; + + double BSIM3Lint; + double BSIM3Ll; + double BSIM3Llc; + double BSIM3Lln; + double BSIM3Lw; + double BSIM3Lwc; + double BSIM3Lwn; + double BSIM3Lwl; + double BSIM3Lwlc; + double BSIM3Lmin; + double BSIM3Lmax; + + double BSIM3Wint; + double BSIM3Wl; + double BSIM3Wlc; + double BSIM3Wln; + double BSIM3Ww; + double BSIM3Wwc; + double BSIM3Wwn; + double BSIM3Wwl; + double BSIM3Wwlc; + double BSIM3Wmin; + double BSIM3Wmax; + + +/* Pre-calculated constants */ + /* MCJ: move to size-dependent param. */ + double BSIM3vtm; + double BSIM3cox; + double BSIM3cof1; + double BSIM3cof2; + double BSIM3cof3; + double BSIM3cof4; + double BSIM3vcrit; + double BSIM3factor1; + double BSIM3PhiB; + double BSIM3PhiBSW; + double BSIM3PhiBSWG; + double BSIM3jctTempSatCurDensity; + double BSIM3jctSidewallTempSatCurDensity; + double BSIM3unitAreaTempJctCap; + double BSIM3unitLengthSidewallTempJctCap; + double BSIM3unitLengthGateSidewallTempJctCap; + + double BSIM3oxideTrapDensityA; + double BSIM3oxideTrapDensityB; + double BSIM3oxideTrapDensityC; + double BSIM3em; + double BSIM3ef; + double BSIM3af; + double BSIM3kf; + double BSIM3lintnoi; /* lint offset for noise calculation */ + + double BSIM3vgsMax; + double BSIM3vgdMax; + double BSIM3vgbMax; + double BSIM3vdsMax; + double BSIM3vbsMax; + double BSIM3vbdMax; + double BSIM3vgsrMax; + double BSIM3vgdrMax; + double BSIM3vgbrMax; + double BSIM3vbsrMax; + double BSIM3vbdrMax; + + struct bsim3SizeDependParam *pSizeDependParamKnot; + + BSIM3group* groupHead; + +#if 1 + int BSIM3InstCount; + struct sBSIM3instance **BSIM3InstanceArray; +#endif + + /* Flags */ + 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; + unsigned BSIM3versionGiven :1; + unsigned BSIM3toxmGiven :1; + unsigned BSIM3cdscGiven :1; + unsigned BSIM3cdscbGiven :1; + unsigned BSIM3cdscdGiven :1; + unsigned BSIM3citGiven :1; + unsigned BSIM3nfactorGiven :1; + unsigned BSIM3xjGiven :1; + unsigned BSIM3vsatGiven :1; + unsigned BSIM3atGiven :1; + unsigned BSIM3a0Given :1; + unsigned BSIM3agsGiven :1; + unsigned BSIM3a1Given :1; + unsigned BSIM3a2Given :1; + unsigned BSIM3ketaGiven :1; + unsigned BSIM3nsubGiven :1; + unsigned BSIM3npeakGiven :1; + unsigned BSIM3ngateGiven :1; + unsigned BSIM3gamma1Given :1; + unsigned BSIM3gamma2Given :1; + unsigned BSIM3vbxGiven :1; + unsigned BSIM3vbmGiven :1; + unsigned BSIM3xtGiven :1; + unsigned BSIM3k1Given :1; + unsigned BSIM3kt1Given :1; + unsigned BSIM3kt1lGiven :1; + unsigned BSIM3kt2Given :1; + unsigned BSIM3k2Given :1; + unsigned BSIM3k3Given :1; + 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 BSIM3vth0Given :1; + unsigned BSIM3uaGiven :1; + unsigned BSIM3ua1Given :1; + unsigned BSIM3ubGiven :1; + unsigned BSIM3ub1Given :1; + unsigned BSIM3ucGiven :1; + unsigned BSIM3uc1Given :1; + 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 BSIM3wrGiven :1; + unsigned BSIM3dwgGiven :1; + unsigned BSIM3dwbGiven :1; + unsigned BSIM3b0Given :1; + unsigned BSIM3b1Given :1; + unsigned BSIM3alpha0Given :1; + unsigned BSIM3alpha1Given :1; + unsigned BSIM3beta0Given :1; + unsigned BSIM3ijthGiven :1; + unsigned BSIM3vfbGiven :1; + + /* CV model */ + unsigned BSIM3elmGiven :1; + unsigned BSIM3cgslGiven :1; + unsigned BSIM3cgdlGiven :1; + unsigned BSIM3ckappaGiven :1; + unsigned BSIM3cfGiven :1; + unsigned BSIM3vfbcvGiven :1; + unsigned BSIM3clcGiven :1; + unsigned BSIM3cleGiven :1; + unsigned BSIM3dwcGiven :1; + unsigned BSIM3dlcGiven :1; + unsigned BSIM3noffGiven :1; + unsigned BSIM3voffcvGiven :1; + unsigned BSIM3acdeGiven :1; + unsigned BSIM3moinGiven :1; + unsigned BSIM3tcjGiven :1; + unsigned BSIM3tcjswGiven :1; + unsigned BSIM3tcjswgGiven :1; + unsigned BSIM3tpbGiven :1; + 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; + unsigned BSIM3lcdscbGiven :1; + unsigned BSIM3lcdscdGiven :1; + unsigned BSIM3lcitGiven :1; + unsigned BSIM3lnfactorGiven :1; + unsigned BSIM3lxjGiven :1; + unsigned BSIM3lvsatGiven :1; + unsigned BSIM3latGiven :1; + unsigned BSIM3la0Given :1; + unsigned BSIM3lagsGiven :1; + unsigned BSIM3la1Given :1; + unsigned BSIM3la2Given :1; + unsigned BSIM3lketaGiven :1; + unsigned BSIM3lnsubGiven :1; + unsigned BSIM3lnpeakGiven :1; + unsigned BSIM3lngateGiven :1; + unsigned BSIM3lgamma1Given :1; + unsigned BSIM3lgamma2Given :1; + unsigned BSIM3lvbxGiven :1; + unsigned BSIM3lvbmGiven :1; + unsigned BSIM3lxtGiven :1; + unsigned BSIM3lk1Given :1; + unsigned BSIM3lkt1Given :1; + unsigned BSIM3lkt1lGiven :1; + unsigned BSIM3lkt2Given :1; + unsigned BSIM3lk2Given :1; + unsigned BSIM3lk3Given :1; + 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 BSIM3lvth0Given :1; + unsigned BSIM3luaGiven :1; + unsigned BSIM3lua1Given :1; + unsigned BSIM3lubGiven :1; + unsigned BSIM3lub1Given :1; + unsigned BSIM3lucGiven :1; + unsigned BSIM3luc1Given :1; + 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 BSIM3lwrGiven :1; + unsigned BSIM3ldwgGiven :1; + unsigned BSIM3ldwbGiven :1; + unsigned BSIM3lb0Given :1; + unsigned BSIM3lb1Given :1; + unsigned BSIM3lalpha0Given :1; + unsigned BSIM3lalpha1Given :1; + unsigned BSIM3lbeta0Given :1; + unsigned BSIM3lvfbGiven :1; + + /* CV model */ + unsigned BSIM3lelmGiven :1; + unsigned BSIM3lcgslGiven :1; + unsigned BSIM3lcgdlGiven :1; + unsigned BSIM3lckappaGiven :1; + unsigned BSIM3lcfGiven :1; + unsigned BSIM3lclcGiven :1; + unsigned BSIM3lcleGiven :1; + unsigned BSIM3lvfbcvGiven :1; + unsigned BSIM3lnoffGiven :1; + unsigned BSIM3lvoffcvGiven :1; + unsigned BSIM3lacdeGiven :1; + unsigned BSIM3lmoinGiven :1; + + /* Width dependence */ + unsigned BSIM3wcdscGiven :1; + unsigned BSIM3wcdscbGiven :1; + unsigned BSIM3wcdscdGiven :1; + unsigned BSIM3wcitGiven :1; + unsigned BSIM3wnfactorGiven :1; + unsigned BSIM3wxjGiven :1; + unsigned BSIM3wvsatGiven :1; + unsigned BSIM3watGiven :1; + unsigned BSIM3wa0Given :1; + unsigned BSIM3wagsGiven :1; + unsigned BSIM3wa1Given :1; + unsigned BSIM3wa2Given :1; + unsigned BSIM3wketaGiven :1; + unsigned BSIM3wnsubGiven :1; + unsigned BSIM3wnpeakGiven :1; + unsigned BSIM3wngateGiven :1; + unsigned BSIM3wgamma1Given :1; + unsigned BSIM3wgamma2Given :1; + unsigned BSIM3wvbxGiven :1; + unsigned BSIM3wvbmGiven :1; + unsigned BSIM3wxtGiven :1; + unsigned BSIM3wk1Given :1; + unsigned BSIM3wkt1Given :1; + unsigned BSIM3wkt1lGiven :1; + unsigned BSIM3wkt2Given :1; + unsigned BSIM3wk2Given :1; + unsigned BSIM3wk3Given :1; + 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 BSIM3wvth0Given :1; + unsigned BSIM3wuaGiven :1; + unsigned BSIM3wua1Given :1; + unsigned BSIM3wubGiven :1; + unsigned BSIM3wub1Given :1; + unsigned BSIM3wucGiven :1; + unsigned BSIM3wuc1Given :1; + 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 BSIM3wwrGiven :1; + unsigned BSIM3wdwgGiven :1; + unsigned BSIM3wdwbGiven :1; + unsigned BSIM3wb0Given :1; + unsigned BSIM3wb1Given :1; + unsigned BSIM3walpha0Given :1; + unsigned BSIM3walpha1Given :1; + unsigned BSIM3wbeta0Given :1; + unsigned BSIM3wvfbGiven :1; + + /* CV model */ + unsigned BSIM3welmGiven :1; + unsigned BSIM3wcgslGiven :1; + unsigned BSIM3wcgdlGiven :1; + unsigned BSIM3wckappaGiven :1; + unsigned BSIM3wcfGiven :1; + unsigned BSIM3wclcGiven :1; + unsigned BSIM3wcleGiven :1; + unsigned BSIM3wvfbcvGiven :1; + unsigned BSIM3wnoffGiven :1; + unsigned BSIM3wvoffcvGiven :1; + unsigned BSIM3wacdeGiven :1; + unsigned BSIM3wmoinGiven :1; + + /* Cross-term dependence */ + unsigned BSIM3pcdscGiven :1; + unsigned BSIM3pcdscbGiven :1; + unsigned BSIM3pcdscdGiven :1; + unsigned BSIM3pcitGiven :1; + unsigned BSIM3pnfactorGiven :1; + unsigned BSIM3pxjGiven :1; + unsigned BSIM3pvsatGiven :1; + unsigned BSIM3patGiven :1; + unsigned BSIM3pa0Given :1; + unsigned BSIM3pagsGiven :1; + unsigned BSIM3pa1Given :1; + unsigned BSIM3pa2Given :1; + unsigned BSIM3pketaGiven :1; + unsigned BSIM3pnsubGiven :1; + unsigned BSIM3pnpeakGiven :1; + unsigned BSIM3pngateGiven :1; + unsigned BSIM3pgamma1Given :1; + unsigned BSIM3pgamma2Given :1; + unsigned BSIM3pvbxGiven :1; + unsigned BSIM3pvbmGiven :1; + unsigned BSIM3pxtGiven :1; + unsigned BSIM3pk1Given :1; + unsigned BSIM3pkt1Given :1; + unsigned BSIM3pkt1lGiven :1; + unsigned BSIM3pkt2Given :1; + unsigned BSIM3pk2Given :1; + unsigned BSIM3pk3Given :1; + 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 BSIM3pvth0Given :1; + unsigned BSIM3puaGiven :1; + unsigned BSIM3pua1Given :1; + unsigned BSIM3pubGiven :1; + unsigned BSIM3pub1Given :1; + unsigned BSIM3pucGiven :1; + unsigned BSIM3puc1Given :1; + 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 BSIM3pwrGiven :1; + unsigned BSIM3pdwgGiven :1; + unsigned BSIM3pdwbGiven :1; + unsigned BSIM3pb0Given :1; + unsigned BSIM3pb1Given :1; + unsigned BSIM3palpha0Given :1; + unsigned BSIM3palpha1Given :1; + unsigned BSIM3pbeta0Given :1; + unsigned BSIM3pvfbGiven :1; + + /* CV model */ + unsigned BSIM3pelmGiven :1; + unsigned BSIM3pcgslGiven :1; + unsigned BSIM3pcgdlGiven :1; + unsigned BSIM3pckappaGiven :1; + unsigned BSIM3pcfGiven :1; + unsigned BSIM3pclcGiven :1; + unsigned BSIM3pcleGiven :1; + unsigned BSIM3pvfbcvGiven :1; + unsigned BSIM3pnoffGiven :1; + unsigned BSIM3pvoffcvGiven :1; + unsigned BSIM3pacdeGiven :1; + unsigned BSIM3pmoinGiven :1; + + unsigned BSIM3useFringeGiven :1; + + unsigned BSIM3tnomGiven :1; + unsigned BSIM3cgsoGiven :1; + unsigned BSIM3cgdoGiven :1; + unsigned BSIM3cgboGiven :1; + unsigned BSIM3xpartGiven :1; + unsigned BSIM3sheetResistanceGiven :1; + unsigned BSIM3jctSatCurDensityGiven :1; + unsigned BSIM3jctSidewallSatCurDensityGiven :1; + unsigned BSIM3bulkJctPotentialGiven :1; + unsigned BSIM3bulkJctBotGradingCoeffGiven :1; + unsigned BSIM3sidewallJctPotentialGiven :1; + unsigned BSIM3GatesidewallJctPotentialGiven :1; + unsigned BSIM3bulkJctSideGradingCoeffGiven :1; + unsigned BSIM3unitAreaJctCapGiven :1; + unsigned BSIM3unitLengthSidewallJctCapGiven :1; + unsigned BSIM3bulkJctGateSideGradingCoeffGiven :1; + unsigned BSIM3unitLengthGateSidewallJctCapGiven :1; + unsigned BSIM3jctEmissionCoeffGiven :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 BSIM3lintnoiGiven :1; + + unsigned BSIM3vgsMaxGiven :1; + unsigned BSIM3vgdMaxGiven :1; + unsigned BSIM3vgbMaxGiven :1; + unsigned BSIM3vdsMaxGiven :1; + unsigned BSIM3vbsMaxGiven :1; + unsigned BSIM3vbdMaxGiven :1; + unsigned BSIM3vgsrMaxGiven :1; + unsigned BSIM3vgdrMaxGiven :1; + unsigned BSIM3vgbrMaxGiven :1; + unsigned BSIM3vbsrMaxGiven :1; + unsigned BSIM3vbdrMaxGiven :1; + + unsigned BSIM3LintGiven :1; + unsigned BSIM3LlGiven :1; + unsigned BSIM3LlcGiven :1; + unsigned BSIM3LlnGiven :1; + unsigned BSIM3LwGiven :1; + unsigned BSIM3LwcGiven :1; + unsigned BSIM3LwnGiven :1; + unsigned BSIM3LwlGiven :1; + unsigned BSIM3LwlcGiven :1; + unsigned BSIM3LminGiven :1; + unsigned BSIM3LmaxGiven :1; + + unsigned BSIM3WintGiven :1; + unsigned BSIM3WlGiven :1; + unsigned BSIM3WlcGiven :1; + unsigned BSIM3WlnGiven :1; + unsigned BSIM3WwGiven :1; + unsigned BSIM3WwcGiven :1; + unsigned BSIM3WwnGiven :1; + unsigned BSIM3WwlGiven :1; + unsigned BSIM3WwlcGiven :1; + unsigned BSIM3WminGiven :1; + unsigned BSIM3WmaxGiven :1; + +} BSIM3model; + + +#ifndef NMOS +#define NMOS 1 +#define PMOS -1 +#endif /*NMOS*/ + + +/* device parameters */ +#define BSIM3_W 1 +#define BSIM3_L 2 +#define BSIM3_AS 3 +#define BSIM3_AD 4 +#define BSIM3_PS 5 +#define BSIM3_PD 6 +#define BSIM3_NRS 7 +#define BSIM3_NRD 8 +#define BSIM3_OFF 9 +#define BSIM3_IC_VBS 10 +#define BSIM3_IC_VDS 11 +#define BSIM3_IC_VGS 12 +#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 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 + +#define BSIM3_MOD_CDSC 106 +#define BSIM3_MOD_CDSCB 107 +#define BSIM3_MOD_CIT 108 +#define BSIM3_MOD_NFACTOR 109 +#define BSIM3_MOD_XJ 110 +#define BSIM3_MOD_VSAT 111 +#define BSIM3_MOD_AT 112 +#define BSIM3_MOD_A0 113 +#define BSIM3_MOD_A1 114 +#define BSIM3_MOD_A2 115 +#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_VBM 125 + +#define BSIM3_MOD_XT 126 +#define BSIM3_MOD_K1 129 +#define BSIM3_MOD_KT1 130 +#define BSIM3_MOD_KT1L 131 +#define BSIM3_MOD_K2 132 +#define BSIM3_MOD_KT2 133 +#define BSIM3_MOD_K3 134 +#define BSIM3_MOD_K3B 135 +#define BSIM3_MOD_W0 136 +#define BSIM3_MOD_NLX 137 + +#define BSIM3_MOD_DVT0 138 +#define BSIM3_MOD_DVT1 139 +#define BSIM3_MOD_DVT2 140 + +#define BSIM3_MOD_DVT0W 141 +#define BSIM3_MOD_DVT1W 142 +#define BSIM3_MOD_DVT2W 143 + +#define BSIM3_MOD_DROUT 144 +#define BSIM3_MOD_DSUB 145 +#define BSIM3_MOD_VTH0 146 +#define BSIM3_MOD_UA 147 +#define BSIM3_MOD_UA1 148 +#define BSIM3_MOD_UB 149 +#define BSIM3_MOD_UB1 150 +#define BSIM3_MOD_UC 151 +#define BSIM3_MOD_UC1 152 +#define BSIM3_MOD_U0 153 +#define BSIM3_MOD_UTE 154 +#define BSIM3_MOD_VOFF 155 +#define BSIM3_MOD_DELTA 156 +#define BSIM3_MOD_RDSW 157 +#define BSIM3_MOD_PRT 158 +#define BSIM3_MOD_LDD 159 +#define BSIM3_MOD_ETA 160 +#define BSIM3_MOD_ETA0 161 +#define BSIM3_MOD_ETAB 162 +#define BSIM3_MOD_PCLM 163 +#define BSIM3_MOD_PDIBL1 164 +#define BSIM3_MOD_PDIBL2 165 +#define BSIM3_MOD_PSCBE1 166 +#define BSIM3_MOD_PSCBE2 167 +#define BSIM3_MOD_PVAG 168 +#define BSIM3_MOD_WR 169 +#define BSIM3_MOD_DWG 170 +#define BSIM3_MOD_DWB 171 +#define BSIM3_MOD_B0 172 +#define BSIM3_MOD_B1 173 +#define BSIM3_MOD_ALPHA0 174 +#define BSIM3_MOD_BETA0 175 +#define BSIM3_MOD_PDIBLB 178 + +#define BSIM3_MOD_PRWG 179 +#define BSIM3_MOD_PRWB 180 + +#define BSIM3_MOD_CDSCD 181 +#define BSIM3_MOD_AGS 182 + +#define BSIM3_MOD_FRINGE 184 +#define BSIM3_MOD_ELM 185 +#define BSIM3_MOD_CGSL 186 +#define BSIM3_MOD_CGDL 187 +#define BSIM3_MOD_CKAPPA 188 +#define BSIM3_MOD_CF 189 +#define BSIM3_MOD_CLC 190 +#define BSIM3_MOD_CLE 191 +#define BSIM3_MOD_PARAMCHK 192 +#define BSIM3_MOD_VERSION 193 +#define BSIM3_MOD_VFBCV 194 +#define BSIM3_MOD_ACDE 195 +#define BSIM3_MOD_MOIN 196 +#define BSIM3_MOD_NOFF 197 +#define BSIM3_MOD_IJTH 198 +#define BSIM3_MOD_ALPHA1 199 +#define BSIM3_MOD_VFB 200 +#define BSIM3_MOD_TOXM 201 +#define BSIM3_MOD_TCJ 202 +#define BSIM3_MOD_TCJSW 203 +#define BSIM3_MOD_TCJSWG 204 +#define BSIM3_MOD_TPB 205 +#define BSIM3_MOD_TPBSW 206 +#define BSIM3_MOD_TPBSWG 207 +#define BSIM3_MOD_VOFFCV 208 +#define BSIM3_MOD_LINTNOI 209 +#define BSIM3_MOD_NQSMOD 210 +#define BSIM3_MOD_ACNQSMOD 211 + +/* Length dependence */ +#define BSIM3_MOD_LCDSC 251 +#define BSIM3_MOD_LCDSCB 252 +#define BSIM3_MOD_LCIT 253 +#define BSIM3_MOD_LNFACTOR 254 +#define BSIM3_MOD_LXJ 255 +#define BSIM3_MOD_LVSAT 256 +#define BSIM3_MOD_LAT 257 +#define BSIM3_MOD_LA0 258 +#define BSIM3_MOD_LA1 259 +#define BSIM3_MOD_LA2 260 +#define BSIM3_MOD_LKETA 261 +#define BSIM3_MOD_LNSUB 262 +#define BSIM3_MOD_LNPEAK 263 +#define BSIM3_MOD_LNGATE 265 +#define BSIM3_MOD_LGAMMA1 266 +#define BSIM3_MOD_LGAMMA2 267 +#define BSIM3_MOD_LVBX 268 + +#define BSIM3_MOD_LVBM 270 + +#define BSIM3_MOD_LXT 272 +#define BSIM3_MOD_LK1 275 +#define BSIM3_MOD_LKT1 276 +#define BSIM3_MOD_LKT1L 277 +#define BSIM3_MOD_LK2 278 +#define BSIM3_MOD_LKT2 279 +#define BSIM3_MOD_LK3 280 +#define BSIM3_MOD_LK3B 281 +#define BSIM3_MOD_LW0 282 +#define BSIM3_MOD_LNLX 283 + +#define BSIM3_MOD_LDVT0 284 +#define BSIM3_MOD_LDVT1 285 +#define BSIM3_MOD_LDVT2 286 + +#define BSIM3_MOD_LDVT0W 287 +#define BSIM3_MOD_LDVT1W 288 +#define BSIM3_MOD_LDVT2W 289 + +#define BSIM3_MOD_LDROUT 290 +#define BSIM3_MOD_LDSUB 291 +#define BSIM3_MOD_LVTH0 292 +#define BSIM3_MOD_LUA 293 +#define BSIM3_MOD_LUA1 294 +#define BSIM3_MOD_LUB 295 +#define BSIM3_MOD_LUB1 296 +#define BSIM3_MOD_LUC 297 +#define BSIM3_MOD_LUC1 298 +#define BSIM3_MOD_LU0 299 +#define BSIM3_MOD_LUTE 300 +#define BSIM3_MOD_LVOFF 301 +#define BSIM3_MOD_LDELTA 302 +#define BSIM3_MOD_LRDSW 303 +#define BSIM3_MOD_LPRT 304 +#define BSIM3_MOD_LLDD 305 +#define BSIM3_MOD_LETA 306 +#define BSIM3_MOD_LETA0 307 +#define BSIM3_MOD_LETAB 308 +#define BSIM3_MOD_LPCLM 309 +#define BSIM3_MOD_LPDIBL1 310 +#define BSIM3_MOD_LPDIBL2 311 +#define BSIM3_MOD_LPSCBE1 312 +#define BSIM3_MOD_LPSCBE2 313 +#define BSIM3_MOD_LPVAG 314 +#define BSIM3_MOD_LWR 315 +#define BSIM3_MOD_LDWG 316 +#define BSIM3_MOD_LDWB 317 +#define BSIM3_MOD_LB0 318 +#define BSIM3_MOD_LB1 319 +#define BSIM3_MOD_LALPHA0 320 +#define BSIM3_MOD_LBETA0 321 +#define BSIM3_MOD_LPDIBLB 324 + +#define BSIM3_MOD_LPRWG 325 +#define BSIM3_MOD_LPRWB 326 + +#define BSIM3_MOD_LCDSCD 327 +#define BSIM3_MOD_LAGS 328 + + +#define BSIM3_MOD_LFRINGE 331 +#define BSIM3_MOD_LELM 332 +#define BSIM3_MOD_LCGSL 333 +#define BSIM3_MOD_LCGDL 334 +#define BSIM3_MOD_LCKAPPA 335 +#define BSIM3_MOD_LCF 336 +#define BSIM3_MOD_LCLC 337 +#define BSIM3_MOD_LCLE 338 +#define BSIM3_MOD_LVFBCV 339 +#define BSIM3_MOD_LACDE 340 +#define BSIM3_MOD_LMOIN 341 +#define BSIM3_MOD_LNOFF 342 +#define BSIM3_MOD_LALPHA1 344 +#define BSIM3_MOD_LVFB 345 +#define BSIM3_MOD_LVOFFCV 346 + +/* Width dependence */ +#define BSIM3_MOD_WCDSC 381 +#define BSIM3_MOD_WCDSCB 382 +#define BSIM3_MOD_WCIT 383 +#define BSIM3_MOD_WNFACTOR 384 +#define BSIM3_MOD_WXJ 385 +#define BSIM3_MOD_WVSAT 386 +#define BSIM3_MOD_WAT 387 +#define BSIM3_MOD_WA0 388 +#define BSIM3_MOD_WA1 389 +#define BSIM3_MOD_WA2 390 +#define BSIM3_MOD_WKETA 391 +#define BSIM3_MOD_WNSUB 392 +#define BSIM3_MOD_WNPEAK 393 +#define BSIM3_MOD_WNGATE 395 +#define BSIM3_MOD_WGAMMA1 396 +#define BSIM3_MOD_WGAMMA2 397 +#define BSIM3_MOD_WVBX 398 + +#define BSIM3_MOD_WVBM 400 + +#define BSIM3_MOD_WXT 402 +#define BSIM3_MOD_WK1 405 +#define BSIM3_MOD_WKT1 406 +#define BSIM3_MOD_WKT1L 407 +#define BSIM3_MOD_WK2 408 +#define BSIM3_MOD_WKT2 409 +#define BSIM3_MOD_WK3 410 +#define BSIM3_MOD_WK3B 411 +#define BSIM3_MOD_WW0 412 +#define BSIM3_MOD_WNLX 413 + +#define BSIM3_MOD_WDVT0 414 +#define BSIM3_MOD_WDVT1 415 +#define BSIM3_MOD_WDVT2 416 + +#define BSIM3_MOD_WDVT0W 417 +#define BSIM3_MOD_WDVT1W 418 +#define BSIM3_MOD_WDVT2W 419 + +#define BSIM3_MOD_WDROUT 420 +#define BSIM3_MOD_WDSUB 421 +#define BSIM3_MOD_WVTH0 422 +#define BSIM3_MOD_WUA 423 +#define BSIM3_MOD_WUA1 424 +#define BSIM3_MOD_WUB 425 +#define BSIM3_MOD_WUB1 426 +#define BSIM3_MOD_WUC 427 +#define BSIM3_MOD_WUC1 428 +#define BSIM3_MOD_WU0 429 +#define BSIM3_MOD_WUTE 430 +#define BSIM3_MOD_WVOFF 431 +#define BSIM3_MOD_WDELTA 432 +#define BSIM3_MOD_WRDSW 433 +#define BSIM3_MOD_WPRT 434 +#define BSIM3_MOD_WLDD 435 +#define BSIM3_MOD_WETA 436 +#define BSIM3_MOD_WETA0 437 +#define BSIM3_MOD_WETAB 438 +#define BSIM3_MOD_WPCLM 439 +#define BSIM3_MOD_WPDIBL1 440 +#define BSIM3_MOD_WPDIBL2 441 +#define BSIM3_MOD_WPSCBE1 442 +#define BSIM3_MOD_WPSCBE2 443 +#define BSIM3_MOD_WPVAG 444 +#define BSIM3_MOD_WWR 445 +#define BSIM3_MOD_WDWG 446 +#define BSIM3_MOD_WDWB 447 +#define BSIM3_MOD_WB0 448 +#define BSIM3_MOD_WB1 449 +#define BSIM3_MOD_WALPHA0 450 +#define BSIM3_MOD_WBETA0 451 +#define BSIM3_MOD_WPDIBLB 454 + +#define BSIM3_MOD_WPRWG 455 +#define BSIM3_MOD_WPRWB 456 + +#define BSIM3_MOD_WCDSCD 457 +#define BSIM3_MOD_WAGS 458 + + +#define BSIM3_MOD_WFRINGE 461 +#define BSIM3_MOD_WELM 462 +#define BSIM3_MOD_WCGSL 463 +#define BSIM3_MOD_WCGDL 464 +#define BSIM3_MOD_WCKAPPA 465 +#define BSIM3_MOD_WCF 466 +#define BSIM3_MOD_WCLC 467 +#define BSIM3_MOD_WCLE 468 +#define BSIM3_MOD_WVFBCV 469 +#define BSIM3_MOD_WACDE 470 +#define BSIM3_MOD_WMOIN 471 +#define BSIM3_MOD_WNOFF 472 +#define BSIM3_MOD_WALPHA1 474 +#define BSIM3_MOD_WVFB 475 +#define BSIM3_MOD_WVOFFCV 476 + +/* Cross-term dependence */ +#define BSIM3_MOD_PCDSC 511 +#define BSIM3_MOD_PCDSCB 512 +#define BSIM3_MOD_PCIT 513 +#define BSIM3_MOD_PNFACTOR 514 +#define BSIM3_MOD_PXJ 515 +#define BSIM3_MOD_PVSAT 516 +#define BSIM3_MOD_PAT 517 +#define BSIM3_MOD_PA0 518 +#define BSIM3_MOD_PA1 519 +#define BSIM3_MOD_PA2 520 +#define BSIM3_MOD_PKETA 521 +#define BSIM3_MOD_PNSUB 522 +#define BSIM3_MOD_PNPEAK 523 +#define BSIM3_MOD_PNGATE 525 +#define BSIM3_MOD_PGAMMA1 526 +#define BSIM3_MOD_PGAMMA2 527 +#define BSIM3_MOD_PVBX 528 + +#define BSIM3_MOD_PVBM 530 + +#define BSIM3_MOD_PXT 532 +#define BSIM3_MOD_PK1 535 +#define BSIM3_MOD_PKT1 536 +#define BSIM3_MOD_PKT1L 537 +#define BSIM3_MOD_PK2 538 +#define BSIM3_MOD_PKT2 539 +#define BSIM3_MOD_PK3 540 +#define BSIM3_MOD_PK3B 541 +#define BSIM3_MOD_PW0 542 +#define BSIM3_MOD_PNLX 543 + +#define BSIM3_MOD_PDVT0 544 +#define BSIM3_MOD_PDVT1 545 +#define BSIM3_MOD_PDVT2 546 + +#define BSIM3_MOD_PDVT0W 547 +#define BSIM3_MOD_PDVT1W 548 +#define BSIM3_MOD_PDVT2W 549 + +#define BSIM3_MOD_PDROUT 550 +#define BSIM3_MOD_PDSUB 551 +#define BSIM3_MOD_PVTH0 552 +#define BSIM3_MOD_PUA 553 +#define BSIM3_MOD_PUA1 554 +#define BSIM3_MOD_PUB 555 +#define BSIM3_MOD_PUB1 556 +#define BSIM3_MOD_PUC 557 +#define BSIM3_MOD_PUC1 558 +#define BSIM3_MOD_PU0 559 +#define BSIM3_MOD_PUTE 560 +#define BSIM3_MOD_PVOFF 561 +#define BSIM3_MOD_PDELTA 562 +#define BSIM3_MOD_PRDSW 563 +#define BSIM3_MOD_PPRT 564 +#define BSIM3_MOD_PLDD 565 +#define BSIM3_MOD_PETA 566 +#define BSIM3_MOD_PETA0 567 +#define BSIM3_MOD_PETAB 568 +#define BSIM3_MOD_PPCLM 569 +#define BSIM3_MOD_PPDIBL1 570 +#define BSIM3_MOD_PPDIBL2 571 +#define BSIM3_MOD_PPSCBE1 572 +#define BSIM3_MOD_PPSCBE2 573 +#define BSIM3_MOD_PPVAG 574 +#define BSIM3_MOD_PWR 575 +#define BSIM3_MOD_PDWG 576 +#define BSIM3_MOD_PDWB 577 +#define BSIM3_MOD_PB0 578 +#define BSIM3_MOD_PB1 579 +#define BSIM3_MOD_PALPHA0 580 +#define BSIM3_MOD_PBETA0 581 +#define BSIM3_MOD_PPDIBLB 584 + +#define BSIM3_MOD_PPRWG 585 +#define BSIM3_MOD_PPRWB 586 + +#define BSIM3_MOD_PCDSCD 587 +#define BSIM3_MOD_PAGS 588 + +#define BSIM3_MOD_PFRINGE 591 +#define BSIM3_MOD_PELM 592 +#define BSIM3_MOD_PCGSL 593 +#define BSIM3_MOD_PCGDL 594 +#define BSIM3_MOD_PCKAPPA 595 +#define BSIM3_MOD_PCF 596 +#define BSIM3_MOD_PCLC 597 +#define BSIM3_MOD_PCLE 598 +#define BSIM3_MOD_PVFBCV 599 +#define BSIM3_MOD_PACDE 600 +#define BSIM3_MOD_PMOIN 601 +#define BSIM3_MOD_PNOFF 602 +#define BSIM3_MOD_PALPHA1 604 +#define BSIM3_MOD_PVFB 605 +#define BSIM3_MOD_PVOFFCV 606 + +#define BSIM3_MOD_TNOM 651 +#define BSIM3_MOD_CGSO 652 +#define BSIM3_MOD_CGDO 653 +#define BSIM3_MOD_CGBO 654 +#define BSIM3_MOD_XPART 655 + +#define BSIM3_MOD_RSH 656 +#define BSIM3_MOD_JS 657 +#define BSIM3_MOD_PB 658 +#define BSIM3_MOD_MJ 659 +#define BSIM3_MOD_PBSW 660 +#define BSIM3_MOD_MJSW 661 +#define BSIM3_MOD_CJ 662 +#define BSIM3_MOD_CJSW 663 +#define BSIM3_MOD_NMOS 664 +#define BSIM3_MOD_PMOS 665 + +#define BSIM3_MOD_NOIA 666 +#define BSIM3_MOD_NOIB 667 +#define BSIM3_MOD_NOIC 668 + +#define BSIM3_MOD_LINT 669 +#define BSIM3_MOD_LL 670 +#define BSIM3_MOD_LLN 671 +#define BSIM3_MOD_LW 672 +#define BSIM3_MOD_LWN 673 +#define BSIM3_MOD_LWL 674 +#define BSIM3_MOD_LMIN 675 +#define BSIM3_MOD_LMAX 676 + +#define BSIM3_MOD_WINT 677 +#define BSIM3_MOD_WL 678 +#define BSIM3_MOD_WLN 679 +#define BSIM3_MOD_WW 680 +#define BSIM3_MOD_WWN 681 +#define BSIM3_MOD_WWL 682 +#define BSIM3_MOD_WMIN 683 +#define BSIM3_MOD_WMAX 684 + +#define BSIM3_MOD_DWC 685 +#define BSIM3_MOD_DLC 686 + +#define BSIM3_MOD_EM 687 +#define BSIM3_MOD_EF 688 +#define BSIM3_MOD_AF 689 +#define BSIM3_MOD_KF 690 + +#define BSIM3_MOD_NJ 691 +#define BSIM3_MOD_XTI 692 + +#define BSIM3_MOD_PBSWG 693 +#define BSIM3_MOD_MJSWG 694 +#define BSIM3_MOD_CJSWG 695 +#define BSIM3_MOD_JSW 696 + +#define BSIM3_MOD_LLC 697 +#define BSIM3_MOD_LWC 698 +#define BSIM3_MOD_LWLC 699 + +#define BSIM3_MOD_WLC 700 +#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 +#define BSIM3_SNODE 753 +#define BSIM3_BNODE 754 +#define BSIM3_DNODEPRIME 755 +#define BSIM3_SNODEPRIME 756 +#define BSIM3_VBD 757 +#define BSIM3_VBS 758 +#define BSIM3_VGS 759 +#define BSIM3_VDS 760 +#define BSIM3_CD 761 +#define BSIM3_CBS 762 +#define BSIM3_CBD 763 +#define BSIM3_GM 764 +#define BSIM3_GDS 765 +#define BSIM3_GMBS 766 +#define BSIM3_GBD 767 +#define BSIM3_GBS 768 +#define BSIM3_QB 769 +#define BSIM3_CQB 770 +#define BSIM3_QG 771 +#define BSIM3_CQG 772 +#define BSIM3_QD 773 +#define BSIM3_CQD 774 +#define BSIM3_CGG 775 +#define BSIM3_CGD 776 +#define BSIM3_CGS 777 +#define BSIM3_CBG 778 +#define BSIM3_CAPBD 779 +#define BSIM3_CQBD 780 +#define BSIM3_CAPBS 781 +#define BSIM3_CQBS 782 +#define BSIM3_CDG 783 +#define BSIM3_CDD 784 +#define BSIM3_CDS 785 +#define BSIM3_VON 786 +#define BSIM3_VDSAT 787 +#define BSIM3_QBS 788 +#define BSIM3_QBD 789 +#define BSIM3_SOURCECONDUCT 790 +#define BSIM3_DRAINCONDUCT 791 +#define BSIM3_CBDB 792 +#define BSIM3_CBSB 793 + +#define BSIM3_MOD_VGS_MAX 801 +#define BSIM3_MOD_VGD_MAX 802 +#define BSIM3_MOD_VGB_MAX 803 +#define BSIM3_MOD_VDS_MAX 804 +#define BSIM3_MOD_VBS_MAX 805 +#define BSIM3_MOD_VBD_MAX 806 +#define BSIM3_MOD_VGSR_MAX 807 +#define BSIM3_MOD_VGDR_MAX 808 +#define BSIM3_MOD_VGBR_MAX 809 +#define BSIM3_MOD_VBSR_MAX 810 +#define BSIM3_MOD_VBDR_MAX 811 + +#include "bsim3ext.h" + +extern void BSIM3SIMDevaluate(double,double,double,BSIM3instance*,BSIM3model*, + double*,double*,double*, double*, double*, double*, double*, + double*, double*, double*, double*, double*, double*, double*, + double*, double*, double*, double*, CKTcircuit*); +extern int BSIM3SIMDdebug(BSIM3model*, BSIM3instance*, CKTcircuit*, int); +extern int BSIM3SIMDcheckModel(BSIM3model*, BSIM3instance*, CKTcircuit*); + +#endif /*BSIM3*/ + diff --git a/src/spicelib/devices/bsim3simd/bsim3ext.h b/src/spicelib/devices/bsim3simd/bsim3ext.h new file mode 100644 index 000000000..2939410e1 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/bsim3ext.h @@ -0,0 +1,30 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1991 JianHui Huang and Min-Chie Jeng. +Modified by Yuhua Cheng to use BSIM3v3 in Spice3f5 (Jan. 1997) +File: bsim3ext.h +**********/ + +extern int BSIM3SIMDacLoad(GENmodel *,CKTcircuit*); +extern int BSIM3SIMDask(CKTcircuit *,GENinstance*,int,IFvalue*,IFvalue*); +extern int BSIM3SIMDconvTest(GENmodel *,CKTcircuit*); +extern int BSIM3SIMDgetic(GENmodel*,CKTcircuit*); +extern int BSIM3SIMDload(GENmodel*,CKTcircuit*); +extern int BSIM3SIMDloadSel(GENmodel*,CKTcircuit*); +extern int BSIM3SIMDmAsk(CKTcircuit*,GENmodel *,int, IFvalue*); +extern int BSIM3SIMDmDelete(GENmodel*); +extern int BSIM3SIMDmParam(int,IFvalue*,GENmodel*); +extern void BSIM3SIMDmosCap(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*); +extern int BSIM3SIMDparam(int,IFvalue*,GENinstance*,IFvalue*); +extern int BSIM3SIMDpzLoad(GENmodel*,CKTcircuit*,SPcomplex*); +extern int BSIM3SIMDsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int BSIM3SIMDtemp(GENmodel*,CKTcircuit*); +extern int BSIM3SIMDtrunc(GENmodel*,CKTcircuit*,double*); +extern int BSIM3SIMDnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); +extern int BSIM3SIMDunsetup(GENmodel*,CKTcircuit*); +extern int BSIM3SIMDsoaCheck(CKTcircuit *, GENmodel *); diff --git a/src/spicelib/devices/bsim3simd/bsim3init.c b/src/spicelib/devices/bsim3simd/bsim3init.c new file mode 100644 index 000000000..3ea85164d --- /dev/null +++ b/src/spicelib/devices/bsim3simd/bsim3init.c @@ -0,0 +1,78 @@ +#include "ngspice/config.h" + +#include "ngspice/devdefs.h" + +#include "bsim3itf.h" +#include "bsim3ext.h" +#include "bsim3init.h" + + +SPICEdev BSIM3SIMDinfo = { + .DEVpublic = { + .name = "BSIM3simd", + .description = "Berkeley Short Channel IGFET Model Version-3", + .terms = &BSIM3SIMDnSize, + .numNames = &BSIM3SIMDnSize, + .termNames = BSIM3SIMDnames, + .numInstanceParms = &BSIM3SIMDpTSize, + .instanceParms = BSIM3SIMDpTable, + .numModelParms = &BSIM3SIMDmPTSize, + .modelParms = BSIM3SIMDmPTable, + .flags = DEV_DEFAULT, + +#ifdef XSPICE + .cm_func = NULL, + .num_conn = 0, + .conn = NULL, + .num_param = 0, + .param = NULL, + .num_inst_var = 0, + .inst_var = NULL, +#endif + }, + + .DEVparam = BSIM3SIMDparam, + .DEVmodParam = BSIM3SIMDmParam, + .DEVload = BSIM3SIMDloadSel, + .DEVsetup = BSIM3SIMDsetup, + .DEVunsetup = BSIM3SIMDunsetup, + .DEVpzSetup = BSIM3SIMDsetup, + .DEVtemperature = BSIM3SIMDtemp, + .DEVtrunc = BSIM3SIMDtrunc, + .DEVfindBranch = NULL, + .DEVacLoad = BSIM3SIMDacLoad, + .DEVaccept = NULL, + .DEVdestroy = NULL, + .DEVmodDelete = BSIM3SIMDmDelete, + .DEVdelete = NULL, + .DEVsetic = BSIM3SIMDgetic, + .DEVask = BSIM3SIMDask, + .DEVmodAsk = BSIM3SIMDmAsk, + .DEVpzLoad = BSIM3SIMDpzLoad, + .DEVconvTest = BSIM3SIMDconvTest, + .DEVsenSetup = NULL, + .DEVsenLoad = NULL, + .DEVsenUpdate = NULL, + .DEVsenAcLoad = NULL, + .DEVsenPrint = NULL, + .DEVsenTrunc = NULL, + .DEVdisto = NULL, + .DEVnoise = BSIM3SIMDnoise, + .DEVsoaCheck = BSIM3SIMDsoaCheck, + .DEVinstSize = &BSIM3SIMDiSize, + .DEVmodSize = &BSIM3SIMDmSize, + +#ifdef CIDER + .DEVdump = NULL, + .DEVacct = NULL, +#endif +}; + + +SPICEdev * +get_bsim3simd_info(void) +{ + return &BSIM3SIMDinfo; +} + + diff --git a/src/spicelib/devices/bsim3simd/bsim3init.h b/src/spicelib/devices/bsim3simd/bsim3init.h new file mode 100644 index 000000000..24e1d637d --- /dev/null +++ b/src/spicelib/devices/bsim3simd/bsim3init.h @@ -0,0 +1,13 @@ +#ifndef _BSIM3SIMDINIT_H +#define _BSIM3SIMDINIT_H + +extern IFparm BSIM3SIMDpTable[ ]; +extern IFparm BSIM3SIMDmPTable[ ]; +extern char *BSIM3SIMDnames[ ]; +extern int BSIM3SIMDpTSize; +extern int BSIM3SIMDmPTSize; +extern int BSIM3SIMDnSize; +extern int BSIM3SIMDiSize; +extern int BSIM3SIMDmSize; + +#endif diff --git a/src/spicelib/devices/bsim3simd/bsim3itf.h b/src/spicelib/devices/bsim3simd/bsim3itf.h new file mode 100644 index 000000000..ca2fd2ec7 --- /dev/null +++ b/src/spicelib/devices/bsim3simd/bsim3itf.h @@ -0,0 +1,12 @@ +/********** +Copyright 1999 Regents of the University of California. All rights reserved. +Author: 1991 JianHui Huang and Min-Chie Jeng. +File: bsim3itf.h +**********/ + +#ifndef DEV_BSIM3SIMD +#define DEV_BSIM3SIMD + +SPICEdev *get_bsim3simd_info(void); + +#endif diff --git a/src/spicelib/devices/bsim3v32simd/b3v32ldsimd4d.c b/src/spicelib/devices/bsim3v32simd/b3v32ldsimd4d.c index 0de5af537..886af5a73 100644 --- a/src/spicelib/devices/bsim3v32simd/b3v32ldsimd4d.c +++ b/src/spicelib/devices/bsim3v32simd/b3v32ldsimd4d.c @@ -39,7 +39,7 @@ #define vec4_powMJSWG(x,p) vec4_pow(x,p) -#ifdef USE_SLEEF +#ifdef HAVE_LIBSLEEF #include #define vec4_exp(a) Sleef_expd4_u10(a) #define vec4_log(a) Sleef_logd4_u35(a) @@ -50,7 +50,7 @@ #endif -/* HAS_LIBMVEC defined from configure.ac */ +/* HAS_LIBMVEC and/or HAVE_LIBSLEEF defined from configure.ac */ /* USE_SERIAL_FORM can be defined but has no performance influence */ @@ -73,7 +73,7 @@ static inline Vec4d vec4_blend(Vec4d fa, Vec4d tr, Vec4m mask) } #endif -#ifndef USE_SLEEF +#ifndef HAVE_LIBSLEEF /******* vec4_exp, vec4_log *******/ #ifdef HAS_LIBMVEC Vec4d _ZGVdN4v_exp(Vec4d x); @@ -161,7 +161,7 @@ static inline Vec4d vec4_pow(Vec4d x, double p) return vec4_exp(vec4_log(x)*p); } -#endif /* USE_SLEEF */ +#endif /* HAVE_LIBSLEEF */ /******* vec4_SIMDTOVECTOR, vec4_SIMDTOVECTORMASK *******/ #ifdef USE_SERIAL_FORM diff --git a/src/spicelib/devices/dev.c b/src/spicelib/devices/dev.c index c7ffaa1a2..529102d74 100644 --- a/src/spicelib/devices/dev.c +++ b/src/spicelib/devices/dev.c @@ -79,6 +79,7 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */ #include "bsim1/bsim1itf.h" #include "bsim2/bsim2itf.h" #include "bsim3/bsim3itf.h" +#include "bsim3simd/bsim3itf.h" #include "bsim3v0/bsim3v0itf.h" #include "bsim3v1/bsim3v1itf.h" #include "bsim3v32/bsim3v32itf.h" @@ -218,8 +219,9 @@ static SPICEdev *(*static_devices[])(void) = { get_ndev_info, #endif -#ifdef BSIM3v32SIMD +#ifdef MODSIMD get_bsim3v32simd_info, + get_bsim3simd_info, #endif }; @@ -299,12 +301,12 @@ SPICEdev ** devices(void) /*not yet usable*/ #ifdef ADMS -#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v32simd", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ +#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3simd", "bsim3v32", "bsim3v32simd", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ "bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \ "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \ "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum0", "hicum2", "bjt504t", "ekv", "psp102"} #else -#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v32simd", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ +#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3simd", "bsim3v32", "bsim3v32simd", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ "bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \ "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \ "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc"} diff --git a/src/spicelib/parser/inp2m.c b/src/spicelib/parser/inp2m.c index ecfa9c100..bd633a911 100644 --- a/src/spicelib/parser/inp2m.c +++ b/src/spicelib/parser/inp2m.c @@ -120,7 +120,6 @@ INP2M(CKTcircuit *ckt, INPtables *tab, struct card *current) thismodel->INPmodType != INPtypelook("BSIM2") && thismodel->INPmodType != INPtypelook("BSIM3") && thismodel->INPmodType != INPtypelook("BSIM3v32") && - thismodel->INPmodType != INPtypelook("BSIM3v32simd") && thismodel->INPmodType != INPtypelook("B4SOI") && thismodel->INPmodType != INPtypelook("B3SOIPD") && thismodel->INPmodType != INPtypelook("B3SOIFD") && @@ -138,6 +137,10 @@ INP2M(CKTcircuit *ckt, INPtables *tab, struct card *current) #ifdef ADMS thismodel->INPmodType != INPtypelook("ekv") && thismodel->INPmodType != INPtypelook("psp102") && +#endif +#ifdef MODSIMD + thismodel->INPmodType != INPtypelook("BSIM3v32simd") && + thismodel->INPmodType != INPtypelook("BSIM3simd") && #endif thismodel->INPmodType != INPtypelook("HiSIM2") && thismodel->INPmodType != INPtypelook("HiSIMHV1") && diff --git a/src/spicelib/parser/inpdomod.c b/src/spicelib/parser/inpdomod.c index 03422cf91..9871564dd 100644 --- a/src/spicelib/parser/inpdomod.c +++ b/src/spicelib/parser/inpdomod.c @@ -7,9 +7,34 @@ Author: 1985 Thomas L. Quarles #include "ngspice/iferrmsg.h" #include "ngspice/inpdefs.h" #include "inpxx.h" -#ifdef BSIM3v32SIMD +#ifdef MODSIMD #include "ngspice/cpextern.h" #endif + +#ifdef MODSIMD +int SIMDselect(const char* ver) +{ + const char* ev; + ev = getenv("NGSPICE_MODSIMD"); + if(ev && strcmp(ev,"never")==0) + return 0; + if(ev && strcmp(ev,"always")==0) + return 1; + + if(((strlen(ver)>5) && (strcmp(&ver[strlen(ver)-4],"simd")==0)) + || cp_getvar("modsimd", CP_BOOL, NULL, 0) + #if defined(MODSIMD_ALWAYS) + || 1 + #endif + ) + return 1; + else + return 0; +} +#else +#define SIMDselect 0 +#endif + /*-------------------------------------------------------------- * This fcn takes the model card & examines it. Depending upon * model type, it parses the model line, and then calls @@ -301,30 +326,28 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab) type = INPtypelook("BSIM3v1"); } if (prefix("3.2", ver)) { /* version string ver has to start with 3.2 */ - #ifdef BSIM3v32SIMD - if(((strlen(ver)>5) && (strcmp(&ver[strlen(ver)-4],"simd")==0)) - || cp_getvar("modsimd", CP_BOOL, NULL, 0) - #if defined(MODSIMD_ALWAYS) - || 1 - #endif - ) + if(SIMDselect(ver)) type = INPtypelook("BSIM3v32simd"); else - #endif /* BSIM3v32SIMD */ type = INPtypelook("BSIM3v32"); } if ( (strstr(ver, "default")) || (prefix("3.3", ver)) ) { - type = INPtypelook("BSIM3"); + if(SIMDselect(ver)) + type = INPtypelook("BSIM3simd"); + else + type = INPtypelook("BSIM3"); } if (type < 0) { err = tprintf("Device type BSIM3 version %s not available in this binary\n", ver); } break; - case 88: + case 88: /* level 88 select simd version of BSIM3 - not so useful and should be removed */ err = INPfindVer(line, ver); if (prefix("3.2", ver)) { /* version string ver has to start with 3.2 */ type = INPtypelook("BSIM3v32simd"); } + if ( (strstr(ver, "default")) || (prefix("3.3", ver)) ) + type = INPtypelook("BSIM3simd"); if (type < 0) { err = tprintf("Device type BSIM3(simd) version %s not available in this binary\n", ver); } diff --git a/src/spicelib/parser/inpgmod.c b/src/spicelib/parser/inpgmod.c index 0c26c4e3e..958ce1eb1 100644 --- a/src/spicelib/parser/inpgmod.c +++ b/src/spicelib/parser/inpgmod.c @@ -244,7 +244,8 @@ INPgetModBin(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab, char /* skip if not binnable */ if (modtmp->INPmodType != INPtypelook("BSIM3") && - modtmp->INPmodType != INPtypelook("BSIM3v32") && + modtmp->INPmodType != INPtypelook("BSIM3simd") && + modtmp->INPmodType != INPtypelook("BSIM3v32") && modtmp->INPmodType != INPtypelook("BSIM3v32simd") && modtmp->INPmodType != INPtypelook("BSIM3v0") && modtmp->INPmodType != INPtypelook("BSIM3v1") &&