Merge branch 'StefanSchippers:master' into master

This commit is contained in:
Chayan Deb 2025-01-09 17:21:52 +05:30 committed by GitHub
commit a184d38007
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1026 additions and 723 deletions

View File

@ -1342,8 +1342,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
if x0, y0 not given use mouse coordinates </pre>
<li><kbd> rotate_in_place</kbd></li><pre>
Rotate selected objects around their 0,0 coordinate point </pre>
<li><kbd> save</kbd></li><pre>
Save schematic if modified. Does not ask confirmation! </pre>
<li><kbd> save [fast]</kbd></li><pre>
Save schematic if modified. Does not ask confirmation!
if 'fast' is given it is passed to save_schematic() to avoid
updating window/tab/sim button states </pre>
<li><kbd> saveas [file] [type]</kbd></li><pre>
save current schematic as 'file'
if file is empty ({}) use current schematic name
@ -1393,6 +1395,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
for all other objects 'id' is the position in the respective arrays
if 'clear' is specified does an unselect operation
if 'fast' is specified avoid sending information to infowindow and status bar
if 'nodraw' is given on select instance do not draw selection
returns 1 if something selected, 0 otherwise </pre>
<li><kbd> select_all</kbd></li><pre>
Selects all objects in schematic </pre>

View File

@ -66,9 +66,6 @@ p{padding: 15px 30px 10px;}
<kbd>Waves-&gt;Op | Ac | Dc | Tran | Tran | Noise | Sp </kbd>. This command loads the user selected
.raw file produced by a ngspice/Xyce simulation.
</p>
<p class="important">
Ensure the <kbd>circuit.raw</kbd> is saved in binary format (no <kbd>set filetype=ascii</kbd> in your testbench)
</p>
<p>
The raw file is usually located in the simulation/netlisting directory
<kbd>Simulation -&gt;set netlist dir</kbd>.<br>
@ -80,6 +77,17 @@ p{padding: 15px 30px 10px;}
Then, select a node or a net label, press 'Alt-G', the net will be added to the graph. Here after a
list of commands you can perform in a graph to modify the viewport. These commands are active when
the mouse is Inside the graph (you will notice the mouse pointer changing from an arrow to a <kbd>+</kbd>).
</p>
<p class="important">
if <kbd>set graph_use_ctrl_key 1</kbd> is set in the <kbd>xschemrc</kbd> file all bind keys shown
below will need the <kbd>Control</kbd> key pressed to operate on the graphs. This setting can be used
to make it more explicit when the user wants to operate on graphs. Without the <kbd>Control</kbd>
key pressed the usual functions on schematic are performed instead of graph functions.<br>
Example: the key <kbd>a</kbd> will create a symbol if used in a schematic while it shows a cursor
if done when the mouse pointer is inside a graph. With the <kbd>set graph_use_ctrl_key 1</kbd> option
you will need to press <kbd>Control-a</kbd> with the mouse pointer inside a graph to show a cursor.
</p>
<p>
if the mouse is outside the graph the usual Xschem functions will be available to operate on schematics:
</p>
<ul>
@ -87,13 +95,14 @@ p{padding: 15px 30px 10px;}
<li>Pressing <kbd>f</kbd> with the mouse on the left of the Y axis will do a full Y-axis zoom.</li>
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is inside a graph will
move the waveforms to the left/right or zoom in/zoom out respectively.</li>
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is on the left of the Y-axis
will move the waveforms or zoom in/zoom out in the Y direction respectively.</li>
<li>Pressing <kbd>Left/Right</kbd> arrow keys while the mouse is on the left of the Y-axis
will zoom in/zoom out in the Y direction.</li>
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is in the center of the graph
will move the waves left or right following the pointer X movement.</li>
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is on the left of the Y-axis
will move the waves high or low following the pointer Y movement.</li>
<li> Doing the above with the <kbd>Shift</kbd> key pressed will zoom in/out instead of moving.</li>
<li> pressing <kbd>A</kbd> and/or <kbd>B</kbd> will show a horizontal cursor.
The difference between the <kbd>A</kbd> and the <kbd>B</kbd> cursor is shown.</li>
<li> pressing <kbd>a</kbd> and/or <kbd>b</kbd> will show a vertical cursor.
The sweep variable difference between the <kbd>a</kbd> and the <kbd>b</kbd> cursor is shown and
the values of all signals at the X position of the <kbd>a</kbd> cursor is shown. </li>
@ -104,6 +113,8 @@ p{padding: 15px 30px 10px;}
configuration dialog box, where you can change many graph parameters.</li>
<li> Pressing the <kbd>right</kbd> mouse button in the graph area and dragging some distance in the X direction
will zoom in the waveforms to that X range.</li>
<li> Pressing the <kbd>right</kbd> mouse button to the left of the Y axis and dragging some distance in the Y direction
will zoom in the waveforms to that Y range.</li>
</ul>
<p>
<img src="graphs07.png"><br>

