From 0d34bb52ccf87a3be2cb7b0bab5267f8f06b5bdb Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 12 Jul 2020 09:46:49 +0200 Subject: [PATCH] compile scripts for simd --- compile_linux_simd.sh | 84 ++++++++++++++ compile_min_simd.sh | 92 +++++++++++++++ configure.ac | 2 +- src/frontend/outitf.c | 7 +- src/spicelib/devices/bsim3v32/Makefile.am | 11 +- src/spicelib/devices/bsim3v32/b3v32ld.c | 112 +++++++++++++------ src/spicelib/devices/bsim3v32/b3v32set.c | 66 +++++++++-- src/spicelib/devices/bsim3v32/bsim3v32def.h | 44 +++++++- src/spicelib/devices/bsim3v32/bsim3v32ext.h | 6 + src/spicelib/devices/bsim3v32/bsim3v32init.c | 4 + 10 files changed, 378 insertions(+), 50 deletions(-) create mode 100644 compile_linux_simd.sh create mode 100644 compile_min_simd.sh diff --git a/compile_linux_simd.sh b/compile_linux_simd.sh new file mode 100644 index 000000000..9b249ffa6 --- /dev/null +++ b/compile_linux_simd.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# ngspice build script for Linux, release or debug version, 64 bit +# compile_linux.sh + +# Procedure: +# Install gcc, bison, flex, libtool, autoconf, automake, +# libx11 and libx11-dev (headers), libXaw and libXaw-dev, libreadline and dev +# Declare 'compile_linux.sh' executable and start compiling with +# './compile_linux.sh' or './compile_linux.sh d' from the ngspice directory. +# Options: +# --adms and --enable-adms will install extra HICUM, EKV and MEXTRAM models via the +# adms interface. You need to download and install the *.va files via ng-adms-va.tgz +# Please see the ngspice manual, chapt. 13, for more info on adms. +# CIDER, XSPICE, and OpenMP may be selected at will. +# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info. + +# ngspice as shared library: +# Replace --with-x by --with-ngshared in line ../configure ... . +# Add (optionally) --enable-relpath to avoid absolute paths when searching for code models. +# It might be necessary to uncomment and run ./autogen.sh . + +SECONDS=0 + +if test "$1" = "d"; then + if [ ! -d "debug" ]; then + mkdir debug + if [ $? -ne 0 ]; then echo "mkdir debug failed"; exit 1 ; fi + fi +else + if [ ! -d "release" ]; then + mkdir release + if [ $? -ne 0 ]; then echo "mkdir release failed"; exit 1 ; fi + fi +fi + +# If compiling sources from git, you may need to uncomment the following two lines: +./autogen.sh +if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi + +# Alternatively, if compiling sources from git, and want to add adms created devices, +# you may need to uncomment the following two lines (and don't forget to add adms option +# to the ../configure statement): +#./autogen.sh --adms +#if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi + +echo +if test "$1" = "d"; then + cd debug + if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi + echo "configuring for 64 bit debug" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-x --enable-xspice --enable-cider --with-readline=yes --enable-openmp CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable -march=native" LDFLAGS="-m64 -g" +else + cd release + if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi + echo "configuring for 64 bit release" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-x --enable-xspice --enable-cider --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m64 -O3 -march=native" LDFLAGS="-m64 -s" +fi +if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi + +echo +# make clean is required for properly making the code models +echo "cleaning (see make_clean.log)" +make clean 2>&1 -j8 | tee make_clean.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make clean failed"; exit 1 ; fi +echo "compiling (see make.log)" +make 2>&1 -j8 | tee make.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make failed"; exit 1 ; fi +# Install to /usr/local +echo "installing (see make_install.log)" +make install 2>&1 | tee make_install.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make install failed"; exit 1 ; fi + +ELAPSED="Elapsed compile time: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec" +echo +echo $ELAPSED +echo "success" +exit 0 diff --git a/compile_min_simd.sh b/compile_min_simd.sh new file mode 100644 index 000000000..41dc78287 --- /dev/null +++ b/compile_min_simd.sh @@ -0,0 +1,92 @@ +#!/bin/bash +# ngspice build script for MINGW-w64, release or debug version, 64 bit +# compile_min.sh + +#Procedure: +# Install MSYS2, plus gcc 64 bit, libtool, autoconf, automake, bison, git, and make +# See either https://github.com/orlp/dev-on-windows/wiki/Installing-GCC--&-MSYS2 +# (allows to generate either 32 or 64 bit executables by setting flag -m32 or -m64) +# start compiling with +# './compile_min.sh' for release or './compile_min.sh d' for debug version. + +# Options: +# --adms and --enable-adms will install extra HICUM, EKV and MEXTRAM models via the +# adms interface. +# Please see http://ngspice.sourceforge.net/admshowto.html for more info on adms. +# CIDER, XSPICE, and OpenMP may be selected at will. +# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info. +# --enable-oldapps will make ngnutmeg ngsconvert ngproc2mod ngmultidec ngmakeidx in addition to ngspice + +# ngspice as shared library: +# Replace --with-wingui by --with-ngshared in line ../configure ... . +# Add (optionally) --enable-relpath to avoid absolute paths when searching for code models. +# It might be necessary to uncomment and run ./autogen.sh . + +SECONDS=0 + +if test "$1" = "d"; then + if [ ! -d "debug" ]; then + mkdir debug + if [ $? -ne 0 ]; then echo "mkdir debug failed"; exit 1 ; fi + fi +else + if [ ! -d "release" ]; then + mkdir release + if [ $? -ne 0 ]; then echo "mkdir release failed"; exit 1 ; fi + fi +fi + +# If compiling sources from git, you may need to uncomment the following two lines: +./autogen.sh +if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi + +# Alternatively, if compiling sources from git, and want to add adms created devices, +# you may need to uncomment the following two lines (and don't forget to add adms option +# to the ../configure statement): +#./autogen.sh --adms +#if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi + +echo +if test "$1" = "d"; then + cd debug + if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi + echo "configuring for 64 bit debug" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-wingui --enable-xspice --enable-cider --enable-openmp prefix="C:/Spice64d" CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable -march=native" LDFLAGS="-g -m64" +else + cd release + if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi + echo "configuring for 64 bit release" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --disable-debug prefix="C:/Spice64" CFLAGS="-m64 -O3 -march=native " LDFLAGS="-m64 -s" +fi +if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi + +echo +# make clean is required for properly making the code models +echo "cleaning (see make_clean.log)" +make clean 2>&1 -j8 | tee make_clean.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make clean failed"; exit 1 ; fi +echo "compiling the icon" +windres ../src/ngicon.rc -O coff -o ./src/ngicon.o +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "compiling the icon failed"; exit 1 ; fi +echo "compiling (see make.log)" +make 2>&1 -j8 | tee make.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make failed"; exit 1 ; fi +# 64 bit debug: Install to C:\Spice64d +# 64 bit: Install to C:\Spice64 +echo "installing (see make_install.log)" +make install 2>&1 | tee make_install.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make install failed"; exit 1 ; fi + +ELAPSED="Elapsed compile time: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec" +echo +echo $ELAPSED +echo "success" +exit 0 diff --git a/configure.ac b/configure.ac index 2419e69f1..a6b74ca82 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,7 @@ AC_CONFIG_HEADER([src/include/ngspice/config.h]) # Initialise automake stuff AM_INIT_AUTOMAKE([-Wall -Werror nostdinc serial-tests]) -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])]) ext_CFLAGS="${CFLAGS+yes}" diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 0304a1a42..240178999 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -1402,9 +1402,14 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) static double timeold = 0.0, timenew = 0.0, timestep = 0.0; bool nodata = FALSE; bool interpolatenow = FALSE; + static bool pass2done = FALSE; + /* If tran with uic and interp, run fileInit_pass2 only once */ if (run->pointCount == 1) { - fileInit_pass2(run); + if (!pass2done) { + fileInit_pass2(run); + pass2done = TRUE; + } timestep = run->circuit->CKTinitTime + run->circuit->CKTstep; } diff --git a/src/spicelib/devices/bsim3v32/Makefile.am b/src/spicelib/devices/bsim3v32/Makefile.am index 0f5818873..3b4b5ca1d 100644 --- a/src/spicelib/devices/bsim3v32/Makefile.am +++ b/src/spicelib/devices/bsim3v32/Makefile.am @@ -24,12 +24,17 @@ libbsim3v32_la_SOURCES = \ bsim3v32ext.h \ bsim3v32init.c \ bsim3v32init.h \ - bsim3v32itf.h + bsim3v32itf.h \ + b3v32ldseq.c \ + b3v32ldsel.c \ + b3v32ldsimd.c \ + vec4_exp.c \ + vec4_log.c -AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -AM_CFLAGS = $(STATIC) +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -DBSIM3v32SIMD +AM_CFLAGS = $(STATIC) -Wall -fno-math-errno -ffast-math MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/bsim3v32/b3v32ld.c b/src/spicelib/devices/bsim3v32/b3v32ld.c index 06c153c32..c114ba6db 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ld.c +++ b/src/spicelib/devices/bsim3v32/b3v32ld.c @@ -10,7 +10,6 @@ * Modified by Xuemei Xi, 10/05, 12/21, 2001. * Modified by Paolo Nenzi 2002 and Dietmar Warning 2003 **********/ - #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" #include "bsim3v32def.h" @@ -70,17 +69,14 @@ double SourceSatCurrent, DrainSatCurrent; double ag0, qgd, qgs, qgb, von, cbhat, VgstNVt, ExpVgst; double cdrain, cdhat, cdreq, ceqbd, ceqbs, ceqqb, ceqqd, ceqqg, ceq, geq; double czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; -double delvbd, delvbs, delvds, delvgd, delvgs; +/* double delvbd, delvbs, delvds, delvgd, delvgs; FB: moved decl into sub block */ double Vfbeff, dVfbeff_dVg, dVfbeff_dVd = 0.0, dVfbeff_dVb, V3, V4; double gcbdb, gcbgb, gcbsb, gcddb, gcdgb, gcdsb, gcgdb, gcggb, gcgsb, gcsdb; -#ifndef NEWCONV -double tol; -#endif +/* FB: moved double to decl into NEWCONV block */ + double gcsgb, gcssb, MJ, MJSW, MJSWG; double vbd, vbs, vds, vgb, vgd, vgs, vgdo; -#ifndef PREDICTOR -double xfact; -#endif +/* FB: xfact decl moved inside PREDICTOR block */ double qgate = 0.0, qbulk = 0.0, qdrn = 0.0, qsrc; double qinoi, cqgate, cqbulk, cqdrn; double Vds, Vgs, Vbs, Gmbs, FwdSum, RevSum; @@ -120,7 +116,7 @@ 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; +/* double Idtot, Ibtot; FB: moved Idtot and Ibtot decl into sub blocks */ #ifndef NOBYPASS double tempv; #endif @@ -211,9 +207,12 @@ for (; model != NULL; model = BSIM3v32nextModel(model)) } else { + double Idtot, Ibtot; + double delvbd, delvbs, delvds, delvgd, delvgs; #ifndef PREDICTOR if ((ckt->CKTmode & MODEINITPRED)) - { xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; + { double xfact; + xfact = ckt->CKTdelta / ckt->CKTdeltaOld[1]; *(ckt->CKTstate0 + here->BSIM3v32vbs) = *(ckt->CKTstate1 + here->BSIM3v32vbs); vbs = (1.0 + xfact)* (*(ckt->CKTstate1 + here->BSIM3v32vbs)) @@ -2747,13 +2746,24 @@ finished: /* * check convergence */ + #ifdef USE_OMP + here->BSIM3v32noncon=0; + #endif if ((here->BSIM3v32off == 0) || (!(ckt->CKTmode & MODEINITFIX))) { if (Check == 1) - { ckt->CKTnoncon++; + { + #ifdef USE_OMP + here->BSIM3v32noncon++; + #else + ckt->CKTnoncon++; + #endif #ifndef NEWCONV } else - { if (here->BSIM3v32mode >= 0) + { + double tol; + double Idtot, Ibtot; + if (here->BSIM3v32mode >= 0) { Idtot = here->BSIM3v32cd + here->BSIM3v32csub - here->BSIM3v32cbd; } else @@ -2769,7 +2779,12 @@ finished: tol = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + ckt->CKTabstol; if (fabs(cbhat - Ibtot) > tol) - { ckt->CKTnoncon++; + { + #ifdef USE_OMP + here->BSIM3v32noncon++; + #else + ckt->CKTnoncon++; + #endif } } #endif /* NEWCONV */ @@ -3172,7 +3187,9 @@ line850: gqdef = gcqgb = gcqdb = gcqsb = gcqbb = 0.0; ggtg = ggtd = ggtb = ggts = 0.0; - sxpart = (1.0 - (dxpart = (here->BSIM3v32mode > 0) ? 0.4 : 0.6)); + /* F.B: moved dxpart assignment outside the following expression */ + dxpart = (here->BSIM3v32mode > 0) ? 0.4 : 0.6; + sxpart = (1.0 - dxpart); ddxpart_dVd = ddxpart_dVg = ddxpart_dVb = ddxpart_dVs = 0.0; dsxpart_dVd = dsxpart_dVg = dsxpart_dVb = dsxpart_dVs = 0.0; @@ -3310,8 +3327,13 @@ line900: here->BSIM3v32rhsD = m * (ceqbd - cdreq - ceqqd); here->BSIM3v32rhsS = m * (cdreq + ceqbs + ceqqg + ceqqb + ceqqd); + #ifndef OMP_EFFMEM if (here->BSIM3v32nqsMod) here->BSIM3v32rhsQ = m * (cqcheq - cqdef); + #else + if (here->BSIM3v32nqsMod) + *(ckt->CKTrhs + here->BSIM3v32qNode) += m * (cqcheq - cqdef); + #endif #else (*(ckt->CKTrhs + here->BSIM3v32gNode) -= m * ceqqg); (*(ckt->CKTrhs + here->BSIM3v32bNode) -= m * (ceqbs + ceqbd + ceqqb)); @@ -3329,27 +3351,17 @@ line900: T1 = qdef * here->BSIM3v32gtau; #ifdef USE_OMP here->BSIM3v32DdPt = m * here->BSIM3v32drainConductance; + here->BSIM3v32SsPt = m * here->BSIM3v32sourceConductance; here->BSIM3v32GgPt = m * (gcggb - ggtg); - here->BSIM3v32SsPt = m * here->BSIM3v32sourceConductance; - here->BSIM3v32BbPt = m * (here->BSIM3v32gbd + here->BSIM3v32gbs + here->BSIM3v32BbPt = m * (here->BSIM3v32gbd + here->BSIM3v32gbs - gcbgb - gcbdb - gcbsb - here->BSIM3v32gbbs); - here->BSIM3v32DPdpPt = m * (here->BSIM3v32drainConductance - + here->BSIM3v32gds + here->BSIM3v32gbd - + RevSum + gcddb + dxpart * ggtd - + T1 * ddxpart_dVd + gbdpdp); - here->BSIM3v32SPspPt = m * (here->BSIM3v32sourceConductance - + here->BSIM3v32gds + here->BSIM3v32gbs - + FwdSum + gcssb + sxpart * ggts - + T1 * dsxpart_dVs + gbspsp); - here->BSIM3v32DdpPt = m * here->BSIM3v32drainConductance; + here->BSIM3v32GbPt = m * (gcggb + gcgdb + gcgsb + ggtb); here->BSIM3v32GdpPt = m * (gcgdb - ggtd); here->BSIM3v32GspPt = m * (gcgsb - ggts); - here->BSIM3v32SspPt = m * here->BSIM3v32sourceConductance; here->BSIM3v32BgPt = m * (gcbgb - here->BSIM3v32gbgs); here->BSIM3v32BdpPt = m * (gcbdb - here->BSIM3v32gbd + gbbdp); here->BSIM3v32BspPt = m * (gcbsb - here->BSIM3v32gbs + gbbsp); - here->BSIM3v32DPdPt = m * here->BSIM3v32drainConductance; here->BSIM3v32DPgPt = m * (Gm + gcdgb + dxpart * ggtg + T1 * ddxpart_dVg + gbdpg); here->BSIM3v32DPbPt = m * (here->BSIM3v32gbd - Gmbs + gcdgb + gcddb @@ -3359,14 +3371,25 @@ line900: - dxpart * ggts - T1 * ddxpart_dVs - gbdpsp); here->BSIM3v32SPgPt = m * (gcsgb - Gm + sxpart * ggtg + T1 * dsxpart_dVg + gbspg); - here->BSIM3v32SPsPt = m * here->BSIM3v32sourceConductance; here->BSIM3v32SPbPt = m * (here->BSIM3v32gbs + Gmbs + gcsgb + gcsdb + gcssb - sxpart * ggtb - T1 * dsxpart_dVb - gbspb); here->BSIM3v32SPdpPt = m * (here->BSIM3v32gds + RevSum - gcsdb - sxpart * ggtd - T1 * dsxpart_dVd - gbspdp); - - if (here->BSIM3v32nqsMod) + here->BSIM3v32DPdpPt = m * (here->BSIM3v32drainConductance + + here->BSIM3v32gds + here->BSIM3v32gbd + + RevSum + gcddb + dxpart * ggtd + + T1 * ddxpart_dVd + gbdpdp); + here->BSIM3v32SPspPt = m * (here->BSIM3v32sourceConductance + + here->BSIM3v32gds + here->BSIM3v32gbs + + FwdSum + gcssb + sxpart * ggts + + T1 * dsxpart_dVs + gbspsp); + here->BSIM3v32DdpPt = m * here->BSIM3v32drainConductance; + here->BSIM3v32SspPt = m * here->BSIM3v32sourceConductance; + here->BSIM3v32DPdPt = m * here->BSIM3v32drainConductance; + here->BSIM3v32SPsPt = m * here->BSIM3v32sourceConductance; + #ifndef OMP_EFFMEM + if (here->BSIM3v32nqsMod) { here->BSIM3v32QqPt = m * (gqdef + here->BSIM3v32gtau); @@ -3379,7 +3402,24 @@ line900: here->BSIM3v32QspPt = m * (ggts - gcqsb); here->BSIM3v32QbPt = m * (ggtb - gcqbb); } -#else + #else + if (here->BSIM3v32nqsMod) + { + *(here->BSIM3v32QqPtr) += m * (gqdef + here->BSIM3v32gtau); + + *(here->BSIM3v32DPqPtr) += m * (dxpart * here->BSIM3v32gtau); + *(here->BSIM3v32SPqPtr) += m * (sxpart * here->BSIM3v32gtau); + *(here->BSIM3v32GqPtr) -= m * here->BSIM3v32gtau; + + *(here->BSIM3v32QgPtr) += m * (ggtg - gcqgb); + *(here->BSIM3v32QdpPtr) += m * (ggtd - gcqdb); + *(here->BSIM3v32QspPtr) += m * (ggts - gcqsb); + *(here->BSIM3v32QbPtr) += m * (ggtb - gcqbb); + } + #endif +#endif /* ifdef USE_OMP */ + +#ifndef USE_OMP (*(here->BSIM3v32DdPtr) += m * here->BSIM3v32drainConductance); (*(here->BSIM3v32GgPtr) += m * (gcggb - ggtg)); (*(here->BSIM3v32SsPtr) += m * here->BSIM3v32sourceConductance); @@ -3457,14 +3497,18 @@ void BSIM3v32LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) for (idx = 0; idx < InstCount; idx++) { here = InstArray[idx]; model = BSIM3v32modPtr(here); + /* F.B. Update non convergence count */ + ckt->CKTnoncon += here->BSIM3v32noncon; /* Update b for Ax = b */ (*(ckt->CKTrhs + here->BSIM3v32gNode) -= here->BSIM3v32rhsG); (*(ckt->CKTrhs + here->BSIM3v32bNode) -= here->BSIM3v32rhsB); (*(ckt->CKTrhs + here->BSIM3v32dNodePrime) += here->BSIM3v32rhsD); (*(ckt->CKTrhs + here->BSIM3v32sNodePrime) += here->BSIM3v32rhsS); + #ifndef OMP_EFFMEM if (here->BSIM3v32nqsMod) (*(ckt->CKTrhs + here->BSIM3v32qNode) += here->BSIM3v32rhsQ); - + #endif + /* Update A for Ax = b */ (*(here->BSIM3v32DdPtr) += here->BSIM3v32DdPt); (*(here->BSIM3v32GgPtr) += here->BSIM3v32GgPt); @@ -3488,7 +3532,8 @@ void BSIM3v32LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) (*(here->BSIM3v32SPsPtr) -= here->BSIM3v32SPsPt); (*(here->BSIM3v32SPbPtr) -= here->BSIM3v32SPbPt); (*(here->BSIM3v32SPdpPtr) -= here->BSIM3v32SPdpPt); - + + #ifndef OMP_EFFMEM if (here->BSIM3v32nqsMod) { *(here->BSIM3v32QqPtr) += here->BSIM3v32QqPt; @@ -3502,6 +3547,7 @@ void BSIM3v32LoadRhsMat(GENmodel *inModel, CKTcircuit *ckt) *(here->BSIM3v32QspPtr) += here->BSIM3v32QspPt; *(here->BSIM3v32QbPtr) += here->BSIM3v32QbPt; } + #endif } } diff --git a/src/spicelib/devices/bsim3v32/b3v32set.c b/src/spicelib/devices/bsim3v32/b3v32set.c index 919b0f2ee..a77246046 100644 --- a/src/spicelib/devices/bsim3v32/b3v32set.c +++ b/src/spicelib/devices/bsim3v32/b3v32set.c @@ -6,6 +6,7 @@ * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi + * Modified by Florian Ballenegger 2020 (for SIMD evaluation) **********/ #include "ngspice/ngspice.h" @@ -39,7 +40,7 @@ CKTnode *tmp; CKTnode *tmpNode; IFuid tmpName; -#ifdef USE_OMP +#if defined(USE_OMP) || defined(BSIM3v32SIMD) int idx, InstCount; BSIM3v32instance **InstArray; #endif @@ -1034,7 +1035,7 @@ BSIM3v32instance **InstArray; /* process drain series resistance */ if (DrainResistance != 0) { - if(here->BSIM3v32dNodePrime == 0) { + if(here->BSIM3v32dNodePrime == 0) { error = CKTmkVolt(ckt,&tmp,here->BSIM3v32name,"drain"); if(error) return(error); here->BSIM3v32dNodePrime = tmp->number; @@ -1135,7 +1136,7 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ } } -#ifdef USE_OMP +#if defined(USE_OMP) || defined(BSIM3v32SIMD) InstCount = 0; model = (BSIM3v32model*)inModel; /* loop through all the BSIM3 device models @@ -1157,6 +1158,7 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ /* store this in the first model only */ model->BSIM3v32InstCount = InstCount; model->BSIM3v32InstanceArray = InstArray; +#ifndef BSIM3v32SIMD idx = 0; for (; model != NULL; model = BSIM3v32nextModel(model)) { @@ -1168,7 +1170,45 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ idx++; } } +#else + idx=0; + int ngroups=0; + for (; model != NULL; model = BSIM3v32nextModel(model)) + { + BSIM3v32group *group; + BSIM3v32instance *first; + model->groupHead=NULL; + first = BSIM3v32instances(model); + while((idxInstArray=&InstArray[idx]; + group->InstArray[0] = first; + group->InstCount=0; + /* build linked list of groups */ + group->next = model->groupHead; + model->groupHead=group; + /* init the for loop below */ + here = first; first=NULL; + for (; here != NULL; here = BSIM3v32nextInstance(here)) + { + if((here->BSIM3v32nqsMod == group->InstArray[0]->BSIM3v32nqsMod) + && (here->pParam == group->InstArray[0]->pParam) /* compare if pParam point to the same */ + && (here->BSIM3v32geo == group->InstArray[0]->BSIM3v32geo) + && (here->BSIM3v32off == group->InstArray[0]->BSIM3v32off) ) + { /* instance can be grouped with the current group */ + InstArray[idx++] = here; + group->InstCount++; + } + else if (first!=NULL) + first=here; /* first different instance, start from here at next while iteration */ + } + } + } + printf("BSIM3v32 has %d groups\n",ngroups); +#endif #endif return(OK); } @@ -1181,14 +1221,20 @@ BSIM3v32unsetup( BSIM3v32model *model; BSIM3v32instance *here; -#ifdef USE_OMP - model = (BSIM3v32model*)inModel; - tfree(model->BSIM3v32InstanceArray); -#endif + for (model = (BSIM3v32model *)inModel; model != NULL; model = BSIM3v32nextModel(model)) { +#ifdef BSIM3v32SIMD + BSIM3v32group *group,*ngroup; + group=model->groupHead; + while(group) { + ngroup=group->next; + tfree(group); + group=ngroup; + } +#endif for (here = BSIM3v32instances(model); here != NULL; here=BSIM3v32nextInstance(here)) { @@ -1207,6 +1253,12 @@ BSIM3v32unsetup( here->BSIM3v32dNodePrime = 0; } } + +#if defined(USE_OMP) || defined(BSIM3v32SIMD) + model = (BSIM3v32model*)inModel; + tfree(model->BSIM3v32InstanceArray); +#endif + return OK; } diff --git a/src/spicelib/devices/bsim3v32/bsim3v32def.h b/src/spicelib/devices/bsim3v32/bsim3v32def.h index 85192c57f..d5db6e4a4 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32def.h +++ b/src/spicelib/devices/bsim3v32/bsim3v32def.h @@ -4,6 +4,7 @@ Author: 1995 Min-Chie Jeng and Mansun Chan. Author: 1997-1999 Weidong Liu. Author: 2001 Xuemei Xi Modified by Paolo Nenzi 2002 and Dietmar Warning 2003 +Modified by Florian Ballenegger 2020 (for SIMD evaluation) File: bsim3v32def.h **********/ @@ -16,6 +17,10 @@ File: bsim3v32def.h #include "ngspice/complex.h" #include "ngspice/noisedef.h" +#ifdef BSIM3v32SIMD +#define NSIMD 4 +#endif + typedef struct sBSIM3v32instance { @@ -36,7 +41,7 @@ typedef struct sBSIM3v32instance /* MCJ */ double BSIM3v32ueff; - double BSIM3v32thetavth; + double BSIM3v32thetavth; /* F.B. It is not useful to store this here, should be removed */ double BSIM3v32von; double BSIM3v32vdsat; double BSIM3v32cgdo; @@ -174,15 +179,29 @@ typedef struct sBSIM3v32instance double *BSIM3v32GqPtr; double *BSIM3v32SPqPtr; double *BSIM3v32BqPtr; - +#ifdef USE_OMP +#ifdef BSIM3v32SIMD + /* store here values calculated before SIMD evaluation really start */ + double BSIM3v32SIMDvbs; + double BSIM3v32SIMDvgs; + double BSIM3v32SIMDvds; + double BSIM3v32SIMDqdef; + double BSIM3v32SIMDcdhat; + double BSIM3v32SIMDcbhat; + int BSIM3v32SIMDCheck; +#endif +#endif #ifdef USE_OMP /* per instance storage of results, to update matrix at a later stge */ + int BSIM3v32noncon; /* F.B. bug fix potential race when writing ckt->CKTnoncon */ double BSIM3v32rhsG; double BSIM3v32rhsB; double BSIM3v32rhsD; double BSIM3v32rhsS; + #ifndef OMP_EFFMEM double BSIM3v32rhsQ; - + #endif + double BSIM3v32DdPt; double BSIM3v32GgPt; double BSIM3v32SsPt; @@ -205,7 +224,7 @@ typedef struct sBSIM3v32instance double BSIM3v32DPbPt; double BSIM3v32SPbPt; double BSIM3v32SPdpPt; - + #ifndef OMP_EFFMEM double BSIM3v32QqPt; double BSIM3v32QdpPt; double BSIM3v32QgPt; @@ -215,6 +234,7 @@ typedef struct sBSIM3v32instance double BSIM3v32GqPt; double BSIM3v32SPqPt; double BSIM3v32BqPt; + #endif #endif #define BSIM3v32vbd BSIM3v32states+ 0 @@ -397,6 +417,16 @@ struct bsim3v32SizeDependParam struct bsim3v32SizeDependParam *pNext; }; +#ifdef BSIM3v32SIMD +/* Group by same pParam, nqsMode, geo, off for more efficient SIMD processing */ +typedef struct sBSIM3v32group { + int InstCount; + int EvalCount; + int SimdCount; + BSIM3v32instance** InstArray; /* actually sub-array of one allocated array globally */ + struct sBSIM3v32group* next; +} BSIM3v32group; +#endif typedef struct sBSIM3v32model { @@ -887,8 +917,12 @@ typedef struct sBSIM3v32model double BSIM3v32vbdrMax; struct bsim3v32SizeDependParam *pSizeDependParamKnot; + +#ifdef BSIM3v32SIMD + BSIM3v32group* groupHead; +#endif -#ifdef USE_OMP +#if defined(USE_OMP) || defined(BSIM3v32SIMD) int BSIM3v32InstCount; struct sBSIM3v32instance **BSIM3v32InstanceArray; #endif diff --git a/src/spicelib/devices/bsim3v32/bsim3v32ext.h b/src/spicelib/devices/bsim3v32/bsim3v32ext.h index 1612149da..a27ddaed4 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32ext.h +++ b/src/spicelib/devices/bsim3v32/bsim3v32ext.h @@ -28,3 +28,9 @@ extern int BSIM3v32trunc(GENmodel*,CKTcircuit*,double*); extern int BSIM3v32noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BSIM3v32unsetup(GENmodel*,CKTcircuit*); extern int BSIM3v32soaCheck(CKTcircuit *, GENmodel *); +#ifndef BSIM3v32SIMD +#define BSIM3v32SIMD +#endif +#ifdef BSIM3v32SIMD +extern int BSIM3v32loadSel(GENmodel*,CKTcircuit*); +#endif diff --git a/src/spicelib/devices/bsim3v32/bsim3v32init.c b/src/spicelib/devices/bsim3v32/bsim3v32init.c index aaeb71c9b..78f83b3c6 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32init.c +++ b/src/spicelib/devices/bsim3v32/bsim3v32init.c @@ -33,7 +33,11 @@ SPICEdev BSIM3v32info = { .DEVparam = BSIM3v32param, .DEVmodParam = BSIM3v32mParam, +#ifdef BSIM3v32SIMD + .DEVload = BSIM3v32loadSel, /*F.B: point to load function wrapper */ +#else .DEVload = BSIM3v32load, +#endif .DEVsetup = BSIM3v32setup, .DEVunsetup = BSIM3v32unsetup, .DEVpzSetup = BSIM3v32setup,