"xschem connected_nets" command now works for any selected instance, not only labels/probes/pins. Argument can be 0, 1, 2 (2-->select only wire segments drectly attached to selected net/instance)

This commit is contained in:
stefan schippers 2023-09-14 09:48:12 +02:00
parent 34946c2f0a
commit e0bcc302c9
5 changed files with 98 additions and 87 deletions

View File

@ -500,8 +500,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
@ -556,9 +554,11 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> compare_schematics [sch_file]</kbd></li><pre>
Compare currently loaded schematic with another 'sch_file' schematic.
if no file is given prompt user to choose one </pre>
<li><kbd> connected_nets [1|0]</kbd></li><pre>
Select nets connected to currently selected net or net label/pin.
if '1' argument is given, stop at wire junctions </pre>
<li><kbd> connected_nets [0|1|2|3]</kbd></li><pre>
Select nets/labels connected to currently selected instance
if '1' argument is given, stop at wire junctions
if '2' argument is given select only wires directly attached to selected instance/net
if '3' argument is given combine '1' and '2' </pre>
<li><kbd> copy</kbd></li><pre>
Copy selection to clipboard </pre>
<li><kbd> copy_objects</kbd></li><pre>
@ -1284,6 +1284,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"

View File

@ -2416,7 +2416,7 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
if(button == Button3 && state == ControlMask && xctx->semaphore <2)
{
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0);
if(sel) select_connected_wires(1);
if(sel) select_connected_nets(1);
}
else if(button == Button3 && state == Mod1Mask && xctx->semaphore <2)
{
@ -2425,7 +2425,7 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
else if(button == Button3 && state == ShiftMask && xctx->semaphore <2)
{
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0);
if(sel) select_connected_wires(0);
if(sel) select_connected_nets(0);
}
else if(button == Button3 && state == 0 && xctx->semaphore <2) {
int ret;

View File

@ -477,14 +477,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
}
/* connected_nets [1|0]
* Select nets connected to currently selected net or net label/pin.
* if '1' argument is given, stop at wire junctions */
/* connected_nets [0|1|2|3]
* Select nets/labels connected to currently selected instance
* if '1' argument is given, stop at wire junctions
* if '2' argument is given select only wires directly attached to selected instance/net
* if '3' argument is given combine '1' and '2' */
else if(!strcmp(argv[1], "connected_nets"))
{
int stop_at_junction = 0;
if(argc > 2 && argv[2][0] == '1') stop_at_junction = 1;
select_connected_wires(stop_at_junction);
if(argc > 2 ) stop_at_junction = atoi(argv[2]);
select_connected_nets(stop_at_junction);
Tcl_ResetResult(interp);
}

View File

@ -22,10 +22,12 @@
#include "xschem.h"
/* select all nets and pins/labels that are *physically* connected to current selected wire segments */
/* stop_at_junction==1 --> stop selecting wires at 'T' junctions */
/* Recursive routine */
static void check_connected_wire(int stop_at_junction, int n)
/* select all nets and pins/labels that are *physically* connected to current selected wire segments
* stop_at_junction==1 --> stop selecting wires at 'T' junctions
* stop_at_junction==2 --> select only wires directly attached to selected net/instance
* Recursive routine
*/
static void check_connected_nets(int stop_at_junction, int n)
{
int k, touches;
xWire * const wire = xctx->wire;
@ -40,7 +42,7 @@ static void check_connected_wire(int stop_at_junction, int n)
x2 = wire[n].x2;
y2 = wire[n].y2;
RECTORDER(x1, y1, x2, y2);
dbg(1, "check_connected_wire(): n=%d, %g %g %g %g\n", n, x1, y1, x2, y2);
dbg(1, "check_connected_nets(): n=%d, %g %g %g %g\n", n, x1, y1, x2, y2);
for(init_inst_iterator(&ctx, x1, y1, x2, y2); (instptr = inst_iterator_next(&ctx)) ;) {
k = instptr->n;
type = (xctx->inst[k].ptr+ xctx->sym)->type;
@ -58,28 +60,83 @@ static void check_connected_wire(int stop_at_junction, int n)
}
}
}
for(init_wire_iterator(&ctx, x1, y1, x2, y2); (wireptr = wire_iterator_next(&ctx)) ;) {
k = wireptr->n;
if(n == k || xctx->wire[k].sel == SELECTED) continue;
if(!stop_at_junction) {
touches = touch(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, wire[k].x1, wire[k].y1) ||
touch(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, wire[k].x2, wire[k].y2) ||
touch(wire[k].x1, wire[k].y1, wire[k].x2, wire[k].y2, wire[n].x1, wire[n].y1) ||
touch(wire[k].x1, wire[k].y1, wire[k].x2, wire[k].y2, wire[n].x2, wire[n].y2);
} else {
touches = (wire[n].x1 == wire[k].x1 && wire[n].y1 == wire[k].y1 && wire[n].end1 < 2 && wire[k].end1 < 2) ||
(wire[n].x1 == wire[k].x2 && wire[n].y1 == wire[k].y2 && wire[n].end1 < 2 && wire[k].end2 < 2) ||
(wire[n].x2 == wire[k].x1 && wire[n].y2 == wire[k].y1 && wire[n].end2 < 2 && wire[k].end1 < 2) ||
(wire[n].x2 == wire[k].x2 && wire[n].y2 == wire[k].y2 && wire[n].end2 < 2 && wire[k].end2 < 2);
}
if(touches) {
xctx->need_reb_sel_arr=1;
xctx->wire[k].sel = SELECTED;
check_connected_wire(stop_at_junction, k); /* recursive check */
if(!(stop_at_junction & 2)) {
for(init_wire_iterator(&ctx, x1, y1, x2, y2); (wireptr = wire_iterator_next(&ctx)) ;) {
k = wireptr->n;
if(n == k || xctx->wire[k].sel == SELECTED) continue;
if((stop_at_junction & 1)== 0) {
touches = touch(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, wire[k].x1, wire[k].y1) ||
touch(wire[n].x1, wire[n].y1, wire[n].x2, wire[n].y2, wire[k].x2, wire[k].y2) ||
touch(wire[k].x1, wire[k].y1, wire[k].x2, wire[k].y2, wire[n].x1, wire[n].y1) ||
touch(wire[k].x1, wire[k].y1, wire[k].x2, wire[k].y2, wire[n].x2, wire[n].y2);
} else {
touches = (wire[n].x1 == wire[k].x1 && wire[n].y1 == wire[k].y1 && wire[n].end1 < 2 && wire[k].end1 < 2) ||
(wire[n].x1 == wire[k].x2 && wire[n].y1 == wire[k].y2 && wire[n].end1 < 2 && wire[k].end2 < 2) ||
(wire[n].x2 == wire[k].x1 && wire[n].y2 == wire[k].y1 && wire[n].end2 < 2 && wire[k].end1 < 2) ||
(wire[n].x2 == wire[k].x2 && wire[n].y2 == wire[k].y2 && wire[n].end2 < 2 && wire[k].end2 < 2);
}
if(touches) {
xctx->wire[k].sel = SELECTED;
check_connected_nets(stop_at_junction, k); /* recursive check */
}
}
}
}
/* stop_at_junction==1 --> stop selecting wires at 'T' junctions
* stop_at_junction==2 --> select only wires directly attached to selected net/instance
*/
void select_connected_nets(int stop_at_junction)
{
int i, n;
if(stop_at_junction & 1) trim_wires();
hash_wires();
hash_instances();
rebuild_selected_array(); /* does nothing as already done in most of use cases */
for(n=0; n<xctx->lastsel; ++n) {
i = xctx->sel_array[n].n;
switch(xctx->sel_array[n].type) {
double x0, y0;
int sqx, sqy, p, rects;
Wireentry *wptr;
case WIRE:
if(xctx->wire[i].sel == SELECTED) check_connected_nets(stop_at_junction, i);
break;
case ELEMENT:
rects = (xctx->inst[i].ptr + xctx->sym)->rects[PINLAYER];
for(p = 0; p < rects; p++)
{
get_inst_pin_coord(i, p, &x0, &y0);
get_square(x0, y0, &sqx, &sqy);
wptr = xctx->wire_spatial_table[sqx][sqy];
while (wptr) {
dbg(1, "select_connected_nets(): x0=%g y0=%g wire[%d]=%g %g %g %g\n",
x0, y0, wptr->n, xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2);
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0)) {
xctx->wire[wptr->n].sel = SELECTED;
check_connected_nets(stop_at_junction, wptr->n);
}
wptr=wptr->next;
}
} /* for(p...) */
break;
default:
break;
} /* switch(...) */
} /* for(... lastsel ...) */
xctx->need_reb_sel_arr=1;
rebuild_selected_array();
draw_selection(xctx->gc[SELLAYER], 0);
}
int select_dangling_nets(void)
{
int netlist_lvs_ignore=tclgetboolvar("lvs_ignore");
@ -243,57 +300,6 @@ int select_dangling_nets(void)
return ret;
}
/* stop_at_junction==1 --> stop selecting wires at 'T' junctions */
void select_connected_wires(int stop_at_junction)
{
int i, n;
if(stop_at_junction) trim_wires();
hash_wires();
hash_instances();
rebuild_selected_array(); /* does nothing as already done in most of use cases */
for(n=0; n<xctx->lastsel; ++n) {
i = xctx->sel_array[n].n;
switch(xctx->sel_array[n].type) {
char *type;
case WIRE:
if(xctx->wire[i].sel == SELECTED) check_connected_wire(stop_at_junction, i);
break;
case ELEMENT:
type = (xctx->inst[i].ptr+ xctx->sym)->type;
if( type && (IS_LABEL_SH_OR_PIN(type) || !strcmp(type, "probe") )) {
double x0, y0;
int sqx, sqy;
xRect *rct;
Wireentry *wptr;
rct = (xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER];
if(rct) {
get_inst_pin_coord(i, 0, &x0, &y0);
get_square(x0, y0, &sqx, &sqy);
wptr = xctx->wire_spatial_table[sqx][sqy];
while (wptr) {
dbg(1, "select_connected_wires(): x0=%g y0=%g wire[%d]=%g %g %g %g\n",
x0, y0, wptr->n, xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2);
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0)) {
xctx->wire[wptr->n].sel = SELECTED;
check_connected_wire(stop_at_junction, wptr->n);
}
wptr=wptr->next;
}
} /* if(rct) */
} /* if(type & ...) */
break;
default:
break;
} /* switch(...) */
} /* for(... lastsel ...) */
rebuild_selected_array();
draw_selection(xctx->gc[SELLAYER], 0);
}
void symbol_bbox(int i, double *x1,double *y1, double *x2, double *y2)
{
int j, tmp;

View File

@ -1537,7 +1537,7 @@ extern void logic_set(int v, int num, const char *net_name);
extern int hilight_netname(const char *name);
extern void unhilight_net();
extern void propagate_hilights(int set, int clear, int mode);
extern void select_connected_wires(int stop_at_junction);
extern void select_connected_nets(int stop_at_junction);
extern char *resolved_net(const char *net);
extern void draw_hilight_net(int on_window);
extern void display_hilights(int what, char **str);