Merge with head, hopefully the last time for this batch.
This commit is contained in:
commit
ea8b347dc5
132 changed files with 1719 additions and 909 deletions
21
SConstruct
21
SConstruct
|
@ -473,7 +473,8 @@ CXX_V = readCommand([main['CXX'],'-V'], exception=False)
|
||||||
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
|
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
|
||||||
main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
|
main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
|
||||||
main['ICC'] = CXX_V and CXX_V.find('Intel') >= 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?'
|
print 'Error: How can we have two at the same time?'
|
||||||
Exit(1)
|
Exit(1)
|
||||||
|
|
||||||
|
@ -501,6 +502,24 @@ elif main['SUNCC']:
|
||||||
main.Append(CCFLAGS=['-library=stlport4'])
|
main.Append(CCFLAGS=['-library=stlport4'])
|
||||||
main.Append(CCFLAGS=['-xar'])
|
main.Append(CCFLAGS=['-xar'])
|
||||||
#main.Append(CCFLAGS=['-instances=semiexplicit'])
|
#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:
|
else:
|
||||||
print 'Error: Don\'t know what compiler options to use for your compiler.'
|
print 'Error: Don\'t know what compiler options to use for your compiler.'
|
||||||
print ' Please fix SConstruct and src/SConscript and try again.'
|
print ' Please fix SConstruct and src/SConscript and try again.'
|
||||||
|
|
|
@ -94,6 +94,8 @@ if m4env['GCC']:
|
||||||
major,minor,dot = [int(x) for x in m4env['GCC_VERSION'].split('.')]
|
major,minor,dot = [int(x) for x in m4env['GCC_VERSION'].split('.')]
|
||||||
if major >= 4:
|
if major >= 4:
|
||||||
m4env.Append(CCFLAGS=['-Wno-pointer-sign'])
|
m4env.Append(CCFLAGS=['-Wno-pointer-sign'])
|
||||||
|
if m4env['CLANG']:
|
||||||
|
m4env.Append(CCFLAGS=['-Wno-initializer-overrides', '-Wno-pointer-sign'])
|
||||||
m4env.Append(CCFLAGS=['-Wno-implicit'])
|
m4env.Append(CCFLAGS=['-Wno-implicit'])
|
||||||
del m4env['CPPPATH']
|
del m4env['CPPPATH']
|
||||||
|
|
||||||
|
|
|
@ -854,6 +854,9 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||||
swig_env.Append(CCFLAGS='-Wno-unused-label')
|
swig_env.Append(CCFLAGS='-Wno-unused-label')
|
||||||
if compareVersions(env['GCC_VERSION'], '4.6.0') != -1:
|
if compareVersions(env['GCC_VERSION'], '4.6.0') != -1:
|
||||||
swig_env.Append(CCFLAGS='-Wno-unused-but-set-variable')
|
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 = new_env.Clone()
|
||||||
werror_env.Append(CCFLAGS='-Werror')
|
werror_env.Append(CCFLAGS='-Werror')
|
||||||
|
@ -928,7 +931,7 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||||
|
|
||||||
# Debug binary
|
# Debug binary
|
||||||
ccflags = {}
|
ccflags = {}
|
||||||
if env['GCC']:
|
if env['GCC'] or env['CLANG']:
|
||||||
if sys.platform == 'sunos5':
|
if sys.platform == 'sunos5':
|
||||||
ccflags['debug'] = '-gstabs+'
|
ccflags['debug'] = '-gstabs+'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -64,7 +64,7 @@ TLB::TLB(const Params *p)
|
||||||
: BaseTLB(p), size(p->size), nlu(0)
|
: BaseTLB(p), size(p->size), nlu(0)
|
||||||
{
|
{
|
||||||
table = new TlbEntry[size];
|
table = new TlbEntry[size];
|
||||||
memset(table, 0, sizeof(TlbEntry[size]));
|
memset(table, 0, sizeof(TlbEntry) * size);
|
||||||
flushCache();
|
flushCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ void
|
||||||
TLB::flushAll()
|
TLB::flushAll()
|
||||||
{
|
{
|
||||||
DPRINTF(TLB, "flushAll\n");
|
DPRINTF(TLB, "flushAll\n");
|
||||||
memset(table, 0, sizeof(TlbEntry[size]));
|
memset(table, 0, sizeof(TlbEntry) * size);
|
||||||
flushCache();
|
flushCache();
|
||||||
lookupTable.clear();
|
lookupTable.clear();
|
||||||
nlu = 0;
|
nlu = 0;
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace AlphaISA {
|
namespace AlphaISA {
|
||||||
|
|
||||||
class TlbEntry;
|
struct TlbEntry;
|
||||||
|
|
||||||
class TLB : public BaseTLB
|
class TLB : public BaseTLB
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "arch/arm/utility.hh"
|
#include "arch/arm/utility.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
#include "sim/byteswap.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
|
|
||||||
namespace ArmISA
|
namespace ArmISA
|
||||||
|
|
|
@ -107,6 +107,9 @@ enum VfpRoundingMode
|
||||||
VfpRoundZero = 3
|
VfpRoundZero = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline float bitsToFp(uint64_t, float);
|
||||||
|
static inline uint32_t fpToBits(float);
|
||||||
|
|
||||||
template <class fpType>
|
template <class fpType>
|
||||||
static inline bool
|
static inline bool
|
||||||
flushToZero(fpType &op)
|
flushToZero(fpType &op)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -39,12 +39,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/arm/isa.hh"
|
#include "arch/arm/isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "debug/Arm.hh"
|
#include "debug/Arm.hh"
|
||||||
#include "debug/MiscRegs.hh"
|
#include "debug/MiscRegs.hh"
|
||||||
#include "sim/faults.hh"
|
#include "sim/faults.hh"
|
||||||
#include "sim/stat_control.hh"
|
#include "sim/stat_control.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ArmISA
|
namespace ArmISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -279,7 +284,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
PCState pc = tc->pcState();
|
PCState pc = tc->pcState();
|
||||||
pc.nextThumb(cpsr.t);
|
pc.nextThumb(cpsr.t);
|
||||||
pc.nextJazelle(cpsr.j);
|
pc.nextJazelle(cpsr.j);
|
||||||
|
#if USE_CHECKER
|
||||||
|
tc->pcStateNoRecord(pc);
|
||||||
|
#else
|
||||||
tc->pcState(pc);
|
tc->pcState(pc);
|
||||||
|
#endif //USE_CHECKER
|
||||||
} else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
|
} else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
|
||||||
misc_reg < MISCREG_CP15_END) {
|
misc_reg < MISCREG_CP15_END) {
|
||||||
panic("Unimplemented CP15 register %s wrote with %#x.\n",
|
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 = sys->getThreadContext(x);
|
||||||
oc->getDTBPtr()->allCpusCaching();
|
oc->getDTBPtr()->allCpusCaching();
|
||||||
oc->getITBPtr()->allCpusCaching();
|
oc->getITBPtr()->allCpusCaching();
|
||||||
|
#if USE_CHECKER
|
||||||
|
CheckerCPU *checker =
|
||||||
|
dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
|
||||||
|
if (checker) {
|
||||||
|
checker->getDTBPtr()->allCpusCaching();
|
||||||
|
checker->getITBPtr()->allCpusCaching();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,6 +416,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
assert(oc->getITBPtr() && oc->getDTBPtr());
|
assert(oc->getITBPtr() && oc->getDTBPtr());
|
||||||
oc->getITBPtr()->flushAll();
|
oc->getITBPtr()->flushAll();
|
||||||
oc->getDTBPtr()->flushAll();
|
oc->getDTBPtr()->flushAll();
|
||||||
|
#if USE_CHECKER
|
||||||
|
CheckerCPU *checker =
|
||||||
|
dynamic_cast<CheckerCPU*>(oc->getCheckerCpuPtr());
|
||||||
|
if (checker) {
|
||||||
|
checker->getITBPtr()->flushAll();
|
||||||
|
checker->getDTBPtr()->flushAll();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case MISCREG_ITLBIALL:
|
case MISCREG_ITLBIALL:
|
||||||
|
@ -417,6 +442,16 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
bits(newVal, 7,0));
|
bits(newVal, 7,0));
|
||||||
oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
|
oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
|
||||||
bits(newVal, 7,0));
|
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;
|
return;
|
||||||
case MISCREG_TLBIASIDIS:
|
case MISCREG_TLBIASIDIS:
|
||||||
|
@ -427,6 +462,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
assert(oc->getITBPtr() && oc->getDTBPtr());
|
assert(oc->getITBPtr() && oc->getDTBPtr());
|
||||||
oc->getITBPtr()->flushAsid(bits(newVal, 7,0));
|
oc->getITBPtr()->flushAsid(bits(newVal, 7,0));
|
||||||
oc->getDTBPtr()->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;
|
return;
|
||||||
case MISCREG_TLBIMVAAIS:
|
case MISCREG_TLBIMVAAIS:
|
||||||
|
@ -437,6 +480,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
assert(oc->getITBPtr() && oc->getDTBPtr());
|
assert(oc->getITBPtr() && oc->getDTBPtr());
|
||||||
oc->getITBPtr()->flushMva(mbits(newVal, 31,12));
|
oc->getITBPtr()->flushMva(mbits(newVal, 31,12));
|
||||||
oc->getDTBPtr()->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;
|
return;
|
||||||
case MISCREG_ITLBIMVA:
|
case MISCREG_ITLBIMVA:
|
||||||
|
|
|
@ -59,6 +59,7 @@ def format M5ops() {{
|
||||||
case 0x41: return new Dumpstats(machInst);
|
case 0x41: return new Dumpstats(machInst);
|
||||||
case 0x42: return new Dumpresetstats(machInst);
|
case 0x42: return new Dumpresetstats(machInst);
|
||||||
case 0x43: return new M5checkpoint(machInst);
|
case 0x43: return new M5checkpoint(machInst);
|
||||||
|
case 0x4F: return new M5writefile(machInst);
|
||||||
case 0x50: return new M5readfile(machInst);
|
case 0x50: return new M5readfile(machInst);
|
||||||
case 0x51: return new M5break(machInst);
|
case 0x51: return new M5break(machInst);
|
||||||
case 0x52: return new M5switchcpu(machInst);
|
case 0x52: return new M5switchcpu(machInst);
|
||||||
|
|
|
@ -243,7 +243,7 @@ let {{
|
||||||
m5checkpointIop = InstObjParams("m5checkpoint", "M5checkpoint", "PredOp",
|
m5checkpointIop = InstObjParams("m5checkpoint", "M5checkpoint", "PredOp",
|
||||||
{ "code": m5checkpoint_code,
|
{ "code": m5checkpoint_code,
|
||||||
"predicate_test": predicateTest },
|
"predicate_test": predicateTest },
|
||||||
["IsNonSpeculative"])
|
["IsNonSpeculative", "IsUnverifiable"])
|
||||||
header_output += BasicDeclare.subst(m5checkpointIop)
|
header_output += BasicDeclare.subst(m5checkpointIop)
|
||||||
decoder_output += BasicConstructor.subst(m5checkpointIop)
|
decoder_output += BasicConstructor.subst(m5checkpointIop)
|
||||||
exec_output += PredOpExecute.subst(m5checkpointIop)
|
exec_output += PredOpExecute.subst(m5checkpointIop)
|
||||||
|
@ -256,11 +256,27 @@ let {{
|
||||||
m5readfileIop = InstObjParams("m5readfile", "M5readfile", "PredOp",
|
m5readfileIop = InstObjParams("m5readfile", "M5readfile", "PredOp",
|
||||||
{ "code": m5readfileCode,
|
{ "code": m5readfileCode,
|
||||||
"predicate_test": predicateTest },
|
"predicate_test": predicateTest },
|
||||||
["IsNonSpeculative"])
|
["IsNonSpeculative", "IsUnverifiable"])
|
||||||
header_output += BasicDeclare.subst(m5readfileIop)
|
header_output += BasicDeclare.subst(m5readfileIop)
|
||||||
decoder_output += BasicConstructor.subst(m5readfileIop)
|
decoder_output += BasicConstructor.subst(m5readfileIop)
|
||||||
exec_output += PredOpExecute.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",
|
m5breakIop = InstObjParams("m5break", "M5break", "PredOp",
|
||||||
{ "code": "PseudoInst::debugbreak(xc->tcBase());",
|
{ "code": "PseudoInst::debugbreak(xc->tcBase());",
|
||||||
"predicate_test": predicateTest },
|
"predicate_test": predicateTest },
|
||||||
|
|
|
@ -521,7 +521,8 @@ let {{
|
||||||
{ "code" : wfeCode,
|
{ "code" : wfeCode,
|
||||||
"pred_fixup" : wfePredFixUpCode,
|
"pred_fixup" : wfePredFixUpCode,
|
||||||
"predicate_test" : predicateTest },
|
"predicate_test" : predicateTest },
|
||||||
["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
|
["IsNonSpeculative", "IsQuiesce",
|
||||||
|
"IsSerializeAfter", "IsUnverifiable"])
|
||||||
header_output += BasicDeclare.subst(wfeIop)
|
header_output += BasicDeclare.subst(wfeIop)
|
||||||
decoder_output += BasicConstructor.subst(wfeIop)
|
decoder_output += BasicConstructor.subst(wfeIop)
|
||||||
exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
|
exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop)
|
||||||
|
@ -536,7 +537,8 @@ let {{
|
||||||
'''
|
'''
|
||||||
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
|
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
|
||||||
{ "code" : wfiCode, "predicate_test" : predicateTest },
|
{ "code" : wfiCode, "predicate_test" : predicateTest },
|
||||||
["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
|
["IsNonSpeculative", "IsQuiesce",
|
||||||
|
"IsSerializeAfter", "IsUnverifiable"])
|
||||||
header_output += BasicDeclare.subst(wfiIop)
|
header_output += BasicDeclare.subst(wfiIop)
|
||||||
decoder_output += BasicConstructor.subst(wfiIop)
|
decoder_output += BasicConstructor.subst(wfiIop)
|
||||||
exec_output += QuiescePredOpExecute.subst(wfiIop)
|
exec_output += QuiescePredOpExecute.subst(wfiIop)
|
||||||
|
@ -557,7 +559,7 @@ let {{
|
||||||
'''
|
'''
|
||||||
sevIop = InstObjParams("sev", "SevInst", "PredOp", \
|
sevIop = InstObjParams("sev", "SevInst", "PredOp", \
|
||||||
{ "code" : sevCode, "predicate_test" : predicateTest },
|
{ "code" : sevCode, "predicate_test" : predicateTest },
|
||||||
["IsNonSpeculative", "IsSquashAfter"])
|
["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"])
|
||||||
header_output += BasicDeclare.subst(sevIop)
|
header_output += BasicDeclare.subst(sevIop)
|
||||||
decoder_output += BasicConstructor.subst(sevIop)
|
decoder_output += BasicConstructor.subst(sevIop)
|
||||||
exec_output += PredOpExecute.subst(sevIop)
|
exec_output += PredOpExecute.subst(sevIop)
|
||||||
|
|
|
@ -49,7 +49,7 @@ def template BasicDeclare {{
|
||||||
|
|
||||||
// Basic instruction class constructor template.
|
// Basic instruction class constructor template.
|
||||||
def template BasicConstructor {{
|
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;
|
%(constructor)s;
|
||||||
if (!(condCode == COND_AL || condCode == COND_UC)) {
|
if (!(condCode == COND_AL || condCode == COND_UC)) {
|
||||||
|
|
|
@ -411,7 +411,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
if (opc1 >= 0 && opc1 <=7) {
|
if (opc1 <=7) {
|
||||||
switch (crm) {
|
switch (crm) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -107,8 +107,9 @@ TableWalker::getPort(const std::string &if_name, int idx)
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
|
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) {
|
if (!currState) {
|
||||||
// For atomic mode, a new WalkerState instance should be only created
|
// For atomic mode, a new WalkerState instance should be only created
|
||||||
// once per TLB. For timing mode, a new instance is generated for every
|
// 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->fault = NoFault;
|
||||||
currState->contextId = _cid;
|
currState->contextId = _cid;
|
||||||
currState->timing = _timing;
|
currState->timing = _timing;
|
||||||
|
currState->functional = _functional;
|
||||||
currState->mode = _mode;
|
currState->mode = _mode;
|
||||||
|
|
||||||
/** @todo These should be cached or grabbed from cached copies in
|
/** @todo These should be cached or grabbed from cached copies in
|
||||||
|
@ -230,12 +232,21 @@ TableWalker::processWalk()
|
||||||
stateQueueL1.size());
|
stateQueueL1.size());
|
||||||
stateQueueL1.push_back(currState);
|
stateQueueL1.push_back(currState);
|
||||||
currState = NULL;
|
currState = NULL;
|
||||||
} else {
|
} else if (!currState->functional) {
|
||||||
port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
||||||
NULL, (uint8_t*)&currState->l1Desc.data,
|
NULL, (uint8_t*)&currState->l1Desc.data,
|
||||||
currState->tc->getCpuPtr()->ticks(1), flag);
|
currState->tc->getCpuPtr()->ticks(1), flag);
|
||||||
doL1Descriptor();
|
doL1Descriptor();
|
||||||
f = currState->fault;
|
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;
|
return f;
|
||||||
|
@ -566,11 +577,19 @@ TableWalker::doL1Descriptor()
|
||||||
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||||
&doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
|
&doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
|
||||||
currState->tc->getCpuPtr()->ticks(1));
|
currState->tc->getCpuPtr()->ticks(1));
|
||||||
} else {
|
} else if (!currState->functional) {
|
||||||
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||||
NULL, (uint8_t*)&currState->l2Desc.data,
|
NULL, (uint8_t*)&currState->l2Desc.data,
|
||||||
currState->tc->getCpuPtr()->ticks(1));
|
currState->tc->getCpuPtr()->ticks(1));
|
||||||
doL2Descriptor();
|
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;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -294,6 +294,9 @@ class TableWalker : public MemObject
|
||||||
/** If the mode is timing or atomic */
|
/** If the mode is timing or atomic */
|
||||||
bool timing;
|
bool timing;
|
||||||
|
|
||||||
|
/** If the atomic mode should be functional */
|
||||||
|
bool functional;
|
||||||
|
|
||||||
/** Save mode for use in delayed response */
|
/** Save mode for use in delayed response */
|
||||||
BaseTLB::Mode mode;
|
BaseTLB::Mode mode;
|
||||||
|
|
||||||
|
@ -354,7 +357,7 @@ class TableWalker : public MemObject
|
||||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||||
|
|
||||||
Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
|
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 setTlb(TLB *_tlb) { tlb = _tlb; }
|
||||||
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
|
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
|
||||||
|
|
|
@ -443,8 +443,11 @@ TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
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) {
|
if (!miscRegValid) {
|
||||||
updateMiscReg(tc);
|
updateMiscReg(tc);
|
||||||
DPRINTF(TLBVerbose, "TLB variables changed!\n");
|
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",
|
DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n",
|
||||||
vaddr, contextId);
|
vaddr, contextId);
|
||||||
fault = tableWalker->walk(req, tc, contextId, mode, translation,
|
fault = tableWalker->walk(req, tc, contextId, mode, translation,
|
||||||
timing);
|
timing, functional);
|
||||||
if (timing && fault == NoFault) {
|
if (timing && fault == NoFault) {
|
||||||
delay = true;
|
delay = true;
|
||||||
// for timing mode, return and wait for table walk
|
// for timing mode, return and wait for table walk
|
||||||
|
@ -686,6 +689,19 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
Fault
|
||||||
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, Mode mode)
|
Translation *translation, Mode mode)
|
||||||
|
|
|
@ -180,6 +180,12 @@ class TLB : public BaseTLB
|
||||||
*/
|
*/
|
||||||
bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr);
|
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
|
/** Accessor functions for memory attributes for last accessed TLB entry
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -194,7 +200,8 @@ class TLB : public BaseTLB
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
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,
|
Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||||
Translation *translation, bool &delay, bool timing);
|
Translation *translation, bool &delay, bool timing);
|
||||||
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "arch/arm/tlb.hh"
|
#include "arch/arm/tlb.hh"
|
||||||
#include "arch/arm/utility.hh"
|
#include "arch/arm/utility.hh"
|
||||||
#include "arch/arm/vtophys.hh"
|
#include "arch/arm/vtophys.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "mem/fs_translating_port_proxy.hh"
|
#include "mem/fs_translating_port_proxy.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
|
@ -113,7 +114,11 @@ skipFunction(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
TheISA::PCState newPC = tc->pcState();
|
TheISA::PCState newPC = tc->pcState();
|
||||||
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
|
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
|
||||||
|
#if USE_CHECKER
|
||||||
|
tc->pcStateNoRecord(newPC);
|
||||||
|
#else
|
||||||
tc->pcState(newPC);
|
tc->pcState(newPC);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -64,7 +64,7 @@ readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, MemT &mem,
|
||||||
memset(&mem, 0, sizeof(mem));
|
memset(&mem, 0, sizeof(mem));
|
||||||
Fault fault = readMemTiming(xc, traceData, addr, mem, flags);
|
Fault fault = readMemTiming(xc, traceData, addr, mem, flags);
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
mem = gtoh(mem);
|
mem = TheISA::gtoh(mem);
|
||||||
if (traceData)
|
if (traceData)
|
||||||
traceData->setData(mem);
|
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);
|
Fault fault = writeMemTiming(xc, traceData, mem, addr, flags, res);
|
||||||
if (fault == NoFault && res != NULL) {
|
if (fault == NoFault && res != NULL) {
|
||||||
*res = gtoh((MemT)*res);
|
*res = TheISA::gtoh((MemT)*res);
|
||||||
}
|
}
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ template <> FaultVals MipsFault<TlbInvalidFault>::vals =
|
||||||
template <> FaultVals MipsFault<TlbRefillFault>::vals =
|
template <> FaultVals MipsFault<TlbRefillFault>::vals =
|
||||||
{ "TLB Refill Exception", 0x180, ExcCodeDummy };
|
{ "TLB Refill Exception", 0x180, ExcCodeDummy };
|
||||||
|
|
||||||
template <> FaultVals MipsFault<TlbModifiedFault>::vals =
|
template <> MipsFaultBase::FaultVals MipsFault<TlbModifiedFault>::vals =
|
||||||
{ "TLB Modified Exception", 0x180, ExcCodeMod };
|
{ "TLB Modified Exception", 0x180, ExcCodeMod };
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -300,7 +300,7 @@ class TlbModifiedFault : public TlbFault<TlbModifiedFault>
|
||||||
TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false)
|
TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ExcCode code() const { return vals.code; }
|
ExcCode code() const { return MipsFault<TlbModifiedFault>::code(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MipsISA
|
} // namespace MipsISA
|
||||||
|
|
|
@ -48,11 +48,11 @@
|
||||||
|
|
||||||
class Port;
|
class Port;
|
||||||
|
|
||||||
class X86ACPIRSDPParams;
|
struct X86ACPIRSDPParams;
|
||||||
|
|
||||||
class X86ACPISysDescTableParams;
|
struct X86ACPISysDescTableParams;
|
||||||
class X86ACPIRSDTParams;
|
struct X86ACPIRSDTParams;
|
||||||
class X86ACPIXSDTParams;
|
struct X86ACPIXSDTParams;
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,7 +72,7 @@ template<class T>
|
||||||
uint8_t
|
uint8_t
|
||||||
writeOutField(PortProxy* proxy, Addr addr, T val)
|
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));
|
proxy->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T));
|
||||||
|
|
||||||
uint8_t checkSum = 0;
|
uint8_t checkSum = 0;
|
||||||
|
|
|
@ -54,24 +54,24 @@
|
||||||
class PortProxy;
|
class PortProxy;
|
||||||
|
|
||||||
// Config entry types
|
// Config entry types
|
||||||
class X86IntelMPBaseConfigEntryParams;
|
struct X86IntelMPBaseConfigEntryParams;
|
||||||
class X86IntelMPExtConfigEntryParams;
|
struct X86IntelMPExtConfigEntryParams;
|
||||||
|
|
||||||
// General table structures
|
// General table structures
|
||||||
class X86IntelMPConfigTableParams;
|
struct X86IntelMPConfigTableParams;
|
||||||
class X86IntelMPFloatingPointerParams;
|
struct X86IntelMPFloatingPointerParams;
|
||||||
|
|
||||||
// Base entry types
|
// Base entry types
|
||||||
class X86IntelMPBusParams;
|
struct X86IntelMPBusParams;
|
||||||
class X86IntelMPIOAPICParams;
|
struct X86IntelMPIOAPICParams;
|
||||||
class X86IntelMPIOIntAssignmentParams;
|
struct X86IntelMPIOIntAssignmentParams;
|
||||||
class X86IntelMPLocalIntAssignmentParams;
|
struct X86IntelMPLocalIntAssignmentParams;
|
||||||
class X86IntelMPProcessorParams;
|
struct X86IntelMPProcessorParams;
|
||||||
|
|
||||||
// Extended entry types
|
// Extended entry types
|
||||||
class X86IntelMPAddrSpaceMappingParams;
|
struct X86IntelMPAddrSpaceMappingParams;
|
||||||
class X86IntelMPBusHierarchyParams;
|
struct X86IntelMPBusHierarchyParams;
|
||||||
class X86IntelMPCompatAddrSpaceModParams;
|
struct X86IntelMPCompatAddrSpaceModParams;
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,9 +52,9 @@
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
class PortProxy;
|
class PortProxy;
|
||||||
class X86SMBiosBiosInformationParams;
|
struct X86SMBiosBiosInformationParams;
|
||||||
class X86SMBiosSMBiosStructureParams;
|
struct X86SMBiosSMBiosStructureParams;
|
||||||
class X86SMBiosSMBiosTableParams;
|
struct X86SMBiosSMBiosTableParams;
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,10 +40,6 @@
|
||||||
|
|
||||||
#if USE_FAST_ALLOC
|
#if USE_FAST_ALLOC
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#pragma implementation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *FastAlloc::freeLists[Num_Buckets];
|
void *FastAlloc::freeLists[Num_Buckets];
|
||||||
|
|
||||||
#if FAST_ALLOC_STATS
|
#if FAST_ALLOC_STATS
|
||||||
|
|
|
@ -73,6 +73,13 @@ class OutputDirectory
|
||||||
*/
|
*/
|
||||||
std::ostream *checkForStdio(const std::string &name) const;
|
std::ostream *checkForStdio(const std::string &name) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor. */
|
||||||
|
OutputDirectory();
|
||||||
|
|
||||||
|
/** Destructor. */
|
||||||
|
~OutputDirectory();
|
||||||
|
|
||||||
/** Opens a file (optionally compressed).
|
/** Opens a file (optionally compressed).
|
||||||
*
|
*
|
||||||
* Will open a file as a compressed stream if filename ends in .gz.
|
* 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::ostream *openFile(const std::string &filename,
|
||||||
std::ios_base::openmode mode = std::ios::trunc);
|
std::ios_base::openmode mode = std::ios::trunc);
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructor. */
|
|
||||||
OutputDirectory();
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~OutputDirectory();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets name of this directory.
|
* Sets name of this directory.
|
||||||
* @param dir name of this directory
|
* @param dir name of this directory
|
||||||
|
|
|
@ -215,7 +215,7 @@ class range_multimap
|
||||||
{
|
{
|
||||||
std::pair<iterator,iterator> p;
|
std::pair<iterator,iterator> p;
|
||||||
p = find(r);
|
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())
|
p.first == tree.end())
|
||||||
return tree.insert(std::make_pair<Range<T>,V>(r, d));
|
return tree.insert(std::make_pair<Range<T>,V>(r, d));
|
||||||
else
|
else
|
||||||
|
|
|
@ -204,7 +204,7 @@ class BaseRemoteGDB
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
|
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);
|
virtual void process(ThreadContext *tc);
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,7 +72,7 @@ class ContainerPrint
|
||||||
|
|
||||||
// Treat all objects in an stl container as pointers to heap objects,
|
// Treat all objects in an stl container as pointers to heap objects,
|
||||||
// calling delete on each one and zeroing the pointers along the way
|
// 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
|
void
|
||||||
deletePointers(C<T,A> &container)
|
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
|
// Write out all elements in an stl container as a space separated
|
||||||
// list enclosed in square brackets
|
// 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 &
|
std::ostream &
|
||||||
operator<<(std::ostream& out, const C<T,A> &vec)
|
operator<<(std::ostream& out, const C<T,A> &vec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,6 @@ class BaseCPU(MemObject):
|
||||||
self.connectUncachedPorts(uncached_bus)
|
self.connectUncachedPorts(uncached_bus)
|
||||||
|
|
||||||
def addPrivateSplitL1Caches(self, ic, dc, iwc = None, dwc = None):
|
def addPrivateSplitL1Caches(self, ic, dc, iwc = None, dwc = None):
|
||||||
assert(len(self._cached_ports) < 7)
|
|
||||||
self.icache = ic
|
self.icache = ic
|
||||||
self.dcache = dc
|
self.dcache = dc
|
||||||
self.icache_port = ic.cpu_side
|
self.icache_port = ic.cpu_side
|
||||||
|
@ -180,6 +179,11 @@ class BaseCPU(MemObject):
|
||||||
"dtb_walker_cache.mem_side"]
|
"dtb_walker_cache.mem_side"]
|
||||||
else:
|
else:
|
||||||
self._cached_ports += ["itb.walker.port", "dtb.walker.port"]
|
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):
|
def addTwoLevelCacheHierarchy(self, ic, dc, l2c, iwc = None, dwc = None):
|
||||||
self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
|
self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
|
||||||
|
|
|
@ -35,7 +35,7 @@ class CheckerCPU(BaseCPU):
|
||||||
exitOnError = Param.Bool(False, "Exit on an error")
|
exitOnError = Param.Bool(False, "Exit on an error")
|
||||||
updateOnError = Param.Bool(False,
|
updateOnError = Param.Bool(False,
|
||||||
"Update the checker with the main CPU's state on an error")
|
"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")
|
"If a load result is incorrect, only print a warning and do not exit")
|
||||||
function_trace = Param.Bool(False, "Enable function trace")
|
function_trace = Param.Bool(False, "Enable function trace")
|
||||||
function_trace_start = Param.Tick(0, "Cycle to start function trace")
|
function_trace_start = Param.Tick(0, "Cycle to start function trace")
|
||||||
|
|
42
src/cpu/DummyChecker.py
Normal file
42
src/cpu/DummyChecker.py
Normal file
|
@ -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'
|
|
@ -134,7 +134,9 @@ if env['TARGET_ISA'] == 'sparc':
|
||||||
Source('legiontrace.cc')
|
Source('legiontrace.cc')
|
||||||
|
|
||||||
if env['USE_CHECKER']:
|
if env['USE_CHECKER']:
|
||||||
|
SimObject('DummyChecker.py')
|
||||||
Source('checker/cpu.cc')
|
Source('checker/cpu.cc')
|
||||||
|
Source('dummy_checker_builder.cc')
|
||||||
DebugFlag('Checker')
|
DebugFlag('Checker')
|
||||||
checker_supports = False
|
checker_supports = False
|
||||||
for i in CheckerSupportedCPUList:
|
for i in CheckerSupportedCPUList:
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/output.hh"
|
#include "base/output.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/cpuevent.hh"
|
#include "cpu/cpuevent.hh"
|
||||||
#include "cpu/profile.hh"
|
#include "cpu/profile.hh"
|
||||||
|
@ -65,6 +66,10 @@
|
||||||
#include "sim/sim_exit.hh"
|
#include "sim/sim_exit.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Hack
|
// Hack
|
||||||
#include "sim/stat_control.hh"
|
#include "sim/stat_control.hh"
|
||||||
|
|
||||||
|
@ -212,7 +217,10 @@ BaseCPU::BaseCPU(Params *p)
|
||||||
schedule(event, p->function_trace_start);
|
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) {
|
if (FullSystem) {
|
||||||
profileEvent = NULL;
|
profileEvent = NULL;
|
||||||
|
@ -351,8 +359,10 @@ BaseCPU::switchOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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());
|
assert(threadContexts.size() == oldCPU->threadContexts.size());
|
||||||
|
|
||||||
_cpuId = oldCPU->cpuId();
|
_cpuId = oldCPU->cpuId();
|
||||||
|
@ -396,6 +406,35 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
|
||||||
new_dtb_port->setPeer(peer);
|
new_dtb_port->setPeer(peer);
|
||||||
peer->setPeer(new_dtb_port);
|
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;
|
interrupts = oldCPU->interrupts;
|
||||||
|
|
|
@ -237,16 +237,16 @@ class BaseCPU : public MemObject
|
||||||
/// Notify the CPU that the indicated context is now active. The
|
/// Notify the CPU that the indicated context is now active. The
|
||||||
/// delay parameter indicates the number of ticks to wait before
|
/// delay parameter indicates the number of ticks to wait before
|
||||||
/// executing (typically 0 or 1).
|
/// 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.
|
/// 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.
|
/// 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.
|
/// 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
|
/// Given a Thread Context pointer return the thread num
|
||||||
int findContext(ThreadContext *tc);
|
int findContext(ThreadContext *tc);
|
||||||
|
@ -275,7 +275,7 @@ class BaseCPU : public MemObject
|
||||||
|
|
||||||
/// Take over execution from the given CPU. Used for warm-up and
|
/// Take over execution from the given CPU. Used for warm-up and
|
||||||
/// sampling.
|
/// sampling.
|
||||||
virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);
|
virtual void takeOverFrom(BaseCPU *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
|
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
|
||||||
|
|
|
@ -48,12 +48,14 @@
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "arch/faults.hh"
|
#include "arch/faults.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
#include "base/fast_alloc.hh"
|
#include "base/fast_alloc.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/o3/comm.hh"
|
#include "cpu/o3/comm.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/inst_seq.hh"
|
#include "cpu/inst_seq.hh"
|
||||||
|
@ -175,6 +177,11 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
RequestPtr savedSreqLow;
|
RequestPtr savedSreqLow;
|
||||||
RequestPtr savedSreqHigh;
|
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. */
|
/** @todo: Consider making this private. */
|
||||||
public:
|
public:
|
||||||
/** The sequence number of the instruction. */
|
/** The sequence number of the instruction. */
|
||||||
|
@ -247,14 +254,17 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
|
|
||||||
union Result {
|
union Result {
|
||||||
uint64_t integer;
|
uint64_t integer;
|
||||||
// float fp;
|
|
||||||
double dbl;
|
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
|
/** The result of the instruction; assumes an instruction can have many
|
||||||
* destination register.
|
* destination registers.
|
||||||
*/
|
*/
|
||||||
Result instResult;
|
std::queue<Result> instResult;
|
||||||
|
|
||||||
/** Records changes to result? */
|
/** Records changes to result? */
|
||||||
bool recordResult;
|
bool recordResult;
|
||||||
|
@ -557,56 +567,68 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
/** Returns the logical register index of the i'th source register. */
|
/** Returns the logical register index of the i'th source register. */
|
||||||
RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
|
RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
|
||||||
|
|
||||||
/** Returns the result of an integer instruction. */
|
/** Pops a result off the instResult queue */
|
||||||
uint64_t readIntResult() { return instResult.integer; }
|
template <class T>
|
||||||
|
void popResult(T& t)
|
||||||
|
{
|
||||||
|
if (!instResult.empty()) {
|
||||||
|
instResult.front().get(t);
|
||||||
|
instResult.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the result of a floating point instruction. */
|
/** Read the most recent result stored by this instruction */
|
||||||
float readFloatResult() { return (float)instResult.dbl; }
|
template <class T>
|
||||||
|
void readResult(T& t)
|
||||||
|
{
|
||||||
|
instResult.back().get(t);
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the result of a floating point (double) instruction. */
|
/** Pushes a result onto the instResult queue */
|
||||||
double readDoubleResult() { return instResult.dbl; }
|
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. */
|
/** Records an integer register being set to a value. */
|
||||||
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
|
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
|
||||||
{
|
{
|
||||||
if (recordResult)
|
setResult<uint64_t>(val);
|
||||||
instResult.integer = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records an fp register being set to a value. */
|
/** Records an fp register being set to a value. */
|
||||||
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
|
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
|
||||||
int width)
|
int width)
|
||||||
{
|
{
|
||||||
if (recordResult) {
|
if (width == 32 || width == 64) {
|
||||||
if (width == 32)
|
setResult<double>(val);
|
||||||
instResult.dbl = (double)val;
|
} else {
|
||||||
else if (width == 64)
|
panic("Unsupported width!");
|
||||||
instResult.dbl = val;
|
|
||||||
else
|
|
||||||
panic("Unsupported width!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records an fp register being set to a value. */
|
/** Records an fp register being set to a value. */
|
||||||
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
||||||
{
|
{
|
||||||
if (recordResult)
|
setResult<double>(val);
|
||||||
instResult.dbl = (double)val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records an fp register being set to an integer value. */
|
/** Records an fp register being set to an integer value. */
|
||||||
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val,
|
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val,
|
||||||
int width)
|
int width)
|
||||||
{
|
{
|
||||||
if (recordResult)
|
setResult<uint64_t>(val);
|
||||||
instResult.integer = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records an fp register being set to an integer value. */
|
/** Records an fp register being set to an integer value. */
|
||||||
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val)
|
void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val)
|
||||||
{
|
{
|
||||||
if (recordResult)
|
setResult<uint64_t>(val);
|
||||||
instResult.integer = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records that one of the source registers is ready. */
|
/** Records that one of the source registers is ready. */
|
||||||
|
@ -871,6 +893,12 @@ BaseDynInst<Impl>::readMem(Addr addr, uint8_t *data,
|
||||||
effAddr = req->getVaddr();
|
effAddr = req->getVaddr();
|
||||||
effSize = size;
|
effSize = size;
|
||||||
effAddrValid = true;
|
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);
|
fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
|
||||||
} else {
|
} else {
|
||||||
// Commit will have to clean up whatever happened. Set this
|
// 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();
|
effAddr = req->getVaddr();
|
||||||
effSize = size;
|
effSize = size;
|
||||||
effAddrValid = true;
|
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);
|
fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "base/cprintf.hh"
|
#include "base/cprintf.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/base_dyn_inst.hh"
|
#include "cpu/base_dyn_inst.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "debug/DynInst.hh"
|
#include "debug/DynInst.hh"
|
||||||
|
@ -117,7 +118,6 @@ BaseDynInst<Impl>::initVars()
|
||||||
reqMade = false;
|
reqMade = false;
|
||||||
readyRegs = 0;
|
readyRegs = 0;
|
||||||
|
|
||||||
instResult.integer = 0;
|
|
||||||
recordResult = true;
|
recordResult = true;
|
||||||
|
|
||||||
status.reset();
|
status.reset();
|
||||||
|
@ -157,6 +157,10 @@ BaseDynInst<Impl>::initVars()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
cpu->snList.insert(seqNum);
|
cpu->snList.insert(seqNum);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
reqToVerify = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
@ -182,6 +186,11 @@ BaseDynInst<Impl>::~BaseDynInst()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
cpu->snList.erase(seqNum);
|
cpu->snList.erase(seqNum);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
if (reqToVerify)
|
||||||
|
delete reqToVerify;
|
||||||
|
#endif // USE_CHECKER
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -26,6 +38,7 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Kevin Lim
|
* Authors: Kevin Lim
|
||||||
|
* Geoffrey Blake
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -38,10 +51,11 @@
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "params/CheckerCPU.hh"
|
||||||
|
#include "sim/tlb.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
//The CheckerCPU does alpha only
|
using namespace TheISA;
|
||||||
using namespace AlphaISA;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckerCPU::init()
|
CheckerCPU::init()
|
||||||
|
@ -52,6 +66,8 @@ CheckerCPU::CheckerCPU(Params *p)
|
||||||
: BaseCPU(p), thread(NULL), tc(NULL)
|
: BaseCPU(p), thread(NULL), tc(NULL)
|
||||||
{
|
{
|
||||||
memReq = NULL;
|
memReq = NULL;
|
||||||
|
curStaticInst = NULL;
|
||||||
|
curMacroStaticInst = NULL;
|
||||||
|
|
||||||
numInst = 0;
|
numInst = 0;
|
||||||
startNumInst = 0;
|
startNumInst = 0;
|
||||||
|
@ -66,13 +82,14 @@ CheckerCPU::CheckerCPU(Params *p)
|
||||||
itb = p->itb;
|
itb = p->itb;
|
||||||
dtb = p->dtb;
|
dtb = p->dtb;
|
||||||
systemPtr = NULL;
|
systemPtr = NULL;
|
||||||
process = p->process;
|
workload = p->workload;
|
||||||
thread = new SimpleThread(this, /* thread_num */ 0, process);
|
// 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();
|
tc = thread->getTC();
|
||||||
threadContexts.push_back(tc);
|
threadContexts.push_back(tc);
|
||||||
|
|
||||||
result.integer = 0;
|
updateOnError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckerCPU::~CheckerCPU()
|
CheckerCPU::~CheckerCPU()
|
||||||
|
@ -107,191 +124,193 @@ CheckerCPU::setDcachePort(Port *dcache_port)
|
||||||
void
|
void
|
||||||
CheckerCPU::serialize(ostream &os)
|
CheckerCPU::serialize(ostream &os)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
BaseCPU::serialize(os);
|
|
||||||
SERIALIZE_SCALAR(inst);
|
|
||||||
nameOut(os, csprintf("%s.xc", name()));
|
|
||||||
thread->serialize(os);
|
|
||||||
cacheCompletionEvent.serialize(os);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckerCPU::unserialize(Checkpoint *cp, const string §ion)
|
CheckerCPU::unserialize(Checkpoint *cp, const string §ion)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
BaseCPU::unserialize(cp, section);
|
|
||||||
UNSERIALIZE_SCALAR(inst);
|
|
||||||
thread->unserialize(cp, csprintf("%s.xc", section));
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
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
|
Fault fault = NoFault;
|
||||||
memReq = new Request();
|
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;
|
||||||
|
|
||||||
memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
|
||||||
|
|
||||||
// translate to physical address
|
if (secondAddr > addr)
|
||||||
dtb->translateAtomic(memReq, tc, false);
|
size = secondAddr - addr;
|
||||||
|
|
||||||
PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
|
// 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());
|
||||||
|
|
||||||
pkt->dataStatic(&data);
|
// translate to physical address
|
||||||
|
fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read);
|
||||||
|
|
||||||
if (!(memReq->isUncacheable())) {
|
if (!checked_flags && fault == NoFault && unverifiedReq) {
|
||||||
// Access memory to see if we have the same data
|
flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
|
||||||
dcachePort->sendFunctional(pkt);
|
memReq->getPaddr(), memReq->getFlags());
|
||||||
} else {
|
pAddr = memReq->getPaddr();
|
||||||
// Assume the data is correct if it's an uncached access
|
checked_flags = true;
|
||||||
memcpy(&data, &unverifiedResult.integer, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pkt;
|
|
||||||
|
|
||||||
return NoFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
return read(addr, *(uint64_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CheckerCPU::read(Addr addr, float &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(addr, *(uint32_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(addr, (uint32_t&)data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
dcachePort->sendFunctional(pkt);
|
|
||||||
|
|
||||||
delete pkt;
|
|
||||||
*/
|
|
||||||
memcpy(&inst_data, unverifiedMemData, sizeof(T));
|
|
||||||
|
|
||||||
if (data != inst_data) {
|
|
||||||
warn("%lli: Store value does not match value in memory! "
|
|
||||||
"Instruction: %#x, memory: %#x",
|
|
||||||
curTick(), inst_data, data);
|
|
||||||
handleError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fault != NoFault) {
|
||||||
|
if (memReq->isPrefetch()) {
|
||||||
|
fault = NoFault;
|
||||||
|
}
|
||||||
|
delete memReq;
|
||||||
|
memReq = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memReq != NULL) {
|
||||||
|
delete memReq;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we don't need to access a second cache line, stop now.
|
||||||
|
if (secondAddr <= addr)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup for accessing next cache line
|
||||||
|
data += size;
|
||||||
|
unverifiedMemData += size;
|
||||||
|
size = addr + fullSize - secondAddr;
|
||||||
|
addr = secondAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume the result was the same as the one passed in. This checker
|
if (!flags_match) {
|
||||||
// doesn't check if the SC should succeed or fail, it just checks the
|
warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
|
||||||
// value.
|
curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
|
||||||
if (res && unverifiedReq->scResultValid())
|
unverifiedReq->getFlags(), addr, pAddr, flags);
|
||||||
*res = unverifiedReq->getExtraData();
|
handleError();
|
||||||
|
}
|
||||||
|
|
||||||
return NoFault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
template
|
|
||||||
Fault
|
Fault
|
||||||
CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
|
CheckerCPU::writeMem(uint8_t *data, unsigned size,
|
||||||
|
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);
|
Fault fault = NoFault;
|
||||||
}
|
bool checked_flags = false;
|
||||||
|
bool flags_match = true;
|
||||||
|
Addr pAddr = 0x0;
|
||||||
|
|
||||||
template<>
|
unsigned blockSize = dcachePort->peerBlockSize();
|
||||||
Fault
|
int fullSize = size;
|
||||||
CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(*(uint32_t*)&data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
Addr secondAddr = roundDown(addr + size - 1, blockSize);
|
||||||
Fault
|
|
||||||
CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
|
|
||||||
{
|
|
||||||
return write((uint32_t)data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (secondAddr > addr)
|
||||||
|
size = secondAddr - addr;
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
// translate to physical address
|
||||||
|
fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write);
|
||||||
|
|
||||||
|
if (!checked_flags && fault == NoFault && unverifiedReq) {
|
||||||
|
flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
|
||||||
|
memReq->getPaddr(), memReq->getFlags());
|
||||||
|
pAddr = memReq->getPaddr();
|
||||||
|
checked_flags = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
Addr
|
||||||
CheckerCPU::dbg_vtophys(Addr addr)
|
CheckerCPU::dbg_vtophys(Addr addr)
|
||||||
|
@ -299,24 +318,30 @@ CheckerCPU::dbg_vtophys(Addr addr)
|
||||||
return vtophys(tc, addr);
|
return vtophys(tc, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the flags set by the Checker and Checkee match.
|
||||||
|
*/
|
||||||
bool
|
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.
|
Addr unverifiedVAddr = unverified_req->getVaddr();
|
||||||
unsigned flags = unverifiedReq->getFlags();
|
Addr unverifiedPAddr = unverified_req->getPaddr();
|
||||||
unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
|
int unverifiedFlags = unverified_req->getFlags();
|
||||||
flags = flags & (mask);
|
|
||||||
if (flags == req->getFlags()) {
|
if (unverifiedVAddr != vAddr ||
|
||||||
|
unverifiedPAddr != pAddr ||
|
||||||
|
unverifiedFlags != flags) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckerCPU::dumpAndExit()
|
CheckerCPU::dumpAndExit()
|
||||||
{
|
{
|
||||||
warn("%lli: Checker PC:%#x, next PC:%#x",
|
warn("%lli: Checker PC:%s",
|
||||||
curTick(), thread->readPC(), thread->readNextPC());
|
curTick(), thread->pcState());
|
||||||
panic("Checker found an error!");
|
panic("Checker found an error!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -35,6 +47,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "arch/predecoder.hh"
|
||||||
#include "arch/types.hh"
|
#include "arch/types.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
|
@ -42,6 +55,8 @@
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
#include "debug/Checker.hh"
|
||||||
|
#include "params/CheckerCPU.hh"
|
||||||
#include "sim/eventq.hh"
|
#include "sim/eventq.hh"
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
|
@ -52,12 +67,6 @@ namespace TheISA
|
||||||
|
|
||||||
template <class>
|
template <class>
|
||||||
class BaseDynInst;
|
class BaseDynInst;
|
||||||
class CheckerCPUParams;
|
|
||||||
class Checkpoint;
|
|
||||||
class MemInterface;
|
|
||||||
class PhysicalMemory;
|
|
||||||
class Process;
|
|
||||||
class Processor;
|
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
class Request;
|
class Request;
|
||||||
|
|
||||||
|
@ -90,11 +99,11 @@ class CheckerCPU : public BaseCPU
|
||||||
public:
|
public:
|
||||||
typedef CheckerCPUParams Params;
|
typedef CheckerCPUParams Params;
|
||||||
const Params *params() const
|
const Params *params() const
|
||||||
{ return reinterpret_cast<const Params *>(_params); }
|
{ return reinterpret_cast<const Params *>(_params); }
|
||||||
CheckerCPU(Params *p);
|
CheckerCPU(Params *p);
|
||||||
virtual ~CheckerCPU();
|
virtual ~CheckerCPU();
|
||||||
|
|
||||||
Process *process;
|
std::vector<Process*> workload;
|
||||||
|
|
||||||
void setSystem(System *system);
|
void setSystem(System *system);
|
||||||
|
|
||||||
|
@ -127,19 +136,25 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
union Result {
|
union Result {
|
||||||
uint64_t integer;
|
uint64_t integer;
|
||||||
// float fp;
|
|
||||||
double dbl;
|
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
|
// current instruction
|
||||||
MachInst machInst;
|
TheISA::MachInst machInst;
|
||||||
|
|
||||||
// Pointer to the one memory request.
|
// Pointer to the one memory request.
|
||||||
RequestPtr memReq;
|
RequestPtr memReq;
|
||||||
|
|
||||||
StaticInstPtr curStaticInst;
|
StaticInstPtr curStaticInst;
|
||||||
|
StaticInstPtr curMacroStaticInst;
|
||||||
|
|
||||||
// number of simulated instructions
|
// number of simulated instructions
|
||||||
Counter numInst;
|
Counter numInst;
|
||||||
|
@ -147,6 +162,9 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
std::queue<int> miscRegIdxs;
|
std::queue<int> miscRegIdxs;
|
||||||
|
|
||||||
|
TheISA::TLB* getITBPtr() { return itb; }
|
||||||
|
TheISA::TLB* getDTBPtr() { return dtb; }
|
||||||
|
|
||||||
virtual Counter totalInstructions() const
|
virtual Counter totalInstructions() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -159,12 +177,6 @@ class CheckerCPU : public BaseCPU
|
||||||
virtual void serialize(std::ostream &os);
|
virtual void serialize(std::ostream &os);
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
||||||
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
|
// These functions are only used in CPU models that split
|
||||||
// effective address computation from the actual memory access.
|
// effective address computation from the actual memory access.
|
||||||
void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
|
void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
|
||||||
|
@ -198,17 +210,25 @@ class CheckerCPU : public BaseCPU
|
||||||
return thread->readFloatRegBits(reg_idx);
|
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)
|
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
|
||||||
{
|
{
|
||||||
thread->setIntReg(si->destRegIdx(idx), val);
|
thread->setIntReg(si->destRegIdx(idx), val);
|
||||||
result.integer = val;
|
setResult<uint64_t>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
||||||
{
|
{
|
||||||
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
|
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
|
||||||
thread->setFloatReg(reg_idx, val);
|
thread->setFloatReg(reg_idx, val);
|
||||||
result.dbl = (double)val;
|
setResult<double>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFloatRegOperandBits(const StaticInst *si, int idx,
|
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;
|
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
|
||||||
thread->setFloatRegBits(reg_idx, val);
|
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)
|
MiscReg readMiscRegNoEffect(int misc_reg)
|
||||||
{
|
{
|
||||||
|
@ -235,7 +269,6 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
|
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
result.integer = val;
|
|
||||||
miscRegIdxs.push(misc_reg);
|
miscRegIdxs.push(misc_reg);
|
||||||
return thread->setMiscRegNoEffect(misc_reg, val);
|
return thread->setMiscRegNoEffect(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
@ -246,8 +279,25 @@ class CheckerCPU : public BaseCPU
|
||||||
return thread->setMiscReg(misc_reg, val);
|
return thread->setMiscReg(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recordPCChange(uint64_t val) { changedPC = true; newPC = val; }
|
MiscReg readMiscRegOperand(const StaticInst *si, int idx)
|
||||||
void recordNextPCChange(uint64_t val) { changedNextPC = true; }
|
{
|
||||||
|
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)
|
void demapPage(Addr vaddr, uint64_t asn)
|
||||||
{
|
{
|
||||||
|
@ -265,8 +315,17 @@ class CheckerCPU : public BaseCPU
|
||||||
this->dtb->demapPage(vaddr, asn);
|
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(); }
|
Fault hwrei() { return thread->hwrei(); }
|
||||||
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
||||||
|
void wakeup() { }
|
||||||
// Assume that the normal CPU's call to syscall was successful.
|
// Assume that the normal CPU's call to syscall was successful.
|
||||||
// The checker's state would have already been updated by the syscall.
|
// The checker's state would have already been updated by the syscall.
|
||||||
void syscall(uint64_t callnum) { }
|
void syscall(uint64_t callnum) { }
|
||||||
|
@ -277,7 +336,8 @@ class CheckerCPU : public BaseCPU
|
||||||
dumpAndExit();
|
dumpAndExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkFlags(Request *req);
|
bool checkFlags(Request *unverified_req, Addr vAddr,
|
||||||
|
Addr pAddr, int flags);
|
||||||
|
|
||||||
void dumpAndExit();
|
void dumpAndExit();
|
||||||
|
|
||||||
|
@ -290,7 +350,7 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
bool changedPC;
|
bool changedPC;
|
||||||
bool willChangePC;
|
bool willChangePC;
|
||||||
uint64_t newPC;
|
TheISA::PCState newPCState;
|
||||||
bool changedNextPC;
|
bool changedNextPC;
|
||||||
bool exitOnError;
|
bool exitOnError;
|
||||||
bool updateOnError;
|
bool updateOnError;
|
||||||
|
@ -305,24 +365,31 @@ class CheckerCPU : public BaseCPU
|
||||||
* template instantiations of the Checker must be placed at the bottom
|
* template instantiations of the Checker must be placed at the bottom
|
||||||
* of checker/cpu.cc.
|
* of checker/cpu.cc.
|
||||||
*/
|
*/
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
class Checker : public CheckerCPU
|
class Checker : public CheckerCPU
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
typedef typename Impl::DynInstPtr DynInstPtr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Checker(Params *p)
|
Checker(Params *p)
|
||||||
: CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
|
: CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL),
|
||||||
|
predecoder(NULL)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
|
void advancePC(Fault fault);
|
||||||
|
|
||||||
void verify(DynInstPtr &inst);
|
void verify(DynInstPtr &inst);
|
||||||
|
|
||||||
void validateInst(DynInstPtr &inst);
|
void validateInst(DynInstPtr &inst);
|
||||||
void validateExecution(DynInstPtr &inst);
|
void validateExecution(DynInstPtr &inst);
|
||||||
void validateState();
|
void validateState();
|
||||||
|
|
||||||
void copyResult(DynInstPtr &inst);
|
void copyResult(DynInstPtr &inst, uint64_t mismatch_val, int start_idx);
|
||||||
|
void handlePendingInt();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleError(DynInstPtr &inst)
|
void handleError(DynInstPtr &inst)
|
||||||
|
@ -339,6 +406,7 @@ class Checker : public CheckerCPU
|
||||||
bool updateThisCycle;
|
bool updateThisCycle;
|
||||||
|
|
||||||
DynInstPtr unverifiedInst;
|
DynInstPtr unverifiedInst;
|
||||||
|
TheISA::Predecoder predecoder;
|
||||||
|
|
||||||
std::list<DynInstPtr> instList;
|
std::list<DynInstPtr> instList;
|
||||||
typedef typename std::list<DynInstPtr>::iterator InstListIt;
|
typedef typename std::list<DynInstPtr>::iterator InstListIt;
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -26,6 +38,7 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Kevin Lim
|
* Authors: Kevin Lim
|
||||||
|
* Geoffrey Blake
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -34,25 +47,93 @@
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
#include "base/refcnt.hh"
|
#include "base/refcnt.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "cpu/checker/cpu.hh"
|
|
||||||
#include "cpu/base_dyn_inst.hh"
|
#include "cpu/base_dyn_inst.hh"
|
||||||
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#include "debug/Checker.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
#include "sim/stats.hh"
|
#include "sim/stats.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
//The CheckerCPU does alpha only
|
using namespace TheISA;
|
||||||
using namespace AlphaISA;
|
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
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 Impl>
|
||||||
|
void
|
||||||
|
Checker<Impl>::verify(DynInstPtr &completed_inst)
|
||||||
{
|
{
|
||||||
DynInstPtr 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
|
// Either check this instruction, or add it to a list of
|
||||||
// instructions waiting to be checked. Instructions must be
|
// instructions waiting to be checked. Instructions must be
|
||||||
// checked in program order, so if a store has committed yet not
|
// 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.
|
// behind it that have completed and must be checked.
|
||||||
if (!instList.empty()) {
|
if (!instList.empty()) {
|
||||||
if (youngestSN < completed_inst->seqNum) {
|
if (youngestSN < completed_inst->seqNum) {
|
||||||
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
|
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
|
||||||
completed_inst->seqNum, completed_inst->readPC());
|
completed_inst->seqNum, completed_inst->pcState());
|
||||||
instList.push_back(completed_inst);
|
instList.push_back(completed_inst);
|
||||||
youngestSN = completed_inst->seqNum;
|
youngestSN = completed_inst->seqNum;
|
||||||
}
|
}
|
||||||
|
@ -75,8 +156,8 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
} else {
|
} else {
|
||||||
if (!completed_inst->isCompleted()) {
|
if (!completed_inst->isCompleted()) {
|
||||||
if (youngestSN < completed_inst->seqNum) {
|
if (youngestSN < completed_inst->seqNum) {
|
||||||
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
|
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
|
||||||
completed_inst->seqNum, completed_inst->readPC());
|
completed_inst->seqNum, completed_inst->pcState());
|
||||||
instList.push_back(completed_inst);
|
instList.push_back(completed_inst);
|
||||||
youngestSN = completed_inst->seqNum;
|
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;
|
unverifiedInst = inst;
|
||||||
|
inst = NULL;
|
||||||
|
|
||||||
// Try to check all instructions that are completed, ending if we
|
// Try to check all instructions that are completed, ending if we
|
||||||
// run out of instructions to check or if an instruction is not
|
// run out of instructions to check or if an instruction is not
|
||||||
// yet completed.
|
// yet completed.
|
||||||
while (1) {
|
while (1) {
|
||||||
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
|
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n",
|
||||||
inst->seqNum, inst->readPC());
|
unverifiedInst->seqNum, unverifiedInst->pcState());
|
||||||
unverifiedResult.integer = inst->readIntResult();
|
unverifiedReq = NULL;
|
||||||
unverifiedReq = inst->req;
|
unverifiedReq = unverifiedInst->reqToVerify;
|
||||||
unverifiedMemData = inst->memData;
|
unverifiedMemData = unverifiedInst->memData;
|
||||||
|
// Make sure results queue is empty
|
||||||
|
while (!result.empty()) {
|
||||||
|
result.pop();
|
||||||
|
}
|
||||||
numCycles++;
|
numCycles++;
|
||||||
|
|
||||||
Fault fault = NoFault;
|
Fault fault = NoFault;
|
||||||
|
@ -116,15 +209,15 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
// expect to happen. This is mostly to check if traps or
|
// expect to happen. This is mostly to check if traps or
|
||||||
// PC-based events have occurred in both the checker and CPU.
|
// PC-based events have occurred in both the checker and CPU.
|
||||||
if (changedPC) {
|
if (changedPC) {
|
||||||
DPRINTF(Checker, "Changed PC recently to %#x\n",
|
DPRINTF(Checker, "Changed PC recently to %s\n",
|
||||||
thread->readPC());
|
thread->pcState());
|
||||||
if (willChangePC) {
|
if (willChangePC) {
|
||||||
if (newPC == thread->readPC()) {
|
if (newPCState == thread->pcState()) {
|
||||||
DPRINTF(Checker, "Changed PC matches expected PC\n");
|
DPRINTF(Checker, "Changed PC matches expected PC\n");
|
||||||
} else {
|
} else {
|
||||||
warn("%lli: Changed PC does not match expected PC, "
|
warn("%lli: Changed PC does not match expected PC, "
|
||||||
"changed: %#x, expected: %#x",
|
"changed: %s, expected: %s",
|
||||||
curTick(), thread->readPC(), newPC);
|
curTick(), thread->pcState(), newPCState);
|
||||||
CheckerCPU::handleError();
|
CheckerCPU::handleError();
|
||||||
}
|
}
|
||||||
willChangePC = false;
|
willChangePC = false;
|
||||||
|
@ -133,118 +226,186 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
}
|
}
|
||||||
if (changedNextPC) {
|
if (changedNextPC) {
|
||||||
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
|
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
|
||||||
thread->readNextPC());
|
thread->nextInstAddr());
|
||||||
changedNextPC = false;
|
changedNextPC = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to fetch the instruction
|
// Try to fetch the instruction
|
||||||
|
uint64_t fetchOffset = 0;
|
||||||
|
bool fetchDone = false;
|
||||||
|
|
||||||
#define IFETCH_FLAGS(pc) (FullSystem ? 0 : ((pc) & 1) ? PHYSICAL : 0)
|
while (!fetchDone) {
|
||||||
|
Addr fetch_PC = thread->instAddr();
|
||||||
|
fetch_PC = (fetch_PC & PCMask) + fetchOffset;
|
||||||
|
|
||||||
uint64_t fetch_PC = thread->readPC() & ~3;
|
// 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());
|
||||||
|
|
||||||
// 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);
|
fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
|
||||||
|
|
||||||
if (!succeeded) {
|
if (fault != NoFault) {
|
||||||
if (inst->getFault() == NoFault) {
|
if (unverifiedInst->getFault() == NoFault) {
|
||||||
// In this case the instruction was not a dummy
|
// In this case the instruction was not a dummy
|
||||||
// instruction carrying an ITB fault. In the single
|
// instruction carrying an ITB fault. In the single
|
||||||
// threaded case the ITB should still be able to
|
// threaded case the ITB should still be able to
|
||||||
// translate this instruction; in the SMT case it's
|
// translate this instruction; in the SMT case it's
|
||||||
// possible that its ITB entry was kicked out.
|
// possible that its ITB entry was kicked out.
|
||||||
warn("%lli: Instruction PC %#x was not found in the ITB!",
|
warn("%lli: Instruction PC %s was not found in the "
|
||||||
curTick(), thread->readPC());
|
"ITB!", curTick(), thread->pcState());
|
||||||
handleError(inst);
|
handleError(unverifiedInst);
|
||||||
|
|
||||||
// go to the next instruction
|
// go to the next instruction
|
||||||
thread->setPC(thread->readNextPC());
|
advancePC(NoFault);
|
||||||
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
|
|
||||||
|
|
||||||
break;
|
// Give up on an ITB fault..
|
||||||
} else {
|
delete memReq;
|
||||||
// The instruction is carrying an ITB fault. Handle
|
unverifiedInst = NULL;
|
||||||
// the fault and see if our results match the CPU on
|
return;
|
||||||
// the next tick().
|
} else {
|
||||||
fault = inst->getFault();
|
// 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);
|
||||||
|
|
||||||
|
pkt->dataStatic(&machInst);
|
||||||
|
icachePort->sendFunctional(pkt);
|
||||||
|
machInst = gtoh(machInst);
|
||||||
|
|
||||||
|
delete memReq;
|
||||||
|
delete pkt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
if (fault == NoFault) {
|
||||||
PacketPtr pkt = new Packet(memReq, Packet::ReadReq,
|
unverifiedFault = unverifiedInst->getFault();
|
||||||
Packet::Broadcast);
|
|
||||||
|
|
||||||
pkt->dataStatic(&machInst);
|
|
||||||
|
|
||||||
icachePort->sendFunctional(pkt);
|
|
||||||
|
|
||||||
delete pkt;
|
|
||||||
|
|
||||||
// keep an instruction count
|
|
||||||
numInst++;
|
|
||||||
|
|
||||||
// decode the instruction
|
|
||||||
machInst = gtoh(machInst);
|
|
||||||
// Checks that the instruction matches what we expected it to be.
|
// Checks that the instruction matches what we expected it to be.
|
||||||
// Checks both the machine instruction and the PC.
|
// Checks both the machine instruction and the PC.
|
||||||
validateInst(inst);
|
validateInst(unverifiedInst);
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard fetch's memReq.
|
// keep an instruction count
|
||||||
delete memReq;
|
numInst++;
|
||||||
memReq = NULL;
|
|
||||||
|
|
||||||
// Either the instruction was a fault and we should process the fault,
|
// Either the instruction was a fault and we should process the fault,
|
||||||
// or we should just go ahead execute the instruction. This assumes
|
// or we should just go ahead execute the instruction. This assumes
|
||||||
// that the instruction is properly marked as a fault.
|
// that the instruction is properly marked as a fault.
|
||||||
if (fault == NoFault) {
|
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 (fault == NoFault && unverifiedFault == NoFault) {
|
||||||
|
thread->funcExeInst++;
|
||||||
|
// Checks to make sure instrution results are correct.
|
||||||
|
validateExecution(unverifiedInst);
|
||||||
|
|
||||||
if (!inst->isUnverifiable())
|
if (curStaticInst->isLoad()) {
|
||||||
fault = curStaticInst->execute(this, NULL);
|
++numLoad;
|
||||||
|
}
|
||||||
// Checks to make sure instrution results are correct.
|
} else if (fault != NoFault && unverifiedFault == NoFault) {
|
||||||
validateExecution(inst);
|
panic("%lli: sn: %lli at PC: %s took a fault in checker "
|
||||||
|
"but not in driver CPU\n", curTick(),
|
||||||
if (curStaticInst->isLoad()) {
|
unverifiedInst->seqNum, unverifiedInst->pcState());
|
||||||
++numLoad;
|
} 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) {
|
if (fault != NoFault) {
|
||||||
fault->invoke(tc, curStaticInst);
|
fault->invoke(tc, curStaticInst);
|
||||||
willChangePC = true;
|
willChangePC = true;
|
||||||
newPC = thread->readPC();
|
newPCState = thread->pcState();
|
||||||
DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
|
DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
|
||||||
|
curMacroStaticInst = StaticInst::nullStaticInstPtr;
|
||||||
} else {
|
} else {
|
||||||
#if THE_ISA != MIPS_ISA
|
advancePC(fault);
|
||||||
// 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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FullSystem) {
|
if (FullSystem) {
|
||||||
|
@ -254,14 +415,14 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
Addr oldpc;
|
Addr oldpc;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
do {
|
do {
|
||||||
oldpc = thread->readPC();
|
oldpc = thread->instAddr();
|
||||||
system->pcEventQueue.service(tc);
|
system->pcEventQueue.service(tc);
|
||||||
count++;
|
count++;
|
||||||
} while (oldpc != thread->readPC());
|
} while (oldpc != thread->instAddr());
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
willChangePC = true;
|
willChangePC = true;
|
||||||
newPC = thread->readPC();
|
newPCState = thread->pcState();
|
||||||
DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
|
DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,17 +430,13 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
// that have been modified).
|
// that have been modified).
|
||||||
validateState();
|
validateState();
|
||||||
|
|
||||||
if (memReq) {
|
|
||||||
delete memReq;
|
|
||||||
memReq = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue verifying instructions if there's another completed
|
// Continue verifying instructions if there's another completed
|
||||||
// instruction waiting to be verified.
|
// instruction waiting to be verified.
|
||||||
if (instList.empty()) {
|
if (instList.empty()) {
|
||||||
break;
|
break;
|
||||||
} else if (instList.front()->isCompleted()) {
|
} else if (instList.front()->isCompleted()) {
|
||||||
inst = instList.front();
|
unverifiedInst = NULL;
|
||||||
|
unverifiedInst = instList.front();
|
||||||
instList.pop_front();
|
instList.pop_front();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -288,26 +445,26 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
unverifiedInst = NULL;
|
unverifiedInst = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::switchOut()
|
Checker<Impl>::switchOut()
|
||||||
{
|
{
|
||||||
instList.clear();
|
instList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
|
Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
|
Checker<Impl>::validateInst(DynInstPtr &inst)
|
||||||
{
|
{
|
||||||
if (inst->readPC() != thread->readPC()) {
|
if (inst->instAddr() != thread->instAddr()) {
|
||||||
warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
|
warn("%lli: PCs do not match! Inst: %s, checker: %s",
|
||||||
curTick(), inst->readPC(), thread->readPC());
|
curTick(), inst->pcState(), thread->pcState());
|
||||||
if (changedPC) {
|
if (changedPC) {
|
||||||
warn("%lli: Changed PCs recently, may not be an error",
|
warn("%lli: Changed PCs recently, may not be an error",
|
||||||
curTick());
|
curTick());
|
||||||
|
@ -319,51 +476,70 @@ Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
|
||||||
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
|
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
|
||||||
|
|
||||||
if (mi != machInst) {
|
if (mi != machInst) {
|
||||||
warn("%lli: Binary instructions do not match! Inst: %#x, "
|
panic("%lli: Binary instructions do not match! Inst: %#x, "
|
||||||
"checker: %#x",
|
"checker: %#x",
|
||||||
curTick(), mi, machInst);
|
curTick(), mi, machInst);
|
||||||
handleError(inst);
|
handleError(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
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;
|
bool result_mismatch = false;
|
||||||
if (inst->numDestRegs()) {
|
|
||||||
// @todo: Support more destination registers.
|
if (inst->isUnverifiable()) {
|
||||||
if (inst->isUnverifiable()) {
|
// Unverifiable instructions assume they were executed
|
||||||
// Unverifiable instructions assume they were executed
|
// properly by the CPU. Grab the result from the
|
||||||
// properly by the CPU. Grab the result from the
|
// instruction and write it to the register.
|
||||||
// instruction and write it to the register.
|
copyResult(inst, 0, idx);
|
||||||
copyResult(inst);
|
} else if (inst->numDestRegs() > 0 && !result.empty()) {
|
||||||
} else if (result.integer != inst->readIntResult()) {
|
DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
|
||||||
result_mismatch = true;
|
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) {
|
if (result_mismatch) {
|
||||||
warn("%lli: Instruction results do not match! (Values may not "
|
warn("%lli: Instruction results do not match! (Values may not "
|
||||||
"actually be integers) Inst: %#x, checker: %#x",
|
"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
|
// It's useful to verify load values from memory, but in MP
|
||||||
// systems the value obtained at execute may be different than
|
// systems the value obtained at execute may be different than
|
||||||
// the value obtained at completion. Similarly DMA can
|
// the value obtained at completion. Similarly DMA can
|
||||||
// present the same problem on even UP systems. Thus there is
|
// present the same problem on even UP systems. Thus there is
|
||||||
// the option to only warn on loads having a result error.
|
// 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) {
|
if (inst->isLoad() && warnOnlyOnLoadError) {
|
||||||
copyResult(inst);
|
copyResult(inst, inst_val, idx);
|
||||||
} else {
|
} else {
|
||||||
handleError(inst);
|
handleError(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->readNextPC() != thread->readNextPC()) {
|
if (inst->nextInstAddr() != thread->nextInstAddr()) {
|
||||||
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
|
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
|
||||||
"checker: %#x",
|
"checker: %#x",
|
||||||
curTick(), inst->readNextPC(), thread->readNextPC());
|
curTick(), inst->nextInstAddr(), thread->nextInstAddr());
|
||||||
handleError(inst);
|
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
|
void
|
||||||
Checker<DynInstPtr>::validateState()
|
Checker<Impl>::validateState()
|
||||||
{
|
{
|
||||||
if (updateThisCycle) {
|
if (updateThisCycle) {
|
||||||
warn("%lli: Instruction PC %#x results didn't match up, copying all "
|
// Change this back to warn if divergences end up being false positives
|
||||||
"registers from main CPU", curTick(), unverifiedInst->readPC());
|
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
|
// Heavy-weight copying of all registers
|
||||||
thread->copyArchRegs(unverifiedInst->tcBase());
|
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.
|
// Also advance the PC. Hopefully no PC-based events happened.
|
||||||
#if THE_ISA != MIPS_ISA
|
advancePC(NoFault);
|
||||||
// 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
|
|
||||||
updateThisCycle = false;
|
updateThisCycle = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
|
Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
|
||||||
|
int start_idx)
|
||||||
{
|
{
|
||||||
RegIndex idx = inst->destRegIdx(0);
|
// We've already popped one dest off the queue,
|
||||||
if (idx < TheISA::FP_Base_DepTag) {
|
// so do the fix-up then start with the next dest reg;
|
||||||
thread->setIntReg(idx, inst->readIntResult());
|
if (start_idx >= 0) {
|
||||||
} else if (idx < TheISA::Fpcr_DepTag) {
|
RegIndex idx = inst->destRegIdx(start_idx);
|
||||||
thread->setFloatRegBits(idx, inst->readIntResult());
|
if (idx < TheISA::FP_Base_DepTag) {
|
||||||
} else {
|
thread->setIntReg(idx, mismatch_val);
|
||||||
thread->setMiscRegNoEffect(idx, inst->readIntResult());
|
} 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
|
void
|
||||||
Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
|
Checker<Impl>::dumpAndExit(DynInstPtr &inst)
|
||||||
{
|
{
|
||||||
cprintf("Error detected, instruction information:\n");
|
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",
|
"Completed:%i\n",
|
||||||
inst->readPC(),
|
inst->pcState(),
|
||||||
inst->readNextPC(),
|
inst->nextInstAddr(),
|
||||||
inst->seqNum,
|
inst->seqNum,
|
||||||
inst->threadNumber,
|
inst->threadNumber,
|
||||||
inst->isCompleted());
|
inst->isCompleted());
|
||||||
|
@ -442,9 +643,9 @@ Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
|
||||||
CheckerCPU::dumpAndExit();
|
CheckerCPU::dumpAndExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DynInstPtr>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
Checker<DynInstPtr>::dumpInsts()
|
Checker<Impl>::dumpInsts()
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
|
@ -457,9 +658,9 @@ Checker<DynInstPtr>::dumpInsts()
|
||||||
cprintf("Instruction:%i\n",
|
cprintf("Instruction:%i\n",
|
||||||
num);
|
num);
|
||||||
|
|
||||||
cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
|
cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n"
|
||||||
"Completed:%i\n",
|
"Completed:%i\n",
|
||||||
(*inst_list_it)->readPC(),
|
(*inst_list_it)->pcState(),
|
||||||
(*inst_list_it)->seqNum,
|
(*inst_list_it)->seqNum,
|
||||||
(*inst_list_it)->threadNumber,
|
(*inst_list_it)->threadNumber,
|
||||||
(*inst_list_it)->isCompleted());
|
(*inst_list_it)->isCompleted());
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +48,7 @@
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "debug/Checker.hh"
|
||||||
|
|
||||||
class EndQuiesceEvent;
|
class EndQuiesceEvent;
|
||||||
namespace TheISA {
|
namespace TheISA {
|
||||||
|
@ -77,18 +90,32 @@ class CheckerThreadContext : public ThreadContext
|
||||||
|
|
||||||
BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); }
|
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);
|
actualTC->setContextId(id);
|
||||||
checkerTC->setCpuId(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 *getITBPtr() { return actualTC->getITBPtr(); }
|
||||||
|
|
||||||
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
||||||
|
|
||||||
|
BaseCPU *getCheckerCpuPtr() { return checkerTC->getCpuPtr(); }
|
||||||
|
|
||||||
|
Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
|
||||||
|
|
||||||
System *getSystemPtr() { return actualTC->getSystemPtr(); }
|
System *getSystemPtr() { return actualTC->getSystemPtr(); }
|
||||||
|
|
||||||
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
|
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
|
||||||
|
@ -103,8 +130,21 @@ class CheckerThreadContext : public ThreadContext
|
||||||
FSTranslatingPortProxy* getVirtProxy()
|
FSTranslatingPortProxy* getVirtProxy()
|
||||||
{ return actualTC->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(); }
|
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(); }
|
Status status() const { return actualTC->status(); }
|
||||||
|
|
||||||
void setStatus(Status new_status)
|
void setStatus(Status new_status)
|
||||||
|
@ -118,10 +158,10 @@ class CheckerThreadContext : public ThreadContext
|
||||||
void activate(int delay = 1) { actualTC->activate(delay); }
|
void activate(int delay = 1) { actualTC->activate(delay); }
|
||||||
|
|
||||||
/// Set the status to Suspended.
|
/// Set the status to Suspended.
|
||||||
void suspend() { actualTC->suspend(); }
|
void suspend(int delay) { actualTC->suspend(delay); }
|
||||||
|
|
||||||
/// Set the status to Halted.
|
/// Set the status to Halted.
|
||||||
void halt() { actualTC->halt(); }
|
void halt(int delay) { actualTC->halt(delay); }
|
||||||
|
|
||||||
void dumpFuncProfile() { actualTC->dumpFuncProfile(); }
|
void dumpFuncProfile() { actualTC->dumpFuncProfile(); }
|
||||||
|
|
||||||
|
@ -131,7 +171,11 @@ class CheckerThreadContext : public ThreadContext
|
||||||
checkerTC->copyState(oldContext);
|
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 serialize(std::ostream &os) { actualTC->serialize(os); }
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
@ -145,8 +189,6 @@ class CheckerThreadContext : public ThreadContext
|
||||||
void profileClear() { return actualTC->profileClear(); }
|
void profileClear() { return actualTC->profileClear(); }
|
||||||
void profileSample() { return actualTC->profileSample(); }
|
void profileSample() { return actualTC->profileSample(); }
|
||||||
|
|
||||||
int threadId() { return actualTC->threadId(); }
|
|
||||||
|
|
||||||
// @todo: Do I need this?
|
// @todo: Do I need this?
|
||||||
void copyArchRegs(ThreadContext *tc)
|
void copyArchRegs(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
|
@ -190,32 +232,36 @@ class CheckerThreadContext : public ThreadContext
|
||||||
checkerTC->setFloatRegBits(reg_idx, val);
|
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);
|
DPRINTF(Checker, "Changing PC to %s, old PC %s\n",
|
||||||
checkerTC->setPC(val);
|
val, checkerTC->pcState());
|
||||||
|
checkerTC->pcState(val);
|
||||||
checkerCPU->recordPCChange(val);
|
checkerCPU->recordPCChange(val);
|
||||||
|
return actualTC->pcState(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t readNextPC() { return actualTC->readNextPC(); }
|
void pcStateNoRecord(const TheISA::PCState &val)
|
||||||
|
|
||||||
void setNextPC(uint64_t val)
|
|
||||||
{
|
{
|
||||||
actualTC->setNextPC(val);
|
return actualTC->pcState(val);
|
||||||
checkerTC->setNextPC(val);
|
|
||||||
checkerCPU->recordNextPCChange(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t readNextNPC() { return actualTC->readNextNPC(); }
|
/** Reads this thread's PC. */
|
||||||
|
Addr instAddr()
|
||||||
|
{ return actualTC->instAddr(); }
|
||||||
|
|
||||||
void setNextNPC(uint64_t val)
|
/** Reads this thread's next PC. */
|
||||||
{
|
Addr nextInstAddr()
|
||||||
actualTC->setNextNPC(val);
|
{ return actualTC->nextInstAddr(); }
|
||||||
checkerTC->setNextNPC(val);
|
|
||||||
checkerCPU->recordNextPCChange(val);
|
/** Reads this thread's next PC. */
|
||||||
}
|
MicroPC microPC()
|
||||||
|
{ return actualTC->microPC(); }
|
||||||
|
|
||||||
MiscReg readMiscRegNoEffect(int misc_reg)
|
MiscReg readMiscRegNoEffect(int misc_reg)
|
||||||
{ return actualTC->readMiscRegNoEffect(misc_reg); }
|
{ return actualTC->readMiscRegNoEffect(misc_reg); }
|
||||||
|
@ -225,22 +271,28 @@ class CheckerThreadContext : public ThreadContext
|
||||||
|
|
||||||
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
|
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);
|
checkerTC->setMiscRegNoEffect(misc_reg, val);
|
||||||
actualTC->setMiscRegNoEffect(misc_reg, val);
|
actualTC->setMiscRegNoEffect(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMiscReg(int misc_reg, const MiscReg &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);
|
checkerTC->setMiscReg(misc_reg, val);
|
||||||
actualTC->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()
|
unsigned readStCondFailures()
|
||||||
{ return actualTC->readStCondFailures(); }
|
{ return actualTC->readStCondFailures(); }
|
||||||
|
|
||||||
void setStCondFailures(unsigned sc_failures)
|
void setStCondFailures(unsigned sc_failures)
|
||||||
{
|
{
|
||||||
checkerTC->setStCondFailures(sc_failures);
|
|
||||||
actualTC->setStCondFailures(sc_failures);
|
actualTC->setStCondFailures(sc_failures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
97
src/cpu/dummy_checker_builder.cc
Normal file
97
src/cpu/dummy_checker_builder.cc
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -47,8 +47,9 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
struct OpDesc : public SimObject
|
class OpDesc : public SimObject
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
OpClass opClass;
|
OpClass opClass;
|
||||||
unsigned opLat;
|
unsigned opLat;
|
||||||
unsigned issueLat;
|
unsigned issueLat;
|
||||||
|
@ -58,8 +59,9 @@ struct OpDesc : public SimObject
|
||||||
issueLat(p->issueLat) {};
|
issueLat(p->issueLat) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FUDesc : public SimObject
|
class FUDesc : public SimObject
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
std::vector<OpDesc *> opDescList;
|
std::vector<OpDesc *> opDescList;
|
||||||
unsigned number;
|
unsigned number;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ InOrderCPU::TickEvent::process()
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
InOrderCPU::TickEvent::description()
|
InOrderCPU::TickEvent::description() const
|
||||||
{
|
{
|
||||||
return "InOrderCPU tick event";
|
return "InOrderCPU tick event";
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ InOrderCPU::CPUEvent::process()
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
InOrderCPU::CPUEvent::description()
|
InOrderCPU::CPUEvent::description() const
|
||||||
{
|
{
|
||||||
return "InOrderCPU event";
|
return "InOrderCPU event";
|
||||||
}
|
}
|
||||||
|
@ -1156,11 +1156,11 @@ InOrderCPU::activateNextReadyContext(int delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
InOrderCPU::haltContext(ThreadID tid, int delay)
|
InOrderCPU::haltContext(ThreadID tid)
|
||||||
{
|
{
|
||||||
DPRINTF(InOrderCPU, "[tid:%i]: Calling Halt Context...\n", 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();
|
activityRec.activity();
|
||||||
}
|
}
|
||||||
|
@ -1181,9 +1181,9 @@ InOrderCPU::haltThread(ThreadID tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
|
|
|
@ -147,7 +147,7 @@ class InOrderCPU : public BaseCPU
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
/** Returns the description of the tick event. */
|
/** Returns the description of the tick event. */
|
||||||
const char *description();
|
const char *description() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The tick event used for scheduling CPU ticks. */
|
/** The tick event used for scheduling CPU ticks. */
|
||||||
|
@ -229,7 +229,7 @@ class InOrderCPU : public BaseCPU
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
/** Returns the description of the CPU event. */
|
/** Returns the description of the CPU event. */
|
||||||
const char *description();
|
const char *description() const;
|
||||||
|
|
||||||
/** Schedule Event */
|
/** Schedule Event */
|
||||||
void scheduleEvent(int delay);
|
void scheduleEvent(int delay);
|
||||||
|
@ -469,13 +469,13 @@ class InOrderCPU : public BaseCPU
|
||||||
void deactivateThread(ThreadID tid);
|
void deactivateThread(ThreadID tid);
|
||||||
|
|
||||||
/** Schedule a thread suspension on the CPU */
|
/** 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 */
|
/** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
|
||||||
void suspendThread(ThreadID tid);
|
void suspendThread(ThreadID tid);
|
||||||
|
|
||||||
/** Schedule a thread halt on the CPU */
|
/** 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
|
/** Halt Thread, Remove from Active Thread List, Place Thread on Halted
|
||||||
* Threads List
|
* Threads List
|
||||||
|
|
|
@ -512,7 +512,7 @@ ResourceEvent::process()
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ResourceEvent::description()
|
ResourceEvent::description() const
|
||||||
{
|
{
|
||||||
string desc = resource->name() + "-event:slot[" + to_string(slotIdx)
|
string desc = resource->name() + "-event:slot[" + to_string(slotIdx)
|
||||||
+ "]";
|
+ "]";
|
||||||
|
|
|
@ -51,6 +51,9 @@ class ResourceRequest;
|
||||||
typedef ResourceRequest ResReq;
|
typedef ResourceRequest ResReq;
|
||||||
typedef ResourceRequest* ResReqPtr;
|
typedef ResourceRequest* ResReqPtr;
|
||||||
|
|
||||||
|
class CacheRequest;
|
||||||
|
typedef CacheRequest* CacheReqPtr;
|
||||||
|
|
||||||
class Resource {
|
class Resource {
|
||||||
public:
|
public:
|
||||||
typedef ThePipeline::DynInstPtr DynInstPtr;
|
typedef ThePipeline::DynInstPtr DynInstPtr;
|
||||||
|
@ -154,8 +157,9 @@ class Resource {
|
||||||
* if instruction is actually in resource before
|
* if instruction is actually in resource before
|
||||||
* trying to do access.Needs to be defined for derived units.
|
* trying to do access.Needs to be defined for derived units.
|
||||||
*/
|
*/
|
||||||
virtual Fault doCacheAccess(DynInstPtr inst, uint64_t *res=NULL)
|
virtual void doCacheAccess(DynInstPtr inst, uint64_t *write_result = NULL,
|
||||||
{ panic("doCacheAccess undefined for %s", name()); return NoFault; }
|
CacheReqPtr split_req = NULL)
|
||||||
|
{ panic("doCacheAccess undefined for %s", name()); }
|
||||||
|
|
||||||
/** Setup Squash to be sent out to pipeline and resource pool */
|
/** Setup Squash to be sent out to pipeline and resource pool */
|
||||||
void setupSquash(DynInstPtr inst, int stage_num, ThreadID tid);
|
void setupSquash(DynInstPtr inst, int stage_num, ThreadID tid);
|
||||||
|
@ -283,7 +287,7 @@ class ResourceEvent : public Event
|
||||||
virtual void process();
|
virtual void process();
|
||||||
|
|
||||||
/** Returns the description of the resource event. */
|
/** Returns the description of the resource event. */
|
||||||
const char *description();
|
const char *description() const;
|
||||||
|
|
||||||
/** Set slot idx for event */
|
/** Set slot idx for event */
|
||||||
void setSlot(int slot) { slotIdx = slot; }
|
void setSlot(int slot) { slotIdx = slot; }
|
||||||
|
@ -320,7 +324,7 @@ class ResourceRequest
|
||||||
|
|
||||||
int reqID;
|
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);
|
int res_idx, int slot_num, unsigned _cmd);
|
||||||
|
|
||||||
virtual void clearRequest();
|
virtual void clearRequest();
|
||||||
|
|
|
@ -485,7 +485,7 @@ ResourcePool::ResPoolEvent::process()
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ResourcePool::ResPoolEvent::description()
|
ResourcePool::ResPoolEvent::description() const
|
||||||
{
|
{
|
||||||
return "Resource Pool event";
|
return "Resource Pool event";
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ class ResourcePool {
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
/** Returns the description of the resource event. */
|
/** Returns the description of the resource event. */
|
||||||
const char *description();
|
const char *description() const;
|
||||||
|
|
||||||
/** Schedule Event */
|
/** Schedule Event */
|
||||||
void scheduleEvent(int delay);
|
void scheduleEvent(int delay);
|
||||||
|
|
|
@ -49,9 +49,6 @@
|
||||||
#include "params/InOrderCPU.hh"
|
#include "params/InOrderCPU.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
class CacheRequest;
|
|
||||||
typedef CacheRequest* CacheReqPtr;
|
|
||||||
|
|
||||||
class CacheReqPacket;
|
class CacheReqPacket;
|
||||||
typedef CacheReqPacket* CacheReqPktPtr;
|
typedef CacheReqPacket* CacheReqPktPtr;
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ InOrderThreadContext::suspend(int delay)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
thread->setStatus(ThreadContext::Suspended);
|
thread->setStatus(ThreadContext::Suspended);
|
||||||
cpu->suspendContext(thread->threadId(), delay);
|
cpu->suspendContext(thread->threadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -135,7 +135,7 @@ InOrderThreadContext::halt(int delay)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
thread->setStatus(ThreadContext::Halted);
|
thread->setStatus(ThreadContext::Halted);
|
||||||
cpu->haltContext(thread->threadId(), delay);
|
cpu->haltContext(thread->threadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ class NativeTrace : public ExeTracer
|
||||||
{
|
{
|
||||||
size_t soFar = 0;
|
size_t soFar = 0;
|
||||||
while (soFar < size) {
|
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)
|
if (res < 0)
|
||||||
panic("Read call failed! %s\n", strerror(errno));
|
panic("Read call failed! %s\n", strerror(errno));
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,11 +40,15 @@ class DerivO3CPU(BaseCPU):
|
||||||
activity = Param.Unsigned(0, "Initial count")
|
activity = Param.Unsigned(0, "Initial count")
|
||||||
|
|
||||||
if buildEnv['USE_CHECKER']:
|
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,
|
exitOnError=False,
|
||||||
updateOnError=True,
|
updateOnError=True,
|
||||||
warnOnlyOnLoadError=False),
|
warnOnlyOnLoadError=True),
|
||||||
"checker")
|
"checker")
|
||||||
checker.itb = Parent.itb
|
checker.itb = Parent.itb
|
||||||
checker.dtb = Parent.dtb
|
checker.dtb = Parent.dtb
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class O3Checker(BaseCPU):
|
||||||
exitOnError = Param.Bool(False, "Exit on an error")
|
exitOnError = Param.Bool(False, "Exit on an error")
|
||||||
updateOnError = Param.Bool(False,
|
updateOnError = Param.Bool(False,
|
||||||
"Update the checker with the main CPU's state on an error")
|
"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")
|
"If a load result is incorrect, only print a warning and do not exit")
|
||||||
function_trace = Param.Bool(False, "Enable function trace")
|
function_trace = Param.Bool(False, "Enable function trace")
|
||||||
function_trace_start = Param.Tick(0, "Cycle to start function trace")
|
function_trace_start = Param.Tick(0, "Cycle to start function trace")
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#include "cpu/pred/tournament.hh"
|
#include "cpu/pred/tournament.hh"
|
||||||
#include "cpu/inst_seq.hh"
|
#include "cpu/inst_seq.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basically a wrapper class to hold both the branch predictor
|
* Basically a wrapper class to hold both the branch predictor
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -31,8 +43,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "cpu/checker/cpu_impl.hh"
|
#include "cpu/checker/cpu_impl.hh"
|
||||||
#include "cpu/o3/alpha/dyn_inst.hh"
|
#include "cpu/o3/dyn_inst.hh"
|
||||||
#include "cpu/o3/alpha/impl.hh"
|
#include "cpu/o3/impl.hh"
|
||||||
#include "cpu/inst_seq.hh"
|
#include "cpu/inst_seq.hh"
|
||||||
#include "params/O3Checker.hh"
|
#include "params/O3Checker.hh"
|
||||||
#include "sim/process.hh"
|
#include "sim/process.hh"
|
||||||
|
@ -41,16 +53,16 @@
|
||||||
class MemObject;
|
class MemObject;
|
||||||
|
|
||||||
template
|
template
|
||||||
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
|
class Checker<O3CPUImpl>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific non-templated derived class used for SimObject configuration.
|
* Specific non-templated derived class used for SimObject configuration.
|
||||||
*/
|
*/
|
||||||
class O3Checker : public Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >
|
class O3Checker : public Checker<O3CPUImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
O3Checker(Params *p)
|
O3Checker(Params *p)
|
||||||
: Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >(p)
|
: Checker<O3CPUImpl>(p)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,7 +75,7 @@ O3CheckerParams::create()
|
||||||
{
|
{
|
||||||
O3Checker::Params *params = new O3Checker::Params();
|
O3Checker::Params *params = new O3Checker::Params();
|
||||||
params->name = name;
|
params->name = name;
|
||||||
params->numberOfThreads = 1;
|
params->numThreads = numThreads;
|
||||||
params->max_insts_any_thread = 0;
|
params->max_insts_any_thread = 0;
|
||||||
params->max_insts_all_threads = 0;
|
params->max_insts_all_threads = 0;
|
||||||
params->max_loads_any_thread = 0;
|
params->max_loads_any_thread = 0;
|
||||||
|
@ -71,10 +83,8 @@ O3CheckerParams::create()
|
||||||
params->exitOnError = exitOnError;
|
params->exitOnError = exitOnError;
|
||||||
params->updateOnError = updateOnError;
|
params->updateOnError = updateOnError;
|
||||||
params->warnOnlyOnLoadError = warnOnlyOnLoadError;
|
params->warnOnlyOnLoadError = warnOnlyOnLoadError;
|
||||||
params->deferRegistration = defer_registration;
|
|
||||||
params->functionTrace = function_trace;
|
|
||||||
params->functionTraceStart = function_trace_start;
|
|
||||||
params->clock = clock;
|
params->clock = clock;
|
||||||
|
params->tracer = tracer;
|
||||||
// Hack to touch all parameters. Consider not deriving Checker
|
// Hack to touch all parameters. Consider not deriving Checker
|
||||||
// from BaseCPU..it's not really a CPU in the end.
|
// from BaseCPU..it's not really a CPU in the end.
|
||||||
Counter temp;
|
Counter temp;
|
||||||
|
@ -91,7 +101,8 @@ O3CheckerParams::create()
|
||||||
params->system = system;
|
params->system = system;
|
||||||
params->cpu_id = cpu_id;
|
params->cpu_id = cpu_id;
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
params->process = workload;
|
params->interrupts = NULL;
|
||||||
|
params->workload = workload;
|
||||||
|
|
||||||
O3Checker *cpu = new O3Checker(params);
|
O3Checker *cpu = new O3Checker(params);
|
||||||
return cpu;
|
return cpu;
|
||||||
|
|
|
@ -51,10 +51,10 @@
|
||||||
#include "cpu/inst_seq.hh"
|
#include "cpu/inst_seq.hh"
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
template <class>
|
template <class>
|
||||||
class O3ThreadState;
|
struct O3ThreadState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultCommit handles single threaded and SMT commit. Its width is
|
* DefaultCommit handles single threaded and SMT commit. Its width is
|
||||||
|
|
|
@ -725,6 +725,12 @@ DefaultCommit<Impl>::handleInterrupt()
|
||||||
assert(!thread[0]->inSyscall);
|
assert(!thread[0]->inSyscall);
|
||||||
thread[0]->inSyscall = true;
|
thread[0]->inSyscall = true;
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
if (cpu->checker) {
|
||||||
|
cpu->checker->handlePendingInt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// CPU will handle interrupt.
|
// CPU will handle interrupt.
|
||||||
cpu->processInterrupts(interrupt);
|
cpu->processInterrupts(interrupt);
|
||||||
|
|
||||||
|
@ -769,8 +775,8 @@ void
|
||||||
DefaultCommit<Impl>::commit()
|
DefaultCommit<Impl>::commit()
|
||||||
{
|
{
|
||||||
if (FullSystem) {
|
if (FullSystem) {
|
||||||
// Check for any interrupt that we've already squashed for and start
|
// Check for any interrupt that we've already squashed for and
|
||||||
// processing it.
|
// start processing it.
|
||||||
if (interrupt != NoFault)
|
if (interrupt != NoFault)
|
||||||
handleInterrupt();
|
handleInterrupt();
|
||||||
|
|
||||||
|
@ -1128,7 +1134,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
head_inst->setCompleted();
|
head_inst->setCompleted();
|
||||||
|
|
||||||
#if USE_CHECKER
|
#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);
|
cpu->checker->verify(head_inst);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
|
|
||||||
#if USE_CHECKER
|
#if USE_CHECKER
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#include "cpu/checker/thread_context.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if THE_ISA == ALPHA_ISA
|
#if THE_ISA == ALPHA_ISA
|
||||||
|
@ -72,7 +73,7 @@
|
||||||
#include "debug/Activity.hh"
|
#include "debug/Activity.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class BaseCPUParams;
|
struct BaseCPUParams;
|
||||||
|
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -265,7 +266,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
|
||||||
#if USE_CHECKER
|
#if USE_CHECKER
|
||||||
if (params->checker) {
|
if (params->checker) {
|
||||||
BaseCPU *temp_checker = 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->setIcachePort(&icachePort);
|
||||||
checker->setSystem(params->system);
|
checker->setSystem(params->system);
|
||||||
} else {
|
} else {
|
||||||
|
@ -759,7 +760,8 @@ FullO3CPU<Impl>::activateContext(ThreadID tid, int delay)
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
bool
|
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
|
// Schedule removal of thread data from CPU
|
||||||
if (delay){
|
if (delay){
|
||||||
|
@ -780,7 +782,7 @@ void
|
||||||
FullO3CPU<Impl>::suspendContext(ThreadID tid)
|
FullO3CPU<Impl>::suspendContext(ThreadID tid)
|
||||||
{
|
{
|
||||||
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", 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 this was the last thread then unschedule the tick event.
|
||||||
if ((activeThreads.size() == 1 && !deallocated) ||
|
if ((activeThreads.size() == 1 && !deallocated) ||
|
||||||
activeThreads.size() == 0)
|
activeThreads.size() == 0)
|
||||||
|
@ -797,7 +799,7 @@ FullO3CPU<Impl>::haltContext(ThreadID tid)
|
||||||
{
|
{
|
||||||
//For now, this is the same as deallocate
|
//For now, this is the same as deallocate
|
||||||
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
|
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
|
||||||
deallocateContext(tid, true, 1);
|
scheduleDeallocateContext(tid, true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
@ -1216,7 +1218,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
|
||||||
activityRec.reset();
|
activityRec.reset();
|
||||||
|
|
||||||
BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
|
BaseCPU::takeOverFrom(oldCPU);
|
||||||
|
|
||||||
fetch.takeOverFrom();
|
fetch.takeOverFrom();
|
||||||
decode.takeOverFrom();
|
decode.takeOverFrom();
|
||||||
|
|
|
@ -78,7 +78,7 @@ class Checkpoint;
|
||||||
class MemObject;
|
class MemObject;
|
||||||
class Process;
|
class Process;
|
||||||
|
|
||||||
class BaseCPUParams;
|
struct BaseCPUParams;
|
||||||
|
|
||||||
class BaseO3CPU : public BaseCPU
|
class BaseO3CPU : public BaseCPU
|
||||||
{
|
{
|
||||||
|
@ -400,7 +400,7 @@ class FullO3CPU : public BaseO3CPU
|
||||||
/** Remove Thread from Active Threads List &&
|
/** Remove Thread from Active Threads List &&
|
||||||
* Possibly Remove Thread Context from CPU.
|
* 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 from Active Threads List &&
|
||||||
* Remove Thread Context from CPU.
|
* 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
|
* instruction results at run time. This can be set to NULL if it
|
||||||
* is not being used.
|
* is not being used.
|
||||||
*/
|
*/
|
||||||
Checker<DynInstPtr> *checker;
|
Checker<Impl> *checker;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Pointer to the system. */
|
/** Pointer to the system. */
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultDecode class handles both single threaded and SMT
|
* DefaultDecode class handles both single threaded and SMT
|
||||||
|
|
|
@ -38,7 +38,9 @@
|
||||||
#include "params/DerivO3CPU.hh"
|
#include "params/DerivO3CPU.hh"
|
||||||
#include "sim/full_system.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>
|
template<class Impl>
|
||||||
DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
|
DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "base/cp_annotate.hh"
|
#include "base/cp_annotate.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/o3/dyn_inst.hh"
|
#include "cpu/o3/dyn_inst.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
|
|
||||||
|
@ -137,6 +138,11 @@ BaseO3DynInst<Impl>::completeAcc(PacketPtr pkt)
|
||||||
bool in_syscall = this->thread->inSyscall;
|
bool in_syscall = this->thread->inSyscall;
|
||||||
this->thread->inSyscall = true;
|
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->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
|
||||||
|
|
||||||
this->thread->inSyscall = in_syscall;
|
this->thread->inSyscall = in_syscall;
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
#include "sim/eventq.hh"
|
#include "sim/eventq.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultFetch class handles both single threaded and SMT fetch. Its
|
* DefaultFetch class handles both single threaded and SMT fetch. Its
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
#include "arch/tlb.hh"
|
#include "arch/tlb.hh"
|
||||||
|
@ -52,7 +55,6 @@
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "config/use_checker.hh"
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/checker/cpu.hh"
|
|
||||||
#include "cpu/o3/fetch.hh"
|
#include "cpu/o3/fetch.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "debug/Activity.hh"
|
#include "debug/Activity.hh"
|
||||||
|
@ -66,6 +68,10 @@
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#endif // USE_CHECKER
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
|
|
|
@ -252,7 +252,7 @@ FUPool::switchOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FUPool::takeOverFrom()
|
FUPool::takeOver()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numFU; i++) {
|
for (int i = 0; i < numFU; i++) {
|
||||||
unitBusy[i] = false;
|
unitBusy[i] = false;
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "cpu/op_class.hh"
|
#include "cpu/op_class.hh"
|
||||||
#include "cpu/sched_list.hh"
|
|
||||||
#include "params/FUPool.hh"
|
#include "params/FUPool.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
|
@ -162,7 +161,7 @@ class FUPool : public SimObject
|
||||||
void switchOut();
|
void switchOut();
|
||||||
|
|
||||||
/** Takes over from another CPU's thread. */
|
/** Takes over from another CPU's thread. */
|
||||||
void takeOverFrom();
|
void takeOver();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CPU_O3_FU_POOL_HH__
|
#endif // __CPU_O3_FU_POOL_HH__
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
#include "debug/IEW.hh"
|
#include "debug/IEW.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
class FUPool;
|
class FUPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,9 +93,6 @@ class DefaultIEW
|
||||||
typedef typename CPUPol::RenameStruct RenameStruct;
|
typedef typename CPUPol::RenameStruct RenameStruct;
|
||||||
typedef typename CPUPol::IssueStruct IssueStruct;
|
typedef typename CPUPol::IssueStruct IssueStruct;
|
||||||
|
|
||||||
friend class Impl::O3CPU;
|
|
||||||
friend class CPUPol::IQ;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Overall IEW stage status. Used to determine if the CPU can
|
/** Overall IEW stage status. Used to determine if the CPU can
|
||||||
* deschedule itself due to a lack of activity.
|
* deschedule itself due to a lack of activity.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
|
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/o3/fu_pool.hh"
|
#include "cpu/o3/fu_pool.hh"
|
||||||
#include "cpu/o3/iew.hh"
|
#include "cpu/o3/iew.hh"
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
|
@ -56,6 +57,10 @@
|
||||||
#include "debug/IEW.hh"
|
#include "debug/IEW.hh"
|
||||||
#include "params/DerivO3CPU.hh"
|
#include "params/DerivO3CPU.hh"
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#endif // USE_CHECKER
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
|
@ -294,6 +299,13 @@ DefaultIEW<Impl>::initStage()
|
||||||
ldstQueue.numFreeEntries(tid);
|
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);
|
cpu->activateStage(O3CPU::IEWIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +412,7 @@ DefaultIEW<Impl>::takeOverFrom()
|
||||||
|
|
||||||
instQueue.takeOverFrom();
|
instQueue.takeOverFrom();
|
||||||
ldstQueue.takeOverFrom();
|
ldstQueue.takeOverFrom();
|
||||||
fuPool->takeOverFrom();
|
fuPool->takeOver();
|
||||||
|
|
||||||
initStage();
|
initStage();
|
||||||
cpu->activityThisCycle();
|
cpu->activityThisCycle();
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
#include "sim/eventq.hh"
|
#include "sim/eventq.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
class FUPool;
|
class FUPool;
|
||||||
class MemInterface;
|
class MemInterface;
|
||||||
|
|
||||||
|
@ -93,8 +93,6 @@ class InstructionQueue
|
||||||
// Typedef of iterator through the list of instructions.
|
// Typedef of iterator through the list of instructions.
|
||||||
typedef typename std::list<DynInstPtr>::iterator ListIt;
|
typedef typename std::list<DynInstPtr>::iterator ListIt;
|
||||||
|
|
||||||
friend class Impl::O3CPU;
|
|
||||||
|
|
||||||
/** FU completion event class. */
|
/** FU completion event class. */
|
||||||
class FUCompletion : public Event {
|
class FUCompletion : public Event {
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -51,7 +51,9 @@
|
||||||
#include "params/DerivO3CPU.hh"
|
#include "params/DerivO3CPU.hh"
|
||||||
#include "sim/core.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>
|
template <class Impl>
|
||||||
InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
|
InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
class LSQ {
|
class LSQ {
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that implements the actual LQ and SQ for each specific
|
* Class that implements the actual LQ and SQ for each specific
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -45,7 +45,6 @@
|
||||||
#include "arch/locked_mem.hh"
|
#include "arch/locked_mem.hh"
|
||||||
#include "base/str.hh"
|
#include "base/str.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "config/use_checker.hh"
|
|
||||||
#include "cpu/o3/lsq.hh"
|
#include "cpu/o3/lsq.hh"
|
||||||
#include "cpu/o3/lsq_unit.hh"
|
#include "cpu/o3/lsq_unit.hh"
|
||||||
#include "debug/Activity.hh"
|
#include "debug/Activity.hh"
|
||||||
|
@ -246,12 +245,6 @@ void
|
||||||
LSQUnit<Impl>::setDcachePort(Port *dcache_port)
|
LSQUnit<Impl>::setDcachePort(Port *dcache_port)
|
||||||
{
|
{
|
||||||
dcachePort = dcache_port;
|
dcachePort = dcache_port;
|
||||||
|
|
||||||
#if USE_CHECKER
|
|
||||||
if (cpu->checker) {
|
|
||||||
cpu->checker->setDcachePort(dcachePort);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
|
@ -878,6 +871,11 @@ LSQUnit<Impl>::writebackStores()
|
||||||
inst->seqNum);
|
inst->seqNum);
|
||||||
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
|
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
|
||||||
cpu->schedule(wb, curTick() + 1);
|
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);
|
completeStore(storeWBIdx);
|
||||||
incrStIdx(storeWBIdx);
|
incrStIdx(storeWBIdx);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
#include "cpu/o3/mem_dep_unit_impl.hh"
|
#include "cpu/o3/mem_dep_unit_impl.hh"
|
||||||
#include "cpu/o3/store_set.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
|
#ifdef DEBUG
|
||||||
template <>
|
template <>
|
||||||
int
|
int
|
||||||
|
@ -47,3 +43,7 @@ template <>
|
||||||
int
|
int
|
||||||
MemDepUnit<StoreSet, O3CPUImpl>::MemDepEntry::memdep_erase = 0;
|
MemDepUnit<StoreSet, O3CPUImpl>::MemDepEntry::memdep_erase = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Force instantation of memory dependency unit using store sets and
|
||||||
|
// O3CPUImpl.
|
||||||
|
template class MemDepUnit<StoreSet, O3CPUImpl>;
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct SNHash {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
class InstructionQueue;
|
class InstructionQueue;
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "cpu/timebuf.hh"
|
#include "cpu/timebuf.hh"
|
||||||
|
|
||||||
class DerivO3CPUParams;
|
struct DerivO3CPUParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultRename handles both single threaded and SMT rename. Its
|
* DefaultRename handles both single threaded and SMT rename. Its
|
||||||
|
|
|
@ -65,7 +65,8 @@ class SatCounter
|
||||||
* @param initial_val Starting value for each counter.
|
* @param initial_val Starting value for each counter.
|
||||||
*/
|
*/
|
||||||
SatCounter(unsigned bits, uint8_t initial_val)
|
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
|
// Check to make sure initial value doesn't exceed the max
|
||||||
// counter value.
|
// counter value.
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2004-2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -32,6 +44,7 @@
|
||||||
#define __CPU_O3_THREAD_CONTEXT_HH__
|
#define __CPU_O3_THREAD_CONTEXT_HH__
|
||||||
|
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/o3/isa_specific.hh"
|
#include "cpu/o3/isa_specific.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
@ -71,6 +84,10 @@ class O3ThreadContext : public ThreadContext
|
||||||
/** Returns a pointer to the DTB. */
|
/** Returns a pointer to the DTB. */
|
||||||
TheISA::TLB *getDTBPtr() { return cpu->dtb; }
|
TheISA::TLB *getDTBPtr() { return cpu->dtb; }
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
BaseCPU *getCheckerCpuPtr() { return NULL; }
|
||||||
|
#endif
|
||||||
|
|
||||||
Decoder *getDecoderPtr() { return &cpu->fetch.decoder; }
|
Decoder *getDecoderPtr() { return &cpu->fetch.decoder; }
|
||||||
|
|
||||||
/** Returns a pointer to this CPU. */
|
/** Returns a pointer to this CPU. */
|
||||||
|
@ -177,6 +194,10 @@ class O3ThreadContext : public ThreadContext
|
||||||
/** Sets this thread's PC state. */
|
/** Sets this thread's PC state. */
|
||||||
virtual void pcState(const TheISA::PCState &val);
|
virtual void pcState(const TheISA::PCState &val);
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
virtual void pcStateNoRecord(const TheISA::PCState &val);
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Reads this thread's PC. */
|
/** Reads this thread's PC. */
|
||||||
virtual Addr instAddr()
|
virtual Addr instAddr()
|
||||||
{ return cpu->instAddr(thread->threadId()); }
|
{ return cpu->instAddr(thread->threadId()); }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
#include "arch/kernel_stats.hh"
|
#include "arch/kernel_stats.hh"
|
||||||
#include "arch/registers.hh"
|
#include "arch/registers.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/o3/thread_context.hh"
|
#include "cpu/o3/thread_context.hh"
|
||||||
#include "cpu/quiesce_event.hh"
|
#include "cpu/quiesce_event.hh"
|
||||||
#include "debug/O3CPU.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>
|
template <class Impl>
|
||||||
int
|
int
|
||||||
O3ThreadContext<Impl>::flattenIntIndex(int reg)
|
O3ThreadContext<Impl>::flattenIntIndex(int reg)
|
||||||
|
|
|
@ -36,8 +36,9 @@
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
|
|
||||||
/** Event for timing out quiesce instruction */
|
/** Event for timing out quiesce instruction */
|
||||||
struct EndQuiesceEvent : public Event
|
class EndQuiesceEvent : public Event
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
/** A pointer to the thread context that is quiesced */
|
/** A pointer to the thread context that is quiesced */
|
||||||
ThreadContext *tc;
|
ThreadContext *tc;
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -26,9 +26,18 @@
|
||||||
#
|
#
|
||||||
# Authors: Gabe Black
|
# Authors: Gabe Black
|
||||||
|
|
||||||
|
from m5.defines import buildEnv
|
||||||
from m5.params import *
|
from m5.params import *
|
||||||
from BaseCPU import BaseCPU
|
from BaseCPU import BaseCPU
|
||||||
|
|
||||||
|
if buildEnv['USE_CHECKER']:
|
||||||
|
from DummyChecker import DummyChecker
|
||||||
|
|
||||||
class BaseSimpleCPU(BaseCPU):
|
class BaseSimpleCPU(BaseCPU):
|
||||||
type = 'BaseSimpleCPU'
|
type = 'BaseSimpleCPU'
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
if buildEnv['USE_CHECKER']:
|
||||||
|
checker = Param.BaseCPU(DummyChecker(), "checker")
|
||||||
|
checker.itb = BaseCPU.itb
|
||||||
|
checker.dtb = BaseCPU.dtb
|
||||||
|
|
|
@ -175,7 +175,7 @@ AtomicSimpleCPU::switchOut()
|
||||||
void
|
void
|
||||||
AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
{
|
{
|
||||||
BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
|
BaseCPU::takeOverFrom(oldCPU);
|
||||||
|
|
||||||
assert(!tickEvent.scheduled());
|
assert(!tickEvent.scheduled());
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
|
||||||
|
|
||||||
void
|
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);
|
DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AtomicSimpleCPU::suspendContext(int thread_num)
|
AtomicSimpleCPU::suspendContext(ThreadID thread_num)
|
||||||
{
|
{
|
||||||
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
|
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
virtual void activateContext(int thread_num, int delay);
|
virtual void activateContext(ThreadID thread_num, int delay);
|
||||||
virtual void suspendContext(int thread_num);
|
virtual void suspendContext(ThreadID thread_num);
|
||||||
|
|
||||||
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 ARM Limited
|
* Copyright (c) 2010-2011 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/simple/base.hh"
|
#include "cpu/simple/base.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
|
@ -79,6 +80,11 @@
|
||||||
#include "sim/stats.hh"
|
#include "sim/stats.hh"
|
||||||
#include "sim/system.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 std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
|
@ -95,6 +101,19 @@ BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
|
||||||
|
|
||||||
tc = thread->getTC();
|
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;
|
numInst = 0;
|
||||||
startNumInst = 0;
|
startNumInst = 0;
|
||||||
numLoad = 0;
|
numLoad = 0;
|
||||||
|
@ -114,7 +133,7 @@ BaseSimpleCPU::~BaseSimpleCPU()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseSimpleCPU::deallocateContext(int thread_num)
|
BaseSimpleCPU::deallocateContext(ThreadID thread_num)
|
||||||
{
|
{
|
||||||
// for now, these are equivalent
|
// for now, these are equivalent
|
||||||
suspendContext(thread_num);
|
suspendContext(thread_num);
|
||||||
|
@ -122,7 +141,7 @@ BaseSimpleCPU::deallocateContext(int thread_num)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseSimpleCPU::haltContext(int thread_num)
|
BaseSimpleCPU::haltContext(ThreadID thread_num)
|
||||||
{
|
{
|
||||||
// for now, these are equivalent
|
// for now, these are equivalent
|
||||||
suspendContext(thread_num);
|
suspendContext(thread_num);
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +48,7 @@
|
||||||
#include "arch/predecoder.hh"
|
#include "arch/predecoder.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/decode.hh"
|
#include "cpu/decode.hh"
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
|
@ -48,6 +61,10 @@
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
class Checkpoint;
|
class Checkpoint;
|
||||||
class MemObject;
|
class MemObject;
|
||||||
|
@ -66,7 +83,7 @@ namespace Trace {
|
||||||
class InstRecord;
|
class InstRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseSimpleCPUParams;
|
struct BaseSimpleCPUParams;
|
||||||
|
|
||||||
|
|
||||||
class BaseSimpleCPU : public BaseCPU
|
class BaseSimpleCPU : public BaseCPU
|
||||||
|
@ -111,6 +128,10 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
* objects to modify this thread's state.
|
* objects to modify this thread's state.
|
||||||
*/
|
*/
|
||||||
ThreadContext *tc;
|
ThreadContext *tc;
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
CheckerCPU *checker;
|
||||||
|
#endif
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
|
@ -157,8 +178,8 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
void postExecute();
|
void postExecute();
|
||||||
void advancePC(Fault fault);
|
void advancePC(Fault fault);
|
||||||
|
|
||||||
virtual void deallocateContext(int thread_num);
|
virtual void deallocateContext(ThreadID thread_num);
|
||||||
virtual void haltContext(int thread_num);
|
virtual void haltContext(ThreadID thread_num);
|
||||||
|
|
||||||
// statistics
|
// statistics
|
||||||
virtual void regStats();
|
virtual void regStats();
|
||||||
|
|
|
@ -176,7 +176,7 @@ TimingSimpleCPU::switchOut()
|
||||||
void
|
void
|
||||||
TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
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
|
// if any of this CPU's ThreadContexts are active, mark the CPU as
|
||||||
// running and schedule its tick event.
|
// running and schedule its tick event.
|
||||||
|
@ -197,7 +197,7 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
|
||||||
|
|
||||||
void
|
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);
|
DPRINTF(SimpleCPU, "ActivateContext %d (%d cycles)\n", thread_num, delay);
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ TimingSimpleCPU::activateContext(int thread_num, int delay)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimingSimpleCPU::suspendContext(int thread_num)
|
TimingSimpleCPU::suspendContext(ThreadID thread_num)
|
||||||
{
|
{
|
||||||
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
|
DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
|
||||||
|
|
||||||
|
|
|
@ -244,8 +244,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
virtual void activateContext(int thread_num, int delay);
|
virtual void activateContext(ThreadID thread_num, int delay);
|
||||||
virtual void suspendContext(int thread_num);
|
virtual void suspendContext(ThreadID thread_num);
|
||||||
|
|
||||||
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
|
|
|
@ -47,14 +47,13 @@
|
||||||
#include "cpu/quiesce_event.hh"
|
#include "cpu/quiesce_event.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "params/BaseCPU.hh"
|
|
||||||
#include "mem/fs_translating_port_proxy.hh"
|
#include "mem/fs_translating_port_proxy.hh"
|
||||||
#include "mem/se_translating_port_proxy.hh"
|
#include "mem/se_translating_port_proxy.hh"
|
||||||
|
#include "params/BaseCPU.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
#include "sim/process.hh"
|
#include "sim/process.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
#include "sim/sim_exit.hh"
|
#include "sim/sim_exit.hh"
|
||||||
#include "sim/process.hh"
|
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -62,8 +61,7 @@ using namespace std;
|
||||||
// constructor
|
// constructor
|
||||||
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
|
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
|
||||||
TheISA::TLB *_itb, TheISA::TLB *_dtb)
|
TheISA::TLB *_itb, TheISA::TLB *_dtb)
|
||||||
: ThreadState(_cpu, _thread_num, _process),
|
: ThreadState(_cpu, _thread_num, _process), itb(_itb), dtb(_dtb)
|
||||||
cpu(_cpu), itb(_itb), dtb(_dtb)
|
|
||||||
{
|
{
|
||||||
clearArchRegs();
|
clearArchRegs();
|
||||||
tc = new ProxyThreadContext<SimpleThread>(this);
|
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,
|
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||||
TheISA::TLB *_itb, TheISA::TLB *_dtb,
|
TheISA::TLB *_itb, TheISA::TLB *_dtb,
|
||||||
bool use_kernel_stats)
|
bool use_kernel_stats)
|
||||||
: ThreadState(_cpu, _thread_num, NULL),
|
: ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb)
|
||||||
cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
tc = new ProxyThreadContext<SimpleThread>(this);
|
tc = new ProxyThreadContext<SimpleThread>(this);
|
||||||
|
|
||||||
|
@ -81,7 +77,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||||
|
|
||||||
clearArchRegs();
|
clearArchRegs();
|
||||||
|
|
||||||
if (cpu->params()->profile) {
|
if (baseCpu->params()->profile) {
|
||||||
profile = new FunctionProfile(system->kernelSymtab);
|
profile = new FunctionProfile(system->kernelSymtab);
|
||||||
Callback *cb =
|
Callback *cb =
|
||||||
new MakeCallback<SimpleThread,
|
new MakeCallback<SimpleThread,
|
||||||
|
@ -183,7 +179,7 @@ SimpleThread::serialize(ostream &os)
|
||||||
//
|
//
|
||||||
// Now must serialize all the ISA dependent state
|
// 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 §ion)
|
||||||
//
|
//
|
||||||
// Now must unserialize all the ISA dependent state
|
// Now must unserialize all the ISA dependent state
|
||||||
//
|
//
|
||||||
isa.unserialize(cpu, cp, section);
|
isa.unserialize(baseCpu, cp, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SimpleThread::dumpFuncProfile()
|
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);
|
profile->dump(tc, *os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +222,7 @@ SimpleThread::activate(int delay)
|
||||||
_status = ThreadContext::Active;
|
_status = ThreadContext::Active;
|
||||||
|
|
||||||
// status() == Suspended
|
// status() == Suspended
|
||||||
cpu->activateContext(_threadId, delay);
|
baseCpu->activateContext(_threadId, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -237,7 +234,7 @@ SimpleThread::suspend()
|
||||||
lastActivate = curTick();
|
lastActivate = curTick();
|
||||||
lastSuspend = curTick();
|
lastSuspend = curTick();
|
||||||
_status = ThreadContext::Suspended;
|
_status = ThreadContext::Suspended;
|
||||||
cpu->suspendContext(_threadId);
|
baseCpu->suspendContext(_threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,7 +245,7 @@ SimpleThread::halt()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_status = ThreadContext::Halted;
|
_status = ThreadContext::Halted;
|
||||||
cpu->haltContext(_threadId);
|
baseCpu->haltContext(_threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2001-2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -39,6 +51,7 @@
|
||||||
#include "arch/types.hh"
|
#include "arch/types.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
#include "cpu/decode.hh"
|
#include "cpu/decode.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "cpu/thread_state.hh"
|
#include "cpu/thread_state.hh"
|
||||||
|
@ -106,12 +119,9 @@ class SimpleThread : public ThreadState
|
||||||
public:
|
public:
|
||||||
std::string name() const
|
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;
|
ProxyThreadContext<SimpleThread> *tc;
|
||||||
|
|
||||||
System *system;
|
System *system;
|
||||||
|
@ -182,12 +192,16 @@ class SimpleThread : public ThreadState
|
||||||
* ThreadContext interface functions.
|
* ThreadContext interface functions.
|
||||||
******************************************/
|
******************************************/
|
||||||
|
|
||||||
BaseCPU *getCpuPtr() { return cpu; }
|
BaseCPU *getCpuPtr() { return baseCpu; }
|
||||||
|
|
||||||
TheISA::TLB *getITBPtr() { return itb; }
|
TheISA::TLB *getITBPtr() { return itb; }
|
||||||
|
|
||||||
TheISA::TLB *getDTBPtr() { return dtb; }
|
TheISA::TLB *getDTBPtr() { return dtb; }
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
BaseCPU *getCheckerCpuPtr() { return NULL; }
|
||||||
|
#endif
|
||||||
|
|
||||||
Decoder *getDecoderPtr() { return &decoder; }
|
Decoder *getDecoderPtr() { return &decoder; }
|
||||||
|
|
||||||
System *getSystemPtr() { return system; }
|
System *getSystemPtr() { return system; }
|
||||||
|
@ -281,7 +295,10 @@ class SimpleThread : public ThreadState
|
||||||
{
|
{
|
||||||
int flatIndex = isa.flattenFloatIndex(reg_idx);
|
int flatIndex = isa.flattenFloatIndex(reg_idx);
|
||||||
assert(flatIndex < TheISA::NumFloatRegs);
|
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",
|
DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x, %#f.\n",
|
||||||
reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
|
reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
|
||||||
}
|
}
|
||||||
|
@ -298,6 +315,14 @@ class SimpleThread : public ThreadState
|
||||||
_pcState = val;
|
_pcState = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
void
|
||||||
|
pcStateNoRecord(const TheISA::PCState &val)
|
||||||
|
{
|
||||||
|
_pcState = val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Addr
|
Addr
|
||||||
instAddr()
|
instAddr()
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ThreadContext;
|
||||||
class DynInst;
|
class DynInst;
|
||||||
class Packet;
|
class Packet;
|
||||||
|
|
||||||
class O3CPUImpl;
|
struct O3CPUImpl;
|
||||||
template <class Impl> class BaseO3DynInst;
|
template <class Impl> class BaseO3DynInst;
|
||||||
typedef BaseO3DynInst<O3CPUImpl> O3DynInst;
|
typedef BaseO3DynInst<O3CPUImpl> O3DynInst;
|
||||||
template <class Impl> class OzoneDynInst;
|
template <class Impl> class OzoneDynInst;
|
||||||
|
|
|
@ -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
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -38,6 +50,7 @@
|
||||||
#include "arch/types.hh"
|
#include "arch/types.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "config/use_checker.hh"
|
||||||
|
|
||||||
// @todo: Figure out a more architecture independent way to obtain the ITB and
|
// @todo: Figure out a more architecture independent way to obtain the ITB and
|
||||||
// DTB pointers.
|
// DTB pointers.
|
||||||
|
@ -120,6 +133,10 @@ class ThreadContext
|
||||||
|
|
||||||
virtual TheISA::TLB *getDTBPtr() = 0;
|
virtual TheISA::TLB *getDTBPtr() = 0;
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
virtual BaseCPU *getCheckerCpuPtr() = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual Decoder *getDecoderPtr() = 0;
|
virtual Decoder *getDecoderPtr() = 0;
|
||||||
|
|
||||||
virtual System *getSystemPtr() = 0;
|
virtual System *getSystemPtr() = 0;
|
||||||
|
@ -198,6 +215,10 @@ class ThreadContext
|
||||||
|
|
||||||
virtual void pcState(const TheISA::PCState &val) = 0;
|
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 instAddr() = 0;
|
||||||
|
|
||||||
virtual Addr nextInstAddr() = 0;
|
virtual Addr nextInstAddr() = 0;
|
||||||
|
@ -287,6 +308,10 @@ class ProxyThreadContext : public ThreadContext
|
||||||
|
|
||||||
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
||||||
|
|
||||||
|
#if USE_CHECKER
|
||||||
|
BaseCPU *getCheckerCpuPtr() { return actualTC->getCheckerCpuPtr(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
|
Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
|
||||||
|
|
||||||
System *getSystemPtr() { return actualTC->getSystemPtr(); }
|
System *getSystemPtr() { return actualTC->getSystemPtr(); }
|
||||||
|
@ -367,6 +392,10 @@ class ProxyThreadContext : public ThreadContext
|
||||||
|
|
||||||
void pcState(const TheISA::PCState &val) { actualTC->pcState(val); }
|
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 instAddr() { return actualTC->instAddr(); }
|
||||||
Addr nextInstAddr() { return actualTC->nextInstAddr(); }
|
Addr nextInstAddr() { return actualTC->nextInstAddr(); }
|
||||||
MicroPC microPC() { return actualTC->microPC(); }
|
MicroPC microPC() { return actualTC->microPC(); }
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct ThreadState {
|
||||||
|
|
||||||
ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process);
|
ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process);
|
||||||
|
|
||||||
~ThreadState();
|
virtual ~ThreadState();
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
void serialize(std::ostream &os);
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
#include "params/TsunamiCChip.hh"
|
#include "params/TsunamiCChip.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
//Should this be AlphaISA?
|
//Should this be AlphaISA?
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,11 @@
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
#include "sim/system.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?
|
//Should this be AlphaISA?
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,10 @@
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "mem/packet_access.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;
|
using namespace AmbaDev;
|
||||||
|
|
||||||
// initialize clcd registers
|
// initialize clcd registers
|
||||||
|
@ -69,11 +73,12 @@ Pl111::Pl111(const Params *p)
|
||||||
|
|
||||||
pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
|
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(lcdPalette, 0, sizeof(lcdPalette));
|
||||||
memset(cursorImage, 0, sizeof(cursorImage));
|
memset(cursorImage, 0, sizeof(cursorImage));
|
||||||
memset(dmaBuffer, 0, sizeof(dmaBuffer));
|
memset(dmaBuffer, 0, buffer_size);
|
||||||
|
|
||||||
if (vncserver)
|
if (vncserver)
|
||||||
vncserver->setFramebufferAddr(dmaBuffer);
|
vncserver->setFramebufferAddr(dmaBuffer);
|
||||||
|
|
|
@ -53,8 +53,6 @@
|
||||||
#include "params/Pl111.hh"
|
#include "params/Pl111.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class Gic;
|
class Gic;
|
||||||
class VncServer;
|
class VncServer;
|
||||||
class Bitmap;
|
class Bitmap;
|
||||||
|
@ -304,7 +302,7 @@ class Pl111: public AmbaDmaDevice
|
||||||
EventWrapper<Pl111, &Pl111::fillFifo> fillFifoEvent;
|
EventWrapper<Pl111, &Pl111::fillFifo> fillFifoEvent;
|
||||||
|
|
||||||
/** DMA done event */
|
/** 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 */
|
/** Wrapper to create an event out of the interrupt */
|
||||||
EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
|
EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
using namespace CopyEngineReg;
|
using namespace CopyEngineReg;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
CopyEngine::CopyEngine(const Params *p)
|
CopyEngine::CopyEngine(const Params *p)
|
||||||
: PciDev(p)
|
: PciDev(p)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue