Jspice3
check.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1992 Stephen R. Whiteley
5 ****************************************************************************/
6 
7 /*
8  * Routines for operating range and related analysis
9  */
10 
11 #include "spice.h"
12 #include "ftedefs.h"
13 #include "fteinp.h"
14 #include "spfteext.h"
15 #include "ftegraph.h"
16 #include "plotext.h"
17 #include "outdata.h"
18 #include "util.h"
19 #include "iferrmsg.h"
20 
21 
22 static FILE *Op; /* output file pointer */
23 static int graphid; /* graph id if plotting */
24 static bool batchmode; /* if true, no user prompts */
25 static bool no_output; /* supress output recording */
26 static struct sOUTcontrol *OUTcntrl;
27  /* structure to control output */
28 
29 struct control {
30  double delta1;
31  double delta2;
32  int step1;
33  int step2;
34  double val1;
35  double val2;
36  int iterno; /* number iterations for extrema seeking */
37 };
38 
39 struct sLOOPprms {
40  double start[2]; /* starting parameter value */
41  double stop[2]; /* ending parameter value */
42  double step[2]; /* step size */
43  double state[2]; /* internal values saved */
44  int dims[3]; /* dimensions of output vector */
45  int nestLevel; /* number of levels of nesting */
46  int nestSave; /* iteration state during pause */
47  char *rundesc; /* save rundesc */
48  int inprogress; /* not done yet */
49 };
50 
51 #ifdef __STDC__
52 static bool parse_var(struct sLOOPprms *,wordlist**);
53 static void pr_parms(void);
54 static void checkloop(wordlist*);
55 static void set_opvec(int);
56 static int mainloop(struct control*);
57 static int do_it(int,int,double,double);
58 static int findext(int,double*,double,double);
59 static void check_end(void);
60 static bool read_check_control_file(FILE*,char*);
61 static bool check_evaluate(void);
62 static void execblock(char*);
63 static void modify(double,double);
64 static void setvec(double,double);
65 static FILE *df_open(void);
66 static void df_close(FILE*);
67 #else
68 static bool parse_var();
69 static void pr_parms();
70 static void checkloop();
71 static void set_opvec();
72 static int mainloop();
73 static int do_it();
74 static int findext();
75 static void check_end();
76 static bool read_check_control_file();
77 static bool check_evaluate();
78 static void execblock();
79 static void modify();
80 static void setvec();
81 static FILE *df_open();
82 static void df_close();
83 #endif
84 
85 
86 void
88 
89 wordlist *wl;
90 {
91  int i, step1, step2;
92  struct dvec *d;
93  char buf[BSIZE_SP];
94  char *c, *hdr;
95  wordlist *ww, *wn;
96  struct circ *ct;
97  struct plot *pl;
98  extern char *kw_mplot_cur;
99 
100  batchmode = true;
101 
102  if (!ft_curckt || !ft_curckt->ci_ckt) {
103  (void) fprintf(cp_err,"Error: no circuit loaded.\n");
104  return;
105  }
106  if (!ft_curckt->ci_contblk) {
107  (void) fprintf(cp_err,"Error: no bound codeblock.\n");
108  return;
109  }
111  (void) fprintf(cp_err,"Error: codeblock %s not found.\n",
113  return;
114  }
115  for (ct = ft_circuits; ct; ct = ct->ci_next)
116  ct->ci_inprogress = false;
117  ft_intrpt = false;
118 
119  pl = plot_alloc("range");
120  plot_new(pl);
122 
123  /* margin analysis creates two codeblocks:
124  * #_name and ##name. ##name is the header block, which is
125  * executed after the plot is created. #_name is the bound
126  * codeblock.
127  */
128 
129  hdr = copy(ft_curckt->ci_contblk);
130  hdr[1] = '#';
131  if (cp_isblockdef(hdr))
132  execblock(hdr);
133  txfree(hdr);
134 
135  ww = cp_lexer("checkFAIL = 0");
136  com_let(ww);
137  wl_free(ww);
138 
139  if (wl) {
140  wl = wl_copy(wl);
141  for (ww = wl; wl; wl = wn) {
142  wn = wl->wl_next;
143  if (wl->wl_word[0] == '-' && wl->wl_word[1] == 'v') {
144  if (wl->wl_prev)
145  wl->wl_prev->wl_next = wl->wl_next;
146  if (wl->wl_next)
147  wl->wl_next->wl_prev = wl->wl_prev;
148  if (ww == wl)
149  ww = wl->wl_next;
150  txfree(wl->wl_word);
151  txfree((char*)wl);
152  batchmode = false;
153  }
154  }
155  wl = ww;
156  }
157 
158  /* analysis specification */
159  if (!wl || !wl->wl_word || *wl->wl_word == '\0') {
160  wn = GetAnalysisFromDeck();
161  if (wn == NULL) {
162  (void) fprintf(cp_err,
163  "Error: no or more than one analysis specified\n");
164  wl_free(wl);
165  com_destroy(NULL);
166  return;
167  }
168  wl_free(wl);
169  wl = wn;
170  }
171  for (c = wl->wl_word; *c; c++)
172  if (isupper(*c)) *c = tolower(*c);
173 
174  Op = (FILE*)NULL;
175  step1 = step2 = 0;
176  if ((d = vec_get("checkSTP1")) != NULL)
177  step1 = (int) *d->v_realdata;
178  if ((d = vec_get("checkSTP2")) != NULL)
179  step2 = (int) *d->v_realdata;
180  if (step1 || step2) {
181  if ((Op = df_open()) == NULL) {
182  (void) fprintf(cp_err,"Error: Can't open data output file\n");
183  wl_free(wl);
184  com_destroy(NULL);
185  return;
186  }
187  }
188  if ((d = vec_get("checkPNTS")) == NULL) {
189  (void) fprintf(cp_err,"Error: check variable checkPNTS not set\n");
190  com_destroy(NULL);
191  return;
192  }
193 
194  OUTcntrl = (struct sOUTcontrol *)OUTcntrlInit();
195  OUTcntrl->out_evaluate = check_evaluate;
196  OUTcntrl->out_end = check_end;
197  OUTcntrl->out_max = d->v_length;
198  OUTcntrl->out_points = d->v_realdata;
199 
200  /* make sure an "exact" point is recognized */
201  for (i = 0; i < d->v_length; i++)
202  d->v_realdata[i] *= .9999;
203 
204  if (!batchmode)
205  pr_parms();
206 
207  checkloop(wl);
208 
209  df_close(Op);
210  if (OUTcntrl->out_destroy)
211  (*OUTcntrl->out_destroy)();
212  wl_free(wl);
213  mp_done(graphid);
214 
215  *buf = '\0';
216  (void)cp_getvar(kw_mplot_cur,VT_STRING,buf);
217  if (!batchmode && Op && *buf)
218  (void) fprintf(cp_out,
219  "Operating range analysis complete. Data in file %s.\n",buf);
220  Op = NULL;
221 }
222 
223 
224 void
226 
227 wordlist *wl;
228 {
229  static struct sLOOPprms loop;
230  double tt;
231  int i;
232  int error;
233  int count;
234  bool firsttime;
235  char *c, *task;
236 
237 
238  if (ft_curckt->ci_inprogress && loop.inprogress) {
239  i = loop.nestSave;
240  firsttime = false;
241  OUTcntrl->out_rundesc = loop.rundesc;
242  OUTcntrl->out_keepplot = true;
243  loop.inprogress = false;
244  task = ft_curckt->ci_curTask;
245  goto didpause;
246  }
247  else {
248  /* reset static variables */
249  error = parse_var(&loop,&wl);
250  if (error) {
251  fprintf(cp_err,"Syntax error\n");
252  return;
253  }
254  /* analysis specification */
255  if (!wl || !wl->wl_word || *wl->wl_word == '\0') {
256  wl = GetAnalysisFromDeck();
257  if (wl == NULL) {
258  (void) fprintf(cp_err,
259  "Error: no or more than one analysis specified\n");
260  return;
261  }
262  }
263  for (c = wl->wl_word; *c; c++)
264  if (isupper(*c)) *c = tolower(*c);
265 
266  OUTcntrl = (struct sOUTcontrol *)OUTcntrlInit();
267  OUTcntrl->out_keepplot = true;
268  for (i = 0; i <= loop.nestLevel; i++)
269  loop.state[i] = loop.start[i];
270  i = 0;
271  firsttime = true;
272  }
273 
274  for (;;) {
275 
276  tt = loop.state[i] - loop.stop[i];
277 
278  if ((loop.step[i] > 0 && tt > 1e-8) ||
279  (loop.step[i] < 0 && tt < 1e-8) ||
280  loop.step[i] == 0) {
281 
282  i++;
283  if (i > loop.nestLevel)
284  break;
285  loop.dims[0]++;
286  if (loop.dims[2] <= 1) {
287  OUTsetDims(OUTcntrl->out_rundesc,loop.dims,2);
288  }
289  }
290  else {
291  if (!loop.dims[0])
292  loop.dims[1]++;
293 
294  while (i > 0) {
295  i--;
296  loop.state[i] = loop.start[i];
297  }
298 
299  modify(loop.state[0],loop.state[1]);
300  if (ft_curckt->ci_specTask) {
301  task = ft_curckt->ci_specTask;
304  ft_curckt->ci_specTask = task;
305  }
306  else {
308  task = ft_curckt->ci_defTask;
309 
310  }
311  ft_curckt->ci_curTask = task;
312 didpause:
313 
314  if (firsttime) {
315  count = 0;
316  error = if_run(wl->wl_word, wl->wl_next);
317  firsttime = false;
318  }
319  else {
320  count = plot_cur->pl_scale->v_length;
321  error = (*(ft_sim->doAnalyses))
322  (ft_curckt->ci_ckt, 1, task);
323  }
324  if (error) {
325  if (error == E_PAUSE) {
326  loop.nestSave = i;
327  loop.rundesc = OUTcntrl->out_rundesc;
328  OUTcntrl->out_rundesc = NULL;
329  loop.inprogress = true;
330  }
331  gr_end_iplot();
332  if (OUTcntrl->out_destroy)
333  (*OUTcntrl->out_destroy)();
334  return;
335  }
336 
337  /* store block size in dims[] */
338  loop.dims[2] = plot_cur->pl_scale->v_length - count;
339 
340  if (loop.dims[2] > 1) {
341 
342  if (loop.dims[0])
343  OUTsetDims(OUTcntrl->out_rundesc,loop.dims,3);
344  else
345  OUTsetDims(OUTcntrl->out_rundesc,loop.dims+1,2);
346  }
347  }
348  loop.state[i] += loop.step[i];
349  }
350 
351  gr_end_iplot();
352  ft_curckt->ci_inprogress = false;
353  if (OUTcntrl->out_destroy)
354  (*OUTcntrl->out_destroy)();
355 
356  return;
357 }
358 
359 
360 static bool
362 
363 struct sLOOPprms *loop;
364 wordlist **wl;
365 {
366  char *line;
367  int error;
368  double tmp;
369  double INPevaluate();
370 
371  loop->start[0] = 0;
372  loop->stop[0] = 0;
373  loop->step[0] = 0;
374  loop->start[1] = 0;
375  loop->stop[1] = 0;
376  loop->step[1] = 0;
377  loop->nestLevel = 0;
378  loop->dims[0] = 0;
379  loop->dims[1] = 0;
380  loop->dims[2] = 0;
381  loop->nestSave = 0;
382  loop->inprogress = 0;
383 
384  if (wl == NULL || *wl == NULL)
385  return (true);
386  line = (*wl)->wl_word;
387  tmp = INPevaluate(&line,&error,1); /* start1 */
388  if (error == 0)
389  loop->start[0] = tmp;
390  else
391  return (error);
392  loop->nestLevel = 0;
393 
394  *wl = (*wl)->wl_next;
395  if (!*wl) {
396  loop->stop[0] = loop->start[0];
397  loop->step[0] = 0;
398  return (false);
399  }
400 
401  line = (*wl)->wl_word;
402  tmp = INPevaluate(&line,&error,1); /* stop1 */
403  if (error == 0)
404  loop->stop[0] = tmp;
405  else {
406  loop->stop[0] = loop->start[0];
407  loop->step[0] = 0;
408  return (false);
409  }
410 
411  (*wl) = (*wl)->wl_next;
412  if (!*wl) {
413  loop->step[0] = loop->stop[0] - loop->start[0];
414  return (false);
415  }
416 
417  line = (*wl)->wl_word;
418  tmp = INPevaluate(&line,&error,1); /* step1 */
419  if (error == 0)
420  loop->step[0] = tmp;
421  else {
422  loop->step[0] = loop->stop[0] - loop->start[0];
423  return (false);
424  }
425 
426  (*wl) = (*wl)->wl_next;
427  if (!*wl) {
428  return (false);
429  }
430 
431  line = (*wl)->wl_word;
432  tmp = INPevaluate(&line,&error,1); /* start2 */
433  if (error == 0)
434  loop->start[1] = tmp;
435  else {
436  return (false);
437  }
438  loop->nestLevel = 1;
439 
440  (*wl) = (*wl)->wl_next;
441  if (!*wl) {
442  loop->stop[1] = loop->start[1];
443  loop->step[1] = 0;
444  return (false);
445  }
446 
447  line = (*wl)->wl_word;
448  tmp = INPevaluate(&line,&error,1); /* stop2 */
449  if (error == 0)
450  loop->start[1] = tmp;
451  else {
452  loop->stop[1] = loop->start[1];
453  loop->step[1] = 0;
454  return (false);
455  }
456 
457  (*wl) = (*wl)->wl_next;
458  if (!*wl) {
459  loop->step[1] = loop->stop[1] - loop->start[1];
460  return (false);
461  }
462 
463  line = (*wl)->wl_word;
464  tmp = INPevaluate(&line,&error,1); /* step2 */
465  if (error == 0)
466  loop->start[1] = tmp;
467  else {
468  loop->step[1] = loop->stop[1] - loop->start[1];
469  return (false);
470  }
471  (*wl) = (*wl)->wl_next;
472  return (false);
473 }
474 
475 
476 void
477 ft_check(wl,infile)
478 
479 wordlist *wl;
480 FILE *infile;
481 {
482  FILE *fp;
483  struct line *deck;
484  wordlist *ww;
485  char *filename = NULL;
486  char *cblock;
487 
489  ShowPrompt("Exit sced to run operating range analysis.");
490  return;
491  }
492 
493  out_init(); /* this might not have been called before, needed
494  * for inp_dodeck()
495  */
496 
497  if (infile != NULL) {
498  /* file sourced */
499  fp = infile;
500  if (wl && wl->wl_word && *wl->wl_word) {
501  filename = wl->wl_word;
502  wl = wl->wl_next;
503  }
504  }
505 
506  else {
507  if (!wl || !wl->wl_word || *wl->wl_word == '\0') {
508  fp = cp_in;
509  }
510  else {
511  filename = wl->wl_word;
512  wl = wl->wl_next;
513  if ((fp = fopen(filename,"r")) == NULL) {
514  (void) fprintf(cp_err,"Error: can't open source file\n");
515  return;
516  }
517  }
518  }
519 
520  if (filename && *filename) {
521  cblock = tmalloc(strlen(filename) + 3);
522  sprintf(cblock,"#_%s",filename);
523  }
524  else
525  cblock = copy("#_");
526 
527 
528  if (read_check_control_file(fp,cblock)) {
529  (void) fclose(fp);
530  return;
531  }
532  inp_readall(fp,&deck,NULL);
533  if (fp != cp_in)
534  (void) fclose(fp);
535 
536  ww = cp_lexer("set value1=0.0 value2=0.0");
537  com_set(ww);
538  wl_free(ww);
539  inp_spdeck(deck,filename);
540  ft_curckt->ci_contblk = cblock;
541 
542  if (ft_batchmode) {
543  /* run the analysis and free */
545  if_cktclear();
546  }
547 }
548 
549 
550 static void
552 
553 {
554  int step1, step2, iterno;
555  double val1, delta1, val2, delta2;
556  struct dvec *d;
557  extern char *kw_checkiterate;
558 
559  val1 = 0;
560  step1 = 0;
561  delta1 = 0;
562  val2 = 0;
563  step2 = 0;
564  delta2 = 0;
565  iterno = 0;
566 
567  if ((d = vec_get("checkDEL1")) != NULL)
568  delta1 = *d->v_realdata;
569  if ((d = vec_get("checkVAL1")) != NULL)
570  val1 = *d->v_realdata;
571  if ((d = vec_get("checkDEL2")) != NULL)
572  delta2 = *d->v_realdata;
573  if ((d = vec_get("checkVAL2")) != NULL)
574  val2 = *d->v_realdata;
575  if ((d = vec_get("checkSTP1")) != NULL)
576  step1 = (int) *d->v_realdata;
577  if ((d = vec_get("checkSTP2")) != NULL)
578  step2 = (int) *d->v_realdata;
579  (void) cp_getvar(kw_checkiterate,VT_NUM,(char*)&iterno);
580 
581  out_printf(
582 "Substitution for value1:\n\
583  value: %g\n\
584  delta: %g\n\
585  steps: %d\n\n",val1,delta1,step1);
586 
587  out_printf(
588 "Substitution for value2:\n\
589  value: %g\n\
590  delta: %g\n\
591  steps: %d\n\n",val2,delta2,step2);
592 
593  out_printf("checkiterate is set to %d\n\n",iterno);
594 }
595 
596 
597 static void
598 checkloop(cmdwl)
599 
600 wordlist *cmdwl;
601 {
602  struct dvec *d;
603  struct control cntrl;
604  double value1, value2;
605  char *apology = "Sorry, margin analysis can't be resumed in this version.\n";
606  extern char *kw_checkiterate;
607 
608  OUTcntrl->out_check = true;
609  OUTcntrl->out_keepplot = true;
610  OUTcntrl->out_usecurplot = true;
611 
612  cntrl.val1 = 0;
613  cntrl.step1 = 0;
614  cntrl.delta1 = 0;
615  cntrl.val2 = 0;
616  cntrl.step2 = 0;
617  cntrl.delta2 = 0;
618  cntrl.iterno = 0;
619 
620  if ((d = vec_get("checkDEL1")) != NULL)
621  cntrl.delta1 = *d->v_realdata;
622  if ((d = vec_get("checkVAL1")) != NULL)
623  cntrl.val1 = *d->v_realdata;
624  if ((d = vec_get("checkDEL2")) != NULL)
625  cntrl.delta2 = *d->v_realdata;
626  if ((d = vec_get("checkVAL2")) != NULL)
627  cntrl.val2 = *d->v_realdata;
628  if ((d = vec_get("checkSTP1")) != NULL)
629  cntrl.step1 = (int) *d->v_realdata;
630  if ((d = vec_get("checkSTP2")) != NULL)
631  cntrl.step2 = (int) *d->v_realdata;
632 
633  value1 = cntrl.val1 - cntrl.step1 * cntrl.delta1;
634  value2 = cntrl.val2 - cntrl.step2 * cntrl.delta2;
635  modify(value1,value2);
637  graphid = (mp_init(2*cntrl.step1+1,2*cntrl.step2+1,
638  value1, cntrl.val1+cntrl.step1*cntrl.delta1,
639  value2, cntrl.val2+cntrl.step2*cntrl.delta2));
640 
641  if (!graphid && !batchmode)
642  (void) fprintf(cp_out,"%d %d %g %g\n",
643  -cntrl.step1,-cntrl.step2,value1,value2);
644 
645  if (Op)
646  (void) fprintf(Op,"%d %d %g %g\n",
647  -cntrl.step1,-cntrl.step2,value1,value2);
648 
649  mp_where(graphid,-cntrl.step1,-cntrl.step2);
650 
651 
652  /* run the analysis */
653  (void)cp_getvar(kw_checkiterate,VT_NUM,(char*)&cntrl.iterno);
654  if (cntrl.iterno < 0 || cntrl.iterno > 10) {
655  cntrl.iterno = 0;
656  (void)fprintf(cp_err,
657  "Warning: bad value for checkiterate, ignored.\n");
658  }
659  set_opvec(cntrl.step2);
660 
661  (void) if_run(cmdwl->wl_word, cmdwl->wl_next);
662 
663  if (OUTcntrl->out_check == 0) { /* user interrupt */
664  (void) fprintf(cp_err,apology);
665  return;
666  }
667 
668  if (mainloop(&cntrl))
669  (void) fprintf(cp_err,apology);
670 }
671 
672 
673 static void
675 
676 /* create vectors for operating range exterma (value 2) */
677 int n;
678 {
679  char buf[BSIZE_SP];
680  bool temp;
681 
682  temp = cp_interactive;
683  cp_interactive = false;
684  cp_pushcontrol();
685  sprintf(buf,"unlet oplo; let oplo[%d]=0",2*n);
686  cp_evloop(buf);
687  sprintf(buf,"unlet ophi; let ophi[%d]=0",2*n);
688  cp_evloop(buf);
689  cp_popcontrol();
690  cp_interactive = temp;
691 }
692 
693 
694 static int
695 mainloop(cntrl)
696 
697 struct control *cntrl;
698 {
699  int i, j, last;
700  int num1, num2;
701  double value1, value2, delta;
702  char *flags, *rowflags;
703  struct dvec *d;
704 
705  if (cntrl->step1 == 0 && cntrl->step2 == 0) {
706  /* new feature - find the operating range of value1 */
707 
708  if (cntrl->iterno == 0)
709  return (false);
710  if (OUTcntrl->out_fail) {
711  /* center point bad */
712  (void) fprintf(cp_err,
713  "Error: central point bad, range not found.\n");
714  return (false);
715  }
716  value2 = cntrl->val2;
717  value1 = cntrl->val1;
718  delta = .5*value1;
719  for (i = 0; i < 10; i++) {
720  value1 += delta;
721  no_output = true;
722  do_it(0,0,value1,value2);
723  no_output = false;
724  if (OUTcntrl->out_fail) {
725  value1 -= delta;
726  if (findext(cntrl->iterno,&value1,value2,-delta))
727  goto quit;
728  if ((d = vec_get("ophi")) != NULL)
729  d->v_realdata[0] = value1;
730  break;
731  }
732  }
733  if (i == 10) {
734  (void) fprintf(cp_err,"Warning: could not find upper limit.\n");
735  if ((d = vec_get("ophi")) != NULL)
736  d->v_realdata[0] = value1;
737  }
738  value1 = cntrl->val1;
739  delta = .49*value1;
740  for (i = 0; i < 2; i++) {
741  value1 -= delta;
742  no_output = true;
743  do_it(0,0,value1,value2);
744  no_output = false;
745  if (OUTcntrl->out_fail) {
746  value1 += delta;
747  if (findext(cntrl->iterno,&value1,value2,delta))
748  goto quit;
749  if ((d = vec_get("oplo")) != NULL)
750  d->v_realdata[0] = value1;
751  break;
752  }
753  }
754  if (i == 2) {
755  (void) fprintf(cp_err,"Warning: could not find lower limit.\n");
756  if ((d = vec_get("oplo")) != NULL)
757  d->v_realdata[0] = value1;
758  }
759  return (false);
760  }
761 
762  num1 = 2*cntrl->step1 + 1;
763  num2 = 2*cntrl->step2 + 1;
764  flags = tmalloc(num1*num2);
765  /* fill in the first point */
766  *flags = 1 + OUTcntrl->out_fail;
767 
768  /* Find the range along the rows. */
769  for (j = -cntrl->step2; j <= cntrl->step2; j++) {
770  value2 = cntrl->val2 + j*cntrl->delta2;
771 
772  rowflags = flags + (j + cntrl->step2)*num1;
773  for (last = i = -cntrl->step1; i <= cntrl->step1; i++,rowflags++) {
774  if (*rowflags == 2) continue;
775  if (*rowflags == 1) break;
776  value1 = cntrl->val1 + i*cntrl->delta1;
777  *rowflags = do_it(i,j,value1,value2);
778  if (OUTcntrl->out_check == 0) /* user interrupt */
779  goto quit;
780  last = i;
781  if (!OUTcntrl->out_fail) break;
782  }
783  if (!OUTcntrl->out_fail && i != -cntrl->step1) {
784  if (findext(cntrl->iterno,&value1,value2,cntrl->delta1))
785  goto quit;
786  if ((d = vec_get("oplo")) != NULL)
787  d->v_realdata[j+cntrl->step2] = value1;
788  }
789 
790  rowflags = flags + (j + cntrl->step2 + 1)*num1 - 1;
791  for (i = cntrl->step1; i > last; i--,rowflags--) {
792  if (*rowflags == 2) continue;
793  if (*rowflags == 1) break;
794  value1 = cntrl->val1 + i*cntrl->delta1;
795  *rowflags = do_it(i,j,value1,value2);
796  if (OUTcntrl->out_check == 0) /* user interrupt */
797  goto quit;
798  if (!OUTcntrl->out_fail) break;
799  }
800  if (!OUTcntrl->out_fail && i != cntrl->step1) {
801  if (findext(cntrl->iterno,&value1,value2,-cntrl->delta1))
802  goto quit;
803  if ((d = vec_get("ophi")) != NULL)
804  d->v_realdata[j+cntrl->step2] = value1;
805  }
806  }
807 
808  /* Now check the columns, fill in any missing points.
809  * Do this for column height > 3 only.
810  */
811  if (cntrl->step2 > 1) {
812  for (i = -cntrl->step1; i <= cntrl->step1; i++) {
813  value1 = cntrl->val1 + i*cntrl->delta1;
814 
815  rowflags = flags + i + cntrl->step1;
816  for (last = j = -cntrl->step2; j <= cntrl->step2;
817  j++,rowflags += num1) {
818  if (*rowflags == 2) continue;
819  if (*rowflags == 1) break;
820  value2 = cntrl->val2 + j*cntrl->delta2;
821  *rowflags = do_it(i,j,value1,value2);
822  if (OUTcntrl->out_check == 0) /* user interrupt */
823  goto quit;
824  last = j;
825  if (!OUTcntrl->out_fail) break;
826  }
827 
828  rowflags = flags + i + cntrl->step1 + 2*cntrl->step2*num1;
829  for (j = cntrl->step2; j > last; j--,rowflags -= num1) {
830  if (*rowflags == 2) continue;
831  if (*rowflags == 1) break;
832  value2 = cntrl->val2 + j*cntrl->delta2;
833  *rowflags = do_it(i,j,value1,value2);
834  if (OUTcntrl->out_check == 0) /* user interrupt */
835  goto quit;
836  if (!OUTcntrl->out_fail) break;
837  }
838  }
839  }
840  txfree(flags);
841  return (false);
842 quit:
843  txfree(flags);
844  return (true);
845 }
846 
847 
848 static int
849 do_it(i,j,value1,value2)
850 
851 int i,j;
852 double value1,value2;
853 {
854  char *task;
855 
856  modify(value1,value2);
857  if (!no_output) {
858  if (mp_where(graphid,i,j) && !batchmode)
859  (void) fprintf(cp_out,"%d %d %g %g\n",i,j,value1,value2);
860  if (Op)
861  (void) fprintf(Op,"%d %d %g %g\n",i,j,value1,value2);
862  }
863  if (ft_curckt->ci_specTask) {
864  task = ft_curckt->ci_specTask;
867  ft_curckt->ci_specTask = task;
868  }
869  else {
871  task = ft_curckt->ci_defTask;
872  }
873 
874  ft_curckt->ci_curTask = task;
875  (void)(*(ft_sim->doAnalyses))(ft_curckt->ci_ckt, 1,task);
876  return (OUTcntrl->out_fail + 1);
877 }
878 
879 
880 static int
881 findext(iterno,value1,value2,delta)
882 
883 /* Iterate to the edge of the operating region along row */
884 int iterno;
885 double *value1,value2,delta;
886 {
887  char *task;
888 
889  delta *= .5;
890  *value1 -= delta;
891 
892  no_output = true;
893  while (iterno--) {
894  modify(*value1,value2);
895 
896  if (ft_curckt->ci_specTask) {
897  task = ft_curckt->ci_specTask;
900  ft_curckt->ci_specTask = task;
901  }
902  else {
904  task = ft_curckt->ci_defTask;
905  }
906 
907  ft_curckt->ci_curTask = task;
908  (void) (*(ft_sim->doAnalyses))(ft_curckt->ci_ckt, 1, task);
909 
910  if (OUTcntrl->out_check == 0) { /* user interrupt */
911  no_output = false;
912  return (true);
913  }
914 
915  delta *= .5;
916  if (!OUTcntrl->out_fail)
917  *value1 -= delta;
918  else
919  *value1 += delta;
920  }
921  no_output = false;
922  return (false);
923 }
924 
925 
926 static void
928 {
929  if (no_output)
930  return;
931  if (mp_mark(graphid,!OUTcntrl->out_fail) && !batchmode)
932  (void) fprintf(cp_out,OUTcntrl->out_fail ? " fail\n\n" : " pass\n\n");
933  if (Op)
934  (void) fprintf(Op,OUTcntrl->out_fail ? "\tfail\n" : "\tpass\n");
935 }
936 
937 
938 static int
940 
941 FILE *fp;
942 char *blname;
943 {
944  char *buf;
945  wordlist *chklst = NULL, *ckl;
946  wordlist *hdrlst = NULL, *hdl;
947  bool begin = false;
948 
949  while ((buf = readline(fp)) != NULL) {
950  if (*buf == '#') {
951  txfree(buf);
952  continue;
953  }
954  if (prefix(".control",buf)) {
955  begin = true;
956  txfree(buf);
957  continue;
958  }
959  if (prefix(".endc",buf)) {
960  if (!begin)
961  (void) fprintf(cp_err,"Warning: no .control line found\n");
962  txfree(buf);
963  break;
964  }
965  *strchr(buf,'\n') = '\0';
966  if (!*buf) {
967  txfree(buf);
968  continue;
969  }
970  if (!begin) {
971  if (!hdrlst)
972  hdrlst = hdl = alloc(wordlist);
973  else {
974  hdl->wl_next = alloc(wordlist);
975  hdl = hdl->wl_next;
976  }
977  hdl->wl_word = buf;
978  continue;
979  }
980  if (!chklst)
981  chklst = ckl = alloc(wordlist);
982  else {
983  ckl->wl_next = alloc(wordlist);
984  ckl = ckl->wl_next;
985  }
986  ckl->wl_word = buf;
987  }
988  cp_addblock(blname,chklst);
989  blname[1] = '#';
990  cp_addblock(blname,hdrlst);
991  blname[1] = '_';
992  wl_free(chklst);
993  wl_free(hdrlst);
994  return (false);
995 }
996 
997 
998 static bool
1000 {
1001  struct dvec *d;
1002  char *blname;
1003 
1004  blname = ft_curckt->ci_contblk;
1005  if (!blname)
1006  return (true);
1007 
1008  execblock(blname);
1009  d = vec_get("checkFAIL");
1010 
1011  /* checkFAIL is true if failed */
1012  return ((int) *d->v_realdata ? true : false);
1013 }
1014 
1015 
1016 static void
1017 execblock(blname)
1018 
1019 char *blname;
1020 {
1021  bool temp;
1022  FILE *lastin, *lastout, *lasterr;
1023 
1024  temp = cp_interactive;
1025  cp_interactive = false;
1026  lastin = cp_curin;
1027  lastout = cp_curout;
1028  lasterr = cp_curerr;
1029  cp_curin = cp_in;
1030  cp_curout = cp_out;
1031  cp_curerr = cp_err;
1032 
1033  cp_execcontrol(blname);
1034 
1035  cp_curin = lastin;
1036  cp_curout = lastout;
1037  cp_curerr = lasterr;
1038  cp_interactive = temp;
1039 }
1040 
1041 
1042 static void
1043 modify(value1,value2)
1044 
1045 double value1,value2;
1046 {
1047  char buf[BSIZE_SP];
1048  wordlist *wl;
1049 
1050  sprintf(buf,"set value1=%g value2=%g",value1,value2);
1051  wl = cp_lexer(buf);
1052  com_set(wl);
1053  wl_free(wl);
1054  setvec(value1,value2);
1055 }
1056 
1057 
1058 static void
1059 setvec(v1,v2)
1060 
1061 double v1,v2;
1062 {
1063  struct dvec *d, *n1, *n2;
1064  int i, len;
1065 
1066  d = vec_get("value");
1067  if (d == NULL)
1068  return;
1069  if (!isreal(d))
1070  return;
1071  n1 = vec_get("checkN1");
1072  n2 = vec_get("checkN2");
1073  if (n1 == NULL && n2 == NULL)
1074  return;
1075  len = d->v_length;
1076  if (n1) {
1077  i = (int)n1->v_realdata[0];
1078  if (i < 0 || i >= len)
1079  return;
1080  d->v_realdata[i] = v1;
1081  }
1082  if (n2) {
1083  i = (int)n2->v_realdata[0];
1084  if (i < 0 || i >= len)
1085  return;
1086  d->v_realdata[i] = v2;
1087  }
1088 }
1089 
1090 
1091 
1092 static FILE *
1094 
1095 /* open the data output file for writing. name: xxxxx.dnn , where
1096  * xxxxx is the base of the circuit file name, or "check" if no
1097  * current file name. nn is 00 - 99.
1098  * If successful, set the variable "mplot_cur" to the file name.
1099  */
1100 {
1101  FILE *fp, *fopen();
1102  char buf[128], buf1[128], *s;
1103  wordlist *wl;
1104  int i;
1105 
1106  if (ft_servermode) {
1107  wl = cp_lexer("set mplot_cur=mplot");
1108  com_set(wl);
1109  wl_free(wl);
1110  return (cp_out);
1111  }
1112 
1113  if (ft_curckt->ci_filename)
1114  sprintf(buf,ft_curckt->ci_filename);
1115  else
1116  strcpy(buf,"check");
1117  if ((s = strrchr(buf,DIR_TERM)) != NULL)
1118  s++;
1119  else
1120  s = buf;
1121  strcpy(buf1,s);
1122 
1123  if ((s = strrchr(buf1,'.')) != NULL)
1124  *s = '\0';
1125  strcat(buf1,".d00");
1126  s = strchr(buf1,'.') + 2;
1127  for (i = 1; i < 100; i++) {
1128  if (access(buf1,0)) break;
1129  *s = i/10 + '0';
1130  *(s+1) = i%10 + '0';
1131  }
1132  if (i == 100)
1133  return (NULL);
1134  fp = fopen(buf1,"w");
1135  if (!fp) {
1136  perror(buf1);
1137  return (NULL);
1138  }
1139 
1140  sprintf(buf,"set mplot_cur=%s",buf1);
1141  wl = cp_lexer(buf);
1142  com_set(wl);
1143  wl_free(wl);
1144 
1145  return (fp);
1146 }
1147 
1148 
1149 static void
1151 
1152 FILE *fp;
1153 {
1154  if (fp && fp != cp_out)
1155  (void) fclose(fp);
1156 }
#define E_PAUSE
Definition: iferrmsg.h:15
bool ft_intrpt
Definition: main.c:47
static char buf[MAXPROMPT]
Definition: arg.c:18
int step2
Definition: check.c:33
static void df_close()
bool cp_isblockdef()
#define BSIZE_SP
Definition: misc.h:19
void com_loop(wordlist *wl)
Definition: check.c:225
struct circ * ci_next
Definition: ftedefs.h:37
#define loop
Definition: cdmacs.h:11
int out_max
Definition: outdata.h:42
void inp_readall()
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
struct plot * plot_alloc()
char * kw_checkiterate
Definition: options.c:338
int out_keepplot
Definition: outdata.h:39
IFsimulator * ft_sim
Definition: main.c:111
void plot_new()
char * rundesc
Definition: check.c:47
int inprogress
Definition: check.c:48
char * pl_typename
Definition: ftedata.h:65
char * ci_specTask
Definition: ftedefs.h:42
int out_usecurplot
Definition: outdata.h:38
#define prefix(x, y)
Definition: readhelp.c:39
void out_printf()
int if_run()
char * strcpy()
static void checkloop()
Definition: ftedefs.h:25
Definition: cddefs.h:119
struct plot * plot_cur
Definition: vectors.c:43
if(TDesc==NULL)
Definition: cd.c:1326
Definition: xforms.c:16
bool inp_spdeck(struct line *deck, char *filename)
Definition: inp.c:463
bool ci_inprogress
Definition: ftedefs.h:34
double INPevaluate()
static double e
Definition: vectors.c:17
FILE * cp_curerr
Definition: cshpar.c:77
char * ci_ckt
Definition: ftedefs.h:27
Definition: ftedata.h:61
char * ci_filename
Definition: ftedefs.h:40
int mp_done()
static void set_opvec()
void cp_addblock()
Definition: library.c:18
int mp_where()
char * ci_contblk
Definition: ftedefs.h:29
void com_set()
double delta2
Definition: check.c:31
char * ci_curTask
Definition: ftedefs.h:43
char * out_rundesc
Definition: outdata.h:44
char * ci_defTask
Definition: ftedefs.h:41
int nestLevel
Definition: check.c:45
int dims[3]
Definition: check.c:44
#define alloc(type)
Definition: cdmacs.h:21
double step[2]
Definition: check.c:42
int step1
Definition: check.c:32
char * copy()
static bool check_evaluate()
Definition: check.c:999
int iterno
Definition: check.c:36
FILE * cp_curin
Definition: cshpar.c:75
void wl_free()
#define GR_SCED
Definition: ftegraph.h:23
void(* out_destroy)()
Definition: outdata.h:52
void ft_check(wordlist *wl, FILE *infile)
Definition: check.c:477
FILE * cp_err
Definition: help.c:101
char * tmalloc()
Definition: fteinp.h:14
static char start[32]
Definition: subckt.c:76
double * out_points
Definition: outdata.h:40
struct circ * ft_circuits
Definition: main.c:185
void if_cktclear()
Definition: spiceif.c:476
struct wordlist * wl_prev
Definition: cpstd.h:24
static bool no_output
Definition: check.c:25
void cp_execcontrol()
char * OUTcntrlInit()
Definition: outitf.c:111
Definition: cddefs.h:237
bool cp_interactive
Definition: help.c:100
struct dvec * vec_get()
void txfree()
struct dvec * pl_scale
Definition: ftedata.h:68
#define NULL
Definition: spdefs.h:121
int graphtype
Definition: ftegraph.h:31
struct circ * ft_curckt
Definition: main.c:184
void com_rset()
static void setvec()
FILE * cp_out
Definition: help.c:101
int mp_init()
#define VT_NUM
Definition: cpstd.h:61
static int findext()
bool ft_servermode
Definition: main.c:46
wordlist * GetAnalysisFromDeck()
Definition: main.c:255
static int do_it()
double state[2]
Definition: check.c:43
int access(char *pth, int m)
Definition: libfuncs.c:75
void com_check(wordlist *wl)
Definition: check.c:87
int nestSave
Definition: check.c:46
static double c
Definition: vectors.c:16
#define VT_STRING
Definition: cpstd.h:63
#define isreal(v)
Definition: ftedata.h:54
void perror()
Definition: ftedata.h:24
wordlist * cp_lexer()
double val1
Definition: check.c:34
int mp_mark()
Definition: front.c:25
Definition: cpstd.h:21
double delta1
Definition: check.c:30
char * kw_mplot_cur
Definition: options.c:376
static void pr_parms()
Definition: check.c:551
Definition: netlist.c:477
bool ft_batchmode
Definition: main.c:98
static bool read_check_control_file()
int out_fail
Definition: outdata.h:43
static void check_end()
Definition: check.c:927
double stop[2]
Definition: check.c:41
struct wordlist * wl_next
Definition: cpstd.h:23
double start[2]
Definition: check.c:40
static bool parse_var()
static struct sOUTcontrol * OUTcntrl
Definition: check.c:26
static int mainloop()
GRAPH * currentgraph
Definition: graphdb.c:21
int count
Definition: output.c:152
char * wl_word
Definition: cpstd.h:22
void cp_pushcontrol()
Definition: front.c:1066
double val2
Definition: check.c:35
void gr_end_iplot()
Definition: iplot.c:397
void cp_popcontrol()
Definition: front.c:1051
int v_length
Definition: ftedata.h:34
int cp_evloop()
FILE * cp_curout
Definition: cshpar.c:76
static FILE * df_open()
Definition: check.c:1093
FILE * cp_in
Definition: help.c:101
double * v_realdata
Definition: ftedata.h:28
static void execblock()
void plot_setcur()
int out_check
Definition: outdata.h:37
int OUTsetDims()
void(* out_end)()
Definition: outdata.h:51
static int graphid
Definition: check.c:23
void com_let()
void ShowPrompt(char *str)
Definition: scedstub.c:71
void com_destroy()
int(* out_evaluate)()
Definition: outdata.h:50
static void modify()
static FILE * Op
Definition: check.c:22
char * readline()
static bool batchmode
Definition: check.c:24
void out_init()
Definition: output.c:128
wordlist * wl_copy()