From e0bcc302c92597647830b82a05993a1fe82a0323 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 14 Sep 2023 09:48:12 +0200 Subject: [PATCH] "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) --- doc/xschem_man/developer_info.html | 13 ++- src/callback.c | 4 +- src/scheduler.c | 12 ++- src/select.c | 154 +++++++++++++++-------------- src/xschem.h | 2 +- 5 files changed, 98 insertions(+), 87 deletions(-) diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index ebd464e5..965f744e 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -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"
  • compare_schematics [sch_file]
  •     Compare currently loaded schematic with another 'sch_file' schematic.
        if no file is given prompt user to choose one 
    -
  • 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' 
  • copy
  •     Copy selection to clipboard 
  • copy_objects
  • @@ -1284,6 +1284,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
     
     
     
    +
    +
    +
     
     
     
    diff --git a/src/callback.c b/src/callback.c
    index 830baf9a..34c378f9 100644
    --- a/src/callback.c
    +++ b/src/callback.c
    @@ -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;
    diff --git a/src/scheduler.c b/src/scheduler.c
    index f3a9b710..16d2cbd2 100644
    --- a/src/scheduler.c
    +++ b/src/scheduler.c
    @@ -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);
         }
     
    diff --git a/src/select.c b/src/select.c
    index 996c1d9d..8e4dab79 100644
    --- a/src/select.c
    +++ b/src/select.c
    @@ -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; nlastsel; ++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; nlastsel; ++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;
    diff --git a/src/xschem.h b/src/xschem.h
    index 09d52dd7..fcab50ec 100644
    --- a/src/xschem.h
    +++ b/src/xschem.h
    @@ -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);