Browse Source
xspice/icm/digital, introduce d_genlut
xspice/icm/digital, introduce d_genlut
a digital n-input x m-output look-up table gatepre-master-46
committed by
rlar
4 changed files with 467 additions and 0 deletions
-
385src/xspice/icm/digital/d_genlut/cfunc.mod
-
77src/xspice/icm/digital/d_genlut/ifspec.ifs
-
1src/xspice/icm/digital/modpath.lst
-
4visualc/xspice/digital.vcxproj
@ -0,0 +1,385 @@ |
|||||
|
/*.......1.........2.........3.........4.........5.........6.........7.........8 |
||||
|
================================================================================ |
||||
|
|
||||
|
FILE d_genlut/cfunc.mod |
||||
|
|
||||
|
AUTHORS |
||||
|
|
||||
|
25 Aug 2016 Tim Edwards efabless inc., San Jose, CA |
||||
|
|
||||
|
SUMMARY |
||||
|
|
||||
|
This file contains the functional description of the d_genlut |
||||
|
code model. |
||||
|
|
||||
|
LICENSE |
||||
|
|
||||
|
This software is in the public domain. |
||||
|
|
||||
|
INTERFACES |
||||
|
|
||||
|
FILE ROUTINE CALLED |
||||
|
|
||||
|
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 ====================*/ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <ctype.h> |
||||
|
#include <math.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
|
||||
|
|
||||
|
/*=== CONSTANTS ========================*/ |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/*=== MACROS ===========================*/ |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/*============================================================================== |
||||
|
|
||||
|
FUNCTION cm_d_genlut() |
||||
|
|
||||
|
AUTHORS |
||||
|
|
||||
|
25 Aug 2016 Tim Edwards |
||||
|
|
||||
|
SUMMARY |
||||
|
|
||||
|
This function implements the d_genlut code model. |
||||
|
|
||||
|
INTERFACES |
||||
|
|
||||
|
FILE ROUTINE CALLED |
||||
|
|
||||
|
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_LUT ROUTINE ===*/ |
||||
|
|
||||
|
/************************************************ |
||||
|
* The following is the model for the * |
||||
|
* digital n-input LUT gate * |
||||
|
* * |
||||
|
* Created 8/25/16 Tim Edwards * |
||||
|
************************************************/ |
||||
|
|
||||
|
|
||||
|
void cm_d_genlut(ARGS) |
||||
|
{ |
||||
|
int i, /* generic loop counter index */ |
||||
|
j, /* lookup index bit value */ |
||||
|
k, /* generic loop counter index */ |
||||
|
idx, /* lookup index */ |
||||
|
ivalid, /* check for valid input */ |
||||
|
isize, /* number of input ports */ |
||||
|
osize, /* number of output ports */ |
||||
|
dsize, /* number of input delay params */ |
||||
|
rsize, /* number of output rise delay params */ |
||||
|
fsize, /* number of output fall delay params */ |
||||
|
lsize, /* number of input load params */ |
||||
|
entrylen, /* length of table per output (2^isize) */ |
||||
|
tablelen; /* length of table (osize * (2^isize)) */ |
||||
|
|
||||
|
char *table_string; |
||||
|
double maxdelay, /* maximum input-to-output delay */ |
||||
|
testdelay; |
||||
|
|
||||
|
Digital_State_t *in, /* temp storage for input bits */ |
||||
|
*in_old; /* previous input for buffers */ |
||||
|
Digital_t *out, /* temporary output for buffers */ |
||||
|
*out_old, /* previous output for buffers */ |
||||
|
*lookup_table; /* lookup table */ |
||||
|
|
||||
|
/** Retrieve size values and compute table length... **/ |
||||
|
isize = PORT_SIZE(in); |
||||
|
osize = PORT_SIZE(out); |
||||
|
|
||||
|
if (PARAM_NULL(input_load)) |
||||
|
lsize = 0; |
||||
|
else |
||||
|
lsize = PARAM_SIZE(input_load); |
||||
|
|
||||
|
if (PARAM_NULL(input_delay)) |
||||
|
dsize = 0; |
||||
|
else |
||||
|
dsize = PARAM_SIZE(input_delay); |
||||
|
|
||||
|
if (PARAM_NULL(rise_delay)) |
||||
|
rsize = 0; |
||||
|
else |
||||
|
rsize = PARAM_SIZE(rise_delay); |
||||
|
|
||||
|
if (PARAM_NULL(fall_delay)) |
||||
|
fsize = 0; |
||||
|
else |
||||
|
fsize = PARAM_SIZE(fall_delay); |
||||
|
|
||||
|
entrylen = (1 << isize); |
||||
|
tablelen = osize * entrylen; |
||||
|
|
||||
|
/*** Setup required state variables ***/ |
||||
|
|
||||
|
if (INIT) { /* initial pass */ |
||||
|
|
||||
|
/* allocate storage for the lookup table */ |
||||
|
STATIC_VAR (locdata) = calloc((size_t) tablelen, sizeof(Digital_t)); |
||||
|
lookup_table = STATIC_VAR (locdata); |
||||
|
|
||||
|
/* allocate storage for the outputs */ |
||||
|
cm_event_alloc(0, osize * (int) sizeof(Digital_t)); |
||||
|
cm_event_alloc(1, isize * (int) sizeof(Digital_State_t)); |
||||
|
|
||||
|
/* set loading for inputs */ |
||||
|
for (i = 0; i < isize; i++) |
||||
|
if (i < lsize) |
||||
|
LOAD(in[i]) = PARAM(input_load[i]); |
||||
|
else if (lsize > 0) |
||||
|
LOAD(in[i]) = PARAM(input_load[lsize - 1]); |
||||
|
else |
||||
|
LOAD(in[i]) = 1.0e-12; |
||||
|
|
||||
|
/* retrieve storage for the outputs */ |
||||
|
out = out_old = (Digital_t *) cm_event_get_ptr(0, 0); |
||||
|
in = in_old = (Digital_State_t *) cm_event_get_ptr(1, 0); |
||||
|
|
||||
|
/* read parameter string into lookup table */ |
||||
|
table_string = PARAM(table_values); |
||||
|
for (idx = 0; idx < (int)strlen(table_string); idx++) { |
||||
|
if (idx == tablelen) |
||||
|
// If string is longer than 2^num_inputs, ignore |
||||
|
// the extra values at the end |
||||
|
break; |
||||
|
if (table_string[idx] == '1') { |
||||
|
lookup_table[idx].state = ONE; |
||||
|
lookup_table[idx].strength = STRONG; |
||||
|
} else if (table_string[idx] == '0') { |
||||
|
lookup_table[idx].state = ZERO; |
||||
|
lookup_table[idx].strength = STRONG; |
||||
|
} else if (table_string[idx] == 'z') { |
||||
|
lookup_table[idx].state = UNKNOWN; |
||||
|
lookup_table[idx].strength = HI_IMPEDANCE; |
||||
|
} else { |
||||
|
lookup_table[idx].state = UNKNOWN; |
||||
|
lookup_table[idx].strength = UNDETERMINED; |
||||
|
} |
||||
|
} |
||||
|
for (; idx < tablelen; idx++) { |
||||
|
// If string is shorter than 2^num_inputs, fill |
||||
|
// the remainder of the lookup table with UNKNOWN |
||||
|
// values. |
||||
|
lookup_table[idx].state = UNKNOWN; |
||||
|
lookup_table[idx].strength = UNDETERMINED; |
||||
|
} |
||||
|
} else { /* Retrieve previous values */ |
||||
|
|
||||
|
/* retrieve lookup table */ |
||||
|
lookup_table = STATIC_VAR (locdata); |
||||
|
|
||||
|
/* retrieve storage for the inputs and outputs */ |
||||
|
out = (Digital_t *) cm_event_get_ptr(0, 0); |
||||
|
out_old = (Digital_t *) cm_event_get_ptr(0, 1); |
||||
|
in = (Digital_State_t *) cm_event_get_ptr(1, 0); |
||||
|
in_old = (Digital_State_t *) cm_event_get_ptr(1, 1); |
||||
|
} |
||||
|
|
||||
|
/*** Calculate new output value based on inputs and table ***/ |
||||
|
|
||||
|
j = 1; |
||||
|
idx = 0; |
||||
|
ivalid = 1; |
||||
|
for (k = 0; k < osize; k++) { |
||||
|
out[k].state = UNKNOWN; |
||||
|
out[k].strength = UNDETERMINED; |
||||
|
} |
||||
|
for (i = 0; i < isize; i++) { |
||||
|
|
||||
|
/* make sure this input isn't floating... */ |
||||
|
if (PORT_NULL(in) == FALSE) { |
||||
|
|
||||
|
/* use inputs to find index into lookup table */ |
||||
|
if ((in[i] = INPUT_STATE(in[i])) == UNKNOWN) { |
||||
|
ivalid = 0; |
||||
|
break; |
||||
|
} else if (in[i] == ONE) { |
||||
|
idx += j; |
||||
|
} |
||||
|
j <<= 1; |
||||
|
} else { |
||||
|
/* at least one port is floating...output is unknown */ |
||||
|
ivalid = 0; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (ivalid) |
||||
|
for (k = 0; k < osize; k++) |
||||
|
out[k] = lookup_table[idx + (k * entrylen)]; |
||||
|
|
||||
|
/*** Determine analysis type and output appropriate values ***/ |
||||
|
|
||||
|
if (ANALYSIS == DC) { /** DC analysis...output w/o delays **/ |
||||
|
|
||||
|
for (i = 0; i < osize; i++) { |
||||
|
OUTPUT_STATE(out[i]) = out[i].state; |
||||
|
OUTPUT_STRENGTH(out[i]) = out[i].strength; |
||||
|
} |
||||
|
} |
||||
|
else { /** Transient Analysis **/ |
||||
|
|
||||
|
/* Determine maximum input-to-output delay */ |
||||
|
maxdelay = 0.0; |
||||
|
for (i = 0; i < isize; i++) |
||||
|
if (in[i] != in_old[i]) { |
||||
|
if (i < dsize) |
||||
|
testdelay = PARAM(input_delay[i]); |
||||
|
else if (dsize > 0) |
||||
|
testdelay = PARAM(input_delay[dsize - 1]); |
||||
|
else |
||||
|
testdelay = 0.0; |
||||
|
if (maxdelay < testdelay) |
||||
|
maxdelay = testdelay; |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < osize; i++) { |
||||
|
if (out[i].state != out_old[i].state) { /* output value is changing */ |
||||
|
|
||||
|
OUTPUT_DELAY(out[i]) = maxdelay; |
||||
|
switch (out[i].state) { |
||||
|
|
||||
|
/* fall to zero value */ |
||||
|
case ZERO: |
||||
|
OUTPUT_STATE(out[i]) = ZERO; |
||||
|
if (i < fsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[i]); |
||||
|
else if (fsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[fsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
OUTPUT_STRENGTH(out[i]) = out[i].strength; |
||||
|
break; |
||||
|
|
||||
|
/* rise to one value */ |
||||
|
case ONE: |
||||
|
OUTPUT_STATE(out[i]) = ONE; |
||||
|
if (i < rsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[i]); |
||||
|
else if (rsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[rsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
OUTPUT_STRENGTH(out[i]) = out[i].strength; |
||||
|
break; |
||||
|
|
||||
|
/* unknown output */ |
||||
|
default: |
||||
|
OUTPUT_STATE(out[i]) = out[i].state = UNKNOWN; |
||||
|
OUTPUT_STRENGTH(out[i]) = out[i].strength; |
||||
|
|
||||
|
/* based on old value, add rise or fall delay */ |
||||
|
if (out_old[i].state == 0) { /* add rising delay */ |
||||
|
if (i < rsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[i]); |
||||
|
else if (rsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[rsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} else { /* add falling delay */ |
||||
|
if (i < fsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[i]); |
||||
|
else if (fsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[fsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} else if (out[i].strength != out_old[i].strength) { |
||||
|
/* output strength is changing */ |
||||
|
OUTPUT_STRENGTH(out[i]) = out[i].strength; |
||||
|
switch (out[i].strength) { |
||||
|
case STRONG: |
||||
|
if (out_old[i].state == 0) { /* add falling delay */ |
||||
|
if (i < fsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[i]); |
||||
|
else if (fsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[fsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} else { /* add rising delay */ |
||||
|
if (i < rsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[i]); |
||||
|
else if (rsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[rsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} |
||||
|
break; |
||||
|
default: |
||||
|
if (out_old[i].state == 0) { /* add rising delay */ |
||||
|
if (i < rsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[i]); |
||||
|
else if (rsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(rise_delay[rsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} else { /* add falling delay */ |
||||
|
if (i < fsize) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[i]); |
||||
|
else if (fsize > 0) |
||||
|
OUTPUT_DELAY(out[i]) += PARAM(fall_delay[fsize - 1]); |
||||
|
else |
||||
|
OUTPUT_DELAY(out[i]) += 1.0e-9; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} else { /* output value not changing */ |
||||
|
OUTPUT_CHANGED(out[i]) = FALSE; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
/*.......1.........2.........3.........4.........5.........6.........7.........8 |
||||
|
================================================================================ |
||||
|
|
||||
|
AUTHORS |
||||
|
|
||||
|
25 Aug 2016 Tim Edwards efabless inc., San Jose, CA |
||||
|
|
||||
|
SUMMARY |
||||
|
|
||||
|
This file contains the interface specification file for the |
||||
|
digital d_genlut code model. |
||||
|
|
||||
|
LICENSE |
||||
|
|
||||
|
This software is in the public domain. |
||||
|
|
||||
|
===============================================================================*/ |
||||
|
|
||||
|
NAME_TABLE: |
||||
|
|
||||
|
|
||||
|
C_Function_Name: cm_d_genlut |
||||
|
Spice_Model_Name: d_genlut |
||||
|
Description: "digital n-input x m-output look-up table gate" |
||||
|
|
||||
|
|
||||
|
PORT_TABLE: |
||||
|
|
||||
|
Port_Name: in out |
||||
|
Description: "input" "output" |
||||
|
Direction: in out |
||||
|
Default_Type: d d |
||||
|
Allowed_Types: [d] [d] |
||||
|
Vector: yes yes |
||||
|
Vector_Bounds: - - |
||||
|
Null_Allowed: no no |
||||
|
|
||||
|
|
||||
|
PARAMETER_TABLE: |
||||
|
|
||||
|
Parameter_Name: rise_delay fall_delay |
||||
|
Description: "rise delay" "fall delay" |
||||
|
Data_Type: real real |
||||
|
Default_Value: 1.0e-9 1.0e-9 |
||||
|
Limits: [1e-12 -] [1e-12 -] |
||||
|
Vector: yes yes |
||||
|
Vector_Bounds: - - |
||||
|
Null_Allowed: yes yes |
||||
|
|
||||
|
|
||||
|
PARAMETER_TABLE: |
||||
|
|
||||
|
Parameter_Name: input_load input_delay |
||||
|
Description: "input load value (F)" "input delay" |
||||
|
Data_Type: real real |
||||
|
Default_Value: 1.0e-12 0.0 |
||||
|
Limits: - - |
||||
|
Vector: yes yes |
||||
|
Vector_Bounds: - - |
||||
|
Null_Allowed: yes yes |
||||
|
|
||||
|
PARAMETER_TABLE: |
||||
|
|
||||
|
Parameter_Name: table_values |
||||
|
Description: "lookup table values" |
||||
|
Data_Type: string |
||||
|
Default_Value: "0" |
||||
|
Limits: - |
||||
|
Vector: no |
||||
|
Vector_Bounds: - |
||||
|
Null_Allowed: no |
||||
|
|
||||
|
STATIC_VAR_TABLE: |
||||
|
|
||||
|
Static_Var_Name: locdata |
||||
|
Description: "lookup table" |
||||
|
Data_Type: pointer |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue