From 4309bad14d2d5cd0bff94aed799ff46a65cbdb5c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 3 Feb 2023 18:50:55 +0100 Subject: [PATCH 01/91] Set the recounter to 0 upon every exit from function inp_get_param_level --- src/frontend/inpcom.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 9c5591e88..8099347d3 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -4544,11 +4544,14 @@ static int inp_get_param_level( " You probably do have a circular parameter dependency at line\n"); fprintf(stderr, " %s\n", deps[param_num].card->line); + recounter = 0; controlled_exit(EXIT_FAILURE); } - if (deps[param_num].level != -1) + if (deps[param_num].level != -1) { + recounter = 0; return deps[param_num].level; + } for (i = 0; deps[param_num].depends_on[i]; i++) { @@ -4560,6 +4563,7 @@ static int inp_get_param_level( fprintf(stderr, "ERROR: unable to find dependency parameter for %s!\n", deps[param_num].param_name); + recounter = 0; controlled_exit(EXIT_FAILURE); } From f9ed3fd080bfb88804e530114071ab840a1238ad Mon Sep 17 00:00:00 2001 From: holger Date: Sun, 5 Feb 2023 11:25:42 +0100 Subject: [PATCH 02/91] Patch by Robert Turnbull: remove warning messages --- src/xspice/icm/digital/d_osc/cfunc.mod | 3 ++- src/xspice/icm/digital/d_pwm/cfunc.mod | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/xspice/icm/digital/d_osc/cfunc.mod b/src/xspice/icm/digital/d_osc/cfunc.mod index b76386132..567b405cf 100644 --- a/src/xspice/icm/digital/d_osc/cfunc.mod +++ b/src/xspice/icm/digital/d_osc/cfunc.mod @@ -20,6 +20,7 @@ MODIFICATIONS 23 Aug 1991 Jeffrey P. Murray 30 Sep 1991 Jeffrey P. Murray 09 Nov 2022 Holger Vogt + 05 Jan 2023 Robert Turnbull SUMMARY @@ -54,7 +55,7 @@ NON-STANDARD FEATURES #include "d_osc.h" /* ...contains macros & type defns. for this model. 7/24/91 - JPM */ - +#include /*=== CONSTANTS ========================*/ diff --git a/src/xspice/icm/digital/d_pwm/cfunc.mod b/src/xspice/icm/digital/d_pwm/cfunc.mod index e64d6efcd..3d73e4ced 100644 --- a/src/xspice/icm/digital/d_pwm/cfunc.mod +++ b/src/xspice/icm/digital/d_pwm/cfunc.mod @@ -20,6 +20,7 @@ MODIFICATIONS 23 Aug 1991 Jeffrey P. Murray 30 Sep 1991 Jeffrey P. Murray 06 Oct 2022 Holger Vogt + 05 Jan 2023 Robert Turnbull SUMMARY @@ -54,6 +55,7 @@ NON-STANDARD FEATURES #include "d_pwm.h" /* ...contains macros & type defns. for this model. 7/24/91 - JPM */ +#include From 3ff9643f4919b6a9f65f4da135b3699358d6705f Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 22 Jan 2023 16:32:09 +0100 Subject: [PATCH 03/91] Add a scale factor 'a' (atto, 1e-18) --- src/frontend/inpcom.c | 2 ++ src/frontend/numparam/xpressn.c | 1 + src/frontend/parser/numparse.c | 5 +++++ src/spicelib/parser/inpeval.c | 12 ++++++++++++ src/xspice/icm/digital/d_source/cfunc.mod | 4 ++++ src/xspice/icm/digital/d_state/cfunc.mod | 4 ++++ 6 files changed, 28 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 8099347d3..16fea8644 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -2490,6 +2490,8 @@ static int is_a_modelname(char *s, const char* line) case 'P': case 'f': case 'F': + case 'a': + case 'A': st = st + 1; break; case 'm': diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index fd0749bc3..2a59f807d 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -610,6 +610,7 @@ parseunit(const char *s) case 'N': return 1e-9; case 'P': return 1e-12; case 'F': return 1e-15; + case 'A': return 1e-18; default : return 1; } } diff --git a/src/frontend/parser/numparse.c b/src/frontend/parser/numparse.c index ccb2d5e83..3ea6c62d6 100644 --- a/src/frontend/parser/numparse.c +++ b/src/frontend/parser/numparse.c @@ -95,6 +95,11 @@ int ft_numparse(char **p_str, bool whole, double *p_val) expo = -15.0; ++p_cur; break; + case 'a': + case 'A': + expo = -18.0; + ++p_cur; + break; case 'm': case 'M': { char ch_cur; diff --git a/src/spicelib/parser/inpeval.c b/src/spicelib/parser/inpeval.c index 8e8b24c9b..13dcaa81b 100644 --- a/src/spicelib/parser/inpeval.c +++ b/src/spicelib/parser/inpeval.c @@ -169,6 +169,10 @@ INPevaluate(char **line, int *error, int gobble) case 'F': expo1 = expo1 - 15; break; + case 'a': + case 'A': + expo1 = expo1 - 18; + break; case 'm': case 'M': if (((here[1] == 'E') || (here[1] == 'e')) && @@ -626,6 +630,10 @@ INPevaluateRKM_C(char** line, int* error, int gobble) expo1 = expo1 - 15; hasmulti = TRUE; break; + case 'a': + case 'A': + expo1 = expo1 - 18; + break; case 'm': case 'M': if (((here[1] == 'E') || (here[1] == 'e')) && @@ -860,6 +868,10 @@ INPevaluateRKM_L(char** line, int* error, int gobble) expo1 = expo1 - 15; hasmulti = TRUE; break; + case 'a': + case 'A': + expo1 = expo1 - 18; + break; case 'm': case 'M': if (((here[1] == 'E') || (here[1] == 'e')) && diff --git a/src/xspice/icm/digital/d_source/cfunc.mod b/src/xspice/icm/digital/d_source/cfunc.mod index da428c4a5..716ebb387 100644 --- a/src/xspice/icm/digital/d_source/cfunc.mod +++ b/src/xspice/icm/digital/d_source/cfunc.mod @@ -429,6 +429,10 @@ double *p_value ) /* OUT - The numerical value */ scale_factor = 1.0e-15; break; + case 'a': + scale_factor = 1.0e-18; + break; + case 'm': i++; if(i >= len) { diff --git a/src/xspice/icm/digital/d_state/cfunc.mod b/src/xspice/icm/digital/d_state/cfunc.mod index 472738f98..4666e8b8d 100644 --- a/src/xspice/icm/digital/d_state/cfunc.mod +++ b/src/xspice/icm/digital/d_state/cfunc.mod @@ -441,6 +441,10 @@ double *p_value ) /* OUT - The numerical value */ scale_factor = 1.0e-15; break; + case 'a': + scale_factor = 1.0e-18; + break; + case 'm': i++; if(i >= len) { From ff9c98f59784f3ebca1239ae29e289939b7751ae Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 6 Feb 2023 12:05:59 +0100 Subject: [PATCH 04/91] Patch 112 by Robert Turnbull Remove compiler warning. --- src/misc/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/string.c b/src/misc/string.c index 147fe3648..1374607da 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -88,7 +88,7 @@ char *dup_string(const char *str, size_t n_char) char *tvprintf(const char *fmt, va_list args) { - char buf[1024]; + static char buf[1024]; char *p = buf; int size = sizeof(buf); int nchars; From c2fb32f98ab91084bd5fc5fcb4539021c4143d38 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Feb 2023 11:03:10 +0100 Subject: [PATCH 05/91] really run a dc simulation --- examples/osdi/bsimcmg/simple_inverter_dc.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/osdi/bsimcmg/simple_inverter_dc.sp b/examples/osdi/bsimcmg/simple_inverter_dc.sp index 13b164094..71ad6aa53 100644 --- a/examples/osdi/bsimcmg/simple_inverter_dc.sp +++ b/examples/osdi/bsimcmg/simple_inverter_dc.sp @@ -12,10 +12,10 @@ NP1 vout vin supply supply BSIMCMG_osdi_P NN1 vout vin 0 0 BSIMCMG_osdi_N * --- DC Analysis --- -*.dc vsig 0 1 0.01 +.dc vsig 0 1 0.01 * --- Transient Analysis --- -.tran 10n 2u +*.tran 10n 2u .control * pre_osdi ../osdi_libs/bsimcmg.osdi From 5cb5d218c9d15e735af0975a9bb629e629437f06 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Feb 2023 11:04:09 +0100 Subject: [PATCH 06/91] Remove the obsolete RETSIGTYPE, replace by void --- configure.ac | 1 - src/frontend/aspice.c | 4 ++-- src/frontend/evaluate.c | 4 ++-- src/frontend/parser/unixcom.c | 2 +- src/frontend/resource.c | 4 ++-- src/frontend/signal_handler.c | 18 +++++++++--------- src/frontend/signal_handler.h | 18 +++++++++--------- src/include/ngspice/defines.h | 4 ++-- visualc/src/include/ngspice/config.h | 3 --- 9 files changed, 27 insertions(+), 31 deletions(-) diff --git a/configure.ac b/configure.ac index 5492f6bf0..a72f08971 100644 --- a/configure.ac +++ b/configure.ac @@ -888,7 +888,6 @@ AM_CONDITIONAL([OLDAPPS], [test "x$enable_oldapps" = xyes]) # Check for a few typdefs: AC_TYPE_PID_T -AC_TYPE_SIGNAL # sighandler_t is the type of the signal handler on GNU variants, # sig_t is the type of a signal handler on 4.4BSD's, diff --git a/src/frontend/aspice.c b/src/frontend/aspice.c index 671708b38..7125d64ea 100644 --- a/src/frontend/aspice.c +++ b/src/frontend/aspice.c @@ -52,7 +52,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group # define SEEK_SET 0 #endif -static RETSIGTYPE sigchild(void); +static void sigchild(void); struct proc { int pr_pid; /* The pid of the spice job. */ @@ -163,7 +163,7 @@ com_jobs(wordlist *wl) } -static RETSIGTYPE +static void sigchild(void) { numchanged++; diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c index 044f85d51..f38aff246 100644 --- a/src/frontend/evaluate.c +++ b/src/frontend/evaluate.c @@ -20,7 +20,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/sim.h" /* To get SV_VOLTAGE definition */ -static RETSIGTYPE sig_matherr(void); +static void sig_matherr(void); static struct dvec *apply_func(struct func *func, struct pnode *arg); static struct dvec *ft_ternary(struct pnode *node); static char *mkcname(char what, char *v1, char *v2); @@ -33,7 +33,7 @@ static char *mkcname(char what, char *v1, char *v2); static JMP_BUF matherrbuf; -static RETSIGTYPE +static void sig_matherr(void) { fprintf(cp_err, "Error: argument out of range for math function\n"); diff --git a/src/frontend/parser/unixcom.c b/src/frontend/parser/unixcom.c index 6186acae2..6cbc46da7 100644 --- a/src/frontend/parser/unixcom.c +++ b/src/frontend/parser/unixcom.c @@ -187,7 +187,7 @@ tryexec(char *name, char *argv[]) # endif int pid, j; - RETSIGTYPE (*svint)(), (*svquit)(), (*svtstp)(); + void (*svint)(), (*svquit)(), (*svtstp)(); pid = vfork(); if (pid == 0) { diff --git a/src/frontend/resource.c b/src/frontend/resource.c index b8013eec9..09b40863b 100644 --- a/src/frontend/resource.c +++ b/src/frontend/resource.c @@ -570,7 +570,7 @@ static int get_sysmem(struct sys_mem *memall) static JMP_BUF env; -static RETSIGTYPE +static void fault(void) { signal(SIGSEGV, (SIGNAL_FUNCTION) fault); /* SysV style */ @@ -586,7 +586,7 @@ baseaddr(void) #else char *low, *high, *at; long x; - RETSIGTYPE (*orig_signal)(); + void (*orig_signal)(); if (getenv("SPICE_NO_DATASEG_CHECK")) return 0; diff --git a/src/frontend/signal_handler.c b/src/frontend/signal_handler.c index 5b414e8d0..058c3c352 100644 --- a/src/frontend/signal_handler.c +++ b/src/frontend/signal_handler.c @@ -70,7 +70,7 @@ ft_sigintr_cleanup(void) /* invoke this function upon keyboard interrupt */ -RETSIGTYPE +void ft_sigintr(void) { static int interrupt_counter = 0; @@ -103,7 +103,7 @@ ft_sigintr(void) } -RETSIGTYPE +void sigfloat(int code) { fperror("Error", code); @@ -117,7 +117,7 @@ sigfloat(int code) #ifdef SIGTSTP -RETSIGTYPE +void sigstop(void) { gr_clean(); @@ -127,7 +127,7 @@ sigstop(void) } -RETSIGTYPE +void sigcont(void) { (void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop); @@ -141,7 +141,7 @@ sigcont(void) /* Special (void) signal handlers. */ -RETSIGTYPE +void sigill(void) { fprintf(cp_err, "\ninternal error -- illegal instruction\n"); @@ -149,7 +149,7 @@ sigill(void) } -RETSIGTYPE +void sigbus(void) { fprintf(cp_err, "\ninternal error -- bus error\n"); @@ -157,7 +157,7 @@ sigbus(void) } -RETSIGTYPE +void sigsegv(void) { fprintf(cp_err, "\ninternal error -- segmentation violation\n"); @@ -167,7 +167,7 @@ sigsegv(void) fatal(); } -RETSIGTYPE +void sigsegvsh(void) { fprintf(cp_err, "\ninternal error -- segmentation violation\n"); @@ -175,7 +175,7 @@ sigsegvsh(void) } -RETSIGTYPE +void sig_sys(void) { fprintf(cp_err, "\ninternal error -- bad argument to system call\n"); diff --git a/src/frontend/signal_handler.h b/src/frontend/signal_handler.h index cfe1eca46..7ef02c6da 100644 --- a/src/frontend/signal_handler.h +++ b/src/frontend/signal_handler.h @@ -6,15 +6,15 @@ #ifndef ngspice_SIGNAL_HANDLER_H #define ngspice_SIGNAL_HANDLER_H -RETSIGTYPE ft_sigintr(void); -RETSIGTYPE sigfloat(int code); -RETSIGTYPE sigstop(void); -RETSIGTYPE sigcont(void); -RETSIGTYPE sigill(void); -RETSIGTYPE sigbus(void); -RETSIGTYPE sigsegv(void); -RETSIGTYPE sigsegvsh(void); -RETSIGTYPE sig_sys(void); +void ft_sigintr(void); +void sigfloat(int code); +void sigstop(void); +void sigcont(void); +void sigill(void); +void sigbus(void); +void sigsegv(void); +void sigsegvsh(void); +void sig_sys(void); extern JMP_BUF jbuf; diff --git a/src/include/ngspice/defines.h b/src/include/ngspice/defines.h index d5dadd650..62e2737bd 100644 --- a/src/include/ngspice/defines.h +++ b/src/include/ngspice/defines.h @@ -101,7 +101,7 @@ #define HAS_TIME_H #define HAS_RLIMIT_ - +#define void void #ifndef SIGNAL_FUNCTION # ifdef HAVE_SIGHANDLER_T @@ -111,7 +111,7 @@ # elif HAVE___SIGHANDLER_T # define SIGNAL_FUNCTION __sighandler_t # else -# define SIGNAL_FUNCTION RETSIGTYPE (*)(int) +# define SIGNAL_FUNCTION void (*)(int) # endif #endif diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 47a327dcc..0381179f1 100644 --- a/visualc/src/include/ngspice/config.h +++ b/visualc/src/include/ngspice/config.h @@ -499,9 +499,6 @@ /* Define if you want to debug pole-zero analysis */ /* #undef PZDEBUG */ -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - /* Define to the type of arg 1 for `select'. */ /* #undef SELECT_TYPE_ARG1 */ From aafcb68522eadd70bfbe75ed3de69b00c89bd42b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Feb 2023 14:46:22 +0100 Subject: [PATCH 07/91] Remove obsolete macros, replace other by newer versions --- configure.ac | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index a72f08971..9cf63f46e 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ AC_REVISION([$Revision: ngspice_version$]) AC_CONFIG_SRCDIR([src/ngspice.c]) # Create a configuration header -AC_CONFIG_HEADER([src/include/ngspice/config.h]) +AC_CONFIG_HEADERS([src/include/ngspice/config.h]) # Initialize automake stuff AM_INIT_AUTOMAKE([-Wall -Werror nostdinc serial-tests]) @@ -360,19 +360,11 @@ if test "x$enable_gprof" = xyes; then fi # Checks for ANSI-C header files. -AC_HEADER_STDC + AC_CHECK_HEADERS([strings.h]) if test "x$enable_ansi" = xyes; then - AC_PROG_CC() - AC_DIAGNOSE([obsolete], [AM_PROG_CC_STDC: - your code should no longer depend upon `am_cv_prog_cc_stdc', but upon - `ac_cv_prog_cc_stdc'. Remove this warning and the assignment when - you adjust the code. You can also remove the above call to - AC_PROG_CC if you already called it elsewhere.]) - am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc - - if test "x$am_cv_prog_cc_stdc" != xyes ; then + if test "x$ac_cv_prog_cc_stdc" != xyes ; then AC_MSG_WARN([Failed to find Ansi flag!]) fi fi @@ -652,15 +644,8 @@ AC_SUBST([TCL_LIB_SPEC]) # ################################################################# - - # Checks for programs -AC_LIBTOOL_WIN32_DLL -AC_LIBTOOL_DLOPEN AM_PROG_CC_C_O -## AM_PROG_LIBTOOL -AC_PROG_LIBTOOL - # --with-windows : the user wants to use generate the MS WINDOWS GUI executable # old command version, deprecated, use --with-wingui @@ -759,7 +744,6 @@ AC_TYPE_SIZE_T # Checks for library functions. AC_FUNC_CLOSEDIR_VOID AC_FUNC_SELECT_ARGTYPES -AC_FUNC_SETVBUF_REVERSED AC_FUNC_VPRINTF # Check if the user wants to use the appropriate rpath commands to compile in @@ -906,7 +890,6 @@ AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stddef.h sys/file.h sys/param # Check time and resources headers and functions: -AC_HEADER_TIME AC_STRUCT_TM AC_STRUCT_TIMEZONE AC_CHECK_FUNCS([localtime]) From 5924ae2dfbace58fc7de8453100131cadb678bd5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 11 Feb 2023 13:57:44 +0100 Subject: [PATCH 08/91] bug report 619 by Hanspeter Niederstrasser remove double inclusion of stdlib.h Correction of commit 9e432838c ("Patch by Robert Turnbull: remove warning messages", 2023-02-05) --- src/xspice/icm/digital/d_osc/cfunc.mod | 1 - src/xspice/icm/digital/d_pwm/cfunc.mod | 1 - 2 files changed, 2 deletions(-) diff --git a/src/xspice/icm/digital/d_osc/cfunc.mod b/src/xspice/icm/digital/d_osc/cfunc.mod index 567b405cf..6f16a93e4 100644 --- a/src/xspice/icm/digital/d_osc/cfunc.mod +++ b/src/xspice/icm/digital/d_osc/cfunc.mod @@ -181,7 +181,6 @@ static void cm_d_osc_callback(ARGS, * * *************************************************************/ -#include void cm_d_osc(ARGS) { diff --git a/src/xspice/icm/digital/d_pwm/cfunc.mod b/src/xspice/icm/digital/d_pwm/cfunc.mod index 3d73e4ced..4aa5ec6be 100644 --- a/src/xspice/icm/digital/d_pwm/cfunc.mod +++ b/src/xspice/icm/digital/d_pwm/cfunc.mod @@ -184,7 +184,6 @@ static void cm_d_pwm_callback(ARGS, * * *************************************************************/ -#include void cm_d_pwm(ARGS) { From 9c6fe3f8e4177b38c68248cbf12f9e2a5c805602 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Feb 2023 18:54:54 +0100 Subject: [PATCH 09/91] Definitely exclude A devices from power probing (and others with less than 2 pins). --- src/frontend/inpc_probe.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 112b1208d..8a7a79f47 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -874,6 +874,12 @@ void inp_probe(struct card* deck) else numnodes = get_number_terminals(thisline); + if (numnodes < 2) { + fprintf(stderr, "Warning: Power mesasurement not available,\n .probe %s will be ignored\n", wltmp->wl_word); + tfree(instname); + continue; + } + int err = 0; /* call fcn with power requested */ err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE); @@ -1266,7 +1272,7 @@ void modprobenames(INPtables* tab) { If .probe p(Q1) is found, flag power is true, then do additional power calculations: Define a reference voltage of an n-terminal device as Vref = (V(1) + V(2) +...+ V(n)) / n with terminal (node) voltages V(n). Calculate power PQ1 = (v(1) - Vref) * i1 + (V(2) - Vref) * i2 + ... + (V(n) - Vref) * in) with terminal currents in. - See "Quantities of a Multiterminal Circuit Determined on the Basis of Kirchhoff’s Laws", M. Depenbrock, + See "Quantities of a Multiterminal Circuit Determined on the Basis of Kirchhoff�s Laws", M. Depenbrock, ETEP Vol. 8, No. 4, July/August 1998. probe_int_ is used to trigger supressing the vectors when saving the results. Internal vectors thus are not saved. */ From 7ca305804d70f66283c2d8bf0cfec87f5dca6f09 Mon Sep 17 00:00:00 2001 From: dwarning Date: Sun, 12 Feb 2023 08:35:29 +0100 Subject: [PATCH 10/91] ret variable only used for openMP enabled --- src/osdi/osdiload.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/osdi/osdiload.c b/src/osdi/osdiload.c index 6612323d4..43d20a05d 100644 --- a/src/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -174,13 +174,13 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { sim_info.flags |= CALC_NOISE | ANALYSIS_NOISE; } - int ret = OK; - OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); const OsdiDescriptor *descr = entry->descriptor; uint32_t eval_flags = 0; #ifdef USE_OMP + int ret = OK; + /* use openmp 3.0 tasks to parallelize linked list transveral */ #pragma omp parallel #pragma omp single From bccaee48218c850e6d305e619a2fd38052b79981 Mon Sep 17 00:00:00 2001 From: dwarning Date: Wed, 15 Feb 2023 15:24:55 +0100 Subject: [PATCH 11/91] correct fft dc scaling bug #620 --- src/frontend/com_fft.c | 6 ++++-- src/maths/cmaths/cmath4.c | 14 ++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/frontend/com_fft.c b/src/frontend/com_fft.c index 0dc42ddc6..2d592525b 100644 --- a/src/frontend/com_fft.c +++ b/src/frontend/com_fft.c @@ -179,7 +179,9 @@ com_fft(wordlist *wl) fftw_execute(plan_forward); scale = (double) fpts - 1.0; - for (j = 0; j < fpts; j++) { + fdvec[i][0].cx_real = out[0][0]/scale/2.0; + fdvec[i][0].cx_imag = 0.0; + for (j = 1; j < fpts; j++) { fdvec[i][j].cx_real = out[j][0]/scale; fdvec[i][j].cx_imag = out[j][1]/scale; } @@ -212,7 +214,7 @@ com_fft(wordlist *wl) scale = (double) fpts - 1.0; /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ - fdvec[i][0].cx_real = in[0]/scale; + fdvec[i][0].cx_real = in[0]/scale/2.0; fdvec[i][0].cx_imag = 0.0; for (j = 1; j < fpts-1; j++) { fdvec[i][j].cx_real = in[2*j]/scale; diff --git a/src/maths/cmaths/cmath4.c b/src/maths/cmaths/cmath4.c index b3dd42f9a..11d7bf8f7 100644 --- a/src/maths/cmaths/cmath4.c +++ b/src/maths/cmaths/cmath4.c @@ -713,7 +713,9 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp outdata = alloc_c(fpts); scale = (double) fpts; - for (i = 0; i < fpts; i++) { + outdata[0].cx_real = out[0][0]/scale/2.0; + outdata[0].cx_imag = out[0][1]/scale/2.0; + for (i = 1; i < fpts; i++) { outdata[i].cx_real = out[i][0]/scale; outdata[i].cx_imag = out[i][1]/scale; } @@ -744,7 +746,9 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp outdata = alloc_c(N); scale = (double) N; - for (i = 0; i < N; i++) { + outdata[0].cx_real = datax[0]/scale/2.0; + outdata[0].cx_imag = datax[1]/scale/2.0; + for (i = 1; i < N; i++) { outdata[i].cx_real = datax[2*i]/scale; outdata[i].cx_imag = datax[2*i+1]/scale; } @@ -773,7 +777,9 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp fftw_execute(plan_forward); scale = (double) fpts - 1.0; - for (i = 0; i < fpts; i++) { + outdata[0].cx_real = out[0][0]/scale/2.0; + outdata[0].cx_imag = 0.0; + for (i = 1; i < fpts; i++) { outdata[i].cx_real = out[i][0]/scale; outdata[i].cx_imag = out[i][1]/scale; } @@ -798,7 +804,7 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp scale = (double) fpts - 1.0; /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ - outdata[0].cx_real = datax[0]/scale; + outdata[0].cx_real = datax[0]/scale/2.0; outdata[0].cx_imag = 0.0; for (i = 1; i < fpts-1; i++) { outdata[i].cx_real = datax[2*i]/scale; From 45e6d319f30b7d72d109b54d5e65a8a8a3244c1d Mon Sep 17 00:00:00 2001 From: dwarning Date: Sat, 18 Feb 2023 17:14:13 +0100 Subject: [PATCH 12/91] partly revert last commit: only real input vector get special scaling for dc component --- src/maths/cmaths/cmath4.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/maths/cmaths/cmath4.c b/src/maths/cmaths/cmath4.c index 11d7bf8f7..fa2b7cb6f 100644 --- a/src/maths/cmaths/cmath4.c +++ b/src/maths/cmaths/cmath4.c @@ -713,9 +713,7 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp outdata = alloc_c(fpts); scale = (double) fpts; - outdata[0].cx_real = out[0][0]/scale/2.0; - outdata[0].cx_imag = out[0][1]/scale/2.0; - for (i = 1; i < fpts; i++) { + for (i = 0; i < fpts; i++) { outdata[i].cx_real = out[i][0]/scale; outdata[i].cx_imag = out[i][1]/scale; } @@ -746,9 +744,7 @@ cx_fft(void *data, short int type, int length, int *newlength, short int *newtyp outdata = alloc_c(N); scale = (double) N; - outdata[0].cx_real = datax[0]/scale/2.0; - outdata[0].cx_imag = datax[1]/scale/2.0; - for (i = 1; i < N; i++) { + for (i = 0; i < N; i++) { outdata[i].cx_real = datax[2*i]/scale; outdata[i].cx_imag = datax[2*i+1]/scale; } From 845dfbd830dfe8ed284b83561c4ff95d5c9ec86d Mon Sep 17 00:00:00 2001 From: dwarning Date: Sun, 19 Feb 2023 19:31:06 +0100 Subject: [PATCH 13/91] diode recombination current emission coefficient default to 2 --- src/spicelib/devices/dio/diosetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index ef0695669..2cae77ca0 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -180,7 +180,7 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) model->DIOte_max = 1e99; } if(!model->DIOrecEmissionCoeffGiven) { - model->DIOrecEmissionCoeff = 1; + model->DIOrecEmissionCoeff = 2; } if(!model->DIOrecSatCurGiven) { model->DIOrecSatCur = 1e-14; From 50173ac6171ea47f27b3133cce40faa4ea0f26e8 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 19 Feb 2023 23:03:30 +0100 Subject: [PATCH 14/91] Enable potential calls to tprint() for debugging --- src/frontend/inp.c | 1 + src/frontend/subckt.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 86652c08e..bf6d954d5 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -60,6 +60,7 @@ static char *upper(register char *string); static void rem_unused_mos_models(struct card* deck); extern void com_optran(wordlist * wl); +extern void tprint(struct card *deck); //void inp_source_recent(void); diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 3d5b7b337..9579784a7 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -77,6 +77,7 @@ Modified: 2000 AlansFixes extern void line_free_x(struct card *deck, bool recurse); extern int get_number_terminals(char* c); +extern void tprint(struct card* deck); #define line_free(line, flag) \ do { \ From 3365fd4309e965c794b00b4a8fdbd93500d23104 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sat, 4 Feb 2023 16:33:39 -0800 Subject: [PATCH 15/91] Remove dead code. --- src/frontend/logicexp.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index ec4d95d08..b92ea5b28 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -1248,30 +1248,8 @@ static BOOL gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols) } ds_cat_printf(&instance, "%s ", get_inst_name()); if (in_count == 1) { - /* If the input name is inv_out_ use the - and instantiate an inverter to avoid an extra buffer. - */ - char *tail = NULL; - SYM_TAB ent; - tail = get_inv_tail(ds_get_buf(&in_names)); - if (tail && strlen(tail) > 0) { - ds_clear(&gate_name); - ds_cat_str(&gate_name, lex_gate_name('~', TRUE)); - ds_cat_printf(&instance, "%s %s ", tail, - ds_get_buf(&out_name)); - ent = member_sym_tab(tail, parser_symbols); - if (!ent) { - goto gen_error; - } - if ((ent->attribute & SYM_INVERTER) == 0) { - goto gen_error; - } - ent->ref_count--; - } else { - ds_cat_printf(&instance, "%s %s ", ds_get_buf(&in_names), - ds_get_buf(&out_name)); - } - + ds_cat_printf(&instance, "%s %s ", ds_get_buf(&in_names), + ds_get_buf(&out_name)); } else { ds_cat_printf(&instance, "[%s ] %s ", ds_get_buf(&in_names), ds_get_buf(&out_name)); From 8dd16feee48f571d22641c9deec9c29d077030cb Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sat, 11 Feb 2023 10:13:03 -0800 Subject: [PATCH 16/91] Use dstrings where fixed size char buffers should not have been used. --- src/frontend/logicexp.c | 137 +++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index b92ea5b28..4893792b4 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -519,11 +519,10 @@ static TLINE gen_tab_add_line(char *line, BOOL ignore_blank) return t; } -static char *get_temp_from_line(char *line, BOOL begin) +static char *get_temp_from_line(char *line, BOOL begin, DSTRING *pds) { - /* First occurrence of "tmp" on the line */ - /* If begin is TRUE then "tmp" must be at the start of line */ - static char lbuf[64]; + /* First occurrence of "tmpx.." on the line, x is a digit */ + /* If begin is TRUE then "tmpx.." must be at the start of line */ char *p, *q; int j = 0; p = strstr(line, "tmp"); @@ -531,41 +530,47 @@ static char *get_temp_from_line(char *line, BOOL begin) return NULL; if (begin && p != line) return NULL; - for (q = p, j = 0; isalnum(q[j]) || q[j] == '_'; j++) { - if (j >= 63) - return NULL; - lbuf[j] = q[j]; + ds_clear(pds); + p += 3; + if (!isdigit(p[0])) + return NULL; + ds_cat_str(pds, "tmp"); + for (q = p, j = 0; isdigit(q[j]) || q[j] == '_'; j++) { + ds_cat_char(pds, q[j]); } - lbuf[j] = '\0'; - return lbuf; + ds_cat_char(pds, '\0'); + return ds_get_buf(pds); } -static char *find_temp_begin(char *line) +static char *find_temp_begin(char *line, DSTRING *pds) { - return get_temp_from_line(line, TRUE); + return get_temp_from_line(line, TRUE, pds); } -static char *find_temp_anywhere(char *line) +static char *find_temp_anywhere(char *line, DSTRING *pds) { - return get_temp_from_line(line, FALSE); + return get_temp_from_line(line, FALSE, pds); } static int get_temp_depth(char *line) { - char buf[64]; char *p, *endp; - int depth; - p = find_temp_anywhere(line); + int depth = -1; + DS_CREATE(dstr, 128); + p = find_temp_anywhere(line, &dstr); if (p) { + char *buf; + buf = TMALLOC(char, strlen(p) + 1); strcpy(buf, p); p = strstr(buf + strlen("tmp"), "__"); if (p) { p = p + 2; depth = (int) strtol(p, &endp, 10); - return depth; } + tfree(buf); } - return -1; + ds_free(&dstr); + return depth; } static TLINE tab_find(PTABLE pt, char *str, BOOL start_of_line) @@ -606,7 +611,6 @@ static void ptable_print(PTABLE pt) /* Start of logicexp parser */ static char *get_inst_name(void); -static char *get_inverter_output_name(char *input); static void aerror(char *s); static BOOL amatch(int t); static BOOL bexpr(void); @@ -637,34 +641,31 @@ static char *get_inst_name(void) return name; } -static char *get_inverter_output_name(char *input) +static char *get_inverter_output_name(char *input, DSTRING *pds) { - static char buf[LEX_BUF_SZ]; LEXER lx = parse_lexer; // FIX ME keep this name in the symbol table to ensure uniqueness - (void) sprintf(buf, "inv_out__%s", input); - if (member_sym_tab(buf, lx->lexer_sym_tab)) - fprintf(stderr, "ERROR %s is already in use\n", buf); - return buf; + ds_clear(pds); + ds_cat_printf(pds, "inv_out__%s", input); + if (member_sym_tab(ds_get_buf(pds), lx->lexer_sym_tab)) + fprintf(stderr, "ERROR %s is already in use\n", ds_get_buf(pds)); + return ds_get_buf(pds); } -static char *get_inv_tail(char *str) +static char *get_inv_tail(char *str, DSTRING *pds) { - static char lbuf[64]; char *p = NULL, *q = NULL; int j = 0; size_t slen = strlen("inv_out__"); - p = strstr(str, "inv_out__"); if (!p) return NULL; + ds_clear(pds); for (q = p + slen, j = 0; q[j] != '\0' && !isspace(q[j]); j++) { - if (j >= 63) - return NULL; - lbuf[j] = q[j]; + ds_cat_char(pds, q[j]); } - lbuf[j] = '\0'; - return lbuf; + ds_cat_char(pds, '\0'); + return ds_get_buf(pds); } static void gen_models(void) @@ -776,8 +777,11 @@ static BOOL bfactor(void) if (lookahead == LEX_ID) { entry = add_sym_tab_entry(lx->lexer_buf, SYM_ID, &lx->lexer_sym_tab); if (is_not) { + DS_CREATE(dstr, 128); + ds_clear(&dstr); ds_cat_printf(&d_curr_line, "%s ", - get_inverter_output_name(lx->lexer_buf)); + get_inverter_output_name(lx->lexer_buf, &dstr)); + ds_free(&dstr); entry->attribute |= SYM_INVERTER; entry->ref_count++; } else { @@ -953,12 +957,14 @@ static PTABLE optimize_gen_tab(PTABLE pt) DS_CREATE(alias, 64); DS_CREATE(non_tmp_name, 64); DS_CREATE(tmp_name, 64); + DS_CREATE(find_str, 128); if (!pt || !pt->first) { ds_free(&scratch); ds_free(&alias); ds_free(&non_tmp_name); ds_free(&tmp_name); + ds_free(&find_str); return NULL; } t = pt->first; @@ -977,7 +983,7 @@ static PTABLE optimize_gen_tab(PTABLE pt) ds_clear(&alias); entry = NULL; found_tilde = FALSE; - if (find_temp_begin(t->line)) + if (find_temp_begin(t->line, &find_str)) starts_with_temp = TRUE; else starts_with_temp = FALSE; @@ -1041,7 +1047,7 @@ static PTABLE optimize_gen_tab(PTABLE pt) val = lexer_scan(lxr); idnum = 0; entry = NULL; - if (find_temp_begin(t->line)) + if (find_temp_begin(t->line, &find_str)) starts_with_temp = TRUE; else starts_with_temp = FALSE; @@ -1066,12 +1072,12 @@ static PTABLE optimize_gen_tab(PTABLE pt) ds_cat_printf(&scratch, "%s ", lxr->lexer_buf); if (tok_count == 1) { ds_clear(&non_tmp_name); - if (!find_temp_begin(lxr->lexer_buf)) + if (!find_temp_begin(lxr->lexer_buf, &find_str)) ds_cat_str(&non_tmp_name, lxr->lexer_buf); } else if (tok_count == 3) { if (ds_get_length(&non_tmp_name) > 0) { char *str1 = NULL; - str1 = find_temp_begin(lxr->lexer_buf); + str1 = find_temp_begin(lxr->lexer_buf, &find_str); if (str1) { ds_clear(&tmp_name); ds_cat_str(&tmp_name, lxr->lexer_buf); @@ -1138,6 +1144,7 @@ quick_return: ds_free(&scratch); ds_free(&non_tmp_name); ds_free(&tmp_name); + ds_free(&find_str); delete_lexer(lxr); delete_sym_tab(alias_tab); @@ -1189,8 +1196,9 @@ static BOOL gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols) ds_cat_str(&out_name, lxr->lexer_buf); } else { // input name char *tail = NULL; + DS_CREATE(dstr, 64); in_count++; - tail = get_inv_tail(lxr->lexer_buf); + tail = get_inv_tail(lxr->lexer_buf, &dstr); if (tail && strlen(tail) > 0) { ds_cat_printf(&in_names, " ~%s", tail); if (prit) { @@ -1201,6 +1209,7 @@ static BOOL gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols) } else { ds_cat_printf(&in_names, " %s", lxr->lexer_buf); } + ds_free(&dstr); } } else if (val == '~') { found_tilde = TRUE; @@ -1306,10 +1315,13 @@ static void bevaluate(TLINE t, int deep) DS_CREATE(this, 64); DS_CREATE(other, 64); DS_CREATE(new_line, LEX_BUF_SZ); + DS_CREATE(find_str, 128); - s = find_temp_begin(t->line); - if (!s) + s = find_temp_begin(t->line, &find_str); + if (!s) { + ds_free(&find_str); return; + } ds_clear(&other); ds_clear(&new_line); ds_clear(&this); @@ -1325,19 +1337,19 @@ static void bevaluate(TLINE t, int deep) } t = t->next; while (t) { - s = find_temp_anywhere(t->line); + s = find_temp_anywhere(t->line, &find_str); if (s) { if (eq(ds_get_buf(&this), s)) { break; } else { if (down == 0) { - s = find_temp_begin(t->line); + s = find_temp_begin(t->line, &find_str); ds_clear(&other); ds_cat_str(&other, s); down = 1; ds_cat_printf(&new_line, " %s", ds_get_buf(&other)); } else if (down == 1) { - s = find_temp_anywhere(t->line); + s = find_temp_anywhere(t->line, &find_str); if (eq(ds_get_buf(&other), s)) { down = 0; ds_clear(&other); @@ -1345,7 +1357,7 @@ static void bevaluate(TLINE t, int deep) } } } else if (down == 0) { - s = find_temp_anywhere(t->line); + s = find_temp_anywhere(t->line, &find_str); if (!s) { ds_cat_printf(&new_line, " %s", t->line); } @@ -1356,6 +1368,7 @@ static void bevaluate(TLINE t, int deep) ds_free(&this); ds_free(&other); ds_free(&new_line); + ds_free(&find_str); return; } @@ -1850,16 +1863,16 @@ static void gen_pindly_buffers(void) ds_free(&dbuf); } -static char *get_typ_estimate(char *min, char *typ, char *max) +static char *get_typ_estimate(char *min, char *typ, char *max, DSTRING *pds) { char *tmpmax = NULL, *tmpmin = NULL; float valmin, valmax, average; char *units1, *units2; - static char tbuf[128]; + ds_clear(pds); if (typ && strlen(typ) > 0 && typ[0] != '-') { - strcpy(tbuf, typ); - return tbuf; + ds_cat_str(pds, typ); + return ds_get_buf(pds); } if (max && strlen(max) > 0 && max[0] != '-') { tmpmax = max; @@ -1872,25 +1885,25 @@ static char *get_typ_estimate(char *min, char *typ, char *max) valmin = strtof(tmpmin, &units1); valmax = strtof(tmpmax, &units2); average = (valmin + valmax) / (float)2.0; - sprintf(tbuf, "%.2f%s", average, units2); + ds_cat_printf(pds, "%.2f%s", average, units2); if (!eq(units1, units2)) { printf("WARNING units do not match\n"); } - return tbuf; + return ds_get_buf(pds); } } else if (tmpmax && strlen(tmpmax) > 0) { - strcpy(tbuf, tmpmax); - return tbuf; + ds_cat_str(pds, tmpmax); + return ds_get_buf(pds); } else if (tmpmin && strlen(tmpmin) > 0) { - strcpy(tbuf, tmpmin); - return tbuf; + ds_cat_str(pds, tmpmin); + return ds_get_buf(pds); } else { return NULL; } return NULL; } -static char *typical_estimate(char *delay_str) +static char *typical_estimate(char *delay_str, DSTRING *pds) { /* Input string (t1,t2,t2) */ int which = 0; @@ -1924,7 +1937,7 @@ static char *typical_estimate(char *delay_str) } } s = get_typ_estimate(ds_get_buf(&dmin), ds_get_buf(&dtyp), - ds_get_buf(&dmax)); + ds_get_buf(&dmax), pds); ds_free(&dmin); ds_free(&dtyp); ds_free(&dmax); @@ -1949,16 +1962,19 @@ static BOOL extract_delay( char *units; DS_CREATE(dly, 64); DS_CREATE(dtyp_max_str, 16); + DS_CREATE(tmp_ds, 128); if (val != '=') { ds_free(&dly); ds_free(&dtyp_max_str); + ds_free(&tmp_ds); return FALSE; } val = lexer_scan(lx); if (val != '{') { ds_free(&dly); ds_free(&dtyp_max_str); + ds_free(&tmp_ds); return FALSE; } val = lexer_scan(lx); @@ -1978,10 +1994,12 @@ static BOOL extract_delay( ds_cat_printf(&dly, "%c", val); if (val == ')') { char *tmps; + ds_clear(&tmp_ds); in_delay = FALSE; - tmps = typical_estimate(ds_get_buf(&dly)); + tmps = typical_estimate(ds_get_buf(&dly), &tmp_ds); if (!tmps) { ret_val = FALSE; + ds_clear(&tmp_ds); break; } if (prit) { @@ -2029,6 +2047,7 @@ static BOOL extract_delay( } // end while != '}' ds_free(&dly); ds_free(&dtyp_max_str); + ds_free(&tmp_ds); return ret_val; } From 91144582a01ea1462361e85aa43ebd1f985f1e76 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Feb 2023 09:44:52 +0100 Subject: [PATCH 17/91] Remove duplicated lines. Remove reference to deprecated ADMS, add OSDI instead --- INSTALL | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/INSTALL b/INSTALL index 67e9f7fe6..ea2bdb479 100644 --- a/INSTALL +++ b/INSTALL @@ -198,12 +198,11 @@ This file describes the procedures to install ngspice from sources. 1.5.1 Most useful options: - --enable-adms - ADMS is an experimental model compiler that translates - Verilog-A compact models into C code that can be compiled into - ngspice. This is (as of ngspice-27) still experimental, some - features (e.g. noise) are missing. If you want to use it, please - refer to the ADMS section on ngspice web site. + --enable-osdi + Add the OSDI interface to ngspice. This interface allow to dynamically + load compiled Veriloag-A compact models. Compiling is done with + OpenVAF. Thus for the first time ngspice has access to modern + device models like BSOMBULK or BSIM_CMG. --enable-cider Cider is a mixed-level simulator that couples Spice3 and DSIM @@ -246,9 +245,6 @@ This file describes the procedures to install ngspice from sources. Enables a 'make check' with strongly reduced runtime. Besides some regression tests only BSIM3 and BSM4 devices are checked. - --enable-shortcheck - Enables a 'make check' with strongly reduced runtime. Besides some - regression tests only BSIM3 and BSM4 devices are checked. 1.5.2 Options Specific to Enable Ngspice as a shared library From dbb5219dc76c75a2c51f4b2fdc5c85a6908b85cd Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Sat, 18 Feb 2023 15:36:01 +0000 Subject: [PATCH 18/91] Fix a crash reported by Thomas Hoffmann when using the "TARG AT=xxxx" variant of "measure", General Form 1. --- src/frontend/com_measure2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 91dbffa7b..9db0c14da 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -1699,7 +1699,10 @@ get_measure2( goto err_ret1; } // measure targ - com_measure_when(measTarg); + if (measTarg->m_at == 1e99) + com_measure_when(measTarg); + else + measTarg->m_measured = measTarg->m_at; if (isnan(measTarg->m_measured)) { sprintf(errbuf, "out of interval\n"); From 7457a2684bb52b19278e6ea7b102adee38e495eb Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 21 Feb 2023 15:35:35 +0000 Subject: [PATCH 19/91] Revert "Fixes bug #331" This reverts commit 6d9876229cf0e9e17a436f352345acb95ebff3ca, because it was found to break examples/xspice/various/xspice_c3.cir (see discussion in bug report for February 2023) and an alternative fix is available. --- src/xspice/evt/evtbackup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xspice/evt/evtbackup.c b/src/xspice/evt/evtbackup.c index 1055deced..dc4432a43 100644 --- a/src/xspice/evt/evtbackup.c +++ b/src/xspice/evt/evtbackup.c @@ -577,7 +577,7 @@ static void EVTbackup_output_queue( output = *output_ptr; while(output) { - if (output->posted_time < new_time) + if(output->event_time > new_time) break; output_ptr = &((*output_ptr)->next); output = *output_ptr; From 06aa693852db92e248a0d81184bdd16adf1798c8 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 21 Feb 2023 15:57:20 +0000 Subject: [PATCH 20/91] A new fix for Bug #331: "XSpice skips digital output point". The problem was caused by removing an output queue from the "modified" list when it had been modified by processing one of its events. --- src/xspice/evt/evtbackup.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/xspice/evt/evtbackup.c b/src/xspice/evt/evtbackup.c index dc4432a43..fe1e02784 100644 --- a/src/xspice/evt/evtbackup.c +++ b/src/xspice/evt/evtbackup.c @@ -618,17 +618,26 @@ static void EVTbackup_output_queue( } output_queue->next_time = next_time; - /* Update the modified list by looking for any queued events */ - /* with posted time > last_time */ + /* Update the modified list by looking for events that were processed + * or queued in the current timestep. + */ + for(i = 0, j = 0; i < num_modified; i++) { output_index = output_queue->modified_index[i]; output = *(output_queue->last_step[output_index]); - while(output) { - if(output->posted_time > output_queue->last_time) - break; - output = output->next; + if (output_queue->current[output_index] == + output_queue->last_step[output_index]) { + /* Nothing now removed from the queue, + * but it may have been modified by an addition. + */ + + while(output) { + if(output->posted_time > output_queue->last_time) + break; + output = output->next; + } } if(! output) { From d9b52eb3e121ee52a72fc27ff69f843954c4af85 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 21 Feb 2023 16:04:39 +0000 Subject: [PATCH 21/91] Fix a bug reported by Thomas Hoffmann in ngspice-users discussion, 2023-02-18. Incorrect tests were used to detect a crossing in the first two data samples. --- src/frontend/com_measure2.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 9db0c14da..5b947eacf 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -491,14 +491,13 @@ com_measure_when( crossCnt = 0; if (value < value2) { section = S_BELOW_VAL; - if ((prevValue <= value2) && (value >= value2)) { + if (prevValue >= prevValue2) { fallCnt = 1; crossCnt = 1; } - } else { section = S_ABOVE_VAL; - if ((prevValue <= value2) && (value >= value2)) { + if (prevValue < prevValue2) { riseCnt = 1; crossCnt = 1; } @@ -509,14 +508,13 @@ com_measure_when( crossCnt = 0; if (value < meas->m_val) { section = S_BELOW_VAL; - if ((prevValue <= meas->m_val) && (value >= meas->m_val)) { + if (prevValue >= meas->m_val) { fallCnt = 1; crossCnt = 1; } - } else { section = S_ABOVE_VAL; - if ((prevValue <= meas->m_val) && (value >= meas->m_val)) { + if (prevValue < meas->m_val) { riseCnt = 1; crossCnt = 1; } From da77fad749054f28b725d934fb79151063b2e0de Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 22 Feb 2023 15:31:47 +0100 Subject: [PATCH 22/91] In the very rare case of pPivot being NULL, prevent a crsh by reordering the matrix. --- src/maths/sparse/spfactor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/maths/sparse/spfactor.c b/src/maths/sparse/spfactor.c index 337ad2ace..de5de6177 100644 --- a/src/maths/sparse/spfactor.c +++ b/src/maths/sparse/spfactor.c @@ -228,6 +228,11 @@ spOrderAndFactor(MatrixPtr Matrix, RealNumber RHS[], RealNumber RelThreshold, INCRESP; #endif pPivot = Matrix->Diag[Step]; + if (!pPivot) { + fprintf(stderr, "Warning: spfactor.c, 230, Pivot for step = %d not found\n", Step); + ReorderingRequired = YES; + break; /* for loop */ + } LargestInCol = FindLargestInCol(pPivot->NextInCol); if ((LargestInCol * RelThreshold < ELEMENT_MAG(pPivot))) { if (Matrix->Complex) From d495333578e9cf00d88e05f64b08a281e2aac275 Mon Sep 17 00:00:00 2001 From: Markus Mueller Date: Wed, 22 Feb 2023 17:44:33 +0100 Subject: [PATCH 23/91] fix small memory leak in OSDI interface --- src/osdi/osdiregistry.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c index 66d14704b..7d925e581 100644 --- a/src/osdi/osdiregistry.c +++ b/src/osdi/osdiregistry.c @@ -316,6 +316,8 @@ extern OsdiObjectFile load_object_file(const char *input) { return INVALID_OBJECT; } + txfree(path); + GET_CONST(OSDI_NUM_DESCRIPTORS, uint32_t); GET_PTR(OSDI_DESCRIPTORS, OsdiDescriptor); From bd30bd4e85a8af6612861a52e3fc8f0a3b16dfad Mon Sep 17 00:00:00 2001 From: Markus Mueller Date: Wed, 22 Feb 2023 17:59:32 +0100 Subject: [PATCH 24/91] fix memory leak more rigorously --- src/osdi/osdiregistry.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c index 7d925e581..827bbe6a0 100644 --- a/src/osdi/osdiregistry.c +++ b/src/osdi/osdiregistry.c @@ -288,6 +288,7 @@ extern OsdiObjectFile load_object_file(const char *input) { if (!path) { fprintf(stderr, "Error opening osdi lib \"%s\": No such file or directory!\n", input); + txfree(path); return INVALID_OBJECT; } @@ -302,6 +303,7 @@ extern OsdiObjectFile load_object_file(const char *input) { * nghash_insert returns NULL if the key (handle) was not already in the table * and the data (DUMMYDATA) that was previously insered (!= NULL) otherwise*/ if (nghash_insert(known_object_files, handle, DUMMYDATA)) { + txfree(path); return EMPTY_OBJECT; } @@ -313,11 +315,10 @@ extern OsdiObjectFile load_object_file(const char *input) { printf("NGSPICE only supports OSDI v%d.%d but \"%s\" targets v%d.%d!", OSDI_VERSION_MAJOR_CURR, OSDI_VERSION_MINOR_CURR, path, OSDI_VERSION_MAJOR, OSDI_VERSION_MINOR); + txfree(path); return INVALID_OBJECT; } - txfree(path); - GET_CONST(OSDI_NUM_DESCRIPTORS, uint32_t); GET_PTR(OSDI_DESCRIPTORS, OsdiDescriptor); @@ -386,6 +387,7 @@ extern OsdiObjectFile load_object_file(const char *input) { }; } + txfree(path); return (OsdiObjectFile){ .entrys = dst, .num_entries = (int)OSDI_NUM_DESCRIPTORS, From 75f94517029dfba50dda7770505fec79cc4b9dab Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Feb 2023 15:40:21 +0100 Subject: [PATCH 25/91] Fix bug 624 also for MS Windows by moving DestroyGraph() from WM_CLOSE to RemoveWindow() --- src/frontend/wdisp/windisp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/frontend/wdisp/windisp.c b/src/frontend/wdisp/windisp.c index 93716f3e9..33a238fcd 100644 --- a/src/frontend/wdisp/windisp.c +++ b/src/frontend/wdisp/windisp.c @@ -645,14 +645,7 @@ LRESULT CALLBACK PlotWindowProc(HWND hwnd, UINT uMsg, case WM_CLOSE: /* close window */ { - GRAPH *g = pGraph(hwnd); - if (g) { - /* if g equals currentgraph, reset currentgraph. */ - if (g == currentgraph) - currentgraph = NULL; - DestroyGraph(g->graphid); - } } goto WIN_DEFAULT; @@ -1233,6 +1226,13 @@ void RemoveWindow(GRAPH *dgraph) wd = pWindowData(dgraph); if (wd) SendMessage(wd->wnd, WM_CLOSE, (WPARAM) wd->hDC, 0); + + if (dgraph) { + /* if g equals currentgraph, reset currentgraph. */ + if (dgraph == currentgraph) + currentgraph = NULL; + DestroyGraph(dgraph->graphid); + } } From f83c89cce7fe529bcf9ad19e8fe1287c1a01ab8b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Feb 2023 15:40:52 +0100 Subject: [PATCH 26/91] When path is NULL, we don't need to free it. --- src/osdi/osdiregistry.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c index 827bbe6a0..dc5c47756 100644 --- a/src/osdi/osdiregistry.c +++ b/src/osdi/osdiregistry.c @@ -288,7 +288,6 @@ extern OsdiObjectFile load_object_file(const char *input) { if (!path) { fprintf(stderr, "Error opening osdi lib \"%s\": No such file or directory!\n", input); - txfree(path); return INVALID_OBJECT; } From 2233e2f82501da086f1a0da39e0da4c985d570a1 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Sat, 25 Feb 2023 09:54:04 +0000 Subject: [PATCH 27/91] Fix Bug #624 - "Destroy All Fails with an Open Plot Window" for X11. Move XftDrawDestroy() call to a point where the window still exists. --- src/frontend/plotting/x11.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/frontend/plotting/x11.c b/src/frontend/plotting/x11.c index 0b5d5f5eb..8879328ac 100644 --- a/src/frontend/plotting/x11.c +++ b/src/frontend/plotting/x11.c @@ -1189,6 +1189,9 @@ void RemoveWindow(GRAPH *graph) DEVDEP(graph).isopen = 0; /* MW. Not sure but DestroyGraph might free() too much - try Xt...() first */ XtUnmapWidget(DEVDEP(graph).shell); +#ifdef HAVE_LIBXFT + XftDrawDestroy(DEVDEP(graph).draw); +#endif XtDestroyWidget(DEVDEP(graph).shell); #ifndef HAVE_LIBXFT XFreeFont(display, DEVDEP(graph).font); @@ -1198,7 +1201,6 @@ void RemoveWindow(GRAPH *graph) #ifdef HAVE_LIBXFT XftFontClose( display, DEVDEP(graph).font0); XftFontClose( display, DEVDEP(graph).font90); - XftDrawDestroy(DEVDEP(graph).draw); XftColorFree(display, DefaultVisual(display, 0), DEVDEP(graph).cmap, &DEVDEP(graph).color); #endif } From d4ee9af2e670797b88b0ecf435358139ed05b300 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 27 Feb 2023 13:29:25 +0100 Subject: [PATCH 28/91] We are developing towards ngspice-40 --- configure.ac | 2 +- src/include/ngspice/sharedspice.h | 2 +- visualc/src/include/ngspice/config.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 9cf63f46e..55da0c74c 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], [39+]) m4_define([ngspice_minor_version], [0]) m4_define([ngspice_version], [ngspice_major_version]) diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index 8c3b3084f..a3b4ffed9 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 "39+" #endif /* we have NG_BOOL instead of BOOL */ #ifndef HAS_NG_BOOL diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 0381179f1..91125700e 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 "39+" /* Define the directory for executables */ #define NGSPICEBINDIR "../bin" From 0caf1aa815c7f931a75eabb11bc5ab3effb75011 Mon Sep 17 00:00:00 2001 From: Markus Mueller Date: Wed, 1 Mar 2023 13:50:35 +0100 Subject: [PATCH 29/91] (fix) CALC_OP during transient analysis in OSDI interface --- src/osdi/osdiload.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/osdi/osdiload.c b/src/osdi/osdiload.c index 43d20a05d..6fe4b4f40 100644 --- a/src/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -137,9 +137,7 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { .flags = CALC_RESIST_JACOBIAN, }; - if (is_init_smsig || is_sweep) { - sim_info.flags |= CALC_OP; - } + sim_info.flags |= CALC_OP; if (is_dc) { sim_info.flags |= ANALYSIS_DC | ANALYSIS_STATIC; From 79fcb5d4bd6363d5519283f837d0879d7dd4e00e Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 28 Feb 2023 17:31:35 +0000 Subject: [PATCH 30/91] Fix plotting bug reported by Robert Turnbull: ngspice-devel 2023-02-10. --- src/frontend/plotting/graf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/plotting/graf.c b/src/frontend/plotting/graf.c index 2e9a70797..929a6e5fb 100644 --- a/src/frontend/plotting/graf.c +++ b/src/frontend/plotting/graf.c @@ -485,12 +485,15 @@ void gr_point(struct dvec *dv, case PLOT_RETLIN: /* If it's a linear plot, ignore first point since we don't want to connect with oldx and oldy. */ - if (np) + if (np) { #ifdef LINE_COMPRESSION_CHECKS drawLine(fromx, fromy, tox, toy, dv); #else drawLine(fromx, fromy, tox, toy); #endif + } else { + LC_flush(); // May be retrace with non-monotonic x-axis + } if ((tics = currentgraph->ticdata) != NULL) { for (; *tics < HUGE; tics++) From d2fb3fb16b8c8254cb50031512cdb2c117fdb665 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 3 Mar 2023 14:53:32 +0100 Subject: [PATCH 31/91] Prevent memory leak. Remove use controls. Safeguard against NULL. --- src/frontend/inp.c | 3 ++- src/sharedspice.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/inp.c b/src/frontend/inp.c index bf6d954d5..38118347a 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -1122,7 +1122,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) inputdir = dir_name; #endif if (cp_getvar("controlswait", CP_BOOL, NULL, 0)) { - exec_controls(wl_copy(wl)); + if (wl) + exec_controls(wl_copy(wl)); break; } else diff --git a/src/sharedspice.c b/src/sharedspice.c index 4d7e52514..af9dccd02 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -485,6 +485,7 @@ _cthread_run(void *controls) #ifdef HAVE_LIBPTHREAD cont_condition = FALSE; #endif + wl_free(controls); return NULL; } @@ -608,6 +609,7 @@ exec_controls(wordlist *newcontrols) wordlist *wl; for (wl = shcontrols; wl; wl = wl->wl_next) cp_evloop(wl->wl_word); + wl_free(shcontrols); #endif } From 5ee7a0ad2dd7614be2badf5fc0c5b148d27eff5f Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 5 Mar 2023 11:20:02 +0100 Subject: [PATCH 32/91] prevent crash when defect .model line is given (no model name or no model type) --- src/frontend/inpcom.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 16fea8644..b4a13bc5a 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -8651,7 +8651,15 @@ static struct card *pspice_compat(struct card *oldcard) char *cut_del = curr_line = cut_line = inp_remove_ws(copy(cut_line)); cut_line = nexttok(cut_line); /* skip .model */ modname = gettok(&cut_line); /* save model name */ + if (!modname) { + fprintf(stderr, "Warning: No model name given for %s\n", curr_line); + controlled_exit(EXIT_BAD); + } modtype = gettok_noparens(&cut_line); /* save model type */ + if (!modtype) { + fprintf(stderr, "Warning: No model type given for %s\n", curr_line); + controlled_exit(EXIT_BAD); + } if (cieq(modtype, "NMOS") || cieq(modtype, "PMOS")) { char* lv = strstr(cut_line, "level="); if (lv) { From 8915d42241d3954700bd1784fa12df4cf970e6b6 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 5 Mar 2023 11:26:00 +0100 Subject: [PATCH 33/91] Prevent crash during .probe p(...) when no subcircuits are given. --- src/frontend/inpc_probe.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 8a7a79f47..4c547446b 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -313,6 +313,12 @@ void inp_probe(struct card* deck) /* to make the nodes unique */ snprintf(nodebuf, 12, "%d", i); nodename = get_terminal_name(instname, nodebuf, instances); + if (!nodename || *nodename == '\0') { + fprintf(stderr, "Warning: Cannot find node name %d in line %s\n", i, curr_line); + fprintf(stderr, " Instance not ready for .probe command\n"); + tfree(thisnode); + continue; + } char* vline = tprintf("vcurr_%s:%s:%s_%s %s %s 0", instname, nodename, thisnode, nodebuf, thisnode, newnode); card = insert_new_line(card, vline, 0, 0); /* special for KiCad: add shunt resistor if thisnode contains 'unconnected' */ @@ -1040,6 +1046,16 @@ static char *get_terminal_name(char* element, char *numberstr, NGHASHPTR instanc /*Search for the corresponding .subckt line*/ struct card_assoc* allsubs = xcard->level->subckts; + if (!allsubs) { + char* instline = xcard->line; + char* inst = gettok(&instline); + fprintf(stderr, "Warning: No .subckt line found during evaluating command .probe (...)!\n"); + fprintf(stderr, " failing instance: %s\n", inst); + tfree(subcktname); + tfree(inst); + return tprintf("n%s", numberstr); + } + while (allsubs) { xcardsubsline = allsubs->line->line; /* safeguard against NULL pointers) */ From ae6375c5194cedcfb8bcfba05664aeaedf207670 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Mon, 6 Mar 2023 11:53:36 +0000 Subject: [PATCH 34/91] Prevent a crash when "portnum" is used in a voltage source without "z0". --- src/spicelib/devices/vsrc/vsrcpar.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index bbe812143..19686293f 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -298,14 +298,19 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) { here->VSRCportNum = value->iValue; here->VSRCportNumGiven = TRUE; - here->VSRCisPort = ((here->VSRCportNumGiven) && (here->VSRCportNum > 0) && (here->VSRCportZ0 > 0.0)); + here->VSRCisPort = (here->VSRCportNum > 0); + if (here->VSRCportZ0 <= 0.0) { + here->VSRCportZ0 = 50; + here->VSRCVAmplitude = + sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0); + } break; } case VSRC_PORTZ0: { here->VSRCportZ0 = value->rValue; - here->VSRCVAmplitude = sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0); - here->VSRCisPort = ((here->VSRCportNumGiven) && (here->VSRCportNum > 0) && (here->VSRCportZ0 > 0.0)); + here->VSRCVAmplitude = + sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0); here->VSRCportZ0Given = TRUE; break; } From 4b30113f6017726c6ccb8f6fef2dbe99ac00eaa0 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Thu, 2 Mar 2023 12:19:53 -0800 Subject: [PATCH 35/91] Check current_subckt is set when printing TRANS_OUT. --- src/frontend/udevices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 6ef3b11b5..7bd0b50d2 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -776,7 +776,7 @@ struct card *replacement_udevice_cards(void) translated_p = add_xlator(translated_p, x); } - if (ps_port_directions & 2) { + if (current_subckt && (ps_port_directions & 2)) { char *tmp = NULL, *pos = NULL, *posp = NULL; tmp = TMALLOC(char, strlen(current_subckt) + 1); (void) memcpy(tmp, current_subckt, strlen(current_subckt) + 1); @@ -809,7 +809,7 @@ struct card *replacement_udevice_cards(void) nextcard = insert_new_line(nextcard, new_str, 0, 0); } } - if (ps_port_directions & 2) { + if (current_subckt && (ps_port_directions & 2)) { char *p1 = NULL, *p2 = NULL; DS_CREATE(tmpds, 64); p1 = strstr(current_subckt, ".subckt"); From 3a76a1ef52a114c4f9b8185f09e83ceba879b271 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Thu, 2 Mar 2023 17:40:15 -0800 Subject: [PATCH 36/91] Prepare for inertial_delay model parameter. --- src/frontend/logicexp.c | 26 +++++++++++++------------- src/frontend/udevices.c | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 4893792b4..77ae2d7be 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -674,47 +674,47 @@ static void gen_models(void) ds_clear(&model); ds_cat_printf(&model, - ".model d_inv_zero_delay d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_inv_zero_delay d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__inverter__1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__inverter__1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__buffer__1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__buffer__1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nand__1 d_nand(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nand__1 d_nand(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__and__1 d_and(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__and__1 d_and(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xnor__1 d_xnor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xnor__1 d_xnor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xor__1 d_xor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xor__1 d_xor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nor__1 d_nor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nor__1 d_nor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__or__1 d_or(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__or__1 d_or(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_free(&model); @@ -2015,11 +2015,11 @@ static BOOL extract_delay( if (ds_get_length(&dtyp_max_str) > 0) { if (tri) { ds_cat_printf(&delay_string, - "(delay=%s)", + "(inertial_delay=true delay=%s)", ds_get_buf(&dtyp_max_str)); } else { ds_cat_printf(&delay_string, - "(rise_delay=%s fall_delay=%s)", + "(inertial_delay=true rise_delay=%s fall_delay=%s)", ds_get_buf(&dtyp_max_str), ds_get_buf(&dtyp_max_str)); } @@ -2027,10 +2027,10 @@ static BOOL extract_delay( printf("WARNING pindly DELAY not found\n"); if (tri) { ds_cat_printf(&delay_string, - "(delay=10ns)"); + "(inertial_delay=true delay=10ns)"); } else { ds_cat_printf(&delay_string, - "(rise_delay=10ns fall_delay=10ns)"); + "(inertial_delay=true rise_delay=10ns fall_delay=10ns)"); } } for (i = 0; i < idx; i++) { diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 7bd0b50d2..fd5fb3335 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -748,7 +748,7 @@ struct card *replacement_udevice_cards(void) } if (add_zero_delay_inverter_model) { x = create_xlate_translated( - ".model d_zero_inv99 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_zero_inv99 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); } if (add_drive_hilo) { @@ -757,7 +757,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a1 0 drive___0 dbuf1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dbuf1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dbuf1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___lo"); translated_p = add_xlator(translated_p, x); @@ -766,7 +766,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a2 0 drive___1 dinv1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dinv1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dinv1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___hi"); translated_p = add_xlator(translated_p, x); @@ -891,7 +891,7 @@ void initialize_udevice(char *subckt_line) model_xlatorp = create_xlator(); default_models = create_xlator(); /* .model d0_gate ugate () */ - xdata = create_xlate("", "(rise_delay=1.0e-12 fall_delay=1.0e-12)", + xdata = create_xlate("", "(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)", "ugate", "", "d0_gate", ""); (void) add_xlator(default_models, xdata); /* .model d0_gff ugff () */ @@ -903,7 +903,7 @@ void initialize_udevice(char *subckt_line) xdata = create_xlate("", "", "ueff", "", "d0_eff", ""); (void) add_xlator(default_models, xdata); /* .model d0_tgate utgate () */ - xdata = create_xlate("", "(delay=1.0e-12)", + xdata = create_xlate("", "(inertial_delay=true delay=1.0e-12)", "utgate", "", "d0_tgate", ""); (void) add_xlator(default_models, xdata); /* reset for the new subckt */ @@ -2618,7 +2618,7 @@ static char *larger_delay(char *delay1, char *delay2) static char *get_zero_rise_fall(void) { /* The caller needs to tfree the returned string after use */ - return tprintf("(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + return tprintf("(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); } static char *get_delays_ugate(char *rem) @@ -2634,7 +2634,7 @@ static char *get_delays_ugate(char *rem) falling = get_estimate(tdp2); if (rising && falling) { if (strlen(rising) > 0 && strlen(falling) > 0) { - delays = tprintf("(rise_delay = %s fall_delay = %s)", + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", rising, falling); } else { delays = get_zero_rise_fall(); @@ -2665,12 +2665,12 @@ static char *get_delays_utgate(char *rem) if (rising && strlen(rising) > 0) { if (falling && strlen(falling) > 0) { larger = larger_delay(rising, falling); - delays = tprintf("(delay = %s)", larger); + delays = tprintf("(inertial_delay=true delay = %s)", larger); } else { - delays = tprintf("(delay = %s)", rising); + delays = tprintf("(inertial_delay=true delay = %s)", rising); } } else if (falling && strlen(falling) > 0) { - delays = tprintf("(delay = %s)", falling); + delays = tprintf("(inertial_delay=true delay = %s)", falling); } else if (use_zdelays) { /* No lh/hl delays, so try the largest lz/hz/zl/zh delay */ tdp3 = create_min_typ_max("tplz", rem); @@ -2716,16 +2716,16 @@ static char *get_delays_utgate(char *rem) larger3 = larger2; } if (larger3) { - delays = tprintf("(delay = %s)", larger3); + delays = tprintf("(inertial_delay=true delay = %s)", larger3); } else { - delays = tprintf("(delay=1.0e-12)"); + delays = tprintf("(inertial_delay=true delay=1.0e-12)"); } delete_timing_data(tdp3); delete_timing_data(tdp4); delete_timing_data(tdp5); delete_timing_data(tdp6); } else { // Not use_zdelays - delays = tprintf("(delay=1.0e-12)"); + delays = tprintf("(inertial_delay=true delay=1.0e-12)"); } delete_timing_data(tdp1); delete_timing_data(tdp2); From 0e5a5a62ac9338c092e016e221d46c40819c5286 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 3 Mar 2023 12:48:02 -0800 Subject: [PATCH 37/91] 74F550 and 74F551 have only fall delays on the inverters. Use the fall delay for both rise and fall. --- src/frontend/udevices.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index fd5fb3335..f3f617b2f 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -2625,6 +2625,7 @@ static char *get_delays_ugate(char *rem) { char *rising, *falling, *delays = NULL; struct timing_data *tdp1, *tdp2; + BOOL has_rising = FALSE, has_falling = FALSE; tdp1 = create_min_typ_max("tplh", rem); estimate_typ(tdp1); @@ -2632,13 +2633,19 @@ static char *get_delays_ugate(char *rem) tdp2 = create_min_typ_max("tphl", rem); estimate_typ(tdp2); falling = get_estimate(tdp2); - if (rising && falling) { - if (strlen(rising) > 0 && strlen(falling) > 0) { + has_rising = (rising && strlen(rising) > 0); + has_falling = (falling && strlen(falling) > 0); + if (has_rising) { + if (has_falling) { delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", rising, falling); - } else { - delays = get_zero_rise_fall(); + } else { /* use rising for both rise/fall */ + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", + rising, rising); } + } else if (has_falling) { /* use falling for both rise/fall */ + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", + falling, falling); } else { delays = get_zero_rise_fall(); } @@ -2655,6 +2662,7 @@ static char *get_delays_utgate(char *rem) struct timing_data *tdp3, *tdp4, *tdp5, *tdp6; char *tplz, *tphz, *tpzl, *tpzh, *larger, *larger1, *larger2, *larger3; BOOL use_zdelays = FALSE; + BOOL has_rising = FALSE, has_falling = FALSE; tdp1 = create_min_typ_max("tplh", rem); estimate_typ(tdp1); @@ -2662,14 +2670,16 @@ static char *get_delays_utgate(char *rem) tdp2 = create_min_typ_max("tphl", rem); estimate_typ(tdp2); falling = get_estimate(tdp2); - if (rising && strlen(rising) > 0) { - if (falling && strlen(falling) > 0) { + has_rising = (rising && strlen(rising) > 0); + has_falling = (falling && strlen(falling) > 0); + if (has_rising) { + if (has_falling) { larger = larger_delay(rising, falling); delays = tprintf("(inertial_delay=true delay = %s)", larger); } else { delays = tprintf("(inertial_delay=true delay = %s)", rising); } - } else if (falling && strlen(falling) > 0) { + } else if (has_falling) { delays = tprintf("(inertial_delay=true delay = %s)", falling); } else if (use_zdelays) { /* No lh/hl delays, so try the largest lz/hz/zl/zh delay */ From a6b2773c90cb41d8dd0e4bab0c011820dc244c11 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sat, 4 Mar 2023 11:08:09 -0800 Subject: [PATCH 38/91] For a ugate timing model, when tphlXX/tplhXX is not found, set the fall/rise delay to zero (1.0e-12). --- src/frontend/udevices.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index f3f617b2f..09a3ddf3e 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -2639,13 +2639,13 @@ static char *get_delays_ugate(char *rem) if (has_falling) { delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", rising, falling); - } else { /* use rising for both rise/fall */ - delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", - rising, rising); + } else { + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = 1.0e-12)", + rising); } - } else if (has_falling) { /* use falling for both rise/fall */ - delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", - falling, falling); + } else if (has_falling) { + delays = tprintf("(inertial_delay=true rise_delay = 1.0e-12 fall_delay = %s)", + falling); } else { delays = get_zero_rise_fall(); } From 4111aaf1100c567fe16658fc42488b023b6dcb78 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sun, 5 Mar 2023 20:54:19 -0800 Subject: [PATCH 39/91] When logicexp has a ugate timing model other than d0_gate, use its delays for an inverter or buffer. --- src/frontend/logicexp.c | 54 +++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 77ae2d7be..6dc47c680 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -319,6 +319,12 @@ static char *tmodel_gate_name(int c, BOOL not) else sprintf(buf, "dxspice_dly_xor"); break; + case '~': + if (not) + sprintf(buf, "dxspice_dly_inverter"); + else + sprintf(buf, "dxspice_dly_buffer"); + break; default: return NULL; } @@ -1229,32 +1235,34 @@ static BOOL gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols) if (in_count == 1) { // buffer or inverter if (gate_op != 0) goto gen_error; - ds_cat_str(&gate_name, lex_gate_name('~', found_tilde)); + gate_op = '~'; // found_tilde specifies inverter or buffer } else if (in_count >= 2) { // AND, OR. XOR and inverses if (gate_op == 0) goto gen_error; - if (use_tmodel_delays) { - /* This is the case when logicexp has a UGATE - timing model (not d0_gate) and no pindly. - */ - SYM_TAB entry = NULL; - char *nm1 = 0; - entry = member_sym_tab(ds_get_buf(&out_name), parser_symbols); - if (entry && (entry->attribute & SYM_OUTPUT)) { - nm1 = tmodel_gate_name(gate_op, found_tilde); - if (nm1) { - ds_cat_str(&gate_name, nm1); - } - } - if (!nm1) { - nm1 = lex_gate_name(gate_op, found_tilde); - ds_cat_str(&gate_name, nm1); - } - } else { - ds_cat_str(&gate_name, lex_gate_name(gate_op, found_tilde)); - } } else { goto gen_error; } + + if (use_tmodel_delays) { + /* This is the case when logicexp has a UGATE + timing model (not d0_gate) and no pindly. + */ + SYM_TAB entry = NULL; + char *nm1 = 0; + entry = member_sym_tab(ds_get_buf(&out_name), parser_symbols); + if (entry && (entry->attribute & SYM_OUTPUT)) { + nm1 = tmodel_gate_name(gate_op, found_tilde); + if (nm1) { + ds_cat_str(&gate_name, nm1); + } + } + if (!nm1) { + nm1 = lex_gate_name(gate_op, found_tilde); + ds_cat_str(&gate_name, nm1); + } + } else { + ds_cat_str(&gate_name, lex_gate_name(gate_op, found_tilde)); + } + ds_cat_printf(&instance, "%s ", get_inst_name()); if (in_count == 1) { ds_cat_printf(&instance, "%s %s ", ds_get_buf(&in_names), @@ -1632,6 +1640,10 @@ BOOL f_logicexp(char *line) "d_xor", "dxspice_dly_xor"); u_add_logicexp_model(parse_lexer->lexer_buf, "d_xnor", "dxspice_dly_xnor"); + u_add_logicexp_model(parse_lexer->lexer_buf, + "d_buffer", "dxspice_dly_buffer"); + u_add_logicexp_model(parse_lexer->lexer_buf, + "d_inverter", "dxspice_dly_inverter"); use_tmodel_delays = TRUE; } else { use_tmodel_delays = FALSE; From 4cc63494db44175f5adff5e3894c009cdd3da24c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 6 Mar 2023 23:14:56 +0100 Subject: [PATCH 40/91] Improve error message Typo --- src/spicelib/devices/ind/mutsetup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/spicelib/devices/ind/mutsetup.c b/src/spicelib/devices/ind/mutsetup.c index 16bce77c7..b623be039 100644 --- a/src/spicelib/devices/ind/mutsetup.c +++ b/src/spicelib/devices/ind/mutsetup.c @@ -47,17 +47,17 @@ MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) here->MUTind1 = (INDinstance *) CKTfndDev(ckt, here->MUTindName1); if (!here->MUTind1) { SPfrontEnd->IFerrorf (ERR_FATAL, - "%s: coupling to non-existant inductor %s.", + "%s: coupling to non-existent inductor %s.", here->MUTname, here->MUTindName1); - return(E_INTERN); /* We have to leave, or TSTALLOC will segfault */ + return(E_NOTFOUND); /* We have to leave, or TSTALLOC will segfault */ } if (!here->MUTind2) here->MUTind2 = (INDinstance *) CKTfndDev(ckt, here->MUTindName2); if (!here->MUTind2) { SPfrontEnd->IFerrorf (ERR_FATAL, - "%s: coupling to non-existant inductor %s.", + "%s: coupling to non-existent inductor %s.", here->MUTname, here->MUTindName2); - return(E_INTERN); + return(E_NOTFOUND); } TSTALLOC(MUTbr1br2Ptr, MUTind1->INDbrEq, MUTind2->INDbrEq); From bcec3cb5e305a8e2ad20ad135067420e3e84356a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Mar 2023 23:18:25 +0100 Subject: [PATCH 41/91] Updating links to ngspice web pages --- src/conf.c | 4 ++-- src/frontend/com_ghelp.c | 2 +- src/frontend/misccoms.c | 2 +- src/spicelib/devices/jfet2/jfet2temp.c | 2 +- visualc/src/include/ngspice/config.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/conf.c b/src/conf.c index aad7dc6c6..eece44db0 100644 --- a/src/conf.c +++ b/src/conf.c @@ -8,7 +8,7 @@ #ifdef PACKAGE_BUGREPORT #define BUG_ADDRESS PACKAGE_BUGREPORT #else -#define BUG_ADDRESS "http://ngspice.sourceforge.net/bugrep.html" +#define BUG_ADDRESS "https://ngspice.sourceforge.io/bugrep.html" #endif char Spice_Version[] = PACKAGE_VERSION; @@ -19,7 +19,7 @@ char Spice_Build_Date[] = NGSPICEBUILDDATE; char Spice_Build_Date[] = __DATE__" "__TIME__; #endif -char Spice_Manual[] = "Please get your ngspice manual from http://ngspice.sourceforge.net/docs.html"; +char Spice_Manual[] = "Please get your ngspice manual from https://ngspice.sourceforge.io/docs.html"; char *Spice_Exec_Dir = NGSPICEBINDIR; char *Spice_Lib_Dir = NGSPICEDATADIR; diff --git a/src/frontend/com_ghelp.c b/src/frontend/com_ghelp.c index ab0241694..dfcddfde2 100644 --- a/src/frontend/com_ghelp.c +++ b/src/frontend/com_ghelp.c @@ -17,7 +17,7 @@ * Internet Archive using the link below. * https://web.archive.org/web/20180221111839/http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/ */ -#define BASE_HELP_URL "http://ngspice.sourceforge.net/docs" +#define BASE_HELP_URL "https://ngspice.sourceforge.io/docs" void com_ghelp(wordlist *wl) { #if defined(HAS_WINGUI) || defined(_MSC_VER) || defined(__MINGW32__) ||\ diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index a74d5b870..05d4838b9 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -162,7 +162,7 @@ com_bug(wordlist *wl) fprintf(cp_out, "Please use the ngspice bug tracker at:\n" - "http://sourceforge.net/p/ngspice/bugs/\n"); + "https://sourceforge.net/p/ngspice/bugs/\n"); } #endif diff --git a/src/spicelib/devices/jfet2/jfet2temp.c b/src/spicelib/devices/jfet2/jfet2temp.c index eee92cabd..174767f10 100644 --- a/src/spicelib/devices/jfet2/jfet2temp.c +++ b/src/spicelib/devices/jfet2/jfet2temp.c @@ -4,7 +4,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified to add PS model and new parameter definitions ( Anthony E. Parker ). -See http://ngspice.sourceforge.net/external-documents/models/psfet.pdf +See https://ngspice.sourceforge.io/external-documents/models/psfet.pdf Copyright 1994 Macquarie University, Sydney Australia. 10 Feb 1994: Call to PSinstanceinit() added Change gatePotential to phi and used rs and rd for diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 91125700e..159ebc085 100644 --- a/visualc/src/include/ngspice/config.h +++ b/visualc/src/include/ngspice/config.h @@ -476,7 +476,7 @@ /* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "http://ngspice.sourceforge.net/bugrep.html" +#define PACKAGE_BUGREPORT "https://ngspice.sourceforge.io/bugrep.html" /* Define to the full name of this package. */ #define PACKAGE_NAME PACKAGE From 247562c09673b4cafe81cfb342379ab65baca9e0 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Mar 2023 23:26:55 +0100 Subject: [PATCH 42/91] Update copyright notice --- src/frontend/misccoms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index 05d4838b9..f69912019 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -185,7 +185,7 @@ com_version(wordlist *wl) "** %s-%s : %s\n" "** The U. C. Berkeley CAD Group\n" "** Copyright 1985-1994, Regents of the University of California.\n" - "** Copyright 2001-2022, The ngspice team.\n" + "** Copyright 2001-2023, The ngspice team.\n" "** %s\n", ft_sim->simulator, ft_sim->version, ft_sim->description, Spice_Manual); if (*Spice_Notice != '\0') @@ -222,7 +222,7 @@ com_version(wordlist *wl) "** %s-%s : %s\n" "** The U. C. Berkeley CAD Group\n" "** Copyright 1985-1994, Regents of the University of California.\n" - "** Copyright 2001-2022, The ngspice team.\n" + "** Copyright 2001-2023, The ngspice team.\n" "** %s\n", ft_sim->simulator, ft_sim->version, ft_sim->description, Spice_Manual); if (*Spice_Notice != '\0') From c61acefef7980e0476f93dcb6e5388d9802b8df9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 13 Mar 2023 09:24:43 +0100 Subject: [PATCH 43/91] Prevent crash when a bad .model line is given, like .model .model xxx --- src/frontend/inpcom.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index b4a13bc5a..b98ea8163 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -10276,6 +10276,12 @@ void inp_rem_unused_models(struct nscope *root, struct card *deck) struct modellist *modl_new; modl_new = TMALLOC(struct modellist, 1); char *model_type = get_model_type(curr_line); + if (!model_type) { + fprintf(stderr, "Warning: no model type given in line %s, ignored!\n", curr_line); + tfree(modl_new); + *curr_line = '*'; + continue; + } modl_new->elemb = inp_get_elem_ident(model_type); modl_new->modelname = get_subckt_model_name(curr_line); modl_new->model = card; From f32f3ac8cd8e1bd5155dc0294b2d6e5749652661 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 13 Mar 2023 09:59:29 +0100 Subject: [PATCH 44/91] Improve previous commit: A bad .model line leads to a breakup of the simulation. --- src/frontend/inpcom.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index b98ea8163..ed32283e8 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -10277,10 +10277,9 @@ void inp_rem_unused_models(struct nscope *root, struct card *deck) modl_new = TMALLOC(struct modellist, 1); char *model_type = get_model_type(curr_line); if (!model_type) { - fprintf(stderr, "Warning: no model type given in line %s, ignored!\n", curr_line); + fprintf(stderr, "Error: no model type given in line %s!\n", curr_line); tfree(modl_new); - *curr_line = '*'; - continue; + controlled_exit(EXIT_BAD); } modl_new->elemb = inp_get_elem_ident(model_type); modl_new->modelname = get_subckt_model_name(curr_line); From e4601c16ee201feb7e5531c27b5f62c77fb82be3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 14 Mar 2023 21:14:18 +0100 Subject: [PATCH 45/91] Not a warning but an error, stopping the simulation --- src/frontend/inpcom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index ed32283e8..916fd4ec7 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -8652,12 +8652,12 @@ static struct card *pspice_compat(struct card *oldcard) cut_line = nexttok(cut_line); /* skip .model */ modname = gettok(&cut_line); /* save model name */ if (!modname) { - fprintf(stderr, "Warning: No model name given for %s\n", curr_line); + fprintf(stderr, "Error: No model name given for %s\n", curr_line); controlled_exit(EXIT_BAD); } modtype = gettok_noparens(&cut_line); /* save model type */ if (!modtype) { - fprintf(stderr, "Warning: No model type given for %s\n", curr_line); + fprintf(stderr, "Error: No model type given for %s\n", curr_line); controlled_exit(EXIT_BAD); } if (cieq(modtype, "NMOS") || cieq(modtype, "PMOS")) { From c12296182c5d6ab4ecae60257a75836663f96d98 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Tue, 14 Mar 2023 21:47:50 +0100 Subject: [PATCH 46/91] The code in src/frontend/subckt.c has a fixed-size structure called table at the top with a size set to N_GLOBAL_NODES = 1005. If the number of items passed in formal and actual exceeds 1005, then ngspice exits immediately with an error. This patch lets table be reallocated on the fly as needed to accommodate the number of subcircuit arguments, instead of being a fixed value. --- src/frontend/subckt.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 9579784a7..9cd9db8d3 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -89,11 +89,12 @@ extern void tprint(struct card* deck); struct subs; static struct card *doit(struct card *deck, wordlist *modnames); -static int translate(struct card *deck, char *formal, char *actual, char *scname, - const char *subname, struct subs *subs, wordlist const *modnames); +static int translate(struct card *deck, char *formal, int flen, char *actual, + char *scname, const char *subname, struct subs *subs, + wordlist const *modnames); struct bxx_buffer; static void finishLine(struct bxx_buffer *dst, char *src, char *scname); -static int settrans(char *formal, char *actual, const char *subname); +static int settrans(char *formal, int flen, char *actual, const char *subname); static char *gettrans(const char *name, const char *name_end); static int numnodes(const char *line, struct subs *subs, wordlist const *modnames); static int numdevs(char *s); @@ -106,12 +107,12 @@ static int inp_numnodes(char c); /*--------------------------------------------------------------------- * table is used in settrans and gettrans -- it holds the netnames used * in the .subckt definition (t_old), and in the subcircuit invocation - * (t_new) + * (t_new). The table ends when t_old is NULL. *--------------------------------------------------------------------*/ static struct tab { char *t_old; char *t_new; -} table[N_GLOBAL_NODES]; /* That had better be enough. */ +} *table; /*--------------------------------------------------------------------- @@ -739,7 +740,7 @@ doit(struct card *deck, wordlist *modnames) { /* now invoke translate, which handles the remainder of the * translation. */ - if (!translate(su_deck, sss->su_args, t, scname, sss->su_name, subs, modnames)) + if (!translate(su_deck, sss->su_args, sss->su_numargs, t, scname, sss->su_name, subs, modnames)) error = 1; /* Now splice the decks together. */ @@ -1139,7 +1140,7 @@ translate_inst_name(struct bxx_buffer *buffer, const char *scname, const char *n static int -translate(struct card *deck, char *formal, char *actual, char *scname, const char *subname, struct subs *subs, wordlist const *modnames) +translate(struct card *deck, char *formal, int flen, char *actual, char *scname, const char *subname, struct subs *subs, wordlist const *modnames) { struct card *c; struct bxx_buffer buffer; @@ -1150,7 +1151,7 @@ translate(struct card *deck, char *formal, char *actual, char *scname, const cha bxx_init(&buffer); /* settrans builds the table holding the translated netnames. */ - i = settrans(formal, actual, subname); + i = settrans(formal, flen, actual, subname); if (i < 0) { fprintf(stderr, "Too few parameters for subcircuit type \"%s\" (instance: x%s)\n", @@ -1490,12 +1491,14 @@ translate(struct card *deck, char *formal, char *actual, char *scname, const cha } rtn = 1; quit: - for (i = 0; i < N_GLOBAL_NODES; i++) { + for (i = 0; ; i++) { if (!table[i].t_old && !table[i].t_new) break; FREE(table[i].t_old); FREE(table[i].t_new); } + FREE(table); + table = (struct tab *)NULL; bxx_free(&buffer); return rtn; @@ -1576,13 +1579,14 @@ finishLine(struct bxx_buffer *t, char *src, char *scname) * subname = copy of the subcircuit name *------------------------------------------------------------------------------*/ static int -settrans(char *formal, char *actual, const char *subname) +settrans(char *formal, int flen, char *actual, const char *subname) { int i; - memset(table, 0, N_GLOBAL_NODES * sizeof(*table)); + table = TMALLOC(struct tab, flen + 1); + memset(table, 0, (size_t)(flen + 1) * sizeof(struct tab)); - for (i = 0; i < N_GLOBAL_NODES; i++) { + for (i = 0; i < flen; i++) { table[i].t_old = gettok(&formal); table[i].t_new = gettok(&actual); @@ -1595,10 +1599,6 @@ settrans(char *formal, char *actual, const char *subname) return 1; /* Too many actual / too few formal */ } } - if (i == N_GLOBAL_NODES) { - fprintf(stderr, "ERROR, N_GLOBAL_NODES overflow\n"); - controlled_exit(EXIT_FAILURE); - } return 0; } From d8505f0069f35feea0bed91fb837d704d4403845 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 13:15:11 +0100 Subject: [PATCH 47/91] Make error message more verbose by a hint to the line (fragment). --- src/frontend/numparam/xpressn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 2a59f807d..a8ac9b6f5 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -1272,7 +1272,7 @@ nupa_substitute(dico_t *dico, const char *s, char *r) } if (*kptr == '\0') { - err = message(dico, "Closing \"}\" not found.\n"); + err = message(dico, "Closing \"}\" not found in line fragment\n {%s.\n", s); goto Lend; } From e4202ea1817b06ed22321726e5de2d086f7c5649 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 13:33:44 +0100 Subject: [PATCH 48/91] The tc for R, L, C may include an expression like tc={expression} or tc={expression}, 1.3u or tc={expression}, {expression2} --- src/frontend/inpcom.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 916fd4ec7..9a3ac7439 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -8819,6 +8819,7 @@ static struct card *pspice_compat(struct card *oldcard) } char *tctok = search_plain_identifier(ntok, "tc"); if (tctok) { + char *tc1, *tc2; char *tctok1 = strchr(tctok, '='); if (tctok1) /* skip '=' */ @@ -8826,8 +8827,23 @@ static struct card *pspice_compat(struct card *oldcard) else /* no '=' found, skip 'tc' */ tctok1 = tctok + 2; - char *tc1 = gettok_node(&tctok1); - char *tc2 = gettok_node(&tctok1); + /* tc1 may be an expression, enclosed in {} */ + if (*tctok1 == '{') { + tc1 = gettok_char(&tctok1, '}', TRUE, TRUE); + } + else { + tc1 = gettok_node(&tctok1); + } + /* skip spaces and commas */ + while (isspace_c(*tctok1) || (*tctok1 == ',')) + tctok1++; + /* tc2 may be an expression, enclosed in {} */ + if (*tctok1 == '{') { + tc2 = gettok_char(&tctok1, '}', TRUE, TRUE); + } + else { + tc2 = gettok_node(&tctok1); + } tctok[-1] = '\0'; char *newstring; if (tc1 && tc2) From 63d86f5af852a175b8f4b61d1ef4c296a12294c2 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 15:42:34 +0100 Subject: [PATCH 49/91] Prevent a crash in strchr Reported by KiCad Sentry --- src/frontend/inpc_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 4c547446b..7ef70ce93 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -1264,8 +1264,12 @@ void modprobenames(INPtables* tab) { char* name = GENinst->GENname; if (prefix("vcurr_", name)) { /* copy from char no. 6 to (and excluding) second colon */ + char* endname2; char* endname = strchr(name, ':'); - char* endname2 = strchr(endname + 1, ':'); + if (endname) + endname2 = strchr(endname + 1, ':'); + else /* not a single colon, something different? */ + continue; /* two-terminal device, one colon, copy all from char no. 6 to (and excluding) colon */ if (!endname2) { char* newname = copy_substring(name + 6, endname); From f34ff7e63ce2670a40e3e56ac2fd7023543e97f7 Mon Sep 17 00:00:00 2001 From: dwarning Date: Sat, 18 Feb 2023 18:28:59 +0100 Subject: [PATCH 50/91] Revert "implement typedpnjlim as optional limiter for verilog-a models" This reverts commit f73d3b20a07cd206db8d7c7dd8679e6eecb02391. --- src/osdi/osdicallbacks.c | 12 ------------ src/osdi/osdidefs.h | 3 +-- src/osdi/osdiregistry.c | 1 - 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/osdi/osdicallbacks.c b/src/osdi/osdicallbacks.c index 1efecf212..de7b1dc97 100644 --- a/src/osdi/osdicallbacks.c +++ b/src/osdi/osdicallbacks.c @@ -50,18 +50,6 @@ double osdi_pnjlim(bool init, bool *check, double vnew, double vold, double vt, return res; } -double osdi_typedpnjlim(bool init, bool *check, double vnew, double vold, double vt, - double vcrit, double type) { - if (init) { - *check = true; - return vcrit; - } - int icheck = 0; - double res = DEVpnjlim(type*vnew, vold, vt, vcrit, &icheck); - *check = icheck != 0; - return res; -} - double osdi_limvds(bool init, bool *check, double vnew, double vold) { if (init) { *check = true; diff --git a/src/osdi/osdidefs.h b/src/osdi/osdidefs.h index d1108b666..6130482ad 100644 --- a/src/osdi/osdidefs.h +++ b/src/osdi/osdidefs.h @@ -96,8 +96,7 @@ typedef void (*osdi_log_ptr)(void *handle, char *msg, uint32_t lvl); double osdi_pnjlim(bool init, bool *icheck, double vnew, double vold, double vt, double vcrit); -double osdi_typedpnjlim(bool init, bool *icheck, double vnew, double vold, double vt, - double vcrit, double type); + double osdi_limvds(bool init, bool *icheck, double vnew, double vold); double osdi_limitlog(bool init, bool *icheck, double vnew, double vold, double LIM_TOL); diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c index dc5c47756..e3362fa38 100644 --- a/src/osdi/osdiregistry.c +++ b/src/osdi/osdiregistry.c @@ -340,7 +340,6 @@ extern OsdiObjectFile load_object_file(const char *input) { for (uint32_t i = 0; i < lim_table_len; i++) { int expected_args = -1; IS_LIM_FUN("pnjlim", 2, osdi_pnjlim) - IS_LIM_FUN("typedpnjlim", 3, osdi_typedpnjlim) IS_LIM_FUN("limvds", 0, osdi_limvds) IS_LIM_FUN("fetlim", 1, osdi_fetlim) IS_LIM_FUN("limitlog", 1, osdi_limitlog) From 7af6c4a661b7b3bb3754b7439fa17d8c36435d70 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 10:05:17 +0100 Subject: [PATCH 51/91] Re-enable single line parameter lists, separated by commas --- src/frontend/inpcom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 9a3ac7439..75a7039c1 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -5096,6 +5096,8 @@ static int inp_split_multi_param_lines(struct card *card, int line_num) end_param++; if (*end_param == '"') end_param++; + } else if (*end_param == ',' && paren_depth == 0) { + break; } else { while (*end_param != '\0' && *end_param != '"' && (!isspace_c(*end_param) || From 3996d27b29e5d58ebdf7d153959b31cf175b79e9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 22:28:32 +0100 Subject: [PATCH 52/91] Make code a little more efficient --- src/frontend/inpcom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 75a7039c1..67d1ea3a3 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -5106,11 +5106,11 @@ static int inp_split_multi_param_lines(struct card *card, int line_num) break; if (*end_param == '{') ++expression_depth; - if (*end_param == '(') + else if (*end_param == '(') ++paren_depth; - if (*end_param == '}' && expression_depth > 0) + else if (*end_param == '}' && expression_depth > 0) --expression_depth; - if (*end_param == ')' && paren_depth > 0) + else if (*end_param == ')' && paren_depth > 0) --paren_depth; end_param++; } From 71571a1432b2f5acb85d3d220a97a55efb7dc64d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 15 Mar 2023 16:06:58 +0100 Subject: [PATCH 53/91] Add function atanh to .control section --- src/frontend/parse.c | 1 + src/include/ngspice/fteext.h | 1 + src/maths/cmaths/cmath1.c | 32 ++++++++++++++++++++++++++++++++ src/maths/cmaths/cmath1.h | 1 + 4 files changed, 35 insertions(+) diff --git a/src/frontend/parse.c b/src/frontend/parse.c index 89581b964..16666a1bc 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -343,6 +343,7 @@ struct func ft_funcs[] = { { "cosh", cx_cosh }, { "tanh", cx_tanh }, { "atan", cx_atan }, + { "atanh", cx_atanh }, { "sortorder", cx_sortorder }, { "norm", cx_norm }, { "rnd", cx_rnd }, diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 5907badb4..7c8a383b7 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -74,6 +74,7 @@ extern void *cx_cosh(void *, short int , int , int *, short int *); extern void *cx_tan(void *, short int , int , int *, short int *); extern void *cx_tanh(void *, short int , int , int *, short int *); extern void *cx_atan(void *, short int , int , int *, short int *); +extern void *cx_atanh(void*, short int, int, int*, short int*); extern void *cx_floor(void *, short int , int , int *, short int *); extern void *cx_ceil(void *, short int , int , int *, short int *); extern void *cx_nint(void *, short int , int , int *, short int *); diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index 3f36ecd33..d90128882 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -21,6 +21,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include +#include #include "ngspice/ngspice.h" #include "ngspice/memory.h" @@ -862,6 +863,37 @@ cx_tanh(void *data, short int type, int length, int *newlength, short int *newty } } +/** atanh of a complex vector: use C99 function catanh. */ +void* +cx_atanh(void* data, short int type, int length, int* newlength, short int* newtype) +{ + if (type == VF_COMPLEX) { + ngcomplex_t* d = alloc_c(length); + *newtype = VF_COMPLEX; + *newlength = length; + ngcomplex_t* cc = (ngcomplex_t*)data; + int i; + for (i = 0; i < length; i++) { + _Dcomplex midin = _Cbuild(cc->cx_real, cc->cx_imag); + _Dcomplex midout = catanh(midin); + d[i].cx_real = creal(midout); + d[i].cx_imag = cimag(midout); + } + return ((void*)d); + } + else { + double* d = alloc_d(length); + *newtype = VF_REAL; + *newlength = length; + double* cc = (double*)data; + int i; + for (i = 0; i < length; i++) { + d[i] = atanh(cc[i]); + } + return ((void*)d); + } +} + /** atan of a complex vector: return atan of the real part. */ void * cx_atan(void *data, short int type, int length, int *newlength, short int *newtype) diff --git a/src/maths/cmaths/cmath1.h b/src/maths/cmaths/cmath1.h index 24671f60a..fbda4bd54 100644 --- a/src/maths/cmaths/cmath1.h +++ b/src/maths/cmaths/cmath1.h @@ -32,6 +32,7 @@ void * cx_cosh(void *data, short int type, int length, int *newlength, short int void * cx_tan(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_tanh(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_atan(void *data, short int type, int length, int *newlength, short int *newtype); +void * cx_atanh(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_sortorder(void *data, short int type, int length, int *newlength, short int *newtype); From 68156fa62c6284d8a91dcb84378cecf1c72b6056 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 15 Mar 2023 18:32:43 +0100 Subject: [PATCH 54/91] Complex number handling other than MSVC --- src/maths/cmaths/cmath1.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index d90128882..f0ecf0821 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -874,8 +874,13 @@ cx_atanh(void* data, short int type, int length, int* newlength, short int* newt ngcomplex_t* cc = (ngcomplex_t*)data; int i; for (i = 0; i < length; i++) { +#ifdef _MSC_VER _Dcomplex midin = _Cbuild(cc->cx_real, cc->cx_imag); _Dcomplex midout = catanh(midin); +#else + double complex midin = cc->cx_real + _Complex_I * cc->cx_imag; + double complex midout = catanh(midin); +#endif d[i].cx_real = creal(midout); d[i].cx_imag = cimag(midout); } From 2a6052517bc3dcbdb3938cbbb0458ded832e1ec6 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 21:04:08 +0100 Subject: [PATCH 55/91] Fix prvious commit: allow access to all vector elements of cc --- src/maths/cmaths/cmath1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index f0ecf0821..34ddc9ca1 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -875,10 +875,10 @@ cx_atanh(void* data, short int type, int length, int* newlength, short int* newt int i; for (i = 0; i < length; i++) { #ifdef _MSC_VER - _Dcomplex midin = _Cbuild(cc->cx_real, cc->cx_imag); + _Dcomplex midin = _Cbuild(cc[i].cx_real, cc[i].cx_imag); _Dcomplex midout = catanh(midin); #else - double complex midin = cc->cx_real + _Complex_I * cc->cx_imag; + double complex midin = cc[i].cx_real + _Complex_I * cc[i].cx_imag; double complex midout = catanh(midin); #endif d[i].cx_real = creal(midout); From 3632a6b4ae73e9186eeced31cdfb70350e6769f6 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 21:27:41 +0100 Subject: [PATCH 56/91] We need to translate from degree to rad --- src/maths/cmaths/cmath1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index 34ddc9ca1..8389fea4a 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -875,10 +875,10 @@ cx_atanh(void* data, short int type, int length, int* newlength, short int* newt int i; for (i = 0; i < length; i++) { #ifdef _MSC_VER - _Dcomplex midin = _Cbuild(cc[i].cx_real, cc[i].cx_imag); + _Dcomplex midin = _Cbuild(degtorad(realpart(cc[i])), degtorad(imagpart(cc[i]))); _Dcomplex midout = catanh(midin); #else - double complex midin = cc[i].cx_real + _Complex_I * cc[i].cx_imag; + double complex midin = degtorad(realpart(cc[i])) + _Complex_I * degtorad(imagpart(cc[i])); double complex midout = catanh(midin); #endif d[i].cx_real = creal(midout); From 6213145c945a7b0cc008a5078738e9f9fb96819c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 14:49:11 +0100 Subject: [PATCH 57/91] .control section: atanh examples --- examples/various/atanh.sp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/various/atanh.sp diff --git a/examples/various/atanh.sp b/examples/various/atanh.sp new file mode 100644 index 000000000..e7889ea48 --- /dev/null +++ b/examples/various/atanh.sp @@ -0,0 +1,27 @@ +atanh test for real and complex inputs +v1 1 0 dc 0 ac 1 +r1 1 2 50 +c1 2 0 40f +l1 2 3 50p +c2 3 0 40f +l2 3 4 50p +r2 4 0 50 +.control +* real numbers +let invec = vector(1999) +compose invec start=-0.999 stop=0.999 step=0.001 +let outvec = atanh(invec) +setscale invec +set xbrushwidth=3 +plot outvec +ac dec 100 1g 100g +let X=v(4); complex vector to be worked +*complex numbers +let Y1=X+X^3/3+X^5/5+X^7/7+X^9/9+X^11/11; pseudo atanh +Let Y2 = atanh(X) +plot polar Y1 +plot polar Y2 +plot polar Y1 Y2 + +.endc +.end From 86951501a7ffffcd43454659d09f8a81055b7096 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 19 Mar 2023 12:10:52 +0100 Subject: [PATCH 58/91] Add eprvcd to the commands which set node names to lower case, but not the file names after > Does not work for manually entered eprvcd commands, where the user has to provide lower case node names. --- src/frontend/inpcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 67d1ea3a3..1767b1c4a 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -1538,6 +1538,7 @@ struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name, } else if (ciprefix("print", buffer) || ciprefix("eprint", buffer) || + ciprefix("eprvcd", buffer) || ciprefix("asciiplot", buffer)) { /* lower case excluded for tokens following output redirection * '>' */ From 164db58404d1933d662c99b7d735e21c5f6e66eb Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 10 Mar 2023 11:40:37 -0800 Subject: [PATCH 59/91] The intent now is to rely on a variable setting in .spiceinit to control the use of inertial delay XSPICE digital models. This will apply to U* instances in subcircuits which are translated to XSPICE. --- src/frontend/logicexp.c | 26 +++++++++++++------------- src/frontend/udevices.c | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 6dc47c680..055883ad8 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -680,47 +680,47 @@ static void gen_models(void) ds_clear(&model); ds_cat_printf(&model, - ".model d_inv_zero_delay d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_inv_zero_delay d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__inverter__1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__inverter__1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__buffer__1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__buffer__1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nand__1 d_nand(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nand__1 d_nand(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__and__1 d_and(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__and__1 d_and(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xnor__1 d_xnor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xnor__1 d_xnor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xor__1 d_xor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xor__1 d_xor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nor__1 d_nor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nor__1 d_nor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__or__1 d_or(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__or__1 d_or(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_free(&model); @@ -2027,11 +2027,11 @@ static BOOL extract_delay( if (ds_get_length(&dtyp_max_str) > 0) { if (tri) { ds_cat_printf(&delay_string, - "(inertial_delay=true delay=%s)", + "(delay=%s)", ds_get_buf(&dtyp_max_str)); } else { ds_cat_printf(&delay_string, - "(inertial_delay=true rise_delay=%s fall_delay=%s)", + "(rise_delay=%s fall_delay=%s)", ds_get_buf(&dtyp_max_str), ds_get_buf(&dtyp_max_str)); } @@ -2039,10 +2039,10 @@ static BOOL extract_delay( printf("WARNING pindly DELAY not found\n"); if (tri) { ds_cat_printf(&delay_string, - "(inertial_delay=true delay=10ns)"); + "(delay=10ns)"); } else { ds_cat_printf(&delay_string, - "(inertial_delay=true rise_delay=10ns fall_delay=10ns)"); + "(rise_delay=10ns fall_delay=10ns)"); } } for (i = 0; i < idx; i++) { diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 09a3ddf3e..f857a53c4 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -748,7 +748,7 @@ struct card *replacement_udevice_cards(void) } if (add_zero_delay_inverter_model) { x = create_xlate_translated( - ".model d_zero_inv99 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_zero_inv99 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); } if (add_drive_hilo) { @@ -757,7 +757,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a1 0 drive___0 dbuf1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dbuf1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dbuf1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___lo"); translated_p = add_xlator(translated_p, x); @@ -766,7 +766,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a2 0 drive___1 dinv1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dinv1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dinv1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___hi"); translated_p = add_xlator(translated_p, x); @@ -891,7 +891,7 @@ void initialize_udevice(char *subckt_line) model_xlatorp = create_xlator(); default_models = create_xlator(); /* .model d0_gate ugate () */ - xdata = create_xlate("", "(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)", + xdata = create_xlate("", "(rise_delay=1.0e-12 fall_delay=1.0e-12)", "ugate", "", "d0_gate", ""); (void) add_xlator(default_models, xdata); /* .model d0_gff ugff () */ @@ -903,7 +903,7 @@ void initialize_udevice(char *subckt_line) xdata = create_xlate("", "", "ueff", "", "d0_eff", ""); (void) add_xlator(default_models, xdata); /* .model d0_tgate utgate () */ - xdata = create_xlate("", "(inertial_delay=true delay=1.0e-12)", + xdata = create_xlate("", "(delay=1.0e-12)", "utgate", "", "d0_tgate", ""); (void) add_xlator(default_models, xdata); /* reset for the new subckt */ @@ -2618,7 +2618,7 @@ static char *larger_delay(char *delay1, char *delay2) static char *get_zero_rise_fall(void) { /* The caller needs to tfree the returned string after use */ - return tprintf("(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); + return tprintf("(rise_delay=1.0e-12 fall_delay=1.0e-12)"); } static char *get_delays_ugate(char *rem) @@ -2637,14 +2637,14 @@ static char *get_delays_ugate(char *rem) has_falling = (falling && strlen(falling) > 0); if (has_rising) { if (has_falling) { - delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", + delays = tprintf("(rise_delay = %s fall_delay = %s)", rising, falling); } else { - delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = 1.0e-12)", + delays = tprintf("(rise_delay = %s fall_delay = 1.0e-12)", rising); } } else if (has_falling) { - delays = tprintf("(inertial_delay=true rise_delay = 1.0e-12 fall_delay = %s)", + delays = tprintf("(rise_delay = 1.0e-12 fall_delay = %s)", falling); } else { delays = get_zero_rise_fall(); @@ -2675,12 +2675,12 @@ static char *get_delays_utgate(char *rem) if (has_rising) { if (has_falling) { larger = larger_delay(rising, falling); - delays = tprintf("(inertial_delay=true delay = %s)", larger); + delays = tprintf("(delay = %s)", larger); } else { - delays = tprintf("(inertial_delay=true delay = %s)", rising); + delays = tprintf("(delay = %s)", rising); } } else if (has_falling) { - delays = tprintf("(inertial_delay=true delay = %s)", falling); + delays = tprintf("(delay = %s)", falling); } else if (use_zdelays) { /* No lh/hl delays, so try the largest lz/hz/zl/zh delay */ tdp3 = create_min_typ_max("tplz", rem); @@ -2726,16 +2726,16 @@ static char *get_delays_utgate(char *rem) larger3 = larger2; } if (larger3) { - delays = tprintf("(inertial_delay=true delay = %s)", larger3); + delays = tprintf("(delay = %s)", larger3); } else { - delays = tprintf("(inertial_delay=true delay=1.0e-12)"); + delays = tprintf("(delay=1.0e-12)"); } delete_timing_data(tdp3); delete_timing_data(tdp4); delete_timing_data(tdp5); delete_timing_data(tdp6); } else { // Not use_zdelays - delays = tprintf("(inertial_delay=true delay=1.0e-12)"); + delays = tprintf("(delay=1.0e-12)"); } delete_timing_data(tdp1); delete_timing_data(tdp2); From 40a540a2ffea2fc942629108f316ba40dd56193c Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 17 Mar 2023 07:18:12 -0700 Subject: [PATCH 60/91] Add inertial_delay=true to .model statements generated when U* instances in PSpice library subckts are translated to Xspice. Any other Xspice A* digital instances might have different inertial_delay settings in their models, so potentially there could be a mixture of delay types. For example, if a user wishes to model a DLYLINE using a d_buffer with inertial_delay=false and equal rise/fall delays. --- src/frontend/logicexp.c | 26 +++++++++++++------------- src/frontend/udevices.c | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 055883ad8..6dc47c680 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -680,47 +680,47 @@ static void gen_models(void) ds_clear(&model); ds_cat_printf(&model, - ".model d_inv_zero_delay d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_inv_zero_delay d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__inverter__1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__inverter__1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__buffer__1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__buffer__1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nand__1 d_nand(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nand__1 d_nand(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__and__1 d_and(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__and__1 d_and(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xnor__1 d_xnor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xnor__1 d_xnor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xor__1 d_xor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__xor__1 d_xor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nor__1 d_nor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__nor__1 d_nor(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__or__1 d_or(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d__or__1 d_or(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_free(&model); @@ -2027,11 +2027,11 @@ static BOOL extract_delay( if (ds_get_length(&dtyp_max_str) > 0) { if (tri) { ds_cat_printf(&delay_string, - "(delay=%s)", + "(inertial_delay=true delay=%s)", ds_get_buf(&dtyp_max_str)); } else { ds_cat_printf(&delay_string, - "(rise_delay=%s fall_delay=%s)", + "(inertial_delay=true rise_delay=%s fall_delay=%s)", ds_get_buf(&dtyp_max_str), ds_get_buf(&dtyp_max_str)); } @@ -2039,10 +2039,10 @@ static BOOL extract_delay( printf("WARNING pindly DELAY not found\n"); if (tri) { ds_cat_printf(&delay_string, - "(delay=10ns)"); + "(inertial_delay=true delay=10ns)"); } else { ds_cat_printf(&delay_string, - "(rise_delay=10ns fall_delay=10ns)"); + "(inertial_delay=true rise_delay=10ns fall_delay=10ns)"); } } for (i = 0; i < idx; i++) { diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index f857a53c4..09a3ddf3e 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -748,7 +748,7 @@ struct card *replacement_udevice_cards(void) } if (add_zero_delay_inverter_model) { x = create_xlate_translated( - ".model d_zero_inv99 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model d_zero_inv99 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); } if (add_drive_hilo) { @@ -757,7 +757,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a1 0 drive___0 dbuf1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dbuf1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dbuf1 d_buffer(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___lo"); translated_p = add_xlator(translated_p, x); @@ -766,7 +766,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a2 0 drive___1 dinv1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dinv1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + ".model dinv1 d_inverter(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___hi"); translated_p = add_xlator(translated_p, x); @@ -891,7 +891,7 @@ void initialize_udevice(char *subckt_line) model_xlatorp = create_xlator(); default_models = create_xlator(); /* .model d0_gate ugate () */ - xdata = create_xlate("", "(rise_delay=1.0e-12 fall_delay=1.0e-12)", + xdata = create_xlate("", "(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)", "ugate", "", "d0_gate", ""); (void) add_xlator(default_models, xdata); /* .model d0_gff ugff () */ @@ -903,7 +903,7 @@ void initialize_udevice(char *subckt_line) xdata = create_xlate("", "", "ueff", "", "d0_eff", ""); (void) add_xlator(default_models, xdata); /* .model d0_tgate utgate () */ - xdata = create_xlate("", "(delay=1.0e-12)", + xdata = create_xlate("", "(inertial_delay=true delay=1.0e-12)", "utgate", "", "d0_tgate", ""); (void) add_xlator(default_models, xdata); /* reset for the new subckt */ @@ -2618,7 +2618,7 @@ static char *larger_delay(char *delay1, char *delay2) static char *get_zero_rise_fall(void) { /* The caller needs to tfree the returned string after use */ - return tprintf("(rise_delay=1.0e-12 fall_delay=1.0e-12)"); + return tprintf("(inertial_delay=true rise_delay=1.0e-12 fall_delay=1.0e-12)"); } static char *get_delays_ugate(char *rem) @@ -2637,14 +2637,14 @@ static char *get_delays_ugate(char *rem) has_falling = (falling && strlen(falling) > 0); if (has_rising) { if (has_falling) { - delays = tprintf("(rise_delay = %s fall_delay = %s)", + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = %s)", rising, falling); } else { - delays = tprintf("(rise_delay = %s fall_delay = 1.0e-12)", + delays = tprintf("(inertial_delay=true rise_delay = %s fall_delay = 1.0e-12)", rising); } } else if (has_falling) { - delays = tprintf("(rise_delay = 1.0e-12 fall_delay = %s)", + delays = tprintf("(inertial_delay=true rise_delay = 1.0e-12 fall_delay = %s)", falling); } else { delays = get_zero_rise_fall(); @@ -2675,12 +2675,12 @@ static char *get_delays_utgate(char *rem) if (has_rising) { if (has_falling) { larger = larger_delay(rising, falling); - delays = tprintf("(delay = %s)", larger); + delays = tprintf("(inertial_delay=true delay = %s)", larger); } else { - delays = tprintf("(delay = %s)", rising); + delays = tprintf("(inertial_delay=true delay = %s)", rising); } } else if (has_falling) { - delays = tprintf("(delay = %s)", falling); + delays = tprintf("(inertial_delay=true delay = %s)", falling); } else if (use_zdelays) { /* No lh/hl delays, so try the largest lz/hz/zl/zh delay */ tdp3 = create_min_typ_max("tplz", rem); @@ -2726,16 +2726,16 @@ static char *get_delays_utgate(char *rem) larger3 = larger2; } if (larger3) { - delays = tprintf("(delay = %s)", larger3); + delays = tprintf("(inertial_delay=true delay = %s)", larger3); } else { - delays = tprintf("(delay=1.0e-12)"); + delays = tprintf("(inertial_delay=true delay=1.0e-12)"); } delete_timing_data(tdp3); delete_timing_data(tdp4); delete_timing_data(tdp5); delete_timing_data(tdp6); } else { // Not use_zdelays - delays = tprintf("(delay=1.0e-12)"); + delays = tprintf("(inertial_delay=true delay=1.0e-12)"); } delete_timing_data(tdp1); delete_timing_data(tdp2); From 8c69ada5b534e909aea642b6b15fcbfb670914bf Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Tue, 7 Mar 2023 17:16:38 -0800 Subject: [PATCH 61/91] The logicexp example in the PSpice ref. manual has a name with a '+' character (LCN+4). Update lexer_scan. --- src/frontend/logicexp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 6dc47c680..e25b89a5c 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -347,7 +347,7 @@ static int lex_gate_op(int c) static int lex_ident(int c) { /* Pspice and MicroCap are vague about what defines an identifier */ - if (isalnum(c) || c == '_' || c == '/' || c == '-') + if (isalnum(c) || c == '_' || c == '/' || c == '-' || c == '+') return c; else return 0; @@ -369,6 +369,11 @@ static int lexer_scan(LEXER lx) return c; else if (lex_ident(c)) { size_t i = 0; + if (c == '+') { // an identifier does not begin with '+' + lx->lexer_buf[0] = (char) c; + lx->lexer_buf[1] = '\0'; + return LEX_OTHER; + } while (lex_ident(c)) { if (i >= lx->lexer_blen) { lx->lexer_blen *= 2; From 2d0561f386b6d96ac5d05def0be2d36559f46759 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Sat, 5 Nov 2022 21:07:46 +0000 Subject: [PATCH 62/91] Allow string-valued parameters to XSPICE device models with no default. The code model then sees the value NULL. Needed for the "family" parameter on logic models, used by automatic bridge insertion. --- src/xspice/mif/mif_inp2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xspice/mif/mif_inp2.c b/src/xspice/mif/mif_inp2.c index bb603f78a..41f606b9a 100644 --- a/src/xspice/mif/mif_inp2.c +++ b/src/xspice/mif/mif_inp2.c @@ -568,8 +568,15 @@ MIF_INP2A ( param_info = &(DEVices[type]->DEVpublic.param[i]); if(mdfast->param[i]->is_null) { + char* emessage; + if(! param_info->has_default) { - LITERR("Parameter on model has no default"); + if (param_info->type == MIF_STRING) + continue; // Allow NULL + emessage = tprintf("Parameter %s on model %s has no default", + param_info->name, mdfast->gen.GENmodName); + LITERR(emessage); + tfree(emessage); gc_end(); return; } else if((param_info->is_array) && (! param_info->has_conn_ref)) { From c1659a64c33df46bd313e8d1f07cdbfce2b5461c Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Thu, 23 Feb 2023 17:56:40 +0000 Subject: [PATCH 63/91] Change output event setup in evtload.c so that, when making an event call to a code model, there is no longer a reference to the value of the event at the head of the free list. That allows all such free lists (with the same data type) to be combined, probably improving performance. This is in preparation for full implementation of inertial delay for digital nodes. --- src/include/ngspice/evt.h | 2 +- src/include/ngspice/evtproto.h | 1 + src/include/ngspice/evtudn.h | 26 +++--- src/include/ngspice/mifcmdat.h | 1 + src/xspice/evt/evtaccept.c | 7 +- src/xspice/evt/evtbackup.c | 7 +- src/xspice/evt/evtdest.c | 10 +- src/xspice/evt/evtinit.c | 3 +- src/xspice/evt/evtload.c | 126 +++++++++++--------------- src/xspice/evt/evtsetup.c | 56 +++++++++--- src/xspice/icm/xtraevt/int/udnfunc.c | 1 + src/xspice/icm/xtraevt/real/udnfunc.c | 1 + src/xspice/idn/idndig.c | 1 + 13 files changed, 124 insertions(+), 118 deletions(-) diff --git a/src/include/ngspice/evt.h b/src/include/ngspice/evt.h index 2917b76a5..7dfb35c27 100644 --- a/src/include/ngspice/evt.h +++ b/src/include/ngspice/evt.h @@ -172,7 +172,7 @@ struct Evt_Output_Queue { Evt_Output_Event_t **head; /* Beginning of linked lists */ Evt_Output_Event_t ***current; /* Beginning of pending events */ Evt_Output_Event_t ***last_step; /* Values of 'current' at last accepted timepoint */ - Evt_Output_Event_t **free; /* Linked lists of items freed by backups */ + Evt_Output_Event_t ***free_list; /* Pointers to linked lists of items freed by backups */ double last_time; /* Time at which last_step was set */ double next_time; /* Earliest next event time in queue */ int num_modified; /* Number modified since last accepted timepoint */ diff --git a/src/include/ngspice/evtproto.h b/src/include/ngspice/evtproto.h index 359133801..f37bb0fa7 100644 --- a/src/include/ngspice/evtproto.h +++ b/src/include/ngspice/evtproto.h @@ -134,5 +134,6 @@ bool Evtcheck_nodes( struct INPtables *stab); /* Symbol table. */ struct dvec *EVTfindvec(char *node); +void Evt_purge_free_outputs(void); #endif diff --git a/src/include/ngspice/evtudn.h b/src/include/ngspice/evtudn.h index 936c44daf..0e941a5b5 100644 --- a/src/include/ngspice/evtudn.h +++ b/src/include/ngspice/evtudn.h @@ -99,20 +99,22 @@ NON-STANDARD FEATURES void **evt_ipc_val, \ int *evt_ipc_val_size +/* Information about each Digital/User-defined type of node value. */ typedef struct { - char *name; - char *description; - void ((*create)(CREATE_ARGS)); - void ((*dismantle)(DISMANTLE_ARGS)); - void ((*initialize)(INITIALIZE_ARGS)); - void ((*invert)(INVERT_ARGS)); - void ((*copy)(COPY_ARGS)); - void ((*resolve)(RESOLVE_ARGS)); - void ((*compare)(COMPARE_ARGS)); - void ((*plot_val)(PLOT_VAL_ARGS)); - void ((*print_val)(PRINT_VAL_ARGS)); - void ((*ipc_val)(IPC_VAL_ARGS)); + char *name; + char *description; + Evt_Output_Event_t *free_list; /* Event structs for these values. */ + void ((*create)(CREATE_ARGS)); + void ((*dismantle)(DISMANTLE_ARGS)); + void ((*initialize)(INITIALIZE_ARGS)); + void ((*invert)(INVERT_ARGS)); + void ((*copy)(COPY_ARGS)); + void ((*resolve)(RESOLVE_ARGS)); + void ((*compare)(COMPARE_ARGS)); + void ((*plot_val)(PLOT_VAL_ARGS)); + void ((*print_val)(PRINT_VAL_ARGS)); + void ((*ipc_val)(IPC_VAL_ARGS)); } Evt_Udn_Info_t; diff --git a/src/include/ngspice/mifcmdat.h b/src/include/ngspice/mifcmdat.h index 213713c6c..4196c8ee0 100644 --- a/src/include/ngspice/mifcmdat.h +++ b/src/include/ngspice/mifcmdat.h @@ -226,6 +226,7 @@ typedef struct Mif_Port_Data_s { Mif_Boolean_t is_null; /* Set to true if null in SPICE deck */ Mif_Value_t input; /* The input value */ Mif_Value_t output; /* The output value */ + struct Evt_Output_Event *next_event; Mif_Partial_t *partial; /* Partials for this port wrt inputs */ Mif_AC_Gain_t *ac_gain; /* AC gains for this port wrt inputs */ int old_input; /* Index into CKTstate for old input */ diff --git a/src/xspice/evt/evtaccept.c b/src/xspice/evt/evtaccept.c index 1d031d7ed..0e68c26e6 100644 --- a/src/xspice/evt/evtaccept.c +++ b/src/xspice/evt/evtaccept.c @@ -126,13 +126,14 @@ void EVTaccept( num_modified = output_queue->num_modified; /* Loop through list of items modified since last time */ for(i = 0; i < num_modified; i++) { - Evt_Output_Event_t *stale, *next; + Evt_Output_Event_t *stale, *next, **free_list; /* Get the index of the output modified */ index = output_queue->modified_index[i]; /* Reset the modified flag */ output_queue->modified[index] = MIF_FALSE; /* Move stale entries to the free list. */ + free_list = output_queue->free_list[index]; next = output_queue->head[index]; while (next) { if (next->event_time >= time || @@ -141,8 +142,8 @@ void EVTaccept( } stale = next; next = next->next; - stale->next = output_queue->free[index]; - output_queue->free[index] = stale; + stale->next = *free_list; + *free_list = stale; } output_queue->head[index] = next; if (!next) diff --git a/src/xspice/evt/evtbackup.c b/src/xspice/evt/evtbackup.c index fe1e02784..f857c6816 100644 --- a/src/xspice/evt/evtbackup.c +++ b/src/xspice/evt/evtbackup.c @@ -530,7 +530,7 @@ static void EVTbackup_output_queue( Evt_Output_Queue_t *output_queue; - Evt_Output_Event_t **output_ptr; + Evt_Output_Event_t **output_ptr, **free_list; Evt_Output_Event_t *output; double next_time; @@ -554,12 +554,13 @@ static void EVTbackup_output_queue( output_ptr = output_queue->last_step[output_index]; output = *output_ptr; + free_list = output_queue->free_list[output_index]; while(output) { if(output->posted_time > new_time) { *output_ptr = output->next; - output->next = output_queue->free[output_index]; - output_queue->free[output_index] = output; + output->next = *free_list; + *free_list = output; output = *output_ptr; } else { diff --git a/src/xspice/evt/evtdest.c b/src/xspice/evt/evtdest.c index 454f1a94e..c80367686 100644 --- a/src/xspice/evt/evtdest.c +++ b/src/xspice/evt/evtdest.c @@ -82,18 +82,11 @@ Evt_Queue_destroy(Evt_Ckt_Data_t *evt, Evt_Queue_t *queue) tfree(event); event = next; } - event = output_queue->free[i]; - while (event) { - Evt_Output_Event_t *next = event->next; - tfree(event->value); - tfree(event); - event = next; - } } tfree(output_queue->head); tfree(output_queue->current); tfree(output_queue->last_step); - tfree(output_queue->free); + tfree(output_queue->free_list); tfree(output_queue->modified_index); tfree(output_queue->modified); @@ -101,6 +94,7 @@ Evt_Queue_destroy(Evt_Ckt_Data_t *evt, Evt_Queue_t *queue) tfree(output_queue->pending); tfree(output_queue->changed_index); tfree(output_queue->changed); + Evt_purge_free_outputs(); } /* diff --git a/src/xspice/evt/evtinit.c b/src/xspice/evt/evtinit.c index 1f2b1a041..283c1ea79 100644 --- a/src/xspice/evt/evtinit.c +++ b/src/xspice/evt/evtinit.c @@ -325,7 +325,7 @@ static int EVTinit_queue( CKALLOC(output_queue->head, num_outputs, Evt_Output_Event_t *) CKALLOC(output_queue->current, num_outputs, Evt_Output_Event_t **) CKALLOC(output_queue->last_step, num_outputs, Evt_Output_Event_t **) - CKALLOC(output_queue->free, num_outputs, Evt_Output_Event_t *) + CKALLOC(output_queue->free_list, num_outputs, Evt_Output_Event_t **) CKALLOC(output_queue->modified_index, num_outputs, int) CKALLOC(output_queue->modified, num_outputs, Mif_Boolean_t) CKALLOC(output_queue->pending_index, num_outputs, int) @@ -333,7 +333,6 @@ static int EVTinit_queue( CKALLOC(output_queue->changed_index, num_outputs, int) CKALLOC(output_queue->changed, num_outputs, Mif_Boolean_t) - /* Return */ return(OK); } diff --git a/src/xspice/evt/evtload.c b/src/xspice/evt/evtload.c index f65353743..557eea16d 100644 --- a/src/xspice/evt/evtload.c +++ b/src/xspice/evt/evtload.c @@ -61,20 +61,13 @@ static void EVTadd_msg( int port_index, char *msg_text); -static void EVTcreate_output_event( - CKTcircuit *ckt, - int node_index, - int output_index, - void **value_ptr); +static Evt_Output_Event_t *EVTget_output_event( + CKTcircuit *ckt, + Mif_Port_Data_t *port); static void EVTprocess_output( CKTcircuit *ckt, - Mif_Boolean_t changed, - int output_index, - Mif_Boolean_t invert, - double delay); - - + Mif_Port_Data_t *port); /* EVTload @@ -101,14 +94,10 @@ int EVTload( Mif_Conn_Data_t *conn; Mif_Port_Data_t *port; - - Mif_Private_t cm_data; - + Evt_Node_Data_t *node_data; MIFinstance *inst; - Evt_Node_Data_t *node_data; - - void *value_ptr; + Mif_Private_t cm_data; /* ***************************** */ @@ -191,17 +180,16 @@ int EVTload( port->load = 0.0; port->total_load = node_data->total_load[port->evt_data.node_index]; - /* If connection is an output, initialize changed to true */ - /* and create a new output event object in the free list */ - /* if transient analysis mode */ + /* If connection is an output and transient analysis, + * initialize changed to true and ensure an output location. + */ if(conn->is_output) { port->changed = MIF_TRUE; - if(g_mif_info.circuit.anal_type == MIF_TRAN) { - EVTcreate_output_event(ckt, - port->evt_data.node_index, - port->evt_data.output_index, - &value_ptr); - port->output.pvalue = value_ptr; + if (g_mif_info.circuit.anal_type == MIF_TRAN) { + if (port->next_event == NULL) { + port->next_event = EVTget_output_event(ckt, port); + } + port->output.pvalue = port->next_event->value; } } } @@ -276,9 +264,9 @@ int EVTload( continue; /* If output changed, process it */ - EVTprocess_output(ckt, port->changed, - port->evt_data.output_index, - port->invert, port->delay); + + if (port->changed) + EVTprocess_output(ckt, port); /* And prevent erroneous models from overwriting it during */ /* analog iterations */ @@ -369,43 +357,40 @@ static void EVTcreate_state( /* -EVTcreate_output_event +EVTget_output_event This function creates a new output event. */ -static void EVTcreate_output_event( - CKTcircuit *ckt, /* The circuit structure */ - int node_index, /* The node type port is on */ - int output_index, /* The output index for this port */ - void **value_ptr) /* The event created */ +static Evt_Output_Event_t *EVTget_output_event( + CKTcircuit *ckt, /* The circuit structure */ + Mif_Port_Data_t *port) /* The output port. */ { int udn_index; Evt_Node_Info_t **node_table; Evt_Output_Queue_t *output_queue; - Evt_Output_Event_t *event; + Evt_Output_Event_t *event, **free_list; /* Check the output queue free list and use the structure */ /* at the head of the list if non-null. Otherwise, create a new one. */ + output_queue = &(ckt->evt->queue.output); - if(output_queue->free[output_index]) { - *value_ptr = output_queue->free[output_index]->value; - } - else { + free_list = output_queue->free_list[port->evt_data.output_index]; + if (*free_list) { + event = *free_list; + *free_list = event->next; + } else { /* Create a new event */ event = TMALLOC(Evt_Output_Event_t, 1); event->next = NULL; /* Initialize the value */ node_table = ckt->evt->info.node_table; - udn_index = node_table[node_index]->udn_index; + udn_index = node_table[port->evt_data.node_index]->udn_index; g_evt_udn_info[udn_index]->create (&(event->value)); - - /* Put the event onto the free list and return the value pointer */ - output_queue->free[output_index] = event; - *value_ptr = event->value; } + return event; } @@ -482,16 +467,14 @@ the event is processed immediately. static void EVTprocess_output( - CKTcircuit *ckt, /* The circuit structure */ - Mif_Boolean_t changed, /* Has output changed? */ - int output_index, /* The output of interest */ - Mif_Boolean_t invert, /* Does output need to be inverted? */ - double delay) /* The output delay in transient analysis */ + CKTcircuit *ckt, /* The circuit structure */ + Mif_Port_Data_t *port) { int num_outputs; int node_index; int udn_index; + int output_index; int output_subindex; Evt_Output_Info_t **output_table; @@ -503,33 +486,35 @@ static void EVTprocess_output( Evt_Output_Queue_t *output_queue; Evt_Output_Event_t *output_event; - Mif_Boolean_t equal; - + Mif_Boolean_t invert, equal; + double delay; output_queue = &(ckt->evt->queue.output); output_table = ckt->evt->info.output_table; node_table = ckt->evt->info.node_table; + output_index = port->evt_data.output_index; node_index = output_table[output_index]->node_index; udn_index = node_table[node_index]->udn_index; - + invert = port->invert; /* if transient analysis, just put the output event on the queue */ /* to be processed at a later time */ - if(g_mif_info.circuit.anal_type == MIF_TRAN) { - /* If model signaled that output was not posted, */ - /* leave the event struct on the free list and return */ - if(!changed) - return; + + if (g_mif_info.circuit.anal_type == MIF_TRAN) { + delay = port->delay; if(delay <= 0.0) { printf("\nERROR - Output delay <= 0 not allowed - output ignored!\n"); printf(" Instance: %s\n Node: %s\n Time: %f \n", - g_mif_info.instance->MIFname, node_table[node_index]->name, g_mif_info.ckt->CKTtime); + g_mif_info.instance->MIFname, node_table[node_index]->name, + g_mif_info.ckt->CKTtime); return; } - /* Remove the (now used) struct from the head of the free list */ - output_event = output_queue->free[output_index]; - output_queue->free[output_index] = output_event->next; + /* Remove the (now used) struct from the port data struct. */ + + output_event = port->next_event; + port->next_event = NULL; + /* Invert the output value if necessary */ if(invert) g_evt_udn_info[udn_index]->invert @@ -539,20 +524,11 @@ static void EVTprocess_output( g_mif_info.circuit.evt_step, g_mif_info.circuit.evt_step + delay); return; - } - /* If not transient analysis, process immediately. */ - /* Determine if output has changed from rhsold value */ - /* and put entry in output queue changed list if so */ - else { + } else { + /* If not transient analysis, process immediately. */ + /* Determine if output has changed from rhsold value */ + /* and put entry in output queue changed list if so */ - /* If model signaled that output was not posted, */ - /* just return */ - if(! changed) - return; -/* - if(delay > 0.0) - printf("\nWARNING - Non-zero output delay not allowed in DCOP - delay ignored!\n"); -*/ rhs = ckt->evt->data.node->rhs; rhsold = ckt->evt->data.node->rhsold; diff --git a/src/xspice/evt/evtsetup.c b/src/xspice/evt/evtsetup.c index 606c7959e..761a40bba 100644 --- a/src/xspice/evt/evtsetup.c +++ b/src/xspice/evt/evtsetup.c @@ -183,7 +183,6 @@ static int EVTsetup_queues( Evt_Inst_Event_t *inst_event; Evt_Output_Event_t *output_event; - void *ptr; /* ************************ */ @@ -255,16 +254,9 @@ static int EVTsetup_queues( output_event = output_event->next; FREE(ptr); } - output_event = output_queue->free[i]; - while(output_event) { - ptr = output_event; - output_event = output_event->next; - FREE(ptr); - } output_queue->head[i] = NULL; output_queue->current[i] = &(output_queue->head[i]); output_queue->last_step[i] = &(output_queue->head[i]); - output_queue->free[i] = NULL; } output_queue->next_time = 0.0; @@ -274,15 +266,51 @@ static int EVTsetup_queues( output_queue->num_pending = 0; output_queue->num_changed = 0; - for(i = 0; i < num_outputs; i++) { - output_queue->modified[i] = MIF_FALSE; - output_queue->pending[i] = MIF_FALSE; - output_queue->changed[i] = MIF_FALSE; - } + if (num_outputs > 0) { + for (i = 0; i < num_outputs; i++) { + output_queue->modified[i] = MIF_FALSE; + output_queue->pending[i] = MIF_FALSE; + output_queue->changed[i] = MIF_FALSE; + } - return(OK); + if (output_queue->free_list[0]) { + Evt_purge_free_outputs(); + } else { + Evt_Output_Info_t *output_info; + Evt_Node_Info_t *node; + + /* ********************************************************* * + * On first call for this circuit, set the free-list pointer + * for each output queue. + * ********************************************************* */ + + output_info = ckt->evt->info.output_list; + for (i = 0; i < num_outputs; i++) { + node = ckt->evt->info.node_table[output_info->node_index]; + output_queue->free_list[i] = + &g_evt_udn_info[node->udn_index]->free_list; + output_info = output_info->next; + } + } + } + return OK; } +void Evt_purge_free_outputs(void) +{ + Evt_Output_Event_t *output_event, *next; + int i; + + for (i = 0; i < g_evt_num_udn_types; ++i) { + output_event = g_evt_udn_info[i]->free_list; + while (output_event) { + next = output_event->next; + tfree(output_event->value); + tfree(output_event); + output_event = next; + } + } +} /* diff --git a/src/xspice/icm/xtraevt/int/udnfunc.c b/src/xspice/icm/xtraevt/int/udnfunc.c index 8a279f519..4c568d74f 100644 --- a/src/xspice/icm/xtraevt/int/udnfunc.c +++ b/src/xspice/icm/xtraevt/int/udnfunc.c @@ -182,6 +182,7 @@ Evt_Udn_Info_t udn_int_info = { "int", "integer valued data", + NULL, udn_int_create, udn_int_dismantle, diff --git a/src/xspice/icm/xtraevt/real/udnfunc.c b/src/xspice/icm/xtraevt/real/udnfunc.c index baacfad97..c0ba212dd 100644 --- a/src/xspice/icm/xtraevt/real/udnfunc.c +++ b/src/xspice/icm/xtraevt/real/udnfunc.c @@ -183,6 +183,7 @@ Evt_Udn_Info_t udn_real_info = { "real", "real valued data", + NULL, udn_real_create, udn_real_dismantle, diff --git a/src/xspice/idn/idndig.c b/src/xspice/idn/idndig.c index 25870229b..53c21dbad 100644 --- a/src/xspice/idn/idndig.c +++ b/src/xspice/idn/idndig.c @@ -345,6 +345,7 @@ Evt_Udn_Info_t idn_digital_info = { "d", "12 state digital data", +NULL, idn_digital_create, idn_digital_dismantle, idn_digital_initialize, From 2643e3b17f98e8d869d6873a99c22f654ddc9678 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Sat, 25 Feb 2023 09:18:17 +0000 Subject: [PATCH 64/91] New code-model library functions cm_schedule_output() and cm_getvar(). To be used in the inertial delay code for digital code models. --- src/include/ngspice/cmproto.h | 4 +++ src/include/ngspice/dllitf.h | 3 +++ src/xspice/cm/cmexport.c | 4 +++ src/xspice/evt/evtload.c | 47 ++++++++++++++++++++++++++++++++++- src/xspice/icm/dlmain.c | 13 ++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/include/ngspice/cmproto.h b/src/include/ngspice/cmproto.h index 0a117f561..aa987d584 100644 --- a/src/include/ngspice/cmproto.h +++ b/src/include/ngspice/cmproto.h @@ -98,6 +98,10 @@ double cm_netlist_get_l(void); const char *cm_get_node_name(const char *, unsigned int); bool cm_probe_node(unsigned int, unsigned int, void *); +bool cm_schedule_output(unsigned int, unsigned int, double, void *); + +enum cp_types; +bool cm_getvar(char *, enum cp_types, void *, size_t); Complex_t cm_complex_set(double real, double imag); Complex_t cm_complex_add(Complex_t x, Complex_t y); diff --git a/src/include/ngspice/dllitf.h b/src/include/ngspice/dllitf.h index 736111af8..702c46abf 100644 --- a/src/include/ngspice/dllitf.h +++ b/src/include/ngspice/dllitf.h @@ -61,6 +61,9 @@ struct coreInfo_t { const char * ((*dllitf_cm_get_node_name)(const char *, unsigned int)); bool ((*dllitf_cm_probe_node)(unsigned int, unsigned int, void *)); + bool ((*dllitf_cm_schedule_output)(unsigned int, unsigned int, + double, void *)); + bool ((*dllitf_cm_getvar)(char *, enum cp_types, void *, size_t)); Complex_t ((*dllitf_cm_complex_set)(double, double)); Complex_t ((*dllitf_cm_complex_add)(Complex_t, Complex_t)); Complex_t ((*dllitf_cm_complex_subtract)(Complex_t, Complex_t)); diff --git a/src/xspice/cm/cmexport.c b/src/xspice/cm/cmexport.c index e0a98849d..f34b2179a 100644 --- a/src/xspice/cm/cmexport.c +++ b/src/xspice/cm/cmexport.c @@ -3,6 +3,8 @@ #include "ngspice/cm.h" #include "ngspice/dllitf.h" +extern bool cp_getvar(char *, enum cp_types, void *, size_t); + /*how annoying!, needed for structure below*/ static void *tcalloc(size_t a, size_t b) { return tmalloc(a*b); /* FIXME, tcalloc must zero !?!? */ @@ -60,6 +62,8 @@ struct coreInfo_t coreInfo = cm_netlist_get_l, cm_get_node_name, cm_probe_node, + cm_schedule_output, + cp_getvar, cm_complex_set, cm_complex_add, cm_complex_subtract, diff --git a/src/xspice/evt/evtload.c b/src/xspice/evt/evtload.c index 557eea16d..a2603e818 100644 --- a/src/xspice/evt/evtload.c +++ b/src/xspice/evt/evtload.c @@ -50,6 +50,7 @@ NON-STANDARD FEATURES #include "ngspice/mifproto.h" #include "ngspice/evtproto.h" +#include "ngspice/cmproto.h" static void EVTcreate_state( @@ -127,7 +128,6 @@ int EVTload( cm_data.circuit.call_type = MIF_EVENT_DRIVEN; cm_data.circuit.temperature = ckt->CKTtemp - 273.15; - /* Setup data needed by cm_... functions */ g_mif_info.ckt = ckt; @@ -456,6 +456,51 @@ static void EVTadd_msg( } +/* This is a code-model library function. Placed here to use local + * static functions. + */ + +bool cm_schedule_output(unsigned int conn_index, unsigned int port_index, + double delay, void *vp) +{ + MIFinstance *instance; + Mif_Conn_Data_t *conn; + Mif_Port_Data_t *port; + Evt_Node_Info_t *node_info; + Evt_Output_Event_t *output_event; + int udn_index; + + if (delay < 0 || g_mif_info.circuit.anal_type != MIF_TRAN) + return FALSE; + instance = g_mif_info.instance; + if (conn_index >= (unsigned int)instance->num_conn) + return FALSE; + conn = instance->conn[conn_index]; + if (port_index >= (unsigned int)conn->size) + return FALSE; + port = conn->port[port_index]; + if (port->type != MIF_DIGITAL && port->type != MIF_USER_DEFINED) + return FALSE; + + /* Get an output structure and copy the new value. */ + + output_event = EVTget_output_event(g_mif_info.ckt, port); + node_info = + g_mif_info.ckt->evt->info.node_table[port->evt_data.node_index]; + udn_index = node_info->udn_index; + g_evt_udn_info[node_info->udn_index]->copy(vp, output_event->value); + + /* Queue the output. */ + + if (port->invert) + g_evt_udn_info[udn_index]->invert(output_event->value); + EVTqueue_output(g_mif_info.ckt, port->evt_data.output_index, + udn_index, output_event, + g_mif_info.circuit.evt_step, + g_mif_info.circuit.evt_step + delay); + return TRUE; +} + /* EVTprocess_output diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index a62713fcd..339201109 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -13,6 +13,7 @@ #include #include +#include "ngspice/cpextern.h" #include "ngspice/devdefs.h" #include "ngspice/dstring.h" #include "ngspice/dllitf.h" @@ -348,6 +349,18 @@ bool cm_probe_node(unsigned int conn_index, return coreitf->dllitf_cm_probe_node(conn_index, port_index, value); } +bool cm_schedule_output(unsigned int conn_index, unsigned int port_index, + double delay, void *vp) +{ + return (coreitf->dllitf_cm_schedule_output)(conn_index, port_index, + delay, vp); +} + +bool cm_getvar(char *name, enum cp_types type, void *retval, size_t rsize) +{ + return (coreitf->dllitf_cm_getvar)(name, type, retval, rsize); +} + Complex_t cm_complex_set(double real, double imag) { return (coreitf->dllitf_cm_complex_set)(real,imag); } From e3b4df6a517c6a1d0776eac64a8ed935e891e030 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Fri, 10 Mar 2023 19:12:01 +0000 Subject: [PATCH 65/91] First group of digital code models with improved implementation of inertial delay: buffer, inverter, and, nor. Also adds utility function cm_is_inertial((). --- src/xspice/icm/digital/d_and/cfunc.mod | 180 +++++++++---------- src/xspice/icm/digital/d_and/ifspec.ifs | 36 ++-- src/xspice/icm/digital/d_buffer/cfunc.mod | 139 +++++++------- src/xspice/icm/digital/d_buffer/ifspec.ifs | 31 +++- src/xspice/icm/digital/d_inverter/cfunc.mod | 178 +++++++++--------- src/xspice/icm/digital/d_inverter/ifspec.ifs | 19 ++ src/xspice/icm/digital/d_nor/cfunc.mod | 175 +++++++++--------- src/xspice/icm/digital/d_nor/ifspec.ifs | 36 ++-- src/xspice/icm/dlmain.c | 22 +++ 9 files changed, 426 insertions(+), 390 deletions(-) diff --git a/src/xspice/icm/digital/d_and/cfunc.mod b/src/xspice/icm/digital/d_and/cfunc.mod index 8945fef48..7ba465417 100644 --- a/src/xspice/icm/digital/d_and/cfunc.mod +++ b/src/xspice/icm/digital/d_and/cfunc.mod @@ -14,31 +14,25 @@ AUTHORS 14 June 1991 Jeffrey P. Murray - MODIFICATIONS 27 Sept 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_and code model. - INTERFACES FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -53,29 +47,16 @@ NON-STANDARD FEATURES #include #include - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - - /*=== MACROS ===========================*/ - - - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - - /*============================================================================== FUNCTION cm_d_and() @@ -94,13 +75,13 @@ SUMMARY INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES @@ -123,124 +104,123 @@ NON-STANDARD FEATURES * Created 6/14/91 J.P.Murray * ************************************************/ - void cm_d_and(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - + size; /* number of input & output ports */ - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ + Digital_State_t val, /* Output value. */ + *out, /* temporary output for buffers */ input; /* temp storage for input bits */ - /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ if(INIT) { /* initial pass */ - /* allocate storage for the outputs */ + cm_event_alloc(0,sizeof(Digital_State_t)); - - /* set loading for inputs */ + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + for (i=0; iwhen <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - } diff --git a/src/xspice/icm/digital/d_and/ifspec.ifs b/src/xspice/icm/digital/d_and/ifspec.ifs index feaa22c93..1480107e5 100644 --- a/src/xspice/icm/digital/d_and/ifspec.ifs +++ b/src/xspice/icm/digital/d_and/ifspec.ifs @@ -33,8 +33,8 @@ Description: "input" "output" Direction: in out Default_Type: d d Allowed_Types: [d] [d] -Vector: yes no -Vector_Bounds: [2 -] - +Vector: yes no +Vector_Bounds: [2 -] - Null_Allowed: no no @@ -52,12 +52,28 @@ Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_buffer/cfunc.mod b/src/xspice/icm/digital/d_buffer/cfunc.mod index a34196cde..92a6e6734 100644 --- a/src/xspice/icm/digital/d_buffer/cfunc.mod +++ b/src/xspice/icm/digital/d_buffer/cfunc.mod @@ -9,36 +9,29 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - AUTHORS 14 June 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 27 Sept 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_buffer code model. - INTERFACES FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,39 +41,25 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - - /*=== MACROS ===========================*/ - - - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - - /*============================================================================== FUNCTION cm_d_buffer() -AUTHORS +AUTHORS 14 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 27 Sep 1991 Jeffrey P. Murray @@ -88,7 +67,7 @@ SUMMARY This function implements the d_buffer code model. -INTERFACES +INTERFACES FILE ROUTINE CALLED @@ -96,7 +75,7 @@ INTERFACES void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES @@ -119,78 +98,94 @@ NON-STANDARD FEATURES * Created 6/14/91 J.P,Murray * ************************************************/ - -void cm_d_buffer(ARGS) +void cm_d_buffer(ARGS) { - /*int i;*/ /* generic loop counter index */ - - - - Digital_State_t *out, /* temporary output for buffers */ - *out_old; /* previous output for buffers */ - + Digital_State_t val, /* Output value. */ + *out; /* Previous value */ /** Setup required state variables **/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ cm_event_alloc(0,sizeof(Digital_State_t)); + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + /* define input loading... */ LOAD(in) = PARAM(input_load); - + } else { /* Retrieve previous values */ /* retrieve storage for the outputs */ - out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0); - } - else { /* Retrieve previous values */ - - /* retrieve storage for the outputs */ out = (Digital_State_t *) cm_event_get_ptr(0,0); - out_old = (Digital_State_t *) cm_event_get_ptr(0,1); } - - /** Check on analysis type **/ + val = INPUT_STATE(in); + if (val == *out) { + /* output value not changing */ - if (ANALYSIS == DC) { /* DC analysis...output w/o delays */ - - OUTPUT_STATE(out) = *out = INPUT_STATE(in); + OUTPUT_CHANGED(out) = FALSE; + } else { + switch (val) { - } - else { /* Transient Analysis */ - - switch ( INPUT_STATE(in) ) { - /* fall to zero value */ - case 0: OUTPUT_STATE(out) = *out = ZERO; - OUTPUT_DELAY(out) = PARAM(fall_delay); + case 0: OUTPUT_DELAY(out) = PARAM(fall_delay); break; /* rise to one value */ - case 1: OUTPUT_STATE(out) = *out = ONE; - OUTPUT_DELAY(out) = PARAM(rise_delay); + case 1: OUTPUT_DELAY(out) = PARAM(rise_delay); break; - + /* unknown output */ default: - OUTPUT_STATE(out) = *out = UNKNOWN; - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ + if (0 == *out) /* add rising delay */ OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ + else /* add falling delay */ OUTPUT_DELAY(out) = PARAM(fall_delay); - } break; } + + if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) { + struct idata *idp; + + idp = (struct idata *)cm_event_get_ptr(1, 0); + if (idp->when <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; + } + } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; -} - - - +} diff --git a/src/xspice/icm/digital/d_buffer/ifspec.ifs b/src/xspice/icm/digital/d_buffer/ifspec.ifs index 4aa5dee61..eb9ac2224 100644 --- a/src/xspice/icm/digital/d_buffer/ifspec.ifs +++ b/src/xspice/icm/digital/d_buffer/ifspec.ifs @@ -48,15 +48,30 @@ Vector: no no Vector_Bounds: - - Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_inverter/cfunc.mod b/src/xspice/icm/digital/d_inverter/cfunc.mod index 19d38e95a..ea7856d8c 100644 --- a/src/xspice/icm/digital/d_inverter/cfunc.mod +++ b/src/xspice/icm/digital/d_inverter/cfunc.mod @@ -8,36 +8,31 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 14 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 30 Sep 1991 Jeffrey P. Murray - - + a SUMMARY This file contains the functional description of the code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -52,38 +47,25 @@ NON-STANDARD FEATURES #include #include - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - - /*=== MACROS ===========================*/ - - - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - - /*============================================================================== FUNCTION cm_d_inverter() -AUTHORS +AUTHORS 14 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 30 Sep 1991 Jeffrey P. Murray @@ -91,13 +73,12 @@ SUMMARY This function implements the d_inverter code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - RETURNED VALUE Returns inputs and outputs via ARGS structure. @@ -122,92 +103,99 @@ NON-STANDARD FEATURES * Created 6/14/91 J.P.Murray * ************************************************/ - void cm_d_inverter(ARGS) - { - /*int i;*/ /* generic loop counter index */ - - - - Digital_State_t *out, /* temporary output for inverter */ - *out_old; /* previous output for inverter */ - + Digital_State_t val, /* Output value. */ + *out; /* Previous output. */ /** Setup required state variables **/ if(INIT) { /* initial pass */ + /* allocate storage for the output */ - /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. /* define load value on inputs */ LOAD(in) = PARAM(input_load); - - /* retrieve storage for the outputs */ - out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0); - - } - else { /* Retrieve previous values */ - + } else { /* Retrieve previous values */ /* retrieve storage for the outputs */ out = (Digital_State_t *) cm_event_get_ptr(0,0); - out_old = (Digital_State_t *) cm_event_get_ptr(0,1); } - - /** Check on analysis type **/ + val = INPUT_STATE(in); + if (val != UNKNOWN) + val = !val; - if (ANALYSIS == DC) { /* DC analysis...output w/o delays */ - - switch ( INPUT_STATE(in) ) { + /*** Check for change and output appropriate values ***/ - case ZERO: - OUTPUT_STATE(out) = *out = *out_old = ONE; + if (val == *out) { /* output value is changing */ + OUTPUT_CHANGED(out) = FALSE; + } else { /* output value not changing */ + switch (val) { + + /* fall to zero value */ + case 0: + OUTPUT_DELAY(out) = PARAM(fall_delay); break; - case ONE: - OUTPUT_STATE(out) = *out = *out_old = ZERO; + /* rise to one value */ + case 1: + OUTPUT_DELAY(out) = PARAM(rise_delay); break; - + + /* unknown output */ default: - OUTPUT_STATE(out) = *out = *out_old = UNKNOWN; - break; - } - - } - else { /* Transient Analysis */ - - switch ( INPUT_STATE(in) ) { - - /* fall to zero value */ - case 1: OUTPUT_STATE(out) = *out = ZERO; - OUTPUT_DELAY(out) = PARAM(fall_delay); - break; - - /* rise to one value */ - case 0: OUTPUT_STATE(out) = *out = ONE; + /* based on old value, add rise or fall delay */ + if (0 == *out) { /* add rising delay */ OUTPUT_DELAY(out) = PARAM(rise_delay); - break; - - /* unknown output */ - default: - OUTPUT_STATE(out) = *out = UNKNOWN; - - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ - OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ - OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + } else { /* add falling delay */ + OUTPUT_DELAY(out) = PARAM(fall_delay); + } + break; } + + if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) { + struct idata *idp; + + idp = (struct idata *)cm_event_get_ptr(1, 0); + if (idp->when <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; + } + } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; -} - - - - +} diff --git a/src/xspice/icm/digital/d_inverter/ifspec.ifs b/src/xspice/icm/digital/d_inverter/ifspec.ifs index 3d0f9479a..f544695a3 100644 --- a/src/xspice/icm/digital/d_inverter/ifspec.ifs +++ b/src/xspice/icm/digital/d_inverter/ifspec.ifs @@ -50,6 +50,18 @@ Vector_Bounds: - - Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: inertial_delay family +Description: "swallow short pulses" "Logic family for bridging" +Data_Type: boolean string +Default_Value: false - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + PARAMETER_TABLE: Parameter_Name: input_load @@ -61,3 +73,10 @@ Vector: no Vector_Bounds: - Null_Allowed: yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" + diff --git a/src/xspice/icm/digital/d_nor/cfunc.mod b/src/xspice/icm/digital/d_nor/cfunc.mod index 46569eafe..883ef90d7 100644 --- a/src/xspice/icm/digital/d_nor/cfunc.mod +++ b/src/xspice/icm/digital/d_nor/cfunc.mod @@ -48,29 +48,20 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - /*============================================================================== FUNCTION cm_d_nor() @@ -119,126 +110,120 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - void cm_d_nor(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - + size; /* number of input & output ports */ - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ + Digital_State_t val, /* Output value. */ + *out, /* temporary output for buffers */ input; /* temp storage for input bits */ /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ - if(INIT) { /* initial pass */ - + if (INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. for (i=0; iwhen <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - -} - - - - - +} diff --git a/src/xspice/icm/digital/d_nor/ifspec.ifs b/src/xspice/icm/digital/d_nor/ifspec.ifs index 316a13638..ccd40b5a3 100644 --- a/src/xspice/icm/digital/d_nor/ifspec.ifs +++ b/src/xspice/icm/digital/d_nor/ifspec.ifs @@ -33,8 +33,8 @@ Description: "input" "output" Direction: in out Default_Type: d d Allowed_Types: [d] [d] -Vector: yes no -Vector_Bounds: [2 -] - +Vector: yes no +Vector_Bounds: [2 -] - Null_Allowed: no no @@ -52,12 +52,28 @@ Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (pF)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index 339201109..02fffe706 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -19,6 +19,7 @@ #include "ngspice/dllitf.h" #include "ngspice/evtudn.h" #include "ngspice/inpdefs.h" +#include "ngspice/inertial.h" #include "cmextrn.h" #include "udnextrn.h" @@ -547,3 +548,24 @@ cm_message_printf(const char *fmt, ...) txfree(p); return rv; } + +/* Function used for inertial delay in digital logic models. */ + +Mif_Boolean_t cm_is_inertial(enum param_vals param) +{ + int cvar; + + /* Get the value of the control variable. */ + + if (cm_getvar("digital_delay_type", CP_NUM, &cvar, sizeof cvar)) { + if (cvar >= OVERRIDE_TRANSPORT) { + /* Parameter override. */ + + return cvar > OVERRIDE_TRANSPORT; + } + if (param == Not_set) // Not specified + return cvar != DEFAULT_TRANSPORT; + return param != Off; + } + return param == On; +} From 4623a0461584bcffbc7052820e1da45b78b1b09e Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Sun, 12 Mar 2023 13:13:58 +0000 Subject: [PATCH 66/91] Interim version of inertial delay for tristate buffer. This does not handle three-way or mixed transitions. --- src/xspice/icm/digital/d_tristate/cfunc.mod | 148 ++++++++++++------- src/xspice/icm/digital/d_tristate/ifspec.ifs | 39 +++-- 2 files changed, 118 insertions(+), 69 deletions(-) diff --git a/src/xspice/icm/digital/d_tristate/cfunc.mod b/src/xspice/icm/digital/d_tristate/cfunc.mod index 74be5e56f..ac9cb086b 100644 --- a/src/xspice/icm/digital/d_tristate/cfunc.mod +++ b/src/xspice/icm/digital/d_tristate/cfunc.mod @@ -8,37 +8,30 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 18 Nov 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 26 Nov 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_tristate code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,39 +41,30 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - /*============================================================================== FUNCTION cm_d_tristate() -AUTHORS +AUTHORS 18 Nov 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 26 Nov 1991 Jeffrey P. Murray @@ -88,9 +72,9 @@ SUMMARY This function implements the d_tristate code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() @@ -100,7 +84,7 @@ RETURNED VALUE Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES @@ -123,43 +107,101 @@ NON-STANDARD FEATURES * Last Modified 11/26/91 * ************************************************/ - void cm_d_tristate(ARGS) { - int enable; /* holding variable for enable input */ + Digital_t *out; + Digital_State_t val, enable; + Digital_Strength_t str; + struct idata *idp; + if (INIT) { /* initial pass */ + /* define input loading... */ + LOAD(in) = PARAM(input_load); + LOAD(enable) = PARAM(enable_load); + OUTPUT_DELAY(out) = PARAM(delay); + /* allocate storage for the previous output. */ + + cm_event_alloc(0, sizeof (Digital_t)); + out = (Digital_t *)cm_event_get_ptr(0, 0); + out->state = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, 2 * sizeof (struct idata)); + idp = (struct idata *)cm_event_get_ptr(1, 0); + idp[1].when = idp[0].when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_t *)cm_event_get_ptr(0, 0); + out->state = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + } else { + out = (Digital_t *)cm_event_get_ptr(0, 0); + } /* Retrieve input values and static variables */ + + val = INPUT_STATE(in); + enable = INPUT_STATE(enable); - - OUTPUT_STATE(out) = INPUT_STATE(in); - OUTPUT_DELAY(out) = PARAM(delay); - - - /* define input loading... */ - LOAD(in) = PARAM(input_load); - LOAD(enable) = PARAM(enable_load); - - - - if (ZERO == enable) { - - OUTPUT_STRENGTH(out) = HI_IMPEDANCE; - + str = HI_IMPEDANCE; + } else if (UNKNOWN == enable) { + str = UNDETERMINED; + } else { + str = STRONG; } - else - if (UNKNOWN == enable) { - OUTPUT_STRENGTH(out) = UNDETERMINED; + if (val == out->state && str == out->strength) { + OUTPUT_CHANGED(out) = FALSE; + } else { + if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) { + int d_cancel, s_cancel; - } - else { - - OUTPUT_STRENGTH(out) = STRONG; + idp = (struct idata *)cm_event_get_ptr(1, 0); + d_cancel = (idp[0].when > TIME && val == idp[0].prev); + s_cancel = (idp[1].when > TIME && + str == (Digital_Strength_t)idp[1].prev); + if ((d_cancel && s_cancel) || + (d_cancel && str == out->strength && TIME >= idp[1].when) || + (s_cancel && val == out->state && TIME >= idp[0].when)) { + double when; + /* Changing back: override pending change. */ + + when = d_cancel ? idp[0].when : idp[1].when; + if (s_cancel && when > idp[1].when) + when = idp[1].when; + + OUTPUT_DELAY(out) = (when - TIME) / 2.0; // Override + idp[1].when = idp[0].when = -1.0; + } else { + /* Normal transition, or third value during delay, + * or needs cancel followed by restore of + * the other component (fudge). + */ + + OUTPUT_DELAY(out) = PARAM(delay); + if (val != out->state) { + idp[0].prev = out->state; + idp[0].when = TIME + OUTPUT_DELAY(out); + } + if (str != out->strength) { + idp[1].prev = (Digital_State_t)out->strength; + idp[1].when = TIME + OUTPUT_DELAY(out); + } + } + } + out->state = val; + out->strength = str; + *(Digital_t *)OUTPUT(out) = *out; } } - - diff --git a/src/xspice/icm/digital/d_tristate/ifspec.ifs b/src/xspice/icm/digital/d_tristate/ifspec.ifs index fc68e337a..20fe5eef9 100644 --- a/src/xspice/icm/digital/d_tristate/ifspec.ifs +++ b/src/xspice/icm/digital/d_tristate/ifspec.ifs @@ -52,26 +52,33 @@ Null_Allowed: yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load enable_load +Description: "input load value (F)" "enable load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: enable_load -Description: "enable load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes + +Parameter_Name: inertial_delay family +Description: "swallow short pulses" "Logic family for bridging" +Data_Type: boolean string +Default_Value: false - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" From 240a2b9406ea0e320bdf60f171df665b915daf7f Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Mon, 13 Mar 2023 13:57:16 +0000 Subject: [PATCH 67/91] Add missed file inertial.h. --- src/include/ngspice/inertial.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/include/ngspice/inertial.h diff --git a/src/include/ngspice/inertial.h b/src/include/ngspice/inertial.h new file mode 100644 index 000000000..1fb526155 --- /dev/null +++ b/src/include/ngspice/inertial.h @@ -0,0 +1,22 @@ +/* Definitions for inertial transport for XSPICE digital models. */ + +/* Determine whether inertial transport should be used. */ + +/* Values for control variable, "digital_delay_type". */ + +#define DEFAULT_TRANSPORT 0 +#define DEFAULT_INERTIAL 1 +#define OVERRIDE_TRANSPORT 2 +#define OVERRIDE_INERTIAL 3 + +enum param_vals {Off, On, Not_set}; +Mif_Boolean_t cm_is_inertial(enum param_vals param); + +/* Extra state data for inertial delays, one structure per output. */ + +struct idata { + double when; + Digital_State_t prev; +}; + + From db38d4ad54b99c3b27bd90eaea8d72bcf6a1d141 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 14 Mar 2023 10:30:11 +0000 Subject: [PATCH 68/91] Correct timing of transitions to UNKNOWN. --- src/xspice/icm/digital/d_and/cfunc.mod | 10 +++++++++- src/xspice/icm/digital/d_buffer/cfunc.mod | 8 ++++++++ src/xspice/icm/digital/d_inverter/cfunc.mod | 10 +++++++++- src/xspice/icm/digital/d_nor/cfunc.mod | 10 +++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/xspice/icm/digital/d_and/cfunc.mod b/src/xspice/icm/digital/d_and/cfunc.mod index 7ba465417..921b273f8 100644 --- a/src/xspice/icm/digital/d_and/cfunc.mod +++ b/src/xspice/icm/digital/d_and/cfunc.mod @@ -168,7 +168,7 @@ void cm_d_and(ARGS) if (val == *out) { /* output value is not changing */ OUTPUT_CHANGED(out) = FALSE; - } else { /* output value not changing */ + } else { switch (val) { /* fall to zero value */ @@ -209,6 +209,14 @@ void cm_d_and(ARGS) /* Third value: cancel earlier change and output as usual. */ cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(rise_delay); + else + OUTPUT_DELAY(out) = PARAM(fall_delay); + } idp->when = TIME + OUTPUT_DELAY(out); // Actual output time } else { /* Changing back: override pending change. */ diff --git a/src/xspice/icm/digital/d_buffer/cfunc.mod b/src/xspice/icm/digital/d_buffer/cfunc.mod index 92a6e6734..1ee0f75cc 100644 --- a/src/xspice/icm/digital/d_buffer/cfunc.mod +++ b/src/xspice/icm/digital/d_buffer/cfunc.mod @@ -176,6 +176,14 @@ void cm_d_buffer(ARGS) /* Third value: cancel earlier change and output as usual. */ cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(rise_delay); + else + OUTPUT_DELAY(out) = PARAM(fall_delay); + } idp->when = TIME + OUTPUT_DELAY(out); // Actual output time } else { /* Changing back: override pending change. */ diff --git a/src/xspice/icm/digital/d_inverter/cfunc.mod b/src/xspice/icm/digital/d_inverter/cfunc.mod index ea7856d8c..cb76cf874 100644 --- a/src/xspice/icm/digital/d_inverter/cfunc.mod +++ b/src/xspice/icm/digital/d_inverter/cfunc.mod @@ -147,7 +147,7 @@ void cm_d_inverter(ARGS) if (val == *out) { /* output value is changing */ OUTPUT_CHANGED(out) = FALSE; - } else { /* output value not changing */ + } else { switch (val) { /* fall to zero value */ @@ -186,6 +186,14 @@ void cm_d_inverter(ARGS) /* Third value: cancel earlier change and output as usual. */ cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(rise_delay); + else + OUTPUT_DELAY(out) = PARAM(fall_delay); + } idp->when = TIME + OUTPUT_DELAY(out); // Actual output time } else { /* Changing back: override pending change. */ diff --git a/src/xspice/icm/digital/d_nor/cfunc.mod b/src/xspice/icm/digital/d_nor/cfunc.mod index 883ef90d7..85e5561c7 100644 --- a/src/xspice/icm/digital/d_nor/cfunc.mod +++ b/src/xspice/icm/digital/d_nor/cfunc.mod @@ -175,7 +175,7 @@ void cm_d_nor(ARGS) if (val == *out) { /* output value is not changing */ OUTPUT_CHANGED(out) = FALSE; - } else { /* output value not changing */ + } else { switch (val) { /* fall to zero value */ @@ -214,6 +214,14 @@ void cm_d_nor(ARGS) /* Third value: cancel earlier change and output as usual. */ cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(rise_delay); + else + OUTPUT_DELAY(out) = PARAM(fall_delay); + } idp->when = TIME + OUTPUT_DELAY(out); // Actual output time } else { /* Changing back: override pending change. */ From cecce5163ed2fb19c2343ca1501d82b2dd05577b Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 14 Mar 2023 21:41:10 +0000 Subject: [PATCH 69/91] Inertial delay for remaining simple gates and buffers: nand or xor open_c open_e, but not tristate. --- src/xspice/icm/digital/d_nand/cfunc.mod | 218 +++++++++--------- src/xspice/icm/digital/d_nand/ifspec.ifs | 52 +++-- src/xspice/icm/digital/d_open_c/cfunc.mod | 220 +++++++++--------- src/xspice/icm/digital/d_open_c/ifspec.ifs | 56 +++-- src/xspice/icm/digital/d_open_e/cfunc.mod | 220 +++++++++--------- src/xspice/icm/digital/d_open_e/ifspec.ifs | 56 +++-- src/xspice/icm/digital/d_or/cfunc.mod | 215 +++++++++--------- src/xspice/icm/digital/d_or/ifspec.ifs | 51 +++-- src/xspice/icm/digital/d_xor/cfunc.mod | 248 ++++++++++----------- src/xspice/icm/digital/d_xor/ifspec.ifs | 48 ++-- 10 files changed, 726 insertions(+), 658 deletions(-) diff --git a/src/xspice/icm/digital/d_nand/cfunc.mod b/src/xspice/icm/digital/d_nand/cfunc.mod index 5e277f6b4..e5a260a77 100644 --- a/src/xspice/icm/digital/d_nand/cfunc.mod +++ b/src/xspice/icm/digital/d_nand/cfunc.mod @@ -8,37 +8,31 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS + +AUTHORS 18 June 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 30 Sept 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_nand code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,38 +42,29 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - /*============================================================================== FUNCTION cm_d_nand() -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 30 Sep 1991 Jeffrey P. Murray @@ -87,19 +72,19 @@ SUMMARY This function implements the d_nand code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES @@ -118,128 +103,125 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - -void cm_d_nand(ARGS) - +void cm_d_nand(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - - - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ - input; /* temp storage for input bits */ + size; /* number of input & output ports */ + Digital_State_t val, /* Output value. */ + *out, /* temporary output for buffers */ + input; /* temp storage for input bits */ /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. for (i=0; iwhen <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ + else OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - -} - - - - - - +} diff --git a/src/xspice/icm/digital/d_nand/ifspec.ifs b/src/xspice/icm/digital/d_nand/ifspec.ifs index b4e18059f..6a3bdc2e5 100644 --- a/src/xspice/icm/digital/d_nand/ifspec.ifs +++ b/src/xspice/icm/digital/d_nand/ifspec.ifs @@ -28,14 +28,14 @@ Description: "digital n-input nand gate" PORT_TABLE: -Port_Name: in out -Description: "input" "output" -Direction: in out -Default_Type: d d -Allowed_Types: [d] [d] -Vector: yes no -Vector_Bounds: [2 -] - -Null_Allowed: no no +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: yes no +Vector_Bounds: [2 -] - +Null_Allowed: no no PARAMETER_TABLE: @@ -45,19 +45,35 @@ Description: "rise delay" "fall delay" Data_Type: real real Default_Value: 1.0e-9 1.0e-9 Limits: [1e-12 -] [1e-12 -] -Vector: no no -Vector_Bounds: - - +Vector: no no +Vector_Bounds: - - Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_open_c/cfunc.mod b/src/xspice/icm/digital/d_open_c/cfunc.mod index 8e2af3310..95e1b459c 100644 --- a/src/xspice/icm/digital/d_open_c/cfunc.mod +++ b/src/xspice/icm/digital/d_open_c/cfunc.mod @@ -8,37 +8,31 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS + +AUTHORS 19 Nov 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 19 Nov 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_open_c code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,39 +42,28 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - - /*============================================================================== FUNCTION cm_d_open_c() -AUTHORS +AUTHORS 19 Nov 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 19 Nov 1991 Jeffrey P. Murray @@ -88,19 +71,19 @@ SUMMARY This function implements the d_open_c code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES @@ -109,6 +92,23 @@ NON-STANDARD FEATURES ==============================================================================*/ +/* Find strength for given output. */ + +static Digital_Strength_t strength(Digital_State_t s) +{ + switch (s) { + case ZERO: + return STRONG; + break; + case ONE: + return HI_IMPEDANCE; + break; + default: + return UNDETERMINED; + break; + } +} + /*=== CM_D_OPEN_C ROUTINE ===*/ /************************************************ @@ -119,96 +119,106 @@ NON-STANDARD FEATURES * Created 11/19/91 J.P,Murray * ************************************************/ - -void cm_d_open_c(ARGS) - +void cm_d_open_c(ARGS) { - /*int i;*/ /* generic loop counter index */ - - - - Digital_State_t *out, /* temporary output for buffers */ - *out_old; /* previous output for buffers */ - + Digital_State_t val, + *out; /* temporary output for buffers */ /** Setup required state variables **/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); - /* define input loading... */ + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + LOAD(in) = PARAM(input_load); - - /* retrieve storage for the outputs */ - out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0); - - } - else { /* Retrieve previous values */ - + } else { /* retrieve storage for the outputs */ out = (Digital_State_t *) cm_event_get_ptr(0,0); - out_old = (Digital_State_t *) cm_event_get_ptr(0,1); } - - /** Check on analysis type **/ + /*** Calculate new output value based on inputs ***/ - if (ANALYSIS == DC) { /* DC analysis...output w/o delays */ - - OUTPUT_STATE(out) = *out = INPUT_STATE(in); - if ( ONE == *out ) { - OUTPUT_STRENGTH(out) = HI_IMPEDANCE; - } - else - if ( ZERO == *out ) { - OUTPUT_STRENGTH(out) = STRONG; - } - else { - OUTPUT_STRENGTH(out) = UNDETERMINED; - } - + val = INPUT_STATE(in); - } - else { /* Transient Analysis */ + /*** Check for change and output appropriate values ***/ - switch ( INPUT_STATE(in) ) { - - /* fall to zero value */ - case 0: OUTPUT_STATE(out) = *out = ZERO; - OUTPUT_STRENGTH(out) = STRONG; - OUTPUT_DELAY(out) = PARAM(fall_delay); - break; + if (val == *out) { /* output value is not changing */ + OUTPUT_CHANGED(out) = FALSE; + } else { + switch (val) { - /* rise to one value */ - case 1: OUTPUT_STATE(out) = *out = ONE; - OUTPUT_STRENGTH(out) = HI_IMPEDANCE; - OUTPUT_DELAY(out) = PARAM(open_delay); - break; - - /* unknown output */ + /* fall to zero value */ + case 0: + OUTPUT_DELAY(out) = PARAM(fall_delay); + break; + + /* rise to one value */ + case 1: + OUTPUT_DELAY(out) = PARAM(open_delay); + break; + + /* unknown output */ default: - OUTPUT_STATE(out) = *out = UNKNOWN; - OUTPUT_STRENGTH(out) = UNDETERMINED; - - - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ - OUTPUT_DELAY(out) = PARAM(open_delay); - } - else { /* add falling delay */ - OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + /* based on old value, add rise or fall delay */ + if (0 == *out) { /* add rising delay */ + OUTPUT_DELAY(out) = PARAM(open_delay); + } else { /* add falling delay */ + OUTPUT_DELAY(out) = PARAM(fall_delay); + } + break; } + + if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) { + struct idata *idp; + + idp = (struct idata *)cm_event_get_ptr(1, 0); + if (idp->when <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, strength(idp->prev)}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(open_delay); + else + OUTPUT_DELAY(out) = PARAM(fall_delay); + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; + } + } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = strength(val); } -} - - - - - - - - +} diff --git a/src/xspice/icm/digital/d_open_c/ifspec.ifs b/src/xspice/icm/digital/d_open_c/ifspec.ifs index 55b0b2221..7b73efe43 100644 --- a/src/xspice/icm/digital/d_open_c/ifspec.ifs +++ b/src/xspice/icm/digital/d_open_c/ifspec.ifs @@ -6,14 +6,14 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 -AUTHORS +AUTHORS 19 Nov 1991 Jeffrey P. Murray SUMMARY - This file contains the interface specification file for the + This file contains the interface specification file for the digital d_open_c (open collector) code model. ===============================================================================*/ @@ -32,31 +32,49 @@ Description: "input" "output" Direction: in out Default_Type: d d Allowed_Types: [d] [d] -Vector: no no -Vector_Bounds: - - +Vector: no no +Vector_Bounds: - - Null_Allowed: no no PARAMETER_TABLE: -Parameter_Name: open_delay fall_delay +Parameter_Name: open_delay fall_delay Description: "open delay" "fall delay" -Data_Type: real real -Default_Value: 1.0e-9 1.0e-9 -Limits: [1e-12 -] [1e-12 -] -Vector: no no -Vector_Bounds: - - -Null_Allowed: yes yes +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_open_e/cfunc.mod b/src/xspice/icm/digital/d_open_e/cfunc.mod index 4b786610f..9d6c1563f 100644 --- a/src/xspice/icm/digital/d_open_e/cfunc.mod +++ b/src/xspice/icm/digital/d_open_e/cfunc.mod @@ -8,37 +8,30 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 19 Nov 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 19 Nov 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_open_e code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,39 +41,29 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - /*============================================================================== FUNCTION cm_d_open_e() -AUTHORS +AUTHORS 19 Nov 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 19 Nov 1991 Jeffrey P. Murray @@ -88,19 +71,19 @@ SUMMARY This function implements the d_open_e code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES @@ -109,6 +92,23 @@ NON-STANDARD FEATURES ==============================================================================*/ +/* Find strength for given output. */ + +static Digital_Strength_t strength(Digital_State_t s) +{ + switch (s) { + case ZERO: + return HI_IMPEDANCE; + break; + case ONE: + return STRONG; + break; + default: + return UNDETERMINED; + break; + } +} + /*=== CM_D_OPEN_E ROUTINE ===*/ /************************************************ @@ -120,100 +120,106 @@ NON-STANDARD FEATURES ************************************************/ -void cm_d_open_e(ARGS) +void cm_d_open_e(ARGS) { - /*int i;*/ /* generic loop counter index */ - - - - Digital_State_t *out, /* temporary output for buffers */ - *out_old; /* previous output for buffers */ - + Digital_State_t val, + *out; /* temporary output for buffers */ /** Setup required state variables **/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); - /* define input loading... */ + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. + LOAD(in) = PARAM(input_load); - - /* retrieve storage for the outputs */ - out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0); - - } - else { /* Retrieve previous values */ - + } else { /* retrieve storage for the outputs */ out = (Digital_State_t *) cm_event_get_ptr(0,0); - out_old = (Digital_State_t *) cm_event_get_ptr(0,1); } - - /** Check on analysis type **/ + /*** Calculate new output value based on inputs ***/ - if (ANALYSIS == DC) { /* DC analysis...output w/o delays */ - - OUTPUT_STATE(out) = *out = INPUT_STATE(in); - if ( ONE == *out ) { - OUTPUT_STRENGTH(out) = STRONG; - } - else - if ( ZERO == *out ) { - OUTPUT_STRENGTH(out) = HI_IMPEDANCE; - } - else { - OUTPUT_STRENGTH(out) = UNDETERMINED; - } - + val = INPUT_STATE(in); - } - else { /* Transient Analysis */ + /*** Check for change and output appropriate values ***/ - switch ( INPUT_STATE(in) ) { - - /* fall to zero value */ - case 0: OUTPUT_STATE(out) = *out = ZERO; - OUTPUT_STRENGTH(out) = HI_IMPEDANCE; - OUTPUT_DELAY(out) = PARAM(open_delay); - break; + if (val == *out) { /* output value is not changing */ + OUTPUT_CHANGED(out) = FALSE; + } else { + switch (val) { + /* fall to zero value */ + case 0: + OUTPUT_DELAY(out) = PARAM(open_delay); + break; - /* rise to one value */ - case 1: OUTPUT_STATE(out) = *out = ONE; - OUTPUT_STRENGTH(out) = STRONG; - OUTPUT_DELAY(out) = PARAM(rise_delay); - break; - - /* unknown output */ + /* rise to one value */ + case 1: + OUTPUT_DELAY(out) = PARAM(rise_delay); + break; + + /* unknown output */ default: - OUTPUT_STATE(out) = *out = UNKNOWN; - OUTPUT_STRENGTH(out) = UNDETERMINED; - - - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ - OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ - OUTPUT_DELAY(out) = PARAM(open_delay); - } - break; + /* based on old value, add rise or fall delay */ + if (0 == *out) { /* add rising delay */ + OUTPUT_DELAY(out) = PARAM(rise_delay); + } else { /* add falling delay */ + OUTPUT_DELAY(out) = PARAM(open_delay); + } + break; } + + if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) { + struct idata *idp; + + idp = (struct idata *)cm_event_get_ptr(1, 0); + if (idp->when <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, strength(idp->prev)}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) + OUTPUT_DELAY(out) = PARAM(rise_delay); + else + OUTPUT_DELAY(out) = PARAM(open_delay); + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; + } + } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = strength(val); } -} - - - - - - - - - - - - - +} diff --git a/src/xspice/icm/digital/d_open_e/ifspec.ifs b/src/xspice/icm/digital/d_open_e/ifspec.ifs index 9241fb5f5..e66ea18bf 100644 --- a/src/xspice/icm/digital/d_open_e/ifspec.ifs +++ b/src/xspice/icm/digital/d_open_e/ifspec.ifs @@ -6,14 +6,14 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 -AUTHORS +AUTHORS 19 Nov 1991 Jeffrey P. Murray SUMMARY - This file contains the interface specification file for the + This file contains the interface specification file for the digital d_open_e code model. ===============================================================================*/ @@ -32,31 +32,49 @@ Description: "input" "output" Direction: in out Default_Type: d d Allowed_Types: [d] [d] -Vector: no no -Vector_Bounds: - - +Vector: no no +Vector_Bounds: - - Null_Allowed: no no PARAMETER_TABLE: -Parameter_Name: rise_delay open_delay +Parameter_Name: rise_delay open_delay Description: "rise delay" "open delay" -Data_Type: real real -Default_Value: 1.0e-9 1.0e-9 -Limits: [1e-12 -] [1e-12 -] -Vector: no no -Vector_Bounds: - - -Null_Allowed: yes yes +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_or/cfunc.mod b/src/xspice/icm/digital/d_or/cfunc.mod index 7671862e9..e7bed2dcf 100644 --- a/src/xspice/icm/digital/d_or/cfunc.mod +++ b/src/xspice/icm/digital/d_or/cfunc.mod @@ -8,37 +8,30 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 30 Sep 1991 Jeffrey P. Murray - SUMMARY This file contains the functional description of the d_or code model. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -48,39 +41,29 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - /*============================================================================== FUNCTION cm_d_or() -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 30 Sep 1991 Jeffrey P. Murray @@ -88,19 +71,19 @@ SUMMARY This function implements the d_or code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES @@ -119,126 +102,132 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - -void cm_d_or(ARGS) - +void cm_d_or(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - + size; /* number of input & output ports */ - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ + Digital_State_t val, /* Output value. */ + *out, /* temporary output for buffers */ input; /* temp storage for input bits */ /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ - if(INIT) { /* initial pass */ - + if (INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. for (i=0; iwhen <= TIME) { + /* Normal transition. */ + + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; + + /* Third value: cancel earlier change and output as usual. */ + + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ + + if (idp->prev == ZERO) OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ + else OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - -} - - +} + + diff --git a/src/xspice/icm/digital/d_or/ifspec.ifs b/src/xspice/icm/digital/d_or/ifspec.ifs index f3e2f1af6..1c8e105a8 100644 --- a/src/xspice/icm/digital/d_or/ifspec.ifs +++ b/src/xspice/icm/digital/d_or/ifspec.ifs @@ -6,18 +6,18 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 -AUTHORS +AUTHORS 30 Sept 1991 Jeffrey P. Murray SUMMARY - This file contains the interface specification file for the + This file contains the interface specification file for the digital d_or code model. ===============================================================================*/ - + NAME_TABLE: @@ -40,24 +40,43 @@ Null_Allowed: no no PARAMETER_TABLE: -Parameter_Name: rise_delay fall_delay +Parameter_Name: rise_delay fall_delay Description: "rise delay" "fall delay" -Data_Type: real real -Default_Value: 1.0e-9 1.0e-9 -Limits: [1e-12 -] [1e-12 -] +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] Vector: no no Vector_Bounds: - - -Null_Allowed: yes yes +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_xor/cfunc.mod b/src/xspice/icm/digital/d_xor/cfunc.mod index da04e3a12..b4ad95961 100644 --- a/src/xspice/icm/digital/d_xor/cfunc.mod +++ b/src/xspice/icm/digital/d_xor/cfunc.mod @@ -8,125 +8,109 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 7 Aug 1991 Jeffrey P. Murray 2 Oct 1991 Jeffrey P. Murray - SUMMARY This file contains the model-specific routines used to functionally describe the d_xor code model. +INTERFACES -INTERFACES + FILE ROUTINE CALLED - FILE ROUTINE CALLED + CMutil.c void cm_toggle_bit(); - CMutil.c void cm_toggle_bit(); - CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES NONE - ================================================================================ FUNCTION cm_toggle_bit() - -AUTHORS +AUTHORS 27 Sept 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS NONE - SUMMARY Alters the state of a passed digital variable to its complement. Thus, a ONE changes to a ZERO. A ZERO changes to a ONE, and an UNKNOWN remains unchanged. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED N/A N/A - RETURNED VALUE - - No returned value. Passed pointer to variable is used + + No returned value. Passed pointer to variable is used to redefine the variable value. - GLOBAL VARIABLES - - NONE + NONE NON-STANDARD FEATURES NONE - + ===============================================================================*/ +#include "ngspice/inertial.h" + /*=== CM_TOGGLE_BIT ROUTINE ===*/ -static void cm_toggle_bit(Digital_State_t *bit) - +static void cm_toggle_bit(Digital_State_t *bit) { /* Toggle bit from ONE to ZERO or vice versa, unless the - bit value is UNKNOWN. In the latter case, return + bit value is UNKNOWN. In the latter case, return without changing the bit value. */ if ( UNKNOWN != *bit ) { if ( ONE == *bit ) { *bit = ZERO; } - else { + else { *bit = ONE; } } - } - + /*============================================================================== FUNCTION cm_d_xor() -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray -MODIFICATIONS +MODIFICATIONS 7 Aug 1991 Jeffrey P. Murray 2 Oct 1991 Jeffrey P. Murray @@ -137,30 +121,30 @@ SUMMARY This function implements the d_xor code model. -INTERFACES +INTERFACES - FILE ROUTINE CALLED + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); - CMutil.c void cm_toggle_bit(); - CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() RETURNED VALUE - + Returns inputs and outputs via ARGS structure. - + GLOBAL VARIABLES - + NONE NON-STANDARD FEATURES NONE - + ===============================================================================*/ /*=== CM_D_XOR ROUTINE ===*/ @@ -174,125 +158,135 @@ NON-STANDARD FEATURES ************************************************/ -void cm_d_xor(ARGS) +void cm_d_xor(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - + size; /* number of input & output ports */ - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ - input; /* temp storage for input bits */ + + + Digital_State_t val, + *out, /* temporary output for buffers */ + input; /* temp storage for input bits */ /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. for (i=0; iwhen <= TIME) { + /* Normal transition. */ - /*** Determine analysis type and output appropriate values ***/ + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; - if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/ - - OUTPUT_STATE(out) = *out; + /* Third value: cancel earlier change and output as usual. */ - } + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ - else { /** Transient Analysis **/ - - - if ( *out != *out_old ) { /* output value is changing */ - - switch ( *out ) { - - /* fall to zero value */ - case 0: OUTPUT_STATE(out) = ZERO; - OUTPUT_DELAY(out) = PARAM(fall_delay); - break; - - /* rise to one value */ - case 1: OUTPUT_STATE(out) = ONE; - OUTPUT_DELAY(out) = PARAM(rise_delay); - break; - - /* unknown output */ - default: - OUTPUT_STATE(out) = *out = UNKNOWN; - - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ + if (idp->prev == ZERO) OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ + else OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - -} - - +} + + diff --git a/src/xspice/icm/digital/d_xor/ifspec.ifs b/src/xspice/icm/digital/d_xor/ifspec.ifs index ddd3aa53d..27a83cd8c 100644 --- a/src/xspice/icm/digital/d_xor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xor/ifspec.ifs @@ -6,18 +6,18 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 -AUTHORS +AUTHORS 2 Oct 1991 Jeffrey P. Murray SUMMARY - This file contains the interface specification file for the + This file contains the interface specification file for the digital d_xor code model. ===============================================================================*/ - + NAME_TABLE: @@ -40,24 +40,40 @@ Null_Allowed: no no PARAMETER_TABLE: -Parameter_Name: rise_delay fall_delay +Parameter_Name: rise_delay fall_delay Description: "rise delay" "fall delay" -Data_Type: real real -Default_Value: 1.0e-9 1.0e-9 -Limits: [1e-12 -] [1e-12 -] +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] Vector: no no Vector_Bounds: - - -Null_Allowed: yes yes +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (F)" -Data_Type: real -Default_Value: 1.0e-12 -Limits: - -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" From e25f8bd522a143925eb4785a9264b9d7c8d80b74 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Fri, 17 Mar 2023 15:21:18 +0000 Subject: [PATCH 70/91] Add inertial delay to missed d_xnor and tidy blank lines in d_xor. --- src/xspice/icm/digital/d_xnor/cfunc.mod | 264 ++++++++++------------- src/xspice/icm/digital/d_xnor/ifspec.ifs | 54 +++-- src/xspice/icm/digital/d_xor/cfunc.mod | 7 - 3 files changed, 153 insertions(+), 172 deletions(-) diff --git a/src/xspice/icm/digital/d_xnor/cfunc.mod b/src/xspice/icm/digital/d_xnor/cfunc.mod index 89c584d9b..09a042e1a 100644 --- a/src/xspice/icm/digital/d_xnor/cfunc.mod +++ b/src/xspice/icm/digital/d_xnor/cfunc.mod @@ -8,40 +8,33 @@ Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 - -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 7 Aug 1991 Jeffrey P. Murray 2 Oct 1991 Jeffrey P. Murray - SUMMARY This file contains the model-specific routines used to functionally describe the d_xnor code model. +INTERFACES -INTERFACES + FILE ROUTINE CALLED - FILE ROUTINE CALLED + CMutil.c void cm_toggle_bit(); - CMutil.c void cm_toggle_bit(); - CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - - REFERENCED FILES Inputs from and outputs to ARGS structure. - NON-STANDARD FEATURES @@ -51,142 +44,116 @@ NON-STANDARD FEATURES /*=== INCLUDE FILES ====================*/ - - +#include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ - - /*=== MACROS ===========================*/ - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - /*============================================================================== FUNCTION cm_toggle_bit() - -AUTHORS +AUTHORS 27 Sept 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS NONE - SUMMARY Alters the state of a passed digital variable to its complement. Thus, a ONE changes to a ZERO. A ZERO changes to a ONE, and an UNKNOWN remains unchanged. +INTERFACES -INTERFACES - - FILE ROUTINE CALLED + FILE ROUTINE CALLED N/A N/A - RETURNED VALUE - - No returned value. Passed pointer to variable is used + + No returned value. Passed pointer to variable is used to redefine the variable value. - GLOBAL VARIABLES - - NONE + NONE NON-STANDARD FEATURES NONE - + ===============================================================================*/ /*=== CM_TOGGLE_BIT ROUTINE ===*/ -static void cm_toggle_bit(Digital_State_t *bit) - +static void cm_toggle_bit(Digital_State_t *bit) { /* Toggle bit from ONE to ZERO or vice versa, unless the - bit value is UNKNOWN. In the latter case, return + bit value is UNKNOWN. In the latter case, return without changing the bit value. */ if ( UNKNOWN != *bit ) { if ( ONE == *bit ) { *bit = ZERO; } - else { + else { *bit = ONE; } } - } - + /*============================================================================== FUNCTION cm_d_xnor() - -AUTHORS +AUTHORS 18 Jun 1991 Jeffrey P. Murray - -MODIFICATIONS +MODIFICATIONS 7 Aug 1991 Jeffrey P. Murray 2 Oct 1991 Jeffrey P. Murray - SUMMARY This function implements the d_xnor code model. +INTERFACES -INTERFACES + FILE ROUTINE CALLED - FILE ROUTINE CALLED + CMutil.c void cm_toggle_bit(); - CMutil.c void cm_toggle_bit(); - CMevt.c void *cm_event_alloc() void *cm_event_get_ptr() - RETURNED VALUE - + Returns inputs and outputs via ARGS structure. - GLOBAL VARIABLES - - NONE + NONE NON-STANDARD FEATURES NONE - + ===============================================================================*/ /*=== CM_D_XNOR ROUTINE ===*/ @@ -199,126 +166,129 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - -void cm_d_xnor(ARGS) - +void cm_d_xnor(ARGS) { int i, /* generic loop counter index */ - size; /* number of input & output ports */ - - + size; /* number of input & output ports */ - Digital_State_t *out, /* temporary output for buffers */ - *out_old, /* previous output for buffers */ - input; /* temp storage for input bits */ + + + Digital_State_t val, + *out, /* temporary output for buffers */ + input; /* temp storage for input bits */ /** Retrieve size value... **/ size = PORT_SIZE(in); - - /*** Setup required state variables ***/ - if(INIT) { /* initial pass */ - + if(INIT) { /* initial pass */ /* allocate storage for the outputs */ - cm_event_alloc(0,sizeof(Digital_State_t)); + + cm_event_alloc(0, sizeof (Digital_State_t)); + + /* Inertial delay? */ + + STATIC_VAR(is_inertial) = + cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set : + PARAM(inertial_delay)); + if (STATIC_VAR(is_inertial)) { + /* Allocate storage for event time. */ + + cm_event_alloc(1, sizeof (struct idata)); + ((struct idata *)cm_event_get_ptr(1, 0))->when = -1.0; + } + + /* Prepare initial output. */ + + out = (Digital_State_t *)cm_event_get_ptr(0, 0); + *out = (Digital_State_t)(UNKNOWN + 1); // Force initial output. for (i=0; iwhen <= TIME) { + /* Normal transition. */ - /*** Determine analysis type and output appropriate values ***/ + idp->prev = *out; + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else if (val != idp->prev) { + Digital_t ov = {idp->prev, STRONG}; - if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/ - - OUTPUT_STATE(out) = *out; + /* Third value: cancel earlier change and output as usual. */ - } + cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov); + if (val == UNKNOWN) { + /* Delay based in idp->prev, not *out. */ - else { /** Transient Analysis **/ - - - if ( *out != *out_old ) { /* output value is changing */ - - switch ( *out ) { - - /* fall to zero value */ - case 0: OUTPUT_STATE(out) = ZERO; - OUTPUT_DELAY(out) = PARAM(fall_delay); - break; - - /* rise to one value */ - case 1: OUTPUT_STATE(out) = ONE; - OUTPUT_DELAY(out) = PARAM(rise_delay); - break; - - /* unknown output */ - default: - OUTPUT_STATE(out) = *out = UNKNOWN; - - /* based on old value, add rise or fall delay */ - if (0 == *out_old) { /* add rising delay */ + if (idp->prev == ZERO) OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { /* add falling delay */ + else OUTPUT_DELAY(out) = PARAM(fall_delay); - } - break; + } + idp->when = TIME + OUTPUT_DELAY(out); // Actual output time + } else { + /* Changing back: override pending change. */ + + OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override + idp->when = -1.0; } } - else { /* output value not changing */ - OUTPUT_CHANGED(out) = FALSE; - } + *out = val; + OUTPUT_STATE(out) = val; + OUTPUT_STRENGTH(out) = STRONG; } - - OUTPUT_STRENGTH(out) = STRONG; - -} - - - - - +} diff --git a/src/xspice/icm/digital/d_xnor/ifspec.ifs b/src/xspice/icm/digital/d_xnor/ifspec.ifs index ee858089b..e225f83ab 100644 --- a/src/xspice/icm/digital/d_xnor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xnor/ifspec.ifs @@ -6,18 +6,18 @@ Georgia Tech Research Corporation Atlanta, Georgia 30332 -AUTHORS +AUTHORS 2 Oct 1991 Jeffrey P. Murray SUMMARY - This file contains the interface specification file for the + This file contains the interface specification file for the digital d_xnor code model. ===============================================================================*/ - + NAME_TABLE: @@ -33,31 +33,49 @@ Description: "input" "output" Direction: in out Default_Type: d d Allowed_Types: [d] [d] -Vector: yes no -Vector_Bounds: [2 -] - +Vector: yes no +Vector_Bounds: [2 -] - Null_Allowed: no no PARAMETER_TABLE: -Parameter_Name: rise_delay fall_delay +Parameter_Name: rise_delay fall_delay Description: "rise delay" "fall delay" -Data_Type: real real -Default_Value: 1.0e-9 1.0e-9 -Limits: [1e-12 -] [1e-12 -] +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] Vector: no no Vector_Bounds: - - -Null_Allowed: yes yes +Null_Allowed: yes yes PARAMETER_TABLE: -Parameter_Name: input_load -Description: "input load value (pF)" -Data_Type: real -Default_Value: 1.0 -Limits: [0.0 -] -Vector: no -Vector_Bounds: - -Null_Allowed: yes +Parameter_Name: input_load family +Description: "input load value (F)" "Logic family for bridging" +Data_Type: real string +Default_Value: 1.0e-12 - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: inertial_delay +Description: "swallow short pulses" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: is_inertial +Data_Type: boolean +Description: "using inertial delay" diff --git a/src/xspice/icm/digital/d_xor/cfunc.mod b/src/xspice/icm/digital/d_xor/cfunc.mod index b4ad95961..8e83a9a18 100644 --- a/src/xspice/icm/digital/d_xor/cfunc.mod +++ b/src/xspice/icm/digital/d_xor/cfunc.mod @@ -157,9 +157,7 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - void cm_d_xor(ARGS) - { int i, /* generic loop counter index */ size; /* number of input & output ports */ @@ -285,8 +283,3 @@ void cm_d_xor(ARGS) OUTPUT_STRENGTH(out) = STRONG; } } - - - - - From 2a647f8462c8a9b6e31f41365dda412819aa99dd Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 09:46:58 +0100 Subject: [PATCH 71/91] Set default VDMOS model parameters to resemble IRF540, 9540 --- src/spicelib/devices/vdmos/vdmosset.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/spicelib/devices/vdmos/vdmosset.c b/src/spicelib/devices/vdmos/vdmosset.c index 6d7661d11..f0c383ce6 100644 --- a/src/spicelib/devices/vdmos/vdmosset.c +++ b/src/spicelib/devices/vdmos/vdmosset.c @@ -32,10 +32,10 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, model->VDMOStype = NMOS; if (!model->VDMOStransconductanceGiven) - model->VDMOStransconductance = 1; + model->VDMOStransconductance = 25 + 10 * model->VDMOStype; /* IRF540, 9540 */ if (!model->VDMOSvth0Given) - model->VDMOSvth0 = 0; + model->VDMOSvth0 = 3 * model->VDMOStype; /* IRF540, 9540 */ if (!model->VDIOjctSatCurGiven) model->VDIOjctSatCur = 1e-14; @@ -68,13 +68,13 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, model->VDMOSfNexp = 1; if (!model->VDMOScgdminGiven) - model->VDMOScgdmin = 0; + model->VDMOScgdmin = 2e-11; /* IRF540, 9540 */ if (!model->VDMOScgdmaxGiven) - model->VDMOScgdmax = 0; + model->VDMOScgdmax = 2e-9; /* IRF540, 9540 */ if (!model->VDMOScgsGiven) - model->VDMOScgs = 0; + model->VDMOScgs = 1.4e-9; /* IRF540, 9540 */ if (!model->VDMOSaGiven) model->VDMOSa = 1.; From 2ce18ab18404d725ddbf3cf5ffe9a6494cd88b1a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 12:34:31 +0100 Subject: [PATCH 72/91] Add VDMOS default junction cap IRF540 IRF9540 --- src/spicelib/devices/vdmos/vdmosset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/vdmos/vdmosset.c b/src/spicelib/devices/vdmos/vdmosset.c index f0c383ce6..fab46f43e 100644 --- a/src/spicelib/devices/vdmos/vdmosset.c +++ b/src/spicelib/devices/vdmos/vdmosset.c @@ -44,7 +44,7 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, model->VDIOjunctionPot = .8; if (!model->VDIOjunctionCapGiven) - model->VDIOjunctionCap = 0.; + model->VDIOjunctionCap = 5e-10; /* IRF540, 9540 */ if (!model->VDIOgradCoeffGiven) model->VDIOgradCoeff = .5; From f121c433a7657a9476ff473eec141f279ef9d930 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 21:32:24 +0100 Subject: [PATCH 73/91] Check for buggy diode instance line, avoid crash --- src/frontend/inpcom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 1767b1c4a..9c6d67a07 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -9769,8 +9769,14 @@ static struct card *ltspice_compat(struct card *oldcard) /* check for the model name */ int i; char *stoks[4]; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { stoks[i] = gettok_node(&cut_line); + if (stoks[i] == NULL) { + fprintf(stderr, "Error in line %d: buggy diode instance line\n %s\n", card->linenum_orig, card->line); + fprintf(stderr, "At least 'Dxx n1 n2 d' is required.\n"); + controlled_exit(EXIT_BAD); + } + } /* rewrite d line and replace it if a model is found */ if ((nesting > 0) && find_a_model(modelsfound, stoks[3], subcktline->line)) { From 82de3db8ad98681b28bab6da42563e67acedbc66 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 21:34:02 +0100 Subject: [PATCH 74/91] VBIC: Add bvbe, bvbc, and bvce as redundant SOA parameters --- src/spicelib/devices/vbic/vbic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index 50bae6289..682a7f25b 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -180,8 +180,11 @@ IFparm VBICmPTable[] = { /* model parameters */ IOP("vers", VBIC_MOD_VERS, IF_REAL, "Revision Version"), IOP("vref", VBIC_MOD_VREF, IF_REAL, "Reference Version"), IOP("vbe_max", VBIC_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"), + IOPR("bvbe", VBIC_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"), IOP("vbc_max", 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("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") }; char *VBICnames[] = { From 98333ee89a8ceefbeaaf91f96a7b89b7db2f0a43 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Mon, 20 Mar 2023 13:15:52 +0000 Subject: [PATCH 75/91] Fix a memory leak reported by Brian Taylor that was introduced by commit 4d8e17487b2232834a017732e82f8dd29b6b6a14. --- src/xspice/mif/mifdelete.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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); From 5197200fb3267f5ac5133ffdadce907014cd2fdc Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Tue, 21 Mar 2023 21:01:06 +0000 Subject: [PATCH 76/91] Fix crash reported by Brian Taylor. If "source" is used after analysis, the circuit is both deleted and destroyed. Beware of double frees. --- src/xspice/evt/evtsetup.c | 1 + 1 file changed, 1 insertion(+) 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); From ff77c583d771cb13cc99519b2829c7913c4edaaa Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 22 Mar 2023 17:40:49 +0100 Subject: [PATCH 77/91] Add model parameter selft, to switch on self-heating, default: off (selft=0) --- src/spicelib/devices/vbic/vbic.c | 3 ++- src/spicelib/devices/vbic/vbicdefs.h | 3 +++ src/spicelib/devices/vbic/vbicmask.c | 3 +++ src/spicelib/devices/vbic/vbicmpar.c | 4 ++++ src/spicelib/devices/vbic/vbicsetup.c | 6 +++++- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index 682a7f25b..df398a1ce 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -184,7 +184,8 @@ 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("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..50653a95f 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; @@ -571,6 +572,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; @@ -734,6 +736,7 @@ enum { VBIC_MOD_VBE_MAX, VBIC_MOD_VBC_MAX, VBIC_MOD_VCE_MAX, + VBIC_MOD_SELFT, }; /* device questions */ diff --git a/src/spicelib/devices/vbic/vbicmask.c b/src/spicelib/devices/vbic/vbicmask.c index d5f61d901..e8d1f94a1 100644 --- a/src/spicelib/devices/vbic/vbicmask.c +++ b/src/spicelib/devices/vbic/vbicmask.c @@ -369,6 +369,9 @@ VBICmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) 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..73ed58ad6 100644 --- a/src/spicelib/devices/vbic/vbicmpar.c +++ b/src/spicelib/devices/vbic/vbicmpar.c @@ -509,6 +509,10 @@ VBICmParam(int param, IFvalue *value, GENmodel *inModel) mods->VBICvceMax = value->rValue; mods->VBICvceMaxGiven = 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..a0945d47c 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -391,6 +391,9 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->VBICvceMaxGiven) { model->VBICvceMax = 1e99; } + if(!model->VBICselftGiven) { + model->VBICselft = 0; + } /* loop through all the instances of the model */ for (here = VBICinstances(model); here != NULL ; @@ -472,7 +475,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; From 443567dbafeb0634dd54e39d392c332d7f9da238 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 22 Mar 2023 18:08:15 +0100 Subject: [PATCH 78/91] Add SOA-check for collector-substrate diode (model parameter bvsub) --- src/spicelib/devices/vbic/vbic.c | 2 ++ src/spicelib/devices/vbic/vbicdefs.h | 3 +++ src/spicelib/devices/vbic/vbicmask.c | 3 +++ src/spicelib/devices/vbic/vbicmpar.c | 4 ++++ src/spicelib/devices/vbic/vbicsoachk.c | 14 ++++++++++++-- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index df398a1ce..7463cfa71 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -185,6 +185,8 @@ IFparm VBICmPTable[] = { /* model parameters */ 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"), + 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("selft", VBIC_MOD_SELFT, IF_INTEGER, "0: self-heating off, 1: self-heating on") }; diff --git a/src/spicelib/devices/vbic/vbicdefs.h b/src/spicelib/devices/vbic/vbicdefs.h index 50653a95f..2f771084e 100644 --- a/src/spicelib/devices/vbic/vbicdefs.h +++ b/src/spicelib/devices/vbic/vbicdefs.h @@ -485,6 +485,7 @@ 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 */ unsigned VBICtnomGiven : 1; unsigned VBICextCollResistGiven : 1; @@ -600,6 +601,7 @@ typedef struct sVBICmodel { /* model structure for a vbic */ unsigned VBICvbeMaxGiven : 1; unsigned VBICvbcMaxGiven : 1; unsigned VBICvceMaxGiven : 1; + unsigned VBICvsubMaxGiven : 1; } VBICmodel; #ifndef NPN @@ -736,6 +738,7 @@ enum { VBIC_MOD_VBE_MAX, VBIC_MOD_VBC_MAX, VBIC_MOD_VCE_MAX, + VBIC_MOD_VSUB_MAX, VBIC_MOD_SELFT, }; diff --git a/src/spicelib/devices/vbic/vbicmask.c b/src/spicelib/devices/vbic/vbicmask.c index e8d1f94a1..18142d917 100644 --- a/src/spicelib/devices/vbic/vbicmask.c +++ b/src/spicelib/devices/vbic/vbicmask.c @@ -363,6 +363,9 @@ 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_TYPE: if (here->VBICtype == NPN) value->sValue = "npn"; diff --git a/src/spicelib/devices/vbic/vbicmpar.c b/src/spicelib/devices/vbic/vbicmpar.c index 73ed58ad6..efd8a8fdf 100644 --- a/src/spicelib/devices/vbic/vbicmpar.c +++ b/src/spicelib/devices/vbic/vbicmpar.c @@ -509,6 +509,10 @@ 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_SELFT: mods->VBICselft = value->iValue; mods->VBICselftGiven = TRUE; diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index 34d6755ac..f6d6b4a25 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -17,14 +17,15 @@ 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; if (!ckt) { warns_vbe = 0; warns_vbc = 0; warns_vce = 0; + warns_vsub = 0; return OK; } @@ -40,6 +41,8 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) 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) { @@ -65,6 +68,13 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) 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++; + } } } From c30af55491a30cee5227405d3d96bc5b65276b4a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 24 Mar 2023 13:41:06 +0100 Subject: [PATCH 79/91] Add operating point information to SOA check, using vbefwd, vbcfwd, and vsubfwd Operating point heck is enabled by .options warn=2 --- src/spicelib/devices/vbic/vbic.c | 3 + src/spicelib/devices/vbic/vbicdefs.h | 9 +++ src/spicelib/devices/vbic/vbicmask.c | 9 +++ src/spicelib/devices/vbic/vbicmpar.c | 12 ++++ src/spicelib/devices/vbic/vbicsetup.c | 12 ++++ src/spicelib/devices/vbic/vbicsoachk.c | 92 ++++++++++++++++++++------ 6 files changed, 115 insertions(+), 22 deletions(-) diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index 7463cfa71..2ac939058 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -187,6 +187,9 @@ IFparm VBICmPTable[] = { /* model parameters */ 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") }; diff --git a/src/spicelib/devices/vbic/vbicdefs.h b/src/spicelib/devices/vbic/vbicdefs.h index 2f771084e..fd28eebf0 100644 --- a/src/spicelib/devices/vbic/vbicdefs.h +++ b/src/spicelib/devices/vbic/vbicdefs.h @@ -486,6 +486,9 @@ typedef struct sVBICmodel { /* model structure for a vbic */ 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; @@ -602,6 +605,9 @@ typedef struct sVBICmodel { /* model structure for a vbic */ unsigned VBICvbcMaxGiven : 1; unsigned VBICvceMaxGiven : 1; unsigned VBICvsubMaxGiven : 1; + unsigned VBICvbcfwdMaxGiven : 1; + unsigned VBICvbefwdMaxGiven : 1; + unsigned VBICvsubfwdMaxGiven : 1; } VBICmodel; #ifndef NPN @@ -739,6 +745,9 @@ enum { 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, }; diff --git a/src/spicelib/devices/vbic/vbicmask.c b/src/spicelib/devices/vbic/vbicmask.c index 18142d917..757ee7771 100644 --- a/src/spicelib/devices/vbic/vbicmask.c +++ b/src/spicelib/devices/vbic/vbicmask.c @@ -366,6 +366,15 @@ VBICmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) 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"; diff --git a/src/spicelib/devices/vbic/vbicmpar.c b/src/spicelib/devices/vbic/vbicmpar.c index efd8a8fdf..cac58ad3f 100644 --- a/src/spicelib/devices/vbic/vbicmpar.c +++ b/src/spicelib/devices/vbic/vbicmpar.c @@ -513,6 +513,18 @@ VBICmParam(int param, IFvalue *value, GENmodel *inModel) 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; diff --git a/src/spicelib/devices/vbic/vbicsetup.c b/src/spicelib/devices/vbic/vbicsetup.c index a0945d47c..bbb90f7ae 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -391,6 +391,18 @@ 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; } diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index f6d6b4a25..b67a944a2 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -19,13 +19,14 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) VBICinstance *here; double vbe, vbc, vce, vsub; /* actual bjt voltages */ int maxwarns; - static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0, warns_vsub = 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; } @@ -33,48 +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]); - vsub = fabs(ckt->CKTrhsOld [here->VBICcollNode] - - ckt->CKTrhsOld [here->VBICsubsNode]); + 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); + 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 sturation\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++; + } + } + } } } From ce38a768b5c38ada65052c49edd9751c75a53083 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 24 Mar 2023 14:55:57 +0100 Subject: [PATCH 80/91] typo --- src/spicelib/devices/vbic/vbicsoachk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index b67a944a2..c436b16d7 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -102,7 +102,7 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) /*saturation*/ if (warns_op < maxwarns) { soa_printf(ckt, (GENinstance*)here, - "device is in sturation\n"); + "device is in saturation\n"); warns_op++; } } From 062785319a081abf44e367d7d8ba64c3ac5fce12 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 24 Mar 2023 18:23:24 +0100 Subject: [PATCH 81/91] When '.probe alli' is set, disable auto bridging and set a flag --- src/frontend/inpcom.c | 13 +++++++++++++ src/xspice/evt/evtcheck_nodes.c | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 9c6d67a07..2536fad8a 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -9822,6 +9822,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/xspice/evt/evtcheck_nodes.c b/src/xspice/evt/evtcheck_nodes.c index a95e0e82a..ade9dbe28 100644 --- a/src/xspice/evt/evtcheck_nodes.c +++ b/src/xspice/evt/evtcheck_nodes.c @@ -667,8 +667,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. */ From 311ddeac0dd8d7f27eb59117d75090b6651e72c7 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 24 Mar 2023 22:27:12 +0100 Subject: [PATCH 82/91] Prepare for ngspice-40 --- configure.ac | 4 ++-- src/include/ngspice/sharedspice.h | 2 +- visualc/src/include/ngspice/config.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 55da0c74c..8385ce743 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/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/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 159ebc085..5d98fb7d9 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" From 806489860f9cf1a04e4bd97526c14cffc8fe8c97 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 24 Mar 2023 23:47:10 +0100 Subject: [PATCH 83/91] Prepare for ngspice-40 --- DEVICES | 9 ++------- FAQ | 6 +++--- INSTALL | 20 +++++++++----------- README_OSDI.md | 6 ------ 4 files changed, 14 insertions(+), 27 deletions(-) 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/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`. - From c4c77211e923f6d9990379d45f520f052a9bdaf8 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Mar 2023 13:08:51 +0100 Subject: [PATCH 84/91] Prepare ngspice-40 --- NEWS | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/NEWS b/NEWS index a744b6a9b..31ba62a66 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 inertal delay to all basic gital 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: From 95c4c0f5876af59cf53f5828c3b84378408ca7cc Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 25 Mar 2023 15:36:15 +0100 Subject: [PATCH 85/91] Add inertial.h to the distributable headers --- src/include/ngspice/Makefile.am | 1 + 1 file changed, 1 insertion(+) 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 \ From 6060a2fb93605695bb12a0c2df3c17f6f0906609 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 27 Mar 2023 10:03:10 +0200 Subject: [PATCH 86/91] typos --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 31ba62a66..810f0c127 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ 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 inertal delay to all basic gital code models, make it available + + 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 From 6eeb48bb5a1e0132ae7d58ac5cd05d9785c6b31c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 27 Mar 2023 15:52:19 +0200 Subject: [PATCH 87/91] Remove obsolete READMEs from distribution, add new and interesting ones --- Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 \ From 8f8f7ff8ab8117bb5d178c0bc6b249b1eddea98a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 31 Mar 2023 11:16:26 +0200 Subject: [PATCH 88/91] Command 'listing r': No extra formatting, truncation etc. of netlist lines when printing to file or console. --- src/frontend/inp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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)) From 5aa48cab0bdfe16fbc58991cfc057d7d8966e516 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Thu, 30 Mar 2023 20:34:19 +0100 Subject: [PATCH 89/91] Do not generate netlist lines that use non-existent libraries. To support that, give global scope to function inp_pathresolve() in inpcom.c. Update internal documentation (long comment). --- src/frontend/inpcom.c | 3 +- src/frontend/inpcom.h | 2 +- src/xspice/evt/evtcheck_nodes.c | 121 +++++++++++++++++++++----------- 3 files changed, 83 insertions(+), 43 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 2536fad8a..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; 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/xspice/evt/evtcheck_nodes.c b/src/xspice/evt/evtcheck_nodes.c index ade9dbe28..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) { From 7f4eb1c7d843538530adbc072febb95ebf2d991d Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.comâ€> Date: Thu, 30 Mar 2023 21:40:29 +0100 Subject: [PATCH 90/91] Add examples of controlling auto-bridge behaviour with the "vcc" and "family" parameters. --- examples/digital/auto_bridge/adder_family.cir | 43 +++++++++++++++++++ .../bridge_demo_family_d_in.subcir | 11 +++++ examples/digital/auto_bridge/vcc.cir | 23 ++++++++++ 3 files changed, 77 insertions(+) create mode 100644 examples/digital/auto_bridge/adder_family.cir create mode 100644 examples/digital/auto_bridge/bridge_demo_family_d_in.subcir create mode 100644 examples/digital/auto_bridge/vcc.cir 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 + From 4a95de5cd7429c408f544d4275350a5b4cbbeb9e Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 1 Apr 2023 17:31:59 +0200 Subject: [PATCH 91/91] We are developing towards ngspice-41 --- configure.ac | 2 +- visualc/src/include/ngspice/config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 8385ce743..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], [40]) +m4_define([ngspice_major_version], [40+]) m4_define([ngspice_minor_version], [0]) m4_define([ngspice_version], [ngspice_major_version]) diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 5d98fb7d9..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 "40" +#define VERSION "40+" /* Define the directory for executables */ #define NGSPICEBINDIR "../bin"