summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-10-07 13:41:49 -0400
committerKevin Lim <ktlim@umich.edu>2006-10-07 13:41:49 -0400
commit3afc69df7753c33822d822012261603eb301b04e (patch)
tree94e16cbae96e79f91a9c1365eb443a6a3d10a40b
parent413a5379b86729d298d666f9ff2b51d2ed1d4463 (diff)
parentfe762278e70edfc6d0eba5dd614db02ff99429b8 (diff)
downloadgem5-3afc69df7753c33822d822012261603eb301b04e.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zizzer.eecs.umich.edu:/.automount/zamp/z/ktlim2/clean/o3-merge/newmem --HG-- extra : convert_revision : b013b35f5c2264712eb51bef5623b208eb6128f9
-rw-r--r--src/SConscript1
-rw-r--r--src/cpu/memtest/memtest.cc302
-rw-r--r--src/cpu/memtest/memtest.hh96
3 files changed, 263 insertions, 136 deletions
diff --git a/src/SConscript b/src/SConscript
index 9f88bbeea..e75a36ab5 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -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
diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc
index 7ea9eaefc..e3a47f10a 100644
--- a/src/cpu/memtest/memtest.cc
+++ b/src/cpu/memtest/memtest.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;
+
+ // Needs to be masked off once we know the block size.
+ traceBlockAddr = _traceAddr;
+ baseAddr1 = 0x100000;
+ baseAddr2 = 0x400000;
+ uncacheAddr = 0x800000;
- blockSize = cacheInterface->getBlockSize();
+ // 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;
-}
-
-
-const char *
-MemCompleteEvent::description()
-{
- return "memory access completion";
+ if (cachePort.sendTiming(retryPkt)) {
+ accessRetry = false;
+ retryPkt = NULL;
+ }
}
-
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);
diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh
index 42fb235db..a0e58126b 100644
--- a/src/cpu/memtest/memtest.hh
+++ b/src/cpu/memtest/memtest.hh
@@ -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
+ {
+
+ 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)
+ { }
- MemInterface *cacheInterface;
- FunctionalMemory *mainMem;
- FunctionalMemory *checkMem;
+ // 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,29 +178,11 @@ class MemTest : public SimObject
Stats::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process()
- void completeRequest(MemReqPtr &req, uint8_t *data);
+ void completeRequest(Packet *pkt);
- friend class MemCompleteEvent;
-};
+ void doRetry();
-
-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();
+ friend class MemCompleteEvent;
};
#endif // __CPU_MEMTEST_MEMTEST_HH__