first pass at merging m5 with linux
--HG-- extra : convert_revision : dfe23349b80ae3b34d3cb95c5734e01ef62f700e
This commit is contained in:
commit
a5f90eba3b
67 changed files with 5639 additions and 2733 deletions
356
Doxyfile
356
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 =
|
||||
|
|
|
@ -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 §ion)
|
||||
AlphaTLB::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(size);
|
||||
UNSERIALIZE_SCALAR(nlu);
|
||||
|
@ -255,13 +249,13 @@ AlphaTlb::unserialize(Checkpoint *cp, const string §ion)
|
|||
//
|
||||
// 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)
|
||||
|
||||
|
|
|
@ -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 §ion);
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,44 +239,29 @@ def template BasicDeclare {{
|
|||
%(constructor)s;
|
||||
}
|
||||
|
||||
Fault execute(SimpleCPU *cpu, ExecContext *xc,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
%(exec_func_declarations)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template BasicExecute {{
|
||||
Fault %(class_name)s::execute(%(cpu_model)s *xc,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
Fault fault = No_Fault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(code)s;
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(op_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template BasicDecode {{
|
||||
return new %(class_name)s(machInst);
|
||||
}};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(postacc_code)s;
|
||||
}
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(simple_nonmem_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
|
||||
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) {
|
||||
%(dtld_nonmem_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
%(exec_func_declarations)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template LoadStoreExecute {{
|
||||
Fault %(class_name)s::execute(%(cpu_model)s *xc,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = No_Fault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_nonmem_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(op_mem_rd)s;
|
||||
%(memacc_code)s;
|
||||
}
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(op_mem_wb)s;
|
||||
}
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(postacc_code)s;
|
||||
}
|
||||
|
||||
if (fault == No_Fault) {
|
||||
%(op_nonmem_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template PrefetchDeclare {{
|
||||
/**
|
||||
|
@ -1048,44 +897,29 @@ def template PrefetchDeclare {{
|
|||
%(constructor)s;
|
||||
}
|
||||
|
||||
Fault execute(SimpleCPU *cpu, ExecContext *xc,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = No_Fault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(exec_decl)s;
|
||||
%(simple_nonmem_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (fault == No_Fault) {
|
||||
cpu->prefetch(EA, memAccessFlags);
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
%(exec_func_declarations)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template PrefetchExecute {{
|
||||
Fault %(class_name)s::execute(%(cpu_model)s *xc,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = No_Fault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_nonmem_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (fault == No_Fault) {
|
||||
xc->prefetch(EA, memAccessFlags);
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
}};
|
||||
|
||||
// load instructions use Ra as dest, so check for
|
||||
// Ra == 31 to detect nops
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -41,9 +41,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "base/sat_counter.hh"
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "sim/sim_stats.hh"
|
||||
|
||||
class HybridPredictor : public GenericPredictor
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
97
base/mysql.cc
Normal file
97
base/mysql.cc
Normal file
|
@ -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 */ }
|
410
base/mysql.hh
Normal file
410
base/mysql.hh
Normal file
|
@ -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__
|
|
@ -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;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "base/predictor.hh"
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "sim/sim_stats.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
//
|
||||
//
|
||||
|
|
1144
base/statistics.cc
1144
base/statistics.cc
File diff suppressed because it is too large
Load diff
1285
base/statistics.hh
1285
base/statistics.hh
File diff suppressed because it is too large
Load diff
73
base/stats/flags.hh
Normal file
73
base/stats/flags.hh
Normal file
|
@ -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__
|
844
base/stats/mysql.cc
Normal file
844
base/stats/mysql.cc
Normal file
|
@ -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 */ }
|
149
base/stats/mysql.hh
Normal file
149
base/stats/mysql.hh
Normal file
|
@ -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__
|
47
base/stats/output.hh
Normal file
47
base/stats/output.hh
Normal file
|
@ -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__
|
89
base/stats/statdb.cc
Normal file
89
base/stats/statdb.cc
Normal file
|
@ -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 */ }
|
74
base/stats/statdb.hh
Normal file
74
base/stats/statdb.hh
Normal file
|
@ -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__
|
731
base/stats/text.cc
Normal file
731
base/stats/text.cc
Normal file
|
@ -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 */ }
|
77
base/stats/text.hh
Normal file
77
base/stats/text.hh
Normal file
|
@ -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__
|
49
base/stats/types.hh
Normal file
49
base/stats/types.hh
Normal file
|
@ -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__
|
41
base/stats/visit.cc
Normal file
41
base/stats/visit.cc
Normal file
|
@ -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 */ }
|
63
base/stats/visit.hh
Normal file
63
base/stats/visit.hh
Normal file
|
@ -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__
|
15
base/time.cc
15
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include "base/trace_flags.hh"
|
||||
#include "base/traceflags.hh"
|
||||
|
||||
namespace Trace {
|
||||
|
||||
|
|
336
base/traceflags.py
Normal file
336
base/traceflags.py
Normal file
|
@ -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()
|
||||
|
41
base/userinfo.cc
Normal file
41
base/userinfo.cc
Normal file
|
@ -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;
|
||||
}
|
36
base/userinfo.hh
Normal file
36
base/userinfo.hh
Normal file
|
@ -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__
|
|
@ -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
|
||||
|
|
|
@ -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(®s, 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(®s, 0, sizeof(RegFile));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -84,14 +84,6 @@ SimObject::resetStats()
|
|||
{
|
||||
}
|
||||
|
||||
//
|
||||
// no default extra output
|
||||
//
|
||||
void
|
||||
SimObject::printExtraOutput(ostream &os)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// static function:
|
||||
// call regStats() on all SimObjects and then regFormulas() on all
|
||||
|
@ -162,21 +154,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.
|
||||
//
|
||||
|
|
|
@ -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 &);
|
||||
};
|
||||
|
|
207
sim/stat_control.cc
Normal file
207
sim/stat_control.cc
Normal file
|
@ -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();
|
||||
}
|
||||
|
52
sim/stat_control.hh
Normal file
52
sim/stat_control.hh
Normal file
|
@ -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__
|
41
sim/stats.hh
Normal file
41
sim/stats.hh
Normal file
|
@ -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__
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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: test/bitvectest.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
bitvectest: bitvectest.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
circletest: test/circletest.cc base/circlebuf.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
circletest: circletest.o circlebuf.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
cprintftest: test/cprintftest.cc base/cprintf.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
cprintftest: cprintftest.o cprintf.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
initest: initest.o str.o inifile.o cprintf.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
lrutest: test/lru_test.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
lrutest: lru_test.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
nmtest: test/nmtest.cc base/object_file.cc base/symtab.cc base/misc.cc base/str.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
nmtest: nmtest.o object_file.o symtab.o misc.o str.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
offtest: test/offtest.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
offtest: offtest.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
rangetest: test/rangetest.cc base/range.cc base/str.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
rangetest: rangetest.o range.o str.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 $@ $^
|
||||
|
||||
stattest: cprintf.o hostinfo.o misc.o python.o statistics.o stattest.o \
|
||||
str.o time.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
strnumtest: test/strnumtest.cc base/str.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
strnumtest: strnumtest.o str.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
symtest: test/symtest.cc base/misc.cc base/symtab.cc base/str.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
symtest: misc.o symtest.o symtab.o str.o
|
||||
$(CXX) $(LFLAGS) -o $@ $^
|
||||
tokentest: test/tokentest.cc base/str.cc
|
||||
$(CXX) $(CCFLAGS) -o $@ $^
|
||||
|
||||
tokentest: tokentest.o str.o
|
||||
$(CXX) $(LFLAGS) -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
804
util/config/m5config.py
Normal file
804
util/config/m5config.py
Normal file
|
@ -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()
|
||||
|
||||
|
|
@ -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)))))
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue