Updates to bring MemTest closer to working with newmem. Ron still needs to do the initial setup and configuration for it to work properly.

src/SConscript:
    Include MemTest for now.  It's not complete but it compiles so it shouldn't mess anything else up.

--HG--
extra : convert_revision : 15a610c855b677fdced817850c92e4c911cf6d1c
This commit is contained in:
Kevin Lim 2006-10-07 13:37:22 -04:00
parent f2acc3a4a3
commit fe762278e7
3 changed files with 263 additions and 136 deletions

View file

@ -285,6 +285,7 @@ turbolaser_sources = Split('''
# Syscall emulation (non-full-system) sources # Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split(''' syscall_emulation_sources = Split('''
cpu/memtest/memtest.cc
mem/translating_port.cc mem/translating_port.cc
mem/page_table.cc mem/page_table.cc
sim/process.cc sim/process.cc

View file

@ -40,7 +40,8 @@
#include "base/statistics.hh" #include "base/statistics.hh"
#include "cpu/simple_thread.hh" #include "cpu/simple_thread.hh"
#include "cpu/memtest/memtest.hh" #include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh" //#include "mem/cache/base_cache.hh"
#include "mem/physical.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/sim_events.hh" #include "sim/sim_events.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
@ -50,27 +51,64 @@ using namespace TheISA;
int TESTER_ALLOCATOR=0; int TESTER_ALLOCATOR=0;
bool
MemTest::CpuPort::recvTiming(Packet *pkt)
{
memtest->completeRequest(pkt);
return true;
}
Tick
MemTest::CpuPort::recvAtomic(Packet *pkt)
{
panic("MemTest doesn't expect recvAtomic callback!");
return curTick;
}
void
MemTest::CpuPort::recvFunctional(Packet *pkt)
{
memtest->completeRequest(pkt);
}
void
MemTest::CpuPort::recvStatusChange(Status status)
{
if (status == RangeChange)
return;
panic("MemTest doesn't expect recvStatusChange callback!");
}
void
MemTest::CpuPort::recvRetry()
{
memtest->doRetry();
}
MemTest::MemTest(const string &name, MemTest::MemTest(const string &name,
MemInterface *_cache_interface, // MemInterface *_cache_interface,
FunctionalMemory *main_mem, PhysicalMemory *main_mem,
FunctionalMemory *check_mem, PhysicalMemory *check_mem,
unsigned _memorySize, unsigned _memorySize,
unsigned _percentReads, unsigned _percentReads,
unsigned _percentCopies, // unsigned _percentCopies,
unsigned _percentUncacheable, unsigned _percentUncacheable,
unsigned _progressInterval, unsigned _progressInterval,
unsigned _percentSourceUnaligned, unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned, unsigned _percentDestUnaligned,
Addr _traceAddr, Addr _traceAddr,
Counter _max_loads) Counter _max_loads)
: SimObject(name), : MemObject(name),
tickEvent(this), tickEvent(this),
cacheInterface(_cache_interface), cachePort("dcache", this),
retryPkt(NULL),
mainMem(main_mem), mainMem(main_mem),
checkMem(check_mem), checkMem(check_mem),
size(_memorySize), size(_memorySize),
percentReads(_percentReads), percentReads(_percentReads),
percentCopies(_percentCopies), // percentCopies(_percentCopies),
percentUncacheable(_percentUncacheable), percentUncacheable(_percentUncacheable),
progressInterval(_progressInterval), progressInterval(_progressInterval),
nextProgressMessage(_progressInterval), nextProgressMessage(_progressInterval),
@ -81,11 +119,43 @@ MemTest::MemTest(const string &name,
vector<string> cmd; vector<string> cmd;
cmd.push_back("/bin/ls"); cmd.push_back("/bin/ls");
vector<string> null_vec; vector<string> null_vec;
thread = new SimpleThread(NULL, 0, mainMem, 0); thread = new SimpleThread(NULL, 0, NULL, 0, mainMem);
curTick = 0;
blockSize = cacheInterface->getBlockSize(); // Needs to be masked off once we know the block size.
traceBlockAddr = _traceAddr;
baseAddr1 = 0x100000;
baseAddr2 = 0x400000;
uncacheAddr = 0x800000;
// set up counters
noResponseCycles = 0;
numReads = 0;
tickEvent.schedule(0);
id = TESTER_ALLOCATOR++;
}
Port *
MemTest::getPort(const std::string &if_name, int idx)
{
// ***** NOTE TO RON: I'm not sure what it should do if these get ports
// are called on it.
if (if_name == "dcache_port")
return &cachePort;
else if (if_name == "icache_port")
return &cachePort;
else
panic("No Such Port\n");
}
void
MemTest::init()
{
// By the time init() is called, the ports should be hooked up.
blockSize = cachePort.peerBlockSize();
blockAddrMask = blockSize - 1; blockAddrMask = blockSize - 1;
traceBlockAddr = blockAddr(_traceAddr); traceBlockAddr = blockAddr(traceBlockAddr);
//setup data storage with interesting values //setup data storage with interesting values
uint8_t *data1 = new uint8_t[size]; uint8_t *data1 = new uint8_t[size];
@ -94,30 +164,22 @@ MemTest::MemTest(const string &name,
memset(data1, 1, size); memset(data1, 1, size);
memset(data2, 2, size); memset(data2, 2, size);
memset(data3, 3, size); memset(data3, 3, size);
curTick = 0;
baseAddr1 = 0x100000;
baseAddr2 = 0x400000;
uncacheAddr = 0x800000;
// set up intial memory contents here // set up intial memory contents here
// ***** NOTE FOR RON: I'm not sure how to setup initial memory
// contents. - Kevin
/*
mainMem->prot_write(baseAddr1, data1, size); mainMem->prot_write(baseAddr1, data1, size);
checkMem->prot_write(baseAddr1, data1, size); checkMem->prot_write(baseAddr1, data1, size);
mainMem->prot_write(baseAddr2, data2, size); mainMem->prot_write(baseAddr2, data2, size);
checkMem->prot_write(baseAddr2, data2, size); checkMem->prot_write(baseAddr2, data2, size);
mainMem->prot_write(uncacheAddr, data3, size); mainMem->prot_write(uncacheAddr, data3, size);
checkMem->prot_write(uncacheAddr, data3, size); checkMem->prot_write(uncacheAddr, data3, size);
*/
delete [] data1; delete [] data1;
delete [] data2; delete [] data2;
delete [] data3; delete [] data3;
// set up counters
noResponseCycles = 0;
numReads = 0;
tickEvent.schedule(0);
id = TESTER_ALLOCATOR++;
} }
static void static void
@ -132,23 +194,31 @@ printData(ostream &os, uint8_t *data, int nbytes)
} }
void void
MemTest::completeRequest(MemReqPtr &req, uint8_t *data) MemTest::completeRequest(Packet *pkt)
{ {
MemTestSenderState *state =
dynamic_cast<MemTestSenderState *>(pkt->senderState);
uint8_t *data = state->data;
uint8_t *pkt_data = pkt->getPtr<uint8_t>();
Request *req = pkt->req;
//Remove the address from the list of outstanding //Remove the address from the list of outstanding
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr); std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->getPaddr());
assert(removeAddr != outstandingAddrs.end()); assert(removeAddr != outstandingAddrs.end());
outstandingAddrs.erase(removeAddr); outstandingAddrs.erase(removeAddr);
switch (req->cmd) { switch (pkt->cmd) {
case Read: case Packet::ReadReq:
if (memcmp(req->data, data, req->size) != 0) {
cerr << name() << ": on read of 0x" << hex << req->paddr if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
<< " (0x" << hex << blockAddr(req->paddr) << ")" cerr << name() << ": on read of 0x" << hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< "@ cycle " << dec << curTick << "@ cycle " << dec << curTick
<< ", cache returns 0x"; << ", cache returns 0x";
printData(cerr, req->data, req->size); printData(cerr, pkt_data, pkt->getSize());
cerr << ", expected 0x"; cerr << ", expected 0x";
printData(cerr, data, req->size); printData(cerr, data, pkt->getSize());
cerr << endl; cerr << endl;
fatal(""); fatal("");
} }
@ -163,13 +233,13 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
} }
if (numReads >= maxLoads) if (numReads >= maxLoads)
SimExit(curTick, "Maximum number of loads reached!"); exitSimLoop("Maximum number of loads reached!");
break; break;
case Write: case Packet::WriteReq:
numWritesStat++; numWritesStat++;
break; break;
/*
case Copy: case Copy:
//Also remove dest from outstanding list //Also remove dest from outstanding list
removeAddr = outstandingAddrs.find(req->dest); removeAddr = outstandingAddrs.find(req->dest);
@ -177,36 +247,37 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
outstandingAddrs.erase(removeAddr); outstandingAddrs.erase(removeAddr);
numCopiesStat++; numCopiesStat++;
break; break;
*/
default: default:
panic("invalid command"); panic("invalid command");
} }
if (blockAddr(req->paddr) == traceBlockAddr) { if (blockAddr(req->getPaddr()) == traceBlockAddr) {
cerr << name() << ": completed " cerr << name() << ": completed "
<< (req->cmd.isWrite() ? "write" : "read") << (pkt->isWrite() ? "write" : "read")
<< " access of " << " access of "
<< dec << req->size << " bytes at address 0x" << dec << pkt->getSize() << " bytes at address 0x"
<< hex << req->paddr << hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->paddr) << ")" << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< ", value = 0x"; << ", value = 0x";
printData(cerr, req->data, req->size); printData(cerr, pkt_data, pkt->getSize());
cerr << " @ cycle " << dec << curTick; cerr << " @ cycle " << dec << curTick;
cerr << endl; cerr << endl;
} }
noResponseCycles = 0; noResponseCycles = 0;
delete state;
delete [] data; delete [] data;
delete pkt->req;
delete pkt;
} }
void void
MemTest::regStats() MemTest::regStats()
{ {
using namespace Stats; using namespace Stats;
numReadsStat numReadsStat
.name(name() + ".num_reads") .name(name() + ".num_reads")
.desc("number of read accesses completed") .desc("number of read accesses completed")
@ -234,7 +305,7 @@ MemTest::tick()
fatal(""); fatal("");
} }
if (cacheInterface->isBlocked()) { if (accessRetry) {
return; return;
} }
@ -248,6 +319,9 @@ MemTest::tick()
//If we aren't doing copies, use id as offset, and do a false sharing //If we aren't doing copies, use id as offset, and do a false sharing
//mem tester //mem tester
// ***** NOTE FOR RON: We're not doing copies, but I'm not sure if this
// code should be used.
/*
if (percentCopies == 0) { if (percentCopies == 0) {
//We can eliminate the lower bits of the offset, and then use the id //We can eliminate the lower bits of the offset, and then use the id
//to offset within the blks //to offset within the blks
@ -255,23 +329,25 @@ MemTest::tick()
offset += id; offset += id;
access_size = 0; access_size = 0;
} }
*/
MemReqPtr req = new MemReq(); Request *req = new Request();
uint32_t flags = req->getFlags();
Addr paddr;
if (cacheable < percentUncacheable) { if (cacheable < percentUncacheable) {
req->flags |= UNCACHEABLE; flags |= UNCACHEABLE;
req->paddr = uncacheAddr + offset; paddr = uncacheAddr + offset;
} else { } else {
req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset; paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
} }
// bool probe = (random() % 2 == 1) && !req->isUncacheable(); // bool probe = (random() % 2 == 1) && !req->isUncacheable();
bool probe = false; bool probe = false;
req->size = 1 << access_size; paddr &= ~((1 << access_size) - 1);
req->data = new uint8_t[req->size]; req->setPhys(paddr, 1 << access_size, flags);
req->paddr &= ~(req->size - 1);
req->time = curTick; uint8_t *result = new uint8_t[8];
req->xc = thread->getProxy();
if (cmd < percentReads) { if (cmd < percentReads) {
// read // read
@ -279,60 +355,84 @@ MemTest::tick()
//For now we only allow one outstanding request per addreess per tester //For now we only allow one outstanding request per addreess per tester
//This means we assume CPU does write forwarding to reads that alias something //This means we assume CPU does write forwarding to reads that alias something
//in the cpu store buffer. //in the cpu store buffer.
if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return; if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
else outstandingAddrs.insert(req->paddr); else outstandingAddrs.insert(paddr);
req->cmd = Read; // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
uint8_t *result = new uint8_t[8]; // checkMem->access(Read, req->getPaddr(), result, req->size);
checkMem->access(Read, req->paddr, result, req->size); if (blockAddr(paddr) == traceBlockAddr) {
if (blockAddr(req->paddr) == traceBlockAddr) {
cerr << name() cerr << name()
<< ": initiating read " << ": initiating read "
<< ((probe) ? "probe of " : "access of ") << ((probe) ? "probe of " : "access of ")
<< dec << req->size << " bytes from addr 0x" << dec << req->getSize() << " bytes from addr 0x"
<< hex << req->paddr << hex << paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")" << " (0x" << hex << blockAddr(paddr) << ")"
<< " at cycle " << " at cycle "
<< dec << curTick << endl; << dec << curTick << endl;
} }
Packet *pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
pkt->dataDynamicArray(new uint8_t[req->getSize()]);
MemTestSenderState *state = new MemTestSenderState(result);
pkt->senderState = state;
if (probe) { if (probe) {
cacheInterface->probeAndUpdate(req); // ***** NOTE FOR RON: Send functional access? It used to
completeRequest(req, result); // be a probeAndUpdate access. - Kevin
cachePort.sendFunctional(pkt);
// completeRequest(pkt, result);
} else { } else {
req->completionEvent = new MemCompleteEvent(req, result, this); // req->completionEvent = new MemCompleteEvent(req, result, this);
cacheInterface->access(req); if (!cachePort.sendTiming(pkt)) {
accessRetry = true;
retryPkt = pkt;
} }
} else if (cmd < (100 - percentCopies)){ }
} else {
// write // write
//For now we only allow one outstanding request per addreess per tester //For now we only allow one outstanding request per addreess per tester
//This means we assume CPU does write forwarding to reads that alias something //This means we assume CPU does write forwarding to reads that alias something
//in the cpu store buffer. //in the cpu store buffer.
if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return; if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
else outstandingAddrs.insert(req->paddr); else outstandingAddrs.insert(paddr);
req->cmd = Write; // ***** NOTE FOR RON: Not sure how to access memory.
memcpy(req->data, &data, req->size); // checkMem->access(Write, req->paddr, req->data, req->size);
checkMem->access(Write, req->paddr, req->data, req->size); /*
if (blockAddr(req->paddr) == traceBlockAddr) { if (blockAddr(req->getPaddr()) == traceBlockAddr) {
cerr << name() << ": initiating write " cerr << name() << ": initiating write "
<< ((probe)?"probe of ":"access of ") << ((probe)?"probe of ":"access of ")
<< dec << req->size << " bytes (value = 0x"; << dec << req->getSize() << " bytes (value = 0x";
printData(cerr, req->data, req->size); printData(cerr, data_pkt->getPtr(), req->getSize());
cerr << ") to addr 0x" cerr << ") to addr 0x"
<< hex << req->paddr << hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->paddr) << ")" << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< " at cycle " << " at cycle "
<< dec << curTick << endl; << dec << curTick << endl;
} }
*/
Packet *pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
uint8_t *pkt_data = new uint8_t[req->getSize()];
pkt->dataDynamicArray(pkt_data);
memcpy(pkt_data, &data, req->getSize());
MemTestSenderState *state = new MemTestSenderState(result);
pkt->senderState = state;
if (probe) { if (probe) {
cacheInterface->probeAndUpdate(req); // ***** NOTE FOR RON: Send functional access? It used to
completeRequest(req, NULL); // be a probe access. - Kevin
cachePort.sendFunctional(pkt);
// completeRequest(req, NULL);
} else { } else {
req->completionEvent = new MemCompleteEvent(req, NULL, this); // req->completionEvent = new MemCompleteEvent(req, NULL, this);
cacheInterface->access(req); if (!cachePort.sendTiming(pkt)) {
accessRetry = true;
retryPkt = pkt;
} }
} else { }
}
/* else {
// copy // copy
unsigned source_align = random() % 100; unsigned source_align = random() % 100;
unsigned dest_align = random() % 100; unsigned dest_align = random() % 100;
@ -369,38 +469,32 @@ MemTest::tick()
<< " (0x" << hex << blockAddr(dest) << ")" << " (0x" << hex << blockAddr(dest) << ")"
<< " at cycle " << " at cycle "
<< dec << curTick << endl; << dec << curTick << endl;
} }*
cacheInterface->access(req); cacheInterface->access(req);
uint8_t result[blockSize]; uint8_t result[blockSize];
checkMem->access(Read, source, &result, blockSize); checkMem->access(Read, source, &result, blockSize);
checkMem->access(Write, dest, &result, blockSize); checkMem->access(Write, dest, &result, blockSize);
} }
*/
} }
void void
MemCompleteEvent::process() MemTest::doRetry()
{ {
tester->completeRequest(req, data); if (cachePort.sendTiming(retryPkt)) {
delete this; accessRetry = false;
retryPkt = NULL;
}
} }
const char *
MemCompleteEvent::description()
{
return "memory access completion";
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest) BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
SimObjectParam<BaseCache *> cache; // SimObjectParam<BaseCache *> cache;
SimObjectParam<FunctionalMemory *> main_mem; SimObjectParam<PhysicalMemory *> main_mem;
SimObjectParam<FunctionalMemory *> check_mem; SimObjectParam<PhysicalMemory *> check_mem;
Param<unsigned> memory_size; Param<unsigned> memory_size;
Param<unsigned> percent_reads; Param<unsigned> percent_reads;
Param<unsigned> percent_copies; // Param<unsigned> percent_copies;
Param<unsigned> percent_uncacheable; Param<unsigned> percent_uncacheable;
Param<unsigned> progress_interval; Param<unsigned> progress_interval;
Param<unsigned> percent_source_unaligned; Param<unsigned> percent_source_unaligned;
@ -413,12 +507,12 @@ END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest) BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
INIT_PARAM(cache, "L1 cache"), // INIT_PARAM(cache, "L1 cache"),
INIT_PARAM(main_mem, "hierarchical memory"), INIT_PARAM(main_mem, "hierarchical memory"),
INIT_PARAM(check_mem, "check memory"), INIT_PARAM(check_mem, "check memory"),
INIT_PARAM(memory_size, "memory size"), INIT_PARAM(memory_size, "memory size"),
INIT_PARAM(percent_reads, "target read percentage"), INIT_PARAM(percent_reads, "target read percentage"),
INIT_PARAM(percent_copies, "target copy percentage"), // INIT_PARAM(percent_copies, "target copy percentage"),
INIT_PARAM(percent_uncacheable, "target uncacheable percentage"), INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
INIT_PARAM(progress_interval, "progress report interval (in accesses)"), INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
INIT_PARAM(percent_source_unaligned, INIT_PARAM(percent_source_unaligned,
@ -433,8 +527,8 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest)
CREATE_SIM_OBJECT(MemTest) CREATE_SIM_OBJECT(MemTest)
{ {
return new MemTest(getInstanceName(), cache->getInterface(), main_mem, return new MemTest(getInstanceName(), /*cache->getInterface(),*/ main_mem,
check_mem, memory_size, percent_reads, percent_copies, check_mem, memory_size, percent_reads, /*percent_copies,*/
percent_uncacheable, progress_interval, percent_uncacheable, progress_interval,
percent_source_unaligned, percent_dest_unaligned, percent_source_unaligned, percent_dest_unaligned,
trace_addr, max_loads); trace_addr, max_loads);

View file

@ -35,25 +35,26 @@
#include <set> #include <set>
#include "base/statistics.hh" #include "base/statistics.hh"
#include "mem/functional/functional.hh" //#include "mem/functional/functional.hh"
#include "mem/mem_interface.hh" //#include "mem/mem_interface.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "sim/sim_exit.hh" #include "sim/sim_exit.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
class PhysicalMemory;
class ThreadContext; class ThreadContext;
class MemTest : public SimObject class MemTest : public MemObject
{ {
public: public:
MemTest(const std::string &name, MemTest(const std::string &name,
MemInterface *_cache_interface, // MemInterface *_cache_interface,
FunctionalMemory *main_mem, PhysicalMemory *main_mem,
FunctionalMemory *check_mem, PhysicalMemory *check_mem,
unsigned _memorySize, unsigned _memorySize,
unsigned _percentReads, unsigned _percentReads,
unsigned _percentCopies, // unsigned _percentCopies,
unsigned _percentUncacheable, unsigned _percentUncacheable,
unsigned _progressInterval, unsigned _progressInterval,
unsigned _percentSourceUnaligned, unsigned _percentSourceUnaligned,
@ -61,6 +62,8 @@ class MemTest : public SimObject
Addr _traceAddr, Addr _traceAddr,
Counter _max_loads); Counter _max_loads);
virtual void init();
// register statistics // register statistics
virtual void regStats(); virtual void regStats();
@ -69,6 +72,8 @@ class MemTest : public SimObject
// main simulation loop (one cycle) // main simulation loop (one cycle)
void tick(); void tick();
virtual Port *getPort(const std::string &if_name, int idx = -1);
protected: protected:
class TickEvent : public Event class TickEvent : public Event
{ {
@ -82,16 +87,61 @@ class MemTest : public SimObject
}; };
TickEvent tickEvent; TickEvent tickEvent;
class CpuPort : public Port
{
MemInterface *cacheInterface; MemTest *memtest;
FunctionalMemory *mainMem;
FunctionalMemory *checkMem; public:
CpuPort(const std::string &_name, MemTest *_memtest)
: Port(_name), memtest(_memtest)
{ }
protected:
virtual bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt);
virtual void recvFunctional(Packet *pkt);
virtual void recvStatusChange(Status status);
virtual void recvRetry();
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
};
CpuPort cachePort;
class MemTestSenderState : public Packet::SenderState
{
public:
/** Constructor. */
MemTestSenderState(uint8_t *_data)
: data(_data)
{ }
// Hold onto data pointer
uint8_t *data;
};
// Request *dataReq;
Packet *retryPkt;
// MemInterface *cacheInterface;
PhysicalMemory *mainMem;
PhysicalMemory *checkMem;
SimpleThread *thread; SimpleThread *thread;
bool accessRetry;
unsigned size; // size of testing memory region unsigned size; // size of testing memory region
unsigned percentReads; // target percentage of read accesses unsigned percentReads; // target percentage of read accesses
unsigned percentCopies; // target percentage of copy accesses // unsigned percentCopies; // target percentage of copy accesses
unsigned percentUncacheable; unsigned percentUncacheable;
int id; int id;
@ -128,31 +178,13 @@ class MemTest : public SimObject
Stats::Scalar<> numCopiesStat; Stats::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process() // called by MemCompleteEvent::process()
void completeRequest(MemReqPtr &req, uint8_t *data); void completeRequest(Packet *pkt);
void doRetry();
friend class MemCompleteEvent; friend class MemCompleteEvent;
}; };
class MemCompleteEvent : public Event
{
MemReqPtr req;
uint8_t *data;
MemTest *tester;
public:
MemCompleteEvent(MemReqPtr &_req, uint8_t *_data, MemTest *_tester)
: Event(&mainEventQueue),
req(_req), data(_data), tester(_tester)
{
}
void process();
virtual const char *description();
};
#endif // __CPU_MEMTEST_MEMTEST_HH__ #endif // __CPU_MEMTEST_MEMTEST_HH__