ngspice/src/frontend/runcoms.c

305 lines
6.8 KiB
C
Raw Normal View History

2000-04-27 22:03:57 +02:00
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
**********/
/*
* Circuit simulation commands.
*/
#include "ngspice.h"
#include "cpdefs.h"
#include "ftedefs.h"
#include "ftedev.h"
#include "ftedebug.h"
#include "ftedata.h"
#include "runcoms.h"
/* static declarations */
static int dosim(char *what, wordlist *wl);
extern struct dbcomm *dbs;
/* Routines for the commands op, tran, ac, dc, listing, device, state,
* resume, stop, trace, run, end. Op, tran, ac, and dc cause the action
* to be performed immediately, and run causes whatever actions were
* present in the deck to be carried out. End has the effect of stopping
* any simulations in progress, as opposed to ending te input deck as
* the .end line does.
*/
FILE *rawfileFp;
bool rawfileBinary;
void
com_scirc(wordlist *wl)
{
struct circ *p;
int i, j = 0;
char buf[BSIZE_SP];
if (ft_circuits == NULL) {
fprintf(cp_err, "Error: there aren't any circuits loaded.\n");
return;
}
if (wl == NULL) {
fprintf(cp_out,
"\tType the number of the desired circuit:\n\n");
for (p = ft_circuits; p; p = p->ci_next) {
if (ft_curckt == p)
fprintf(cp_out, "Current");
fprintf(cp_out, "\t%d\t%s\n", ++j, p->ci_name);
}
fprintf(cp_out, "? ");
(void) fflush(cp_out);
(void) fgets(buf, BSIZE_SP, cp_in);
clearerr(cp_in);
if ((sscanf(buf, " %d ", &i) != 1) || (i < 0) || (i > j))
return;
for (p = ft_circuits; --i > 0; p = p->ci_next);
} else {
for (p = ft_circuits; p; p = p->ci_next)
if (ciprefix(wl->wl_word, p->ci_name))
break;
if (p == NULL) {
fprintf(cp_err, "Warning: no such circuit \"%s\"\n",
wl->wl_word);
return;
}
fprintf(cp_out, "\t%s\n", p->ci_name);
}
if (ft_curckt) {
/* Actually this can't be FALSE */
ft_curckt->ci_devices =
cp_kwswitch(CT_DEVNAMES, p->ci_devices);
ft_curckt->ci_nodes = cp_kwswitch(CT_NODENAMES, p->ci_nodes);
}
ft_curckt = p;
return;
}
void
com_pz(wordlist *wl)
{
dosim("pz", wl);
return;
}
void
com_op(wordlist *wl)
{
dosim("op", wl);
return;
}
void
com_dc(wordlist *wl)
{
dosim("dc", wl);
return;
}
void
com_ac(wordlist *wl)
{
dosim("ac", wl);
return;
}
void
com_tf(wordlist *wl)
{
dosim("tf", wl);
return;
}
void
com_tran(wordlist *wl)
{
dosim("tran", wl);
return;
}
void
com_sens(wordlist *wl)
{
dosim("sens", wl);
return;
}
void
com_disto(wordlist *wl)
{
dosim("disto", wl);
return;
}
void
com_noise(wordlist *wl)
{
dosim("noise", wl);
return;
}
static int
dosim(char *what, wordlist *wl)
{
wordlist *ww;
bool dofile = FALSE;
char buf[BSIZE_SP];
struct circ *ct;
int err = 0;
bool ascii = AsciiRawFile;
if (eq(what, "run") && wl)
dofile = TRUE;
if (!dofile) {
ww = alloc(struct wordlist);
ww->wl_next = wl;
if (wl)
wl->wl_prev = ww;
ww->wl_word = copy(what);
}
if (cp_getvar("filetype", VT_STRING, buf)) {
if (eq(buf, "binary"))
ascii = FALSE;
else if (eq(buf, "ascii"))
ascii = TRUE;
else
fprintf(cp_err,
"Warning: strange file type \"%s\" (using \"ascii\")\n",
buf);
}
if (!ft_curckt) {
fprintf(cp_err, "Error: there aren't any circuits loaded.\n");
return 1;
} else if (ft_curckt->ci_ckt == NULL) { /* Set noparse? */
fprintf(cp_err, "Error: circuit not parsed.\n");
return 1;
}
for (ct = ft_circuits; ct; ct = ct->ci_next)
if (ct->ci_inprogress && (ct != ft_curckt)) {
fprintf(cp_err,
"Warning: losing old state for circuit '%s'\n",
ct->ci_name);
ct->ci_inprogress = FALSE;
}
if (ft_curckt->ci_inprogress && eq(what, "resume")) {
ft_setflag = TRUE;
ft_intrpt = FALSE;
fprintf(cp_err, "Warning: resuming run in progress.\n");
com_resume((wordlist *) NULL);
ft_setflag = FALSE;
return 0;
}
/* From now on until the next prompt, an interrupt will just
* set a flag and let spice finish up, then control will be
* passed back to the user.
*/
ft_setflag = TRUE;
ft_intrpt = FALSE;
if (dofile) {
#ifdef PARALLEL_ARCH
if (ARCHme == 0) {
#endif /* PARALLEL_ARCH */
if (!*wl->wl_word)
rawfileFp = stdout;
else if (!(rawfileFp = fopen(wl->wl_word, "w"))) {
perror(wl->wl_word);
ft_setflag = FALSE;
return 1;
}
rawfileBinary = !ascii;
#ifdef PARALLEL_ARCH
} else {
rawfileFp = NULL;
}
#endif /* PARALLEL_ARCH */
} else {
rawfileFp = NULL;
}
/* Spice calls wrd_init and wrd_end itself */
ft_curckt->ci_inprogress = TRUE;
if (eq(what,"sens2")) {
if (if_sens_run(ft_curckt->ci_ckt, ww, ft_curckt->ci_symtab) == 1) {
/* The circuit was interrupted somewhere. */
fprintf(cp_err, "%s simulation interrupted\n", what);
} else
ft_curckt->ci_inprogress = FALSE;
} else {
err = if_run(ft_curckt->ci_ckt, what, ww, ft_curckt->ci_symtab);
if (err == 1) {
/* The circuit was interrupted somewhere. */
fprintf(cp_err, "%s simulation interrupted\n", what);
err = 0;
} else if (err == 2) {
fprintf(cp_err, "%s simulation(s) aborted\n", what);
ft_curckt->ci_inprogress = FALSE;
err = 1;
} else
ft_curckt->ci_inprogress = FALSE;
}
if (rawfileFp)
(void) fclose(rawfileFp);
ft_curckt->ci_runonce = TRUE;
ft_setflag = FALSE;
return err;
}
/* Usage is run [filename] Do the wrd_{open,run} and wrd_(void) close
* here, and let the CKT stuff do wrd_init and wrd_end.
*/
void
com_run(wordlist *wl)
{
/* ft_getsaves(); */
dosim("run", wl);
return;
}
int
ft_dorun(char *file)
{
static wordlist wl = { NULL, NULL, NULL } ;
wl.wl_word = file;
if (file)
return dosim("run", &wl);
else
return dosim("run", (wordlist *) NULL);
}
/* ARGSUSED */ /* until the else clause gets put back */
bool
ft_getOutReq(FILE **fpp, struct plot **plotp, bool *binp, char *name, char *title)
{
/*struct plot *pl;*/
if (rawfileFp) {
*fpp = rawfileFp;
*binp = rawfileBinary;
return (TRUE);
} else {
/*
pl = plot_alloc(name);
pl->pl_title = copy(title);
pl->pl_name = copy(name);
pl->pl_date = copy(datestring( ));
pl->pl_next = plot_list;
plot_list = pl;
plot_cur = pl;
*plotp = pl;
*/
return (FALSE);
}
}