Merge branch 'pre-master' into bt_dev before adding U* transformation flag to disable probe alli.

This commit is contained in:
Brian Taylor 2023-03-20 17:49:37 -07:00
commit e0a22f01f6
61 changed files with 1856 additions and 1450 deletions

27
examples/various/atanh.sp Normal file
View File

@ -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

View File

@ -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;

View File

@ -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__) ||\

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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')

View File

@ -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;
}

View File

@ -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 },

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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 */

View File

@ -134,5 +134,6 @@ bool Evtcheck_nodes(
struct INPtables *stab); /* Symbol table. */
struct dvec *EVTfindvec(char *node);
void Evt_purge_free_outputs(void);
#endif

View File

@ -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;

View File

@ -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 *);

View File

@ -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;
};

View File

@ -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 */

View File

@ -21,6 +21,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <errno.h>
#include <complex.h>
#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)

View File

@ -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);

View File

@ -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
}

View File

@ -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);

View File

@ -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

View File

@ -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[] = {

View File

@ -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.;

View File

@ -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;
}

View File

@ -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,

View File

@ -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)

View File

@ -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 {

View File

@ -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();
}
/*

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}
}
}
/*

View File

@ -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 <math.h>
#include <string.h>
#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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ONE;
val = ONE;
for (i=0; i<size; i++) {
/* if a 0, set val low */
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 0, set *out low */
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
*out = ZERO;
break;
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
}
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
val = ZERO;
break;
} else {
/* if an unknown input, set val to unknown & break */
if ( UNKNOWN == input )
val = UNKNOWN;
}
}
/*** Determine analysis type and output appropriate values ***/
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
OUTPUT_STATE(out) = *out;
}
else { /** Transient Analysis **/
/*** Check for change and output appropriate values ***/
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
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;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
/* unknown output */
default:
OUTPUT_STATE(out) = *out = UNKNOWN;
default:
OUTPUT_STATE(out) = UNKNOWN;
/* based on old value, add rise or fall delay */
if (0 == *out_old) { /* add rising delay */
/* 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(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 { /* 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;
}

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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"

View File

@ -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 <model_name>
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 <math.h>
#include <string.h>
#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;
}
}

View File

@ -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"

View File

@ -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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ZERO;
val = ZERO;
for (i=0; i<size; i++) {
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 0, set *out high */
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
*out = ONE;
break;
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
}
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
/* if a 0, set *out high */
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
val = ONE;
break;
} else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input )
val = UNKNOWN;
}
}
/*** Determine analysis type and output appropriate values ***/
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
OUTPUT_STATE(out) = *out;
}
else { /** Transient Analysis **/
/*** Check for change and output appropriate values ***/
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
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;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
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 */
default:
/* 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(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 { /* 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;
}
}

View File

@ -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"

View File

@ -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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ONE;
val = ONE;
for (i=0; i<size; i++) {
/* If a 1, set val low, and done. */
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 1, set *out low */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
*out = ZERO;
break;
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
}
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
if ( ONE == (input = INPUT_STATE(in[i])) ) {
val = ZERO;
break;
} else {
/* If an unknown input, set val to unknown. */
if (UNKNOWN == input)
val = UNKNOWN;
}
}
/*** Check for change and output appropriate values ***/
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
/*** Determine analysis type and output appropriate values ***/
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
OUTPUT_STATE(out) = *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;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
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 */
default:
/* 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(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 { /* 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;
}
}

View File

@ -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"

View File

@ -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);
}
}
}

View File

@ -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"

View File

@ -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);
}
}
}

View File

@ -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"

View File

@ -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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ZERO;
val = ZERO;
for (i=0; i<size; i++) {
/* If a 1, set val high, and done. */
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 1, set *out high */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
*out = ONE;
break;
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
}
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
if ( ONE == (input = INPUT_STATE(in[i])) ) {
val = ONE;
break;
} else {
/* If an unknown input, set val to unknown. */
if (UNKNOWN == input)
val = UNKNOWN;
}
}
/*** Check for change and output appropriate values ***/
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
/*** Determine analysis type and output appropriate values ***/
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
OUTPUT_STATE(out) = *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;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
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 */
default:
/* 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(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 { /* 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;
}
}

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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"

View File

@ -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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ONE;
val = ONE;
for (i=0; i<size; i++) {
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 1, toggle bit value */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
cm_toggle_bit(out);
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
break;
}
/* if a 1, toggle bit value */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
cm_toggle_bit(&val);
} else {
/* if an unknown input, set val to unknown & break */
if ( UNKNOWN == input ) {
val = UNKNOWN;
break;
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
}
/*** Check for change and output appropriate values ***/
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(fall_delay);
break;
/* rise to one value */
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
/* unknown output */
default:
/* 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(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. */
/*** 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;
}
}

View File

@ -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"

View File

@ -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; i<size; i++) LOAD(in[i]) = 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);
}
/*** Calculate new output value based on inputs ***/
*out = ZERO;
val = ZERO;
for (i=0; i<size; i++) {
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 1, toggle bit value */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
cm_toggle_bit(out);
}
else {
/* if an unknown input, set *out to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
break;
}
/* if a 1, toggle bit value */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
cm_toggle_bit(&val);
} else {
/* if an unknown input, set val to unknown & break */
if ( UNKNOWN == input ) {
val = UNKNOWN;
break;
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
}
/*** Check for change and output appropriate values ***/
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(fall_delay);
break;
/* rise to one value */
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
/* unknown output */
default:
/* 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(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. */
/*** 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;
}
}

View File

@ -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"

View File

@ -13,11 +13,13 @@
#include <stdlib.h>
#include <string.h>
#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;
}

View File

@ -182,6 +182,7 @@ Evt_Udn_Info_t udn_int_info = {
"int",
"integer valued data",
NULL,
udn_int_create,
udn_int_dismantle,

View File

@ -183,6 +183,7 @@ Evt_Udn_Info_t udn_real_info = {
"real",
"real valued data",
NULL,
udn_real_create,
udn_real_dismantle,

View File

@ -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,

View File

@ -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)) {

View File

@ -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