Add command "Tools -> Remove wires running throuh selected inst. pins"

This commit is contained in:
Stefan Schippers 2023-06-10 17:24:12 +02:00
parent 0c9bdba37f
commit d5cc702fe8
8 changed files with 153 additions and 66 deletions

View File

@ -492,6 +492,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> abort_operation</kbd></li><pre>
Resets UI state, unselect all and abort any pending operation </pre>
<li><kbd> add_symbol_pin</kbd></li><pre>
@ -513,8 +514,10 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Attach net labels to selected component(s) instance(s) </pre>
<li><kbd> bbox begin|end</kbd></li><pre>
Start/end bounding box calculation: parameter is either 'begin' or 'end' </pre>
<li><kbd> break_wires</kbd></li><pre>
Break wires at selected instance pins </pre>
<li><kbd> break_wires [remove] </kbd></li><pre>
Break wires at selected instance pins
if '1' is given as 'remove' parameter broken wires that are all inside selected
instances will be deleted </pre>
<li><kbd> build_colors</kbd></li><pre>
Rebuild color palette using values of tcl vars dim_value and dim_bg </pre>
<li><kbd> callback winpath event mx my key button aux state</kbd></li><pre>
@ -873,6 +876,8 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
destroy: destroy tab/window identified by winpath. Example:
xschem new_schematic destroy .x1.drw
destroy_all: close all tabs/additional windows
if the 'force'argument is given do not issue a warning if modified
tabs are about to be closed.
switch: switch context to specified 'winpath' window or specified schematic name
Main window/tab has winpath set to .drw,
Additional windows/tabs have winpath set to .x1.drw, .x2.drw and so on...</pre>

View File

@ -2377,13 +2377,20 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
view_unzoom(0.0);
break;
}
if(key=='!')
if(key=='!' && !(state & ControlMask))
{
if(xctx->semaphore >= 2) break;
break_wires_at_pins();
break_wires_at_pins(0);
break;
}
if(key=='!' && (state & ControlMask))
{
if(xctx->semaphore >= 2) break;
break_wires_at_pins(1);
break;
}
break;
case ButtonPress: /* end operation */
dbg(1, "callback(): ButtonPress ui_state=%d state=%d\n",xctx->ui_state,state);
if(waves_selected(event, key, state, button)) {

View File

@ -378,13 +378,34 @@ void trim_wires(void)
update_conn_cues(WIRELAYER, 0, 0);
}
void break_wires_at_pins(void)
static int touches_inst_pin(double x, double y, int inst)
{
int rects, r;
double x0, y0;
int touches = 0;
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);
if(x == x0 && y == y0) {
touches = 1;
break;
}
}
}
dbg(0, "touches_inst_pin(): %g %g : touches =%d on inst %d\n", x, y, touches, inst);
return touches;
}
/* if remove=1 is given wires that are all inside instance bboxes are deleted */
void break_wires_at_pins(int remove)
{
int k, i, j, r, rects, sqx, sqy;
Wireentry *wptr;
double x0, y0;
int changed=0;
int deleted_wire = 0;
hash_wires();
rebuild_selected_array();
@ -409,33 +430,61 @@ void break_wires_at_pins(void)
i, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2);
if(!changed) { xctx->push_undo(); changed=1;}
check_wire_storage();
xctx->wire[xctx->wires].x1=xctx->wire[i].x1;
xctx->wire[xctx->wires].y1=xctx->wire[i].y1;
xctx->wire[xctx->wires].x2=x0;
xctx->wire[xctx->wires].y2=y0;
xctx->wire[xctx->wires].sel=0;
xctx->wire[xctx->wires].prop_ptr=NULL;
my_strdup(_ALLOC_ID_, &xctx->wire[xctx->wires].prop_ptr, xctx->wire[i].prop_ptr);
if(!strcmp(get_tok_value(xctx->wire[xctx->wires].prop_ptr,"bus",0), "true"))
xctx->wire[xctx->wires].bus=1;
else
xctx->wire[xctx->wires].bus=0;
xctx->wire[xctx->wires].node=NULL;
hash_wire(XINSERT, xctx->wires, 0); /* insertion happens at beginning of list */
dbg(1, "break_wires_at_pins(): hashing new wire %d: %g %g %g %g\n",
xctx->wires, xctx->wire[xctx->wires].x1, xctx->wire[xctx->wires].y1,
xctx->wire[xctx->wires].x2, xctx->wire[xctx->wires].y2);
my_strdup(_ALLOC_ID_, &xctx->wire[xctx->wires].node, xctx->wire[i].node);
xctx->need_reb_sel_arr=1;
xctx->wires++;
if(!remove || !RECT_INSIDE(xctx->wire[i].x1, xctx->wire[i].y1, x0, y0,
xctx->inst[k].xx1, xctx->inst[k].yy1, xctx->inst[k].xx2, xctx->inst[k].yy2)
|| !touches_inst_pin(xctx->wire[i].x1, xctx->wire[i].y1, k)
) {
xctx->wire[xctx->wires].x1=xctx->wire[i].x1;
xctx->wire[xctx->wires].y1=xctx->wire[i].y1;
xctx->wire[xctx->wires].end1 = xctx->wire[i].end1;
xctx->wire[xctx->wires].end2 = 0;
xctx->wire[xctx->wires].x2=x0;
xctx->wire[xctx->wires].y2=y0;
xctx->wire[xctx->wires].sel=0;
xctx->wire[xctx->wires].prop_ptr=NULL;
my_strdup(_ALLOC_ID_, &xctx->wire[xctx->wires].prop_ptr, xctx->wire[i].prop_ptr);
if(!strcmp(get_tok_value(xctx->wire[xctx->wires].prop_ptr,"bus",0), "true"))
xctx->wire[xctx->wires].bus=1;
else
xctx->wire[xctx->wires].bus=0;
xctx->wire[xctx->wires].node=NULL;
hash_wire(XINSERT, xctx->wires, 0); /* insertion happens at beginning of list */
dbg(1, "break_wires_at_pins(): hashing new wire %d: %g %g %g %g\n",
xctx->wires, xctx->wire[xctx->wires].x1, xctx->wire[xctx->wires].y1,
xctx->wire[xctx->wires].x2, xctx->wire[xctx->wires].y2);
my_strdup(_ALLOC_ID_, &xctx->wire[xctx->wires].node, xctx->wire[i].node);
xctx->need_reb_sel_arr=1;
xctx->wires++;
} else {
dbg(0, "break_wires_at_pins(): skipping wire creation on wire %d\n", i);
deleted_wire = 1;
}
xctx->wire[i].x1 = x0;
xctx->wire[i].y1 = y0;
if(remove && RECT_INSIDE(xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2,
xctx->inst[k].xx1, xctx->inst[k].yy1, xctx->inst[k].xx2, xctx->inst[k].yy2)) {
if(touches_inst_pin(xctx->wire[i].x2, xctx->wire[i].y2, k)) {
dbg(1, "break_wires_at_pins(): wire %d needs to be deleted: %g %g %g %g\n",
i, xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2);
/* mark for deletion only if no other nets attached */
xctx->wire[i].sel = SELECTED4; /* use a special flag to later delete these wires
* only and not other seleted wires */
dbg(0, "break_wires_at_pins(): mark wire %d for deletion: end2=%d\n", i, xctx->wire[i].end2);
}
}
}
}
}
}
}
}
if(remove) {
if(delete_wires(1, SELECTED4)) {
deleted_wire = 1;
}
}
/* break wires that touch selected wires */
rebuild_selected_array();
for(j=0;j<xctx->lastsel; ++j) if(xctx->sel_array[j].type==WIRE) {
@ -493,6 +542,10 @@ void break_wires_at_pins(void)
xctx->prep_net_structs=0;
xctx->prep_hi_structs=0;
xctx->prep_hash_wires=0;
/*update_conn_cues(WIRELAYER, 0, 0); */
if(deleted_wire) {
if(tclgetboolvar("autotrim_wires")) trim_wires();
update_conn_cues(WIRELAYER, 0, 0);
draw();
}
}

View File

@ -186,6 +186,7 @@ static void wiredelete(int n, int x, int y)
Wireentry *saveptr, **prevptr;
prevptr = &xctx->wire_spatial_table[x][y];
if(*prevptr == NULL) return;
while( (*prevptr)->n != n) prevptr = &(*prevptr)->next;
saveptr = (*prevptr)->next;
my_free(_ALLOC_ID_, prevptr);

View File

@ -307,11 +307,15 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* break_wires
* Break wires at selected instance pins */
/* break_wires [remove]
* Break wires at selected instance pins
* if '1' is given as 'remove' parameter broken wires that are all inside selected
* instances will be deleted */
else if(!strcmp(argv[1], "break_wires"))
{
break_wires_at_pins();
int remove = 0;
if(argc > 2) remove = atoi(argv[2]);
break_wires_at_pins(remove);
Tcl_ResetResult(interp);
}

View File

