Fix the NAND and NOR variants of XSPICE code model multi_input_pwl

and add an example of its use with the E-source NAND variant.
This commit is contained in:
Giles Atkinson 2023-06-22 16:47:27 +01:00 committed by Holger Vogt
parent 3a260fd4d9
commit 576f218945
4 changed files with 94 additions and 16 deletions

View File

@ -1,4 +1,4 @@
Compare four different 4-bit full adders,
Compare five different 4-bit full adders,
made of NAND gates
Simulating for 6400ns
@ -21,3 +21,9 @@ Fully digital, event node based NAND gates
digital plotting into vcd file, display with gtkwave
Simulation time 0.27s
adder_esource
Uses the NAND variant of the E-type behavioral voltage source.
There are further variations of adder_Xspice in directory
examples/digital/auto_bridge.

View File

@ -0,0 +1,16 @@
ADDER - 4 BIT BINARY ADDER USING E-SOURCE AND GATES
* behavioral gate description
*** SUBCIRCUIT DEFINITION
.SUBCKT 74HC00 in1 in2 out NVCC NVGND vcc1={vcc} tripdt1={tripdt}
.param Rout={60*4.0/(vcc1-0.5)} ; standard output driver
E1 out20 0 nand(2) in1 0 in2 0 ({vcc / 3}, 0) ({2 * vcc / 3}, {vcc})
Rout out20 out {Rout}
.ends
.param vcc=3 tripdt=6n
.include ../adder_common.inc
.END

View File

@ -174,33 +174,81 @@ get_output( ARGS, double x )
return result;
}
static double
get_reverse_output( ARGS, double x )
{
int size = PARAM_SIZE(x);
double result = 0;
double slope = 0;
int i;
/* check if x beyond specified limits */
if ( x <= PARAM(x[0]) ) return PARAM(y[size-1]);
if ( x >= PARAM(x[size-1]) ) return PARAM(y[0]);
for ( i = 1; i < size; i++ )
if ( x > PARAM(x[i-1]) && x <= PARAM(x[i]) )
{
result = PARAM(y[size - i - 1]) + slope * (x - PARAM(x[i - 1]));
break;
}
return result;
}
void
cm_multi_input_pwl(ARGS)
{
const char* model = ( PARAM_NULL(model) == 1 ) ? "and" : PARAM(model);
const char* model = PARAM(model);
double output;
if ( ANALYSIS == TRANSIENT || ANALYSIS == DC )
{
if ( strcmp( model, "and" ) != 0 && strcmp( model, "or" ) != 0 &&
strcmp( model, "nand" ) != 0 && strcmp( model, "nor" ) != 0 )
{
fprintf( stderr, "ERROR(cm_multi_input_pwl): unknown gate model type '%s'; expecting 'and|or|nand|nor'.\n", model );
if (INIT) {
int type;
if (!strcmp(model, "and"))
type = 0;
else if (!strcmp(model, "nand"))
type = 1;
else if (!strcmp(model, "or"))
type = 2;
else if (!strcmp(model, "nor"))
type = 3;
else {
fprintf(stderr, "ERROR(cm_multi_input_pwl): unknown gate model type "
"'%s'; expecting 'and|or|nand|nor'.\n", model );
exit(-1);
}
if ( PARAM_SIZE(x) != PARAM_SIZE(y) )
{
fprintf( stderr, "ERROR(cm_multi_input_pwl): 'x' and 'y' input vectors are not the same size!\n" );
exit(-1);
}
}
STATIC_VAR(type) = type;
if ( PARAM_SIZE(x) != PARAM_SIZE(y) ) {
fprintf(stderr, "ERROR(cm_multi_input_pwl): 'x' and 'y' input vectors are not the same size!\n" );
if (PARAM_SIZE(x) > PARAM_SIZE(y))
PARAM_SIZE(x) = PARAM_SIZE(y);
}
}
if ( ANALYSIS == TRANSIENT || ANALYSIS == DC ) {
/*
Iterate through each input and find output value
and/nand: controlling input is chosen on the basis of the smallest value
or/nor: controlling input is chosen on the basis of the largest value
*/
if (strstr(model, "and")) output = get_output(mif_private, get_smallest_input(mif_private));
else output = get_output(mif_private, get_largest_input(mif_private));
switch (STATIC_VAR(type)) {
case 0:
default:
output = get_output(mif_private, get_smallest_input(mif_private));
break;
case 1:
output = get_reverse_output(mif_private,
get_smallest_input(mif_private));
break;
case 2:
output = get_output(mif_private, get_largest_input(mif_private));
break;
case 3:
output = get_reverse_output(mif_private,
get_largest_input(mif_private));
break;
}
OUTPUT(out) = output;
}
}

View File

@ -49,3 +49,11 @@ Limits: - - -
Vector: yes yes no
Vector_Bounds: [2 -] [2 -] -
Null_Allowed: no no yes
/* This is used internally to cache the model type. */
STATIC_VAR_TABLE:
Static_Var_Name: type
Description: "Internal copy of model type"
Data_Type: int