summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xSConstruct21
-rw-r--r--ext/libelf/SConscript2
-rwxr-xr-xsrc/SConscript5
-rw-r--r--src/arch/alpha/tlb.cc4
-rw-r--r--src/arch/alpha/tlb.hh2
-rw-r--r--src/arch/arm/insts/static_inst.hh1
-rw-r--r--src/arch/arm/insts/vfp.hh3
-rw-r--r--src/arch/arm/isa.cc53
-rw-r--r--src/arch/arm/isa/formats/m5ops.isa1
-rw-r--r--src/arch/arm/isa/insts/m5ops.isa20
-rw-r--r--src/arch/arm/isa/insts/misc.isa8
-rw-r--r--src/arch/arm/isa/templates/basic.isa2
-rw-r--r--src/arch/arm/miscregs.cc2
-rw-r--r--src/arch/arm/table_walker.cc25
-rw-r--r--src/arch/arm/table_walker.hh5
-rw-r--r--src/arch/arm/tlb.cc20
-rw-r--r--src/arch/arm/tlb.hh9
-rw-r--r--src/arch/arm/utility.cc5
-rw-r--r--src/arch/generic/memhelpers.hh4
-rw-r--r--src/arch/mips/faults.cc2
-rw-r--r--src/arch/mips/faults.hh2
-rw-r--r--src/arch/x86/bios/acpi.hh8
-rw-r--r--src/arch/x86/bios/intelmp.cc2
-rw-r--r--src/arch/x86/bios/intelmp.hh24
-rw-r--r--src/arch/x86/bios/smbios.hh6
-rw-r--r--src/base/fast_alloc.cc4
-rw-r--r--src/base/output.hh14
-rw-r--r--src/base/range_map.hh2
-rw-r--r--src/base/remote_gdb.hh2
-rw-r--r--src/base/stl_helpers.hh4
-rw-r--r--src/cpu/BaseCPU.py6
-rw-r--r--src/cpu/CheckerCPU.py2
-rw-r--r--src/cpu/DummyChecker.py42
-rw-r--r--src/cpu/SConscript2
-rw-r--r--src/cpu/base.cc43
-rw-r--r--src/cpu/base.hh10
-rw-r--r--src/cpu/base_dyn_inst.hh84
-rw-r--r--src/cpu/base_dyn_inst_impl.hh11
-rw-r--r--src/cpu/checker/cpu.cc363
-rw-r--r--src/cpu/checker/cpu.hh128
-rw-r--r--src/cpu/checker/cpu_impl.hh539
-rw-r--r--src/cpu/checker/thread_context.hh106
-rw-r--r--src/cpu/dummy_checker_builder.cc97
-rw-r--r--src/cpu/func_unit.hh6
-rw-r--r--src/cpu/inorder/cpu.cc12
-rw-r--r--src/cpu/inorder/cpu.hh8
-rw-r--r--src/cpu/inorder/resource.cc2
-rw-r--r--src/cpu/inorder/resource.hh12
-rw-r--r--src/cpu/inorder/resource_pool.cc2
-rw-r--r--src/cpu/inorder/resource_pool.hh2
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh3
-rw-r--r--src/cpu/inorder/thread_context.cc4
-rw-r--r--src/cpu/nativetrace.hh2
-rw-r--r--src/cpu/o3/O3CPU.py10
-rw-r--r--src/cpu/o3/O3Checker.py2
-rw-r--r--src/cpu/o3/bpred_unit.hh2
-rw-r--r--src/cpu/o3/checker_builder.cc31
-rw-r--r--src/cpu/o3/commit.hh4
-rw-r--r--src/cpu/o3/commit_impl.hh13
-rw-r--r--src/cpu/o3/cpu.cc14
-rw-r--r--src/cpu/o3/cpu.hh6
-rw-r--r--src/cpu/o3/decode.hh2
-rw-r--r--src/cpu/o3/decode_impl.hh4
-rw-r--r--src/cpu/o3/dyn_inst_impl.hh8
-rw-r--r--src/cpu/o3/fetch.hh2
-rw-r--r--src/cpu/o3/fetch_impl.hh8
-rw-r--r--src/cpu/o3/fu_pool.cc2
-rw-r--r--src/cpu/o3/fu_pool.hh3
-rw-r--r--src/cpu/o3/iew.hh5
-rw-r--r--src/cpu/o3/iew_impl.hh16
-rw-r--r--src/cpu/o3/inst_queue.hh4
-rw-r--r--src/cpu/o3/inst_queue_impl.hh4
-rw-r--r--src/cpu/o3/lsq.hh2
-rw-r--r--src/cpu/o3/lsq_unit.hh2
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh14
-rw-r--r--src/cpu/o3/mem_dep_unit.cc8
-rw-r--r--src/cpu/o3/mem_dep_unit.hh2
-rw-r--r--src/cpu/o3/rename.hh2
-rw-r--r--src/cpu/o3/sat_counter.hh3
-rwxr-xr-xsrc/cpu/o3/thread_context.hh21
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh17
-rw-r--r--src/cpu/quiesce_event.hh3
-rw-r--r--src/cpu/sched_list.hh180
-rw-r--r--src/cpu/simple/BaseSimpleCPU.py9
-rw-r--r--src/cpu/simple/atomic.cc6
-rw-r--r--src/cpu/simple/atomic.hh4
-rw-r--r--src/cpu/simple/base.cc25
-rw-r--r--src/cpu/simple/base.hh27
-rw-r--r--src/cpu/simple/timing.cc6
-rw-r--r--src/cpu/simple/timing.hh4
-rw-r--r--src/cpu/simple_thread.cc25
-rw-r--r--src/cpu/simple_thread.hh37
-rw-r--r--src/cpu/static_inst.hh2
-rw-r--r--src/cpu/thread_context.hh29
-rw-r--r--src/cpu/thread_state.hh2
-rw-r--r--src/dev/alpha/tsunami_cchip.cc1
-rw-r--r--src/dev/alpha/tsunami_io.cc6
-rw-r--r--src/dev/arm/pl111.cc9
-rw-r--r--src/dev/arm/pl111.hh4
-rw-r--r--src/dev/copy_engine.cc1
-rw-r--r--src/dev/disk_image.cc6
-rw-r--r--src/dev/disk_image.hh2
-rw-r--r--src/dev/ide_ctrl.cc5
-rw-r--r--src/dev/ns_gige.cc42
-rw-r--r--src/dev/pciconfigall.cc2
-rw-r--r--src/dev/pcidev.cc4
-rw-r--r--src/mem/bus.cc3
-rw-r--r--src/mem/cache/base.cc9
-rw-r--r--src/mem/cache/base.hh11
-rw-r--r--src/mem/cache/cache_impl.hh2
-rw-r--r--src/mem/cache/tags/iic.cc2
-rw-r--r--src/mem/cache/tags/iic_repl/gen.cc2
-rw-r--r--src/mem/cache/tags/iic_repl/gen.hh2
-rw-r--r--src/mem/cache/tags/iic_repl/repl.hh2
-rw-r--r--src/mem/packet.hh2
-rw-r--r--src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc11
-rw-r--r--src/mem/ruby/system/Sequencer.hh2
-rw-r--r--src/python/m5/SimObject.py2
-rw-r--r--src/sim/core.hh2
-rw-r--r--src/sim/process.cc4
-rw-r--r--src/sim/process.hh4
-rw-r--r--src/sim/process_impl.hh2
-rw-r--r--src/sim/pseudo_inst.cc45
-rw-r--r--src/sim/pseudo_inst.hh2
-rw-r--r--src/sim/serialize.cc7
-rw-r--r--src/sim/sim_object.cc2
-rw-r--r--src/sim/sim_object.hh3
-rw-r--r--src/sim/syscall_emul.hh56
-rw-r--r--util/m5/m5.c43
-rw-r--r--util/m5/m5op.h1
-rw-r--r--util/m5/m5op_arm.S2
-rw-r--r--util/m5/m5ops.h1
132 files changed, 1717 insertions, 907 deletions
diff --git a/SConstruct b/SConstruct
index 4ea8ad788..62d90b359 100755
--- a/SConstruct
+++ b/SConstruct
@@ -473,7 +473,8 @@ CXX_V = readCommand([main['CXX'],'-V'], exception=False)
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
main['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
-if main['GCC'] + main['SUNCC'] + main['ICC'] > 1:
+main['CLANG'] = CXX_V and CXX_V.find('clang') >= 0
+if main['GCC'] + main['SUNCC'] + main['ICC'] + main['CLANG'] > 1:
print 'Error: How can we have two at the same time?'
Exit(1)
@@ -501,6 +502,24 @@ elif main['SUNCC']:
main.Append(CCFLAGS=['-library=stlport4'])
main.Append(CCFLAGS=['-xar'])
#main.Append(CCFLAGS=['-instances=semiexplicit'])
+elif main['CLANG']:
+ clang_version_re = re.compile(".* version (\d+\.\d+)")
+ clang_version_match = clang_version_re.match(CXX_version)
+ if (clang_version_match):
+ clang_version = clang_version_match.groups()[0]
+ if compareVersions(clang_version, "2.9") < 0:
+ print 'Error: clang version 2.9 or newer required.'
+ print ' Installed version:', clang_version
+ Exit(1)
+ else:
+ print 'Error: Unable to determine clang version.'
+ Exit(1)
+
+ main.Append(CCFLAGS=['-pipe'])
+ main.Append(CCFLAGS=['-fno-strict-aliasing'])
+ main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
+ main.Append(CCFLAGS=['-Wno-tautological-compare'])
+ main.Append(CCFLAGS=['-Wno-self-assign'])
else:
print 'Error: Don\'t know what compiler options to use for your compiler.'
print ' Please fix SConstruct and src/SConscript and try again.'
diff --git a/ext/libelf/SConscript b/ext/libelf/SConscript
index 7f33990d8..5e92fe08b 100644
--- a/ext/libelf/SConscript
+++ b/ext/libelf/SConscript
@@ -94,6 +94,8 @@ if m4env['GCC']:
major,minor,dot = [int(x) for x in m4env['GCC_VERSION'].split('.')]
if major >= 4:
m4env.Append(CCFLAGS=['-Wno-pointer-sign'])
+if m4env['CLANG']:
+ m4env.Append(CCFLAGS=['-Wno-initializer-overrides', '-Wno-pointer-sign'])
m4env.Append(CCFLAGS=['-Wno-implicit'])
del m4env['CPPPATH']
diff --git a/src/SConscript b/src/SConscript
index 7fb03e821..679403020 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -854,6 +854,9 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
swig_env.Append(CCFLAGS='-Wno-unused-label')
if compareVersions(env['GCC_VERSION'], '4.6.0') != -1:
swig_env.Append(CCFLAGS='-Wno-unused-but-set-variable')
+ if env['CLANG']:
+ swig_env.Append(CCFLAGS=['-Wno-unused-label'])
+
werror_env = new_env.Clone()
werror_env.Append(CCFLAGS='-Werror')
@@ -928,7 +931,7 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
# Debug binary
ccflags = {}
-if env['GCC']:
+if env['GCC'] or env['CLANG']:
if sys.platform == 'sunos5':
ccflags['debug'] = '-gstabs+'
else:
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index 623eafb8a..f1199b9b6 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -64,7 +64,7 @@ TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), nlu(0)
{
table = new TlbEntry[size];
- memset(table, 0, sizeof(TlbEntry[size]));
+ memset(table, 0, sizeof(TlbEntry) * size);
flushCache();
}
@@ -280,7 +280,7 @@ void
TLB::flushAll()
{
DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(TlbEntry[size]));
+ memset(table, 0, sizeof(TlbEntry) * size);
flushCache();
lookupTable.clear();
nlu = 0;
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
index b6261769f..1d4b6c6f8 100644
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -49,7 +49,7 @@ class ThreadContext;
namespace AlphaISA {
-class TlbEntry;
+struct TlbEntry;
class TLB : public BaseTLB
{
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index d65555822..c36024ecd 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -46,6 +46,7 @@
#include "arch/arm/utility.hh"
#include "base/trace.hh"
#include "cpu/static_inst.hh"
+#include "sim/byteswap.hh"
#include "sim/full_system.hh"
namespace ArmISA
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh
index 57b74d040..b3582a351 100644
--- a/src/arch/arm/insts/vfp.hh
+++ b/src/arch/arm/insts/vfp.hh
@@ -107,6 +107,9 @@ enum VfpRoundingMode
VfpRoundZero = 3
};
+static inline float bitsToFp(uint64_t, float);
+static inline uint32_t fpToBits(float);
+
template <class fpType>
static inline bool
flushToZero(fpType &op)
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index b504550a1..5c2478946 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -39,12 +39,17 @@
*/
#include "arch/arm/isa.hh"
+#include "config/use_checker.hh"
#include "debug/Arm.hh"
#include "debug/MiscRegs.hh"
#include "sim/faults.hh"
#include "sim/stat_control.hh"
#include "sim/system.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif
+
namespace ArmISA
{
@@ -279,7 +284,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
PCState pc = tc->pcState();
pc.nextThumb(cpsr.t);
pc.nextJazelle(cpsr.j);
+#if USE_CHECKER
+ tc->pcStateNoRecord(pc);
+#else
tc->pcState(pc);
+#endif //USE_CHECKER
} else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
misc_reg < MISCREG_CP15_END) {
panic("Unimplemented CP15 register %s wrote with %#x.\n",
@@ -382,6 +391,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
oc = sys->getThreadContext(x);
oc->getDTBPtr()->allCpusCaching();
oc->getITBPtr()->allCpusCaching();
+#if USE_CHECKER
+ CheckerCPU *checker =
+ dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
+ if (checker) {
+ checker->getDTBPtr()->allCpusCaching();
+ checker->getITBPtr()->allCpusCaching();
+ }
+#endif
}
return;
}
@@ -399,6 +416,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
assert(oc->getITBPtr() && oc->getDTBPtr());
oc->getITBPtr()->flushAll();
oc->getDTBPtr()->flushAll();
+#if USE_CHECKER
+ CheckerCPU *checker =
+ dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
+ if (checker) {
+ checker->getITBPtr()->flushAll();
+ checker->getDTBPtr()->flushAll();
+ }
+#endif
}
return;
case MISCREG_ITLBIALL:
@@ -417,6 +442,16 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
bits(newVal, 7,0));
oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
bits(newVal, 7,0));
+#if USE_CHECKER
+ CheckerCPU *checker =
+ dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
+ if (checker) {
+ checker->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ checker->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ }
+#endif
}
return;
case MISCREG_TLBIASIDIS:
@@ -427,6 +462,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
assert(oc->getITBPtr() && oc->getDTBPtr());
oc->getITBPtr()->flushAsid(bits(newVal, 7,0));
oc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
+#if USE_CHECKER
+ CheckerCPU *checker =
+ dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
+ if (checker) {
+ checker->getITBPtr()->flushAsid(bits(newVal, 7,0));
+ checker->getDTBPtr()->flushAsid(bits(newVal, 7,0));
+ }
+#endif
}
return;
case MISCREG_TLBIMVAAIS:
@@ -437,6 +480,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
assert(oc->getITBPtr() && oc->getDTBPtr());
oc->getITBPtr()->flushMva(mbits(newVal, 31,12));
oc->getDTBPtr()->flushMva(mbits(newVal, 31,12));
+#if USE_CHECKER
+ CheckerCPU *checker =
+ dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
+ if (checker) {
+ checker->getITBPtr()->flushMva(mbits(newVal, 31,12));
+ checker->getDTBPtr()->flushMva(mbits(newVal, 31,12));
+ }
+#endif
}
return;
case MISCREG_ITLBIMVA:
diff --git a/src/arch/arm/isa/formats/m5ops.isa b/src/arch/arm/isa/formats/m5ops.isa
index 3b08acad7..1eb7d3f65 100644
--- a/src/arch/arm/isa/formats/m5ops.isa
+++ b/src/arch/arm/isa/formats/m5ops.isa
@@ -59,6 +59,7 @@ def format M5ops() {{
case 0x41: return new Dumpstats(machInst);
case 0x42: return new Dumpresetstats(machInst);
case 0x43: return new M5checkpoint(machInst);
+ case 0x4F: return new M5writefile(machInst);
case 0x50: return new M5readfile(machInst);
case 0x51: return new M5break(machInst);
case 0x52: return new M5switchcpu(machInst);
diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa
index da2e10886..a32bf6dfc 100644
--- a/src/arch/arm/isa/insts/m5ops.isa
+++ b/src/arch/arm/isa/insts/m5ops.isa
@@ -243,7 +243,7 @@ let {{
m5checkpointIop = InstObjParams("m5checkpoint", "M5checkpoint", "PredOp",
{ "code": m5checkpoint_code,
"predicate_test": predicateTest },
- ["IsNonSpeculative"])
+ ["IsNonSpeculative", "IsUnverifiable"])
header_output += BasicDeclare.subst(m5checkpointIop)
decoder_output += BasicConstructor.subst(m5checkpointIop)
exec_output += PredOpExecute.subst(m5checkpointIop)
@@ -256,11 +256,27 @@ let {{
m5readfileIop = InstObjParams("m5readfile", "M5readfile", "PredOp",
{ "code": m5readfileCode,
"predicate_test": predicateTest },
- ["IsNonSpeculative"])
+ ["IsNonSpeculative", "IsUnverifiable"])
header_output += BasicDeclare.subst(m5readfileIop)
decoder_output += BasicConstructor.subst(m5readfileIop)
exec_output += PredOpExecute.subst(m5readfileIop)
+ m5writefileCode = '''
+ int n = 4;
+ uint64_t offset = getArgument(xc->tcBase(), n, sizeof(uint64_t), false);
+ n = 6;
+ Addr filenameAddr = getArgument(xc->tcBase(), n, sizeof(Addr), false);
+ R0 = PseudoInst::writefile(xc->tcBase(), R0, join32to64(R3,R2), offset,
+ filenameAddr);
+ '''
+ m5writefileIop = InstObjParams("m5writefile", "M5writefile", "PredOp",
+ { "code": m5writefileCode,
+ "predicate_test": predicateTest },
+ ["IsNonSpeculative"])
+ header_output += BasicDeclare.subst(m5writefileIop)
+ decoder_output += BasicConstructor.subst(m5writefileIop)
+ exec_output += PredOpExecute.subst(m5writefileIop)
+
m5breakIop = InstObjParams("m5break", "M5break", "PredOp",
{ "code": "PseudoInst::debugbreak(xc->tcBase());",
"predicate_test": predicateTest },
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index b671843cf..d8ee5e88d 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -521,7 +521,8 @@ let {{
{ "code" : wfeCode,
"pred_fixup" : wfePredFixUpCode,
"predicate_test" : predicateTest },
- ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
+ ["IsNonSpeculative", "IsQuiesce",
+ "IsSerializeAfter", "IsUnverifiable"])
header_output += BasicDeclare.subst(wfeIop)
decoder_output += BasicConstructor.subst(wfeIop)
exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
@@ -536,7 +537,8 @@ let {{
'''
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
{ "code" : wfiCode, "predicate_test" : predicateTest },
- ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
+ ["IsNonSpeculative", "IsQuiesce",
+ "IsSerializeAfter", "IsUnverifiable"])
header_output += BasicDeclare.subst(wfiIop)
decoder_output += BasicConstructor.subst(wfiIop)
exec_output += QuiescePredOpExecute.subst(wfiIop)
@@ -557,7 +559,7 @@ let {{
'''
sevIop = InstObjParams("sev", "SevInst", "PredOp", \
{ "code" : sevCode, "predicate_test" : predicateTest },
- ["IsNonSpeculative", "IsSquashAfter"])
+ ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
header_output += BasicDeclare.subst(sevIop)
decoder_output += BasicConstructor.subst(sevIop)
exec_output += PredOpExecute.subst(sevIop)
diff --git a/src/arch/arm/isa/templates/basic.isa b/src/arch/arm/isa/templates/basic.isa
index 0728b66e3..b3878b89a 100644
--- a/src/arch/arm/isa/templates/basic.isa
+++ b/src/arch/arm/isa/templates/basic.isa
@@ -49,7 +49,7 @@ def template BasicDeclare {{
// Basic instruction class constructor template.
def template BasicConstructor {{
- inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index db097c653..c31818377 100644
--- a/src/arch/arm/miscregs.cc
+++ b/src/arch/arm/miscregs.cc
@@ -411,7 +411,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
}
break;
case 11:
- if (opc1 >= 0 && opc1 <=7) {
+ if (opc1 <=7) {
switch (crm) {
case 0:
case 1:
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index b2ab010c0..9c92ebdf6 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -107,8 +107,9 @@ TableWalker::getPort(const std::string &if_name, int idx)
Fault
TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
- TLB::Translation *_trans, bool _timing)
+ TLB::Translation *_trans, bool _timing, bool _functional)
{
+ assert(!(_functional && _timing));
if (!currState) {
// For atomic mode, a new WalkerState instance should be only created
// once per TLB. For timing mode, a new instance is generated for every
@@ -136,6 +137,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _
currState->fault = NoFault;
currState->contextId = _cid;
currState->timing = _timing;
+ currState->functional = _functional;
currState->mode = _mode;
/** @todo These should be cached or grabbed from cached copies in
@@ -230,12 +232,21 @@ TableWalker::processWalk()
stateQueueL1.size());
stateQueueL1.push_back(currState);
currState = NULL;
- } else {
+ } else if (!currState->functional) {
port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
NULL, (uint8_t*)&currState->l1Desc.data,
currState->tc->getCpuPtr()->ticks(1), flag);
doL1Descriptor();
f = currState->fault;
+ } else {
+ RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag);
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
+ pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
+ port->sendFunctional(pkt);
+ doL1Descriptor();
+ delete req;
+ delete pkt;
+ f = currState->fault;
}
return f;
@@ -566,11 +577,19 @@ TableWalker::doL1Descriptor()
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
&doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
currState->tc->getCpuPtr()->ticks(1));
- } else {
+ } else if (!currState->functional) {
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
NULL, (uint8_t*)&currState->l2Desc.data,
currState->tc->getCpuPtr()->ticks(1));
doL2Descriptor();
+ } else {
+ RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0);
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
+ pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
+ port->sendFunctional(pkt);
+ doL2Descriptor();
+ delete req;
+ delete pkt;
}
return;
default:
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index 85db1fa77..d4a2e87b5 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -294,6 +294,9 @@ class TableWalker : public MemObject
/** If the mode is timing or atomic */
bool timing;
+ /** If the atomic mode should be functional */
+ bool functional;
+
/** Save mode for use in delayed response */
BaseTLB::Mode mode;
@@ -354,7 +357,7 @@ class TableWalker : public MemObject
virtual Port *getPort(const std::string &if_name, int idx = -1);
Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
- TLB::Translation *_trans, bool timing);
+ TLB::Translation *_trans, bool timing, bool functional = false);
void setTlb(TLB *_tlb) { tlb = _tlb; }
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index b19ad5265..0b003e9fb 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -443,8 +443,11 @@ TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
Fault
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
- Translation *translation, bool &delay, bool timing)
+ Translation *translation, bool &delay, bool timing, bool functional)
{
+ // No such thing as a functional timing access
+ assert(!(timing && functional));
+
if (!miscRegValid) {
updateMiscReg(tc);
DPRINTF(TLBVerbose, "TLB variables changed!\n");
@@ -531,7 +534,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n",
vaddr, contextId);
fault = tableWalker->walk(req, tc, contextId, mode, translation,
- timing);
+ timing, functional);
if (timing && fault == NoFault) {
delay = true;
// for timing mode, return and wait for table walk
@@ -687,6 +690,19 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
}
Fault
+TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
+{
+ bool delay = false;
+ Fault fault;
+ if (FullSystem)
+ fault = translateFs(req, tc, mode, NULL, delay, false, true);
+ else
+ fault = translateSe(req, tc, mode, NULL, delay, false);
+ assert(!delay);
+ return fault;
+}
+
+Fault
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, Mode mode)
{
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 0bf13fe83..daf59f01d 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -180,6 +180,12 @@ class TLB : public BaseTLB
*/
bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr);
+ /**
+ * Do a functional lookup on the TLB (for checker cpu) that
+ * behaves like a normal lookup without modifying any page table state.
+ */
+ Fault translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode);
+
/** Accessor functions for memory attributes for last accessed TLB entry
*/
void
@@ -194,7 +200,8 @@ class TLB : public BaseTLB
}
Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
- Translation *translation, bool &delay, bool timing);
+ Translation *translation, bool &delay,
+ bool timing, bool functional = false);
Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing);
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index ac81c7db6..0527e135f 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -43,6 +43,7 @@
#include "arch/arm/tlb.hh"
#include "arch/arm/utility.hh"
#include "arch/arm/vtophys.hh"
+#include "config/use_checker.hh"
#include "cpu/thread_context.hh"
#include "mem/fs_translating_port_proxy.hh"
#include "sim/full_system.hh"
@@ -113,7 +114,11 @@ skipFunction(ThreadContext *tc)
{
TheISA::PCState newPC = tc->pcState();
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
+#if USE_CHECKER
+ tc->pcStateNoRecord(newPC);
+#else
tc->pcState(newPC);
+#endif
}
void
diff --git a/src/arch/generic/memhelpers.hh b/src/arch/generic/memhelpers.hh
index c753aaf2a..f7bbfa269 100644
--- a/src/arch/generic/memhelpers.hh
+++ b/src/arch/generic/memhelpers.hh
@@ -64,7 +64,7 @@ readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, MemT &mem,
memset(&mem, 0, sizeof(mem));
Fault fault = readMemTiming(xc, traceData, addr, mem, flags);
if (fault == NoFault) {
- mem = gtoh(mem);
+ mem = TheISA::gtoh(mem);
if (traceData)
traceData->setData(mem);
}
@@ -92,7 +92,7 @@ writeMemAtomic(XC *xc, Trace::InstRecord *traceData, const MemT &mem,
{
Fault fault = writeMemTiming(xc, traceData, mem, addr, flags, res);
if (fault == NoFault && res != NULL) {
- *res = gtoh((MemT)*res);
+ *res = TheISA::gtoh((MemT)*res);
}
return fault;
}
diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc
index 3076e0afe..3697601dc 100644
--- a/src/arch/mips/faults.cc
+++ b/src/arch/mips/faults.cc
@@ -95,7 +95,7 @@ template <> FaultVals MipsFault<TlbInvalidFault>::vals =
template <> FaultVals MipsFault<TlbRefillFault>::vals =
{ "TLB Refill Exception", 0x180, ExcCodeDummy };
-template <> FaultVals MipsFault<TlbModifiedFault>::vals =
+template <> MipsFaultBase::FaultVals MipsFault<TlbModifiedFault>::vals =
{ "TLB Modified Exception", 0x180, ExcCodeMod };
void
diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh
index b90c38e99..98638ac9a 100644
--- a/src/arch/mips/faults.hh
+++ b/src/arch/mips/faults.hh
@@ -300,7 +300,7 @@ class TlbModifiedFault : public TlbFault<TlbModifiedFault>
TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false)
{}
- ExcCode code() const { return vals.code; }
+ ExcCode code() const { return MipsFault<TlbModifiedFault>::code(); }
};
} // namespace MipsISA
diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh
index 5040c434c..b10b18092 100644
--- a/src/arch/x86/bios/acpi.hh
+++ b/src/arch/x86/bios/acpi.hh
@@ -48,11 +48,11 @@
class Port;
-class X86ACPIRSDPParams;
+struct X86ACPIRSDPParams;
-class X86ACPISysDescTableParams;
-class X86ACPIRSDTParams;
-class X86ACPIXSDTParams;
+struct X86ACPISysDescTableParams;
+struct X86ACPIRSDTParams;
+struct X86ACPIXSDTParams;
namespace X86ISA
{
diff --git a/src/arch/x86/bios/intelmp.cc b/src/arch/x86/bios/intelmp.cc
index 974af28a5..4c9c61adb 100644
--- a/src/arch/x86/bios/intelmp.cc
+++ b/src/arch/x86/bios/intelmp.cc
@@ -72,7 +72,7 @@ template<class T>
uint8_t
writeOutField(PortProxy* proxy, Addr addr, T val)
{
- T guestVal = X86ISA::htog(val);
+ uint64_t guestVal = X86ISA::htog(val);
proxy->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T));
uint8_t checkSum = 0;
diff --git a/src/arch/x86/bios/intelmp.hh b/src/arch/x86/bios/intelmp.hh
index 0ddb62b8d..4b730ad4b 100644
--- a/src/arch/x86/bios/intelmp.hh
+++ b/src/arch/x86/bios/intelmp.hh
@@ -54,24 +54,24 @@
class PortProxy;
// Config entry types
-class X86IntelMPBaseConfigEntryParams;
-class X86IntelMPExtConfigEntryParams;
+struct X86IntelMPBaseConfigEntryParams;
+struct X86IntelMPExtConfigEntryParams;
// General table structures
-class X86IntelMPConfigTableParams;
-class X86IntelMPFloatingPointerParams;
+struct X86IntelMPConfigTableParams;
+struct X86IntelMPFloatingPointerParams;
// Base entry types
-class X86IntelMPBusParams;
-class X86IntelMPIOAPICParams;
-class X86IntelMPIOIntAssignmentParams;
-class X86IntelMPLocalIntAssignmentParams;
-class X86IntelMPProcessorParams;
+struct X86IntelMPBusParams;
+struct X86IntelMPIOAPICParams;
+struct X86IntelMPIOIntAssignmentParams;
+struct X86IntelMPLocalIntAssignmentParams;
+struct X86IntelMPProcessorParams;
// Extended entry types
-class X86IntelMPAddrSpaceMappingParams;
-class X86IntelMPBusHierarchyParams;
-class X86IntelMPCompatAddrSpaceModParams;
+struct X86IntelMPAddrSpaceMappingParams;
+struct X86IntelMPBusHierarchyParams;
+struct X86IntelMPCompatAddrSpaceModParams;
namespace X86ISA
{
diff --git a/src/arch/x86/bios/smbios.hh b/src/arch/x86/bios/smbios.hh
index 9fa6cd6dc..805b03fbb 100644
--- a/src/arch/x86/bios/smbios.hh
+++ b/src/arch/x86/bios/smbios.hh
@@ -52,9 +52,9 @@
#include "sim/sim_object.hh"
class PortProxy;
-class X86SMBiosBiosInformationParams;
-class X86SMBiosSMBiosStructureParams;
-class X86SMBiosSMBiosTableParams;
+struct X86SMBiosBiosInformationParams;
+struct X86SMBiosSMBiosStructureParams;
+struct X86SMBiosSMBiosTableParams;
namespace X86ISA
{
diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc
index 0736d26e2..d370b93e8 100644
--- a/src/base/fast_alloc.cc
+++ b/src/base/fast_alloc.cc
@@ -40,10 +40,6 @@
#if USE_FAST_ALLOC
-#ifdef __GNUC__
-#pragma implementation
-#endif
-
void *FastAlloc::freeLists[Num_Buckets];
#if FAST_ALLOC_STATS
diff --git a/src/base/output.hh b/src/base/output.hh
index b86e68856..68d9daf85 100644
--- a/src/base/output.hh
+++ b/src/base/output.hh
@@ -73,6 +73,13 @@ class OutputDirectory
*/
std::ostream *checkForStdio(const std::string &name) const;
+ public:
+ /** Constructor. */
+ OutputDirectory();
+
+ /** Destructor. */
+ ~OutputDirectory();
+
/** Opens a file (optionally compressed).
*
* Will open a file as a compressed stream if filename ends in .gz.
@@ -84,13 +91,6 @@ class OutputDirectory
std::ostream *openFile(const std::string &filename,
std::ios_base::openmode mode = std::ios::trunc);
- public:
- /** Constructor. */
- OutputDirectory();
-
- /** Destructor. */
- ~OutputDirectory();
-
/**
* Sets name of this directory.
* @param dir name of this directory
diff --git a/src/base/range_map.hh b/src/base/range_map.hh
index 7714a0049..5d6547f9b 100644
--- a/src/base/range_map.hh
+++ b/src/base/range_map.hh
@@ -215,7 +215,7 @@ class range_multimap
{
std::pair<iterator,iterator> p;
p = find(r);
- if (p.first->first.start == r.start && p.first->first.end == r.end ||
+ if ((p.first->first.start == r.start && p.first->first.end == r.end) ||
p.first == tree.end())
return tree.insert(std::make_pair<Range<T>,V>(r, d));
else
diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh
index 899c7c29e..15a725438 100644
--- a/src/base/remote_gdb.hh
+++ b/src/base/remote_gdb.hh
@@ -204,7 +204,7 @@ class BaseRemoteGDB
public:
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
- std::string name() { return gdb->name() + ".hwbkpt"; }
+ const std::string name() const { return gdb->name() + ".hwbkpt"; }
virtual void process(ThreadContext *tc);
};
diff --git a/src/base/stl_helpers.hh b/src/base/stl_helpers.hh
index a34ca7bb6..689cb626b 100644
--- a/src/base/stl_helpers.hh
+++ b/src/base/stl_helpers.hh
@@ -72,7 +72,7 @@ class ContainerPrint
// Treat all objects in an stl container as pointers to heap objects,
// calling delete on each one and zeroing the pointers along the way
-template <typename T, template <typename T, typename A> class C, typename A>
+template <template <typename T, typename A> class C, typename T, typename A>
void
deletePointers(C<T,A> &container)
{
@@ -81,7 +81,7 @@ deletePointers(C<T,A> &container)
// Write out all elements in an stl container as a space separated
// list enclosed in square brackets
-template <typename T, template <typename T, typename A> class C, typename A>
+template <template <typename T, typename A> class C, typename T, typename A>
std::ostream &
operator<<(std::ostream& out, const C<T,A> &vec)
{
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py
index 19464acbc..fda0a3bc8 100644
--- a/src/cpu/BaseCPU.py
+++ b/src/cpu/BaseCPU.py
@@ -164,7 +164,6 @@ class BaseCPU(MemObject):
self.connectUncachedPorts(uncached_bus)
def addPrivateSplitL1Caches(self, ic, dc, iwc = None, dwc = None):
- assert(len(self._cached_ports) < 7)
self.icache = ic
self.dcache = dc
self.icache_port = ic.cpu_side
@@ -180,6 +179,11 @@ class BaseCPU(MemObject):
"dtb_walker_cache.mem_side"]
else:
self._cached_ports += ["itb.walker.port", "dtb.walker.port"]
+ # Checker doesn't need its own tlb caches because it does
+ # functional accesses only
+ if buildEnv['USE_CHECKER']:
+ self._cached_ports += ["checker.itb.walker.port", \
+ "checker.dtb.walker.port"]
def addTwoLevelCacheHierarchy(self, ic, dc, l2c, iwc = None, dwc = None):
self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
diff --git a/src/cpu/CheckerCPU.py b/src/cpu/CheckerCPU.py
index 132254413..c144c4678 100644
--- a/src/cpu/CheckerCPU.py
+++ b/src/cpu/CheckerCPU.py
@@ -35,7 +35,7 @@ class CheckerCPU(BaseCPU):
exitOnError = Param.Bool(False, "Exit on an error")
updateOnError = Param.Bool(False,
"Update the checker with the main CPU's state on an error")
- warnOnlyOnLoadError = Param.Bool(False,
+ warnOnlyOnLoadError = Param.Bool(True,
"If a load result is incorrect, only print a warning and do not exit")
function_trace = Param.Bool(False, "Enable function trace")
function_trace_start = Param.Tick(0, "Cycle to start function trace")
diff --git a/src/cpu/DummyChecker.py b/src/cpu/DummyChecker.py
new file mode 100644
index 000000000..3c276e1d2
--- /dev/null
+++ b/src/cpu/DummyChecker.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2010-2011 ARM Limited
+# All rights reserved
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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.
+#
+# Authors: Geoffrey Blake
+
+from m5.params import *
+from BaseCPU import BaseCPU
+
+class DummyChecker(BaseCPU):
+ type = 'DummyChecker'
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index ff731336a..de59dcc24 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -134,7 +134,9 @@ if env['TARGET_ISA'] == 'sparc':
Source('legiontrace.cc')
if env['USE_CHECKER']:
+ SimObject('DummyChecker.py')
Source('checker/cpu.cc')
+ Source('dummy_checker_builder.cc')
DebugFlag('Checker')
checker_supports = False
for i in CheckerSupportedCPUList:
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index d174995a9..977769126 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -53,6 +53,7 @@
#include "base/misc.hh"
#include "base/output.hh"
#include "base/trace.hh"
+#include "config/use_checker.hh"
#include "cpu/base.hh"
#include "cpu/cpuevent.hh"
#include "cpu/profile.hh"
@@ -65,6 +66,10 @@
#include "sim/sim_exit.hh"
#include "sim/system.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif
+
// Hack
#include "sim/stat_control.hh"
@@ -212,7 +217,10 @@ BaseCPU::BaseCPU(Params *p)
schedule(event, p->function_trace_start);
}
}
- interrupts->setCPU(this);
+ // Check if CPU model has interrupts connected. The CheckerCPU
+ // cannot take interrupts directly for example.
+ if (interrupts)
+ interrupts->setCPU(this);
if (FullSystem) {
profileEvent = NULL;
@@ -351,8 +359,10 @@ BaseCPU::switchOut()
}
void
-BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
+BaseCPU::takeOverFrom(BaseCPU *oldCPU)
{
+ Port *ic = getPort("icache_port");
+ Port *dc = getPort("dcache_port");
assert(threadContexts.size() == oldCPU->threadContexts.size());
_cpuId = oldCPU->cpuId();
@@ -396,6 +406,35 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
new_dtb_port->setPeer(peer);
peer->setPeer(new_dtb_port);
}
+
+#if USE_CHECKER
+ Port *old_checker_itb_port, *old_checker_dtb_port;
+ Port *new_checker_itb_port, *new_checker_dtb_port;
+
+ CheckerCPU *oldChecker =
+ dynamic_cast<CheckerCPU*>(oldTC->getCheckerCpuPtr());
+ CheckerCPU *newChecker =
+ dynamic_cast<CheckerCPU*>(newTC->getCheckerCpuPtr());
+ old_checker_itb_port = oldChecker->getITBPtr()->getPort();
+ old_checker_dtb_port = oldChecker->getDTBPtr()->getPort();
+ new_checker_itb_port = newChecker->getITBPtr()->getPort();
+ new_checker_dtb_port = newChecker->getDTBPtr()->getPort();
+
+ // Move over any table walker ports if they exist for checker
+ if (new_checker_itb_port && !new_checker_itb_port->isConnected()) {
+ assert(old_checker_itb_port);
+ Port *peer = old_checker_itb_port->getPeer();;
+ new_checker_itb_port->setPeer(peer);
+ peer->setPeer(new_checker_itb_port);
+ }
+ if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) {
+ assert(old_checker_dtb_port);
+ Port *peer = old_checker_dtb_port->getPeer();;
+ new_checker_dtb_port->setPeer(peer);
+ peer->setPeer(new_checker_dtb_port);
+ }
+#endif
+
}
interrupts = oldCPU->interrupts;
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 41c79dff6..8250338cc 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -237,16 +237,16 @@ class BaseCPU : public MemObject
/// Notify the CPU that the indicated context is now active. The
/// delay parameter indicates the number of ticks to wait before
/// executing (typically 0 or 1).
- virtual void activateContext(int thread_num, int delay) {}
+ virtual void activateContext(ThreadID thread_num, int delay) {}
/// Notify the CPU that the indicated context is now suspended.
- virtual void suspendContext(int thread_num) {}
+ virtual void suspendContext(ThreadID thread_num) {}
/// Notify the CPU that the indicated context is now deallocated.
- virtual void deallocateContext(int thread_num) {}
+ virtual void deallocateContext(ThreadID thread_num) {}
/// Notify the CPU that the indicated context is now halted.
- virtual void haltContext(int thread_num) {}
+ virtual void haltContext(ThreadID thread_num) {}
/// Given a Thread Context pointer return the thread num
int findContext(ThreadContext *tc);
@@ -275,7 +275,7 @@ class BaseCPU : public MemObject
/// Take over execution from the given CPU. Used for warm-up and
/// sampling.
- virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);
+ virtual void takeOverFrom(BaseCPU *);
/**
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 9089d1069..2b0e26cd2 100644
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -48,12 +48,14 @@
#include <bitset>
#include <list>
#include <string>
+#include <queue>
#include "arch/faults.hh"
#include "arch/utility.hh"
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/o3/comm.hh"
#include "cpu/exetrace.hh"
#include "cpu/inst_seq.hh"
@@ -175,6 +177,11 @@ class BaseDynInst : public FastAlloc, public RefCounted
RequestPtr savedSreqLow;
RequestPtr savedSreqHigh;
+#if USE_CHECKER
+ // Need a copy of main request pointer to verify on writes.
+ RequestPtr reqToVerify;
+#endif //USE_CHECKER
+
/** @todo: Consider making this private. */
public:
/** The sequence number of the instruction. */
@@ -247,14 +254,17 @@ class BaseDynInst : public FastAlloc, public RefCounted
union Result {
uint64_t integer;
-// float fp;
double dbl;
+ void set(uint64_t i) { integer = i; }
+ void set(double d) { dbl = d; }
+ void get(uint64_t& i) { i = integer; }
+ void get(double& d) { d = dbl; }
};
- /** The result of the instruction; assumes for now that there's only one
- * destination register.
+ /** The result of the instruction; assumes an instruction can have many
+ * destination registers.
*/
- Result instResult;
+ std::queue<Result> instResult;
/** Records changes to result? */
bool recordResult;
@@ -557,56 +567,68 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns the logical register index of the i'th source register. */
RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
- /** Returns the result of an integer instruction. */
- uint64_t readIntResult() { return instResult.integer; }
+ /** Pops a result off the instResult queue */
+ template <class T>
+ void popResult(T& t)
+ {
+ if (!instResult.empty()) {
+ instResult.front().get(t);
+ instResult.pop();
+ }
+ }
- /** Returns the result of a floating point instruction. */
- float readFloatResult() { return (float)instResult.dbl; }
+ /** Read the most recent result stored by this instruction */
+ template <class T>
+ void readResult(T& t)
+ {
+ instResult.back().get(t);
+ }
- /** Returns the result of a floating point (double) instruction. */
- double readDoubleResult() { return instResult.dbl; }
+ /** Pushes a result onto the instResult queue */
+ template <class T>
+ void setResult(T t)
+ {
+ if (recordResult) {
+ Result instRes;
+ instRes.set(t);
+ instResult.push(instRes);
+ }
+ }
/** Records an integer register being set to a value. */
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
- if (recordResult)
- instResult.integer = val;
+ setResult<uint64_t>(val);
}
/** Records an fp register being set to a value. */
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
int width)
{
- if (recordResult) {
- if (width == 32)
- instResult.dbl = (double)val;
- else if (width == 64)
- instResult.dbl = val;
- else
- panic("Unsupported width!");
+ if (width == 32 || width == 64) {
+ setResult<double>(val);
+ } else {
+ panic("Unsupported width!");
}
}
/** Records an fp register being set to a value. */
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
- if (recordResult)
- instResult.dbl = (double)val;
+ setResult<double>(val);
}
/** Records an fp register being set to an integer value. */
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val,
int width)
{
- if (recordResult)
- instResult.integer = val;
+ setResult<uint64_t>(val);
}
/** Records an fp register being set to an integer value. */
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val)
{
- if (recordResult)
- instResult.integer = val;
+ setResult<uint64_t>(val);
}
/** Records that one of the source registers is ready. */
@@ -871,6 +893,12 @@ BaseDynInst<Impl>::readMem(Addr addr, uint8_t *data,
effAddr = req->getVaddr();
effSize = size;
effAddrValid = true;
+#if USE_CHECKER
+ if (reqToVerify != NULL) {
+ delete reqToVerify;
+ }
+ reqToVerify = new Request(*req);
+#endif //USE_CHECKER
fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
} else {
// Commit will have to clean up whatever happened. Set this
@@ -926,6 +954,12 @@ BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size,
effAddr = req->getVaddr();
effSize = size;
effAddrValid = true;
+#if USE_CHECKER
+ if (reqToVerify != NULL) {
+ delete reqToVerify;
+ }
+ reqToVerify = new Request(*req);
+#endif // USE_CHECKER
fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx);
}
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
index a37ec5e25..d2ecd01ff 100644
--- a/src/cpu/base_dyn_inst_impl.hh
+++ b/src/cpu/base_dyn_inst_impl.hh
@@ -48,6 +48,7 @@
#include "base/cprintf.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/exetrace.hh"
#include "debug/DynInst.hh"
@@ -117,7 +118,6 @@ BaseDynInst<Impl>::initVars()
reqMade = false;
readyRegs = 0;
- instResult.integer = 0;
recordResult = true;
status.reset();
@@ -157,6 +157,10 @@ BaseDynInst<Impl>::initVars()
#ifdef DEBUG
cpu->snList.insert(seqNum);
#endif
+
+#if USE_CHECKER
+ reqToVerify = NULL;
+#endif
}
template <class Impl>
@@ -182,6 +186,11 @@ BaseDynInst<Impl>::~BaseDynInst()
#ifdef DEBUG
cpu->snList.erase(seqNum);
#endif
+
+#if USE_CHECKER
+ if (reqToVerify)
+ delete reqToVerify;
+#endif // USE_CHECKER
}
#ifdef DEBUG
diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc
index ec4496eb4..c905c62eb 100644
--- a/src/cpu/checker/cpu.cc
+++ b/src/cpu/checker/cpu.cc
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -26,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
+ * Geoffrey Blake
*/
#include <list>
@@ -38,10 +51,11 @@
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
+#include "params/CheckerCPU.hh"
+#include "sim/tlb.hh"
using namespace std;
-//The CheckerCPU does alpha only
-using namespace AlphaISA;
+using namespace TheISA;
void
CheckerCPU::init()
@@ -52,6 +66,8 @@ CheckerCPU::CheckerCPU(Params *p)
: BaseCPU(p), thread(NULL), tc(NULL)
{
memReq = NULL;
+ curStaticInst = NULL;
+ curMacroStaticInst = NULL;
numInst = 0;
startNumInst = 0;
@@ -66,13 +82,14 @@ CheckerCPU::CheckerCPU(Params *p)
itb = p->itb;
dtb = p->dtb;
systemPtr = NULL;
- process = p->process;
- thread = new SimpleThread(this, /* thread_num */ 0, process);
+ workload = p->workload;
+ // XXX: This is a hack to get this to work some
+ thread = new SimpleThread(this, /* thread_num */ 0, workload[0], itb, dtb);
tc = thread->getTC();
threadContexts.push_back(tc);
- result.integer = 0;
+ updateOnError = true;
}
CheckerCPU::~CheckerCPU()
@@ -107,216 +124,224 @@ CheckerCPU::setDcachePort(Port *dcache_port)
void
CheckerCPU::serialize(ostream &os)
{
-/*
- BaseCPU::serialize(os);
- SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
- thread->serialize(os);
- cacheCompletionEvent.serialize(os);
-*/
}
void
CheckerCPU::unserialize(Checkpoint *cp, const string &section)
{
-/*
- BaseCPU::unserialize(cp, section);
- UNSERIALIZE_SCALAR(inst);
- thread->unserialize(cp, csprintf("%s.xc", section));
-*/
}
-template <class T>
Fault
-CheckerCPU::read(Addr addr, T &data, unsigned flags)
+CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags)
{
- // need to fill in CPU & thread IDs here
- memReq = new Request();
+ Fault fault = NoFault;
+ unsigned blockSize = dcachePort->peerBlockSize();
+ int fullSize = size;
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
+ bool checked_flags = false;
+ bool flags_match = true;
+ Addr pAddr = 0x0;
+
+
+ if (secondAddr > addr)
+ size = secondAddr - addr;
+
+ // Need to account for multiple accesses like the Atomic and TimingSimple
+ while (1) {
+ memReq = new Request();
+ memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr());
+
+ // translate to physical address
+ fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read);
+
+ if (!checked_flags && fault == NoFault && unverifiedReq) {
+ flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
+ memReq->getPaddr(), memReq->getFlags());
+ pAddr = memReq->getPaddr();
+ checked_flags = true;
+ }
- memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
+ // Now do the access
+ if (fault == NoFault &&
+ !memReq->getFlags().isSet(Request::NO_ACCESS)) {
+ PacketPtr pkt = new Packet(memReq,
+ memReq->isLLSC() ?
+ MemCmd::LoadLockedReq : MemCmd::ReadReq,
+ Packet::Broadcast);
+
+ pkt->dataStatic(data);
+
+ if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) {
+ // Access memory to see if we have the same data
+ dcachePort->sendFunctional(pkt);
+ } else {
+ // Assume the data is correct if it's an uncached access
+ memcpy(data, unverifiedMemData, size);
+ }
+
+ delete memReq;
+ memReq = NULL;
+ delete pkt;
+ }
- // translate to physical address
- dtb->translateAtomic(memReq, tc, false);
+ if (fault != NoFault) {
+ if (memReq->isPrefetch()) {
+ fault = NoFault;
+ }
+ delete memReq;
+ memReq = NULL;
+ break;
+ }
- PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
+ if (memReq != NULL) {
+ delete memReq;
+ }
- pkt->dataStatic(&data);
+ //If we don't need to access a second cache line, stop now.
+ if (secondAddr <= addr)
+ {
+ break;
+ }
- if (!(memReq->isUncacheable())) {
- // Access memory to see if we have the same data
- dcachePort->sendFunctional(pkt);
- } else {
- // Assume the data is correct if it's an uncached access
- memcpy(&data, &unverifiedResult.integer, sizeof(T));
+ // Setup for accessing next cache line
+ data += size;
+ unverifiedMemData += size;
+ size = addr + fullSize - secondAddr;
+ addr = secondAddr;
}
- delete pkt;
+ if (!flags_match) {
+ warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
+ curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
+ unverifiedReq->getFlags(), addr, pAddr, flags);
+ handleError();
+ }
- return NoFault;
+ return fault;
}
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
Fault
-CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, double &data, unsigned flags)
+CheckerCPU::writeMem(uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res)
{
- return read(addr, *(uint64_t*)&data, flags);
-}
+ Fault fault = NoFault;
+ bool checked_flags = false;
+ bool flags_match = true;
+ Addr pAddr = 0x0;
-template<>
-Fault
-CheckerCPU::read(Addr addr, float &data, unsigned flags)
-{
- return read(addr, *(uint32_t*)&data, flags);
-}
+ unsigned blockSize = dcachePort->peerBlockSize();
+ int fullSize = size;
-template<>
-Fault
-CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
-{
- return read(addr, (uint32_t&)data, flags);
-}
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
-template <class T>
-Fault
-CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- // need to fill in CPU & thread IDs here
- memReq = new Request();
-
- memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
-
- // translate to physical address
- dtb->translateAtomic(memReq, tc, true);
-
- // Can compare the write data and result only if it's cacheable,
- // not a store conditional, or is a store conditional that
- // succeeded.
- // @todo: Verify that actual memory matches up with these values.
- // Right now it only verifies that the instruction data is the
- // same as what was in the request that got sent to memory; there
- // is no verification that it is the same as what is in memory.
- // This is because the LSQ would have to be snooped in the CPU to
- // verify this data.
- if (unverifiedReq &&
- !(unverifiedReq->isUncacheable()) &&
- (!(unverifiedReq->isLLSC()) ||
- ((unverifiedReq->isLLSC()) &&
- unverifiedReq->getExtraData() == 1))) {
- T inst_data;
-/*
- // This code would work if the LSQ allowed for snooping.
- PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
- pkt.dataStatic(&inst_data);
+ if (secondAddr > addr)
+ size = secondAddr - addr;
- dcachePort->sendFunctional(pkt);
+ // Need to account for a multiple access like Atomic and Timing CPUs
+ while (1) {
+ memReq = new Request();
+ memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr());
- delete pkt;
-*/
- memcpy(&inst_data, unverifiedMemData, sizeof(T));
+ // translate to physical address
+ fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write);
- if (data != inst_data) {
- warn("%lli: Store value does not match value in memory! "
- "Instruction: %#x, memory: %#x",
- curTick(), inst_data, data);
- handleError();
+ if (!checked_flags && fault == NoFault && unverifiedReq) {
+ flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
+ memReq->getPaddr(), memReq->getFlags());
+ pAddr = memReq->getPaddr();
+ checked_flags = true;
}
- }
-
- // Assume the result was the same as the one passed in. This checker
- // doesn't check if the SC should succeed or fail, it just checks the
- // value.
- if (res && unverifiedReq->scResultValid())
- *res = unverifiedReq->getExtraData();
-
- return NoFault;
-}
-
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-template<>
-Fault
-CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint32_t*)&data, addr, flags, res);
-}
+ /*
+ * We don't actually check memory for the store because there
+ * is no guarantee it has left the lsq yet, and therefore we
+ * can't verify the memory on stores without lsq snooping
+ * enabled. This is left as future work for the Checker: LSQ snooping
+ * and memory validation after stores have committed.
+ */
+
+ delete memReq;
+
+ //If we don't need to access a second cache line, stop now.
+ if (fault != NoFault || secondAddr <= addr)
+ {
+ if (fault != NoFault && memReq->isPrefetch()) {
+ fault = NoFault;
+ }
+ break;
+ }
-template<>
-Fault
-CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write((uint32_t)data, addr, flags, res);
+ //Update size and access address
+ size = addr + fullSize - secondAddr;
+ //And access the right address.
+ addr = secondAddr;
+ }
+
+ if (!flags_match) {
+ warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n",
+ curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
+ unverifiedReq->getFlags(), addr, pAddr, flags);
+ handleError();
+ }
+
+ // Assume the result was the same as the one passed in. This checker
+ // doesn't check if the SC should succeed or fail, it just checks the
+ // value.
+ if (unverifiedReq && res && unverifiedReq->extraDataValid())
+ *res = unverifiedReq->getExtraData();
+
+ // Entire purpose here is to make sure we are getting the
+ // same data to send to the mem system as the CPU did.
+ // Cannot check this is actually what went to memory because
+ // there stores can be in ld/st queue or coherent operations
+ // overwriting values.
+ bool extraData;
+ if (unverifiedReq) {
+ extraData = unverifiedReq->extraDataValid() ?
+ unverifiedReq->getExtraData() : 1;
+ }
+
+ if (unverifiedReq && unverifiedMemData &&
+ memcmp(data, unverifiedMemData, fullSize) && extraData) {
+ warn("%lli: Store value does not match value sent to memory!\
+ data: %#x inst_data: %#x", curTick(), data,
+ unverifiedMemData);
+ handleError();
+ }
+
+ return fault;
}
-
Addr
CheckerCPU::dbg_vtophys(Addr addr)
{
return vtophys(tc, addr);
}
+/**
+ * Checks if the flags set by the Checker and Checkee match.
+ */
bool
-CheckerCPU::checkFlags(Request *req)
+CheckerCPU::checkFlags(Request *unverified_req, Addr vAddr,
+ Addr pAddr, int flags)
{
- // Remove any dynamic flags that don't have to do with the request itself.
- unsigned flags = unverifiedReq->getFlags();
- unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
- flags = flags & (mask);
- if (flags == req->getFlags()) {
+ Addr unverifiedVAddr = unverified_req->getVaddr();
+ Addr unverifiedPAddr = unverified_req->getPaddr();
+ int unverifiedFlags = unverified_req->getFlags();
+
+ if (unverifiedVAddr != vAddr ||
+ unverifiedPAddr != pAddr ||
+ unverifiedFlags != flags) {
return false;
- } else {
- return true;
}
+
+ return true;
}
void
CheckerCPU::dumpAndExit()
{
- warn("%lli: Checker PC:%#x, next PC:%#x",
- curTick(), thread->readPC(), thread->readNextPC());
+ warn("%lli: Checker PC:%s",
+ curTick(), thread->pcState());
panic("Checker found an error!");
}
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index a3e95137d..6f5125625 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -35,6 +47,7 @@
#include <map>
#include <queue>
+#include "arch/predecoder.hh"
#include "arch/types.hh"
#include "base/statistics.hh"
#include "cpu/base.hh"
@@ -42,6 +55,8 @@
#include "cpu/pc_event.hh"
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
+#include "debug/Checker.hh"
+#include "params/CheckerCPU.hh"
#include "sim/eventq.hh"
// forward declarations
@@ -52,12 +67,6 @@ namespace TheISA
template <class>
class BaseDynInst;
-class CheckerCPUParams;
-class Checkpoint;
-class MemInterface;
-class PhysicalMemory;
-class Process;
-class Processor;
class ThreadContext;
class Request;
@@ -90,11 +99,11 @@ class CheckerCPU : public BaseCPU
public:
typedef CheckerCPUParams Params;
const Params *params() const
- { return reinterpret_cast<const Params *>(_params); }
+ { return reinterpret_cast<const Params *>(_params); }
CheckerCPU(Params *p);
virtual ~CheckerCPU();
- Process *process;
+ std::vector<Process*> workload;
void setSystem(System *system);
@@ -127,19 +136,25 @@ class CheckerCPU : public BaseCPU
union Result {
uint64_t integer;
-// float fp;
double dbl;
+ void set(uint64_t i) { integer = i; }
+ void set(double d) { dbl = d; }
+ void get(uint64_t& i) { i = integer; }
+ void get(double& d) { d = dbl; }
};
- Result result;
+ // ISAs like ARM can have multiple destination registers to check,
+ // keep them all in a std::queue
+ std::queue<Result> result;
// current instruction
- MachInst machInst;
+ TheISA::MachInst machInst;
// Pointer to the one memory request.
RequestPtr memReq;
StaticInstPtr curStaticInst;
+ StaticInstPtr curMacroStaticInst;
// number of simulated instructions
Counter numInst;
@@ -147,6 +162,9 @@ class CheckerCPU : public BaseCPU
std::queue<int> miscRegIdxs;
+ TheISA::TLB* getITBPtr() { return itb; }
+ TheISA::TLB* getDTBPtr() { return dtb; }
+
virtual Counter totalInstructions() const
{
return 0;
@@ -159,12 +177,6 @@ class CheckerCPU : public BaseCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
-
// These functions are only used in CPU models that split
// effective address computation from the actual memory access.
void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
@@ -198,17 +210,25 @@ class CheckerCPU : public BaseCPU
return thread->readFloatRegBits(reg_idx);
}
+ template <class T>
+ void setResult(T t)
+ {
+ Result instRes;
+ instRes.set(t);
+ result.push(instRes);
+ }
+
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
thread->setIntReg(si->destRegIdx(idx), val);
- result.integer = val;
+ setResult<uint64_t>(val);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
thread->setFloatReg(reg_idx, val);
- result.dbl = (double)val;
+ setResult<double>(val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
@@ -216,12 +236,26 @@ class CheckerCPU : public BaseCPU
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
thread->setFloatRegBits(reg_idx, val);
- result.integer = val;
+ setResult<uint64_t>(val);
}
- uint64_t instAddr() { return thread->instAddr(); }
+ bool readPredicate() { return thread->readPredicate(); }
+ void setPredicate(bool val)
+ {
+ thread->setPredicate(val);
+ }
- uint64_t nextInstAddr() { return thread->nextInstAddr(); }
+ TheISA::PCState pcState() { return thread->pcState(); }
+ void pcState(const TheISA::PCState &val)
+ {
+ DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
+ val, thread->pcState());
+ thread->pcState(val);
+ }
+ Addr instAddr() { return thread->instAddr(); }
+ Addr nextInstAddr() { return thread->nextInstAddr(); }
+ MicroPC microPC() { return thread->microPC(); }
+ //////////////////////////////////////////
MiscReg readMiscRegNoEffect(int misc_reg)
{
@@ -235,7 +269,6 @@ class CheckerCPU : public BaseCPU
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
- result.integer = val;
miscRegIdxs.push(misc_reg);
return thread->setMiscRegNoEffect(misc_reg, val);
}
@@ -246,8 +279,25 @@ class CheckerCPU : public BaseCPU
return thread->setMiscReg(misc_reg, val);
}
- void recordPCChange(uint64_t val) { changedPC = true; newPC = val; }
- void recordNextPCChange(uint64_t val) { changedNextPC = true; }
+ MiscReg readMiscRegOperand(const StaticInst *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
+ return thread->readMiscReg(reg_idx);
+ }
+
+ void setMiscRegOperand(
+ const StaticInst *si, int idx, const MiscReg &val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
+ return thread->setMiscReg(reg_idx, val);
+ }
+ /////////////////////////////////////////
+
+ void recordPCChange(const TheISA::PCState &val)
+ {
+ changedPC = true;
+ newPCState = val;
+ }
void demapPage(Addr vaddr, uint64_t asn)
{
@@ -265,8 +315,17 @@ class CheckerCPU : public BaseCPU
this->dtb->demapPage(vaddr, asn);
}
+ Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+ Fault writeMem(uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res);
+
+ void setStCondFailures(unsigned sc_failures)
+ {}
+ /////////////////////////////////////////////////////
+
Fault hwrei() { return thread->hwrei(); }
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
+ void wakeup() { }
// Assume that the normal CPU's call to syscall was successful.
// The checker's state would have already been updated by the syscall.
void syscall(uint64_t callnum) { }
@@ -277,7 +336,8 @@ class CheckerCPU : public BaseCPU
dumpAndExit();
}
- bool checkFlags(Request *req);
+ bool checkFlags(Request *unverified_req, Addr vAddr,
+ Addr pAddr, int flags);
void dumpAndExit();
@@ -290,7 +350,7 @@ class CheckerCPU : public BaseCPU
bool changedPC;
bool willChangePC;
- uint64_t newPC;
+ TheISA::PCState newPCState;
bool changedNextPC;
bool exitOnError;
bool updateOnError;
@@ -305,24 +365,31 @@ class CheckerCPU : public BaseCPU
* template instantiations of the Checker must be placed at the bottom
* of checker/cpu.cc.
*/
-template <class DynInstPtr>
+template <class Impl>
class Checker : public CheckerCPU
{
+ private:
+ typedef typename Impl::DynInstPtr DynInstPtr;
+
public:
Checker(Params *p)
- : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
+ : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL),
+ predecoder(NULL)
{ }
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
+ void advancePC(Fault fault);
+
void verify(DynInstPtr &inst);
void validateInst(DynInstPtr &inst);
void validateExecution(DynInstPtr &inst);
void validateState();
- void copyResult(DynInstPtr &inst);
+ void copyResult(DynInstPtr &inst, uint64_t mismatch_val, int start_idx);
+ void handlePendingInt();
private:
void handleError(DynInstPtr &inst)
@@ -339,6 +406,7 @@ class Checker : public CheckerCPU
bool updateThisCycle;
DynInstPtr unverifiedInst;
+ TheISA::Predecoder predecoder;
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;
diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh
index 7d8cc8a19..7a99feb06 100644
--- a/src/cpu/checker/cpu_impl.hh
+++ b/src/cpu/checker/cpu_impl.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -26,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
+ * Geoffrey Blake
*/
#include <list>
@@ -34,25 +47,93 @@
#include "arch/vtophys.hh"
#include "base/refcnt.hh"
#include "config/the_isa.hh"
-#include "cpu/checker/cpu.hh"
#include "cpu/base_dyn_inst.hh"
+#include "cpu/exetrace.hh"
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
+#include "cpu/checker/cpu.hh"
+#include "debug/Checker.hh"
#include "sim/full_system.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
using namespace std;
-//The CheckerCPU does alpha only
-using namespace AlphaISA;
+using namespace TheISA;
+
+template <class Impl>
+void
+Checker<Impl>::advancePC(Fault fault)
+{
+ if (fault != NoFault) {
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+ fault->invoke(tc, curStaticInst);
+ predecoder.reset();
+ } else {
+ if (curStaticInst) {
+ if (curStaticInst->isLastMicroop())
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+ TheISA::PCState pcState = thread->pcState();
+ TheISA::advancePC(pcState, curStaticInst);
+ thread->pcState(pcState);
+ DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState());
+ }
+ }
+}
+//////////////////////////////////////////////////
+
+template <class Impl>
+void
+Checker<Impl>::handlePendingInt()
+{
+ DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n",
+ thread->pcState(), instList.size());
+ DynInstPtr boundaryInst = NULL;
+ if (!instList.empty()) {
+ // Set the instructions as completed and verify as much as possible.
+ DynInstPtr inst;
+ typename std::list<DynInstPtr>::iterator itr;
+
+ for (itr = instList.begin(); itr != instList.end(); itr++) {
+ (*itr)->setCompleted();
+ }
+
+ inst = instList.front();
+ boundaryInst = instList.back();
+ verify(inst); // verify the instructions
+ inst = NULL;
+ }
+ if ((!boundaryInst && curMacroStaticInst &&
+ curStaticInst->isDelayedCommit() &&
+ !curStaticInst->isLastMicroop()) ||
+ (boundaryInst && boundaryInst->isDelayedCommit() &&
+ !boundaryInst->isLastMicroop())) {
+ panic("%lli: Trying to take an interrupt in middle of "
+ "a non-interuptable instruction!", curTick());
+ }
+ boundaryInst = NULL;
+ predecoder.reset();
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
+Checker<Impl>::verify(DynInstPtr &completed_inst)
{
DynInstPtr inst;
+ // Make sure serializing instructions are actually
+ // seen as serializing to commit. instList should be
+ // empty in these cases.
+ if ((completed_inst->isSerializing() ||
+ completed_inst->isSerializeBefore()) &&
+ (!instList.empty() ?
+ (instList.front()->seqNum != completed_inst->seqNum) : 0)) {
+ panic("%lli: Instruction sn:%lli at PC %s is serializing before but is"
+ " entering instList with other instructions\n", curTick(),
+ completed_inst->seqNum, completed_inst->pcState());
+ }
+
// Either check this instruction, or add it to a list of
// instructions waiting to be checked. Instructions must be
// checked in program order, so if a store has committed yet not
@@ -60,8 +141,8 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
// behind it that have completed and must be checked.
if (!instList.empty()) {
if (youngestSN < completed_inst->seqNum) {
- DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
- completed_inst->seqNum, completed_inst->readPC());
+ DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
+ completed_inst->seqNum, completed_inst->pcState());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
@@ -75,8 +156,8 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
} else {
if (!completed_inst->isCompleted()) {
if (youngestSN < completed_inst->seqNum) {
- DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
- completed_inst->seqNum, completed_inst->readPC());
+ DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
+ completed_inst->seqNum, completed_inst->pcState());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
@@ -91,17 +172,29 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
}
}
+ // Make sure a serializing instruction is actually seen as
+ // serializing. instList should be empty here
+ if (inst->isSerializeAfter() && !instList.empty()) {
+ panic("%lli: Instruction sn:%lli at PC %s is serializing after but is"
+ " exiting instList with other instructions\n", curTick(),
+ completed_inst->seqNum, completed_inst->pcState());
+ }
unverifiedInst = inst;
+ inst = NULL;
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
while (1) {
- DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
- inst->seqNum, inst->readPC());
- unverifiedResult.integer = inst->readIntResult();
- unverifiedReq = inst->req;
- unverifiedMemData = inst->memData;
+ DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n",
+ unverifiedInst->seqNum, unverifiedInst->pcState());
+ unverifiedReq = NULL;
+ unverifiedReq = unverifiedInst->reqToVerify;
+ unverifiedMemData = unverifiedInst->memData;
+ // Make sure results queue is empty
+ while (!result.empty()) {
+ result.pop();
+ }
numCycles++;
Fault fault = NoFault;
@@ -116,15 +209,15 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.
if (changedPC) {
- DPRINTF(Checker, "Changed PC recently to %#x\n",
- thread->readPC());
+ DPRINTF(Checker, "Changed PC recently to %s\n",
+ thread->pcState());
if (willChangePC) {
- if (newPC == thread->readPC()) {
+ if (newPCState == thread->pcState()) {
DPRINTF(Checker, "Changed PC matches expected PC\n");
} else {
warn("%lli: Changed PC does not match expected PC, "
- "changed: %#x, expected: %#x",
- curTick(), thread->readPC(), newPC);
+ "changed: %s, expected: %s",
+ curTick(), thread->pcState(), newPCState);
CheckerCPU::handleError();
}
willChangePC = false;
@@ -133,118 +226,186 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
- thread->readNextPC());
+ thread->nextInstAddr());
changedNextPC = false;
}
// Try to fetch the instruction
+ uint64_t fetchOffset = 0;
+ bool fetchDone = false;
+
+ while (!fetchDone) {
+ Addr fetch_PC = thread->instAddr();
+ fetch_PC = (fetch_PC & PCMask) + fetchOffset;
+
+ // If not in the middle of a macro instruction
+ if (!curMacroStaticInst) {
+ // set up memory request for instruction fetch
+ memReq = new Request(unverifiedInst->threadNumber, fetch_PC,
+ sizeof(MachInst),
+ 0,
+ fetch_PC, thread->contextId(),
+ unverifiedInst->threadNumber);
+ memReq->setVirt(0, fetch_PC, sizeof(MachInst),
+ Request::INST_FETCH, thread->instAddr());
+
+
+ fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
+
+ if (fault != NoFault) {
+ if (unverifiedInst->getFault() == NoFault) {
+ // In this case the instruction was not a dummy
+ // instruction carrying an ITB fault. In the single
+ // threaded case the ITB should still be able to
+ // translate this instruction; in the SMT case it's
+ // possible that its ITB entry was kicked out.
+ warn("%lli: Instruction PC %s was not found in the "
+ "ITB!", curTick(), thread->pcState());
+ handleError(unverifiedInst);
+
+ // go to the next instruction
+ advancePC(NoFault);
+
+ // Give up on an ITB fault..
+ delete memReq;
+ unverifiedInst = NULL;
+ return;
+ } else {
+ // The instruction is carrying an ITB fault. Handle
+ // the fault and see if our results match the CPU on
+ // the next tick().
+ fault = unverifiedInst->getFault();
+ delete memReq;
+ break;
+ }
+ } else {
+ PacketPtr pkt = new Packet(memReq,
+ MemCmd::ReadReq,
+ Packet::Broadcast);
-#define IFETCH_FLAGS(pc) (FullSystem ? 0 : ((pc) & 1) ? PHYSICAL : 0)
-
- uint64_t fetch_PC = thread->readPC() & ~3;
-
- // set up memory request for instruction fetch
- memReq = new Request(inst->threadNumber, fetch_PC,
- sizeof(uint32_t),
- IFETCH_FLAGS(thread->readPC()),
- fetch_PC, thread->contextId(),
- inst->threadNumber);
-
- bool succeeded = itb->translateAtomic(memReq, thread);
-
- if (!succeeded) {
- if (inst->getFault() == NoFault) {
- // In this case the instruction was not a dummy
- // instruction carrying an ITB fault. In the single
- // threaded case the ITB should still be able to
- // translate this instruction; in the SMT case it's
- // possible that its ITB entry was kicked out.
- warn("%lli: Instruction PC %#x was not found in the ITB!",
- curTick(), thread->readPC());
- handleError(inst);
+ pkt->dataStatic(&machInst);
+ icachePort->sendFunctional(pkt);
+ machInst = gtoh(machInst);
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+ delete memReq;
+ delete pkt;
+ }
+ }
- break;
- } else {
- // The instruction is carrying an ITB fault. Handle
- // the fault and see if our results match the CPU on
- // the next tick().
- fault = inst->getFault();
+ if (fault == NoFault) {
+ TheISA::PCState pcState = thread->pcState();
+
+ if (isRomMicroPC(pcState.microPC())) {
+ fetchDone = true;
+ curStaticInst =
+ microcodeRom.fetchMicroop(pcState.microPC(), NULL);
+ } else if (!curMacroStaticInst) {
+ //We're not in the middle of a macro instruction
+ StaticInstPtr instPtr = NULL;
+
+ //Predecode, ie bundle up an ExtMachInst
+ predecoder.setTC(thread->getTC());
+ //If more fetch data is needed, pass it in.
+ Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
+ predecoder.moreBytes(pcState, fetchPC, machInst);
+
+ //If an instruction is ready, decode it.
+ //Otherwise, we'll have to fetch beyond the
+ //MachInst at the current pc.
+ if (predecoder.extMachInstReady()) {
+ fetchDone = true;
+ ExtMachInst newMachInst =
+ predecoder.getExtMachInst(pcState);
+ thread->pcState(pcState);
+ instPtr = thread->decoder.decode(newMachInst,
+ pcState.instAddr());
+ machInst = newMachInst;
+ } else {
+ fetchDone = false;
+ fetchOffset += sizeof(TheISA::MachInst);
+ }
+
+ //If we decoded an instruction and it's microcoded,
+ //start pulling out micro ops
+ if (instPtr && instPtr->isMacroop()) {
+ curMacroStaticInst = instPtr;
+ curStaticInst =
+ instPtr->fetchMicroop(pcState.microPC());
+ } else {
+ curStaticInst = instPtr;
+ }
+ } else {
+ // Read the next micro op from the macro-op
+ curStaticInst =
+ curMacroStaticInst->fetchMicroop(pcState.microPC());
+ fetchDone = true;
+ }
}
}
+ // reset predecoder on Checker
+ predecoder.reset();
+ // Check Checker and CPU get same instruction, and record
+ // any faults the CPU may have had.
+ Fault unverifiedFault;
if (fault == NoFault) {
- PacketPtr pkt = new Packet(memReq, Packet::ReadReq,
- Packet::Broadcast);
-
- pkt->dataStatic(&machInst);
-
- icachePort->sendFunctional(pkt);
-
- delete pkt;
-
- // keep an instruction count
- numInst++;
+ unverifiedFault = unverifiedInst->getFault();
- // decode the instruction
- machInst = gtoh(machInst);
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
- validateInst(inst);
-
-#if THE_ISA == ALPHA_ISA
- curStaticInst = StaticInst::decode(makeExtMI(machInst,
- thread->readPC()));
-#elif THE_ISA == SPARC_ISA
- curStaticInst = StaticInst::decode(makeExtMI(machInst,
- thread->getTC()));
-#endif
-
- fault = inst->getFault();
+ validateInst(unverifiedInst);
}
- // Discard fetch's memReq.
- delete memReq;
- memReq = NULL;
+ // keep an instruction count
+ numInst++;
+
// Either the instruction was a fault and we should process the fault,
// or we should just go ahead execute the instruction. This assumes
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
+ // Execute Checker instruction and trace
+ if (!unverifiedInst->isUnverifiable()) {
+ Trace::InstRecord *traceData = tracer->getInstRecord(curTick(),
+ tc,
+ curStaticInst,
+ pcState(),
+ curMacroStaticInst);
+ fault = curStaticInst->execute(this, traceData);
+ if (traceData) {
+ traceData->dump();
+ delete traceData;
+ }
+ }
- thread->funcExeInst++;
-
- if (!inst->isUnverifiable())
- fault = curStaticInst->execute(this, NULL);
-
- // Checks to make sure instrution results are correct.
- validateExecution(inst);
+ if (fault == NoFault && unverifiedFault == NoFault) {
+ thread->funcExeInst++;
+ // Checks to make sure instrution results are correct.
+ validateExecution(unverifiedInst);
- if (curStaticInst->isLoad()) {
- ++numLoad;
+ if (curStaticInst->isLoad()) {
+ ++numLoad;
+ }
+ } else if (fault != NoFault && unverifiedFault == NoFault) {
+ panic("%lli: sn: %lli at PC: %s took a fault in checker "
+ "but not in driver CPU\n", curTick(),
+ unverifiedInst->seqNum, unverifiedInst->pcState());
+ } else if (fault == NoFault && unverifiedFault != NoFault) {
+ panic("%lli: sn: %lli at PC: %s took a fault in driver "
+ "CPU but not in checker\n", curTick(),
+ unverifiedInst->seqNum, unverifiedInst->pcState());
}
}
+ // Take any faults here
if (fault != NoFault) {
fault->invoke(tc, curStaticInst);
willChangePC = true;
- newPC = thread->readPC();
- DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
+ newPCState = thread->pcState();
+ DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
} else {
-#if THE_ISA != MIPS_ISA
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
-#else
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
-#endif
-
+ advancePC(fault);
}
if (FullSystem) {
@@ -254,14 +415,14 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
Addr oldpc;
int count = 0;
do {
- oldpc = thread->readPC();
+ oldpc = thread->instAddr();
system->pcEventQueue.service(tc);
count++;
- } while (oldpc != thread->readPC());
+ } while (oldpc != thread->instAddr());
if (count > 1) {
willChangePC = true;
- newPC = thread->readPC();
- DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
+ newPCState = thread->pcState();
+ DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState);
}
}
@@ -269,17 +430,13 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
// that have been modified).
validateState();
- if (memReq) {
- delete memReq;
- memReq = NULL;
- }
-
// Continue verifying instructions if there's another completed
// instruction waiting to be verified.
if (instList.empty()) {
break;
} else if (instList.front()->isCompleted()) {
- inst = instList.front();
+ unverifiedInst = NULL;
+ unverifiedInst = instList.front();
instList.pop_front();
} else {
break;
@@ -288,26 +445,26 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
unverifiedInst = NULL;
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::switchOut()
+Checker<Impl>::switchOut()
{
instList.clear();
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
+Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
{
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
+Checker<Impl>::validateInst(DynInstPtr &inst)
{
- if (inst->readPC() != thread->readPC()) {
- warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
- curTick(), inst->readPC(), thread->readPC());
+ if (inst->instAddr() != thread->instAddr()) {
+ warn("%lli: PCs do not match! Inst: %s, checker: %s",
+ curTick(), inst->pcState(), thread->pcState());
if (changedPC) {
warn("%lli: Changed PCs recently, may not be an error",
curTick());
@@ -319,51 +476,70 @@ Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
if (mi != machInst) {
- warn("%lli: Binary instructions do not match! Inst: %#x, "
+ panic("%lli: Binary instructions do not match! Inst: %#x, "
"checker: %#x",
curTick(), mi, machInst);
handleError(inst);
}
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
+Checker<Impl>::validateExecution(DynInstPtr &inst)
{
+ uint64_t checker_val;
+ uint64_t inst_val;
+ int idx = -1;
bool result_mismatch = false;
- if (inst->numDestRegs()) {
- // @todo: Support more destination registers.
- if (inst->isUnverifiable()) {
- // Unverifiable instructions assume they were executed
- // properly by the CPU. Grab the result from the
- // instruction and write it to the register.
- copyResult(inst);
- } else if (result.integer != inst->readIntResult()) {
- result_mismatch = true;
+
+ if (inst->isUnverifiable()) {
+ // Unverifiable instructions assume they were executed
+ // properly by the CPU. Grab the result from the
+ // instruction and write it to the register.
+ copyResult(inst, 0, idx);
+ } else if (inst->numDestRegs() > 0 && !result.empty()) {
+ DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
+ inst->numDestRegs(), result.size());
+ for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) {
+ result.front().get(checker_val);
+ result.pop();
+ inst_val = 0;
+ inst->template popResult<uint64_t>(inst_val);
+ if (checker_val != inst_val) {
+ result_mismatch = true;
+ idx = i;
+ break;
+ }
}
- }
+ } // Checker CPU checks all the saved results in the dyninst passed by
+ // the cpu model being checked against the saved results present in
+ // the static inst executed in the Checker. Sometimes the number
+ // of saved results differs between the dyninst and static inst, but
+ // this is ok and not a bug. May be worthwhile to try and correct this.
if (result_mismatch) {
warn("%lli: Instruction results do not match! (Values may not "
"actually be integers) Inst: %#x, checker: %#x",
- curTick(), inst->readIntResult(), result.integer);
+ curTick(), inst_val, checker_val);
// It's useful to verify load values from memory, but in MP
// systems the value obtained at execute may be different than
// the value obtained at completion. Similarly DMA can
// present the same problem on even UP systems. Thus there is
// the option to only warn on loads having a result error.
+ // The load/store queue in Detailed CPU can also cause problems
+ // if load/store forwarding is allowed.
if (inst->isLoad() && warnOnlyOnLoadError) {
- copyResult(inst);
+ copyResult(inst, inst_val, idx);
} else {
handleError(inst);
}
}
- if (inst->readNextPC() != thread->readNextPC()) {
+ if (inst->nextInstAddr() != thread->nextInstAddr()) {
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
"checker: %#x",
- curTick(), inst->readNextPC(), thread->readNextPC());
+ curTick(), inst->nextInstAddr(), thread->nextInstAddr());
handleError(inst);
}
@@ -388,53 +564,78 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
}
}
-template <class DynInstPtr>
+
+// This function is weird, if it is called it means the Checker and
+// O3 have diverged, so panic is called for now. It may be useful
+// to resynch states and continue if the divergence is a false positive
+template <class Impl>
void
-Checker<DynInstPtr>::validateState()
+Checker<Impl>::validateState()
{
if (updateThisCycle) {
- warn("%lli: Instruction PC %#x results didn't match up, copying all "
- "registers from main CPU", curTick(), unverifiedInst->readPC());
+ // Change this back to warn if divergences end up being false positives
+ panic("%lli: Instruction PC %#x results didn't match up, copying all "
+ "registers from main CPU", curTick(), unverifiedInst->instAddr());
+
+ // Terribly convoluted way to make sure O3 model does not implode
+ bool inSyscall = unverifiedInst->thread->inSyscall;
+ unverifiedInst->thread->inSyscall = true;
+
// Heavy-weight copying of all registers
thread->copyArchRegs(unverifiedInst->tcBase());
+ unverifiedInst->thread->inSyscall = inSyscall;
+
+ // Set curStaticInst to unverifiedInst->staticInst
+ curStaticInst = unverifiedInst->staticInst;
// Also advance the PC. Hopefully no PC-based events happened.
-#if THE_ISA != MIPS_ISA
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
-#else
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
-#endif
+ advancePC(NoFault);
updateThisCycle = false;
}
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
+Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
+ int start_idx)
{
- RegIndex idx = inst->destRegIdx(0);
- if (idx < TheISA::FP_Base_DepTag) {
- thread->setIntReg(idx, inst->readIntResult());
- } else if (idx < TheISA::Fpcr_DepTag) {
- thread->setFloatRegBits(idx, inst->readIntResult());
- } else {
- thread->setMiscRegNoEffect(idx, inst->readIntResult());
+ // We've already popped one dest off the queue,
+ // so do the fix-up then start with the next dest reg;
+ if (start_idx >= 0) {
+ RegIndex idx = inst->destRegIdx(start_idx);
+ if (idx < TheISA::FP_Base_DepTag) {
+ thread->setIntReg(idx, mismatch_val);
+ } else if (idx < TheISA::Ctrl_Base_DepTag) {
+ thread->setFloatRegBits(idx, mismatch_val);
+ } else if (idx < TheISA::Max_DepTag) {
+ thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag,
+ mismatch_val);
+ }
+ }
+ start_idx++;
+ uint64_t res = 0;
+ for (int i = start_idx; i < inst->numDestRegs(); i++) {
+ RegIndex idx = inst->destRegIdx(i);
+ inst->template popResult<uint64_t>(res);
+ if (idx < TheISA::FP_Base_DepTag) {
+ thread->setIntReg(idx, res);
+ } else if (idx < TheISA::Ctrl_Base_DepTag) {
+ thread->setFloatRegBits(idx, res);
+ } else if (idx < TheISA::Max_DepTag) {
+ // Try to get the proper misc register index for ARM here...
+ thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res);
+ } // else Register is out of range...
}
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
+Checker<Impl>::dumpAndExit(DynInstPtr &inst)
{
cprintf("Error detected, instruction information:\n");
- cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
+ cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
- inst->readPC(),
- inst->readNextPC(),
+ inst->pcState(),
+ inst->nextInstAddr(),
inst->seqNum,
inst->threadNumber,
inst->isCompleted());
@@ -442,9 +643,9 @@ Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
CheckerCPU::dumpAndExit();
}
-template <class DynInstPtr>
+template <class Impl>
void
-Checker<DynInstPtr>::dumpInsts()
+Checker<Impl>::dumpInsts()
{
int num = 0;
@@ -457,9 +658,9 @@ Checker<DynInstPtr>::dumpInsts()
cprintf("Instruction:%i\n",
num);
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+ cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
- (*inst_list_it)->readPC(),
+ (*inst_list_it)->pcState(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isCompleted());
diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh
index 178ded80e..d21de9f53 100644
--- a/src/cpu/checker/thread_context.hh
+++ b/src/cpu/checker/thread_context.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -36,6 +48,7 @@
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
+#include "debug/Checker.hh"
class EndQuiesceEvent;
namespace TheISA {
@@ -77,18 +90,32 @@ class CheckerThreadContext : public ThreadContext
BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); }
- void setCpuId(int id)
+ int cpuId() { return actualTC->cpuId(); }
+
+ int contextId() { return actualTC->contextId(); }
+
+ void setContextId(int id)
{
- actualTC->setCpuId(id);
- checkerTC->setCpuId(id);
+ actualTC->setContextId(id);
+ checkerTC->setContextId(id);
}
- int cpuId() { return actualTC->cpuId(); }
+ /** Returns this thread's ID number. */
+ int threadId() { return actualTC->threadId(); }
+ void setThreadId(int id)
+ {
+ checkerTC->setThreadId(id);
+ actualTC->setThreadId(id);
+ }
TheISA::TLB *getITBPtr() { return actualTC->getITBPtr(); }
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
+ BaseCPU *getCheckerCpuPtr() { return checkerTC->getCpuPtr(); }
+
+ Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
+
System *getSystemPtr() { return actualTC->getSystemPtr(); }
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
@@ -103,8 +130,21 @@ class CheckerThreadContext : public ThreadContext
FSTranslatingPortProxy* getVirtProxy()
{ return actualTC->getVirtProxy(); }
+ //XXX: How does this work now?
+ void initMemProxies(ThreadContext *tc)
+ { actualTC->initMemProxies(tc); }
+
+ void connectMemPorts(ThreadContext *tc)
+ {
+ actualTC->connectMemPorts(tc);
+ }
+
SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); }
+ /** Executes a syscall in SE mode. */
+ void syscall(int64_t callnum)
+ { return actualTC->syscall(callnum); }
+
Status status() const { return actualTC->status(); }
void setStatus(Status new_status)
@@ -118,10 +158,10 @@ class CheckerThreadContext : public ThreadContext
void activate(int delay = 1) { actualTC->activate(delay); }
/// Set the status to Suspended.
- void suspend() { actualTC->suspend(); }
+ void suspend(int delay) { actualTC->suspend(delay); }
/// Set the status to Halted.
- void halt() { actualTC->halt(); }
+ void halt(int delay) { actualTC->halt(delay); }
void dumpFuncProfile() { actualTC->dumpFuncProfile(); }
@@ -131,7 +171,11 @@ class CheckerThreadContext : public ThreadContext
checkerTC->copyState(oldContext);
}
- void regStats(const std::string &name) { actualTC->regStats(name); }
+ void regStats(const std::string &name)
+ {
+ actualTC->regStats(name);
+ checkerTC->regStats(name);
+ }
void serialize(std::ostream &os) { actualTC->serialize(os); }
void unserialize(Checkpoint *cp, const std::string &section)
@@ -145,8 +189,6 @@ class CheckerThreadContext : public ThreadContext
void profileClear() { return actualTC->profileClear(); }
void profileSample() { return actualTC->profileSample(); }
- int threadId() { return actualTC->threadId(); }
-
// @todo: Do I need this?
void copyArchRegs(ThreadContext *tc)
{
@@ -190,32 +232,36 @@ class CheckerThreadContext : public ThreadContext
checkerTC->setFloatRegBits(reg_idx, val);
}
- uint64_t readPC() { return actualTC->readPC(); }
+ /** Reads this thread's PC state. */
+ TheISA::PCState pcState()
+ { return actualTC->pcState(); }
- void setPC(uint64_t val)
+ /** Sets this thread's PC state. */
+ void pcState(const TheISA::PCState &val)
{
- actualTC->setPC(val);
- checkerTC->setPC(val);
+ DPRINTF(Checker, "Changing PC to %s, old PC %s\n",
+ val, checkerTC->pcState());
+ checkerTC->pcState(val);
checkerCPU->recordPCChange(val);
+ return actualTC->pcState(val);
}
- uint64_t readNextPC() { return actualTC->readNextPC(); }
-
- void setNextPC(uint64_t val)
+ void pcStateNoRecord(const TheISA::PCState &val)
{
- actualTC->setNextPC(val);
- checkerTC->setNextPC(val);
- checkerCPU->recordNextPCChange(val);
+ return actualTC->pcState(val);
}
- uint64_t readNextNPC() { return actualTC->readNextNPC(); }
+ /** Reads this thread's PC. */
+ Addr instAddr()
+ { return actualTC->instAddr(); }
- void setNextNPC(uint64_t val)
- {
- actualTC->setNextNPC(val);
- checkerTC->setNextNPC(val);
- checkerCPU->recordNextPCChange(val);
- }
+ /** Reads this thread's next PC. */
+ Addr nextInstAddr()
+ { return actualTC->nextInstAddr(); }
+
+ /** Reads this thread's next PC. */
+ MicroPC microPC()
+ { return actualTC->microPC(); }
MiscReg readMiscRegNoEffect(int misc_reg)
{ return actualTC->readMiscRegNoEffect(misc_reg); }
@@ -225,22 +271,28 @@ class CheckerThreadContext : public ThreadContext
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
+ DPRINTF(Checker, "Setting misc reg with no effect: %d to both Checker"
+ " and O3..\n", misc_reg);
checkerTC->setMiscRegNoEffect(misc_reg, val);
actualTC->setMiscRegNoEffect(misc_reg, val);
}
void setMiscReg(int misc_reg, const MiscReg &val)
{
+ DPRINTF(Checker, "Setting misc reg with effect: %d to both Checker"
+ " and O3..\n", misc_reg);
checkerTC->setMiscReg(misc_reg, val);
actualTC->setMiscReg(misc_reg, val);
}
+ int flattenIntIndex(int reg) { return actualTC->flattenIntIndex(reg); }
+ int flattenFloatIndex(int reg) { return actualTC->flattenFloatIndex(reg); }
+
unsigned readStCondFailures()
{ return actualTC->readStCondFailures(); }
void setStCondFailures(unsigned sc_failures)
{
- checkerTC->setStCondFailures(sc_failures);
actualTC->setStCondFailures(sc_failures);
}
diff --git a/src/cpu/dummy_checker_builder.cc b/src/cpu/dummy_checker_builder.cc
new file mode 100644
index 000000000..0c83dabd0
--- /dev/null
+++ b/src/cpu/dummy_checker_builder.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ *
+ * Authors: Geoffrey Blake
+ */
+
+#include <string>
+
+#include "cpu/checker/cpu.hh"
+#include "cpu/inst_seq.hh"
+#include "params/DummyChecker.hh"
+#include "sim/process.hh"
+#include "sim/sim_object.hh"
+
+class MemObject;
+
+/**
+ * Specific non-templated derived class used for SimObject configuration.
+ */
+class DummyChecker : public CheckerCPU
+{
+ public:
+ DummyChecker(Params *p)
+ : CheckerCPU(p)
+ { }
+};
+
+////////////////////////////////////////////////////////////////////////
+//
+// DummyChecker Simulation Object
+//
+DummyChecker *
+DummyCheckerParams::create()
+{
+ DummyChecker::Params *params = new DummyChecker::Params();
+ params->name = name;
+ params->numThreads = numThreads;
+ params->max_insts_any_thread = 0;
+ params->max_insts_all_threads = 0;
+ params->max_loads_any_thread = 0;
+ params->max_loads_all_threads = 0;
+ params->clock = clock;
+ // Hack to touch all parameters. Consider not deriving Checker
+ // from BaseCPU..it's not really a CPU in the end.
+ Counter temp;
+ temp = max_insts_any_thread;
+ temp = max_insts_all_threads;
+ temp = max_loads_any_thread;
+ temp = max_loads_all_threads;
+ Tick temp2 = progress_interval;
+ params->progress_interval = 0;
+ temp2++;
+
+ params->itb = itb;
+ params->dtb = dtb;
+ params->system = system;
+ params->cpu_id = cpu_id;
+ params->profile = profile;
+ params->interrupts = NULL;
+ params->workload = workload;
+
+ DummyChecker *cpu = new DummyChecker(params);
+ return cpu;
+}
diff --git a/src/cpu/func_unit.hh b/src/cpu/func_unit.hh
index 59c5ee8a0..3745bb7d1 100644
--- a/src/cpu/func_unit.hh
+++ b/src/cpu/func_unit.hh
@@ -47,8 +47,9 @@
//
//
-struct OpDesc : public SimObject
+class OpDesc : public SimObject
{
+ public:
OpClass opClass;
unsigned opLat;
unsigned issueLat;
@@ -58,8 +59,9 @@ struct OpDesc : public SimObject
issueLat(p->issueLat) {};
};
-struct FUDesc : public SimObject
+class FUDesc : public SimObject
{
+ public:
std::vector<OpDesc *> opDescList;
unsigned number;
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index 5a14e92a7..62d48e89e 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -81,7 +81,7 @@ InOrderCPU::TickEvent::process()
const char *
-InOrderCPU::TickEvent::description()
+InOrderCPU::TickEvent::description() const
{
return "InOrderCPU tick event";
}
@@ -165,7 +165,7 @@ InOrderCPU::CPUEvent::process()
const char *
-InOrderCPU::CPUEvent::description()
+InOrderCPU::CPUEvent::description() const
{
return "InOrderCPU event";
}
@@ -1156,11 +1156,11 @@ InOrderCPU::activateNextReadyContext(int delay)
}
void
-InOrderCPU::haltContext(ThreadID tid, int delay)
+InOrderCPU::haltContext(ThreadID tid)
{
DPRINTF(InOrderCPU, "[tid:%i]: Calling Halt Context...\n", tid);
- scheduleCpuEvent(HaltThread, NoFault, tid, dummyInst[tid], delay);
+ scheduleCpuEvent(HaltThread, NoFault, tid, dummyInst[tid]);
activityRec.activity();
}
@@ -1181,9 +1181,9 @@ InOrderCPU::haltThread(ThreadID tid)
}
void
-InOrderCPU::suspendContext(ThreadID tid, int delay)
+InOrderCPU::suspendContext(ThreadID tid)
{
- scheduleCpuEvent(SuspendThread, NoFault, tid, dummyInst[tid], delay);
+ scheduleCpuEvent(SuspendThread, NoFault, tid, dummyInst[tid]);
}
void
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
index 7d22bc902..4abcb05b4 100644
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -147,7 +147,7 @@ class InOrderCPU : public BaseCPU
void process();
/** Returns the description of the tick event. */
- const char *description();
+ const char *description() const;
};
/** The tick event used for scheduling CPU ticks. */
@@ -229,7 +229,7 @@ class InOrderCPU : public BaseCPU
void process();
/** Returns the description of the CPU event. */
- const char *description();
+ const char *description() const;
/** Schedule Event */
void scheduleEvent(int delay);
@@ -469,13 +469,13 @@ class InOrderCPU : public BaseCPU
void deactivateThread(ThreadID tid);
/** Schedule a thread suspension on the CPU */
- void suspendContext(ThreadID tid, int delay = 0);
+ void suspendContext(ThreadID tid);
/** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
void suspendThread(ThreadID tid);
/** Schedule a thread halt on the CPU */
- void haltContext(ThreadID tid, int delay = 0);
+ void haltContext(ThreadID tid);
/** Halt Thread, Remove from Active Thread List, Place Thread on Halted
* Threads List
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
index d2327795e..2ddce13c3 100644
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -512,7 +512,7 @@ ResourceEvent::process()
}
const char *
-ResourceEvent::description()
+ResourceEvent::description() const
{
string desc = resource->name() + "-event:slot[" + to_string(slotIdx)
+ "]";
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
index 78e5af5de..972925d94 100644
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -51,6 +51,9 @@ class ResourceRequest;
typedef ResourceRequest ResReq;
typedef ResourceRequest* ResReqPtr;
+class CacheRequest;
+typedef CacheRequest* CacheReqPtr;
+
class Resource {
public:
typedef ThePipeline::DynInstPtr DynInstPtr;
@@ -154,8 +157,9 @@ class Resource {
* if instruction is actually in resource before
* trying to do access.Needs to be defined for derived units.
*/
- virtual Fault doCacheAccess(DynInstPtr inst, uint64_t *res=NULL)
- { panic("doCacheAccess undefined for %s", name()); return NoFault; }
+ virtual void doCacheAccess(DynInstPtr inst, uint64_t *write_result = NULL,
+ CacheReqPtr split_req = NULL)
+ { panic("doCacheAccess undefined for %s", name()); }
/** Setup Squash to be sent out to pipeline and resource pool */
void setupSquash(DynInstPtr inst, int stage_num, ThreadID tid);
@@ -283,7 +287,7 @@ class ResourceEvent : public Event
virtual void process();
/** Returns the description of the resource event. */
- const char *description();
+ const char *description() const;
/** Set slot idx for event */
void setSlot(int slot) { slotIdx = slot; }
@@ -320,7 +324,7 @@ class ResourceRequest
int reqID;
- virtual void setRequest(DynInstPtr _inst, int stage_num,
+ void setRequest(DynInstPtr _inst, int stage_num,
int res_idx, int slot_num, unsigned _cmd);
virtual void clearRequest();
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index 0e89a7650..50d667ea7 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -485,7 +485,7 @@ ResourcePool::ResPoolEvent::process()
const char *
-ResourcePool::ResPoolEvent::description()
+ResourcePool::ResPoolEvent::description() const
{
return "Resource Pool event";
}
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
index e892d750a..4f05494c4 100644
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -118,7 +118,7 @@ class ResourcePool {
void process();
/** Returns the description of the resource event. */
- const char *description();
+ const char *description() const;
/** Schedule Event */
void scheduleEvent(int delay);
diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh
index 2155c920c..416cb76d1 100644
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -49,9 +49,6 @@
#include "params/InOrderCPU.hh"
#include "sim/sim_object.hh"
-class CacheRequest;
-typedef CacheRequest* CacheReqPtr;
-
class CacheReqPacket;
typedef CacheReqPacket* CacheReqPktPtr;
diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc
index acfcf0939..1a7ac0890 100644
--- a/src/cpu/inorder/thread_context.cc
+++ b/src/cpu/inorder/thread_context.cc
@@ -122,7 +122,7 @@ InOrderThreadContext::suspend(int delay)
return;
thread->setStatus(ThreadContext::Suspended);
- cpu->suspendContext(thread->threadId(), delay);
+ cpu->suspendContext(thread->threadId());
}
void
@@ -135,7 +135,7 @@ InOrderThreadContext::halt(int delay)
return;
thread->setStatus(ThreadContext::Halted);
- cpu->haltContext(thread->threadId(), delay);
+ cpu->haltContext(thread->threadId());
}
diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh
index 9869853c4..f6bf63d76 100644
--- a/src/cpu/nativetrace.hh
+++ b/src/cpu/nativetrace.hh
@@ -108,7 +108,7 @@ class NativeTrace : public ExeTracer
{
size_t soFar = 0;
while (soFar < size) {
- size_t res = ::read(fd, (uint8_t *)ptr + soFar, size - soFar);
+ ssize_t res = ::read(fd, (uint8_t *)ptr + soFar, size - soFar);
if (res < 0)
panic("Read call failed! %s\n", strerror(errno));
else
diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py
index c3e561cd9..acc7a9056 100644
--- a/src/cpu/o3/O3CPU.py
+++ b/src/cpu/o3/O3CPU.py
@@ -40,11 +40,15 @@ class DerivO3CPU(BaseCPU):
activity = Param.Unsigned(0, "Initial count")
if buildEnv['USE_CHECKER']:
- checker = Param.BaseCPU(O3Checker(workload=Parent.workload,
+ # FIXME: Shouldn't need to derefernce Parent.workload
+ # Somewhere in the param parsing code
+ # src/python/m5/params.py is and error that
+ # has trouble converting the workload parameter properly.
+ checker = Param.BaseCPU(O3Checker(workload=Parent.workload[0],
exitOnError=False,
updateOnError=True,
- warnOnlyOnLoadError=False),
- "checker")
+ warnOnlyOnLoadError=True),
+ "checker")
checker.itb = Parent.itb
checker.dtb = Parent.dtb
diff --git a/src/cpu/o3/O3Checker.py b/src/cpu/o3/O3Checker.py
index d0c4ce537..d53e5e527 100644
--- a/src/cpu/o3/O3Checker.py
+++ b/src/cpu/o3/O3Checker.py
@@ -34,7 +34,7 @@ class O3Checker(BaseCPU):
exitOnError = Param.Bool(False, "Exit on an error")
updateOnError = Param.Bool(False,
"Update the checker with the main CPU's state on an error")
- warnOnlyOnLoadError = Param.Bool(False,
+ warnOnlyOnLoadError = Param.Bool(True,
"If a load result is incorrect, only print a warning and do not exit")
function_trace = Param.Bool(False, "Enable function trace")
function_trace_start = Param.Tick(0, "Cycle to start function trace")
diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh
index 84f2dc8c1..8dbba9085 100644
--- a/src/cpu/o3/bpred_unit.hh
+++ b/src/cpu/o3/bpred_unit.hh
@@ -41,7 +41,7 @@
#include "cpu/pred/tournament.hh"
#include "cpu/inst_seq.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
/**
* Basically a wrapper class to hold both the branch predictor
diff --git a/src/cpu/o3/checker_builder.cc b/src/cpu/o3/checker_builder.cc
index b34613f68..72b50d104 100644
--- a/src/cpu/o3/checker_builder.cc
+++ b/src/cpu/o3/checker_builder.cc
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -31,8 +43,8 @@
#include <string>
#include "cpu/checker/cpu_impl.hh"
-#include "cpu/o3/alpha/dyn_inst.hh"
-#include "cpu/o3/alpha/impl.hh"
+#include "cpu/o3/dyn_inst.hh"
+#include "cpu/o3/impl.hh"
#include "cpu/inst_seq.hh"
#include "params/O3Checker.hh"
#include "sim/process.hh"
@@ -41,16 +53,16 @@
class MemObject;
template
-class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
+class Checker<O3CPUImpl>;
/**
* Specific non-templated derived class used for SimObject configuration.
*/
-class O3Checker : public Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >
+class O3Checker : public Checker<O3CPUImpl>
{
public:
O3Checker(Params *p)
- : Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >(p)
+ : Checker<O3CPUImpl>(p)
{ }
};
@@ -63,7 +75,7 @@ O3CheckerParams::create()
{
O3Checker::Params *params = new O3Checker::Params();
params->name = name;
- params->numberOfThreads = 1;
+ params->numThreads = numThreads;
params->max_insts_any_thread = 0;
params->max_insts_all_threads = 0;
params->max_loads_any_thread = 0;
@@ -71,10 +83,8 @@ O3CheckerParams::create()
params->exitOnError = exitOnError;
params->updateOnError = updateOnError;
params->warnOnlyOnLoadError = warnOnlyOnLoadError;
- params->deferRegistration = defer_registration;
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
params->clock = clock;
+ params->tracer = tracer;
// Hack to touch all parameters. Consider not deriving Checker
// from BaseCPU..it's not really a CPU in the end.
Counter temp;
@@ -91,7 +101,8 @@ O3CheckerParams::create()
params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
- params->process = workload;
+ params->interrupts = NULL;
+ params->workload = workload;
O3Checker *cpu = new O3Checker(params);
return cpu;
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index b45d37df9..f35928b08 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -51,10 +51,10 @@
#include "cpu/inst_seq.hh"
#include "cpu/timebuf.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
template <class>
-class O3ThreadState;
+struct O3ThreadState;
/**
* DefaultCommit handles single threaded and SMT commit. Its width is
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index b6a4c0387..edf7e861b 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -725,6 +725,12 @@ DefaultCommit<Impl>::handleInterrupt()
assert(!thread[0]->inSyscall);
thread[0]->inSyscall = true;
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->handlePendingInt();
+ }
+#endif
+
// CPU will handle interrupt.
cpu->processInterrupts(interrupt);
@@ -769,8 +775,8 @@ void
DefaultCommit<Impl>::commit()
{
if (FullSystem) {
- // Check for any interrupt that we've already squashed for and start
- // processing it.
+ // Check for any interrupt that we've already squashed for and
+ // start processing it.
if (interrupt != NoFault)
handleInterrupt();
@@ -1128,7 +1134,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
head_inst->setCompleted();
#if USE_CHECKER
- if (cpu->checker && head_inst->isStore()) {
+ if (cpu->checker) {
+ // Need to check the instruction before its fault is processed
cpu->checker->verify(head_inst);
}
#endif
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index ef08c96f4..d16270943 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -65,6 +65,7 @@
#if USE_CHECKER
#include "cpu/checker/cpu.hh"
+#include "cpu/checker/thread_context.hh"
#endif
#if THE_ISA == ALPHA_ISA
@@ -72,7 +73,7 @@
#include "debug/Activity.hh"
#endif
-class BaseCPUParams;
+struct BaseCPUParams;
using namespace TheISA;
using namespace std;
@@ -265,7 +266,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
#if USE_CHECKER
if (params->checker) {
BaseCPU *temp_checker = params->checker;
- checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
+ checker = dynamic_cast<Checker<Impl> *>(temp_checker);
checker->setIcachePort(&icachePort);
checker->setSystem(params->system);
} else {
@@ -759,7 +760,8 @@ FullO3CPU<Impl>::activateContext(ThreadID tid, int delay)
template <class Impl>
bool
-FullO3CPU<Impl>::deallocateContext(ThreadID tid, bool remove, int delay)
+FullO3CPU<Impl>::scheduleDeallocateContext(ThreadID tid, bool remove,
+ int delay)
{
// Schedule removal of thread data from CPU
if (delay){
@@ -780,7 +782,7 @@ void
FullO3CPU<Impl>::suspendContext(ThreadID tid)
{
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
- bool deallocated = deallocateContext(tid, false, 1);
+ bool deallocated = scheduleDeallocateContext(tid, false, 1);
// If this was the last thread then unschedule the tick event.
if ((activeThreads.size() == 1 && !deallocated) ||
activeThreads.size() == 0)
@@ -797,7 +799,7 @@ FullO3CPU<Impl>::haltContext(ThreadID tid)
{
//For now, this is the same as deallocate
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
- deallocateContext(tid, true, 1);
+ scheduleDeallocateContext(tid, true, 1);
}
template <class Impl>
@@ -1216,7 +1218,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
activityRec.reset();
- BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
+ BaseCPU::takeOverFrom(oldCPU);
fetch.takeOverFrom();
decode.takeOverFrom();
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 165144c1b..94c0a873b 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -78,7 +78,7 @@ class Checkpoint;
class MemObject;
class Process;
-class BaseCPUParams;
+struct BaseCPUParams;
class BaseO3CPU : public BaseCPU
{
@@ -400,7 +400,7 @@ class FullO3CPU : public BaseO3CPU
/** Remove Thread from Active Threads List &&
* Possibly Remove Thread Context from CPU.
*/
- bool deallocateContext(ThreadID tid, bool remove, int delay = 1);
+ bool scheduleDeallocateContext(ThreadID tid, bool remove, int delay = 1);
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
@@ -725,7 +725,7 @@ class FullO3CPU : public BaseO3CPU
* instruction results at run time. This can be set to NULL if it
* is not being used.
*/
- Checker<DynInstPtr> *checker;
+ Checker<Impl> *checker;
#endif
/** Pointer to the system. */
diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 482b4b7fc..663831254 100644
--- a/src/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
@@ -36,7 +36,7 @@
#include "base/statistics.hh"
#include "cpu/timebuf.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
/**
* DefaultDecode class handles both single threaded and SMT
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 985e92826..60bca1041 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -38,7 +38,9 @@
#include "params/DerivO3CPU.hh"
#include "sim/full_system.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::list;
template<class Impl>
DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh
index 76a456ee3..ed1e374e8 100644
--- a/src/cpu/o3/dyn_inst_impl.hh
+++ b/src/cpu/o3/dyn_inst_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -41,6 +41,7 @@
*/
#include "base/cp_annotate.hh"
+#include "config/use_checker.hh"
#include "cpu/o3/dyn_inst.hh"
#include "sim/full_system.hh"
@@ -137,6 +138,11 @@ BaseO3DynInst<Impl>::completeAcc(PacketPtr pkt)
bool in_syscall = this->thread->inSyscall;
this->thread->inSyscall = true;
+#if USE_CHECKER
+ if (this->isStoreConditional()) {
+ this->reqToVerify->setExtraData(pkt->req->getExtraData());
+ }
+#endif
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
this->thread->inSyscall = in_syscall;
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index f5d275593..b61ae2c7b 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -56,7 +56,7 @@
#include "mem/port.hh"
#include "sim/eventq.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
/**
* DefaultFetch class handles both single threaded and SMT fetch. Its
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 1b82f8a4c..553198980 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -43,6 +43,9 @@
#include <algorithm>
#include <cstring>
+#include <list>
+#include <map>
+#include <queue>
#include "arch/isa_traits.hh"
#include "arch/tlb.hh"
@@ -52,7 +55,6 @@
#include "config/the_isa.hh"
#include "config/use_checker.hh"
#include "cpu/base.hh"
-#include "cpu/checker/cpu.hh"
#include "cpu/o3/fetch.hh"
#include "cpu/exetrace.hh"
#include "debug/Activity.hh"
@@ -66,6 +68,10 @@
#include "sim/full_system.hh"
#include "sim/system.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif // USE_CHECKER
+
using namespace std;
template<class Impl>
diff --git a/src/cpu/o3/fu_pool.cc b/src/cpu/o3/fu_pool.cc
index b7c972b09..3f0e46543 100644
--- a/src/cpu/o3/fu_pool.cc
+++ b/src/cpu/o3/fu_pool.cc
@@ -252,7 +252,7 @@ FUPool::switchOut()
}
void
-FUPool::takeOverFrom()
+FUPool::takeOver()
{
for (int i = 0; i < numFU; i++) {
unitBusy[i] = false;
diff --git a/src/cpu/o3/fu_pool.hh b/src/cpu/o3/fu_pool.hh
index ea4b53e1a..66804b534 100644
--- a/src/cpu/o3/fu_pool.hh
+++ b/src/cpu/o3/fu_pool.hh
@@ -37,7 +37,6 @@
#include <vector>
#include "cpu/op_class.hh"
-#include "cpu/sched_list.hh"
#include "params/FUPool.hh"
#include "sim/sim_object.hh"
@@ -162,7 +161,7 @@ class FUPool : public SimObject
void switchOut();
/** Takes over from another CPU's thread. */
- void takeOverFrom();
+ void takeOver();
};
#endif // __CPU_O3_FU_POOL_HH__
diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index 0d7e0f68f..adb797525 100644
--- a/src/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
@@ -53,7 +53,7 @@
#include "cpu/timebuf.hh"
#include "debug/IEW.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
class FUPool;
/**
@@ -93,9 +93,6 @@ class DefaultIEW
typedef typename CPUPol::RenameStruct RenameStruct;
typedef typename CPUPol::IssueStruct IssueStruct;
- friend class Impl::O3CPU;
- friend class CPUPol::IQ;
-
public:
/** Overall IEW stage status. Used to determine if the CPU can
* deschedule itself due to a lack of activity.
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 92c8875e4..97b41ad9f 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -48,6 +48,7 @@
#include "arch/utility.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/o3/fu_pool.hh"
#include "cpu/o3/iew.hh"
#include "cpu/timebuf.hh"
@@ -56,6 +57,10 @@
#include "debug/IEW.hh"
#include "params/DerivO3CPU.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif // USE_CHECKER
+
using namespace std;
template<class Impl>
@@ -294,6 +299,13 @@ DefaultIEW<Impl>::initStage()
ldstQueue.numFreeEntries(tid);
}
+// Initialize the checker's dcache port here
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->setDcachePort(cpu->getDcachePort());
+ }
+#endif
+
cpu->activateStage(O3CPU::IEWIdx);
}
@@ -400,7 +412,7 @@ DefaultIEW<Impl>::takeOverFrom()
instQueue.takeOverFrom();
ldstQueue.takeOverFrom();
- fuPool->takeOverFrom();
+ fuPool->takeOver();
initStage();
cpu->activityThisCycle();
diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh
index eb35fd285..9ceab1525 100644
--- a/src/cpu/o3/inst_queue.hh
+++ b/src/cpu/o3/inst_queue.hh
@@ -56,7 +56,7 @@
#include "cpu/timebuf.hh"
#include "sim/eventq.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
class FUPool;
class MemInterface;
@@ -93,8 +93,6 @@ class InstructionQueue
// Typedef of iterator through the list of instructions.
typedef typename std::list<DynInstPtr>::iterator ListIt;
- friend class Impl::O3CPU;
-
/** FU completion event class. */
class FUCompletion : public Event {
private:
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index b2016cc9c..2c0779a03 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -51,7 +51,9 @@
#include "params/DerivO3CPU.hh"
#include "sim/core.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::list;
template <class Impl>
InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index db127a2da..b821dd3f9 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -51,7 +51,7 @@
#include "mem/port.hh"
#include "sim/sim_object.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
template <class Impl>
class LSQ {
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 3c1a4eda3..4247c3796 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -51,7 +51,7 @@
#include "mem/packet.hh"
#include "mem/port.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
/**
* Class that implements the actual LQ and SQ for each specific
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index d0db6f6fe..facd88597 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -45,7 +45,6 @@
#include "arch/locked_mem.hh"
#include "base/str.hh"
#include "config/the_isa.hh"
-#include "config/use_checker.hh"
#include "cpu/o3/lsq.hh"
#include "cpu/o3/lsq_unit.hh"
#include "debug/Activity.hh"
@@ -246,12 +245,6 @@ void
LSQUnit<Impl>::setDcachePort(Port *dcache_port)
{
dcachePort = dcache_port;
-
-#if USE_CHECKER
- if (cpu->checker) {
- cpu->checker->setDcachePort(dcachePort);
- }
-#endif
}
template<class Impl>
@@ -878,6 +871,11 @@ LSQUnit<Impl>::writebackStores()
inst->seqNum);
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
cpu->schedule(wb, curTick() + 1);
+#if USE_CHECKER
+ // Make sure to set the LLSC data for verification
+ inst->reqToVerify->setExtraData(0);
+ inst->completeAcc(data_pkt);
+#endif
completeStore(storeWBIdx);
incrStIdx(storeWBIdx);
continue;
diff --git a/src/cpu/o3/mem_dep_unit.cc b/src/cpu/o3/mem_dep_unit.cc
index ac0db4784..234a6f9c4 100644
--- a/src/cpu/o3/mem_dep_unit.cc
+++ b/src/cpu/o3/mem_dep_unit.cc
@@ -32,10 +32,6 @@
#include "cpu/o3/mem_dep_unit_impl.hh"
#include "cpu/o3/store_set.hh"
-// Force instantation of memory dependency unit using store sets and
-// O3CPUImpl.
-template class MemDepUnit<StoreSet, O3CPUImpl>;
-
#ifdef DEBUG
template <>
int
@@ -47,3 +43,7 @@ template <>
int
MemDepUnit<StoreSet, O3CPUImpl>::MemDepEntry::memdep_erase = 0;
#endif
+
+// Force instantation of memory dependency unit using store sets and
+// O3CPUImpl.
+template class MemDepUnit<StoreSet, O3CPUImpl>;
diff --git a/src/cpu/o3/mem_dep_unit.hh b/src/cpu/o3/mem_dep_unit.hh
index 7d00369d3..ce5a62ef8 100644
--- a/src/cpu/o3/mem_dep_unit.hh
+++ b/src/cpu/o3/mem_dep_unit.hh
@@ -49,7 +49,7 @@ struct SNHash {
}
};
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
template <class Impl>
class InstructionQueue;
diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index e2472a62d..a5c83dfea 100644
--- a/src/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
@@ -37,7 +37,7 @@
#include "config/the_isa.hh"
#include "cpu/timebuf.hh"
-class DerivO3CPUParams;
+struct DerivO3CPUParams;
/**
* DefaultRename handles both single threaded and SMT rename. Its
diff --git a/src/cpu/o3/sat_counter.hh b/src/cpu/o3/sat_counter.hh
index 7dd840f31..17ff8546b 100644
--- a/src/cpu/o3/sat_counter.hh
+++ b/src/cpu/o3/sat_counter.hh
@@ -65,7 +65,8 @@ class SatCounter
* @param initial_val Starting value for each counter.
*/
SatCounter(unsigned bits, uint8_t initial_val)
- : initialVal(initialVal), maxVal((1 << bits) - 1), counter(initial_val)
+ : initialVal(initial_val), maxVal((1 << bits) - 1),
+ counter(initial_val)
{
// Check to make sure initial value doesn't exceed the max
// counter value.
diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh
index ffe828c94..c2096fab2 100755
--- a/src/cpu/o3/thread_context.hh
+++ b/src/cpu/o3/thread_context.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -32,6 +44,7 @@
#define __CPU_O3_THREAD_CONTEXT_HH__
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/thread_context.hh"
@@ -71,6 +84,10 @@ class O3ThreadContext : public ThreadContext
/** Returns a pointer to the DTB. */
TheISA::TLB *getDTBPtr() { return cpu->dtb; }
+#if USE_CHECKER
+ BaseCPU *getCheckerCpuPtr() { return NULL; }
+#endif
+
Decoder *getDecoderPtr() { return &cpu->fetch.decoder; }
/** Returns a pointer to this CPU. */
@@ -177,6 +194,10 @@ class O3ThreadContext : public ThreadContext
/** Sets this thread's PC state. */
virtual void pcState(const TheISA::PCState &val);
+#if USE_CHECKER
+ virtual void pcStateNoRecord(const TheISA::PCState &val);
+#endif
+
/** Reads this thread's PC. */
virtual Addr instAddr()
{ return cpu->instAddr(thread->threadId()); }
diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh
index 5ba454458..2ea39f3eb 100755
--- a/src/cpu/o3/thread_context_impl.hh
+++ b/src/cpu/o3/thread_context_impl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -44,6 +44,7 @@
#include "arch/kernel_stats.hh"
#include "arch/registers.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/o3/thread_context.hh"
#include "cpu/quiesce_event.hh"
#include "debug/O3CPU.hh"
@@ -296,6 +297,20 @@ O3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
}
}
+#if USE_CHECKER
+template <class Impl>
+void
+O3ThreadContext<Impl>::pcStateNoRecord(const TheISA::PCState &val)
+{
+ cpu->pcState(val, thread->threadId());
+
+ // Squash if we're not already in a state update mode.
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromTC(thread->threadId());
+ }
+}
+#endif
+
template <class Impl>
int
O3ThreadContext<Impl>::flattenIntIndex(int reg)
diff --git a/src/cpu/quiesce_event.hh b/src/cpu/quiesce_event.hh
index 85c88ab32..74db27481 100644
--- a/src/cpu/quiesce_event.hh
+++ b/src/cpu/quiesce_event.hh
@@ -36,8 +36,9 @@
class ThreadContext;
/** Event for timing out quiesce instruction */
-struct EndQuiesceEvent : public Event
+class EndQuiesceEvent : public Event
{
+ public:
/** A pointer to the thread context that is quiesced */
ThreadContext *tc;
diff --git a/src/cpu/sched_list.hh b/src/cpu/sched_list.hh
deleted file mode 100644
index 4d3b0dd71..000000000
--- a/src/cpu/sched_list.hh
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2002-2005 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.
- *
- * Authors: Steve Raasch
- */
-
-#ifndef SCHED_LIST_HH
-#define SCHED_LIST_HH
-
-#include <list>
-
-#include "base/intmath.hh"
-#include "base/misc.hh"
-
-// Any types you use this class for must be covered here...
-namespace {
- void ClearEntry(int &i) { i = 0; };
- void ClearEntry(unsigned &i) { i = 0; };
- void ClearEntry(double &i) { i = 0; };
- template <class T> void ClearEntry(std::list<T> &l) { l.clear(); };
-};
-
-
-//
-// this is a special list type that allows the user to insert elements at a
-// specified positive offset from the "current" element, but only allow them
-// be extracted from the "current" element
-//
-
-
-template <class T>
-class SchedList
-{
- T *data_array;
- unsigned position;
- unsigned size;
- unsigned mask;
-
- public:
- SchedList(unsigned size);
- SchedList(void);
-
- void init(unsigned size);
-
- T &operator[](unsigned offset);
-
- void advance(void);
-
- void clear(void);
-};
-
-
-
-//
-// Constructor
-//
-template<class T>
-SchedList<T>::SchedList(unsigned _size)
-{
- size = _size;
-
- // size must be a power of two
- if (!isPowerOf2(size)) {
- panic("SchedList: size must be a power of two");
- }
-
- if (size < 2) {
- panic("SchedList: you don't want a list that small");
- }
-
- // calculate the bit mask for the modulo operation
- mask = size - 1;
-
- data_array = new T[size];
-
- if (!data_array) {
- panic("SchedList: could not allocate memory");
- }
-
- clear();
-}
-
-template<class T>
-SchedList<T>::SchedList(void)
-{
- data_array = 0;
- size = 0;
-}
-
-
-template<class T> void
-SchedList<T>::init(unsigned _size)
-{
- size = _size;
-
- if (!data_array) {
- // size must be a power of two
- if (size & (size-1)) {
- panic("SchedList: size must be a power of two");
- }
-
- if (size < 2) {
- panic("SchedList: you don't want a list that small");
- }
-
- // calculate the bit mask for the modulo operation
- mask = size - 1;
-
- data_array = new T[size];
-
- if (!data_array) {
- panic("SchedList: could not allocate memory");
- }
-
- clear();
- }
-}
-
-
-template<class T> void
-SchedList<T>::advance(void)
-{
- ClearEntry(data_array[position]);
-
- // position = (++position % size);
- position = ++position & mask;
-}
-
-
-template<class T> void
-SchedList<T>::clear(void)
-{
- for (unsigned i=0; i<size; ++i) {
- ClearEntry(data_array[i]);
- }
-
- position = 0;
-}
-
-
-template<class T> T&
-SchedList<T>::operator[](unsigned offset)
-{
- if (offset >= size) {
- panic("SchedList: can't access element beyond current pointer");
- }
-
- // unsigned p = (position + offset) % size;
- unsigned p = (position + offset) & mask;
-
- return data_array[p];
-}
-
-
-
-#endif
diff --git a/src/cpu/simple/BaseSimpleCPU.py b/src/cpu/simple/BaseSimpleCPU.py
index 9f528bc20..ea2c642e6 100644
--- a/src/cpu/simple/BaseSimpleCPU.py
+++ b/src/cpu/simple/BaseSimpleCPU.py
@@ -26,9 +26,18 @@
#
# Authors: Gabe Black
+from m5.defines import buildEnv
from m5.params import *
from BaseCPU import BaseCPU
+if buildEnv['USE_CHECKER']:
+ from DummyChecker import DummyChecker
+
class BaseSimpleCPU(BaseCPU):
type = 'BaseSimpleCPU'
abstract = True
+
+ if buildEnv['USE_CHECKER']:
+ checker = Param.BaseCPU(DummyChecker(), "checker")
+ checker.itb = BaseCPU.itb
+ checker.dtb = BaseCPU.dtb
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 2c12b244b..24e2f1eb8 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -175,7 +175,7 @@ AtomicSimpleCPU::switchOut()
void
AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
{
- BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
+ BaseCPU::takeOverFrom(oldCPU);
assert(!tickEvent.scheduled());
@@ -201,7 +201,7 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
void
-AtomicSimpleCPU::activateContext(int thread_num, int delay)
+AtomicSimpleCPU::activateContext(ThreadID thread_num, int delay)
{
DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
@@ -221,7 +221,7 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay)
void
-AtomicSimpleCPU::suspendContext(int thread_num)
+AtomicSimpleCPU::suspendContext(ThreadID thread_num)
{
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index 77a9d6b0d..f677ed49b 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -112,8 +112,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
- virtual void activateContext(int thread_num, int delay);
- virtual void suspendContext(int thread_num);
+ virtual void activateContext(ThreadID thread_num, int delay);
+ virtual void suspendContext(ThreadID thread_num);
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 610cc6b89..97ce3264a 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -56,6 +56,7 @@
#include "base/trace.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/simple/base.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
@@ -79,6 +80,11 @@
#include "sim/stats.hh"
#include "sim/system.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#include "cpu/checker/thread_context.hh"
+#endif
+
using namespace std;
using namespace TheISA;
@@ -95,6 +101,19 @@ BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
tc = thread->getTC();
+#if USE_CHECKER
+ if (p->checker) {
+ BaseCPU *temp_checker = p->checker;
+ checker = dynamic_cast<CheckerCPU *>(temp_checker);
+ checker->setSystem(p->system);
+ // Manipulate thread context
+ ThreadContext *cpu_tc = tc;
+ tc = new CheckerThreadContext<ThreadContext>(cpu_tc, this->checker);
+ } else {
+ checker = NULL;
+ }
+#endif
+
numInst = 0;
startNumInst = 0;
numLoad = 0;
@@ -114,7 +133,7 @@ BaseSimpleCPU::~BaseSimpleCPU()
}
void
-BaseSimpleCPU::deallocateContext(int thread_num)
+BaseSimpleCPU::deallocateContext(ThreadID thread_num)
{
// for now, these are equivalent
suspendContext(thread_num);
@@ -122,7 +141,7 @@ BaseSimpleCPU::deallocateContext(int thread_num)
void
-BaseSimpleCPU::haltContext(int thread_num)
+BaseSimpleCPU::haltContext(ThreadID thread_num)
{
// for now, these are equivalent
suspendContext(thread_num);
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 0e5526040..55dec5d53 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -36,6 +48,7 @@
#include "arch/predecoder.hh"
#include "base/statistics.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/base.hh"
#include "cpu/decode.hh"
#include "cpu/pc_event.hh"
@@ -48,6 +61,10 @@
#include "sim/full_system.hh"
#include "sim/system.hh"
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif
+
// forward declarations
class Checkpoint;
class MemObject;
@@ -66,7 +83,7 @@ namespace Trace {
class InstRecord;
}
-class BaseSimpleCPUParams;
+struct BaseSimpleCPUParams;
class BaseSimpleCPU : public BaseCPU
@@ -111,6 +128,10 @@ class BaseSimpleCPU : public BaseCPU
* objects to modify this thread's state.
*/
ThreadContext *tc;
+
+#if USE_CHECKER
+ CheckerCPU *checker;
+#endif
protected:
enum Status {
@@ -157,8 +178,8 @@ class BaseSimpleCPU : public BaseCPU
void postExecute();
void advancePC(Fault fault);
- virtual void deallocateContext(int thread_num);
- virtual void haltContext(int thread_num);
+ virtual void deallocateContext(ThreadID thread_num);
+ virtual void haltContext(ThreadID thread_num);
// statistics
virtual void regStats();
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index fd02e8300..6cf7c582c 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -176,7 +176,7 @@ TimingSimpleCPU::switchOut()
void
TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
{
- BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
+ BaseCPU::takeOverFrom(oldCPU);
// if any of this CPU's ThreadContexts are active, mark the CPU as
// running and schedule its tick event.
@@ -197,7 +197,7 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
void
-TimingSimpleCPU::activateContext(int thread_num, int delay)
+TimingSimpleCPU::activateContext(ThreadID thread_num, int delay)
{
DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
@@ -215,7 +215,7 @@ TimingSimpleCPU::activateContext(int thread_num, int delay)
void
-TimingSimpleCPU::suspendContext(int thread_num)
+TimingSimpleCPU::suspendContext(ThreadID thread_num)
{
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index dce3c58ff..ed91524cf 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -244,8 +244,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
- virtual void activateContext(int thread_num, int delay);
- virtual void suspendContext(int thread_num);
+ virtual void activateContext(ThreadID thread_num, int delay);
+ virtual void suspendContext(ThreadID thread_num);
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index a12ab8e8a..e193b1273 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -47,14 +47,13 @@
#include "cpu/quiesce_event.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
-#include "params/BaseCPU.hh"
#include "mem/fs_translating_port_proxy.hh"
#include "mem/se_translating_port_proxy.hh"
+#include "params/BaseCPU.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
-#include "sim/process.hh"
#include "sim/system.hh"
using namespace std;
@@ -62,8 +61,7 @@ using namespace std;
// constructor
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
TheISA::TLB *_itb, TheISA::TLB *_dtb)
- : ThreadState(_cpu, _thread_num, _process),
- cpu(_cpu), itb(_itb), dtb(_dtb)
+ : ThreadState(_cpu, _thread_num, _process), itb(_itb), dtb(_dtb)
{
clearArchRegs();
tc = new ProxyThreadContext<SimpleThread>(this);
@@ -71,9 +69,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
TheISA::TLB *_itb, TheISA::TLB *_dtb,
bool use_kernel_stats)
- : ThreadState(_cpu, _thread_num, NULL),
- cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb)
-
+ : ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb)
{
tc = new ProxyThreadContext<SimpleThread>(this);
@@ -81,7 +77,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
clearArchRegs();
- if (cpu->params()->profile) {
+ if (baseCpu->params()->profile) {
profile = new FunctionProfile(system->kernelSymtab);
Callback *cb =
new MakeCallback<SimpleThread,
@@ -183,7 +179,7 @@ SimpleThread::serialize(ostream &os)
//
// Now must serialize all the ISA dependent state
//
- isa.serialize(cpu, os);
+ isa.serialize(baseCpu, os);
}
@@ -199,13 +195,14 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
//
// Now must unserialize all the ISA dependent state
//
- isa.unserialize(cpu, cp, section);
+ isa.unserialize(baseCpu, cp, section);
}
void
SimpleThread::dumpFuncProfile()
{
- std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
+ std::ostream *os = simout.create(csprintf("profile.%s.dat",
+ baseCpu->name()));
profile->dump(tc, *os);
}
@@ -225,7 +222,7 @@ SimpleThread::activate(int delay)
_status = ThreadContext::Active;
// status() == Suspended
- cpu->activateContext(_threadId, delay);
+ baseCpu->activateContext(_threadId, delay);
}
void
@@ -237,7 +234,7 @@ SimpleThread::suspend()
lastActivate = curTick();
lastSuspend = curTick();
_status = ThreadContext::Suspended;
- cpu->suspendContext(_threadId);
+ baseCpu->suspendContext(_threadId);
}
@@ -248,7 +245,7 @@ SimpleThread::halt()
return;
_status = ThreadContext::Halted;
- cpu->haltContext(_threadId);
+ baseCpu->haltContext(_threadId);
}
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index 97964c0e8..39cb96c3a 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -39,6 +51,7 @@
#include "arch/types.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/decode.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
@@ -106,12 +119,9 @@ class SimpleThread : public ThreadState
public:
std::string name() const
{
- return csprintf("%s.[tid:%i]", cpu->name(), tc->threadId());
+ return csprintf("%s.[tid:%i]", baseCpu->name(), tc->threadId());
}
- // pointer to CPU associated with this SimpleThread
- BaseCPU *cpu;
-
ProxyThreadContext<SimpleThread> *tc;
System *system;
@@ -182,12 +192,16 @@ class SimpleThread : public ThreadState
* ThreadContext interface functions.
******************************************/
- BaseCPU *getCpuPtr() { return cpu; }
+ BaseCPU *getCpuPtr() { return baseCpu; }
TheISA::TLB *getITBPtr() { return itb; }
TheISA::TLB *getDTBPtr() { return dtb; }
+#if USE_CHECKER
+ BaseCPU *getCheckerCpuPtr() { return NULL; }
+#endif
+
Decoder *getDecoderPtr() { return &decoder; }
System *getSystemPtr() { return system; }
@@ -281,7 +295,10 @@ class SimpleThread : public ThreadState
{
int flatIndex = isa.flattenFloatIndex(reg_idx);
assert(flatIndex < TheISA::NumFloatRegs);
- floatRegs.i[flatIndex] = val;
+ // XXX: Fix array out of bounds compiler error for gem5.fast
+ // when checkercpu enabled
+ if (flatIndex < TheISA::NumFloatRegs)
+ floatRegs.i[flatIndex] = val;
DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x, %#f.\n",
reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
}
@@ -298,6 +315,14 @@ class SimpleThread : public ThreadState
_pcState = val;
}
+#if USE_CHECKER
+ void
+ pcStateNoRecord(const TheISA::PCState &val)
+ {
+ _pcState = val;
+ }
+#endif
+
Addr
instAddr()
{
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index adda82c49..7c5fcaa3a 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -52,7 +52,7 @@ class ThreadContext;
class DynInst;
class Packet;
-class O3CPUImpl;
+struct O3CPUImpl;
template <class Impl> class BaseO3DynInst;
typedef BaseO3DynInst<O3CPUImpl> O3DynInst;
template <class Impl> class OzoneDynInst;
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 261ace7cf..2f2e5b02b 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -38,6 +50,7 @@
#include "arch/types.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
+#include "config/use_checker.hh"
// @todo: Figure out a more architecture independent way to obtain the ITB and
// DTB pointers.
@@ -120,6 +133,10 @@ class ThreadContext
virtual TheISA::TLB *getDTBPtr() = 0;
+#if USE_CHECKER
+ virtual BaseCPU *getCheckerCpuPtr() = 0;
+#endif
+
virtual Decoder *getDecoderPtr() = 0;
virtual System *getSystemPtr() = 0;
@@ -198,6 +215,10 @@ class ThreadContext
virtual void pcState(const TheISA::PCState &val) = 0;
+#if USE_CHECKER
+ virtual void pcStateNoRecord(const TheISA::PCState &val) = 0;
+#endif
+
virtual Addr instAddr() = 0;
virtual Addr nextInstAddr() = 0;
@@ -287,6 +308,10 @@ class ProxyThreadContext : public ThreadContext
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
+#if USE_CHECKER
+ BaseCPU *getCheckerCpuPtr() { return actualTC->getCheckerCpuPtr(); }
+#endif
+
Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
System *getSystemPtr() { return actualTC->getSystemPtr(); }
@@ -367,6 +392,10 @@ class ProxyThreadContext : public ThreadContext
void pcState(const TheISA::PCState &val) { actualTC->pcState(val); }
+#if USE_CHECKER
+ void pcStateNoRecord(const TheISA::PCState &val) { actualTC->pcState(val); }
+#endif
+
Addr instAddr() { return actualTC->instAddr(); }
Addr nextInstAddr() { return actualTC->nextInstAddr(); }
MicroPC microPC() { return actualTC->microPC(); }
diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh
index 30bb64ed7..3622ed37f 100644
--- a/src/cpu/thread_state.hh
+++ b/src/cpu/thread_state.hh
@@ -64,7 +64,7 @@ struct ThreadState {
ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process);
- ~ThreadState();
+ virtual ~ThreadState();
void serialize(std::ostream &os);
diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc
index 74f769c86..0960c71ab 100644
--- a/src/dev/alpha/tsunami_cchip.cc
+++ b/src/dev/alpha/tsunami_cchip.cc
@@ -53,7 +53,6 @@
#include "params/TsunamiCChip.hh"
#include "sim/system.hh"
-using namespace std;
//Should this be AlphaISA?
using namespace TheISA;
diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc
index 0c1937a32..bccdddf85 100644
--- a/src/dev/alpha/tsunami_io.cc
+++ b/src/dev/alpha/tsunami_io.cc
@@ -54,7 +54,11 @@
#include "mem/port.hh"
#include "sim/system.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::string;
+using std::ostream;
+
//Should this be AlphaISA?
using namespace TheISA;
diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc
index 263a3b620..d416ab31f 100644
--- a/src/dev/arm/pl111.cc
+++ b/src/dev/arm/pl111.cc
@@ -50,6 +50,10 @@
#include "mem/packet.hh"
#include "mem/packet_access.hh"
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::vector;
+
using namespace AmbaDev;
// initialize clcd registers
@@ -69,11 +73,12 @@ Pl111::Pl111(const Params *p)
pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
- dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
+ const int buffer_size = LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t);
+ dmaBuffer = new uint8_t[buffer_size];
memset(lcdPalette, 0, sizeof(lcdPalette));
memset(cursorImage, 0, sizeof(cursorImage));
- memset(dmaBuffer, 0, sizeof(dmaBuffer));
+ memset(dmaBuffer, 0, buffer_size);
if (vncserver)
vncserver->setFramebufferAddr(dmaBuffer);
diff --git a/src/dev/arm/pl111.hh b/src/dev/arm/pl111.hh
index b2dc1f640..e0a03641c 100644
--- a/src/dev/arm/pl111.hh
+++ b/src/dev/arm/pl111.hh
@@ -53,8 +53,6 @@
#include "params/Pl111.hh"
#include "sim/serialize.hh"
-using namespace std;
-
class Gic;
class VncServer;
class Bitmap;
@@ -304,7 +302,7 @@ class Pl111: public AmbaDmaDevice
EventWrapper<Pl111, &Pl111::fillFifo> fillFifoEvent;
/** DMA done event */
- vector<EventWrapper<Pl111, &Pl111::dmaDone> > dmaDoneEvent;
+ std::vector<EventWrapper<Pl111, &Pl111::dmaDone> > dmaDoneEvent;
/** Wrapper to create an event out of the interrupt */
EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
diff --git a/src/dev/copy_engine.cc b/src/dev/copy_engine.cc
index 361d4db1b..33994cfde 100644
--- a/src/dev/copy_engine.cc
+++ b/src/dev/copy_engine.cc
@@ -45,7 +45,6 @@
#include "sim/system.hh"
using namespace CopyEngineReg;
-using namespace std;
CopyEngine::CopyEngine(const Params *p)
: PciDev(p)
diff --git a/src/dev/disk_image.cc b/src/dev/disk_image.cc
index 4c770fbcd..c9defb605 100644
--- a/src/dev/disk_image.cc
+++ b/src/dev/disk_image.cc
@@ -170,12 +170,12 @@ CowDiskImage::CowDiskImage(const Params *p)
: DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
{
if (filename.empty()) {
- init(p->table_size);
+ initSectorTable(p->table_size);
} else {
if (!open(filename)) {
if (p->read_only)
fatal("could not open read-only file");
- init(p->table_size);
+ initSectorTable(p->table_size);
}
if (!p->read_only)
@@ -270,7 +270,7 @@ CowDiskImage::open(const string &file)
}
void
-CowDiskImage::init(int hash_size)
+CowDiskImage::initSectorTable(int hash_size)
{
table = new SectorTable(hash_size);
diff --git a/src/dev/disk_image.hh b/src/dev/disk_image.hh
index 3865562a0..1b846522f 100644
--- a/src/dev/disk_image.hh
+++ b/src/dev/disk_image.hh
@@ -121,7 +121,7 @@ class CowDiskImage : public DiskImage
CowDiskImage(const Params *p);
~CowDiskImage();
- void init(int hash_size);
+ void initSectorTable(int hash_size);
bool open(const std::string &file);
void save();
void save(const std::string &file);
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
index 5a663bac9..f33d603af 100644
--- a/src/dev/ide_ctrl.cc
+++ b/src/dev/ide_ctrl.cc
@@ -32,7 +32,6 @@
#include <string>
-#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "debug/IdeCtrl.hh"
#include "dev/ide_ctrl.hh"
@@ -42,7 +41,9 @@
#include "params/IdeController.hh"
#include "sim/byteswap.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::string;
// Bus master IDE registers
enum BMIRegOffset {
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
index eb6eb6353..4dc4aeae9 100644
--- a/src/dev/ns_gige.cc
+++ b/src/dev/ns_gige.cc
@@ -50,6 +50,12 @@
#include "params/NSGigE.hh"
#include "sim/system.hh"
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::min;
+using std::ostream;
+using std::string;
+
const char *NsRxStateStrings[] =
{
"rxIdle",
@@ -81,7 +87,6 @@ const char *NsDmaState[] =
"dmaWriteWaiting"
};
-using namespace std;
using namespace Net;
using namespace TheISA;
@@ -479,12 +484,12 @@ NSGigE::write(PacketPtr pkt)
// all these #if 0's are because i don't THINK the kernel needs to
// have these implemented. if there is a problem relating to one of
// these, you may need to add functionality in.
+
+// grouped together and #if 0'ed to avoid empty if body and make clang happy
+#if 0
if (reg & CFGR_TBI_EN) ;
if (reg & CFGR_MODE_1000) ;
- if (reg & CFGR_AUTO_1000)
- panic("CFGR_AUTO_1000 not implemented!\n");
-
if (reg & CFGR_PINT_DUPSTS ||
reg & CFGR_PINT_LNKSTS ||
reg & CFGR_PINT_SPDSTS)
@@ -494,22 +499,11 @@ NSGigE::write(PacketPtr pkt)
if (reg & CFGR_MRM_DIS) ;
if (reg & CFGR_MWI_DIS) ;
- if (reg & CFGR_T64ADDR) ;
- // panic("CFGR_T64ADDR is read only register!\n");
-
- if (reg & CFGR_PCI64_DET)
- panic("CFGR_PCI64_DET is read only register!\n");
-
if (reg & CFGR_DATA64_EN) ;
if (reg & CFGR_M64ADDR) ;
if (reg & CFGR_PHY_RST) ;
if (reg & CFGR_PHY_DIS) ;
- if (reg & CFGR_EXTSTS_EN)
- extstsEnable = true;
- else
- extstsEnable = false;
-
if (reg & CFGR_REQALG) ;
if (reg & CFGR_SB) ;
if (reg & CFGR_POW) ;
@@ -518,6 +512,20 @@ NSGigE::write(PacketPtr pkt)
if (reg & CFGR_BROM_DIS) ;
if (reg & CFGR_EXT_125) ;
if (reg & CFGR_BEM) ;
+
+ if (reg & CFGR_T64ADDR) ;
+ // panic("CFGR_T64ADDR is read only register!\n");
+#endif
+ if (reg & CFGR_AUTO_1000)
+ panic("CFGR_AUTO_1000 not implemented!\n");
+
+ if (reg & CFGR_PCI64_DET)
+ panic("CFGR_PCI64_DET is read only register!\n");
+
+ if (reg & CFGR_EXTSTS_EN)
+ extstsEnable = true;
+ else
+ extstsEnable = false;
break;
case MEAR:
@@ -541,9 +549,13 @@ NSGigE::write(PacketPtr pkt)
eepromClk = reg & MEAR_EECLK;
// since phy is completely faked, MEAR_MD* don't matter
+
+// grouped together and #if 0'ed to avoid empty if body and make clang happy
+#if 0
if (reg & MEAR_MDIO) ;
if (reg & MEAR_MDDIR) ;
if (reg & MEAR_MDC) ;
+#endif
break;
case PTSCR:
diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc
index e7130e11d..320f45543 100644
--- a/src/dev/pciconfigall.cc
+++ b/src/dev/pciconfigall.cc
@@ -43,8 +43,6 @@
#include "params/PciConfigAll.hh"
#include "sim/system.hh"
-using namespace std;
-
PciConfigAll::PciConfigAll(const Params *p)
: PioDevice(p)
{
diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc
index 42c803553..cb27f8b3d 100644
--- a/src/dev/pcidev.cc
+++ b/src/dev/pcidev.cc
@@ -52,8 +52,6 @@
#include "sim/byteswap.hh"
#include "sim/core.hh"
-using namespace std;
-
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
int funcid, Platform *p)
@@ -341,7 +339,7 @@ PciDev::writeConfig(PacketPtr pkt)
}
void
-PciDev::serialize(ostream &os)
+PciDev::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index a20f90108..dfe4be3cc 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -436,7 +436,8 @@ Bus::recvFunctional(PacketPtr pkt)
pkt->setSrc(src_id);
}
- // If the snooping hasn't found what we were looking for, keep going.
+ // If the snooping hasn't found what we were looking for and it is not
+ // a forwarded snoop from below, keep going.
if (!pkt->isResponse() && port_id != pkt->getSrc()) {
port->sendFunctional(pkt);
}
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index 2b7fa4b9f..b0fb3bc6c 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -45,8 +45,7 @@ using namespace std;
BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
const std::string &_label)
: SimpleTimingPort(_name, _cache), cache(_cache),
- label(_label), otherPort(NULL),
- blocked(false), mustSendRetry(false)
+ label(_label), blocked(false), mustSendRetry(false)
{
}
@@ -70,12 +69,6 @@ BaseCache::BaseCache(const Params *p)
{
}
-void
-BaseCache::CachePort::recvRangeChange() const
-{
- otherPort->sendRangeChange();
-}
-
bool
BaseCache::CachePort::checkFunctional(PacketPtr pkt)
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh
index fded6fca6..3aaed4455 100644
--- a/src/mem/cache/base.hh
+++ b/src/mem/cache/base.hh
@@ -73,6 +73,7 @@ class BaseCache : public MemObject
MSHRQueue_WriteBuffer
};
+ public:
/**
* Reasons for caches to be blocked.
*/
@@ -83,7 +84,6 @@ class BaseCache : public MemObject
NUM_BLOCKED_CAUSES
};
- public:
/**
* Reasons for cache to request a bus.
*/
@@ -94,7 +94,7 @@ class BaseCache : public MemObject
NUM_REQUEST_CAUSES
};
- private:
+ protected:
class CachePort : public SimpleTimingPort
{
@@ -105,8 +105,6 @@ class BaseCache : public MemObject
CachePort(const std::string &_name, BaseCache *_cache,
const std::string &_label);
- virtual void recvRangeChange() const;
-
virtual unsigned deviceBlockSize() const;
bool recvRetryCommon();
@@ -117,16 +115,12 @@ class BaseCache : public MemObject
const std::string label;
public:
- void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; }
-
void setBlocked();
void clearBlocked();
bool checkFunctional(PacketPtr pkt);
- CachePort *otherPort;
-
bool blocked;
bool mustSendRetry;
@@ -144,7 +138,6 @@ class BaseCache : public MemObject
}
};
- public: //Made public so coherence can get at it.
CachePort *cpuSidePort;
CachePort *memSidePort;
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 13484eb79..2ef53e040 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -77,8 +77,6 @@ Cache<TagStore>::Cache(const Params *p, TagStore *tags, BasePrefetcher *pf)
"CpuSidePort");
memSidePort = new MemSidePort(p->name + "-mem_side_port", this,
"MemSidePort");
- cpuSidePort->setOtherPort(memSidePort);
- memSidePort->setOtherPort(cpuSidePort);
tags->setCache(this);
if (prefetcher)
diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc
index 71c3ba48c..acce3ffc8 100644
--- a/src/mem/cache/tags/iic.cc
+++ b/src/mem/cache/tags/iic.cc
@@ -187,7 +187,7 @@ IIC::regStats(const string &name)
.flags(pdf)
;
- repl->regStats(name);
+ repl->regStatsWithSuffix(name);
if (PROFILE_IIC)
setAccess
diff --git a/src/mem/cache/tags/iic_repl/gen.cc b/src/mem/cache/tags/iic_repl/gen.cc
index 7a1e7a110..137130b27 100644
--- a/src/mem/cache/tags/iic_repl/gen.cc
+++ b/src/mem/cache/tags/iic_repl/gen.cc
@@ -184,7 +184,7 @@ GenRepl::add(unsigned long tag_index)
}
void
-GenRepl::regStats(const string name)
+GenRepl::regStatsWithSuffix(const string name)
{
using namespace Stats;
diff --git a/src/mem/cache/tags/iic_repl/gen.hh b/src/mem/cache/tags/iic_repl/gen.hh
index fe105d95a..cbd15a6fd 100644
--- a/src/mem/cache/tags/iic_repl/gen.hh
+++ b/src/mem/cache/tags/iic_repl/gen.hh
@@ -209,7 +209,7 @@ class GenRepl : public Repl
* Register statistics.
* @param name The name to prepend to statistic descriptions.
*/
- virtual void regStats(const std::string name);
+ virtual void regStatsWithSuffix(const std::string name);
/**
* Update the tag pointer to when the tag moves.
diff --git a/src/mem/cache/tags/iic_repl/repl.hh b/src/mem/cache/tags/iic_repl/repl.hh
index 994af5164..51d8169e9 100644
--- a/src/mem/cache/tags/iic_repl/repl.hh
+++ b/src/mem/cache/tags/iic_repl/repl.hh
@@ -102,7 +102,7 @@ class Repl : public SimObject
* Register statistics.
* @param name The name to prepend to statistic descriptions.
*/
- virtual void regStats(const std::string name) = 0;
+ virtual void regStatsWithSuffix(const std::string name) = 0;
/**
* Update the tag pointer to when the tag moves.
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index e49ce7577..ce5748c24 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -53,7 +53,7 @@
#include "mem/request.hh"
#include "sim/core.hh"
-struct Packet;
+class Packet;
typedef Packet *PacketPtr;
typedef uint8_t* PacketDataPtr;
typedef std::list<PacketPtr> PacketList;
diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
index aee05b696..126c5c811 100644
--- a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
+++ b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
@@ -104,11 +104,12 @@ GarnetNetwork_d::init()
for (vector<Router_d*>::const_iterator i= m_router_ptr_vector.begin();
i != m_router_ptr_vector.end(); ++i) {
Router_d* router = safe_cast<Router_d*>(*i);
- int router_id=fault_model->declare_router(router->get_num_inports(),
- router->get_num_outports(),
- router->get_vc_per_vnet(),
- getBuffersPerDataVC(),
- getBuffersPerCtrlVC());
+ int router_id M5_VAR_USED =
+ fault_model->declare_router(router->get_num_inports(),
+ router->get_num_outports(),
+ router->get_vc_per_vnet(),
+ getBuffersPerDataVC(),
+ getBuffersPerCtrlVC());
assert(router_id == router->get_id());
router->printAggregateFaultProbability(cout);
router->printFaultVector(cout);
diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh
index e262e32e8..296258994 100644
--- a/src/mem/ruby/system/Sequencer.hh
+++ b/src/mem/ruby/system/Sequencer.hh
@@ -41,7 +41,7 @@
class DataBlock;
class CacheMemory;
-class RubySequencerParams;
+struct RubySequencerParams;
struct SequencerRequest
{
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index 84d70d663..c45867c85 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -477,7 +477,7 @@ struct PyObject;
#include <string>
-struct EventQueue;
+class EventQueue;
''')
for param in params:
param.cxx_predecls(code)
diff --git a/src/sim/core.hh b/src/sim/core.hh
index a529ff17b..4f842ab48 100644
--- a/src/sim/core.hh
+++ b/src/sim/core.hh
@@ -95,7 +95,7 @@ void setClockFrequency(Tick ticksPerSecond);
void setOutputDir(const std::string &dir);
-struct Callback;
+class Callback;
void registerExitCallback(Callback *callback);
void doExitCleanup();
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 45362fe1b..8f3b3be79 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -86,8 +86,8 @@ AuxVector<IntType>::AuxVector(IntType type, IntType val)
a_val = TheISA::htog(val);
}
-template class AuxVector<uint32_t>;
-template class AuxVector<uint64_t>;
+template struct AuxVector<uint32_t>;
+template struct AuxVector<uint64_t>;
Process::Process(ProcessParams * params)
: SimObject(params), system(params->system),
diff --git a/src/sim/process.hh b/src/sim/process.hh
index 3896492b7..17b530ab8 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -43,8 +43,8 @@
#include "sim/syscallreturn.hh"
class PageTable;
-class ProcessParams;
-class LiveProcessParams;
+struct ProcessParams;
+struct LiveProcessParams;
class SyscallDesc;
class System;
class ThreadContext;
diff --git a/src/sim/process_impl.hh b/src/sim/process_impl.hh
index 401e16f52..0fb827498 100644
--- a/src/sim/process_impl.hh
+++ b/src/sim/process_impl.hh
@@ -47,7 +47,7 @@ copyStringArray(std::vector<std::string> &strings,
{
AddrType data_ptr_swap;
for (std::vector<std::string>::size_type i = 0; i < strings.size(); ++i) {
- data_ptr_swap = htog(data_ptr);
+ data_ptr_swap = TheISA::htog(data_ptr);
memProxy->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
sizeof(AddrType));
memProxy->writeString(data_ptr, strings[i].c_str());
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index b72fdca4a..8a7f0c469 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -51,6 +51,7 @@
#include "arch/kernel_stats.hh"
#include "arch/vtophys.hh"
#include "base/debug.hh"
+#include "base/output.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
#include "cpu/quiesce_event.hh"
@@ -387,6 +388,48 @@ readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
return result;
}
+uint64_t
+writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
+ Addr filename_addr)
+{
+ ostream *os;
+
+ // copy out target filename
+ char fn[100];
+ std::string filename;
+ CopyStringOut(tc, fn, filename_addr, 100);
+ filename = std::string(fn);
+
+ if (offset == 0) {
+ // create a new file (truncate)
+ os = simout.create(filename, true);
+ } else {
+ // do not truncate file if offset is non-zero
+ // (ios::in flag is required as well to keep the existing data
+ // intact, otherwise existing data will be zeroed out.)
+ os = simout.openFile(simout.directory() + filename,
+ ios::in | ios::out | ios::binary);
+ }
+ if (!os)
+ panic("could not open file %s\n", filename);
+
+ // seek to offset
+ os->seekp(offset);
+
+ // copy out data and write to file
+ char *buf = new char[len];
+ CopyOut(tc, buf, vaddr, len);
+ os->write(buf, len);
+ if (os->fail() || os->bad())
+ panic("Error while doing writefile!\n");
+
+ simout.close(os);
+
+ delete [] buf;
+
+ return len;
+}
+
void
debugbreak(ThreadContext *tc)
{
diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 399c88a4f..27d3b19d4 100644
--- a/src/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
@@ -53,6 +53,8 @@ void quiesceCycles(ThreadContext *tc, uint64_t cycles);
uint64_t quiesceTime(ThreadContext *tc);
uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len,
uint64_t offset);
+uint64_t writefile(ThreadContext *tc, Addr vaddr, uint64_t len,
+ uint64_t offset, Addr filenameAddr);
void loadsymbol(ThreadContext *xc);
void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr);
uint64_t initParam(ThreadContext *xc);
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index 03f900837..30655e692 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -438,7 +438,7 @@ class Globals : public Serializable
public:
const string name() const;
void serialize(ostream &os);
- void unserialize(Checkpoint *cp);
+ void unserialize(Checkpoint *cp, const std::string &section);
};
/// The one and only instance of the Globals class.
@@ -461,9 +461,8 @@ Globals::serialize(ostream &os)
}
void
-Globals::unserialize(Checkpoint *cp)
+Globals::unserialize(Checkpoint *cp, const std::string &section)
{
- const string &section = name();
Tick tick;
paramIn(cp, section, "curTick", tick);
curTick(tick);
@@ -510,7 +509,7 @@ Serializable::serializeAll(const string &cpt_dir)
void
Serializable::unserializeGlobals(Checkpoint *cp)
{
- globals.unserialize(cp);
+ globals.unserialize(cp, globals.name());
}
void
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 9ac0b7fff..95bc6bf84 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -169,7 +169,7 @@ SimObject::resume()
}
void
-SimObject::setMemoryMode(State new_mode)
+SimObject::setMemoryMode(Enums::MemoryMode new_mode)
{
panic("setMemoryMode() should only be called on systems");
}
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 995431845..4388ff584 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -43,6 +43,7 @@
#include <string>
#include <vector>
+#include "enums/MemoryMode.hh"
#include "params/SimObject.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
@@ -146,7 +147,7 @@ class SimObject : public EventManager, public Serializable
// before the object will be done draining. Normally this should be 1
virtual unsigned int drain(Event *drain_event);
virtual void resume();
- virtual void setMemoryMode(State new_mode);
+ virtual void setMemoryMode(Enums::MemoryMode new_mode);
virtual void switchOut();
virtual void takeOverFrom(BaseCPU *cpu);
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 45c87f0ab..ad00f6e3d 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -401,41 +401,41 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
tgt->st_dev = 0xA;
else
tgt->st_dev = host->st_dev;
- tgt->st_dev = htog(tgt->st_dev);
+ tgt->st_dev = TheISA::htog(tgt->st_dev);
tgt->st_ino = host->st_ino;
- tgt->st_ino = htog(tgt->st_ino);
+ tgt->st_ino = TheISA::htog(tgt->st_ino);
tgt->st_mode = host->st_mode;
if (fakeTTY) {
// Claim to be a character device
tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
tgt->st_mode |= S_IFCHR; // Set S_IFCHR
}
- tgt->st_mode = htog(tgt->st_mode);
+ tgt->st_mode = TheISA::htog(tgt->st_mode);
tgt->st_nlink = host->st_nlink;
- tgt->st_nlink = htog(tgt->st_nlink);
+ tgt->st_nlink = TheISA::htog(tgt->st_nlink);
tgt->st_uid = host->st_uid;
- tgt->st_uid = htog(tgt->st_uid);
+ tgt->st_uid = TheISA::htog(tgt->st_uid);
tgt->st_gid = host->st_gid;
- tgt->st_gid = htog(tgt->st_gid);
+ tgt->st_gid = TheISA::htog(tgt->st_gid);
if (fakeTTY)
tgt->st_rdev = 0x880d;
else
tgt->st_rdev = host->st_rdev;
- tgt->st_rdev = htog(tgt->st_rdev);
+ tgt->st_rdev = TheISA::htog(tgt->st_rdev);
tgt->st_size = host->st_size;
- tgt->st_size = htog(tgt->st_size);
+ tgt->st_size = TheISA::htog(tgt->st_size);
tgt->st_atimeX = host->st_atime;
- tgt->st_atimeX = htog(tgt->st_atimeX);
+ tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
tgt->st_mtimeX = host->st_mtime;
- tgt->st_mtimeX = htog(tgt->st_mtimeX);
+ tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
tgt->st_ctimeX = host->st_ctime;
- tgt->st_ctimeX = htog(tgt->st_ctimeX);
+ tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
// Force the block size to be 8k. This helps to ensure buffered io works
// consistently across different hosts.
tgt->st_blksize = 0x2000;
- tgt->st_blksize = htog(tgt->st_blksize);
+ tgt->st_blksize = TheISA::htog(tgt->st_blksize);
tgt->st_blocks = host->st_blocks;
- tgt->st_blocks = htog(tgt->st_blocks);
+ tgt->st_blocks = TheISA::htog(tgt->st_blocks);
}
// Same for stat64
@@ -449,11 +449,11 @@ convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
#if defined(STAT_HAVE_NSEC)
tgt->st_atime_nsec = host->st_atime_nsec;
- tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
+ tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
tgt->st_mtime_nsec = host->st_mtime_nsec;
- tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
+ tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
tgt->st_ctime_nsec = host->st_ctime_nsec;
- tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
+ tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
#else
tgt->st_atime_nsec = 0;
tgt->st_mtime_nsec = 0;
@@ -967,9 +967,9 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
(uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
- hiov[i].iov_len = gtoh(tiov.iov_len);
+ hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
+ p->readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
hiov[i].iov_len);
}
@@ -1085,15 +1085,15 @@ getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
case OS::TGT_RLIMIT_STACK:
// max stack size in bytes: make up a number (8MB for now)
rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
- rlp->rlim_cur = htog(rlp->rlim_cur);
- rlp->rlim_max = htog(rlp->rlim_max);
+ rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
+ rlp->rlim_max = TheISA::htog(rlp->rlim_max);
break;
case OS::TGT_RLIMIT_DATA:
// max data segment size in bytes: make up a number
rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
- rlp->rlim_cur = htog(rlp->rlim_cur);
- rlp->rlim_max = htog(rlp->rlim_max);
+ rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
+ rlp->rlim_max = TheISA::htog(rlp->rlim_max);
break;
default:
@@ -1148,8 +1148,8 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
struct timeval hostTimeval[2];
for (int i = 0; i < 2; ++i)
{
- hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
- hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
+ hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
+ hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
}
// Adjust path for current working directory
@@ -1194,8 +1194,8 @@ getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
switch (who) {
case OS::TGT_RUSAGE_SELF:
getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
- rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
- rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+ rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
+ rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
break;
case OS::TGT_RUSAGE_CHILDREN:
@@ -1231,7 +1231,7 @@ timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
bufp->tms_cstime = 0;
// Convert to host endianness
- bufp->tms_utime = htog(bufp->tms_utime);
+ bufp->tms_utime = TheISA::htog(bufp->tms_utime);
// Write back
bufp.copyOut(tc->getMemProxy());
@@ -1254,7 +1254,7 @@ timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
Addr taddr = (Addr)process->getSyscallArg(tc, index);
if(taddr != 0) {
typename OS::time_t t = sec;
- t = htog(t);
+ t = TheISA::htog(t);
SETranslatingPortProxy *p = tc->getMemProxy();
p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
}
diff --git a/util/m5/m5.c b/util/m5/m5.c
index 40328bc38..a0ce9b3ec 100644
--- a/util/m5/m5.c
+++ b/util/m5/m5.c
@@ -88,6 +88,33 @@ read_file(int dest_fid)
}
}
+int
+write_file(const char *filename)
+{
+ fprintf(stderr, "opening %s\n", filename);
+ int src_fid = open(filename, O_RDONLY);
+
+ if (src_fid < 0) {
+ fprintf(stderr, "error opening %s\n", filename);
+ return;
+ }
+
+ char buf[256*1024];
+ int offset = 0;
+ int len;
+ int bytes = 0;
+
+ memset(buf, 0, sizeof(buf));
+
+ while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
+ bytes += m5_writefile(buf, len, offset, filename);
+ offset += len;
+ }
+ fprintf(stderr, "written %d bytes\n", bytes);
+
+ close(src_fid);
+}
+
void
do_exit(int argc, char *argv[])
{
@@ -131,6 +158,17 @@ do_read_file(int argc, char *argv[])
}
void
+do_write_file(int argc, char *argv[])
+{
+ if (argc != 1)
+ usage();
+
+ const char *filename = argv[0];
+
+ write_file(filename);
+}
+
+void
do_exec_file(int argc, char *argv[])
{
if (argc > 0)
@@ -227,8 +265,9 @@ struct MainFunc mainfuncs[] = {
{ "resetstats", do_reset_stats, "[delay [period]]" },
{ "dumpstats", do_dump_stats, "[delay [period]]" },
{ "dumpresetstats", do_dump_reset_stats, "[delay [period]]" },
- { "readfile", do_read_file, "[filename]" },
- { "execfile", do_exec_file, "<filename>" },
+ { "readfile", do_read_file, "" },
+ { "writefile", do_write_file, "<filename>" },
+ { "execfile", do_exec_file, "" },
{ "checkpoint", do_checkpoint, "[delay [period]]" },
{ "loadsymbol", do_load_symbol, "<address> <symbol>" },
{ "initparam", do_initparam, "" },
diff --git a/util/m5/m5op.h b/util/m5/m5op.h
index 38815e3c3..4e1d0b638 100644
--- a/util/m5/m5op.h
+++ b/util/m5/m5op.h
@@ -49,6 +49,7 @@ void m5_reset_stats(uint64_t ns_delay, uint64_t ns_period);
void m5_dump_stats(uint64_t ns_delay, uint64_t ns_period);
void m5_dumpreset_stats(uint64_t ns_delay, uint64_t ns_period);
uint64_t m5_readfile(void *buffer, uint64_t len, uint64_t offset);
+uint64_t m5_writefile(void *buffer, uint64_t len, uint64_t offset, const char *filename);
void m5_debugbreak(void);
void m5_switchcpu(void);
void m5_addsymbol(uint64_t addr, char *symbol);
diff --git a/util/m5/m5op_arm.S b/util/m5/m5op_arm.S
index b9557ee9d..8cdf5c62d 100644
--- a/util/m5/m5op_arm.S
+++ b/util/m5/m5op_arm.S
@@ -80,6 +80,7 @@ func:
#define DUMPRST_STATS INST(m5_op, 0, 0, dumprststats_func)
#define CHECKPOINT INST(m5_op, 0, 0, ckpt_func)
#define READFILE INST(m5_op, 0, 0, readfile_func)
+#define WRITEFILE INST(m5_op, 0, 0, writefile_func)
#define DEBUGBREAK INST(m5_op, 0, 0, debugbreak_func)
#define SWITCHCPU INST(m5_op, 0, 0, switchcpu_func)
#define ADDSYMBOL INST(m5_op, 0, 0, addsymbol_func)
@@ -121,6 +122,7 @@ SIMPLE_OP(m5_dump_stats, DUMP_STATS)
SIMPLE_OP(m5_dumpreset_stats, DUMPRST_STATS)
SIMPLE_OP(m5_checkpoint, CHECKPOINT)
SIMPLE_OP(m5_readfile, READFILE)
+SIMPLE_OP(m5_writefile, WRITEFILE)
SIMPLE_OP(m5_debugbreak, DEBUGBREAK)
SIMPLE_OP(m5_switchcpu, SWITCHCPU)
SIMPLE_OP(m5_addsymbol, ADDSYMBOL)
diff --git a/util/m5/m5ops.h b/util/m5/m5ops.h
index bc2ae06be..f08524014 100644
--- a/util/m5/m5ops.h
+++ b/util/m5/m5ops.h
@@ -46,6 +46,7 @@
#define dumpstats_func 0x41
#define dumprststats_func 0x42
#define ckpt_func 0x43
+#define writefile_func 0x4F
#define readfile_func 0x50
#define debugbreak_func 0x51
#define switchcpu_func 0x52