1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
4 Modified: 2000 AlansFixes
5 **********/
6 
7 /*
8  * Circuit simulation commands.
9  */
10 
11 #include "ngspice/ngspice.h"
12 #include "ngspice/cpdefs.h"
13 #include "ngspice/ftedefs.h"
14 #include "ngspice/ftedev.h"
15 #include "ngspice/ftedebug.h"
16 #include "ngspice/dvec.h"
17 
18 #include "numparam/numpaif.h"
19 
20 #include "circuits.h"
21 #include "completion.h"
22 #include "runcoms.h"
23 #include "variable.h"
24 #include "spiceif.h"
25 #include "runcoms2.h"
26 
27 #ifdef XSPICE
28 /* gtri - add - 12/12/90 - wbk - include ipc stuff */
29 #include "ngspice/ipctiein.h"
30 /* gtri - end - 12/12/90 */
31 #endif
32 
33 
34 static int dosim(char *what, wordlist *wl);
35 extern struct INPmodel *modtab;
36 extern struct dbcomm *dbs;
37 
38 /* Routines for the commands op, tran, ac, dc, listing, device, state,
39  * resume, stop, trace, run, end.  Op, tran, ac, and dc cause the action
40  * to be performed immediately, and run causes whatever actions were
41  * present in the deck to be carried out. End has the effect of stopping
42  * any simulations in progress, as opposed to ending the input deck as
43  * the .end line does.
44  */
45 
46 FILE *rawfileFp;
47 bool rawfileBinary;
48 /*To tell resume the rawfile name saj*/
49 char *last_used_rawfile = NULL;
50 /*end saj */
51 
52 
53 /*
54  * command "setcirc"
55  *   print a list of circuits loaded
56  * command "setcirc <n>"
57  *   switch to circuit number <n>
58  */
59 
60 void
com_scirc(wordlist * wl)61 com_scirc(wordlist *wl)
62 {
63     struct circ *p;
64     int i, j = 0;
65 
66     if (ft_circuits == NULL) {
67         fprintf(cp_err, "Error: there aren't any circuits loaded.\n");
68         return;
69     }
70 
71     if (wl == NULL) {
72         fprintf(cp_out,
73                 "List of circuits loaded:\n\n");
74         for (p = ft_circuits; p; p = p->ci_next) {
75             if (ft_curckt == p)
76                 fprintf(cp_out, "Current");
77             fprintf(cp_out, "\t%d\t%s\n", ++j, p->ci_name);
78         }
79         return;
80     } else {
81         for (p = ft_circuits; p; p = p->ci_next)
82             j++;
83 
84         p = NULL;
85         if ((sscanf(wl->wl_word, " %d ", &i) != 1) || (i < 0) || (i > j))
86             ;
87         else
88             for (p = ft_circuits; --i > 0; p = p->ci_next)
89                 ;
90         /* for (p = ft_circuits; p; p = p->ci_next)
91          *   if (ciprefix(wl->wl_word, p->ci_name))
92          *    break;
93          */
94         if (p == NULL) {
95             fprintf(cp_err, "Warning: no such circuit \"%s\"\n", wl->wl_word);
96             return;
97         }
98         fprintf(cp_out, "\t%s\n", p->ci_name);
99     }
100     if (ft_curckt) {
101         /* Actually this can't be FALSE */
102         ft_curckt->ci_devices =
103             cp_kwswitch(CT_DEVNAMES, p->ci_devices);
104         ft_curckt->ci_nodes = cp_kwswitch(CT_NODENAMES, p->ci_nodes);
105     }
106     ft_curckt = p;
107     /* get the model table for the current circuit, store it in the global variable modtab */
108     modtab = ft_curckt->ci_modtab;
109     /* get the database for save, iplot, stop */
110     dbs = ft_curckt->ci_dbs;
111     /* set the numparam dicos structure for use with measure */
112     nupa_set_dicoslist(ft_curckt->ci_dicos);
113 }
114 
115 
116 void
com_pz(wordlist * wl)117 com_pz(wordlist *wl)
118 {
119     dosim("pz", wl);
120 }
121 
122 
123 void
com_op(wordlist * wl)124 com_op(wordlist *wl)
125 {
126     dosim("op", wl);
127 }
128 
129 
130 void
com_dc(wordlist * wl)131 com_dc(wordlist *wl)
132 {
133     dosim("dc", wl);
134 }
135 
136 
137 void
com_ac(wordlist * wl)138 com_ac(wordlist *wl)
139 {
140     dosim("ac", wl);
141 }
142 
143 
144 void
com_tf(wordlist * wl)145 com_tf(wordlist *wl)
146 {
147     dosim("tf", wl);
148 }
149 
150 
151 void
com_tran(wordlist * wl)152 com_tran(wordlist *wl)
153 {
154     dosim("tran", wl);
155 }
156 
157 
158 void
com_sens(wordlist * wl)159 com_sens(wordlist *wl)
160 {
161     dosim("sens", wl);
162 }
163 
164 
165 void
com_disto(wordlist * wl)166 com_disto(wordlist *wl)
167 {
168     dosim("disto", wl);
169 }
170 
171 
172 void
com_noise(wordlist * wl)173 com_noise(wordlist *wl)
174 {
175     dosim("noise", wl);
176 }
177 
178 
179 #ifdef WITH_PSS
180 /* SP: Steady State Analysis */
181 void
com_pss(wordlist * wl)182 com_pss(wordlist *wl)
183 {
184     dosim("pss", wl);
185 }
186 /* SP */
187 #endif
188 
189 
dosim(char * what,wordlist * wl)190 static int dosim(
191         char *what, /* in: command
192                      * (pz,op,dc,ac,tf,tran,sens,disto,noise,run) */
193         wordlist *wl /* in: command option */
194         /* global variables in: ft_curckt, ft_circuits,
195          * out: ft_setflag, ft_intrpt, rawfileFp, rawfileBinary,
196          *      last_used_rawfile
197          */
198     )
199 {
200     wordlist *ww = NULL;
201     bool dofile = FALSE;
202     char buf[BSIZE_SP];
203     struct circ *ct;
204     int err = 0;
205     /* set file type to binary or to what is given by environmental
206        variable SPICE_ASCIIRAWFILE in ivars.c */
207     bool ascii = AsciiRawFile;
208     if (eq(what, "run") && wl) {
209         dofile = TRUE;
210     }
211     /* add "what" to beginning of wordlist wl, except "what" equals "run"
212        and a rawfile name is given (in wl) */
213     if (!dofile) {
214         ww = wl_cons(copy(what), wl);
215     }
216     /* reset output file type according to variable given in spinit */
217     if (cp_getvar("filetype", CP_STRING, buf, sizeof(buf))) {
218         if (eq(buf, "binary")) {
219             ascii = FALSE;
220         }
221         else if (eq(buf, "ascii")) {
222             ascii = TRUE;
223         }
224         else {
225             fprintf(cp_err,
226                     "Warning: strange file type \"%s\" (using \"ascii\")\n", buf);
227             ascii = TRUE;
228         }
229     }
230 
231     if (!ft_curckt) {
232         fprintf(cp_err, "Error: there aren't any circuits loaded.\n");
233         return 1;
234     }
235     else if (ft_curckt->ci_ckt == NULL) { /* Set noparse? */
236         fprintf(cp_err, "Error: circuit not parsed.\n");
237         return 1;
238     }
239     for (ct = ft_circuits; ct; ct = ct->ci_next) {
240         if (ct->ci_inprogress && (ct != ft_curckt)) {
241             fprintf(cp_err,
242                     "Warning: losing old state for circuit '%s'\n",
243                     ct->ci_name);
244             ct->ci_inprogress = FALSE;
245         }
246     }
247     /* "resume" will never occur in ngspice */
248     if (ft_curckt->ci_inprogress && eq(what, "resume")) {
249         ft_setflag = TRUE;  /* don't allow abort upon interrupt during run  */
250         ft_intrpt = FALSE;
251         fprintf(cp_err, "Warning: resuming run in progress.\n");
252         com_resume(NULL);
253         ft_setflag = FALSE;  /* Now allow aborts again  */
254         return 0;
255     }
256 
257     /* From now on until the next prompt, an interrupt will just
258      * set a flag and let spice finish up, then control will be
259      * passed back to the user.
260      */
261     ft_setflag = TRUE;  /* Don't allow abort upon interrupt during run.  */
262     ft_intrpt = FALSE;
263     /* command "run" is given with rawfile name in wl */
264     if (dofile) {
265         if (!*wl->wl_word) {
266             rawfileFp = stdout;
267         }
268 
269         /* ask if binary or ASCII, open file with wb or w */
270         else if (ascii) {
271             if ((rawfileFp = fopen(wl->wl_word, "w")) == NULL) {
272                 perror(wl->wl_word);
273                 ft_setflag = FALSE;
274                 return 1;
275             }
276             fprintf(cp_out, "ASCII raw file \"%s\"\n", wl->wl_word);
277         }
278         else { /* binary */
279             if ((rawfileFp = fopen(wl->wl_word, "wb")) == NULL) {
280                 perror(wl->wl_word);
281                 ft_setflag = FALSE;
282                 return 1;
283             }
284             fprintf(cp_out, "binary raw file \"%s\"\n", wl->wl_word);
285         }
286         rawfileBinary = !ascii;
287     }
288     else {
289         rawfileFp = NULL;
290     }
291 
292     /*save rawfile name */
293     if (last_used_rawfile) {
294         tfree(last_used_rawfile);
295     }
296     if (rawfileFp) {
297         last_used_rawfile = copy(wl->wl_word);
298     }
299     else {
300         last_used_rawfile = NULL;
301     }
302 
303     ft_curckt->ci_inprogress = TRUE;
304     cp_vset("sim_status", CP_NUM, &err);
305     /* "sens2" not used in ngspice */
306     if (eq(what, "sens2")) {
307         if (if_sens_run(ft_curckt->ci_ckt, ww, ft_curckt->ci_symtab) == 1) {
308             /* The circuit was interrupted somewhere. */
309             fprintf(cp_err, "%s simulation interrupted\n", what);
310 #ifdef XSPICE
311             /* gtri - add - 12/12/90 - wbk - record error and return errchk */
312             g_ipc.run_error = IPC_TRUE;
313             if (g_ipc.enabled) {
314                 ipc_send_errchk();
315             }
316             /* gtri - end - 12/12/90 */
317 #endif
318         }
319         else {
320             ft_curckt->ci_inprogress = FALSE;
321         }
322         /* Do a run of the circuit */
323     }
324     else {
325         err = if_run(ft_curckt->ci_ckt, what, ww, ft_curckt->ci_symtab);
326         if (err == 1) {
327             /* The circuit was interrupted somewhere. */
328             fprintf(cp_err, "%s simulation interrupted\n", what);
329 #ifdef XSPICE
330             /* record error and return errchk */
331             g_ipc.run_error = IPC_TRUE;
332             if (g_ipc.enabled) {
333                 ipc_send_errchk();
334             }
335             /* gtri - end - 12/12/90 */
336 #endif
337             err = 0;
338         }
339         else if (err == 2) {
340             fprintf(cp_err, "%s simulation(s) aborted\n", what);
341             ft_curckt->ci_inprogress = FALSE;
342             err = 1;
343             cp_vset("sim_status", CP_NUM, &err);
344         }
345         else {
346             ft_curckt->ci_inprogress = FALSE;
347         }
348     }
349     /* close the rawfile */
350     if (rawfileFp) {
351         if (ftell(rawfileFp) == 0) {
352             (void) fclose(rawfileFp);
353             if (wl) {
354                 (void) unlink(wl->wl_word);
355             }
356         }
357         else {
358             (void) fclose(rawfileFp);
359         }
360     }
361     ft_curckt->ci_runonce = TRUE;
362     ft_setflag = FALSE;
363 
364     /* va: garbage collection: unlink first word (inserted here) and tfree it */
365     if (!dofile) {
366         txfree(ww->wl_word);
367         if (wl) {
368             wl->wl_prev = NULL;
369         }
370         txfree(ww);
371     }
372 
373     /* execute the .measure statements */
374     if (!err && ft_curckt->ci_last_an && ft_curckt->ci_meas) {
375         do_measure(ft_curckt->ci_last_an, FALSE);
376     }
377 
378     return err;
379 } /* end of function dosim */
380 
381 
382 
383 /* Usage is run [filename] */
com_run(wordlist * wl)384 void com_run(wordlist *wl)
385 {
386     /* ft_getsaves(); */
387     dosim("run", wl);
388 }
389 
390 
391 int
ft_dorun(char * file)392 ft_dorun(char *file)
393 {
394     static wordlist wl = { NULL, NULL, NULL };
395 
396     wl.wl_word = file;
397     if (file)
398         return dosim("run", &wl);
399     else
400         return dosim("run", NULL);
401 }
402 
403 
404 /* ARGSUSED */ /* until the else clause gets put back */
405 bool
ft_getOutReq(FILE ** fpp,struct plot ** plotp,bool * binp,char * name,char * title)406 ft_getOutReq(FILE **fpp, struct plot **plotp, bool *binp, char *name, char *title)
407 {
408     NG_IGNORE(title);
409     NG_IGNORE(name);
410     NG_IGNORE(plotp);
411 
412     if (rawfileFp) {
413         *fpp = rawfileFp;
414         *binp = rawfileBinary;
415         return (TRUE);
416     } else {
417         return (FALSE);
418     }
419 }
420