Merge branch 'pre-master' into bt_dev before adding U* transformation flag to disable probe alli.
This commit is contained in:
commit
e0a22f01f6
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__) ||\
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -134,5 +134,6 @@ bool Evtcheck_nodes(
|
|||
struct INPtables *stab); /* Symbol table. */
|
||||
|
||||
struct dvec *EVTfindvec(char *node);
|
||||
void Evt_purge_free_outputs(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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.;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ Evt_Udn_Info_t udn_int_info = {
|
|||
|
||||
"int",
|
||||
"integer valued data",
|
||||
NULL,
|
||||
|
||||
udn_int_create,
|
||||
udn_int_dismantle,
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ Evt_Udn_Info_t udn_real_info = {
|
|||
|
||||
"real",
|
||||
"real valued data",
|
||||
NULL,
|
||||
|
||||
udn_real_create,
|
||||
udn_real_dismantle,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue