add command "xschem select_dangling_nets" that selects all labels/wires that are not connected to any non-label/non-probe components

This commit is contained in:
stefan schippers 2023-09-14 00:57:13 +02:00
parent afd25cf430
commit 75e5d3d5b0
4 changed files with 178 additions and 43 deletions

View File

@ -496,6 +496,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
@ -1078,6 +1081,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
if 'clear' is specified does an unselect operation </pre>
<li><kbd> select_all</kbd></li><pre>
Selects all objects in schematic </pre>
<li><kbd> select_dangling_nets </kbd></li><pre>
Select all nets/labels that are dangling, ie not attached to any non pin/port/probe components
Returns 1 if danglings found, 0 otherwise </pre>
<li><kbd> select_hilight_net</kbd></li><pre>
Select all highlight objects (wires, labels, pins, instances) </pre>
<li><kbd> selected_set</kbd></li><pre>

View File

@ -1768,8 +1768,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
* returns pin_name x y */
xSymbol *symbol;
xRect *rct;
short flip, rot;
double x0,y0, pinx0, piny0;
double pinx0, piny0;
char num[60];
int p, i, no_of_pins, slot;
const char *pin;
@ -1785,10 +1784,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, "", TCL_STATIC);
return TCL_OK;
}
x0 = xctx->inst[i].x0;
y0 = xctx->inst[i].y0;
rot = xctx->inst[i].rot;
flip = xctx->inst[i].flip;
symbol = xctx->sym + xctx->inst[i].ptr;
no_of_pins= symbol->rects[PINLAYER];
rct=symbol->rect[PINLAYER];
@ -1810,11 +1805,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, "", TCL_STATIC);
return TCL_OK;
}
pinx0 = (rct[p].x1+rct[p].x2)/2;
piny0 = (rct[p].y1+rct[p].y2)/2;
ROTATION(rot, flip, 0.0, 0.0, pinx0, piny0, pinx0, piny0);
pinx0 += x0;
piny0 += y0;
get_inst_pin_coord(i, p, &pinx0, &piny0);
my_snprintf(num, S(num), "{%s} %g %g", get_tok_value(rct[p].prop_ptr, "name", 0), pinx0, piny0);
Tcl_SetResult(interp, num, TCL_VOLATILE);
my_free(_ALLOC_ID_, &tmpstr);
@ -1869,8 +1860,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
/* xschem instances_to_net PLUS */
xSymbol *symbol;
xRect *rct;
short flip, rot;
double x0,y0, pinx0, piny0, rpinx0, rpiny0;
double pinx0, piny0;
char *pins = NULL;
int p, i, no_of_pins;
prepare_netlist_structs(0);
@ -1879,10 +1869,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
return TCL_ERROR;
}
for(i = 0;i < xctx->instances; ++i) {
x0 = xctx->inst[i].x0;
y0 = xctx->inst[i].y0;
rot = xctx->inst[i].rot;
flip = xctx->inst[i].flip;
symbol = xctx->sym + xctx->inst[i].ptr;
no_of_pins= symbol->rects[PINLAYER];
rct=symbol->rect[PINLAYER];
@ -1894,13 +1880,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(xctx->inst[i].node[p] && !strcmp(xctx->inst[i].node[p], argv[2]) &&
!IS_LABEL_SH_OR_PIN( (xctx->inst[i].ptr+xctx->sym)->type )) {
my_mstrcat(_ALLOC_ID_, &pins, "{ {", xctx->inst[i].instname, "} {", pin, NULL);
pinx0 = (rct[p].x1+rct[p].x2)/2;
piny0 = (rct[p].y1+rct[p].y2)/2;
ROTATION(rot, flip, 0.0, 0.0, pinx0, piny0, rpinx0, rpiny0);
rpinx0 += x0;
rpiny0 += y0;
my_strncpy(xx, dtoa(rpinx0), S(xx));
my_strncpy(yy, dtoa(rpiny0), S(yy));
get_inst_pin_coord(i, p, &pinx0, &piny0);
my_strncpy(xx, dtoa(pinx0), S(xx));
my_strncpy(yy, dtoa(piny0), S(yy));
my_mstrcat(_ALLOC_ID_, &pins, "} {", xx, "} {", yy, "} } ", NULL);
}
}
@ -3311,6 +3293,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* select_dangling_nets
* Select all nets/labels that are dangling, ie not attached to any non pin/port/probe components
* Returns 1 if danglings found, 0 otherwise */
else if(!strcmp(argv[1], "select_dangling_nets"))
{
int r;
r = select_dangling_nets();
Tcl_SetResult(interp, my_itoa(r), TCL_VOLATILE);
}
/* select_hilight_net
* Select all highlight objects (wires, labels, pins, instances) */
else if(!strcmp(argv[1], "select_hilight_net"))

