Browse Source

First group of digital code models with improved implementation

of inertial delay: buffer, inverter, and, nor.  Also adds
utility function cm_is_inertial(().
pre-master-46
Giles Atkinson 3 years ago
committed by Holger Vogt
parent
commit
e3b4df6a51
  1. 176
      src/xspice/icm/digital/d_and/cfunc.mod
  2. 36
      src/xspice/icm/digital/d_and/ifspec.ifs
  3. 133
      src/xspice/icm/digital/d_buffer/cfunc.mod
  4. 31
      src/xspice/icm/digital/d_buffer/ifspec.ifs
  5. 168
      src/xspice/icm/digital/d_inverter/cfunc.mod
  6. 19
      src/xspice/icm/digital/d_inverter/ifspec.ifs
  7. 163
      src/xspice/icm/digital/d_nor/cfunc.mod
  8. 36
      src/xspice/icm/digital/d_nor/ifspec.ifs
  9. 22
      src/xspice/icm/dlmain.c

176
src/xspice/icm/digital/d_and/cfunc.mod

@ -14,31 +14,25 @@ AUTHORS
14 June 1991 Jeffrey P. Murray 14 June 1991 Jeffrey P. Murray
MODIFICATIONS MODIFICATIONS
27 Sept 1991 Jeffrey P. Murray 27 Sept 1991 Jeffrey P. Murray
SUMMARY SUMMARY
This file contains the functional description of the d_and This file contains the functional description of the d_and
code model. code model.
INTERFACES INTERFACES
FILE ROUTINE CALLED FILE ROUTINE CALLED
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
@ -53,29 +47,16 @@ NON-STANDARD FEATURES
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/ /*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/ /*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ /*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*============================================================================== /*==============================================================================
FUNCTION cm_d_and() FUNCTION cm_d_and()
@ -94,13 +75,13 @@ SUMMARY
INTERFACES INTERFACES
FILE ROUTINE CALLED
FILE ROUTINE CALLED
CMevt.c void *cm_event_alloc() CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr() void *cm_event_get_ptr()
RETURNED VALUE RETURNED VALUE
Returns inputs and outputs via ARGS structure. Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES GLOBAL VARIABLES
@ -123,124 +104,123 @@ NON-STANDARD FEATURES
* Created 6/14/91 J.P.Murray * * Created 6/14/91 J.P.Murray *
************************************************/ ************************************************/
void cm_d_and(ARGS) void cm_d_and(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 *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 */ 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));
/* set loading for inputs */
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);
/* Inertial delay? */
}
else { /* Retrieve previous values */
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 */ /* 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 = ONE;
val = ONE;
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
/* if a 0, set val low */
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 0, set *out low */
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
*out = ZERO;
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;
if ( ZERO == (input = INPUT_STATE(in[i])) ) {
val = ZERO;
break; break;
} else {
/* if an unknown input, set val to unknown & break */
if ( UNKNOWN == input )
val = UNKNOWN;
} }
}
/*** Determine analysis type and output appropriate values ***/
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/
OUTPUT_STATE(out) = *out;
} }
else { /** Transient Analysis **/
/*** Check for change and output appropriate values ***/
if (val == *out) { /* output value is not changing */
OUTPUT_CHANGED(out) = FALSE;
} else { /* output value not changing */
switch (val) {
if ( *out != *out_old ) { /* output value is changing */
switch ( *out ) {
/* fall to zero value */ /* fall to zero value */
case 0: OUTPUT_STATE(out) = ZERO;
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */ /* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
/* unknown output */ /* unknown output */
default:
OUTPUT_STATE(out) = *out = UNKNOWN;
default:
OUTPUT_STATE(out) = UNKNOWN;
/* based on old value, add rise or fall delay */
if (0 == *out_old) { /* add rising delay */
OUTPUT_DELAY(out) = PARAM(rise_delay);
}
else { /* add falling delay */
OUTPUT_DELAY(out) = PARAM(fall_delay);
}
break;
/* 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;
} }
else { /* output value not changing */
OUTPUT_CHANGED(out) = FALSE;
}
}
OUTPUT_STRENGTH(out) = STRONG;
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);
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;
}
} }

36
src/xspice/icm/digital/d_and/ifspec.ifs

@ -33,8 +33,8 @@ Description: "input" "output"
Direction: in out Direction: in out
Default_Type: d d Default_Type: d d
Allowed_Types: [d] [d] Allowed_Types: [d] [d]
Vector: yes no
Vector_Bounds: [2 -] -
Vector: yes no
Vector_Bounds: [2 -] -
Null_Allowed: no no Null_Allowed: no no
@ -52,12 +52,28 @@ Null_Allowed: yes yes
PARAMETER_TABLE: PARAMETER_TABLE:
Parameter_Name: input_load
Description: "input load value (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
Parameter_Name: input_load 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"

133
src/xspice/icm/digital/d_buffer/cfunc.mod

@ -9,36 +9,29 @@ Georgia Tech Research Corporation
Atlanta, Georgia 30332 Atlanta, Georgia 30332
PROJECT A-8503-405 PROJECT A-8503-405
AUTHORS AUTHORS
14 June 1991 Jeffrey P. Murray 14 June 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
27 Sept 1991 Jeffrey P. Murray 27 Sept 1991 Jeffrey P. Murray
SUMMARY SUMMARY
This file contains the functional description of the d_buffer This file contains the functional description of the d_buffer
code model. code model.
INTERFACES INTERFACES
FILE ROUTINE CALLED FILE ROUTINE CALLED
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
@ -48,39 +41,25 @@ 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_buffer() FUNCTION cm_d_buffer()
AUTHORS
AUTHORS
14 Jun 1991 Jeffrey P. Murray 14 Jun 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
27 Sep 1991 Jeffrey P. Murray 27 Sep 1991 Jeffrey P. Murray
@ -88,7 +67,7 @@ SUMMARY
This function implements the d_buffer code model. This function implements the d_buffer code model.
INTERFACES
INTERFACES
FILE ROUTINE CALLED FILE ROUTINE CALLED
@ -96,7 +75,7 @@ INTERFACES
void *cm_event_get_ptr() void *cm_event_get_ptr()
RETURNED VALUE RETURNED VALUE
Returns inputs and outputs via ARGS structure. Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES GLOBAL VARIABLES
@ -119,78 +98,94 @@ NON-STANDARD FEATURES
* Created 6/14/91 J.P,Murray * * Created 6/14/91 J.P,Murray *
************************************************/ ************************************************/
void cm_d_buffer(ARGS)
void cm_d_buffer(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, /* Output value. */
*out; /* Previous value */
/** 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.
/* define input loading... */ /* define input loading... */
LOAD(in) = PARAM(input_load); LOAD(in) = 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);
} }
/** Check on analysis type **/
if (ANALYSIS == DC) { /* DC analysis...output w/o delays */
OUTPUT_STATE(out) = *out = INPUT_STATE(in);
val = INPUT_STATE(in);
if (val == *out) {
/* output value not changing */
}
else { /* Transient Analysis */
OUTPUT_CHANGED(out) = FALSE;
} else {
switch (val) {
switch ( INPUT_STATE(in) ) {
/* fall to zero value */ /* fall to zero value */
case 0: OUTPUT_STATE(out) = *out = ZERO;
OUTPUT_DELAY(out) = PARAM(fall_delay);
case 0: OUTPUT_DELAY(out) = PARAM(fall_delay);
break; break;
/* rise to one value */ /* rise to one value */
case 1: OUTPUT_STATE(out) = *out = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
case 1: 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;
} }
}
OUTPUT_STRENGTH(out) = STRONG;
}
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);
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;
}
}

31
src/xspice/icm/digital/d_buffer/ifspec.ifs

@ -48,15 +48,30 @@ Vector: no no
Vector_Bounds: - - Vector_Bounds: - -
Null_Allowed: yes yes Null_Allowed: yes yes
PARAMETER_TABLE:
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_TABLE:
Parameter_Name: input_load
Description: "input load value (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
Parameter_Name: 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"

168
src/xspice/icm/digital/d_inverter/cfunc.mod

