OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [modelsim/] [commands.do] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 danv
###############################################################################
2
#
3
# Copyright (C) 2014
4
# ASTRON (Netherlands Institute for Radio Astronomy) 
5
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see .
19
#
20
###############################################################################
21
 
22
# Purpose: Provide useful commands for simulating Modelsim projects
23
# Desription:
24
#
25
# * The user commands are typically used at the Modelsim prompt are:
26
#
27
#   . lp  : load HDL library .mpf project
28
#   . mk  : make one or range of HDL library mpf projects
29
#   . as #      : add signals for # levels of hierarchy to the wave window
30
#   . ds        : delete all signals from the wave window
31
#
32
# * The other procedures in this commands.do are internal command procedures
33
#   that are typically not used at the Modelsim prompt.
34
#
35
# * The recommended project directory structure is:
36
#
37
#     $arg_lib/build/modelsim    : Modelsim project file
38
#                   /quartus     : Quartus project file
39
#             /src/vhdl          : VHDL source code that gets synthesized
40
#             /tb/vhdl           : VHDL source code for test bench
41
#
42
#   Alternatively the build/ directory may be located at another more central
43
#   location.
44
#
45
 
46
#-------------------------------------------------------------------------------
47
# HDL library settings
48
#-------------------------------------------------------------------------------
49
 
50
echo "Loading general HDL library commands..."
51
 
52
proc hdl_env {} {
53
    global env
54
    return $env(HDL)
55
}
56
 
57
proc hdl_build {} {
58
    global env
59
    return $env(RADIOHDL_BUILD_DIR)
60
}
61
 
62
proc hdl_buildset {} {
63
    global env
64
    return $env(BUILDSET)
65
}
66
 
67
#-------------------------------------------------------------------------------
68
# LP = Load project
69
#-------------------------------------------------------------------------------
70
 
71
proc get_cur_lib {} {
72
    set mpf [eval project env]
73
    set cur_lib [string range $mpf [expr [string last / $mpf]+1] [expr [string last . $mpf]-1]]
74
    return $cur_lib
75
}
76
 
77
proc lp {{arg_lib ""}} {
78
    set cur_lib [get_cur_lib]
79
    if {$arg_lib=="help"} {
80
        echo ""
81
        echo "lp \[project\]"
82
        echo "  possible projects are:"
83
        echo "     : load project .mpf"
84
        echo "               : report current project library"
85
        echo "    all        : report all libraries that the current project library depends on"
86
        echo "    help       : displays this help"
87
        echo ""
88
    } elseif {$arg_lib == "" || $arg_lib == $cur_lib} {
89
        return $cur_lib
90
    } elseif {$arg_lib=="all"} {
91
        read_lib_compile_order_file $cur_lib
92
        return
93
    } else {
94
        set sim [simdir $arg_lib]
95
        if {[eval project env]!=""} {
96
            project close                 ;# close current project
97
        }
98
        project open $sim/$arg_lib.mpf    ;# load project for the requested library
99
        return $arg_lib
100
    }
101
}
102
 
103
 
104
#-------------------------------------------------------------------------------
105
# MK = Make project
106
#-------------------------------------------------------------------------------
107
 
108
proc project_mk_cmds {} {
109
    return {clean execute compile files make test vmake}   ;# mk with arg_cmd="" will default to "make"
110
}
111
 
112
# Get commands from the mk args
113
proc parse_for_cmds arg_list {
114
    set cmds {}
115
    if [ string equal $arg_list "help" ] then {
116
        echo ""
117
        echo "mk \[commands\] \[projects\]"
118
        echo "  possible commands are:"
119
        echo "    clean:   removes the library files"
120
        echo "    execute: runs compile IP scripts"
121
        echo "    compile: runs project compileall"
122
        echo "    files:   list files in compile order"
123
        echo "    help:    displays this help"
124
        echo "    make:    runs makefile"
125
        echo "    test:    runs test cases"
126
        echo "    vmake:   creates makefile"
127
        echo ""
128
        echo "  commands are executed for the projects indicated"
129
        echo "  - when no command is specified, 'make' is used as default"
130
        echo "  - when no projects are specified, the current project is used"
131
        echo "  - when the keyword 'all' is specified, then the command is applied to all projects that the current project depends on"
132
        echo ""
133
        return
134
    } else {
135
        # search for commands in arg_list
136
        foreach cmd [project_mk_cmds] {
137
            if {[lsearch $arg_list $cmd] >= 0} then {
138
                lappend cmds $cmd
139
            }
140
        }
141
        if {[llength $cmds] == 0} then {
142
            # no commands found, use default command
143
            set cmds {make}
144
        }
145
    }
146
    return $cmds
147
}
148
 
