Jspice3
spiceif.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Interface routines. These are specific to spice. The only changes to FTE
10  * that should be needed to make FTE work with a different simulator is
11  * to rewrite this file. What each routine is expected to do can be
12  * found in the programmer's manual. This file should be the only one
13  * that includes spice header files.
14  */
15 
16 #include "spice.h"
17 #include "ftedefs.h"
18 #include "ftedebug.h"
19 #include "spfteext.h"
20 #include "inpdefs.h"
21 #include "fteinp.h"
22 #include "jobdefs.h"
23 #include "iferrmsg.h"
24 #include "util.h"
25 
26 #ifdef __STDC__
27 static int get_anal(char*);
28 static void set_options(void);
29 static struct variable *parmtovar(IFvalue*,IFparm*);
30 static IFparm * parmlookup(IFdevice*,GENinstance*,GENmodel*,char*);
31 static IFvalue *doask(char*,int,GENinstance*,GENmodel*,IFparm*,int);
32 static int finddev(char*,char*,GENERIC**,GENERIC**);
33 #else
34 static int get_anal();
35 static void set_options();
36 static struct variable *parmtovar();
37 static IFparm * parmlookup();
38 static IFvalue *doask();
39 static int finddev();
40 #endif
41 
42 
43 char *
45 
46 /* Input a single deck, and return a pointer to the circuit. */
47 struct line *deck;
48 char **tab;
49 {
50  GENERIC *ckt;
51  int err, i, j;
52  struct line *ll;
53  IFuid taskUid;
54  IFuid optUid;
55  int which;
56 
57  for (i = 0, ll = deck; ll; ll = ll->li_next)
58  i++;
59  *tab = (char *)INPtabInit(i);
61  if ((err = (*(ft_sim->newCircuit))(&ckt)) != OK) {
62  ft_sperror(err, "CKTinit");
63  return (NULL);
64  }
65  err =
66  IFnewUid(ckt,&taskUid,(IFuid)NULL,"default",UID_TASK,(GENERIC**)NULL);
67  if (err) {
68  ft_sperror(err,"newUid");
69  return (NULL);
70  }
71  err =
72  (*(ft_sim->newTask))(ckt,(GENERIC**)&(ft_curckt->ci_defTask),taskUid);
73  if (err) {
74  ft_sperror(err,"newTask");
75  return (NULL);
76  }
77  which = get_anal("options");
78  if (which != -1) {
79  err = IFnewUid(ckt,&optUid,(IFuid)NULL,"options",UID_ANALYSIS,
80  (GENERIC**)NULL);
81  if (err) {
82  ft_sperror(err,"newUid");
83  return (NULL);
84  }
85  err = (*(ft_sim->newAnalysis))(ckt,which,optUid,
88  if (err) {
89  ft_sperror(err,"createOptions");
90  return (NULL);
91  }
93  }
95  INPpas1((GENERIC *) ckt, (card *) deck->li_next,(INPtables *)*tab);
96  INPpas2((GENERIC *) ckt, (card *) deck->li_next,
97  (INPtables *) *tab,ft_curckt->ci_defTask);
98  INPkillMods();
99  return (ckt);
100 }
101 
102 
103 int
104 if_run(what, args)
105 
106 /* Do a run of the circuit, of the given type. Type "resume" is special --
107  * it means to resume whatever simulation that was in progress. The
108  * return value of this routine is 0 if the exit was ok, and 1 if there was
109  * a reason to interrupt the circuit (interrupt typed at the keyboard,
110  * error in the simulation, etc).
111  * args may be the entire command line,
112  * e.g. "tran 1 10 20 uic",
113  * or only the arguments that follow "what".
114  */
115 char *what;
116 wordlist *args;
117 {
118  GENERIC *ckt = (GENERIC *)ft_curckt->ci_ckt;
120  int err;
121  struct line deck;
122  char buf[BSIZE_SP], *tmp;
123  int j;
124  int which;
125  IFuid specUid,optUid;
126 
127  /* First parse the line... */
128  if (eq(what,"sens") || eq(what, "tran") || eq(what, "ac") ||
129  eq(what, "dc") || eq(what, "op") || eq(what, "pz") ||
130  eq(what,"disto")|| eq(what,"tf") || eq(what, "noise")) {
131 
132  if (args) {
133  tmp = wl_flatten(args);
134  if (ciprefix(what,tmp))
135  (void) sprintf(buf, ".%s", tmp);
136  else
137  (void) sprintf(buf, ".%s %s", what, tmp);
138  txfree(tmp);
139  }
140  else
141  (void) sprintf(buf, ".%s", what);
142 
143  deck.li_next = deck.li_actual = NULL;
144  deck.li_error = NULL;
145  deck.li_linenum = 0;
146  deck.li_line = buf;
147 
148  if (ft_curckt->ci_specTask) {
149  err = (*(ft_sim->deleteTask))(ckt, ft_curckt->ci_specTask);
150  if (err) {
151  ft_sperror(err,"deleteTask");
152  return (2);
153  }
154  }
155  err = IFnewUid(ckt,&specUid,(IFuid)NULL,"special",
156  UID_TASK,(GENERIC**)NULL);
157  if (err) {
158  ft_sperror(err,"newUid");
159  return (2);
160  }
161  err = (*(ft_sim->newTask))(ckt,
162  (GENERIC**)&(ft_curckt->ci_specTask),specUid);
163  if (err) {
164  ft_sperror(err,"newTask");
165  return (2);
166  }
167  which = get_anal("options");
168  if (which != -1) {
169  err = IFnewUid(ckt,&optUid,(IFuid)NULL,"options",
170  UID_ANALYSIS,(GENERIC**)NULL);
171  if (err) {
172  ft_sperror(err,"newUid");
173  return (2);
174  }
175  err = (*(ft_sim->newAnalysis))(ckt,which,optUid,
178  if (err) {
179  ft_sperror(err,"createOptions");
180  return (2);
181  }
183  set_options();
184  }
186 
187  INPpas2(ckt, (card *) &deck, tab, ft_curckt->ci_specTask);
188  if (deck.li_error) {
189  /* INP produdes an E_EXISTS error here... Don't
190  * make this fatal...
191  */
192  fprintf(cp_err, "Warning: %s\n", deck.li_error);
193  }
194  }
195  if ( eq(what,"run") ) {
198  }
199 
200  if ( (eq(what, "tran")) ||
201  (eq(what, "ac")) ||
202  (eq(what, "dc")) ||
203  (eq(what, "op")) ||
204  (eq(what, "pz")) ||
205  (eq(what, "disto")) ||
206  (eq(what, "sens")) ||
207  (eq(what, "noise")) ||
208  (eq(what, "tf")) ||
209  (eq(what, "run")) ) {
210  if ((err =
211  (*(ft_sim->doAnalyses))(ckt, 1, ft_curckt->ci_curTask)) != OK) {
212  if (err == E_PAUSE)
213  return (1);
214  else {
215  ft_sperror(err, "doAnalyses");
216  return (2);
217  }
218  }
219  }
220  else if (eq(what, "resume")) {
221  if ((err =
222  (*(ft_sim->doAnalyses))(ckt, 0, ft_curckt->ci_curTask)) != OK) {
223  if (err == E_PAUSE)
224  return (1);
225  else {
226  ft_sperror(err, "doAnalyses");
227  return (2);
228  }
229  }
230  }
231  else {
232  fprintf(cp_err, "if_run: Internal Error: bad run type %s\n", what);
233  return (2);
234  }
235  return (0);
236 }
237 
238 
239 static int
240 get_anal(string)
241 char *string;
242 {
243  int i;
244 
245  for (i = 0; i < ft_sim->numAnalyses; i++) {
246  if (strcmp(ft_sim->analyses[i]->name,string) == 0) {
247  return (i);
248  }
249  }
250  return (-1);
251 }
252 
253 
254 static void
256 
257 /* Set the options for the "special" task. If analysis is initiated with
258  * the "run" command, we use the options found in the .options line only,
259  * which have already been set (so this routine need not be called).
260  * Otherise if an analysis is given, a new task is created. This routine
261  * is called to first set the options found in the .options line, then
262  * (laboriously) set any options that were entered with the "set" command.
263  * The options set with the "set" command override those set in the
264  * .options line. Note that if "run" is used, the "set" options are
265  * ignored.
266  */
267 {
268  int i, which, type;
269  char *name, *vv;
270  double f;
271  struct variable *var;
272  struct line *opt;
273 
274 
275  for (opt = ft_curckt->ci_options; opt; opt = opt->li_next) {
276  txfree(opt->li_error);
277  opt->li_error = NULL;
279  (card*)opt,NULL,NULL);
280  }
281 
282  /* set the "set" variables */
283  which = get_anal("options");
284  if (which == -1) return;
285 
286  for (i = 0; i < ft_sim->analyses[which]->numParms; i++) {
287  type = ft_sim->analyses[which]->analysisParms[i].dataType;
288  if (type & IF_SET) {
289 
290  name = ft_sim->analyses[which]->analysisParms[i].keyword;
291 
292  if (type & IF_FLAG) {
293  if (cp_getvar(name,VT_BOOL,(char*)&f))
294  if_option(ft_curckt->ci_ckt, name, VT_BOOL, (char*)&f);
295  }
296  else if (type & IF_INTEGER) {
297  if (cp_getvar(name,VT_NUM,(char*)&f))
298  if_option(ft_curckt->ci_ckt, name, VT_NUM, (char*)&f);
299  }
300  else if (type & IF_REAL) {
301  if (cp_getvar(name,VT_REAL,(char*)&f))
302  if_option(ft_curckt->ci_ckt, name, VT_REAL, (char*)&f);
303  }
304  else if (type & IF_STRING) {
305  if (cp_getvar(name,VT_STRING,(char*)&f))
306  if_option(ft_curckt->ci_ckt, name, VT_STRING, (char*)&f);
307  }
308  }
309  }
310 }
311 
312 static char *unsupported[] = {
313  "itl3",
314  "itl5",
315  "lvltim",
316  "maxord",
317  "method",
318  NULL
319 } ;
320 
321 static char *obsolete[] = {
322  "limpts",
323  "limtim",
324  "lvlcod",
325  "nomod",
326  NULL
327 } ;
328 
329 
330 void
331 if_option(ckt, name, type, value)
332 
333 /* Set an option in the circuit. Arguments are option name, type, and
334  * value (the last a char *), suitable for casting to whatever needed...
335  */
336 char *ckt;
337 char *name;
338 int type;
339 char *value;
340 {
341  IFvalue pval;
342  int err, i;
343  GENERIC *cc = (GENERIC *) ckt;
344  char **vv;
345  int which;
346 
347  if (eq(name, "acct")) {
348  ft_acctprint = true;
349  return;
350  }
351  else if (eq(name, "list")) {
352  ft_listprint = true;
353  return;
354  }
355  else if (eq(name, "node")) {
356  ft_nodesprint = true;
357  return;
358  }
359  else if (eq(name, "opts")) {
360  ft_optsprint = true;
361  return;
362  }
363  else if (eq(name, "nopage")) {
364  ft_nopage = true;
365  return;
366  }
367 
368  which = get_anal("options");
369  if (which == -1) {
370  fprintf(cp_err,"Warning: .options card unsupported\n");
371  return;
372  }
373 
374  for (i = 0; i < ft_sim->analyses[which]->numParms; i++)
375  if (eq(ft_sim->analyses[which]->analysisParms[i].keyword, name) &&
376  (ft_sim->analyses[which]->analysisParms[i].dataType & IF_SET))
377  break;
378  if (i == ft_sim->analyses[which]->numParms) {
379  /* See if this is unsupported or obsolete. */
380  for (vv = unsupported; *vv; vv++)
381  if (eq(name, *vv)) {
382  fprintf(cp_err,
383  "Warning: option %s is currently unsupported.\n", name);
384  return;
385  }
386  for (vv = obsolete; *vv; vv++)
387  if (eq(name, *vv)) {
388  fprintf(cp_err,
389  "Warning: option %s is obsolete.\n", name);
390  return;
391  }
392  return;
393  }
394 
395  switch (ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) {
396  case IF_REAL:
397  if (type == VT_REAL)
398  pval.rValue = *((double *) value);
399  else if (type == VT_NUM)
400  pval.rValue = *((int *) value);
401  else
402  goto badtype;
403  break;
404  case IF_INTEGER:
405  if (type == VT_NUM)
406  pval.iValue = *((int *) value);
407  else if (type == VT_REAL)
408  pval.iValue = *((double *) value);
409  else
410  goto badtype;
411  break;
412  case IF_STRING:
413  if (type == VT_STRING)
414  pval.sValue = copy(value);
415  else
416  goto badtype;
417  break;
418  case IF_FLAG:
419  /* Do nothing. */
420  pval.iValue = 1;
421  break;
422  default:
423  fprintf(cp_err,
424  "if_option: Internal Error: bad option type %d.\n",
425  ft_sim->analyses[which]->analysisParms[i].dataType);
426  }
427 
428  if ((err = (*(ft_sim->setAnalysisParm))(cc, (GENERIC *)ft_curckt->ci_curOpt,
429  ft_sim->analyses[which]->analysisParms[i].id, &pval,
430  (IFvalue *)NULL)) != OK)
431  ft_sperror(err, "setAnalysisParm(options)");
432 
433  return;
434 
435 badtype:
436  fprintf(cp_err, "Error: bad type given for option %s --\n", name);
437  fprintf(cp_err, "\ttype given was ");
438  switch (type) {
439  case VT_BOOL: fputs("boolean", cp_err); break;
440  case VT_NUM: fputs("integer", cp_err); break;
441  case VT_REAL: fputs("real", cp_err); break;
442  case VT_STRING: fputs("string", cp_err); break;
443  case VT_LIST: fputs("list", cp_err); break;
444  default: fputs("something strange", cp_err); break;
445  }
446  fprintf(cp_err, ", type expected was ");
447  switch(ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) {
448  case IF_REAL: fputs("real.\n", cp_err); break;
449  case IF_INTEGER:fputs("integer.\n", cp_err); break;
450  case IF_STRING: fputs("string.\n", cp_err); break;
451  case IF_FLAG: fputs("flag.\n", cp_err); break;
452  default: fputs("something strange.\n", cp_err); break;
453  }
454  if (type == VT_BOOL)
455 fputs("\t(Note that you must use an = to separate option name and value.)\n",
456  cp_err);
457  return;
458 }
459 
460 
461 void
463 
464 char *ckt;
465 char *tab;
466 {
467  GENERIC *cc = (GENERIC *) ckt;
468 
469  (*(ft_sim->deleteCircuit))(cc);
470  INPtabEnd((INPtables *) tab);
471  return;
472 }
473 
474 
475 void
477 
478 /* Delete the current circuit.
479  * This blows away all the peripheral stuff, unlike if_cktfree() which only
480  * frees the ckt structure and input tables.
481  */
482 {
483  struct circ *cc;
484 
485  if (!ft_curckt) return;
490 
491  (*(ft_sim->deleteTask))(ft_curckt->ci_ckt,ft_curckt->ci_specTask);
492  (*(ft_sim->deleteTask))(ft_curckt->ci_ckt,ft_curckt->ci_defTask);
494 
496 
497  if (ft_curckt->ci_contblk) {
498  for (cc = ft_circuits; cc; cc = cc->ci_next) {
499  if (cc == ft_curckt)
500  continue;
501  if (cc->ci_contblk && eq(cc->ci_contblk,ft_curckt->ci_contblk))
502  break;
503  }
504  if (!cc) {
505  if (prefix("#_",ft_curckt->ci_contblk)) {
507  ft_curckt->ci_contblk[1] = '#';
509  }
510  }
512  }
513 
519 
520  if (ft_curckt == ft_circuits) {
521  tfree(ft_curckt);
523  }
524  else {
525  for (cc = ft_circuits; cc; cc = cc->ci_next)
526  if (cc->ci_next == ft_curckt)
527  break;
528 
529  if (!cc) {
530  fprintf(cp_err,"Internal Error: cktfree -- not in list\n");
531  goto xxx;
532  }
533  cc->ci_next = ft_curckt->ci_next;
534  tfree(ft_curckt);
535  ft_curckt = cc;
536  }
537 xxx:
538  if (ft_curckt) {
541  }
542 }
543 
544 /* Return a string describing an error code. */
545 
546 
547 /* BLOW THIS AWAY.... */
548 
549 char *
551 
552 int code;
553 {
554  return (INPerror(code));
555 }
556 
557 
558 struct variable *
559 spif_getparam(ckt, name, param, ind, keyword)
560 
561 /* Get a parameter value from the circuit. If name is left unspecified,
562  * we want a circuit parameter. If keywords is not null, a list of
563  * matching keywords is built.
564  */
565 char *ckt;
566 char **name;
567 char *param;
568 int ind;
569 wordlist **keyword;
570 {
571  struct variable *vv, *tv;
572  IFvalue *pv;
573  IFparm *opt;
574  int typecode, i, num;
575  GENinstance *dev = (GENinstance *)NULL;
576  GENmodel *mod = (GENmodel *)NULL;
577  IFdevice *device;
578  wordlist *ww;
579 
580  if (param && eq(param, "all")) {
582  typecode = finddev(ckt, *name,(GENERIC**) &dev,(GENERIC**) &mod);
583  if (typecode == -1) {
584  fprintf(cp_err,
585  "Error: no such device or model name %s\n", *name);
586  return (NULL);
587  }
588  device = ft_sim->devices[typecode];
589  vv = tv = (struct variable*)NULL;
590  if (dev) {
591  num = *(device->numInstanceParms);
592  opt = device->instanceParms;
593  }
594  else {
595  num = *(device->numModelParms);
596  opt = device->modelParms;
597  }
598  if (opt) {
599  for (i = 0; i < num; i++, opt++) {
600  if (!(opt->dataType & IF_ASK)) continue;
601  pv = doask(ckt, typecode, dev, mod, opt, ind);
602  if (pv) {
603  if (tv) {
604  if (keyword) {
605  ww->wl_next = alloc(struct wordlist);
606  ww = ww->wl_next;
607  ww->wl_word = copy(opt->keyword);
608  }
609  tv->va_next = parmtovar(pv,opt);
610  tv = tv->va_next;
611  }
612  else {
613  if (keyword) {
614  *keyword = ww = alloc(struct wordlist);
615  ww->wl_word = copy(opt->keyword);
616  }
617  vv = tv = parmtovar(pv,opt);
618  }
619  }
620  else
621  fprintf(cp_err,
622  "Internal Error: no parameter '%s' on device '%s'\n",
623  device->instanceParms[i].keyword,
624  device->name);
625  }
626  return (vv);
627  }
628  else
629  return (NULL);
630  }
631  else if (param) {
633  typecode = finddev(ckt, *name, (GENERIC**)&dev, (GENERIC**)&mod);
634  if (typecode == -1) {
635  fprintf(cp_err,
636  "Error: no such device or model name %s\n", *name);
637  return (NULL);
638  }
639  device = ft_sim->devices[typecode];
640  opt = parmlookup(device, dev, mod, param);
641  if (!opt) {
642  fprintf(cp_err, "Error: no such parameter %s.\n", param);
643  return (NULL);
644  }
645  pv = doask(ckt, typecode, dev, mod, opt, ind);
646  if (pv) {
647  if (keyword) {
648  *keyword = alloc(struct wordlist);
649  (*keyword)->wl_word = copy(opt->keyword);
650  }
651  vv = parmtovar(pv, opt);
652  }
653  return (vv);
654  }
655  else
656  return (if_getstat(ckt, *name, keyword));
657 }
658 
659 
660 /* ARGSUSED */
661 void
662 if_setparam(ckt, name, param, val)
663 
664 char *ckt;
665 char *name;
666 char *param;
667 struct variable *val;
668 {
669 }
670 
671 
672 static struct variable *
673 parmtovar(pv, opt)
674 
675 IFvalue *pv;
676 IFparm *opt;
677 {
678  struct variable *tv, *vv = alloc(struct variable);
679  int i = 0;
680 
681  switch (opt->dataType & IF_VARTYPES) {
682  case IF_INTEGER:
683  vv->va_type = VT_NUM;
684  vv->va_num = pv->iValue;
685  break;
686  case IF_REAL:
687  case IF_COMPLEX:
688  vv->va_type = VT_REAL;
689  vv->va_real = pv->rValue;
690  break;
691  case IF_STRING:
692  vv->va_type = VT_STRING;
693  vv->va_string = copy(pv->sValue);
694  break;
695  case IF_INSTANCE:
696  vv->va_type = VT_STRING;
697  vv->va_string = copy((char*)pv->uValue);
698  break;
699  case IF_FLAG:
700  vv->va_type = VT_BOOL;
701  vv->va_bool = pv->iValue ? true : false;
702  break;
703  case IF_REALVEC:
704  vv->va_type = VT_LIST;
705  tv = NULL;
706  for (i = 0; i < pv->v.numValue; i++) {
707  if (!tv)
708  tv = vv->va_vlist = alloc(struct variable);
709  else {
710  tv->va_next = alloc(struct variable);
711  tv = tv->va_next;
712  }
713  tv->va_type = VT_REAL;
714  tv->va_real = (pv->v.vec.rVec)[i];
715  }
716  break;
717  case IF_PARSETREE:
718  vv->va_type = VT_STRING;
719  vv->va_string = NULL;
720  if (pv->tValue)
721  vv->va_string = copy(pv->tValue->line);
722  break;
723  default:
724  fprintf(cp_err,
725  "parmtovar: Internal Error: bad PARM type %d.\n",
726  opt->dataType);
727  tfree(vv);
728  return (NULL);
729  }
730 
731  /* It's not clear whether we want the keyword or the desc here... */
732  vv->va_name = copy(opt->description);
733  return (vv);
734 }
735 
736 
737 static IFparm *
738 parmlookup(device, dev, mod, param)
739 
740 /* Extract the IFparm structure from the device. A match is assumed if
741  * param is a case insensitive match of the IFdevice keyword. If inptr
742  * is not NULL, the devices are checked first. *inptr is NULLed if
743  * no matching device is found, and a model is returned if there is a
744  * match.
745  */
747 GENinstance *dev;
748 GENmodel *mod;
749 char *param;
750 {
751  int i;
752 
753  if (dev) {
754  for (i = 0; i < *(device->numInstanceParms); i++) {
755  if ((device->instanceParms[i].dataType & IF_ASK) &&
756  cieq(param,device->instanceParms[i].keyword))
757  return (&device->instanceParms[i]);
758  }
759  }
760  else if (mod) {
761  if (device->modelParms == NULL)
762  return (NULL);
763  for (i = 0; i < *(device->numModelParms); i++)
764  if ((device->modelParms[i].dataType & IF_ASK) &&
765  cieq(param,device->modelParms[i].keyword))
766  return (&device->modelParms[i]);
767  }
768  return (NULL);
769 }
770 
771 
772 /* ARGSUSED */
773 static IFvalue *
774 doask(ckt, typecode, dev, mod, opt, ind)
775 
776 /* Perform the CKTask call. We have both 'fast' and 'modfast', so the other
777  * parameters aren't necessary.
778  */
779 char *ckt;
780 GENinstance *dev;
781 GENmodel *mod;
782 IFparm *opt;
783 int ind;
784 {
785  static IFvalue pv;
786  int err;
787 
788  pv.rValue = 0.0;
789  pv.iValue = ind; /* Sometimes this will be junk and ignored... */
790 
791  if (dev)
792  err = (*(ft_sim->askInstanceQuest))((GENERIC *)ckt, (GENERIC *)dev,
793  opt->id, &pv, (IFvalue *)NULL);
794  else
795  err = (*(ft_sim->askModelQuest))((GENERIC*)ckt, (GENERIC*) mod,
796  opt->id, &pv, (IFvalue *)NULL);
797  if (err != OK) {
798  ft_sperror(err, "doask");
799  return (NULL);
800  }
801 
802  return (&pv);
803 }
804 
805 
806 static int
807 finddev(ck, name, devptr, modptr)
808 
809 /* Get pointers to a device, its model, and its type number given the name.
810  * If there is no such device, try to find a model with that name.
811  */
812 char *ck;
813 char *name;
814 GENERIC **devptr;
815 GENERIC **modptr;
816 {
817  int err;
818  int type = -1;
819 
820  err =
821  (*(ft_sim->findInstance))((GENERIC *)ck,&type,devptr,name,NULL,NULL);
822  if (err == OK)
823  return (type);
824 
825  type = -1;
826  *devptr = (GENERIC *)NULL;
827 
828  err = (*(ft_sim->findModel))((GENERIC *)ck,&type,modptr,name);
829  if (err == OK)
830  return(type);
831 
832  *modptr = (GENERIC *)NULL;
833  return (-1);
834 }
835 
836 
837 /* Extract the node and device names from the line and add them to the command
838  * completion structure. This is probably not a good thing to do if it
839  * takes too much time.
840  */
841 
842 void
844 
845 char *line;
846 {
847  int i;
848  char buf[BSIZE_SP];
849 
850  while (isspace(*line))
851  line++;
852 
853  if (!*line || (*line == '*'))
854  return;
855  if (*line == '.') {
856  line++;
857  if (prefix("model",line)) {
858  copytok(buf,&line);
859  copytok(buf,&line);
860  cp_addkword(CT_DEVNAMES, buf);
861  }
862  return;
863  }
864  copytok(buf,&line);
865  cp_addkword(CT_DEVNAMES, buf);
866 
867 /* inefficient and not very useful */
868 /*
869  if (!(i = inp_numnodes(*buf)))
870  return;
871  if ((*buf == 'q') || (*buf == 'Q'))
872  i = 3;
873 
874  while (i-- > 0) {
875  if (copytok(buf,&line))
876  cp_addkword(CT_NODENAMES, buf);
877  }
878  return;
879 */
880 }
881 
882 
883 struct variable *
884 if_getstat(ckt, name, keyword)
885 
886 /* Get the statistic called 'name'. If this is NULL get all statistics
887  * available. If keyword is not null, it returns a wordlist of actual
888  * keyword matches. A match is assumed if name is a case insensitive
889  * prefix of the keyword.
890  */
891 char *ckt;
892 char *name;
893 wordlist **keyword;
894 {
895  int i;
896  struct variable *v, *vars;
897  IFvalue parm;
898  int which;
899  wordlist *ww;
900 
901  which = get_anal("options");
902  if (which == -1) {
903  fprintf(cp_err,"Warning: statistics unsupported\n");
904  return(NULL);
905  }
906 
907  if (name) {
908  for (i = 0; i < ft_sim->analyses[which]->numParms; i++)
909  if (ciprefix(name,
910  ft_sim->analyses[which]->analysisParms[i].keyword))
911  break;
912  if (i == ft_sim->analyses[which]->numParms)
913  return (NULL);
914  if ((*(ft_sim->askAnalysisQuest))(ckt, ft_curckt->ci_curTask,
915  ft_sim->analyses[which]->analysisParms[i].id, &parm,
916  (IFvalue *)NULL) == -1) {
917  goto error;
918  }
919  if (keyword) {
920  *keyword = alloc(struct wordlist);
921  (*keyword)->wl_word = copy(
922  ft_sim->analyses[which]->analysisParms[i].keyword);
923  }
924  return (parmtovar(&parm,
925  &(ft_sim->analyses[which]->analysisParms[i])));
926  }
927  else {
928  for (i = 0, vars = v = NULL;
929  i < ft_sim->analyses[which]->numParms; i++) {
930  if (!(ft_sim->analyses[which]->analysisParms[i].dataType&IF_ASK)) {
931  continue;
932  }
933  if ((*(ft_sim->askAnalysisQuest))(ckt, ft_curckt->ci_curTask,
934  ft_sim->analyses[which]->analysisParms[i].id,
935  &parm, (IFvalue *)NULL) == -1) {
936  goto error;
937  }
938  if (v) {
939  if (keyword) {
940  ww->wl_next = alloc(struct wordlist);
941  ww = ww->wl_next;
942  ww->wl_word = copy(
943  ft_sim->analyses[which]->analysisParms[i].keyword);
944  }
945  v->va_next = parmtovar(&parm,
946  &(ft_sim->analyses[which]->analysisParms[i]));
947  v = v->va_next;
948  }
949  else {
950  if (keyword) {
951  *keyword = ww = alloc(struct wordlist);
952  ww->wl_word = copy(
953  ft_sim->analyses[which]->analysisParms[i].keyword);
954  }
955  vars = v = parmtovar(&parm,
956  &(ft_sim->analyses[which]->analysisParms[i]));
957  }
958  }
959  return (vars);
960  }
961 error:
962  fprintf(cp_err,"if_getstat: Internal Error: can't get %s.\n",name);
963  return NULL;
964 }
965 
966 
967 wordlist *
969 {
970  wordlist *tl1 = NULL;
971  int numjobs;
972 
973  if (!(*ft_sim->findAnalysis)(ft_curckt->ci_ckt,&numjobs,
975 
976  if (numjobs != 1)
977  return (NULL);
978 
979  /* one analysis specified in file */
982  tl1 = alloc(wordlist);
983  tl1->wl_word = copy("run");
984  }
985  return (tl1);
986 }
987 
988 
989 int
991 {
992  return (ft_curckt && ft_curckt->ci_inprogress);
993 }
994 
995 
996 int
998 {
999  struct dbcomm *d;
1000  extern struct dbcomm *dbiplot;
1001 
1002  for (d = dbiplot; d; d = d->db_next) {
1003  if (d->db_type == DB_IPLOT) return (true);
1004  if (d->db_type == DB_IPLOTALL) return (true);
1005  }
1006  return (false);
1007 }
bool ft_acctprint
Definition: main.c:191
int li_linenum
Definition: fteinp.h:15
struct line * li_actual
Definition: fteinp.h:19
#define E_PAUSE
Definition: iferrmsg.h:15
static char buf[MAXPROMPT]
Definition: arg.c:18
struct dbcomm * dbiplot
Definition: main.c:186
#define BSIZE_SP
Definition: misc.h:19
#define eq(a, b)
Definition: misc.h:29
DISPDEVICE device[]
Definition: display.c:24
Definition: variable.c:632
int ciprefix()
struct circ * ci_next
Definition: ftedefs.h:37
#define IF_COMPLEX
Definition: ifsim.h:109
int if_run(char *what, wordlist *args)
Definition: spiceif.c:104
wordlist * GetAnalysisFromDeck()
Definition: spiceif.c:968
Definition: subckt.c:18
char * INPerror()
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
IFsimulator * ft_sim
Definition: main.c:111
static struct variable * parmtovar()
char * ci_specTask
Definition: ftedefs.h:42
int cieq()
#define prefix(x, y)
Definition: readhelp.c:39
int * numInstanceParms
Definition: ifsim.h:312
Definition: ftedefs.h:25
int IFnewUid()
char * ci_defOpt
Definition: ftedefs.h:44
#define UID_TASK
Definition: ifsim.h:81
char * name
Definition: ifsim.h:336
struct variable * spif_getparam(char *ckt, char **name, char *param, int ind, wordlist **keyword)
Definition: spiceif.c:559
struct line * ci_deck
Definition: ftedefs.h:30
char * ci_devices
Definition: ftedefs.h:39
int * numModelParms
Definition: ifsim.h:315
#define IF_ASK
Definition: ifsim.h:136
IFparm * instanceParms
Definition: ifsim.h:313
char * ci_curOpt
Definition: ftedefs.h:46
Definition: inpdefs.h:62
#define VT_LIST
Definition: cpstd.h:64
struct line * ci_options
Definition: ftedefs.h:32
bool ci_inprogress
Definition: ftedefs.h:34
static char * obsolete[]
Definition: spiceif.c:321
char * ci_ckt
Definition: ftedefs.h:27
bool ft_listprint
Definition: main.c:188
Definition: subckt.c:51
char * ci_filename
Definition: ftedefs.h:40
#define tab(num)
Definition: front.c:1365
INPtables * INPtabInit()
void if_setndnames(char *line)
Definition: spiceif.c:843
void INPpas2()
char * ci_contblk
Definition: ftedefs.h:29
#define IF_INSTANCE
Definition: ifsim.h:112
char * ci_curTask
Definition: ftedefs.h:43
int iValue
Definition: ifsim.h:232
char * ci_defTask
Definition: ftedefs.h:41
static IFparm * parmlookup()
double rValue
Definition: ifsim.h:233
#define alloc(type)
Definition: cdmacs.h:21
void va_free()
void if_option(char *ckt, char *name, int type, char *value)
Definition: spiceif.c:331
char * ci_nodes
Definition: ftedefs.h:38
char * copy()
static IFvalue * doask()
char va_type
Definition: cpstd.h:42
int INPinsert()
void wl_free()
static char * unsupported[]
Definition: spiceif.c:312
FILE * cp_err
Definition: help.c:101
#define OK
Definition: iferrmsg.h:17
#define CT_DEVNAMES
Definition: fteconst.h:87
Definition: fteinp.h:14
static int finddev()
GENERIC * IFuid
Definition: ifsim.h:72
struct circ * ft_circuits
Definition: main.c:185
IFdevice ** devices
Definition: ifsim.h:461
int id
Definition: ifsim.h:56
char * va_name
Definition: cpstd.h:43
int numParms
Definition: ifsim.h:339
#define IF_SET
Definition: ifsim.h:135
void INPtabEnd()
Definition: cddefs.h:237
char db_type
Definition: ftedebug.h:22
#define tfree(x)
Definition: cdmacs.h:22
char * ci_specOpt
Definition: ftedefs.h:45
void txfree()
#define NULL
Definition: spdefs.h:121
Definition: types.c:18
char * li_error
Definition: fteinp.h:17
IFparm * analysisParms
Definition: ifsim.h:340
struct circ * ft_curckt
Definition: main.c:184
void if_cktclear()
Definition: spiceif.c:476
char * if_errstring(int code)
Definition: spiceif.c:550
char * li_line
Definition: fteinp.h:16
#define VT_NUM
Definition: cpstd.h:61
struct dbcomm * db_next
Definition: ftedebug.h:28
static void set_options()
Definition: spiceif.c:255
#define IF_INTEGER
Definition: ifsim.h:107
int INP2dot()
int IsIplot()
Definition: spiceif.c:997
void INPkillMods()
Definition: inpkmods.c:16
struct variable * ci_vars
Definition: ftedefs.h:33
void ft_sperror()
#define VT_STRING
Definition: cpstd.h:63
int InProgress()
Definition: spiceif.c:990
struct line * li_next
Definition: fteinp.h:18
static int get_anal()
void cp_freeblock()
#define VT_BOOL
Definition: cpstd.h:60
Definition: ifsim.h:54
char * name
Definition: ifsim.h:293
int numAnalyses
Definition: ifsim.h:463
void inp_deckfree()
Definition: cpstd.h:21
#define IF_REAL
Definition: ifsim.h:108
int dataType
Definition: ifsim.h:57
bool ft_nodesprint
Definition: main.c:190
#define IF_FLAG
Definition: ifsim.h:106
#define IF_REALVEC
Definition: ifsim.h:125
#define IF_VARTYPES
Definition: ifsim.h:133
Definition: netlist.c:477
bool ft_optsprint
Definition: main.c:189
char * if_inpdeck(struct line *deck, char **tab)
Definition: spiceif.c:44
IFanalysis ** analyses
Definition: ifsim.h:464
struct wordlist * wl_next
Definition: cpstd.h:23
#define VT_REAL
Definition: cpstd.h:62
#define CT_NODENAMES
Definition: fteconst.h:89
char * ci_symtab
Definition: ftedefs.h:28
void cp_ccfreetrie()
char * ci_name
Definition: ftedefs.h:26
Definition: mfb.h:383
char * sValue
Definition: ifsim.h:235
char * wl_word
Definition: cpstd.h:22
wordlist * ci_commands
Definition: ftedefs.h:36
char * description
Definition: ifsim.h:58
#define UID_ANALYSIS
Definition: ifsim.h:80
#define DB_IPLOTALL
Definition: ftedebug.h:17
void if_setparam(char *ckt, char *name, char *param, struct variable *val)
Definition: spiceif.c:662
void cp_addkword()
#define IF_STRING
Definition: ifsim.h:111
char * wl_flatten()
char * keyword
Definition: ifsim.h:55
#define DB_IPLOT
Definition: ftedebug.h:16
void INPpas1()
int copytok()
IFparm * modelParms
Definition: ifsim.h:316
struct variable * va_next
Definition: cpstd.h:51
bool ft_nopage
Definition: options.c:23
Definition: cpstd.h:41
struct variable * if_getstat(char *ckt, char *name, wordlist **keyword)
Definition: spiceif.c:884
void if_cktfree(char *ckt, char *tab)
Definition: spiceif.c:462
char GENERIC
Definition: ifsim.h:27
#define IF_PARSETREE
Definition: ifsim.h:113
char * cp_kwswitch()