XSPICE filesource: remove segfault with op before tran

This commit is contained in:
h_vogt 2012-09-07 23:48:09 +02:00
parent 9de9336581
commit 5ce51f148e
2 changed files with 153 additions and 120 deletions

View File

@ -11,6 +11,7 @@ Thomas Sailer
AUTHORS AUTHORS
20 May 2011 Thomas Sailer 20 May 2011 Thomas Sailer
03 Sep 2012 Holger Vogt
MODIFICATIONS MODIFICATIONS
@ -19,7 +20,8 @@ MODIFICATIONS
SUMMARY SUMMARY
This file contains the model-specific routines used to 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 INTERFACES
@ -55,18 +57,38 @@ NON-STANDARD FEATURES
/*=== MACROS ===========================*/ /*=== MACROS ===========================*/
#if defined(__MINGW32__) || defined(_MSC_VER) #if defined(__MINGW32__) || defined(_MSC_VER)
#define DIR_PATHSEP "\\" #define DIR_PATHSEP "\\"
#else #else
#define DIR_PATHSEP "/" #define DIR_PATHSEP "/"
#endif
#if defined(_MSC_VER)
#define strdup _strdup
#define snprintf _snprintf
#endif #endif
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ /*=== LOCAL VARIABLES & TYPEDEFS =======*/
struct filesource_state { struct filesource_state {
FILE *fp; FILE *fp;
long pos; long pos;
unsigned char atend; 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 ===*/ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
@ -76,19 +98,19 @@ struct filesource_state {
/*============================================================================== /*==============================================================================
FUNCTION void cm_gain() FUNCTION void cm_filesource()
AUTHORS AUTHORS
2 Oct 1991 Jeffrey P. Murray 20 May 2011 Thomas Sailer
MODIFICATIONS MODIFICATIONS
NONE 07 Sept 2012 Holger Vogt
SUMMARY SUMMARY
This function implements the gain code model. This function implements the filesource code model.
INTERFACES INTERFACES
@ -117,121 +139,125 @@ NON-STANDARD FEATURES
void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */
{ {
int size; int size;
int amplscalesize; int amplscalesize;
int amploffssize; int amploffssize;
double *timeinterval;
double *amplinterval;
struct filesource_state *state;
if(ANALYSIS == MIF_AC) { Local_Data_t *loc; /* Pointer to local static data, not to be included
return; in the state vector */
}
size = PORT_SIZE(out); if(ANALYSIS == MIF_AC) {
if (INIT == 1) { return;
/* Allocate storage for internal state */ }
cm_analog_alloc(0, 2 * sizeof(double)); size = PORT_SIZE(out);
cm_analog_alloc(1, size * (int) (2 * sizeof(double))); if (INIT == 1) {
cm_analog_alloc(2, sizeof(struct filesource_state));
} int i;
timeinterval = (double *)cm_analog_get_ptr(0, 0);
amplinterval = (double *)cm_analog_get_ptr(1, 0); /*** allocate static storage for *loc ***/
state = (struct filesource_state *)cm_analog_get_ptr(2, 0); STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t ));
if (INIT == 1) { loc = STATIC_VAR (locdata);
int i;
timeinterval[0] = timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); /* Allocate storage for internal state */
for (i = 0; i < size; ++i) loc->timeinterval = (double*)calloc(2, sizeof(double));
amplinterval[2 * i] = amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); loc->amplinterval = (double*)calloc(2 * size, sizeof(double));
state->fp = fopen(PARAM(file), "r"); loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state));
state->pos = 0;
state->atend = 0; loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset);
if (!state->fp) { for (i = 0; i < size; ++i)
char *lbuffer, *p; 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"); lbuffer = getenv("NGSPICE_INPUT_DIR");
if (lbuffer && *lbuffer) { if (lbuffer && *lbuffer) {
p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1); p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1);
sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file));
state->fp = fopen(p, "r"); loc->state->fp = fopen(p, "r");
free(p); free(p);
} }
if (!state->fp) { if (!loc->state->fp) {
char msg[512]; char msg[512];
snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file)); snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file));
cm_message_send(msg); cm_message_send(msg);
state->atend = 1; loc->state->atend = 1;
} }
} }
} }
amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale);
amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset); amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale);
while (TIME >= timeinterval[1] && !state->atend) { amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset);
char line[512]; loc = STATIC_VAR (locdata);
char *cp, *cpdel; while (TIME >= loc->timeinterval[1] && !loc->state->atend) {
char *cp2; char line[512];
double t; char *cp, *cpdel;
int i; char *cp2;
if (ftell(state->fp) != state->pos) { double t;
clearerr(state->fp); int i;
fseek(state->fp, state->pos, SEEK_SET); if (ftell(loc->state->fp) != loc->state->pos) {
} clearerr(loc->state->fp);
if (!fgets(line, sizeof(line), state->fp)) { fseek(loc->state->fp, loc->state->pos, SEEK_SET);
state->atend = 1; }
break; if (!fgets(line, sizeof(line), loc->state->fp)) {
} loc->state->atend = 1;
state->pos = ftell(state->fp); break;
cpdel = cp = strdup(line); }
while (*cp && isspace(*cp)) loc->state->pos = ftell(loc->state->fp);
++cp; cpdel = cp = strdup(line);
if (*cp == '#' || *cp == ';') { while (*cp && isspace(*cp))
free(cpdel); ++cp;
continue; if (*cp == '#' || *cp == ';') {
} free(cpdel);
t = strtod(cp, &cp2); continue;
if (cp2 == cp) { }
free(cpdel); t = strtod(cp, &cp2);
continue; if (cp2 == cp) {
} free(cpdel);
cp = cp2; continue;
if (!PARAM_NULL(timescale)) }
t *= PARAM(timescale); cp = cp2;
if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE) if (!PARAM_NULL(timescale))
t += timeinterval[1]; t *= PARAM(timescale);
else if (!PARAM_NULL(timeoffset)) if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE)
t += PARAM(timeoffset); t += loc->timeinterval[1];
timeinterval[0] = timeinterval[1]; else if (!PARAM_NULL(timeoffset))
timeinterval[1] = t; t += PARAM(timeoffset);
for (i = 0; i < size; ++i) loc->timeinterval[0] = loc->timeinterval[1];
amplinterval[2 * i] = amplinterval[2 * i + 1]; loc->timeinterval[1] = t;
for (i = 0; i < size; ++i) { for (i = 0; i < size; ++i)
while (*cp && (isspace(*cp) || *cp == ',')) loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1];
++cp; for (i = 0; i < size; ++i) {
t = strtod(cp, &cp2); while (*cp && (isspace(*cp) || *cp == ','))
if (cp2 == cp) ++cp;
break; t = strtod(cp, &cp2);
cp = cp2; if (cp2 == cp)
if (i < amplscalesize) break;
t *= PARAM(amplscale[i]); cp = cp2;
if (i < amploffssize) if (i < amplscalesize)
t += PARAM(amploffset[i]); t *= PARAM(amplscale[i]);
amplinterval[2 * i + 1] = t; if (i < amploffssize)
} t += PARAM(amploffset[i]);
free(cpdel); loc->amplinterval[2 * i + 1] = t;
} }
if (TIME < timeinterval[1] && timeinterval[0] < timeinterval[1] && 0.0 <= timeinterval[0]) { free(cpdel);
if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { }
int i; if (TIME < loc->timeinterval[1] && loc->timeinterval[0] < loc->timeinterval[1] && 0.0 <= loc->timeinterval[0]) {
for (i = 0; i < size; ++i) if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) {
OUTPUT(out[i]) = amplinterval[2 * i]; int i;
} else { for (i = 0; i < size; ++i)
double mul0 = (timeinterval[1] - TIME) / (timeinterval[1] - timeinterval[0]); OUTPUT(out[i]) = loc->amplinterval[2 * i];
double mul1 = 1.0 - mul0; } else {
int i; double mul0 = (loc->timeinterval[1] - TIME) / (loc->timeinterval[1] - loc->timeinterval[0]);
for (i = 0; i < size; ++i) double mul1 = 1.0 - mul0;
OUTPUT(out[i]) = mul0 * amplinterval[2 * i] + mul1 * amplinterval[2 * i + 1]; int i;
} for (i = 0; i < size; ++i)
} else { OUTPUT(out[i]) = mul0 * loc->amplinterval[2 * i] + mul1 * loc->amplinterval[2 * i + 1];
int i; }
for (i = 0; i < size; ++i) } else {
OUTPUT(out[i]) = amplinterval[2 * i + 1]; int i;
} for (i = 0; i < size; ++i)
OUTPUT(out[i]) = loc->amplinterval[2 * i + 1];
}
} }

View File

@ -80,3 +80,10 @@ Limits: -
Vector: no Vector: no
Vector_Bounds: - Vector_Bounds: -
Null_Allowed: yes Null_Allowed: yes
STATIC_VAR_TABLE:
Static_Var_Name: locdata
Description: "local static data"
Data_Type: pointer