@ -8,36 +8,31 @@ Public Domain
Georgia Tech Research Corporation Georgia Tech Research Corporation
Atlanta, Georgia 30332 Atlanta, Georgia 30332
PROJECT A-8503-405 PROJECT A-8503-405
AUTHORS
AUTHORS
14 Jun 1991 Jeffrey P. Murray 14 Jun 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
30 Sep 1991 Jeffrey P. Murray 30 Sep 1991 Jeffrey P. Murray
a
SUMMARY SUMMARY
This file contains the functional description of the <model_name> This file contains the functional description of the <model_name>
code model. code model.
INTERFACES
INTERFACES
FILE ROUTINE CALLED
FILE ROUTINE CALLED
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
@ -52,38 +47,25 @@ NON-STANDARD FEATURES
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include "ngspice/inertial.h"
/*=== CONSTANTS ========================*/ /*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/ /*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ /*=== LOCAL VARIABLES & TYPEDEFS =======*/
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*============================================================================== /*==============================================================================
FUNCTION cm_d_inverter() FUNCTION cm_d_inverter()
AUTHORS
AUTHORS
14 Jun 1991 Jeffrey P. Murray 14 Jun 1991 Jeffrey P. Murray
MODIFICATIONS
MODIFICATIONS
30 Sep 1991 Jeffrey P. Murray 30 Sep 1991 Jeffrey P. Murray
@ -91,13 +73,12 @@ SUMMARY
This function implements the d_inverter code model. This function implements the d_inverter code model.
INTERFACES
INTERFACES
FILE ROUTINE CALLED
FILE ROUTINE CALLED
CMevt.c void *cm_event_alloc() CMevt.c void *cm_event_alloc()
void *cm_event_get_ptr() void *cm_event_get_ptr()
RETURNED VALUE RETURNED VALUE
Returns inputs and outputs via ARGS structure. Returns inputs and outputs via ARGS structure.
@ -122,92 +103,99 @@ NON-STANDARD FEATURES
* Created 6/14/91 J.P.Murray * * Created 6/14/91 J.P.Murray *
************************************************/ ************************************************/
void cm_d_inverter(ARGS) void cm_d_inverter(ARGS)
{ {
/*int i;*/ /* generic loop counter index */
Digital_State_t *out, /* temporary output for inverter */
*out_old; /* previous output for inverter */
Digital_State_t val, /* Output value. */
*out; /* Previous output. */
/** Setup required state variables **/ /** Setup required state variables **/
if(INIT) { /* initial pass */ if(INIT) { /* initial pass */
/* allocate storage for the output */
/* allocate storage for the outputs */
cm_event_alloc(0,sizeof(Digital_State_t));
cm_event_alloc(0, sizeof (Digital_State_t));
/* define load value on inputs */
LOAD(in) = PARAM(input_load);
/* Inertial delay? */
/* retrieve storage for the outputs */
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. */
}
else { /* Retrieve previous values */
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 load value on inputs */
LOAD(in) = PARAM(input_load);
} 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);
} }
/** Check on analysis type **/
val = INPUT_STATE(in);
if (val != UNKNOWN)
val = !val;
/*** Check for change and output appropriate values ***/
if (ANALYSIS == DC) { /* DC analysis...output w/o delays */
switch ( INPUT_STATE(in) ) {
if (val == *out) { /* output value is changing */
OUTPUT_CHANGED(out) = FALSE;
} else { /* output value not changing */
switch (val) {
case ZERO:
OUTPUT_STATE(out) = *out = *out_old = ONE;
/* fall to zero value */
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break; break;
case ONE:
OUTPUT_STATE(out) = *out = *out_old = ZERO;
/* rise to one value */
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break; break;
/* unknown output */
default: default:
OUTPUT_STATE(out) = *out = *out_old = UNKNOWN;
/* 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; break;
} }
}
else { /* Transient Analysis */
switch ( INPUT_STATE(in) ) {
/* fall to zero value */
case 1: OUTPUT_STATE(out) = *out = ZERO;
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */
case 0: OUTPUT_STATE(out) = *out = ONE;
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 */
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;
OUTPUT_STRENGTH(out) = STRONG;
}
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);
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;
}
}

19
src/xspice/icm/digital/d_inverter/ifspec.ifs

@ -50,6 +50,18 @@ Vector_Bounds: - -
Null_Allowed: yes yes Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: inertial_delay family
Description: "swallow short pulses" "Logic family for bridging"
Data_Type: boolean string
Default_Value: false -
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE: PARAMETER_TABLE:
Parameter_Name: input_load Parameter_Name: input_load
@ -61,3 +73,10 @@ 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"

163
src/xspice/icm/digital/d_nor/cfunc.mod

@ -48,29 +48,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_nor() FUNCTION cm_d_nor()
@ -119,126 +110,120 @@ NON-STANDARD FEATURES
* Created 6/18/91 J.P.Murray * * Created 6/18/91 J.P.Murray *
************************************************/ ************************************************/
void cm_d_nor(ARGS) void cm_d_nor(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 *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 */ 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));
for (i=0; i<size; i++) LOAD(in[i]) = 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? */
}
else { /* Retrieve previous values */
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 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 = ONE;
val = ONE;
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
/* If a 1, set val low, and done. */
/* make sure this input isn't floating... */
if ( FALSE == PORT_NULL(in) ) {
/* if a 1, set *out low */
if ( ONE == (input = INPUT_STATE(in[i])) ) {
*out = ZERO;
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;
if ( ONE == (input = INPUT_STATE(in[i])) ) {
val = ZERO;
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 */
OUTPUT_CHANGED(out) = FALSE;
} else { /* output value not changing */
switch (val) {
/*** 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 ) {
/* fall to zero value */ /* fall to zero value */
case 0: OUTPUT_STATE(out) = ZERO;
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
case 0:
OUTPUT_DELAY(out) = PARAM(fall_delay);
break;
/* rise to one value */ /* rise to one value */
case 1: OUTPUT_STATE(out) = ONE;
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
case 1:
OUTPUT_DELAY(out) = PARAM(rise_delay);
break;
/* unknown output */ /* unknown output */
default:
OUTPUT_STATE(out) = *out = UNKNOWN;
/* based on old value, add rise or fall delay */
if (0 == *out_old) { /* add rising delay */
OUTPUT_DELAY(out) = PARAM(rise_delay);
}
else { /* add falling delay */
OUTPUT_DELAY(out) = PARAM(fall_delay);
}
break;
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;
} }
else { /* output value not changing */
OUTPUT_CHANGED(out) = FALSE;
}
}
OUTPUT_STRENGTH(out) = STRONG;
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);
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;
}
}