View File

@ -536,8 +536,9 @@ const char *get_file_path(char *f)
* 1 : file saved or not needed to save since no change
* -1 : user cancel
* 0 : file not saved due to errors or per user request
* confirm:
*/
int save(int confirm)
int save(int confirm, int fast)
{
struct stat buf;
char *name = xctx->sch[xctx->currsch];
@ -556,10 +557,10 @@ int save(int confirm)
if(confirm) {
tcleval("ask_save_optional");
if(!strcmp(tclresult(), "") ) return -1; /* user clicks "Cancel" */
else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch]);
else if(!strcmp(tclresult(), "yes") ) return save_schematic(xctx->sch[xctx->currsch], fast);
else return 0; /* user clicks "no" */
} else {
return save_schematic(xctx->sch[xctx->currsch]);
return save_schematic(xctx->sch[xctx->currsch], fast);
}
}
return 1; /* circuit not changed: always succeeed */
@ -592,7 +593,7 @@ void saveas(const char *f, int type) /* changed name from ask_save_file to save
if(!res[0]) return;
dbg(1, "saveas(): res = %s\n", res);
save_schematic(res);
save_schematic(res, 0);
tclvareval("update_recent_file {", res,"}", NULL);
return;
}
@ -603,7 +604,7 @@ void ask_new_file(void)
if(!has_x) return;
if(xctx->modified) {
if(save(1) == -1 ) return; /* user cancels save, so do nothing. */
if(save(1, 0) == -1 ) return; /* user cancels save, so do nothing. */
}
tcleval("load_file_dialog {Load file} *.\\{sch,sym,tcl\\} INITIALLOADDIR");
my_snprintf(f, S(f),"%s", tclresult());
@ -2231,7 +2232,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
my_strncpy(res, tclresult(), S(res));
if(!res[0]) return 0;
dbg(1, "descend_schematic(): saving: %s\n",res);
save_ok = save_schematic(res);
save_ok = save_schematic(res, 0);
if(save_ok==0) return 0;
}
n = xctx->sel_array[0].n;
@ -2248,7 +2249,7 @@ int descend_schematic(int instnumber, int fallback, int alert, int set_title)
if(xctx->modified) {
int ret;
ret = save(1);
ret = save(1, 0);
/* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights
* save() return value:
@ -2402,10 +2403,10 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
{
if(confirm) {
tcleval("ask_save_optional");
if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch]);
if(!strcmp(tclresult(), "yes") ) save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
else if(!strcmp(tclresult(), "") ) return;
} else {
save_ok = save_schematic(xctx->sch[xctx->currsch]);
save_ok = save_schematic(xctx->sch[xctx->currsch], 0);
}
}
if(save_ok==0) {
@ -2458,7 +2459,7 @@ void go_back(int confirm, int set_title) /* 20171006 add confirm */
void clear_schematic(int cancel, int symbol)
{
if(cancel == 1) cancel=save(1);
if(cancel == 1) cancel=save(1, 0);
if(cancel != -1) { /* -1 means user cancel save request */
char name[PATH_MAX];
struct stat buf;

File diff suppressed because it is too large Load Diff

View File

@ -2514,6 +2514,9 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset)
int cnt=0, wrap;
register SPICE_DATA *gv = raw->values[sweep_idx];
ofs_end = ofs + raw->npoints[dset];
/* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
for(p = ofs ; p < ofs_end; p++) {
if(gr->logx) xx = mylog10(gv[p]);
else xx = gv[p];
@ -2539,6 +2542,9 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset)
++cnt;
}
} /* for(p = ofs ; p < ofs + raw->npoints[dset]; p++) */
done:
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
@ -2905,7 +2911,18 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->digital = 0;
gr->rainbow = 0;
gr->linewidth_mult = tclgetdoublevar("graph_linewidth_mult");
xctx->graph_flags &= ~(128 | 256); /* clear hcursor flags */
gr->hcursor1_y = gr->hcursor2_y = 0.0;
val = get_tok_value(r->prop_ptr,"hcursor1_y", 0);
if(val[0]) {
gr->hcursor1_y = atof_spice(val);
xctx->graph_flags |= 128;
}
val = get_tok_value(r->prop_ptr,"hcursor2_y", 0);
if(val[0]) {
gr->hcursor2_y = atof_spice(val);
xctx->graph_flags |= 256;
}
if(!skip) {
gr->gx1 = 0;
gr->gx2 = 1e-6;
@ -3016,9 +3033,9 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->gh = gr->gy2 - gr->gy1;
/* set margins */
tmp = gr->rw * 0.14;
gr->marginx = tmp < 30 ? 30 : tmp;
gr->marginx = tmp < 50 ? 50 : tmp;
tmp = gr->rh * 0.14;
gr->marginy = tmp < 35 ? 35 : tmp;
gr->marginy = tmp < 40 ? 40 : tmp;
/* calculate graph bounding box (container - margin)
* This is the box where plot is done */
@ -3031,7 +3048,7 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->h = gr->y2 - gr->y1;
/* label text size calculations */
gr->txtsizelab = gr->marginy * 0.007;
gr->txtsizelab = gr->marginy * 0.006;
/*
* tmp = gr->w * 0.00044;
* if(tmp < gr->txtsizelab) gr->txtsizelab = tmp;
@ -3042,8 +3059,8 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
gr->digtxtsizelab = 0.001200 * fabs( gr->h / gr->posh * gr->gh );
/* x axis, y axis text sizes */
gr->txtsizey = gr->h / gr->divy * 0.009;
tmp = gr->marginx * 0.005;
gr->txtsizey = gr->h / gr->divy * 0.0095;
tmp = gr->marginx * 0.003;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
tmp = gr->marginy * 0.02;
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
@ -3136,6 +3153,72 @@ static void draw_cursor_difference(double c1, double c2, Graph_ctx *gr)
}
}
static void draw_hcursor(double active_cursory, int cursor_color, Graph_ctx *gr)
{
double yy, pos = active_cursory;
double tx1, ty1, tx2, ty2, dtmp;
int tmp;
char tmpstr[100];
double txtsize = gr->txtsizey;
double th;
if(gr->digital) return;
if(gr->logy) pos = mylog10(pos);
yy = W_Y(pos);
if(yy >= gr->y1 && yy <= gr->y2) {
drawline(cursor_color, NOW, gr->rx1 + 10, yy, gr->rx2 - 10, yy, 1, NULL);
if(gr->unity != 1.0)
my_snprintf(tmpstr, S(tmpstr), " %.5g%c ", gr->unity * active_cursory , gr->unity_suffix);
else
my_snprintf(tmpstr, S(tmpstr), " %s ", dtoa_eng(active_cursory));
text_bbox(tmpstr, txtsize, txtsize, 0, 0, 0, 0, gr->rx1 + 5, yy, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
th = (ty2 - ty1) / 2.; /* half text height */
ty1 -= th;
ty2 -= th;
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
draw_string(cursor_color, NOW, tmpstr, 0, 0, 0, 0, gr->rx1 + 5, yy - th, txtsize, txtsize);
}
}
static void draw_hcursor_difference(double c1, double c2, Graph_ctx *gr)
{
int tmp;
char tmpstr[100];
double txtsize = gr->txtsizey;
double tx1, ty1, tx2, ty2;
double cc1 = gr->logy ? mylog10(c1) : c1;
double cc2 = gr->logy ? mylog10(c2) : c2;
double aa = W_Y(cc1);
double a = CLIP(aa, gr->y1, gr->y2);
double bb = W_Y(cc2);
double b = CLIP(bb, gr->y1, gr->y2);
double diff = fabs(b - a);
double diffh;
double yy = ( a + b ) * 0.5;
double xx = gr->rx1 + 5;
double dtmp;
double xline;
if(gr->digital) return;
diffh = fabs(c2 - c1);
if(gr->unity != 1.0)
my_snprintf(tmpstr, S(tmpstr), " %.4g%c ", gr->unity * diffh , gr->unity_suffix);
else
my_snprintf(tmpstr, S(tmpstr), " %s ", dtoa_eng(diffh));
text_bbox(tmpstr, txtsize, txtsize, 0, 0, 0, 1, xx, yy, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
if( 2 * (ty2 - ty1) < diff ) {
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
draw_string(3, NOW, tmpstr, 0, 0, 0, 1, xx, yy, txtsize, txtsize);
if( a > b) {
dtmp = a; a = b; b = dtmp;
}
xline = tx1 + 10;
if( ty1 - a > 4.0) drawline(3, NOW, xline, a + 2, xline, ty1 - 2, 1, NULL);
if( b - ty2 > 4.0) drawline(3, NOW, xline, ty2 + 2, xline, b - 2, 1, NULL);
}
}
/* sweep variables on x-axis, node labels */
static void draw_graph_variables(int wcnt, int wave_color, int n_nodes, int sweep_idx,
int flags, const char *ntok, const char *stok, const char *bus_msb, Graph_ctx *gr)
@ -3451,6 +3534,9 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
ofs_end = ofs + raw->npoints[dset];
first = -1;
last = ofs;
/* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
for(p = ofs ; p < ofs_end; p++) {
if(gr->logx)
xx = mylog10(gv[p]);
@ -3483,6 +3569,9 @@ int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr)
idx = plot_raw_custom_data(sweep_idx, first, last, express, NULL);
}
}
done:
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
@ -3654,12 +3743,14 @@ int find_closest_wave(int i, Graph_ctx *gr)
/* flags:
* 1: do final XCopyArea (copy 2nd buffer areas to screen)
* 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.
* 2: draw x-cursor1
* 4: draw x-cursor2
* 8: all drawing, if not set do only XCopyArea / x-cursor if specified
* 1: do final XCopyArea (copy 2nd buffer areas to screen)
* 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.
* 2: draw x-cursor1
* 4: draw x-cursor2
* 128: draw y-cursor1
* 256: draw y-cursor2
* 8: all drawing, if not set do only XCopyArea / x-cursor if specified
* ct is a pointer used in windows for cairo
*/
void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
@ -3714,7 +3805,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
#if 0
dbg(0, "draw_graph(): window: %d %d %d %d\n", xctx->areax1, xctx->areay1, xctx->areax2, xctx->areay2);
dbg(0, "draw_graph(): graph: %g %g %g %g\n", gr->sx1, gr->sy1, gr->sx2, gr->sy2);
dbg(0, "draw_graph(): i = %d, flags = %d\n", i, flags);
dbg(0, "draw_graph(): i = %d, flags = %d graph_flags=%d\n", i, flags, xctx->graph_flags);
#endif
/* draw stuff */
@ -3905,6 +3996,10 @@ 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;
/* optimization: skip unwanted datasets, if no dc no need to detect sweep variable wraps */
if(dataset >= 0 && strcmp(xctx->raw->sim_type, "dc") && dataset != sweepvar_wrap) goto done;
for(p = ofs ; p < ofs_end; p++) {
double xxprevious, xxfollowing;
@ -3980,6 +4075,8 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
} /* if(xx >= start && xx <= end) */
prev_x = xx;
} /* for(p = ofs ; p < ofs + xctx->raw->npoints[dset]; p++) */
if(first != -1) {
if(dataset == -1 || dataset == sweepvar_wrap) {
/* plot graph. Bus bundles are not plotted if graph is not digital.*/
@ -3996,6 +4093,9 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
}
}
}
done:
/* offset pointing to next dataset */
ofs = ofs_end;
sweepvar_wrap++;
@ -4036,17 +4136,17 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
*/
if(flags & 8) {
/* cursor1 */
if((flags & 2)) {
draw_cursor(cursor1, cursor2, 1, gr);
}
if((flags & 2)) draw_cursor(cursor1, cursor2, 1, gr);
/* cursor2 */
if((flags & 4)) {
draw_cursor(cursor2, cursor1, 3, gr);
}
if((flags & 4)) draw_cursor(cursor2, cursor1, 3, gr);
/* difference between cursors */
if((flags & 2) && (flags & 4)) {
draw_cursor_difference(cursor1, cursor2, gr);
}
if((flags & 2) && (flags & 4)) draw_cursor_difference(cursor1, cursor2, gr);
/* difference between hcursors */
if((flags & 128) && (flags & 256)) draw_hcursor_difference(gr->hcursor1_y, gr->hcursor2_y, gr);
/* hcursor1 */
if(flags & 128) draw_hcursor(gr->hcursor1_y, 15, gr);
/* hcursor2 */
if(flags & 256) draw_hcursor(gr->hcursor2_y, 19, gr);
}
if(flags & 1) { /* copy save buffer to screen */
if(!xctx->draw_window) {
@ -4097,8 +4197,10 @@ static void draw_graph_all(int flags)
if(xctx->enable_layer[GRIDLAYER]) for(i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
xRect *r = &xctx->rect[GRIDLAYER][i];
if(r->flags & 1) {
int flags2;
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, flags, &xctx->graph_struct, NULL); /* draw data in each graph box */
flags2 = flags | (xctx->graph_flags & (128 | 256)); /* include drawing hcursors if enabled */
draw_graph(i, flags2, &xctx->graph_struct, NULL); /* draw data in each graph box */
}
}
}
@ -4701,7 +4803,7 @@ void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2,
xRect *r = &xctx->rect[GRIDLAYER][i];
if(r->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8, &xctx->graph_struct, (void *)ct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
}
#endif

View File

@ -341,7 +341,7 @@ static int ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, doubl
xRect* r2 = &xctx->rect[GRIDLAYER][i];
if (r2->flags & 1) {
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, 8, &xctx->graph_struct, (void*)ct);
draw_graph(i, 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), &xctx->graph_struct, (void *)ct);
}
}
#endif

