Merge with head, hopefully the last time for this batch.

This commit is contained in:
Gabe Black 2012-01-31 22:40:08 -08:00
commit ea8b347dc5
132 changed files with 1719 additions and 909 deletions

View file

@ -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.'

View file

@ -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']

View file

@ -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:

View file

@ -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;

View file

@ -49,7 +49,7 @@ class ThreadContext;
namespace AlphaISA {
class TlbEntry;
struct TlbEntry;
class TLB : public BaseTLB
{

View file

@ -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

View file

@ -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)

View file

@ -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:

View file

@ -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);

View file

@ -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 },

View file

@ -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)

View file

@ -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)) {

View file

@ -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:

View file

@ -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:

View file

@ -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,

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -48,11 +48,11 @@
class Port;
class X86ACPIRSDPParams;
struct X86ACPIRSDPParams;
class X86ACPISysDescTableParams;
class X86ACPIRSDTParams;
class X86ACPIXSDTParams;
struct X86ACPISysDescTableParams;
struct X86ACPIRSDTParams;
struct X86ACPIXSDTParams;
namespace X86ISA
{

View file

@ -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;

View file

@ -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
{

View file

@ -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
{

View file

@ -40,10 +40,6 @@
#if USE_FAST_ALLOC
#ifdef __GNUC__
#pragma implementation
#endif
void *FastAlloc::freeLists[Num_Buckets];
#if FAST_ALLOC_STATS

View file

@ -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

View file

@ -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

View file

@ -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);
};

View file

@ -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)
{

View file

@ -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)

View file

@ -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
View 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'

View file

@ -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:

View file

@ -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,6 +217,9 @@ BaseCPU::BaseCPU(Params *p)
schedule(event, p->function_trace_start);
}
}
// Check if CPU model has interrupts connected. The CheckerCPU
// cannot take interrupts directly for example.
if (interrupts)
interrupts->setCPU(this);
if (FullSystem) {
@ -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;

View file

@ -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).

View file

@ -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,32 +567,47 @@ 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
if (width == 32 || width == 64) {
setResult<double>(val);
} else {
panic("Unsupported width!");
}
}
@ -590,23 +615,20 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** 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);
}

View file

@ -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

View file

@ -1,4 +1,16 @@
/*
* Copyright (c) 2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@ -26,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Geoffrey Blake
*/
#include <list>
@ -38,10 +51,11 @@
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "params/CheckerCPU.hh"
#include "sim/tlb.hh"
using namespace std;
//The CheckerCPU does alpha only
using namespace AlphaISA;
using namespace TheISA;
void
CheckerCPU::init()
@ -52,6 +66,8 @@ CheckerCPU::CheckerCPU(Params *p)
: BaseCPU(p), thread(NULL), tc(NULL)
{
memReq = NULL;
curStaticInst = NULL;
curMacroStaticInst = NULL;
numInst = 0;
startNumInst = 0;
@ -66,13 +82,14 @@ CheckerCPU::CheckerCPU(Params *p)
itb = p->itb;
dtb = p->dtb;
systemPtr = NULL;
process = p->process;
thread = new SimpleThread(this, /* thread_num */ 0, process);
workload = p->workload;
// XXX: This is a hack to get this to work some
thread = new SimpleThread(this, /* thread_num */ 0, workload[0], itb, dtb);
tc = thread->getTC();
threadContexts.push_back(tc);
result.integer = 0;
updateOnError = true;
}
CheckerCPU::~CheckerCPU()
@ -107,216 +124,224 @@ CheckerCPU::setDcachePort(Port *dcache_port)
void
CheckerCPU::serialize(ostream &os)
{
/*
BaseCPU::serialize(os);
SERIALIZE_SCALAR(inst);
nameOut(os, csprintf("%s.xc", name()));
thread->serialize(os);
cacheCompletionEvent.serialize(os);
*/
}
void
CheckerCPU::unserialize(Checkpoint *cp, const string &section)
{
/*
BaseCPU::unserialize(cp, section);
UNSERIALIZE_SCALAR(inst);
thread->unserialize(cp, csprintf("%s.xc", section));
*/
}
template <class T>
Fault
CheckerCPU::read(Addr addr, T &data, unsigned flags)
CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags)
{
// need to fill in CPU & thread IDs here
memReq = new Request();
Fault fault = NoFault;
unsigned blockSize = dcachePort->peerBlockSize();
int fullSize = size;
Addr secondAddr = roundDown(addr + size - 1, blockSize);
bool checked_flags = false;
bool flags_match = true;
Addr pAddr = 0x0;
memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
if (secondAddr > addr)
size = secondAddr - addr;
// Need to account for multiple accesses like the Atomic and TimingSimple
while (1) {
memReq = new Request();
memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr());
// translate to physical address
dtb->translateAtomic(memReq, tc, false);
fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read);
PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
if (!checked_flags && fault == NoFault && unverifiedReq) {
flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
memReq->getPaddr(), memReq->getFlags());
pAddr = memReq->getPaddr();
checked_flags = true;
}
pkt->dataStatic(&data);
// 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);
if (!(memReq->isUncacheable())) {
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, &unverifiedResult.integer, sizeof(T));
memcpy(data, unverifiedMemData, size);
}
delete memReq;
memReq = NULL;
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);
if (fault != NoFault) {
if (memReq->isPrefetch()) {
fault = NoFault;
}
delete memReq;
memReq = NULL;
break;
}
template<>
Fault
CheckerCPU::read(Addr addr, float &data, unsigned flags)
{
return read(addr, *(uint32_t*)&data, flags);
if (memReq != NULL) {
delete memReq;
}
template<>
Fault
CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
//If we don't need to access a second cache line, stop now.
if (secondAddr <= addr)
{
return read(addr, (uint32_t&)data, flags);
break;
}
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();
// Setup for accessing next cache line
data += size;
unverifiedMemData += size;
size = addr + fullSize - secondAddr;
addr = secondAddr;
}
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);
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 fault;
}
Fault
CheckerCPU::writeMem(uint8_t *data, unsigned size,
Addr addr, unsigned flags, uint64_t *res)
{
Fault fault = NoFault;
bool checked_flags = false;
bool flags_match = true;
Addr pAddr = 0x0;
unsigned blockSize = dcachePort->peerBlockSize();
int fullSize = size;
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 (res && unverifiedReq->scResultValid())
if (unverifiedReq && res && unverifiedReq->extraDataValid())
*res = unverifiedReq->getExtraData();
return NoFault;
// 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;
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
Fault
CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
template
Fault
CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
template
Fault
CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
template
Fault
CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
#endif //DOXYGEN_SHOULD_SKIP_THIS
template<>
Fault
CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
{
return write(*(uint64_t*)&data, addr, flags, res);
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();
}
template<>
Fault
CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
{
return write(*(uint32_t*)&data, addr, flags, res);
return fault;
}
template<>
Fault
CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
{
return write((uint32_t)data, addr, flags, res);
}
Addr
CheckerCPU::dbg_vtophys(Addr addr)
{
return vtophys(tc, addr);
}
/**
* Checks if the flags set by the Checker and Checkee match.
*/
bool
CheckerCPU::checkFlags(Request *req)
CheckerCPU::checkFlags(Request *unverified_req, Addr vAddr,
Addr pAddr, int flags)
{
// Remove any dynamic flags that don't have to do with the request itself.
unsigned flags = unverifiedReq->getFlags();
unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
flags = flags & (mask);
if (flags == req->getFlags()) {
Addr unverifiedVAddr = unverified_req->getVaddr();
Addr unverifiedPAddr = unverified_req->getPaddr();
int unverifiedFlags = unverified_req->getFlags();
if (unverifiedVAddr != vAddr ||
unverifiedPAddr != pAddr ||
unverifiedFlags != flags) {
return false;
} else {
return true;
}
return true;
}
void
CheckerCPU::dumpAndExit()
{
warn("%lli: Checker PC:%#x, next PC:%#x",
curTick(), thread->readPC(), thread->readNextPC());
warn("%lli: Checker PC:%s",
curTick(), thread->pcState());
panic("Checker found an error!");
}

View file

@ -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;
@ -94,7 +103,7 @@ class CheckerCPU : public BaseCPU
CheckerCPU(Params *p);
virtual ~CheckerCPU();
Process *process;
std::vector<Process*> workload;
void setSystem(System *system);
@ -127,19 +136,25 @@ class CheckerCPU : public BaseCPU
union Result {
uint64_t integer;
// float fp;
double dbl;
void set(uint64_t i) { integer = i; }
void set(double d) { dbl = d; }
void get(uint64_t& i) { i = integer; }
void get(double& d) { d = dbl; }
};
Result result;
// ISAs like ARM can have multiple destination registers to check,
// keep them all in a std::queue
std::queue<Result> result;
// current instruction
MachInst machInst;
TheISA::MachInst machInst;
// Pointer to the one memory request.
RequestPtr memReq;
StaticInstPtr curStaticInst;
StaticInstPtr curMacroStaticInst;
// number of simulated instructions
Counter numInst;
@ -147,6 +162,9 @@ class CheckerCPU : public BaseCPU
std::queue<int> miscRegIdxs;
TheISA::TLB* getITBPtr() { return itb; }
TheISA::TLB* getDTBPtr() { return dtb; }
virtual Counter totalInstructions() const
{
return 0;
@ -159,12 +177,6 @@ class CheckerCPU : public BaseCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
// These functions are only used in CPU models that split
// effective address computation from the actual memory access.
void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
@ -198,17 +210,25 @@ class CheckerCPU : public BaseCPU
return thread->readFloatRegBits(reg_idx);
}
template <class T>
void setResult(T t)
{
Result instRes;
instRes.set(t);
result.push(instRes);
}
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
thread->setIntReg(si->destRegIdx(idx), val);
result.integer = val;
setResult<uint64_t>(val);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
thread->setFloatReg(reg_idx, val);
result.dbl = (double)val;
setResult<double>(val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
@ -216,12 +236,26 @@ class CheckerCPU : public BaseCPU
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
thread->setFloatRegBits(reg_idx, val);
result.integer = val;
setResult<uint64_t>(val);
}
uint64_t instAddr() { return thread->instAddr(); }
bool readPredicate() { return thread->readPredicate(); }
void setPredicate(bool val)
{
thread->setPredicate(val);
}
uint64_t nextInstAddr() { return thread->nextInstAddr(); }
TheISA::PCState pcState() { return thread->pcState(); }
void pcState(const TheISA::PCState &val)
{
DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
val, thread->pcState());
thread->pcState(val);
}
Addr instAddr() { return thread->instAddr(); }
Addr nextInstAddr() { return thread->nextInstAddr(); }
MicroPC microPC() { return thread->microPC(); }
//////////////////////////////////////////
MiscReg readMiscRegNoEffect(int misc_reg)
{
@ -235,7 +269,6 @@ class CheckerCPU : public BaseCPU
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
result.integer = val;
miscRegIdxs.push(misc_reg);
return thread->setMiscRegNoEffect(misc_reg, val);
}
@ -246,8 +279,25 @@ class CheckerCPU : public BaseCPU
return thread->setMiscReg(misc_reg, val);
}
void recordPCChange(uint64_t val) { changedPC = true; newPC = val; }
void recordNextPCChange(uint64_t val) { changedNextPC = true; }
MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
return thread->readMiscReg(reg_idx);
}
void setMiscRegOperand(
const StaticInst *si, int idx, const MiscReg &val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
return thread->setMiscReg(reg_idx, val);
}
/////////////////////////////////////////
void recordPCChange(const TheISA::PCState &val)
{
changedPC = true;
newPCState = val;
}
void demapPage(Addr vaddr, uint64_t asn)
{
@ -265,8 +315,17 @@ class CheckerCPU : public BaseCPU
this->dtb->demapPage(vaddr, asn);
}
Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
Fault writeMem(uint8_t *data, unsigned size,
Addr addr, unsigned flags, uint64_t *res);
void setStCondFailures(unsigned sc_failures)
{}
/////////////////////////////////////////////////////
Fault hwrei() { return thread->hwrei(); }
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
void wakeup() { }
// Assume that the normal CPU's call to syscall was successful.
// The checker's state would have already been updated by the syscall.
void syscall(uint64_t callnum) { }
@ -277,7 +336,8 @@ class CheckerCPU : public BaseCPU
dumpAndExit();
}
bool checkFlags(Request *req);
bool checkFlags(Request *unverified_req, Addr vAddr,
Addr pAddr, int flags);
void dumpAndExit();
@ -290,7 +350,7 @@ class CheckerCPU : public BaseCPU
bool changedPC;
bool willChangePC;
uint64_t newPC;
TheISA::PCState newPCState;
bool changedNextPC;
bool exitOnError;
bool updateOnError;
@ -305,24 +365,31 @@ class CheckerCPU : public BaseCPU
* template instantiations of the Checker must be placed at the bottom
* of checker/cpu.cc.
*/
template <class DynInstPtr>
template <class Impl>
class Checker : public CheckerCPU
{
private:
typedef typename Impl::DynInstPtr DynInstPtr;
public:
Checker(Params *p)
: CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
: CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL),
predecoder(NULL)
{ }
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
void advancePC(Fault fault);
void verify(DynInstPtr &inst);
void validateInst(DynInstPtr &inst);
void validateExecution(DynInstPtr &inst);
void validateState();
void copyResult(DynInstPtr &inst);
void copyResult(DynInstPtr &inst, uint64_t mismatch_val, int start_idx);
void handlePendingInt();
private:
void handleError(DynInstPtr &inst)
@ -339,6 +406,7 @@ class Checker : public CheckerCPU
bool updateThisCycle;
DynInstPtr unverifiedInst;
TheISA::Predecoder predecoder;
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;

