diff --git a/DEVICES b/DEVICES index 71415a168..a64e2e4aa 100644 --- a/DEVICES +++ b/DEVICES @@ -63,11 +63,6 @@ Table of contents 12.4 BSIMSOI - SOI model (partially/full depleted devices) 12.5 SOI3 - STAG SOI3 Model 13. Verilog-A models - 13.1 EKV MOS model - 13.2 PSP MOS model 102 - 13.3 PSP MOS model 103 - 13.4 HICUM0 Bipolar Model - 13.5 Mextram Bipolar Model 14. XSPICE code models 15. Digital Building Blocks (U instances) @@ -831,8 +826,8 @@ will be updated every time the device specific code is altered or changed to ref 13.7 PSP 103.8 13.8 r2_cmc - More may be made available, user compiled models are possible as well - (See ngspice manual, chapter 13). + More models are available at https://github.com/dwarning/VA-Models, + user compiled models are possible as well (See ngspice manual, chapter 13). 14. XSpice code models diff --git a/FAQ b/FAQ index 391970f65..751c2ec02 100644 --- a/FAQ +++ b/FAQ @@ -1,7 +1,7 @@ - Ngspice F.A.Q.Version 2.9 (ngspice-39 release) + Ngspice F.A.Q.Version 2.9 (ngspice-40 release) Maintained by Holger Vogt - Last update: Jan 24 2023 + Last update: Mar 24 2023 This document contains the Frequently Asked Questions (and Answers) for ngspice project. @@ -252,7 +252,7 @@ The latest version released is: - * ngspice-39 (released on Jan 31 2023) + * ngspice-40 (released on Mar 26 2023) 2.2. What are the latest features in the current release? diff --git a/INSTALL b/INSTALL index ea2bdb479..8555ceea3 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Ngspice installation instructions ================================= -Important notice: since ngspice-35 there has been an update +Important notice: since ngspice-39 there has been an update to the XSPICE code models (analog.cm etc.). Therefore it is not sufficient to only re-make the main executable, you will have to compile and install the code models as well, @@ -28,7 +28,7 @@ Table of contents 8 Operation Controls 9 NGSPICE COMPILATION UNDER WINDOWS OS 9.1 How to make ngspice with MINGW and MSYS - 9.2 make ngspice with MS Visual Studio 2019 or 2022 + 9.2 make ngspice with MS Visual Studio 2022 9.3 make ngspice with pure CYGWIN 9.4 ngspice console app with MINGW or CYGWIN 9.5 cross compiling ngspice for Windows from LINUX @@ -580,9 +580,9 @@ This file describes the procedures to install ngspice from sources. script compile_min_shared.sh. -9.2 make ngspice with MS Visual Studio 2019 and 2022 +9.2 make ngspice with MS Visual Studio 2022 - ngspice may be compiled with MS Visual Studio 2019 or newer. + ngspice may be compiled with MS Visual Studio 2022 or newer. CIDER and XSPICE are included, the code models for XSPICE (*.cm) are made as well. @@ -594,13 +594,13 @@ This file describes the procedures to install ngspice from sources. The directory (visualc) with its files vngspice.sln (project starter) and vngspice.vcproj (project contents) - allows to compile and link ngspice with MS Visual Studio 2019. + allows to compile and link ngspice with MS Visual Studio 2022. /visualc/include contains a dedicated config.h file. It contains the preprocessor definitions required to properly compile the code. strings.h has been necessary during setting up the project. - Install Microsoft Visual Studio 2019 Community with C/C++. For + Install Microsoft Visual Studio 2022 Community with C/C++. For example, the German edition is available at no cost from https://www.visualstudio.com/de/vs/community/. @@ -612,7 +612,7 @@ This file describes the procedures to install ngspice from sources. Goto /ngspice/visualc. - Start MS Visual Studio 2019 by double click onto vngspice.sln. + Start MS Visual Studio 2022 by double click onto vngspice.sln. After MS Visual Studio has opened up, select debug or release version by checking 'Build' , 'Configuration Manager', 'Debug' or 'ReleaseOmp'. @@ -722,11 +722,9 @@ cross-compile-shared.sh. sudo port install automake autoconf libtool bison flex ncurses xorg-libXaw readline fontconfig freetype libomp SM ICE 4. Execute this command: - ./autogen.sh or ./autogen.sh --adms (if you want to enable ADMS) + ./autogen.sh 5. Configure NGSPICE invoking "./configure". A complete set of feature is: ./configure --enable-cider --enable-xspice --enable-openmp --enable-pss --with-readline=yes --enable-debug=no - or (if you want to enable ADMS) - ./configure --enable-adms --enable-cider --enable-xspice --enable-openmp --enable-pss --with-readline=yes --enable-debug=no 6. Compile NGSPICE invoking "make -j4" 7. Install NGSPICE invoking "make install" or "sudo make install" @@ -749,7 +747,7 @@ Resulting dependencies of ngspice /usr/lib/libSystem.B.dylib /usr/local/lib/gcc/11/libgcc_s.1.dylib - 10.5 About compilers + 10.4 About compilers A compile script compile_macos_clang.sh contains all necessary steps for compiling with the Xcode clang/llvm compiler. This compiler however does not support -fopenmp. Therefore you may download and install gcc, e.g. from Homebrew and run the new diff --git a/Makefile.am b/Makefile.am index 6b40d10aa..3fda76704 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,10 +4,10 @@ SUBDIRS = src man tests DIST_SUBDIRS = src man tests EXTRA_DIST = FAQ autogen.sh Stuarts_Poly_Notes \ - ANALYSES BUGS AUTHORS ChangeLog \ - DEVICES NEWS README README.tcl \ - README.shared-xspice README.vdmos \ - README.adms README.utf8 \ + ANALYSES BUGS AUTHORS INSTALL \ + DEVICES INTERNALS NEWS README README.tcl README.optran\ + README.shared-xspice README.vdmos README_OSDI.md\ + README_OSDI_howto README.cpl-gc README.utf8 \ examples m4 visualc \ cross-compile.sh cross-compile-shared.sh \ compile_min.sh compile_linux.sh compile_min_shared.sh \ diff --git a/NEWS b/NEWS index a744b6a9b..810f0c127 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,22 @@ +Ngspice-40, Mar 31st, 2023 +============ +- New features: + + VBIC: Add optional parameters for determining the operation region + + VBIC: Add bvbe, bvbc, bvce, bvsub as SOA parameters + + Add inertial delay to all basic digital code models, make it available + for U devices + + VDMOS default parameters are now similar to IRF540 IRF9540 + + Add function atanh to .control section + + Add a scale factor 'a' (atto, 1e-18) + +- Bug fixes: + + ngspice-40 is mostly a bug-fix release. In conjunction with KiCad and + shared ngspice, inappropriate user inputs have led to crashing ngspice. + + bugs no. 331, 619, 620, 624 have been fixed + + 9 crash bugs (double delete, access NULL pointer etc) removed which have + occurred mostly due to incomplete or faulty inputs. + + Memory leaks removed + Ngspice-39, Jan 31st, 2023 ============ - New features: diff --git a/README_OSDI.md b/README_OSDI.md index e09d46212..cb0ab670e 100644 --- a/README_OSDI.md +++ b/README_OSDI.md @@ -24,10 +24,4 @@ To compile NGSPICE with OSDI support ensure that the `--enable-predictor` and `- The `compile_linux.sh` file enables these flags by default. -## Example/Test Case - -A simple handwritten diode can be found in `test_cases/diode/diode.c`. -In the same directory a script named `test_diode.py` is provided that will compile this model and run some example simulations. -After the script has finished the compilation result `diode.osdi` and the netlist can then be found in `test_cases/diode/test_osdi`. - diff --git a/configure.ac b/configure.ac index 55da0c74c..f7f5f1139 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ # problem to the user. AC_PREREQ([2.59]) -m4_define([ngspice_major_version], [39+]) +m4_define([ngspice_major_version], [40+]) m4_define([ngspice_minor_version], [0]) m4_define([ngspice_version], [ngspice_major_version]) @@ -117,7 +117,7 @@ LT_INIT([shared static]) # --> Set 'LT_NGSPICE_AGE' to 0. LT_NGSPICE_CURRENT=0 -LT_NGSPICE_REVISION=6 +LT_NGSPICE_REVISION=7 LT_NGSPICE_AGE=1 LIBNGSPICE_SO_VERSION=$LT_NGSPICE_CURRENT.$LT_NGSPICE_REVISION.$LT_NGSPICE_AGE diff --git a/examples/digital/auto_bridge/adder_family.cir b/examples/digital/auto_bridge/adder_family.cir new file mode 100644 index 000000000..0eb0946f9 --- /dev/null +++ b/examples/digital/auto_bridge/adder_family.cir @@ -0,0 +1,43 @@ + ADDER - 4 BIT ALL-74HC00-GATE BINARY ADDER WITH AUTOMATIC BRIDGING + * behavioral gate description + * Automatic A/D insertion using bi-directional bridges + +* The NAND gates in the adder have a "family" parameter that determines +* the A/D and D/A bridges that are inserted. For A/D a subcircuit is +* used, defined by the file bridge_demo_family_d_in.subcir. For D/A +* the following interpreter variable sets up the bridges with non-default +* output levels. + +.control +pre_set auto_bridge_demo_family_d_out = ++ ( ".model auto_da dac_bridge(out_high='%g-0.7' out_low=0.9 )" ++ "auto_bridge%d [ %s ] [ %s ] auto_da" 1000 ) +.endc + +.param vcc=5 tripdt=6n + +* +* 2-input NAND gate +* vcc 2 /4.5/5 /6 +* tpd 25n/9n/7n/7n +* tr 19n/7n / /6n + +*** Subcircuit definition: copy of 74HCng_auto.lib with "family" parameter + +.SUBCKT 74HC00 in1 in2 out NVCC NVGND vcc1={vcc} tripdt1={tripdt} +.param td1={1e-9*(9-3-3)*4.0/(vcc1-0.5)} +.param Rout={60*4.0/(vcc1-0.5)} ; standard output driver + +a6 [in1 in2] dout nand1 + +.model nand1 d_nand(rise_delay = {td1} fall_delay = {td1} ++ input_load = 0.5e-12) family="demo_family" + +Rout dout out {Rout} +.ends + +.param vcc=3 tripdt=6n + +.include ../adder_common.inc + +.END diff --git a/examples/digital/auto_bridge/bridge_demo_family_d_in.subcir b/examples/digital/auto_bridge/bridge_demo_family_d_in.subcir new file mode 100644 index 000000000..d37ec8fe1 --- /dev/null +++ b/examples/digital/auto_bridge/bridge_demo_family_d_in.subcir @@ -0,0 +1,11 @@ +* Subcircuit for analogue to digital converter + +.subckt bridge_demo_family_d_in in out vcc=3.3 + +* For no good reason the voltage is reduced before A/D converion + +r1 in in2 1k +r2 in2 0 1k +adc [ in2 ] [ out ] lv_adc +.model lv_adc adc_bridge in_low={vcc/4} in_high={vcc/4} +.ends diff --git a/examples/digital/auto_bridge/vcc.cir b/examples/digital/auto_bridge/vcc.cir new file mode 100644 index 000000000..cbc087c86 --- /dev/null +++ b/examples/digital/auto_bridge/vcc.cir @@ -0,0 +1,23 @@ +Level shift by auto-bridges with different VCCs. + +* A level shifter made by placing digital buffers in subcircuits. + +.param vcc=5 ; Circuit-wide default for auto-bridge levels (not used) + +.subckt buffer in out vcc=3 ; These subcircuits default to 3V. +abuf in out buf +.ends + +.model buf d_buffer + +vin in 0 sin(1.5 1.5 100k) +xb1 in mid buffer ; ADC bridge with VCC=3V will be used. +xb2 mid out buffer vcc=6 ; DAC bridge with 6V swing will be used, +rload out 0 10k ; Analog node forces bridge insertion, + +.control +tran 100n 30u +plot in out +.endc +.end + diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 38118347a..aca467a86 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -250,7 +250,7 @@ inp_list(FILE *file, struct card *deck, struct card *extras, int type) Xprintf(file, "%s\n", here->error); } else if ((*here->line != '*') && (type == LS_RUNNABLE)) { - Xprintf(file, "%s\n", upper(here->line)); + Xprintf(file, "%s\n", here->line); if (here->error) Xprintf(file, "%s\n", here->error); } @@ -279,7 +279,7 @@ inp_list(FILE *file, struct card *deck, struct card *extras, int type) continue; if (type == LS_PHYSICAL) Xprintf(file, "%6d : %s\n", - here->linenum, upper(here->line)); + here->linenum, upper(here->line)); else Xprintf(file, "%s\n", upper(here->line)); if (here->error && (type == LS_PHYSICAL)) @@ -291,7 +291,7 @@ inp_list(FILE *file, struct card *deck, struct card *extras, int type) continue; if (type == LS_PHYSICAL) Xprintf(file, "%6d : %s\n", - there->linenum, upper(there->line)); + there->linenum, upper(there->line)); else Xprintf(file, "%s\n", upper(there->line)); if (there->error && (type == LS_PHYSICAL)) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 9c6d67a07..750a3d5f2 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -169,7 +169,6 @@ static void inp_check_syntax(struct card *deck); static char *inp_spawn_brace(char *s); -static char *inp_pathresolve(const char *name); static char *inp_pathresolve_at(const char *name, const char *dir); char *search_plain_identifier(char *str, const char *identifier); @@ -1756,7 +1755,7 @@ FILE *inp_pathopen(const char *name, const char *mode) if the file isn't in . and it isn't an abs path name. *-------------------------------------------------------------------------*/ -static char *inp_pathresolve(const char *name) +char *inp_pathresolve(const char *name) { struct variable *v; struct stat st; @@ -9822,6 +9821,19 @@ static void inp_check_syntax(struct card *deck) controlled_exit(EXIT_BAD); } + + /* When '.probe alli' is set, disable auto bridging and set a flag */ + for (card = deck; card; card = card->nextcard) { + char* cut_line = card->line; + if (ciprefix(".probe", cut_line) && search_plain_identifier(cut_line, "alli")) { + int i = 0; + bool bi = TRUE; + cp_vset("auto_bridge", CP_NUM, &i); + cp_vset("probe_alli_given", CP_BOOL, &bi); + break; + } + } + for (ii = 0; ii < 10; ii++) subs[ii] = NULL; diff --git a/src/frontend/inpcom.h b/src/frontend/inpcom.h index 3344f8fab..fa8d243f8 100644 --- a/src/frontend/inpcom.h +++ b/src/frontend/inpcom.h @@ -8,5 +8,5 @@ struct card *insert_new_line(struct card *card, char *line, int linenum, int linenum_orig); - +char *inp_pathresolve(const char *name); #endif diff --git a/src/include/ngspice/Makefile.am b/src/include/ngspice/Makefile.am index 3d39f57c9..2e8073a95 100644 --- a/src/include/ngspice/Makefile.am +++ b/src/include/ngspice/Makefile.am @@ -55,6 +55,7 @@ noinst_HEADERS = \ hlpdefs.h \ iferrmsg.h \ ifsim.h \ + inertial.h \ inpdefs.h \ inpmacs.h \ inpptree.h \ diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index a3b4ffed9..d125d8be8 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -97,7 +97,7 @@ are of type bool if sharedspice.h is used externally. */ #ifndef NGSPICE_PACKAGE_VERSION -#define NGSPICE_PACKAGE_VERSION "39+" +#define NGSPICE_PACKAGE_VERSION "40" #endif /* we have NG_BOOL instead of BOOL */ #ifndef HAS_NG_BOOL diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index 682a7f25b..2ac939058 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -184,7 +184,13 @@ IFparm VBICmPTable[] = { /* model parameters */ IOP("vbc_max", VBIC_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"), IOPR("bvbc", VBIC_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"), IOP("vce_max", VBIC_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch"), - IOPR("bvce", VBIC_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch") + IOPR("bvce", VBIC_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch"), + IOP("vsub_max", VBIC_MOD_VSUB_MAX, IF_REAL, "maximum voltage C-substrate branch"), + IOPR("bvsub", VBIC_MOD_VSUB_MAX, IF_REAL, "maximum voltage C-substrate branch"), + IOP("vbefwd", VBIC_MOD_VBEFWD_MAX, IF_REAL, "maximum forward voltage B-E junction"), + IOP("vbcfwd", VBIC_MOD_VBCFWD_MAX, IF_REAL, "maximum forward voltage B-C junction"), + IOP("vsubfwd", VBIC_MOD_VSUBFWD_MAX, IF_REAL, "maximum forward voltage C-substrate junction"), + IOP("selft", VBIC_MOD_SELFT, IF_INTEGER, "0: self-heating off, 1: self-heating on") }; char *VBICnames[] = { diff --git a/src/spicelib/devices/vbic/vbicdefs.h b/src/spicelib/devices/vbic/vbicdefs.h index 1ed3f31f1..fd28eebf0 100644 --- a/src/spicelib/devices/vbic/vbicdefs.h +++ b/src/spicelib/devices/vbic/vbicdefs.h @@ -457,6 +457,7 @@ typedef struct sVBICmodel { /* model structure for a vbic */ double VBICtempExpAVC; double VBICthermalResist; double VBICthermalCapacitance; + int VBICselft; double VBICpunchThroughVoltageBC; double VBICdeplCapCoeff1; double VBICfixedCapacitanceCS; @@ -484,6 +485,10 @@ typedef struct sVBICmodel { /* model structure for a vbic */ double VBICvbeMax; /* maximum voltage over B-E junction */ double VBICvbcMax; /* maximum voltage over B-C junction */ double VBICvceMax; /* maximum voltage over C-E branch */ + double VBICvsubMax; /* maximum voltage over C-substrate branch */ + double VBICvbcfwdMax; /* maximum forward voltage over B-C junction */ + double VBICvbefwdMax; /* maximum forward voltage over C-E branch */ + double VBICvsubfwdMax; /* maximum forward voltage over C-substrate branch */ unsigned VBICtnomGiven : 1; unsigned VBICextCollResistGiven : 1; @@ -571,6 +576,7 @@ typedef struct sVBICmodel { /* model structure for a vbic */ unsigned VBICtempExpNFGiven : 1; unsigned VBICtempExpAVCGiven : 1; unsigned VBICthermalResistGiven : 1; + unsigned VBICselftGiven : 1; unsigned VBICthermalCapacitanceGiven : 1; unsigned VBICpunchThroughVoltageBCGiven : 1; unsigned VBICdeplCapCoeff1Given : 1; @@ -598,6 +604,10 @@ typedef struct sVBICmodel { /* model structure for a vbic */ unsigned VBICvbeMaxGiven : 1; unsigned VBICvbcMaxGiven : 1; unsigned VBICvceMaxGiven : 1; + unsigned VBICvsubMaxGiven : 1; + unsigned VBICvbcfwdMaxGiven : 1; + unsigned VBICvbefwdMaxGiven : 1; + unsigned VBICvsubfwdMaxGiven : 1; } VBICmodel; #ifndef NPN @@ -734,6 +744,11 @@ enum { VBIC_MOD_VBE_MAX, VBIC_MOD_VBC_MAX, VBIC_MOD_VCE_MAX, + VBIC_MOD_VSUB_MAX, + VBIC_MOD_VBEFWD_MAX, + VBIC_MOD_VBCFWD_MAX, + VBIC_MOD_VSUBFWD_MAX, + VBIC_MOD_SELFT, }; /* device questions */ diff --git a/src/spicelib/devices/vbic/vbicmask.c b/src/spicelib/devices/vbic/vbicmask.c index d5f61d901..757ee7771 100644 --- a/src/spicelib/devices/vbic/vbicmask.c +++ b/src/spicelib/devices/vbic/vbicmask.c @@ -363,12 +363,27 @@ VBICmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case VBIC_MOD_VCE_MAX: value->rValue = here->VBICvceMax; return(OK); + case VBIC_MOD_VSUB_MAX: + value->rValue = here->VBICvsubMax; + return(OK); + case VBIC_MOD_VBEFWD_MAX: + value->rValue = here->VBICvbefwdMax; + return(OK); + case VBIC_MOD_VBCFWD_MAX: + value->rValue = here->VBICvbcfwdMax; + return(OK); + case VBIC_MOD_VSUBFWD_MAX: + value->rValue = here->VBICvsubfwdMax; + return(OK); case VBIC_MOD_TYPE: if (here->VBICtype == NPN) value->sValue = "npn"; else value->sValue = "pnp"; return(OK); + case VBIC_MOD_SELFT: + value->iValue = here->VBICselft; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/vbic/vbicmpar.c b/src/spicelib/devices/vbic/vbicmpar.c index 16bd00386..cac58ad3f 100644 --- a/src/spicelib/devices/vbic/vbicmpar.c +++ b/src/spicelib/devices/vbic/vbicmpar.c @@ -509,6 +509,26 @@ VBICmParam(int param, IFvalue *value, GENmodel *inModel) mods->VBICvceMax = value->rValue; mods->VBICvceMaxGiven = TRUE; break; + case VBIC_MOD_VSUB_MAX: + mods->VBICvsubMax = value->rValue; + mods->VBICvsubMaxGiven = TRUE; + break; + case VBIC_MOD_VBEFWD_MAX: + mods->VBICvbefwdMax = value->rValue; + mods->VBICvbefwdMaxGiven = TRUE; + break; + case VBIC_MOD_VBCFWD_MAX: + mods->VBICvbcfwdMax = value->rValue; + mods->VBICvbcfwdMaxGiven = TRUE; + break; + case VBIC_MOD_VSUBFWD_MAX: + mods->VBICvsubfwdMax = value->rValue; + mods->VBICvsubfwdMaxGiven = TRUE; + break; + case VBIC_MOD_SELFT: + mods->VBICselft = value->iValue; + mods->VBICselftGiven = TRUE; + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/vbic/vbicsetup.c b/src/spicelib/devices/vbic/vbicsetup.c index ef6b238ea..bbb90f7ae 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -391,6 +391,21 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->VBICvceMaxGiven) { model->VBICvceMax = 1e99; } + if(!model->VBICvsubMaxGiven) { + model->VBICvsubMax = 1e99; + } + if (!model->VBICvbefwdMaxGiven) { + model->VBICvbefwdMax = 0.2; + } + if (!model->VBICvbcfwdMaxGiven) { + model->VBICvbcfwdMax = 0.2; + } + if (!model->VBICvsubfwdMaxGiven) { + model->VBICvsubfwdMax = 0.2; + } + if(!model->VBICselftGiven) { + model->VBICselft = 0; + } /* loop through all the instances of the model */ for (here = VBICinstances(model); here != NULL ; @@ -472,7 +487,8 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } } - if((model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0)) + if((model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0) + && model->VBICselftGiven && model->VBICselft == 1) here->VBIC_selfheat = 1; else here->VBIC_selfheat = 0; diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index 34d6755ac..c436b16d7 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -17,14 +17,16 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) { VBICmodel *model = (VBICmodel *) inModel; VBICinstance *here; - double vbe, vbc, vce; /* actual bjt voltages */ + double vbe, vbc, vce, vsub; /* actual bjt voltages */ int maxwarns; - static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0; + static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0, warns_vsub = 0, warns_op = 0; if (!ckt) { warns_vbe = 0; warns_vbc = 0; warns_vce = 0; + warns_vsub = 0; + warns_op = 0; return OK; } @@ -32,39 +34,95 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) for (; model; model = VBICnextModel(model)) { - for (here = VBICinstances(model); here; here=VBICnextInstance(here)) { + for (here = VBICinstances(model); here; here = VBICnextInstance(here)) { - vbe = fabs(ckt->CKTrhsOld [here->VBICbaseNode] - - ckt->CKTrhsOld [here->VBICemitNode]); - vbc = fabs(ckt->CKTrhsOld [here->VBICbaseNode] - - ckt->CKTrhsOld [here->VBICcollNode]); - vce = fabs(ckt->CKTrhsOld [here->VBICcollNode] - - ckt->CKTrhsOld [here->VBICemitNode]); + vbe = fabs(ckt->CKTrhsOld[here->VBICbaseNode] - + ckt->CKTrhsOld[here->VBICemitNode]); + vbc = fabs(ckt->CKTrhsOld[here->VBICbaseNode] - + ckt->CKTrhsOld[here->VBICcollNode]); + vce = fabs(ckt->CKTrhsOld[here->VBICcollNode] - + ckt->CKTrhsOld[here->VBICemitNode]); + vsub = fabs(ckt->CKTrhsOld[here->VBICcollNode] - + ckt->CKTrhsOld[here->VBICsubsNode]); if (vbe > model->VBICvbeMax) if (warns_vbe < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vbe|=%g has exceeded Vbe_max=%g\n", - vbe, model->VBICvbeMax); + soa_printf(ckt, (GENinstance*)here, + "|Vbe|=%g has exceeded Vbe_max=%g\n", + vbe, model->VBICvbeMax); warns_vbe++; } if (vbc > model->VBICvbcMax) if (warns_vbc < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vbc|=%g has exceeded Vbc_max=%g\n", - vbc, model->VBICvbcMax); + soa_printf(ckt, (GENinstance*)here, + "|Vbc|=%g has exceeded Vbc_max=%g\n", + vbc, model->VBICvbcMax); warns_vbc++; } if (vce > model->VBICvceMax) if (warns_vce < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vce|=%g has exceeded Vce_max=%g\n", - vce, model->VBICvceMax); + soa_printf(ckt, (GENinstance*)here, + "|Vce|=%g has exceeded Vce_max=%g\n", + vce, model->VBICvceMax); warns_vce++; } + if (vsub > model->VBICvsubMax) + if (warns_vsub < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "|Vce|=%g has exceeded Vce_max=%g\n", + vsub, model->VBICvsubMax); + warns_vsub++; + } + + /* substrate diode is forward biased */ + if (model->VBICtype * (ckt->CKTrhsOld[here->VBICsubsNode] - + ckt->CKTrhsOld[here->VBICcollNode]) > model->VBICvsubfwdMax) { + /* substrate leakage */ + if (warns_vsub < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "substrate juntion is forward biased\n"); + warns_vsub++; + } + } + + /* operating point information */ + if (ckt->CKTsoaCheck == 2) { + if (vbe <= model->VBICvbefwdMax && vbc <= model->VBICvbefwdMax) { + /*off*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is off\n"); + warns_op++; + } + } + else if (vbe > model->VBICvbefwdMax && vbc > model->VBICvbefwdMax) { + /*saturation*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is in saturation\n"); + warns_op++; + } + } + else if (vbe > model->VBICvbefwdMax && vbc <= model->VBICvbefwdMax) { + /*forward*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is forward biased\n"); + warns_op++; + } + } + else if (vbe <= model->VBICvbefwdMax && vbc > model->VBICvbefwdMax) { + /*reverse*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is reverse biased\n"); + warns_op++; + } + } + } } } diff --git a/src/xspice/evt/evtcheck_nodes.c b/src/xspice/evt/evtcheck_nodes.c index a95e0e82a..3bbdaebfb 100644 --- a/src/xspice/evt/evtcheck_nodes.c +++ b/src/xspice/evt/evtcheck_nodes.c @@ -32,7 +32,7 @@ When using XSPICE to simulate digital devices in a mixed-mode simulation, bridging devices must be included in the circuit to pass signals between the analogue simulator and XSPICE. Such devices may be included in the netlist, -or they may can be inserted automatically. Different types of automatic +or they can be inserted automatically. Different types of automatic bridge may exist in the same circuit, depending on signal direction and characteristics of the connected device, for example digital devices powered by differing voltages. Non-digital XSPICE nodes are supported. @@ -95,21 +95,26 @@ for device libraries whose devices are defined by subcircuits. the enclosing subcircuits for a definition of the parameter. If found, set vcc from the parameter. -3: If a command interpreter variable "no_auto_bridge_family": exists, go to - step 5. Search the connected device instances for a parameter, - "family" with a string value. The first one found will be used. - If the first character of the value is not '*', the setup card will - be ".include bridge_FFFFF_DDD.cir" where FFFFF is the family and - DDD is the signal direction for the XSPICE device: "in", "out" or - "inout". The device card will be "Xauto_bridge%d %s %s - bridge_FFFFF_DDD vcc=%g", so a suitably parameterised subcircuit - must be defined in the included file. +3: If a command interpreter variable "no_auto_bridge_family": exists, + go to step 5. Search the connected XSPICE device instances for a + parameter, "family" with a string value. The first one found will + be used. If no such instance exists, search for a string-valued + parameter, "family", in enclosing subcircuits, as in step 2. If + the first character of the value is not '*', the setup card may be + ".include bridge_FFFFF_TTTT_DDD.subcir" where FFFFF is the family, + TTTT is as before and DDD is the signal direction for the XSPICE + device: "in", "out" or "inout". This form will be used only when + the required file can be found. In that case, the device card will + be "Xauto_bridge%d %s %s bridge_FFFFF_TTTT_DDD vcc=%g", so a + suitably parameterised subcircuit must be defined in the included + file. -4: If the first character of "family" was '*', look for a variable - "auto_bridge_FFFFF_TTTT_DDD" where FFFFF is the family without '*', - TTTT is the node type string and DDD is the direction. So this might be - "auto_bridge_74HCT_d_inout" for a digital node. Use the variable's value - as in step 6, proceeding to step 5 if checks fail. +4: If the first character of "family" was '*', or no file was found, + look for a variable "auto_bridge_FFFFF_TTTT_DDD" where FFFFF is the + family without '*', TTTT is the node type string and DDD is the + direction. So this might be "auto_bridge_74HCT_d_inout" for a + digital node. Use the variable's value as in step 6, proceeding to + step 5 if checks fail. 5: Look for a variable "auto_bridge_TTTT_DDD" where TTTT and DDD are as before. @@ -160,9 +165,9 @@ for device libraries whose devices are defined by subcircuits. and invoked by: - set auto_bridge_d_out_30 = ( ".include test_sub.cir" - + "xauto_buf%d %s %s auto_buf vcc=%g" - + 1 ) + set auto_bridge_d_out = ( ".include test_sub.subcir" + + "xauto_buf%d %s %s auto_buf vcc=%g" + + 1 ) */ /* Working information about a type of bridge. */ @@ -195,10 +200,15 @@ static struct card *expand_deck(struct card *head) struct card *card, *next; char **pointers; int i, dico; + bool save_debug; - /* Save the current parameter symbol table. */ + /* Save the current parameter symbol table and debug global. + * Prevent overwriting of debug output in inp_readall(). + */ dico = nupa_add_dicoslist(); + save_debug = ft_ngdebug; + ft_ngdebug = FALSE; /* Count the cards, allocate and fill a pointer array. */ @@ -221,6 +231,7 @@ static struct card *expand_deck(struct card *head) circarray = pointers; card = inp_readall(NULL, Infile_Path, FALSE, TRUE, NULL); card = inp_subcktexpand(card); + ft_ngdebug = save_debug; /* Destroy the parameter table that was created in subcircuit/parameter * expansion and restore the previous version. @@ -479,8 +490,8 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node, family = NULL; deep = scan_devices(event_node, ckt, &family); - /* Look for a real parameter (.param type) in the device's subcircuit - * and those enclosing it. + /* Look for a real parameter (.param type) and perhaps a string-valued + * "family" parameter in the device's subcircuit and those enclosing it. */ snprintf(buff, sizeof buff, "%s", deep); @@ -490,7 +501,11 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node, snprintf(dot + 1, sizeof buff - (size_t)(dot - buff), "%s", vcc_parm); vcc = nupa_get_param(buff, &ok); } - if (ok) + if (!family) { + snprintf(dot + 1, sizeof buff - (size_t)(dot - buff), "family"); + family = nupa_get_string_param(buff); + } + if (ok && family) break; *dot = '\0'; dot = strrchr(buff, '.'); @@ -506,12 +521,29 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node, } } + if (!family) + family = nupa_get_string_param("family"); if (family && cp_getvar("no_auto_bridge_family", CP_BOOL, NULL, 0)) family = NULL; - if (family && *family == '*') { - s_family = family + 1; - family = NULL; // Not used for matching. + if (family) { + if (*family == '*') { + s_family = family + 1; // Use variable look-up. + } else { + char *fam_inc_path; + + /* Check if an include file exists for the family. */ + + snprintf(buff, sizeof buff, "bridge_%s_%s_%s.subcir", + family, type_name, dirs[direction]); + fam_inc_path = inp_pathresolve(buff); + if (fam_inc_path) { + tfree(fam_inc_path); + s_family = NULL; + } else { + s_family = family; // Use variable look-up. + } + } } else { s_family = NULL; } @@ -523,10 +555,19 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node, bridge->direction == direction) { if (family) { if (!strcmp(family, bridge->family)) { - /* Return vcc for formatting: requires bridge->max == 1. */ + if (!s_family && bridge->max == 1) { + /* Set bridge vcc for formatting. */ - bridge->vcc = vcc; - break; + bridge->vcc = vcc; + break; + } else { + /* Using cards from variable, or shared sub-circuit: + * vcc must also match. + */ + + if (bridge->vcc == vcc) + break; + } } } else if (bridge->vcc == vcc) { // Match vcc. break; @@ -538,23 +579,23 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node, /* Determine if a bridging element exists, starting with the node type. */ - if (family) { - /* Use standard pattern for known parts family. */ - - snprintf(buff, sizeof buff, ".include bridge_%s_%s.cir", - family, dirs[direction]); - setup = copy(buff); - snprintf(buff, sizeof buff, - "Xauto_bridge%%d %%s %%s bridge_%s_%s vcc=%%g", - family, dirs[direction]); - format = copy(buff); - max = 1; - } else if (s_family) { + if (s_family) { /* Family variable lookup. */ snprintf(buff, sizeof buff, "auto_bridge_%s_%s_%s", s_family, type_name, dirs[direction]); cp_getvar(buff, CP_LIST, &cvar, sizeof cvar); + } else if (family) { + /* Use standard pattern for known parts family. */ + + snprintf(buff, sizeof buff, ".include bridge_%s_%s_%s.subcir", + family, type_name, dirs[direction]); + setup = copy(buff); + snprintf(buff, sizeof buff, + "Xauto_bridge%%d %%s %%s bridge_%s_%s_%s vcc=%%g", + family, type_name, dirs[direction]); + format = copy(buff); + max = 1; } if (!format && !cvar) { @@ -667,8 +708,13 @@ bool Evtcheck_nodes( int nl; if (strcmp(event_node->name, analog_node->name) == 0) { - if (show == AB_OFF) + if (show == AB_OFF) { + if (cp_getvar("probe_alli_given", CP_BOOL, NULL, 0)) + fprintf(stderr, "\nDot command '.probe alli' and digital nodes are not compatible.\n"); + FREE(errMsg); + errMsg = copy("Auto bridging is switched off"); return FALSE; // Auto-bridge disabled + } bridge = find_bridge(event_node, ckt, &bridge_list); if (!bridge) { /* Fatal, circuit cannot run. */ diff --git a/src/xspice/evt/evtsetup.c b/src/xspice/evt/evtsetup.c index 761a40bba..62024531d 100644 --- a/src/xspice/evt/evtsetup.c +++ b/src/xspice/evt/evtsetup.c @@ -303,6 +303,7 @@ void Evt_purge_free_outputs(void) for (i = 0; i < g_evt_num_udn_types; ++i) { output_event = g_evt_udn_info[i]->free_list; + g_evt_udn_info[i]->free_list = NULL; while (output_event) { next = output_event->next; tfree(output_event->value); diff --git a/src/xspice/mif/mifdelete.c b/src/xspice/mif/mifdelete.c index 24291a13d..60230b6ff 100644 --- a/src/xspice/mif/mifdelete.c +++ b/src/xspice/mif/mifdelete.c @@ -43,6 +43,7 @@ NON-STANDARD FEATURES #include "ngspice/mifproto.h" #include "ngspice/mifdefs.h" +#include "ngspice/evt.h" #if defined(_MSC_VER) || defined(__MINGW32__) #include "ngspice/mifparse.h" @@ -134,8 +135,16 @@ MIFdelete(GENinstance *gen_inst) /* Free the basic port structure allocated in MIFget_port */ num_port = here->conn[i]->size; for (j = 0; j < num_port; j++) { - /* Memory allocated in mif_inp2.c */ + Evt_Output_Event_t *evt; + + /* Memory allocated in mif_inp2.c and evtload.c. */ + FREE(here->conn[i]->port[j]->type_str); + evt = here->conn[i]->port[j]->next_event; + if (evt) { + FREE(evt->value); + FREE(evt); + } FREE(here->conn[i]->port[j]); } FREE(here->conn[i]->port); diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 159ebc085..804859e93 100644 --- a/visualc/src/include/ngspice/config.h +++ b/visualc/src/include/ngspice/config.h @@ -15,7 +15,7 @@ #define PACKAGE "ngspice" /* Version number of package */ -#define VERSION "39+" +#define VERSION "40+" /* Define the directory for executables */ #define NGSPICEBINDIR "../bin"