From 06846167cefdf14d7362720d6d6b6f08d58d7be1 Mon Sep 17 00:00:00 2001 From: Francesco Lannutti Date: Sat, 26 Apr 2014 20:09:21 +0200 Subject: [PATCH] CUSPICE Integration from scratch --- configure.ac | 59 +- examples/CUSPICE/Circuits | 1 + .../CUSPICE/Test_Current_Source_Model.net | 10 + examples/CUSPICE/Test_Inductor_Model.net | 9 + .../CUSPICE/Test_Mutual_Inductor_Model.net | 11 + src/frontend/misccoms.c | 8 + src/include/ngspice/CUSPICE/CUSPICE.h | 78 + src/include/ngspice/CUSPICE/cuniinteg.cuh | 36 + src/include/ngspice/bool.h | 2 + src/include/ngspice/cktdefs.h | 39 + src/include/ngspice/devdefs.h | 7 + src/include/ngspice/smpdefs.h | 8 + src/libtool_wrapper_for_cuda.tcl | 58 + src/maths/ni/niinit.c | 7 + src/spicelib/analysis/CUSPICE/cucktflush.c | 50 + .../analysis/CUSPICE/cucktnonconupdate.c | 68 + .../analysis/CUSPICE/cucktrhsoldupdate.c | 86 + src/spicelib/analysis/CUSPICE/cucktsetup.c | 145 + .../analysis/CUSPICE/cucktstatesupdate.c | 164 + src/spicelib/analysis/CUSPICE/cucktsystem.c | 63 + src/spicelib/analysis/Makefile.am | 15 + src/spicelib/analysis/cktdest.c | 5 + src/spicelib/analysis/cktload.c | 105 +- src/spicelib/analysis/cktop.c | 54 + src/spicelib/analysis/cktsetup.c | 204 + src/spicelib/analysis/dctran.c | 38 +- src/spicelib/devices/asrc/asrcinit.c | 4 + src/spicelib/devices/bjt/bjtinit.c | 4 + src/spicelib/devices/bsim1/bsim1init.c | 4 + src/spicelib/devices/bsim2/bsim2init.c | 4 + src/spicelib/devices/bsim3/bsim3init.c | 4 + .../devices/bsim3soi_dd/b3soiddinit.c | 6 +- .../devices/bsim3soi_fd/b3soifdinit.c | 4 + .../devices/bsim3soi_pd/b3soipdinit.c | 4 + src/spicelib/devices/bsim3v0/bsim3v0init.c | 4 + src/spicelib/devices/bsim3v1/bsim3v1init.c | 4 + src/spicelib/devices/bsim3v32/bsim3v32init.c | 4 + src/spicelib/devices/bsim4v5/bsim4v5init.c | 5 +- src/spicelib/devices/bsim4v6/bsim4v6init.c | 5 +- .../devices/bsim4v7/CUSPICE/b4v7topology.c | 844 +++ .../devices/bsim4v7/CUSPICE/cubsim4v7free.c | 845 +++ .../devices/bsim4v7/CUSPICE/cubsim4v7getic.c | 63 + .../devices/bsim4v7/CUSPICE/cubsim4v7load.cu | 5357 +++++++++++++++++ .../devices/bsim4v7/CUSPICE/cubsim4v7setup.c | 1123 ++++ .../devices/bsim4v7/CUSPICE/cubsim4v7temp.c | 633 ++ src/spicelib/devices/bsim4v7/Makefile.am | 15 + src/spicelib/devices/bsim4v7/b4v7getic.c | 32 +- src/spicelib/devices/bsim4v7/b4v7set.c | 566 ++ src/spicelib/devices/bsim4v7/b4v7temp.c | 203 + src/spicelib/devices/bsim4v7/bsim4v7def.h | 558 ++ src/spicelib/devices/bsim4v7/bsim4v7ext.h | 4 + src/spicelib/devices/bsim4v7/bsim4v7init.c | 11 + src/spicelib/devices/bsimsoi/b4soiinit.c | 6 +- .../devices/cap/CUSPICE/captopology.c | 99 + src/spicelib/devices/cap/CUSPICE/cucapfree.c | 69 + src/spicelib/devices/cap/CUSPICE/cucapgetic.c | 56 + src/spicelib/devices/cap/CUSPICE/cucapload.cu | 162 + src/spicelib/devices/cap/CUSPICE/cucapsetup.c | 111 + src/spicelib/devices/cap/CUSPICE/cucaptemp.c | 71 + src/spicelib/devices/cap/Makefile.am | 15 + src/spicelib/devices/cap/capdefs.h | 48 + src/spicelib/devices/cap/capext.h | 4 + src/spicelib/devices/cap/capinit.c | 11 + src/spicelib/devices/cap/capsetup.c | 89 + src/spicelib/devices/cap/captemp.c | 30 +- src/spicelib/devices/cccs/cccsinit.c | 4 + src/spicelib/devices/ccvs/ccvsinit.c | 4 + src/spicelib/devices/cpl/cplinit.c | 4 + src/spicelib/devices/csw/cswinit.c | 4 + src/spicelib/devices/dio/dioinit.c | 5 +- src/spicelib/devices/hfet1/hfetinit.c | 4 + src/spicelib/devices/hfet2/hfet2init.c | 5 +- src/spicelib/devices/hisim2/hsm2init.c | 5 +- src/spicelib/devices/hisimhv1/hsmhvinit.c | 5 +- src/spicelib/devices/ind/CUSPICE/cuindfree.c | 63 + src/spicelib/devices/ind/CUSPICE/cuindload.cu | 170 + src/spicelib/devices/ind/CUSPICE/cuindsetup.c | 103 + src/spicelib/devices/ind/CUSPICE/cuindtemp.c | 68 + src/spicelib/devices/ind/CUSPICE/cumutfree.c | 60 + src/spicelib/devices/ind/CUSPICE/cumutload.cu | 169 + src/spicelib/devices/ind/CUSPICE/cumutsetup.c | 113 + src/spicelib/devices/ind/CUSPICE/cumuttemp.c | 71 + .../devices/ind/CUSPICE/indtopology.c | 99 + .../devices/ind/CUSPICE/muttopology.c | 72 + src/spicelib/devices/ind/Makefile.am | 21 + src/spicelib/devices/ind/inddefs.h | 98 +- src/spicelib/devices/ind/indext.h | 5 + src/spicelib/devices/ind/indinit.c | 19 + src/spicelib/devices/ind/indload.c | 1 + src/spicelib/devices/ind/indsacl.c | 3 + src/spicelib/devices/ind/indsetup.c | 102 +- src/spicelib/devices/ind/indsupd.c | 5 +- src/spicelib/devices/ind/indtemp.c | 30 +- src/spicelib/devices/ind/mutacld.c | 1 - src/spicelib/devices/ind/mutsetup.c | 85 + src/spicelib/devices/ind/muttemp.c | 31 +- .../devices/isrc/CUSPICE/cuisrcfree.c | 85 + .../devices/isrc/CUSPICE/cuisrcload.cu | 431 ++ .../devices/isrc/CUSPICE/cuisrcsetup.c | 127 + .../devices/isrc/CUSPICE/cuisrctemp.c | 81 + .../devices/isrc/CUSPICE/isrctopology.c | 70 + src/spicelib/devices/isrc/Makefile.am | 17 +- src/spicelib/devices/isrc/isrcdefs.h | 51 + src/spicelib/devices/isrc/isrcext.h | 5 + src/spicelib/devices/isrc/isrcinit.c | 15 + src/spicelib/devices/isrc/isrcpar.c | 5 + src/spicelib/devices/isrc/isrcsetup.c | 81 + src/spicelib/devices/isrc/isrctemp.c | 36 +- src/spicelib/devices/jfet/jfetinit.c | 5 +- src/spicelib/devices/jfet2/jfet2init.c | 5 +- src/spicelib/devices/ltra/ltrainit.c | 5 +- src/spicelib/devices/mes/mesinit.c | 5 +- src/spicelib/devices/mesa/mesainit.c | 5 +- src/spicelib/devices/mos1/mos1init.c | 5 +- src/spicelib/devices/mos2/mos2init.c | 5 +- src/spicelib/devices/mos3/mos3init.c | 5 +- src/spicelib/devices/mos6/mos6init.c | 5 +- src/spicelib/devices/mos9/mos9init.c | 5 +- src/spicelib/devices/nbjt/nbjtinit.c | 5 +- src/spicelib/devices/nbjt2/nbt2init.c | 5 +- src/spicelib/devices/ndev/ndevinit.c | 5 +- src/spicelib/devices/numd/numdinit.c | 5 +- src/spicelib/devices/numd2/numd2init.c | 5 +- src/spicelib/devices/numos/numosinit.c | 5 +- src/spicelib/devices/res/CUSPICE/curesfree.c | 84 + src/spicelib/devices/res/CUSPICE/curesload.cu | 117 + src/spicelib/devices/res/CUSPICE/curessetup.c | 125 + src/spicelib/devices/res/CUSPICE/curestemp.c | 89 + .../devices/res/CUSPICE/restopology.c | 84 + src/spicelib/devices/res/Makefile.am | 14 + src/spicelib/devices/res/resdefs.h | 53 + src/spicelib/devices/res/resext.h | 4 + src/spicelib/devices/res/resinit.c | 11 + src/spicelib/devices/res/ressetup.c | 69 +- src/spicelib/devices/res/restemp.c | 30 + src/spicelib/devices/soi3/soi3init.c | 5 +- src/spicelib/devices/sw/swinit.c | 5 +- src/spicelib/devices/tra/trainit.c | 5 +- src/spicelib/devices/txl/txlinit.c | 4 + src/spicelib/devices/urc/urcinit.c | 5 +- src/spicelib/devices/vbic/vbicinit.c | 5 +- src/spicelib/devices/vccs/vccsinit.c | 5 +- src/spicelib/devices/vcvs/vcvsinit.c | 5 +- .../devices/vsrc/CUSPICE/cuvsrcfree.c | 94 + .../devices/vsrc/CUSPICE/cuvsrcload.cu | 489 ++ .../devices/vsrc/CUSPICE/cuvsrcsetup.c | 145 + .../devices/vsrc/CUSPICE/cuvsrctemp.c | 90 + .../devices/vsrc/CUSPICE/vsrctopology.c | 93 + src/spicelib/devices/vsrc/Makefile.am | 14 + src/spicelib/devices/vsrc/vsrcdefs.h | 61 + src/spicelib/devices/vsrc/vsrcext.h | 4 + src/spicelib/devices/vsrc/vsrcinit.c | 11 + src/spicelib/devices/vsrc/vsrcpar.c | 5 + src/spicelib/devices/vsrc/vsrcset.c | 89 +- src/spicelib/devices/vsrc/vsrctemp.c | 41 +- 155 files changed, 16718 insertions(+), 61 deletions(-) create mode 120000 examples/CUSPICE/Circuits create mode 100644 examples/CUSPICE/Test_Current_Source_Model.net create mode 100644 examples/CUSPICE/Test_Inductor_Model.net create mode 100644 examples/CUSPICE/Test_Mutual_Inductor_Model.net create mode 100644 src/include/ngspice/CUSPICE/CUSPICE.h create mode 100644 src/include/ngspice/CUSPICE/cuniinteg.cuh create mode 100755 src/libtool_wrapper_for_cuda.tcl create mode 100644 src/spicelib/analysis/CUSPICE/cucktflush.c create mode 100644 src/spicelib/analysis/CUSPICE/cucktnonconupdate.c create mode 100644 src/spicelib/analysis/CUSPICE/cucktrhsoldupdate.c create mode 100644 src/spicelib/analysis/CUSPICE/cucktsetup.c create mode 100644 src/spicelib/analysis/CUSPICE/cucktstatesupdate.c create mode 100644 src/spicelib/analysis/CUSPICE/cucktsystem.c create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/b4v7topology.c create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7free.c create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7getic.c create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7load.cu create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7setup.c create mode 100644 src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7temp.c create mode 100644 src/spicelib/devices/cap/CUSPICE/captopology.c create mode 100644 src/spicelib/devices/cap/CUSPICE/cucapfree.c create mode 100644 src/spicelib/devices/cap/CUSPICE/cucapgetic.c create mode 100644 src/spicelib/devices/cap/CUSPICE/cucapload.cu create mode 100644 src/spicelib/devices/cap/CUSPICE/cucapsetup.c create mode 100644 src/spicelib/devices/cap/CUSPICE/cucaptemp.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cuindfree.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cuindload.cu create mode 100644 src/spicelib/devices/ind/CUSPICE/cuindsetup.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cuindtemp.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cumutfree.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cumutload.cu create mode 100644 src/spicelib/devices/ind/CUSPICE/cumutsetup.c create mode 100644 src/spicelib/devices/ind/CUSPICE/cumuttemp.c create mode 100644 src/spicelib/devices/ind/CUSPICE/indtopology.c create mode 100644 src/spicelib/devices/ind/CUSPICE/muttopology.c create mode 100644 src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c create mode 100644 src/spicelib/devices/isrc/CUSPICE/cuisrcload.cu create mode 100644 src/spicelib/devices/isrc/CUSPICE/cuisrcsetup.c create mode 100644 src/spicelib/devices/isrc/CUSPICE/cuisrctemp.c create mode 100644 src/spicelib/devices/isrc/CUSPICE/isrctopology.c create mode 100644 src/spicelib/devices/isrc/isrcsetup.c create mode 100644 src/spicelib/devices/res/CUSPICE/curesfree.c create mode 100644 src/spicelib/devices/res/CUSPICE/curesload.cu create mode 100644 src/spicelib/devices/res/CUSPICE/curessetup.c create mode 100644 src/spicelib/devices/res/CUSPICE/curestemp.c create mode 100644 src/spicelib/devices/res/CUSPICE/restopology.c create mode 100644 src/spicelib/devices/vsrc/CUSPICE/cuvsrcfree.c create mode 100644 src/spicelib/devices/vsrc/CUSPICE/cuvsrcload.cu create mode 100644 src/spicelib/devices/vsrc/CUSPICE/cuvsrcsetup.c create mode 100644 src/spicelib/devices/vsrc/CUSPICE/cuvsrctemp.c create mode 100644 src/spicelib/devices/vsrc/CUSPICE/vsrctopology.c diff --git a/configure.ac b/configure.ac index 92ebfc65f..2a26c6db6 100644 --- a/configure.ac +++ b/configure.ac @@ -207,7 +207,64 @@ if test "x$enable_klu" = xyes; then AC_DEFINE(KLU, [], [Define if we want KLU linear systems solver]) AC_MSG_WARN([KLU solver enabled]) fi -AM_CONDITIONAL([KLU_WANTED], [test "x$enable_klu" = xyes]) +AM_CONDITIONAL([KLU_WANTED], [test "x$enable_klu" = xyes || test "x$enable_cuspice" = xyes]) + +# --enable-cuspice: Use CUSPICE (NGSPICE on CUDA Platforms) +AC_ARG_ENABLE([cuspice], + [AS_HELP_STRING([--enable-cuspice], [Use CUSPICE (NGSPICE on CUDA Platforms)])]) + +# Add CUSPICE (NGSPICE on CUDA Platforms) to NGSPICE +if test "x$enable_cuspice" = xyes; then + AC_DEFINE(USE_CUSPICE, [], [Define if we want CUSPICE (NGSPICE on CUDA Platforms) enabled]) + AC_MSG_WARN(CUSPICE (NGSPICE on CUDA Platforms) enabled) + AC_ARG_WITH([cuda], + [AS_HELP_STRING([--with-cuda=PATH], [Define the prefix where cuda is installed (default=/usr/local/cuda)])]) + ARCH=`uname -m` + if test -n "$with_cuda" + then + CUDA_CPPFLAGS="-I$with_cuda/include" + if [[ $ARCH == "x86_64" ]] + then + CUDA_LIBS="-L$with_cuda/lib64 -lcuda -lcudart" + else + CUDA_LIBS="-L$with_cuda/lib -lcuda -lcudart" + fi + NVCC="$with_cuda/bin/nvcc" + else + CUDA_CPPFLAGS="-I/usr/local/cuda/include" + if [[ $ARCH == "x86_64" ]] + then + CUDA_LIBS="-L/usr/local/cuda/lib64 -lcuda -lcudart" + else + CUDA_LIBS="-L/usr/local/cuda/lib -lcuda -lcudart" + fi + AC_PATH_PROG(NVCC, nvcc, "no") + AS_IF([test "x$NVCC" = xno], + [AC_MSG_ERROR([NVCC compiler not found!])]) + NVCC="nvcc" + fi + AC_SUBST(CUDA_CPPFLAGS) + AC_SUBST(CUDA_LIBS) + AC_SUBST(NVCC) + + # NVCC Compilation Flags + CUDA_CFLAGS="-gencode arch=compute_20,\"code=sm_20\"" + CUDA_CFLAGS+=" -gencode arch=compute_30,\"code=sm_30\"" + CUDA_CFLAGS+=" -gencode arch=compute_32,\"code=sm_32\"" + CUDA_CFLAGS+=" -gencode arch=compute_35,\"code=sm_35\"" + CUDA_CFLAGS+=" -gencode arch=compute_50,\"code=sm_50\"" + CUDA_CFLAGS+=" -DCOMPILED_BY_NVCC" + if test "x$enable_debug" = xno; then + CUDA_CFLAGS+=" -O2" + else + CUDA_CFLAGS+=" -g -O1 -G" + fi + AC_SUBST(CUDA_CFLAGS) + + AC_DEFINE(KLU, [], [Define if we want KLU linear systems solver]) + AC_MSG_WARN([KLU solver enabled, because CUSPICE needs it]) +fi +AM_CONDITIONAL([USE_CUSPICE_WANTED], [test "x$enable_cuspice" = xyes]) # Enable maintainer commands only if requested diff --git a/examples/CUSPICE/Circuits b/examples/CUSPICE/Circuits new file mode 120000 index 000000000..8d662efc2 --- /dev/null +++ b/examples/CUSPICE/Circuits @@ -0,0 +1 @@ +../klu/Circuits \ No newline at end of file diff --git a/examples/CUSPICE/Test_Current_Source_Model.net b/examples/CUSPICE/Test_Current_Source_Model.net new file mode 100644 index 000000000..a17a337b6 --- /dev/null +++ b/examples/CUSPICE/Test_Current_Source_Model.net @@ -0,0 +1,10 @@ +* Test Current Source Model + +I1 0 1 pulse(0 1 0p 200p 200p 1n 2n) +R1 0 1 1k +R2 1 2 0.5k +R3 2 0 0.2k + +.tran 1ps 1ns +.print tran all +.end diff --git a/examples/CUSPICE/Test_Inductor_Model.net b/examples/CUSPICE/Test_Inductor_Model.net new file mode 100644 index 000000000..345dec55b --- /dev/null +++ b/examples/CUSPICE/Test_Inductor_Model.net @@ -0,0 +1,9 @@ +* Test Inductor Model + +V1 0 1 pulse(0 1 0p 200p 200p 1n 2n) +R1 1 2 10 +L1 2 0 10 + +.tran 1ps 1ns +.print tran all +.end diff --git a/examples/CUSPICE/Test_Mutual_Inductor_Model.net b/examples/CUSPICE/Test_Mutual_Inductor_Model.net new file mode 100644 index 000000000..7d3e80e55 --- /dev/null +++ b/examples/CUSPICE/Test_Mutual_Inductor_Model.net @@ -0,0 +1,11 @@ +* Test Mutual Inductor Model + +V1 0 1 pulse(0 1 0p 200p 200p 1n 2n) +R1 1 2 10 +L1 2 0 10 +L2 3 0 10 +K1 L1 L2 0.5 + +.tran 1ps 1ns +.print tran all +.end diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index 5623c97ec..b004a7e20 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -189,6 +189,10 @@ com_version(wordlist *wl) "** Compiled with Sparse Direct Linear Solver\n" #endif +#ifdef USE_CUSPICE + "** Compiled with CUSPICE (NGSPICE on CUDA Platforms)\n" +#endif + "** The U. C. Berkeley CAD Group\n" "** Copyright 1985-1994, Regents of the University of California.\n" "** %s\n", @@ -229,6 +233,10 @@ com_version(wordlist *wl) "** Compiled with Sparse Direct Linear Solver\n" #endif +#ifdef USE_CUSPICE + "** Compiled with CUSPICE (NGSPICE on CUDA Platforms)\n" +#endif + "** The U. C. Berkeley CAD Group\n" "** Copyright 1985-1994, Regents of the University of California.\n" "** %s\n", diff --git a/src/include/ngspice/CUSPICE/CUSPICE.h b/src/include/ngspice/CUSPICE/CUSPICE.h new file mode 100644 index 000000000..770424553 --- /dev/null +++ b/src/include/ngspice/CUSPICE/CUSPICE.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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. + */ + +int cuCKTcsrmv (CKTcircuit *) ; +int cuCKTflush (CKTcircuit *) ; +int cuCKTnonconUpdateHtoD (CKTcircuit *) ; +int cuCKTnonconUpdateDtoH (CKTcircuit *) ; +int cuCKTrhsOldFlush (CKTcircuit *) ; +int cuCKTrhsOldUpdateHtoD (CKTcircuit *) ; +int cuCKTrhsOldUpdateDtoH (CKTcircuit *) ; +int cuCKTsetup (CKTcircuit *) ; +int cuCKTsystemDtoH (CKTcircuit *) ; +int cuCKTstatesFlush (CKTcircuit *) ; +int cuCKTstatesUpdateDtoH (CKTcircuit *) ; +int cuCKTstate0UpdateHtoD (CKTcircuit *) ; +int cuCKTstate0UpdateDtoH (CKTcircuit *) ; +int cuCKTstate01copy (CKTcircuit *) ; +int cuCKTstatesCircularBuffer (CKTcircuit *) ; +int cuCKTstate123copy (CKTcircuit *) ; + +int cuBSIM4v7destroy (GENmodel *) ; +int cuBSIM4v7getic (GENmodel *) ; +int cuBSIM4v7load (GENmodel *, CKTcircuit *) ; +int cuBSIM4v7setup (GENmodel *) ; +int cuBSIM4v7temp (GENmodel *) ; + +int cuCAPdestroy (GENmodel *) ; +int cuCAPgetic (GENmodel *) ; +int cuCAPload (GENmodel *, CKTcircuit *) ; +int cuCAPsetup (GENmodel *) ; +int cuCAPtemp (GENmodel *) ; + +int cuINDdestroy (GENmodel *) ; +int cuINDload (GENmodel *, CKTcircuit *) ; +int cuINDsetup (GENmodel *) ; +int cuINDtemp (GENmodel *) ; + +int cuISRCdestroy (GENmodel *) ; +int cuISRCload (GENmodel *, CKTcircuit *) ; +int cuISRCsetup (GENmodel *) ; +int cuISRCtemp (GENmodel *) ; + +int cuMUTdestroy (GENmodel *) ; +int cuMUTload (GENmodel *, CKTcircuit *) ; +int cuMUTsetup (GENmodel *) ; +int cuMUTtemp (GENmodel *) ; + +int cuRESdestroy (GENmodel *) ; +int cuRESload (GENmodel *, CKTcircuit *) ; +int cuRESsetup (GENmodel *) ; +int cuREStemp (GENmodel *) ; + +int cuVSRCdestroy (GENmodel *) ; +int cuVSRCload (GENmodel *, CKTcircuit *) ; +int cuVSRCsetup (GENmodel *) ; +int cuVSRCtemp (GENmodel *) ; diff --git a/src/include/ngspice/CUSPICE/cuniinteg.cuh b/src/include/ngspice/CUSPICE/cuniinteg.cuh new file mode 100644 index 000000000..306434422 --- /dev/null +++ b/src/include/ngspice/CUSPICE/cuniinteg.cuh @@ -0,0 +1,36 @@ +#include +#include "ngspice/sperror.h" + +extern "C" +__device__ +static +int +cuNIintegrate_device_kernel +( +double *CKTstate_0, double *CKTstate_1, double *geq, double *ceq, +double value, int charge, double CKTag_0, double CKTag_1, int CKTorder +) +{ + +#define current charge+1 + + switch (CKTorder) + { + case 1: + CKTstate_0 [current] = CKTag_0 * (CKTstate_0 [charge]) + CKTag_1 * (CKTstate_1 [charge]) ; + break ; + + case 2: + CKTstate_0 [current] = -CKTstate_1 [current] * CKTag_1 + CKTag_0 * (CKTstate_0 [charge] - CKTstate_1 [charge]) ; + break ; + + default: + printf ("Error inside the integration formula\n") ; + return (E_ORDER) ; + } + + *ceq = CKTstate_0 [current] - CKTag_0 * CKTstate_0 [charge] ; + *geq = CKTag_0 * value ; + + return (OK) ; +} diff --git a/src/include/ngspice/bool.h b/src/include/ngspice/bool.h index 6bdc0df8e..5bc4c7c8d 100644 --- a/src/include/ngspice/bool.h +++ b/src/include/ngspice/bool.h @@ -2,7 +2,9 @@ #define ngspice_BOOL_H //typedef unsigned char bool; +#ifndef COMPILED_BY_NVCC typedef int bool; +#endif typedef int BOOL ; diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 5668d67f1..410bb0a40 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -303,6 +303,45 @@ struct CKTcircuit { #ifdef KLU unsigned int CKTkluMODE:1; #endif + +#ifdef USE_CUSPICE + double *(d_CKTstates[8]); +#define d_CKTstate0 d_CKTstates[0] +#define d_CKTstate1 d_CKTstates[1] +#define d_CKTstate2 d_CKTstates[2] +#define d_CKTstate3 d_CKTstates[3] +#define d_CKTstate4 d_CKTstates[4] +#define d_CKTstate5 d_CKTstates[5] +#define d_CKTstate6 d_CKTstates[6] +#define d_CKTstate7 d_CKTstates[7] + + double *d_CKTrhsOld; + int *d_CKTnoncon; + int d_MatrixSize; + + int CKTdiagElements; + int total_n_values; + int total_n_Ptr; + double *d_CKTloadOutput; + int *CKTtopologyMatrixCOOi; + int *CKTtopologyMatrixCOOj; + double *CKTtopologyMatrixCOOx; + int *CKTtopologyMatrixCSRp; + int *d_CKTtopologyMatrixCSRp; + int *d_CKTtopologyMatrixCSRj; + double *d_CKTtopologyMatrixCSRx; + + int total_n_valuesRHS; + int total_n_PtrRHS; + double *d_CKTloadOutputRHS; + int *CKTtopologyMatrixCOOiRHS; + int *CKTtopologyMatrixCOOjRHS; + double *CKTtopologyMatrixCOOxRHS; + int *CKTtopologyMatrixCSRpRHS; + int *d_CKTtopologyMatrixCSRpRHS; + int *d_CKTtopologyMatrixCSRjRHS; + double *d_CKTtopologyMatrixCSRxRHS; +#endif }; diff --git a/src/include/ngspice/devdefs.h b/src/include/ngspice/devdefs.h index be65de693..b6aeb89e0 100644 --- a/src/include/ngspice/devdefs.h +++ b/src/include/ngspice/devdefs.h @@ -123,6 +123,13 @@ typedef struct SPICEdev { /* routine to convert Complex CSC array to Real CSC array */ #endif +#ifdef USE_CUSPICE + int (*cuDEVdestroy)(GENmodel *) ; + /* routine to Destroy the CUSPICE allocations */ + int (*DEVtopology)(GENmodel *, CKTcircuit *, int *, int *) ; + /* routine to create the Topology Matrix */ +#endif + } SPICEdev; /* instance of structure for each possible type of device */ diff --git a/src/include/ngspice/smpdefs.h b/src/include/ngspice/smpdefs.h index 432d90adf..cdd5e9028 100644 --- a/src/include/ngspice/smpdefs.h +++ b/src/include/ngspice/smpdefs.h @@ -49,6 +49,14 @@ typedef struct sSMPmatrix { #define CKTkluOFF 0 /* KLU MODE OFF definition */ #endif +#ifdef USE_CUSPICE + double *d_CKTkluAx ; + double *d_CKTrhs ; + + void *CKTcsrmvHandle ; + void *CKTcsrmvDescr ; +#endif + } SMPmatrix ; diff --git a/src/libtool_wrapper_for_cuda.tcl b/src/libtool_wrapper_for_cuda.tcl new file mode 100755 index 000000000..31f0c3886 --- /dev/null +++ b/src/libtool_wrapper_for_cuda.tcl @@ -0,0 +1,58 @@ +#!/usr/bin/tclsh + +if {$argc == 0} { + puts "Usage: 'libtool_wrapper_for_cuda.tcl' 'filename' 'compilation line'" + exit 1 +} + +# Rename object file .lo in .o +set filename_lo [lindex $argv 0] +set filename_o [file rootname $filename_lo].o + +# Determine where the object file has to be created and the NVCC compilation command +if {[lindex $argv 1] == "-static"} { + set filename $filename_o + set command [lrange $argv 2 end] + append command " -o $filename" +} else { + file mkdir .libs + set filename ".libs/${filename_o}" + set command [lrange $argv 2 end] + append command " -Xcompiler -fPIC" + append command " -o $filename" +} + +# Compile +exec /bin/sh -c $command + +# Determine the libtool version (including compiler version) +catch {exec libtool --help} output +set output [split $output "\n"] +foreach elem $output { + if {[regexp -- {libtool:\t(.+)$} $elem -> version]} { + break + } +} + +# Generate the .lo libtool object file +set fid [open $filename_lo w] +puts $fid "# $filename_lo - a libtool object file" +puts $fid "# Generated by libtool $version" +puts $fid "#" +puts $fid "# Please DO NOT delete this file!" +puts $fid "# It is necessary for linking the library." +puts $fid "" +if {[lindex $argv 1] == "-static"} { + puts $fid "# Name of the PIC object." + puts $fid "pic_object=none" + puts $fid "" + puts $fid "# Name of the non-PIC object" + puts $fid "non_pic_object='[file tail $filename]'" +} else { + puts $fid "# Name of the PIC object." + puts $fid "pic_object='[file tail $filename]'" + puts $fid "" + puts $fid "# Name of the non-PIC object" + puts $fid "non_pic_object=none" +} +close $fid diff --git a/src/maths/ni/niinit.c b/src/maths/ni/niinit.c index 301269de5..526c8104a 100644 --- a/src/maths/ni/niinit.c +++ b/src/maths/ni/niinit.c @@ -50,6 +50,13 @@ NIinit(CKTcircuit *ckt) klu_defaults (ckt->CKTmatrix->CKTkluCommon) ; #endif +#ifdef USE_CUSPICE + ckt->CKTmatrix->d_CKTkluAx = NULL ; + ckt->CKTmatrix->d_CKTrhs = NULL ; + ckt->CKTmatrix->CKTcsrmvHandle = NULL ; + ckt->CKTmatrix->CKTcsrmvDescr = NULL ; +#endif + ckt->CKTniState = NIUNINITIALIZED; return SMPnewMatrix(ckt->CKTmatrix, 0); } diff --git a/src/spicelib/analysis/CUSPICE/cucktflush.c b/src/spicelib/analysis/CUSPICE/cucktflush.c new file mode 100644 index 000000000..fe6bf801f --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktflush.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuCKTflush +( +CKTcircuit *ckt +) +{ + long unsigned int m, mRHS ; + + m = (long unsigned int)(ckt->total_n_values + 1) ; // + 1 because of CKTdiagGmin + mRHS = (long unsigned int)ckt->total_n_valuesRHS ; + + /* Clean-up the CKTloadOutput */ + cudaMemset (ckt->d_CKTloadOutput, 0, m * sizeof(double)) ; + + /* Clean-up the CKTloadOutputRHS */ + cudaMemset (ckt->d_CKTloadOutputRHS, 0, mRHS * sizeof(double)) ; + + return (OK) ; +} diff --git a/src/spicelib/analysis/CUSPICE/cucktnonconupdate.c b/src/spicelib/analysis/CUSPICE/cucktnonconupdate.c new file mode 100644 index 000000000..f56377153 --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktnonconupdate.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTnonconUpdate routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCKTnonconUpdateHtoD +( +CKTcircuit *ckt +) +{ + cudaError_t status ; + + status = cudaMemcpy (ckt->d_CKTnoncon, &(ckt->CKTnoncon), sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTnoncon, 1, int, status) + + return (OK) ; +} + +int +cuCKTnonconUpdateDtoH +( +CKTcircuit *ckt +) +{ + cudaError_t status ; + + status = cudaMemcpy (&(ckt->CKTnoncon), ckt->d_CKTnoncon, sizeof(int), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (&(ckt->CKTnoncon), 1, int, status) + + return (OK) ; +} diff --git a/src/spicelib/analysis/CUSPICE/cucktrhsoldupdate.c b/src/spicelib/analysis/CUSPICE/cucktrhsoldupdate.c new file mode 100644 index 000000000..1e07e0281 --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktrhsoldupdate.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTrhsOldUpdate routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCKTrhsOldFlush +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + + size = (long unsigned int)(ckt->d_MatrixSize + 1) ; + cudaMemset (ckt->d_CKTrhsOld, 0, size * sizeof(double)) ; + + return (OK) ; +} + +int +cuCKTrhsOldUpdateHtoD +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)(ckt->d_MatrixSize + 1) ; + status = cudaMemcpy (ckt->d_CKTrhsOld, ckt->CKTrhsOld, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTrhsOld, size, double, status) + + return (OK) ; +} + +int +cuCKTrhsOldUpdateDtoH +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)(ckt->d_MatrixSize + 1) ; + status = cudaMemcpy (ckt->CKTrhsOld, ckt->d_CKTrhsOld, size * sizeof(double), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (ckt->CKTrhsOld, size, double, status) + + return (OK) ; +} diff --git a/src/spicelib/analysis/CUSPICE/cucktsetup.c b/src/spicelib/analysis/CUSPICE/cucktsetup.c new file mode 100644 index 000000000..e8097facb --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktsetup.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCKTsetup +( +CKTcircuit *ckt +) +{ + int i ; + long unsigned int m, mRHS, n, nz, TopologyNNZ, TopologyNNZRHS, size1, size2 ; + cudaError_t status ; + + n = (long unsigned int)ckt->CKTmatrix->CKTkluN ; + nz = (long unsigned int)ckt->CKTmatrix->CKTklunz ; + + m = (long unsigned int)(ckt->total_n_values + 1) ; // + 1 because of CKTdiagGmin + + TopologyNNZ = (long unsigned int)(ckt->total_n_Ptr + ckt->CKTdiagElements) ; // + n because of CKTdiagGmin + // without the zeroes along the diagonal + + mRHS = (long unsigned int)ckt->total_n_valuesRHS ; + TopologyNNZRHS = (long unsigned int)ckt->total_n_PtrRHS ; + + size1 = (long unsigned int)(ckt->d_MatrixSize + 1) ; + size2 = (long unsigned int)ckt->CKTnumStates ; + + /* Topology Matrix Handling */ + status = cudaMalloc ((void **)&(ckt->CKTmatrix->d_CKTrhs), (n + 1) * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->CKTmatrix->d_CKTrhs, (n + 1), double, status) + + status = cudaMalloc ((void **)&(ckt->CKTmatrix->d_CKTkluAx), nz * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->CKTmatrix->d_CKTkluAx, nz, double, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTloadOutput), m * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTloadOutput, m, double, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTloadOutputRHS), mRHS * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTloadOutputRHS, mRHS, double, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRp), (nz + 1) * sizeof(int)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRp, (nz + 1), int, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRj), TopologyNNZ * sizeof(int)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRj, TopologyNNZ, int, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRx), TopologyNNZ * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRx, TopologyNNZ, double, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRpRHS), ((n + 1) + 1) * sizeof(int)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRpRHS, ((n + 1) + 1), int, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRjRHS), TopologyNNZRHS * sizeof(int)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRjRHS, TopologyNNZRHS, int, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTtopologyMatrixCSRxRHS), TopologyNNZRHS * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTtopologyMatrixCSRxRHS, TopologyNNZRHS, double, status) + + + cudaMemset (ckt->d_CKTloadOutput + ckt->total_n_values, 0, sizeof(double)) ; //DiagGmin is 0 at the beginning + + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRp, ckt->CKTtopologyMatrixCSRp, (nz + 1) * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRp, (nz + 1), int, status) + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRj, ckt->CKTtopologyMatrixCOOj, TopologyNNZ * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRj, TopologyNNZ, int, status) + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRx, ckt->CKTtopologyMatrixCOOx, TopologyNNZ * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRx, TopologyNNZ, double, status) + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRpRHS, ckt->CKTtopologyMatrixCSRpRHS, ((n + 1) + 1) * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRpRHS, ((n + 1) + 1), int, status) + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRjRHS, ckt->CKTtopologyMatrixCOOjRHS, TopologyNNZRHS * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRjRHS, TopologyNNZRHS, int, status) + + status = cudaMemcpy (ckt->d_CKTtopologyMatrixCSRxRHS, ckt->CKTtopologyMatrixCOOxRHS, TopologyNNZRHS * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTtopologyMatrixCSRxRHS, TopologyNNZRHS, double, status) + /* ------------------------ */ + + status = cudaMalloc ((void **)&(ckt->d_CKTnoncon), sizeof(int)) ; + CUDAMALLOCCHECK (ckt->d_CKTnoncon, 1, int, status) + + status = cudaMalloc ((void **)&(ckt->d_CKTrhsOld), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTrhsOld, size1, double, status) + + for (i = 0 ; i <= MAX (2, ckt->CKTmaxOrder) + 1 ; i++) /* dctran needs 3 states at least */ + { + status = cudaMalloc ((void **)&(ckt->d_CKTstates[i]), size2 * sizeof(double)) ; + CUDAMALLOCCHECK (ckt->d_CKTstates[i], size2, double, status) + } + + return (OK) ; +} diff --git a/src/spicelib/analysis/CUSPICE/cucktstatesupdate.c b/src/spicelib/analysis/CUSPICE/cucktstatesupdate.c new file mode 100644 index 000000000..46c2d4fef --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktstatesupdate.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTstatesUpdate routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCKTstatesUpdateDtoH +( +CKTcircuit *ckt +) +{ + int i ; + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)ckt->CKTnumStates ; + + for (i = 0 ; i < 8 ; i++) + { + if (ckt->CKTstates[i] != NULL) + { + status = cudaMemcpy (ckt->CKTstates[i], ckt->d_CKTstates[i], size * sizeof(double), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (ckt->CKTstates[i], size, double, status) + } + } + + return (OK) ; +} + +int +cuCKTstatesFlush +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + + size = (long unsigned int)ckt->CKTnumStates ; + cudaMemset (ckt->d_CKTstate0, 0, size * sizeof(double)) ; + + return (OK) ; +} + +int +cuCKTstate0UpdateHtoD +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)ckt->CKTnumStates ; + status = cudaMemcpy (ckt->d_CKTstate0, ckt->CKTstate0, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTstate0, size, double, status) + + return (OK) ; +} + +int +cuCKTstate0UpdateDtoH +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)ckt->CKTnumStates ; + status = cudaMemcpy (ckt->CKTstate0, ckt->d_CKTstate0, size * sizeof(double), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (ckt->CKTstate0, size, double, status) + + return (OK) ; +} + +int +cuCKTstate01copy +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)ckt->CKTnumStates ; + status = cudaMemcpy (ckt->d_CKTstate1, ckt->d_CKTstate0, size * sizeof(double), cudaMemcpyDeviceToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTstate1, size, double, status) + + return (OK) ; +} + +int +cuCKTstatesCircularBuffer +( +CKTcircuit *ckt +) +{ + int i ; + double *temp ; + + temp = ckt->d_CKTstates [ckt->CKTmaxOrder + 1] ; + for (i = ckt->CKTmaxOrder ; i >= 0 ; i--) + ckt->d_CKTstates [i + 1] = ckt->d_CKTstates [i] ; + + ckt->d_CKTstates [0] = temp ; + + return (OK) ; +} + +int +cuCKTstate123copy +( +CKTcircuit *ckt +) +{ + long unsigned int size ; + cudaError_t status ; + + size = (long unsigned int)ckt->CKTnumStates ; + + status = cudaMemcpy (ckt->d_CKTstate2, ckt->d_CKTstate1, size * sizeof(double), cudaMemcpyDeviceToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTstate2, size, double, status) + + status = cudaMemcpy (ckt->d_CKTstate3, ckt->d_CKTstate1, size * sizeof(double), cudaMemcpyDeviceToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTstate3, size, double, status) + + return (OK) ; +} diff --git a/src/spicelib/analysis/CUSPICE/cucktsystem.c b/src/spicelib/analysis/CUSPICE/cucktsystem.c new file mode 100644 index 000000000..447a6d654 --- /dev/null +++ b/src/spicelib/analysis/CUSPICE/cucktsystem.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "cuda_runtime_api.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTsystem routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCKTsystemDtoH +( +CKTcircuit *ckt +) +{ + long unsigned int nz, n ; + cudaError_t status ; + + nz = (long unsigned int)ckt->CKTmatrix->CKTklunz ; + n = (long unsigned int)ckt->CKTmatrix->CKTkluN ; + + /* Copy back the Matrix */ + status = cudaMemcpy (ckt->CKTmatrix->CKTkluAx, ckt->CKTmatrix->d_CKTkluAx, nz * sizeof(double), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (ckt->CKTmatrix->CKTkluAx, nz, double, status) + + /* Copy back the RHS */ + status = cudaMemcpy (ckt->CKTrhs, ckt->CKTmatrix->d_CKTrhs, (n + 1) * sizeof(double), cudaMemcpyDeviceToHost) ; + CUDAMEMCPYCHECK (ckt->CKTrhs, (n + 1), double, status) + + return (OK) ; +} diff --git a/src/spicelib/analysis/Makefile.am b/src/spicelib/analysis/Makefile.am index 86d6b7371..5770a90aa 100644 --- a/src/spicelib/analysis/Makefile.am +++ b/src/spicelib/analysis/Makefile.am @@ -109,4 +109,19 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices AM_CFLAGS = $(STATIC) + +if USE_CUSPICE_WANTED + +libckt_la_SOURCES += \ + CUSPICE/cucktflush.c \ + CUSPICE/cucktnonconupdate.c \ + CUSPICE/cucktrhsoldupdate.c \ + CUSPICE/cucktsetup.c \ + CUSPICE/cucktstatesupdate.c \ + CUSPICE/cucktsystem.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +AM_LDFLAGS = $(CUDA_LIBS) -lcusparse +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/analysis/cktdest.c b/src/spicelib/analysis/cktdest.c index 6136c7ff4..a8415ccf2 100644 --- a/src/spicelib/analysis/cktdest.c +++ b/src/spicelib/analysis/cktdest.c @@ -40,6 +40,11 @@ CKTdestroy(CKTcircuit *ckt) for (i = 0; i < DEVmaxnum; i++) if (DEVices[i]) { GENmodel *model = ckt->CKThead[i]; + #warning "this needs to be reviewed, due to rebase onto newer master!" +#ifdef USE_CUSPICE + if (DEVices[i]->cuDEVdestroy && model) + DEVices[i]->cuDEVdestroy(model); +#endif while (model) { GENmodel *next_model = model->GENnextModel; GENinstance *inst = model->GENinstances; diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index b56f7e255..71d7648f6 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -18,6 +18,23 @@ Modified: 2000 AlansFixes #include "ngspice/devdefs.h" #include "ngspice/sperror.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#include "cuda_runtime.h" +#include "cusparse_v2.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCKTload routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +#endif + #ifdef XSPICE #include "ngspice/enh.h" /* gtri - add - wbk - 11/26/90 - add include for MIF global data */ @@ -30,8 +47,17 @@ static int ZeroNoncurRow(SMPmatrix *matrix, CKTnode *nodes, int rownum); int CKTload(CKTcircuit *ckt) { +#ifdef USE_CUSPICE + cusparseStatus_t cusparseStatus ; + double alpha, beta ; + int status ; + alpha = 1.0 ; + beta = 0.0 ; +#else + int size ; +#endif + int i; - int size; double startTime; CKTnode *node; int error; @@ -50,18 +76,43 @@ CKTload(CKTcircuit *ckt) #endif startTime = SPfrontEnd->IFseconds(); - size = SMPmatSize(ckt->CKTmatrix); - for (i = 0; i <= size; i++) { - ckt->CKTrhs[i] = 0; - } - SMPclear(ckt->CKTmatrix); + +#ifdef USE_CUSPICE + status = cuCKTflush (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#else + size = SMPmatSize (ckt->CKTmatrix) ; + for (i = 0 ; i <= size ; i++) + *(ckt->CKTrhs + i) = 0 ; + + SMPclear (ckt->CKTmatrix) ; +#endif + #ifdef STEPDEBUG noncon = ckt->CKTnoncon; #endif /* STEPDEBUG */ +#ifdef USE_CUSPICE + status = cuCKTnonconUpdateHtoD (ckt) ; + if (status != 0) + return (E_NOMEM) ; + + status = cuCKTrhsOldUpdateHtoD (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + for (i = 0; i < DEVmaxnum; i++) { if (DEVices[i] && DEVices[i]->DEVload && ckt->CKThead[i]) { error = DEVices[i]->DEVload (ckt->CKThead[i], ckt); + +#ifdef USE_CUSPICE + status = cuCKTnonconUpdateDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + if (ckt->CKTnoncon) ckt->CKTtroubleNode = 0; #ifdef STEPDEBUG @@ -75,6 +126,48 @@ CKTload(CKTcircuit *ckt) } } +#ifdef USE_CUSPICE + /* Copy the CKTdiagGmin value to the GPU */ + status = cudaMemcpy (ckt->d_CKTloadOutput + ckt->total_n_values, &(ckt->CKTdiagGmin), sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (ckt->d_CKTloadOutput + ckt->total_n_values, 1, double, status) + + /* Performing CSRMV for the Sparse Matrix using CUSPARSE */ + cusparseStatus = cusparseDcsrmv ((cusparseHandle_t)(ckt->CKTmatrix->CKTcsrmvHandle), + CUSPARSE_OPERATION_NON_TRANSPOSE, + ckt->CKTmatrix->CKTklunz, ckt->total_n_values + 1, + ckt->total_n_Ptr + ckt->CKTdiagElements, + &alpha, (cusparseMatDescr_t)(ckt->CKTmatrix->CKTcsrmvDescr), + ckt->d_CKTtopologyMatrixCSRx, ckt->d_CKTtopologyMatrixCSRp, + ckt->d_CKTtopologyMatrixCSRj, ckt->d_CKTloadOutput, &beta, + ckt->CKTmatrix->d_CKTkluAx) ; + + if (cusparseStatus != CUSPARSE_STATUS_SUCCESS) + { + fprintf (stderr, "CUSPARSE MATRIX Call Error\n") ; + return (E_NOMEM) ; + } + + /* Performing CSRMV for the RHS using CUSPARSE */ + cusparseStatus = cusparseDcsrmv ((cusparseHandle_t)(ckt->CKTmatrix->CKTcsrmvHandle), + CUSPARSE_OPERATION_NON_TRANSPOSE, + ckt->CKTmatrix->CKTkluN + 1, ckt->total_n_valuesRHS, ckt->total_n_PtrRHS, + &alpha, (cusparseMatDescr_t)(ckt->CKTmatrix->CKTcsrmvDescr), + ckt->d_CKTtopologyMatrixCSRxRHS, ckt->d_CKTtopologyMatrixCSRpRHS, + ckt->d_CKTtopologyMatrixCSRjRHS, ckt->d_CKTloadOutputRHS, &beta, + ckt->CKTmatrix->d_CKTrhs) ; + + if (cusparseStatus != CUSPARSE_STATUS_SUCCESS) + { + fprintf (stderr, "CUSPARSE RHS Call Error\n") ; + return (E_NOMEM) ; + } + + cudaDeviceSynchronize () ; + + status = cuCKTsystemDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif #ifdef XSPICE /* gtri - add - wbk - 11/26/90 - reset the MIF init flags */ diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index e9b1fb075..18e302d35 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -20,6 +20,9 @@ static int spice3_gmin(CKTcircuit *, long int, long int, int); static int gillespie_src(CKTcircuit *, long int, long int, int); static int spice3_src(CKTcircuit *, long int, long int, int); +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif int CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode, @@ -127,6 +130,10 @@ static int dynamic_gmin (CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) { +#ifdef USE_CUSPICE + int status ; +#endif + double OldGmin, gtarget, factor; int converged; @@ -150,6 +157,12 @@ dynamic_gmin (CKTcircuit *ckt, long int firstmode, for (i = 0; i < ckt->CKTnumStates; i++) ckt->CKTstate0 [i] = 0; +#ifdef USE_CUSPICE + status = cuCKTstatesFlush (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + factor = ckt->CKTgminFactor; OldGmin = 1e-2; ckt->CKTdiagGmin = OldGmin / factor; @@ -173,6 +186,12 @@ dynamic_gmin (CKTcircuit *ckt, long int firstmode, for (i = 0, n = ckt->CKTnodes; n; n = n->next) OldRhsOld[i++] = ckt->CKTrhsOld[n->number]; +#ifdef USE_CUSPICE + status = cuCKTstate0UpdateDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + memcpy(OldCKTstate0, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); @@ -207,6 +226,13 @@ dynamic_gmin (CKTcircuit *ckt, long int firstmode, memcpy(ckt->CKTstate0, OldCKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); + +#ifdef USE_CUSPICE + status = cuCKTstate0UpdateHtoD (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } } @@ -320,6 +346,10 @@ static int gillespie_src (CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) { +#ifdef USE_CUSPICE + int status ; +#endif + int converged, i, iters; double ConvFact; CKTnode *n; @@ -338,6 +368,12 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, for (i = 0; i < ckt->CKTnumStates; i++) ckt->CKTstate0[i] = 0; +#ifdef USE_CUSPICE + status = cuCKTstatesFlush (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + /* First, try a straight solution with all sources at zero */ fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); @@ -398,6 +434,12 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, for (i = 0, n = ckt->CKTnodes; n; n = n->next) OldRhsOld[i++] = ckt->CKTrhsOld[n->number]; +#ifdef USE_CUSPICE + status = cuCKTstate0UpdateDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + memcpy(OldCKTstate0, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); @@ -425,6 +467,12 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, for (i = 0, n = ckt->CKTnodes; n; n = n->next) OldRhsOld[i++] = ckt->CKTrhsOld[n->number]; +#ifdef USE_CUSPICE + status = cuCKTstate0UpdateDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + memcpy(OldCKTstate0, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); @@ -460,6 +508,12 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, memcpy(ckt->CKTstate0, OldCKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); +#ifdef USE_CUSPICE + status = cuCKTstate0UpdateHtoD (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } if (ckt->CKTsrcFact > 1) diff --git a/src/spicelib/analysis/cktsetup.c b/src/spicelib/analysis/cktsetup.c index a841af434..497cbfc97 100644 --- a/src/spicelib/analysis/cktsetup.c +++ b/src/spicelib/analysis/cktsetup.c @@ -19,6 +19,11 @@ Author: 1985 Thomas L. Quarles #include "ngspice/enh.h" #endif +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#include "cusparse_v2.h" +#endif + #ifdef USE_OMP #include #include "ngspice/cpextern.h" @@ -45,9 +50,62 @@ BindCompare (const void *a, const void *b) } #endif +#ifdef USE_CUSPICE +typedef struct sElement { + int row ; + int col ; + double val ; +} Element ; + +static +int +Compare (const void *a, const void *b) +{ + Element *A, *B ; + A = (Element *)a ; + B = (Element *)b ; + return (A->row - B->row) ; +} + +static +int +Compress (int *Ai, int *Bp, int num_rows, int n_COO) +{ + int i, j ; + + for (i = 0 ; i <= Ai [0] ; i++) + Bp [i] = 0 ; + + j = Ai [0] + 1 ; + for (i = 1 ; i < n_COO ; i++) + { + if (Ai [i] == Ai [i - 1] + 1) + { + Bp [j] = i ; + j++ ; + } + else if (Ai [i] > Ai [i - 1] + 1) + { + for ( ; j <= Ai [i] ; j++) + Bp [j] = i ; + } + } + + for ( ; j <= num_rows ; j++) + Bp [j] = i ; + + return 0 ; +} +#endif + int CKTsetup(CKTcircuit *ckt) { +#ifdef USE_CUSPICE + int status ; + cusparseStatus_t cusparseStatus ; +#endif + int i; int error; #ifdef XSPICE @@ -143,6 +201,124 @@ CKTsetup(CKTcircuit *ckt) DEVices [i]->DEVbindCSC (ckt->CKThead [i], ckt) ; ckt->CKTmatrix->CKTkluMatrixIsComplex = CKTkluMatrixReal ; + +#ifdef USE_CUSPICE + fprintf (stderr, "Using CUSPICE (NGSPICE on CUDA Platforms)\n") ; + + /* In the DEVsetup the Position Vectors must be assigned and copied to the GPU */ + int j, k, u, TopologyNNZ ; + int uRHS, TopologyNNZRHS ; + int ret ; + + + /* CKTloadOutput Vector allocation - DIRECTLY in the GPU memory */ + + /* CKTloadOutput for the RHS Vector allocation - DIRECTLY in the GPU memory */ + + + /* Diagonal Elements Counting */ + j = 0 ; + for (i = 0 ; i < n ; i++) + if (ckt->CKTmatrix->CKTdiag_CSC [i] != NULL) + j++ ; + + ckt->CKTdiagElements = j ; + + /* Topology Matrix Pre-Allocation in COO format */ + TopologyNNZ = ckt->total_n_Ptr + ckt->CKTdiagElements ; // + ckt->CKTdiagElements because of CKTdiagGmin + // without the zeroes along the diagonal + ckt->CKTtopologyMatrixCOOi = TMALLOC (int, TopologyNNZ) ; + ckt->CKTtopologyMatrixCOOj = TMALLOC (int, TopologyNNZ) ; + ckt->CKTtopologyMatrixCOOx = TMALLOC (double, TopologyNNZ) ; + + /* Topology Matrix for the RHS Pre-Allocation in COO format */ + TopologyNNZRHS = ckt->total_n_PtrRHS ; + ckt->CKTtopologyMatrixCOOiRHS = TMALLOC (int, TopologyNNZRHS) ; + ckt->CKTtopologyMatrixCOOjRHS = TMALLOC (int, TopologyNNZRHS) ; + ckt->CKTtopologyMatrixCOOxRHS = TMALLOC (double, TopologyNNZRHS) ; + + + /* Topology Matrix Pre-Allocation in CSR format */ + ckt->CKTtopologyMatrixCSRp = TMALLOC (int, nz + 1) ; + + /* Topology Matrix for the RHS Pre-Allocation in CSR format */ + ckt->CKTtopologyMatrixCSRpRHS = TMALLOC (int, (n + 1) + 1) ; + + + /* Topology Matrix Construction & Topology Matrix for the RHS Construction */ + + u = 0 ; + uRHS = 0 ; + for (i = 0 ; i < DEVmaxnum ; i++) + if (DEVices [i] && DEVices [i]->DEVtopology && ckt->CKThead [i]) + DEVices [i]->DEVtopology (ckt->CKThead [i], ckt, &u, &uRHS) ; + + + /* CKTdiagGmin Contribute Addition to the Topology Matrix */ + k = u ; + for (j = 0 ; j < n ; j++) + { + if (ckt->CKTmatrix->CKTdiag_CSC [j] >= ckt->CKTmatrix->CKTkluAx) + { + ckt->CKTtopologyMatrixCOOi [k] = (int)(ckt->CKTmatrix->CKTdiag_CSC [j] - ckt->CKTmatrix->CKTkluAx) ; + ckt->CKTtopologyMatrixCOOj [k] = ckt->total_n_values ; + ckt->CKTtopologyMatrixCOOx [k] = 1 ; + k++ ; + } + } + + /* Copy the Topology Matrix to the GPU in COO format */ + + + /* COO format to CSR format Conversion using Quick Sort */ + + Element *TopologyStruct ; + TopologyStruct = TMALLOC (Element, TopologyNNZ) ; + + for (i = 0 ; i < TopologyNNZ ; i++) + { + TopologyStruct [i].row = ckt->CKTtopologyMatrixCOOi [i] ; + TopologyStruct [i].col = ckt->CKTtopologyMatrixCOOj [i] ; + TopologyStruct [i].val = ckt->CKTtopologyMatrixCOOx [i] ; + } + + qsort (TopologyStruct, (size_t)TopologyNNZ, sizeof(Element), Compare) ; + + for (i = 0 ; i < TopologyNNZ ; i++) + { + ckt->CKTtopologyMatrixCOOi [i] = TopologyStruct [i].row ; + ckt->CKTtopologyMatrixCOOj [i] = TopologyStruct [i].col ; + ckt->CKTtopologyMatrixCOOx [i] = TopologyStruct [i].val ; + } + + ret = Compress (ckt->CKTtopologyMatrixCOOi, ckt->CKTtopologyMatrixCSRp, nz, TopologyNNZ) ; + + /* COO format to CSR format Conversion for the RHS using Quick Sort */ + + Element *TopologyStructRHS ; + TopologyStructRHS = TMALLOC (Element, TopologyNNZRHS) ; + + for (i = 0 ; i < TopologyNNZRHS ; i++) + { + TopologyStructRHS [i].row = ckt->CKTtopologyMatrixCOOiRHS [i] ; + TopologyStructRHS [i].col = ckt->CKTtopologyMatrixCOOjRHS [i] ; + TopologyStructRHS [i].val = ckt->CKTtopologyMatrixCOOxRHS [i] ; + } + + qsort (TopologyStructRHS, (size_t)TopologyNNZRHS, sizeof(Element), Compare) ; + + for (i = 0 ; i < TopologyNNZRHS ; i++) + { + ckt->CKTtopologyMatrixCOOiRHS [i] = TopologyStructRHS [i].row ; + ckt->CKTtopologyMatrixCOOjRHS [i] = TopologyStructRHS [i].col ; + ckt->CKTtopologyMatrixCOOxRHS [i] = TopologyStructRHS [i].val ; + } + + ret = Compress (ckt->CKTtopologyMatrixCOOiRHS, ckt->CKTtopologyMatrixCSRpRHS, n + 1, TopologyNNZRHS) ; + + /* Multiply the Topology Matrix by the M Vector to build the Final CSC Matrix - after the CKTload Call */ +#endif + } else { fprintf (stderr, "Using SPARSE 1.3 as Direct Linear Solver\n") ; } @@ -151,6 +327,34 @@ CKTsetup(CKTcircuit *ckt) for(i=0;i<=MAX(2,ckt->CKTmaxOrder)+1;i++) { /* dctran needs 3 states as minimum */ CKALLOC(ckt->CKTstates[i],ckt->CKTnumStates,double); } + +#ifdef USE_CUSPICE + ckt->d_MatrixSize = SMPmatSize (ckt->CKTmatrix) ; + status = cuCKTsetup (ckt) ; + if (status != 0) + return (E_NOMEM) ; + + /* CUSPARSE Handle Creation */ + cusparseStatus = cusparseCreate ((cusparseHandle_t *)(&(ckt->CKTmatrix->CKTcsrmvHandle))) ; + if (cusparseStatus != CUSPARSE_STATUS_SUCCESS) + { + fprintf (stderr, "CUSPARSE Handle Setup Error\n") ; + return (E_NOMEM) ; + } + + /* CUSPARSE Matrix Descriptor Creation */ + cusparseStatus = cusparseCreateMatDescr ((cusparseMatDescr_t *)(&(ckt->CKTmatrix->CKTcsrmvDescr))) ; + if (cusparseStatus != CUSPARSE_STATUS_SUCCESS) + { + fprintf (stderr, "CUSPARSE Matrix Descriptor Setup Error\n") ; + return (E_NOMEM) ; + } + + /* CUSPARSE Matrix Properties Definition */ + cusparseSetMatType ((cusparseMatDescr_t)(ckt->CKTmatrix->CKTcsrmvDescr), CUSPARSE_MATRIX_TYPE_GENERAL) ; + cusparseSetMatIndexBase ((cusparseMatDescr_t)(ckt->CKTmatrix->CKTcsrmvDescr), CUSPARSE_INDEX_BASE_ZERO) ; +#endif + #ifdef WANT_SENSE2 if(ckt->CKTsenInfo){ /* to allocate memory to sensitivity structures if diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index fc62f782a..6ad18bab0 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -62,18 +62,26 @@ do { \ ckt->CKTstat->STATtranSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \ } while(0) +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif int DCtran(CKTcircuit *ckt, int restart) /* forced restart flag */ { +#ifdef USE_CUSPICE + int status ; +#else + double *temp ; +#endif + TRANan *job = (TRANan *) ckt->CKTcurJob; int i; double olddelta; double delta; double newdelta; - double *temp; double startdTime; double startsTime; double startlTime; @@ -340,8 +348,15 @@ DCtran(CKTcircuit *ckt, ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODETRAN | MODEINITTRAN; /* modeinittran set here */ ckt->CKTag[0]=ckt->CKTag[1]=0; + +#ifdef USE_CUSPICE + status = cuCKTstate01copy (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#else memcpy(ckt->CKTstate1, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); +#endif #ifdef WANT_SENSE2 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){ @@ -705,11 +720,17 @@ resume: ckt->CKTdeltaOld[i+1] = ckt->CKTdeltaOld[i]; ckt->CKTdeltaOld[0] = ckt->CKTdelta; +#ifdef USE_CUSPICE + status = cuCKTstatesCircularBuffer (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#else temp = ckt->CKTstates[ckt->CKTmaxOrder+1]; for(i=ckt->CKTmaxOrder;i>=0;i--) { ckt->CKTstates[i+1] = ckt->CKTstates[i]; } ckt->CKTstates[0] = temp; +#endif /* 600 */ for (;;) { @@ -780,10 +801,18 @@ resume: ckt->CKTstat->STATtimePts ++; ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITPRED; if(firsttime) { + +#ifdef USE_CUSPICE + status = cuCKTstate123copy (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#else memcpy(ckt->CKTstate2, ckt->CKTstate1, (size_t) ckt->CKTnumStates * sizeof(double)); memcpy(ckt->CKTstate3, ckt->CKTstate1, (size_t) ckt->CKTnumStates * sizeof(double)); +#endif + } /* txl, cpl addition */ if (converged == 1111) { @@ -853,6 +882,13 @@ resume: goto chkStep; #endif } + +#ifdef USE_CUSPICE + status = cuCKTstatesUpdateDtoH (ckt) ; + if (status != 0) + return (E_NOMEM) ; +#endif + newdelta = ckt->CKTdelta; error = CKTtrunc(ckt,&newdelta); if(error) { diff --git a/src/spicelib/devices/asrc/asrcinit.c b/src/spicelib/devices/asrc/asrcinit.c index 9e716079b..05f8c2f7b 100644 --- a/src/spicelib/devices/asrc/asrcinit.c +++ b/src/spicelib/devices/asrc/asrcinit.c @@ -71,6 +71,10 @@ SPICEdev ASRCinfo = { .DEVbindCSCComplex = ASRCbindCSCComplex, .DEVbindCSCComplexToReal = ASRCbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bjt/bjtinit.c b/src/spicelib/devices/bjt/bjtinit.c index 1a568a9ea..0ead9b7b6 100644 --- a/src/spicelib/devices/bjt/bjtinit.c +++ b/src/spicelib/devices/bjt/bjtinit.c @@ -71,6 +71,10 @@ SPICEdev BJTinfo = { .DEVbindCSCComplex = BJTbindCSCComplex, .DEVbindCSCComplexToReal = BJTbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim1/bsim1init.c b/src/spicelib/devices/bsim1/bsim1init.c index 35cbe3d3b..ef9316862 100644 --- a/src/spicelib/devices/bsim1/bsim1init.c +++ b/src/spicelib/devices/bsim1/bsim1init.c @@ -71,6 +71,10 @@ SPICEdev B1info = { .DEVbindCSCComplex = B1bindCSCComplex, .DEVbindCSCComplexToReal = B1bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim2/bsim2init.c b/src/spicelib/devices/bsim2/bsim2init.c index cde441ba9..2cc2109c0 100644 --- a/src/spicelib/devices/bsim2/bsim2init.c +++ b/src/spicelib/devices/bsim2/bsim2init.c @@ -71,6 +71,10 @@ SPICEdev B2info = { .DEVbindCSCComplex = B2bindCSCComplex, .DEVbindCSCComplexToReal = B2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3/bsim3init.c b/src/spicelib/devices/bsim3/bsim3init.c index cb461e47c..271d429b3 100644 --- a/src/spicelib/devices/bsim3/bsim3init.c +++ b/src/spicelib/devices/bsim3/bsim3init.c @@ -71,6 +71,10 @@ SPICEdev BSIM3info = { .DEVbindCSCComplex = BSIM3bindCSCComplex, .DEVbindCSCComplexToReal = BSIM3bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c b/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c index fa5a41dee..b69381214 100644 --- a/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c +++ b/src/spicelib/devices/bsim3soi_dd/b3soiddinit.c @@ -69,6 +69,10 @@ SPICEdev B3SOIDDinfo = { .DEVbindCSCComplex = B3SOIDDbindCSCComplex, .DEVbindCSCComplexToReal = B3SOIDDbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; @@ -77,5 +81,3 @@ get_b3soidd_info (void) { return &B3SOIDDinfo; } - - diff --git a/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c b/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c index be2f77e38..d1c40835a 100644 --- a/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c +++ b/src/spicelib/devices/bsim3soi_fd/b3soifdinit.c @@ -69,6 +69,10 @@ SPICEdev B3SOIFDinfo = { .DEVbindCSCComplex = B3SOIFDbindCSCComplex, .DEVbindCSCComplexToReal = B3SOIFDbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c b/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c index bbd74b700..e8590bb56 100644 --- a/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c +++ b/src/spicelib/devices/bsim3soi_pd/b3soipdinit.c @@ -70,6 +70,10 @@ SPICEdev B3SOIPDinfo = { .DEVbindCSCComplex = B3SOIPDbindCSCComplex, .DEVbindCSCComplexToReal = B3SOIPDbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3v0/bsim3v0init.c b/src/spicelib/devices/bsim3v0/bsim3v0init.c index 6cf4353da..69d75373d 100644 --- a/src/spicelib/devices/bsim3v0/bsim3v0init.c +++ b/src/spicelib/devices/bsim3v0/bsim3v0init.c @@ -70,6 +70,10 @@ SPICEdev B3v0info = { .DEVbindCSCComplex = BSIM3v0bindCSCComplex, .DEVbindCSCComplexToReal = BSIM3v0bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3v1/bsim3v1init.c b/src/spicelib/devices/bsim3v1/bsim3v1init.c index 6268854d0..30fd4ebf7 100644 --- a/src/spicelib/devices/bsim3v1/bsim3v1init.c +++ b/src/spicelib/devices/bsim3v1/bsim3v1init.c @@ -70,6 +70,10 @@ SPICEdev BSIM3v1info = { .DEVbindCSCComplex = BSIM3v1bindCSCComplex, .DEVbindCSCComplexToReal = BSIM3v1bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim3v32/bsim3v32init.c b/src/spicelib/devices/bsim3v32/bsim3v32init.c index 3d7f0aa9c..4863a3e92 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32init.c +++ b/src/spicelib/devices/bsim3v32/bsim3v32init.c @@ -71,6 +71,10 @@ SPICEdev BSIM3v32info = { .DEVbindCSCComplex = BSIM3v32bindCSCComplex, .DEVbindCSCComplexToReal = BSIM3v32bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/bsim4v5/bsim4v5init.c b/src/spicelib/devices/bsim4v5/bsim4v5init.c index 36f9b2cce..6efef398d 100644 --- a/src/spicelib/devices/bsim4v5/bsim4v5init.c +++ b/src/spicelib/devices/bsim4v5/bsim4v5init.c @@ -71,9 +71,12 @@ SPICEdev BSIM4v5info = { .DEVbindCSCComplex = BSIM4v5bindCSCComplex, .DEVbindCSCComplexToReal = BSIM4v5bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_bsim4v5_info(void) { diff --git a/src/spicelib/devices/bsim4v6/bsim4v6init.c b/src/spicelib/devices/bsim4v6/bsim4v6init.c index 29ca2102e..87f08dcd0 100644 --- a/src/spicelib/devices/bsim4v6/bsim4v6init.c +++ b/src/spicelib/devices/bsim4v6/bsim4v6init.c @@ -71,9 +71,12 @@ SPICEdev BSIM4v6info = { .DEVbindCSCComplex = BSIM4v6bindCSCComplex, .DEVbindCSCComplexToReal = BSIM4v6bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_bsim4v6_info(void) { diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/b4v7topology.c b/src/spicelib/devices/bsim4v7/CUSPICE/b4v7topology.c new file mode 100644 index 000000000..9776a12bb --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/b4v7topology.c @@ -0,0 +1,844 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "bsim4v7def.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +#define TopologyMatrixInsertRHS(offset, instance_ID, offsetRHS, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOiRHS [global_ID] = here->offset ; \ + ckt->CKTtopologyMatrixCOOjRHS [global_ID] = model->PositionVectorRHS [instance_ID] + offsetRHS ; \ + ckt->CKTtopologyMatrixCOOxRHS [global_ID] = Value ; + +int +BSIM4v7topology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + BSIM4v7model *model = (BSIM4v7model *)inModel ; + BSIM4v7instance *here ; + int k, total_offset, total_offsetRHS ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the capacitor models */ + for ( ; model != NULL ; model = BSIM4v7nextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = BSIM4v7instances(model); here != NULL ; here = BSIM4v7nextInstance(here)) + { + total_offset = 0 ; + total_offsetRHS = 0 ; + + /* For the Matrix */ + if (here->BSIM4v7rgateMod == 1) + { + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgpPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (gcggb + geltd - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPspPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPbpPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + total_offset += 5 ; + } + else if (here->BSIM4v7rgateMod == 2) + { + /* m * gcrg */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgg */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GEdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgs */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GEspPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgb */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GEbpPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + /* m * gcrg */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgpPtr, k, 5, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPdpPtr, k, 6, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPspPtr, k, 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPbpPtr, k, 8, 1, *i) ; + (*i)++ ; + } + + total_offset += 9 ; + } + else if (here->BSIM4v7rgateMod == 3) + { + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7GEgmPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4v7GMgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (geltd + gcrg + gcgmgmb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7GMgmPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgd + gcgmdb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GMdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgg */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GMgpPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgs + gcgmsb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GMspPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgb + gcgmbb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GMbpPtr, k, 5, 1, *i) ; + (*i)++ ; + } + + /* m * gcdgmb */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7DPgmPtr, k, 6, 1, *i) ; + (*i)++ ; + } + + /* m * gcrg */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgmPtr, k, 7, -1, *i) ; + (*i)++ ; + } + + /* m * gcsgmb */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7SPgmPtr, k, 8, 1, *i) ; + (*i)++ ; + } + + /* m * gcbgmb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4v7BPgmPtr, k, 9, 1, *i) ; + (*i)++ ; + } + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgpPtr, k, 10, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPdpPtr, k, 11, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPspPtr, k, 12, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPbpPtr, k, 13, 1, *i) ; + (*i)++ ; + } + + total_offset += 14 ; + } else { + /* m * (gcggb - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPgpPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPdpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPspPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7GPbpPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + total_offset += 4 ; + } + + + if (model->BSIM4v7rdsMod) + { + /* m * gdtotg */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DgpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * gdtots */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DspPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * gdtotb */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DbpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * gstotd */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SdpPtr, k, total_offset + 3, 1, *i) ; + (*i)++ ; + } + + /* m * gstotg */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SgpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * gstotb */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SbpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + total_offset += 4 ; + } + + + /* m * (gdpr + here->BSIM4v7gds + here->BSIM4v7gbd + T1 * ddxpart_dVd - + gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd) + m * ggidld */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DPdpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DPdPtr, k, total_offset + 1, -1, *i) ; + (*i)++ ; + } + + /* m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + dxpart * ggtg + T1 * ddxpart_dVg) + m * ggidlg */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DPgpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7gds + gdtots - dxpart * ggts + gIdtots - + T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp) + m * (ggidlg + ggidld + ggidlb) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DPspPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb - T1 * ddxpart_dVb - dxpart * ggtb) - m * ggidlb */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DPbpPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * (gdpr - gdtotd) */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DdpPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7dNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DdPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7gds + gstotd + RevSum - gcsdb - gbspdp - + T1 * dsxpart_dVd - sxpart * ggtd + gIstotd) + m * (ggisls + ggislg + ggislb) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SPdpPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + T1 * dsxpart_dVg - gIstotg) + m * ggislg */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SPgpPtr, k, total_offset + 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gspr + here->BSIM4v7gds + here->BSIM4v7gbs + T1 * dsxpart_dVs - + gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots) + m * ggisls */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SPspPtr, k, total_offset + 8, 1, *i) ; + (*i)++ ; + } + + /* m * (gspr + gstot) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SPsPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb - T1 * dsxpart_dVb + gIstotb) - m * ggislb */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SPbpPtr, k, total_offset + 10, -1, *i) ; + (*i)++ ; + } + + /* m * (gspr - gstots) */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SspPtr, k, total_offset + 11, -1, *i) ; + (*i)++ ; + } + + /* m * (gspr + gstot) */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7sNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SsPtr, k, total_offset + 9, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbdb - gjbd + gbbdp - gIbtotd) - m * ggidld + m * (ggislg + ggisls + ggislb) */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BPdpPtr, k, total_offset + 12, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbgb - here->BSIM4v7gbgs - gIbtotg) - m * ggidlg - m * ggislg */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BPgpPtr, k, total_offset + 13, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbsb - gjbs + gbbsp - gIbtots) + m * (ggidlg + ggidld + ggidlb) - m * ggisls */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BPspPtr, k, total_offset + 14, 1, *i) ; + (*i)++ ; + } + + /* m * (gjbd + gjbs + gcbbb - here->BSIM4v7gbbs - gIbtotb) - m * ggidlb - m * ggislb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BPbpPtr, k, total_offset + 15, 1, *i) ; + (*i)++ ; + } + + total_offset += 16 ; + + /* stamp gidl included above */ + /* stamp gisl included above */ + + + if (here->BSIM4v7rbodyMod) + { + /* m * (gcdbdb - here->BSIM4v7gbd) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DPdbPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7gbs - gcsbsb) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SPsbPtr, k, total_offset + 1, -1, *i) ; + (*i)++ ; + } + + /* m * (gcdbdb - here->BSIM4v7gbd) */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DBdpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7gbd - gcdbdb + here->BSIM4v7grbpd + here->BSIM4v7grbdb) */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7dbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DBdbPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbpd */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7DBbpPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbdb */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7bNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DBbPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbpd */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7dbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BPdbPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbpb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BPbPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbps */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7sbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BPsbPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7grbpd + here->BSIM4v7grbps + here->BSIM4v7grbpb) */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BPbpPtr, k, total_offset + 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gcsbsb - here->BSIM4v7gbs) */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SBspPtr, k, total_offset + 8, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbps */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7SBbpPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbsb */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7bNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SBbPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7gbs - gcsbsb + here->BSIM4v7grbps + here->BSIM4v7grbsb) */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7sbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SBsbPtr, k, total_offset + 10, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbdb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7dbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BdbPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbpb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7BbpPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7grbsb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7sbNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BsbPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4v7grbsb + here->BSIM4v7grbdb + here->BSIM4v7grbpb) */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7bNode != 0)) + { + TopologyMatrixInsert (BSIM4v7BbPtr, k, total_offset + 11, 1, *i) ; + (*i)++ ; + } + + total_offset += 12 ; + } + + + if (here->BSIM4v7trnqsMod) + { + /* m * (gqdef + here->BSIM4v7gtau) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7qNode != 0)) + { + TopologyMatrixInsert (BSIM4v7QqPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtg - gcqgb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7QgpPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtd - gcqdb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7QdpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * (ggts - gcqsb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7QspPtr, k, total_offset + 3, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtb - gcqbb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4v7QbpPtr, k, total_offset + 4, 1, *i) ; + (*i)++ ; + } + + /* m * dxpart * here->BSIM4v7gtau */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7qNode != 0)) + { + TopologyMatrixInsert (BSIM4v7DPqPtr, k, total_offset + 5, 1, *i) ; + (*i)++ ; + } + + /* m * sxpart * here->BSIM4v7gtau */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7qNode != 0)) + { + TopologyMatrixInsert (BSIM4v7SPqPtr, k, total_offset + 6, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4v7gtau */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7qNode != 0)) + { + TopologyMatrixInsert (BSIM4v7GPqPtr, k, total_offset + 7, -1, *i) ; + (*i)++ ; + } + } + + + + /* For the RHS */ + /* m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq) */ + if (here->BSIM4v7dNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7dNodePrime, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqqg - ceqgcrg + Igtoteq) */ + if (here->BSIM4v7gNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7gNodePrime, k, total_offsetRHS + 1, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + + if (here->BSIM4v7rgateMod == 2) + { + /* m * ceqgcrg */ + if (here->BSIM4v7gNodeExt != 0) + { + TopologyMatrixInsertRHS (BSIM4v7gNodeExt, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 1 ; + } + else if (here->BSIM4v7rgateMod == 3) + { + /* m * (ceqqgmid + ceqgcrg) */ + if (here->BSIM4v7gNodeMid != 0) + { + TopologyMatrixInsertRHS (BSIM4v7gNodeMid, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 1 ; + } + + + if (!here->BSIM4v7rbodyMod) + { + /* m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq) */ + if (here->BSIM4v7bNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7bNodePrime, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4v7sNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7sNodePrime, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + } else { + /* m * (ceqjd + ceqqjd) */ + if (here->BSIM4v7dbNode != 0) + { + TopologyMatrixInsertRHS (BSIM4v7dbNode, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + /* m * (ceqbd + ceqbs - ceqqb + Ibtoteq) */ + if (here->BSIM4v7bNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7bNodePrime, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqjs + ceqqjs) */ + if (here->BSIM4v7sbNode != 0) + { + TopologyMatrixInsertRHS (BSIM4v7sbNode, k, total_offsetRHS + 2, -1, *j) ; + (*j)++ ; + } + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4v7sNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4v7sNodePrime, k, total_offsetRHS + 3, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 4 ; + } + + + if (model->BSIM4v7rdsMod) + { + /* m * ceqgdtot */ + if (here->BSIM4v7dNode != 0) + { + TopologyMatrixInsertRHS (BSIM4v7dNode, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + /* m * ceqgstot */ + if (here->BSIM4v7sNode != 0) + { + TopologyMatrixInsertRHS (BSIM4v7sNode, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + } + + + if (here->BSIM4v7trnqsMod) + { + /* m * (cqcheq - cqdef) */ + if (here->BSIM4v7qNode != 0) + { + TopologyMatrixInsertRHS (BSIM4v7qNode, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7free.c b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7free.c new file mode 100644 index 000000000..a3c2c5ab0 --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7free.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "bsim4v7def.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuBSIM4v7destroy +( +GENmodel *inModel +) +{ + BSIM4v7model *model = (BSIM4v7model *)inModel ; + BSIM4v7instance *here ; + + int i ; + + for ( ; model != NULL ; model = BSIM4v7nextModel(model)) + { + /* Special case here->d_pParam */ + i = 0 ; + + for (here = BSIM4v7instances(model); here != NULL ; here = BSIM4v7nextInstance(here)) + { + if (here->pParam != NULL) + cudaFree (model->pParamHost [i]) ; + + i++ ; + } + + free (model->pParamHost) ; + cudaFree (model->d_pParam) ; + + /* DOUBLE */ + free (model->BSIM4v7paramCPU.BSIM4v7gbsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gbsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gbdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gbdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vonRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vonRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vdsatRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vdsatRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7csubRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7csubRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gmRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gmRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gmbsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gmbsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gcrgRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gcrgRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgidlRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgidlRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgislRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgislRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgcsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgcsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgcdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgcdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IgbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IgbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qinvRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qinvRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cggbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cggbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cgsbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cgsbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cgdbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cgdbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cdgbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cdgbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cdsbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cdsbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cddbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cddbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbgbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbgbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbsbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbsbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbdbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbdbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7csgbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7csgbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cssbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cssbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7csdbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7csdbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cgbbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cgbbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7csbbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7csbbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cdbbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cdbbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cbbbRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cbbbRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gtauRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gtauRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qgateRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qgateRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qbulkRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qbulkRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qdrnRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qdrnRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qsrcRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qsrcRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7capbsRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7capbsRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7capbdRWArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7capbdRWArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7icVDSArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7icVGSArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7icVBSArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vth0Array) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vth0Array) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gbbsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gbbsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggidlbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggidlbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gbgsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gbgsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggidlgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggidlgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gbdsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gbdsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggidldArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggidldArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggislsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggislsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggislgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggislgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggislbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggislbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgsgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgsgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcsgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcsdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcsbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgdgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgdgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcdgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcddArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcddArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcdbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgbgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgbgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgbdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgbdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgbbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgbbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggidlsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggidlsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ggisldArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ggisldArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gstotArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gstotArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gstotdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gstotdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gstotgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gstotgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gstotbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gstotbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdtotArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdtotArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdtotdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdtotdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdtotgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdtotgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdtotbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdtotbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cgdoArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cgdoArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qgdoArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qgdoArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cgsoArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cgsoArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qgsoArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qgsoArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7AseffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7AseffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7PseffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7PseffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7nfArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7nfArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7XExpBVSArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVSArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vjsmFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vjsmFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IVjsmFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vjsmRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vjsmRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IVjsmRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SslpRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SslpRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SslpFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SslpFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7AdeffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7AdeffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7PdeffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7PdeffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7XExpBVDArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVDArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vjdmFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vjdmFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IVjdmFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vjdmRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vjdmRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IVjdmRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DslpRevArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DslpRevArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DslpFwdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DslpFwdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SjctTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SjctTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SswTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SswTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SswgTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SswgTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DjctTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DjctTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DswTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DswTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DswgTempRevSatCurArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DswgTempRevSatCurArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vbscArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vbscArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7thetavthArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7thetavthArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7eta0Array) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7eta0Array) ; + + free (model->BSIM4v7paramCPU.BSIM4v7k2oxArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7k2oxArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7nstarArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7nstarArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vfbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vfbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vgs_effArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vgs_effArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vgd_effArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vgd_effArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dvgs_eff_dvgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dvgs_eff_dvgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dvgd_eff_dvgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dvgd_eff_dvgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7VgsteffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7VgsteffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grdswArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grdswArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7AbulkArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7AbulkArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vtfbphi1Array) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi1Array) ; + + free (model->BSIM4v7paramCPU.BSIM4v7ueffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7ueffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7u0tempArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7u0tempArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vsattempArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vsattempArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7EsatLArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7EsatLArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7VdseffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7VdseffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vtfbphi2Array) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi2Array) ; + + free (model->BSIM4v7paramCPU.BSIM4v7CoxeffArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7CoxeffArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7AbovVgst2VtmArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7AbovVgst2VtmArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7IdovVdsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7IdovVdsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gcrgdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gcrgdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gcrgbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gcrgbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gcrggArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gcrggArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grgeltdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grgeltdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gcrgsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gcrgsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sourceConductanceArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sourceConductanceArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7drainConductanceArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7drainConductanceArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gstotsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gstotsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gdtotsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gdtotsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7vfbzbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7vfbzbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgssArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgssArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgddArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgddArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgbsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgbsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcssArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcssArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gIgcdsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7noiGd0Array) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7noiGd0Array) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cqdbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cqdbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cqsbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cqsbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cqgbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cqgbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qchqsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qchqsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7cqbbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7cqbbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7taunetArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7taunetArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gtgArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gtgArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gtdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gtdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gtsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gtsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gtbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gtbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7mArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7mArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grbpdArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grbpdArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grbdbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grbdbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grbpbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grbpbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grbpsArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grbpsArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7grbsbArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7grbsbArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodeExtRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodeMidRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7bNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dbNodeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sbNodeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dNodeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dNodeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sNodeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sNodeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qNodeRHSValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qNodeRHSValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEgeValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEgeValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPgeValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPgeValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GEgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GEgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMgeValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMgeValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GMbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GMbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPgmValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPgmValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPdValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPdValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DdValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DdValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPsValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPsValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SsValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SsValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPdbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPdbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPsbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPsbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DBdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DBdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DBdbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DBdbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DBbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DBbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DBbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DBbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPdbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPdbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPsbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPsbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BPbpIFValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BPbpIFValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SBspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SBspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SBbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SBbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SBbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SBbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SBsbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SBsbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BdbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BdbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BsbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BsbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7BbValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7BbValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7QqValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7QqValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7QgpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7QgpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7QdpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7QdpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7QspValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7QspValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7QbpValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7QbpValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7DPqValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7DPqValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7SPqValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7SPqValueArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7GPqValueArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7GPqValueArray) ; + + /* INT */ + free (model->BSIM4v7paramCPU.BSIM4v7offArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7offArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dNodePrimeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sNodePrimeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodePrimeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7bNodePrimeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodeExtArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7gNodeMidArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dbNodeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sbNodeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7sNodeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7sNodeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7dNodeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7dNodeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7qNodeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7qNodeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7rbodyModArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7rbodyModArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7modeArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7modeArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7rgateModArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7rgateModArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7trnqsModArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7trnqsModArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7acnqsModArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7acnqsModArray) ; + + free (model->BSIM4v7paramCPU.BSIM4v7statesArray) ; + cudaFree (model->BSIM4v7paramGPU.d_BSIM4v7statesArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7getic.c b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7getic.c new file mode 100644 index 000000000..14cbe506f --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7getic.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "bsim4v7def.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuBSIM4v7getic routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuBSIM4v7getic +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + BSIM4v7model *model = (BSIM4v7model *)inModel ; + + size = (long unsigned int) model->n_instances; + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray, model->BSIM4v7paramCPU.BSIM4v7icVDSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray, model->BSIM4v7paramCPU.BSIM4v7icVGSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray, model->BSIM4v7paramCPU.BSIM4v7icVBSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray, size, double, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7load.cu b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7load.cu new file mode 100644 index 000000000..fbba3224c --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7load.cu @@ -0,0 +1,5357 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/const.h" +#include "ngspice/macros.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "bsim4v7def.h" + +#define MAX_EXPL 2.688117142e+43 +#define MIN_EXPL 3.720075976e-44 +#define EXPL_THRESHOLD 100.0 +#define MAX_EXP 5.834617425e14 +#define MIN_EXP 1.713908431e-15 +#define EXP_THRESHOLD 34.0 +#define EPS0 8.85418e-12 +#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 MM 3 /* smooth coeff */ +#define DEXP(A,B,C) { \ + if (A > EXP_THRESHOLD) { \ + B = MAX_EXP*(1.0+(A)-EXP_THRESHOLD); \ + C = MAX_EXP; \ + } else if (A < -EXP_THRESHOLD) { \ + B = MIN_EXP; \ + C = 0; \ + } else { \ + B = exp(A); \ + C = B; \ + } \ + } + +extern "C" +__device__ +static +double +DEVlimvds (double vnew, double vold) +{ + if (vold >= 3.5) + { + if (vnew > vold) + vnew = MIN (vnew, (3 * vold) + 2) ; + else + if (vnew < 3.5) + vnew = MAX (vnew, 2) ; + } else { + if (vnew > vold) + vnew = MIN (vnew, 4) ; + else + vnew = MAX (vnew, -.5) ; + } + + return (vnew) ; +} + +extern "C" +__device__ +static +double +DEVpnjlim (double vnew, double vold, double vt, double vcrit, int *icheck) +{ + double arg ; + + if ((vnew > vcrit) && (fabs (vnew - vold) > (vt + vt))) + { + if (vold > 0) + { + arg = (vnew - vold) / vt ; + if (arg > 0) + vnew = vold + vt * (2 + log (arg - 2)) ; + else + vnew = vold - vt * (2 + log (2 - arg)) ; + } else + vnew = vt * log (vnew / vt) ; + + *icheck = 1 ; + + } else { + if (vnew < 0) + { + if (vold > 0) + arg = -1 * vold - 1 ; + else + arg = 2 * vold - 1 ; + + if (vnew < arg) + { + vnew = arg ; + *icheck = 1 ; + } else { + *icheck = 0 ; + } ; + } else { + *icheck = 0 ; + } + } + + return (vnew) ; +} + +extern "C" +__device__ +static +double +DEVfetlim (double vnew, double vold, double vto) +{ + double vtsthi, vtstlo, vtox, delv, vtemp ; + + vtsthi = fabs (2 * (vold - vto)) + 2 ; + vtstlo = fabs (vold - vto) + 1 ; + vtox = vto + 3.5 ; + delv = vnew - vold ; + + if (vold >= vto) + { + if (vold >= vtox) + { + if (delv <= 0) + { + /* going off */ + if (vnew >= vtox) + { + if (-delv > vtstlo) + vnew = vold - vtstlo ; + } else + vnew = MAX (vnew, vto + 2) ; + } else { + /* staying on */ + if (delv >= vtsthi) + vnew = vold + vtsthi ; + } + } else { + /* middle region */ + if (delv <= 0) + /* decreasing */ + vnew = MAX (vnew, vto - .5) ; + else + /* increasing */ + vnew = MIN (vnew, vto + 4) ; + } + } else { + /* off */ + if (delv <= 0) + { + if (-delv >vtsthi) + vnew = vold - vtsthi ; + } else { + vtemp = vto + .5 ; + if (vnew <= vtemp) + { + if (delv >vtstlo) + vnew = vold + vtstlo ; + } else + vnew = vtemp ; + } + } + + return (vnew) ; +} + +/* function to compute poly depletion effect */ +extern "C" +__device__ +static +int +BSIM4v7polyDepletion (double phi, double ngate, double epsgate, double coxe, + double Vgs, double *Vgs_eff, double *dVgs_eff_dVg) +{ + double T1, T2, T3, T4, T5, T6, T7, T8 ; + + /* Poly Gate Si Depletion Effect */ + if ((ngate > 1.0e18) && (ngate < 1.0e25) && (Vgs > phi) && (epsgate!=0)) + { + T1 = 1.0e6 * CHARGE * epsgate * ngate / (coxe * coxe) ; + T8 = Vgs - phi ; + T4 = sqrt (1.0 + 2.0 * T8 / T1) ; + T2 = 2.0 * T8 / (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 ; + } + + return 0 ; +} + +extern "C" +__global__ void cuBSIM4v7load_kernel +( +BSIM4v7paramGPUstruct, struct bsim4SizeDependParam **, double *, double *, double *, double *, +double, double, double, double, double, +double, double, double, int, int, int, int, +double, int *, double, +/* Model */ +int, int, int, int, double, double, +double, double, double, +double, double, double, +double, int, 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, int, +int, double, double, double, double, +double, double, int, double, int, +int, int, double, int, int, +double, double, double, double, double, +double, double, double, double, +double, double, double, double, double, +double, double, double, double, +/* Position Vectors and CKTloadOutputs */ +int *, double *, int *, double * +) ; + +extern "C" +int +cuBSIM4v7load +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + BSIM4v7model *model = (BSIM4v7model *)inModel ; + int i, thread_x, thread_y, block_x ; + + cudaStream_t stream [2] ; + + cudaError_t status ; + + for (i = 0 ; i < 2 ; i++) + cudaStreamCreate (&(stream [i])) ; + + i = 0 ; + + /* loop through all the BSIM4v7 models */ + for ( ; model != NULL ; model = BSIM4v7nextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)((model->n_instances + thread_y - 1) / thread_y) ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuBSIM4v7load_kernel <<< block_x, thread, 0, stream [i] >>> + (model->BSIM4v7paramGPU, model->d_pParam, ckt->d_CKTrhsOld, + ckt->d_CKTstate0, ckt->d_CKTstate1, ckt->d_CKTstate2, + ckt->CKTdelta, ckt->CKTdeltaOld [1], ckt->CKTreltol, + ckt->CKTvoltTol, ckt->CKTabstol, ckt->CKTag [0], ckt->CKTag [1], + ckt->CKTgmin, ckt->CKTbypass, ckt->CKTmode, ckt->CKTorder, + model->n_instances, ckt->CKTtemp, ckt->d_CKTnoncon, CONSTvt0, + /* Model */ + model->BSIM4v7type, model->BSIM4v7rdsMod, model->BSIM4v7igcMod, + model->BSIM4v7igbMod, model->BSIM4v7vcrit, model->BSIM4v7vtm, + model->BSIM4v7vtm0, model->BSIM4v7SjctEmissionCoeff, + model->BSIM4v7SjctTempSatCurDensity, + model->BSIM4v7SjctSidewallTempSatCurDensity, + model->BSIM4v7SjctGateSidewallTempSatCurDensity, + model->BSIM4v7xjbvs, model->BSIM4v7bvs, model->BSIM4v7dioMod, + model->BSIM4v7DjctEmissionCoeff, model->BSIM4v7DjctTempSatCurDensity, + model->BSIM4v7DjctSidewallTempSatCurDensity, + model->BSIM4v7DjctGateSidewallTempSatCurDensity, model->BSIM4v7xjbvd, + model->BSIM4v7bvd, model->BSIM4v7njtsswstemp, model->BSIM4v7njtsswgstemp, + model->BSIM4v7njtsstemp, model->BSIM4v7njtsswdtemp, + model->BSIM4v7njtsswgdtemp, model->BSIM4v7njtsdtemp, model->BSIM4v7vtss, + model->BSIM4v7vtsd, model->BSIM4v7vtssws, model->BSIM4v7vtsswd, + model->BSIM4v7vtsswgs, model->BSIM4v7vtsswgd, model->BSIM4v7mtrlMod, + model->BSIM4v7eot, model->BSIM4v7epsrsub, model->BSIM4v7epsrox, + model->BSIM4v7toxe, model->BSIM4v7factor1, model->BSIM4v7tnom, + model->BSIM4v7coxe, model->BSIM4v7tempMod, model->BSIM4v7epsrgate, + model->BSIM4v7mtrlCompatMod, model->BSIM4v7phig, model->BSIM4v7easub, + model->BSIM4v7Eg0, model->BSIM4v7mobMod, model->BSIM4v7lambdaGiven, + model->BSIM4v7lambda, model->BSIM4v7toxp, model->BSIM4v7bdos, + model->BSIM4v7ados, model->BSIM4v7coxp, model->BSIM4v7pditsl, + model->BSIM4v7vtlGiven, model->BSIM4v7vtl, model->BSIM4v7gidlMod, + model->BSIM4v7pigcdGiven, model->BSIM4v7tnoiMod, model->BSIM4v7xpart, + model->BSIM4v7capMod, model->BSIM4v7cvchargeMod, + model->BSIM4v7DunitAreaTempJctCap, model->BSIM4v7SunitAreaTempJctCap, + model->BSIM4v7DunitLengthSidewallTempJctCap, + model->BSIM4v7DunitLengthGateSidewallTempJctCap, + model->BSIM4v7SunitLengthSidewallTempJctCap, + model->BSIM4v7SunitLengthGateSidewallTempJctCap, + model->BSIM4v7SbulkJctBotGradingCoeff, + model->BSIM4v7SbulkJctSideGradingCoeff, + model->BSIM4v7SbulkJctGateSideGradingCoeff, + model->BSIM4v7DbulkJctBotGradingCoeff, + model->BSIM4v7DbulkJctSideGradingCoeff, + model->BSIM4v7DbulkJctGateSideGradingCoeff, + model->BSIM4v7PhiBS, model->BSIM4v7PhiBSWS, model->BSIM4v7PhiBSWGS, + model->BSIM4v7PhiBD, model->BSIM4v7PhiBSWD, model->BSIM4v7PhiBSWGD, + model->d_PositionVector, ckt->d_CKTloadOutput, + model->d_PositionVectorRHS, ckt->d_CKTloadOutputRHS) ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the BSIM4v7 Model\n\n") ; + return (E_NOMEM) ; + } + + i++ ; + } + + cudaDeviceSynchronize () ; + + /* Deallocation */ + for (i = 0 ; i < 2 ; i++) + cudaStreamDestroy (stream [i]) ; + + return (OK) ; +} + +extern "C" +__global__ +void +cuBSIM4v7load_kernel +( +BSIM4v7paramGPUstruct BSIM4v7entry, struct bsim4SizeDependParam **d_pParam, double *CKTrhsOld, +double *CKTstate_0, double *CKTstate_1, double *CKTstate_2, +double CKTdelta, double CKTdeltaOld_1, double CKTrelTol, double CKTvoltTol, double CKTabsTol, +double CKTag_0, double CKTag_1, double CKTgmin, int CKTbypass, int CKTmode, int CKTorder, int n_instances, +double CKTtemp, int *d_CKTnoncon, double CONSTvt0, +/* Model */ +int BSIM4v7type, int BSIM4v7rdsMod, int BSIM4v7igcMod, int BSIM4v7igbMod, double BSIM4v7vcrit, double BSIM4v7vtm, +double BSIM4v7vtm0, double BSIM4v7SjctEmissionCoeff, double BSIM4v7SjctTempSatCurDensity, +double BSIM4v7SjctSidewallTempSatCurDensity, double BSIM4v7SjctGateSidewallTempSatCurDensity, double BSIM4v7xjbvs, +double BSIM4v7bvs, int BSIM4v7dioMod, double BSIM4v7DjctEmissionCoeff, double BSIM4v7DjctTempSatCurDensity, +double BSIM4v7DjctSidewallTempSatCurDensity, double BSIM4v7DjctGateSidewallTempSatCurDensity, double BSIM4v7xjbvd, +double BSIM4v7bvd, double BSIM4v7njtsswstemp, double BSIM4v7njtsswgstemp, double BSIM4v7njtsstemp, +double BSIM4v7njtsswdtemp, double BSIM4v7njtsswgdtemp, double BSIM4v7njtsdtemp, double BSIM4v7vtss, +double BSIM4v7vtsd, double BSIM4v7vtssws, double BSIM4v7vtsswd, double BSIM4v7vtsswgs, double BSIM4v7vtsswgd, +double BSIM4v7mtrlMod, double BSIM4v7eot, double BSIM4v7epsrsub, double BSIM4v7epsrox, double BSIM4v7toxe, +double BSIM4v7factor1, double BSIM4v7tnom, double BSIM4v7coxe, double BSIM4v7tempMod, double BSIM4v7epsrgate, +double BSIM4v7mtrlCompatMod, double BSIM4v7phig, double BSIM4v7easub, double BSIM4v7Eg0, int BSIM4v7mobMod, +int BSIM4v7lambdaGiven, double BSIM4v7lambda, double BSIM4v7toxp, double BSIM4v7bdos, double BSIM4v7ados, +double BSIM4v7coxp, double BSIM4v7pditsl, int BSIM4v7vtlGiven, double BSIM4v7vtl, int BSIM4v7gidlMod, +int BSIM4v7pigcdGiven, int BSIM4v7tnoiMod, double BSIM4v7xpart, int BSIM4v7capMod, int BSIM4v7cvchargeMod, +double BSIM4v7DunitAreaTempJctCap, double BSIM4v7SunitAreaTempJctCap, double BSIM4v7DunitLengthSidewallTempJctCap, +double BSIM4v7DunitLengthGateSidewallTempJctCap, double BSIM4v7SunitLengthSidewallTempJctCap, +double BSIM4v7SunitLengthGateSidewallTempJctCap, double BSIM4v7SbulkJctBotGradingCoeff, +double BSIM4v7SbulkJctSideGradingCoeff, double BSIM4v7SbulkJctGateSideGradingCoeff, +double BSIM4v7DbulkJctBotGradingCoeff, double BSIM4v7DbulkJctSideGradingCoeff, +double BSIM4v7DbulkJctGateSideGradingCoeff, double BSIM4v7PhiBS, double BSIM4v7PhiBSWS, double BSIM4v7PhiBSWGS, +double BSIM4v7PhiBD, double BSIM4v7PhiBSWD, double BSIM4v7PhiBSWGD, +/* Position Vectors and CKTloadOutputs */ +int *d_PositionVector, double *d_CKTloadOutput, int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID, pos, posRHS, total_offset, total_offsetRHS ; + + double ceqgstot, dgstot_dvd, dgstot_dvg, dgstot_dvs, dgstot_dvb ; + double ceqgdtot, dgdtot_dvd, dgdtot_dvg, dgdtot_dvs, dgdtot_dvb ; + double gstot, gstotd, gstotg, gstots, gstotb, gspr, Rs, Rd ; + double gdtot, gdtotd, gdtotg, gdtots, gdtotb, gdpr ; + double vgs_eff, vgd_eff, dvgs_eff_dvg, dvgd_eff_dvg ; + double dRs_dvg, dRd_dvg, dRs_dvb, dRd_dvb ; + double dT0_dvg, dT1_dvb, dT3_dvg, dT3_dvb ; + double vses, vdes, vdedo, delvses, delvded, delvdes ; + double Isestot, cseshat, Idedtot, cdedhat ; + +#ifndef NEWCONV + double tol0, tol1, tol2, tol3, tol4, tol5, tol6 ; +#endif + + double geltd, gcrg, gcrgg, gcrgd, gcrgs, gcrgb, ceqgcrg ; + double vges, vgms, vgedo, vgmdo, vged, vgmd ; + double delvges, delvgms, vgmb ; + double gcgmgmb = 0.0, gcgmdb = 0.0, gcgmsb = 0.0, gcdgmb, gcsgmb ; + double gcgmbb = 0.0, gcbgmb, qgmb, qgmid = 0.0, ceqqgmid ; + double vbd, vbs, vds, vgb, vgd, vgs, vgdo ; + +#ifndef PREDICTOR + double xfact ; +#endif + + double vdbs, vdbd, vsbs, vsbdo, vsbd ; + double delvdbs, delvdbd, delvsbs ; + double delvbd_jct, delvbs_jct, vbs_jct, vbd_jct ; + double SourceSatCurrent, DrainSatCurrent ; + double ag0, qgb, von, cbhat, VgstNVt, ExpVgst ; + double ceqqb, ceqqd, ceqqg, ceqqjd = 0.0, ceqqjs = 0.0, ceq, geq ; + double cdrain, cdhat, ceqdrn, ceqbd, ceqbs, ceqjd, ceqjs, gjbd, gjbs ; + double 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 ; + double gcgbb, gcdbb, gcsbb, gcbbb ; + double gcdbdb, gcsbsb ; + double gcsgb, gcssb, MJD, MJSWD, MJSWGD, MJS, MJSWS, MJSWGS ; + double qgate = 0.0, qbulk = 0.0, qdrn = 0.0, qsrc, cqgate, cqbody, cqdrn ; + double Vds, Vbs, Gmbs, FwdSum, RevSum ; + double Igidl, Ggidld, Ggidlg, Ggidlb ; + double Voxacc = 0.0, dVoxacc_dVg = 0.0, dVoxacc_dVb = 0.0 ; + double Voxdepinv = 0.0, dVoxdepinv_dVg = 0.0, dVoxdepinv_dVd = 0.0, dVoxdepinv_dVb = 0.0 ; + double VxNVt = 0.0, ExpVxNVt, Vaux = 0.0, dVaux_dVg = 0.0, dVaux_dVd = 0.0, dVaux_dVb = 0.0 ; + double Igc, dIgc_dVg, dIgc_dVd, dIgc_dVb ; + double Igcs, dIgcs_dVg, dIgcs_dVd, dIgcs_dVb ; + double Igcd, dIgcd_dVg, dIgcd_dVd, dIgcd_dVb ; + double Igs, dIgs_dVg, dIgs_dVs, Igd, dIgd_dVg, dIgd_dVd ; + double Igbacc, dIgbacc_dVg, dIgbacc_dVb ; + double Igbinv, dIgbinv_dVg, dIgbinv_dVd, dIgbinv_dVb ; + double Pigcd, dPigcd_dVg, dPigcd_dVd, dPigcd_dVb ; + double Istoteq, gIstotg, gIstotd, gIstots, gIstotb ; + double Idtoteq, gIdtotg, gIdtotd, gIdtots, gIdtotb ; + double Ibtoteq, gIbtotg, gIbtotd, gIbtots, gIbtotb ; + double Igtoteq, gIgtotg, gIgtotd, gIgtots, gIgtotb ; + double Igstot, cgshat, Igdtot, cgdhat, Igbtot, cgbhat ; + double Vgs_eff, Vfb = 0.0, Vth_NarrowW ; + + /* double Vgd_eff, dVgd_eff_dVg; v4.7.0 */ + + double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb, Vth, dVth_dVb, dVth_dVd ; + double Vgst, dVgs_eff_dVg, Nvtms, Nvtmd ; + double Vtm, Vtm0 ; + double n, dn_dVb, dn_dVd, voffcv, noff, dnoff_dVd, dnoff_dVb ; + double 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_dVd, dCoxeff_dVg, 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 VgsteffVth, dT11_dVg ; + double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL ; + double T0 = 0.0, 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, dT4_dVd, dT4_dVb ; + double T5, dT5_dVg, dT5_dVd, dT5_dVb ; + double T6, dT6_dVg, dT6_dVd, dT6_dVb ; + double T7, dT7_dVg, dT7_dVd, dT7_dVb ; + double T8, dT8_dVg, dT8_dVd, dT8_dVb ; + double T9, dT9_dVg, dT9_dVd, dT9_dVb ; + double T10, dT10_dVg, dT10_dVb, dT10_dVd ; + double T11, T12, T13, T14 ; + double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb ; + double Cclm, dCclm_dVg, dCclm_dVd, dCclm_dVb ; + double FP, dFP_dVg, PvagTerm, dPvagTerm_dVg, dPvagTerm_dVd, dPvagTerm_dVb ; + double VADITS, dVADITS_dVg, dVADITS_dVd ; + double Lpe_Vb, dDITS_Sft_dVb, dDITS_Sft_dVd ; + + /* v4.7 New DITS */ + double DITS_Sft2, dDITS_Sft2_dVd ; + + 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, 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, devbs_dvb, devbd_dvb ; + double Isub, Gbd, Gbg, Gbb ; + double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb ; + double CoxeffWovL ; + double Rds, dRds_dVg, dRds_dVb, WVCox, WVCoxRds ; + double Vgst2Vtm, VdsatCV ; + double Leff, Weff, dWeff_dVg, dWeff_dVb ; + double AbulkCV, dAbulkCV_dVb ; + double qcheq, qdef, gqdef = 0.0, cqdef = 0.0, cqcheq = 0.0 ; + double 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 qgdo, qgso, cgdo, cgso ; + double Cgg, Cgd, Cgb, Cdg, Cdd, Cds ; + double Csg, Csd, Css, Csb, Cbg, Cbd, Cbb ; + double Cgg1, Cgd1, Cgb1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0 ; + double dQac0_dVg, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb ; + double ggidld, ggidlg, ggidlb, ggislg, ggislb, ggisls ; + double Igisl, Ggislg, Ggislb, Ggisls ; + double Nvtmrss, Nvtmrssws, Nvtmrsswgs ; + double Nvtmrsd, Nvtmrsswd, Nvtmrsswgd ; + double vs, Fsevl, dvs_dVg, dvs_dVd, dvs_dVb, dFsevl_dVg, dFsevl_dVd, dFsevl_dVb ; + double vgdx, vgsx, epssub, toxe, epsrox ; + struct bsim4SizeDependParam *pParam ; + int ByPass, ChargeComputationNeeded, error, Check, Check1, Check2 ; + double m ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < n_instances) + { + if (threadIdx.x == 0) + { + ScalingFactor = 1.0e-9 ; + ChargeComputationNeeded = ((CKTmode & (MODEAC | MODETRAN | MODEINITSMSIG)) || + ((CKTmode & MODETRANOP) && (CKTmode & MODEUIC))) ? 1 : 0 ; + + Check = Check1 = Check2 = 1 ; + ByPass = 0 ; + pParam = d_pParam [instance_ID] ; + + /* 1 - non-divergent */ + if (CKTmode & MODEINITSMSIG) + { + vds = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vgs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + vbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + vges = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + vgms = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + vdbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + vsbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + vses = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + vdes = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + qdef = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] ; + } + else if (CKTmode & MODEINITTRAN) + { + vds = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vgs = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + vbs = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + vges = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + vgms = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + vdbs = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + vsbs = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + vses = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + vdes = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + qdef = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] ; + } + else if ((CKTmode & MODEINITJCT) && !BSIM4v7entry.d_BSIM4v7offArray [instance_ID]) + { + vds = BSIM4v7type * BSIM4v7entry.d_BSIM4v7icVDSArray [instance_ID] ; + vgs = vges = vgms = BSIM4v7type * BSIM4v7entry.d_BSIM4v7icVGSArray [instance_ID] ; + vbs = vdbs = vsbs = BSIM4v7type * BSIM4v7entry.d_BSIM4v7icVBSArray [instance_ID] ; + + /* 1 - DIVERGENT */ + if (vds > 0.0) + { + vdes = vds + 0.01 ; + vses = -0.01 ; + } + else if (vds < 0.0) + { + vdes = vds - 0.01 ; + vses = 0.01 ; + } + else + vdes = vses = 0.0 ; + + qdef = 0.0 ; + + /* 2 - DIVERGENT */ + if ((vds == 0.0) && (vgs == 0.0) && (vbs == 0.0) + && ((CKTmode & (MODETRAN | MODEAC|MODEDCOP | + MODEDCTRANCURVE)) || (!(CKTmode & MODEUIC)))) + { + vds = 0.1 ; + vdes = 0.11 ; + vses = -0.01 ; + vgs = vges = vgms = BSIM4v7type * BSIM4v7entry.d_BSIM4v7vth0Array [instance_ID] + 0.1 ; + vbs = vdbs = vsbs = 0.0 ; + } + } + else if ((CKTmode & (MODEINITJCT | MODEINITFIX)) && (BSIM4v7entry.d_BSIM4v7offArray [instance_ID])) + { + vds = vgs = vbs = vges = vgms = 0.0 ; + vdbs = vsbs = vdes = vses = qdef = 0.0 ; + } else { + +#ifndef PREDICTOR + /* 2 - non-divergent */ + if (CKTmode & MODEINITPRED) + { + xfact = CKTdelta / CKTdeltaOld_1 ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vds = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + vgs = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + vges = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + vgms = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + vbs = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + vdbs = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + vsbs = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + vses = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + vdes = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] = CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] ; + qdef = (1.0 + xfact) * CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] - xfact * CKTstate_2 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] ; + } else { +#endif /* PREDICTOR */ + + vds = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7dNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vgs = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7gNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vbs = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7bNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vges = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7gNodeExtArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vgms = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7gNodeMidArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vdbs = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7dbNodeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vsbs = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7sbNodeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vses = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + vdes = BSIM4v7type * (CKTrhsOld [BSIM4v7entry.d_BSIM4v7dNodeArray [instance_ID]] - CKTrhsOld [BSIM4v7entry.d_BSIM4v7sNodePrimeArray [instance_ID]]) ; + qdef = BSIM4v7type * CKTrhsOld [BSIM4v7entry.d_BSIM4v7qNodeArray [instance_ID]] ; + +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + + vgdo = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vgedo = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vgmdo = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vbd = vbs - vds ; + vdbd = vdbs - vds ; + vgd = vgs - vds ; + vged = vges - vds ; + vgmd = vgms - vds ; + delvbd = vbd - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]] ; + delvdbd = vdbd - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5] ; + delvgd = vgd - vgdo ; + delvds = vds - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + delvgs = vgs - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + delvges = vges - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + delvgms = vgms - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + delvbs = vbs - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + delvdbs = vdbs - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + delvsbs = vsbs - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + delvses = vses - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + vdedo = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + delvdes = vdes - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + delvded = vdes - vds - vdedo ; + delvbd_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? delvbd : delvdbd ; + delvbs_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? delvbs : delvsbs ; + + /* I DON'T KNOW */ + if (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] >= 0) + { + Idtot = BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] ; + cdhat = Idtot - BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * delvbd_jct + + (BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID]) * delvbs + + (BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID]) * delvgs + + (BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID]) * delvds ; + + Ibtot = BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] ; + cbhat = Ibtot + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * delvbd_jct + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] * delvbs_jct - + (BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID]) * delvbs - + (BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID]) * delvgs - + (BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] - BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID]) * delvds - + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] * delvgd - BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] * delvbd ; + + Igstot = BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] ; + cgshat = Igstot + (BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID]) * delvgs + + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] * delvds + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] * delvbs ; + + Igdtot = BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] ; + cgdhat = Igdtot + BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] * delvgd + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] * delvgs + + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] * delvds + BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] * delvbs ; + + Igbtot = BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] ; + cgbhat = BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] * delvgs + BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] * + delvds + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] * delvbs ; + } else { + /* bugfix */ + Idtot = BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] ; + /* ------ */ + + cdhat = Idtot + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * delvbd_jct + BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] * delvbd + + BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] * delvgd - (BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlsArray [instance_ID]) * delvds - + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] * delvgs - BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] * delvbs ; + + Ibtot = BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] ; + cbhat = Ibtot + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] * delvbs_jct + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * delvbd_jct - + (BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID]) * delvbd - + (BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID]) * delvgd + + (BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggisldArray [instance_ID] - BSIM4v7entry.d_BSIM4v7ggidlsArray [instance_ID]) * delvds - + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] * delvgs - BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] * delvbs ; + + Igstot = BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] ; + cgshat = Igstot + BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] * delvgs + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] * delvgd - + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] * delvds + BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] * delvbd ; + + Igdtot = BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] ; + cgdhat = Igdtot + (BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID]) * delvgd - + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] * delvds + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] * delvbd ; + + Igbtot = BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] ; + cgbhat = BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] * delvgd - BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] * delvds + + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] * delvbd ; + } + + Isestot = BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] * CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + cseshat = Isestot + BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] * delvses + BSIM4v7entry.d_BSIM4v7gstotdArray [instance_ID] * delvds + + BSIM4v7entry.d_BSIM4v7gstotgArray [instance_ID] * delvgs + BSIM4v7entry.d_BSIM4v7gstotbArray [instance_ID] * delvbs ; + + Idedtot = BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] * vdedo ; + cdedhat = Idedtot + BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] * delvded + BSIM4v7entry.d_BSIM4v7gdtotdArray [instance_ID] * delvds + + BSIM4v7entry.d_BSIM4v7gdtotgArray [instance_ID] * delvgs + BSIM4v7entry.d_BSIM4v7gdtotbArray [instance_ID] * delvbs ; + +#ifndef NOBYPASS + /* Following should be one IF statement, but some C compilers + * can't handle that all at once, so we split it into several + * successive IF's */ + + /* 3 - DIVERGENT - CRITICAL */ + /* NESTED version */ + if ((!(CKTmode & MODEINITPRED)) && (CKTbypass)) + if ((fabs (delvds) < (CKTrelTol * MAX (fabs (vds), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3])) + CKTvoltTol))) + if ((fabs (delvgs) < (CKTrelTol * MAX(fabs (vgs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2])) + + CKTvoltTol))) + if ((fabs (delvbs) < (CKTrelTol * MAX (fabs (vbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1])) + + CKTvoltTol))) + if ((fabs (delvbd) < (CKTrelTol * MAX (fabs (vbd), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]])) + + CKTvoltTol))) + if ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 0) || (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 1) || + (fabs (delvges) < (CKTrelTol * MAX (fabs (vges), + fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7])) + CKTvoltTol))) + if ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] != 3) || (fabs (delvgms) < (CKTrelTol * + MAX (fabs (vgms), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8])) + CKTvoltTol))) + if ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvdbs) < (CKTrelTol * + MAX (fabs (vdbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4])) + CKTvoltTol))) + if ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvdbd) < (CKTrelTol * + MAX (fabs (vdbd), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5])) + CKTvoltTol))) + if ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvsbs) < (CKTrelTol * + MAX (fabs (vsbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6])) + + CKTvoltTol))) + if ((!BSIM4v7rdsMod) || (fabs (delvses) < (CKTrelTol * + MAX (fabs (vses), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9])) + + CKTvoltTol))) + if ((!BSIM4v7rdsMod) || (fabs (delvdes) < (CKTrelTol * + MAX (fabs (vdes), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10])) + + CKTvoltTol))) + if ((fabs (cdhat - Idtot) < CKTrelTol * + MAX (fabs (cdhat), fabs (Idtot)) + CKTabsTol)) + if ((fabs (cbhat - Ibtot) < CKTrelTol * + MAX (fabs (cbhat), fabs (Ibtot)) + CKTabsTol)) + if ((!BSIM4v7igcMod) || ((fabs (cgshat - Igstot) + < CKTrelTol * MAX (fabs (cgshat), + fabs (Igstot)) + CKTabsTol))) + if ((!BSIM4v7igcMod) || ((fabs (cgdhat - + Igdtot) < CKTrelTol * MAX (fabs + (cgdhat), fabs (Igdtot)) + CKTabsTol))) + if ((!BSIM4v7igbMod) || ((fabs (cgbhat - + Igbtot) < CKTrelTol * MAX + (fabs (cgbhat), fabs (Igbtot)) + + CKTabsTol))) + if ((!BSIM4v7rdsMod) || + ((fabs (cseshat - Isestot) < + CKTrelTol * MAX (fabs (cseshat), + fabs (Isestot)) + CKTabsTol))) + if ((!BSIM4v7rdsMod) || + ((fabs (cdedhat - Idedtot) < + CKTrelTol * + MAX (fabs (cdedhat), + fabs (Idedtot)) + CKTabsTol))) + + /* 3 - DIVERGENT - CRITICAL */ + /* NON-NESTED version + if (((!(CKTmode & MODEINITPRED)) && (CKTbypass)) + && ((fabs (delvds) < (CKTrelTol * MAX (fabs (vds), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3])) + CKTvoltTol))) + && ((fabs (delvgs) < (CKTrelTol * MAX(fabs (vgs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2])) + CKTvoltTol))) + && ((fabs (delvbs) < (CKTrelTol * MAX (fabs (vbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1])) +CKTvoltTol))) + && ((fabs (delvbd) < (CKTrelTol * MAX (fabs (vbd), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]])) + CKTvoltTol))) + && ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 0) || (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 1) || (fabs (delvges) < (CKTrelTol * + MAX (fabs (vges), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7])) + CKTvoltTol))) + && ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] != 3) || (fabs (delvgms) < (CKTrelTol * + MAX (fabs (vgms), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8])) + CKTvoltTol))) + && ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvdbs) < (CKTrelTol * + MAX (fabs (vdbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4])) + CKTvoltTol))) + && ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvdbd) < (CKTrelTol * + MAX (fabs (vdbd), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5])) + CKTvoltTol))) + && ((!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) || (fabs (delvsbs) < (CKTrelTol * + MAX (fabs (vsbs), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6])) + CKTvoltTol))) + && ((!BSIM4v7rdsMod) || (fabs (delvses) < (CKTrelTol * + MAX (fabs (vses), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9])) + CKTvoltTol))) + && ((!BSIM4v7rdsMod) || (fabs (delvdes) < (CKTrelTol * + MAX (fabs (vdes), fabs (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10])) + CKTvoltTol))) + && ((fabs (cdhat - Idtot) < CKTrelTol * MAX (fabs (cdhat), fabs (Idtot)) + CKTabsTol)) + && ((fabs (cbhat - Ibtot) < CKTrelTol * MAX (fabs (cbhat), fabs (Ibtot)) + CKTabsTol)) + && ((!BSIM4v7igcMod) || ((fabs (cgshat - Igstot) < CKTrelTol * + MAX (fabs (cgshat), fabs (Igstot)) + CKTabsTol))) + && ((!BSIM4v7igcMod) || ((fabs (cgdhat - Igdtot) < CKTrelTol * + MAX (fabs (cgdhat), fabs (Igdtot)) + CKTabsTol))) + && ((!BSIM4v7igbMod) || ((fabs (cgbhat - Igbtot) < CKTrelTol * + MAX (fabs (cgbhat), fabs (Igbtot)) + CKTabsTol))) + && ((!BSIM4v7rdsMod) || ((fabs (cseshat - Isestot) < CKTrelTol * + MAX (fabs (cseshat), fabs (Isestot)) + CKTabsTol))) + && ((!BSIM4v7rdsMod) || ((fabs (cdedhat - Idedtot) < CKTrelTol * + MAX (fabs (cdedhat), fabs (Idedtot)) + CKTabsTol)))) + */ + { + /* It isn't possible to maintain correct indentation with the NESTED version */ + vds = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vgs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] ; + vbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] ; + vges = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] ; + vgms = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] ; + + vbd = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]] ; + vdbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] ; + vdbd = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5] ; + vsbs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] ; + vses = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] ; + vdes = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] ; + + vgd = vgs - vds ; + vgb = vgs - vbs ; + vged = vges - vds ; + vgmd = vgms - vds ; + vgmb = vgms - vbs ; + + vbs_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? vbs : vsbs ; + vbd_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? vbd : vdbd ; + +/*** qdef should not be kept fixed even if vgs, vds & vbs has converged +**** qdef = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] ; +***/ + cdrain = BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] ; + + if ((CKTmode & (MODETRAN | MODEAC)) || ((CKTmode & MODETRANOP) && (CKTmode & MODEUIC))) + { + ByPass = 1 ; + + qgate = BSIM4v7entry.d_BSIM4v7qgateRWArray [instance_ID] ; + qbulk = BSIM4v7entry.d_BSIM4v7qbulkRWArray [instance_ID] ; + qdrn = BSIM4v7entry.d_BSIM4v7qdrnRWArray [instance_ID] ; + cgdo = BSIM4v7entry.d_BSIM4v7cgdoArray [instance_ID] ; + qgdo = BSIM4v7entry.d_BSIM4v7qgdoArray [instance_ID] ; + cgso = BSIM4v7entry.d_BSIM4v7cgsoArray [instance_ID] ; + qgso = BSIM4v7entry.d_BSIM4v7qgsoArray [instance_ID] ; + + /* Unconditional jump */ + goto line755 ; + } else { + /* Unconditional jump */ + goto line850 ; + } + } +#endif /*NOBYPASS*/ + + von = BSIM4v7entry.d_BSIM4v7vonRWArray [instance_ID] ; + + /* 4 - DIVERGENT - CRITICAL */ + if (CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] >= 0.0) + { + vgs = DEVfetlim (vgs, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2], von) ; + vds = vgs - vgd ; + vds = DEVlimvds (vds, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3]) ; + vgd = vgs - vds ; + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + vges = DEVfetlim (vges, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7], von) ; + vgms = DEVfetlim (vgms, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8], von) ; + vged = vges - vds ; + vgmd = vgms - vds ; + } + else if ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 1) || (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2)) + { + vges = DEVfetlim (vges, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7], von) ; + vged = vges - vds ; + } + + if (BSIM4v7rdsMod) + { + vdes = DEVlimvds (vdes, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10]) ; + vses = -DEVlimvds (-vses, -(CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9])) ; + } + + } else { + vgd = DEVfetlim (vgd, vgdo, von) ; + vds = vgs - vgd ; + vds = -DEVlimvds (-vds, -(CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3])) ; + vgs = vgd + vds ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + vged = DEVfetlim (vged, vgedo, von) ; + vges = vged + vds ; + vgmd = DEVfetlim (vgmd, vgmdo, von) ; + vgms = vgmd + vds ; + } + if ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 1) || (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2)) + { + vged = DEVfetlim (vged, vgedo, von) ; + vges = vged + vds ; + } + + if (BSIM4v7rdsMod) + { + vdes = -DEVlimvds (-vdes, -(CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10])) ; + vses = DEVlimvds (vses, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9]) ; + } + } + + /* 5 - DIVERGENT - CRITICAL */ + if (vds >= 0.0) + { + vbs = DEVpnjlim (vbs, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1], CONSTvt0, BSIM4v7vcrit, &Check) ; + vbd = vbs - vds ; + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + vdbs = DEVpnjlim (vdbs, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4], CONSTvt0, BSIM4v7vcrit, &Check1) ; + vdbd = vdbs - vds ; + vsbs = DEVpnjlim (vsbs, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6], CONSTvt0, BSIM4v7vcrit, &Check2) ; + + if ((Check1 == 0) && (Check2 == 0)) + Check = 0 ; + else + Check = 1 ; + } + } else { + vbd = DEVpnjlim (vbd, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]], CONSTvt0, BSIM4v7vcrit, &Check) ; + vbs = vbd + vds ; + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + vdbd = DEVpnjlim (vdbd, CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5], CONSTvt0, BSIM4v7vcrit, &Check1) ; + vdbs = vdbd + vds ; + vsbdo = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] ; + vsbd = vsbs - vds ; + vsbd = DEVpnjlim (vsbd, vsbdo, CONSTvt0, BSIM4v7vcrit, &Check2) ; + vsbs = vsbd + vds ; + + if ((Check1 == 0) && (Check2 == 0)) + { + Check = 0 ; + } else { + Check = 1 ; + } + } + } + } + + /* Calculate DC currents and their derivatives */ + vbd = vbs - vds ; + vgd = vgs - vds ; + vgb = vgs - vbs ; + vged = vges - vds ; + vgmd = vgms - vds ; + vgmb = vgms - vbs ; + vdbd = vdbs - vds ; + + vbs_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? vbs : vsbs ; + vbd_jct = (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) ? vbd : vdbd ; + + + /* Source/drain junction diode DC model begins */ + Nvtms = BSIM4v7vtm * BSIM4v7SjctEmissionCoeff ; + +/* + if ((BSIM4v7entry.d_BSIM4v7AseffArray [instance_ID] <= 0.0) && (BSIM4v7entry.d_BSIM4v7PseffArray [instance_ID] <= 0.0)) + SourceSatCurrent = 1.0e-14 ; //v4.7 +*/ + /* POTENTIALLY DIVERGENT */ + if ((BSIM4v7entry.d_BSIM4v7AseffArray [instance_ID] <= 0.0) && (BSIM4v7entry.d_BSIM4v7PseffArray [instance_ID] <= 0.0)) + { + SourceSatCurrent = 0.0 ; + } else { + SourceSatCurrent = BSIM4v7entry.d_BSIM4v7AseffArray [instance_ID] * BSIM4v7SjctTempSatCurDensity + + BSIM4v7entry.d_BSIM4v7PseffArray [instance_ID] * BSIM4v7SjctSidewallTempSatCurDensity + + pParam->BSIM4v7weffCJ * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * BSIM4v7SjctGateSidewallTempSatCurDensity ; + } + + /* POTENTIALLY DIVERGENT */ + if (SourceSatCurrent <= 0.0) + { + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] * vbs_jct ; + } else { + switch (BSIM4v7dioMod) + { + case 0 : + evbs = exp (vbs_jct / Nvtms) ; + T1 = BSIM4v7xjbvs * exp (-(BSIM4v7bvs + vbs_jct) / Nvtms) ; + /* WDLiu: Magic T1 in this form; different from BSIM4v7 beta. */ + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = SourceSatCurrent * (evbs + T1) / Nvtms + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = SourceSatCurrent * (evbs + BSIM4v7entry.d_BSIM4v7XExpBVSArray [instance_ID] - T1 - 1.0) + CKTgmin * vbs_jct ; + break ; + + case 1 : + T2 = vbs_jct / Nvtms ; + if (T2 < -EXP_THRESHOLD) + { + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = SourceSatCurrent * (MIN_EXP - 1.0) + CKTgmin * vbs_jct ; + } + else if (vbs_jct <= BSIM4v7entry.d_BSIM4v7vjsmFwdArray [instance_ID]) + { + evbs = exp (T2) ; + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = SourceSatCurrent * evbs / Nvtms + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = SourceSatCurrent * (evbs - 1.0) + CKTgmin * vbs_jct ; + } else { + T0 = BSIM4v7entry.d_BSIM4v7IVjsmFwdArray [instance_ID] / Nvtms ; + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = T0 + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7IVjsmFwdArray [instance_ID] - SourceSatCurrent + T0 * + (vbs_jct - BSIM4v7entry.d_BSIM4v7vjsmFwdArray [instance_ID]) + CKTgmin * vbs_jct ; + } + break ; + + case 2 : + if (vbs_jct < BSIM4v7entry.d_BSIM4v7vjsmRevArray [instance_ID]) + { + T0 = vbs_jct / Nvtms ; + if (T0 < -EXP_THRESHOLD) + { + evbs = MIN_EXP ; + devbs_dvb = 0.0 ; + } + else + { + evbs = exp (T0) ; + devbs_dvb = evbs / Nvtms ; + } + + T1 = evbs - 1.0 ; + T2 = BSIM4v7entry.d_BSIM4v7IVjsmRevArray [instance_ID] + BSIM4v7entry.d_BSIM4v7SslpRevArray [instance_ID] * (vbs_jct - BSIM4v7entry.d_BSIM4v7vjsmRevArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = devbs_dvb * T2 + T1 * BSIM4v7entry.d_BSIM4v7SslpRevArray [instance_ID] + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = T1 * T2 + CKTgmin * vbs_jct ; + } + else if (vbs_jct <= BSIM4v7entry.d_BSIM4v7vjsmFwdArray [instance_ID]) + { + T0 = vbs_jct / Nvtms ; + if (T0 < -EXP_THRESHOLD) + { + evbs = MIN_EXP ; + devbs_dvb = 0.0 ; + } + else + { + evbs = exp (T0) ; + devbs_dvb = evbs / Nvtms ; + } + + T1 = (BSIM4v7bvs + vbs_jct) / Nvtms ; + if (T1 > EXP_THRESHOLD) + { + T2 = MIN_EXP ; + T3 = 0.0 ; + } + else + { + T2 = exp (-T1) ; + T3 = -T2 /Nvtms ; + } + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = SourceSatCurrent * (devbs_dvb - BSIM4v7xjbvs * T3) + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = SourceSatCurrent * (evbs + BSIM4v7entry.d_BSIM4v7XExpBVSArray [instance_ID] - 1.0 - + BSIM4v7xjbvs * T2) + CKTgmin * vbs_jct ; + } + else + { + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7SslpFwdArray [instance_ID] + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7IVjsmFwdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7SslpFwdArray [instance_ID] * + (vbs_jct - BSIM4v7entry.d_BSIM4v7vjsmFwdArray [instance_ID]) + CKTgmin * vbs_jct ; + } + break ; + + default: break ; + } + } + + Nvtmd = BSIM4v7vtm * BSIM4v7DjctEmissionCoeff ; +/* + if ((BSIM4v7entry.d_BSIM4v7AdeffArray [instance_ID] <= 0.0) && (BSIM4v7entry.d_BSIM4v7PdeffArray [instance_ID] <= 0.0)) + DrainSatCurrent = 1.0e-14 ; //v4.7 +*/ + /* POTENTIALLY DIVERGENT */ + if ((BSIM4v7entry.d_BSIM4v7AdeffArray [instance_ID] <= 0.0) && (BSIM4v7entry.d_BSIM4v7PdeffArray [instance_ID] <= 0.0)) + { + DrainSatCurrent = 0.0 ; + } else { + DrainSatCurrent = BSIM4v7entry.d_BSIM4v7AdeffArray [instance_ID] * BSIM4v7DjctTempSatCurDensity + + BSIM4v7entry.d_BSIM4v7PdeffArray [instance_ID] * BSIM4v7DjctSidewallTempSatCurDensity + + pParam->BSIM4v7weffCJ * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * BSIM4v7DjctGateSidewallTempSatCurDensity ; + } + + /* POTENTIALLY DIVERGENT */ + if (DrainSatCurrent <= 0.0) + { + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * vbd_jct ; + } else { + switch (BSIM4v7dioMod) + { + case 0 : + evbd = exp (vbd_jct / Nvtmd) ; + T1 = BSIM4v7xjbvd * exp (-(BSIM4v7bvd + vbd_jct) / Nvtmd) ; + /* WDLiu: Magic T1 in this form; different from BSIM4v7 beta. */ + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = DrainSatCurrent * (evbd + T1) / Nvtmd + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = DrainSatCurrent * (evbd + BSIM4v7entry.d_BSIM4v7XExpBVDArray [instance_ID] - T1 - 1.0) + CKTgmin * vbd_jct ; + break ; + + case 1 : + T2 = vbd_jct / Nvtmd ; + if (T2 < -EXP_THRESHOLD) + { + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = DrainSatCurrent * (MIN_EXP - 1.0) + CKTgmin * vbd_jct ; + } + else if (vbd_jct <= BSIM4v7entry.d_BSIM4v7vjdmFwdArray [instance_ID]) + { + evbd = exp (T2) ; + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = DrainSatCurrent * evbd / Nvtmd + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = DrainSatCurrent * (evbd - 1.0) + CKTgmin * vbd_jct ; + } else { + T0 = BSIM4v7entry.d_BSIM4v7IVjdmFwdArray [instance_ID] / Nvtmd ; + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = T0 + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7IVjdmFwdArray [instance_ID] - DrainSatCurrent + + T0 * (vbd_jct - BSIM4v7entry.d_BSIM4v7vjdmFwdArray [instance_ID]) + CKTgmin * vbd_jct ; + } + break ; + + case 2 : + if (vbd_jct < BSIM4v7entry.d_BSIM4v7vjdmRevArray [instance_ID]) + { + T0 = vbd_jct / Nvtmd ; + if (T0 < -EXP_THRESHOLD) + { + evbd = MIN_EXP ; + devbd_dvb = 0.0 ; + } + else + { + evbd = exp (T0) ; + devbd_dvb = evbd / Nvtmd ; + } + + T1 = evbd - 1.0 ; + T2 = BSIM4v7entry.d_BSIM4v7IVjdmRevArray [instance_ID] + BSIM4v7entry.d_BSIM4v7DslpRevArray [instance_ID] * (vbd_jct - BSIM4v7entry.d_BSIM4v7vjdmRevArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = devbd_dvb * T2 + T1 * BSIM4v7entry.d_BSIM4v7DslpRevArray [instance_ID] + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = T1 * T2 + CKTgmin * vbd_jct ; + } + else if (vbd_jct <= BSIM4v7entry.d_BSIM4v7vjdmFwdArray [instance_ID]) + { + T0 = vbd_jct / Nvtmd ; + if (T0 < -EXP_THRESHOLD) + { + evbd = MIN_EXP ; + devbd_dvb = 0.0 ; + } + else + { + evbd = exp (T0) ; + devbd_dvb = evbd / Nvtmd ; + } + + T1 = (BSIM4v7bvd + vbd_jct) / Nvtmd ; + if (T1 > EXP_THRESHOLD) + { + T2 = MIN_EXP ; + T3 = 0.0 ; + } + else + { + T2 = exp (-T1) ; + T3 = -T2 /Nvtmd ; + } + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = DrainSatCurrent * (devbd_dvb - BSIM4v7xjbvd * T3) + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = DrainSatCurrent * (evbd + BSIM4v7entry.d_BSIM4v7XExpBVDArray [instance_ID] - 1.0 - + BSIM4v7xjbvd * T2) + CKTgmin * vbd_jct ; + } + else + { + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7DslpFwdArray [instance_ID] + CKTgmin ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7IVjdmFwdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7DslpFwdArray [instance_ID] * + (vbd_jct - BSIM4v7entry.d_BSIM4v7vjdmFwdArray [instance_ID]) + CKTgmin * vbd_jct ; + } + break ; + + default: break ; + } + } + + + /* trap-assisted tunneling and recombination current for reverse bias */ + Nvtmrssws = BSIM4v7vtm0 * BSIM4v7njtsswstemp ; + Nvtmrsswgs = BSIM4v7vtm0 * BSIM4v7njtsswgstemp ; + Nvtmrss = BSIM4v7vtm0 * BSIM4v7njtsstemp ; + Nvtmrsswd = BSIM4v7vtm0 * BSIM4v7njtsswdtemp ; + Nvtmrsswgd = BSIM4v7vtm0 * BSIM4v7njtsswgdtemp ; + Nvtmrsd = BSIM4v7vtm0 * BSIM4v7njtsdtemp ; + + /* POSSIBLE DIVERGENT */ + if ((BSIM4v7vtss - vbs_jct) < (BSIM4v7vtss * 1e-3)) + { + T9 = 1.0e3 ; + T0 = - vbs_jct / Nvtmrss * T9 ; + DEXP (T0, T1, T10) ; + dT1_dVb = T10 / Nvtmrss * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtss - vbs_jct) ; + T0 = -vbs_jct / Nvtmrss * BSIM4v7vtss * T9 ; + dT0_dVb = BSIM4v7vtss / Nvtmrss * (T9 + vbs_jct * T9 * T9) ; + DEXP (T0, T1, T10) ; + dT1_dVb = T10 * dT0_dVb ; + } + + if ((BSIM4v7vtsd - vbd_jct) < (BSIM4v7vtsd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsd * T9 ; + DEXP (T0, T2, T10) ; + dT2_dVb = T10 / Nvtmrsd * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtsd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsd * BSIM4v7vtsd * T9 ; + dT0_dVb = BSIM4v7vtsd / Nvtmrsd * (T9 + vbd_jct * T9 * T9) ; + DEXP (T0, T2, T10) ; + dT2_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4v7vtssws - vbs_jct) < (BSIM4v7vtssws * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbs_jct / Nvtmrssws * T9 ; + DEXP (T0, T3, T10) ; + dT3_dVb = T10 / Nvtmrssws * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtssws - vbs_jct) ; + T0 = -vbs_jct / Nvtmrssws * BSIM4v7vtssws * T9 ; + dT0_dVb = BSIM4v7vtssws / Nvtmrssws * (T9 + vbs_jct * T9 * T9) ; + DEXP (T0, T3, T10) ; + dT3_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4v7vtsswd - vbd_jct) < (BSIM4v7vtsswd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsswd * T9 ; + DEXP (T0, T4, T10) ; + dT4_dVb = T10 / Nvtmrsswd * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtsswd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsswd * BSIM4v7vtsswd * T9 ; + dT0_dVb = BSIM4v7vtsswd / Nvtmrsswd * (T9 + vbd_jct * T9 * T9) ; + DEXP(T0, T4, T10) ; + dT4_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4v7vtsswgs - vbs_jct) < (BSIM4v7vtsswgs * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbs_jct / Nvtmrsswgs * T9 ; + DEXP (T0, T5, T10) ; + dT5_dVb = T10 / Nvtmrsswgs * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtsswgs - vbs_jct) ; + T0 = -vbs_jct / Nvtmrsswgs * BSIM4v7vtsswgs * T9 ; + dT0_dVb = BSIM4v7vtsswgs / Nvtmrsswgs * (T9 + vbs_jct * T9 * T9) ; + DEXP(T0, T5, T10) ; + dT5_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4v7vtsswgd - vbd_jct) < (BSIM4v7vtsswgd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsswgd * T9 ; + DEXP (T0, T6, T10) ; + dT6_dVb = T10 / Nvtmrsswgd * T9 ; + } else { + T9 = 1.0 / (BSIM4v7vtsswgd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsswgd * BSIM4v7vtsswgd * T9 ; + dT0_dVb = BSIM4v7vtsswgd / Nvtmrsswgd * (T9 + vbd_jct * T9 * T9) ; + DEXP (T0, T6, T10) ; + dT6_dVb = T10 * dT0_dVb ; + } + + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] += BSIM4v7entry.d_BSIM4v7SjctTempRevSatCurArray [instance_ID] * dT1_dVb + BSIM4v7entry.d_BSIM4v7SswTempRevSatCurArray [instance_ID] * dT3_dVb + + BSIM4v7entry.d_BSIM4v7SswgTempRevSatCurArray [instance_ID] * dT5_dVb ; + BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] -= BSIM4v7entry.d_BSIM4v7SjctTempRevSatCurArray [instance_ID] * (T1 - 1.0) + BSIM4v7entry.d_BSIM4v7SswTempRevSatCurArray [instance_ID] * (T3 - 1.0) + + BSIM4v7entry.d_BSIM4v7SswgTempRevSatCurArray [instance_ID] * (T5 - 1.0) ; + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] += BSIM4v7entry.d_BSIM4v7DjctTempRevSatCurArray [instance_ID] * dT2_dVb + BSIM4v7entry.d_BSIM4v7DswTempRevSatCurArray [instance_ID] * dT4_dVb + + BSIM4v7entry.d_BSIM4v7DswgTempRevSatCurArray [instance_ID] * dT6_dVb ; + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] -= BSIM4v7entry.d_BSIM4v7DjctTempRevSatCurArray [instance_ID] * (T2 - 1.0) + BSIM4v7entry.d_BSIM4v7DswTempRevSatCurArray [instance_ID] * (T4 - 1.0) + + BSIM4v7entry.d_BSIM4v7DswgTempRevSatCurArray [instance_ID] * (T6 - 1.0) ; + /* End of diode DC model */ + + + /* 6 - DIVERGENT */ + if (vds >= 0.0) + { + BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] = 1 ; + Vds = vds ; + Vbs = vbs ; + + /* WDLiu: for GIDL */ + } else { + BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] = -1 ; + Vds = -vds ; + Vbs = vbd ; + } + + + /* 3 - non-divergent */ + /* dunga */ + if (BSIM4v7mtrlMod) + { + epsrox = 3.9 ; + toxe = BSIM4v7eot ; + epssub = EPS0 * BSIM4v7epsrsub ; + } else { + epsrox = BSIM4v7epsrox ; + toxe = BSIM4v7toxe ; + epssub = EPSSI ; + } + + + T0 = Vbs - BSIM4v7entry.d_BSIM4v7vbscArray [instance_ID] - 0.001 ; + T1 = sqrt (T0 * T0 - 0.004 * BSIM4v7entry.d_BSIM4v7vbscArray [instance_ID]) ; + + /* 7 - DIVERGENT */ + if (T0 >= 0.0) + { + Vbseff = BSIM4v7entry.d_BSIM4v7vbscArray [instance_ID] + 0.5 * (T0 + T1) ; + dVbseff_dVb = 0.5 * (1.0 + T0 / T1) ; + } else { + T2 = -0.002 / (T1 - T0) ; + Vbseff = BSIM4v7entry.d_BSIM4v7vbscArray [instance_ID] * (1.0 + T2) ; + dVbseff_dVb = T2 * BSIM4v7entry.d_BSIM4v7vbscArray [instance_ID] / T1 ; + } + + + /* JX: Correction to forward body bias */ + T9 = 0.95 * pParam->BSIM4v7phi ; + T0 = T9 - Vbseff - 0.001 ; + T1 = sqrt (T0 * T0 + 0.004 * T9) ; + Vbseff = T9 - 0.5 * (T0 + T1) ; + dVbseff_dVb *= 0.5 * (1.0 + T0 / T1) ; + Phis = pParam->BSIM4v7phi - Vbseff ; + dPhis_dVb = -1.0 ; + sqrtPhis = sqrt (Phis) ; + dsqrtPhis_dVb = -0.5 / sqrtPhis ; + + Xdep = pParam->BSIM4v7Xdep0 * sqrtPhis / pParam->BSIM4v7sqrtPhi ; + dXdep_dVb = (pParam->BSIM4v7Xdep0 / pParam->BSIM4v7sqrtPhi) * dsqrtPhis_dVb ; + + Leff = pParam->BSIM4v7leff ; + Vtm = BSIM4v7vtm ; + Vtm0 = BSIM4v7vtm0 ; + + + /* Vth Calculation */ + T3 = sqrt (Xdep) ; + V0 = pParam->BSIM4v7vbi - pParam->BSIM4v7phi ; + T0 = pParam->BSIM4v7dvt2 * Vbseff ; + + /* 8 - DIVERGENT */ + if (T0 >= - 0.5) + { + T1 = 1.0 + T0 ; + T2 = pParam->BSIM4v7dvt2 ; + } else { + T4 = 1.0 / (3.0 + 8.0 * T0) ; + T1 = (1.0 + 3.0 * T0) * T4 ; + T2 = pParam->BSIM4v7dvt2 * T4 * T4 ; + } + lt1 = BSIM4v7factor1 * T3 * T1 ; + dlt1_dVb = BSIM4v7factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2) ; + T0 = pParam->BSIM4v7dvt2w * Vbseff ; + + /* 9 - DIVERGENT */ + if (T0 >= - 0.5) + { + T1 = 1.0 + T0 ; + T2 = pParam->BSIM4v7dvt2w ; + } else { + T4 = 1.0 / (3.0 + 8.0 * T0) ; + T1 = (1.0 + 3.0 * T0) * T4 ; + T2 = pParam->BSIM4v7dvt2w * T4 * T4 ; + } + ltw = BSIM4v7factor1 * T3 * T1 ; + dltw_dVb = BSIM4v7factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2) ; + T0 = pParam->BSIM4v7dvt1 * Leff / lt1 ; + + /* 10 - DIVERGENT */ + if (T0 < EXP_THRESHOLD) + { + T1 = exp (T0) ; + T2 = T1 - 1.0 ; + T3 = T2 * T2 ; + T4 = T3 + 2.0 * T1 * MIN_EXP ; + Theta0 = T1 / T4 ; + dT1_dVb = -T0 * T1 * dlt1_dVb / lt1 ; + dTheta0_dVb = dT1_dVb * (T4 - 2.0 * T1 * (T2 + MIN_EXP)) / T4 / T4 ; + } else { + Theta0 = 1.0 / (MAX_EXP - 2.0) ; /* 3.0 * MIN_EXP omitted */ + dTheta0_dVb = 0.0 ; + } + BSIM4v7entry.d_BSIM4v7thetavthArray [instance_ID] = pParam->BSIM4v7dvt0 * Theta0 ; + Delt_vth = BSIM4v7entry.d_BSIM4v7thetavthArray [instance_ID] * V0 ; + dDelt_vth_dVb = pParam->BSIM4v7dvt0 * dTheta0_dVb * V0 ; + T0 = pParam->BSIM4v7dvt1w * pParam->BSIM4v7weff * Leff / ltw ; + + /* 11 - DIVERGENT */ + if (T0 < EXP_THRESHOLD) + { + T1 = exp (T0) ; + T2 = T1 - 1.0 ; + T3 = T2 * T2 ; + T4 = T3 + 2.0 * T1 * MIN_EXP ; + T5 = T1 / T4 ; + dT1_dVb = -T0 * T1 * dltw_dVb / ltw ; + dT5_dVb = dT1_dVb * (T4 - 2.0 * T1 * (T2 + MIN_EXP)) / T4 / T4 ; + } else { + T5 = 1.0 / (MAX_EXP - 2.0) ; /* 3.0 * MIN_EXP omitted */ + dT5_dVb = 0.0 ; + } + T0 = pParam->BSIM4v7dvt0w * T5 ; + T2 = T0 * V0 ; + dT2_dVb = pParam->BSIM4v7dvt0w * dT5_dVb * V0 ; + TempRatio = CKTtemp / BSIM4v7tnom - 1.0 ; + T0 = sqrt (1.0 + pParam->BSIM4v7lpe0 / Leff) ; + T1 = pParam->BSIM4v7k1ox * (T0 - 1.0) * pParam->BSIM4v7sqrtPhi + (pParam->BSIM4v7kt1 + + pParam->BSIM4v7kt1l / Leff + pParam->BSIM4v7kt2 * Vbseff) * TempRatio ; + Vth_NarrowW = toxe * pParam->BSIM4v7phi / (pParam->BSIM4v7weff + pParam->BSIM4v7w0) ; + T3 = BSIM4v7entry.d_BSIM4v7eta0Array [instance_ID] + pParam->BSIM4v7etab * Vbseff ; + + /* 12 - DIVERGENT */ + if (T3 < 1.0e-4) + { + 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->BSIM4v7theta0vb0 ; + DIBL_Sft = dDIBL_Sft_dVd * Vds ; + Lpe_Vb = sqrt (1.0 + pParam->BSIM4v7lpeb / Leff) ; + Vth = BSIM4v7type * BSIM4v7entry.d_BSIM4v7vth0Array [instance_ID] + (pParam->BSIM4v7k1ox * sqrtPhis - pParam->BSIM4v7k1 * + pParam->BSIM4v7sqrtPhi) * Lpe_Vb - BSIM4v7entry.d_BSIM4v7k2oxArray [instance_ID] * Vbseff - Delt_vth - T2 + + (pParam->BSIM4v7k3 + pParam->BSIM4v7k3b * Vbseff) * Vth_NarrowW + T1 - DIBL_Sft ; + dVth_dVb = Lpe_Vb * pParam->BSIM4v7k1ox * dsqrtPhis_dVb - BSIM4v7entry.d_BSIM4v7k2oxArray [instance_ID] - dDelt_vth_dVb - + dT2_dVb + pParam->BSIM4v7k3b * Vth_NarrowW - pParam->BSIM4v7etab * Vds * + pParam->BSIM4v7theta0vb0 * T4 + pParam->BSIM4v7kt2 * TempRatio ; + dVth_dVd = -dDIBL_Sft_dVd ; + + + /* Calculate n */ + tmp1 = epssub / Xdep ; + BSIM4v7entry.d_BSIM4v7nstarArray [instance_ID] = BSIM4v7vtm / Charge_q * (BSIM4v7coxe + tmp1 + pParam->BSIM4v7cit) ; + tmp2 = pParam->BSIM4v7nfactor * tmp1 ; + tmp3 = pParam->BSIM4v7cdsc + pParam->BSIM4v7cdscb * Vbseff + pParam->BSIM4v7cdscd * Vds ; + tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM4v7cit) / BSIM4v7coxe ; + + /* 13 - DIVERGENT */ + if (tmp4 >= -0.5) + { + n = 1.0 + tmp4 ; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * + dTheta0_dVb + pParam->BSIM4v7cdscb * Theta0) / BSIM4v7coxe ; + dn_dVd = pParam->BSIM4v7cdscd * Theta0 / BSIM4v7coxe ; + } else { + 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->BSIM4v7cdscb * Theta0) / BSIM4v7coxe * T0 ; + dn_dVd = pParam->BSIM4v7cdscd * Theta0 / BSIM4v7coxe * T0 ; + } + + + /* Vth correction for Pocket implant */ + /* 14 - DIVERGENT */ + if (pParam->BSIM4v7dvtp0 > 0.0) + { + T0 = -pParam->BSIM4v7dvtp1 * Vds ; + if (T0 < -EXP_THRESHOLD) + { + T2 = MIN_EXP ; + dT2_dVd = 0.0 ; + } + else + { + T2 = exp (T0) ; + dT2_dVd = -pParam->BSIM4v7dvtp1 * T2 ; + } + T3 = Leff + pParam->BSIM4v7dvtp0 * (1.0 + T2) ; + dT3_dVd = pParam->BSIM4v7dvtp0 * dT2_dVd ; + + if (BSIM4v7tempMod < 2) + { + T4 = Vtm * log (Leff / T3) ; + dT4_dVd = -Vtm * dT3_dVd / T3 ; + } + else + { + T4 = BSIM4v7vtm0 * log (Leff / T3) ; + dT4_dVd = -BSIM4v7vtm0 * dT3_dVd / T3 ; + } + dDITS_Sft_dVd = dn_dVd * T4 + n * dT4_dVd ; + dDITS_Sft_dVb = T4 * dn_dVb ; + Vth -= n * T4 ; + dVth_dVd -= dDITS_Sft_dVd ; + dVth_dVb -= dDITS_Sft_dVb ; + } + + /* v4.7 DITS_SFT2 */ + /* 15 - DIVERGENT */ + if ((pParam->BSIM4v7dvtp4 == 0.0) || (pParam->BSIM4v7dvtp2factor == 0.0)) + { + T0 = 0.0 ; + DITS_Sft2 = 0.0 ; + } else { + T1 = 2.0 * pParam->BSIM4v7dvtp4 * Vds ; + DEXP (T1, T0, T10) ; + DITS_Sft2 = pParam->BSIM4v7dvtp2factor * (T0 - 1) / (T0 + 1) ; + dDITS_Sft2_dVd = pParam->BSIM4v7dvtp2factor * pParam->BSIM4v7dvtp4 * 4.0 * T10 / ((T0+1) * (T0+1)) ; + Vth -= DITS_Sft2 ; + dVth_dVd -= dDITS_Sft2_dVd ; + } + BSIM4v7entry.d_BSIM4v7vonRWArray [instance_ID] = Vth ; + + + /* Poly Gate Si Depletion Effect */ + T0 = BSIM4v7entry.d_BSIM4v7vfbArray [instance_ID] + pParam->BSIM4v7phi; + + /* 16 - DIVERGENT */ + if (BSIM4v7mtrlMod == 0) + T1 = EPSSI ; + else + T1 = BSIM4v7epsrgate * EPS0 ; + + BSIM4v7polyDepletion (T0, pParam->BSIM4v7ngate, T1, BSIM4v7coxe, vgs, &vgs_eff, &dvgs_eff_dvg) ; + + BSIM4v7polyDepletion (T0, pParam->BSIM4v7ngate, T1, BSIM4v7coxe, vgd, &vgd_eff, &dvgd_eff_dvg) ; + + /* 17 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] > 0) + { + Vgs_eff = vgs_eff ; + dVgs_eff_dVg = dvgs_eff_dvg ; + } else { + Vgs_eff = vgd_eff ; + dVgs_eff_dVg = dvgd_eff_dvg ; + } + BSIM4v7entry.d_BSIM4v7vgs_effArray [instance_ID] = vgs_eff ; + BSIM4v7entry.d_BSIM4v7vgd_effArray [instance_ID] = vgd_eff ; + BSIM4v7entry.d_BSIM4v7dvgs_eff_dvgArray [instance_ID] = dvgs_eff_dvg ; + BSIM4v7entry.d_BSIM4v7dvgd_eff_dvgArray [instance_ID] = dvgd_eff_dvg ; + Vgst = Vgs_eff - Vth ; + + + /* Calculate Vgsteff */ + T0 = n * Vtm ; + T1 = pParam->BSIM4v7mstar * Vgst ; + T2 = T1 / T0 ; + + /* 18 - DIVERGENT */ + if (T2 > EXP_THRESHOLD) + { + T10 = T1 ; + dT10_dVg = pParam->BSIM4v7mstar * dVgs_eff_dVg ; + dT10_dVd = -dVth_dVd * pParam->BSIM4v7mstar ; + dT10_dVb = -dVth_dVb * pParam->BSIM4v7mstar ; + } + else if (T2 < -EXP_THRESHOLD) + { + T10 = Vtm * log (1.0 + MIN_EXP) ; + dT10_dVg = 0.0 ; + dT10_dVd = T10 * dn_dVd ; + dT10_dVb = T10 * dn_dVb ; + T10 *= n ; + } else { + ExpVgst = exp (T2) ; + T3 = Vtm * log (1.0 + ExpVgst) ; + T10 = n * T3 ; + dT10_dVg = pParam->BSIM4v7mstar * ExpVgst / (1.0 + ExpVgst) ; + dT10_dVb = T3 * dn_dVb - dT10_dVg * (dVth_dVb + Vgst * dn_dVb / n) ; + dT10_dVd = T3 * dn_dVd - dT10_dVg * (dVth_dVd + Vgst * dn_dVd / n) ; + dT10_dVg *= dVgs_eff_dVg ; + } + + T1 = pParam->BSIM4v7voffcbn - (1.0 - pParam->BSIM4v7mstar) * Vgst ; + T2 = T1 / T0 ; + + /* 19 - DIVERGENT */ + if (T2 < -EXP_THRESHOLD) + { + T3 = BSIM4v7coxe * MIN_EXP / pParam->BSIM4v7cdep0 ; + T9 = pParam->BSIM4v7mstar + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } + else if (T2 > EXP_THRESHOLD) + { + T3 = BSIM4v7coxe * MAX_EXP / pParam->BSIM4v7cdep0 ; + T9 = pParam->BSIM4v7mstar + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } else { + ExpVgst = exp (T2) ; + T3 = BSIM4v7coxe / pParam->BSIM4v7cdep0 ; + T4 = T3 * ExpVgst ; + T5 = T1 * T4 / T0 ; + T9 = pParam->BSIM4v7mstar + n * T4 ; + dT9_dVg = T3 * (pParam->BSIM4v7mstar - 1.0) * ExpVgst / Vtm ; + dT9_dVb = T4 * dn_dVb - dT9_dVg * dVth_dVb - T5 * dn_dVb ; + dT9_dVd = T4 * dn_dVd - dT9_dVg * dVth_dVd - T5 * dn_dVd ; + dT9_dVg *= dVgs_eff_dVg ; + } + BSIM4v7entry.d_BSIM4v7VgsteffArray [instance_ID] = Vgsteff = T10 / T9 ; + T11 = T9 * T9 ; + dVgsteff_dVg = (T9 * dT10_dVg - T10 * dT9_dVg) / T11 ; + dVgsteff_dVd = (T9 * dT10_dVd - T10 * dT9_dVd) / T11 ; + dVgsteff_dVb = (T9 * dT10_dVb - T10 * dT9_dVb) / T11 ; + + + /* Calculate Effective Channel Geometry */ + T9 = sqrtPhis - pParam->BSIM4v7sqrtPhi; + Weff = pParam->BSIM4v7weff - 2.0 * (pParam->BSIM4v7dwg * Vgsteff + pParam->BSIM4v7dwb * T9) ; + dWeff_dVg = -2.0 * pParam->BSIM4v7dwg ; + dWeff_dVb = -2.0 * pParam->BSIM4v7dwb * dsqrtPhis_dVb ; + + /* 20 - DIVERGENT */ + 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 ; + } + + /* 21 - DIVERGENT */ + if (BSIM4v7rdsMod == 1) + Rds = dRds_dVg = dRds_dVb = 0.0 ; + else + { + T0 = 1.0 + pParam->BSIM4v7prwg * Vgsteff ; + dT0_dVg = -pParam->BSIM4v7prwg / T0 / T0 ; + T1 = pParam->BSIM4v7prwb * T9 ; + dT1_dVb = pParam->BSIM4v7prwb * dsqrtPhis_dVb ; + T2 = 1.0 / T0 + T1 ; + T3 = T2 + sqrt (T2 * T2 + 0.01) ; /* 0.01 = 4.0 * 0.05 * 0.05 */ + dT3_dVg = 1.0 + T2 / (T3 - T2) ; + dT3_dVb = dT3_dVg * dT1_dVb ; + dT3_dVg *= dT0_dVg ; + T4 = pParam->BSIM4v7rds0 * 0.5 ; + Rds = pParam->BSIM4v7rdswmin + T3 * T4 ; + dRds_dVg = T4 * dT3_dVg ; + dRds_dVb = T4 * dT3_dVb ; + + if (Rds > 0.0) + BSIM4v7entry.d_BSIM4v7grdswArray [instance_ID] = 1.0 / Rds* BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; /*4.6.2*/ + else + BSIM4v7entry.d_BSIM4v7grdswArray [instance_ID] = 0.0 ; + } + + + /* Calculate Abulk */ + T9 = 0.5 * pParam->BSIM4v7k1ox * Lpe_Vb / sqrtPhis ; + T1 = T9 + BSIM4v7entry.d_BSIM4v7k2oxArray [instance_ID] - pParam->BSIM4v7k3b * Vth_NarrowW ; + dT1_dVb = -T9 / sqrtPhis * dsqrtPhis_dVb ; + T9 = sqrt (pParam->BSIM4v7xj * Xdep) ; + tmp1 = Leff + 2.0 * T9 ; + T5 = Leff / tmp1 ; + tmp2 = pParam->BSIM4v7a0 * T5 ; + tmp3 = pParam->BSIM4v7weff + pParam->BSIM4v7b1 ; + tmp4 = pParam->BSIM4v7b0 / 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->BSIM4v7ags * pParam->BSIM4v7a0 * T7 ; + dAbulk_dVg = -T1 * T8 ; + Abulk = Abulk0 + dAbulk_dVg * Vgsteff ; + dAbulk_dVb = dAbulk0_dVb - T8 * Vgsteff * (dT1_dVb + 3.0 * T1 * dT2_dVb) ; + + /* 22 - DIVERGENT */ + 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 ; + } + + /* 23 - DIVERGENT */ + if (Abulk < 0.1) + { + T9 = 1.0 / (3.0 - 20.0 * Abulk) ; + Abulk = (0.2 - Abulk) * T9 ; + T10 = T9 * T9 ; + dAbulk_dVb *= T10 ; + dAbulk_dVg *= T10 ; + } + BSIM4v7entry.d_BSIM4v7AbulkArray [instance_ID] = Abulk ; + T2 = pParam->BSIM4v7keta * Vbseff ; + + /* 24 - DIVERGENT */ + if (T2 >= -0.9) + { + T0 = 1.0 / (1.0 + T2) ; + dT0_dVb = -pParam->BSIM4v7keta * T0 * T0 ; + } + else + { + T1 = 1.0 / (0.8 + T2) ; + T0 = (17.0 + 20.0 * T2) * T1 ; + dT0_dVb = -pParam->BSIM4v7keta * 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 */ + /* 4 - non-divergent */ + if (BSIM4v7mtrlMod && BSIM4v7mtrlCompatMod == 0) + T14 = 2.0 * BSIM4v7type * (BSIM4v7phig - BSIM4v7easub - 0.5 * BSIM4v7Eg0 + 0.45) ; + else + T14 = 0.0 ; + + /* 5 - non-divergent */ + if (BSIM4v7mobMod == 0) + { + T0 = Vgsteff + Vth + Vth - T14 ; + T2 = pParam->BSIM4v7ua + pParam->BSIM4v7uc * Vbseff ; + T3 = T0 / toxe ; + T12 = sqrt (Vth * Vth + 0.0001) ; + T9 = 1.0 / (Vgsteff + 2 * T12) ; + T10 = T9 * toxe ; + T8 = pParam->BSIM4v7ud * T10 * T10 * Vth ; + T6 = T8 * Vth ; + T5 = T3 * (T2 + pParam->BSIM4v7ub * T3) + T6 ; + T7 = -2.0 * T6 * T9 ; + T11 = T7 * Vth / T12 ; + dDenomi_dVg = (T2 + 2.0 * pParam->BSIM4v7ub * T3) / toxe ; + T13 = 2.0 * (dDenomi_dVg + T11 + T8) ; + dDenomi_dVd = T13 * dVth_dVd ; + dDenomi_dVb = T13 * dVth_dVb + pParam->BSIM4v7uc * T3 ; + dDenomi_dVg += T7 ; + } + else if (BSIM4v7mobMod == 1) + { + T0 = Vgsteff + Vth + Vth - T14 ; + T2 = 1.0 + pParam->BSIM4v7uc * Vbseff ; + T3 = T0 / toxe ; + T4 = T3 * (pParam->BSIM4v7ua + pParam->BSIM4v7ub * T3) ; + T12 = sqrt (Vth * Vth + 0.0001) ; + T9 = 1.0 / (Vgsteff + 2 * T12) ; + T10 = T9 * toxe ; + T8 = pParam->BSIM4v7ud * T10 * T10 * Vth ; + T6 = T8 * Vth ; + T5 = T4 * T2 + T6 ; + T7 = -2.0 * T6 * T9 ; + T11 = T7 * Vth / T12 ; + dDenomi_dVg = (pParam->BSIM4v7ua + 2.0 * pParam->BSIM4v7ub * T3) * T2 / toxe ; + T13 = 2.0 * (dDenomi_dVg + T11 + T8) ; + dDenomi_dVd = T13 * dVth_dVd ; + dDenomi_dVb = T13 * dVth_dVb + pParam->BSIM4v7uc * T4 ; + dDenomi_dVg += T7 ; + } + else if (BSIM4v7mobMod == 2) + { + T0 = (Vgsteff + BSIM4v7entry.d_BSIM4v7vtfbphi1Array [instance_ID]) / toxe ; + T1 = exp (pParam->BSIM4v7eu * log (T0)) ; + dT1_dVg = T1 * pParam->BSIM4v7eu / T0 / toxe ; + T2 = pParam->BSIM4v7ua + pParam->BSIM4v7uc * Vbseff ; + T3 = T0 / toxe ; /*Do we need it?*/ + T12 = sqrt (Vth * Vth + 0.0001) ; + T9 = 1.0 / (Vgsteff + 2 * T12) ; + T10 = T9 * toxe ; + T8 = pParam->BSIM4v7ud * T10 * T10 * Vth ; + T6 = T8 * Vth ; + T5 = T1 * T2 + T6 ; + T7 = -2.0 * T6 * T9 ; + T11 = T7 * Vth/T12 ; + dDenomi_dVg = T2 * dT1_dVg + T7 ; + T13 = 2.0 * (T11 + T8) ; + dDenomi_dVd = T13 * dVth_dVd ; + dDenomi_dVb = T13 * dVth_dVb + T1 * pParam->BSIM4v7uc ; + } + + /*high K mobility*/ + else + { + /* univsersal mobility */ + T0 = (Vgsteff + BSIM4v7entry.d_BSIM4v7vtfbphi1Array [instance_ID]) * 1.0e-8 / toxe / 6.0 ; + T1 = exp (pParam->BSIM4v7eu * log (T0)) ; + dT1_dVg = T1 * pParam->BSIM4v7eu * 1.0e-8 / T0 / toxe / 6.0 ; + T2 = pParam->BSIM4v7ua + pParam->BSIM4v7uc * Vbseff ; + + /*Coulombic*/ + VgsteffVth = pParam->BSIM4v7VgsteffVth ; + T10 = exp (pParam->BSIM4v7ucs * log (0.5 + 0.5 * Vgsteff / VgsteffVth)) ; + T11 = pParam->BSIM4v7ud / T10; + dT11_dVg = -0.5 * pParam->BSIM4v7ucs * T11 / (0.5 + 0.5 * Vgsteff / VgsteffVth) / VgsteffVth ; + dDenomi_dVg = T2 * dT1_dVg + dT11_dVg ; + dDenomi_dVd = 0.0 ; + dDenomi_dVb = T1 * pParam->BSIM4v7uc ; + T5 = T1 * T2 + T11 ; + } + + /* 25 - DIVERGENT */ + if (T5 >= -0.8) + Denomi = 1.0 + T5 ; + else + { + T9 = 1.0 / (7.0 + 10.0 * T5) ; + Denomi = (0.6 + T5) * T9 ; + T9 *= T9 ; + dDenomi_dVg *= T9 ; + dDenomi_dVd *= T9 ; + dDenomi_dVb *= T9 ; + } + BSIM4v7entry.d_BSIM4v7ueffArray [instance_ID] = ueff = BSIM4v7entry.d_BSIM4v7u0tempArray [instance_ID] / 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 * BSIM4v7entry.d_BSIM4v7vsattempArray [instance_ID] * BSIM4v7coxe ; + WVCoxRds = WVCox * Rds ; + Esat = 2.0 * BSIM4v7entry.d_BSIM4v7vsattempArray [instance_ID] / ueff ; + BSIM4v7entry.d_BSIM4v7EsatLArray [instance_ID] = EsatL = Esat * Leff ; + T0 = -EsatL / ueff ; + dEsatL_dVg = T0 * dueff_dVg ; + dEsatL_dVd = T0 * dueff_dVd ; + dEsatL_dVb = T0 * dueff_dVb ; + + /* Sqrt() */ + /* 26 - DIVERGENT */ + a1 = pParam->BSIM4v7a1 ; + if (a1 == 0.0) + { + Lambda = pParam->BSIM4v7a2 ; + dLambda_dVg = 0.0 ; + } + else if (a1 > 0.0) + { + T0 = 1.0 - pParam->BSIM4v7a2 ; + T1 = T0 - pParam->BSIM4v7a1 * Vgsteff - 0.0001 ; + T2 = sqrt (T1 * T1 + 0.0004 * T0) ; + Lambda = pParam->BSIM4v7a2 + T0 - 0.5 * (T1 + T2) ; + dLambda_dVg = 0.5 * pParam->BSIM4v7a1 * (1.0 + T1 / T2) ; + } + else + { + T1 = pParam->BSIM4v7a2 + pParam->BSIM4v7a1 * Vgsteff - 0.0001 ; + T2 = sqrt (T1 * T1 + 0.0004 * pParam->BSIM4v7a2) ; + Lambda = 0.5 * (T1 + T2) ; + dLambda_dVg = 0.5 * pParam->BSIM4v7a1 * (1.0 + T1 / T2) ; + } + Vgst2Vtm = Vgsteff + 2.0 * Vtm ; + + /* 27 - DIVERGENT */ + 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 ; + } + + /* 28 - DIVERGENT */ + 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 ; + } + BSIM4v7entry.d_BSIM4v7vdsatRWArray [instance_ID] = Vdsat ; + + + /* Calculate Vdseff */ + T1 = Vdsat - Vds - pParam->BSIM4v7delta ; + dT1_dVg = dVdsat_dVg ; + dT1_dVd = dVdsat_dVd - 1.0 ; + dT1_dVb = dVdsat_dVb ; + T2 = sqrt (T1 * T1 + 4.0 * pParam->BSIM4v7delta * Vdsat) ; + T0 = T1 / T2 ; + T9 = 2.0 * pParam->BSIM4v7delta ; + T3 = T9 / 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 ; + + /* 29 - DIVERGENT */ + if (T1 >= 0.0) + { + 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) ; + } + else + { + T4 = T9 / (T2 - T1) ; + T5 = 1.0 - T4 ; + T6 = Vdsat * T4 / (T2 - T1) ; + Vdseff = Vdsat * T5 ; + dVdseff_dVg = dVdsat_dVg * T5 + T6 * (dT2_dVg - dT1_dVg) ; + dVdseff_dVd = dVdsat_dVd * T5 + T6 * (dT2_dVd - dT1_dVd) ; + dVdseff_dVb = dVdsat_dVb * T5 + T6 * (dT2_dVb - dT1_dVb) ; + } + + /* 30 - DIVERGENT */ + if (Vds == 0.0) + { + Vdseff = 0.0 ; + dVdseff_dVg = 0.0 ; + dVdseff_dVb = 0.0 ; + } + + /* 31 - DIVERGENT */ + if (Vdseff > Vds) + Vdseff = Vds ; + + diffVds = Vds - Vdseff ; + BSIM4v7entry.d_BSIM4v7VdseffArray [instance_ID] = Vdseff ; + + + /* Velocity Overshoot */ + /* 6 - non-divergent */ + if((BSIM4v7lambdaGiven) && (BSIM4v7lambda > 0.0)) + { + T1 = Leff * ueff ; + T2 = pParam->BSIM4v7lambda / T1 ; + T3 = -T2 / T1 * Leff ; + dT2_dVd = T3 * dueff_dVd ; + dT2_dVg = T3 * dueff_dVg ; + dT2_dVb = T3 * dueff_dVb ; + T5 = 1.0 / (Esat * pParam->BSIM4v7litl) ; + T4 = -T5 / EsatL ; + dT5_dVg = dEsatL_dVg * T4 ; + dT5_dVd = dEsatL_dVd * T4 ; + dT5_dVb = dEsatL_dVb * T4 ; + T6 = 1.0 + diffVds * T5 ; + dT6_dVg = dT5_dVg * diffVds - dVdseff_dVg * T5 ; + dT6_dVd = dT5_dVd * diffVds + (1.0 - dVdseff_dVd) * T5 ; + dT6_dVb = dT5_dVb * diffVds - dVdseff_dVb * T5 ; + T7 = 2.0 / (T6 * T6 + 1.0) ; + T8 = 1.0 - T7 ; + T9 = T6 * T7 * T7 ; + dT8_dVg = T9 * dT6_dVg ; + dT8_dVd = T9 * dT6_dVd ; + dT8_dVb = T9 * dT6_dVb ; + T10 = 1.0 + T2 * T8 ; + dT10_dVg = dT2_dVg * T8 + T2 * dT8_dVg ; + dT10_dVd = dT2_dVd * T8 + T2 * dT8_dVd ; + dT10_dVb = dT2_dVb * T8 + T2 * dT8_dVb ; + + if(T10 == 1.0) + dT10_dVg = dT10_dVd = dT10_dVb = 0.0 ; + + dEsatL_dVg *= T10 ; + dEsatL_dVg += EsatL * dT10_dVg ; + dEsatL_dVd *= T10 ; + dEsatL_dVd += EsatL * dT10_dVd ; + dEsatL_dVb *= T10 ; + dEsatL_dVb += EsatL * dT10_dVb ; + EsatL *= T10 ; + Esat = EsatL / Leff ; /* bugfix by Wenwei Yang (4.6.4) */ + BSIM4v7entry.d_BSIM4v7EsatLArray [instance_ID] = EsatL ; + } + + + /* 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 ; + + + /* Calculate Idl first */ + tmp1 = BSIM4v7entry.d_BSIM4v7vtfbphi2Array [instance_ID] ; + tmp2 = 2.0e8 * BSIM4v7toxp ; + dT0_dVg = 1.0 / tmp2 ; + T0 = (Vgsteff + tmp1) * dT0_dVg ; + tmp3 = exp (BSIM4v7bdos * 0.7 * log (T0)) ; + T1 = 1.0 + tmp3 ; + T2 = BSIM4v7bdos * 0.7 * tmp3 / T0 ; + Tcen = BSIM4v7ados * 1.9e-9 / T1 ; + dTcen_dVg = -Tcen * T2 * dT0_dVg / T1 ; + Coxeff = epssub * BSIM4v7coxp / (epssub + BSIM4v7coxp * Tcen) ; + BSIM4v7entry.d_BSIM4v7CoxeffArray [instance_ID] = Coxeff ; + dCoxeff_dVg = -Coxeff * Coxeff * dTcen_dVg / epssub ; + CoxeffWovL = Coxeff * Weff / Leff ; + beta = ueff * CoxeffWovL ; + T3 = ueff / Leff ; + dbeta_dVg = CoxeffWovL * dueff_dVg + T3 * (Weff * dCoxeff_dVg + Coxeff * dWeff_dVg) ; + dbeta_dVd = CoxeffWovL * dueff_dVd ; + dbeta_dVb = CoxeffWovL * dueff_dVb + T3 * Coxeff * dWeff_dVb ; + BSIM4v7entry.d_BSIM4v7AbovVgst2VtmArray [instance_ID] = Abulk / Vgst2Vtm ; + T0 = 1.0 - 0.5 * Vdseff * BSIM4v7entry.d_BSIM4v7AbovVgst2VtmArray [instance_ID] ; + 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 ; + Idl = gche / T0 ; + T1 = (1.0 - Idl * Rds) / T0 ; + T2 = Idl * Idl ; + dIdl_dVg = T1 * dgche_dVg - T2 * dRds_dVg ; + dIdl_dVd = T1 * dgche_dVd ; + dIdl_dVb = T1 * dgche_dVb - T2 * dRds_dVb ; + + + /* Calculate degradation factor due to pocket implant */ + /* 31 - DIVERGENT */ + if (pParam->BSIM4v7fprout <= 0.0) + { + FP = 1.0 ; + dFP_dVg = 0.0 ; + } + else + { + T9 = pParam->BSIM4v7fprout * sqrt (Leff) / Vgst2Vtm ; + FP = 1.0 / (1.0 + T9) ; + dFP_dVg = FP * FP * T9 / Vgst2Vtm ; + } + + + /* Calculate VACLM */ + T8 = pParam->BSIM4v7pvag / EsatL ; + T9 = T8 * Vgsteff ; + + /* 32 - DIVERGENT */ + if (T9 > -0.9) + { + PvagTerm = 1.0 + T9 ; + dPvagTerm_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL) ; + dPvagTerm_dVb = -T9 * dEsatL_dVb / EsatL ; + dPvagTerm_dVd = -T9 * dEsatL_dVd / EsatL ; + } + else + { + T4 = 1.0 / (17.0 + 20.0 * T9) ; + PvagTerm = (0.8 + T9) * T4 ; + T4 *= T4 ; + dPvagTerm_dVg = T8 * (1.0 - Vgsteff * dEsatL_dVg / EsatL) * T4 ; + T9 *= T4 / EsatL ; + dPvagTerm_dVb = -T9 * dEsatL_dVb ; + dPvagTerm_dVd = -T9 * dEsatL_dVd ; + } + + /* 33 - DIVERGENT */ + if ((pParam->BSIM4v7pclm > MIN_EXP) && (diffVds > 1.0e-10)) + { + T0 = 1.0 + Rds * Idl ; + dT0_dVg = dRds_dVg * Idl + Rds * dIdl_dVg ; + dT0_dVd = Rds * dIdl_dVd ; + dT0_dVb = dRds_dVb * Idl + Rds * dIdl_dVb ; + T2 = Vdsat / Esat ; + T1 = Leff + T2 ; + dT1_dVg = (dVdsat_dVg - T2 * dEsatL_dVg / Leff) / Esat ; + dT1_dVd = (dVdsat_dVd - T2 * dEsatL_dVd / Leff) / Esat ; + dT1_dVb = (dVdsat_dVb - T2 * dEsatL_dVb / Leff) / Esat ; + Cclm = FP * PvagTerm * T0 * T1 / (pParam->BSIM4v7pclm * pParam->BSIM4v7litl) ; + dCclm_dVg = Cclm * (dFP_dVg / FP + dPvagTerm_dVg / PvagTerm + dT0_dVg / T0 + dT1_dVg / T1) ; + dCclm_dVb = Cclm * (dPvagTerm_dVb / PvagTerm + dT0_dVb / T0 + dT1_dVb / T1) ; + dCclm_dVd = Cclm * (dPvagTerm_dVd / PvagTerm + dT0_dVd / T0 + dT1_dVd / T1) ; + VACLM = Cclm * diffVds ; + dVACLM_dVg = dCclm_dVg * diffVds - dVdseff_dVg * Cclm ; + dVACLM_dVb = dCclm_dVb * diffVds - dVdseff_dVb * Cclm ; + dVACLM_dVd = dCclm_dVd * diffVds + (1.0 - dVdseff_dVd) * Cclm ; + } + else + { + VACLM = Cclm = MAX_EXP ; + dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0 ; + dCclm_dVd = dCclm_dVg = dCclm_dVb = 0.0 ; + } + + + /* Calculate VADIBL */ + /* 34 - DIVERGENT */ + if (pParam->BSIM4v7thetaRout > MIN_EXP) + { + 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->BSIM4v7thetaRout ; + 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->BSIM4v7pdiblb * Vbseff ; + if (T7 >= -0.9) + { + T3 = 1.0 / (1.0 + T7) ; + VADIBL *= T3 ; + dVADIBL_dVg *= T3 ; + dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM4v7pdiblb) * T3 ; + dVADIBL_dVd *= T3 ; + } + else + { + T4 = 1.0 / (0.8 + T7) ; + T3 = (17.0 + 20.0 * T7) * T4 ; + dVADIBL_dVg *= T3 ; + dVADIBL_dVb = dVADIBL_dVb * T3 - VADIBL * pParam->BSIM4v7pdiblb * T4 * T4 ; + dVADIBL_dVd *= T3 ; + VADIBL *= T3 ; + } + dVADIBL_dVg = dVADIBL_dVg * PvagTerm + VADIBL * dPvagTerm_dVg ; + dVADIBL_dVb = dVADIBL_dVb * PvagTerm + VADIBL * dPvagTerm_dVb ; + dVADIBL_dVd = dVADIBL_dVd * PvagTerm + VADIBL * dPvagTerm_dVd ; + VADIBL *= PvagTerm ; + } + else + { + VADIBL = MAX_EXP ; + dVADIBL_dVd = dVADIBL_dVg = dVADIBL_dVb = 0.0 ; + } + + + /* Calculate Va */ + Va = Vasat + VACLM ; + dVa_dVg = dVasat_dVg + dVACLM_dVg ; + dVa_dVb = dVasat_dVb + dVACLM_dVb ; + dVa_dVd = dVasat_dVd + dVACLM_dVd ; + + + /* Calculate VADITS */ + T0 = pParam->BSIM4v7pditsd * Vds ; + + /* 35 - DIVERGENT */ + if (T0 > EXP_THRESHOLD) + { + T1 = MAX_EXP ; + dT1_dVd = 0 ; + } + else + { + T1 = exp (T0) ; + dT1_dVd = T1 * pParam->BSIM4v7pditsd ; + } + + /* 36 - DIVERGENT */ + if (pParam->BSIM4v7pdits > MIN_EXP) + { + T2 = 1.0 + BSIM4v7pditsl * Leff ; + VADITS = (1.0 + T2 * T1) / pParam->BSIM4v7pdits ; + dVADITS_dVg = VADITS * dFP_dVg ; + dVADITS_dVd = FP * T2 * dT1_dVd / pParam->BSIM4v7pdits ; + VADITS *= FP ; + } + else + { + VADITS = MAX_EXP ; + dVADITS_dVg = dVADITS_dVd = 0 ; + } + + + /* Calculate VASCBE */ + /* 37 - DIVERGENT */ + if ((pParam->BSIM4v7pscbe2 > 0.0) && (pParam->BSIM4v7pscbe1 >= 0.0)) /*4.6.2*/ + { + if (diffVds > pParam->BSIM4v7pscbe1 * pParam->BSIM4v7litl / EXP_THRESHOLD) + { + T0 = pParam->BSIM4v7pscbe1 * pParam->BSIM4v7litl / diffVds ; + VASCBE = Leff * exp (T0) / pParam->BSIM4v7pscbe2 ; + 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->BSIM4v7pscbe2 ; + dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0 ; + } + } + else + { + VASCBE = MAX_EXP ; + dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0 ; + } + + + /* Add DIBL to Ids */ + T9 = diffVds / VADIBL ; + T0 = 1.0 + T9 ; + Idsa = Idl * T0 ; + dIdsa_dVg = T0 * dIdl_dVg - Idl * (dVdseff_dVg + T9 * dVADIBL_dVg) / VADIBL ; + dIdsa_dVd = T0 * dIdl_dVd + Idl * (1.0 - dVdseff_dVd - T9 * dVADIBL_dVd) / VADIBL ; + dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVADIBL_dVb) / VADIBL ; + + + /* Add DITS to Ids */ + T9 = diffVds / VADITS ; + T0 = 1.0 + T9 ; + dIdsa_dVg = T0 * dIdsa_dVg - Idsa * (dVdseff_dVg + T9 * dVADITS_dVg) / VADITS ; + dIdsa_dVd = T0 * dIdsa_dVd + Idsa * (1.0 - dVdseff_dVd - T9 * dVADITS_dVd) / VADITS ; + dIdsa_dVb = T0 * dIdsa_dVb - Idsa * dVdseff_dVb / VADITS ; + Idsa *= T0 ; + + + /* Add CLM to Ids */ + T0 = log (Va / Vasat) ; + dT0_dVg = dVa_dVg / Va - dVasat_dVg / Vasat ; + dT0_dVb = dVa_dVb / Va - dVasat_dVb / Vasat ; + dT0_dVd = dVa_dVd / Va - dVasat_dVd / Vasat ; + T1 = T0 / Cclm ; + T9 = 1.0 + T1 ; + dT9_dVg = (dT0_dVg - T1 * dCclm_dVg) / Cclm ; + dT9_dVb = (dT0_dVb - T1 * dCclm_dVb) / Cclm ; + dT9_dVd = (dT0_dVd - T1 * dCclm_dVd) / Cclm ; + dIdsa_dVg = dIdsa_dVg * T9 + Idsa * dT9_dVg ; + dIdsa_dVb = dIdsa_dVb * T9 + Idsa * dT9_dVb ; + dIdsa_dVd = dIdsa_dVd * T9 + Idsa * dT9_dVd ; + Idsa *= T9 ; + + + /* Substrate current begins */ + tmp = pParam->BSIM4v7alpha0 + pParam->BSIM4v7alpha1 * Leff ; + + /* 38 - DIVERGENT */ + if ((tmp <= 0.0) || (pParam->BSIM4v7beta0 <= 0.0)) + Isub = Gbd = Gbb = Gbg = 0.0 ; + else + { + T2 = tmp / Leff ; + if (diffVds > pParam->BSIM4v7beta0 / EXP_THRESHOLD) + { + T0 = -pParam->BSIM4v7beta0 / 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 ; + } + T4 = Idsa * Vdseff ; + Isub = T1 * T4 ; + Gbg = T1 * (dIdsa_dVg * Vdseff + Idsa * dVdseff_dVg) + T4 * dT1_dVg ; + Gbd = T1 * (dIdsa_dVd * Vdseff + Idsa * dVdseff_dVd) + T4 * dT1_dVd ; + Gbb = T1 * (dIdsa_dVb * Vdseff + Idsa * dVdseff_dVb) + T4 * dT1_dVb ; + Gbd += Gbg * dVgsteff_dVd ; + Gbb += Gbg * dVgsteff_dVb ; + Gbg *= dVgsteff_dVg ; + Gbb *= dVbseff_dVb ; + } + BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] = Isub ; + BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] = Gbb ; + BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] = Gbg ; + BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] = Gbd ; + + + /* Add SCBE to Ids */ + 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 ; + tmp1 = Gds + Gm * dVgsteff_dVd ; + tmp2 = Gmb + Gm * dVgsteff_dVb ; + tmp3 = Gm ; + Gm = (Ids * dVdseff_dVg + Vdseff * tmp3) * dVgsteff_dVg ; + Gds = Ids * (dVdseff_dVd + dVdseff_dVg * dVgsteff_dVd) + Vdseff * tmp1 ; + Gmb = (Ids * (dVdseff_dVb + dVdseff_dVg * dVgsteff_dVb) + Vdseff * tmp2) * dVbseff_dVb ; + cdrain = Ids * Vdseff ; + + + /* Source End Velocity Limit */ + /* 7 - non-divergent */ + if ((BSIM4v7vtlGiven) && (BSIM4v7vtl > 0.0)) + { + T12 = 1.0 / Leff / CoxeffWovL ; + T11 = T12 / Vgsteff ; + T10 = -T11 / Vgsteff ; + vs = cdrain * T11 ; /* vs */ + dvs_dVg = Gm * T11 + cdrain * T10 * dVgsteff_dVg ; + dvs_dVd = Gds * T11 + cdrain * T10 * dVgsteff_dVd ; + dvs_dVb = Gmb * T11 + cdrain * T10 * dVgsteff_dVb ; + T0 = 2 * MM ; + T1 = vs / (pParam->BSIM4v7vtl * pParam->BSIM4v7tfactor) ; + + /* 39 - DIVERGENT */ + if (T1 > 0.0) + { + T2 = 1.0 + exp (T0 * log (T1)) ; + T3 = (T2 - 1.0) * T0 / vs ; + Fsevl = 1.0 / exp (log (T2)/ T0) ; + dT2_dVg = T3 * dvs_dVg ; + dT2_dVd = T3 * dvs_dVd ; + dT2_dVb = T3 * dvs_dVb ; + T4 = -1.0 / T0 * Fsevl / T2 ; + dFsevl_dVg = T4 * dT2_dVg ; + dFsevl_dVd = T4 * dT2_dVd ; + dFsevl_dVb = T4 * dT2_dVb ; + } else { + Fsevl = 1.0 ; + dFsevl_dVg = 0.0 ; + dFsevl_dVd = 0.0 ; + dFsevl_dVb = 0.0 ; + } + Gm *= Fsevl ; + Gm += cdrain * dFsevl_dVg ; + Gmb *= Fsevl ; + Gmb += cdrain * dFsevl_dVb ; + Gds *= Fsevl ; + Gds += cdrain * dFsevl_dVd ; + cdrain *= Fsevl ; + } + BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] = Gds ; + BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] = Gm ; + BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] = Gmb ; + BSIM4v7entry.d_BSIM4v7IdovVdsArray [instance_ID] = Ids ; + + if (BSIM4v7entry.d_BSIM4v7IdovVdsArray [instance_ID] <= 1.0e-9) + BSIM4v7entry.d_BSIM4v7IdovVdsArray [instance_ID] = 1.0e-9 ; + + + /* Calculate Rg */ + /* 40 - DIVERGENT */ + if ((BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] > 1) || (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID] != 0) || (BSIM4v7entry.d_BSIM4v7acnqsModArray [instance_ID] != 0)) + { + T9 = pParam->BSIM4v7xrcrg2 * BSIM4v7vtm ; + T0 = T9 * beta ; + dT0_dVd = (dbeta_dVd + dbeta_dVg * dVgsteff_dVd) * T9 ; + dT0_dVb = (dbeta_dVb + dbeta_dVg * dVgsteff_dVb) * T9 ; + dT0_dVg = dbeta_dVg * T9 ; + BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] = pParam->BSIM4v7xrcrg1 * ( T0 + Ids) ; + BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] = pParam->BSIM4v7xrcrg1 * (dT0_dVd + tmp1) ; + BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] = pParam->BSIM4v7xrcrg1 * (dT0_dVb + tmp2) * dVbseff_dVb ; + BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] = pParam->BSIM4v7xrcrg1 * (dT0_dVg + tmp3) * dVgsteff_dVg ; + if (BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] != 1.0) + { + BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + } + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2) + { + T10 = BSIM4v7entry.d_BSIM4v7grgeltdArray [instance_ID] * BSIM4v7entry.d_BSIM4v7grgeltdArray [instance_ID] ; + T11 = BSIM4v7entry.d_BSIM4v7grgeltdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7grgeltdArray [instance_ID] * BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] / T11 ; + T12 = T10 / T11 / T11 ; + BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] *= T12 ; + BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] *= T12 ; + BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] *= T12 ; + } + BSIM4v7entry.d_BSIM4v7gcrgsArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID]) ; + } + + + /* Calculate bias-dependent external S/D resistance */ + /* 8 - non-divergent */ + if (BSIM4v7rdsMod) + { + /* Rs(V) */ + T0 = vgs - pParam->BSIM4v7vfbsd ; + T1 = sqrt (T0 * T0 + 1.0e-4) ; + vgs_eff = 0.5 * (T0 + T1) ; + dvgs_eff_dvg = vgs_eff / T1 ; + T0 = 1.0 + pParam->BSIM4v7prwg * vgs_eff ; + dT0_dvg = -pParam->BSIM4v7prwg / T0 / T0 * dvgs_eff_dvg ; + T1 = -pParam->BSIM4v7prwb * vbs ; + dT1_dvb = -pParam->BSIM4v7prwb ; + T2 = 1.0 / T0 + T1 ; + T3 = T2 + sqrt (T2 * T2 + 0.01) ; + dT3_dvg = T3 / (T3 - T2) ; + dT3_dvb = dT3_dvg * dT1_dvb ; + dT3_dvg *= dT0_dvg ; + T4 = pParam->BSIM4v7rs0 * 0.5 ; + Rs = pParam->BSIM4v7rswmin + T3 * T4 ; + dRs_dvg = T4 * dT3_dvg ; + dRs_dvb = T4 * dT3_dvb ; + T0 = 1.0 + BSIM4v7entry.d_BSIM4v7sourceConductanceArray [instance_ID] * Rs ; + BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] = BSIM4v7entry.d_BSIM4v7sourceConductanceArray [instance_ID] / T0 ; + T0 = -BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] * BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] ; + dgstot_dvd = 0.0 ; /* place holder */ + dgstot_dvg = T0 * dRs_dvg ; + dgstot_dvb = T0 * dRs_dvb ; + dgstot_dvs = -(dgstot_dvg + dgstot_dvb + dgstot_dvd) ; + + /* Rd(V) */ + T0 = vgd - pParam->BSIM4v7vfbsd ; + T1 = sqrt (T0 * T0 + 1.0e-4) ; + vgd_eff = 0.5 * (T0 + T1) ; + dvgd_eff_dvg = vgd_eff / T1 ; + T0 = 1.0 + pParam->BSIM4v7prwg * vgd_eff ; + dT0_dvg = -pParam->BSIM4v7prwg / T0 / T0 * dvgd_eff_dvg ; + T1 = -pParam->BSIM4v7prwb * vbd ; + dT1_dvb = -pParam->BSIM4v7prwb ; + T2 = 1.0 / T0 + T1 ; + T3 = T2 + sqrt (T2 * T2 + 0.01) ; + dT3_dvg = T3 / (T3 - T2) ; + dT3_dvb = dT3_dvg * dT1_dvb ; + dT3_dvg *= dT0_dvg ; + T4 = pParam->BSIM4v7rd0 * 0.5 ; + Rd = pParam->BSIM4v7rdwmin + T3 * T4 ; + dRd_dvg = T4 * dT3_dvg ; + dRd_dvb = T4 * dT3_dvb ; + T0 = 1.0 + BSIM4v7entry.d_BSIM4v7drainConductanceArray [instance_ID] * Rd ; + BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] = BSIM4v7entry.d_BSIM4v7drainConductanceArray [instance_ID] / T0 ; + T0 = -BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] * BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] ; + dgdtot_dvs = 0.0 ; + dgdtot_dvg = T0 * dRd_dvg ; + dgdtot_dvb = T0 * dRd_dvb ; + dgdtot_dvd = -(dgdtot_dvg + dgdtot_dvb + dgdtot_dvs) ; + BSIM4v7entry.d_BSIM4v7gstotdArray [instance_ID] = vses * dgstot_dvd ; + BSIM4v7entry.d_BSIM4v7gstotgArray [instance_ID] = vses * dgstot_dvg ; + BSIM4v7entry.d_BSIM4v7gstotsArray [instance_ID] = vses * dgstot_dvs ; + BSIM4v7entry.d_BSIM4v7gstotbArray [instance_ID] = vses * dgstot_dvb ; + T2 = vdes - vds ; + BSIM4v7entry.d_BSIM4v7gdtotdArray [instance_ID] = T2 * dgdtot_dvd ; + BSIM4v7entry.d_BSIM4v7gdtotgArray [instance_ID] = T2 * dgdtot_dvg ; + BSIM4v7entry.d_BSIM4v7gdtotsArray [instance_ID] = T2 * dgdtot_dvs ; + BSIM4v7entry.d_BSIM4v7gdtotbArray [instance_ID] = T2 * dgdtot_dvb ; + } + else /* WDLiu: for bypass */ + { + BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gstotdArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gstotgArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7gstotsArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gstotbArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gdtotdArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gdtotgArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7gdtotsArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gdtotbArray [instance_ID] = 0.0 ; + } + + + /* GIDL/GISL Models */ + /* 9 - non-divergent */ + if (BSIM4v7mtrlMod == 0) + T0 = 3.0 * toxe ; + else + T0 = BSIM4v7epsrsub * toxe / epsrox ; + + + /* Calculate GIDL current */ + vgs_eff = BSIM4v7entry.d_BSIM4v7vgs_effArray [instance_ID] ; + dvgs_eff_dvg = BSIM4v7entry.d_BSIM4v7dvgs_eff_dvgArray [instance_ID] ; + vgd_eff = BSIM4v7entry.d_BSIM4v7vgd_effArray [instance_ID] ; + dvgd_eff_dvg = BSIM4v7entry.d_BSIM4v7dvgd_eff_dvgArray [instance_ID] ; + + /* 10 - non-divergent */ + if (BSIM4v7gidlMod == 0) + { + /* 11 - non-divergent */ + if (BSIM4v7mtrlMod == 0) + T1 = (vds - vgs_eff - pParam->BSIM4v7egidl ) / T0 ; + else + T1 = (vds - vgs_eff - pParam->BSIM4v7egidl + pParam->BSIM4v7vfbsd) / T0 ; + + /* 41 - DIVERGENT */ + if ((pParam->BSIM4v7agidl <= 0.0) || (pParam->BSIM4v7bgidl <= 0.0) || + (T1 <= 0.0) || (pParam->BSIM4v7cgidl <= 0.0) || (vbd > 0.0)) + { + Igidl = Ggidld = Ggidlg = Ggidlb = 0.0 ; + } else { + dT1_dVd = 1.0 / T0 ; + dT1_dVg = -dvgs_eff_dvg * dT1_dVd ; + T2 = pParam->BSIM4v7bgidl / T1 ; + if (T2 < 100.0) + { + Igidl = pParam->BSIM4v7agidl * pParam->BSIM4v7weffCJ * T1 * exp (-T2) ; + T3 = Igidl * (1.0 + T2) / T1 ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } else { + Igidl = pParam->BSIM4v7agidl * pParam->BSIM4v7weffCJ * 3.720075976e-44 ; + Ggidld = Igidl * dT1_dVd ; + Ggidlg = Igidl * dT1_dVg ; + Igidl *= T1 ; + } + T4 = vbd * vbd ; + T5 = -vbd * T4 ; + T6 = pParam->BSIM4v7cgidl + T5 ; + T7 = T5 / T6 ; + T8 = 3.0 * pParam->BSIM4v7cgidl * T4 / T6 / T6 ; + Ggidld = Ggidld * T7 + Igidl * T8 ; + Ggidlg = Ggidlg * T7 ; + Ggidlb = -Igidl * T8 ; + Igidl *= T7 ; + } + BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] = Igidl ; + BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] = Ggidld ; + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] = Ggidlg ; + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] = Ggidlb ; + + + /* Calculate GISL current */ + /* 12 - non-divergent */ + if (BSIM4v7mtrlMod ==0) + T1 = (-vds - vgd_eff - pParam->BSIM4v7egisl ) / T0 ; + else + T1 = (-vds - vgd_eff - pParam->BSIM4v7egisl + pParam->BSIM4v7vfbsd ) / T0 ; + + /* 42 - DIVERGENT */ + if ((pParam->BSIM4v7agisl <= 0.0) || (pParam->BSIM4v7bgisl <= 0.0) || + (T1 <= 0.0) || (pParam->BSIM4v7cgisl <= 0.0) || (vbs > 0.0)) + { + Igisl = Ggisls = Ggislg = Ggislb = 0.0 ; + } else { + dT1_dVd = 1.0 / T0 ; + dT1_dVg = -dvgd_eff_dvg * dT1_dVd ; + T2 = pParam->BSIM4v7bgisl / T1 ; + if (T2 < 100.0) + { + Igisl = pParam->BSIM4v7agisl * pParam->BSIM4v7weffCJ * T1 * exp (-T2) ; + T3 = Igisl * (1.0 + T2) / T1 ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } else { + Igisl = pParam->BSIM4v7agisl * pParam->BSIM4v7weffCJ * 3.720075976e-44 ; + Ggisls = Igisl * dT1_dVd ; + Ggislg = Igisl * dT1_dVg ; + Igisl *= T1 ; + } + T4 = vbs * vbs ; + T5 = -vbs * T4 ; + T6 = pParam->BSIM4v7cgisl + T5 ; + T7 = T5 / T6 ; + T8 = 3.0 * pParam->BSIM4v7cgisl * T4 / T6 / T6 ; + Ggisls = Ggisls * T7 + Igisl * T8 ; + Ggislg = Ggislg * T7 ; + Ggislb = -Igisl * T8 ; + Igisl *= T7 ; + } + BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] = Igisl ; + BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] = Ggisls ; + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] = Ggislg ; + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] = Ggislb ; + } else{ /* v4.7 New Gidl/GISL model */ + /* GISL */ + /* 13 - non-divergent */ + if (BSIM4v7mtrlMod==0) + T1 = (-vds - pParam->BSIM4v7rgisl * vgd_eff - pParam->BSIM4v7egisl) / T0 ; + else + T1 = (-vds - pParam->BSIM4v7rgisl * vgd_eff - pParam->BSIM4v7egisl + pParam->BSIM4v7vfbsd) / T0 ; + + /* 43 - DIVERGENT */ + if ((pParam->BSIM4v7agisl <= 0.0) || (pParam->BSIM4v7bgisl <= 0.0) || (T1 <= 0.0) || + (pParam->BSIM4v7cgisl < 0.0)) + { + Igisl = Ggisls = Ggislg = Ggislb = 0.0 ; + } else { + dT1_dVd = 1 / T0 ; + dT1_dVg = - pParam->BSIM4v7rgisl * dT1_dVd * dvgd_eff_dvg ; + T2 = pParam->BSIM4v7bgisl / T1 ; + if (T2 < EXPL_THRESHOLD) + { + Igisl = pParam->BSIM4v7weffCJ * pParam->BSIM4v7agisl * T1 * exp (-T2) ; + T3 = Igisl / T1 * (T2 + 1) ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } else { + T3 = pParam->BSIM4v7weffCJ * pParam->BSIM4v7agisl * MIN_EXPL ; + Igisl = T3 * T1 ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } + T4 = vbs - pParam->BSIM4v7fgisl ; + + if (T4 == 0) + T5 = EXPL_THRESHOLD ; + else + T5 = pParam->BSIM4v7kgisl / T4 ; + + if (T5 < EXPL_THRESHOLD) + { + T6 = exp (T5) ; + Ggislb = -Igisl * T6 * T5 / T4 ; + } else { + T6 = MAX_EXPL ; + Ggislb = 0.0 ; + } + Ggisls *= T6 ; + Ggislg *= T6 ; + Igisl *= T6 ; + } + BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] = Igisl ; + BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] = Ggisls ; + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] = Ggislg ; + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] = Ggislb ; + /* End of GISL */ + + /* GIDL */ + /* 14 - non-divergent */ + if (BSIM4v7mtrlMod == 0) + T1 = (vds - pParam->BSIM4v7rgidl * vgs_eff - pParam->BSIM4v7egidl) / T0 ; + else + T1 = (vds - pParam->BSIM4v7rgidl * vgs_eff - pParam->BSIM4v7egidl + pParam->BSIM4v7vfbsd) / T0 ; + + /* 44 - DIVERGENT */ + if ((pParam->BSIM4v7agidl <= 0.0) || (pParam->BSIM4v7bgidl <= 0.0) || (T1 <= 0.0) || + (pParam->BSIM4v7cgidl < 0.0)) + { + Igidl = Ggidld = Ggidlg = Ggidlb = 0.0 ; + } else { + dT1_dVd = 1 / T0 ; + dT1_dVg = - pParam->BSIM4v7rgidl * dT1_dVd * dvgs_eff_dvg ; + T2 = pParam->BSIM4v7bgidl / T1 ; + if (T2 < EXPL_THRESHOLD) + { + Igidl = pParam->BSIM4v7weffCJ * pParam->BSIM4v7agidl * T1 * exp (-T2) ; + T3 = Igidl / T1 * (T2 + 1) ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } else { + T3 = pParam->BSIM4v7weffCJ * pParam->BSIM4v7agidl * MIN_EXPL ; + Igidl = T3 * T1 ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } + T4 = vbd - pParam->BSIM4v7fgidl ; + + if (T4 == 0) + T5 = EXPL_THRESHOLD ; + else + T5 = pParam->BSIM4v7kgidl / T4 ; + + if (T5BSIM4v7k1ox ; + T3 = Vgs_eff - Vfbeff - Vbseff - Vgsteff ; + + /* 45 - DIVERGENT */ + if (pParam->BSIM4v7k1ox == 0.0) + Voxdepinv = dVoxdepinv_dVg = dVoxdepinv_dVd = dVoxdepinv_dVb = 0.0 ; + else if (T3 < 0.0) + { + Voxdepinv = -T3 ; + dVoxdepinv_dVg = -dVgs_eff_dVg + dVfbeff_dVg + dVgsteff_dVg ; + dVoxdepinv_dVd = dVgsteff_dVd ; + dVoxdepinv_dVb = dVfbeff_dVb + 1.0 + dVgsteff_dVb ; + } + else + { + T1 = sqrt (T0 * T0 + T3) ; + T2 = T0 / T1 ; + Voxdepinv = pParam->BSIM4v7k1ox * (T1 - T0) ; + dVoxdepinv_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg) ; + dVoxdepinv_dVd = -T2 * dVgsteff_dVd ; + dVoxdepinv_dVb = -T2 * (dVfbeff_dVb + 1.0 + dVgsteff_dVb) ; + } + Voxdepinv += Vgsteff ; + dVoxdepinv_dVg += dVgsteff_dVg ; + dVoxdepinv_dVd += dVgsteff_dVd ; + dVoxdepinv_dVb += dVgsteff_dVb ; + } + + /* 16 - non-divergent */ + if (BSIM4v7tempMod < 2) + tmp = Vtm ; + else /* BSIM4v7tempMod = 2 , 3*/ + tmp = Vtm0 ; + + /* 17 - non-divergent */ + if (BSIM4v7igcMod) + { + T0 = tmp * pParam->BSIM4v7nigc ; + if (BSIM4v7igcMod == 1) + { + VxNVt = (Vgs_eff - BSIM4v7type * BSIM4v7entry.d_BSIM4v7vth0Array [instance_ID]) / T0 ; + + /* 46 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = Vgs_eff - BSIM4v7type * BSIM4v7entry.d_BSIM4v7vth0Array [instance_ID] ; + dVaux_dVg = dVgs_eff_dVg ; + dVaux_dVd = 0.0 ; + dVaux_dVb = 0.0 ; + } + } + else if (BSIM4v7igcMod == 2) + { + VxNVt = (Vgs_eff - BSIM4v7entry.d_BSIM4v7vonRWArray [instance_ID]) / T0 ; + + /* 47 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = Vgs_eff - BSIM4v7entry.d_BSIM4v7vonRWArray [instance_ID] ; + dVaux_dVg = dVgs_eff_dVg ; + dVaux_dVd = -dVth_dVd ; + dVaux_dVb = -dVth_dVb ; + } + } + + /* 48 - DIVERGENT */ + if (VxNVt < -EXP_THRESHOLD) + { + Vaux = T0 * log (1.0 + MIN_EXP) ; + dVaux_dVg = dVaux_dVd = dVaux_dVb = 0.0 ; + } + else if ((VxNVt >= -EXP_THRESHOLD) && (VxNVt <= EXP_THRESHOLD)) + { + ExpVxNVt = exp (VxNVt) ; + Vaux = T0 * log (1.0 + ExpVxNVt) ; + dVaux_dVg = ExpVxNVt / (1.0 + ExpVxNVt) ; + if (BSIM4v7igcMod == 1) + { + dVaux_dVd = 0.0 ; + dVaux_dVb = 0.0 ; + } else if (BSIM4v7igcMod == 2) + { + dVaux_dVd = -dVgs_eff_dVg * dVth_dVd ; + dVaux_dVb = -dVgs_eff_dVg * dVth_dVb ; + } + dVaux_dVg *= dVgs_eff_dVg ; + } + T2 = Vgs_eff * Vaux ; + dT2_dVg = dVgs_eff_dVg * Vaux + Vgs_eff * dVaux_dVg ; + dT2_dVd = Vgs_eff * dVaux_dVd ; + dT2_dVb = Vgs_eff * dVaux_dVb ; + T11 = pParam->BSIM4v7Aechvb ; + T12 = pParam->BSIM4v7Bechvb ; + T3 = pParam->BSIM4v7aigc * pParam->BSIM4v7cigc - pParam->BSIM4v7bigc ; + T4 = pParam->BSIM4v7bigc * pParam->BSIM4v7cigc ; + T5 = T12 * (pParam->BSIM4v7aigc + T3 * Voxdepinv - T4 * Voxdepinv * Voxdepinv) ; + + /* 49 - DIVERGENT */ + if (T5 > EXP_THRESHOLD) + { + T6 = MAX_EXP ; + dT6_dVg = dT6_dVd = dT6_dVb = 0.0 ; + } + else if (T5 < -EXP_THRESHOLD) + { T6 = MIN_EXP ; + dT6_dVg = dT6_dVd = dT6_dVb = 0.0 ; + } + else + { + T6 = exp (T5) ; + dT6_dVg = T6 * T12 * (T3 - 2.0 * T4 * Voxdepinv) ; + dT6_dVd = dT6_dVg * dVoxdepinv_dVd ; + dT6_dVb = dT6_dVg * dVoxdepinv_dVb ; + dT6_dVg *= dVoxdepinv_dVg ; + } + Igc = T11 * T2 * T6 ; + dIgc_dVg = T11 * (T2 * dT6_dVg + T6 * dT2_dVg) ; + dIgc_dVd = T11 * (T2 * dT6_dVd + T6 * dT2_dVd) ; + dIgc_dVb = T11 * (T2 * dT6_dVb + T6 * dT2_dVb) ; + + if (BSIM4v7pigcdGiven) + { + Pigcd = pParam->BSIM4v7pigcd ; + dPigcd_dVg = dPigcd_dVd = dPigcd_dVb = 0.0 ; + } else { + /* T11 = pParam->BSIM4v7Bechvb * toxe; v4.7 */ + T11 = -pParam->BSIM4v7Bechvb ; + T12 = Vgsteff + 1.0e-20 ; + T13 = T11 / T12 / T12 ; + T14 = -T13 / T12 ; + Pigcd = T13 * (1.0 - 0.5 * Vdseff / T12) ; + dPigcd_dVg = T14 * (2.0 + 0.5 * (dVdseff_dVg - 3.0 * Vdseff / T12)) ; + dPigcd_dVd = 0.5 * T14 * dVdseff_dVd ; + dPigcd_dVb = 0.5 * T14 * dVdseff_dVb ; + } + + /* bugfix */ + T7 = -Pigcd * Vdseff ; + /* ------ */ + + dT7_dVg = -Vdseff * dPigcd_dVg - Pigcd * dVdseff_dVg ; + dT7_dVd = -Vdseff * dPigcd_dVd - Pigcd * dVdseff_dVd + dT7_dVg * dVgsteff_dVd ; + dT7_dVb = -Vdseff * dPigcd_dVb - Pigcd * dVdseff_dVb + dT7_dVg * dVgsteff_dVb ; + dT7_dVg *= dVgsteff_dVg ; + dT7_dVb *= dVbseff_dVb ; + T8 = T7 * T7 + 2.0e-4 ; + dT8_dVg = 2.0 * T7 ; + dT8_dVd = dT8_dVg * dT7_dVd ; + dT8_dVb = dT8_dVg * dT7_dVb ; + dT8_dVg *= dT7_dVg ; + + /* 50 - DIVERGENT */ + if (T7 > EXP_THRESHOLD) + { + T9 = MAX_EXP ; + dT9_dVg = dT9_dVd = dT9_dVb = 0.0 ; + } + else if (T7 < -EXP_THRESHOLD) + { + T9 = MIN_EXP ; + dT9_dVg = dT9_dVd = dT9_dVb = 0.0 ; + } + else + { + T9 = exp (T7) ; + dT9_dVg = T9 * dT7_dVg ; + dT9_dVd = T9 * dT7_dVd ; + dT9_dVb = T9 * dT7_dVb ; + } + T0 = T8 * T8 ; + T1 = T9 - 1.0 + 1.0e-4 ; + T10 = (T1 - T7) / T8 ; + dT10_dVg = (dT9_dVg - dT7_dVg - T10 * dT8_dVg) / T8 ; + dT10_dVd = (dT9_dVd - dT7_dVd - T10 * dT8_dVd) / T8 ; + dT10_dVb = (dT9_dVb - dT7_dVb - T10 * dT8_dVb) / T8 ; + Igcs = Igc * T10 ; + dIgcs_dVg = dIgc_dVg * T10 + Igc * dT10_dVg ; + dIgcs_dVd = dIgc_dVd * T10 + Igc * dT10_dVd ; + dIgcs_dVb = dIgc_dVb * T10 + Igc * dT10_dVb ; + T1 = T9 - 1.0 - 1.0e-4 ; + T10 = (T7 * T9 - T1) / T8 ; + dT10_dVg = (dT7_dVg * T9 + (T7 - 1.0) * dT9_dVg - T10 * dT8_dVg) / T8 ; + dT10_dVd = (dT7_dVd * T9 + (T7 - 1.0) * dT9_dVd - T10 * dT8_dVd) / T8 ; + dT10_dVb = (dT7_dVb * T9 + (T7 - 1.0) * dT9_dVb - T10 * dT8_dVb) / T8 ; + Igcd = Igc * T10 ; + dIgcd_dVg = dIgc_dVg * T10 + Igc * dT10_dVg ; + dIgcd_dVd = dIgc_dVd * T10 + Igc * dT10_dVd ; + dIgcd_dVb = dIgc_dVb * T10 + Igc * dT10_dVb ; + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] = Igcs ; + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] = dIgcs_dVg ; + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] = dIgcs_dVd ; + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] = dIgcs_dVb * dVbseff_dVb ; + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] = Igcd ; + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] = dIgcd_dVg ; + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] = dIgcd_dVd ; + BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] = dIgcd_dVb * dVbseff_dVb ; + T0 = vgs - (pParam->BSIM4v7vfbsd + pParam->BSIM4v7vfbsdoff) ; + vgs_eff = sqrt (T0 * T0 + 1.0e-4) ; + dvgs_eff_dvg = T0 / vgs_eff ; + T2 = vgs * vgs_eff ; + dT2_dVg = vgs * dvgs_eff_dvg + vgs_eff ; + T11 = pParam->BSIM4v7AechvbEdgeS ; + T12 = pParam->BSIM4v7BechvbEdge ; + T3 = pParam->BSIM4v7aigs * pParam->BSIM4v7cigs - pParam->BSIM4v7bigs ; + T4 = pParam->BSIM4v7bigs * pParam->BSIM4v7cigs ; + T5 = T12 * (pParam->BSIM4v7aigs + T3 * vgs_eff - T4 * vgs_eff * vgs_eff) ; + + /* 51 - DIVERGENT */ + if (T5 > EXP_THRESHOLD) + { + T6 = MAX_EXP ; + dT6_dVg = 0.0 ; + } + else if (T5 < -EXP_THRESHOLD) + { + T6 = MIN_EXP ; + dT6_dVg = 0.0 ; + } else { + T6 = exp (T5) ; + dT6_dVg = T6 * T12 * (T3 - 2.0 * T4 * vgs_eff) * dvgs_eff_dvg ; + } + Igs = T11 * T2 * T6 ; + dIgs_dVg = T11 * (T2 * dT6_dVg + T6 * dT2_dVg) ; + dIgs_dVs = -dIgs_dVg ; + T0 = vgd - (pParam->BSIM4v7vfbsd + pParam->BSIM4v7vfbsdoff) ; + vgd_eff = sqrt (T0 * T0 + 1.0e-4) ; + dvgd_eff_dvg = T0 / vgd_eff ; + T2 = vgd * vgd_eff ; + dT2_dVg = vgd * dvgd_eff_dvg + vgd_eff ; + T11 = pParam->BSIM4v7AechvbEdgeD ; + T3 = pParam->BSIM4v7aigd * pParam->BSIM4v7cigd - pParam->BSIM4v7bigd ; + T4 = pParam->BSIM4v7bigd * pParam->BSIM4v7cigd ; + T5 = T12 * (pParam->BSIM4v7aigd + T3 * vgd_eff - T4 * vgd_eff * vgd_eff) ; + + /* 52 - DIVERGENT */ + if (T5 > EXP_THRESHOLD) + { + T6 = MAX_EXP ; + dT6_dVg = 0.0 ; + } + else if (T5 < -EXP_THRESHOLD) + { + T6 = MIN_EXP ; + dT6_dVg = 0.0 ; + } else { + T6 = exp (T5) ; + dT6_dVg = T6 * T12 * (T3 - 2.0 * T4 * vgd_eff) * dvgd_eff_dvg ; + } + Igd = T11 * T2 * T6 ; + dIgd_dVg = T11 * (T2 * dT6_dVg + T6 * dT2_dVg) ; + dIgd_dVd = -dIgd_dVg ; + BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] = Igs ; + BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] = dIgs_dVg ; + BSIM4v7entry.d_BSIM4v7gIgssArray [instance_ID] = dIgs_dVs ; + BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] = Igd ; + BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] = dIgd_dVg ; + BSIM4v7entry.d_BSIM4v7gIgddArray [instance_ID] = dIgd_dVd ; + } else { + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgssArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgddArray [instance_ID] = 0.0 ; + } + + /* 18 - non-divergent */ + if (BSIM4v7igbMod) + { + T0 = tmp * pParam->BSIM4v7nigbacc ; + T1 = -Vgs_eff + Vbseff + Vfb ; + VxNVt = T1 / T0 ; + + /* 53 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = T1 ; + dVaux_dVg = -dVgs_eff_dVg ; + dVaux_dVb = 1.0 ; + } + else if (VxNVt < -EXP_THRESHOLD) + { + Vaux = T0 * log (1.0 + MIN_EXP) ; + dVaux_dVg = dVaux_dVb = 0.0 ; + } else { + ExpVxNVt = exp (VxNVt) ; + Vaux = T0 * log (1.0 + ExpVxNVt) ; + dVaux_dVb = ExpVxNVt / (1.0 + ExpVxNVt) ; + dVaux_dVg = -dVaux_dVb * dVgs_eff_dVg ; + } + T2 = (Vgs_eff - Vbseff) * Vaux ; + dT2_dVg = dVgs_eff_dVg * Vaux + (Vgs_eff - Vbseff) * dVaux_dVg ; + dT2_dVb = -Vaux + (Vgs_eff - Vbseff) * dVaux_dVb ; + T11 = 4.97232e-7 * pParam->BSIM4v7weff * pParam->BSIM4v7leff * pParam->BSIM4v7ToxRatio ; + T12 = -7.45669e11 * toxe ; + T3 = pParam->BSIM4v7aigbacc * pParam->BSIM4v7cigbacc - pParam->BSIM4v7bigbacc ; + T4 = pParam->BSIM4v7bigbacc * pParam->BSIM4v7cigbacc ; + T5 = T12 * (pParam->BSIM4v7aigbacc + T3 * Voxacc - T4 * Voxacc * Voxacc) ; + + /* 54 - DIVERGENT */ + if (T5 > EXP_THRESHOLD) + { + T6 = MAX_EXP ; + dT6_dVg = dT6_dVb = 0.0 ; + } + else if (T5 < -EXP_THRESHOLD) + { + T6 = MIN_EXP ; + dT6_dVg = dT6_dVb = 0.0 ; + } else { + T6 = exp (T5) ; + dT6_dVg = T6 * T12 * (T3 - 2.0 * T4 * Voxacc) ; + dT6_dVb = dT6_dVg * dVoxacc_dVb ; + dT6_dVg *= dVoxacc_dVg ; + } + Igbacc = T11 * T2 * T6 ; + dIgbacc_dVg = T11 * (T2 * dT6_dVg + T6 * dT2_dVg) ; + dIgbacc_dVb = T11 * (T2 * dT6_dVb + T6 * dT2_dVb) ; + T0 = tmp * pParam->BSIM4v7nigbinv ; + T1 = Voxdepinv - pParam->BSIM4v7eigbinv ; + VxNVt = T1 / T0 ; + + /* 55 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = T1 ; + dVaux_dVg = dVoxdepinv_dVg ; + dVaux_dVd = dVoxdepinv_dVd ; + dVaux_dVb = dVoxdepinv_dVb ; + } + else if (VxNVt < -EXP_THRESHOLD) + { + Vaux = T0 * log (1.0 + MIN_EXP) ; + dVaux_dVg = dVaux_dVd = dVaux_dVb = 0.0 ; + } else { + ExpVxNVt = exp (VxNVt) ; + Vaux = T0 * log (1.0 + ExpVxNVt) ; + dVaux_dVg = ExpVxNVt / (1.0 + ExpVxNVt) ; + dVaux_dVd = dVaux_dVg * dVoxdepinv_dVd ; + dVaux_dVb = dVaux_dVg * dVoxdepinv_dVb ; + dVaux_dVg *= dVoxdepinv_dVg ; + } + T2 = (Vgs_eff - Vbseff) * Vaux ; + dT2_dVg = dVgs_eff_dVg * Vaux + (Vgs_eff - Vbseff) * dVaux_dVg ; + dT2_dVd = (Vgs_eff - Vbseff) * dVaux_dVd ; + dT2_dVb = -Vaux + (Vgs_eff - Vbseff) * dVaux_dVb ; + T11 *= 0.75610 ; + T12 *= 1.31724 ; + T3 = pParam->BSIM4v7aigbinv * pParam->BSIM4v7cigbinv - pParam->BSIM4v7bigbinv ; + T4 = pParam->BSIM4v7bigbinv * pParam->BSIM4v7cigbinv ; + T5 = T12 * (pParam->BSIM4v7aigbinv + T3 * Voxdepinv - T4 * Voxdepinv * Voxdepinv) ; + + /* 56 - DIVERGENT */ + if (T5 > EXP_THRESHOLD) + { + T6 = MAX_EXP ; + dT6_dVg = dT6_dVd = dT6_dVb = 0.0 ; + } + else if (T5 < -EXP_THRESHOLD) + { + T6 = MIN_EXP ; + dT6_dVg = dT6_dVd = dT6_dVb = 0.0 ; + } else { + T6 = exp (T5) ; + dT6_dVg = T6 * T12 * (T3 - 2.0 * T4 * Voxdepinv) ; + dT6_dVd = dT6_dVg * dVoxdepinv_dVd ; + dT6_dVb = dT6_dVg * dVoxdepinv_dVb ; + dT6_dVg *= dVoxdepinv_dVg ; + } + Igbinv = T11 * T2 * T6 ; + dIgbinv_dVg = T11 * (T2 * dT6_dVg + T6 * dT2_dVg) ; + dIgbinv_dVd = T11 * (T2 * dT6_dVd + T6 * dT2_dVd) ; + dIgbinv_dVb = T11 * (T2 * dT6_dVb + T6 * dT2_dVb) ; + BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] = Igbinv + Igbacc ; + BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] = dIgbinv_dVg + dIgbacc_dVg ; + BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] = dIgbinv_dVd ; + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] = (dIgbinv_dVb + dIgbacc_dVb) * dVbseff_dVb ; + } else { + BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgbsArray [instance_ID] = BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] = 0.0 ; + } + /* End of Gate current */ + + /* 57 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] != 1.0) + { + cdrain *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IdovVdsArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgssArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgddArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + } + BSIM4v7entry.d_BSIM4v7ggidlsArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7ggisldArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7gIgbsArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7gIgcssArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7gIgcdsArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] = cdrain ; + + + /* Calculations for noise analysis */ + /* 19 - non-divergent */ + if (BSIM4v7tnoiMod == 0) + { + Abulk = Abulk0 * pParam->BSIM4v7abulkCVfactor ; + Vdsat = Vgsteff / Abulk ; + T0 = Vdsat - Vds - DELTA_4 ; + T1 = sqrt (T0 * T0 + 4.0 * DELTA_4 * Vdsat) ; + + /* 58 - DIVERGENT */ + if (T0 >= 0.0) + Vdseff = Vdsat - 0.5 * (T0 + T1) ; + else + { + T3 = (DELTA_4 + DELTA_4) / (T1 - T0) ; + T4 = 1.0 - T3 ; + T5 = Vdsat * T3 / (T1 - T0) ; + Vdseff = Vdsat * T4 ; + } + if (Vds == 0.0) + Vdseff = 0.0 ; + + T0 = Abulk * Vdseff ; + T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.0e-20) ; + T2 = Vdseff / T1 ; + T3 = T0 * T2 ; + BSIM4v7entry.d_BSIM4v7qinvRWArray [instance_ID] = Coxeff * pParam->BSIM4v7weffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * pParam->BSIM4v7leffCV * + (Vgsteff - 0.5 * T0 + Abulk * T3) ; + } + else if(BSIM4v7tnoiMod == 2) + BSIM4v7entry.d_BSIM4v7noiGd0Array [instance_ID] = BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * beta * Vgsteff / (1.0 + gche * Rds) ; + + + /* BSIM4v7 C-V begins */ + /* 20 - non-divergent */ + if ((BSIM4v7xpart < 0) || (!ChargeComputationNeeded)) + { + qgate = qdrn = qsrc = qbulk = 0.0 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7csgbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cssbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7csdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cgbbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7csbbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cdbbRWArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cbbbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cqdbArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cqsbArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cqgbArray [instance_ID] = BSIM4v7entry.d_BSIM4v7cqbbArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] = 0.0 ; + goto finished ; + } + else if (BSIM4v7capMod == 0) + { + if (Vbseff < 0.0) + { + VbseffCV = Vbs ; /*4.6.2*/ + dVbseffCV_dVb = 1.0 ; + } else { + VbseffCV = pParam->BSIM4v7phi - Phis ; + dVbseffCV_dVb = -dPhis_dVb * dVbseff_dVb ; /*4.6.2*/ + } + Vfb = pParam->BSIM4v7vfbcv ; + Vth = Vfb + pParam->BSIM4v7phi + pParam->BSIM4v7k1ox * sqrtPhis ; + Vgst = Vgs_eff - Vth ; + dVth_dVb = pParam->BSIM4v7k1ox * dsqrtPhis_dVb *dVbseff_dVb ; /*4.6.2*/ + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * pParam->BSIM4v7leffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + Arg1 = Vgs_eff - VbseffCV - Vfb ; + + /* 59 - DIVERGENT */ + if (Arg1 <= 0.0) + { + qgate = CoxWL * Arg1 ; + qbulk = -qgate ; + qdrn = 0.0 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = CoxWL * dVgs_eff_dVg ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = CoxWL * (dVbseffCV_dVb - dVgs_eff_dVg) ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -CoxWL * dVgs_eff_dVg ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] ; + } /* Arg1 <= 0.0, end of accumulation */ + else if (Vgst <= 0.0) + { + T1 = 0.5 * pParam->BSIM4v7k1ox ; + T2 = sqrt (T1 * T1 + Arg1) ; + qgate = CoxWL * pParam->BSIM4v7k1ox * (T2 - T1) ; + qbulk = -qgate ; + qdrn = 0.0 ; + T0 = CoxWL * T1 / T2 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = T0 * dVgs_eff_dVg ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = T0 * (dVbseffCV_dVb - dVgs_eff_dVg) ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] ; + } /* Vgst <= 0.0, end of depletion */ + else + { + One_Third_CoxWL = CoxWL / 3.0 ; + Two_Third_CoxWL = 2.0 * One_Third_CoxWL ; + AbulkCV = Abulk0 * pParam->BSIM4v7abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4v7abulkCVfactor * dAbulk0_dVb*dVbseff_dVb ; + dVdsat_dVg = 1.0 / AbulkCV ; /*4.6.2*/ + Vdsat = Vgst * dVdsat_dVg ; + dVdsat_dVb = -(Vdsat * dAbulkCV_dVb + dVth_dVb)* dVdsat_dVg ; + + if (BSIM4v7xpart > 0.5) + { /* 0/100 Charge partition model */ + + if (Vdsat <= Vds) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4v7phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.0 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + T2) ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + T3) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + } 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->BSIM4v7phi - 0.5 * (Vds - T3)) ; + T10 = T4 * T8 ; + qdrn = T4 * T7 ; + qbulk = -(qgate + qdrn + T10) ; + T5 = T3 / T1 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + T11 = -CoxWL * T5 * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + T11 + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID]) ; + 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) ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = (T7 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg ; + T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = T4 * (3.0 - 6.0 * T2 - 3.0 * T5) ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + T12 + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) ; + 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) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + T10) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + T12) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] + T0) ; + } + } + else if (BSIM4v7xpart < 0.5) + { /* 40/60 Charge partition model */ + + if (Vds >= Vdsat) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4v7phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.4 * T2 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + T2) ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + T3 = 0.4 * Two_Third_CoxWL ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = -T3 * dVgs_eff_dVg ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + T4 = T3 * dVth_dVb ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = -(T4 + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + T3) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + } 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->BSIM4v7phi - 0.5 * (Vds - T3)) ; + T5 = T3 / T1 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + tmp = -CoxWL * T5 * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + 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)) ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = (T7 * dAlphaz_dVg - tmp1 * dVdsat_dVg) * dVgs_eff_dVg ; + T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = T4 * (2.0 - (1.0 / (3.0 * T1 * T1) + 2.0 * tmp) * T6 + T8 * + (6.0 * Vdsat - 2.4 * Vds)) ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + T10 + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) ; + T7 = 2.0 * (T1 + T3) ; + qbulk = -(qgate - T4 * T7) ; + T7 *= T9 ; + T0 = 4.0 * T4 * (1.0 - T5) ; + T12 = (-T7 * dAlphaz_dVg - T0 * dVdsat_dVg) * dVgs_eff_dVg - BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] ; /*4.6.2*/ + T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb ; + T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] ; + tmp = -(T10 + T11 + T12) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + T12) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + T10) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] + tmp) ; + } + } else { + /* 50/50 partitioning */ + + if (Vds >= Vdsat) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4v7phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.5 * T2 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + T2) ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = 0.0 ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = -One_Third_CoxWL * dVgs_eff_dVg ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = 0.0 ; + T4 = One_Third_CoxWL * dVth_dVb ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = -(T4 + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + T3) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = 0.0 ; + } 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->BSIM4v7phi - 0.5 * (Vds - T3)) ; + T5 = T3 / T1 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + tmp = -CoxWL * T5 * dVdsat_dVb ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + 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) ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = (T0 * dVdsat_dVg - T7 * dAlphaz_dVg) * dVgs_eff_dVg ; + T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = T4 * (1.0 - 2.0 * T2 - T5) ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + T12 + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + 2.0 * BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + 2.0 * BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + 2.0 * BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID]) ; + } /* end of linear region */ + } /* end of 50/50 partition */ + } /* end of inversion */ + } /* end of capMod=0 */ + else + { + if (Vbseff < 0.0) + { + VbseffCV = Vbseff ; + dVbseffCV_dVb = 1.0 ; + } else { + VbseffCV = pParam->BSIM4v7phi - Phis ; + dVbseffCV_dVb = -dPhis_dVb ; + } + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * pParam->BSIM4v7leffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + + if (BSIM4v7cvchargeMod == 0) + { + /* Seperate VgsteffCV with noff and voffcv */ + noff = n * pParam->BSIM4v7noff ; + dnoff_dVd = pParam->BSIM4v7noff * dn_dVd ; + dnoff_dVb = pParam->BSIM4v7noff * dn_dVb ; + T0 = Vtm * noff ; + voffcv = pParam->BSIM4v7voffcv ; + VgstNVt = (Vgst - voffcv) / T0 ; + + /* 60 - DIVERGENT */ + 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 for cvchargeMod = 0 */ + } else { + T0 = n * Vtm ; + T1 = pParam->BSIM4v7mstarcv * Vgst ; + T2 = T1 / T0 ; + + /* 61 - DIVERGENT */ + if (T2 > EXP_THRESHOLD) + { + T10 = T1 ; + dT10_dVg = pParam->BSIM4v7mstarcv * dVgs_eff_dVg ; + dT10_dVd = -dVth_dVd * pParam->BSIM4v7mstarcv ; + dT10_dVb = -dVth_dVb * pParam->BSIM4v7mstarcv ; + } + else if (T2 < -EXP_THRESHOLD) + { + T10 = Vtm * log (1.0 + MIN_EXP) ; + dT10_dVg = 0.0 ; + dT10_dVd = T10 * dn_dVd ; + dT10_dVb = T10 * dn_dVb ; + T10 *= n ; + } else { + ExpVgst = exp (T2) ; + T3 = Vtm * log (1.0 + ExpVgst) ; + T10 = n * T3 ; + dT10_dVg = pParam->BSIM4v7mstarcv * ExpVgst / (1.0 + ExpVgst) ; + dT10_dVb = T3 * dn_dVb - dT10_dVg * (dVth_dVb + Vgst * dn_dVb / n) ; + dT10_dVd = T3 * dn_dVd - dT10_dVg * (dVth_dVd + Vgst * dn_dVd / n) ; + dT10_dVg *= dVgs_eff_dVg ; + } + T1 = pParam->BSIM4v7voffcbncv - (1.0 - pParam->BSIM4v7mstarcv) * Vgst ; + T2 = T1 / T0 ; + + /* 62 - DIVERGENT */ + if (T2 < -EXP_THRESHOLD) + { + T3 = BSIM4v7coxe * MIN_EXP / pParam->BSIM4v7cdep0 ; + T9 = pParam->BSIM4v7mstarcv + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } + else if (T2 > EXP_THRESHOLD) + { + T3 = BSIM4v7coxe * MAX_EXP / pParam->BSIM4v7cdep0 ; + T9 = pParam->BSIM4v7mstarcv + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } else { + ExpVgst = exp (T2) ; + T3 = BSIM4v7coxe / pParam->BSIM4v7cdep0 ; + T4 = T3 * ExpVgst ; + T5 = T1 * T4 / T0 ; + T9 = pParam->BSIM4v7mstarcv + n * T4 ; + dT9_dVg = T3 * (pParam->BSIM4v7mstarcv - 1.0) * ExpVgst / Vtm ; + dT9_dVb = T4 * dn_dVb - dT9_dVg * dVth_dVb - T5 * dn_dVb ; + dT9_dVd = T4 * dn_dVd - dT9_dVg * dVth_dVd - T5 * dn_dVd ; + dT9_dVg *= dVgs_eff_dVg ; + } + Vgsteff = T10 / T9 ; + T11 = T9 * T9 ; + dVgsteff_dVg = (T9 * dT10_dVg - T10 * dT9_dVg) / T11 ; + dVgsteff_dVd = (T9 * dT10_dVd - T10 * dT9_dVd) / T11 ; + dVgsteff_dVb = (T9 * dT10_dVb - T10 * dT9_dVb) / T11 ; + /* End of VgsteffCV for cvchargeMod = 1 */ + } + + if (BSIM4v7capMod == 1) + { + Vfb = BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID] ; + V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3 ; + + if (Vfb <= 0.0) + T0 = sqrt (V3 * V3 - 4.0 * DELTA_3 * Vfb) ; + else + T0 = sqrt (V3 * V3 + 4.0 * DELTA_3 * Vfb) ; + + 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->BSIM4v7k1ox ; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff ; + + /* 63 - DIVERGENT */ + if (pParam->BSIM4v7k1ox == 0.0) + { + T1 = 0.0 ; + T2 = 0.0 ; + } + else if (T3 < 0.0) + { + T1 = T0 + T3 / pParam->BSIM4v7k1ox ; + T2 = CoxWL ; + } else { + T1 = sqrt (T0 * T0 + T3) ; + T2 = CoxWL * T0 / T1 ; + } + Qsub0 = CoxWL * pParam->BSIM4v7k1ox * (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->BSIM4v7abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4v7abulkCVfactor * dAbulk0_dVb ; + VdsatCV = Vgsteff / AbulkCV ; + T0 = VdsatCV - Vds - DELTA_4 ; + dT0_dVg = 1.0 / 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 ; + + /* 64 - DIVERGENT */ + 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 * (T4 - T5) + T5 * dT1_dVb ; + } + 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 + 1.0e-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 ; + 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 (BSIM4v7xpart > 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 (BSIM4v7xpart < 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 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = Cgg ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(Cgg + Cgd + Cgb) ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = Cgd ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = -(Cgg + Cbg + Csg) ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb) ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = -(Cgd + Cbd + Csd) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = Cbg ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(Cbg + Cbd + Cbb) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = Cbd ; + } + + + /* Charge-Thickness capMod (CTM) begins */ + else if (BSIM4v7capMod == 2) + { + V3 = BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID] - Vgs_eff + VbseffCV - DELTA_3 ; + + if (BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID] <= 0.0) + T0 = sqrt (V3 * V3 - 4.0 * DELTA_3 * BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID]) ; + else + T0 = sqrt (V3 * V3 + 4.0 * DELTA_3 * BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID]) ; + + T1 = 0.5 * (1.0 + V3 / T0) ; + Vfbeff = BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID] - 0.5 * (V3 + T0) ; + dVfbeff_dVg = T1 * dVgs_eff_dVg ; + dVfbeff_dVb = -T1 * dVbseffCV_dVb ; + Cox = BSIM4v7coxp ; + Tox = 1.0e8 * BSIM4v7toxp ; + T0 = (Vgs_eff - VbseffCV - BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID]) / Tox ; + dT0_dVg = dVgs_eff_dVg / Tox ; + dT0_dVb = -dVbseffCV_dVb / Tox ; + tmp = T0 * pParam->BSIM4v7acde ; + + /* 65 - DIVERGENT */ + if ((-EXP_THRESHOLD < tmp) && (tmp < EXP_THRESHOLD)) + { + Tcen = pParam->BSIM4v7ldeb * exp (tmp) ; + dTcen_dVg = pParam->BSIM4v7acde * Tcen ; + dTcen_dVb = dTcen_dVg * dT0_dVb ; + dTcen_dVg *= dT0_dVg ; + } + else if (tmp <= -EXP_THRESHOLD) + { + Tcen = pParam->BSIM4v7ldeb * MIN_EXP ; + dTcen_dVg = dTcen_dVb = 0.0 ; + } else { + Tcen = pParam->BSIM4v7ldeb * MAX_EXP ; + dTcen_dVg = dTcen_dVb = 0.0 ; + } + LINK = 1.0e-3 * BSIM4v7toxp ; + V3 = pParam->BSIM4v7ldeb - Tcen - LINK ; + V4 = sqrt (V3 * V3 + 4.0 * LINK * pParam->BSIM4v7ldeb) ; + Tcen = pParam->BSIM4v7ldeb - 0.5 * (V3 + V4) ; + T1 = 0.5 * (1.0 + V3 / V4) ; + dTcen_dVg *= T1 ; + dTcen_dVb *= T1 ; + Ccen = epssub / 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 / BSIM4v7coxe ; + Qac0 = CoxWLcen * (Vfbeff - BSIM4v7entry.d_BSIM4v7vfbzbArray [instance_ID]) ; + QovCox = Qac0 / Coxeff ; + dQac0_dVg = CoxWLcen * dVfbeff_dVg + QovCox * dCoxeff_dVg ; + dQac0_dVb = CoxWLcen * dVfbeff_dVb + QovCox * dCoxeff_dVb ; + T0 = 0.5 * pParam->BSIM4v7k1ox ; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff ; + + /* 66 - DIVERGENT */ + if (pParam->BSIM4v7k1ox == 0.0) + { + T1 = 0.0 ; + T2 = 0.0 ; + } + else if (T3 < 0.0) + { + T1 = T0 + T3 / pParam->BSIM4v7k1ox ; + T2 = CoxWLcen ; + } else { + T1 = sqrt (T0 * T0 + T3) ; + T2 = CoxWLcen * T0 / T1 ; + } + Qsub0 = CoxWLcen * pParam->BSIM4v7k1ox * (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 */ + /* 67 - DIVERGENT */ + if (pParam->BSIM4v7k1ox <= 0.0) + { + Denomi = 0.25 * pParam->BSIM4v7moin * Vtm ; + T0 = 0.5 * pParam->BSIM4v7sqrtPhi ; + } else { + Denomi = pParam->BSIM4v7moin * Vtm * pParam->BSIM4v7k1ox * pParam->BSIM4v7k1ox ; + T0 = pParam->BSIM4v7k1ox * pParam->BSIM4v7sqrtPhi ; + } + 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) ; + Tox += Tox ; /* WDLiu: Tcen reevaluated below due to different Vgsteff */ + T0 = (Vgsteff + BSIM4v7entry.d_BSIM4v7vtfbphi2Array [instance_ID]) / Tox ; + tmp = exp (BSIM4v7bdos * 0.7 * log (T0)) ; + T1 = 1.0 + tmp ; + T2 = BSIM4v7bdos * 0.7 * tmp / (T0 * Tox) ; + Tcen = BSIM4v7ados * 1.9e-9 / T1 ; + dTcen_dVg = -Tcen * T2 / T1 ; + dTcen_dVd = dTcen_dVg * dVgsteff_dVd ; + dTcen_dVb = dTcen_dVg * dVgsteff_dVb ; + dTcen_dVg *= dVgsteff_dVg ; + Ccen = epssub / 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 / BSIM4v7coxe ; + AbulkCV = Abulk0 * pParam->BSIM4v7abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4v7abulkCVfactor * 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 ; + + /* 68 - DIVERGENT */ + 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 * (T4 - T5) + T5 * dT1_dVb ; + } + + 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 = 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 (BSIM4v7xpart > 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 (BSIM4v7xpart < 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 ; + BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] = Cgg ; + BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] = -(Cgg + Cgd + Cgb) ; + BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] = Cgd ; + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] = -(Cgg + Cbg + Csg) ; + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb) ; + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] = -(Cgd + Cbd + Csd) ; + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] = Cbg ; + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] = -(Cbg + Cbd + Cbb) ; + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] = Cbd ; + } /* End of CTM */ + } + + BSIM4v7entry.d_BSIM4v7csgbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7csdbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7cssbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7cgbbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7cdbbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7cbbbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7csbbRWArray [instance_ID] = - BSIM4v7entry.d_BSIM4v7cgbbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cdbbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbbbRWArray [instance_ID] ; + BSIM4v7entry.d_BSIM4v7qgateRWArray [instance_ID] = qgate ; + BSIM4v7entry.d_BSIM4v7qbulkRWArray [instance_ID] = qbulk ; + BSIM4v7entry.d_BSIM4v7qdrnRWArray [instance_ID] = qdrn ; + BSIM4v7entry.d_BSIM4v7qsrcRWArray [instance_ID] = -(qgate + qbulk + qdrn) ; + + + /* NQS begins */ + /* 69 - DIVERGENT */ + if ((BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) || (BSIM4v7entry.d_BSIM4v7acnqsModArray [instance_ID])) + { + BSIM4v7entry.d_BSIM4v7qchqsArray [instance_ID] = qcheq = -(qbulk + qgate) ; + BSIM4v7entry.d_BSIM4v7cqgbArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cqdbArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cqsbArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID]) ; + BSIM4v7entry.d_BSIM4v7cqbbArray [instance_ID] = -(BSIM4v7entry.d_BSIM4v7cqgbArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cqdbArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cqsbArray [instance_ID]) ; + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * pParam->BSIM4v7leffCV ; + T1 = BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] / CoxWL ; /* 1 / tau */ + BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] = T1 * ScalingFactor ; + + if (BSIM4v7entry.d_BSIM4v7acnqsModArray [instance_ID]) + BSIM4v7entry.d_BSIM4v7taunetArray [instance_ID] = 1.0 / T1 ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 23] = qcheq ; + if (CKTmode & MODEINITTRAN) + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 23] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 23] ; + + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 23, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return(error) ; + } + } + + +finished: + + /* Calculate junction C-V */ + if (ChargeComputationNeeded) + { + /* bug fix */ + czbd = BSIM4v7DunitAreaTempJctCap * BSIM4v7entry.d_BSIM4v7AdeffArray [instance_ID] ; + /* ------- */ + + czbs = BSIM4v7SunitAreaTempJctCap * BSIM4v7entry.d_BSIM4v7AseffArray [instance_ID] ; + czbdsw = BSIM4v7DunitLengthSidewallTempJctCap * BSIM4v7entry.d_BSIM4v7PdeffArray [instance_ID] ; + czbdswg = BSIM4v7DunitLengthGateSidewallTempJctCap * pParam->BSIM4v7weffCJ * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + czbssw = BSIM4v7SunitLengthSidewallTempJctCap * BSIM4v7entry.d_BSIM4v7PseffArray [instance_ID] ; + czbsswg = BSIM4v7SunitLengthGateSidewallTempJctCap * pParam->BSIM4v7weffCJ * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + MJS = BSIM4v7SbulkJctBotGradingCoeff ; + MJSWS = BSIM4v7SbulkJctSideGradingCoeff ; + MJSWGS = BSIM4v7SbulkJctGateSideGradingCoeff ; + MJD = BSIM4v7DbulkJctBotGradingCoeff ; + MJSWD = BSIM4v7DbulkJctSideGradingCoeff ; + MJSWGD = BSIM4v7DbulkJctGateSideGradingCoeff ; + + + /* Source Bulk Junction */ + /* 70 - DIVERGENT */ + if (vbs_jct == 0.0) + { + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] = 0.0 ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] = czbs + czbssw + czbsswg ; + } + else if (vbs_jct < 0.0) + { + if (czbs > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4v7PhiBS ; + + if (MJS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJS * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] = BSIM4v7PhiBS * czbs * (1.0 - arg * sarg) / (1.0 - MJS) ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] = czbs * sarg ; + } else { + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] = 0.0 ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] = 0.0 ; + } + if (czbssw > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4v7PhiBSWS ; + + if (MJSWS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWS * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] += BSIM4v7PhiBSWS * czbssw * (1.0 - arg * sarg) / (1.0 - MJSWS) ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] += czbssw * sarg ; + } + if (czbsswg > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4v7PhiBSWGS ; + + if (MJSWGS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWGS * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] += BSIM4v7PhiBSWGS * czbsswg * (1.0 - arg * sarg) / + (1.0 - MJSWGS) ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] += czbsswg * sarg ; + } + } + else + { + T0 = czbs + czbssw + czbsswg ; + T1 = vbs_jct * (czbs * MJS / BSIM4v7PhiBS + czbssw * MJSWS / BSIM4v7PhiBSWS + + czbsswg * MJSWGS / BSIM4v7PhiBSWGS) ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] = vbs_jct * (T0 + 0.5 * T1) ; + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] = T0 + T1 ; + } + + + /* Drain Bulk Junction */ + /* 71 - DIVERGENT */ + if (vbd_jct == 0.0) + { + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] = 0.0 ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] = czbd + czbdsw + czbdswg ; + } + else if (vbd_jct < 0.0) + { + if (czbd > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4v7PhiBD ; + + if (MJD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJD * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] = BSIM4v7PhiBD* czbd * (1.0 - arg * sarg) / (1.0 - MJD) ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] = czbd * sarg ; + } + else + { + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] = 0.0 ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] = 0.0 ; + } + if (czbdsw > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4v7PhiBSWD ; + + if (MJSWD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWD * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] += BSIM4v7PhiBSWD * czbdsw * (1.0 - arg * sarg) / (1.0 - MJSWD) ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] += czbdsw * sarg ; + } + if (czbdswg > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4v7PhiBSWGD ; + + if (MJSWGD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWGD * log (arg)) ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] += BSIM4v7PhiBSWGD * czbdswg * (1.0 - arg * sarg) / + (1.0 - MJSWGD) ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] += czbdswg * sarg ; + } + } else { + T0 = czbd + czbdsw + czbdswg ; + T1 = vbd_jct * (czbd * MJD / BSIM4v7PhiBD + czbdsw * MJSWD / BSIM4v7PhiBSWD + + czbdswg * MJSWGD / BSIM4v7PhiBSWGD) ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] = vbd_jct * (T0 + 0.5 * T1) ; + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] = T0 + T1 ; + } + } + + + /* check convergence */ + /* 72 - DIVERGENT */ + if ((BSIM4v7entry.d_BSIM4v7offArray [instance_ID] == 0) || (!(CKTmode & MODEINITFIX))) + { + if (Check == 1) + { + atomicAdd (d_CKTnoncon, 1) ; + +#ifndef NEWCONV + } else { + + if (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] >= 0) + Idtot = BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] ; + else + Idtot = BSIM4v7entry.d_BSIM4v7cdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] ; /* bugfix */ + + tol0 = CKTrelTol * MAX (fabs (cdhat), fabs (Idtot)) + CKTabsTol ; + tol1 = CKTrelTol * MAX (fabs (cseshat), fabs (Isestot)) + CKTabsTol ; + tol2 = CKTrelTol * MAX (fabs (cdedhat), fabs (Idedtot)) + CKTabsTol ; + tol3 = CKTrelTol * MAX (fabs (cgshat), fabs (Igstot)) + CKTabsTol ; + tol4 = CKTrelTol * MAX (fabs (cgdhat), fabs (Igdtot)) + CKTabsTol ; + tol5 = CKTrelTol * MAX (fabs (cgbhat), fabs (Igbtot)) + CKTabsTol ; + if ((fabs (cdhat - Idtot) >= tol0) || (fabs (cseshat - Isestot) >= tol1) || + (fabs(cdedhat - Idedtot) >= tol2)) + { + atomicAdd (d_CKTnoncon, 1) ; + } + else if ((fabs(cgshat - Igstot) >= tol3) || (fabs(cgdhat - Igdtot) >= tol4) || + (fabs(cgbhat - Igbtot) >= tol5)) + { + atomicAdd (d_CKTnoncon, 1) ; + } else { + Ibtot = BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] ; + tol6 = CKTrelTol * MAX (fabs (cbhat), fabs (Ibtot)) + CKTabsTol ; + if (fabs (cbhat - Ibtot) > tol6) + { + atomicAdd (d_CKTnoncon, 1) ; + } + } +#endif /* NEWCONV */ + + } + } + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 3] = vds ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 2] = vgs ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 1] = vbs ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID]] = vbd ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 7] = vges ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 8] = vgms ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 4] = vdbs ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 5] = vdbd ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 6] = vsbs ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 9] = vses ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 10] = vdes ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 27] = qdef ; + + + if (!ChargeComputationNeeded) + goto line850 ; + + /* 73 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + vgdx = vgmd ; + vgsx = vgms ; + } else { + /* For rgateMod == 0, 1 and 2 */ + vgdx = vgd ; + vgsx = vgs ; + } + + if (BSIM4v7capMod == 0) + { + cgdo = pParam->BSIM4v7cgdo ; + qgdo = pParam->BSIM4v7cgdo * vgdx ; + cgso = pParam->BSIM4v7cgso ; + qgso = pParam->BSIM4v7cgso * vgsx ; + } else { + /* For both capMod == 1 and 2 */ + T0 = vgdx + DELTA_1 ; + T1 = sqrt (T0 * T0 + 4.0 * DELTA_1) ; + T2 = 0.5 * (T0 - T1) ; + T3 = pParam->BSIM4v7weffCV * pParam->BSIM4v7cgdl ; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4v7ckappad) ; + cgdo = pParam->BSIM4v7cgdo + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1) ; + qgdo = (pParam->BSIM4v7cgdo + T3) * vgdx - T3 * (T2 + 0.5 * pParam->BSIM4v7ckappad * (T4 - 1.0)) ; + T0 = vgsx + DELTA_1 ; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1) ; + T2 = 0.5 * (T0 - T1) ; + T3 = pParam->BSIM4v7weffCV * pParam->BSIM4v7cgsl ; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4v7ckappas) ; + cgso = pParam->BSIM4v7cgso + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1) ; + qgso = (pParam->BSIM4v7cgso + T3) * vgsx - T3 * (T2 + 0.5 * pParam->BSIM4v7ckappas * (T4 - 1.0)) ; + } + + /* 74 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] != 1.0) + { + cgdo *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + cgso *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + qgdo *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + qgso *= BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] ; + } + BSIM4v7entry.d_BSIM4v7cgdoArray [instance_ID] = cgdo ; + BSIM4v7entry.d_BSIM4v7qgdoArray [instance_ID] = qgdo ; + BSIM4v7entry.d_BSIM4v7cgsoArray [instance_ID] = cgso ; + BSIM4v7entry.d_BSIM4v7qgsoArray [instance_ID] = qgso ; + +#ifndef NOBYPASS +line755: +#endif + ag0 = CKTag_0 ; + + /* 75 - DIVERGENT - CRITICAL */ + if (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] > 0) + { + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID] == 0) + { + qdrn -= qgdo ; + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4v7cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcggb = BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] * ag0 ; + gcgdb = BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] * ag0 ; + gcgsb = BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] * ag0 ; + gcsgb = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID]) * ag0 ; + gcbgb = BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] * ag0 ; + qgmb = pParam->BSIM4v7cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qbulk -= qgmb ; + qsrc = -(qgate + qgmid + qbulk + qdrn) ; + } else { + gcggb = (BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + cgdo + cgso + pParam->BSIM4v7cgbo ) * ag0 ; + gcgdb = (BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] - cgdo) * ag0 ; + gcgsb = (BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] - cgso) * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = (BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] - cgdo) * ag0 ; + gcsgb = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + cgso) * ag0 ; + gcbgb = (BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] - pParam->BSIM4v7cgbo) * ag0 ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4v7cgbo * vgb ; + qgate += qgdo + qgso + qgb ; + qbulk -= qgb ; + qsrc = -(qgate + qbulk + qdrn) ; + } + gcddb = (BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] * ag0 ; + gcsdb = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) * ag0 ; + gcssb = (BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] + cgso - (BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID])) * ag0 ; + + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) ; + gcbdb = (BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID]) * ag0 ; + gcbsb = (BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID]) * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = -(BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID]) * ag0 ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + gcbdb = BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] * ag0 ; + gcbsb = BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] * ag0 ; + gcdbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb) ; + 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 { + qcheq = BSIM4v7entry.d_BSIM4v7qchqsArray [instance_ID] ; + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * pParam->BSIM4v7leffCV ; + T0 = qdef * ScalingFactor / CoxWL ; + ggtg = BSIM4v7entry.d_BSIM4v7gtgArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] ; + ggtd = BSIM4v7entry.d_BSIM4v7gtdArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] ; + ggts = BSIM4v7entry.d_BSIM4v7gtsArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgsArray [instance_ID] ; + ggtb = BSIM4v7entry.d_BSIM4v7gtbArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] ; + gqdef = ScalingFactor * ag0 ; + gcqgb = BSIM4v7entry.d_BSIM4v7cqgbArray [instance_ID] * ag0 ; + gcqdb = BSIM4v7entry.d_BSIM4v7cqdbArray [instance_ID] * ag0 ; + gcqsb = BSIM4v7entry.d_BSIM4v7cqsbArray [instance_ID] * ag0 ; + gcqbb = BSIM4v7entry.d_BSIM4v7cqbbArray [instance_ID] * ag0 ; + + if (fabs (qcheq) <= 1.0e-5 * CoxWL) + { + + if (BSIM4v7xpart < 0.5) + dxpart = 0.4 ; + else if (BSIM4v7xpart > 0.5) + dxpart = 0.0 ; + else + dxpart = 0.5 ; + + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0 ; + } else { + dxpart = qdrn / qcheq ; + Cdd = BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] ; + Csd = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID]) ; + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq ; + Cdg = BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] ; + Csg = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID]) ; + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq ; + Cds = BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] ; + Css = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID]) ; + 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) ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4v7cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcdgb = gcsgb = gcbgb = 0.0 ; + gcggb = gcgdb = gcgsb = gcgbb = 0.0 ; + qgmb = pParam->BSIM4v7cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qgate = 0.0 ; + qbulk = -qgmb ; + qdrn = -qgdo ; + qsrc = -(qgmid + qbulk + qdrn) ; + } else { + gcggb = (cgdo + cgso + pParam->BSIM4v7cgbo) * ag0 ; + gcgdb = -cgdo * ag0 ; + gcgsb = -cgso * ag0 ; + gcgbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgb = gcgdb ; + gcsgb = gcgsb ; + gcbgb = gcgbb ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4v7cgbo * vgb ; + qgate = qgdo + qgso + qgb ; + qbulk = -qgb ; + qdrn = -qgdo ; + qsrc = -(qgate + qbulk + qdrn) ; + } + gcddb = (BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = gcsdb = 0.0 ; + gcssb = (BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdgmb) ; + gcsbb = -(gcsgb + gcssb + gcsgmb) ; + gcbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = gcsbb = gcbdb = gcbsb = 0.0 ; + gcdbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb) ; + } + } else { + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID] == 0) + { + qsrc = qdrn - qgso ; + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4v7cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcggb = BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] * ag0 ; + gcgdb = BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] * ag0 ; + gcgsb = BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID]) * ag0 ; + gcsgb = BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] * ag0 ; + gcbgb = BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] * ag0 ; + qgmb = pParam->BSIM4v7cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qbulk -= qgmb ; + qdrn = -(qgate + qgmid + qbulk + qsrc) ; + } else { + gcggb = (BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + cgdo + cgso + pParam->BSIM4v7cgbo ) * ag0 ; + gcgdb = (BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] - cgdo) * ag0 ; + gcgsb = (BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] - cgso) * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + cgdo) * ag0 ; + gcsgb = (BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] - cgso) * ag0 ; + gcbgb = (BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID] - pParam->BSIM4v7cgbo) * ag0 ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4v7cgbo * vgb ; + qgate += qgdo + qgso + qgb ; + qbulk -= qgb ; + qdrn = -(qgate + qbulk + qsrc) ; + } + gcddb = (BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] + cgdo - (BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID])) * ag0 ; + gcdsb = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID]) * ag0 ; + gcsdb = BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] * ag0 ; + gcssb = (BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) ; + gcbdb = (BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID]) * ag0 ; + gcbsb = (BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID]) * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) + BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcsbb = -(BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID]) * ag0 ; + gcbdb = BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID] * ag0 ; + gcbsb = BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID] * ag0 ; + gcdbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbgb + gcbdb + gcbsb + gcbgmb) ; + 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 { + qcheq = BSIM4v7entry.d_BSIM4v7qchqsArray [instance_ID] ; + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * pParam->BSIM4v7leffCV ; + T0 = qdef * ScalingFactor / CoxWL ; + ggtg = BSIM4v7entry.d_BSIM4v7gtgArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] ; + ggts = BSIM4v7entry.d_BSIM4v7gtsArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] ; + ggtd = BSIM4v7entry.d_BSIM4v7gtdArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgsArray [instance_ID] ; + ggtb = BSIM4v7entry.d_BSIM4v7gtbArray [instance_ID] = T0 * BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] ; + gqdef = ScalingFactor * ag0 ; + gcqgb = BSIM4v7entry.d_BSIM4v7cqgbArray [instance_ID] * ag0 ; + gcqdb = BSIM4v7entry.d_BSIM4v7cqsbArray [instance_ID] * ag0 ; + gcqsb = BSIM4v7entry.d_BSIM4v7cqdbArray [instance_ID] * ag0 ; + gcqbb = BSIM4v7entry.d_BSIM4v7cqbbArray [instance_ID] * ag0 ; + + if (fabs (qcheq) <= 1.0e-5 * CoxWL) + { + + if (BSIM4v7xpart < 0.5) + sxpart = 0.4 ; + else if (BSIM4v7xpart > 0.5) + sxpart = 0.0 ; + else + sxpart = 0.5 ; + + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0 ; + } else { + sxpart = qdrn / qcheq ; + Css = BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] ; + Cds = -(BSIM4v7entry.d_BSIM4v7cgdbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cddbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbdbRWArray [instance_ID]) ; + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq ; + Csg = BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] ; + Cdg = -(BSIM4v7entry.d_BSIM4v7cggbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdgbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbgbRWArray [instance_ID]) ; + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq ; + Csd = BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] ; + Cdd = -(BSIM4v7entry.d_BSIM4v7cgsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cdsbRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7cbsbRWArray [instance_ID]) ; + 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) ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4v7cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcdgb = gcsgb = gcbgb = 0.0 ; + gcggb = gcgdb = gcgsb = gcgbb = 0.0 ; + qgmb = pParam->BSIM4v7cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qgate = 0.0 ; + qbulk = -qgmb ; + qdrn = -qgdo ; + qsrc = -qgso ; + } else { + gcggb = (cgdo + cgso + pParam->BSIM4v7cgbo ) * ag0 ; + gcgdb = -cgdo * ag0 ; + gcgsb = -cgso * ag0 ; + gcgbb = -pParam->BSIM4v7cgbo * ag0 ; + gcdgb = gcgdb ; + gcsgb = gcgsb ; + gcbgb = gcgbb ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4v7cgbo * vgb ; + qgate = qgdo + qgso + qgb ; + qbulk = -qgb ; + qdrn = -qgdo ; + qsrc = -qgso ; + } + gcddb = (BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = gcsdb = 0.0 ; + gcssb = (BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdgmb) ; + gcsbb = -(gcsgb + gcssb + gcsgmb) ; + gcbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = gcsbb = gcbdb = gcbsb = 0.0 ; + gcdbdb = -BSIM4v7entry.d_BSIM4v7capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4v7entry.d_BSIM4v7capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb) ; + } + } + + /* 76 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 25] = qdef * ScalingFactor ; + + if (CKTmode & MODEINITTRAN) + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 25] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 25] ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 25, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + } + + if (ByPass) + goto line860 ; + + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 13] = qgate ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 15] = qdrn - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] ; + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 28] = qsrc - CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] ; + + /* 77 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 17] = qgmid ; + + /* 78 - DIVERGENT */ + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 11] = qbulk + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] ; + else + CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 11] = qbulk ; + + + /* Store small signal parameters */ + if (CKTmode & MODEINITSMSIG) + goto line1000 ; + + /* I DON'T KNOW */ + if (!ChargeComputationNeeded) + goto line850 ; + + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 11] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 11] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 13] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 13] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 15] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 15] ; + + /* 79 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 17] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 17] ; + + /* 80 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21] ; + } + } + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 11, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 13, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 15, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + + /* 81 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 17, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + } + + /* 82 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 19, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 21, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + } + goto line860 ; + + +line850: + /* Zero gcap and ceqcap if (!ChargeComputationNeeded) */ + ceqqg = ceqqb = ceqqd = 0.0 ; + ceqqjd = ceqqjs = 0.0 ; + cqcheq = cqdef = 0.0 ; + gcdgb = gcddb = gcdsb = gcdbb = 0.0 ; + gcsgb = gcsdb = gcssb = gcsbb = 0.0 ; + gcggb = gcgdb = gcgsb = gcgbb = 0.0 ; + gcbdb = gcbgb = gcbsb = gcbbb = 0.0 ; + gcgmgmb = gcgmdb = gcgmsb = gcgmbb = 0.0 ; + gcdgmb = gcsgmb = gcbgmb = ceqqgmid = 0.0 ; + gcdbdb = gcsbsb = 0.0 ; + gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0 ; + ggtg = ggtd = ggtb = ggts = 0.0 ; + sxpart = (1.0 - (dxpart = (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] > 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 ; + + /* 83 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + CoxWL = BSIM4v7coxe * pParam->BSIM4v7weffCV * BSIM4v7entry.d_BSIM4v7nfArray [instance_ID] * pParam->BSIM4v7leffCV ; + T1 = BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] / CoxWL ; + BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] = T1 * ScalingFactor ; + } + else + BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] = 0.0 ; + + goto line900 ; + + +line860: + /* Calculate equivalent charge current */ + cqgate = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 14] ; + cqbody = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 12] ; + cqdrn = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 16] ; + ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs ; + ceqqd = cqdrn - gcdgb * vgb - gcdgmb * vgmb + (gcddb + gcdbdb) * vbd - gcdbdb * vbd_jct + gcdsb * vbs ; + ceqqb = cqbody - gcbgb * vgb - gcbgmb * vgmb + gcbdb * vbd + gcbsb * vbs ; + + /* 84 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + ceqqgmid = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 18] + gcgmdb * vbd + gcgmsb * vbs - gcgmgmb * vgmb ; + else + ceqqgmid = 0.0 ; + + /* 85 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + ceqqjs = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 20] + gcsbsb * vbs_jct ; + ceqqjd = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 22] + gcdbdb * vbd_jct ; + } + + /* 86 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + T0 = ggtg * vgb - ggtd * vbd - ggts * vbs ; + ceqqg += T0 ; + T1 = qdef * BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] ; + ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd * vbd - ddxpart_dVs * vbs) ; + cqdef = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 26] - gqdef * qdef ; + cqcheq = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 24] - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0 ; + } + + /* 21 - non-divergent */ + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 12] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 12] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 14] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 14] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 16] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 16] ; + + /* 87 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 18] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 18] ; + + /* 88 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 20] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 20] ; + CKTstate_1 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 22] = CKTstate_0 [BSIM4v7entry.d_BSIM4v7statesArray [instance_ID] + 22] ; + } + } + + + /* Load current vector */ + /* 89 - DIVERGENT - CRITICAL */ +line900: + if (BSIM4v7entry.d_BSIM4v7modeArray [instance_ID] >= 0) + { + Gm = BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] ; + Gmbs = BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] ; + FwdSum = Gm + Gmbs ; + RevSum = 0.0 ; + ceqdrn = BSIM4v7type * (cdrain - BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] * vds - Gm * vgs - Gmbs * vbs) ; + ceqbd = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - + (BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID]) * vds - + (BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID]) * vgs - (BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID]) * vbs) ; + ceqbs = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] * vds - + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] * vgd - BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] * vbd) ; + gbbdp = -(BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID]) ; + gbbsp = BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] ; + gbdpg = BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] ; + gbdpdp = BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] ; + gbdpb = BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] ; + gbdpsp = -(gbdpg + gbdpdp + gbdpb) ; + gbspg = 0.0 ; + gbspdp = 0.0 ; + gbspb = 0.0 ; + gbspsp = 0.0 ; + + if (BSIM4v7igcMod) + { + gIstotg = BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] ; + gIstotd = BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] ; + gIstots = BSIM4v7entry.d_BSIM4v7gIgssArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcssArray [instance_ID] ; + gIstotb = BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] ; + Istoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] - gIstotg * vgs - + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] * vds - BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] * vbs) ; + gIdtotg = BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] ; + gIdtotd = BSIM4v7entry.d_BSIM4v7gIgddArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] ; + gIdtots = BSIM4v7entry.d_BSIM4v7gIgcdsArray [instance_ID] ; + gIdtotb = BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] ; + Idtoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] * vgd - + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] * vgs - BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] * vds - BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] * vbs) ; + } else { + gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0 ; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0 ; + } + + if (BSIM4v7igbMod) + { + gIbtotg = BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] ; + gIbtotd = BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] ; + gIbtots = BSIM4v7entry.d_BSIM4v7gIgbsArray [instance_ID] ; + gIbtotb = BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] ; + Ibtoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] * vgs - BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] * vds - + BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] * vbs) ; + } + else + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0 ; + + if ((BSIM4v7igcMod != 0) || (BSIM4v7igbMod != 0)) + { + gIgtotg = gIstotg + gIdtotg + gIbtotg ; + gIgtotd = gIstotd + gIdtotd + gIbtotd ; + gIgtots = gIstots + gIdtots + gIbtots ; + gIgtotb = gIstotb + gIdtotb + gIbtotb ; + Igtoteq = Istoteq + Idtoteq + Ibtoteq ; + } + else + gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = 0.0 ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2) + T0 = vges - vgs ; + else if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + T0 = vgms - vgs ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] > 1) + { + gcrgd = BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] * T0 ; + gcrgg = BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] * T0 ; + gcrgs = BSIM4v7entry.d_BSIM4v7gcrgsArray [instance_ID] * T0 ; + gcrgb = BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] * T0 ; + ceqgcrg = -(gcrgd * vds + gcrgg * vgs + gcrgb * vbs) ; + gcrgg -= BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] ; + gcrg = BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] ; + } + else + ceqgcrg = gcrg = gcrgd = gcrgg = gcrgs = gcrgb = 0.0 ; + } else { + Gm = -BSIM4v7entry.d_BSIM4v7gmRWArray [instance_ID] ; + Gmbs = -BSIM4v7entry.d_BSIM4v7gmbsRWArray [instance_ID] ; + FwdSum = 0.0 ; + RevSum = -(Gm + Gmbs) ; + ceqdrn = -BSIM4v7type * (cdrain + BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] * vds + Gm * vgd + Gmbs * vbd) ; + ceqbs = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7csubRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgislRWArray [instance_ID] + + (BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID]) * vds - + (BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID]) * vgd - (BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID]) * vbd) ; + ceqbd = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgidlRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] * vds - BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] * vgs - + BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] * vbs) ; + gbbsp = -(BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID]) ; + gbbdp = BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] ; + gbdpg = 0.0 ; + gbdpsp = 0.0 ; + gbdpb = 0.0 ; + gbdpdp = 0.0 ; + gbspg = BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] ; + gbspsp = BSIM4v7entry.d_BSIM4v7gbdsArray [instance_ID] ; + gbspb = BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] ; + gbspdp = -(gbspg + gbspsp + gbspb) ; + + if (BSIM4v7igcMod) + { + gIstotg = BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] ; + gIstotd = BSIM4v7entry.d_BSIM4v7gIgcdsArray [instance_ID] ; + gIstots = BSIM4v7entry.d_BSIM4v7gIgssArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] ; + gIstotb = BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] ; + Istoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gIgsgArray [instance_ID] * vgs - + BSIM4v7entry.d_BSIM4v7gIgcdgArray [instance_ID] * vgd + BSIM4v7entry.d_BSIM4v7gIgcddArray [instance_ID] * vds - BSIM4v7entry.d_BSIM4v7gIgcdbArray [instance_ID] * vbd) ; + gIdtotg = BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID] ; + gIdtotd = BSIM4v7entry.d_BSIM4v7gIgddArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcssArray [instance_ID] ; + gIdtots = BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] ; + gIdtotb = BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] ; + Idtoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgdRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7IgcsRWArray [instance_ID] - + (BSIM4v7entry.d_BSIM4v7gIgdgArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gIgcsgArray [instance_ID]) * vgd + BSIM4v7entry.d_BSIM4v7gIgcsdArray [instance_ID] * vds - + BSIM4v7entry.d_BSIM4v7gIgcsbArray [instance_ID] * vbd) ; + } else { + gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0 ; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0 ; + } + + if (BSIM4v7igbMod) + { + gIbtotg = BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] ; + gIbtotd = BSIM4v7entry.d_BSIM4v7gIgbsArray [instance_ID] ; + gIbtots = BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] ; + gIbtotb = BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] ; + Ibtoteq = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7IgbRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gIgbgArray [instance_ID] * vgd + + BSIM4v7entry.d_BSIM4v7gIgbdArray [instance_ID] * vds - BSIM4v7entry.d_BSIM4v7gIgbbArray [instance_ID] * vbd) ; + } + else + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0 ; + + if ((BSIM4v7igcMod != 0) || (BSIM4v7igbMod != 0)) + { + gIgtotg = gIstotg + gIdtotg + gIbtotg ; + gIgtotd = gIstotd + gIdtotd + gIbtotd ; + gIgtots = gIstots + gIdtots + gIbtots ; + gIgtotb = gIstotb + gIdtotb + gIbtotb ; + Igtoteq = Istoteq + Idtoteq + Ibtoteq ; + } + else + gIgtotg = gIgtotd = gIgtots = gIgtotb = Igtoteq = 0.0 ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2) + T0 = vges - vgs ; + else if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + T0 = vgms - vgs ; + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] > 1) + { + gcrgd = BSIM4v7entry.d_BSIM4v7gcrgsArray [instance_ID] * T0 ; + gcrgg = BSIM4v7entry.d_BSIM4v7gcrggArray [instance_ID] * T0 ; + gcrgs = BSIM4v7entry.d_BSIM4v7gcrgdArray [instance_ID] * T0 ; + gcrgb = BSIM4v7entry.d_BSIM4v7gcrgbArray [instance_ID] * T0 ; + ceqgcrg = -(gcrgg * vgd - gcrgs * vds + gcrgb * vbd) ; + gcrgg -= BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] ; + gcrg = BSIM4v7entry.d_BSIM4v7gcrgRWArray [instance_ID] ; + } + else + ceqgcrg = gcrg = gcrgd = gcrgg = gcrgs = gcrgb = 0.0 ; + } + + /* 22 - non-divergent */ + if (BSIM4v7rdsMod == 1) + { + ceqgstot = BSIM4v7type * (BSIM4v7entry.d_BSIM4v7gstotdArray [instance_ID] * vds + BSIM4v7entry.d_BSIM4v7gstotgArray [instance_ID] * vgs + + BSIM4v7entry.d_BSIM4v7gstotbArray [instance_ID] * vbs) ; + + /* WDLiu: ceqgstot flowing away from sNodePrime */ + gstot = BSIM4v7entry.d_BSIM4v7gstotArray [instance_ID] ; + gstotd = BSIM4v7entry.d_BSIM4v7gstotdArray [instance_ID] ; + gstotg = BSIM4v7entry.d_BSIM4v7gstotgArray [instance_ID] ; + gstots = BSIM4v7entry.d_BSIM4v7gstotsArray [instance_ID] - gstot ; + gstotb = BSIM4v7entry.d_BSIM4v7gstotbArray [instance_ID] ; + ceqgdtot = -BSIM4v7type * (BSIM4v7entry.d_BSIM4v7gdtotdArray [instance_ID] * vds + BSIM4v7entry.d_BSIM4v7gdtotgArray [instance_ID] * vgs + + BSIM4v7entry.d_BSIM4v7gdtotbArray [instance_ID] * vbs) ; + + /* WDLiu: ceqgdtot defined as flowing into dNodePrime */ + gdtot = BSIM4v7entry.d_BSIM4v7gdtotArray [instance_ID] ; + gdtotd = BSIM4v7entry.d_BSIM4v7gdtotdArray [instance_ID] - gdtot ; + gdtotg = BSIM4v7entry.d_BSIM4v7gdtotgArray [instance_ID] ; + gdtots = BSIM4v7entry.d_BSIM4v7gdtotsArray [instance_ID] ; + gdtotb = BSIM4v7entry.d_BSIM4v7gdtotbArray [instance_ID] ; + } else { + gstot = gstotd = gstotg = gstots = gstotb = ceqgstot = 0.0 ; + gdtot = gdtotd = gdtotg = gdtots = gdtotb = ceqgdtot = 0.0 ; + } + + /* 23 - non-divergent */ + if (BSIM4v7type > 0) + { + ceqjs = (BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] * vbs_jct) ; + ceqjd = (BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * vbd_jct) ; + } else { + ceqjs = -(BSIM4v7entry.d_BSIM4v7cbsRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] * vbs_jct) ; + ceqjd = -(BSIM4v7entry.d_BSIM4v7cbdRWArray [instance_ID] - BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] * vbd_jct) ; + ceqqg = -ceqqg ; + ceqqd = -ceqqd ; + ceqqb = -ceqqb ; + ceqgcrg = -ceqgcrg ; + + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + cqdef = -cqdef ; + cqcheq = -cqcheq ; + } + + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + ceqqjs = -ceqqjs ; + ceqqjd = -ceqqjd ; + } + + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + ceqqgmid = -ceqqgmid ; + } + + + m = BSIM4v7entry.d_BSIM4v7mArray [instance_ID] ; + + + /* Loading RHS */ + posRHS = d_PositionVectorRHS [instance_ID] ; + total_offsetRHS = 0 ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq) ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 1] = m * (ceqqg - ceqgcrg + Igtoteq) ; + + total_offsetRHS += 2 ; + + + /* 90 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * ceqgcrg ; + + total_offsetRHS += 1 ; + } + else if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * (ceqqgmid + ceqgcrg) ; + + total_offsetRHS += 1 ; + } + + /* 90 - DIVERGENT */ + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq) ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 1] = m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq) ; + + total_offsetRHS += 2 ; + + } else { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * (ceqjd + ceqqjd) ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 1] = m * (ceqbd + ceqbs - ceqqb + Ibtoteq) ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 2] = m * (ceqjs + ceqqjs) ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 3] = m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq) ; + + total_offsetRHS += 4 ; + } + + /* 24 - non-divergent */ + if (BSIM4v7rdsMod) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * ceqgdtot ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 1] = m * ceqgstot ; + + total_offsetRHS += 2 ; + } + + /* 91 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 2] = m * (cqcheq - cqdef) ; + + + + /* Loading Matrix */ + pos = d_PositionVector [instance_ID] ; + total_offset = 0 ; + + /* 92 - DIVERGENT */ + if (!BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + gjbd = BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] ; + gjbs = BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] ; + } else + gjbd = gjbs = 0.0 ; + + /* 25 - non-divergent */ + if (!BSIM4v7rdsMod) + { + gdpr = BSIM4v7entry.d_BSIM4v7drainConductanceArray [instance_ID] ; + gspr = BSIM4v7entry.d_BSIM4v7sourceConductanceArray [instance_ID] ; + } else + gdpr = gspr = 0.0 ; + + geltd = BSIM4v7entry.d_BSIM4v7grgeltdArray [instance_ID] ; + T1 = qdef * BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] ; + + /* 26 - non-divergent */ + if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 1) + { + d_CKTloadOutput [pos + total_offset + 0] = m * geltd ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (gcggb + geltd - ggtg + gIgtotg) ; + + d_CKTloadOutput [pos + total_offset + 2] = m * (gcgdb - ggtd + gIgtotd) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * (gcgsb - ggts + gIgtots) ; + + d_CKTloadOutput [pos + total_offset + 4] = m * (gcgbb - ggtb + gIgtotb) ; + + total_offset += 5 ; + } + else if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 2) + { + d_CKTloadOutput [pos + total_offset + 0] = m * gcrg ; + + d_CKTloadOutput [pos + total_offset + 1] = m * gcrgg ; + + d_CKTloadOutput [pos + total_offset + 2] = m * gcrgd ; + + d_CKTloadOutput [pos + total_offset + 3] = m * gcrgs ; + + d_CKTloadOutput [pos + total_offset + 4] = m * gcrgb ; + + d_CKTloadOutput [pos + total_offset + 5] = m * (gcggb - gcrgg - ggtg + gIgtotg) ; + + d_CKTloadOutput [pos + total_offset + 6] = m * (gcgdb - gcrgd - ggtd + gIgtotd) ; + + d_CKTloadOutput [pos + total_offset + 7] = m * (gcgsb - gcrgs - ggts + gIgtots) ; + + d_CKTloadOutput [pos + total_offset + 8] = m * (gcgbb - gcrgb - ggtb + gIgtotb) ; + + total_offset += 9 ; + } + else if (BSIM4v7entry.d_BSIM4v7rgateModArray [instance_ID] == 3) + { + d_CKTloadOutput [pos + total_offset + 0] = m * geltd ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (geltd + gcrg + gcgmgmb) ; + + d_CKTloadOutput [pos + total_offset + 2] = m * (gcrgd + gcgmdb) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * gcrgg ; + + d_CKTloadOutput [pos + total_offset + 4] = m * (gcrgs + gcgmsb) ; + + d_CKTloadOutput [pos + total_offset + 5] = m * (gcrgb + gcgmbb) ; + + d_CKTloadOutput [pos + total_offset + 6] = m * gcdgmb ; + + d_CKTloadOutput [pos + total_offset + 7] = m * gcrg ; + + d_CKTloadOutput [pos + total_offset + 8] = m * gcsgmb ; + + d_CKTloadOutput [pos + total_offset + 9] = m * gcbgmb ; + + d_CKTloadOutput [pos + total_offset + 10] = m * (gcggb - gcrgg - ggtg + gIgtotg) ; + + d_CKTloadOutput [pos + total_offset + 11] = m * (gcgdb - gcrgd - ggtd + gIgtotd) ; + + d_CKTloadOutput [pos + total_offset + 12] = m * (gcgsb - gcrgs - ggts + gIgtots) ; + + d_CKTloadOutput [pos + total_offset + 13] = m * (gcgbb - gcrgb - ggtb + gIgtotb) ; + + total_offset += 14 ; + } else { + d_CKTloadOutput [pos + total_offset + 0] = m * (gcggb - ggtg + gIgtotg) ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (gcgdb - ggtd + gIgtotd) ; + + d_CKTloadOutput [pos + total_offset + 2] = m * (gcgsb - ggts + gIgtots) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * (gcgbb - ggtb + gIgtotb) ; + + total_offset += 4 ; + } + + /* 27 - non-divergent */ + if (BSIM4v7rdsMod) + { + d_CKTloadOutput [pos + total_offset + 0] = m * gdtotg ; + + d_CKTloadOutput [pos + total_offset + 1] = m * gdtots ; + + d_CKTloadOutput [pos + total_offset + 2] = m * gdtotb ; + + d_CKTloadOutput [pos + total_offset + 3] = m * gstotd ; + + total_offset += 4 ; + } + + ggidld = BSIM4v7entry.d_BSIM4v7ggidldArray [instance_ID] ; + ggidlg = BSIM4v7entry.d_BSIM4v7ggidlgArray [instance_ID] ; + ggidlb = BSIM4v7entry.d_BSIM4v7ggidlbArray [instance_ID] ; + ggislg = BSIM4v7entry.d_BSIM4v7ggislgArray [instance_ID] ; + ggisls = BSIM4v7entry.d_BSIM4v7ggislsArray [instance_ID] ; + ggislb = BSIM4v7entry.d_BSIM4v7ggislbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 0] = m * (gdpr + BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] + T1 * ddxpart_dVd - gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd) + m * ggidld ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (gdpr + gdtot) ; + + d_CKTloadOutput [pos + total_offset + 2] = m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + dxpart * ggtg + T1 * ddxpart_dVg) + m * ggidlg ; + + d_CKTloadOutput [pos + total_offset + 3] = m * (BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + gdtots - dxpart * ggts + gIdtots - T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp) + m * (ggidlg + ggidld + ggidlb) ; + + d_CKTloadOutput [pos + total_offset + 4] = m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb - T1 * ddxpart_dVb - dxpart * ggtb) - m * ggidlb ; + + d_CKTloadOutput [pos + total_offset + 5] = m * (gdpr - gdtotd) ; + + d_CKTloadOutput [pos + total_offset + 6] = m * (BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + gstotd + RevSum - gcsdb - gbspdp - T1 * dsxpart_dVd - sxpart * ggtd + gIstotd) + m * (ggisls + ggislg + ggislb) ; + + d_CKTloadOutput [pos + total_offset + 7] = m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + T1 * dsxpart_dVg - gIstotg) + m * ggislg ; + + d_CKTloadOutput [pos + total_offset + 8] = m * (gspr + BSIM4v7entry.d_BSIM4v7gdsRWArray [instance_ID] + BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] + T1 * dsxpart_dVs - gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots) + m * ggisls ; + + d_CKTloadOutput [pos + total_offset + 9] = m * (gspr + gstot) ; + + d_CKTloadOutput [pos + total_offset + 10] = m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb - T1 * dsxpart_dVb + gIstotb) - m * ggislb ; + + d_CKTloadOutput [pos + total_offset + 11] = m * (gspr - gstots) ; + + d_CKTloadOutput [pos + total_offset + 12] = m * (gcbdb - gjbd + gbbdp - gIbtotd) - m * ggidld + m * (ggislg + ggisls + ggislb) ; + + d_CKTloadOutput [pos + total_offset + 13] = m * (gcbgb - BSIM4v7entry.d_BSIM4v7gbgsArray [instance_ID] - gIbtotg) - m * ggidlg - m * ggislg ; + + d_CKTloadOutput [pos + total_offset + 14] = m * (gcbsb - gjbs + gbbsp - gIbtots) + m * (ggidlg + ggidld + ggidlb) - m * ggisls ; + + d_CKTloadOutput [pos + total_offset + 15] = m * (gjbd + gjbs + gcbbb - BSIM4v7entry.d_BSIM4v7gbbsArray [instance_ID] - gIbtotb) - m * ggidlb - m * ggislb ; + + total_offset += 16 ; + + /* stamp gidl included above */ + /* stamp gisl included above */ + + /* 94 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7rbodyModArray [instance_ID]) + { + d_CKTloadOutput [pos + total_offset + 0] = m * (gcdbdb - BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] - gcsbsb) ; + + + d_CKTloadOutput [pos + total_offset + 2] = m * (BSIM4v7entry.d_BSIM4v7gbdRWArray [instance_ID] - gcdbdb + BSIM4v7entry.d_BSIM4v7grbpdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbdbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * BSIM4v7entry.d_BSIM4v7grbpdArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 4] = m * BSIM4v7entry.d_BSIM4v7grbdbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 5] = m * BSIM4v7entry.d_BSIM4v7grbpbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 6] = m * BSIM4v7entry.d_BSIM4v7grbpsArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 7] = m * (BSIM4v7entry.d_BSIM4v7grbpdArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbpsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbpbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 8] = m * (gcsbsb - BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 9] = m * BSIM4v7entry.d_BSIM4v7grbsbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 10] = m * (BSIM4v7entry.d_BSIM4v7gbsRWArray [instance_ID] - gcsbsb + BSIM4v7entry.d_BSIM4v7grbpsArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbsbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 11] = m * (BSIM4v7entry.d_BSIM4v7grbsbArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbdbArray [instance_ID] + BSIM4v7entry.d_BSIM4v7grbpbArray [instance_ID]) ; + + total_offset += 12 ; + } + + /* 94 - DIVERGENT */ + if (BSIM4v7entry.d_BSIM4v7trnqsModArray [instance_ID]) + { + d_CKTloadOutput [pos + total_offset + 0] = m * (gqdef + BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (ggtg - gcqgb) ; + + d_CKTloadOutput [pos + total_offset + 2] = m * (ggtd - gcqdb) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * (ggts - gcqsb) ; + + d_CKTloadOutput [pos + total_offset + 4] = m * (ggtb - gcqbb) ; + + d_CKTloadOutput [pos + total_offset + 5] = m * dxpart * BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 6] = m * sxpart * BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 7] = m * BSIM4v7entry.d_BSIM4v7gtauRWArray [instance_ID] ; + } + +line1000: ; + + } + } + + return ; +} diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7setup.c b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7setup.c new file mode 100644 index 000000000..6d015a12b --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7setup.c @@ -0,0 +1,1123 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "bsim4v7def.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuBSIM4v7setup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuBSIM4v7setup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuBSIM4v7setup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + BSIM4v7model *model = (BSIM4v7model *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size, int, status) + + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, size, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, size, int, status) + + /* DOUBLE */ + model->BSIM4v7paramCPU.BSIM4v7gbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vonRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vonRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vonRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vdsatRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vdsatRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vdsatRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7csubRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7csubRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csubRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gmRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gmRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gmRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gmbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gmbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gmbsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gcrgRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gcrgRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgidlRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgidlRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgidlRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgislRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgislRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgislRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgcsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgcsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgcsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgcdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgcdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgcdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qinvRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qinvRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qinvRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cggbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cggbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cggbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cgsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cgsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgsbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cgdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cgdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgdbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cdgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cdgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdgbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cdsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cdsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdsbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cddbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cddbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cddbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbgbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbsbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbdbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7csgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7csgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csgbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cssbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cssbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cssbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7csdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7csdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csdbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cgbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cgbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgbbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7csbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7csbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csbbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cdbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cdbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdbbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cbbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cbbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbbbRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gtauRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gtauRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtauRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qgateRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qgateRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgateRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qbulkRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qbulkRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qbulkRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qdrnRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qdrnRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qdrnRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qsrcRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qsrcRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qsrcRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7capbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7capbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7capbsRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7capbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7capbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7capbdRWArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7icVDSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7icVGSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7icVBSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vth0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vth0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vth0Array, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gbbsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gbbsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbbsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggidlbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggidlbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gbgsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gbgsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbgsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggidlgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggidlgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gbdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gbdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbdsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggidldArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggidldArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidldArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggislsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggislsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggislgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggislgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggislbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggislbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgsgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgsgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgsgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcsgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcsgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcsdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcsdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgdgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgdgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgdgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcdgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcdgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcddArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcddArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcddArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgbgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgbgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgbdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgbdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgbbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgbbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggidlsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggidlsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ggisldArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ggisldArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggisldArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gstotArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gstotArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gstotdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gstotdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gstotgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gstotgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gstotbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gstotbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdtotArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdtotArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdtotdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdtotdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdtotgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdtotgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdtotbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdtotbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cgdoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cgdoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgdoArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qgdoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qgdoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgdoArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cgsoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cgsoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgsoArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qgsoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qgsoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgsoArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7AseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7AseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AseffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7PseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7PseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7PseffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7nfArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7nfArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7nfArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7XExpBVSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7XExpBVSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVSArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vjsmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vjsmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjsmFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IVjsmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IVjsmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vjsmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vjsmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjsmRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IVjsmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IVjsmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SslpRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SslpRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SslpRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SslpFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SslpFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SslpFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7AdeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7AdeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AdeffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7PdeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7PdeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7PdeffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7XExpBVDArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7XExpBVDArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVDArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vjdmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vjdmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjdmFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IVjdmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IVjdmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vjdmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vjdmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjdmRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IVjdmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IVjdmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DslpRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DslpRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DslpRevArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DslpFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DslpFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DslpFwdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SjctTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SjctTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SjctTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SswTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SswTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SswTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SswgTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SswgTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SswgTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DjctTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DjctTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DjctTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DswTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DswTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DswTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DswgTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DswgTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DswgTempRevSatCurArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vbscArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vbscArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vbscArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7thetavthArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7thetavthArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7thetavthArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7eta0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7eta0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7eta0Array, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7k2oxArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7k2oxArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7k2oxArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7nstarArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7nstarArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7nstarArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vfbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vfbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vfbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vgs_effArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vgs_effArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vgs_effArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vgd_effArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vgd_effArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vgd_effArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7dvgs_eff_dvgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dvgs_eff_dvgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dvgs_eff_dvgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7dvgd_eff_dvgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dvgd_eff_dvgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dvgd_eff_dvgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7VgsteffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7VgsteffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7VgsteffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grdswArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grdswArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grdswArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7AbulkArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7AbulkArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AbulkArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vtfbphi1Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi1Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi1Array, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7ueffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7ueffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ueffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7u0tempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7u0tempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7u0tempArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vsattempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vsattempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vsattempArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7EsatLArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7EsatLArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7EsatLArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7VdseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7VdseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7VdseffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vtfbphi2Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi2Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi2Array, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7CoxeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7CoxeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7CoxeffArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7AbovVgst2VtmArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7AbovVgst2VtmArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AbovVgst2VtmArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7IdovVdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7IdovVdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IdovVdsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gcrgdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gcrgdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gcrgbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gcrgbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gcrggArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gcrggArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrggArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grgeltdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grgeltdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grgeltdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gcrgsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gcrgsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7sourceConductanceArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sourceConductanceArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sourceConductanceArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7drainConductanceArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7drainConductanceArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7drainConductanceArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gstotsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gstotsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gdtotsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gdtotsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7vfbzbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7vfbzbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vfbzbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgssArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgssArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgssArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgddArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgddArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgddArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgbsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgbsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcssArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcssArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcssArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gIgcdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gIgcdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7noiGd0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7noiGd0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7noiGd0Array, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cqdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cqdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqdbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cqsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cqsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqsbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cqgbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cqgbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqgbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qchqsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qchqsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qchqsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7cqbbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7cqbbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqbbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7taunetArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7taunetArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7taunetArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gtgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gtgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtgArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gtdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gtdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gtsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gtsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gtbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gtbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7mArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7mArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7mArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grbpdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grbpdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpdArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grbdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grbdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbdbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grbpbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grbpbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grbpsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grbpsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpsArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7grbsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7grbsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbsbArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7dNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodeExtRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodeMidRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7bNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7sNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7dbNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dbNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7sbNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sbNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7dNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7sNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7qNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qNodeRHSValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEgeValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPgeValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GEgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GEgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GEgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMgeValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GMbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GMbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GMbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPgmValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPdValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPdValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPdValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DdValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DdValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DdValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPsValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPsValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPsValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SsValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SsValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SsValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPdbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPsbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DBdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DBdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DBdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DBdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DBdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DBdbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DBbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DBbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DBbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DBbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DBbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DBbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPdbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPsbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BPbpIFValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BPbpIFValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BPbpIFValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SBspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SBspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SBspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SBbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SBbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SBbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SBbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SBbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SBbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SBsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SBsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SBsbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BdbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BsbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7BbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7BbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7BbValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7QqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7QqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7QqValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7QgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7QgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7QgpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7QdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7QdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7QdpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7QspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7QspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7QspValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7QbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7QbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7QbpValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7DPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7DPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DPqValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7SPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7SPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SPqValueArray, size, double, status) + + model->BSIM4v7paramCPU.BSIM4v7GPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7GPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7GPqValueArray, size, double, status) + + /* INT */ + model->BSIM4v7paramCPU.BSIM4v7offArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7offArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7offArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7dNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7sNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7bNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodeExtArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7gNodeMidArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7dbNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dbNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7sbNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sbNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7sNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7sNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7dNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7dNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7qNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7qNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qNodeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7rbodyModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7rbodyModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7rbodyModArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7modeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7modeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7modeArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7rgateModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7rgateModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7rgateModArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7trnqsModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7trnqsModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7trnqsModArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7acnqsModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7acnqsModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7acnqsModArray, size, int, status) + + model->BSIM4v7paramCPU.BSIM4v7statesArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4v7paramGPU.d_BSIM4v7statesArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4v7paramGPU.d_BSIM4v7statesArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7temp.c b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7temp.c new file mode 100644 index 000000000..0c07a9a22 --- /dev/null +++ b/src/spicelib/devices/bsim4v7/CUSPICE/cubsim4v7temp.c @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "bsim4v7def.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuBSIM4v7temp routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuBSIM4v7temp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuBSIM4v7temp +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size ; + cudaError_t status ; + BSIM4v7model *model = (BSIM4v7model *)inModel ; + BSIM4v7instance *here ; + + size = (long unsigned int) model->n_instances; + + /* Special case here->d_pParam */ + model->pParamHost = (struct bsim4SizeDependParam **) malloc (size * sizeof(struct bsim4SizeDependParam *)) ; + status = cudaMalloc ((void **)&(model->d_pParam), size * sizeof(struct bsim4SizeDependParam *)) ; + CUDAMALLOCCHECK (model->d_pParam, size, struct bsim4SizeDependParam *, status) + + i = 0 ; + + for (here = BSIM4v7instances(model); here != NULL ; here = BSIM4v7nextInstance(here)) + { + if (here->pParam != NULL) + { + status = cudaMalloc ((void **)&(model->pParamHost [i]), sizeof(struct bsim4SizeDependParam)) ; + CUDAMALLOCCHECK (model->pParamHost [i], 1, struct bsim4SizeDependParam, status) + + status = cudaMemcpy (model->pParamHost [i], here->pParam, sizeof(struct bsim4SizeDependParam), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->pParamHost [i], 1, struct bsim4SizeDependParam, status) + } + else + model->pParamHost [i] = NULL ; + + i++ ; + } + + /* Structure pointer vectors in GPU */ + status = cudaMemcpy (model->d_pParam, model->pParamHost, size * sizeof(struct bsim4SizeDependParam *), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_pParam, size, struct bsim4SizeDependParam *, status) + /* -------------------------------- */ + + /* DOUBLE */ + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gbsRWArray, model->BSIM4v7paramCPU.BSIM4v7gbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbsRWArray, model->BSIM4v7paramCPU.BSIM4v7cbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gbdRWArray, model->BSIM4v7paramCPU.BSIM4v7gbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbdRWArray, model->BSIM4v7paramCPU.BSIM4v7cbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vonRWArray, model->BSIM4v7paramCPU.BSIM4v7vonRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vonRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vdsatRWArray, model->BSIM4v7paramCPU.BSIM4v7vdsatRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vdsatRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7csubRWArray, model->BSIM4v7paramCPU.BSIM4v7csubRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csubRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdsRWArray, model->BSIM4v7paramCPU.BSIM4v7gdsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gmRWArray, model->BSIM4v7paramCPU.BSIM4v7gmRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gmRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gmbsRWArray, model->BSIM4v7paramCPU.BSIM4v7gmbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gmbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gcrgRWArray, model->BSIM4v7paramCPU.BSIM4v7gcrgRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgidlRWArray, model->BSIM4v7paramCPU.BSIM4v7IgidlRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgidlRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgislRWArray, model->BSIM4v7paramCPU.BSIM4v7IgislRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgislRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgcsRWArray, model->BSIM4v7paramCPU.BSIM4v7IgcsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgcsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgcdRWArray, model->BSIM4v7paramCPU.BSIM4v7IgcdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgcdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgsRWArray, model->BSIM4v7paramCPU.BSIM4v7IgsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgdRWArray, model->BSIM4v7paramCPU.BSIM4v7IgdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IgbRWArray, model->BSIM4v7paramCPU.BSIM4v7IgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cdRWArray, model->BSIM4v7paramCPU.BSIM4v7cdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qinvRWArray, model->BSIM4v7paramCPU.BSIM4v7qinvRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qinvRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cggbRWArray, model->BSIM4v7paramCPU.BSIM4v7cggbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cggbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cgsbRWArray, model->BSIM4v7paramCPU.BSIM4v7cgsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cgdbRWArray, model->BSIM4v7paramCPU.BSIM4v7cgdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cdgbRWArray, model->BSIM4v7paramCPU.BSIM4v7cdgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cdsbRWArray, model->BSIM4v7paramCPU.BSIM4v7cdsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cddbRWArray, model->BSIM4v7paramCPU.BSIM4v7cddbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cddbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbgbRWArray, model->BSIM4v7paramCPU.BSIM4v7cbgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbsbRWArray, model->BSIM4v7paramCPU.BSIM4v7cbsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbdbRWArray, model->BSIM4v7paramCPU.BSIM4v7cbdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7csgbRWArray, model->BSIM4v7paramCPU.BSIM4v7csgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cssbRWArray, model->BSIM4v7paramCPU.BSIM4v7cssbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cssbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7csdbRWArray, model->BSIM4v7paramCPU.BSIM4v7csdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cgbbRWArray, model->BSIM4v7paramCPU.BSIM4v7cgbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7csbbRWArray, model->BSIM4v7paramCPU.BSIM4v7csbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7csbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cdbbRWArray, model->BSIM4v7paramCPU.BSIM4v7cdbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cdbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cbbbRWArray, model->BSIM4v7paramCPU.BSIM4v7cbbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cbbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gtauRWArray, model->BSIM4v7paramCPU.BSIM4v7gtauRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtauRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qgateRWArray, model->BSIM4v7paramCPU.BSIM4v7qgateRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgateRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qbulkRWArray, model->BSIM4v7paramCPU.BSIM4v7qbulkRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qbulkRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qdrnRWArray, model->BSIM4v7paramCPU.BSIM4v7qdrnRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qdrnRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qsrcRWArray, model->BSIM4v7paramCPU.BSIM4v7qsrcRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qsrcRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7capbsRWArray, model->BSIM4v7paramCPU.BSIM4v7capbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7capbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7capbdRWArray, model->BSIM4v7paramCPU.BSIM4v7capbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7capbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray, model->BSIM4v7paramCPU.BSIM4v7icVDSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVDSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray, model->BSIM4v7paramCPU.BSIM4v7icVGSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVGSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray, model->BSIM4v7paramCPU.BSIM4v7icVBSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7icVBSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vth0Array, model->BSIM4v7paramCPU.BSIM4v7vth0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vth0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gbbsArray, model->BSIM4v7paramCPU.BSIM4v7gbbsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbbsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggidlbArray, model->BSIM4v7paramCPU.BSIM4v7ggidlbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gbgsArray, model->BSIM4v7paramCPU.BSIM4v7gbgsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbgsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggidlgArray, model->BSIM4v7paramCPU.BSIM4v7ggidlgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gbdsArray, model->BSIM4v7paramCPU.BSIM4v7gbdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gbdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggidldArray, model->BSIM4v7paramCPU.BSIM4v7ggidldArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidldArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggislsArray, model->BSIM4v7paramCPU.BSIM4v7ggislsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggislgArray, model->BSIM4v7paramCPU.BSIM4v7ggislgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggislbArray, model->BSIM4v7paramCPU.BSIM4v7ggislbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggislbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgsgArray, model->BSIM4v7paramCPU.BSIM4v7gIgsgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgsgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsgArray, model->BSIM4v7paramCPU.BSIM4v7gIgcsgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsdArray, model->BSIM4v7paramCPU.BSIM4v7gIgcsdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsbArray, model->BSIM4v7paramCPU.BSIM4v7gIgcsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcsbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgdgArray, model->BSIM4v7paramCPU.BSIM4v7gIgdgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgdgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdgArray, model->BSIM4v7paramCPU.BSIM4v7gIgcdgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcddArray, model->BSIM4v7paramCPU.BSIM4v7gIgcddArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcddArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdbArray, model->BSIM4v7paramCPU.BSIM4v7gIgcdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgbgArray, model->BSIM4v7paramCPU.BSIM4v7gIgbgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgbdArray, model->BSIM4v7paramCPU.BSIM4v7gIgbdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgbbArray, model->BSIM4v7paramCPU.BSIM4v7gIgbbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggidlsArray, model->BSIM4v7paramCPU.BSIM4v7ggidlsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggidlsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ggisldArray, model->BSIM4v7paramCPU.BSIM4v7ggisldArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ggisldArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gstotArray, model->BSIM4v7paramCPU.BSIM4v7gstotArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gstotdArray, model->BSIM4v7paramCPU.BSIM4v7gstotdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gstotgArray, model->BSIM4v7paramCPU.BSIM4v7gstotgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gstotbArray, model->BSIM4v7paramCPU.BSIM4v7gstotbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdtotArray, model->BSIM4v7paramCPU.BSIM4v7gdtotArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdtotdArray, model->BSIM4v7paramCPU.BSIM4v7gdtotdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdtotgArray, model->BSIM4v7paramCPU.BSIM4v7gdtotgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdtotbArray, model->BSIM4v7paramCPU.BSIM4v7gdtotbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cgdoArray, model->BSIM4v7paramCPU.BSIM4v7cgdoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgdoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qgdoArray, model->BSIM4v7paramCPU.BSIM4v7qgdoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgdoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cgsoArray, model->BSIM4v7paramCPU.BSIM4v7cgsoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cgsoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qgsoArray, model->BSIM4v7paramCPU.BSIM4v7qgsoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qgsoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7AseffArray, model->BSIM4v7paramCPU.BSIM4v7AseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7PseffArray, model->BSIM4v7paramCPU.BSIM4v7PseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7PseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7nfArray, model->BSIM4v7paramCPU.BSIM4v7nfArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7nfArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVSArray, model->BSIM4v7paramCPU.BSIM4v7XExpBVSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vjsmFwdArray, model->BSIM4v7paramCPU.BSIM4v7vjsmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjsmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmFwdArray, model->BSIM4v7paramCPU.BSIM4v7IVjsmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vjsmRevArray, model->BSIM4v7paramCPU.BSIM4v7vjsmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjsmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmRevArray, model->BSIM4v7paramCPU.BSIM4v7IVjsmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjsmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7SslpRevArray, model->BSIM4v7paramCPU.BSIM4v7SslpRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SslpRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7SslpFwdArray, model->BSIM4v7paramCPU.BSIM4v7SslpFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SslpFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7AdeffArray, model->BSIM4v7paramCPU.BSIM4v7AdeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AdeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7PdeffArray, model->BSIM4v7paramCPU.BSIM4v7PdeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7PdeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVDArray, model->BSIM4v7paramCPU.BSIM4v7XExpBVDArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7XExpBVDArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vjdmFwdArray, model->BSIM4v7paramCPU.BSIM4v7vjdmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjdmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmFwdArray, model->BSIM4v7paramCPU.BSIM4v7IVjdmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vjdmRevArray, model->BSIM4v7paramCPU.BSIM4v7vjdmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vjdmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmRevArray, model->BSIM4v7paramCPU.BSIM4v7IVjdmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IVjdmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7DslpRevArray, model->BSIM4v7paramCPU.BSIM4v7DslpRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DslpRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7DslpFwdArray, model->BSIM4v7paramCPU.BSIM4v7DslpFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DslpFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7SjctTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7SjctTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SjctTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7SswTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7SswTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SswTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7SswgTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7SswgTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7SswgTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7DjctTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7DjctTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DjctTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7DswTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7DswTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DswTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7DswgTempRevSatCurArray, model->BSIM4v7paramCPU.BSIM4v7DswgTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7DswgTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vbscArray, model->BSIM4v7paramCPU.BSIM4v7vbscArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vbscArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7thetavthArray, model->BSIM4v7paramCPU.BSIM4v7thetavthArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7thetavthArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7eta0Array, model->BSIM4v7paramCPU.BSIM4v7eta0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7eta0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7k2oxArray, model->BSIM4v7paramCPU.BSIM4v7k2oxArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7k2oxArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7nstarArray, model->BSIM4v7paramCPU.BSIM4v7nstarArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7nstarArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vfbArray, model->BSIM4v7paramCPU.BSIM4v7vfbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vfbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vgs_effArray, model->BSIM4v7paramCPU.BSIM4v7vgs_effArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vgs_effArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vgd_effArray, model->BSIM4v7paramCPU.BSIM4v7vgd_effArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vgd_effArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7dvgs_eff_dvgArray, model->BSIM4v7paramCPU.BSIM4v7dvgs_eff_dvgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dvgs_eff_dvgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7dvgd_eff_dvgArray, model->BSIM4v7paramCPU.BSIM4v7dvgd_eff_dvgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dvgd_eff_dvgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7VgsteffArray, model->BSIM4v7paramCPU.BSIM4v7VgsteffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7VgsteffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grdswArray, model->BSIM4v7paramCPU.BSIM4v7grdswArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grdswArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7AbulkArray, model->BSIM4v7paramCPU.BSIM4v7AbulkArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AbulkArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi1Array, model->BSIM4v7paramCPU.BSIM4v7vtfbphi1Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi1Array, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7ueffArray, model->BSIM4v7paramCPU.BSIM4v7ueffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7ueffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7u0tempArray, model->BSIM4v7paramCPU.BSIM4v7u0tempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7u0tempArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vsattempArray, model->BSIM4v7paramCPU.BSIM4v7vsattempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vsattempArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7EsatLArray, model->BSIM4v7paramCPU.BSIM4v7EsatLArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7EsatLArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7VdseffArray, model->BSIM4v7paramCPU.BSIM4v7VdseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7VdseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi2Array, model->BSIM4v7paramCPU.BSIM4v7vtfbphi2Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vtfbphi2Array, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7CoxeffArray, model->BSIM4v7paramCPU.BSIM4v7CoxeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7CoxeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7AbovVgst2VtmArray, model->BSIM4v7paramCPU.BSIM4v7AbovVgst2VtmArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7AbovVgst2VtmArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7IdovVdsArray, model->BSIM4v7paramCPU.BSIM4v7IdovVdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7IdovVdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gcrgdArray, model->BSIM4v7paramCPU.BSIM4v7gcrgdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gcrgbArray, model->BSIM4v7paramCPU.BSIM4v7gcrgbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gcrggArray, model->BSIM4v7paramCPU.BSIM4v7gcrggArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrggArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grgeltdArray, model->BSIM4v7paramCPU.BSIM4v7grgeltdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grgeltdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gcrgsArray, model->BSIM4v7paramCPU.BSIM4v7gcrgsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gcrgsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7sourceConductanceArray, model->BSIM4v7paramCPU.BSIM4v7sourceConductanceArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sourceConductanceArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7drainConductanceArray, model->BSIM4v7paramCPU.BSIM4v7drainConductanceArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7drainConductanceArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gstotsArray, model->BSIM4v7paramCPU.BSIM4v7gstotsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gstotsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gdtotsArray, model->BSIM4v7paramCPU.BSIM4v7gdtotsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gdtotsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7vfbzbArray, model->BSIM4v7paramCPU.BSIM4v7vfbzbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7vfbzbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgssArray, model->BSIM4v7paramCPU.BSIM4v7gIgssArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgssArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgddArray, model->BSIM4v7paramCPU.BSIM4v7gIgddArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgddArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgbsArray, model->BSIM4v7paramCPU.BSIM4v7gIgbsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgbsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcssArray, model->BSIM4v7paramCPU.BSIM4v7gIgcssArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcssArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdsArray, model->BSIM4v7paramCPU.BSIM4v7gIgcdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gIgcdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7noiGd0Array, model->BSIM4v7paramCPU.BSIM4v7noiGd0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7noiGd0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cqdbArray, model->BSIM4v7paramCPU.BSIM4v7cqdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cqsbArray, model->BSIM4v7paramCPU.BSIM4v7cqsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqsbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cqgbArray, model->BSIM4v7paramCPU.BSIM4v7cqgbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqgbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qchqsArray, model->BSIM4v7paramCPU.BSIM4v7qchqsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qchqsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7cqbbArray, model->BSIM4v7paramCPU.BSIM4v7cqbbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7cqbbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7taunetArray, model->BSIM4v7paramCPU.BSIM4v7taunetArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7taunetArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gtgArray, model->BSIM4v7paramCPU.BSIM4v7gtgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gtdArray, model->BSIM4v7paramCPU.BSIM4v7gtdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gtsArray, model->BSIM4v7paramCPU.BSIM4v7gtsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gtbArray, model->BSIM4v7paramCPU.BSIM4v7gtbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gtbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7mArray, model->BSIM4v7paramCPU.BSIM4v7mArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7mArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grbpdArray, model->BSIM4v7paramCPU.BSIM4v7grbpdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grbdbArray, model->BSIM4v7paramCPU.BSIM4v7grbdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grbpbArray, model->BSIM4v7paramCPU.BSIM4v7grbpbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grbpsArray, model->BSIM4v7paramCPU.BSIM4v7grbpsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbpsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7grbsbArray, model->BSIM4v7paramCPU.BSIM4v7grbsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7grbsbArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7offArray, model->BSIM4v7paramCPU.BSIM4v7offArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7offArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeArray, model->BSIM4v7paramCPU.BSIM4v7dNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeArray, model->BSIM4v7paramCPU.BSIM4v7sNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeArray, model->BSIM4v7paramCPU.BSIM4v7gNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeArray, model->BSIM4v7paramCPU.BSIM4v7bNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7bNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtArray, model->BSIM4v7paramCPU.BSIM4v7gNodeExtArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeExtArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidArray, model->BSIM4v7paramCPU.BSIM4v7gNodeMidArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7gNodeMidArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeArray, model->BSIM4v7paramCPU.BSIM4v7dbNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dbNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeArray, model->BSIM4v7paramCPU.BSIM4v7sbNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sbNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7sNodeArray, model->BSIM4v7paramCPU.BSIM4v7sNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7sNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7dNodeArray, model->BSIM4v7paramCPU.BSIM4v7dNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7dNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7qNodeArray, model->BSIM4v7paramCPU.BSIM4v7qNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7qNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7rbodyModArray, model->BSIM4v7paramCPU.BSIM4v7rbodyModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7rbodyModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7modeArray, model->BSIM4v7paramCPU.BSIM4v7modeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7modeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7rgateModArray, model->BSIM4v7paramCPU.BSIM4v7rgateModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7rgateModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7trnqsModArray, model->BSIM4v7paramCPU.BSIM4v7trnqsModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7trnqsModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7acnqsModArray, model->BSIM4v7paramCPU.BSIM4v7acnqsModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.d_BSIM4v7acnqsModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4v7paramGPU.d_BSIM4v7statesArray, model->BSIM4v7paramCPU.BSIM4v7statesArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4v7paramGPU.BSIM4v7statesArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4v7/Makefile.am b/src/spicelib/devices/bsim4v7/Makefile.am index b763ee5cd..52cfec744 100644 --- a/src/spicelib/devices/bsim4v7/Makefile.am +++ b/src/spicelib/devices/bsim4v7/Makefile.am @@ -37,6 +37,21 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libbsim4v7_la_SOURCES += \ + CUSPICE/b4v7topology.c \ + CUSPICE/cubsim4v7free.c \ + CUSPICE/cubsim4v7getic.c \ + CUSPICE/cubsim4v7load.cu \ + CUSPICE/cubsim4v7setup.c \ + CUSPICE/cubsim4v7temp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = B4TERMS_OF_USE diff --git a/src/spicelib/devices/bsim4v7/b4v7getic.c b/src/spicelib/devices/bsim4v7/b4v7getic.c index 553a41366..fce7c3ba1 100644 --- a/src/spicelib/devices/bsim4v7/b4v7getic.c +++ b/src/spicelib/devices/bsim4v7/b4v7getic.c @@ -16,6 +16,9 @@ #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif int BSIM4v7getic( @@ -25,8 +28,17 @@ CKTcircuit *ckt) BSIM4v7model *model = (BSIM4v7model*)inModel; BSIM4v7instance *here; - for (; model ; model = BSIM4v7nextModel(model)) - { for (here = BSIM4v7instances(model); here; here = BSIM4v7nextInstance(here)) +#ifdef USE_CUSPICE + int i, status; +#endif + + for (; model; model = BSIM4v7nextModel(model)) { + +#ifdef USE_CUSPICE + i = 0; +#endif + + for (here = BSIM4v7instances(model); here; here = BSIM4v7nextInstance(here)) { if (!here->BSIM4v7icVDSGiven) { here->BSIM4v7icVDS = *(ckt->CKTrhs + here->BSIM4v7dNode) @@ -40,7 +52,23 @@ BSIM4v7instance *here; { here->BSIM4v7icVBS = *(ckt->CKTrhs + here->BSIM4v7bNode) - *(ckt->CKTrhs + here->BSIM4v7sNode); } + +#ifdef USE_CUSPICE + model->BSIM4v7paramCPU.BSIM4v7icVDSArray [i] = here->BSIM4v7icVDS; + model->BSIM4v7paramCPU.BSIM4v7icVGSArray [i] = here->BSIM4v7icVGS; + model->BSIM4v7paramCPU.BSIM4v7icVBSArray [i] = here->BSIM4v7icVBS; + + i++; +#endif + } + +#ifdef USE_CUSPICE + status = cuBSIM4v7getic ((GENmodel *)model); + if (status != 0) + return E_NOMEM; +#endif + } return(OK); } diff --git a/src/spicelib/devices/bsim4v7/b4v7set.c b/src/spicelib/devices/bsim4v7/b4v7set.c index f768d7fb3..15c88abdb 100644 --- a/src/spicelib/devices/bsim4v7/b4v7set.c +++ b/src/spicelib/devices/bsim4v7/b4v7set.c @@ -35,6 +35,10 @@ #include "ngspice/cpextern.h" #endif +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + #define MAX_EXP 5.834617425e14 #define MIN_EXP 1.713908431e-15 #define EXP_THRESHOLD 34.0 @@ -2582,6 +2586,568 @@ do { if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NUL } } +#ifdef USE_CUSPICE + int i, j, jRHS, l, lRHS, status ; + + /* Counting the instances */ + for (model = (BSIM4v7model *)inModel ; model != NULL ; model = BSIM4v7nextModel(model)) + { + i = 0 ; + + for (here = BSIM4v7instances(model); here != NULL ; here = BSIM4v7nextInstance(here)) + { + i++ ; + } + + /* How much instances we have */ + model->n_instances = i ; + } + + /* loop through all the BSIM4v7 models */ + for (model = (BSIM4v7model *)inModel ; model != NULL ; model = BSIM4v7nextModel(model)) + { + /* Position Vector Allocation */ + model->PositionVector = TMALLOC (int, model->n_instances) ; + + /* Position Vector Allocation for the RHS */ + model->PositionVectorRHS = TMALLOC (int, model->n_instances) ; + + + model->offset = ckt->total_n_values ; + model->offsetRHS = ckt->total_n_valuesRHS ; + + i = 0 ; + j = 0 ; + jRHS = 0 ; + l = 0 ; + lRHS = 0 ; + + /* loop through all the instances of the model */ + for (here = BSIM4v7instances(model); here != NULL ; here = BSIM4v7nextInstance(here)) + { + /* Position Vector Assignment */ + model->PositionVector [i] = model->offset + l ; + + /* Position Vector Assignment for the RHS */ + model->PositionVectorRHS [i] = model->offsetRHS + lRHS ; + + + /* For the Matrix */ + if (here->BSIM4v7rgateMod == 1) + { + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * geltd */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcggb + geltd - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 5 ; + } + else if (here->BSIM4v7rgateMod == 2) + { + /* m * gcrg */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * gcrgg */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * gcrgd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * gcrgs */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * gcrgb */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * gcrg */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 9 ; + } + else if (here->BSIM4v7rgateMod == 3) + { + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * geltd */ + if ((here->BSIM4v7gNodeExt != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * geltd */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodeExt != 0)) + j++ ; + + /* m * (geltd + gcrg + gcgmgmb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * (gcrgd + gcgmdb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * gcrgg */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcrgs + gcgmsb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gcrgb + gcgmbb) */ + if ((here->BSIM4v7gNodeMid != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * gcdgmb */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * gcrg */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * gcsgmb */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * gcbgmb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7gNodeMid != 0)) + j++ ; + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 14 ; + } else { + /* m * (gcggb - ggtg + gIgtotg) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 4 ; + } + + + if (model->BSIM4v7rdsMod) + { + /* m * gdtotg */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * gdtots */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * gdtotb */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * gstotd */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * gstotg */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * gstotb */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 4 ; + } + + + /* m * (gdpr + here->BSIM4v7gds + here->BSIM4v7gbd + T1 * ddxpart_dVd - + gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd) + m * ggidld */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dNode != 0)) + j++ ; + + /* m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + dxpart * ggtg + T1 * ddxpart_dVg) + m * ggidlg */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (here->BSIM4v7gds + gdtots - dxpart * ggts + gIdtots - + T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp) + m * (ggidlg + ggidld + ggidlb) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb - T1 * ddxpart_dVb - dxpart * ggtb) - m * ggidlb */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * (gdpr - gdtotd) */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4v7dNode != 0) && (here->BSIM4v7dNode != 0)) + j++ ; + + /* m * (here->BSIM4v7gds + gstotd + RevSum - gcsdb - gbspdp - + T1 * dsxpart_dVd - sxpart * ggtd + gIstotd) + m * (ggisls + ggislg + ggislb) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + T1 * dsxpart_dVg - gIstotg) + m * ggislg */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gspr + here->BSIM4v7gds + here->BSIM4v7gbs + T1 * dsxpart_dVs - + gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots) + m * ggisls */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gspr + gstot) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sNode != 0)) + j++ ; + + /* m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb - T1 * dsxpart_dVb + gIstotb) - m * ggislb */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * (gspr - gstots) */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gspr + gstot) */ + if ((here->BSIM4v7sNode != 0) && (here->BSIM4v7sNode != 0)) + j++ ; + + /* m * (gcbdb - gjbd + gbbdp - gIbtotd) - m * ggidld + m * (ggislg + ggisls + ggislb) */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (gcbgb - here->BSIM4v7gbgs - gIbtotg) - m * ggidlg - m * ggislg */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (gcbsb - gjbs + gbbsp - gIbtots) + m * (ggidlg + ggidld + ggidlb) - m * ggisls */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (gjbd + gjbs + gcbbb - here->BSIM4v7gbbs - gIbtotb) - m * ggidlb - m * ggislb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 16 ; + + + if (here->BSIM4v7rbodyMod) + { + /* m * (gcdbdb - here->BSIM4v7gbd) */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7dbNode != 0)) + j++ ; + + /* m * (here->BSIM4v7gbs - gcsbsb) */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7sbNode != 0)) + j++ ; + + /* m * (gcdbdb - here->BSIM4v7gbd) */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (here->BSIM4v7gbd - gcdbdb + here->BSIM4v7grbpd + here->BSIM4v7grbdb) */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7dbNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbpd */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * here->BSIM4v7grbdb */ + if ((here->BSIM4v7dbNode != 0) && (here->BSIM4v7bNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbpd */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7dbNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbpb */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbps */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7sbNode != 0)) + j++ ; + + /* m * (here->BSIM4v7grbpd + here->BSIM4v7grbps + here->BSIM4v7grbpb) */ + if ((here->BSIM4v7bNodePrime != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * (gcsbsb - here->BSIM4v7gbs) */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * here->BSIM4v7grbps */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * here->BSIM4v7grbsb */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7bNode != 0)) + j++ ; + + /* m * (here->BSIM4v7gbs - gcsbsb + here->BSIM4v7grbps + here->BSIM4v7grbsb) */ + if ((here->BSIM4v7sbNode != 0) && (here->BSIM4v7sbNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbdb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7dbNode != 0)) + j++ ; + + /* m * here->BSIM4v7grbpb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * here->BSIM4v7grbsb */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7sbNode != 0)) + j++ ; + + /* m * (here->BSIM4v7grbsb + here->BSIM4v7grbdb + here->BSIM4v7grbpb) */ + if ((here->BSIM4v7bNode != 0) && (here->BSIM4v7bNode != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 12 ; + } + + + if (here->BSIM4v7trnqsMod) + { + /* m * (gqdef + here->BSIM4v7gtau) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7qNode != 0)) + j++ ; + + /* m * (ggtg - gcqgb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7gNodePrime != 0)) + j++ ; + + /* m * (ggtd - gcqdb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7dNodePrime != 0)) + j++ ; + + /* m * (ggts - gcqsb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7sNodePrime != 0)) + j++ ; + + /* m * (ggtb - gcqbb) */ + if ((here->BSIM4v7qNode != 0) && (here->BSIM4v7bNodePrime != 0)) + j++ ; + + /* m * dxpart * here->BSIM4v7gtau */ + if ((here->BSIM4v7dNodePrime != 0) && (here->BSIM4v7qNode != 0)) + j++ ; + + /* m * sxpart * here->BSIM4v7gtau */ + if ((here->BSIM4v7sNodePrime != 0) && (here->BSIM4v7qNode != 0)) + j++ ; + + /* m * here->BSIM4v7gtau */ + if ((here->BSIM4v7gNodePrime != 0) && (here->BSIM4v7qNode != 0)) + j++ ; + + /* Different Values for the CKTloadOutput */ + l += 8 ; + } + + + /* For the RHS */ + /* m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq) */ + if (here->BSIM4v7dNodePrime != 0) + jRHS++ ; + + /* m * (ceqqg - ceqgcrg + Igtoteq) */ + if (here->BSIM4v7gNodePrime != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 2 ; + + + if (here->BSIM4v7rgateMod == 2) + { + /* m * ceqgcrg */ + if (here->BSIM4v7gNodeExt != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 1 ; + } + else if (here->BSIM4v7rgateMod == 3) + { + /* m * (ceqqgmid + ceqgcrg) */ + if (here->BSIM4v7gNodeMid != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 1 ; + } + + + if (!here->BSIM4v7rbodyMod) + { + /* m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq) */ + if (here->BSIM4v7bNodePrime != 0) + jRHS++ ; + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4v7sNodePrime != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 2 ; + } else { + /* m * (ceqjd + ceqqjd) */ + if (here->BSIM4v7dbNode != 0) + jRHS++ ; + + /* m * (ceqbd + ceqbs - ceqqb + Ibtoteq) */ + if (here->BSIM4v7bNodePrime != 0) + jRHS++ ; + + /* m * (ceqjs + ceqqjs) */ + if (here->BSIM4v7sbNode != 0) + jRHS++ ; + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4v7sNodePrime != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 4 ; + } + + + if (model->BSIM4v7rdsMod) + { + /* m * ceqgdtot */ + if (here->BSIM4v7dNode != 0) + jRHS++ ; + + /* m * ceqgstot */ + if (here->BSIM4v7sNode != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 2 ; + } + + + if (here->BSIM4v7trnqsMod) + { + /* m * (cqcheq - cqdef) */ + if (here->BSIM4v7qNode != 0) + jRHS++ ; + + /* Different Values for the CKTloadOutputRHS */ + lRHS += 1 ; + } + + i++ ; + } + + model->n_values = l ; + ckt->total_n_values += model->n_values ; + + model->n_Ptr = j ; + ckt->total_n_Ptr += model->n_Ptr ; + + model->n_valuesRHS = lRHS ; + ckt->total_n_valuesRHS += model->n_valuesRHS ; + + model->n_PtrRHS = jRHS ; + ckt->total_n_PtrRHS += model->n_PtrRHS ; + } + + /* loop through all the BSIM4v7 models */ + for (model = (BSIM4v7model *)inModel ; model != NULL ; model = BSIM4v7nextModel(model)) + { + status = cuBSIM4v7setup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } +#endif + #ifdef USE_OMP InstCount = 0; model = (BSIM4v7model*)inModel; diff --git a/src/spicelib/devices/bsim4v7/b4v7temp.c b/src/spicelib/devices/bsim4v7/b4v7temp.c index 2cbc3f477..14a7661e8 100644 --- a/src/spicelib/devices/bsim4v7/b4v7temp.c +++ b/src/spicelib/devices/bsim4v7/b4v7temp.c @@ -30,6 +30,10 @@ #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + #define Kb 1.3806226e-23 #define KboQ 8.617087e-5 #define EPS0 8.85418e-12 @@ -91,6 +95,10 @@ double vtfbphi2eot, phieot, TempRatioeot, Vtm0eot, Vtmeot,vbieot; int Size_Not_Found, i; +#ifdef USE_CUSPICE + int j, status; +#endif + /* loop through all the BSIM4v7 device models */ for (; model != NULL; model = BSIM4v7nextModel(model)) { Temp = ckt->CKTtemp; @@ -404,6 +412,9 @@ int Size_Not_Found, i; fprintf(stderr, "BVS reset to %g.\n", model->BSIM4v7bvs); } +#ifdef USE_CUSPICE + j = 0; +#endif /* loop through all the instances of the model */ for (here = BSIM4v7instances(model); here != NULL; @@ -2309,7 +2320,199 @@ int Size_Not_Found, i; SPfrontEnd->IFerrorf (ERR_FATAL, "Fatal error(s) detected during BSIM4v7.6.0 parameter checking for %s in model %s", model->BSIM4v7modName, here->BSIM4v7name); return(E_BADPARM); } + +#ifdef USE_CUSPICE + model->BSIM4v7paramCPU.BSIM4v7gbsRWArray [j] = here->BSIM4v7gbs; + model->BSIM4v7paramCPU.BSIM4v7cbsRWArray [j] = here->BSIM4v7cbs; + model->BSIM4v7paramCPU.BSIM4v7gbdRWArray [j] = here->BSIM4v7gbd; + model->BSIM4v7paramCPU.BSIM4v7cbdRWArray [j] = here->BSIM4v7cbd; + model->BSIM4v7paramCPU.BSIM4v7vonRWArray [j] = here->BSIM4v7von; + model->BSIM4v7paramCPU.BSIM4v7vdsatRWArray [j] = here->BSIM4v7vdsat; + model->BSIM4v7paramCPU.BSIM4v7csubRWArray [j] = here->BSIM4v7csub; + model->BSIM4v7paramCPU.BSIM4v7gdsRWArray [j] = here->BSIM4v7gds; + model->BSIM4v7paramCPU.BSIM4v7gmRWArray [j] = here->BSIM4v7gm; + model->BSIM4v7paramCPU.BSIM4v7gmbsRWArray [j] = here->BSIM4v7gmbs; + model->BSIM4v7paramCPU.BSIM4v7gcrgRWArray [j] = here->BSIM4v7gcrg; + model->BSIM4v7paramCPU.BSIM4v7IgidlRWArray [j] = here->BSIM4v7Igidl; + model->BSIM4v7paramCPU.BSIM4v7IgislRWArray [j] = here->BSIM4v7Igisl; + model->BSIM4v7paramCPU.BSIM4v7IgcsRWArray [j] = here->BSIM4v7Igcs; + model->BSIM4v7paramCPU.BSIM4v7IgcdRWArray [j] = here->BSIM4v7Igcd; + model->BSIM4v7paramCPU.BSIM4v7IgsRWArray [j] = here->BSIM4v7Igs; + model->BSIM4v7paramCPU.BSIM4v7IgdRWArray [j] = here->BSIM4v7Igd; + model->BSIM4v7paramCPU.BSIM4v7IgbRWArray [j] = here->BSIM4v7Igb; + model->BSIM4v7paramCPU.BSIM4v7cdRWArray [j] = here->BSIM4v7cd; + model->BSIM4v7paramCPU.BSIM4v7qinvRWArray [j] = here->BSIM4v7qinv; + model->BSIM4v7paramCPU.BSIM4v7cggbRWArray [j] = here->BSIM4v7cggb; + model->BSIM4v7paramCPU.BSIM4v7cgsbRWArray [j] = here->BSIM4v7cgsb; + model->BSIM4v7paramCPU.BSIM4v7cgdbRWArray [j] = here->BSIM4v7cgdb; + model->BSIM4v7paramCPU.BSIM4v7cdgbRWArray [j] = here->BSIM4v7cdgb; + model->BSIM4v7paramCPU.BSIM4v7cdsbRWArray [j] = here->BSIM4v7cdsb; + model->BSIM4v7paramCPU.BSIM4v7cddbRWArray [j] = here->BSIM4v7cddb; + model->BSIM4v7paramCPU.BSIM4v7cbgbRWArray [j] = here->BSIM4v7cbgb; + model->BSIM4v7paramCPU.BSIM4v7cbsbRWArray [j] = here->BSIM4v7cbsb; + model->BSIM4v7paramCPU.BSIM4v7cbdbRWArray [j] = here->BSIM4v7cbdb; + model->BSIM4v7paramCPU.BSIM4v7csgbRWArray [j] = here->BSIM4v7csgb; + model->BSIM4v7paramCPU.BSIM4v7cssbRWArray [j] = here->BSIM4v7cssb; + model->BSIM4v7paramCPU.BSIM4v7csdbRWArray [j] = here->BSIM4v7csdb; + model->BSIM4v7paramCPU.BSIM4v7cgbbRWArray [j] = here->BSIM4v7cgbb; + model->BSIM4v7paramCPU.BSIM4v7csbbRWArray [j] = here->BSIM4v7csbb; + model->BSIM4v7paramCPU.BSIM4v7cdbbRWArray [j] = here->BSIM4v7cdbb; + model->BSIM4v7paramCPU.BSIM4v7cbbbRWArray [j] = here->BSIM4v7cbbb; + model->BSIM4v7paramCPU.BSIM4v7gtauRWArray [j] = here->BSIM4v7gtau; + model->BSIM4v7paramCPU.BSIM4v7qgateRWArray [j] = here->BSIM4v7qgate; + model->BSIM4v7paramCPU.BSIM4v7qbulkRWArray [j] = here->BSIM4v7qbulk; + model->BSIM4v7paramCPU.BSIM4v7qdrnRWArray [j] = here->BSIM4v7qdrn; + model->BSIM4v7paramCPU.BSIM4v7qsrcRWArray [j] = here->BSIM4v7qsrc; + model->BSIM4v7paramCPU.BSIM4v7capbsRWArray [j] = here->BSIM4v7capbs; + model->BSIM4v7paramCPU.BSIM4v7capbdRWArray [j] = here->BSIM4v7capbd; + model->BSIM4v7paramCPU.BSIM4v7icVDSArray [j] = here->BSIM4v7icVDS; + model->BSIM4v7paramCPU.BSIM4v7icVGSArray [j] = here->BSIM4v7icVGS; + model->BSIM4v7paramCPU.BSIM4v7icVBSArray [j] = here->BSIM4v7icVBS; + model->BSIM4v7paramCPU.BSIM4v7vth0Array [j] = here->BSIM4v7vth0; + model->BSIM4v7paramCPU.BSIM4v7gbbsArray [j] = here->BSIM4v7gbbs; + model->BSIM4v7paramCPU.BSIM4v7ggidlbArray [j] = here->BSIM4v7ggidlb; + model->BSIM4v7paramCPU.BSIM4v7gbgsArray [j] = here->BSIM4v7gbgs; + model->BSIM4v7paramCPU.BSIM4v7ggidlgArray [j] = here->BSIM4v7ggidlg; + model->BSIM4v7paramCPU.BSIM4v7gbdsArray [j] = here->BSIM4v7gbds; + model->BSIM4v7paramCPU.BSIM4v7ggidldArray [j] = here->BSIM4v7ggidld; + model->BSIM4v7paramCPU.BSIM4v7ggislsArray [j] = here->BSIM4v7ggisls; + model->BSIM4v7paramCPU.BSIM4v7ggislgArray [j] = here->BSIM4v7ggislg; + model->BSIM4v7paramCPU.BSIM4v7ggislbArray [j] = here->BSIM4v7ggislb; + model->BSIM4v7paramCPU.BSIM4v7gIgsgArray [j] = here->BSIM4v7gIgsg; + model->BSIM4v7paramCPU.BSIM4v7gIgcsgArray [j] = here->BSIM4v7gIgcsg; + model->BSIM4v7paramCPU.BSIM4v7gIgcsdArray [j] = here->BSIM4v7gIgcsd; + model->BSIM4v7paramCPU.BSIM4v7gIgcsbArray [j] = here->BSIM4v7gIgcsb; + model->BSIM4v7paramCPU.BSIM4v7gIgdgArray [j] = here->BSIM4v7gIgdg; + model->BSIM4v7paramCPU.BSIM4v7gIgcdgArray [j] = here->BSIM4v7gIgcdg; + model->BSIM4v7paramCPU.BSIM4v7gIgcddArray [j] = here->BSIM4v7gIgcdd; + model->BSIM4v7paramCPU.BSIM4v7gIgcdbArray [j] = here->BSIM4v7gIgcdb; + model->BSIM4v7paramCPU.BSIM4v7gIgbgArray [j] = here->BSIM4v7gIgbg; + model->BSIM4v7paramCPU.BSIM4v7gIgbdArray [j] = here->BSIM4v7gIgbd; + model->BSIM4v7paramCPU.BSIM4v7gIgbbArray [j] = here->BSIM4v7gIgbb; + model->BSIM4v7paramCPU.BSIM4v7ggidlsArray [j] = here->BSIM4v7ggidls; + model->BSIM4v7paramCPU.BSIM4v7ggisldArray [j] = here->BSIM4v7ggisld; + model->BSIM4v7paramCPU.BSIM4v7gstotArray [j] = here->BSIM4v7gstot; + model->BSIM4v7paramCPU.BSIM4v7gstotdArray [j] = here->BSIM4v7gstotd; + model->BSIM4v7paramCPU.BSIM4v7gstotgArray [j] = here->BSIM4v7gstotg; + model->BSIM4v7paramCPU.BSIM4v7gstotbArray [j] = here->BSIM4v7gstotb; + model->BSIM4v7paramCPU.BSIM4v7gdtotArray [j] = here->BSIM4v7gdtot; + model->BSIM4v7paramCPU.BSIM4v7gdtotdArray [j] = here->BSIM4v7gdtotd; + model->BSIM4v7paramCPU.BSIM4v7gdtotgArray [j] = here->BSIM4v7gdtotg; + model->BSIM4v7paramCPU.BSIM4v7gdtotbArray [j] = here->BSIM4v7gdtotb; + model->BSIM4v7paramCPU.BSIM4v7cgdoArray [j] = here->BSIM4v7cgdo; + model->BSIM4v7paramCPU.BSIM4v7qgdoArray [j] = here->BSIM4v7qgdo; + model->BSIM4v7paramCPU.BSIM4v7cgsoArray [j] = here->BSIM4v7cgso; + model->BSIM4v7paramCPU.BSIM4v7qgsoArray [j] = here->BSIM4v7qgso; + model->BSIM4v7paramCPU.BSIM4v7AseffArray [j] = here->BSIM4v7Aseff; + model->BSIM4v7paramCPU.BSIM4v7PseffArray [j] = here->BSIM4v7Pseff; + model->BSIM4v7paramCPU.BSIM4v7nfArray [j] = here->BSIM4v7nf; + model->BSIM4v7paramCPU.BSIM4v7XExpBVSArray [j] = here->BSIM4v7XExpBVS; + model->BSIM4v7paramCPU.BSIM4v7vjsmFwdArray [j] = here->BSIM4v7vjsmFwd; + model->BSIM4v7paramCPU.BSIM4v7IVjsmFwdArray [j] = here->BSIM4v7IVjsmFwd; + model->BSIM4v7paramCPU.BSIM4v7vjsmRevArray [j] = here->BSIM4v7vjsmRev; + model->BSIM4v7paramCPU.BSIM4v7IVjsmRevArray [j] = here->BSIM4v7IVjsmRev; + model->BSIM4v7paramCPU.BSIM4v7SslpRevArray [j] = here->BSIM4v7SslpRev; + model->BSIM4v7paramCPU.BSIM4v7SslpFwdArray [j] = here->BSIM4v7SslpFwd; + model->BSIM4v7paramCPU.BSIM4v7AdeffArray [j] = here->BSIM4v7Adeff; + model->BSIM4v7paramCPU.BSIM4v7PdeffArray [j] = here->BSIM4v7Pdeff; + model->BSIM4v7paramCPU.BSIM4v7XExpBVDArray [j] = here->BSIM4v7XExpBVD; + model->BSIM4v7paramCPU.BSIM4v7vjdmFwdArray [j] = here->BSIM4v7vjdmFwd; + model->BSIM4v7paramCPU.BSIM4v7IVjdmFwdArray [j] = here->BSIM4v7IVjdmFwd; + model->BSIM4v7paramCPU.BSIM4v7vjdmRevArray [j] = here->BSIM4v7vjdmRev; + model->BSIM4v7paramCPU.BSIM4v7IVjdmRevArray [j] = here->BSIM4v7IVjdmRev; + model->BSIM4v7paramCPU.BSIM4v7DslpRevArray [j] = here->BSIM4v7DslpRev; + model->BSIM4v7paramCPU.BSIM4v7DslpFwdArray [j] = here->BSIM4v7DslpFwd; + model->BSIM4v7paramCPU.BSIM4v7SjctTempRevSatCurArray [j] = here->BSIM4v7SjctTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7SswTempRevSatCurArray [j] = here->BSIM4v7SswTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7SswgTempRevSatCurArray [j] = here->BSIM4v7SswgTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7DjctTempRevSatCurArray [j] = here->BSIM4v7DjctTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7DswTempRevSatCurArray [j] = here->BSIM4v7DswTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7DswgTempRevSatCurArray [j] = here->BSIM4v7DswgTempRevSatCur; + model->BSIM4v7paramCPU.BSIM4v7vbscArray [j] = here->BSIM4v7vbsc; + model->BSIM4v7paramCPU.BSIM4v7thetavthArray [j] = here->BSIM4v7thetavth; + model->BSIM4v7paramCPU.BSIM4v7eta0Array [j] = here->BSIM4v7eta0; + model->BSIM4v7paramCPU.BSIM4v7k2oxArray [j] = here->BSIM4v7k2ox; + model->BSIM4v7paramCPU.BSIM4v7nstarArray [j] = here->BSIM4v7nstar; + model->BSIM4v7paramCPU.BSIM4v7vfbArray [j] = here->BSIM4v7vfb; + model->BSIM4v7paramCPU.BSIM4v7vgs_effArray [j] = here->BSIM4v7vgs_eff; + model->BSIM4v7paramCPU.BSIM4v7vgd_effArray [j] = here->BSIM4v7vgd_eff; + model->BSIM4v7paramCPU.BSIM4v7dvgs_eff_dvgArray [j] = here->BSIM4v7dvgs_eff_dvg; + model->BSIM4v7paramCPU.BSIM4v7dvgd_eff_dvgArray [j] = here->BSIM4v7dvgd_eff_dvg; + model->BSIM4v7paramCPU.BSIM4v7VgsteffArray [j] = here->BSIM4v7Vgsteff; + model->BSIM4v7paramCPU.BSIM4v7grdswArray [j] = here->BSIM4v7grdsw; + model->BSIM4v7paramCPU.BSIM4v7AbulkArray [j] = here->BSIM4v7Abulk; + model->BSIM4v7paramCPU.BSIM4v7vtfbphi1Array [j] = here->BSIM4v7vtfbphi1; + model->BSIM4v7paramCPU.BSIM4v7ueffArray [j] = here->BSIM4v7ueff; + model->BSIM4v7paramCPU.BSIM4v7u0tempArray [j] = here->BSIM4v7u0temp; + model->BSIM4v7paramCPU.BSIM4v7vsattempArray [j] = here->BSIM4v7vsattemp; + model->BSIM4v7paramCPU.BSIM4v7EsatLArray [j] = here->BSIM4v7EsatL; + model->BSIM4v7paramCPU.BSIM4v7VdseffArray [j] = here->BSIM4v7Vdseff; + model->BSIM4v7paramCPU.BSIM4v7vtfbphi2Array [j] = here->BSIM4v7vtfbphi2; + model->BSIM4v7paramCPU.BSIM4v7CoxeffArray [j] = here->BSIM4v7Coxeff; + model->BSIM4v7paramCPU.BSIM4v7AbovVgst2VtmArray [j] = here->BSIM4v7AbovVgst2Vtm; + model->BSIM4v7paramCPU.BSIM4v7IdovVdsArray [j] = here->BSIM4v7IdovVds; + model->BSIM4v7paramCPU.BSIM4v7gcrgdArray [j] = here->BSIM4v7gcrgd; + model->BSIM4v7paramCPU.BSIM4v7gcrgbArray [j] = here->BSIM4v7gcrgb; + model->BSIM4v7paramCPU.BSIM4v7gcrggArray [j] = here->BSIM4v7gcrgg; + model->BSIM4v7paramCPU.BSIM4v7grgeltdArray [j] = here->BSIM4v7grgeltd; + model->BSIM4v7paramCPU.BSIM4v7gcrgsArray [j] = here->BSIM4v7gcrgs; + model->BSIM4v7paramCPU.BSIM4v7sourceConductanceArray [j] = here->BSIM4v7sourceConductance; + model->BSIM4v7paramCPU.BSIM4v7drainConductanceArray [j] = here->BSIM4v7drainConductance; + model->BSIM4v7paramCPU.BSIM4v7gstotsArray [j] = here->BSIM4v7gstots; + model->BSIM4v7paramCPU.BSIM4v7gdtotsArray [j] = here->BSIM4v7gdtots; + model->BSIM4v7paramCPU.BSIM4v7vfbzbArray [j] = here->BSIM4v7vfbzb; + model->BSIM4v7paramCPU.BSIM4v7gIgssArray [j] = here->BSIM4v7gIgss; + model->BSIM4v7paramCPU.BSIM4v7gIgddArray [j] = here->BSIM4v7gIgdd; + model->BSIM4v7paramCPU.BSIM4v7gIgbsArray [j] = here->BSIM4v7gIgbs; + model->BSIM4v7paramCPU.BSIM4v7gIgcssArray [j] = here->BSIM4v7gIgcss; + model->BSIM4v7paramCPU.BSIM4v7gIgcdsArray [j] = here->BSIM4v7gIgcds; + model->BSIM4v7paramCPU.BSIM4v7noiGd0Array [j] = here->BSIM4v7noiGd0; + model->BSIM4v7paramCPU.BSIM4v7cqdbArray [j] = here->BSIM4v7cqdb; + model->BSIM4v7paramCPU.BSIM4v7cqsbArray [j] = here->BSIM4v7cqsb; + model->BSIM4v7paramCPU.BSIM4v7cqgbArray [j] = here->BSIM4v7cqgb; + model->BSIM4v7paramCPU.BSIM4v7qchqsArray [j] = here->BSIM4v7qchqs; + model->BSIM4v7paramCPU.BSIM4v7cqbbArray [j] = here->BSIM4v7cqbb; + model->BSIM4v7paramCPU.BSIM4v7taunetArray [j] = here->BSIM4v7taunet; + model->BSIM4v7paramCPU.BSIM4v7gtgArray [j] = here->BSIM4v7gtg; + model->BSIM4v7paramCPU.BSIM4v7gtdArray [j] = here->BSIM4v7gtd; + model->BSIM4v7paramCPU.BSIM4v7gtsArray [j] = here->BSIM4v7gts; + model->BSIM4v7paramCPU.BSIM4v7gtbArray [j] = here->BSIM4v7gtb; + model->BSIM4v7paramCPU.BSIM4v7mArray [j] = here->BSIM4v7m; + model->BSIM4v7paramCPU.BSIM4v7grbpdArray [j] = here->BSIM4v7grbpd; + model->BSIM4v7paramCPU.BSIM4v7grbdbArray [j] = here->BSIM4v7grbdb; + model->BSIM4v7paramCPU.BSIM4v7grbpbArray [j] = here->BSIM4v7grbpb; + model->BSIM4v7paramCPU.BSIM4v7grbpsArray [j] = here->BSIM4v7grbps; + model->BSIM4v7paramCPU.BSIM4v7grbsbArray [j] = here->BSIM4v7grbsb; + model->BSIM4v7paramCPU.BSIM4v7offArray [j] = here->BSIM4v7off; + model->BSIM4v7paramCPU.BSIM4v7dNodePrimeArray [j] = here->BSIM4v7dNodePrime; + model->BSIM4v7paramCPU.BSIM4v7sNodePrimeArray [j] = here->BSIM4v7sNodePrime; + model->BSIM4v7paramCPU.BSIM4v7gNodePrimeArray [j] = here->BSIM4v7gNodePrime; + model->BSIM4v7paramCPU.BSIM4v7bNodePrimeArray [j] = here->BSIM4v7bNodePrime; + model->BSIM4v7paramCPU.BSIM4v7gNodeExtArray [j] = here->BSIM4v7gNodeExt; + model->BSIM4v7paramCPU.BSIM4v7gNodeMidArray [j] = here->BSIM4v7gNodeMid; + model->BSIM4v7paramCPU.BSIM4v7dbNodeArray [j] = here->BSIM4v7dbNode; + model->BSIM4v7paramCPU.BSIM4v7sbNodeArray [j] = here->BSIM4v7sbNode; + model->BSIM4v7paramCPU.BSIM4v7sNodeArray [j] = here->BSIM4v7sNode; + model->BSIM4v7paramCPU.BSIM4v7dNodeArray [j] = here->BSIM4v7dNode; + model->BSIM4v7paramCPU.BSIM4v7qNodeArray [j] = here->BSIM4v7qNode; + model->BSIM4v7paramCPU.BSIM4v7rbodyModArray [j] = here->BSIM4v7rbodyMod; + model->BSIM4v7paramCPU.BSIM4v7modeArray [j] = here->BSIM4v7mode; + model->BSIM4v7paramCPU.BSIM4v7rgateModArray [j] = here->BSIM4v7rgateMod; + model->BSIM4v7paramCPU.BSIM4v7trnqsModArray [j] = here->BSIM4v7trnqsMod; + model->BSIM4v7paramCPU.BSIM4v7acnqsModArray [j] = here->BSIM4v7acnqsMod; + model->BSIM4v7paramCPU.BSIM4v7statesArray [j] = here->BSIM4v7states; + + j++; +#endif + } /* End instance */ + +#ifdef USE_CUSPICE + status = cuBSIM4v7temp ((GENmodel *)model); + if (status != 0) + return E_NOMEM; +#endif + } return(OK); } diff --git a/src/spicelib/devices/bsim4v7/bsim4v7def.h b/src/spicelib/devices/bsim4v7/bsim4v7def.h index bc6117367..be3ff7abc 100644 --- a/src/spicelib/devices/bsim4v7/bsim4v7def.h +++ b/src/spicelib/devices/bsim4v7/bsim4v7def.h @@ -887,6 +887,543 @@ struct bsim4SizeDependParam struct bsim4SizeDependParam *pNext; }; +#ifdef USE_CUSPICE +typedef struct sBSIM4v7paramCPUstruct { + + double *BSIM4v7cpuPointersD [243]; + #define BSIM4v7gbsRWArray BSIM4v7cpuPointersD[0] + #define BSIM4v7cbsRWArray BSIM4v7cpuPointersD[1] + #define BSIM4v7gbdRWArray BSIM4v7cpuPointersD[2] + #define BSIM4v7cbdRWArray BSIM4v7cpuPointersD[3] + #define BSIM4v7vonRWArray BSIM4v7cpuPointersD[4] + #define BSIM4v7vdsatRWArray BSIM4v7cpuPointersD[5] + #define BSIM4v7csubRWArray BSIM4v7cpuPointersD[6] + #define BSIM4v7gdsRWArray BSIM4v7cpuPointersD[7] + #define BSIM4v7gmRWArray BSIM4v7cpuPointersD[8] + #define BSIM4v7gmbsRWArray BSIM4v7cpuPointersD[9] + #define BSIM4v7gcrgRWArray BSIM4v7cpuPointersD[10] + #define BSIM4v7IgidlRWArray BSIM4v7cpuPointersD[11] + #define BSIM4v7IgislRWArray BSIM4v7cpuPointersD[12] + #define BSIM4v7IgcsRWArray BSIM4v7cpuPointersD[13] + #define BSIM4v7IgcdRWArray BSIM4v7cpuPointersD[14] + #define BSIM4v7IgsRWArray BSIM4v7cpuPointersD[15] + #define BSIM4v7IgdRWArray BSIM4v7cpuPointersD[16] + #define BSIM4v7IgbRWArray BSIM4v7cpuPointersD[17] + #define BSIM4v7cdRWArray BSIM4v7cpuPointersD[18] + #define BSIM4v7qinvRWArray BSIM4v7cpuPointersD[19] + #define BSIM4v7cggbRWArray BSIM4v7cpuPointersD[20] + #define BSIM4v7cgsbRWArray BSIM4v7cpuPointersD[21] + #define BSIM4v7cgdbRWArray BSIM4v7cpuPointersD[22] + #define BSIM4v7cdgbRWArray BSIM4v7cpuPointersD[23] + #define BSIM4v7cdsbRWArray BSIM4v7cpuPointersD[24] + #define BSIM4v7cddbRWArray BSIM4v7cpuPointersD[25] + #define BSIM4v7cbgbRWArray BSIM4v7cpuPointersD[26] + #define BSIM4v7cbsbRWArray BSIM4v7cpuPointersD[27] + #define BSIM4v7cbdbRWArray BSIM4v7cpuPointersD[28] + #define BSIM4v7csgbRWArray BSIM4v7cpuPointersD[29] + #define BSIM4v7cssbRWArray BSIM4v7cpuPointersD[30] + #define BSIM4v7csdbRWArray BSIM4v7cpuPointersD[31] + #define BSIM4v7cgbbRWArray BSIM4v7cpuPointersD[32] + #define BSIM4v7csbbRWArray BSIM4v7cpuPointersD[33] + #define BSIM4v7cdbbRWArray BSIM4v7cpuPointersD[34] + #define BSIM4v7cbbbRWArray BSIM4v7cpuPointersD[35] + #define BSIM4v7gtauRWArray BSIM4v7cpuPointersD[36] + #define BSIM4v7qgateRWArray BSIM4v7cpuPointersD[37] + #define BSIM4v7qbulkRWArray BSIM4v7cpuPointersD[38] + #define BSIM4v7qdrnRWArray BSIM4v7cpuPointersD[39] + #define BSIM4v7qsrcRWArray BSIM4v7cpuPointersD[40] + #define BSIM4v7capbsRWArray BSIM4v7cpuPointersD[41] + #define BSIM4v7capbdRWArray BSIM4v7cpuPointersD[42] + #define BSIM4v7icVDSArray BSIM4v7cpuPointersD[43] + #define BSIM4v7icVGSArray BSIM4v7cpuPointersD[44] + #define BSIM4v7icVBSArray BSIM4v7cpuPointersD[45] + #define BSIM4v7vth0Array BSIM4v7cpuPointersD[46] + #define BSIM4v7gbbsArray BSIM4v7cpuPointersD[47] + #define BSIM4v7ggidlbArray BSIM4v7cpuPointersD[48] + #define BSIM4v7gbgsArray BSIM4v7cpuPointersD[49] + #define BSIM4v7ggidlgArray BSIM4v7cpuPointersD[50] + #define BSIM4v7gbdsArray BSIM4v7cpuPointersD[51] + #define BSIM4v7ggidldArray BSIM4v7cpuPointersD[52] + #define BSIM4v7ggislsArray BSIM4v7cpuPointersD[53] + #define BSIM4v7ggislgArray BSIM4v7cpuPointersD[54] + #define BSIM4v7ggislbArray BSIM4v7cpuPointersD[55] + #define BSIM4v7gIgsgArray BSIM4v7cpuPointersD[56] + #define BSIM4v7gIgcsgArray BSIM4v7cpuPointersD[57] + #define BSIM4v7gIgcsdArray BSIM4v7cpuPointersD[58] + #define BSIM4v7gIgcsbArray BSIM4v7cpuPointersD[59] + #define BSIM4v7gIgdgArray BSIM4v7cpuPointersD[60] + #define BSIM4v7gIgcdgArray BSIM4v7cpuPointersD[61] + #define BSIM4v7gIgcddArray BSIM4v7cpuPointersD[62] + #define BSIM4v7gIgcdbArray BSIM4v7cpuPointersD[63] + #define BSIM4v7gIgbgArray BSIM4v7cpuPointersD[64] + #define BSIM4v7gIgbdArray BSIM4v7cpuPointersD[65] + #define BSIM4v7gIgbbArray BSIM4v7cpuPointersD[66] + #define BSIM4v7ggidlsArray BSIM4v7cpuPointersD[67] + #define BSIM4v7ggisldArray BSIM4v7cpuPointersD[68] + #define BSIM4v7gstotArray BSIM4v7cpuPointersD[69] + #define BSIM4v7gstotdArray BSIM4v7cpuPointersD[70] + #define BSIM4v7gstotgArray BSIM4v7cpuPointersD[71] + #define BSIM4v7gstotbArray BSIM4v7cpuPointersD[72] + #define BSIM4v7gdtotArray BSIM4v7cpuPointersD[73] + #define BSIM4v7gdtotdArray BSIM4v7cpuPointersD[74] + #define BSIM4v7gdtotgArray BSIM4v7cpuPointersD[75] + #define BSIM4v7gdtotbArray BSIM4v7cpuPointersD[76] + #define BSIM4v7cgdoArray BSIM4v7cpuPointersD[77] + #define BSIM4v7qgdoArray BSIM4v7cpuPointersD[78] + #define BSIM4v7cgsoArray BSIM4v7cpuPointersD[79] + #define BSIM4v7qgsoArray BSIM4v7cpuPointersD[80] + #define BSIM4v7AseffArray BSIM4v7cpuPointersD[81] + #define BSIM4v7PseffArray BSIM4v7cpuPointersD[82] + #define BSIM4v7nfArray BSIM4v7cpuPointersD[83] + #define BSIM4v7XExpBVSArray BSIM4v7cpuPointersD[84] + #define BSIM4v7vjsmFwdArray BSIM4v7cpuPointersD[85] + #define BSIM4v7IVjsmFwdArray BSIM4v7cpuPointersD[86] + #define BSIM4v7vjsmRevArray BSIM4v7cpuPointersD[87] + #define BSIM4v7IVjsmRevArray BSIM4v7cpuPointersD[88] + #define BSIM4v7SslpRevArray BSIM4v7cpuPointersD[89] + #define BSIM4v7SslpFwdArray BSIM4v7cpuPointersD[90] + #define BSIM4v7AdeffArray BSIM4v7cpuPointersD[91] + #define BSIM4v7PdeffArray BSIM4v7cpuPointersD[92] + #define BSIM4v7XExpBVDArray BSIM4v7cpuPointersD[93] + #define BSIM4v7vjdmFwdArray BSIM4v7cpuPointersD[94] + #define BSIM4v7IVjdmFwdArray BSIM4v7cpuPointersD[95] + #define BSIM4v7vjdmRevArray BSIM4v7cpuPointersD[96] + #define BSIM4v7IVjdmRevArray BSIM4v7cpuPointersD[97] + #define BSIM4v7DslpRevArray BSIM4v7cpuPointersD[98] + #define BSIM4v7DslpFwdArray BSIM4v7cpuPointersD[99] + #define BSIM4v7SjctTempRevSatCurArray BSIM4v7cpuPointersD[100] + #define BSIM4v7SswTempRevSatCurArray BSIM4v7cpuPointersD[101] + #define BSIM4v7SswgTempRevSatCurArray BSIM4v7cpuPointersD[102] + #define BSIM4v7DjctTempRevSatCurArray BSIM4v7cpuPointersD[103] + #define BSIM4v7DswTempRevSatCurArray BSIM4v7cpuPointersD[104] + #define BSIM4v7DswgTempRevSatCurArray BSIM4v7cpuPointersD[105] + #define BSIM4v7vbscArray BSIM4v7cpuPointersD[106] + #define BSIM4v7thetavthArray BSIM4v7cpuPointersD[107] + #define BSIM4v7eta0Array BSIM4v7cpuPointersD[108] + #define BSIM4v7k2oxArray BSIM4v7cpuPointersD[109] + #define BSIM4v7nstarArray BSIM4v7cpuPointersD[110] + #define BSIM4v7vfbArray BSIM4v7cpuPointersD[111] + #define BSIM4v7vgs_effArray BSIM4v7cpuPointersD[112] + #define BSIM4v7vgd_effArray BSIM4v7cpuPointersD[113] + #define BSIM4v7dvgs_eff_dvgArray BSIM4v7cpuPointersD[114] + #define BSIM4v7dvgd_eff_dvgArray BSIM4v7cpuPointersD[115] + #define BSIM4v7VgsteffArray BSIM4v7cpuPointersD[116] + #define BSIM4v7grdswArray BSIM4v7cpuPointersD[117] + #define BSIM4v7AbulkArray BSIM4v7cpuPointersD[118] + #define BSIM4v7vtfbphi1Array BSIM4v7cpuPointersD[119] + #define BSIM4v7ueffArray BSIM4v7cpuPointersD[120] + #define BSIM4v7u0tempArray BSIM4v7cpuPointersD[121] + #define BSIM4v7vsattempArray BSIM4v7cpuPointersD[122] + #define BSIM4v7EsatLArray BSIM4v7cpuPointersD[123] + #define BSIM4v7VdseffArray BSIM4v7cpuPointersD[124] + #define BSIM4v7vtfbphi2Array BSIM4v7cpuPointersD[125] + #define BSIM4v7CoxeffArray BSIM4v7cpuPointersD[126] + #define BSIM4v7AbovVgst2VtmArray BSIM4v7cpuPointersD[127] + #define BSIM4v7IdovVdsArray BSIM4v7cpuPointersD[128] + #define BSIM4v7gcrgdArray BSIM4v7cpuPointersD[129] + #define BSIM4v7gcrgbArray BSIM4v7cpuPointersD[130] + #define BSIM4v7gcrggArray BSIM4v7cpuPointersD[131] + #define BSIM4v7grgeltdArray BSIM4v7cpuPointersD[132] + #define BSIM4v7gcrgsArray BSIM4v7cpuPointersD[133] + #define BSIM4v7sourceConductanceArray BSIM4v7cpuPointersD[134] + #define BSIM4v7drainConductanceArray BSIM4v7cpuPointersD[135] + #define BSIM4v7gstotsArray BSIM4v7cpuPointersD[136] + #define BSIM4v7gdtotsArray BSIM4v7cpuPointersD[137] + #define BSIM4v7vfbzbArray BSIM4v7cpuPointersD[138] + #define BSIM4v7gIgssArray BSIM4v7cpuPointersD[139] + #define BSIM4v7gIgddArray BSIM4v7cpuPointersD[140] + #define BSIM4v7gIgbsArray BSIM4v7cpuPointersD[141] + #define BSIM4v7gIgcssArray BSIM4v7cpuPointersD[142] + #define BSIM4v7gIgcdsArray BSIM4v7cpuPointersD[143] + #define BSIM4v7noiGd0Array BSIM4v7cpuPointersD[144] + #define BSIM4v7cqdbArray BSIM4v7cpuPointersD[145] + #define BSIM4v7cqsbArray BSIM4v7cpuPointersD[146] + #define BSIM4v7cqgbArray BSIM4v7cpuPointersD[147] + #define BSIM4v7qchqsArray BSIM4v7cpuPointersD[148] + #define BSIM4v7cqbbArray BSIM4v7cpuPointersD[149] + #define BSIM4v7taunetArray BSIM4v7cpuPointersD[150] + #define BSIM4v7gtgArray BSIM4v7cpuPointersD[151] + #define BSIM4v7gtdArray BSIM4v7cpuPointersD[152] + #define BSIM4v7gtsArray BSIM4v7cpuPointersD[153] + #define BSIM4v7gtbArray BSIM4v7cpuPointersD[154] + #define BSIM4v7mArray BSIM4v7cpuPointersD[155] + #define BSIM4v7grbpdArray BSIM4v7cpuPointersD[156] + #define BSIM4v7grbdbArray BSIM4v7cpuPointersD[157] + #define BSIM4v7grbpbArray BSIM4v7cpuPointersD[158] + #define BSIM4v7grbpsArray BSIM4v7cpuPointersD[159] + #define BSIM4v7grbsbArray BSIM4v7cpuPointersD[160] + #define BSIM4v7dNodePrimeRHSValueArray BSIM4v7cpuPointersD[161] + #define BSIM4v7gNodePrimeRHSValueArray BSIM4v7cpuPointersD[162] + #define BSIM4v7gNodeExtRHSValueArray BSIM4v7cpuPointersD[163] + #define BSIM4v7gNodeMidRHSValueArray BSIM4v7cpuPointersD[164] + #define BSIM4v7bNodePrimeRHSValueArray BSIM4v7cpuPointersD[165] + #define BSIM4v7sNodePrimeRHSValueArray BSIM4v7cpuPointersD[166] + #define BSIM4v7dbNodeRHSValueArray BSIM4v7cpuPointersD[167] + #define BSIM4v7sbNodeRHSValueArray BSIM4v7cpuPointersD[168] + #define BSIM4v7dNodeRHSValueArray BSIM4v7cpuPointersD[169] + #define BSIM4v7sNodeRHSValueArray BSIM4v7cpuPointersD[170] + #define BSIM4v7qNodeRHSValueArray BSIM4v7cpuPointersD[171] + #define BSIM4v7GEgeValueArray BSIM4v7cpuPointersD[172] + #define BSIM4v7GPgeValueArray BSIM4v7cpuPointersD[173] + #define BSIM4v7GEgpValueArray BSIM4v7cpuPointersD[174] + #define BSIM4v7GPgpValueArray BSIM4v7cpuPointersD[175] + #define BSIM4v7GPdpValueArray BSIM4v7cpuPointersD[176] + #define BSIM4v7GPspValueArray BSIM4v7cpuPointersD[177] + #define BSIM4v7GPbpValueArray BSIM4v7cpuPointersD[178] + #define BSIM4v7GEdpValueArray BSIM4v7cpuPointersD[179] + #define BSIM4v7GEspValueArray BSIM4v7cpuPointersD[180] + #define BSIM4v7GEbpValueArray BSIM4v7cpuPointersD[181] + #define BSIM4v7GEgmValueArray BSIM4v7cpuPointersD[182] + #define BSIM4v7GMgeValueArray BSIM4v7cpuPointersD[183] + #define BSIM4v7GMgmValueArray BSIM4v7cpuPointersD[184] + #define BSIM4v7GMdpValueArray BSIM4v7cpuPointersD[185] + #define BSIM4v7GMgpValueArray BSIM4v7cpuPointersD[186] + #define BSIM4v7GMspValueArray BSIM4v7cpuPointersD[187] + #define BSIM4v7GMbpValueArray BSIM4v7cpuPointersD[188] + #define BSIM4v7DPgmValueArray BSIM4v7cpuPointersD[189] + #define BSIM4v7GPgmValueArray BSIM4v7cpuPointersD[190] + #define BSIM4v7SPgmValueArray BSIM4v7cpuPointersD[191] + #define BSIM4v7BPgmValueArray BSIM4v7cpuPointersD[192] + #define BSIM4v7DgpValueArray BSIM4v7cpuPointersD[193] + #define BSIM4v7DspValueArray BSIM4v7cpuPointersD[194] + #define BSIM4v7DbpValueArray BSIM4v7cpuPointersD[195] + #define BSIM4v7SdpValueArray BSIM4v7cpuPointersD[196] + #define BSIM4v7SgpValueArray BSIM4v7cpuPointersD[197] + #define BSIM4v7SbpValueArray BSIM4v7cpuPointersD[198] + #define BSIM4v7DPdpValueArray BSIM4v7cpuPointersD[199] + #define BSIM4v7DPdValueArray BSIM4v7cpuPointersD[200] + #define BSIM4v7DPgpValueArray BSIM4v7cpuPointersD[201] + #define BSIM4v7DPspValueArray BSIM4v7cpuPointersD[202] + #define BSIM4v7DPbpValueArray BSIM4v7cpuPointersD[203] + #define BSIM4v7DdpValueArray BSIM4v7cpuPointersD[204] + #define BSIM4v7DdValueArray BSIM4v7cpuPointersD[205] + #define BSIM4v7SPdpValueArray BSIM4v7cpuPointersD[206] + #define BSIM4v7SPgpValueArray BSIM4v7cpuPointersD[207] + #define BSIM4v7SPspValueArray BSIM4v7cpuPointersD[208] + #define BSIM4v7SPsValueArray BSIM4v7cpuPointersD[209] + #define BSIM4v7SPbpValueArray BSIM4v7cpuPointersD[210] + #define BSIM4v7SspValueArray BSIM4v7cpuPointersD[211] + #define BSIM4v7SsValueArray BSIM4v7cpuPointersD[212] + #define BSIM4v7BPdpValueArray BSIM4v7cpuPointersD[213] + #define BSIM4v7BPgpValueArray BSIM4v7cpuPointersD[214] + #define BSIM4v7BPspValueArray BSIM4v7cpuPointersD[215] + #define BSIM4v7BPbpValueArray BSIM4v7cpuPointersD[216] + #define BSIM4v7DPdbValueArray BSIM4v7cpuPointersD[217] + #define BSIM4v7SPsbValueArray BSIM4v7cpuPointersD[218] + #define BSIM4v7DBdpValueArray BSIM4v7cpuPointersD[219] + #define BSIM4v7DBdbValueArray BSIM4v7cpuPointersD[220] + #define BSIM4v7DBbpValueArray BSIM4v7cpuPointersD[221] + #define BSIM4v7DBbValueArray BSIM4v7cpuPointersD[222] + #define BSIM4v7BPdbValueArray BSIM4v7cpuPointersD[223] + #define BSIM4v7BPbValueArray BSIM4v7cpuPointersD[224] + #define BSIM4v7BPsbValueArray BSIM4v7cpuPointersD[225] + #define BSIM4v7BPbpIFValueArray BSIM4v7cpuPointersD[226] + #define BSIM4v7SBspValueArray BSIM4v7cpuPointersD[227] + #define BSIM4v7SBbpValueArray BSIM4v7cpuPointersD[228] + #define BSIM4v7SBbValueArray BSIM4v7cpuPointersD[229] + #define BSIM4v7SBsbValueArray BSIM4v7cpuPointersD[230] + #define BSIM4v7BdbValueArray BSIM4v7cpuPointersD[231] + #define BSIM4v7BbpValueArray BSIM4v7cpuPointersD[232] + #define BSIM4v7BsbValueArray BSIM4v7cpuPointersD[233] + #define BSIM4v7BbValueArray BSIM4v7cpuPointersD[234] + #define BSIM4v7QqValueArray BSIM4v7cpuPointersD[235] + #define BSIM4v7QgpValueArray BSIM4v7cpuPointersD[236] + #define BSIM4v7QdpValueArray BSIM4v7cpuPointersD[237] + #define BSIM4v7QspValueArray BSIM4v7cpuPointersD[238] + #define BSIM4v7QbpValueArray BSIM4v7cpuPointersD[239] + #define BSIM4v7DPqValueArray BSIM4v7cpuPointersD[240] + #define BSIM4v7SPqValueArray BSIM4v7cpuPointersD[241] + #define BSIM4v7GPqValueArray BSIM4v7cpuPointersD[242] + + int *BSIM4v7cpuPointersI [18]; + #define BSIM4v7offArray BSIM4v7cpuPointersI[0] + #define BSIM4v7dNodePrimeArray BSIM4v7cpuPointersI[1] + #define BSIM4v7sNodePrimeArray BSIM4v7cpuPointersI[2] + #define BSIM4v7gNodePrimeArray BSIM4v7cpuPointersI[3] + #define BSIM4v7bNodePrimeArray BSIM4v7cpuPointersI[4] + #define BSIM4v7gNodeExtArray BSIM4v7cpuPointersI[5] + #define BSIM4v7gNodeMidArray BSIM4v7cpuPointersI[6] + #define BSIM4v7dbNodeArray BSIM4v7cpuPointersI[7] + #define BSIM4v7sbNodeArray BSIM4v7cpuPointersI[8] + #define BSIM4v7sNodeArray BSIM4v7cpuPointersI[9] + #define BSIM4v7dNodeArray BSIM4v7cpuPointersI[10] + #define BSIM4v7qNodeArray BSIM4v7cpuPointersI[11] + #define BSIM4v7rbodyModArray BSIM4v7cpuPointersI[12] + #define BSIM4v7modeArray BSIM4v7cpuPointersI[13] + #define BSIM4v7rgateModArray BSIM4v7cpuPointersI[14] + #define BSIM4v7trnqsModArray BSIM4v7cpuPointersI[15] + #define BSIM4v7acnqsModArray BSIM4v7cpuPointersI[16] + #define BSIM4v7statesArray BSIM4v7cpuPointersI[17] +} BSIM4v7paramCPUstruct ; + +typedef struct sBSIM4v7paramGPUstruct { + + double *BSIM4v7cudaPointersD [243]; + #define d_BSIM4v7gbsRWArray BSIM4v7cudaPointersD[0] + #define d_BSIM4v7cbsRWArray BSIM4v7cudaPointersD[1] + #define d_BSIM4v7gbdRWArray BSIM4v7cudaPointersD[2] + #define d_BSIM4v7cbdRWArray BSIM4v7cudaPointersD[3] + #define d_BSIM4v7vonRWArray BSIM4v7cudaPointersD[4] + #define d_BSIM4v7vdsatRWArray BSIM4v7cudaPointersD[5] + #define d_BSIM4v7csubRWArray BSIM4v7cudaPointersD[6] + #define d_BSIM4v7gdsRWArray BSIM4v7cudaPointersD[7] + #define d_BSIM4v7gmRWArray BSIM4v7cudaPointersD[8] + #define d_BSIM4v7gmbsRWArray BSIM4v7cudaPointersD[9] + #define d_BSIM4v7gcrgRWArray BSIM4v7cudaPointersD[10] + #define d_BSIM4v7IgidlRWArray BSIM4v7cudaPointersD[11] + #define d_BSIM4v7IgislRWArray BSIM4v7cudaPointersD[12] + #define d_BSIM4v7IgcsRWArray BSIM4v7cudaPointersD[13] + #define d_BSIM4v7IgcdRWArray BSIM4v7cudaPointersD[14] + #define d_BSIM4v7IgsRWArray BSIM4v7cudaPointersD[15] + #define d_BSIM4v7IgdRWArray BSIM4v7cudaPointersD[16] + #define d_BSIM4v7IgbRWArray BSIM4v7cudaPointersD[17] + #define d_BSIM4v7cdRWArray BSIM4v7cudaPointersD[18] + #define d_BSIM4v7qinvRWArray BSIM4v7cudaPointersD[19] + #define d_BSIM4v7cggbRWArray BSIM4v7cudaPointersD[20] + #define d_BSIM4v7cgsbRWArray BSIM4v7cudaPointersD[21] + #define d_BSIM4v7cgdbRWArray BSIM4v7cudaPointersD[22] + #define d_BSIM4v7cdgbRWArray BSIM4v7cudaPointersD[23] + #define d_BSIM4v7cdsbRWArray BSIM4v7cudaPointersD[24] + #define d_BSIM4v7cddbRWArray BSIM4v7cudaPointersD[25] + #define d_BSIM4v7cbgbRWArray BSIM4v7cudaPointersD[26] + #define d_BSIM4v7cbsbRWArray BSIM4v7cudaPointersD[27] + #define d_BSIM4v7cbdbRWArray BSIM4v7cudaPointersD[28] + #define d_BSIM4v7csgbRWArray BSIM4v7cudaPointersD[29] + #define d_BSIM4v7cssbRWArray BSIM4v7cudaPointersD[30] + #define d_BSIM4v7csdbRWArray BSIM4v7cudaPointersD[31] + #define d_BSIM4v7cgbbRWArray BSIM4v7cudaPointersD[32] + #define d_BSIM4v7csbbRWArray BSIM4v7cudaPointersD[33] + #define d_BSIM4v7cdbbRWArray BSIM4v7cudaPointersD[34] + #define d_BSIM4v7cbbbRWArray BSIM4v7cudaPointersD[35] + #define d_BSIM4v7gtauRWArray BSIM4v7cudaPointersD[36] + #define d_BSIM4v7qgateRWArray BSIM4v7cudaPointersD[37] + #define d_BSIM4v7qbulkRWArray BSIM4v7cudaPointersD[38] + #define d_BSIM4v7qdrnRWArray BSIM4v7cudaPointersD[39] + #define d_BSIM4v7qsrcRWArray BSIM4v7cudaPointersD[40] + #define d_BSIM4v7capbsRWArray BSIM4v7cudaPointersD[41] + #define d_BSIM4v7capbdRWArray BSIM4v7cudaPointersD[42] + #define d_BSIM4v7icVDSArray BSIM4v7cudaPointersD[43] + #define d_BSIM4v7icVGSArray BSIM4v7cudaPointersD[44] + #define d_BSIM4v7icVBSArray BSIM4v7cudaPointersD[45] + #define d_BSIM4v7vth0Array BSIM4v7cudaPointersD[46] + #define d_BSIM4v7gbbsArray BSIM4v7cudaPointersD[47] + #define d_BSIM4v7ggidlbArray BSIM4v7cudaPointersD[48] + #define d_BSIM4v7gbgsArray BSIM4v7cudaPointersD[49] + #define d_BSIM4v7ggidlgArray BSIM4v7cudaPointersD[50] + #define d_BSIM4v7gbdsArray BSIM4v7cudaPointersD[51] + #define d_BSIM4v7ggidldArray BSIM4v7cudaPointersD[52] + #define d_BSIM4v7ggislsArray BSIM4v7cudaPointersD[53] + #define d_BSIM4v7ggislgArray BSIM4v7cudaPointersD[54] + #define d_BSIM4v7ggislbArray BSIM4v7cudaPointersD[55] + #define d_BSIM4v7gIgsgArray BSIM4v7cudaPointersD[56] + #define d_BSIM4v7gIgcsgArray BSIM4v7cudaPointersD[57] + #define d_BSIM4v7gIgcsdArray BSIM4v7cudaPointersD[58] + #define d_BSIM4v7gIgcsbArray BSIM4v7cudaPointersD[59] + #define d_BSIM4v7gIgdgArray BSIM4v7cudaPointersD[60] + #define d_BSIM4v7gIgcdgArray BSIM4v7cudaPointersD[61] + #define d_BSIM4v7gIgcddArray BSIM4v7cudaPointersD[62] + #define d_BSIM4v7gIgcdbArray BSIM4v7cudaPointersD[63] + #define d_BSIM4v7gIgbgArray BSIM4v7cudaPointersD[64] + #define d_BSIM4v7gIgbdArray BSIM4v7cudaPointersD[65] + #define d_BSIM4v7gIgbbArray BSIM4v7cudaPointersD[66] + #define d_BSIM4v7ggidlsArray BSIM4v7cudaPointersD[67] + #define d_BSIM4v7ggisldArray BSIM4v7cudaPointersD[68] + #define d_BSIM4v7gstotArray BSIM4v7cudaPointersD[69] + #define d_BSIM4v7gstotdArray BSIM4v7cudaPointersD[70] + #define d_BSIM4v7gstotgArray BSIM4v7cudaPointersD[71] + #define d_BSIM4v7gstotbArray BSIM4v7cudaPointersD[72] + #define d_BSIM4v7gdtotArray BSIM4v7cudaPointersD[73] + #define d_BSIM4v7gdtotdArray BSIM4v7cudaPointersD[74] + #define d_BSIM4v7gdtotgArray BSIM4v7cudaPointersD[75] + #define d_BSIM4v7gdtotbArray BSIM4v7cudaPointersD[76] + #define d_BSIM4v7cgdoArray BSIM4v7cudaPointersD[77] + #define d_BSIM4v7qgdoArray BSIM4v7cudaPointersD[78] + #define d_BSIM4v7cgsoArray BSIM4v7cudaPointersD[79] + #define d_BSIM4v7qgsoArray BSIM4v7cudaPointersD[80] + #define d_BSIM4v7AseffArray BSIM4v7cudaPointersD[81] + #define d_BSIM4v7PseffArray BSIM4v7cudaPointersD[82] + #define d_BSIM4v7nfArray BSIM4v7cudaPointersD[83] + #define d_BSIM4v7XExpBVSArray BSIM4v7cudaPointersD[84] + #define d_BSIM4v7vjsmFwdArray BSIM4v7cudaPointersD[85] + #define d_BSIM4v7IVjsmFwdArray BSIM4v7cudaPointersD[86] + #define d_BSIM4v7vjsmRevArray BSIM4v7cudaPointersD[87] + #define d_BSIM4v7IVjsmRevArray BSIM4v7cudaPointersD[88] + #define d_BSIM4v7SslpRevArray BSIM4v7cudaPointersD[89] + #define d_BSIM4v7SslpFwdArray BSIM4v7cudaPointersD[90] + #define d_BSIM4v7AdeffArray BSIM4v7cudaPointersD[91] + #define d_BSIM4v7PdeffArray BSIM4v7cudaPointersD[92] + #define d_BSIM4v7XExpBVDArray BSIM4v7cudaPointersD[93] + #define d_BSIM4v7vjdmFwdArray BSIM4v7cudaPointersD[94] + #define d_BSIM4v7IVjdmFwdArray BSIM4v7cudaPointersD[95] + #define d_BSIM4v7vjdmRevArray BSIM4v7cudaPointersD[96] + #define d_BSIM4v7IVjdmRevArray BSIM4v7cudaPointersD[97] + #define d_BSIM4v7DslpRevArray BSIM4v7cudaPointersD[98] + #define d_BSIM4v7DslpFwdArray BSIM4v7cudaPointersD[99] + #define d_BSIM4v7SjctTempRevSatCurArray BSIM4v7cudaPointersD[100] + #define d_BSIM4v7SswTempRevSatCurArray BSIM4v7cudaPointersD[101] + #define d_BSIM4v7SswgTempRevSatCurArray BSIM4v7cudaPointersD[102] + #define d_BSIM4v7DjctTempRevSatCurArray BSIM4v7cudaPointersD[103] + #define d_BSIM4v7DswTempRevSatCurArray BSIM4v7cudaPointersD[104] + #define d_BSIM4v7DswgTempRevSatCurArray BSIM4v7cudaPointersD[105] + #define d_BSIM4v7vbscArray BSIM4v7cudaPointersD[106] + #define d_BSIM4v7thetavthArray BSIM4v7cudaPointersD[107] + #define d_BSIM4v7eta0Array BSIM4v7cudaPointersD[108] + #define d_BSIM4v7k2oxArray BSIM4v7cudaPointersD[109] + #define d_BSIM4v7nstarArray BSIM4v7cudaPointersD[110] + #define d_BSIM4v7vfbArray BSIM4v7cudaPointersD[111] + #define d_BSIM4v7vgs_effArray BSIM4v7cudaPointersD[112] + #define d_BSIM4v7vgd_effArray BSIM4v7cudaPointersD[113] + #define d_BSIM4v7dvgs_eff_dvgArray BSIM4v7cudaPointersD[114] + #define d_BSIM4v7dvgd_eff_dvgArray BSIM4v7cudaPointersD[115] + #define d_BSIM4v7VgsteffArray BSIM4v7cudaPointersD[116] + #define d_BSIM4v7grdswArray BSIM4v7cudaPointersD[117] + #define d_BSIM4v7AbulkArray BSIM4v7cudaPointersD[118] + #define d_BSIM4v7vtfbphi1Array BSIM4v7cudaPointersD[119] + #define d_BSIM4v7ueffArray BSIM4v7cudaPointersD[120] + #define d_BSIM4v7u0tempArray BSIM4v7cudaPointersD[121] + #define d_BSIM4v7vsattempArray BSIM4v7cudaPointersD[122] + #define d_BSIM4v7EsatLArray BSIM4v7cudaPointersD[123] + #define d_BSIM4v7VdseffArray BSIM4v7cudaPointersD[124] + #define d_BSIM4v7vtfbphi2Array BSIM4v7cudaPointersD[125] + #define d_BSIM4v7CoxeffArray BSIM4v7cudaPointersD[126] + #define d_BSIM4v7AbovVgst2VtmArray BSIM4v7cudaPointersD[127] + #define d_BSIM4v7IdovVdsArray BSIM4v7cudaPointersD[128] + #define d_BSIM4v7gcrgdArray BSIM4v7cudaPointersD[129] + #define d_BSIM4v7gcrgbArray BSIM4v7cudaPointersD[130] + #define d_BSIM4v7gcrggArray BSIM4v7cudaPointersD[131] + #define d_BSIM4v7grgeltdArray BSIM4v7cudaPointersD[132] + #define d_BSIM4v7gcrgsArray BSIM4v7cudaPointersD[133] + #define d_BSIM4v7sourceConductanceArray BSIM4v7cudaPointersD[134] + #define d_BSIM4v7drainConductanceArray BSIM4v7cudaPointersD[135] + #define d_BSIM4v7gstotsArray BSIM4v7cudaPointersD[136] + #define d_BSIM4v7gdtotsArray BSIM4v7cudaPointersD[137] + #define d_BSIM4v7vfbzbArray BSIM4v7cudaPointersD[138] + #define d_BSIM4v7gIgssArray BSIM4v7cudaPointersD[139] + #define d_BSIM4v7gIgddArray BSIM4v7cudaPointersD[140] + #define d_BSIM4v7gIgbsArray BSIM4v7cudaPointersD[141] + #define d_BSIM4v7gIgcssArray BSIM4v7cudaPointersD[142] + #define d_BSIM4v7gIgcdsArray BSIM4v7cudaPointersD[143] + #define d_BSIM4v7noiGd0Array BSIM4v7cudaPointersD[144] + #define d_BSIM4v7cqdbArray BSIM4v7cudaPointersD[145] + #define d_BSIM4v7cqsbArray BSIM4v7cudaPointersD[146] + #define d_BSIM4v7cqgbArray BSIM4v7cudaPointersD[147] + #define d_BSIM4v7qchqsArray BSIM4v7cudaPointersD[148] + #define d_BSIM4v7cqbbArray BSIM4v7cudaPointersD[149] + #define d_BSIM4v7taunetArray BSIM4v7cudaPointersD[150] + #define d_BSIM4v7gtgArray BSIM4v7cudaPointersD[151] + #define d_BSIM4v7gtdArray BSIM4v7cudaPointersD[152] + #define d_BSIM4v7gtsArray BSIM4v7cudaPointersD[153] + #define d_BSIM4v7gtbArray BSIM4v7cudaPointersD[154] + #define d_BSIM4v7mArray BSIM4v7cudaPointersD[155] + #define d_BSIM4v7grbpdArray BSIM4v7cudaPointersD[156] + #define d_BSIM4v7grbdbArray BSIM4v7cudaPointersD[157] + #define d_BSIM4v7grbpbArray BSIM4v7cudaPointersD[158] + #define d_BSIM4v7grbpsArray BSIM4v7cudaPointersD[159] + #define d_BSIM4v7grbsbArray BSIM4v7cudaPointersD[160] + #define d_BSIM4v7dNodePrimeRHSValueArray BSIM4v7cudaPointersD[161] + #define d_BSIM4v7gNodePrimeRHSValueArray BSIM4v7cudaPointersD[162] + #define d_BSIM4v7gNodeExtRHSValueArray BSIM4v7cudaPointersD[163] + #define d_BSIM4v7gNodeMidRHSValueArray BSIM4v7cudaPointersD[164] + #define d_BSIM4v7bNodePrimeRHSValueArray BSIM4v7cudaPointersD[165] + #define d_BSIM4v7sNodePrimeRHSValueArray BSIM4v7cudaPointersD[166] + #define d_BSIM4v7dbNodeRHSValueArray BSIM4v7cudaPointersD[167] + #define d_BSIM4v7sbNodeRHSValueArray BSIM4v7cudaPointersD[168] + #define d_BSIM4v7dNodeRHSValueArray BSIM4v7cudaPointersD[169] + #define d_BSIM4v7sNodeRHSValueArray BSIM4v7cudaPointersD[170] + #define d_BSIM4v7qNodeRHSValueArray BSIM4v7cudaPointersD[171] + #define d_BSIM4v7GEgeValueArray BSIM4v7cudaPointersD[172] + #define d_BSIM4v7GPgeValueArray BSIM4v7cudaPointersD[173] + #define d_BSIM4v7GEgpValueArray BSIM4v7cudaPointersD[174] + #define d_BSIM4v7GPgpValueArray BSIM4v7cudaPointersD[175] + #define d_BSIM4v7GPdpValueArray BSIM4v7cudaPointersD[176] + #define d_BSIM4v7GPspValueArray BSIM4v7cudaPointersD[177] + #define d_BSIM4v7GPbpValueArray BSIM4v7cudaPointersD[178] + #define d_BSIM4v7GEdpValueArray BSIM4v7cudaPointersD[179] + #define d_BSIM4v7GEspValueArray BSIM4v7cudaPointersD[180] + #define d_BSIM4v7GEbpValueArray BSIM4v7cudaPointersD[181] + #define d_BSIM4v7GEgmValueArray BSIM4v7cudaPointersD[182] + #define d_BSIM4v7GMgeValueArray BSIM4v7cudaPointersD[183] + #define d_BSIM4v7GMgmValueArray BSIM4v7cudaPointersD[184] + #define d_BSIM4v7GMdpValueArray BSIM4v7cudaPointersD[185] + #define d_BSIM4v7GMgpValueArray BSIM4v7cudaPointersD[186] + #define d_BSIM4v7GMspValueArray BSIM4v7cudaPointersD[187] + #define d_BSIM4v7GMbpValueArray BSIM4v7cudaPointersD[188] + #define d_BSIM4v7DPgmValueArray BSIM4v7cudaPointersD[189] + #define d_BSIM4v7GPgmValueArray BSIM4v7cudaPointersD[190] + #define d_BSIM4v7SPgmValueArray BSIM4v7cudaPointersD[191] + #define d_BSIM4v7BPgmValueArray BSIM4v7cudaPointersD[192] + #define d_BSIM4v7DgpValueArray BSIM4v7cudaPointersD[193] + #define d_BSIM4v7DspValueArray BSIM4v7cudaPointersD[194] + #define d_BSIM4v7DbpValueArray BSIM4v7cudaPointersD[195] + #define d_BSIM4v7SdpValueArray BSIM4v7cudaPointersD[196] + #define d_BSIM4v7SgpValueArray BSIM4v7cudaPointersD[197] + #define d_BSIM4v7SbpValueArray BSIM4v7cudaPointersD[198] + #define d_BSIM4v7DPdpValueArray BSIM4v7cudaPointersD[199] + #define d_BSIM4v7DPdValueArray BSIM4v7cudaPointersD[200] + #define d_BSIM4v7DPgpValueArray BSIM4v7cudaPointersD[201] + #define d_BSIM4v7DPspValueArray BSIM4v7cudaPointersD[202] + #define d_BSIM4v7DPbpValueArray BSIM4v7cudaPointersD[203] + #define d_BSIM4v7DdpValueArray BSIM4v7cudaPointersD[204] + #define d_BSIM4v7DdValueArray BSIM4v7cudaPointersD[205] + #define d_BSIM4v7SPdpValueArray BSIM4v7cudaPointersD[206] + #define d_BSIM4v7SPgpValueArray BSIM4v7cudaPointersD[207] + #define d_BSIM4v7SPspValueArray BSIM4v7cudaPointersD[208] + #define d_BSIM4v7SPsValueArray BSIM4v7cudaPointersD[209] + #define d_BSIM4v7SPbpValueArray BSIM4v7cudaPointersD[210] + #define d_BSIM4v7SspValueArray BSIM4v7cudaPointersD[211] + #define d_BSIM4v7SsValueArray BSIM4v7cudaPointersD[212] + #define d_BSIM4v7BPdpValueArray BSIM4v7cudaPointersD[213] + #define d_BSIM4v7BPgpValueArray BSIM4v7cudaPointersD[214] + #define d_BSIM4v7BPspValueArray BSIM4v7cudaPointersD[215] + #define d_BSIM4v7BPbpValueArray BSIM4v7cudaPointersD[216] + #define d_BSIM4v7DPdbValueArray BSIM4v7cudaPointersD[217] + #define d_BSIM4v7SPsbValueArray BSIM4v7cudaPointersD[218] + #define d_BSIM4v7DBdpValueArray BSIM4v7cudaPointersD[219] + #define d_BSIM4v7DBdbValueArray BSIM4v7cudaPointersD[220] + #define d_BSIM4v7DBbpValueArray BSIM4v7cudaPointersD[221] + #define d_BSIM4v7DBbValueArray BSIM4v7cudaPointersD[222] + #define d_BSIM4v7BPdbValueArray BSIM4v7cudaPointersD[223] + #define d_BSIM4v7BPbValueArray BSIM4v7cudaPointersD[224] + #define d_BSIM4v7BPsbValueArray BSIM4v7cudaPointersD[225] + #define d_BSIM4v7BPbpIFValueArray BSIM4v7cudaPointersD[226] + #define d_BSIM4v7SBspValueArray BSIM4v7cudaPointersD[227] + #define d_BSIM4v7SBbpValueArray BSIM4v7cudaPointersD[228] + #define d_BSIM4v7SBbValueArray BSIM4v7cudaPointersD[229] + #define d_BSIM4v7SBsbValueArray BSIM4v7cudaPointersD[230] + #define d_BSIM4v7BdbValueArray BSIM4v7cudaPointersD[231] + #define d_BSIM4v7BbpValueArray BSIM4v7cudaPointersD[232] + #define d_BSIM4v7BsbValueArray BSIM4v7cudaPointersD[233] + #define d_BSIM4v7BbValueArray BSIM4v7cudaPointersD[234] + #define d_BSIM4v7QqValueArray BSIM4v7cudaPointersD[235] + #define d_BSIM4v7QgpValueArray BSIM4v7cudaPointersD[236] + #define d_BSIM4v7QdpValueArray BSIM4v7cudaPointersD[237] + #define d_BSIM4v7QspValueArray BSIM4v7cudaPointersD[238] + #define d_BSIM4v7QbpValueArray BSIM4v7cudaPointersD[239] + #define d_BSIM4v7DPqValueArray BSIM4v7cudaPointersD[240] + #define d_BSIM4v7SPqValueArray BSIM4v7cudaPointersD[241] + #define d_BSIM4v7GPqValueArray BSIM4v7cudaPointersD[242] + + int *BSIM4v7cudaPointersI [18]; + #define d_BSIM4v7offArray BSIM4v7cudaPointersI[0] + #define d_BSIM4v7dNodePrimeArray BSIM4v7cudaPointersI[1] + #define d_BSIM4v7sNodePrimeArray BSIM4v7cudaPointersI[2] + #define d_BSIM4v7gNodePrimeArray BSIM4v7cudaPointersI[3] + #define d_BSIM4v7bNodePrimeArray BSIM4v7cudaPointersI[4] + #define d_BSIM4v7gNodeExtArray BSIM4v7cudaPointersI[5] + #define d_BSIM4v7gNodeMidArray BSIM4v7cudaPointersI[6] + #define d_BSIM4v7dbNodeArray BSIM4v7cudaPointersI[7] + #define d_BSIM4v7sbNodeArray BSIM4v7cudaPointersI[8] + #define d_BSIM4v7sNodeArray BSIM4v7cudaPointersI[9] + #define d_BSIM4v7dNodeArray BSIM4v7cudaPointersI[10] + #define d_BSIM4v7qNodeArray BSIM4v7cudaPointersI[11] + #define d_BSIM4v7rbodyModArray BSIM4v7cudaPointersI[12] + #define d_BSIM4v7modeArray BSIM4v7cudaPointersI[13] + #define d_BSIM4v7rgateModArray BSIM4v7cudaPointersI[14] + #define d_BSIM4v7trnqsModArray BSIM4v7cudaPointersI[15] + #define d_BSIM4v7acnqsModArray BSIM4v7cudaPointersI[16] + #define d_BSIM4v7statesArray BSIM4v7cudaPointersI[17] +} BSIM4v7paramGPUstruct; +#endif typedef struct sBSIM4v7model { @@ -2791,6 +3328,27 @@ typedef struct sBSIM4v7model unsigned BSIM4v7pk2weGiven :1; unsigned BSIM4v7pku0weGiven :1; +#ifdef USE_CUSPICE + struct bsim4SizeDependParam **d_pParam; + struct bsim4SizeDependParam **pParamHost; + + BSIM4v7paramCPUstruct BSIM4v7paramCPU; + BSIM4v7paramGPUstruct BSIM4v7paramGPU; + + int offset; + int n_values; + int n_Ptr; + int *PositionVector; + int *d_PositionVector; + + int offsetRHS; + int n_valuesRHS; + int n_PtrRHS; + int *PositionVectorRHS; + int *d_PositionVectorRHS; + + int n_instances; +#endif } BSIM4v7model; diff --git a/src/spicelib/devices/bsim4v7/bsim4v7ext.h b/src/spicelib/devices/bsim4v7/bsim4v7ext.h index 9bd0f532a..d09a77819 100644 --- a/src/spicelib/devices/bsim4v7/bsim4v7ext.h +++ b/src/spicelib/devices/bsim4v7/bsim4v7ext.h @@ -35,3 +35,7 @@ extern int BSIM4v7bindCSC (GENmodel*, CKTcircuit*) ; extern int BSIM4v7bindCSCComplex (GENmodel*, CKTcircuit*) ; extern int BSIM4v7bindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef USE_CUSPICE +extern int BSIM4v7topology (GENmodel *, CKTcircuit *, int *, int *); +#endif diff --git a/src/spicelib/devices/bsim4v7/bsim4v7init.c b/src/spicelib/devices/bsim4v7/bsim4v7init.c index 04a1fb591..f30439bd6 100644 --- a/src/spicelib/devices/bsim4v7/bsim4v7init.c +++ b/src/spicelib/devices/bsim4v7/bsim4v7init.c @@ -6,6 +6,9 @@ #include "bsim4v7ext.h" #include "bsim4v7init.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev BSIM4v7info = { .DEVpublic = { @@ -33,7 +36,11 @@ SPICEdev BSIM4v7info = { .DEVparam = BSIM4v7param, .DEVmodParam = BSIM4v7mParam, +#ifdef USE_CUSPICE + .DEVload = cuBSIM4v7load, +#else .DEVload = BSIM4v7load, +#endif .DEVsetup = BSIM4v7setup, .DEVunsetup = BSIM4v7unsetup, .DEVpzSetup = BSIM4v7setup, @@ -71,6 +78,10 @@ SPICEdev BSIM4v7info = { .DEVbindCSCComplex = BSIM4v7bindCSCComplex, .DEVbindCSCComplexToReal = BSIM4v7bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuBSIM4v7destroy, + .DEVtopology = BSIM4v7topology, +#endif }; diff --git a/src/spicelib/devices/bsimsoi/b4soiinit.c b/src/spicelib/devices/bsimsoi/b4soiinit.c index fe110e4f0..6a0c8d709 100644 --- a/src/spicelib/devices/bsimsoi/b4soiinit.c +++ b/src/spicelib/devices/bsimsoi/b4soiinit.c @@ -69,6 +69,10 @@ SPICEdev B4SOIinfo = { .DEVbindCSCComplex = B4SOIbindCSCComplex, .DEVbindCSCComplexToReal = B4SOIbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; @@ -77,5 +81,3 @@ get_b4soi_info (void) { return &B4SOIinfo; } - - diff --git a/src/spicelib/devices/cap/CUSPICE/captopology.c b/src/spicelib/devices/cap/CUSPICE/captopology.c new file mode 100644 index 000000000..9214945f2 --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/captopology.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "capdefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +#define TopologyMatrixInsertRHS(offset, instance_ID, offsetRHS, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOiRHS [global_ID] = here->offset ; \ + ckt->CKTtopologyMatrixCOOjRHS [global_ID] = model->PositionVectorRHS [instance_ID] + offsetRHS ; \ + ckt->CKTtopologyMatrixCOOxRHS [global_ID] = Value ; + +int +CAPtopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + CAPmodel *model = (CAPmodel *)inModel ; + CAPinstance *here ; + int k ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the capacitor models */ + for ( ; model != NULL ; model = CAPnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = CAPinstances(model); here != NULL ; here = CAPnextInstance(here)) + { + if ((here->CAPposNode != 0) && (here->CAPposNode != 0)) + { + TopologyMatrixInsert (CAPposPosPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->CAPnegNode != 0) && (here->CAPnegNode != 0)) + { + TopologyMatrixInsert (CAPnegNegPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->CAPposNode != 0) && (here->CAPnegNode != 0)) + { + TopologyMatrixInsert (CAPposNegPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->CAPnegNode != 0) && (here->CAPposNode != 0)) + { + TopologyMatrixInsert (CAPnegPosPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if (here->CAPposNode != 0) + { + TopologyMatrixInsertRHS (CAPposNode, k, 0, -1, *j) ; + (*j)++ ; + } + + if (here->CAPnegNode != 0) + { + TopologyMatrixInsertRHS (CAPnegNode, k, 0, 1, *j) ; + (*j)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/cucapfree.c b/src/spicelib/devices/cap/CUSPICE/cucapfree.c new file mode 100644 index 000000000..68aa5511c --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/cucapfree.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "capdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuCAPdestroy +( +GENmodel *inModel +) +{ + CAPmodel *model = (CAPmodel *)inModel ; + + for ( ; model != NULL ; model = CAPnextModel(model)) + { + /* DOUBLE */ + free (model->CAPparamCPU.CAPinitCondArray) ; + cudaFree (model->CAPparamGPU.d_CAPinitCondArray) ; + + free (model->CAPparamCPU.CAPcapacArray) ; + cudaFree (model->CAPparamGPU.d_CAPcapacArray) ; + + free (model->CAPparamCPU.CAPmArray) ; + cudaFree (model->CAPparamGPU.d_CAPmArray) ; + + free (model->CAPparamCPU.CAPgeqValueArray) ; + cudaFree (model->CAPparamGPU.d_CAPgeqValueArray) ; + + free (model->CAPparamCPU.CAPceqValueArray) ; + cudaFree (model->CAPparamGPU.d_CAPceqValueArray) ; + + /* INT */ + free (model->CAPparamCPU.CAPposNodeArray) ; + cudaFree (model->CAPparamGPU.d_CAPposNodeArray) ; + + free (model->CAPparamCPU.CAPnegNodeArray) ; + cudaFree (model->CAPparamGPU.d_CAPnegNodeArray) ; + + free (model->CAPparamCPU.CAPstateArray) ; + cudaFree (model->CAPparamGPU.d_CAPstateArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/cucapgetic.c b/src/spicelib/devices/cap/CUSPICE/cucapgetic.c new file mode 100644 index 000000000..62b75f566 --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/cucapgetic.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "capdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCAPgetic routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCAPgetic +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + CAPmodel *model = (CAPmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + status = cudaMemcpy (model->CAPparamGPU.d_CAPinitCondArray, model->CAPparamCPU.CAPinitCondArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.d_CAPinitCondArray, size, double, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/cucapload.cu b/src/spicelib/devices/cap/CUSPICE/cucapload.cu new file mode 100644 index 000000000..cf4de91d3 --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/cucapload.cu @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "capdefs.h" + +extern "C" +__global__ void cuCAPload_kernel (CAPparamGPUstruct, double *, double *, double *, + int, double, double, int, int, int, int *, double *, int *, double *) ; + +extern "C" +int +cuCAPload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + CAPmodel *model = (CAPmodel *)inModel ; + int cond1, thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* check if capacitors are in the circuit or are open circuited */ + if (ckt->CKTmode & (MODETRAN|MODEAC|MODETRANOP)) + { + /* evaluate device independent analysis conditions */ + cond1 = (((ckt->CKTmode & MODEDC) && (ckt->CKTmode & MODEINITJCT)) + || ((ckt->CKTmode & MODEUIC) && (ckt->CKTmode & MODEINITTRAN))) ; + + /* loop through all the resistor models */ + for ( ; model != NULL ; model = CAPnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)((model->n_instances + thread_y - 1) / thread_y) ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuCAPload_kernel <<< block_x, thread >>> (model->CAPparamGPU, ckt->d_CKTrhsOld, ckt->d_CKTstate0, + ckt->d_CKTstate1, ckt->CKTmode, ckt->CKTag [0], ckt->CKTag [1], + ckt->CKTorder, model->n_instances, cond1, + model->d_PositionVector, ckt->d_CKTloadOutput, + model->d_PositionVectorRHS, ckt->d_CKTloadOutputRHS) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Capacitor Model\n\n") ; + return (E_NOMEM) ; + } + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuCAPload_kernel +( +CAPparamGPUstruct CAPentry, double *CKTrhsOld, double *CKTstate_0, +double *CKTstate_1, int CKTmode, double CKTag_0, double CKTag_1, +int CKTorder, int n_instances, int cond1, int *d_PositionVector, +double *d_CKTloadOutput, int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID ; + double vcap, geq, ceq, m ; + int error ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < n_instances) + { + if (threadIdx.x == 0) + { + m = CAPentry.d_CAPmArray [instance_ID] ; + + if (cond1) + { + vcap = CAPentry.d_CAPinitCondArray [instance_ID] ; + } else { + vcap = CKTrhsOld [CAPentry.d_CAPposNodeArray [instance_ID]] - + CKTrhsOld [CAPentry.d_CAPnegNodeArray [instance_ID]] ; + } + + if (CKTmode & (MODETRAN | MODEAC)) + { +#ifndef PREDICTOR + if (CKTmode & MODEINITPRED) + { + CKTstate_0 [CAPentry.d_CAPstateArray [instance_ID]] = + CKTstate_1 [CAPentry.d_CAPstateArray [instance_ID]] ; + } else { /* only const caps - no poly's */ +#endif /* PREDICTOR */ + CKTstate_0 [CAPentry.d_CAPstateArray [instance_ID]] = CAPentry.d_CAPcapacArray [instance_ID] * vcap ; + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [CAPentry.d_CAPstateArray [instance_ID]] = + CKTstate_0 [CAPentry.d_CAPstateArray [instance_ID]] ; + } +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, + CAPentry.d_CAPcapacArray [instance_ID], + CAPentry.d_CAPstateArray [instance_ID], + CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Error in the integration!\n\n") ; + //return (error) ; + + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [CAPentry.d_CAPstateArray [instance_ID] + 1] = + CKTstate_0 [CAPentry.d_CAPstateArray [instance_ID] + 1] ; + } + + d_CKTloadOutput [d_PositionVector [instance_ID]] = m * geq ; + d_CKTloadOutputRHS [d_PositionVectorRHS [instance_ID]] = m * ceq ; + + } else { + CKTstate_0 [CAPentry.d_CAPstateArray [instance_ID]] = CAPentry.d_CAPcapacArray [instance_ID] * vcap ; + } + } + } + + return ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/cucapsetup.c b/src/spicelib/devices/cap/CUSPICE/cucapsetup.c new file mode 100644 index 000000000..bf3f25dd5 --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/cucapsetup.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "capdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCAPsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCAPsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCAPsetup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + CAPmodel *model = (CAPmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size, int, status) + + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, size, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, size, int, status) + + /* DOUBLE */ + model->CAPparamCPU.CAPinitCondArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPinitCondArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPinitCondArray, size, double, status) + + model->CAPparamCPU.CAPcapacArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPcapacArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPcapacArray, size, double, status) + + model->CAPparamCPU.CAPmArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPmArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPmArray, size, double, status) + + model->CAPparamCPU.CAPgeqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPgeqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPgeqValueArray, size, double, status) + + model->CAPparamCPU.CAPceqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPceqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPceqValueArray, size, double, status) + + /* INT */ + model->CAPparamCPU.CAPposNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPposNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPposNodeArray, size, int, status) + + model->CAPparamCPU.CAPnegNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPnegNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPnegNodeArray, size, int, status) + + model->CAPparamCPU.CAPstateArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->CAPparamGPU.d_CAPstateArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->CAPparamGPU.d_CAPstateArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/cucaptemp.c b/src/spicelib/devices/cap/CUSPICE/cucaptemp.c new file mode 100644 index 000000000..2adf40bd6 --- /dev/null +++ b/src/spicelib/devices/cap/CUSPICE/cucaptemp.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "capdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuCAPtemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuCAPtemp +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + CAPmodel *model = (CAPmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* DOUBLE */ + status = cudaMemcpy (model->CAPparamGPU.d_CAPcapacArray, model->CAPparamCPU.CAPcapacArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.d_CAPcapacArray, size, double, status) + + status = cudaMemcpy (model->CAPparamGPU.d_CAPmArray, model->CAPparamCPU.CAPmArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.d_CAPmArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->CAPparamGPU.d_CAPposNodeArray, model->CAPparamCPU.CAPposNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.d_CAPposNodeArray, size, int, status) + + status = cudaMemcpy (model->CAPparamGPU.d_CAPnegNodeArray, model->CAPparamCPU.CAPnegNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.d_CAPnegNodeArray, size, int, status) + + status = cudaMemcpy (model->CAPparamGPU.d_CAPstateArray, model->CAPparamCPU.CAPstateArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->CAPparamGPU.CAPstateArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/Makefile.am b/src/spicelib/devices/cap/Makefile.am index e0916e32b..9feadb584 100644 --- a/src/spicelib/devices/cap/Makefile.am +++ b/src/spicelib/devices/cap/Makefile.am @@ -38,4 +38,19 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libcap_la_SOURCES += \ + CUSPICE/captopology.c \ + CUSPICE/cucapfree.c \ + CUSPICE/cucapgetic.c \ + CUSPICE/cucapload.cu \ + CUSPICE/cucapsetup.c \ + CUSPICE/cucaptemp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/cap/capdefs.h b/src/spicelib/devices/cap/capdefs.h index af355cb54..cacf099c2 100644 --- a/src/spicelib/devices/cap/capdefs.h +++ b/src/spicelib/devices/cap/capdefs.h @@ -79,6 +79,35 @@ typedef struct sCAPinstance { +3 for the derivatives - pointer to the beginning of the array */ +#ifdef USE_CUSPICE +typedef struct sCAPparamCPUstruct { + double *CAPcpuPointersD [5] ; + #define CAPinitCondArray CAPcpuPointersD[0] + #define CAPcapacArray CAPcpuPointersD[1] + #define CAPmArray CAPcpuPointersD[2] + #define CAPgeqValueArray CAPcpuPointersD[3] + #define CAPceqValueArray CAPcpuPointersD[4] + + int *CAPcpuPointersI [3] ; + #define CAPposNodeArray CAPcpuPointersI[0] + #define CAPnegNodeArray CAPcpuPointersI[1] + #define CAPstateArray CAPcpuPointersI[2] +} CAPparamCPUstruct ; + +typedef struct sCAPparamGPUstruct { + double *CAPcudaPointersD [5] ; + #define d_CAPinitCondArray CAPcudaPointersD[0] + #define d_CAPcapacArray CAPcudaPointersD[1] + #define d_CAPmArray CAPcudaPointersD[2] + #define d_CAPgeqValueArray CAPcudaPointersD[3] + #define d_CAPceqValueArray CAPcudaPointersD[4] + + int *CAPcudaPointersI [3] ; + #define d_CAPposNodeArray CAPcudaPointersI[0] + #define d_CAPnegNodeArray CAPcudaPointersI[1] + #define d_CAPstateArray CAPcudaPointersI[2] +} CAPparamGPUstruct ; +#endif /* data per model */ @@ -120,6 +149,25 @@ typedef struct sCAPmodel { /* model structure for a capacitor */ unsigned CAPthickGiven : 1; /* flags indicates insulator thickness given */ unsigned CAPbv_maxGiven : 1; /* flags indicates maximum voltage is given */ +#ifdef USE_CUSPICE + CAPparamCPUstruct CAPparamCPU ; + CAPparamGPUstruct CAPparamGPU ; + + int offset ; + int n_values ; + int n_Ptr ; + int *PositionVector ; + int *d_PositionVector ; + + int offsetRHS ; + int n_valuesRHS ; + int n_PtrRHS ; + int *PositionVectorRHS ; + int *d_PositionVectorRHS ; + + int n_instances ; +#endif + } CAPmodel; /* device parameters */ diff --git a/src/spicelib/devices/cap/capext.h b/src/spicelib/devices/cap/capext.h index 51308524d..b0bbd8df7 100644 --- a/src/spicelib/devices/cap/capext.h +++ b/src/spicelib/devices/cap/capext.h @@ -29,3 +29,7 @@ extern int CAPbindCSC (GENmodel*, CKTcircuit*) ; extern int CAPbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int CAPbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef USE_CUSPICE +extern int CAPtopology (GENmodel *, CKTcircuit *, int *, int *) ; +#endif diff --git a/src/spicelib/devices/cap/capinit.c b/src/spicelib/devices/cap/capinit.c index cab0599ba..0ed91c225 100644 --- a/src/spicelib/devices/cap/capinit.c +++ b/src/spicelib/devices/cap/capinit.c @@ -6,6 +6,9 @@ #include "capext.h" #include "capinit.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev CAPinfo = { .DEVpublic = { @@ -33,7 +36,11 @@ SPICEdev CAPinfo = { .DEVparam = CAPparam, .DEVmodParam = CAPmParam, +#ifdef USE_CUSPICE + .DEVload = cuCAPload, +#else .DEVload = CAPload, +#endif .DEVsetup = CAPsetup, .DEVunsetup = NULL, .DEVpzSetup = CAPsetup, @@ -71,6 +78,10 @@ SPICEdev CAPinfo = { .DEVbindCSCComplex = CAPbindCSCComplex, .DEVbindCSCComplexToReal = CAPbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuCAPdestroy, + .DEVtopology = CAPtopology, +#endif }; diff --git a/src/spicelib/devices/cap/capsetup.c b/src/spicelib/devices/cap/capsetup.c index c003bd57a..a9c79c91b 100644 --- a/src/spicelib/devices/cap/capsetup.c +++ b/src/spicelib/devices/cap/capsetup.c @@ -12,6 +12,9 @@ Modified: September 2003 Paolo Nenzi #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif /*ARGSUSED*/ int @@ -117,6 +120,92 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ TSTALLOC(CAPnegPosPtr,CAPnegNode,CAPposNode); } } + +#ifdef USE_CUSPICE + int i, j, k, status ; + + /* Counting the instances */ + for (model = (CAPmodel *)inModel ; model != NULL ; model = CAPnextModel(model)) + { + i = 0 ; + + for (here = CAPinstances(model); here != NULL ; here = CAPnextInstance(here)) + { + i++ ; + } + + /* How much instances we have */ + model->n_instances = i ; + } + + /* loop through all the capacitor models */ + for (model = (CAPmodel *)inModel ; model != NULL ; model = CAPnextModel(model)) + { + model->offset = ckt->total_n_values ; + model->offsetRHS = ckt->total_n_valuesRHS ; + + j = 0 ; + k = 0 ; + + /* loop through all the instances of the model */ + for (here = CAPinstances(model); here != NULL ; here = CAPnextInstance(here)) + { + /* For the Matrix */ + if ((here->CAPposNode != 0) && (here->CAPposNode != 0)) + j++ ; + + if ((here->CAPnegNode != 0) && (here->CAPnegNode != 0)) + j++ ; + + if ((here->CAPposNode != 0) && (here->CAPnegNode != 0)) + j++ ; + + if ((here->CAPnegNode != 0) && (here->CAPposNode != 0)) + j++ ; + + /* For the RHS */ + if (here->CAPposNode != 0) + k++ ; + + if (here->CAPnegNode != 0) + k++ ; + } + + model->n_values = model->n_instances; + ckt->total_n_values += model->n_values ; + + model->n_Ptr = j ; + ckt->total_n_Ptr += model->n_Ptr ; + + model->n_valuesRHS = model->n_instances; + ckt->total_n_valuesRHS += model->n_valuesRHS ; + + model->n_PtrRHS = k ; + ckt->total_n_PtrRHS += model->n_PtrRHS ; + + + /* Position Vector assignment */ + model->PositionVector = TMALLOC (int, model->n_instances) ; + + for (j = 0 ; j < model->n_instances; j++) + model->PositionVector [j] = model->offset + j ; + + /* Position Vector assignment for the RHS */ + model->PositionVectorRHS = TMALLOC (int, model->n_instances) ; + + for (j = 0 ; j < model->n_instances; j++) + model->PositionVectorRHS [j] = model->offsetRHS + j ; + } + + /* loop through all the capacitor models */ + for (model = (CAPmodel *)inModel ; model != NULL ; model = CAPnextModel(model)) + { + status = cuCAPsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } +#endif + return(OK); } diff --git a/src/spicelib/devices/cap/captemp.c b/src/spicelib/devices/cap/captemp.c index 926a3c666..b3cdd38c0 100644 --- a/src/spicelib/devices/cap/captemp.c +++ b/src/spicelib/devices/cap/captemp.c @@ -16,6 +16,9 @@ Modified: September 2003 Paolo Nenzi #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif /*ARGSUSED*/ int @@ -28,9 +31,17 @@ CAPtemp(GENmodel *inModel, CKTcircuit *ckt) double factor; double tc1, tc2; +#ifdef USE_CUSPICE + int i, status ; +#endif + /* loop through all the capacitor models */ for( ; model != NULL; model = CAPnextModel(model)) { +#ifdef USE_CUSPICE + i = 0 ; +#endif + /* loop through all the instances of the model */ for (here = CAPinstances(model); here != NULL ; here=CAPnextInstance(here)) { @@ -85,8 +96,25 @@ CAPtemp(GENmodel *inModel, CKTcircuit *ckt) here->CAPcapac = here->CAPcapac * factor * here->CAPscale; +#ifdef USE_CUSPICE + model->CAPparamCPU.CAPcapacArray[i] = here->CAPcapac ; + model->CAPparamCPU.CAPmArray[i] = here->CAPm ; + model->CAPparamCPU.CAPposNodeArray[i] = here->CAPposNode ; + model->CAPparamCPU.CAPnegNodeArray[i] = here->CAPnegNode ; + model->CAPparamCPU.CAPstateArray[i] = here->CAPstate ; + + i++ ; +#endif + } + +#ifdef USE_CUSPICE + status = cuCAPtemp ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } - return(OK); + return (OK) ; } diff --git a/src/spicelib/devices/cccs/cccsinit.c b/src/spicelib/devices/cccs/cccsinit.c index 16235b406..7d323efd0 100644 --- a/src/spicelib/devices/cccs/cccsinit.c +++ b/src/spicelib/devices/cccs/cccsinit.c @@ -71,6 +71,10 @@ SPICEdev CCCSinfo = { .DEVbindCSCComplex = CCCSbindCSCComplex, .DEVbindCSCComplexToReal = CCCSbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/ccvs/ccvsinit.c b/src/spicelib/devices/ccvs/ccvsinit.c index 57b4d8083..5d4bdffd1 100644 --- a/src/spicelib/devices/ccvs/ccvsinit.c +++ b/src/spicelib/devices/ccvs/ccvsinit.c @@ -71,6 +71,10 @@ SPICEdev CCVSinfo = { .DEVbindCSCComplex = CCVSbindCSCComplex, .DEVbindCSCComplexToReal = CCVSbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/cpl/cplinit.c b/src/spicelib/devices/cpl/cplinit.c index 05bb0c51a..dea3b58b2 100644 --- a/src/spicelib/devices/cpl/cplinit.c +++ b/src/spicelib/devices/cpl/cplinit.c @@ -71,6 +71,10 @@ SPICEdev CPLinfo = { .DEVbindCSCComplex = CPLbindCSCComplex, .DEVbindCSCComplexToReal = CPLbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/csw/cswinit.c b/src/spicelib/devices/csw/cswinit.c index 65e1b3a07..ca3a4373a 100644 --- a/src/spicelib/devices/csw/cswinit.c +++ b/src/spicelib/devices/csw/cswinit.c @@ -73,6 +73,10 @@ SPICEdev CSWinfo = { .DEVbindCSCComplex = CSWbindCSCComplex, .DEVbindCSCComplexToReal = CSWbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/dio/dioinit.c b/src/spicelib/devices/dio/dioinit.c index 6cd494b81..545f77297 100644 --- a/src/spicelib/devices/dio/dioinit.c +++ b/src/spicelib/devices/dio/dioinit.c @@ -72,9 +72,12 @@ SPICEdev DIOinfo = { .DEVbindCSCComplex = DIObindCSCComplex, .DEVbindCSCComplexToReal = DIObindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_dio_info(void) { diff --git a/src/spicelib/devices/hfet1/hfetinit.c b/src/spicelib/devices/hfet1/hfetinit.c index 422dafe35..15b8b1e1a 100644 --- a/src/spicelib/devices/hfet1/hfetinit.c +++ b/src/spicelib/devices/hfet1/hfetinit.c @@ -71,6 +71,10 @@ SPICEdev HFETAinfo = { .DEVbindCSCComplex = HFETAbindCSC, .DEVbindCSCComplexToReal = HFETAbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/hfet2/hfet2init.c b/src/spicelib/devices/hfet2/hfet2init.c index c29dc8407..3431b5c09 100644 --- a/src/spicelib/devices/hfet2/hfet2init.c +++ b/src/spicelib/devices/hfet2/hfet2init.c @@ -71,9 +71,12 @@ SPICEdev HFET2info = { .DEVbindCSCComplex = HFET2bindCSCComplex, .DEVbindCSCComplexToReal = HFET2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_hfet2_info(void) { diff --git a/src/spicelib/devices/hisim2/hsm2init.c b/src/spicelib/devices/hisim2/hsm2init.c index b887560a4..255dd4b64 100644 --- a/src/spicelib/devices/hisim2/hsm2init.c +++ b/src/spicelib/devices/hisim2/hsm2init.c @@ -71,9 +71,12 @@ SPICEdev HSM2info = { .DEVbindCSCComplex = HSM2bindCSCComplex, .DEVbindCSCComplexToReal = HSM2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_hsm2_info(void) { diff --git a/src/spicelib/devices/hisimhv1/hsmhvinit.c b/src/spicelib/devices/hisimhv1/hsmhvinit.c index e79ce69e4..b475949cb 100644 --- a/src/spicelib/devices/hisimhv1/hsmhvinit.c +++ b/src/spicelib/devices/hisimhv1/hsmhvinit.c @@ -71,9 +71,12 @@ SPICEdev HSMHVinfo = { .DEVbindCSCComplex = HSMHVbindCSCComplex, .DEVbindCSCComplexToReal = HSMHVbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_hsmhv_info(void) { diff --git a/src/spicelib/devices/ind/CUSPICE/cuindfree.c b/src/spicelib/devices/ind/CUSPICE/cuindfree.c new file mode 100644 index 000000000..f59d63148 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cuindfree.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuINDdestroy +( +GENmodel *inModel +) +{ + INDmodel *model = (INDmodel *)inModel ; + + for ( ; model != NULL ; model = INDnextModel(model)) + { + /* DOUBLE */ + free (model->INDparamCPU.INDinitCondArray) ; + cudaFree (model->INDparamGPU.d_INDinitCondArray) ; + + free (model->INDparamCPU.INDinductArray) ; + cudaFree (model->INDparamGPU.d_INDinductArray) ; + + free (model->INDparamCPU.INDreqValueArray) ; + cudaFree (model->INDparamGPU.d_INDreqValueArray) ; + + free (model->INDparamCPU.INDveqValueArray) ; + cudaFree (model->INDparamGPU.d_INDveqValueArray) ; + + /* INT */ + free (model->INDparamCPU.INDbrEqArray) ; + cudaFree (model->INDparamGPU.d_INDbrEqArray) ; + + free (model->INDparamCPU.INDstateArray) ; + cudaFree (model->INDparamGPU.d_INDstateArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cuindload.cu b/src/spicelib/devices/ind/CUSPICE/cuindload.cu new file mode 100644 index 000000000..e5c699113 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cuindload.cu @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "inddefs.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuINDload routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuINDload routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +extern "C" +__global__ void cuINDload_kernel (INDparamGPUstruct, double *, double *, double *, int, double, double, int, int, int *, double *, int *, double *) ; + +extern "C" +int +cuINDload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + INDmodel *model = (INDmodel *)inModel ; + int thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* loop through all the inductor models */ + for ( ; model != NULL ; model = INDnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)(model->n_instances / thread_y) + 1 ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuINDload_kernel <<< block_x, thread >>> (model->INDparamGPU, ckt->d_CKTrhsOld, ckt->d_CKTstate0, + ckt->d_CKTstate1, ckt->CKTmode, ckt->CKTag [0], ckt->CKTag [1], + ckt->CKTorder, model->n_instances, + model->d_PositionVector, ckt->d_CKTloadOutput, + model->d_PositionVectorRHS, ckt->d_CKTloadOutputRHS) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Inductor Model\n\n") ; + return (E_NOMEM) ; + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuINDload_kernel +( +INDparamGPUstruct INDentry, double *CKTrhsOld, double *CKTstate_0, +double *CKTstate_1, int CKTmode, double CKTag_0, double CKTag_1, +int CKTorder, int ind_n_instances, +int *d_PositionVector, double *d_CKTloadOutput, +int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID ; + int error ; + double req, veq ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < ind_n_instances) + { + if (threadIdx.x == 0) + { + if (!(CKTmode & (MODEDC | MODEINITPRED))) + { + if (CKTmode & MODEUIC && CKTmode & MODEINITTRAN) + CKTstate_0 [INDentry.d_INDstateArray [instance_ID]] = + INDentry.d_INDinductArray [instance_ID] * INDentry.d_INDinitCondArray [instance_ID] ; + else + CKTstate_0 [INDentry.d_INDstateArray [instance_ID]] = + INDentry.d_INDinductArray [instance_ID] * CKTrhsOld [INDentry.d_INDbrEqArray [instance_ID]] ; + } + + if (CKTmode & MODEDC) + { + req = 0.0 ; + veq = 0.0 ; + } else { +#ifndef PREDICTOR + if (CKTmode & MODEINITPRED) + CKTstate_0 [INDentry.d_INDstateArray [instance_ID]] = + CKTstate_1 [INDentry.d_INDstateArray [instance_ID]] ; + else +#endif /*PREDICTOR*/ + if (CKTmode & MODEINITTRAN) + CKTstate_1 [INDentry.d_INDstateArray [instance_ID]] = + CKTstate_0 [INDentry.d_INDstateArray [instance_ID]] ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &req, &veq, + INDentry.d_INDinductArray [instance_ID], + INDentry.d_INDstateArray [instance_ID], + CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Error in the integration!\n\n") ; + //return (error) ; + } + + if (CKTmode & MODEINITTRAN) + CKTstate_1 [INDentry.d_INDstateArray [instance_ID] + 1] = + CKTstate_0 [INDentry.d_INDstateArray [instance_ID] + 1] ; + + /* Output for the Matrix */ + d_CKTloadOutput [d_PositionVector [instance_ID]] = 1.0 ; + d_CKTloadOutput [d_PositionVector [instance_ID] + 1] = req ; + + /* Output for the RHS */ + d_CKTloadOutputRHS [d_PositionVectorRHS [instance_ID]] = veq ; + } + } + + return ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cuindsetup.c b/src/spicelib/devices/ind/CUSPICE/cuindsetup.c new file mode 100644 index 000000000..2d266a4d8 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cuindsetup.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuINDsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuINDsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuINDsetup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + INDmodel *model = (INDmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size, int, status) + + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, size, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, size, int, status) + + /* DOUBLE */ + model->INDparamCPU.INDinitCondArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDinitCondArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDinitCondArray, size, double, status) + + model->INDparamCPU.INDinductArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDinductArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDinductArray, size, double, status) + + model->INDparamCPU.INDreqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDreqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDreqValueArray, size, double, status) + + model->INDparamCPU.INDveqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDveqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDveqValueArray, size, double, status) + + /* INT */ + model->INDparamCPU.INDbrEqArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDbrEqArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDbrEqArray, size, int, status) + + model->INDparamCPU.INDstateArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->INDparamGPU.d_INDstateArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->INDparamGPU.d_INDstateArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cuindtemp.c b/src/spicelib/devices/ind/CUSPICE/cuindtemp.c new file mode 100644 index 000000000..05d67a972 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cuindtemp.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuINDtemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuINDtemp +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + INDmodel *model = (INDmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* DOUBLE */ + status = cudaMemcpy (model->INDparamGPU.d_INDinitCondArray, model->INDparamCPU.INDinitCondArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->INDparamGPU.d_INDinitCondArray, size, double, status) + + status = cudaMemcpy (model->INDparamGPU.d_INDinductArray, model->INDparamCPU.INDinductArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->INDparamGPU.d_INDinductArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->INDparamGPU.d_INDbrEqArray, model->INDparamCPU.INDbrEqArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->INDparamGPU.d_INDbrEqArray, size, int, status) + + status = cudaMemcpy (model->INDparamGPU.d_INDstateArray, model->INDparamCPU.INDstateArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->INDparamGPU.INDstateArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cumutfree.c b/src/spicelib/devices/ind/CUSPICE/cumutfree.c new file mode 100644 index 000000000..957011b34 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cumutfree.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuMUTdestroy +( +GENmodel *inModel +) +{ + MUTmodel *model = (MUTmodel *)inModel ; + + for ( ; model != NULL ; model = MUTnextModel(model)) + { + /* DOUBLE */ + free (model->MUTparamCPU.MUTfactorArray) ; + cudaFree (model->MUTparamGPU.d_MUTfactorArray) ; + + /* INT */ + free (model->MUTparamCPU.MUTflux1Array) ; + cudaFree (model->MUTparamGPU.d_MUTflux1Array) ; + + free (model->MUTparamCPU.MUTflux2Array) ; + cudaFree (model->MUTparamGPU.d_MUTflux2Array) ; + + free (model->MUTparamCPU.MUTbrEq1Array) ; + cudaFree (model->MUTparamGPU.d_MUTbrEq1Array) ; + + free (model->MUTparamCPU.MUTbrEq2Array) ; + cudaFree (model->MUTparamGPU.d_MUTbrEq2Array) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cumutload.cu b/src/spicelib/devices/ind/CUSPICE/cumutload.cu new file mode 100644 index 000000000..56405c08e --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cumutload.cu @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "inddefs.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuMUTload routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuMUTload routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +extern "C" +__global__ void cuMUTload_kernel (MUTparamGPUstruct, double *, double *, double *, int, double, double, int, int, int *, double *, int *, double *) ; + +extern "C" +int +cuMUTload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + MUTmodel *model = (MUTmodel *)inModel ; + int thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* loop through all the mutual inductor models */ + for ( ; model != NULL ; model = MUTnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)(model->n_instances / thread_y) + 1 ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuMUTload_kernel <<< block_x, thread >>> (model->MUTparamGPU, ckt->d_CKTrhsOld, ckt->d_CKTstate0, + ckt->d_CKTstate1, ckt->CKTmode, ckt->CKTag [0], ckt->CKTag [1], + ckt->CKTorder, model->n_instances, + model->d_PositionVector, ckt->d_CKTloadOutput, + model->d_PositionVectorRHS, ckt->d_CKTloadOutputRHS) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Mutual Inductor Model\n\n") ; + return (E_NOMEM) ; + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuMUTload_kernel +( +MUTparamGPUstruct MUTentry, double *CKTrhsOld, double *CKTstate_0, +double *CKTstate_1, int CKTmode, double CKTag_0, double CKTag_1, +int CKTorder, int mut_n_instances, +int *d_PositionVector, double *d_CKTloadOutput, +int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID ; + int error ; + double req_dummy, veq ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < mut_n_instances) + { + if (threadIdx.x == 0) + { + if (!(CKTmode & (MODEDC | MODEINITPRED))) + { + CKTstate_0 [MUTentry.d_MUTflux1Array [instance_ID]] += MUTentry.d_MUTfactorArray [instance_ID] * CKTrhsOld [MUTentry.d_MUTbrEq2Array [instance_ID]] ; + CKTstate_0 [MUTentry.d_MUTflux2Array [instance_ID]] += MUTentry.d_MUTfactorArray [instance_ID] * CKTrhsOld [MUTentry.d_MUTbrEq1Array [instance_ID]] ; + } + + /* Inductor-related */ + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [MUTentry.d_MUTflux1Array [instance_ID]] = CKTstate_0 [MUTentry.d_MUTflux1Array [instance_ID]] ; + CKTstate_1 [MUTentry.d_MUTflux2Array [instance_ID]] = CKTstate_0 [MUTentry.d_MUTflux2Array [instance_ID]] ; + } + + if (!(CKTmode & MODEDC)) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &req_dummy, &veq, + 1.0, MUTentry.d_MUTflux1Array [instance_ID], + CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Error in the integration 1 of MUTload!\n\n") ; + + /* Output for the RHS */ + d_CKTloadOutputRHS [d_PositionVectorRHS [MUTentry.d_MUTinstanceIND1Array [instance_ID]]] = veq ; + + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &req_dummy, &veq, + 1.0, MUTentry.d_MUTflux2Array [instance_ID], + CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Error in the integration 2 of MUTload!\n\n") ; + + /* Output for the RHS */ + d_CKTloadOutputRHS [d_PositionVectorRHS [MUTentry.d_MUTinstanceIND2Array [instance_ID]]] = veq ; + } + + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [MUTentry.d_MUTflux1Array [instance_ID] + 1] = CKTstate_0 [MUTentry.d_MUTflux1Array [instance_ID] + 1] ; + CKTstate_1 [MUTentry.d_MUTflux2Array [instance_ID] + 1] = CKTstate_0 [MUTentry.d_MUTflux2Array [instance_ID] + 1] ; + + } + + d_CKTloadOutput [d_PositionVector [instance_ID]] = MUTentry.d_MUTfactorArray [instance_ID] * CKTag_0 ; + } + } + + return ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cumutsetup.c b/src/spicelib/devices/ind/CUSPICE/cumutsetup.c new file mode 100644 index 000000000..b5f39fb6e --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cumutsetup.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuMUTsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuMUTsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuMUTsetup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + MUTmodel *model = (MUTmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size, int, status) + + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), (long unsigned int)model->n_instancesRHS * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, (long unsigned int)model->n_instancesRHS, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, (long unsigned int)model->n_instancesRHS * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, (long unsigned int)model->n_instancesRHS, int, status) + + /* PARTICULAR SITUATION */ + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTinstanceIND1Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTinstanceIND1Array, size, int, status) + + status = cudaMemcpy (model->MUTparamGPU.d_MUTinstanceIND1Array, model->MUTparamCPU.MUTinstanceIND1Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->MUTparamGPU.d_MUTinstanceIND1Array, size, int, status) + + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTinstanceIND2Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTinstanceIND2Array, size, int, status) + + status = cudaMemcpy (model->MUTparamGPU.d_MUTinstanceIND2Array, model->MUTparamCPU.MUTinstanceIND2Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->MUTparamGPU.d_MUTinstanceIND2Array, size, int, status) + + + /* DOUBLE */ + model->MUTparamCPU.MUTfactorArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTfactorArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTfactorArray, size, double, status) + + /* INT */ + model->MUTparamCPU.MUTflux1Array = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTflux1Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTflux1Array, size, int, status) + + model->MUTparamCPU.MUTflux2Array = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTflux2Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTflux2Array, size, int, status) + + model->MUTparamCPU.MUTbrEq1Array = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTbrEq1Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTbrEq1Array, size, int, status) + + model->MUTparamCPU.MUTbrEq2Array = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->MUTparamGPU.d_MUTbrEq2Array), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->MUTparamGPU.d_MUTbrEq2Array, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/cumuttemp.c b/src/spicelib/devices/ind/CUSPICE/cumuttemp.c new file mode 100644 index 000000000..eb61d2e64 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/cumuttemp.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "inddefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuMUTtemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuMUTtemp +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + MUTmodel *model = (MUTmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* DOUBLE */ + status = cudaMemcpy (model->MUTparamGPU.d_MUTfactorArray, model->MUTparamCPU.MUTfactorArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->MUTparamGPU.d_MUTfactorArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->MUTparamGPU.d_MUTflux1Array, model->MUTparamCPU.MUTflux1Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->MUTparamGPU.d_MUTflux1Array, size, int, status) + + status = cudaMemcpy (model->MUTparamGPU.d_MUTflux2Array, model->MUTparamCPU.MUTflux2Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->MUTparamGPU.d_MUTflux2Array, size, int, status) + + status = cudaMemcpy (model->MUTparamGPU.d_MUTbrEq1Array, model->MUTparamCPU.MUTbrEq1Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->MUTparamGPU.d_MUTbrEq1Array, size, int, status) + + status = cudaMemcpy (model->MUTparamGPU.d_MUTbrEq2Array, model->MUTparamCPU.MUTbrEq2Array, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->MUTparamGPU.MUTbrEq2Array, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/indtopology.c b/src/spicelib/devices/ind/CUSPICE/indtopology.c new file mode 100644 index 000000000..6c8801f47 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/indtopology.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "inddefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +#define TopologyMatrixInsertRHS(offset, instance_ID, offsetRHS, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOiRHS [global_ID] = here->offset ; \ + ckt->CKTtopologyMatrixCOOjRHS [global_ID] = model->PositionVectorRHS [instance_ID] + offsetRHS ; \ + ckt->CKTtopologyMatrixCOOxRHS [global_ID] = Value ; + +int +INDtopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + INDmodel *model = (INDmodel *)inModel ; + INDinstance *here ; + int k ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the inductor models */ + for ( ; model != NULL ; model = INDnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = INDinstances(model); here != NULL ; here = INDnextInstance(here)) + { + if ((here->INDposNode != 0) && (here->INDbrEq != 0)) + { + TopologyMatrixInsert (INDposIbrPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->INDnegNode != 0) && (here->INDbrEq != 0)) + { + TopologyMatrixInsert (INDnegIbrPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->INDbrEq != 0) && (here->INDnegNode != 0)) + { + TopologyMatrixInsert (INDibrNegPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->INDbrEq != 0) && (here->INDposNode != 0)) + { + TopologyMatrixInsert (INDibrPosPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->INDbrEq != 0) && (here->INDbrEq != 0)) + { + TopologyMatrixInsert (INDibrIbrPtr, k, 1, -1, *i) ; + (*i)++ ; + } + + if (here->INDbrEq != 0) + { + TopologyMatrixInsertRHS (INDbrEq, k, 0, 1, *j) ; + (*j)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/CUSPICE/muttopology.c b/src/spicelib/devices/ind/CUSPICE/muttopology.c new file mode 100644 index 000000000..896f5f4f7 --- /dev/null +++ b/src/spicelib/devices/ind/CUSPICE/muttopology.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "inddefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +int +MUTtopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + NG_IGNORE (j) ; + + MUTmodel *model = (MUTmodel *)inModel ; + MUTinstance *here ; + int k ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the mutual inductor models */ + for ( ; model != NULL ; model = MUTnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = MUTinstances(model); here != NULL ; here = MUTnextInstance(here)) + { + if ((here->MUTind1->INDbrEq != 0) && (here->MUTind2->INDbrEq != 0)) + { + TopologyMatrixInsert (MUTbr1br2Ptr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->MUTind2->INDbrEq != 0) && (here->MUTind1->INDbrEq != 0)) + { + TopologyMatrixInsert (MUTbr2br1Ptr, k, 0, -1, *i) ; + (*i)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/ind/Makefile.am b/src/spicelib/devices/ind/Makefile.am index dfbc0442f..833e9529f 100644 --- a/src/spicelib/devices/ind/Makefile.am +++ b/src/spicelib/devices/ind/Makefile.am @@ -48,4 +48,25 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libind_la_SOURCES += \ + CUSPICE/indtopology.c \ + CUSPICE/cuindfree.c \ + CUSPICE/cuindload.cu \ + CUSPICE/cuindsetup.c \ + CUSPICE/cuindtemp.c + +libind_la_SOURCES += \ + CUSPICE/muttopology.c \ + CUSPICE/cumutfree.c \ + CUSPICE/cumutload.cu \ + CUSPICE/cumutsetup.c \ + CUSPICE/cumuttemp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/ind/inddefs.h b/src/spicelib/devices/ind/inddefs.h index d5d36d867..70880b340 100644 --- a/src/spicelib/devices/ind/inddefs.h +++ b/src/spicelib/devices/ind/inddefs.h @@ -79,6 +79,12 @@ struct sINDinstance { BindElement *INDibrPosBinding; BindElement *INDibrIbrBinding; #endif + +/* PARTICULAR SITUATION */ +#ifdef USE_CUSPICE + int instanceID; +#endif + }; #define INDflux INDstate /* flux in the inductor */ @@ -87,6 +93,31 @@ struct sINDinstance { * +3 for the derivatives - pointer to the * beginning of the array */ +#ifdef USE_CUSPICE +typedef struct sINDparamCPUstruct { + double *INDcpuPointersD [4]; + #define INDinitCondArray INDcpuPointersD[0] + #define INDinductArray INDcpuPointersD[1] + #define INDreqValueArray INDcpuPointersD[2] + #define INDveqValueArray INDcpuPointersD[3] + + int *INDcpuPointersI [2]; + #define INDbrEqArray INDcpuPointersI[0] + #define INDstateArray INDcpuPointersI[1] +} INDparamCPUstruct; + +typedef struct sINDparamGPUstruct { + double *INDcudaPointersD [4]; + #define d_INDinitCondArray INDcudaPointersD[0] + #define d_INDinductArray INDcudaPointersD[1] + #define d_INDreqValueArray INDcudaPointersD[2] + #define d_INDveqValueArray INDcudaPointersD[3] + + int *INDcudaPointersI [2]; + #define d_INDbrEqArray INDcudaPointersI[0] + #define d_INDstateArray INDcudaPointersI[1] +} INDparamGPUstruct; +#endif /* per model data */ @@ -118,8 +149,27 @@ struct sINDmodel { /* model structure for an inductor */ unsigned INDmIndGiven : 1; /* flag to indicate model inductance given */ double INDspecInd; /* Specific (one turn) inductance */ -}; +#ifdef USE_CUSPICE + INDparamCPUstruct INDparamCPU; + INDparamGPUstruct INDparamGPU; + + int offset; + int n_values; + int n_Ptr; + int *PositionVector; + int *d_PositionVector; + + int offsetRHS; + int n_valuesRHS; + int n_PtrRHS; + int *PositionVectorRHS; + int *d_PositionVectorRHS; + + int n_instances; +#endif + +}; /* structures used to describe mutual inductors */ @@ -157,6 +207,33 @@ struct sMUTinstance { #endif }; +#ifdef USE_CUSPICE +typedef struct sMUTparamCPUstruct { + double *MUTcpuPointersD [1]; + #define MUTfactorArray MUTcpuPointersD[0] + + int *MUTcpuPointersI [6]; + #define MUTflux1Array MUTcpuPointersI[0] + #define MUTflux2Array MUTcpuPointersI[1] + #define MUTbrEq1Array MUTcpuPointersI[2] + #define MUTbrEq2Array MUTcpuPointersI[3] + #define MUTinstanceIND1Array MUTcpuPointersI[4] + #define MUTinstanceIND2Array MUTcpuPointersI[5] +} MUTparamCPUstruct; + +typedef struct sMUTparamGPUstruct { + double *MUTcudaPointersD [1]; + #define d_MUTfactorArray MUTcudaPointersD[0] + + int *MUTcudaPointersI [6]; + #define d_MUTflux1Array MUTcudaPointersI[0] + #define d_MUTflux2Array MUTcudaPointersI[1] + #define d_MUTbrEq1Array MUTcudaPointersI[2] + #define d_MUTbrEq2Array MUTcudaPointersI[3] + #define d_MUTinstanceIND1Array MUTcudaPointersI[4] + #define d_MUTinstanceIND2Array MUTcudaPointersI[5] +} MUTparamGPUstruct; +#endif /* per model data */ @@ -169,6 +246,24 @@ struct sMUTmodel { /* model structure for a mutual inductor */ #define MUTinstances(inst) ((MUTinstance *)((inst)->gen.GENinstances)) #define MUTmodName gen.GENmodName +#ifdef USE_CUSPICE + MUTparamCPUstruct MUTparamCPU; + MUTparamGPUstruct MUTparamGPU; + + int offset; + int n_values; + int n_Ptr; + int *PositionVector; + int *d_PositionVector; + + int *PositionVectorRHS; + int *d_PositionVectorRHS; + + int n_instances; + + /* PARTICULAR SITUATION */ + int n_instancesRHS; +#endif }; @@ -215,6 +310,7 @@ struct INDsystem { #define IND_QUEST_SENS_CPLX 205 #define IND_QUEST_SENS_DC 206 + /* device parameters */ #define MUT_COEFF 401 #define MUT_IND1 402 diff --git a/src/spicelib/devices/ind/indext.h b/src/spicelib/devices/ind/indext.h index e7adf53f8..7416dea3e 100644 --- a/src/spicelib/devices/ind/indext.h +++ b/src/spicelib/devices/ind/indext.h @@ -46,4 +46,9 @@ extern int MUTbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int MUTbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif +#ifdef USE_CUSPICE +extern int INDtopology (GENmodel *, CKTcircuit *, int *, int *) ; +extern int MUTtopology (GENmodel *, CKTcircuit *, int *, int *) ; +#endif + #endif diff --git a/src/spicelib/devices/ind/indinit.c b/src/spicelib/devices/ind/indinit.c index 86bd698d3..98e21b824 100644 --- a/src/spicelib/devices/ind/indinit.c +++ b/src/spicelib/devices/ind/indinit.c @@ -6,6 +6,9 @@ #include "indext.h" #include "indinit.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev INDinfo = { .DEVpublic = { @@ -33,7 +36,11 @@ SPICEdev INDinfo = { .DEVparam = INDparam, .DEVmodParam = INDmParam, +#ifdef USE_CUSPICE + .DEVload = cuINDload, +#else .DEVload = INDload, +#endif .DEVsetup = INDsetup, .DEVunsetup = INDunsetup, .DEVpzSetup = INDsetup, @@ -71,6 +78,10 @@ SPICEdev INDinfo = { .DEVbindCSCComplex = INDbindCSCComplex, .DEVbindCSCComplexToReal = INDbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuINDdestroy, + .DEVtopology = INDtopology, +#endif }; @@ -100,7 +111,11 @@ SPICEdev MUTinfo = { .DEVparam = MUTparam, .DEVmodParam = NULL, +#ifdef USE_CUSPICE + .DEVload = cuMUTload, +#else .DEVload = NULL, +#endif .DEVsetup = MUTsetup, .DEVunsetup = NULL, .DEVpzSetup = MUTsetup, @@ -138,6 +153,10 @@ SPICEdev MUTinfo = { .DEVbindCSCComplex = MUTbindCSCComplex, .DEVbindCSCComplexToReal = MUTbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuMUTdestroy, + .DEVtopology = MUTtopology, +#endif }; diff --git a/src/spicelib/devices/ind/indload.c b/src/spicelib/devices/ind/indload.c index f70ebbb71..078cf38f0 100644 --- a/src/spicelib/devices/ind/indload.c +++ b/src/spicelib/devices/ind/indload.c @@ -29,6 +29,7 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) int ktype; int itype; + /* loop through all the inductor models */ for( ; model != NULL; model = INDnextModel(model)) { diff --git a/src/spicelib/devices/ind/indsacl.c b/src/spicelib/devices/ind/indsacl.c index 719bea901..504377fc1 100644 --- a/src/spicelib/devices/ind/indsacl.c +++ b/src/spicelib/devices/ind/indsacl.c @@ -22,6 +22,7 @@ INDsAcLoad(GENmodel *inModel, CKTcircuit *ckt) INDmodel *model = (INDmodel*)inModel; INDinstance *here; double cind,icind,val,ival; + MUTinstance *muthere; MUTmodel *mutmodel; double cind1; @@ -47,6 +48,7 @@ INDsAcLoad(GENmodel *inModel, CKTcircuit *ckt) double k2; int ktype; int itype; + SENstruct *info; info = ckt->CKTsenInfo; @@ -139,6 +141,7 @@ INDsAcLoad(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = INDinstances(model); here != NULL ; here=INDnextInstance(here)) { + if(here->INDsenParmNo){ cind = *(ckt->CKTrhsOld + here->INDbrEq); icind = *(ckt->CKTirhsOld + here->INDbrEq); diff --git a/src/spicelib/devices/ind/indsetup.c b/src/spicelib/devices/ind/indsetup.c index 51bd0d924..0a23bfcfd 100644 --- a/src/spicelib/devices/ind/indsetup.c +++ b/src/spicelib/devices/ind/indsetup.c @@ -10,6 +10,10 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + int INDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* load the inductor structure with those pointers needed later @@ -22,9 +26,9 @@ INDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) CKTnode *tmp; /* loop through all the inductor models */ - for( ; model != NULL; model = INDnextModel(model)) { - - /* Default Value Processing for Model Parameters */ + for ( ; model != NULL ; model = INDnextModel(model)) + { + /* Default Value Processing for Model Parameters */ if (!model->INDmIndGiven) { model->INDmInd = 0.0; } @@ -103,7 +107,97 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ TSTALLOC(INDibrIbrPtr,INDbrEq,INDbrEq); } } - return(OK); + +#ifdef USE_CUSPICE + int i, j, k, status ; + + /* Counting the instances */ + for (model = (INDmodel *)inModel ; model != NULL ; model = INDnextModel(model)) + { + i = 0 ; + + for (here = INDinstances(model); here != NULL ; here = INDnextInstance(here)) + { + i++ ; + } + + /* How much instances we have */ + model->n_instances = i ; + } + + /* loop through all the inductor models */ + for (model = (INDmodel *)inModel ; model != NULL ; model = INDnextModel(model)) + { + model->offset = ckt->total_n_values ; + model->offsetRHS = ckt->total_n_valuesRHS ; + + j = 0 ; + k = 0 ; + + /* loop through all the instances of the model */ + for (here = INDinstances(model); here != NULL ; here = INDnextInstance(here)) + { + /* For the Matrix */ + if ((here->INDposNode != 0) && (here->INDbrEq != 0)) + j++ ; + + if ((here->INDnegNode != 0) && (here->INDbrEq != 0)) + j++ ; + + if ((here->INDbrEq != 0) && (here->INDnegNode != 0)) + j++ ; + + if ((here->INDbrEq != 0) && (here->INDposNode != 0)) + j++ ; + + if ((here->INDbrEq != 0) && (here->INDbrEq != 0)) + j++ ; + + /* For the RHS */ + if (here->INDbrEq != 0) + k++ ; + } + + /* 2 Different Values for Every Instance */ + model->n_values = 2 * model->n_instances; + ckt->total_n_values += model->n_values ; + + model->n_Ptr = j ; + ckt->total_n_Ptr += model->n_Ptr ; + + model->n_valuesRHS = model->n_instances; + ckt->total_n_valuesRHS += model->n_valuesRHS ; + + model->n_PtrRHS = k ; + ckt->total_n_PtrRHS += model->n_PtrRHS ; + + + /* Position Vector assignment */ + model->PositionVector = TMALLOC (int, model->n_instances) ; + + for (j = 0 ; j < model->n_instances; j++) + { + /* 2 Different Values for Every Instance */ + model->PositionVector [j] = model->offset + 2 * j ; + } + + /* Position Vector assignment for the RHS */ + model->PositionVectorRHS = TMALLOC (int, model->n_instances) ; + + for (j = 0 ; j < model->n_instances; j++) + model->PositionVectorRHS [j] = model->offsetRHS + j ; + } + + /* loop through all the inductor models */ + for (model = (INDmodel *)inModel ; model != NULL ; model = INDnextModel(model)) + { + status = cuINDsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } +#endif + + return (OK) ; } int diff --git a/src/spicelib/devices/ind/indsupd.c b/src/spicelib/devices/ind/indsupd.c index 0c12957d1..6f2c81498 100644 --- a/src/spicelib/devices/ind/indsupd.c +++ b/src/spicelib/devices/ind/indsupd.c @@ -28,6 +28,7 @@ INDsUpdate(GENmodel *inModel, CKTcircuit *ckt) double dummy1; double dummy2; SENstruct *info; + MUTinstance *muthere; MUTmodel *mutmodel; double sxp1; @@ -37,6 +38,7 @@ INDsUpdate(GENmodel *inModel, CKTcircuit *ckt) int ktype; int itype; + info = ckt->CKTsenInfo; if(ckt->CKTmode & MODEINITTRAN) return(OK); @@ -63,8 +65,6 @@ INDsUpdate(GENmodel *inModel, CKTcircuit *ckt) *(ckt->CKTstate0 + here->INDsensxp + 2 * (iparmno - 1)) = sxp; } - - } } ktype = CKTtypelook("mutual"); @@ -125,6 +125,7 @@ INDsUpdate(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = INDinstances(model); here != NULL ; here=INDnextInstance(here)) { + for(iparmno = 1;iparmno<=info->SENparms;iparmno++){ if(ckt->CKTmode&MODETRANOP){ diff --git a/src/spicelib/devices/ind/indtemp.c b/src/spicelib/devices/ind/indtemp.c index c355e03d8..7eeba855c 100644 --- a/src/spicelib/devices/ind/indtemp.c +++ b/src/spicelib/devices/ind/indtemp.c @@ -5,13 +5,15 @@ Author: 2003 Paolo Nenzi /* */ - #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" #include "inddefs.h" #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif /*ARGSUSED*/ int @@ -23,9 +25,17 @@ INDtemp(GENmodel *inModel, CKTcircuit *ckt) double factor; double tc1, tc2; +#ifdef USE_CUSPICE + int i, status ; +#endif + /* loop through all the inductor models */ for( ; model != NULL; model = INDnextModel(model)) { +#ifdef USE_CUSPICE + i = 0 ; +#endif + /* loop through all the instances of the model */ for (here = INDinstances(model); here != NULL ; here=INDnextInstance(here)) { @@ -70,8 +80,24 @@ INDtemp(GENmodel *inModel, CKTcircuit *ckt) here->INDinduct = here->INDinduct * factor * here->INDscale; +#ifdef USE_CUSPICE + model->INDparamCPU.INDinitCondArray[i] = here->INDinitCond ; + model->INDparamCPU.INDinductArray[i] = here->INDinduct ; + model->INDparamCPU.INDbrEqArray[i] = here->INDbrEq ; + model->INDparamCPU.INDstateArray[i] = here->INDstate ; + + i++ ; +#endif + } + +#ifdef USE_CUSPICE + status = cuINDtemp ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } - return(OK); + return (OK) ; } diff --git a/src/spicelib/devices/ind/mutacld.c b/src/spicelib/devices/ind/mutacld.c index 09aa3ce76..50644c680 100644 --- a/src/spicelib/devices/ind/mutacld.c +++ b/src/spicelib/devices/ind/mutacld.c @@ -11,7 +11,6 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" - int MUTacLoad(GENmodel *inModel, CKTcircuit *ckt) { diff --git a/src/spicelib/devices/ind/mutsetup.c b/src/spicelib/devices/ind/mutsetup.c index 8580247b8..0abf21076 100644 --- a/src/spicelib/devices/ind/mutsetup.c +++ b/src/spicelib/devices/ind/mutsetup.c @@ -15,6 +15,9 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif #define TSTALLOC(ptr, first, second) \ do { \ @@ -62,5 +65,87 @@ MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) TSTALLOC(MUTbr2br1Ptr, MUTind2->INDbrEq, MUTind1->INDbrEq); } +#ifdef USE_CUSPICE + int i, j, status; + INDmodel *indmodel; + INDinstance *indhere; + + /* Counting the instances */ + for (model = (MUTmodel *)inModel; model; model = MUTnextModel(model)) { + i = 0; + + for (here = MUTinstances(model); here; here = MUTnextInstance(here)) + i++; + + /* How much instances we have */ + model->n_instances = i; + } + + /* loop through all the mutual inductor models */ + for (model = (MUTmodel *)inModel; model; model = MUTnextModel(model)) { + model->offset = ckt->total_n_values; + + j = 0; + + /* loop through all the instances of the model */ + for (here = MUTinstances(model); here; here = MUTnextInstance(here)) { + /* For the Matrix */ + if ((here->MUTind1->INDbrEq != 0) && (here->MUTind2->INDbrEq != 0)) + j++; + + if ((here->MUTind2->INDbrEq != 0) && (here->MUTind1->INDbrEq != 0)) + j++; + } + + model->n_values = model->n_instances; + ckt->total_n_values += model->n_values; + + model->n_Ptr = j; + ckt->total_n_Ptr += model->n_Ptr; + + + /* Position Vector assignment */ + model->PositionVector = TMALLOC(int, model->n_instances); + + for (j = 0; j < model->n_instances; j++) + model->PositionVector [j] = model->offset + j; + + + /* PARTICULAR SITUATION */ + /* Pick up the IND model from one of the two IND instances */ + indmodel = INDmodPtr(MUTinstances(model)->MUTind1); + model->n_instancesRHS = indmodel->n_instances; + + /* Position Vector assignment for the RHS */ + model->PositionVectorRHS = TMALLOC(int, model->n_instancesRHS); + + for (j = 0 ; j < model->n_instancesRHS ; j++) + model->PositionVectorRHS [j] = indmodel->PositionVectorRHS [j]; + + /* InstanceID assignment for every IND instance */ + j = 0; + for (indhere = INDinstances(indmodel); indhere; indhere = INDnextInstance(indhere)) + indhere->instanceID = j++; + + /* InstanceID storing for every MUT instance */ + model->MUTparamCPU.MUTinstanceIND1Array = TMALLOC(int, + model->n_instances); + model->MUTparamCPU.MUTinstanceIND2Array = TMALLOC(int, + model->n_instances); + j = 0; + for (here = MUTinstances(model); here; here = MUTnextInstance(here)) { + model->MUTparamCPU.MUTinstanceIND1Array [j] = here->MUTind1->instanceID; + model->MUTparamCPU.MUTinstanceIND2Array [j++] = here->MUTind2->instanceID; + } + } + + /* loop through all the mutual inductor models */ + for (model = (MUTmodel *)inModel; model; model = MUTnextModel(model)) { + status = cuMUTsetup ((GENmodel *)model); + if (status != 0) + return (E_NOMEM); + } +#endif + return(OK); } diff --git a/src/spicelib/devices/ind/muttemp.c b/src/spicelib/devices/ind/muttemp.c index 30c589adc..27ca67551 100644 --- a/src/spicelib/devices/ind/muttemp.c +++ b/src/spicelib/devices/ind/muttemp.c @@ -9,6 +9,9 @@ Author: 2003 Paolo Nenzi #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif static int cholesky(double *a, int n) @@ -40,9 +43,18 @@ MUTtemp(GENmodel *inModel, CKTcircuit *ckt) struct INDsystem *first_system = NULL; +#ifdef USE_CUSPICE + int i, status; +#endif + NG_IGNORE(ckt); - for (; model; model = MUTnextModel(model)) + for (; model; model = MUTnextModel(model)) { + +#ifdef USE_CUSPICE + i = 0; +#endif + for (here = MUTinstances(model); here; here = MUTnextInstance(here)) { /* Value Processing for mutual inductors */ @@ -55,6 +67,16 @@ MUTtemp(GENmodel *inModel, CKTcircuit *ckt) */ here->MUTfactor = here->MUTcoupling * sqrt(fabs(ind1 * ind2)); +#ifdef USE_CUSPICE + model->MUTparamCPU.MUTfactorArray[i] = here->MUTfactor; + model->MUTparamCPU.MUTflux1Array[i] = here->MUTind1->INDflux; + model->MUTparamCPU.MUTflux2Array[i] = here->MUTind2->INDflux; + model->MUTparamCPU.MUTbrEq1Array[i] = here->MUTind1->INDbrEq; + model->MUTparamCPU.MUTbrEq2Array[i] = here->MUTind2->INDbrEq; + + i++; +#endif + if (ckt->CKTindverbosity > 0) { struct INDsystem *system; @@ -118,6 +140,13 @@ MUTtemp(GENmodel *inModel, CKTcircuit *ckt) } } +#ifdef USE_CUSPICE + status = cuMUTtemp ((GENmodel *)model); + if (status != 0) + return (E_NOMEM); +#endif + } + if (first_system) { struct INDsystem *system; int sz = 0; diff --git a/src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c b/src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c new file mode 100644 index 000000000..384efe2ca --- /dev/null +++ b/src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "isrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuISRCdestroy +( +GENmodel *inModel +) +{ + ISRCmodel *model = (ISRCmodel *)inModel ; + ISRCinstance *here ; + int i ; + + for ( ; model != NULL ; model = ISRCnextModel(model)) + { + /* Special case VSRCparamGPU.VSRCcoeffsArray */ + i = 0 ; + + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + cudaFree (model->ISRCparamCPU.ISRCcoeffsArray[i]) ; + + i++ ; + } + free (model->ISRCparamCPU.ISRCcoeffsArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCcoeffsArray) ; + + i = 0 ; + + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + free (model->ISRCparamCPU.ISRCcoeffsArrayHost [i]) ; + + i++ ; + } + free (model->ISRCparamCPU.ISRCcoeffsArrayHost) ; + /* ----------------------------------------- */ + + /* DOUBLE */ + free (model->ISRCparamCPU.ISRCdcvalueArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCdcvalueArray) ; + + free (model->ISRCparamCPU.ISRCValueArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCValueArray) ; + + /* INT */ + free (model->ISRCparamCPU.ISRCdcGivenArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCdcGivenArray) ; + + free (model->ISRCparamCPU.ISRCfunctionTypeArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCfunctionTypeArray) ; + + free (model->ISRCparamCPU.ISRCfunctionOrderArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCfunctionOrderArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/CUSPICE/cuisrcload.cu b/src/spicelib/devices/isrc/CUSPICE/cuisrcload.cu new file mode 100644 index 000000000..4cf835af2 --- /dev/null +++ b/src/spicelib/devices/isrc/CUSPICE/cuisrcload.cu @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "isrcdefs.h" + +#ifdef XSPICE_EXP +/* gtri - begin - wbk - modify for supply ramping option */ +#include "ngspice/cmproto.h" +/* gtri - end - wbk - modify for supply ramping option */ +#endif + + + +/*** TRNOISE and TRRANDOM don't work in the CUDA implementation ***/ + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuISRCload routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +extern "C" +__global__ void cuISRCload_kernel (ISRCparamGPUstruct, int, double, double, double, double, int, int *, double *) ; + +extern "C" +int +cuISRCload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + ISRCmodel *model = (ISRCmodel *)inModel ; + int thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* loop through all the inductor models */ + for ( ; model != NULL ; model = ISRCnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)((model->n_instances + thread_y - 1) / thread_y) ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuISRCload_kernel <<< block_x, thread >>> (model->ISRCparamGPU, ckt->CKTmode, ckt->CKTtime, + ckt->CKTstep, ckt->CKTfinalTime, ckt->CKTsrcFact, + model->n_instances, model->d_PositionVectorRHS, + ckt->d_CKTloadOutputRHS) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Current Source Model\n\n") ; + return (E_NOMEM) ; + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuISRCload_kernel +( +ISRCparamGPUstruct ISRCentry, int CKTmode, double CKTtime, +double CKTstep, double CKTfinalTime, double CKTsrcFact, int n_instances, +int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID ; + double value, time ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < n_instances) + { + if (threadIdx.x == 0) + { + if ((CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && ISRCentry.d_ISRCdcGivenArray [instance_ID]) + { + /* load using DC value */ + +#ifdef XSPICE_EXP +/* gtri - begin - wbk - modify to process srcFact, etc. for all sources */ + value = ISRCentry.d_ISRCdcvalueArray [instance_ID] ; +#else + value = ISRCentry.d_ISRCdcvalueArray [instance_ID] * CKTsrcFact ; +#endif + + } else { + if (CKTmode & (MODEDC)) + time = 0 ; + else + time = CKTtime ; + + /* use the transient functions */ + switch (ISRCentry.d_ISRCfunctionTypeArray [instance_ID]) + { + default: + +#ifdef XSPICE_EXP + value = ISRCentry.d_ISRCdcvalueArray [instance_ID] ; +#else + value = ISRCentry.d_ISRCdcvalueArray [instance_ID] * CKTsrcFact ; +#endif + + break ; + + case PULSE: + { + double V1, V2, TD, TR, TF, PW, PER, basetime = 0 ; + +#ifdef XSPICE + double PHASE, phase, deltat ; +#endif + + V1 = ISRCentry.d_ISRCcoeffsArray [instance_ID] [0] ; + V2 = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + TD = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 2 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] : 0.0 ; + TR = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 3 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] : CKTstep ; + TF = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 4 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] : CKTstep ; + PW = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 5 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] : CKTfinalTime ; + PER = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 6 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [6] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [6] : CKTfinalTime ; + + /* shift time by delay time TD */ + time -= TD ; + +#ifdef XSPICE +/* gtri - begin - wbk - add PHASE parameter */ + PHASE = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 7 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [7] : 0.0 ; + + /* normalize phase to cycles */ + phase = PHASE / 360.0 ; + phase = fmod (phase, 1.0) ; + deltat = phase * PER ; + while (deltat > 0) + deltat -= PER ; + + /* shift time by pase (neg. for pos. phase value) */ + time += deltat ; + +/* gtri - end - wbk - add PHASE parameter */ +#endif + + if (time > PER) + { + /* repeating signal - figure out where we are */ + /* in period */ + basetime = PER * floor (time / PER) ; + time -= basetime ; + } + if (time <= 0 || time >= TR + PW + TF) + value = V1 ; + else if (time >= TR && time <= TR + PW) + value = V2 ; + else if (time > 0 && time < TR) + value = V1 + (V2 - V1) * (time) / TR ; + else /* time > TR + PW && < TR + PW + TF */ + value = V2 + (V1 - V2) * (time - (TR + PW)) / TF ; + } + break ; + + case SINE: + { + double VO, VA, FREQ, TD, THETA ; + +/* gtri - begin - wbk - add PHASE parameter */ +#ifdef XSPICE + double PHASE, phase ; + + PHASE = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 5 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] : 0.0 ; + + /* compute phase in radians */ + phase = PHASE * M_PI / 180.0 ; +#endif + + VO = ISRCentry.d_ISRCcoeffsArray [instance_ID] [0] ; + VA = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + FREQ = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 2 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + TD = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 3 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] : 0.0 ; + THETA = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 4 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] : 0.0 ; + + time -= TD ; + if (time <= 0) + +#ifdef XSPICE + value = VO + VA * sin (phase) ; + else + value = VO + VA * sin (FREQ * time * 2.0 * M_PI + phase) * exp (-time * THETA) ; +#else + value = VO ; + else + value = VO + VA * sin (FREQ * time * 2.0 * M_PI) * exp (-time * THETA) ; +#endif +/* gtri - end - wbk - add PHASE parameter */ + + } + break ; + + case EXP: + { + double V1, V2, TD1, TD2, TAU1, TAU2 ; + + V1 = ISRCentry.d_ISRCcoeffsArray [instance_ID] [0] ; + V2 = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + TD1 = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 2 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] : CKTstep ; + TAU1 = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 3 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] : CKTstep ; + TD2 = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 4 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] != 0.0 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] : TD1 + CKTstep ; + TAU2 = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 5 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] : CKTstep ; + + if (time <= TD1) + value = V1 ; + else if (time <= TD2) + value = V1 + (V2 - V1) * (1 - exp (-(time - TD1) / TAU1)) ; + else + value = V1 + (V2 - V1) * (1 - exp (-(time - TD1) / TAU1)) + + (V1 - V2) * (1 - exp (-(time - TD2) / TAU2)) ; + } + break ; + + case SFFM: + { + double VO, VA, FC, MDI, FS ; + +/* gtri - begin - wbk - add PHASE parameters */ +#ifdef XSPICE + double PHASEC, PHASES, phasec, phases ; + + PHASEC = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 5 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] : 0.0 ; + PHASES = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 6 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [6] : 0.0 ; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0 ; + phases = PHASES * M_PI / 180.0 ; +#endif + + VO = ISRCentry.d_ISRCcoeffsArray [instance_ID] [0] ; + VA = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + FC = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 2 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + MDI = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 3 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] : 0.0 ; + FS = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 4 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] : (1 / CKTfinalTime) ; + +#ifdef XSPICE + /* compute waveform value */ + value = VO + VA * sin ((2.0 * M_PI * FC * time + phasec) + + MDI * sin (2.0 * M_PI * FS * time + phases)) ; +#else + value = VO + VA * sin ((2.0 * M_PI * FC * time) + + MDI * sin (2.0 * M_PI * FS * time)) ; +#endif +/* gtri - end - wbk - add PHASE parameters */ + + } + break ; + + case AM: + { + double VA, FC, MF, VO, TD ; + +/* gtri - begin - wbk - add PHASE parameters */ +#ifdef XSPICE + double PHASEC, PHASES, phasec, phases ; + + PHASEC = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 5 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [5] : 0.0 ; + PHASES = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 6 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [6] : 0.0 ; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0 ; + phases = PHASES * M_PI / 180.0 ; +#endif + + VA = ISRCentry.d_ISRCcoeffsArray [instance_ID] [0] ; + VO = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + MF = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 2 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + FC = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 3 + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [3] : 0.0 ; + TD = ISRCentry.d_ISRCfunctionOrderArray [instance_ID] > 4 + && ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] + ? ISRCentry.d_ISRCcoeffsArray [instance_ID] [4] : 0.0 ; + + time -= TD ; + if (time <= 0) + value = 0 ; + else +#ifdef XSPICE + /* compute waveform value */ + value = VA * (VO + sin (2.0 * M_PI * MF * time + phases )) * + sin (2.0 * M_PI * FC * time + phases) ; +#else + value = VA * (VO + sin (2.0 * M_PI * MF * time)) * + sin (2.0 * M_PI * FC * time) ; +/* gtri - end - wbk - add PHASE parameters */ +#endif + + } + break ; + + case PWL: + { + int i ; + if (time < ISRCentry.d_ISRCcoeffsArray [instance_ID] [0]) + { + value = ISRCentry.d_ISRCcoeffsArray [instance_ID] [1] ; + break ; + } + + for (i = 0 ; i <= (ISRCentry.d_ISRCfunctionOrderArray [instance_ID] / 2) - 1 ; i++) + { + if ((ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i] == time)) + { + value = ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i + 1] ; + goto loadDone ; + } + if ((ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i] < time) + && (ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * (i + 1)] > time)) + { + value = ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i + 1] + + (((time - ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i]) / + (ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * (i + 1)] - + ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i])) * + (ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i + 3] - + ISRCentry.d_ISRCcoeffsArray [instance_ID] [2 * i + 1])) ; + goto loadDone ; + } + } + value = ISRCentry.d_ISRCcoeffsArray [instance_ID] + [ISRCentry.d_ISRCfunctionOrderArray [instance_ID] - 1] ; + break ; + } + } // switch + } // else (line 593) + +loadDone: + +#ifdef XSPICE_EXP +/* gtri - begin - wbk - modify for supply ramping option */ + value *= CKTsrcFact ; + value *= cm_analog_ramp_factor () ; +#else + if (CKTmode & MODETRANOP) + value *= CKTsrcFact ; +/* gtri - end - wbk - modify for supply ramping option */ +#endif + + d_CKTloadOutputRHS [d_PositionVectorRHS [instance_ID]] = value ; + +/* gtri - end - wbk - modify to process srcFact, etc. for all sources */ + +#ifdef XSPICE +/* gtri - begin - wbk - record value so it can be output if requested */ + here->ISRCcurrent = value ; +/* gtri - end - wbk - record value so it can be output if requested */ +#endif + } + } + + return ; +} diff --git a/src/spicelib/devices/isrc/CUSPICE/cuisrcsetup.c b/src/spicelib/devices/isrc/CUSPICE/cuisrcsetup.c new file mode 100644 index 000000000..ce6450c7f --- /dev/null +++ b/src/spicelib/devices/isrc/CUSPICE/cuisrcsetup.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "isrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuISRCsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuISRCsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuISRCsetup +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size1, size2 ; + cudaError_t status ; + ISRCmodel *model = (ISRCmodel *)inModel ; + ISRCinstance *here ; + + size1 = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, size1, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, size1, int, status) + + /* Special case ISRCparamGPU.ISRCcoeffsArray */ + model->ISRCparamCPU.ISRCcoeffsArray = (double **) malloc (size1 * sizeof(double *)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCcoeffsArray), size1 * sizeof(double *)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.ISRCcoeffsArray, size1, double*, status) + + i = 0 ; + + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + status = cudaMalloc ((void **)&(model->ISRCparamCPU.ISRCcoeffsArray[i]), size2 * sizeof(double)) ; + CUDAMALLOCCHECK (model->ISRCparamCPU.ISRCcoeffsArray[i], size2, double, status) + + i++ ; + } + + /* Structure pointer vectors in GPU */ + status = cudaMemcpy (model->ISRCparamGPU.d_ISRCcoeffsArray, model->ISRCparamCPU.ISRCcoeffsArray, size1 * sizeof(double *), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->ISRCparamGPU.d_ISRCcoeffsArray, size1, sizeof(double *), status) + + i = 0 ; + + model->ISRCparamCPU.ISRCcoeffsArrayHost = (double **) malloc (size1 * sizeof(double *)) ; + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + model->ISRCparamCPU.ISRCcoeffsArrayHost [i] = (double *) malloc (size2 * sizeof(double)) ; + + i++ ; + } + /* ----------------------------------------- */ + + /* DOUBLE */ + model->ISRCparamCPU.ISRCdcvalueArray = (double *) malloc (size1 * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCdcvalueArray), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.d_ISRCdcvalueArray, size1, double, status) + + model->ISRCparamCPU.ISRCValueArray = (double *) malloc (size1 * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCValueArray), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.d_ISRCValueArray, size1, double, status) + + /* INT */ + model->ISRCparamCPU.ISRCdcGivenArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCdcGivenArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.d_ISRCdcGivenArray, size1, int, status) + + model->ISRCparamCPU.ISRCfunctionTypeArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCfunctionTypeArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.d_ISRCfunctionTypeArray, size1, int, status) + + model->ISRCparamCPU.ISRCfunctionOrderArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->ISRCparamGPU.d_ISRCfunctionOrderArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->ISRCparamGPU.d_ISRCfunctionOrderArray, size1, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/CUSPICE/cuisrctemp.c b/src/spicelib/devices/isrc/CUSPICE/cuisrctemp.c new file mode 100644 index 000000000..dbeaf06da --- /dev/null +++ b/src/spicelib/devices/isrc/CUSPICE/cuisrctemp.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "isrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuISRCtemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuISRCtemp +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size1, size2 ; + cudaError_t status ; + ISRCmodel *model = (ISRCmodel *)inModel ; + ISRCinstance *here ; + + size1 = (long unsigned int) model->n_instances; + + i = 0 ; + + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + status = cudaMemcpy (model->ISRCparamCPU.ISRCcoeffsArray [i], model->ISRCparamCPU.ISRCcoeffsArrayHost [i], size2 * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->ISRCparamCPU.ISRCcoeffsArray [i], size2, double, status) + + i++ ; + } + + /* DOUBLE */ + status = cudaMemcpy (model->ISRCparamGPU.d_ISRCdcvalueArray, model->ISRCparamCPU.ISRCdcvalueArray, size1 * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->ISRCparamGPU.d_ISRCdcvalueArray, size1, double, status) + + /* INT */ + status = cudaMemcpy (model->ISRCparamGPU.d_ISRCdcGivenArray, model->ISRCparamCPU.ISRCdcGivenArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->ISRCparamGPU.d_ISRCdcGivenArray, size1, int, status) + + status = cudaMemcpy (model->ISRCparamGPU.d_ISRCfunctionTypeArray, model->ISRCparamCPU.ISRCfunctionTypeArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->ISRCparamGPU.d_ISRCfunctionTypeArray, size1, int, status) + + status = cudaMemcpy (model->ISRCparamGPU.d_ISRCfunctionOrderArray, model->ISRCparamCPU.ISRCfunctionOrderArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->ISRCparamGPU.ISRCfunctionOrderArray, size1, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/CUSPICE/isrctopology.c b/src/spicelib/devices/isrc/CUSPICE/isrctopology.c new file mode 100644 index 000000000..eb4d85e32 --- /dev/null +++ b/src/spicelib/devices/isrc/CUSPICE/isrctopology.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "isrcdefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsertRHS(offset, instance_ID, offsetRHS, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOiRHS [global_ID] = here->offset ; \ + ckt->CKTtopologyMatrixCOOjRHS [global_ID] = model->PositionVectorRHS [instance_ID] + offsetRHS ; \ + ckt->CKTtopologyMatrixCOOxRHS [global_ID] = Value ; + +int +ISRCtopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + NG_IGNORE (i) ; + + ISRCmodel *model = (ISRCmodel *)inModel ; + ISRCinstance *here ; + int k ; + + /* loop through all the voltage source models */ + for ( ; model != NULL ; model = ISRCnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + if (here->ISRCposNode != 0) + { + TopologyMatrixInsertRHS (ISRCposNode, k, 0, 1, *j) ; + (*j)++ ; + } + + if (here->ISRCnegNode != 0) + { + TopologyMatrixInsertRHS (ISRCnegNode, k, 0, -1, *j) ; + (*j)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/Makefile.am b/src/spicelib/devices/isrc/Makefile.am index 90443bfc7..3b9598b80 100644 --- a/src/spicelib/devices/isrc/Makefile.am +++ b/src/spicelib/devices/isrc/Makefile.am @@ -20,7 +20,22 @@ libisrc_la_SOURCES = \ isrctemp.c - AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) + +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libisrc_la_SOURCES += \ + isrcsetup.c \ + CUSPICE/isrctopology.c \ + CUSPICE/cuisrcfree.c \ + CUSPICE/cuisrcload.cu \ + CUSPICE/cuisrcsetup.c \ + CUSPICE/cuisrctemp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/isrc/isrcdefs.h b/src/spicelib/devices/isrc/isrcdefs.h index 4e8533aed..b761a2e33 100644 --- a/src/spicelib/devices/isrc/isrcdefs.h +++ b/src/spicelib/devices/isrc/isrcdefs.h @@ -68,8 +68,46 @@ typedef struct sISRCinstance { unsigned ISRCdGiven :1 ; /* flag to indicate source is a distortion input */ unsigned ISRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */ unsigned ISRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */ + +#ifdef USE_CUSPICE + double *d_ISRCcoeffs ; + + int n_coeffs ; +#endif + } ISRCinstance ; +#ifdef USE_CUSPICE +typedef struct sISRCparamCPUstruct { + /* pointer to array of coefficients in GPU */ + double **ISRCcoeffsArrayHost ; + double **ISRCcoeffsArray ; + + double *ISRCcpuPointersD [2] ; + #define ISRCdcvalueArray ISRCcpuPointersD[0] + #define ISRCValueArray ISRCcpuPointersD[1] + + int *ISRCcpuPointersI [3] ; + #define ISRCdcGivenArray ISRCcpuPointersI[0] + #define ISRCfunctionTypeArray ISRCcpuPointersI[1] + #define ISRCfunctionOrderArray ISRCcpuPointersI[2] +} ISRCparamCPUstruct ; + +typedef struct sISRCparamGPUstruct { + /* pointer to array of coefficients in GPU */ + double **d_ISRCcoeffsArray ; + + double *ISRCcudaPointersD [2] ; + #define d_ISRCdcvalueArray ISRCcudaPointersD[0] + #define d_ISRCValueArray ISRCcudaPointersD[1] + + int *ISRCcudaPointersI [3] ; + #define d_ISRCdcGivenArray ISRCcudaPointersI[0] + #define d_ISRCfunctionTypeArray ISRCcudaPointersI[1] + #define d_ISRCfunctionOrderArray ISRCcudaPointersI[2] + +} ISRCparamGPUstruct ; +#endif /* per model data */ @@ -82,6 +120,19 @@ typedef struct sISRCmodel { #define ISRCinstances(inst) ((ISRCinstance *)((inst)->gen.GENinstances)) #define ISRCmodName gen.GENmodName +#ifdef USE_CUSPICE + ISRCparamCPUstruct ISRCparamCPU ; + ISRCparamGPUstruct ISRCparamGPU ; + + int offsetRHS ; + int n_valuesRHS ; + int n_PtrRHS ; + int *PositionVectorRHS ; + int *d_PositionVectorRHS ; + + int n_instances ; +#endif + } ISRCmodel; diff --git a/src/spicelib/devices/isrc/isrcext.h b/src/spicelib/devices/isrc/isrcext.h index 8146c6074..5462389a8 100644 --- a/src/spicelib/devices/isrc/isrcext.h +++ b/src/spicelib/devices/isrc/isrcext.h @@ -13,3 +13,8 @@ extern int ISRCmDelete(GENmodel*); extern int ISRCparam(int,IFvalue*,GENinstance*,IFvalue*); extern int ISRCpzLoad(GENmodel*,CKTcircuit*,SPcomplex*); extern int ISRCtemp(GENmodel*,CKTcircuit*); + +#ifdef USE_CUSPICE +extern int ISRCsetup (SMPmatrix *, GENmodel *, CKTcircuit *, int *) ; +extern int ISRCtopology (GENmodel *, CKTcircuit *, int *, int *) ; +#endif diff --git a/src/spicelib/devices/isrc/isrcinit.c b/src/spicelib/devices/isrc/isrcinit.c index 10366f40f..9ebaf6394 100644 --- a/src/spicelib/devices/isrc/isrcinit.c +++ b/src/spicelib/devices/isrc/isrcinit.c @@ -6,6 +6,9 @@ #include "isrcext.h" #include "isrcinit.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev ISRCinfo = { .DEVpublic = { @@ -33,8 +36,16 @@ SPICEdev ISRCinfo = { .DEVparam = ISRCparam, .DEVmodParam = NULL, +#ifdef USE_CUSPICE + .DEVload = cuISRCload, +#else .DEVload = ISRCload, +#endif +#ifdef USE_CUSPICE + .DEVsetup = ISRCsetup, +#else .DEVsetup = NULL, +#endif .DEVunsetup = NULL, .DEVpzSetup = NULL, .DEVtemperature = ISRCtemp, @@ -71,6 +82,10 @@ SPICEdev ISRCinfo = { .DEVbindCSCComplex = NULL, .DEVbindCSCComplexToReal = NULL, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuISRCdestroy, + .DEVtopology = ISRCtopology, +#endif }; diff --git a/src/spicelib/devices/isrc/isrcpar.c b/src/spicelib/devices/isrc/isrcpar.c index 46a220f8e..0c89eb23f 100644 --- a/src/spicelib/devices/isrc/isrcpar.c +++ b/src/spicelib/devices/isrc/isrcpar.c @@ -26,6 +26,11 @@ static void copy_coeffs(ISRCinstance *here, IFvalue *value) here->ISRCcoeffsGiven = TRUE; memcpy(here->ISRCcoeffs, value->v.vec.rVec, (size_t) n * sizeof(double)); + +#ifdef USE_CUSPICE + here->n_coeffs = n ; +#endif + } diff --git a/src/spicelib/devices/isrc/isrcsetup.c b/src/spicelib/devices/isrc/isrcsetup.c new file mode 100644 index 000000000..70abef374 --- /dev/null +++ b/src/spicelib/devices/isrc/isrcsetup.c @@ -0,0 +1,81 @@ +/********** +Author: 2012 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/smpdefs.h" +#include "ngspice/cktdefs.h" +#include "isrcdefs.h" +#include "ngspice/sperror.h" + +#include "ngspice/CUSPICE/CUSPICE.h" + +/* ARGSUSED */ +int +ISRCsetup (SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) +{ + ISRCmodel *model = (ISRCmodel *)inModel ; + ISRCinstance *here ; + + int i, j, k, status ; + + NG_IGNORE(matrix) ; + NG_IGNORE(ckt) ; + NG_IGNORE(state) ; + + /* Counting the instances */ + for ( ; model != NULL ; model = ISRCnextModel(model)) + { + i = 0 ; + + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + i++ ; + } + + /* How many instances we have */ + model->n_instances = i ; + } + + /* loop through all the current source models */ + for (model = (ISRCmodel *)inModel ; model != NULL ; model = ISRCnextModel(model)) + { + model->offsetRHS = ckt->total_n_valuesRHS ; + + k = 0 ; + + /* loop through all the instances of the model */ + for (here = ISRCinstances(model); here != NULL ; here = ISRCnextInstance(here)) + { + /* For the RHS */ + if (here->ISRCposNode != 0) + k++ ; + + if (here->ISRCnegNode != 0) + k++ ; + } + + model->n_valuesRHS = model->n_instances; + ckt->total_n_valuesRHS += model->n_valuesRHS ; + + model->n_PtrRHS = k ; + ckt->total_n_PtrRHS += model->n_PtrRHS ; + + + /* Position Vector assignment for the RHS */ + model->PositionVectorRHS = TMALLOC (int, model->n_instances) ; + + for (j = 0 ; j < model->n_instances; j++) + model->PositionVectorRHS [j] = model->offsetRHS + j ; + } + + /* loop through all the current source models */ + for (model = (ISRCmodel *)inModel ; model != NULL ; model = ISRCnextModel(model)) + { + status = cuISRCsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/isrctemp.c b/src/spicelib/devices/isrc/isrctemp.c index d0fa55aef..db9a03837 100644 --- a/src/spicelib/devices/isrc/isrctemp.c +++ b/src/spicelib/devices/isrc/isrctemp.c @@ -10,6 +10,10 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + /*ARGSUSED*/ int ISRCtemp(GENmodel *inModel, CKTcircuit *ckt) @@ -22,9 +26,17 @@ ISRCtemp(GENmodel *inModel, CKTcircuit *ckt) NG_IGNORE(ckt); +#ifdef USE_CUSPICE + int i, j, status ; +#endif + /* loop through all the voltage source models */ for( ; model != NULL; model = ISRCnextModel(model)) { +#ifdef USE_CUSPICE + i = 0 ; +#endif + /* loop through all the instances of the model */ for (here = ISRCinstances(model); here != NULL ; here=ISRCnextInstance(here)) { @@ -52,8 +64,30 @@ ISRCtemp(GENmodel *inModel, CKTcircuit *ckt) radians = here->ISRCacPhase * M_PI / 180.0; here->ISRCacReal = here->ISRCacMag * cos(radians); here->ISRCacImag = here->ISRCacMag * sin(radians); + +#ifdef USE_CUSPICE + for (j = 0 ; j < here->n_coeffs ; j++) + { + model->ISRCparamCPU.ISRCcoeffsArrayHost [i] [j] = here->ISRCcoeffs [j] ; + } + + model->ISRCparamCPU.ISRCdcvalueArray[i] = here->ISRCdcValue ; + model->ISRCparamCPU.ISRCdcGivenArray[i] = here->ISRCdcGiven ; + model->ISRCparamCPU.ISRCfunctionTypeArray[i] = here->ISRCfunctionType ; + model->ISRCparamCPU.ISRCfunctionOrderArray[i] = here->ISRCfunctionOrder ; + + i++ ; +#endif + } + +#ifdef USE_CUSPICE + status = cuISRCtemp ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } - return(OK); + return (OK) ; } diff --git a/src/spicelib/devices/jfet/jfetinit.c b/src/spicelib/devices/jfet/jfetinit.c index d36dd556f..6825cddbf 100644 --- a/src/spicelib/devices/jfet/jfetinit.c +++ b/src/spicelib/devices/jfet/jfetinit.c @@ -71,9 +71,12 @@ SPICEdev JFETinfo = { .DEVbindCSCComplex = JFETbindCSCComplex, .DEVbindCSCComplexToReal = JFETbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_jfet_info(void) { diff --git a/src/spicelib/devices/jfet2/jfet2init.c b/src/spicelib/devices/jfet2/jfet2init.c index 7fa2600d5..1187a26a7 100644 --- a/src/spicelib/devices/jfet2/jfet2init.c +++ b/src/spicelib/devices/jfet2/jfet2init.c @@ -71,9 +71,12 @@ SPICEdev JFET2info = { .DEVbindCSCComplex = JFET2bindCSCComplex, .DEVbindCSCComplexToReal = JFET2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_jfet2_info(void) { diff --git a/src/spicelib/devices/ltra/ltrainit.c b/src/spicelib/devices/ltra/ltrainit.c index 47f64ccd5..08a95fcd5 100644 --- a/src/spicelib/devices/ltra/ltrainit.c +++ b/src/spicelib/devices/ltra/ltrainit.c @@ -71,9 +71,12 @@ SPICEdev LTRAinfo = { .DEVbindCSCComplex = LTRAbindCSCComplex, .DEVbindCSCComplexToReal = LTRAbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_ltra_info(void) { diff --git a/src/spicelib/devices/mes/mesinit.c b/src/spicelib/devices/mes/mesinit.c index 8b22406df..ecc4c24d3 100644 --- a/src/spicelib/devices/mes/mesinit.c +++ b/src/spicelib/devices/mes/mesinit.c @@ -71,9 +71,12 @@ SPICEdev MESinfo = { .DEVbindCSCComplex = MESbindCSCComplex, .DEVbindCSCComplexToReal = MESbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mes_info(void) { diff --git a/src/spicelib/devices/mesa/mesainit.c b/src/spicelib/devices/mesa/mesainit.c index 10e518227..4136af1ea 100644 --- a/src/spicelib/devices/mesa/mesainit.c +++ b/src/spicelib/devices/mesa/mesainit.c @@ -71,9 +71,12 @@ SPICEdev MESAinfo = { .DEVbindCSCComplex = MESAbindCSCComplex, .DEVbindCSCComplexToReal = MESAbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mesa_info(void) { diff --git a/src/spicelib/devices/mos1/mos1init.c b/src/spicelib/devices/mos1/mos1init.c index 4d25c32e6..0c5becbe2 100644 --- a/src/spicelib/devices/mos1/mos1init.c +++ b/src/spicelib/devices/mos1/mos1init.c @@ -71,9 +71,12 @@ SPICEdev MOS1info = { .DEVbindCSCComplex = MOS1bindCSCComplex, .DEVbindCSCComplexToReal = MOS1bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mos1_info(void) { diff --git a/src/spicelib/devices/mos2/mos2init.c b/src/spicelib/devices/mos2/mos2init.c index e3d0adb9b..590e08e75 100644 --- a/src/spicelib/devices/mos2/mos2init.c +++ b/src/spicelib/devices/mos2/mos2init.c @@ -71,9 +71,12 @@ SPICEdev MOS2info = { .DEVbindCSCComplex = MOS2bindCSCComplex, .DEVbindCSCComplexToReal = MOS2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mos2_info(void) { diff --git a/src/spicelib/devices/mos3/mos3init.c b/src/spicelib/devices/mos3/mos3init.c index badd06b5c..1e2d72fa2 100644 --- a/src/spicelib/devices/mos3/mos3init.c +++ b/src/spicelib/devices/mos3/mos3init.c @@ -71,9 +71,12 @@ SPICEdev MOS3info = { .DEVbindCSCComplex = MOS3bindCSCComplex, .DEVbindCSCComplexToReal = MOS3bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mos3_info(void) { diff --git a/src/spicelib/devices/mos6/mos6init.c b/src/spicelib/devices/mos6/mos6init.c index 008b8443b..e81117f6b 100644 --- a/src/spicelib/devices/mos6/mos6init.c +++ b/src/spicelib/devices/mos6/mos6init.c @@ -71,9 +71,12 @@ SPICEdev MOS6info = { .DEVbindCSCComplex = MOS6bindCSCComplex, .DEVbindCSCComplexToReal = MOS6bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mos6_info(void) { diff --git a/src/spicelib/devices/mos9/mos9init.c b/src/spicelib/devices/mos9/mos9init.c index 523c8c61e..71c512707 100644 --- a/src/spicelib/devices/mos9/mos9init.c +++ b/src/spicelib/devices/mos9/mos9init.c @@ -71,9 +71,12 @@ SPICEdev MOS9info = { .DEVbindCSCComplex = MOS9bindCSCComplex, .DEVbindCSCComplexToReal = MOS9bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_mos9_info(void) { diff --git a/src/spicelib/devices/nbjt/nbjtinit.c b/src/spicelib/devices/nbjt/nbjtinit.c index 76112f56f..9b25d80e6 100644 --- a/src/spicelib/devices/nbjt/nbjtinit.c +++ b/src/spicelib/devices/nbjt/nbjtinit.c @@ -71,9 +71,12 @@ SPICEdev NBJTinfo = { .DEVbindCSCComplex = NBJTbindCSCComplex, .DEVbindCSCComplexToReal = NBJTbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_nbjt_info(void) { diff --git a/src/spicelib/devices/nbjt2/nbt2init.c b/src/spicelib/devices/nbjt2/nbt2init.c index ff9913f73..f27591ae1 100644 --- a/src/spicelib/devices/nbjt2/nbt2init.c +++ b/src/spicelib/devices/nbjt2/nbt2init.c @@ -71,9 +71,12 @@ SPICEdev NBJT2info = { .DEVbindCSCComplex = NBJT2bindCSCComplex, .DEVbindCSCComplexToReal = NBJT2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_nbjt2_info(void) { diff --git a/src/spicelib/devices/ndev/ndevinit.c b/src/spicelib/devices/ndev/ndevinit.c index 922bb4310..bab699529 100644 --- a/src/spicelib/devices/ndev/ndevinit.c +++ b/src/spicelib/devices/ndev/ndevinit.c @@ -71,9 +71,12 @@ SPICEdev NDEVinfo = { .DEVbindCSCComplex = NULL, .DEVbindCSCComplexToReal = NULL, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_ndev_info(void) { diff --git a/src/spicelib/devices/numd/numdinit.c b/src/spicelib/devices/numd/numdinit.c index 09c7bd9e6..cf6a23537 100644 --- a/src/spicelib/devices/numd/numdinit.c +++ b/src/spicelib/devices/numd/numdinit.c @@ -71,9 +71,12 @@ SPICEdev NUMDinfo = { .DEVbindCSCComplex = NUMDbindCSCComplex, .DEVbindCSCComplexToReal = NUMDbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_numd_info(void) { diff --git a/src/spicelib/devices/numd2/numd2init.c b/src/spicelib/devices/numd2/numd2init.c index 6aaf72ef5..880d4d643 100644 --- a/src/spicelib/devices/numd2/numd2init.c +++ b/src/spicelib/devices/numd2/numd2init.c @@ -71,9 +71,12 @@ SPICEdev NUMD2info = { .DEVbindCSCComplex = NUMD2bindCSCComplex, .DEVbindCSCComplexToReal = NUMD2bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_numd2_info(void) { diff --git a/src/spicelib/devices/numos/numosinit.c b/src/spicelib/devices/numos/numosinit.c index d448ec41f..0385b225a 100644 --- a/src/spicelib/devices/numos/numosinit.c +++ b/src/spicelib/devices/numos/numosinit.c @@ -71,9 +71,12 @@ SPICEdev NUMOSinfo = { .DEVbindCSCComplex = NUMOSbindCSCComplex, .DEVbindCSCComplexToReal = NUMOSbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_numos_info(void) { diff --git a/src/spicelib/devices/res/CUSPICE/curesfree.c b/src/spicelib/devices/res/CUSPICE/curesfree.c new file mode 100644 index 000000000..6efa9fbc7 --- /dev/null +++ b/src/spicelib/devices/res/CUSPICE/curesfree.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "resdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuRESdestroy +( +GENmodel *inModel +) +{ + RESmodel *model = (RESmodel *)inModel ; + + for ( ; model != NULL ; model = RESnextModel(model)) + { + /* DOUBLE */ + free (model->RESparamCPU.REStc1Array) ; + cudaFree (model->RESparamGPU.d_REStc1Array) ; + + free (model->RESparamCPU.REStc2Array) ; + cudaFree (model->RESparamGPU.d_REStc2Array) ; + + free (model->RESparamCPU.RESmArray) ; + cudaFree (model->RESparamGPU.d_RESmArray) ; + + free (model->RESparamCPU.RESconductArray) ; + cudaFree (model->RESparamGPU.d_RESconductArray) ; + + free (model->RESparamCPU.REStempArray) ; + cudaFree (model->RESparamGPU.d_REStempArray) ; + + free (model->RESparamCPU.RESdtempArray) ; + cudaFree (model->RESparamGPU.d_RESdtempArray) ; + + free (model->RESparamCPU.REScurrentArray) ; + cudaFree (model->RESparamGPU.d_REScurrentArray) ; + + free (model->RESparamCPU.RESgValueArray) ; + cudaFree (model->RESparamGPU.d_RESgValueArray) ; + + /* INT */ + free (model->RESparamCPU.REStc1GivenArray) ; + cudaFree (model->RESparamGPU.d_REStc1GivenArray) ; + + free (model->RESparamCPU.REStc2GivenArray) ; + cudaFree (model->RESparamGPU.d_REStc2GivenArray) ; + + free (model->RESparamCPU.RESmGivenArray) ; + cudaFree (model->RESparamGPU.d_RESmGivenArray) ; + + free (model->RESparamCPU.RESposNodeArray) ; + cudaFree (model->RESparamGPU.d_RESposNodeArray) ; + + free (model->RESparamCPU.RESnegNodeArray) ; + cudaFree (model->RESparamGPU.d_RESnegNodeArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/res/CUSPICE/curesload.cu b/src/spicelib/devices/res/CUSPICE/curesload.cu new file mode 100644 index 000000000..ebeac3a4c --- /dev/null +++ b/src/spicelib/devices/res/CUSPICE/curesload.cu @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "resdefs.h" + +extern "C" +__global__ void cuRESload_kernel (RESparamGPUstruct, double *, int, int *, double *) ; + +extern "C" +int +cuRESload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + RESmodel *model = (RESmodel *)inModel ; + int thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* loop through all the resistor models */ + for ( ; model != NULL ; model = RESnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)((model->n_instances + thread_y - 1) / thread_y) ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuRESload_kernel <<< block_x, thread >>> (model->RESparamGPU, ckt->d_CKTrhsOld, model->n_instances, + model->d_PositionVector, ckt->d_CKTloadOutput) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Resistor Model\n\n") ; + return (E_NOMEM) ; + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuRESload_kernel +( +RESparamGPUstruct RESentry, double *CKTrhsOld, int n_instances, int *d_PositionVector, double * d_CKTloadOutput +) +{ + double m, difference, factor ; + + int instance_ID ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + if (instance_ID < n_instances) + { + if (threadIdx.x == 0) + { + if (!(RESentry.d_REStc1GivenArray [instance_ID])) + RESentry.d_REStc1Array [instance_ID] = 0.0 ; + + if (!(RESentry.d_REStc2GivenArray [instance_ID])) + RESentry.d_REStc2Array [instance_ID] = 0.0 ; + + if (!(RESentry.d_RESmGivenArray [instance_ID])) + RESentry.d_RESmArray [instance_ID] = 1.0 ; + + RESentry.d_REScurrentArray [instance_ID] = (CKTrhsOld [RESentry.d_RESposNodeArray [instance_ID]] - + CKTrhsOld [RESentry.d_RESnegNodeArray [instance_ID]]) * + RESentry.d_RESconductArray [instance_ID] ; + + difference = (RESentry.d_REStempArray [instance_ID] + RESentry.d_RESdtempArray [instance_ID]) - 300.15 ; + factor = 1.0 + (RESentry.d_REStc1Array [instance_ID]) * difference + + (RESentry.d_REStc2Array [instance_ID]) * difference * difference ; + + m = (RESentry.d_RESmArray [instance_ID]) / factor ; + + d_CKTloadOutput [d_PositionVector [instance_ID]] = m * RESentry.d_RESconductArray [instance_ID] ; + } + } + + return ; +} diff --git a/src/spicelib/devices/res/CUSPICE/curessetup.c b/src/spicelib/devices/res/CUSPICE/curessetup.c new file mode 100644 index 000000000..444389bad --- /dev/null +++ b/src/spicelib/devices/res/CUSPICE/curessetup.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "resdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuRESsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuRESsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuRESsetup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + RESmodel *model = (RESmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size, int, status) + + /* DOUBLE */ + model->RESparamCPU.REStc1Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REStc1Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REStc1Array, size, double, status) + + model->RESparamCPU.REStc2Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REStc2Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REStc2Array, size, double, status) + + model->RESparamCPU.RESmArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESmArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESmArray, size, double, status) + + model->RESparamCPU.RESconductArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESconductArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESconductArray, size, double, status) + + model->RESparamCPU.REStempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REStempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REStempArray, size, double, status) + + model->RESparamCPU.RESdtempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESdtempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESdtempArray, size, double, status) + + model->RESparamCPU.REScurrentArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REScurrentArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REScurrentArray, size, double, status) + + model->RESparamCPU.RESgValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESgValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESgValueArray, size, double, status) + + /* INT */ + model->RESparamCPU.REStc1GivenArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REStc1GivenArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REStc1GivenArray, size, int, status) + + model->RESparamCPU.REStc2GivenArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_REStc2GivenArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_REStc2GivenArray, size, int, status) + + model->RESparamCPU.RESmGivenArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESmGivenArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESmGivenArray, size, int, status) + + model->RESparamCPU.RESposNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESposNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESposNodeArray, size, int, status) + + model->RESparamCPU.RESnegNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->RESparamGPU.d_RESnegNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->RESparamGPU.d_RESnegNodeArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/res/CUSPICE/curestemp.c b/src/spicelib/devices/res/CUSPICE/curestemp.c new file mode 100644 index 000000000..b996764ee --- /dev/null +++ b/src/spicelib/devices/res/CUSPICE/curestemp.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "resdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuREStemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuREStemp +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + RESmodel *model = (RESmodel *)inModel ; + + size = (long unsigned int) model->n_instances; + + /* DOUBLE */ + status = cudaMemcpy (model->RESparamGPU.d_REStc1Array, model->RESparamCPU.REStc1Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_REStc1Array, size, double, status) + + status = cudaMemcpy (model->RESparamGPU.d_REStc2Array, model->RESparamCPU.REStc2Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_REStc2Array, size, double, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESmArray, model->RESparamCPU.RESmArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_RESmArray, size, double, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESconductArray, model->RESparamCPU.RESconductArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_RESconductArray, size, double, status) + + status = cudaMemcpy (model->RESparamGPU.d_REStempArray, model->RESparamCPU.REStempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_REStempArray, size, double, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESdtempArray, model->RESparamCPU.RESdtempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_RESdtempArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->RESparamGPU.d_REStc1GivenArray, model->RESparamCPU.REStc1GivenArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_REStc1GivenArray, size, int, status) + + status = cudaMemcpy (model->RESparamGPU.d_REStc2GivenArray, model->RESparamCPU.REStc2GivenArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_REStc2GivenArray, size, int, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESmGivenArray, model->RESparamCPU.RESmGivenArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_RESmGivenArray, size, int, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESposNodeArray, model->RESparamCPU.RESposNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.d_RESposNodeArray, size, int, status) + + status = cudaMemcpy (model->RESparamGPU.d_RESnegNodeArray, model->RESparamCPU.RESnegNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->RESparamGPU.RESnegNodeArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/res/CUSPICE/restopology.c b/src/spicelib/devices/res/CUSPICE/restopology.c new file mode 100644 index 000000000..3f8ca2d17 --- /dev/null +++ b/src/spicelib/devices/res/CUSPICE/restopology.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "resdefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +int +REStopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + RESmodel *model = (RESmodel *)inModel ; + RESinstance *here ; + int k ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + NG_IGNORE (j) ; + + /* loop through all the resistor models */ + for ( ; model != NULL ; model = RESnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = RESinstances(model); here != NULL ; here = RESnextInstance(here)) + { + if ((here->RESposNode != 0) && (here->RESposNode != 0)) + { + TopologyMatrixInsert (RESposPosPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->RESnegNode != 0) && (here->RESnegNode != 0)) + { + TopologyMatrixInsert (RESnegNegPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->RESposNode != 0) && (here->RESnegNode != 0)) + { + TopologyMatrixInsert (RESposNegPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->RESnegNode != 0) && (here->RESposNode != 0)) + { + TopologyMatrixInsert (RESnegPosPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/res/Makefile.am b/src/spicelib/devices/res/Makefile.am index c2fd893d9..e20f38e2c 100644 --- a/src/spicelib/devices/res/Makefile.am +++ b/src/spicelib/devices/res/Makefile.am @@ -35,4 +35,18 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libres_la_SOURCES += \ + CUSPICE/restopology.c \ + CUSPICE/curesfree.c \ + CUSPICE/curesload.cu \ + CUSPICE/curessetup.c \ + CUSPICE/curestemp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index b601d236f..327031cbc 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -97,6 +97,45 @@ typedef struct sRESinstance { } RESinstance ; +#ifdef USE_CUSPICE +typedef struct sRESparamCPUstruct { + double *REScpuPointersD [8] ; + #define REStc1Array REScpuPointersD[0] + #define REStc2Array REScpuPointersD[1] + #define RESmArray REScpuPointersD[2] + #define RESconductArray REScpuPointersD[3] + #define REStempArray REScpuPointersD[4] + #define RESdtempArray REScpuPointersD[5] + #define REScurrentArray REScpuPointersD[6] + #define RESgValueArray REScpuPointersD[7] + + int *REScpuPointersI [5] ; + #define REStc1GivenArray REScpuPointersI[0] + #define REStc2GivenArray REScpuPointersI[1] + #define RESmGivenArray REScpuPointersI[2] + #define RESposNodeArray REScpuPointersI[3] + #define RESnegNodeArray REScpuPointersI[4] +} RESparamCPUstruct ; + +typedef struct sRESparamGPUstruct { + double *REScudaPointersD [8] ; + #define d_REStc1Array REScudaPointersD[0] + #define d_REStc2Array REScudaPointersD[1] + #define d_RESmArray REScudaPointersD[2] + #define d_RESconductArray REScudaPointersD[3] + #define d_REStempArray REScudaPointersD[4] + #define d_RESdtempArray REScudaPointersD[5] + #define d_REScurrentArray REScudaPointersD[6] + #define d_RESgValueArray REScudaPointersD[7] + + int *REScudaPointersI [5] ; + #define d_REStc1GivenArray REScudaPointersI[0] + #define d_REStc2GivenArray REScudaPointersI[1] + #define d_RESmGivenArray REScudaPointersI[2] + #define d_RESposNodeArray REScudaPointersI[3] + #define d_RESnegNodeArray REScudaPointersI[4] +} RESparamGPUstruct ; +#endif /* per model data */ @@ -141,6 +180,20 @@ typedef struct sRESmodel { /* model structure for a resistor */ unsigned RESlfGiven :1; /* flags indicates lf is given */ unsigned RESwfGiven :1; /* flags indicates wf is given */ unsigned RESefGiven :1; /* flags indicates ef is given */ + +#ifdef USE_CUSPICE + RESparamCPUstruct RESparamCPU ; + RESparamGPUstruct RESparamGPU ; + + int offset ; + int n_values ; + int n_Ptr ; + int *PositionVector ; + int *d_PositionVector ; + + int n_instances ; +#endif + } RESmodel; /* device parameters */ diff --git a/src/spicelib/devices/res/resext.h b/src/spicelib/devices/res/resext.h index 36da842ae..b0ebacdb9 100644 --- a/src/spicelib/devices/res/resext.h +++ b/src/spicelib/devices/res/resext.h @@ -27,3 +27,7 @@ extern int RESbindCSC (GENmodel*, CKTcircuit*) ; extern int RESbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int RESbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef USE_CUSPICE +extern int REStopology (GENmodel *, CKTcircuit *, int *, int *) ; +#endif diff --git a/src/spicelib/devices/res/resinit.c b/src/spicelib/devices/res/resinit.c index 739150d1b..8d51bb6b0 100644 --- a/src/spicelib/devices/res/resinit.c +++ b/src/spicelib/devices/res/resinit.c @@ -6,6 +6,9 @@ #include "resext.h" #include "resinit.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev RESinfo = { .DEVpublic = { @@ -33,7 +36,11 @@ SPICEdev RESinfo = { .DEVparam = RESparam, .DEVmodParam = RESmParam, +#ifdef USE_CUSPICE + .DEVload = cuRESload, +#else .DEVload = RESload, +#endif .DEVsetup = RESsetup, .DEVunsetup = NULL, .DEVpzSetup = RESsetup, @@ -71,6 +78,10 @@ SPICEdev RESinfo = { .DEVbindCSCComplex = RESbindCSCComplex, .DEVbindCSCComplexToReal = RESbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuRESdestroy, + .DEVtopology = REStopology, +#endif }; diff --git a/src/spicelib/devices/res/ressetup.c b/src/spicelib/devices/res/ressetup.c index 6064a412c..6dfae725c 100644 --- a/src/spicelib/devices/res/ressetup.c +++ b/src/spicelib/devices/res/ressetup.c @@ -9,6 +9,9 @@ Modified: Apr 2000 Paolo Nenzi #include "resdefs.h" #include "ngspice/sperror.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif int RESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state) @@ -75,5 +78,69 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ TSTALLOC(RESnegPosPtr, RESnegNode, RESposNode); } } - return(OK); + +#ifdef USE_CUSPICE + int i, j, status ; + + /* Counting the instances */ + for (model = (RESmodel *)inModel ; model != NULL ; model = RESnextModel(model)) + { + i = 0 ; + + for (here = RESinstances(model); here != NULL ; here = RESnextInstance(here)) + { + i++ ; + } + + /* How much instances we have */ + model->n_instances = i ; + } + + /* loop through all the resistor models */ + for (model = (RESmodel *)inModel ; model != NULL ; model = RESnextModel(model)) + { + model->offset = ckt->total_n_values ; + + j = 0 ; + + /* loop through all the instances of the model */ + for (here = RESinstances(model); here != NULL ; here = RESnextInstance(here)) + { + if ((here->RESposNode != 0) && (here->RESposNode != 0)) + j++ ; + + if ((here->RESnegNode != 0) && (here->RESnegNode != 0)) + j++ ; + + if ((here->RESposNode != 0) && (here->RESnegNode != 0)) + j++ ; + + if ((here->RESnegNode != 0) && (here->RESposNode != 0)) + j++ ; + } + + model->n_values = !model->n_instances; + ckt->total_n_values += model->n_values ; + + model->n_Ptr = j ; + ckt->total_n_Ptr += model->n_Ptr ; + + + /* Position Vector assignment */ + model->PositionVector = TMALLOC (int, !model->n_instances) ; + + for (j = 0 ; j < !model->n_instances; j++) + model->PositionVector [j] = model->offset + j ; + } + + /* loop through all the resistor models */ + for (model = (RESmodel *)inModel ; model != NULL ; model = RESnextModel(model)) + { + status = cuRESsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } +#endif + + return (OK) ; } diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index 7fbdcd505..0f9116557 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -10,6 +10,10 @@ Modified: 2000 AlanSfixes #include "resdefs.h" #include "ngspice/sperror.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + int REStemp(GENmodel *inModel, CKTcircuit *ckt) /* perform the temperature update to the resistors @@ -26,6 +30,10 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the resistor models */ for( ; model != NULL; model = RESnextModel(model)) { +#ifdef USE_CUSPICE + int i = 0; +#endif + /* loop through all the instances of the model */ for (here = RESinstances(model); here != NULL ; here=RESnextInstance(here)) { @@ -43,7 +51,29 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) } RESupdate_conduct(here, TRUE); + +#ifdef USE_CUSPICE + model->RESparamCPU.REStc1GivenArray[i] = here->REStc1Given; + model->RESparamCPU.REStc2GivenArray[i] = here->REStc2Given; + model->RESparamCPU.RESmGivenArray[i] = here->RESmGiven; + model->RESparamCPU.REStc1Array[i] = here->REStc1; + model->RESparamCPU.REStc2Array[i] = here->REStc2; + model->RESparamCPU.RESmArray[i] = here->RESm; + model->RESparamCPU.RESposNodeArray[i] = here->RESposNode; + model->RESparamCPU.RESnegNodeArray[i] = here->RESnegNode; + model->RESparamCPU.RESconductArray[i] = here->RESconduct; + model->RESparamCPU.REStempArray[i] = here->REStemp; + model->RESparamCPU.RESdtempArray[i] = here->RESdtemp; + + i++; +#endif } + +#ifdef USE_CUSPICE + int status = cuREStemp ((GENmodel *)model); + if (status != 0) + return E_NOMEM; +#endif } return OK; diff --git a/src/spicelib/devices/soi3/soi3init.c b/src/spicelib/devices/soi3/soi3init.c index 93d748e3d..505a0942d 100644 --- a/src/spicelib/devices/soi3/soi3init.c +++ b/src/spicelib/devices/soi3/soi3init.c @@ -71,9 +71,12 @@ SPICEdev SOI3info = { .DEVbindCSCComplex = SOI3bindCSCComplex, .DEVbindCSCComplexToReal = SOI3bindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_soi3_info(void) { diff --git a/src/spicelib/devices/sw/swinit.c b/src/spicelib/devices/sw/swinit.c index b3bf4e2d5..427187f6d 100644 --- a/src/spicelib/devices/sw/swinit.c +++ b/src/spicelib/devices/sw/swinit.c @@ -72,9 +72,12 @@ SPICEdev SWinfo = { .DEVbindCSCComplex = SWbindCSCComplex, .DEVbindCSCComplexToReal = SWbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_sw_info(void) { diff --git a/src/spicelib/devices/tra/trainit.c b/src/spicelib/devices/tra/trainit.c index 9a0c79658..5d1cf91dc 100644 --- a/src/spicelib/devices/tra/trainit.c +++ b/src/spicelib/devices/tra/trainit.c @@ -71,9 +71,12 @@ SPICEdev TRAinfo = { .DEVbindCSCComplex = TRAbindCSCComplex, .DEVbindCSCComplexToReal = TRAbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_tra_info(void) { diff --git a/src/spicelib/devices/txl/txlinit.c b/src/spicelib/devices/txl/txlinit.c index 8f76c4741..7533aa15b 100644 --- a/src/spicelib/devices/txl/txlinit.c +++ b/src/spicelib/devices/txl/txlinit.c @@ -76,6 +76,10 @@ SPICEdev TXLinfo = { .DEVbindCSCComplex = TXLbindCSCComplex, .DEVbindCSCComplexToReal = TXLbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; diff --git a/src/spicelib/devices/urc/urcinit.c b/src/spicelib/devices/urc/urcinit.c index 2f9ad074d..7226b777b 100644 --- a/src/spicelib/devices/urc/urcinit.c +++ b/src/spicelib/devices/urc/urcinit.c @@ -71,9 +71,12 @@ SPICEdev URCinfo = { .DEVbindCSCComplex = NULL, .DEVbindCSCComplexToReal = NULL, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_urc_info(void) { diff --git a/src/spicelib/devices/vbic/vbicinit.c b/src/spicelib/devices/vbic/vbicinit.c index 2bdb7cf1e..d71c3f0fb 100644 --- a/src/spicelib/devices/vbic/vbicinit.c +++ b/src/spicelib/devices/vbic/vbicinit.c @@ -76,9 +76,12 @@ SPICEdev VBICinfo = { .DEVbindCSCComplex = VBICbindCSCComplex, .DEVbindCSCComplexToReal = VBICbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_vbic_info(void) { diff --git a/src/spicelib/devices/vccs/vccsinit.c b/src/spicelib/devices/vccs/vccsinit.c index d5e86fa02..9d7c42c1b 100644 --- a/src/spicelib/devices/vccs/vccsinit.c +++ b/src/spicelib/devices/vccs/vccsinit.c @@ -71,9 +71,12 @@ SPICEdev VCCSinfo = { .DEVbindCSCComplex = VCCSbindCSCComplex, .DEVbindCSCComplexToReal = VCCSbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_vccs_info(void) { diff --git a/src/spicelib/devices/vcvs/vcvsinit.c b/src/spicelib/devices/vcvs/vcvsinit.c index b0583d015..4e7766121 100644 --- a/src/spicelib/devices/vcvs/vcvsinit.c +++ b/src/spicelib/devices/vcvs/vcvsinit.c @@ -71,9 +71,12 @@ SPICEdev VCVSinfo = { .DEVbindCSCComplex = VCVSbindCSCComplex, .DEVbindCSCComplexToReal = VCVSbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = NULL, + .DEVtopology = NULL, +#endif }; - SPICEdev * get_vcvs_info(void) { diff --git a/src/spicelib/devices/vsrc/CUSPICE/cuvsrcfree.c b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcfree.c new file mode 100644 index 000000000..af5ac2298 --- /dev/null +++ b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcfree.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "vsrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuVSRCdestroy +( +GENmodel *inModel +) +{ + VSRCmodel *model = (VSRCmodel *)inModel ; + VSRCinstance *here ; + int i ; + + for ( ; model != NULL ; model = VSRCnextModel(model)) + { + /* Special case VSRCparamGPU.VSRCcoeffsArray */ + i = 0 ; + + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + cudaFree (model->VSRCparamCPU.VSRCcoeffsArray [i]) ; + + i++ ; + } + free (model->VSRCparamCPU.VSRCcoeffsArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCcoeffsArray) ; + + i = 0 ; + + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + free (model->VSRCparamCPU.VSRCcoeffsArrayHost [i]) ; + + i++ ; + } + free (model->VSRCparamCPU.VSRCcoeffsArrayHost) ; + /* ----------------------------------------- */ + + /* DOUBLE */ + free (model->VSRCparamCPU.VSRCdcvalueArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCdcvalueArray) ; + + free (model->VSRCparamCPU.VSRCrdelayArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCrdelayArray) ; + + free (model->VSRCparamCPU.VSRCValueArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCValueArray) ; + + /* INT */ + free (model->VSRCparamCPU.VSRCdcGivenArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCdcGivenArray) ; + + free (model->VSRCparamCPU.VSRCfunctionTypeArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCfunctionTypeArray) ; + + free (model->VSRCparamCPU.VSRCfunctionOrderArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCfunctionOrderArray) ; + + free (model->VSRCparamCPU.VSRCrGivenArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCrGivenArray) ; + + free (model->VSRCparamCPU.VSRCrBreakptArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCrBreakptArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/vsrc/CUSPICE/cuvsrcload.cu b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcload.cu new file mode 100644 index 000000000..387aa7752 --- /dev/null +++ b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcload.cu @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "ngspice/CUSPICE/cuniinteg.cuh" +#include "vsrcdefs.h" + + + +/*** STUFF NEEDED BECAUSE OF SOME INCLUSIONS IN NGSPICE THAT ARE NOT AVAILABLE IN CUDA ***/ +/* TRNOISE and TRRANDOM don't work in the CUDA implementation */ + +/********** +Copyright 1991 Regents of the University of California. All rights reserved. +**********/ + +#include +#include + +#ifdef _MSC_VER +#define llabs(x) ((x) < 0 ? -(x) : (x)) +#endif + +#define int64_min (((int64_t) -1) << 63) + +#define TRUE 1 +#define FALSE 0 + +/* From Bruce Dawson, Comparing floating point numbers, + http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm + Original this function is named AlmostEqual2sComplement but we leave it to AlmostEqualUlps + and can leave the code (measure.c, dctran.c) unchanged. The transformation to the 2's complement + prevent problems around 0.0. + One Ulp is equivalent to a maxRelativeError of between 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000. + Practical: 3 < maxUlps < some hundred's (or thousand's) - depending on numerical requirements. +*/ + +__device__ +static +bool +AlmostEqualUlps (double A, double B, int maxUlps) +{ + int64_t aInt, bInt, intDiff; + + if (A == B) + return TRUE ; + + /* If not - the entire method can not work */ + assert (sizeof(double) == sizeof(int64_t)) ; + + /* Make sure maxUlps is non-negative and small enough that the */ + /* default NAN won't compare as equal to anything. */ + assert (maxUlps > 0 && maxUlps < 4 * 1024 * 1024) ; + + aInt = *(int64_t*)&A ; + /* Make aInt lexicographically ordered as a twos-complement int */ + if (aInt < 0) + aInt = int64_min - aInt ; + + bInt = *(int64_t*)&B ; + /* Make bInt lexicographically ordered as a twos-complement int */ + if (bInt < 0) + bInt = int64_min - bInt ; + + intDiff = llabs (aInt - bInt) ; + +/* printf("A:%e B:%e aInt:%d bInt:%d diff:%d\n", A, B, aInt, bInt, intDiff); */ + + if (intDiff <= maxUlps) + return TRUE ; + return FALSE ; +} + + + +/*** CODE STARTING ***/ +extern "C" +__global__ void cuVSRCload_kernel (VSRCparamGPUstruct, int, double, double, double, double, int, int *, double *, int *, double *) ; + +extern "C" +int +cuVSRCload +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + VSRCmodel *model = (VSRCmodel *)inModel ; + int thread_x, thread_y, block_x ; + + cudaError_t status ; + + /* loop through all the inductor models */ + for ( ; model != NULL ; model = VSRCnextModel(model)) + { + /* Determining how many blocks should exist in the kernel */ + thread_x = 1 ; + thread_y = 256 ; + if (model->n_instances % thread_y != 0) + block_x = (int)((model->n_instances + thread_y - 1) / thread_y) ; + else + block_x = model->n_instances / thread_y ; + + dim3 thread (thread_x, thread_y) ; + + /* Kernel launch */ + status = cudaGetLastError () ; // clear error status + + cuVSRCload_kernel <<< block_x, thread >>> (model->VSRCparamGPU, ckt->CKTmode, ckt->CKTtime, + ckt->CKTstep, ckt->CKTfinalTime, ckt->CKTsrcFact, + model->n_instances, model->d_PositionVector, + ckt->d_CKTloadOutput, model->d_PositionVectorRHS, + ckt->d_CKTloadOutputRHS) ; + + cudaDeviceSynchronize () ; + + status = cudaGetLastError () ; // check for launch error + if (status != cudaSuccess) + { + fprintf (stderr, "Kernel launch failure in the Voltage Source Model\n\n") ; + return (E_NOMEM) ; + } + } + + return (OK) ; +} + +extern "C" +__global__ +void +cuVSRCload_kernel +( +VSRCparamGPUstruct VSRCentry, int CKTmode, double CKTtime, +double CKTstep, double CKTfinalTime, double CKTsrcFact, int n_instances, +int *d_PositionVector, double *d_CKTloadOutput, int *d_PositionVectorRHS, double *d_CKTloadOutputRHS +) +{ + int instance_ID ; + double time, value = 0.0 ; + + instance_ID = threadIdx.y + blockDim.y * blockIdx.x ; + + if (instance_ID < n_instances) + { + if (threadIdx.x == 0) + { + d_CKTloadOutput [d_PositionVector [instance_ID]] = 1.0 ; + + if ((CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && VSRCentry.d_VSRCdcGivenArray [instance_ID]) + { + /* load using DC value */ +#ifdef XSPICE_EXP +/* gtri - begin - wbk - modify to process srcFact, etc. for all sources */ + value = VSRCentry.d_VSRCdcvalueArray [instance_ID] ; +#else + value = VSRCentry.d_VSRCdcvalueArray [instance_ID] * CKTsrcFact ; +#endif + } else { + if (CKTmode & (MODEDC)) + time = 0 ; + else + time = CKTtime ; + + /* use the transient functions */ + switch (VSRCentry.d_VSRCfunctionTypeArray [instance_ID]) + { + default: + value = VSRCentry.d_VSRCdcvalueArray [instance_ID] ; + break ; + + case PULSE: + { + double V1, V2, TD, TR, TF, PW, PER, basetime = 0.0 ; +#ifdef XSPICE + double PHASE, phase, deltat ; +#endif + V1 = VSRCentry.d_VSRCcoeffsArray [instance_ID] [0] ; + V2 = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + TD = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 2 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] : 0.0 ; + TR = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 3 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] : CKTstep ; + TF = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 4 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] : CKTstep ; + PW = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 5 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] : CKTfinalTime ; + PER = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 6 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [6] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [6] : CKTfinalTime ; + + /* shift time by delay time TD */ + time -= TD ; + +#ifdef XSPICE +/* gtri - begin - wbk - add PHASE parameter */ + + PHASE = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 7 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [7] : 0.0 ; + + /* normalize phase to cycles */ + phase = PHASE / 360.0 ; + phase = fmod (phase, 1.0) ; + deltat = phase * PER ; + while (deltat > 0) + deltat -= PER ; + + /* shift time by pase (neg. for pos. phase value) */ + time += deltat ; + +/* gtri - end - wbk - add PHASE parameter */ +#endif + if (time > PER) + { + /* repeating signal - figure out where we are */ + /* in period */ + basetime = PER * floor (time / PER) ; + time -= basetime ; + } + + if (time <= 0 || time >= TR + PW + TF) + value = V1 ; + else if (time >= TR && time <= TR + PW) + value = V2 ; + else if (time > 0 && time < TR) + value = V1 + (V2 - V1) * time / TR ; + else /* time > TR + PW && < TR + PW + TF */ + value = V2 + (V1 - V2) * (time - (TR + PW)) / TF ; + } + break ; + + case SINE: + { + double VO, VA, FREQ, TD, THETA ; + +#ifdef XSPICE +/* gtri - begin - wbk - add PHASE parameter */ + + double PHASE, phase ; + + PHASE = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 5 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] : 0.0 ; + + /* compute phase in radians */ + phase = PHASE * M_PI / 180.0 ; +#endif + + VO = VSRCentry.d_VSRCcoeffsArray [instance_ID] [0] ; + VA = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + FREQ = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 2 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + TD = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 3 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] : 0.0 ; + THETA = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 4 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] : 0.0 ; + + time -= TD ; + if (time <= 0) + { + +#ifdef XSPICE + value = VO + VA * sin (phase) ; + } else { + value = VO + VA * sin (FREQ * time * 2.0 * M_PI + phase) * exp (-time * THETA) ; +#else + value = VO ; + } else { + value = VO + VA * sin (FREQ * time * 2.0 * M_PI) * exp (-time * THETA) ; +/* gtri - end - wbk - add PHASE parameter */ +#endif + + } + } + break ; + + case EXP: + { + double V1, V2, TD1, TD2, TAU1, TAU2 ; + + V1 = VSRCentry.d_VSRCcoeffsArray [instance_ID] [0] ; + V2 = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + TD1 = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 2 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] : CKTstep ; + TAU1 = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 3 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] : CKTstep ; + TD2 = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 4 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] != 0.0 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] : TD1 + CKTstep ; + TAU2 = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 5 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] : CKTstep ; + + if(time <= TD1) + value = V1 ; + else if (time <= TD2) + value = V1 + (V2 - V1) * (1 - exp (-(time - TD1) / TAU1)) ; + else + value = V1 + (V2 - V1) * (1 - exp (-(time - TD1) / TAU1)) + + (V1 - V2) * (1 - exp (-(time - TD2) / TAU2)) ; + } + break ; + + case SFFM: + { + double VO, VA, FC, MDI, FS ; + +#ifdef XSPICE +/* gtri - begin - wbk - add PHASE parameters */ + double PHASEC, PHASES, phasec, phases ; + + PHASEC = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 5 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] : 0.0 ; + PHASES = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 6 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [6] : 0.0 ; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0 ; + phases = PHASES * M_PI / 180.0 ; +#endif + + VO = VSRCentry.d_VSRCcoeffsArray [instance_ID] [0] ; + VA = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + FC = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 2 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + MDI = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 3 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [3] : 0.0 ; + FS = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 4 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] : (1 / CKTfinalTime) ; + +#ifdef XSPICE + /* compute waveform value */ + value = VO + VA * sin ((2.0 * M_PI * FC * time + phasec) + + MDI * sin (2.0 * M_PI * FS * time + phases)) ; +#else + value = VO + VA * sin ((2.0 * M_PI * FC * time) + + MDI * sin (2.0 * M_PI * FS * time)) ; +/* gtri - end - wbk - add PHASE parameters */ +#endif + + } + break ; + + case AM: + { + double VA, FC, MF, VO, TD ; + +#ifdef XSPICE +/* gtri - begin - wbk - add PHASE parameters */ + double PHASEC, PHASES, phasec, phases ; + + PHASEC = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 5 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [5] : 0.0 ; + PHASES = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 6 + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [6] : 0.0 ; + + /* compute phases in radians */ + phasec = PHASEC * M_PI / 180.0 ; + phases = PHASES * M_PI / 180.0 ; +#endif + + VA = VSRCentry.d_VSRCcoeffsArray [instance_ID] [0] ; + VO = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + MF = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 2 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [2] : (1 / CKTfinalTime) ; + FC = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 3 + ? VSRCentry.d_VSRCcoeffsArray [3] [instance_ID] : 0.0 ; + TD = VSRCentry.d_VSRCfunctionOrderArray [instance_ID] > 4 + && VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] + ? VSRCentry.d_VSRCcoeffsArray [instance_ID] [4] : 0.0 ; + + time -= TD ; + if (time <= 0) + value = 0 ; + else { + +#ifdef XSPICE + /* compute waveform value */ + value = VA * (VO + sin (2.0 * M_PI * MF * time + phases )) * + sin (2.0 * M_PI * FC * time + phases) ; + +#else + value = VA * (VO + sin (2.0 * M_PI * MF * time)) * + sin (2.0 * M_PI * FC * time) ; +/* gtri - end - wbk - add PHASE parameters */ +#endif + + } + } + break ; + + case PWL: + { + int i = 0, num_repeat = 0, ii = 0 ; + double repeat_time = 0.0, end_time, breakpt_time, itime ; + + time -= VSRCentry.d_VSRCrdelayArray [instance_ID] ; + + if (time < VSRCentry.d_VSRCcoeffsArray [instance_ID] [0]) + { + value = VSRCentry.d_VSRCcoeffsArray [instance_ID] [1] ; + goto loadDone ; + } + + do + { + for (i = ii ; i < (VSRCentry.d_VSRCfunctionOrderArray [instance_ID] / 2) - 1 ; i++) + { + itime = VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i] ; + if (AlmostEqualUlps (itime + repeat_time, time, 3)) + { + value = VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i + 1] ; + goto loadDone ; + } else if ((VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i] + repeat_time < time) + && (VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * (i + 1)] + + repeat_time > time)) + { + value = VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i + 1] + + (((time - (VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i] + repeat_time)) / + (VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * (i + 1)] - + VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i])) * + (VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i + 3] - + VSRCentry.d_VSRCcoeffsArray [instance_ID] [2 * i + 1])) ; + goto loadDone ; + } + } + value = VSRCentry.d_VSRCcoeffsArray [instance_ID] + [VSRCentry.d_VSRCfunctionOrderArray [instance_ID] - 1] ; + + if (!VSRCentry.d_VSRCrGivenArray [instance_ID]) + goto loadDone ; + + end_time = VSRCentry.d_VSRCcoeffsArray [instance_ID] + [VSRCentry.d_VSRCfunctionOrderArray [instance_ID] - 2] ; + breakpt_time = VSRCentry.d_VSRCcoeffsArray [instance_ID] + [VSRCentry.d_VSRCrBreakptArray [instance_ID]] ; + repeat_time = end_time + (end_time - breakpt_time) * (num_repeat ++) - breakpt_time ; + ii = VSRCentry.d_VSRCrBreakptArray [instance_ID] / 2 ; + } while (VSRCentry.d_VSRCrGivenArray [instance_ID]) ; + break ; + } + } // switch + } // else (line 55) +loadDone: + +#ifdef XSPICE_EXP +/* gtri - begin - wbk - modify for supply ramping option */ + value *= CKTsrcFact ; + value *= cm_analog_ramp_factor () ; +#else + if (CKTmode & MODETRANOP) + value *= CKTsrcFact ; +/* gtri - end - wbk - modify to process srcFact, etc. for all sources */ +#endif + + d_CKTloadOutputRHS [d_PositionVectorRHS [instance_ID]] = value ; + } + } + + return ; +} diff --git a/src/spicelib/devices/vsrc/CUSPICE/cuvsrcsetup.c b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcsetup.c new file mode 100644 index 000000000..39d6c558a --- /dev/null +++ b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcsetup.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "vsrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMalloc MACRO to check it for errors --> CUDAMALLOCCHECK(name of pointer, dimension, type, status) */ +#define CUDAMALLOCCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuVSRCsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMalloc failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuVSRCsetup routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuVSRCsetup +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size1, size2 ; + cudaError_t status ; + VSRCmodel *model = (VSRCmodel *)inModel ; + VSRCinstance *here ; + + size1 = (long unsigned int) model->n_instances; + + /* Space Allocation to GPU */ + status = cudaMalloc ((void **)&(model->d_PositionVector), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVector, size1, int, status) + + status = cudaMemcpy (model->d_PositionVector, model->PositionVector, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVector, size1, int, status) + + status = cudaMalloc ((void **)&(model->d_PositionVectorRHS), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->d_PositionVectorRHS, size1, int, status) + + status = cudaMemcpy (model->d_PositionVectorRHS, model->PositionVectorRHS, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->d_PositionVectorRHS, size1, int, status) + + /* Special case VSRCparamGPU.VSRCcoeffsArray */ + model->VSRCparamCPU.VSRCcoeffsArray = (double **) malloc (size1 * sizeof(double *)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCcoeffsArray), size1 * sizeof(double *)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCcoeffsArray, size1, double*, status) + + i = 0 ; + + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + status = cudaMalloc ((void **)&(model->VSRCparamCPU.VSRCcoeffsArray[i]), size2 * sizeof(double)) ; + CUDAMALLOCCHECK (model->VSRCparamCPU.VSRCcoeffsArray [i], size2, double, status) + + i++ ; + } + + /* Structure pointer vectors in GPU */ + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCcoeffsArray, model->VSRCparamCPU.VSRCcoeffsArray, size1 * sizeof(double *), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->VSRCparamGPU.d_VSRCcoeffsArray, size1, sizeof(double *), status) + + i = 0 ; + + model->VSRCparamCPU.VSRCcoeffsArrayHost = (double **) malloc (size1 * sizeof(double *)) ; + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + model->VSRCparamCPU.VSRCcoeffsArrayHost [i] = (double *) malloc (size2 * sizeof(double)) ; + + i++ ; + } + /* ----------------------------------------- */ + + /* DOUBLE */ + model->VSRCparamCPU.VSRCdcvalueArray = (double *) malloc (size1 * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCdcvalueArray), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCdcvalueArray, size1, double, status) + + model->VSRCparamCPU.VSRCrdelayArray = (double *) malloc (size1 * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCrdelayArray), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCrdelayArray, size1, double, status) + + model->VSRCparamCPU.VSRCValueArray = (double *) malloc (size1 * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCValueArray), size1 * sizeof(double)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCValueArray, size1, double, status) + + /* INT */ + model->VSRCparamCPU.VSRCdcGivenArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCdcGivenArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCdcGivenArray, size1, int, status) + + model->VSRCparamCPU.VSRCfunctionTypeArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCfunctionTypeArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCfunctionTypeArray, size1, int, status) + + model->VSRCparamCPU.VSRCfunctionOrderArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCfunctionOrderArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCfunctionOrderArray, size1, int, status) + + model->VSRCparamCPU.VSRCrGivenArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCrGivenArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCrGivenArray, size1, int, status) + + model->VSRCparamCPU.VSRCrBreakptArray = (int *) malloc (size1 * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->VSRCparamGPU.d_VSRCrBreakptArray), size1 * sizeof(int)) ; + CUDAMALLOCCHECK (model->VSRCparamGPU.d_VSRCrBreakptArray, size1, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/vsrc/CUSPICE/cuvsrctemp.c b/src/spicelib/devices/vsrc/CUSPICE/cuvsrctemp.c new file mode 100644 index 000000000..2de620cf5 --- /dev/null +++ b/src/spicelib/devices/vsrc/CUSPICE/cuvsrctemp.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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/config.h" +#include "cuda_runtime_api.h" +#include "vsrcdefs.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +/* cudaMemcpy MACRO to check it for errors --> CUDAMEMCPYCHECK(name of pointer, dimension, type, status) */ +#define CUDAMEMCPYCHECK(a, b, c, d) \ + if (d != cudaSuccess) \ + { \ + fprintf (stderr, "cuVSRCtemp routine...\n") ; \ + fprintf (stderr, "Error: cudaMemcpy failed on %s size1 of %d bytes\n", #a, (int)(b * sizeof(c))) ; \ + fprintf (stderr, "Error: %s = %d, %s\n", #d, d, cudaGetErrorString (d)) ; \ + return (E_NOMEM) ; \ + } + +int +cuVSRCtemp +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size1, size2 ; + cudaError_t status ; + VSRCmodel *model = (VSRCmodel *)inModel ; + VSRCinstance *here ; + + size1 = (long unsigned int) model->n_instances; + + i = 0 ; + + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + size2 = (long unsigned int)here->n_coeffs ; + status = cudaMemcpy (model->VSRCparamCPU.VSRCcoeffsArray [i], model->VSRCparamCPU.VSRCcoeffsArrayHost [i], size2 * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->VSRCparamCPU.VSRCcoeffsArray [i], size2, double, status) + + i++ ; + } + + /* DOUBLE */ + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCdcvalueArray, model->VSRCparamCPU.VSRCdcvalueArray, size1 * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCdcvalueArray, size1, double, status) + + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCrdelayArray, model->VSRCparamCPU.VSRCrdelayArray, size1 * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCrdelayArray, size1, double, status) + + /* INT */ + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCdcGivenArray, model->VSRCparamCPU.VSRCdcGivenArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCdcGivenArray, size1, int, status) + + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCfunctionTypeArray, model->VSRCparamCPU.VSRCfunctionTypeArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCfunctionTypeArray, size1, int, status) + + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCfunctionOrderArray, model->VSRCparamCPU.VSRCfunctionOrderArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCfunctionOrderArray, size1, int, status) + + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCrGivenArray, model->VSRCparamCPU.VSRCrGivenArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.d_VSRCrGivenArray, size1, int, status) + + status = cudaMemcpy (model->VSRCparamGPU.d_VSRCrBreakptArray, model->VSRCparamCPU.VSRCrBreakptArray, size1 * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK(model->VSRCparamGPU.VSRCrBreakptArray, size1, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/vsrc/CUSPICE/vsrctopology.c b/src/spicelib/devices/vsrc/CUSPICE/vsrctopology.c new file mode 100644 index 000000000..220135c5c --- /dev/null +++ b/src/spicelib/devices/vsrc/CUSPICE/vsrctopology.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * 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 "ngspice/cktdefs.h" +#include "vsrcdefs.h" +#include "ngspice/sperror.h" + +#define TopologyMatrixInsert(Ptr, instance_ID, offset, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOi [global_ID] = (int)(here->Ptr - basePtr) ; \ + ckt->CKTtopologyMatrixCOOj [global_ID] = model->PositionVector [instance_ID] + offset ; \ + ckt->CKTtopologyMatrixCOOx [global_ID] = Value ; + +#define TopologyMatrixInsertRHS(offset, instance_ID, offsetRHS, Value, global_ID) \ + ckt->CKTtopologyMatrixCOOiRHS [global_ID] = here->offset ; \ + ckt->CKTtopologyMatrixCOOjRHS [global_ID] = model->PositionVectorRHS [instance_ID] + offsetRHS ; \ + ckt->CKTtopologyMatrixCOOxRHS [global_ID] = Value ; + +int +VSRCtopology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + VSRCmodel *model = (VSRCmodel *)inModel ; + VSRCinstance *here ; + int k ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the capacitor models */ + for ( ; model != NULL ; model = VSRCnextModel(model)) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + if ((here->VSRCposNode != 0) && (here->VSRCbranch != 0)) + { + TopologyMatrixInsert (VSRCposIbrPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->VSRCnegNode != 0) && (here->VSRCbranch != 0)) + { + TopologyMatrixInsert (VSRCnegIbrPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->VSRCbranch != 0) && (here->VSRCposNode != 0)) + { + TopologyMatrixInsert (VSRCibrPosPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + if ((here->VSRCbranch != 0) && (here->VSRCnegNode != 0)) + { + TopologyMatrixInsert (VSRCibrNegPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + if (here->VSRCbranch != 0) + { + TopologyMatrixInsertRHS (VSRCbranch, k, 0, 1, *j) ; + (*j)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/vsrc/Makefile.am b/src/spicelib/devices/vsrc/Makefile.am index 9800efa14..05daca1b3 100644 --- a/src/spicelib/devices/vsrc/Makefile.am +++ b/src/spicelib/devices/vsrc/Makefile.am @@ -31,4 +31,18 @@ endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) +if USE_CUSPICE_WANTED +.cu.lo: + $(AM_V_GEN)$(top_srcdir)/src/libtool_wrapper_for_cuda.tcl $@ $(AM_CFLAGS) $(NVCC) $(CUDA_CFLAGS) $(AM_CPPFLAGS) -c $< + +libvsrc_la_SOURCES += \ + CUSPICE/vsrctopology.c \ + CUSPICE/cuvsrcfree.c \ + CUSPICE/cuvsrcload.cu \ + CUSPICE/cuvsrcsetup.c \ + CUSPICE/cuvsrctemp.c + +AM_CPPFLAGS += $(CUDA_CPPFLAGS) +endif + MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index 21cbee378..773526296 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -86,8 +86,50 @@ typedef struct sVSRCinstance { BindElement *VSRCibrIbrBinding ; #endif +#ifdef USE_CUSPICE + double *d_VSRCcoeffs ; + + int n_coeffs ; +#endif + } VSRCinstance ; +#ifdef USE_CUSPICE +typedef struct sVSRCparamCPUstruct { + /* pointer to array of coefficients in GPU */ + double **VSRCcoeffsArrayHost ; + double **VSRCcoeffsArray ; + + double *VSRCcpuPointersD [3] ; + #define VSRCdcvalueArray VSRCcpuPointersD[0] + #define VSRCrdelayArray VSRCcpuPointersD[1] + #define VSRCValueArray VSRCcpuPointersD[2] + + int *VSRCcpuPointersI [5] ; + #define VSRCdcGivenArray VSRCcpuPointersI[0] + #define VSRCfunctionTypeArray VSRCcpuPointersI[1] + #define VSRCfunctionOrderArray VSRCcpuPointersI[2] + #define VSRCrGivenArray VSRCcpuPointersI[3] + #define VSRCrBreakptArray VSRCcpuPointersI[4] +} VSRCparamCPUstruct ; + +typedef struct sVSRCparamGPUstruct { + /* pointer to array of coefficients in GPU */ + double **d_VSRCcoeffsArray ; + + double *VSRCcudaPointersD [3] ; + #define d_VSRCdcvalueArray VSRCcudaPointersD[0] + #define d_VSRCrdelayArray VSRCcudaPointersD[1] + #define d_VSRCValueArray VSRCcudaPointersD[2] + + int *VSRCcudaPointersI [5] ; + #define d_VSRCdcGivenArray VSRCcudaPointersI[0] + #define d_VSRCfunctionTypeArray VSRCcudaPointersI[1] + #define d_VSRCfunctionOrderArray VSRCcudaPointersI[2] + #define d_VSRCrGivenArray VSRCcudaPointersI[3] + #define d_VSRCrBreakptArray VSRCcudaPointersI[4] +} VSRCparamGPUstruct ; +#endif /* per model data */ @@ -100,6 +142,25 @@ typedef struct sVSRCmodel { #define VSRCinstances(inst) ((VSRCinstance *)((inst)->gen.GENinstances)) #define VSRCmodName gen.GENmodName +#ifdef USE_CUSPICE + VSRCparamCPUstruct VSRCparamCPU ; + VSRCparamGPUstruct VSRCparamGPU ; + + int offset ; + int n_values ; + int n_Ptr ; + int *PositionVector ; + int *d_PositionVector ; + + int offsetRHS ; + int n_valuesRHS ; + int n_PtrRHS ; + int *PositionVectorRHS ; + int *d_PositionVectorRHS ; + + int n_instances ; +#endif + } VSRCmodel; /* source function types (shared with current sources) */ diff --git a/src/spicelib/devices/vsrc/vsrcext.h b/src/spicelib/devices/vsrc/vsrcext.h index f5f74e89e..de67ded0b 100644 --- a/src/spicelib/devices/vsrc/vsrcext.h +++ b/src/spicelib/devices/vsrc/vsrcext.h @@ -24,3 +24,7 @@ extern int VSRCbindCSC (GENmodel*, CKTcircuit*) ; extern int VSRCbindCSCComplex (GENmodel*, CKTcircuit*) ; extern int VSRCbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; #endif + +#ifdef USE_CUSPICE +extern int VSRCtopology (GENmodel *, CKTcircuit *, int *, int *) ; +#endif diff --git a/src/spicelib/devices/vsrc/vsrcinit.c b/src/spicelib/devices/vsrc/vsrcinit.c index 97af7a504..91ef2a4be 100644 --- a/src/spicelib/devices/vsrc/vsrcinit.c +++ b/src/spicelib/devices/vsrc/vsrcinit.c @@ -6,6 +6,9 @@ #include "vsrcext.h" #include "vsrcinit.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif SPICEdev VSRCinfo = { .DEVpublic = { @@ -33,7 +36,11 @@ SPICEdev VSRCinfo = { .DEVparam = VSRCparam, .DEVmodParam = NULL, +#ifdef USE_CUSPICE + .DEVload = cuVSRCload, +#else .DEVload = VSRCload, +#endif .DEVsetup = VSRCsetup, .DEVunsetup = VSRCunsetup, .DEVpzSetup = VSRCpzSetup, @@ -71,6 +78,10 @@ SPICEdev VSRCinfo = { .DEVbindCSCComplex = VSRCbindCSCComplex, .DEVbindCSCComplexToReal = VSRCbindCSCComplexToReal, #endif +#ifdef USE_CUSPICE + .cuDEVdestroy = cuVSRCdestroy, + .DEVtopology = VSRCtopology, +#endif }; diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index f21ec4354..69fe4e70c 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -26,6 +26,11 @@ static void copy_coeffs(VSRCinstance *here, IFvalue *value) here->VSRCcoeffsGiven = TRUE; memcpy(here->VSRCcoeffs, value->v.vec.rVec, (size_t) n * sizeof(double)); + +#ifdef USE_CUSPICE + here->n_coeffs = n ; +#endif + } diff --git a/src/spicelib/devices/vsrc/vsrcset.c b/src/spicelib/devices/vsrc/vsrcset.c index 6ec98db9c..b595230a7 100644 --- a/src/spicelib/devices/vsrc/vsrcset.c +++ b/src/spicelib/devices/vsrc/vsrcset.c @@ -10,6 +10,10 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + /* ARGSUSED */ int VSRCsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *state) @@ -60,7 +64,90 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ } } - return(OK); + +#ifdef USE_CUSPICE + int i, j, k, status ; + + /* Counting the instances */ + for (model = (VSRCmodel *)inModel ; model != NULL ; model = VSRCnextModel(model)) + { + i = 0 ; + + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + i++ ; + } + + /* How much instances we have */ + model->n_instances = i ; + } + + /* loop through all the voltage source models */ + for (model = (VSRCmodel *)inModel ; model != NULL ; model = VSRCnextModel(model)) + { + model->offset = ckt->total_n_values ; + model->offsetRHS = ckt->total_n_valuesRHS ; + + j = 0 ; + k = 0 ; + + /* loop through all the instances of the model */ + for (here = VSRCinstances(model); here != NULL ; here = VSRCnextInstance(here)) + { + /* For the Matrix */ + if ((here->VSRCposNode != 0) && (here->VSRCbranch != 0)) + j++ ; + + if ((here->VSRCnegNode != 0) && (here->VSRCbranch != 0)) + j++ ; + + if ((here->VSRCbranch != 0) && (here->VSRCposNode != 0)) + j++ ; + + if ((here->VSRCbranch != 0) && (here->VSRCnegNode != 0)) + j++ ; + + /* For the RHS */ + if (here->VSRCbranch != 0) + k++ ; + } + + model->n_values = !model->n_instances; + ckt->total_n_values += model->n_values ; + + model->n_Ptr = j ; + ckt->total_n_Ptr += model->n_Ptr ; + + model->n_valuesRHS = !model->n_instances; + ckt->total_n_valuesRHS += model->n_valuesRHS ; + + model->n_PtrRHS = k ; + ckt->total_n_PtrRHS += model->n_PtrRHS ; + + + /* Position Vector assignment */ + model->PositionVector = TMALLOC (int, !model->n_instances) ; + + for (j = 0 ; j < !model->n_instances; j++) + model->PositionVector [j] = model->offset + j ; + + /* Position Vector assignment for the RHS */ + model->PositionVectorRHS = TMALLOC (int, !model->n_instances) ; + + for (j = 0 ; j < !model->n_instances; j++) + model->PositionVectorRHS [j] = model->offsetRHS + j ; + } + + /* loop through all the voltage source models */ + for (model = (VSRCmodel *)inModel ; model != NULL ; model = VSRCnextModel(model)) + { + status = cuVSRCsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } +#endif + + return (OK) ; } int diff --git a/src/spicelib/devices/vsrc/vsrctemp.c b/src/spicelib/devices/vsrc/vsrctemp.c index 0a468e34f..b6d20d74f 100644 --- a/src/spicelib/devices/vsrc/vsrctemp.c +++ b/src/spicelib/devices/vsrc/vsrctemp.c @@ -10,21 +10,33 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef USE_CUSPICE +#include "ngspice/CUSPICE/CUSPICE.h" +#endif + /*ARGSUSED*/ int VSRCtemp(GENmodel *inModel, CKTcircuit *ckt) /* Pre-process voltage source parameters */ { - VSRCmodel *model = (VSRCmodel *) inModel; + VSRCmodel *model = (VSRCmodel *)inModel; VSRCinstance *here; double radians; NG_IGNORE(ckt); +#ifdef USE_CUSPICE + int i, j, status ; +#endif + /* loop through all the voltage source models */ for( ; model != NULL; model = VSRCnextModel(model)) { +#ifdef USE_CUSPICE + i = 0 ; +#endif + /* loop through all the instances of the model */ for (here = VSRCinstances(model); here != NULL ; here=VSRCnextInstance(here)) { @@ -50,8 +62,33 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt) radians = here->VSRCacPhase * M_PI / 180.0; here->VSRCacReal = here->VSRCacMag * cos(radians); here->VSRCacImag = here->VSRCacMag * sin(radians); + +#ifdef USE_CUSPICE + for (j = 0 ; j < here->n_coeffs ; j++) + { + model->VSRCparamCPU.VSRCcoeffsArrayHost [i] [j] = here->VSRCcoeffs [j] ; + } + + model->VSRCparamCPU.VSRCdcvalueArray[i] = here->VSRCdcValue ; + model->VSRCparamCPU.VSRCrdelayArray[i] = here->VSRCrdelay ; + model->VSRCparamCPU.VSRCdcGivenArray[i] = here->VSRCdcGiven ; + model->VSRCparamCPU.VSRCfunctionTypeArray[i] = here->VSRCfunctionType ; + model->VSRCparamCPU.VSRCfunctionOrderArray[i] = here->VSRCfunctionOrder ; + model->VSRCparamCPU.VSRCrGivenArray[i] = here->VSRCrGiven ; + model->VSRCparamCPU.VSRCrBreakptArray[i] = here->VSRCrBreakpt ; + + i++ ; +#endif + } + +#ifdef USE_CUSPICE + status = cuVSRCtemp ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; +#endif + } - return(OK); + return (OK) ; }