diff options
Diffstat (limited to 'src/outitf.c')
-rw-r--r-- | src/outitf.c | 886 |
1 files changed, 664 insertions, 222 deletions
diff --git a/src/outitf.c b/src/outitf.c index df22af2..bedf36d 100644 --- a/src/outitf.c +++ b/src/outitf.c @@ -1,15 +1,14 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group -Modified: 2000 AlansFixes +Modified: 2000 AlansFixes, 2013/2015 patch by Krzysztof Blaszkowski **********/ /************************************************************************** * 10.Mar.2017 - RM - Added a dirty fix to handle orphan FOSSEE test bench * processes. The following static functions were added in the process: * o nghdl_orphan_tb() * o nghdl_tb_SIGUSR1() - ************************************************************************** - */ + **************************************************************************/ /* * This module replaces the old "writedata" routines in nutmeg. * Unlike the writedata routines, the OUT routines are only called by @@ -53,8 +52,8 @@ extern char *spice_analysis_get_description(int index); static int beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analName, char *refName, int refType, int numNames, char **dataNames, int dataType, bool windowed, runDesc **runp); -static int addDataDesc(runDesc *run, char *name, int type, int ind); -static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind); +static int addDataDesc(runDesc *run, char *name, int type, int ind, int meminit); +static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit); static void fileInit(runDesc *run); static void fileInit_pass2(runDesc *run); static void fileStartPoint(FILE *fp, bool bin, int num); @@ -70,6 +69,8 @@ static bool parseSpecial(char *name, char *dev, char *param, char *ind); static bool name_eq(char *n1, char *n2); static bool getSpecial(dataDesc *desc, runDesc *run, IFvalue *val); static void freeRun(runDesc *run); +static int InterpFileAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); +static int InterpPlotAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); /*Output data to spice module*/ #ifdef TCL_MODULE @@ -84,6 +85,11 @@ extern void sh_vecinit(runDesc *run); extern bool orflag; #endif +// fixme +// ugly hack to work around missing api to specify the "type" of signals +int fixme_onoise_type = SV_NOTYPE; +int fixme_inoise_type = SV_NOTYPE; + #define DOUBLE_PRECISION 15 @@ -94,6 +100,13 @@ static size_t column, rowbuflen; static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */ +static bool interpolated = FALSE; +static double *valueold, *valuenew; + +#ifdef SHARED_MODULE +static bool savenone = FALSE; +#endif + /* 10.Mar.2017 - RM - Added nghdl_tb_SIGUSR1().*/ static void nghdl_tb_SIGUSR1(char* pid_file) { @@ -107,31 +120,36 @@ static void nghdl_tb_SIGUSR1(char* pid_file) if (fp) { - while (fscanf(fp, "%s", line) == 1) - { - // PID is converted to a decimal value. - tmp = (pid_t) strtol(line, &nptr, 10); - if ((errno != ERANGE) && (errno!= EINVAL)) - { - pid[count++] = tmp; - } - } - - fclose(fp); - } - - for(i=0; i<count; i++) - { - if (pid[i]) - { + /* 15.Oct.2019 - RP - Scan and store all the PIDs in this file */ + while (fscanf(fp, "%s", line) == 1) + { + // PID is converted to a decimal value. + tmp = (pid_t) strtol(line, &nptr, 10); + if ((errno != ERANGE) && (errno!= EINVAL)) + { + pid[count++] = tmp; + } + } + + fclose(fp); + } + + /* 15.Oct.2019 - RP - Kill all the active PIDs */ + for(i=0; i<count; i++) + { + if (pid[i]) + { // Check if a process with this pid really exists. - ret = kill(pid[i], 0); - if (ret == 0) - { - kill(pid[i], SIGUSR1); - } - } - } + ret = kill(pid[i], 0); + if (ret == 0) + { + kill(pid[i], SIGUSR1); + } + } + } + + // 15.Oct.2019 - RP + remove(pid_file); } /* 10.Mar.2017 - RM - Added nghdl_orphan_tb().*/ @@ -147,35 +165,38 @@ static void nghdl_orphan_tb(void) if ((dirfd = opendir(dir)) == NULL) { - fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n"); + fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n"); return; } /* Loop through /tmp directories looking for "NGHDL_<my pid>*" files.*/ while ((dirp = readdir(dirfd)) != NULL) { - struct stat stbuf; - sprintf(filename_tmp, "/tmp/%s", dirp->d_name); - if (strstr(filename_tmp, pid_file_prefix)) - { - if (stat(filename_tmp, &stbuf) == -1) - { - fprintf(stderr, + struct stat stbuf; + sprintf(filename_tmp, "/tmp/%s", dirp->d_name); + if (strstr(filename_tmp, pid_file_prefix)) + { + if (stat(filename_tmp, &stbuf) == -1) + { + fprintf(stderr, "nghdl_orphan_tb: stat() failed; ERRNO=%d on file:%s\n", errno, filename_tmp); - continue; - } - - if ((stbuf.st_mode & S_IFMT) == S_IFDIR) - { - continue; - } - else - { - nghdl_tb_SIGUSR1(filename_tmp); - } - } + continue; + } + + if ((stbuf.st_mode & S_IFMT) == S_IFDIR) + { + continue; + } + else + { + nghdl_tb_SIGUSR1(filename_tmp); + } + } } + + // 15.Oct.2019 - RP + remove("/tmp/NGHDL_COMMON_IP.txt"); } /* End 10.Mar.2017 - RM */ @@ -228,9 +249,11 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam bool saveall = TRUE; bool savealli = FALSE; char *an_name; + int initmem; /*to resume a run saj *All it does is reassign the file pointer and return (requires *runp to be NULL if this is not needed) */ + if (dataType == 666 && numNames == 666) { run = *runp; run->writeOut = ft_getOutReq(&run->fp, &run->runPlot, &run->binary, @@ -240,10 +263,16 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam /*end saj*/ /* Check to see if we want to print informational data. */ - if (cp_getvar("printinfo", CP_BOOL, NULL)) + if (cp_getvar("printinfo", CP_BOOL, NULL, 0)) fprintf(cp_err, "(debug printing enabled)\n"); - *runp = run = alloc(struct runDesc); + /* Check to see if we want to save only interpolated data. */ + if (cp_getvar("interp", CP_BOOL, NULL, 0)) { + interpolated = TRUE; + fprintf(cp_out, "Warning: Interpolated raw file data!\n\n"); + } + + *runp = run = TMALLOC(struct runDesc, 1); /* First fill in some general information. */ run->analysis = analysisPtr; @@ -289,12 +318,27 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam saves[i].used = 1; continue; } +#ifdef SHARED_MODULE + /* this may happen if shared ngspice*/ + if (cieq(saves[i].name, "none")) { + savenone = TRUE; + saveall = TRUE; + savesused[i] = TRUE; + saves[i].used = 1; + continue; + } +#endif } } + if (numsaves && !saveall) + initmem = numsaves; + else + initmem = numNames; + /* Pass 0. */ if (refName) { - addDataDesc(run, refName, refType, -1); + addDataDesc(run, refName, refType, -1, initmem); for (i = 0; i < numsaves; i++) if (!savesused[i] && name_eq(saves[i].name, refName)) { savesused[i] = TRUE; @@ -311,7 +355,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam if (!savesused[i]) for (j = 0; j < numNames; j++) if (name_eq(saves[i].name, dataNames[j])) { - addDataDesc(run, dataNames[j], dataType, j); + addDataDesc(run, dataNames[j], dataType, j, initmem); savesused[i] = TRUE; saves[i].used = 1; break; @@ -327,7 +371,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam !strstr(dataNames[i], "#emitter") && !strstr(dataNames[i], "#base")) { - addDataDesc(run, dataNames[i], dataType, i); + addDataDesc(run, dataNames[i], dataType, i, initmem); } } @@ -357,17 +401,17 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam } else if (strstr(ch, "#emitter")) { strcpy(ch, "[ie]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) - addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem); strcpy(ch, "[is]"); } else if (strstr(ch, "#drain")) { strcpy(ch, "[id]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) - addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem); strcpy(ch, "[ig]"); } else if (strstr(ch, "#source")) { strcpy(ch, "[is]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) - addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem); strcpy(ch, "[ib]"); } else if (strstr(ch, "#internal") && (tmpname[1] == 'd')) { strcpy(ch, "[id]"); @@ -381,7 +425,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam fprintf(stderr, "Warning : unexpected dependent variable on %s\n", tmpname); } else { - addSpecialDesc(run, tmpname, namebuf, parambuf, depind); + addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem); } } } @@ -418,7 +462,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam depbuf, saves[i].name); continue; } - addDataDesc(run, dataNames[j], dataType, j); + addDataDesc(run, dataNames[j], dataType, j, initmem); savesused[i] = TRUE; saves[i].used = 1; depind = j; @@ -427,7 +471,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam } } - addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind); + addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind, initmem); } if (numsaves) { @@ -463,6 +507,14 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam } } + /* define storage for old and new data, to allow interpolation */ + if (interpolated && run->circuit->CKTcurJob->JOBtype == 4) { + valueold = TMALLOC(double, run->numData); + for (i = 0; i < run->numData; i++) + valueold[i] = 0.0; + valuenew = TMALLOC(double, run->numData); + } + /*Start BLT, initilises the blt vectors saj*/ #ifdef TCL_MODULE blt_init(run); @@ -473,20 +525,28 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam return (OK); } - +/* Initialze memory for the list of all vectors in the current plot. + Add a standard vector to this plot */ static int -addDataDesc(runDesc *run, char *name, int type, int ind) +addDataDesc(runDesc *run, char *name, int type, int ind, int meminit) { dataDesc *data; - if (!run->numData) - run->data = TMALLOC(dataDesc, 1); - else - run->data = TREALLOC(dataDesc, run->data, run->numData + 1); + /* initialize memory (for all vectors or given by 'save') */ + if (!run->numData) { + /* even if input 0, do a malloc */ + run->data = TMALLOC(dataDesc, ++meminit); + run->maxData = meminit; + } + /* If there is need for more memory */ + else if (run->numData == run->maxData) { + run->maxData = (int)(run->maxData * 1.1) + 1; + run->data = TREALLOC(dataDesc, run->data, run->maxData); + } data = &run->data[run->numData]; /* so freeRun will get nice NULL pointers for the fields we don't set */ - bzero(data, sizeof(dataDesc)); + memset(data, 0, sizeof(dataDesc)); data->name = copy(name); data->type = type; @@ -503,30 +563,40 @@ addDataDesc(runDesc *run, char *name, int type, int ind) return (OK); } - +/* Initialze memory for the list of all vectors in the current plot. + Add a special vector (e.g. @q1[ib]) to this plot */ static int -addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind) +addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit) { dataDesc *data; - char *unique; /* unique char * from back-end */ + char *unique, *freeunique; /* unique char * from back-end */ + int ret; - if (!run->numData) - run->data = TMALLOC(dataDesc, 1); - else - run->data = TREALLOC(dataDesc, run->data, run->numData + 1); + if (!run->numData) { + /* even if input 0, do a malloc */ + run->data = TMALLOC(dataDesc, ++meminit); + run->maxData = meminit; + } + else if (run->numData == run->maxData) { + run->maxData = (int)(run->maxData * 1.1) + 1; + run->data = TREALLOC(dataDesc, run->data, run->maxData); + } data = &run->data[run->numData]; /* so freeRun will get nice NULL pointers for the fields we don't set */ - bzero(data, sizeof(dataDesc)); + memset(data, 0, sizeof(dataDesc)); data->name = copy(name); - unique = copy(devname); + freeunique = unique = copy(devname); - /* MW. My "special" routine here */ - INPinsertNofree(&unique, ft_curckt->ci_symtab); + /* unique will be overridden, if it already exists */ + ret = INPinsertNofree(&unique, ft_curckt->ci_symtab); data->specName = unique; + if (ret == E_EXISTS) + tfree(freeunique); + data->specParamName = copy(param); data->specIndex = depind; @@ -540,6 +610,56 @@ addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind) } +static void +OUTpD_memory(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) +{ + int i, n = run->numData; + + for (i = 0; i < n; i++) { + + dataDesc *d; + +#ifdef TCL_MODULE + /*Locks the blt vector to stop access*/ + blt_lockvec(i); +#endif + + d = &run->data[i]; + + if (d->outIndex == -1) { + if (d->type == IF_REAL) + plotAddRealValue(d, refValue->rValue); + else if (d->type == IF_COMPLEX) + plotAddComplexValue(d, refValue->cValue); + } else if (d->regular) { + if (d->type == IF_REAL) + plotAddRealValue(d, valuePtr->v.vec.rVec[d->outIndex]); + else if (d->type == IF_COMPLEX) + plotAddComplexValue(d, valuePtr->v.vec.cVec[d->outIndex]); + } else { + IFvalue val; + + /* should pre-check instance */ + if (!getSpecial(d, run, &val)) + continue; + + if (d->type == IF_REAL) + plotAddRealValue(d, val.rValue); + else if (d->type == IF_COMPLEX) + plotAddComplexValue(d, val.cValue); + else + fprintf(stderr, "OUTpData: unsupported data type\n"); + } + +#ifdef TCL_MODULE + /*relinks and unlocks vector*/ + blt_relink(i, d->vec); +#endif + + } +} + + int OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) { @@ -551,8 +671,18 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) #ifdef TCL_MODULE steps_completed = run->pointCount; #endif - - if (run->writeOut) { + /* interpolated batch mode output to file in transient analysis */ + if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) { + InterpFileAdd(run, refValue, valuePtr); + return (OK); + } + /* interpolated interactive or control mode output to plot in transient analysis */ + else if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && !(run->writeOut)) { + InterpPlotAdd(run, refValue, valuePtr); + return (OK); + } + /* standard batch mode output to file */ + else if (run->writeOut) { if (run->pointCount == 1) fileInit_pass2(run); @@ -567,7 +697,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) every quarter of a second, to give some feedback without using too much CPU time */ #ifndef HAS_WINGUI - if (!orflag) { + if (!orflag && !ft_norefprint) { currclock = clock(); if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stderr, " Reference value : % 12.5e\r", @@ -582,7 +712,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) fileAddRealValue(run->fp, run->binary, refValue->rValue); #ifndef HAS_WINGUI - if (!orflag) { + if (!orflag && !ft_norefprint) { currclock = clock(); if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stderr, " Reference value : % 12.5e\r", @@ -650,7 +780,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) } - fileEndPoint(run->fp, run->binary); /* Check that the write to disk completed successfully, otherwise abort */ @@ -662,11 +791,13 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) } else { + OUTpD_memory(run, refValue, valuePtr); + /* This is interactive mode. Update the screen with the reference variable just the same */ #ifndef HAS_WINGUI - if (!orflag) { + if (!orflag && !ft_norefprint) { currclock = clock(); if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { if (run->isComplex) { @@ -681,45 +812,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) } #endif - for (i = 0; i < run->numData; i++) { - -#ifdef TCL_MODULE - /*Locks the blt vector to stop access*/ - blt_lockvec(i); -#endif - - if (run->data[i].outIndex == -1) { - if (run->data[i].type == IF_REAL) - plotAddRealValue(&run->data[i], refValue->rValue); - else if (run->data[i].type == IF_COMPLEX) - plotAddComplexValue(&run->data[i], refValue->cValue); - } else if (run->data[i].regular) { - if (run->data[i].type == IF_REAL) - plotAddRealValue(&run->data[i], - valuePtr->v.vec.rVec[run->data[i].outIndex]); - else if (run->data[i].type == IF_COMPLEX) - plotAddComplexValue(&run->data[i], - valuePtr->v.vec.cVec[run->data[i].outIndex]); - } else { - IFvalue val; - /* should pre-check instance */ - if (!getSpecial(&run->data[i], run, &val)) - continue; - if (run->data[i].type == IF_REAL) - plotAddRealValue(&run->data[i], val.rValue); - else if (run->data[i].type == IF_COMPLEX) - plotAddComplexValue(&run->data[i], val.cValue); - else - fprintf(stderr, "OUTpData: unsupported data type\n"); - } - -#ifdef TCL_MODULE - /*relinks and unlocks vector*/ - blt_relink(i, (run->data[i]).vec); -#endif - - } - gr_iplot(run->runPlot); } @@ -736,7 +828,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) } -/* ARGSUSED */ /* until some code gets written */ int OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr) { @@ -748,7 +839,6 @@ OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr) } -/* ARGSUSED */ /* until some code gets written */ int OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr) { @@ -761,7 +851,6 @@ OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr) } -/* ARGSUSED */ /* until some code gets written */ int OUTwEnd(runDesc *plotPtr) { @@ -774,22 +863,22 @@ OUTwEnd(runDesc *plotPtr) int OUTendPlot(runDesc *plotPtr) { - runDesc *run = plotPtr; // FIXME - - if (run->writeOut) { - fileEnd(run); + if (plotPtr->writeOut) { + fileEnd(plotPtr); } else { gr_end_iplot(); - plotEnd(run); + plotEnd(plotPtr); } - freeRun(run); + tfree(valueold); + tfree(valuenew); + + freeRun(plotPtr); return (OK); } -/* ARGSUSED */ /* until some code gets written */ int OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefValue) { @@ -802,7 +891,6 @@ OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefVa } -/* ARGSUSED */ /* until some code gets written */ int OUTendDomain(runDesc *plotPtr) { @@ -812,7 +900,6 @@ OUTendDomain(runDesc *plotPtr) } -/* ARGSUSED */ /* until some code gets written */ int OUTattributes(runDesc *plotPtr, IFuid varName, int param, IFvalue *value) { @@ -905,6 +992,42 @@ fileInit(runDesc *run) } +static int +guess_type(const char *name) +{ + int type; + + if (substring("#branch", name)) + type = SV_CURRENT; + else if (cieq(name, "time")) + type = SV_TIME; + else if (cieq(name, "frequency")) + type = SV_FREQUENCY; + else if (ciprefix("inoise", name)) + type = fixme_inoise_type; + else if (ciprefix("onoise", name)) + type = fixme_onoise_type; + else if (cieq(name, "temp-sweep")) + type = SV_TEMP; + else if (cieq(name, "res-sweep")) + type = SV_RES; + else if ((*name == '@') && substring("[g", name)) /* token starting with [g */ + type = SV_ADMITTANCE; + else if ((*name == '@') && substring("[c", name)) + type = SV_CAPACITANCE; + else if ((*name == '@') && substring("[i", name)) + type = SV_CURRENT; + else if ((*name == '@') && substring("[q", name)) + type = SV_CHARGE; + else if ((*name == '@') && substring("[p]", name)) /* token is exactly [p] */ + type = SV_POWER; + else + type = SV_VOLTAGE; + + return type; +} + + static void fileInit_pass2(runDesc *run) { @@ -914,26 +1037,7 @@ fileInit_pass2(runDesc *run) char *name = run->data[i].name; - if (substring("#branch", name)) - type = SV_CURRENT; - else if (cieq(name, "time")) - type = SV_TIME; - else if (cieq(name, "frequency")) - type = SV_FREQUENCY; - else if (cieq(name, "temp-sweep")) - type = SV_TEMP; - else if (cieq(name, "res-sweep")) - type = SV_RES; - else if ((*name == '@') && (substring("[g", name))) - type = SV_ADMITTANCE; - else if ((*name == '@') && (substring("[c", name))) - type = SV_CAPACITANCE; - else if ((*name == '@') && (substring("[i", name))) - type = SV_CURRENT; - else if ((*name == '@') && (substring("[q", name))) - type = SV_CHARGE; - else - type = SV_VOLTAGE; + type = guess_type(name); if (type == SV_CURRENT) { char *branch = strstr(name, "#branch"); @@ -965,7 +1069,7 @@ fileInit_pass2(runDesc *run) rowbuflen *= 2; rowbuf = TMALLOC(double, rowbuflen); } else { - // fIXME rowbuflen = 0; + rowbuflen = 0; rowbuf = NULL; } } @@ -1006,7 +1110,6 @@ fileAddComplexValue(FILE *fp, bool bin, IFcomplex value) } -/* ARGSUSED */ /* until some code gets written */ static void fileEndPoint(FILE *fp, bool bin) { @@ -1023,12 +1126,13 @@ fileEndPoint(FILE *fp, bool bin) static void fileEnd(runDesc *run) { -/* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are - * found, force them to exit. - */ - nghdl_orphan_tb(); + /* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are + * found, force them to exit. + */ + nghdl_orphan_tb(); + + /* End 10.Mar.2017 */ -/* End 10.Mar.2017 */ if (run->fp != stdout) { long place = ftell(run->fp); @@ -1043,10 +1147,7 @@ fileEnd(runDesc *run) fflush(run->fp); - if (run->binary) { - /* deallocate row buffer */ - tfree(rowbuf); - } + tfree(rowbuf); } @@ -1056,9 +1157,7 @@ static void plotInit(runDesc *run) { struct plot *pl = plot_alloc(run->type); - char buf[100]; struct dvec *v; - dataDesc *dd; int i; pl->pl_title = copy(run->name); @@ -1077,71 +1176,83 @@ plotInit(runDesc *run) run->isComplex = TRUE; for (i = 0; i < run->numData; i++) { - dd = &run->data[i]; - v = alloc(struct dvec); - if (isdigit(*dd->name)) { - (void) sprintf(buf, "V(%s)", dd->name); - v->v_name = copy(buf); - } else { - v->v_name = copy(dd->name); - } - if (substring("#branch", v->v_name)) - v->v_type = SV_CURRENT; - else if (cieq(v->v_name, "time")) - v->v_type = SV_TIME; - else if (cieq(v->v_name, "frequency")) - v->v_type = SV_FREQUENCY; - else if (cieq(v->v_name, "onoise_spectrum")) - v->v_type = SV_OUTPUT_N_DENS; - else if (cieq(v->v_name, "onoise_integrated")) - v->v_type = SV_OUTPUT_NOISE; - else if (cieq(v->v_name, "inoise_spectrum")) - v->v_type = SV_INPUT_N_DENS; - else if (cieq(v->v_name, "inoise_integrated")) - v->v_type = SV_INPUT_NOISE; - else if (cieq(v->v_name, "temp-sweep")) - v->v_type = SV_TEMP; - else if (cieq(v->v_name, "res-sweep")) - v->v_type = SV_RES; - else if ((*(v->v_name) == '@') && (substring("[g", v->v_name))) - v->v_type = SV_ADMITTANCE; - else if ((*(v->v_name) == '@') && (substring("[c", v->v_name))) - v->v_type = SV_CAPACITANCE; - else if ((*(v->v_name) == '@') && (substring("[i", v->v_name))) - v->v_type = SV_CURRENT; - else if ((*(v->v_name) == '@') && (substring("[q", v->v_name))) - v->v_type = SV_CHARGE; + dataDesc *dd = &run->data[i]; + char *name; + + if (isdigit_c(dd->name[0])) + name = tprintf("V(%s)", dd->name); else - v->v_type = SV_VOLTAGE; - v->v_length = 0; - v->v_scale = NULL; - if (!run->isComplex) { - v->v_flags = VF_REAL; - v->v_realdata = NULL; - } else { - v->v_flags = VF_COMPLEX; - v->v_compdata = NULL; - } + name = copy(dd->name); - v->v_flags |= VF_PERMANENT; + v = dvec_alloc(name, + guess_type(name), + run->isComplex + ? (VF_COMPLEX | VF_PERMANENT) + : (VF_REAL | VF_PERMANENT), + 0, NULL); vec_new(v); dd->vec = v; } } +/* prepare the vector length data for memory allocation + If new, and tran or pss, length is TSTOP / TSTEP plus some margin. + If allocated length is exceeded, check progress. When > 20% then extrapolate memory needed, + if less than 20% then just double the size. + If not tran or pss, return fixed value (1024) of memory to be added. + */ +static inline int +vlength2delta(int len) +{ +#ifdef SHARED_MODULE + if (savenone) + /* We need just a vector length of 1 */ + return 1; +#endif + /* TSTOP / TSTEP */ + int points = ft_curckt->ci_ckt->CKTtimeListSize; + /* transient and pss analysis (points > 0) upon start */ + if (len == 0 && points > 0) { + /* number of timesteps plus some overhead */ + return points + 100; + } + /* transient and pss if original estimate is exceeded */ + else if (points > 0) { + /* check where we are */ + double timerel = ft_curckt->ci_ckt->CKTtime / ft_curckt->ci_ckt->CKTfinalTime; + /* return an estimate of the appropriate number of time points, if more than 20% of + the anticipated total time has passed */ + if (timerel > 0.2) + return (int)(len / timerel) - len + 1; + /* If not, just double the available memory */ + else + return len; + } + /* other analysis types that do not set CKTtimeListSize */ + else + return 1024; +} + static void plotAddRealValue(dataDesc *desc, double value) { struct dvec *v = desc->vec; +#ifdef SHARED_MODULE + if (savenone) + /* always save new data to same location */ + v->v_length = 0; +#endif + + if (v->v_length >= v->v_alloc_length) + dvec_extend(v, v->v_length + vlength2delta(v->v_length)); + if (isreal(v)) { - v->v_realdata = TREALLOC(double, v->v_realdata, v->v_length + 1); v->v_realdata[v->v_length] = value; } else { /* a real parading as a VF_COMPLEX */ - v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1); v->v_compdata[v->v_length].cx_real = value; v->v_compdata[v->v_length].cx_imag = 0.0; } @@ -1156,7 +1267,14 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value) { struct dvec *v = desc->vec; - v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1); +#ifdef SHARED_MODULE + if (savenone) + v->v_length = 0; +#endif + + if (v->v_length >= v->v_alloc_length) + dvec_extend(v, v->v_length + vlength2delta(v->v_length)); + v->v_compdata[v->v_length].cx_real = value.real; v->v_compdata[v->v_length].cx_imag = value.imag; @@ -1165,18 +1283,17 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value) } -/* ARGSUSED */ /* until some code gets written */ static void plotEnd(runDesc *run) { -/* 10.Mar.2017 - RM */ - nghdl_orphan_tb(); -/* End 10.Mar.2017 */ + /* 10.Mar.2017 - RM */ + nghdl_orphan_tb(); + /* End 10.Mar.2017 */ - fprintf(stderr, "\n"); fprintf(stdout, "\nNo. of Data Rows : %d\n", run->pointCount); } + /* ParseSpecial takes something of the form "@name[param,index]" and rips * out name, param, andstrchr. */ @@ -1335,7 +1452,7 @@ OUTerror(int flags, char *format, IFuid *names) char buf[BSIZE_SP], *s, *bptr; int nindex = 0; - if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL)) + if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0)) return; for (m = msgs; m->flag; m++) @@ -1360,3 +1477,328 @@ OUTerror(int flags, char *format, IFuid *names) fprintf(cp_err, "%s\n", buf); fflush(cp_err); } + + +void +OUTerrorf(int flags, const char *format, ...) +{ + struct mesg *m; + va_list args; + + if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0)) + return; + + for (m = msgs; m->flag; m++) + if (flags & m->flag) + fprintf(cp_err, "%s: ", m->string); + + va_start (args, format); + + vfprintf(cp_err, format, args); + fputc('\n', cp_err); + + fflush(cp_err); + + va_end(args); +} + + +static int +InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) +{ + int i; + static double timeold = 0.0, timenew = 0.0, timestep = 0.0; + bool nodata = FALSE; + bool interpolatenow = FALSE; + + if (run->pointCount == 1) { + fileInit_pass2(run); + timestep = run->circuit->CKTinitTime + run->circuit->CKTstep; + } + + if (run->refIndex != -1) { + /* Save first time step */ + if (refValue->rValue == run->circuit->CKTinitTime) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, run->circuit->CKTinitTime); + interpolatenow = nodata = FALSE; + } + /* Save last time step */ + else if (refValue->rValue == run->circuit->CKTfinalTime) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, run->circuit->CKTfinalTime); + interpolatenow = nodata = FALSE; + } + /* Save exact point */ + else if (refValue->rValue == timestep) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, timestep); + timestep += run->circuit->CKTstep; + interpolatenow = nodata = FALSE; + } + else if (refValue->rValue > timestep) { + /* add the next time step value to the vector */ + fileStartPoint(run->fp, run->binary, run->pointCount); + timenew = refValue->rValue; + fileAddRealValue(run->fp, run->binary, timestep); + timestep += run->circuit->CKTstep; + nodata = FALSE; + interpolatenow = TRUE; + } + else { + /* Do not save this step */ + run->pointCount--; + timeold = refValue->rValue; + nodata = TRUE; + interpolatenow = FALSE; + } +#ifndef HAS_WINGUI + if (!orflag && !ft_norefprint) { + currclock = clock(); + if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", + refValue->rValue); + lastclock = currclock; + } + } +#endif + + } + + for (i = 0; i < run->numData; i++) { + /* we've already printed reference vec first */ + if (run->data[i].outIndex == -1) + continue; + +#ifdef TCL_MODULE + blt_add(i, refValue ? refValue->rValue : NAN); +#endif + + if (run->data[i].regular) { + /* Store value or interpolate and store or do not store any value to file */ + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + fileAddRealValue(run->fp, run->binary, valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + fileAddRealValue(run->fp, run->binary, newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + } else { + IFvalue val; + /* should pre-check instance */ + if (!getSpecial(&run->data[i], run, &val)) { + + /* If this is the first data point, print a warning for any unrecognized + variables, since this has not already been checked */ + if (run->pointCount == 1) + fprintf(stderr, "Warning: unrecognized variable - %s\n", + run->data[i].name); + val.rValue = 0; + fileAddRealValue(run->fp, run->binary, val.rValue); + continue; + } + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = val.rValue; + fileAddRealValue(run->fp, run->binary, valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = val.rValue; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + fileAddRealValue(run->fp, run->binary, newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = val.rValue; + } + +#ifdef TCL_MODULE + blt_add(i, valuePtr->v.vec.rVec [run->data[i].outIndex]); +#endif + + } + + fileEndPoint(run->fp, run->binary); + + /* Check that the write to disk completed successfully, otherwise abort */ + if (ferror(run->fp)) { + fprintf(stderr, "Warning: rawfile write error !!\n"); + shouldstop = TRUE; + } + + if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE) + shouldstop = TRUE; + +#ifdef TCL_MODULE + Tcl_ExecutePerLoop(); +#elif defined SHARED_MODULE + sh_ExecutePerLoop(); +#endif + return(OK); +} + +static int +InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) +{ + int i, iscale = -1; + static double timeold = 0.0, timenew = 0.0, timestep = 0.0; + bool nodata = FALSE; + bool interpolatenow = FALSE; + + if (run->pointCount == 1) + timestep = run->circuit->CKTinitTime + run->circuit->CKTstep; + + /* find the scale vector */ + for (i = 0; i < run->numData; i++) + if (run->data[i].outIndex == -1) { + iscale = i; + break; + } + if (iscale == -1) + fprintf(stderr, "Error: no scale vector found\n"); + +#ifdef TCL_MODULE + /*Locks the blt vector to stop access*/ + blt_lockvec(iscale); +#endif + + /* Save first time step */ + if (refValue->rValue == run->circuit->CKTinitTime) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], refValue->rValue); + interpolatenow = nodata = FALSE; + } + /* Save last time step */ + else if (refValue->rValue == run->circuit->CKTfinalTime) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], run->circuit->CKTfinalTime); + interpolatenow = nodata = FALSE; + } + /* Save exact point */ + else if (refValue->rValue == timestep) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], timestep); + timestep += run->circuit->CKTstep; + interpolatenow = nodata = FALSE; + } + else if (refValue->rValue > timestep) { + /* add the next time step value to the vector */ + timenew = refValue->rValue; + plotAddRealValue(&run->data[iscale], timestep); + timestep += run->circuit->CKTstep; + nodata = FALSE; + interpolatenow = TRUE; + } + else { + /* Do not save this step */ + run->pointCount--; + timeold = refValue->rValue; + nodata = TRUE; + interpolatenow = FALSE; + } + +#ifdef TCL_MODULE + /*relinks and unlocks vector*/ + blt_relink(iscale, (run->data[iscale]).vec); +#endif + +#ifndef HAS_WINGUI + if (!orflag && !ft_norefprint) { + currclock = clock(); + if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", + refValue->rValue); + lastclock = currclock; + } + } +#endif + + for (i = 0; i < run->numData; i++) { + if (i == iscale) + continue; + +#ifdef TCL_MODULE + /*Locks the blt vector to stop access*/ + blt_lockvec(i); +#endif + + if (run->data[i].regular) { + /* Store value or interpolate and store or do not store any value to file */ + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + plotAddRealValue(&run->data[i], valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + plotAddRealValue(&run->data[i], newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + } else { + IFvalue val; + /* should pre-check instance */ + if (!getSpecial(&run->data[i], run, &val)) + continue; + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = val.rValue; + plotAddRealValue(&run->data[i], valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = val.rValue; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + plotAddRealValue(&run->data[i], newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = val.rValue; + } + +#ifdef TCL_MODULE + /*relinks and unlocks vector*/ + blt_relink(i, (run->data[i]).vec); +#endif + + } + + gr_iplot(run->runPlot); + + if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE) + shouldstop = TRUE; + +#ifdef TCL_MODULE + Tcl_ExecutePerLoop(); +#elif defined SHARED_MODULE + sh_ExecutePerLoop(); +#endif + + return(OK); +} |