View File

@ -80,30 +80,165 @@ static void check_connected_wire(int stop_at_junction, int n)
}
}
#if 0
int select_dangling_labels(void)
int select_dangling_nets(void)
{
int i;
char * type;
for(i = 0; i < xctx->instances; i++) {
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];
}
int i, p, w, touches, rects, done;
int ret = 0; /* return code: 1: dangling elements found */
int *table = NULL;
xRect *rct;
xWire * const wire = xctx->wire;
Instentry *instptr;
Wireentry *wireptr;
Iterator_ctx ctx;
char *type;
double x0, y0, x1, y1, x2, y2;
table = my_calloc(_ALLOC_ID_, xctx->wires, sizeof(int));
hash_instances();
hash_wires();
/* Mark nets connected to non pin/label/probe components as NOT dangling (table[w] = 1) */
for(w = 0; w < xctx->wires; w++) {
x1 = xctx->wire[w].x1;
y1 = xctx->wire[w].y1;
x2 = xctx->wire[w].x2;
y2 = xctx->wire[w].y2;
RECTORDER(x1, y1, x2, y2);
for(init_inst_iterator(&ctx, x1, y1, x2, y2); (instptr = inst_iterator_next(&ctx)) ;) {
i = instptr->n;
type = (xctx->inst[i].ptr+ xctx->sym)->type;
rct=(xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER];
if(!rct) continue;
if( type && (!strcmp(type, "label") || !strcmp(type, "probe") )) {
continue;
}
rects = (xctx->inst[i].ptr + xctx->sym)->rects[PINLAYER];
for(p = 0; p < rects; p++)
{
get_inst_pin_coord(i, p, &x0, &y0);
touches = touch(xctx->wire[w].x1, xctx->wire[w].y1, xctx->wire[w].x2, xctx->wire[w].y2, x0, y0);
if(touches) {
table[w] = 1; /* wire[w] is NOT dangling */
dbg(0, "wire %d touches inst %d\n", w, i);
}
}
}
}
return 0;
/* Propagate NOT dangling nets to other nets */
done = 0;
while(!done) {
done = 1;
for(w = 0; w < xctx->wires; w++) {
if(table[w] == 0) continue;
/* wire[w] is not dangling */
x1 = xctx->wire[w].x1;
y1 = xctx->wire[w].y1;
x2 = xctx->wire[w].x2;
y2 = xctx->wire[w].y2;
RECTORDER(x1, y1, x2, y2);
for(init_wire_iterator(&ctx, x1, y1, x2, y2); (wireptr = wire_iterator_next(&ctx)) ;) {
i = wireptr->n;
if(i == w) continue;
if(table[i]) continue;
touches = touch(wire[w].x1, wire[w].y1, wire[w].x2, wire[w].y2, wire[i].x1, wire[i].y1) ||
touch(wire[w].x1, wire[w].y1, wire[w].x2, wire[w].y2, wire[i].x2, wire[i].y2) ||
touch(wire[i].x1, wire[i].y1, wire[i].x2, wire[i].y2, wire[w].x1, wire[w].y1) ||
touch(wire[i].x1, wire[i].y1, wire[i].x2, wire[i].y2, wire[w].x2, wire[w].y2);
if(touches) {
table[i] = 1; /* wire[i] also not dangling */
done = 0;
}
}
}
}
/* Select all nets that are dangling */
for(w = 0; w < xctx->wires; w++) {
if(!table[w]) {
xctx->wire[w].sel = SELECTED;
ret = 1;
}
}
/* select pins/labels/probes attached to dangling nets */
for(w = 0; w < xctx->wires; w++) {
x1 = xctx->wire[w].x1;
y1 = xctx->wire[w].y1;
x2 = xctx->wire[w].x2;
y2 = xctx->wire[w].y2;
RECTORDER(x1, y1, x2, y2);
for(init_inst_iterator(&ctx, x1, y1, x2, y2); (instptr = inst_iterator_next(&ctx)) ;) {
i = instptr->n;
type = (xctx->inst[i].ptr+ xctx->sym)->type;
if( type && (!strcmp(type, "label") || !strcmp(type, "probe") )) {
rct = (xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER];
if(!rct) continue;
get_inst_pin_coord(i, 0, &x0, &y0);
touches = touch(xctx->wire[w].x1, xctx->wire[w].y1, xctx->wire[w].x2, xctx->wire[w].y2, x0, y0);
if(touches && table[w] == 0) {
xctx->inst[i].sel = SELECTED;
ret = 1;
}
}
}
}
/* select dangling labels/probes (not connected to anything) */
for(i = 0; i < xctx->instances; i++) {
int dangling = 1;
type = (xctx->inst[i].ptr+ xctx->sym)->type;
if( type && (!strcmp(type, "label") || !strcmp(type, "probe")) ) {
int sqx, sqy;
rct = (xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER];
if(!rct) continue;
get_inst_pin_coord(i, 0, &x0, &y0);
get_square(x0, y0, &sqx, &sqy);
wireptr = xctx->wire_spatial_table[sqx][sqy];
while (wireptr) {
int n = wireptr->n;
if (touch(xctx->wire[n].x1, xctx->wire[n].y1, xctx->wire[n].x2, xctx->wire[n].y2, x0, y0)) {
dangling = 0; /* inst[i] connected to a wire */
}
wireptr = wireptr->next;
}
instptr = xctx->inst_spatial_table[sqx][sqy];
while(instptr) {
int n = instptr->n;
if(n == i) goto cont2;
type = (xctx->inst[n].ptr+ xctx->sym)->type;
if( type && (!strcmp(type, "label") || !strcmp(type, "probe")) ) {
goto cont2;
}
rct = (xctx->inst[n].ptr+ xctx->sym)->rect[PINLAYER];
if(!rct) goto cont2;
rects = (xctx->inst[n].ptr + xctx->sym)->rects[PINLAYER];
for(p = 0; p < rects; p++)
{
get_inst_pin_coord(n, p, &x1, &y1);
touches = (x0 == x1 && y0 == y1);
if(touches) {
dangling = 0; /* inst[i] connected to non label/probe inst[n] */
}
}
cont2:
instptr = instptr->next;
}
if(dangling) {
xctx->inst[i].sel = SELECTED;
ret = 1;
}
}
}
/* draw selection */
xctx->need_reb_sel_arr = 1;
rebuild_selected_array();
draw_selection(xctx->gc[SELLAYER], 0);
my_free(_ALLOC_ID_, &table);
return ret;
}
#endif
/* stop_at_junction==1 --> stop selecting wires at 'T' junctions */
void select_connected_wires(int stop_at_junction)

View File

@ -1259,6 +1259,8 @@ extern unsigned short select_object(double mx,double my, unsigned short sel_mode
extern void unselect_all(int dr);
extern void select_attached_nets(void);
extern void select_inside(double x1,double y1, double x2, double y2, int sel);
/* Select all nets that are dangling, ie not attached to any non pin/port/probe components */
extern int select_dangling_nets(void);
extern int Tcl_AppInit(Tcl_Interp *interp);
extern void abort_operation(void);
extern int callback(const char *winpath, int event, int mx, int my, KeySym key,