@ -333,6 +333,50 @@ static void del_rect_line_arc_poly(int floaters)
}
int delete_wires(int floaters, int selected_flag)
{
int i, j = 0, deleted = 0;
for(i=0;i<xctx->wires; ++i)
{
if(xctx->wire[i].sel == selected_flag) {
++j;
if(xctx->wire[i].bus){
double ov, y1, y2;
ov = INT_BUS_WIDTH(xctx->lw)> cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
if(!floaters) bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 );
} else {
double ov, y1, y2;
ov = cadhalfdotsize;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
if(!floaters) bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 );
}
hash_wire(XDELETE, i, 0);
my_free(_ALLOC_ID_, &xctx->wire[i].prop_ptr);
my_free(_ALLOC_ID_, &xctx->wire[i].node);
deleted = 1;
continue;
}
if(j) {
xctx->wire[i-j] = xctx->wire[i];
}
}
xctx->wires -= j;
if(j) {
xctx->prep_hash_wires=0;
xctx->prep_net_structs=0;
xctx->prep_hi_structs=0;
}
if(xctx->hilight_nets) {
propagate_hilights(1, 1, XINSERT_NOREPLACE);
}
return deleted;
}
void delete(int to_push_undo)
{
int i, j, tmp, deleted = 0, floaters;
@ -420,44 +464,15 @@ void delete(int to_push_undo)
xctx->prep_net_structs=0;
xctx->prep_hi_structs=0;
}
j = 0;
for(i=0;i<xctx->wires; ++i)
{
if(xctx->wire[i].sel == SELECTED) {
++j;
if(xctx->wire[i].bus){
double ov, y1, y2;
ov = INT_BUS_WIDTH(xctx->lw)> cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
if(!floaters) bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 );
} else {
double ov, y1, y2;
ov = cadhalfdotsize;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
if(!floaters) bbox(ADD, xctx->wire[i].x1-ov, y1 , xctx->wire[i].x2+ov , y2 );
}
my_free(_ALLOC_ID_, &xctx->wire[i].prop_ptr);
my_free(_ALLOC_ID_, &xctx->wire[i].node);
if(delete_wires(floaters, SELECTED)) {
deleted = 1;
if(tclgetboolvar("autotrim_wires")) trim_wires();
update_conn_cues(WIRELAYER, 0, 0);
}
deleted = 1;
continue;
}
if(j) {
xctx->wire[i-j] = xctx->wire[i];
}
}
xctx->wires -= j;
if(j) {
xctx->prep_hash_wires=0;
xctx->prep_net_structs=0;
xctx->prep_hi_structs=0;
}
if(tclgetboolvar("autotrim_wires")) trim_wires();
del_rect_line_arc_poly(floaters);
update_conn_cues(WIRELAYER, 0, 0);
if(xctx->hilight_nets) {
propagate_hilights(1, 1, XINSERT_NOREPLACE);
}
@ -479,7 +494,6 @@ void delete(int to_push_undo)
xctx->ui_state &= ~SELECTION;
}
void delete_only_rect_line_arc_poly(void)
{
bbox(START, 0.0 , 0.0 , 0.0 , 0.0);

View File

@ -1221,6 +1221,7 @@ extern const char *get_sym_template(char *s, char *extra);
extern void zoom_full(int draw, int sel, int flags, double shrink);
extern void updatebbox(int count,xRect *boundbox,xRect *tmp);
extern void draw_selection(GC g, int interruptable);
extern int delete_wires(int floaters, int selected_flag);
extern void delete(int to_push_undo);
extern void delete_only_rect_line_arc_poly(void);
extern void polygon_bbox(double *x, double *y, int points, double *bx1, double *by1, double *bx2, double *by2);
@ -1300,7 +1301,7 @@ extern int rectclip(int,int,int,int,
double*,double*,double*,double*);
extern void trim_wires(void);
extern void update_conn_cues(int layer, int draw_cues, int dr_win);
extern void break_wires_at_pins(void);
extern void break_wires_at_pins(int remove);
extern void check_touch(int i, int j,
unsigned short *parallel,unsigned short *breaks,

View File

@ -6101,6 +6101,8 @@ proc build_widgets { {topwin {} } } {
toolbar_add ToolJoinTrim "xschem trim_wires" "Join/Trim Wires" $topwin
$topwin.menubar.tools.menu add command -label "Break wires at selected instance pins" \
-command "xschem break_wires" -accelerator {!}
$topwin.menubar.tools.menu add command -label "Remove wires running throuh selected inst. pins" \
-command "xschem break_wires 1" -accelerator {Ctrl-!}
toolbar_add ToolBreak "xschem break_wires" "Break wires at selected\ninstance pin intersections" $topwin
$topwin.menubar.tools.menu add checkbutton -label "Auto Join/Trim Wires" -variable autotrim_wires \
-command {