From ecb288138f5ba3bce0a173ab1e0288f55e54984c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Thu, 4 Sep 2025 00:03:25 +0200 Subject: [PATCH 01/20] Fix a bug in the Windows Builds: With commit 80d6e681f ("MS Windows: Get a canonical paths name: Important if path length exceeds MAX_PATH, might happen when using PDKs", 2025-04-12) the newly introduced function get_windows_canonical_path() does not do the right thing when the path name is only a simple file name. Then internally used function GetFullPathNameW() then will prepend the current directory to the file name, which may be simply wrong. --- src/frontend/inpcom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index ff9bb8072..86d2534f7 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -9867,6 +9867,10 @@ char* get_windows_canonical_path(const char* input_path) { return NULL; } + /* If plain filename, just copy it. */ + if (!strchr(input_path, '\\') && !strchr(input_path, '/')) + return copy(input_path); + inputLenMB = (int)strlen(input_path); if (inputLenMB == 0) { From a754cc187b5263bf46627b26ff98d97270c0b775 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Thu, 4 Sep 2025 00:25:26 +0200 Subject: [PATCH 02/20] free(info.errors) leads to a assertion error on the heap. On Windows it reads: is_block_type_valid(header->_block_use). Memory for info.errors is allocated in the osdi device dll during the call to descr->setup_instance((void *)&handle, inst, model, temp, connected_terminals, sim_params, &init_info); (in fcn OSDIsetup(), line 254 of osdisetup.c). Therefore ngspice is not the owner of this memory and thus cannot free it. Fixes bug no. 803. --- src/osdi/osdisetup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/osdi/osdisetup.c b/src/osdi/osdisetup.c index 4feb3ec90..46cabceb5 100644 --- a/src/osdi/osdisetup.c +++ b/src/osdi/osdisetup.c @@ -46,7 +46,6 @@ static int handle_init_info(OsdiInitInfo info, const OsdiDescriptor *descr) { printf("Unknown OSDO init error code %d!\n", err->code); } } - free(info.errors); errMsg = tprintf("%i errors occurred during initialization", info.num_errors); return (E_PRIVATE); } From 4693173d37492c0f2203c00cb8dbc9994e374d75 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 6 Sep 2025 17:46:50 +0200 Subject: [PATCH 03/20] Revert "Fix a bug in the Windows Builds:" This reverts commit ecb288138f5ba3bce0a173ab1e0288f55e54984c. --- src/frontend/inpcom.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 86d2534f7..ff9bb8072 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -9867,10 +9867,6 @@ char* get_windows_canonical_path(const char* input_path) { return NULL; } - /* If plain filename, just copy it. */ - if (!strchr(input_path, '\\') && !strchr(input_path, '/')) - return copy(input_path); - inputLenMB = (int)strlen(input_path); if (inputLenMB == 0) { From aa3ab5bc2553d22cd85a725934e7e387274b98a3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 5 Sep 2025 23:59:05 +0200 Subject: [PATCH 04/20] Fixing bug 804. Using function get_windows_canonical_path() may neglect the ngspice file search sequence, as an absolute path is returned also for relative input paths. ngspice however searches a file not only relative to the current directory, as inforced by this function, but for example also in the directory of the previous input file. So restrict this function to paths longer than MAX_PATH, which would fail otherwise. --- src/frontend/inpcom.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index ff9bb8072..71a3bdeaf 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -9844,6 +9844,10 @@ static void inp_meas_control(struct card* card) * might need to add the prefix separately if using the result in APIs * that require it for long path support. * + * Using this function however may neglect the ngspice file search sequence, + * as an absolute path is returned also for relative paths. + * So restrict this function to paths longer than MAX_PATH. + * * @param input_path The input path string (UTF-8 encoded). Can be relative or * absolute, may contain '.' or '..'. * @return char* A newly allocated UTF-8 string containing the canonical absolute @@ -9869,6 +9873,10 @@ char* get_windows_canonical_path(const char* input_path) { inputLenMB = (int)strlen(input_path); + /* If path length is less than MAX_PATH, just copy and return path. */ + if (inputLenMB < MAX_PATH) + return copy(input_path); + if (inputLenMB == 0) { inputLenW = 1; } From 434863651e4456e8e245939636d67bad86748aff Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 7 Sep 2025 18:46:21 +0200 Subject: [PATCH 05/20] Updated as it is on master --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index a9b487200..f0816b363 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +Ngspice-45.2, Sept. 5th, 2025 +============ +- Bug-fix release + + A bug in the MS Windows version has been fixed + (bug no. 804, see https://sourceforge.net/p/ngspice/bugs/804/) + Ngspice-45, August 17th, 2025 ============ - New features: From 0a739f6b762da7ec908f8385e4f45387eecb15e9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 7 Sep 2025 18:49:22 +0200 Subject: [PATCH 06/20] Remove files that are remade anyway. Makefile.in prescribed using aclocal 1.16. The fix removes any dependency on the autotool version. Fixing bug 806. --- autogen.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autogen.sh b/autogen.sh index bd1c3f5a0..2e3b036c7 100755 --- a/autogen.sh +++ b/autogen.sh @@ -115,6 +115,10 @@ fi exit 1 } +echo "Removing files to be remade" +rm -f Makefile.in aclocal.m4 ar-lib config.guess config.sub +rm -f depcomp install-sh ltmain.sh missing ylwrap +rm -r -f autom4te.cache echo "Running $LIBTOOLIZE" $LIBTOOLIZE --copy --force \ From 57dd3342ef53bb0bbd0aca2f847a88e9d695ec2b Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Wed, 3 Sep 2025 16:56:36 -0700 Subject: [PATCH 07/20] Enable CIDER with KLU for DC, OP, and TRAN analyses. Small signal AC analysis is not yet supported for CIDER complex valued device KLU matrices. The examples/cider testcases produce printed simulation result values which have slight differences between Sparse and KLU. Differences are probably expected and in a few cases are ~1-2%, sometimes a little more. This should be good enough for most CIDER analyses. Francesco did a good piece of work. Runtimes are significantly shorter with KLU. --- examples/cider/surfmob/Tbicmpd1.cir | 111 ++++++++++++ examples/cider/surfmob/Tbicmpd1xy.cir | 111 ++++++++++++ examples/cider/surfmob/Tbicmpu1.cir | 105 ++++++++++++ examples/cider/surfmob/Tbicmpu1xy.cir | 105 ++++++++++++ examples/cider/surfmob/cd4007n_200402idvg.net | 159 ++++++++++++++++++ examples/cider/surfmob/cdxy.net | 159 ++++++++++++++++++ examples/cider/surfmob/runtests.sh | 9 + examples/cider/surfmob/spiceinit | 2 + src/ciderlib/oned/oneadmit.c | 38 ++++- src/ciderlib/twod/twoadmit.c | 45 +++++ src/ciderlib/twod/twocont.c | 3 +- src/ciderlib/twod/twoncont.c | 3 +- src/ciderlib/twod/twopcont.c | 3 +- src/spicelib/devices/nbjt/nbjtset.c | 2 +- src/spicelib/devices/nbjt2/nbt2set.c | 2 +- src/spicelib/devices/numd/numdset.c | 2 +- src/spicelib/devices/numd2/nud2set.c | 2 +- src/spicelib/devices/numos/nummset.c | 2 +- 18 files changed, 854 insertions(+), 9 deletions(-) create mode 100644 examples/cider/surfmob/Tbicmpd1.cir create mode 100644 examples/cider/surfmob/Tbicmpd1xy.cir create mode 100644 examples/cider/surfmob/Tbicmpu1.cir create mode 100644 examples/cider/surfmob/Tbicmpu1xy.cir create mode 100644 examples/cider/surfmob/cd4007n_200402idvg.net create mode 100644 examples/cider/surfmob/cdxy.net create mode 100755 examples/cider/surfmob/runtests.sh create mode 100644 examples/cider/surfmob/spiceinit diff --git a/examples/cider/surfmob/Tbicmpd1.cir b/examples/cider/surfmob/Tbicmpd1.cir new file mode 100644 index 000000000..2da793fbf --- /dev/null +++ b/examples/cider/surfmob/Tbicmpd1.cir @@ -0,0 +1,111 @@ +BiCMOS Pulldown Circuit + +VSS 2 0 0v + +VIN 3 2 0v (PULSE 0.0v 4.2v 0ns 1ns 1ns 9ns 20ns) + +M1 8 3 5 11 M_NMOS_1 W=4u L=1u +VD 4 8 0v +VBK 11 2 0v + +Q1 10 7 9 M_NPN AREA=8 +VC 4 10 0v +VB 5 7 0v +VE 9 2 0v + +CL 4 6 1pF +VL 6 2 0v + +.IC V(10)=5.0v V(7)=0.0v +*.TRAN 0.1ns 5ns 0ns 0.1ns +.TRAN 0.1ns 0.3ns 0ns 0.1ns +.PLOT TRAN I(VIN) + +*.include bicmos.lib +.MODEL M_NPN nbjt level=2 ++ title TWO-DIMENSIONAL NUMERICAL POLYSILICON EMITTER BIPOLAR TRANSISTOR ++ * Since, we are only simulating half of a device, we double the unit width ++ * 1.0 um emitter length ++ options defw=2.0u ++ ++ *x.mesh w=2.5 n=5 ++ x.mesh w=2.0 h.e=0.05 h.m=0.2 r=1.5 ++ x.mesh w=0.5 h.s=0.05 h.m=0.1 r=1.5 ++ ++ y.mesh l=-0.2 n=1 ++ y.mesh l= 0.0 n=5 ++ y.mesh w=0.10 h.e=0.002 h.m=0.01 r=1.5 ++ y.mesh w=0.15 h.s=0.002 h.m=0.01 r=1.5 ++ y.mesh w=0.35 h.s=0.01 h.m=0.2 r=1.5 ++ y.mesh w=0.40 h.e=0.05 h.m=0.2 r=1.5 ++ y.mesh w=0.30 h.s=0.05 h.m=0.1 r=1.5 ++ ++ domain num=1 material=1 x.l=2.0 y.h=0.0 ++ domain num=2 material=2 x.h=2.0 y.h=0.0 ++ domain num=3 material=3 y.l=0.0 ++ material num=1 polysilicon ++ material num=2 oxide ++ material num=3 silicon ++ ++ elec num=1 x.l=0.0 x.h=0.0 y.l=1.1 y.h=1.3 ++ elec num=2 x.l=0.0 x.h=0.5 y.l=0.0 y.h=0.0 ++ elec num=3 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=-0.2 ++ ++ doping gauss n.type conc=3e20 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.047 lat.rotate ++ doping gauss p.type conc=1e19 x.l=0.0 x.h=5.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.094 lat.rotate ++ doping unif n.type conc=1e16 x.l=0.0 x.h=5.0 y.l=0.0 y.h=1.3 ++ doping gauss n.type conc=5e19 x.l=0.0 x.h=5.0 y.l=1.3 y.h=1.3 ++ + char.l=0.100 lat.rotate ++ ++ method ac=direct itlim=10 ++ models bgn srh auger conctau concmob fieldmob + +.MODEL M_NMOS_1 numos ++ title 1.0um NMOS Device ++ ++ x.mesh w=0.9 h.e=0.020 h.m=0.2 r=2.0 ++ x.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ x.mesh w=0.4 h.s=0.005 h.m=0.1 r=2.0 ++ x.mesh w=0.4 h.e=0.005 h.m=0.1 r=2.0 ++ x.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ x.mesh w=0.9 h.s=0.020 h.m=0.2 r=2.0 ++ ++ y.mesh l=-.0200 n=1 ++ y.mesh l=0.0 n=6 ++ y.mesh w=0.15 h.s=0.0001 h.max=.02 r=2.0 ++ y.mesh w=0.45 h.s=0.02 h.max=0.2 r=2.0 ++ y.mesh w=1.40 h.s=0.20 h.max=0.4 r=2.0 ++ ++ region num=1 material=1 y.h=0.0 ++ region num=2 material=2 y.l=0.0 ++ interface dom=2 nei=1 x.l=1.0 x.h=2.0 layer.width=0.0 ++ material num=1 oxide ++ material num=2 silicon ++ ++ elec num=1 x.l=2.5 x.h=3.1 y.l=0.0 y.h=0.0 ++ elec num=2 x.l=1.0 x.h=2.0 iy.l=1 iy.h=1 ++ elec num=3 x.l=-0.1 x.h=0.5 y.l=0.0 y.h=0.0 ++ elec num=4 x.l=-0.1 x.h=3.1 y.l=2.0 y.h=2.0 ++ ++ doping gauss p.type conc=1.0e17 x.l=-0.1 x.h=3.1 y.l=0.0 ++ + char.l=0.30 ++ doping unif p.type conc=5.0e15 x.l=-0.1 x.h=3.1 y.l=0.0 y.h=2.1 ++ doping gauss n.type conc=4e17 x.l=-0.1 x.h=1.0 y.l=0.0 y.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss n.type conc=1e20 x.l=-0.1 x.h=0.95 y.l=0.0 y.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ doping gauss n.type conc=4e17 x.l=2.0 x.h=3.1 y.l=0.0 y.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss n.type conc=1e20 x.l=2.05 x.h=3.1 y.l=0.0 y.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ ++ contact num=2 workf=4.10 ++ models concmob fieldmob surfmob srh auger conctau bgn ^aval ++ method ac=direct itlim=10 onec + + +* .OPTIONS ACCT BYPASS=1 filetype=ascii +* .OPTIONS filetype=ascii +.END diff --git a/examples/cider/surfmob/Tbicmpd1xy.cir b/examples/cider/surfmob/Tbicmpd1xy.cir new file mode 100644 index 000000000..12fc7541b --- /dev/null +++ b/examples/cider/surfmob/Tbicmpd1xy.cir @@ -0,0 +1,111 @@ +BiCMOS Pulldown Circuit + +VSS 2 0 0v + +VIN 3 2 0v (PULSE 0.0v 4.2v 0ns 1ns 1ns 9ns 20ns) + +M1 8 3 5 11 M_NMOS_1 W=4u L=1u +VD 4 8 0v +VBK 11 2 0v + +Q1 10 7 9 M_NPN AREA=8 +VC 4 10 0v +VB 5 7 0v +VE 9 2 0v + +CL 4 6 1pF +VL 6 2 0v + +.IC V(10)=5.0v V(7)=0.0v +*.TRAN 0.1ns 5ns 0ns 0.1ns +.TRAN 0.1ns 0.3ns 0ns 0.1ns +.PLOT TRAN I(VIN) + +*.include bicmos.lib +.MODEL M_NPN nbjt level=2 ++ title TWO-DIMENSIONAL NUMERICAL POLYSILICON EMITTER BIPOLAR TRANSISTOR ++ * Since, we are only simulating half of a device, we double the unit width ++ * 1.0 um emitter length ++ options defw=2.0u ++ ++ *y.mesh w=2.5 n=5 ++ y.mesh w=2.0 h.e=0.05 h.m=0.2 r=1.5 ++ y.mesh w=0.5 h.s=0.05 h.m=0.1 r=1.5 ++ ++ x.mesh l=-0.2 n=1 ++ x.mesh l= 0.0 n=5 ++ x.mesh w=0.10 h.e=0.002 h.m=0.01 r=1.5 ++ x.mesh w=0.15 h.s=0.002 h.m=0.01 r=1.5 ++ x.mesh w=0.35 h.s=0.01 h.m=0.2 r=1.5 ++ x.mesh w=0.40 h.e=0.05 h.m=0.2 r=1.5 ++ x.mesh w=0.30 h.s=0.05 h.m=0.1 r=1.5 ++ ++ domain num=1 material=1 y.l=2.0 x.h=0.0 ++ domain num=2 material=2 y.h=2.0 x.h=0.0 ++ domain num=3 material=3 x.l=0.0 ++ material num=1 polysilicon ++ material num=2 oxide ++ material num=3 silicon ++ ++ elec num=1 y.l=0.0 y.h=0.0 x.l=1.1 x.h=1.3 ++ elec num=2 y.l=0.0 y.h=0.5 x.l=0.0 x.h=0.0 ++ elec num=3 y.l=2.0 y.h=3.0 x.l=-0.2 x.h=-0.2 ++ ++ doping gauss n.type conc=3e20 y.l=2.0 y.h=3.0 x.l=-0.2 x.h=0.0 ++ + char.l=0.047 lat.rotate ++ doping gauss p.type conc=1e19 y.l=0.0 y.h=5.0 x.l=-0.2 x.h=0.0 ++ + char.l=0.094 lat.rotate ++ doping unif n.type conc=1e16 y.l=0.0 y.h=5.0 x.l=0.0 x.h=1.3 ++ doping gauss n.type conc=5e19 y.l=0.0 y.h=5.0 x.l=1.3 x.h=1.3 ++ + char.l=0.100 lat.rotate ++ ++ method ac=direct itlim=10 ++ models bgn srh auger conctau concmob fieldmob + +.MODEL M_NMOS_1 numos ++ title 1.0um NMOS Device ++ ++ y.mesh w=0.9 h.e=0.020 h.m=0.2 r=2.0 ++ y.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ y.mesh w=0.4 h.s=0.005 h.m=0.1 r=2.0 ++ y.mesh w=0.4 h.e=0.005 h.m=0.1 r=2.0 ++ y.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ y.mesh w=0.9 h.s=0.020 h.m=0.2 r=2.0 ++ ++ x.mesh l=-.0200 n=1 ++ x.mesh l=0.0 n=6 ++ x.mesh w=0.15 h.s=0.0001 h.max=.02 r=2.0 ++ x.mesh w=0.45 h.s=0.02 h.max=0.2 r=2.0 ++ x.mesh w=1.40 h.s=0.20 h.max=0.4 r=2.0 ++ ++ region num=1 material=1 x.h=0.0 ++ region num=2 material=2 x.l=0.0 ++ interface dom=2 nei=1 y.l=1.0 y.h=2.0 layer.width=0.0 ++ material num=1 oxide ++ material num=2 silicon ++ ++ elec num=1 y.l=2.5 y.h=3.1 x.l=0.0 x.h=0.0 ++ elec num=2 y.l=1.0 y.h=2.0 ix.l=1 ix.h=1 ++ elec num=3 y.l=-0.1 y.h=0.5 x.l=0.0 x.h=0.0 ++ elec num=4 y.l=-0.1 y.h=3.1 x.l=2.0 x.h=2.0 ++ ++ doping gauss p.type conc=1.0e17 y.l=-0.1 y.h=3.1 x.l=0.0 ++ + char.l=0.30 ++ doping unif p.type conc=5.0e15 y.l=-0.1 y.h=3.1 x.l=0.0 x.h=2.1 ++ doping gauss n.type conc=4e17 y.l=-0.1 y.h=1.0 x.l=0.0 x.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss n.type conc=1e20 y.l=-0.1 y.h=0.95 x.l=0.0 x.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ doping gauss n.type conc=4e17 y.l=2.0 y.h=3.1 x.l=0.0 x.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss n.type conc=1e20 y.l=2.05 y.h=3.1 x.l=0.0 x.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ ++ contact num=2 workf=4.10 ++ models concmob fieldmob surfmob srh auger conctau bgn ^aval ++ method ac=direct itlim=10 onec + + +* .OPTIONS ACCT BYPASS=1 filetype=ascii +* .OPTIONS filetype=ascii +.END diff --git a/examples/cider/surfmob/Tbicmpu1.cir b/examples/cider/surfmob/Tbicmpu1.cir new file mode 100644 index 000000000..d1e381786 --- /dev/null +++ b/examples/cider/surfmob/Tbicmpu1.cir @@ -0,0 +1,105 @@ +BICMOS INVERTER PULLUP CIRCUIT + +VDD 1 0 5.0V +VSS 2 0 0.0V + +VIN 3 0 0.75V + +VC 1 11 0.0V +VB 5 15 0.0V + +Q1 11 15 4 M_NPNS AREA=8 +M1 5 3 1 1 M_PMOS_1 W=10U L=1U + +CL 4 0 5.0PF + +.IC V(4)=0.75V V(5)=0.0V + +.MODEL M_NPNS nbjt level=2 ++ title TWO-DIMENSIONAL NUMERICAL POLYSILICON EMITTER BIPOLAR TRANSISTOR ++ * Since half the device is simulated, double the unit width to get ++ * 1.0 um emitter. Use a small mesh for this model. ++ options defw=2.0u ++ ++ x.mesh w=2.0 h.e=0.02 h.m=0.5 r=2.0 ++ x.mesh w=0.5 h.s=0.02 h.m=0.2 r=2.0 ++ ++ y.mesh l=-0.2 n=1 ++ y.mesh l= 0.0 n=5 ++ y.mesh w=0.10 h.e=0.004 h.m=0.05 r=2.5 ++ y.mesh w=0.15 h.s=0.004 h.m=0.02 r=2.5 ++ y.mesh w=1.05 h.s=0.02 h.m=0.1 r=2.5 ++ ++ domain num=1 material=1 x.l=2.0 y.h=0.0 ++ domain num=2 material=2 x.h=2.0 y.h=0.0 ++ domain num=3 material=3 y.l=0.0 ++ material num=1 polysilicon ++ material num=2 oxide ++ material num=3 silicon ++ ++ elec num=1 x.l=0.0 x.h=0.0 y.l=1.1 y.h=1.3 ++ elec num=2 x.l=0.0 x.h=0.5 y.l=0.0 y.h=0.0 ++ elec num=3 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=-0.2 ++ ++ doping gauss n.type conc=3e20 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.047 lat.rotate ++ doping gauss p.type conc=5e18 x.l=0.0 x.h=5.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.100 lat.rotate ++ doping gauss p.type conc=1e20 x.l=0.0 x.h=0.5 y.l=-0.2 y.h=0.0 ++ + char.l=0.100 lat.rotate ratio=0.7 ++ doping unif n.type conc=1e16 x.l=0.0 x.h=5.0 y.l=0.0 y.h=1.3 ++ doping gauss n.type conc=5e19 x.l=0.0 x.h=5.0 y.l=1.3 y.h=1.3 ++ + char.l=0.100 lat.rotate ++ ++ method ac=direct itlim=10 ++ models bgn srh auger conctau concmob fieldmob + +.MODEL M_PMOS_1 numos ++ ++ x.mesh w=0.9 h.e=0.020 h.m=0.2 r=2.0 ++ x.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ x.mesh w=0.4 h.s=0.005 h.m=0.1 r=2.0 ++ x.mesh w=0.4 h.e=0.005 h.m=0.1 r=2.0 ++ x.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ x.mesh w=0.9 h.s=0.020 h.m=0.2 r=2.0 ++ ++ y.mesh l=-.0200 n=1 ++ y.mesh l=0.0 n=6 ++ y.mesh w=0.15 h.s=0.0001 h.max=.02 r=2.0 ++ y.mesh w=0.45 h.s=0.02 h.max=0.2 r=2.0 ++ y.mesh w=1.40 h.s=0.20 h.max=0.4 r=2.0 ++ ++ region num=1 material=1 y.h=0.0 ++ region num=2 material=2 y.l=0.0 ++ interface dom=2 nei=1 x.l=1 x.h=2 layer.width=0.0 ++ material num=1 oxide ++ material num=2 silicon ++ ++ elec num=1 x.l=2.5 x.h=3.1 y.l=0.0 y.h=0.0 ++ elec num=2 x.l=1 x.h=2 iy.l=1 iy.h=1 ++ elec num=3 x.l=-0.1 x.h=0.5 y.l=0.0 y.h=0.0 ++ elec num=4 x.l=-0.1 x.h=3.1 y.l=2.0 y.h=2.0 ++ ++ doping gauss n.type conc=1.0e17 x.l=-0.1 x.h=3.1 y.l=0.0 ++ + char.l=0.30 ++ doping unif n.type conc=5.0e15 x.l=-0.1 x.h=3.1 y.l=0.0 y.h=2.1 ++ doping gauss p.type conc=4e17 x.l=-0.1 x.h=1 y.l=0.0 y.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss p.type conc=1e20 x.l=-0.1 x.h=0.95 y.l=0.0 y.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ doping gauss p.type conc=4e17 x.l=2 x.h=3.1 y.l=0.0 y.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss p.type conc=1e20 x.l=2.05 x.h=3.1 y.l=0.0 y.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ ++ contact num=2 workf=5.29 ++ models concmob surfmob transmob fieldmob srh auger conctau bgn ++ method ac=direct itlim=10 onec + + +.TRAN 0.5NS 3.0NS +.PRINT TRAN V(3) V(4) +.PLOT TRAN V(3) V(4) + +* .OPTION ACCT BYPASS=1 +.END diff --git a/examples/cider/surfmob/Tbicmpu1xy.cir b/examples/cider/surfmob/Tbicmpu1xy.cir new file mode 100644 index 000000000..229ea31db --- /dev/null +++ b/examples/cider/surfmob/Tbicmpu1xy.cir @@ -0,0 +1,105 @@ +BICMOS INVERTER PULLUP CIRCUIT + +VDD 1 0 5.0V +VSS 2 0 0.0V + +VIN 3 0 0.75V + +VC 1 11 0.0V +VB 5 15 0.0V + +Q1 11 15 4 M_NPNS AREA=8 +M1 5 3 1 1 M_PMOS_1 W=10U L=1U + +CL 4 0 5.0PF + +.IC V(4)=0.75V V(5)=0.0V + +.MODEL M_NPNS nbjt level=2 ++ title TWO-DIMENSIONAL NUMERICAL POLYSILICON EMITTER BIPOLAR TRANSISTOR ++ * Since half the device is simulated, double the unit width to get ++ * 1.0 um emitter. Use a small mesh for this model. ++ options defw=2.0u ++ ++ x.mesh w=2.0 h.e=0.02 h.m=0.5 r=2.0 ++ x.mesh w=0.5 h.s=0.02 h.m=0.2 r=2.0 ++ ++ y.mesh l=-0.2 n=1 ++ y.mesh l= 0.0 n=5 ++ y.mesh w=0.10 h.e=0.004 h.m=0.05 r=2.5 ++ y.mesh w=0.15 h.s=0.004 h.m=0.02 r=2.5 ++ y.mesh w=1.05 h.s=0.02 h.m=0.1 r=2.5 ++ ++ domain num=1 material=1 x.l=2.0 y.h=0.0 ++ domain num=2 material=2 x.h=2.0 y.h=0.0 ++ domain num=3 material=3 y.l=0.0 ++ material num=1 polysilicon ++ material num=2 oxide ++ material num=3 silicon ++ ++ elec num=1 x.l=0.0 x.h=0.0 y.l=1.1 y.h=1.3 ++ elec num=2 x.l=0.0 x.h=0.5 y.l=0.0 y.h=0.0 ++ elec num=3 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=-0.2 ++ ++ doping gauss n.type conc=3e20 x.l=2.0 x.h=3.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.047 lat.rotate ++ doping gauss p.type conc=5e18 x.l=0.0 x.h=5.0 y.l=-0.2 y.h=0.0 ++ + char.l=0.100 lat.rotate ++ doping gauss p.type conc=1e20 x.l=0.0 x.h=0.5 y.l=-0.2 y.h=0.0 ++ + char.l=0.100 lat.rotate ratio=0.7 ++ doping unif n.type conc=1e16 x.l=0.0 x.h=5.0 y.l=0.0 y.h=1.3 ++ doping gauss n.type conc=5e19 x.l=0.0 x.h=5.0 y.l=1.3 y.h=1.3 ++ + char.l=0.100 lat.rotate ++ ++ method ac=direct itlim=10 ++ models bgn srh auger conctau concmob fieldmob + +.MODEL M_PMOS_1 numos ++ ++ y.mesh w=0.9 h.e=0.020 h.m=0.2 r=2.0 ++ y.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ y.mesh w=0.4 h.s=0.005 h.m=0.1 r=2.0 ++ y.mesh w=0.4 h.e=0.005 h.m=0.1 r=2.0 ++ y.mesh w=0.2 h.e=0.005 h.m=0.02 r=2.0 ++ y.mesh w=0.9 h.s=0.020 h.m=0.2 r=2.0 ++ ++ x.mesh l=-.0200 n=1 ++ x.mesh l=0.0 n=6 ++ x.mesh w=0.15 h.s=0.0001 h.max=.02 r=2.0 ++ x.mesh w=0.45 h.s=0.02 h.max=0.2 r=2.0 ++ x.mesh w=1.40 h.s=0.20 h.max=0.4 r=2.0 ++ ++ region num=1 material=1 x.h=0.0 ++ region num=2 material=2 x.l=0.0 ++ interface dom=2 nei=1 y.l=1 y.h=2 layer.width=0.0 ++ material num=1 oxide ++ material num=2 silicon ++ ++ elec num=1 y.l=2.5 y.h=3.1 x.l=0.0 x.h=0.0 ++ elec num=2 y.l=1 y.h=2 ix.l=1 ix.h=1 ++ elec num=3 y.l=-0.1 y.h=0.5 x.l=0.0 x.h=0.0 ++ elec num=4 y.l=-0.1 y.h=3.1 x.l=2.0 x.h=2.0 ++ ++ doping gauss n.type conc=1.0e17 y.l=-0.1 y.h=3.1 x.l=0.0 ++ + char.l=0.30 ++ doping unif n.type conc=5.0e15 y.l=-0.1 y.h=3.1 x.l=0.0 x.h=2.1 ++ doping gauss p.type conc=4e17 y.l=-0.1 y.h=1 x.l=0.0 x.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss p.type conc=1e20 y.l=-0.1 y.h=0.95 x.l=0.0 x.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ doping gauss p.type conc=4e17 y.l=2 y.h=3.1 x.l=0.0 x.h=0.0 ++ + char.l=0.16 lat.rotate ratio=0.65 ++ doping gauss p.type conc=1e20 y.l=2.05 y.h=3.1 x.l=0.0 x.h=0.08 ++ + char.l=0.03 lat.rotate ratio=0.65 ++ ++ contact num=2 workf=5.29 ++ models concmob surfmob transmob fieldmob srh auger conctau bgn ++ method ac=direct itlim=10 onec + + +.TRAN 0.5NS 3.0NS +.PRINT TRAN V(3) V(4) +.PLOT TRAN V(3) V(4) + +* .OPTION ACCT BYPASS=1 +.END diff --git a/examples/cider/surfmob/cd4007n_200402idvg.net b/examples/cider/surfmob/cd4007n_200402idvg.net new file mode 100644 index 000000000..6d8c45e1a --- /dev/null +++ b/examples/cider/surfmob/cd4007n_200402idvg.net @@ -0,0 +1,159 @@ +$ CD4007, version: cd4007n_200402idvg +$ Generated using Matlab automation script. + + +$ BEGIN CIDER + +.model CD4007UBENUMOSN numos +$ -- x Grid +$ ---- GOX ++ x.mesh (location = -64.0000e-3) (node = 1) ++ x.mesh (location = -48.0000e-3) (node = 2) ++ x.mesh (location = -32.0000e-3) (node = 3) ++ x.mesh (location = -16.0000e-3) (node = 4) ++ x.mesh (location = 0.0000e-3) (node = 5) +$ ---- Channel and S/D ++ x.mesh (location = 20.0000e-3) (node = 6) ++ x.mesh (location = 48.4511e-3) (node = 7) ++ x.mesh (location = 86.9893e-3) (node = 8) ++ x.mesh (location = 139.1911e-3) (node = 9) ++ x.mesh (location = 209.9008e-3) (node = 10) ++ x.mesh (location = 305.6803e-3) (node = 11) ++ x.mesh (location = 435.4180e-3) (node = 12) ++ x.mesh (location = 611.1537e-3) (node = 13) ++ x.mesh (location = 849.1956e-3) (node = 14) ++ x.mesh (location = 1171.6341e-3) (node = 15) ++ x.mesh (location = 1608.3918e-3) (node = 16) ++ x.mesh (location = 2200.0000e-3) (node = 17) ++ x.mesh (location = 3000.0000e-3) (node = 18) +$ ---- Mid substrate ++ x.mesh (location = 3800.0000e-3) (node = 19) ++ x.mesh (location = 4911.8170e-3) (node = 20) ++ x.mesh (location = 6290.4701e-3) (node = 21) ++ x.mesh (location = 8000.0000e-3) (node = 22) ++ x.mesh (location = 10000.0000e-3) (node = 23) ++ +$ -- y Grid +$ ---- Body well ++ y.mesh (location = -35000.0000e-3) (node = 1) ++ y.mesh (location = -30000.0000e-3) (node = 2) ++ y.mesh (location = -25000.0000e-3) (node = 3) ++ y.mesh (location = -20000.0000e-3) (node = 4) +$ ---- Body-Source ++ y.mesh (location = -17500.0000e-3) (node = 5) ++ y.mesh (location = -15000.0000e-3) (node = 6) ++ y.mesh (location = -12500.0000e-3) (node = 7) ++ y.mesh (location = -10000.0000e-3) (node = 8) +$ ---- Mid source ++ y.mesh (location = -7500.0000e-3) (node = 9) ++ y.mesh (location = -4980.0000e-3) (node = 10) ++ y.mesh (location = -3000.0000e-3) (node = 11) ++ y.mesh (location = -2000.0000e-3) (node = 12) +$ ---- Near source ++ y.mesh (location = -1000.0000e-3) (node = 13) ++ y.mesh (location = -200.0000e-3) (node = 14) ++ y.mesh (location = 0.0000e-3) (node = 15) +$ ---- Channel near source ++ y.mesh (location = 200.0000e-3) (node = 16) ++ y.mesh (location = 442.1759e-3) (node = 17) ++ y.mesh (location = 732.7869e-3) (node = 18) ++ y.mesh (location = 1081.5201e-3) (node = 19) ++ y.mesh (location = 1500.0000e-3) (node = 20) ++ y.mesh (location = 2000.0000e-3) (node = 21) +$ ---- Channel center ++ y.mesh (location = 2500.0000e-3) (node = 22) ++ y.mesh (location = 3000.0000e-3) (node = 23) ++ y.mesh (location = 3500.0000e-3) (node = 24) ++ y.mesh (location = 4000.0000e-3) (node = 25) ++ y.mesh (location = 4500.0000e-3) (node = 26) ++ y.mesh (location = 5000.0000e-3) (node = 27) +$ ---- Channel near drain ++ y.mesh (location = 5500.0000e-3) (node = 28) ++ y.mesh (location = 5961.8362e-3) (node = 29) ++ y.mesh (location = 6376.3046e-3) (node = 30) ++ y.mesh (location = 6748.2634e-3) (node = 31) ++ y.mesh (location = 7082.0725e-3) (node = 32) ++ y.mesh (location = 7381.6449e-3) (node = 33) ++ y.mesh (location = 7650.4919e-3) (node = 34) ++ y.mesh (location = 7891.7648e-3) (node = 35) ++ y.mesh (location = 8108.2918e-3) (node = 36) ++ y.mesh (location = 8302.6109e-3) (node = 37) ++ y.mesh (location = 8476.9998e-3) (node = 38) ++ y.mesh (location = 8633.5027e-3) (node = 39) ++ y.mesh (location = 8773.9540e-3) (node = 40) ++ y.mesh (location = 8900.0000e-3) (node = 41) ++ y.mesh (location = 9000.0000e-3) (node = 42) +$ ---- Near drain ++ y.mesh (location = 9200.0000e-3) (node = 43) ++ y.mesh (location = 9612.8440e-3) (node = 44) ++ y.mesh (location = 10190.8257e-3) (node = 45) ++ y.mesh (location = 11000.0000e-3) (node = 46) ++ y.mesh (location = 12000.0000e-3) (node = 47) +$ ---- Mid drain ++ y.mesh (location = 13000.0000e-3) (node = 48) ++ y.mesh (location = 15500.0000e-3) (node = 49) ++ y.mesh (location = 18000.0000e-3) (node = 50) ++ +$ -- Regions +$ ---- substrate ++ region (num=1 material=1) x.l = 0.0000e-3 +$ ---- GOX ++ region (num=2 material=2) x.h = 0.0000e-3 ++ +$ -- Materials ++ material num=1 silicon ++ mobility material=1 concmod=sg fieldmod=sg ++ Mobility Material=1 elec major MuMax=1200.0 MuMin=200.0 Vsat=3.2e7 ++ Mobility Material=1 elec MuS=600.0 EC.A=3.0e5 ++ mobility material=1 elec minor MuMax=1200.0 MuMin=200.0 ++ mobility material=1 hole major ++ mobility material=1 hole minor ++ material num=2 oxide ++ +$ -- Contacts and workfunction +$ ---- Drain ++ elec num=1 (x.l = 0.0000e-3 x.h = 0.0000e-3) (y.l = 12000.0000e-3 y.h = 16000.0000e-3) +$ ---- Gate contact ++ elec num=2 (x.l = -64.0000e-3 x.h = -64.0000e-3) (y.l = 0.0000e-3 y.h = 9000.0000e-3) +$ ---- Source ++ elec num=3 (x.l = 0.0000e-3 x.h = 0.0000e-3) (y.l = -6000.0000e-3 y.h = -3000.0000e-3) +$ ---- Body ++ elec num=4 (x.l = 0.0000e-3 x.h = 0.0000e-3) (y.l = -30000.0000e-3 y.h = -25000.0000e-3) ++ contact num=1 workf=4.0500 ++ contact num=2 workf=4.0500 ++ contact num=3 workf=4.0500 ++ contact num=4 workf=5.1700 ++ +$ -- Doping profiles +$ ---- p subs ++ doping Domains = 1 Uniform P.Type Conc = 1e16 +$ ---- Threshold Adjustment Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc X.Axis P.Type x.l=0.0 x.h=0.5 y.l=-0 y.h=10 Peak.Conc=2e16 Location=0.1 Char.Length=0.8 Ratio.Lat=0.8 +$ ---- Body Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc X.Axis P.Type x.l=0.0 x.h=3.0 y.l=-30 y.h=-20 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 +$ ---- Source Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc X.Axis N.Type x.l=0.0 x.h=3.0 y.l=-10 y.h=0 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 +$ ---- Drain Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc X.Axis N.Type x.l=0.0 x.h=3.0 y.l=9.0 y.h=18.0 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 ++ ++ models concmob fieldmob ++ method ac=direct ^onec ++ ++ interface domain=1 neighbor=2 y.l=0 y.h=8.0 layer.width=0.5 ++ models surfmob transmob ^matchmob + +$ Total grid points X23 x Y50 = 1150 + +$ END OF CIDER + + +$ PSPICE Schematics Netlist +VId VPP VDD 0 +MN1 VDD VGG 0 0 CD4007UBENUMOSN w=298u +* .save i(VId) * +VVDS VPP 0 DC 0 +VVGS VGG 0 DC 0 +.dc VVGS 0.00 5.00 0.25 VVDS 0.05 0.05 0.50 +$ VGS x VDS sweep points: 51 x 1 = 51 +.print dc VPP VGG VPP +.end diff --git a/examples/cider/surfmob/cdxy.net b/examples/cider/surfmob/cdxy.net new file mode 100644 index 000000000..f420c0c80 --- /dev/null +++ b/examples/cider/surfmob/cdxy.net @@ -0,0 +1,159 @@ +$ CD4007, version: cd4007n_200402idvg +$ Generated using Matlab automation script. + + +$ BEGIN CIDER + +.model CD4007UBENUMOSN numos +$ -- y Grid +$ ---- GOX ++ y.mesh (location = -64.0000e-3) (node = 1) ++ y.mesh (location = -48.0000e-3) (node = 2) ++ y.mesh (location = -32.0000e-3) (node = 3) ++ y.mesh (location = -16.0000e-3) (node = 4) ++ y.mesh (location = 0.0000e-3) (node = 5) +$ ---- Channel and S/D ++ y.mesh (location = 20.0000e-3) (node = 6) ++ y.mesh (location = 48.4511e-3) (node = 7) ++ y.mesh (location = 86.9893e-3) (node = 8) ++ y.mesh (location = 139.1911e-3) (node = 9) ++ y.mesh (location = 209.9008e-3) (node = 10) ++ y.mesh (location = 305.6803e-3) (node = 11) ++ y.mesh (location = 435.4180e-3) (node = 12) ++ y.mesh (location = 611.1537e-3) (node = 13) ++ y.mesh (location = 849.1956e-3) (node = 14) ++ y.mesh (location = 1171.6341e-3) (node = 15) ++ y.mesh (location = 1608.3918e-3) (node = 16) ++ y.mesh (location = 2200.0000e-3) (node = 17) ++ y.mesh (location = 3000.0000e-3) (node = 18) +$ ---- Mid substrate ++ y.mesh (location = 3800.0000e-3) (node = 19) ++ y.mesh (location = 4911.8170e-3) (node = 20) ++ y.mesh (location = 6290.4701e-3) (node = 21) ++ y.mesh (location = 8000.0000e-3) (node = 22) ++ y.mesh (location = 10000.0000e-3) (node = 23) ++ +$ -- x Grid +$ ---- Body well ++ x.mesh (location = -35000.0000e-3) (node = 1) ++ x.mesh (location = -30000.0000e-3) (node = 2) ++ x.mesh (location = -25000.0000e-3) (node = 3) ++ x.mesh (location = -20000.0000e-3) (node = 4) +$ ---- Body-Source ++ x.mesh (location = -17500.0000e-3) (node = 5) ++ x.mesh (location = -15000.0000e-3) (node = 6) ++ x.mesh (location = -12500.0000e-3) (node = 7) ++ x.mesh (location = -10000.0000e-3) (node = 8) +$ ---- Mid source ++ x.mesh (location = -7500.0000e-3) (node = 9) ++ x.mesh (location = -4980.0000e-3) (node = 10) ++ x.mesh (location = -3000.0000e-3) (node = 11) ++ x.mesh (location = -2000.0000e-3) (node = 12) +$ ---- Near source ++ x.mesh (location = -1000.0000e-3) (node = 13) ++ x.mesh (location = -200.0000e-3) (node = 14) ++ x.mesh (location = 0.0000e-3) (node = 15) +$ ---- Channel near source ++ x.mesh (location = 200.0000e-3) (node = 16) ++ x.mesh (location = 442.1759e-3) (node = 17) ++ x.mesh (location = 732.7869e-3) (node = 18) ++ x.mesh (location = 1081.5201e-3) (node = 19) ++ x.mesh (location = 1500.0000e-3) (node = 20) ++ x.mesh (location = 2000.0000e-3) (node = 21) +$ ---- Channel center ++ x.mesh (location = 2500.0000e-3) (node = 22) ++ x.mesh (location = 3000.0000e-3) (node = 23) ++ x.mesh (location = 3500.0000e-3) (node = 24) ++ x.mesh (location = 4000.0000e-3) (node = 25) ++ x.mesh (location = 4500.0000e-3) (node = 26) ++ x.mesh (location = 5000.0000e-3) (node = 27) +$ ---- Channel near drain ++ x.mesh (location = 5500.0000e-3) (node = 28) ++ x.mesh (location = 5961.8362e-3) (node = 29) ++ x.mesh (location = 6376.3046e-3) (node = 30) ++ x.mesh (location = 6748.2634e-3) (node = 31) ++ x.mesh (location = 7082.0725e-3) (node = 32) ++ x.mesh (location = 7381.6449e-3) (node = 33) ++ x.mesh (location = 7650.4919e-3) (node = 34) ++ x.mesh (location = 7891.7648e-3) (node = 35) ++ x.mesh (location = 8108.2918e-3) (node = 36) ++ x.mesh (location = 8302.6109e-3) (node = 37) ++ x.mesh (location = 8476.9998e-3) (node = 38) ++ x.mesh (location = 8633.5027e-3) (node = 39) ++ x.mesh (location = 8773.9540e-3) (node = 40) ++ x.mesh (location = 8900.0000e-3) (node = 41) ++ x.mesh (location = 9000.0000e-3) (node = 42) +$ ---- Near drain ++ x.mesh (location = 9200.0000e-3) (node = 43) ++ x.mesh (location = 9612.8440e-3) (node = 44) ++ x.mesh (location = 10190.8257e-3) (node = 45) ++ x.mesh (location = 11000.0000e-3) (node = 46) ++ x.mesh (location = 12000.0000e-3) (node = 47) +$ ---- Mid drain ++ x.mesh (location = 13000.0000e-3) (node = 48) ++ x.mesh (location = 15500.0000e-3) (node = 49) ++ x.mesh (location = 18000.0000e-3) (node = 50) ++ +$ -- Regions +$ ---- substrate ++ region (num=1 material=1) y.l = 0.0000e-3 +$ ---- GOX ++ region (num=2 material=2) y.h = 0.0000e-3 ++ +$ -- Materials ++ material num=1 silicon ++ mobility material=1 concmod=sg fieldmod=sg ++ Mobility Material=1 elec major MuMax=1200.0 MuMin=200.0 Vsat=3.2e7 ++ Mobility Material=1 elec MuS=600.0 EC.A=3.0e5 ++ mobility material=1 elec minor MuMax=1200.0 MuMin=200.0 ++ mobility material=1 hole major ++ mobility material=1 hole minor ++ material num=2 oxide ++ +$ -- Contacts and workfunction +$ ---- Drain ++ elec num=1 (y.l = 0.0000e-3 y.h = 0.0000e-3) (x.l = 12000.0000e-3 x.h = 16000.0000e-3) +$ ---- Gate contact ++ elec num=2 (y.l = -64.0000e-3 y.h = -64.0000e-3) (x.l = 0.0000e-3 x.h = 9000.0000e-3) +$ ---- Source ++ elec num=3 (y.l = 0.0000e-3 y.h = 0.0000e-3) (x.l = -6000.0000e-3 x.h = -3000.0000e-3) +$ ---- Body ++ elec num=4 (y.l = 0.0000e-3 y.h = 0.0000e-3) (x.l = -30000.0000e-3 x.h = -25000.0000e-3) ++ contact num=1 workf=4.0500 ++ contact num=2 workf=4.0500 ++ contact num=3 workf=4.0500 ++ contact num=4 workf=5.1700 ++ +$ -- Doping profiles +$ ---- p subs ++ doping Domains = 1 Uniform P.Type Conc = 1e16 +$ ---- Threshold Adjustment Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc Y.Axis P.Type y.l=0.0 y.h=0.5 x.l=-0 x.h=10 Peak.Conc=2e16 Location=0.1 Char.Length=0.8 Ratio.Lat=0.8 +$ ---- Body Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc Y.Axis P.Type y.l=0.0 y.h=3.0 x.l=-30 x.h=-20 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 +$ ---- Source Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc Y.Axis N.Type y.l=0.0 y.h=3.0 x.l=-10 x.h=0 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 +$ ---- Drain Diffuse ++ doping Domains = 1 Gaussian Lat.Erfc Y.Axis N.Type y.l=0.0 y.h=3.0 x.l=9.0 x.h=18.0 Peak.Conc=2e20 Location=0 Char.Length=0.6 Ratio.Lat=0.8 ++ ++ models concmob fieldmob ++ method ac=direct ^onec ++ ++ interface domain=1 neighbor=2 x.l=0 x.h=8.0 layer.width=0.5 ++ models surfmob transmob ^matchmob + +$ Total grid points X23 x Y50 = 1150 + +$ END OF CIDER + + +$ PSPICE Schematics Netlist +VId VPP VDD 0 +MN1 VDD VGG 0 0 CD4007UBENUMOSN w=298u +* .save i(VId) * +VVDS VPP 0 DC 0 +VVGS VGG 0 DC 0 +.dc VVGS 0.00 5.00 0.25 VVDS 0.05 0.05 0.50 +$ VGS x VDS sweep points: 51 x 1 = 51 +.print dc VPP VGG VPP +.end diff --git a/examples/cider/surfmob/runtests.sh b/examples/cider/surfmob/runtests.sh new file mode 100755 index 000000000..b137641c7 --- /dev/null +++ b/examples/cider/surfmob/runtests.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -xv + +ngspice -b cd4007n_200402idvg.net +ngspice -b cdxy.net +ngspice -b Tbicmpd1.cir +ngspice -b Tbicmpd1xy.cir +ngspice -b Tbicmpu1.cir +ngspice -b Tbicmpu1xy.cir diff --git a/examples/cider/surfmob/spiceinit b/examples/cider/surfmob/spiceinit new file mode 100644 index 000000000..d08d85362 --- /dev/null +++ b/examples/cider/surfmob/spiceinit @@ -0,0 +1,2 @@ +option klu +set numdgt=3 diff --git a/src/ciderlib/oned/oneadmit.c b/src/ciderlib/oned/oneadmit.c index 686e96a98..38c251003 100644 --- a/src/ciderlib/oned/oneadmit.c +++ b/src/ciderlib/oned/oneadmit.c @@ -14,6 +14,8 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group #include "ngspice/complex.h" #include "ngspice/spmatrix.h" #include "ngspice/ifsim.h" +#include "ngspice/cktdefs.h" +#include "ngspice/ftedefs.h" #include "onedext.h" #include "oneddefs.h" @@ -29,7 +31,17 @@ extern IFfrontEnd *SPfrontEnd; */ SPcomplex yAc; - +#ifdef KLU +static void small_signal_check(char *where) +{ + if (ft_curckt->ci_ckt->CKTmode == MODEAC + || ft_curckt->ci_ckt->CKTmode == MODEACNOISE) { + fprintf(stderr, "Error: CIDER %s small signal simulation is not (yet) supported with 'option klu'.\n", where); + fprintf(stderr, " Use 'option sparse' instead.\n"); + controlled_exit(1); + } +} +#endif int NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd) @@ -45,6 +57,11 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd) bool SORFailed; double startTime; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMDadmittance"); + } +#endif /* Each time we call this counts as one AC iteration. */ pDevice->pStats->numIters[STAT_AC] += 1; @@ -119,6 +136,7 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd) #ifdef KLU if (pDevice->matrix->CKTkluMODE) { + // Not implemented pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; } else { #endif @@ -196,6 +214,11 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce, SPcomplex cOmega, pIeVce, pIcVce, pIeVbe, pIcVbe; double startTime; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NBJTadmittance"); + } +#endif /* Each time we call this counts as one AC iteration. */ pDevice->pStats->numIters[STAT_AC] += 1; @@ -315,6 +338,7 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce, #ifdef KLU if (pDevice->matrix->CKTkluMODE) { + // Not implemented pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; } else { #endif @@ -552,6 +576,11 @@ NUMDys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yd) SPcomplex *y; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMDys"); + } +#endif /* * change context names of solution vectors for ac analysis dcDeltaSolution * stores the real part and copiedSolution stores the imaginary part of the @@ -580,6 +609,7 @@ NUMDys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yd) #ifdef KLU if (pDevice->matrix->CKTkluMODE) { + // Not implemented pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; } else { #endif @@ -640,6 +670,11 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex temp, cOmega; SPcomplex pIeVce, pIcVce, pIeVbe, pIcVbe; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NBJTys"); + } +#endif /* * change context names of solution vectors for ac analysis dcDeltaSolution * stores the real part and copiedSolution stores the imaginary part of the @@ -667,6 +702,7 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, #ifdef KLU if (pDevice->matrix->CKTkluMODE) { + // Not implemented pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; } else { #endif diff --git a/src/ciderlib/twod/twoadmit.c b/src/ciderlib/twod/twoadmit.c index 8f3a4e1b5..787c10805 100644 --- a/src/ciderlib/twod/twoadmit.c +++ b/src/ciderlib/twod/twoadmit.c @@ -16,6 +16,9 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group #include "ngspice/bool.h" #include "ngspice/macros.h" #include "ngspice/ifsim.h" +#include "ngspice/cktdefs.h" +#include "ngspice/ftedefs.h" + #include "twoddefs.h" #include "twodext.h" #include "ngspice/cidersupt.h" @@ -28,6 +31,18 @@ extern IFfrontEnd *SPfrontEnd; */ SPcomplex yTotal; +#ifdef KLU +static void small_signal_check(char *where) +{ + if (ft_curckt->ci_ckt->CKTmode == MODEAC + || ft_curckt->ci_ckt->CKTmode == MODEACNOISE) { + fprintf(stderr, "Error: CIDER %s small signal simulation is not (yet) supported with 'option klu'.\n", where); + fprintf(stderr, " Use 'option sparse' instead.\n"); + controlled_exit(1); + } +} +#endif + int NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd) { @@ -42,6 +57,11 @@ NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd) bool SORFailed; double startTime; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMD2admittance"); + } +#endif /* Each time we call this counts as one AC iteration. */ pDevice->pStats->numIters[STAT_AC] += 1; @@ -192,6 +212,11 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce, SPcomplex cOmega; double startTime; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NBJT2admittance"); + } +#endif /* Each time we call this counts as one AC iteration. */ pDevice->pStats->numIters[STAT_AC] += 1; @@ -416,6 +441,11 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc) SPcomplex *y, cOmega; double startTime; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMOSadmittance"); + } +#endif /* Each time we call this counts as one AC iteration. */ pDevice->pStats->numIters[STAT_AC] += 1; @@ -1151,6 +1181,11 @@ NUMD2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIn) bool deltaVContact = FALSE; SPcomplex temp, cOmega; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMD2ys"); + } +#endif /* * change context names of solution vectors for ac analysis dcDeltaSolution * stores the real part and copiedSolution stores the imaginary part of the @@ -1252,6 +1287,11 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce, SPcomplex pIeVce, pIcVce, pIeVbe, pIcVbe; SPcomplex temp, cOmega; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NBJT2ys"); + } +#endif pDevice->solverType = SLV_SMSIG; rhsReal = pDevice->rhs; rhsImag = pDevice->rhsImag; @@ -1375,6 +1415,11 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc) SPcomplex *y; SPcomplex temp, cOmega; +#ifdef KLU + if (pDevice->matrix->CKTkluMODE) { + small_signal_check("NUMOSys"); + } +#endif pDevice->solverType = SLV_SMSIG; rhsReal = pDevice->rhs; rhsImag = pDevice->rhsImag; diff --git a/src/ciderlib/twod/twocont.c b/src/ciderlib/twod/twocont.c index 4e79d8415..1fce53439 100644 --- a/src/ciderlib/twod/twocont.c +++ b/src/ciderlib/twod/twocont.c @@ -1149,7 +1149,8 @@ TWObindCSC (TWOdevice *pDevice) } } else { /* Horizontal Slice */ - if ( nIndex <= 1 ) { /* Top Side */ + //if ( nIndex <= 1 ) { /* Top Side */ + if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */ CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ; CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ; diff --git a/src/ciderlib/twod/twoncont.c b/src/ciderlib/twod/twoncont.c index 194339dfe..58c984d00 100644 --- a/src/ciderlib/twod/twoncont.c +++ b/src/ciderlib/twod/twoncont.c @@ -786,7 +786,8 @@ TWONbindCSC (TWOdevice *pDevice) } } else { /* Horizontal Slice */ - if ( nIndex <= 1 ) { /* Top Side */ + //if ( nIndex <= 1 ) { /* Top Side */ + if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */ CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ; CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ; diff --git a/src/ciderlib/twod/twopcont.c b/src/ciderlib/twod/twopcont.c index a3b1e6dd5..41e8811f8 100644 --- a/src/ciderlib/twod/twopcont.c +++ b/src/ciderlib/twod/twopcont.c @@ -786,7 +786,8 @@ TWOPbindCSC (TWOdevice *pDevice) } } else { /* Horizontal Slice */ - if ( nIndex <= 1 ) { /* Top Side */ + //if ( nIndex <= 1 ) { /* Top Side */ + if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */ CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ; CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ; diff --git a/src/spicelib/devices/nbjt/nbjtset.c b/src/spicelib/devices/nbjt/nbjtset.c index 34f62293d..9656ef443 100644 --- a/src/spicelib/devices/nbjt/nbjtset.c +++ b/src/spicelib/devices/nbjt/nbjtset.c @@ -44,7 +44,7 @@ NBJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) ONEmaterial *pM, *pMaterial = NULL, *materialList = NULL; double startTime; -#ifdef KLU +#if defined(KLU) && defined(NOT_WITH_CIDER) if (ckt->CKTkluMODE) { fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n"); fprintf(stderr, " Use 'option sparse' instead.\n"); diff --git a/src/spicelib/devices/nbjt2/nbt2set.c b/src/spicelib/devices/nbjt2/nbt2set.c index 3164d329f..d700fa2b0 100644 --- a/src/spicelib/devices/nbjt2/nbt2set.c +++ b/src/spicelib/devices/nbjt2/nbt2set.c @@ -47,7 +47,7 @@ NBJT2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) DOPtable *dopTableList = NULL; double startTime; -#ifdef KLU +#if defined(KLU) && defined(NOT_WITH_CIDER) if (ckt->CKTkluMODE) { fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n"); fprintf(stderr, " Use 'option sparse' instead.\n"); diff --git a/src/spicelib/devices/numd/numdset.c b/src/spicelib/devices/numd/numdset.c index 365d290d4..426629062 100644 --- a/src/spicelib/devices/numd/numdset.c +++ b/src/spicelib/devices/numd/numdset.c @@ -46,7 +46,7 @@ NUMDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) double startTime; -#ifdef KLU +#if defined(KLU) && defined(NOT_WITH_CIDER) if (ckt->CKTkluMODE) { fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n"); fprintf(stderr, " Use 'option sparse' instead.\n"); diff --git a/src/spicelib/devices/numd2/nud2set.c b/src/spicelib/devices/numd2/nud2set.c index a35a3132f..79f0e3ddd 100644 --- a/src/spicelib/devices/numd2/nud2set.c +++ b/src/spicelib/devices/numd2/nud2set.c @@ -47,7 +47,7 @@ NUMD2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) DOPtable *dopTableList = NULL; double startTime; -#ifdef KLU +#if defined(KLU) && defined(NOT_WITH_CIDER) if (ckt->CKTkluMODE) { fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n"); fprintf(stderr, " Use 'option sparse' instead.\n"); diff --git a/src/spicelib/devices/numos/nummset.c b/src/spicelib/devices/numos/nummset.c index 7e9838056..bba47089b 100644 --- a/src/spicelib/devices/numos/nummset.c +++ b/src/spicelib/devices/numos/nummset.c @@ -47,7 +47,7 @@ NUMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) DOPtable *dopTableList = NULL; double startTime; -#ifdef KLU +#if defined(KLU) && defined(NOT_WITH_CIDER) if (ckt->CKTkluMODE) { fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n"); fprintf(stderr, " Use 'option sparse' instead.\n"); From 5900f704383ef446b30cf5ea9d5691315f60f1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Fri, 12 Sep 2025 10:04:29 +0200 Subject: [PATCH 08/20] Fast version checks in BSIM4. --- src/spicelib/devices/bsim4/b4noi.c | 21 ++++++++++++--------- src/spicelib/devices/bsim4/b4set.c | 20 +++++++++++++++++--- src/spicelib/devices/bsim4/b4temp.c | 9 +++++---- src/spicelib/devices/bsim4/bsim4def.h | 7 ++++++- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4noi.c b/src/spicelib/devices/bsim4/b4noi.c index 473dea60d..faea45ab6 100644 --- a/src/spicelib/devices/bsim4/b4noi.c +++ b/src/spicelib/devices/bsim4/b4noi.c @@ -366,9 +366,10 @@ double mult_i, mult_fn; epsilon = (T7 - T7 * T7 * T7 / 3.0) / (6.0 * T6); T8 = here->BSIM4Vgsteff / here->BSIM4EsatL; T8 *= T8; - if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && + // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && + // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + if (model->BSIM4v48intVersion<=BSIM4v48V480) { npart_c = model->BSIM4rnoic * (1.0 + T8 * model->BSIM4tnoic * Leff); @@ -420,9 +421,10 @@ double mult_i, mult_fn; } switch(model->BSIM4tnoiMod) { case 0: - if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && + // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && + // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + if (model->BSIM4v48intVersion<=BSIM4v48V480) { T0 = here->BSIM4ueff * fabs(here->BSIM4qinv); T1 = T0 * tmp + pParam->BSIM4leff @@ -449,9 +451,10 @@ double mult_i, mult_fn; } break; case 1: - if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && + // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && + // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + if (model->BSIM4v48intVersion<=BSIM4v48V480) { T0 = here->BSIM4gm + here->BSIM4gmbs + here->BSIM4gds; T0 *= T0; diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 0637be32e..2135ce9a3 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -203,6 +203,19 @@ BSIM4instance **InstArray; } if (!model->BSIM4versionGiven) model->BSIM4version = copy("4.8.3"); + /* Speed up version checking via integer version number */ + if ((!strcmp(model->BSIM4version, "4.8.3"))||(!strncmp(model->BSIM4version, "4.83", 4))) { + model->BSIM4v48intVersion = BSIM4v48V483; + } else if ((!strcmp(model->BSIM4version, "4.8.2"))||(!strncmp(model->BSIM4version, "4.82", 4))) { + model->BSIM4v48intVersion = BSIM4v48V482; + } else if ((!strcmp(model->BSIM4version, "4.8.1"))||(!strncmp(model->BSIM4version, "4.81", 4))) { + model->BSIM4v48intVersion = BSIM4v48V481; + } else if ((!strcmp(model->BSIM4version, "4.8.0"))||(!strncmp(model->BSIM4version, "4.80", 4))||(!strncmp(model->BSIM4version, "4.8", 3))) { + model->BSIM4v48intVersion = BSIM4v48V480; + } else { + printf("Warning: unknown BSIM4 version. Working now with BSIM4.8.3.\n"); + model->BSIM4v48intVersion = BSIM4v48V483; + } if (!model->BSIM4toxrefGiven) model->BSIM4toxref = 30.0e-10; if (!model->BSIM4eotGiven) @@ -342,9 +355,10 @@ BSIM4instance **InstArray; if (!model->BSIM4ucsGiven) model->BSIM4ucs = (model->BSIM4type == NMOS) ? 1.67 : 1.0; - if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && - (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && + // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && + // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + if (model->BSIM4v48intVersion<=BSIM4v48V480) { if (!model->BSIM4uaGiven) model->BSIM4ua = ((model->BSIM4mobMod == 2)) ? 1.0e-15 : 1.0e-9; /* unit m/V */ diff --git a/src/spicelib/devices/bsim4/b4temp.c b/src/spicelib/devices/bsim4/b4temp.c index 3c9796db6..3b41db563 100644 --- a/src/spicelib/devices/bsim4/b4temp.c +++ b/src/spicelib/devices/bsim4/b4temp.c @@ -1368,10 +1368,11 @@ int Fatal_Flag = 0; pParam->BSIM4Aechvb = (model->BSIM4type == NMOS) ? 4.97232e-7 : 3.42537e-7; pParam->BSIM4Bechvb = (model->BSIM4type == NMOS) ? 7.45669e11 : 1.16645e12; - if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && - (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) - { + // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && + // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && + // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) + // { + if (model->BSIM4v48intVersion<=BSIM4v48V480) { pParam->BSIM4AechvbEdgeS = pParam->BSIM4Aechvb * pParam->BSIM4weff * model->BSIM4dlcig * pParam->BSIM4ToxRatioEdge; pParam->BSIM4AechvbEdgeD = pParam->BSIM4Aechvb * pParam->BSIM4weff diff --git a/src/spicelib/devices/bsim4/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index a2bff4121..6d7d652e8 100644 --- a/src/spicelib/devices/bsim4/bsim4def.h +++ b/src/spicelib/devices/bsim4/bsim4def.h @@ -941,7 +941,12 @@ typedef struct sBSIM4model int BSIM4tempMod; int BSIM4binUnit; int BSIM4paramChk; - char *BSIM4version; + char *BSIM4version; + int BSIM4v48intVersion; +#define BSIM4v48V483 483 /* BSIM4v48 V4.8.3 */ +#define BSIM4v48V482 482 /* BSIM4v48 V4.8.2 */ +#define BSIM4v48V481 481 /* BSIM4v48 V4.8.1 */ +#define BSIM4v48V480 480 /* BSIM4v48 V4.8.0 */ double BSIM4eot; double BSIM4vddeot; double BSIM4tempeot; From e4aa062156f8fcf9a33c918c43c9154b5b808322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Fri, 22 Aug 2025 11:20:43 +0200 Subject: [PATCH 09/20] icvgs, icvds, icvbs exposed as BSIM4v8 parameters. --- src/spicelib/devices/bsim4/b4.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/spicelib/devices/bsim4/b4.c b/src/spicelib/devices/bsim4/b4.c index b39901f32..438c1498b 100644 --- a/src/spicelib/devices/bsim4/b4.c +++ b/src/spicelib/devices/bsim4/b4.c @@ -71,6 +71,9 @@ IOP( "mult_i", BSIM4_MULT_I, IF_REAL, "Variability in current"), IOP( "mult_q", BSIM4_MULT_Q, IF_REAL, "Variability in charge"), IOP( "mult_fn", BSIM4_MULT_FN, IF_REAL, "Variability in flicker noise"), IP( "ic", BSIM4_IC, IF_REALVEC , "Vector of DS,GS,BS initial voltages"), +IOP( "icvgs", BSIM4_IC_VGS, IF_REAL , "GS initial voltage"), +IOP( "icvds", BSIM4_IC_VDS, IF_REAL , "DS initial voltage"), +IOP( "icvbs", BSIM4_IC_VBS, IF_REAL , "BS initial voltage"), OP( "gmbs", BSIM4_GMBS, IF_REAL, "Gmb"), OP( "gm", BSIM4_GM, IF_REAL, "Gm"), OP( "gds", BSIM4_GDS, IF_REAL, "Gds"), From 740670805e6df9c32fbf5a1226f0d14c98a1a9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Fri, 12 Sep 2025 10:10:48 +0200 Subject: [PATCH 10/20] Check if toxp+dtox!=toxe with double precision tolerance. --- src/spicelib/devices/bsim4/b4temp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/spicelib/devices/bsim4/b4temp.c b/src/spicelib/devices/bsim4/b4temp.c index 3b41db563..f4c76dd65 100644 --- a/src/spicelib/devices/bsim4/b4temp.c +++ b/src/spicelib/devices/bsim4/b4temp.c @@ -122,8 +122,12 @@ int Fatal_Flag = 0; if(model->BSIM4mtrlMod == 0) { + double chktol = fabs(model->BSIM4toxe); + if (fabs(model->BSIM4toxp)>chktol) chktol = fabs(model->BSIM4toxp); + if (fabs(model->BSIM4dtox)>chktol) chktol = fabs(model->BSIM4dtox); + chktol=chktol*1e-14; if ((model->BSIM4toxeGiven) && (model->BSIM4toxpGiven) && (model->BSIM4dtoxGiven) - && (model->BSIM4toxe != (model->BSIM4toxp + model->BSIM4dtox))) + && (fabs(model->BSIM4toxe-(model->BSIM4toxp + model->BSIM4dtox))>chktol)) { printf("Warning: toxe, toxp and dtox all given and toxe != toxp + dtox; dtox ignored.\n"); } else if ((model->BSIM4toxeGiven) && (!model->BSIM4toxpGiven)) From 82491425060a59b65eceec6fad3b5363921435b7 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 13 Sep 2025 12:18:05 +0200 Subject: [PATCH 11/20] Spelling Found by Lintian, patches provided by C. Schoenert --- ChangeLog | 2 +- src/frontend/options.c | 2 +- src/include/ngspice/klu.h | 2 +- src/xspice/icm/analog/file_source/cfunc.mod | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b586ca150..491675b42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13794,7 +13794,7 @@ New include File: 2010-10-09 Robert Larice * src/include/complex.h : !REVERT! remove typedef for _complex, which is used nowhere - this breaks MSVC, currently unkown why, FIXME + this breaks MSVC, currently unknown why, FIXME 2010-10-09 Robert Larice * src/frontend/parse-bison.c , diff --git a/src/frontend/options.c b/src/frontend/options.c index 0b54881ba..7dfe6f97a 100644 --- a/src/frontend/options.c +++ b/src/frontend/options.c @@ -330,7 +330,7 @@ cp_usrset(struct variable *var, bool isset) ft_stricterror = isset; if (ft_ngdebug) fprintf(stdout, "Note: strict_errorhandling is set\n"); - /* Immediately bail out when spinit error has occured */ + /* Immediately bail out when spinit error has occurred */ if (ft_spiniterror) controlled_exit(EXIT_BAD); } else if (eq(var->va_name, "rawfileprec")) { diff --git a/src/include/ngspice/klu.h b/src/include/ngspice/klu.h index 248b9bf64..7e64bcdc5 100644 --- a/src/include/ngspice/klu.h +++ b/src/include/ngspice/klu.h @@ -133,7 +133,7 @@ typedef struct /* 64-bit version (otherwise same as above) */ #define KLU_EMPTY_MATRIX (2) /* Modified by Francesco Lannutti - Case when the matrix is empty */ #define KLU_OUT_OF_MEMORY (-2) #define KLU_INVALID (-3) -#define KLU_TOO_LARGE (-4) /* integer overflow has occured */ +#define KLU_TOO_LARGE (-4) /* integer overflow has occurred */ typedef struct klu_common_struct { diff --git a/src/xspice/icm/analog/file_source/cfunc.mod b/src/xspice/icm/analog/file_source/cfunc.mod index 2190b1a67..73eb12e68 100644 --- a/src/xspice/icm/analog/file_source/cfunc.mod +++ b/src/xspice/icm/analog/file_source/cfunc.mod @@ -336,9 +336,9 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. loc->timeinterval[1] = loc->indata->datavec[loc->indata->actpointer + stepsize]; if (terr) - cm_message_printf("WARNING: some error occured during reading the time values"); + cm_message_printf("WARNING: some error occurred during reading the time values"); if (derr) - cm_message_printf("WARNING: some error occured during reading the data values"); + cm_message_printf("WARNING: some error occurred during reading the data values"); } loc = STATIC_VAR (locdata); From 535e22a5020b43607fe216a01728e1b6cabca234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Mon, 15 Sep 2025 10:23:11 +0200 Subject: [PATCH 12/20] Fixed a bug causing mult_* factors to get scaled at each setup(). --- src/spicelib/devices/bsim4/b4acld.c | 4 +- src/spicelib/devices/bsim4/b4ask.c | 88 ++++++++++++++--------------- src/spicelib/devices/bsim4/b4ld.c | 6 +- src/spicelib/devices/bsim4/b4noi.c | 4 +- src/spicelib/devices/bsim4/b4pzld.c | 4 +- src/spicelib/devices/bsim4/b4set.c | 7 ++- 6 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4acld.c b/src/spicelib/devices/bsim4/b4acld.c index 18257423c..c972d6866 100644 --- a/src/spicelib/devices/bsim4/b4acld.c +++ b/src/spicelib/devices/bsim4/b4acld.c @@ -462,8 +462,8 @@ double m, mult_i, mult_q; * Loading AC matrix */ m = here->BSIM4m; - mult_i = here->BSIM4mult_i; - mult_q = here->BSIM4mult_q; + mult_i = here->BSIM4mult_i * here->BSIM4m; + mult_q = here->BSIM4mult_q * here->BSIM4m; if (!model->BSIM4rdsMod) { gdpr = here->BSIM4drainConductance; diff --git a/src/spicelib/devices/bsim4/b4ask.c b/src/spicelib/devices/bsim4/b4ask.c index c0f843e95..d43e1a708 100644 --- a/src/spicelib/devices/bsim4/b4ask.c +++ b/src/spicelib/devices/bsim4/b4ask.c @@ -203,11 +203,11 @@ BSIM4instance *here = (BSIM4instance*)inst; return(OK); case BSIM4_SOURCECONDUCT: value->rValue = here->BSIM4sourceConductance; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_DRAINCONDUCT: value->rValue = here->BSIM4drainConductance; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_VBD: value->rValue = *(ckt->CKTstate0 + here->BSIM4vbd); @@ -223,67 +223,67 @@ BSIM4instance *here = (BSIM4instance*)inst; return(OK); case BSIM4_CD: value->rValue = here->BSIM4cd; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_CBS: value->rValue = here->BSIM4cbs; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_CBD: value->rValue = here->BSIM4cbd; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_CSUB: value->rValue = here->BSIM4csub; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGIDL: value->rValue = here->BSIM4Igidl; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGISL: value->rValue = here->BSIM4Igisl; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGS: value->rValue = here->BSIM4Igs; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGD: value->rValue = here->BSIM4Igd; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGB: value->rValue = here->BSIM4Igb; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGCS: value->rValue = here->BSIM4Igcs; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_IGCD: value->rValue = here->BSIM4Igcd; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GM: value->rValue = here->BSIM4gm; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GDS: value->rValue = here->BSIM4gds; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GMBS: value->rValue = here->BSIM4gmbs; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GBD: value->rValue = here->BSIM4gbd; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GBS: value->rValue = here->BSIM4gbs; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); /* case BSIM4_QB: value->rValue = *(ckt->CKTstate0 + here->BSIM4qb); @@ -308,19 +308,19 @@ BSIM4instance *here = (BSIM4instance*)inst; return(OK); */ case BSIM4_QB: value->rValue = here->BSIM4qbulk; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_QG: value->rValue = here->BSIM4qgate; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_QS: value->rValue = here->BSIM4qsrc; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_QD: value->rValue = here->BSIM4qdrn; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_QINV: value->rValue = here->BSIM4qinv; @@ -330,82 +330,82 @@ BSIM4instance *here = (BSIM4instance*)inst; return(OK); case BSIM4_GCRG: value->rValue = here->BSIM4gcrg; - value->rValue *= here->BSIM4mult_i; + value->rValue *= here->BSIM4mult_i * here->BSIM4m; return(OK); case BSIM4_GTAU: value->rValue = here->BSIM4gtau; return(OK); case BSIM4_CGGB: value->rValue = here->BSIM4cggb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CGDB: value->rValue = here->BSIM4cgdb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CGSB: value->rValue = here->BSIM4cgsb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CDGB: value->rValue = here->BSIM4cdgb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CDDB: value->rValue = here->BSIM4cddb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CDSB: value->rValue = here->BSIM4cdsb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CBGB: value->rValue = here->BSIM4cbgb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CBDB: value->rValue = here->BSIM4cbdb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CBSB: value->rValue = here->BSIM4cbsb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CSGB: value->rValue = here->BSIM4csgb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CSDB: value->rValue = here->BSIM4csdb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CSSB: value->rValue = here->BSIM4cssb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CGBB: value->rValue = here->BSIM4cgbb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CDBB: value->rValue = here->BSIM4cdbb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CSBB: value->rValue = here->BSIM4csbb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CBBB: value->rValue = here->BSIM4cbbb; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CAPBD: value->rValue = here->BSIM4capbd; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CAPBS: value->rValue = here->BSIM4capbs; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_VON: value->rValue = here->BSIM4von; @@ -427,15 +427,15 @@ BSIM4instance *here = (BSIM4instance*)inst; return(OK); case BSIM4_CGSO: value->rValue = here->BSIM4cgso; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CGDO: value->rValue = here->BSIM4cgdo; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_CGBO: value->rValue = here->pParam->BSIM4cgbo; - value->rValue *= here->BSIM4mult_q; + value->rValue *= here->BSIM4mult_q * here->BSIM4m; return(OK); case BSIM4_WEFF: value->rValue = here->pParam->BSIM4weff; diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index da408eaef..5001e12f3 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -4986,9 +4986,9 @@ line900: */ m = here->BSIM4m; - mult_i = here->BSIM4mult_i; - mult_q = here->BSIM4mult_q; - + mult_i = here->BSIM4mult_i * here->BSIM4m; + mult_q = here->BSIM4mult_q * here->BSIM4m; + #ifdef USE_OMP here->BSIM4rhsdPrime = (mult_i * (ceqjd - ceqbd + ceqgdtot - ceqdrn + Idtoteq) - mult_q * ceqqd); diff --git a/src/spicelib/devices/bsim4/b4noi.c b/src/spicelib/devices/bsim4/b4noi.c index faea45ab6..d56b19cb2 100644 --- a/src/spicelib/devices/bsim4/b4noi.c +++ b/src/spicelib/devices/bsim4/b4noi.c @@ -155,8 +155,8 @@ double mult_i, mult_fn; } break; case N_CALC: - mult_i = here->BSIM4mult_i; - mult_fn = here->BSIM4mult_fn; + mult_i = here->BSIM4mult_i * here->BSIM4m; + mult_fn = here->BSIM4mult_fn * here->BSIM4m; switch (mode) { case N_DENS: if (model->BSIM4tnoiMod == 0) diff --git a/src/spicelib/devices/bsim4/b4pzld.c b/src/spicelib/devices/bsim4/b4pzld.c index 970f78889..ff66cf13a 100644 --- a/src/spicelib/devices/bsim4/b4pzld.c +++ b/src/spicelib/devices/bsim4/b4pzld.c @@ -494,8 +494,8 @@ double m, mult_i, mult_q; * Loading PZ matrix */ m = here->BSIM4m; - mult_i = here->BSIM4mult_i; - mult_q = here->BSIM4mult_q; + mult_i = here->BSIM4mult_i * here->BSIM4m; + mult_q = here->BSIM4mult_q * here->BSIM4m; if (!model->BSIM4rdsMod) { gdpr = here->BSIM4drainConductance; diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 2135ce9a3..56ae72096 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -2375,9 +2375,10 @@ BSIM4instance **InstArray; if (!here->BSIM4ngconGiven) here->BSIM4ngcon = model->BSIM4ngcon; - here->BSIM4mult_i = here->BSIM4mult_i * here->BSIM4m; - here->BSIM4mult_q = here->BSIM4mult_q * here->BSIM4m; - here->BSIM4mult_fn = here->BSIM4mult_fn * here->BSIM4m; + // Recursive scaling produces incorrect results after second call to setup() + // here->BSIM4mult_i = here->BSIM4mult_i * here->BSIM4m; + // here->BSIM4mult_q = here->BSIM4mult_q * here->BSIM4m; + // here->BSIM4mult_fn = here->BSIM4mult_fn * here->BSIM4m; /* Process instance model selectors, some * may override their global counterparts From 06b73b405646557b4198e46021eead4d6b0944f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Mon, 15 Sep 2025 10:25:08 +0200 Subject: [PATCH 13/20] ceqqjd, ceqqjs should be scaled with mult_q. This fixes erratic simulation behavior when mult_i != mult_q. --- src/spicelib/devices/bsim4/b4ld.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index 5001e12f3..fa7d56f96 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -5006,9 +5006,9 @@ line900: - ceqgstot + Istoteq) + mult_q * (ceqqg + ceqqb + ceqqd + ceqqgmid)); } else - { here->BSIM4rhsdb = mult_i * (ceqjd + ceqqjd); + { here->BSIM4rhsdb = mult_i * (ceqjd /*+ ceqqjd */) + mult_q * ceqqjd); here->BSIM4rhsbPrime = (mult_i * (ceqbd + ceqbs + Ibtoteq) - mult_q * ceqqb); - here->BSIM4rhssb = mult_i * (ceqjs + ceqqjs); + here->BSIM4rhssb = mult_i * (ceqjs /*+ ceqqjs*/) + mult_q * ceqqjs; here->BSIM4rhssPrime = (mult_i * (ceqdrn - ceqbs + ceqjs - ceqgstot + Istoteq) + mult_q * (ceqqd + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid)); } @@ -5037,9 +5037,9 @@ line900: - ceqgstot + Istoteq) + mult_q * (ceqqg + ceqqb + ceqqd + ceqqgmid))); } else - { (*(ckt->CKTrhs + here->BSIM4dbNode) -= mult_i * (ceqjd + ceqqjd)); + { (*(ckt->CKTrhs + here->BSIM4dbNode) -= mult_i * (ceqjd /*+ ceqqjd*/) + mult_q * ceqqjd); (*(ckt->CKTrhs + here->BSIM4bNodePrime) += (mult_i * (ceqbd + ceqbs + Ibtoteq) - mult_q * ceqqb)); - (*(ckt->CKTrhs + here->BSIM4sbNode) -= mult_i * (ceqjs + ceqqjs)); + (*(ckt->CKTrhs + here->BSIM4sbNode) -= mult_i * (ceqjs /*+ ceqqjs*/) + mult_q * ceqqjs); (*(ckt->CKTrhs + here->BSIM4sNodePrime) += (mult_i * (ceqdrn - ceqbs + ceqjs - ceqgstot + Istoteq) + mult_q * (ceqqd + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid))); } From c6a6bd9edb51bde19dc7ed1a112b2140cf8c6d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Mon, 15 Sep 2025 12:04:44 +0200 Subject: [PATCH 14/20] Scaling of NQS charge deficit with mult_q. --- src/spicelib/devices/bsim4/b4ld.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index fa7d56f96..9c840e395 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -5227,9 +5227,9 @@ line900: here->BSIM4_99 = m * (ggts - gcqsb); here->BSIM4_100 = m * (ggtb - gcqbb); - here->BSIM4_101 = m * dxpart * here->BSIM4gtau; - here->BSIM4_102 = m * sxpart * here->BSIM4gtau; - here->BSIM4_103 = m * here->BSIM4gtau; + here->BSIM4_101 = mult_q * dxpart * here->BSIM4gtau; + here->BSIM4_102 = mult_q * sxpart * here->BSIM4gtau; + here->BSIM4_103 = mult_q * here->BSIM4gtau; } #else if (here->BSIM4rgateMod == 1) @@ -5382,9 +5382,9 @@ line900: (*(here->BSIM4QspPtr) += m * (ggts - gcqsb)); (*(here->BSIM4QbpPtr) += m * (ggtb - gcqbb)); - (*(here->BSIM4DPqPtr) += m * (dxpart * here->BSIM4gtau)); - (*(here->BSIM4SPqPtr) += m * (sxpart * here->BSIM4gtau)); - (*(here->BSIM4GPqPtr) -= m * (here->BSIM4gtau)); + (*(here->BSIM4DPqPtr) += mult_q * (dxpart * here->BSIM4gtau)); + (*(here->BSIM4SPqPtr) += mult_q * (sxpart * here->BSIM4gtau)); + (*(here->BSIM4GPqPtr) -= mult_q * (here->BSIM4gtau)); } #endif From 683e208d87f431eb175a368d63dc10f2311a7bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20B=C5=B1rmen?= Date: Tue, 16 Sep 2025 13:37:50 +0200 Subject: [PATCH 15/20] BSIM4 version 4.8 is considered to be the latest, i.e. 4.8.3. --- src/spicelib/devices/bsim4/b4set.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 56ae72096..72495a636 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -204,13 +204,13 @@ BSIM4instance **InstArray; if (!model->BSIM4versionGiven) model->BSIM4version = copy("4.8.3"); /* Speed up version checking via integer version number */ - if ((!strcmp(model->BSIM4version, "4.8.3"))||(!strncmp(model->BSIM4version, "4.83", 4))) { + if ((!strcmp(model->BSIM4version, "4.8.3"))||(!strncmp(model->BSIM4version, "4.83", 4))||(!strncmp(model->BSIM4version, "4.8", 3))) { model->BSIM4v48intVersion = BSIM4v48V483; } else if ((!strcmp(model->BSIM4version, "4.8.2"))||(!strncmp(model->BSIM4version, "4.82", 4))) { model->BSIM4v48intVersion = BSIM4v48V482; } else if ((!strcmp(model->BSIM4version, "4.8.1"))||(!strncmp(model->BSIM4version, "4.81", 4))) { model->BSIM4v48intVersion = BSIM4v48V481; - } else if ((!strcmp(model->BSIM4version, "4.8.0"))||(!strncmp(model->BSIM4version, "4.80", 4))||(!strncmp(model->BSIM4version, "4.8", 3))) { + } else if ((!strcmp(model->BSIM4version, "4.8.0"))||(!strncmp(model->BSIM4version, "4.80", 4))) { model->BSIM4v48intVersion = BSIM4v48V480; } else { printf("Warning: unknown BSIM4 version. Working now with BSIM4.8.3.\n"); From 2b1dc09caf523f4a808071d111688c08c99f10b3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 16 Sep 2025 15:08:34 +0200 Subject: [PATCH 16/20] Improve detection of the number of terminals for bipolar devices. Fixes bug no. 807. --- src/frontend/inpcom.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 71a3bdeaf..031dd9d5b 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -5286,8 +5286,7 @@ int get_number_terminals(char *c) char* comma; name[i] = gettok_instance(&cc); - if (search_plain_identifier(name[i], "off") || - strchr(name[i], '=')) { + if (search_plain_identifier(name[i], "off")) { j++; } #ifdef CIDER @@ -5296,16 +5295,9 @@ int get_number_terminals(char *c) j++; } #endif - /* If we have IC=VBE, VCE instead of IC=VBE,VCE - * we need to increment j. - */ - if ((comma = strchr(name[i], ',')) != NULL && - (*(++comma) == '\0')) - j++; - /* If we have IC=VBE , VCE ("," is a token) we need to inc j - */ - if (eq(name[i], ",")) - j++; + if (strchr(name[i], '=')) { + break; + } } i--; tfree(ccfree); From 056ca890fd2a5903989cf47f89d50584ff1304be Mon Sep 17 00:00:00 2001 From: dwarning Date: Tue, 16 Sep 2025 18:33:55 +0200 Subject: [PATCH 17/20] remove old commented strncmp version check code --- src/spicelib/devices/bsim4/b4noi.c | 9 --------- src/spicelib/devices/bsim4/b4set.c | 8 -------- src/spicelib/devices/bsim4/b4temp.c | 4 ---- 3 files changed, 21 deletions(-) diff --git a/src/spicelib/devices/bsim4/b4noi.c b/src/spicelib/devices/bsim4/b4noi.c index d56b19cb2..c6aa87936 100644 --- a/src/spicelib/devices/bsim4/b4noi.c +++ b/src/spicelib/devices/bsim4/b4noi.c @@ -366,9 +366,6 @@ double mult_i, mult_fn; epsilon = (T7 - T7 * T7 * T7 / 3.0) / (6.0 * T6); T8 = here->BSIM4Vgsteff / here->BSIM4EsatL; T8 *= T8; - // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) if (model->BSIM4v48intVersion<=BSIM4v48V480) { npart_c = model->BSIM4rnoic * (1.0 + T8 @@ -421,9 +418,6 @@ double mult_i, mult_fn; } switch(model->BSIM4tnoiMod) { case 0: - // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) if (model->BSIM4v48intVersion<=BSIM4v48V480) { T0 = here->BSIM4ueff * fabs(here->BSIM4qinv); @@ -451,9 +445,6 @@ double mult_i, mult_fn; } break; case 1: - // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && (strncmp(model->BSIM4version, "4.8", 3)) && - // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) if (model->BSIM4v48intVersion<=BSIM4v48V480) { T0 = here->BSIM4gm + here->BSIM4gmbs + here->BSIM4gds; diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index 72495a636..71bc75a81 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -355,9 +355,6 @@ BSIM4instance **InstArray; if (!model->BSIM4ucsGiven) model->BSIM4ucs = (model->BSIM4type == NMOS) ? 1.67 : 1.0; - // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && - // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) if (model->BSIM4v48intVersion<=BSIM4v48V480) { if (!model->BSIM4uaGiven) @@ -2375,11 +2372,6 @@ BSIM4instance **InstArray; if (!here->BSIM4ngconGiven) here->BSIM4ngcon = model->BSIM4ngcon; - // Recursive scaling produces incorrect results after second call to setup() - // here->BSIM4mult_i = here->BSIM4mult_i * here->BSIM4m; - // here->BSIM4mult_q = here->BSIM4mult_q * here->BSIM4m; - // here->BSIM4mult_fn = here->BSIM4mult_fn * here->BSIM4m; - /* Process instance model selectors, some * may override their global counterparts */ diff --git a/src/spicelib/devices/bsim4/b4temp.c b/src/spicelib/devices/bsim4/b4temp.c index f4c76dd65..9e786ab3c 100644 --- a/src/spicelib/devices/bsim4/b4temp.c +++ b/src/spicelib/devices/bsim4/b4temp.c @@ -1372,10 +1372,6 @@ int Fatal_Flag = 0; pParam->BSIM4Aechvb = (model->BSIM4type == NMOS) ? 4.97232e-7 : 3.42537e-7; pParam->BSIM4Bechvb = (model->BSIM4type == NMOS) ? 7.45669e11 : 1.16645e12; - // if ((strcmp(model->BSIM4version, "4.8.1")) && (strncmp(model->BSIM4version, "4.81", 4)) && - // (strcmp(model->BSIM4version, "4.8.2")) && (strncmp(model->BSIM4version, "4.82", 4)) && - // (strcmp(model->BSIM4version, "4.8.3")) && (strncmp(model->BSIM4version, "4.83", 4))) - // { if (model->BSIM4v48intVersion<=BSIM4v48V480) { pParam->BSIM4AechvbEdgeS = pParam->BSIM4Aechvb * pParam->BSIM4weff * model->BSIM4dlcig * pParam->BSIM4ToxRatioEdge; From 8b9047ed8ae58acb2ee3554feb07fc43e2803c13 Mon Sep 17 00:00:00 2001 From: dwarning Date: Tue, 16 Sep 2025 18:44:51 +0200 Subject: [PATCH 18/20] remove obsolete bracket --- src/spicelib/devices/bsim4/b4ld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index 9c840e395..af8713ef8 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -5006,7 +5006,7 @@ line900: - ceqgstot + Istoteq) + mult_q * (ceqqg + ceqqb + ceqqd + ceqqgmid)); } else - { here->BSIM4rhsdb = mult_i * (ceqjd /*+ ceqqjd */) + mult_q * ceqqjd); + { here->BSIM4rhsdb = mult_i * (ceqjd /*+ ceqqjd */) + mult_q * ceqqjd; here->BSIM4rhsbPrime = (mult_i * (ceqbd + ceqbs + Ibtoteq) - mult_q * ceqqb); here->BSIM4rhssb = mult_i * (ceqjs /*+ ceqqjs*/) + mult_q * ceqqjs; here->BSIM4rhssPrime = (mult_i * (ceqdrn - ceqbs + ceqjs - ceqgstot + Istoteq) + mult_q * (ceqqd From aadd12965bc37a9ba8aa4527e24c02e9063f2656 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 17 Sep 2025 10:15:42 +0200 Subject: [PATCH 19/20] Enable plain expression instead of only a number for area in bipolr device instances. --- src/frontend/inpcom.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 031dd9d5b..40d1809d6 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -5283,7 +5283,6 @@ int get_number_terminals(char *c) /* required to make m= 1 a single token m=1 */ ccfree = cc = inp_remove_ws(cc); for (i = j = 0; (i < 12) && (*cc != '\0'); ++i) { - char* comma; name[i] = gettok_instance(&cc); if (search_plain_identifier(name[i], "off")) { @@ -5298,6 +5297,10 @@ int get_number_terminals(char *c) if (strchr(name[i], '=')) { break; } + /* an expression for area {...}, (without area={...})*/ + if (*name[i] == '{') { + break; + } } i--; tfree(ccfree); From 91c5fe7926eaea52869e7fd8736a515c696e2c57 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 17 Sep 2025 14:46:18 +0200 Subject: [PATCH 20/20] Cosmetics: Indentation --- src/spicelib/devices/vsrc/vsrcset.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/spicelib/devices/vsrc/vsrcset.c b/src/spicelib/devices/vsrc/vsrcset.c index e9febf2a7..b539fc493 100644 --- a/src/spicelib/devices/vsrc/vsrcset.c +++ b/src/spicelib/devices/vsrc/vsrcset.c @@ -107,13 +107,13 @@ VSRCunsetup(GENmodel *inModel, CKTcircuit *ckt) VSRCinstance *here; for (model = (VSRCmodel *)inModel; model != NULL; - model = VSRCnextModel(model)) + model = VSRCnextModel(model)) { for (here = VSRCinstances(model); here != NULL; here=VSRCnextInstance(here)) - { - if (here->VSRCbranch > 0) - CKTdltNNum(ckt, here->VSRCbranch); + { + if (here->VSRCbranch > 0) + CKTdltNNum(ckt, here->VSRCbranch); here->VSRCbranch = 0; #ifdef RFSPICE if ((here->VSRCresNode > 0) & (here->VSRCisPort)) @@ -121,7 +121,7 @@ VSRCunsetup(GENmodel *inModel, CKTcircuit *ckt) here->VSRCresNode = 0; #endif - } + } } return OK; }