📄 argand.tcl
字号:
# * repaint
# re-create the display and its axes, to account for
# user resizing of the window
# * trace
# Do all that's necessary to respond to a change of the
# currently selected moment of simulation time. This is
# achieved simply by calling privArgand_proc again
# (recursively!) first with the getValues option and then
# with the replot option.
# * destroy
# Do all necessary cleanup operations as required when one
# of these plot windows is destroyed
#
# * index:
# the index number of the plot window that is to be manipulated.
#
# Other arguments can be added if required, but they aren't used
# in this version.
proc privArgand_proc {option index args} {
global privArgand
global vsimPriv
switch -glob -- $option {
getValues { # ________________________________________ getValues ___
# Look in the wave window to find the relevant signal values.
# If one or both signals are absent, return 0 and do nothing.
# If both signals are found, return 1 (true) and update the
# variables privArgand($index,X) and privArgand($index,Y).
#
# ########## NOTE ##############
# The code given here to search the wave tree is useful because it
# allows the scaling of the plot display to be influenced on-the-fly
# by the height and scale factor of the analog waveform display.
# We pay a heavy price for this flexibility, and in most cases it
# will be better to use the ModelSim "examine" command to find
# the values of signals at specific times.
# Locate the tree.
#
set tree $privArgand($index,tree)
# First, locate the two signals. They may have been moved since
# we set up the window, and ModelSim's "find" command would alter
# the user's selection, so we must search the wave window by hand.
#
foreach {x_fullName y_fullName} $privArgand($index,fullNames) {}
set x_index {}
set y_index {}
for {set i 0} {$i < [$tree size]} {incr i} {
# Use "string equal" if you have Tcl/Tk 8.3 (ModelSim 5.6 or above)
#
if {![string compare [$tree get4 $i] $x_fullName]} {set x_index $i}
if {![string compare [$tree get4 $i] $y_fullName]} {set y_index $i}
}
# Assume all's well until proven otherwise...
#
set valOK 1
# Did we find both?
#
if {(![string length $x_index]) || (![string length $y_index])} {
# One or both signals has been deleted, can't get its value!
set valOK 0
} else {
# Both signals are still available. Get their values.
# We must check that the values are proper numbers, to
# protect against "X" values etc. In Tcl 8.3 or higher, we
# can do this easily with the "string is double" command. For
# backwards compatibility we do it a different way here: we try
# to increment the value by zero, and use "catch" to detect
# whether the increment failed.
# Get the X-value
#
set privArgand($index,X) [$tree get3 $x_index]
# Check it's a number
#
if {[catch {incr privArgand($index,X) 0}]} {
# It's not a valid number
#
set privArgand($index,X) 0
set valOK 0
}
# Same process for the Y-value
#
set privArgand($index,Y) [$tree get3 $y_index]
if {[catch {incr privArgand($index,Y)}]} {
set privArgand($index,Y) 0
set valOK 0
}
# If we got valid numbers, find the scale factors.
# This we determine from the height and scale factors
# of the analog displays.
#
# Find maximum of the two trace heights:
#
set h [$tree itemcget $x_index -height]
set hY [$tree itemcget $y_index -height]
if {$h < $hY} {set h $hY}
# Obtain scale factors for both traces
#
set s [$tree itemcget $x_index -scale]
set privArgand($index,rangeX) [expr $h/($s*2)]
set s [$tree itemcget $y_index -scale]
set privArgand($index,rangeY) [expr $h/($s*2)]
}
# Do we need to change display state?
#
set privArgand($index,doState) 1
if {[info exists privArgand($index,valOK)]} {
if {$privArgand($index,valOK) == $valOK} {
set privArgand($index,doState) 0
}
}
set privArgand($index,valOK) $valOK
}
rep* { # _______________________________________ replot, repaint ___
# Repaint or replot the window. First, find its canvas:
#
set c $privArgand($index,plot)
# Determine the window's size
#
set w [winfo width $c]
set h [winfo height $c]
# Determine its origin (centre)
#
set x0 [expr $w/2]
set y0 [expr $h/2]
# Determine half-size (minimum of w/2, h/2)
#
set r $x0
if {$r > $y0} {set r $y0}
# Move axes if necessary (only for repaint, not replot)
#
if {![string compare $option repaint]} {
$c coords axisX [expr $x0-$r] $y0 [expr $x0+$r] $y0
$c coords axisY $x0 [expr $y0+$r] $x0 [expr $y0-$r]
$c coords labelX [expr $x0+$r-5] [expr $y0-5]
$c coords labelY [expr $x0+5] [expr $y0-$r+5]
}
# Sort out the vector plot
#
set x [expr $x0 + $r*$privArgand($index,X)/$privArgand($index,rangeX)]
set y [expr $y0 - $r*$privArgand($index,Y)/$privArgand($index,rangeY)]
$c coords vector $x0 $y0 $x $y
$c coords pointH [expr $x-5] $y [expr $x+5] $y
$c coords pointV $x [expr $y-5] $x [expr $y+5]
# Could possibly add some code here to leave trails behind,
# making a cumulative constellation plot. The following line
# is a possible method, but it has a nasty bug (try resizing
# the window when this code is in use!). It also creates very
# large numbers of objects on the canvas, which probably leads to
# significantly worse performance.
#
# $c lower [$c create rectangle $x $y $x $y -outline darkgray]
# Grey-out the display if necessary
#
if {$privArgand($index,doState)} {
# The "valOK" state flag has changed.
# Modify the display as appropriate.
#
if {$privArgand($index,valOK)} {
$c lower noData
$c configure -background black
$c itemconfigure noData -fill black
$c itemconfigure pointH -fill white
$c itemconfigure pointV -fill white
$c itemconfigure labelX -fill white
$c itemconfigure labelY -fill white
$c itemconfigure vector -fill green
} else {
$c raise noData
$c configure -background darkgray
$c itemconfigure noData -fill red
$c itemconfigure pointH -fill darkgray
$c itemconfigure pointV -fill darkgray
$c itemconfigure labelX -fill darkgray
$c itemconfigure labelY -fill darkgray
$c itemconfigure vector -fill darkgray
}
# Note that the change has been effected.
#
set privArgand($index,doState) 0
}
}
trace { # ______________________________________________ trace ___
# Cursor was moved or swapped, or simulation time advanced.
# Update the display.
privArgand_proc getValues $index
privArgand_proc replot $index
}
destroy { # ____________________________________________ destroy ___
# Clean up all our debris
#
trace vdelete vsimPriv(acttime) w $privArgand($index,trace)
# Really get rid of the window
#
destroy $privArgand($index,toplevel)
# Get rid of private globals specific to this window
#
foreach n [array names privArgand $index,*] {
unset privArgand($n)
}
}
default { # ____________________________________ catchall default ___
uplevel error "\{privArgand_proc: bad option \"$option\": \
must be one of getValues, repaint, trace, destroy\}"
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -