diff --git a/examples/xspice/pll/pll-xspice-fstep.cir b/examples/xspice/pll/pll-xspice-fstep.cir index 0bb2fb17f..09feede63 100644 --- a/examples/xspice/pll/pll-xspice-fstep.cir +++ b/examples/xspice/pll/pll-xspice-fstep.cir @@ -69,7 +69,7 @@ save cont s1 s2 u1 d1 set xbrushwidth=2 let isbmode = $?batchmode if isbmode = 0 - iplot -w $&simtime cont + iplot -w $&simtime -d 4000 cont endif * calculate breakpoint for switching frequency let t1_3 = simtime/3 diff --git a/examples/xspice/pll/pll-xspice.cir b/examples/xspice/pll/pll-xspice.cir index 1d14368de..a1df101f1 100644 --- a/examples/xspice/pll/pll-xspice.cir +++ b/examples/xspice/pll/pll-xspice.cir @@ -64,7 +64,7 @@ abridge-w1 [d_divout d_ref d_Un d_D] [s1 s2 u1n d1] dac1 ; change to d_u or d_Un .control save cont s1 s2 u1n d1 v.xlf.vdd#branch; to save memory -iplot cont +iplot -d 4000 cont tran 0.1n $&simtime uic rusage plot cont s1 s2+1.2 u1n+2.4 d1+3.6 xlimit 4u 5u diff --git a/src/frontend/breakp.c b/src/frontend/breakp.c index 190e91730..cf1e410b4 100644 --- a/src/frontend/breakp.c +++ b/src/frontend/breakp.c @@ -205,36 +205,50 @@ com_iplot(wordlist *wl) /* settrace(wl, VF_PLOT); */ struct dbcomm *d, *td, *currentdb = NULL; - double window; + double window = 0.0; + int initial_steps = IPOINTMIN; char *s; - /* Look for "-w window-size" at the front, indicating a windowed iplot. */ + /* Look for "-w window-size" at the front, indicating a windowed iplot + * or "-d steps" to set the initial delay before the window appears. + */ - if (wl->wl_next && !strcmp("-w", wl->wl_word)) { - char *cp; - int error; + while (wl && wl->wl_word[0] == '-') { + if (wl->wl_word[1] == 'w' && !wl->wl_word[2]) { + wl = wl->wl_next; + if (wl) { + char *cp; + int error; - wl = wl->wl_next; - cp = wl->wl_word; - window = INPevaluate(&cp, &error, 0); - if (error || window <= 0) { - fprintf(cp_err, "Incremental plot width must be positive.\n"); - return; + cp = wl->wl_word; + window = INPevaluate(&cp, &error, 0); + if (error || window <= 0) { + fprintf(cp_err, + "Incremental plot width must be positive.\n"); + return; + } + } + } else if (wl->wl_word[1] == 'd' && !wl->wl_word[2]) { + wl = wl->wl_next; + if (wl) + initial_steps = atoi(wl->wl_word); + } else { + break; } wl = wl->wl_next; - } else { - window = 0.0; } /* We use a modified ad-hoc algorithm here where db_also denotes vectors on the same command line and db_next denotes separate iplot commands. */ + while (wl) { s = cp_unquote(wl->wl_word); d = TMALLOC(struct dbcomm, 1); d->db_analysis = NULL; d->db_number = debugnumber++; - d->db_value1 = window; // Field re-use + d->db_op = initial_steps; // Field re-use + d->db_value1 = window; // Field re-use if (eq(s, "all")) { d->db_type = DB_IPLOTALL; } else { diff --git a/src/frontend/com_compose.c b/src/frontend/com_compose.c index 099e68c8b..7d2249a70 100644 --- a/src/frontend/com_compose.c +++ b/src/frontend/com_compose.c @@ -11,6 +11,7 @@ #include "ngspice/fteext.h" #include "ngspice/cpextern.h" #include "ngspice/randnumb.h" +#include "ngspice/evtproto.h" #include "com_compose.h" #include "completion.h" @@ -225,9 +226,26 @@ com_compose(wordlist *wl) } length *= blocksize; - } - else { +#ifdef XSPICE + } else if (eq(wl->wl_word, "xspice")) { + /* Make vectors from an event node. */ + + result = EVTfindvec(resname); + if (result == NULL) { + fprintf(cp_err, "There is no event node %s or it has no data\n", + resname); + goto done; + } + result->v_flags |= VF_PERMANENT; + result->v_scale->v_flags |= VF_PERMANENT; + vec_new(result->v_scale); + cp_addkword(CT_VECTOR, result->v_scale->v_name); + txfree(resname); // It was copied + goto finished; +#endif + } else { /* Parse the line... */ + while (wl) { char *s, *var, *val; if ((s = strchr(wl->wl_word, '=')) != NULL && s[1]) { @@ -600,6 +618,7 @@ com_compose(wordlist *wl) /* The allocation for resname has been assigned to the result vector, so * set to NULL so that it is not freed */ + finished: resname = NULL; /* Set dimension info */ diff --git a/src/frontend/com_setscale.c b/src/frontend/com_setscale.c index 024bb043d..254b65c39 100644 --- a/src/frontend/com_setscale.c +++ b/src/frontend/com_setscale.c @@ -9,30 +9,64 @@ #include "plotting/pvec.h" #include "ngspice/fteext.h" +static struct dvec *find_vec(wordlist *wl) +{ + struct dvec *d; + char *s; + + s = cp_unquote(wl->wl_word); + if (s) { + d = vec_get(s); + tfree(s); /*DG to avoid the cp_unquote memory leak */ + } else { + d = NULL; + } + + if (d == NULL) + fprintf(cp_err, "Error: no such vector as %s.\n", wl->wl_word); + return d; +} /* Set the default scale to the named vector. If no vector named, * find and print the default scale. */ + void com_setscale(wordlist *wl) { - struct dvec *d; - char *s; + struct dvec *d, *ds; - if (plot_cur) { - if (wl) { - s = cp_unquote(wl->wl_word); - d = vec_get(s); - if (s) - tfree(s);/*DG to avoid the cp_unquote memory leak */ - - if (d == NULL) - fprintf(cp_err, "Error: no such vector as %s.\n", wl->wl_word); - else - plot_cur->pl_scale = d; - } else if (plot_cur->pl_scale) { - pvec(plot_cur->pl_scale); - } - } else { + if (!plot_cur) { fprintf(cp_err, "Error: no current plot.\n"); + return; + } + + if (!wl) { + if (plot_cur->pl_scale) + pvec(plot_cur->pl_scale); + return; + } + + d = find_vec(wl); + if (d == NULL) + return; + + /* Two-word form for altering the scale of a specific vector? + * Keyword "none" clears the scale so that the plot's default scale + * will be used. + */ + + wl = wl->wl_next; + if (wl) { + if (!strcmp(wl->wl_word, "none")) { + d->v_scale = NULL; + return; + } + + ds = find_vec(wl); + if (ds == NULL) + return; + d->v_scale = ds; + } else { + plot_cur->pl_scale = d; } } diff --git a/src/frontend/com_shell.c b/src/frontend/com_shell.c index 96e60417f..a2a73d098 100644 --- a/src/frontend/com_shell.c +++ b/src/frontend/com_shell.c @@ -14,13 +14,14 @@ #ifdef _WIN32 #define SHELL "cmd /k" #else -#define SHELL "/bin/csh" +#define SHELL "/bin/sh" #endif /* Fork a shell. */ void com_shell(wordlist *wl) { + int status; char *shell = NULL; shell = getenv("SHELL"); @@ -61,16 +62,20 @@ com_shell(wordlist *wl) /* Easier to forget about changing the io descriptors. */ if (wl) { char * const com = wl_flatten(wl); - if (system(com) == -1) { + + status = system(com); + if (status == -1) { (void) fprintf(cp_err, "Unable to execute \"%s\".\n", com); } txfree(com); } else { - if (system(shell) == -1) { + status = system(shell); + if (status == -1) { (void) fprintf(cp_err, "Unable to execute \"%s\".\n", shell); } } + cp_vset("shellstatus", CP_NUM, &status); #endif } /* end of function com_shell */ diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 225dbf884..a72560cba 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -195,9 +195,10 @@ struct comm spcp_coms[] = { NULL, "[circuit name] : Change the current circuit." } , { "setscale", com_setscale, FALSE, FALSE, - { 040000, 0, 0, 0 }, E_DEFHMASK, 0, 1, + { 040000, 0, 0, 0 }, E_DEFHMASK, 0, 2, NULL, - "[vecname] : Change default scale of current working plot." } , + "[vecname [vecname]] : Change default scale of current working plot" + "\n or set/clear the scale for a single vector." } , { "setseed", com_sseed, FALSE, FALSE, { 04, 0, 0, 0 }, E_DEFHMASK, 0, 1, NULL, @@ -426,7 +427,7 @@ struct comm spcp_coms[] = { { "iplot", com_iplot, TRUE, TRUE, { 0200, 0200, 0200, 0200 }, E_DEFHMASK, 0, LOTS, NULL, - "[-w width] [all] [node ...] : Incrementally plot nodes." } , + "[-w width] [-s initial_steps] [all] [node ...] : Incrementally plot nodes." } , { "status", com_sttus, TRUE, FALSE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0, NULL, diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 0b0c21f2c..0cbbf0425 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -1340,6 +1340,7 @@ inp_dodeck( g_ipc.syntax_error = IPC_TRUE; #endif p = dd->error; + fflush(stdout); do { q = strchr(p, '\n'); if (q) @@ -1348,7 +1349,7 @@ inp_dodeck( if (p == dd->error) { if (strstr(dd->line, ".model")) fprintf(stderr, "Warning: Model issue on line %d :\n %.*s ...\n%s\n", - dd->linenum_orig, 72, dd->line, dd->error); + dd->linenum_orig, 72, dd->line, dd->error); else if (dd->linenum_orig == 0) { fprintf(stderr, "Error on line:\n %s\n%s\n", dd->line, dd->error); @@ -1364,13 +1365,13 @@ inp_dodeck( if (ft_stricterror) controlled_exit(EXIT_BAD); } else { - out_printf("%s\n", p); + fprintf(stderr, "%s\n", p); } - if (q) *q++ = '\n'; p = q; } while (p && *p); + fprintf(stderr, "\n"); } /* end if (dd->error) */ } /* for (dd = deck; dd; dd = dd->nextcard) */ diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 2ed33d5d4..d557bf5a3 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -629,6 +629,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stdout, " Reference value : % 12.5e\r", refValue->cValue.real); + fflush(stdout); lastclock = currclock; } } @@ -642,6 +643,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stdout, " Reference value : % 12.5e\r", refValue->rValue); + fflush(stdout); lastclock = currclock; } } @@ -741,6 +743,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) fprintf(stdout, " Reference value : % 12.5e\r", refValue ? refValue->rValue : NAN); } + fflush(stdout); lastclock = currclock; } } @@ -1508,6 +1511,7 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stdout, " Reference value : % 12.5e\r", refValue->rValue); + fflush(stdout); lastclock = currclock; } } @@ -1672,6 +1676,7 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { fprintf(stdout, " Reference value : % 12.5e\r", refValue->rValue); + fflush(stdout); lastclock = currclock; } } diff --git a/src/frontend/plotting/graf.c b/src/frontend/plotting/graf.c index 33e7187ae..590b419b6 100644 --- a/src/frontend/plotting/graf.c +++ b/src/frontend/plotting/graf.c @@ -855,7 +855,7 @@ static int iplot(struct plot *pl, struct dbcomm *db) /* Do simple check for exit first */ window = db->db_value1; - if (len < 2 || (window == 0.0 && len < IPOINTMIN)) { /* Nothing yet */ + if (len < 2 || db->db_op > len) { /* Nothing yet */ return 0; } diff --git a/src/frontend/plotting/plotit.c b/src/frontend/plotting/plotit.c index 5d4d245bf..0b8b9a951 100644 --- a/src/frontend/plotting/plotit.c +++ b/src/frontend/plotting/plotit.c @@ -859,7 +859,11 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) int ii = 0, jj = 0; for (d = vecs; d; d = d->v_link2) { - if (d->v_scale && eq(d->v_scale->v_name, "step") && (d->v_scale->v_type == SV_TIME) && (d->v_type == SV_VOLTAGE) && (d->v_length > 1)) { + if ((d->v_flags & VF_EVENT_NODE) && + !(d->v_flags & VF_PERMANENT) && + d->v_scale && (d->v_scale->v_flags & VF_EVENT_NODE) && + (d->v_scale->v_type == SV_TIME) && (d->v_type == SV_VOLTAGE) && + (d->v_length > 1)) { for (ii = 0; ii < d->v_length; ii++) { d->v_realdata[ii] += nn; } diff --git a/src/frontend/plotting/x11.c b/src/frontend/plotting/x11.c index 8879328ac..fed83762c 100644 --- a/src/frontend/plotting/x11.c +++ b/src/frontend/plotting/x11.c @@ -449,17 +449,24 @@ X11_NewViewport(GRAPH *graph) static Arg formargs[ ] = { { XtNleft, (XtArgVal) XtChainLeft }, - { XtNresizable, (XtArgVal) TRUE } + { XtNresizable, (XtArgVal) TRUE }, + { XtNbackground, (XtArgVal) 0x191942} // MidnightBlue }; static Arg bboxargs[ ] = { { XtNfromHoriz, (XtArgVal) NULL }, { XtNbottom, (XtArgVal) XtChainTop }, { XtNtop, (XtArgVal) XtChainTop }, { XtNleft, (XtArgVal) XtChainRight }, - { XtNright, (XtArgVal) XtChainRight } + { XtNright, (XtArgVal) XtChainRight }, + { XtNbackground, (XtArgVal) 0xbebebe} + }; + static Arg quitbuttonargs[ ] = { + { XtNlabel, (XtArgVal) "Quit" }, + { XtNbackground, (XtArgVal) 0xff4500} // OrangeRed }; static Arg buttonargs[ ] = { - { XtNlabel, (XtArgVal) NULL } + { XtNlabel, (XtArgVal) NULL }, + { XtNbackground, (XtArgVal) 0x87cefa} // LightSkyBlue }; static Arg viewargs[] = { { XtNresizable, (XtArgVal) TRUE }, @@ -500,21 +507,18 @@ X11_NewViewport(GRAPH *graph) ("buttonbox", boxWidgetClass, DEVDEP(graph).form, bboxargs, XtNumber(bboxargs)); /* set up buttons */ - XtSetArg(buttonargs[0], XtNlabel, "Quit"); - XtSetArg(bboxargs[1], XtNfromVert, NULL); DEVDEP(graph).buttons[0] = XtCreateManagedWidget - ("quit", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 1); + ("quit", commandWidgetClass, DEVDEP(graph).buttonbox, quitbuttonargs, 2); XtAddCallback(DEVDEP(graph).buttons[0], XtNcallback, killwin, graph); XtSetArg(buttonargs[0], XtNlabel, "PostScript"); - XtSetArg(bboxargs[1], XtNfromVert, DEVDEP(graph).buttons[0]); DEVDEP(graph).buttons[1] = XtCreateManagedWidget - ("hardcopy", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 1); + ("hardcopy", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 2); XtAddCallback(DEVDEP(graph).buttons[1], XtNcallback, hardcopy, graph); XtSetArg(buttonargs[0], XtNlabel, "SVG"); DEVDEP(graph).buttons[2] = XtCreateManagedWidget( - "SVG", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 1); + "SVG", commandWidgetClass, DEVDEP(graph).buttonbox, buttonargs, 2); XtAddCallback(DEVDEP(graph).buttons[2], XtNcallback, hardcopySVG, graph); /* set up fonts */ diff --git a/src/include/ngspice/dvec.h b/src/include/ngspice/dvec.h index ea0a9b83c..558eb6929 100644 --- a/src/include/ngspice/dvec.h +++ b/src/include/ngspice/dvec.h @@ -16,7 +16,8 @@ enum dvec_flags { VF_PRINT = (1 << 4), /* writedata should print this vector. */ VF_MINGIVEN = (1 << 5), /* The v_minsignal value is valid. */ VF_MAXGIVEN = (1 << 6), /* The v_maxsignal value is valid. */ - VF_PERMANENT = (1 << 7) /* Don't garbage collect this vector. */ + VF_PERMANENT = (1 << 7), /* Don't garbage collect this vector. */ + VF_EVENT_NODE = (1 << 8) /* Derived from and XSPICE event node. */ }; diff --git a/src/include/ngspice/ftedebug.h b/src/include/ngspice/ftedebug.h index f9225f43e..34c215904 100644 --- a/src/include/ngspice/ftedebug.h +++ b/src/include/ngspice/ftedebug.h @@ -34,6 +34,8 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #define DBC_GTE 5 /* >= (ge) */ #define DBC_LTE 6 /* <= (le) */ +/* Below, members db_op and db_value1 are re-purposed by iplot options. */ + struct dbcomm { int db_number; /* The number of this debugging command. */ char db_type; /* One of the above. */ @@ -41,7 +43,7 @@ struct dbcomm { char *db_nodename2; /* What node. */ char *db_analysis; /* for a specific analysis. */ int db_iteration; /* For the DB_STOPAFTER command. */ - char db_op; /* For DB_STOPWHEN. */ + int db_op; /* For DB_STOPWHEN. */ double db_value1; /* If this is DB_STOPWHEN. */ double db_value2; /* If this is DB_STOPWHEN. */ int db_graphid; /* If iplot, id of graph. */ diff --git a/src/spicelib/devices/vsrc/vsrcacct.c b/src/spicelib/devices/vsrc/vsrcacct.c index 0be45f8e2..36994a837 100644 --- a/src/spicelib/devices/vsrc/vsrcacct.c +++ b/src/spicelib/devices/vsrc/vsrcacct.c @@ -172,7 +172,11 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel) period = end - here->VSRCcoeffs[here->VSRCrBreakpt]; + time -= + here->VSRCcoeffs[here->VSRCrBreakpt]; time -= period * floor(time / period); + time += + here->VSRCcoeffs[here->VSRCrBreakpt]; } else { here->VSRCbreak_time = ckt->CKTfinalTime; break; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index a24bacc31..c68138eb1 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -318,6 +318,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) period = end_time - here->VSRCcoeffs[here->VSRCrBreakpt]; + time -= here->VSRCcoeffs[here->VSRCrBreakpt]; time -= period * floor(time / period); time += here->VSRCcoeffs[here->VSRCrBreakpt]; } else { diff --git a/src/xspice/evt/evtplot.c b/src/xspice/evt/evtplot.c index af5c50792..a4d17842f 100644 --- a/src/xspice/evt/evtplot.c +++ b/src/xspice/evt/evtplot.c @@ -206,14 +206,15 @@ struct dvec *EVTfindvec( /* Allocate dvec structures and assign the vectors into them. */ /* See FTE/OUTinterface.c:plotInit() for initialization example. */ - scale = dvec_alloc(MIFcopy("step"), + ptr = tprintf("%s_steps", name); + scale = dvec_alloc(ptr, SV_TIME, - VF_REAL & ~VF_PERMANENT, + (VF_REAL | VF_EVENT_NODE) & ~VF_PERMANENT, i, anal_point_vec); d = dvec_alloc(name, SV_VOLTAGE, - VF_REAL & ~VF_PERMANENT, + (VF_REAL | VF_EVENT_NODE) & ~VF_PERMANENT, i, value_vec); d->v_scale = scale;