View file

@ -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)
uint64_t fetch_PC = thread->readPC() & ~3;
while (!fetchDone) {
Addr fetch_PC = thread->instAddr();
fetch_PC = (fetch_PC & PCMask) + fetchOffset;
// If not in the middle of a macro instruction
if (!curMacroStaticInst) {
// set up memory request for instruction fetch
memReq = new Request(inst->threadNumber, fetch_PC,
sizeof(uint32_t),
IFETCH_FLAGS(thread->readPC()),
memReq = new Request(unverifiedInst->threadNumber, fetch_PC,
sizeof(MachInst),
0,
fetch_PC, thread->contextId(),
inst->threadNumber);
unverifiedInst->threadNumber);
memReq->setVirt(0, fetch_PC, sizeof(MachInst),
Request::INST_FETCH, thread->instAddr());
bool succeeded = itb->translateAtomic(memReq, thread);
if (!succeeded) {
if (inst->getFault() == NoFault) {
fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
if (fault != NoFault) {
if (unverifiedInst->getFault() == NoFault) {
// In this case the instruction was not a dummy
// instruction carrying an ITB fault. In the single
// threaded case the ITB should still be able to
// translate this instruction; in the SMT case it's
// possible that its ITB entry was kicked out.
warn("%lli: Instruction PC %#x was not found in the ITB!",
curTick(), thread->readPC());
handleError(inst);
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));
advancePC(NoFault);
break;
// 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 = inst->getFault();
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) {
PacketPtr pkt = new Packet(memReq, Packet::ReadReq,
Packet::Broadcast);
TheISA::PCState pcState = thread->pcState();
pkt->dataStatic(&machInst);
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;
icachePort->sendFunctional(pkt);
//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);
delete pkt;
//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) {
unverifiedFault = unverifiedInst->getFault();
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
validateInst(unverifiedInst);
}
// 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();
}
// Discard fetch's memReq.
delete memReq;
memReq = NULL;
// 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;
}
}
if (fault == NoFault && unverifiedFault == NoFault) {
thread->funcExeInst++;
if (!inst->isUnverifiable())
fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
validateExecution(unverifiedInst);
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()) {
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);
// 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, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
thread->setFloatRegBits(idx, inst->readIntResult());
} else {
thread->setMiscRegNoEffect(idx, inst->readIntResult());
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());

