--- /dev/null
- BoolOption('STATS_BINNING', 'Bin statistics by CPU mode', have_mysql),
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Steve Reinhardt
+
+###################################################
+#
+# SCons top-level build description (SConstruct) file.
+#
+# While in this directory ('m5'), just type 'scons' to build the default
+# configuration (see below), or type 'scons build/<CONFIG>/<binary>'
+# to build some other configuration (e.g., 'build/ALPHA_FS/m5.opt' for
+# the optimized full-system version).
+#
+# You can build M5 in a different directory as long as there is a
+# 'build/<CONFIG>' somewhere along the target path. The build system
+# expdects that all configs under the same build directory are being
+# built for the same host system.
+#
+# Examples:
+# These two commands are equivalent. The '-u' option tells scons to
+# search up the directory tree for this SConstruct file.
+# % cd <path-to-src>/m5 ; scons build/ALPHA_FS/m5.debug
+# % cd <path-to-src>/m5/build/ALPHA_FS; scons -u m5.debug
+# These two commands are equivalent and demonstrate building in a
+# directory outside of the source tree. The '-C' option tells scons
+# to chdir to the specified directory to find this SConstruct file.
+# % cd <path-to-src>/m5 ; scons /local/foo/build/ALPHA_FS/m5.debug
+# % cd /local/foo/build/ALPHA_FS; scons -C <path-to-src>/m5 m5.debug
+#
+# You can use 'scons -H' to print scons options. If you're in this
+# 'm5' directory (or use -u or -C to tell scons where to find this
+# file), you can use 'scons -h' to print all the M5-specific build
+# options as well.
+#
+###################################################
+
+# Python library imports
+import sys
+import os
+
+# Check for recent-enough Python and SCons versions. If your system's
+# default installation of Python is not recent enough, you can use a
+# non-default installation of the Python interpreter by either (1)
+# rearranging your PATH so that scons finds the non-default 'python'
+# first or (2) explicitly invoking an alternative interpreter on the
+# scons script, e.g., "/usr/local/bin/python2.4 `which scons` [args]".
+EnsurePythonVersion(2,4)
+
+# Ironically, SCons 0.96 dies if you give EnsureSconsVersion a
+# 3-element version number.
+min_scons_version = (0,96,91)
+try:
+ EnsureSConsVersion(*min_scons_version)
+except:
+ print "Error checking current SCons version."
+ print "SCons", ".".join(map(str,min_scons_version)), "or greater required."
+ Exit(2)
+
+
+# The absolute path to the current directory (where this file lives).
+ROOT = Dir('.').abspath
+
+# Paths to the M5 and external source trees.
+SRCDIR = os.path.join(ROOT, 'src')
+
+# tell python where to find m5 python code
+sys.path.append(os.path.join(ROOT, 'src/python'))
+
+###################################################
+#
+# Figure out which configurations to set up based on the path(s) of
+# the target(s).
+#
+###################################################
+
+# Find default configuration & binary.
+Default(os.environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
+
+# Ask SCons which directory it was invoked from.
+launch_dir = GetLaunchDir()
+
+# Make targets relative to invocation directory
+abs_targets = map(lambda x: os.path.normpath(os.path.join(launch_dir, str(x))),
+ BUILD_TARGETS)
+
+# helper function: find last occurrence of element in list
+def rfind(l, elt, offs = -1):
+ for i in range(len(l)+offs, 0, -1):
+ if l[i] == elt:
+ return i
+ raise ValueError, "element not found"
+
+# Each target must have 'build' in the interior of the path; the
+# directory below this will determine the build parameters. For
+# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we
+# recognize that ALPHA_SE specifies the configuration because it
+# follow 'build' in the bulid path.
+
+# Generate a list of the unique build roots and configs that the
+# collected targets reference.
+build_paths = []
+build_root = None
+for t in abs_targets:
+ path_dirs = t.split('/')
+ try:
+ build_top = rfind(path_dirs, 'build', -2)
+ except:
+ print "Error: no non-leaf 'build' dir found on target path", t
+ Exit(1)
+ this_build_root = os.path.join('/',*path_dirs[:build_top+1])
+ if not build_root:
+ build_root = this_build_root
+ else:
+ if this_build_root != build_root:
+ print "Error: build targets not under same build root\n"\
+ " %s\n %s" % (build_root, this_build_root)
+ Exit(1)
+ build_path = os.path.join('/',*path_dirs[:build_top+2])
+ if build_path not in build_paths:
+ build_paths.append(build_path)
+
+###################################################
+#
+# Set up the default build environment. This environment is copied
+# and modified according to each selected configuration.
+#
+###################################################
+
+env = Environment(ENV = os.environ, # inherit user's environment vars
+ ROOT = ROOT,
+ SRCDIR = SRCDIR)
+
+env.SConsignFile("sconsign")
+
+# Default duplicate option is to use hard links, but this messes up
+# when you use emacs to edit a file in the target dir, as emacs moves
+# file to file~ then copies to file, breaking the link. Symbolic
+# (soft) links work better.
+env.SetOption('duplicate', 'soft-copy')
+
+# I waffle on this setting... it does avoid a few painful but
+# unnecessary builds, but it also seems to make trivial builds take
+# noticeably longer.
+if False:
+ env.TargetSignatures('content')
+
+# M5_PLY is used by isa_parser.py to find the PLY package.
+env.Append(ENV = { 'M5_PLY' : Dir('ext/ply') })
+
+# Set up default C++ compiler flags
+env.Append(CCFLAGS='-pipe')
+env.Append(CCFLAGS='-fno-strict-aliasing')
+env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
+if sys.platform == 'cygwin':
+ # cygwin has some header file issues...
+ env.Append(CCFLAGS=Split("-Wno-uninitialized"))
+env.Append(CPPPATH=[Dir('ext/dnet')])
+
+# Find Python include and library directories for embedding the
+# interpreter. For consistency, we will use the same Python
+# installation used to run scons (and thus this script). If you want
+# to link in an alternate version, see above for instructions on how
+# to invoke scons with a different copy of the Python interpreter.
+
+# Get brief Python version name (e.g., "python2.4") for locating
+# include & library files
+py_version_name = 'python' + sys.version[:3]
+
+# include path, e.g. /usr/local/include/python2.4
+env.Append(CPPPATH = os.path.join(sys.exec_prefix, 'include', py_version_name))
+env.Append(LIBS = py_version_name)
+# add library path too if it's not in the default place
+if sys.exec_prefix != '/usr':
+ env.Append(LIBPATH = os.path.join(sys.exec_prefix, 'lib'))
+
+# Set up SWIG flags & scanner
+
+env.Append(SWIGFLAGS=Split('-c++ -python -modern $_CPPINCFLAGS'))
+
+import SCons.Scanner
+
+swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
+
+swig_scanner = SCons.Scanner.ClassicCPP("SwigScan", ".i", "CPPPATH",
+ swig_inc_re)
+
+env.Append(SCANNERS = swig_scanner)
+
+# Other default libraries
+env.Append(LIBS=['z'])
+
+# Platform-specific configuration. Note again that we assume that all
+# builds under a given build root run on the same host platform.
+conf = Configure(env,
+ conf_dir = os.path.join(build_root, '.scons_config'),
+ log_file = os.path.join(build_root, 'scons_config.log'))
+
+# Check for <fenv.h> (C99 FP environment control)
+have_fenv = conf.CheckHeader('fenv.h', '<>')
+if not have_fenv:
+ print "Warning: Header file <fenv.h> not found."
+ print " This host has no IEEE FP rounding mode control."
+
+# Check for mysql.
+mysql_config = WhereIs('mysql_config')
+have_mysql = mysql_config != None
+
+# Check MySQL version.
+if have_mysql:
+ mysql_version = os.popen(mysql_config + ' --version').read()
+ mysql_version = mysql_version.split('.')
+ mysql_major = int(mysql_version[0])
+ mysql_minor = int(mysql_version[1])
+ # This version check is probably overly conservative, but it deals
+ # with the versions we have installed.
+ if mysql_major < 4 or (mysql_major == 4 and mysql_minor < 1):
+ print "Warning: MySQL v4.1 or newer required."
+ have_mysql = False
+
+# Set up mysql_config commands.
+if have_mysql:
+ mysql_config_include = mysql_config + ' --include'
+ if os.system(mysql_config_include + ' > /dev/null') != 0:
+ # older mysql_config versions don't support --include, use
+ # --cflags instead
+ mysql_config_include = mysql_config + ' --cflags | sed s/\\\'//g'
+ # This seems to work in all versions
+ mysql_config_libs = mysql_config + ' --libs'
+
+env = conf.Finish()
+
+# Define the universe of supported ISAs
+env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
+
+# Define the universe of supported CPU models
+env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
+ 'FullCPU', 'AlphaFullCPU',
+ 'OzoneSimpleCPU', 'OzoneCPU', 'CheckerCPU']
+
+# Sticky options get saved in the options file so they persist from
+# one invocation to the next (unless overridden, in which case the new
+# value becomes sticky).
+sticky_opts = Options(args=ARGUMENTS)
+sticky_opts.AddOptions(
+ EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']),
+ BoolOption('FULL_SYSTEM', 'Full-system support', False),
+ # There's a bug in scons 0.96.1 that causes ListOptions with list
+ # values (more than one value) not to be able to be restored from
+ # a saved option file. If this causes trouble then upgrade to
+ # scons 0.96.90 or later.
+ ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU',
+ env['ALL_CPU_LIST']),
+ BoolOption('ALPHA_TLASER',
+ 'Model Alpha TurboLaser platform (vs. Tsunami)', False),
+ BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
+ BoolOption('EFENCE', 'Link with Electric Fence malloc debugger',
+ False),
+ BoolOption('SS_COMPATIBLE_FP',
+ 'Make floating-point results compatible with SimpleScalar',
+ False),
+ BoolOption('USE_SSE2',
+ 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
+ False),
- 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
- 'STATS_BINNING']
+ BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
+ BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
+ ('CC', 'C compiler', os.environ.get('CC', env['CC'])),
+ ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
+ BoolOption('BATCH', 'Use batch pool for build and tests', False),
+ ('BATCH_CMD', 'Batch pool submission command name', 'qdo')
+ )
+
+# Non-sticky options only apply to the current build.
+nonsticky_opts = Options(args=ARGUMENTS)
+nonsticky_opts.AddOptions(
+ BoolOption('update_ref', 'Update test reference outputs', False)
+ )
+
+# These options get exported to #defines in config/*.hh (see m5/SConscript).
+env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
++ 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP']
+
+# Define a handy 'no-op' action
+def no_action(target, source, env):
+ return 0
+
+env.NoAction = Action(no_action, None)
+
+###################################################
+#
+# Define a SCons builder for configuration flag headers.
+#
+###################################################
+
+# This function generates a config header file that #defines the
+# option symbol to the current option setting (0 or 1). The source
+# operands are the name of the option and a Value node containing the
+# value of the option.
+def build_config_file(target, source, env):
+ (option, value) = [s.get_contents() for s in source]
+ f = file(str(target[0]), 'w')
+ print >> f, '#define', option, value
+ f.close()
+ return None
+
+# Generate the message to be printed when building the config file.
+def build_config_file_string(target, source, env):
+ (option, value) = [s.get_contents() for s in source]
+ return "Defining %s as %s in %s." % (option, value, target[0])
+
+# Combine the two functions into a scons Action object.
+config_action = Action(build_config_file, build_config_file_string)
+
+# The emitter munges the source & target node lists to reflect what
+# we're really doing.
+def config_emitter(target, source, env):
+ # extract option name from Builder arg
+ option = str(target[0])
+ # True target is config header file
+ target = os.path.join('config', option.lower() + '.hh')
+ # Force value to 0/1 even if it's a Python bool
+ val = int(eval(str(env[option])))
+ # Sources are option name & value (packaged in SCons Value nodes)
+ return ([target], [Value(option), Value(val)])
+
+config_builder = Builder(emitter = config_emitter, action = config_action)
+
+env.Append(BUILDERS = { 'ConfigFile' : config_builder })
+
+###################################################
+#
+# Define a SCons builder for copying files. This is used by the
+# Python zipfile code in src/python/SConscript, but is placed up here
+# since it's potentially more generally applicable.
+#
+###################################################
+
+copy_builder = Builder(action = Copy("$TARGET", "$SOURCE"))
+
+env.Append(BUILDERS = { 'CopyFile' : copy_builder })
+
+###################################################
+#
+# Define a simple SCons builder to concatenate files.
+#
+# Used to append the Python zip archive to the executable.
+#
+###################################################
+
+concat_builder = Builder(action = Action(['cat $SOURCES > $TARGET',
+ 'chmod +x $TARGET']))
+
+env.Append(BUILDERS = { 'Concat' : concat_builder })
+
+
+# base help text
+help_text = '''
+Usage: scons [scons options] [build options] [target(s)]
+
+'''
+
+# libelf build is shared across all configs in the build root.
+env.SConscript('ext/libelf/SConscript',
+ build_dir = os.path.join(build_root, 'libelf'),
+ exports = 'env')
+
+###################################################
+#
+# Define build environments for selected configurations.
+#
+###################################################
+
+# rename base env
+base_env = env
+
+for build_path in build_paths:
+ print "Building in", build_path
+ # build_dir is the tail component of build path, and is used to
+ # determine the build parameters (e.g., 'ALPHA_SE')
+ (build_root, build_dir) = os.path.split(build_path)
+ # Make a copy of the build-root environment to use for this config.
+ env = base_env.Copy()
+
+ # Set env options according to the build directory config.
+ sticky_opts.files = []
+ # Options for $BUILD_ROOT/$BUILD_DIR are stored in
+ # $BUILD_ROOT/options/$BUILD_DIR so you can nuke
+ # $BUILD_ROOT/$BUILD_DIR without losing your options settings.
+ current_opts_file = os.path.join(build_root, 'options', build_dir)
+ if os.path.isfile(current_opts_file):
+ sticky_opts.files.append(current_opts_file)
+ print "Using saved options file %s" % current_opts_file
+ else:
+ # Build dir-specific options file doesn't exist.
+
+ # Make sure the directory is there so we can create it later
+ opt_dir = os.path.dirname(current_opts_file)
+ if not os.path.isdir(opt_dir):
+ os.mkdir(opt_dir)
+
+ # Get default build options from source tree. Options are
+ # normally determined by name of $BUILD_DIR, but can be
+ # overriden by 'default=' arg on command line.
+ default_opts_file = os.path.join('build_opts',
+ ARGUMENTS.get('default', build_dir))
+ if os.path.isfile(default_opts_file):
+ sticky_opts.files.append(default_opts_file)
+ print "Options file %s not found,\n using defaults in %s" \
+ % (current_opts_file, default_opts_file)
+ else:
+ print "Error: cannot find options file %s or %s" \
+ % (current_opts_file, default_opts_file)
+ Exit(1)
+
+ # Apply current option settings to env
+ sticky_opts.Update(env)
+ nonsticky_opts.Update(env)
+
+ help_text += "Sticky options for %s:\n" % build_dir \
+ + sticky_opts.GenerateHelpText(env) \
+ + "\nNon-sticky options for %s:\n" % build_dir \
+ + nonsticky_opts.GenerateHelpText(env)
+
+ # Process option settings.
+
+ if not have_fenv and env['USE_FENV']:
+ print "Warning: <fenv.h> not available; " \
+ "forcing USE_FENV to False in", build_dir + "."
+ env['USE_FENV'] = False
+
+ if not env['USE_FENV']:
+ print "Warning: No IEEE FP rounding mode control in", build_dir + "."
+ print " FP results may deviate slightly from other platforms."
+
+ if env['EFENCE']:
+ env.Append(LIBS=['efence'])
+
+ if env['USE_MYSQL']:
+ if not have_mysql:
+ print "Warning: MySQL not available; " \
+ "forcing USE_MYSQL to False in", build_dir + "."
+ env['USE_MYSQL'] = False
+ else:
+ print "Compiling in", build_dir, "with MySQL support."
+ env.ParseConfig(mysql_config_libs)
+ env.ParseConfig(mysql_config_include)
+
+ # Save sticky option settings back to current options file
+ sticky_opts.Save(current_opts_file, env)
+
+ # Do this after we save setting back, or else we'll tack on an
+ # extra 'qdo' every time we run scons.
+ if env['BATCH']:
+ env['CC'] = env['BATCH_CMD'] + ' ' + env['CC']
+ env['CXX'] = env['BATCH_CMD'] + ' ' + env['CXX']
+
+ if env['USE_SSE2']:
+ env.Append(CCFLAGS='-msse2')
+
+ # The m5/SConscript file sets up the build rules in 'env' according
+ # to the configured options. It returns a list of environments,
+ # one for each variant build (debug, opt, etc.)
+ envList = SConscript('src/SConscript', build_dir = build_path,
+ exports = 'env')
+
+ # Set up the regression tests for each build.
+# for e in envList:
+# SConscript('m5-test/SConscript',
+# build_dir = os.path.join(build_dir, 'test', e.Label),
+# exports = { 'env' : e }, duplicate = False)
+
+Help(help_text)
+
+###################################################
+#
+# Let SCons do its thing. At this point SCons will use the defined
+# build environments to build the requested targets.
+#
+###################################################
+
--- /dev/null
- kern/kernel_binning.cc
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Steve Reinhardt
+
+import os
+import sys
+from os.path import isdir
+
+# This file defines how to build a particular configuration of M5
+# based on variable settings in the 'env' build environment.
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+
+base_sources = Split('''
+ base/circlebuf.cc
+ base/cprintf.cc
+ base/fast_alloc.cc
+ base/fifo_buffer.cc
+ base/hostinfo.cc
+ base/hybrid_pred.cc
+ base/inifile.cc
+ base/intmath.cc
+ base/match.cc
+ base/misc.cc
+ base/output.cc
+ base/pollevent.cc
+ base/range.cc
+ base/random.cc
+ base/sat_counter.cc
+ base/serializer.cc
+ base/socket.cc
+ base/statistics.cc
+ base/str.cc
+ base/time.cc
+ base/trace.cc
+ base/traceflags.cc
+ base/userinfo.cc
+ base/compression/lzss_compression.cc
+ base/loader/aout_object.cc
+ base/loader/ecoff_object.cc
+ base/loader/elf_object.cc
+ base/loader/object_file.cc
+ base/loader/symtab.cc
+ base/stats/events.cc
+ base/stats/statdb.cc
+ base/stats/visit.cc
+ base/stats/text.cc
+
+ cpu/activity.cc
+ cpu/base.cc
+ cpu/cpuevent.cc
+ cpu/exetrace.cc
+ cpu/op_class.cc
+ cpu/pc_event.cc
+ cpu/quiesce_event.cc
+ cpu/static_inst.cc
+ cpu/sampler/sampler.cc
+ cpu/simple_thread.cc
+ cpu/thread_state.cc
+
+ encumbered/cpu/full/fu_pool.cc
+
+ mem/bridge.cc
+ mem/bus.cc
+ mem/connector.cc
+ mem/mem_object.cc
+ mem/packet.cc
+ mem/physical.cc
+ mem/port.cc
+
+ sim/builder.cc
+ sim/configfile.cc
+ sim/debug.cc
+ sim/eventq.cc
+ sim/faults.cc
+ sim/main.cc
+ python/swig/main_wrap.cc
+ sim/param.cc
+ sim/profile.cc
+ sim/root.cc
+ sim/serialize.cc
+ sim/sim_events.cc
+ sim/sim_object.cc
+ sim/startup.cc
+ sim/stat_context.cc
+ sim/stat_control.cc
+ sim/system.cc
+ sim/trace_context.cc
+ ''')
+
+# Old FullCPU sources
+full_cpu_sources = Split('''
+ encumbered/cpu/full/bpred.cc
+ encumbered/cpu/full/commit.cc
+ encumbered/cpu/full/cpu.cc
+ encumbered/cpu/full/create_vector.cc
+ encumbered/cpu/full/cv_spec_state.cc
+ encumbered/cpu/full/dd_queue.cc
+ encumbered/cpu/full/dep_link.cc
+ encumbered/cpu/full/dispatch.cc
+ encumbered/cpu/full/dyn_inst.cc
+ encumbered/cpu/full/execute.cc
+ encumbered/cpu/full/fetch.cc
+ encumbered/cpu/full/floss_reasons.cc
+ encumbered/cpu/full/fu_pool.cc
+ encumbered/cpu/full/inst_fifo.cc
+ encumbered/cpu/full/instpipe.cc
+ encumbered/cpu/full/issue.cc
+ encumbered/cpu/full/ls_queue.cc
+ encumbered/cpu/full/machine_queue.cc
+ encumbered/cpu/full/pipetrace.cc
+ encumbered/cpu/full/readyq.cc
+ encumbered/cpu/full/reg_info.cc
+ encumbered/cpu/full/rob_station.cc
+ encumbered/cpu/full/spec_memory.cc
+ encumbered/cpu/full/spec_state.cc
+ encumbered/cpu/full/storebuffer.cc
+ encumbered/cpu/full/writeback.cc
+ encumbered/cpu/full/iq/iq_station.cc
+ encumbered/cpu/full/iq/iqueue.cc
+ encumbered/cpu/full/iq/segmented/chain_info.cc
+ encumbered/cpu/full/iq/segmented/chain_wire.cc
+ encumbered/cpu/full/iq/segmented/iq_seg.cc
+ encumbered/cpu/full/iq/segmented/iq_segmented.cc
+ encumbered/cpu/full/iq/segmented/seg_chain.cc
+ encumbered/cpu/full/iq/seznec/iq_seznec.cc
+ encumbered/cpu/full/iq/standard/iq_standard.cc
+ ''')
+
+trace_reader_sources = Split('''
+ cpu/trace/reader/mem_trace_reader.cc
+ cpu/trace/reader/ibm_reader.cc
+ cpu/trace/reader/itx_reader.cc
+ cpu/trace/reader/m5_reader.cc
+ cpu/trace/opt_cpu.cc
+ cpu/trace/trace_cpu.cc
+ ''')
+
+
+
+# MySql sources
+mysql_sources = Split('''
+ base/mysql.cc
+ base/stats/mysql.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ base/crc.cc
+ base/inet.cc
+ base/remote_gdb.cc
+
+ cpu/intr_control.cc
+ cpu/profile.cc
+
+ dev/alpha_console.cc
+ dev/baddev.cc
+ dev/disk_image.cc
+ dev/etherbus.cc
+ dev/etherdump.cc
+ dev/etherint.cc
+ dev/etherlink.cc
+ dev/etherpkt.cc
+ dev/ethertap.cc
+ dev/ide_ctrl.cc
+ dev/ide_disk.cc
+ dev/io_device.cc
+ dev/isa_fake.cc
+ dev/ns_gige.cc
+ dev/pciconfigall.cc
+ dev/pcidev.cc
+ dev/pcifake.cc
+ dev/pktfifo.cc
+ dev/platform.cc
+ dev/simconsole.cc
+ dev/simple_disk.cc
+ dev/sinic.cc
+ dev/tsunami.cc
+ dev/tsunami_cchip.cc
+ dev/tsunami_io.cc
+ dev/tsunami_fake.cc
+ dev/tsunami_pchip.cc
+
+ dev/uart.cc
+ dev/uart8250.cc
+
+ kern/kernel_stats.cc
+ kern/system_events.cc
+ kern/linux/events.cc
+ kern/linux/linux_syscalls.cc
+ kern/linux/printk.cc
+
+ mem/vport.cc
+
+ sim/pseudo_inst.cc
+ ''')
+
+
+if env['TARGET_ISA'] == 'alpha':
+ full_system_sources += Split('''
+ kern/tru64/dump_mbuf.cc
+ kern/tru64/printf.cc
+ kern/tru64/tru64_events.cc
+ kern/tru64/tru64_syscalls.cc
+ ''')
+
+# turbolaser encumbered sources
+turbolaser_sources = Split('''
+ encumbered/dev/dma.cc
+ encumbered/dev/etherdev.cc
+ encumbered/dev/scsi.cc
+ encumbered/dev/scsi_ctrl.cc
+ encumbered/dev/scsi_disk.cc
+ encumbered/dev/scsi_none.cc
+ encumbered/dev/tlaser_clock.cc
+ encumbered/dev/tlaser_ipi.cc
+ encumbered/dev/tlaser_mbox.cc
+ encumbered/dev/tlaser_mc146818.cc
+ encumbered/dev/tlaser_node.cc
+ encumbered/dev/tlaser_pcia.cc
+ encumbered/dev/tlaser_pcidev.cc
+ encumbered/dev/tlaser_serial.cc
+ encumbered/dev/turbolaser.cc
+ encumbered/dev/uart8530.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ mem/translating_port.cc
+ mem/page_table.cc
+ sim/process.cc
+ sim/syscall_emul.cc
+ ''')
+
+#if env['TARGET_ISA'] == 'alpha':
+# syscall_emulation_sources += Split('''
+# kern/tru64/tru64.cc
+# ''')
+
+alpha_eio_sources = Split('''
+ encumbered/eio/exolex.cc
+ encumbered/eio/libexo.cc
+ encumbered/eio/eio.cc
+ ''')
+
+if env['TARGET_ISA'] == 'ALPHA_ISA':
+ syscall_emulation_sources += alpha_eio_sources
+
+memtest_sources = Split('''
+ cpu/memtest/memtest.cc
+ ''')
+
+# Include file paths are rooted in this directory. SCons will
+# automatically expand '.' to refer to both the source directory and
+# the corresponding build directory to pick up generated include
+# files.
+env.Append(CPPPATH=Dir('.'))
+
+# Add a flag defining what THE_ISA should be for all compilation
+env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
+
+arch_sources = SConscript('arch/SConscript', exports = 'env')
+
+cpu_sources = SConscript('cpu/SConscript', exports = 'env')
+
+# This is outside of cpu/SConscript since the source directory isn't
+# underneath 'cpu'.
+if 'FullCPU' in env['CPU_MODELS']:
+ cpu_sources += full_cpu_sources
+
+# Set up complete list of sources based on configuration.
+sources = base_sources + arch_sources + cpu_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+ if env['ALPHA_TLASER']:
+ sources += turbolaser_sources
+else:
+ sources += syscall_emulation_sources
+
+if env['USE_MYSQL']:
+ sources += mysql_sources
+
+for opt in env.ExportOptions:
+ env.ConfigFile(opt)
+
+###################################################
+#
+# Special build rules.
+#
+###################################################
+
+# base/traceflags.{cc,hh} are generated from base/traceflags.py.
+# $TARGET.base will expand to "<build-dir>/base/traceflags".
+env.Command(Split('base/traceflags.hh base/traceflags.cc'),
+ 'base/traceflags.py',
+ 'python $SOURCE $TARGET.base')
+
+SConscript('python/SConscript', exports = ['env'])
+
+# This function adds the specified sources to the given build
+# environment, and returns a list of all the corresponding SCons
+# Object nodes (including an extra one for date.cc). We explicitly
+# add the Object nodes so we can set up special dependencies for
+# date.cc.
+def make_objs(sources, env):
+ objs = [env.Object(s) for s in sources]
+ # make date.cc depend on all other objects so it always gets
+ # recompiled whenever anything else does
+ date_obj = env.Object('base/date.cc')
+ env.Depends(date_obj, objs)
+ objs.append(date_obj)
+ return objs
+
+###################################################
+#
+# Define binaries. Each different build type (debug, opt, etc.) gets
+# a slightly different build environment.
+#
+###################################################
+
+# List of constructed environments to pass back to SConstruct
+envList = []
+
+# Function to create a new build environment as clone of current
+# environment 'env' with modified object suffix and optional stripped
+# binary. Additional keyword arguments are appended to corresponding
+# build environment vars.
+def makeEnv(label, objsfx, strip = False, **kwargs):
+ newEnv = env.Copy(OBJSUFFIX=objsfx)
+ newEnv.Label = label
+ newEnv.Append(**kwargs)
+ exe = 'm5.' + label # final executable
+ bin = exe + '.bin' # executable w/o appended Python zip archive
+ newEnv.Program(bin, make_objs(sources, newEnv))
+ if strip:
+ stripped_bin = bin + '.stripped'
+ newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET')
+ bin = stripped_bin
+ targets = newEnv.Concat(exe, [bin, 'python/m5py.zip'])
+ newEnv.M5Binary = targets[0]
+ envList.append(newEnv)
+
+# Debug binary
+makeEnv('debug', '.do',
+ CCFLAGS = Split('-g3 -gdwarf-2 -O0'),
+ CPPDEFINES = 'DEBUG')
+
+# Optimized binary
+makeEnv('opt', '.o',
+ CCFLAGS = Split('-g -O3'))
+
+# "Fast" binary
+makeEnv('fast', '.fo', strip = True,
+ CCFLAGS = Split('-O3'),
+ CPPDEFINES = 'NDEBUG')
+
+# Profiled binary
+makeEnv('prof', '.po',
+ CCFLAGS = Split('-O3 -g -pg'),
+ LINKFLAGS = '-pg')
+
+Return('envList')
--- /dev/null
- Param<bool> bin;
- VectorParam<string> binned_fns;
- Param<bool> bin_int;
-
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ben Nash
+ */
+
+/**
+ * @file
+ * Modifications for the FreeBSD kernel.
+ * Based on kern/linux/linux_system.cc.
+ *
+ */
+
+#include "arch/alpha/system.hh"
+#include "arch/alpha/freebsd/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/thread_context.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "arch/isa_traits.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "arch/vtophys.hh"
+
+#define TIMER_FREQUENCY 1193180
+
+using namespace std;
+using namespace AlphaISA;
+
+FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ /**
+ * Any time DELAY is called just skip the function.
+ * Shouldn't we actually emulate the delay?
+ */
+ skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
+ skipCalibrateClocks =
+ addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
+}
+
+
+FreebsdAlphaSystem::~FreebsdAlphaSystem()
+{
+ delete skipDelayEvent;
+ delete skipCalibrateClocks;
+}
+
+
+void
+FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc)
+{
+ Addr ppc_vaddr = 0;
+ Addr timer_vaddr = 0;
+
+ ppc_vaddr = (Addr)tc->readIntReg(ArgumentReg1);
+ timer_vaddr = (Addr)tc->readIntReg(ArgumentReg2);
+
+ virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency);
+ virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY);
+}
+
+
+void
+FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc)
+{
+ SkipFuncEvent::process(tc);
+ ((FreebsdAlphaSystem *)tc->getSystemPtr())->doCalibrateClocks(tc);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
++ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10)
+
+END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+CREATE_SIM_OBJECT(FreebsdAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ return new FreebsdAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("FreebsdAlphaSystem", FreebsdAlphaSystem)
+
--- /dev/null
-
- if (params()->bin_int) {
- intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
- if (!intStartEvent)
- panic("could not find symbol: sys_int_21\n");
-
- intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
- if (!intEndEvent)
- panic("could not find symbol: rti_to_kern\n");
-
- intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
- if (!intEndEvent2)
- panic("could not find symbol: rti_to_user\n");
-
- intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
- if (!intEndEvent3)
- panic("could not find symbol: do_softirq\n");
- }
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ * Lisa Hsu
+ * Nathan Binkert
+ * Steve Reinhardt
+ */
+
+/**
+ * @file
+ * This code loads the linux kernel, console, pal and patches certain
+ * functions. The symbol tables are loaded so that traces can show
+ * the executing function and we can skip functions. Various delay
+ * loops are skipped and their final values manually computed to speed
+ * up boot time.
+ */
+
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
+#include "arch/alpha/linux/system.hh"
+#include "arch/alpha/linux/threadinfo.hh"
+#include "arch/alpha/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/thread_context.hh"
+#include "cpu/base.hh"
+#include "dev/platform.hh"
+#include "kern/linux/printk.hh"
+#include "kern/linux/events.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+using namespace AlphaISA;
+using namespace Linux;
+
+LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+
+ /**
+ * The symbol swapper_pg_dir marks the beginning of the kernel and
+ * the location of bootloader passed arguments
+ */
+ if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
+ panic("Could not determine start location of kernel");
+ }
+
+ /**
+ * Since we aren't using a bootloader, we have to copy the
+ * kernel arguments directly into the kernel's memory.
+ */
+ virtPort.writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(),
+ params()->boot_osflags.length()+1);
+
+ /**
+ * find the address of the est_cycle_freq variable and insert it
+ * so we don't through the lengthly process of trying to
+ * calculated it by using the PIT, RTC, etc.
+ */
+ if (kernelSymtab->findAddress("est_cycle_freq", addr))
+ virtPort.write(addr, (uint64_t)(Clock::Frequency /
+ p->boot_cpu_frequency));
+
+
+ /**
+ * EV5 only supports 127 ASNs so we are going to tell the kernel that the
+ * paritiuclar EV6 we have only supports 127 asns.
+ * @todo At some point we should change ev5.hh and the palcode to support
+ * 255 ASNs.
+ */
+ if (kernelSymtab->findAddress("dp264_mv", addr))
+ virtPort.write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127));
+ else
+ panic("could not find dp264_mv\n");
+
+#ifndef NDEBUG
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+
+#if 0
+ kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
+ if (!kernelDieEvent)
+ panic("could not find kernel symbol \'die_if_kernel\'");
+#endif
+
+#endif
+
+ /**
+ * Any time ide_delay_50ms, calibarte_delay or
+ * determine_cpu_caches is called just skip the
+ * function. Currently determine_cpu_caches only is used put
+ * information in proc, however if that changes in the future we
+ * will have to fill in the cache size variables appropriately.
+ */
+
+ skipIdeDelay50msEvent =
+ addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
+ skipDelayLoopEvent =
+ addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
+ skipCacheProbeEvent =
+ addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
+ debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
+ idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
+
+ if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) {
+ printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
+ addr + sizeof(MachInst) * 6);
+ } else {
+ printThreadEvent = NULL;
+ }
- Param<bool> bin;
- VectorParam<string> binned_fns;
- Param<bool> bin_int;
-
+}
+
+LinuxAlphaSystem::~LinuxAlphaSystem()
+{
+#ifndef NDEBUG
+ delete kernelPanicEvent;
+#endif
+ delete skipIdeDelay50msEvent;
+ delete skipDelayLoopEvent;
+ delete skipCacheProbeEvent;
+ delete debugPrintkEvent;
+ delete idleStartEvent;
+ delete printThreadEvent;
+ delete intStartEvent;
+ delete intEndEvent;
+ delete intEndEvent2;
+}
+
+
+void
+LinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
+ Tick cpuFreq = tc->getCpuPtr()->frequency();
+ Tick intrFreq = platform->intrFrequency();
+ VirtualPort *vp;
+
+ vp = tc->getVirtPort();
+ vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988));
+ tc->delVirtPort(vp);
+ }
+}
+
+
+void
+LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
+{
+ SkipFuncEvent::process(tc);
+ // calculate and set loops_per_jiffy
+ ((LinuxAlphaSystem *)tc->getSystemPtr())->setDelayLoop(tc);
+}
+
+void
+LinuxAlphaSystem::PrintThreadInfo::process(ThreadContext *tc)
+{
+ Linux::ThreadInfo ti(tc);
+
+ DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
+ ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
++ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10)
+
+END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+CREATE_SIM_OBJECT(LinuxAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ return new LinuxAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("LinuxAlphaSystem", LinuxAlphaSystem)
+
--- /dev/null
- * This class contains linux specific system code (Loading, Events, Binning).
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ * Lisa Hsu
+ * Nathan Binkert
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__
+#define __ARCH_ALPHA_LINUX_SYSTEM_HH__
+
+class ThreadContext;
+
+class BreakPCEvent;
+class IdleStartEvent;
+
+#include "arch/alpha/system.hh"
+#include "kern/linux/events.hh"
+
+using namespace AlphaISA;
+using namespace Linux;
+
+/**
- /**
- * Event to bin Interrupts seperately from kernel code
- */
- InterruptStartEvent *intStartEvent;
-
- /**
- * Event to bin Interrupts seperately from kernel code
- */
- InterruptEndEvent *intEndEvent;
- InterruptEndEvent *intEndEvent2;
- InterruptEndEvent *intEndEvent3;
-
++ * This class contains linux specific system code (Loading, Events).
+ * It points to objects that are the system binaries to load and patches them
+ * appropriately to work in simulator.
+ */
+class LinuxAlphaSystem : public AlphaSystem
+{
+ private:
+ class SkipDelayLoopEvent : public SkipFuncEvent
+ {
+ public:
+ SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+ : SkipFuncEvent(q, desc, addr) {}
+ virtual void process(ThreadContext *tc);
+ };
+
+ class PrintThreadInfo : public PCEvent
+ {
+ public:
+ PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
+ : PCEvent(q, desc, addr) {}
+ virtual void process(ThreadContext *tc);
+ };
+
+
+ /**
+ * Addresses defining where the kernel bootloader places various
+ * elements. Details found in include/asm-alpha/system.h
+ */
+ Addr KernelStart; // Lookup the symbol swapper_pg_dir
+
+ public:
+ Addr InitStack() const { return KernelStart + 0x02000; }
+ Addr EmptyPGT() const { return KernelStart + 0x04000; }
+ Addr EmptyPGE() const { return KernelStart + 0x08000; }
+ Addr ZeroPGE() const { return KernelStart + 0x0A000; }
+ Addr StartAddr() const { return KernelStart + 0x10000; }
+
+ Addr Param() const { return ZeroPGE() + 0x0; }
+ Addr CommandLine() const { return Param() + 0x0; }
+ Addr InitrdStart() const { return Param() + 0x100; }
+ Addr InitrdSize() const { return Param() + 0x108; }
+ static const int CommandLineSize = 256;
+
+ private:
+#ifndef NDEBUG
+ /** Event to halt the simulator if the kernel calls panic() */
+ BreakPCEvent *kernelPanicEvent;
+
+ /** Event to halt the simulator if the kernel calls die_if_kernel */
+ BreakPCEvent *kernelDieEvent;
+#endif
+
+ /**
+ * Event to skip determine_cpu_caches() because we don't support
+ * the IPRs that the code can access to figure out cache sizes
+ */
+ SkipFuncEvent *skipCacheProbeEvent;
+
+ /** PC based event to skip the ide_delay_50ms() call */
+ SkipFuncEvent *skipIdeDelay50msEvent;
+
+ /**
+ * PC based event to skip the dprink() call and emulate its
+ * functionality
+ */
+ DebugPrintkEvent *debugPrintkEvent;
+
+ /**
+ * Skip calculate_delay_loop() rather than waiting for this to be
+ * calculated
+ */
+ SkipDelayLoopEvent *skipDelayLoopEvent;
+
+ /**
+ * Event to print information about thread switches if the trace flag
+ * Thread is set
+ */
+ PrintThreadInfo *printThreadEvent;
+
+ /** Grab the PCBB of the idle process when it starts */
+ IdleStartEvent *idleStartEvent;
+
+ public:
+ LinuxAlphaSystem(Params *p);
+ ~LinuxAlphaSystem();
+
+ void setDelayLoop(ThreadContext *tc);
+};
+
+#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__
--- /dev/null
- Param<bool> bin;
- VectorParam<std::string> binned_fns;
- Param<bool> bin_int;
-
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "arch/alpha/ev5.hh"
+#include "arch/alpha/system.hh"
+#include "arch/vtophys.hh"
+#include "base/remote_gdb.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "mem/physical.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+
+
+using namespace LittleEndianGuest;
+
+AlphaSystem::AlphaSystem(Params *p)
+ : System(p)
+{
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+
+
+ /**
+ * Load the pal, and console code into memory
+ */
+ // Load Console Code
+ console = createObjectFile(params()->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params()->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params()->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params()->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
+ console->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
+
+ // load symbols
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ Addr addr = 0;
+#ifndef NDEBUG
+ consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
+#endif
+
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ virtPort.writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(),
+ strlen(params()->boot_osflags.c_str()));
+ }
+
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("m5_rpb", addr)) {
+ uint64_t data;
+ data = htog(params()->system_type);
+ virtPort.write(addr+0x50, data);
+ data = htog(params()->system_rev);
+ virtPort.write(addr+0x58, data);
+ } else
+ panic("could not find hwrpb\n");
+
+}
+
+AlphaSystem::~AlphaSystem()
+{
+ delete consoleSymtab;
+ delete console;
+ delete pal;
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
+}
+
+/**
+ * This function fixes up addresses that are used to match PCs for
+ * hooking simulator events on to target function executions.
+ *
+ * Alpha binaries may have multiple global offset table (GOT)
+ * sections. A function that uses the GOT starts with a
+ * two-instruction prolog which sets the global pointer (gp == r29) to
+ * the appropriate GOT section. The proper gp value is calculated
+ * based on the function address, which must be passed by the caller
+ * in the procedure value register (pv aka t12 == r27). This sequence
+ * looks like the following:
+ *
+ * opcode Ra Rb offset
+ * ldah gp,X(pv) 09 29 27 X
+ * lda gp,Y(gp) 08 29 29 Y
+ *
+ * for some constant offsets X and Y. The catch is that the linker
+ * (or maybe even the compiler, I'm not sure) may recognize that the
+ * caller and callee are using the same GOT section, making this
+ * prolog redundant, and modify the call target to skip these
+ * instructions. If we check for execution of the first instruction
+ * of a function (the one the symbol points to) to detect when to skip
+ * it, we'll miss all these modified calls. It might work to
+ * unconditionally check for the third instruction, but not all
+ * functions have this prolog, and there's some chance that those
+ * first two instructions could have undesired consequences. So we do
+ * the Right Thing and pattern-match the first two instructions of the
+ * function to decide where to patch.
+ *
+ * Eventually this code should be moved into an ISA-specific file.
+ */
+Addr
+AlphaSystem::fixFuncEventAddr(Addr addr)
+{
+ // mask for just the opcode, Ra, and Rb fields (not the offset)
+ const uint32_t inst_mask = 0xffff0000;
+ // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
+ const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
+ // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
+ const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
+
+ uint32_t i1 = virtPort.read<uint32_t>(addr);
+ uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(AlphaISA::MachInst));
+
+ if ((i1 & inst_mask) == gp_ldah_pattern &&
+ (i2 & inst_mask) == gp_lda_pattern) {
+ Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst);
+ DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
+ return new_addr;
+ } else {
+ return addr;
+ }
+}
+
+
+void
+AlphaSystem::setAlphaAccess(Addr access)
+{
+ Addr addr = 0;
+ if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
+ virtPort.write(addr, htog(EV5::Phys2K0Seg(access)));
+ } else
+ panic("could not find m5AlphaAccess\n");
+}
+
+bool
+AlphaSystem::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
+
+void
+AlphaSystem::serialize(std::ostream &os)
+{
+ System::serialize(os);
+ consoleSymtab->serialize("console_symtab", os);
+ palSymtab->serialize("pal_symtab", os);
+}
+
+
+void
+AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion)
+{
+ System::unserialize(cp,section);
+ consoleSymtab->unserialize("console_symtab", cp, section);
+ palSymtab->unserialize("pal_symtab", cp, section);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<std::string> kernel;
+ Param<std::string> console;
+ Param<std::string> pal;
+
+ Param<std::string> boot_osflags;
+ Param<std::string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
++ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+CREATE_SIM_OBJECT(AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ return new AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem)
+
+
--- /dev/null
- Param<bool> bin;
- VectorParam<string> binned_fns;
-
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ * Lisa Hsu
+ */
+
+#include "arch/alpha/tru64/system.hh"
+#include "arch/isa_traits.hh"
+#include "arch/vtophys.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+#include "kern/tru64/tru64_events.hh"
+#include "kern/system_events.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("enable_async_printf", addr)) {
+ virtPort.write(addr, (uint32_t)0);
+ }
+
+#ifdef DEBUG
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+#endif
+
+ badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
+ if (!badaddrEvent)
+ panic("could not find kernel symbol \'badaddr\'");
+
+ skipPowerStateEvent =
+ addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
+ skipScavengeBootEvent =
+ addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
+
+#if TRACING_ON
+ printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
+ debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
+ debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
+ dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
+#endif
+}
+
+Tru64AlphaSystem::~Tru64AlphaSystem()
+{
+#ifdef DEBUG
+ delete kernelPanicEvent;
+#endif
+ delete badaddrEvent;
+ delete skipPowerStateEvent;
+ delete skipScavengeBootEvent;
+#if TRACING_ON
+ delete printfEvent;
+ delete debugPrintfEvent;
+ delete debugPrintfrEvent;
+ delete dumpMbufEvent;
+#endif
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned")
+END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 12),
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = false;
++ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1)
+
+END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+CREATE_SIM_OBJECT(Tru64AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+
+ return new Tru64AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("Tru64AlphaSystem", Tru64AlphaSystem)
--- /dev/null
- #include "config/stats_binning.hh"
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <iomanip>
+#include <fstream>
+#include <list>
+#include <map>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/hostinfo.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "base/trace.hh"
+#include "base/stats/statdb.hh"
- bool
- FormulaBase::binned() const
- {
- return root && root->binned();
- }
-
+
+using namespace std;
+
+namespace Stats {
+
+StatData *
+DataAccess::find() const
+{
+ return Database::find(const_cast<void *>((const void *)this));
+}
+
+const StatData *
+getStatData(const void *stat)
+{
+ return Database::find(const_cast<void *>(stat));
+}
+
+void
+DataAccess::map(StatData *data)
+{
+ Database::regStat(this, data);
+}
+
+StatData *
+DataAccess::statData()
+{
+ StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+const StatData *
+DataAccess::statData() const
+{
+ const StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+void
+DataAccess::setInit()
+{
+ statData()->flags |= init;
+}
+
+void
+DataAccess::setPrint()
+{
+ Database::regPrint(this);
+}
+
+StatData::StatData()
+ : flags(none), precision(-1), prereq(0)
+{
+ static int count = 0;
+ id = count++;
+}
+
+StatData::~StatData()
+{
+}
+
+bool
+StatData::less(StatData *stat1, StatData *stat2)
+{
+ const string &name1 = stat1->name;
+ const string &name2 = stat2->name;
+
+ vector<string> v1;
+ vector<string> v2;
+
+ tokenize(v1, name1, '.');
+ tokenize(v2, name2, '.');
+
+ int last = min(v1.size(), v2.size()) - 1;
+ for (int i = 0; i < last; ++i)
+ if (v1[i] != v2[i])
+ return v1[i] < v2[i];
+
+ // Special compare for last element.
+ if (v1[last] == v2[last])
+ return v1.size() < v2.size();
+ else
+ return v1[last] < v2[last];
+
+ return false;
+}
+
+bool
+StatData::baseCheck() const
+{
+ if (!(flags & init)) {
+#ifdef DEBUG
+ cprintf("this is stat number %d\n", id);
+#endif
+ panic("Not all stats have been initialized");
+ return false;
+ }
+
+ if ((flags & print) && name.empty()) {
+ panic("all printable stats must be named");
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+FormulaBase::result(VResult &vec) const
+{
+ if (root)
+ vec = root->result();
+}
+
+Result
+FormulaBase::total() const
+{
+ return root ? root->total() : 0.0;
+}
+
+size_t
+FormulaBase::size() const
+{
+ if (!root)
+ return 0;
+ else
+ return root->size();
+}
+
- MainBin::MainBin(const string &name)
- : _name(name), mem(NULL), memsize(-1)
- {
- Database::regBin(this, name);
- }
-
- MainBin::~MainBin()
- {
- if (mem)
- delete [] mem;
- }
-
- char *
- MainBin::memory(off_t off)
- {
- if (memsize == -1)
- memsize = ceilPow2((size_t) offset());
-
- if (!mem) {
- mem = new char[memsize];
- memset(mem, 0, memsize);
- }
-
- assert(offset() <= size());
- return mem + off;
- }
-
+void
+FormulaBase::reset()
+{
+}
+
+bool
+FormulaBase::zero() const
+{
+ VResult vec;
+ result(vec);
+ for (int i = 0; i < vec.size(); ++i)
+ if (vec[i] != 0.0)
+ return false;
+ return true;
+}
+
+void
+FormulaBase::update(StatData *)
+{
+}
+
+string
+FormulaBase::str() const
+{
+ return root ? root->str() : "";
+}
+
+Formula::Formula()
+{
+ setInit();
+}
+
+Formula::Formula(Temp r)
+{
+ root = r;
+ assert(size());
+}
+
+const Formula &
+Formula::operator=(Temp r)
+{
+ assert(!root && "Can't change formulas");
+ root = r;
+ assert(size());
+ return *this;
+}
+
+const Formula &
+Formula::operator+=(Temp r)
+{
+ if (root)
+ root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
+ else
+ root = r;
+ assert(size());
+ return *this;
+}
+
- #if STATS_BINNING
- if (MainBin::curBin() == NULL) {
- static MainBin mainBin("main bin");
- mainBin.activate();
- }
- #endif
-
+void
+check()
+{
+ typedef Database::stat_list_t::iterator iter_t;
+
+ iter_t i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ assert(data);
+ if (!data->check() || !data->baseCheck())
+ panic("stat check failed for %s\n", data->name);
+ }
+
+ int j = 0;
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (!(data->flags & print))
+ data->name = "__Stat" + to_string(j++);
+ }
+
+ Database::stats().sort(StatData::less);
+
- // reset non-binned stats
+ if (i == end)
+ return;
+
+ iter_t last = i;
+ ++i;
+
+ for (i = Database::stats().begin(); i != end; ++i) {
+ if ((*i)->name == (*last)->name)
+ panic("same name used twice! name=%s\n", (*i)->name);
+
+ last = i;
+ }
+}
+
+CallbackQueue resetQueue;
+
+void
+reset()
+{
- if (!data->binned())
- data->reset();
+ Database::stat_list_t::iterator i = Database::stats().begin();
+ Database::stat_list_t::iterator end = Database::stats().end();
+ while (i != end) {
+ StatData *data = *i;
- // save the bin so we can go back to where we were
- MainBin *orig = MainBin::curBin();
-
- // reset binned stats
- Database::bin_list_t::iterator bi = Database::bins().begin();
- Database::bin_list_t::iterator be = Database::bins().end();
- while (bi != be) {
- MainBin *bin = *bi;
- bin->activate();
-
- i = Database::stats().begin();
- while (i != end) {
- StatData *data = *i;
- if (data->binned())
- data->reset();
- ++i;
- }
- ++bi;
- }
-
- // restore bin
- MainBin::curBin() = orig;
-
++ data->reset();
+ ++i;
+ }
+
+ resetQueue.process();
+}
+
+void
+registerResetCallback(Callback *cb)
+{
+ resetQueue.add(cb);
+}
+
+/* namespace Stats */ }
--- /dev/null
- #include "base/stats/bin.hh"
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ * Erik Hallnor
+ */
+
+/** @file
+ * Declaration of Statistics objects.
+ */
+
+/**
+* @todo
+*
+* Generalized N-dimensinal vector
+* documentation
+* key stats
+* interval stats
+* -- these both can use the same function that prints out a
+* specific set of stats
+* VectorStandardDeviation totals
+* Document Namespaces
+*/
+#ifndef __BASE_STATISTICS_HH__
+#define __BASE_STATISTICS_HH__
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/cprintf.hh"
+#include "base/intmath.hh"
+#include "base/refcnt.hh"
+#include "base/str.hh"
- #include "config/stats_binning.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/visit.hh"
+#include "base/stats/types.hh"
- /**
- * @return true if the stat is binned.
- */
- virtual bool binned() const = 0;
-
+#include "sim/host.hh"
+
+class Callback;
+
+/** The current simulated cycle. */
+extern Tick curTick;
+
+/* A namespace for all of the Statistics */
+namespace Stats {
+
+/* Contains the statistic implementation details */
+//////////////////////////////////////////////////////////////////////
+//
+// Statistics Framework Base classes
+//
+//////////////////////////////////////////////////////////////////////
+struct StatData
+{
+ /** The name of the stat. */
+ std::string name;
+ /** The description of the stat. */
+ std::string desc;
+ /** The formatting flags. */
+ StatFlags flags;
+ /** The display precision. */
+ int precision;
+ /** A pointer to a prerequisite Stat. */
+ const StatData *prereq;
+ /**
+ * A unique stat ID for each stat in the simulator.
+ * Can be used externally for lookups as well as for debugging.
+ */
+ int id;
+
+ StatData();
+ virtual ~StatData();
+
- virtual bool binned() const { return s.binned(); }
+ /**
+ * Reset the corresponding stat to the default state.
+ */
+ virtual void reset() = 0;
+
+ /**
+ * @return true if this stat has a value and satisfies its
+ * requirement as a prereq
+ */
+ virtual bool zero() const = 0;
+
+ /**
+ * Check that this stat has been set up properly and is ready for
+ * use
+ * @return true for success
+ */
+ virtual bool check() const = 0;
+ bool baseCheck() const;
+
+ /**
+ * Visitor entry for outputing statistics data
+ */
+ virtual void visit(Visit &visitor) = 0;
+
+ /**
+ * Checks if the first stat's name is alphabetically less than the second.
+ * This function breaks names up at periods and considers each subname
+ * separately.
+ * @param stat1 The first stat.
+ * @param stat2 The second stat.
+ * @return stat1's name is alphabetically before stat2's
+ */
+ static bool less(StatData *stat1, StatData *stat2);
+};
+
+class ScalarData : public StatData
+{
+ public:
+ virtual Counter value() const = 0;
+ virtual Result result() const = 0;
+ virtual Result total() const = 0;
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
+};
+
+template <class Stat>
+class ScalarStatData : public ScalarData
+{
+ protected:
+ Stat &s;
+
+ public:
+ ScalarStatData(Stat &stat) : s(stat) {}
+
- virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual Counter value() const { return s.value(); }
+ virtual Result result() const { return s.result(); }
+ virtual Result total() const { return s.total(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+};
+
+struct VectorData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ virtual size_t size() const = 0;
+ virtual const VCounter &value() const = 0;
+ virtual const VResult &result() const = 0;
+ virtual Result total() const = 0;
+ void update()
+ {
+ if (!subnames.empty()) {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+ }
+};
+
+template <class Stat>
+class VectorStatData : public VectorData
+{
+ protected:
+ Stat &s;
+ mutable VCounter cvec;
+ mutable VResult rvec;
+
+ public:
+ VectorStatData(Stat &stat) : s(stat) {}
+
- virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual VCounter &value() const
+ {
+ s.value(cvec);
+ return cvec;
+ }
+ virtual const VResult &result() const
+ {
+ s.result(rvec);
+ return rvec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct DistDataData
+{
+ Counter min_val;
+ Counter max_val;
+ Counter underflow;
+ Counter overflow;
+ VCounter cvec;
+ Counter sum;
+ Counter squares;
+ Counter samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+};
+
+struct DistData : public StatData
+{
+ /** Local storage for the entry values, used for printing. */
+ DistDataData data;
+};
+
+template <class Stat>
+class DistStatData : public DistData
+{
+ protected:
+ Stat &s;
+
+ public:
+ DistStatData(Stat &stat) : s(stat) {}
+
- typedef typename Stat::bin_t bin_t;
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct VectorDistData : public StatData
+{
+ std::vector<DistDataData> data;
+
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VResult rvec;
+
+ virtual size_t size() const = 0;
+ void update()
+ {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+};
+
+template <class Stat>
+class VectorDistStatData : public VectorDistData
+{
+ protected:
+ Stat &s;
- virtual bool binned() const { return bin_t::binned; }
+
+ public:
+ VectorDistStatData(Stat &stat) : s(stat) {}
+
- typedef typename Stat::bin_t bin_t;
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual size_t size() const { return s.size(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct Vector2dData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ std::vector<std::string> subnames;
+ std::vector<std::string> subdescs;
+ std::vector<std::string> y_subnames;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VCounter cvec;
+ mutable int x;
+ mutable int y;
+
+ void update()
+ {
+ if (subnames.size() < x)
+ subnames.resize(x);
+ }
+};
+
+template <class Stat>
+class Vector2dStatData : public Vector2dData
+{
+ protected:
+ Stat &s;
- virtual bool binned() const { return bin_t::binned; }
+
+ public:
+ Vector2dStatData(Stat &stat) : s(stat) {}
+
-
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
- * @todo add lateny to the stat and fix binning.
+class DataAccess
+{
+ protected:
+ StatData *find() const;
+ void map(StatData *data);
+
+ StatData *statData();
+ const StatData *statData() const;
+
+ void setInit();
+ void setPrint();
+};
+
+template <class Parent, class Child, template <class> class Data>
+class Wrap : public Child
+{
+ protected:
+ Parent &self() { return *reinterpret_cast<Parent *>(this); }
+
+ protected:
+ Data<Child> *statData()
+ {
+ StatData *__data = DataAccess::statData();
+ Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ public:
+ const Data<Child> *statData() const
+ {
+ const StatData *__data = DataAccess::statData();
+ const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ protected:
+ /**
+ * Copy constructor, copies are not allowed.
+ */
+ Wrap(const Wrap &stat);
+ /**
+ * Can't copy stats.
+ */
+ void operator=(const Wrap &);
+
+ public:
+ Wrap()
+ {
+ map(new Data<Child>(*this));
+ }
+
+ /**
+ * Set the name and marks this stat to print at the end of simulation.
+ * @param name The new name.
+ * @return A reference to this stat.
+ */
+ Parent &name(const std::string &_name)
+ {
+ Data<Child> *data = this->statData();
+ data->name = _name;
+ this->setPrint();
+ return this->self();
+ }
+
+ /**
+ * Set the description and marks this stat to print at the end of
+ * simulation.
+ * @param desc The new description.
+ * @return A reference to this stat.
+ */
+ Parent &desc(const std::string &_desc)
+ {
+ this->statData()->desc = _desc;
+ return this->self();
+ }
+
+ /**
+ * Set the precision and marks this stat to print at the end of simulation.
+ * @param p The new precision
+ * @return A reference to this stat.
+ */
+ Parent &precision(int _precision)
+ {
+ this->statData()->precision = _precision;
+ return this->self();
+ }
+
+ /**
+ * Set the flags and marks this stat to print at the end of simulation.
+ * @param f The new flags.
+ * @return A reference to this stat.
+ */
+ Parent &flags(StatFlags _flags)
+ {
+ this->statData()->flags |= _flags;
+ return this->self();
+ }
+
+ /**
+ * Set the prerequisite stat and marks this stat to print at the end of
+ * simulation.
+ * @param prereq The prerequisite stat.
+ * @return A reference to this stat.
+ */
+ template <class Stat>
+ Parent &prereq(const Stat &prereq)
+ {
+ this->statData()->prereq = prereq.statData();
+ return this->self();
+ }
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec : public Wrap<Parent, Child, Data>
+{
+ public:
+ // The following functions are specific to vectors. If you use them
+ // in a non vector context, you will get a nice compiler error!
+
+ /**
+ * Set the subfield name for the given index, and marks this stat to print
+ * at the end of simulation.
+ * @param index The subfield index.
+ * @param name The new name of the subfield.
+ * @return A reference to this stat.
+ */
+ Parent &subname(int index, const std::string &name)
+ {
+ std::vector<std::string> &subn = this->statData()->subnames;
+ if (subn.size() <= index)
+ subn.resize(index + 1);
+ subn[index] = name;
+ return this->self();
+ }
+
+ /**
+ * Set the subfield description for the given index and marks this stat to
+ * print at the end of simulation.
+ * @param index The subfield index.
+ * @param desc The new description of the subfield
+ * @return A reference to this stat.
+ */
+ Parent &subdesc(int index, const std::string &desc)
+ {
+ std::vector<std::string> &subd = this->statData()->subdescs;
+ if (subd.size() <= index)
+ subd.resize(index + 1);
+ subd[index] = desc;
+
+ return this->self();
+ }
+
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec2d : public WrapVec<Parent, Child, Data>
+{
+ public:
+ /**
+ * @warning This makes the assumption that if you're gonna subnames a 2d
+ * vector, you're subnaming across all y
+ */
+ Parent &ysubnames(const char **names)
+ {
+ Data<Child> *data = this->statData();
+ data->y_subnames.resize(this->y);
+ for (int i = 0; i < this->y; ++i)
+ data->y_subnames[i] = names[i];
+ return this->self();
+ }
+ Parent &ysubname(int index, const std::string subname)
+ {
+ Data<Child> *data = this->statData();
+ assert(index < this->y);
+ data->y_subnames.resize(this->y);
+ data->y_subnames[index] = subname.c_str();
+ return this->self();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Simple Statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a simple scalar stat.
+ */
+struct StatStor
+{
+ public:
+ /** The paramaters for this storage type, none for a scalar. */
+ struct Params { };
+
+ private:
+ /** The statistic value. */
+ Counter data;
+
+ public:
+ /**
+ * Builds this storage element and calls the base constructor of the
+ * datatype.
+ */
+ StatStor(const Params &) : data(Counter()) {}
+
+ /**
+ * The the stat to the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void set(Counter val, const Params &p) { data = val; }
+ /**
+ * Increment the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void inc(Counter val, const Params &p) { data += val; }
+ /**
+ * Decrement the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void dec(Counter val, const Params &p) { data -= val; }
+ /**
+ * Return the value of this stat as its base type.
+ * @param p The params of this storage type.
+ * @return The value of this stat.
+ */
+ Counter value(const Params &p) const { return data; }
+ /**
+ * Return the value of this stat as a result type.
+ * @param p The parameters of this storage type.
+ * @return The value of this stat.
+ */
+ Result result(const Params &p) const { return (Result)data; }
+ /**
+ * Reset stat value to default
+ */
+ void reset() { data = Counter(); }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return data == Counter(); }
+};
+
+/**
+ * Templatized storage and interface to a per-cycle average stat. This keeps
+ * a current count and updates a total (count * cycles) when this count
+ * changes. This allows the quick calculation of a per cycle count of the item
+ * being watched. This is good for keeping track of residencies in structures
+ * among other things.
- struct Params
- {
- /**
- * The current count. We stash this here because the current
- * value is not a binned value.
- */
- Counter current;
- };
+ */
+struct AvgStor
+{
+ public:
+ /** The paramaters for this storage type */
- AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
++ struct Params { };
+
+ private:
++ /** The current count. */
++ Counter current;
+ /** The total count for all cycles. */
+ mutable Result total;
+ /** The cycle that current last changed. */
+ mutable Tick last;
+
+ public:
+ /**
+ * Build and initializes this stat storage.
+ */
- total += p.current * (curTick - last);
++ AvgStor(Params &p) : current(0), total(0), last(0) { }
+
+ /**
+ * Set the current count to the one provided, update the total and last
+ * set values.
+ * @param val The new count.
+ * @param p The parameters for this storage.
+ */
+ void set(Counter val, Params &p) {
- p.current = val;
++ total += current * (curTick - last);
+ last = curTick;
- void inc(Counter val, Params &p) { set(p.current + val, p); }
++ current = val;
+ }
+
+ /**
+ * Increment the current count by the provided value, calls set.
+ * @param val The amount to increment.
+ * @param p The parameters for this storage.
+ */
- void dec(Counter val, Params &p) { set(p.current - val, p); }
++ void inc(Counter val, Params &p) { set(current + val, p); }
+
+ /**
+ * Deccrement the current count by the provided value, calls set.
+ * @param val The amount to decrement.
+ * @param p The parameters for this storage.
+ */
- Counter value(const Params &p) const { return p.current; }
++ void dec(Counter val, Params &p) { set(current - val, p); }
+
+ /**
+ * Return the current count.
+ * @param p The parameters for this storage.
+ * @return The current count.
+ */
- total += p.current * (curTick - last);
++ Counter value(const Params &p) const { return current; }
+
+ /**
+ * Return the current average.
+ * @param p The parameters for this storage.
+ * @return The current average.
+ */
+ Result result(const Params &p) const
+ {
- return (Result)(total + p.current) / (Result)(curTick + 1);
++ total += current * (curTick - last);
+ last = curTick;
- * Storage template. The storage for this stat is held within the Bin class.
- * This allows for breaking down statistics across multiple bins easily.
++ return (Result)(total + current) / (Result)(curTick + 1);
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ total = 0;
+ last = curTick;
+ }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return total == 0.0; }
+};
+
+/**
+ * Implementation of a scalar stat. The type of stat is determined by the
- template <class Storage, class Bin>
++ * Storage template.
+ */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template Bin<Storage> bin_t;
++template <class Stor>
+class ScalarBase : public DataAccess
+{
+ public:
++ typedef Stor Storage;
++
+ /** Define the params of the storage class. */
- /** The bin of this stat. */
- bin_t bin;
++ typedef typename Storage::Params Params;
+
+ protected:
- params_t params;
++ /** The storage of this stat. */
++ char storage[sizeof(Storage)];
++
+ /** The parameters for this stat. */
- * Retrieve the storage from the bin.
- * @return The storage object for this stat.
++ Params params;
+
+ protected:
+ /**
- Storage *data() { return bin.data(params); }
++ * Retrieve the storage.
++ * @param index The vector index to access.
++ * @return The storage object at the given index.
+ */
- * Retrieve a const pointer to the storage from the bin.
- * @return A const pointer to the storage object for this stat.
++ Storage *
++ data()
++ {
++ return reinterpret_cast<Storage *>(storage);
++ }
++
+ /**
- const Storage *data() const
++ * Retrieve a const pointer to the storage.
++ * for the given index.
++ * @param index The vector index to access.
++ * @return A const pointer to the storage object at the given index.
+ */
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(¶ms);
- return _bin->data(*_params);
++ const Storage *
++ data() const
+ {
- {
- bin.init(params);
- }
++ return reinterpret_cast<const Storage *>(storage);
++ }
++
++ void
++ doInit()
++ {
++ new (storage) Storage(params);
++ setInit();
+ }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
+ Counter value() const { return data()->value(params); }
+
+ public:
+ /**
+ * Create and initialize this stat, register it with the database.
+ */
+ ScalarBase()
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
++ { }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
+ void operator++() { data()->inc(1, params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
+ void operator--() { data()->dec(1, params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { data()->set(v, params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
+ void operator+=(const U &v) { data()->inc(v, params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
+ void operator-=(const U &v) { data()->dec(v, params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
- bool check() const { return bin.initialized(); }
+
- void reset() { bin.reset(); }
++ bool check() const { return true; }
+
+ /**
+ * Reset stat value to default
+ */
- virtual bool binned() const { return false; }
++ void reset() { data()->reset(); }
+
+ Counter value() { return data()->value(params); }
+
+ Result result() { return data()->result(params); }
+
+ Result total() { return result(); }
+
+ bool zero() { return result() == 0.0; }
+
+};
+
+class ProxyData : public ScalarData
+{
+ public:
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
- bool binned() const { return proxy->binned(); }
+ virtual std::string str() const { return to_string(value()); }
+ virtual size_t size() const { return 1; }
+ virtual bool zero() const { return value() == 0; }
+ virtual bool check() const { return true; }
+ virtual void reset() { }
+};
+
+template <class T>
+class ValueProxy : public ProxyData
+{
+ private:
+ T *scalar;
+
+ public:
+ ValueProxy(T &val) : scalar(&val) {}
+ virtual Counter value() const { return *scalar; }
+ virtual Result result() const { return *scalar; }
+ virtual Result total() const { return *scalar; }
+};
+
+template <class T>
+class FunctorProxy : public ProxyData
+{
+ private:
+ T *functor;
+
+ public:
+ FunctorProxy(T &func) : functor(&func) {}
+ virtual Counter value() const { return (*functor)(); }
+ virtual Result result() const { return (*functor)(); }
+ virtual Result total() const { return (*functor)(); }
+};
+
+class ValueBase : public DataAccess
+{
+ private:
+ ProxyData *proxy;
+
+ public:
+ ValueBase() : proxy(NULL) { }
+ ~ValueBase() { if (proxy) delete proxy; }
+
+ template <class T>
+ void scalar(T &value)
+ {
+ proxy = new ValueProxy<T>(value);
+ setInit();
+ }
+
+ template <class T>
+ void functor(T &func)
+ {
+ proxy = new FunctorProxy<T>(func);
+ setInit();
+ }
+
+ Counter value() { return proxy->value(); }
+ Result result() const { return proxy->result(); }
+ Result total() const { return proxy->total(); };
+ size_t size() const { return proxy->size(); }
+
- template <class Storage, class Bin>
- class ScalarProxy;
-
- /**
- * Implementation of a vector of stats. The type of stat is determined by the
- * Storage class. @sa ScalarBase
- */
- template <class Storage, class Bin>
- class VectorBase : public DataAccess
- {
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- protected:
- /** The bin of this stat. */
- bin_t bin;
- /** The parameters for this stat. */
- params_t params;
-
- protected:
- /**
- * Retrieve the storage from the bin for the given index.
- * @param index The vector index to access.
- * @return The storage object at the given index.
- */
- Storage *data(int index) { return bin.data(index, params); }
- /**
- * Retrieve a const pointer to the storage from the bin
- * for the given index.
- * @param index The vector index to access.
- * @return A const pointer to the storage object at the given index.
- */
- const Storage *data(int index) const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(¶ms);
- return _bin->data(index, *_params);
- }
-
- public:
- void value(VCounter &vec) const
- {
- vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->value(params);
- }
-
- /**
- * Copy the values to a local vector and return a reference to it.
- * @return A reference to a vector of the stat values.
- */
- void result(VResult &vec) const
- {
- vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->result(params);
- }
-
- /**
- * @return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
-
- /**
- * Return a total of all entries in this vector.
- * @return The total of all vector entries.
- */
- Result total() const {
- Result total = 0.0;
- for (int i = 0; i < size(); ++i)
- total += data(i)->result(params);
- return total;
- }
-
- /**
- * @return the number of elements in this vector.
- */
- size_t size() const { return bin.size(); }
-
- bool zero() const
- {
- for (int i = 0; i < size(); ++i)
- if (data(i)->zero())
- return true;
- return false;
- }
-
- bool check() const { return bin.initialized(); }
- void reset() { bin.reset(); }
-
- public:
- VectorBase() {}
-
- /** Friend this class with the associated scalar proxy. */
- friend class ScalarProxy<Storage, Bin>;
-
- /**
- * Return a reference (ScalarProxy) to the stat at the given index.
- * @param index The vector index to access.
- * @return A reference of the stat.
- */
- ScalarProxy<Storage, Bin> operator[](int index);
-
- void update(StatData *data) {}
- };
-
- const StatData * getStatData(const void *stat);
+ std::string str() const { return proxy->str(); }
+ bool zero() const { return proxy->zero(); }
+ bool check() const { return proxy != NULL; }
+ void reset() { }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Vector Statistics
+//
+//////////////////////////////////////////////////////////////////////
- template <class Storage, class Bin>
+
+/**
+ * A proxy class to access the stat at a given index in a VectorBase stat.
+ * Behaves like a ScalarBase.
+ */
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
++template <class Stat>
+class ScalarProxy
+{
- /** Pointer to the bin in the parent VectorBase. */
- bin_t *bin;
- /** Pointer to the params in the parent VectorBase. */
- params_t *params;
+ private:
- /** Keep a pointer to the original stat so was can get data */
- void *stat;
-
- protected:
- /**
- * Retrieve the storage from the bin.
- * @return The storage from the bin for this stat.
- */
- Storage *data() { return bin->data(index, *params); }
- /**
- * Retrieve a const pointer to the storage from the bin.
- * @return A const pointer to the storage for this stat.
- */
- const Storage *data() const
- {
- bin_t *_bin = const_cast<bin_t *>(bin);
- params_t *_params = const_cast<params_t *>(params);
- return _bin->data(index, *_params);
- }
++ /** Pointer to the parent Vector. */
++ Stat *stat;
++
+ /** The index to access in the parent VectorBase. */
+ int index;
- Counter value() const { return data()->value(*params); }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
- Result result() const { return data()->result(*params); }
++ Counter value() const { return stat->data(index)->value(stat->params); }
+
+ /**
+ * Return the current value of this statas a result type.
+ * @return The current value.
+ */
- * @param b The bin to use.
++ Result result() const { return stat->data(index)->result(stat->params); }
+
+ public:
+ /**
+ * Create and initialize this proxy, do not register it with the database.
- ScalarProxy(bin_t &b, params_t &p, int i, void *s)
- : bin(&b), params(&p), index(i), stat(s) {}
+ * @param p The params to use.
+ * @param i The index to access.
+ */
- : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {}
++ ScalarProxy(Stat *s, int i)
++ : stat(s), index(i)
++ {
++ assert(stat);
++ }
++
+ /**
+ * Create a copy of the provided ScalarProxy.
+ * @param sp The proxy to copy.
+ */
+ ScalarProxy(const ScalarProxy &sp)
- bin = sp.bin;
- params = sp.params;
- index = sp.index;
++ : stat(sp.stat), index(sp.index)
++ {}
++
+ /**
+ * Set this proxy equal to the provided one.
+ * @param sp The proxy to copy.
+ * @return A reference to this proxy.
+ */
+ const ScalarProxy &operator=(const ScalarProxy &sp) {
- void operator++() { data()->inc(1, *params); }
+ stat = sp.stat;
++ index = sp.index;
+ return *this;
+ }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
- void operator--() { data()->dec(1, *params); }
++ void operator++() { stat->data(index)->inc(1, stat->params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
- void operator=(const U &v) { data()->set(v, *params); }
++ void operator--() { stat->data(index)->dec(1, stat->params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
- void operator+=(const U &v) { data()->inc(v, *params); }
++ void operator=(const U &v) { stat->data(index)->set(v, stat->params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
- void operator-=(const U &v) { data()->dec(v, *params); }
++ void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
- /**
- * Return true if stat is binned.
- *@return false since Proxies aren't printed/binned
- */
- bool binned() const { return false; }
-
++ void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
+
- const StatData *statData() const { return getStatData(stat); }
- std::string str() const
+ /**
+ * This stat has no state. Nothing to reset
+ */
+ void reset() { }
+
+ public:
- return csprintf("%s[%d]", this->statData()->name, index);
++ std::string
++ str() const
+ {
- template <class Storage, class Bin>
- inline ScalarProxy<Storage, Bin>
- VectorBase<Storage, Bin>::operator[](int index)
++ return csprintf("%s[%d]", stat->str(), index);
+
+ }
+};
+
- assert (index >= 0 && index < size());
- return ScalarProxy<Storage, Bin>(bin, params, index, this);
- }
++/**
++ * Implementation of a vector of stats. The type of stat is determined by the
++ * Storage class. @sa ScalarBase
++ */
++template <class Stor>
++class VectorBase : public DataAccess
+{
- template <class Storage, class Bin>
- class VectorProxy;
++ public:
++ typedef Stor Storage;
++
++ /** Define the params of the storage class. */
++ typedef typename Storage::Params Params;
+
- template <class Storage, class Bin>
- class Vector2dBase : public DataAccess
- {
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
++ /** Proxy type */
++ typedef ScalarProxy<VectorBase<Storage> > Proxy;
+
- size_t x;
- size_t y;
- bin_t bin;
- params_t params;
++ friend class ScalarProxy<VectorBase<Storage> >;
+
+ protected:
- Storage *data(int index) { return bin.data(index, params); }
- const Storage *data(int index) const
++ /** The storage of this stat. */
++ Storage *storage;
++ size_t _size;
++
++ /** The parameters for this stat. */
++ Params params;
+
+ protected:
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(¶ms);
- return _bin->data(index, *_params);
++ /**
++ * Retrieve the storage.
++ * @param index The vector index to access.
++ * @return The storage object at the given index.
++ */
++ Storage *data(int index) { return &storage[index]; }
++
++ /**
++ * Retrieve a const pointer to the storage.
++ * @param index The vector index to access.
++ * @return A const pointer to the storage object at the given index.
++ */
++ const Storage *data(int index) const { return &storage[index]; }
++
++ void
++ doInit(int s)
+ {
- Vector2dBase() {}
++ assert(s > 0 && "size must be positive!");
++ assert(!storage && "already initialized");
++ _size = s;
++
++ char *ptr = new char[_size * sizeof(Storage)];
++ storage = reinterpret_cast<Storage *>(ptr);
++
++ for (int i = 0; i < _size; ++i)
++ new (&storage[i]) Storage(params);
++
++ setInit();
+ }
+
+ public:
- void update(Vector2dData *data)
++ void value(VCounter &vec) const
++ {
++ vec.resize(size());
++ for (int i = 0; i < size(); ++i)
++ vec[i] = data(i)->value(params);
++ }
+
- int size = this->size();
- data->cvec.resize(size);
- for (int i = 0; i < size; ++i)
- data->cvec[i] = this->data(i)->value(params);
++ /**
++ * Copy the values to a local vector and return a reference to it.
++ * @return A reference to a vector of the stat values.
++ */
++ void result(VResult &vec) const
+ {
- std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
++ vec.resize(size());
++ for (int i = 0; i < size(); ++i)
++ vec[i] = data(i)->result(params);
+ }
+
- friend class VectorProxy<Storage, Bin>;
- VectorProxy<Storage, Bin> operator[](int index);
++ /**
++ * Return a total of all entries in this vector.
++ * @return The total of all vector entries.
++ */
++ Result total() const {
++ Result total = 0.0;
++ for (int i = 0; i < size(); ++i)
++ total += data(i)->result(params);
++ return total;
++ }
++
++ /**
++ * @return the number of elements in this vector.
++ */
++ size_t size() const { return _size; }
+
- size_t size() const { return bin.size(); }
- bool zero() const { return data(0)->value(params) == 0.0; }
++ bool
++ zero() const
++ {
++ for (int i = 0; i < size(); ++i)
++ if (data(i)->zero())
++ return false;
++ return true;
++ }
+
- * Reset stat value to default
++ bool
++ check() const
++ {
++ return storage != NULL;
++ }
++
++ void
++ reset()
++ {
++ for (int i = 0; i < size(); ++i)
++ data(i)->reset();
++ }
++
++ public:
++ VectorBase()
++ : storage(NULL)
++ {}
++
++ ~VectorBase()
++ {
++ if (!storage)
++ return;
++
++ for (int i = 0; i < _size; ++i)
++ data(i)->~Storage();
++ delete [] reinterpret_cast<char *>(storage);
++ }
+
+ /**
- void reset() { bin.reset(); }
++ * Return a reference (ScalarProxy) to the stat at the given index.
++ * @param index The vector index to access.
++ * @return A reference of the stat.
+ */
- bool check() { return bin.initialized(); }
++ Proxy
++ operator[](int index)
++ {
++ assert (index >= 0 && index < size());
++ return Proxy(this, index);
++ }
+
- template <class Storage, class Bin>
++ void update(StatData *data) {}
+};
+
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
++template <class Stat>
+class VectorProxy
+{
- bin_t *bin;
- params_t *params;
+ private:
- void *stat;
++ Stat *stat;
+ int offset;
+ int len;
- mutable VResult *vec;
+
+ private:
- Storage *data(int index) {
++ mutable VResult vec;
+
- return bin->data(offset + index, *params);
++ typename Stat::Storage *
++ data(int index)
++ {
+ assert(index < len);
- const Storage *data(int index) const {
- bin_t *_bin = const_cast<bin_t *>(bin);
- params_t *_params = const_cast<params_t *>(params);
- return _bin->data(offset + index, *_params);
++ return stat->data(offset + index);
+ }
+
- const VResult &result() const {
- if (vec)
- vec->resize(size());
- else
- vec = new VResult(size());
++ const typename Stat::Storage *
++ data(int index) const
++ {
++ assert(index < len);
++ return const_cast<Stat *>(stat)->data(offset + index);
+ }
+
+ public:
- (*vec)[i] = data(i)->result(*params);
++ const VResult &
++ result() const
++ {
++ vec.resize(size());
+
+ for (int i = 0; i < size(); ++i)
- return *vec;
++ vec[i] = data(i)->result(stat->params);
+
- Result total() const {
- Result total = 0.0;
++ return vec;
+ }
+
- total += data(i)->result(*params);
++ Result
++ total() const
++ {
++ Result total = 0;
+ for (int i = 0; i < size(); ++i)
- VectorProxy(bin_t &b, params_t &p, int o, int l, void *s)
- : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL)
++ total += data(i)->result(stat->params);
+ return total;
+ }
+
+ public:
- : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
- stat(sp.stat), vec(NULL)
- {
- }
-
- ~VectorProxy()
++ VectorProxy(Stat *s, int o, int l)
++ : stat(s), offset(o), len(l)
+ {
+ }
+
+ VectorProxy(const VectorProxy &sp)
- if (vec)
- delete vec;
++ : stat(sp.stat), offset(sp.offset), len(sp.len)
+ {
- const VectorProxy &operator=(const VectorProxy &sp)
+ }
+
- bin = sp.bin;
- params = sp.params;
++ const VectorProxy &
++ operator=(const VectorProxy &sp)
+ {
- stat = sp.stat;
- if (vec)
- delete vec;
- vec = NULL;
++ stat = sp.stat;
+ offset = sp.offset;
+ len = sp.len;
- ScalarProxy<Storage, Bin> operator[](int index)
+ return *this;
+ }
+
- return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
++ ScalarProxy<Stat> operator[](int index)
+ {
+ assert (index >= 0 && index < size());
- /**
- * Return true if stat is binned.
- *@return false since Proxies aren't printed/binned
- */
- bool binned() const { return false; }
-
++ return ScalarProxy<Stat>(stat, offset + index);
+ }
+
+ size_t size() const { return len; }
+
- template <class Storage, class Bin>
- inline VectorProxy<Storage, Bin>
- Vector2dBase<Storage, Bin>::operator[](int index)
+ /**
+ * This stat has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
- int offset = index * y;
- assert (index >= 0 && offset < size());
- return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
- }
++template <class Stor>
++class Vector2dBase : public DataAccess
+{
- /**
- * Construct this storage with the supplied params.
- * @param params The parameters.
- */
++ public:
++ typedef Stor Storage;
++ typedef typename Storage::Params Params;
++ typedef VectorProxy<Vector2dBase<Storage> > Proxy;
++ friend class ScalarProxy<Vector2dBase<Storage> >;
++ friend class VectorProxy<Vector2dBase<Storage> >;
++
++ protected:
++ size_t x;
++ size_t y;
++ size_t _size;
++ Storage *storage;
++ Params params;
++
++ protected:
++ Storage *data(int index) { return &storage[index]; }
++ const Storage *data(int index) const { return &storage[index]; }
++
++ void
++ doInit(int _x, int _y)
++ {
++ assert(_x > 0 && _y > 0 && "sizes must be positive!");
++ assert(!storage && "already initialized");
++
++ Vector2dData *statdata = dynamic_cast<Vector2dData *>(find());
++
++ x = _x;
++ y = _y;
++ statdata->x = _x;
++ statdata->y = _y;
++ _size = x * y;
++
++ char *ptr = new char[_size * sizeof(Storage)];
++ storage = reinterpret_cast<Storage *>(ptr);
++
++ for (int i = 0; i < _size; ++i)
++ new (&storage[i]) Storage(params);
++
++ setInit();
++ }
++
++ public:
++ Vector2dBase()
++ : storage(NULL)
++ {}
++
++ ~Vector2dBase()
++ {
++ if (!storage)
++ return;
++
++ for (int i = 0; i < _size; ++i)
++ data(i)->~Storage();
++ delete [] reinterpret_cast<char *>(storage);
++ }
++
++ void
++ update(Vector2dData *newdata)
++ {
++ int size = this->size();
++ newdata->cvec.resize(size);
++ for (int i = 0; i < size; ++i)
++ newdata->cvec[i] = data(i)->value(params);
++ }
++
++ std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
++
++ Proxy
++ operator[](int index)
++ {
++ int offset = index * y;
++ assert (index >= 0 && offset + index < size());
++ return Proxy(this, offset, y);
++ }
++
++
++ size_t
++ size() const
++ {
++ return _size;
++ }
++
++ bool
++ zero() const
++ {
++ return data(0)->zero();
++#if 0
++ for (int i = 0; i < size(); ++i)
++ if (!data(i)->zero())
++ return false;
++ return true;
++#endif
++ }
++
++ /**
++ * Reset stat value to default
++ */
++ void
++ reset()
++ {
++ for (int i = 0; i < size(); ++i)
++ data(i)->reset();
++ }
++
++ bool
++ check()
++ {
++ return storage != NULL;
++ }
++};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Non formula statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a distrbution stat.
+ */
+struct DistStor
+{
+ public:
+ /** The parameters for a distribution stat. */
+ struct Params
+ {
+ /** The minimum value to track. */
+ Counter min;
+ /** The maximum value to track. */
+ Counter max;
+ /** The number of entries in each bucket. */
+ Counter bucket_size;
+ /** The number of buckets. Equal to (max-min)/bucket_size. */
+ int size;
+ };
+ enum { fancy = false };
+
+ private:
+ /** The smallest value sampled. */
+ Counter min_val;
+ /** The largest value sampled. */
+ Counter max_val;
+ /** The number of values sampled less than min. */
+ Counter underflow;
+ /** The number of values sampled more than max. */
+ Counter overflow;
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+ /** Counter for each bucket. */
+ VCounter cvec;
+
+ public:
- : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
- overflow(Counter()), sum(Counter()), squares(Counter()),
- samples(Counter()), cvec(params.size)
+ DistStor(const Params ¶ms)
- template <class Storage, class Bin>
++ : cvec(params.size)
+ {
+ reset();
+ }
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param params The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params ¶ms)
+ {
+ if (val < params.min)
+ underflow += number;
+ else if (val > params.max)
+ overflow += number;
+ else {
+ int index = (int)floor((val - params.min) / params.bucket_size);
+ assert(index < size(params));
+ cvec[index] += number;
+ }
+
+ if (val < min_val)
+ min_val = val;
+
+ if (val > max_val)
+ max_val = val;
+
+ Counter sample = val * number;
+ sum += sample;
+ squares += sample * sample;
+ samples += number;
+ }
+
+ /**
+ * Return the number of buckets in this distribution.
+ * @return the number of buckets.
+ * @todo Is it faster to return the size from the parameters?
+ */
+ size_t size(const Params &) const { return cvec.size(); }
+
+ /**
+ * Returns true if any calls to sample have been made.
+ * @param params The paramters of the distribution.
+ * @return True if any values have been sampled.
+ */
+ bool zero(const Params ¶ms) const
+ {
+ return samples == Counter();
+ }
+
+ void update(DistDataData *data, const Params ¶ms)
+ {
+ data->min = params.min;
+ data->max = params.max;
+ data->bucket_size = params.bucket_size;
+ data->size = params.size;
+
+ data->min_val = (min_val == INT_MAX) ? 0 : min_val;
+ data->max_val = (max_val == INT_MIN) ? 0 : max_val;
+ data->underflow = underflow;
+ data->overflow = overflow;
+ data->cvec.resize(params.size);
+ for (int i = 0; i < params.size; ++i)
+ data->cvec[i] = cvec[i];
+
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ min_val = INT_MAX;
+ max_val = INT_MIN;
+ underflow = 0;
+ overflow = 0;
+
+ int size = cvec.size();
+ for (int i = 0; i < size; ++i)
+ cvec[i] = Counter();
+
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage and interface for a distribution that calculates mean
+ * and variance.
+ */
+struct FancyStor
+{
+ public:
+ /**
+ * No paramters for this storage.
+ */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ FancyStor(const Params &)
+ : sum(Counter()), squares(Counter()), samples(Counter())
+ { }
+
+ /**
+ * Add a value the given number of times to this running average.
+ * Update the running sum and sum of squares, increment the number of
+ * values seen by the given number.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The parameters of this stat.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ samples += number;
+ }
+
+ void update(DistDataData *data, const Params ¶ms)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Return the number of entries in this stat, 1
+ * @return 1.
+ */
+ size_t size(const Params &) const { return 1; }
+
+ /**
+ * Return true if no samples have been added.
+ * @return True if no samples have been added.
+ */
+ bool zero(const Params &) const { return samples == Counter(); }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage for distribution that calculates per cycle mean and
+ * variance.
+ */
+struct AvgFancy
+{
+ public:
+ /** No parameters for this storage. */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** Current total. */
+ Counter sum;
+ /** Current sum of squares. */
+ Counter squares;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * Update the running sum and sum of squares.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ }
+
+ void update(DistDataData *data, const Params ¶ms)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = curTick;
+ }
+
+ /**
+ * Return the number of entries, in this case 1.
+ * @return 1.
+ */
+ size_t size(const Params ¶ms) const { return 1; }
+ /**
+ * Return true if no samples have been added.
+ * @return True if the sum is zero.
+ */
+ bool zero(const Params ¶ms) const { return sum == Counter(); }
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ }
+};
+
+/**
+ * Implementation of a distribution stat. The type of distribution is
+ * determined by the Storage template. @sa ScalarBase
+ */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template Bin<Storage> bin_t;
++template <class Stor>
+class DistBase : public DataAccess
+{
+ public:
++ typedef Stor Storage;
+ /** Define the params of the storage class. */
- /** The bin of this stat. */
- bin_t bin;
++ typedef typename Storage::Params Params;
+
+ protected:
- params_t params;
++ /** The storage for this stat. */
++ char storage[sizeof(Storage)];
++
+ /** The parameters for this stat. */
- * Retrieve the storage from the bin.
++ Params params;
+
+ protected:
+ /**
- Storage *data() { return bin.data(params); }
++ * Retrieve the storage.
+ * @return The storage object for this stat.
+ */
- * Retrieve a const pointer to the storage from the bin.
++ Storage *data()
++ {
++ return reinterpret_cast<Storage *>(storage);
++ }
++
+ /**
- const Storage *data() const
++ * Retrieve a const pointer to the storage.
+ * @return A const pointer to the storage object for this stat.
+ */
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(¶ms);
- return _bin->data(*_params);
++ const Storage *
++ data() const
+ {
- /**
- * @return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
++ return reinterpret_cast<const Storage *>(storage);
++ }
++
++ void
++ doInit()
++ {
++ new (storage) Storage(params);
++ setInit();
+ }
+
+ public:
+ DistBase() { }
+
+ /**
+ * Add a value to the distribtion n times. Calls sample on the storage
+ * class.
+ * @param v The value to add.
+ * @param n The number of times to add it, defaults to 1.
+ */
+ template <typename U>
+ void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
+
+ /**
+ * Return the number of entries in this stat.
+ * @return The number of entries.
+ */
+ size_t size() const { return data()->size(params); }
+ /**
+ * Return true if no samples have been added.
+ * @return True if there haven't been any samples.
+ */
+ bool zero() const { return data()->zero(params); }
+
+ void update(DistData *base)
+ {
+ base->data.fancy = Storage::fancy;
+ data()->update(&(base->data), params);
+ }
- void reset()
++
+ /**
+ * Reset stat value to default
+ */
- bin.reset();
++ void
++ reset()
+ {
- bool check() { return bin.initialized(); }
++ data()->reset();
+ }
+
- template <class Storage, class Bin>
++ bool
++ check()
++ {
++ return true;
++ }
+};
+
- template <class Storage, class Bin>
++template <class Stat>
+class DistProxy;
+
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
++template <class Stor>
+class VectorDistBase : public DataAccess
+{
+ public:
- bin_t bin;
- params_t params;
++ typedef Stor Storage;
++ typedef typename Storage::Params Params;
++ typedef DistProxy<VectorDistBase<Storage> > Proxy;
++ friend class DistProxy<VectorDistBase<Storage> >;
+
+ protected:
- Storage *data(int index) { return bin.data(index, params); }
- const Storage *data(int index) const
++ Storage *storage;
++ size_t _size;
++ Params params;
+
+ protected:
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(¶ms);
- return _bin->data(index, *_params);
++ Storage *
++ data(int index)
++ {
++ return &storage[index];
++ }
++
++ const Storage *
++ data(int index) const
+ {
- VectorDistBase() {}
++ return &storage[index];
++ }
++
++ void
++ doInit(int s)
++ {
++ assert(s > 0 && "size must be positive!");
++ assert(!storage && "already initialized");
++ _size = s;
++
++ char *ptr = new char[_size * sizeof(Storage)];
++ storage = reinterpret_cast<Storage *>(ptr);
++
++ for (int i = 0; i < _size; ++i)
++ new (&storage[i]) Storage(params);
++
++ setInit();
+ }
+
+ public:
- friend class DistProxy<Storage, Bin>;
- DistProxy<Storage, Bin> operator[](int index);
- const DistProxy<Storage, Bin> operator[](int index) const;
++ VectorDistBase()
++ : storage(NULL)
++ {}
+
- size_t size() const { return bin.size(); }
- bool zero() const { return false; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
++ ~VectorDistBase()
++ {
++ if (!storage)
++ return ;
++
++ for (int i = 0; i < _size; ++i)
++ data(i)->~Storage();
++ delete [] reinterpret_cast<char *>(storage);
++ }
++
++ Proxy operator[](int index);
++
++ size_t
++ size() const
++ {
++ return _size;
++ }
++
++ bool
++ zero() const
++ {
++ return false;
++#if 0
++ for (int i = 0; i < size(); ++i)
++ if (!data(i)->zero(params))
++ return false;
++ return true;
++#endif
++ }
+
- void reset() { bin.reset(); }
+ /**
+ * Reset stat value to default
+ */
- bool check() { return bin.initialized(); }
- void update(VectorDistData *base)
++ void
++ reset()
++ {
++ for (int i = 0; i < size(); ++i)
++ data(i)->reset();
++ }
++
++ bool
++ check()
++ {
++ return storage != NULL;
++ }
+
- template <class Storage, class Bin>
++ void
++ update(VectorDistData *base)
+ {
+ int size = this->size();
+ base->data.resize(size);
+ for (int i = 0; i < size; ++i) {
+ base->data[i].fancy = Storage::fancy;
+ data(i)->update(&(base->data[i]), params);
+ }
+ }
+};
+
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template Bin<Storage> bin_t;
- typedef VectorDistBase<Storage, Bin> base_t;
-
++template <class Stat>
+class DistProxy
+{
- union {
- base_t *stat;
- const base_t *cstat;
- };
+ private:
- Storage *data() { return stat->data(index); }
- const Storage *data() const { return cstat->data(index); }
++ Stat *stat;
+ int index;
+
+ protected:
- DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
- : cstat(&s), index(i) {}
++ typename Stat::Storage *data() { return stat->data(index); }
++ const typename Stat::Storage *data() const { return stat->data(index); }
+
+ public:
- : cstat(sp.cstat), index(sp.index) {}
- const DistProxy &operator=(const DistProxy &sp) {
- cstat = sp.cstat; index = sp.index; return *this;
++ DistProxy(Stat *s, int i)
++ : stat(s), index(i)
++ {}
++
+ DistProxy(const DistProxy &sp)
- void sample(const U &v, int n = 1) { data()->sample(v, n, cstat->params); }
++ : stat(sp.stat), index(sp.index)
++ {}
++
++ const DistProxy &operator=(const DistProxy &sp)
++ {
++ stat = sp.stat;
++ index = sp.index;
++ return *this;
+ }
+
+ public:
+ template <typename U>
- size_t size() const { return 1; }
- bool zero() const { return data()->zero(cstat->params); }
- /**
- * Return true if stat is binned.
- *@return false since Proxies are not binned/printed.
- */
- bool binned() const { return false; }
++ void
++ sample(const U &v, int n = 1)
++ {
++ data()->sample(v, n, stat->params);
++ }
++
++ size_t
++ size() const
++ {
++ return 1;
++ }
++
++ bool
++ zero() const
++ {
++ return data()->zero(stat->params);
++ }
+
- template <class Storage, class Bin>
- inline DistProxy<Storage, Bin>
- VectorDistBase<Storage, Bin>::operator[](int index)
+ /**
+ * Proxy has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
- return DistProxy<Storage, Bin>(*this, index);
- }
-
- template <class Storage, class Bin>
- inline const DistProxy<Storage, Bin>
- VectorDistBase<Storage, Bin>::operator[](int index) const
- {
- assert (index >= 0 && index < size());
- return DistProxy<Storage, Bin>(*this, index);
++template <class Storage>
++inline typename VectorDistBase<Storage>::Proxy
++VectorDistBase<Storage>::operator[](int index)
+{
+ assert (index >= 0 && index < size());
- template <class Storage, class Bin>
++ return typename VectorDistBase<Storage>::Proxy(this, index);
+}
+
+#if 0
- VectorDistBase<Storage, Bin>::total(int index) const
++template <class Storage>
+Result
- for (int i=0; i < x_size(); ++i) {
- total += data(i)->result(*params);
++VectorDistBase<Storage>::total(int index) const
+{
+ int total = 0;
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const = 0;
++ for (int i = 0; i < x_size(); ++i) {
++ total += data(i)->result(stat->params);
+ }
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////
+//
+// Formula Details
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Base class for formula statistic node. These nodes are used to build a tree
+ * that represents the formula.
+ */
+class Node : public RefCounted
+{
+ public:
+ /**
+ * Return the number of nodes in the subtree starting at this node.
+ * @return the number of nodes in this subtree.
+ */
+ virtual size_t size() const = 0;
+ /**
+ * Return the result vector of this subtree.
+ * @return The result vector of this subtree.
+ */
+ virtual const VResult &result() const = 0;
+ /**
+ * Return the total of the result vector.
+ * @return The total of the result vector.
+ */
+ virtual Result total() const = 0;
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return data->binned(); }
+
+ /**
+ *
+ */
+ virtual std::string str() const = 0;
+};
+
+/** Reference counting pointer to a function Node. */
+typedef RefCountingPtr<Node> NodePtr;
+
+class ScalarStatNode : public Node
+{
+ private:
+ const ScalarData *data;
+ mutable VResult vresult;
+
+ public:
+ ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
+ virtual const VResult &result() const
+ {
+ vresult[0] = data->result();
+ return vresult;
+ }
+ virtual Result total() const { return data->result(); };
+
+ virtual size_t size() const { return 1; }
- template <class Storage, class Bin>
+
+ /**
+ *
+ */
+ virtual std::string str() const { return data->name; }
+};
+
- const ScalarProxy<Storage, Bin> proxy;
++template <class Stat>
+class ScalarProxyNode : public Node
+{
+ private:
- ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
- : proxy(p), vresult(1) { }
- virtual const VResult &result() const
++ const ScalarProxy<Stat> proxy;
+ mutable VResult vresult;
+
+ public:
- virtual Result total() const { return proxy.result(); };
++ ScalarProxyNode(const ScalarProxy<Stat> &p)
++ : proxy(p), vresult(1)
++ { }
++
++ virtual const VResult &
++ result() const
+ {
+ vresult[0] = proxy.result();
+ return vresult;
+ }
- virtual size_t size() const { return 1; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return proxy.binned(); }
+
- virtual std::string str() const { return proxy.str(); }
++ virtual Result
++ total() const
++ {
++ return proxy.result();
++ }
++
++ virtual size_t
++ size() const
++ {
++ return 1;
++ }
+
+ /**
+ *
+ */
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return data->binned(); }
++ virtual std::string
++ str() const
++ {
++ return proxy.str();
++ }
+};
+
+class VectorStatNode : public Node
+{
+ private:
+ const VectorData *data;
+
+ public:
+ VectorStatNode(const VectorData *d) : data(d) { }
+ virtual const VResult &result() const { return data->result(); }
+ virtual Result total() const { return data->total(); };
+
+ virtual size_t size() const { return data->size(); }
-
- /**
- * Return true if stat is binned.
- *@return False since constants aren't binned.
- */
- virtual bool binned() const { return false; }
-
+
+ virtual std::string str() const { return data->name; }
+};
+
+template <class T>
+class ConstNode : public Node
+{
+ private:
+ VResult vresult;
+
+ public:
+ ConstNode(T s) : vresult(1, (Result)s) {}
+ const VResult &result() const { return vresult; }
+ virtual Result total() const { return vresult[0]; };
+ virtual size_t size() const { return 1; }
- /**
- * Return true if child of node is binned.
- *@return True if child of node is binned.
- */
- virtual bool binned() const { return l->binned(); }
+ virtual std::string str() const { return to_string(vresult[0]); }
+};
+
+template <class Op>
+struct OpString;
+
+template<>
+struct OpString<std::plus<Result> >
+{
+ static std::string str() { return "+"; }
+};
+
+template<>
+struct OpString<std::minus<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template<>
+struct OpString<std::multiplies<Result> >
+{
+ static std::string str() { return "*"; }
+};
+
+template<>
+struct OpString<std::divides<Result> >
+{
+ static std::string str() { return "/"; }
+};
+
+template<>
+struct OpString<std::modulus<Result> >
+{
+ static std::string str() { return "%"; }
+};
+
+template<>
+struct OpString<std::negate<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template <class Op>
+class UnaryNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ UnaryNode(NodePtr &p) : l(p) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+
+ assert(size > 0);
+
+ vresult.resize(size);
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total());
+ }
+
+ virtual size_t size() const { return l->size(); }
- /**
- * Return true if any children of node are binned
- *@return True if either child of node is binned.
- */
- virtual bool binned() const { return (l->binned() || r->binned()); }
+
+ virtual std::string str() const
+ {
+ return OpString<Op>::str() + l->str();
+ }
+};
+
+template <class Op>
+class BinaryNode : public Node
+{
+ public:
+ NodePtr l;
+ NodePtr r;
+ mutable VResult vresult;
+
+ public:
+ BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
+
+ const VResult &result() const
+ {
+ Op op;
+ const VResult &lvec = l->result();
+ const VResult &rvec = r->result();
+
+ assert(lvec.size() > 0 && rvec.size() > 0);
+
+ if (lvec.size() == 1 && rvec.size() == 1) {
+ vresult.resize(1);
+ vresult[0] = op(lvec[0], rvec[0]);
+ } else if (lvec.size() == 1) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[0], rvec[i]);
+ } else if (rvec.size() == 1) {
+ int size = lvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[0]);
+ } else if (rvec.size() == lvec.size()) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[i]);
+ }
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total(), r->total());
+ }
+
+ virtual size_t size() const {
+ int ls = l->size();
+ int rs = r->size();
+ if (ls == 1)
+ return rs;
+ else if (rs == 1)
+ return ls;
+ else {
+ assert(ls == rs && "Node vector sizes are not equal");
+ return ls;
+ }
+ }
- /**
- * Return true if child of node is binned.
- *@return True if child of node is binned.
- */
- virtual bool binned() const { return l->binned(); }
+
+ virtual std::string str() const
+ {
+ return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
+ }
+};
+
+template <class Op>
+class SumNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ SumNode(NodePtr &p) : l(p), vresult(1) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ vresult[0] = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[0] = op(vresult[0], lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ Result vresult = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult = op(vresult, lvec[i]);
+
+ return vresult;
+ }
+
+ virtual size_t size() const { return 1; }
- * These are the statistics that are used in the simulator. By default these
- * store counters and don't use binning, but are templatized to accept any type
- * and any Bin class.
+
+ virtual std::string str() const
+ {
+ return csprintf("total(%s)", l->str());
+ }
+};
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Visible Statistics Types
+//
+//////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup VisibleStats "Statistic Types"
- /**
- * This is an easy way to assign all your stats to be binned or not
- * binned. If the typedef is NoBin, nothing is binned. If it is
- * MainBin, then all stats are binned under that Bin.
- */
- #if STATS_BINNING
- typedef MainBin DefaultBin;
- #else
- typedef NoBin DefaultBin;
- #endif
-
++ * These are the statistics that are used in the simulator.
+ * @{
+ */
+
- template <class Bin = DefaultBin>
- class Scalar
- : public Wrap<Scalar<Bin>,
- ScalarBase<StatStor, Bin>,
- ScalarStatData>
+/**
+ * This is a simple scalar statistic, like a counter.
+ * @sa Stat, ScalarBase, StatStor
+ */
- typedef ScalarBase<StatStor, Bin> Base;
++template<int N = 0>
++class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData>
+{
+ public:
+ /** The base implementation. */
- this->setInit();
++ typedef ScalarBase<StatStor> Base;
+
+ Scalar()
+ {
- class Value
- : public Wrap<Value,
- ValueBase,
- ScalarStatData>
++ this->doInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
- template <class Bin = DefaultBin>
- class Average
- : public Wrap<Average<Bin>,
- ScalarBase<AvgStor, Bin>,
- ScalarStatData>
++class Value : public Wrap<Value, ValueBase, ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ValueBase Base;
+
+ template <class T>
+ Value &scalar(T &value)
+ {
+ Base::scalar(value);
+ return *this;
+ }
+
+ template <class T>
+ Value &functor(T &func)
+ {
+ Base::functor(func);
+ return *this;
+ }
+};
+
+/**
+ * A stat that calculates the per cycle average of a value.
+ * @sa Stat, ScalarBase, AvgStor
+ */
- typedef ScalarBase<AvgStor, Bin> Base;
++template<int N = 0>
++class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData>
+{
+ public:
+ /** The base implementation. */
- this->setInit();
++ typedef ScalarBase<AvgStor> Base;
+
+ Average()
+ {
- template <class Bin = DefaultBin>
- class Vector
- : public WrapVec<Vector<Bin>,
- VectorBase<StatStor, Bin>,
- VectorStatData>
++ this->doInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
+/**
+ * A vector of scalar stats.
+ * @sa Stat, VectorBase, StatStor
+ */
- typedef ScalarBase<StatStor, Bin> Base;
++template<int N = 0>
++class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData>
+{
+ public:
+ /** The base implementation. */
- this->bin.init(size, this->params);
- this->setInit();
-
++ typedef ScalarBase<StatStor> Base;
+
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ Vector &init(size_t size) {
- template <class Bin = DefaultBin>
++ this->doInit(size);
+ return *this;
+ }
+};
+
+/**
+ * A vector of Average stats.
+ * @sa Stat, VectorBase, AvgStor
+ */
- : public WrapVec<AverageVector<Bin>,
- VectorBase<AvgStor, Bin>,
- VectorStatData>
++template<int N = 0>
+class AverageVector
- this->bin.init(size, this->params);
- this->setInit();
-
++ : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData>
+{
+ public:
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ AverageVector &init(size_t size) {
- template <class Bin = DefaultBin>
++ this->doInit(size);
+ return *this;
+ }
+};
+
+/**
+ * A 2-Dimensional vecto of scalar stats.
+ * @sa Stat, Vector2dBase, StatStor
+ */
- : public WrapVec2d<Vector2d<Bin>,
- Vector2dBase<StatStor, Bin>,
- Vector2dStatData>
++template<int N = 0>
+class Vector2d
- Vector2d &init(size_t _x, size_t _y) {
- this->statData()->x = this->x = _x;
- this->statData()->y = this->y = _y;
- this->bin.init(this->x * this->y, this->params);
- this->setInit();
-
++ : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData>
+{
+ public:
- template <class Bin = DefaultBin>
++ Vector2d &init(size_t x, size_t y) {
++ this->doInit(x, y);
+ return *this;
+ }
+};
+
+/**
+ * A simple distribution stat.
+ * @sa Stat, DistBase, DistStor
+ */
- : public Wrap<Distribution<Bin>,
- DistBase<DistStor, Bin>,
- DistStatData>
++template<int N = 0>
+class Distribution
- typedef DistBase<DistStor, Bin> Base;
++ : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData>
+{
+ public:
+ /** Base implementation. */
- typedef typename DistStor::Params Params;
++ typedef DistBase<DistStor> Base;
+ /** The Parameter type. */
- this->bin.init(this->params);
- this->setInit();
-
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Set the parameters of this distribution. @sa DistStor::Params
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ Distribution &init(Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
- template <class Bin = DefaultBin>
++ this->doInit();
+ return *this;
+ }
+};
+
+/**
+ * Calculates the mean and variance of all the samples.
+ * @sa Stat, DistBase, FancyStor
+ */
- : public Wrap<StandardDeviation<Bin>,
- DistBase<FancyStor, Bin>,
- DistStatData>
++template<int N = 0>
+class StandardDeviation
- typedef DistBase<DistStor, Bin> Base;
++ : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData>
+{
+ public:
+ /** The base implementation */
- typedef typename DistStor::Params Params;
++ typedef DistBase<DistStor> Base;
+ /** The parameter type. */
- this->bin.init(this->params);
- this->setInit();
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ StandardDeviation() {
- template <class Bin = DefaultBin>
++ this->doInit();
+ }
+};
+
+/**
+ * Calculates the per cycle mean and variance of the samples.
+ * @sa Stat, DistBase, AvgFancy
+ */
- : public Wrap<AverageDeviation<Bin>,
- DistBase<AvgFancy, Bin>,
- DistStatData>
++template<int N = 0>
+class AverageDeviation
- typedef DistBase<DistStor, Bin> Base;
++ : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData>
+{
+ public:
+ /** The base implementation */
- typedef typename DistStor::Params Params;
++ typedef DistBase<DistStor> Base;
+ /** The parameter type. */
- this->bin.init(this->params);
- this->setInit();
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ AverageDeviation()
+ {
- template <class Bin = DefaultBin>
++ this->doInit();
+ }
+};
+
+/**
+ * A vector of distributions.
+ * @sa Stat, VectorDistBase, DistStor
+ */
- : public WrapVec<VectorDistribution<Bin>,
- VectorDistBase<DistStor, Bin>,
++template<int N = 0>
+class VectorDistribution
- typedef VectorDistBase<DistStor, Bin> Base;
++ : public WrapVec<VectorDistribution<N>,
++ VectorDistBase<DistStor>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
- typedef typename DistStor::Params Params;
++ typedef VectorDistBase<DistStor> Base;
+ /** The parameter type. */
- this->bin.init(size, this->params);
- this->setInit();
-
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage and parameters for this distribution.
+ * @param size The size of the vector (the number of distributions).
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
- template <class Bin = DefaultBin>
++ this->doInit(size);
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of StandardDeviation stats.
+ * @sa Stat, VectorDistBase, FancyStor
+ */
- : public WrapVec<VectorStandardDeviation<Bin>,
- VectorDistBase<FancyStor, Bin>,
++template<int N = 0>
+class VectorStandardDeviation
- typedef VectorDistBase<FancyStor, Bin> Base;
++ : public WrapVec<VectorStandardDeviation<N>,
++ VectorDistBase<FancyStor>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
- typedef typename DistStor::Params Params;
++ typedef VectorDistBase<FancyStor> Base;
+ /** The parameter type. */
- this->bin.init(size, this->params);
- this->setInit();
-
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorStandardDeviation &init(int size) {
- template <class Bin = DefaultBin>
++ this->doInit(size);
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of AverageDeviation stats.
+ * @sa Stat, VectorDistBase, AvgFancy
+ */
- : public WrapVec<VectorAverageDeviation<Bin>,
- VectorDistBase<AvgFancy, Bin>,
++template<int N = 0>
+class VectorAverageDeviation
- typedef VectorDistBase<AvgFancy, Bin> Base;
++ : public WrapVec<VectorAverageDeviation<N>,
++ VectorDistBase<AvgFancy>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
- typedef typename DistStor::Params Params;
++ typedef VectorDistBase<AvgFancy> Base;
+ /** The parameter type. */
- this->bin.init(size, this->params);
- this->setInit();
-
++ typedef DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorAverageDeviation &init(int size) {
- /**
- * Return true if Formula is binned. i.e. any of its children
- * nodes are binned
- * @return True if Formula is binned.
- */
- bool binned() const;
-
++ this->doInit(size);
+ return *this;
+ }
+};
+
+/**
+ * A formula for statistics that is calculated when printed. A formula is
+ * stored as a tree of Nodes that represent the equation to calculate.
+ * @sa Stat, ScalarStat, VectorStat, Node, Temp
+ */
+class FormulaBase : public DataAccess
+{
+ protected:
+ /** The root of the tree which represents the Formula */
+ NodePtr root;
+ friend class Temp;
+
+ public:
+ /**
+ * Return the result of the Fomula in a vector. If there were no Vector
+ * components to the Formula, then the vector is size 1. If there were,
+ * like x/y with x being a vector of size 3, then the result returned will
+ * be x[0]/y, x[1]/y, x[2]/y, respectively.
+ * @return The result vector.
+ */
+ void result(VResult &vec) const;
+
+ /**
+ * Return the total Formula result. If there is a Vector
+ * component to this Formula, then this is the result of the
+ * Formula if the formula is applied after summing all the
+ * components of the Vector. For example, if Formula is x/y where
+ * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
+ * there is no Vector component, total() returns the same value as
+ * the first entry in the VResult val() returns.
+ * @return The total of the result vector.
+ */
+ Result total() const;
+
+ /**
+ * Return the number of elements in the tree.
+ */
+ size_t size() const;
+
- virtual bool binned() const { return s.binned(); }
+ bool check() const { return true; }
+
+ /**
+ * Formulas don't need to be reset
+ */
+ void reset();
+
+ /**
+ *
+ */
+ bool zero() const;
+
+ /**
+ *
+ */
+ void update(StatData *);
+
+ std::string str() const;
+};
+
+class FormulaData : public VectorData
+{
+ public:
+ virtual std::string str() const = 0;
+ virtual bool check() const { return true; }
+};
+
+template <class Stat>
+class FormulaStatData : public FormulaData
+{
+ protected:
+ Stat &s;
+ mutable VResult vec;
+ mutable VCounter cvec;
+
+ public:
+ FormulaStatData(Stat &stat) : s(stat) {}
+
- virtual bool binned() const { return formula.binned(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual const VResult &result() const
+ {
+ s.result(vec);
+ return vec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual VCounter &value() const { return cvec; }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+ virtual std::string str() const { return s.str(); }
+};
+
+class Temp;
+class Formula
+ : public WrapVec<Formula,
+ FormulaBase,
+ FormulaStatData>
+{
+ public:
+ /**
+ * Create and initialize thie formula, and register it with the database.
+ */
+ Formula();
+
+ /**
+ * Create a formula with the given root node, register it with the
+ * database.
+ * @param r The root of the expression tree.
+ */
+ Formula(Temp r);
+
+ /**
+ * Set an unitialized Formula to the given root.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator=(Temp r);
+
+ /**
+ * Add the given tree to the existing one.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator+=(Temp r);
+};
+
+class FormulaNode : public Node
+{
+ private:
+ const Formula &formula;
+ mutable VResult vec;
+
+ public:
+ FormulaNode(const Formula &f) : formula(f) {}
+
+ virtual size_t size() const { return formula.size(); }
+ virtual const VResult &result() const { formula.result(vec); return vec; }
+ virtual Result total() const { return formula.total(); }
- template <class Bin>
- Temp(const Scalar<Bin> &s)
+
+ virtual std::string str() const { return formula.str(); }
+};
+
+/**
+ * Helper class to construct formula node trees.
+ */
+class Temp
+{
+ protected:
+ /**
+ * Pointer to a Node object.
+ */
+ NodePtr node;
+
+ public:
+ /**
+ * Copy the given pointer to this class.
+ * @param n A pointer to a Node object to copy.
+ */
+ Temp(NodePtr n) : node(n) { }
+
+ /**
+ * Return the node pointer.
+ * @return the node pointer.
+ */
+ operator NodePtr&() { return node;}
+
+ public:
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
- template <class Bin>
- Temp(const Average<Bin> &s)
++ template <int N>
++ Temp(const Scalar<N> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ Temp(const Value &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
- template <class Bin>
- Temp(const Vector<Bin> &s)
++ template <int N>
++ Temp(const Average<N> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new VectorStatNode.
+ * @param s The VectorStat to place in a node.
+ */
- template <class Storage, class Bin>
- Temp(const ScalarProxy<Storage, Bin> &p)
- : node(new ScalarProxyNode<Storage, Bin>(p)) { }
++ template <int N>
++ Temp(const Vector<N> &s)
+ : node(new VectorStatNode(s.statData())) { }
+
+ /**
+ *
+ */
+ Temp(const Formula &f)
+ : node(new FormulaNode(f)) { }
+
+ /**
+ * Create a new ScalarProxyNode.
+ * @param p The ScalarProxy to place in a node.
+ */
++ template <class Stat>
++ Temp(const ScalarProxy<Stat> &p)
++ : node(new ScalarProxyNode<Stat>(p)) { }
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed char value)
+ : node(new ConstNode<signed char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned char value)
+ : node(new ConstNode<unsigned char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed short value)
+ : node(new ConstNode<signed short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned short value)
+ : node(new ConstNode<unsigned short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed int value)
+ : node(new ConstNode<signed int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned int value)
+ : node(new ConstNode<unsigned int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long value)
+ : node(new ConstNode<signed long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long value)
+ : node(new ConstNode<unsigned long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long long value)
+ : node(new ConstNode<signed long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long long value)
+ : node(new ConstNode<unsigned long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(float value)
+ : node(new ConstNode<float>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(double value)
+ : node(new ConstNode<double>(value)) {}
+};
+
+
+/**
+ * @}
+ */
+
+void check();
+void reset();
+void registerResetCallback(Callback *cb);
+
+inline Temp
+operator+(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
+}
+
+inline Temp
+operator*(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
+}
+
+inline Temp
+operator/(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l)
+{
+ return NodePtr(new UnaryNode<std::negate<Result> >(l));
+}
+
+template <typename T>
+inline Temp
+constant(T val)
+{
+ return NodePtr(new ConstNode<T>(val));
+}
+
+inline Temp
+sum(Temp val)
+{
+ return NodePtr(new SumNode<std::plus<Result> >(val));
+}
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATISTICS_HH__
--- /dev/null
- mysql.query("DELETE bins "
- "FROM bins "
- "LEFT JOIN data ON bn_id=dt_bin "
- "WHERE dt_bin IS NULL");
-
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
-
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <cassert>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/misc.hh"
+#include "base/mysql.hh"
+#include "base/statistics.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/mysql_run.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/types.hh"
+#include "base/str.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Stats {
+
+MySqlRun MySqlDB;
+
+bool
+MySqlConnected()
+{
+ return MySqlDB.connected();
+}
+
+void
+MySqlRun::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &sample,
+ const string &project)
+{
+ if (connected())
+ panic("can only get one database connection at this time!");
+
+ mysql.connect(host, user, passwd, db);
+ if (mysql.error)
+ panic("could not connect to database server\n%s\n", mysql.error);
+
+ if (mysql.autocommit(false))
+ panic("could not set autocommit\n%s\n", mysql.error);
+
+ remove(name);
+ //cleanup();
+ setup(name, sample, user, project);
+}
+
+void
+MySqlRun::setup(const string &name, const string &sample, const string &user,
+ const string &project)
+{
+ assert(mysql.connected());
+
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO "
+ "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
+ "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
+ "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
+ name, sample, user, project);
+
+ mysql.query(insert);
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ run_id = mysql.insert_id();
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySqlRun::remove(const string &name)
+{
+ assert(mysql.connected());
+ stringstream sql;
+ ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name);
+ mysql.query(sql);
+ if (mysql.error)
+ panic("could not delete run\n%s\n", mysql.error);
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySqlRun::cleanup()
+{
+ assert(mysql.connected());
+
+ mysql.query("DELETE data "
+ "FROM data "
+ "LEFT JOIN runs ON dt_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE formula_ref "
+ "FROM formula_ref "
+ "LEFT JOIN runs ON fr_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE formulas "
+ "FROM formulas "
+ "LEFT JOIN formula_ref ON fm_stat=fr_stat "
+ "WHERE fr_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE stats "
+ "FROM stats "
+ "LEFT JOIN data ON st_id=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE subdata "
+ "FROM subdata "
+ "LEFT JOIN data ON sd_stat=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
- unsigned
- SetupBin(const string &bin)
- {
- static map<string, int> binmap;
-
- using namespace MySQL;
- map<string,int>::const_iterator i = binmap.find(bin);
- if (i != binmap.end())
- return (*i).second;
-
- Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
-
- uint16_t bin_id;
-
- stringstream select;
- stringstream insert;
- ccprintf(select, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin);
-
- mysql.query(select);
- MySQL::Result result = mysql.store_result();
- if (result) {
- assert(result.num_fields() == 1);
- MySQL::Row row = result.fetch_row();
- if (row) {
- to_number(row[0], bin_id);
- goto exit;
- }
- }
-
- ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin);
-
- mysql.query(insert);
- if (mysql.error)
- panic("could not get a bin\n%s\n", mysql.error);
-
- bin_id = mysql.insert_id();
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
-
- binmap.insert(make_pair(bin, bin_id));
-
- exit:
- return bin_id;
- }
-
+ mysql.query("DELETE events"
+ "FROM events"
+ "LEFT JOIN runs ON ev_run=rn_id"
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE event_names"
+ "FROM event_names"
+ "LEFT JOIN events ON en_id=ev_event"
+ "WHERE ev_event IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+SetupStat::init()
+{
+ name = "";
+ descr = "";
+ type = "";
+ print = false;
+ prereq = 0;
+ prec = -1;
+ nozero = false;
+ nonan = false;
+ total = false;
+ pdf = false;
+ cdf = false;
+ min = 0;
+ max = 0;
+ bktsize = 0;
+ size = 0;
+}
+
+unsigned
+SetupStat::setup()
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO "
+ "stats(st_name, st_descr, st_type, st_print, st_prereq, "
+ "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
+ "st_min, st_max, st_bktsize, st_size)"
+ "values(\"%s\",\"%s\",\"%s\","
+ " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
+ name, descr, type, print, prereq, (int)prec, nozero, nonan,
+ total, pdf, cdf,
+ min, max, bktsize, size);
+
+ mysql.query(insert);
+ if (!mysql.error) {
+ int id = mysql.insert_id();
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+ return id;
+ }
+
+ stringstream select;
+ ccprintf(select, "SELECT * FROM stats WHERE st_name=\"%s\"", name);
+
+ mysql.query(select);
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not find stat\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 16);
+ MySQL::Row row = result.fetch_row();
+ if (!row)
+ panic("could not get stat row\n%s\n", mysql.error);
+
+ bool tb;
+ int8_t ti8;
+ uint16_t tu16;
+ int64_t ti64;
+ uint64_t tu64;
+
+ if (name != (char *)row[1])
+ panic("failed stat check on %s:name. %s != %s\n",
+ name, name, row[1]);
+
+ if (descr != (char *)row[2])
+ panic("failed stat check on %s:descr. %s != %s\n",
+ name, descr, row[2]);
+
+ if (type != (char *)row[3])
+ panic("failed stat check on %s:type. %s != %s\n",
+ name, type, row[3]);
+
+ if (!to_number(row[4], tb) || print != tb)
+ panic("failed stat check on %s:print. %d != %d\n",
+ name, print, tb);
+
+ if (!to_number(row[6], ti8) || prec != ti8)
+ panic("failed stat check on %s:prec. %d != %d\n",
+ name, prec, ti8);
+
+ if (!to_number(row[7], tb) || nozero != tb)
+ panic("failed stat check on %s:nozero. %d != %d\n",
+ name, nozero, tb);
+
+ if (!to_number(row[8], tb) || nonan != tb)
+ panic("failed stat check on %s:nonan. %d != %d\n",
+ name, nonan, tb);
+
+ if (!to_number(row[9], tb) || total != tb)
+ panic("failed stat check on %s:total. %d != %d\n",
+ name, total, tb);
+
+ if (!to_number(row[10], tb) || pdf != tb)
+ panic("failed stat check on %s:pdf. %d != %d\n",
+ name, pdf, tb);
+
+ if (!to_number(row[11], tb) || cdf != tb)
+ panic("failed stat check on %s:cdf. %d != %d\n",
+ name, cdf, tb);
+
+ if (!to_number(row[12], ti64) || min != ti64)
+ panic("failed stat check on %s:min. %d != %d\n",
+ name, min, ti64);
+
+ if (!to_number(row[13], ti64) || max != ti64)
+ panic("failed stat check on %s:max. %d != %d\n",
+ name, max, ti64);
+
+ if (!to_number(row[14], tu64) || bktsize != tu64)
+ panic("failed stat check on %s:bktsize. %d != %d\n",
+ name, bktsize, tu64);
+
+ if (!to_number(row[15], tu16) || size != tu16)
+ panic("failed stat check on %s:size. %d != %d\n",
+ name, size, tu16);
+
+ to_number(row[5], prereq);
+ uint16_t statid;
+ to_number(row[0], statid);
+ return statid;
+}
+
- "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin,dt_data) "
+InsertData::InsertData()
+{
+ query = new char[maxsize + 1];
+ size = 0;
+ flush();
+}
+
+InsertData::~InsertData()
+{
+ delete [] query;
+}
+
+void
+InsertData::flush()
+{
+ if (size) {
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ mysql.query(query);
+ if (mysql.error)
+ panic("could not insert data\n%s\n", mysql.error);
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+ }
+
+ query[0] = '\0';
+ size = 0;
+ first = true;
+ strcpy(query, "INSERT INTO "
- size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
++ "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_data) "
+ "values");
+ size = strlen(query);
+}
+
+void
+InsertData::insert()
+{
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
- bin, data);
++ size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")",
+ stat, x, y, MySqlDB.run(), (unsigned long long)tick,
- void
- MySql::output(MainBin *bin)
- {
- MySQL::Connection &mysql = MySqlDB.conn();
-
- if (bin) {
- bin->activate();
- newdata.bin = SetupBin(bin->name());
- } else {
- newdata.bin = 0;
- }
-
- Database::stat_list_t::const_iterator i, end = Database::stats().end();
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *stat = *i;
- if (bin && stat->binned() || !bin && !stat->binned()) {
- stat->visit(*this);
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
- }
- }
- }
-
++ data);
+}
+
+struct InsertSubData
+{
+ uint16_t stat;
+ int16_t x;
+ int16_t y;
+ string name;
+ string descr;
+
+ void setup();
+};
+
+void
+InsertSubData::setup()
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
+ "values(%d,%d,%d,\"%s\",\"%s\")",
+ stat, x, y, name, descr);
+
+ mysql.query(insert);
+// if (mysql.error)
+// panic("could not insert subdata\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+InsertFormula(uint16_t stat, const string &formula)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream insert_formula;
+ ccprintf(insert_formula,
+ "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
+ stat, formula);
+
+ mysql.query(insert_formula);
+// if (mysql.error)
+// panic("could not insert formula\n%s\n", mysql.error);
+
+ stringstream insert_ref;
+ ccprintf(insert_ref,
+ "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+ stat, MySqlDB.run());
+
+ mysql.query(insert_ref);
+// if (mysql.error)
+// panic("could not insert formula reference\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+UpdatePrereq(uint16_t stat, uint16_t prereq)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream update;
+ ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+ prereq, stat);
+ mysql.query(update);
+ if (mysql.error)
+ panic("could not update prereq\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySql::configure()
+{
+ /*
+ * set up all stats!
+ */
+ using namespace Database;
+
+ MySQL::Connection &mysql = MySqlDB.conn();
+
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i) {
+ (*i)->visit(*this);
+ }
+
+ for (i = stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (data->prereq) {
+ uint16_t stat_id = find(data->id);
+ uint16_t prereq_id = find(data->prereq->id);
+ assert(stat_id && prereq_id);
+
+ UpdatePrereq(stat_id, prereq_id);
+ }
+ }
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ configured = true;
+}
+
+
+bool
+MySql::configure(const StatData &data, string type)
+{
+ stat.init();
+ stat.name = data.name;
+ stat.descr = data.desc;
+ stat.type = type;
+ stat.print = data.flags & print;
+ stat.prec = data.precision;
+ stat.nozero = data.flags & nozero;
+ stat.nonan = data.flags & nonan;
+ stat.total = data.flags & total;
+ stat.pdf = data.flags & pdf;
+ stat.cdf = data.flags & cdf;
+
+ return stat.print;
+}
+
+void
+MySql::configure(const ScalarData &data)
+{
+ if (!configure(data, "SCALAR"))
+ return;
+
+ insert(data.id, stat.setup());
+}
+
+void
+MySql::configure(const VectorData &data)
+{
+ if (!configure(data, "VECTOR"))
+ return;
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = 0;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const DistData &data)
+{
+ if (!configure(data, "DIST"))
+ return;
+
+ if (!data.data.fancy) {
+ stat.size = data.data.size;
+ stat.min = data.data.min;
+ stat.max = data.data.max;
+ stat.bktsize = data.data.bucket_size;
+ }
+ insert(data.id, stat.setup());
+}
+
+void
+MySql::configure(const VectorDistData &data)
+{
+ if (!configure(data, "VECTORDIST"))
+ return;
+
+ if (!data.data[0].fancy) {
+ stat.size = data.data[0].size;
+ stat.min = data.data[0].min;
+ stat.max = data.data[0].max;
+ stat.bktsize = data.data[0].bucket_size;
+ }
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = 0;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const Vector2dData &data)
+{
+ if (!configure(data, "VECTOR2D"))
+ return;
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = -1;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ if (!data.y_subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.x = -1;
+ subdata.descr = "";
+ for (int i = 0; i < data.y_subnames.size(); ++i) {
+ subdata.y = i;
+ subdata.name = data.y_subnames[i];
+ if (!subdata.name.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const FormulaData &data)
+{
+ configure(data, "FORMULA");
+ insert(data.id, stat.setup());
+ InsertFormula(find(data.id), data.str());
+}
+
- output(NULL);
- if (!bins().empty()) {
- bin_list_t::iterator i, end = bins().end();
- for (i = bins().begin(); i != end; ++i)
- output(*i);
+bool
+MySql::valid() const
+{
+ return MySqlDB.connected();
+}
+
+void
+MySql::output()
+{
+ using namespace Database;
+ assert(valid());
+
+ if (!configured)
+ configure();
+
+ // store sample #
+ newdata.tick = curTick;
+
++ MySQL::Connection &mysql = MySqlDB.conn();
++
++ Database::stat_list_t::const_iterator i, end = Database::stats().end();
++ for (i = Database::stats().begin(); i != end; ++i) {
++ StatData *stat = *i;
++ stat->visit(*this);
++ if (mysql.commit())
++ panic("could not commit transaction\n%s\n", mysql.error);
+ }
+
+ newdata.flush();
+}
+
+void
+MySql::output(const ScalarData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.x = 0;
+ newdata.y = 0;
+ newdata.data = data.value();
+
+ newdata.insert();
+}
+
+void
+MySql::output(const VectorData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.y = 0;
+
+ const VCounter &cvec = data.value();
+ int size = data.size();
+ for (int x = 0; x < size; x++) {
+ newdata.x = x;
+ newdata.data = cvec[x];
+ newdata.insert();
+ }
+}
+
+void
+MySql::output(const DistDataData &data)
+{
+ const int db_sum = -1;
+ const int db_squares = -2;
+ const int db_samples = -3;
+ const int db_min_val = -4;
+ const int db_max_val = -5;
+ const int db_underflow = -6;
+ const int db_overflow = -7;
+
+ newdata.x = db_sum;
+ newdata.data = data.sum;
+ newdata.insert();
+
+ newdata.x = db_squares;
+ newdata.data = data.squares;
+ newdata.insert();
+
+ newdata.x = db_samples;
+ newdata.data = data.samples;
+ newdata.insert();
+
+ if (data.samples && !data.fancy) {
+ newdata.x = db_min_val;
+ newdata.data = data.min_val;
+ newdata.insert();
+
+ newdata.x = db_max_val;
+ newdata.data = data.max_val;
+ newdata.insert();
+
+ newdata.x = db_underflow;
+ newdata.data = data.underflow;
+ newdata.insert();
+
+ newdata.x = db_overflow;
+ newdata.data = data.overflow;
+ newdata.insert();
+
+ int size = data.cvec.size();
+ for (int x = 0; x < size; x++) {
+ newdata.x = x;
+ newdata.data = data.cvec[x];
+ newdata.insert();
+ }
+ }
+}
+
+
+void
+MySql::output(const DistData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.y = 0;
+ output(data.data);
+}
+
+void
+MySql::output(const VectorDistData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+
+ int size = data.data.size();
+ for (int y = 0; y < size; ++y) {
+ newdata.y = y;
+ output(data.data[y]);
+ }
+}
+
+void
+MySql::output(const Vector2dData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+
+ int index = 0;
+ for (int x = 0; x < data.x; x++) {
+ newdata.x = x;
+ for (int y = 0; y < data.y; y++) {
+ newdata.y = y;
+ newdata.data = data.cvec[index++];
+ newdata.insert();
+ }
+ }
+}
+
+void
+MySql::output(const FormulaData &data)
+{
+}
+
+/*
+ * Implement the visitor
+ */
+void
+MySql::visit(const ScalarData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const VectorData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const DistData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const VectorDistData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const Vector2dData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const FormulaData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+/* namespace Stats */ }
--- /dev/null
- class MainBin;
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_STATS_MYSQL_HH__
+#define __BASE_STATS_MYSQL_HH__
+
+#include <map>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace MySQL { class Connection; }
+namespace Stats {
+
- uint16_t bin;
+class DistDataData;
+class MySqlRun;
+bool MySqlConnected();
+extern MySqlRun MySqlDB;
+
+struct SetupStat
+{
+ std::string name;
+ std::string descr;
+ std::string type;
+ bool print;
+ uint16_t prereq;
+ int8_t prec;
+ bool nozero;
+ bool nonan;
+ bool total;
+ bool pdf;
+ bool cdf;
+ double min;
+ double max;
+ double bktsize;
+ uint16_t size;
+
+ void init();
+ unsigned setup();
+};
+
+class InsertData
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ public:
+ MySqlRun *run;
+
+ public:
+ uint64_t tick;
+ double data;
+ uint16_t stat;
- void output(MainBin *bin);
+ int16_t x;
+ int16_t y;
+
+ public:
+ InsertData();
+ ~InsertData();
+
+ void flush();
+ void insert();
+};
+
+class MySql : public Output
+{
+ protected:
+ SetupStat stat;
+ InsertData newdata;
+ std::list<FormulaData *> formulas;
+ bool configured;
+
+ protected:
+ std::map<int, int> idmap;
+
+ void insert(int sim_id, int db_id)
+ {
+ using namespace std;
+ idmap.insert(make_pair(sim_id, db_id));
+ }
+
+ int find(int sim_id)
+ {
+ using namespace std;
+ map<int,int>::const_iterator i = idmap.find(sim_id);
+ assert(i != idmap.end());
+ return (*i).second;
+ }
+ public:
+ // Implement Visit
+ virtual void visit(const ScalarData &data);
+ virtual void visit(const VectorData &data);
+ virtual void visit(const DistData &data);
+ virtual void visit(const VectorDistData &data);
+ virtual void visit(const Vector2dData &data);
+ virtual void visit(const FormulaData &data);
+
+ // Implement Output
+ virtual bool valid() const;
+ virtual void output();
+
+ protected:
+ // Output helper
+ void output(const DistDataData &data);
+ void output(const ScalarData &data);
+ void output(const VectorData &data);
+ void output(const DistData &data);
+ void output(const VectorDistData &data);
+ void output(const Vector2dData &data);
+ void output(const FormulaData &data);
+
+ void configure();
+ bool configure(const StatData &data, std::string type);
+ void configure(const ScalarData &data);
+ void configure(const VectorData &data);
+ void configure(const DistData &data);
+ void configure(const VectorDistData &data);
+ void configure(const Vector2dData &data);
+ void configure(const FormulaData &data);
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_MYSQL_HH__
--- /dev/null
- #include "base/stats/bin.hh"
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/statistics.hh"
- void
- regBin(MainBin *bin, const std::string &_name)
- {
- bin_list_t::iterator i, end = bins().end();
- for (i = bins().begin(); i != end; ++i)
- if ((*i)->name() == _name)
- panic("re-registering bin %s", _name);
- bins().push_back(bin);
- DPRINTF(Stats, "registering %s\n", _name);
- }
-
+#include "base/stats/statdb.hh"
+
+using namespace std;
+
+namespace Stats {
+namespace Database {
+
+StatData *
+find(void *stat)
+{
+ stat_map_t::const_iterator i = map().find(stat);
+
+ if (i == map().end())
+ return NULL;
+
+ return (*i).second;
+}
+
+void
+regStat(void *stat, StatData *data)
+{
+ if (map().find(stat) != map().end())
+ panic("shouldn't register stat twice!");
+
+ stats().push_back(data);
+
+#ifndef NDEBUG
+ pair<stat_map_t::iterator, bool> result =
+#endif
+ map().insert(make_pair(stat, data));
+ assert(result.second && "this should never fail");
+ assert(map().find(stat) != map().end());
+}
+
+void
+regPrint(void *stat)
+{
+ StatData *data = find(stat);
+ assert(data);
+ data->flags |= print;
+}
+
+TheDatabase &db()
+{
+ static TheDatabase db;
+ return db;
+}
+
+/* namespace Database */ }
+/* namespace Stats */ }
--- /dev/null
- class MainBin;
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_STATS_STATDB_HH__
+#define __BASE_STATS_STATDB_HH__
+
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+class Python;
+
+namespace Stats {
+
- typedef std::list<MainBin *> bin_list_t;
+class StatData;
+
+namespace Database {
+
+typedef std::map<void *, StatData *> stat_map_t;
+typedef std::list<StatData *> stat_list_t;
- bin_list_t bins;
-
+
+// We wrap the database in a struct to make sure it is built in time.
+struct TheDatabase
+{
+ stat_map_t map;
+ stat_list_t stats;
- inline bin_list_t &bins() { return db().bins; }
+};
+
+TheDatabase &db();
+inline stat_map_t &map() { return db().map; }
+inline stat_list_t &stats() { return db().stats; }
- void regBin(MainBin *bin, const std::string &name);
+
+StatData *find(void *stat);
+void regStat(void *stat, StatData *data);
+void regPrint(void *stat);
+
+inline std::string name() { return "Statistics Database"; }
+
+/* namespace Database */ }
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_STATDB_HH__
--- /dev/null
- if (bins().empty() || bins().size() == 1) {
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i)
- (*i)->visit(*this);
- } else {
- ccprintf(*stream, "PRINTING BINNED STATS\n");
- bin_list_t::iterator i, end = bins().end();
- for (i = bins().begin(); i != end; ++i) {
- MainBin *bin = *i;
- bin->activate();
- ccprintf(*stream,"---%s Bin------------\n", bin->name());
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i)
- (*i)->visit(*this);
- ccprintf(*stream, "---------------------------------\n");
- }
- }
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#if defined(__APPLE__)
+#define _GLIBCPP_USE_C99 1
+#endif
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/text.hh"
+#include "base/stats/visit.hh"
+
+using namespace std;
+
+#ifndef NAN
+float __nan();
+/** Define Not a number. */
+#define NAN (__nan())
+/** Need to define __nan() */
+#define __M5_NAN
+#endif
+
+#ifdef __M5_NAN
+float
+__nan()
+{
+ union {
+ uint32_t ui;
+ float f;
+ } nan;
+
+ nan.ui = 0x7fc00000;
+ return nan.f;
+}
+#endif
+
+namespace Stats {
+
+Text::Text()
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+}
+
+Text::Text(std::ostream &stream)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(stream);
+}
+
+Text::Text(const std::string &file)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(file);
+}
+
+
+Text::~Text()
+{
+ if (mystream) {
+ assert(stream);
+ delete stream;
+ }
+}
+
+void
+Text::open(std::ostream &_stream)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = false;
+ stream = &_stream;
+ assert(valid());
+}
+
+void
+Text::open(const std::string &file)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = true;
+ stream = new ofstream(file.c_str(), ios::trunc);
+ assert(valid());
+}
+
+bool
+Text::valid() const
+{
+ return stream != NULL;
+}
+
+void
+Text::output()
+{
+ using namespace Database;
+
+ ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
++ stat_list_t::const_iterator i, end = stats().end();
++ for (i = stats().begin(); i != end; ++i)
++ (*i)->visit(*this);
+ ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
+ stream->flush();
+}
+
+bool
+Text::noOutput(const StatData &data)
+{
+ if (!(data.flags & print))
+ return true;
+
+ if (data.prereq && data.prereq->zero())
+ return true;
+
+ return false;
+}
+
+string
+ValueToString(Result value, int precision, bool compat)
+{
+ stringstream val;
+
+ if (!isnan(value)) {
+ if (precision != -1)
+ val.precision(precision);
+ else if (value == rint(value))
+ val.precision(0);
+
+ val.unsetf(ios::showpoint);
+ val.setf(ios::fixed);
+ val << value;
+ } else {
+ val << (compat ? "<err: div-0>" : "no value");
+ }
+
+ return val.str();
+}
+
+struct ScalarPrint
+{
+ Result value;
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ Result pdf;
+ Result cdf;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+ScalarPrint::operator()(ostream &stream) const
+{
+ if (flags & nozero && value == 0.0 ||
+ flags & nonan && isnan(value))
+ return;
+
+ stringstream pdfstr, cdfstr;
+
+ if (!isnan(pdf))
+ ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
+
+ if (!isnan(cdf))
+ ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
+
+ if (compat && flags & __substat) {
+ ccprintf(stream, "%32s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ } else {
+ ccprintf(stream, "%-40s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ }
+
+ if (descriptions) {
+ if (!desc.empty())
+ ccprintf(stream, " # %s", desc);
+ }
+ stream << endl;
+}
+
+struct VectorPrint
+{
+ string name;
+ string desc;
+ vector<string> subnames;
+ vector<string> subdescs;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ VResult vec;
+ Result total;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+VectorPrint::operator()(std::ostream &stream) const
+{
+ int _size = vec.size();
+ Result _total = 0.0;
+
+ if (flags & (pdf | cdf)) {
+ for (int i = 0; i < _size; ++i) {
+ _total += vec[i];
+ }
+ }
+
+ string base = name + (compat ? "_" : "::");
+
+ ScalarPrint print;
+ print.name = name;
+ print.desc = desc;
+ print.precision = precision;
+ print.descriptions = descriptions;
+ print.flags = flags;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ bool havesub = !subnames.empty();
+
+ if (_size == 1) {
+ print.value = vec[0];
+ print(stream);
+ } else if (!compat) {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && (i >= subnames.size() || subnames[i].empty()))
+ continue;
+
+ print.name = base + (havesub ? subnames[i] : to_string(i));
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total && (flags & pdf)) {
+ print.pdf = vec[i] / _total;
+ print.cdf += print.pdf;
+ }
+
+ print(stream);
+ }
+
+ if (flags & ::Stats::total) {
+ print.name = base + "total";
+ print.desc = desc;
+ print.value = total;
+ print(stream);
+ }
+ } else {
+ if (flags & ::Stats::total) {
+ print.value = total;
+ print(stream);
+ }
+
+ Result _pdf = 0.0;
+ Result _cdf = 0.0;
+ if (flags & dist) {
+ ccprintf(stream, "%s.start_dist\n", name);
+ for (int i = 0; i < _size; ++i) {
+ print.name = havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.flags |= __substat;
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ }
+
+ if (flags & pdf)
+ print.pdf = _pdf;
+ if (flags & cdf)
+ print.cdf = _cdf;
+
+ print(stream);
+ }
+ ccprintf(stream, "%s.end_dist\n", name);
+ } else {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && subnames[i].empty())
+ continue;
+
+ print.name = base;
+ print.name += havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ } else {
+ _pdf = _cdf = NAN;
+ }
+
+ if (flags & pdf) {
+ print.pdf = _pdf;
+ print.cdf = _cdf;
+ }
+
+ print(stream);
+ }
+ }
+ }
+}
+
+struct DistPrint
+{
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+
+ Result min_val;
+ Result max_val;
+ Result underflow;
+ Result overflow;
+ VResult vec;
+ Result sum;
+ Result squares;
+ Result samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+DistPrint::operator()(ostream &stream) const
+{
+ if (fancy) {
+ ScalarPrint print;
+ string base = name + (compat ? "_" : "::");
+
+ print.precision = precision;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.desc = desc;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print.name = base + "mean";
+ print.value = samples ? sum / samples : NAN;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = samples ? sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0))) : NAN;
+ print(stream);
+
+ print.name = "**Ignore: " + base + "TOT";
+ print.value = samples;
+ print(stream);
+ return;
+ }
+
+ assert(size == vec.size());
+
+ Result total = 0.0;
+
+ total += underflow;
+ for (int i = 0; i < size; ++i)
+ total += vec[i];
+ total += overflow;
+
+ string base = name + (compat ? "." : "::");
+
+ ScalarPrint print;
+ print.desc = compat ? "" : desc;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (compat) {
+ ccprintf(stream, "%-42s", base + "start_dist");
+ if (descriptions && !desc.empty())
+ ccprintf(stream, " # %s", desc);
+ stream << endl;
+ }
+
+ print.name = base + "samples";
+ print.value = samples;
+ print(stream);
+
+ print.name = base + "min_value";
+ print.value = min_val;
+ print(stream);
+
+ if (!compat || underflow > 0.0) {
+ print.name = base + "underflows";
+ print.value = underflow;
+ if (!compat && total) {
+ print.pdf = underflow / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+
+ if (!compat) {
+ for (int i = 0; i < size; ++i) {
+ stringstream namestr;
+ namestr << name;
+
+ Counter low = i * bucket_size + min;
+ Counter high = ::min(low + bucket_size, max);
+ namestr << low;
+ if (low < high)
+ namestr << "-" << high;
+
+ print.name = namestr.str();
+ print.value = vec[i];
+ if (total) {
+ print.pdf = vec[i] / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+ } else {
+ Counter _min;
+ Result _pdf;
+ Result _cdf = 0.0;
+
+ print.flags = flags | __substat;
+
+ for (int i = 0; i < size; ++i) {
+ if (flags & nozero && vec[i] == 0.0 ||
+ flags & nonan && isnan(vec[i]))
+ continue;
+
+ _min = i * bucket_size + min;
+ _pdf = vec[i] / total * 100.0;
+ _cdf += _pdf;
+
+
+ print.name = ValueToString(_min, 0, compat);
+ print.value = vec[i];
+ print.pdf = (flags & pdf) ? _pdf : NAN;
+ print.cdf = (flags & cdf) ? _cdf : NAN;
+ print(stream);
+ }
+
+ print.flags = flags;
+ }
+
+ if (!compat || overflow > 0.0) {
+ print.name = base + "overflows";
+ print.value = overflow;
+ if (!compat && total) {
+ print.pdf = overflow / total;
+ print.cdf += print.pdf;
+ } else {
+ print.pdf = NAN;
+ print.cdf = NAN;
+ }
+ print(stream);
+ }
+
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (!compat) {
+ print.name = base + "total";
+ print.value = total;
+ print(stream);
+ }
+
+ print.name = base + "max_value";
+ print.value = max_val;
+ print(stream);
+
+ if (!compat && samples != 0) {
+ print.name = base + "mean";
+ print.value = sum / samples;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0)));
+ print(stream);
+ }
+
+ if (compat)
+ ccprintf(stream, "%send_dist\n\n", base);
+}
+
+void
+Text::visit(const ScalarData &data)
+{
+ if (noOutput(data))
+ return;
+
+ ScalarPrint print;
+ print.value = data.result();
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorData &data)
+{
+ if (noOutput(data))
+ return;
+
+ int size = data.size();
+ VectorPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.vec = data.result();
+ print.total = data.total();
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty()) {
+ print.subnames = data.subnames;
+ print.subnames.resize(size);
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty() &&
+ !data.subdescs[i].empty()) {
+ print.subdescs = data.subdescs;
+ print.subdescs.resize(size);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ print(*stream);
+}
+
+void
+Text::visit(const Vector2dData &data)
+{
+ if (noOutput(data))
+ return;
+
+ bool havesub = false;
+ VectorPrint print;
+
+ print.subnames = data.y_subnames;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < data.x; ++i)
+ if (!data.subnames[i].empty())
+ havesub = true;
+ }
+
+ VResult tot_vec(data.y);
+ Result super_total = 0.0;
+ for (int i = 0; i < data.x; ++i) {
+ if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
+ continue;
+
+ int iy = i * data.y;
+ VResult yvec(data.y);
+
+ Result total = 0.0;
+ for (int j = 0; j < data.y; ++j) {
+ yvec[j] = data.cvec[iy + j];
+ tot_vec[j] += yvec[j];
+ total += yvec[j];
+ super_total += yvec[j];
+ }
+
+ print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
+ print.desc = data.desc;
+ print.vec = yvec;
+ print.total = total;
+ print(*stream);
+ }
+
+ if ((data.flags & ::Stats::total) && (data.x > 1)) {
+ print.name = data.name;
+ print.desc = data.desc;
+ print.vec = tot_vec;
+ print.total = super_total;
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const DistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ DistPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data.min_val;
+ print.max_val = data.data.max_val;
+ print.underflow = data.data.underflow;
+ print.overflow = data.data.overflow;
+ print.vec.resize(data.data.cvec.size());
+ for (int i = 0; i < print.vec.size(); ++i)
+ print.vec[i] = (Result)data.data.cvec[i];
+ print.sum = data.data.sum;
+ print.squares = data.data.squares;
+ print.samples = data.data.samples;
+
+ print.min = data.data.min;
+ print.max = data.data.max;
+ print.bucket_size = data.data.bucket_size;
+ print.size = data.data.size;
+ print.fancy = data.data.fancy;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorDistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ for (int i = 0; i < data.size(); ++i) {
+ DistPrint print;
+
+ print.name = data.name +
+ (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
+ print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data[i].min_val;
+ print.max_val = data.data[i].max_val;
+ print.underflow = data.data[i].underflow;
+ print.overflow = data.data[i].overflow;
+ print.vec.resize(data.data[i].cvec.size());
+ for (int j = 0; j < print.vec.size(); ++j)
+ print.vec[j] = (Result)data.data[i].cvec[j];
+ print.sum = data.data[i].sum;
+ print.squares = data.data[i].squares;
+ print.samples = data.data[i].samples;
+
+ print.min = data.data[i].min;
+ print.max = data.data[i].max;
+ print.bucket_size = data.data[i].bucket_size;
+ print.size = data.data[i].size;
+ print.fancy = data.data[i].fancy;
+
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const FormulaData &data)
+{
+ visit((const VectorData &)data);
+}
+
+/* namespace Stats */ }
--- /dev/null
- void binout();
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_STATS_TEXT_HH__
+#define __BASE_STATS_TEXT_HH__
+
+#include <iosfwd>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace Stats {
+
+class Text : public Output
+{
+ protected:
+ bool mystream;
+ std::ostream *stream;
+
+ protected:
+ bool noOutput(const StatData &data);
+
+ public:
+ bool compat;
+ bool descriptions;
+
+ public:
+ Text();
+ Text(std::ostream &stream);
+ Text(const std::string &file);
+ ~Text();
+
+ void open(std::ostream &stream);
+ void open(const std::string &file);
+
+ // Implement Visit
+ virtual void visit(const ScalarData &data);
+ virtual void visit(const VectorData &data);
+ virtual void visit(const DistData &data);
+ virtual void visit(const VectorDistData &data);
+ virtual void visit(const Vector2dData &data);
+ virtual void visit(const FormulaData &data);
+
+ // Implement Output
+ virtual bool valid() const;
+ virtual void output();
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_TEXT_HH__
--- /dev/null
- if (system->kernelBinning->fnbin) {
- assert(thread->getKernelStats());
- system->kernelBinning->execute(tc, inst);
- }
-
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ */
+
+#include "arch/utility.hh"
+#include "base/cprintf.hh"
+#include "base/inifile.hh"
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "base/range.hh"
+#include "base/stats/events.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "cpu/profile.hh"
+#include "cpu/sampler/sampler.hh"
+#include "cpu/simple/base.hh"
+#include "cpu/simple_thread.hh"
+#include "cpu/smt.hh"
+#include "cpu/static_inst.hh"
+#include "cpu/thread_context.hh"
+#include "kern/kernel_stats.hh"
+#include "mem/packet_impl.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "sim/debug.hh"
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+#include "sim/sim_object.hh"
+#include "sim/stats.hh"
+
+#if FULL_SYSTEM
+#include "base/remote_gdb.hh"
+#include "sim/system.hh"
+#include "arch/tlb.hh"
+#include "arch/stacktrace.hh"
+#include "arch/vtophys.hh"
+#else // !FULL_SYSTEM
+#include "mem/mem_object.hh"
+#endif // FULL_SYSTEM
+
+using namespace std;
+using namespace TheISA;
+
+BaseSimpleCPU::BaseSimpleCPU(Params *p)
+ : BaseCPU(p), mem(p->mem), thread(NULL)
+{
+#if FULL_SYSTEM
+ thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
+#else
+ thread = new SimpleThread(this, /* thread_num */ 0, p->process,
+ /* asid */ 0, mem);
+#endif // !FULL_SYSTEM
+
+ thread->setStatus(ThreadContext::Suspended);
+
+ tc = thread->getTC();
+
+ numInst = 0;
+ startNumInst = 0;
+ numLoad = 0;
+ startNumLoad = 0;
+ lastIcacheStall = 0;
+ lastDcacheStall = 0;
+
+ threadContexts.push_back(tc);
+}
+
+BaseSimpleCPU::~BaseSimpleCPU()
+{
+}
+
+void
+BaseSimpleCPU::deallocateContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
+}
+
+
+void
+BaseSimpleCPU::haltContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
+}
+
+
+void
+BaseSimpleCPU::regStats()
+{
+ using namespace Stats;
+
+ BaseCPU::regStats();
+
+ numInsts
+ .name(name() + ".num_insts")
+ .desc("Number of instructions executed")
+ ;
+
+ numMemRefs
+ .name(name() + ".num_refs")
+ .desc("Number of memory references")
+ ;
+
+ notIdleFraction
+ .name(name() + ".not_idle_fraction")
+ .desc("Percentage of non-idle cycles")
+ ;
+
+ idleFraction
+ .name(name() + ".idle_fraction")
+ .desc("Percentage of idle cycles")
+ ;
+
+ icacheStallCycles
+ .name(name() + ".icache_stall_cycles")
+ .desc("ICache total stall cycles")
+ .prereq(icacheStallCycles)
+ ;
+
+ dcacheStallCycles
+ .name(name() + ".dcache_stall_cycles")
+ .desc("DCache total stall cycles")
+ .prereq(dcacheStallCycles)
+ ;
+
+ icacheRetryCycles
+ .name(name() + ".icache_retry_cycles")
+ .desc("ICache total retry cycles")
+ .prereq(icacheRetryCycles)
+ ;
+
+ dcacheRetryCycles
+ .name(name() + ".dcache_retry_cycles")
+ .desc("DCache total retry cycles")
+ .prereq(dcacheRetryCycles)
+ ;
+
+ idleFraction = constant(1.0) - notIdleFraction;
+}
+
+void
+BaseSimpleCPU::resetStats()
+{
+ startNumInst = numInst;
+ // notIdleFraction = (_status != Idle);
+}
+
+void
+BaseSimpleCPU::serialize(ostream &os)
+{
+ BaseCPU::serialize(os);
+ SERIALIZE_SCALAR(inst);
+ nameOut(os, csprintf("%s.xc", name()));
+ thread->serialize(os);
+}
+
+void
+BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion)
+{
+ BaseCPU::unserialize(cp, section);
+ UNSERIALIZE_SCALAR(inst);
+ thread->unserialize(cp, csprintf("%s.xc", section));
+}
+
+void
+change_thread_state(int thread_number, int activate, int priority)
+{
+}
+
+Fault
+BaseSimpleCPU::copySrcTranslate(Addr src)
+{
+#if 0
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ int offset = src & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (src & PageMask) != ((src + blk_size) & PageMask) &&
+ (src >> 40) != 0xfffffc) {
+ warn("Copied block source spans pages %x.", src);
+ no_warn = false;
+ }
+
+ memReq->reset(src & ~(blk_size - 1), blk_size);
+
+ // translate to physical address
+ Fault fault = thread->translateDataReadReq(req);
+
+ if (fault == NoFault) {
+ thread->copySrcAddr = src;
+ thread->copySrcPhysAddr = memReq->paddr + offset;
+ } else {
+ assert(!fault->isAlignmentFault());
+
+ thread->copySrcAddr = 0;
+ thread->copySrcPhysAddr = 0;
+ }
+ return fault;
+#else
+ return NoFault;
+#endif
+}
+
+Fault
+BaseSimpleCPU::copy(Addr dest)
+{
+#if 0
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ uint8_t data[blk_size];
+ //assert(thread->copySrcAddr);
+ int offset = dest & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (dest & PageMask) != ((dest + blk_size) & PageMask) &&
+ (dest >> 40) != 0xfffffc) {
+ no_warn = false;
+ warn("Copied block destination spans pages %x. ", dest);
+ }
+
+ memReq->reset(dest & ~(blk_size -1), blk_size);
+ // translate to physical address
+ Fault fault = thread->translateDataWriteReq(req);
+
+ if (fault == NoFault) {
+ Addr dest_addr = memReq->paddr + offset;
+ // Need to read straight from memory since we have more than 8 bytes.
+ memReq->paddr = thread->copySrcPhysAddr;
+ thread->mem->read(memReq, data);
+ memReq->paddr = dest_addr;
+ thread->mem->write(memReq, data);
+ if (dcacheInterface) {
+ memReq->cmd = Copy;
+ memReq->completionEvent = NULL;
+ memReq->paddr = thread->copySrcPhysAddr;
+ memReq->dest = dest_addr;
+ memReq->size = 64;
+ memReq->time = curTick;
+ memReq->flags &= ~INST_READ;
+ dcacheInterface->access(memReq);
+ }
+ }
+ else
+ assert(!fault->isAlignmentFault());
+
+ return fault;
+#else
+ panic("copy not implemented");
+ return NoFault;
+#endif
+}
+
+#if FULL_SYSTEM
+Addr
+BaseSimpleCPU::dbg_vtophys(Addr addr)
+{
+ return vtophys(tc, addr);
+}
+#endif // FULL_SYSTEM
+
+#if FULL_SYSTEM
+void
+BaseSimpleCPU::post_interrupt(int int_num, int index)
+{
+ BaseCPU::post_interrupt(int_num, index);
+
+ if (thread->status() == ThreadContext::Suspended) {
+ DPRINTF(IPI,"Suspended Processor awoke\n");
+ thread->activate();
+ }
+}
+#endif // FULL_SYSTEM
+
+void
+BaseSimpleCPU::checkForInterrupts()
+{
+#if FULL_SYSTEM
+ if (checkInterrupts && check_interrupts() && !thread->inPalMode()) {
+ int ipl = 0;
+ int summary = 0;
+ checkInterrupts = false;
+
+ if (thread->readMiscReg(IPR_SIRR)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ uint64_t interrupts = thread->cpu->intr_status();
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
+ if (interrupts & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = i;
+ summary |= (ULL(1) << i);
+ }
+ }
+
+ if (thread->readMiscReg(IPR_ASTRR))
+ panic("asynchronous traps not implemented\n");
+
+ if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) {
+ thread->setMiscReg(IPR_ISR, summary);
+ thread->setMiscReg(IPR_INTID, ipl);
+
+ Fault(new InterruptFault)->invoke(tc);
+
+ DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+ thread->readMiscReg(IPR_IPLR), ipl, summary);
+ }
+ }
+#endif
+}
+
+
+Fault
+BaseSimpleCPU::setupFetchRequest(Request *req)
+{
+ // set up memory request for instruction fetch
+ DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(),
+ thread->readNextPC(),thread->readNextNPC());
+
+ req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst),
+ (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0,
+ thread->readPC());
+
+ Fault fault = thread->translateInstReq(req);
+
+ return fault;
+}
+
+
+void
+BaseSimpleCPU::preExecute()
+{
+ // maintain $r0 semantics
+ thread->setIntReg(ZeroReg, 0);
+#if THE_ISA == ALPHA_ISA
+ thread->setFloatReg(ZeroReg, 0.0);
+#endif // ALPHA_ISA
+
+ // keep an instruction count
+ numInst++;
+ numInsts++;
+
+ thread->funcExeInst++;
+
+ // check for instruction-count-based events
+ comInstEventQueue[0]->serviceEvents(numInst);
+
+ // decode the instruction
+ inst = gtoh(inst);
+ curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC()));
+
+ traceData = Trace::getInstRecord(curTick, tc, this, curStaticInst,
+ thread->readPC());
+
+ DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n",
+ curStaticInst->getName(), curStaticInst->getOpcode(),
+ curStaticInst->machInst);
+
+#if FULL_SYSTEM
+ thread->setInst(inst);
+#endif // FULL_SYSTEM
+}
+
+void
+BaseSimpleCPU::postExecute()
+{
+#if FULL_SYSTEM
+ if (thread->profile) {
+ bool usermode =
+ (thread->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
+ thread->profilePC = usermode ? 1 : thread->readPC();
+ ProfileNode *node = thread->profile->consume(tc, inst);
+ if (node)
+ thread->profileNode = node;
+ }
+#endif
+
+ if (curStaticInst->isMemRef()) {
+ numMemRefs++;
+ }
+
+ if (curStaticInst->isLoad()) {
+ ++numLoad;
+ comLoadEventQueue[0]->serviceEvents(numLoad);
+ }
+
+ traceFunctions(thread->readPC());
+
+ if (traceData) {
+ traceData->finalize();
+ }
+}
+
+
+void
+BaseSimpleCPU::advancePC(Fault fault)
+{
+ if (fault != NoFault) {
+#if FULL_SYSTEM
+ fault->invoke(tc);
+#else // !FULL_SYSTEM
+ fatal("fault (%s) detected @ PC %08p", fault->name(), thread->readPC());
+#endif // FULL_SYSTEM
+ }
+ else {
+ // go to the next instruction
+ thread->setPC(thread->readNextPC());
+#if THE_ISA == ALPHA_ISA
+ thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+#else
+ thread->setNextPC(thread->readNextNPC());
+ thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+#endif
+
+ }
+
+#if FULL_SYSTEM
+ Addr oldpc;
+ do {
+ oldpc = thread->readPC();
+ system->pcEventQueue.service(tc);
+ } while (oldpc != thread->readPC());
+#endif
+}
+
--- /dev/null
- const char *modestr[] = { "kernel", "user", "idle", "interrupt" };
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Lisa Hsu
+ * Nathan Binkert
+ */
+
+#include <map>
+#include <stack>
+#include <string>
+
+#include "arch/alpha/osfpal.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "kern/kernel_stats.hh"
+#include "kern/tru64/tru64_syscalls.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace Stats;
+
+namespace Kernel {
+
- bin_int = system->params()->bin_int;
++const char *modestr[] = { "kernel", "user", "idle" };
+
+Statistics::Statistics(System *system)
+ : idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
+ iplLast(0), iplLastTick(0)
+{
- assert(themode == kernel || themode == interrupt);
+}
+
+void
+Statistics::regStats(const string &_name)
+{
+ myname = _name;
+
+ _arm
+ .name(name() + ".inst.arm")
+ .desc("number of arm instructions executed")
+ ;
+
+ _quiesce
+ .name(name() + ".inst.quiesce")
+ .desc("number of quiesce instructions executed")
+ ;
+
+ _ivlb
+ .name(name() + ".inst.ivlb")
+ .desc("number of ivlb instructions executed")
+ ;
+
+ _ivle
+ .name(name() + ".inst.ivle")
+ .desc("number of ivle instructions executed")
+ ;
+
+ _hwrei
+ .name(name() + ".inst.hwrei")
+ .desc("number of hwrei instructions executed")
+ ;
+
+ _iplCount
+ .init(32)
+ .name(name() + ".ipl_count")
+ .desc("number of times we switched to this ipl")
+ .flags(total | pdf | nozero | nonan)
+ ;
+
+ _iplGood
+ .init(32)
+ .name(name() + ".ipl_good")
+ .desc("number of times we switched to this ipl from a different ipl")
+ .flags(total | pdf | nozero | nonan)
+ ;
+
+ _iplTicks
+ .init(32)
+ .name(name() + ".ipl_ticks")
+ .desc("number of cycles we spent at this ipl")
+ .flags(total | pdf | nozero | nonan)
+ ;
+
+ _iplUsed
+ .name(name() + ".ipl_used")
+ .desc("fraction of swpipl calls that actually changed the ipl")
+ .flags(total | nozero | nonan)
+ ;
+
+ _iplUsed = _iplGood / _iplCount;
+
+ _callpal
+ .init(256)
+ .name(name() + ".callpal")
+ .desc("number of callpals executed")
+ .flags(total | pdf | nozero | nonan)
+ ;
+
+ for (int i = 0; i < PAL::NumCodes; ++i) {
+ const char *str = PAL::name(i);
+ if (str)
+ _callpal.subname(i, str);
+ }
+
+ _syscall
+ .init(SystemCalls<Tru64>::Number)
+ .name(name() + ".syscall")
+ .desc("number of syscalls executed")
+ .flags(total | pdf | nozero | nonan)
+ ;
+
+ for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) {
+ const char *str = SystemCalls<Tru64>::name(i);
+ if (str) {
+ _syscall.subname(i, str);
+ }
+ }
+
+ _mode
+ .init(cpu_mode_num)
+ .name(name() + ".mode_switch")
+ .desc("number of protection mode switches")
+ ;
+
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _mode.subname(i, modestr[i]);
+
+ _modeGood
+ .init(cpu_mode_num)
+ .name(name() + ".mode_good")
+ ;
+
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeGood.subname(i, modestr[i]);
+
+ _modeFraction
+ .name(name() + ".mode_switch_good")
+ .desc("fraction of useful protection mode switches")
+ .flags(total)
+ ;
+
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeFraction.subname(i, modestr[i]);
+
+ _modeFraction = _modeGood / _mode;
+
+ _modeTicks
+ .init(cpu_mode_num)
+ .name(name() + ".mode_ticks")
+ .desc("number of ticks spent at the given mode")
+ .flags(pdf)
+ ;
+ for (int i = 0; i < cpu_mode_num; ++i)
+ _modeTicks.subname(i, modestr[i]);
+
+ _swap_context
+ .name(name() + ".swap_context")
+ .desc("number of times the context was actually changed")
+ ;
+}
+
+void
+Statistics::setIdleProcess(Addr idlepcbb, ThreadContext *tc)
+{
- tc->getSystemPtr()->kernelBinning->changeMode(newmode);
-
++ assert(themode == kernel);
+ idleProcess = idlepcbb;
+ themode = idle;
+ changeMode(themode, tc);
+}
+
+void
+Statistics::changeMode(cpu_mode newmode, ThreadContext *tc)
+{
+ _mode[newmode]++;
+
+ if (newmode == themode)
+ return;
+
+ DPRINTF(Context, "old mode=%-8s new mode=%-8s\n",
+ modestr[themode], modestr[newmode]);
+
+ _modeGood[newmode]++;
+ _modeTicks[themode] += curTick - lastModeTick;
+
- if ((newmode == kernel || newmode == interrupt) &&
- pcbb == idleProcess)
+ lastModeTick = curTick;
+ themode = newmode;
+}
+
+void
+Statistics::swpipl(int ipl)
+{
+ assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n");
+
+ _iplCount[ipl]++;
+
+ if (ipl == iplLast)
+ return;
+
+ _iplGood[ipl]++;
+ _iplTicks[iplLast] += curTick - iplLastTick;
+ iplLastTick = curTick;
+ iplLast = ipl;
+}
+
+void
+Statistics::mode(cpu_mode newmode, ThreadContext *tc)
+{
+ Addr pcbb = tc->readMiscReg(AlphaISA::IPR_PALtemp23);
+
- if (bin_int == false && newmode == interrupt)
- newmode = kernel;
-
++ if (newmode == kernel && pcbb == idleProcess)
+ newmode = idle;
+
-
- case PAL::swpctx:
- if (tc->getSystemPtr()->kernelBinning)
- tc->getSystemPtr()->kernelBinning->palSwapContext(tc);
- break;
+ changeMode(newmode, tc);
+}
+
+void
+Statistics::context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc)
+{
+ assert(themode != user);
+
+ _swap_context++;
+ changeMode(newpcbb == idleProcess ? idle : kernel, tc);
+}
+
+void
+Statistics::callpal(int code, ThreadContext *tc)
+{
+ if (!PAL::name(code))
+ return;
+
+ _callpal[code]++;
+
+ switch (code) {
+ case PAL::callsys: {
+ int number = tc->readIntReg(0);
+ if (SystemCalls<Tru64>::validSyscallNumber(number)) {
+ int cvtnum = SystemCalls<Tru64>::convert(number);
+ _syscall[cvtnum]++;
+ }
+ } break;
+ }
+}
+
+void
+Statistics::serialize(ostream &os)
+{
+ int exemode = themode;
+ SERIALIZE_SCALAR(exemode);
+ SERIALIZE_SCALAR(idleProcess);
+ SERIALIZE_SCALAR(iplLast);
+ SERIALIZE_SCALAR(iplLastTick);
+ SERIALIZE_SCALAR(lastModeTick);
+}
+
+void
+Statistics::unserialize(Checkpoint *cp, const string §ion)
+{
+ int exemode;
+ UNSERIALIZE_SCALAR(exemode);
+ UNSERIALIZE_SCALAR(idleProcess);
+ UNSERIALIZE_SCALAR(iplLast);
+ UNSERIALIZE_SCALAR(iplLastTick);
+ UNSERIALIZE_SCALAR(lastModeTick);
+ themode = (cpu_mode)exemode;
+}
+
+/* end namespace Kernel */ }
--- /dev/null
- enum cpu_mode { kernel, user, idle, interrupt, cpu_mode_num };
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Lisa Hsu
+ * Nathan Binkert
+ */
+
+#ifndef __KERNEL_STATS_HH__
+#define __KERNEL_STATS_HH__
+
+#include <map>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include "cpu/static_inst.hh"
+
+class BaseCPU;
+class ThreadContext;
+class FnEvent;
+// What does kernel stats expect is included?
+class System;
+
+namespace Kernel {
+
- class Binning
- {
- private:
- std::string myname;
- System *system;
-
- private:
- // lisa's binning stuff
- struct fnCall
- {
- Stats::MainBin *myBin;
- std::string name;
- };
-
- struct SWContext
- {
- Counter calls;
- std::stack<fnCall *> callStack;
- };
-
- std::map<const std::string, Stats::MainBin *> fnBins;
- std::map<const Addr, SWContext *> swCtxMap;
-
- std::multimap<const std::string, std::string> callerMap;
- void populateMap(std::string caller, std::string callee);
-
- std::vector<FnEvent *> fnEvents;
-
- Stats::Scalar<> fnCalls;
-
- Stats::MainBin *getBin(const std::string &name);
- bool findCaller(std::string, std::string) const;
-
- SWContext *findContext(Addr pcb);
- bool addContext(Addr pcb, SWContext *ctx)
- {
- return (swCtxMap.insert(std::make_pair(pcb, ctx))).second;
- }
-
- void remContext(Addr pcb)
- {
- swCtxMap.erase(pcb);
- }
-
- void dumpState() const;
-
- SWContext *swctx;
- std::vector<std::string> binned_fns;
-
- private:
- Stats::MainBin *modeBin[cpu_mode_num];
-
- public:
- const bool bin;
- const bool fnbin;
-
- cpu_mode themode;
- void palSwapContext(ThreadContext *tc);
- void execute(ThreadContext *tc, StaticInstPtr inst);
- void call(ThreadContext *tc, Stats::MainBin *myBin);
- void changeMode(cpu_mode mode);
-
- public:
- Binning(System *sys);
- virtual ~Binning();
-
- const std::string name() const { return myname; }
- void regStats(const std::string &name);
-
- public:
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
- };
-
++enum cpu_mode { kernel, user, idle, cpu_mode_num };
+extern const char *modestr[];
+
- private:
- friend class Binning;
-
+class Statistics : public Serializable
+{
- bool bin_int;
+ private:
+ std::string myname;
+
+ Addr idleProcess;
+ cpu_mode themode;
+ Tick lastModeTick;
+
+ void changeMode(cpu_mode newmode, ThreadContext *tc);
+
+ private:
+ Stats::Scalar<> _arm;
+ Stats::Scalar<> _quiesce;
+ Stats::Scalar<> _ivlb;
+ Stats::Scalar<> _ivle;
+ Stats::Scalar<> _hwrei;
+
+ Stats::Vector<> _iplCount;
+ Stats::Vector<> _iplGood;
+ Stats::Vector<> _iplTicks;
+ Stats::Formula _iplUsed;
+
+ Stats::Vector<> _callpal;
+ Stats::Vector<> _syscall;
+// Stats::Vector<> _faults;
+
+ Stats::Vector<> _mode;
+ Stats::Vector<> _modeGood;
+ Stats::Formula _modeFraction;
+ Stats::Vector<> _modeTicks;
+
+ Stats::Scalar<> _swap_context;
+
+ private:
+ int iplLast;
+ Tick iplLastTick;
+
+ public:
+ Statistics(System *system);
+
+ const std::string name() const { return myname; }
+ void regStats(const std::string &name);
+
+ public:
+ void arm() { _arm++; }
+ void quiesce() { _quiesce++; }
+ void ivlb() { _ivlb++; }
+ void ivle() { _ivle++; }
+ void hwrei() { _hwrei++; }
+ void swpipl(int ipl);
+ void mode(cpu_mode newmode, ThreadContext *tc);
+ void context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc);
+ void callpal(int code, ThreadContext *tc);
+
+ void setIdleProcess(Addr idle, ThreadContext *tc);
+
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
+};
+
+/* end namespace Kernel */ }
+
+#endif // __KERNEL_STATS_HH__
--- /dev/null
-
- FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- Stats::MainBin *bin)
- : PCEvent(q, desc, addr), _name(desc), mybin(bin)
- {
- }
-
- void
- FnEvent::process(ThreadContext *tc)
- {
- if (tc->misspeculating())
- return;
-
- tc->getSystemPtr()->kernelBinning->call(tc, mybin);
- }
-
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Lisa Hsu
+ * Nathan Binkert
+ */
+
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+#include "kern/kernel_stats.hh"
+#include "kern/system_events.hh"
+#include "sim/system.hh"
+
+using namespace TheISA;
+
+void
+SkipFuncEvent::process(ThreadContext *tc)
+{
+ Addr newpc = tc->readIntReg(ReturnAddressReg);
+
+ DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
+ tc->readPC(), newpc);
+
+ tc->setPC(newpc);
+ tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+/*
+ BranchPred *bp = tc->getCpuPtr()->getBranchPred();
+ if (bp != NULL) {
+ bp->popRAS(tc->getThreadNum());
+ }
+*/
+}
+
-
- void
- InterruptStartEvent::process(ThreadContext *tc)
- {
- if (tc->getKernelStats())
- tc->getKernelStats()->mode(Kernel::interrupt, tc);
- }
-
- void
- InterruptEndEvent::process(ThreadContext *tc)
- {
- // We go back to kernel, if we are user, inside the rti
- // pal code we will get switched to user because of the ICM write
- if (tc->getKernelStats())
- tc->getKernelStats()->mode(Kernel::kernel, tc);
- }
+void
+IdleStartEvent::process(ThreadContext *tc)
+{
+ if (tc->getKernelStats())
+ tc->getKernelStats()->setIdleProcess(
+ tc->readMiscReg(AlphaISA::IPR_PALtemp23), tc);
+ remove();
+}
--- /dev/null
- class FnEvent : public PCEvent
- {
- public:
- FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- Stats::MainBin *bin);
- virtual void process(ThreadContext *tc);
- std::string myname() const { return _name; }
-
- private:
- std::string _name;
- Stats::MainBin *mybin;
- };
-
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Lisa Hsu
+ * Ali Saidi
+ */
+
+#ifndef __SYSTEM_EVENTS_HH__
+#define __SYSTEM_EVENTS_HH__
+
+#include "cpu/pc_event.hh"
+
+class System;
+
+class SkipFuncEvent : public PCEvent
+{
+ public:
+ SkipFuncEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+ : PCEvent(q, desc, addr)
+ {}
+ virtual void process(ThreadContext *tc);
+};
+
- class InterruptStartEvent : public PCEvent
- {
- public:
- InterruptStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
- : PCEvent(q, desc, addr)
- {}
- virtual void process(ThreadContext *tc);
- };
-
- class InterruptEndEvent : public PCEvent
- {
- public:
- InterruptEndEvent(PCEventQueue *q, const std::string &desc, Addr addr)
- : PCEvent(q, desc, addr)
- {}
- virtual void process(ThreadContext *tc);
- };
-
-
+class IdleStartEvent : public PCEvent
+{
+ public:
+ IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+ : PCEvent(q, desc, addr)
+ {}
+ virtual void process(ThreadContext *tc);
+};
+
+#endif // __SYSTEM_EVENTS_HH__
--- /dev/null
- bin = Param.Bool(False, "is this system binned")
- binned_fns = VectorParam.String([], "functions broken down and binned")
+from m5 import build_env
+from m5.config import *
+
+class System(SimObject):
+ type = 'System'
+ physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ if build_env['FULL_SYSTEM']:
+ boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
+ "boot processor frequency")
+ init_param = Param.UInt64(0, "numerical value to pass into simulator")
+ boot_osflags = Param.String("a", "boot flags to pass to the kernel")
+ kernel = Param.String("file that contains the kernel code")
+ readfile = Param.String("", "file to read startup script from")
+
+class AlphaSystem(System):
+ type = 'AlphaSystem'
+ console = Param.String("file that contains the console code")
+ pal = Param.String("file that contains palcode")
+ system_type = Param.UInt64("Type of system we are emulating")
+ system_rev = Param.UInt64("Revision of system we are emulating")
--- /dev/null
-
- delete kernelBinning;
+/*
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ * Lisa Hsu
+ * Nathan Binkert
+ * Ali Saidi
+ */
+
+#include "arch/isa_traits.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "mem/mem_object.hh"
+#include "mem/physical.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "sim/system.hh"
+#if FULL_SYSTEM
+#include "arch/vtophys.hh"
+#include "base/remote_gdb.hh"
+#include "kern/kernel_stats.hh"
+#endif
+
+using namespace std;
+using namespace TheISA;
+
+vector<System *> System::systemList;
+
+int System::numSystemsRunning = 0;
+
+System::System(Params *p)
+ : SimObject(p->name), physmem(p->physmem), numcpus(0),
+#if FULL_SYSTEM
+ init_param(p->init_param),
+ functionalPort(p->name + "-fport"),
+ virtPort(p->name + "-vport"),
+#else
+ page_ptr(0),
+#endif
+ _params(p)
+{
+ // add self to global system list
+ systemList.push_back(this);
+
+#if FULL_SYSTEM
+ kernelSymtab = new SymbolTable;
+ debugSymbolTable = new SymbolTable;
+
+
+ /**
+ * Get a functional port to memory
+ */
+ Port *mem_port;
+ mem_port = physmem->getPort("functional");
+ functionalPort.setPeer(mem_port);
+ mem_port->setPeer(&functionalPort);
+
+ mem_port = physmem->getPort("functional");
+ virtPort.setPeer(mem_port);
+ mem_port->setPeer(&virtPort);
+
+
+ /**
+ * Load the kernel code into memory
+ */
+ // Load kernel code
+ kernel = createObjectFile(params()->kernel_path);
+ if (kernel == NULL)
+ fatal("Could not load kernel file %s", params()->kernel_path);
+
+ // Load program sections into memory
+ kernel->loadSections(&functionalPort, LoadAddrMask);
+
+ // setup entry points
+ kernelStart = kernel->textBase();
+ kernelEnd = kernel->bssBase() + kernel->bssSize();
+ kernelEntry = kernel->entryPoint();
+
+ // load symbols
+ if (!kernel->loadGlobalSymbols(kernelSymtab))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(kernelSymtab))
+ panic("could not load kernel local symbols\n");
+
+ if (!kernel->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(debugSymbolTable))
+ panic("could not load kernel local symbols\n");
+
+ DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+ DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
+ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+ DPRINTF(Loader, "Kernel loaded...\n");
+
+ kernelBinning = new Kernel::Binning(this);
+#endif // FULL_SYSTEM
+
+ // increment the number of running systms
+ numSystemsRunning++;
+}
+
+System::~System()
+{
+#if FULL_SYSTEM
+ delete kernelSymtab;
+ delete kernel;
- void
- System::regStats()
- {
- #if FULL_SYSTEM
- kernelBinning->regStats(name() + ".kern");
- #endif // FULL_SYSTEM
- }
-
+#else
+ panic("System::fixFuncEventAddr needs to be rewritten "
+ "to work with syscall emulation");
+#endif // FULL_SYSTEM}
+}
+
+#if FULL_SYSTEM
+
+
+int rgdb_wait = -1;
+
+#endif // FULL_SYSTEM
+
+int
+System::registerThreadContext(ThreadContext *tc, int id)
+{
+ if (id == -1) {
+ for (id = 0; id < threadContexts.size(); id++) {
+ if (!threadContexts[id])
+ break;
+ }
+ }
+
+ if (threadContexts.size() <= id)
+ threadContexts.resize(id + 1);
+
+ if (threadContexts[id])
+ panic("Cannot have two CPUs with the same id (%d)\n", id);
+
+ threadContexts[id] = tc;
+ numcpus++;
+
+#if FULL_SYSTEM
+ RemoteGDB *rgdb = new RemoteGDB(this, tc);
+ GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
+ gdbl->listen();
+ /**
+ * Uncommenting this line waits for a remote debugger to connect
+ * to the simulator before continuing.
+ */
+ if (rgdb_wait != -1 && rgdb_wait == id)
+ gdbl->accept();
+
+ if (remoteGDB.size() <= id) {
+ remoteGDB.resize(id + 1);
+ }
+
+ remoteGDB[id] = rgdb;
+#endif // FULL_SYSTEM
+
+ return id;
+}
+
+void
+System::startup()
+{
+ int i;
+ for (i = 0; i < threadContexts.size(); i++)
+ threadContexts[i]->activate(0);
+}
+
+void
+System::replaceThreadContext(ThreadContext *tc, int id)
+{
+ if (id >= threadContexts.size()) {
+ panic("replaceThreadContext: bad id, %d >= %d\n",
+ id, threadContexts.size());
+ }
+
+ threadContexts[id] = tc;
+#if FULL_SYSTEM
+ remoteGDB[id]->replaceThreadContext(tc);
+#endif // FULL_SYSTEM
+}
+
+#if !FULL_SYSTEM
+Addr
+System::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ ++page_ptr;
+ return return_addr;
+}
+#endif
+
- kernelBinning->serialize(os);
-
+void
+System::serialize(ostream &os)
+{
+#if FULL_SYSTEM
- kernelBinning->unserialize(cp, section);
-
+ kernelSymtab->serialize("kernel_symtab", os);
+#endif // FULL_SYSTEM
+}
+
+
+void
+System::unserialize(Checkpoint *cp, const string §ion)
+{
+#if FULL_SYSTEM
+ kernelSymtab->unserialize("kernel_symtab", cp, section);
+#endif // FULL_SYSTEM
+}
+
+void
+System::printSystems()
+{
+ vector<System *>::iterator i = systemList.begin();
+ vector<System *>::iterator end = systemList.end();
+ for (; i != end; ++i) {
+ System *sys = *i;
+ cerr << "System " << sys->name() << ": " << hex << sys << endl;
+ }
+}
+
+extern "C"
+void
+printSystems()
+{
+ System::printSystems();
+}
+
+#if FULL_SYSTEM
+
+// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
+// can be created directly.
+
+DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
+
+#else
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
+
+ SimObjectParam<PhysicalMemory *> physmem;
+
+END_DECLARE_SIM_OBJECT_PARAMS(System)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(System)
+
+ INIT_PARAM(physmem, "physical memory")
+
+END_INIT_SIM_OBJECT_PARAMS(System)
+
+CREATE_SIM_OBJECT(System)
+{
+ System::Params *p = new System::Params;
+ p->name = getInstanceName();
+ p->physmem = physmem;
+ return new System(p);
+}
+
+REGISTER_SIM_OBJECT("System", System)
+
+#endif
--- /dev/null
- namespace Kernel { class Binning; }
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ * Lisa Hsu
+ * Nathan Binkert
+ */
+
+#ifndef __SYSTEM_HH__
+#define __SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "cpu/pc_event.hh"
+#include "mem/port.hh"
+#include "sim/sim_object.hh"
+#if FULL_SYSTEM
+#include "kern/system_events.hh"
+#include "mem/vport.hh"
+#endif
+
+class BaseCPU;
+class ThreadContext;
+class ObjectFile;
+class PhysicalMemory;
+
+#if FULL_SYSTEM
+class Platform;
+class GDBListener;
+class RemoteGDB;
- Kernel::Binning *kernelBinning;
-
+#endif
+
+class System : public SimObject
+{
+ public:
+ PhysicalMemory *physmem;
+ PCEventQueue pcEventQueue;
+
+ std::vector<ThreadContext *> threadContexts;
+ int numcpus;
+
+ int getNumCPUs()
+ {
+ if (numcpus != threadContexts.size())
+ panic("cpu array not fully populated!");
+
+ return numcpus;
+ }
+
+#if FULL_SYSTEM
+ Platform *platform;
+ uint64_t init_param;
+
+ /** Port to physical memory used for writing object files into ram at
+ * boot.*/
+ FunctionalPort functionalPort;
+ VirtualPort virtPort;
+
+ /** kernel symbol table */
+ SymbolTable *kernelSymtab;
+
+ /** Object pointer for the kernel code */
+ ObjectFile *kernel;
+
+ /** Begining of kernel code */
+ Addr kernelStart;
+
+ /** End of kernel code */
+ Addr kernelEnd;
+
+ /** Entry point in the kernel to start at */
+ Addr kernelEntry;
+
- bool bin;
- std::vector<std::string> binned_fns;
- bool bin_int;
+#else
+
+ int page_ptr;
+
+
+#endif // FULL_SYSTEM
+
+ protected:
+
+#if FULL_SYSTEM
+ /**
+ * Fix up an address used to match PCs for hooking simulator
+ * events on to target function executions. See comment in
+ * system.cc for details.
+ */
+ virtual Addr fixFuncEventAddr(Addr addr) = 0;
+
+ /**
+ * Add a function-based event to the given function, to be looked
+ * up in the specified symbol table.
+ */
+ template <class T>
+ T *System::addFuncEvent(SymbolTable *symtab, const char *lbl)
+ {
+ Addr addr = 0; // initialize only to avoid compiler warning
+
+ if (symtab->findAddress(lbl, addr)) {
+ T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
+ return ev;
+ }
+
+ return NULL;
+ }
+
+ /** Add a function-based event to kernel code. */
+ template <class T>
+ T *System::addKernelFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(kernelSymtab, lbl);
+ }
+
+#endif
+ public:
+#if FULL_SYSTEM
+ std::vector<RemoteGDB *> remoteGDB;
+ std::vector<GDBListener *> gdbListen;
+ virtual bool breakpoint() = 0;
+#endif // FULL_SYSTEM
+
+ public:
+ struct Params
+ {
+ std::string name;
+ PhysicalMemory *physmem;
+
+#if FULL_SYSTEM
+ Tick boot_cpu_frequency;
+ std::string boot_osflags;
+ uint64_t init_param;
- void regStats();
+
+ std::string kernel_path;
+ std::string readfile;
+#endif
+ };
+
+ protected:
+ Params *_params;
+
+ public:
+ System(Params *p);
+ ~System();
+
+ void startup();
+
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
+
+#if FULL_SYSTEM
+ /**
+ * Returns the addess the kernel starts at.
+ * @return address the kernel starts at
+ */
+ Addr getKernelStart() const { return kernelStart; }
+
+ /**
+ * Returns the addess the kernel ends at.
+ * @return address the kernel ends at
+ */
+ Addr getKernelEnd() const { return kernelEnd; }
+
+ /**
+ * Returns the addess the entry point to the kernel code.
+ * @return entry point of the kernel code
+ */
+ Addr getKernelEntry() const { return kernelEntry; }
+
+#else
+
+ Addr new_page();
+
+#endif // FULL_SYSTEM
+
+ int registerThreadContext(ThreadContext *tc, int tcIndex);
+ void replaceThreadContext(ThreadContext *tc, int tcIndex);
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string §ion);
+
+ public:
+ ////////////////////////////////////////////
+ //
+ // STATIC GLOBAL SYSTEM LIST
+ //
+ ////////////////////////////////////////////
+
+ static std::vector<System *> systemList;
+ static int numSystemsRunning;
+
+ static void printSystems();
+
+
+};
+
+#endif // __SYSTEM_HH__
--- /dev/null
- Scalar<MainBin> s4;
- Vector<MainBin> s5;
- Distribution<MainBin> s6;
- Vector<MainBin> s7;
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <unistd.h>
+
+#include "base/cprintf.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/stats/text.hh"
+#include "base/stats/mysql.hh"
+#include "sim/host.hh"
+
+using namespace std;
+using namespace Stats;
+
+Tick curTick = 0;
+Tick ticksPerSecond = ULL(2000000000);
+
+Scalar<> s1;
+Scalar<> s2;
+Average<> s3;
- MainBin bin1("bin1");
- MainBin bin2("bin2");
-
++Scalar<> s4;
++Vector<> s5;
++Distribution<> s6;
++Vector<> s7;
+AverageVector<> s8;
+StandardDeviation<> s9;
+AverageDeviation<> s10;
+Scalar<> s11;
+Distribution<> s12;
+VectorDistribution<> s13;
+VectorStandardDeviation<> s14;
+VectorAverageDeviation<> s15;
+Vector2d<> s16;
+
+Formula f1;
+Formula f2;
+Formula f3;
+Value f4;
+Value f5;
+Formula f6;
+Formula f7;
+
- bin1.activate();
-
+ostream *outputStream = &cout;
+
+double
+testfunc()
+{
+ return 9.8;
+}
+
+class TestClass {
+ public:
+ double operator()() { return 9.7; }
+};
+
+char *progname = "";
+
+void
+usage()
+{
+ panic("incorrect usage.\n"
+ "usage:\n"
+ "\t%s [-t [-c] [-d]]\n", progname);
+}
+
+int
+main(int argc, char *argv[])
+{
+ bool descriptions = false;
+ bool compat = false;
+ bool text = false;
+ string mysql_name;
+ string mysql_host;
+ string mysql_user = "binkertn";
+ string mysql_passwd;
+
+ char c;
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "cdh:P:p:s:tu:")) != -1) {
+ switch (c) {
+ case 'c':
+ compat = true;
+ break;
+ case 'd':
+ descriptions = true;
+ break;
+ case 'h':
+ mysql_host = optarg;
+ break;
+ case 'P':
+ mysql_passwd = optarg;
+ break;
+ case 's':
+ mysql_name = optarg;
+ break;
+ case 't':
+ text = true;
+ break;
+ case 'u':
+ mysql_user = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (!text && (compat || descriptions))
+ usage();
+
+ s5.init(5);
+ s6.init(1, 100, 13);
+ s7.init(7);
+ s8.init(10);
+ s12.init(1, 100, 13);
+ s13.init(4, 0, 99, 10);
+ s14.init(9);
+ s15.init(10);
+ s16.init(2, 9);
+
+ s1
+ .name("Stat01")
+ .desc("this is statistic 1")
+ ;
+
+ s2
+ .name("Stat02")
+ .desc("this is statistic 2")
+ .prereq(s11)
+ ;
+
+ s3
+ .name("Stat03")
+ .desc("this is statistic 3")
+ .prereq(f7)
+ ;
+
+ s4
+ .name("Stat04")
+ .desc("this is statistic 4")
+ .prereq(s11)
+ ;
+
+ s5
+ .name("Stat05")
+ .desc("this is statistic 5")
+ .prereq(s11)
+ .subname(0, "foo1")
+ .subname(1, "foo2")
+ .subname(2, "foo3")
+ .subname(3, "foo4")
+ .subname(4, "foo5")
+ ;
+
+ s6
+ .name("Stat06")
+ .desc("this is statistic 6")
+ .prereq(s11)
+ ;
+
+ s7
+ .name("Stat07")
+ .desc("this is statistic 7")
+ .precision(1)
+ .flags(pdf | total)
+ .prereq(s11)
+ ;
+
+ s8
+ .name("Stat08")
+ .desc("this is statistic 8")
+ .precision(2)
+ .prereq(s11)
+ .subname(4, "blarg")
+ ;
+
+ s9
+ .name("Stat09")
+ .desc("this is statistic 9")
+ .precision(4)
+ .prereq(s11)
+ ;
+
+ s10
+ .name("Stat10")
+ .desc("this is statistic 10")
+ .prereq(s11)
+ ;
+
+ s12
+ .name("Stat12")
+ .desc("this is statistic 12")
+ ;
+
+ s13
+ .name("Stat13")
+ .desc("this is statistic 13")
+ ;
+
+ s14
+ .name("Stat14")
+ .desc("this is statistic 14")
+ ;
+
+ s15
+ .name("Stat15")
+ .desc("this is statistic 15")
+ ;
+
+ s16
+ .name("Stat16")
+ .desc("this is statistic 16")
+ .flags(total)
+ .subname(0, "sub0")
+ .subname(1, "sub1")
+ .ysubname(0, "y0")
+ .ysubname(1, "y1")
+ ;
+
+ f1
+ .name("Formula1")
+ .desc("this is formula 1")
+ .prereq(s11)
+ ;
+
+ f2
+ .name("Formula2")
+ .desc("this is formula 2")
+ .prereq(s11)
+ .precision(1)
+ ;
+
+ f3
+ .name("Formula3")
+ .desc("this is formula 3")
+ .prereq(s11)
+ .subname(0, "bar1")
+ .subname(1, "bar2")
+ .subname(2, "bar3")
+ .subname(3, "bar4")
+ .subname(4, "bar5")
+ ;
+
+ f4
+ .functor(testfunc)
+ .name("Formula4")
+ .desc("this is formula 4")
+ ;
+
+ TestClass testclass;
+ f5
+ .functor(testclass)
+ .name("Formula5")
+ .desc("this is formula 5")
+ ;
+
+ f6
+ .name("Formula6")
+ .desc("this is formula 6")
+ ;
+
+ f1 = s1 + s2;
+ f2 = (-s1) / (-s2) * (-s3 + ULL(100) + s4);
+ f3 = sum(s5) * s7;
+ f6 += constant(10.0);
+ f6 += s5[3];
+ f7 = constant(1);
+
+ check();
+ reset();
+
- bin2.activate();
+ s16[1][0] = 1;
+ s16[0][1] = 3;
+ s16[0][0] = 2;
+ s16[1][1] = 9;
+ s16[1][1] += 9;
+ s16[1][8] += 8;
+ s16[1][7] += 7;
+ s16[1][6] += 6;
+ s16[1][5] += 5;
+ s16[1][4] += 4;
+
+ s11 = 1;
+ s3 = 9;
+ s8[3] = 9;
+ s15[0].sample(1234);
+ s15[1].sample(1234);
+ s15[2].sample(1234);
+ s15[3].sample(1234);
+ s15[4].sample(1234);
+ s15[5].sample(1234);
+ s15[6].sample(1234);
+ s15[7].sample(1234);
+ s15[8].sample(1234);
+ s15[9].sample(1234);
+
+ s10.sample(1000000000);
+ curTick += ULL(1000000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s10.sample(100000);
+ s13[0].sample(12);
+ s13[1].sample(29);
+ s13[2].sample(12);
+ s13[3].sample(29);
+ s13[0].sample(42);
+ s13[1].sample(29);
+ s13[2].sample(42);
+ s13[3].sample(32);
+ s13[0].sample(52);
+ s13[1].sample(49);
+ s13[2].sample(42);
+ s13[3].sample(25);
+ s13[0].sample(32);
+ s13[1].sample(49);
+ s13[2].sample(22);
+ s13[3].sample(49);
+ s13[0].sample(62);
+ s13[1].sample(99);
+ s13[2].sample(72);
+ s13[3].sample(23);
+ s13[0].sample(52);
+ s13[1].sample(78);
+ s13[2].sample(69);
+ s13[3].sample(49);
+
+ s14[0].sample(1234);
+ s14[1].sample(4134);
+ s14[4].sample(1213);
+ s14[3].sample(1124);
+ s14[2].sample(1243);
+ s14[7].sample(1244);
+ s14[4].sample(7234);
+ s14[2].sample(9234);
+ s14[3].sample(1764);
+ s14[7].sample(1564);
+ s14[3].sample(3234);
+ s14[1].sample(2234);
+ s14[5].sample(1234);
+ s14[2].sample(4334);
+ s14[2].sample(1234);
+ s14[4].sample(4334);
+ s14[6].sample(1234);
+ s14[8].sample(8734);
+ s14[1].sample(5234);
+ s14[3].sample(8234);
+ s14[7].sample(5234);
+ s14[4].sample(4434);
+ s14[3].sample(7234);
+ s14[2].sample(1934);
+ s14[1].sample(9234);
+ s14[5].sample(5634);
+ s14[3].sample(1264);
+ s14[7].sample(5223);
+ s14[0].sample(1234);
+ s14[0].sample(5434);
+ s14[3].sample(8634);
+ s14[1].sample(1234);
+
+
+ s15[0].sample(1234);
+ s15[1].sample(4134);
+ curTick += ULL(1000000);
+ s15[4].sample(1213);
+ curTick += ULL(1000000);
+ s15[3].sample(1124);
+ curTick += ULL(1000000);
+ s15[2].sample(1243);
+ curTick += ULL(1000000);
+ s15[7].sample(1244);
+ curTick += ULL(1000000);
+ s15[4].sample(7234);
+ s15[2].sample(9234);
+ s15[3].sample(1764);
+ s15[7].sample(1564);
+ s15[3].sample(3234);
+ s15[1].sample(2234);
+ curTick += ULL(1000000);
+ s15[5].sample(1234);
+ curTick += ULL(1000000);
+ s15[9].sample(4334);
+ curTick += ULL(1000000);
+ s15[2].sample(1234);
+ curTick += ULL(1000000);
+ s15[4].sample(4334);
+ s15[6].sample(1234);
+ curTick += ULL(1000000);
+ s15[8].sample(8734);
+ curTick += ULL(1000000);
+ s15[1].sample(5234);
+ curTick += ULL(1000000);
+ s15[3].sample(8234);
+ curTick += ULL(1000000);
+ s15[7].sample(5234);
+ s15[4].sample(4434);
+ s15[3].sample(7234);
+ s15[2].sample(1934);
+ s15[1].sample(9234);
+ curTick += ULL(1000000);
+ s15[5].sample(5634);
+ s15[3].sample(1264);
+ s15[7].sample(5223);
+ s15[0].sample(1234);
+ s15[0].sample(5434);
+ s15[3].sample(8634);
+ curTick += ULL(1000000);
+ s15[1].sample(1234);
+
+ s4 = curTick;
+
+ s8[3] = 99999;
+
+ s3 = 12;
+ s3++;
+ curTick += 9;
+
+ s1 = 9;
+ s1 += 9;
+ s1 -= 11;
+ s1++;
+ ++s1;
+ s1--;
+ --s1;
+
+ s2 = 9;
+
+ s5[0] += 1;
+ s5[1] += 2;
+ s5[2] += 3;
+ s5[3] += 4;
+ s5[4] += 5;
+
+ s7[0] = 10;
+ s7[1] = 20;
+ s7[2] = 30;
+ s7[3] = 40;
+ s7[4] = 50;
+ s7[5] = 60;
+ s7[6] = 70;
+
+ s6.sample(0);
+ s6.sample(1);
+ s6.sample(2);
+ s6.sample(3);
+ s6.sample(4);
+ s6.sample(5);
+ s6.sample(6);
+ s6.sample(7);
+ s6.sample(8);
+ s6.sample(9);
+
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(10);
+ s6.sample(11);
+ s6.sample(19);
+ s6.sample(20);
+ s6.sample(20);
+ s6.sample(21);
+ s6.sample(21);
+ s6.sample(31);
+ s6.sample(98);
+ s6.sample(99);
+ s6.sample(99);
+ s6.sample(99);
+
+ s7[0] = 700;
+ s7[1] = 600;
+ s7[2] = 500;
+ s7[3] = 400;
+ s7[4] = 300;
+ s7[5] = 200;
+ s7[6] = 100;
+
+ s9.sample(100);
+ s9.sample(100);
+ s9.sample(100);
+ s9.sample(100);
+ s9.sample(10);
+ s9.sample(10);
+ s9.sample(10);
+ s9.sample(10);
+ s9.sample(10);
+
+ curTick += 9;
+ s4 = curTick;
+ s6.sample(100);
+ s6.sample(100);
+ s6.sample(100);
+ s6.sample(101);
+ s6.sample(102);
+
+ s12.sample(100);
+
+ if (text) {
+ Text out(cout);
+ out.descriptions = descriptions;
+ out.compat = compat;
+ out();
+ }
+
+ if (!mysql_name.empty()) {
+ MySql out;
+ out.connect(mysql_host, mysql_user, mysql_passwd, "m5stats",
+ mysql_name, "test");
+ out();
+ }
+
+ return 0;
+}