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