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/include/ngspice/CUSPICE/CUSPICE.h b/src/include/ngspice/CUSPICE/CUSPICE.h new file mode 100644 index 000000000..19b5fdf37 --- /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 cuBSIM4destroy (GENmodel *) ; +int cuBSIM4getic (GENmodel *) ; +int cuBSIM4load (GENmodel *, CKTcircuit *) ; +int cuBSIM4setup (GENmodel *) ; +int cuBSIM4temp (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/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/spicelib/analysis/CUSPICE/cucktflush.c b/src/spicelib/analysis/CUSPICE/cucktflush.c new file mode 100644 index 000000000..c2bc44555 --- /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..aba087b73 --- /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..db67ebef6 --- /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..ce3f9e113 --- /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..6c63f82f7 --- /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..6bf0f739d --- /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/devices/bsim4/CUSPICE/b4topology.c b/src/spicelib/devices/bsim4/CUSPICE/b4topology.c new file mode 100644 index 000000000..037c160fe --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/b4topology.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 "bsim4def.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 +BSIM4topology (GENmodel *inModel, CKTcircuit *ckt, int *i, int *j) +{ + BSIM4model *model = (BSIM4model *)inModel ; + BSIM4instance *here ; + int k, total_offset, total_offsetRHS ; + double *basePtr ; + basePtr = ckt->CKTmatrix->CKTkluAx ; + + /* loop through all the capacitor models */ + for ( ; model != NULL ; model = model->BSIM4nextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->BSIM4instances ; here != NULL ; here = here->BSIM4nextInstance) + { + total_offset = 0 ; + total_offsetRHS = 0 ; + + /* For the Matrix */ + if (here->BSIM4rgateMod == 1) + { + /* m * geltd */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GPgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GEgpPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (gcggb + geltd - ggtg + gIgtotg) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPgpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPspPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPbpPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + total_offset += 5 ; + } + else if (here->BSIM4rgateMod == 2) + { + /* m * gcrg */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgg */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GEgpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgd */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GEdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgs */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GEspPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgb */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GEbpPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + /* m * gcrg */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GPgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPgpPtr, k, 5, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPdpPtr, k, 6, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPspPtr, k, 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPbpPtr, k, 8, 1, *i) ; + (*i)++ ; + } + + total_offset += 9 ; + } + else if (here->BSIM4rgateMod == 3) + { + /* m * geltd */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GEgePtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4gNodeExt != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4GEgmPtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * geltd */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4gNodeExt != 0)) + { + TopologyMatrixInsert (BSIM4GMgePtr, k, 0, -1, *i) ; + (*i)++ ; + } + + /* m * (geltd + gcrg + gcgmgmb) */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4GMgmPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgd + gcgmdb) */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GMdpPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * gcrgg */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GMgpPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgs + gcgmsb) */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GMspPtr, k, 4, 1, *i) ; + (*i)++ ; + } + + /* m * (gcrgb + gcgmbb) */ + if ((here->BSIM4gNodeMid != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GMbpPtr, k, 5, 1, *i) ; + (*i)++ ; + } + + /* m * gcdgmb */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4DPgmPtr, k, 6, 1, *i) ; + (*i)++ ; + } + + /* m * gcrg */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4GPgmPtr, k, 7, -1, *i) ; + (*i)++ ; + } + + /* m * gcsgmb */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4SPgmPtr, k, 8, 1, *i) ; + (*i)++ ; + } + + /* m * gcbgmb */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4gNodeMid != 0)) + { + TopologyMatrixInsert (BSIM4BPgmPtr, k, 9, 1, *i) ; + (*i)++ ; + } + + /* m * (gcggb - gcrgg - ggtg + gIgtotg) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPgpPtr, k, 10, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - gcrgd - ggtd + gIgtotd) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPdpPtr, k, 11, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - gcrgs - ggts + gIgtots) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPspPtr, k, 12, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - gcrgb - ggtb + gIgtotb) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPbpPtr, k, 13, 1, *i) ; + (*i)++ ; + } + + total_offset += 14 ; + } else { + /* m * (gcggb - ggtg + gIgtotg) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPgpPtr, k, 0, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgdb - ggtd + gIgtotd) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPdpPtr, k, 1, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgsb - ggts + gIgtots) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPspPtr, k, 2, 1, *i) ; + (*i)++ ; + } + + /* m * (gcgbb - ggtb + gIgtotb) */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4GPbpPtr, k, 3, 1, *i) ; + (*i)++ ; + } + + total_offset += 4 ; + } + + + if (model->BSIM4rdsMod) + { + /* m * gdtotg */ + if ((here->BSIM4dNode != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DgpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * gdtots */ + if ((here->BSIM4dNode != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DspPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * gdtotb */ + if ((here->BSIM4dNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DbpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * gstotd */ + if ((here->BSIM4sNode != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SdpPtr, k, total_offset + 3, 1, *i) ; + (*i)++ ; + } + + /* m * gstotg */ + if ((here->BSIM4sNode != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SgpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * gstotb */ + if ((here->BSIM4sNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SbpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + total_offset += 4 ; + } + + + /* m * (gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd - + gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd) + m * ggidld */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DPdpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4dNode != 0)) + { + TopologyMatrixInsert (BSIM4DPdPtr, k, total_offset + 1, -1, *i) ; + (*i)++ ; + } + + /* m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + dxpart * ggtg + T1 * ddxpart_dVg) + m * ggidlg */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DPgpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4gds + gdtots - dxpart * ggts + gIdtots - + T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp) + m * (ggidlg + ggidld + ggidlb) */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DPspPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb - T1 * ddxpart_dVb - dxpart * ggtb) - m * ggidlb */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DPbpPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * (gdpr - gdtotd) */ + if ((here->BSIM4dNode != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DdpPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * (gdpr + gdtot) */ + if ((here->BSIM4dNode != 0) && (here->BSIM4dNode != 0)) + { + TopologyMatrixInsert (BSIM4DdPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4gds + gstotd + RevSum - gcsdb - gbspdp - + T1 * dsxpart_dVd - sxpart * ggtd + gIstotd) + m * (ggisls + ggislg + ggislb) */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SPdpPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + T1 * dsxpart_dVg - gIstotg) + m * ggislg */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SPgpPtr, k, total_offset + 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gspr + here->BSIM4gds + here->BSIM4gbs + T1 * dsxpart_dVs - + gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots) + m * ggisls */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SPspPtr, k, total_offset + 8, 1, *i) ; + (*i)++ ; + } + + /* m * (gspr + gstot) */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4sNode != 0)) + { + TopologyMatrixInsert (BSIM4SPsPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb - T1 * dsxpart_dVb + gIstotb) - m * ggislb */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SPbpPtr, k, total_offset + 10, -1, *i) ; + (*i)++ ; + } + + /* m * (gspr - gstots) */ + if ((here->BSIM4sNode != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SspPtr, k, total_offset + 11, -1, *i) ; + (*i)++ ; + } + + /* m * (gspr + gstot) */ + if ((here->BSIM4sNode != 0) && (here->BSIM4sNode != 0)) + { + TopologyMatrixInsert (BSIM4SsPtr, k, total_offset + 9, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbdb - gjbd + gbbdp - gIbtotd) - m * ggidld + m * (ggislg + ggisls + ggislb) */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BPdpPtr, k, total_offset + 12, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbgb - here->BSIM4gbgs - gIbtotg) - m * ggidlg - m * ggislg */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BPgpPtr, k, total_offset + 13, 1, *i) ; + (*i)++ ; + } + + /* m * (gcbsb - gjbs + gbbsp - gIbtots) + m * (ggidlg + ggidld + ggidlb) - m * ggisls */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BPspPtr, k, total_offset + 14, 1, *i) ; + (*i)++ ; + } + + /* m * (gjbd + gjbs + gcbbb - here->BSIM4gbbs - gIbtotb) - m * ggidlb - m * ggislb */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BPbpPtr, k, total_offset + 15, 1, *i) ; + (*i)++ ; + } + + total_offset += 16 ; + + /* stamp gidl included above */ + /* stamp gisl included above */ + + + if (here->BSIM4rbodyMod) + { + /* m * (gcdbdb - here->BSIM4gbd) */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4dbNode != 0)) + { + TopologyMatrixInsert (BSIM4DPdbPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4gbs - gcsbsb) */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4sbNode != 0)) + { + TopologyMatrixInsert (BSIM4SPsbPtr, k, total_offset + 1, -1, *i) ; + (*i)++ ; + } + + /* m * (gcdbdb - here->BSIM4gbd) */ + if ((here->BSIM4dbNode != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DBdpPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4gbd - gcdbdb + here->BSIM4grbpd + here->BSIM4grbdb) */ + if ((here->BSIM4dbNode != 0) && (here->BSIM4dbNode != 0)) + { + TopologyMatrixInsert (BSIM4DBdbPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbpd */ + if ((here->BSIM4dbNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4DBbpPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbdb */ + if ((here->BSIM4dbNode != 0) && (here->BSIM4bNode != 0)) + { + TopologyMatrixInsert (BSIM4DBbPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbpd */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4dbNode != 0)) + { + TopologyMatrixInsert (BSIM4BPdbPtr, k, total_offset + 3, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbpb */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4bNode != 0)) + { + TopologyMatrixInsert (BSIM4BPbPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbps */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4sbNode != 0)) + { + TopologyMatrixInsert (BSIM4BPsbPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4grbpd + here->BSIM4grbps + here->BSIM4grbpb) */ + if ((here->BSIM4bNodePrime != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BPbpPtr, k, total_offset + 7, 1, *i) ; + (*i)++ ; + } + + /* m * (gcsbsb - here->BSIM4gbs) */ + if ((here->BSIM4sbNode != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SBspPtr, k, total_offset + 8, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbps */ + if ((here->BSIM4sbNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4SBbpPtr, k, total_offset + 6, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbsb */ + if ((here->BSIM4sbNode != 0) && (here->BSIM4bNode != 0)) + { + TopologyMatrixInsert (BSIM4SBbPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4gbs - gcsbsb + here->BSIM4grbps + here->BSIM4grbsb) */ + if ((here->BSIM4sbNode != 0) && (here->BSIM4sbNode != 0)) + { + TopologyMatrixInsert (BSIM4SBsbPtr, k, total_offset + 10, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbdb */ + if ((here->BSIM4bNode != 0) && (here->BSIM4dbNode != 0)) + { + TopologyMatrixInsert (BSIM4BdbPtr, k, total_offset + 4, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbpb */ + if ((here->BSIM4bNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4BbpPtr, k, total_offset + 5, -1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4grbsb */ + if ((here->BSIM4bNode != 0) && (here->BSIM4sbNode != 0)) + { + TopologyMatrixInsert (BSIM4BsbPtr, k, total_offset + 9, -1, *i) ; + (*i)++ ; + } + + /* m * (here->BSIM4grbsb + here->BSIM4grbdb + here->BSIM4grbpb) */ + if ((here->BSIM4bNode != 0) && (here->BSIM4bNode != 0)) + { + TopologyMatrixInsert (BSIM4BbPtr, k, total_offset + 11, 1, *i) ; + (*i)++ ; + } + + total_offset += 12 ; + } + + + if (here->BSIM4trnqsMod) + { + /* m * (gqdef + here->BSIM4gtau) */ + if ((here->BSIM4qNode != 0) && (here->BSIM4qNode != 0)) + { + TopologyMatrixInsert (BSIM4QqPtr, k, total_offset + 0, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtg - gcqgb) */ + if ((here->BSIM4qNode != 0) && (here->BSIM4gNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4QgpPtr, k, total_offset + 1, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtd - gcqdb) */ + if ((here->BSIM4qNode != 0) && (here->BSIM4dNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4QdpPtr, k, total_offset + 2, 1, *i) ; + (*i)++ ; + } + + /* m * (ggts - gcqsb) */ + if ((here->BSIM4qNode != 0) && (here->BSIM4sNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4QspPtr, k, total_offset + 3, 1, *i) ; + (*i)++ ; + } + + /* m * (ggtb - gcqbb) */ + if ((here->BSIM4qNode != 0) && (here->BSIM4bNodePrime != 0)) + { + TopologyMatrixInsert (BSIM4QbpPtr, k, total_offset + 4, 1, *i) ; + (*i)++ ; + } + + /* m * dxpart * here->BSIM4gtau */ + if ((here->BSIM4dNodePrime != 0) && (here->BSIM4qNode != 0)) + { + TopologyMatrixInsert (BSIM4DPqPtr, k, total_offset + 5, 1, *i) ; + (*i)++ ; + } + + /* m * sxpart * here->BSIM4gtau */ + if ((here->BSIM4sNodePrime != 0) && (here->BSIM4qNode != 0)) + { + TopologyMatrixInsert (BSIM4SPqPtr, k, total_offset + 6, 1, *i) ; + (*i)++ ; + } + + /* m * here->BSIM4gtau */ + if ((here->BSIM4gNodePrime != 0) && (here->BSIM4qNode != 0)) + { + TopologyMatrixInsert (BSIM4GPqPtr, k, total_offset + 7, -1, *i) ; + (*i)++ ; + } + } + + + + /* For the RHS */ + /* m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq) */ + if (here->BSIM4dNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4dNodePrime, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqqg - ceqgcrg + Igtoteq) */ + if (here->BSIM4gNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4gNodePrime, k, total_offsetRHS + 1, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + + if (here->BSIM4rgateMod == 2) + { + /* m * ceqgcrg */ + if (here->BSIM4gNodeExt != 0) + { + TopologyMatrixInsertRHS (BSIM4gNodeExt, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 1 ; + } + else if (here->BSIM4rgateMod == 3) + { + /* m * (ceqqgmid + ceqgcrg) */ + if (here->BSIM4gNodeMid != 0) + { + TopologyMatrixInsertRHS (BSIM4gNodeMid, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 1 ; + } + + + if (!here->BSIM4rbodyMod) + { + /* m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq) */ + if (here->BSIM4bNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4bNodePrime, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4sNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4sNodePrime, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + } else { + /* m * (ceqjd + ceqqjd) */ + if (here->BSIM4dbNode != 0) + { + TopologyMatrixInsertRHS (BSIM4dbNode, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + /* m * (ceqbd + ceqbs - ceqqb + Ibtoteq) */ + if (here->BSIM4bNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4bNodePrime, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + /* m * (ceqjs + ceqqjs) */ + if (here->BSIM4sbNode != 0) + { + TopologyMatrixInsertRHS (BSIM4sbNode, k, total_offsetRHS + 2, -1, *j) ; + (*j)++ ; + } + + /* m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq) */ + if (here->BSIM4sNodePrime != 0) + { + TopologyMatrixInsertRHS (BSIM4sNodePrime, k, total_offsetRHS + 3, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 4 ; + } + + + if (model->BSIM4rdsMod) + { + /* m * ceqgdtot */ + if (here->BSIM4dNode != 0) + { + TopologyMatrixInsertRHS (BSIM4dNode, k, total_offsetRHS + 0, -1, *j) ; + (*j)++ ; + } + + /* m * ceqgstot */ + if (here->BSIM4sNode != 0) + { + TopologyMatrixInsertRHS (BSIM4sNode, k, total_offsetRHS + 1, 1, *j) ; + (*j)++ ; + } + + total_offsetRHS += 2 ; + + } + + + if (here->BSIM4trnqsMod) + { + /* m * (cqcheq - cqdef) */ + if (here->BSIM4qNode != 0) + { + TopologyMatrixInsertRHS (BSIM4qNode, k, total_offsetRHS + 0, 1, *j) ; + (*j)++ ; + } + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4/CUSPICE/cubsim4free.c b/src/spicelib/devices/bsim4/CUSPICE/cubsim4free.c new file mode 100644 index 000000000..b4f823640 --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/cubsim4free.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 "bsim4def.h" +#include "ngspice/CUSPICE/CUSPICE.h" + +int +cuBSIM4destroy +( +GENmodel *inModel +) +{ + BSIM4model *model = (BSIM4model *)inModel ; + BSIM4instance *here ; + + int i ; + + for ( ; model != NULL ; model = model->BSIM4nextModel) + { + /* Special case here->d_pParam */ + i = 0 ; + + for (here = model->BSIM4instances ; here != NULL ; here = here->BSIM4nextInstance) + { + if (here->pParam != NULL) + cudaFree (model->pParamHost [i]) ; + + i++ ; + } + + free (model->pParamHost) ; + cudaFree (model->d_pParam) ; + + /* DOUBLE */ + free (model->BSIM4paramCPU.BSIM4gbsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gbsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gbdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gbdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4vonRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vonRWArray) ; + + free (model->BSIM4paramCPU.BSIM4vdsatRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vdsatRWArray) ; + + free (model->BSIM4paramCPU.BSIM4csubRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4csubRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gdsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gmRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gmRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gmbsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gmbsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gcrgRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gcrgRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgidlRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgidlRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgislRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgislRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgcsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgcsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgcdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgcdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4IgbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IgbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4qinvRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qinvRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cggbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cggbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cgsbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cgsbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cgdbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cgdbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cdgbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cdgbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cdsbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cdsbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cddbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cddbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbgbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbgbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbsbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbsbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbdbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbdbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4csgbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4csgbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cssbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cssbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4csdbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4csdbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cgbbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cgbbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4csbbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4csbbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cdbbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cdbbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4cbbbRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cbbbRWArray) ; + + free (model->BSIM4paramCPU.BSIM4gtauRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gtauRWArray) ; + + free (model->BSIM4paramCPU.BSIM4qgateRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qgateRWArray) ; + + free (model->BSIM4paramCPU.BSIM4qbulkRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qbulkRWArray) ; + + free (model->BSIM4paramCPU.BSIM4qdrnRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qdrnRWArray) ; + + free (model->BSIM4paramCPU.BSIM4qsrcRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qsrcRWArray) ; + + free (model->BSIM4paramCPU.BSIM4capbsRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4capbsRWArray) ; + + free (model->BSIM4paramCPU.BSIM4capbdRWArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4capbdRWArray) ; + + free (model->BSIM4paramCPU.BSIM4icVDSArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4icVDSArray) ; + + free (model->BSIM4paramCPU.BSIM4icVGSArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4icVGSArray) ; + + free (model->BSIM4paramCPU.BSIM4icVBSArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4icVBSArray) ; + + free (model->BSIM4paramCPU.BSIM4vth0Array) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vth0Array) ; + + free (model->BSIM4paramCPU.BSIM4gbbsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gbbsArray) ; + + free (model->BSIM4paramCPU.BSIM4ggidlbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggidlbArray) ; + + free (model->BSIM4paramCPU.BSIM4gbgsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gbgsArray) ; + + free (model->BSIM4paramCPU.BSIM4ggidlgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggidlgArray) ; + + free (model->BSIM4paramCPU.BSIM4gbdsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gbdsArray) ; + + free (model->BSIM4paramCPU.BSIM4ggidldArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggidldArray) ; + + free (model->BSIM4paramCPU.BSIM4ggislsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggislsArray) ; + + free (model->BSIM4paramCPU.BSIM4ggislgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggislgArray) ; + + free (model->BSIM4paramCPU.BSIM4ggislbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggislbArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgsgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgsgArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcsgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcsgArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcsdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcsdArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcsbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcsbArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgdgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgdgArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcdgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcdgArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcddArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcddArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcdbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcdbArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgbgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgbgArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgbdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgbdArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgbbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgbbArray) ; + + free (model->BSIM4paramCPU.BSIM4ggidlsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggidlsArray) ; + + free (model->BSIM4paramCPU.BSIM4ggisldArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ggisldArray) ; + + free (model->BSIM4paramCPU.BSIM4gstotArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gstotArray) ; + + free (model->BSIM4paramCPU.BSIM4gstotdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gstotdArray) ; + + free (model->BSIM4paramCPU.BSIM4gstotgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gstotgArray) ; + + free (model->BSIM4paramCPU.BSIM4gstotbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gstotbArray) ; + + free (model->BSIM4paramCPU.BSIM4gdtotArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdtotArray) ; + + free (model->BSIM4paramCPU.BSIM4gdtotdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdtotdArray) ; + + free (model->BSIM4paramCPU.BSIM4gdtotgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdtotgArray) ; + + free (model->BSIM4paramCPU.BSIM4gdtotbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdtotbArray) ; + + free (model->BSIM4paramCPU.BSIM4cgdoArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cgdoArray) ; + + free (model->BSIM4paramCPU.BSIM4qgdoArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qgdoArray) ; + + free (model->BSIM4paramCPU.BSIM4cgsoArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cgsoArray) ; + + free (model->BSIM4paramCPU.BSIM4qgsoArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qgsoArray) ; + + free (model->BSIM4paramCPU.BSIM4AseffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4AseffArray) ; + + free (model->BSIM4paramCPU.BSIM4PseffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4PseffArray) ; + + free (model->BSIM4paramCPU.BSIM4nfArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4nfArray) ; + + free (model->BSIM4paramCPU.BSIM4XExpBVSArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4XExpBVSArray) ; + + free (model->BSIM4paramCPU.BSIM4vjsmFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vjsmFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4IVjsmFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IVjsmFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4vjsmRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vjsmRevArray) ; + + free (model->BSIM4paramCPU.BSIM4IVjsmRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IVjsmRevArray) ; + + free (model->BSIM4paramCPU.BSIM4SslpRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SslpRevArray) ; + + free (model->BSIM4paramCPU.BSIM4SslpFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SslpFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4AdeffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4AdeffArray) ; + + free (model->BSIM4paramCPU.BSIM4PdeffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4PdeffArray) ; + + free (model->BSIM4paramCPU.BSIM4XExpBVDArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4XExpBVDArray) ; + + free (model->BSIM4paramCPU.BSIM4vjdmFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vjdmFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4IVjdmFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IVjdmFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4vjdmRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vjdmRevArray) ; + + free (model->BSIM4paramCPU.BSIM4IVjdmRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IVjdmRevArray) ; + + free (model->BSIM4paramCPU.BSIM4DslpRevArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DslpRevArray) ; + + free (model->BSIM4paramCPU.BSIM4DslpFwdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DslpFwdArray) ; + + free (model->BSIM4paramCPU.BSIM4SjctTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SjctTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4SswTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SswTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4SswgTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SswgTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4DjctTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DjctTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4DswTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DswTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4DswgTempRevSatCurArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DswgTempRevSatCurArray) ; + + free (model->BSIM4paramCPU.BSIM4vbscArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vbscArray) ; + + free (model->BSIM4paramCPU.BSIM4thetavthArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4thetavthArray) ; + + free (model->BSIM4paramCPU.BSIM4eta0Array) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4eta0Array) ; + + free (model->BSIM4paramCPU.BSIM4k2oxArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4k2oxArray) ; + + free (model->BSIM4paramCPU.BSIM4nstarArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4nstarArray) ; + + free (model->BSIM4paramCPU.BSIM4vfbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vfbArray) ; + + free (model->BSIM4paramCPU.BSIM4vgs_effArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vgs_effArray) ; + + free (model->BSIM4paramCPU.BSIM4vgd_effArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vgd_effArray) ; + + free (model->BSIM4paramCPU.BSIM4dvgs_eff_dvgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dvgs_eff_dvgArray) ; + + free (model->BSIM4paramCPU.BSIM4dvgd_eff_dvgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dvgd_eff_dvgArray) ; + + free (model->BSIM4paramCPU.BSIM4VgsteffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4VgsteffArray) ; + + free (model->BSIM4paramCPU.BSIM4grdswArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grdswArray) ; + + free (model->BSIM4paramCPU.BSIM4AbulkArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4AbulkArray) ; + + free (model->BSIM4paramCPU.BSIM4vtfbphi1Array) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vtfbphi1Array) ; + + free (model->BSIM4paramCPU.BSIM4ueffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4ueffArray) ; + + free (model->BSIM4paramCPU.BSIM4u0tempArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4u0tempArray) ; + + free (model->BSIM4paramCPU.BSIM4vsattempArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vsattempArray) ; + + free (model->BSIM4paramCPU.BSIM4EsatLArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4EsatLArray) ; + + free (model->BSIM4paramCPU.BSIM4VdseffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4VdseffArray) ; + + free (model->BSIM4paramCPU.BSIM4vtfbphi2Array) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vtfbphi2Array) ; + + free (model->BSIM4paramCPU.BSIM4CoxeffArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4CoxeffArray) ; + + free (model->BSIM4paramCPU.BSIM4AbovVgst2VtmArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4AbovVgst2VtmArray) ; + + free (model->BSIM4paramCPU.BSIM4IdovVdsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4IdovVdsArray) ; + + free (model->BSIM4paramCPU.BSIM4gcrgdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gcrgdArray) ; + + free (model->BSIM4paramCPU.BSIM4gcrgbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gcrgbArray) ; + + free (model->BSIM4paramCPU.BSIM4gcrggArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gcrggArray) ; + + free (model->BSIM4paramCPU.BSIM4grgeltdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grgeltdArray) ; + + free (model->BSIM4paramCPU.BSIM4gcrgsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gcrgsArray) ; + + free (model->BSIM4paramCPU.BSIM4sourceConductanceArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sourceConductanceArray) ; + + free (model->BSIM4paramCPU.BSIM4drainConductanceArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4drainConductanceArray) ; + + free (model->BSIM4paramCPU.BSIM4gstotsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gstotsArray) ; + + free (model->BSIM4paramCPU.BSIM4gdtotsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gdtotsArray) ; + + free (model->BSIM4paramCPU.BSIM4vfbzbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4vfbzbArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgssArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgssArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgddArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgddArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgbsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgbsArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcssArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcssArray) ; + + free (model->BSIM4paramCPU.BSIM4gIgcdsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gIgcdsArray) ; + + free (model->BSIM4paramCPU.BSIM4noiGd0Array) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4noiGd0Array) ; + + free (model->BSIM4paramCPU.BSIM4cqdbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cqdbArray) ; + + free (model->BSIM4paramCPU.BSIM4cqsbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cqsbArray) ; + + free (model->BSIM4paramCPU.BSIM4cqgbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cqgbArray) ; + + free (model->BSIM4paramCPU.BSIM4qchqsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qchqsArray) ; + + free (model->BSIM4paramCPU.BSIM4cqbbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4cqbbArray) ; + + free (model->BSIM4paramCPU.BSIM4taunetArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4taunetArray) ; + + free (model->BSIM4paramCPU.BSIM4gtgArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gtgArray) ; + + free (model->BSIM4paramCPU.BSIM4gtdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gtdArray) ; + + free (model->BSIM4paramCPU.BSIM4gtsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gtsArray) ; + + free (model->BSIM4paramCPU.BSIM4gtbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gtbArray) ; + + free (model->BSIM4paramCPU.BSIM4mArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4mArray) ; + + free (model->BSIM4paramCPU.BSIM4grbpdArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grbpdArray) ; + + free (model->BSIM4paramCPU.BSIM4grbdbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grbdbArray) ; + + free (model->BSIM4paramCPU.BSIM4grbpbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grbpbArray) ; + + free (model->BSIM4paramCPU.BSIM4grbpsArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grbpsArray) ; + + free (model->BSIM4paramCPU.BSIM4grbsbArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4grbsbArray) ; + + free (model->BSIM4paramCPU.BSIM4dNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dNodePrimeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodePrimeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodeExtRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodeExtRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodeMidRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodeMidRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4bNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4bNodePrimeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4sNodePrimeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sNodePrimeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4dbNodeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dbNodeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4sbNodeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sbNodeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4dNodeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dNodeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4sNodeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sNodeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4qNodeRHSValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qNodeRHSValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEgeValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEgeValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPgeValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPgeValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GEgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GEgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMgeValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMgeValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GMbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GMbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPgmValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPgmValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPdValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPdValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DdValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DdValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPsValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPsValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SsValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SsValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPdbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPdbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPsbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPsbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DBdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DBdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DBdbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DBdbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DBbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DBbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DBbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DBbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPdbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPdbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPsbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPsbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BPbpIFValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BPbpIFValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SBspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SBspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SBbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SBbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SBbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SBbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SBsbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SBsbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BdbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BdbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BsbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BsbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4BbValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4BbValueArray) ; + + free (model->BSIM4paramCPU.BSIM4QqValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4QqValueArray) ; + + free (model->BSIM4paramCPU.BSIM4QgpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4QgpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4QdpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4QdpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4QspValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4QspValueArray) ; + + free (model->BSIM4paramCPU.BSIM4QbpValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4QbpValueArray) ; + + free (model->BSIM4paramCPU.BSIM4DPqValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4DPqValueArray) ; + + free (model->BSIM4paramCPU.BSIM4SPqValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4SPqValueArray) ; + + free (model->BSIM4paramCPU.BSIM4GPqValueArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4GPqValueArray) ; + + /* INT */ + free (model->BSIM4paramCPU.BSIM4offArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4offArray) ; + + free (model->BSIM4paramCPU.BSIM4dNodePrimeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dNodePrimeArray) ; + + free (model->BSIM4paramCPU.BSIM4sNodePrimeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sNodePrimeArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodePrimeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodePrimeArray) ; + + free (model->BSIM4paramCPU.BSIM4bNodePrimeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4bNodePrimeArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodeExtArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodeExtArray) ; + + free (model->BSIM4paramCPU.BSIM4gNodeMidArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4gNodeMidArray) ; + + free (model->BSIM4paramCPU.BSIM4dbNodeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dbNodeArray) ; + + free (model->BSIM4paramCPU.BSIM4sbNodeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sbNodeArray) ; + + free (model->BSIM4paramCPU.BSIM4sNodeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4sNodeArray) ; + + free (model->BSIM4paramCPU.BSIM4dNodeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4dNodeArray) ; + + free (model->BSIM4paramCPU.BSIM4qNodeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4qNodeArray) ; + + free (model->BSIM4paramCPU.BSIM4rbodyModArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4rbodyModArray) ; + + free (model->BSIM4paramCPU.BSIM4modeArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4modeArray) ; + + free (model->BSIM4paramCPU.BSIM4rgateModArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4rgateModArray) ; + + free (model->BSIM4paramCPU.BSIM4trnqsModArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4trnqsModArray) ; + + free (model->BSIM4paramCPU.BSIM4acnqsModArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4acnqsModArray) ; + + free (model->BSIM4paramCPU.BSIM4statesArray) ; + cudaFree (model->BSIM4paramGPU.d_BSIM4statesArray) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4/CUSPICE/cubsim4getic.c b/src/spicelib/devices/bsim4/CUSPICE/cubsim4getic.c new file mode 100644 index 000000000..7d99cb2b2 --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/cubsim4getic.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 "bsim4def.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, "cuBSIM4getic 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 +cuBSIM4getic +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + BSIM4model *model = (BSIM4model *)inModel ; + + size = (long unsigned int)model->n_instances ; + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVDSArray, model->BSIM4paramCPU.BSIM4icVDSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVDSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVGSArray, model->BSIM4paramCPU.BSIM4icVGSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVGSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVBSArray, model->BSIM4paramCPU.BSIM4icVBSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVBSArray, size, double, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4/CUSPICE/cubsim4load.cu b/src/spicelib/devices/bsim4/CUSPICE/cubsim4load.cu new file mode 100644 index 000000000..cb209b778 --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/cubsim4load.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 "bsim4def.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 +BSIM4polyDepletion (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 cuBSIM4load_kernel +( +BSIM4paramGPUstruct, 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 +cuBSIM4load +( +GENmodel *inModel, CKTcircuit *ckt +) +{ + BSIM4model *model = (BSIM4model *)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 BSIM4 models */ + for ( ; model != NULL ; model = model->BSIM4nextModel) + { + /* 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 + + cuBSIM4load_kernel <<< block_x, thread, 0, stream [i] >>> + (model->BSIM4paramGPU, 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->BSIM4type, model->BSIM4rdsMod, model->BSIM4igcMod, + model->BSIM4igbMod, model->BSIM4vcrit, model->BSIM4vtm, + model->BSIM4vtm0, model->BSIM4SjctEmissionCoeff, + model->BSIM4SjctTempSatCurDensity, + model->BSIM4SjctSidewallTempSatCurDensity, + model->BSIM4SjctGateSidewallTempSatCurDensity, + model->BSIM4xjbvs, model->BSIM4bvs, model->BSIM4dioMod, + model->BSIM4DjctEmissionCoeff, model->BSIM4DjctTempSatCurDensity, + model->BSIM4DjctSidewallTempSatCurDensity, + model->BSIM4DjctGateSidewallTempSatCurDensity, model->BSIM4xjbvd, + model->BSIM4bvd, model->BSIM4njtsswstemp, model->BSIM4njtsswgstemp, + model->BSIM4njtsstemp, model->BSIM4njtsswdtemp, + model->BSIM4njtsswgdtemp, model->BSIM4njtsdtemp, model->BSIM4vtss, + model->BSIM4vtsd, model->BSIM4vtssws, model->BSIM4vtsswd, + model->BSIM4vtsswgs, model->BSIM4vtsswgd, model->BSIM4mtrlMod, + model->BSIM4eot, model->BSIM4epsrsub, model->BSIM4epsrox, + model->BSIM4toxe, model->BSIM4factor1, model->BSIM4tnom, + model->BSIM4coxe, model->BSIM4tempMod, model->BSIM4epsrgate, + model->BSIM4mtrlCompatMod, model->BSIM4phig, model->BSIM4easub, + model->BSIM4Eg0, model->BSIM4mobMod, model->BSIM4lambdaGiven, + model->BSIM4lambda, model->BSIM4toxp, model->BSIM4bdos, + model->BSIM4ados, model->BSIM4coxp, model->BSIM4pditsl, + model->BSIM4vtlGiven, model->BSIM4vtl, model->BSIM4gidlMod, + model->BSIM4pigcdGiven, model->BSIM4tnoiMod, model->BSIM4xpart, + model->BSIM4capMod, model->BSIM4cvchargeMod, + model->BSIM4DunitAreaTempJctCap, model->BSIM4SunitAreaTempJctCap, + model->BSIM4DunitLengthSidewallTempJctCap, + model->BSIM4DunitLengthGateSidewallTempJctCap, + model->BSIM4SunitLengthSidewallTempJctCap, + model->BSIM4SunitLengthGateSidewallTempJctCap, + model->BSIM4SbulkJctBotGradingCoeff, + model->BSIM4SbulkJctSideGradingCoeff, + model->BSIM4SbulkJctGateSideGradingCoeff, + model->BSIM4DbulkJctBotGradingCoeff, + model->BSIM4DbulkJctSideGradingCoeff, + model->BSIM4DbulkJctGateSideGradingCoeff, + model->BSIM4PhiBS, model->BSIM4PhiBSWS, model->BSIM4PhiBSWGS, + model->BSIM4PhiBD, model->BSIM4PhiBSWD, model->BSIM4PhiBSWGD, + 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 BSIM4 Model\n\n") ; + return (E_NOMEM) ; + } + + i++ ; + } + + cudaDeviceSynchronize () ; + + /* Deallocation */ + for (i = 0 ; i < 2 ; i++) + cudaStreamDestroy (stream [i]) ; + + return (OK) ; +} + +extern "C" +__global__ +void +cuBSIM4load_kernel +( +BSIM4paramGPUstruct BSIM4entry, 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 BSIM4type, int BSIM4rdsMod, int BSIM4igcMod, int BSIM4igbMod, double BSIM4vcrit, double BSIM4vtm, +double BSIM4vtm0, double BSIM4SjctEmissionCoeff, double BSIM4SjctTempSatCurDensity, +double BSIM4SjctSidewallTempSatCurDensity, double BSIM4SjctGateSidewallTempSatCurDensity, double BSIM4xjbvs, +double BSIM4bvs, int BSIM4dioMod, double BSIM4DjctEmissionCoeff, double BSIM4DjctTempSatCurDensity, +double BSIM4DjctSidewallTempSatCurDensity, double BSIM4DjctGateSidewallTempSatCurDensity, double BSIM4xjbvd, +double BSIM4bvd, double BSIM4njtsswstemp, double BSIM4njtsswgstemp, double BSIM4njtsstemp, +double BSIM4njtsswdtemp, double BSIM4njtsswgdtemp, double BSIM4njtsdtemp, double BSIM4vtss, +double BSIM4vtsd, double BSIM4vtssws, double BSIM4vtsswd, double BSIM4vtsswgs, double BSIM4vtsswgd, +double BSIM4mtrlMod, double BSIM4eot, double BSIM4epsrsub, double BSIM4epsrox, double BSIM4toxe, +double BSIM4factor1, double BSIM4tnom, double BSIM4coxe, double BSIM4tempMod, double BSIM4epsrgate, +double BSIM4mtrlCompatMod, double BSIM4phig, double BSIM4easub, double BSIM4Eg0, int BSIM4mobMod, +int BSIM4lambdaGiven, double BSIM4lambda, double BSIM4toxp, double BSIM4bdos, double BSIM4ados, +double BSIM4coxp, double BSIM4pditsl, int BSIM4vtlGiven, double BSIM4vtl, int BSIM4gidlMod, +int BSIM4pigcdGiven, int BSIM4tnoiMod, double BSIM4xpart, int BSIM4capMod, int BSIM4cvchargeMod, +double BSIM4DunitAreaTempJctCap, double BSIM4SunitAreaTempJctCap, double BSIM4DunitLengthSidewallTempJctCap, +double BSIM4DunitLengthGateSidewallTempJctCap, double BSIM4SunitLengthSidewallTempJctCap, +double BSIM4SunitLengthGateSidewallTempJctCap, double BSIM4SbulkJctBotGradingCoeff, +double BSIM4SbulkJctSideGradingCoeff, double BSIM4SbulkJctGateSideGradingCoeff, +double BSIM4DbulkJctBotGradingCoeff, double BSIM4DbulkJctSideGradingCoeff, +double BSIM4DbulkJctGateSideGradingCoeff, double BSIM4PhiBS, double BSIM4PhiBSWS, double BSIM4PhiBSWGS, +double BSIM4PhiBD, double BSIM4PhiBSWD, double BSIM4PhiBSWGD, +/* 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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vgs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + vbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + vges = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + vgms = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + vdbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + vsbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + vses = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + vdes = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + qdef = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] ; + } + else if (CKTmode & MODEINITTRAN) + { + vds = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vgs = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + vbs = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + vges = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + vgms = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + vdbs = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + vsbs = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + vses = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + vdes = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + qdef = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] ; + } + else if ((CKTmode & MODEINITJCT) && !BSIM4entry.d_BSIM4offArray [instance_ID]) + { + vds = BSIM4type * BSIM4entry.d_BSIM4icVDSArray [instance_ID] ; + vgs = vges = vgms = BSIM4type * BSIM4entry.d_BSIM4icVGSArray [instance_ID] ; + vbs = vdbs = vsbs = BSIM4type * BSIM4entry.d_BSIM4icVBSArray [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 = BSIM4type * BSIM4entry.d_BSIM4vth0Array [instance_ID] + 0.1 ; + vbs = vdbs = vsbs = 0.0 ; + } + } + else if ((CKTmode & (MODEINITJCT | MODEINITFIX)) && (BSIM4entry.d_BSIM4offArray [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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vds = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + vgs = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + vges = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + vgms = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + vbs = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + vdbs = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + vsbs = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + vses = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + vdes = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] = CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] ; + qdef = (1.0 + xfact) * CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] - xfact * CKTstate_2 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] ; + } else { +#endif /* PREDICTOR */ + + vds = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4dNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vgs = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4gNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vbs = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4bNodePrimeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vges = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4gNodeExtArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vgms = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4gNodeMidArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vdbs = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4dbNodeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vsbs = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4sbNodeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vses = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4sNodeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + vdes = BSIM4type * (CKTrhsOld [BSIM4entry.d_BSIM4dNodeArray [instance_ID]] - CKTrhsOld [BSIM4entry.d_BSIM4sNodePrimeArray [instance_ID]]) ; + qdef = BSIM4type * CKTrhsOld [BSIM4entry.d_BSIM4qNodeArray [instance_ID]] ; + +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + + vgdo = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vgedo = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vgmdo = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vbd = vbs - vds ; + vdbd = vdbs - vds ; + vgd = vgs - vds ; + vged = vges - vds ; + vgmd = vgms - vds ; + delvbd = vbd - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]] ; + delvdbd = vdbd - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5] ; + delvgd = vgd - vgdo ; + delvds = vds - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + delvgs = vgs - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + delvges = vges - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + delvgms = vgms - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + delvbs = vbs - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + delvdbs = vdbs - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + delvsbs = vsbs - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + delvses = vses - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + vdedo = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + delvdes = vdes - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + delvded = vdes - vds - vdedo ; + delvbd_jct = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? delvbd : delvdbd ; + delvbs_jct = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? delvbs : delvsbs ; + + /* I DON'T KNOW */ + if (BSIM4entry.d_BSIM4modeArray [instance_ID] >= 0) + { + Idtot = BSIM4entry.d_BSIM4cdRWArray [instance_ID] + BSIM4entry.d_BSIM4csubRWArray [instance_ID] - BSIM4entry.d_BSIM4cbdRWArray [instance_ID] + BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] ; + cdhat = Idtot - BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * delvbd_jct + + (BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] + BSIM4entry.d_BSIM4gbbsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlbArray [instance_ID]) * delvbs + + (BSIM4entry.d_BSIM4gmRWArray [instance_ID] + BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlgArray [instance_ID]) * delvgs + + (BSIM4entry.d_BSIM4gdsRWArray [instance_ID] + BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4ggidldArray [instance_ID]) * delvds ; + + Ibtot = BSIM4entry.d_BSIM4cbsRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - BSIM4entry.d_BSIM4IgislRWArray [instance_ID] - BSIM4entry.d_BSIM4csubRWArray [instance_ID] ; + cbhat = Ibtot + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * delvbd_jct + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] * delvbs_jct - + (BSIM4entry.d_BSIM4gbbsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlbArray [instance_ID]) * delvbs - + (BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlgArray [instance_ID]) * delvgs - + (BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4ggidldArray [instance_ID] - BSIM4entry.d_BSIM4ggislsArray [instance_ID]) * delvds - + BSIM4entry.d_BSIM4ggislgArray [instance_ID] * delvgd - BSIM4entry.d_BSIM4ggislbArray [instance_ID] * delvbd ; + + Igstot = BSIM4entry.d_BSIM4IgsRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] ; + cgshat = Igstot + (BSIM4entry.d_BSIM4gIgsgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID]) * delvgs + + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] * delvds + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] * delvbs ; + + Igdtot = BSIM4entry.d_BSIM4IgdRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] ; + cgdhat = Igdtot + BSIM4entry.d_BSIM4gIgdgArray [instance_ID] * delvgd + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] * delvgs + + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] * delvds + BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] * delvbs ; + + Igbtot = BSIM4entry.d_BSIM4IgbRWArray [instance_ID] ; + cgbhat = BSIM4entry.d_BSIM4IgbRWArray [instance_ID] + BSIM4entry.d_BSIM4gIgbgArray [instance_ID] * delvgs + BSIM4entry.d_BSIM4gIgbdArray [instance_ID] * + delvds + BSIM4entry.d_BSIM4gIgbbArray [instance_ID] * delvbs ; + } else { + /* bugfix */ + Idtot = BSIM4entry.d_BSIM4cdRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] ; + /* ------ */ + + cdhat = Idtot + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * delvbd_jct + BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] * delvbd + + BSIM4entry.d_BSIM4gmRWArray [instance_ID] * delvgd - (BSIM4entry.d_BSIM4gdsRWArray [instance_ID] + BSIM4entry.d_BSIM4ggidlsArray [instance_ID]) * delvds - + BSIM4entry.d_BSIM4ggidlgArray [instance_ID] * delvgs - BSIM4entry.d_BSIM4ggidlbArray [instance_ID] * delvbs ; + + Ibtot = BSIM4entry.d_BSIM4cbsRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - BSIM4entry.d_BSIM4IgislRWArray [instance_ID] - BSIM4entry.d_BSIM4csubRWArray [instance_ID] ; + cbhat = Ibtot + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] * delvbs_jct + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * delvbd_jct - + (BSIM4entry.d_BSIM4gbbsArray [instance_ID] + BSIM4entry.d_BSIM4ggislbArray [instance_ID]) * delvbd - + (BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4ggislgArray [instance_ID]) * delvgd + + (BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4ggisldArray [instance_ID] - BSIM4entry.d_BSIM4ggidlsArray [instance_ID]) * delvds - + BSIM4entry.d_BSIM4ggidlgArray [instance_ID] * delvgs - BSIM4entry.d_BSIM4ggidlbArray [instance_ID] * delvbs ; + + Igstot = BSIM4entry.d_BSIM4IgsRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] ; + cgshat = Igstot + BSIM4entry.d_BSIM4gIgsgArray [instance_ID] * delvgs + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] * delvgd - + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] * delvds + BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] * delvbd ; + + Igdtot = BSIM4entry.d_BSIM4IgdRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] ; + cgdhat = Igdtot + (BSIM4entry.d_BSIM4gIgdgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID]) * delvgd - + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] * delvds + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] * delvbd ; + + Igbtot = BSIM4entry.d_BSIM4IgbRWArray [instance_ID] ; + cgbhat = BSIM4entry.d_BSIM4IgbRWArray [instance_ID] + BSIM4entry.d_BSIM4gIgbgArray [instance_ID] * delvgd - BSIM4entry.d_BSIM4gIgbdArray [instance_ID] * delvds + + BSIM4entry.d_BSIM4gIgbbArray [instance_ID] * delvbd ; + } + + Isestot = BSIM4entry.d_BSIM4gstotArray [instance_ID] * CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + cseshat = Isestot + BSIM4entry.d_BSIM4gstotArray [instance_ID] * delvses + BSIM4entry.d_BSIM4gstotdArray [instance_ID] * delvds + + BSIM4entry.d_BSIM4gstotgArray [instance_ID] * delvgs + BSIM4entry.d_BSIM4gstotbArray [instance_ID] * delvbs ; + + Idedtot = BSIM4entry.d_BSIM4gdtotArray [instance_ID] * vdedo ; + cdedhat = Idedtot + BSIM4entry.d_BSIM4gdtotArray [instance_ID] * delvded + BSIM4entry.d_BSIM4gdtotdArray [instance_ID] * delvds + + BSIM4entry.d_BSIM4gdtotgArray [instance_ID] * delvgs + BSIM4entry.d_BSIM4gdtotbArray [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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3])) + CKTvoltTol))) + if ((fabs (delvgs) < (CKTrelTol * MAX(fabs (vgs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2])) + + CKTvoltTol))) + if ((fabs (delvbs) < (CKTrelTol * MAX (fabs (vbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1])) + + CKTvoltTol))) + if ((fabs (delvbd) < (CKTrelTol * MAX (fabs (vbd), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]])) + + CKTvoltTol))) + if ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 0) || (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 1) || + (fabs (delvges) < (CKTrelTol * MAX (fabs (vges), + fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7])) + CKTvoltTol))) + if ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] != 3) || (fabs (delvgms) < (CKTrelTol * + MAX (fabs (vgms), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8])) + CKTvoltTol))) + if ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvdbs) < (CKTrelTol * + MAX (fabs (vdbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4])) + CKTvoltTol))) + if ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvdbd) < (CKTrelTol * + MAX (fabs (vdbd), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5])) + CKTvoltTol))) + if ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvsbs) < (CKTrelTol * + MAX (fabs (vsbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6])) + + CKTvoltTol))) + if ((!BSIM4rdsMod) || (fabs (delvses) < (CKTrelTol * + MAX (fabs (vses), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9])) + + CKTvoltTol))) + if ((!BSIM4rdsMod) || (fabs (delvdes) < (CKTrelTol * + MAX (fabs (vdes), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [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 ((!BSIM4igcMod) || ((fabs (cgshat - Igstot) + < CKTrelTol * MAX (fabs (cgshat), + fabs (Igstot)) + CKTabsTol))) + if ((!BSIM4igcMod) || ((fabs (cgdhat - + Igdtot) < CKTrelTol * MAX (fabs + (cgdhat), fabs (Igdtot)) + CKTabsTol))) + if ((!BSIM4igbMod) || ((fabs (cgbhat - + Igbtot) < CKTrelTol * MAX + (fabs (cgbhat), fabs (Igbtot)) + + CKTabsTol))) + if ((!BSIM4rdsMod) || + ((fabs (cseshat - Isestot) < + CKTrelTol * MAX (fabs (cseshat), + fabs (Isestot)) + CKTabsTol))) + if ((!BSIM4rdsMod) || + ((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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3])) + CKTvoltTol))) + && ((fabs (delvgs) < (CKTrelTol * MAX(fabs (vgs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2])) + CKTvoltTol))) + && ((fabs (delvbs) < (CKTrelTol * MAX (fabs (vbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1])) +CKTvoltTol))) + && ((fabs (delvbd) < (CKTrelTol * MAX (fabs (vbd), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]])) + CKTvoltTol))) + && ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 0) || (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 1) || (fabs (delvges) < (CKTrelTol * + MAX (fabs (vges), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7])) + CKTvoltTol))) + && ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] != 3) || (fabs (delvgms) < (CKTrelTol * + MAX (fabs (vgms), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8])) + CKTvoltTol))) + && ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvdbs) < (CKTrelTol * + MAX (fabs (vdbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4])) + CKTvoltTol))) + && ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvdbd) < (CKTrelTol * + MAX (fabs (vdbd), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5])) + CKTvoltTol))) + && ((!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) || (fabs (delvsbs) < (CKTrelTol * + MAX (fabs (vsbs), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6])) + CKTvoltTol))) + && ((!BSIM4rdsMod) || (fabs (delvses) < (CKTrelTol * + MAX (fabs (vses), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9])) + CKTvoltTol))) + && ((!BSIM4rdsMod) || (fabs (delvdes) < (CKTrelTol * + MAX (fabs (vdes), fabs (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10])) + CKTvoltTol))) + && ((fabs (cdhat - Idtot) < CKTrelTol * MAX (fabs (cdhat), fabs (Idtot)) + CKTabsTol)) + && ((fabs (cbhat - Ibtot) < CKTrelTol * MAX (fabs (cbhat), fabs (Ibtot)) + CKTabsTol)) + && ((!BSIM4igcMod) || ((fabs (cgshat - Igstot) < CKTrelTol * + MAX (fabs (cgshat), fabs (Igstot)) + CKTabsTol))) + && ((!BSIM4igcMod) || ((fabs (cgdhat - Igdtot) < CKTrelTol * + MAX (fabs (cgdhat), fabs (Igdtot)) + CKTabsTol))) + && ((!BSIM4igbMod) || ((fabs (cgbhat - Igbtot) < CKTrelTol * + MAX (fabs (cgbhat), fabs (Igbtot)) + CKTabsTol))) + && ((!BSIM4rdsMod) || ((fabs (cseshat - Isestot) < CKTrelTol * + MAX (fabs (cseshat), fabs (Isestot)) + CKTabsTol))) + && ((!BSIM4rdsMod) || ((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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vgs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] ; + vbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] ; + vges = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] ; + vgms = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] ; + + vbd = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]] ; + vdbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] ; + vdbd = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5] ; + vsbs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] ; + vses = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] ; + vdes = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] ; + + vgd = vgs - vds ; + vgb = vgs - vbs ; + vged = vges - vds ; + vgmd = vgms - vds ; + vgmb = vgms - vbs ; + + vbs_jct = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? vbs : vsbs ; + vbd_jct = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? vbd : vdbd ; + +/*** qdef should not be kept fixed even if vgs, vds & vbs has converged +**** qdef = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] ; +***/ + cdrain = BSIM4entry.d_BSIM4cdRWArray [instance_ID] ; + + if ((CKTmode & (MODETRAN | MODEAC)) || ((CKTmode & MODETRANOP) && (CKTmode & MODEUIC))) + { + ByPass = 1 ; + + qgate = BSIM4entry.d_BSIM4qgateRWArray [instance_ID] ; + qbulk = BSIM4entry.d_BSIM4qbulkRWArray [instance_ID] ; + qdrn = BSIM4entry.d_BSIM4qdrnRWArray [instance_ID] ; + cgdo = BSIM4entry.d_BSIM4cgdoArray [instance_ID] ; + qgdo = BSIM4entry.d_BSIM4qgdoArray [instance_ID] ; + cgso = BSIM4entry.d_BSIM4cgsoArray [instance_ID] ; + qgso = BSIM4entry.d_BSIM4qgsoArray [instance_ID] ; + + /* Unconditional jump */ + goto line755 ; + } else { + /* Unconditional jump */ + goto line850 ; + } + } +#endif /*NOBYPASS*/ + + von = BSIM4entry.d_BSIM4vonRWArray [instance_ID] ; + + /* 4 - DIVERGENT - CRITICAL */ + if (CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] >= 0.0) + { + vgs = DEVfetlim (vgs, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2], von) ; + vds = vgs - vgd ; + vds = DEVlimvds (vds, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3]) ; + vgd = vgs - vds ; + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + vges = DEVfetlim (vges, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7], von) ; + vgms = DEVfetlim (vgms, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8], von) ; + vged = vges - vds ; + vgmd = vgms - vds ; + } + else if ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 1) || (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2)) + { + vges = DEVfetlim (vges, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7], von) ; + vged = vges - vds ; + } + + if (BSIM4rdsMod) + { + vdes = DEVlimvds (vdes, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10]) ; + vses = -DEVlimvds (-vses, -(CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9])) ; + } + + } else { + vgd = DEVfetlim (vgd, vgdo, von) ; + vds = vgs - vgd ; + vds = -DEVlimvds (-vds, -(CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3])) ; + vgs = vgd + vds ; + + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + vged = DEVfetlim (vged, vgedo, von) ; + vges = vged + vds ; + vgmd = DEVfetlim (vgmd, vgmdo, von) ; + vgms = vgmd + vds ; + } + if ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 1) || (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2)) + { + vged = DEVfetlim (vged, vgedo, von) ; + vges = vged + vds ; + } + + if (BSIM4rdsMod) + { + vdes = -DEVlimvds (-vdes, -(CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10])) ; + vses = DEVlimvds (vses, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9]) ; + } + } + + /* 5 - DIVERGENT - CRITICAL */ + if (vds >= 0.0) + { + vbs = DEVpnjlim (vbs, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1], CONSTvt0, BSIM4vcrit, &Check) ; + vbd = vbs - vds ; + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + vdbs = DEVpnjlim (vdbs, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4], CONSTvt0, BSIM4vcrit, &Check1) ; + vdbd = vdbs - vds ; + vsbs = DEVpnjlim (vsbs, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6], CONSTvt0, BSIM4vcrit, &Check2) ; + + if ((Check1 == 0) && (Check2 == 0)) + Check = 0 ; + else + Check = 1 ; + } + } else { + vbd = DEVpnjlim (vbd, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]], CONSTvt0, BSIM4vcrit, &Check) ; + vbs = vbd + vds ; + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + vdbd = DEVpnjlim (vdbd, CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5], CONSTvt0, BSIM4vcrit, &Check1) ; + vdbs = vdbd + vds ; + vsbdo = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] ; + vsbd = vsbs - vds ; + vsbd = DEVpnjlim (vsbd, vsbdo, CONSTvt0, BSIM4vcrit, &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 = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? vbs : vsbs ; + vbd_jct = (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) ? vbd : vdbd ; + + + /* Source/drain junction diode DC model begins */ + Nvtms = BSIM4vtm * BSIM4SjctEmissionCoeff ; + +/* + if ((BSIM4entry.d_BSIM4AseffArray [instance_ID] <= 0.0) && (BSIM4entry.d_BSIM4PseffArray [instance_ID] <= 0.0)) + SourceSatCurrent = 1.0e-14 ; //v4.7 +*/ + /* POTENTIALLY DIVERGENT */ + if ((BSIM4entry.d_BSIM4AseffArray [instance_ID] <= 0.0) && (BSIM4entry.d_BSIM4PseffArray [instance_ID] <= 0.0)) + { + SourceSatCurrent = 0.0 ; + } else { + SourceSatCurrent = BSIM4entry.d_BSIM4AseffArray [instance_ID] * BSIM4SjctTempSatCurDensity + + BSIM4entry.d_BSIM4PseffArray [instance_ID] * BSIM4SjctSidewallTempSatCurDensity + + pParam->BSIM4weffCJ * BSIM4entry.d_BSIM4nfArray [instance_ID] * BSIM4SjctGateSidewallTempSatCurDensity ; + } + + /* POTENTIALLY DIVERGENT */ + if (SourceSatCurrent <= 0.0) + { + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = BSIM4entry.d_BSIM4gbsRWArray [instance_ID] * vbs_jct ; + } else { + switch (BSIM4dioMod) + { + case 0 : + evbs = exp (vbs_jct / Nvtms) ; + T1 = BSIM4xjbvs * exp (-(BSIM4bvs + vbs_jct) / Nvtms) ; + /* WDLiu: Magic T1 in this form; different from BSIM4 beta. */ + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = SourceSatCurrent * (evbs + T1) / Nvtms + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = SourceSatCurrent * (evbs + BSIM4entry.d_BSIM4XExpBVSArray [instance_ID] - T1 - 1.0) + CKTgmin * vbs_jct ; + break ; + + case 1 : + T2 = vbs_jct / Nvtms ; + if (T2 < -EXP_THRESHOLD) + { + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = SourceSatCurrent * (MIN_EXP - 1.0) + CKTgmin * vbs_jct ; + } + else if (vbs_jct <= BSIM4entry.d_BSIM4vjsmFwdArray [instance_ID]) + { + evbs = exp (T2) ; + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = SourceSatCurrent * evbs / Nvtms + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = SourceSatCurrent * (evbs - 1.0) + CKTgmin * vbs_jct ; + } else { + T0 = BSIM4entry.d_BSIM4IVjsmFwdArray [instance_ID] / Nvtms ; + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = T0 + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = BSIM4entry.d_BSIM4IVjsmFwdArray [instance_ID] - SourceSatCurrent + T0 * + (vbs_jct - BSIM4entry.d_BSIM4vjsmFwdArray [instance_ID]) + CKTgmin * vbs_jct ; + } + break ; + + case 2 : + if (vbs_jct < BSIM4entry.d_BSIM4vjsmRevArray [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 = BSIM4entry.d_BSIM4IVjsmRevArray [instance_ID] + BSIM4entry.d_BSIM4SslpRevArray [instance_ID] * (vbs_jct - BSIM4entry.d_BSIM4vjsmRevArray [instance_ID]) ; + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = devbs_dvb * T2 + T1 * BSIM4entry.d_BSIM4SslpRevArray [instance_ID] + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = T1 * T2 + CKTgmin * vbs_jct ; + } + else if (vbs_jct <= BSIM4entry.d_BSIM4vjsmFwdArray [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 = (BSIM4bvs + vbs_jct) / Nvtms ; + if (T1 > EXP_THRESHOLD) + { + T2 = MIN_EXP ; + T3 = 0.0 ; + } + else + { + T2 = exp (-T1) ; + T3 = -T2 /Nvtms ; + } + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = SourceSatCurrent * (devbs_dvb - BSIM4xjbvs * T3) + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = SourceSatCurrent * (evbs + BSIM4entry.d_BSIM4XExpBVSArray [instance_ID] - 1.0 - + BSIM4xjbvs * T2) + CKTgmin * vbs_jct ; + } + else + { + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] = BSIM4entry.d_BSIM4SslpFwdArray [instance_ID] + CKTgmin ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] = BSIM4entry.d_BSIM4IVjsmFwdArray [instance_ID] + BSIM4entry.d_BSIM4SslpFwdArray [instance_ID] * + (vbs_jct - BSIM4entry.d_BSIM4vjsmFwdArray [instance_ID]) + CKTgmin * vbs_jct ; + } + break ; + + default: break ; + } + } + + Nvtmd = BSIM4vtm * BSIM4DjctEmissionCoeff ; +/* + if ((BSIM4entry.d_BSIM4AdeffArray [instance_ID] <= 0.0) && (BSIM4entry.d_BSIM4PdeffArray [instance_ID] <= 0.0)) + DrainSatCurrent = 1.0e-14 ; //v4.7 +*/ + /* POTENTIALLY DIVERGENT */ + if ((BSIM4entry.d_BSIM4AdeffArray [instance_ID] <= 0.0) && (BSIM4entry.d_BSIM4PdeffArray [instance_ID] <= 0.0)) + { + DrainSatCurrent = 0.0 ; + } else { + DrainSatCurrent = BSIM4entry.d_BSIM4AdeffArray [instance_ID] * BSIM4DjctTempSatCurDensity + + BSIM4entry.d_BSIM4PdeffArray [instance_ID] * BSIM4DjctSidewallTempSatCurDensity + + pParam->BSIM4weffCJ * BSIM4entry.d_BSIM4nfArray [instance_ID] * BSIM4DjctGateSidewallTempSatCurDensity ; + } + + /* POTENTIALLY DIVERGENT */ + if (DrainSatCurrent <= 0.0) + { + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * vbd_jct ; + } else { + switch (BSIM4dioMod) + { + case 0 : + evbd = exp (vbd_jct / Nvtmd) ; + T1 = BSIM4xjbvd * exp (-(BSIM4bvd + vbd_jct) / Nvtmd) ; + /* WDLiu: Magic T1 in this form; different from BSIM4 beta. */ + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = DrainSatCurrent * (evbd + T1) / Nvtmd + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = DrainSatCurrent * (evbd + BSIM4entry.d_BSIM4XExpBVDArray [instance_ID] - T1 - 1.0) + CKTgmin * vbd_jct ; + break ; + + case 1 : + T2 = vbd_jct / Nvtmd ; + if (T2 < -EXP_THRESHOLD) + { + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = DrainSatCurrent * (MIN_EXP - 1.0) + CKTgmin * vbd_jct ; + } + else if (vbd_jct <= BSIM4entry.d_BSIM4vjdmFwdArray [instance_ID]) + { + evbd = exp (T2) ; + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = DrainSatCurrent * evbd / Nvtmd + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = DrainSatCurrent * (evbd - 1.0) + CKTgmin * vbd_jct ; + } else { + T0 = BSIM4entry.d_BSIM4IVjdmFwdArray [instance_ID] / Nvtmd ; + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = T0 + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = BSIM4entry.d_BSIM4IVjdmFwdArray [instance_ID] - DrainSatCurrent + + T0 * (vbd_jct - BSIM4entry.d_BSIM4vjdmFwdArray [instance_ID]) + CKTgmin * vbd_jct ; + } + break ; + + case 2 : + if (vbd_jct < BSIM4entry.d_BSIM4vjdmRevArray [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 = BSIM4entry.d_BSIM4IVjdmRevArray [instance_ID] + BSIM4entry.d_BSIM4DslpRevArray [instance_ID] * (vbd_jct - BSIM4entry.d_BSIM4vjdmRevArray [instance_ID]) ; + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = devbd_dvb * T2 + T1 * BSIM4entry.d_BSIM4DslpRevArray [instance_ID] + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = T1 * T2 + CKTgmin * vbd_jct ; + } + else if (vbd_jct <= BSIM4entry.d_BSIM4vjdmFwdArray [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 = (BSIM4bvd + vbd_jct) / Nvtmd ; + if (T1 > EXP_THRESHOLD) + { + T2 = MIN_EXP ; + T3 = 0.0 ; + } + else + { + T2 = exp (-T1) ; + T3 = -T2 /Nvtmd ; + } + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = DrainSatCurrent * (devbd_dvb - BSIM4xjbvd * T3) + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = DrainSatCurrent * (evbd + BSIM4entry.d_BSIM4XExpBVDArray [instance_ID] - 1.0 - + BSIM4xjbvd * T2) + CKTgmin * vbd_jct ; + } + else + { + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] = BSIM4entry.d_BSIM4DslpFwdArray [instance_ID] + CKTgmin ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] = BSIM4entry.d_BSIM4IVjdmFwdArray [instance_ID] + BSIM4entry.d_BSIM4DslpFwdArray [instance_ID] * + (vbd_jct - BSIM4entry.d_BSIM4vjdmFwdArray [instance_ID]) + CKTgmin * vbd_jct ; + } + break ; + + default: break ; + } + } + + + /* trap-assisted tunneling and recombination current for reverse bias */ + Nvtmrssws = BSIM4vtm0 * BSIM4njtsswstemp ; + Nvtmrsswgs = BSIM4vtm0 * BSIM4njtsswgstemp ; + Nvtmrss = BSIM4vtm0 * BSIM4njtsstemp ; + Nvtmrsswd = BSIM4vtm0 * BSIM4njtsswdtemp ; + Nvtmrsswgd = BSIM4vtm0 * BSIM4njtsswgdtemp ; + Nvtmrsd = BSIM4vtm0 * BSIM4njtsdtemp ; + + /* POSSIBLE DIVERGENT */ + if ((BSIM4vtss - vbs_jct) < (BSIM4vtss * 1e-3)) + { + T9 = 1.0e3 ; + T0 = - vbs_jct / Nvtmrss * T9 ; + DEXP (T0, T1, T10) ; + dT1_dVb = T10 / Nvtmrss * T9 ; + } else { + T9 = 1.0 / (BSIM4vtss - vbs_jct) ; + T0 = -vbs_jct / Nvtmrss * BSIM4vtss * T9 ; + dT0_dVb = BSIM4vtss / Nvtmrss * (T9 + vbs_jct * T9 * T9) ; + DEXP (T0, T1, T10) ; + dT1_dVb = T10 * dT0_dVb ; + } + + if ((BSIM4vtsd - vbd_jct) < (BSIM4vtsd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsd * T9 ; + DEXP (T0, T2, T10) ; + dT2_dVb = T10 / Nvtmrsd * T9 ; + } else { + T9 = 1.0 / (BSIM4vtsd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsd * BSIM4vtsd * T9 ; + dT0_dVb = BSIM4vtsd / Nvtmrsd * (T9 + vbd_jct * T9 * T9) ; + DEXP (T0, T2, T10) ; + dT2_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4vtssws - vbs_jct) < (BSIM4vtssws * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbs_jct / Nvtmrssws * T9 ; + DEXP (T0, T3, T10) ; + dT3_dVb = T10 / Nvtmrssws * T9 ; + } else { + T9 = 1.0 / (BSIM4vtssws - vbs_jct) ; + T0 = -vbs_jct / Nvtmrssws * BSIM4vtssws * T9 ; + dT0_dVb = BSIM4vtssws / Nvtmrssws * (T9 + vbs_jct * T9 * T9) ; + DEXP (T0, T3, T10) ; + dT3_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4vtsswd - vbd_jct) < (BSIM4vtsswd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsswd * T9 ; + DEXP (T0, T4, T10) ; + dT4_dVb = T10 / Nvtmrsswd * T9 ; + } else { + T9 = 1.0 / (BSIM4vtsswd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsswd * BSIM4vtsswd * T9 ; + dT0_dVb = BSIM4vtsswd / Nvtmrsswd * (T9 + vbd_jct * T9 * T9) ; + DEXP(T0, T4, T10) ; + dT4_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4vtsswgs - vbs_jct) < (BSIM4vtsswgs * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbs_jct / Nvtmrsswgs * T9 ; + DEXP (T0, T5, T10) ; + dT5_dVb = T10 / Nvtmrsswgs * T9 ; + } else { + T9 = 1.0 / (BSIM4vtsswgs - vbs_jct) ; + T0 = -vbs_jct / Nvtmrsswgs * BSIM4vtsswgs * T9 ; + dT0_dVb = BSIM4vtsswgs / Nvtmrsswgs * (T9 + vbs_jct * T9 * T9) ; + DEXP(T0, T5, T10) ; + dT5_dVb = T10 * dT0_dVb ; + } + + /* POSSIBLE DIVERGENT */ + if ((BSIM4vtsswgd - vbd_jct) < (BSIM4vtsswgd * 1e-3)) + { + T9 = 1.0e3 ; + T0 = -vbd_jct / Nvtmrsswgd * T9 ; + DEXP (T0, T6, T10) ; + dT6_dVb = T10 / Nvtmrsswgd * T9 ; + } else { + T9 = 1.0 / (BSIM4vtsswgd - vbd_jct) ; + T0 = -vbd_jct / Nvtmrsswgd * BSIM4vtsswgd * T9 ; + dT0_dVb = BSIM4vtsswgd / Nvtmrsswgd * (T9 + vbd_jct * T9 * T9) ; + DEXP (T0, T6, T10) ; + dT6_dVb = T10 * dT0_dVb ; + } + + BSIM4entry.d_BSIM4gbsRWArray [instance_ID] += BSIM4entry.d_BSIM4SjctTempRevSatCurArray [instance_ID] * dT1_dVb + BSIM4entry.d_BSIM4SswTempRevSatCurArray [instance_ID] * dT3_dVb + + BSIM4entry.d_BSIM4SswgTempRevSatCurArray [instance_ID] * dT5_dVb ; + BSIM4entry.d_BSIM4cbsRWArray [instance_ID] -= BSIM4entry.d_BSIM4SjctTempRevSatCurArray [instance_ID] * (T1 - 1.0) + BSIM4entry.d_BSIM4SswTempRevSatCurArray [instance_ID] * (T3 - 1.0) + + BSIM4entry.d_BSIM4SswgTempRevSatCurArray [instance_ID] * (T5 - 1.0) ; + BSIM4entry.d_BSIM4gbdRWArray [instance_ID] += BSIM4entry.d_BSIM4DjctTempRevSatCurArray [instance_ID] * dT2_dVb + BSIM4entry.d_BSIM4DswTempRevSatCurArray [instance_ID] * dT4_dVb + + BSIM4entry.d_BSIM4DswgTempRevSatCurArray [instance_ID] * dT6_dVb ; + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] -= BSIM4entry.d_BSIM4DjctTempRevSatCurArray [instance_ID] * (T2 - 1.0) + BSIM4entry.d_BSIM4DswTempRevSatCurArray [instance_ID] * (T4 - 1.0) + + BSIM4entry.d_BSIM4DswgTempRevSatCurArray [instance_ID] * (T6 - 1.0) ; + /* End of diode DC model */ + + + /* 6 - DIVERGENT */ + if (vds >= 0.0) + { + BSIM4entry.d_BSIM4modeArray [instance_ID] = 1 ; + Vds = vds ; + Vbs = vbs ; + + /* WDLiu: for GIDL */ + } else { + BSIM4entry.d_BSIM4modeArray [instance_ID] = -1 ; + Vds = -vds ; + Vbs = vbd ; + } + + + /* 3 - non-divergent */ + /* dunga */ + if (BSIM4mtrlMod) + { + epsrox = 3.9 ; + toxe = BSIM4eot ; + epssub = EPS0 * BSIM4epsrsub ; + } else { + epsrox = BSIM4epsrox ; + toxe = BSIM4toxe ; + epssub = EPSSI ; + } + + + T0 = Vbs - BSIM4entry.d_BSIM4vbscArray [instance_ID] - 0.001 ; + T1 = sqrt (T0 * T0 - 0.004 * BSIM4entry.d_BSIM4vbscArray [instance_ID]) ; + + /* 7 - DIVERGENT */ + if (T0 >= 0.0) + { + Vbseff = BSIM4entry.d_BSIM4vbscArray [instance_ID] + 0.5 * (T0 + T1) ; + dVbseff_dVb = 0.5 * (1.0 + T0 / T1) ; + } else { + T2 = -0.002 / (T1 - T0) ; + Vbseff = BSIM4entry.d_BSIM4vbscArray [instance_ID] * (1.0 + T2) ; + dVbseff_dVb = T2 * BSIM4entry.d_BSIM4vbscArray [instance_ID] / T1 ; + } + + + /* JX: Correction to forward body bias */ + T9 = 0.95 * pParam->BSIM4phi ; + 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->BSIM4phi - Vbseff ; + dPhis_dVb = -1.0 ; + sqrtPhis = sqrt (Phis) ; + dsqrtPhis_dVb = -0.5 / sqrtPhis ; + + Xdep = pParam->BSIM4Xdep0 * sqrtPhis / pParam->BSIM4sqrtPhi ; + dXdep_dVb = (pParam->BSIM4Xdep0 / pParam->BSIM4sqrtPhi) * dsqrtPhis_dVb ; + + Leff = pParam->BSIM4leff ; + Vtm = BSIM4vtm ; + Vtm0 = BSIM4vtm0 ; + + + /* Vth Calculation */ + T3 = sqrt (Xdep) ; + V0 = pParam->BSIM4vbi - pParam->BSIM4phi ; + T0 = pParam->BSIM4dvt2 * Vbseff ; + + /* 8 - DIVERGENT */ + if (T0 >= - 0.5) + { + T1 = 1.0 + T0 ; + T2 = pParam->BSIM4dvt2 ; + } else { + T4 = 1.0 / (3.0 + 8.0 * T0) ; + T1 = (1.0 + 3.0 * T0) * T4 ; + T2 = pParam->BSIM4dvt2 * T4 * T4 ; + } + lt1 = BSIM4factor1 * T3 * T1 ; + dlt1_dVb = BSIM4factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2) ; + T0 = pParam->BSIM4dvt2w * Vbseff ; + + /* 9 - DIVERGENT */ + if (T0 >= - 0.5) + { + T1 = 1.0 + T0 ; + T2 = pParam->BSIM4dvt2w ; + } else { + T4 = 1.0 / (3.0 + 8.0 * T0) ; + T1 = (1.0 + 3.0 * T0) * T4 ; + T2 = pParam->BSIM4dvt2w * T4 * T4 ; + } + ltw = BSIM4factor1 * T3 * T1 ; + dltw_dVb = BSIM4factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2) ; + T0 = pParam->BSIM4dvt1 * 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 ; + } + BSIM4entry.d_BSIM4thetavthArray [instance_ID] = pParam->BSIM4dvt0 * Theta0 ; + Delt_vth = BSIM4entry.d_BSIM4thetavthArray [instance_ID] * V0 ; + dDelt_vth_dVb = pParam->BSIM4dvt0 * dTheta0_dVb * V0 ; + T0 = pParam->BSIM4dvt1w * pParam->BSIM4weff * 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->BSIM4dvt0w * T5 ; + T2 = T0 * V0 ; + dT2_dVb = pParam->BSIM4dvt0w * dT5_dVb * V0 ; + TempRatio = CKTtemp / BSIM4tnom - 1.0 ; + T0 = sqrt (1.0 + pParam->BSIM4lpe0 / Leff) ; + T1 = pParam->BSIM4k1ox * (T0 - 1.0) * pParam->BSIM4sqrtPhi + (pParam->BSIM4kt1 + + pParam->BSIM4kt1l / Leff + pParam->BSIM4kt2 * Vbseff) * TempRatio ; + Vth_NarrowW = toxe * pParam->BSIM4phi / (pParam->BSIM4weff + pParam->BSIM4w0) ; + T3 = BSIM4entry.d_BSIM4eta0Array [instance_ID] + pParam->BSIM4etab * 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->BSIM4theta0vb0 ; + DIBL_Sft = dDIBL_Sft_dVd * Vds ; + Lpe_Vb = sqrt (1.0 + pParam->BSIM4lpeb / Leff) ; + Vth = BSIM4type * BSIM4entry.d_BSIM4vth0Array [instance_ID] + (pParam->BSIM4k1ox * sqrtPhis - pParam->BSIM4k1 * + pParam->BSIM4sqrtPhi) * Lpe_Vb - BSIM4entry.d_BSIM4k2oxArray [instance_ID] * Vbseff - Delt_vth - T2 + + (pParam->BSIM4k3 + pParam->BSIM4k3b * Vbseff) * Vth_NarrowW + T1 - DIBL_Sft ; + dVth_dVb = Lpe_Vb * pParam->BSIM4k1ox * dsqrtPhis_dVb - BSIM4entry.d_BSIM4k2oxArray [instance_ID] - dDelt_vth_dVb - + dT2_dVb + pParam->BSIM4k3b * Vth_NarrowW - pParam->BSIM4etab * Vds * + pParam->BSIM4theta0vb0 * T4 + pParam->BSIM4kt2 * TempRatio ; + dVth_dVd = -dDIBL_Sft_dVd ; + + + /* Calculate n */ + tmp1 = epssub / Xdep ; + BSIM4entry.d_BSIM4nstarArray [instance_ID] = BSIM4vtm / Charge_q * (BSIM4coxe + tmp1 + pParam->BSIM4cit) ; + tmp2 = pParam->BSIM4nfactor * tmp1 ; + tmp3 = pParam->BSIM4cdsc + pParam->BSIM4cdscb * Vbseff + pParam->BSIM4cdscd * Vds ; + tmp4 = (tmp2 + tmp3 * Theta0 + pParam->BSIM4cit) / BSIM4coxe ; + + /* 13 - DIVERGENT */ + if (tmp4 >= -0.5) + { + n = 1.0 + tmp4 ; + dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * + dTheta0_dVb + pParam->BSIM4cdscb * Theta0) / BSIM4coxe ; + dn_dVd = pParam->BSIM4cdscd * Theta0 / BSIM4coxe ; + } 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->BSIM4cdscb * Theta0) / BSIM4coxe * T0 ; + dn_dVd = pParam->BSIM4cdscd * Theta0 / BSIM4coxe * T0 ; + } + + + /* Vth correction for Pocket implant */ + /* 14 - DIVERGENT */ + if (pParam->BSIM4dvtp0 > 0.0) + { + T0 = -pParam->BSIM4dvtp1 * Vds ; + if (T0 < -EXP_THRESHOLD) + { + T2 = MIN_EXP ; + dT2_dVd = 0.0 ; + } + else + { + T2 = exp (T0) ; + dT2_dVd = -pParam->BSIM4dvtp1 * T2 ; + } + T3 = Leff + pParam->BSIM4dvtp0 * (1.0 + T2) ; + dT3_dVd = pParam->BSIM4dvtp0 * dT2_dVd ; + + if (BSIM4tempMod < 2) + { + T4 = Vtm * log (Leff / T3) ; + dT4_dVd = -Vtm * dT3_dVd / T3 ; + } + else + { + T4 = BSIM4vtm0 * log (Leff / T3) ; + dT4_dVd = -BSIM4vtm0 * 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->BSIM4dvtp4 == 0.0) || (pParam->BSIM4dvtp2factor == 0.0)) + { + T0 = 0.0 ; + DITS_Sft2 = 0.0 ; + } else { + T1 = 2.0 * pParam->BSIM4dvtp4 * Vds ; + DEXP (T1, T0, T10) ; + DITS_Sft2 = pParam->BSIM4dvtp2factor * (T0 - 1) / (T0 + 1) ; + dDITS_Sft2_dVd = pParam->BSIM4dvtp2factor * pParam->BSIM4dvtp4 * 4.0 * T10 / ((T0+1) * (T0+1)) ; + Vth -= DITS_Sft2 ; + dVth_dVd -= dDITS_Sft2_dVd ; + } + BSIM4entry.d_BSIM4vonRWArray [instance_ID] = Vth ; + + + /* Poly Gate Si Depletion Effect */ + T0 = BSIM4entry.d_BSIM4vfbArray [instance_ID] + pParam->BSIM4phi; + + /* 16 - DIVERGENT */ + if (BSIM4mtrlMod == 0) + T1 = EPSSI ; + else + T1 = BSIM4epsrgate * EPS0 ; + + BSIM4polyDepletion (T0, pParam->BSIM4ngate, T1, BSIM4coxe, vgs, &vgs_eff, &dvgs_eff_dvg) ; + + BSIM4polyDepletion (T0, pParam->BSIM4ngate, T1, BSIM4coxe, vgd, &vgd_eff, &dvgd_eff_dvg) ; + + /* 17 - DIVERGENT */ + if (BSIM4entry.d_BSIM4modeArray [instance_ID] > 0) + { + Vgs_eff = vgs_eff ; + dVgs_eff_dVg = dvgs_eff_dvg ; + } else { + Vgs_eff = vgd_eff ; + dVgs_eff_dVg = dvgd_eff_dvg ; + } + BSIM4entry.d_BSIM4vgs_effArray [instance_ID] = vgs_eff ; + BSIM4entry.d_BSIM4vgd_effArray [instance_ID] = vgd_eff ; + BSIM4entry.d_BSIM4dvgs_eff_dvgArray [instance_ID] = dvgs_eff_dvg ; + BSIM4entry.d_BSIM4dvgd_eff_dvgArray [instance_ID] = dvgd_eff_dvg ; + Vgst = Vgs_eff - Vth ; + + + /* Calculate Vgsteff */ + T0 = n * Vtm ; + T1 = pParam->BSIM4mstar * Vgst ; + T2 = T1 / T0 ; + + /* 18 - DIVERGENT */ + if (T2 > EXP_THRESHOLD) + { + T10 = T1 ; + dT10_dVg = pParam->BSIM4mstar * dVgs_eff_dVg ; + dT10_dVd = -dVth_dVd * pParam->BSIM4mstar ; + dT10_dVb = -dVth_dVb * pParam->BSIM4mstar ; + } + 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->BSIM4mstar * 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->BSIM4voffcbn - (1.0 - pParam->BSIM4mstar) * Vgst ; + T2 = T1 / T0 ; + + /* 19 - DIVERGENT */ + if (T2 < -EXP_THRESHOLD) + { + T3 = BSIM4coxe * MIN_EXP / pParam->BSIM4cdep0 ; + T9 = pParam->BSIM4mstar + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } + else if (T2 > EXP_THRESHOLD) + { + T3 = BSIM4coxe * MAX_EXP / pParam->BSIM4cdep0 ; + T9 = pParam->BSIM4mstar + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } else { + ExpVgst = exp (T2) ; + T3 = BSIM4coxe / pParam->BSIM4cdep0 ; + T4 = T3 * ExpVgst ; + T5 = T1 * T4 / T0 ; + T9 = pParam->BSIM4mstar + n * T4 ; + dT9_dVg = T3 * (pParam->BSIM4mstar - 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 ; + } + BSIM4entry.d_BSIM4VgsteffArray [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->BSIM4sqrtPhi; + Weff = pParam->BSIM4weff - 2.0 * (pParam->BSIM4dwg * Vgsteff + pParam->BSIM4dwb * T9) ; + dWeff_dVg = -2.0 * pParam->BSIM4dwg ; + dWeff_dVb = -2.0 * pParam->BSIM4dwb * 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 (BSIM4rdsMod == 1) + Rds = dRds_dVg = dRds_dVb = 0.0 ; + else + { + T0 = 1.0 + pParam->BSIM4prwg * Vgsteff ; + dT0_dVg = -pParam->BSIM4prwg / T0 / T0 ; + T1 = pParam->BSIM4prwb * T9 ; + dT1_dVb = pParam->BSIM4prwb * 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->BSIM4rds0 * 0.5 ; + Rds = pParam->BSIM4rdswmin + T3 * T4 ; + dRds_dVg = T4 * dT3_dVg ; + dRds_dVb = T4 * dT3_dVb ; + + if (Rds > 0.0) + BSIM4entry.d_BSIM4grdswArray [instance_ID] = 1.0 / Rds* BSIM4entry.d_BSIM4nfArray [instance_ID] ; /*4.6.2*/ + else + BSIM4entry.d_BSIM4grdswArray [instance_ID] = 0.0 ; + } + + + /* Calculate Abulk */ + T9 = 0.5 * pParam->BSIM4k1ox * Lpe_Vb / sqrtPhis ; + T1 = T9 + BSIM4entry.d_BSIM4k2oxArray [instance_ID] - pParam->BSIM4k3b * Vth_NarrowW ; + dT1_dVb = -T9 / sqrtPhis * dsqrtPhis_dVb ; + T9 = sqrt (pParam->BSIM4xj * Xdep) ; + tmp1 = Leff + 2.0 * T9 ; + T5 = Leff / tmp1 ; + tmp2 = pParam->BSIM4a0 * T5 ; + tmp3 = pParam->BSIM4weff + pParam->BSIM4b1 ; + tmp4 = pParam->BSIM4b0 / 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->BSIM4ags * pParam->BSIM4a0 * 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 ; + } + BSIM4entry.d_BSIM4AbulkArray [instance_ID] = Abulk ; + T2 = pParam->BSIM4keta * Vbseff ; + + /* 24 - DIVERGENT */ + if (T2 >= -0.9) + { + T0 = 1.0 / (1.0 + T2) ; + dT0_dVb = -pParam->BSIM4keta * T0 * T0 ; + } + else + { + T1 = 1.0 / (0.8 + T2) ; + T0 = (17.0 + 20.0 * T2) * T1 ; + dT0_dVb = -pParam->BSIM4keta * 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 (BSIM4mtrlMod && BSIM4mtrlCompatMod == 0) + T14 = 2.0 * BSIM4type * (BSIM4phig - BSIM4easub - 0.5 * BSIM4Eg0 + 0.45) ; + else + T14 = 0.0 ; + + /* 5 - non-divergent */ + if (BSIM4mobMod == 0) + { + T0 = Vgsteff + Vth + Vth - T14 ; + T2 = pParam->BSIM4ua + pParam->BSIM4uc * Vbseff ; + T3 = T0 / toxe ; + T12 = sqrt (Vth * Vth + 0.0001) ; + T9 = 1.0 / (Vgsteff + 2 * T12) ; + T10 = T9 * toxe ; + T8 = pParam->BSIM4ud * T10 * T10 * Vth ; + T6 = T8 * Vth ; + T5 = T3 * (T2 + pParam->BSIM4ub * T3) + T6 ; + T7 = -2.0 * T6 * T9 ; + T11 = T7 * Vth / T12 ; + dDenomi_dVg = (T2 + 2.0 * pParam->BSIM4ub * T3) / toxe ; + T13 = 2.0 * (dDenomi_dVg + T11 + T8) ; + dDenomi_dVd = T13 * dVth_dVd ; + dDenomi_dVb = T13 * dVth_dVb + pParam->BSIM4uc * T3 ; + dDenomi_dVg += T7 ; + } + else if (BSIM4mobMod == 1) + { + T0 = Vgsteff + Vth + Vth - T14 ; + T2 = 1.0 + pParam->BSIM4uc * Vbseff ; + T3 = T0 / toxe ; + T4 = T3 * (pParam->BSIM4ua + pParam->BSIM4ub * T3) ; + T12 = sqrt (Vth * Vth + 0.0001) ; + T9 = 1.0 / (Vgsteff + 2 * T12) ; + T10 = T9 * toxe ; + T8 = pParam->BSIM4ud * T10 * T10 * Vth ; + T6 = T8 * Vth ; + T5 = T4 * T2 + T6 ; + T7 = -2.0 * T6 * T9 ; + T11 = T7 * Vth / T12 ; + dDenomi_dVg = (pParam->BSIM4ua + 2.0 * pParam->BSIM4ub * T3) * T2 / toxe ; + T13 = 2.0 * (dDenomi_dVg + T11 + T8) ; + dDenomi_dVd = T13 * dVth_dVd ; + dDenomi_dVb = T13 * dVth_dVb + pParam->BSIM4uc * T4 ; + dDenomi_dVg += T7 ; + } + else if (BSIM4mobMod == 2) + { + T0 = (Vgsteff + BSIM4entry.d_BSIM4vtfbphi1Array [instance_ID]) / toxe ; + T1 = exp (pParam->BSIM4eu * log (T0)) ; + dT1_dVg = T1 * pParam->BSIM4eu / T0 / toxe ; + T2 = pParam->BSIM4ua + pParam->BSIM4uc * 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->BSIM4ud * 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->BSIM4uc ; + } + + /*high K mobility*/ + else + { + /* univsersal mobility */ + T0 = (Vgsteff + BSIM4entry.d_BSIM4vtfbphi1Array [instance_ID]) * 1.0e-8 / toxe / 6.0 ; + T1 = exp (pParam->BSIM4eu * log (T0)) ; + dT1_dVg = T1 * pParam->BSIM4eu * 1.0e-8 / T0 / toxe / 6.0 ; + T2 = pParam->BSIM4ua + pParam->BSIM4uc * Vbseff ; + + /*Coulombic*/ + VgsteffVth = pParam->BSIM4VgsteffVth ; + T10 = exp (pParam->BSIM4ucs * log (0.5 + 0.5 * Vgsteff / VgsteffVth)) ; + T11 = pParam->BSIM4ud / T10; + dT11_dVg = -0.5 * pParam->BSIM4ucs * T11 / (0.5 + 0.5 * Vgsteff / VgsteffVth) / VgsteffVth ; + dDenomi_dVg = T2 * dT1_dVg + dT11_dVg ; + dDenomi_dVd = 0.0 ; + dDenomi_dVb = T1 * pParam->BSIM4uc ; + 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 ; + } + BSIM4entry.d_BSIM4ueffArray [instance_ID] = ueff = BSIM4entry.d_BSIM4u0tempArray [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 * BSIM4entry.d_BSIM4vsattempArray [instance_ID] * BSIM4coxe ; + WVCoxRds = WVCox * Rds ; + Esat = 2.0 * BSIM4entry.d_BSIM4vsattempArray [instance_ID] / ueff ; + BSIM4entry.d_BSIM4EsatLArray [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->BSIM4a1 ; + if (a1 == 0.0) + { + Lambda = pParam->BSIM4a2 ; + dLambda_dVg = 0.0 ; + } + else if (a1 > 0.0) + { + T0 = 1.0 - pParam->BSIM4a2 ; + T1 = T0 - pParam->BSIM4a1 * Vgsteff - 0.0001 ; + T2 = sqrt (T1 * T1 + 0.0004 * T0) ; + Lambda = pParam->BSIM4a2 + T0 - 0.5 * (T1 + T2) ; + dLambda_dVg = 0.5 * pParam->BSIM4a1 * (1.0 + T1 / T2) ; + } + else + { + T1 = pParam->BSIM4a2 + pParam->BSIM4a1 * Vgsteff - 0.0001 ; + T2 = sqrt (T1 * T1 + 0.0004 * pParam->BSIM4a2) ; + Lambda = 0.5 * (T1 + T2) ; + dLambda_dVg = 0.5 * pParam->BSIM4a1 * (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 ; + } + BSIM4entry.d_BSIM4vdsatRWArray [instance_ID] = Vdsat ; + + + /* Calculate Vdseff */ + T1 = Vdsat - Vds - pParam->BSIM4delta ; + dT1_dVg = dVdsat_dVg ; + dT1_dVd = dVdsat_dVd - 1.0 ; + dT1_dVb = dVdsat_dVb ; + T2 = sqrt (T1 * T1 + 4.0 * pParam->BSIM4delta * Vdsat) ; + T0 = T1 / T2 ; + T9 = 2.0 * pParam->BSIM4delta ; + 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 ; + BSIM4entry.d_BSIM4VdseffArray [instance_ID] = Vdseff ; + + + /* Velocity Overshoot */ + /* 6 - non-divergent */ + if((BSIM4lambdaGiven) && (BSIM4lambda > 0.0)) + { + T1 = Leff * ueff ; + T2 = pParam->BSIM4lambda / 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->BSIM4litl) ; + 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) */ + BSIM4entry.d_BSIM4EsatLArray [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 = BSIM4entry.d_BSIM4vtfbphi2Array [instance_ID] ; + tmp2 = 2.0e8 * BSIM4toxp ; + dT0_dVg = 1.0 / tmp2 ; + T0 = (Vgsteff + tmp1) * dT0_dVg ; + tmp3 = exp (BSIM4bdos * 0.7 * log (T0)) ; + T1 = 1.0 + tmp3 ; + T2 = BSIM4bdos * 0.7 * tmp3 / T0 ; + Tcen = BSIM4ados * 1.9e-9 / T1 ; + dTcen_dVg = -Tcen * T2 * dT0_dVg / T1 ; + Coxeff = epssub * BSIM4coxp / (epssub + BSIM4coxp * Tcen) ; + BSIM4entry.d_BSIM4CoxeffArray [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 ; + BSIM4entry.d_BSIM4AbovVgst2VtmArray [instance_ID] = Abulk / Vgst2Vtm ; + T0 = 1.0 - 0.5 * Vdseff * BSIM4entry.d_BSIM4AbovVgst2VtmArray [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->BSIM4fprout <= 0.0) + { + FP = 1.0 ; + dFP_dVg = 0.0 ; + } + else + { + T9 = pParam->BSIM4fprout * sqrt (Leff) / Vgst2Vtm ; + FP = 1.0 / (1.0 + T9) ; + dFP_dVg = FP * FP * T9 / Vgst2Vtm ; + } + + + /* Calculate VACLM */ + T8 = pParam->BSIM4pvag / 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->BSIM4pclm > 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->BSIM4pclm * pParam->BSIM4litl) ; + 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->BSIM4thetaRout > 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->BSIM4thetaRout ; + 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->BSIM4pdiblb * Vbseff ; + if (T7 >= -0.9) + { + T3 = 1.0 / (1.0 + T7) ; + VADIBL *= T3 ; + dVADIBL_dVg *= T3 ; + dVADIBL_dVb = (dVADIBL_dVb - VADIBL * pParam->BSIM4pdiblb) * 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->BSIM4pdiblb * 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->BSIM4pditsd * Vds ; + + /* 35 - DIVERGENT */ + if (T0 > EXP_THRESHOLD) + { + T1 = MAX_EXP ; + dT1_dVd = 0 ; + } + else + { + T1 = exp (T0) ; + dT1_dVd = T1 * pParam->BSIM4pditsd ; + } + + /* 36 - DIVERGENT */ + if (pParam->BSIM4pdits > MIN_EXP) + { + T2 = 1.0 + BSIM4pditsl * Leff ; + VADITS = (1.0 + T2 * T1) / pParam->BSIM4pdits ; + dVADITS_dVg = VADITS * dFP_dVg ; + dVADITS_dVd = FP * T2 * dT1_dVd / pParam->BSIM4pdits ; + VADITS *= FP ; + } + else + { + VADITS = MAX_EXP ; + dVADITS_dVg = dVADITS_dVd = 0 ; + } + + + /* Calculate VASCBE */ + /* 37 - DIVERGENT */ + if ((pParam->BSIM4pscbe2 > 0.0) && (pParam->BSIM4pscbe1 >= 0.0)) /*4.6.2*/ + { + if (diffVds > pParam->BSIM4pscbe1 * pParam->BSIM4litl / EXP_THRESHOLD) + { + T0 = pParam->BSIM4pscbe1 * pParam->BSIM4litl / diffVds ; + VASCBE = Leff * exp (T0) / pParam->BSIM4pscbe2 ; + 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->BSIM4pscbe2 ; + 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->BSIM4alpha0 + pParam->BSIM4alpha1 * Leff ; + + /* 38 - DIVERGENT */ + if ((tmp <= 0.0) || (pParam->BSIM4beta0 <= 0.0)) + Isub = Gbd = Gbb = Gbg = 0.0 ; + else + { + T2 = tmp / Leff ; + if (diffVds > pParam->BSIM4beta0 / EXP_THRESHOLD) + { + T0 = -pParam->BSIM4beta0 / 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 ; + } + BSIM4entry.d_BSIM4csubRWArray [instance_ID] = Isub ; + BSIM4entry.d_BSIM4gbbsArray [instance_ID] = Gbb ; + BSIM4entry.d_BSIM4gbgsArray [instance_ID] = Gbg ; + BSIM4entry.d_BSIM4gbdsArray [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 ((BSIM4vtlGiven) && (BSIM4vtl > 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->BSIM4vtl * pParam->BSIM4tfactor) ; + + /* 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 ; + } + BSIM4entry.d_BSIM4gdsRWArray [instance_ID] = Gds ; + BSIM4entry.d_BSIM4gmRWArray [instance_ID] = Gm ; + BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] = Gmb ; + BSIM4entry.d_BSIM4IdovVdsArray [instance_ID] = Ids ; + + if (BSIM4entry.d_BSIM4IdovVdsArray [instance_ID] <= 1.0e-9) + BSIM4entry.d_BSIM4IdovVdsArray [instance_ID] = 1.0e-9 ; + + + /* Calculate Rg */ + /* 40 - DIVERGENT */ + if ((BSIM4entry.d_BSIM4rgateModArray [instance_ID] > 1) || (BSIM4entry.d_BSIM4trnqsModArray [instance_ID] != 0) || (BSIM4entry.d_BSIM4acnqsModArray [instance_ID] != 0)) + { + T9 = pParam->BSIM4xrcrg2 * BSIM4vtm ; + 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 ; + BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] = pParam->BSIM4xrcrg1 * ( T0 + Ids) ; + BSIM4entry.d_BSIM4gcrgdArray [instance_ID] = pParam->BSIM4xrcrg1 * (dT0_dVd + tmp1) ; + BSIM4entry.d_BSIM4gcrgbArray [instance_ID] = pParam->BSIM4xrcrg1 * (dT0_dVb + tmp2) * dVbseff_dVb ; + BSIM4entry.d_BSIM4gcrggArray [instance_ID] = pParam->BSIM4xrcrg1 * (dT0_dVg + tmp3) * dVgsteff_dVg ; + if (BSIM4entry.d_BSIM4nfArray [instance_ID] != 1.0) + { + BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gcrggArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gcrgdArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gcrgbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + } + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2) + { + T10 = BSIM4entry.d_BSIM4grgeltdArray [instance_ID] * BSIM4entry.d_BSIM4grgeltdArray [instance_ID] ; + T11 = BSIM4entry.d_BSIM4grgeltdArray [instance_ID] + BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] ; + BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] = BSIM4entry.d_BSIM4grgeltdArray [instance_ID] * BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] / T11 ; + T12 = T10 / T11 / T11 ; + BSIM4entry.d_BSIM4gcrggArray [instance_ID] *= T12 ; + BSIM4entry.d_BSIM4gcrgdArray [instance_ID] *= T12 ; + BSIM4entry.d_BSIM4gcrgbArray [instance_ID] *= T12 ; + } + BSIM4entry.d_BSIM4gcrgsArray [instance_ID] = -(BSIM4entry.d_BSIM4gcrggArray [instance_ID] + BSIM4entry.d_BSIM4gcrgdArray [instance_ID] + BSIM4entry.d_BSIM4gcrgbArray [instance_ID]) ; + } + + + /* Calculate bias-dependent external S/D resistance */ + /* 8 - non-divergent */ + if (BSIM4rdsMod) + { + /* Rs(V) */ + T0 = vgs - pParam->BSIM4vfbsd ; + T1 = sqrt (T0 * T0 + 1.0e-4) ; + vgs_eff = 0.5 * (T0 + T1) ; + dvgs_eff_dvg = vgs_eff / T1 ; + T0 = 1.0 + pParam->BSIM4prwg * vgs_eff ; + dT0_dvg = -pParam->BSIM4prwg / T0 / T0 * dvgs_eff_dvg ; + T1 = -pParam->BSIM4prwb * vbs ; + dT1_dvb = -pParam->BSIM4prwb ; + 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->BSIM4rs0 * 0.5 ; + Rs = pParam->BSIM4rswmin + T3 * T4 ; + dRs_dvg = T4 * dT3_dvg ; + dRs_dvb = T4 * dT3_dvb ; + T0 = 1.0 + BSIM4entry.d_BSIM4sourceConductanceArray [instance_ID] * Rs ; + BSIM4entry.d_BSIM4gstotArray [instance_ID] = BSIM4entry.d_BSIM4sourceConductanceArray [instance_ID] / T0 ; + T0 = -BSIM4entry.d_BSIM4gstotArray [instance_ID] * BSIM4entry.d_BSIM4gstotArray [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->BSIM4vfbsd ; + T1 = sqrt (T0 * T0 + 1.0e-4) ; + vgd_eff = 0.5 * (T0 + T1) ; + dvgd_eff_dvg = vgd_eff / T1 ; + T0 = 1.0 + pParam->BSIM4prwg * vgd_eff ; + dT0_dvg = -pParam->BSIM4prwg / T0 / T0 * dvgd_eff_dvg ; + T1 = -pParam->BSIM4prwb * vbd ; + dT1_dvb = -pParam->BSIM4prwb ; + 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->BSIM4rd0 * 0.5 ; + Rd = pParam->BSIM4rdwmin + T3 * T4 ; + dRd_dvg = T4 * dT3_dvg ; + dRd_dvb = T4 * dT3_dvb ; + T0 = 1.0 + BSIM4entry.d_BSIM4drainConductanceArray [instance_ID] * Rd ; + BSIM4entry.d_BSIM4gdtotArray [instance_ID] = BSIM4entry.d_BSIM4drainConductanceArray [instance_ID] / T0 ; + T0 = -BSIM4entry.d_BSIM4gdtotArray [instance_ID] * BSIM4entry.d_BSIM4gdtotArray [instance_ID] ; + dgdtot_dvs = 0.0 ; + dgdtot_dvg = T0 * dRd_dvg ; + dgdtot_dvb = T0 * dRd_dvb ; + dgdtot_dvd = -(dgdtot_dvg + dgdtot_dvb + dgdtot_dvs) ; + BSIM4entry.d_BSIM4gstotdArray [instance_ID] = vses * dgstot_dvd ; + BSIM4entry.d_BSIM4gstotgArray [instance_ID] = vses * dgstot_dvg ; + BSIM4entry.d_BSIM4gstotsArray [instance_ID] = vses * dgstot_dvs ; + BSIM4entry.d_BSIM4gstotbArray [instance_ID] = vses * dgstot_dvb ; + T2 = vdes - vds ; + BSIM4entry.d_BSIM4gdtotdArray [instance_ID] = T2 * dgdtot_dvd ; + BSIM4entry.d_BSIM4gdtotgArray [instance_ID] = T2 * dgdtot_dvg ; + BSIM4entry.d_BSIM4gdtotsArray [instance_ID] = T2 * dgdtot_dvs ; + BSIM4entry.d_BSIM4gdtotbArray [instance_ID] = T2 * dgdtot_dvb ; + } + else /* WDLiu: for bypass */ + { + BSIM4entry.d_BSIM4gstotArray [instance_ID] = BSIM4entry.d_BSIM4gstotdArray [instance_ID] = BSIM4entry.d_BSIM4gstotgArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4gstotsArray [instance_ID] = BSIM4entry.d_BSIM4gstotbArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4gdtotArray [instance_ID] = BSIM4entry.d_BSIM4gdtotdArray [instance_ID] = BSIM4entry.d_BSIM4gdtotgArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4gdtotsArray [instance_ID] = BSIM4entry.d_BSIM4gdtotbArray [instance_ID] = 0.0 ; + } + + + /* GIDL/GISL Models */ + /* 9 - non-divergent */ + if (BSIM4mtrlMod == 0) + T0 = 3.0 * toxe ; + else + T0 = BSIM4epsrsub * toxe / epsrox ; + + + /* Calculate GIDL current */ + vgs_eff = BSIM4entry.d_BSIM4vgs_effArray [instance_ID] ; + dvgs_eff_dvg = BSIM4entry.d_BSIM4dvgs_eff_dvgArray [instance_ID] ; + vgd_eff = BSIM4entry.d_BSIM4vgd_effArray [instance_ID] ; + dvgd_eff_dvg = BSIM4entry.d_BSIM4dvgd_eff_dvgArray [instance_ID] ; + + /* 10 - non-divergent */ + if (BSIM4gidlMod == 0) + { + /* 11 - non-divergent */ + if (BSIM4mtrlMod == 0) + T1 = (vds - vgs_eff - pParam->BSIM4egidl ) / T0 ; + else + T1 = (vds - vgs_eff - pParam->BSIM4egidl + pParam->BSIM4vfbsd) / T0 ; + + /* 41 - DIVERGENT */ + if ((pParam->BSIM4agidl <= 0.0) || (pParam->BSIM4bgidl <= 0.0) || + (T1 <= 0.0) || (pParam->BSIM4cgidl <= 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->BSIM4bgidl / T1 ; + if (T2 < 100.0) + { + Igidl = pParam->BSIM4agidl * pParam->BSIM4weffCJ * T1 * exp (-T2) ; + T3 = Igidl * (1.0 + T2) / T1 ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } else { + Igidl = pParam->BSIM4agidl * pParam->BSIM4weffCJ * 3.720075976e-44 ; + Ggidld = Igidl * dT1_dVd ; + Ggidlg = Igidl * dT1_dVg ; + Igidl *= T1 ; + } + T4 = vbd * vbd ; + T5 = -vbd * T4 ; + T6 = pParam->BSIM4cgidl + T5 ; + T7 = T5 / T6 ; + T8 = 3.0 * pParam->BSIM4cgidl * T4 / T6 / T6 ; + Ggidld = Ggidld * T7 + Igidl * T8 ; + Ggidlg = Ggidlg * T7 ; + Ggidlb = -Igidl * T8 ; + Igidl *= T7 ; + } + BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] = Igidl ; + BSIM4entry.d_BSIM4ggidldArray [instance_ID] = Ggidld ; + BSIM4entry.d_BSIM4ggidlgArray [instance_ID] = Ggidlg ; + BSIM4entry.d_BSIM4ggidlbArray [instance_ID] = Ggidlb ; + + + /* Calculate GISL current */ + /* 12 - non-divergent */ + if (BSIM4mtrlMod ==0) + T1 = (-vds - vgd_eff - pParam->BSIM4egisl ) / T0 ; + else + T1 = (-vds - vgd_eff - pParam->BSIM4egisl + pParam->BSIM4vfbsd ) / T0 ; + + /* 42 - DIVERGENT */ + if ((pParam->BSIM4agisl <= 0.0) || (pParam->BSIM4bgisl <= 0.0) || + (T1 <= 0.0) || (pParam->BSIM4cgisl <= 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->BSIM4bgisl / T1 ; + if (T2 < 100.0) + { + Igisl = pParam->BSIM4agisl * pParam->BSIM4weffCJ * T1 * exp (-T2) ; + T3 = Igisl * (1.0 + T2) / T1 ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } else { + Igisl = pParam->BSIM4agisl * pParam->BSIM4weffCJ * 3.720075976e-44 ; + Ggisls = Igisl * dT1_dVd ; + Ggislg = Igisl * dT1_dVg ; + Igisl *= T1 ; + } + T4 = vbs * vbs ; + T5 = -vbs * T4 ; + T6 = pParam->BSIM4cgisl + T5 ; + T7 = T5 / T6 ; + T8 = 3.0 * pParam->BSIM4cgisl * T4 / T6 / T6 ; + Ggisls = Ggisls * T7 + Igisl * T8 ; + Ggislg = Ggislg * T7 ; + Ggislb = -Igisl * T8 ; + Igisl *= T7 ; + } + BSIM4entry.d_BSIM4IgislRWArray [instance_ID] = Igisl ; + BSIM4entry.d_BSIM4ggislsArray [instance_ID] = Ggisls ; + BSIM4entry.d_BSIM4ggislgArray [instance_ID] = Ggislg ; + BSIM4entry.d_BSIM4ggislbArray [instance_ID] = Ggislb ; + } else{ /* v4.7 New Gidl/GISL model */ + /* GISL */ + /* 13 - non-divergent */ + if (BSIM4mtrlMod==0) + T1 = (-vds - pParam->BSIM4rgisl * vgd_eff - pParam->BSIM4egisl) / T0 ; + else + T1 = (-vds - pParam->BSIM4rgisl * vgd_eff - pParam->BSIM4egisl + pParam->BSIM4vfbsd) / T0 ; + + /* 43 - DIVERGENT */ + if ((pParam->BSIM4agisl <= 0.0) || (pParam->BSIM4bgisl <= 0.0) || (T1 <= 0.0) || + (pParam->BSIM4cgisl < 0.0)) + { + Igisl = Ggisls = Ggislg = Ggislb = 0.0 ; + } else { + dT1_dVd = 1 / T0 ; + dT1_dVg = - pParam->BSIM4rgisl * dT1_dVd * dvgd_eff_dvg ; + T2 = pParam->BSIM4bgisl / T1 ; + if (T2 < EXPL_THRESHOLD) + { + Igisl = pParam->BSIM4weffCJ * pParam->BSIM4agisl * T1 * exp (-T2) ; + T3 = Igisl / T1 * (T2 + 1) ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } else { + T3 = pParam->BSIM4weffCJ * pParam->BSIM4agisl * MIN_EXPL ; + Igisl = T3 * T1 ; + Ggisls = T3 * dT1_dVd ; + Ggislg = T3 * dT1_dVg ; + } + T4 = vbs - pParam->BSIM4fgisl ; + + if (T4 == 0) + T5 = EXPL_THRESHOLD ; + else + T5 = pParam->BSIM4kgisl / 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 ; + } + BSIM4entry.d_BSIM4IgislRWArray [instance_ID] = Igisl ; + BSIM4entry.d_BSIM4ggislsArray [instance_ID] = Ggisls ; + BSIM4entry.d_BSIM4ggislgArray [instance_ID] = Ggislg ; + BSIM4entry.d_BSIM4ggislbArray [instance_ID] = Ggislb ; + /* End of GISL */ + + /* GIDL */ + /* 14 - non-divergent */ + if (BSIM4mtrlMod == 0) + T1 = (vds - pParam->BSIM4rgidl * vgs_eff - pParam->BSIM4egidl) / T0 ; + else + T1 = (vds - pParam->BSIM4rgidl * vgs_eff - pParam->BSIM4egidl + pParam->BSIM4vfbsd) / T0 ; + + /* 44 - DIVERGENT */ + if ((pParam->BSIM4agidl <= 0.0) || (pParam->BSIM4bgidl <= 0.0) || (T1 <= 0.0) || + (pParam->BSIM4cgidl < 0.0)) + { + Igidl = Ggidld = Ggidlg = Ggidlb = 0.0 ; + } else { + dT1_dVd = 1 / T0 ; + dT1_dVg = - pParam->BSIM4rgidl * dT1_dVd * dvgs_eff_dvg ; + T2 = pParam->BSIM4bgidl / T1 ; + if (T2 < EXPL_THRESHOLD) + { + Igidl = pParam->BSIM4weffCJ * pParam->BSIM4agidl * T1 * exp (-T2) ; + T3 = Igidl / T1 * (T2 + 1) ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } else { + T3 = pParam->BSIM4weffCJ * pParam->BSIM4agidl * MIN_EXPL ; + Igidl = T3 * T1 ; + Ggidld = T3 * dT1_dVd ; + Ggidlg = T3 * dT1_dVg ; + } + T4 = vbd - pParam->BSIM4fgidl ; + + if (T4 == 0) + T5 = EXPL_THRESHOLD ; + else + T5 = pParam->BSIM4kgidl / T4 ; + + if (T5BSIM4k1ox ; + T3 = Vgs_eff - Vfbeff - Vbseff - Vgsteff ; + + /* 45 - DIVERGENT */ + if (pParam->BSIM4k1ox == 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->BSIM4k1ox * (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 (BSIM4tempMod < 2) + tmp = Vtm ; + else /* BSIM4tempMod = 2 , 3*/ + tmp = Vtm0 ; + + /* 17 - non-divergent */ + if (BSIM4igcMod) + { + T0 = tmp * pParam->BSIM4nigc ; + if (BSIM4igcMod == 1) + { + VxNVt = (Vgs_eff - BSIM4type * BSIM4entry.d_BSIM4vth0Array [instance_ID]) / T0 ; + + /* 46 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = Vgs_eff - BSIM4type * BSIM4entry.d_BSIM4vth0Array [instance_ID] ; + dVaux_dVg = dVgs_eff_dVg ; + dVaux_dVd = 0.0 ; + dVaux_dVb = 0.0 ; + } + } + else if (BSIM4igcMod == 2) + { + VxNVt = (Vgs_eff - BSIM4entry.d_BSIM4vonRWArray [instance_ID]) / T0 ; + + /* 47 - DIVERGENT */ + if (VxNVt > EXP_THRESHOLD) + { + Vaux = Vgs_eff - BSIM4entry.d_BSIM4vonRWArray [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 (BSIM4igcMod == 1) + { + dVaux_dVd = 0.0 ; + dVaux_dVb = 0.0 ; + } else if (BSIM4igcMod == 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->BSIM4Aechvb ; + T12 = pParam->BSIM4Bechvb ; + T3 = pParam->BSIM4aigc * pParam->BSIM4cigc - pParam->BSIM4bigc ; + T4 = pParam->BSIM4bigc * pParam->BSIM4cigc ; + T5 = T12 * (pParam->BSIM4aigc + 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 (BSIM4pigcdGiven) + { + Pigcd = pParam->BSIM4pigcd ; + dPigcd_dVg = dPigcd_dVd = dPigcd_dVb = 0.0 ; + } else { + /* T11 = pParam->BSIM4Bechvb * toxe; v4.7 */ + T11 = -pParam->BSIM4Bechvb ; + 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 ; + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] = Igcs ; + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] = dIgcs_dVg ; + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] = dIgcs_dVd ; + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] = dIgcs_dVb * dVbseff_dVb ; + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] = Igcd ; + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] = dIgcd_dVg ; + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] = dIgcd_dVd ; + BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] = dIgcd_dVb * dVbseff_dVb ; + T0 = vgs - (pParam->BSIM4vfbsd + pParam->BSIM4vfbsdoff) ; + 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->BSIM4AechvbEdgeS ; + T12 = pParam->BSIM4BechvbEdge ; + T3 = pParam->BSIM4aigs * pParam->BSIM4cigs - pParam->BSIM4bigs ; + T4 = pParam->BSIM4bigs * pParam->BSIM4cigs ; + T5 = T12 * (pParam->BSIM4aigs + 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->BSIM4vfbsd + pParam->BSIM4vfbsdoff) ; + 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->BSIM4AechvbEdgeD ; + T3 = pParam->BSIM4aigd * pParam->BSIM4cigd - pParam->BSIM4bigd ; + T4 = pParam->BSIM4bigd * pParam->BSIM4cigd ; + T5 = T12 * (pParam->BSIM4aigd + 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 ; + BSIM4entry.d_BSIM4IgsRWArray [instance_ID] = Igs ; + BSIM4entry.d_BSIM4gIgsgArray [instance_ID] = dIgs_dVg ; + BSIM4entry.d_BSIM4gIgssArray [instance_ID] = dIgs_dVs ; + BSIM4entry.d_BSIM4IgdRWArray [instance_ID] = Igd ; + BSIM4entry.d_BSIM4gIgdgArray [instance_ID] = dIgd_dVg ; + BSIM4entry.d_BSIM4gIgddArray [instance_ID] = dIgd_dVd ; + } else { + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] = BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] = BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] = BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] = BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] = BSIM4entry.d_BSIM4gIgcddArray [instance_ID] = BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4IgsRWArray [instance_ID] = BSIM4entry.d_BSIM4gIgsgArray [instance_ID] = BSIM4entry.d_BSIM4gIgssArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4IgdRWArray [instance_ID] = BSIM4entry.d_BSIM4gIgdgArray [instance_ID] = BSIM4entry.d_BSIM4gIgddArray [instance_ID] = 0.0 ; + } + + /* 18 - non-divergent */ + if (BSIM4igbMod) + { + T0 = tmp * pParam->BSIM4nigbacc ; + 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->BSIM4weff * pParam->BSIM4leff * pParam->BSIM4ToxRatio ; + T12 = -7.45669e11 * toxe ; + T3 = pParam->BSIM4aigbacc * pParam->BSIM4cigbacc - pParam->BSIM4bigbacc ; + T4 = pParam->BSIM4bigbacc * pParam->BSIM4cigbacc ; + T5 = T12 * (pParam->BSIM4aigbacc + 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->BSIM4nigbinv ; + T1 = Voxdepinv - pParam->BSIM4eigbinv ; + 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->BSIM4aigbinv * pParam->BSIM4cigbinv - pParam->BSIM4bigbinv ; + T4 = pParam->BSIM4bigbinv * pParam->BSIM4cigbinv ; + T5 = T12 * (pParam->BSIM4aigbinv + 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) ; + BSIM4entry.d_BSIM4IgbRWArray [instance_ID] = Igbinv + Igbacc ; + BSIM4entry.d_BSIM4gIgbgArray [instance_ID] = dIgbinv_dVg + dIgbacc_dVg ; + BSIM4entry.d_BSIM4gIgbdArray [instance_ID] = dIgbinv_dVd ; + BSIM4entry.d_BSIM4gIgbbArray [instance_ID] = (dIgbinv_dVb + dIgbacc_dVb) * dVbseff_dVb ; + } else { + BSIM4entry.d_BSIM4IgbRWArray [instance_ID] = BSIM4entry.d_BSIM4gIgbgArray [instance_ID] = BSIM4entry.d_BSIM4gIgbdArray [instance_ID] = BSIM4entry.d_BSIM4gIgbsArray [instance_ID] = BSIM4entry.d_BSIM4gIgbbArray [instance_ID] = 0.0 ; + } + /* End of Gate current */ + + /* 57 - DIVERGENT */ + if (BSIM4entry.d_BSIM4nfArray [instance_ID] != 1.0) + { + cdrain *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gdsRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gmRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IdovVdsArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gbbsArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gbgsArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gbdsArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4csubRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggidldArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggidlgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggidlbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgislRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggislsArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggislgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4ggislbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgsRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgsgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgssArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgdRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgdgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgddArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4IgbRWArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgbgArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgbdArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + BSIM4entry.d_BSIM4gIgbbArray [instance_ID] *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + } + BSIM4entry.d_BSIM4ggidlsArray [instance_ID] = -(BSIM4entry.d_BSIM4ggidldArray [instance_ID] + BSIM4entry.d_BSIM4ggidlgArray [instance_ID] + BSIM4entry.d_BSIM4ggidlbArray [instance_ID]) ; + BSIM4entry.d_BSIM4ggisldArray [instance_ID] = -(BSIM4entry.d_BSIM4ggislsArray [instance_ID] + BSIM4entry.d_BSIM4ggislgArray [instance_ID] + BSIM4entry.d_BSIM4ggislbArray [instance_ID]) ; + BSIM4entry.d_BSIM4gIgbsArray [instance_ID] = -(BSIM4entry.d_BSIM4gIgbgArray [instance_ID] + BSIM4entry.d_BSIM4gIgbdArray [instance_ID] + BSIM4entry.d_BSIM4gIgbbArray [instance_ID]) ; + BSIM4entry.d_BSIM4gIgcssArray [instance_ID] = -(BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID]) ; + BSIM4entry.d_BSIM4gIgcdsArray [instance_ID] = -(BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] + BSIM4entry.d_BSIM4gIgcdbArray [instance_ID]) ; + BSIM4entry.d_BSIM4cdRWArray [instance_ID] = cdrain ; + + + /* Calculations for noise analysis */ + /* 19 - non-divergent */ + if (BSIM4tnoiMod == 0) + { + Abulk = Abulk0 * pParam->BSIM4abulkCVfactor ; + 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 ; + BSIM4entry.d_BSIM4qinvRWArray [instance_ID] = Coxeff * pParam->BSIM4weffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] * pParam->BSIM4leffCV * + (Vgsteff - 0.5 * T0 + Abulk * T3) ; + } + else if(BSIM4tnoiMod == 2) + BSIM4entry.d_BSIM4noiGd0Array [instance_ID] = BSIM4entry.d_BSIM4nfArray [instance_ID] * beta * Vgsteff / (1.0 + gche * Rds) ; + + + /* BSIM4 C-V begins */ + /* 20 - non-divergent */ + if ((BSIM4xpart < 0) || (!ChargeComputationNeeded)) + { + qgate = qdrn = qsrc = qbulk = 0.0 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4csgbRWArray [instance_ID] = BSIM4entry.d_BSIM4cssbRWArray [instance_ID] = BSIM4entry.d_BSIM4csdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cgbbRWArray [instance_ID] = BSIM4entry.d_BSIM4csbbRWArray [instance_ID] = BSIM4entry.d_BSIM4cdbbRWArray [instance_ID] = BSIM4entry.d_BSIM4cbbbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cqdbArray [instance_ID] = BSIM4entry.d_BSIM4cqsbArray [instance_ID] = BSIM4entry.d_BSIM4cqgbArray [instance_ID] = BSIM4entry.d_BSIM4cqbbArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4gtauRWArray [instance_ID] = 0.0 ; + goto finished ; + } + else if (BSIM4capMod == 0) + { + if (Vbseff < 0.0) + { + VbseffCV = Vbs ; /*4.6.2*/ + dVbseffCV_dVb = 1.0 ; + } else { + VbseffCV = pParam->BSIM4phi - Phis ; + dVbseffCV_dVb = -dPhis_dVb * dVbseff_dVb ; /*4.6.2*/ + } + Vfb = pParam->BSIM4vfbcv ; + Vth = Vfb + pParam->BSIM4phi + pParam->BSIM4k1ox * sqrtPhis ; + Vgst = Vgs_eff - Vth ; + dVth_dVb = pParam->BSIM4k1ox * dsqrtPhis_dVb *dVbseff_dVb ; /*4.6.2*/ + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * pParam->BSIM4leffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] ; + Arg1 = Vgs_eff - VbseffCV - Vfb ; + + /* 59 - DIVERGENT */ + if (Arg1 <= 0.0) + { + qgate = CoxWL * Arg1 ; + qbulk = -qgate ; + qdrn = 0.0 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = CoxWL * dVgs_eff_dVg ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = CoxWL * (dVbseffCV_dVb - dVgs_eff_dVg) ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -CoxWL * dVgs_eff_dVg ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] ; + } /* Arg1 <= 0.0, end of accumulation */ + else if (Vgst <= 0.0) + { + T1 = 0.5 * pParam->BSIM4k1ox ; + T2 = sqrt (T1 * T1 + Arg1) ; + qgate = CoxWL * pParam->BSIM4k1ox * (T2 - T1) ; + qbulk = -qgate ; + qdrn = 0.0 ; + T0 = CoxWL * T1 / T2 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = T0 * dVgs_eff_dVg ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = T0 * (dVbseffCV_dVb - dVgs_eff_dVg) ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -BSIM4entry.d_BSIM4cggbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -BSIM4entry.d_BSIM4cgsbRWArray [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->BSIM4abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4abulkCVfactor * 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 (BSIM4xpart > 0.5) + { /* 0/100 Charge partition model */ + + if (Vdsat <= Vds) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.0 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + T2) ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + T3) ; + BSIM4entry.d_BSIM4cbdbRWArray [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->BSIM4phi - 0.5 * (Vds - T3)) ; + T10 = T4 * T8 ; + qdrn = T4 * T7 ; + qbulk = -(qgate + qdrn + T10) ; + T5 = T3 / T1 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + T11 = -CoxWL * T5 * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + T11 + BSIM4entry.d_BSIM4cgdbRWArray [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) ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = (T7 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg ; + T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = T4 * (3.0 - 6.0 * T2 - 3.0 * T5) ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + T12 + BSIM4entry.d_BSIM4cddbRWArray [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) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + T10) ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + T12) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] + T0) ; + } + } + else if (BSIM4xpart < 0.5) + { /* 40/60 Charge partition model */ + + if (Vds >= Vdsat) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.4 * T2 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + T2) ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + T3 = 0.4 * Two_Third_CoxWL ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = -T3 * dVgs_eff_dVg ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + T4 = T3 * dVth_dVb ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = -(T4 + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + T3) ; + BSIM4entry.d_BSIM4cbdbRWArray [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->BSIM4phi - 0.5 * (Vds - T3)) ; + T5 = T3 / T1 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + tmp = -CoxWL * T5 * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cgdbRWArray [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)) ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = (T7 * dAlphaz_dVg - tmp1 * dVdsat_dVg) * dVgs_eff_dVg ; + T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = T4 * (2.0 - (1.0 / (3.0 * T1 * T1) + 2.0 * tmp) * T6 + T8 * + (6.0 * Vdsat - 2.4 * Vds)) ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + T10 + BSIM4entry.d_BSIM4cddbRWArray [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 - BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] ; /*4.6.2*/ + T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb ; + T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - BSIM4entry.d_BSIM4cddbRWArray [instance_ID] ; + tmp = -(T10 + T11 + T12) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + T12) ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + T10) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] + tmp) ; + } + } else { + /* 50/50 partitioning */ + + if (Vds >= Vdsat) + { + /* saturation region */ + T1 = Vdsat / 3.0 ; + qgate = CoxWL * (Vgs_eff - Vfb - pParam->BSIM4phi - T1) ; + T2 = -Two_Third_CoxWL * Vgst ; + qbulk = -(qgate + T2) ; + qdrn = 0.5 * T2 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg ; + T2 = -One_Third_CoxWL * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + T2) ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = 0.0 ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = -One_Third_CoxWL * dVgs_eff_dVg ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = 0.0 ; + T4 = One_Third_CoxWL * dVth_dVb ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = -(T4 + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] - Two_Third_CoxWL * dVgs_eff_dVg) ; + T3 = -(T2 + Two_Third_CoxWL * dVth_dVb) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + T3) ; + BSIM4entry.d_BSIM4cbdbRWArray [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->BSIM4phi - 0.5 * (Vds - T3)) ; + T5 = T3 / T1 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg ; + tmp = -CoxWL * T5 * dVdsat_dVb ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = CoxWL * (T2 - 0.5 + 0.5 * T5) ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cgdbRWArray [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) ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = (T0 * dVdsat_dVg - T7 * dAlphaz_dVg) * dVgs_eff_dVg ; + T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = T4 * (1.0 - 2.0 * T2 - T5) ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + T12 + BSIM4entry.d_BSIM4cddbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + 2.0 * BSIM4entry.d_BSIM4cdgbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + 2.0 * BSIM4entry.d_BSIM4cddbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + 2.0 * BSIM4entry.d_BSIM4cdsbRWArray [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->BSIM4phi - Phis ; + dVbseffCV_dVb = -dPhis_dVb ; + } + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * pParam->BSIM4leffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] ; + + if (BSIM4cvchargeMod == 0) + { + /* Seperate VgsteffCV with noff and voffcv */ + noff = n * pParam->BSIM4noff ; + dnoff_dVd = pParam->BSIM4noff * dn_dVd ; + dnoff_dVb = pParam->BSIM4noff * dn_dVb ; + T0 = Vtm * noff ; + voffcv = pParam->BSIM4voffcv ; + 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->BSIM4mstarcv * Vgst ; + T2 = T1 / T0 ; + + /* 61 - DIVERGENT */ + if (T2 > EXP_THRESHOLD) + { + T10 = T1 ; + dT10_dVg = pParam->BSIM4mstarcv * dVgs_eff_dVg ; + dT10_dVd = -dVth_dVd * pParam->BSIM4mstarcv ; + dT10_dVb = -dVth_dVb * pParam->BSIM4mstarcv ; + } + 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->BSIM4mstarcv * 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->BSIM4voffcbncv - (1.0 - pParam->BSIM4mstarcv) * Vgst ; + T2 = T1 / T0 ; + + /* 62 - DIVERGENT */ + if (T2 < -EXP_THRESHOLD) + { + T3 = BSIM4coxe * MIN_EXP / pParam->BSIM4cdep0 ; + T9 = pParam->BSIM4mstarcv + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } + else if (T2 > EXP_THRESHOLD) + { + T3 = BSIM4coxe * MAX_EXP / pParam->BSIM4cdep0 ; + T9 = pParam->BSIM4mstarcv + T3 * n ; + dT9_dVg = 0.0 ; + dT9_dVd = dn_dVd * T3 ; + dT9_dVb = dn_dVb * T3 ; + } else { + ExpVgst = exp (T2) ; + T3 = BSIM4coxe / pParam->BSIM4cdep0 ; + T4 = T3 * ExpVgst ; + T5 = T1 * T4 / T0 ; + T9 = pParam->BSIM4mstarcv + n * T4 ; + dT9_dVg = T3 * (pParam->BSIM4mstarcv - 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 (BSIM4capMod == 1) + { + Vfb = BSIM4entry.d_BSIM4vfbzbArray [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->BSIM4k1ox ; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff ; + + /* 63 - DIVERGENT */ + if (pParam->BSIM4k1ox == 0.0) + { + T1 = 0.0 ; + T2 = 0.0 ; + } + else if (T3 < 0.0) + { + T1 = T0 + T3 / pParam->BSIM4k1ox ; + T2 = CoxWL ; + } else { + T1 = sqrt (T0 * T0 + T3) ; + T2 = CoxWL * T0 / T1 ; + } + Qsub0 = CoxWL * pParam->BSIM4k1ox * (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->BSIM4abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4abulkCVfactor * 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 (BSIM4xpart > 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 (BSIM4xpart < 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 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = Cgg ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(Cgg + Cgd + Cgb) ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = Cgd ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = -(Cgg + Cbg + Csg) ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb) ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = -(Cgd + Cbd + Csd) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = Cbg ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(Cbg + Cbd + Cbb) ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = Cbd ; + } + + + /* Charge-Thickness capMod (CTM) begins */ + else if (BSIM4capMod == 2) + { + V3 = BSIM4entry.d_BSIM4vfbzbArray [instance_ID] - Vgs_eff + VbseffCV - DELTA_3 ; + + if (BSIM4entry.d_BSIM4vfbzbArray [instance_ID] <= 0.0) + T0 = sqrt (V3 * V3 - 4.0 * DELTA_3 * BSIM4entry.d_BSIM4vfbzbArray [instance_ID]) ; + else + T0 = sqrt (V3 * V3 + 4.0 * DELTA_3 * BSIM4entry.d_BSIM4vfbzbArray [instance_ID]) ; + + T1 = 0.5 * (1.0 + V3 / T0) ; + Vfbeff = BSIM4entry.d_BSIM4vfbzbArray [instance_ID] - 0.5 * (V3 + T0) ; + dVfbeff_dVg = T1 * dVgs_eff_dVg ; + dVfbeff_dVb = -T1 * dVbseffCV_dVb ; + Cox = BSIM4coxp ; + Tox = 1.0e8 * BSIM4toxp ; + T0 = (Vgs_eff - VbseffCV - BSIM4entry.d_BSIM4vfbzbArray [instance_ID]) / Tox ; + dT0_dVg = dVgs_eff_dVg / Tox ; + dT0_dVb = -dVbseffCV_dVb / Tox ; + tmp = T0 * pParam->BSIM4acde ; + + /* 65 - DIVERGENT */ + if ((-EXP_THRESHOLD < tmp) && (tmp < EXP_THRESHOLD)) + { + Tcen = pParam->BSIM4ldeb * exp (tmp) ; + dTcen_dVg = pParam->BSIM4acde * Tcen ; + dTcen_dVb = dTcen_dVg * dT0_dVb ; + dTcen_dVg *= dT0_dVg ; + } + else if (tmp <= -EXP_THRESHOLD) + { + Tcen = pParam->BSIM4ldeb * MIN_EXP ; + dTcen_dVg = dTcen_dVb = 0.0 ; + } else { + Tcen = pParam->BSIM4ldeb * MAX_EXP ; + dTcen_dVg = dTcen_dVb = 0.0 ; + } + LINK = 1.0e-3 * BSIM4toxp ; + V3 = pParam->BSIM4ldeb - Tcen - LINK ; + V4 = sqrt (V3 * V3 + 4.0 * LINK * pParam->BSIM4ldeb) ; + Tcen = pParam->BSIM4ldeb - 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 / BSIM4coxe ; + Qac0 = CoxWLcen * (Vfbeff - BSIM4entry.d_BSIM4vfbzbArray [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->BSIM4k1ox ; + T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff ; + + /* 66 - DIVERGENT */ + if (pParam->BSIM4k1ox == 0.0) + { + T1 = 0.0 ; + T2 = 0.0 ; + } + else if (T3 < 0.0) + { + T1 = T0 + T3 / pParam->BSIM4k1ox ; + T2 = CoxWLcen ; + } else { + T1 = sqrt (T0 * T0 + T3) ; + T2 = CoxWLcen * T0 / T1 ; + } + Qsub0 = CoxWLcen * pParam->BSIM4k1ox * (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->BSIM4k1ox <= 0.0) + { + Denomi = 0.25 * pParam->BSIM4moin * Vtm ; + T0 = 0.5 * pParam->BSIM4sqrtPhi ; + } else { + Denomi = pParam->BSIM4moin * Vtm * pParam->BSIM4k1ox * pParam->BSIM4k1ox ; + T0 = pParam->BSIM4k1ox * pParam->BSIM4sqrtPhi ; + } + 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 + BSIM4entry.d_BSIM4vtfbphi2Array [instance_ID]) / Tox ; + tmp = exp (BSIM4bdos * 0.7 * log (T0)) ; + T1 = 1.0 + tmp ; + T2 = BSIM4bdos * 0.7 * tmp / (T0 * Tox) ; + Tcen = BSIM4ados * 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 / BSIM4coxe ; + AbulkCV = Abulk0 * pParam->BSIM4abulkCVfactor ; + dAbulkCV_dVb = pParam->BSIM4abulkCVfactor * 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 (BSIM4xpart > 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 (BSIM4xpart < 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 ; + BSIM4entry.d_BSIM4cggbRWArray [instance_ID] = Cgg ; + BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] = -(Cgg + Cgd + Cgb) ; + BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] = Cgd ; + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] = -(Cgg + Cbg + Csg) ; + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb) ; + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] = -(Cgd + Cbd + Csd) ; + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] = Cbg ; + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] = -(Cbg + Cbd + Cbb) ; + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] = Cbd ; + } /* End of CTM */ + } + + BSIM4entry.d_BSIM4csgbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cggbRWArray [instance_ID] - BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4csdbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] - BSIM4entry.d_BSIM4cddbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4cssbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] - BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4cgbbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] - BSIM4entry.d_BSIM4cggbRWArray [instance_ID] - BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4cdbbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cddbRWArray [instance_ID] - BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] - BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4cbbbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4csbbRWArray [instance_ID] = - BSIM4entry.d_BSIM4cgbbRWArray [instance_ID] - BSIM4entry.d_BSIM4cdbbRWArray [instance_ID] - BSIM4entry.d_BSIM4cbbbRWArray [instance_ID] ; + BSIM4entry.d_BSIM4qgateRWArray [instance_ID] = qgate ; + BSIM4entry.d_BSIM4qbulkRWArray [instance_ID] = qbulk ; + BSIM4entry.d_BSIM4qdrnRWArray [instance_ID] = qdrn ; + BSIM4entry.d_BSIM4qsrcRWArray [instance_ID] = -(qgate + qbulk + qdrn) ; + + + /* NQS begins */ + /* 69 - DIVERGENT */ + if ((BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) || (BSIM4entry.d_BSIM4acnqsModArray [instance_ID])) + { + BSIM4entry.d_BSIM4qchqsArray [instance_ID] = qcheq = -(qbulk + qgate) ; + BSIM4entry.d_BSIM4cqgbArray [instance_ID] = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cqdbArray [instance_ID] = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cqsbArray [instance_ID] = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID]) ; + BSIM4entry.d_BSIM4cqbbArray [instance_ID] = -(BSIM4entry.d_BSIM4cqgbArray [instance_ID] + BSIM4entry.d_BSIM4cqdbArray [instance_ID] + BSIM4entry.d_BSIM4cqsbArray [instance_ID]) ; + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] * pParam->BSIM4leffCV ; + T1 = BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] / CoxWL ; /* 1 / tau */ + BSIM4entry.d_BSIM4gtauRWArray [instance_ID] = T1 * ScalingFactor ; + + if (BSIM4entry.d_BSIM4acnqsModArray [instance_ID]) + BSIM4entry.d_BSIM4taunetArray [instance_ID] = 1.0 / T1 ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 23] = qcheq ; + if (CKTmode & MODEINITTRAN) + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 23] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 23] ; + + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4entry.d_BSIM4statesArray [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 = BSIM4DunitAreaTempJctCap * BSIM4entry.d_BSIM4AdeffArray [instance_ID] ; + /* ------- */ + + czbs = BSIM4SunitAreaTempJctCap * BSIM4entry.d_BSIM4AseffArray [instance_ID] ; + czbdsw = BSIM4DunitLengthSidewallTempJctCap * BSIM4entry.d_BSIM4PdeffArray [instance_ID] ; + czbdswg = BSIM4DunitLengthGateSidewallTempJctCap * pParam->BSIM4weffCJ * BSIM4entry.d_BSIM4nfArray [instance_ID] ; + czbssw = BSIM4SunitLengthSidewallTempJctCap * BSIM4entry.d_BSIM4PseffArray [instance_ID] ; + czbsswg = BSIM4SunitLengthGateSidewallTempJctCap * pParam->BSIM4weffCJ * BSIM4entry.d_BSIM4nfArray [instance_ID] ; + MJS = BSIM4SbulkJctBotGradingCoeff ; + MJSWS = BSIM4SbulkJctSideGradingCoeff ; + MJSWGS = BSIM4SbulkJctGateSideGradingCoeff ; + MJD = BSIM4DbulkJctBotGradingCoeff ; + MJSWD = BSIM4DbulkJctSideGradingCoeff ; + MJSWGD = BSIM4DbulkJctGateSideGradingCoeff ; + + + /* Source Bulk Junction */ + /* 70 - DIVERGENT */ + if (vbs_jct == 0.0) + { + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] = 0.0 ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] = czbs + czbssw + czbsswg ; + } + else if (vbs_jct < 0.0) + { + if (czbs > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4PhiBS ; + + if (MJS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJS * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] = BSIM4PhiBS * czbs * (1.0 - arg * sarg) / (1.0 - MJS) ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] = czbs * sarg ; + } else { + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] = 0.0 ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] = 0.0 ; + } + if (czbssw > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4PhiBSWS ; + + if (MJSWS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWS * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] += BSIM4PhiBSWS * czbssw * (1.0 - arg * sarg) / (1.0 - MJSWS) ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] += czbssw * sarg ; + } + if (czbsswg > 0.0) + { + arg = 1.0 - vbs_jct / BSIM4PhiBSWGS ; + + if (MJSWGS == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWGS * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] += BSIM4PhiBSWGS * czbsswg * (1.0 - arg * sarg) / + (1.0 - MJSWGS) ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] += czbsswg * sarg ; + } + } + else + { + T0 = czbs + czbssw + czbsswg ; + T1 = vbs_jct * (czbs * MJS / BSIM4PhiBS + czbssw * MJSWS / BSIM4PhiBSWS + + czbsswg * MJSWGS / BSIM4PhiBSWGS) ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] = vbs_jct * (T0 + 0.5 * T1) ; + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] = T0 + T1 ; + } + + + /* Drain Bulk Junction */ + /* 71 - DIVERGENT */ + if (vbd_jct == 0.0) + { + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] = 0.0 ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] = czbd + czbdsw + czbdswg ; + } + else if (vbd_jct < 0.0) + { + if (czbd > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4PhiBD ; + + if (MJD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJD * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] = BSIM4PhiBD* czbd * (1.0 - arg * sarg) / (1.0 - MJD) ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] = czbd * sarg ; + } + else + { + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] = 0.0 ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] = 0.0 ; + } + if (czbdsw > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4PhiBSWD ; + + if (MJSWD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWD * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] += BSIM4PhiBSWD * czbdsw * (1.0 - arg * sarg) / (1.0 - MJSWD) ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] += czbdsw * sarg ; + } + if (czbdswg > 0.0) + { + arg = 1.0 - vbd_jct / BSIM4PhiBSWGD ; + + if (MJSWGD == 0.5) + sarg = 1.0 / sqrt (arg) ; + else + sarg = exp (-MJSWGD * log (arg)) ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] += BSIM4PhiBSWGD * czbdswg * (1.0 - arg * sarg) / + (1.0 - MJSWGD) ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] += czbdswg * sarg ; + } + } else { + T0 = czbd + czbdsw + czbdswg ; + T1 = vbd_jct * (czbd * MJD / BSIM4PhiBD + czbdsw * MJSWD / BSIM4PhiBSWD + + czbdswg * MJSWGD / BSIM4PhiBSWGD) ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] = vbd_jct * (T0 + 0.5 * T1) ; + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] = T0 + T1 ; + } + } + + + /* check convergence */ + /* 72 - DIVERGENT */ + if ((BSIM4entry.d_BSIM4offArray [instance_ID] == 0) || (!(CKTmode & MODEINITFIX))) + { + if (Check == 1) + { + atomicAdd (d_CKTnoncon, 1) ; + +#ifndef NEWCONV + } else { + + if (BSIM4entry.d_BSIM4modeArray [instance_ID] >= 0) + Idtot = BSIM4entry.d_BSIM4cdRWArray [instance_ID] + BSIM4entry.d_BSIM4csubRWArray [instance_ID] + BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - BSIM4entry.d_BSIM4cbdRWArray [instance_ID] ; + else + Idtot = BSIM4entry.d_BSIM4cdRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4IgidlRWArray [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 = BSIM4entry.d_BSIM4cbsRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - BSIM4entry.d_BSIM4IgislRWArray [instance_ID] - BSIM4entry.d_BSIM4csubRWArray [instance_ID] ; + tol6 = CKTrelTol * MAX (fabs (cbhat), fabs (Ibtot)) + CKTabsTol ; + if (fabs (cbhat - Ibtot) > tol6) + { + atomicAdd (d_CKTnoncon, 1) ; + } + } +#endif /* NEWCONV */ + + } + } + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 3] = vds ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 2] = vgs ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 1] = vbs ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID]] = vbd ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 7] = vges ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 8] = vgms ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 4] = vdbs ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 5] = vdbd ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 6] = vsbs ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 9] = vses ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 10] = vdes ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 27] = qdef ; + + + if (!ChargeComputationNeeded) + goto line850 ; + + /* 73 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + vgdx = vgmd ; + vgsx = vgms ; + } else { + /* For rgateMod == 0, 1 and 2 */ + vgdx = vgd ; + vgsx = vgs ; + } + + if (BSIM4capMod == 0) + { + cgdo = pParam->BSIM4cgdo ; + qgdo = pParam->BSIM4cgdo * vgdx ; + cgso = pParam->BSIM4cgso ; + qgso = pParam->BSIM4cgso * 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->BSIM4weffCV * pParam->BSIM4cgdl ; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4ckappad) ; + cgdo = pParam->BSIM4cgdo + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1) ; + qgdo = (pParam->BSIM4cgdo + T3) * vgdx - T3 * (T2 + 0.5 * pParam->BSIM4ckappad * (T4 - 1.0)) ; + T0 = vgsx + DELTA_1 ; + T1 = sqrt(T0 * T0 + 4.0 * DELTA_1) ; + T2 = 0.5 * (T0 - T1) ; + T3 = pParam->BSIM4weffCV * pParam->BSIM4cgsl ; + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4ckappas) ; + cgso = pParam->BSIM4cgso + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1) ; + qgso = (pParam->BSIM4cgso + T3) * vgsx - T3 * (T2 + 0.5 * pParam->BSIM4ckappas * (T4 - 1.0)) ; + } + + /* 74 - DIVERGENT */ + if (BSIM4entry.d_BSIM4nfArray [instance_ID] != 1.0) + { + cgdo *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + cgso *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + qgdo *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + qgso *= BSIM4entry.d_BSIM4nfArray [instance_ID] ; + } + BSIM4entry.d_BSIM4cgdoArray [instance_ID] = cgdo ; + BSIM4entry.d_BSIM4qgdoArray [instance_ID] = qgdo ; + BSIM4entry.d_BSIM4cgsoArray [instance_ID] = cgso ; + BSIM4entry.d_BSIM4qgsoArray [instance_ID] = qgso ; + +#ifndef NOBYPASS +line755: +#endif + ag0 = CKTag_0 ; + + /* 75 - DIVERGENT - CRITICAL */ + if (BSIM4entry.d_BSIM4modeArray [instance_ID] > 0) + { + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID] == 0) + { + qdrn -= qgdo ; + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcggb = BSIM4entry.d_BSIM4cggbRWArray [instance_ID] * ag0 ; + gcgdb = BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] * ag0 ; + gcgsb = BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] * ag0 ; + gcsgb = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID]) * ag0 ; + gcbgb = BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] * ag0 ; + qgmb = pParam->BSIM4cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qbulk -= qgmb ; + qsrc = -(qgate + qgmid + qbulk + qdrn) ; + } else { + gcggb = (BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + cgdo + cgso + pParam->BSIM4cgbo ) * ag0 ; + gcgdb = (BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] - cgdo) * ag0 ; + gcgsb = (BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] - cgso) * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = (BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] - cgdo) * ag0 ; + gcsgb = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + cgso) * ag0 ; + gcbgb = (BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] - pParam->BSIM4cgbo) * ag0 ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4cgbo * vgb ; + qgate += qgdo + qgso + qgb ; + qbulk -= qgb ; + qsrc = -(qgate + qbulk + qdrn) ; + } + gcddb = (BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] * ag0 ; + gcsdb = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID]) * ag0 ; + gcssb = (BSIM4entry.d_BSIM4capbsRWArray [instance_ID] + cgso - (BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID])) * ag0 ; + + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) ; + gcbdb = (BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] - BSIM4entry.d_BSIM4capbdRWArray [instance_ID]) * ag0 ; + gcbsb = (BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] - BSIM4entry.d_BSIM4capbsRWArray [instance_ID]) * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = -(BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID]) * ag0 ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] * ag0 ; + gcbdb = BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] * ag0 ; + gcbsb = BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] * ag0 ; + gcdbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4entry.d_BSIM4capbsRWArray [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 = BSIM4entry.d_BSIM4qchqsArray [instance_ID] ; + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] * pParam->BSIM4leffCV ; + T0 = qdef * ScalingFactor / CoxWL ; + ggtg = BSIM4entry.d_BSIM4gtgArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrggArray [instance_ID] ; + ggtd = BSIM4entry.d_BSIM4gtdArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgdArray [instance_ID] ; + ggts = BSIM4entry.d_BSIM4gtsArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgsArray [instance_ID] ; + ggtb = BSIM4entry.d_BSIM4gtbArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgbArray [instance_ID] ; + gqdef = ScalingFactor * ag0 ; + gcqgb = BSIM4entry.d_BSIM4cqgbArray [instance_ID] * ag0 ; + gcqdb = BSIM4entry.d_BSIM4cqdbArray [instance_ID] * ag0 ; + gcqsb = BSIM4entry.d_BSIM4cqsbArray [instance_ID] * ag0 ; + gcqbb = BSIM4entry.d_BSIM4cqbbArray [instance_ID] * ag0 ; + + if (fabs (qcheq) <= 1.0e-5 * CoxWL) + { + + if (BSIM4xpart < 0.5) + dxpart = 0.4 ; + else if (BSIM4xpart > 0.5) + dxpart = 0.0 ; + else + dxpart = 0.5 ; + + ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0 ; + } else { + dxpart = qdrn / qcheq ; + Cdd = BSIM4entry.d_BSIM4cddbRWArray [instance_ID] ; + Csd = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID]) ; + ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq ; + Cdg = BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] ; + Csg = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID]) ; + ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq ; + Cds = BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] ; + Css = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbsbRWArray [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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcdgb = gcsgb = gcbgb = 0.0 ; + gcggb = gcgdb = gcgsb = gcgbb = 0.0 ; + qgmb = pParam->BSIM4cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qgate = 0.0 ; + qbulk = -qgmb ; + qdrn = -qgdo ; + qsrc = -(qgmid + qbulk + qdrn) ; + } else { + gcggb = (cgdo + cgso + pParam->BSIM4cgbo) * ag0 ; + gcgdb = -cgdo * ag0 ; + gcgsb = -cgso * ag0 ; + gcgbb = -pParam->BSIM4cgbo * ag0 ; + gcdgb = gcgdb ; + gcsgb = gcgsb ; + gcbgb = gcgbb ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4cgbo * vgb ; + qgate = qgdo + qgso + qgb ; + qbulk = -qgb ; + qdrn = -qgdo ; + qsrc = -(qgate + qbulk + qdrn) ; + } + gcddb = (BSIM4entry.d_BSIM4capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = gcsdb = 0.0 ; + gcssb = (BSIM4entry.d_BSIM4capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdgmb) ; + gcsbb = -(gcsgb + gcssb + gcsgmb) ; + gcbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcbsb = -BSIM4entry.d_BSIM4capbsRWArray [instance_ID] * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = gcsbb = gcbdb = gcbsb = 0.0 ; + gcdbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4entry.d_BSIM4capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb) ; + } + } else { + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID] == 0) + { + qsrc = qdrn - qgso ; + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcggb = BSIM4entry.d_BSIM4cggbRWArray [instance_ID] * ag0 ; + gcgdb = BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] * ag0 ; + gcgsb = BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID]) * ag0 ; + gcsgb = BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] * ag0 ; + gcbgb = BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] * ag0 ; + qgmb = pParam->BSIM4cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qbulk -= qgmb ; + qdrn = -(qgate + qgmid + qbulk + qsrc) ; + } else { + gcggb = (BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + cgdo + cgso + pParam->BSIM4cgbo ) * ag0 ; + gcgdb = (BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] - cgdo) * ag0 ; + gcgsb = (BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] - cgso) * ag0 ; + gcgbb = -(gcggb + gcgdb + gcgsb) ; + gcdgb = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + cgdo) * ag0 ; + gcsgb = (BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] - cgso) * ag0 ; + gcbgb = (BSIM4entry.d_BSIM4cbgbRWArray [instance_ID] - pParam->BSIM4cgbo) * ag0 ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4cgbo * vgb ; + qgate += qgdo + qgso + qgb ; + qbulk -= qgb ; + qdrn = -(qgate + qbulk + qsrc) ; + } + gcddb = (BSIM4entry.d_BSIM4capbdRWArray [instance_ID] + cgdo - (BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID])) * ag0 ; + gcdsb = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID]) * ag0 ; + gcsdb = BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] * ag0 ; + gcssb = (BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) ; + gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) ; + gcbdb = (BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] - BSIM4entry.d_BSIM4capbdRWArray [instance_ID]) * ag0 ; + gcbsb = (BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] - BSIM4entry.d_BSIM4capbsRWArray [instance_ID]) * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) + BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcsbb = -(BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID]) * ag0 ; + gcbdb = BSIM4entry.d_BSIM4cbsbRWArray [instance_ID] * ag0 ; + gcbsb = BSIM4entry.d_BSIM4cbdbRWArray [instance_ID] * ag0 ; + gcdbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4entry.d_BSIM4capbsRWArray [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 = BSIM4entry.d_BSIM4qchqsArray [instance_ID] ; + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] * pParam->BSIM4leffCV ; + T0 = qdef * ScalingFactor / CoxWL ; + ggtg = BSIM4entry.d_BSIM4gtgArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrggArray [instance_ID] ; + ggts = BSIM4entry.d_BSIM4gtsArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgdArray [instance_ID] ; + ggtd = BSIM4entry.d_BSIM4gtdArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgsArray [instance_ID] ; + ggtb = BSIM4entry.d_BSIM4gtbArray [instance_ID] = T0 * BSIM4entry.d_BSIM4gcrgbArray [instance_ID] ; + gqdef = ScalingFactor * ag0 ; + gcqgb = BSIM4entry.d_BSIM4cqgbArray [instance_ID] * ag0 ; + gcqdb = BSIM4entry.d_BSIM4cqsbArray [instance_ID] * ag0 ; + gcqsb = BSIM4entry.d_BSIM4cqdbArray [instance_ID] * ag0 ; + gcqbb = BSIM4entry.d_BSIM4cqbbArray [instance_ID] * ag0 ; + + if (fabs (qcheq) <= 1.0e-5 * CoxWL) + { + + if (BSIM4xpart < 0.5) + sxpart = 0.4 ; + else if (BSIM4xpart > 0.5) + sxpart = 0.0 ; + else + sxpart = 0.5 ; + + dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0 ; + } else { + sxpart = qdrn / qcheq ; + Css = BSIM4entry.d_BSIM4cddbRWArray [instance_ID] ; + Cds = -(BSIM4entry.d_BSIM4cgdbRWArray [instance_ID] + BSIM4entry.d_BSIM4cddbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbdbRWArray [instance_ID]) ; + dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq ; + Csg = BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] ; + Cdg = -(BSIM4entry.d_BSIM4cggbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdgbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbgbRWArray [instance_ID]) ; + dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq ; + Csd = BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] ; + Cdd = -(BSIM4entry.d_BSIM4cgsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cdsbRWArray [instance_ID] + BSIM4entry.d_BSIM4cbsbRWArray [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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + gcgmgmb = (cgdo + cgso + pParam->BSIM4cgbo) * ag0 ; + gcgmdb = -cgdo * ag0 ; + gcgmsb = -cgso * ag0 ; + gcgmbb = -pParam->BSIM4cgbo * ag0 ; + gcdgmb = gcgmdb ; + gcsgmb = gcgmsb ; + gcbgmb = gcgmbb ; + gcdgb = gcsgb = gcbgb = 0.0 ; + gcggb = gcgdb = gcgsb = gcgbb = 0.0 ; + qgmb = pParam->BSIM4cgbo * vgmb ; + qgmid = qgdo + qgso + qgmb ; + qgate = 0.0 ; + qbulk = -qgmb ; + qdrn = -qgdo ; + qsrc = -qgso ; + } else { + gcggb = (cgdo + cgso + pParam->BSIM4cgbo ) * ag0 ; + gcgdb = -cgdo * ag0 ; + gcgsb = -cgso * ag0 ; + gcgbb = -pParam->BSIM4cgbo * ag0 ; + gcdgb = gcgdb ; + gcsgb = gcgsb ; + gcbgb = gcgbb ; + gcdgmb = gcsgmb = gcbgmb = 0.0 ; + qgb = pParam->BSIM4cgbo * vgb ; + qgate = qgdo + qgso + qgb ; + qbulk = -qgb ; + qdrn = -qgdo ; + qsrc = -qgso ; + } + gcddb = (BSIM4entry.d_BSIM4capbdRWArray [instance_ID] + cgdo) * ag0 ; + gcdsb = gcsdb = 0.0 ; + gcssb = (BSIM4entry.d_BSIM4capbsRWArray [instance_ID] + cgso) * ag0 ; + + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + gcdbb = -(gcdgb + gcddb + gcdgmb) ; + gcsbb = -(gcsgb + gcssb + gcsgmb) ; + gcbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcbsb = -BSIM4entry.d_BSIM4capbsRWArray [instance_ID] * ag0 ; + gcdbdb = 0.0 ; + gcsbsb = 0.0 ; + } else { + gcdbb = gcsbb = gcbdb = gcbsb = 0.0 ; + gcdbdb = -BSIM4entry.d_BSIM4capbdRWArray [instance_ID] * ag0 ; + gcsbsb = -BSIM4entry.d_BSIM4capbsRWArray [instance_ID] * ag0 ; + } + gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb) ; + } + } + + /* 76 - DIVERGENT */ + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 25] = qdef * ScalingFactor ; + + if (CKTmode & MODEINITTRAN) + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 25] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 25] ; + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4entry.d_BSIM4statesArray [instance_ID] + 25, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + } + + if (ByPass) + goto line860 ; + + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 13] = qgate ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 15] = qdrn - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] ; + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 28] = qsrc - CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] ; + + /* 77 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 17] = qgmid ; + + /* 78 - DIVERGENT */ + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 11] = qbulk + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] ; + else + CKTstate_0 [BSIM4entry.d_BSIM4statesArray [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 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 11] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 11] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 13] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 13] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 15] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 15] ; + + /* 79 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 17] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 17] ; + + /* 80 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 19] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 21] ; + } + } + + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4entry.d_BSIM4statesArray [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, + BSIM4entry.d_BSIM4statesArray [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, + BSIM4entry.d_BSIM4statesArray [instance_ID] + 15, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + + /* 81 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4entry.d_BSIM4statesArray [instance_ID] + 17, CKTag_0, CKTag_1, CKTorder) ; + if (error) + printf ("Integration error\n\n") ; + //return (error) ; + } + + /* 82 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + error = cuNIintegrate_device_kernel (CKTstate_0, CKTstate_1, &geq, &ceq, 0.0, + BSIM4entry.d_BSIM4statesArray [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, + BSIM4entry.d_BSIM4statesArray [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 = (BSIM4entry.d_BSIM4modeArray [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 (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + CoxWL = BSIM4coxe * pParam->BSIM4weffCV * BSIM4entry.d_BSIM4nfArray [instance_ID] * pParam->BSIM4leffCV ; + T1 = BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] / CoxWL ; + BSIM4entry.d_BSIM4gtauRWArray [instance_ID] = T1 * ScalingFactor ; + } + else + BSIM4entry.d_BSIM4gtauRWArray [instance_ID] = 0.0 ; + + goto line900 ; + + +line860: + /* Calculate equivalent charge current */ + cqgate = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 14] ; + cqbody = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 12] ; + cqdrn = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + ceqqgmid = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 18] + gcgmdb * vbd + gcgmsb * vbs - gcgmgmb * vgmb ; + else + ceqqgmid = 0.0 ; + + /* 85 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + ceqqjs = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 20] + gcsbsb * vbs_jct ; + ceqqjd = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 22] + gcdbdb * vbd_jct ; + } + + /* 86 - DIVERGENT */ + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + T0 = ggtg * vgb - ggtd * vbd - ggts * vbs ; + ceqqg += T0 ; + T1 = qdef * BSIM4entry.d_BSIM4gtauRWArray [instance_ID] ; + ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd * vbd - ddxpart_dVs * vbs) ; + cqdef = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 26] - gqdef * qdef ; + cqcheq = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 24] - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0 ; + } + + /* 21 - non-divergent */ + if (CKTmode & MODEINITTRAN) + { + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 12] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 12] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 14] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 14] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 16] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 16] ; + + /* 87 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 18] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 18] ; + + /* 88 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 20] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 20] ; + CKTstate_1 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 22] = CKTstate_0 [BSIM4entry.d_BSIM4statesArray [instance_ID] + 22] ; + } + } + + + /* Load current vector */ + /* 89 - DIVERGENT - CRITICAL */ +line900: + if (BSIM4entry.d_BSIM4modeArray [instance_ID] >= 0) + { + Gm = BSIM4entry.d_BSIM4gmRWArray [instance_ID] ; + Gmbs = BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] ; + FwdSum = Gm + Gmbs ; + RevSum = 0.0 ; + ceqdrn = BSIM4type * (cdrain - BSIM4entry.d_BSIM4gdsRWArray [instance_ID] * vds - Gm * vgs - Gmbs * vbs) ; + ceqbd = BSIM4type * (BSIM4entry.d_BSIM4csubRWArray [instance_ID] + BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - + (BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4ggidldArray [instance_ID]) * vds - + (BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlgArray [instance_ID]) * vgs - (BSIM4entry.d_BSIM4gbbsArray [instance_ID] + BSIM4entry.d_BSIM4ggidlbArray [instance_ID]) * vbs) ; + ceqbs = BSIM4type * (BSIM4entry.d_BSIM4IgislRWArray [instance_ID] + BSIM4entry.d_BSIM4ggislsArray [instance_ID] * vds - + BSIM4entry.d_BSIM4ggislgArray [instance_ID] * vgd - BSIM4entry.d_BSIM4ggislbArray [instance_ID] * vbd) ; + gbbdp = -(BSIM4entry.d_BSIM4gbdsArray [instance_ID]) ; + gbbsp = BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4gbbsArray [instance_ID] ; + gbdpg = BSIM4entry.d_BSIM4gbgsArray [instance_ID] ; + gbdpdp = BSIM4entry.d_BSIM4gbdsArray [instance_ID] ; + gbdpb = BSIM4entry.d_BSIM4gbbsArray [instance_ID] ; + gbdpsp = -(gbdpg + gbdpdp + gbdpb) ; + gbspg = 0.0 ; + gbspdp = 0.0 ; + gbspb = 0.0 ; + gbspsp = 0.0 ; + + if (BSIM4igcMod) + { + gIstotg = BSIM4entry.d_BSIM4gIgsgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] ; + gIstotd = BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] ; + gIstots = BSIM4entry.d_BSIM4gIgssArray [instance_ID] + BSIM4entry.d_BSIM4gIgcssArray [instance_ID] ; + gIstotb = BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] ; + Istoteq = BSIM4type * (BSIM4entry.d_BSIM4IgsRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] - gIstotg * vgs - + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] * vds - BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] * vbs) ; + gIdtotg = BSIM4entry.d_BSIM4gIgdgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] ; + gIdtotd = BSIM4entry.d_BSIM4gIgddArray [instance_ID] + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] ; + gIdtots = BSIM4entry.d_BSIM4gIgcdsArray [instance_ID] ; + gIdtotb = BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] ; + Idtoteq = BSIM4type * (BSIM4entry.d_BSIM4IgdRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] - BSIM4entry.d_BSIM4gIgdgArray [instance_ID] * vgd - + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] * vgs - BSIM4entry.d_BSIM4gIgcddArray [instance_ID] * vds - BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] * vbs) ; + } else { + gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0 ; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0 ; + } + + if (BSIM4igbMod) + { + gIbtotg = BSIM4entry.d_BSIM4gIgbgArray [instance_ID] ; + gIbtotd = BSIM4entry.d_BSIM4gIgbdArray [instance_ID] ; + gIbtots = BSIM4entry.d_BSIM4gIgbsArray [instance_ID] ; + gIbtotb = BSIM4entry.d_BSIM4gIgbbArray [instance_ID] ; + Ibtoteq = BSIM4type * (BSIM4entry.d_BSIM4IgbRWArray [instance_ID] - BSIM4entry.d_BSIM4gIgbgArray [instance_ID] * vgs - BSIM4entry.d_BSIM4gIgbdArray [instance_ID] * vds - + BSIM4entry.d_BSIM4gIgbbArray [instance_ID] * vbs) ; + } + else + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0 ; + + if ((BSIM4igcMod != 0) || (BSIM4igbMod != 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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2) + T0 = vges - vgs ; + else if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + T0 = vgms - vgs ; + + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] > 1) + { + gcrgd = BSIM4entry.d_BSIM4gcrgdArray [instance_ID] * T0 ; + gcrgg = BSIM4entry.d_BSIM4gcrggArray [instance_ID] * T0 ; + gcrgs = BSIM4entry.d_BSIM4gcrgsArray [instance_ID] * T0 ; + gcrgb = BSIM4entry.d_BSIM4gcrgbArray [instance_ID] * T0 ; + ceqgcrg = -(gcrgd * vds + gcrgg * vgs + gcrgb * vbs) ; + gcrgg -= BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] ; + gcrg = BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] ; + } + else + ceqgcrg = gcrg = gcrgd = gcrgg = gcrgs = gcrgb = 0.0 ; + } else { + Gm = -BSIM4entry.d_BSIM4gmRWArray [instance_ID] ; + Gmbs = -BSIM4entry.d_BSIM4gmbsRWArray [instance_ID] ; + FwdSum = 0.0 ; + RevSum = -(Gm + Gmbs) ; + ceqdrn = -BSIM4type * (cdrain + BSIM4entry.d_BSIM4gdsRWArray [instance_ID] * vds + Gm * vgd + Gmbs * vbd) ; + ceqbs = BSIM4type * (BSIM4entry.d_BSIM4csubRWArray [instance_ID] + BSIM4entry.d_BSIM4IgislRWArray [instance_ID] + + (BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4ggislsArray [instance_ID]) * vds - + (BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4ggislgArray [instance_ID]) * vgd - (BSIM4entry.d_BSIM4gbbsArray [instance_ID] + BSIM4entry.d_BSIM4ggislbArray [instance_ID]) * vbd) ; + ceqbd = BSIM4type * (BSIM4entry.d_BSIM4IgidlRWArray [instance_ID] - BSIM4entry.d_BSIM4ggidldArray [instance_ID] * vds - BSIM4entry.d_BSIM4ggidlgArray [instance_ID] * vgs - + BSIM4entry.d_BSIM4ggidlbArray [instance_ID] * vbs) ; + gbbsp = -(BSIM4entry.d_BSIM4gbdsArray [instance_ID]) ; + gbbdp = BSIM4entry.d_BSIM4gbdsArray [instance_ID] + BSIM4entry.d_BSIM4gbgsArray [instance_ID] + BSIM4entry.d_BSIM4gbbsArray [instance_ID] ; + gbdpg = 0.0 ; + gbdpsp = 0.0 ; + gbdpb = 0.0 ; + gbdpdp = 0.0 ; + gbspg = BSIM4entry.d_BSIM4gbgsArray [instance_ID] ; + gbspsp = BSIM4entry.d_BSIM4gbdsArray [instance_ID] ; + gbspb = BSIM4entry.d_BSIM4gbbsArray [instance_ID] ; + gbspdp = -(gbspg + gbspsp + gbspb) ; + + if (BSIM4igcMod) + { + gIstotg = BSIM4entry.d_BSIM4gIgsgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] ; + gIstotd = BSIM4entry.d_BSIM4gIgcdsArray [instance_ID] ; + gIstots = BSIM4entry.d_BSIM4gIgssArray [instance_ID] + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] ; + gIstotb = BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] ; + Istoteq = BSIM4type * (BSIM4entry.d_BSIM4IgsRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcdRWArray [instance_ID] - BSIM4entry.d_BSIM4gIgsgArray [instance_ID] * vgs - + BSIM4entry.d_BSIM4gIgcdgArray [instance_ID] * vgd + BSIM4entry.d_BSIM4gIgcddArray [instance_ID] * vds - BSIM4entry.d_BSIM4gIgcdbArray [instance_ID] * vbd) ; + gIdtotg = BSIM4entry.d_BSIM4gIgdgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID] ; + gIdtotd = BSIM4entry.d_BSIM4gIgddArray [instance_ID] + BSIM4entry.d_BSIM4gIgcssArray [instance_ID] ; + gIdtots = BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] ; + gIdtotb = BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] ; + Idtoteq = BSIM4type * (BSIM4entry.d_BSIM4IgdRWArray [instance_ID] + BSIM4entry.d_BSIM4IgcsRWArray [instance_ID] - + (BSIM4entry.d_BSIM4gIgdgArray [instance_ID] + BSIM4entry.d_BSIM4gIgcsgArray [instance_ID]) * vgd + BSIM4entry.d_BSIM4gIgcsdArray [instance_ID] * vds - + BSIM4entry.d_BSIM4gIgcsbArray [instance_ID] * vbd) ; + } else { + gIstotg = gIstotd = gIstots = gIstotb = Istoteq = 0.0 ; + gIdtotg = gIdtotd = gIdtots = gIdtotb = Idtoteq = 0.0 ; + } + + if (BSIM4igbMod) + { + gIbtotg = BSIM4entry.d_BSIM4gIgbgArray [instance_ID] ; + gIbtotd = BSIM4entry.d_BSIM4gIgbsArray [instance_ID] ; + gIbtots = BSIM4entry.d_BSIM4gIgbdArray [instance_ID] ; + gIbtotb = BSIM4entry.d_BSIM4gIgbbArray [instance_ID] ; + Ibtoteq = BSIM4type * (BSIM4entry.d_BSIM4IgbRWArray [instance_ID] - BSIM4entry.d_BSIM4gIgbgArray [instance_ID] * vgd + + BSIM4entry.d_BSIM4gIgbdArray [instance_ID] * vds - BSIM4entry.d_BSIM4gIgbbArray [instance_ID] * vbd) ; + } + else + gIbtotg = gIbtotd = gIbtots = gIbtotb = Ibtoteq = 0.0 ; + + if ((BSIM4igcMod != 0) || (BSIM4igbMod != 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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2) + T0 = vges - vgs ; + else if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + T0 = vgms - vgs ; + + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] > 1) + { + gcrgd = BSIM4entry.d_BSIM4gcrgsArray [instance_ID] * T0 ; + gcrgg = BSIM4entry.d_BSIM4gcrggArray [instance_ID] * T0 ; + gcrgs = BSIM4entry.d_BSIM4gcrgdArray [instance_ID] * T0 ; + gcrgb = BSIM4entry.d_BSIM4gcrgbArray [instance_ID] * T0 ; + ceqgcrg = -(gcrgg * vgd - gcrgs * vds + gcrgb * vbd) ; + gcrgg -= BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] ; + gcrg = BSIM4entry.d_BSIM4gcrgRWArray [instance_ID] ; + } + else + ceqgcrg = gcrg = gcrgd = gcrgg = gcrgs = gcrgb = 0.0 ; + } + + /* 22 - non-divergent */ + if (BSIM4rdsMod == 1) + { + ceqgstot = BSIM4type * (BSIM4entry.d_BSIM4gstotdArray [instance_ID] * vds + BSIM4entry.d_BSIM4gstotgArray [instance_ID] * vgs + + BSIM4entry.d_BSIM4gstotbArray [instance_ID] * vbs) ; + + /* WDLiu: ceqgstot flowing away from sNodePrime */ + gstot = BSIM4entry.d_BSIM4gstotArray [instance_ID] ; + gstotd = BSIM4entry.d_BSIM4gstotdArray [instance_ID] ; + gstotg = BSIM4entry.d_BSIM4gstotgArray [instance_ID] ; + gstots = BSIM4entry.d_BSIM4gstotsArray [instance_ID] - gstot ; + gstotb = BSIM4entry.d_BSIM4gstotbArray [instance_ID] ; + ceqgdtot = -BSIM4type * (BSIM4entry.d_BSIM4gdtotdArray [instance_ID] * vds + BSIM4entry.d_BSIM4gdtotgArray [instance_ID] * vgs + + BSIM4entry.d_BSIM4gdtotbArray [instance_ID] * vbs) ; + + /* WDLiu: ceqgdtot defined as flowing into dNodePrime */ + gdtot = BSIM4entry.d_BSIM4gdtotArray [instance_ID] ; + gdtotd = BSIM4entry.d_BSIM4gdtotdArray [instance_ID] - gdtot ; + gdtotg = BSIM4entry.d_BSIM4gdtotgArray [instance_ID] ; + gdtots = BSIM4entry.d_BSIM4gdtotsArray [instance_ID] ; + gdtotb = BSIM4entry.d_BSIM4gdtotbArray [instance_ID] ; + } else { + gstot = gstotd = gstotg = gstots = gstotb = ceqgstot = 0.0 ; + gdtot = gdtotd = gdtotg = gdtots = gdtotb = ceqgdtot = 0.0 ; + } + + /* 23 - non-divergent */ + if (BSIM4type > 0) + { + ceqjs = (BSIM4entry.d_BSIM4cbsRWArray [instance_ID] - BSIM4entry.d_BSIM4gbsRWArray [instance_ID] * vbs_jct) ; + ceqjd = (BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * vbd_jct) ; + } else { + ceqjs = -(BSIM4entry.d_BSIM4cbsRWArray [instance_ID] - BSIM4entry.d_BSIM4gbsRWArray [instance_ID] * vbs_jct) ; + ceqjd = -(BSIM4entry.d_BSIM4cbdRWArray [instance_ID] - BSIM4entry.d_BSIM4gbdRWArray [instance_ID] * vbd_jct) ; + ceqqg = -ceqqg ; + ceqqd = -ceqqd ; + ceqqb = -ceqqb ; + ceqgcrg = -ceqgcrg ; + + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + cqdef = -cqdef ; + cqcheq = -cqcheq ; + } + + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + ceqqjs = -ceqqjs ; + ceqqjd = -ceqqjd ; + } + + if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + ceqqgmid = -ceqqgmid ; + } + + + m = BSIM4entry.d_BSIM4mArray [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 (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 2) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * ceqgcrg ; + + total_offsetRHS += 1 ; + } + else if (BSIM4entry.d_BSIM4rgateModArray [instance_ID] == 3) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * (ceqqgmid + ceqgcrg) ; + + total_offsetRHS += 1 ; + } + + /* 90 - DIVERGENT */ + if (!BSIM4entry.d_BSIM4rbodyModArray [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 (BSIM4rdsMod) + { + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 0] = m * ceqgdtot ; + + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 1] = m * ceqgstot ; + + total_offsetRHS += 2 ; + } + + /* 91 - DIVERGENT */ + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + d_CKTloadOutputRHS [posRHS + total_offsetRHS + 2] = m * (cqcheq - cqdef) ; + + + + /* Loading Matrix */ + pos = d_PositionVector [instance_ID] ; + total_offset = 0 ; + + /* 92 - DIVERGENT */ + if (!BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + gjbd = BSIM4entry.d_BSIM4gbdRWArray [instance_ID] ; + gjbs = BSIM4entry.d_BSIM4gbsRWArray [instance_ID] ; + } else + gjbd = gjbs = 0.0 ; + + /* 25 - non-divergent */ + if (!BSIM4rdsMod) + { + gdpr = BSIM4entry.d_BSIM4drainConductanceArray [instance_ID] ; + gspr = BSIM4entry.d_BSIM4sourceConductanceArray [instance_ID] ; + } else + gdpr = gspr = 0.0 ; + + geltd = BSIM4entry.d_BSIM4grgeltdArray [instance_ID] ; + T1 = qdef * BSIM4entry.d_BSIM4gtauRWArray [instance_ID] ; + + /* 26 - non-divergent */ + if (BSIM4entry.d_BSIM4rgateModArray [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 (BSIM4entry.d_BSIM4rgateModArray [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 (BSIM4entry.d_BSIM4rgateModArray [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 (BSIM4rdsMod) + { + 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 = BSIM4entry.d_BSIM4ggidldArray [instance_ID] ; + ggidlg = BSIM4entry.d_BSIM4ggidlgArray [instance_ID] ; + ggidlb = BSIM4entry.d_BSIM4ggidlbArray [instance_ID] ; + ggislg = BSIM4entry.d_BSIM4ggislgArray [instance_ID] ; + ggisls = BSIM4entry.d_BSIM4ggislsArray [instance_ID] ; + ggislb = BSIM4entry.d_BSIM4ggislbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 0] = m * (gdpr + BSIM4entry.d_BSIM4gdsRWArray [instance_ID] + BSIM4entry.d_BSIM4gbdRWArray [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 * (BSIM4entry.d_BSIM4gdsRWArray [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 * (BSIM4entry.d_BSIM4gdsRWArray [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 + BSIM4entry.d_BSIM4gdsRWArray [instance_ID] + BSIM4entry.d_BSIM4gbsRWArray [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 - BSIM4entry.d_BSIM4gbgsArray [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 - BSIM4entry.d_BSIM4gbbsArray [instance_ID] - gIbtotb) - m * ggidlb - m * ggislb ; + + total_offset += 16 ; + + /* stamp gidl included above */ + /* stamp gisl included above */ + + /* 94 - DIVERGENT */ + if (BSIM4entry.d_BSIM4rbodyModArray [instance_ID]) + { + d_CKTloadOutput [pos + total_offset + 0] = m * (gcdbdb - BSIM4entry.d_BSIM4gbdRWArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 1] = m * (BSIM4entry.d_BSIM4gbsRWArray [instance_ID] - gcsbsb) ; + + + d_CKTloadOutput [pos + total_offset + 2] = m * (BSIM4entry.d_BSIM4gbdRWArray [instance_ID] - gcdbdb + BSIM4entry.d_BSIM4grbpdArray [instance_ID] + BSIM4entry.d_BSIM4grbdbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 3] = m * BSIM4entry.d_BSIM4grbpdArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 4] = m * BSIM4entry.d_BSIM4grbdbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 5] = m * BSIM4entry.d_BSIM4grbpbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 6] = m * BSIM4entry.d_BSIM4grbpsArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 7] = m * (BSIM4entry.d_BSIM4grbpdArray [instance_ID] + BSIM4entry.d_BSIM4grbpsArray [instance_ID] + BSIM4entry.d_BSIM4grbpbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 8] = m * (gcsbsb - BSIM4entry.d_BSIM4gbsRWArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 9] = m * BSIM4entry.d_BSIM4grbsbArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 10] = m * (BSIM4entry.d_BSIM4gbsRWArray [instance_ID] - gcsbsb + BSIM4entry.d_BSIM4grbpsArray [instance_ID] + BSIM4entry.d_BSIM4grbsbArray [instance_ID]) ; + + d_CKTloadOutput [pos + total_offset + 11] = m * (BSIM4entry.d_BSIM4grbsbArray [instance_ID] + BSIM4entry.d_BSIM4grbdbArray [instance_ID] + BSIM4entry.d_BSIM4grbpbArray [instance_ID]) ; + + total_offset += 12 ; + } + + /* 94 - DIVERGENT */ + if (BSIM4entry.d_BSIM4trnqsModArray [instance_ID]) + { + d_CKTloadOutput [pos + total_offset + 0] = m * (gqdef + BSIM4entry.d_BSIM4gtauRWArray [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 * BSIM4entry.d_BSIM4gtauRWArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 6] = m * sxpart * BSIM4entry.d_BSIM4gtauRWArray [instance_ID] ; + + d_CKTloadOutput [pos + total_offset + 7] = m * BSIM4entry.d_BSIM4gtauRWArray [instance_ID] ; + } + +line1000: ; + + } + } + + return ; +} diff --git a/src/spicelib/devices/bsim4/CUSPICE/cubsim4setup.c b/src/spicelib/devices/bsim4/CUSPICE/cubsim4setup.c new file mode 100644 index 000000000..3082f85aa --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/cubsim4setup.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 "bsim4def.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, "cuBSIM4setup 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, "cuBSIM4setup 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 +cuBSIM4setup +( +GENmodel *inModel +) +{ + long unsigned int size ; + cudaError_t status ; + BSIM4model *model = (BSIM4model *)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->BSIM4paramCPU.BSIM4gbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gbsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gbdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vonRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vonRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vonRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vdsatRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vdsatRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vdsatRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4csubRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4csubRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4csubRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gmRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gmRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gmRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gmbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gmbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gmbsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gcrgRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gcrgRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gcrgRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgidlRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgidlRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgidlRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgislRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgislRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgislRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgcsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgcsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgcsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgcdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgcdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgcdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IgbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qinvRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qinvRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qinvRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cggbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cggbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cggbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cgsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cgsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cgsbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cgdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cgdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cgdbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cdgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cdgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cdgbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cdsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cdsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cdsbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cddbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cddbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cddbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbgbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbsbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbsbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbsbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbdbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4csgbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4csgbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4csgbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cssbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cssbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cssbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4csdbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4csdbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4csdbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cgbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cgbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cgbbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4csbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4csbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4csbbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cdbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cdbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cdbbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cbbbRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cbbbRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cbbbRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gtauRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gtauRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gtauRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qgateRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qgateRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qgateRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qbulkRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qbulkRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qbulkRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qdrnRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qdrnRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qdrnRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qsrcRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qsrcRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qsrcRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4capbsRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4capbsRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4capbsRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4capbdRWArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4capbdRWArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4capbdRWArray, size, double, status) + + model->BSIM4paramCPU.BSIM4icVDSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4icVDSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4icVDSArray, size, double, status) + + model->BSIM4paramCPU.BSIM4icVGSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4icVGSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4icVGSArray, size, double, status) + + model->BSIM4paramCPU.BSIM4icVBSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4icVBSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4icVBSArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vth0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vth0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vth0Array, size, double, status) + + model->BSIM4paramCPU.BSIM4gbbsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gbbsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gbbsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggidlbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggidlbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggidlbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gbgsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gbgsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gbgsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggidlgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggidlgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggidlgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gbdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gbdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gbdsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggidldArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggidldArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggidldArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggislsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggislsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggislsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggislgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggislgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggislgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggislbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggislbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggislbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgsgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgsgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgsgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcsgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcsgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcsdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcsdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgdgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgdgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgdgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcdgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcdgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcddArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcddArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcddArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgbgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgbgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgbgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgbdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgbdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgbdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgbbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgbbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgbbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggidlsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggidlsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggidlsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4ggisldArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ggisldArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ggisldArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gstotArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gstotArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gstotArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gstotdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gstotdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gstotdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gstotgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gstotgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gstotgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gstotbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gstotbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gstotbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdtotArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdtotArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdtotArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdtotdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdtotdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdtotdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdtotgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdtotgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdtotgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdtotbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdtotbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdtotbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cgdoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cgdoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cgdoArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qgdoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qgdoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qgdoArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cgsoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cgsoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cgsoArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qgsoArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qgsoArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qgsoArray, size, double, status) + + model->BSIM4paramCPU.BSIM4AseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4AseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4AseffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4PseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4PseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4PseffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4nfArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4nfArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4nfArray, size, double, status) + + model->BSIM4paramCPU.BSIM4XExpBVSArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4XExpBVSArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4XExpBVSArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vjsmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vjsmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vjsmFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IVjsmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IVjsmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IVjsmFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vjsmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vjsmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vjsmRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IVjsmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IVjsmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IVjsmRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SslpRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SslpRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SslpRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SslpFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SslpFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SslpFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4AdeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4AdeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4AdeffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4PdeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4PdeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4PdeffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4XExpBVDArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4XExpBVDArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4XExpBVDArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vjdmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vjdmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vjdmFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IVjdmFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IVjdmFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IVjdmFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vjdmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vjdmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vjdmRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IVjdmRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IVjdmRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IVjdmRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DslpRevArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DslpRevArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DslpRevArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DslpFwdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DslpFwdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DslpFwdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SjctTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SjctTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SjctTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SswTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SswTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SswTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SswgTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SswgTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SswgTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DjctTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DjctTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DjctTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DswTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DswTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DswTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DswgTempRevSatCurArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DswgTempRevSatCurArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DswgTempRevSatCurArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vbscArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vbscArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vbscArray, size, double, status) + + model->BSIM4paramCPU.BSIM4thetavthArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4thetavthArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4thetavthArray, size, double, status) + + model->BSIM4paramCPU.BSIM4eta0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4eta0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4eta0Array, size, double, status) + + model->BSIM4paramCPU.BSIM4k2oxArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4k2oxArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4k2oxArray, size, double, status) + + model->BSIM4paramCPU.BSIM4nstarArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4nstarArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4nstarArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vfbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vfbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vfbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vgs_effArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vgs_effArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vgs_effArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vgd_effArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vgd_effArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vgd_effArray, size, double, status) + + model->BSIM4paramCPU.BSIM4dvgs_eff_dvgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dvgs_eff_dvgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dvgs_eff_dvgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4dvgd_eff_dvgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dvgd_eff_dvgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dvgd_eff_dvgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4VgsteffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4VgsteffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4VgsteffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grdswArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grdswArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grdswArray, size, double, status) + + model->BSIM4paramCPU.BSIM4AbulkArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4AbulkArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4AbulkArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vtfbphi1Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vtfbphi1Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vtfbphi1Array, size, double, status) + + model->BSIM4paramCPU.BSIM4ueffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4ueffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4ueffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4u0tempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4u0tempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4u0tempArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vsattempArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vsattempArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vsattempArray, size, double, status) + + model->BSIM4paramCPU.BSIM4EsatLArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4EsatLArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4EsatLArray, size, double, status) + + model->BSIM4paramCPU.BSIM4VdseffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4VdseffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4VdseffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vtfbphi2Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vtfbphi2Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vtfbphi2Array, size, double, status) + + model->BSIM4paramCPU.BSIM4CoxeffArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4CoxeffArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4CoxeffArray, size, double, status) + + model->BSIM4paramCPU.BSIM4AbovVgst2VtmArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4AbovVgst2VtmArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4AbovVgst2VtmArray, size, double, status) + + model->BSIM4paramCPU.BSIM4IdovVdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4IdovVdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4IdovVdsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gcrgdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gcrgdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gcrgdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gcrgbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gcrgbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gcrgbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gcrggArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gcrggArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gcrggArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grgeltdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grgeltdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grgeltdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gcrgsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gcrgsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gcrgsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4sourceConductanceArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sourceConductanceArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sourceConductanceArray, size, double, status) + + model->BSIM4paramCPU.BSIM4drainConductanceArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4drainConductanceArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4drainConductanceArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gstotsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gstotsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gstotsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gdtotsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gdtotsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gdtotsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4vfbzbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4vfbzbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4vfbzbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgssArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgssArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgssArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgddArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgddArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgddArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgbsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgbsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgbsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcssArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcssArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcssArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gIgcdsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gIgcdsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4noiGd0Array = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4noiGd0Array), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4noiGd0Array, size, double, status) + + model->BSIM4paramCPU.BSIM4cqdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cqdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cqdbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cqsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cqsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cqsbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cqgbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cqgbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cqgbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qchqsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qchqsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qchqsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4cqbbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4cqbbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4cqbbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4taunetArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4taunetArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4taunetArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gtgArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gtgArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gtgArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gtdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gtdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gtdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gtsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gtsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gtsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gtbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gtbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gtbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4mArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4mArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4mArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grbpdArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grbpdArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grbpdArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grbdbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grbdbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grbdbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grbpbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grbpbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grbpbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grbpsArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grbpsArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grbpsArray, size, double, status) + + model->BSIM4paramCPU.BSIM4grbsbArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4grbsbArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4grbsbArray, size, double, status) + + model->BSIM4paramCPU.BSIM4dNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dNodePrimeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodePrimeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gNodeExtRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodeExtRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodeExtRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4gNodeMidRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodeMidRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodeMidRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4bNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4bNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4bNodePrimeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4sNodePrimeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sNodePrimeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sNodePrimeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4dbNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dbNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dbNodeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4sbNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sbNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sbNodeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4dNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dNodeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4sNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sNodeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4qNodeRHSValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qNodeRHSValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qNodeRHSValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEgeValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPgeValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GEgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GEgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GEgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMgeValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMgeValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMgeValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GMbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GMbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GMbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPgmValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPgmValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPgmValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPdValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPdValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPdValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DdValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DdValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DdValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPsValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPsValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPsValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SsValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SsValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SsValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPdbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPsbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DBdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DBdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DBdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DBdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DBdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DBdbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DBbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DBbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DBbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DBbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DBbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DBbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPdbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPsbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BPbpIFValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BPbpIFValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BPbpIFValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SBspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SBspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SBspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SBbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SBbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SBbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SBbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SBbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SBbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SBsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SBsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SBsbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BdbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BdbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BdbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BsbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BsbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BsbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4BbValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4BbValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4BbValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4QqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4QqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4QqValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4QgpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4QgpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4QgpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4QdpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4QdpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4QdpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4QspValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4QspValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4QspValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4QbpValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4QbpValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4QbpValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4DPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4DPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4DPqValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4SPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4SPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4SPqValueArray, size, double, status) + + model->BSIM4paramCPU.BSIM4GPqValueArray = (double *) malloc (size * sizeof(double)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4GPqValueArray), size * sizeof(double)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4GPqValueArray, size, double, status) + + /* INT */ + model->BSIM4paramCPU.BSIM4offArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4offArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4offArray, size, int, status) + + model->BSIM4paramCPU.BSIM4dNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dNodePrimeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4sNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sNodePrimeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4gNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodePrimeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4bNodePrimeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4bNodePrimeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4bNodePrimeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4gNodeExtArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodeExtArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodeExtArray, size, int, status) + + model->BSIM4paramCPU.BSIM4gNodeMidArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4gNodeMidArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4gNodeMidArray, size, int, status) + + model->BSIM4paramCPU.BSIM4dbNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dbNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dbNodeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4sbNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sbNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sbNodeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4sNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4sNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4sNodeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4dNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4dNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4dNodeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4qNodeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4qNodeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4qNodeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4rbodyModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4rbodyModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4rbodyModArray, size, int, status) + + model->BSIM4paramCPU.BSIM4modeArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4modeArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4modeArray, size, int, status) + + model->BSIM4paramCPU.BSIM4rgateModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4rgateModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4rgateModArray, size, int, status) + + model->BSIM4paramCPU.BSIM4trnqsModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4trnqsModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4trnqsModArray, size, int, status) + + model->BSIM4paramCPU.BSIM4acnqsModArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4acnqsModArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4acnqsModArray, size, int, status) + + model->BSIM4paramCPU.BSIM4statesArray = (int *) malloc (size * sizeof(int)) ; + status = cudaMalloc ((void **)&(model->BSIM4paramGPU.d_BSIM4statesArray), size * sizeof(int)) ; + CUDAMALLOCCHECK (model->BSIM4paramGPU.d_BSIM4statesArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/bsim4/CUSPICE/cubsim4temp.c b/src/spicelib/devices/bsim4/CUSPICE/cubsim4temp.c new file mode 100644 index 000000000..089bd9815 --- /dev/null +++ b/src/spicelib/devices/bsim4/CUSPICE/cubsim4temp.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 "bsim4def.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, "cuBSIM4temp 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, "cuBSIM4temp 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 +cuBSIM4temp +( +GENmodel *inModel +) +{ + int i ; + long unsigned int size ; + cudaError_t status ; + BSIM4model *model = (BSIM4model *)inModel ; + BSIM4instance *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 = model->BSIM4instances ; here != NULL ; here = here->BSIM4nextInstance) + { + 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->BSIM4paramGPU.d_BSIM4gbsRWArray, model->BSIM4paramCPU.BSIM4gbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbsRWArray, model->BSIM4paramCPU.BSIM4cbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gbdRWArray, model->BSIM4paramCPU.BSIM4gbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbdRWArray, model->BSIM4paramCPU.BSIM4cbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vonRWArray, model->BSIM4paramCPU.BSIM4vonRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vonRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vdsatRWArray, model->BSIM4paramCPU.BSIM4vdsatRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vdsatRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4csubRWArray, model->BSIM4paramCPU.BSIM4csubRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4csubRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdsRWArray, model->BSIM4paramCPU.BSIM4gdsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gmRWArray, model->BSIM4paramCPU.BSIM4gmRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gmRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gmbsRWArray, model->BSIM4paramCPU.BSIM4gmbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gmbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gcrgRWArray, model->BSIM4paramCPU.BSIM4gcrgRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gcrgRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgidlRWArray, model->BSIM4paramCPU.BSIM4IgidlRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgidlRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgislRWArray, model->BSIM4paramCPU.BSIM4IgislRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgislRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgcsRWArray, model->BSIM4paramCPU.BSIM4IgcsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgcsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgcdRWArray, model->BSIM4paramCPU.BSIM4IgcdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgcdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgsRWArray, model->BSIM4paramCPU.BSIM4IgsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgdRWArray, model->BSIM4paramCPU.BSIM4IgdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IgbRWArray, model->BSIM4paramCPU.BSIM4IgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cdRWArray, model->BSIM4paramCPU.BSIM4cdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qinvRWArray, model->BSIM4paramCPU.BSIM4qinvRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qinvRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cggbRWArray, model->BSIM4paramCPU.BSIM4cggbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cggbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cgsbRWArray, model->BSIM4paramCPU.BSIM4cgsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cgsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cgdbRWArray, model->BSIM4paramCPU.BSIM4cgdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cgdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cdgbRWArray, model->BSIM4paramCPU.BSIM4cdgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cdgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cdsbRWArray, model->BSIM4paramCPU.BSIM4cdsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cdsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cddbRWArray, model->BSIM4paramCPU.BSIM4cddbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cddbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbgbRWArray, model->BSIM4paramCPU.BSIM4cbgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbsbRWArray, model->BSIM4paramCPU.BSIM4cbsbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbsbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbdbRWArray, model->BSIM4paramCPU.BSIM4cbdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4csgbRWArray, model->BSIM4paramCPU.BSIM4csgbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4csgbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cssbRWArray, model->BSIM4paramCPU.BSIM4cssbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cssbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4csdbRWArray, model->BSIM4paramCPU.BSIM4csdbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4csdbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cgbbRWArray, model->BSIM4paramCPU.BSIM4cgbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cgbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4csbbRWArray, model->BSIM4paramCPU.BSIM4csbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4csbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cdbbRWArray, model->BSIM4paramCPU.BSIM4cdbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cdbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cbbbRWArray, model->BSIM4paramCPU.BSIM4cbbbRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cbbbRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gtauRWArray, model->BSIM4paramCPU.BSIM4gtauRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gtauRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qgateRWArray, model->BSIM4paramCPU.BSIM4qgateRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qgateRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qbulkRWArray, model->BSIM4paramCPU.BSIM4qbulkRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qbulkRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qdrnRWArray, model->BSIM4paramCPU.BSIM4qdrnRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qdrnRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qsrcRWArray, model->BSIM4paramCPU.BSIM4qsrcRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qsrcRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4capbsRWArray, model->BSIM4paramCPU.BSIM4capbsRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4capbsRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4capbdRWArray, model->BSIM4paramCPU.BSIM4capbdRWArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4capbdRWArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVDSArray, model->BSIM4paramCPU.BSIM4icVDSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVDSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVGSArray, model->BSIM4paramCPU.BSIM4icVGSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVGSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4icVBSArray, model->BSIM4paramCPU.BSIM4icVBSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4icVBSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vth0Array, model->BSIM4paramCPU.BSIM4vth0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vth0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gbbsArray, model->BSIM4paramCPU.BSIM4gbbsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gbbsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggidlbArray, model->BSIM4paramCPU.BSIM4ggidlbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggidlbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gbgsArray, model->BSIM4paramCPU.BSIM4gbgsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gbgsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggidlgArray, model->BSIM4paramCPU.BSIM4ggidlgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggidlgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gbdsArray, model->BSIM4paramCPU.BSIM4gbdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gbdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggidldArray, model->BSIM4paramCPU.BSIM4ggidldArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggidldArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggislsArray, model->BSIM4paramCPU.BSIM4ggislsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggislsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggislgArray, model->BSIM4paramCPU.BSIM4ggislgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggislgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggislbArray, model->BSIM4paramCPU.BSIM4ggislbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggislbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgsgArray, model->BSIM4paramCPU.BSIM4gIgsgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgsgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcsgArray, model->BSIM4paramCPU.BSIM4gIgcsgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcsdArray, model->BSIM4paramCPU.BSIM4gIgcsdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcsbArray, model->BSIM4paramCPU.BSIM4gIgcsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcsbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgdgArray, model->BSIM4paramCPU.BSIM4gIgdgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgdgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcdgArray, model->BSIM4paramCPU.BSIM4gIgcdgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcddArray, model->BSIM4paramCPU.BSIM4gIgcddArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcddArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcdbArray, model->BSIM4paramCPU.BSIM4gIgcdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgbgArray, model->BSIM4paramCPU.BSIM4gIgbgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgbgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgbdArray, model->BSIM4paramCPU.BSIM4gIgbdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgbdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgbbArray, model->BSIM4paramCPU.BSIM4gIgbbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgbbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggidlsArray, model->BSIM4paramCPU.BSIM4ggidlsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggidlsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ggisldArray, model->BSIM4paramCPU.BSIM4ggisldArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ggisldArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gstotArray, model->BSIM4paramCPU.BSIM4gstotArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gstotArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gstotdArray, model->BSIM4paramCPU.BSIM4gstotdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gstotdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gstotgArray, model->BSIM4paramCPU.BSIM4gstotgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gstotgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gstotbArray, model->BSIM4paramCPU.BSIM4gstotbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gstotbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdtotArray, model->BSIM4paramCPU.BSIM4gdtotArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdtotArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdtotdArray, model->BSIM4paramCPU.BSIM4gdtotdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdtotdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdtotgArray, model->BSIM4paramCPU.BSIM4gdtotgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdtotgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdtotbArray, model->BSIM4paramCPU.BSIM4gdtotbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdtotbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cgdoArray, model->BSIM4paramCPU.BSIM4cgdoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cgdoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qgdoArray, model->BSIM4paramCPU.BSIM4qgdoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qgdoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cgsoArray, model->BSIM4paramCPU.BSIM4cgsoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cgsoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qgsoArray, model->BSIM4paramCPU.BSIM4qgsoArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qgsoArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4AseffArray, model->BSIM4paramCPU.BSIM4AseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4AseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4PseffArray, model->BSIM4paramCPU.BSIM4PseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4PseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4nfArray, model->BSIM4paramCPU.BSIM4nfArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4nfArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4XExpBVSArray, model->BSIM4paramCPU.BSIM4XExpBVSArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4XExpBVSArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vjsmFwdArray, model->BSIM4paramCPU.BSIM4vjsmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vjsmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IVjsmFwdArray, model->BSIM4paramCPU.BSIM4IVjsmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IVjsmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vjsmRevArray, model->BSIM4paramCPU.BSIM4vjsmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vjsmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IVjsmRevArray, model->BSIM4paramCPU.BSIM4IVjsmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IVjsmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4SslpRevArray, model->BSIM4paramCPU.BSIM4SslpRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4SslpRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4SslpFwdArray, model->BSIM4paramCPU.BSIM4SslpFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4SslpFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4AdeffArray, model->BSIM4paramCPU.BSIM4AdeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4AdeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4PdeffArray, model->BSIM4paramCPU.BSIM4PdeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4PdeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4XExpBVDArray, model->BSIM4paramCPU.BSIM4XExpBVDArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4XExpBVDArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vjdmFwdArray, model->BSIM4paramCPU.BSIM4vjdmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vjdmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IVjdmFwdArray, model->BSIM4paramCPU.BSIM4IVjdmFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IVjdmFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vjdmRevArray, model->BSIM4paramCPU.BSIM4vjdmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vjdmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IVjdmRevArray, model->BSIM4paramCPU.BSIM4IVjdmRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IVjdmRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4DslpRevArray, model->BSIM4paramCPU.BSIM4DslpRevArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4DslpRevArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4DslpFwdArray, model->BSIM4paramCPU.BSIM4DslpFwdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4DslpFwdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4SjctTempRevSatCurArray, model->BSIM4paramCPU.BSIM4SjctTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4SjctTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4SswTempRevSatCurArray, model->BSIM4paramCPU.BSIM4SswTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4SswTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4SswgTempRevSatCurArray, model->BSIM4paramCPU.BSIM4SswgTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4SswgTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4DjctTempRevSatCurArray, model->BSIM4paramCPU.BSIM4DjctTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4DjctTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4DswTempRevSatCurArray, model->BSIM4paramCPU.BSIM4DswTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4DswTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4DswgTempRevSatCurArray, model->BSIM4paramCPU.BSIM4DswgTempRevSatCurArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4DswgTempRevSatCurArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vbscArray, model->BSIM4paramCPU.BSIM4vbscArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vbscArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4thetavthArray, model->BSIM4paramCPU.BSIM4thetavthArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4thetavthArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4eta0Array, model->BSIM4paramCPU.BSIM4eta0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4eta0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4k2oxArray, model->BSIM4paramCPU.BSIM4k2oxArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4k2oxArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4nstarArray, model->BSIM4paramCPU.BSIM4nstarArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4nstarArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vfbArray, model->BSIM4paramCPU.BSIM4vfbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vfbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vgs_effArray, model->BSIM4paramCPU.BSIM4vgs_effArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vgs_effArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vgd_effArray, model->BSIM4paramCPU.BSIM4vgd_effArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vgd_effArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4dvgs_eff_dvgArray, model->BSIM4paramCPU.BSIM4dvgs_eff_dvgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4dvgs_eff_dvgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4dvgd_eff_dvgArray, model->BSIM4paramCPU.BSIM4dvgd_eff_dvgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4dvgd_eff_dvgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4VgsteffArray, model->BSIM4paramCPU.BSIM4VgsteffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4VgsteffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grdswArray, model->BSIM4paramCPU.BSIM4grdswArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grdswArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4AbulkArray, model->BSIM4paramCPU.BSIM4AbulkArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4AbulkArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vtfbphi1Array, model->BSIM4paramCPU.BSIM4vtfbphi1Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vtfbphi1Array, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4ueffArray, model->BSIM4paramCPU.BSIM4ueffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4ueffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4u0tempArray, model->BSIM4paramCPU.BSIM4u0tempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4u0tempArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vsattempArray, model->BSIM4paramCPU.BSIM4vsattempArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vsattempArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4EsatLArray, model->BSIM4paramCPU.BSIM4EsatLArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4EsatLArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4VdseffArray, model->BSIM4paramCPU.BSIM4VdseffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4VdseffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vtfbphi2Array, model->BSIM4paramCPU.BSIM4vtfbphi2Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vtfbphi2Array, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4CoxeffArray, model->BSIM4paramCPU.BSIM4CoxeffArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4CoxeffArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4AbovVgst2VtmArray, model->BSIM4paramCPU.BSIM4AbovVgst2VtmArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4AbovVgst2VtmArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4IdovVdsArray, model->BSIM4paramCPU.BSIM4IdovVdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4IdovVdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gcrgdArray, model->BSIM4paramCPU.BSIM4gcrgdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gcrgdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gcrgbArray, model->BSIM4paramCPU.BSIM4gcrgbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gcrgbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gcrggArray, model->BSIM4paramCPU.BSIM4gcrggArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gcrggArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grgeltdArray, model->BSIM4paramCPU.BSIM4grgeltdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grgeltdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gcrgsArray, model->BSIM4paramCPU.BSIM4gcrgsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gcrgsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4sourceConductanceArray, model->BSIM4paramCPU.BSIM4sourceConductanceArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4sourceConductanceArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4drainConductanceArray, model->BSIM4paramCPU.BSIM4drainConductanceArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4drainConductanceArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gstotsArray, model->BSIM4paramCPU.BSIM4gstotsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gstotsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gdtotsArray, model->BSIM4paramCPU.BSIM4gdtotsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gdtotsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4vfbzbArray, model->BSIM4paramCPU.BSIM4vfbzbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4vfbzbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgssArray, model->BSIM4paramCPU.BSIM4gIgssArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgssArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgddArray, model->BSIM4paramCPU.BSIM4gIgddArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgddArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgbsArray, model->BSIM4paramCPU.BSIM4gIgbsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgbsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcssArray, model->BSIM4paramCPU.BSIM4gIgcssArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcssArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gIgcdsArray, model->BSIM4paramCPU.BSIM4gIgcdsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gIgcdsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4noiGd0Array, model->BSIM4paramCPU.BSIM4noiGd0Array, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4noiGd0Array, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cqdbArray, model->BSIM4paramCPU.BSIM4cqdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cqdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cqsbArray, model->BSIM4paramCPU.BSIM4cqsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cqsbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cqgbArray, model->BSIM4paramCPU.BSIM4cqgbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cqgbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qchqsArray, model->BSIM4paramCPU.BSIM4qchqsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qchqsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4cqbbArray, model->BSIM4paramCPU.BSIM4cqbbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4cqbbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4taunetArray, model->BSIM4paramCPU.BSIM4taunetArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4taunetArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gtgArray, model->BSIM4paramCPU.BSIM4gtgArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gtgArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gtdArray, model->BSIM4paramCPU.BSIM4gtdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gtdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gtsArray, model->BSIM4paramCPU.BSIM4gtsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gtsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gtbArray, model->BSIM4paramCPU.BSIM4gtbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gtbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4mArray, model->BSIM4paramCPU.BSIM4mArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4mArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grbpdArray, model->BSIM4paramCPU.BSIM4grbpdArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grbpdArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grbdbArray, model->BSIM4paramCPU.BSIM4grbdbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grbdbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grbpbArray, model->BSIM4paramCPU.BSIM4grbpbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grbpbArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grbpsArray, model->BSIM4paramCPU.BSIM4grbpsArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grbpsArray, size, double, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4grbsbArray, model->BSIM4paramCPU.BSIM4grbsbArray, size * sizeof(double), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4grbsbArray, size, double, status) + + /* INT */ + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4offArray, model->BSIM4paramCPU.BSIM4offArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4offArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4dNodePrimeArray, model->BSIM4paramCPU.BSIM4dNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4dNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4sNodePrimeArray, model->BSIM4paramCPU.BSIM4sNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4sNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gNodePrimeArray, model->BSIM4paramCPU.BSIM4gNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4bNodePrimeArray, model->BSIM4paramCPU.BSIM4bNodePrimeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4bNodePrimeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gNodeExtArray, model->BSIM4paramCPU.BSIM4gNodeExtArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gNodeExtArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4gNodeMidArray, model->BSIM4paramCPU.BSIM4gNodeMidArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4gNodeMidArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4dbNodeArray, model->BSIM4paramCPU.BSIM4dbNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4dbNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4sbNodeArray, model->BSIM4paramCPU.BSIM4sbNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4sbNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4sNodeArray, model->BSIM4paramCPU.BSIM4sNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4sNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4dNodeArray, model->BSIM4paramCPU.BSIM4dNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4dNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4qNodeArray, model->BSIM4paramCPU.BSIM4qNodeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4qNodeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4rbodyModArray, model->BSIM4paramCPU.BSIM4rbodyModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4rbodyModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4modeArray, model->BSIM4paramCPU.BSIM4modeArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4modeArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4rgateModArray, model->BSIM4paramCPU.BSIM4rgateModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4rgateModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4trnqsModArray, model->BSIM4paramCPU.BSIM4trnqsModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4trnqsModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4acnqsModArray, model->BSIM4paramCPU.BSIM4acnqsModArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.d_BSIM4acnqsModArray, size, int, status) + + status = cudaMemcpy (model->BSIM4paramGPU.d_BSIM4statesArray, model->BSIM4paramCPU.BSIM4statesArray, size * sizeof(int), cudaMemcpyHostToDevice) ; + CUDAMEMCPYCHECK (model->BSIM4paramGPU.BSIM4statesArray, size, int, status) + + return (OK) ; +} diff --git a/src/spicelib/devices/cap/CUSPICE/captopology.c b/src/spicelib/devices/cap/CUSPICE/captopology.c new file mode 100644 index 000000000..7bc6d8cd3 --- /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 = model->CAPnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->CAPinstances ; here != NULL ; here = here->CAPnextInstance) + { + 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..9e9d5665b --- /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 = model->CAPnextModel) + { + /* 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..df4a817b8 --- /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..0b11ffa1b --- /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 = model->CAPnextModel) + { + /* 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..54802974a --- /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..b21310c9e --- /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/ind/CUSPICE/cuindfree.c b/src/spicelib/devices/ind/CUSPICE/cuindfree.c new file mode 100644 index 000000000..b581f1d7d --- /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 = model->INDnextModel) + { + /* 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..76612e187 --- /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 = model->INDnextModel) + { + /* 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..db7e40c65 --- /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..68f22d9c6 --- /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..0b81b1a53 --- /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 = model->MUTnextModel) + { + /* 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..232b665e3 --- /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 = model->MUTnextModel) + { + /* 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..5df9a0e30 --- /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..52d9a12ff --- /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..d73ab3f2a --- /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 = model->INDnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->INDinstances ; here != NULL ; here = here->INDnextInstance) + { + 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..a651bbd13 --- /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 = model->MUTnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->MUTinstances ; here != NULL ; here = here->MUTnextInstance) + { + if ((here->MUTind1->INDbrEq != 0) && (here->MUTind2->INDbrEq != 0)) + { + TopologyMatrixInsert (MUTbr1br2, k, 0, -1, *i) ; + (*i)++ ; + } + + if ((here->MUTind2->INDbrEq != 0) && (here->MUTind1->INDbrEq != 0)) + { + TopologyMatrixInsert (MUTbr2br1, k, 0, -1, *i) ; + (*i)++ ; + } + + k++ ; + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c b/src/spicelib/devices/isrc/CUSPICE/cuisrcfree.c new file mode 100644 index 000000000..8060a20e8 --- /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 = model->ISRCnextModel) + { + /* Special case VSRCparamGPU.VSRCcoeffsArray */ + i = 0 ; + + for (here = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + cudaFree (model->ISRCparamCPU.ISRCcoeffsArray[i]) ; + + i++ ; + } + free (model->ISRCparamCPU.ISRCcoeffsArray) ; + cudaFree (model->ISRCparamGPU.d_ISRCcoeffsArray) ; + + i = 0 ; + + for (here = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + 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..116ae0b4b --- /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 = model->ISRCnextModel) + { + /* 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..68b9f702e --- /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 = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + 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 = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + 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..8d4f89f18 --- /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 = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + 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..bd9aa8c11 --- /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 = model->ISRCnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + 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/isrcsetup.c b/src/spicelib/devices/isrc/isrcsetup.c new file mode 100644 index 000000000..7c3458285 --- /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 = model->ISRCnextModel) + { + i = 0 ; + + for (here = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + i++ ; + } + + /* How many instances we have */ + model->n_instances = i ; + } + + /* loop through all the current source models */ + for (model = (ISRCmodel *)inModel ; model != NULL ; model = model->ISRCnextModel) + { + model->offsetRHS = ckt->total_n_valuesRHS ; + + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->ISRCinstances ; here != NULL ; here = here->ISRCnextInstance) + { + /* 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 = model->ISRCnextModel) + { + status = cuISRCsetup ((GENmodel *)model) ; + if (status != 0) + return (E_NOMEM) ; + } + + return (OK) ; +} diff --git a/src/spicelib/devices/res/CUSPICE/curesfree.c b/src/spicelib/devices/res/CUSPICE/curesfree.c new file mode 100644 index 000000000..957b14cf8 --- /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 = model->RESnextModel) + { + /* 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..0591893c4 --- /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 = model->RESnextModel) + { + /* 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..b19e61d42 --- /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..6fd4d0ee6 --- /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..ecd943fc1 --- /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 = model->RESnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->RESinstances ; here != NULL ; here = here->RESnextInstance) + { + 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/vsrc/CUSPICE/cuvsrcfree.c b/src/spicelib/devices/vsrc/CUSPICE/cuvsrcfree.c new file mode 100644 index 000000000..7eb0b034c --- /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 = model->VSRCnextModel) + { + /* Special case VSRCparamGPU.VSRCcoeffsArray */ + i = 0 ; + + for (here = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + cudaFree (model->VSRCparamCPU.VSRCcoeffsArray [i]) ; + + i++ ; + } + free (model->VSRCparamCPU.VSRCcoeffsArray) ; + cudaFree (model->VSRCparamGPU.d_VSRCcoeffsArray) ; + + i = 0 ; + + for (here = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + 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..b832c104a --- /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 = model->VSRCnextModel) + { + /* 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..df90501e1 --- /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 = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + 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 = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + 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..44c04de98 --- /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 = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + 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..2f4fb809e --- /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 = model->VSRCnextModel) + { + k = 0 ; + + /* loop through all the instances of the model */ + for (here = model->VSRCinstances ; here != NULL ; here = here->VSRCnextInstance) + { + 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) ; +}