⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outitf.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********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 + -