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:
parent
f2acc3a4a3
commit
fe762278e7
3 changed files with 263 additions and 136 deletions
|
@ -285,6 +285,7 @@ turbolaser_sources = Split('''
|
|||
|
||||
# Syscall emulation (non-full-system) sources
|
||||
syscall_emulation_sources = Split('''
|
||||
cpu/memtest/memtest.cc
|
||||
mem/translating_port.cc
|
||||
mem/page_table.cc
|
||||
sim/process.cc
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
#include "base/statistics.hh"
|
||||
#include "cpu/simple_thread.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/sim_events.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
@ -50,27 +51,64 @@ using namespace TheISA;
|
|||
|
||||
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,
|
||||
MemInterface *_cache_interface,
|
||||
FunctionalMemory *main_mem,
|
||||
FunctionalMemory *check_mem,
|
||||
// MemInterface *_cache_interface,
|
||||
PhysicalMemory *main_mem,
|
||||
PhysicalMemory *check_mem,
|
||||
unsigned _memorySize,
|
||||
unsigned _percentReads,
|
||||
unsigned _percentCopies,
|
||||
// unsigned _percentCopies,
|
||||
unsigned _percentUncacheable,
|
||||
unsigned _progressInterval,
|
||||
unsigned _percentSourceUnaligned,
|
||||
unsigned _percentDestUnaligned,
|
||||
Addr _traceAddr,
|
||||
Counter _max_loads)
|
||||
: SimObject(name),
|
||||
: MemObject(name),
|
||||
tickEvent(this),
|
||||
cacheInterface(_cache_interface),
|
||||
cachePort("dcache", this),
|
||||
retryPkt(NULL),
|
||||
mainMem(main_mem),
|
||||
checkMem(check_mem),
|
||||
size(_memorySize),
|
||||
percentReads(_percentReads),
|
||||
percentCopies(_percentCopies),
|
||||
// percentCopies(_percentCopies),
|
||||
percentUncacheable(_percentUncacheable),
|
||||
progressInterval(_progressInterval),
|
||||
nextProgressMessage(_progressInterval),
|
||||
|
@ -81,11 +119,43 @@ MemTest::MemTest(const string &name,
|
|||
vector<string> cmd;
|
||||
cmd.push_back("/bin/ls");
|
||||
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;
|
||||
traceBlockAddr = blockAddr(_traceAddr);
|
||||
traceBlockAddr = blockAddr(traceBlockAddr);
|
||||
|
||||
//setup data storage with interesting values
|
||||
uint8_t *data1 = new uint8_t[size];
|
||||
|
@ -94,30 +164,22 @@ MemTest::MemTest(const string &name,
|
|||
memset(data1, 1, size);
|
||||
memset(data2, 2, size);
|
||||
memset(data3, 3, size);
|
||||
curTick = 0;
|
||||
|
||||
baseAddr1 = 0x100000;
|
||||
baseAddr2 = 0x400000;
|
||||
uncacheAddr = 0x800000;
|
||||
|
||||
// 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);
|
||||
checkMem->prot_write(baseAddr1, data1, size);
|
||||
mainMem->prot_write(baseAddr2, data2, size);
|
||||
checkMem->prot_write(baseAddr2, data2, size);
|
||||
mainMem->prot_write(uncacheAddr, data3, size);
|
||||
checkMem->prot_write(uncacheAddr, data3, size);
|
||||
*/
|
||||
|
||||
delete [] data1;
|
||||
delete [] data2;
|
||||
delete [] data3;
|
||||
|
||||
// set up counters
|
||||
noResponseCycles = 0;
|
||||
numReads = 0;
|
||||
tickEvent.schedule(0);
|
||||
|
||||
id = TESTER_ALLOCATOR++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -132,23 +194,31 @@ printData(ostream &os, uint8_t *data, int nbytes)
|
|||
}
|
||||
|
||||
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
|
||||
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
|
||||
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->getPaddr());
|
||||
assert(removeAddr != outstandingAddrs.end());
|
||||
outstandingAddrs.erase(removeAddr);
|
||||
|
||||
switch (req->cmd) {
|
||||
case Read:
|
||||
if (memcmp(req->data, data, req->size) != 0) {
|
||||
cerr << name() << ": on read of 0x" << hex << req->paddr
|
||||
<< " (0x" << hex << blockAddr(req->paddr) << ")"
|
||||
switch (pkt->cmd) {
|
||||
case Packet::ReadReq:
|
||||
|
||||
if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
|
||||
cerr << name() << ": on read of 0x" << hex << req->getPaddr()
|
||||
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
|
||||
<< "@ cycle " << dec << curTick
|
||||
<< ", cache returns 0x";
|
||||
printData(cerr, req->data, req->size);
|
||||
printData(cerr, pkt_data, pkt->getSize());
|
||||
cerr << ", expected 0x";
|
||||
printData(cerr, data, req->size);
|
||||
printData(cerr, data, pkt->getSize());
|
||||
cerr << endl;
|
||||
fatal("");
|
||||
}
|
||||
|
@ -163,13 +233,13 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
|
|||
}
|
||||
|
||||
if (numReads >= maxLoads)
|
||||
SimExit(curTick, "Maximum number of loads reached!");
|
||||
exitSimLoop("Maximum number of loads reached!");
|
||||
break;
|
||||
|
||||
case Write:
|
||||
case Packet::WriteReq:
|
||||
numWritesStat++;
|
||||
break;
|
||||
|
||||
/*
|
||||
case Copy:
|
||||
//Also remove dest from outstanding list
|
||||
removeAddr = outstandingAddrs.find(req->dest);
|
||||
|
@ -177,36 +247,37 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
|
|||
outstandingAddrs.erase(removeAddr);
|
||||
numCopiesStat++;
|
||||
break;
|
||||
|
||||
*/
|
||||
default:
|
||||
panic("invalid command");
|
||||
}
|
||||
|
||||
if (blockAddr(req->paddr) == traceBlockAddr) {
|
||||
if (blockAddr(req->getPaddr()) == traceBlockAddr) {
|
||||
cerr << name() << ": completed "
|
||||
<< (req->cmd.isWrite() ? "write" : "read")
|
||||
<< (pkt->isWrite() ? "write" : "read")
|
||||
<< " access of "
|
||||
<< dec << req->size << " bytes at address 0x"
|
||||
<< hex << req->paddr
|
||||
<< " (0x" << hex << blockAddr(req->paddr) << ")"
|
||||
<< dec << pkt->getSize() << " bytes at address 0x"
|
||||
<< hex << req->getPaddr()
|
||||
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
|
||||
<< ", value = 0x";
|
||||
printData(cerr, req->data, req->size);
|
||||
printData(cerr, pkt_data, pkt->getSize());
|
||||
cerr << " @ cycle " << dec << curTick;
|
||||
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
noResponseCycles = 0;
|
||||
delete state;
|
||||
delete [] data;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MemTest::regStats()
|
||||
{
|
||||
using namespace Stats;
|
||||
|
||||
|
||||
numReadsStat
|
||||
.name(name() + ".num_reads")
|
||||
.desc("number of read accesses completed")
|
||||
|
@ -234,7 +305,7 @@ MemTest::tick()
|
|||
fatal("");
|
||||
}
|
||||
|
||||
if (cacheInterface->isBlocked()) {
|
||||
if (accessRetry) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,6 +319,9 @@ MemTest::tick()
|
|||
|
||||
//If we aren't doing copies, use id as offset, and do a false sharing
|
||||
//mem tester
|
||||
// ***** NOTE FOR RON: We're not doing copies, but I'm not sure if this
|
||||
// code should be used.
|
||||
/*
|
||||
if (percentCopies == 0) {
|
||||
//We can eliminate the lower bits of the offset, and then use the id
|
||||
//to offset within the blks
|
||||
|
@ -255,23 +329,25 @@ MemTest::tick()
|
|||
offset += id;
|
||||
access_size = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
MemReqPtr req = new MemReq();
|
||||
Request *req = new Request();
|
||||
uint32_t flags = req->getFlags();
|
||||
Addr paddr;
|
||||
|
||||
if (cacheable < percentUncacheable) {
|
||||
req->flags |= UNCACHEABLE;
|
||||
req->paddr = uncacheAddr + offset;
|
||||
flags |= UNCACHEABLE;
|
||||
paddr = uncacheAddr + offset;
|
||||
} else {
|
||||
req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
|
||||
paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
|
||||
}
|
||||
// bool probe = (random() % 2 == 1) && !req->isUncacheable();
|
||||
bool probe = false;
|
||||
|
||||
req->size = 1 << access_size;
|
||||
req->data = new uint8_t[req->size];
|
||||
req->paddr &= ~(req->size - 1);
|
||||
req->time = curTick;
|
||||
req->xc = thread->getProxy();
|
||||
paddr &= ~((1 << access_size) - 1);
|
||||
req->setPhys(paddr, 1 << access_size, flags);
|
||||
|
||||
uint8_t *result = new uint8_t[8];
|
||||
|
||||
if (cmd < percentReads) {
|
||||
// read
|
||||
|
@ -279,60 +355,84 @@ MemTest::tick()
|
|||
//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
|
||||
//in the cpu store buffer.
|
||||
if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
|
||||
else outstandingAddrs.insert(req->paddr);
|
||||
if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
|
||||
else outstandingAddrs.insert(paddr);
|
||||
|
||||
req->cmd = Read;
|
||||
uint8_t *result = new uint8_t[8];
|
||||
checkMem->access(Read, req->paddr, result, req->size);
|
||||
if (blockAddr(req->paddr) == traceBlockAddr) {
|
||||
// ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
|
||||
// checkMem->access(Read, req->getPaddr(), result, req->size);
|
||||
if (blockAddr(paddr) == traceBlockAddr) {
|
||||
cerr << name()
|
||||
<< ": initiating read "
|
||||
<< ((probe) ? "probe of " : "access of ")
|
||||
<< dec << req->size << " bytes from addr 0x"
|
||||
<< hex << req->paddr
|
||||
<< " (0x" << hex << blockAddr(req->paddr) << ")"
|
||||
<< dec << req->getSize() << " bytes from addr 0x"
|
||||
<< hex << paddr
|
||||
<< " (0x" << hex << blockAddr(paddr) << ")"
|
||||
<< " at cycle "
|
||||
<< 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) {
|
||||
cacheInterface->probeAndUpdate(req);
|
||||
completeRequest(req, result);
|
||||
// ***** NOTE FOR RON: Send functional access? It used to
|
||||
// be a probeAndUpdate access. - Kevin
|
||||
cachePort.sendFunctional(pkt);
|
||||
// completeRequest(pkt, result);
|
||||
} else {
|
||||
req->completionEvent = new MemCompleteEvent(req, result, this);
|
||||
cacheInterface->access(req);
|
||||
// req->completionEvent = new MemCompleteEvent(req, result, this);
|
||||
if (!cachePort.sendTiming(pkt)) {
|
||||
accessRetry = true;
|
||||
retryPkt = pkt;
|
||||
}
|
||||
}
|
||||
} else if (cmd < (100 - percentCopies)){
|
||||
} else {
|
||||
// write
|
||||
|
||||
//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
|
||||
//in the cpu store buffer.
|
||||
if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
|
||||
else outstandingAddrs.insert(req->paddr);
|
||||
if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
|
||||
else outstandingAddrs.insert(paddr);
|
||||
|
||||
req->cmd = Write;
|
||||
memcpy(req->data, &data, req->size);
|
||||
checkMem->access(Write, req->paddr, req->data, req->size);
|
||||
if (blockAddr(req->paddr) == traceBlockAddr) {
|
||||
// ***** NOTE FOR RON: Not sure how to access memory.
|
||||
// checkMem->access(Write, req->paddr, req->data, req->size);
|
||||
/*
|
||||
if (blockAddr(req->getPaddr()) == traceBlockAddr) {
|
||||
cerr << name() << ": initiating write "
|
||||
<< ((probe)?"probe of ":"access of ")
|
||||
<< dec << req->size << " bytes (value = 0x";
|
||||
printData(cerr, req->data, req->size);
|
||||
<< dec << req->getSize() << " bytes (value = 0x";
|
||||
printData(cerr, data_pkt->getPtr(), req->getSize());
|
||||
cerr << ") to addr 0x"
|
||||
<< hex << req->paddr
|
||||
<< " (0x" << hex << blockAddr(req->paddr) << ")"
|
||||
<< hex << req->getPaddr()
|
||||
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
|
||||
<< " at cycle "
|
||||
<< 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) {
|
||||
cacheInterface->probeAndUpdate(req);
|
||||
completeRequest(req, NULL);
|
||||
// ***** NOTE FOR RON: Send functional access? It used to
|
||||
// be a probe access. - Kevin
|
||||
cachePort.sendFunctional(pkt);
|
||||
// completeRequest(req, NULL);
|
||||
} else {
|
||||
req->completionEvent = new MemCompleteEvent(req, NULL, this);
|
||||
cacheInterface->access(req);
|
||||
// req->completionEvent = new MemCompleteEvent(req, NULL, this);
|
||||
if (!cachePort.sendTiming(pkt)) {
|
||||
accessRetry = true;
|
||||
retryPkt = pkt;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
/* else {
|
||||
// copy
|
||||
unsigned source_align = random() % 100;
|
||||
unsigned dest_align = random() % 100;
|
||||
|
@ -369,38 +469,32 @@ MemTest::tick()
|
|||
<< " (0x" << hex << blockAddr(dest) << ")"
|
||||
<< " at cycle "
|
||||
<< dec << curTick << endl;
|
||||
}
|
||||
}*
|
||||
cacheInterface->access(req);
|
||||
uint8_t result[blockSize];
|
||||
checkMem->access(Read, source, &result, blockSize);
|
||||
checkMem->access(Write, dest, &result, blockSize);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MemCompleteEvent::process()
|
||||
MemTest::doRetry()
|
||||
{
|
||||
tester->completeRequest(req, data);
|
||||
delete this;
|
||||
if (cachePort.sendTiming(retryPkt)) {
|
||||
accessRetry = false;
|
||||
retryPkt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
MemCompleteEvent::description()
|
||||
{
|
||||
return "memory access completion";
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
|
||||
|
||||
SimObjectParam<BaseCache *> cache;
|
||||
SimObjectParam<FunctionalMemory *> main_mem;
|
||||
SimObjectParam<FunctionalMemory *> check_mem;
|
||||
// SimObjectParam<BaseCache *> cache;
|
||||
SimObjectParam<PhysicalMemory *> main_mem;
|
||||
SimObjectParam<PhysicalMemory *> check_mem;
|
||||
Param<unsigned> memory_size;
|
||||
Param<unsigned> percent_reads;
|
||||
Param<unsigned> percent_copies;
|
||||
// Param<unsigned> percent_copies;
|
||||
Param<unsigned> percent_uncacheable;
|
||||
Param<unsigned> progress_interval;
|
||||
Param<unsigned> percent_source_unaligned;
|
||||
|
@ -413,12 +507,12 @@ END_DECLARE_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(check_mem, "check memory"),
|
||||
INIT_PARAM(memory_size, "memory size"),
|
||||
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(progress_interval, "progress report interval (in accesses)"),
|
||||
INIT_PARAM(percent_source_unaligned,
|
||||
|
@ -433,8 +527,8 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest)
|
|||
|
||||
CREATE_SIM_OBJECT(MemTest)
|
||||
{
|
||||
return new MemTest(getInstanceName(), cache->getInterface(), main_mem,
|
||||
check_mem, memory_size, percent_reads, percent_copies,
|
||||
return new MemTest(getInstanceName(), /*cache->getInterface(),*/ main_mem,
|
||||
check_mem, memory_size, percent_reads, /*percent_copies,*/
|
||||
percent_uncacheable, progress_interval,
|
||||
percent_source_unaligned, percent_dest_unaligned,
|
||||
trace_addr, max_loads);
|
||||
|
|
|
@ -35,25 +35,26 @@
|
|||
#include <set>
|
||||
|
||||
#include "base/statistics.hh"
|
||||
#include "mem/functional/functional.hh"
|
||||
#include "mem/mem_interface.hh"
|
||||
//#include "mem/functional/functional.hh"
|
||||
//#include "mem/mem_interface.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
class PhysicalMemory;
|
||||
class ThreadContext;
|
||||
class MemTest : public SimObject
|
||||
class MemTest : public MemObject
|
||||
{
|
||||
public:
|
||||
|
||||
MemTest(const std::string &name,
|
||||
MemInterface *_cache_interface,
|
||||
FunctionalMemory *main_mem,
|
||||
FunctionalMemory *check_mem,
|
||||
// MemInterface *_cache_interface,
|
||||
PhysicalMemory *main_mem,
|
||||
PhysicalMemory *check_mem,
|
||||
unsigned _memorySize,
|
||||
unsigned _percentReads,
|
||||
unsigned _percentCopies,
|
||||
// unsigned _percentCopies,
|
||||
unsigned _percentUncacheable,
|
||||
unsigned _progressInterval,
|
||||
unsigned _percentSourceUnaligned,
|
||||
|
@ -61,6 +62,8 @@ class MemTest : public SimObject
|
|||
Addr _traceAddr,
|
||||
Counter _max_loads);
|
||||
|
||||
virtual void init();
|
||||
|
||||
// register statistics
|
||||
virtual void regStats();
|
||||
|
||||
|
@ -69,6 +72,8 @@ class MemTest : public SimObject
|
|||
// main simulation loop (one cycle)
|
||||
void tick();
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
|
||||
protected:
|
||||
class TickEvent : public Event
|
||||
{
|
||||
|
@ -82,16 +87,61 @@ class MemTest : public SimObject
|
|||
};
|
||||
|
||||
TickEvent tickEvent;
|
||||
class CpuPort : public Port
|
||||
{
|
||||
|
||||
MemInterface *cacheInterface;
|
||||
FunctionalMemory *mainMem;
|
||||
FunctionalMemory *checkMem;
|
||||
MemTest *memtest;
|
||||
|
||||
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;
|
||||
|
||||
bool accessRetry;
|
||||
|
||||
unsigned size; // size of testing memory region
|
||||
|
||||
unsigned percentReads; // target percentage of read accesses
|
||||
unsigned percentCopies; // target percentage of copy accesses
|
||||
// unsigned percentCopies; // target percentage of copy accesses
|
||||
unsigned percentUncacheable;
|
||||
|
||||
int id;
|
||||
|
@ -128,31 +178,13 @@ class MemTest : public SimObject
|
|||
Stats::Scalar<> numCopiesStat;
|
||||
|
||||
// called by MemCompleteEvent::process()
|
||||
void completeRequest(MemReqPtr &req, uint8_t *data);
|
||||
void completeRequest(Packet *pkt);
|
||||
|
||||
void doRetry();
|
||||
|
||||
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__
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue