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" +
  • abort_operation
  • @@ -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)
  • raw_read [file] [sim]
  •     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 
    -
  • test
  • +   
  • test [rawfile type]
  •     testmode 
  • toggle_colorscheme
  •     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\\"