diff --git a/src/callback.c b/src/callback.c index 7de1337a..a6ef8dcc 100644 --- a/src/callback.c +++ b/src/callback.c @@ -266,6 +266,8 @@ 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"); 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]); @@ -403,6 +405,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int } } else { xctx->raw->annot_p = -1; + xctx->raw->annot_sweep_idx = -1; /* need_all_redraw = 1; */ redraw_all_at_end = 1; } diff --git a/src/save.c b/src/save.c index 0c254f83..91f9a5d9 100644 --- a/src/save.c +++ b/src/save.c @@ -383,18 +383,16 @@ void transpose_matrix(double *a, int r, int c) * data layout in memory arranged to maximize cache locality * when looking up data */ -static void read_binary_block(FILE *fd, Raw *raw) +static void read_binary_block(FILE *fd, Raw *raw, int ac) { int p, v; double *tmp; int offset = 0; - int ac = 0; if(!raw) { dbg(0, "read_binary_block() no raw struct allocated\n"); return; } - if(!strcmp(raw->sim_type, "ac")) ac = 1; /* AC analysis, complex numbers twice the size */ for(p = 0 ; p < raw->datasets; p++) { offset += raw->npoints[p]; @@ -497,7 +495,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) if(raw->sim_type) { done_header = 1; dbg(dbglev, "read_dataset(): read binary block, nvars=%d npoints=%d\n", nvars, npoints); - read_binary_block(fd, raw); + read_binary_block(fd, raw, ac); raw->datasets++; exit_status = 1; } else { @@ -775,6 +773,7 @@ int raw_read(const char *f, Raw **rawptr, const char *type) raw = *rawptr; raw->level = -1; raw->annot_p = -1; + raw->annot_sweep_idx = -1; int_hash_init(&raw->table, HASHSIZE); fd = fopen(f, fopen_read_mode); @@ -842,6 +841,7 @@ int table_read(const char *f) raw = xctx->raw; raw->level = -1; raw->annot_p = -1; + raw->annot_sweep_idx = -1; /* quick inspect file and get upper bound of number of data lines */ ufd = open(f, O_RDONLY); diff --git a/src/token.c b/src/token.c index d41b9cc0..f8d755f9 100644 --- a/src/token.c +++ b/src/token.c @@ -3380,6 +3380,31 @@ 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; + 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 */ @@ -3599,7 +3624,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 = xctx->raw->values[idx][xctx->raw->annot_p]; + val = interpolate_yval(idx); } if(idx < 0) { valstr = ""; @@ -3656,7 +3681,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 = xctx->raw->values[idx][xctx->raw->annot_p]; + val = interpolate_yval(idx); } if(idx < 0) { valstr = ""; @@ -3724,7 +3749,7 @@ const char *translate(int inst, const char* s) dbg(1, "fqdev=%s\n", fqdev); idx = get_raw_index(fqdev); if(idx >= 0) { - val = xctx->raw->values[idx][xctx->raw->annot_p]; + val = interpolate_yval(idx); } if(idx < 0) { valstr = ""; @@ -3784,19 +3809,13 @@ const char *translate(int inst, const char* s) dbg(1, "translate(): fqnet1=%s start_level=%d\n", fqnet1, start_level); dbg(1, "translate(): fqnet2=%s start_level=%d\n", fqnet2, start_level); idx1 = get_raw_index(fqnet1); - if(idx1 >= 0) { - val1 = xctx->raw->values[idx1][xctx->raw->annot_p]; - } idx2 = get_raw_index(fqnet2); - if(idx2 >= 0) { - val2 = xctx->raw->values[idx2][xctx->raw->annot_p]; - } - val = val1 - val2; if(idx1 < 0 || idx2 < 0) { valstr = ""; xctx->tok_size = 0; len = 0; } else { + val = interpolate_yval(idx1) - interpolate_yval(idx2); valstr = dtoa_eng(val); len = xctx->tok_size; } @@ -3856,7 +3875,7 @@ const char *translate(int inst, const char* s) strtolower(fqdev); idx = get_raw_index(fqdev); if(idx >= 0) { - val = xctx->raw->values[idx][xctx->raw->annot_p]; + val = interpolate_yval(idx); } if(idx < 0) { valstr = ""; diff --git a/src/xschem.h b/src/xschem.h index 9096c733..5fb0106e 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -774,7 +774,12 @@ typedef struct { int datasets; Int_hashtable table; const char *sim_type; /* type of sim, "tran", "dc", "ac", "op", ... */ - int annot_p; /* point in raw file to use for annotating schematic voltages/currents/etc */ + int annot_p; /* point in raw file to use for annotating schematic voltages/currents/etc + * this is the closest available simulated point *before* the point + * calculated from mouse in graph */ + 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 */ /* 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;