📄 spiceif.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* * Interface routines. These are specific to spice. The only changes to FTE * that should be needed to make FTE work with a different simulator is * to rewrite this file. What each routine is expected to do can be * found in the programmer's manual. This file should be the only one * that includes spice header files. */#include "spice.h"#include "cpdefs.h"#include "ftedefs.h"#include "fteinp.h"#include "fteconst.h"#include "inpdefs.h"#include "iferrmsg.h"#include "ifsim.h"#include "util.h"#include "suffix.h"static IFvalue *doask();static int doset( );static int finddev();static IFparm * parmlookup();static struct variable *parmtovar();/* Input a single deck, and return a pointer to the circuit. */char *if_inpdeck(deck, tab) struct line *deck; INPtables **tab;{ GENERIC *ckt; int err, i, j; struct line *ll; IFuid taskUid; IFuid optUid; int which = -1; for (i = 0, ll = deck; ll; ll = ll->li_next) i++; *tab = INPtabInit(i); ft_curckt->ci_symtab = *tab; if ((err = (*(ft_sim->newCircuit))(&ckt)) != OK) { ft_sperror(err, "CKTinit"); return (NULL); } err = IFnewUid(ckt,&taskUid,(IFuid)NULL,"default",UID_TASK,(GENERIC**)NULL); if(err) { ft_sperror(err,"newUid"); return(NULL); } err = (*(ft_sim->newTask))(ckt,(GENERIC**)&(ft_curckt->ci_defTask),taskUid); if(err) { ft_sperror(err,"newTask"); return(NULL); } for(j=0;j<ft_sim->numAnalyses;j++) { if(strcmp(ft_sim->analyses[j]->name,"options")==0) { which = j; break; } } if(which != -1) { err = IFnewUid(ckt,&optUid,(IFuid)NULL,"options",UID_ANALYSIS, (GENERIC**)NULL); if(err) { ft_sperror(err,"newUid"); return(NULL); } err = (*(ft_sim->newAnalysis))(ft_curckt->ci_ckt,which,optUid, (GENERIC**)&(ft_curckt->ci_defOpt), (GENERIC*)ft_curckt->ci_defTask); if(err) { ft_sperror(err,"createOptions"); return(NULL); } ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; } ft_curckt->ci_curTask = ft_curckt->ci_defTask; INPpas1((GENERIC *) ckt, (card *) deck->li_next,(INPtables *)*tab); INPpas2((GENERIC *) ckt, (card *) deck->li_next, (INPtables *) *tab,ft_curckt->ci_defTask); INPkillMods(); return (ckt);}/* Do a run of the circuit, of the given type. Type "resume" is special -- * it means to resume whatever simulation that was in progress. The * return value of this routine is 0 if the exit was ok, and 1 if there was * a reason to interrupt the circuit (interrupt typed at the keyboard, * error in the simulation, etc). args should be the entire command line, * e.g. "tran 1 10 20 uic" */intif_run(t, what, args, tab) char *t; char *what; wordlist *args; char *tab;{ GENERIC *ckt = (GENERIC *) t; int err; struct line deck; char buf[BSIZE_SP]; int j; int which = -1; IFuid specUid,optUid; /* First parse the line... */ if (eq(what, "tran") || eq(what, "ac") || eq(what, "dc") || eq(what, "op") || eq(what, "pz") || eq(what,"disto") || eq(what, "adjsen") || eq(what, "sens") || eq(what,"tf") || eq(what, "noise")) { (void) sprintf(buf, ".%s", wl_flatten(args)); deck.li_next = deck.li_actual = NULL; deck.li_error = NULL; deck.li_linenum = 0; deck.li_line = buf; if(ft_curckt->ci_specTask) { err=(*(ft_sim->deleteTask))(ft_curckt->ci_ckt, ft_curckt->ci_specTask); if(err) { ft_sperror(err,"deleteTask"); return(2); } } err = IFnewUid(ft_curckt->ci_ckt,&specUid,(IFuid)NULL,"special", UID_TASK,(GENERIC**)NULL); if(err) { ft_sperror(err,"newUid"); return(2); } err = (*(ft_sim->newTask))(ft_curckt->ci_ckt, (GENERIC**)&(ft_curckt->ci_specTask),specUid); if(err) { ft_sperror(err,"newTask"); return(2); } for(j=0;j<ft_sim->numAnalyses;j++) { if(strcmp(ft_sim->analyses[j]->name,"options")==0) { which = j; break; } } if(which != -1) { err = IFnewUid(ft_curckt->ci_ckt,&optUid,(IFuid)NULL,"options", UID_ANALYSIS,(GENERIC**)NULL); if(err) { ft_sperror(err,"newUid"); return(2); } err = (*(ft_sim->newAnalysis))(ft_curckt->ci_ckt,which,optUid, (GENERIC**)&(ft_curckt->ci_specOpt), (GENERIC*)ft_curckt->ci_specTask); if(err) { ft_sperror(err,"createOptions"); return(2); } ft_curckt->ci_curOpt = ft_curckt->ci_specOpt; } ft_curckt->ci_curTask = ft_curckt->ci_specTask; INPpas2(ckt, (card *) &deck, (INPtables *)tab, ft_curckt->ci_specTask); if (deck.li_error) { fprintf(cp_err, "Warning: %s\n", deck.li_error); return 2; } } if( eq(what,"run") ) { ft_curckt->ci_curTask = ft_curckt->ci_defTask; ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; } if ( (eq(what, "tran")) || (eq(what, "ac")) || (eq(what, "dc")) || (eq(what, "op")) || (eq(what, "pz")) || (eq(what, "disto")) || (eq(what, "noise")) || eq(what, "adjsen") || eq(what, "sens") || eq(what,"tf") || (eq(what, "run")) ) { if ((err = (*(ft_sim->doAnalyses))(ckt, 1, ft_curckt->ci_curTask))!=OK){ ft_sperror(err, "doAnalyses"); /* wrd_end(); */ if (err == E_PAUSE) return (1); else return (2); } } else if (eq(what, "resume")) { if ((err = (*(ft_sim->doAnalyses))(ckt, 0, ft_curckt->ci_curTask))!=OK){ ft_sperror(err, "doAnalyses"); /* wrd_end(); */ if (err == E_PAUSE) return (1); else return (2); } } else { fprintf(cp_err, "if_run: Internal Error: bad run type %s\n", what); return (2); } return (0);}/* Set an option in the circuit. Arguments are option name, type, and * value (the last a char *), suitable for casting to whatever needed... */static char *unsupported[] = { "itl3", "itl5", "lvltim", "maxord", "method", NULL} ;static char *obsolete[] = { "limpts", "limtim", "lvlcod", NULL} ;intif_option(ckt, name, type, value) char *ckt; char *name; int type; char *value;{ IFvalue pval; int err, i; GENERIC *cc = (GENERIC *) ckt; char **vv; int which = -1; if (eq(name, "acct")) { ft_acctprint = true; return 0; } else if (eq(name, "list")) { ft_listprint = true; return 0; } else if (eq(name, "node")) { ft_nodesprint = true; return 0; } else if (eq(name, "opts")) { ft_optsprint = true; return 0; } else if (eq(name, "nopage")) { ft_nopage = true; return 0; } else if (eq(name, "nomod")) { ft_nomod = true; return 0; } for(i=0;i<ft_sim->numAnalyses;i++) { if(strcmp(ft_sim->analyses[i]->name,"options")==0) { which = i; break; } } if(which==-1) { fprintf(cp_err,"Warning: .options line unsupported\n"); return 0; } for (i = 0; i < ft_sim->analyses[which]->numParms; i++) if (eq(ft_sim->analyses[which]->analysisParms[i].keyword, name) && (ft_sim->analyses[which]->analysisParms[i].dataType & IF_SET)) break; if (i == ft_sim->analyses[which]->numParms) { /* See if this is unsupported or obsolete. */ for (vv = unsupported; *vv; vv++) if (eq(name, *vv)) { fprintf(cp_err, "Warning: option %s is currently unsupported.\n", name); return 1; } for (vv = obsolete; *vv; vv++) if (eq(name, *vv)) { fprintf(cp_err, "Warning: option %s is obsolete.\n", name); return 1; } return 0; } switch (ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) { case IF_REAL: if (type == VT_REAL) pval.rValue = *((double *) value); else if (type == VT_NUM) pval.rValue = *((int *) value); else goto badtype; break; case IF_INTEGER: if (type == VT_NUM) pval.iValue = *((int *) value); else if (type == VT_REAL) pval.iValue = *((double *) value); else goto badtype; break; case IF_STRING: if (type == VT_STRING) pval.sValue = copy(value); else goto badtype; break; case IF_FLAG: /* Do nothing. */ pval.iValue = *((int *) value); break; default: fprintf(cp_err, "if_option: Internal Error: bad option type %d.\n", ft_sim->analyses[which]->analysisParms[i].dataType); } if (!ckt) { /* XXX No circuit loaded */ fprintf(cp_err, "Simulation parameter \"%s\" can't be set until\n", name); fprintf(cp_err, "a circuit has been loaded.\n"); return 1; } if ((err = (*(ft_sim->setAnalysisParm))(cc, (GENERIC *)ft_curckt->ci_curOpt, ft_sim->analyses[which]->analysisParms[i].id, &pval, (IFvalue *)NULL)) != OK) ft_sperror(err, "setAnalysisParm(options)"); return 1;badtype: fprintf(cp_err, "Error: bad type given for option %s --\n", name); fprintf(cp_err, "\ttype given was "); switch (type) { case VT_BOOL: fputs("boolean", cp_err); break; case VT_NUM: fputs("integer", cp_err); break; case VT_REAL: fputs("real", cp_err); break; case VT_STRING: fputs("string", cp_err); break; case VT_LIST: fputs("list", cp_err); break; default: fputs("something strange", cp_err); break; } fprintf(cp_err, ", type expected was "); switch(ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) { case IF_REAL: fputs("real.\n", cp_err); break; case IF_INTEGER:fputs("integer.\n", cp_err); break; case IF_STRING: fputs("string.\n", cp_err); break; case IF_FLAG: fputs("flag.\n", cp_err); break; default: fputs("something strange.\n", cp_err); break; } if (type == VT_BOOL)fputs("\t(Note that you must use an = to separate option name and value.)\n", cp_err); return 0;}/* ARGSUSED */voidif_dump(ckt, file) char *ckt; FILE *file;{ /*GENERIC *cc = (GENERIC *) ckt;*/ fprintf(file,"diagnostic output dump unavailable."); return;}voidif_cktfree(ckt, tab) char *ckt; char *tab;{ GENERIC *cc = (GENERIC *) ckt; (*(ft_sim->deleteCircuit))(cc); INPtabEnd((INPtables *) tab); return;}/* Return a string describing an error code. *//* BLOW THIS AWAY.... */char *if_errstring(code) int code;{ return (INPerror(code));}/* Get a parameter value from the circuit. If name is left unspecified, * we want a circuit parameter. */struct variable *spif_getparam(ckt, name, param, ind, do_model) char *ckt; char **name; char *param; int ind; int do_model;{ struct variable *vv = NULL, *tv; IFvalue *pv; IFparm *opt; int typecode, i; GENinstance *dev=(GENinstance *)NULL; GENmodel *mod=(GENmodel *)NULL; IFdevice *device; /* fprintf(cp_err, "Calling if_getparam(%s, %s)\n", *name, param); */ if (param && eq(param, "all")) { INPretrieve(name,(INPtables *)ft_curckt->ci_symtab); typecode = finddev(ckt, *name,(GENERIC**) &dev,(GENERIC**) &mod); if (typecode == -1) { fprintf(cp_err, "Error: no such device or model name %s\n", *name); return (NULL); } device = ft_sim->devices[typecode]; for (i = 0; i < *(device->numInstanceParms); i++) { opt = &device->instanceParms[i]; if(opt->dataType & IF_REDUNDANT || !opt->description) continue; if(!(opt->dataType & IF_ASK)) continue; pv = doask(ckt, typecode, dev, mod, opt, ind); if (pv) { tv = parmtovar(pv, opt); if (vv) tv->va_next = vv; vv = tv; } else fprintf(cp_err, "Internal Error: no parameter '%s' on device '%s'\n", device->instanceParms[i].keyword, device->name); } return (vv); } else if (param) { INPretrieve(name,(INPtables *)ft_curckt->ci_symtab); typecode = finddev(ckt, *name, (GENERIC**)&dev, (GENERIC**)&mod); if (typecode == -1) { fprintf(cp_err, "Error: no such device or model name %s\n", *name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -