📄 outitf.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group **********//* * 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 "spice.h"#include "misc.h"#include "cpdefs.h"#include "ftedefs.h"#include "ftedata.h"#include "fteconst.h"#include "inpdefs.h" /* for INPtables */#include "ifsim.h"#include "jobdefs.h"#include "iferrmsg.h"#include "suffix.h"extern void gr_end_iplot();extern SPICEanalysis *analInfo[];#define DOUBLE_PRECISION 15typedef struct dataDesc { char *name; /* The name of the vector. */ int type; /* The type. */ int gtype; /* default plot scale */ bool regular; /* Is this given to us? */ int outIndex; /* If regular then the index. */ char *specName; /* The device name if special. */ char *specParamName; /* The parameter name if special. */ int specIndex; /* For sensitivity, if special. */ int specType; GENERIC *specFast; int refIndex; /* The index of our ref vector. */ struct dvec *vec;} dataDesc;typedef struct runDesc { GENERIC *analysis; GENERIC *circuit; char *name; char *type; int numData; int refIndex; dataDesc *data; bool writeOut; bool windowed; bool binary; struct plot *runPlot; FILE *fp; long pointPos; /* where to write pointCount */ int pointCount; int isComplex; int windowCount;} runDesc;static int beginPlot();static int addDataDesc();static int addSpecialDesc();static void fileInit();static void fileInit_pass2( );static void fileStartPoint();static void fileAddRealValue();static void fileAddComplexValue();static void fileEndPoint();static void fileEnd();static void plotInit();static void plotAddRealValue();static void plotAddComplexValue();static void plotEnd();static bool parseSpecial();static bool name_eq();static bool getSpecial();static void freeRun();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(circuitPtr, analysisPtr, analName, refName, refType, numNames, dataNames, dataType, plotPtr) GENERIC *circuitPtr; GENERIC *analysisPtr; IFuid analName; IFuid refName; int refType; int numNames; IFuid *dataNames; int dataType; GENERIC **plotPtr;{ char *name;#ifdef PARALLEL_ARCH if (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(circuitPtr, analysisPtr, analName, refName, refType, numNames, dataNames, dataType, plotPtr) GENERIC *circuitPtr; GENERIC *analysisPtr; IFuid analName; IFuid refName; int refType; int numNames; IFuid *dataNames; int dataType; GENERIC **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(analysisPtr, circuitPtr, cktName, analName, refName, refType, numNames, dataNames, dataType, windowed, runp) GENERIC *analysisPtr; GENERIC *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; int numsaves; int i, j, depind; char namebuf[BSIZE_SP], parambuf[BSIZE_SP], depbuf[BSIZE_SP]; bool saveall = true; char *an_name; /* 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 = analInfo[((JOB *) analysisPtr)->JOBtype]->public.name; /* 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(saves[i].analysis, an_name)) { /* ignore this one this time around */ savesused[i] = true; continue; } if (cieq(saves[i].name, "all")) { saveall = 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)) { addDataDesc(run, dataNames[i], dataType, i); } } /* 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)) { fprintf(cp_err, "Error: no data saved for %s; analysis not run\n", analInfo[((JOB *) analysisPtr)->JOBtype]->public.description); 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(run, name, type, ind) 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; } run->numData++; return (OK);}static intaddSpecialDesc(run, name, devname, param, depind) runDesc *run; char *name; char *devname; char *param; int depind;{ dataDesc *data; char *unique; /* unique char * from back-end */ 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); unique = devname; INPinsert(&unique, (INPtables *) ft_curckt->ci_symtab); data->specName = unique; data->specParamName = copy(param); data->specIndex = depind; data->specType = -1; data->specFast = NULL; data->regular = false; run->numData++; return (OK);}intOUTpData(plotPtr, refValue, valuePtr) GENERIC *plotPtr; IFvalue *refValue; IFvalue *valuePtr;{ runDesc *run = (runDesc *) plotPtr; IFvalue val; int i;#ifdef PARALLEL_ARCH if (ARCHme != 0) return(OK);#endif /* PARALLEL_ARCH */ run->pointCount++; if (run->writeOut) { if (run->pointCount == 1) fileInit_pass2(plotPtr); fileStartPoint(run->fp, run->binary, run->pointCount); if (run->refIndex != -1) { if (run->isComplex) fileAddComplexValue(run->fp, run->binary, refValue->cValue); else fileAddRealValue(run->fp, run->binary, refValue->rValue); } for (i = 0; i < run->numData; i++) { /* we've already printed reference vec first */ if (run->data[i].outIndex == -1) continue; if (run->data[i].regular) { if(run->data[i].type == IF_REAL) fileAddRealValue(run->fp, run->binary, valuePtr->v.vec.rVec [run->data[i].outIndex]); else if (run->data[i].type == IF_COMPLEX) fileAddComplexValue(run->fp, run->binary, valuePtr->v.vec.cVec [run->data[i].outIndex]); else fprintf(stderr, "OUTpData: unsupported data type\n"); } else { /* should pre-check instance */ if (!getSpecial(&run->data[i], run, &val)) continue; if (run->data[i].type == IF_REAL) fileAddRealValue(run->fp, run->binary, val.rValue); else if (run->data[i].type == IF_COMPLEX) fileAddComplexValue(run->fp, run->binary, val.cValue); else fprintf(stderr, "OUTpData: unsupported data type\n"); } } fileEndPoint(run->fp, run->binary); } else { for (i = 0; i < run->numData; i++) { 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 { /* 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"); } } gr_iplot(run->runPlot); } if (ft_bpcheck(run->runPlot, run->pointCount) == false) shouldstop = true; return (OK);}/* ARGSUSED */ /* until some code gets written */intOUTwReference(plotPtr, valuePtr, refPtr) GENERIC *plotPtr; IFvalue *valuePtr; GENERIC **refPtr;{ return (OK);}/* ARGSUSED */ /* until some code gets written */intOUTwData(plotPtr, dataIndex, valuePtr, refPtr) GENERIC *plotPtr; int dataIndex; IFvalue *valuePtr; GENERIC *refPtr;{ return (OK);}/* ARGSUSED */ /* until some code gets written */intOUTwEnd(plotPtr) GENERIC *plotPtr;{ return (OK);}intOUTendPlot(plotPtr) GENERIC *plotPtr;{ runDesc *run = (runDesc *) plotPtr;#ifdef PARALLEL_ARCH if (ARCHme != 0) return(OK);#endif /* PARALLEL_ARCH */ if (run->writeOut) fileEnd(run); else { gr_end_iplot(); plotEnd(run); } freeRun(run);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -