From 0f014e4340bb0991716cb0f0feafd48b53e865d7 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Tue, 6 Jun 2006 14:06:30 -0400 Subject: [PATCH] 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 --- src/cpu/checker/cpu.cc | 108 ++++++++++++++++++++++++------------ src/cpu/checker/cpu.hh | 16 +++++- src/cpu/o3/fetch_impl.hh | 5 ++ src/cpu/o3/lsq_unit_impl.hh | 4 ++ src/mem/request.hh | 2 + 5 files changed, 99 insertions(+), 36 deletions(-) diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index bb9ec0445..c94570d7d 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -64,8 +64,7 @@ CheckerCPU::init() CheckerCPU::CheckerCPU(Params *p) : BaseCPU(p), cpuXC(NULL), xcProxy(NULL) { - memReq = new Request(); -// memReq->data = new uint8_t[64]; + memReq = NULL; numInst = 0; startNumInst = 0; @@ -81,6 +80,8 @@ CheckerCPU::CheckerCPU(Params *p) dtb = p->dtb; systemPtr = NULL; memPtr = NULL; +#else + process = p->process; #endif } @@ -93,7 +94,7 @@ CheckerCPU::setMemory(MemObject *mem) { memPtr = mem; #if !FULL_SYSTEM - cpuXC = new CPUExecContext(this, /* thread_num */ 0, NULL, + cpuXC = new CPUExecContext(this, /* thread_num */ 0, process, /* asid */ 0, mem); cpuXC->setStatus(ExecContext::Suspended); @@ -132,6 +133,18 @@ CheckerCPU::setSystem(System *system) } #endif +void +CheckerCPU::setIcachePort(Port *icache_port) +{ + icachePort = icache_port; +} + +void +CheckerCPU::setDcachePort(Port *dcache_port) +{ + dcachePort = dcache_port; +} + void CheckerCPU::serialize(ostream &os) { @@ -170,25 +183,28 @@ template Fault CheckerCPU::read(Addr addr, T &data, unsigned flags) { -/* - memReq->reset(addr, sizeof(T), flags); + // need to fill in CPU & thread IDs here + memReq = new Request(); + + memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); // translate to physical address translateDataReadReq(memReq); - memReq->cmd = Read; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; + Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); - if (!(memReq->flags & UNCACHEABLE)) { + pkt->dataStatic(&data); + + if (!(memReq->getFlags() & UNCACHEABLE)) { // Access memory to see if we have the same data - cpuXC->read(memReq, data); + dcachePort->sendFunctional(pkt); } else { // Assume the data is correct if it's an uncached access memcpy(&data, &unverifiedResult.integer, sizeof(T)); } -*/ + + delete pkt; + return NoFault; } @@ -237,8 +253,10 @@ template Fault CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { -/* - memReq->reset(addr, sizeof(T), flags); + // need to fill in CPU & thread IDs here + memReq = new Request(); + + memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); // translate to physical address 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 // verify this data. if (unverifiedReq && - !(unverifiedReq->flags & UNCACHEABLE) && - (!(unverifiedReq->flags & LOCKED) || - ((unverifiedReq->flags & LOCKED) && - unverifiedReq->result == 1))) { -#if 0 - memReq->cmd = Read; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - cpuXC->read(memReq, inst_data); -#endif + !(unverifiedReq->getFlags() & UNCACHEABLE) && + (!(unverifiedReq->getFlags() & LOCKED) || + ((unverifiedReq->getFlags() & LOCKED) && + unverifiedReq->getScResult() == 1))) { 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) { 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 // doesn't check if the SC should succeed or fail, it just checks the // value. - if (res) - *res = unverifiedReq->result; - */ + if (res && unverifiedReq->scResultValid()) + *res = unverifiedReq->getScResult(); + return NoFault; } @@ -451,6 +471,7 @@ Checker::tick(DynInstPtr &completed_inst) inst->seqNum, inst->readPC()); unverifiedResult.integer = inst->readIntResult(); unverifiedReq = inst->req; + unverifiedMemData = inst->memData; numCycles++; Fault fault = NoFault; @@ -494,10 +515,13 @@ Checker::tick(DynInstPtr &completed_inst) #define IFETCH_FLAGS(pc) 0 #endif + uint64_t fetch_PC = cpuXC->readPC() & ~3; + // set up memory request for instruction fetch -// memReq->cmd = Read; -// memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), -// IFETCH_FLAGS(cpuXC->readPC())); + memReq = new Request(inst->threadNumber, fetch_PC, + sizeof(uint32_t), + IFETCH_FLAGS(cpuXC->readPC()), + fetch_PC, cpuXC->readCpuId(), inst->threadNumber); bool succeeded = translateInstReq(memReq); @@ -526,7 +550,14 @@ Checker::tick(DynInstPtr &completed_inst) } 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 numInst++; @@ -547,6 +578,10 @@ Checker::tick(DynInstPtr &completed_inst) 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. @@ -609,6 +644,11 @@ Checker::tick(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()) { @@ -679,7 +719,7 @@ Checker::validateExecution(DynInstPtr &inst) cpuXC->setMiscReg(idx, 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", curTick, inst->readIntResult(), result.integer); handleError(); diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 2f9689028..704580d80 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -108,6 +108,8 @@ class CheckerCPU : public BaseCPU CheckerCPU(Params *p); virtual ~CheckerCPU(); + Process *process; + void setMemory(MemObject *mem); MemObject *memPtr; @@ -117,6 +119,15 @@ class CheckerCPU : public BaseCPU System *systemPtr; #endif + + void setIcachePort(Port *icache_port); + + Port *icachePort; + + void setDcachePort(Port *dcache_port); + + Port *dcachePort; + public: // execution context CPUExecContext *cpuXC; @@ -141,8 +152,8 @@ class CheckerCPU : public BaseCPU // current instruction MachInst machInst; - // Refcounted pointer to the one memory request. - Request *memReq; + // Pointer to the one memory request. + RequestPtr memReq; StaticInstPtr curStaticInst; @@ -334,6 +345,7 @@ class CheckerCPU : public BaseCPU Result unverifiedResult; Request *unverifiedReq; + uint8_t *unverifiedMemData; bool changedPC; bool willChangePC; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 84f2c3b7e..3a41de721 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -30,6 +30,7 @@ #include "arch/isa_traits.hh" #include "arch/utility.hh" +#include "cpu/checker/cpu.hh" #include "cpu/exetrace.hh" #include "cpu/o3/fetch.hh" #include "mem/packet.hh" @@ -289,6 +290,10 @@ DefaultFetch::setCPU(FullCPU *cpu_ptr) icachePort->setPeer(mem_dport); mem_dport->setPeer(icachePort); + if (cpu->checker) { + cpu->checker->setIcachePort(icachePort); + } + // Fetch needs to start fetching instructions at the very beginning, // so it must start up in active state. switchToActive(); diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 5398426e2..2679eb52b 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -186,6 +186,10 @@ LSQUnit::setCPU(FullCPU *cpu_ptr) Port *mem_dport = mem->getPort(""); dcachePort->setPeer(mem_dport); mem_dport->setPeer(dcachePort); + + if (cpu->checker) { + cpu->checker->setDcachePort(dcachePort); + } } template diff --git a/src/mem/request.hh b/src/mem/request.hh index e8f4daacb..af1d6d8a8 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -208,6 +208,8 @@ class Request /** Accessor function for 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.*/ uint64_t getScResult() { assert(validScResult); return scResult; } /** Accessor function for store conditional return value.*/ -- 2.30.2