You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
827 lines
27 KiB
827 lines
27 KiB
/* $Id$ */
|
|
/*.......1.........2.........3.........4.........5.........6.........7.........8
|
|
================================================================================
|
|
|
|
FILE <model_name>/cfunc.mod
|
|
|
|
Copyright 1991
|
|
Georgia Tech Research Corporation, Atlanta, Ga. 30332
|
|
All Rights Reserved
|
|
|
|
PROJECT A-8503-405
|
|
|
|
|
|
AUTHORS
|
|
|
|
25 Jun 1991 Jeffrey P. Murray
|
|
|
|
MODIFICATIONS
|
|
|
|
13 Aug 1991 Jeffrey P. Murray
|
|
30 Sep 1991 Jeffrey P. Murray
|
|
29 Jan 1992 Jeffrey P. Murray
|
|
|
|
SUMMARY
|
|
|
|
This file contains the model-specific routines used to
|
|
functionally describe the <model_name> code model.
|
|
|
|
|
|
INTERFACES
|
|
|
|
FILE ROUTINE CALLED
|
|
|
|
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
|
|
|
|
===============================================================================*/
|
|
|
|
/*=== INCLUDE FILES ====================*/
|
|
|
|
|
|
|
|
|
|
/*=== CONSTANTS ========================*/
|
|
|
|
|
|
|
|
|
|
/*=== MACROS ===========================*/
|
|
|
|
|
|
|
|
|
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
|
|
|
|
|
|
|
|
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*==============================================================================
|
|
|
|
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
|
|
|
|
|
|
===============================================================================*/
|
|
|
|
/*=== 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
|
|
without changing the bit value. */
|
|
|
|
if ( UNKNOWN != *bit ) {
|
|
if ( ONE == *bit ) {
|
|
*bit = ZERO;
|
|
}
|
|
else {
|
|
*bit = ONE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*==============================================================================
|
|
|
|
FUNCTION cm_eval_sr_result
|
|
|
|
AUTHORS
|
|
|
|
30 Sept 1991 Jeffrey P. Murray
|
|
|
|
MODIFICATIONS
|
|
|
|
NONE
|
|
|
|
SUMMARY
|
|
|
|
Evaluates the S and R input states, plus the last state of
|
|
the latch, and returns the expected output value.
|
|
|
|
INTERFACES
|
|
|
|
FILE ROUTINE CALLED
|
|
|
|
CMutil.c void cm_toggle_bit();
|
|
|
|
|
|
RETURNED VALUE
|
|
|
|
A Digital_State_t.
|
|
|
|
GLOBAL VARIABLES
|
|
|
|
NONE
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
NONE
|
|
|
|
==============================================================================*/
|
|
|
|
/*=== CM_EVAL_SR_RESULT ROUTINE ===*/
|
|
|
|
static Digital_State_t cm_eval_sr_result(Digital_State_t s_input,
|
|
Digital_State_t r_input,
|
|
Digital_State_t old_output)
|
|
{
|
|
Digital_State_t output;
|
|
|
|
|
|
switch (s_input) {
|
|
|
|
case ZERO:
|
|
switch (r_input) {
|
|
case ZERO:
|
|
output = old_output;
|
|
break;
|
|
case ONE:
|
|
output = ZERO;
|
|
break;
|
|
case UNKNOWN:
|
|
output = UNKNOWN;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ONE:
|
|
switch (r_input) {
|
|
case ZERO:
|
|
output = ONE;
|
|
break;
|
|
case ONE:
|
|
output = UNKNOWN;
|
|
break;
|
|
case UNKNOWN:
|
|
output = UNKNOWN;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case UNKNOWN:
|
|
output = UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*==============================================================================
|
|
|
|
FUNCTION cm_d_srlatch()
|
|
|
|
AUTHORS
|
|
|
|
25 Jun 1991 Jeffrey P. Murray
|
|
|
|
MODIFICATIONS
|
|
|
|
13 Aug 1991 Jeffrey P. Murray
|
|
30 Sep 1991 Jeffrey P. Murray
|
|
29 Jan 1992 Jeffrey P. Murray
|
|
|
|
SUMMARY
|
|
|
|
This function implements the d_srlatch code model.
|
|
|
|
INTERFACES
|
|
|
|
FILE ROUTINE CALLED
|
|
|
|
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_SRLATCH ROUTINE ===*/
|
|
|
|
/************************************************
|
|
* The following is the model for the *
|
|
* digital sr-type latch for the *
|
|
* ATESSE Version 2.0 system. *
|
|
* *
|
|
* Created 6/25/91 J.P.Murray *
|
|
************************************************/
|
|
|
|
|
|
void cm_d_srlatch(ARGS)
|
|
|
|
{
|
|
int i; /* generic loop counter index */
|
|
|
|
|
|
Digital_State_t *s, /* current s-input value */
|
|
*s_old, /* previous s-input value */
|
|
*r, /* current r-input value */
|
|
*r_old, /* previous r-input value */
|
|
*enable, /* current enable value */
|
|
*enable_old, /* previous enable value */
|
|
*set, /* current set value for srlatch */
|
|
*set_old, /* previous set value for srlatch */
|
|
*reset, /* current reset value for srlatch */
|
|
*reset_old, /* previous reset value for srlatch */
|
|
*out, /* current output for srlatch */
|
|
*out_old, /* previous output for srlatch */
|
|
|
|
temp; /* temp storage for state values */
|
|
|
|
|
|
|
|
/*** Setup required state variables ***/
|
|
|
|
if(INIT) { /* initial pass */
|
|
|
|
/* allocate storage */
|
|
s = s_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t));
|
|
r = r_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t));
|
|
enable = enable_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t));
|
|
set = set_old = (Digital_State_t *) cm_event_alloc(3,sizeof(Digital_State_t));
|
|
reset = reset_old = (Digital_State_t *) cm_event_alloc(4,sizeof(Digital_State_t));
|
|
out = out_old = (Digital_State_t *) cm_event_alloc(5,sizeof(Digital_State_t));
|
|
|
|
/* declare load values */
|
|
LOAD(s) = PARAM(sr_load);
|
|
LOAD(r) = PARAM(sr_load);
|
|
LOAD(enable) = PARAM(enable_load);
|
|
if ( !PORT_NULL(set) ) {
|
|
LOAD(set) = PARAM(set_load);
|
|
}
|
|
if ( !PORT_NULL(reset) ) {
|
|
LOAD(reset) = PARAM(reset_load);
|
|
}
|
|
|
|
}
|
|
else { /* Retrieve previous values */
|
|
|
|
/* retrieve storage for the outputs */
|
|
s = (Digital_State_t *) cm_event_get_ptr(0,0);
|
|
s_old = (Digital_State_t *) cm_event_get_ptr(0,1);
|
|
r = (Digital_State_t *) cm_event_get_ptr(1,0);
|
|
r_old = (Digital_State_t *) cm_event_get_ptr(1,1);
|
|
enable = (Digital_State_t *) cm_event_get_ptr(2,0);
|
|
enable_old = (Digital_State_t *) cm_event_get_ptr(2,1);
|
|
set = (Digital_State_t *) cm_event_get_ptr(3,0);
|
|
set_old = (Digital_State_t *) cm_event_get_ptr(3,1);
|
|
reset = (Digital_State_t *) cm_event_get_ptr(4,0);
|
|
reset_old = (Digital_State_t *) cm_event_get_ptr(4,1);
|
|
out = (Digital_State_t *) cm_event_get_ptr(5,0);
|
|
out_old = (Digital_State_t *) cm_event_get_ptr(5,1);
|
|
}
|
|
|
|
|
|
|
|
/******* load current input values if set or reset
|
|
are not connected, set to zero... *******/
|
|
*s = INPUT_STATE(s);
|
|
*r = INPUT_STATE(r);
|
|
*enable = INPUT_STATE(enable);
|
|
if ( PORT_NULL(set) ) {
|
|
*set = *set_old = ZERO;
|
|
}
|
|
else {
|
|
*set = INPUT_STATE(set);
|
|
}
|
|
if ( PORT_NULL(reset) ) {
|
|
*reset = *reset_old = ZERO;
|
|
}
|
|
else {
|
|
*reset = INPUT_STATE(reset);
|
|
}
|
|
|
|
|
|
|
|
|
|
/******* Determine analysis type and output appropriate values *******/
|
|
|
|
if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/
|
|
|
|
temp = PARAM(ic);
|
|
|
|
/** Modify output if set or reset lines are active **/
|
|
if ( (*enable==ONE) && (*s==ONE) && (*r==ZERO) ) temp = ONE;
|
|
if ( (*enable==ONE) && (*s==ZERO) && (*r==ONE) ) temp = ZERO;
|
|
if ( (*set==ONE) && (*reset==ZERO) ) temp = ONE;
|
|
if ( (*set==ZERO) && (*reset==ONE) ) temp = ZERO;
|
|
if ( (*set==ONE) && (*reset==ONE) ) temp = UNKNOWN;
|
|
|
|
*out = *out_old = temp;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = temp;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
cm_toggle_bit(&temp);
|
|
OUTPUT_STATE(Nout) = temp;
|
|
}
|
|
}
|
|
|
|
else { /****** Transient Analysis ******/
|
|
|
|
|
|
/***** Find input that has changed... *****/
|
|
|
|
/**** Test set value for change ****/
|
|
if ( *set != *set_old ) { /* either set or set release */
|
|
switch ( *set ) {
|
|
|
|
case ONE:
|
|
if ( ONE != *reset) {
|
|
if (*out_old != ONE) { /* set will change output */
|
|
*out = ONE;
|
|
|
|
/* output goes to ONE */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = ONE;
|
|
OUTPUT_DELAY(out) = PARAM(set_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = ZERO;
|
|
OUTPUT_DELAY(Nout) = PARAM(set_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already set */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (*out_old != UNKNOWN) { /* set will change output */
|
|
*out = UNKNOWN;
|
|
|
|
/* output goes to UNKNOWN */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = UNKNOWN;
|
|
OUTPUT_DELAY(out) = PARAM(set_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = UNKNOWN;
|
|
OUTPUT_DELAY(Nout) = PARAM(set_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already unknown */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ZERO:
|
|
case UNKNOWN:
|
|
if ( ONE != *reset) {
|
|
if ( ONE == *enable ) {
|
|
/* active level...save & output current value */
|
|
temp = cm_eval_sr_result(*s,*r,*out_old);
|
|
|
|
if (*out_old != temp) { /* enable will change output */
|
|
*out = temp;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = temp;
|
|
OUTPUT_DELAY(out) = PARAM(set_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
cm_toggle_bit(&temp);
|
|
OUTPUT_STATE(Nout) = temp;
|
|
OUTPUT_DELAY(Nout) = PARAM(set_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output same as before */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* output remains at current value */
|
|
*out = *out_old;
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (*out_old != ZERO) { /* set will change output */
|
|
/* output returns to reset condition */
|
|
*out = ZERO;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = ZERO;
|
|
OUTPUT_DELAY(out) = PARAM(set_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = ONE;
|
|
OUTPUT_DELAY(Nout) = PARAM(set_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already reset */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
else {
|
|
|
|
/**** Test reset value for change ****/
|
|
if ( *reset != *reset_old ) { /* either reset or reset release */
|
|
switch ( *reset ) {
|
|
|
|
case ONE:
|
|
if ( ONE != *set) {
|
|
if (*out_old != ZERO) { /* reset will change output */
|
|
/* output goes to ZERO */
|
|
*out = ZERO;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = ZERO;
|
|
OUTPUT_DELAY(out) = PARAM(reset_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = ONE;
|
|
OUTPUT_DELAY(Nout) = PARAM(reset_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already reset */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (*out_old != UNKNOWN) { /* reset will change output */
|
|
/* output goes to UNKNOWN */
|
|
*out = UNKNOWN;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = UNKNOWN;
|
|
OUTPUT_DELAY(out) = PARAM(reset_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = UNKNOWN;
|
|
OUTPUT_DELAY(Nout) = PARAM(reset_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already unknown */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ZERO:
|
|
case UNKNOWN:
|
|
if ( ONE != *set) {
|
|
if ( ONE == *enable ) {
|
|
/* active level...save & output current value */
|
|
temp = cm_eval_sr_result(*s,*r,*out_old);
|
|
|
|
if (*out_old != temp) { /* enable will change output */
|
|
*out = temp;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = temp;
|
|
OUTPUT_DELAY(out) = PARAM(reset_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
cm_toggle_bit(&temp);
|
|
OUTPUT_STATE(Nout) = temp;
|
|
OUTPUT_DELAY(Nout) = PARAM(reset_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output same as before */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* output remains at current value */
|
|
*out = *out_old;
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (*out_old != ONE) { /* reset will change output */
|
|
/* output returns to set condition */
|
|
*out = ONE;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = ONE;
|
|
OUTPUT_DELAY(out) = PARAM(reset_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STATE(Nout) = ZERO;
|
|
OUTPUT_DELAY(Nout) = PARAM(reset_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output already reset */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
|
|
/**** Test for enable change... ****/
|
|
if ( (*enable != *enable_old) && (*reset != ONE) &&
|
|
(*set != ONE) ) { /* enable or enable release */
|
|
switch ( *enable ) {
|
|
|
|
case ONE:
|
|
/* active edge...save & output current data value */
|
|
temp = cm_eval_sr_result(*s,*r,*out_old);
|
|
|
|
if (*out_old != temp) { /* enable will change output */
|
|
*out = temp;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = temp;
|
|
OUTPUT_DELAY(out) = PARAM(enable_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
cm_toggle_bit(&temp);
|
|
OUTPUT_STATE(Nout) = temp;
|
|
OUTPUT_DELAY(Nout) = PARAM(enable_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output same as before */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ZERO:
|
|
case UNKNOWN:
|
|
/* inactive edge...return previous values */
|
|
*out = *out_old;
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
else { /* test data value for change... */
|
|
|
|
if ( ((*s != *s_old) || (*r != *r_old)) &&
|
|
(*reset != ONE) && (*set != ONE) ) {
|
|
/* input values have changed...
|
|
test enable, and if active, update
|
|
the output...else return w/o change. */
|
|
switch ( *enable ) {
|
|
|
|
case ONE:
|
|
/* active level...save & output current data value */
|
|
temp = cm_eval_sr_result(*s,*r,*out_old);
|
|
|
|
if (*out_old != temp) { /* enable will change output */
|
|
*out = temp;
|
|
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STATE(out) = temp;
|
|
OUTPUT_DELAY(out) = PARAM(sr_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
cm_toggle_bit(&temp);
|
|
OUTPUT_STATE(Nout) = temp;
|
|
OUTPUT_DELAY(Nout) = PARAM(sr_delay);
|
|
}
|
|
}
|
|
else {
|
|
*out = *out_old; /* output same as before */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ZERO:
|
|
case UNKNOWN:
|
|
/* inactive level...return previous values */
|
|
*out = *out_old;
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else { /* nothing has changed!!! This shouldn't happen! */
|
|
*out = *out_old;
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_CHANGED(out) = FALSE;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_CHANGED(Nout) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***** Add additional rise or fall delays, if appropriate *****/
|
|
|
|
if ( *out != *out_old ) { /*** output value is changing ***/
|
|
|
|
switch ( *out ) {
|
|
|
|
/** fall to zero value **/
|
|
case 0:
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_DELAY(out) += PARAM(fall_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_DELAY(Nout) += PARAM(rise_delay);
|
|
}
|
|
break;
|
|
|
|
/** rise to one value **/
|
|
case 1:
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_DELAY(out) += PARAM(rise_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_DELAY(Nout) += PARAM(fall_delay);
|
|
}
|
|
break;
|
|
|
|
/** unknown output **/
|
|
default:
|
|
/* based on old value, add rise or fall delay */
|
|
if (0 == *out_old) { /* add rising delay */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_DELAY(out) += PARAM(rise_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_DELAY(Nout) += PARAM(fall_delay);
|
|
}
|
|
}
|
|
else { /* add falling delay */
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_DELAY(out) += PARAM(fall_delay);
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_DELAY(Nout) += PARAM(rise_delay);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*** output strength values ***/
|
|
if ( !PORT_NULL(out) ) {
|
|
OUTPUT_STRENGTH(out) = STRONG;
|
|
}
|
|
if ( !PORT_NULL(Nout) ) {
|
|
OUTPUT_STRENGTH(Nout) = STRONG;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|