do not do a rectangle zoom (`z` key) if no minimum area is given; added `xschem get symbols` command; added `derived_symbols` in `xschem symbols` command; added menu `simulations->Keep symbols when traversing hierarchy`; created `proc cellview` and integrated `traversal.tcl` into xschem.tcl

This commit is contained in:
stefan schippers 2024-12-29 12:38:26 +01:00
parent 61c4f72c15
commit 0ffd327b85
5 changed files with 239 additions and 37 deletions

View File

@ -551,7 +551,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> abort_operation</kbd></li><pre>
@ -798,6 +797,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> schtedaxprop </kbd> get schematic "tedax" global attributes </li>
<li><kbd> sch_path </kbd> get hierarchy path. if 'n' given get hierpath of level 'n' </li>
<li><kbd> sch_to_compare </kbd> if set return schematic current design is compared with </li>
<li><kbd> symbols </kbd> number of loaded symbols </li>
<li><kbd> temp_dir </kbd> get windows temporary dir </li>
<li><kbd> text_svg </kbd> return 1 if using &lt;text&gt; elements in svg export </li>
<li><kbd> textlayer </kbd> layer number for texts </li>
@ -1513,9 +1513,11 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
returns 0 if switch was successfull or 1 in case of errors
(no tabs/windows present or no matching winpath / schematic name
found).</pre>
<li><kbd> symbols [n]</kbd></li><pre>
if 'n' given list symbol with name or number 'n', else
list all used symbols </pre>
<li><kbd> symbols [n | 'derived_symbols']</kbd></li><pre>
if 'n' given list symbol with name or number 'n', else list all
if 'derived_symbols' is given list also symbols derived from base symbol
due to instance based implementation selection. This option must be used
after a netlist operation with 'keep_symbols' TCL variable set to 1 </pre>
<li><kbd> tab_list</kbd></li><pre>
list all windows / tabs with window pathname and associated filename </pre>
<li><kbd> table_read [table_file]</kbd></li><pre>
@ -1679,6 +1681,8 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"

View File