View file

@ -1,4 +1,16 @@
/*
* Copyright (c) 2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@ -36,6 +48,7 @@
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "debug/Checker.hh"
class EndQuiesceEvent;
namespace TheISA {
@ -77,18 +90,32 @@ class CheckerThreadContext : public ThreadContext
BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); }
void setCpuId(int id)
int cpuId() { return actualTC->cpuId(); }
int contextId() { return actualTC->contextId(); }
void setContextId(int id)
{
actualTC->setCpuId(id);
checkerTC->setCpuId(id);
actualTC->setContextId(id);
checkerTC->setContextId(id);
}
int cpuId() { return actualTC->cpuId(); }
/** Returns this thread's ID number. */
int threadId() { return actualTC->threadId(); }
void setThreadId(int id)
{
checkerTC->setThreadId(id);
actualTC->setThreadId(id);
}
TheISA::TLB *getITBPtr() { return actualTC->getITBPtr(); }
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
BaseCPU *getCheckerCpuPtr() { return checkerTC->getCpuPtr(); }
Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
System *getSystemPtr() { return actualTC->getSystemPtr(); }
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
@ -103,8 +130,21 @@ class CheckerThreadContext : public ThreadContext
FSTranslatingPortProxy* getVirtProxy()
{ return actualTC->getVirtProxy(); }
//XXX: How does this work now?
void initMemProxies(ThreadContext *tc)
{ actualTC->initMemProxies(tc); }
void connectMemPorts(ThreadContext *tc)
{
actualTC->connectMemPorts(tc);
}
SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); }
/** Executes a syscall in SE mode. */
void syscall(int64_t callnum)
{ return actualTC->syscall(callnum); }
Status status() const { return actualTC->status(); }
void setStatus(Status new_status)
@ -118,10 +158,10 @@ class CheckerThreadContext : public ThreadContext
void activate(int delay = 1) { actualTC->activate(delay); }
/// Set the status to Suspended.
void suspend() { actualTC->suspend(); }
void suspend(int delay) { actualTC->suspend(delay); }
/// Set the status to Halted.
void halt() { actualTC->halt(); }
void halt(int delay) { actualTC->halt(delay); }
void dumpFuncProfile() { actualTC->dumpFuncProfile(); }
@ -131,7 +171,11 @@ class CheckerThreadContext : public ThreadContext
checkerTC->copyState(oldContext);
}
void regStats(const std::string &name) { actualTC->regStats(name); }
void regStats(const std::string &name)
{
actualTC->regStats(name);
checkerTC->regStats(name);
}
void serialize(std::ostream &os) { actualTC->serialize(os); }
void unserialize(Checkpoint *cp, const std::string &section)
@ -145,8 +189,6 @@ class CheckerThreadContext : public ThreadContext
void profileClear() { return actualTC->profileClear(); }
void profileSample() { return actualTC->profileSample(); }
int threadId() { return actualTC->threadId(); }
// @todo: Do I need this?
void copyArchRegs(ThreadContext *tc)
{
@ -190,32 +232,36 @@ class CheckerThreadContext : public ThreadContext
checkerTC->setFloatRegBits(reg_idx, val);
}
uint64_t readPC() { return actualTC->readPC(); }
/** Reads this thread's PC state. */
TheISA::PCState pcState()
{ return actualTC->pcState(); }
void setPC(uint64_t val)
/** Sets this thread's PC state. */
void pcState(const TheISA::PCState &val)
{
actualTC->setPC(val);
checkerTC->setPC(val);
DPRINTF(Checker, "Changing PC to %s, old PC %s\n",
val, checkerTC->pcState());
checkerTC->pcState(val);
checkerCPU->recordPCChange(val);
return actualTC->pcState(val);
}
uint64_t readNextPC() { return actualTC->readNextPC(); }
void setNextPC(uint64_t val)
void pcStateNoRecord(const TheISA::PCState &val)
{
actualTC->setNextPC(val);
checkerTC->setNextPC(val);
checkerCPU->recordNextPCChange(val);
return actualTC->pcState(val);
}
uint64_t readNextNPC() { return actualTC->readNextNPC(); }
/** Reads this thread's PC. */
Addr instAddr()
{ return actualTC->instAddr(); }
void setNextNPC(uint64_t val)
{
actualTC->setNextNPC(val);
checkerTC->setNextNPC(val);
checkerCPU->recordNextPCChange(val);
}
/** Reads this thread's next PC. */
Addr nextInstAddr()
{ return actualTC->nextInstAddr(); }
/** Reads this thread's next PC. */
MicroPC microPC()
{ return actualTC->microPC(); }
MiscReg readMiscRegNoEffect(int misc_reg)
{ return actualTC->readMiscRegNoEffect(misc_reg); }
@ -225,22 +271,28 @@ class CheckerThreadContext : public ThreadContext
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
DPRINTF(Checker, "Setting misc reg with no effect: %d to both Checker"
" and O3..\n", misc_reg);
checkerTC->setMiscRegNoEffect(misc_reg, val);
actualTC->setMiscRegNoEffect(misc_reg, val);
}
void setMiscReg(int misc_reg, const MiscReg &val)
{
DPRINTF(Checker, "Setting misc reg with effect: %d to both Checker"
" and O3..\n", misc_reg);
checkerTC->setMiscReg(misc_reg, val);
actualTC->setMiscReg(misc_reg, val);
}
int flattenIntIndex(int reg) { return actualTC->flattenIntIndex(reg); }
int flattenFloatIndex(int reg) { return actualTC->flattenFloatIndex(reg); }
unsigned readStCondFailures()
{ return actualTC->readStCondFailures(); }
void setStCondFailures(unsigned sc_failures)
{
checkerTC->setStCondFailures(sc_failures);
actualTC->setStCondFailures(sc_failures);
}

