diff --git a/src/xspice/icm/analog/file_source/cfunc.mod b/src/xspice/icm/analog/file_source/cfunc.mod index da391d499..9394e573c 100644 --- a/src/xspice/icm/analog/file_source/cfunc.mod +++ b/src/xspice/icm/analog/file_source/cfunc.mod @@ -11,6 +11,7 @@ Thomas Sailer AUTHORS 20 May 2011 Thomas Sailer + 03 Sep 2012 Holger Vogt MODIFICATIONS @@ -19,7 +20,8 @@ MODIFICATIONS SUMMARY This file contains the model-specific routines used to - functionally describe the gain code model. + functionally describe the file source code model used + to read an array of analog values per time step from a file. INTERFACES @@ -55,18 +57,38 @@ NON-STANDARD FEATURES /*=== MACROS ===========================*/ #if defined(__MINGW32__) || defined(_MSC_VER) -#define DIR_PATHSEP "\\" +#define DIR_PATHSEP "\\" #else -#define DIR_PATHSEP "/" +#define DIR_PATHSEP "/" +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#define snprintf _snprintf #endif /*=== LOCAL VARIABLES & TYPEDEFS =======*/ struct filesource_state { - FILE *fp; - long pos; - unsigned char atend; + FILE *fp; + long pos; + unsigned char atend; }; + + +typedef struct { + + double *amplinterval; /* the storage array for the + amplitude offsets */ + + double *timeinterval; /* the storage array for the + time offset */ + + struct filesource_state *state; /* the storage array for the + filesource status. */ + +} Local_Data_t; + /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ @@ -76,19 +98,19 @@ struct filesource_state { /*============================================================================== -FUNCTION void cm_gain() +FUNCTION void cm_filesource() AUTHORS - 2 Oct 1991 Jeffrey P. Murray + 20 May 2011 Thomas Sailer MODIFICATIONS - NONE + 07 Sept 2012 Holger Vogt SUMMARY - This function implements the gain code model. + This function implements the filesource code model. INTERFACES @@ -117,121 +139,125 @@ NON-STANDARD FEATURES void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */ { - int size; - int amplscalesize; - int amploffssize; - double *timeinterval; - double *amplinterval; - struct filesource_state *state; + int size; + int amplscalesize; + int amploffssize; - if(ANALYSIS == MIF_AC) { - return; - } - size = PORT_SIZE(out); - if (INIT == 1) { - /* Allocate storage for internal state */ - cm_analog_alloc(0, 2 * sizeof(double)); - cm_analog_alloc(1, size * (int) (2 * sizeof(double))); - cm_analog_alloc(2, sizeof(struct filesource_state)); - } - timeinterval = (double *)cm_analog_get_ptr(0, 0); - amplinterval = (double *)cm_analog_get_ptr(1, 0); - state = (struct filesource_state *)cm_analog_get_ptr(2, 0); - if (INIT == 1) { - int i; - timeinterval[0] = timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); - for (i = 0; i < size; ++i) - amplinterval[2 * i] = amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); - state->fp = fopen(PARAM(file), "r"); - state->pos = 0; - state->atend = 0; - if (!state->fp) { - char *lbuffer, *p; + Local_Data_t *loc; /* Pointer to local static data, not to be included + in the state vector */ + + if(ANALYSIS == MIF_AC) { + return; + } + size = PORT_SIZE(out); + if (INIT == 1) { + + int i; + + /*** allocate static storage for *loc ***/ + STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); + loc = STATIC_VAR (locdata); + + /* Allocate storage for internal state */ + loc->timeinterval = (double*)calloc(2, sizeof(double)); + loc->amplinterval = (double*)calloc(2 * size, sizeof(double)); + loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state)); + + loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); + for (i = 0; i < size; ++i) + loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); + loc->state->fp = fopen(PARAM(file), "r"); + loc->state->pos = 0; + loc->state->atend = 0; + if (!loc->state->fp) { + char *lbuffer, *p; lbuffer = getenv("NGSPICE_INPUT_DIR"); if (lbuffer && *lbuffer) { p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1); sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); - state->fp = fopen(p, "r"); + loc->state->fp = fopen(p, "r"); free(p); } - if (!state->fp) { - char msg[512]; - snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file)); - cm_message_send(msg); - state->atend = 1; - } - } - } - amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale); - amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset); - while (TIME >= timeinterval[1] && !state->atend) { - char line[512]; - char *cp, *cpdel; - char *cp2; - double t; - int i; - if (ftell(state->fp) != state->pos) { - clearerr(state->fp); - fseek(state->fp, state->pos, SEEK_SET); - } - if (!fgets(line, sizeof(line), state->fp)) { - state->atend = 1; - break; - } - state->pos = ftell(state->fp); - cpdel = cp = strdup(line); - while (*cp && isspace(*cp)) - ++cp; - if (*cp == '#' || *cp == ';') { - free(cpdel); - continue; - } - t = strtod(cp, &cp2); - if (cp2 == cp) { - free(cpdel); - continue; - } - cp = cp2; - if (!PARAM_NULL(timescale)) - t *= PARAM(timescale); - if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE) - t += timeinterval[1]; - else if (!PARAM_NULL(timeoffset)) - t += PARAM(timeoffset); - timeinterval[0] = timeinterval[1]; - timeinterval[1] = t; - for (i = 0; i < size; ++i) - amplinterval[2 * i] = amplinterval[2 * i + 1]; - for (i = 0; i < size; ++i) { - while (*cp && (isspace(*cp) || *cp == ',')) - ++cp; - t = strtod(cp, &cp2); - if (cp2 == cp) - break; - cp = cp2; - if (i < amplscalesize) - t *= PARAM(amplscale[i]); - if (i < amploffssize) - t += PARAM(amploffset[i]); - amplinterval[2 * i + 1] = t; - } - free(cpdel); - } - if (TIME < timeinterval[1] && timeinterval[0] < timeinterval[1] && 0.0 <= timeinterval[0]) { - if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { - int i; - for (i = 0; i < size; ++i) - OUTPUT(out[i]) = amplinterval[2 * i]; - } else { - double mul0 = (timeinterval[1] - TIME) / (timeinterval[1] - timeinterval[0]); - double mul1 = 1.0 - mul0; - int i; - for (i = 0; i < size; ++i) - OUTPUT(out[i]) = mul0 * amplinterval[2 * i] + mul1 * amplinterval[2 * i + 1]; - } - } else { - int i; - for (i = 0; i < size; ++i) - OUTPUT(out[i]) = amplinterval[2 * i + 1]; - } + if (!loc->state->fp) { + char msg[512]; + snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file)); + cm_message_send(msg); + loc->state->atend = 1; + } + } + } + + amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale); + amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset); + loc = STATIC_VAR (locdata); + while (TIME >= loc->timeinterval[1] && !loc->state->atend) { + char line[512]; + char *cp, *cpdel; + char *cp2; + double t; + int i; + if (ftell(loc->state->fp) != loc->state->pos) { + clearerr(loc->state->fp); + fseek(loc->state->fp, loc->state->pos, SEEK_SET); + } + if (!fgets(line, sizeof(line), loc->state->fp)) { + loc->state->atend = 1; + break; + } + loc->state->pos = ftell(loc->state->fp); + cpdel = cp = strdup(line); + while (*cp && isspace(*cp)) + ++cp; + if (*cp == '#' || *cp == ';') { + free(cpdel); + continue; + } + t = strtod(cp, &cp2); + if (cp2 == cp) { + free(cpdel); + continue; + } + cp = cp2; + if (!PARAM_NULL(timescale)) + t *= PARAM(timescale); + if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE) + t += loc->timeinterval[1]; + else if (!PARAM_NULL(timeoffset)) + t += PARAM(timeoffset); + loc->timeinterval[0] = loc->timeinterval[1]; + loc->timeinterval[1] = t; + for (i = 0; i < size; ++i) + loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1]; + for (i = 0; i < size; ++i) { + while (*cp && (isspace(*cp) || *cp == ',')) + ++cp; + t = strtod(cp, &cp2); + if (cp2 == cp) + break; + cp = cp2; + if (i < amplscalesize) + t *= PARAM(amplscale[i]); + if (i < amploffssize) + t += PARAM(amploffset[i]); + loc->amplinterval[2 * i + 1] = t; + } + free(cpdel); + } + if (TIME < loc->timeinterval[1] && loc->timeinterval[0] < loc->timeinterval[1] && 0.0 <= loc->timeinterval[0]) { + if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { + int i; + for (i = 0; i < size; ++i) + OUTPUT(out[i]) = loc->amplinterval[2 * i]; + } else { + double mul0 = (loc->timeinterval[1] - TIME) / (loc->timeinterval[1] - loc->timeinterval[0]); + double mul1 = 1.0 - mul0; + int i; + for (i = 0; i < size; ++i) + OUTPUT(out[i]) = mul0 * loc->amplinterval[2 * i] + mul1 * loc->amplinterval[2 * i + 1]; + } + } else { + int i; + for (i = 0; i < size; ++i) + OUTPUT(out[i]) = loc->amplinterval[2 * i + 1]; + } } diff --git a/src/xspice/icm/analog/file_source/ifspec.ifs b/src/xspice/icm/analog/file_source/ifspec.ifs index e07e51972..d294c1bab 100644 --- a/src/xspice/icm/analog/file_source/ifspec.ifs +++ b/src/xspice/icm/analog/file_source/ifspec.ifs @@ -80,3 +80,10 @@ Limits: - Vector: no Vector_Bounds: - Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: locdata +Description: "local static data" +Data_Type: pointer