diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index f8af26ee..c936661c 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -492,6 +492,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" +
  • abort_operation
  •     Resets UI state, unselect all and abort any pending operation 
  • add_symbol_pin
  • @@ -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) 
  • bbox begin|end
  •     Start/end bounding box calculation: parameter is either 'begin' or 'end' 
    -
  • 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 
  • build_colors
  •     Rebuild color palette using values of tcl vars dim_value and dim_bg 
  • callback winpath event mx my key button aux state
  • @@ -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...
    diff --git a/src/callback.c b/src/callback.c index 95d86d9e..7b101c17 100644 --- a/src/callback.c +++ b/src/callback.c @@ -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)) { diff --git a/src/check.c b/src/check.c index 5a4bfe1b..95a703e4 100644 --- a/src/check.c +++ b/src/check.c @@ -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;rwire[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;jlastsel; ++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(); + } } diff --git a/src/netlist.c b/src/netlist.c index 18ad946a..77dd924c 100644 --- a/src/netlist.c +++ b/src/netlist.c @@ -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); diff --git a/src/scheduler.c b/src/scheduler.c index 6e768d1c..c2093e12 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -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); } diff --git a/src/select.c b/src/select.c index be36613f..84190051 100644 --- a/src/select.c +++ b/src/select.c @@ -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;iwires; ++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;iwires; ++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); diff --git a/src/xschem.h b/src/xschem.h index 4d9ed391..78144db8 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -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, diff --git a/src/xschem.tcl b/src/xschem.tcl index 2265a396..09e97db7 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -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 {