36
src/xspice/icm/digital/d_nor/ifspec.ifs

@ -33,8 +33,8 @@ Description: "input" "output"
Direction: in out Direction: in out
Default_Type: d d Default_Type: d d
Allowed_Types: [d] [d] Allowed_Types: [d] [d]
Vector: yes no
Vector_Bounds: [2 -] -
Vector: yes no
Vector_Bounds: [2 -] -
Null_Allowed: no no Null_Allowed: no no
@ -52,12 +52,28 @@ Null_Allowed: yes yes
PARAMETER_TABLE: PARAMETER_TABLE:
Parameter_Name: input_load
Description: "input load value (pF)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
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"

22
src/xspice/icm/dlmain.c

@ -19,6 +19,7 @@
#include "ngspice/dllitf.h" #include "ngspice/dllitf.h"
#include "ngspice/evtudn.h" #include "ngspice/evtudn.h"
#include "ngspice/inpdefs.h" #include "ngspice/inpdefs.h"
#include "ngspice/inertial.h"
#include "cmextrn.h" #include "cmextrn.h"
#include "udnextrn.h" #include "udnextrn.h"
@ -547,3 +548,24 @@ cm_message_printf(const char *fmt, ...)
txfree(p); txfree(p);
return rv; return rv;
} }
/* Function used for inertial delay in digital logic models. */
Mif_Boolean_t cm_is_inertial(enum param_vals param)
{
int cvar;
/* Get the value of the control variable. */
if (cm_getvar("digital_delay_type", CP_NUM, &cvar, sizeof cvar)) {
if (cvar >= OVERRIDE_TRANSPORT) {
/* Parameter override. */
return cvar > OVERRIDE_TRANSPORT;
}
if (param == Not_set) // Not specified
return cvar != DEFAULT_TRANSPORT;
return param != Off;
}
return param == On;
}
Loading…
Cancel
Save