From 10991e662c62b0d0559417c2cea3a95e4d7c5782 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Wed, 15 Jan 2025 00:44:39 +0100 Subject: [PATCH 1/9] added `xschem symbol_base_name` command to get the base symbol a symbol defined by instance `schematic` attribute comes from; updated `celview` procedure --- doc/xschem_man/developer_info.html | 5 ++ src/scheduler.c | 23 +++++++ src/xschem.tcl | 102 ++++++++++++++++++++++------- 3 files changed, 108 insertions(+), 22 deletions(-) diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 4961ea54..9a847521 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -1517,6 +1517,11 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" if rep not preceeded by an 'escape' character
  • subst_tok str tok newval
  •     Return string 'str' with 'tok' attribute value replaced with 'newval' 
    +
  • symbol_base_name n
  • +   Return the base_name field of a symbol with name or number `n`
    +   Normally this is empty. It is set for overloaded symbols, that is symbols
    +   derived from the base symbol due to instance based implementation selection
    +   (the instance "schematic" attribute) 
  • symbol_in_new_window [new_process]
  •     When a symbol is selected edit it in a new tab/window if not already open.
        If nothing selected open another window of the second schematic (issues a warning).
    diff --git a/src/scheduler.c b/src/scheduler.c
    index 799a01e4..b2e99256 100644
    --- a/src/scheduler.c
    +++ b/src/scheduler.c
    @@ -5591,6 +5591,29 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
           Tcl_SetResult(interp, s, TCL_VOLATILE);
           my_free(_ALLOC_ID_, &s);
         }
    +    /* symbol_base_name n
    +     *   Return the base_name field of a symbol with name or number `n`
    +     *   Normally this is empty. It is set for overloaded symbols, that is symbols
    +     *   derived from the base symbol due to instance based implementation selection
    +     *   (the instance "schematic" attribute) */
    +    else if(!strcmp(argv[1], "symbol_base_name"))
    +    {
    +      int i = -1, found = 0;
    +      if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
    +      if(argc > 2 && argv[2][0]) {
    +        i = get_symbol(argv[2]);
    +        if(i >=0) {
    +          found = 1;
    +        }
    +      }
    +      if(found) {
    +        Tcl_AppendResult(interp, xctx->sym[i].base_name, NULL);
    +      } else {
    +        Tcl_SetResult(interp, "Missing arguments or symbol not found", TCL_STATIC);
    +        return TCL_ERROR;
    +      }
    +    }
    +
     
         /* symbol_in_new_window [new_process]
          *   When a symbol is selected edit it in a new tab/window if not already open.
    diff --git a/src/xschem.tcl b/src/xschem.tcl
    index 11244c90..7edac6b3 100644
    --- a/src/xschem.tcl
    +++ b/src/xschem.tcl
    @@ -1770,29 +1770,31 @@ proc simconf_add {tool} {
     ############ cellview
     # proc cellview prints symbol bindings (default binding or "schematic" attr in symbol)
     # of all symbols used in current and sub schematics.
    -proc cellview_setlabels {w symbol sym_sch default_sch sym_spice_sym_def} {
    +proc cellview_setlabels {w symbol sym_sch sym_spice_sym_def derived_symbol} {
       global dark_gui_colorscheme
       if {$dark_gui_colorscheme} {
    +    set instfg orange1
         set symfg SeaGreen1
         set symbg SeaGreen4
         set missingbg IndianRed4
       } else { 
    +    set instfg orange4
         set symfg SeaGreen4
         set symbg SeaGreen1
         set missingbg IndianRed1 
       }     
       $w configure -fg [option get . foreground {}]
       $w configure -bg [option get . background {}]
    -  if { $sym_spice_sym_def ne {}} {
    +  if { $derived_symbol} {
    +    $w configure -fg $instfg
    +  } elseif {$sym_spice_sym_def ne {} } {
         $w configure -fg $symfg
    -  } else {
    -    if {[$w get] eq $default_sch} {
    -        puts "$symbol: need to clear schematic attr in symbol"
    -    } elseif {[$w get] eq $sym_sch} {
    -      $w configure -bg $symbg
    -    } else {
    -      puts "need to update:[$w get] --> $sym_sch"
    -    }
    +  } 
    +  puts ===============
    +  puts sym_sch=$sym_sch
    +  puts symbol=$symbol
    +
    +  if { $sym_spice_sym_def eq {}} {
         if { ![file exists [abs_sym_path [$w get]]] } {
           $w configure -bg $missingbg
         }
    @@ -1811,8 +1813,31 @@ proc cellview_edit_item {w sym_spice_sym_def} {
       }
     }
     
    +proc cellview_edit_sym {w} {
    +  set sym [$w cget -text]
    +  set res [catch {xschem symbol_base_name $sym} base_name]
    +  if {$res == 0} {
    +    if {$base_name ne {}} {
    +      set sym $base_name
    +    }
    +  }
    +  xschem load_new_window $sym
    +}
    +
     proc cellview {{derived_symbols {}}} {
    -  global keep_symbols nolist_libs
    +  global keep_symbols nolist_libs dark_gui_colorscheme
    +
    +  if {$dark_gui_colorscheme} { 
    +    set instfg orange1
    +    set symfg SeaGreen1
    +    set symbg SeaGreen4
    +    set missingbg IndianRed4
    +  } else { 
    +    set instfg orange4
    +    set symfg SeaGreen4
    +    set symbg SeaGreen1
    +    set missingbg IndianRed1 
    +  }     
     
       if {[info tclversion] >= 8.5} {
         set font {TkDefaultFont 10 bold} ;# Monospace
    @@ -1820,6 +1845,7 @@ proc cellview {{derived_symbols {}}} {
         set font fixed
       }
       toplevel .cv
    +  xschem reload_symbols ;# purge unused symbols
       set save_keep $keep_symbols
       set keep_symbols 1 ;# keep all symbols when doing a hierarchic netlist
       xschem netlist ;# traverse the hierarchy and retain all encountered symbols
    @@ -1830,7 +1856,7 @@ proc cellview {{derived_symbols {}}} {
       frame .cv.top
       label .cv.top.sym -text {   SYMBOL} -width 30 -bg grey60 -anchor w -padx 4 -font $font
       label .cv.top.sch -text SCHEMATIC -width 45 -bg grey60 -anchor w -padx 4 -font $font
    -  label .cv.top.pad -text {      } -width 1 -bg grey60 -font $font
    +  label .cv.top.pad -text {      } -width 4 -bg grey60 -font $font
       pack .cv.top.sym .cv.top.sch -side left -fill x -expand 1
       pack .cv.top.pad -side left -fill x
       frame .cv.center
    @@ -1838,9 +1864,17 @@ proc cellview {{derived_symbols {}}} {
       # puts sf=$sf
       set syms [join [lsort -index 1 [xschem symbols $derived_symbols]]]
       foreach {i symbol} $syms {
    +    set base_name [xschem symbol_base_name $symbol]
    +    set derived_symbol 0
    +    if {$base_name ne {}} {
    +      set derived_symbol 1
    +    }
         set abs_sch [xschem get_sch_from_sym -1 $symbol]
    -    set abs_sym [abs_sym_path $symbol]
    -    set default_sch [add_ext $symbol .sch]
    +    if {$derived_symbol} {
    +      set abs_sym [abs_sym_path $base_name]
    +    } else {
    +      set abs_sym [abs_sym_path $symbol]
    +    }
         set skip 0
         foreach j $nolist_libs {
           if {[regexp $j $abs_sym]} { 
    @@ -1851,28 +1885,53 @@ proc cellview {{derived_symbols {}}} {
         if {$skip} { continue }
         set sym_sch [rel_sym_path $abs_sch]
         set type [xschem getprop symbol $symbol type]
    -    set sym_spice_sym_def [xschem getprop symbol $symbol spice_sym_def]
    +    set sym_spice_sym_def [xschem getprop symbol $symbol spice_sym_def 2]
         if {$type eq {subcircuit}} {
           frame $sf.f$i
           pack $sf.f$i -side top -fill x
           label  $sf.f$i.l -text $symbol -width 30 -anchor w -padx 4 -borderwidth 1 \
             -relief sunken -pady 1 -font $font
    +      if {$derived_symbol} { 
    +        $sf.f$i.l configure -fg $instfg
    +      }
           # puts $sf.f$i.s
           entry $sf.f$i.s -width 45 -borderwidth 1 -relief sunken -font $font
    -      balloon $sf.f$i.s $abs_sch
    -      button $sf.f$i.b -text Sch -padx 4 -borderwidth 1 -pady 0 -font $font \
    +      button $sf.f$i.sym -text Sym -padx 4 -borderwidth 1 -pady 0 -font $font \
    +             -command "cellview_edit_sym $sf.f$i.l"
    +      button $sf.f$i.sch -text Sch -padx 4 -borderwidth 1 -pady 0 -font $font \
                  -command "cellview_edit_item $sf.f$i.s [list $sym_spice_sym_def]"
           if {$sym_spice_sym_def eq {}} {
             $sf.f$i.s insert 0 $sym_sch
           } else {
    -        $sf.f$i.s insert 0 {defined in symbol spice_sym_def}
    +        if {$derived_symbol} {
    +          $sf.f$i.s insert 0 {defined in instance spice_sym_def}
    +        } else {
    +          $sf.f$i.s insert 0 {defined in symbol spice_sym_def}
    +        }
           }
    +      if {[xschem is_generator [ $sf.f$i.s get]]} {
    +        set f [ $sf.f$i.s get]
    +        regsub {\(.*} $f {} f
    +      } elseif { $sym_spice_sym_def eq {}} {
    +        set f [abs_sym_path [$sf.f$i.s get]]
    +      } else {
    +        set ff [split $sym_spice_sym_def \n]
    +        puts ff=$ff
    +        if {[llength $ff] > 5} {
    +          set ff [lrange $ff 0 4]
    +          lappend ff ...
    +        }   
    +        set f [join $ff \n]
    +        puts f=$f
    +      }
    +      balloon $sf.f$i.s $f
    +
           bind $sf.f$i.s  "
    -        cellview_setlabels %W [list $symbol] [list $sym_sch] [list $default_sch] [list $sym_spice_sym_def]
    +        cellview_setlabels %W [list $symbol] [list $sym_sch] [list $sym_spice_sym_def] $derived_symbol
           "
    -      cellview_setlabels $sf.f$i.s $symbol $sym_sch $default_sch $sym_spice_sym_def
    +      cellview_setlabels $sf.f$i.s $symbol $sym_sch $sym_spice_sym_def $derived_symbol
           pack $sf.f$i.l $sf.f$i.s -side left -fill x -expand 1
    -      pack $sf.f$i.b -side left
    +      pack $sf.f$i.sch $sf.f$i.sym -side left
         }
       }
       frame .cv.bottom
    @@ -1888,7 +1947,6 @@ proc cellview {{derived_symbols {}}} {
       bind .cv  { sframeyview .cv.center scroll -0.1}
       bind .cv  { sframeyview .cv.center scroll 0.1}
       bind .cv  {destroy .cv}
    -  xschem reload_symbols ;# purge all symbols used in below hierarchies
     }
     ############ /cellview
     
    
    From 7d6c3f47642ccbbb39f155518af4438138e41cb0 Mon Sep 17 00:00:00 2001
    From: stefan schippers 
    Date: Wed, 15 Jan 2025 03:11:12 +0100
    Subject: [PATCH 2/9] destroy_all_tabs() do a final redraw to avoid
     inconsistent screen after some tab removals
    
    ---
     src/xinit.c                              | 1 +
     xschem_library/ngspice/diode_ngspice.sym | 8 +++++---
     2 files changed, 6 insertions(+), 3 deletions(-)
    
    diff --git a/src/xinit.c b/src/xinit.c
    index 1fbc00a1..e3d48898 100644
    --- a/src/xinit.c
    +++ b/src/xinit.c
    @@ -1990,6 +1990,7 @@ static void destroy_all_tabs(int *window_count, int force)
         xctx = savectx; /* restore previous schematic or main if old is destroyed */
         tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
         set_modify(-1); /* sets window title */
    +    draw();
       }
     }
     
    diff --git a/xschem_library/ngspice/diode_ngspice.sym b/xschem_library/ngspice/diode_ngspice.sym
    index 002e17fe..76f5bd95 100644
    --- a/xschem_library/ngspice/diode_ngspice.sym
    +++ b/xschem_library/ngspice/diode_ngspice.sym
    @@ -1,4 +1,4 @@
    -v {xschem version=3.4.4 file_version=1.2
    +v {xschem version=3.4.6 file_version=1.2
     *
     * This file is part of XSCHEM,
     * a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
    @@ -37,5 +37,7 @@ B 5 -2.5 -32.5 2.5 -27.5 {name=plus dir=inout pinnumber=1 propag=1 goto=1}
     B 5 -2.5 27.5 2.5 32.5 {name=minus dir=inout pinnumber=2 goto=0}
     P 4 4 -0 5 -10 -5 10 -5 0 5 {fill=true}
     T {@name} 15 -18.75 0 0 0.2 0.2 {}
    -T {@#0:net_name} 10 -28.75 0 0 0.15 0.15 {layer=15}
    -T {@#1:net_name} 10 20 0 0 0.15 0.15 {layer=15}
    +T {@#0:net_name} 10 -28.75 0 0 0.15 0.15 {layer=15
    +hide=instance}
    +T {@#1:net_name} 10 20 0 0 0.15 0.15 {layer=15
    +hide=instance}
    
    From f2b9d0c6f30bb17cb1b813f4118803a826b7c0a1 Mon Sep 17 00:00:00 2001
    From: stefan schippers 
    Date: Wed, 15 Jan 2025 17:39:59 +0100
    Subject: [PATCH 3/9]  added attribute @spice_get_current for retrieving
     current through terminal  of primitive device; example:
     @spice_get_current2 to get base current of BJT device
    
    ---
     src/save.c  | 14 +++++----
     src/token.c | 83 +++++++++++++++++++++++++++++++++++++++--------------
     2 files changed, 71 insertions(+), 26 deletions(-)
    
    diff --git a/src/save.c b/src/save.c
    index 83a6edcf..c19593e5 100644
    --- a/src/save.c
    +++ b/src/save.c
    @@ -4629,10 +4629,12 @@ int load_sym_def(const char *name, FILE *embed_fd)
                 my_free(_ALLOC_ID_, &path);
                 dbg(1, " --> tt[i].txt_ptr=%s\n", tt[i].txt_ptr);
               }
    -          if(!strcmp(tt[i].txt_ptr, "@spice_get_current")) {
    +          /* @spice_get_current or @spice_get_current */
    +          if(!strncmp(tt[i].txt_ptr, "@spice_get_current", 18)) {
                 /* prop_ptr is the attribute string of last loaded LCC component */
                 const char *dev;
                 size_t new_size = 0;
    +            char *txt_ptr = NULL;
                 char *path = NULL;
                 if(level > 1) { /* add parent LCC instance names (X1, Xinv etc) */
                   int i;
    @@ -4644,11 +4646,13 @@ int load_sym_def(const char *name, FILE *embed_fd)
                 } 
                 if(path) new_size += strlen(path);
                 dev = get_tok_value(prop_ptr, "name", 0);
    -            new_size += strlen(dev) + 21; /* @spice_get_current() */
    -            my_realloc(_ALLOC_ID_, &tt[i].txt_ptr, new_size);
    -            my_snprintf(tt[i].txt_ptr, new_size, "@spice_get_current(%s%s)", path ? path : "", dev);
    +            new_size += strlen(tt[i].txt_ptr) + strlen(dev) + 2 + 1; /* tok() */
    +            my_realloc(_ALLOC_ID_, &txt_ptr, new_size);
    +            my_snprintf(txt_ptr, new_size, "%s(%s%s)", tt[i].txt_ptr, path ? path : "", dev);
    +            my_free(_ALLOC_ID_, &tt[i].txt_ptr);
    +            tt[i].txt_ptr = txt_ptr;
                 my_free(_ALLOC_ID_, &path);
    -            dbg(1, " --> tt[i].txt_ptr=%s\n", tt[i].txt_ptr);
    +            dbg(1, "--> tt[i].txt_ptr=%s\n", tt[i].txt_ptr);
               } 
               ROTATION(rot, flip, 0.0, 0.0, tt[i].x0, tt[i].y0, rx1, ry1);
               tt[i].x0 = lcc[level].x0 + rx1;  tt[i].y0 = lcc[level].y0 + ry1;
    diff --git a/src/token.c b/src/token.c
    index 31c0b2cb..c892b3b4 100644
    --- a/src/token.c
    +++ b/src/token.c
    @@ -3723,6 +3723,7 @@ const char *spice_get_node(const char *token)
     /* if s==NULL return emty string */
     const char *translate(int inst, const char* s)
     {
    + static regex_t *get_sp_cur = NULL; 
      static const char *empty="";
      static char *translated_tok = NULL;
      static char *result=NULL; /* safe to keep even with multiple schematics */
    @@ -3746,10 +3747,16 @@ const char *translate(int inst, const char* s)
      int sim_is_xyce;
      char *instname = NULL;
     
    + if(!get_sp_cur) {
    +   get_sp_cur = my_malloc(_ALLOC_ID_, sizeof(regex_t));
    +   regcomp(get_sp_cur, "^@spice_get_current[0-9]*\\(", REG_NOSUB | REG_EXTENDED);
    + }
    +
      sp_prefix = tclgetboolvar("spiceprefix");
      if(!s || !xctx || !xctx->inst) {
        my_free(_ALLOC_ID_, &result);
        my_free(_ALLOC_ID_, &translated_tok);
    +   regfree(get_sp_cur);
        return empty;
      }
      if(inst >= xctx->instances) {
    @@ -3770,6 +3777,7 @@ const char *translate(int inst, const char* s)
     
      while(1)
      {
    +  
       c=*s++;
       if(c=='\\') {
         escape=1;
    @@ -4074,7 +4082,8 @@ const char *translate(int inst, const char* s)
            }
          }
        }
    -   else if(strncmp(token,"@spice_get_current(", 19)==0 )
    +   /* @spice_get_current(...) or @spice_get_current(...) */
    +   else if(!regexec(get_sp_cur, token, 0 , NULL, 0) )
        {
          int start_level; /* hierarchy level where waves were loaded */
          int live = tclgetboolvar("live_cursor2_backannotate");
    @@ -4082,6 +4091,7 @@ const char *translate(int inst, const char* s)
            char *fqdev = NULL;
            const char *path =  xctx->sch_path[xctx->currsch] + 1;
            char *dev = NULL;
    +       int ncurrent = 1;
            size_t len;
            int idx, n;
            double val = 0.0;
    @@ -4095,8 +4105,14 @@ const char *translate(int inst, const char* s)
                ++path;
              }
              dev = my_malloc(_ALLOC_ID_, tmp);
    -         n = sscanf(token + 19, "%[^)]", dev);
    -         if(n == 1) {
    +         dbg(0, "%s\n", token);
    +         if(!strncmp(token, "@spice_get_current(", 19)) {
    +           n = sscanf(token + 19, "%[^)]", dev);
    +         } else {
    +           n = sscanf(token, "@spice_get_current%d(%[^)]", &ncurrent, dev);
    +           dbg(0, "ncurrent=%d, dev=%s\n", ncurrent, dev);
    +         }
    +         if(n >= 1) {
                strtolower(dev);
                len = strlen(path) + strlen(instname) +
                      strlen(dev) + 21; /* some extra chars for i(..) wrapper */
    @@ -4109,14 +4125,19 @@ const char *translate(int inst, const char* s)
                  else prefix=dev[0];
                  dbg(1, "prefix=%c, path=%s\n", prefix, path);
                  vsource = (prefix == 'v') || (prefix == 'e');
    -             if(vsource) my_snprintf(fqdev, len, "i(%c.%s%s.%s)", prefix, path, instname, dev);
    -             else if(prefix == 'q')
    -               my_snprintf(fqdev, len, "i(@%c.%s%s.%s[ic])", prefix, path, instname, dev);
    -             else if(prefix == 'd' || prefix == 'm')
    -               my_snprintf(fqdev, len, "i(@%c.%s%s.%s[id])", prefix, path, instname, dev);
    -             else if(prefix == 'i')
    +             if(vsource) {
    +               my_snprintf(fqdev, len, "i(%c.%s%s.%s)", prefix, path, instname, dev);
    +             } else if(prefix == 'q') {
    +               const char *current[] = {"ic", "ic", "ib", "ie"};
    +               my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]);
    +             } else if(prefix == 'd' || prefix == 'm') {
    +               const char *current[] = {"id", "id", "ig", "is", "ib"};
    +               my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]);
    +             } else if(prefix == 'i') {
                    my_snprintf(fqdev, len, "i(@%c.%s%s.%s[current])", prefix, path, instname, dev);
    -             else my_snprintf(fqdev, len, "i(@%c.%s%s.%s[i])", prefix, path, instname, dev);
    +             } else {
    +              my_snprintf(fqdev, len, "i(@%c.%s%s.%s[i])", prefix, path, instname, dev);
    +             }
                } else {
                  my_snprintf(fqdev, len, "i(%s%s.%s)", path, instname, dev);
                }
    @@ -4214,7 +4235,7 @@ const char *translate(int inst, const char* s)
            }
          }
        }
    -   else if(strcmp(token,"@spice_get_current")==0 )
    +   else if(strncmp(token,"@spice_get_current", 18)==0 )
        {
          int start_level; /* hierarchy level where waves were loaded */
          int live = tclgetboolvar("live_cursor2_backannotate");
    @@ -4222,6 +4243,7 @@ const char *translate(int inst, const char* s)
            char *fqdev = NULL;
            const char *path =  xctx->sch_path[xctx->currsch] + 1;
            char *dev = NULL;
    +       int ncurrent = 1;
            size_t len;
            int idx;
            double val = 0.0;
    @@ -4233,6 +4255,9 @@ const char *translate(int inst, const char* s)
                if(*path == '.') skip++;
                ++path;
              }
    +         if(strcmp(token, "@spice_get_current")) {
    +           if(sscanf(token, "@spice_get_current%d", &ncurrent) != 1) ncurrent = 1;
    +         }
              my_strdup2(_ALLOC_ID_, &dev, instname);
              strtolower(dev);
              len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */
    @@ -4242,17 +4267,33 @@ const char *translate(int inst, const char* s)
                int prefix=dev[0];
                int vsource = (prefix == 'v') || (prefix == 'e');
                if(path[0]) {
    -             if(vsource) my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev);
    -             else if(prefix=='q') my_snprintf(fqdev, len, "i(@%c.%s%s[ic])", prefix, path, dev);
    -             else if(prefix=='d' || prefix == 'm') my_snprintf(fqdev, len, "i(@%c.%s%s[id])", prefix, path, dev);
    -             else if(prefix=='i') my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev);
    -             else my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev);
    +             if(vsource) {
    +               my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev);
    +             } else if(prefix=='q') {
    +               const char *current[] = {"ic", "ic", "ib", "ie"};
    +               my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]);
    +             } else if(prefix=='d' || prefix == 'm') {
    +               const char *current[] = {"id", "id", "ig", "is", "ib"};
    +               my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]);
    +             } else if(prefix=='i') {
    +               my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev);
    +             } else {
    +               my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev);
    +             }
                } else {
    -             if(vsource) my_snprintf(fqdev, len, "i(%s)", dev);
    -             else if(prefix == 'q') my_snprintf(fqdev, len, "i(@%s[ic])", dev);
    -             else if(prefix == 'd' || prefix == 'm') my_snprintf(fqdev, len, "i(@%s[id])", dev);
    -             else if(prefix == 'i') my_snprintf(fqdev, len, "i(@%s[current])", dev);
    -             else my_snprintf(fqdev, len, "i(@%s[i])", dev);
    +             if(vsource) {
    +               my_snprintf(fqdev, len, "i(%s)", dev);
    +             } else if(prefix == 'q') {
    +               const char *current[] = {"ic", "ic", "ib", "ie"};
    +               my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]);
    +             } else if(prefix == 'd' || prefix == 'm') {
    +               const char *current[] = {"id", "id", "ig", "is", "ib"};
    +               my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]);
    +             } else if(prefix == 'i') {
    +               my_snprintf(fqdev, len, "i(@%s[current])");
    +             } else {
    +               my_snprintf(fqdev, len, "i(@%s[i])", dev);
    +             }
                }
              } else {
                my_snprintf(fqdev, len, "i(%s%s)", path, dev);
    
    From f79f9ecf1dbdfbaaee463d2f44a4d6aa9ce35b12 Mon Sep 17 00:00:00 2001
    From: stefan schippers 
    Date: Wed, 15 Jan 2025 19:12:30 +0100
    Subject: [PATCH 4/9] removed dbg mesages
    
    ---
     src/token.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/src/token.c b/src/token.c
    index c892b3b4..d70a6ad4 100644
    --- a/src/token.c
    +++ b/src/token.c
    @@ -4105,12 +4105,12 @@ const char *translate(int inst, const char* s)
                ++path;
              }
              dev = my_malloc(_ALLOC_ID_, tmp);
    -         dbg(0, "%s\n", token);
    +         dbg(1, "%s\n", token);
              if(!strncmp(token, "@spice_get_current(", 19)) {
                n = sscanf(token + 19, "%[^)]", dev);
              } else {
                n = sscanf(token, "@spice_get_current%d(%[^)]", &ncurrent, dev);
    -           dbg(0, "ncurrent=%d, dev=%s\n", ncurrent, dev);
    +           dbg(1, "ncurrent=%d, dev=%s\n", ncurrent, dev);
              }
              if(n >= 1) {
                strtolower(dev);
    
    From 315c5bd600945a596fda9a17a630d08009153476 Mon Sep 17 00:00:00 2001
    From: stefan schippers 
    Date: Thu, 16 Jan 2025 02:52:52 +0100
    Subject: [PATCH 5/9] added symbol attributes @spice_get_current_,
     @spice_get_modelparam_, @spice_get_modelvoltage_
    
    ---
     doc/xschem_man/symbol_property_syntax.html |  23 +++
     src/token.c                                | 189 ++++++++++++---------
     2 files changed, 136 insertions(+), 76 deletions(-)
    
    diff --git a/doc/xschem_man/symbol_property_syntax.html b/doc/xschem_man/symbol_property_syntax.html
    index d0ca082c..9aa02448 100644
    --- a/doc/xschem_man/symbol_property_syntax.html
    +++ b/doc/xschem_man/symbol_property_syntax.html
    @@ -619,6 +619,29 @@ verilog_format="xnor #(@risedel , @falldel ) @name ( @@Z , @@A , @@B );"
         sequence number n, extracted from simulation raw file (operating point or 
         cursor b position)

    +
  • @spice_get_voltage
  • +

    This attribute will be replaced by the voltage of the net attached to the first pin (pin number 0) + of the symbol

    + +
  • @spice_get_current
  • +

    This attribute will be replaced by the current through the first pin of the primitive symbol + according to the SPICE syntax. This can be used for elementary devices like voltage sources, + resistors, mosfets, bjts and so on. For example @spice_get_current will display the + drain current of a mosfet if this attribute is placed inside a MOS symbol.

    + +
  • @spice_get_current_param
  • +

    This will specify in param the current to display, for example:
    + @spice_get_current_ibs to get the body-source current in a Mosfet, + @spice_get_current_ie to get the emitter current in a Bjt.

    + +
  • @spice_get_modelvoltage_param
  • +

    This will specify in param the voltage to display, for example:
    + @spice_get_modelvoltage_vth to get the Vth in a Mosfet

    + +
  • @spice_get_modelparam_param
  • +

    This will specify in param the model parameter to display, for example:
    + @spice_get_modelparam_gm to get the transconductance in a Mosfet

    +
  • @spice_get_node spice_node
  • spice_node Will be replaced with the Spice simulated value for that node.
    diff --git a/src/token.c b/src/token.c index d70a6ad4..8745aaf6 100644 --- a/src/token.c +++ b/src/token.c @@ -3749,7 +3749,11 @@ const char *translate(int inst, const char* s) if(!get_sp_cur) { get_sp_cur = my_malloc(_ALLOC_ID_, sizeof(regex_t)); - regcomp(get_sp_cur, "^@spice_get_current[0-9]*\\(", REG_NOSUB | REG_EXTENDED); + /* @spice_get_current_param(...) or @spice_get_modelparam_param(...) */ + /* @spice_get_current(...) or @spice_get_modelparam(...) */ + /* @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...) */ + regcomp(get_sp_cur, + "^@spice_get_(current|modelparam|modelvoltage)(_[a-zA-Z][a-zA-Z0-9_]*)*\\(", REG_NOSUB | REG_EXTENDED); } sp_prefix = tclgetboolvar("spiceprefix"); @@ -4082,7 +4086,12 @@ const char *translate(int inst, const char* s) } } } - /* @spice_get_current(...) or @spice_get_current(...) */ + /* @spice_get_current(...) or @spice_get_current_param(...) + * @spice_get_modelparam(...) or @spice_get_modelparam_param(...) + * @spice_get_modelvoltage(...) or @spice_get_modelvoltage_param(...) + * + * Only @spice_get_current(...) and @spice_get_current_param(...) are processed + * the other types are ignored */ else if(!regexec(get_sp_cur, token, 0 , NULL, 0) ) { int start_level; /* hierarchy level where waves were loaded */ @@ -4090,10 +4099,9 @@ const char *translate(int inst, const char* s) if(live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) { char *fqdev = NULL; const char *path = xctx->sch_path[xctx->currsch] + 1; - char *dev = NULL; - int ncurrent = 1; + char *dev = NULL, *param = NULL; size_t len; - int idx, n; + int idx, n = 0; double val = 0.0; const char *valstr; tmp = strlen(token) + 1; @@ -4109,8 +4117,12 @@ const char *translate(int inst, const char* s) if(!strncmp(token, "@spice_get_current(", 19)) { n = sscanf(token + 19, "%[^)]", dev); } else { - n = sscanf(token, "@spice_get_current%d(%[^)]", &ncurrent, dev); - dbg(1, "ncurrent=%d, dev=%s\n", ncurrent, dev); + param = my_malloc(_ALLOC_ID_, tmp); + n = sscanf(token, "@spice_get_current_%s(%[^)]", param, dev); + if(n < 2) { + my_free(_ALLOC_ID_, ¶m); + n = sscanf(token, "@spice_get_current[^(](%[^)]", dev); + } } if(n >= 1) { strtolower(dev); @@ -4128,11 +4140,9 @@ const char *translate(int inst, const char* s) if(vsource) { my_snprintf(fqdev, len, "i(%c.%s%s.%s)", prefix, path, instname, dev); } else if(prefix == 'q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]); + my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "ic"); } else if(prefix == 'd' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, current[ncurrent]); + my_snprintf(fqdev, len, "i(@%c.%s%s.%s[%s])", prefix, path, instname, dev, param ? param : "id"); } else if(prefix == 'i') { my_snprintf(fqdev, len, "i(@%c.%s%s.%s[current])", prefix, path, instname, dev); } else { @@ -4165,6 +4175,7 @@ const char *translate(int inst, const char* s) dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); my_free(_ALLOC_ID_, &fqdev); } /* if(n == 1) */ + if(param) my_free(_ALLOC_ID_, ¶m); my_free(_ALLOC_ID_, &dev); } /* if(path) */ } /* if((start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) */ @@ -4235,17 +4246,22 @@ const char *translate(int inst, const char* s) } } } - else if(strncmp(token,"@spice_get_current", 18)==0 ) + else if( + strncmp(token,"@spice_get_current", 18)==0 || + strncmp(token,"@spice_get_modelparam", 21)==0 || + strncmp(token,"@spice_get_modelvoltage", 23)==0 + ) { int start_level; /* hierarchy level where waves were loaded */ int live = tclgetboolvar("live_cursor2_backannotate"); if(live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) { char *fqdev = NULL; const char *path = xctx->sch_path[xctx->currsch] + 1; - char *dev = NULL; - int ncurrent = 1; + char *dev = NULL, *param = NULL; + int modelparam = 0; /* 0: current, 1: modelparam, 2: modelvoltage */ size_t len; int idx; + int error = 0; double val = 0.0; const char *valstr; if(path) { @@ -4255,73 +4271,94 @@ const char *translate(int inst, const char* s) if(*path == '.') skip++; ++path; } - if(strcmp(token, "@spice_get_current")) { - if(sscanf(token, "@spice_get_current%d", &ncurrent) != 1) ncurrent = 1; + /* token contans _param after @spice_get_current or @spice_get_modelparam + * or @spice_get_modelvoltage */ + if(strcmp(token, "@spice_get_current") && + strcmp(token, "@spice_get_modelparam") && + strcmp(token, "@spice_get_modelvoltage")) { + int n = 0; + param = my_malloc(_ALLOC_ID_, strlen(token) + 1); + n = sscanf(token, "@spice_get_current_%s", param); + if(n == 0) { + n = sscanf(token, "@spice_get_modelparam_%s", param); + modelparam = 1; + } + if(n == 0) { + n = sscanf(token, "@spice_get_modelvoltage_%s", param); + modelparam = 2; + } + if(n == 0) { + my_free(_ALLOC_ID_, ¶m); + error = 1; + } } - my_strdup2(_ALLOC_ID_, &dev, instname); - strtolower(dev); - len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */ - dbg(1, "dev=%s\n", dev); - fqdev = my_malloc(_ALLOC_ID_, len); - if(!sim_is_xyce) { - int prefix=dev[0]; - int vsource = (prefix == 'v') || (prefix == 'e'); - if(path[0]) { - if(vsource) { - my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev); - } else if(prefix=='q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]); - } else if(prefix=='d' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%c.%s%s[%s])", prefix, path, dev, current[ncurrent]); - } else if(prefix=='i') { - my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev); + if(!error) { + char *iprefix = modelparam == 0 ? "i(" : modelparam == 1 ? "" : "v("; + char *ipostfix = modelparam == 1 ? "" : ")"; + my_strdup2(_ALLOC_ID_, &dev, instname); + strtolower(dev); + len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */ + dbg(1, "token=%s, dev=%s param=%s\n", token, dev, param ? param : ""); + fqdev = my_malloc(_ALLOC_ID_, len); + if(!sim_is_xyce) { + int prefix=dev[0]; + int vsource = (prefix == 'v') || (prefix == 'e'); + if(path[0]) { + if(vsource) { + my_snprintf(fqdev, len, "i(%c.%s%s)", prefix, path, dev); + } else if(prefix=='q') { + my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s", + iprefix, prefix, path, dev, param ? param : "ic", ipostfix); + } else if(prefix=='d' || prefix == 'm') { + my_snprintf(fqdev, len, "%s@%c.%s%s[%s]%s", + iprefix, prefix, path, dev, param ? param : "id", ipostfix); + } else if(prefix=='i') { + my_snprintf(fqdev, len, "i(@%c.%s%s[current])", prefix, path, dev); + } else { + my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev); + } } else { - my_snprintf(fqdev, len, "i(@%c.%s%s[i])", prefix, path, dev); + if(vsource) { + my_snprintf(fqdev, len, "i(%s)", dev); + } else if(prefix == 'q') { + my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "ic", ipostfix); + } else if(prefix == 'd' || prefix == 'm') { + my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "id", ipostfix); + } else if(prefix == 'i') { + my_snprintf(fqdev, len, "i(@%s[current])"); + } else { + my_snprintf(fqdev, len, "i(@%s[i])", dev); + } } } else { - if(vsource) { - my_snprintf(fqdev, len, "i(%s)", dev); - } else if(prefix == 'q') { - const char *current[] = {"ic", "ic", "ib", "ie"}; - my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]); - } else if(prefix == 'd' || prefix == 'm') { - const char *current[] = {"id", "id", "ig", "is", "ib"}; - my_snprintf(fqdev, len, "i(@%s[%s])", dev, current[ncurrent]); - } else if(prefix == 'i') { - my_snprintf(fqdev, len, "i(@%s[current])"); - } else { - my_snprintf(fqdev, len, "i(@%s[i])", dev); - } + my_snprintf(fqdev, len, "i(%s%s)", path, dev); } - } else { - my_snprintf(fqdev, len, "i(%s%s)", path, dev); - } - dbg(1, "fqdev=%s\n", fqdev); - strtolower(fqdev); - idx = get_raw_index(fqdev, NULL); - if(idx >= 0) { - val = xctx->raw->cursor_b_val[idx]; - } - if(idx < 0) { - valstr = "-"; - xctx->tok_size = 1; - len = 1; - } else { - valstr = engineering ? dtoa_eng(val) : dtoa(val); - len = xctx->tok_size; - } - if(len) { - STR_ALLOC(&result, len + result_pos, &size); - memcpy(result+result_pos, valstr, len+1); - result_pos += len; - } - dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); - my_free(_ALLOC_ID_, &fqdev); - my_free(_ALLOC_ID_, &dev); - } - } + if(param) my_free(_ALLOC_ID_, ¶m); + dbg(1, "fqdev=%s\n", fqdev); + strtolower(fqdev); + idx = get_raw_index(fqdev, NULL); + if(idx >= 0) { + val = xctx->raw->cursor_b_val[idx]; + } + if(idx < 0) { + valstr = "-"; + xctx->tok_size = 1; + len = 1; + } else { + valstr = engineering ? dtoa_eng(val) : dtoa(val); + len = xctx->tok_size; + } + if(len) { + STR_ALLOC(&result, len + result_pos, &size); + memcpy(result+result_pos, valstr, len+1); + result_pos += len; + } + dbg(1, "instname %s, dev=%s, fqdev=%s idx=%d valstr=%s\n", instname, dev, fqdev, idx, valstr); + my_free(_ALLOC_ID_, &fqdev); + my_free(_ALLOC_ID_, &dev); + } /* if(!error) */ + } /* if(path) */ + } /* (live && (start_level = sch_waves_loaded()) >= 0 && xctx->raw->annot_p>=0) */ } else if(strcmp(token,"@schvhdlprop")==0 && xctx->schvhdlprop) { From bcca65da908ae7483d2175e1b6c9f10754ceefdf Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 16 Jan 2025 15:35:11 +0100 Subject: [PATCH 6/9] translate(), @spice_get_current, typo led to missing argument in printf() --- src/token.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/token.c b/src/token.c index 8745aaf6..145c8e63 100644 --- a/src/token.c +++ b/src/token.c @@ -4297,7 +4297,7 @@ const char *translate(int inst, const char* s) char *ipostfix = modelparam == 1 ? "" : ")"; my_strdup2(_ALLOC_ID_, &dev, instname); strtolower(dev); - len = strlen(path) + strlen(dev) + 21; /* some extra chars for i(..) wrapper */ + len = strlen(path) + strlen(dev) + 40; /* some extra chars for i(..) wrapper */ dbg(1, "token=%s, dev=%s param=%s\n", token, dev, param ? param : ""); fqdev = my_malloc(_ALLOC_ID_, len); if(!sim_is_xyce) { @@ -4325,7 +4325,7 @@ const char *translate(int inst, const char* s) } else if(prefix == 'd' || prefix == 'm') { my_snprintf(fqdev, len, "%s@%s[%s]%s", iprefix, dev, param ? param : "id", ipostfix); } else if(prefix == 'i') { - my_snprintf(fqdev, len, "i(@%s[current])"); + my_snprintf(fqdev, len, "i(@%s[current])", dev); } else { my_snprintf(fqdev, len, "i(@%s[i])", dev); } From f2225677cc60195463840023868588ea1c05de05 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 16 Jan 2025 16:03:34 +0100 Subject: [PATCH 7/9] fix regression in (V) cursor movement when multiple side-by-side graphs are present --- src/callback.c | 89 +++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 56 deletions(-) diff --git a/src/callback.c b/src/callback.c index 9dfa4532..b4697452 100644 --- a/src/callback.c +++ b/src/callback.c @@ -451,12 +451,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int tcleval("graph_show_measure"); } /* if(xctx->graph_flags & 64) */ - - - - - - gr->master_gx1 = gr->gx1; gr->master_gx2 = gr->gx2; gr->master_gw = gr->gw; @@ -481,11 +475,41 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int need_redraw_master = 1; } + /* move cursor1 */ + /* set cursor position from master graph x-axis */ + else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) { + double c; + c = G_X(xctx->mousex); + if(gr->logx) c = pow(10, c); + if(r->flags & 4) { /* private_cursor */ + my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c))); + } else { + xctx->graph_cursor1_x = c; + } + need_all_redraw = 1; + } + /* move cursor2 */ + /* set cursor position from master graph x-axis */ + else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) { + double c; + int floaters = there_are_floaters(); - - - + c = G_X(xctx->mousex); + if(gr->logx) c = pow(10, c); + if(r->flags & 4) { /* private_cursor */ + my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c))); + } else { + xctx->graph_cursor2_x = c; + } + if(tclgetboolvar("live_cursor2_backannotate")) { + backannotate_at_cursor_b_pos(r, gr); + if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */ + need_fullredraw = 1; + } else { + need_all_redraw = 1; + } + } if(xctx->ui_state & GRAPHPAN) goto finish; /* After GRAPHPAN only need to check Motion events for cursors */ if(xctx->mousey_snap < W_Y(gr->gy2)) { @@ -909,53 +933,6 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int } } - - - /* move cursor1 */ - /* set cursor position from master graph x-axis */ - else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) { - double c; - - /* selected or locked or master */ - if( r->sel || !(r->flags & 2) || i == xctx->graph_master) { - c = G_X(xctx->mousex); - if(gr->logx) c = pow(10, c); - if(r->flags & 4) { /* private_cursor */ - my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor1_x", dtoa(c))); - } else { - xctx->graph_cursor1_x = c; - } - need_all_redraw = 1; - } - } - /* move cursor2 */ - /* set cursor position from master graph x-axis */ - else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 32 )) { - double c; - int floaters = there_are_floaters(); - - /* selected or locked or master */ - if( r->sel || !(r->flags & 2) || i == xctx->graph_master) { - c = G_X(xctx->mousex); - if(gr->logx) c = pow(10, c); - if(r->flags & 4) { /* private_cursor */ - my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "cursor2_x", dtoa(c))); - } else { - xctx->graph_cursor2_x = c; - } - if(tclgetboolvar("live_cursor2_backannotate")) { - backannotate_at_cursor_b_pos(r, gr); - if(floaters) set_modify(-2); /* update floater caches to reflect actual backannotation */ - need_fullredraw = 1; - } else { - need_all_redraw = 1; - } - } - } - - - - else if(event == ButtonPress && button == Button5 && !(state & ShiftMask)) { double delta; /* vertical move of waveforms with mouse wheel */ From ca6b8fe85b2b55c27a4e6e00b02ed0f42d7a57c4 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 16 Jan 2025 17:19:42 +0100 Subject: [PATCH 8/9] end_shape_point_edit(): fix erroneous set_modify because comparing unsmapped mouse saved coords with snapped actual mouse coords --- src/callback.c | 10 +++++++--- xschem_library/ngspice/solar_panel.sch | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/callback.c b/src/callback.c index b4697452..3b0e50ae 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1985,9 +1985,10 @@ static int handle_mouse_wheel(int event, int mx, int my, KeySym key, int button, return 0; } -static void end_shape_point_edit() +static void end_shape_point_edit(double c_snap) { int save = xctx->modified; + double sx, sy; dbg(1, "%g %g %g %g\n", xctx->mx_double_save, xctx->my_double_save, xctx->mousex_snap, xctx->mousey_snap); if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) { @@ -2033,7 +2034,10 @@ static void end_shape_point_edit() xctx->shape_point_selected = 0; xctx->need_reb_sel_arr=1; } - if(xctx->mx_double_save == xctx->mousex_snap && xctx->my_double_save == xctx->mousey_snap) { + sx = my_round(xctx->mx_double_save / c_snap) * c_snap; + sy = my_round(xctx->my_double_save / c_snap) * c_snap; + + if(sx == xctx->mousex_snap && sy == xctx->mousey_snap) { set_modify(save); } } @@ -4106,7 +4110,7 @@ int rstate; /* (reduced state, without ShiftMask) */ /* if a polygon/bezier/rectangle control point was clicked, end point move operation * and set polygon state back to SELECTED from SELECTED1 */ else if((xctx->ui_state & (STARTMOVE | SELECTION)) && xctx->shape_point_selected) { - end_shape_point_edit(); + end_shape_point_edit(c_snap); } if(xctx->ui_state & STARTPAN) { diff --git a/xschem_library/ngspice/solar_panel.sch b/xschem_library/ngspice/solar_panel.sch index 8cd6c87a..046ef49c 100644 --- a/xschem_library/ngspice/solar_panel.sch +++ b/xschem_library/ngspice/solar_panel.sch @@ -295,7 +295,7 @@ lab=0} C {title.sym} 160 -40 0 0 {name=l1 author="Stefan Schippers"} C {code_shown.sym} 170 -310 0 0 {name=CONTROL value="tcleval( -.option savecurrents +.probe alli .control * example of tcl evaluation of code blocks: * current path: $path From c57c49fde8b9bdb03f9f85457ace7ae5d94c5f03 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Thu, 16 Jan 2025 20:37:19 +0100 Subject: [PATCH 9/9] Hiding the TEXT layer will disable only symbol texts on that layer, not all texts, `proc select_layers` make the widget non-modal --- src/draw.c | 7 ++++++- src/xschem.tcl | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/draw.c b/src/draw.c index df693b78..2066be3d 100644 --- a/src/draw.c +++ b/src/draw.c @@ -561,7 +561,6 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, disabled = 1; } - if( (layer != PINLAYER && !xctx->enable_layer[layer]) ) return; if(!has_x) return; if( (xctx->inst[n].flags & HIDE_INST) || (xctx->hide_symbols==1 && (xctx->inst[n].ptr+ xctx->sym)->prop_ptr && @@ -620,6 +619,9 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, x0=xctx->inst[n].x0 + xoffset; y0=xctx->inst[n].y0 + yoffset; symptr = (xctx->inst[n].ptr+ xctx->sym); + + if( (layer != PINLAYER && !xctx->enable_layer[layer]) ) goto draw_texts; + if(!hide) { for(j=0;j< symptr->lines[layer]; ++j) { @@ -713,6 +715,9 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, } } } + + draw_texts: + if( !(xctx->inst[n].flags & HIDE_SYMBOL_TEXTS) && ( diff --git a/src/xschem.tcl b/src/xschem.tcl index 7edac6b3..ca81fb4a 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -5129,7 +5129,7 @@ proc tclcmd {} { proc select_layers {} { global dark_colorscheme enable_layer - xschem set semaphore [expr {[xschem get semaphore] +1}] + # xschem set semaphore [expr {[xschem get semaphore] +1}] toplevel .sl -class Dialog wm transient .sl [xschem get topwindow] if { $dark_colorscheme == 1 } { @@ -5182,6 +5182,7 @@ proc select_layers {} { -selectcolor $ind_bg -anchor w -foreground $layfg -background $i -activebackground $i \ -command { xschem enable_layers + xschem redraw } pack .sl.f0.f$f.cb$j -side top -fill x incr j @@ -5191,8 +5192,8 @@ proc select_layers {} { pack .sl.f0.f$f -side left -fill y } } - tkwait window .sl - xschem set semaphore [expr {[xschem get semaphore] -1}] + # tkwait window .sl + # xschem set semaphore [expr {[xschem get semaphore] -1}] } proc color_dim {} {