From ae1bed65f4bdc900e061531c9c025ec97b1e9fcf Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Fri, 2 Sep 2022 17:11:50 +0200 Subject: [PATCH] added [t]rack bindkey in graph to display the wave closest to mouse in multiple dataset plots --- src/callback.c | 25 ++++++++- src/draw.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++-- src/token.c | 2 +- src/xschem.h | 1 + 4 files changed, 158 insertions(+), 6 deletions(-) diff --git a/src/callback.c b/src/callback.c index bbb06533..9b2a6f63 100644 --- a/src/callback.c +++ b/src/callback.c @@ -471,6 +471,25 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int } } } + else if((key == 't') ) { + int dset = -1; + if(!gr->digital && i == xctx->graph_master) { + const char *d = get_tok_value(r->prop_ptr, "dataset", 0); + if(d[0]) { + dset = atoi(d); + } else { + dset = -1; + } + if(dset >= 0) { + my_strdup(1448, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", "-1")); + } else { + dset = find_closest_wave(i, gr); + my_strdup(1448, &r->prop_ptr, subst_token(r->prop_ptr, "dataset", my_itoa(dset))); + } + need_redraw = 1; + + } + } /* key == 't' */ else if(key == XK_Left) { double delta; if(xctx->graph_left) { @@ -483,7 +502,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int yy2 = gr->gy2 + var * b / delta; yy1 = gr->gy1 - var * a / delta; my_strdup(1451, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(yy1))); - my_strdup(1448, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2))); + my_strdup(1517, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(yy2))); need_redraw = 1; } } else { @@ -1487,6 +1506,10 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key, } if(key=='t' && state == 0) /* place text */ { + if(waves_selected(event, state, button)) { + waves_callback(event, mx, my, key, button, aux, state); + break; + } if(xctx->semaphore >= 2) break; xctx->last_command = 0; xctx->mx_double_save = xctx->mousex_snap; diff --git a/src/draw.c b/src/draw.c index 722d55d4..786aef91 100644 --- a/src/draw.c +++ b/src/draw.c @@ -2506,6 +2506,134 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr) return idx; } +int find_closest_wave(int i, Graph_ctx *gr) +{ + double xval, yval; + char *node = NULL, *sweep = NULL; + int sweep_idx = 0; + char *saven, *saves, *nptr, *sptr; + const char *ntok, *stok; + int wcnt = 0, idx, expression; + char *express = NULL; + xRect *r = &xctx->rect[GRIDLAYER][i]; + int closest_dataset = -1; + double min=-1.0; + + if(gr->digital) return -1; + + yval = G_Y(xctx->mousey); + xval = G_X(xctx->mousex); + if(gr->logx) xval = pow(10, xval); + if(gr->logy) yval = pow(10, yval); + dbg(0, "x=%g y=%g\n", xval, yval); + /* get data to plot */ + my_strdup2(474, &node, get_tok_value(r->prop_ptr,"node",0)); + my_strdup2(1012, &sweep, get_tok_value(r->prop_ptr,"sweep",0)); + nptr = node; + sptr = sweep; + /* process each node given in "node" attribute, get also associated sweep var if any*/ + while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) { + if(strstr(ntok, ",")) { + if(find_nth(ntok, ";,", 2)[0]) continue; /* bus signal: skip */ + } + stok = my_strtok_r(sptr, "\t\n ", "\"", &saves); + nptr = sptr = NULL; + dbg(1, "ntok=%s\n", ntok); + if(stok && stok[0]) { + sweep_idx = get_raw_index(stok); + if( sweep_idx == -1) { + sweep_idx = 0; + } + } + /* if ntok following possible 'alias;' definition contains spaces --> custom data plot */ + idx = -1; + expression = 0; + if(xctx->graph_values) { + if(strstr(ntok, ";")) { + my_strdup2(1191, &express, find_nth(ntok, ";", 2)); + } else { + my_strdup2(1192, &express, ntok); + } + if(strstr(express, " ")) { + expression = 1; + } + } + if(expression) idx = plot_raw_custom_data(sweep_idx, 0, xctx->graph_allpoints-1, express); + else idx = get_raw_index(express); + if( idx != -1 ) { + int p, dset, ofs; + int first, last; + double xx, yy ; /* the p-th point */ + double start; + double end; + int sweepvar_wrap = 0; /* incremented on new dataset or sweep variable wrap */ + ofs = 0; + start = (gr->gx1 <= gr->gx2) ? gr->gx1 : gr->gx2; + end = (gr->gx1 <= gr->gx2) ? gr->gx2 : gr->gx1; + /* loop through all datasets found in raw file */ + for(dset = 0 ; dset < xctx->graph_datasets; dset++) { + double prev_x, prev_prev_x; + int cnt=0, wrap; + register SPICE_DATA *gvx = xctx->graph_values[sweep_idx]; + register SPICE_DATA *gvy = xctx->graph_values[idx]; + first = -1; + /* Process "npoints" simulation items + * p loop split repeated 2 timed (for x and y points) to preserve cache locality */ + prev_prev_x = prev_x = 0; + last = ofs; + for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) { + if(gr->logx) xx = mylog10(gvx[p]); + else xx = gvx[p]; + if(gr->logy) yy = mylog10(gvy[p]); + else yy = gvy[p]; + wrap = (sweep_idx == 0 && cnt > 1 && XSIGN(xx - prev_x) != XSIGN(prev_x - prev_prev_x)); + if(first != -1) { + if(xx > end || xx < start || wrap) { + dbg(1, "find_closest_wave(): last=%d\n", last); + first = -1; + } + } + if(wrap) { + cnt = 0; + sweepvar_wrap++; + } + if(xx >= start && xx <= end) { + if(first == -1) first = p; + if( XSIGN(xval - xx) != XSIGN(xval - prev_x)) { + + if(min < 0.0) { + min = fabs(yval - yy); + closest_dataset = sweepvar_wrap; + } else { + double tmp = fabs(yval - yy); + if(tmp < min) { + min = tmp; + closest_dataset = sweepvar_wrap; + } + } + dbg(1, "find_closest_wave(): xval=%g yval=%g xx=%g yy=%g sweepvar_wrap=%d ntok=%s\n", + xval, yval, xx, yy, sweepvar_wrap, ntok); + } + last = p; + cnt++; + } /* if(xx >= start && xx <= end) */ + prev_prev_x = prev_x; + prev_x = xx; + } /* for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) */ + /* offset pointing to next dataset */ + ofs += xctx->graph_npoints[dset]; + sweepvar_wrap++; + } /* for(dset...) */ + + } /* if( (idx = get_raw_index(ntok)) != -1 ) */ + wcnt++; + } /* while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) */ + dbg(0, "closest dataset=%d\n", closest_dataset); + if(express) my_free(1487, &express); + my_free(478, &node); + my_free(1262, &sweep); + return closest_dataset; +} /* flags: @@ -2581,9 +2709,9 @@ void draw_graph(int i, const int flags, Graph_ctx *gr) expression = 0; if(xctx->graph_values && !bus_msb) { if(strstr(ntok, ";")) { - my_strdup2(1191, &express, find_nth(ntok, ";", 2)); + my_strdup2(460, &express, find_nth(ntok, ";", 2)); } else { - my_strdup2(1192, &express, ntok); + my_strdup2(473, &express, ntok); } if(strstr(express, " ")) { expression = 1; @@ -2696,11 +2824,11 @@ void draw_graph(int i, const int flags, Graph_ctx *gr) my_free(1403, &point); if(idx_arr) my_free(1455, &idx_arr); - } /* if( (idx = get_raw_index(bus_msb ? bus_msb : ntok)) != -1 ) */ + } /* if( expression || (idx = get_raw_index(bus_msb ? bus_msb : express)) != -1 ) */ wcnt++; if(bus_msb) my_free(1453, &bus_msb); } /* while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) */ - if(express) my_free(1487, &express); + if(express) my_free(1520, &express); my_free(1391, &node); my_free(1392, &color); my_free(1408, &sweep); diff --git a/src/token.c b/src/token.c index cc59b41b..f74faf3e 100644 --- a/src/token.c +++ b/src/token.c @@ -121,7 +121,7 @@ void hash_all_names(int n) for(i=0; iinstances; i++) { has_fmt_attr = get_tok_value((xctx->inst[i].ptr + xctx->sym)->prop_ptr, fmt_attr, 2)[0] ? 1 : 0; if(xctx->inst[i].instname && xctx->inst[i].instname[0]) { - my_strdup(1519, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + my_strdup(1526, &type,(xctx->inst[i].ptr+ xctx->sym)->type); if(!type || !has_fmt_attr || IS_LABEL_SH_OR_PIN(type) ) continue; my_strdup(1254, &upinst, xctx->inst[i].instname); strtoupper(upinst); diff --git a/src/xschem.h b/src/xschem.h index 29c8bfbf..57a1ed38 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1041,6 +1041,7 @@ extern int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx extern int schematic_waves_loaded(void); extern int edit_wave_attributes(int what, int i, Graph_ctx *gr); extern void draw_graph(int i, int flags, Graph_ctx *gr); +extern int find_closest_wave(int i, Graph_ctx *gr); extern void setup_graph_data(int i, const int flags, int skip, Graph_ctx *gr); extern double timer(int start); extern void enable_layers(void);