Inertial delay for remaining simple gates and buffers:

nand or xor open_c open_e, but not tristate.
This commit is contained in:
Giles Atkinson 2023-03-14 21:41:10 +00:00 committed by Holger Vogt
parent db38d4ad54
commit cecce5163e
10 changed files with 726 additions and 658 deletions

View File

@ -14,18 +14,15 @@ AUTHORS
18 June 1991 Jeffrey P. Murray
MODIFICATIONS
30 Sept 1991 Jeffrey P. Murray
SUMMARY
This file contains the functional description of the d_nand
code model.
INTERFACES
FILE ROUTINE CALLED
@ -33,13 +30,10 @@ INTERFACES
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
@ -48,29 +42,20 @@ NON-STANDARD FEATURES
/*=== INCLUDE FILES ====================*/
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
FUNCTION cm_d_nand()
@ -118,128 +103,125 @@ NON-STANDARD FEATURES
* Created 6/18/91 J.P.Murray *
************************************************/
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 */
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));
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;
val = ONE;
break;
}
else {
} 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;
if ( UNKNOWN == input )
val = UNKNOWN;
}
}
/*** Check for change and output appropriate values ***/
/*** 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 ) {
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
/* fall to zero value */
case 0: OUTPUT_STATE(out) = ZERO;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
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;
}
}
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;
}
}

View File

@ -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
Parameter_Name: input_load family
Description: "input load value (F)" "Logic family for bridging"
Data_Type: real string
Default_Value: 1.0e-12 -
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: inertial_delay
Description: "swallow short pulses"
Data_Type: boolean
Default_Value: false
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
STATIC_VAR_TABLE:
Static_Var_Name: is_inertial
Data_Type: boolean
Description: "using inertial delay"

View File

@ -14,18 +14,15 @@ AUTHORS
19 Nov 1991 Jeffrey P. Murray
MODIFICATIONS
19 Nov 1991 Jeffrey P. Murray
SUMMARY
This file contains the functional description of the d_open_c
code model.
INTERFACES
FILE ROUTINE CALLED
@ -33,13 +30,10 @@ INTERFACES
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
@ -48,30 +42,19 @@ NON-STANDARD FEATURES
/*=== INCLUDE FILES ====================*/
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
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 ===*/
/************************************************
@ -119,96 +119,106 @@ NON-STANDARD FEATURES
* Created 11/19/91 J.P,Murray *
************************************************/
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 */
/* allocate storage for the outputs */
cm_event_alloc(0,sizeof(Digital_State_t));
/* define input loading... */
LOAD(in) = PARAM(input_load);
cm_event_alloc(0, sizeof (Digital_State_t));
/* retrieve storage for the outputs */
out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0);
/* 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;
}
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 */
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) = HI_IMPEDANCE;
}
else
if ( ZERO == *out ) {
OUTPUT_STRENGTH(out) = STRONG;
}
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 */
case 0: OUTPUT_STATE(out) = *out = ZERO;
OUTPUT_STRENGTH(out) = STRONG;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = *out = ONE;
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
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 */
if (0 == *out) { /* add rising delay */
OUTPUT_DELAY(out) = PARAM(open_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, strength(idp->prev)};
/* Third value: cancel earlier change and output as usual. */
cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov);
if (val == UNKNOWN) {
/* Delay based in idp->prev, not *out. */
if (idp->prev == ZERO)
OUTPUT_DELAY(out) = PARAM(open_delay);
else
OUTPUT_DELAY(out) = PARAM(fall_delay);
}
idp->when = TIME + OUTPUT_DELAY(out); // Actual output time
} else {
/* Changing back: override pending change. */
OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override
idp->when = -1.0;
}
}
*out = val;
OUTPUT_STATE(out) = val;
OUTPUT_STRENGTH(out) = strength(val);
}
}

View File

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

View File

@ -9,23 +9,19 @@ Georgia Tech Research Corporation
Atlanta, Georgia 30332
PROJECT A-8503-405
AUTHORS
19 Nov 1991 Jeffrey P. Murray
MODIFICATIONS
19 Nov 1991 Jeffrey P. Murray
SUMMARY
This file contains the functional description of the d_open_e
code model.
INTERFACES
FILE ROUTINE CALLED
@ -33,13 +29,10 @@ INTERFACES
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
@ -48,30 +41,20 @@ NON-STANDARD FEATURES
/*=== INCLUDE FILES ====================*/
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
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 ===*/
/************************************************
@ -123,97 +123,103 @@ NON-STANDARD FEATURES
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 */
/* allocate storage for the outputs */
cm_event_alloc(0,sizeof(Digital_State_t));
/* define input loading... */
LOAD(in) = PARAM(input_load);
cm_event_alloc(0, sizeof (Digital_State_t));
/* retrieve storage for the outputs */
out = out_old = (Digital_State_t *) cm_event_get_ptr(0,0);
/* 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;
}
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 */
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 */
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) ) {
/*** 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_STATE(out) = *out = ZERO;
OUTPUT_STRENGTH(out) = HI_IMPEDANCE;
case 0:
OUTPUT_DELAY(out) = PARAM(open_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = *out = ONE;
OUTPUT_STRENGTH(out) = STRONG;
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 */
if (0 == *out) { /* add rising delay */
OUTPUT_DELAY(out) = PARAM(rise_delay);
}
else { /* add falling delay */
} else { /* add falling delay */
OUTPUT_DELAY(out) = PARAM(open_delay);
}
break;
}
if (STATIC_VAR(is_inertial) && ANALYSIS == TRANSIENT) {
struct idata *idp;
idp = (struct idata *)cm_event_get_ptr(1, 0);
if (idp->when <= TIME) {
/* Normal transition. */
idp->prev = *out;
idp->when = TIME + OUTPUT_DELAY(out); // Actual output time
} else if (val != idp->prev) {
Digital_t ov = {idp->prev, strength(idp->prev)};
/* Third value: cancel earlier change and output as usual. */
cm_schedule_output(1, 0, (idp->when - TIME) / 2.0, &ov);
if (val == UNKNOWN) {
/* Delay based in idp->prev, not *out. */
if (idp->prev == ZERO)
OUTPUT_DELAY(out) = PARAM(rise_delay);
else
OUTPUT_DELAY(out) = PARAM(open_delay);
}
idp->when = TIME + OUTPUT_DELAY(out); // Actual output time
} else {
/* Changing back: override pending change. */
OUTPUT_DELAY(out) = (idp->when - TIME) / 2.0; // Override
idp->when = -1.0;
}
}
*out = val;
OUTPUT_STATE(out) = val;
OUTPUT_STRENGTH(out) = strength(val);
}
}

View File

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

View File

@ -9,23 +9,19 @@ Georgia Tech Research Corporation
Atlanta, Georgia 30332
PROJECT A-8503-405
AUTHORS
18 Jun 1991 Jeffrey P. Murray
MODIFICATIONS
30 Sep 1991 Jeffrey P. Murray
SUMMARY
This file contains the functional description of the d_or
code model.
INTERFACES
FILE ROUTINE CALLED
@ -33,13 +29,10 @@ INTERFACES
CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr()
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
@ -48,30 +41,20 @@ NON-STANDARD FEATURES
/*=== INCLUDE FILES ====================*/
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
FUNCTION cm_d_or()
@ -119,123 +102,129 @@ NON-STANDARD FEATURES
* Created 6/18/91 J.P.Murray *
************************************************/
void cm_d_or(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 */
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;
val = ONE;
break;
} else {
/* If an unknown input, set val to unknown. */
if (UNKNOWN == input)
val = UNKNOWN;
}
}
/*** Check for change and output appropriate values ***/
/*** 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 ) {
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
/* fall to zero value */
case 0: OUTPUT_STATE(out) = ZERO;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
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;
}
}
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;
}
}

View File

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

View File

@ -9,24 +9,20 @@ Georgia Tech Research Corporation
Atlanta, Georgia 30332
PROJECT A-8503-405
AUTHORS
18 Jun 1991 Jeffrey P. Murray
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
FILE ROUTINE CALLED
@ -35,59 +31,47 @@ INTERFACES
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
27 Sept 1991 Jeffrey P. Murray
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
FILE ROUTINE CALLED
N/A N/A
RETURNED VALUE
No returned value. Passed pointer to variable is used
to redefine the variable value.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
@ -95,10 +79,11 @@ NON-STANDARD FEATURES
===============================================================================*/
#include "ngspice/inertial.h"
/*=== CM_TOGGLE_BIT ROUTINE ===*/
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
@ -112,7 +97,6 @@ static void cm_toggle_bit(Digital_State_t *bit)
*bit = ONE;
}
}
}
@ -182,114 +166,124 @@ void cm_d_xor(ARGS)
Digital_State_t *out, /* temporary output for buffers */
*out_old, /* previous output for buffers */
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 */
/* 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 */
cm_toggle_bit(&val);
} else {
/* if an unknown input, set val to unknown & break */
if ( UNKNOWN == input ) {
*out = UNKNOWN;
val = UNKNOWN;
break;
}
}
}
else {
/* at least one port is floating...output is unknown */
*out = UNKNOWN;
break;
}
}
/*** Check for change and output appropriate values ***/
/*** 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 ) {
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
/* fall to zero value */
case 0: OUTPUT_STATE(out) = ZERO;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
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;
}
}
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;
}
}

View File

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