From cb4b34c463f1f6593fd010a6ce8995b4c3010bc0 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 3 Mar 2023 14:53:32 +0100 Subject: [PATCH 01/45] 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 6dbe585978b328f56ac5281680d817b12b09d202 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 5 Mar 2023 11:20:02 +0100 Subject: [PATCH 02/45] 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 1730227d624a9445159ebb6c98123af1ae4c7a84 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 5 Mar 2023 11:26:00 +0100 Subject: [PATCH 03/45] 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 eea7b1c2f9a0ff3d14154c26b70267cbbcac3cf5 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 6 Mar 2023 11:53:36 +0000 Subject: [PATCH 04/45] 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 269ec61e6dfe990beba6dbb58c0b5f6eec1111de Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Thu, 2 Mar 2023 12:19:53 -0800 Subject: [PATCH 05/45] 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 28a710b2d6a8f92e30bdb2dcc41a8973b3e933a1 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Thu, 2 Mar 2023 17:40:15 -0800 Subject: [PATCH 06/45] 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 48cd7d5fd41e01886eb7c6e3cd3ab1ea6f09f768 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 3 Mar 2023 12:48:02 -0800 Subject: [PATCH 07/45] 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 5be7c07eee1dc9322be56da9c3bfdace5b9fb0a8 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sat, 4 Mar 2023 11:08:09 -0800 Subject: [PATCH 08/45] 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 d03c6e8c4569081d7a840e31f2410aa49fcd2cc8 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sun, 5 Mar 2023 20:54:19 -0800 Subject: [PATCH 09/45] 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 86bf9fdc119e529c747bff42ce0ae14ae69c705d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 6 Mar 2023 23:14:56 +0100 Subject: [PATCH 10/45] 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 38307b88491af8cbf8122833dd1fdb7bbe471f71 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Mar 2023 23:18:25 +0100 Subject: [PATCH 11/45] 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 f360e6e58a4463f0f3d95f086bd2dfeace3d9cf5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Mar 2023 23:26:55 +0100 Subject: [PATCH 12/45] 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 53c8bc05e6fef0fdfd761ce5a973f4c8cbd44da8 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 13 Mar 2023 09:24:43 +0100 Subject: [PATCH 13/45] 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 e86627dd605b25845c920237e789503f03a97f22 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 13 Mar 2023 09:59:29 +0100 Subject: [PATCH 14/45] 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 fd87e02087244480733d83f4c6593b231415a84b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 14 Mar 2023 21:14:18 +0100 Subject: [PATCH 15/45] 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 c8dd2987489da67479f91bfe8ed6f7dee82b0c91 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Tue, 14 Mar 2023 21:47:50 +0100 Subject: [PATCH 16/45] 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 6330dbb8ed55630064ca5fd31e71dba5d5b4366c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 13:15:11 +0100 Subject: [PATCH 17/45] 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 137220c0156ade22af0b80c79d68bb0df0767414 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 13:33:44 +0100 Subject: [PATCH 18/45] 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 f888eb5ef9f4722c0598974c4565abc6721ae3f3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 15:42:34 +0100 Subject: [PATCH 19/45] 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 2b425f2cb841f1a8988e7200f535c2e1452c054d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 10:05:17 +0100 Subject: [PATCH 20/45] 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 56639e338da204dd42cecb3dd146b0d227a123bd Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 15 Mar 2023 16:06:58 +0100 Subject: [PATCH 21/45] 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 33becb211f14d1cfd7f3640bb819a5fe884e0fcd Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 15 Mar 2023 18:32:43 +0100 Subject: [PATCH 22/45] 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 746121543f2080f835b3351832ca63e825000201 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 21:04:08 +0100 Subject: [PATCH 23/45] 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 a5490cc03709972c2b1f52c39fae025ef51dcd61 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 17 Mar 2023 21:27:41 +0100 Subject: [PATCH 24/45] 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 26404d985f739393890da41e5c9656d71a216ba8 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 14:49:11 +0100 Subject: [PATCH 25/45] .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 7bf550f6377c3f2e58333ec7f3a325c5cebd3b1d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Mar 2023 22:28:32 +0100 Subject: [PATCH 26/45] 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 36943f4d88aac84f5c3e9089a64131d007b8b9bb Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 19 Mar 2023 12:10:52 +0100 Subject: [PATCH 27/45] 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 2ee1444dfa502d7facc6133903f558023db10b76 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Mon, 6 Mar 2023 17:46:22 -0800 Subject: [PATCH 28/45] Temporary changes to add an inertial_delay parameter table. There are no changes to the cfunc.mod files. Thus the additions are ignored. This will prevent MIF unrecognized parameter warnings. --- src/xspice/icm/digital/d_and/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_buffer/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_inverter/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_nand/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_nor/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_or/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_tristate/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_xnor/ifspec.ifs | 12 ++++++++++++ src/xspice/icm/digital/d_xor/ifspec.ifs | 12 ++++++++++++ 9 files changed, 108 insertions(+) diff --git a/src/xspice/icm/digital/d_and/ifspec.ifs b/src/xspice/icm/digital/d_and/ifspec.ifs index feaa22c93..4d1252ff8 100644 --- a/src/xspice/icm/digital/d_and/ifspec.ifs +++ b/src/xspice/icm/digital/d_and/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_buffer/ifspec.ifs b/src/xspice/icm/digital/d_buffer/ifspec.ifs index 4aa5dee61..00dcc5dcb 100644 --- a/src/xspice/icm/digital/d_buffer/ifspec.ifs +++ b/src/xspice/icm/digital/d_buffer/ifspec.ifs @@ -60,3 +60,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_inverter/ifspec.ifs b/src/xspice/icm/digital/d_inverter/ifspec.ifs index 3d0f9479a..f5d955ee8 100644 --- a/src/xspice/icm/digital/d_inverter/ifspec.ifs +++ b/src/xspice/icm/digital/d_inverter/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_nand/ifspec.ifs b/src/xspice/icm/digital/d_nand/ifspec.ifs index b4e18059f..9a55fcf42 100644 --- a/src/xspice/icm/digital/d_nand/ifspec.ifs +++ b/src/xspice/icm/digital/d_nand/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_nor/ifspec.ifs b/src/xspice/icm/digital/d_nor/ifspec.ifs index 316a13638..554656dd7 100644 --- a/src/xspice/icm/digital/d_nor/ifspec.ifs +++ b/src/xspice/icm/digital/d_nor/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_or/ifspec.ifs b/src/xspice/icm/digital/d_or/ifspec.ifs index f3e2f1af6..5ac414723 100644 --- a/src/xspice/icm/digital/d_or/ifspec.ifs +++ b/src/xspice/icm/digital/d_or/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_tristate/ifspec.ifs b/src/xspice/icm/digital/d_tristate/ifspec.ifs index fc68e337a..92ef59039 100644 --- a/src/xspice/icm/digital/d_tristate/ifspec.ifs +++ b/src/xspice/icm/digital/d_tristate/ifspec.ifs @@ -75,3 +75,15 @@ Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_xnor/ifspec.ifs b/src/xspice/icm/digital/d_xnor/ifspec.ifs index ee858089b..0c6074a18 100644 --- a/src/xspice/icm/digital/d_xnor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xnor/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + diff --git a/src/xspice/icm/digital/d_xor/ifspec.ifs b/src/xspice/icm/digital/d_xor/ifspec.ifs index ddd3aa53d..cef26892a 100644 --- a/src/xspice/icm/digital/d_xor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xor/ifspec.ifs @@ -61,3 +61,15 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 + From e041aa2c3802169b8fa3fd0ea41deaee1a68d0b9 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Thu, 9 Mar 2023 08:49:19 -0800 Subject: [PATCH 29/45] Undo the temporary changes to ifspec.ifs files made by commit abe26ac1fef4986fafb89b72caf1c6be0a700239. --- src/xspice/icm/digital/d_and/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_buffer/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_inverter/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_nand/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_nor/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_or/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_tristate/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_xnor/ifspec.ifs | 12 ------------ src/xspice/icm/digital/d_xor/ifspec.ifs | 12 ------------ 9 files changed, 108 deletions(-) diff --git a/src/xspice/icm/digital/d_and/ifspec.ifs b/src/xspice/icm/digital/d_and/ifspec.ifs index 4d1252ff8..feaa22c93 100644 --- a/src/xspice/icm/digital/d_and/ifspec.ifs +++ b/src/xspice/icm/digital/d_and/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_buffer/ifspec.ifs b/src/xspice/icm/digital/d_buffer/ifspec.ifs index 00dcc5dcb..4aa5dee61 100644 --- a/src/xspice/icm/digital/d_buffer/ifspec.ifs +++ b/src/xspice/icm/digital/d_buffer/ifspec.ifs @@ -60,15 +60,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_inverter/ifspec.ifs b/src/xspice/icm/digital/d_inverter/ifspec.ifs index f5d955ee8..3d0f9479a 100644 --- a/src/xspice/icm/digital/d_inverter/ifspec.ifs +++ b/src/xspice/icm/digital/d_inverter/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_nand/ifspec.ifs b/src/xspice/icm/digital/d_nand/ifspec.ifs index 9a55fcf42..b4e18059f 100644 --- a/src/xspice/icm/digital/d_nand/ifspec.ifs +++ b/src/xspice/icm/digital/d_nand/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_nor/ifspec.ifs b/src/xspice/icm/digital/d_nor/ifspec.ifs index 554656dd7..316a13638 100644 --- a/src/xspice/icm/digital/d_nor/ifspec.ifs +++ b/src/xspice/icm/digital/d_nor/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_or/ifspec.ifs b/src/xspice/icm/digital/d_or/ifspec.ifs index 5ac414723..f3e2f1af6 100644 --- a/src/xspice/icm/digital/d_or/ifspec.ifs +++ b/src/xspice/icm/digital/d_or/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_tristate/ifspec.ifs b/src/xspice/icm/digital/d_tristate/ifspec.ifs index 92ef59039..fc68e337a 100644 --- a/src/xspice/icm/digital/d_tristate/ifspec.ifs +++ b/src/xspice/icm/digital/d_tristate/ifspec.ifs @@ -75,15 +75,3 @@ Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_xnor/ifspec.ifs b/src/xspice/icm/digital/d_xnor/ifspec.ifs index 0c6074a18..ee858089b 100644 --- a/src/xspice/icm/digital/d_xnor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xnor/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - diff --git a/src/xspice/icm/digital/d_xor/ifspec.ifs b/src/xspice/icm/digital/d_xor/ifspec.ifs index cef26892a..ddd3aa53d 100644 --- a/src/xspice/icm/digital/d_xor/ifspec.ifs +++ b/src/xspice/icm/digital/d_xor/ifspec.ifs @@ -61,15 +61,3 @@ Vector: no Vector_Bounds: - Null_Allowed: 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 - From 3ac7d21d156772428ffd2a6b823a0dacaf233295 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 10 Mar 2023 11:40:37 -0800 Subject: [PATCH 30/45] 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 2ac72c62f832f82aae26fed394ca28ad22ffaaed Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Fri, 17 Mar 2023 07:18:12 -0700 Subject: [PATCH 31/45] 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 72c8bc45f25b618cd373dc56e4f370769da87731 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Tue, 7 Mar 2023 17:16:38 -0800 Subject: [PATCH 32/45] 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 b09c46d2a501fbe5a937204b2ef0986d33fbe556 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Sat, 5 Nov 2022 21:07:46 +0000 Subject: [PATCH 33/45] 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 4d8e17487b2232834a017732e82f8dd29b6b6a14 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Thu, 23 Feb 2023 17:56:40 +0000 Subject: [PATCH 34/45] 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 a9270aa312cd3aa07870d373f30f5d70bf830e24 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Sat, 25 Feb 2023 09:18:17 +0000 Subject: [PATCH 35/45] 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 22f3690fa40b6e3ed609ccec265747cdac8fd5ac Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Fri, 10 Mar 2023 19:12:01 +0000 Subject: [PATCH 36/45] 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 6afdc33b219f604c50d6d90956efce33639a420f Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Sun, 12 Mar 2023 13:13:58 +0000 Subject: [PATCH 37/45] 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 a1e42bd04194dff90c6885d2ab068e4c29586f1c Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 13 Mar 2023 13:57:16 +0000 Subject: [PATCH 38/45] 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 393be438870db18460b0573dbc5f6922330434ed Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 14 Mar 2023 10:30:11 +0000 Subject: [PATCH 39/45] 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 f91b5d66372c41f4b74ccb0001362e643753084f Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 14 Mar 2023 21:41:10 +0000 Subject: [PATCH 40/45] 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 d3ce882ce76c75e97a99ad0e08fbcb37d6d915ff Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Fri, 17 Mar 2023 15:21:18 +0000 Subject: [PATCH 41/45] 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 a7d04da0232a079bfbb5f2e860079e06a9a649e9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 09:46:58 +0100 Subject: [PATCH 42/45] 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 269524eaf7591639dfe7bb0ad3018a9a6f9e29f9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 12:34:31 +0100 Subject: [PATCH 43/45] 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 50a52a19cf35680d1b4f203e60974f179cbddd76 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 21:32:24 +0100 Subject: [PATCH 44/45] 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 acca48dd190b684aa0c9c2e5aa174459fa0b5fb1 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 20 Mar 2023 21:34:02 +0100 Subject: [PATCH 45/45] 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[] = {