149
# Get libraries from the mk args
150
proc parse_for_libs arg_list {
151
    # strip the commands from arg_list to keep only the libraries
152
    set libs $arg_list
153
    foreach cmd [project_mk_cmds] {
154
        set i [lsearch $libs $cmd]
155
        if {$i >= 0} then {
156
            set libs [lreplace $libs $i $i]
157
        }
158
    }
159
    return $libs
160
}
161
 
162
# Create work library
163
proc do_vlib arg_work {
164
    set modelsimId [vsimId]
165
    set dot_index [string first . $modelsimId]
166
    set majorId [string range $modelsimId 0 [expr $dot_index-1]]
167
    if {$majorId <= 6} {
168
        vlib $arg_work
169
    } else {
170
        # The makefile that is created by vmake relies on using directories in vlib
171
        vlib -type directory $arg_work
172
    }
173
}
174
 
175
# Extract this lib or all libs that it depends on for arg_lib
176
proc extract_all_libs arg_lib {
177
    if {$arg_lib=="all"} {
178
        set cur_lib [get_cur_lib]
179
        return [read_lib_compile_order_file $cur_lib]
180
    } else {
181
        return $arg_lib
182
    }
183
}
184
 
185
# General make project
186
proc mk args {
187
    # Parse the args, the args is a special TCL argument because it allows more than one formal.
188
    set arg_cmd [parse_for_cmds $args]
189
    set arg_lib [parse_for_libs $args]
190
    # Extract arg_lib or all libs that it depends on for arg_lib
191
    set arg_lib [extract_all_libs $arg_lib]
192
 
193
    # keep current lib
194
    set cur_lib [get_cur_lib]
195
 
196
    # Without arguments mk current lib
197
    if { [llength $arg_lib] == 0 } {
198
        set arg_lib $cur_lib
199
    }
200
    # Perform the commands on the specified libs
201
    foreach cmd $arg_cmd {
202
        foreach lib $arg_lib {
203
            if { [ catch { eval ["mk_$cmd" $lib] } msg ] } {
204
                echo $msg
205
            }
206
        }
207
    }
208
 
209
    # back to original lib
210
    lp $cur_lib
211
}
212
 
213
proc mk_clean {arg_lib} {
214
    echo "\[mk clean $arg_lib\]"
215
    set sim [simdir $arg_lib]
216
    if {[file exists "$sim/work"]} then {
217
        vdel -lib $sim/work -all
218
    }
219
    if {[file exists "$sim/makefile"]} then {
220
        file delete $sim/makefile
221
    }
222
    if {[file exists "$sim/vsim.wlf"]} then {
223
        file delete $sim/vsim.wlf
224
    }
225
    if {[file exists "$sim/$arg_lib.cr.mti"]} then {
226
        file delete $sim/$arg_lib.cr.mti
227
    }
228
}
229
 
230
proc mk_execute {arg_lib} {
231
    # if there are compile scripts for IP files then first use use mk_execute to compile those into this work
232
    set compile_ip [read_lib_compile_ip_file $arg_lib]
233
    if {[llength $compile_ip] > 0} {
234
        echo "\[mk execute $arg_lib\]"
235
        set sim [simdir $arg_lib]
236
        lp $arg_lib
237
        # create work library if it does not already exist
238
        if {![file exists "$sim/work"]} then {
239
            do_vlib work
240
        }
241
        global env   ;# Make global env() variable known locally. This is necessary for $env(*) in compile IP tcl script, alternatively use $::env(*) in compile IP tcl scrip
242
        foreach ip $compile_ip {
243
            echo "do $ip"
244
            do $ip
245
        }
246
    }
247
}
248
 
249
proc mk_compile {arg_lib} {
250
    set sim [simdir $arg_lib]
251
    if {[string compare [env] ""] != 0} {
252
        echo "A project cannot be closed while a simulation is in progress.\nUse the \"quit -sim\" command to unload the simulation first."
253
        return
254
    }
255
    echo "\[mk compile $arg_lib\]"
256
    lp $arg_lib
257
    # recreate work library
258
    if {[file exists "$sim/work"]} then {
259
        vdel -lib $sim/work -all
260
    }
261
    do_vlib work
262
    # and then first execute any IP compile scripts
263
    mk_execute $arg_lib
264
    # and then compile the HDL
265
    project compileall
266
}
267
 
268
proc mk_files {arg_lib} {
269
    lp $arg_lib
270
    foreach file [project compileorder] {
271
        echo $file
272
    }
273
}
274
 
275
proc mk_vmake {arg_lib} {
276
    set sim [simdir $arg_lib]
277
    if {![file exists "$sim/work/_info"]} then {
278
        mk_compile $arg_lib
279
    }
280
    echo "\[mk vmake $arg_lib\]"
281
    if {![file exists "$sim/makefile"] || ([file mtime "$sim/makefile"] < [file mtime "$sim/work/_info"]) } then {
282
        # Both the specific library name $(arg_lib)_lib and the work library map to the same local work library,
283
        # so to be compatible for both names always use work to generate the makefile
284
        echo [exec vmake -fullsrcpath work > $sim/makefile]
285
    }
286
    # recreate work library
287
    vdel -lib $sim/work -all
288
    do_vlib work
289
    # and then first execute any IP compile scripts
290
    mk_execute $arg_lib
291
}
292
 
293
proc mk_make {arg_lib} {
294
    set sim [simdir $arg_lib]
295
    if {! [file exists "$sim/makefile"] } then {
296
        mk_vmake $arg_lib
297
    }
298
    echo "\[mk make $arg_lib\]"
299
    if {[this_os]=="Windows"} {
300
        echo [exec [hdl_env]/radiohdl/bin/make.exe -C $sim -s -k -f makefile]
301
    } else {
302
        echo [exec /usr/bin/make -C $sim -s -k -f makefile]
303
    }
304
}
305
 
306
proc mk_test {arg_lib} {
307
  echo "\[mk test $arg_lib\]"
308
  radix -decimal
309
  vsim -quiet tst_lib.tb_$arg_lib
310
  set tb [tbdir $arg_lib]
311
 
312
  foreach tc [glob -directory $tb/data -type d -nocomplain tc*] {
313
      echo "testcase $tc"
314
      foreach fileName [glob -directory $tc -type f -nocomplain *.in *.out *.ref] {
315
          file copy -force $fileName .
316
      }
317
      restart -force
318
      run 1 ms
319
      foreach fileName [glob -dir . -type f -nocomplain *.in *.out *.ref] {
320
          file delete -force $fileName
321
      }
322
  }
323
  quit -sim
324
}
325
 
326
 
327
#-------------------------------------------------------------------------------
328
# Auxiliary procedures
329
#-------------------------------------------------------------------------------
330
 
331
proc read_modelsim_project_files_file {} {
332
    set fp [open [hdl_build]/[hdl_buildset]/modelsim/modelsim_project_files.txt]
333
    set data [read $fp]
334
    close $fp
335
    set lines [split $data \n]
336
    set lib_names {}
337
    set mpf_paths {}
338
    foreach line $lines {
339
        set ll [split $line]
340
        if {[lindex $ll 1]== "="} {
341
            lappend lib_names [lindex $ll 0]
342
            lappend mpf_paths [lindex $ll 2]
343
        }
344
    }
345
    set ret {}
346
    lappend ret $lib_names
347
    lappend ret $mpf_paths
348
    return $ret
349
}
350
 
351
proc read_lib_compile_order_file {arg_lib} {
352
    set sim [simdir $arg_lib]
353
    set file_name $arg_lib
354
    append file_name "_lib_order.txt"
355
    set fp [open $sim/$file_name]
356
    set data [read $fp]
357
    set data [string trim $data]  ;# trim any trailing white space
358
    close $fp
359
    set lib_names [split $data]
360
    echo $lib_names
361
    return $lib_names
362
}
363
 
364
proc read_lib_compile_ip_file {arg_lib} {
365
    set sim [simdir $arg_lib]
366
    set file_name $arg_lib
367
    append file_name "_lib_compile_ip.txt"
368
    if {[file exists "$sim/$file_name"]} then {
369
        set fp [open $sim/$file_name]
370
        set data [read $fp]
371
        set data [string trim $data]  ;# trim any trailing white space
372
        close $fp
373
        set compile_ip [split $data]
374
        echo $compile_ip
375
        return $compile_ip
376
    } else {
377
        return
378
    }
379
}
380
 
381
# Compute simulation directory where the mpf is located
382
proc simdir {arg_lib} {
383
    set project_libs [read_modelsim_project_files_file]
384
    set lib_names [lindex $project_libs 0]
385
    set mpf_paths [lindex $project_libs 1]
386
    set lib_index [lsearch $lib_names $arg_lib]
387
    if {$lib_index >= 0} {
388
        return [lindex $mpf_paths $lib_index]
389
    } else {
390
        error "Project directory $arg_lib not found"
391
        return -1
392
    }
393
}
394
 
395
# Compute tb directory
396
proc tbdir {arg_lib} {
397
}
398
 
399
# find out which environment operating system we are on
400
proc this_os {} {
401
    if {$::tcl_platform(platform)=="windows"} {
402
        return "Windows"
403
    } else {
404
        return "Not Windows"   ;# Linux, Unix, ...
405
    }
406
}
407
 
408
 
409
#-------------------------------------------------------------------------------
410
# DS = Delete Signals : deletes all signals in the waveform window.
411
#-------------------------------------------------------------------------------
412
proc ds {} {
413
    delete wave *
414
}
415
 
