#!/usr/bin/wish

package require BLT
namespace import blt::*

###############################################################
#
#   Key presses -- shortcuts to menu items
#
#          q -- quit
#          o -- graph options
#          d -- select data items for graphing
#         -> -- scroll 1 "page" to the right
#         <- -- scroll 1 "page" to the left
#
###############################################################

bind . <q> {exit 0}
bind . <o> {SetGraphOptions}
bind . <d> {GetGraphData ""}
bind . <Key-Right> {ScrollAll scroll  1 pages}
bind . <Key-Left>  {ScrollAll scroll -1 pages}

################################################################
#
# Read in the test data
#
#   column_count gives total number of vectors
#   V0 will be the x-axis variable for all the others
#       (instruction count)
#   V1 ... V<column_count-1> contain data to be plotted
#   column_names() array contains labels for vectors
#   column_indices() array contains column numbers for labels
#
################################################################

source $env(PROFILER_DIR)/_read_emitter.tcl
source $env(PROFILER_DIR)/_error_dialog.tcl

################################################################
#
#  Set up to select the graphs from the list of available vectors
#
################################################################

source $env(PROFILER_DIR)/_choose_from_list.tcl

################################################################
#
# Set of options governing display of the graph
#
################################################################

# yTicksLength = The current width (in "m"s) for multiple graphs
# yInitialTicksLength = The initial width (in "m"s) for multiple graphs
# yFixedTicksLength The fixed width for single graph options -- should be fixed
array set graphOptions {
    yTicksLength         5
    yInitialTicksLength  5
    yFixedTicksLength    13
    yTicksCommas         yes
    xTicksRotation       0
    xTicksCommas         yes
    xAxisLabel           "Machine Cycles"
    yAxisLabel           ""
    y2AxisLabel          ""
    plotCount            0
    title                ""
    currentDirectory     "."
    pattern              "str*"
    fileName             ""
    plotStyle            multiple
    displayedPlotStyle   multiple
    barChart             0
    initialRead          2000000000
    subsequentRead       0
    waitRead             1
}

#################################################################
#
# Define a dummy graph for the bottom of the table.
# This is used to dislay the (common) x-axis
#
#################################################################

proc DefineDummyXAxisGraph {} {
    global graphOptions

    graph .glast -title "" -topmargin 1 -rightmargin 1 \
	    -height .8i -width 10i \
	    -plotpadx 4 -plotpady 0 -bd 0
    .glast axis configure x -title $graphOptions(xAxisLabel)
    .glast axis configure x -command FormatXTickLabels
    .glast axis configure x -scrollcommand ".xbar set"
    .glast axis configure y -title "" -command FormatYTickLabelsFixedLength -min 0 -max 0.0001
    .glast axis configure y -color [. cget -background]
    .glast legend configure -hide yes
    .glast element create "e1" -xdata V0 -ydata 0 -color white -symbol none -smooth step
}

################################################################
#
# Initialization
#
################################################################

# Initialize the zoom stack
set zoomStack {}

# Count of graphs currently displayed
set graphCount 0

# List of graphs currently displayed
set graphList ""

# Names of columns currently displayed
set graphVectorList ""

# Axis indicator (L, R) for each column
set graphAxisList ""

################################################################
#
# Menu bar
#
################################################################

option add *background grey85

. configure -background grey85

frame .mbar -borderwidth 2 -relief groove

####################################
#  FILE button
####################################

menubutton .mbar.file -text " File " -menu .mbar.file.m -relief raised
pack .mbar.file -side left -padx 4
menu .mbar.file.m

# "Open"

.mbar.file.m add command -label "Open" \
	-command {GetFileName "Open data file" \
	$graphOptions(currentDirectory) $graphOptions(pattern) OpenFile}

# "Print"

.mbar.file.m add command -label "Print" \
	-command {PrintCommand}

# "Exit"

.mbar.file.m add command -label "Exit" \
	-command {exit}

####################################
#  DATA button
####################################

button .mbar.data -text "Data" -relief raised -command {GetGraphData ""} -underline 0
pack .mbar.data -side left -padx 4

####################################
#  OPTIONS button
####################################

button .mbar.options -text "Options" -relief raised -command {SetGraphOptions} -underline 0
pack .mbar.options -side left -padx 4


##############################################################
#
#  Title at top of graph
#
##############################################################

label .title -textvariable graphOptions(title)

##########################################################
#
#  Horizontal scrollbar at top of stack of graphs
#  scrolls all of them at once
#
##########################################################

scrollbar .xbar  -orient horizontal -command {ScrollAll}

