Merge ktlim@zizzer:/bk/newmem
into zizzer.eecs.umich.edu:/.automount/zamp/z/ktlim2/clean/o3-merge/newmem --HG-- extra : convert_revision : b013b35f5c2264712eb51bef5623b208eb6128f9
This commit is contained in:
commit
3afc69df77
3 changed files with 263 additions and 136 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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__
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue