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