349 lines
8.3 KiB
C
349 lines
8.3 KiB
C
/*============================================================================
|
|
FILE IDNdig.c
|
|
|
|
MEMBER OF process XSPICE
|
|
|
|
Copyright 1991
|
|
Georgia Tech Research Corporation
|
|
Atlanta, Georgia 30332
|
|
All Rights Reserved
|
|
|
|
PROJECT A-8503
|
|
|
|
AUTHORS
|
|
|
|
9/12/91 Bill Kuhn
|
|
|
|
MODIFICATIONS
|
|
|
|
<date> <person name> <nature of modifications>
|
|
|
|
SUMMARY
|
|
|
|
This file contains the definition of the 'digital' node type
|
|
used by 12-state digital models in the code model library.
|
|
These functions are called exclusively through function
|
|
pointers in an Evt_Udn_Info_t data structure.
|
|
|
|
INTERFACES
|
|
|
|
Evt_Udn_Info_t idn_digital_info
|
|
|
|
REFERENCED FILES
|
|
|
|
None.
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
None.
|
|
|
|
============================================================================*/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
|
|
#include "ngspice/cm.h"
|
|
|
|
#include "ngspice/evtudn.h"
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_create(void **evt_struct)
|
|
{
|
|
/* Malloc space for a digital struct */
|
|
|
|
*evt_struct = TMALLOC(Digital_t, 1);
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_dismantle(void *evt_struct)
|
|
{
|
|
NG_IGNORE(evt_struct);
|
|
|
|
/* Do nothing. There are no internally malloc'ed things to dismantle */
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_initialize(void *evt_struct)
|
|
{
|
|
Digital_t *dig_struct = (Digital_t *) evt_struct;
|
|
|
|
|
|
/* Initialize to unknown state and strength */
|
|
dig_struct->state = ZERO;
|
|
dig_struct->strength = UNDETERMINED;
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_invert(void *evt_struct)
|
|
{
|
|
Digital_t *dig_struct = (Digital_t *) evt_struct;
|
|
|
|
|
|
/* Invert the state */
|
|
switch(dig_struct->state) {
|
|
|
|
case ZERO:
|
|
dig_struct->state = ONE;
|
|
return;
|
|
|
|
case ONE:
|
|
dig_struct->state = ZERO;
|
|
return;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_copy(void *evt_from_struct, void *evt_to_struct)
|
|
{
|
|
Digital_t *dig_from_struct = (Digital_t *) evt_from_struct;
|
|
Digital_t *dig_to_struct = (Digital_t *) evt_to_struct;
|
|
|
|
/* Copy the structure */
|
|
dig_to_struct->state = dig_from_struct->state;
|
|
dig_to_struct->strength = dig_from_struct->strength;
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_resolve(int num_struct,
|
|
void **evt_struct_array, void *evt_struct)
|
|
{
|
|
Digital_t **dig_struct_array;
|
|
Digital_t *dig_struct;
|
|
|
|
static int map[12][12] = {
|
|
{ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2},
|
|
{ 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1},
|
|
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
|
|
{ 0, 1, 2, 3, 5, 5, 3, 3, 3, 9, 11, 11},
|
|
{ 0, 1, 2, 5, 4, 5, 4, 4, 4, 11, 10, 11},
|
|
{ 0, 1, 2, 5, 5, 5, 5, 5, 5, 10, 11, 11},
|
|
{ 0, 1, 2, 3, 4, 5, 6, 8, 8, 9, 11, 11},
|
|
{ 0, 1, 2, 3, 4, 5, 8, 7, 8, 11, 10, 11},
|
|
{ 0, 1, 2, 3, 4, 5, 8, 8, 8, 11, 11, 11},
|
|
{ 0, 2, 2, 9, 11, 11, 9, 11, 11, 9, 11, 11},
|
|
{ 2, 1, 2, 11, 10, 11, 11, 10, 11, 11, 10, 11},
|
|
{ 2, 1, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11} };
|
|
|
|
int i;
|
|
|
|
int index1;
|
|
int index2;
|
|
|
|
/* Cast the input void pointers to pointers of the digital type */
|
|
dig_struct = (Digital_t *) evt_struct;
|
|
dig_struct_array = (Digital_t **)evt_struct_array;
|
|
|
|
/* Copy the first member of the array directly to the output */
|
|
dig_struct->state = dig_struct_array[0]->state;
|
|
dig_struct->strength = dig_struct_array[0]->strength;
|
|
|
|
/* Convert struct to index into map */
|
|
index1 = (int) (dig_struct->state + dig_struct->strength * 3);
|
|
|
|
|
|
/* For the remaining members, perform the resolution algorithm */
|
|
for(i = 1; i < num_struct; i++) {
|
|
|
|
/* Convert struct to index into map */
|
|
index2 = (int)(dig_struct_array[i]->state +
|
|
dig_struct_array[i]->strength * 3);
|
|
|
|
/* Compute the result */
|
|
index1 = map[index1][index2];
|
|
}
|
|
|
|
/* Convert result back to state and strength */
|
|
dig_struct->state = (Digital_State_t) (index1 % 3);
|
|
dig_struct->strength = (Digital_Strength_t) (index1 / 3);
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_compare(void *evt_struct1, void *evt_struct2,
|
|
Boolean_t *equal)
|
|
{
|
|
Digital_t *dig_struct1 = (Digital_t *) evt_struct1;
|
|
Digital_t *dig_struct2 = (Digital_t *) evt_struct2;
|
|
|
|
/* Compare the structures in order of most likely differences */
|
|
if(dig_struct1->state != dig_struct2->state)
|
|
*equal = FALSE;
|
|
else if(dig_struct1->strength != dig_struct2->strength)
|
|
*equal = FALSE;
|
|
else
|
|
*equal = TRUE;
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_plot_val(void *evt_struct, char *member, double *val)
|
|
{
|
|
Digital_t *dig_struct = (Digital_t *) evt_struct;
|
|
|
|
|
|
/* Output a value for the requested member of the digital struct */
|
|
if(strcmp(member,"strength") == 0) {
|
|
|
|
/* Choose values that will not make plots lie on state plots */
|
|
switch(dig_struct->strength) {
|
|
|
|
case STRONG:
|
|
*val = 0.1;
|
|
return;
|
|
|
|
case RESISTIVE:
|
|
*val = 0.6;
|
|
return;
|
|
|
|
case HI_IMPEDANCE:
|
|
*val = 1.1;
|
|
return;
|
|
|
|
case UNDETERMINED:
|
|
*val = -0.4;
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
/* member = "state" or anything else */
|
|
|
|
/* Pick reasonable values */
|
|
switch(dig_struct->state) {
|
|
|
|
case ZERO:
|
|
*val = 0.0;
|
|
return;
|
|
|
|
case ONE:
|
|
*val = 1.0;
|
|
return;
|
|
|
|
case UNKNOWN:
|
|
*val = 0.5;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_print_val(void *evt_struct, char *member, char **val)
|
|
{
|
|
Digital_t *dig_struct = (Digital_t *) evt_struct;
|
|
|
|
int index;
|
|
|
|
static char *map[] = { "0s", "1s", "Us",
|
|
"0r", "1r", "Ur",
|
|
"0z", "1z", "Uz",
|
|
"0u", "1u", "Uu" };
|
|
|
|
|
|
/* Output a value for the requested member of the digital struct */
|
|
|
|
if(strcmp(member,"state") == 0) {
|
|
|
|
/* Pick reasonable values */
|
|
switch(dig_struct->state) {
|
|
|
|
case ZERO:
|
|
*val = "0";
|
|
return;
|
|
|
|
case ONE:
|
|
*val = "1";
|
|
return;
|
|
|
|
case UNKNOWN:
|
|
*val = "U";
|
|
return;
|
|
|
|
default:
|
|
*val = "?";
|
|
return;
|
|
}
|
|
}
|
|
else if(strcmp(member,"strength") == 0) {
|
|
|
|
/* Choose values that will not make plots lie on state plots */
|
|
switch(dig_struct->strength) {
|
|
|
|
case STRONG:
|
|
*val = "s";
|
|
return;
|
|
|
|
case RESISTIVE:
|
|
*val = "r";
|
|
return;
|
|
|
|
case HI_IMPEDANCE:
|
|
*val = "z";
|
|
return;
|
|
|
|
case UNDETERMINED:
|
|
*val = "u";
|
|
return;
|
|
|
|
default:
|
|
*val = "?";
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
index = (int)(dig_struct->state + dig_struct->strength * 3);
|
|
if((index < 0) || (index > 11))
|
|
*val = "??";
|
|
else
|
|
*val = map[index];
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************ */
|
|
|
|
static void idn_digital_ipc_val(void *evt_struct, void **ipc_val, int *ipc_val_size)
|
|
{
|
|
/* Return the digital data structure and its size */
|
|
*ipc_val = evt_struct;
|
|
*ipc_val_size = sizeof(Digital_t);
|
|
}
|
|
|
|
|
|
|
|
Evt_Udn_Info_t idn_digital_info = {
|
|
|
|
"d",
|
|
"12 state digital data",
|
|
idn_digital_create,
|
|
idn_digital_dismantle,
|
|
idn_digital_initialize,
|
|
idn_digital_invert,
|
|
idn_digital_copy,
|
|
idn_digital_resolve,
|
|
idn_digital_compare,
|
|
idn_digital_plot_val,
|
|
idn_digital_print_val,
|
|
idn_digital_ipc_val
|
|
|
|
};
|
|
|