improve connect by kissing: now 3 move operations are present: 1) just move selection, 2) move adding wires to connected pins/wire endpoints, 3) move by stretching wires attached to pins/endpoints to follow moving objects

This commit is contained in:
stefan schippers 2023-09-18 13:29:49 +02:00
parent 690486c848
commit 98ffd177ce
7 changed files with 156 additions and 57 deletions

View File

@ -168,8 +168,9 @@ alt+shift 'l' add lab_wire.sym to schematic
alt 'l' add lab_pin.sym to schematic
ctrl+shift 'o' Load most recent schematic
ctrl 'o' Load schematic
- 'm' Move selected obj.
shift 'M' Move selected obj, insert wire when separating touching instance pins.
- 'm' Move selected objects
ctrl 'm' Move selected objects, stretching wires attached to them
shift 'M' Move selected objects, insert wire when separating touching instance pins/wires
Stretch wires that land on selected instance pins.
shift 'N' Top level only netlist
- 'n' Hierarchical Netlist

View File

@ -965,6 +965,7 @@ void enable_layers(void)
}
}
/* Add wires when moving instances or wires */
short connect_by_kissing(void)
{
xSymbol *symbol;
@ -977,16 +978,22 @@ short connect_by_kissing(void)
Wireentry *wptr;
Instpinentry *iptr;
int sqx, sqy;
Str_hashtable coord_table = {NULL, 0}; /* hash table to add new wires at a given position only once */
char coord[200]; /* string representation of 'x0 y0' or 'pinx0 piny0' */
str_hash_init(&coord_table, HASHSIZE);
rebuild_selected_array();
k = xctx->lastsel;
prepare_netlist_structs(0);
/* add wires to moving instance pins */
for(j=0;j<k; ++j) if(xctx->sel_array[j].type==ELEMENT) {
x0 = xctx->inst[xctx->sel_array[j].n].x0;
y0 = xctx->inst[xctx->sel_array[j].n].y0;
rot = xctx->inst[xctx->sel_array[j].n].rot;
flip = xctx->inst[xctx->sel_array[j].n].flip;
symbol = xctx->sym + xctx->inst[xctx->sel_array[j].n].ptr;
int inst = xctx->sel_array[j].n;
x0 = xctx->inst[inst].x0;
y0 = xctx->inst[inst].y0;
rot = xctx->inst[inst].rot;
flip = xctx->inst[inst].flip;
symbol = xctx->sym + xctx->inst[inst].ptr;
npin = symbol->rects[PINLAYER];
rct=symbol->rect[PINLAYER];
for(i=0;i<npin; ++i) {
@ -1001,7 +1008,7 @@ short connect_by_kissing(void)
kissing=0;
while(iptr) {
ii = iptr->n;
if(ii == xctx->sel_array[j].n) {
if(ii == inst) {
iptr = iptr->next;
continue;
}
@ -1018,7 +1025,7 @@ short connect_by_kissing(void)
kissing=0;
break;
}
else if( (pinx0 != w->x1 || piny0 != w->y1) && (pinx0 != w->x2 || piny0 != w->y2)) {
else {
kissing = 1;
break;
}
@ -1027,17 +1034,85 @@ short connect_by_kissing(void)
}
if(kissing) {
dbg(1, "connect_by_kissing(): adding wire in %g %g, wires before = %d\n", pinx0, piny0, xctx->wires);
if(!done_undo) {
xctx->push_undo();
done_undo = 1;
}
storeobject(-1, pinx0, piny0, pinx0, piny0, WIRE, 0, SELECTED1, NULL);
changed = 1;
xctx->need_reb_sel_arr = 1;
my_snprintf(coord, S(coord), "%.16g %.16g", pinx0, piny0);
if (str_hash_lookup(&coord_table, coord, "", XLOOKUP)==NULL) {
dbg(1, "connect_by_kissing(): adding wire in %g %g, wires before = %d\n", pinx0, piny0, xctx->wires);
str_hash_lookup(&coord_table, coord, "", XINSERT);
storeobject(-1, pinx0, piny0, pinx0, piny0, WIRE, 0, SELECTED1, NULL);
changed = 1;
xctx->need_reb_sel_arr = 1;
}
}
}
}
/* add wires to moving wire endpoints */
for(j=0; j < k; ++j) if(xctx->sel_array[j].type == WIRE) {
int wire = xctx->sel_array[j].n;
if(xctx->wire[wire].sel != SELECTED) continue; /* skip partially selected wires */
for(i=0;i<2; ++i) {
if(i == 0) {
x0 = xctx->wire[wire].x1;
y0 = xctx->wire[wire].y1;
} else {
x0 = xctx->wire[wire].x2;
y0 = xctx->wire[wire].y2;
}
get_square(x0, y0, &sqx, &sqy);
iptr=xctx->instpin_spatial_table[sqx][sqy];
wptr=xctx->wire_spatial_table[sqx][sqy];
kissing=0;
while(iptr) {
ii = iptr->n;
dbg(1, "connect_by_kissing(): ii=%d, x0=%g, y0=%g, iptr->x0=%g, iptr->y0=%g\n",
ii, x0, y0, iptr->x0, iptr->y0);
if( iptr->x0 == x0 && iptr->y0 == y0 && xctx->inst[ii].sel == 0) {
kissing=1;
break;
}
iptr = iptr->next;
}
while(wptr) {
xWire *w = &xctx->wire[wptr->n];
if(wire == wptr->n) {
wptr = wptr->next;
continue;
}
if( touch(w->x1, w->y1, w->x2, w->y2, x0, y0)) {
if( w->sel) {
kissing=0;
break;
}
else {
kissing = 1;
break;
}
}
wptr = wptr->next;
}
if(kissing) {
if(!done_undo) {
xctx->push_undo();
done_undo = 1;
}
my_snprintf(coord, S(coord), "%.16g %.16g", x0, y0);
if (str_hash_lookup(&coord_table, coord, "", XLOOKUP)==NULL) {
dbg(1, "connect_by_kissing(): adding wire in %g %g, wires before = %d\n", x0, y0, xctx->wires);
str_hash_lookup(&coord_table, coord, "", XINSERT);
storeobject(-1, x0, y0, x0, y0, WIRE, 0, SELECTED1, NULL);
changed = 1;
xctx->need_reb_sel_arr = 1;
}
}
}
}
str_hash_free(&coord_table);
rebuild_selected_array();
return changed;
}

View File

@ -2177,10 +2177,19 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
tclsetintvar("connect_by_kissing", 2); /* 2 will be used to reset var to 0 at end of move */
select_attached_nets(); /* stretch nets that land on selected instance pins */
/* select_attached_nets(); */ /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
break;
}
if(key=='m' && state==ControlMask && !(xctx->ui_state & (STARTMOVE | STARTCOPY))) /* move selection */
{
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
select_attached_nets(); /* stretch nets that land on selected instance pins */
move_objects(START,0,0,0);
break;
}
if(key=='c' && state==0 && /* duplicate selection */
!(xctx->ui_state & (STARTMOVE | STARTCOPY)))
{
@ -2636,7 +2645,7 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
/* stretch nets that land on selected instance pins if connect_by_kissing == 2 */
select_attached_nets();
/* select_attached_nets(); */
move_objects(START,0,0,0);
xctx->ui_state &=~MENUSTARTMOVE;
break;

View File

@ -128,8 +128,9 @@ alt+shift 'l' add lab_wire.sym to schematic
alt 'l' add lab_pin.sym to schematic
ctrl+shift 'o' Load most recent schematic
ctrl 'o' Load schematic
- 'm' Move selected obj.
shift 'M' Move selected obj, insert wire when separating touching instance pins.
- 'm' Move selected objects
ctrl 'm' Move selected objects, stretching wires attached to them
shift 'M' Move selected objects, insert wire when separating touching instance pins/wires
Stretch wires that land on selected instance pins.
shift 'N' Top level only netlist
- 'n' Hierarchical Netlist

View File

@ -2311,12 +2311,26 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
xctx->prep_hi_structs=0;
}
}
/* move_objects [dx dy]
/* move_objects [dx dy] [kissing] [stretch]
* Start a move operation on selection and let user terminate the operation in the GUI
* if kissing is given add nets to pins that touch other instances or nets
* if stretch is given stretch connected nets to follow instace pins
* if dx and dy are given move by that amount. */
else if(!strcmp(argv[1], "move_objects"))
{
if(argc==4) {
int kissing= 0;
int stretch = 0;
if(argc > 2) {
int i;
for(i = 2; i < argc; i++) {
if(!strcmp(argv[i], "kissing")) kissing = 1;
if(!strcmp(argv[i], "stretch")) stretch = 1;
}
}
if(kissing | stretch) argc = 2;
if(stretch) select_attached_nets();
if(kissing) tclsetintvar("connect_by_kissing", 2);
if(argc > 3) {
move_objects(START,0,0,0);
move_objects( END,0,atof(argv[2]), atof(argv[3]));
}

View File

@ -1239,48 +1239,21 @@ void select_attached_nets(void)
int wire, inst, j, i, rects, r, sqx, sqy;
double x0, y0;
Wireentry *wptr;
int cbk = (tclgetintvar("connect_by_kissing") == 2);
hash_wires();
rebuild_selected_array();
if(cbk) {
for(j=0;j<xctx->lastsel; ++j) {
if(xctx->sel_array[j].type==ELEMENT) {
inst = xctx->sel_array[j].n;
if((xctx->inst[inst].ptr >= 0)) {
rects = (xctx->inst[inst].ptr + xctx->sym)->rects[PINLAYER];
for(r = 0; r < rects; r++)
{
get_inst_pin_coord(inst, r, &x0, &y0);
get_square(x0, y0, &sqx, &sqy);
for(wptr=xctx->wire_spatial_table[sqx][sqy]; wptr; wptr=wptr->next) {
i = wptr->n;
if(xctx->wire[i].x1 == x0 && xctx->wire[i].y1 == y0) {
select_wire(i,SELECTED1, 1);
}
if(xctx->wire[i].x2 == x0 && xctx->wire[i].y2 == y0) {
select_wire(i,SELECTED2, 1);
}
}
}
}
}
if(xctx->sel_array[j].type==WIRE) {
wire = xctx->sel_array[j].n;
for(r = 0; r < 2; r++)
for(j=0;j<xctx->lastsel; ++j) {
if(xctx->sel_array[j].type==ELEMENT) {
inst = xctx->sel_array[j].n;
if((xctx->inst[inst].ptr >= 0)) {
rects = (xctx->inst[inst].ptr + xctx->sym)->rects[PINLAYER];
for(r = 0; r < rects; r++)
{
if(r == 0) {
x0 = xctx->wire[wire].x1;
y0 = xctx->wire[wire].y1;
} else {
x0 = xctx->wire[wire].x2;
y0 = xctx->wire[wire].y2;
}
get_inst_pin_coord(inst, r, &x0, &y0);
get_square(x0, y0, &sqx, &sqy);
for(wptr=xctx->wire_spatial_table[sqx][sqy]; wptr; wptr=wptr->next) {
i = wptr->n;
if(i == wire) continue;
if(xctx->wire[i].x1 == x0 && xctx->wire[i].y1 == y0) {
select_wire(i,SELECTED1, 1);
}
@ -1290,9 +1263,33 @@ void select_attached_nets(void)
}
}
}
} /* for(j=0;j<xctx->lastsel; ++j) */
rebuild_selected_array();
} /* if(cbk) */
}
if(xctx->sel_array[j].type==WIRE) {
wire = xctx->sel_array[j].n;
for(r = 0; r < 2; r++)
{
if(r == 0) {
x0 = xctx->wire[wire].x1;
y0 = xctx->wire[wire].y1;
} else {
x0 = xctx->wire[wire].x2;
y0 = xctx->wire[wire].y2;
}
get_square(x0, y0, &sqx, &sqy);
for(wptr=xctx->wire_spatial_table[sqx][sqy]; wptr; wptr=wptr->next) {
i = wptr->n;
if(i == wire) continue;
if(xctx->wire[i].x1 == x0 && xctx->wire[i].y1 == y0) {
select_wire(i,SELECTED1, 1);
}
if(xctx->wire[i].x2 == x0 && xctx->wire[i].y2 == y0) {
select_wire(i,SELECTED2, 1);
}
}
}
}
} /* for(j=0;j<xctx->lastsel; ++j) */
rebuild_selected_array();
}
void select_inside(double x1,double y1, double x2, double y2, int sel) /*added unselect (sel param) */

View File

@ -6043,7 +6043,9 @@ proc build_widgets { {topwin {} } } {
toolbar_add EditDuplicate "xschem copy_objects" "Duplicate objects" $topwin
$topwin.menubar.edit.menu add command -label "Move objects" -command "xschem move_objects" -accelerator M
$topwin.menubar.edit.menu add command -label "Move objects stretching attached wires" \
-command "set connect_by_kissing 2; xschem move_objects" -accelerator Shift+M
-command "xschem move_objects stretch" -accelerator Control+M
$topwin.menubar.edit.menu add command -label "Move objects adding wires to connected pins" \
-command "xschem move_objects kissing" -accelerator Shift+M
toolbar_add EditMove "xschem move_objects" "Move objects" $topwin
$topwin.menubar.edit.menu add command -label "Flip selected objects" -command "xschem flip" -accelerator {Alt-F}
$topwin.menubar.edit.menu add command -label "Rotate selected objects" -command "xschem rotate" -accelerator {Alt-R}