proc ScrollAll {args} {
	global graphList

	foreach i $graphList {
		eval [concat $i axis view x $args]
    }
    eval [concat .glast axis view x $args]
}

DefineDummyXAxisGraph

########################################################
#
#  Define the table that configures all the graphs
#
#  Constant stuff (menu bar, x-axis graph) goes at top and bottom.
#  Data graphs are added at in-between rows later.
#
########################################################

table . \
    .mbar    0,0  -cspan 2  -fill x  \
    .title   1,0  -cspan 2           \
    .xbar    2,0  -cspan 2  -fill x  \
    .glast   3,1            -fill x

table configure . c0 r0 r1 r2 r3 -resize none

####################################################
#
#  Read in the print-to-postscript and
#  file selection dialog support routines
#
####################################################

source $env(PROFILER_DIR)/_ps.tcl
source $env(PROFILER_DIR)/_select_file.tcl


################################################################
#
# DefineMultGraph -- Create a graph widget, potentially one of
#                    several, that displays a single vector
#
#   parameters:  name (path) of graph
#                index number of vector for x-axis
#                index number of vector for y-axis (the data to be plotted)
#
################################################################

proc DefineMultGraph { g xindex yindex} {
    global column_names column_indices column_count graphCount graphList

    set xvals "V$xindex"
    set yvals "V$yindex"

puts "DefineMultGraph g is $g, index $yindex"
    graph $g -title "" -topmargin 1 -bottommargin 1 -rightmargin 1 \
	    -height 1i -width 10i \
	    -plotpadx 4 -plotpady 8 -bd 0
    $g axis configure x -title "" -hide yes
    $g axis configure y -title "" -min 0
    $g axis configure y2 -hide yes
    $g axis configure y -command FormatYTickLabelsFixedLength
    $g element create "e1" -xdata $xvals -ydata $yvals -color blue -symbol none -smooth step
    $g legend configure -hide yes
    set gl [format "%slabel" $g]
    label $gl -text $column_names($yindex)

    # Bind mouse buttons to zoom in/out

    bind $g <ButtonPress-1>   {SelectStart %W %x %y}
    bind $g <B1-Motion>       {SelectMove  %W %x %y}
    bind $g <ButtonRelease-1> {SelectEnd   %W %x %y}
    bind $g <ButtonRelease-3> {ZoomOut             }

    # Record this graph -- bump count graphs, add to graph list
    incr graphCount
    lappend graphList $g

    # Delete the "x-axis" graph from the last row,
    #   insert the new graph there,
    #   re-insert the "x-axis" graph one row down.

    set current [expr $graphCount + 2]
    set next    [expr $graphCount + 3]
	# TODO FIX THIS
    #table configure . -rows $current    ;# removes last row
    table . \
	    $gl    $current,0 -anchor e  \
	    $g     $current,1 -fill both \
	    .glast $next,1    -fill x
    table configure . r$current -resize both
    table configure . r$next    -resize none
}

################################################################
#
# DefineSingleGraph -- Create a single graph widget that displays
#                      one or more vectors
#
#   parameters:  name (path) of graph
#                index number of vector for x-axis
#                list of "column names" (names of vectors of
#                  data to be plotted)
#                list indicating which axis (Left, Right) is
#                  to be used for each vector
#
################################################################

