diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 3177e1ca..a45eb3e0 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -514,6 +514,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" +
@@ -1030,13 +1031,14 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
xschem raw_query datasets: get number of datasets (simulation runs)
xschem raw_query value node n: return n-th value of 'node' in raw file
xschem raw_query loaded: return hierarchy level
+ xschem raw_query filename: return raw filename
where raw file was loaded or -1 if no raw loaded
xschem raw_query index node: get index of simulation variable 'node'.
Example: raw_query index v(led) --> 46
xschem raw_query values node [dset] : print all simulation
values of 'node' for dataset 'dset' (default dset=0)
xschem raw_query points [dset] : print simulation points for
- dataset 'dset' (default dataset points combined)
+ dataset 'dset' (default: all dataset points combined)
If a raw file is already loaded delete from memory
else load specified file and analysis 'sim' (dc, ac, tran, op, ...)
@@ -1281,7 +1283,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
props is the attribute string
size sets the size
draw is a flag. If set to 1 will draw the created text
- +
testmode
Toggle dark/light colorscheme
@@ -1379,7 +1381,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
-
diff --git a/src/callback.c b/src/callback.c
index a6ef8dcc..e4839a21 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -188,11 +188,30 @@ static void start_wire(double mx, double my)
}
+static double interpolate_yval(int idx, int point_not_last)
+{
+ double val = xctx->raw->values[idx][xctx->raw->annot_p];
+ /* not operating point, annotate from 'b' cursor */
+ if((xctx->raw->allpoints > 1) && xctx->raw->annot_sweep_idx >= 0) {
+ Raw *raw = xctx->raw;
+ SPICE_DATA *sweep_gv = raw->values[raw->annot_sweep_idx];
+ SPICE_DATA *gv = raw->values[idx];
+ if(point_not_last) {
+ double dx = sweep_gv[raw->annot_p + 1] - sweep_gv[raw->annot_p];
+ double dy = gv[raw->annot_p + 1] - gv[raw->annot_p];
+ double offset = raw->annot_x - sweep_gv[raw->annot_p];
+ double interp = dx != 0.0 ? offset * dy / dx : 0.0;
+ val += interp;
+ }
+ }
+ return val;
+}
+
static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
{
if(sch_waves_loaded() >= 0) {
- int dset, first = -1, last, dataset = gr->dataset, i, p, ofs = 0;
+ int dset, first = -1, last, dataset = gr->dataset, i, p, ofs = 0, ofs_end;
double start, end;
int sweepvar_wrap = 0, sweep_idx;
double xx, cursor2; /* xx is the p-th sweep variable value, cursor2 is cursor 'b' x position */
@@ -217,10 +236,11 @@ static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
int s=0;
+ ofs_end = ofs + raw->npoints[dset];
first = -1;
prev_prev_x = prev_x = 0;
last = ofs;
- for(p = ofs ; p < ofs + raw->npoints[dset]; p++) {
+ for(p = ofs ; p < ofs_end; p++) {
xx = gv[p];
wrap = ( cnt > 1 && XSIGN(xx - prev_x) != XSIGN(prev_x - prev_prev_x));
if(wrap) {
@@ -233,13 +253,13 @@ static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
xx, cursor2, first, last, start, end, p, wrap, sweepvar_wrap, ofs);
if(first == -1) first = p;
if(p == first) {
- if(xx == cursor2) {dset = raw->datasets; break;}
+ if(xx == cursor2) {goto done;}
s = XSIGN0(xx - cursor2);
dbg(1, "s=%d\n", s);
} else {
int ss = XSIGN0(xx - cursor2);
dbg(1, "s=%d, ss=%d\n", s, ss);
- if(ss != s) {dset = raw->datasets; break;}
+ if(ss != s) {goto done;}
}
last = p;
}
@@ -249,10 +269,10 @@ static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
prev_x = xx;
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
/* offset pointing to next dataset */
- ofs += raw->npoints[dset];
+ ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
-
+ done:
if(first != -1) {
if(p > last) {
double sweep0, sweep1;
@@ -264,18 +284,19 @@ static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr)
}
}
dbg(1, "xx=%g, p=%d\n", xx, p);
- tcleval("array unset ngspice::ngspice_data");
+ Tcl_UnsetVar(interp, "ngspice::ngspice_data", TCL_GLOBAL_ONLY);
raw->annot_p = p;
raw->annot_x = cursor2;
raw->annot_sweep_idx = sweep_idx;
for(i = 0; i < raw->nvars; ++i) {
char s[100];
- my_snprintf(s, S(s), "%.4g", raw->values[i][p]);
- dbg(1, "%s = %g\n", raw->names[i], raw->values[i][p]);
- tclvareval("array set ngspice::ngspice_data [list {", raw->names[i], "} ", s, "]", NULL);
+ raw->cursor_b_val[i] = interpolate_yval(i, (p < ofs_end));
+ my_snprintf(s, S(s), "%.5g", raw->cursor_b_val[i]);
+ /* tclvareval("array set ngspice::ngspice_data [list {", raw->names[i], "} ", s, "]", NULL); */
+ Tcl_SetVar2(interp, "ngspice::ngspice_data", raw->names[i], s, TCL_GLOBAL_ONLY);
}
- tclvareval("set ngspice::ngspice_data(n\\ vars) ", my_itoa( raw->nvars), NULL);
- tclvareval("set ngspice::ngspice_data(n\\ points) 1", NULL);
+ Tcl_SetVar2(interp, "ngspice::ngspice_data", "n\\ vars", my_itoa( raw->nvars), TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "ngspice::ngspice_data", "n\\ points", "1", TCL_GLOBAL_ONLY);
}
}
}
diff --git a/src/draw.c b/src/draw.c
index 057c74a7..c9fd4f9c 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -2083,12 +2083,13 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int dataset)
}
if(xctx->raw && v >= 0) {
int sweepvar_wrap = 0; /* incremented on new dataset or sweep variable wrap */
- int ofs = 0;
+ int ofs = 0, ofs_end;
for(dset = 0 ; dset < raw->datasets; dset++) {
double xx, xx0;
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
- for(p = ofs ; p < ofs + raw->npoints[dset]; p++) {
+ ofs_end = ofs + raw->npoints[dset];
+ for(p = ofs ; p < ofs_end; p++) {
if(gr->logx) xx = mylog10(gv[p]);
else xx = gv[p];
if(p == ofs) xx0 = xx;
@@ -2114,7 +2115,7 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int dataset)
}
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
/* offset pointing to next dataset */
- ofs += raw->npoints[dset];
+ ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
}
@@ -2911,7 +2912,7 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
{
int idx = -1;
- int p, dset, ofs;
+ int p, dset, ofs, ofs_end;
int first, last;
double xx; /* the p-th sweep variable value: xctx->raw->values[sweep_idx][p] */
double xx0 = 0; /* first sweep value */
@@ -2930,9 +2931,10 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
for(dset = 0 ; dset < raw->datasets; dset++) {
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
+ ofs_end = ofs + raw->npoints[dset];
first = -1;
last = ofs;
- for(p = ofs ; p < ofs + raw->npoints[dset]; p++) {
+ for(p = ofs ; p < ofs_end; p++) {
if(gr->logx)
xx = mylog10(gv[p]);
else
@@ -2965,7 +2967,7 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
}
}
/* offset pointing to next dataset */
- ofs += raw->npoints[dset];
+ ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
return idx;
@@ -3028,7 +3030,7 @@ int find_closest_wave(int i, Graph_ctx *gr)
else idx = get_raw_index(express);
dbg(1, "find_closest_wave(): expression=%d, idx=%d\n", expression, idx);
if( idx != -1 ) {
- int p, dset, ofs;
+ int p, dset, ofs, ofs_end;
int first, last;
double xx, yy ; /* the p-th point */
double xx0 = 0.0; /* first sweep value */
@@ -3044,7 +3046,8 @@ int find_closest_wave(int i, Graph_ctx *gr)
int cnt=0, wrap;
register SPICE_DATA *gvx = raw->values[sweep_idx];
register SPICE_DATA *gvy;
- if(expression) plot_raw_custom_data(sweep_idx, ofs, ofs + raw->npoints[dset]-1, express);
+ ofs_end = ofs + raw->npoints[dset];
+ if(expression) plot_raw_custom_data(sweep_idx, ofs, ofs_end - 1, express);
gvy = raw->values[idx];
dbg(1, "find_closest_wave(): dset=%d\n", dset);
first = -1;
@@ -3052,7 +3055,7 @@ int find_closest_wave(int i, Graph_ctx *gr)
* p loop split repeated 2 timed (for x and y points) to preserve cache locality */
last = ofs;
dbg(1, "find_closest_wave(): xval=%g yval=%g\n", xval, yval);
- for(p = ofs ; p < ofs + raw->npoints[dset]; p++) {
+ for(p = ofs ; p < ofs_end; p++) {
if(gr->logx) xx = mylog10(gvx[p]);
else xx = gvx[p];
if(p == ofs) xx0 = xx;
@@ -3092,7 +3095,7 @@ int find_closest_wave(int i, Graph_ctx *gr)
prev_x = xx;
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
/* offset pointing to next dataset */
- ofs += raw->npoints[dset];
+ ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
@@ -3224,7 +3227,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
}
/* quickly find index number of ntok_copy variable to be plotted */
if( expression || (idx = get_raw_index(bus_msb ? bus_msb : express)) != -1 ) {
- int p, dset, ofs;
+ int p, dset, ofs, ofs_end;
int poly_npoints;
int first, last;
double xx; /* the p-th sweep variable value: raw->values[sweep_idx][p] */
@@ -3251,7 +3254,8 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
double prev_x;
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
-
+
+ ofs_end = ofs + raw->npoints[dset];
first = -1;
poly_npoints = 0;
my_realloc(_ALLOC_ID_, &point, raw->npoints[dset] * sizeof(XPoint));
@@ -3259,7 +3263,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
* p loop split repeated 2 timed (for x and y points) to preserve cache locality */
prev_x = 0;
last = ofs;
- for(p = ofs ; p < ofs + raw->npoints[dset]; p++) {
+ for(p = ofs ; p < ofs_end; p++) {
if(gr->logx) xx = mylog10(gv[p]);
else xx = gv[p];
if(p == ofs) xx0 = xx;
@@ -3326,7 +3330,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
}
}
/* offset pointing to next dataset */
- ofs += raw->npoints[dset];
+ ofs = ofs_end;
sweepvar_wrap++;
} /* for(dset...) */
bbox(END, 0.0, 0.0, 0.0, 0.0);
diff --git a/src/save.c b/src/save.c
index 91f9a5d9..55122e29 100644
--- a/src/save.c
+++ b/src/save.c
@@ -610,6 +610,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type)
char *ptr;
/* get the list of lines with index and node name */
if(!raw->names) raw->names = my_calloc(_ALLOC_ID_, raw->nvars, sizeof(char *));
+ if(!raw->cursor_b_val) raw->cursor_b_val = my_calloc(_ALLOC_ID_, raw->nvars, sizeof(double));
my_realloc(_ALLOC_ID_, &varname, strlen(line) + 1) ;
n = sscanf(line, "%d %s", &i, varname); /* read index and name of saved waveform */
if(n < 2) {
@@ -672,6 +673,7 @@ void free_rawfile(Raw **rawptr, int dr)
my_free(_ALLOC_ID_, &raw->names[i]);
}
my_free(_ALLOC_ID_, &raw->names);
+ my_free(_ALLOC_ID_, &raw->cursor_b_val);
}
if(raw->values) {
deleted = 1;
@@ -682,8 +684,8 @@ void free_rawfile(Raw **rawptr, int dr)
my_free(_ALLOC_ID_, &raw->values);
}
if(raw->npoints) my_free(_ALLOC_ID_, &raw->npoints);
+ if(raw->filename) my_free(_ALLOC_ID_, &raw->filename);
if(raw->schname) my_free(_ALLOC_ID_, &raw->schname);
- my_strncpy(raw->filename, "", S(raw->filename));
if(raw->table.table) int_hash_free(&raw->table);
my_free(_ALLOC_ID_, rawptr);
if(deleted && dr) draw();
@@ -780,7 +782,7 @@ int raw_read(const char *f, Raw **rawptr, const char *type)
if(fd) {
if((res = read_dataset(fd, rawptr, type)) == 1) {
int i;
- my_strncpy(raw->filename, f, S(raw->filename));
+ my_strdup2(_ALLOC_ID_, &raw->filename, f);
my_strdup2(_ALLOC_ID_, &raw->schname, xctx->sch[xctx->currsch]);
raw->level = xctx->currsch;
raw->allpoints = 0;
@@ -925,8 +927,8 @@ int table_read(const char *f)
raw->allpoints = 0;
if(res == 1) {
int i;
+ my_strdup2(_ALLOC_ID_, &raw->filename, f);
my_strdup2(_ALLOC_ID_, &raw->schname, xctx->sch[xctx->currsch]);
- my_strncpy(raw->filename, f, S(raw->filename));
raw->level = xctx->currsch;
raw->allpoints = 0;
for(i = 0; i < raw->datasets; ++i) {
@@ -938,7 +940,7 @@ int table_read(const char *f)
} else {
dbg(0, "table_read(): no useful data found\n");
}
-
+ raw->cursor_b_val = my_calloc(_ALLOC_ID_, raw->nvars, sizeof(double));
fclose(fd);
return res;
}
diff --git a/src/scheduler.c b/src/scheduler.c
index ba2a4716..3c206440 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -3087,13 +3087,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* xschem raw_query datasets: get number of datasets (simulation runs)
* xschem raw_query value node n: return n-th value of 'node' in raw file
* xschem raw_query loaded: return hierarchy level
+ * xschem raw_query filename: return raw filename
* where raw file was loaded or -1 if no raw loaded
* xschem raw_query index node: get index of simulation variable 'node'.
* Example: raw_query index v(led) --> 46
* xschem raw_query values node [dset] : print all simulation
* values of 'node' for dataset 'dset' (default dset=0)
* xschem raw_query points [dset] : print simulation points for
- * dataset 'dset' (default dataset points combined)
+ * dataset 'dset' (default: all dataset points combined)
*/
else if(!strcmp(argv[1], "raw_query"))
{
@@ -3156,6 +3157,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(dset >= 0 && dset < raw->datasets)
Tcl_SetResult(interp, my_itoa(raw->npoints[dset]), TCL_VOLATILE);
}
+ } else if(argc > 2 && !strcmp(argv[2], "filename")) {
+ Tcl_SetResult(interp, raw->filename, TCL_VOLATILE);
} else if(argc > 2 && !strcmp(argv[2], "vars")) {
Tcl_SetResult(interp, my_itoa(raw->nvars), TCL_VOLATILE);
} else if(argc > 2 && !strcmp(argv[2], "list")) {
@@ -4524,26 +4527,30 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
- /* test
+ /* test [rawfile type]
* testmode */
- else if(0 && !strcmp(argv[1], "test"))
+ else if(!strcmp(argv[1], "test"))
{
- static int swap = 0;
- static Raw *saveraw = NULL;
- if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
- if(swap == 0) {
- saveraw = xctx->raw;
- swap = 1;
- xctx->raw = NULL;
- raw_read("/home/schippes/.xschem/simulations/cmos_example_ngspice2.raw", &xctx->raw, "dc");
- draw();
- } else {
- free_rawfile(&xctx->raw, 0);
- swap = 0;
- xctx->raw = saveraw;
- draw();
- }
+ static int cnt = 1;
+ static Raw *raw[10];
+ static int nraw = 0;
+ if(nraw == 0) {
+ raw[nraw] = xctx->raw;
+ nraw++;
+ }
+ if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
+ if(argc > 3) {
+ xctx->raw = NULL;
+ raw_read(argv[2], &xctx->raw, argv[3]);
+ raw[nraw] = xctx->raw;
+ nraw++;
+ cnt = (cnt + 1) % nraw;
+ draw();
+ } else {
+ xctx->raw = raw[cnt];
+ cnt = (cnt + 1) % nraw;
+ }
Tcl_ResetResult(interp);
}
diff --git a/src/token.c b/src/token.c
index 9a6cc284..1358de28 100644
--- a/src/token.c
+++ b/src/token.c
@@ -3380,31 +3380,6 @@ static char *get_pin_attr(const char *token, int inst, int s_pnetname)
return value;
}
-static double interpolate_yval(int idx)
-{
- double val = xctx->raw->values[idx][xctx->raw->annot_p];
- /* not operating point, annotate from 'b' cursor */
- if((xctx->raw->allpoints > 1) && xctx->raw->annot_sweep_idx >= 0) {
- Raw *raw = xctx->raw;
- int dset;
- int npoints = 0;
- SPICE_DATA *sweep_gv = raw->values[raw->annot_sweep_idx];
- SPICE_DATA *gv = raw->values[idx];
- for(dset = 0 ; dset < raw->datasets; dset++) {
- npoints += raw->npoints[dset];
- if(npoints > raw->annot_p) break;
- }
- if(raw->annot_p + 1 < npoints) {
- double dx = sweep_gv[raw->annot_p + 1] - sweep_gv[raw->annot_p];
- double dy = gv[raw->annot_p + 1] - gv[raw->annot_p];
- double offset = raw->annot_x - sweep_gv[raw->annot_p];
- double interp = dx != 0.0 ? offset * dy / dx : 0.0;
- val += interp;
- }
- }
- return val;
-}
-
/* substitute given tokens in a string with their corresponding values */
/* ex.: name=@name w=@w l=@l ---> name=m112 w=3e-6 l=0.8e-6 */
/* if s==NULL return emty string */
@@ -3624,7 +3599,7 @@ const char *translate(int inst, const char* s)
dbg(1, "translate() @spice_get_voltage: fqnet=%s start_level=%d\n", fqnet, start_level);
idx = get_raw_index(fqnet);
if(idx >= 0) {
- val = interpolate_yval(idx);
+ val = xctx->raw->cursor_b_val[idx];
}
if(idx < 0) {
valstr = "";
@@ -3681,7 +3656,7 @@ const char *translate(int inst, const char* s)
dbg(1, "translate(): net=%s, fqnet=%s start_level=%d\n", net, fqnet, start_level);
idx = get_raw_index(fqnet);
if(idx >= 0) {
- val = interpolate_yval(idx);
+ val = xctx->raw->cursor_b_val[idx];
}
if(idx < 0) {
valstr = "";
@@ -3749,7 +3724,7 @@ const char *translate(int inst, const char* s)
dbg(1, "fqdev=%s\n", fqdev);
idx = get_raw_index(fqdev);
if(idx >= 0) {
- val = interpolate_yval(idx);
+ val = xctx->raw->cursor_b_val[idx];
}
if(idx < 0) {
valstr = "";
@@ -3815,7 +3790,7 @@ const char *translate(int inst, const char* s)
xctx->tok_size = 0;
len = 0;
} else {
- val = interpolate_yval(idx1) - interpolate_yval(idx2);
+ val = xctx->raw->cursor_b_val[idx1] - xctx->raw->cursor_b_val[idx2];
valstr = dtoa_eng(val);
len = xctx->tok_size;
}
@@ -3875,7 +3850,7 @@ const char *translate(int inst, const char* s)
strtolower(fqdev);
idx = get_raw_index(fqdev);
if(idx >= 0) {
- val = interpolate_yval(idx);
+ val = xctx->raw->cursor_b_val[idx];
}
if(idx < 0) {
valstr = "";
diff --git a/src/xschem.h b/src/xschem.h
index 5fb0106e..c3035d70 100644
--- a/src/xschem.h
+++ b/src/xschem.h
@@ -766,7 +766,7 @@ struct hilight_hashentry
typedef struct {
/* spice raw file specific data */
char **names;
- char filename[PATH_MAX];
+ char *filename;
SPICE_DATA **values;
int nvars;
int *npoints;
@@ -780,6 +780,7 @@ typedef struct {
double annot_x; /* X point to backannotate as calculated from mouse position.
* need to interpolate the Y value between annot_p and annot_p + 1 */
int annot_sweep_idx; /* index of sweep variable where cursor annotation has occurred */
+ double *cursor_b_val;
/* when descending hierarchy xctx->current_name changes, xctx->raw_schname
* holds the name of the top schematic from which the raw file was loaded */
char *schname;
diff --git a/xschem_library/ngspice/autozero_comp.sch b/xschem_library/ngspice/autozero_comp.sch
index 427ac89d..95df3af4 100644
--- a/xschem_library/ngspice/autozero_comp.sch
+++ b/xschem_library/ngspice/autozero_comp.sch
@@ -51,7 +51,7 @@ node="cal%0
saout
saout%70
saout%3"
-color="8 14 7 12"
+color="8 19 7 12"
linewidth_mult=1.0
hilight_wave=-1
@@ -65,8 +65,8 @@ x2=4.39927e-07
unitx=n
divx=5
subdivx=2
-node="plus
-minus"
+node="plus%0
+minus%0"
color="4 5"
dataset=-1
linewidth_mult=1.0
@@ -81,8 +81,8 @@ x2=4.39927e-07
unitx=n
divx=5
subdivx=4
-node="en
-cal
+node="en%0
+cal%0
\\"SAOUT#3; vss,saout%3\\"
--slow--
\\"SAOUT#15; vss,saout%15\\"