View File

@ -3315,14 +3315,13 @@ Sch_pin_record *sort_schematic_pins(int *npins)
* 0 : did not save
* 1 : schematic saved
*/
int save_schematic(const char *schname) /* 20171020 added return value */
int save_schematic(const char *schname, int fast) /* 20171020 added return value */
{
FILE *fd;
struct stat buf;
xRect *rect;
int rects;
char msg[PATH_MAX + 100];
int same_name = 0;
if(!schname || !strcmp(schname, "")) return 0;
@ -3338,7 +3337,6 @@ int save_schematic(const char *schname) /* 20171020 added return value */
set_modify(-1); /* set title to new filename */
}
else { /* user asks to save to same filename */
same_name = 1;
if(!stat(xctx->sch[xctx->currsch], &buf)) {
if(xctx->time_last_modify && xctx->time_last_modify != buf.st_mtime) {
tclvareval("ask_save_optional \"Schematic file: ", xctx->sch[xctx->currsch],
@ -3374,8 +3372,8 @@ int save_schematic(const char *schname) /* 20171020 added return value */
* xctx->prep_hash_wires=0;
*/
if(!strstr(xctx->sch[xctx->currsch], ".xschem_embedded_")) {
if(same_name) set_modify(2); /* clear only modified flag, do not set window title etc */
else set_modify(0);
if(fast) set_modify(2); /* only clear modified flag, no title/tab/sim buttons update */
else set_modify(0);
}
tclvareval(xctx->top_path, ".menubar entryconfigure Simulate -background $simulate_bg", NULL);
tclvareval("set tctx::", xctx->current_win_path, "_simulate $simulate_bg", NULL);
@ -5070,7 +5068,7 @@ void descend_symbol(void)
if(xctx->modified)
{
int ret;
ret = save(1);
ret = save(1, 1);
/* if circuit is changed but not saved before descending
* state will be inconsistent when returning, can not propagare hilights
* save() return value:

View File

@ -877,14 +877,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
int i = atoi(argv[2]);
setup_graph_data(i, 0, &xctx->graph_struct);
if(argc > 3) {
flags = atoi(argv[3]);
} else {
/* 2: draw cursor 1
* 4: draw cursor 2 */
flags = 1 + 8 + (xctx->graph_flags & (2 + 4));
* 4: draw cursor 2
* 128: draw hcursor 1
* 256: draw hcursor 2 */
flags = 1 + 8 + (xctx->graph_flags & (2 + 4 + 128 + 256));
}
setup_graph_data(i, 0, &xctx->graph_struct);
draw_graph(i, flags, &xctx->graph_struct, NULL);
}
Tcl_ResetResult(interp);
@ -914,7 +916,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
rebuild_selected_array();
if(xctx->lastsel==0 ) {
save_schematic(xctx->sch[xctx->currsch]); /* sync data with disk file before editing file */
save_schematic(xctx->sch[xctx->currsch], 0); /* sync data with disk file before editing file */
my_snprintf(name, S(name), "edit_file {%s}",
abs_sym_path(xctx->sch[xctx->currsch], ""));
tcleval(name);
@ -2815,7 +2817,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f);
my_strncpy(f, tclresult(), S(f));
if(force || !has_x || !xctx->modified || save(1) != -1 ) { /* save(1)==-1 --> user cancel */
if(force || !has_x || !xctx->modified || save(1, 0) != -1 ) { /* save(1)==-1 --> user cancel */
char win_path[WINDOW_PATH_SIZE];
int skip = 0;
dbg(1, "scheduler(): load: filename=%s\n", argv[2]);
@ -3049,7 +3051,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(has_x) tcleval("tk_messageBox -type okcancel -parent [xschem get topwindow] "
"-message {do you want to make symbol view ?}");
if(!has_x || strcmp(tclresult(), "ok")==0) {
save_schematic(xctx->sch[xctx->currsch]);
save_schematic(xctx->sch[xctx->currsch], 0);
make_symbol();
}
Tcl_ResetResult(interp);
@ -4590,16 +4592,23 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else { cmd_found = 0;}
break;
case 's': /*----------------------------------------------*/
/* save
* Save schematic if modified. Does not ask confirmation! */
/* save [fast]
* Save schematic if modified. Does not ask confirmation!
* if 'fast' is given it is passed to save_schematic() to avoid
* updating window/tab/sim button states */
if(!strcmp(argv[1], "save"))
{
int fast = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
dbg(1, "scheduler(): saving: current schematic\n");
for(i = 2; i < argc; i++) {
if(!strcmp(argv[i], "fast")) fast |= 1;
}
if(!strcmp(xctx->sch[xctx->currsch], "")) { /* check if unnamed schematic, use saveas in this case... */
saveas(NULL, SCHEMATIC);
} else {
save(0);
save(0, fast);
}
}
@ -4745,6 +4754,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* for all other objects 'id' is the position in the respective arrays
* if 'clear' is specified does an unselect operation
* if 'fast' is specified avoid sending information to infowindow and status bar
* if 'nodraw' is given on select instance do not draw selection
* returns 1 if something selected, 0 otherwise */
else if(!strcmp(argv[1], "select"))
{
@ -4766,7 +4776,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
int i;
for(i = 4; i < argc; i++) {
if(!strcmp(argv[i], "clear")) sel = 0;
if(!strcmp(argv[i], "fast")) fast = 1;
if(!strcmp(argv[i], "fast")) fast |= 1;
if(!strcmp(argv[i], "nodraw") && !strcmp(argv[2], "instance")) fast |= 2;
}
}
if(!strcmp(argv[2], "instance") && argc > 3) {

View File

@ -937,6 +937,10 @@ void select_wire(int i,unsigned short select_mode, int fast)
xctx->need_reb_sel_arr=1;
}
/* fast == 1: do not update status line
* fast == 2: do not draw / undraw selected elements
* fast == 3: 1 + 2
*/
void select_element(int i,unsigned short select_mode, int fast, int override_lock)
{
int c, j;
@ -946,7 +950,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
if(!strboolcmp(get_tok_value(xctx->inst[i].prop_ptr, "lock", 0), "true") &&
select_mode == SELECTED && !override_lock) return;
my_strncpy(s,xctx->inst[i].prop_ptr!=NULL?xctx->inst[i].prop_ptr:"<NULL>",S(s));
if( !fast )
if( !(fast & 1) )
{
my_snprintf(str, S(str), "Info: selected element %d: %s\nproperties:\n%s", i,
xctx->inst[i].name ? xctx->inst[i].name : "<NULL>" , s);
@ -976,7 +980,7 @@ void select_element(int i,unsigned short select_mode, int fast, int override_loc
}
xctx->inst[i].sel = select_mode;
if(select_mode == SELECTED) set_first_sel(ELEMENT, i, 0);
if(!fast) {
if(!(fast & 2) ) {
if(select_mode) {
for(c=0;c<cadlayers; ++c) {
draw_temp_symbol(ADD, xctx->gc[SELLAYER], i,c,0,0,0.0,0.0);

View File

@ -484,7 +484,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->extra_idx = 0;
xctx->extra_prev_idx = 0;
xctx->extra_raw_n = 0;
xctx->graph_master = 0;
xctx->graph_master = -1;
xctx->graph_cursor1_x = 0;
xctx->graph_cursor2_x = 0;
xctx->graph_flags = 0;

View File

@ -888,6 +888,7 @@ typedef struct {
int logx, logy;
int rainbow; /* draw multiple datasets with incrementing colors */
double linewidth_mult; /* multiply factor for waveforms line width */
double hcursor1_y, hcursor2_y; /* hcursor positions */
} Graph_ctx;
typedef struct {
@ -1310,7 +1311,7 @@ extern void new_xschem_process(const char *cell, int symbol);
extern void ask_new_file(void);
extern void saveas(const char *f, int type);
extern const char *get_file_path(char *f);
extern int save(int confirm);
extern int save(int confirm, int fast);
extern void save_ascii_string(const char *ptr, FILE *fd, int newline);
extern Hilight_hashentry *bus_hilight_hash_lookup(const char *token, int value, int what) ;
/* wrapper function to hash highlighted instances, avoid clash with net names */
@ -1496,7 +1497,7 @@ extern int sym_vs_sch_pins(int all);
extern char *get_generator_command(const char *str);
extern int match_symbol(const char name[]);
extern Sch_pin_record *sort_schematic_pins(int *npins);
extern int save_schematic(const char *); /* 20171020 added return value */
extern int save_schematic(const char *, int fast); /* 20171020 added return value */
extern void copy_symbol(xSymbol *dest_sym, xSymbol *src_sym);
extern void push_undo(void);
extern void pop_undo(int redo, int set_modify_status);

View File

@ -1785,16 +1785,17 @@ proc cellview_setlabels {w symbol sym_sch default_sch sym_spice_sym_def} {
$w configure -bg [option get . background {}]
if { $sym_spice_sym_def ne {}} {
$w configure -fg $symfg
} elseif { ![file exists [abs_sym_path [$w get]]] } {
$w configure -bg $missingbg
} else {
if {[$w get] eq $default_sch} {
# ....
puts "need to clear schematic attr in symbol"
} elseif {[$w get] eq $sym_sch} {
$w configure -bg $symbg
} else {
puts "need to update:[$w get] --> $sym_sch"
}
if { ![file exists [abs_sym_path [$w get]]] } {
$w configure -bg $missingbg
}
}
}
@ -1904,7 +1905,7 @@ proc traversal_setlabels {w parent_sch instname inst_sch sym_sch default_sch ins
xschem setprop instance $instname schematic [$w get] fast ;# set schematic attr on instance
}
xschem set_modify 3 ;# set only modified flag to force a save, do not update window/tab titles
xschem save
xschem save fast
set inst_sch [$w get]
# puts "inst_sch set to: $inst_sch"
xschem load $current noundoreset nodraw
@ -2083,7 +2084,7 @@ proc hier_traversal {{level 0} {only_subckts 0} {all_hierarchy 1}} {
set done_print 1
if {$type eq {subcircuit} && $all_hierarchy} {
xschem select instance $i fast
xschem select instance $i fast nodraw
set descended [xschem descend 1 6]
if {$descended} {
incr level
@ -6570,7 +6571,7 @@ proc swap_compare_schematics {} {
}
proc input_line {txt {cmd {}} {preset {}} {w 12}} {
global wm_fix retval
set retval {}
set retval $preset
if { [winfo exists .dialog] } {return}
xschem set semaphore [expr {[xschem get semaphore] +1}]
toplevel .dialog -class Dialog

View File

@ -53,10 +53,12 @@ color="8 6"
linewidth_mult=1.0
hilight_wave=-1
dataset=-1
dataset=188
rawfile=$netlist_dir/autozero_comp.raw
sim_type=tran
rainbow=0}
rainbow=0
hcursor1_y=0.13350312
hcursor2_y=0.58853305}
B 2 270 -1160 680 -1030 {flags=graph,unlocked
y1 = 0.647319
y2 = 0.652563
@ -135,6 +137,27 @@ saout
sweep="freq0 freq1 freq0"
mode=HistoH
xlabmag=2.0}
B 2 270 -1610 680 -1450 {flags=graph,unlocked
y1 = 0
y2 = 0.9
divy = 5
x1=1.9099218e-07
x2=3.4920522e-07
divx=5
subdivx=4
unitx=n
node="zero0
zero1
zero2"
color="12 4 7"
linewidth_mult=0.1
hilight_wave=-1
rawfile=$netlist_dir/autozero_comp.raw
sim_type=tran
rainbow=0
dataset=235}
T {CAL} 140 -180 0 1 0.4 0.4 {}
T {EN} 140 -130 0 1 0.4 0.4 {}
T {CALIBRATION