Fix checker to work in newmem in SE mode.
src/cpu/o3/fetch_impl.hh: Give the checker a pointer to the icachePort. src/cpu/o3/lsq_unit_impl.hh: Give the checker a pointer to the dcachePort. src/mem/request.hh: Allow checking for the scResult being valid prior to accessing it. --HG-- extra : convert_revision : ced4180588d242111ecba4a11586823badd6cf15
This commit is contained in:
parent
090496bf2d
commit
0f014e4340
5 changed files with 99 additions and 36 deletions
|
@ -64,8 +64,7 @@ CheckerCPU::init()
|
||||||
CheckerCPU::CheckerCPU(Params *p)
|
CheckerCPU::CheckerCPU(Params *p)
|
||||||
: BaseCPU(p), cpuXC(NULL), xcProxy(NULL)
|
: BaseCPU(p), cpuXC(NULL), xcProxy(NULL)
|
||||||
{
|
{
|
||||||
memReq = new Request();
|
memReq = NULL;
|
||||||
// memReq->data = new uint8_t[64];
|
|
||||||
|
|
||||||
numInst = 0;
|
numInst = 0;
|
||||||
startNumInst = 0;
|
startNumInst = 0;
|
||||||
|
@ -81,6 +80,8 @@ CheckerCPU::CheckerCPU(Params *p)
|
||||||
dtb = p->dtb;
|
dtb = p->dtb;
|
||||||
systemPtr = NULL;
|
systemPtr = NULL;
|
||||||
memPtr = NULL;
|
memPtr = NULL;
|
||||||
|
#else
|
||||||
|
process = p->process;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ CheckerCPU::setMemory(MemObject *mem)
|
||||||
{
|
{
|
||||||
memPtr = mem;
|
memPtr = mem;
|
||||||
#if !FULL_SYSTEM
|
#if !FULL_SYSTEM
|
||||||
cpuXC = new CPUExecContext(this, /* thread_num */ 0, NULL,
|
cpuXC = new CPUExecContext(this, /* thread_num */ 0, process,
|
||||||
/* asid */ 0, mem);
|
/* asid */ 0, mem);
|
||||||
|
|
||||||
cpuXC->setStatus(ExecContext::Suspended);
|
cpuXC->setStatus(ExecContext::Suspended);
|
||||||
|
@ -132,6 +133,18 @@ CheckerCPU::setSystem(System *system)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
CheckerCPU::setIcachePort(Port *icache_port)
|
||||||
|
{
|
||||||
|
icachePort = icache_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CheckerCPU::setDcachePort(Port *dcache_port)
|
||||||
|
{
|
||||||
|
dcachePort = dcache_port;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckerCPU::serialize(ostream &os)
|
CheckerCPU::serialize(ostream &os)
|
||||||
{
|
{
|
||||||
|
@ -170,25 +183,28 @@ template <class T>
|
||||||
Fault
|
Fault
|
||||||
CheckerCPU::read(Addr addr, T &data, unsigned flags)
|
CheckerCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
/*
|
// need to fill in CPU & thread IDs here
|
||||||
memReq->reset(addr, sizeof(T), flags);
|
memReq = new Request();
|
||||||
|
|
||||||
|
memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
translateDataReadReq(memReq);
|
translateDataReadReq(memReq);
|
||||||
|
|
||||||
memReq->cmd = Read;
|
Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
|
||||||
memReq->completionEvent = NULL;
|
|
||||||
memReq->time = curTick;
|
|
||||||
memReq->flags &= ~INST_READ;
|
|
||||||
|
|
||||||
if (!(memReq->flags & UNCACHEABLE)) {
|
pkt->dataStatic(&data);
|
||||||
|
|
||||||
|
if (!(memReq->getFlags() & UNCACHEABLE)) {
|
||||||
// Access memory to see if we have the same data
|
// Access memory to see if we have the same data
|
||||||
cpuXC->read(memReq, data);
|
dcachePort->sendFunctional(pkt);
|
||||||
} else {
|
} else {
|
||||||
// Assume the data is correct if it's an uncached access
|
// Assume the data is correct if it's an uncached access
|
||||||
memcpy(&data, &unverifiedResult.integer, sizeof(T));
|
memcpy(&data, &unverifiedResult.integer, sizeof(T));
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
delete pkt;
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,8 +253,10 @@ template <class T>
|
||||||
Fault
|
Fault
|
||||||
CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
/*
|
// need to fill in CPU & thread IDs here
|
||||||
memReq->reset(addr, sizeof(T), flags);
|
memReq = new Request();
|
||||||
|
|
||||||
|
memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
cpuXC->translateDataWriteReq(memReq);
|
cpuXC->translateDataWriteReq(memReq);
|
||||||
|
@ -253,19 +271,21 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
// This is because the LSQ would have to be snooped in the CPU to
|
// This is because the LSQ would have to be snooped in the CPU to
|
||||||
// verify this data.
|
// verify this data.
|
||||||
if (unverifiedReq &&
|
if (unverifiedReq &&
|
||||||
!(unverifiedReq->flags & UNCACHEABLE) &&
|
!(unverifiedReq->getFlags() & UNCACHEABLE) &&
|
||||||
(!(unverifiedReq->flags & LOCKED) ||
|
(!(unverifiedReq->getFlags() & LOCKED) ||
|
||||||
((unverifiedReq->flags & LOCKED) &&
|
((unverifiedReq->getFlags() & LOCKED) &&
|
||||||
unverifiedReq->result == 1))) {
|
unverifiedReq->getScResult() == 1))) {
|
||||||
#if 0
|
|
||||||
memReq->cmd = Read;
|
|
||||||
memReq->completionEvent = NULL;
|
|
||||||
memReq->time = curTick;
|
|
||||||
memReq->flags &= ~INST_READ;
|
|
||||||
cpuXC->read(memReq, inst_data);
|
|
||||||
#endif
|
|
||||||
T inst_data;
|
T inst_data;
|
||||||
memcpy(&inst_data, unverifiedReq->data, sizeof(T));
|
/*
|
||||||
|
// This code would work if the LSQ allowed for snooping.
|
||||||
|
Packet *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) {
|
if (data != inst_data) {
|
||||||
warn("%lli: Store value does not match value in memory! "
|
warn("%lli: Store value does not match value in memory! "
|
||||||
|
@ -278,9 +298,9 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
// Assume the result was the same as the one passed in. This checker
|
// 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
|
// doesn't check if the SC should succeed or fail, it just checks the
|
||||||
// value.
|
// value.
|
||||||
if (res)
|
if (res && unverifiedReq->scResultValid())
|
||||||
*res = unverifiedReq->result;
|
*res = unverifiedReq->getScResult();
|
||||||
*/
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +471,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
||||||
inst->seqNum, inst->readPC());
|
inst->seqNum, inst->readPC());
|
||||||
unverifiedResult.integer = inst->readIntResult();
|
unverifiedResult.integer = inst->readIntResult();
|
||||||
unverifiedReq = inst->req;
|
unverifiedReq = inst->req;
|
||||||
|
unverifiedMemData = inst->memData;
|
||||||
numCycles++;
|
numCycles++;
|
||||||
|
|
||||||
Fault fault = NoFault;
|
Fault fault = NoFault;
|
||||||
|
@ -494,10 +515,13 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
||||||
#define IFETCH_FLAGS(pc) 0
|
#define IFETCH_FLAGS(pc) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint64_t fetch_PC = cpuXC->readPC() & ~3;
|
||||||
|
|
||||||
// set up memory request for instruction fetch
|
// set up memory request for instruction fetch
|
||||||
// memReq->cmd = Read;
|
memReq = new Request(inst->threadNumber, fetch_PC,
|
||||||
// memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
|
sizeof(uint32_t),
|
||||||
// IFETCH_FLAGS(cpuXC->readPC()));
|
IFETCH_FLAGS(cpuXC->readPC()),
|
||||||
|
fetch_PC, cpuXC->readCpuId(), inst->threadNumber);
|
||||||
|
|
||||||
bool succeeded = translateInstReq(memReq);
|
bool succeeded = translateInstReq(memReq);
|
||||||
|
|
||||||
|
@ -526,7 +550,14 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
// cpuXC->read(memReq, machInst);
|
Packet *pkt = new Packet(memReq, Packet::ReadReq,
|
||||||
|
Packet::Broadcast);
|
||||||
|
|
||||||
|
pkt->dataStatic(&machInst);
|
||||||
|
|
||||||
|
icachePort->sendFunctional(pkt);
|
||||||
|
|
||||||
|
delete pkt;
|
||||||
|
|
||||||
// keep an instruction count
|
// keep an instruction count
|
||||||
numInst++;
|
numInst++;
|
||||||
|
@ -547,6 +578,10 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
||||||
fault = inst->getFault();
|
fault = inst->getFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discard fetch's memReq.
|
||||||
|
delete memReq;
|
||||||
|
memReq = NULL;
|
||||||
|
|
||||||
// Either the instruction was a fault and we should process the fault,
|
// Either the instruction was a fault and we should process the fault,
|
||||||
// or we should just go ahead execute the instruction. This assumes
|
// or we should just go ahead execute the instruction. This assumes
|
||||||
// that the instruction is properly marked as a fault.
|
// that the instruction is properly marked as a fault.
|
||||||
|
@ -609,6 +644,11 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
||||||
// that have been modified).
|
// that have been modified).
|
||||||
validateState();
|
validateState();
|
||||||
|
|
||||||
|
if (memReq) {
|
||||||
|
delete memReq;
|
||||||
|
memReq = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Continue verifying instructions if there's another completed
|
// Continue verifying instructions if there's another completed
|
||||||
// instruction waiting to be verified.
|
// instruction waiting to be verified.
|
||||||
if (instList.empty()) {
|
if (instList.empty()) {
|
||||||
|
@ -679,7 +719,7 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
|
||||||
cpuXC->setMiscReg(idx, inst->readIntResult());
|
cpuXC->setMiscReg(idx, inst->readIntResult());
|
||||||
}
|
}
|
||||||
} else if (result.integer != inst->readIntResult()) {
|
} else if (result.integer != inst->readIntResult()) {
|
||||||
warn("%lli: Instruction results do not match! (Results may not "
|
warn("%lli: Instruction results do not match! (Values may not "
|
||||||
"actually be integers) Inst: %#x, checker: %#x",
|
"actually be integers) Inst: %#x, checker: %#x",
|
||||||
curTick, inst->readIntResult(), result.integer);
|
curTick, inst->readIntResult(), result.integer);
|
||||||
handleError();
|
handleError();
|
||||||
|
|
|
@ -108,6 +108,8 @@ class CheckerCPU : public BaseCPU
|
||||||
CheckerCPU(Params *p);
|
CheckerCPU(Params *p);
|
||||||
virtual ~CheckerCPU();
|
virtual ~CheckerCPU();
|
||||||
|
|
||||||
|
Process *process;
|
||||||
|
|
||||||
void setMemory(MemObject *mem);
|
void setMemory(MemObject *mem);
|
||||||
|
|
||||||
MemObject *memPtr;
|
MemObject *memPtr;
|
||||||
|
@ -117,6 +119,15 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
System *systemPtr;
|
System *systemPtr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void setIcachePort(Port *icache_port);
|
||||||
|
|
||||||
|
Port *icachePort;
|
||||||
|
|
||||||
|
void setDcachePort(Port *dcache_port);
|
||||||
|
|
||||||
|
Port *dcachePort;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// execution context
|
// execution context
|
||||||
CPUExecContext *cpuXC;
|
CPUExecContext *cpuXC;
|
||||||
|
@ -141,8 +152,8 @@ class CheckerCPU : public BaseCPU
|
||||||
// current instruction
|
// current instruction
|
||||||
MachInst machInst;
|
MachInst machInst;
|
||||||
|
|
||||||
// Refcounted pointer to the one memory request.
|
// Pointer to the one memory request.
|
||||||
Request *memReq;
|
RequestPtr memReq;
|
||||||
|
|
||||||
StaticInstPtr curStaticInst;
|
StaticInstPtr curStaticInst;
|
||||||
|
|
||||||
|
@ -334,6 +345,7 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
Result unverifiedResult;
|
Result unverifiedResult;
|
||||||
Request *unverifiedReq;
|
Request *unverifiedReq;
|
||||||
|
uint8_t *unverifiedMemData;
|
||||||
|
|
||||||
bool changedPC;
|
bool changedPC;
|
||||||
bool willChangePC;
|
bool willChangePC;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
|
#include "cpu/checker/cpu.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/o3/fetch.hh"
|
#include "cpu/o3/fetch.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
|
@ -289,6 +290,10 @@ DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
|
||||||
icachePort->setPeer(mem_dport);
|
icachePort->setPeer(mem_dport);
|
||||||
mem_dport->setPeer(icachePort);
|
mem_dport->setPeer(icachePort);
|
||||||
|
|
||||||
|
if (cpu->checker) {
|
||||||
|
cpu->checker->setIcachePort(icachePort);
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch needs to start fetching instructions at the very beginning,
|
// Fetch needs to start fetching instructions at the very beginning,
|
||||||
// so it must start up in active state.
|
// so it must start up in active state.
|
||||||
switchToActive();
|
switchToActive();
|
||||||
|
|
|
@ -186,6 +186,10 @@ LSQUnit<Impl>::setCPU(FullCPU *cpu_ptr)
|
||||||
Port *mem_dport = mem->getPort("");
|
Port *mem_dport = mem->getPort("");
|
||||||
dcachePort->setPeer(mem_dport);
|
dcachePort->setPeer(mem_dport);
|
||||||
mem_dport->setPeer(dcachePort);
|
mem_dport->setPeer(dcachePort);
|
||||||
|
|
||||||
|
if (cpu->checker) {
|
||||||
|
cpu->checker->setDcachePort(dcachePort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
|
|
|
@ -208,6 +208,8 @@ class Request
|
||||||
/** Accessor function for asid.*/
|
/** Accessor function for asid.*/
|
||||||
int getAsid() { assert(validAsidVaddr); return asid; }
|
int getAsid() { assert(validAsidVaddr); return asid; }
|
||||||
|
|
||||||
|
/** Accessor function to check if sc result is valid. */
|
||||||
|
bool scResultValid() { return validScResult; }
|
||||||
/** Accessor function for store conditional return value.*/
|
/** Accessor function for store conditional return value.*/
|
||||||
uint64_t getScResult() { assert(validScResult); return scResult; }
|
uint64_t getScResult() { assert(validScResult); return scResult; }
|
||||||
/** Accessor function for store conditional return value.*/
|
/** Accessor function for store conditional return value.*/
|
||||||
|
|
Loading…
Reference in a new issue