416
#-------------------------------------------------------------------------------
417
# AS = Add signals : adds all signals up to hierarchy depth to the wave window
418
#-------------------------------------------------------------------------------
419
proc as {depth {inst ""}} {
420
    #asf $depth
421
    asg $depth $inst
422
}
423
 
424
#-------------------------------------------------------------------------------
425
# ASF = add signals flat : flat adds all signals up to hierarchy depth to the wave window
426
# It will automatically add dividers between the blocks, and it will discard all
427
# nxt_ and i_ signals. Altera alt_ blocks will also be ignored.
428
#-------------------------------------------------------------------------------
429
proc asf depth {
430
    global env
431
    # Start with all signals in the model.
432
    add wave -noupdate -divider {as}
433
    add wave -noupdate -depth $depth -r "/*"
434
    # Allow users to set environment variable if they don't want the signals to be deleted
435
    if { ![info exists ::env(MODELSIM_WAVE_NO_DEL) ] } {
436
        delete wave */nxt_*
437
        delete wave */i_*
438
    }
439
    #delete wave */alt*
440
    configure wave -signalnamewidth 0
441
    echo "Done."
442
}
443
 
444
#-------------------------------------------------------------------------------
445
# ASG = add signals in groups : recursively scans the hierarchy and adds signals
446
#       groupwise to the wave window.
447
#       Normal use:
448
#       . asg [depth]
449
#         => Adds all signals down to a depth of [depth].
450
#       Advanced/debugging use:
451
#       . asg [depth] [instance_name]
452
#         => Adds all signals in [instance_name] down to to a level of [depth]
453
#         NOTE: instance_name = NOT the entity name!
454
#-------------------------------------------------------------------------------
455
proc asg {depth {inst ""}} {
456
    add_wave_grouped_recursive "" "" $depth $inst 0
457
    wave refresh
458
    # The grouping already displays the hierarchy, so use short signal names.
459
    config wave -signalnamewidth 1
460
    # With our short signal names, the name column can be narrower than default.
461
    config wave -namecolwidth 300
462
}
463
 
464
# called by ASG:
465
proc add_wave_grouped_recursive {current_level prev_group_option depth target_inst target_inst_det} {
466
    # Find all instances (=next hierarchy levels) in the ecurrent hierarchy level
467
    set found_instances [find instances "$current_level/*"]
468
 
469
    # Find all blocks (=GENERATE statement labels that are also hierarchy levels to be explored)
470
    set found_blocks [find blocks "$current_level/*"]
471
 
472
    # Concatenate the instance list with the block list, sort them alphabetically
473
    set objects [lsort -dictionary [concat $found_instances $found_blocks]]
474
 
475
    foreach object $objects {
476
        # Separate "/object_path"  from "(entity_name)"
477
        set object_path [lindex [split $object " "] 0]
478
        # Get the word after last "/"
479
        set gname [lrange [split $object_path "/"] end end]
480
 
481
        if {[path_depth $object_path]<$depth} {
482
            if { $gname == $target_inst || $target_inst_det==1}  {
483
                # Found an instance that matches user input - or we're already inside that instance.
484
                add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 1
485
            } else {
486
                add_wave_grouped_recursive "$object_path" "$prev_group_option -group $gname" $depth $target_inst 0
487
            }
488
        }
489
    }
490
 
491
    if { $current_level != "" } {
492
        # First check if what we're about to add is an instance, not merely a GENERATE level
493
        if {[context isInst $current_level]==1} {
494
            set CMD "add wave -noupdate -radix unsigned $prev_group_option $current_level/*"
495
 
496
            if {$target_inst!=""} {
497
                # User passed a target inst. Check if we inside of it.
498
                if {$target_inst_det==0} {
499
                    # We're not in in instance. Only add a group and move on.
500
                    set CMD "add wave -noupdate -radix unsigned $prev_group_option"
501
                }
502
            }
503
            # Use catch so e.g. empty entities don't cause script to fail
504
            catch {eval $CMD}
505
        }
506
        return
507
    }
508
}
509
 
510
# Count the number of occurences in a string:
511
proc scount {subs string} {
512
    regsub -all $subs $string $subs string
513
}
514
 
515
# Return the depth of a given path; e.g. /some/path/to/some/thing = 5.
516
proc path_depth path {
517
    scount "/" $path
518
}
519
 
520
 
521
#-------------------------------------------------------------------------------
522
# NOWARN default disables the library warnings for subsequent simulation runs.
523
# Use argument 0 to enable the warnings again.
524
#-------------------------------------------------------------------------------
525
proc nowarn {{off 1}} {
526
    set ::StdArithNoWarnings   $off
527
    set ::NumericStdNoWarnings $off
528
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.