@ -2823,17 +2823,19 @@ void zoom_rectangle(int what)
{
xctx->ui_state &= ~STARTZOOM;
RECTORDER(xctx->nl_x1,xctx->nl_y1,xctx->nl_x2,xctx->nl_y2);
drawtemprect(xctx->gctiled, NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
xctx->xorigin=-xctx->nl_x1;xctx->yorigin=-xctx->nl_y1;
xctx->zoom=(xctx->nl_x2-xctx->nl_x1)/(xctx->areaw-4*INT_WIDTH(xctx->lw));
xctx->nl_yy1=(xctx->nl_y2-xctx->nl_y1)/(xctx->areah-4*INT_WIDTH(xctx->lw));
if(xctx->nl_yy1>xctx->zoom) xctx->zoom=xctx->nl_yy1;
xctx->mooz=1/xctx->zoom;
change_linewidth(-1.);
draw();
redraw_w_a_l_r_p_rubbers();
dbg(1, "zoom_rectangle(): coord: %.16g %.16g %.16g %.16g zoom=%.16g\n",
xctx->nl_x1,xctx->nl_y1,xctx->mousex_snap, xctx->mousey_snap,xctx->zoom);
drawtemprect(xctx->gctiled, NOW, xctx->nl_xx1, xctx->nl_yy1, xctx->nl_xx2, xctx->nl_yy2);
if( xctx->nl_x1 != xctx->nl_x2 || xctx->nl_y1 != xctx->nl_y2) {
xctx->xorigin = -xctx->nl_x1; xctx->yorigin = -xctx->nl_y1;
xctx->zoom = (xctx->nl_x2 - xctx->nl_x1) / (xctx->areaw - 4 * INT_WIDTH(xctx->lw));
xctx->nl_yy1=(xctx->nl_y2 - xctx->nl_y1) / (xctx->areah - 4 * INT_WIDTH(xctx->lw));
if(xctx->nl_yy1 > xctx->zoom) xctx->zoom = xctx->nl_yy1;
xctx->mooz = 1 / xctx->zoom;
change_linewidth(-1.);
draw();
redraw_w_a_l_r_p_rubbers();
dbg(1, "zoom_rectangle(): coord: %.16g %.16g %.16g %.16g zoom=%.16g\n",
xctx->nl_x1, xctx->nl_y1, xctx->mousex_snap, xctx->mousey_snap, xctx->zoom);
}
}
if(what & RUBBER)
{

View File

@ -1595,6 +1595,11 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, xctx->sch_to_compare, TCL_VOLATILE);
}
else if(!strcmp(argv[2], "symbols")) { /* number of loaded symbols */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
Tcl_SetResult(interp, my_itoa(xctx->symbols), TCL_VOLATILE);
}
break;
case 't':
#ifndef __unix__
@ -2857,7 +2862,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!is_from_web(argv[2])) {
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f);
tclvareval("file normalize {", tclresult(), "}", NULL);
/* tclvareval("file normalize {", tclresult(), "}", NULL); */
my_strncpy(f, abs_sym_path(tclresult(), ""), S(f));
} else {
my_strncpy(f, argv[2], S(f));
@ -5585,20 +5590,32 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_SetResult(interp, my_itoa(r), TCL_VOLATILE);
}
/* symbols [n]
* if 'n' given list symbol with name or number 'n', else
* list all used symbols */
/* symbols [n | 'derived_symbols']
* if 'n' given list symbol with name or number 'n', else list all
* if 'derived_symbols' is given list also symbols derived from base symbol
* due to instance based implementation selection. This option must be used
* after a netlist operation with 'keep_symbols' TCL variable set to 1 */
else if(!strcmp(argv[1], "symbols"))
{
int i;
int derived_symbols = 0;
int one_symbol = 0;
char n[100];
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
if(argc > 2 && !strcmp(argv[2], "derived_symbols")) derived_symbols = 1;
else if(argc > 2) {
one_symbol = 1;
i = get_symbol(argv[2]);
Tcl_AppendResult(interp, my_itoa(i), " {", xctx->sym[i].name, "}", NULL);
} else for(i=0; i<xctx->symbols; ++i) {
my_snprintf(n , S(n), "%d", i);
Tcl_AppendResult(interp, " {", n, " ", "{", xctx->sym[i].name, "}", "}\n", NULL);
if(i >=0) Tcl_AppendResult(interp, my_itoa(i), " {", xctx->sym[i].name, "}", NULL);
else Tcl_SetResult(interp, "", TCL_STATIC);
}
if(!one_symbol) {
for(i=0; i<xctx->symbols; ++i) {
const char *base_name = xctx->sym[i].base_name;
if(base_name && !derived_symbols) continue;
my_snprintf(n , S(n), "%d", i);
Tcl_AppendResult(interp, " {", n, " ", "{", xctx->sym[i].name, "}", "}\n", NULL);
}
}
}
else { cmd_found = 0;}

View File

