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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [libgui/] [library/] [debug.tcl] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
# -----------------------------------------------------------------------------
2
# NAME: 
3
#               ::debug
4
#
5
# DESC: 
6
#               This namespace implements general-purpose debugging functions
7
#               to display information as a program runs.  In addition, it 
8
#               includes profiling (derived from Sage 1.1) and tracing.  For 
9
#               output it can write to files, stdout, or use a debug output 
10
#               window.
11
#
12
# NOTES:        
13
#               Output of profiler is compatible with sageview.
14
#
15
# -----------------------------------------------------------------------------
16
 
17
package provide debug 1.0
18
 
19
namespace eval ::debug {
20
  namespace export debug dbug
21
  variable VERSION 1.1
22
  variable absolute
23
  variable stack ""
24
  variable outfile "trace.out"
25
  variable watch 0
26
  variable watchstart 0
27
  variable debugwin ""
28
  variable tracedVars
29
  variable logfile ""
30
  variable initialized 0
31
  variable stoptrace 0
32
  variable tracing 0
33
  variable profiling 0
34
  variable level 0
35
 
36
  # here's where we'll store our collected profile data
37
  namespace eval data {
38
    variable entries
39
  }
40
 
41
  proc logfile {file} {
42
    variable logfile
43
    if {$logfile != "" && $logfile != "stdout" && $logfile != "stderr"} {
44
      catch {close $logfile}
45
    }
46
 
47
    if {$file == ""} {
48
      set logfile ""
49
    } elseif {$file == "stdout" || $file == "stderr"} {
50
      set logfile $file
51
    } else {
52
      set logfile [open $file w+]
53
      fconfigure $logfile -buffering line -blocking 0
54
    }
55
  }
56
 
57
# ----------------------------------------------------------------------------
58
# NAME:         debug::trace_var
59
# SYNOPSIS:     debug::trace_var {varName mode}
60
# DESC:         Sets up variable trace.  When the trace is activated, 
61
#               debugging messages will be displayed.
62
# ARGS:         varName - the variable name
63
#               mode - one of more of the following letters
64
#                       r - read
65
#                       w - write
66
#                       u - unset
67
# -----------------------------------------------------------------------------
68
  proc trace_var {varName mode} {
69
    variable tracedVars
70
    lappend tracedVars [list $varName $mode]
71
    uplevel \#0 trace variable $varName $mode ::debug::touched_by
72
  }
73
 
74
# ----------------------------------------------------------------------------
75
# NAME:         debug::remove_trace
76
# SYNOPSIS:     debug::remove_trace {var mode}
77
# DESC:         Removes a trace set up with "trace_var".
78
# ----------------------------------------------------------------------------
79
  proc remove_trace {var mode} {
80
    uplevel \#0 trace vdelete $var $mode ::debug::touched_by
81
  }
82
 
83
# ----------------------------------------------------------------------------
84
# NAME:         debug::remove_all_traces
85
# SYNOPSIS:     debug::remove_all_traces
86
# DESC:         Removes all traces set up with "trace_var".
87
# ----------------------------------------------------------------------------
88
  proc remove_all_traces {} {
89
    variable tracedVars
90
    if {[info exists tracedVars]} {
91
      foreach {elem} $tracedVars {
92
        eval remove_trace $elem
93
      }
94
      unset tracedVars
95
    }
96
  }
97
 
98
# ----------------------------------------------------------------------------
99
# NAME:         debug::touched_by
100
# SYNOPSIS:     debug::touched_by {v a m}
101
# DESC:         Trace function used by trace_var. Currently writes standard
102
#               debugging messages or priority "W".
103
# ARGS:         v - variable
104
#               a - array element or ""
105
#               m - mode
106
# ----------------------------------------------------------------------------
107
  proc touched_by {v a m} {
108
    if {$a==""} {
109
      upvar $v foo
110
      dbug W "Variable $v touched in mode $m"
111
    } else {
112
      dbug W "Variable ${v}($a) touched in mode $m"
113
      upvar $v($a) foo
114
    }
115
    dbug  W "New value: $foo"
116
    show_call_stack 2
117
  }
118
 
119
# ----------------------------------------------------------------------------
120
# NAME:         debug::show_call_stack
121
# SYNOPSIS:     debug::show_call_stack {{start_decr 0}}
122
# DESC:         Function used by trace_var to print stack trace. Currently 
123
#               writes standard debugging messages or priority "W".
124
# ARGS:         start_decr - how many levels to go up to start trace
125
# ----------------------------------------------------------------------------
126
  proc show_call_stack {{start_decr 0}} {
127
    set depth [expr {[info level] - $start_decr}]
128
    if {$depth == 0} {
129
      dbug W "Called at global scope"
130
    } else {
131
      dbug W "Stack Trace follows:"
132
      for {set i $depth} {$i > 0} {incr i -1} {
133
        dbug W "Level $i: [info level $i]"
134
      }
135
    }
136
  }
137
 
138
# ----------------------------------------------------------------------------
139
# NAME:         debug::createData
140
# SYNOPSIS:     createData { name }
141
# DESC:         Basically creates a data structure for storing profiling 
142
#               information about a function.
143
# ARGS:         name - unique (full) function name
144
# -----------------------------------------------------------------------------
145
  proc createData {name} {
146
    lappend data::entries $name
147
 
148
    namespace eval data::$name {
149
      variable totaltimes 0
150
      variable activetime 0
151
      variable proccounts 0
152
      variable timers 0
153
      variable timerstart 0
154
      variable nest 0
155
    }
156
  }
157
 
158
  proc debugwin {obj} {
159
    variable debugwin
160
    set debugwin $obj
161
  }
162
 
163
# -----------------------------------------------------------------------------
164
# NAME:         debug::debug
165
#
166
# SYNOPSIS:     debug { {msg ""} }
167
#
168
# DESC:         Writes a message to the proper output. The priority of the 
169
#               message is assumed to be "I" (informational). This function
170
#               is provided for compatibility with the previous debug function.
171
#               For higher priority messages, use dbug.
172
#
173
# ARGS:         msg - Message to be displayed. 
174
# -----------------------------------------------------------------------------
175
 
176
  proc debug {{msg ""}} {
177
    set cls [string trimleft [uplevel namespace current] :]
178
    if {$cls == ""} {
179
      set cls "global"
180
    }
181
 
182
    set i [expr {[info level] - 1}]
183
    if {$i > 0} {
184
      set func [lindex [info level $i] 0]
185
      set i [string first "::" $func]
186
      if {$i != -1} {
187
        # itcl proc has class prepended to func
188
        # strip it off because we already have class in $cls
189
        set func [string range $func [expr {$i+2}] end]
190
      }
191
    } else {
192
      set func ""
193
    }
194
 
195
    ::debug::_putdebug I $cls $func $msg
196
  }
197
 
198
# -----------------------------------------------------------------------------
199
# NAME:         debug::dbug
200
#
201
# SYNOPSIS:     dbug { level msg }
202
#
203
# DESC:         Writes a message to the proper output. Unlike debug, this
204
#               function take a priority level.
205
#
206
# ARGS:         msg   - Message to be displayed.
207
#               level - One of the following:
208
#                               "I" - Informational only 
209
#                               "W" - Warning
210
#                               "E" - Error
211
#                               "X" - Fatal Error
212
# -----------------------------------------------------------------------------
213
  proc dbug {level msg} {
214
    set cls [string trimleft [uplevel namespace current] :]
215
    if {$cls == ""} {
216
      set cls "global"
217
    }
218
 
219
    set i [expr {[info level] - 1}]
220
    if {$i > 0} {
221
      set func [lindex [info level $i] 0]
222
    } else {
223
      set func ""
224
    }
225
 
226
    ::debug::_putdebug $level $cls $func $msg
227
  }
228
 
229
# -----------------------------------------------------------------------------
230
# NAME:         debug::_putdebug
231
#
232
# SYNOPSIS:     _putdebug { level cls func msg }
233
#
234
# DESC: Writes a message to the proper output. Will write to a debug
235
#       window if one is defined. Otherwise will write to stdout.
236
#
237
# ARGS:         msg   - Message to be displayed.
238
#               cls   - name of calling itcl class or "global"
239
#               func  - name of calling function
240
#               level - One of the following:
241
#                       "I" - Informational only 
242
#                       "W" - Warning
243
#                       "E" - Error
244
#                       "X" - Fatal Error
245
# -----------------------------------------------------------------------------
246
  proc _putdebug {lev cls func msg} {
247
    variable debugwin
248
    variable logfile
249
    if {$debugwin != ""} {
250
      $debugwin puts $lev $cls $func $msg
251
    }
252
    if {$logfile == "stdout"} {
253
      if {$func != ""} { append cls ::$func }
254
      puts $logfile "$lev: ($cls) $msg"
255
    } elseif {$logfile != ""} {
256
      puts $logfile [concat [list $lev] [list $cls] [list $func] [list $msg]]
257
    }
258
  }
259
 
260
  proc _puttrace {enter lev func {ar ""}} {
261
    variable debugwin
262
    variable logfile
263
    variable stoptrace
264
    variable tracing
265
 
266
    if {!$tracing} { return }
267
 
268
    set func [string trimleft $func :]
269
    if {$func == "DebugWin::put_trace" || $func == "DebugWin::_buildwin"} {
270
      if {$enter} {
271
        incr stoptrace
272
      } else {
273
        incr stoptrace -1
274
      }
275
    }
276
 
277
    if {$stoptrace == 0} {
278
      incr stoptrace
279
      # strip off leading function name
280
      set ar [lrange $ar 1 end]
281
      if {$debugwin != ""} {
282
        $debugwin put_trace $enter $lev $func $ar
283
      }
284
 
285
      if {$logfile != ""} {
286
        puts $logfile [concat {T} [list $enter] [list $lev] [list $func] \
287
                         [list $ar]]
288
      }
289
      incr stoptrace -1
290
    }
291
  }
292
 
293
# -----------------------------------------------------------------------------
294
# NAME:         debug::init
295
# SYNOPSIS:     init
296
# DESC:         Installs hooks in all procs and methods to enable profiling
297
#               and tracing.
298
# NOTES:        Installing these hooks slows loading of the program. Running
299
#               with the hooks installed will cause significant slowdown of
300
#               program execution. 
301
# -----------------------------------------------------------------------------
302
  proc init {} {
303
    variable VERSION
304
    variable absolute
305
    variable initialized
306
 
307
    # create the arrays for the .global. level
308
    createData .global.
309
 
310
    # start the absolute timer
311
    set absolute [clock clicks]
312
 
313
    # rename waits, exit, and all the ways of declaring functions
314
    rename ::vwait ::original_vwait
315
    interp alias {} ::vwait {} [namespace current]::sagevwait
316
    createData .wait.
317
 
318
    rename ::tkwait ::original_tkwait
319
    interp alias {} ::tkwait {} [namespace current]::sagetkwait
320
 
321
    rename ::exit ::original_exit
322
    interp alias {} ::exit {} [namespace current]::sageexit
323
 
324
    rename ::proc ::original_proc
325
    interp alias {} ::proc {} [namespace current]::sageproc
326
 
327
    rename ::itcl::parser::method ::original_method
328
    interp alias {} ::itcl::parser::method {} [namespace current]::sagemethod
329
 
330
    rename ::itcl::parser::proc ::original_itclproc
331
    interp alias {} ::itcl::parser::proc {} [namespace current]::sageitclproc
332
 
333
    rename ::body ::original_itclbody
334
    interp alias {} ::body {} [namespace current]::sageitclbody
335
 
336
    # redefine core procs
337
    #    foreach p [uplevel \#0 info procs] {
338
    #      set args ""
339
    #      set default ""
340
    #      # get the list of args (some could be defaulted)
341
    #      foreach arg [info args $p] {
342
    #   if { [info default $p $arg default] } {
343
    #     lappend args [list $arg $default]
344
    #   } else {
345
    #     lappend args $arg
346
    #   }
347
    #      }
348
    #      uplevel \#0 proc [list $p] [list $args] [list [info body $p]]
349
    #}
350
 
351
    set initialized 1
352
    resetWatch 0
353
    procEntry .global.
354
    startWatch
355
  }
356
 
357
# -----------------------------------------------------------------------------
358
# NAME:         ::debug::trace_start
359
# SYNOPSIS:     ::debug::trace_start
360
# DESC:         Starts logging of function trace information.
361
# -----------------------------------------------------------------------------
362
  proc trace_start {} {
363
    variable tracing
364
    set tracing 1
365
  }
366
 
367
# -----------------------------------------------------------------------------
368
# NAME:         ::debug::trace_stop
369
# SYNOPSIS:     ::debug::trace_stop
370
# DESC:         Stops logging of function trace information.
371
# -----------------------------------------------------------------------------
372
  proc trace_stop {} {
373
    variable tracing
374
    set tracing 0
375
  }
376
 
377
# -----------------------------------------------------------------------------
378
# NAME:         debug::sagetkwait
379
# SYNOPSIS:     sagetkwait {args}
380
# DESC:         A wrapper function around tkwait so we know how much time the
381
#               program is spending in the wait state.
382
# ARGS:         args - args to pass to tkwait
383
# ----------------------------------------------------------------------------
384
  proc sagetkwait {args} {
385
    # simulate going into the .wait. proc
386
    stopWatch
387
    procEntry .wait.
388
    startWatch
389
    uplevel ::original_tkwait $args
390
    # simulate the exiting of this proc
391
    stopWatch
392
    procExit .wait.
393
    startWatch
394
  }
395
 
396
# ----------------------------------------------------------------------------
397
# NAME:         debug::sagevwait
398
# SYNOPSIS:     sagevwait {args}
399
# DESC:         A wrapper function around vwait so we know how much time the
400
#               program is spending in the wait state.
401
# ARGS:         args - args to pass to vwait
402
# ----------------------------------------------------------------------------
403
  proc sagevwait {args} {
404
    # simulate going into the .wait. proc
405
    stopWatch
406
    procEntry .wait.
407
    startWatch
408
    uplevel ::original_vwait $args
409
    # simulate the exiting of this proc
410
    stopWatch
411
    procExit .wait.
412
    startWatch
413
  }
414
 
415
# -----------------------------------------------------------------------------
416
# NAME:         debug::sageexit
417
# SYNOPSIS:     sageexit {{value 0}}
418
# DESC:         A wrapper function around exit so we can turn off profiling
419
#               and tracing before exiting.
420
# ARGS:         value - value to pass to exit
421
# -----------------------------------------------------------------------------
422
  proc sageexit {{value 0}} {
423
    variable program_name GDBtk
424
    variable program_args ""
425
    variable absolute
426
 
427
    # stop the stopwatch
428
    stopWatch
429
 
430
    set totaltime [getWatch]
431
 
432
    # stop the absolute timer
433
    set stop [clock clicks]
434
 
435
    # unwind the stack and turn off everyone's timers
436
    stackUnwind
437
 
438
    # disengage the proc callbacks
439
    ::original_proc procEntry {name} {}
440
    ::original_proc procExit {name args} {}
441
    ::original_proc methodEntry {name} {}
442
    ::original_proc methodExit {name args} {}
443
 
444
    set absolute [expr {$stop - $absolute}]
445
 
446
    # get the sage overhead time
447
    set sagetime [expr {$absolute - $totaltime}]
448
 
449
    # save the data
450
    variable outfile
451
    variable VERSION
452
    set f [open $outfile w]
453
    puts $f "set VERSION {$VERSION}"
454
    puts $f "set program_name {$program_name}"
455
    puts $f "set program_args {$program_args}"
456
    puts $f "set absolute $absolute"
457
    puts $f "set sagetime $sagetime"
458
    puts $f "set totaltime $totaltime"
459
 
460
    foreach procname $data::entries {
461
      set totaltimes($procname) [set data::${procname}::totaltimes]
462
      set proccounts($procname) [set data::${procname}::proccounts]
463
      set timers($procname) [set data::${procname}::timers]
464
    }
465
 
466
    puts $f "array set totaltimes {[array get totaltimes]}"
467
    puts $f "array set proccounts {[array get proccounts]}"
468
    puts $f "array set timers {[array get timers]}"
469
    close $f
470
    original_exit $value
471
  }
472
 
473
 
474
  proc sageproc {name args body} {
475
    # stop the watch
476
    stopWatch
477
 
478
    # update the name to include the namespace if it doesn't have one already
479
    if {[string range $name 0 1] != "::"} {
480
      # get the namespace this proc is being defined in
481
      set ns [uplevel namespace current]
482
      if { $ns == "::" } {
483
        set ns ""
484
      }
485
      set name ${ns}::$name
486
    }
487
 
488
    createData $name
489
    # create the callbacks for proc entry and exit
490
    set ns [namespace current]
491
    set extra "${ns}::stopWatch;"
492
    append extra "set __.__ {};trace variable __.__ u {${ns}::stopWatch;${ns}::procExit $name;${ns}::startWatch};"
493
    append extra "[namespace current]::procEntry $name;"
494
    append extra "[namespace current]::startWatch;"
495
 
496
    set args [list $args]
497
    set body [list [concat $extra $body]]
498
 
499
    startWatch
500
 
501
    # define the proc with our extra stuff snuck in
502
    uplevel ::original_proc $name $args $body
503
  }
504
 
505
  proc sageitclbody {name args body} {
506
    # stop the watch
507
    stopWatch
508
 
509
    if {$name == "iwidgets::Scrolledwidget::_scrollWidget"} {
510
      # Hack.  This causes too many problems for the scrolled debug window
511
      # so just don't include it in the profile functions.
512
      uplevel ::original_itclbody $name [list $args] [list $body]
513
      return
514
    }
515
 
516
    set fullname $name
517
    # update the name to include the namespace if it doesn't have one already
518
    if {[string range $name 0 1] != "::"} {
519
      # get the namespace this proc is being defined in
520
      set ns [uplevel namespace current]
521
      if { $ns == "::" } {
522
        set ns ""
523
      }
524
      set fullname ${ns}::$name
525
    }
526
 
527
    createData $fullname
528
    # create the callbacks for proc entry and exit
529
    set ns [namespace current]
530
    set extra "${ns}::stopWatch;"
531
    append extra "set __.__ {};trace variable __.__ u {${ns}::stopWatch;${ns}::procExit $fullname;${ns}::startWatch};"
532
    append extra "[namespace current]::procEntry $fullname;"
533
    append extra "[namespace current]::startWatch;"
534
 
535
    set args [list $args]
536
    set body [list [concat $extra $body]]
537
 
538
    startWatch
539
 
540
    # define the proc with our extra stuff snuck in
541
    uplevel ::original_itclbody $name $args $body
542
  }
543
 
544
  proc sageitclproc {name args} {
545
    # stop the watch
546
    stopWatch
547
 
548
    set body [lindex $args 1]
549
    set args [lindex $args 0]
550
 
551
    if {$body == ""} {
552
      set args [list $args]
553
      set args [concat $args $body]
554
    } else {
555
      # create the callbacks for proc entry and exit
556
      set ns [namespace current]
557
      set extra "${ns}::stopWatch;"
558
      append extra "set __.__ {};trace variable __.__ u {${ns}::stopWatch;${ns}::methodExit $name;${ns}::startWatch};"
559
      append extra "[namespace current]::methodEntry $name;"
560
      append extra "[namespace current]::startWatch;"
561
 
562
      set args [list $args [concat $extra $body]]
563
    }
564
 
565
    startWatch
566
    uplevel ::original_itclproc $name $args
567
  }
568
 
569
  proc sagemethod {name args} {
570
    # stop the watch
571
    stopWatch
572
 
573
    set body [lindex $args 1]
574
    set args [lindex $args 0]
575
 
576
    if {[string index $body 0] == "@" || $body == ""} {
577
      set args [list $args]
578
      set args [concat $args $body]
579
    } else {
580
      # create the callbacks for proc entry and exit
581
      set ns [namespace current]
582
      set extra "${ns}::stopWatch;"
583
      append extra "set __.__ {};trace variable __.__ u {${ns}::stopWatch;${ns}::methodExit $name;${ns}::startWatch};"
584
      append extra "[namespace current]::methodEntry $name;"
585
      append extra "[namespace current]::startWatch;"
586
 
587
      set args [list $args [concat $extra $body]]
588
    }
589
 
590
    startWatch
591
    uplevel ::original_method $name $args
592
  }
593
 
594
  proc push {v} {
595
    variable stack
596
    variable level
597
    lappend stack $v
598
    incr level
599
  }
600
 
601
  proc pop {} {
602
    variable stack
603
    variable level
604
    set v [lindex $stack end]
605
    set stack [lreplace $stack end end]
606
    incr level -1
607
    return $v
608
  }
609
 
610
  proc look {} {
611
    variable stack
612
    return [lindex $stack end]
613
  }
614
 
615
  proc stackUnwind {} {
616
    # Now unwind all the stacked procs by calling procExit on each.
617
    # It is OK to use procExit on methods because the full name
618
    # was pushed on the stack
619
    while { [set procname [look]] != "" } {
620
      procExit $procname
621
    }
622
  }
623
 
624
  # we need args because this is part of a trace callback
625
  proc startWatch {args} {
626
    variable watchstart
627
    set watchstart [clock clicks]
628
  }
629
 
630
  proc resetWatch {value} {
631
    variable watch
632
    set watch $value
633
  }
634
 
635
  proc stopWatch {} {
636
    variable watch
637
    variable watchstart
638
    set watch [expr {$watch + ([clock clicks] - $watchstart)}]
639
    return $watch
640
  }
641
 
642
  proc getWatch {} {
643
    variable watch
644
    return $watch
645
  }
646
 
647
  proc startTimer {v} {
648
    if { $v != "" } {
649
      set data::${v}::timerstart [getWatch]
650
    }
651
  }
652
 
653
  proc stopTimer {v} {
654
    if { $v == "" } return
655
    set stop [getWatch]
656
    set data::${v}::timers [expr {[set data::${v}::timers] + ($stop - [set data::${v}::timerstart])}]
657
  }
658
 
659
  proc procEntry {procname} {
660
    variable level
661
    _puttrace 1 $level $procname [uplevel info level [uplevel info level]]
662
 
663
    set time [getWatch]
664
 
665
    # stop the timer of the caller
666
    set caller [look]
667
    stopTimer $caller
668
 
669
    incr data::${procname}::proccounts
670
 
671
    if { [set data::${procname}::nest] == 0 } {
672
      set data::${procname}::activetime $time
673
    }
674
    incr data::${procname}::nest
675
 
676
    # push this proc on the stack
677
    push $procname
678
 
679
    # start the timer for this
680
    startTimer $procname
681
  }
682
 
683
  proc methodEntry {procname} {
684
    variable level
685
 
686
    set time [getWatch]
687
 
688
    # stop the timer of the caller
689
    set caller [look]
690
    stopTimer $caller
691
 
692
    # get the namespace this method is in
693
    set ns [uplevel namespace current]
694
    if { $ns == "::" } {
695
      set ns ""
696
    }
697
    set name ${ns}::$procname
698
    _puttrace 1 $level $name [uplevel info level [uplevel info level]]
699
 
700
    if {![info exists data::${name}::proccounts]} {
701
      createData $name
702
    }
703
 
704
    incr data::${name}::proccounts
705
 
706
    if { [set data::${name}::nest] == 0 } {
707
      set data::${name}::activetime $time
708
    }
709
    incr data::${name}::nest
710
 
711
    # push this proc on the stack
712
    push $name
713
 
714
    # start the timer for this
715
    startTimer $name
716
  }
717
 
718
  # we need the args because this is called from a vartrace handler
719
  proc procExit {procname args} {
720
    variable level
721
 
722
    set time [getWatch]
723
    # stop the timer of the proc
724
    stopTimer [pop]
725
 
726
    _puttrace 0 $level $procname
727
 
728
    set r [incr data::${procname}::nest -1]
729
    if { $r == 0 } {
730
      set data::${procname}::totaltimes \
731
        [expr {[set data::${procname}::totaltimes] \
732
                 + ($time - [set data::${procname}::activetime])}]
733
    }
734
 
735
    # now restart the timer of the caller
736
    startTimer [look]
737
  }
738
 
739
  proc methodExit {procname args} {
740
    variable level
741
 
742
    set time [getWatch]
743
    # stop the timer of the proc
744
    stopTimer [pop]
745
 
746
    # get the namespace this method is in
747
    set ns [uplevel namespace current]
748
    if { $ns == "::" } {
749
      set ns ""
750
    }
751
    set procname ${ns}::$procname
752
 
753
    _puttrace 0 $level $procname
754
 
755
    set r [incr data::${procname}::nest -1]
756
    if { $r == 0 } {
757
      set data::${procname}::totaltimes \
758
        [expr {[set data::${procname}::totaltimes] \
759
                 + ($time - [set data::${procname}::activetime])}]
760
    }
761
 
762
    # now restart the timer of the caller
763
    startTimer [look]
764
  }
765
}

powered by: WebSVN 2.1.0

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