diff --git a/tools/modelsim/commands.do b/tools/modelsim/commands.do index 0664b008bdcb672395f4aa2f847013d0a0eb92a1..548f0a63d80dd760358b94435362b362bac64bbd 100644 --- a/tools/modelsim/commands.do +++ b/tools/modelsim/commands.do @@ -1,6 +1,6 @@ ############################################################################### # -# Copyright (C) 2009 +# Copyright (C) 2014 # ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> # P.O.Box 2, 7990 AA Dwingeloo, The Netherlands # @@ -24,48 +24,34 @@ # # * The user commands are typically used at the Modelsim prompt are: # -# . lp <name> : load UniBoard <name>.mpf project -# . mk <name> : make one or range of UniBoard mpf projects +# . lp <name> : load HDL library <name>.mpf project +# . mk <name> : make one or range of HDL library mpf projects # . as # : add signals for # levels of hierarchy to the wave window # . ds : delete all signals from the wave window # # * The other procedures in this commands.do are internal command procedures -# that are typically not used at the Modelsim prompt. However they can be -# used to create user commands for other projects (i.e. another arg_env then -# UNB with other arg_dir for the libraries). -# -# * The general lp and mk commands assume that the Modelsim project file is -# located at: -# -# "$env($arg_env)/Firmware/$sdir/$arg_lib/build/sim/modelsim" -# -# or for designs with an SOPC system at: -# -# "$env($arg_env)/Firmware/$sdir/$arg_lib/build/synth/quartus/*_sim/" +# that are typically not used at the Modelsim prompt. # # * The recommended project directory structure is: # -# $arg_lib/build/sim/modelsim : Modelsim project file -# /synth/quartus : Quartus project file -# /src/vhdl : VHDL source code that gets synthesized -# /tb/vhdl : VHDL source code for test bench +# $arg_lib/build/modelsim : Modelsim project file +# /quartus : Quartus project file +# /src/vhdl : VHDL source code that gets synthesized +# /tb/vhdl : VHDL source code for test bench +# +# Alternatively the build/ directory may be located at another more central +# location. # - #------------------------------------------------------------------------------- -# UniBoard settings +# HDL library settings #------------------------------------------------------------------------------- -puts "Loading general UniBoard commands..." +puts "Loading general HDL library commands..." -# UniBoard environment variable -proc unb_env {} { - return "UNB" -} - -# UniBoard project directories -proc unb_dir {} { - return {"designs" "modules" "modules/Altera" "modules/MegaWizard" "modules/Lofar" "dsp" "systems"} +proc hdl_env {} { + global env + return $env(RADIOHDL) } @@ -73,52 +59,24 @@ proc unb_dir {} { # LP = Load project #------------------------------------------------------------------------------- -# Default load UniBoard project -proc lp {{arg_lib ""}} { - lpu $arg_lib -} - -# UniBoard load project -proc lpu {{arg_lib ""}} { - set arg_env [unb_env] - set arg_dir [unb_dir] - lp_gen $arg_env $arg_dir $arg_lib +proc get_cur_lib {} { + set mpf [eval project env] + set cur_lib [string range $mpf [expr [string last / $mpf]+1] [expr [string last . $mpf]-1]] + return $cur_lib } -# General load project -proc lp_gen {arg_env arg_dir arg_lib} { - set mpf [eval project env] - set cur_lib [string range $mpf [expr [string last / $mpf]+1] [expr [string last . $mpf]-1]] - - if {[string equal $arg_lib ""] || [string equal $arg_lib $cur_lib]} { - # find out current module name - return $cur_lib - } elseif [file exists $arg_lib] { - set mpf $arg_lib - } else { - set sim [simdir $arg_env $arg_dir $arg_lib] - set mpf $sim/$arg_lib.mpf - } - if [file exists $mpf] then { -# if {[this_os]=="Windows"} { -# if [file attributes $mpf -readonly] then { -# file attributes $mpf -readonly 0 -# } -# } else { -# set mpf_readonly [file attributes $mpf -permissions] ;# 5 char string: 0,0,u(rwx),g(rwx),a(rwx) -# set mpf_readonly [expr !([string index $mpf_readonly 2] & 0x2)] ;# filter out user write status -# if {$mpf_readonly==1} then { -# file attributes $mpf -permissions u+w -# } -# } - if {! [string equal $cur_lib ""]} then { - project close +proc lp {{arg_lib ""}} { + set cur_lib [get_cur_lib] + if {$arg_lib == "" || $arg_lib == $cur_lib} { + return $cur_lib + } else { + set sim [simdir $arg_lib] + if {[eval project env]!=""} { + project close + } + project open $sim/$arg_lib.mpf + return $arg_lib } - project open $mpf - } else { - error "Project file $arg_lib not found" - } - return $arg_lib } @@ -126,244 +84,180 @@ proc lp_gen {arg_env arg_dir arg_lib} { # MK = Make project #------------------------------------------------------------------------------- -# Default make UniBoard project -# . The args is a special TCL argument because it allows more than one formal. -# However when args is subsequently passed on to proc mku, then all arguments -# in args will be treated as a signal argument in mku. Therefore duplicate -# the content of proc mku in proc mk, because simply calling mku $args in mk -# does not work. -# . However using an alias also works and is a nicer solution: -# One can also define a command as an alias to a sequence of one or more -# words, which will be substituted for it before execution. (The funny {} -# arguments are names of the source and target interpreter, which typically -# is the current one, named by the empty string {} or ""). -interp alias {} mk {} mku - - -# UniBoard make project -proc mku args { - set arg_env [unb_env] - set arg_dir [unb_dir] - set arg_cmd [parse_for_cmds $args] - set arg_lib [parse_for_libs $args] - set arg_lib [extract_unb_libs $arg_lib] - - mk_gen $arg_env $arg_dir $arg_cmd $arg_lib -} - - -# Extract groups of UniBoard libs from arg_lib -proc extract_unb_libs arg_lib { - # Check arg_lib for make groups of UniBoard modules and designs - # Remarks: - # . order of groups is important - # . for the designs that have an SOPC system that needs to be generated first with SOPC Builder (to avoid pop up windows if these files are missing) - # . e.g. group of designs for which the node component is reused in other designs - # . e.g. group of reference designs that are still maintained - set m_unb_common {fmf easics tst common mm dp uth} - set m_unb_lofar {async_logic diag util i2c rcuh sens mdio eth ado pfs pft2 ss st} - set m_unb_dsp {bf rTwoSDF fft filter wpfb} - set m_unb_modules {diagnostics ppsh tse aduh tr_nonbonded ddr3 udp_packetizer remu epcs unb_common} - set m_unb_designs {unb_tr_nonbonded unb_ddr3 unb_tr_xaui bn_terminal_bg fn_terminal_db} - set m_old_designs {unb_sens unb_tse unb_heater fn_mdio unb_base bn_base fn_base} - set m_apertif_designs {bn_capture fn_bf bn_filterbank fn_beamformer} - - if [ string equal $arg_lib "all_mod" ] { set arg_lib "$m_unb_common $m_unb_lofar $m_unb_modules $m_unb_dsp" - } elseif [ string equal $arg_lib "unb_designs" ] { set arg_lib "$m_unb_designs" - } elseif [ string equal $arg_lib "all_unb" ] { set arg_lib "$m_unb_common $m_unb_lofar $m_unb_modules $m_unb_dsp $m_unb_designs" - } elseif [ string equal $arg_lib "all_apertif" ] { set arg_lib "$m_unb_common $m_unb_lofar $m_unb_modules $m_unb_dsp $m_unb_designs $m_apertif_designs" - } elseif [ string equal $arg_lib "old_designs" ] { set arg_lib "$m_old_designs" - } elseif [ string equal $arg_lib "all" ] { set arg_lib "$m_unb_common $m_unb_lofar $m_unb_modules $m_unb_dsp $m_unb_designs $m_apertif_designs $m_old_designs" - } - return $arg_lib +proc project_mk_cmds {} { + return {clean compile files make test vmake} ;# mk with arg_cmd="" will default to "make" } # Get commands from the mk args proc parse_for_cmds arg_list { - set cmds {} - if [ string equal $arg_list "help" ] then { - puts "mk \[commands\] \[projects\]" - puts " possible commands are:" - puts " check: check for absolute paths in project sources" - puts " clean: removes the library files" - puts " compile: runs project compileall" - puts " delete: delete Modelsim project file" - puts " files: list files in compile order" - puts " help: displays this help" - puts " make: runs makefile" - puts " test: runs test cases" - puts " vmake: creates makefile" - puts "" - puts "commands are executed for the projects indicated" - puts "- when no command is specified, 'make' is used as default" - puts "- when no projects are specified, the current project is used" - puts "- the keyword 'all_mod' is expanded to a subset of all uniboard reuseable modules" - puts "- the keyword 'all_unb' is expanded to a subset of all uniboard reuseable designs and reference designs" - puts "" - return - } else { - # search for commands in arg_list - foreach cmd {check clean compile delete files make test vmake} { - if {[lsearch $arg_list $cmd] >= 0} then { - lappend cmds $cmd - } - } - if {[llength $cmds] == 0} then { - # no commands found, use default commands - set cmds {make} + set cmds {} + if [ string equal $arg_list "help" ] then { + puts "mk \[commands\] \[projects\]" + puts " possible commands are:" + puts " clean: removes the library files" + puts " compile: runs project compileall" + puts " files: list files in compile order" + puts " help: displays this help" + puts " make: runs makefile" + puts " test: runs test cases" + puts " vmake: creates makefile" + puts "" + puts "commands are executed for the projects indicated" + puts "- when no command is specified, 'make' is used as default" + puts "- when no projects are specified, the current project is used" + puts "- when the keyword 'all' is specified, then the command is applied to all projects that the current project depends on" + puts "" + return + } else { + # search for commands in arg_list + foreach cmd [project_mk_cmds] { + if {[lsearch $arg_list $cmd] >= 0} then { + lappend cmds $cmd + } + } + if {[llength $cmds] == 0} then { + # no commands found, use default command + set cmds {make} + } } - } - return $cmds + return $cmds } - -# Get libraries (modules, designs) from the mk args +# Get libraries from the mk args proc parse_for_libs arg_list { - # strip the commands from arg_list to keep only the modules - set libs $arg_list - foreach cmd {check clean compile delete files make test vmake} { - set i [lsearch $libs $cmd] - if {$i >= 0} then { - set libs [lreplace $libs $i $i] + # strip the commands from arg_list to keep only the libraries + set libs $arg_list + foreach cmd [project_mk_cmds] { + set i [lsearch $libs $cmd] + if {$i >= 0} then { + set libs [lreplace $libs $i $i] + } } - } - return $libs + return $libs } +# Extract this lib or all libs that it depends on for arg_lib +proc extract_all_libs arg_lib { + if {$arg_lib=="all"} { + set cur_lib [get_cur_lib] + return [read_lib_compile_order_file $cur_lib] + } else { + return $arg_lib + } +} # General make project -proc mk_gen {arg_env arg_dir arg_cmd arg_lib} { - if {[llength $arg_cmd] > 0} then { - set cur_lib [lp_gen $arg_env $arg_dir ""] - - # without arguments mk current lib +proc mk args { + # Parse the args, the args is a special TCL argument because it allows more than one formal. + set arg_cmd [parse_for_cmds $args] + set arg_lib [parse_for_libs $args] + # Extract arg_lib or all libs that it depends on for arg_lib + set arg_lib [extract_all_libs $arg_lib] + + # keep current lib + set cur_lib [get_cur_lib] + + # Without arguments mk current lib if { [llength $arg_lib] == 0 } { - set arg_lib $cur_lib + set arg_lib $cur_lib } - # perform the commands on the specified libs + # Perform the commands on the specified libs foreach cmd $arg_cmd { - foreach lib $arg_lib { - if { [ catch { eval ["mk_$cmd" $arg_env $arg_dir $lib] } msg ] } { - puts stderr $msg + foreach lib $arg_lib { + if { [ catch { eval ["mk_$cmd" $lib] } msg ] } { + puts stderr $msg + } } - } } + # back to original lib - lp_gen $arg_env $arg_dir $cur_lib - } + lp $cur_lib } - -proc mk_check {arg_env arg_dir arg_lib} { - lp_gen $arg_env $arg_dir $arg_lib - puts "\[mk check $arg_lib\]" - foreach file [project compileorder] { - if {[string first "../" $file] != 0 && - [string first "\$" $file] != 0} { - puts stderr "Warning: $file is an absolute path" +proc mk_clean {arg_lib} { + puts "\[mk clean $arg_lib\]" + set sim [simdir $arg_lib] + if {[file exists "$sim/work"]} then { + vdel -lib $sim/work -all + } + if {[file exists "$sim/makefile"]} then { + file delete $sim/makefile + } + if {[file exists "$sim/vsim.wlf"]} then { + file delete $sim/vsim.wlf + } + if {[file exists "$sim/$arg_lib.cr.mti"]} then { + file delete $sim/$arg_lib.cr.mti } - } -} - -# Issue mk delete all to delete all Modelsim project files to ensure that SVN -# update refreshes them all from the repository. This is necessary because -# Modelsim edits the mpf files even when they have no significant modification -# and then the edited mpf files will not get SVN updated. -proc mk_delete {arg_env arg_dir arg_lib} { - puts "\[mk delete $arg_lib\]" - set sim [simdir $arg_env $arg_dir $arg_lib] - if {[file exists "$sim/$arg_lib.mpf"]} then { - file delete $sim/$arg_lib.mpf - } -} - -proc mk_clean {arg_env arg_dir arg_lib} { - puts "\[mk clean $arg_lib\]" - set sim [simdir $arg_env $arg_dir $arg_lib] - if {[file exists "$sim/work"]} then { - vdel -lib $sim/work -all - } - if {[file exists "$sim/makefile"]} then { - file delete $sim/makefile - } - if {[file exists "$sim/vsim.wlf"]} then { - file delete $sim/vsim.wlf - } - if {[file exists "$sim/$arg_lib.cr.mti"]} then { - file delete $sim/$arg_lib.cr.mti - } } -proc mk_compile {arg_env arg_dir arg_lib} { - if {[string compare [env] "<No Context>"] != 0} { - puts "A project cannot be closed while a simulation is in progress.\nUse the \"quit -sim\" command to unload the design first." - return - } - puts "\[mk compile $arg_lib\]" - lp_gen $arg_env $arg_dir $arg_lib - if {![file exists work"]} then { - vlib work; - } - project compileall +proc mk_compile {arg_lib} { + if {[string compare [env] "<No Context>"] != 0} { + puts "A project cannot be closed while a simulation is in progress.\nUse the \"quit -sim\" command to unload the simulation first." + return + } + puts "\[mk compile $arg_lib\]" + lp $arg_lib + if {![file exists work"]} then { + vlib work; + } + project compileall } -proc mk_files {arg_env arg_dir arg_lib} { - lp_gen $arg_env $arg_dir $arg_lib - foreach file [project compileorder] { - puts $file - } +proc mk_files {arg_lib} { + lp $arg_lib + foreach file [project compileorder] { + puts $file + } } -proc mk_vmake {arg_env arg_dir arg_lib} { - set sim [simdir $arg_env $arg_dir $arg_lib] - if {![file exists "$sim/work/_info"]} then { - mk_compile $arg_env $arg_dir $arg_lib - } - puts "\[mk vmake $arg_lib\]" - if {![file exists "$sim/makefile"] || - ([file mtime "$sim/makefile"] < [file mtime "$sim/work/_info"]) } then { - # Both the specific library name $(arg_lib)_lib and the work library map to the same local work library, - # so to be compatible for both names always use work to generate the makefile - puts [exec vmake -fullsrcpath work > $sim/makefile] - adapt_makefile "$sim/makefile" - } - if {[file exists "$sim/work"]} then { - vdel -lib $sim/work -all - vlib work - } +proc mk_vmake {arg_lib} { + set sim [simdir $arg_lib] + if {![file exists "$sim/work/_info"]} then { + mk_compile $arg_lib + } + puts "\[mk vmake $arg_lib\]" + if {![file exists "$sim/makefile"] || + ([file mtime "$sim/makefile"] < [file mtime "$sim/work/_info"]) } then { + # Both the specific library name $(arg_lib)_lib and the work library map to the same local work library, + # so to be compatible for both names always use work to generate the makefile + puts [exec vmake -fullsrcpath work > $sim/makefile] + } + if {[file exists "$sim/work"]} then { + vdel -lib $sim/work -all + vlib work + } } -proc mk_make {arg_env arg_dir arg_lib} { - global env - set sim [simdir $arg_env $arg_dir $arg_lib] - if {! [file exists "$sim/makefile"] } then { - mk_vmake $arg_env $arg_dir $arg_lib - } - puts "\[mk make $arg_lib\]" - if {[this_os]=="Windows"} { - puts [exec $env(UNB)/Firmware/sim/bin/make.exe -C $sim -s -k -f makefile] - } else { - puts [exec /usr/bin/make -C $sim -s -k -f makefile] - } +proc mk_make {arg_lib} { + set sim [simdir $arg_lib] + if {! [file exists "$sim/makefile"] } then { + mk_vmake $arg_lib + } + puts "\[mk make $arg_lib\]" + if {[this_os]=="Windows"} { + puts [exec [hdl_env]/tools/bin/make.exe -C $sim -s -k -f makefile] + } else { + puts [exec /usr/bin/make -C $sim -s -k -f makefile] + } } -proc mk_test {arg_env arg_dir arg_lib} { - # only for directory /modules, so arg_dir is not used but kept to match the other proc mk_* +proc mk_test {arg_lib} { puts "\[mk test $arg_lib\]" radix -decimal vsim -quiet tst_lib.tb_$arg_lib - set tb [tbdir $arg_env $arg_lib] + set tb [tbdir $arg_lib] foreach tc [glob -directory $tb/data -type d -nocomplain tc*] { - puts "testcase $tc" - foreach fileName [glob -directory $tc -type f -nocomplain *.in *.out *.ref] { - file copy -force $fileName . - } - restart -force - run 1 ms - foreach fileName [glob -dir . -type f -nocomplain *.in *.out *.ref] { - file delete -force $fileName - } + puts "testcase $tc" + foreach fileName [glob -directory $tc -type f -nocomplain *.in *.out *.ref] { + file copy -force $fileName . + } + restart -force + run 1 ms + foreach fileName [glob -dir . -type f -nocomplain *.in *.out *.ref] { + file delete -force $fileName + } } quit -sim } @@ -373,86 +267,79 @@ proc mk_test {arg_env arg_dir arg_lib} { # Auxiliary procedures #------------------------------------------------------------------------------- -# compute simulation directory -proc simdir {arg_env arg_dir arg_lib {return_code -1}} { - global env - # The order of arg_dir is important when modules with the same name exist, - # the first one where the mpf is found will be used - foreach sdir $arg_dir { - # First look in the project default Modelsim project directory - if {[file exists "$env($arg_env)/Firmware/$sdir/$arg_lib/build/sim/modelsim"]} { - return $env($arg_env)/Firmware/$sdir/$arg_lib/build/sim/modelsim +proc read_modelsim_project_files_file {} { + set fp [open [hdl_env]/tools/modelsim/modelsim_project_files.txt] + set data [read $fp] + close $fp + set lines [split $data \n] + set lib_names {} + set mpf_paths {} + foreach line $lines { + set ll [split $line] + if {[lindex $ll 1]== "="} { + lappend lib_names [lindex $ll 0] + lappend mpf_paths [lindex $ll 2] + } + } + set ret {} + lappend ret $lib_names + lappend ret $mpf_paths + return $ret +} + +proc read_lib_compile_order_file {arg_lib} { + set sim [simdir $arg_lib] + set file_name $arg_lib + append file_name "_lib_order.txt" + set fp [open $sim/$file_name] + set data [read $fp] + close $fp + set lib_names [split $data] + puts $lib_names + return $lib_names +} + +# Compute simulation directory where the mpf is located +proc simdir {arg_lib} { + set project_libs [read_modelsim_project_files_file] + set lib_names [lindex $project_libs 0] + set mpf_paths [lindex $project_libs 1] + set lib_index [lsearch $lib_names $arg_lib] + if {$lib_index >= 0} { + return [lindex $mpf_paths $lib_index] } else { - # then also support the <sopc design name>_sim directory generated by SOPC Builder - # note that for this path to be found the modelsim/ directory in sim/ must be deleted - if {[catch {glob -directory $env($arg_env)/Firmware/$sdir/$arg_lib/build/synth/quartus *_sim/}] == 0} { - # If there exists more then one dir ending at '_sim' then return only the first - return [lindex [glob -directory $env($arg_env)/Firmware/$sdir/$arg_lib/build/synth/quartus *_sim/] 0] - } + error "Project directory $arg_lib not found" + return -1 } - } - if {$return_code==-1} { - # Default raise error to abort script - error "Project directory $arg_lib not found" - } else { - # Optionally return with return_code to continue script - return $return_code - } } -# compute tb directory -proc tbdir {arg_env arg_lib} { - global env - return $arg_env/Firmware/modules/$arg_lib/tb +# Compute tb directory +proc tbdir {arg_lib} { } # find out which environment operating system we are on proc this_os {} { - if {$::tcl_platform(platform)=="windows"} { - return "Windows" - } else { - return "Not Windows" ;# Linux, Unix, ... - } -} - -# adapt makefile to allow (arch_name) in filenames by changing them into \\(arch_name\\) -proc adapt_makefile arg { - if {[this_os]=="Windows"} { - # Nothing to do, works OK - } else { - set arch_names {"pkg" "rtl" "str" "wrap" "recursive" "beh" "empty" "stratix4"} - set fh [open $arg r] - set txt [read $fh] - close $fh - foreach an $arch_names { - set ai [string first "($an)" $txt] - while {$ai != -1} { - set txt [string replace $txt $ai [expr $ai + [string length $an] + 1] "\\($an\\)"] - incr ai 2 - set ai [string first "($an)" $txt $ai] - } + if {$::tcl_platform(platform)=="windows"} { + return "Windows" + } else { + return "Not Windows" ;# Linux, Unix, ... } - set fh [open $arg w] - puts $fh $txt - close $fh - } } - #------------------------------------------------------------------------------- # DS = Delete Signals : deletes all signals in the waveform window. #------------------------------------------------------------------------------- proc ds {} { - delete wave * + delete wave * } #------------------------------------------------------------------------------- # AS = Add signals : adds all signals up to hierarchy depth to the wave window #------------------------------------------------------------------------------- proc as {depth {inst ""}} { - #asf $depth - asg $depth $inst + #asf $depth + asg $depth $inst } #------------------------------------------------------------------------------- @@ -461,18 +348,18 @@ proc as {depth {inst ""}} { # nxt_ and i_ signals. Altera alt_ blocks will also be ignored. #------------------------------------------------------------------------------- proc asf depth { - global env - # Start with all signals in the model. - add wave -noupdate -divider {as} - add wave -noupdate -depth $depth -r "/*" - # Allow users to set environment variable if they don't want the signals to be deleted - if { ![info exists ::env(MODELSIM_WAVE_NO_DEL) ] } { - delete wave */nxt_* - delete wave */i_* - } - #delete wave */alt* - configure wave -signalnamewidth 0 - echo "Done." + global env + # Start with all signals in the model. + add wave -noupdate -divider {as} + add wave -noupdate -depth $depth -r "/*" + # Allow users to set environment variable if they don't want the signals to be deleted + if { ![info exists ::env(MODELSIM_WAVE_NO_DEL) ] } { + delete wave */nxt_* + delete wave */i_* + } + #delete wave */alt* + configure wave -signalnamewidth 0 + echo "Done." } #------------------------------------------------------------------------------- @@ -487,68 +374,68 @@ proc asf depth { # NOTE: instance_name = NOT the entity name! #------------------------------------------------------------------------------- proc asg {depth {inst ""}} { - add_wave_grouped_recursive "" "" $depth $inst 0 - wave refresh - # The grouping already displays the hierarchy, so use short signal names. - config wave -signalnamewidth 1 - # With our short signal names, the name column can be narrower than default. - config wave -namecolwidth 300 + add_wave_grouped_recursive "" "" $depth $inst 0 + wave refresh + # The grouping already displays the hierarchy, so use short signal names. + config wave -signalnamewidth 1 + # With our short signal names, the name column can be narrower than default. + config wave -namecolwidth 300 } # called by ASG: proc add_wave_grouped_recursive {current_level prev_group_option depth target_inst target_inst_det} { - # Find all instances (=next hierarchy levels) in the ecurrent hierarchy level - set found_instances [find instances "$current_level/*"] - - # Find all blocks (=GENERATE statement labels that are also hierarchy levels to be explored) - set found_blocks [find blocks "$current_level/*"] - - # Concatenate the instance list with the block list, sort them alphabetically - set objects [lsort -dictionary [concat $found_instances $found_blocks]] - - foreach object $objects { - # Separate "/object_path" from "(entity_name)" - set object_path [lindex [split $object " "] 0] - # Get the word after last "/" - set gname [lrange [split $object_path "/"] end end] - - if {[path_depth $object_path]<$depth} { - if { $gname == $target_inst || $target_inst_det==1} { - # Found an instance that matches user input - or we're already inside that instance. - add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 1 - } else { - add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 0 - } - } - } + # Find all instances (=next hierarchy levels) in the ecurrent hierarchy level + set found_instances [find instances "$current_level/*"] - if { $current_level != "" } { - # First check if what we're about to add is an instance, not merely a GENERATE level - if {[context isInst $current_level]==1} { - set CMD "add wave -noupdate -radix unsigned $prev_group_option $current_level/*" - - if {$target_inst!=""} { - # User passed a target inst. Check if we inside of it. - if {$target_inst_det==0} { - # We're not in in instance. Only add a group and move on. - set CMD "add wave -noupdate -radix unsigned $prev_group_option" + # Find all blocks (=GENERATE statement labels that are also hierarchy levels to be explored) + set found_blocks [find blocks "$current_level/*"] + + # Concatenate the instance list with the block list, sort them alphabetically + set objects [lsort -dictionary [concat $found_instances $found_blocks]] + + foreach object $objects { + # Separate "/object_path" from "(entity_name)" + set object_path [lindex [split $object " "] 0] + # Get the word after last "/" + set gname [lrange [split $object_path "/"] end end] + + if {[path_depth $object_path]<$depth} { + if { $gname == $target_inst || $target_inst_det==1} { + # Found an instance that matches user input - or we're already inside that instance. + add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 1 + } else { + add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 0 + } } - } - # Use catch so e.g. empty entities don't cause script to fail - catch {eval $CMD} } - return - } + + if { $current_level != "" } { + # First check if what we're about to add is an instance, not merely a GENERATE level + if {[context isInst $current_level]==1} { + set CMD "add wave -noupdate -radix unsigned $prev_group_option $current_level/*" + + if {$target_inst!=""} { + # User passed a target inst. Check if we inside of it. + if {$target_inst_det==0} { + # We're not in in instance. Only add a group and move on. + set CMD "add wave -noupdate -radix unsigned $prev_group_option" + } + } + # Use catch so e.g. empty entities don't cause script to fail + catch {eval $CMD} + } + return + } } # Count the number of occurences in a string: proc scount {subs string} { - regsub -all $subs $string $subs string + regsub -all $subs $string $subs string } # Return the depth of a given path; e.g. /some/path/to/some/thing = 5. proc path_depth path { - scount "/" $path + scount "/" $path } @@ -557,6 +444,6 @@ proc path_depth path { # Use argument 0 to enable the warnings again. #------------------------------------------------------------------------------- proc nowarn {{off 1}} { - set ::StdArithNoWarnings $off - set ::NumericStdNoWarnings $off + set ::StdArithNoWarnings $off + set ::NumericStdNoWarnings $off }