proc DefineSingleGraph {g xindex ylist axes} {
    global column_names column_indices column_count
    global graphCount graphList graphVectorList graphAxisList graphOptions
    global V0

puts "DefineSingleGraph g is $g"
    # hack -- predefine a color list
    set colorList {black brown red orange green blue violet gray50 magenta cyan darkgreen darkorange}

    set dashList {
	{}
	{8 2}
	{6 2 2 2}
	{2 2}
	{6 2 2 2 2 2}
	{6 2 6 2 2 2 2 2}
    }

    set xvals "V$xindex"

    if {$graphOptions(barChart)} {
	puts "ylist is $ylist"
	set bw 1
	if {[V0 length] >= 1} {
	    set n [llength $ylist]          ;# number of bars to plot per x value
	    set xdelta [expr $V0(1) - $V0(0)]
	    set bw [expr $xdelta / $n]
	}
	puts "make the bar chart, bw is $bw"
	barchart $g -title "" \
		-height 6i -width 10i \
		-plotpadx 4 -plotpady 8 -bd 0 \
		-barmode stacked -barwidth $bw
	puts "made"
    } else {
	graph $g -title "" \
		-height 6i -width 10i \
		-plotpadx 4 -plotpady 8 -bd 0
    }
    $g axis configure x  -title $graphOptions(xAxisLabel) -scrollcommand ".xbar set" -command FormatXTickLabels
    $g axis configure y  -title $graphOptions(yAxisLabel)
    $g axis configure y  -command FormatYTickLabels -color blue -min 0.0 -max 1.2
    $g axis configure y2 -title $graphOptions(y2AxisLabel)
    $g axis configure y2 -command FormatYTickLabels -color red  -min 0.0 -max 1.2
    $g legend configure -position top -relief flat

    if {[lsearch $graphAxisList "Left"]  >= 0} {
	set leftPresent 1
	$g axis configure y -hide no
    } else {
	set leftPresent 0
	$g axis configure y -hide yes
    }
    if {[lsearch $graphAxisList "Right"] >= 0} {
	set rightPresent 1
	$g axis configure y2 -hide no
    } else {
	set rightPresent 0
	$g axis configure y2 -hide yes
    }
    set bothPresent [expr $leftPresent & $rightPresent]

    set lcount 0
    set rcount 0
    set enum 1
    foreach e $ylist a $axes {
	set yvals "V$column_indices($e)"
	set color [lindex $colorList [expr $enum % [llength $colorList]]]
	if {$a == "Left"} {
#	    set color blue
	    set lineType $lcount
	    incr lcount
	    set yaxis y
	} else {
#	    set color red
	    set lineType $rcount
	    incr rcount
	    set yaxis y2
	}
	if {$graphOptions(barChart)} {
	    $g pen create $e -foreground $color -relief flat
	    $g element create $e -xdata $xvals -ydata $yvals \
		    -mapy $yaxis -pen $e
	} else {
	    $g pen create $e -color $color -linewidth 1 -symbol none \
		    -dashes [lindex $dashList [expr $lineType % [llength $dashList]]]
	    $g element create $e -xdata $xvals -ydata $yvals \
		    -smooth step -mapy $yaxis -pen $e
	}
	incr enum
    }
    set gl [format "%slabel" $g]
    label $gl -text "" -width 0

    # Bind mouse buttons to zoom in/out

    bind $g <ButtonPress-1>   {SelectStart %W %x %y}
    bind $g <B1-Motion>       {SelectMove  %W %x %y}
    bind $g <ButtonRelease-1> {SelectEnd   %W %x %y}
    bind $g <ButtonRelease-3> {ZoomOut             }

   if {[lsearch $ylist "*POWER*"] >= 0} {
       puts "have a POWER GRAPH in here"
       bind $g <Shift-ButtonRelease-1>  "TrackPC $g %x %y"
       bind $g <Shift-Motion>  "TrackPC $g %x %y"
       bind $g <Shift-ButtonPress-1>  "ShowPC $g %x %y"
    }


    # Record this graph -- bump count graphs, add to graph list

    incr graphCount
    lappend graphList $g

    table . \
		.mbar    0,0  -cspan 2  -fill x  \
		.title   1,0  -cspan 2           \
		.xbar    2,0  -cspan 2  -fill x  \
		$gl		 3,0            -fill both \
		$g  	 3,1            -fill both

    table configure . c0 r0 r1 r2 -resize none
    table configure . r3 -resize both
}

###########################################################
#
#  Procedures to format tick labels
#
#  For the y-axis tick labels, it is important that they
#  all be the same number of characters so that the graph
#  widget doesn't pick different widths for the y-axis
#  regions of the graphs.
#
###########################################################

proc FormatXTickLabels {graph val} {
    global graphOptions
    set xval $val

# hack to make this print correct values > 2^31
    if ![regexp "e" $val] { append xval "e0" }

	if {$graphOptions(xTicksCommas) == "yes"} {
	    return [CommaInsert $xval]
	} else {
	    return $xval
	}
}

proc FormatYTickLabelsFixedLength {graph val} {
    global graphOptions graphVectorList graphAxisList

    if {$graphOptions(yTicksCommas) == "yes"} {
	# Commas wanted

	set v [CommaInsert $val]

    # Find width of value in pixels
    set vlength [font measure [$graph axis cget y -tickfont] $v]
    # Find target width
    set tlength [expr $graphOptions(yTicksLength) * [font measure [$graph axis cget y -tickfont] m]]
    # Bump up target width if the new value is wider than it
    while { [expr $tlength < $vlength] } {
        set graphOptions(yTicksLength) [expr 3 + $graphOptions(yTicksLength)]
        set tlength [expr $graphOptions(yTicksLength) * [font measure [$graph axis cget y -tickfont] m]]
    }

    # The width we need to make up
    set difflength [expr $tlength - $vlength]
    # The number of spaces equal to that width
    set diffspaces [expr $difflength / [font measure [$graph axis cget y -tickfont] " "]]
    set spaces [string repeat " " $diffspaces]
    append spaces $v
    return $spaces

    } else {

	# No commas; format with %g, specifying proper length

	set fmt [format "%%%sg" $graphOptions(yTicksLength)]
	return [format "$fmt" $val]
    }
}

proc FormatYTickLabels {graph val} {
    global graphOptions
    if {$graphOptions(yTicksCommas) == "yes"} {

	# Commas wanted

	return [CommaInsert $val]

    } else {

	# No commas; format with %g

	return $val
    }
}

proc FormatDummyYTickLabels {graph val} {
    global graphOptions
    set blanks "                                       "
    return [string range $blanks 1 $graphOptions(yTicksLength)]
}


###################################################################
#
# Zooming support
#
###################################################################

proc ZoomIn {x0 y0 x1 y1} {
    global graphList

    if {($x0 == $x1) || ($y0 == $y1)} {
	# first and last points are the same
	return
    }
    busy hold .
    update
    PushZoomStack [.glast xaxis cget -min] [.glast xaxis cget -max] \
	    [.glast yaxis cget -min] [.glast yaxis cget -max]

    if {$x0 > $x1} {
	set temp $x0
	set x0 $x1
	set x1 $temp
    }
    .glast xaxis configure -min $x0 -max $x1
    foreach w $graphList {
	$w xaxis configure -min $x0 -max $x1
    }

    update
    busy release .
}

proc ZoomOut { } {
    global zoomStack graphList
    if {![EmptyZoomStack]} {
	busy hold .
	update
	set level [llength $zoomStack]
	ShowLevel [expr $level - 1]
	eval [PopZoomStack]
	set x0 [.glast xaxis cget -min]
	set x1 [.glast xaxis cget -max]
	foreach w $graphList {
	    $w xaxis configure -min $x0 -max $x1
	}
	busy release .
	after 2000 "HideLevel"
    }
}

proc GetCoords {win scrX scrY xVar yVar} {
    upvar $xVar x
    upvar $yVar y
    set coords [$win invtransform $scrX $scrY]
    set x [lindex $coords 0]
    set y [lindex $coords 1]
}

proc SelectStart {win x y} {
    global x0 y0
    GetCoords $win $x $y x0 y0
    CreateRectangle $win
}

proc SelectMove {win x y} {
    global x0 y0
    GetCoords $win $x $y x1 y1
    DrawRectangle $win $x0 $y0 $x1 $y1
}

proc SelectEnd {win x y} {
    global x0 y0
    GetCoords $win $x $y x1 y1
    DestroyRectangle $win
    ZoomIn $x0 $y0 $x1 $y1
}

proc CreateRectangle {win} {
    global zoomStack
    $win marker create line -name ZoomRegion -dashes {4 2}
    # Display the level of the *next* zoom.
    ShowLevel [expr [llength $zoomStack] + 1]
}

proc DrawRectangle {win x0 y0 x1 y1} {
    $win marker configure "ZoomRegion" \
	    -coords {$x0 $y0 $x1 $y0 $x1 $y1 $x0 $y1 $x0 $y0}
}

proc DestroyRectangle {win} {
    global zoomStack
    $win marker delete "ZoomRegion"
    HideLevel
}

proc EmptyZoomStack {} {
    global zoomStack
    return [expr {[llength $zoomStack] == 0}]
}

proc PushZoomStack {xmin xmax ymin ymax} {
    global zoomStack
    set fmt {
	.glast xaxis configure -min "%s" -max "%s"
#	.glast yaxis configure -min "%s" -max "%s"
    }
    lappend zoomStack [format $fmt $xmin $xmax $ymin $ymax]
}

proc PopZoomStack {} {
    global zoomStack
    set cmd [lindex $zoomStack end]
    set zoomStack [lreplace $zoomStack end end]
    return $cmd
}

proc ShowLevel {level} {
    set text "Zoom #$level"

    set w ""
    if {[winfo exists .glast]} {
	set w .glast
    }
    if {[winfo exists .g1]} {
	set w .g1
    }
    if {$w == ""} {return}

    if {[$w marker exists "ZoomLevel"]} {
	$w marker configure "ZoomLevel" -text $text
    } else {
	$w marker create text -name "ZoomLevel" -text $text \
		-coords {-Inf Inf} -anchor nw -bg {} -fg darkgreen
    }
    after 2000 HideLevel
}

proc HideLevel {} {
    set w ""
    if {[winfo exists .glast]} {
	set w .glast
    }
    if {[winfo exists .g1]} {
	set w .g1
    }
    if {$w == ""} {return}

    if {[$w marker exists "ZoomLevel"]} {
	$w marker delete "ZoomLevel"
    }
}

######################################################################
#
# CommaInsert -- Put punctuating commas into numbers, so that
#                large integers can be parsed by eye.
#                1000000000  becomes 1,000,000,000
#
######################################################################

proc CommaInsert {val} {
    global graphOptions

    set retval ""

    # If $val formatted with "%f" contains a non-zero fraction part,
    # don't try to insert commas.  Just return the value unchanged.

#    set prec [expr $graphOptions(yTicksLength) - 6]
    set prec 7
    set fmt [format "%%.%sf" $prec]
    set fval [format "$fmt" $val]
    set dot [string first "." $fval]
    if {$dot >= 0} {
	set frac [string range $fval $dot end]
	if {$frac != 0} {
	    return $val
	}
    }

    set sign ""
    if {$val < 0} {
	set sign "-"
	set val [expr 0 - $val]
    }

    set val [format "%.0f" $val]

    set lv [string length $val]
    if {$lv < 4} {
	return "$sign$val"
    }
    set ex [expr $lv % 3]
    if {$ex == 2} {
	set retval [string range $val 0 1]
	append retval ","
    } elseif {$ex == 1} {
	set retval [string range $val 0 0]
	append retval ","
    }
    while {$ex <= $lv - 3} {
	append retval [string range $val $ex [expr $ex + 2]]
	if {$ex < $lv - 3} {
	    append retval ","
	}
	set ex [expr $ex + 3]
    }
    return "$sign$retval"
}

######################################################################
#
#  Select list of vectors to be plotted
#
######################################################################

proc GetGraphData {graph} {
    global column_count column_names
    global graphVectorList graphAxisList

    set names ""
    for {set i 0} {$i < $column_count} {incr i} {
		lappend names $column_names($i)
    }

    ChooseFromList $graph "Select data to be plotted" $names $graphVectorList $graphAxisList GetGraphDataCallback
}

proc TrackPC {graph x y} {

}

proc ShowPC {graph x y} {
	if { [$graph element closest $x $y info ] } {
	    set pclist [getPC $info(index)]
	    puts "pclist is $pclist"
	    puts [llength $pclist]
	    set pc [lindex $pclist 0]
	    set name [lindex $pclist 1]
	    if { $name == "" } {
		set name "UNKOWN"
	    }
	    set prelist [lindex $pclist 2]
	    set theline [lindex $pclist 3]
	    set taillist [lindex $pclist 4]
	    showSrc $pc $name $prelist $theline $taillist
	} else {
	    puts "no closest"
	}
}

proc showSrc {pc name prelist line postlist} {

    set srco .srco
    toplevel $srco
    label $srco.title -text "PC: $pc proc: $name"

    listbox $srco.lb -width 60 -height 11 \
	    -yscrollcommand "$srco.sb set"
    scrollbar $srco.sb -orient vertical \
	    -command "$srco.lb yview"

    table $srco \
	    0,0 $srco.title -cspan 2 \
	    1,0 $srco.sb \
	    1,1 $srco.lb

    eval [concat $srco.lb insert 0 $prelist $line $postlist ]

    $srco.lb yview [expr [llength $prelist] + 1]
}


set L1I {}
proc TrackCache {cache graph element x y} {
	global L1I
	if { [$graph element closest $x $y info $element] } {
		puts "$cache index is $info(index)"
		set $cache $info(index)
	}
}
proc ClearTrack {cache} {
	global L1I
	set $cache {}
}

proc GetGraphDataCallback {choices axes} {
    global graphCount graphList graphVectorList graphAxisList
    global column_indices
    global graphOptions

puts "GetGraphDataCallback choices is $choices axes is $axes"
    if {$choices == ""} {
	return                 ;# selection operation was cancelled
    }

# reset the y tick offset
    set graphOptions(yTicksLength) $graphOptions(yInitialTicksLength)

    # Delete the current set of graphs, if any

	foreach n $graphList {
		set nl [format "%slabel" $n]
		table forget $n
		table forget $nl
		destroy $n
		destroy $nl
    }
    if {[winfo exists .glast]} {
	destroy .glast
    }
    set graphList ""
    set graphVectorList $choices
    set graphAxisList   $axes
    set graphCount 0

    # Add a new set of graphs

    set gnum 1
    if {$graphOptions(plotStyle) == "multiple"} {

	# Reinitialize the "element" in the dummy graph showing the x-axis
	DefineDummyXAxisGraph
	.glast element delete "e1"
	.glast element create "e1" -xdata V0 -ydata 0 -color white -symbol none -smooth step

	foreach v $choices {
	    set index $column_indices($v)
	    set graph ".g$gnum"
	    DefineMultGraph $graph 0 $index
	    if { [string compare "$v" "L1I_CACHE_MISS"] == 0 } {
    		bind $graph <Shift-Motion>   "TrackCache L1I $graph e1 %x %y"
    		bind $graph <Shift-ButtonPress-1>  "ClearTrack L1I"
	    }
	    if { [string first "POWER" "$v"] == 0 } {
    		bind $graph <Shift-ButtonRelease-1>  "TrackPC $graph %x %y"
    		bind $graph <Shift-Motion>  "TrackPC $graph %x %y"
    		bind $graph <Shift-ButtonPress-1>  "ShowPC $graph %x %y"
	    }

	    $graph xaxis configure -min [.glast xaxis cget -min] -max [.glast xaxis cget -max]

	    incr gnum
	}
    } else {
	set graph ".glast"
	DefineSingleGraph $graph 0 $choices $axes
    }
}

######################################################################
#
# SetGraphOptions
#
######################################################################

proc SetGraphOptions {} {
    global graphOptions

    set graphOptions(displayedPlotStyle) $graphOptions(plotStyle)

    # Title on top line

    set sgo .sgo
    toplevel $sgo
    label $sgo.title -text "Set graph options"

    # Graph style -- multiple plots (one vector per plot), or single plot (all vectors on same plot)

    frame $sgo.graphStyle -relief flat -borderwidth 0
    label $sgo.graphStyle.label -text "Plot style:  " -relief flat
    radiobutton $sgo.graphStyle.multiple -text "Multiple plots, one vector per plot" \
	    -variable graphOptions(plotStyle) -value multiple -command SetGraphOptionsStyleChanged
    radiobutton $sgo.graphStyle.single   -text "All vectors on a single plot"   \
	    -variable graphOptions(plotStyle) -value single   -command SetGraphOptionsStyleChanged
    table $sgo.graphStyle \
	    0,0 $sgo.graphStyle.label -anchor w    \
	    0,1 $sgo.graphStyle.multiple -anchor w \
	    1,1 $sgo.graphStyle.single -anchor w

    # Graph title, labels for x-axis, y-axis, y2-axis

    frame $sgo.labels -relief flat -borderwidth 0
    label $sgo.labels.t  -text "Graph title:" -relief flat
    entry $sgo.labels.title -textvariable graphOptions(title) \
	    -justify left -relief sunken -width 50
    label $sgo.labels.lx -text "X-axis label:" -relief flat
    entry $sgo.labels.xaxis -textvariable graphOptions(xAxisLabel) \
	    -justify left -relief sunken -width 50
    label $sgo.labels.ly -text "Left Y-axis label:" -relief flat
    entry $sgo.labels.yaxis -textvariable graphOptions(yAxisLabel) \
	    -justify left -relief sunken -width 50
    label $sgo.labels.ly2 -text "Right Y-axis label:" -relief flat
    entry $sgo.labels.y2axis -textvariable graphOptions(y2AxisLabel) \
	    -justify left -relief sunken -width 50

    # Make the y-axis label entry fields match the single/multiple state

    SetGraphOptionsStyleChanged

    table $sgo.labels \
	    0,0 $sgo.labels.t      -anchor w \
	    0,1 $sgo.labels.title  -anchor w -padx {15 0} \
	    1,0 $sgo.labels.lx     -anchor w \
	    1,1 $sgo.labels.xaxis  -anchor w -padx {15 0} \
	    2,0 $sgo.labels.ly     -anchor w \
	    2,1 $sgo.labels.yaxis  -anchor w -padx {15 0} \
	    3,0 $sgo.labels.ly2    -anchor w \
	    3,1 $sgo.labels.y2axis -anchor w -padx {15 0}
    table configure $sgo.labels r1 r2 -pady {15 0}

    # Specify rotation of tick labels on X-axis

    frame $sgo.tickRotate -relief flat -borderwidth 0
    label $sgo.tickRotate.label -text "X-axis tick labels rotation:  " -relief flat
    entry $sgo.tickRotate.value -textvariable graphOptions(xTicksRotation) \
	    -justify left -relief sunken -width 3
    table $sgo.tickRotate \
	    0,0 $sgo.tickRotate.label -anchor w \
	    0,1 $sgo.tickRotate.value -anchor w

    # Disable the rotation value for now, as it no longer seems to work correctly
    # when the xaxis is reconfigured.

    $sgo.tickRotate.value configure -state disabled -bg grey85

    # Parameters for incremental reading of data file

    frame $sgo.incr -relief flat -borderwidth 0
    label $sgo.incr.l1 -text "Incremental reading:    Initial " -relief flat
    entry $sgo.incr.initial -textvariable graphOptions(initialRead) \
	    -justify left -relief sunken -width 5
    label $sgo.incr.l2 -text "    Increment " -relief flat
    entry $sgo.incr.increment -textvariable graphOptions(subsequentRead) \
	    -justify left -relief sunken -width 5
    label $sgo.incr.l3 -text "    Period " -relief flat
    entry $sgo.incr.period -textvariable graphOptions(waitRead) \
	    -justify left -relief sunken -width 5

    table $sgo.incr \
	    0,0 $sgo.incr.l1         -anchor w \
	    0,1 $sgo.incr.initial    -anchor w \
	    0,2 $sgo.incr.l2         -anchor w \
	    0,3 $sgo.incr.increment  -anchor w \
	    0,4 $sgo.incr.l3         -anchor w \
	    0,5 $sgo.incr.period     -anchor w

    # "Done" button on bottom line

    button $sgo.done -text "Done" -command "SetGraphOptionsDone"

    # Put it all together

    table $sgo \
	    0,0 $sgo.title      -anchor c               -pady {15 0}  \
	    1,0 $sgo.graphStyle -anchor w -padx {15 15} -pady {15 0}  \
	    2,0 $sgo.labels     -anchor w -padx {15 15} -pady {15 0}  \
	    3,0 $sgo.tickRotate -anchor w -padx {15 15} -pady {15 0}  \
	    4,0 $sgo.incr       -anchor w -padx {15 15} -pady {15 0}  \
	    5,0 $sgo.done       -anchor w -padx {15 0}  -pady {15 15}

    # The "Enter" key invokes the "Done" button

    bind $sgo <KeyPress-Return> "$sgo.done invoke"
}

proc SetGraphOptionsStyleChanged {} {
    global graphOptions

    if {$graphOptions(plotStyle) == "single"} {
	.sgo.labels.yaxis configure -state normal -bg white
	.sgo.labels.y2axis configure -state normal -bg white
    set graphOptions(yTicksLength) $graphOptions(yFixedTicksLength)
    } else {
	.sgo.labels.yaxis configure -state disabled -bg grey85
	.sgo.labels.y2axis configure -state disabled -bg grey85
    set graphOptions(yTicksLength) $graphOptions(yInitialTicksLength)
    }
}

proc SetGraphOptionsDone {} {
    global graphOptions graphVectorList graphAxisList zoomStack

    # x-axis ticks rotation

    .glast axis configure x -rotate $graphOptions(xTicksRotation)

    # x-axis label

    if {[winfo exists .glast]} {
	.glast axis configure x -title $graphOptions(xAxisLabel)
    } else {
	if {[winfo exists .g1]} {
	    .g1 axis configure x -title $graphOption(xAxisLabel)
	}
    }

    # y-axis labels (y and y2)

    if {[winfo exists .glast]} {
	if {$graphOptions(plotStyle) == "single"} {
	    .glast yaxis configure -title $graphOptions(yAxisLabel)
	    .glast y2axis configure -title $graphOptions(y2AxisLabel)
	}
    }

    # a complete re-draw if plotStyle has changed

    if {$graphOptions(displayedPlotStyle) != $graphOptions(plotStyle)} {
	set graphOptions(displayedPlotStyle) $graphOptions(plotStyle)
	GetGraphDataCallback $graphVectorList $graphAxisList
	set zoomStack {}
    }

    destroy .sgo
}

##################################################################
#
#   Open a file
#
#      Discard current graphs, if any
#      Reinitialize necessary vectors
#      Read in data from new file
#
#################################################################

proc OpenFile {filename curdir pattern} {
    global graphOptions
    global column_count column_names column_indices graphList graphVectorList graphAxisList
    global zoomStack
    global V0

    if {$filename == ""} {
	return              ;# open operation was cancelled
    }

    set graphOptions(currentDirectory) $curdir
    set graphOptions(pattern) $pattern
    set graphOptions(fileName) [file tail $filename]

    # Discard all the current graphs

    foreach n $graphList {
	set nl [format "%slabel" $n]
	table forget $n
	table forget $nl
	destroy $n
	destroy $nl
    }
    if {[winfo exists .glast]} {
	destroy .glast
    }
    DefineDummyXAxisGraph
    table . .glast 3,1 -fill x
    table configure . r3 -resize none
    set graphList ""
    set graphVectorList ""
    set graphAxisList ""
    set column_count 0

    for {set i 0} {$i < 30} {incr i} {
	VecReinit $i
    }

    # Read in the new data file, create the vectors for graphing

    busy hold .
    update idletasks
    ParseStrip $filename [list $graphOptions(initialRead) $graphOptions(subsequentRead) $graphOptions(waitRead)]
    busy release .

    # Reinitiaize the x-axis graph (.glast); discard any stacked zoom data

    .glast element delete "e1"
    .glast element create "e1" -xdata V0 -ydata 0 -color white -symbol none -smooth step
    .glast xaxis configure -min $V0(min) -max $V0(max)
    set zoomStack {}

    # Use the file name (basename, not full path) as the initial title of the graph

    file stat $filename filestat
    set mtime $filestat(mtime)    ;# value of modification-time field, as integer

    set graphOptions(title) $graphOptions(fileName)
}
proc FirstReadLiveData {} {
    global graphOptions
    global column_count column_names column_indices graphList graphVectorList graphAxisList
    global zoomStack
    global V0

    # Discard all the current graphs

    foreach n $graphList {
	set nl [format "%slabel" $n]
	table forget $n
	table forget $nl
	destroy $n
	destroy $nl
    }
    if {[winfo exists .glast]} {
	destroy .glast
    }
    DefineDummyXAxisGraph
    table . .glast 3,1 -fill x
    table configure . r3 -resize none
    set graphList ""
    set graphVectorList ""
    set graphAxisList ""
    set column_count 0

    for {set i 0} {$i < 30} {incr i} {
	VecReinit $i
    }

    # Read in the new data file, create the vectors for graphing

    busy hold .
    update idletasks
    ParseStripLive
    busy release .

    # Reinitiaize the x-axis graph (.glast); discard any stacked zoom data

    .glast element delete "e1"
    .glast element create "e1" -xdata V0 -ydata 0 -color white -symbol none -smooth step
    .glast xaxis configure -min $V0(min) -max $V0(max)
    set zoomStack {}

    # Use the file name (basename, not full path) as the initial title of the graph

    #GetGraphDataCallback {	POWER_SIM POWER_CALIBRATED } {Left Left}
    #GetGraphDataCallback {POWER_DCACHE POWER_BRANCH POWER_INST_OTHER  POWER_IDLE } {Left Left Left Left}
    #GetGraphDataCallback {HV_CYCLES P0_CYCLES P1_CYCLES P2_CYCLES HV_L2_CACHE_MISS P0_L2_CACHE_MISS P1_L2_CACHE_MISS P2_L2_CACHE_MISS HV_SLB_MISS_DATA HV_UTLB_MISS_DATA P0_UTLB_MISS_DATA HV_SLB_MISS_DATA P0_SLB_MISS_DATA P1_SLB_MISS_DATA} {Left Left Left Left Left Left Left Left Left Left Left Left Left Left}
    GetGraphDataCallback {} {}
    set graphOptions(title) "Live! Data from Mambo"
}
proc SubsequentReadLiveData {} {
    global graphOptions
    global column_count column_names column_indices graphList graphVectorList graphAxisList

    # Read in the new data file, create the vectors for graphing
    busy hold .
    ParseStripLive
    update idletasks
    busy release .
}

#########################################################################
#
#  PrintCommand -- Invoke PsDialog to print the current graph
#
#########################################################################

proc PrintCommand {} {

    # Hack for now -- print .g1 if it exists, else print .glast

    if {[winfo exists .g1]} {
	PsDialog .g1
    } else {
	if {[winfo exists .glast]} {
	    PsDialog .glast
	}
    }
}

####################################################
#
#  If a file name was specified on the command line,
#  read it in now
#
####################################################

if {$argv != ""} {
    OpenFile [lindex $argv 0] $graphOptions(currentDirectory) \
	    $graphOptions(pattern)
}

set refreshDelayMS 1000

proc GraphRefresh {} {
	global refreshDelayMS

	# Read Live Stripstats Data
	SubsequentReadLiveData

	# Clear out any existing after jobs
	foreach i [after info] {
		after cancel $i
	}
	update

	after $refreshDelayMS { GraphRefresh }
}

FirstReadLiveData
GraphRefresh

#source $env(PROFILER_DIR)/prof.tcl

##############################################################
#
#  Cache Misses Box
#
##############################################################
#toplevel .caches
#CacheMiss_Init .caches

##############################################################
#
#  Process Tracking Box
#
##############################################################
#toplevel .procs
#ProcBox_Init .procs
