From a0265ba8a42730de751d27e6737894b91c86a69b Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Thu, 22 May 2014 10:03:40 +0000
Subject: [PATCH] Moved or copied files to RadioHDL.

---
 tools/modelsim/commands.do | 562 +++++++++++++++++++++++++++++++++++++
 1 file changed, 562 insertions(+)
 create mode 100644 tools/modelsim/commands.do

diff --git a/tools/modelsim/commands.do b/tools/modelsim/commands.do
new file mode 100644
index 0000000000..0664b008bd
--- /dev/null
+++ b/tools/modelsim/commands.do
@@ -0,0 +1,562 @@
+###############################################################################
+#
+# Copyright (C) 2009
+# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+# Purpose: Provide useful commands for simulating Modelsim projects
+# Desription:
+# 
+# * 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
+#   . 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/"
+#
+# * 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
+#
+
+
+#-------------------------------------------------------------------------------
+# UniBoard settings
+#-------------------------------------------------------------------------------
+
+puts "Loading general UniBoard 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"}
+}
+
+
+#-------------------------------------------------------------------------------
+# 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
+}
+
+# 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
+    }
+    project open $mpf
+  } else {
+    error "Project file $arg_lib not found"
+  }
+  return $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
+}
+
+# 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}
+    }
+  }
+  return $cmds
+}
+
+
+# Get libraries (modules, designs) 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]
+    }
+  }
+  return $libs
+}
+
+
+# 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
+    if { [llength $arg_lib] == 0 } {
+      set arg_lib $cur_lib
+    }
+    # 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
+        }
+      }
+    }
+    # back to original lib
+    lp_gen $arg_env $arg_dir $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"
+    }
+  }
+}
+
+# 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_files {arg_env arg_dir arg_lib} {
+  lp_gen $arg_env $arg_dir $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_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_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_*
+  puts "\[mk test $arg_lib\]"
+  radix -decimal
+  vsim -quiet tst_lib.tb_$arg_lib
+  set tb [tbdir $arg_env $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
+    }
+  }
+  quit -sim
+}
+
+
+#-------------------------------------------------------------------------------
+# 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
+    } 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]
+      }
+    }
+  }
+  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
+}
+
+# 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]
+      }
+    }
+    set fh [open $arg w]
+    puts $fh $txt
+    close $fh
+  }
+}
+
+
+
+#-------------------------------------------------------------------------------
+# DS = Delete Signals : deletes all signals in the waveform window.
+#-------------------------------------------------------------------------------
+proc ds {} {
+  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 = add signals flat : flat adds all signals up to hierarchy depth to the wave window
+# It will automatically add dividers between the blocks, and it will discard all
+# 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."
+}
+
+#-------------------------------------------------------------------------------
+# ASG = add signals in groups : recursively scans the hierarchy and adds signals
+#       groupwise to the wave window.
+#       Normal use: 
+#       . asg [depth] 
+#         => Adds all signals down to a depth of [depth].
+#       Advanced/debugging use:
+#       . asg [depth] [instance_name]
+#         => Adds all signals in [instance_name] down to to a level of [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
+}
+
+# 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
+      }
+    }
+  }
+  
+  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
+}
+
+# Return the depth of a given path; e.g. /some/path/to/some/thing = 5.
+proc path_depth path {
+  scount "/" $path 
+}
+
+
+#-------------------------------------------------------------------------------
+# NOWARN default disables the library warnings for subsequent simulation runs.
+# Use argument 0 to enable the warnings again.
+#-------------------------------------------------------------------------------
+proc nowarn {{off 1}} {
+  set ::StdArithNoWarnings   $off
+  set ::NumericStdNoWarnings $off
+}
-- 
GitLab