first pass at merging m5 with linux

--HG--
extra : convert_revision : dfe23349b80ae3b34d3cb95c5734e01ef62f700e
This commit is contained in:
Lisa Hsu 2004-05-11 01:15:18 -04:00
commit a5f90eba3b
67 changed files with 5639 additions and 2733 deletions

356
Doxyfile
View file

@ -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 =

View file

@ -44,20 +44,14 @@ using namespace std;
//
// Alpha TLB
//
#ifdef DEBUG
bool uncacheBit39 = false;
bool uncacheBit40 = false;
#endif
AlphaTlb::AlphaTlb(const string &name, int s)
AlphaTLB::AlphaTLB(const string &name, int s)
: SimObject(name), size(s), nlu(0)
{
table = new AlphaISA::PTE[size];
memset(table, 0, sizeof(AlphaISA::PTE[size]));
}
AlphaTlb::~AlphaTlb()
AlphaTLB::~AlphaTLB()
{
if (table)
delete [] table;
@ -65,7 +59,7 @@ AlphaTlb::~AlphaTlb()
// look up an entry in the TLB
AlphaISA::PTE *
AlphaTlb::lookup(Addr vpn, uint8_t asn) const
AlphaTLB::lookup(Addr vpn, uint8_t asn) const
{
DPRINTF(TLB, "lookup %#x\n", vpn);
@ -89,7 +83,7 @@ AlphaTlb::lookup(Addr vpn, uint8_t asn) const
void
AlphaTlb::checkCacheability(MemReqPtr &req)
AlphaTLB::checkCacheability(MemReqPtr &req)
{
// in Alpha, cacheability is controlled by upper-level bits of the
// physical address
@ -135,7 +129,7 @@ AlphaTlb::checkCacheability(MemReqPtr &req)
// insert a new TLB entry
void
AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte)
{
if (table[nlu].valid) {
Addr oldvpn = table[nlu].tag;
@ -169,7 +163,7 @@ AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
}
void
AlphaTlb::flushAll()
AlphaTLB::flushAll()
{
memset(table, 0, sizeof(AlphaISA::PTE[size]));
lookupTable.clear();
@ -177,7 +171,7 @@ AlphaTlb::flushAll()
}
void
AlphaTlb::flushProcesses()
AlphaTLB::flushProcesses()
{
PageTable::iterator i = lookupTable.begin();
PageTable::iterator end = lookupTable.end();
@ -197,7 +191,7 @@ AlphaTlb::flushProcesses()
}
void
AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
AlphaTLB::flushAddr(Addr vaddr, uint8_t asn)
{
Addr vpn = VA_VPN(vaddr);
@ -225,7 +219,7 @@ AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
void
AlphaTlb::serialize(ostream &os)
AlphaTLB::serialize(ostream &os)
{
SERIALIZE_SCALAR(size);
SERIALIZE_SCALAR(nlu);
@ -237,7 +231,7 @@ AlphaTlb::serialize(ostream &os)
}
void
AlphaTlb::unserialize(Checkpoint *cp, const string &section)
AlphaTLB::unserialize(Checkpoint *cp, const string &section)
{
UNSERIALIZE_SCALAR(size);
UNSERIALIZE_SCALAR(nlu);
@ -255,13 +249,13 @@ AlphaTlb::unserialize(Checkpoint *cp, const string &section)
//
// Alpha ITB
//
AlphaItb::AlphaItb(const std::string &name, int size)
: AlphaTlb(name, size)
AlphaITB::AlphaITB(const std::string &name, int size)
: AlphaTLB(name, size)
{}
void
AlphaItb::regStats()
AlphaITB::regStats()
{
hits
.name(name() + ".hits")
@ -280,7 +274,7 @@ AlphaItb::regStats()
}
void
AlphaItb::fault(Addr pc, ExecContext *xc) const
AlphaITB::fault(Addr pc, ExecContext *xc) const
{
uint64_t *ipr = xc->regs.ipr;
@ -293,7 +287,7 @@ AlphaItb::fault(Addr pc, ExecContext *xc) const
Fault
AlphaItb::translate(MemReqPtr &req) const
AlphaITB::translate(MemReqPtr &req) const
{
InternalProcReg *ipr = req->xc->regs.ipr;
@ -311,7 +305,7 @@ AlphaItb::translate(MemReqPtr &req) const
if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
return Itb_Acv_Fault;
return ITB_Acv_Fault;
}
// Check for "superpage" mapping: when SP<1> is set, and
@ -373,12 +367,12 @@ AlphaItb::translate(MemReqPtr &req) const
//
// Alpha DTB
//
AlphaDtb::AlphaDtb(const std::string &name, int size)
: AlphaTlb(name, size)
AlphaDTB::AlphaDTB(const std::string &name, int size)
: AlphaTLB(name, size)
{}
void
AlphaDtb::regStats()
AlphaDTB::regStats()
{
read_hits
.name(name() + ".read_hits")
@ -447,7 +441,7 @@ AlphaDtb::regStats()
}
void
AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
{
uint64_t *ipr = xc->regs.ipr;
@ -471,7 +465,7 @@ AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
}
Fault
AlphaDtb::translate(MemReqPtr &req, bool write) const
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
RegFile *regs = &req->xc->regs;
Addr pc = regs->pc;
@ -497,7 +491,7 @@ AlphaDtb::translate(MemReqPtr &req, bool write) const
req->xc);
if (write) { write_acv++; } else { read_acv++; }
return Dtb_Fault_Fault;
return DTB_Fault_Fault;
}
// Check for "superpage" mapping: when SP<1> is set, and
@ -593,7 +587,7 @@ AlphaDtb::translate(MemReqPtr &req, bool write) const
}
AlphaISA::PTE &
AlphaTlb::index(bool advance)
AlphaTLB::index(bool advance)
{
AlphaISA::PTE *pte = &table[nlu];
@ -603,43 +597,45 @@ AlphaTlb::index(bool advance)
return *pte;
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
Param<int> size;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb)
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
INIT_PARAM_DFLT(size, "TLB size", 48)
END_INIT_SIM_OBJECT_PARAMS(AlphaItb)
END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
CREATE_SIM_OBJECT(AlphaItb)
CREATE_SIM_OBJECT(AlphaITB)
{
return new AlphaItb(getInstanceName(), size);
return new AlphaITB(getInstanceName(), size);
}
REGISTER_SIM_OBJECT("AlphaITB", AlphaItb)
REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
Param<int> size;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
INIT_PARAM_DFLT(size, "TLB size", 64)
END_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
CREATE_SIM_OBJECT(AlphaDtb)
CREATE_SIM_OBJECT(AlphaDTB)
{
return new AlphaDtb(getInstanceName(), size);
return new AlphaDTB(getInstanceName(), size);
}
REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb)
REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)

View file

@ -37,7 +37,7 @@
class ExecContext;
class AlphaTlb : public SimObject
class AlphaTLB : public SimObject
{
protected:
typedef std::multimap<Addr, int> PageTable;
@ -51,8 +51,8 @@ class AlphaTlb : public SimObject
AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
public:
AlphaTlb(const std::string &name, int size);
virtual ~AlphaTlb();
AlphaTLB(const std::string &name, int size);
virtual ~AlphaTLB();
int getsize() const { return size; }
@ -77,7 +77,7 @@ class AlphaTlb : public SimObject
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
class AlphaItb : public AlphaTlb
class AlphaITB : public AlphaTLB
{
protected:
mutable Statistics::Scalar<> hits;
@ -89,13 +89,13 @@ class AlphaItb : public AlphaTlb
void fault(Addr pc, ExecContext *xc) const;
public:
AlphaItb(const std::string &name, int size);
AlphaITB(const std::string &name, int size);
virtual void regStats();
Fault translate(MemReqPtr &req) const;
};
class AlphaDtb : public AlphaTlb
class AlphaDTB : public AlphaTLB
{
protected:
mutable Statistics::Scalar<> read_hits;
@ -115,7 +115,7 @@ class AlphaDtb : public AlphaTlb
void fault(Addr pc, uint64_t flags, ExecContext *xc) const;
public:
AlphaDtb(const std::string &name, int size);
AlphaDTB(const std::string &name, int size);
virtual void regStats();
Fault translate(MemReqPtr &req, bool write) const;

View file

@ -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 */

View file

@ -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

View file

@ -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 {

View file

@ -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);
}

View file

@ -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])

View file

@ -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);

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -41,9 +41,7 @@
#include <string>
#include "base/sat_counter.hh"
#include "base/statistics.hh"
#include "sim/sim_stats.hh"
class HybridPredictor : public GenericPredictor
{

View file

@ -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
View 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
View 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__

View file

@ -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;

View file

@ -34,7 +34,7 @@
#include "base/predictor.hh"
#include "base/statistics.hh"
#include "sim/sim_stats.hh"
#include "sim/stats.hh"
//
//

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

73
base/stats/flags.hh Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__

View file

@ -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);

View file

@ -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;

View file

@ -43,7 +43,7 @@
#endif
#endif
#include "base/trace_flags.hh"
#include "base/traceflags.hh"
namespace Trace {

336
base/traceflags.py Normal file
View 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
View 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
View 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__

View file

@ -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

View file

@ -42,7 +42,7 @@ using namespace std;
// constructor
#ifdef FULL_SYSTEM
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
AlphaItb *_itb, AlphaDtb *_dtb,
AlphaITB *_itb, AlphaDTB *_dtb,
FunctionalMemory *_mem)
: _status(ExecContext::Unallocated),
kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
@ -60,6 +60,7 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
process(_process), mem(process->getMemory()), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
memset(&regs, 0, sizeof(RegFile));
}
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
@ -67,6 +68,7 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
: cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
memset(&regs, 0, sizeof(RegFile));
}
#endif

View file

@ -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

View file

@ -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")
;

View file

@ -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);

View file

@ -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;
}

View file

@ -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__

View file

@ -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;
/**

View file

@ -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)

View file

@ -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)

View file

@ -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);
}

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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;
}

View file

@ -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)
////////////////////////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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;

View file

@ -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.
//

View file

@ -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
View 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
View 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
View 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__

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -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
View 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()

View file

@ -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)))))

View file

@ -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.