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:
Kevin Lim 2006-06-06 14:06:30 -04:00
parent 090496bf2d
commit 0f014e4340
5 changed files with 99 additions and 36 deletions

View file

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

View file

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

View file

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

View file

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

View file

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