/*.......1.........2.........3.........4.........5.........6.........7.........8 ================================================================================ FILE d_buffer/cfunc.mod Public Domain Georgia Tech Research Corporation Atlanta, Georgia 30332 PROJECT A-8503-405 AUTHORS 14 June 1991 Jeffrey P. Murray 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 NONE ===============================================================================*/ /*=== INCLUDE FILES ====================*/ #include "ngspice/inertial.h" /*=== CONSTANTS ========================*/ /*=== MACROS ===========================*/ /*=== LOCAL VARIABLES & TYPEDEFS =======*/ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ /*============================================================================== FUNCTION cm_d_buffer() AUTHORS 14 Jun 1991 Jeffrey P. Murray MODIFICATIONS 27 Sep 1991 Jeffrey P. Murray SUMMARY This function implements the d_buffer code model. INTERFACES 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 NONE ==============================================================================*/ /*=== CM_D_BUFFER ROUTINE ===*/ /************************************************ * The following is the model for the * * digital buffer for the * * ATESSE Version 2.0 system. * * * * Created 6/14/91 J.P,Murray * ************************************************/ void cm_d_buffer(ARGS) { Digital_State_t val, /* Output value. */ *out; /* Previous value */ /** Setup required state variables **/ 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 = (Digital_State_t *) cm_event_get_ptr(0,0); } val = INPUT_STATE(in); if (val == *out) { /* output value 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. */ 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; } }