merge m5 with linux for the event and binning lifting

--HG--
extra : convert_revision : 09d3678746c2e9a93a9982dc75d5e1ac309cb2fa
This commit is contained in:
Lisa Hsu 2004-05-18 01:40:03 -04:00
commit a0ccdf8aba
28 changed files with 1844 additions and 1224 deletions

View file

@ -1,7 +1,6 @@
/* $Id$ */
#include "targetarch/alpha_memory.hh"
#include "sim/annotation.hh"
#ifdef DEBUG
#include "sim/debug.hh"
#endif
@ -126,8 +125,6 @@ ExecContext::ev5_trap(Fault fault)
regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
regs.npc = regs.pc + sizeof(MachInst);
Annotate::Ev5Trap(this, fault);
}
@ -303,6 +300,7 @@ Fault
ExecContext::setIpr(int idx, uint64_t val)
{
uint64_t *ipr = regs.ipr;
uint64_t old;
if (misspeculating())
return No_Fault;
@ -355,9 +353,9 @@ ExecContext::setIpr(int idx, uint64_t val)
case AlphaISA::IPR_PALtemp23:
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
kernelStats.context(ipr[idx]);
Annotate::Context(this);
kernelStats.context(old, val);
break;
case AlphaISA::IPR_DTB_PTE:
@ -385,11 +383,9 @@ ExecContext::setIpr(int idx, uint64_t val)
// only write least significant five bits - interrupt level
ipr[idx] = val & 0x1f;
kernelStats.swpipl(ipr[idx]);
Annotate::IPL(this, val & 0x1f);
break;
case AlphaISA::IPR_DTB_CM:
Annotate::ChangeMode(this, (val & 0x18) != 0);
kernelStats.mode((val & 0x18) != 0);
case AlphaISA::IPR_ICM:

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,6 @@
#include "arch/alpha/pseudo_inst.hh"
#include "cpu/exec_context.hh"
#include "sim/annotation.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
@ -46,17 +45,33 @@ namespace AlphaPseudo
bool doCheckpointInsts;
bool doQuiesce;
void
arm(ExecContext *xc)
{
xc->kernelStats.arm();
}
void
quiesce(ExecContext *xc)
{
if (!doQuiesce)
return;
Annotate::QUIESCE(xc);
xc->suspend();
xc->kernelStats.quiesce();
}
void
ivlb(ExecContext *xc)
{
xc->kernelStats.ivlb();
}
void
ivle(ExecContext *xc)
{
}
void
m5exit_old(ExecContext *xc)
{

View file

@ -37,7 +37,10 @@ namespace AlphaPseudo
extern bool doCheckpointInsts;
extern bool doQuiesce;
void arm(ExecContext *xc);
void quiesce(ExecContext *xc);
void ivlb(ExecContext *xc);
void ivle(ExecContext *xc);
void m5exit(ExecContext *xc);
void m5exit_old(ExecContext *xc);
void resetstats(ExecContext *xc);

113
arch/alpha/vptr.hh Normal file
View file

@ -0,0 +1,113 @@
/*
* 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 __VPTR_HH__
#define __VPTR_HH__
#include "arch/alpha/vtophys.hh"
class ExecContext;
template <class T>
class VPtr
{
public:
typedef T Type;
private:
ExecContext *xc;
Addr ptr;
public:
ExecContext *GetXC() const { return xc; }
Addr GetPointer() const { return ptr; }
public:
explicit VPtr(ExecContext *_xc, Addr p = 0) : xc(_xc), ptr(p) { }
template <class U>
VPtr(const VPtr<U> &vp) : xc(vp.GetXC()), ptr(vp.GetPointer()) {}
~VPtr() {}
bool operator!() const
{
return ptr == 0;
}
VPtr<T> operator+(int offset)
{
VPtr<T> ptr(*this);
ptr += offset;
return ptr;
}
const VPtr<T> &operator+=(int offset)
{
ptr += offset;
assert((ptr & (ALPHA_PGBYTES - 1)) + sizeof(T) < ALPHA_PGBYTES);
return *this;
}
const VPtr<T> &operator=(Addr p)
{
assert((p & (ALPHA_PGBYTES - 1)) + sizeof(T) < ALPHA_PGBYTES);
ptr = p;
return *this;
}
template <class U>
const VPtr<T> &operator=(const VPtr<U> &vp)
{
xc = vp.GetXC();
ptr = vp.GetPointer();
return *this;
}
operator T *()
{
void *addr = vtomem(xc, ptr, sizeof(T));
return (T *)addr;
}
T *operator->()
{
void *addr = vtomem(xc, ptr, sizeof(T));
return (T *)addr;
}
T &operator*()
{
void *addr = vtomem(xc, ptr, sizeof(T));
return *(T *)addr;
}
};
#endif // __VPTR_HH__

View file

@ -63,8 +63,9 @@ import yacc
# using the same regexp as generic IDs, but distinguished in the
# t_ID() function. The PLY documentation suggests this approach.
reserved = (
'BITFIELD', 'DECLARE', 'DECODE', 'DEFAULT', 'DEF', 'FORMAT',
'LET', 'NAMESPACE', 'SIGNED', 'TEMPLATE'
'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
'OUTPUT', 'SIGNED', 'TEMPLATE'
)
# List of tokens. The lex module requires this.
@ -195,14 +196,6 @@ lex.lex()
# (by assigning to t[0]).
#####################################################################
# Not sure why, but we get a handful of shift/reduce conflicts on DECLARE.
# By default these get resolved as shifts, which is correct, but
# warnings are printed. Explicitly marking DECLARE as right-associative
# suppresses the warnings.
precedence = (
('right', 'DECLARE'),
)
# The LHS of the first grammar rule is used as the start symbol
# (in this case, 'specification'). Note that this rule enforces
# that there will be exactly one namespace declaration, with 0 or more
@ -210,163 +203,123 @@ precedence = (
# the namespace decl will be outside the namespace; those after
# will be inside. The decoder function is always inside the namespace.
def p_specification(t):
'specification : opt_defs_and_declares name_decl opt_defs_and_declares decode_block'
global_decls1 = t[1]
'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
global_code = t[1]
isa_name = t[2]
namespace = isa_name + "Inst"
global_decls2 = t[3]
(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,
# echo that into the output too
try:
local_rcs_id = rcs_id
# strip $s out of ID so it doesn't get re-substituted
local_rcs_id = re.sub(r'\$', '', local_rcs_id)
except NameError:
local_rcs_id = 'Id: no RCS id found'
output = open(decoder_filename, 'w')
# split string to keep rcs from substituting this file's RCS id in
print >> output, '/* $Id' + '''$ */
/*
* Copyright (c) 2003
* 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!!!
*
* It was automatically generated from this ISA description:
* Filename: %(filename)s
* RCS %(local_rcs_id)s
*/
#include "base/bitfield.hh" // required for bitfield support
/////////////////////////////////////
// Global defs (outside namespace) //
/////////////////////////////////////
%(global_decls1)s
/**
* Namespace for %(isa_name)s static instruction objects.
*/
namespace %(namespace)s
{
/////////////////////////////////////
// Global defs (within namespace) //
/////////////////////////////////////
%(global_decls2)s
////////////////////////////////////
// Declares from inst definitions //
////////////////////////////////////
%(inst_decls)s
%(exec_code)s
} // namespace %(namespace)s
//////////////////////
// Decoder function //
//////////////////////
# wrap the decode block as a function definition
t[4].wrap_decode_block('''
StaticInstPtr<%(isa_name)s>
%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
{
using namespace %(namespace)s;
%(decode_code)s
} // decodeInst
''' % vars()
output.close()
''' % vars(), '}')
# both the latter output blocks and the decode block are in the namespace
namespace_code = t[3] + t[4]
# pass it all back to the caller of yacc.parse()
t[0] = (isa_name, namespace, global_code, namespace_code)
# ISA name declaration looks like "namespace <foo>;"
def p_name_decl(t):
'name_decl : NAMESPACE ID SEMI'
t[0] = t[2]
# 'opt_defs_and_declares' is a possibly empty sequence of
# defs and/or declares.
def p_opt_defs_and_declares_0(t):
'opt_defs_and_declares : empty'
t[0] = ''
# 'opt_defs_and_outputs' is a possibly empty sequence of
# def and/or output statements.
def p_opt_defs_and_outputs_0(t):
'opt_defs_and_outputs : empty'
t[0] = GenCode()
def p_opt_defs_and_declares_1(t):
'opt_defs_and_declares : defs_and_declares'
def p_opt_defs_and_outputs_1(t):
'opt_defs_and_outputs : defs_and_outputs'
t[0] = t[1]
def p_defs_and_declares_0(t):
'defs_and_declares : def_or_declare'
def p_defs_and_outputs_0(t):
'defs_and_outputs : def_or_output'
t[0] = t[1]
def p_defs_and_declares_1(t):
'defs_and_declares : defs_and_declares def_or_declare'
def p_defs_and_outputs_1(t):
'defs_and_outputs : defs_and_outputs def_or_output'
t[0] = t[1] + t[2]
# The list of possible definition/declaration statements.
def p_def_or_declare(t):
'''def_or_declare : def_format
| def_bitfield
| def_template
| global_declare
| global_let
| cpp_directive'''
# The list of possible definition/output statements.
def p_def_or_output(t):
'''def_or_output : def_format
| def_bitfield
| def_template
| def_operand_types
| def_operands
| output_header
| output_decoder
| output_exec
| global_let'''
t[0] = t[1]
# preprocessor directives are copied directly to the output.
def p_cpp_directive(t):
'''cpp_directive : CPPDIRECTIVE'''
t[0] = t[1]
# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
# directly to the appropriate output section.
# Global declares 'declare {{...}}' (C++ code blocks) are copied
# directly to the output.
def p_global_declare(t):
'global_declare : DECLARE CODELIT SEMI'
t[0] = substBitOps(t[2])
# Massage output block by substituting in template definitions and bit
# operators. We handle '%'s embedded in the string that don't
# indicate template substitutions (or CPU-specific symbols, which get
# handled in GenCode) by doubling them first so that the format
# operation will reduce them back to single '%'s.
def process_output(s):
# protect any non-substitution '%'s (not followed by '(')
s = re.sub(r'%(?!\()', '%%', s)
# protects cpu-specific symbols too
s = protect_cpu_symbols(s)
return substBitOps(s % templateMap)
def p_output_header(t):
'output_header : OUTPUT HEADER CODELIT SEMI'
t[0] = GenCode(header_output = process_output(t[3]))
def p_output_decoder(t):
'output_decoder : OUTPUT DECODER CODELIT SEMI'
t[0] = GenCode(decoder_output = process_output(t[3]))
def p_output_exec(t):
'output_exec : OUTPUT EXEC CODELIT SEMI'
t[0] = GenCode(exec_output = process_output(t[3]))
# global let blocks 'let {{...}}' (Python code blocks) are executed
# directly when seen. These are typically used to initialize global
# Python variables used in later format definitions.
# directly when seen. Note that these execute in a special variable
# context 'exportContext' to prevent the code from polluting this
# script's namespace.
def p_global_let(t):
'global_let : LET CODELIT SEMI'
updateExportContext()
try:
exec(fixPythonIndentation(t[2]))
except:
error_bt(t.lineno(1), 'error in global let block "%s".' % t[2])
t[0] = '' # contributes nothing to the output C++ file
exec fixPythonIndentation(t[2]) in exportContext
except Exception, exc:
error(t.lineno(1),
'error: %s in global let block "%s".' % (exc, t[2]))
t[0] = GenCode() # contributes nothing to the output C++ file
# Define the mapping from operand type extensions to C++ types and bit
# widths (stored in operandTypeMap).
def p_def_operand_types(t):
'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
s = 'global operandTypeMap; operandTypeMap = {' + t[3] + '}'
try:
exec s
except Exception, exc:
error(t.lineno(1),
'error: %s in def operand_types block "%s".' % (exc, t[3]))
t[0] = GenCode() # contributes nothing to the output C++ file
# Define the mapping from operand names to operand classes and other
# traits. Stored in operandTraitsMap.
def p_def_operands(t):
'def_operands : DEF OPERANDS CODELIT SEMI'
s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}'
try:
exec s
except Exception, exc:
error(t.lineno(1),
'error: %s in def operands block "%s".' % (exc, t[3]))
defineDerivedOperandVars()
t[0] = GenCode() # contributes nothing to the output C++ file
# A bitfield definition looks like:
# 'def [signed] bitfield <ID> [<first>:<last>]'
@ -376,7 +329,8 @@ def p_def_bitfield_0(t):
expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
if (t[2] == 'signed'):
expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
t[0] = GenCode(header_output = hash_define)
# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
def p_def_bitfield_1(t):
@ -384,7 +338,8 @@ def p_def_bitfield_1(t):
expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
if (t[2] == 'signed'):
expr = 'sext<%d>(%s)' % (1, expr)
t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
t[0] = GenCode(header_output = hash_define)
def p_opt_signed_0(t):
'opt_signed : SIGNED'
@ -399,8 +354,8 @@ templateMap = {}
def p_def_template(t):
'def_template : DEF TEMPLATE ID CODELIT SEMI'
templateMap[t[3]] = t[4]
t[0] = ''
templateMap[t[3]] = Template(t[4])
t[0] = GenCode()
# An instruction format definition looks like
# "def format <fmt>(<params>) {{...}};"
@ -408,12 +363,7 @@ def p_def_format(t):
'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
(id, params, code) = (t[3], t[5], t[7])
defFormat(id, params, code, t.lineno(1))
# insert a comment into the output to note that the def was processed
t[0] = '''
//
// parser: format %s defined
//
''' % id
t[0] = GenCode()
# The formal parameter list for an instruction format is a possibly
# empty list of comma-separated parameters.
@ -453,19 +403,13 @@ 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, decode_code, exec_code, has_default) = t[5]
codeObj = 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_decode, default_exec) = default_defaults
decls += default_decls
decode_code += default_decode
exec_code += default_exec
t[0] = (decls, '''
switch (%s) {
%s
}
''' % (t[2], indent(decode_code)), exec_code)
if not codeObj.has_decode_default:
codeObj += default_defaults
codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
t[0] = codeObj
# The opt_default statement serves only to push the "default defaults"
# onto defaultStack. This value will be used by nested decode blocks,
@ -481,8 +425,9 @@ def p_opt_default_0(t):
def p_opt_default_1(t):
'opt_default : DEFAULT inst'
# push the new default
(decls, decode_code, exec_code) = t[2]
defaultStack.push((decls, '\ndefault:\n%sbreak;' % decode_code, exec_code))
codeObj = t[2]
codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
defaultStack.push(codeObj)
# no meaningful value returned
t[0] = None
@ -492,12 +437,9 @@ def p_decode_stmt_list_0(t):
def p_decode_stmt_list_1(t):
'decode_stmt_list : decode_stmt decode_stmt_list'
(decls1, decode_code1, exec_code1, has_default1) = t[1]
(decls2, decode_code2, exec_code2, has_default2) = t[2]
if (has_default1 and has_default2):
if (t[1].has_decode_default and t[2].has_decode_default):
error(t.lineno(1), 'Two default cases in decode block')
t[0] = (decls1 + '\n' + decls2, decode_code1 + '\n' + decode_code2,
exec_code1 + '\n' + exec_code2, has_default1 or has_default2)
t[0] = t[1] + t[2]
#
# Decode statement rules
@ -510,7 +452,7 @@ def p_decode_stmt_list_1(t):
# Preprocessor directives found in a decode statement list are passed
# through to the output, replicated to both the declaration and decode
# through to the output, replicated to all of the output code
# streams. This works well for ifdefs, so we can ifdef out both the
# declarations and the decode cases generated by an instruction
# definition. Handling them as part of the grammar makes it easy to
@ -518,7 +460,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], t[1], 0)
t[0] = GenCode(t[1], t[1], t[1], t[1])
# A format block 'format <foo> { ... }' sets the default instruction
# format used to handle instruction definitions inside the block.
@ -547,29 +489,31 @@ def p_push_format_id(t):
# specified constant, do a nested decode on some other field.
def p_decode_stmt_decode(t):
'decode_stmt : case_label COLON decode_block'
(label, is_default) = t[1]
(decls, decode_code, exec_code) = t[3]
label = t[1]
codeObj = 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(decode_code)),
exec_code, is_default)
codeObj.wrap_decode_block('\n%s:\n' % label)
codeObj.has_decode_default = (label == 'default')
t[0] = codeObj
# Instruction definition (finally!).
def p_decode_stmt_inst(t):
'decode_stmt : case_label COLON inst SEMI'
(label, is_default) = t[1]
(decls, decode_code, exec_code) = t[3]
t[0] = (decls, '\n%s:%sbreak;' % (label, indent(decode_code)),
exec_code, is_default)
label = t[1]
codeObj = t[3]
codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
codeObj.has_decode_default = (label == 'default')
t[0] = codeObj
# The case label is either a list of one or more constants or 'default'
def p_case_label_0(t):
'case_label : intlit_list'
t[0] = (': '.join(map(lambda a: 'case %#x' % a, t[1])), 0)
t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1]))
def p_case_label_1(t):
'case_label : DEFAULT'
t[0] = ('default', 1)
t[0] = 'default'
#
# The constant list for a decode case label must be non-empty, but may have
@ -591,13 +535,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, decode_code, exec_code) = \
currentFormat.defineInst(t[1], t[3], t.lineno(1))
codeObj = 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 + decode_code, comment + exec_code)
comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
codeObj.prepend_all(comment)
t[0] = codeObj
# Define an instruction using an explicitly specified format:
# "<fmt>::<mnemonic>(<args>)"
@ -607,10 +551,10 @@ def p_inst_1(t):
format = formatMap[t[1]]
except KeyError:
error(t.lineno(1), 'instruction format "%s" not defined.' % t[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 + decode_code, comment + exec_code)
codeObj = format.defineInst(t[3], t[5], t.lineno(1))
comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
codeObj.prepend_all(comment)
t[0] = codeObj
def p_arg_list_0(t):
'arg_list : empty'
@ -652,6 +596,133 @@ def p_error(t):
# Now build the parser.
yacc.yacc()
#####################################################################
#
# Support Classes
#
#####################################################################
################
# CpuModel class
#
# The CpuModel class encapsulates everything we need to know about a
# particular CPU model.
class CpuModel:
# List of all CPU models. Accessible as CpuModel.list.
list = []
# Constructor. Automatically adds models to CpuModel.list.
def __init__(self, name, filename, includes, strings):
self.name = name
self.filename = filename # filename for output exec code
self.includes = includes # include files needed in exec file
# The 'strings' dict holds all the per-CPU symbols we can
# substitute into templates etc.
self.strings = strings
# Add self to list.
CpuModel.list.append(self)
# Define CPU models. The following lines should contain the only
# CPU-model-specific information in this file. Note that the ISA
# description itself should have *no* CPU-model-specific content.
CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
'#include "cpu/simple_cpu/simple_cpu.hh"',
{ 'CPU_exec_context': 'SimpleCPU' })
CpuModel('FullCPU', 'full_cpu_exec.cc',
'#include "cpu/full_cpu/dyn_inst.hh"',
{ 'CPU_exec_context': 'DynInst' })
# Expand template with CPU-specific references into a dictionary with
# an entry for each CPU model name. The entry key is the model name
# and the corresponding value is the template with the CPU-specific
# refs substituted for that model.
def expand_cpu_symbols_to_dict(template):
# Protect '%'s that don't go with CPU-specific terms
t = re.sub(r'%(?!\(CPU_)', '%%', template)
result = {}
for cpu in CpuModel.list:
result[cpu.name] = t % cpu.strings
return result
# *If* the template has CPU-specific references, return a single
# string containing a copy of the template for each CPU model with the
# corresponding values substituted in. If the template has no
# CPU-specific references, it is returned unmodified.
def expand_cpu_symbols_to_string(template):
if template.find('%(CPU_') != -1:
return reduce(lambda x,y: x+y,
expand_cpu_symbols_to_dict(template).values())
else:
return template
# Protect CPU-specific references by doubling the corresponding '%'s
# (in preparation for substituting a different set of references into
# the template).
def protect_cpu_symbols(template):
return re.sub(r'%(?=\(CPU_)', '%%', template)
###############
# GenCode class
#
# The GenCode class encapsulates generated code destined for various
# output files. The header_output and decoder_output attributes are
# strings containing code destined for decoder.hh and decoder.cc
# respectively. The decode_block attribute contains code to be
# incorporated in the decode function itself (that will also end up in
# decoder.cc). The exec_output attribute is a dictionary with a key
# for each CPU model name; the value associated with a particular key
# is the string of code for that CPU model's exec.cc file. The
# has_decode_default attribute is used in the decode block to allow
# explicit default clauses to override default default clauses.
class GenCode:
# Constructor. At this point we substitute out all CPU-specific
# symbols. For the exec output, these go into the per-model
# dictionary. For all other output types they get collapsed into
# a single string.
def __init__(self,
header_output = '', decoder_output = '', exec_output = '',
decode_block = '', has_decode_default = False):
self.header_output = expand_cpu_symbols_to_string(header_output)
self.decoder_output = expand_cpu_symbols_to_string(decoder_output)
if isinstance(exec_output, dict):
self.exec_output = exec_output
elif isinstance(exec_output, str):
# If the exec_output arg is a single string, we replicate
# it for each of the CPU models, substituting and
# %(CPU_foo)s params appropriately.
self.exec_output = expand_cpu_symbols_to_dict(exec_output)
self.decode_block = expand_cpu_symbols_to_string(decode_block)
self.has_decode_default = has_decode_default
# Override '+' operator: generate a new GenCode object that
# concatenates all the individual strings in the operands.
def __add__(self, other):
exec_output = {}
for cpu in CpuModel.list:
n = cpu.name
exec_output[n] = self.exec_output[n] + other.exec_output[n]
return GenCode(self.header_output + other.header_output,
self.decoder_output + other.decoder_output,
exec_output,
self.decode_block + other.decode_block,
self.has_decode_default or other.has_decode_default)
# Prepend a string (typically a comment) to all the strings.
def prepend_all(self, pre):
self.header_output = pre + self.header_output
self.decoder_output = pre + self.decoder_output
self.decode_block = pre + self.decode_block
for cpu in CpuModel.list:
self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
# Wrap the decode block in a pair of strings (e.g., 'case foo:'
# and 'break;'). Used to build the big nested switch statement.
def wrap_decode_block(self, pre, post = ''):
self.decode_block = pre + indent(self.decode_block) + post
################
# Format object.
#
@ -664,24 +735,31 @@ class Format:
# constructor: just save away arguments
self.id = id
self.params = params
# strip blank lines from code (ones at the end are troublesome)
code = re.sub(r'(?m)^\s*$', '', code);
if code == '':
code = ' pass\n'
label = 'def format ' + id
self.user_code = compile(fixPythonIndentation(code), label, 'exec')
param_list = string.join(params, ", ")
f = 'def defInst(name, Name, ' + param_list + '):\n' + code
c = compile(f, 'def format ' + id, 'exec')
exec(c)
f = '''def defInst(_code, _context, %s):
my_locals = vars().copy()
exec _code in _context, my_locals
return my_locals\n''' % param_list
c = compile(f, label + ' wrapper', 'exec')
exec c
self.func = defInst
def defineInst(self, name, args, lineno):
# automatically provide a capitalized version of mnemonic
Name = string.capitalize(name)
context = {}
updateExportContext()
context.update(exportContext)
context.update({ 'name': name, 'Name': string.capitalize(name) })
try:
retval = self.func(name, Name, *args)
except:
error_bt(lineno, 'error defining "%s".' % name)
return retval
vars = self.func(self.user_code, context, *args)
except Exception, exc:
error(lineno, 'error defining "%s": %s.' % (name, exc))
for k in vars.keys():
if k not in ('header_output', 'decoder_output',
'exec_output', 'decode_block'):
del vars[k]
return GenCode(**vars)
# Special null format to catch an implicit-format instruction
# definition outside of any format block.
@ -766,13 +844,13 @@ def fixPythonIndentation(s):
# Error handler. Just call exit. Output formatted to work under
# Emacs compile-mode.
def error(lineno, string):
sys.exit("%s:%d: %s" % (isa_desc_filename, lineno, string))
sys.exit("%s:%d: %s" % (input_filename, 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)
print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string)
sys.exit(1)
@ -817,6 +895,37 @@ def substBitOps(code):
return code
####################
# Template objects.
#
# Template objects are format strings that allow substitution from
# the attribute spaces of other objects (e.g. InstObjParams instances).
class Template:
def __init__(self, t):
self.template = t
def subst(self, d):
# Start with the template namespace. Make a copy since we're
# going to modify it.
myDict = templateMap.copy()
# if the argument is a dictionary, we just use it.
if isinstance(d, dict):
myDict.update(d)
# if the argument is an object, we use its attribute map.
elif hasattr(d, '__dict__'):
myDict.update(d.__dict__)
else:
raise TypeError, "Template.subst() arg must be or have dictionary"
# CPU-model-specific substitutions are handled later (in GenCode).
return protect_cpu_symbols(self.template) % myDict
# Convert to string. This handles the case when a template with a
# CPU-specific term gets interpolated into another template or into
# an output block.
def __str__(self):
return expand_cpu_symbols_to_string(self.template)
#####################################################################
#
# Code Parser
@ -1111,6 +1220,22 @@ class NPCOperandTraits(OperandTraits):
return 'xc->setNextPC(%s);\n' % op_desc.munged_name
exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
'ControlRegOperandTraits', 'MemOperandTraits',
'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
're', 'string')
exportContext = {}
def updateExportContext():
exportContext.update(exportDict(*exportContextSymbols))
exportContext.update(templateMap)
def exportDict(*symNames):
return dict([(s, eval(s)) for s in symNames])
#
# Define operand variables that get derived from the basic declaration
# of ISA-specific operands in operandTraitsMap. This function must be
@ -1385,10 +1510,6 @@ 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))
@ -1419,48 +1540,125 @@ 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
#######################
#
# Output file template
#
def subst(self, *args):
result = []
for t in args:
try: template = templateMap[t]
except KeyError:
error(0, 'InstObjParams::subst: undefined template "%s"' % t)
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
file_template = '''
/*
* Copyright (c) 2003
* 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!!!
*
* It was automatically generated from the ISA description in %(filename)s
*/
%(includes)s
%(global_output)s
namespace %(namespace)s {
%(namespace_output)s
} // namespace %(namespace)s
'''
# Update the output file only if the new contents are different from
# the current contents. Minimizes the files that need to be rebuilt
# after minor changes.
def update_if_needed(file, contents):
update = False
if os.access(file, os.R_OK):
f = open(file, 'r')
old_contents = f.read()
f.close()
if contents != old_contents:
print 'Updating', file
os.remove(file) # in case it's write-protected
update = True
else:
print 'File', file, 'is unchanged'
else:
print 'Generating', file
update = True
if update:
f = open(file, 'w')
f.write(contents)
f.close()
#
# Read in and parse the ISA description.
#
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
def parse_isa_desc(isa_desc_file, output_dir, include_path):
# set a global var for the input filename... used in error messages
global input_filename
input_filename = isa_desc_file
# Suck the ISA description file in.
input = open(isa_desc_filename)
input = open(isa_desc_file)
isa_desc = input.read()
input.close()
# Parse it.
yacc.parse(isa_desc)
(isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc)
# grab the last three path components of isa_desc_file to put in
# the output
filename = '/'.join(isa_desc_file.split('/')[-3:])
# generate decoder.hh
includes = '#include "base/bitfield.hh" // for bitfield support'
global_output = global_code.header_output
namespace_output = namespace_code.header_output
update_if_needed(output_dir + '/decoder.hh', file_template % vars())
# generate decoder.cc
includes = '#include "%s/decoder.hh"' % include_path
global_output = global_code.decoder_output
namespace_output = namespace_code.decoder_output
namespace_output += namespace_code.decode_block
update_if_needed(output_dir + '/decoder.cc', file_template % vars())
# generate per-cpu exec files
for cpu in CpuModel.list:
includes = '#include "%s/decoder.hh"\n' % include_path
includes += cpu.includes
global_output = global_code.exec_output[cpu.name]
namespace_output = namespace_code.exec_output[cpu.name]
update_if_needed(output_dir + '/' + cpu.filename,
file_template % vars())
# Called as script: get args from command line.
if __name__ == '__main__':
parse_isa_desc(sys.argv[1], sys.argv[2])
parse_isa_desc(sys.argv[1], sys.argv[2], sys.argv[3])

View file

@ -139,11 +139,13 @@ struct StatData
static bool less(StatData *stat1, StatData *stat2);
};
struct ScalarData : public StatData
class ScalarData : public StatData
{
public:
virtual Counter value() const = 0;
virtual Result result() const = 0;
virtual Result total() const = 0;
virtual void visit(Visit &visitor) { visitor.visit(*this); }
};
template <class Stat>
@ -162,8 +164,6 @@ class ScalarStatData : public ScalarData
virtual Result total() const { return s.total(); }
virtual void reset() { s.reset(); }
virtual bool zero() const { return s.zero(); }
virtual void visit(Visit &visitor) { visitor.visit(*this); }
};
struct VectorData : public StatData
@ -394,6 +394,16 @@ class Wrap : public Child
return ptr;
}
protected:
/**
* Copy constructor, copies are not allowed.
*/
Wrap(const Wrap &stat);
/**
* Can't copy stats.
*/
void operator=(const Wrap &);
public:
Wrap()
{
@ -726,16 +736,6 @@ class ScalarBase : public DataAccess
return _bin->data(*_params);
}
protected:
/**
* Copy constructor, copies are not allowed.
*/
ScalarBase(const ScalarBase &stat);
/**
* Can't copy stats.
*/
const ScalarBase &operator=(const ScalarBase &);
public:
/**
* Return the current value of this stat as its base type.
@ -822,6 +822,79 @@ class ScalarBase : public DataAccess
};
class ProxyData : public ScalarData
{
public:
virtual void visit(Visit &visitor) { visitor.visit(*this); }
virtual bool binned() const { return false; }
virtual std::string str() const { return to_string(value()); }
virtual size_t size() const { return 1; }
virtual bool zero() const { return value() == 0; }
virtual bool check() const { return true; }
virtual void reset() { }
};
template <class T>
class ValueProxy : public ProxyData
{
private:
T *scalar;
public:
ValueProxy(T &val) : scalar(&val) {}
virtual Counter value() const { return *scalar; }
virtual Result result() const { return *scalar; }
virtual Result total() const { return *scalar; }
};
template <class T>
class FunctorProxy : public ProxyData
{
private:
T *functor;
public:
FunctorProxy(T &func) : functor(&func) {}
virtual Counter value() const { return (*functor)(); }
virtual Result result() const { return (*functor)(); }
virtual Result total() const { return (*functor)(); }
};
class ValueBase : public DataAccess
{
private:
ProxyData *proxy;
public:
ValueBase() : proxy(NULL) { }
~ValueBase() { if (proxy) delete proxy; }
template <class T>
void scalar(T &value)
{
proxy = new ValueProxy<T>(value);
setInit();
}
template <class T>
void functor(T &func)
{
proxy = new FunctorProxy<T>(func);
setInit();
}
Counter value() { return proxy->value(); }
Result result() const { return proxy->result(); }
Result total() const { return proxy->total(); };
size_t size() const { return proxy->size(); }
bool binned() const { return proxy->binned(); }
std::string str() const { return proxy->str(); }
bool zero() const { return proxy->zero(); }
bool check() const { return proxy != NULL; }
void reset() { }
};
//////////////////////////////////////////////////////////////////////
//
// Vector Statistics
@ -869,13 +942,6 @@ class VectorBase : public DataAccess
return _bin->data(index, *_params);
}
protected:
// Copying stats is not allowed
/** Copying stats isn't allowed. */
VectorBase(const VectorBase &stat);
/** Copying stats isn't allowed. */
const VectorBase &operator=(const VectorBase &);
public:
void value(VCounter &vec) const
{
@ -1127,11 +1193,6 @@ class Vector2dBase : public DataAccess
return _bin->data(index, *_params);
}
protected:
// Copying stats is not allowed
Vector2dBase(const Vector2dBase &stat);
const Vector2dBase &operator=(const Vector2dBase &);
public:
Vector2dBase() {}
@ -1586,13 +1647,6 @@ class DistBase : public DataAccess
return _bin->data(*_params);
}
protected:
// Copying stats is not allowed
/** Copies are not allowed. */
DistBase(const DistBase &stat);
/** Copies are not allowed. */
const DistBase &operator=(const DistBase &);
public:
DistBase() { }
@ -1659,11 +1713,6 @@ class VectorDistBase : public DataAccess
return _bin->data(index, *_params);
}
protected:
// Copying stats is not allowed
VectorDistBase(const VectorDistBase &stat);
const VectorDistBase &operator=(const VectorDistBase &);
public:
VectorDistBase() {}
@ -1910,56 +1959,6 @@ class ConstNode : public Node
virtual std::string str() const { return to_string(vresult[0]); }
};
template <class T>
class FunctorNode : public Node
{
private:
T &functor;
mutable VResult vresult;
public:
FunctorNode(T &f) : functor(f) { vresult.resize(1); }
const VResult &result() const
{
vresult[0] = (Result)functor();
return vresult;
}
virtual Result total() const { return (Result)functor(); };
virtual size_t size() const { return 1; }
/**
* Return true if stat is binned.
*@return False since Functors aren't binned
*/
virtual bool binned() const { return false; }
virtual std::string str() const { return to_string(functor()); }
};
template <class T>
class ScalarNode : public Node
{
private:
T &scalar;
mutable VResult vresult;
public:
ScalarNode(T &s) : scalar(s) { vresult.resize(1); }
const VResult &result() const
{
vresult[0] = (Result)scalar;
return vresult;
}
virtual Result total() const { return (Result)scalar; };
virtual size_t size() const { return 1; }
/**
* Return true if stat is binned.
*@return False since Scalar's aren't binned
*/
virtual bool binned() const { return false; }
virtual std::string str() const { return to_string(scalar); }
};
template <class Op>
struct OpString;
@ -2219,6 +2218,30 @@ class Scalar
void operator=(const U &v) { Base::operator=(v); }
};
class Value
: public Wrap<Value,
ValueBase,
ScalarStatData>
{
public:
/** The base implementation. */
typedef ValueBase Base;
template <class T>
Value &scalar(T &value)
{
Base::scalar(value);
return *this;
}
template <class T>
Value &functor(T &func)
{
Base::functor(func);
return *this;
}
};
/**
* A stat that calculates the per cycle average of a value.
* @sa Stat, ScalarBase, AvgStor
@ -2694,6 +2717,13 @@ class Temp
Temp(const Scalar<Bin> &s)
: node(new ScalarStatNode(s.statData())) { }
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
Temp(const Value &s)
: node(new ScalarStatNode(s.statData())) { }
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
@ -2861,20 +2891,6 @@ constant(T val)
return NodePtr(new ConstNode<T>(val));
}
template <typename T>
inline Temp
functor(T &val)
{
return NodePtr(new FunctorNode<T>(val));
}
template <typename T>
inline Temp
scalar(T &val)
{
return NodePtr(new ScalarNode<T>(val));
}
inline Temp
sum(Temp val)
{

View file

@ -132,7 +132,7 @@ Text::output()
for (i = bins().begin(); i != end; ++i) {
MainBin *bin = *i;
bin->activate();
ccprintf(*stream,"---%s Bin------------\n", bin);
ccprintf(*stream,"---%s Bin------------\n", bin->name());
stat_list_t::const_iterator i, end = stats().end();
for (i = stats().begin(); i != end; ++i)
(*i)->visit(*this);

View file

@ -130,6 +130,13 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
void
BaseCPU::regStats()
{
using namespace Statistics;
numCycles
.name(name() + ".numCycles")
.desc("number of cpu cycles simulated")
;
int size = execContexts.size();
if (size > 1) {
for (int i = 0; i < size; ++i) {

View file

@ -31,10 +31,10 @@
#include <vector>
#include "base/statistics.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "targetarch/isa_traits.hh" // for Addr
#include "targetarch/isa_traits.hh"
#ifdef FULL_SYSTEM
class System;
@ -147,11 +147,27 @@ class BaseCPU : public SimObject
*/
virtual BranchPred *getBranchPred() { return NULL; };
virtual Counter totalInstructions() const { return 0; }
private:
static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
public:
static int numSimulatedCPUs() { return cpuList.size(); }
static Counter numSimulatedInstructions()
{
Counter total = 0;
int size = cpuList.size();
for (int i = 0; i < size; ++i)
total += cpuList[i]->totalInstructions();
return total;
}
public:
// Number of CPU cycles simulated
Statistics::Scalar<> numCycles;
};
#endif // __BASE_CPU_HH__

View file

@ -50,7 +50,6 @@
#include "cpu/static_inst.hh"
#include "mem/base_mem.hh"
#include "mem/mem_interface.hh"
#include "sim/annotation.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
@ -287,8 +286,6 @@ SimpleCPU::regStats()
;
idleFraction = constant(1.0) - notIdleFraction;
numInsts = Statistics::scalar(numInst) - Statistics::scalar(startNumInst);
simInsts += numInsts;
}
void
@ -581,7 +578,6 @@ SimpleCPU::post_interrupt(int int_num, int index)
if (xc->status() == ExecContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
xc->activate();
Annotate::Resume(xc);
}
}
#endif // FULL_SYSTEM
@ -590,6 +586,8 @@ SimpleCPU::post_interrupt(int int_num, int index)
void
SimpleCPU::tick()
{
numCycles++;
traceData = NULL;
Fault fault = No_Fault;
@ -697,6 +695,7 @@ SimpleCPU::tick()
// keep an instruction count
numInst++;
numInsts++;
// check for instruction-count-based events
comInstEventQueue[0]->serviceEvents(numInst);

View file

@ -34,7 +34,7 @@
#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
#include "base/statistics.hh"
#include "cpu/exec_context.hh"
// forward declarations
#ifdef FULL_SYSTEM
@ -46,6 +46,11 @@ class PhysicalMemory;
class RemoteGDB;
class GDBListener;
#else
class Process;
#endif // FULL_SYSTEM
class MemInterface;
@ -204,7 +209,12 @@ class SimpleCPU : public BaseCPU
// number of simulated instructions
Counter numInst;
Counter startNumInst;
Statistics::Formula numInsts;
Statistics::Scalar<> numInsts;
virtual Counter totalInstructions() const
{
return numInst - startNumInst;
}
// number of simulated memory references
Statistics::Scalar<> numMemRefs;
@ -300,6 +310,4 @@ class SimpleCPU : public BaseCPU
ExecContext *xcBase() { return xc; }
};
typedef SimpleCPU SimpleCPUExecContext;
#endif // __SIMPLE_CPU_HH__

View file

@ -42,9 +42,7 @@
// forward declarations
class ExecContext;
class DynInst;
typedef DynInst FullCPUExecContext;
class SimpleCPU;
typedef SimpleCPU SimpleCPUExecContext;
class SymbolTable;
namespace Trace {
@ -249,7 +247,8 @@ class StaticInst : public StaticInstBase
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the EA computation.
*/
virtual StaticInstPtr<ISA> eaCompInst() { return nullStaticInstPtr; }
virtual const
StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
/**
* Memory references only: returns "fake" instruction representing
@ -257,7 +256,8 @@ class StaticInst : public StaticInstBase
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the memory access (not the EA computation).
*/
virtual StaticInstPtr<ISA> memAccInst() { return nullStaticInstPtr; }
virtual const
StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
/// The binary machine instruction.
const MachInst machInst;
@ -307,14 +307,12 @@ class StaticInst : public StaticInstBase
/**
* Execute this instruction under SimpleCPU model.
*/
virtual Fault execute(SimpleCPUExecContext *xc,
Trace::InstRecord *traceData) = 0;
virtual Fault execute(SimpleCPU *xc, Trace::InstRecord *traceData) = 0;
/**
* Execute this instruction under detailed FullCPU model.
*/
virtual Fault execute(FullCPUExecContext *xc,
Trace::InstRecord *traceData) = 0;
virtual Fault execute(DynInst *xc, Trace::InstRecord *traceData) = 0;
/**
* Return the target address for a PC-relative branch.

109
kern/system_events.cc Normal file
View file

@ -0,0 +1,109 @@
/*
* 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.
*/
#include "cpu/exec_context.hh"
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/bpred.hh"
#include "cpu/full_cpu/full_cpu.hh"
#include "kern/system_events.hh"
#include "sim/system.hh"
#include "sim/sw_context.hh"
void
SkipFuncEvent::process(ExecContext *xc)
{
Addr newpc = xc->regs.intRegFile[ReturnAddressReg];
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
xc->regs.pc, newpc);
xc->regs.pc = newpc;
xc->regs.npc = xc->regs.pc + sizeof(MachInst);
BranchPred *bp = xc->cpu->getBranchPred();
if (bp != NULL) {
bp->popRAS(xc->thread_num);
}
}
FnEvent::FnEvent(PCEventQueue *q, const std::string & desc, System *system)
: PCEvent(q, desc), _name(desc)
{
myBin = system->getBin(desc);
assert(myBin);
}
void
FnEvent::process(ExecContext *xc)
{
if (xc->misspeculating())
return;
assert(xc->system->bin && "FnEvent must be in a binned system");
SWContext *ctx = xc->swCtx;
DPRINTF(TCPIP, "%s: %s Event!!!\n", xc->system->name(), description);
if (ctx && !ctx->callStack.empty()) {
DPRINTF(TCPIP, "already a callstack!\n");
fnCall *last = ctx->callStack.top();
if (last->name == "idle_thread")
ctx->calls++;
if (!xc->system->findCaller(myname(), "" ) &&
!xc->system->findCaller(myname(), last->name)) {
DPRINTF(TCPIP, "but can't find parent %s\n", last->name);
return;
}
ctx->calls--;
//assert(!ctx->calls && "on a binned fn, calls should == 0 (but can happen in boot)");
} else {
DPRINTF(TCPIP, "no callstack yet\n");
if (!xc->system->findCaller(myname(), "")) {
DPRINTF(TCPIP, "not the right function, returning\n");
return;
}
if (!ctx) {
DPRINTF(TCPIP, "creating new context for %s\n", myname());
ctx = new SWContext;
xc->swCtx = ctx;
}
}
DPRINTF(TCPIP, "adding fn %s to context\n", myname());
fnCall *call = new fnCall;
call->myBin = myBin;
call->name = myname();
ctx->callStack.push(call);
myBin->activate();
xc->system->fnCalls++;
DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
xc->system->fnCalls.value());
xc->system->dumpState(xc);
}

56
kern/system_events.hh Normal file
View file

@ -0,0 +1,56 @@
/*
* 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 __SYSTEM_EVENTS_HH__
#define __SYSTEM_EVENTS_HH__
#include "cpu/pc_event.hh"
class System;
class SkipFuncEvent : public PCEvent
{
public:
SkipFuncEvent(PCEventQueue *q, const std::string &desc)
: PCEvent(q, desc) {}
virtual void process(ExecContext *xc);
};
class FnEvent : public PCEvent
{
public:
FnEvent(PCEventQueue *q, const std::string &desc, System *system);
virtual void process(ExecContext *xc);
std::string myname() const { return _name; }
private:
std::string _name;
Statistics::MainBin *myBin;
};
#endif // __SYSTEM_EVENTS_HH__

View file

@ -32,6 +32,8 @@
#include "sim/host.hh"
#include "targetarch/isa_traits.hh"
namespace tru64 {
struct m_hdr {
Addr mh_next; // 0x00
Addr mh_nextpkt; // 0x08
@ -91,4 +93,6 @@ struct mbuf {
#define m_pktdat M_dat.MH.MH_dat.MH_databuf
#define m_dat M_dat.M_databuf
}
#endif // __MBUF_HH__

View file

@ -28,32 +28,14 @@
#include "cpu/exec_context.hh"
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/bpred.hh"
#include "cpu/full_cpu/full_cpu.hh"
#include "kern/system_events.hh"
#include "kern/tru64/tru64_events.hh"
#include "kern/tru64/dump_mbuf.hh"
#include "kern/tru64/printf.hh"
#include "kern/tru64/tru64_events.hh"
#include "mem/functional_mem/memory_control.hh"
#include "targetarch/arguments.hh"
#include "sim/system.hh"
#include "sim/sw_context.hh"
#include "mem/functional_mem/memory_control.hh"
void
SkipFuncEvent::process(ExecContext *xc)
{
Addr newpc = xc->regs.intRegFile[ReturnAddressReg];
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
xc->regs.pc, newpc);
xc->regs.pc = newpc;
xc->regs.npc = xc->regs.pc + sizeof(MachInst);
BranchPred *bp = xc->cpu->getBranchPred();
if (bp != NULL) {
bp->popRAS(xc->thread_num);
}
}
//void SkipFuncEvent::process(ExecContext *xc);
void
BadAddrEvent::process(ExecContext *xc)
@ -106,59 +88,3 @@ DumpMbufEvent::process(ExecContext *xc)
tru64::DumpMbuf(args);
}
}
FnEvent::FnEvent(PCEventQueue *q, const std::string & desc, System *system)
: PCEvent(q, desc), _name(desc)
{
myBin = system->getBin(desc);
assert(myBin);
}
void
FnEvent::process(ExecContext *xc)
{
if (xc->misspeculating())
return;
assert(xc->system->bin && "FnEvent must be in a binned system");
SWContext *ctx = xc->swCtx;
DPRINTF(TCPIP, "%s: %s Event!!!\n", xc->system->name(), description);
if (ctx && !ctx->callStack.empty()) {
DPRINTF(TCPIP, "already a callstack!\n");
fnCall *last = ctx->callStack.top();
if (last->name == "idle_thread")
ctx->calls++;
if (!xc->system->findCaller(myname(), "" ) &&
!xc->system->findCaller(myname(), last->name)) {
DPRINTF(TCPIP, "but can't find parent %s\n", last->name);
return;
}
ctx->calls--;
//assert(!ctx->calls && "on a binned fn, calls should == 0 (but can happen in boot)");
} else {
DPRINTF(TCPIP, "no callstack yet\n");
if (!xc->system->findCaller(myname(), "")) {
DPRINTF(TCPIP, "not the right function, returning\n");
return;
}
if (!ctx) {
DPRINTF(TCPIP, "creating new context for %s\n", myname());
ctx = new SWContext;
xc->swCtx = ctx;
}
}
DPRINTF(TCPIP, "adding fn %s to context\n", myname());
fnCall *call = new fnCall;
call->myBin = myBin;
call->name = myname();
ctx->callStack.push(call);
myBin->activate();
xc->system->fnCalls++;
DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
xc->system->fnCalls.value());
xc->system->dumpState(xc);
}

View file

@ -32,19 +32,10 @@
#include <string>
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
class ExecContext;
class System;
class SkipFuncEvent : public PCEvent
{
public:
SkipFuncEvent(PCEventQueue *q, const std::string &desc)
: PCEvent(q, desc) {}
virtual void process(ExecContext *xc);
};
class BadAddrEvent : public SkipFuncEvent
{
public:
@ -80,15 +71,4 @@ class DumpMbufEvent : public PCEvent
virtual void process(ExecContext *xc);
};
class FnEvent : public PCEvent
{
public:
FnEvent(PCEventQueue *q, const std::string &desc, System *system);
virtual void process(ExecContext *xc);
std::string myname() const { return _name; }
private:
std::string _name;
Statistics::MainBin *myBin;
};
#endif // __TRU64_EVENTS_HH__

View file

@ -35,6 +35,7 @@
#include "cpu/exec_context.hh"
#include "kern/tru64/tru64_events.hh"
#include "kern/tru64/tru64_system.hh"
#include "kern/system_events.hh"
#include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh"
@ -48,7 +49,7 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
const string &kernel_path, const string &console_path,
const string &palcode, const string &boot_osflags,
const bool _bin, const vector<string> &binned_fns)
: System(_name, _init_param, _memCtrl, _physmem, _bin),
: System(_name, _init_param, _memCtrl, _physmem, _bin, binned_fns),
bin(_bin), binned_fns(binned_fns)
{
kernelSymtab = new SymbolTable;
@ -176,33 +177,14 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
// BINNING STUFF
if (bin == true) {
int end = binned_fns.size();
assert(!(end & 1));
Statistics::MainBin *Bin;
Addr address = 0;
fnEvents.resize(end>>1);
for (int i = 0; i < end; i +=2) {
Bin = new Statistics::MainBin(binned_fns[i]);
fnBins.insert(make_pair(binned_fns[i], Bin));
fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
if (kernelSymtab->findAddress(binned_fns[i], address))
fnEvents[(i>>1)]->schedule(address);
else
panic("could not find kernel symbol %s\n", binned_fns[i]);
if (binned_fns[i+1] == "null")
populateMap(binned_fns[i], "");
else
populateMap(binned_fns[i], binned_fns[i+1]);
}
fnCalls
.name(name() + ":fnCalls")
.desc("all fn calls being tracked")
;
}
//
}
@ -226,14 +208,6 @@ Tru64System::~Tru64System()
delete debugPrintfEvent;
delete debugPrintfrEvent;
delete dumpMbufEvent;
if (bin == true) {
int end = fnEvents.size();
for (int i = 0; i < end; ++i) {
delete fnEvents[i];
}
fnEvents.clear();
}
}
int
@ -274,45 +248,6 @@ Tru64System::breakpoint()
return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
}
void
Tru64System::populateMap(std::string callee, std::string caller)
{
multimap<const string, string>::const_iterator i;
i = callerMap.insert(make_pair(callee, caller));
assert(i != callerMap.end() && "should not fail populating callerMap");
}
bool
Tru64System::findCaller(std::string callee, std::string caller) const
{
typedef multimap<const std::string, std::string>::const_iterator iter;
pair<iter, iter> range;
range = callerMap.equal_range(callee);
for (iter i = range.first; i != range.second; ++i) {
if ((*i).second == caller)
return true;
}
return false;
}
void
Tru64System::dumpState(ExecContext *xc) const
{
if (xc->swCtx) {
stack<fnCall *> copy(xc->swCtx->callStack);
if (copy.empty())
return;
DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size());
fnCall *top;
DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls);
for (top = copy.top(); !copy.empty(); copy.pop() ) {
top = copy.top();
DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name());
}
}
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
Param<bool> bin;

View file

@ -67,8 +67,6 @@ class Tru64System : public System
DebugPrintfEvent *debugPrintfrEvent;
DumpMbufEvent *dumpMbufEvent;
std::vector<FnEvent *> fnEvents;
private:
Addr kernelStart;
@ -104,17 +102,6 @@ class Tru64System : public System
static void Printf(AlphaArguments args);
static void DumpMbuf(AlphaArguments args);
// Lisa's binning stuff
private:
std::multimap<const std::string, std::string> callerMap;
void populateMap(std::string caller, std::string callee);
public:
bool findCaller(std::string callee, std::string caller) const;
void dumpState(ExecContext *xc) const;
//
};
#endif // __TRU64_SYSTEM_HH__

View file

@ -40,11 +40,13 @@
using namespace std;
#ifdef DEBUG
void
debug_break()
{
kill(getpid(), SIGTRAP);
}
#endif
//
// Debug event: place a breakpoint on the process function and

View file

@ -29,6 +29,10 @@
#ifndef __DEBUG_HH__
#define __DEBUG_HH__
#ifdef DEBUG
void debug_break();
#else
inline void debug_break() { }
#endif
#endif // __DEBUG_HH__

View file

@ -39,6 +39,7 @@
#include "base/str.hh"
#include "base/time.hh"
#include "base/stats/output.hh"
#include "cpu/base_cpu.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "sim/stat_control.hh"
@ -47,13 +48,14 @@
using namespace std;
Statistics::Formula hostInstRate;
Statistics::Formula hostMemory;
Statistics::Formula hostSeconds;
Statistics::Formula hostTickRate;
Statistics::Value hostMemory;
Statistics::Value hostSeconds;
Statistics::Formula simInsts;
Statistics::Value simTicks;
Statistics::Value simInsts;
Statistics::Value simFreq;
Statistics::Formula simSeconds;
Statistics::Formula simTicks;
namespace Statistics {
@ -84,6 +86,7 @@ void
InitSimStats()
{
simInsts
.functor(BaseCPU::numSimulatedInstructions)
.name("sim_insts")
.desc("Number of instructions simulated")
.precision(0)
@ -95,7 +98,14 @@ InitSimStats()
.desc("Number of seconds simulated")
;
simFreq
.scalar(ticksPerSecond)
.name("sim_freq")
.desc("Frequency of simulated ticks")
;
simTicks
.scalar(curTick)
.name("sim_ticks")
.desc("Number of ticks simulated")
;
@ -108,12 +118,14 @@ InitSimStats()
;
hostMemory
.functor(memUsage)
.name("host_mem_usage")
.desc("Number of bytes of host memory used")
.prereq(hostMemory)
;
hostSeconds
.functor(statElapsedTime)
.name("host_seconds")
.desc("Real time elapsed on the host")
.precision(2)
@ -125,11 +137,7 @@ InitSimStats()
.precision(0)
;
simInsts = constant(0);
simTicks = scalar(curTick) - scalar(startTick);
simSeconds = simTicks / scalar(ticksPerSecond);
hostMemory = functor(memUsage);
hostSeconds = functor(statElapsedTime);
simSeconds = simTicks / simFreq;
hostInstRate = simInsts / hostSeconds;
hostTickRate = simTicks / hostSeconds;

View file

@ -31,11 +31,7 @@
#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;
extern Statistics::Value simTicks;
#endif // __SIM_SIM_STATS_HH__

View file

@ -30,6 +30,7 @@
#include "targetarch/vtophys.hh"
#include "sim/param.hh"
#include "sim/system.hh"
#include "base/trace.hh"
using namespace std;
@ -41,12 +42,15 @@ System::System(const std::string _name,
const uint64_t _init_param,
MemoryController *_memCtrl,
PhysicalMemory *_physmem,
const bool _bin)
const bool _bin,
const std::vector<string> &binned_fns)
: SimObject(_name),
init_param(_init_param),
memCtrl(_memCtrl),
physmem(_physmem),
bin(_bin)
bin(_bin),
binned_fns(binned_fns)
{
// add self to global system list
systemList.push_back(this);
@ -54,6 +58,31 @@ System::System(const std::string _name,
Kernel = new Statistics::MainBin("non TCPIP Kernel stats");
Kernel->activate();
User = new Statistics::MainBin("User stats");
int end = binned_fns.size();
assert(!(end & 1));
Statistics::MainBin *Bin;
fnEvents.resize(end>>1);
for (int i = 0; i < end; i +=2) {
Bin = new Statistics::MainBin(binned_fns[i]);
fnBins.insert(make_pair(binned_fns[i], Bin));
fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
if (binned_fns[i+1] == "null")
populateMap(binned_fns[i], "");
else
populateMap(binned_fns[i], binned_fns[i+1]);
}
fnCalls
.name(name() + ":fnCalls")
.desc("all fn calls being tracked")
;
} else
Kernel = NULL;
}
@ -61,6 +90,13 @@ System::System(const std::string _name,
System::~System()
{
if (bin == true) {
int end = fnEvents.size();
for (int i = 0; i < end; ++i) {
delete fnEvents[i];
}
fnEvents.clear();
}
}
@ -103,6 +139,45 @@ printSystems()
System::printSystems();
}
void
System::populateMap(std::string callee, std::string caller)
{
multimap<const string, string>::const_iterator i;
i = callerMap.insert(make_pair(callee, caller));
assert(i != callerMap.end() && "should not fail populating callerMap");
}
bool
System::findCaller(std::string callee, std::string caller) const
{
typedef multimap<const std::string, std::string>::const_iterator iter;
pair<iter, iter> range;
range = callerMap.equal_range(callee);
for (iter i = range.first; i != range.second; ++i) {
if ((*i).second == caller)
return true;
}
return false;
}
void
System::dumpState(ExecContext *xc) const
{
if (xc->swCtx) {
stack<fnCall *> copy(xc->swCtx->callStack);
if (copy.empty())
return;
DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size());
fnCall *top;
DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls);
for (top = copy.top(); !copy.empty(); copy.pop() ) {
top = copy.top();
DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name());
}
}
}
Statistics::MainBin *
System::getBin(const std::string &name)
{

View file

@ -35,6 +35,7 @@
#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
#include "sim/sim_object.hh"
#include "sim/sw_context.hh"
@ -49,17 +50,20 @@ class ExecContext;
class System : public SimObject
{
// lisa's binning stuff
protected:
private:
std::map<const std::string, Statistics::MainBin *> fnBins;
std::map<const Addr, SWContext *> swCtxMap;
protected:
std::vector<FnEvent *> fnEvents;
public:
Statistics::Scalar<> fnCalls;
Statistics::MainBin *Kernel;
Statistics::MainBin *User;
Statistics::MainBin * getBin(const std::string &name);
virtual bool findCaller(std::string, std::string) const = 0;
bool findCaller(std::string, std::string) const;
SWContext *findContext(Addr pcb);
bool addContext(Addr pcb, SWContext *ctx) {
@ -69,12 +73,16 @@ class System : public SimObject
swCtxMap.erase(pcb);
return;
}
virtual void dumpState(ExecContext *xc) const = 0;
void dumpState(ExecContext *xc) const;
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
//
private:
std::multimap<const std::string, std::string> callerMap;
void populateMap(std::string caller, std::string callee);
//
public:
const uint64_t init_param;
@ -82,6 +90,7 @@ class System : public SimObject
PhysicalMemory *physmem;
Platform *platform;
bool bin;
std::vector<string> binned_fns;
PCEventQueue pcEventQueue;
@ -92,7 +101,8 @@ class System : public SimObject
public:
System(const std::string _name, const uint64_t _init_param,
MemoryController *, PhysicalMemory *, const bool);
MemoryController *, PhysicalMemory *, const bool,
const std::vector<string> &binned_fns);
~System();
virtual Addr getKernelStart() const = 0;

View file

@ -2,18 +2,24 @@
CC?= gcc
CXX?= g++
PYTHON?=/usr/bin/env python
CURDIR?= $(shell /bin/pwd)
SRCDIR?= ..
SRCDIR?= $(CURDIR)/..
CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0
MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
VPATH=$(SRCDIR)
VPATH=$(SRCDIR):$(CURDIR)
default:
@echo "You must specify a target"
base/traceflags.cc base/traceflags.hh: $(SRCDIR)/base/traceflags.py
mkdir -p base; \
cd base; \
$(PYTHON) $<
bitvectest: test/bitvectest.cc
$(CXX) $(CCFLAGS) -o $@ $^
@ -61,5 +67,5 @@ tracetest: $(TRACE)
$(CXX) $(CCFLAGS) -o $@ $^
clean:
@rm -f *test *~ .#* *.core core
@rm -rf *test *~ .#* *.core core base
.PHONY: clean

View file

@ -66,8 +66,8 @@ Vector2d<> s16;
Formula f1;
Formula f2;
Formula f3;
Formula f4;
Formula f5;
Value f4;
Value f5;
Formula f6;
Formula f7;
@ -279,11 +279,14 @@ main(int argc, char *argv[])
;
f4
.functor(testfunc)
.name("Formula4")
.desc("this is formula 4")
;
TestClass testclass;
f5
.functor(testclass)
.name("Formula5")
.desc("this is formula 5")
;
@ -296,9 +299,6 @@ main(int argc, char *argv[])
f1 = s1 + s2;
f2 = (-s1) / (-s2) * (-s3 + ULL(100) + s4);
f3 = sum(s5) * s7;
f4 = functor(testfunc);
TestClass testclass;
f5 = functor(testclass);
f6 += constant(10.0);
f6 += s5[3];
f7 = constant(1);