summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile356
-rw-r--r--arch/alpha/alpha_memory.cc82
-rw-r--r--arch/alpha/alpha_memory.hh14
-rw-r--r--arch/alpha/ev5.cc10
-rw-r--r--arch/alpha/faults.hh10
-rw-r--r--arch/alpha/isa_desc499
-rw-r--r--arch/alpha/pseudo_inst.cc6
-rwxr-xr-xarch/isa_parser.py186
-rw-r--r--base/compression/lzss_compression.cc43
-rw-r--r--base/compression/lzss_compression.hh9
-rw-r--r--base/hashmap.hh2
-rw-r--r--base/hybrid_pred.cc2
-rw-r--r--base/hybrid_pred.hh2
-rw-r--r--base/loader/elf_object.cc1
-rw-r--r--base/mysql.cc97
-rw-r--r--base/mysql.hh410
-rw-r--r--base/sat_counter.cc3
-rw-r--r--base/sat_counter.hh2
-rw-r--r--base/statistics.cc1140
-rw-r--r--base/statistics.hh1275
-rw-r--r--base/stats/flags.hh73
-rw-r--r--base/stats/mysql.cc844
-rw-r--r--base/stats/mysql.hh149
-rw-r--r--base/stats/output.hh47
-rw-r--r--base/stats/statdb.cc89
-rw-r--r--base/stats/statdb.hh74
-rw-r--r--base/stats/text.cc731
-rw-r--r--base/stats/text.hh77
-rw-r--r--base/stats/types.hh49
-rw-r--r--base/stats/visit.cc41
-rw-r--r--base/stats/visit.hh63
-rw-r--r--base/time.cc15
-rw-r--r--base/time.hh4
-rw-r--r--base/trace.hh2
-rw-r--r--base/traceflags.py336
-rw-r--r--base/userinfo.cc41
-rw-r--r--base/userinfo.hh36
-rw-r--r--cpu/base_cpu.cc6
-rw-r--r--cpu/exec_context.cc4
-rw-r--r--cpu/exec_context.hh9
-rw-r--r--cpu/memtest/memtest.cc22
-rw-r--r--cpu/memtest/memtest.hh9
-rw-r--r--cpu/simple_cpu/simple_cpu.cc16
-rw-r--r--cpu/simple_cpu/simple_cpu.hh56
-rw-r--r--cpu/static_inst.hh10
-rw-r--r--dev/ethertap.cc4
-rw-r--r--dev/io_device.cc5
-rw-r--r--kern/tru64/tru64_events.cc2
-rw-r--r--kern/tru64/tru64_system.cc2
-rw-r--r--sim/builder.cc3
-rw-r--r--sim/main.cc5
-rw-r--r--sim/param.cc6
-rw-r--r--sim/process.cc5
-rw-r--r--sim/process.hh2
-rw-r--r--sim/sim_events.cc2
-rw-r--r--sim/sim_object.cc25
-rw-r--r--sim/sim_object.hh7
-rw-r--r--sim/stat_control.cc207
-rw-r--r--sim/stat_control.hh52
-rw-r--r--sim/stats.hh41
-rw-r--r--sim/system.hh2
-rw-r--r--test/Makefile94
-rw-r--r--test/paramtest.cc6
-rw-r--r--test/stattest.cc81
-rw-r--r--util/config/m5config.py804
-rw-r--r--util/emacs/m5-c-style.el21
-rwxr-xr-xutil/tracediff4
67 files changed, 5619 insertions, 2713 deletions
diff --git a/Doxyfile b/Doxyfile
index 4e2aa31d6..3857e0a58 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.3.3
+# Doxyfile 1.3.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -11,7 +11,7 @@
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
-# General configuration options
+# Project related configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
@@ -38,7 +38,7 @@ OUTPUT_DIRECTORY = docs/doxygen
# The default language is English, other supported languages are:
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
-# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
+# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese,
# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
@@ -53,6 +53,141 @@ OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = .
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
@@ -105,46 +240,6 @@ HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = YES
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
-# members of a class in the documentation of that class as if those members were
-# ordinary class members. Constructors, destructors and assignment operators of
-# the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. It is allowed to use relative paths in the argument list.
-
-STRIP_FROM_PATH = .
-
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
@@ -160,12 +255,6 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
@@ -178,35 +267,6 @@ HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explict @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF = YES
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# reimplements.
-
-INHERIT_DOCS = YES
-
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@@ -219,17 +279,22 @@ INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
-DISTRIBUTE_GROUP_DOC = NO
+SORT_BRIEF_DOCS = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
-TAB_SIZE = 8
+SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -255,15 +320,6 @@ GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
@@ -279,34 +335,12 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
-# only. Doxygen will then generate output that is more tailored for Java.
-# For instance, namespaces will be presented as packages, qualified scopes
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -346,7 +380,7 @@ WARN_FORMAT = "$file:$line: $text"
# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
@@ -364,9 +398,13 @@ INPUT = .
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
-# *.h++ *.idl *.odl *.cs
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
-FILE_PATTERNS = *.c *.cc *.h *.hh *.doxygen
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.h \
+ *.hh \
+ *.doxygen
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
@@ -378,7 +416,11 @@ RECURSIVE = YES
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
-EXCLUDE = build configs setup PENDING RESYNC
+EXCLUDE = build \
+ configs \
+ setup \
+ PENDING \
+ RESYNC
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
# that are symbolic links (a Unix filesystem feature) are excluded from the input.
@@ -389,7 +431,9 @@ EXCLUDE_SYMLINKS = YES
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
-EXCLUDE_PATTERNS = */BitKeeper/* */Attic/* */SCCS/*
+EXCLUDE_PATTERNS = */BitKeeper/* \
+ */Attic/* \
+ */SCCS/*
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
@@ -437,7 +481,9 @@ FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
@@ -529,7 +575,9 @@ HTML_FOOTER = docs/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
@@ -549,7 +597,7 @@ GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
-# written to the html output dir.
+# written to the html output directory.
CHM_FILE =
@@ -684,7 +732,7 @@ LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimised for Word 97 and may not look very pretty with
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
@@ -711,7 +759,7 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assigments. You only have to provide
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
@@ -755,9 +803,7 @@ MAN_LINKS = NO
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# the code including all documentation.
GENERATE_XML = NO
@@ -779,6 +825,13 @@ XML_SCHEMA =
XML_DTD =
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -889,7 +942,7 @@ EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
# The TAGFILES option can be used to specify one or more tagfiles.
@@ -938,7 +991,7 @@ PERL_PATH = /usr/bin/perl
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
# super classes. Setting the tag to NO turns the diagrams off. Note that this
-# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
# recommended to install and use dot, since it yields more powerful graphs.
CLASS_DIAGRAMS = YES
@@ -971,7 +1024,7 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similiar to the OMG's Unified Modeling
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
@@ -1065,45 +1118,10 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine
+# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
-
-# The CGI_NAME tag should be the name of the CGI script that
-# starts the search engine (doxysearch) with the correct parameters.
-# A script with this name will be generated by doxygen.
-
-CGI_NAME = search.cgi
-
-# The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for
-# details.
-
-CGI_URL =
-
-# The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the
-# documentation, with file:// prepended to it, will be used.
-
-DOC_URL =
-
-# The DOC_ABSPATH tag should be the absolute path to the directory where the
-# documentation is located. If left blank the directory on the local machine
-# will be used.
-
-DOC_ABSPATH =
-
-# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
-# is installed.
-
-BIN_ABSPATH = /usr/local/bin/
-
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to
-# documentation generated for other projects. This allows doxysearch to search
-# the documentation for these projects as well.
-
-EXT_DOC_PATHS =
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc
index 4cd122431..63fb3ebcb 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/alpha_memory.cc
@@ -44,20 +44,14 @@ using namespace std;
//
// Alpha TLB
//
-
-#ifdef DEBUG
- bool uncacheBit39 = false;
- bool uncacheBit40 = false;
-#endif
-
-AlphaTlb::AlphaTlb(const string &name, int s)
+AlphaTLB::AlphaTLB(const string &name, int s)
: SimObject(name), size(s), nlu(0)
{
table = new AlphaISA::PTE[size];
memset(table, 0, sizeof(AlphaISA::PTE[size]));
}
-AlphaTlb::~AlphaTlb()
+AlphaTLB::~AlphaTLB()
{
if (table)
delete [] table;
@@ -65,7 +59,7 @@ AlphaTlb::~AlphaTlb()
// look up an entry in the TLB
AlphaISA::PTE *
-AlphaTlb::lookup(Addr vpn, uint8_t asn) const
+AlphaTLB::lookup(Addr vpn, uint8_t asn) const
{
DPRINTF(TLB, "lookup %#x\n", vpn);
@@ -89,7 +83,7 @@ AlphaTlb::lookup(Addr vpn, uint8_t asn) const
void
-AlphaTlb::checkCacheability(MemReqPtr &req)
+AlphaTLB::checkCacheability(MemReqPtr &req)
{
// in Alpha, cacheability is controlled by upper-level bits of the
// physical address
@@ -135,7 +129,7 @@ AlphaTlb::checkCacheability(MemReqPtr &req)
// insert a new TLB entry
void
-AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
+AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
{
if (table[nlu].valid) {
Addr oldvpn = table[nlu].tag;
@@ -169,7 +163,7 @@ AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
}
void
-AlphaTlb::flushAll()
+AlphaTLB::flushAll()
{
memset(table, 0, sizeof(AlphaISA::PTE[size]));
lookupTable.clear();
@@ -177,7 +171,7 @@ AlphaTlb::flushAll()
}
void
-AlphaTlb::flushProcesses()
+AlphaTLB::flushProcesses()
{
PageTable::iterator i = lookupTable.begin();
PageTable::iterator end = lookupTable.end();
@@ -197,7 +191,7 @@ AlphaTlb::flushProcesses()
}
void
-AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
+AlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
{
Addr vpn = VA_VPN(vaddr);
@@ -225,7 +219,7 @@ AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
void
-AlphaTlb::serialize(ostream &os)
+AlphaTLB::serialize(ostream &os)
{
SERIALIZE_SCALAR(size);
SERIALIZE_SCALAR(nlu);
@@ -237,7 +231,7 @@ AlphaTlb::serialize(ostream &os)
}
void
-AlphaTlb::unserialize(Checkpoint *cp, const string &section)
+AlphaTLB::unserialize(Checkpoint *cp, const string &section)
{
UNSERIALIZE_SCALAR(size);
UNSERIALIZE_SCALAR(nlu);
@@ -255,13 +249,13 @@ AlphaTlb::unserialize(Checkpoint *cp, const string &section)
//
// Alpha ITB
//
-AlphaItb::AlphaItb(const std::string &name, int size)
- : AlphaTlb(name, size)
+AlphaITB::AlphaITB(const std::string &name, int size)
+ : AlphaTLB(name, size)
{}
void
-AlphaItb::regStats()
+AlphaITB::regStats()
{
hits
.name(name() + ".hits")
@@ -280,7 +274,7 @@ AlphaItb::regStats()
}
void
-AlphaItb::fault(Addr pc, ExecContext *xc) const
+AlphaITB::fault(Addr pc, ExecContext *xc) const
{
uint64_t *ipr = xc->regs.ipr;
@@ -293,7 +287,7 @@ AlphaItb::fault(Addr pc, ExecContext *xc) const
Fault
-AlphaItb::translate(MemReqPtr &req) const
+AlphaITB::translate(MemReqPtr &req) const
{
InternalProcReg *ipr = req->xc->regs.ipr;
@@ -311,7 +305,7 @@ AlphaItb::translate(MemReqPtr &req) const
if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
- return Itb_Acv_Fault;
+ return ITB_Acv_Fault;
}
// Check for "superpage" mapping: when SP<1> is set, and
@@ -373,12 +367,12 @@ AlphaItb::translate(MemReqPtr &req) const
//
// Alpha DTB
//
-AlphaDtb::AlphaDtb(const std::string &name, int size)
- : AlphaTlb(name, size)
+AlphaDTB::AlphaDTB(const std::string &name, int size)
+ : AlphaTLB(name, size)
{}
void
-AlphaDtb::regStats()
+AlphaDTB::regStats()
{
read_hits
.name(name() + ".read_hits")
@@ -447,7 +441,7 @@ AlphaDtb::regStats()
}
void
-AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
+AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
{
uint64_t *ipr = xc->regs.ipr;
@@ -471,7 +465,7 @@ AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
}
Fault
-AlphaDtb::translate(MemReqPtr &req, bool write) const
+AlphaDTB::translate(MemReqPtr &req, bool write) const
{
RegFile *regs = &req->xc->regs;
Addr pc = regs->pc;
@@ -497,7 +491,7 @@ AlphaDtb::translate(MemReqPtr &req, bool write) const
req->xc);
if (write) { write_acv++; } else { read_acv++; }
- return Dtb_Fault_Fault;
+ return DTB_Fault_Fault;
}
// Check for "superpage" mapping: when SP<1> is set, and
@@ -593,7 +587,7 @@ AlphaDtb::translate(MemReqPtr &req, bool write) const
}
AlphaISA::PTE &
-AlphaTlb::index(bool advance)
+AlphaTLB::index(bool advance)
{
AlphaISA::PTE *pte = &table[nlu];
@@ -603,43 +597,45 @@ AlphaTlb::index(bool advance)
return *pte;
}
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
+DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
Param<int> size;
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb)
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
INIT_PARAM_DFLT(size, "TLB size", 48)
-END_INIT_SIM_OBJECT_PARAMS(AlphaItb)
+END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
-CREATE_SIM_OBJECT(AlphaItb)
+CREATE_SIM_OBJECT(AlphaITB)
{
- return new AlphaItb(getInstanceName(), size);
+ return new AlphaITB(getInstanceName(), size);
}
-REGISTER_SIM_OBJECT("AlphaITB", AlphaItb)
+REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
Param<int> size;
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
INIT_PARAM_DFLT(size, "TLB size", 64)
-END_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
+END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
-CREATE_SIM_OBJECT(AlphaDtb)
+CREATE_SIM_OBJECT(AlphaDTB)
{
- return new AlphaDtb(getInstanceName(), size);
+ return new AlphaDTB(getInstanceName(), size);
}
-REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb)
+REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh
index 999eec228..12196c44b 100644
--- a/arch/alpha/alpha_memory.hh
+++ b/arch/alpha/alpha_memory.hh
@@ -37,7 +37,7 @@
class ExecContext;
-class AlphaTlb : public SimObject
+class AlphaTLB : public SimObject
{
protected:
typedef std::multimap<Addr, int> PageTable;
@@ -51,8 +51,8 @@ class AlphaTlb : public SimObject
AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
public:
- AlphaTlb(const std::string &name, int size);
- virtual ~AlphaTlb();
+ AlphaTLB(const std::string &name, int size);
+ virtual ~AlphaTLB();
int getsize() const { return size; }
@@ -77,7 +77,7 @@ class AlphaTlb : public SimObject
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-class AlphaItb : public AlphaTlb
+class AlphaITB : public AlphaTLB
{
protected:
mutable Statistics::Scalar<> hits;
@@ -89,13 +89,13 @@ class AlphaItb : public AlphaTlb
void fault(Addr pc, ExecContext *xc) const;
public:
- AlphaItb(const std::string &name, int size);
+ AlphaITB(const std::string &name, int size);
virtual void regStats();
Fault translate(MemReqPtr &req) const;
};
-class AlphaDtb : public AlphaTlb
+class AlphaDTB : public AlphaTLB
{
protected:
mutable Statistics::Scalar<> read_hits;
@@ -115,7 +115,7 @@ class AlphaDtb : public AlphaTlb
void fault(Addr pc, uint64_t flags, ExecContext *xc) const;
public:
- AlphaDtb(const std::string &name, int size);
+ AlphaDTB(const std::string &name, int size);
virtual void regStats();
Fault translate(MemReqPtr &req, bool write) const;
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 551cbdabf..9b3ac5fff 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -68,11 +68,11 @@ AlphaISA::fault_addr[Num_Faults] = {
0x0201, /* Ndtb_Miss_Fault */
0x0281, /* Pdtb_Miss_Fault */
0x0301, /* Alignment_Fault */
- 0x0381, /* Dtb_Fault_Fault */
- 0x0381, /* Dtb_Acv_Fault */
- 0x0181, /* Itb_Miss_Fault */
- 0x0181, /* Itb_Fault_Fault */
- 0x0081, /* Itb_Acv_Fault */
+ 0x0381, /* DTB_Fault_Fault */
+ 0x0381, /* DTB_Acv_Fault */
+ 0x0181, /* ITB_Miss_Fault */
+ 0x0181, /* ITB_Fault_Fault */
+ 0x0081, /* ITB_Acv_Fault */
0x0481, /* Unimplemented_Opcode_Fault */
0x0581, /* Fen_Fault */
0x2001, /* Pal_Fault */
diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh
index bc8a4da0e..33aa55439 100644
--- a/arch/alpha/faults.hh
+++ b/arch/alpha/faults.hh
@@ -38,11 +38,11 @@ enum Fault {
Ndtb_Miss_Fault, // DTB miss
Pdtb_Miss_Fault, // nested DTB miss
Alignment_Fault, // unaligned access
- Dtb_Fault_Fault, // DTB page fault
- Dtb_Acv_Fault, // DTB access violation
- Itb_Miss_Fault, // ITB miss
- Itb_Fault_Fault, // ITB page fault
- Itb_Acv_Fault, // ITB access violation
+ DTB_Fault_Fault, // DTB page fault
+ DTB_Acv_Fault, // DTB access violation
+ ITB_Miss_Fault, // ITB miss
+ ITB_Fault_Fault, // ITB page fault
+ ITB_Acv_Fault, // ITB access violation
Unimplemented_Opcode_Fault, // invalid/unimplemented instruction
Fen_Fault, // FP not-enabled fault
Pal_Fault, // call_pal S/W interrupt
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
index 0da087f97..0d1e7138f 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -5,7 +5,7 @@
let {{
global rcs_id
- rcs_id = "$Id: s.isa_desc 1.43 04/02/29 22:41:10-05:00 ehallnor@zazzer.eecs.umich.edu $"
+ rcs_id = "$Id$"
}};
@@ -22,9 +22,7 @@ let {{
#include "base/misc.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
-#include "cpu/full_cpu/full_cpu.hh"
-#include "cpu/full_cpu/op_class.hh"
-#include "cpu/full_cpu/spec_state.hh"
+#include "cpu/full_cpu/dyn_inst.hh"
#include "cpu/simple_cpu/simple_cpu.hh"
#include "cpu/static_inst.hh"
#include "sim/annotation.hh"
@@ -143,7 +141,8 @@ declare {{
/// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
/// if not. Non-full-system mode: always returns No_Fault.
#ifdef FULL_SYSTEM
- inline Fault checkFpEnableFault(ExecContext *xc)
+ template <class XC>
+ inline Fault checkFpEnableFault(XC *xc)
{
Fault fault = No_Fault; // dummy... this ipr access should not fault
if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
@@ -152,7 +151,8 @@ declare {{
return fault;
}
#else
- inline Fault checkFpEnableFault(ExecContext *xc)
+ template <class XC>
+ inline Fault checkFpEnableFault(XC *xc)
{
return No_Fault;
}
@@ -239,42 +239,27 @@ def template BasicDeclare {{
%(constructor)s;
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
- Fault fault = No_Fault;
+ %(exec_func_declarations)s
+ };
+}};
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
- %(code)s;
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Fault fault = No_Fault;
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
- return fault;
+ if (fault == No_Fault) {
+ %(op_wb)s;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- DynInst *memAccessObj __attribute__((unused)) = dynInst;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
+ return fault;
+ }
}};
def template BasicDecode {{
@@ -288,7 +273,7 @@ def template BasicDecodeWithMnemonic {{
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
@@ -315,18 +300,6 @@ declare {{
~Nop() { }
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- return No_Fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- return No_Fault;
- }
-
std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
@@ -335,6 +308,12 @@ declare {{
return csprintf("%-10s (%s)", "nop", originalDisassembly);
#endif
}
+
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { return No_Fault; }
+
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { return No_Fault; }
};
/// Helper function for decoding nops. Substitute Nop object
@@ -350,7 +329,7 @@ declare {{
}};
def format Nop() {{
- return ('', 'return new Nop("%s", machInst);\n' % name)
+ return ('', 'return new Nop("%s", machInst);\n' % name, 'return No_Fault;')
}};
@@ -370,7 +349,7 @@ def template OperateNopCheckDecode {{
def format BasicOperateWithNopCheck(code, *opt_args) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
opt_args)
- return iop.subst('BasicDeclare', 'OperateNopCheckDecode')
+ return iop.subst('BasicDeclare', 'OperateNopCheckDecode', 'BasicExecute')
}};
@@ -454,21 +433,24 @@ def format IntegerOperate(code, *opt_flags) {{
# generate declaration for register version
cblk = CodeBlock(code)
iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- decls = iop.subst('BasicDeclare')
+ (decls, exec_code) = iop.subst('BasicDeclare', 'BasicExecute')
if uses_imm:
# append declaration for imm version
imm_cblk = CodeBlock(imm_code)
imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
opt_flags)
- decls += imm_iop.subst('BasicDeclare')
+ (imm_decls, imm_exec_code) = \
+ imm_iop.subst('BasicDeclare', 'BasicExecute')
+ decls += imm_decls
+ exec_code += imm_exec_code
# decode checks IMM bit to pick correct version
decode = iop.subst('RegOrImmDecode')
else:
# no imm version: just check for nop
decode = iop.subst('OperateNopCheckDecode')
- return (decls, decode)
+ return (decls, decode, exec_code)
}};
@@ -544,10 +526,10 @@ declare {{
#if defined(linux)
int
- getC99RoundingMode(ExecContext *xc)
+ getC99RoundingMode(uint64_t fpcr_val)
{
if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(xc->readFpcr(), 59, 58)];
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
}
else {
return alphaToC99RoundingMode[roundingMode];
@@ -618,124 +600,6 @@ declare {{
}};
-def template FloatingPointDeclare {{
- /**
- * "Fast" static instruction class for "%(mnemonic)s" (imprecise
- * trapping mode, normal rounding mode).
- */
- class %(class_name)sFast : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)sFast(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
-
- return fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
-
- /**
- * General static instruction class for "%(mnemonic)s". Supports
- * all the various rounding and trapping modes.
- */
- class %(class_name)sGeneral : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)sGeneral(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_rd)s;
-
-#if defined(linux)
- fesetround(getC99RoundingMode(xc));
-#endif
-
- %(code)s;
-
-#if defined(linux)
- fesetround(FE_TONEAREST);
-#endif
-
- if (fault == No_Fault) {
- %(simple_wb)s;
- }
-
- return fault;
- }
-
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_rd)s;
-
-#if defined(linux)
- fesetround(getC99RoundingMode(xc));
-#endif
-
- %(code)s;
-
-#if defined(linux)
- fesetround(FE_TONEAREST);
-#endif
-
- if (fault == No_Fault) {
- %(dtld_wb)s;
- }
-
- return fault;
- }
- };
-}};
-
def template FloatingPointDecode {{
{
bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
@@ -752,15 +616,34 @@ def template FloatingPointDecode {{
}
}};
-
// General format for floating-point operate instructions:
// - Checks trapping and rounding mode flags. Trapping modes
// currently unimplemented (will fail).
// - Generates NOP if FC == 31.
def format FloatingPointOperate(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code),
- opt_args)
- return iop.subst('FloatingPointDeclare', 'FloatingPointDecode')
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode = iop.subst('FloatingPointDecode')
+
+ fast_iop = InstObjParams(name, Name + 'Fast', 'AlphaFP',
+ CodeBlock(code), opt_args)
+ (fast_declare, fast_exec) = fast_iop.subst('BasicDeclare', 'BasicExecute')
+
+ gen_code_prefix = r'''
+#if defined(linux)
+ fesetround(getC99RoundingMode(xc->readFpcr()));
+#endif
+'''
+ gen_code_suffix = r'''
+#if defined(linux)
+ fesetround(FE_TONEAREST);
+#endif
+'''
+
+ gen_iop = InstObjParams(name, Name + 'General', 'AlphaFP',
+ CodeBlock(gen_code_prefix + code + gen_code_suffix), opt_args)
+ (gen_declare, gen_exec) = gen_iop.subst('BasicDeclare', 'BasicExecute')
+
+ return (fast_declare + gen_declare, decode, fast_exec + gen_exec)
}};
@@ -833,13 +716,11 @@ declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- { panic("attempt to execute eacomp"); }
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute eacomp"); }
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- { panic("attempt to execute eacomp"); }
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute eacomp"); }
};
/**
@@ -855,13 +736,11 @@ declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- { panic("attempt to execute memacc"); }
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute memacc"); }
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- { panic("attempt to execute memacc"); }
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+ { panic("attempt to execute memacc"); }
};
}};
@@ -869,7 +748,7 @@ declare {{
def format LoadAddress(code) {{
iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
@@ -927,72 +806,42 @@ def template LoadStoreDeclare {{
%(constructor)s;
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- SimpleCPU *memAccessObj = cpu;
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(simple_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(simple_mem_wb)s;
- }
+ %(exec_func_declarations)s
+ };
+}};
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
+def template LoadStoreExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Addr EA;
+ Fault fault = No_Fault;
- if (fault == No_Fault) {
- %(simple_nonmem_wb)s;
- }
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ %(ea_code)s;
- return fault;
+ if (fault == No_Fault) {
+ %(op_mem_rd)s;
+ %(memacc_code)s;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- DynInst *memAccessObj = dynInst;
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(dtld_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(dtld_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
+ if (fault == No_Fault) {
+ %(op_mem_wb)s;
+ }
- if (fault == No_Fault) {
- %(dtld_nonmem_wb)s;
- }
+ if (fault == No_Fault) {
+ %(postacc_code)s;
+ }
- return fault;
+ if (fault == No_Fault) {
+ %(op_nonmem_wb)s;
}
- };
-}};
+ return fault;
+ }
+}};
def template PrefetchDeclare {{
/**
@@ -1048,45 +897,30 @@ def template PrefetchDeclare {{
%(constructor)s;
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
- Trace::InstRecord *traceData)
- {
- Addr EA;
- Fault fault = No_Fault;
+ %(exec_func_declarations)s
+ };
+}};
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(simple_nonmem_rd)s;
- %(ea_code)s;
+def template PrefetchExecute {{
+ Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ Addr EA;
+ Fault fault = No_Fault;
- if (fault == No_Fault) {
- cpu->prefetch(EA, memAccessFlags);
- }
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ %(ea_code)s;
- return No_Fault;
+ if (fault == No_Fault) {
+ xc->prefetch(EA, memAccessFlags);
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
- Trace::InstRecord *traceData)
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(exec_decl)s;
- %(dtld_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- dynInst->prefetch(EA, memAccessFlags);
- }
-
- return No_Fault;
- }
- };
+ return No_Fault;
+ }
}};
-
// load instructions use Ra as dest, so check for
// Ra == 31 to detect nops
def template LoadNopCheckDecode {{
@@ -1118,7 +952,8 @@ global LoadStoreBase
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'Memory', flags = [],
declare_template = 'LoadStoreDeclare',
- decode_template = 'BasicDecode'):
+ decode_template = 'BasicDecode',
+ exec_template = 'LoadStoreExecute'):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
@@ -1149,7 +984,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
if mem_flags != '':
iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
- return iop.subst(declare_template, decode_template)
+ return iop.subst(declare_template, decode_template, exec_template)
}};
@@ -1163,7 +998,7 @@ def format LoadOrNop(ea_code, memacc_code, *flags) {{
// Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
# declare the load instruction object and generate the decode block
- (decls, decode) = \
+ (decls, decode, exec_code) = \
LoadStoreBase(name, Name, ea_code, memacc_code,
decode_template = 'LoadPrefetchCheckDecode')
@@ -1172,12 +1007,13 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
# convert flags from tuple to list to make them mutable
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
- (pfdecls, pfdecode) = \
+ (pfdecls, pfdecode, pfexec) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
flags = pf_flags,
- declare_template = 'PrefetchDeclare')
+ declare_template = 'PrefetchDeclare',
+ exec_template = 'PrefetchExecute')
- return (decls + pfdecls, decode)
+ return (decls + pfdecls, decode, exec_code + pfexec)
}};
@@ -1369,7 +1205,7 @@ def format CondBranch(code) {{
code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
('IsDirectControl', 'IsCondControl'))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
let {{
@@ -1379,17 +1215,20 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
nolink_code = 'NPC = %s;\n' % npc_expr
nolink_iop = InstObjParams(name, Name, base_class,
CodeBlock(nolink_code), flags)
- decls = nolink_iop.subst('BasicDeclare')
+ (decls, exec_code) = nolink_iop.subst('BasicDeclare', 'BasicExecute')
# Generate declaration of '*AndLink' version, append to decls
link_code = 'Ra = NPC & ~3;\n' + nolink_code
link_iop = InstObjParams(name, Name + 'AndLink', base_class,
CodeBlock(link_code), flags)
- decls += link_iop.subst('BasicDeclare')
+ (link_decls, link_exec_code) = \
+ link_iop.subst('BasicDeclare', 'BasicExecute')
+ decls += link_decls
+ exec_code += link_exec_code
# need to use link_iop for the decode template since it is expecting
# the shorter version of class_name (w/o "AndLink")
- return (decls, nolink_iop.subst('JumpOrBranchDecode'))
+ return (decls, nolink_iop.subst('JumpOrBranchDecode'), exec_code)
}};
def format UncondBranch(*flags) {{
@@ -1432,7 +1271,7 @@ declare {{
def format EmulatedCallPal(code) {{
iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
declare {{
@@ -1483,7 +1322,7 @@ declare {{
def format CallPal(code) {{
iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
//
@@ -1585,7 +1424,7 @@ declare {{
def format HwMoveIPR(code) {{
iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode')
+ return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
}};
declare {{
@@ -1605,7 +1444,7 @@ declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
panic("attempt to execute unimplemented instruction '%s' "
@@ -1613,11 +1452,11 @@ declare {{
return Unimplemented_Opcode_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
// don't panic if this is a misspeculated instruction
- if (!xc->spec_mode)
+ if (!xc->misspeculating())
panic("attempt to execute unimplemented instruction '%s' "
"(inst 0x%08x, opcode 0x%x)",
mnemonic, machInst, OPCODE);
@@ -1652,7 +1491,7 @@ declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
if (!warned) {
@@ -1663,10 +1502,10 @@ declare {{
return No_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
- if (!xc->spec_mode && !warned) {
+ if (!xc->misspeculating() && !warned) {
warn("instruction '%s' unimplemented\n", mnemonic);
warned = true;
}
@@ -1703,12 +1542,12 @@ def template WarnUnimplDeclare {{
def format FailUnimpl() {{
iop = InstObjParams(name, 'FailUnimplemented')
- return ('', iop.subst('BasicDecodeWithMnemonic'))
+ return ('', iop.subst('BasicDecodeWithMnemonic'), '')
}};
def format WarnUnimpl() {{
iop = InstObjParams(name, Name, 'WarnUnimplemented')
- return iop.subst('WarnUnimplDeclare', 'BasicDecode')
+ return iop.subst('WarnUnimplDeclare', 'BasicDecode') + ['']
}};
declare {{
@@ -1726,7 +1565,7 @@ declare {{
{
}
- Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData)
{
panic("attempt to execute unknown instruction "
@@ -1734,11 +1573,11 @@ declare {{
return Unimplemented_Opcode_Fault;
}
- Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData)
{
// don't panic if this is a misspeculated instruction
- if (!xc->spec_mode)
+ if (!xc->misspeculating())
panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
return Unimplemented_Opcode_Fault;
@@ -1753,7 +1592,7 @@ declare {{
}};
def format Unknown() {{
- return ('', 'return new Unknown(machInst);\n')
+ return ('', 'return new Unknown(machInst);\n', '')
}};
declare {{
@@ -1855,7 +1694,7 @@ decode OPCODE default Unknown::unknown() {
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x20: copy_load({{EA = Ra;}},
- {{ fault = memAccessObj->copySrcTranslate(EA);}},
+ {{ fault = xc->copySrcTranslate(EA);}},
IsMemRef, IsLoad, IsCopy);
}
@@ -1877,7 +1716,7 @@ decode OPCODE default Unknown::unknown() {
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x24: copy_store({{EA = Rb;}},
- {{ fault = memAccessObj->copy(EA);}},
+ {{ fault = xc->copy(EA);}},
IsMemRef, IsStore, IsCopy);
}
@@ -2383,7 +2222,7 @@ decode OPCODE default Unknown::unknown() {
format MiscPrefetch {
0xf800: wh64({{ EA = Rb; }},
- {{ memAccessObj->writeHint(EA, 64); }},
+ {{ xc->writeHint(EA, 64); }},
IsMemRef, IsStore, WrPort);
}
@@ -2421,15 +2260,15 @@ decode OPCODE default Unknown::unknown() {
#ifdef FULL_SYSTEM
format BasicOperate {
0xe000: rc({{
- Ra = xc->regs.intrflag;
+ Ra = xc->readIntrFlag();
if (!xc->misspeculating()) {
- xc->regs.intrflag = 0;
+ xc->setIntrFlag(0);
}
}});
0xf000: rs({{
- Ra = xc->regs.intrflag;
+ Ra = xc->readIntrFlag();
if (!xc->misspeculating()) {
- xc->regs.intrflag = 1;
+ xc->setIntrFlag(1);
}
}});
}
@@ -2458,10 +2297,10 @@ decode OPCODE default Unknown::unknown() {
// on this PAL call (including maybe suppress it)
dopal = xc->simPalCheck(palFunc);
- Annotate::Callpal(xc, palFunc);
+ Annotate::Callpal(xc->xcBase(), palFunc);
if (dopal) {
- AlphaISA::swap_palshadow(&xc->regs, true);
+ AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
}
}
@@ -2519,48 +2358,48 @@ decode OPCODE default Unknown::unknown() {
0x01: decode M5FUNC {
0x00: arm({{
if (!xc->misspeculating()) {
- Annotate::ARM(xc);
- xc->kernelStats.arm();
+ Annotate::ARM(xc->xcBase());
+ xc->xcBase()->kernelStats.arm();
}
}});
0x01: quiesce({{
if (!xc->misspeculating())
- AlphaPseudo::quiesce(xc);
+ AlphaPseudo::quiesce(xc->xcBase());
}});
0x10: ivlb({{
if (!xc->misspeculating()) {
- Annotate::BeginInterval(xc);
- xc->kernelStats.ivlb();
+ Annotate::BeginInterval(xc->xcBase());
+ xc->xcBase()->kernelStats.ivlb();
}
}}, No_OpClass);
0x11: ivle({{
if (!xc->misspeculating())
- Annotate::EndInterval(xc);
+ Annotate::EndInterval(xc->xcBase());
}}, No_OpClass);
0x20: m5exit_old({{
if (!xc->misspeculating())
- AlphaPseudo::m5exit_old(xc);
+ AlphaPseudo::m5exit_old(xc->xcBase());
}}, No_OpClass);
0x21: m5exit({{
if (!xc->misspeculating())
- AlphaPseudo::m5exit(xc);
+ AlphaPseudo::m5exit(xc->xcBase());
}}, No_OpClass);
- 0x30: initparam({{ Ra = cpu->system->init_param; }});
+ 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
0x40: resetstats({{
if (!xc->misspeculating())
- AlphaPseudo::resetstats(xc);
+ AlphaPseudo::resetstats(xc->xcBase());
}});
0x41: dumpstats({{
if (!xc->misspeculating())
- AlphaPseudo::dumpstats(xc);
+ AlphaPseudo::dumpstats(xc->xcBase());
}});
0x42: dumpresetstats({{
if (!xc->misspeculating())
- AlphaPseudo::dumpresetstats(xc);
+ AlphaPseudo::dumpresetstats(xc->xcBase());
}});
0x43: m5checkpoint({{
if (!xc->misspeculating())
- AlphaPseudo::m5checkpoint(xc);
+ AlphaPseudo::m5checkpoint(xc->xcBase());
}});
}
}
@@ -2568,7 +2407,7 @@ decode OPCODE default Unknown::unknown() {
format HwMoveIPR {
0x19: hw_mfpr({{
// this instruction is only valid in PAL mode
- if (!PC_PAL(xc->regs.pc)) {
+ if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault;
}
else {
@@ -2577,7 +2416,7 @@ decode OPCODE default Unknown::unknown() {
}});
0x1d: hw_mtpr({{
// this instruction is only valid in PAL mode
- if (!PC_PAL(xc->regs.pc)) {
+ if (!xc->inPalMode()) {
fault = Unimplemented_Opcode_Fault;
}
else {
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index 7f8c6b17c..194dc6400 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -34,7 +34,8 @@
#include "sim/param.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
using namespace std;
using namespace Statistics;
@@ -82,6 +83,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
+ using namespace Statistics;
SetupEvent(Reset, when, repeat);
}
@@ -97,6 +99,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
+ using namespace Statistics;
SetupEvent(Dump, when, repeat);
}
@@ -112,6 +115,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
+ using namespace Statistics;
SetupEvent(Dump|Reset, when, repeat);
}
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index 2e3c0df35..0ee9e2e2d 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -32,20 +32,10 @@ import os
import sys
import re
import string
+import traceback
# get type names
from types import *
-# Check arguments. Right now there are only two: the name of the ISA
-# description (input) file and the name of the C++ decoder (output) file.
-isa_desc_filename = sys.argv[1]
-decoder_filename = sys.argv[2]
-
-# Might as well suck the file in while we're here. This way if it's a
-# bad filename we don't waste a lot of time building the parser :-).
-input = open(isa_desc_filename)
-isa_desc = input.read()
-input.close()
-
# Prepend the directory where the PLY lex & yacc modules are found
# to the search path. Assumes we're compiling in a subdirectory
# of 'build' in the current tree.
@@ -225,8 +215,8 @@ def p_specification(t):
isa_name = t[2]
namespace = isa_name + "Inst"
global_decls2 = t[3]
- (inst_decls, code) = t[4]
- code = indent(code)
+ (inst_decls, decode_code, exec_code) = t[4]
+ decode_code = indent(decode_code)
# grab the last three path components of isa_desc_filename
filename = '/'.join(isa_desc_filename.split('/')[-3:])
# if the isa_desc file defines a 'rcs_id' string,
@@ -306,6 +296,8 @@ namespace %(namespace)s
%(inst_decls)s
+%(exec_code)s
+
} // namespace %(namespace)s
//////////////////////
@@ -316,7 +308,7 @@ StaticInstPtr<%(isa_name)s>
%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
{
using namespace %(namespace)s;
-%(code)s
+%(decode_code)s
} // decodeInst
''' % vars()
output.close()
@@ -461,18 +453,19 @@ def p_param_1(t):
def p_decode_block(t):
'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
default_defaults = defaultStack.pop()
- (decls, code, has_default) = t[5]
+ (decls, decode_code, exec_code, has_default) = t[5]
# use the "default defaults" only if there was no explicit
# default statement in decode_stmt_list
if not has_default:
- (default_decls, default_code) = default_defaults
+ (default_decls, default_decode, default_exec) = default_defaults
decls += default_decls
- code += default_code
+ decode_code += default_decode
+ exec_code += default_exec
t[0] = (decls, '''
switch (%s) {
%s
}
-''' % (t[2], indent(code)))
+''' % (t[2], indent(decode_code)), exec_code)
# The opt_default statement serves only to push the "default defaults"
# onto defaultStack. This value will be used by nested decode blocks,
@@ -488,8 +481,8 @@ def p_opt_default_0(t):
def p_opt_default_1(t):
'opt_default : DEFAULT inst'
# push the new default
- (decls, code) = t[2]
- defaultStack.push((decls, '\ndefault:\n%sbreak;' % code))
+ (decls, decode_code, exec_code) = t[2]
+ defaultStack.push((decls, '\ndefault:\n%sbreak;' % decode_code, exec_code))
# no meaningful value returned
t[0] = None
@@ -499,12 +492,12 @@ def p_decode_stmt_list_0(t):
def p_decode_stmt_list_1(t):
'decode_stmt_list : decode_stmt decode_stmt_list'
- (decls1, code1, has_default1) = t[1]
- (decls2, code2, has_default2) = t[2]
+ (decls1, decode_code1, exec_code1, has_default1) = t[1]
+ (decls2, decode_code2, exec_code2, has_default2) = t[2]
if (has_default1 and has_default2):
error(t.lineno(1), 'Two default cases in decode block')
- t[0] = (decls1 + '\n' + decls2, code1 + '\n' + code2,
- has_default1 or has_default2)
+ t[0] = (decls1 + '\n' + decls2, decode_code1 + '\n' + decode_code2,
+ exec_code1 + '\n' + exec_code2, has_default1 or has_default2)
#
# Decode statement rules
@@ -525,7 +518,7 @@ def p_decode_stmt_list_1(t):
# the other statements.
def p_decode_stmt_cpp(t):
'decode_stmt : CPPDIRECTIVE'
- t[0] = (t[1], t[1], 0)
+ t[0] = (t[1], t[1], t[1], 0)
# A format block 'format <foo> { ... }' sets the default instruction
# format used to handle instruction definitions inside the block.
@@ -555,17 +548,19 @@ def p_push_format_id(t):
def p_decode_stmt_decode(t):
'decode_stmt : case_label COLON decode_block'
(label, is_default) = t[1]
- (decls, code) = t[3]
+ (decls, decode_code, exec_code) = t[3]
# just wrap the decoding code from the block as a case in the
# outer switch statement.
- t[0] = (decls, '\n%s:\n%s' % (label, indent(code)), is_default)
+ t[0] = (decls, '\n%s:\n%s' % (label, indent(decode_code)),
+ exec_code, is_default)
# Instruction definition (finally!).
def p_decode_stmt_inst(t):
'decode_stmt : case_label COLON inst SEMI'
(label, is_default) = t[1]
- (decls, code) = t[3]
- t[0] = (decls, '\n%s:%sbreak;' % (label, indent(code)), is_default)
+ (decls, decode_code, exec_code) = t[3]
+ t[0] = (decls, '\n%s:%sbreak;' % (label, indent(decode_code)),
+ exec_code, is_default)
# The case label is either a list of one or more constants or 'default'
def p_case_label_0(t):
@@ -596,12 +591,13 @@ def p_inst_0(t):
'inst : ID LPAREN arg_list RPAREN'
# Pass the ID and arg list to the current format class to deal with.
currentFormat = formatStack.top()
- (decls, code) = currentFormat.defineInst(t[1], t[3], t.lineno(1))
+ (decls, decode_code, exec_code) = \
+ currentFormat.defineInst(t[1], t[3], t.lineno(1))
args = ','.join(map(str, t[3]))
args = re.sub('(?m)^', '//', args)
args = re.sub('^//', '', args)
comment = '// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
- t[0] = (comment + decls, comment + code)
+ t[0] = (comment + decls, comment + decode_code, comment + exec_code)
# Define an instruction using an explicitly specified format:
# "<fmt>::<mnemonic>(<args>)"
@@ -611,9 +607,10 @@ def p_inst_1(t):
format = formatMap[t[1]]
except KeyError:
error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
- (decls, code) = format.defineInst(t[3], t[5], t.lineno(1))
+ (decls, decode_code, exec_code) = \
+ format.defineInst(t[3], t[5], t.lineno(1))
comment = '// %s::%s(%s)\n' % (t[1], t[3], t[5])
- t[0] = (comment + decls, comment + code)
+ t[0] = (comment + decls, comment + decode_code, comment + exec_code)
def p_arg_list_0(t):
'arg_list : empty'
@@ -673,7 +670,8 @@ class Format:
code = ' pass\n'
param_list = string.join(params, ", ")
f = 'def defInst(name, Name, ' + param_list + '):\n' + code
- exec(f)
+ c = compile(f, 'def format ' + id, 'exec')
+ exec(c)
self.func = defInst
def defineInst(self, name, args, lineno):
@@ -773,8 +771,9 @@ def error(lineno, string):
# Like error(), but include a Python stack backtrace (for processing
# Python exceptions).
def error_bt(lineno, string):
+ traceback.print_exc()
print >> sys.stderr, "%s:%d: %s" % (isa_desc_filename, lineno, string)
- raise
+ sys.exit(1)
#####################################################################
@@ -944,7 +943,7 @@ class IntRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc, cpu_model):
+ def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to read integer register as FP')
@@ -955,7 +954,7 @@ class IntRegOperandTraits(OperandTraits):
return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \
(op_desc.munged_name, op_desc.src_reg_idx, size-1)
- def makeWrite(self, op_desc, cpu_model):
+ def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to write integer register as FP')
@@ -988,7 +987,7 @@ class FloatRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc, cpu_model):
+ def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0
if (type == 'float'):
@@ -1007,7 +1006,7 @@ class FloatRegOperandTraits(OperandTraits):
else:
return '%s = %s;\n' % (op_desc.munged_name, base)
- def makeWrite(self, op_desc, cpu_model):
+ def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
final_val = op_desc.munged_name
if (type == 'float'):
@@ -1044,7 +1043,7 @@ class ControlRegOperandTraits(OperandTraits):
(op_desc.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc, cpu_model):
+ def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
bit_select = 0
if (type == 'float' or type == 'double'):
@@ -1056,7 +1055,7 @@ class ControlRegOperandTraits(OperandTraits):
return '%s = bits(%s, %d, 0);\n' % \
(op_desc.munged_name, base, size-1)
- def makeWrite(self, op_desc, cpu_model):
+ def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
if (type == 'float' or type == 'double'):
error(0, 'Attempt to write control register as FP')
@@ -1087,16 +1086,16 @@ class MemOperandTraits(OperandTraits):
c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name
return c
- def makeRead(self, op_desc, cpu_model):
+ def makeRead(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
eff_type = 'uint%d_t' % size
- return 'fault = memAccessObj->read(EA, (%s&)%s, %s_flags);\n' \
+ return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \
% (eff_type, op_desc.munged_name, op_desc.base_name)
- def makeWrite(self, op_desc, cpu_model):
+ def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
eff_type = 'uint%d_t' % size
- return 'fault = memAccessObj->write((%s&)%s, EA, %s_flags,' \
+ return 'fault = xc->write((%s&)%s, EA, %s_flags,' \
' &%s_write_result);\n' \
% (eff_type, op_desc.munged_name, op_desc.base_name,
op_desc.base_name)
@@ -1105,10 +1104,10 @@ class NPCOperandTraits(OperandTraits):
def makeConstructor(self, op_desc):
return ''
- def makeRead(self, op_desc, cpu_model):
+ def makeRead(self, op_desc):
return '%s = xc->readPC() + 4;\n' % op_desc.munged_name
- def makeWrite(self, op_desc, cpu_model):
+ def makeWrite(self, op_desc):
return 'xc->setNextPC(%s);\n' % op_desc.munged_name
@@ -1172,21 +1171,17 @@ class OperandDescriptor:
def finalize(self):
self.flags = self.traits.getFlags(self)
self.constructor = self.traits.makeConstructor(self)
- self.exec_decl = self.traits.makeDecl(self)
+ self.op_decl = self.traits.makeDecl(self)
if self.is_src:
- self.simple_rd = self.traits.makeRead(self, 'simple')
- self.dtld_rd = self.traits.makeRead(self, 'dtld')
+ self.op_rd = self.traits.makeRead(self)
else:
- self.simple_rd = ''
- self.dtld_rd = ''
+ self.op_rd = ''
if self.is_dest:
- self.simple_wb = self.traits.makeWrite(self, 'simple')
- self.dtld_wb = self.traits.makeWrite(self, 'dtld')
+ self.op_wb = self.traits.makeWrite(self)
else:
- self.simple_wb = ''
- self.dtld_wb = ''
+ self.op_wb = ''
class OperandDescriptorList:
def __init__(self):
@@ -1348,32 +1343,21 @@ class CodeBlock:
self.constructor += \
'\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
- self.exec_decl = self.operands.concatAttrStrings('exec_decl')
+ self.op_decl = self.operands.concatAttrStrings('op_decl')
is_mem = lambda op: op.traits.isMem()
not_mem = lambda op: not op.traits.isMem()
- self.simple_rd = self.operands.concatAttrStrings('simple_rd')
- self.simple_wb = self.operands.concatAttrStrings('simple_wb')
- self.simple_mem_rd = \
- self.operands.concatSomeAttrStrings(is_mem, 'simple_rd')
- self.simple_mem_wb = \
- self.operands.concatSomeAttrStrings(is_mem, 'simple_wb')
- self.simple_nonmem_rd = \
- self.operands.concatSomeAttrStrings(not_mem, 'simple_rd')
- self.simple_nonmem_wb = \
- self.operands.concatSomeAttrStrings(not_mem, 'simple_wb')
-
- self.dtld_rd = self.operands.concatAttrStrings('dtld_rd')
- self.dtld_wb = self.operands.concatAttrStrings('dtld_wb')
- self.dtld_mem_rd = \
- self.operands.concatSomeAttrStrings(is_mem, 'dtld_rd')
- self.dtld_mem_wb = \
- self.operands.concatSomeAttrStrings(is_mem, 'dtld_wb')
- self.dtld_nonmem_rd = \
- self.operands.concatSomeAttrStrings(not_mem, 'dtld_rd')
- self.dtld_nonmem_wb = \
- self.operands.concatSomeAttrStrings(not_mem, 'dtld_wb')
+ self.op_rd = self.operands.concatAttrStrings('op_rd')
+ self.op_wb = self.operands.concatAttrStrings('op_wb')
+ self.op_mem_rd = \
+ self.operands.concatSomeAttrStrings(is_mem, 'op_rd')
+ self.op_mem_wb = \
+ self.operands.concatSomeAttrStrings(is_mem, 'op_wb')
+ self.op_nonmem_rd = \
+ self.operands.concatSomeAttrStrings(not_mem, 'op_rd')
+ self.op_nonmem_wb = \
+ self.operands.concatSomeAttrStrings(not_mem, 'op_wb')
self.flags = self.operands.concatAttrLists('flags')
@@ -1401,6 +1385,10 @@ class InstObjParams:
self.mnemonic = mnem
self.class_name = class_name
self.base_class = base_class
+ self.exec_func_declarations = '''
+ Fault execute(SimpleCPUExecContext *, Trace::InstRecord *);
+ Fault execute(FullCPUExecContext *, Trace::InstRecord *);
+'''
if code_block:
for code_attr in code_block.__dict__.keys():
setattr(self, code_attr, getattr(code_block, code_attr))
@@ -1431,20 +1419,48 @@ class InstObjParams:
else:
self.fp_enable_check = ''
+ def _subst(self, template):
+ try:
+ return template % self.__dict__
+ except KeyError, key:
+ raise KeyError, 'InstObjParams.subst: no definition for %s' % key
+
def subst(self, *args):
result = []
for t in args:
- if not templateMap.has_key(t):
+ try: template = templateMap[t]
+ except KeyError:
error(0, 'InstObjParams::subst: undefined template "%s"' % t)
- try:
- result.append(templateMap[t] % self.__dict__)
- except KeyError, key:
- error(0, 'InstObjParams::subst: no definition for "%s"' % key)
+ if template.find('%(cpu_model)') != -1:
+ tmp = ''
+ for cpu_model in ('SimpleCPUExecContext', 'FullCPUExecContext'):
+ self.cpu_model = cpu_model
+ tmp += self._subst(template)
+ result.append(tmp)
+ else:
+ result.append(self._subst(template))
if len(args) == 1:
result = result[0]
return result
#
-# All set... read in and parse the ISA description.
+# Read in and parse the ISA description.
#
-yacc.parse(isa_desc)
+def parse_isa_desc(isa_desc_file, decoder_file):
+ # Arguments are the name of the ISA description (input) file and
+ # the name of the C++ decoder (output) file.
+ global isa_desc_filename, decoder_filename
+ isa_desc_filename = isa_desc_file
+ decoder_filename = decoder_file
+
+ # Suck the ISA description file in.
+ input = open(isa_desc_filename)
+ isa_desc = input.read()
+ input.close()
+
+ # Parse it.
+ yacc.parse(isa_desc)
+
+# Called as script: get args from command line.
+if __name__ == '__main__':
+ parse_isa_desc(sys.argv[1], sys.argv[2])
diff --git a/base/compression/lzss_compression.cc b/base/compression/lzss_compression.cc
index 8f235b808..2f6c5d338 100644
--- a/base/compression/lzss_compression.cc
+++ b/base/compression/lzss_compression.cc
@@ -36,21 +36,32 @@
#include "base/misc.hh" //for fatal
-int
-LZSSCompression::findSubString(uint8_t *src, int front, int back, int size)
+void
+LZSSCompression::findSubString(uint8_t *src, int back, int size, uint16_t &L,
+ uint16_t &P)
{
- int subSize = 0;
- int max_length = 2048;
- if (size - back < max_length) {
- max_length = size - back;
- }
- for (int i = 0; i < max_length; ++i) {
- if (src[front+i] != src[back+i]) {
- return subSize;
+ int front = 0;
+ int max_length = size - back;
+ L = 0;
+ P = back - 1;
+ while (front < back) {
+ while (src[front] != src[back] && front < back) ++front;
+ if (front >= back) {
+ return;
+ }
+ int i = 1;
+ while (src[front+i] == src[back+i] && i < max_length) ++i;
+ if (i >= L) {
+ L = i;
+ P = front;
+ }
+ if (src[front+i] != src[back+i-1]) {
+ // can't find a longer substring until past this point.
+ front += i;
+ } else {
+ ++front;
}
- ++subSize;
}
- return subSize;
}
int
@@ -106,13 +117,7 @@ LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size)
++i;
continue;
}
- for (int j = 0; j < i; ++j) {
- int sub_size = findSubString(src, j, i, size);
- if (sub_size >= L) {
- L = sub_size;
- P = j;
- }
- }
+ findSubString(src, i, size, L, P);
if (L > 1) {
// Output the string reference
emitString(&dest[dest_index], P, L);
diff --git a/base/compression/lzss_compression.hh b/base/compression/lzss_compression.hh
index 755a52c92..9707a8aca 100644
--- a/base/compression/lzss_compression.hh
+++ b/base/compression/lzss_compression.hh
@@ -41,14 +41,15 @@
class LZSSCompression
{
/**
- * Finds the longest substrings that start at the given offsets.
+ * Finds the longest substring for the given offset.
* @param src The source block that we search for substrings.
- * @param front The smaller offset.
* @param back The larger offset.
* @param size The size of the source block.
- * @return The size of the longest substring.
+ * @param L The length of the largest substring.
+ * @param P The starting offset of the largest substring.
*/
- int findSubString(uint8_t *src, int front, int back, int size);
+ void findSubString(uint8_t *src, int back, int size, uint16_t &L,
+ uint16_t &P);
/**
* Emit an encoded byte to the compressed data array. If the 2 high
diff --git a/base/hashmap.hh b/base/hashmap.hh
index 995e98a90..59c1fe3aa 100644
--- a/base/hashmap.hh
+++ b/base/hashmap.hh
@@ -57,7 +57,7 @@ namespace m5 {
//
namespace __hash_namespace {
-#if !defined(__LP64__)
+#if !defined(__LP64__) && !defined(__alpha__)
template<>
struct hash<uint64_t> {
size_t operator()(uint64_t r) const {
diff --git a/base/hybrid_pred.cc b/base/hybrid_pred.cc
index 83ce7f987..12bab975b 100644
--- a/base/hybrid_pred.cc
+++ b/base/hybrid_pred.cc
@@ -31,7 +31,7 @@
#include "base/hybrid_pred.hh"
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
using namespace std;
diff --git a/base/hybrid_pred.hh b/base/hybrid_pred.hh
index 3fdab9153..9063f3084 100644
--- a/base/hybrid_pred.hh
+++ b/base/hybrid_pred.hh
@@ -41,9 +41,7 @@
#include <string>
#include "base/sat_counter.hh"
-
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
class HybridPredictor : public GenericPredictor
{
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
index 98e3198a6..a0c0c0551 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -36,6 +36,7 @@
// set this now (it causes things to break on 64-bit platforms).
#define __LIBELF64_LINUX 0
#define __LIBELF_NEED_LINK_H 0
+#define __LIBELF_SYMBOL_VERSIONS 0
#include <libelf/libelf.h>
#include <libelf/gelf.h>
diff --git a/base/mysql.cc b/base/mysql.cc
new file mode 100644
index 000000000..8481e74e2
--- /dev/null
+++ b/base/mysql.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#include <iostream>
+
+#include "base/mysql.hh"
+
+using namespace std;
+
+namespace MySQL {
+
+inline const char *
+charstar(const string &string)
+{
+ return string.empty() ? NULL : string.c_str();
+}
+
+ostream &
+operator<<(ostream &stream, const Error &error)
+{
+ stream << error.string();
+ return stream;
+}
+
+/*
+ * The connection class
+ */
+Connection::Connection()
+ : valid(false)
+{
+}
+
+Connection::~Connection()
+{
+ if (valid)
+ close();
+}
+
+
+bool
+Connection::connect(const string &xhost, const string &xuser,
+ const string &xpasswd, const string &xdatabase)
+{
+ if (connected())
+ return error.set("Already Connected");
+
+ _host = xhost;
+ _user = xuser;
+ _passwd = xpasswd;
+ _database = xdatabase;
+
+ error.clear();
+
+ mysql_init(&mysql);
+ mysql_options(&mysql, MYSQL_OPT_COMPRESS, 0); // might want to be 1
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "odbc");
+ if (!mysql_real_connect(&mysql, charstar(_host), charstar(_user),
+ charstar(_passwd), charstar(_database),
+ 0, NULL, 0))
+ return error.set(mysql_error(&mysql));
+
+ valid = true;
+ return false;
+}
+
+void
+Connection::close()
+{
+ mysql_close(&mysql);
+}
+
+/* namespace MySQL */ }
diff --git a/base/mysql.hh b/base/mysql.hh
new file mode 100644
index 000000000..89bec73d0
--- /dev/null
+++ b/base/mysql.hh
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_MYQSL_HH__
+#define __BASE_MYQSL_HH__
+
+#define TO_BE_INCLUDED_LATER 0
+
+#include <cassert>
+#include <iosfwd>
+#include <mysql.h>
+#include <string>
+#include <sstream>
+
+namespace MySQL {
+
+class Error
+{
+ protected:
+ const char *error;
+
+ public:
+ Error() : error(NULL) {}
+
+ Error &clear() { error = NULL; return *this; }
+ Error &set(const char *err) { error = err; return *this; }
+
+ const char *string() const { return error; }
+
+ operator bool() const { return error != NULL; }
+ bool operator!() const { return error == NULL; }
+};
+
+std::ostream &operator<<(std::ostream &stream, const Error &error);
+
+class Result
+{
+ private:
+ MYSQL_RES *result;
+ int *refcount;
+
+ void
+ decref()
+ {
+ if (!refcount)
+ return;
+
+ *refcount -= 1;
+ if (*refcount == 0) {
+ mysql_free_result(result);
+ delete refcount;
+ }
+
+ refcount = NULL;
+ }
+
+ public:
+ Result()
+ : result(0), refcount(NULL)
+ { }
+
+ Result(MYSQL_RES *res)
+ : result(res)
+ {
+ if (result)
+ refcount = new int(1);
+ }
+
+ Result(const Result &result)
+ : result(result.result), refcount(result.refcount)
+ {
+ if (result)
+ *refcount += 1;
+ }
+
+ ~Result()
+ {
+ decref();
+ }
+
+ const Result &
+ operator=(MYSQL_RES *res)
+ {
+ decref();
+ result = res;
+ if (result)
+ refcount = new int(1);
+
+ return *this;
+ }
+
+ const Result &
+ operator=(const Result &res)
+ {
+ decref();
+ result = res.result;
+ refcount = res.refcount;
+ if (result)
+ *refcount += 1;
+
+ return *this;
+ }
+
+ operator bool() const { return result != NULL; }
+ bool operator!() const { return result == NULL; }
+
+ unsigned
+ num_fields()
+ {
+ assert(result);
+ return mysql_num_fields(result);
+ }
+
+ MYSQL_ROW
+ fetch_row()
+ {
+ return mysql_fetch_row(result);
+ }
+
+ unsigned long *
+ fetch_lengths()
+ {
+ return mysql_fetch_lengths(result);
+ }
+};
+
+typedef MYSQL_ROW Row;
+
+class Connection
+{
+ protected:
+ MYSQL mysql;
+ bool valid;
+
+ protected:
+ std::string _host;
+ std::string _user;
+ std::string _passwd;
+ std::string _database;
+
+ public:
+ Connection();
+ virtual ~Connection();
+
+ bool connected() const { return valid; }
+ bool connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &database);
+ void close();
+
+ public:
+ Error error;
+ operator MYSQL *() { return &mysql; }
+
+ public:
+ bool
+ query(const std::string &sql)
+ {
+ error.clear();
+ if (mysql_real_query(&mysql, sql.c_str(), sql.size()))
+ error.set(mysql_error(&mysql));
+
+ return error;
+ }
+
+ bool
+ query(const std::stringstream &sql)
+ {
+ return query(sql.str());
+ }
+
+ unsigned
+ field_count()
+ {
+ return mysql_field_count(&mysql);
+ }
+
+ unsigned
+ affected_rows()
+ {
+ return mysql_affected_rows(&mysql);
+ }
+
+ unsigned
+ insert_id()
+ {
+ return mysql_insert_id(&mysql);
+ }
+
+
+ Result
+ store_result()
+ {
+ error.clear();
+ Result result = mysql_store_result(&mysql);
+ if (!result)
+ error.set(mysql_error(&mysql));
+
+ return result;
+ }
+};
+
+#if 0
+class BindProxy
+{
+ MYSQL_BIND *bind;
+ BindProxy(MYSQL_BIND *b) : bind(b) {}
+
+ void operator=(bool &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int8_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int16_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_SHORT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int32_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int64_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONGLONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint8_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint16_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_SHORT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint32_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint64_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONGLONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(float &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_FLOAT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(double &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_DOUBLE;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(Time &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_DATE;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(const char *buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind->buffer = buffer;
+ }
+
+ void operator=(const std::string &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind->buffer = (char *)&buffer;
+ bind->length = buffer.length;
+ }
+
+ bool
+ set_null(bool null)
+ {
+ bind->is_null = null;
+ }
+};
+
+class Statement
+{
+ protected:
+ Error &error;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND *bind;
+ int size;
+
+ public:
+ Statement(Connection &mysql)
+ : error(mysql.error), bind(NULL), size(0)
+ {
+ stmt = mysql_stmt_init(mysql);
+ assert(valid() && "mysql_stmt_init(), out of memory\n");
+ }
+
+ ~Statement()
+ {
+ assert(valid());
+ error.clear();
+ if (mysql_stmt_close(stmt))
+ error.set(mysql_stmt_error(stmt));
+
+ if (bind)
+ delete [] bind;
+ }
+
+ bool valid()
+ {
+ return stmt != NULL;
+ }
+
+ void prepare(const std::string &query)
+ {
+ assert(valid());
+ mysql.error.clear();
+ if (mysql_stmt_prepare(mysql, query, strlen(query)))
+ mysql.error.set(mysql_stmt_error(stmt));
+
+ int size = count();
+ bind = new MYSQL_BIND[size];
+ }
+
+ unsigned count()
+ {
+ assert(valid());
+ return mysql_stmt_param_count(stmt);
+ }
+
+ unsigned affected()
+ {
+ assert(valid());
+ return mysql_stmt_affected_rows(stmt);
+ }
+
+ void bind(MYSQL_BIND *bind)
+ {
+ mysql.error.clear();
+ if (mysql_stmt_bind_param(stmt, bind))
+ mysql.error.set(mysql_stmt_error(stmt));
+ }
+
+ BindProxy operator[](int index)
+ {
+ assert(index > 0 && index < N);
+ return &bind[N];
+ }
+
+ operator MYSQL_BIND *()
+ {
+ return bind;
+ }
+
+ void operator()()
+ {
+ assert(valid());
+ error.clear();
+ if (mysql_stmt_execute(stmt))
+ error.set(mysql_stmt_error(stmt));
+ }
+}
+#endif
+
+/* namespace MySQL */ }
+
+#endif // __BASE_MYQSL_HH__
diff --git a/base/sat_counter.cc b/base/sat_counter.cc
index c26690a1a..a8367d8a0 100644
--- a/base/sat_counter.cc
+++ b/base/sat_counter.cc
@@ -29,9 +29,8 @@
#include <sstream>
#include "base/sat_counter.hh"
-
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
using namespace std;
diff --git a/base/sat_counter.hh b/base/sat_counter.hh
index 62c18f6b4..a5d9c7e8a 100644
--- a/base/sat_counter.hh
+++ b/base/sat_counter.hh
@@ -34,7 +34,7 @@
#include "base/predictor.hh"
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
//
//
diff --git a/base/statistics.cc b/base/statistics.cc
index dce545f18..1a44cd342 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,343 +42,28 @@
#include "base/str.hh"
#include "base/time.hh"
#include "base/trace.hh"
-
-#ifdef __M5_NAN
-float
-__nan()
-{
- union {
- uint32_t ui;
- float f;
- } nan;
-
- nan.ui = 0x7fc00000;
- return nan.f;
-}
-#endif
-
-#ifdef DEBUG
-static int total_stats = 0;
-#endif
+#include "base/stats/statdb.hh"
using namespace std;
-// This is a hack to get this parameter from the old stats package.
namespace Statistics {
-bool PrintDescriptions = true;
-DisplayMode DefaultMode = mode_simplescalar;
-
-namespace Database
-{
- class Data
- {
- private:
- typedef list<StatData *> list_t;
- typedef map<void *, StatData *> map_t;
-
- list<MainBin *> bins;
-
- list_t allStats;
- list_t printStats;
- map_t statMap;
-
- ofstream *stream;
- Python *py;
-
- public:
- Data();
- ~Data();
-
- void dump(ostream &stream, DisplayMode mode);
- void display(ostream &stream, DisplayMode mode);
- void python_start(const string &file);
- void python_dump(const string &name, const string &subname);
- void python(const string &name, const string &subname,
- const string &bin);
-
- StatData *find(void *stat);
- void mapStat(void *stat, StatData *data);
-
- void check();
- void reset();
- void regBin(MainBin *bin, string name);
- void regPrint(void *stat);
-
- static std::string name() { return "Statistics Database"; }
- };
-
-Data::Data()
- : stream(0), py(0)
-{
-}
-
-Data::~Data()
-{
- if (stream) {
- delete py;
- ccprintf(*stream, "\n\nif __name__ == '__main__':\n");
- ccprintf(*stream, " program_display()\n");
- stream->close();
- delete stream;
- }
-}
-
-void
-Data::dump(ostream &stream, DisplayMode mode)
-{
- MainBin *orig = MainBin::curBin();
-
- switch (mode) {
- case mode_m5:
- case mode_simplescalar:
- display(stream, mode);
- break;
- default:
- warn("invalid display mode!\n");
- display(stream, mode_m5);
- break;
- }
-
- if (orig)
- orig->activate();
-}
-
-void
-Data::display(ostream &stream, DisplayMode mode)
-{
- if (!bins.empty()) {
- list<MainBin *>::iterator i = bins.begin();
- list<MainBin *>::iterator bins_end = bins.end();
- ccprintf(stream, "PRINTING BINNED STATS\n");
- while (i != bins_end) {
- (*i)->activate();
- ccprintf(stream,"---%s Bin------------\n", (*i)->name());
-
- list_t::iterator j = printStats.begin();
- list_t::iterator end = printStats.end();
- while (j != end) {
- StatData *stat = *j;
- if (stat->dodisplay())
- stat->display(stream, mode);
- ++j;
- }
- ++i;
- ccprintf(stream, "---------------------------------\n");
- }
- } else {
- list_t::iterator i = printStats.begin();
- list_t::iterator end = printStats.end();
- while (i != end) {
- StatData *stat = *i;
- if (stat->dodisplay() && !stat->binned())
- stat->display(stream, mode);
- ++i;
- }
- }
-}
-
-void
-Data::python_start(const string &file)
-{
- if (stream)
- panic("can't start python twice!");
-
- stream = new ofstream(file.c_str(), ios::trunc);
- py = new Python(*stream);
-
- ccprintf(*stream, "import sys\n");
- ccprintf(*stream, "sys.path.append('.')\n");
- ccprintf(*stream, "from m5stats import *\n\n");
-}
-
-void
-Data::python_dump(const string &name, const string &subname)
-{
- if (!py)
- panic("Can't dump python without first opening the file");
-
- if (bins.empty()) {
- python(name, subname, "");
- } else {
- list<MainBin *>::iterator i = bins.begin();
- list<MainBin *>::iterator end = bins.end();
-
- while (i != end) {
- (*i)->activate();
- python(name, subname, (*i)->name());
- ++i;
- }
- }
-}
-
-void
-Data::python(const string &name, const string &subname, const string &bin)
-{
- py->name("collections.append");
- py->newline();
- py->name("Collection");
- py->newline();
- py->qarg(name);
- py->newline();
- py->qarg(subname);
- py->newline();
- py->qarg(bin);
- py->newline();
- py->qarg(hostname());
- py->newline();
- py->qarg(Time::start.date());
- py->newline();
- py->list();
- list_t::iterator i = allStats.begin();
- list_t::iterator end = allStats.end();
- while (i != end) {
- StatData *stat = *i;
- py->newline();
- stat->python(*py);
- ++i;
- }
- py->newline();
- py->listEnd();
- py->newline();
- py->nameEnd();
- py->newline();
- py->nameEnd();
- py->newline();
-}
-
-StatData *
-Data::find(void *stat)
-{
- map_t::const_iterator i = statMap.find(stat);
-
- if (i == statMap.end())
- return NULL;
-
- return (*i).second;
-}
-
-void
-Data::check()
-{
- list_t::iterator i = allStats.begin();
- list_t::iterator end = allStats.end();
-
- while (i != end) {
- StatData *data = *i;
- assert(data);
- data->check();
- ++i;
- }
-
- i = allStats.begin();
- int j = 0;
- while (i != end) {
- StatData *data = *i;
- if (!(data->flags & print))
- data->name = "__Stat" + to_string(j++);
- ++i;
- }
-}
-
-void
-Data::reset()
-{
- // reset non-binned stats
- list_t::iterator i = allStats.begin();
- list_t::iterator end = allStats.end();
- while (i != end) {
- StatData *data = *i;
- if (!data->binned())
- data->reset();
- ++i;
- }
-
- // save the bin so we can go back to where we were
- MainBin *orig = MainBin::curBin();
-
- // reset binned stats
- list<MainBin *>::iterator bi = bins.begin();
- list<MainBin *>::iterator be = bins.end();
- while (bi != be) {
- MainBin *bin = *bi;
- bin->activate();
-
- i = allStats.begin();
- while (i != end) {
- StatData *data = *i;
- if (data->binned())
- data->reset();
- ++i;
- }
- ++bi;
- }
-
- // restore bin
- MainBin::curBin() = orig;
-}
-
-void
-Data::mapStat(void *stat, StatData *data)
-{
- if (statMap.find(stat) != statMap.end())
- panic("shouldn't register stat twice!");
-
- allStats.push_back(data);
-
-#ifndef NDEBUG
- bool success =
-#endif
- (statMap.insert(make_pair(stat, data))).second;
- assert(statMap.find(stat) != statMap.end());
- assert(success && "this should never fail");
-}
-
-void
-Data::regBin(MainBin *bin, string _name)
-{
- bins.push_back(bin);
- DPRINTF(Stats, "registering %s\n", _name);
-}
-
-void
-Data::regPrint(void *stat)
-{
- StatData *data = find(stat);
-
- if (data->flags & print)
- return;
-
- data->flags |= print;
-
- list_t::iterator j = printStats.insert(printStats.end(), data);
- inplace_merge(printStats.begin(), j, printStats.end(), StatData::less);
-}
-
-Data &
-StatDB()
-{
- static Data db;
- return db;
-}
-
-}
StatData *
DataAccess::find() const
{
- return Database::StatDB().find(const_cast<void *>((const void *)this));
+ return Database::find(const_cast<void *>((const void *)this));
}
const StatData *
getStatData(const void *stat)
{
- return Database::StatDB().find(const_cast<void *>(stat));
+ return Database::find(const_cast<void *>(stat));
}
void
DataAccess::map(StatData *data)
{
- Database::StatDB().mapStat(this, data);
+ Database::regStat(this, data);
}
StatData *
@@ -406,15 +91,14 @@ DataAccess::setInit()
void
DataAccess::setPrint()
{
- Database::StatDB().regPrint(this);
+ Database::regPrint(this);
}
StatData::StatData()
: flags(none), precision(-1), prereq(0)
{
-#ifdef DEBUG
- number = total_stats++;
-#endif
+ static int count = 0;
+ id = count++;
}
StatData::~StatData()
@@ -452,7 +136,7 @@ StatData::baseCheck() const
{
if (!(flags & init)) {
#ifdef DEBUG
- cprintf("this is stat number %d\n", number);
+ cprintf("this is stat number %d\n", id);
#endif
panic("Not all stats have been initialized");
return false;
@@ -466,719 +150,15 @@ StatData::baseCheck() const
return true;
}
-string
-ValueToString(result_t value, DisplayMode mode, int precision)
-{
- 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 << (mode == mode_m5 ? "no value" : "<err: div-0>");
- }
-
- return val.str();
-}
-
-struct ScalarPrint
-{
- result_t value;
- string name;
- string desc;
- StatFlags flags;
- DisplayMode mode;
- int precision;
- result_t pdf;
- result_t cdf;
-
- ScalarPrint()
- : value(0.0), flags(0), mode(DefaultMode), precision(0),
- pdf(NAN), cdf(NAN)
- {}
-
- 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 (mode == mode_simplescalar && flags & __substat) {
- ccprintf(stream, "%32s %12s %10s %10s", name,
- ValueToString(value, mode, precision), pdfstr, cdfstr);
- } else {
- ccprintf(stream, "%-40s %12s %10s %10s", name,
- ValueToString(value, mode, precision), pdfstr, cdfstr);
- }
-
- if (PrintDescriptions) {
- if (!desc.empty())
- ccprintf(stream, " # %s", desc);
- }
- stream << endl;
-}
-
-struct VectorPrint
-{
- string name;
- string desc;
- vector<string> subnames;
- vector<string> subdescs;
- StatFlags flags;
- DisplayMode mode;
- int precision;
- rvec_t vec;
- result_t total;
-
- VectorPrint()
- : subnames(0), subdescs(0), flags(0), mode(DefaultMode),
- precision(-1), total(NAN)
- {}
-
- void operator()(ostream &stream) const;
-};
-
-void
-VectorPrint::operator()(std::ostream &stream) const
-{
- int _size = vec.size();
- result_t _total = 0.0;
-
- if (flags & (pdf | cdf)) {
- for (int i = 0; i < _size; ++i) {
- _total += vec[i];
- }
- }
-
- string base = name + ((mode == mode_simplescalar) ? "_" : "::");
-
- ScalarPrint print;
- print.name = name;
- print.desc = desc;
- print.precision = precision;
- print.flags = flags;
-
- bool havesub = !subnames.empty();
-
- if (_size == 1) {
- print.value = vec[0];
- print(stream);
- } else if (mode == mode_m5) {
- 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 & ::Statistics::total) {
- print.name = base + "total";
- print.desc = desc;
- print.value = total;
- print(stream);
- }
- } else {
- if (flags & ::Statistics::total) {
- print.value = total;
- print(stream);
- }
-
- result_t _pdf = 0.0;
- result_t _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;
- DisplayMode mode;
- int precision;
-
- result_t min_val;
- result_t max_val;
- result_t underflow;
- result_t overflow;
- rvec_t vec;
- result_t sum;
- result_t squares;
- result_t samples;
-
- int min;
- int max;
- int bucket_size;
- int size;
- bool fancy;
-
- void operator()(ostream &stream) const;
-};
-
-void
-DistPrint::operator()(ostream &stream) const
-{
- if (fancy) {
- ScalarPrint print;
- string base = name + ((mode == mode_m5) ? "::" : "_");
-
- print.precision = precision;
- print.flags = flags;
- print.mode = mode;
- print.desc = desc;
-
- 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_t total = 0.0;
-
- total += underflow;
- for (int i = 0; i < size; ++i)
- total += vec[i];
- total += overflow;
-
- string base = name + (mode == mode_m5 ? "::" : ".");
-
- ScalarPrint print;
- print.desc = (mode == mode_m5) ? desc : "";
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
-
- if (mode == mode_simplescalar) {
- ccprintf(stream, "%-42s", base + "start_dist");
- if (PrintDescriptions && !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 (mode == mode_m5 || underflow > 0.0) {
- print.name = base + "underflows";
- print.value = underflow;
- if (mode == mode_m5 && total) {
- print.pdf = underflow / total;
- print.cdf += print.pdf;
- }
- print(stream);
- }
-
-
- if (mode == mode_m5) {
- for (int i = 0; i < size; ++i) {
- stringstream namestr;
- namestr << name;
-
- int low = i * bucket_size + min;
- int high = ::min((i + 1) * bucket_size + min - 1, 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 {
- int _min;
- result_t _pdf;
- result_t _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, mode, 0);
- print.value = vec[i];
- print.pdf = (flags & pdf) ? _pdf : NAN;
- print.cdf = (flags & cdf) ? _cdf : NAN;
- print(stream);
- }
-
- print.flags = flags;
- }
-
- if (mode == mode_m5 || overflow > 0.0) {
- print.name = base + "overflows";
- print.value = overflow;
- if (mode == mode_m5 && 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 (mode != mode_simplescalar) {
- print.name = base + "total";
- print.value = total;
- print(stream);
- }
-
- print.name = base + "max_value";
- print.value = max_val;
- print(stream);
-
- if (mode != mode_simplescalar && 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 (mode == mode_simplescalar)
- ccprintf(stream, "%send_dist\n\n", base);
-}
void
-ScalarDataBase::display(ostream &stream, DisplayMode mode) const
-{
- ScalarPrint print;
- print.value = val();
- print.name = name;
- print.desc = desc;
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
-
- print(stream);
-}
-
-void
-VectorDataBase::display(ostream &stream, DisplayMode mode) const
-{
- int size = this->size();
- const_cast<VectorDataBase *>(this)->update();
-
- VectorPrint print;
-
- print.name = name;
- print.desc = desc;
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
- print.vec = val();
- print.total = total();
-
- if (!subnames.empty()) {
- for (int i = 0; i < size; ++i) {
- if (!subnames[i].empty()) {
- print.subnames = subnames;
- print.subnames.resize(size);
- for (int i = 0; i < size; ++i) {
- if (!subnames[i].empty() && !subdescs[i].empty()) {
- print.subdescs = subdescs;
- print.subdescs.resize(size);
- break;
- }
- }
- break;
- }
- }
- }
-
- print(stream);
-}
-
-void
-Vector2dDataBase::display(ostream &stream, DisplayMode mode) const
-{
- const_cast<Vector2dDataBase *>(this)->update();
-
- bool havesub = false;
- VectorPrint print;
-
- print.subnames = y_subnames;
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
-
- if (!subnames.empty()) {
- for (int i = 0; i < x; ++i)
- if (!subnames[i].empty())
- havesub = true;
- }
-
- rvec_t tot_vec(y);
- result_t super_total = 0.0;
- for (int i = 0; i < x; ++i) {
- if (havesub && (i >= subnames.size() || subnames[i].empty()))
- continue;
-
- int iy = i * y;
- rvec_t yvec(y);
-
- result_t total = 0.0;
- for (int j = 0; j < y; ++j) {
- yvec[j] = vec[iy + j];
- tot_vec[j] += yvec[j];
- total += yvec[j];
- super_total += yvec[j];
- }
-
- print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
- print.desc = desc;
- print.vec = yvec;
- print.total = total;
- print(stream);
- }
-
- if ((flags & ::Statistics::total) && (x > 1)) {
- print.name = name;
- print.desc = desc;
- print.vec = tot_vec;
- print.total = super_total;
- print(stream);
- }
-}
-
-void
-DistDataBase::display(ostream &stream, DisplayMode mode) const
-{
- const_cast<DistDataBase *>(this)->update();
-
- DistPrint print;
-
- print.name = name;
- print.desc = desc;
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
-
- print.min_val = data.min_val;
- print.max_val = data.max_val;
- print.underflow = data.underflow;
- print.overflow = data.overflow;
- print.vec = data.vec;
- print.sum = data.sum;
- print.squares = data.squares;
- print.samples = data.samples;
-
- print.min = data.min;
- print.max = data.max;
- print.bucket_size = data.bucket_size;
- print.size = data.size;
- print.fancy = data.fancy;
-
- print(stream);
-}
-
-void
-VectorDistDataBase::display(ostream &stream, DisplayMode mode) const
-{
- const_cast<VectorDistDataBase *>(this)->update();
-
- for (int i = 0; i < size(); ++i) {
- DistPrint print;
-
- print.name = name +
- (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
- print.desc = subdescs[i].empty() ? desc : subdescs[i];
- print.flags = flags;
- print.mode = mode;
- print.precision = precision;
-
- print.min_val = data[i].min_val;
- print.max_val = data[i].max_val;
- print.underflow = data[i].underflow;
- print.overflow = data[i].overflow;
- print.vec = data[i].vec;
- print.sum = data[i].sum;
- print.squares = data[i].squares;
- print.samples = data[i].samples;
-
- print.min = data[i].min;
- print.max = data[i].max;
- print.bucket_size = data[i].bucket_size;
- print.size = data[i].size;
- print.fancy = data[i].fancy;
-
- print(stream);
- }
-}
-
-void
-ScalarDataBase::python(Python &py) const
-{
- py.name("Scalar");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
- py.kwarg("value", val());
- py.nameEnd();
-}
-
-void
-VectorDataBase::python(Python &py) const
-{
- const_cast<VectorDataBase *>(this)->update();
-
- py.name("Vector");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
- py.kwarg("value", val());
- if (!subnames.empty())
- py.qkwarg("subnames", subnames);
- if (!subdescs.empty())
- py.qkwarg("subdescs", subdescs);
- py.nameEnd();
-}
-
-void
-DistDataData::python(Python &py, const string &name) const
-{
- string s = name.empty() ? "" : name + "=";
-
- if (samples == 0 || fancy)
- s += "SimpleDist";
- else
- s += "FullDist";
-
- py.name(s);
- py.arg(sum);
- py.arg(squares);
- py.arg(samples);
- if (samples && !fancy) {
- py.arg(min_val);
- py.arg(min_val);
- py.arg(underflow);
- py.arg(vec);
- py.arg(overflow);
- py.arg(min);
- py.arg(max);
- py.arg(bucket_size);
- py.arg(size);
- }
- py.nameEnd();
-}
-
-void
-FormulaDataBase::python(Python &py) const
-{
- const_cast<FormulaDataBase *>(this)->update();
-
- py.name("Formula");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
- py.qkwarg("formula", str());
- if (!subnames.empty())
- py.qkwarg("subnames", subnames);
- if (!subdescs.empty())
- py.qkwarg("subdescs", subdescs);
- py.nameEnd();
-}
-
-void
-DistDataBase::python(Python &py) const
-{
- const_cast<DistDataBase *>(this)->update();
-
- py.name("Dist");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
- data.python(py, "dist");
- py.nameEnd();
-}
-
-void
-VectorDistDataBase::python(Python &py) const
-{
- const_cast<VectorDistDataBase *>(this)->update();
-
- py.name("VectorDist");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
- if (!subnames.empty())
- py.qkwarg("subnames", subnames);
- if (!subdescs.empty())
- py.qkwarg("subdescs", subdescs);
-
- py.tuple("dist");
- typedef std::vector<DistDataData>::const_iterator iter;
- iter i = data.begin();
- iter end = data.end();
- while (i != end) {
- i->python(py, "");
- ++i;
- }
- py.tupleEnd();
- py.nameEnd();
-}
-
-void
-Vector2dDataBase::python(Python &py) const
-{
- const_cast<Vector2dDataBase *>(this)->update();
-
- py.name("Vector2d");
- py.qarg(name);
- py.qqqarg(desc);
- py.kwarg("binned", binned());
- py.kwarg("precision", precision);
- py.kwarg("flags", flags);
- if (prereq)
- py.qkwarg("prereq", prereq->name);
-
- py.kwarg("value", vec);
- if (!subnames.empty())
- py.qkwarg("subnames", subnames);
- if (!subdescs.empty())
- py.qkwarg("subdescs", subdescs);
- if (!y_subnames.empty())
- py.qkwarg("ysubnames", y_subnames);
-
- py.kwarg("x", x);
- py.kwarg("y", y);
- py.nameEnd();
-}
-
-void
-FormulaBase::val(rvec_t &vec) const
+FormulaBase::result(VResult &vec) const
{
if (root)
- vec = root->val();
+ vec = root->result();
}
-result_t
+Result
FormulaBase::total() const
{
return root ? root->total() : 0.0;
@@ -1207,8 +187,8 @@ FormulaBase::reset()
bool
FormulaBase::zero() const
{
- rvec_t vec;
- val(vec);
+ VResult vec;
+ result(vec);
for (int i = 0; i < vec.size(); ++i)
if (vec[i] != 0.0)
return false;
@@ -1250,7 +230,7 @@ const Formula &
Formula::operator+=(Temp r)
{
if (root)
- root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
+ root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
else
root = r;
assert(size());
@@ -1260,7 +240,7 @@ Formula::operator+=(Temp r)
MainBin::MainBin(const string &name)
: _name(name), mem(NULL), memsize(-1)
{
- Database::StatDB().regBin(this, name);
+ Database::regBin(this, name);
}
MainBin::~MainBin()
@@ -1287,41 +267,83 @@ MainBin::memory(off_t off)
void
check()
{
- Database::StatDB().check();
-}
+ typedef Database::stat_list_t::iterator iter_t;
-void
-dump(ostream &stream, DisplayMode mode)
-{
- Database::StatDB().dump(stream, mode);
-}
+ iter_t i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ assert(data);
+ data->check();
+ }
-void
-python_start(const string &file)
-{
- Database::StatDB().python_start(file);
-}
+ int j = 0;
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (!(data->flags & print))
+ data->name = "__Stat" + to_string(j++);
+ }
-void
-python_dump(const string &name, const string &subname)
-{
- Database::StatDB().python_dump(name, subname);
-}
+ Database::stats().sort(StatData::less);
+
+ 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
-registerResetCallback(Callback *cb)
+reset()
{
- resetQueue.add(cb);
+ // reset non-binned stats
+ Database::stat_list_t::iterator i = Database::stats().begin();
+ Database::stat_list_t::iterator end = Database::stats().end();
+ while (i != end) {
+ StatData *data = *i;
+ if (!data->binned())
+ data->reset();
+ ++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;
+
+ resetQueue.process();
}
void
-reset()
+registerResetCallback(Callback *cb)
{
- Database::StatDB().reset();
- resetQueue.process();
+ resetQueue.add(cb);
}
-} // namespace Statistics
+/* namespace Statistics */ }
diff --git a/base/statistics.hh b/base/statistics.hh
index 0dad31a5a..e7fc18d74 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,8 @@
* VectorStandardDeviation totals
* Document Namespaces
*/
-#ifndef __STATISTICS_HH__
-#define __STATISTICS_HH__
+#ifndef __BASE_STATISTICS_HH__
+#define __BASE_STATISTICS_HH__
#include <algorithm>
#include <cassert>
@@ -58,66 +58,19 @@
#include "base/intmath.hh"
#include "base/refcnt.hh"
#include "base/str.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/visit.hh"
+#include "base/stats/types.hh"
#include "sim/host.hh"
-#ifndef NAN
-float __nan();
-/** Define Not a number. */
-#define NAN (__nan())
-/** Need to define __nan() */
-#define __M5_NAN
-#endif
-
class Callback;
-class Python;
/** The current simulated cycle. */
extern Tick curTick;
/* A namespace for all of the Statistics */
namespace Statistics {
-/** All results are doubles. */
-typedef double result_t;
-/** A vector to hold results. */
-typedef std::vector<result_t> rvec_t;
-
-/**
- * Define the storage for format flags.
- * @todo Can probably shrink this.
- */
-typedef u_int32_t StatFlags;
-
-/** Nothing extra to print. */
-const StatFlags none = 0x00000000;
-/** This Stat is Initialized */
-const StatFlags init = 0x00000001;
-/** Print this stat. */
-const StatFlags print = 0x00000002;
-/** Print the total. */
-const StatFlags total = 0x00000010;
-/** Print the percent of the total that this entry represents. */
-const StatFlags pdf = 0x00000020;
-/** Print the cumulative percentage of total upto this entry. */
-const StatFlags cdf = 0x00000040;
-/** Print the distribution. */
-const StatFlags dist = 0x00000080;
-/** Don't print if this is zero. */
-const StatFlags nozero = 0x00000100;
-/** Don't print if this is NAN */
-const StatFlags nonan = 0x00000200;
-/** Used for SS compatability. */
-const StatFlags __substat = 0x80000000;
-
-/** Mask of flags that can't be set directly */
-const StatFlags __reserved = init | print | __substat;
-
-enum DisplayMode
-{
- mode_m5,
- mode_simplescalar
-};
-
-extern DisplayMode DefaultMode;
/* Contains the statistic implementation details */
//////////////////////////////////////////////////////////////////////
@@ -135,10 +88,13 @@ struct StatData
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();
@@ -149,14 +105,6 @@ struct StatData
virtual bool binned() const = 0;
/**
- * Print this stat to the given ostream.
- * @param stream The stream to print to.
- */
- virtual void display(std::ostream &stream, DisplayMode mode) const = 0;
- virtual void python(Python &py) const = 0;
- bool dodisplay() const { return !prereq || !prereq->zero(); }
-
- /**
* Reset the corresponding stat to the default state.
*/
virtual void reset() = 0;
@@ -176,6 +124,11 @@ struct StatData
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.
@@ -184,51 +137,46 @@ struct StatData
* @return stat1's name is alphabetically before stat2's
*/
static bool less(StatData *stat1, StatData *stat2);
-
-#ifdef DEBUG
- int number;
-#endif
};
-struct ScalarDataBase : public StatData
+struct ScalarData : public StatData
{
- virtual result_t val() const = 0;
- virtual result_t total() const = 0;
-
- virtual void display(std::ostream &stream, DisplayMode mode) const;
- virtual void python(Python &py) const;
+ virtual Counter value() const = 0;
+ virtual Result result() const = 0;
+ virtual Result total() const = 0;
};
-template <class T>
-class ScalarData : public ScalarDataBase
+template <class Stat>
+class ScalarStatData : public ScalarData
{
protected:
- T &s;
+ Stat &s;
public:
- ScalarData(T &stat) : s(stat) {}
+ ScalarStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return s.binned(); }
virtual bool check() const { return s.check(); }
- virtual result_t val() const { return s.val(); }
- virtual result_t total() const { return s.total(); }
+ 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(); }
+
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
};
-struct VectorDataBase : public StatData
+struct VectorData : public StatData
{
/** Names and descriptions of subfields. */
mutable std::vector<std::string> subnames;
mutable std::vector<std::string> subdescs;
- virtual void display(std::ostream &stream, DisplayMode mode) const;
- virtual void python(Python &py) const;
-
virtual size_t size() const = 0;
- virtual const rvec_t &val() const = 0;
- virtual result_t total() const = 0;
- virtual void update()
+ 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();
@@ -241,15 +189,16 @@ struct VectorDataBase : public StatData
}
};
-template <class T>
-class VectorData : public VectorDataBase
+template <class Stat>
+class VectorStatData : public VectorData
{
protected:
- T &s;
- mutable rvec_t vec;
+ Stat &s;
+ mutable VCounter cvec;
+ mutable VResult rvec;
public:
- VectorData(T &stat) : s(stat) {}
+ VectorStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return s.binned(); }
virtual bool check() const { return s.check(); }
@@ -257,66 +206,70 @@ class VectorData : public VectorDataBase
virtual void reset() { s.reset(); }
virtual size_t size() const { return s.size(); }
- virtual const rvec_t &val() const
+ virtual VCounter &value() const
{
- s.val(vec);
- return vec;
+ s.value(cvec);
+ return cvec;
+ }
+ virtual const VResult &result() const
+ {
+ s.result(rvec);
+ return rvec;
}
- virtual result_t total() const { return s.total(); }
- virtual void update()
+ virtual Result total() const { return s.total(); }
+ virtual void visit(Visit &visitor)
{
- VectorDataBase::update();
+ update();
s.update(this);
+ visitor.visit(*this);
}
};
struct DistDataData
{
- result_t min_val;
- result_t max_val;
- result_t underflow;
- result_t overflow;
- rvec_t vec;
- result_t sum;
- result_t squares;
- result_t samples;
-
- int min;
- int max;
- int bucket_size;
+ 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;
-
- void python(Python &py, const std::string &name) const;
};
-struct DistDataBase : public StatData
+struct DistData : public StatData
{
/** Local storage for the entry values, used for printing. */
DistDataData data;
-
- virtual void display(std::ostream &stream, DisplayMode mode) const;
- virtual void python(Python &py) const;
- virtual void update() = 0;
};
-template <class T>
-class DistData : public DistDataBase
+template <class Stat>
+class DistStatData : public DistData
{
protected:
- T &s;
+ Stat &s;
public:
- DistData(T &stat) : s(stat) {}
+ DistStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return s.binned(); }
virtual bool check() const { return s.check(); }
virtual void reset() { s.reset(); }
virtual bool zero() const { return s.zero(); }
- virtual void update() { return s.update(this); }
+ virtual void visit(Visit &visitor)
+ {
+ s.update(this);
+ visitor.visit(*this);
+ }
};
-struct VectorDistDataBase : public StatData
+struct VectorDistData : public StatData
{
std::vector<DistDataData> data;
@@ -325,12 +278,10 @@ struct VectorDistDataBase : public StatData
mutable std::vector<std::string> subdescs;
/** Local storage for the entry values, used for printing. */
- mutable rvec_t vec;
+ mutable VResult rvec;
virtual size_t size() const = 0;
- virtual void display(std::ostream &stream, DisplayMode mode) const;
- virtual void python(Python &py) const;
- virtual void update()
+ void update()
{
int s = size();
if (subnames.size() < s)
@@ -341,29 +292,30 @@ struct VectorDistDataBase : public StatData
}
};
-template <class T>
-class VectorDistData : public VectorDistDataBase
+template <class Stat>
+class VectorDistStatData : public VectorDistData
{
protected:
- T &s;
- typedef typename T::bin_t bin_t;
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
public:
- VectorDistData(T &stat) : s(stat) {}
+ VectorDistStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return bin_t::binned; }
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 update()
+ virtual void visit(Visit &visitor)
{
- VectorDistDataBase::update();
- return s.update(this);
+ update();
+ s.update(this);
+ visitor.visit(*this);
}
};
-struct Vector2dDataBase : public StatData
+struct Vector2dData : public StatData
{
/** Names and descriptions of subfields. */
std::vector<std::string> subnames;
@@ -371,37 +323,36 @@ struct Vector2dDataBase : public StatData
std::vector<std::string> y_subnames;
/** Local storage for the entry values, used for printing. */
- mutable rvec_t vec;
+ mutable VCounter cvec;
mutable int x;
mutable int y;
- virtual void display(std::ostream &stream, DisplayMode mode) const;
- virtual void python(Python &py) const;
- virtual void update()
+ void update()
{
if (subnames.size() < x)
subnames.resize(x);
}
};
-template <class T>
-class Vector2dData : public Vector2dDataBase
+template <class Stat>
+class Vector2dStatData : public Vector2dData
{
protected:
- T &s;
- typedef typename T::bin_t bin_t;
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
public:
- Vector2dData(T &stat) : s(stat) {}
+ Vector2dStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return bin_t::binned; }
virtual bool check() const { return s.check(); }
virtual void reset() { s.reset(); }
virtual bool zero() const { return s.zero(); }
- virtual void update()
+ virtual void visit(Visit &visitor)
{
- Vector2dDataBase::update();
+ update();
s.update(this);
+ visitor.visit(*this);
}
};
@@ -502,8 +453,8 @@ class Wrap : public Child
* @param prereq The prerequisite stat.
* @return A reference to this stat.
*/
- template <class T>
- Parent &prereq(const T &prereq)
+ template <class Stat>
+ Parent &prereq(const Stat &prereq)
{
statData()->prereq = prereq.statData();
return self();
@@ -571,9 +522,9 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
Parent &ysubname(int index, const std::string subname)
{
Data<Child> *data = statData();
- assert(i < y);
+ assert(index < y);
data->y_subnames.resize(y);
- data->y_subnames[i] = subname.c_str();
+ data->y_subnames[index] = subname.c_str();
return self();
}
};
@@ -587,7 +538,6 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
/**
* Templatized storage and interface for a simple scalar stat.
*/
-template <typename T>
struct StatStor
{
public:
@@ -596,59 +546,54 @@ struct StatStor
private:
/** The statistic value. */
- T data;
- static T &Null()
- {
- static T __T = T();
- return __T;
- }
+ Counter data;
public:
/**
* Builds this storage element and calls the base constructor of the
* datatype.
*/
- StatStor(const Params &) : data(Null()) {}
+ 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(T val, const Params &p) { data = val; }
+ 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(T val, const Params &p) { data += val; }
+ 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(T val, const Params &p) { data -= val; }
+ void dec(Counter val, const Params &p) { data -= val; }
/**
- * Return the value of this stat as a result type.
- * @param p The parameters of this storage type.
+ * Return the value of this stat as its base type.
+ * @param p The params of this storage type.
* @return The value of this stat.
*/
- result_t val(const Params &p) const { return (result_t)data; }
+ Counter value(const Params &p) const { return data; }
/**
- * Return the value of this stat as its base type.
- * @param p The params of this storage type.
+ * Return the value of this stat as a result type.
+ * @param p The parameters of this storage type.
* @return The value of this stat.
*/
- T value(const Params &p) const { return data; }
+ Result result(const Params &p) const { return (Result)data; }
/**
* Reset stat value to default
*/
- void reset() { data = Null(); }
+ void reset() { data = Counter(); }
/**
* @return true if zero value
*/
- bool zero() const { return data == Null(); }
+ bool zero() const { return data == Counter(); }
};
/**
@@ -659,7 +604,6 @@ struct StatStor
* among other things.
* @todo add lateny to the stat and fix binning.
*/
-template <typename T>
struct AvgStor
{
public:
@@ -670,12 +614,12 @@ struct AvgStor
* The current count. We stash this here because the current
* value is not a binned value.
*/
- T current;
+ Counter current;
};
private:
/** The total count for all cycles. */
- mutable result_t total;
+ mutable Result total;
/** The cycle that current last changed. */
mutable Tick last;
@@ -683,7 +627,7 @@ struct AvgStor
/**
* Build and initializes this stat storage.
*/
- AvgStor(Params &p) : total(0), last(0) { p.current = T(); }
+ AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
/**
* Set the current count to the one provided, update the total and last
@@ -691,7 +635,7 @@ struct AvgStor
* @param val The new count.
* @param p The parameters for this storage.
*/
- void set(T val, Params &p) {
+ void set(Counter val, Params &p) {
total += p.current * (curTick - last);
last = curTick;
p.current = val;
@@ -702,34 +646,35 @@ struct AvgStor
* @param val The amount to increment.
* @param p The parameters for this storage.
*/
- void inc(T val, Params &p) { set(p.current + val, p); }
+ void inc(Counter val, Params &p) { set(p.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.
*/
- void dec(T val, Params &p) { set(p.current - val, p); }
+ void dec(Counter val, Params &p) { set(p.current - val, p); }
+
+ /**
+ * Return the current count.
+ * @param p The parameters for this storage.
+ * @return The current count.
+ */
+ Counter value(const Params &p) const { return p.current; }
/**
* Return the current average.
* @param p The parameters for this storage.
* @return The current average.
*/
- result_t val(const Params &p) const {
+ Result result(const Params &p) const
+ {
total += p.current * (curTick - last);
last = curTick;
- return (result_t)(total + p.current) / (result_t)(curTick + 1);
+ return (Result)(total + p.current) / (Result)(curTick + 1);
}
/**
- * Return the current count.
- * @param p The parameters for this storage.
- * @return The current count.
- */
- T value(const Params &p) const { return p.current; }
-
- /**
* Reset stat value to default
*/
void reset()
@@ -749,16 +694,14 @@ struct AvgStor
* Storage template. The storage for this stat is held within the Bin class.
* This allows for breaking down statistics across multiple bins easily.
*/
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class ScalarBase : public DataAccess
{
public:
- /** Define the type of the storage class. */
- typedef Storage<T> storage_t;
/** Define the params of the storage class. */
- typedef typename storage_t::Params params_t;
+ typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::Bin<storage_t> bin_t;
+ typedef typename Bin::Bin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -771,12 +714,12 @@ class ScalarBase : public DataAccess
* Retrieve the storage from the bin.
* @return The storage object for this stat.
*/
- storage_t *data() { return bin.data(params); }
+ Storage *data() { return bin.data(params); }
/**
* Retrieve a const pointer to the storage from the bin.
* @return A const pointer to the storage object for this stat.
*/
- const storage_t *data() const
+ const Storage *data() const
{
bin_t *_bin = const_cast<bin_t *>(&bin);
params_t *_params = const_cast<params_t *>(&params);
@@ -798,7 +741,7 @@ class ScalarBase : public DataAccess
* Return the current value of this stat as its base type.
* @return The current value.
*/
- T value() const { return data()->value(params); }
+ Counter value() const { return data()->value(params); }
public:
/**
@@ -869,11 +812,14 @@ class ScalarBase : public DataAccess
*/
void reset() { bin.reset(); }
- result_t val() { return data()->val(params); }
+ Counter value() { return data()->value(params); }
+
+ Result result() { return data()->result(params); }
- result_t total() { return val(); }
+ Result total() { return result(); }
+
+ bool zero() { return result() == 0.0; }
- bool zero() { return val() == 0.0; }
};
//////////////////////////////////////////////////////////////////////
@@ -881,23 +827,21 @@ class ScalarBase : public DataAccess
// Vector Statistics
//
//////////////////////////////////////////////////////////////////////
-template <typename T, template <typename T> class Storage, class Bin>
+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 <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class VectorBase : public DataAccess
{
public:
- /** Define the type of the storage class. */
- typedef Storage<T> storage_t;
/** Define the params of the storage class. */
- typedef typename storage_t::Params params_t;
+ typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::VectorBin<storage_t> bin_t;
+ typedef typename Bin::VectorBin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -911,14 +855,14 @@ class VectorBase : public DataAccess
* @param index The vector index to access.
* @return The storage object at the given index.
*/
- storage_t *data(int index) { return bin.data(index, params); }
+ 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_t *data(int index) const
+ const Storage *data(int index) const
{
bin_t *_bin = const_cast<bin_t *>(&bin);
params_t *_params = const_cast<params_t *>(&params);
@@ -933,15 +877,22 @@ class VectorBase : public DataAccess
const VectorBase &operator=(const VectorBase &);
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 val(rvec_t &vec) const
+ void result(VResult &vec) const
{
vec.resize(size());
for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->val(params);
+ vec[i] = data(i)->result(params);
}
/**
@@ -953,10 +904,10 @@ class VectorBase : public DataAccess
* Return a total of all entries in this vector.
* @return The total of all vector entries.
*/
- result_t total() const {
- result_t total = 0.0;
+ Result total() const {
+ Result total = 0.0;
for (int i = 0; i < size(); ++i)
- total += data(i)->val(params);
+ total += data(i)->result(params);
return total;
}
@@ -980,14 +931,14 @@ class VectorBase : public DataAccess
VectorBase() {}
/** Friend this class with the associated scalar proxy. */
- friend class ScalarProxy<T, Storage, Bin>;
+ 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<T, Storage, Bin> operator[](int index);
+ ScalarProxy<Storage, Bin> operator[](int index);
void update(StatData *data) {}
};
@@ -998,16 +949,14 @@ const StatData * getStatData(const void *stat);
* A proxy class to access the stat at a given index in a VectorBase stat.
* Behaves like a ScalarBase.
*/
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class ScalarProxy
{
public:
- /** Define the type of the storage class. */
- typedef Storage<T> storage_t;
/** Define the params of the storage class. */
- typedef typename storage_t::Params params_t;
+ typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::VectorBin<storage_t> bin_t;
+ typedef typename Bin::VectorBin<Storage> bin_t;
private:
/** Pointer to the bin in the parent VectorBase. */
@@ -1024,12 +973,12 @@ class ScalarProxy
* Retrieve the storage from the bin.
* @return The storage from the bin for this stat.
*/
- storage_t *data() { return bin->data(index, *params); }
+ 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_t *data() const
+ const Storage *data() const
{
bin_t *_bin = const_cast<bin_t *>(bin);
params_t *_params = const_cast<params_t *>(params);
@@ -1038,15 +987,16 @@ class ScalarProxy
public:
/**
- * Return the current value of this statas a result type.
+ * Return the current value of this stat as its base type.
* @return The current value.
*/
- result_t val() const { return data()->val(*params); }
+ Counter value() const { return data()->value(*params); }
+
/**
- * Return the current value of this stat as its base type.
+ * Return the current value of this statas a result type.
* @return The current value.
*/
- T value() const { return data()->value(*params); }
+ Result result() const { return data()->result(*params); }
public:
/**
@@ -1144,24 +1094,23 @@ class ScalarProxy
}
};
-template <typename T, template <typename T> class Storage, class Bin>
-inline ScalarProxy<T, Storage, Bin>
-VectorBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline ScalarProxy<Storage, Bin>
+VectorBase<Storage, Bin>::operator[](int index)
{
assert (index >= 0 && index < size());
- return ScalarProxy<T, Storage, Bin>(bin, params, index, this);
+ return ScalarProxy<Storage, Bin>(bin, params, index, this);
}
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class VectorProxy;
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class Vector2dBase : public DataAccess
{
public:
- typedef Storage<T> storage_t;
- typedef typename storage_t::Params params_t;
- typedef typename Bin::VectorBin<storage_t> bin_t;
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::VectorBin<Storage> bin_t;
protected:
size_t x;
@@ -1170,8 +1119,8 @@ class Vector2dBase : public DataAccess
params_t params;
protected:
- storage_t *data(int index) { return bin.data(index, params); }
- const storage_t *data(int index) const
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
{
bin_t *_bin = const_cast<bin_t *>(&bin);
params_t *_params = const_cast<params_t *>(&params);
@@ -1186,18 +1135,18 @@ class Vector2dBase : public DataAccess
public:
Vector2dBase() {}
- void update(Vector2dDataBase *data)
+ void update(Vector2dData *data)
{
int size = this->size();
- data->vec.resize(size);
+ data->cvec.resize(size);
for (int i = 0; i < size; ++i)
- data->vec[i] = this->data(i)->val(params);
+ data->cvec[i] = this->data(i)->value(params);
}
std::string ysubname(int i) const { return (*y_subnames)[i]; }
- friend class VectorProxy<T, Storage, Bin>;
- VectorProxy<T, Storage, Bin> operator[](int index);
+ friend class VectorProxy<Storage, Bin>;
+ VectorProxy<Storage, Bin> operator[](int index);
size_t size() const { return bin.size(); }
bool zero() const { return data(0)->value(params) == 0.0; }
@@ -1210,13 +1159,12 @@ class Vector2dBase : public DataAccess
bool check() { return bin.initialized(); }
};
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class VectorProxy
{
public:
- typedef Storage<T> storage_t;
- typedef typename storage_t::Params params_t;
- typedef typename Bin::VectorBin<storage_t> bin_t;
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::VectorBin<Storage> bin_t;
private:
bin_t *bin;
@@ -1226,36 +1174,36 @@ class VectorProxy
void *stat;
private:
- mutable rvec_t *vec;
+ mutable VResult *vec;
- storage_t *data(int index) {
+ Storage *data(int index) {
assert(index < len);
return bin->data(offset + index, *params);
}
- const storage_t *data(int index) const {
+ 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);
}
public:
- const rvec_t &val() const {
+ const VResult &result() const {
if (vec)
vec->resize(size());
else
- vec = new rvec_t(size());
+ vec = new VResult(size());
for (int i = 0; i < size(); ++i)
- (*vec)[i] = data(i)->val(*params);
+ (*vec)[i] = data(i)->result(*params);
return *vec;
}
- result_t total() const {
- result_t total = 0.0;
+ Result total() const {
+ Result total = 0.0;
for (int i = 0; i < size(); ++i)
- total += data(i)->val(*params);
+ total += data(i)->result(*params);
return total;
}
@@ -1290,11 +1238,10 @@ class VectorProxy
return *this;
}
- ScalarProxy<T, Storage, Bin> operator[](int index)
+ ScalarProxy<Storage, Bin> operator[](int index)
{
assert (index >= 0 && index < size());
- return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index,
- stat);
+ return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
}
size_t size() const { return len; }
@@ -1311,13 +1258,13 @@ class VectorProxy
void reset() { }
};
-template <typename T, template <typename T> class Storage, class Bin>
-inline VectorProxy<T, Storage, Bin>
-Vector2dBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline VectorProxy<Storage, Bin>
+Vector2dBase<Storage, Bin>::operator[](int index)
{
int offset = index * y;
assert (index >= 0 && offset < size());
- return VectorProxy<T, Storage, Bin>(bin, params, offset, y, this);
+ return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
}
//////////////////////////////////////////////////////////////////////
@@ -1329,7 +1276,6 @@ Vector2dBase<T, Storage, Bin>::operator[](int index)
/**
* Templatized storage and interface for a distrbution stat.
*/
-template <typename T>
struct DistStor
{
public:
@@ -1337,11 +1283,11 @@ struct DistStor
struct Params
{
/** The minimum value to track. */
- int min;
+ Counter min;
/** The maximum value to track. */
- int max;
+ Counter max;
/** The number of entries in each bucket. */
- int bucket_size;
+ Counter bucket_size;
/** The number of buckets. Equal to (max-min)/bucket_size. */
int size;
};
@@ -1349,21 +1295,21 @@ struct DistStor
private:
/** The smallest value sampled. */
- T min_val;
+ Counter min_val;
/** The largest value sampled. */
- T max_val;
+ Counter max_val;
/** The number of values sampled less than min. */
- T underflow;
+ Counter underflow;
/** The number of values sampled more than max. */
- T overflow;
+ Counter overflow;
/** The current sum. */
- T sum;
+ Counter sum;
/** The sum of squares. */
- T squares;
+ Counter squares;
/** The number of samples. */
- int samples;
+ Counter samples;
/** Counter for each bucket. */
- std::vector<T> vec;
+ VCounter cvec;
public:
/**
@@ -1371,8 +1317,9 @@ struct DistStor
* @param params The parameters.
*/
DistStor(const Params &params)
- : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
- sum(T()), squares(T()), samples(0), vec(params.size)
+ : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
+ overflow(Counter()), sum(Counter()), squares(Counter()),
+ samples(Counter()), cvec(params.size)
{
reset();
}
@@ -1383,16 +1330,16 @@ struct DistStor
* @param number The number of times to add the value.
* @param params The paramters of the distribution.
*/
- void sample(T val, int number, const Params &params)
+ void sample(Counter val, int number, const Params &params)
{
if (val < params.min)
underflow += number;
else if (val > params.max)
overflow += number;
else {
- int index = (val - params.min) / params.bucket_size;
+ int index = (int)floor((val - params.min) / params.bucket_size);
assert(index < size(params));
- vec[index] += number;
+ cvec[index] += number;
}
if (val < min_val)
@@ -1401,7 +1348,7 @@ struct DistStor
if (val > max_val)
max_val = val;
- T sample = val * number;
+ Counter sample = val * number;
sum += sample;
squares += sample * sample;
samples += number;
@@ -1412,7 +1359,7 @@ struct DistStor
* @return the number of buckets.
* @todo Is it faster to return the size from the parameters?
*/
- size_t size(const Params &) const { return vec.size(); }
+ size_t size(const Params &) const { return cvec.size(); }
/**
* Returns true if any calls to sample have been made.
@@ -1421,7 +1368,7 @@ struct DistStor
*/
bool zero(const Params &params) const
{
- return samples == 0;
+ return samples == Counter();
}
void update(DistDataData *data, const Params &params)
@@ -1435,9 +1382,9 @@ struct DistStor
data->max_val = (max_val == INT_MIN) ? 0 : max_val;
data->underflow = underflow;
data->overflow = overflow;
- data->vec.resize(params.size);
+ data->cvec.resize(params.size);
for (int i = 0; i < params.size; ++i)
- data->vec[i] = vec[i];
+ data->cvec[i] = cvec[i];
data->sum = sum;
data->squares = squares;
@@ -1454,13 +1401,13 @@ struct DistStor
underflow = 0;
overflow = 0;
- int size = vec.size();
+ int size = cvec.size();
for (int i = 0; i < size; ++i)
- vec[i] = T();
+ cvec[i] = Counter();
- sum = T();
- squares = T();
- samples = T();
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
}
};
@@ -1468,7 +1415,6 @@ struct DistStor
* Templatized storage and interface for a distribution that calculates mean
* and variance.
*/
-template <typename T>
struct FancyStor
{
public:
@@ -1480,17 +1426,19 @@ struct FancyStor
private:
/** The current sum. */
- T sum;
+ Counter sum;
/** The sum of squares. */
- T squares;
+ Counter squares;
/** The number of samples. */
- int samples;
+ Counter samples;
public:
/**
* Create and initialize this storage.
*/
- FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {}
+ FancyStor(const Params &)
+ : sum(Counter()), squares(Counter()), samples(Counter())
+ { }
/**
* Add a value the given number of times to this running average.
@@ -1500,9 +1448,9 @@ struct FancyStor
* @param number The number of times to add the value.
* @param p The parameters of this stat.
*/
- void sample(T val, int number, const Params &p)
+ void sample(Counter val, int number, const Params &p)
{
- T value = val * number;
+ Counter value = val * number;
sum += value;
squares += value * value;
samples += number;
@@ -1525,16 +1473,16 @@ struct FancyStor
* Return true if no samples have been added.
* @return True if no samples have been added.
*/
- bool zero(const Params &) const { return samples == 0; }
+ bool zero(const Params &) const { return samples == Counter(); }
/**
* Reset stat value to default
*/
void reset()
{
- sum = T();
- squares = T();
- samples = 0;
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
}
};
@@ -1542,7 +1490,6 @@ struct FancyStor
* Templatized storage for distribution that calculates per cycle mean and
* variance.
*/
-template <typename T>
struct AvgFancy
{
public:
@@ -1552,15 +1499,15 @@ struct AvgFancy
private:
/** Current total. */
- T sum;
+ Counter sum;
/** Current sum of squares. */
- T squares;
+ Counter squares;
public:
/**
* Create and initialize this storage.
*/
- AvgFancy(const Params &) : sum(T()), squares(T()) {}
+ AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
/**
* Add a value to the distribution for the given number of times.
@@ -1569,9 +1516,9 @@ struct AvgFancy
* @param number The number of times to add the value.
* @param p The paramters of the distribution.
*/
- void sample(T val, int number, const Params &p)
+ void sample(Counter val, int number, const Params &p)
{
- T value = val * number;
+ Counter value = val * number;
sum += value;
squares += value * value;
}
@@ -1592,14 +1539,14 @@ struct AvgFancy
* Return true if no samples have been added.
* @return True if the sum is zero.
*/
- bool zero(const Params &params) const { return sum == 0; }
+ bool zero(const Params &params) const { return sum == Counter(); }
/**
* Reset stat value to default
*/
void reset()
{
- sum = T();
- squares = T();
+ sum = Counter();
+ squares = Counter();
}
};
@@ -1607,16 +1554,14 @@ struct AvgFancy
* Implementation of a distribution stat. The type of distribution is
* determined by the Storage template. @sa ScalarBase
*/
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class DistBase : public DataAccess
{
public:
- /** Define the type of the storage class. */
- typedef Storage<T> storage_t;
/** Define the params of the storage class. */
- typedef typename storage_t::Params params_t;
+ typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::Bin<storage_t> bin_t;
+ typedef typename Bin::Bin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -1629,12 +1574,12 @@ class DistBase : public DataAccess
* Retrieve the storage from the bin.
* @return The storage object for this stat.
*/
- storage_t *data() { return bin.data(params); }
+ Storage *data() { return bin.data(params); }
/**
* Retrieve a const pointer to the storage from the bin.
* @return A const pointer to the storage object for this stat.
*/
- const storage_t *data() const
+ const Storage *data() const
{
bin_t *_bin = const_cast<bin_t *>(&bin);
params_t *_params = const_cast<params_t *>(&params);
@@ -1671,9 +1616,9 @@ class DistBase : public DataAccess
*/
bool zero() const { return data()->zero(params); }
- void update(DistDataBase *base)
+ void update(DistData *base)
{
- base->data.fancy = storage_t::fancy;
+ base->data.fancy = Storage::fancy;
data()->update(&(base->data), params);
}
/**
@@ -1691,24 +1636,23 @@ class DistBase : public DataAccess
bool check() { return bin.initialized(); }
};
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class DistProxy;
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class VectorDistBase : public DataAccess
{
public:
- typedef Storage<T> storage_t;
- typedef typename storage_t::Params params_t;
- typedef typename Bin::VectorBin<storage_t> bin_t;
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::VectorBin<Storage> bin_t;
protected:
bin_t bin;
params_t params;
protected:
- storage_t *data(int index) { return bin.data(index, params); }
- const storage_t *data(int index) const
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
{
bin_t *_bin = const_cast<bin_t *>(&bin);
params_t *_params = const_cast<params_t *>(&params);
@@ -1723,9 +1667,9 @@ class VectorDistBase : public DataAccess
public:
VectorDistBase() {}
- friend class DistProxy<T, Storage, Bin>;
- DistProxy<T, Storage, Bin> operator[](int index);
- const DistProxy<T, Storage, Bin> operator[](int index) const;
+ friend class DistProxy<Storage, Bin>;
+ DistProxy<Storage, Bin> operator[](int index);
+ const DistProxy<Storage, Bin> operator[](int index) const;
size_t size() const { return bin.size(); }
bool zero() const { return false; }
@@ -1740,25 +1684,24 @@ class VectorDistBase : public DataAccess
void reset() { bin.reset(); }
bool check() { return bin.initialized(); }
- void update(VectorDistDataBase *base)
+ void update(VectorDistData *base)
{
int size = this->size();
base->data.resize(size);
for (int i = 0; i < size; ++i) {
- base->data[i].fancy = storage_t::fancy;
+ base->data[i].fancy = Storage::fancy;
data(i)->update(&(base->data[i]), params);
}
}
};
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class DistProxy
{
public:
- typedef Storage<T> storage_t;
- typedef typename storage_t::Params params_t;
- typedef typename Bin::Bin<storage_t> bin_t;
- typedef VectorDistBase<T, Storage, Bin> base_t;
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::Bin<Storage> bin_t;
+ typedef VectorDistBase<Storage, Bin> base_t;
private:
union {
@@ -1768,11 +1711,11 @@ class DistProxy
int index;
protected:
- storage_t *data() { return stat->data(index); }
- const storage_t *data() const { return cstat->data(index); }
+ Storage *data() { return stat->data(index); }
+ const Storage *data() const { return cstat->data(index); }
public:
- DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
+ DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
: cstat(&s), index(i) {}
DistProxy(const DistProxy &sp)
: cstat(sp.cstat), index(sp.index) {}
@@ -1797,30 +1740,30 @@ class DistProxy
void reset() { }
};
-template <typename T, template <typename T> class Storage, class Bin>
-inline DistProxy<T, Storage, Bin>
-VectorDistBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index)
{
assert (index >= 0 && index < size());
- return DistProxy<T, Storage, Bin>(*this, index);
+ return DistProxy<Storage, Bin>(*this, index);
}
-template <typename T, template <typename T> class Storage, class Bin>
-inline const DistProxy<T, Storage, Bin>
-VectorDistBase<T, Storage, Bin>::operator[](int index) const
+template <class Storage, class Bin>
+inline const DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index) const
{
assert (index >= 0 && index < size());
- return DistProxy<T, Storage, Bin>(*this, index);
+ return DistProxy<Storage, Bin>(*this, index);
}
#if 0
-template <typename T, template <typename T> class Storage, class Bin>
-result_t
-VectorDistBase<T, Storage, Bin>::total(int index) const
+template <class Storage, class Bin>
+Result
+VectorDistBase<Storage, Bin>::total(int index) const
{
int total = 0;
for (int i=0; i < x_size(); ++i) {
- total += data(i)->val(*params);
+ total += data(i)->result(*params);
}
}
#endif
@@ -1847,12 +1790,12 @@ class Node : public RefCounted
* Return the result vector of this subtree.
* @return The result vector of this subtree.
*/
- virtual const rvec_t &val() const = 0;
+ virtual const VResult &result() const = 0;
/**
* Return the total of the result vector.
* @return The total of the result vector.
*/
- virtual result_t total() const = 0;
+ virtual Result total() const = 0;
/**
* Return true if stat is binned.
*@return True is stat is binned.
@@ -1871,17 +1814,17 @@ typedef RefCountingPtr<Node> NodePtr;
class ScalarStatNode : public Node
{
private:
- const ScalarDataBase *data;
- mutable rvec_t result;
+ const ScalarData *data;
+ mutable VResult vresult;
public:
- ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {}
- virtual const rvec_t &val() const
+ ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
+ virtual const VResult &result() const
{
- result[0] = data->val();
- return result;
+ vresult[0] = data->result();
+ return vresult;
}
- virtual result_t total() const { return data->val(); };
+ virtual Result total() const { return data->result(); };
virtual size_t size() const { return 1; }
/**
@@ -1896,22 +1839,22 @@ class ScalarStatNode : public Node
virtual std::string str() const { return data->name; }
};
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
class ScalarProxyNode : public Node
{
private:
- const ScalarProxy<T, Storage, Bin> proxy;
- mutable rvec_t result;
+ const ScalarProxy<Storage, Bin> proxy;
+ mutable VResult vresult;
public:
- ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
- : proxy(p), result(1) { }
- virtual const rvec_t &val() const
+ ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
+ : proxy(p), vresult(1) { }
+ virtual const VResult &result() const
{
- result[0] = proxy.val();
- return result;
+ vresult[0] = proxy.result();
+ return vresult;
}
- virtual result_t total() const { return proxy.val(); };
+ virtual Result total() const { return proxy.result(); };
virtual size_t size() const { return 1; }
/**
@@ -1929,12 +1872,12 @@ class ScalarProxyNode : public Node
class VectorStatNode : public Node
{
private:
- const VectorDataBase *data;
+ const VectorData *data;
public:
- VectorStatNode(const VectorDataBase *d) : data(d) { }
- virtual const rvec_t &val() const { return data->val(); }
- virtual result_t total() const { return data->total(); };
+ 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(); }
/**
@@ -1946,41 +1889,42 @@ class VectorStatNode : public Node
virtual std::string str() const { return data->name; }
};
-template <typename T>
+template <class T>
class ConstNode : public Node
{
private:
- rvec_t data;
+ VResult vresult;
public:
- ConstNode(T s) : data(1, (result_t)s) {}
- const rvec_t &val() const { return data; }
- virtual result_t total() const { return data[0]; };
-
+ 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 stat is binned.
*@return False since constants aren't binned.
*/
virtual bool binned() const { return false; }
- virtual std::string str() const { return to_string(data[0]); }
+ virtual std::string str() const { return to_string(vresult[0]); }
};
-template <typename T>
+template <class T>
class FunctorNode : public Node
{
private:
T &functor;
- mutable rvec_t result;
+ mutable VResult vresult;
public:
- FunctorNode(T &f) : functor(f) { result.resize(1); }
- const rvec_t &val() const {
- result[0] = (result_t)functor();
- return result;
+ FunctorNode(T &f) : functor(f) { vresult.resize(1); }
+ const VResult &result() const
+ {
+ vresult[0] = (Result)functor();
+ return vresult;
}
- virtual result_t total() const { return (result_t)functor(); };
+ virtual Result total() const { return (Result)functor(); };
virtual size_t size() const { return 1; }
/**
@@ -1991,20 +1935,21 @@ class FunctorNode : public Node
virtual std::string str() const { return to_string(functor()); }
};
-template <typename T>
+template <class T>
class ScalarNode : public Node
{
private:
T &scalar;
- mutable rvec_t result;
+ mutable VResult vresult;
public:
- ScalarNode(T &s) : scalar(s) { result.resize(1); }
- const rvec_t &val() const {
- result[0] = (result_t)scalar;
- return result;
+ ScalarNode(T &s) : scalar(s) { vresult.resize(1); }
+ const VResult &result() const
+ {
+ vresult[0] = (Result)scalar;
+ return vresult;
}
- virtual result_t total() const { return (result_t)scalar; };
+ virtual Result total() const { return (Result)scalar; };
virtual size_t size() const { return 1; }
/**
@@ -2019,37 +1964,37 @@ template <class Op>
struct OpString;
template<>
-struct OpString<std::plus<result_t> >
+struct OpString<std::plus<Result> >
{
static std::string str() { return "+"; }
};
template<>
-struct OpString<std::minus<result_t> >
+struct OpString<std::minus<Result> >
{
static std::string str() { return "-"; }
};
template<>
-struct OpString<std::multiplies<result_t> >
+struct OpString<std::multiplies<Result> >
{
static std::string str() { return "*"; }
};
template<>
-struct OpString<std::divides<result_t> >
+struct OpString<std::divides<Result> >
{
static std::string str() { return "/"; }
};
template<>
-struct OpString<std::modulus<result_t> >
+struct OpString<std::modulus<Result> >
{
static std::string str() { return "%"; }
};
template<>
-struct OpString<std::negate<result_t> >
+struct OpString<std::negate<Result> >
{
static std::string str() { return "-"; }
};
@@ -2059,26 +2004,27 @@ class UnaryNode : public Node
{
public:
NodePtr l;
- mutable rvec_t result;
+ mutable VResult vresult;
public:
UnaryNode(NodePtr &p) : l(p) {}
- const rvec_t &val() const {
- const rvec_t &lvec = l->val();
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
int size = lvec.size();
assert(size > 0);
- result.resize(size);
+ vresult.resize(size);
Op op;
for (int i = 0; i < size; ++i)
- result[i] = op(lvec[i]);
+ vresult[i] = op(lvec[i]);
- return result;
+ return vresult;
}
- result_t total() const {
+ Result total() const {
Op op;
return op(l->total());
}
@@ -2102,42 +2048,43 @@ class BinaryNode : public Node
public:
NodePtr l;
NodePtr r;
- mutable rvec_t result;
+ mutable VResult vresult;
public:
BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
- const rvec_t &val() const {
+ const VResult &result() const
+ {
Op op;
- const rvec_t &lvec = l->val();
- const rvec_t &rvec = r->val();
+ const VResult &lvec = l->result();
+ const VResult &rvec = r->result();
assert(lvec.size() > 0 && rvec.size() > 0);
if (lvec.size() == 1 && rvec.size() == 1) {
- result.resize(1);
- result[0] = op(lvec[0], rvec[0]);
+ vresult.resize(1);
+ vresult[0] = op(lvec[0], rvec[0]);
} else if (lvec.size() == 1) {
int size = rvec.size();
- result.resize(size);
+ vresult.resize(size);
for (int i = 0; i < size; ++i)
- result[i] = op(lvec[0], rvec[i]);
+ vresult[i] = op(lvec[0], rvec[i]);
} else if (rvec.size() == 1) {
int size = lvec.size();
- result.resize(size);
+ vresult.resize(size);
for (int i = 0; i < size; ++i)
- result[i] = op(lvec[i], rvec[0]);
+ vresult[i] = op(lvec[i], rvec[0]);
} else if (rvec.size() == lvec.size()) {
int size = rvec.size();
- result.resize(size);
+ vresult.resize(size);
for (int i = 0; i < size; ++i)
- result[i] = op(lvec[i], rvec[i]);
+ vresult[i] = op(lvec[i], rvec[i]);
}
- return result;
+ return vresult;
}
- result_t total() const {
+ Result total() const {
Op op;
return op(l->total(), r->total());
}
@@ -2171,37 +2118,39 @@ class SumNode : public Node
{
public:
NodePtr l;
- mutable rvec_t result;
+ mutable VResult vresult;
public:
- SumNode(NodePtr &p) : l(p), result(1) {}
+ SumNode(NodePtr &p) : l(p), vresult(1) {}
- const rvec_t &val() const {
- const rvec_t &lvec = l->val();
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
int size = lvec.size();
assert(size > 0);
- result[0] = 0.0;
+ vresult[0] = 0.0;
Op op;
for (int i = 0; i < size; ++i)
- result[0] = op(result[0], lvec[i]);
+ vresult[0] = op(vresult[0], lvec[i]);
- return result;
+ return vresult;
}
- result_t total() const {
- const rvec_t &lvec = l->val();
+ Result total() const
+ {
+ const VResult &lvec = l->result();
int size = lvec.size();
assert(size > 0);
- result_t result = 0.0;
+ Result vresult = 0.0;
Op op;
for (int i = 0; i < size; ++i)
- result = op(result, lvec[i]);
+ vresult = op(vresult, lvec[i]);
- return result;
+ return vresult;
}
virtual size_t size() const { return 1; }
@@ -2217,268 +2166,6 @@ class SumNode : public Node
}
};
-//////////////////////////////////////////////////////////////////////
-//
-// Binning Interface
-//
-//////////////////////////////////////////////////////////////////////
-struct MainBin
-{
- class BinBase;
- friend class MainBin::BinBase;
-
- private:
- std::string _name;
- char *mem;
-
- protected:
- off_t memsize;
- off_t size() const { return memsize; }
- char *memory(off_t off);
-
- public:
- static MainBin *&curBin()
- {
- static MainBin *current = NULL;
- return current;
- }
-
- static void setCurBin(MainBin *bin) { curBin() = bin; }
- static MainBin *current() { assert(curBin()); return curBin(); }
-
- static off_t &offset()
- {
- static off_t offset = 0;
- return offset;
- }
-
- static off_t new_offset(size_t size)
- {
- size_t mask = sizeof(u_int64_t) - 1;
- off_t off = offset();
-
- // That one is for the last trailing flags byte.
- offset() += (size + 1 + mask) & ~mask;
- return off;
- }
-
- public:
- MainBin(const std::string &name);
- ~MainBin();
-
- const std::string &
- name() const
- {
- return _name;
- }
-
- void
- activate()
- {
- setCurBin(this);
- }
-
- class BinBase
- {
- private:
- int offset;
-
- public:
- BinBase() : offset(-1) {}
- void allocate(size_t size)
- {
- offset = new_offset(size);
- }
- char *access()
- {
- assert(offset != -1);
- return current()->memory(offset);
- }
- };
-
- template <class Storage>
- class Bin : public BinBase
- {
- public:
- typedef typename Storage::Params Params;
-
- public:
- enum { binned = true };
- Bin() { allocate(sizeof(Storage)); }
- bool initialized() const { return true; }
- void init(Params &params) { }
-
- int size() const { return 1; }
-
- Storage *
- data(Params &params)
- {
- assert(initialized());
- char *ptr = access();
- char *flags = ptr + sizeof(Storage);
- if (!(*flags & 0x1)) {
- *flags |= 0x1;
- new (ptr) Storage(params);
- }
- return reinterpret_cast<Storage *>(ptr);
- }
-
- void
- reset()
- {
- char *ptr = access();
- char *flags = ptr + size() * sizeof(Storage);
- if (!(*flags & 0x1))
- return;
-
- Storage *s = reinterpret_cast<Storage *>(ptr);
- s->reset();
- }
- };
-
- template <class Storage>
- class VectorBin : public BinBase
- {
- public:
- typedef typename Storage::Params Params;
-
- private:
- int _size;
-
- public:
- enum { binned = true };
- VectorBin() : _size(0) {}
-
- bool initialized() const { return _size > 0; }
- void init(int s, Params &params)
- {
- assert(!initialized());
- assert(s > 0);
- _size = s;
- allocate(_size * sizeof(Storage));
- }
-
- int size() const { return _size; }
-
- Storage *data(int index, Params &params)
- {
- assert(initialized());
- assert(index >= 0 && index < size());
- char *ptr = access();
- char *flags = ptr + size() * sizeof(Storage);
- if (!(*flags & 0x1)) {
- *flags |= 0x1;
- for (int i = 0; i < size(); ++i)
- new (ptr + i * sizeof(Storage)) Storage(params);
- }
- return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
- }
- void reset()
- {
- char *ptr = access();
- char *flags = ptr + size() * sizeof(Storage);
- if (!(*flags & 0x1))
- return;
-
- for (int i = 0; i < _size; ++i) {
- char *p = ptr + i * sizeof(Storage);
- Storage *s = reinterpret_cast<Storage *>(p);
- s->reset();
- }
- }
- };
-};
-
-struct NoBin
-{
- template <class Storage>
- struct Bin
- {
- public:
- typedef typename Storage::Params Params;
- enum { binned = false };
-
- private:
- char ptr[sizeof(Storage)];
-
- public:
- ~Bin()
- {
- reinterpret_cast<Storage *>(ptr)->~Storage();
- }
-
- bool initialized() const { return true; }
- void init(Params &params)
- {
- new (ptr) Storage(params);
- }
- int size() const{ return 1; }
- Storage *data(Params &params)
- {
- assert(initialized());
- return reinterpret_cast<Storage *>(ptr);
- }
- void reset()
- {
- Storage *s = reinterpret_cast<Storage *>(ptr);
- s->reset();
- }
- };
-
- template <class Storage>
- struct VectorBin
- {
- public:
- typedef typename Storage::Params Params;
- enum { binned = false };
-
- private:
- char *ptr;
- int _size;
-
- public:
- VectorBin() : ptr(NULL) { }
- ~VectorBin()
- {
- if (!initialized())
- return;
-
- for (int i = 0; i < _size; ++i) {
- char *p = ptr + i * sizeof(Storage);
- reinterpret_cast<Storage *>(p)->~Storage();
- }
- delete [] ptr;
- }
-
- bool initialized() const { return ptr != NULL; }
- void init(int s, Params &params)
- {
- assert(s > 0 && "size must be positive!");
- assert(!initialized());
- _size = s;
- ptr = new char[_size * sizeof(Storage)];
- for (int i = 0; i < _size; ++i)
- new (ptr + i * sizeof(Storage)) Storage(params);
- }
-
- int size() const { return _size; }
-
- Storage *data(int index, Params &params)
- {
- assert(initialized());
- assert(index >= 0 && index < size());
- return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
- }
- void reset()
- {
- for (int i = 0; i < _size; ++i) {
- char *p = ptr + i * sizeof(Storage);
- Storage *s = reinterpret_cast<Storage *>(p);
- s->reset();
- }
- }
- };
-};
//////////////////////////////////////////////////////////////////////
//
@@ -2508,15 +2195,15 @@ typedef NoBin DefaultBin;
* This is a simple scalar statistic, like a counter.
* @sa Stat, ScalarBase, StatStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class Scalar
- : public Wrap<Scalar<T, Bin>,
- ScalarBase<T, StatStor, Bin>,
- ScalarData>
+ : public Wrap<Scalar<Bin>,
+ ScalarBase<StatStor, Bin>,
+ ScalarStatData>
{
public:
/** The base implementation. */
- typedef ScalarBase<T, StatStor, Bin> Base;
+ typedef ScalarBase<StatStor, Bin> Base;
Scalar()
{
@@ -2536,15 +2223,15 @@ class Scalar
* A stat that calculates the per cycle average of a value.
* @sa Stat, ScalarBase, AvgStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class Average
- : public Wrap<Average<T, Bin>,
- ScalarBase<T, AvgStor, Bin>,
- ScalarData>
+ : public Wrap<Average<Bin>,
+ ScalarBase<AvgStor, Bin>,
+ ScalarStatData>
{
public:
/** The base implementation. */
- typedef ScalarBase<T, AvgStor, Bin> Base;
+ typedef ScalarBase<AvgStor, Bin> Base;
Average()
{
@@ -2564,15 +2251,15 @@ class Average
* A vector of scalar stats.
* @sa Stat, VectorBase, StatStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class Vector
- : public WrapVec<Vector<T, Bin>,
- VectorBase<T, StatStor, Bin>,
- VectorData>
+ : public WrapVec<Vector<Bin>,
+ VectorBase<StatStor, Bin>,
+ VectorStatData>
{
public:
/** The base implementation. */
- typedef ScalarBase<T, StatStor, Bin> Base;
+ typedef ScalarBase<StatStor, Bin> Base;
/**
* Set this vector to have the given size.
@@ -2591,11 +2278,11 @@ class Vector
* A vector of Average stats.
* @sa Stat, VectorBase, AvgStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class AverageVector
- : public WrapVec<AverageVector<T, Bin>,
- VectorBase<T, AvgStor, Bin>,
- VectorData>
+ : public WrapVec<AverageVector<Bin>,
+ VectorBase<AvgStor, Bin>,
+ VectorStatData>
{
public:
/**
@@ -2615,11 +2302,11 @@ class AverageVector
* A 2-Dimensional vecto of scalar stats.
* @sa Stat, Vector2dBase, StatStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class Vector2d
- : public WrapVec2d<Vector2d<T, Bin>,
- Vector2dBase<T, StatStor, Bin>,
- Vector2dData>
+ : public WrapVec2d<Vector2d<Bin>,
+ Vector2dBase<StatStor, Bin>,
+ Vector2dStatData>
{
public:
Vector2d &init(size_t _x, size_t _y) {
@@ -2636,17 +2323,17 @@ class Vector2d
* A simple distribution stat.
* @sa Stat, DistBase, DistStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class Distribution
- : public Wrap<Distribution<T, Bin>,
- DistBase<T, DistStor, Bin>,
- DistData>
+ : public Wrap<Distribution<Bin>,
+ DistBase<DistStor, Bin>,
+ DistStatData>
{
public:
/** Base implementation. */
- typedef DistBase<T, DistStor, Bin> Base;
+ typedef DistBase<DistStor, Bin> Base;
/** The Parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2656,11 +2343,11 @@ class Distribution
* @param bkt The number of values in each bucket.
* @return A reference to this distribution.
*/
- Distribution &init(T min, T max, int bkt) {
+ Distribution &init(Counter min, Counter max, Counter bkt) {
params.min = min;
params.max = max;
params.bucket_size = bkt;
- params.size = (max - min) / bkt + 1;
+ params.size = (int)rint((max - min) / bkt + 1.0);
bin.init(params);
setInit();
@@ -2672,17 +2359,17 @@ class Distribution
* Calculates the mean and variance of all the samples.
* @sa Stat, DistBase, FancyStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class StandardDeviation
- : public Wrap<StandardDeviation<T, Bin>,
- DistBase<T, FancyStor, Bin>,
- DistData>
+ : public Wrap<StandardDeviation<Bin>,
+ DistBase<FancyStor, Bin>,
+ DistStatData>
{
public:
/** The base implementation */
- typedef DistBase<T, DistStor, Bin> Base;
+ typedef DistBase<DistStor, Bin> Base;
/** The parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2698,17 +2385,17 @@ class StandardDeviation
* Calculates the per cycle mean and variance of the samples.
* @sa Stat, DistBase, AvgFancy
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class AverageDeviation
- : public Wrap<AverageDeviation<T, Bin>,
- DistBase<T, AvgFancy, Bin>,
- DistData>
+ : public Wrap<AverageDeviation<Bin>,
+ DistBase<AvgFancy, Bin>,
+ DistStatData>
{
public:
/** The base implementation */
- typedef DistBase<T, DistStor, Bin> Base;
+ typedef DistBase<DistStor, Bin> Base;
/** The parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2725,17 +2412,17 @@ class AverageDeviation
* A vector of distributions.
* @sa Stat, VectorDistBase, DistStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class VectorDistribution
- : public WrapVec<VectorDistribution<T, Bin>,
- VectorDistBase<T, DistStor, Bin>,
- VectorDistData>
+ : public WrapVec<VectorDistribution<Bin>,
+ VectorDistBase<DistStor, Bin>,
+ VectorDistStatData>
{
public:
/** The base implementation */
- typedef VectorDistBase<T, DistStor, Bin> Base;
+ typedef VectorDistBase<DistStor, Bin> Base;
/** The parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2746,11 +2433,11 @@ class VectorDistribution
* @param bkt The number of values in each bucket.
* @return A reference to this distribution.
*/
- VectorDistribution &init(int size, T min, T max, int bkt) {
+ VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
params.min = min;
params.max = max;
params.bucket_size = bkt;
- params.size = (max - min) / bkt + 1;
+ params.size = (int)rint((max - min) / bkt + 1.0);
bin.init(size, params);
setInit();
@@ -2762,17 +2449,17 @@ class VectorDistribution
* This is a vector of StandardDeviation stats.
* @sa Stat, VectorDistBase, FancyStor
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class VectorStandardDeviation
- : public WrapVec<VectorStandardDeviation<T, Bin>,
- VectorDistBase<T, FancyStor, Bin>,
- VectorDistData>
+ : public WrapVec<VectorStandardDeviation<Bin>,
+ VectorDistBase<FancyStor, Bin>,
+ VectorDistStatData>
{
public:
/** The base implementation */
- typedef VectorDistBase<T, FancyStor, Bin> Base;
+ typedef VectorDistBase<FancyStor, Bin> Base;
/** The parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2792,17 +2479,17 @@ class VectorStandardDeviation
* This is a vector of AverageDeviation stats.
* @sa Stat, VectorDistBase, AvgFancy
*/
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
class VectorAverageDeviation
- : public WrapVec<VectorAverageDeviation<T, Bin>,
- VectorDistBase<T, AvgFancy, Bin>,
- VectorDistData>
+ : public WrapVec<VectorAverageDeviation<Bin>,
+ VectorDistBase<AvgFancy, Bin>,
+ VectorDistStatData>
{
public:
/** The base implementation */
- typedef VectorDistBase<T, AvgFancy, Bin> Base;
+ typedef VectorDistBase<AvgFancy, Bin> Base;
/** The parameter type. */
- typedef typename DistStor<T>::Params Params;
+ typedef typename DistStor::Params Params;
public:
/**
@@ -2838,7 +2525,7 @@ class FormulaBase : public DataAccess
* be x[0]/y, x[1]/y, x[2]/y, respectively.
* @return The result vector.
*/
- void val(rvec_t &vec) const;
+ void result(VResult &vec) const;
/**
* Return the total Formula result. If there is a Vector
@@ -2847,10 +2534,10 @@ class FormulaBase : public DataAccess
* 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 rvec_t val() returns.
+ * the first entry in the VResult val() returns.
* @return The total of the result vector.
*/
- result_t total() const;
+ Result total() const;
/**
* Return the number of elements in the tree.
@@ -2884,39 +2571,41 @@ class FormulaBase : public DataAccess
std::string str() const;
};
-class FormulaDataBase : public VectorDataBase
+class FormulaData : public VectorData
{
public:
virtual std::string str() const = 0;
virtual bool check() const { return true; }
- virtual void python(Python &py) const;
};
-template <class T>
-class FormulaData : public FormulaDataBase
+template <class Stat>
+class FormulaStatData : public FormulaData
{
protected:
- T &s;
- mutable rvec_t vec;
+ Stat &s;
+ mutable VResult vec;
+ mutable VCounter cvec;
public:
- FormulaData(T &stat) : s(stat) {}
+ FormulaStatData(Stat &stat) : s(stat) {}
virtual bool binned() const { return s.binned(); }
virtual bool zero() const { return s.zero(); }
virtual void reset() { s.reset(); }
virtual size_t size() const { return s.size(); }
- virtual const rvec_t &val() const
+ virtual const VResult &result() const
{
- s.val(vec);
+ s.result(vec);
return vec;
}
- virtual result_t total() const { return s.total(); }
- virtual void update()
+ virtual Result total() const { return s.total(); }
+ virtual VCounter &value() const { return cvec; }
+ virtual void visit(Visit &visitor)
{
- VectorDataBase::update();
+ update();
s.update(this);
+ visitor.visit(*this);
}
virtual std::string str() const { return s.str(); }
};
@@ -2925,7 +2614,7 @@ class Temp;
class Formula
: public WrapVec<Formula,
FormulaBase,
- FormulaData>
+ FormulaStatData>
{
public:
/**
@@ -2959,14 +2648,14 @@ class FormulaNode : public Node
{
private:
const Formula &formula;
- mutable rvec_t vec;
+ mutable VResult vec;
public:
FormulaNode(const Formula &f) : formula(f) {}
virtual size_t size() const { return formula.size(); }
- virtual const rvec_t &val() const { formula.val(vec); return vec; }
- virtual result_t total() const { return formula.total(); }
+ virtual const VResult &result() const { formula.result(vec); return vec; }
+ virtual Result total() const { return formula.total(); }
virtual bool binned() const { return formula.binned(); }
virtual std::string str() const { return formula.str(); }
@@ -3001,24 +2690,24 @@ class Temp
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
- template <typename T, class Bin>
- Temp(const Scalar<T, Bin> &s)
+ template <class Bin>
+ Temp(const Scalar<Bin> &s)
: node(new ScalarStatNode(s.statData())) { }
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
- template <typename T, class Bin>
- Temp(const Average<T, Bin> &s)
+ template <class Bin>
+ Temp(const Average<Bin> &s)
: node(new ScalarStatNode(s.statData())) { }
/**
* Create a new VectorStatNode.
* @param s The VectorStat to place in a node.
*/
- template <typename T, class Bin>
- Temp(const Vector<T, Bin> &s)
+ template <class Bin>
+ Temp(const Vector<Bin> &s)
: node(new VectorStatNode(s.statData())) { }
/**
@@ -3031,9 +2720,9 @@ class Temp
* Create a new ScalarProxyNode.
* @param p The ScalarProxy to place in a node.
*/
- template <typename T, template <typename T> class Storage, class Bin>
- Temp(const ScalarProxy<T, Storage, Bin> &p)
- : node(new ScalarProxyNode<T, Storage, Bin>(p)) { }
+ template <class Storage, class Bin>
+ Temp(const ScalarProxy<Storage, Bin> &p)
+ : node(new ScalarProxyNode<Storage, Bin>(p)) { }
/**
* Create a ConstNode
@@ -3126,46 +2815,43 @@ class Temp
*/
void check();
-void dump(std::ostream &stream, DisplayMode mode = DefaultMode);
-void python_start(const std::string &file);
-void python_dump(const std::string &name, const std::string &subname);
void reset();
void registerResetCallback(Callback *cb);
inline Temp
operator+(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
+ return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
}
inline Temp
operator-(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
+ return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
}
inline Temp
operator*(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
+ return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
}
inline Temp
operator/(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
+ return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
}
inline Temp
operator%(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
+ return NodePtr(new BinaryNode<std::modulus<Result> >(l, r));
}
inline Temp
operator-(Temp l)
{
- return NodePtr(new UnaryNode<std::negate<result_t> >(l));
+ return NodePtr(new UnaryNode<std::negate<Result> >(l));
}
template <typename T>
@@ -3192,10 +2878,9 @@ scalar(T &val)
inline Temp
sum(Temp val)
{
- return NodePtr(new SumNode<std::plus<result_t> >(val));
+ return NodePtr(new SumNode<std::plus<Result> >(val));
}
-extern bool PrintDescriptions;
-} // namespace statistics
+/* namespace Statistics */ }
-#endif // __STATISTICS_HH__
+#endif // __BASE_STATISTICS_HH__
diff --git a/base/stats/flags.hh b/base/stats/flags.hh
new file mode 100644
index 000000000..2303de172
--- /dev/null
+++ b/base/stats/flags.hh
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_FLAGS_HH__
+#define __BASE_STATS_FLAGS_HH__
+namespace Statistics {
+
+/**
+ * Define the storage for format flags.
+ * @todo Can probably shrink this.
+ */
+typedef u_int32_t StatFlags;
+
+/** Nothing extra to print. */
+const StatFlags none = 0x00000000;
+/** This Stat is Initialized */
+const StatFlags init = 0x00000001;
+/** Print this stat. */
+const StatFlags print = 0x00000002;
+/** Print the total. */
+const StatFlags total = 0x00000010;
+/** Print the percent of the total that this entry represents. */
+const StatFlags pdf = 0x00000020;
+/** Print the cumulative percentage of total upto this entry. */
+const StatFlags cdf = 0x00000040;
+/** Print the distribution. */
+const StatFlags dist = 0x00000080;
+/** Don't print if this is zero. */
+const StatFlags nozero = 0x00000100;
+/** Don't print if this is NAN */
+const StatFlags nonan = 0x00000200;
+/** Used for SS compatability. */
+const StatFlags __substat = 0x80000000;
+
+/** Mask of flags that can't be set directly */
+const StatFlags __reserved = init | print | __substat;
+
+enum DisplayMode
+{
+ mode_m5,
+ mode_simplescalar
+};
+
+extern DisplayMode DefaultMode;
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_FLAGS_HH__
diff --git a/base/stats/mysql.cc b/base/stats/mysql.cc
new file mode 100644
index 000000000..676bc555c
--- /dev/null
+++ b/base/stats/mysql.cc
@@ -0,0 +1,844 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#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/statdb.hh"
+#include "base/stats/types.hh"
+#include "base/str.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Statistics {
+
+struct MySqlData
+{
+ map<int, int> idmap;
+ MySQL::Connection conn;
+};
+
+int
+SetupRun(MySqlData *data, const string &name, const string &user,
+ const string &project)
+{
+ MySQL::Connection &mysql = data->conn;
+ assert(mysql.connected());
+
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO "
+ "runs(rn_name, rn_user, rn_project, rn_date, rn_expire)"
+ "values(\"%s\", \"%s\", \"%s\", NOW(),"
+ "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
+ name, user, project);
+
+ mysql.query(insert);
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ return mysql.insert_id();
+}
+
+void
+DeleteRun(MySqlData *data, const string &name)
+{
+ MySQL::Connection &mysql = data->conn;
+ assert(mysql.connected());
+ stringstream sql;
+ ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name);
+ mysql.query(sql);
+}
+
+void
+Cleanup(MySqlData *data)
+{
+ MySQL::Connection &mysql = data->conn;
+ assert(mysql.connected());
+
+ mysql.query("DELETE data "
+ "FROM data "
+ "LEFT JOIN runs ON dt_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ mysql.query("DELETE formula_ref "
+ "FROM formula_ref "
+ "LEFT JOIN runs ON fr_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ mysql.query("DELETE formulas "
+ "FROM formulas "
+ "LEFT JOIN formula_ref ON fm_stat=fr_stat "
+ "WHERE fr_stat IS NULL");
+
+ mysql.query("DELETE stats "
+ "FROM stats "
+ "LEFT JOIN data ON st_id=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ mysql.query("DELETE subdata "
+ "FROM subdata "
+ "LEFT JOIN data ON sd_stat=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ mysql.query("DELETE bins "
+ "FROM bins "
+ "LEFT JOIN data ON bn_id=dt_bin "
+ "WHERE dt_bin IS NULL");
+}
+
+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::operator()(MySqlData *data)
+{
+ MySQL::Connection &mysql = data->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)
+ return mysql.insert_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 get a run\n%s\n", mysql.error);
+
+
+ assert(result.num_fields() == 16);
+ MySQL::Row row = result.fetch_row();
+ if (!row)
+ panic("could not get a run\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;
+}
+
+unsigned
+SetupBin(MySqlData *data, const string &bin)
+{
+ MySQL::Connection &mysql = data->conn;
+ assert(mysql.connected());
+
+ using namespace MySQL;
+ stringstream select;
+ 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);
+ Row row = result.fetch_row();
+ if (row) {
+ uint16_t bin_id;
+ to_number(row[0], bin_id);
+ return bin_id;
+ }
+ }
+
+ stringstream insert;
+ ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin);
+
+ mysql.query(insert);
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ return mysql.insert_id();
+}
+
+InsertData::InsertData()
+{
+ query = new char[maxsize + 1];
+ size = 0;
+ flush();
+}
+
+InsertData::~InsertData()
+{
+ delete [] query;
+}
+
+void
+InsertData::flush()
+{
+ if (size) {
+ assert(mysql && mysql->connected());
+ mysql->query(query);
+ }
+
+ query[0] = '\0';
+ size = 0;
+ first = true;
+ strcpy(query, "INSERT INTO "
+ "data(dt_stat,dt_x,dt_y,dt_run,dt_sample,dt_bin,dt_data) "
+ "values");
+ size = strlen(query);
+}
+
+void
+InsertData::insert()
+{
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
+ size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
+ stat, x, y, run, (unsigned long long)sample, bin, data);
+}
+
+struct InsertSubData
+{
+ uint16_t stat;
+ int16_t x;
+ int16_t y;
+ string name;
+ string descr;
+
+ void operator()(MySqlData *data);
+};
+
+void
+InsertSubData::operator()(MySqlData *data)
+{
+ MySQL::Connection &mysql = data->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);
+}
+
+void
+InsertFormula(MySqlData *data, uint16_t stat, uint16_t run,
+ const string &formula)
+{
+ MySQL::Connection &mysql = data->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);
+
+ stringstream insert_ref;
+ ccprintf(insert_ref,
+ "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+ stat, run);
+
+ mysql.query(insert_ref);
+}
+
+void
+UpdatePrereq(MySqlData *data, uint16_t stat, uint16_t prereq)
+{
+ MySQL::Connection &mysql = data->conn;
+ assert(mysql.connected());
+ stringstream update;
+ ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+ prereq, stat);
+ mysql.query(update);
+}
+
+#if 0
+class InsertData
+{
+ private:
+ MySQL::Connection &mysql;
+ MySQL::Statement stmt;
+
+ public:
+ InsertData(MySqlData *data)
+ : mysql(data->conn)
+ {
+ stmt.prepare("INSERT INTO "
+ "data(dt_stat,dt_x,dt_y,dt_run,dt_sample,dt_bin,dt_data) "
+ "values(?,?,?,?,?,?,?)");
+ assert(stmt.count() == 7 && "param count invalid");
+
+ stmt[0].buffer = stat;
+ stmt[1].buffer = x;
+ stmt[2].buffer = y;
+ stmt[3].buffer = run;
+ stmt[4].buffer = sample;
+ stmt[5].buffer = bin;
+ stmt[6].buffer = data;
+
+ stmt.bind(bind);
+ if (stmt.error)
+ panic("bind param failed\n%s\n", stmt.error);
+ }
+
+ public:
+ uint64_t sample;
+ uint64_t data;
+ uint16_t stat;
+ uint16_t bin;
+ int16_t x;
+ int16_t y;
+
+ void operator()(MySQL::Connection &mysql)
+ {
+ assert(mysql.connected())
+ stmt();
+ }
+};
+#endif
+
+
+MySql::MySql()
+ : mysql(NULL), configured(false)
+{
+}
+
+MySql::~MySql()
+{
+ if (mysql)
+ delete mysql;
+}
+
+void
+MySql::insert(int sim_id, int db_id)
+{
+ mysql->idmap.insert(make_pair(sim_id, db_id));
+}
+
+int
+MySql::find(int sim_id)
+{
+ map<int,int>::const_iterator i = mysql->idmap.find(sim_id);
+ assert(i != mysql->idmap.end());
+ return (*i).second;
+}
+
+bool
+MySql::valid() const
+{
+ return mysql && mysql->conn.connected();
+}
+
+void
+MySql::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &project)
+{
+ mysql = new MySqlData;
+ newdata.mysql = &mysql->conn;
+ mysql->conn.connect(host, user, passwd, db);
+ if (mysql->conn.error)
+ panic("could not connect to database server\n%s\n", mysql->conn.error);
+
+ DeleteRun(mysql, name);
+ Cleanup(mysql);
+ run_id = SetupRun(mysql, name, user, project);
+}
+
+void
+MySql::configure()
+{
+ /*
+ * set up all stats!
+ */
+ using namespace Database;
+ 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(mysql, stat_id, prereq_id);
+ }
+ }
+
+ configured = true;
+}
+
+
+void
+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;
+}
+
+void
+MySql::configure(const ScalarData &data)
+{
+ configure(data, "SCALAR");
+ insert(data.id, stat(mysql));
+}
+
+void
+MySql::configure(const VectorData &data)
+{
+ configure(data, "VECTOR");
+ uint16_t statid = stat(mysql);
+
+ 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(mysql);
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const DistData &data)
+{
+ configure(data, "DIST");
+ 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(mysql));
+}
+
+void
+MySql::configure(const VectorDistData &data)
+{
+ configure(data, "VECTORDIST");
+
+ 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(mysql);
+
+ 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(mysql);
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const Vector2dData &data)
+{
+ configure(data, "VECTOR2D");
+ uint16_t statid = stat(mysql);
+
+ 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(mysql);
+ }
+ }
+
+ if (!data.y_subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.x = 0;
+ 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(mysql);
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const FormulaData &data)
+{
+ configure(data, "FORMULA");
+ insert(data.id, stat(mysql));
+}
+
+void
+MySql::output(const string &bin)
+{
+ // set up new bin in database if there is a bin name
+ newdata.bin = bin.empty() ? 0 : SetupBin(mysql, bin);
+
+ Database::stat_list_t::const_iterator i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+}
+
+void
+MySql::output()
+{
+ using namespace Database;
+ assert(valid());
+
+ if (!configured)
+ configure();
+
+ // store sample #
+ newdata.run = run_id;
+ newdata.sample = curTick;
+
+ if (bins().empty()) {
+ output(string(""));
+ } else {
+ bin_list_t::iterator i, end = bins().end();
+ for (i = bins().begin(); i != end; ++i) {
+ MainBin *bin = *i;
+ bin->activate();
+ output(bin->name());
+ }
+ }
+
+ newdata.flush();
+}
+
+void
+MySql::output(const ScalarData &data)
+{
+ newdata.stat = find(data.id);
+ newdata.x = 0;
+ newdata.y = 0;
+ newdata.data = data.value();
+
+ newdata.insert();
+}
+
+void
+MySql::output(const VectorData &data)
+{
+ 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)
+{
+ newdata.stat = find(data.id);
+ newdata.y = 0;
+ output(data.data);
+}
+
+void
+MySql::output(const VectorDistData &data)
+{
+ 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)
+{
+ 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)
+{
+ InsertFormula(mysql, find(data.id), run_id, data.str());
+}
+
+/*
+ * 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)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const VectorDistData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const Vector2dData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const FormulaData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+/* namespace Statistics */ }
diff --git a/base/stats/mysql.hh b/base/stats/mysql.hh
new file mode 100644
index 000000000..4ff474752
--- /dev/null
+++ b/base/stats/mysql.hh
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_MYSQL_HH__
+#define __BASE_STATS_MYSQL_HH__
+
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace MySQL { class Connection; }
+namespace Statistics {
+
+class DistDataData;
+class MySqlData;
+
+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 operator()(MySqlData *data);
+};
+
+class InsertData
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ public:
+ MySQL::Connection *mysql;
+
+ public:
+ uint64_t sample;
+ double data;
+ uint16_t stat;
+ uint16_t bin;
+ uint16_t run;
+ int16_t x;
+ int16_t y;
+
+ public:
+ InsertData();
+ ~InsertData();
+
+ void flush();
+ void insert();
+};
+
+class MySql : public Output
+{
+ protected:
+ std::list<FormulaData *> formulas;
+ MySqlData *mysql;
+ bool configured;
+ uint16_t run_id;
+
+ SetupStat stat;
+ InsertData newdata;
+
+ void insert(int sim_id, int db_id);
+ int find(int sim_id);
+
+ public:
+ MySql();
+ ~MySql();
+
+ void connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &project);
+
+ // 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 std::string &bin);
+ 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();
+ void 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 Statistics */ }
+
+#endif // __BASE_STATS_MYSQL_HH__
diff --git a/base/stats/output.hh b/base/stats/output.hh
new file mode 100644
index 000000000..9f1fbf415
--- /dev/null
+++ b/base/stats/output.hh
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_OUTPUT_HH__
+#define __BASE_STATS_OUTPUT_HH__
+
+#include <string>
+
+#include "base/stats/visit.hh"
+
+namespace Statistics {
+
+struct Output : public Visit
+{
+ inline void operator()() { output(); }
+ virtual void output() = 0;
+ virtual bool valid() const = 0;
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_OUTPUT_HH__
diff --git a/base/stats/statdb.cc b/base/stats/statdb.cc
new file mode 100644
index 000000000..f54272a50
--- /dev/null
+++ b/base/stats/statdb.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/statistics.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/statdb.hh"
+
+using namespace std;
+
+namespace Statistics {
+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
+regBin(MainBin *bin, const std::string &_name)
+{
+ bins().push_back(bin);
+ DPRINTF(Stats, "registering %s\n", _name);
+}
+
+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 Statistics */ }
diff --git a/base/stats/statdb.hh b/base/stats/statdb.hh
new file mode 100644
index 000000000..fb672e1dc
--- /dev/null
+++ b/base/stats/statdb.hh
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_STATDB_HH__
+#define __BASE_STATS_STATDB_HH__
+
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+class Python;
+
+namespace Statistics {
+
+class MainBin;
+class StatData;
+
+namespace Database {
+
+typedef std::map<void *, StatData *> stat_map_t;
+typedef std::list<StatData *> stat_list_t;
+typedef std::list<MainBin *> bin_list_t;
+
+// 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;
+ bin_list_t bins;
+
+};
+
+TheDatabase &db();
+inline stat_map_t &map() { return db().map; }
+inline stat_list_t &stats() { return db().stats; }
+inline bin_list_t &bins() { return db().bins; }
+
+StatData *find(void *stat);
+void regBin(MainBin *bin, const std::string &name);
+void regStat(void *stat, StatData *data);
+void regPrint(void *stat);
+
+inline std::string name() { return "Statistics Database"; }
+
+/* namespace Database */ }
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_STATDB_HH__
diff --git a/base/stats/text.cc b/base/stats/text.cc
new file mode 100644
index 000000000..0f43a1772
--- /dev/null
+++ b/base/stats/text.cc
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#include <iostream>
+#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 Statistics {
+
+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");
+ if (bins().empty()) {
+ 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);
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+ ccprintf(*stream, "---------------------------------\n");
+ }
+ }
+ 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 & ::Statistics::total) {
+ print.name = base + "total";
+ print.desc = desc;
+ print.value = total;
+ print(stream);
+ }
+ } else {
+ if (flags & ::Statistics::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 & ::Statistics::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 Statistics */ }
diff --git a/base/stats/text.hh b/base/stats/text.hh
new file mode 100644
index 000000000..89bddf0cb
--- /dev/null
+++ b/base/stats/text.hh
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_TEXT_HH__
+#define __BASE_STATS_TEXT_HH__
+
+#include <iosfwd>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace Statistics {
+
+class Text : public Output
+{
+ protected:
+ bool mystream;
+ std::ostream *stream;
+
+ protected:
+ bool noOutput(const StatData &data);
+ void binout();
+
+ 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 Statistics */ }
+
+#endif // __BASE_STATS_TEXT_HH__
diff --git a/base/stats/types.hh b/base/stats/types.hh
new file mode 100644
index 000000000..4451c4e6e
--- /dev/null
+++ b/base/stats/types.hh
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_TYPES_HH__
+#define __BASE_STATS_TYPES_HH__
+
+#include <vector>
+#include <inttypes.h>
+
+namespace Statistics {
+
+/** All counters are of 64-bit values. */
+typedef double Counter;
+/** vector of counters. */
+typedef std::vector<Counter> VCounter;
+
+/** All results are doubles. */
+typedef double Result;
+/** vector of results. */
+typedef std::vector<Result> VResult;
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_TYPES_HH__
diff --git a/base/stats/visit.cc b/base/stats/visit.cc
new file mode 100644
index 000000000..fec11b262
--- /dev/null
+++ b/base/stats/visit.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#include "base/stats/visit.hh"
+
+namespace Statistics {
+namespace Detail {
+
+Visit::Visit()
+{}
+
+Visit::~Visit()
+{}
+
+/* namespace Detail */ }
+/* namespace Statistics */ }
diff --git a/base/stats/visit.hh b/base/stats/visit.hh
new file mode 100644
index 000000000..a03842c52
--- /dev/null
+++ b/base/stats/visit.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __BASE_STATS_VISIT_HH__
+#define __BASE_STATS_VISIT_HH__
+
+#include <string>
+
+#include "base/time.hh"
+#include "sim/host.hh"
+
+namespace Statistics {
+
+class StatData;
+class ScalarData;
+class VectorData;
+class DistDataData;
+class DistData;
+class VectorDistData;
+class Vector2dData;
+class FormulaData;
+
+struct Visit
+{
+ Visit();
+ virtual ~Visit();
+
+ virtual void visit(const ScalarData &data) = 0;
+ virtual void visit(const VectorData &data) = 0;
+ virtual void visit(const DistData &data) = 0;
+ virtual void visit(const VectorDistData &data) = 0;
+ virtual void visit(const Vector2dData &data) = 0;
+ virtual void visit(const FormulaData &data) = 0;
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_VISIT_HH__
diff --git a/base/time.cc b/base/time.cc
index d2e8f60a5..9a484a883 100644
--- a/base/time.cc
+++ b/base/time.cc
@@ -47,10 +47,11 @@ convert(const timeval &tv)
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
}
-Time::Time()
+Time::Time(bool set_now)
{
time = new _timeval;
- ::gettimeofday(&time->tv, NULL);
+ if (set_now)
+ set();
}
Time::Time(const timeval &val)
@@ -77,15 +78,15 @@ Time::get() const
}
void
-Time::set(const timeval &tv)
+Time::set()
{
- memcpy(&time->tv, &tv, sizeof(timeval));
+ ::gettimeofday(&time->tv, NULL);
}
void
-Time::reset()
+Time::set(const timeval &tv)
{
- ::gettimeofday(&time->tv, NULL);
+ memcpy(&time->tv, &tv, sizeof(timeval));
}
double
@@ -127,4 +128,4 @@ operator-(const Time &l, const Time &r)
return tv;
}
-const Time Time::start;
+const Time Time::start(true);
diff --git a/base/time.hh b/base/time.hh
index 64da52e1d..1f8c7e747 100644
--- a/base/time.hh
+++ b/base/time.hh
@@ -42,15 +42,15 @@ class Time
mutable _timeval *time;
public:
- Time();
+ explicit Time(bool set_now = false);
Time(const timeval &val);
Time(const Time &val);
~Time();
+ void set();
const timeval &get() const;
void set(const timeval &val);
- void reset();
double operator()() const;
std::string date(std::string format = "") const;
diff --git a/base/trace.hh b/base/trace.hh
index e49d7aa61..948bff548 100644
--- a/base/trace.hh
+++ b/base/trace.hh
@@ -43,7 +43,7 @@
#endif
#endif
-#include "base/trace_flags.hh"
+#include "base/traceflags.hh"
namespace Trace {
diff --git a/base/traceflags.py b/base/traceflags.py
new file mode 100644
index 000000000..b7b7fa777
--- /dev/null
+++ b/base/traceflags.py
@@ -0,0 +1,336 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2004 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.
+
+#
+# This file generates the header and source files for the flags
+# that control the tracing facility.
+#
+hhfilename="traceflags.hh"
+ccfilename="traceflags.cc"
+
+#
+# The list of trace flags that can be used to condition DPRINTFs etc.
+# To define a new flag, simply add it to this list.
+#
+baseFlags = [
+ 'TCPIP',
+ 'Bus',
+ 'ScsiDisk',
+ 'ScsiCtrl',
+ 'ScsiNone',
+ 'DMA',
+ 'DMAReadVerbose',
+ 'DMAWriteVerbose',
+ 'TLB',
+ 'SimpleDisk',
+ 'SimpleDiskData',
+ 'Clock',
+ 'Regs',
+ 'MC146818',
+ 'IPI',
+ 'Timer',
+ 'Mbox',
+ 'PCIA',
+ 'PCIDEV',
+ 'ISP',
+ 'BADADDR',
+ 'Console',
+ 'ConsolePoll',
+ 'ConsoleVerbose',
+ 'TlaserUart',
+ 'AlphaConsole',
+ 'Flow',
+ 'Interrupt',
+ 'Cycle',
+ 'Loader',
+ 'MMU',
+ 'Ethernet',
+ 'EthernetPIO',
+ 'EthernetDMA',
+ 'EthernetData',
+ 'GDBMisc',
+ 'GDBAcc',
+ 'GDBRead',
+ 'GDBWrite',
+ 'GDBSend',
+ 'GDBRecv',
+ 'GDBExtra',
+ 'VtoPhys',
+ 'Printf',
+ 'DebugPrintf',
+ 'Serialize',
+ 'Event',
+ 'PCEvent',
+ 'SyscallWarnings',
+ 'SyscallVerbose',
+ 'DiskImage',
+ 'DiskImageRead',
+ 'DiskImageWrite',
+ 'InstExec',
+ 'BPredRAS',
+ 'Cache',
+ 'IIC',
+ 'IICMore',
+ 'MSHR',
+ 'Chains',
+ 'Dispatch',
+ 'Stats',
+ 'Context',
+ 'Config',
+ 'Sampler',
+ 'WriteBarrier'
+ ]
+
+#
+# "Compound" flags correspond to a set of base flags. These exist
+# solely for convenience in setting them via the command line: if a
+# compound flag is specified, all of the corresponding base flags are
+# set. Compound flags cannot be used directly in DPRINTFs etc.
+# To define a new compound flag, add a new entry to this hash
+# following the existing examples.
+#
+compoundFlagMap = {
+ 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
+ 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
+ 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
+ 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' ]
+}
+
+#############################################################
+#
+# Everything below this point generates the appropriate C++
+# declarations and definitions for the trace flags. If you are simply
+# adding or modifying flag definitions, you should not have to change
+# anything below.
+#
+
+import sys
+
+# extract just the compound flag names into a list
+compoundFlags = []
+compoundFlags.extend(compoundFlagMap.keys())
+compoundFlags.sort()
+
+#
+# First generate the header file. This defines the Flag enum
+# and some extern declarations for the .cc file.
+#
+try:
+ hhfile = file(hhfilename, 'w')
+except IOError, e:
+ sys.exit("can't open %s: %s" % (hhfilename, e))
+
+# file header boilerplate
+print >>hhfile, '''/* $Id $ */
+
+/*
+ * Copyright (c) 2004
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator, developed by Nathan Binkert,
+ * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
+ * from Ron Dreslinski, Dave Greene, and Lisa Hsu.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ */
+
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.py
+ */
+
+#ifndef __BASE_TRACE_FLAGS_HH__
+#define __BASE_TRACE_FLAGS_HH__
+
+namespace Trace {
+
+enum Flags {
+''',
+
+# Generate the enum. Base flags come first, then compound flags.
+idx = 0
+for flag in baseFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numBaseFlags = idx
+print >>hhfile, ' NumFlags = %d,' % idx
+
+# put a comment in here to separate base from compound flags
+print >>hhfile, '''
+ // The remaining enum values are *not* valid indices for Trace::flags.
+ // They are "compound" flags, which correspond to sets of base
+ // flags, and are used only by TraceParamContext::setFlags().
+''',
+
+for flag in compoundFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numCompoundFlags = idx - numBaseFlags
+print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
+
+# trailer boilerplate
+print >>hhfile, '''\
+}; // enum Flags
+
+// Array of strings for SimpleEnumParam
+extern const char *flagStrings[];
+extern const int numFlagStrings;
+
+// Array of arraay pointers: for each compound flag, gives the list of
+// base flags to set. Inidividual flag arrays are terminated by -1.
+extern const Flags *compoundFlags[];
+
+/* namespace Trace */ }
+
+#endif // __BASE_TRACE_FLAGS_HH__
+''',
+
+hhfile.close()
+
+#
+#
+# Print out .cc file with array definitions.
+#
+#
+try:
+ ccfile = file(ccfilename, 'w')
+except OSError, e:
+ sys.exit("can't open %s: %s" % (ccfilename, e))
+
+# file header
+print >>ccfile, '''\
+/* $Id $ */
+
+/*
+ * Copyright (c) 2004
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator, developed by Nathan Binkert,
+ * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
+ * from Ron Dreslinski, Dave Greene, and Lisa Hsu.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ */
+
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.pl.
+ */
+
+#include "base/traceflags.hh"
+
+using namespace Trace;
+
+const char *Trace::flagStrings[] =
+{
+''',
+
+# The string array is used by SimpleEnumParam to map the strings
+# provided by the user to enum values.
+for flag in baseFlags:
+ print >>ccfile, ' "%s",' % flag
+
+for flag in compoundFlags:
+ print >>ccfile, ' "%s",' % flag
+
+print >>ccfile, '};\n'
+
+numFlagStrings = len(baseFlags) + len(compoundFlags);
+
+print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
+print >>ccfile
+
+#
+# Now define the individual compound flag arrays. There is an array
+# for each compound flag listing the component base flags.
+#
+
+for flag in compoundFlags:
+ flags = compoundFlagMap[flag]
+ flags.append('(Flags)-1')
+ print >>ccfile, 'static const Flags %sMap[] =' % flag
+ print >>ccfile, '{ %s };' % (', '.join(flags))
+ print >>ccfile
+
+#
+# Finally the compoundFlags[] array maps the compound flags
+# to their individual arrays/
+#
+print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
+print >>ccfile, '{'
+
+for flag in compoundFlags:
+ print >>ccfile, ' %sMap,' % flag
+
+# file trailer
+print >>ccfile, '};'
+
+ccfile.close()
+
diff --git a/base/userinfo.cc b/base/userinfo.cc
new file mode 100644
index 000000000..a729dfdf4
--- /dev/null
+++ b/base/userinfo.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004 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.
+ */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include <string>
+
+std::string
+username()
+{
+ struct passwd *pwd = getpwuid(getuid());
+
+ return pwd->pw_name;
+}
diff --git a/base/userinfo.hh b/base/userinfo.hh
new file mode 100644
index 000000000..14e704ec4
--- /dev/null
+++ b/base/userinfo.hh
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2004 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.
+ */
+
+#ifndef __BASE_USERINFO_HH__
+#define __BASE_USERINFO_HH__
+
+#include <string>
+
+std::string username();
+
+#endif // __BASE_USERINFO_HH__
diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc
index 73fb3e7fa..c6cff814d 100644
--- a/cpu/base_cpu.cc
+++ b/cpu/base_cpu.cc
@@ -237,10 +237,4 @@ BaseCPU::clear_interrupts()
#endif // FULL_SYSTEM
-//
-// This declaration is not needed now that SamplingCPU provides a
-// BaseCPUBuilder object.
-//
-#if 0
DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
-#endif
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index eedd8b8a8..a89cf4bb5 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -42,7 +42,7 @@ using namespace std;
// constructor
#ifdef FULL_SYSTEM
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaItb *_itb, AlphaDtb *_dtb,
+ AlphaITB *_itb, AlphaDTB *_dtb,
FunctionalMemory *_mem)
: _status(ExecContext::Unallocated),
kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
@@ -60,6 +60,7 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
process(_process), mem(process->getMemory()), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
+ memset(&regs, 0, sizeof(RegFile));
}
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
@@ -67,6 +68,7 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
: cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
+ memset(&regs, 0, sizeof(RegFile));
}
#endif
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index a72516ac7..7be83539a 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -124,8 +124,8 @@ class ExecContext
#ifdef FULL_SYSTEM
FunctionalMemory *mem;
- AlphaItb *itb;
- AlphaDtb *dtb;
+ AlphaITB *itb;
+ AlphaDTB *dtb;
System *system;
// the following two fields are redundant, since we can always
@@ -174,7 +174,7 @@ class ExecContext
// constructor: initialize context from given process structure
#ifdef FULL_SYSTEM
ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem);
+ AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
#else
ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
@@ -387,7 +387,10 @@ class ExecContext
#ifdef FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault);
Fault setIpr(int idx, uint64_t val);
+ int readIntrFlag() { return regs.intrflag; }
+ void setIntrFlag(int val) { regs.intrflag = val; }
Fault hwrei();
+ bool inPalMode() { return PC_PAL(regs.pc); }
void ev5_trap(Fault fault);
bool simPalCheck(int palFunc);
#endif
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index 051d9623a..5d608976d 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -40,7 +40,7 @@
#include "mem/functional_mem/main_memory.hh"
#include "sim/builder.hh"
#include "sim/sim_events.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
using namespace std;
@@ -109,7 +109,6 @@ MemTest::MemTest(const string &name,
// set up counters
noResponseCycles = 0;
numReads = 0;
- numWrites = 0;
tickEvent.schedule(0);
}
@@ -142,21 +141,23 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
}
numReads++;
+ numReadsStat++;
- if (numReads.value() == nextProgressMessage) {
- cerr << name() << ": completed " << numReads.value()
- << " read accesses @ " << curTick << endl;
+ if (numReads == nextProgressMessage) {
+ ccprintf(cerr, "%s: completed %d read accesses @%d\n",
+ name(), numReads, curTick);
nextProgressMessage += progressInterval;
}
- comLoadEventQueue[0]->serviceEvents(numReads.value());
+ comLoadEventQueue[0]->serviceEvents(numReads);
break;
case Write:
- numWrites++;
+ numWritesStat++;
break;
case Copy:
+ numCopiesStat++;
break;
default:
@@ -187,17 +188,18 @@ MemTest::regStats()
{
using namespace Statistics;
- numReads
+
+ numReadsStat
.name(name() + ".num_reads")
.desc("number of read accesses completed")
;
- numWrites
+ numWritesStat
.name(name() + ".num_writes")
.desc("number of write accesses completed")
;
- numCopies
+ numCopiesStat
.name(name() + ".num_copies")
.desc("number of copy accesses completed")
;
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index da6e180a0..f2409d54c 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -36,7 +36,7 @@
#include "cpu/exec_context.hh"
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
class MemTest : public BaseCPU
{
@@ -110,9 +110,10 @@ class MemTest : public BaseCPU
Tick noResponseCycles;
- Statistics::Scalar<> numReads;
- Statistics::Scalar<> numWrites;
- Statistics::Scalar<> numCopies;
+ uint64_t numReads;
+ Statistics::Scalar<> numReadsStat;
+ Statistics::Scalar<> numWritesStat;
+ Statistics::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process()
void completeRequest(MemReqPtr &req, uint8_t *data);
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index c2796efd0..065140883 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -56,7 +56,7 @@
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#ifdef FULL_SYSTEM
#include "base/remote_gdb.hh"
@@ -116,7 +116,7 @@ SimpleCPU::SimpleCPU(const string &_name,
Counter max_insts_all_threads,
Counter max_loads_any_thread,
Counter max_loads_all_threads,
- AlphaItb *itb, AlphaDtb *dtb,
+ AlphaITB *itb, AlphaDTB *dtb,
FunctionalMemory *mem,
MemInterface *icache_interface,
MemInterface *dcache_interface,
@@ -714,7 +714,7 @@ SimpleCPU::tick()
xc->func_exe_inst++;
- fault = si->execute(this, xc, traceData);
+ fault = si->execute(this, traceData);
#ifdef FULL_SYSTEM
SWContext *ctx = xc->swCtx;
@@ -778,8 +778,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
Param<Counter> max_loads_all_threads;
#ifdef FULL_SYSTEM
- SimObjectParam<AlphaItb *> itb;
- SimObjectParam<AlphaDtb *> dtb;
+ SimObjectParam<AlphaITB *> itb;
+ SimObjectParam<AlphaDTB *> dtb;
SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<System *> system;
Param<int> mult;
@@ -852,11 +852,7 @@ CREATE_SIM_OBJECT(SimpleCPU)
defer_registration);
#endif // FULL_SYSTEM
-#if 0
- if (!defer_registration) {
- cpu->registerExecContexts();
- }
-#endif
+
return cpu;
}
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 9edd66ab4..4977e6992 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -40,8 +40,8 @@
#ifdef FULL_SYSTEM
class Processor;
class Kernel;
-class AlphaItb;
-class AlphaDtb;
+class AlphaITB;
+class AlphaDTB;
class PhysicalMemory;
class RemoteGDB;
@@ -131,7 +131,7 @@ class SimpleCPU : public BaseCPU
System *_system,
Counter max_insts_any_thread, Counter max_insts_all_threads,
Counter max_loads_any_thread, Counter max_loads_all_threads,
- AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem,
+ AlphaITB *itb, AlphaDTB *dtb, FunctionalMemory *mem,
MemInterface *icache_interface, MemInterface *dcache_interface,
bool _def_reg, Tick freq);
@@ -250,6 +250,56 @@ class SimpleCPU : public BaseCPU
Fault copySrcTranslate(Addr src);
Fault copy(Addr dest);
+
+ uint64_t readIntReg(int reg_idx) { return xc->readIntReg(reg_idx); }
+
+ float readFloatRegSingle(int reg_idx)
+ { return xc->readFloatRegSingle(reg_idx); }
+
+ double readFloatRegDouble(int reg_idx)
+ { return xc->readFloatRegDouble(reg_idx); }
+
+ uint64_t readFloatRegInt(int reg_idx)
+ { return xc->readFloatRegInt(reg_idx); }
+
+ void setIntReg(int reg_idx, uint64_t val)
+ { return xc->setIntReg(reg_idx, val); }
+
+ void setFloatRegSingle(int reg_idx, float val)
+ { return xc->setFloatRegSingle(reg_idx, val); }
+
+ void setFloatRegDouble(int reg_idx, double val)
+ { return xc->setFloatRegDouble(reg_idx, val); }
+
+ void setFloatRegInt(int reg_idx, uint64_t val)
+ { return xc->setFloatRegInt(reg_idx, val); }
+
+ uint64_t readPC() { return xc->readPC(); }
+ void setNextPC(uint64_t val) { return xc->setNextPC(val); }
+
+ uint64_t readUniq() { return xc->readUniq(); }
+ void setUniq(uint64_t val) { return xc->setUniq(val); }
+
+ uint64_t readFpcr() { return xc->readFpcr(); }
+ void setFpcr(uint64_t val) { return xc->setFpcr(val); }
+
+#ifdef FULL_SYSTEM
+ uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
+ Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
+ Fault hwrei() { return xc->hwrei(); }
+ int readIntrFlag() { return xc->readIntrFlag(); }
+ void setIntrFlag(int val) { xc->setIntrFlag(val); }
+ bool inPalMode() { return xc->inPalMode(); }
+ void ev5_trap(Fault fault) { return xc->ev5_trap(fault); }
+ bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
+#else
+ void syscall() { xc->syscall(); }
+#endif
+
+ bool misspeculating() { return xc->misspeculating(); }
+ ExecContext *xcBase() { return xc; }
};
+typedef SimpleCPU SimpleCPUExecContext;
+
#endif // __SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index cdf9aefa0..57208f8e6 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -41,10 +41,10 @@
// forward declarations
class ExecContext;
-class SpecExecContext;
-class SimpleCPU;
-class FullCPU;
class DynInst;
+typedef DynInst FullCPUExecContext;
+class SimpleCPU;
+typedef SimpleCPU SimpleCPUExecContext;
class SymbolTable;
namespace Trace {
@@ -307,13 +307,13 @@ class StaticInst : public StaticInstBase
/**
* Execute this instruction under SimpleCPU model.
*/
- virtual Fault execute(SimpleCPU *cpu, ExecContext *xc,
+ virtual Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) = 0;
/**
* Execute this instruction under detailed FullCPU model.
*/
- virtual Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+ virtual Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) = 0;
/**
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 960d21d73..db1b3660f 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -313,8 +313,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
SimObjectParam<EtherInt *> peer;
SimObjectParam<EtherDump *> packet_dump;
- Param<uint16_t> port;
- Param<uint16_t> bufsz;
+ Param<unsigned> port;
+ Param<unsigned> bufsz;
END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 4f53ba48d..910b889d8 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -29,6 +29,7 @@
#include "dev/io_device.hh"
#include "mem/bus/base_interface.hh"
#include "mem/bus/dma_interface.hh"
+#include "sim/builder.hh"
PioDevice::PioDevice(const std::string &name)
: FunctionalMemory(name), pioInterface(NULL)
@@ -40,6 +41,8 @@ PioDevice::~PioDevice()
delete pioInterface;
}
+DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
+
DmaDevice::DmaDevice(const std::string &name)
: PioDevice(name), dmaInterface(NULL)
{}
@@ -50,3 +53,5 @@ DmaDevice::~DmaDevice()
delete dmaInterface;
}
+DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice)
+
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index a57c01841..17a5e406a 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -159,6 +159,6 @@ FnEvent::process(ExecContext *xc)
myBin->activate();
xc->system->fnCalls++;
DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
- xc->system->fnCalls.val());
+ xc->system->fnCalls.value());
xc->system->dumpState(xc);
}
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index f8dda6f84..905ff5df6 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -318,7 +318,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
Param<bool> bin;
SimObjectParam<MemoryController *> mem_ctl;
SimObjectParam<PhysicalMemory *> physmem;
- Param<uint64_t> init_param;
+ Param<unsigned int> init_param;
Param<string> kernel_code;
Param<string> console_code;
diff --git a/sim/builder.cc b/sim/builder.cc
index e2345556e..110c42f25 100644
--- a/sim/builder.cc
+++ b/sim/builder.cc
@@ -32,6 +32,7 @@
#include "base/misc.hh"
#include "sim/builder.hh"
#include "sim/configfile.hh"
+#include "sim/config_node.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
#include "sim/universe.hh"
@@ -153,7 +154,7 @@ SimObjectClass::createObject(IniFile &configDB,
// (specified by 'type=' parameter)
string simObjClassName;
- if (!configDB.findDefault(configClassName, "type", simObjClassName)) {
+ if (!configNode->find("type", simObjClassName)) {
cerr << "Configuration class '" << configClassName << "' not found."
<< endl;
abort();
diff --git a/sim/main.cc b/sim/main.cc
index 48d64d4cd..8861f3ef0 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -53,7 +53,8 @@
#include "sim/sim_exit.hh"
#include "sim/sim_init.hh"
#include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
#include "sim/universe.hh"
using namespace std;
@@ -235,7 +236,7 @@ main(int argc, char **argv)
sayHello(cerr);
// Initialize statistics database
- initBaseStats();
+ Statistics::InitSimStats();
vector<char *> cppArgs;
diff --git a/sim/param.cc b/sim/param.cc
index 7affe4786..bb372f631 100644
--- a/sim/param.cc
+++ b/sim/param.cc
@@ -147,14 +147,14 @@ template <>
bool
parseParam(const string &s, bool &value)
{
- const string &lower = to_lower(s);
+ const string &ls = to_lower(s);
- if (lower == "true" || lower == "t" || lower == "yes" || lower == "y") {
+ if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
value = true;
return true;
}
- if (lower == "false" || lower == "f" || lower == "no" || lower == "n") {
+ if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
value = false;
return true;
}
diff --git a/sim/process.cc b/sim/process.cc
index c5eee4527..c6b497343 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -43,7 +43,7 @@
#include "sim/builder.hh"
#include "sim/fake_syscall.hh"
#include "sim/process.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#ifdef TARGET_ALPHA
#include "arch/alpha/alpha_tru64_process.hh"
@@ -75,6 +75,7 @@ Process::Process(const string &name,
// allocate initial register file
init_regs = new RegFile;
+ memset(init_regs, 0, sizeof(RegFile));
// initialize first 3 fds (stdin, stdout, stderr)
fd_map[STDIN_FILENO] = stdin_fd;
@@ -220,7 +221,7 @@ Process::sim_fd(int tgt_fd)
// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call,
// which is where these get declared for concrete types).
//
-DEFINE_SIM_OBJECT_CLASS_NAME("Process object", Process)
+DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
////////////////////////////////////////////////////////////////////////
diff --git a/sim/process.hh b/sim/process.hh
index 5df5736ff..b23302b8f 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -40,7 +40,7 @@
#include "targetarch/isa_traits.hh"
#include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#include "base/statistics.hh"
class ExecContext;
diff --git a/sim/sim_events.cc b/sim/sim_events.cc
index f7b07359c..3530adedc 100644
--- a/sim/sim_events.cc
+++ b/sim/sim_events.cc
@@ -35,7 +35,7 @@
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_init.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
using namespace std;
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
index 2ec588afa..5602a89a2 100644
--- a/sim/sim_object.cc
+++ b/sim/sim_object.cc
@@ -35,7 +35,7 @@
#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#include "sim/param.hh"
using namespace std;
@@ -85,14 +85,6 @@ SimObject::resetStats()
}
//
-// no default extra output
-//
-void
-SimObject::printExtraOutput(ostream &os)
-{
-}
-
-//
// static function:
// call regStats() on all SimObjects and then regFormulas() on all
// SimObjects.
@@ -163,21 +155,6 @@ SimObject::resetAllStats()
}
//
-// static function: call printExtraOutput() on all SimObjects.
-//
-void
-SimObject::printAllExtraOutput(ostream &os)
-{
- SimObjectList::iterator i = simObjectList.begin();
- SimObjectList::iterator end = simObjectList.end();
-
- for (; i != end; ++i) {
- SimObject *obj = *i;
- obj->printExtraOutput(os);
- }
-}
-
-//
// static function: serialize all SimObjects.
//
void
diff --git a/sim/sim_object.hh b/sim/sim_object.hh
index aaaafc04b..b1dd19475 100644
--- a/sim/sim_object.hh
+++ b/sim/sim_object.hh
@@ -74,19 +74,12 @@ class SimObject : public Serializable
virtual void regFormulas();
virtual void resetStats();
- // print extra results for this object not covered by registered
- // statistics (called at end of simulation)
- virtual void printExtraOutput(std::ostream&);
-
// static: call reg_stats on all SimObjects
static void regAllStats();
// static: call resetStats on all SimObjects
static void resetAllStats();
- // static: call printExtraOutput on all SimObjects
- static void printAllExtraOutput(std::ostream&);
-
// static: call nameOut() & serialize() on all SimObjects
static void serializeAll(std::ostream &);
};
diff --git a/sim/stat_control.cc b/sim/stat_control.cc
new file mode 100644
index 000000000..d6d7e2c91
--- /dev/null
+++ b/sim/stat_control.cc
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+// This file will contain default statistics for the simulator that
+// don't really belong to a specific simulator object
+
+#include <fstream>
+#include <iostream>
+#include <list>
+
+#include "base/callback.hh"
+#include "base/hostinfo.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "base/stats/output.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_object.hh"
+#include "sim/stat_control.hh"
+#include "sim/universe.hh"
+
+using namespace std;
+
+Statistics::Formula hostInstRate;
+Statistics::Formula hostMemory;
+Statistics::Formula hostSeconds;
+Statistics::Formula hostTickRate;
+
+Statistics::Formula simInsts;
+Statistics::Formula simSeconds;
+Statistics::Formula simTicks;
+
+namespace Statistics {
+
+Time statTime(true);
+Tick startTick;
+
+class SimTicksReset : public Callback
+{
+ public:
+ void process()
+ {
+ statTime.set();
+ startTick = curTick;
+ }
+};
+
+double
+statElapsedTime()
+{
+ Time now(true);
+ Time elapsed = now - statTime;
+ return elapsed();
+}
+
+SimTicksReset simTicksReset;
+
+void
+InitSimStats()
+{
+ simInsts
+ .name("sim_insts")
+ .desc("Number of instructions simulated")
+ .precision(0)
+ .prereq(simInsts)
+ ;
+
+ simSeconds
+ .name("sim_seconds")
+ .desc("Number of seconds simulated")
+ ;
+
+ simTicks
+ .name("sim_ticks")
+ .desc("Number of ticks simulated")
+ ;
+
+ hostInstRate
+ .name("host_inst_rate")
+ .desc("Simulator instruction rate (inst/s)")
+ .precision(0)
+ .prereq(simInsts)
+ ;
+
+ hostMemory
+ .name("host_mem_usage")
+ .desc("Number of bytes of host memory used")
+ .prereq(hostMemory)
+ ;
+
+ hostSeconds
+ .name("host_seconds")
+ .desc("Real time elapsed on the host")
+ .precision(2)
+ ;
+
+ hostTickRate
+ .name("host_tick_rate")
+ .desc("Simulator tick rate (ticks/s)")
+ .precision(0)
+ ;
+
+ simInsts = constant(0);
+ simTicks = scalar(curTick) - scalar(startTick);
+ simSeconds = simTicks / scalar(ticksPerSecond);
+ hostMemory = functor(memUsage);
+ hostSeconds = functor(statElapsedTime);
+ hostInstRate = simInsts / hostSeconds;
+ hostTickRate = simTicks / hostSeconds;
+
+ registerResetCallback(&simTicksReset);
+}
+
+class StatEvent : public Event
+{
+ protected:
+ int flags;
+ Tick repeat;
+
+ public:
+ StatEvent(int _flags, Tick _when, Tick _repeat);
+ virtual void process();
+ virtual const char *description();
+};
+
+StatEvent::StatEvent(int _flags, Tick _when, Tick _repeat)
+ : Event(&mainEventQueue, Stat_Event_Pri),
+ flags(_flags), repeat(_repeat)
+{
+ setFlags(AutoDelete);
+ schedule(_when);
+}
+
+const char *
+StatEvent::description()
+{
+ return "Statistics dump and/or reset";
+}
+
+void
+StatEvent::process()
+{
+ if (flags & Statistics::Dump)
+ DumpNow();
+
+ if (flags & Statistics::Reset)
+ reset();
+
+ if (repeat)
+ schedule(curTick + repeat);
+}
+
+list<Output *> OutputList;
+
+void
+DumpNow()
+{
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->output();
+ }
+}
+
+void
+SetupEvent(int flags, Tick when, Tick repeat)
+{
+ new StatEvent(flags, when, repeat);
+}
+
+/* namespace Statistics */ }
+
+extern "C" void
+debugDumpStats()
+{
+ Statistics::DumpNow();
+}
+
diff --git a/sim/stat_control.hh b/sim/stat_control.hh
new file mode 100644
index 000000000..9a5e269e1
--- /dev/null
+++ b/sim/stat_control.hh
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#ifndef __SIM_STAT_CONTROL_HH__
+#define __SIM_STAT_CONTROL_HH__
+
+#include <fstream>
+#include <list>
+
+namespace Statistics {
+
+enum {
+ Reset = 0x1,
+ Dump = 0x2
+};
+
+class Output;
+extern std::list<Output *> OutputList;
+
+void DumpNow();
+void SetupEvent(int flags, Tick when, Tick repeat = 0);
+
+void InitSimStats();
+
+/* namespace Statistics */ }
+
+#endif // __SIM_STAT_CONTROL_HH__
diff --git a/sim/stats.hh b/sim/stats.hh
new file mode 100644
index 000000000..b736850e7
--- /dev/null
+++ b/sim/stats.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#ifndef __SIM_STATS_HH__
+#define __SIM_STATS_HH__
+
+#include "base/statistics.hh"
+
+extern Statistics::Formula simTicks;
+extern Statistics::Formula simSeconds;
+extern Statistics::Formula simInsts;
+extern Statistics::Formula hostSeconds;
+extern Statistics::Formula hostTickRate;
+extern Statistics::Formula hostInstRate;
+
+#endif // __SIM_SIM_STATS_HH__
diff --git a/sim/system.hh b/sim/system.hh
index 7b011aa8f..0fcdd77cc 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -54,7 +54,7 @@ class System : public SimObject
std::map<const Addr, SWContext *> swCtxMap;
public:
- Statistics::Scalar<Counter> fnCalls;
+ Statistics::Scalar<> fnCalls;
Statistics::MainBin *Kernel;
Statistics::MainBin *User;
diff --git a/test/Makefile b/test/Makefile
index d62dba64a..bf4200ba3 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -5,81 +5,61 @@ CXX?= g++
CURDIR?= $(shell /bin/pwd)
SRCDIR?= ..
-TARGET?= alpha
-
-TEST_SRCDIR?= $(SRCDIR)/test
-ARCH_SRCDIR?= $(SRCDIR)/arch/$(TARGET)
-BASE_SRCDIR?= $(SRCDIR)/base
-SIM_SRCDIR?= $(SRCDIR)/sim
-CACHE_SRCDIR?= $(SRCDIR)/sim/cache
-OLD_SRCDIR= $(SRCDIR)/old
-
-vpath % $(TEST_SRCDIR)
-vpath % $(BASE_SRCDIR)
-vpath % $(SIM_SRCDIR)
-vpath % $(CACHE_SRCDIR)
-vpath % $(OLD_SRCDIR)
CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0
+MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
+
+VPATH=$(SRCDIR)
default:
@echo "You must specify a target"
-targetarch:
- ln -s ../arch/$(TARGET) targetarch
-
-bitvectest: bitvectest.o
- $(CXX) $(LFLAGS) -o $@ $^
+bitvectest: test/bitvectest.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-circletest: circletest.o circlebuf.o
- $(CXX) $(LFLAGS) -o $@ $^
+circletest: test/circletest.cc base/circlebuf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-cprintftest: cprintftest.o cprintf.o
- $(CXX) $(LFLAGS) -o $@ $^
+cprintftest: test/cprintftest.cc base/cprintf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-initest: initest.o str.o inifile.o cprintf.o
- $(CXX) $(LFLAGS) -o $@ $^
+initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-lrutest: lru_test.o
- $(CXX) $(LFLAGS) -o $@ $^
+lrutest: test/lru_test.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-nmtest: nmtest.o object_file.o symtab.o misc.o str.o
- $(CXX) $(LFLAGS) -o $@ $^
+nmtest: test/nmtest.cc base/object_file.cc base/symtab.cc base/misc.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-offtest: offtest.o
- $(CXX) $(LFLAGS) -o $@ $^
+offtest: test/offtest.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-rangetest: rangetest.o range.o str.o
- $(CXX) $(LFLAGS) -o $@ $^
+rangetest: test/rangetest.cc base/range.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-stattest: cprintf.o hostinfo.o misc.o python.o statistics.o stattest.o \
- str.o time.o
- $(CXX) $(LFLAGS) -o $@ $^
+STATTEST+= base/cprintf.cc base/hostinfo.cc base/misc.cc base/mysql.cc
+STATTEST+= base/python.cc base/str.cc base/time.cc
+STATTEST+= base/statistics.cc base/stats/mysql.cc base/stats/python.cc
+STATTEST+= base/stats/statdb.cc base/stats/text.cc base/stats/visit.cc
+STATTEST+= test/stattest.cc
+stattest: $(STATTEST)
+ $(CXX) $(CCFLAGS) $(MYSQL) -o $@ $^
-strnumtest: strnumtest.o str.o
- $(CXX) $(LFLAGS) -o $@ $^
+strnumtest: test/strnumtest.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-symtest: misc.o symtest.o symtab.o str.o
- $(CXX) $(LFLAGS) -o $@ $^
+symtest: test/symtest.cc base/misc.cc base/symtab.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-tokentest: tokentest.o str.o
- $(CXX) $(LFLAGS) -o $@ $^
+tokentest: test/tokentest.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
-tracetest: tracetest.o trace.o trace_flags.o cprintf.o str.o misc.o
- $(CXX) $(LFLAGS) -o $@ $^
+TRACE+=test/tracetest.cc base/trace.cc base/trace_flags.cc base/cprintf.cc
+TRACE+=base/str.cc base/misc.cc
+tracetest: $(TRACE)
+ $(CXX) $(CCFLAGS) -o $@ $^
clean:
- @rm -f *.o *.d *test *~ .#* *.core core
+ @rm -f *test *~ .#* *.core core
.PHONY: clean
-
-# C++ Compilation
-%.o: %.cc
- @echo '$(CXX) $(CCFLAGS) -c $(notdir $<) -o $@'
- @$(CXX) $(CCFLAGS) -c $< -o $@
-
-# C Compilation
-%.o: %.c
- @echo '$(CC) $(CCFLAGS) -c $(notdir $<) -o $@'
- @$(CC) $(CCFLAGS) -c $< -o $@
-
--include *.d
diff --git a/test/paramtest.cc b/test/paramtest.cc
index d63a3aad4..2efe23c83 100644
--- a/test/paramtest.cc
+++ b/test/paramtest.cc
@@ -57,8 +57,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(ParamTest)
VectorParam<string> vecstring;
Param<bool> boolparam;
VectorParam<bool> vecbool;
- SimObjectParam<mem_hierarchy_obj *> memobj;
- SimObjectVectorParam<mem_hierarchy_obj *> vecmemobj;
+ SimObjectParam<BaseMemory *> memobj;
+ SimObjectVectorParam<BaseMemory *> vecmemobj;
SimpleEnumParam<Enum1Type> enum1;
MappedEnumParam<Enum2Type> enum2;
SimpleEnumVectorParam<Enum1Type> vecenum1;
@@ -76,7 +76,7 @@ const EnumParamMap enum2_map[] =
{ "ten", 10 },
{ "twenty", 20 },
{ "thirty", 30 },
- { "fourty", 40 }
+ { "forty", 40 }
};
BEGIN_INIT_SIM_OBJECT_PARAMS(ParamTest)
diff --git a/test/stattest.cc b/test/stattest.cc
index 8dd8eeb8e..7bf355c0e 100644
--- a/test/stattest.cc
+++ b/test/stattest.cc
@@ -35,6 +35,9 @@
#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
+#include "base/stats/text.hh"
+#include "base/stats/python.hh"
+#include "base/stats/mysql.hh"
#include "sim/host.hh"
using namespace std;
@@ -46,14 +49,14 @@ Tick ticksPerSecond = ULL(2000000000);
Scalar<> s1;
Scalar<> s2;
Average<> s3;
-Scalar<Counter, MainBin> s4;
-Vector<Counter, MainBin> s5;
-Distribution<Counter, MainBin> s6;
-Vector<Counter, MainBin> s7;
+Scalar<MainBin> s4;
+Vector<MainBin> s5;
+Distribution<MainBin> s6;
+Vector<MainBin> s7;
AverageVector<> s8;
StandardDeviation<> s9;
AverageDeviation<> s10;
-Scalar<Counter> s11;
+Scalar<> s11;
Distribution<> s12;
VectorDistribution<> s13;
VectorStandardDeviation<> s14;
@@ -71,6 +74,8 @@ Formula f7;
MainBin bin1("bin1");
MainBin bin2("bin2");
+ostream *outputStream = &cout;
+
double
testfunc()
{
@@ -89,26 +94,57 @@ usage()
{
panic("incorrect usage.\n"
"usage:\n"
- "\t%s [-v]\n", progname);
+ "\t%s [-p <python file>] [-t [-c] [-d]]\n", progname);
}
int
main(int argc, char *argv[])
{
+ bool descriptions = false;
+ bool compat = false;
+ bool text = false;
+ string pyfile;
+ string mysql_name;
+ string mysql_host;
+ string mysql_user = "binkertn";
+ string mysql_passwd;
+
char c;
progname = argv[0];
- PrintDescriptions = false;
- while ((c = getopt(argc, argv, "v")) != -1) {
- cprintf("c == %c\n", c);
+ while ((c = getopt(argc, argv, "cdh:P:p:s:tu:")) != -1) {
switch (c) {
- case 'v':
- PrintDescriptions = true;
+ case 'c':
+ compat = true;
+ break;
+ case 'd':
+ descriptions = true;
+ break;
+ case 'h':
+ mysql_host = optarg;
+ break;
+ case 'P':
+ mysql_passwd = optarg;
+ break;
+ case 'p':
+ pyfile = 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);
@@ -214,6 +250,8 @@ main(int argc, char *argv[])
.flags(total)
.subname(0, "sub0")
.subname(1, "sub1")
+ .ysubname(0, "y0")
+ .ysubname(1, "y1")
;
f1
@@ -509,9 +547,24 @@ main(int argc, char *argv[])
s12.sample(100);
-// dump(cout, mode_simplescalar);
- python_start("/tmp/stats.py");
- python_dump("stattest", "all");
+ if (text) {
+ Text out(cout);
+ out.descriptions = descriptions;
+ out.compat = compat;
+ out();
+ }
+
+ if (!pyfile.empty()) {
+ Python out(pyfile);
+ out();
+ }
+
+ if (!mysql_name.empty()) {
+ MySql out;
+ out.connect(mysql_host, mysql_user, mysql_passwd, "m5stats",
+ mysql_name, "test");
+ out();
+ }
return 0;
}
diff --git a/util/config/m5config.py b/util/config/m5config.py
new file mode 100644
index 000000000..9aa3e0387
--- /dev/null
+++ b/util/config/m5config.py
@@ -0,0 +1,804 @@
+from __future__ import generators
+
+import os
+import re
+import sys
+
+#####################################################################
+#
+# M5 Python Configuration Utility
+#
+# The basic idea is to write simple Python programs that build Python
+# objects corresponding to M5 SimObjects for the deisred simulation
+# configuration. For now, the Python emits a .ini file that can be
+# parsed by M5. In the future, some tighter integration between M5
+# and the Python interpreter may allow bypassing the .ini file.
+#
+# Each SimObject class in M5 is represented by a Python class with the
+# same name. The Python inheritance tree mirrors the M5 C++ tree
+# (e.g., SimpleCPU derives from BaseCPU in both cases, and all
+# SimObjects inherit from a single SimObject base class). To specify
+# an instance of an M5 SimObject in a configuration, the user simply
+# instantiates the corresponding Python object. The parameters for
+# that SimObject are given by assigning to attributes of the Python
+# object, either using keyword assignment in the constructor or in
+# separate assignment statements. For example:
+#
+# cache = BaseCache('my_cache', root, size=64*K)
+# cache.hit_latency = 3
+# cache.assoc = 8
+#
+# (The first two constructor arguments specify the name of the created
+# cache and its parent node in the hierarchy.)
+#
+# The magic lies in the mapping of the Python attributes for SimObject
+# classes to the actual SimObject parameter specifications. This
+# allows parameter validity checking in the Python code. Continuing
+# the example above, the statements "cache.blurfl=3" or
+# "cache.assoc='hello'" would both result in runtime errors in Python,
+# since the BaseCache object has no 'blurfl' parameter and the 'assoc'
+# parameter requires an integer, respectively. This magic is done
+# primarily by overriding the special __setattr__ method that controls
+# assignment to object attributes.
+#
+# The Python module provides another class, ConfigNode, which is a
+# superclass of SimObject. ConfigNode implements the parent/child
+# relationship for building the configuration hierarchy tree.
+# Concrete instances of ConfigNode can be used to group objects in the
+# hierarchy, but do not correspond to SimObjects themselves (like a
+# .ini section with "children=" but no "type=".
+#
+# Once a set of Python objects have been instantiated in a hierarchy,
+# calling 'instantiate(obj)' (where obj is the root of the hierarchy)
+# will generate a .ini file. See simple-4cpu.py for an example
+# (corresponding to m5-test/simple-4cpu.ini).
+#
+#####################################################################
+
+#####################################################################
+#
+# ConfigNode/SimObject classes
+#
+# The Python class hierarchy rooted by ConfigNode (which is the base
+# class of SimObject, which in turn is the base class of all other M5
+# SimObject classes) has special attribute behavior. In general, an
+# object in this hierarchy has three categories of attribute-like
+# things:
+#
+# 1. Regular Python methods and variables. These must start with an
+# underscore to be treated normally.
+#
+# 2. SimObject parameters. These values are stored as normal Python
+# attributes, but all assignments to these attributes are checked
+# against the pre-defined set of parameters stored in the class's
+# _param_dict dictionary. Assignments to attributes that do not
+# correspond to predefined parameters, or that are not of the correct
+# type, incur runtime errors.
+#
+# 3. Hierarchy children. The child nodes of a ConfigNode are stored
+# in the node's _children dictionary, but can be accessed using the
+# Python attribute dot-notation (just as they are printed out by the
+# simulator). Children cannot be created using attribute assigment;
+# they must be added by specifying the parent node in the child's
+# constructor or using the '+=' operator.
+
+# The SimObject parameters are the most complex, for a few reasons.
+# First, both parameter descriptions and parameter values are
+# inherited. Thus parameter description lookup must go up the
+# inheritance chain like normal attribute lookup, but this behavior
+# must be explicitly coded since the lookup occurs in each class's
+# _param_dict attribute. Second, because parameter values can be set
+# on SimObject classes (to implement default values), the parameter
+# checking behavior must be enforced on class attribute assignments as
+# well as instance attribute assignments. Finally, because we allow
+# class specialization via inheritance (e.g., see the L1Cache class in
+# the simple-4cpu.py example), we must do parameter checking even on
+# class instantiation. To provide all these features, we use a
+# metaclass to define most of the SimObject parameter behavior for
+# this class hierarchy.
+#
+#####################################################################
+
+# The metaclass for ConfigNode (and thus for everything that derives
+# from ConfigNode, including SimObject). This class controls how new
+# classes that derive from ConfigNode are instantiated, and provides
+# inherited class behavior (just like a class controls how instances
+# of that class are instantiated, and provides inherited instance
+# behavior).
+class MetaConfigNode(type):
+
+ # __new__ is called before __init__, and is where the statements
+ # in the body of the class definition get loaded into the class's
+ # __dict__. We intercept this to filter out parameter assignments
+ # and only allow "private" attributes to be passed to the base
+ # __new__ (starting with underscore).
+ def __new__(cls, name, bases, dict):
+ priv_keys = [k for k in dict.iterkeys() if k.startswith('_')]
+ priv_dict = {}
+ for k in priv_keys: priv_dict[k] = dict[k]; del dict[k]
+ # entries left in dict will get passed to __init__, where we'll
+ # deal with them as params.
+ return super(MetaConfigNode, cls).__new__(cls, name, bases, priv_dict)
+
+ # initialization: start out with an empty param dict (makes life
+ # simpler if we can assume _param_dict is always valid). Also
+ # build inheritance list to simplify searching for inherited
+ # params. Finally set parameters specified in class definition
+ # (if any).
+ def __init__(cls, name, bases, dict):
+ super(MetaConfigNode, cls).__init__(cls, name, bases, {})
+ # initialize _param_dict to empty
+ cls._param_dict = {}
+ # __mro__ is the ordered list of classes Python uses for
+ # method resolution. We want to pick out the ones that have a
+ # _param_dict attribute for doing parameter lookups.
+ cls._param_bases = \
+ [c for c in cls.__mro__ if hasattr(c, '_param_dict')]
+ # initialize attributes with values from class definition
+ for (pname, value) in dict.items():
+ try:
+ setattr(cls, pname, value)
+ except Exception, exc:
+ print "Error setting '%s' to '%s' on class '%s'\n" \
+ % (pname, value, cls.__name__), exc
+
+ # set the class's parameter dictionary (called when loading
+ # class descriptions)
+ def set_param_dict(cls, param_dict):
+ # should only be called once (current one should be empty one
+ # from __init__)
+ assert not cls._param_dict
+ cls._param_dict = param_dict
+ # initialize attributes with default values
+ for (pname, param) in param_dict.items():
+ try:
+ setattr(cls, pname, param.default)
+ except Exception, exc:
+ print "Error setting '%s' default on class '%s'\n" \
+ % (pname, cls.__name__), exc
+
+ # Lookup a parameter description by name in the given class. Use
+ # the _param_bases list defined in __init__ to go up the
+ # inheritance hierarchy if necessary.
+ def lookup_param(cls, param_name):
+ for c in cls._param_bases:
+ param = c._param_dict.get(param_name)
+ if param: return param
+ return None
+
+ # Set attribute (called on foo.attr_name = value when foo is an
+ # instance of class cls).
+ def __setattr__(cls, attr_name, value):
+ # normal processing for private attributes
+ if attr_name.startswith('_'):
+ object.__setattr__(cls, attr_name, value)
+ return
+ # no '_': must be SimObject param
+ param = cls.lookup_param(attr_name)
+ if not param:
+ raise AttributeError, \
+ "Class %s has no parameter %s" % (cls.__name__, attr_name)
+ # It's ok: set attribute by delegating to 'object' class.
+ # Note the use of param.make_value() to verify/canonicalize
+ # the assigned value
+ object.__setattr__(cls, attr_name, param.make_value(value))
+
+ # generator that iterates across all parameters for this class and
+ # all classes it inherits from
+ def all_param_names(cls):
+ for c in cls._param_bases:
+ for p in c._param_dict.iterkeys():
+ yield p
+
+# The ConfigNode class is the root of the special hierarchy. Most of
+# the code in this class deals with the configuration hierarchy itself
+# (parent/child node relationships).
+class ConfigNode(object):
+ # Specify metaclass. Any class inheriting from ConfigNode will
+ # get this metaclass.
+ __metaclass__ = MetaConfigNode
+
+ # Constructor. Since bare ConfigNodes don't have parameters, just
+ # worry about the name and the parent/child stuff.
+ def __init__(self, _name, _parent=None):
+ # Type-check _name
+ if type(_name) != str:
+ if isinstance(_name, ConfigNode):
+ # special case message for common error of trying to
+ # coerce a SimObject to the wrong type
+ raise TypeError, \
+ "Attempt to coerce %s to %s" \
+ % (_name.__class__.__name__, self.__class__.__name__)
+ else:
+ raise TypeError, \
+ "%s name must be string (was %s, %s)" \
+ % (self.__class__.__name__, _name, type(_name))
+ # if specified, parent must be a subclass of ConfigNode
+ if _parent != None and not isinstance(_parent, ConfigNode):
+ raise TypeError, \
+ "%s parent must be ConfigNode subclass (was %s, %s)" \
+ % (self.__class__.__name__, _name, type(_name))
+ self._name = _name
+ self._parent = _parent
+ self._children = {}
+ if (_parent):
+ _parent.__addChild(self)
+ # Set up absolute path from root.
+ if (_parent and _parent._path != 'Universe'):
+ self._path = _parent._path + '.' + self._name
+ else:
+ self._path = self._name
+
+ # When printing (e.g. to .ini file), just give the name.
+ def __str__(self):
+ return self._name
+
+ # Catch attribute accesses that could be requesting children, and
+ # satisfy them. Note that __getattr__ is called only if the
+ # regular attribute lookup fails, so private and parameter lookups
+ # will already be satisfied before we ever get here.
+ def __getattr__(self, name):
+ try:
+ return self._children[name]
+ except KeyError:
+ raise AttributeError, \
+ "Node '%s' has no attribute or child '%s'" \
+ % (self._name, name)
+
+ # Set attribute. All attribute assignments go through here. Must
+ # be private attribute (starts with '_') or valid parameter entry.
+ # Basically identical to MetaConfigClass.__setattr__(), except
+ # this handles instances rather than class attributes.
+ def __setattr__(self, attr_name, value):
+ if attr_name.startswith('_'):
+ object.__setattr__(self, attr_name, value)
+ return
+ # not private; look up as param
+ param = self.__class__.lookup_param(attr_name)
+ if not param:
+ raise AttributeError, \
+ "Class %s has no parameter %s" \
+ % (self.__class__.__name__, attr_name)
+ # It's ok: set attribute by delegating to 'object' class.
+ # Note the use of param.make_value() to verify/canonicalize
+ # the assigned value
+ object.__setattr__(self, attr_name, param.make_value(value))
+
+ # Add a child to this node.
+ def __addChild(self, new_child):
+ # set child's parent before calling this function
+ assert new_child._parent == self
+ if not isinstance(new_child, ConfigNode):
+ raise TypeError, \
+ "ConfigNode child must also be of class ConfigNode"
+ if new_child._name in self._children:
+ raise AttributeError, \
+ "Node '%s' already has a child '%s'" \
+ % (self._name, new_child._name)
+ self._children[new_child._name] = new_child
+
+ # operator overload for '+='. You can say "node += child" to add
+ # a child that was created with parent=None. An early attempt
+ # at playing with syntax; turns out not to be that useful.
+ def __iadd__(self, new_child):
+ if new_child._parent != None:
+ raise AttributeError, \
+ "Node '%s' already has a parent" % new_child._name
+ new_child._parent = self
+ self.__addChild(new_child)
+ return self
+
+ # Print instance info to .ini file.
+ def _instantiate(self):
+ print '[' + self._path + ']' # .ini section header
+ if self._children:
+ # instantiate children in sorted order for backward
+ # compatibility (else we can end up with cpu1 before cpu0).
+ child_names = self._children.keys()
+ child_names.sort()
+ print 'children =',
+ for child_name in child_names:
+ print child_name,
+ print
+ self._instantiateParams()
+ print
+ # recursively dump out children
+ if self._children:
+ for child_name in child_names:
+ self._children[child_name]._instantiate()
+
+ # ConfigNodes have no parameters. Overridden by SimObject.
+ def _instantiateParams(self):
+ pass
+
+# SimObject is a minimal extension of ConfigNode, implementing a
+# hierarchy node that corresponds to an M5 SimObject. It prints out a
+# "type=" line to indicate its SimObject class, prints out the
+# assigned parameters corresponding to its class, and allows
+# parameters to be set by keyword in the constructor. Note that most
+# of the heavy lifting for the SimObject param handling is done in the
+# MetaConfigNode metaclass.
+
+class SimObject(ConfigNode):
+ # initialization: like ConfigNode, but handle keyword-based
+ # parameter initializers.
+ def __init__(self, _name, _parent=None, **params):
+ ConfigNode.__init__(self, _name, _parent)
+ for param, value in params.items():
+ setattr(self, param, value)
+
+ # print type and parameter values to .ini file
+ def _instantiateParams(self):
+ print "type =", self.__class__._name
+ for pname in self.__class__.all_param_names():
+ value = getattr(self, pname)
+ if value != None:
+ print pname, '=', value
+
+ def _sim_code(cls):
+ name = cls.__name__
+ param_names = cls._param_dict.keys()
+ param_names.sort()
+ code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name
+ decls = [" " + cls._param_dict[pname].sim_decl(pname) \
+ for pname in param_names]
+ code += "\n".join(decls) + "\n"
+ code += "END_DECLARE_SIM_OBJECT_PARAMS(%s)\n\n" % name
+ code += "BEGIN_INIT_SIM_OBJECT_PARAMS(%s)\n" % name
+ inits = [" " + cls._param_dict[pname].sim_init(pname) \
+ for pname in param_names]
+ code += ",\n".join(inits) + "\n"
+ code += "END_INIT_SIM_OBJECT_PARAMS(%s)\n\n" % name
+ return code
+ _sim_code = classmethod(_sim_code)
+
+#####################################################################
+#
+# Parameter description classes
+#
+# The _param_dict dictionary in each class maps parameter names to
+# either a Param or a VectorParam object. These objects contain the
+# parameter description string, the parameter type, and the default
+# value (loaded from the PARAM section of the .odesc files). The
+# make_value() method on these objects is used to force whatever value
+# is assigned to the parameter to the appropriate type.
+#
+# Note that the default values are loaded into the class's attribute
+# space when the parameter dictionary is initialized (in
+# MetaConfigNode.set_param_dict()); after that point they aren't
+# used.
+#
+#####################################################################
+
+def isNullPointer(value):
+ return isinstance(value, NullSimObject)
+
+def isSimObjectType(ptype):
+ return issubclass(ptype, SimObject)
+
+# Regular parameter.
+class Param(object):
+ # Constructor. E.g., Param(Int, "number of widgets", 5)
+ def __init__(self, ptype, desc, default=None):
+ self.ptype = ptype
+ self.ptype_name = self.ptype.__name__
+ self.desc = desc
+ self.default = default
+
+ # Convert assigned value to appropriate type. Force parameter
+ # value (rhs of '=') to ptype (or None, which means not set).
+ def make_value(self, value):
+ # nothing to do if None or already correct type. Also allow NULL
+ # pointer to be assigned where a SimObject is expected.
+ if value == None or isinstance(value, self.ptype) or \
+ isNullPointer(value) and isSimObjectType(self.ptype):
+ return value
+ # this type conversion will raise an exception if it's illegal
+ return self.ptype(value)
+
+ def sim_decl(self, name):
+ return 'Param<%s> %s;' % (self.ptype_name, name)
+
+ def sim_init(self, name):
+ if self.default == None:
+ return 'INIT_PARAM(%s, "%s")' % (name, self.desc)
+ else:
+ return 'INIT_PARAM_DFLT(%s, "%s", %s)' % \
+ (name, self.desc, str(self.default))
+
+# The _VectorParamValue class is a wrapper for vector-valued
+# parameters. The leading underscore indicates that users shouldn't
+# see this class; it's magically generated by VectorParam. The
+# parameter values are stored in the 'value' field as a Python list of
+# whatever type the parameter is supposed to be. The only purpose of
+# storing these instead of a raw Python list is that we can override
+# the __str__() method to not print out '[' and ']' in the .ini file.
+class _VectorParamValue(object):
+ def __init__(self, list):
+ self.value = list
+
+ def __str__(self):
+ return ' '.join(map(str, self.value))
+
+# Vector-valued parameter description. Just like Param, except that
+# the value is a vector (list) of the specified type instead of a
+# single value.
+class VectorParam(Param):
+
+ # Inherit Param constructor. However, the resulting parameter
+ # will be a list of ptype rather than a single element of ptype.
+ def __init__(self, ptype, desc, default=None):
+ Param.__init__(self, ptype, desc, default)
+
+ # Convert assigned value to appropriate type. If the RHS is not a
+ # list or tuple, it generates a single-element list.
+ def make_value(self, value):
+ if value == None: return value
+ if isinstance(value, list) or isinstance(value, tuple):
+ # list: coerce each element into new list
+ val_list = [Param.make_value(self, v) for v in iter(value)]
+ else:
+ # singleton: coerce & wrap in a list
+ val_list = [Param.make_value(self, value)]
+ # wrap list in _VectorParamValue (see above)
+ return _VectorParamValue(val_list)
+
+ def sim_decl(self, name):
+ return 'VectorParam<%s> %s;' % (self.ptype_name, name)
+
+ # sim_init inherited from Param
+
+#####################################################################
+#
+# Parameter Types
+#
+# Though native Python types could be used to specify parameter types
+# (the 'ptype' field of the Param and VectorParam classes), it's more
+# flexible to define our own set of types. This gives us more control
+# over how Python expressions are converted to values (via the
+# __init__() constructor) and how these values are printed out (via
+# the __str__() conversion method). Eventually we'll need these types
+# to correspond to distinct C++ types as well.
+#
+#####################################################################
+
+# Integer parameter type.
+class Int(object):
+ # Constructor. Value must be Python int or long (long integer).
+ def __init__(self, value):
+ t = type(value)
+ if t == int or t == long:
+ self.value = value
+ else:
+ raise TypeError, "Int param got value %s %s" % (repr(value), t)
+
+ # Use Python string conversion. Note that this puts an 'L' on the
+ # end of long integers; we can strip that off here if it gives us
+ # trouble.
+ def __str__(self):
+ return str(self.value)
+
+# Counter, Addr, and Tick are just aliases for Int for now.
+class Counter(Int):
+ pass
+
+class Addr(Int):
+ pass
+
+class Tick(Int):
+ pass
+
+# Boolean parameter type.
+class Bool(object):
+
+ # Constructor. Typically the value will be one of the Python bool
+ # constants True or False (or the aliases true and false below).
+ # Also need to take integer 0 or 1 values since bool was not a
+ # distinct type in Python 2.2. Parse a bunch of boolean-sounding
+ # strings too just for kicks.
+ def __init__(self, value):
+ t = type(value)
+ if t == bool:
+ self.value = value
+ elif t == int or t == long:
+ if value == 1:
+ self.value = True
+ elif value == 0:
+ self.value = False
+ elif t == str:
+ v = value.lower()
+ if v == "true" or v == "t" or v == "yes" or v == "y":
+ self.value = True
+ elif v == "false" or v == "f" or v == "no" or v == "n":
+ self.value = False
+ # if we didn't set it yet, it must not be something we understand
+ if not hasattr(self, 'value'):
+ raise TypeError, "Bool param got value %s %s" % (repr(value), t)
+
+ # Generate printable string version.
+ def __str__(self):
+ if self.value: return "true"
+ else: return "false"
+
+# String-valued parameter.
+class String(object):
+ # Constructor. Value must be Python string.
+ def __init__(self, value):
+ t = type(value)
+ if t == str:
+ self.value = value
+ else:
+ raise TypeError, "String param got value %s %s" % (repr(value), t)
+
+ # Generate printable string version. Not too tricky.
+ def __str__(self):
+ return self.value
+
+# Special class for NULL pointers. Note the special check in
+# make_param_value() above that lets these be assigned where a
+# SimObject is required.
+class NullSimObject(object):
+ # Constructor. No parameters, nothing to do.
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ return "NULL"
+
+# The only instance you'll ever need...
+NULL = NullSimObject()
+
+# Enumerated types are a little more complex. The user specifies the
+# type as Enum(foo) where foo is either a list or dictionary of
+# alternatives (typically strings, but not necessarily so). (In the
+# long run, the integer value of the parameter will be the list index
+# or the corresponding dictionary value. For now, since we only check
+# that the alternative is valid and then spit it into a .ini file,
+# there's not much point in using the dictionary.)
+
+# What Enum() must do is generate a new type encapsulating the
+# provided list/dictionary so that specific values of the parameter
+# can be instances of that type. We define two hidden internal
+# classes (_ListEnum and _DictEnum) to serve as base classes, then
+# derive the new type from the appropriate base class on the fly.
+
+
+# Base class for list-based Enum types.
+class _ListEnum(object):
+ # Constructor. Value must be a member of the type's map list.
+ def __init__(self, value):
+ if value in self.map:
+ self.value = value
+ self.index = self.map.index(value)
+ else:
+ raise TypeError, "Enum param got bad value '%s' (not in %s)" \
+ % (value, self.map)
+
+ # Generate printable string version of value.
+ def __str__(self):
+ return str(self.value)
+
+class _DictEnum(object):
+ # Constructor. Value must be a key in the type's map dictionary.
+ def __init__(self, value):
+ if value in self.map:
+ self.value = value
+ self.index = self.map[value]
+ else:
+ raise TypeError, "Enum param got bad value '%s' (not in %s)" \
+ % (value, self.map.keys())
+
+ # Generate printable string version of value.
+ def __str__(self):
+ return str(self.value)
+
+# Enum metaclass... calling Enum(foo) generates a new type (class)
+# that derives from _ListEnum or _DictEnum as appropriate.
+class Enum(type):
+ # counter to generate unique names for generated classes
+ counter = 1
+
+ def __new__(cls, map):
+ if isinstance(map, dict):
+ base = _DictEnum
+ keys = map.keys()
+ elif isinstance(map, list):
+ base = _ListEnum
+ keys = map
+ else:
+ raise TypeError, "Enum map must be list or dict (got %s)" % map
+ classname = "Enum%04d" % Enum.counter
+ Enum.counter += 1
+ # New class derives from selected base, and gets a 'map'
+ # attribute containing the specified list or dict.
+ return type.__new__(cls, classname, (base,), { 'map': map })
+
+
+#
+# "Constants"... handy aliases for various values.
+#
+
+# For compatibility with C++ bool constants.
+false = False
+true = True
+
+# Some memory range specifications use this as a default upper bound.
+MAX_ADDR = 2 ** 63
+
+# For power-of-two sizing, e.g. 64*K gives an integer value 65536.
+K = 1024
+M = K*K
+G = K*M
+
+#####################################################################
+#
+# Object description loading.
+#
+# The final step is to define the classes corresponding to M5 objects
+# and their parameters. These classes are described in .odesc files
+# in the source tree. This code walks the tree to find those files
+# and loads up the descriptions (by evaluating them in pieces as
+# Python code).
+#
+#
+# Because SimObject classes inherit from other SimObject classes, and
+# can use arbitrary other SimObject classes as parameter types, we
+# have to do this in three steps:
+#
+# 1. Walk the tree to find all the .odesc files. Note that the base
+# of the filename *must* match the class name. This step builds a
+# mapping from class names to file paths.
+#
+# 2. Start generating empty class definitions (via def_class()) using
+# the OBJECT field of the .odesc files to determine inheritance.
+# def_class() recurses on demand to define needed base classes before
+# derived classes.
+#
+# 3. Now that all of the classes are defined, go through the .odesc
+# files one more time loading the parameter descriptions.
+#
+#####################################################################
+
+# dictionary: maps object names to file paths
+odesc_file = {}
+
+# dictionary: maps object names to boolean flag indicating whether
+# class definition was loaded yet. Since SimObject is defined in
+# m5.config.py, count it as loaded.
+odesc_loaded = { 'SimObject': True }
+
+# Find odesc files in namelist and initialize odesc_file and
+# odesc_loaded dictionaries. Called via os.path.walk() (see below).
+def find_odescs(process, dirpath, namelist):
+ # Prune out SCCS directories so we don't process s.*.odesc files.
+ i = 0
+ while i < len(namelist):
+ if namelist[i] == "SCCS":
+ del namelist[i]
+ else:
+ i = i + 1
+ # Find .odesc files and record them.
+ for name in namelist:
+ if name.endswith('.odesc'):
+ objname = name[:name.rindex('.odesc')]
+ path = os.path.join(dirpath, name)
+ if odesc_file.has_key(objname):
+ print "Warning: duplicate object names:", \
+ odesc_file[objname], path
+ odesc_file[objname] = path
+ odesc_loaded[objname] = False
+
+
+# Regular expression string for parsing .odesc files.
+file_re_string = r'''
+^OBJECT: \s* (\w+) \s* \( \s* (\w+) \s* \)
+\s*
+^PARAMS: \s*\n ( (\s+.*\n)* )
+'''
+
+# Compiled regular expression object.
+file_re = re.compile(file_re_string, re.MULTILINE | re.VERBOSE)
+
+# .odesc file parsing function. Takes a filename and returns tuple of
+# object name, object base, and parameter description section.
+def parse_file(path):
+ f = open(path, 'r').read()
+ m = file_re.search(f)
+ if not m:
+ print "Can't parse", path
+ sys.exit(1)
+ return (m.group(1), m.group(2), m.group(3))
+
+# Define SimObject class based on description in specified filename.
+# Class itself is empty except for _name attribute; parameter
+# descriptions will be loaded later. Will recurse to define base
+# classes as needed before defining specified class.
+def def_class(path):
+ # load & parse file
+ (obj, parent, params) = parse_file(path)
+ # check to see if base class is defined yet; define it if not
+ if not odesc_loaded.has_key(parent):
+ print "No .odesc file found for", parent
+ sys.exit(1)
+ if not odesc_loaded[parent]:
+ def_class(odesc_file[parent])
+ # define the class. The _name attribute of the class lets us
+ # track the actual SimObject class name even when we derive new
+ # subclasses in scripts (to provide new parameter value settings).
+ s = "class %s(%s): _name = '%s'" % (obj, parent, obj)
+ try:
+ # execute in global namespace, so new class will be globally
+ # visible
+ exec s in globals()
+ except Exception, exc:
+ print "Object error in %s:" % path, exc
+ # mark this file as loaded
+ odesc_loaded[obj] = True
+
+# Munge an arbitrary Python code string to get it to execute (mostly
+# dealing with indentation). Stolen from isa_parser.py... see
+# comments there for a more detailed description.
+def fixPythonIndentation(s):
+ # get rid of blank lines first
+ s = re.sub(r'(?m)^\s*\n', '', s);
+ if (s != '' and re.match(r'[ \t]', s[0])):
+ s = 'if 1:\n' + s
+ return s
+
+# Load parameter descriptions from .odesc file. Object class must
+# already be defined.
+def def_params(path):
+ # load & parse file
+ (obj_name, parent_name, param_code) = parse_file(path)
+ # initialize param dict
+ param_dict = {}
+ # execute parameter descriptions.
+ try:
+ # "in globals(), param_dict" makes exec use the current
+ # globals as the global namespace (so all of the Param
+ # etc. objects are visible) and param_dict as the local
+ # namespace (so the newly defined parameter variables will be
+ # entered into param_dict).
+ exec fixPythonIndentation(param_code) in globals(), param_dict
+ except Exception, exc:
+ print "Param error in %s:" % path, exc
+ return
+ # Convert object name string to Python class object
+ obj = eval(obj_name)
+ # Set the object's parameter description dictionary (see MetaConfigNode).
+ obj.set_param_dict(param_dict)
+
+
+# Walk directory tree to find .odesc files.
+# Someday we'll have to make the root path an argument instead of
+# hard-coding it. For now the assumption is you're running this in
+# util/config.
+root = '../..'
+os.path.walk(root, find_odescs, None)
+
+# Iterate through file dictionary and define classes.
+for objname, path in odesc_file.iteritems():
+ if not odesc_loaded[objname]:
+ def_class(path)
+
+sim_object_list = odesc_loaded.keys()
+sim_object_list.sort()
+
+# Iterate through files again and load parameters.
+for path in odesc_file.itervalues():
+ def_params(path)
+
+#####################################################################
+
+# Hook to generate C++ parameter code.
+def gen_sim_code(file):
+ for objname in sim_object_list:
+ print >> file, eval("%s._sim_code()" % objname)
+
+# The final hook to generate .ini files. Called from configuration
+# script once config is built.
+def instantiate(*objs):
+ for obj in objs:
+ obj._instantiate()
+
+
diff --git a/util/emacs/m5-c-style.el b/util/emacs/m5-c-style.el
index 7f25e9f5f..b9d16a4b1 100644
--- a/util/emacs/m5-c-style.el
+++ b/util/emacs/m5-c-style.el
@@ -1,4 +1,4 @@
-; Copyright (c) 2003 The Regents of The University of Michigan
+; Copyright (c) 2003-2004 The Regents of The University of Michigan
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -28,12 +28,13 @@
; Steve Reinhardt
(c-add-style "m5"
- '((c-basic-offset . 4)
- (c-offsets-alist . ((substatement-open . 0)
- (inline-open . 0)
- (block-open . -4)
- (case-label . 2)
- (label . 2)
- (statement-case-intro . 2)
- (statement-case-open . 2)
- (access-label . -2)))))
+ '((c-basic-offset . 4)
+ (c-offsets-alist . ((substatement-open . 0)
+ (inline-open . 0)
+ (block-open . -4)
+ (case-label . 2)
+ (label . 2)
+ (statement-case-intro . 2)
+ (statement-case-open . 2)
+ (access-label . -2)
+ (innamespace . 0)))))
diff --git a/util/tracediff b/util/tracediff
index 0aa579a7d..ed35d5dd7 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -41,8 +41,8 @@ $sim2 = shift;
# be given to both invocations
$simargs = '"' . join('" "', @ARGV) . '"';
-$cmd1 = "$sim1 $simargs --stats:file=tracediff-$$-1.stats 2>&1 |";
-$cmd2 = "$sim2 $simargs --stats:file=tracediff-$$-2.stats 2>&1 |";
+$cmd1 = "$sim1 $simargs --stats:text_file=tracediff-$$-1.stats 2>&1 |";
+$cmd2 = "$sim2 $simargs --stats:text_file=tracediff-$$-2.stats 2>&1 |";
# This only works if you have rundiff in your path. I just edit it
# with an explicit path if necessary.