Browse Source

read the complete input file at once during inizialization

instaed of reading the file line by line,
and instaed of re-reading from the beginning in case
of time stepping back. This saves a vast amount of
simulation time if the input file is large.
pre-master-46
Holger Vogt 8 years ago
parent
commit
d1761f8d6e
  1. 202
      src/xspice/icm/analog/file_source/cfunc.mod

202
src/xspice/icm/analog/file_source/cfunc.mod

@ -13,16 +13,18 @@ AUTHORS
20 May 2011 Thomas Sailer 20 May 2011 Thomas Sailer
03 Sep 2012 Holger Vogt 03 Sep 2012 Holger Vogt
27 Feb 2017 Marcel Hendrix 27 Feb 2017 Marcel Hendrix
23 JUL 2018 Holger Vogt
MODIFICATIONS
MODIFICATIONS
SUMMARY SUMMARY
This file contains the model-specific routines used to This file contains the model-specific routines used to
functionally describe the file source code model used functionally describe the file source code model used
to read an array of analog values per time step from a file.
to read an array from a file containing lines with
time and analog values, and returning them per time step.
INTERFACES INTERFACES
@ -76,6 +78,14 @@ struct filesource_state {
}; };
struct infiledata {
double *datavec;
int vecallocated;
int maxoccupied;
int actpointer;
int size;
};
typedef struct { typedef struct {
double *amplinterval; /* the storage array for the double *amplinterval; /* the storage array for the
@ -87,6 +97,9 @@ typedef struct {
struct filesource_state *state; /* the storage array for the struct filesource_state *state; /* the storage array for the
filesource status. */ filesource status. */
struct infiledata *indata; /* the storage vector for the input data
sourced from file. */
} Local_Data_t; } Local_Data_t;
@ -108,6 +121,7 @@ MODIFICATIONS
07 Sept 2012 Holger Vogt 07 Sept 2012 Holger Vogt
27 Feb 2017 Marcel Hendrix 27 Feb 2017 Marcel Hendrix
23 JUL 2018 Holger Vogt
SUMMARY SUMMARY
@ -142,15 +156,18 @@ static void
cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason) cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason)
{ {
switch (reason) { switch (reason) {
case MIF_CB_DESTROY: {
Local_Data_t *loc = STATIC_VAR (locdata);
fclose(loc->state->fp);
free(loc->state);
free(loc->amplinterval);
free(loc->timeinterval);
free(loc);
break;
}
case MIF_CB_DESTROY: {
Local_Data_t *loc = STATIC_VAR (locdata);
if (loc->state->fp)
fclose(loc->state->fp);
free(loc->state);
free(loc->amplinterval);
free(loc->timeinterval);
free(loc->indata->datavec);
free(loc->indata);
free(loc);
break;
}
} }
} }
@ -158,8 +175,10 @@ cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason)
void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */
{ {
int size = PORT_SIZE(out); int size = PORT_SIZE(out);
int stepsize = size + 1;
int amplscalesize; int amplscalesize;
int amploffssize; int amploffssize;
int j;
Local_Data_t *loc; /* Pointer to local static data, not to be included Local_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector */ in the state vector */
@ -169,7 +188,7 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
} }
if (INIT == 1) { if (INIT == 1) {
int i;
int i, count;
CALLBACK = cm_filesource_callback; CALLBACK = cm_filesource_callback;
@ -180,11 +199,18 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
/* Allocate storage for internal state */ /* Allocate storage for internal state */
loc->timeinterval = (double*)calloc(2, sizeof(double)); loc->timeinterval = (double*)calloc(2, sizeof(double));
loc->amplinterval = (double*)calloc(2 * (size_t) size, sizeof(double)); loc->amplinterval = (double*)calloc(2 * (size_t) size, sizeof(double));
loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state));
loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state));
loc->indata = (struct infiledata*)malloc(sizeof(struct infiledata));
loc->indata->datavec = (double*)malloc(sizeof(double) * stepsize * 1000);
loc->indata->vecallocated = stepsize * 1000;
loc->indata->maxoccupied = 0;
loc->indata->actpointer = 0;
loc->indata->size = stepsize;
loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset);
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]);
/* open the file */
loc->state->fp = fopen_with_path(PARAM(file), "r"); loc->state->fp = fopen_with_path(PARAM(file), "r");
loc->state->atend = 0; loc->state->atend = 0;
if (!loc->state->fp) { if (!loc->state->fp) {
@ -195,82 +221,118 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file));
loc->state->fp = fopen(p, "r"); loc->state->fp = fopen(p, "r");
free(p); free(p);
}
}
if (!loc->state->fp) { if (!loc->state->fp) {
cm_message_printf("cannot open file %s", PARAM(file)); cm_message_printf("cannot open file %s", PARAM(file));
loc->state->atend = 1; loc->state->atend = 1;
} }
} }
/* read, preprocess and store the data */
amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale);
amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset);
count = 0;
while (!loc->state->atend) {
char line[512];
char *cp, *cpdel;
char *cp2;
double t, tprev = 0;
int i;
if (!fgets(line, sizeof(line), loc->state->fp)) {
loc->state->atend = 1;
break;
}
cpdel = cp = strdup(line);
/* read the time channel; update the time difference */
while (*cp && isspace_c(*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 += tprev;
else if (!PARAM_NULL(timeoffset))
t += PARAM(timeoffset);
tprev = t;
/* before storing, check if vector size is large enough.
If not, add another 1000*size doubles */
if (count > loc->indata->vecallocated - size) {
loc->indata->vecallocated += size * 1000;
loc->indata->datavec = (double*)realloc(loc->indata->datavec, sizeof(double) * loc->indata->vecallocated);
}
if(loc->indata->datavec == NULL){
cm_message_printf("cannot allocate enough memory");
break; // loc->state->atend = 1;
}
loc->indata->datavec[count++] = t;
/* read the data channels; update the amplitude difference of each channel */
for (i = 0; i < size; ++i) {
while (*cp && (isspace_c(*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->indata->datavec[count++] = t;
}
free(cpdel);
}
loc->indata->maxoccupied = count;
if(loc->state->fp) {
fclose(loc->state->fp);
loc->state->fp = NULL;
}
/* point to the next time */
loc->indata->actpointer = stepsize;
} }
amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale);
amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset);
loc = STATIC_VAR (locdata); loc = STATIC_VAR (locdata);
/* The file pointer is at the same position it was for the last simulator TIME ... /* The file pointer is at the same position it was for the last simulator TIME ...
* If TIME steps backward, for example due to a second invocation of a 'tran' analysis * If TIME steps backward, for example due to a second invocation of a 'tran' analysis
* then we need to rewind the file to start from the beginning.
* step back in datavec[loc->indata->actpointer] .
*/ */
if (TIME < loc->timeinterval[0]) { if (TIME < loc->timeinterval[0]) {
rewind(loc->state->fp);
loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset);
while (TIME < loc->indata->datavec[loc->indata->actpointer] && loc->indata->actpointer >= 0)
loc->indata->actpointer -= stepsize;
loc->timeinterval[0] = loc->indata->datavec[loc->indata->actpointer];
} }
loc->timeinterval[1] = loc->indata->datavec[loc->indata->actpointer + stepsize];
while (TIME >= loc->timeinterval[1] && !loc->state->atend) {
char line[512];
char *cp, *cpdel;
char *cp2;
double t;
int i;
if (!fgets(line, sizeof(line), loc->state->fp)) {
loc->state->atend = 1;
break;
while (TIME > loc->timeinterval[1]) {
loc->indata->actpointer += stepsize;
if (loc->indata->actpointer > loc->indata->maxoccupied) {
/* we are done */
return;
} }
cpdel = cp = strdup(line);
loc->timeinterval[1] = loc->indata->datavec[loc->indata->actpointer];
}
loc->timeinterval[0] = loc->indata->datavec[loc->indata->actpointer - stepsize];
/* read the time channel; update the time difference */
while (*cp && isspace_c(*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;
/* read the channels; update the amplitude difference of each channel */
for (i = 0; i < size; ++i)
loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1];
for (i = 0; i < size; ++i) {
while (*cp && (isspace_c(*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);
for (j = 0; j < size; j++) {
loc->amplinterval[2 * j] = loc->indata->datavec[loc->indata->actpointer - stepsize + j + 1];
loc->amplinterval[2 * j + 1] = loc->indata->datavec[loc->indata->actpointer + j + 1];
} }
if (!loc->state->atend && loc->timeinterval[0] <= TIME && TIME <= loc->timeinterval[1]) {
if (loc->timeinterval[0] <= TIME && TIME <= loc->timeinterval[1]) {
if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) {
int i; int i;
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)

Loading…
Cancel
Save