Inertial delay for remaining simple gates and buffers:
nand or xor open_c open_e, but not tristate.
This commit is contained in:
parent
db38d4ad54
commit
cecce5163e
|
|
@ -14,18 +14,15 @@ AUTHORS
|
||||||
|
|
||||||
18 June 1991 Jeffrey P. Murray
|
18 June 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
30 Sept 1991 Jeffrey P. Murray
|
30 Sept 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
This file contains the functional description of the d_nand
|
This file contains the functional description of the d_nand
|
||||||
code model.
|
code model.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
@ -33,13 +30,10 @@ INTERFACES
|
||||||
CMevt.c void *cm_event_alloc()
|
CMevt.c void *cm_event_alloc()
|
||||||
void *cm_event_get_ptr()
|
void *cm_event_get_ptr()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCED FILES
|
REFERENCED FILES
|
||||||
|
|
||||||
Inputs from and outputs to ARGS structure.
|
Inputs from and outputs to ARGS structure.
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
@ -48,29 +42,20 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
/*=== INCLUDE FILES ====================*/
|
/*=== INCLUDE FILES ====================*/
|
||||||
|
|
||||||
|
#include "ngspice/inertial.h"
|
||||||
|
|
||||||
|
|
||||||
/*=== CONSTANTS ========================*/
|
/*=== CONSTANTS ========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== MACROS ===========================*/
|
/*=== MACROS ===========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
|
|
||||||
FUNCTION cm_d_nand()
|
FUNCTION cm_d_nand()
|
||||||
|
|
@ -118,128 +103,125 @@ NON-STANDARD FEATURES
|
||||||
* Created 6/18/91 J.P.Murray *
|
* Created 6/18/91 J.P.Murray *
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
||||||
|
|
||||||
void cm_d_nand(ARGS)
|
void cm_d_nand(ARGS)
|
||||||
|
|
||||||
{
|
{
|
||||||
int i, /* generic loop counter index */
|
int i, /* generic loop counter index */
|
||||||
size; /* number of input & output ports */
|
size; /* number of input & output ports */
|
||||||
|
|
||||||
|
Digital_State_t val, /* Output value. */
|
||||||
|
*out, /* temporary output for buffers */
|
||||||
Digital_State_t *out, /* temporary output for buffers */
|
|
||||||
*out_old, /* previous output for buffers */
|
|
||||||
input; /* temp storage for input bits */
|
input; /* temp storage for input bits */
|
||||||
|
|
||||||
|
|
||||||
/** Retrieve size value... **/
|
/** Retrieve size value... **/
|
||||||
size = PORT_SIZE(in);
|
size = PORT_SIZE(in);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*** Setup required state variables ***/
|
/*** Setup required state variables ***/
|
||||||
|
|
||||||
if(INIT) { /* initial pass */
|
if(INIT) { /* initial pass */
|
||||||
|
|
||||||
/* allocate storage for the outputs */
|
/* 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);
|
for (i=0; i<size; i++) LOAD(in[i]) = PARAM(input_load);
|
||||||
|
} else { /* Retrieve previous values */
|
||||||
/* retrieve storage for the outputs */
|
/* 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 = (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 ***/
|
/*** Calculate new output value based on inputs ***/
|
||||||
|
|
||||||
*out = ZERO;
|
val = ZERO;
|
||||||
for (i=0; i<size; i++) {
|
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 a 0, set *out high */
|
||||||
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
|
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
|
||||||
*out = ONE;
|
val = ONE;
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* if an unknown input, set *out to unknown & break */
|
/* if an unknown input, set *out to unknown & break */
|
||||||
if ( UNKNOWN == input ) {
|
if ( UNKNOWN == input )
|
||||||
*out = UNKNOWN;
|
val = UNKNOWN;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* at least one port is floating...output is unknown */
|
|
||||||
*out = UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** Check for change and output appropriate values ***/
|
||||||
|
|
||||||
|
if (val == *out) { /* output value is not changing */
|
||||||
/*** Determine analysis type and output appropriate values ***/
|
OUTPUT_CHANGED(out) = FALSE;
|
||||||
|
} else {
|
||||||
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
|
switch (val) {
|
||||||
|
|
||||||
OUTPUT_STATE(out) = *out;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else { /** Transient Analysis **/
|
|
||||||
|
|
||||||
|
|
||||||
if ( *out != *out_old ) { /* output value is changing */
|
|
||||||
|
|
||||||
switch ( *out ) {
|
|
||||||
|
|
||||||
/* fall to zero value */
|
/* fall to zero value */
|
||||||
case 0: OUTPUT_STATE(out) = ZERO;
|
case 0:
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* rise to one value */
|
/* rise to one value */
|
||||||
case 1: OUTPUT_STATE(out) = ONE;
|
case 1:
|
||||||
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* unknown output */
|
/* unknown output */
|
||||||
default:
|
default:
|
||||||
OUTPUT_STATE(out) = *out = UNKNOWN;
|
|
||||||
|
|
||||||
/* based on old value, add rise or fall delay */
|
/* 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);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
}
|
} else { /* add falling delay */
|
||||||
else { /* add falling delay */
|
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { /* output value not changing */
|
|
||||||
OUTPUT_CHANGED(out) = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,28 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: input_load
|
Parameter_Name: input_load family
|
||||||
Description: "input load value (F)"
|
Description: "input load value (F)" "Logic family for bridging"
|
||||||
Data_Type: real
|
Data_Type: real string
|
||||||
Default_Value: 1.0e-12
|
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: -
|
Limits: -
|
||||||
Vector: no
|
Vector: no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
STATIC_VAR_TABLE:
|
||||||
|
|
||||||
|
Static_Var_Name: is_inertial
|
||||||
|
Data_Type: boolean
|
||||||
|
Description: "using inertial delay"
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,15 @@ AUTHORS
|
||||||
|
|
||||||
19 Nov 1991 Jeffrey P. Murray
|
19 Nov 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
19 Nov 1991 Jeffrey P. Murray
|
19 Nov 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
This file contains the functional description of the d_open_c
|
This file contains the functional description of the d_open_c
|
||||||
code model.
|
code model.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
@ -33,13 +30,10 @@ INTERFACES
|
||||||
CMevt.c void *cm_event_alloc()
|
CMevt.c void *cm_event_alloc()
|
||||||
void *cm_event_get_ptr()
|
void *cm_event_get_ptr()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCED FILES
|
REFERENCED FILES
|
||||||
|
|
||||||
Inputs from and outputs to ARGS structure.
|
Inputs from and outputs to ARGS structure.
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
@ -48,30 +42,19 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
/*=== INCLUDE FILES ====================*/
|
/*=== INCLUDE FILES ====================*/
|
||||||
|
|
||||||
|
#include "ngspice/inertial.h"
|
||||||
|
|
||||||
|
|
||||||
/*=== CONSTANTS ========================*/
|
/*=== CONSTANTS ========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== MACROS ===========================*/
|
/*=== MACROS ===========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
|
|
||||||
FUNCTION cm_d_open_c()
|
FUNCTION cm_d_open_c()
|
||||||
|
|
@ -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 ===*/
|
/*=== CM_D_OPEN_C ROUTINE ===*/
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
|
|
@ -119,96 +119,106 @@ NON-STANDARD FEATURES
|
||||||
* Created 11/19/91 J.P,Murray *
|
* 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 val,
|
||||||
|
*out; /* temporary output for buffers */
|
||||||
|
|
||||||
|
|
||||||
Digital_State_t *out, /* temporary output for buffers */
|
|
||||||
*out_old; /* previous output for buffers */
|
|
||||||
|
|
||||||
|
|
||||||
/** Setup required state variables **/
|
/** Setup required state variables **/
|
||||||
|
|
||||||
if(INIT) { /* initial pass */
|
if(INIT) { /* initial pass */
|
||||||
|
|
||||||
/* allocate storage for the outputs */
|
/* allocate storage for the outputs */
|
||||||
cm_event_alloc(0,sizeof(Digital_State_t));
|
|
||||||
|
|
||||||
/* define input loading... */
|
cm_event_alloc(0, sizeof (Digital_State_t));
|
||||||
LOAD(in) = PARAM(input_load);
|
|
||||||
|
|
||||||
/* retrieve storage for the outputs */
|
/* Inertial delay? */
|
||||||
out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0);
|
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
else { /* Retrieve previous values */
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
} else {
|
||||||
/* retrieve storage for the outputs */
|
/* retrieve storage for the outputs */
|
||||||
out = (Digital_State_t *) cm_event_get_ptr(0,0);
|
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 ***/
|
||||||
|
|
||||||
/** Check on analysis type **/
|
val = INPUT_STATE(in);
|
||||||
|
|
||||||
if (ANALYSIS == DC) { /* DC analysis...output w/o delays */
|
/*** Check for change and output appropriate values ***/
|
||||||
|
|
||||||
OUTPUT_STATE(out) = *out = INPUT_STATE(in);
|
if (val == *out) { /* output value is not changing */
|
||||||
if ( ONE == *out ) {
|
OUTPUT_CHANGED(out) = FALSE;
|
||||||
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
|
} else {
|
||||||
}
|
switch (val) {
|
||||||
else
|
|
||||||
if ( ZERO == *out ) {
|
|
||||||
OUTPUT_STRENGTH(out) = STRONG;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
OUTPUT_STRENGTH(out) = UNDETERMINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else { /* Transient Analysis */
|
|
||||||
|
|
||||||
switch ( INPUT_STATE(in) ) {
|
|
||||||
|
|
||||||
/* fall to zero value */
|
/* fall to zero value */
|
||||||
case 0: OUTPUT_STATE(out) = *out = ZERO;
|
case 0:
|
||||||
OUTPUT_STRENGTH(out) = STRONG;
|
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* rise to one value */
|
/* rise to one value */
|
||||||
case 1: OUTPUT_STATE(out) = *out = ONE;
|
case 1:
|
||||||
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
|
|
||||||
OUTPUT_DELAY(out) = PARAM(open_delay);
|
OUTPUT_DELAY(out) = PARAM(open_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* unknown output */
|
/* unknown output */
|
||||||
default:
|
default:
|
||||||
OUTPUT_STATE(out) = *out = UNKNOWN;
|
|
||||||
OUTPUT_STRENGTH(out) = UNDETERMINED;
|
|
||||||
|
|
||||||
|
|
||||||
/* based on old value, add rise or fall delay */
|
/* 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(open_delay);
|
OUTPUT_DELAY(out) = PARAM(open_delay);
|
||||||
}
|
} else { /* add falling delay */
|
||||||
else { /* add falling delay */
|
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
}
|
}
|
||||||
break;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,30 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: input_load
|
Parameter_Name: input_load family
|
||||||
Description: "input load value (F)"
|
Description: "input load value (F)" "Logic family for bridging"
|
||||||
Data_Type: real
|
Data_Type: real string
|
||||||
Default_Value: 1.0e-12
|
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: -
|
Limits: -
|
||||||
Vector: no
|
Vector: no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_VAR_TABLE:
|
||||||
|
|
||||||
|
Static_Var_Name: is_inertial
|
||||||
|
Data_Type: boolean
|
||||||
|
Description: "using inertial delay"
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,19 @@ Georgia Tech Research Corporation
|
||||||
Atlanta, Georgia 30332
|
Atlanta, Georgia 30332
|
||||||
PROJECT A-8503-405
|
PROJECT A-8503-405
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
|
|
||||||
19 Nov 1991 Jeffrey P. Murray
|
19 Nov 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
19 Nov 1991 Jeffrey P. Murray
|
19 Nov 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
This file contains the functional description of the d_open_e
|
This file contains the functional description of the d_open_e
|
||||||
code model.
|
code model.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
@ -33,13 +29,10 @@ INTERFACES
|
||||||
CMevt.c void *cm_event_alloc()
|
CMevt.c void *cm_event_alloc()
|
||||||
void *cm_event_get_ptr()
|
void *cm_event_get_ptr()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCED FILES
|
REFERENCED FILES
|
||||||
|
|
||||||
Inputs from and outputs to ARGS structure.
|
Inputs from and outputs to ARGS structure.
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
@ -48,30 +41,20 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
/*=== INCLUDE FILES ====================*/
|
/*=== INCLUDE FILES ====================*/
|
||||||
|
|
||||||
|
#include "ngspice/inertial.h"
|
||||||
|
|
||||||
|
|
||||||
/*=== CONSTANTS ========================*/
|
/*=== CONSTANTS ========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== MACROS ===========================*/
|
/*=== MACROS ===========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
|
|
||||||
FUNCTION cm_d_open_e()
|
FUNCTION cm_d_open_e()
|
||||||
|
|
@ -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 ===*/
|
/*=== CM_D_OPEN_E ROUTINE ===*/
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
|
|
@ -123,97 +123,103 @@ NON-STANDARD FEATURES
|
||||||
void cm_d_open_e(ARGS)
|
void cm_d_open_e(ARGS)
|
||||||
|
|
||||||
{
|
{
|
||||||
/*int i;*/ /* generic loop counter index */
|
Digital_State_t val,
|
||||||
|
*out; /* temporary output for buffers */
|
||||||
|
|
||||||
|
|
||||||
Digital_State_t *out, /* temporary output for buffers */
|
|
||||||
*out_old; /* previous output for buffers */
|
|
||||||
|
|
||||||
|
|
||||||
/** Setup required state variables **/
|
/** Setup required state variables **/
|
||||||
|
|
||||||
if(INIT) { /* initial pass */
|
if(INIT) { /* initial pass */
|
||||||
|
|
||||||
/* allocate storage for the outputs */
|
/* allocate storage for the outputs */
|
||||||
cm_event_alloc(0,sizeof(Digital_State_t));
|
|
||||||
|
|
||||||
/* define input loading... */
|
cm_event_alloc(0, sizeof (Digital_State_t));
|
||||||
LOAD(in) = PARAM(input_load);
|
|
||||||
|
|
||||||
/* retrieve storage for the outputs */
|
/* Inertial delay? */
|
||||||
out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0);
|
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
else { /* Retrieve previous values */
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
} else {
|
||||||
/* retrieve storage for the outputs */
|
/* retrieve storage for the outputs */
|
||||||
out = (Digital_State_t *) cm_event_get_ptr(0,0);
|
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 ***/
|
||||||
|
|
||||||
/** Check on analysis type **/
|
val = INPUT_STATE(in);
|
||||||
|
|
||||||
if (ANALYSIS == DC) { /* DC analysis...output w/o delays */
|
/*** Check for change and output appropriate values ***/
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else { /* Transient Analysis */
|
|
||||||
|
|
||||||
switch ( INPUT_STATE(in) ) {
|
|
||||||
|
|
||||||
|
if (val == *out) { /* output value is not changing */
|
||||||
|
OUTPUT_CHANGED(out) = FALSE;
|
||||||
|
} else {
|
||||||
|
switch (val) {
|
||||||
/* fall to zero value */
|
/* fall to zero value */
|
||||||
case 0: OUTPUT_STATE(out) = *out = ZERO;
|
case 0:
|
||||||
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
|
|
||||||
OUTPUT_DELAY(out) = PARAM(open_delay);
|
OUTPUT_DELAY(out) = PARAM(open_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* rise to one value */
|
/* rise to one value */
|
||||||
case 1: OUTPUT_STATE(out) = *out = ONE;
|
case 1:
|
||||||
OUTPUT_STRENGTH(out) = STRONG;
|
|
||||||
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* unknown output */
|
/* unknown output */
|
||||||
default:
|
default:
|
||||||
OUTPUT_STATE(out) = *out = UNKNOWN;
|
|
||||||
OUTPUT_STRENGTH(out) = UNDETERMINED;
|
|
||||||
|
|
||||||
|
|
||||||
/* based on old value, add rise or fall delay */
|
/* 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);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
}
|
} else { /* add falling delay */
|
||||||
else { /* add falling delay */
|
|
||||||
OUTPUT_DELAY(out) = PARAM(open_delay);
|
OUTPUT_DELAY(out) = PARAM(open_delay);
|
||||||
}
|
}
|
||||||
break;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,30 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: input_load
|
Parameter_Name: input_load family
|
||||||
Description: "input load value (F)"
|
Description: "input load value (F)" "Logic family for bridging"
|
||||||
Data_Type: real
|
Data_Type: real string
|
||||||
Default_Value: 1.0e-12
|
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: -
|
Limits: -
|
||||||
Vector: no
|
Vector: no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_VAR_TABLE:
|
||||||
|
|
||||||
|
Static_Var_Name: is_inertial
|
||||||
|
Data_Type: boolean
|
||||||
|
Description: "using inertial delay"
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,19 @@ Georgia Tech Research Corporation
|
||||||
Atlanta, Georgia 30332
|
Atlanta, Georgia 30332
|
||||||
PROJECT A-8503-405
|
PROJECT A-8503-405
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
|
|
||||||
18 Jun 1991 Jeffrey P. Murray
|
18 Jun 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
30 Sep 1991 Jeffrey P. Murray
|
30 Sep 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
This file contains the functional description of the d_or
|
This file contains the functional description of the d_or
|
||||||
code model.
|
code model.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
@ -33,13 +29,10 @@ INTERFACES
|
||||||
CMevt.c void *cm_event_alloc()
|
CMevt.c void *cm_event_alloc()
|
||||||
void *cm_event_get_ptr()
|
void *cm_event_get_ptr()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCED FILES
|
REFERENCED FILES
|
||||||
|
|
||||||
Inputs from and outputs to ARGS structure.
|
Inputs from and outputs to ARGS structure.
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
@ -48,30 +41,20 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
/*=== INCLUDE FILES ====================*/
|
/*=== INCLUDE FILES ====================*/
|
||||||
|
|
||||||
|
#include "ngspice/inertial.h"
|
||||||
|
|
||||||
|
|
||||||
/*=== CONSTANTS ========================*/
|
/*=== CONSTANTS ========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== MACROS ===========================*/
|
/*=== MACROS ===========================*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
|
|
||||||
FUNCTION cm_d_or()
|
FUNCTION cm_d_or()
|
||||||
|
|
@ -119,123 +102,129 @@ NON-STANDARD FEATURES
|
||||||
* Created 6/18/91 J.P.Murray *
|
* Created 6/18/91 J.P.Murray *
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
||||||
|
|
||||||
void cm_d_or(ARGS)
|
void cm_d_or(ARGS)
|
||||||
|
|
||||||
{
|
{
|
||||||
int i, /* generic loop counter index */
|
int i, /* generic loop counter index */
|
||||||
size; /* number of input & output ports */
|
size; /* number of input & output ports */
|
||||||
|
|
||||||
|
Digital_State_t val, /* Output value. */
|
||||||
|
*out, /* temporary output for buffers */
|
||||||
Digital_State_t *out, /* temporary output for buffers */
|
|
||||||
*out_old, /* previous output for buffers */
|
|
||||||
input; /* temp storage for input bits */
|
input; /* temp storage for input bits */
|
||||||
|
|
||||||
|
|
||||||
/** Retrieve size value... **/
|
/** Retrieve size value... **/
|
||||||
size = PORT_SIZE(in);
|
size = PORT_SIZE(in);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*** Setup required state variables ***/
|
/*** Setup required state variables ***/
|
||||||
|
|
||||||
if(INIT) { /* initial pass */
|
if (INIT) { /* initial pass */
|
||||||
|
|
||||||
/* allocate storage for the outputs */
|
/* 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);
|
for (i=0; i<size; i++) LOAD(in[i]) = PARAM(input_load);
|
||||||
|
} else {
|
||||||
/* 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 */
|
/* retrieve storage for the outputs */
|
||||||
out = (Digital_State_t *) cm_event_get_ptr(0,0);
|
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 ***/
|
/*** Calculate new output value based on inputs ***/
|
||||||
|
|
||||||
*out = ZERO;
|
val = ZERO;
|
||||||
for (i=0; i<size; i++) {
|
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])) ) {
|
if ( ONE == (input = INPUT_STATE(in[i])) ) {
|
||||||
*out = ONE;
|
val = 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;
|
|
||||||
break;
|
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 */
|
||||||
/*** Determine analysis type and output appropriate values ***/
|
OUTPUT_CHANGED(out) = FALSE;
|
||||||
|
} else {
|
||||||
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
|
switch (val) {
|
||||||
|
|
||||||
OUTPUT_STATE(out) = *out;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else { /** Transient Analysis **/
|
|
||||||
|
|
||||||
|
|
||||||
if ( *out != *out_old ) { /* output value is changing */
|
|
||||||
|
|
||||||
switch ( *out ) {
|
|
||||||
|
|
||||||
/* fall to zero value */
|
/* fall to zero value */
|
||||||
case 0: OUTPUT_STATE(out) = ZERO;
|
case 0:
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* rise to one value */
|
/* rise to one value */
|
||||||
case 1: OUTPUT_STATE(out) = ONE;
|
case 1:
|
||||||
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* unknown output */
|
/* unknown output */
|
||||||
default:
|
default:
|
||||||
OUTPUT_STATE(out) = *out = UNKNOWN;
|
|
||||||
|
|
||||||
/* based on old value, add rise or fall delay */
|
/* 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);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
}
|
} else { /* add falling delay */
|
||||||
else { /* add falling delay */
|
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { /* output value not changing */
|
|
||||||
OUTPUT_CHANGED(out) = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,31 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: input_load
|
Parameter_Name: input_load family
|
||||||
Description: "input load value (F)"
|
Description: "input load value (F)" "Logic family for bridging"
|
||||||
Data_Type: real
|
Data_Type: real string
|
||||||
Default_Value: 1.0e-12
|
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: -
|
Limits: -
|
||||||
Vector: no
|
Vector: no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_VAR_TABLE:
|
||||||
|
|
||||||
|
Static_Var_Name: is_inertial
|
||||||
|
Data_Type: boolean
|
||||||
|
Description: "using inertial delay"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,20 @@ Georgia Tech Research Corporation
|
||||||
Atlanta, Georgia 30332
|
Atlanta, Georgia 30332
|
||||||
PROJECT A-8503-405
|
PROJECT A-8503-405
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
|
|
||||||
18 Jun 1991 Jeffrey P. Murray
|
18 Jun 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
7 Aug 1991 Jeffrey P. Murray
|
7 Aug 1991 Jeffrey P. Murray
|
||||||
2 Oct 1991 Jeffrey P. Murray
|
2 Oct 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
This file contains the model-specific routines used to
|
This file contains the model-specific routines used to
|
||||||
functionally describe the d_xor code model.
|
functionally describe the d_xor code model.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
@ -35,59 +31,47 @@ INTERFACES
|
||||||
|
|
||||||
CMevt.c void *cm_event_alloc()
|
CMevt.c void *cm_event_alloc()
|
||||||
void *cm_event_get_ptr()
|
void *cm_event_get_ptr()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCED FILES
|
REFERENCED FILES
|
||||||
|
|
||||||
Inputs from and outputs to ARGS structure.
|
Inputs from and outputs to ARGS structure.
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
FUNCTION cm_toggle_bit()
|
FUNCTION cm_toggle_bit()
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
|
|
||||||
27 Sept 1991 Jeffrey P. Murray
|
27 Sept 1991 Jeffrey P. Murray
|
||||||
|
|
||||||
|
|
||||||
MODIFICATIONS
|
MODIFICATIONS
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
||||||
|
|
||||||
SUMMARY
|
SUMMARY
|
||||||
|
|
||||||
Alters the state of a passed digital variable to its
|
Alters the state of a passed digital variable to its
|
||||||
complement. Thus, a ONE changes to a ZERO. A ZERO changes
|
complement. Thus, a ONE changes to a ZERO. A ZERO changes
|
||||||
to a ONE, and an UNKNOWN remains unchanged.
|
to a ONE, and an UNKNOWN remains unchanged.
|
||||||
|
|
||||||
|
|
||||||
INTERFACES
|
INTERFACES
|
||||||
|
|
||||||
FILE ROUTINE CALLED
|
FILE ROUTINE CALLED
|
||||||
|
|
||||||
N/A N/A
|
N/A N/A
|
||||||
|
|
||||||
|
|
||||||
RETURNED VALUE
|
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.
|
to redefine the variable value.
|
||||||
|
|
||||||
|
|
||||||
GLOBAL VARIABLES
|
GLOBAL VARIABLES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
||||||
|
|
||||||
NON-STANDARD FEATURES
|
NON-STANDARD FEATURES
|
||||||
|
|
||||||
NONE
|
NONE
|
||||||
|
|
@ -95,10 +79,11 @@ NON-STANDARD FEATURES
|
||||||
===============================================================================*/
|
===============================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngspice/inertial.h"
|
||||||
|
|
||||||
/*=== CM_TOGGLE_BIT ROUTINE ===*/
|
/*=== 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
|
/* 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
|
||||||
|
|
@ -112,7 +97,6 @@ static void cm_toggle_bit(Digital_State_t *bit)
|
||||||
*bit = ONE;
|
*bit = ONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -182,114 +166,124 @@ void cm_d_xor(ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Digital_State_t *out, /* temporary output for buffers */
|
Digital_State_t val,
|
||||||
*out_old, /* previous output for buffers */
|
*out, /* temporary output for buffers */
|
||||||
input; /* temp storage for input bits */
|
input; /* temp storage for input bits */
|
||||||
|
|
||||||
|
|
||||||
/** Retrieve size value... **/
|
/** Retrieve size value... **/
|
||||||
size = PORT_SIZE(in);
|
size = PORT_SIZE(in);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*** Setup required state variables ***/
|
/*** Setup required state variables ***/
|
||||||
|
|
||||||
if(INIT) { /* initial pass */
|
if(INIT) { /* initial pass */
|
||||||
|
|
||||||
/* allocate storage for the outputs */
|
/* 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);
|
for (i=0; i<size; i++) LOAD(in[i]) = PARAM(input_load);
|
||||||
|
} else { /* Retrieve previous values */
|
||||||
/* retrieve storage for the outputs */
|
/* 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 = (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 ***/
|
/*** Calculate new output value based on inputs ***/
|
||||||
|
|
||||||
*out = ZERO;
|
val = ZERO;
|
||||||
for (i=0; i<size; i++) {
|
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 a 1, toggle bit value */
|
||||||
if ( ONE == (input = INPUT_STATE(in[i])) ) {
|
if ( ONE == (input = INPUT_STATE(in[i])) ) {
|
||||||
cm_toggle_bit(out);
|
cm_toggle_bit(&val);
|
||||||
}
|
} else {
|
||||||
else {
|
/* if an unknown input, set val to unknown & break */
|
||||||
/* if an unknown input, set *out to unknown & break */
|
|
||||||
if ( UNKNOWN == input ) {
|
if ( UNKNOWN == input ) {
|
||||||
*out = UNKNOWN;
|
val = UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* at least one port is floating...output is unknown */
|
|
||||||
*out = UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*** Check for change and output appropriate values ***/
|
||||||
|
|
||||||
|
if (val == *out) { /* output value is not changing */
|
||||||
/*** Determine analysis type and output appropriate values ***/
|
OUTPUT_CHANGED(out) = FALSE;
|
||||||
|
} else {
|
||||||
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
|
switch (val) {
|
||||||
|
|
||||||
OUTPUT_STATE(out) = *out;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else { /** Transient Analysis **/
|
|
||||||
|
|
||||||
|
|
||||||
if ( *out != *out_old ) { /* output value is changing */
|
|
||||||
|
|
||||||
switch ( *out ) {
|
|
||||||
|
|
||||||
/* fall to zero value */
|
/* fall to zero value */
|
||||||
case 0: OUTPUT_STATE(out) = ZERO;
|
case 0:
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* rise to one value */
|
/* rise to one value */
|
||||||
case 1: OUTPUT_STATE(out) = ONE;
|
case 1:
|
||||||
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* unknown output */
|
/* unknown output */
|
||||||
default:
|
default:
|
||||||
OUTPUT_STATE(out) = *out = UNKNOWN;
|
|
||||||
|
|
||||||
/* based on old value, add rise or fall delay */
|
/* 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);
|
OUTPUT_DELAY(out) = PARAM(rise_delay);
|
||||||
}
|
} else { /* add falling delay */
|
||||||
else { /* add falling delay */
|
|
||||||
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
OUTPUT_DELAY(out) = PARAM(fall_delay);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { /* output value not changing */
|
|
||||||
OUTPUT_CHANGED(out) = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,28 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: input_load
|
Parameter_Name: input_load family
|
||||||
Description: "input load value (F)"
|
Description: "input load value (F)" "Logic family for bridging"
|
||||||
Data_Type: real
|
Data_Type: real string
|
||||||
Default_Value: 1.0e-12
|
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: -
|
Limits: -
|
||||||
Vector: no
|
Vector: no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
STATIC_VAR_TABLE:
|
||||||
|
|
||||||
|
Static_Var_Name: is_inertial
|
||||||
|
Data_Type: boolean
|
||||||
|
Description: "using inertial delay"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue