From 576f2189452fca4fb15495bccc8acb925fb6973c Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Thu, 22 Jun 2023 16:47:27 +0100 Subject: [PATCH] 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. --- examples/digital/compare/adder-comparison.txt | 8 +- examples/digital/compare/adder_esource.cir | 16 ++++ .../icm/analog/multi_input_pwl/cfunc.mod | 78 +++++++++++++++---- .../icm/analog/multi_input_pwl/ifspec.ifs | 8 ++ 4 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 examples/digital/compare/adder_esource.cir diff --git a/examples/digital/compare/adder-comparison.txt b/examples/digital/compare/adder-comparison.txt index ef3e28e12..56972e94e 100644 --- a/examples/digital/compare/adder-comparison.txt +++ b/examples/digital/compare/adder-comparison.txt @@ -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. + diff --git a/examples/digital/compare/adder_esource.cir b/examples/digital/compare/adder_esource.cir new file mode 100644 index 000000000..62ee85673 --- /dev/null +++ b/examples/digital/compare/adder_esource.cir @@ -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 diff --git a/src/xspice/icm/analog/multi_input_pwl/cfunc.mod b/src/xspice/icm/analog/multi_input_pwl/cfunc.mod index 5758ce546..91e228c2e 100644 --- a/src/xspice/icm/analog/multi_input_pwl/cfunc.mod +++ b/src/xspice/icm/analog/multi_input_pwl/cfunc.mod @@ -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; } } diff --git a/src/xspice/icm/analog/multi_input_pwl/ifspec.ifs b/src/xspice/icm/analog/multi_input_pwl/ifspec.ifs index c87b0e471..852c2bda9 100644 --- a/src/xspice/icm/analog/multi_input_pwl/ifspec.ifs +++ b/src/xspice/icm/analog/multi_input_pwl/ifspec.ifs @@ -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