@ -41,8 +41,7 @@ proc traversal {file {only_subckts {0}}} {
}
# return "$n * $indent" spaces
proc spaces {n} {
set indent 4
proc spaces {n {indent 4}} {
set n [expr {$n * $indent}]
# return [format %${n}s {}]
return [string repeat { } $n]

View File

@ -686,6 +686,13 @@ proc ev0 {args} {
}
}
# return "$n * $indent" spaces
proc spaces {n {indent 4}} {
set n [expr {$n * $indent}]
# return [format %${n}s {}]
return [string repeat { } $n]
}
# wraps provided table formatted text into a nice looking bordered table
# sep is the list of characters used as separators, default are { }, {,}, {\t}
# if you want to tabulate data with spaces use only {,} as separator or any other character.
@ -1610,10 +1617,8 @@ proc simconf {} {
# wm transient .sim [xschem get topwindow]
frame .sim.topf
set scrollframe [sframe .sim.topf]
frame ${scrollframe}.top
frame ${scrollframe}.center
frame .sim.bottom
pack ${scrollframe}.top -fill x
pack ${scrollframe}.center -fill both -expand yes
set bg(0) {#dddddd}
set bg(1) {#aaaaaa}
@ -1755,6 +1760,177 @@ proc simconf_add {tool} {
incr sim($tool,n)
}
proc cellview {} {
global keep_symbols
if {[info tclversion] >= 8.5} {
set font Monospace
} else {
set font fixed
}
toplevel .cv
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
set keep_symbols $save_keep
wm geometry .cv 800x200
update
raise .cv
frame .cv.top
label .cv.top.sym -text { SYMBOL} -width 20 -bg grey60 -anchor w -padx 4 -font $font
label .cv.top.sch -text SCHEMATIC -width 50 -bg grey60 -anchor w -padx 4 -font $font
label .cv.top.pad -text { } -width 1 -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
set sf [sframe .cv.center]
# puts sf=$sf
set syms [join [lsort -index 1 [xschem symbols]]]
foreach {i sym} $syms {
set abs_sch [xschem get_sch_from_sym -1 $sym]
set sch [rel_sym_path $abs_sch]
set default_sch [add_ext $sym .sch]
set type [xschem getprop symbol $sym type]
set spice_sym_def [xschem getprop symbol $sym spice_sym_def]
if {$type eq {subcircuit}} {
frame $sf.f$i
pack $sf.f$i -side top -fill x
label $sf.f$i.l -text $sym -width 20 -anchor w -padx 4 -borderwidth 1 \
-relief sunken -pady 1 -bg grey80 -font $font
# puts $sf.f$i.s
entry $sf.f$i.s -width 50 -borderwidth 1 -relief sunken -font $font
if { $spice_sym_def eq {}} {
if {![file exists $abs_sch]} {
$sf.f$i.s configure -bg red
} elseif {$default_sch ne $sch} {
$sf.f$i.s configure -bg cyan
}
}
balloon $sf.f$i.s $abs_sch
button $sf.f$i.b -text Open -padx 4 -borderwidth 1 -pady 0 -font $font \
-command "
if { {$spice_sym_def} eq {}} {
xschem load_new_window \[$sf.f$i.s get\]
} else {
viewdata {$spice_sym_def}
}"
if {$spice_sym_def eq {}} {
$sf.f$i.s insert 0 $sch
} else {
$sf.f$i.s insert 0 {<<spice_sym_def>>}
}
bind $sf.f$i.s <KeyRelease> "
if {\[$sf.f$i.s get\] ne {$sch}} {
if { \[file exists \[abs_sym_path \[$sf.f$i.s get\]\]\] } {
$sf.f$i.s configure -bg cyan
} else {
puts \"$sch --- \[$sf.f$i.s get\]\"
$sf.f$i.s configure -bg red
}
} else {
if { \[file exists \[abs_sym_path \[$sf.f$i.s get\]\]\] } {
$sf.f$i.s configure -bg grey90
} else {
$sf.f$i.s configure -bg red
}
}
"
pack $sf.f$i.l $sf.f$i.s -side left -fill x -expand 1
pack $sf.f$i.b -side left
}
}
frame .cv.bottom
label .cv.bottom.status -text {STATUS LINE}
pack .cv.bottom.status -fill x -expand yes
pack .cv.top -side top -fill x -expand no
pack .cv.center -side top -fill both -expand yes
pack .cv.bottom -side top -fill x -expand no
sframeyview .cv.center place
set maxsize [expr {[winfo height ${sf}] + [winfo height .cv.top] + [winfo height .cv.bottom]}]
wm maxsize .cv 9999 $maxsize
bind .cv.center.f <Configure> {sframeyview .cv.center}
bind .cv <ButtonPress-4> { sframeyview .cv.center scroll -0.2}
bind .cv <ButtonPress-5> { sframeyview .cv.center scroll 0.2}
xschem reload_symbols ;# purge all symbols used in below hierarchies
}
############ traversal
# This proc traverses the hierarchy and prints all instances in design.
proc traversal {file {only_subckts {0}}} {
global keep_symbols
if { $file eq {} || [file exists $file] } {
puts stderr "empty or existing file..."
return
}
set keep_symbols 1
xschem unselect_all
xschem set no_draw 1 ;# disable screen update
xschem set no_undo 1 ;# disable undo
set fd [open $file "w"]
hier_traversal $fd 0 $only_subckts
xschem set no_draw 0
xschem set no_undo 0
set keep_symbols 0
close $fd
}
# recursive procedure
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]
set schematic [xschem get_sch_from_sym $i]
set sch_exists [expr {[file exists $schematic] ? {} : {**missing**}}]
set sch_tail [file tail $schematic]
set sch_rootname [file rootname [file tail $schematic]]
set inst_spice_sym_def [xschem getprop instance $i spice_sym_def]
set sym_spice_sym_def [xschem getprop instance $i cell::spice_sym_def]
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 $type"
puts -nonewline $fd "[spaces $level] $symbol"
if {$type eq {subcircuit}} {
puts -nonewline $fd { ---> }
if {$inst_spice_sym_def ne {}} {puts $fd "$sch_rootname defined in instance spice_sym_def"
} elseif {$sym_spice_sym_def ne {}} {puts $fd "$sch_rootname defined in symbol spice_sym_def"
} else { puts $fd "$sch_tail $sch_exists" }
} else { puts $fd {} }
set done_print 1
if {$type eq {subcircuit}} {
xschem select instance $i fast
set descended [xschem descend 1 6]
if {$descended} {
incr level
set dp [hier_traversal $fd $level $only_subckts]
xschem go_back 1
incr level -1
}
}
}
return $done_print
}
############ /traversal
proc bespice_getdata {sock} {
global bespice_server_getdata
if {[eof $sock] || [catch {gets $sock bespice_server_getdata(line,$sock)}]} {
@ -2704,6 +2880,13 @@ proc set_rect_flags {graph_selected} {
xschem setprop rect 2 $graph_selected flags "graph$unlocked$private_cursor" fast
}
proc graphdialog_set_raw_props {} {
global graph_selected
xschem setprop rect 2 $graph_selected rawfile [.graphdialog.center.right.rawentry get] fast
xschem setprop rect 2 $graph_selected sim_type [.graphdialog.center.right.list get] fast
graph_fill_listbox
}
proc graph_edit_properties {n} {
global graph_bus graph_sort graph_digital graph_selected graph_sel_color graph_legend
global graph_unlocked graph_schname graph_logx graph_logy cadlayers graph_rainbow
@ -2838,17 +3021,12 @@ proc graph_edit_properties {n} {
regsub {/$} $netlist_dir {} netlist_dir
.graphdialog.center.right.rawentry delete 0 end
.graphdialog.center.right.rawentry insert 0 [string map [list $netlist_dir {$netlist_dir}] [select_raw]]
xschem setprop rect 2 $graph_selected rawfile [.graphdialog.center.right.rawentry get] fast
xschem setprop rect 2 $graph_selected sim_type [.graphdialog.center.right.list get] fast
graph_fill_listbox
graphdialog_set_raw_props
}
bind .graphdialog.center.right.rawentry <KeyRelease> {
xschem setprop rect 2 $graph_selected rawfile [.graphdialog.center.right.rawentry get] fast
xschem setprop rect 2 $graph_selected sim_type [.graphdialog.center.right.list get] fast
graph_fill_listbox
}
bind .graphdialog.center.right.rawentry <KeyRelease> graphdialog_set_raw_props
bind .graphdialog.center.right.rawentry <Leave> graphdialog_set_raw_props
.graphdialog.center.right.rawentry insert 0 [xschem getprop rect 2 $graph_selected rawfile 2]
.graphdialog.center.right.rawentry xview moveto 1
text .graphdialog.center.right.text1 -undo 1 -wrap none -width 50 -height 5 -background grey90 -fg black \
@ -8042,6 +8220,8 @@ proc build_widgets { {topwin {} } } {
}
$topwin.menubar.simulation.menu add checkbutton -label "Show netlist after netlist command" \
-selectcolor $selectcolor -variable netlist_show -accelerator {Shift+A}
$topwin.menubar.simulation.menu add checkbutton -label "Keep symbols when traversing hierarchy" \
-selectcolor $selectcolor -variable keep_symbols
$topwin.menubar.simulation.menu add radiobutton -indicatoron 1 -label "Use netlist directory" \
-background grey60 -variable local_netlist_dir -value 0 \
-selectcolor $selectcolor -command {set_netlist_dir 1 }