📄 outitf.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group Modified: 2000 AlansFixes$Id: outitf.c,v 1.18 2005/05/30 20:28:30 sjborley Exp $**********//* * This module replaces the old "writedata" routines in nutmeg. * Unlike the writedata routines, the OUT routines are only called by * the simulator routines, and only call routines in nutmeg. The rest * of nutmeg doesn't deal with OUT at all. */#include "ngspice.h"#include "cpdefs.h"#include "ftedefs.h"#include "dvec.h"#include "plot.h"#include "sim.h"#include "inpdefs.h" /* for INPtables */#include "ifsim.h"#include "jobdefs.h"#include "iferrmsg.h"#include "circuits.h"#include "outitf.h"#include "variable.h"#include <fcntl.h>#include <time.h>#include "cktdefs.h"#include <inpdefs.h>#include "breakp2.h"#include "runcoms.h"#include "plotting/graf.h"extern char *spice_analysis_get_name(int index);extern char *spice_analysis_get_description(int index);/* static declarations */static int beginPlot(void *analysisPtr, void *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 void fileInit(runDesc *run);static void fileInit_pass2(runDesc *run);static void fileStartPoint(FILE *fp, bool bin, int num);static void fileAddRealValue(FILE *fp, bool bin, double value);static void fileAddComplexValue(FILE *fp, bool bin, IFcomplex value);static void fileEndPoint(FILE *fp, bool bin);static void fileEnd(runDesc *run);static void plotInit(runDesc *run);static void plotAddRealValue(dataDesc *desc, double value);static void plotAddComplexValue(dataDesc *desc, IFcomplex value);static void plotEnd(runDesc *run);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);#define DOUBLE_PRECISION 15static clock_t lastclock, currclock;static double *rowbuf;static int column, rowbuflen;static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */static bool printinfo = FALSE; /* Print informational "error messages". *//* The two "begin plot" routines share all their internals... */intOUTpBeginPlot(void *circuitPtr, void *analysisPtr, IFuid analName, IFuid refName, int refType, int numNames, IFuid *dataNames, int dataType, void **plotPtr){ char *name; #ifdef PARALLEL_ARCHif (ARCHme != 0) return(OK);#endif /* PARALLEL_ARCH */ if (ft_curckt->ci_ckt == circuitPtr) name = ft_curckt->ci_name; else name = "circuit name"; return (beginPlot(analysisPtr, circuitPtr, name, (char *) analName, (char *) refName, refType, numNames, (char **) dataNames, dataType, FALSE, (runDesc **) plotPtr));}intOUTwBeginPlot(void *circuitPtr, void *analysisPtr, IFuid analName, IFuid refName, int refType, int numNames, IFuid *dataNames, int dataType, void **plotPtr){#ifdef PARALLEL_ARCH if (ARCHme != 0) return(OK);#endif /* PARALLEL_ARCH */ return (beginPlot(analysisPtr, circuitPtr, "circuit name", (char *) analName, (char *) refName, refType, numNames, (char **) dataNames, dataType, TRUE, (runDesc **) plotPtr));}static intbeginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, char *refName, int refType, int numNames, char **dataNames, int dataType, bool windowed, runDesc **runp){ runDesc *run; struct save_info *saves; bool *savesused = NULL; int numsaves; int i, j, depind = 0; char namebuf[BSIZE_SP], parambuf[BSIZE_SP], depbuf[BSIZE_SP]; char *ch, tmpname[BSIZE_SP]; bool saveall = TRUE; bool savealli = FALSE; char *an_name; /*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, run->type, run->name); } else { /*end saj*/ /* Check to see if we want to print informational data. */ if (cp_getvar("printinfo", VT_BOOL, (char *) &printinfo)) fprintf(cp_err, "(debug printing enabled)\n"); *runp = run = alloc(struct runDesc); /* First fill in some general information. */ run->analysis = analysisPtr; run->circuit = circuitPtr; run->name = copy(cktName); run->type = copy(analName); run->windowed = windowed; run->numData = 0; an_name = spice_analysis_get_name(((JOB *) analysisPtr)->JOBtype); /* Now let's see which of these things we need. First toss in the * reference vector. Then toss in anything that getSaves() tells * us to save that we can find in the name list. Finally unpack * the remaining saves into parameters. */ numsaves = ft_getSaves(&saves); if (numsaves) { savesused = (bool *) tmalloc(sizeof (bool) * numsaves); saveall = FALSE; for (i = 0; i < numsaves; i++) { if (saves[i].analysis && !cieq((char *)saves[i].analysis, an_name)) { /* ignore this one this time around */ savesused[i] = TRUE; continue; }/* Check for ".save all" and new synonym ".save allv" */ if (cieq(saves[i].name, "all") || cieq(saves[i].name, "allv")) { saveall = TRUE; savesused[i] = TRUE; saves[i].used = 1; continue; }/* And now for the new ".save alli" option */ if (cieq(saves[i].name, "alli")) { savealli = TRUE; savesused[i] = TRUE; saves[i].used = 1; continue; } } } /* Pass 0. */ if (refName) { addDataDesc(run, refName, refType, -1); for (i = 0; i < numsaves; i++) if (!savesused[i] && name_eq(saves[i].name, refName)) { savesused[i] = TRUE; saves[i].used = 1; } } else { run->refIndex = -1; } /* Pass 1. */ if (numsaves && !saveall) { for (i = 0; i < numsaves; i++) { if (!savesused[i]) { for (j = 0; j < numNames; j++) { if (name_eq(saves[i].name, dataNames[j])) { addDataDesc(run, dataNames[j], dataType, j); savesused[i] = TRUE; saves[i].used = 1; break; } } } } } else { for (i = 0; i < numNames; i++) if (!refName || !name_eq(dataNames[i], refName)) {/* Save the node as long as it's an internal device node */ if (!strstr(dataNames[i], "#internal") && !strstr(dataNames[i], "#source") && !strstr(dataNames[i], "#drain") && !strstr(dataNames[i], "#collector") && !strstr(dataNames[i], "#emitter") && !strstr(dataNames[i], "#base")) { addDataDesc(run, dataNames[i], dataType, i); } } } /* Pass 1 and a bit. This is a new pass which searches for all the internal device nodes, and saves the terminal currents instead */ if (savealli) { depind=0; for (i = 0; i < numNames; i++) { if (strstr(dataNames[i], "#internal") || strstr(dataNames[i], "#source") || strstr(dataNames[i], "#drain") || strstr(dataNames[i], "#collector") || strstr(dataNames[i], "#emitter") || strstr(dataNames[i], "#base")) { tmpname[0]='@'; tmpname[1]='\0'; strncat(tmpname, dataNames[i], BSIZE_SP-1); ch=strchr(tmpname, '#'); if (strstr(ch, "#collector")!=NULL) { strcpy(ch, "[ic]"); } else if (strstr(ch, "#base")!=NULL) { strcpy(ch, "[ib]"); } else if (strstr(ch, "#emitter")!=NULL) { strcpy(ch, "[ie]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { addSpecialDesc(run, tmpname, namebuf, parambuf, depind); }; strcpy(ch, "[is]"); } else if (strstr(ch, "#drain")!=NULL) { strcpy(ch, "[id]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { addSpecialDesc(run, tmpname, namebuf, parambuf, depind); }; strcpy(ch, "[ig]"); } else if (strstr(ch, "#source")!=NULL) { strcpy(ch, "[is]"); if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { addSpecialDesc(run, tmpname, namebuf, parambuf, depind); }; strcpy(ch, "[ib]"); } else if ((strstr(ch, "#internal")!=NULL)&&(tmpname[1]=='d')) { strcpy(ch, "[id]"); } else { fprintf(cp_err, "Debug: could output current for %s\n", tmpname); continue; }; if (parseSpecial(tmpname, namebuf, parambuf, depbuf)) { if (*depbuf) { fprintf( stderr, "Warning : unexpected dependant variable on %s\n", tmpname); } else { addSpecialDesc(run, tmpname, namebuf, parambuf, depind); } } } } } /* Pass 2. */ for (i = 0; i < numsaves; i++) { if (savesused[i]) continue; if (!parseSpecial(saves[i].name, namebuf, parambuf, depbuf)) { if (saves[i].analysis) fprintf(cp_err, "Warning: can't parse '%s': ignored\n", saves[i].name); continue; } /* Now, if there's a dep variable, do we already have it? */ if (*depbuf) { for (j = 0; j < run->numData; j++) if (name_eq(depbuf, run->data[j].name)) break; if (j == run->numData) { /* Better add it. */ for (j = 0; j < numNames; j++) if (name_eq(depbuf, dataNames[j])) break; if (j == numNames) { fprintf(cp_err, "Warning: can't find '%s': value '%s' ignored\n", depbuf, saves[i].name); continue; } addDataDesc(run, dataNames[j], dataType, j); savesused[i] = TRUE; saves[i].used = 1; depind = j; } else depind = run->data[j].outIndex; } addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind); } if (numsaves) { for (i = 0; i < numsaves; i++) { tfree(saves[i].analysis); tfree(saves[i].name); } tfree(savesused); } if (numNames && ( (run->numData == 1 && run->refIndex != -1) || (run->numData == 0 && run->refIndex == -1)) ) /* va: suggested parentheses */ { fprintf(cp_err, "Error: no data saved for %s; analysis not run\n", spice_analysis_get_description(((JOB *) analysisPtr)->JOBtype)); return E_NOTFOUND; } /* Now that we have our own data structures built up, let's see what * nutmeg wants us to do. */ run->writeOut = ft_getOutReq(&run->fp, &run->runPlot, &run->binary, run->type, run->name); if (run->writeOut) fileInit(run); else { plotInit(run); if (refName) run->runPlot->pl_ndims = 1; } } return (OK);}static intaddDataDesc(runDesc *run, char *name, int type, int ind){ dataDesc *data; if (!run->numData) run->data = (dataDesc *) tmalloc(sizeof (dataDesc)); else run->data = (dataDesc *) trealloc((char *) run->data, sizeof (dataDesc) * (run->numData + 1)); data = &run->data[run->numData]; /* so freeRun will get nice NULL pointers for the fields we don't set */ bzero(data, sizeof(dataDesc)); data->name = copy(name); data->type = type; data->gtype = GRID_LIN; data->regular = TRUE; data->outIndex = ind; if (ind == -1) { /* It's the reference vector. */ run->refIndex = run->numData; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -