summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/alpha_memory.hh32
-rw-r--r--arch/alpha/ev5.cc27
-rw-r--r--arch/alpha/isa_desc1547
-rw-r--r--arch/alpha/pseudo_inst.cc27
-rw-r--r--arch/alpha/pseudo_inst.hh3
-rw-r--r--arch/alpha/vptr.hh113
-rwxr-xr-xarch/isa_parser.py690
-rw-r--r--base/hybrid_pred.cc4
-rw-r--r--base/hybrid_pred.hh32
-rw-r--r--base/sat_counter.cc4
-rw-r--r--base/sat_counter.hh36
-rw-r--r--base/statistics.cc4
-rw-r--r--base/statistics.hh222
-rw-r--r--base/stats/events.cc105
-rw-r--r--base/stats/events.hh63
-rw-r--r--base/stats/flags.hh4
-rw-r--r--base/stats/mysql.cc213
-rw-r--r--base/stats/mysql.hh48
-rw-r--r--base/stats/mysql_run.hh63
-rw-r--r--base/stats/output.hh4
-rw-r--r--base/stats/statdb.cc4
-rw-r--r--base/stats/statdb.hh4
-rw-r--r--base/stats/text.cc12
-rw-r--r--base/stats/text.hh4
-rw-r--r--base/stats/types.hh4
-rw-r--r--base/stats/visit.cc4
-rw-r--r--base/stats/visit.hh4
-rw-r--r--base/traceflags.py1
-rw-r--r--cpu/base_cpu.cc7
-rw-r--r--cpu/base_cpu.hh20
-rw-r--r--cpu/exec_context.cc2
-rw-r--r--cpu/memtest/memtest.cc2
-rw-r--r--cpu/memtest/memtest.hh6
-rw-r--r--cpu/simple_cpu/simple_cpu.cc16
-rw-r--r--cpu/simple_cpu/simple_cpu.hh99
-rw-r--r--cpu/static_inst.hh23
-rw-r--r--kern/system_events.cc109
-rw-r--r--kern/system_events.hh56
-rw-r--r--kern/tru64/mbuf.hh4
-rw-r--r--kern/tru64/tru64_events.cc82
-rw-r--r--kern/tru64/tru64_events.hh22
-rw-r--r--kern/tru64/tru64_system.cc69
-rw-r--r--kern/tru64/tru64_system.hh13
-rw-r--r--sim/debug.cc2
-rw-r--r--sim/debug.hh4
-rw-r--r--sim/main.cc10
-rw-r--r--sim/process.cc2
-rw-r--r--sim/process.hh2
-rw-r--r--sim/sim_object.cc2
-rw-r--r--sim/stat_control.cc42
-rw-r--r--sim/stat_control.hh4
-rw-r--r--sim/stats.hh8
-rw-r--r--sim/system.cc87
-rw-r--r--sim/system.hh32
-rw-r--r--test/Makefile12
-rw-r--r--test/stattest.cc12
56 files changed, 2395 insertions, 1632 deletions
diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh
index 12196c44b..b5fc18255 100644
--- a/arch/alpha/alpha_memory.hh
+++ b/arch/alpha/alpha_memory.hh
@@ -80,10 +80,10 @@ class AlphaTLB : public SimObject
class AlphaITB : public AlphaTLB
{
protected:
- mutable Statistics::Scalar<> hits;
- mutable Statistics::Scalar<> misses;
- mutable Statistics::Scalar<> acv;
- mutable Statistics::Formula accesses;
+ mutable Stats::Scalar<> hits;
+ mutable Stats::Scalar<> misses;
+ mutable Stats::Scalar<> acv;
+ mutable Stats::Formula accesses;
protected:
void fault(Addr pc, ExecContext *xc) const;
@@ -98,18 +98,18 @@ class AlphaITB : public AlphaTLB
class AlphaDTB : public AlphaTLB
{
protected:
- mutable Statistics::Scalar<> read_hits;
- mutable Statistics::Scalar<> read_misses;
- mutable Statistics::Scalar<> read_acv;
- mutable Statistics::Scalar<> read_accesses;
- mutable Statistics::Scalar<> write_hits;
- mutable Statistics::Scalar<> write_misses;
- mutable Statistics::Scalar<> write_acv;
- mutable Statistics::Scalar<> write_accesses;
- Statistics::Formula hits;
- Statistics::Formula misses;
- Statistics::Formula acv;
- Statistics::Formula accesses;
+ mutable Stats::Scalar<> read_hits;
+ mutable Stats::Scalar<> read_misses;
+ mutable Stats::Scalar<> read_acv;
+ mutable Stats::Scalar<> read_accesses;
+ mutable Stats::Scalar<> write_hits;
+ mutable Stats::Scalar<> write_misses;
+ mutable Stats::Scalar<> write_acv;
+ mutable Stats::Scalar<> write_accesses;
+ Stats::Formula hits;
+ Stats::Formula misses;
+ Stats::Formula acv;
+ Stats::Formula accesses;
protected:
void fault(Addr pc, uint64_t flags, ExecContext *xc) const;
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index fe665abe6..e88f6d0a3 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -1,17 +1,15 @@
/* $Id$ */
-#include "targetarch/alpha_memory.hh"
-#include "sim/annotation.hh"
-#ifdef DEBUG
-#include "sim/debug.hh"
-#endif
+#include "arch/alpha/alpha_memory.hh"
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/osfpal.hh"
+#include "base/kgdb.h"
+#include "base/remote_gdb.hh"
+#include "base/stats/events.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast_cpu/fast_cpu.hh"
+#include "sim/debug.hh"
#include "sim/sim_events.hh"
-#include "targetarch/isa_traits.hh"
-#include "base/remote_gdb.hh"
-#include "base/kgdb.h" // for ALPHA_KENTRY_IF
-#include "targetarch/osfpal.hh"
#ifdef FULL_SYSTEM
@@ -162,6 +160,8 @@ AlphaISA::zeroRegisters(XC *xc)
void
ExecContext::ev5_trap(Fault fault)
{
+ Stats::recordEvent(csprintf("Fault %s", FaultName(fault)));
+
assert(!misspeculating());
kernelStats.fault(fault);
@@ -185,8 +185,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);
}
@@ -362,6 +360,7 @@ Fault
ExecContext::setIpr(int idx, uint64_t val)
{
uint64_t *ipr = regs.ipr;
+ uint64_t old;
if (misspeculating())
return No_Fault;
@@ -414,9 +413,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:
@@ -444,11 +443,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:
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
index 016040b79..8641c2880 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -1,41 +1,67 @@
// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
//
// Alpha ISA description file.
//
+////////////////////////////////////////////////////////////////////
-let {{
- global rcs_id
- rcs_id = "$Id$"
-}};
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+output header {{
#include <sstream>
#include <iostream>
#include <iomanip>
+#include "cpu/static_inst.hh"
+#include "mem/mem_req.hh" // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
+}};
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "cpu/exec_context.hh"
+output exec {{
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#include "cpu/base_cpu.hh"
#include "cpu/exetrace.hh"
-#include "cpu/fast_cpu/fast_cpu.hh"
-#include "cpu/full_cpu/dyn_inst.hh"
-#include "cpu/simple_cpu/simple_cpu.hh"
-#include "cpu/static_inst.hh"
-#include "sim/annotation.hh"
#include "sim/sim_exit.hh"
#ifdef FULL_SYSTEM
#include "arch/alpha/ev5.hh"
#include "arch/alpha/pseudo_inst.hh"
#endif
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
namespace AlphaISA;
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
// Universal (format-independent) fields
def bitfield OPCODE <31:26>;
def bitfield RA <25:21>;
@@ -94,70 +120,48 @@ def bitfield HW_IPR_IDX <15:0>; // IPR index
// M5 instructions
def bitfield M5FUNC <7:0>;
-let {{
- global operandTypeMap
- operandTypeMap = {
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'sw' : ('signed int', 16),
- 'uw' : ('unsigned int', 16),
- 'sl' : ('signed int', 32),
- 'ul' : ('unsigned int', 32),
- 'sq' : ('signed int', 64),
- 'uq' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64)
- }
-
- global operandTraitsMap
- operandTraitsMap = {
- # Int regs default to unsigned, but code should not count on this.
- # For clarity, descriptions that depend on unsigned behavior should
- # explicitly specify '.uq'.
- 'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
- 'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
- 'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
- 'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
- 'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
- 'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
- 'Mem': MemOperandTraits('uq', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- 'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- 'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
- # The next two are hacks for non-full-system call-pal emulation
- 'R0': IntRegOperandTraits('uq', '0', None, 1),
- 'R16': IntRegOperandTraits('uq', '16', None, 1),
- }
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sw' : ('signed int', 16),
+ 'uw' : ('unsigned int', 16),
+ 'sl' : ('signed int', 32),
+ 'ul' : ('unsigned int', 32),
+ 'sq' : ('signed int', 64),
+ 'uq' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64)
+}};
- defineDerivedOperandVars()
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
+ 'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
+ 'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
+ 'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
+ 'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
+ 'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
+ 'Mem': MemOperandTraits('uq', None,
+ ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
+ 'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
+ 'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
+ # The next two are hacks for non-full-system call-pal emulation
+ 'R0': IntRegOperandTraits('uq', '0', None, 1),
+ 'R16': IntRegOperandTraits('uq', '16', None, 1)
}};
-declare {{
-// just temporary, while comparing with old code for debugging
-// #define SS_COMPATIBLE_DISASSEMBLY
+////////////////////////////////////////////////////////////////////
+//
+// Basic instruction classes/templates/formats etc.
+//
- /// Check "FP enabled" machine status bit. Called when executing any FP
- /// instruction in full-system mode.
- /// @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
- 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))) {
- fault = Fen_Fault;
- }
- return fault;
- }
-#else
- template <class XC>
- inline Fault checkFpEnableFault(XC *xc)
- {
- return No_Fault;
- }
-#endif
+output header {{
+// uncomment the following to get SimpleScalar-compatible disassembly
+// (useful for diffing output traces).
+// #define SS_COMPATIBLE_DISASSEMBLY
/**
* Base class for all Alpha static instructions.
@@ -185,47 +189,60 @@ declare {{
/// Print a register name for disassembly given the unique
/// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg)
- {
- if (reg < FP_Base_DepTag) {
- ccprintf(os, "r%d", reg);
- }
- else {
- ccprintf(os, "f%d", reg - FP_Base_DepTag);
- }
- }
+ void printReg(std::ostream &os, int reg);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- std::stringstream ss;
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
- ccprintf(ss, "%-10s ", mnemonic);
+output decoder {{
+ void
+ AlphaStaticInst::printReg(std::ostream &os, int reg)
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
+ std::string
+ AlphaStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ std::stringstream ss;
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
+ ccprintf(ss, "%-10s ", mnemonic);
- return ss.str();
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
}
- };
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
}};
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *);
+}};
+// Basic instruction class declaration template.
def template BasicDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
@@ -234,18 +251,24 @@ def template BasicDeclare {{
{
public:
/// Constructor.
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
+ %(class_name)s(MachInst machInst);
- %(exec_func_declarations)s
+ %(BasicExecDeclare)s
};
}};
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData)
{
Fault fault = No_Fault;
@@ -263,10 +286,12 @@ def template BasicExecute {{
}
}};
+// Basic decode template.
def template BasicDecode {{
return new %(class_name)s(machInst);
}};
+// Basic decode template, passing mnemonic in as string arg to constructor.
def template BasicDecodeWithMnemonic {{
return new %(class_name)s("%(mnemonic)s", machInst);
}};
@@ -274,14 +299,20 @@ 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', 'BasicExecute')
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
-declare {{
+output header {{
/**
* Static instruction class for no-ops. This is a leaf class.
*/
@@ -301,24 +332,21 @@ declare {{
~Nop() { }
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
#ifdef SS_COMPATIBLE_DISASSEMBLY
- return originalDisassembly;
+ return originalDisassembly;
#else
- return csprintf("%-10s (%s)", "nop", originalDisassembly);
+ return csprintf("%-10s (%s)", "nop", originalDisassembly);
#endif
- }
-
- Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
- { return No_Fault; }
-
- Fault execute(FastCPUExecContext *, Trace::InstRecord *)
- { return No_Fault; }
-
- Fault execute(FullCPUExecContext *, Trace::InstRecord *)
- { return No_Fault; }
- };
+ }
/// Helper function for decoding nops. Substitute Nop object
/// for original inst passed in as arg (and delete latter).
@@ -332,18 +360,21 @@ declare {{
}
}};
-def format Nop() {{
- return ('', 'return new Nop("%s", machInst);\n' % name, 'return No_Fault;')
+output exec {{
+ Fault
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+ {
+ return No_Fault;
+ }
}};
-
// integer & FP operate instructions use Rc as dest, so check for
// Rc == 31 to detect nops
def template OperateNopCheckDecode {{
{
AlphaStaticInst *i = new %(class_name)s(machInst);
if (RC == 31) {
- i = makeNop(i);
+ i = makeNop(i);
}
return i;
}
@@ -353,7 +384,10 @@ def template OperateNopCheckDecode {{
def format BasicOperateWithNopCheck(code, *opt_args) {{
iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
opt_args)
- return iop.subst('BasicDeclare', 'OperateNopCheckDecode', 'BasicExecute')
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
@@ -362,7 +396,7 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
// Integer operate instructions
//
-declare {{
+output header {{
/**
* Base class for integer immediate instructions.
*/
@@ -378,39 +412,45 @@ declare {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- std::stringstream ss;
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
- ccprintf(ss, "%-10s ", mnemonic);
+output decoder {{
+ std::string
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ std::stringstream ss;
- // just print the first source reg... if there's
- // a second one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
+ ccprintf(ss, "%-10s ", mnemonic);
- ss << (int)imm;
-
- if (_numDestRegs > 0) {
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
+ // just print the first source reg... if there's
+ // a second one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
- return ss.str();
+ ss << (int)imm;
+
+ if (_numDestRegs > 0) {
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
}
- };
+
+ return ss.str();
+ }
}};
+
def template RegOrImmDecode {{
{
AlphaStaticInst *i =
- (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
- : (AlphaStaticInst *)new %(class_name)s(machInst);
+ (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
+ : (AlphaStaticInst *)new %(class_name)s(machInst);
if (RC == 31) {
- i = makeNop(i);
+ i = makeNop(i);
}
return i;
}
@@ -437,24 +477,23 @@ def format IntegerOperate(code, *opt_flags) {{
# generate declaration for register version
cblk = CodeBlock(code)
iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- (decls, exec_code) = iop.subst('BasicDeclare', 'BasicExecute')
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BasicExecute.subst(iop)
if uses_imm:
# append declaration for imm version
imm_cblk = CodeBlock(imm_code)
imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
opt_flags)
- (imm_decls, imm_exec_code) = \
- imm_iop.subst('BasicDeclare', 'BasicExecute')
- decls += imm_decls
- exec_code += imm_exec_code
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += BasicExecute.subst(imm_iop)
# decode checks IMM bit to pick correct version
- decode = iop.subst('RegOrImmDecode')
+ decode_block = RegOrImmDecode.subst(iop)
else:
# no imm version: just check for nop
- decode = iop.subst('OperateNopCheckDecode')
-
- return (decls, decode, exec_code)
+ decode_block = OperateNopCheckDecode.subst(iop)
}};
@@ -467,7 +506,29 @@ def format IntegerOperate(code, *opt_flags) {{
// BasicOperateWithNopCheck.
//
-declare {{
+output exec {{
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction in full-system mode.
+ /// @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(%(CPU_exec_context)s *xc)
+ {
+ Fault fault = No_Fault; // dummy... this ipr access should not fault
+ if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
+ fault = Fen_Fault;
+ }
+ return fault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return No_Fault;
+ }
+#endif
+}};
+
+output header {{
/**
* Base class for general floating-point instructions. Includes
* support for various Alpha rounding and trapping modes. Only FP
@@ -529,61 +590,88 @@ declare {{
}
#if defined(linux)
- int
- getC99RoundingMode(uint64_t fpcr_val)
- {
- if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
- }
- else {
- return alphaToC99RoundingMode[roundingMode];
- }
- }
+ int getC99RoundingMode(uint64_t fpcr_val);
#endif
// This differs from the AlphaStaticInst version only in
// printing suffixes for non-default rounding & trapping modes.
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- std::string mnem_str(mnemonic);
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
-#ifndef SS_COMPATIBLE_DISASSEMBLY
- std::string suffix("");
- suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
- ? fpTrappingModeSuffix[trappingMode]
- : intTrappingModeSuffix[trappingMode]);
- suffix += roundingModeSuffix[roundingMode];
-
- if (suffix != "") {
- mnem_str = csprintf("%s/%s", mnemonic, suffix);
- }
+}};
+
+
+def template FloatingPointDecode {{
+ {
+ bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
+ && FP_ROUNDMODE == AlphaFP::Normal);
+ AlphaStaticInst *i =
+ fast ? (AlphaStaticInst *)new %(class_name)sFast(machInst) :
+ (AlphaStaticInst *)new %(class_name)sGeneral(machInst);
+
+ if (FC == 31) {
+ i = makeNop(i);
+ }
+
+ return i;
+ }
+}};
+
+output decoder {{
+#if defined(linux)
+ int
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val)
+ {
+ if (roundingMode == Dynamic) {
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
+ }
+ else {
+ return alphaToC99RoundingMode[roundingMode];
+ }
+ }
#endif
- std::stringstream ss;
- ccprintf(ss, "%-10s ", mnem_str.c_str());
+ std::string
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ std::string mnem_str(mnemonic);
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+ std::string suffix("");
+ suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+ ? fpTrappingModeSuffix[trappingMode]
+ : intTrappingModeSuffix[trappingMode]);
+ suffix += roundingModeSuffix[roundingMode];
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
+ if (suffix != "") {
+ mnem_str = csprintf("%s/%s", mnemonic, suffix);
+ }
+#endif
- return ss.str();
+ std::stringstream ss;
+ ccprintf(ss, "%-10s ", mnem_str.c_str());
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
}
- };
+
+ return ss.str();
+ }
#if defined(linux)
const int AlphaFP::alphaToC99RoundingMode[] = {
@@ -603,34 +691,19 @@ declare {{
{ "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
}};
-
-def template FloatingPointDecode {{
- {
- bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
- && FP_ROUNDMODE == AlphaFP::Normal);
- AlphaStaticInst *i =
- fast ? (AlphaStaticInst *)new %(class_name)sFast(machInst) :
- (AlphaStaticInst *)new %(class_name)sGeneral(machInst);
-
- if (FC == 31) {
- i = makeNop(i);
- }
-
- return i;
- }
-}};
-
// 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)
- decode = iop.subst('FloatingPointDecode')
+ decode_block = FloatingPointDecode.subst(iop)
fast_iop = InstObjParams(name, Name + 'Fast', 'AlphaFP',
- CodeBlock(code), opt_args)
- (fast_declare, fast_exec) = fast_iop.subst('BasicDeclare', 'BasicExecute')
+ CodeBlock(code), opt_args)
+ header_output = BasicDeclare.subst(fast_iop)
+ decoder_output = BasicConstructor.subst(fast_iop)
+ exec_output = BasicExecute.subst(fast_iop)
gen_code_prefix = r'''
#if defined(linux)
@@ -645,9 +718,9 @@ def format FloatingPointOperate(code, *opt_args) {{
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)
+ header_output += BasicDeclare.subst(gen_iop)
+ decoder_output += BasicConstructor.subst(gen_iop)
+ exec_output += BasicExecute.subst(gen_iop)
}};
@@ -656,7 +729,7 @@ def format FloatingPointOperate(code, *opt_args) {{
// Memory-format instructions: LoadAddress, Load, Store
//
-declare {{
+output header {{
/**
* Base class for general Alpha memory-format instructions.
*/
@@ -664,49 +737,71 @@ declare {{
{
protected:
- /// Displacement for EA calculation (signed).
- int32_t disp;
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr<AlphaISA> eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr<AlphaISA> memAccPtr;
/// Constructor
- Memory(const char *mnem, MachInst _machInst, OpClass __opClass)
+ Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
: AlphaStaticInst(mnem, _machInst, __opClass),
- disp(MEMDISP), memAccessFlags(0)
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+
+ public:
+
+ const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
+ };
+
+ /**
+ * Base class for memory-format instructions using a 32-bit
+ * displacement (i.e. most of them).
+ */
+ class MemoryDisp32 : public Memory
+ {
+ protected:
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor.
+ MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(MEMDISP)
{
- return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
- flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
}
};
+
/**
* Base class for a few miscellaneous memory-format insts
* that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
* None of these instructions has a destination register either.
*/
- class MemoryNoDisp : public AlphaStaticInst
+ class MemoryNoDisp : public Memory
{
protected:
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
-
/// Constructor
- MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- memAccessFlags(0)
+ MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- return csprintf("%-10s (r%d)", mnemonic, RB);
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
};
+
/**
* Base class for "fake" effective-address computation
* instructions returnded by eaCompInst().
@@ -720,14 +815,7 @@ declare {{
{
}
- Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute eacomp"); }
-
- Fault execute(FastCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute eacomp"); }
-
- Fault execute(FullCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute eacomp"); }
+ %(BasicExecDeclare)s
};
/**
@@ -743,22 +831,48 @@ declare {{
{
}
- Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute memacc"); }
+ %(BasicExecDeclare)s
+ };
+
+}};
- Fault execute(FastCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute memacc"); }
- Fault execute(FullCPUExecContext *, Trace::InstRecord *)
- { panic("attempt to execute memacc"); }
- };
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+ flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
+ }
+ std::string
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ return csprintf("%-10s (r%d)", mnemonic, RB);
+ }
+}};
+
+output exec {{
+ Fault
+ EACompBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+ {
+ panic("attempt to execute eacomp");
+ }
+
+ Fault
+ MemAccBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+ {
+ panic("attempt to execute memacc");
+ }
}};
def format LoadAddress(code) {{
- iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
+ iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
@@ -777,11 +891,7 @@ def template LoadStoreDeclare {{
{
public:
/// Constructor
- EAComp(MachInst machInst)
- : EACompBase(machInst)
- {
- %(ea_constructor)s;
- }
+ EAComp(MachInst machInst);
};
/**
@@ -791,37 +901,41 @@ def template LoadStoreDeclare {{
{
public:
/// Constructor
- MemAcc(MachInst machInst)
- : MemAccBase(machInst, %(op_class)s)
- {
- %(memacc_constructor)s;
- }
+ MemAcc(MachInst machInst);
};
- /// Pointer to EAComp object.
- StaticInstPtr<AlphaISA> eaCompPtr;
- /// Pointer to MemAcc object.
- StaticInstPtr<AlphaISA> memAccPtr;
-
public:
- StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
- StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
-
/// Constructor.
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
- eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
- {
- %(constructor)s;
- }
+ %(class_name)s(MachInst machInst);
- %(exec_func_declarations)s
+ %(BasicExecDeclare)s
};
}};
+def template LoadStoreConstructor {{
+ inline %(class_name)s::EAComp::EAComp(MachInst machInst)
+ : EACompBase(machInst)
+ {
+ %(ea_constructor)s;
+ }
+
+ inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
+ : MemAccBase(machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ new EAComp(machInst), new MemAcc(machInst))
+ {
+ %(constructor)s;
+ }
+}};
+
def template LoadStoreExecute {{
- Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData)
{
Addr EA;
@@ -853,66 +967,9 @@ def template LoadStoreExecute {{
}
}};
-def template PrefetchDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- protected:
-
- /**
- * "Fake" effective address computation class for "%(mnemonic)s".
- */
- class EAComp : public EACompBase
- {
- public:
- /// Constructor
- EAComp(MachInst machInst)
- : EACompBase(machInst)
- {
- %(ea_constructor)s;
- }
- };
-
- /**
- * "Fake" memory access instruction class for "%(mnemonic)s".
- */
- class MemAcc : public MemAccBase
- {
- public:
- /// Constructor
- MemAcc(MachInst machInst)
- : MemAccBase(machInst, %(op_class)s)
- {
- %(memacc_constructor)s;
- }
- };
-
- /// Pointer to EAComp object.
- StaticInstPtr<AlphaISA> eaCompPtr;
- /// Pointer to MemAcc object.
- StaticInstPtr<AlphaISA> memAccPtr;
-
- public:
-
- StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
- StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
-
- /// Constructor
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
- eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
- {
- %(constructor)s;
- }
-
- %(exec_func_declarations)s
- };
-}};
def template PrefetchExecute {{
- Fault %(class_name)s::execute(%(cpu_model)s *xc,
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData)
{
Addr EA;
@@ -958,12 +1015,10 @@ def template LoadPrefetchCheckDecode {{
let {{
-global LoadStoreBase
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
- base_class = 'Memory', flags = [],
- declare_template = 'LoadStoreDeclare',
- decode_template = 'BasicDecode',
- exec_template = 'LoadStoreExecute'):
+ base_class = 'MemoryDisp32', flags = [],
+ decode_template = BasicDecode,
+ exec_template = LoadStoreExecute):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
@@ -994,62 +1049,68 @@ 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, exec_template)
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop), exec_template.subst(iop))
}};
def format LoadOrNop(ea_code, memacc_code, *flags) {{
- return LoadStoreBase(name, Name, ea_code, memacc_code,
- flags = flags,
- decode_template = 'LoadNopCheckDecode')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
+ decode_template = LoadNopCheckDecode)
}};
// 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, exec_code) = \
+ (header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code,
- decode_template = 'LoadPrefetchCheckDecode')
+ decode_template = LoadPrefetchCheckDecode)
# Declare the prefetch instruction object.
# convert flags from tuple to list to make them mutable
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
- (pfdecls, pfdecode, pfexec) = \
+ (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
- flags = pf_flags,
- declare_template = 'PrefetchDeclare',
- exec_template = 'PrefetchExecute')
+ flags = pf_flags, exec_template = PrefetchExecute)
- return (decls + pfdecls, decode, exec_code + pfexec)
+ header_output += pf_header_output
+ decoder_output += pf_decoder_output
+ exec_output += pf_exec_output
}};
def format Store(ea_code, memacc_code, *flags) {{
- return LoadStoreBase(name, Name, ea_code, memacc_code,
- flags = flags)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags)
}};
def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
- return LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
- flags = flags)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
+ flags = flags)
}};
// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
def format MiscPrefetch(ea_code, memacc_code, *flags) {{
- return LoadStoreBase(name, Name, ea_code, memacc_code,
- flags = flags, base_class = 'MemoryNoDisp')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
+ base_class = 'MemoryNoDisp')
}};
////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
-
-declare {{
+output header {{
/**
* Base class for instructions whose disassembly is not purely a
@@ -1076,22 +1137,7 @@ declare {{
{
}
- const std::string &disassemble(Addr pc, const SymbolTable *symtab)
- {
- if (!cachedDisassembly ||
- pc != cachedPC || symtab != cachedSymtab)
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
-
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
- cachedPC = pc;
- cachedSymtab = symtab;
- }
-
- return *cachedDisassembly;
- }
+ const std::string &disassemble(Addr pc, const SymbolTable *symtab);
};
/**
@@ -1111,47 +1157,9 @@ declare {{
{
}
- Addr branchTarget(Addr branchPC) const
- {
- return branchPC + 4 + disp;
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // There's only one register arg (RA), but it could be
- // either a source (the condition for conditional
- // branches) or a destination (the link reg for
- // unconditional branches)
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
- else if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numSrcRegs == 0 && _numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
-#endif
-
- Addr target = pc + 4 + disp;
+ Addr branchTarget(Addr branchPC) const;
- std::string str;
- if (symtab && symtab->findSymbol(target, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", target);
-
- return ss.str();
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
};
/**
@@ -1173,36 +1181,106 @@ declare {{
{
}
- Addr branchTarget(ExecContext *xc) const
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab)
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
{
- Addr NPC = xc->readPC() + 4;
- uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- std::stringstream ss;
+ return *cachedDisassembly;
+ }
- ccprintf(ss, "%-10s ", mnemonic);
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+ else if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
+ if (_numSrcRegs == 0 && _numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
+ }
#endif
- if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
+ Addr target = pc + 4 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ std::stringstream ss;
- ccprintf(ss, "(r%d)", RB);
+ ccprintf(ss, "%-10s ", mnemonic);
- return ss.str();
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ if (_numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
}
- };
+#endif
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ ccprintf(ss, "(r%d)", RB);
+
+ return ss.str();
+ }
}};
def template JumpOrBranchDecode {{
@@ -1215,44 +1293,56 @@ 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', 'BasicExecute')
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
let {{
-global UncondCtrlBase
def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
# Declare basic control transfer w/o link (i.e. link reg is R31)
nolink_code = 'NPC = %s;\n' % npc_expr
nolink_iop = InstObjParams(name, Name, base_class,
CodeBlock(nolink_code), flags)
- (decls, exec_code) = nolink_iop.subst('BasicDeclare', 'BasicExecute')
+ header_output = BasicDeclare.subst(nolink_iop)
+ decoder_output = BasicConstructor.subst(nolink_iop)
+ exec_output = BasicExecute.subst(nolink_iop)
# 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)
- (link_decls, link_exec_code) = \
- link_iop.subst('BasicDeclare', 'BasicExecute')
- decls += link_decls
- exec_code += link_exec_code
+ header_output += BasicDeclare.subst(link_iop)
+ decoder_output += BasicConstructor.subst(link_iop)
+ exec_output += BasicExecute.subst(link_iop)
# 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'), exec_code)
+
+ return (header_output, decoder_output,
+ JumpOrBranchDecode.subst(nolink_iop), exec_output)
}};
def format UncondBranch(*flags) {{
flags += ('IsUncondControl', 'IsDirectControl')
- return UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
}};
def format Jump(*flags) {{
flags += ('IsUncondControl', 'IsIndirectControl')
- return UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
}};
-declare {{
+////////////////////////////////////////////////////////////////////
+//
+// PAL calls
+//
+
+output header {{
/**
* Base class for emulated call_pal calls (used only in
* non-full-system mode).
@@ -1268,23 +1358,31 @@ declare {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
+
+output decoder {{
+ std::string
+ EmulatedCallPal::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%s %s", "call_pal", mnemonic);
+ return csprintf("%s %s", "call_pal", mnemonic);
#else
- return csprintf("%-10s %s", "call_pal", mnemonic);
+ return csprintf("%-10s %s", "call_pal", mnemonic);
#endif
- }
- };
+ }
}};
-def format EmulatedCallPal(code) {{
- iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
+def format EmulatedCallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
-declare {{
+output header {{
/**
* Base class for full-system-mode call_pal instructions.
* Probably could turn this into a leaf class and get rid of the
@@ -1300,106 +1398,130 @@ declare {{
/// Constructor.
CallPalBase(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- palFunc(PALFUNC)
- {
- // From the 21164 HRM (paraphrased):
- // Bit 7 of the function code (mask 0x80) indicates
- // whether the call is privileged (bit 7 == 0) or
- // unprivileged (bit 7 == 1). The privileged call table
- // starts at 0x2000, the unprivielged call table starts at
- // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
- // offset.
- const int palPrivMask = 0x80;
- const int palOffsetMask = 0x3f;
-
- // Pal call is invalid unless all other bits are 0
- palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
- palPriv = ((machInst & palPrivMask) == 0);
- int shortPalFunc = (machInst & palOffsetMask);
- // Add 1 to base to set pal-mode bit
- palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- return csprintf("%-10s %#x", "call_pal", palFunc);
- }
+ OpClass __opClass);
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
};
}};
+output decoder {{
+ inline
+ CallPalBase::CallPalBase(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ palFunc(PALFUNC)
+ {
+ // From the 21164 HRM (paraphrased):
+ // Bit 7 of the function code (mask 0x80) indicates
+ // whether the call is privileged (bit 7 == 0) or
+ // unprivileged (bit 7 == 1). The privileged call table
+ // starts at 0x2000, the unprivielged call table starts at
+ // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
+ // offset.
+ const int palPrivMask = 0x80;
+ const int palOffsetMask = 0x3f;
+
+ // Pal call is invalid unless all other bits are 0
+ palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+ palPriv = ((machInst & palPrivMask) == 0);
+ int shortPalFunc = (machInst & palOffsetMask);
+ // Add 1 to base to set pal-mode bit
+ palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
+ }
+
+ std::string
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ return csprintf("%-10s %#x", "call_pal", palFunc);
+ }
+}};
-def format CallPal(code) {{
- iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
+def format CallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
+////////////////////////////////////////////////////////////////////
//
// hw_ld, hw_st
//
-declare {{
+
+output header {{
/**
* Base class for hw_ld and hw_st.
*/
- class HwLoadStore : public AlphaStaticInst
+ class HwLoadStore : public Memory
{
protected:
/// Displacement for EA calculation (signed).
int16_t disp;
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
/// Constructor
- HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass), disp(HW_LDST_DISP)
- {
- memAccessFlags = 0;
- if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
- if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
- if (HW_LDST_VPTE) memAccessFlags |= VPTE;
- if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
- }
+ HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
+
+
+output decoder {{
+ inline
+ HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst,
+ OpClass __opClass,
+ StaticInstPtr<AlphaISA> _eaCompPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(HW_LDST_DISP)
+ {
+ memAccessFlags = 0;
+ if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
+ if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
+ if (HW_LDST_VPTE) memAccessFlags |= VPTE;
+ if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
+ }
+
+ std::string
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
+ return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
#else
- // HW_LDST_LOCK and HW_LDST_COND are the same bit.
- const char *lock_str =
- (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
-
- return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
- mnemonic, RA, disp, RB,
- HW_LDST_PHYS ? ",PHYS" : "",
- HW_LDST_ALT ? ",ALT" : "",
- HW_LDST_QUAD ? ",QUAD" : "",
- HW_LDST_VPTE ? ",VPTE" : "",
- lock_str);
+ // HW_LDST_LOCK and HW_LDST_COND are the same bit.
+ const char *lock_str =
+ (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
+
+ return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
+ mnemonic, RA, disp, RB,
+ HW_LDST_PHYS ? ",PHYS" : "",
+ HW_LDST_ALT ? ",ALT" : "",
+ HW_LDST_QUAD ? ",QUAD" : "",
+ HW_LDST_VPTE ? ",VPTE" : "",
+ lock_str);
#endif
- }
- };
+ }
}};
-
def format HwLoadStore(ea_code, memacc_code, class_ext, *flags) {{
- return LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- flags = flags,
- base_class = 'HwLoadStore')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ flags = flags, base_class = 'HwLoadStore')
}};
def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
- return LoadStoreBase(name, Name + class_ext,
- ea_code, memacc_code, postacc_code,
- flags = flags,
- base_class = 'HwLoadStore')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ postacc_code, flags = flags, base_class = 'HwLoadStore')
}};
-declare {{
+output header {{
/**
* Base class for hw_mfpr and hw_mtpr.
*/
@@ -1416,28 +1538,42 @@ declare {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- if (_numSrcRegs > 0) {
- // must be mtpr
- return csprintf("%-10s r%d,IPR(%#x)",
- mnemonic, RA, ipr_index);
- }
- else {
- // must be mfpr
- return csprintf("%-10s IPR(%#x),r%d",
- mnemonic, ipr_index, RA);
- }
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
};
}};
+output decoder {{
+ std::string
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ if (_numSrcRegs > 0) {
+ // must be mtpr
+ return csprintf("%-10s r%d,IPR(%#x)",
+ mnemonic, RA, ipr_index);
+ }
+ else {
+ // must be mfpr
+ return csprintf("%-10s IPR(%#x),r%d",
+ mnemonic, ipr_index, RA);
+ }
+ }
+}};
+
def format HwMoveIPR(code) {{
iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
- return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
}};
-declare {{
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
/**
* Static instruction class for unimplemented instructions that
* cause simulator termination. Note that these are recognized
@@ -1452,39 +1588,14 @@ declare {{
FailUnimplemented(const char *_mnemonic, MachInst _machInst)
: AlphaStaticInst(_mnemonic, _machInst, No_OpClass)
{
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
}
- Fault execute(SimpleCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
+ %(BasicExecDeclare)s
- Fault execute(FastCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
-
- Fault execute(FullCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- // don't panic if this is a misspeculated instruction
- if (!xc->misspeculating())
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)",
- mnemonic, machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- return csprintf("%-10s (unimplemented)", mnemonic);
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
};
/**
@@ -1507,79 +1618,70 @@ declare {{
WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
: AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
{
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
}
- Fault execute(SimpleCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
-
- return No_Fault;
- }
-
- Fault execute(FastCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
-
- return No_Fault;
- }
+ %(BasicExecDeclare)s
- Fault execute(FullCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- if (!xc->misspeculating() && !warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
- return No_Fault;
- }
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s", mnemonic);
+ return csprintf("%-10s", mnemonic);
#else
- return csprintf("%-10s (unimplemented)", mnemonic);
+ return csprintf("%-10s (unimplemented)", mnemonic);
#endif
- }
- };
+ }
}};
-def template WarnUnimplDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData)
{
- public:
- /// Constructor
- %(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst)
- {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+ return Unimplemented_Opcode_Fault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData)
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
}
- };
+
+ return No_Fault;
+ }
}};
def format FailUnimpl() {{
iop = InstObjParams(name, 'FailUnimplemented')
- return ('', iop.subst('BasicDecodeWithMnemonic'), '')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
}};
def format WarnUnimpl() {{
- iop = InstObjParams(name, Name, 'WarnUnimplemented')
- return iop.subst('WarnUnimplDeclare', 'BasicDecode') + ['']
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
}};
-declare {{
+output header {{
/**
* Static instruction class for unknown (illegal) instructions.
* These cause simulator termination if they are executed in a
@@ -1592,47 +1694,51 @@ declare {{
Unknown(MachInst _machInst)
: AlphaStaticInst("unknown", _machInst, No_OpClass)
{
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
}
- Fault execute(SimpleCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
+ %(BasicExecDeclare)s
- Fault execute(FastCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ };
+}};
- Fault execute(FullCPUExecContext *xc,
- Trace::InstRecord *traceData)
- {
- // don't panic if this is a misspeculated instruction
- if (!xc->misspeculating())
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
- {
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- "unknown", machInst, OPCODE);
- }
- };
+output decoder {{
+ std::string
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ "unknown", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData)
+ {
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
+ return Unimplemented_Opcode_Fault;
+ }
}};
def format Unknown() {{
- return ('', 'return new Unknown(machInst);\n', '')
+ decode_block = 'return new Unknown(machInst);\n'
}};
-declare {{
+////////////////////////////////////////////////////////////////////
+//
+// Utility functions for execute methods
+//
+
+output exec {{
/// Return opa + opb, summing carry into third arg.
inline uint64_t
@@ -1646,7 +1752,7 @@ declare {{
/// Multiply two 64-bit values (opa * opb), returning the 128-bit
/// product in res_hi and res_lo.
- void
+ inline void
mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
{
// do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
@@ -1716,6 +1822,11 @@ declare {{
}
}};
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
decode OPCODE default Unknown::unknown() {
format LoadAddress {
@@ -2298,16 +2409,12 @@ decode OPCODE default Unknown::unknown() {
format BasicOperate {
0xe000: rc({{
Ra = xc->readIntrFlag();
- if (!xc->misspeculating()) {
- xc->setIntrFlag(0);
- }
- }});
+ xc->setIntrFlag(0);
+ }}, IsNonSpeculative);
0xf000: rs({{
Ra = xc->readIntrFlag();
- if (!xc->misspeculating()) {
- xc->setIntrFlag(1);
- }
- }});
+ xc->setIntrFlag(1);
+ }}, IsNonSpeculative);
}
#else
format FailUnimpl {
@@ -2327,40 +2434,26 @@ decode OPCODE default Unknown::unknown() {
fault = Unimplemented_Opcode_Fault;
}
else {
- bool dopal = true;
-
- if (!xc->misspeculating()) {
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- dopal = xc->simPalCheck(palFunc);
-
- Annotate::Callpal(xc->xcBase(), palFunc);
-
- if (dopal) {
- AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
- xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
- }
- }
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ bool dopal = xc->simPalCheck(palFunc);
- // if we're misspeculating, it's still safe (if
- // unrealistic) to set NPC, as the control-flow change
- // won't get committed.
if (dopal) {
+ AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
+ xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
}
}
- }});
+ }}, IsNonSpeculative);
#else
0x00: decode PALFUNC {
format EmulatedCallPal {
0x00: halt ({{
- if (!xc->misspeculating())
- SimExit(curTick, "halt instruction encountered");
- }});
+ SimExit(curTick, "halt instruction encountered");
+ }}, IsNonSpeculative);
0x83: callsys({{
- if (!xc->misspeculating())
- xc->syscall();
- }});
+ xc->syscall();
+ }}, IsNonSpeculative);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }});
// Write uniq reg with value from ABI arg register (r16)
@@ -2394,50 +2487,36 @@ decode OPCODE default Unknown::unknown() {
// M5 special opcodes use the reserved 0x01 opcode space
0x01: decode M5FUNC {
0x00: arm({{
- if (!xc->misspeculating()) {
- Annotate::ARM(xc->xcBase());
- xc->xcBase()->kernelStats.arm();
- }
- }});
+ AlphaPseudo::arm(xc->xcBase());
+ }}, IsNonSpeculative);
0x01: quiesce({{
- if (!xc->misspeculating())
- AlphaPseudo::quiesce(xc->xcBase());
- }});
+ AlphaPseudo::quiesce(xc->xcBase());
+ }}, IsNonSpeculative);
0x10: ivlb({{
- if (!xc->misspeculating()) {
- Annotate::BeginInterval(xc->xcBase());
- xc->xcBase()->kernelStats.ivlb();
- }
- }}, No_OpClass);
+ AlphaPseudo::ivlb(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x11: ivle({{
- if (!xc->misspeculating())
- Annotate::EndInterval(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::ivle(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x20: m5exit_old({{
- if (!xc->misspeculating())
- AlphaPseudo::m5exit_old(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::m5exit_old(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x21: m5exit({{
- if (!xc->misspeculating())
- AlphaPseudo::m5exit(xc->xcBase());
- }}, No_OpClass);
+ AlphaPseudo::m5exit(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
0x40: resetstats({{
- if (!xc->misspeculating())
- AlphaPseudo::resetstats(xc->xcBase());
- }});
+ AlphaPseudo::resetstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x41: dumpstats({{
- if (!xc->misspeculating())
- AlphaPseudo::dumpstats(xc->xcBase());
- }});
+ AlphaPseudo::dumpstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x42: dumpresetstats({{
- if (!xc->misspeculating())
- AlphaPseudo::dumpresetstats(xc->xcBase());
- }});
+ AlphaPseudo::dumpresetstats(xc->xcBase());
+ }}, IsNonSpeculative);
0x43: m5checkpoint({{
- if (!xc->misspeculating())
- AlphaPseudo::m5checkpoint(xc->xcBase());
- }});
+ AlphaPseudo::m5checkpoint(xc->xcBase());
+ }}, IsNonSpeculative);
}
}
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index 194dc6400..12dacebd9 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -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"
@@ -38,7 +37,7 @@
#include "sim/stats.hh"
using namespace std;
-using namespace Statistics;
+using namespace Stats;
namespace AlphaPseudo
{
@@ -47,17 +46,33 @@ namespace AlphaPseudo
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)
{
SimExit(curTick, "m5_exit_old instruction encountered");
@@ -83,7 +98,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
- using namespace Statistics;
+ using namespace Stats;
SetupEvent(Reset, when, repeat);
}
@@ -99,7 +114,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
- using namespace Statistics;
+ using namespace Stats;
SetupEvent(Dump, when, repeat);
}
@@ -115,7 +130,7 @@ namespace AlphaPseudo
Tick when = curTick + NS2Ticks(delay);
Tick repeat = NS2Ticks(period);
- using namespace Statistics;
+ using namespace Stats;
SetupEvent(Dump|Reset, when, repeat);
}
diff --git a/arch/alpha/pseudo_inst.hh b/arch/alpha/pseudo_inst.hh
index 85f432504..e5551a44b 100644
--- a/arch/alpha/pseudo_inst.hh
+++ b/arch/alpha/pseudo_inst.hh
@@ -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);
diff --git a/arch/alpha/vptr.hh b/arch/alpha/vptr.hh
new file mode 100644
index 000000000..7f0b036a3
--- /dev/null
+++ b/arch/alpha/vptr.hh
@@ -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__
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index cc42657e2..7f77241be 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -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]
-
-# 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])
+# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
+# directly to the appropriate output section.
+
+# 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]) 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(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 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
@@ -948,10 +1057,10 @@ class IntRegOperandTraits(OperandTraits):
if (type == 'float' or type == 'double'):
error(0, 'Attempt to read integer register as FP')
if (size == self.dflt_size):
- return '%s = xc->readIntReg(_srcRegIdx[%d]);\n' % \
+ return '%s = xc->readIntReg(this, %d);\n' % \
(op_desc.munged_name, op_desc.src_reg_idx)
else:
- return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \
+ return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
(op_desc.munged_name, op_desc.src_reg_idx, size-1)
def makeWrite(self, op_desc):
@@ -965,7 +1074,7 @@ class IntRegOperandTraits(OperandTraits):
wb = '''
{
%s final_val = %s;
- xc->setIntReg(_destRegIdx[%d], final_val);\n
+ xc->setIntReg(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (self.dflt_type, final_val, op_desc.dest_reg_idx)
return wb
@@ -998,7 +1107,7 @@ class FloatRegOperandTraits(OperandTraits):
func = 'readFloatRegInt'
if (size != self.dflt_size):
bit_select = 1
- base = 'xc->%s(_srcRegIdx[%d] - FP_Base_DepTag)' % \
+ base = 'xc->%s(this, %d)' % \
(func, op_desc.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
@@ -1021,7 +1130,7 @@ class FloatRegOperandTraits(OperandTraits):
wb = '''
{
%s final_val = %s;
- xc->%s(_destRegIdx[%d] - FP_Base_DepTag, final_val);\n
+ xc->%s(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
}''' % (type, final_val, func, op_desc.dest_reg_idx)
return wb
@@ -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,11 +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(FastCPUExecContext *, 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))
@@ -1420,49 +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
-
- 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', 'FastCPUExecContext',
- '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
+#######################
+#
+# Output file template
+#
+
+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])
diff --git a/base/hybrid_pred.cc b/base/hybrid_pred.cc
index 12bab975b..41cf88675 100644
--- a/base/hybrid_pred.cc
+++ b/base/hybrid_pred.cc
@@ -63,7 +63,7 @@ HybridPredictor::HybridPredictor(const char *_p_name, const char *_z_name,
void HybridPredictor::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
string p_name;
stringstream description;
@@ -148,7 +148,7 @@ void HybridPredictor::regStats()
void HybridPredictor::regFormulas()
{
- using namespace Statistics;
+ using namespace Stats;
string p_name;
stringstream description;
diff --git a/base/hybrid_pred.hh b/base/hybrid_pred.hh
index 9063f3084..a76977ae2 100644
--- a/base/hybrid_pred.hh
+++ b/base/hybrid_pred.hh
@@ -59,22 +59,22 @@ class HybridPredictor : public GenericPredictor
//
// Stats
//
- Statistics::Scalar<> pred_one; //num_one_preds
- Statistics::Scalar<> pred_zero; //num_zero_preds
- Statistics::Scalar<> correct_pred_one; //num_one_correct
- Statistics::Scalar<> correct_pred_zero; //num_zero_correct
- Statistics::Scalar<> record_one; //num_one_updates
- Statistics::Scalar<> record_zero; //num_zero_updates
-
- Statistics::Formula total_preds;
- Statistics::Formula frac_preds_zero;
- Statistics::Formula frac_preds_one;
- Statistics::Formula total_correct;
- Statistics::Formula total_accuracy;
- Statistics::Formula zero_accuracy;
- Statistics::Formula one_accuracy;
- Statistics::Formula zero_coverage;
- Statistics::Formula one_coverage;
+ Stats::Scalar<> pred_one; //num_one_preds
+ Stats::Scalar<> pred_zero; //num_zero_preds
+ Stats::Scalar<> correct_pred_one; //num_one_correct
+ Stats::Scalar<> correct_pred_zero; //num_zero_correct
+ Stats::Scalar<> record_one; //num_one_updates
+ Stats::Scalar<> record_zero; //num_zero_updates
+
+ Stats::Formula total_preds;
+ Stats::Formula frac_preds_zero;
+ Stats::Formula frac_preds_one;
+ Stats::Formula total_correct;
+ Stats::Formula total_accuracy;
+ Stats::Formula zero_accuracy;
+ Stats::Formula one_accuracy;
+ Stats::Formula zero_coverage;
+ Stats::Formula one_coverage;
public:
HybridPredictor(const char *_p_name, const char *_z_name,
diff --git a/base/sat_counter.cc b/base/sat_counter.cc
index a8367d8a0..09c8881a5 100644
--- a/base/sat_counter.cc
+++ b/base/sat_counter.cc
@@ -69,7 +69,7 @@ SaturatingCounterPred::SaturatingCounterPred(string p_name,
void SaturatingCounterPred::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
stringstream name, description;
//
@@ -138,7 +138,7 @@ void SaturatingCounterPred::regStats()
void SaturatingCounterPred::regFormulas()
{
- using namespace Statistics;
+ using namespace Stats;
stringstream name, description;
//
diff --git a/base/sat_counter.hh b/base/sat_counter.hh
index a5d9c7e8a..68addbb33 100644
--- a/base/sat_counter.hh
+++ b/base/sat_counter.hh
@@ -61,24 +61,24 @@ class SaturatingCounterPred : public GenericPredictor
unsigned *table;
// Statistics
- Statistics::Scalar<> predicted_one; // Total predictions of one, preds_one
- Statistics::Scalar<> predicted_zero; // Total predictions of zero, preds_zero
- Statistics::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one
- Statistics::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero
-
- Statistics::Scalar<> record_zero; //updates_zero
- Statistics::Scalar<> record_one; //updates_one
-
- Statistics::Formula preds_total;
- Statistics::Formula pred_frac_zero;
- Statistics::Formula pred_frac_one;
- Statistics::Formula correct_total;
- Statistics::Formula updates_total;
- Statistics::Formula pred_rate;
- Statistics::Formula frac_correct_zero;
- Statistics::Formula frac_correct_one;
- Statistics::Formula coverage_zero;
- Statistics::Formula coverage_one;
+ Stats::Scalar<> predicted_one; // Total predictions of one, preds_one
+ Stats::Scalar<> predicted_zero; // Total predictions of zero, preds_zero
+ Stats::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one
+ Stats::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero
+
+ Stats::Scalar<> record_zero; //updates_zero
+ Stats::Scalar<> record_one; //updates_one
+
+ Stats::Formula preds_total;
+ Stats::Formula pred_frac_zero;
+ Stats::Formula pred_frac_one;
+ Stats::Formula correct_total;
+ Stats::Formula updates_total;
+ Stats::Formula pred_rate;
+ Stats::Formula frac_correct_zero;
+ Stats::Formula frac_correct_one;
+ Stats::Formula coverage_zero;
+ Stats::Formula coverage_one;
private:
bool pred_one(unsigned &counter) { return counter > thresh; }
diff --git a/base/statistics.cc b/base/statistics.cc
index 1a44cd342..78012bff7 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -46,7 +46,7 @@
using namespace std;
-namespace Statistics {
+namespace Stats {
StatData *
DataAccess::find() const
@@ -346,4 +346,4 @@ registerResetCallback(Callback *cb)
resetQueue.add(cb);
}
-/* namespace Statistics */ }
+/* namespace Stats */ }
diff --git a/base/statistics.hh b/base/statistics.hh
index e7fc18d74..bd1698ae7 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -70,7 +70,7 @@ class Callback;
extern Tick curTick;
/* A namespace for all of the Statistics */
-namespace Statistics {
+namespace Stats {
/* Contains the statistic implementation details */
//////////////////////////////////////////////////////////////////////
@@ -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
@@ -2698,6 +2721,13 @@ class Temp
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
+ Temp(const Value &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
template <class Bin>
Temp(const Average<Bin> &s)
: node(new ScalarStatNode(s.statData())) { }
@@ -2861,26 +2891,12 @@ 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)
{
return NodePtr(new SumNode<std::plus<Result> >(val));
}
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATISTICS_HH__
diff --git a/base/stats/events.cc b/base/stats/events.cc
new file mode 100644
index 000000000..b579981e9
--- /dev/null
+++ b/base/stats/events.cc
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifdef USE_MYSQL
+#include "base/cprintf.hh"
+#include "base/misc.hh"
+#include "base/mysql.hh"
+#include "base/stats/events.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/mysql_run.hh"
+#include "base/str.hh"
+#endif
+
+#include "sim/host.hh"
+#include "sim/universe.hh"
+
+using namespace std;
+
+namespace Stats {
+
+Tick EventStart = ULL(0xffffffffffffffff);
+
+#ifdef USE_MYSQL
+typedef map<string, uint32_t> event_map_t;
+event_map_t event_map;
+
+void
+__event(const string &stat)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ uint16_t run = MySqlDB.run();
+ assert(mysql.connected());
+
+ event_map_t::iterator i = event_map.find(stat);
+ uint32_t event;
+ if (i == event_map.end()) {
+ mysql.query(
+ csprintf("SELECT en_id "
+ "from event_names "
+ "where en_name=\"%s\"",
+ stat));
+
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 1);
+ MySQL::Row row = result.fetch_row();
+ if (row) {
+ if (!to_number(row[0], event))
+ panic("invalid event id: %s\n", row[0]);
+ } else {
+ mysql.query(
+ csprintf("INSERT INTO "
+ "event_names(en_name)"
+ "values(\"%s\")",
+ stat));
+
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ event = mysql.insert_id();
+ }
+ } else {
+ event = (*i).second;
+ }
+
+ mysql.query(
+ csprintf("INSERT INTO "
+ "events(ev_event, ev_run, ev_tick)"
+ "values(%d, %d, %d)",
+ event, run, curTick));
+
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+}
+#endif
+
+/* namespace Stats */ }
diff --git a/base/stats/events.hh b/base/stats/events.hh
new file mode 100644
index 000000000..49c060645
--- /dev/null
+++ b/base/stats/events.hh
@@ -0,0 +1,63 @@
+/*
+ * 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_STATS_EVENTS_HH__
+#define __BASE_STATS_EVENTS_HH__
+
+#include <string>
+
+#include "base/trace.hh"
+
+namespace Stats {
+
+extern Tick EventStart;
+
+#ifdef USE_MYSQL
+void __event(const std::string &stat);
+bool MySqlConnected();
+#endif
+
+inline void
+recordEvent(const std::string &stat)
+{
+ if (EventStart > curTick)
+ return;
+
+ DPRINTF(StatEvents, "Statistics Event: %s\n", stat);
+
+#ifdef USE_MYSQL
+ if (!MySqlConnected())
+ return;
+
+ __event(stat);
+#endif
+}
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_EVENTS_HH__
diff --git a/base/stats/flags.hh b/base/stats/flags.hh
index 2303de172..b86f87d25 100644
--- a/base/stats/flags.hh
+++ b/base/stats/flags.hh
@@ -28,7 +28,7 @@
#ifndef __BASE_STATS_FLAGS_HH__
#define __BASE_STATS_FLAGS_HH__
-namespace Statistics {
+namespace Stats {
/**
* Define the storage for format flags.
@@ -68,6 +68,6 @@ enum DisplayMode
extern DisplayMode DefaultMode;
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_FLAGS_HH__
diff --git a/base/stats/mysql.cc b/base/stats/mysql.cc
index 676bc555c..77366beb0 100644
--- a/base/stats/mysql.cc
+++ b/base/stats/mysql.cc
@@ -37,6 +37,7 @@
#include "base/statistics.hh"
#include "base/stats/flags.hh"
#include "base/stats/mysql.hh"
+#include "base/stats/mysql_run.hh"
#include "base/stats/statdb.hh"
#include "base/stats/types.hh"
#include "base/str.hh"
@@ -44,19 +45,35 @@
using namespace std;
-namespace Statistics {
+namespace Stats {
-struct MySqlData
+MySqlRun MySqlDB;
+
+bool
+MySqlConnected()
{
- map<int, int> idmap;
- MySQL::Connection conn;
-};
+ return MySqlDB.connected();
+}
+
+void
+MySqlRun::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &project)
+{
+ if (connected())
+ panic("can only get one database connection at this time!");
-int
-SetupRun(MySqlData *data, const string &name, const string &user,
- const string &project)
+ mysql.connect(host, user, passwd, db);
+ if (mysql.error)
+ panic("could not connect to database server\n%s\n", mysql.error);
+
+ remove(name);
+ cleanup();
+ setup(name, user, project);
+}
+
+void
+MySqlRun::setup(const string &name, const string &user, const string &project)
{
- MySQL::Connection &mysql = data->conn;
assert(mysql.connected());
stringstream insert;
@@ -71,13 +88,12 @@ SetupRun(MySqlData *data, const string &name, const string &user,
if (mysql.error)
panic("could not get a run\n%s\n", mysql.error);
- return mysql.insert_id();
+ run_id = mysql.insert_id();
}
void
-DeleteRun(MySqlData *data, const string &name)
+MySqlRun::remove(const string &name)
{
- MySQL::Connection &mysql = data->conn;
assert(mysql.connected());
stringstream sql;
ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name);
@@ -85,9 +101,8 @@ DeleteRun(MySqlData *data, const string &name)
}
void
-Cleanup(MySqlData *data)
+MySqlRun::cleanup()
{
- MySQL::Connection &mysql = data->conn;
assert(mysql.connected());
mysql.query("DELETE data "
@@ -119,6 +134,16 @@ Cleanup(MySqlData *data)
"FROM bins "
"LEFT JOIN data ON bn_id=dt_bin "
"WHERE dt_bin IS NULL");
+
+ mysql.query("DELETE events"
+ "FROM events"
+ "LEFT JOIN runs ON ev_run=rn_id"
+ "WHERE rn_id IS NULL");
+
+ mysql.query("DELETE event_names"
+ "FROM event_names"
+ "LEFT JOIN events ON en_id=ev_event"
+ "WHERE ev_event IS NULL");
}
void
@@ -142,9 +167,9 @@ SetupStat::init()
}
unsigned
-SetupStat::operator()(MySqlData *data)
+SetupStat::setup()
{
- MySQL::Connection &mysql = data->conn;
+ MySQL::Connection &mysql = MySqlDB.conn();
stringstream insert;
ccprintf(insert,
@@ -245,9 +270,9 @@ SetupStat::operator()(MySqlData *data)
}
unsigned
-SetupBin(MySqlData *data, const string &bin)
+SetupBin(const string &bin)
{
- MySQL::Connection &mysql = data->conn;
+ MySQL::Connection &mysql = MySqlDB.conn();
assert(mysql.connected());
using namespace MySQL;
@@ -292,8 +317,9 @@ void
InsertData::flush()
{
if (size) {
- assert(mysql && mysql->connected());
- mysql->query(query);
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ mysql.query(query);
}
query[0] = '\0';
@@ -319,7 +345,8 @@ InsertData::insert()
first = false;
size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
- stat, x, y, run, (unsigned long long)sample, bin, data);
+ stat, x, y, MySqlDB.run(), (unsigned long long)sample,
+ bin, data);
}
struct InsertSubData
@@ -330,13 +357,13 @@ struct InsertSubData
string name;
string descr;
- void operator()(MySqlData *data);
+ void setup();
};
void
-InsertSubData::operator()(MySqlData *data)
+InsertSubData::setup()
{
- MySQL::Connection &mysql = data->conn;
+ MySQL::Connection &mysql = MySqlDB.conn();
assert(mysql.connected());
stringstream insert;
ccprintf(insert,
@@ -348,10 +375,9 @@ InsertSubData::operator()(MySqlData *data)
}
void
-InsertFormula(MySqlData *data, uint16_t stat, uint16_t run,
- const string &formula)
+InsertFormula(uint16_t stat, const string &formula)
{
- MySQL::Connection &mysql = data->conn;
+ MySQL::Connection &mysql = MySqlDB.conn();
assert(mysql.connected());
stringstream insert_formula;
ccprintf(insert_formula,
@@ -363,15 +389,15 @@ InsertFormula(MySqlData *data, uint16_t stat, uint16_t run,
stringstream insert_ref;
ccprintf(insert_ref,
"INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
- stat, run);
+ stat, MySqlDB.run());
mysql.query(insert_ref);
}
void
-UpdatePrereq(MySqlData *data, uint16_t stat, uint16_t prereq)
+UpdatePrereq(uint16_t stat, uint16_t prereq)
{
- MySQL::Connection &mysql = data->conn;
+ MySQL::Connection &mysql = MySqlDB.conn();
assert(mysql.connected());
stringstream update;
ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
@@ -379,98 +405,6 @@ UpdatePrereq(MySqlData *data, uint16_t stat, uint16_t prereq)
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()
{
@@ -489,7 +423,7 @@ MySql::configure()
uint16_t prereq_id = find(data->prereq->id);
assert(stat_id && prereq_id);
- UpdatePrereq(mysql, stat_id, prereq_id);
+ UpdatePrereq(stat_id, prereq_id);
}
}
@@ -517,14 +451,14 @@ void
MySql::configure(const ScalarData &data)
{
configure(data, "SCALAR");
- insert(data.id, stat(mysql));
+ insert(data.id, stat.setup());
}
void
MySql::configure(const VectorData &data)
{
configure(data, "VECTOR");
- uint16_t statid = stat(mysql);
+ uint16_t statid = stat.setup();
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -536,7 +470,7 @@ MySql::configure(const VectorData &data)
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata(mysql);
+ subdata.setup();
}
}
@@ -553,7 +487,7 @@ MySql::configure(const DistData &data)
stat.max = data.data.max;
stat.bktsize = data.data.bucket_size;
}
- insert(data.id, stat(mysql));
+ insert(data.id, stat.setup());
}
void
@@ -568,7 +502,7 @@ MySql::configure(const VectorDistData &data)
stat.bktsize = data.data[0].bucket_size;
}
- uint16_t statid = stat(mysql);
+ uint16_t statid = stat.setup();
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -579,7 +513,7 @@ MySql::configure(const VectorDistData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata(mysql);
+ subdata.setup();
}
}
@@ -590,7 +524,7 @@ void
MySql::configure(const Vector2dData &data)
{
configure(data, "VECTOR2D");
- uint16_t statid = stat(mysql);
+ uint16_t statid = stat.setup();
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -601,7 +535,7 @@ MySql::configure(const Vector2dData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata(mysql);
+ subdata.setup();
}
}
@@ -614,7 +548,7 @@ MySql::configure(const Vector2dData &data)
subdata.y = i;
subdata.name = data.y_subnames[i];
if (!subdata.name.empty())
- subdata(mysql);
+ subdata.setup();
}
}
@@ -625,20 +559,26 @@ void
MySql::configure(const FormulaData &data)
{
configure(data, "FORMULA");
- insert(data.id, stat(mysql));
+ insert(data.id, stat.setup());
}
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);
+ newdata.bin = bin.empty() ? 0 : SetupBin(bin);
Database::stat_list_t::const_iterator i, end = Database::stats().end();
for (i = Database::stats().begin(); i != end; ++i)
(*i)->visit(*this);
}
+bool
+MySql::valid() const
+{
+ return MySqlDB.connected();
+}
+
void
MySql::output()
{
@@ -649,7 +589,6 @@ MySql::output()
configure();
// store sample #
- newdata.run = run_id;
newdata.sample = curTick;
if (bins().empty()) {
@@ -781,7 +720,7 @@ MySql::output(const Vector2dData &data)
void
MySql::output(const FormulaData &data)
{
- InsertFormula(mysql, find(data.id), run_id, data.str());
+ InsertFormula(find(data.id), data.str());
}
/*
@@ -841,4 +780,4 @@ MySql::visit(const FormulaData &data)
output(data);
}
-/* namespace Statistics */ }
+/* namespace Stats */ }
diff --git a/base/stats/mysql.hh b/base/stats/mysql.hh
index 4ff474752..4671b89dd 100644
--- a/base/stats/mysql.hh
+++ b/base/stats/mysql.hh
@@ -29,15 +29,17 @@
#ifndef __BASE_STATS_MYSQL_HH__
#define __BASE_STATS_MYSQL_HH__
+#include <map>
#include <string>
#include "base/stats/output.hh"
-namespace MySQL { class Connection; }
-namespace Statistics {
+namespace Stats {
class DistDataData;
-class MySqlData;
+class MySqlRun;
+bool MySqlConnected();
+extern MySqlRun MySqlDB;
struct SetupStat
{
@@ -58,7 +60,7 @@ struct SetupStat
uint16_t size;
void init();
- unsigned operator()(MySqlData *data);
+ unsigned setup();
};
class InsertData
@@ -70,14 +72,13 @@ class InsertData
static const int maxsize = 1024*1024;
public:
- MySQL::Connection *mysql;
+ MySqlRun *run;
public:
uint64_t sample;
double data;
uint16_t stat;
uint16_t bin;
- uint16_t run;
int16_t x;
int16_t y;
@@ -92,25 +93,28 @@ class InsertData
class MySql : public Output
{
protected:
- std::list<FormulaData *> formulas;
- MySqlData *mysql;
- bool configured;
- uint16_t run_id;
-
SetupStat stat;
InsertData newdata;
+ std::list<FormulaData *> formulas;
+ bool configured;
- void insert(int sim_id, int db_id);
- int find(int sim_id);
-
+ protected:
+ std::map<int, int> idmap;
+
+ void insert(int sim_id, int db_id)
+ {
+ using namespace std;
+ idmap.insert(make_pair(sim_id, db_id));
+ }
+
+ int find(int sim_id)
+ {
+ using namespace std;
+ map<int,int>::const_iterator i = idmap.find(sim_id);
+ assert(i != idmap.end());
+ return (*i).second;
+ }
public:
- 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);
@@ -144,6 +148,6 @@ class MySql : public Output
void configure(const FormulaData &data);
};
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_MYSQL_HH__
diff --git a/base/stats/mysql_run.hh b/base/stats/mysql_run.hh
new file mode 100644
index 000000000..0f8d84297
--- /dev/null
+++ b/base/stats/mysql_run.hh
@@ -0,0 +1,63 @@
+/*
+ * 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_STATS_MYSQL_RUN_HH__
+#define __BASE_STATS_MYSQL_RUN_HH__
+
+#include <string>
+
+#include "base/mysql.hh"
+#include "sim/host.hh"
+
+namespace Stats {
+
+struct MySqlRun
+{
+ private:
+ MySQL::Connection mysql;
+ uint16_t run_id;
+
+ public:
+ bool connected() const { return mysql.connected(); }
+ 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);
+
+ void setup(const std::string &name, const std::string &user,
+ const std::string &project);
+
+ void remove(const std::string &name);
+ void cleanup();
+
+ MySQL::Connection &conn() { return mysql; }
+ uint16_t run() const { return run_id; }
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_MYSQL_RUN_HH__
diff --git a/base/stats/output.hh b/base/stats/output.hh
index 9f1fbf415..186d7bab1 100644
--- a/base/stats/output.hh
+++ b/base/stats/output.hh
@@ -33,7 +33,7 @@
#include "base/stats/visit.hh"
-namespace Statistics {
+namespace Stats {
struct Output : public Visit
{
@@ -42,6 +42,6 @@ struct Output : public Visit
virtual bool valid() const = 0;
};
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_OUTPUT_HH__
diff --git a/base/stats/statdb.cc b/base/stats/statdb.cc
index f54272a50..cd5a095c0 100644
--- a/base/stats/statdb.cc
+++ b/base/stats/statdb.cc
@@ -34,7 +34,7 @@
using namespace std;
-namespace Statistics {
+namespace Stats {
namespace Database {
StatData *
@@ -86,4 +86,4 @@ TheDatabase &db()
}
/* namespace Database */ }
-/* namespace Statistics */ }
+/* namespace Stats */ }
diff --git a/base/stats/statdb.hh b/base/stats/statdb.hh
index fb672e1dc..6935a9aa0 100644
--- a/base/stats/statdb.hh
+++ b/base/stats/statdb.hh
@@ -36,7 +36,7 @@
class Python;
-namespace Statistics {
+namespace Stats {
class MainBin;
class StatData;
@@ -69,6 +69,6 @@ void regPrint(void *stat);
inline std::string name() { return "Statistics Database"; }
/* namespace Database */ }
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_STATDB_HH__
diff --git a/base/stats/text.cc b/base/stats/text.cc
index 0f43a1772..511dbe638 100644
--- a/base/stats/text.cc
+++ b/base/stats/text.cc
@@ -60,7 +60,7 @@ __nan()
}
#endif
-namespace Statistics {
+namespace Stats {
Text::Text()
: mystream(false), stream(NULL), compat(false), descriptions(false)
@@ -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);
@@ -282,14 +282,14 @@ VectorPrint::operator()(std::ostream &stream) const
print(stream);
}
- if (flags & ::Statistics::total) {
+ if (flags & ::Stats::total) {
print.name = base + "total";
print.desc = desc;
print.value = total;
print(stream);
}
} else {
- if (flags & ::Statistics::total) {
+ if (flags & ::Stats::total) {
print.value = total;
print(stream);
}
@@ -640,7 +640,7 @@ Text::visit(const Vector2dData &data)
print(*stream);
}
- if ((data.flags & ::Statistics::total) && (data.x > 1)) {
+ if ((data.flags & ::Stats::total) && (data.x > 1)) {
print.name = data.name;
print.desc = data.desc;
print.vec = tot_vec;
@@ -728,4 +728,4 @@ Text::visit(const FormulaData &data)
visit((const VectorData &)data);
}
-/* namespace Statistics */ }
+/* namespace Stats */ }
diff --git a/base/stats/text.hh b/base/stats/text.hh
index 89bddf0cb..88e32ff0a 100644
--- a/base/stats/text.hh
+++ b/base/stats/text.hh
@@ -34,7 +34,7 @@
#include "base/stats/output.hh"
-namespace Statistics {
+namespace Stats {
class Text : public Output
{
@@ -72,6 +72,6 @@ class Text : public Output
virtual void output();
};
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_TEXT_HH__
diff --git a/base/stats/types.hh b/base/stats/types.hh
index 4451c4e6e..dcfbd5fa9 100644
--- a/base/stats/types.hh
+++ b/base/stats/types.hh
@@ -32,7 +32,7 @@
#include <vector>
#include <inttypes.h>
-namespace Statistics {
+namespace Stats {
/** All counters are of 64-bit values. */
typedef double Counter;
@@ -44,6 +44,6 @@ typedef double Result;
/** vector of results. */
typedef std::vector<Result> VResult;
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_TYPES_HH__
diff --git a/base/stats/visit.cc b/base/stats/visit.cc
index fec11b262..88cd466b4 100644
--- a/base/stats/visit.cc
+++ b/base/stats/visit.cc
@@ -28,7 +28,7 @@
#include "base/stats/visit.hh"
-namespace Statistics {
+namespace Stats {
namespace Detail {
Visit::Visit()
@@ -38,4 +38,4 @@ Visit::~Visit()
{}
/* namespace Detail */ }
-/* namespace Statistics */ }
+/* namespace Stats */ }
diff --git a/base/stats/visit.hh b/base/stats/visit.hh
index a03842c52..3a46bb9ef 100644
--- a/base/stats/visit.hh
+++ b/base/stats/visit.hh
@@ -34,7 +34,7 @@
#include "base/time.hh"
#include "sim/host.hh"
-namespace Statistics {
+namespace Stats {
class StatData;
class ScalarData;
@@ -58,6 +58,6 @@ struct Visit
virtual void visit(const FormulaData &data) = 0;
};
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __BASE_STATS_VISIT_HH__
diff --git a/base/traceflags.py b/base/traceflags.py
index b7b7fa777..69f4e7ab8 100644
--- a/base/traceflags.py
+++ b/base/traceflags.py
@@ -100,6 +100,7 @@ baseFlags = [
'Chains',
'Dispatch',
'Stats',
+ 'StatEvents',
'Context',
'Config',
'Sampler',
diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc
index e00de8389..702a9afe8 100644
--- a/cpu/base_cpu.cc
+++ b/cpu/base_cpu.cc
@@ -130,6 +130,13 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
void
BaseCPU::regStats()
{
+ using namespace Stats;
+
+ numCycles
+ .name(name() + ".numCycles")
+ .desc("number of cpu cycles simulated")
+ ;
+
int size = execContexts.size();
if (size > 1) {
for (int i = 0; i < size; ++i) {
diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh
index 648035732..9c4026784 100644
--- a/cpu/base_cpu.hh
+++ b/cpu/base_cpu.hh
@@ -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
+ Stats::Scalar<> numCycles;
};
#endif // __BASE_CPU_HH__
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index 832a621f8..0d3a80fe7 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -129,7 +129,7 @@ ExecContext::serialize(ostream &os)
SERIALIZE_SCALAR(ctx);
}
if (system->bin) {
- Statistics::MainBin *cur = Statistics::MainBin::curBin();
+ Stats::MainBin *cur = Stats::MainBin::curBin();
string bin_name = cur->name();
SERIALIZE_SCALAR(bin_name);
}
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index 5d608976d..1d745724f 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -186,7 +186,7 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
void
MemTest::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
numReadsStat
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index f2409d54c..4bde5c066 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -111,9 +111,9 @@ class MemTest : public BaseCPU
Tick noResponseCycles;
uint64_t numReads;
- Statistics::Scalar<> numReadsStat;
- Statistics::Scalar<> numWritesStat;
- Statistics::Scalar<> numCopiesStat;
+ Stats::Scalar<> numReadsStat;
+ Stats::Scalar<> numWritesStat;
+ Stats::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process()
void completeRequest(MemReqPtr &req, uint8_t *data);
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index 05b88b04b..e1a861ad8 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -42,6 +42,7 @@
#include "base/pollevent.hh"
#include "base/range.hh"
#include "base/trace.hh"
+#include "base/stats/events.hh"
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
@@ -50,7 +51,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"
@@ -255,7 +255,7 @@ SimpleCPU::haltContext(int thread_num)
void
SimpleCPU::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
BaseCPU::regStats();
@@ -287,8 +287,6 @@ SimpleCPU::regStats()
;
idleFraction = constant(1.0) - notIdleFraction;
- numInsts = Statistics::scalar(numInst) - Statistics::scalar(startNumInst);
- simInsts += numInsts;
}
void
@@ -405,6 +403,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
}
}
+ if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+ Stats::recordEvent("Uncached Read");
+
return fault;
}
@@ -490,6 +491,9 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
if (res && (fault == No_Fault))
*res = memReq->result;
+ if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+ Stats::recordEvent("Uncached Write");
+
return fault;
}
@@ -581,7 +585,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 +593,8 @@ SimpleCPU::post_interrupt(int int_num, int index)
void
SimpleCPU::tick()
{
+ numCycles++;
+
traceData = NULL;
Fault fault = No_Fault;
@@ -697,6 +702,7 @@ SimpleCPU::tick()
// keep an instruction count
numInst++;
+ numInsts++;
// check for instruction-count-based events
comInstEventQueue[0]->serviceEvents(numInst);
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 4977e6992..1c6b18d03 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -34,7 +34,8 @@
#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
#include "base/statistics.hh"
-
+#include "cpu/exec_context.hh"
+#include "cpu/static_inst.hh"
// forward declarations
#ifdef FULL_SYSTEM
@@ -46,6 +47,11 @@ class PhysicalMemory;
class RemoteGDB;
class GDBListener;
+
+#else
+
+class Process;
+
#endif // FULL_SYSTEM
class MemInterface;
@@ -204,25 +210,30 @@ class SimpleCPU : public BaseCPU
// number of simulated instructions
Counter numInst;
Counter startNumInst;
- Statistics::Formula numInsts;
+ Stats::Scalar<> numInsts;
+
+ virtual Counter totalInstructions() const
+ {
+ return numInst - startNumInst;
+ }
// number of simulated memory references
- Statistics::Scalar<> numMemRefs;
+ Stats::Scalar<> numMemRefs;
// number of simulated loads
Counter numLoad;
Counter startNumLoad;
// number of idle cycles
- Statistics::Average<> notIdleFraction;
- Statistics::Formula idleFraction;
+ Stats::Average<> notIdleFraction;
+ Stats::Formula idleFraction;
// number of cycles stalled for I-cache misses
- Statistics::Scalar<> icacheStallCycles;
+ Stats::Scalar<> icacheStallCycles;
Counter lastIcacheStall;
// number of cycles stalled for D-cache misses
- Statistics::Scalar<> dcacheStallCycles;
+ Stats::Scalar<> dcacheStallCycles;
Counter lastDcacheStall;
void processCacheCompletion();
@@ -251,37 +262,71 @@ class SimpleCPU : public BaseCPU
Fault copy(Addr dest);
- uint64_t readIntReg(int reg_idx) { return xc->readIntReg(reg_idx); }
+ // The register accessor methods provide the index of the
+ // instruction's operand (e.g., 0 or 1), not the architectural
+ // register index, to simplify the implementation of register
+ // renaming. We find the architectural register index by indexing
+ // into the instruction's own operand index table. Note that a
+ // raw pointer to the StaticInst is provided instead of a
+ // ref-counted StaticInstPtr to redice overhead. This is fine as
+ // long as these methods don't copy the pointer into any long-term
+ // storage (which is pretty hard to imagine they would have reason
+ // to do).
+
+ uint64_t readIntReg(StaticInst<TheISA> *si, int idx)
+ {
+ return xc->readIntReg(si->srcRegIdx(idx));
+ }
- float readFloatRegSingle(int reg_idx)
- { return xc->readFloatRegSingle(reg_idx); }
+ float readFloatRegSingle(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegSingle(reg_idx);
+ }
- double readFloatRegDouble(int reg_idx)
- { return xc->readFloatRegDouble(reg_idx); }
+ double readFloatRegDouble(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegDouble(reg_idx);
+ }
- uint64_t readFloatRegInt(int reg_idx)
- { return xc->readFloatRegInt(reg_idx); }
+ uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegInt(reg_idx);
+ }
- void setIntReg(int reg_idx, uint64_t val)
- { return xc->setIntReg(reg_idx, val); }
+ void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val)
+ {
+ xc->setIntReg(si->destRegIdx(idx), val);
+ }
- void setFloatRegSingle(int reg_idx, float val)
- { return xc->setFloatRegSingle(reg_idx, val); }
+ void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegSingle(reg_idx, val);
+ }
- void setFloatRegDouble(int reg_idx, double val)
- { return xc->setFloatRegDouble(reg_idx, val); }
+ void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegDouble(reg_idx, val);
+ }
- void setFloatRegInt(int reg_idx, uint64_t val)
- { return xc->setFloatRegInt(reg_idx, val); }
+ void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegInt(reg_idx, val);
+ }
uint64_t readPC() { return xc->readPC(); }
- void setNextPC(uint64_t val) { return xc->setNextPC(val); }
+ void setNextPC(uint64_t val) { xc->setNextPC(val); }
uint64_t readUniq() { return xc->readUniq(); }
- void setUniq(uint64_t val) { return xc->setUniq(val); }
+ void setUniq(uint64_t val) { xc->setUniq(val); }
uint64_t readFpcr() { return xc->readFpcr(); }
- void setFpcr(uint64_t val) { return xc->setFpcr(val); }
+ void setFpcr(uint64_t val) { xc->setFpcr(val); }
#ifdef FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
@@ -290,7 +335,7 @@ class SimpleCPU : public BaseCPU
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); }
+ void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
@@ -300,6 +345,4 @@ class SimpleCPU : public BaseCPU
ExecContext *xcBase() { return xc; }
};
-typedef SimpleCPU SimpleCPUExecContext;
-
#endif // __SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 131c5f756..3eeefb675 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -42,11 +42,8 @@
// forward declarations
class ExecContext;
class DynInst;
-typedef DynInst FullCPUExecContext;
class FastCPU;
-typedef FastCPU FastCPUExecContext;
class SimpleCPU;
-typedef SimpleCPU SimpleCPUExecContext;
class SymbolTable;
namespace Trace {
@@ -110,11 +107,13 @@ class StaticInstBase : public RefCounted
IsThreadSync, ///< Thread synchronization operation.
- IsSerializing, ///< Serializes pipeline: won't until all
+ IsSerializing, ///< Serializes pipeline: won't execute until all
/// older instructions have committed.
IsMemBarrier, ///< Is a memory barrier
IsWriteBarrier, ///< Is a write barrier
+ IsNonSpeculative, ///< Should not be executed speculatively
+
NumFlags
};
@@ -196,6 +195,7 @@ class StaticInstBase : public RefCounted
bool isSerializing() const { return flags[IsSerializing]; }
bool isMemBarrier() const { return flags[IsMemBarrier]; }
bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
+ bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
//@}
/// Operation class. Used to select appropriate function unit in issue.
@@ -251,7 +251,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
@@ -259,7 +260,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;
@@ -309,20 +311,17 @@ 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 FastCPU model.
*/
- virtual Fault execute(FastCPUExecContext *xc,
- Trace::InstRecord *traceData) = 0;
+ virtual Fault execute(FastCPU *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.
diff --git a/kern/system_events.cc b/kern/system_events.cc
new file mode 100644
index 000000000..011dbce5f
--- /dev/null
+++ b/kern/system_events.cc
@@ -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);
+}
diff --git a/kern/system_events.hh b/kern/system_events.hh
new file mode 100644
index 000000000..dba3f326c
--- /dev/null
+++ b/kern/system_events.hh
@@ -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;
+ Stats::MainBin *myBin;
+};
+
+#endif // __SYSTEM_EVENTS_HH__
diff --git a/kern/tru64/mbuf.hh b/kern/tru64/mbuf.hh
index bfee0b3fa..a386fa611 100644
--- a/kern/tru64/mbuf.hh
+++ b/kern/tru64/mbuf.hh
@@ -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__
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index 17a5e406a..89b808653 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -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"
-
-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);
+#include "mem/functional_mem/memory_control.hh"
- 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);
-}
diff --git a/kern/tru64/tru64_events.hh b/kern/tru64/tru64_events.hh
index 96e6a8b26..bcf33d686 100644
--- a/kern/tru64/tru64_events.hh
+++ b/kern/tru64/tru64_events.hh
@@ -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__
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index 3eed78cdf..0717bcbbe 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -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;
@@ -162,33 +163,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")
- ;
}
//
}
@@ -212,14 +194,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
@@ -260,45 +234,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;
diff --git a/kern/tru64/tru64_system.hh b/kern/tru64/tru64_system.hh
index 34569664d..144febbf9 100644
--- a/kern/tru64/tru64_system.hh
+++ b/kern/tru64/tru64_system.hh
@@ -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__
diff --git a/sim/debug.cc b/sim/debug.cc
index 09c604a95..b73ab4245 100644
--- a/sim/debug.cc
+++ b/sim/debug.cc
@@ -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
diff --git a/sim/debug.hh b/sim/debug.hh
index eb0be772e..a4f8b8702 100644
--- a/sim/debug.hh
+++ b/sim/debug.hh
@@ -29,6 +29,10 @@
#ifndef __DEBUG_HH__
#define __DEBUG_HH__
+#ifdef DEBUG
void debug_break();
+#else
+inline void debug_break() { }
+#endif
#endif // __DEBUG_HH__
diff --git a/sim/main.cc b/sim/main.cc
index 8861f3ef0..032a05668 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -236,7 +236,7 @@ main(int argc, char **argv)
sayHello(cerr);
// Initialize statistics database
- Statistics::InitSimStats();
+ Stats::InitSimStats();
vector<char *> cppArgs;
@@ -390,10 +390,10 @@ main(int argc, char **argv)
#endif
// Check to make sure that the stats package is properly initialized
- Statistics::check();
+ Stats::check();
// Reset to put the stats in a consistent state.
- Statistics::reset();
+ Stats::reset();
// Nothing to simulate if we don't have at least one CPU somewhere.
if (BaseCPU::numSimulatedCPUs() == 0) {
@@ -418,14 +418,14 @@ main(int argc, char **argv)
if (async_dump) {
async_dump = false;
- using namespace Statistics;
+ using namespace Stats;
SetupEvent(Dump, curTick);
}
if (async_dumpreset) {
async_dumpreset = false;
- using namespace Statistics;
+ using namespace Stats;
SetupEvent(Dump | Reset, curTick);
}
diff --git a/sim/process.cc b/sim/process.cc
index c6b497343..65cb8409f 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -95,7 +95,7 @@ Process::Process(const string &name,
void
Process::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
num_syscalls
.name(name() + ".PROG:num_syscalls")
diff --git a/sim/process.hh b/sim/process.hh
index b23302b8f..d235f0ef1 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -98,7 +98,7 @@ class Process : public SimObject
std::string prog_fname; // file name
Addr prog_entry; // entry point (initial PC)
- Statistics::Scalar<> num_syscalls; // number of syscalls executed
+ Stats::Scalar<> num_syscalls; // number of syscalls executed
protected:
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
index 9626c54ea..7f756858c 100644
--- a/sim/sim_object.cc
+++ b/sim/sim_object.cc
@@ -120,7 +120,7 @@ SimObject::regAllStats()
(*i)->regFormulas();
}
- Statistics::registerResetCallback(&StatResetCB);
+ Stats::registerResetCallback(&StatResetCB);
}
//
diff --git a/sim/stat_control.cc b/sim/stat_control.cc
index d6d7e2c91..28ee348b5 100644
--- a/sim/stat_control.cc
+++ b/sim/stat_control.cc
@@ -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"
@@ -46,16 +47,17 @@
using namespace std;
-Statistics::Formula hostInstRate;
-Statistics::Formula hostMemory;
-Statistics::Formula hostSeconds;
-Statistics::Formula hostTickRate;
+Stats::Formula hostInstRate;
+Stats::Formula hostTickRate;
+Stats::Value hostMemory;
+Stats::Value hostSeconds;
-Statistics::Formula simInsts;
-Statistics::Formula simSeconds;
-Statistics::Formula simTicks;
+Stats::Value simTicks;
+Stats::Value simInsts;
+Stats::Value simFreq;
+Stats::Formula simSeconds;
-namespace Statistics {
+namespace Stats {
Time statTime(true);
Tick startTick;
@@ -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;
@@ -165,10 +173,10 @@ StatEvent::description()
void
StatEvent::process()
{
- if (flags & Statistics::Dump)
+ if (flags & Stats::Dump)
DumpNow();
- if (flags & Statistics::Reset)
+ if (flags & Stats::Reset)
reset();
if (repeat)
@@ -197,11 +205,11 @@ SetupEvent(int flags, Tick when, Tick repeat)
new StatEvent(flags, when, repeat);
}
-/* namespace Statistics */ }
+/* namespace Stats */ }
extern "C" void
debugDumpStats()
{
- Statistics::DumpNow();
+ Stats::DumpNow();
}
diff --git a/sim/stat_control.hh b/sim/stat_control.hh
index 9a5e269e1..56170dc77 100644
--- a/sim/stat_control.hh
+++ b/sim/stat_control.hh
@@ -32,7 +32,7 @@
#include <fstream>
#include <list>
-namespace Statistics {
+namespace Stats {
enum {
Reset = 0x1,
@@ -47,6 +47,6 @@ void SetupEvent(int flags, Tick when, Tick repeat = 0);
void InitSimStats();
-/* namespace Statistics */ }
+/* namespace Stats */ }
#endif // __SIM_STAT_CONTROL_HH__
diff --git a/sim/stats.hh b/sim/stats.hh
index b736850e7..218036eb6 100644
--- a/sim/stats.hh
+++ b/sim/stats.hh
@@ -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 Stats::Formula simSeconds;
+extern Stats::Value simTicks;
#endif // __SIM_SIM_STATS_HH__
diff --git a/sim/system.cc b/sim/system.cc
index 43f43baec..619593abd 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -30,6 +30,7 @@
#include "targetarch/vtophys.hh"
#include "sim/param.hh"
#include "sim/system.hh"
+#include "base/trace.hh"
using namespace std;
@@ -41,19 +42,47 @@ 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);
if (bin == true) {
- Kernel = new Statistics::MainBin("non TCPIP Kernel stats");
+ Kernel = new Stats::MainBin("non TCPIP Kernel stats");
Kernel->activate();
- User = new Statistics::MainBin("User stats");
+ User = new Stats::MainBin("User stats");
+
+ int end = binned_fns.size();
+ assert(!(end & 1));
+
+ Stats::MainBin *Bin;
+
+ fnEvents.resize(end>>1);
+
+ for (int i = 0; i < end; i +=2) {
+ Bin = new Stats::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,10 +139,49 @@ printSystems()
System::printSystems();
}
-Statistics::MainBin *
+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());
+ }
+ }
+}
+
+Stats::MainBin *
System::getBin(const std::string &name)
{
- std::map<const std::string, Statistics::MainBin *>::const_iterator i;
+ std::map<const std::string, Stats::MainBin *>::const_iterator i;
i = fnBins.find(name);
if (i == fnBins.end())
panic("trying to getBin %s that is not on system map!", name);
diff --git a/sim/system.hh b/sim/system.hh
index 050d1dd11..b83945884 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -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"
@@ -48,17 +49,20 @@ class ExecContext;
class System : public SimObject
{
// lisa's binning stuff
- protected:
- std::map<const std::string, Statistics::MainBin *> fnBins;
+ private:
+ std::map<const std::string, Stats::MainBin *> fnBins;
std::map<const Addr, SWContext *> swCtxMap;
+ protected:
+ std::vector<FnEvent *> fnEvents;
+
public:
- Statistics::Scalar<> fnCalls;
- Statistics::MainBin *Kernel;
- Statistics::MainBin *User;
+ Stats::Scalar<> fnCalls;
+ Stats::MainBin *Kernel;
+ Stats::MainBin *User;
- Statistics::MainBin * getBin(const std::string &name);
- virtual bool findCaller(std::string, std::string) const = 0;
+ Stats::MainBin * getBin(const std::string &name);
+ bool findCaller(std::string, std::string) const;
SWContext *findContext(Addr pcb);
bool addContext(Addr pcb, SWContext *ctx) {
@@ -68,18 +72,23 @@ 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;
MemoryController *memCtrl;
PhysicalMemory *physmem;
bool bin;
+ std::vector<string> binned_fns;
PCEventQueue pcEventQueue;
@@ -90,7 +99,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;
diff --git a/test/Makefile b/test/Makefile
index bf4200ba3..15019a1f5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -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
diff --git a/test/stattest.cc b/test/stattest.cc
index 7bf355c0e..1a035859a 100644
--- a/test/stattest.cc
+++ b/test/stattest.cc
@@ -41,7 +41,7 @@
#include "sim/host.hh"
using namespace std;
-using namespace Statistics;
+using namespace Stats;
Tick curTick = 0;
Tick ticksPerSecond = ULL(2000000000);
@@ -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);