View 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;
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -512,7 +512,7 @@ ResourceEvent::process()
}
const char *
ResourceEvent::description()
ResourceEvent::description() const
{
string desc = resource->name() + "-event:slot[" + to_string(slotIdx)
+ "]";

View file

@ -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();

View file

@ -485,7 +485,7 @@ ResourcePool::ResPoolEvent::process()
const char *
ResourcePool::ResPoolEvent::description()
ResourcePool::ResPoolEvent::description() const
{
return "Resource Pool event";
}

View file

@ -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);

View file

@ -49,9 +49,6 @@
#include "params/InOrderCPU.hh"
#include "sim/sim_object.hh"
class CacheRequest;
typedef CacheRequest* CacheReqPtr;
class CacheReqPacket;
typedef CacheReqPacket* CacheReqPktPtr;

View file

@ -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());
}

View file

@ -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

View file

@ -40,10 +40,14 @@ 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),
warnOnlyOnLoadError=True),
"checker")
checker.itb = Parent.itb
checker.dtb = Parent.dtb

View file

@ -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")

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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. */

View file

@ -36,7 +36,7 @@
#include "base/statistics.hh"
#include "cpu/timebuf.hh"
class DerivO3CPUParams;
struct DerivO3CPUParams;
/**
* DefaultDecode class handles both single threaded and SMT

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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>

View file

@ -252,7 +252,7 @@ FUPool::switchOut()
}
void
FUPool::takeOverFrom()
FUPool::takeOver()
{
for (int i = 0; i < numFU; i++) {
unitBusy[i] = false;

View file

@ -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__

View file

@ -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.

View file

@ -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();

View file

@ -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:

View file

@ -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,

View file

@ -51,7 +51,7 @@
#include "mem/port.hh"
#include "sim/sim_object.hh"
class DerivO3CPUParams;
struct DerivO3CPUParams;
template <class Impl>
class LSQ {

View file

@ -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

View file

@ -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;

View file

@ -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>;

View file

@ -49,7 +49,7 @@ struct SNHash {
}
};
class DerivO3CPUParams;
struct DerivO3CPUParams;
template <class Impl>
class InstructionQueue;

View file

@ -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

View file

@ -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.

View file

@ -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()); }

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -47,14 +47,13 @@
#include "cpu/quiesce_event.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "params/BaseCPU.hh"
#include "mem/fs_translating_port_proxy.hh"
#include "mem/se_translating_port_proxy.hh"
#include "params/BaseCPU.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/process.hh"
#include "sim/system.hh"
using namespace std;
@ -62,8 +61,7 @@ using namespace std;
// constructor
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
TheISA::TLB *_itb, TheISA::TLB *_dtb)
: ThreadState(_cpu, _thread_num, _process),
cpu(_cpu), itb(_itb), dtb(_dtb)
: ThreadState(_cpu, _thread_num, _process), itb(_itb), dtb(_dtb)
{
clearArchRegs();
tc = new ProxyThreadContext<SimpleThread>(this);
@ -71,9 +69,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
TheISA::TLB *_itb, TheISA::TLB *_dtb,
bool use_kernel_stats)
: ThreadState(_cpu, _thread_num, NULL),
cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb)
: ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb)
{
tc = new ProxyThreadContext<SimpleThread>(this);
@ -81,7 +77,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
clearArchRegs();
if (cpu->params()->profile) {
if (baseCpu->params()->profile) {
profile = new FunctionProfile(system->kernelSymtab);
Callback *cb =
new MakeCallback<SimpleThread,
@ -183,7 +179,7 @@ SimpleThread::serialize(ostream &os)
//
// Now must serialize all the ISA dependent state
//
isa.serialize(cpu, os);
isa.serialize(baseCpu, os);
}
@ -199,13 +195,14 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
//
// Now must unserialize all the ISA dependent state
//
isa.unserialize(cpu, cp, section);
isa.unserialize(baseCpu, cp, section);
}
void
SimpleThread::dumpFuncProfile()
{
std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
std::ostream *os = simout.create(csprintf("profile.%s.dat",
baseCpu->name()));
profile->dump(tc, *os);
}
@ -225,7 +222,7 @@ SimpleThread::activate(int delay)
_status = ThreadContext::Active;
// status() == Suspended
cpu->activateContext(_threadId, delay);
baseCpu->activateContext(_threadId, delay);
}
void
@ -237,7 +234,7 @@ SimpleThread::suspend()
lastActivate = curTick();
lastSuspend = curTick();
_status = ThreadContext::Suspended;
cpu->suspendContext(_threadId);
baseCpu->suspendContext(_threadId);
}
@ -248,7 +245,7 @@ SimpleThread::halt()
return;
_status = ThreadContext::Halted;
cpu->haltContext(_threadId);
baseCpu->haltContext(_threadId);
}

View file

@ -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,6 +295,9 @@ class SimpleThread : public ThreadState
{
int flatIndex = isa.flattenFloatIndex(reg_idx);
assert(flatIndex < TheISA::NumFloatRegs);
// 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()
{

View file

@ -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;

View file

@ -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(); }

View file

@ -64,7 +64,7 @@ struct ThreadState {
ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process);
~ThreadState();
virtual ~ThreadState();
void serialize(std::ostream &os);

View file

@ -53,7 +53,6 @@
#include "params/TsunamiCChip.hh"
#include "sim/system.hh"
using namespace std;
//Should this be AlphaISA?
using namespace TheISA;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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