Interim version of inertial delay for tristate buffer.

This does not handle three-way or mixed transitions.
This commit is contained in:
Giles Atkinson 2023-03-12 13:13:58 +00:00 committed by Holger Vogt
parent e3b4df6a51
commit 4623a04615
2 changed files with 118 additions and 69 deletions

View File

@ -8,37 +8,30 @@ Public Domain
Georgia Tech Research Corporation
Atlanta, Georgia 30332
PROJECT A-8503-405
AUTHORS
AUTHORS
18 Nov 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
26 Nov 1991 Jeffrey P. Murray
SUMMARY
This file contains the functional description of the d_tristate
code model.
INTERFACES
INTERFACES
FILE ROUTINE CALLED
FILE ROUTINE CALLED
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
@ -48,39 +41,30 @@ NON-STANDARD FEATURES
/*=== INCLUDE FILES ====================*/
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
FUNCTION cm_d_tristate()
AUTHORS
AUTHORS
18 Nov 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
26 Nov 1991 Jeffrey P. Murray
@ -88,9 +72,9 @@ SUMMARY
This function implements the d_tristate code model.
INTERFACES
INTERFACES
FILE ROUTINE CALLED
FILE ROUTINE CALLED
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
@ -100,7 +84,7 @@ RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
@ -123,43 +107,101 @@ NON-STANDARD FEATURES
* Last Modified 11/26/91 *
************************************************/
void cm_d_tristate(ARGS)
{
int enable; /* holding variable for enable input */
Digital_t *out;
Digital_State_t val, enable;
Digital_Strength_t str;
struct idata *idp;
if (INIT) { /* initial pass */
/* define input loading... */
LOAD(in) = PARAM(input_load);
LOAD(enable) = PARAM(enable_load);
OUTPUT_DELAY(out) = PARAM(delay);
/* allocate storage for the previous output. */
cm_event_alloc(0, sizeof (Digital_t));
out = (Digital_t *)cm_event_get_ptr(0, 0);
out->state = (Digital_State_t)(UNKNOWN + 1); // Force initial output.
/* Inertial delay? */
STATIC_VAR(is_inertial) =
cm_is_inertial(PARAM_NULL(inertial_delay) ? Not_set :
PARAM(inertial_delay));
if (STATIC_VAR(is_inertial)) {
/* Allocate storage for event time. */
cm_event_alloc(1, 2 * sizeof (struct idata));
idp = (struct idata *)cm_event_get_ptr(1, 0);
idp[1].when = idp[0].when = -1.0;
}
/* Prepare initial output. */
out = (Digital_t *)cm_event_get_ptr(0, 0);
out->state = (Digital_State_t)(UNKNOWN + 1); // Force initial output.
} else {
out = (Digital_t *)cm_event_get_ptr(0, 0);
}
/* Retrieve input values and static variables */
val = INPUT_STATE(in);
enable = INPUT_STATE(enable);
OUTPUT_STATE(out) = INPUT_STATE(in);
OUTPUT_DELAY(out) = PARAM(delay);
/* define input loading... */
LOAD(in) = PARAM(input_load);
LOAD(enable) = PARAM(enable_load);
if (ZERO == enable) {
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
str = HI_IMPEDANCE;
} else if (UNKNOWN == enable) {
str = UNDETERMINED;
} else {
str = STRONG;
}
else
if (UNKNOWN == enable) {
OUTPUT_STRENGTH(out) = UNDETERMINED;
if (val == out->state && str == out->strength) {
OUTPUT_CHANGED(out) = FALSE;
} else {
if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) {
int d_cancel, s_cancel;
}
else {
OUTPUT_STRENGTH(out) = STRONG;
idp = (struct idata *)cm_event_get_ptr(1, 0);
d_cancel = (idp[0].when > TIME && val == idp[0].prev);
s_cancel = (idp[1].when > TIME &&
str == (Digital_Strength_t)idp[1].prev);
if ((d_cancel && s_cancel) ||
(d_cancel && str == out->strength && TIME >= idp[1].when) ||
(s_cancel && val == out->state && TIME >= idp[0].when)) {
double when;
/* Changing back: override pending change. */
when = d_cancel ? idp[0].when : idp[1].when;
if (s_cancel && when > idp[1].when)
when = idp[1].when;
OUTPUT_DELAY(out) = (when - TIME) / 2.0; // Override
idp[1].when = idp[0].when = -1.0;
} else {
/* Normal transition, or third value during delay,
* or needs cancel followed by restore of
* the other component (fudge).
*/
OUTPUT_DELAY(out) = PARAM(delay);
if (val != out->state) {
idp[0].prev = out->state;
idp[0].when = TIME + OUTPUT_DELAY(out);
}
if (str != out->strength) {
idp[1].prev = (Digital_State_t)out->strength;
idp[1].when = TIME + OUTPUT_DELAY(out);
}
}
}
out->state = val;
out->strength = str;
*(Digital_t *)OUTPUT(out) = *out;
}
}

View File

@ -52,26 +52,33 @@ Null_Allowed: yes
PARAMETER_TABLE:
Parameter_Name: input_load
Description: "input load value (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
Parameter_Name: input_load enable_load
Description: "input load value (F)" "enable load value (F)"
Data_Type: real real
Default_Value: 1.0e-12 1.0e-12
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: enable_load
Description: "enable load value (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
Parameter_Name: inertial_delay family
Description: "swallow short pulses" "Logic family for bridging"
Data_Type: boolean string
Default_Value: false -
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
STATIC_VAR_TABLE:
Static_Var_Name: is_inertial
Data_Type: boolean
Description: "using inertial delay"