From 94d5c445993f7a9e1b2f144005187666f1e1a6bd Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sun, 3 Nov 2024 00:22:40 +0100 Subject: [PATCH] xschem change_sch_path command for changing the current path we are descended in; set_title parameter for xschem descend and xschem go_back (optimization for faster scripts). optimized utility procedure traversal.tcl. Catch glob pattern errors in proc setglob --- src/actions.c | 50 +++++++++++++++++++++++++++++++++++++++++++---- src/callback.c | 8 ++++---- src/editprop.c | 4 ++-- src/scheduler.c | 46 ++++++++++++++++++++++++++++++++++--------- src/traversal.tcl | 33 +++++++++++++++++++++++-------- src/xschem.h | 5 +++-- src/xschem.tcl | 9 +++++++-- 7 files changed, 124 insertions(+), 31 deletions(-) diff --git a/src/actions.c b/src/actions.c index db087fe1..bbcaa047 100644 --- a/src/actions.c +++ b/src/actions.c @@ -2143,8 +2143,50 @@ void get_sch_from_sym(char *filename, xSymbol *sym, int inst, int fallback) dbg(1, "get_sch_from_sym(): sym->name=%s, filename=%s\n", sym->name, filename); } +int change_sch_path(int instnumber, int dr) +{ + int level = xctx->currsch - 1; + char *instname = NULL; + char *expanded_instname = NULL; + int inst_mult; + char *path = NULL; + char *ptr; + size_t pathlen; + int res = 0; + if(level <= 0 ) return 0; + my_strdup2(_ALLOC_ID_, &instname, get_tok_value(xctx->hier_attr[level].prop_ptr, "name", 0)); + my_strdup2(_ALLOC_ID_, &expanded_instname, expandlabel(instname, &inst_mult)); + my_strdup2(_ALLOC_ID_, &path, xctx->sch_path[xctx->currsch]); + if(instnumber < 0 ) instnumber += inst_mult+1; + /* any invalid number->descend to leftmost inst */ + if(instnumber <1 || instnumber > inst_mult) instnumber = 1; + pathlen = strlen(path); + if(pathlen == 0) goto end; + path[pathlen - 1] = '\0'; + ptr = strrchr(path, '.'); + if(!ptr) goto end; + *(ptr+1) = '\0'; + my_free(_ALLOC_ID_, &xctx->sch_path[xctx->currsch]); + my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], path); + my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], find_nth(expanded_instname, ",", "", 0, instnumber)); + my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], "."); + xctx->sch_path_hash[xctx->currsch] = 0; + xctx->sch_inst_number[level] = instnumber; + dbg(0, "instname=%s, path=%s\n", instname, path); + path[pathlen - 1] = '.'; + res = 1; + if(dr && has_x) { + draw(); + } + end: + my_free(_ALLOC_ID_, &instname); + my_free(_ALLOC_ID_, &path); + my_free(_ALLOC_ID_, &expanded_instname); + return res; +} + /* fallback = 1: if schematic=.. attr is set but file not existing descend into symbol base schematic */ -int descend_schematic(int instnumber, int fallback, int alert) +int descend_schematic(int instnumber, int fallback, int alert, int set_title) { char *str = NULL; char filename[PATH_MAX]; @@ -2297,7 +2339,7 @@ int descend_schematic(int instnumber, int fallback, int alert) dbg(1, "descend_schematic(): filename=%s\n", filename); /* we are descending from a parent schematic downloaded from the web */ if(!tclgetboolvar("keep_symbols")) remove_symbols(); - load_schematic(1, filename, 1, alert); + load_schematic(1, filename, set_title, alert); if(xctx->hilight_nets) { prepare_netlist_structs(0); propagate_hilights(1, 0, XINSERT_NOREPLACE); @@ -2317,7 +2359,7 @@ int descend_schematic(int instnumber, int fallback, int alert) return 1; } -void go_back(int confirm) /* 20171006 add confirm */ +void go_back(int confirm, int set_title) /* 20171006 add confirm */ { int save_ok; int from_embedded_sym; @@ -2363,7 +2405,7 @@ void go_back(int confirm) /* 20171006 add confirm */ /* by default) to parent schematic if going back from embedded symbol */ my_strncpy(filename, xctx->sch[xctx->currsch], S(filename)); - load_schematic(1, filename, 1, 1); + load_schematic(1, filename, set_title, 1); /* if we are returning from a symbol created from a generator don't set modified flag on parent * as these symbols can not be edited / saved as embedded * xctx->sch_inst_number[xctx->currsch + 1] == -1 --> we came from an inst with no embed flag set */ diff --git a/src/callback.c b/src/callback.c index c412077e..5ff3bb12 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1727,13 +1727,13 @@ static void context_menu_action(double mx, double my) edit_property(1); break; case 12: - descend_schematic(0, 1, 1); + descend_schematic(0, 1, 1, 1); break; case 13: descend_symbol(); break; case 14: - go_back(1); + go_back(1, 1); break; case 15: /* copy selection into clipboard */ rebuild_selected_array(); @@ -2791,7 +2791,7 @@ int rstate; /* (reduced state, without ShiftMask) */ if(key=='e' && rstate == 0) /* descend to schematic */ { if(xctx->semaphore >= 2) break; - descend_schematic(0, 1, 1);break; + descend_schematic(0, 1, 1, 1);break; } if(key=='e' && EQUAL_MODMASK) /* edit schematic in new window */ { @@ -2834,7 +2834,7 @@ int rstate; /* (reduced state, without ShiftMask) */ if( (key=='e' && rstate == ControlMask) || (key==XK_BackSpace)) /* back */ { if(xctx->semaphore >= 2) break; - go_back(1);break; + go_back(1, 1);break; } if(key=='a' && rstate == 0) /* make symbol */ diff --git a/src/editprop.c b/src/editprop.c index bbe8a1b5..95c950b7 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -703,10 +703,10 @@ void *my_malloc(int id, size_t size) void my_realloc(int id, void *ptr,size_t size) { void *a; - char old[100]; + char old[100] = ""; void *tmp; a = *(void **)ptr; - my_snprintf(old, S(old), "%p", a); + if(debug_var > 2) my_snprintf(old, S(old), "%p", a); if(size == 0) { free(*(void **)ptr); dbg(3, "\nmy_free(%d,): my_realloc_freeing %p\n",id, *(void **)ptr); diff --git a/src/scheduler.c b/src/scheduler.c index bbd76765..d5069971 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -454,6 +454,21 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } } + /* change_sch_path n + * if descended into a vector instance change inst number we are into to 'n', + * (same rules as 'descend' command) without going up and descending again + * if 'draw' string is given redraw screen */ + else if(!strcmp(argv[1], "change_sch_path")) + { + int dr = 0; + if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} + if(argc > 3 && !strcmp(argv[3], "draw")) dr = 1; + if(argc > 2) { + int n = atoi(argv[2]); + change_sch_path(n, dr); + } + } + /* check_symbols * List all used symbols in current schematic and warn if some symbol is newer */ else if(!strcmp(argv[1], "check_symbols")) @@ -763,19 +778,27 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg delete_files(); } - /* descend [n] + /* descend [n] [notitle] * Descend into selected component instance. Optional number 'n' specifies the - * instance number to descend into for vector instances (default: 0). */ + * instance number to descend into for vector instances (default: 0). + * 0 or 1: leftmost instance, 2: second leftmost instance, ... + * -1: rightmost instance,-2: second rightmost instance, ... + * if string 'notitle' is given do not update window title (slow) */ else if(!strcmp(argv[1], "descend")) { int ret=0; + int set_title = 1; if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(xctx->semaphore == 0) { + + if(argc > 3 && !strcmp(argv[3], "notitle")) { + set_title = 0; + } if(argc > 2) { int n = atoi(argv[2]); - ret = descend_schematic(n, 0, 0); + ret = descend_schematic(n, 0, 0, set_title); } else { - ret = descend_schematic(0, 0, 0); + ret = descend_schematic(0, 0, 0, set_title); } } Tcl_SetResult(interp, dtoa(ret), TCL_VOLATILE); @@ -2019,12 +2042,17 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg #endif } - /* go_back - * Go up one level (pop) in hierarchy */ + /* go_back [notitle] + * Go up one level (pop) in hierarchy + * if string 'notitle' is given do not update window title (slow) */ else if(!strcmp(argv[1], "go_back")) { + int set_title = 1; if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} - if((xctx->semaphore == 0)) go_back(1); + if(argc > 2 && !strcmp(argv[2], "notitle")) { + set_title = 0; + } + if((xctx->semaphore == 0)) go_back(1, set_title); Tcl_ResetResult(interp); } @@ -5765,8 +5793,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else { cmd_found = 0;} break; case 'u': /*----------------------------------------------*/ - /* undo - Undo last action */ + /* undo [redo [set_modify] + Undo last action. Optional integers redo and set_modify are passed to pop_undo() */ if(!strcmp(argv[1], "undo")) { int redo = 0, set_modify = 1; diff --git a/src/traversal.tcl b/src/traversal.tcl index ac36e1e1..05fb1bdf 100644 --- a/src/traversal.tcl +++ b/src/traversal.tcl @@ -22,7 +22,7 @@ # This script traverses the hierarchy and prints all instances in design. -proc traversal {file} { +proc traversal {file {only_subckts {}}} { if { $file eq {} || [file exists $file] } { puts stderr "empty or existing file..." return @@ -31,7 +31,7 @@ proc traversal {file} { xschem set no_draw 1 ;# disable screen update xschem set no_undo 1 ;# disable undo set fd [open $file "w"] - hier_traversal $fd 0 + hier_traversal $fd 0 $only_subckts xschem set no_draw 0 xschem set no_undo 0 close $fd @@ -46,31 +46,48 @@ proc spaces {n} { } # recursive procedure -proc hier_traversal {fd {level 0}} { +proc hier_traversal {fd {level 0} only_subckts} { + global nolist_libs + set done_print 0 set schpath [xschem get sch_path] set instances [xschem get instances] set current_level [xschem get currsch] for {set i 0} { $i < $instances} { incr i} { set instname [xschem getprop instance $i name] set symbol [xschem getprop instance $i cell::name] + set abs_symbol [abs_sym_path $symbol] set type [xschem getprop symbol $symbol type] + if {$only_subckts && ($type ne {subcircuit})} { continue } + + set skip 0 + foreach j $nolist_libs { + if {[regexp $j $abs_symbol]} { + set skip 1 + break + } + } + if {$skip} { continue } puts $fd "[spaces $level]$schpath$instname symbol: $symbol, type: $type" + set done_print 1 if {$type eq {subcircuit}} { set ninst [lindex [split [xschem expandlabel $instname] { }] 1] for {set n 1} {$n <= $ninst} { incr n} { + # set dp 0 xschem select instance $i - # descending ninst times is extremely inefficient --FIXME-- - xschem descend $n + # descending ninst times is extremely inefficient + set descended [xschem descend $n notitle] # ensure previous descend was successful - if {[xschem get currsch] == $current_level + 1} { + if {$descended} { incr level - hier_traversal $fd $level - xschem go_back + set dp [hier_traversal $fd $level $only_subckts] + xschem go_back notitle incr level -1 } + if {!$dp} { break } ;# nothing printed so skip all other vector instances } } } + return $done_print } diff --git a/src/xschem.h b/src/xschem.h index 7ed3e5d4..5af62861 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1520,8 +1520,9 @@ extern void get_sch_from_sym(char *filename, xSymbol *sym, int inst, int fallbac extern const char *get_sym_name(int inst, int ndir, int ext, int abs_path); extern void toggle_ignore(void); extern void get_additional_symbols(int what); -extern int descend_schematic(int instnumber, int fallback, int alert); -extern void go_back(int confirm); +extern int change_sch_path(int instnumber, int dr); +extern int descend_schematic(int instnumber, int fallback, int alert, int set_title); +extern void go_back(int confirm, int set_title); extern void clear_schematic(int cancel, int symbol); extern void view_unzoom(double z); extern void view_zoom(double z); diff --git a/src/xschem.tcl b/src/xschem.tcl index a24283d7..87b2917a 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -3574,8 +3574,13 @@ proc setglob {dir} { if {$OS == "Windows"} { regsub {:} $file_dialog_globfilter {\:} file_dialog_globfilter } - set file_dialog_files2 ${file_dialog_files2}\ [lsort [ - glob -nocomplain -directory $dir -tails -type {f} $file_dialog_globfilter]] + + if {![catch {glob -nocomplain -directory $dir -tails -type {f} $file_dialog_globfilter} res]} { + set flist $res + } else { + set flist [glob -nocomplain -directory $dir -tails -type {f} {*}] + } + set file_dialog_files2 ${file_dialog_files2}\ [lsort $flist] } }