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 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/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/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 8a7a79f47..7ef70ce93 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) */ @@ -1248,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); diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 16fea8644..9c6d67a07 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 * '>' */ @@ -5096,6 +5097,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) || @@ -5104,11 +5107,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++; } @@ -8651,7 +8654,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, "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, "Error: 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) { @@ -8811,6 +8822,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 '=' */ @@ -8818,8 +8830,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) @@ -9742,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)) { @@ -10268,6 +10301,11 @@ 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, "Error: no model type given in line %s!\n", curr_line); + tfree(modl_new); + controlled_exit(EXIT_BAD); + } modl_new->elemb = inp_get_elem_ident(model_type); modl_new->modelname = get_subckt_model_name(curr_line); modl_new->model = card; diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index a74d5b870..f69912019 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 @@ -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') 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; } 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/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; } 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/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/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/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; +}; + + 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/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index 3f36ecd33..8389fea4a 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,42 @@ 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++) { +#ifdef _MSC_VER + _Dcomplex midin = _Cbuild(degtorad(realpart(cc[i])), degtorad(imagpart(cc[i]))); + _Dcomplex midout = catanh(midin); +#else + 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); + 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); 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 } 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); 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/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[] = { diff --git a/src/spicelib/devices/vdmos/vdmosset.c b/src/spicelib/devices/vdmos/vdmosset.c index 6d7661d11..fab46f43e 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; @@ -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; @@ -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.; 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; } 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/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..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( @@ -61,20 +62,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 +95,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; /* ***************************** */ @@ -138,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; @@ -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; } @@ -471,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 @@ -482,16 +512,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 +531,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 +569,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/digital/d_and/cfunc.mod b/src/xspice/icm/digital/d_and/cfunc.mod index 8945fef48..921b273f8 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,131 @@ 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); + 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_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..1ee0f75cc 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,102 @@ 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); + 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. */ + + 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..cb76cf874 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,107 @@ 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 { + 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); + 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. */ + + 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_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_nor/cfunc.mod b/src/xspice/icm/digital/d_nor/cfunc.mod index 46569eafe..85e5561c7 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,128 @@ 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); + 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_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/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_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" 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 da04e3a12..8e83a9a18 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 ===*/ @@ -173,126 +157,129 @@ NON-STANDARD FEATURES * Created 6/18/91 J.P.Murray * ************************************************/ - -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" diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index a62713fcd..02fffe706 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -13,11 +13,13 @@ #include #include +#include "ngspice/cpextern.h" #include "ngspice/devdefs.h" #include "ngspice/dstring.h" #include "ngspice/dllitf.h" #include "ngspice/evtudn.h" #include "ngspice/inpdefs.h" +#include "ngspice/inertial.h" #include "cmextrn.h" #include "udnextrn.h" @@ -348,6 +350,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); } @@ -534,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; +} 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, 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)) { 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