From d6c197d1089d8197a66730d902fc204024ff6e29 Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Wed, 29 Dec 2021 05:11:39 +0100 Subject: [PATCH] fix BadDrawable regression in free_rawfile(): after deleting data a draw() was called, but since this function is called also in exit handler all windows are already closed. Added digital waveforms and bussed signal display --- XSchemWin/XSchemWix/xschemrc | 2 +- src/actions.c | 4 +- src/callback.c | 129 ++++---- src/draw.c | 547 +++++++++++++++++++++------------ src/scheduler.c | 20 +- src/select.c | 27 ++ src/xinit.c | 14 +- src/xschem.h | 44 ++- src/xschem.tcl | 14 +- xschem_library/rom8k/rom8k.sch | 128 +++----- 10 files changed, 556 insertions(+), 373 deletions(-) diff --git a/XSchemWin/XSchemWix/xschemrc b/XSchemWin/XSchemWix/xschemrc index 51199d09..9e9076a8 100644 --- a/XSchemWin/XSchemWix/xschemrc +++ b/XSchemWin/XSchemWix/xschemrc @@ -277,7 +277,7 @@ set to_pdf {gswin64c -sDEVICE=pdfwrite -o} # set editor { xterm -geometry 100x40 -e pico } #### For Windows -# set editor {notepad.exe} +set editor {notepad.exe} ########################################################################### #### SHOW ERC INFO WINDOW (erc errors, warnings etc) diff --git a/src/actions.c b/src/actions.c index 3800ff7d..d93bd14d 100644 --- a/src/actions.c +++ b/src/actions.c @@ -27,7 +27,7 @@ void here(double i) { - fprintf(stderr, "here %g\n", i); + dbg(0, "here %g\n", i); } /* super simple 32 bit hashing function for files @@ -70,7 +70,7 @@ unsigned int hash_file(const char *f, int skip_path_lines) fclose(fd); return h; } else { - fprintf(stderr, "Can not open file %s\n", f); + dbg(0, "Can not open file %s\n", f); } return 0; } diff --git a/src/callback.c b/src/callback.c index 097736d3..651ab5ea 100644 --- a/src/callback.c +++ b/src/callback.c @@ -35,10 +35,11 @@ static int waves_selected(int state) if(xctx->sel_array[i].type == xRECT && c == GRIDLAYER) { n = xctx->sel_array[i].n; r = &xctx->rect[c][n]; - if( (xctx->ui_state & GRAPHPAN) || POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2) ) { + if(r->flags != 1) return 0; + if( (xctx->ui_state & GRAPHPAN) || + POINTINSIDE(xctx->mousex, xctx->mousey, r->x1, r->y1, r->x2, r->y2) ) { is_inside = 1; } - if(r->flags != 1) return 0; } else return 0; } return is_inside; @@ -213,7 +214,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int if(val[0]) wx2 = atof(val); val = get_tok_value(r->prop_ptr,"y2",0); if(val[0]) wy2 = atof(val); - calc_graph_area(GRIDLAYER, n, &x1, &y1, &x2, &y2, &marginx, &marginy); + val = get_tok_value(r->prop_ptr,"digital",0); + if(val[0]) digital = atof(val); + calc_graph_area(GRIDLAYER, n, digital, &x1, &y1, &x2, &y2, &marginx, &marginy); cx = (x2 - x1) / (wx2 - wx1); dx = x1 - wx1 * cx; cy = (y1 - y2) / (wy2 - wy1); @@ -229,23 +232,24 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int xctx->graph_bottom = 0; } xctx->graph_master = n; + if(state & ControlMask) xctx->graph_flags |= 1; + else xctx->graph_flags &= ~1; break; } } } } - - /* lock x-axis to working graph when movint/zooming multiple graphs */ + /* lock x-axis to working graph when moving/zooming multiple graphs */ val = get_tok_value(xctx->rect[GRIDLAYER][xctx->graph_master].prop_ptr,"x1",0); if(val[0]) wx1 = atof(val); val = get_tok_value(xctx->rect[GRIDLAYER][xctx->graph_master].prop_ptr,"x2",0); if(val[0]) wx2 = atof(val); - for(i=0; ilastsel; i++) { - c = xctx->sel_array[i].col; + for(i=0; i< ((xctx->graph_flags & 1) ? xctx->rects[GRIDLAYER] : xctx->lastsel); i++) { + c = (xctx->graph_flags & 1) ? GRIDLAYER : xctx->sel_array[i].col; /* process only graph boxes */ - if(xctx->sel_array[i].type == xRECT && c == GRIDLAYER) { + if( (xctx->graph_flags & 1) || (xctx->sel_array[i].type == xRECT && c == GRIDLAYER) ) { xRect *r; - n = xctx->sel_array[i].n; + n = (xctx->graph_flags & 1) ? i : xctx->sel_array[i].n; r = &xctx->rect[GRIDLAYER][n]; if(r->flags != 1) continue; val = get_tok_value(r->prop_ptr,"divx",0); @@ -258,10 +262,10 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int if(val[0]) wy2 = atof(val); val = get_tok_value(r->prop_ptr,"dataset",0); if(val[0]) dataset = atoi(val); - if(dataset >= xctx->datasets) dataset = xctx->datasets - 1; + if(dataset >= xctx->graph_datasets) dataset = xctx->graph_datasets - 1; val = get_tok_value(r->prop_ptr,"digital",0); if(val[0]) digital = atof(val); - calc_graph_area(GRIDLAYER, n, &x1, &y1, &x2, &y2, &marginx, &marginy); + calc_graph_area(GRIDLAYER, n, digital, &x1, &y1, &x2, &y2, &marginx, &marginy); /* cache coefficients for faster graph coord transformations */ cx = (x2 - x1) / (wx2 - wx1); dx = x1 - wx1 * cx; @@ -271,9 +275,9 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom) { double delta; if(xctx->graph_left) { - if(!digital && n == xctx->graph_master) { + if(n == xctx->graph_master) { delta = (wy2 - wy1) / divy; - delta_threshold = 0.05; + delta_threshold = 0.01; if(fabs(xctx->my_double_save - xctx->mousey_snap) > fabs(cy * delta) * delta_threshold) { yy1 = wy1 + (xctx->my_double_save - xctx->mousey_snap) / cy; yy2 = wy2 + (xctx->my_double_save - xctx->mousey_snap) / cy; @@ -281,6 +285,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int my_strdup(1424, &r->prop_ptr, subst_token(r->prop_ptr, "y1", s)); my_snprintf(s, S(s), "%g", yy2); my_strdup(1425, &r->prop_ptr, subst_token(r->prop_ptr, "y2", s)); + xctx->my_double_save = xctx->mousey_snap; need_redraw = 1; } } @@ -294,15 +299,16 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int my_strdup(1410, &r->prop_ptr, subst_token(r->prop_ptr, "x1", s)); my_snprintf(s, S(s), "%g", xx2); my_strdup(1411, &r->prop_ptr, subst_token(r->prop_ptr, "x2", s)); + /* update saved mouse position after processing all graphs */ + if(i >= ((xctx->graph_flags & 1) ? xctx->rects[GRIDLAYER] : xctx->lastsel) - 1) { + xctx->mx_double_save = xctx->mousex_snap; + xctx->my_double_save = xctx->mousey_snap; + } need_redraw = 1; } } - if(i >= xctx->lastsel -1) { /* update saved mouse position after processing all graphs */ - xctx->mx_double_save = xctx->mousex_snap; - xctx->my_double_save = xctx->mousey_snap; - } } - else if((button == Button5 && state == 0)) { + else if((button == Button5 && !(state & ShiftMask))) { double delta; if(xctx->graph_left) { if(!digital && n == xctx->graph_master) { @@ -328,7 +334,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - else if(key == XK_Left) { double delta; if(xctx->graph_left) { @@ -337,7 +342,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wy1; double b = wy2 -m; double delta = (wy2 - wy1); - double var = delta * 0.1; + double var = delta * 0.2; yy2 = wy2 + var * b / delta; yy1 = wy1 - var * a / delta; my_snprintf(s, S(s), "%g", yy1); @@ -358,8 +363,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - - else if(button == Button4 && state == 0) { + else if(button == Button4 && !(state & ShiftMask)) { double delta; if(xctx->graph_left) { if(!digital && n == xctx->graph_master) { @@ -385,7 +389,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - else if(key == XK_Right) { double delta; if(xctx->graph_left) { @@ -394,7 +397,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wy1; double b = wy2 -m; double delta = (wy2 - wy1); - double var = delta * 0.1; + double var = delta * 0.2; yy2 = wy2 - var * b / delta; yy1 = wy1 + var * a / delta; my_snprintf(s, S(s), "%g", yy1); @@ -415,14 +418,14 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - else if(button == Button5 && state == ShiftMask) { + else if(button == Button5 && (state & ShiftMask)) { if(xctx->graph_left) { if(!digital && n == xctx->graph_master) { double m = G_Y(xctx->mousey); double a = m - wy1; double b = wy2 -m; double delta = (wy2 - wy1); - double var = delta * 0.1; + double var = delta * 0.2; yy2 = wy2 + var * b / delta; yy1 = wy1 - var * a / delta; my_snprintf(s, S(s), "%g", yy1); @@ -436,7 +439,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wx1; double b = wx2 -m; double delta = (wx2 - wx1); - double var = delta * 0.1; + double var = delta * 0.2; xx2 = wx2 + var * b / delta; xx1 = wx1 - var * a / delta; my_snprintf(s, S(s), "%g", xx1); @@ -446,7 +449,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - else if(key == XK_Down) { double delta; if(xctx->graph_left) { @@ -466,7 +468,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wx1; double b = wx2 -m; double delta = (wx2 - wx1); - double var = delta * 0.1; + double var = delta * 0.2; xx2 = wx2 + var * b / delta; xx1 = wx1 - var * a / delta; my_snprintf(s, S(s), "%g", xx1); @@ -476,14 +478,14 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw = 1; } } - else if(button == Button4 && state == ShiftMask) { + else if(button == Button4 && (state & ShiftMask)) { if(xctx->graph_left) { if(!digital && n == xctx->graph_master) { double m = G_Y(xctx->mousey); double a = m - wy1; double b = wy2 -m; double delta = (wy2 - wy1); - double var = delta * 0.1; + double var = delta * 0.2; yy2 = wy2 - var * b / delta; yy1 = wy1 + var * a / delta; my_snprintf(s, S(s), "%g", yy1); @@ -497,7 +499,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wx1; double b = wx2 -m; double delta = (wx2 - wx1); - double var = delta * 0.1; + double var = delta * 0.2; xx2 = wx2 - var * b / delta; xx1 = wx1 + var * a / delta; my_snprintf(s, S(s), "%g", xx1); @@ -527,7 +529,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int double a = m - wx1; double b = wx2 -m; double delta = (wx2 - wx1); - double var = delta * 0.1; + double var = delta * 0.2; xx2 = wx2 - var * b / delta; xx1 = wx1 + var * a / delta; my_snprintf(s, S(s), "%g", xx1); @@ -538,40 +540,38 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int } } else if(key == 'f') { - if(xctx->values) { + if(xctx->graph_values) { if(xctx->graph_left) { - if(!digital) { - int i, j; - double v; - double min=0.0, max=0.0; - int first = 1; - char *saven, *nptr, *ntok, *node = NULL;; - my_strdup2(1426, &node, get_tok_value(r->prop_ptr,"node",0)); - nptr = node; - while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) { - nptr = NULL; - j = get_raw_index(ntok); - if(j >= 0) { - for(i = 0; i < xctx->npoints[dataset]; i++) { - v = get_raw_value(dataset, j, i); - if(first || v < min) {min = v; first = 0;} - if(first || v > max) {max = v; first = 0;} - } - } + int i, j; + double v; + double min=0.0, max=0.0; + int first = 1; + char *saven, *nptr, *ntok, *node = NULL;; + my_strdup2(1426, &node, get_tok_value(r->prop_ptr,"node",0)); + nptr = node; + while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) { + nptr = NULL; + j = get_raw_index(ntok); + if(j >= 0) { + for(i = 0; i < xctx->graph_npoints[dataset]; i++) { + v = get_raw_value(dataset, j, i); + if(first || v < min) {min = v; first = 0;} + if(first || v > max) {max = v; first = 0;} + } } - if(max == min) max += 0.01; - min = floor_to_n_digits(min, 2); - max = ceil_to_n_digits(max, 2); - my_free(1427, &node); - my_snprintf(s, S(s), "%g", min); - my_strdup(1422, &r->prop_ptr, subst_token(r->prop_ptr, "y1", s)); - my_snprintf(s, S(s), "%g", max); - my_strdup(1423, &r->prop_ptr, subst_token(r->prop_ptr, "y2", s)); - need_redraw = 1; } + if(max == min) max += 0.01; + min = floor_to_n_digits(min, 2); + max = ceil_to_n_digits(max, 2); + my_free(1427, &node); + my_snprintf(s, S(s), "%g", min); + my_strdup(1422, &r->prop_ptr, subst_token(r->prop_ptr, "y1", s)); + my_snprintf(s, S(s), "%g", max); + my_strdup(1423, &r->prop_ptr, subst_token(r->prop_ptr, "y2", s)); + need_redraw = 1; } else { xx1 = get_raw_value(dataset, 0, 0); - xx2 = get_raw_value(dataset, 0, xctx->npoints[dataset] -1); + xx2 = get_raw_value(dataset, 0, xctx->graph_npoints[dataset] -1); my_snprintf(s, S(s), "%g", xx1); my_strdup(1409, &r->prop_ptr, subst_token(r->prop_ptr, "x1", s)); my_snprintf(s, S(s), "%g", xx2); @@ -583,10 +583,10 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int else if( event == MotionNotify && (state & Button1Mask) && xctx->graph_bottom ) { double wwx1, wwx2, p, delta, ccx, ddx; - if(xctx->values) { + if(xctx->graph_values) { delta = wx2 - wx1; wwx1 = get_raw_value(dataset, 0, 0); - wwx2 = get_raw_value(dataset, 0, xctx->npoints[dataset] - 1); + wwx2 = get_raw_value(dataset, 0, xctx->graph_npoints[dataset] - 1); ccx = (x2 - x1) / (wwx2 - wwx1); ddx = x1 - wwx1 * ccx; p = (xctx->mousex_snap - ddx) / ccx; @@ -623,7 +623,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int cairo_restore(xctx->cairo_ctx); cairo_restore(xctx->cairo_save_ctx); #endif - return 0; } diff --git a/src/draw.c b/src/draw.c index 39756620..1bca92ab 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1491,26 +1491,26 @@ void read_binary_block(FILE *fd) int offset = 0; - for(p = 0 ; p < xctx->datasets; p++) { - size += xctx->nvars * xctx->npoints[p]; - offset += xctx->npoints[p]; + for(p = 0 ; p < xctx->graph_datasets; p++) { + size += xctx->graph_nvars * xctx->graph_npoints[p]; + offset += xctx->graph_npoints[p]; } /* read buffer */ - tmp = my_calloc(1405, xctx->nvars, sizeof(double *)); + tmp = my_calloc(1405, xctx->graph_nvars, sizeof(double *)); /* allocate storage for binary block */ - if(!xctx->values) xctx->values = my_calloc(118, xctx->nvars, sizeof(SPICE_DATA *)); - for(p = 0 ; p < xctx->nvars; p++) { - my_realloc(372, &xctx->values[p], (size + xctx->npoints[xctx->datasets]) * sizeof(double)); + if(!xctx->graph_values) xctx->graph_values = my_calloc(118, xctx->graph_nvars, sizeof(SPICE_DATA *)); + for(p = 0 ; p < xctx->graph_nvars; p++) { + my_realloc(372, &xctx->graph_values[p], (size + xctx->graph_npoints[xctx->graph_datasets]) * sizeof(double)); } /* read binary block */ - for(p = 0; p < xctx->npoints[xctx->datasets]; p++) { - if(fread(tmp, sizeof(double), xctx->nvars, fd) != xctx->nvars) { + for(p = 0; p < xctx->graph_npoints[xctx->graph_datasets]; p++) { + if(fread(tmp, sizeof(double), xctx->graph_nvars, fd) != xctx->graph_nvars) { dbg(0, "Warning: binary block is not of correct size\n"); } /* assign to xschem struct, memory aligned per variable, for cache locality */ - for(v = 0; v < xctx->nvars; v++) { - xctx->values[v][offset + p] = tmp[v]; + for(v = 0; v < xctx->graph_nvars; v++) { + xctx->graph_values[v][offset + p] = tmp[v]; } } my_free(1406, &tmp); @@ -1550,16 +1550,16 @@ int read_dataset(FILE *fd) while((ptr = fgets(line, sizeof(line), fd)) ) { /* after this line comes the binary blob made of nvars * npoints * sizeof(double) bytes */ if(!strcmp(line, "Binary:\n")) { - int npoints = xctx->npoints[xctx->datasets]; + int npoints = xctx->graph_npoints[xctx->graph_datasets]; if(sim_type) { done_header = 1; read_binary_block(fd); - dbg(1, "read_dataset(): read binary block, nvars=%d npoints=%d\n", xctx->nvars, npoints); - xctx->datasets++; + dbg(1, "read_dataset(): read binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints); + xctx->graph_datasets++; exit_status = 1; } else { - dbg(1, "read_dataset(): skip binary block, nvars=%d npoints=%d\n", xctx->nvars, npoints); - fseek(fd, xctx->nvars * npoints * sizeof(double), SEEK_CUR); /* skip binary block */ + dbg(1, "read_dataset(): skip binary block, nvars=%d npoints=%d\n", xctx->graph_nvars, npoints); + fseek(fd, xctx->graph_nvars * npoints * sizeof(double), SEEK_CUR); /* skip binary block */ } done_points = 0; } @@ -1575,26 +1575,26 @@ int read_dataset(FILE *fd) * to skip binary blobs */ else if(!strncmp(line, "No. of Data Rows :", 18)) { /* array of number of points of datasets (they are of varialbe length) */ - my_realloc(1414, &xctx->npoints, (xctx->datasets+1) * sizeof(int)); - sscanf(line, "No. of Data Rows : %d", &xctx->npoints[xctx->datasets]); + my_realloc(1414, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int)); + sscanf(line, "No. of Data Rows : %d", &xctx->graph_npoints[xctx->graph_datasets]); done_points = 1; } else if(!strncmp(line, "No. Variables:", 14)) { - sscanf(line, "No. Variables: %d", &xctx->nvars); + sscanf(line, "No. Variables: %d", &xctx->graph_nvars); } else if(!done_points && !strncmp(line, "No. Points:", 11)) { - my_realloc(1415, &xctx->npoints, (xctx->datasets+1) * sizeof(int)); - sscanf(line, "No. Points: %d", &xctx->npoints[xctx->datasets]); + my_realloc(1415, &xctx->graph_npoints, (xctx->graph_datasets+1) * sizeof(int)); + sscanf(line, "No. Points: %d", &xctx->graph_npoints[xctx->graph_datasets]); } if(!done_header && variables) { /* get the list of lines with index and node name */ - if(!xctx->names) xctx->names = my_calloc(426, xctx->nvars, sizeof(char *)); + if(!xctx->graph_names) xctx->graph_names = my_calloc(426, xctx->graph_nvars, sizeof(char *)); sscanf(line, "%d %s", &i, varname); /* read index and name of saved waveform */ - xctx->names[i] = my_malloc(415, strlen(varname) + 1); - strcpy(xctx->names[i], varname); + xctx->graph_names[i] = my_malloc(415, strlen(varname) + 1); + strcpy(xctx->graph_names[i], varname); /* use hash table to store index number of variables */ - int_hash_lookup(xctx->raw_table, xctx->names[i], i, XINSERT_NOREPLACE); - dbg(1, "read_dataset(): get node list -> names[%d] = %s\n", i, xctx->names[i]); + int_hash_lookup(xctx->raw_table, xctx->graph_names[i], i, XINSERT_NOREPLACE); + dbg(1, "read_dataset(): get node list -> names[%d] = %s\n", i, xctx->graph_names[i]); } /* after this line comes the list of indexes and associated nodes */ if(sim_type && !strncmp(line, "Variables:", 10)) { @@ -1602,32 +1602,35 @@ int read_dataset(FILE *fd) } } dbg(1, "read_dataset(): datasets=%d, last npoints=%d, nvars=%d\n", - xctx->datasets, xctx->npoints[xctx->datasets-1], xctx->nvars); + xctx->graph_datasets, xctx->graph_npoints[xctx->graph_datasets-1], xctx->graph_nvars); return exit_status; } -void free_rawfile(void) +void free_rawfile(int dr) { int i; - if(xctx->names) { - for(i = 0 ; i < xctx->nvars; i++) { - my_free(510, &xctx->names[i]); + int deleted = 0; + if(xctx->graph_names) { + deleted = 1; + for(i = 0 ; i < xctx->graph_nvars; i++) { + my_free(510, &xctx->graph_names[i]); } - my_free(968, &xctx->names); + my_free(968, &xctx->graph_names); } - if(xctx->values) { - for(i = 0 ; i < xctx->nvars; i++) { - my_free(512, &xctx->values[i]); + if(xctx->graph_values) { + deleted = 1; + for(i = 0 ; i < xctx->graph_nvars; i++) { + my_free(512, &xctx->graph_values[i]); } - my_free(528, &xctx->values); + my_free(528, &xctx->graph_values); } - if(xctx->npoints) my_free(1413, &xctx->npoints); + if(xctx->graph_npoints) my_free(1413, &xctx->graph_npoints); if(xctx->raw_schname) my_free(1393, &xctx->raw_schname); - xctx->datasets = 0; - xctx->nvars = 0; + xctx->graph_datasets = 0; + xctx->graph_nvars = 0; int_hash_free(xctx->raw_table); - draw(); + if(deleted && dr) draw(); } /* read a ngspice raw file (with data portion in binary format) */ @@ -1635,7 +1638,7 @@ int read_rawfile(const char *f) { int res = 0; FILE *fd; - if(xctx->values || xctx->npoints || xctx->nvars || xctx->datasets) { + if(xctx->graph_values || xctx->graph_npoints || xctx->graph_nvars || xctx->graph_datasets) { dbg(0, "read_rawfile(): must clear current raw file before loading new\n"); return 0; } @@ -1658,7 +1661,7 @@ int read_rawfile(const char *f) int get_raw_index(const char *node) { Int_hashentry *entry; - if(xctx->values) { + if(xctx->graph_values) { entry = int_hash_lookup(xctx->raw_table, node, 0, XLOOKUP); if(entry) return entry->value; } @@ -1669,15 +1672,15 @@ double get_raw_value(int dataset, int idx, int point) { int i, ofs; ofs = 0; - if(xctx->values) { + if(xctx->graph_values) { for(i = 0; i < dataset; i++) { - ofs += xctx->npoints[i]; + ofs += xctx->graph_npoints[i]; } - return xctx->values[idx][ofs + point]; + return xctx->graph_values[idx][ofs + point]; } return 0.0; } -void calc_graph_area(int c, int i, double *x1, double *y1,double *x2,double *y2, +void calc_graph_area(int c, int i, int digital, double *x1, double *y1,double *x2,double *y2, double *marginx, double *marginy) { double rx1, rx2, ry1, ry2, rw, rh, tmp; @@ -1688,18 +1691,18 @@ void calc_graph_area(int c, int i, double *x1, double *y1,double *x2,double *y2, rw = (rx2 - rx1); rh = (ry2 - ry1); /* set margins */ - tmp = rw * 0.05; - *marginx = tmp < 80 ? 80 : tmp; - tmp = rh * 0.1; - *marginy = tmp < 20 ? 20 : tmp; + tmp = rw * 0.1; + *marginx = tmp < 30 ? 30 : tmp; + tmp = rh * 0.15; + *marginy = tmp < 15 ? 15 : tmp; /* calculate graph bounding box (container - margin) * This is the box where plot is done */ - *x1 = rx1 + *marginx + 40; - *x2 = rx2 - *marginx/1.8; - *y1 = ry1 + *marginy; - tmp = *marginy < 30 ? 30 : *marginy; - *y2 = ry2 - tmp; /* some more space to accomodate x-axis label */ + *x1 = rx1 + *marginx; + *x2 = rx2 - *marginx / 2.4; /* less space for right margin */ + if(digital) *y1 = ry1 + *marginy * 0.4; + else *y1 = ry1 + *marginy; + *y2 = ry2 - *marginy; } /* round to closest 1e-ee. 2e-ee, 5e-ee @@ -1735,7 +1738,7 @@ static double axis_increment(double a, double b, int div) return scaled_delta * scale * sign; } -double axis_start(double n, double delta, int div) +static double axis_start(double n, double delta, int div) { if(delta == 0.0) return n; /* if user wants only one division, just do what user asks */ @@ -1744,14 +1747,14 @@ double axis_start(double n, double delta, int div) return ceil(n / delta) * delta; } -int axis_end(double x, double delta, double b) +static int axis_end(double x, double delta, double b) { if(delta == 0.0) return 1; /* guard against infinite loops */ if(delta > 0) return x > b + delta / 100000.0; return x < b + delta / 100000.0; } -int axis_within_range(double x, double a, double b) +static int axis_within_range(double x, double a, double b) { if(a < b) return x >= a; return x <= a; @@ -1773,7 +1776,7 @@ static double get_unit(const char *val) int schematic_waves_loaded(void) { int i; - if(xctx->values && xctx->raw_schname) { + if(xctx->graph_values && xctx->raw_schname) { for(i = xctx->currsch; i >= 0; i--) { if( !strcmp(xctx->raw_schname, xctx->sch[i]) ) return 1; } @@ -1787,112 +1790,150 @@ int schematic_waves_loaded(void) #define W_X(x) (cx * (x) + dx) #define W_Y(y) (cy * (y) + dy) -static void get_y_points(int v, int first, int last, double cy, double dy, double *yarr, - int digital, int wcnt, int n_nodes, double ydelta) +/* draw bussed signals: ntok is a comma separated list of items, first item is bus name, + * following are bits that are bundled together: + LDA,LDA[3],LDA[2],LDA1],LDA[0] + */ +static void draw_graph_bus_points(const char *ntok, int first, int last, + double cx, double dx, double cy, double dy, + int wave_col, int sweep_idx, + int digital, int dig_max_waves, int wcnt, int n_nodes, double wy1, double wy2) +{ + int p, i; + int n = dig_max_waves; + double s1 = 1.0 / n; + double s2 = s1 * .66; + double c = (wy2 - wy1) * wcnt * s1; + double x1 = W_X(xctx->graph_values[sweep_idx][first]); + double x2 = W_X(xctx->graph_values[sweep_idx][last-1]); + double ylow = W_Y(c + wy2 * s2); /* swapped as xschem Y coordinates are top-bottom */ + double yhigh = W_Y(c + wy1 * s2); + const char *bit_name; + int n_bits = count_items(ntok, ",") - 1; + int *idx_arr = NULL; + Int_hashentry *entry; + unsigned long val, busval, old_busval; + double vth = (wy1 + wy2) / 2.0; /* A to D threshold */ + double xval, xval_old; + double ydelta = fabs(yhigh - ylow); + double labsize = 0.015 * ydelta; + double charwidth = labsize * 38.0; + char str[100]; + int hex_digits = (n_bits - 1) / 4 + 1; + + idx_arr = my_malloc(1454, (n_bits) * sizeof(int)); + p = 0; + dbg(1, "n_bits = %d\n", n_bits); + while( (bit_name = find_nth(ntok, ',', p + 2))[0] ) { + dbg(1, "draw_graph_bus_points(): bit %d : %s: ", p, bit_name); + entry = int_hash_lookup(xctx->raw_table, bit_name, 0, XLOOKUP); + if(entry) { + dbg(1, "%d\n", entry->value); + idx_arr[p] = entry->value; + } else { + dbg(1, "\n"); + } + p++; + } + drawline(wave_col, NOW, x1, ylow, x2, ylow, 0); + drawline(wave_col, NOW, x1, yhigh, x2, yhigh, 0); + for(p = first ; p < last; p++) { + /* calculate value of bus by adding all binary bits */ + busval = 0; + for(i = 0; i < n_bits; i++) { + val = xctx->graph_values[idx_arr[i]][p]; + busval = (busval << 1) + (val > vth); + } + + xval = W_X(xctx->graph_values[sweep_idx][p]); + + /* used to draw bus value before 1st transition */ + if(p == first) { + old_busval = busval; + xval_old = xval; + } + if(p > first && busval != old_busval) { + /* draw transition ('X') */ + drawline(BACKLAYER, NOW, xval-1, yhigh, xval+1, yhigh, 0); + drawline(BACKLAYER, NOW, xval-1, ylow, xval+1, ylow, 0); + drawline(wave_col, NOW, xval-1, ylow, xval+1, yhigh, 0); + drawline(wave_col, NOW, xval-1, yhigh, xval+1, ylow, 0); + /* build hex string for bus value */ + sprintf(str, "%0*lX", hex_digits, old_busval); + /* draw hex bus value if there is enough room */ + if( fabs(xval - xval_old) > strlen(str) * charwidth) { + draw_string(wave_col, NOW, str, 2, 0, 1, 0, (xval + xval_old) / 2.0, + yhigh, labsize, labsize); + + } + old_busval = busval; + xval_old = xval; + } /* if(p > first && busval != old_busval) */ + } /* for(p = first ; p < last; p++) */ + /* draw hex bus value after last transition */ + sprintf(str, "%0*lX", hex_digits, busval); + if( fabs(xval - xval_old) > strlen(str) * charwidth) { + draw_string(wave_col, NOW, str, 2, 0, 1, 0, (xval + xval_old) / 2.0, + yhigh, labsize, labsize); + } + my_free(1455, &idx_arr); +} + +static void draw_graph_points(int v, int first, int last, double cy, double dy, + double *xarr, double *yarr, int wave_col, + int digital, int dig_max_waves, int wcnt, int n_nodes, double wy1, double wy2) { int p; double yy; + double ydelta = wy2 - wy1; int poly_npoints = 0; - double s1 = 1.0 / n_nodes; + int n = dig_max_waves; + double s1 = 1.0 / n; double s2 = s1 * .66; - for(p = first ; p < last; p++) { - yy = xctx->values[v][p]; - if(digital) { - yy = ydelta * wcnt * s1 + yy *s2; + double c = ydelta * wcnt * s1; + + if( !digital || (c >= wy1 && c <= wy2) ) { + for(p = first ; p < last; p++) { + yy = xctx->graph_values[v][p]; + if(digital) { + yy = c + yy *s2; + } + /* Build poly y array. Translate from graph coordinates to {x1,y1} - {x2, y2} world. */ + yarr[poly_npoints] = W_Y(yy); + poly_npoints++; } - /* Build poly y array. Translate from graph coordinates to {x1,y1} - {x2, y2} world. */ - yarr[poly_npoints] = W_Y(yy); - poly_npoints++; - } + /* plot data */ + drawpolygon(wave_col, 0, xarr, yarr, poly_npoints, 0, 0); + } else dbg(1, "skipping wave: %s\n", xctx->graph_names[v]); } -void draw_graph(int c, int i, int flags) +static void draw_graph_grid( + double rx1, double ry1, double rx2, double ry2, /* container box */ + double x1, double y1, double x2, double y2, /* graph area */ + double marginx, double marginy, + double wx1, double wy1, double wx2, double wy2, /* graph coordinate system */ + double cx, double cy, double dx, double dy, /* graph to xschem matrix transform */ + int divx, int divy, int subdivx, int subdivy, /* axis major/minor grids */ + double unitx, double unity, /* unit conversion (p, u, m, k, M, G) */ + int digital) /* set to 1 for digital plot */ { - /* container box */ - double rx1, ry1, rx2, ry2, rw/*, rh */; - /* graph box (smaller due to margins) */ - double x1, y1, x2, y2, w, h; - /* graph coordinate, some defaults */ - double digital = 0; - double wx1 = -2e-6; - double wy1 = -1; - double wx2 = 8e-6; - double wy2 = 4; - double marginx = 20; /* will be recalculated later */ - double marginy = 20; /* will be recalculated later */ - double wx, wy; /* point coordinates in graph */ - /* coefficients for graph to container coordinate transformations W_X() and W_Y()*/ - double cx, dx, cy, dy; - double dash_sizex, dash_sizey; - int divx = 10; - int divy = 5; - int subdivx = 0; - int subdivy = 0; - double unitx = 1.0; - double unity = 1.0; - int unitx_suffix = ' '; /* 'n' or 'u' or 'M' or 'k' ... */ - int unity_suffix = ' '; - /* label start and increments calculated in order to give 'nice' numbers */ - double deltax, deltay; - double startx, starty; - int j, k, wave_color = 5; + double deltax, startx, deltay, starty, wx,wy, dash_sizex, dash_sizey, w, h; + int j, k; char lab[30]; - const char *val; - char *node = NULL, *color = NULL, *sweep = NULL; - double txtsizelab, txtsizey, txtsizex, tmp; - Int_hashentry *entry; - int sweep_idx = 0; - int n_nodes; /* number of variables to display in a single graph */ - xRect *r = &xctx->rect[c][i]; - char tmpstr[200]; - char *saven, *savec, *saves, *nptr, *cptr, *sptr, *ntok, *ctok, *stok; - int wcnt = 0; - int dataset = -1; - /* container (embedding rectangle) coordinates */ - rx1 = r->x1; - ry1 = r->y1; - rx2 = r->x2; - ry2 = r->y2; - rw = (rx2 - rx1); - /* rh = (ry2 -ry1); */ - /* get variables to plot, x/y range, grid info etc */ - val = get_tok_value(r->prop_ptr,"unitx",0); - unitx_suffix = val[0]; - unitx = get_unit(val);; - val = get_tok_value(r->prop_ptr,"unity",0); - unity_suffix = val[0]; - unity = get_unit(val);; - val = get_tok_value(r->prop_ptr,"subdivx",0); - if(val[0]) subdivx = atoi(val); - val = get_tok_value(r->prop_ptr,"subdivy",0); - if(val[0]) subdivy = atoi(val); - val = get_tok_value(r->prop_ptr,"divx",0); - if(val[0]) divx = atoi(val); - val = get_tok_value(r->prop_ptr,"divy",0); - if(val[0]) divy = atoi(val); - val = get_tok_value(r->prop_ptr,"x1",0); - if(val[0]) wx1 = atof(val); - val = get_tok_value(r->prop_ptr,"y1",0); - if(val[0]) wy1 = atof(val); - val = get_tok_value(r->prop_ptr,"x2",0); - if(val[0]) wx2 = atof(val); - val = get_tok_value(r->prop_ptr,"y2",0); - if(val[0]) wy2 = atof(val); - val = get_tok_value(r->prop_ptr,"digital",0); - if(val[0]) digital = atoi(val); - /* plot single dataset */ - val = get_tok_value(r->prop_ptr,"dataset",0); - if(val[0]) dataset = atoi(val); - if(dataset >= xctx->datasets) dataset = xctx->datasets - 1; - /* set margins */ - calc_graph_area(c, i, &x1, &y1, &x2, &y2, &marginx, &marginy); + double tmp, txtsizex, txtsizey; + w = (x2 - x1); h = (y2 - y1); - /* cache coefficients for faster graph coord transformations */ - cx = (x2 - x1) / (wx2 - wx1); - dx = x1 - wx1 * cx; - cy = (y1 - y2) / (wy2 - wy1); - dy = y2 - wy1 * cy; + /* x axis, y axis label text sizes */ + txtsizey = h / divy * 0.009; + tmp = marginx * 0.005; + if(tmp < txtsizey) txtsizey = tmp; + tmp = marginy * 0.02; + if(tmp < txtsizey) txtsizey = tmp; + + txtsizex = w / divx * 0.0033; + tmp = marginy * 0.0083; + if(tmp < txtsizex) txtsizex = tmp; /* calculate dash length for grid lines */ dash_sizex = 1.5 * xctx->mooz; @@ -1902,22 +1943,10 @@ void draw_graph(int c, int i, int flags) dash_sizey = dash_sizey > 2.0 ? 2.0 : dash_sizey; if(dash_sizey <= 1.0) dash_sizey = 1.0; - /* x axis, y axis, label text sizes */ - txtsizey = h / divy / 90 ; - tmp = marginx / 200; - if(tmp < txtsizey) txtsizey = tmp; - - txtsizex = w / divx / 300; - tmp = marginy / 110; - if(tmp < txtsizex) txtsizex = tmp; - - txtsizelab = marginy / 110; - if(digital) txtsizelab /= 1.3; - /* background */ filledrect(0, NOW, rx1, ry1, rx2, ry2); /* graph bounding box */ - drawrect(c, NOW, rx1, ry1, rx2, ry2, 2); + drawrect(GRIDLAYER, NOW, rx1, ry1, rx2, ry2, 2); /* vertical grid lines */ deltax = axis_increment(wx1, wx2, divx); @@ -1960,18 +1989,117 @@ void draw_graph(int c, int i, int flags) drawline(GRIDLAYER, ADD, W_X(wx1)-4, W_Y(wy), W_X(wx1), W_Y(wy), 0); /* axis marks */ /* Y-axis labels */ my_snprintf(lab, S(lab), "%g", wy * unity); - draw_string(3, NOW, lab, 0, 1, 0, 1, x1 - 2 - 30 * txtsizey, W_Y(wy), txtsizey, txtsizey); + draw_string(3, NOW, lab, 0, 1, 0, 1, x1 - 4 - 30 * txtsizey, W_Y(wy), txtsizey, txtsizey); } } /* first and last horizontal box delimiters */ drawline(GRIDLAYER, ADD, W_X(wx1), W_Y(wy1), W_X(wx2), W_Y(wy1), 0); drawline(GRIDLAYER, ADD, W_X(wx1), W_Y(wy2), W_X(wx2), W_Y(wy2), 0); /* Horizontal axis (if in viewport) */ - if(wy1 <= 0 && wy2 >= 0) drawline(GRIDLAYER, ADD, W_X(wx1), W_Y(0), W_X(wx2), W_Y(0), 0); + if(!digital && wy1 <= 0 && wy2 >= 0) drawline(GRIDLAYER, ADD, W_X(wx1), W_Y(0), W_X(wx2), W_Y(0), 0); /* Vertical axis (if in viewport) * swap order of wy1 and wy2 since grap y orientation is opposite to xorg orientation */ if(wx1 <= 0 && wx2 >= 0) drawline(GRIDLAYER, ADD, W_X(0), W_Y(wy2), W_X(0), W_Y(wy1), 0); drawline(GRIDLAYER, END, 0.0, 0.0, 0.0, 0.0, 0); +} + +void draw_graph(int c, int i, int flags) +{ + /* container box */ + double rx1, ry1, rx2, ry2, rw/*, rh */; + /* graph box (smaller due to margins) */ + double x1, y1, x2, y2; + /* graph coordinate, some defaults */ + int digital = 0; + int dig_max_waves = 10; /* max waves that can be stacked, then vertical pan can be used to view more */ + double wx1 = -2e-6; + double wy1 = -1; + double wx2 = 8e-6; + double wy2 = 4; + double marginx = 20; /* will be recalculated later */ + double marginy = 20; /* will be recalculated later */ + /* coefficients for graph to container coordinate transformations W_X() and W_Y()*/ + double cx, dx, cy, dy; + int divx = 10; + int divy = 5; + int subdivx = 0; + int subdivy = 0; + double unitx = 1.0; + double unity = 1.0; + int unitx_suffix = ' '; /* 'n' or 'u' or 'M' or 'k' ... */ + int unity_suffix = ' '; + int wave_color = 5; + const char *val; + char *node = NULL, *color = NULL, *sweep = NULL; + double txtsizelab, digtxtsizelab, tmp; + Int_hashentry *entry; + int sweep_idx = 0; + int n_nodes; /* number of variables to display in a single graph */ + xRect *r = &xctx->rect[c][i]; + char tmpstr[200]; + char *saven, *savec, *saves, *nptr, *cptr, *sptr; + const char *ntok, *ctok, *stok; + char *bus_msb = NULL; + int wcnt = 0; + int dataset = -1; + /* container (embedding rectangle) coordinates */ + rx1 = r->x1; + ry1 = r->y1; + rx2 = r->x2; + ry2 = r->y2; + rw = (rx2 - rx1); + /* rh = (ry2 -ry1); */ + /* get variables to plot, x/y range, grid info etc */ + val = get_tok_value(r->prop_ptr,"unitx",0); + unitx_suffix = val[0]; + unitx = get_unit(val);; + val = get_tok_value(r->prop_ptr,"unity",0); + unity_suffix = val[0]; + unity = get_unit(val);; + val = get_tok_value(r->prop_ptr,"subdivx",0); + if(val[0]) subdivx = atoi(val); + val = get_tok_value(r->prop_ptr,"subdivy",0); + if(val[0]) subdivy = atoi(val); + val = get_tok_value(r->prop_ptr,"divx",0); + if(val[0]) divx = atoi(val); + val = get_tok_value(r->prop_ptr,"divy",0); + if(val[0]) divy = atoi(val); + val = get_tok_value(r->prop_ptr,"x1",0); + if(val[0]) wx1 = atof(val); + val = get_tok_value(r->prop_ptr,"y1",0); + if(val[0]) wy1 = atof(val); + val = get_tok_value(r->prop_ptr,"x2",0); + if(val[0]) wx2 = atof(val); + val = get_tok_value(r->prop_ptr,"y2",0); + if(val[0]) wy2 = atof(val); + val = get_tok_value(r->prop_ptr,"digital",0); + if(val[0]) digital = atoi(val); + if(digital) { + val = get_tok_value(r->prop_ptr,"dig_max_waves",0); + if(val[0]) dig_max_waves = atoi(val); + } + /* plot single dataset */ + val = get_tok_value(r->prop_ptr,"dataset",0); + if(val[0]) dataset = atoi(val); + if(dataset >= xctx->graph_datasets) dataset = xctx->graph_datasets - 1; + /* set margins */ + calc_graph_area(c, i, digital, &x1, &y1, &x2, &y2, &marginx, &marginy); + + txtsizelab = marginy * 0.011; + tmp = (x2 - x1) / divx * 0.0033; + if(tmp < txtsizelab) txtsizelab = tmp; + digtxtsizelab = txtsizelab * 0.7; + /* cache coefficients for faster graph coord transformations */ + cx = (x2 - x1) / (wx2 - wx1); + dx = x1 - wx1 * cx; + cy = (y1 - y2) / (wy2 - wy1); + dy = y2 - wy1 * cy; + + /* graph box, gridlines and axes */ + draw_graph_grid(rx1, ry1, rx2, ry2, x1, y1, x2, y2, marginx, marginy, + wx1, wy1, wx2, wy2, cx, cy, dx, dy, + divx, divy, subdivx, subdivy, unitx, unity, digital); + /* get data to plot */ my_strdup2(1389, &node, get_tok_value(r->prop_ptr,"node",0)); my_strdup2(1390, &color, get_tok_value(r->prop_ptr,"color",0)); @@ -1980,8 +2108,11 @@ void draw_graph(int c, int i, int flags) cptr = color; sptr = sweep; n_nodes = count_items(node, " \t\n"); - /* process each node given in "node" attribute, get also associated color if any*/ + /* process each node given in "node" attribute, get also associated color/sweep var if any*/ while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) { + if(strstr(ntok, ",")) { + my_strdup2(1452, &bus_msb, find_nth(ntok, ',', 2)); + } ctok = my_strtok_r(cptr, " ", &savec); stok = my_strtok_r(sptr, " ", &saves); nptr = cptr = sptr = NULL; @@ -1993,28 +2124,43 @@ void draw_graph(int c, int i, int flags) sweep_idx = 0; } } + /* clipping everything outside container area */ + bbox(START, 0.0, 0.0, 0.0, 0.0); + bbox(ADD, rx1, ry1, rx2, ry2); + bbox(SET_INSIDE, 0.0, 0.0, 0.0, 0.0); /* draw sweep variable(s) on x-axis */ if(wcnt == 0 || (stok && stok[0])) { - if(xctx->values) stok = xctx->names[sweep_idx]; + if(xctx->graph_values) stok = xctx->graph_names[sweep_idx]; if(unitx != 1.0) my_snprintf(tmpstr, S(tmpstr), "%s[%c]", stok ? stok : "" , unitx_suffix); else my_snprintf(tmpstr, S(tmpstr), "%s", stok ? stok : ""); draw_string(wave_color, NOW, tmpstr, 2, 1, 0, 0, rx1 + 2 + rw / n_nodes * wcnt, ry2-1, txtsizelab, txtsizelab); } /* draw node labels in graph */ - if(unity != 1.0) my_snprintf(tmpstr, S(tmpstr), "%s[%c]", ntok, unity_suffix); - else my_snprintf(tmpstr, S(tmpstr), "%s", ntok); + if(bus_msb) { + if(unity != 1.0) my_snprintf(tmpstr, S(tmpstr), "%s[%c]", find_nth(ntok, ',', 1), unity_suffix); + else my_snprintf(tmpstr, S(tmpstr), "%s",find_nth(ntok, ',', 1)); + } else { + if(unity != 1.0) my_snprintf(tmpstr, S(tmpstr), "%s[%c]", ntok, unity_suffix); + else my_snprintf(tmpstr, S(tmpstr), "%s", ntok); + } if(digital) { - draw_string(wave_color, NOW, tmpstr, 0, 1, 0, 1, - x1 - 2 - 30 * txtsizelab, - W_Y((wy2 - wy1) * ((double)wcnt + 0.5) / n_nodes ), - txtsizelab, txtsizelab); + /* int n = n_nodes > dig_max_waves ? dig_max_waves : n_nodes; */ + int n = dig_max_waves; + double xt = x1 - 4 - 30 * txtsizelab; + double delta_div_n = (wy2 - wy1) / n; + double yt = delta_div_n * (double)wcnt; + + if(yt <= wy2 && yt >= wy1) { + draw_string(wave_color, NOW, tmpstr, 2, 0, 0, 0, xt, W_Y(yt), digtxtsizelab, digtxtsizelab); + } } else { draw_string(wave_color, NOW, tmpstr, 0, 0, 0, 0, rx1 + rw / n_nodes * wcnt, ry1, txtsizelab, txtsizelab); } + bbox(END, 0.0, 0.0, 0.0, 0.0); /* quickly find index number of ntok variable to be plotted */ - entry = int_hash_lookup(xctx->raw_table, ntok, 0, XLOOKUP); - if(xctx->values && entry) { + entry = int_hash_lookup(xctx->raw_table, bus_msb ? bus_msb : ntok, 0, XLOOKUP); + if(xctx->graph_values && entry) { int p, dset, ofs; int poly_npoints; int v; @@ -2034,23 +2180,29 @@ void draw_graph(int c, int i, int flags) start = (wx1 <= wx2) ? wx1 : wx2; end = (wx1 <= wx2) ? wx2 : wx1; /* loop through all datasets found in raw file */ - for(dset = 0 ; dset < xctx->datasets; dset++) { + for(dset = 0 ; dset < xctx->graph_datasets; dset++) { if(dataset == -1 || dset == dataset) { double prev_x; first = -1; poly_npoints = 0; - my_realloc(1401, &xarr, xctx->npoints[dset] * sizeof(double)); - my_realloc(1402, &yarr, xctx->npoints[dset] * sizeof(double)); + my_realloc(1401, &xarr, xctx->graph_npoints[dset] * sizeof(double)); + my_realloc(1402, &yarr, xctx->graph_npoints[dset] * sizeof(double)); /* Process "npoints" simulation items * p loop split repeated 2 timed (for x and y points) to preserve cache locality */ - for(p = ofs ; p < ofs + xctx->npoints[dset]; p++) { - xx = xctx->values[sweep_idx][p]; + for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) { + xx = xctx->graph_values[sweep_idx][p]; if(xx > end || (sweep_idx == 0 && (p > ofs && fabs(xx) < fabs(prev_x))) ) { if(first != -1) { /* get y-axis points */ - get_y_points(v, first, p, cy, dy, yarr, digital, wcnt, n_nodes, wy2 - wy1); - /* plot data */ - drawpolygon(wave_color, 0, xarr, yarr, poly_npoints, 0, 0); + if(bus_msb) { + if(digital) { + draw_graph_bus_points(ntok, first, p, cx, dx, cy, dy, wave_color, + sweep_idx, digital, dig_max_waves, wcnt, n_nodes, wy1, wy2); + } + } else { + draw_graph_points(v, first, p, cy, dy, xarr, yarr, wave_color, + digital, dig_max_waves, wcnt, n_nodes, wy1, wy2); + } poly_npoints = 0; first = -1; } @@ -2065,20 +2217,27 @@ void draw_graph(int c, int i, int flags) } if(first != -1) { /* get y-axis points */ - get_y_points(v, first, p, cy, dy, yarr, digital, wcnt, n_nodes, wy2 - wy1); - /* plot data */ - drawpolygon(wave_color, 0, xarr, yarr, poly_npoints, 0, 0); + if(bus_msb) { + if(digital) { + draw_graph_bus_points(ntok, first, p, cx, dx, cy, dy, wave_color, + sweep_idx, digital, dig_max_waves, wcnt, n_nodes, wy1, wy2); + } + } else { + draw_graph_points(v, first, p, cy, dy, xarr, yarr, wave_color, + digital, dig_max_waves, wcnt, n_nodes, wy1, wy2); + } } } /* if(dataset == -1 || dset == dataset) */ /* offset pointing to next dataset */ - ofs += xctx->npoints[dset]; + ofs += xctx->graph_npoints[dset]; } /* for(dset...) */ my_free(1403, &xarr); my_free(1404, &yarr); bbox(END, 0.0, 0.0, 0.0, 0.0); }/* if(entry) */ wcnt++; + if(bus_msb) my_free(1453, &bus_msb); } /* while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) */ if(flags & 1) { bbox(START, 0.0, 0.0, 0.0, 0.0); @@ -2098,16 +2257,16 @@ void draw_graph(int c, int i, int flags) /* fill graph boxes with data from ngspice simulations */ /* flags: * 1: do final XCopyArea (copy 2nd buffer areas to screen) - * If draw_waves() is called from draw() no need to do XCopyArea, as draw() does it already. + * If draw_graph_all() is called from draw() no need to do XCopyArea, as draw() does it already. * This makes drawing faster and removes a 'tearing' effect when moving around. */ -void draw_waves(int flags) +void draw_graph_all(int flags) { int c, i, sch_loaded, hide_graphs; int bbox_set = 0; const char *tmp; int save_bbx1, save_bby1, save_bbx2, save_bby2; - /* save bbox data, since draw_waves() is called from draw() which may be called after a bbox(SET) */ + /* save bbox data, since draw_graph_all() is called from draw() which may be called after a bbox(SET) */ sch_loaded = schematic_waves_loaded(); tmp = tclgetvar("hide_empty_graphs"); hide_graphs = (tmp && tmp[0] == '1') ? 1 : 0; @@ -2176,7 +2335,7 @@ void draw(void) xctx->areaw, xctx->areah); dbg(1, "draw(): window: %d %d %d %d\n",xctx->areax1, xctx->areay1, xctx->areax2, xctx->areay2); drawgrid(); - draw_waves(0); + draw_graph_all(0); x1 = X_TO_XSCHEM(xctx->areax1); y1 = Y_TO_XSCHEM(xctx->areay1); x2 = X_TO_XSCHEM(xctx->areax2); diff --git a/src/scheduler.c b/src/scheduler.c index eba7281d..fa310a1b 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1964,7 +1964,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg { cmd_found = 1; tclsetvar("rawfile_loaded", "0"); - free_rawfile(); + free_rawfile(1); Tcl_ResetResult(interp); } @@ -1977,7 +1977,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); if(argc > 2 && !strcmp(argv[2], "loaded")) { Tcl_AppendResult(interp, schematic_waves_loaded() ? "1" : "0", NULL); - } else if(xctx->values) { + } else if(xctx->graph_values) { if(argc > 5) dataset = atoi(argv[5]); if(argc > 4) { /* xschem rawfile_query value v(ldcp) 123 */ @@ -1985,10 +1985,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg int point = atoi(argv[4]); const char *node = argv[3]; int idx = -1; - if(point >= 0 && point < xctx->npoints[dataset]) { + if(point >= 0 && point < xctx->graph_npoints[dataset]) { if(isonlydigit(node)) { int i = atoi(node); - if(i >= 0 && i < xctx->nvars) { + if(i >= 0 && i < xctx->graph_nvars) { idx = i; } } else { @@ -2013,14 +2013,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } } else if(argc > 2) { if(!strcmp(argv[2], "points")) { - my_snprintf(s, S(s), "%d", xctx->npoints[0]); + my_snprintf(s, S(s), "%d", xctx->graph_npoints[0]); Tcl_AppendResult(interp, s, NULL); } else if(!strcmp(argv[2], "vars")) { - my_snprintf(s, S(s), "%d", xctx->nvars); + my_snprintf(s, S(s), "%d", xctx->graph_nvars); Tcl_AppendResult(interp, s, NULL); } else if(!strcmp(argv[2], "list")) { - for(i = 0 ; i < xctx->nvars; i++) { - Tcl_AppendResult(interp, xctx->names[i], "\n", NULL); + for(i = 0 ; i < xctx->graph_nvars; i++) { + Tcl_AppendResult(interp, xctx->graph_names[i], "\n", NULL); } } } @@ -2031,9 +2031,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg { cmd_found = 1; if(schematic_waves_loaded()) { - free_rawfile(); + free_rawfile(1); } else if(argc > 2) { - free_rawfile(); + free_rawfile(0); read_rawfile(argv[2]); if(schematic_waves_loaded()) tclsetvar("rawfile_loaded", "1"); else tclsetvar("rawfile_loaded", "0"); diff --git a/src/select.c b/src/select.c index 5fac9b73..d40a42e1 100644 --- a/src/select.c +++ b/src/select.c @@ -545,6 +545,33 @@ void bbox(int what,double x1,double y1, double x2, double y2) xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height); } break; + + + + case SET_INSIDE: /* do not add line widths to clip rectangle so everything remains inside */ + if(xctx->sem==0) { + fprintf(errfp, "ERROR: bbox(SET_INSIDE) call before bbox(START)\n"); + tcleval("alert_ {ERROR: bbox(SET_INSIDE) call before bbox(START)} {}"); + } + xctx->areax1 = xctx->bbx1-2*INT_WIDTH(xctx->lw); + xctx->areax2 = xctx->bbx2+2*INT_WIDTH(xctx->lw); + xctx->areay1 = xctx->bby1-2*INT_WIDTH(xctx->lw); + xctx->areay2 = xctx->bby2+2*INT_WIDTH(xctx->lw); + xctx->areaw = (xctx->areax2-xctx->areax1); + xctx->areah = (xctx->areay2-xctx->areay1); + + xctx->xrect[0].x = xctx->bbx1+INT_WIDTH(xctx->lw); + xctx->xrect[0].y = xctx->bby1+INT_WIDTH(xctx->lw); + xctx->xrect[0].width = xctx->bbx2-xctx->bbx1-2*INT_WIDTH(xctx->lw); + xctx->xrect[0].height = xctx->bby2-xctx->bby1-2*INT_WIDTH(xctx->lw); + if(has_x) { + set_clip_mask(SET); + dbg(2, "bbox(SET): setting clip area: %d %d %d %d\n", + xctx->xrect[0].x, xctx->xrect[0].y, xctx->xrect[0].width, xctx->xrect[0].height); + } + break; + + default: break; } diff --git a/src/xinit.c b/src/xinit.c index 955f3579..258a7c05 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -422,12 +422,13 @@ void alloc_xschem_data(const char *top_path) xctx->mooz=1/CADINITIALZOOM; xctx->xorigin=CADINITIALX; xctx->yorigin=CADINITIALY; - xctx->names = NULL; - xctx->values = NULL; - xctx->nvars = 0; - xctx->npoints = NULL; - xctx->datasets = 0; + xctx->graph_names = NULL; + xctx->graph_values = NULL; + xctx->graph_nvars = 0; + xctx->graph_npoints = NULL; + xctx->graph_datasets = 0; xctx->graph_master = 0; + xctx->graph_flags = 0; xctx->graph_bottom = 0; xctx->graph_left = 0; xctx->raw_schname = NULL; @@ -621,7 +622,7 @@ void delete_schematic_data(void) * inst & wire .node fields, instance name hash */ clear_drawing(); remove_symbols(); - free_rawfile(); + free_rawfile(0); free_xschem_data(); /* delete the xctx struct */ } @@ -1264,6 +1265,7 @@ void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h) } } if(xctx->pending_fullzoom) { + dbg(1, "resetwin(): pending_fulzoom: doing zoom_full()\n"); zoom_full(0, 0, 1, 0.97); xctx->pending_fullzoom=0; } diff --git a/src/xschem.h b/src/xschem.h index a419c227..e497bfd6 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -248,6 +248,7 @@ extern char win_temp_dir[PATH_MAX]; #define THICK 1024 /* used to draw thick lines (buses) */ #define ROTATELOCAL 2048 /* rotate each selected object around its own anchor point 20171208 */ #define CLEAR 4096 /* used in new_wire to clear previous rubber when switching xctx->manhattan_lines */ +#define SET_INSIDE 8192 /* used in bbox() to set clipping rectangle inside, not adding line width */ /* #define DRAW 8192 */ /* was used in bbox() to draw things by using XCopyArea after setting clip rectangle */ #define HILIGHT 8192 /* used when calling draw_*symbol_outline() for hilighting instead of normal draw */ #define FONTWIDTH 20 @@ -635,6 +636,32 @@ typedef struct unsigned short *wireflag; } Iterator_ctx; + +/* will be used some day? <<<< */ +typedef struct { + /* container box */ + /* graph box (smaller tha rect container due to margins) */ + double x1, y1, x2, y2, w, h; + /* graph coordinate, some defaults */ + double digital; + double wx1, wy1, wx2, wy2; + double marginx; /* will be recalculated later */ + double marginy; /* will be recalculated later */ + /* coefficients for graph to container coordinate transformations W_X() and W_Y()*/ + double cx, dx, cy, dy; + double dash_sizex, dash_sizey; + int divx; + int divy; + int subdivx; + int subdivy; + double unitx; + double unity; + int unitx_suffix; /* 'n' or 'u' or 'M' or 'k' ... */ + int unity_suffix; + double txtsizelab, txtsizey, txtsizex; + int dataset; +} Graph_ctx; + typedef struct { xWire *wire; xText *text; @@ -795,11 +822,12 @@ typedef struct { Undo_slot uslot[MAX_UNDO]; int undo_initialized; /* read raw files (draw.c) */ - char **names; - SPICE_DATA **values; - int nvars; - int *npoints; - int datasets; + char **graph_names; + SPICE_DATA **graph_values; + int graph_nvars; + int *graph_npoints; + int graph_datasets; + int graph_flags; /* 1: zoom / pan all graphs even if only one selected */ int graph_master; /* graph where mouse operations are started, used to lock x-axis */ int graph_bottom; /* graph where mouse operations are started, used to lock x-axis */ int graph_left; /* graph where mouse operations are started, used to lock x-axis */ @@ -922,11 +950,11 @@ extern Xschem_ctx *xctx; extern int get_raw_index(const char *node); extern double get_raw_value(int dataset, int idx, int point); extern int schematic_waves_loaded(void); -extern void calc_graph_area(int c, int i, double *x1, double *y1,double *x2, double *y2, +extern void calc_graph_area(int c, int i, int digital, double *x1, double *y1,double *x2, double *y2, double *marginx,double *marginy); extern void draw_graph(int c, int i, int flags); -extern void draw_waves(int flags); -extern void free_rawfile(void); +extern void draw_graph_all(int flags); +extern void free_rawfile(int dr); extern int read_rawfile(const char *f); extern double timer(int start); extern void enable_layers(void); diff --git a/src/xschem.tcl b/src/xschem.tcl index 28e722ba..a5c1db49 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -131,7 +131,7 @@ proc inutile_translate {f} { set p $XSCHEM_SHAREDIR/utile set savedir [pwd] cd $netlist_dir - eval exec $p/preprocess.awk \"$f\" | $p/expand_alias.awk | $p/param.awk | $p/clock.awk | $p/stimuli.awk + eval exec awk -f $p/preprocess.awk \"$f\" | awk -f $p/expand_alias.awk | awk -f $p/param.awk | awk -f $p/clock.awk | awk -f $p/stimuli.awk cd $savedir } @@ -1146,7 +1146,11 @@ proc simulate {{callback {}}} { set cmd [subst $sim($tool,$def,cmd)] if {$OS == "Windows"} { # $cmd cannot be surrounded by {} as exec will change forward slash to backward slash - eval exec $cmd + if { $callback ne {} } { + eval $callback + } + #eval exec {cmd /V /C "cd $netlist_dir&&$cmd} + eval exec $cmd & } else { set execute(callback) $callback $fg $st sh -c "cd $netlist_dir; $cmd" @@ -1298,21 +1302,21 @@ proc edit_netlist {schname } { } elseif { $netlist_type=="spice" } { if {$OS == "Windows"} { set cmd "$editor \"$netlist_dir/${tmpname}.spice\"" - eval exec $cmd + eval exec $cmd & } else { execute 0 sh -c "cd $netlist_dir && $editor $ftype \"${tmpname}.spice\"" } } elseif { $netlist_type=="tedax" } { if {$OS == "Windows"} { set cmd "$editor \"$netlist_dir/${tmpname}.tdx\"" - eval exec $cmd + eval exec $cmd & } else { execute 0 sh -c "cd $netlist_dir && $editor $ftype \"${tmpname}.tdx\"" } } elseif { $netlist_type=="vhdl" } { if {$OS == "Windows"} { set cmd "$editor \"$netlist_dir/${tmpname}.vhdl\"" - eval exec $cmd + eval exec $cmd & } else { execute 0 sh -c "cd $netlist_dir && $editor $ftype \"${tmpname}.vhdl\"" } diff --git a/xschem_library/rom8k/rom8k.sch b/xschem_library/rom8k/rom8k.sch index 5d0a7a24..0969f5bd 100644 --- a/xschem_library/rom8k/rom8k.sch +++ b/xschem_library/rom8k/rom8k.sch @@ -27,26 +27,27 @@ L 8 1150 -160 1180 -160 {} L 8 1180 -160 1180 -120 {} L 8 1180 -120 1300 -120 {} L 8 820 -120 950 -120 {} -B 2 1840 -360 2890 -280 {flags=1 -y1 = -0.0039 -y2 = 0.87 +B 2 1840 -400 2890 -280 {flags=1 +y1 = 0 +y2 = 0.9 divy = 1 -x1=1.26223e-07 -x2=2.06222e-07 divx=10 +subdivy=2 +x1=1.30572e-07 +x2=1.82007e-07 divx=10 node=" v(ldbl[0]) v(ldbl[16]) v(ldbl[32]) v(ldbl[1]) v(ldbl[17]) v(ldbl[33]) v(ldbl[2]) v(ldbl[18]) v(ldbl[34]) " color="8 9 10 11 12 13 14 15 16 17 18" unitx=n} -B 2 1840 -920 2890 -710 {flags=1 +B 2 1840 -1090 2890 -880 {flags=1 digital=0 -y1 = -0.00091 -y2 = 1.5 -subdivy=4 +y1 = -0.0120424 +y2 = 1.50796 +subdivy=1 divy = 4 -x1=1.26223e-07 -x2=2.06222e-07 +x1=1.30572e-07 +x2=1.82007e-07 divx=10 subdivx=4 node="v(ldcp) v(ldyms[4]) v(ldyms[5]) v(ldyms[6]) v(ldyms[7])" @@ -56,10 +57,10 @@ B 2 1840 -280 2890 -120 {flags=1 y1 = -0.0072 y2 = 1.6 divy = 3 -subdivy=1 -subdivx = 4 -x1=1.26223e-07 -x2=2.06222e-07 divx=10 +subdivy=0 +subdivx = 1 +x1=1.30572e-07 +x2=1.82007e-07 divx=10 node=" v(ldcp) v(ldwl[0]) v(ldwl[1]) v(ldwl[2]) v(ldwl[3]) @@ -70,85 +71,48 @@ color="4 5" unitx=n } B 2 1840 -120 2890 -40 {flags=1 -y1 = -0.021 +y1 = 0 y2 = 0.9 divy = 1 -x1=1.26223e-07 -x2=2.06222e-07 divx=10 +x1=1.30572e-07 +x2=1.82007e-07 divx=10 node="v(ldymsref)" color=3 unitx=n subdivy=4} -B 2 1840 -710 2890 -360 {flags=1 +B 2 1840 -880 2890 -400 {flags=1 digital=1 -y1 = 0 -y2 = 1.5 +dig_max_waves=12 +y1 = -0.0811982 +y2 = 1.4188 divy = 1 -x1=1.26223e-07 -x2=2.06222e-07 divx=10 -node="v(ldcp) v(lden) v(ldprech) ---- -v(ldl1x[0]) v(ldl1x[1]) v(ldl1x[2]) v(ldl1x[3]) -v(ldl1x[4]) v(ldl1x[5]) v(ldl1x[6]) v(ldl1x[7]) ---- -v(ldy1[0]) v(ldy1[1]) v(ldy1[2]) v(ldy1[3]) +x1=1.30572e-07 +x2=1.82007e-07 +divx=10 +subdivx=4 +node=" +v(lden) v(ldprech) +---Timing--- +LDL3X,v(ldl3x[7]),v(ldl3x[6]),v(ldl3x[5]),v(ldl3x[4]),v(ldl3x[3]),v(ldl3x[2]),v(ldl3x[1]),v(ldl3x[0]) +LDL2X,v(ldl2x[3]),v(ldl2x[2]),v(ldl2x[1]),v(ldl2x[0]) +LDL1X,v(ldl1x[15]),v(ldl1x[14]),v(ldl1x[13]),v(ldl1x[12]),v(ldl1x[11]),v(ldl1x[10]),v(ldl1x[9]),v(ldl1x[8]),v(ldl1x[7]),v(ldl1x[6]),v(ldl1x[5]),v(ldl1x[4]),v(ldl1x[3]),v(ldl1x[2]),v(ldl1x[1]),v(ldl1x[0]) +LDY1,v(ldy1[3]),v(ldy1[2]),v(ldy1[1]),v(ldy1[0]) +---Decoders--- +LDQ,v(ldq[15]),v(ldq[14]),v(ldq[13]),v(ldq[12]),v(ldq[11]),v(ldq[10]),v(ldq[9]),v(ldq[8]),v(ldq[7]),v(ldq[6]),v(ldq[5]),v(ldq[4]),v(ldq[3]),v(ldq[2]),v(ldq[1]),v(ldq[0]) +LDA,v(lda[12]),v(lda[11]),v(lda[10]),v(lda[9]),v(lda[8]),v(lda[7]),v(lda[6]),v(lda[5]),v(lda[4]),v(lda[3]),v(lda[2]),v(lda[1]),v(lda[0]) +v(ldcp) +---In/Out--- " -color=4 -xcolor="5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 3 4 5 6" +color="4 15 4 15 4 15 4 15 4 15 4 15 4 15 4 15 4 15 4 15 4 15" unitx=n } -B 2 1840 -1030 2890 -920 {flags=1 -y1 = 0 -y2 = 2 -divy = 2 -x1=1.26223e-07 -x2=2.06222e-07 -divx=8 -comm="example of using tcl to replace the path - with $path variable automatically" -node="tcleval(v(xctrl.ldcp_ref) v(xctrl.ldprechref))" -color="16 11 15" -} -B 2 1840 -1120 2890 -1030 {flags=1 -y1 = 0 -y2 = 2 -divy = 2 -x1=1.26223e-07 -x2=2.06222e-07 -divx=8 -comm="example of using tcl to replace the path - with $path variable automatically" -node="tcleval(v(xctrl.ldcp_ref) v(xctrl.ldcpb))" -color="16 11 15" -} -B 2 1840 -1210 2890 -1120 {flags=1 -y1 = 0 -y2 = 2 -divy = 2 -x1=1.26223e-07 -x2=2.06222e-07 -divx=8 -comm="example of using tcl to replace the path - with $path variable automatically" -node="tcleval(v(xctrl.ldcp_ref) v(xctrl.ldouti) v(xctrl.ldoutib))" -color="16 11 15" -} -B 2 1840 -1500 2890 -1320 {flags=1 -y1 = 0 -y2 = 2 +B 2 1840 -1270 2890 -1090 {flags=1 +y1 = -0.0479717 +y2 = 1.55203 divy = 4 -x1=1.26223e-07 -x2=2.06222e-07 +x1=1.30572e-07 +x2=1.82007e-07 divx=8 node="v(xsa[0].ldqi) v(xsa[0].ldqib) v(xsa[0].ldsali)" -color="16 11 15"} -B 2 1840 -1320 2890 -1210 {flags=1 -y1 = 0 -y2 = 2 -divy = 2 -x1=1.26223e-07 -x2=2.06222e-07 -divx=8 -node="v(xsa[0].ldqiii) v(xsa[0].ldqii) v(xsa[0].ldsali)" -color="16 11 15"} +color="16 8 15"} B 7 950 -250 980 -80 {} B 7 1150 -250 1180 -80 {} B 21 10 -970 240 -750 {}