Merge zizzer:/z/m5/Bitkeeper/m5
into zazzer.eecs.umich.edu:/z/rdreslin/m5bk/clean --HG-- extra : convert_revision : 09f035c902eedbf665cf7df8f72abdede4d8bea5
This commit is contained in:
commit
9061301b48
4 changed files with 97 additions and 25 deletions
|
@ -28,9 +28,10 @@
|
||||||
|
|
||||||
// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
|
// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
|
@ -44,6 +45,8 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
int TESTER_ALLOCATOR=0;
|
||||||
|
|
||||||
MemTest::MemTest(const string &name,
|
MemTest::MemTest(const string &name,
|
||||||
MemInterface *_cache_interface,
|
MemInterface *_cache_interface,
|
||||||
FunctionalMemory *main_mem,
|
FunctionalMemory *main_mem,
|
||||||
|
@ -111,6 +114,8 @@ MemTest::MemTest(const string &name,
|
||||||
noResponseCycles = 0;
|
noResponseCycles = 0;
|
||||||
numReads = 0;
|
numReads = 0;
|
||||||
tickEvent.schedule(0);
|
tickEvent.schedule(0);
|
||||||
|
|
||||||
|
id = TESTER_ALLOCATOR++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -127,6 +132,11 @@ printData(ostream &os, uint8_t *data, int nbytes)
|
||||||
void
|
void
|
||||||
MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
|
MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
|
||||||
{
|
{
|
||||||
|
//Remove the address from the list of outstanding
|
||||||
|
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
|
||||||
|
assert(removeAddr != outstandingAddrs.end());
|
||||||
|
outstandingAddrs.erase(removeAddr);
|
||||||
|
|
||||||
switch (req->cmd) {
|
switch (req->cmd) {
|
||||||
case Read:
|
case Read:
|
||||||
if (memcmp(req->data, data, req->size) != 0) {
|
if (memcmp(req->data, data, req->size) != 0) {
|
||||||
|
@ -158,6 +168,10 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Copy:
|
case Copy:
|
||||||
|
//Also remove dest from outstanding list
|
||||||
|
removeAddr = outstandingAddrs.find(req->dest);
|
||||||
|
assert(removeAddr != outstandingAddrs.end());
|
||||||
|
outstandingAddrs.erase(removeAddr);
|
||||||
numCopiesStat++;
|
numCopiesStat++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -212,7 +226,7 @@ MemTest::tick()
|
||||||
if (!tickEvent.scheduled())
|
if (!tickEvent.scheduled())
|
||||||
tickEvent.schedule(curTick + 1);
|
tickEvent.schedule(curTick + 1);
|
||||||
|
|
||||||
if (++noResponseCycles >= 5000) {
|
if (++noResponseCycles >= 500000) {
|
||||||
cerr << name() << ": deadlocked at cycle " << curTick << endl;
|
cerr << name() << ": deadlocked at cycle " << curTick << endl;
|
||||||
fatal("");
|
fatal("");
|
||||||
}
|
}
|
||||||
|
@ -232,6 +246,16 @@ MemTest::tick()
|
||||||
unsigned source_align = rand() % 100;
|
unsigned source_align = rand() % 100;
|
||||||
unsigned dest_align = rand() % 100;
|
unsigned dest_align = rand() % 100;
|
||||||
|
|
||||||
|
//If we aren't doing copies, use id as offset, and do a false sharing
|
||||||
|
//mem tester
|
||||||
|
if (percentCopies == 0) {
|
||||||
|
//We can eliminate the lower bits of the offset, and then use the id
|
||||||
|
//to offset within the blks
|
||||||
|
offset1 &= ~63; //Not the low order bits
|
||||||
|
offset1 += id;
|
||||||
|
access_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MemReqPtr req = new MemReq();
|
MemReqPtr req = new MemReq();
|
||||||
|
|
||||||
if (cacheable < percentUncacheable) {
|
if (cacheable < percentUncacheable) {
|
||||||
|
@ -251,6 +275,13 @@ MemTest::tick()
|
||||||
|
|
||||||
if (cmd < percentReads) {
|
if (cmd < percentReads) {
|
||||||
// read
|
// read
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
req->cmd = Read;
|
req->cmd = Read;
|
||||||
uint8_t *result = new uint8_t[8];
|
uint8_t *result = new uint8_t[8];
|
||||||
checkMem->access(Read, req->paddr, result, req->size);
|
checkMem->access(Read, req->paddr, result, req->size);
|
||||||
|
@ -273,6 +304,13 @@ MemTest::tick()
|
||||||
}
|
}
|
||||||
} else if (cmd < (100 - percentCopies)){
|
} else if (cmd < (100 - percentCopies)){
|
||||||
// write
|
// 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);
|
||||||
|
|
||||||
req->cmd = Write;
|
req->cmd = Write;
|
||||||
memcpy(req->data, &data, req->size);
|
memcpy(req->data, &data, req->size);
|
||||||
checkMem->access(Write, req->paddr, req->data, req->size);
|
checkMem->access(Write, req->paddr, req->data, req->size);
|
||||||
|
@ -298,6 +336,11 @@ MemTest::tick()
|
||||||
// copy
|
// copy
|
||||||
Addr source = ((base) ? baseAddr1 : baseAddr2) + offset1;
|
Addr source = ((base) ? baseAddr1 : baseAddr2) + offset1;
|
||||||
Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
|
Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
|
||||||
|
if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
|
||||||
|
else outstandingAddrs.insert(source);
|
||||||
|
if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
|
||||||
|
else outstandingAddrs.insert(dest);
|
||||||
|
|
||||||
if (source_align >= percentSourceUnaligned) {
|
if (source_align >= percentSourceUnaligned) {
|
||||||
source = blockAddr(source);
|
source = blockAddr(source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,14 @@
|
||||||
#ifndef __MEMTEST_HH__
|
#ifndef __MEMTEST_HH__
|
||||||
#define __MEMTEST_HH__
|
#define __MEMTEST_HH__
|
||||||
|
|
||||||
#include "sim/sim_object.hh"
|
#include <set>
|
||||||
#include "mem/mem_interface.hh"
|
|
||||||
#include "mem/functional_mem/functional_memory.hh"
|
|
||||||
#include "cpu/base_cpu.hh"
|
|
||||||
#include "cpu/exec_context.hh"
|
|
||||||
|
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
|
#include "cpu/base_cpu.hh"
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
|
#include "mem/functional_mem/functional_memory.hh"
|
||||||
|
#include "mem/mem_interface.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
#include "sim/stats.hh"
|
#include "sim/stats.hh"
|
||||||
|
|
||||||
class MemTest : public BaseCPU
|
class MemTest : public BaseCPU
|
||||||
|
@ -87,6 +88,10 @@ class MemTest : public BaseCPU
|
||||||
unsigned percentCopies; // target percentage of copy accesses
|
unsigned percentCopies; // target percentage of copy accesses
|
||||||
unsigned percentUncacheable;
|
unsigned percentUncacheable;
|
||||||
|
|
||||||
|
int id;
|
||||||
|
|
||||||
|
std::set<unsigned> outstandingAddrs;
|
||||||
|
|
||||||
unsigned blockSize;
|
unsigned blockSize;
|
||||||
|
|
||||||
Addr blockAddrMask;
|
Addr blockAddrMask;
|
||||||
|
|
|
@ -414,21 +414,22 @@ template <class T>
|
||||||
Fault
|
Fault
|
||||||
SimpleCPU::read(Addr addr, T &data, unsigned flags)
|
SimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
|
if (status() == DcacheMissStall) {
|
||||||
|
Fault fault = xc->read(memReq,data);
|
||||||
|
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setAddr(addr);
|
||||||
|
if (fault == No_Fault)
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
memReq->reset(addr, sizeof(T), flags);
|
memReq->reset(addr, sizeof(T), flags);
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = xc->translateDataReadReq(memReq);
|
Fault fault = xc->translateDataReadReq(memReq);
|
||||||
|
|
||||||
// do functional access
|
|
||||||
if (fault == No_Fault)
|
|
||||||
fault = xc->read(memReq, data);
|
|
||||||
|
|
||||||
if (traceData) {
|
|
||||||
traceData->setAddr(addr);
|
|
||||||
if (fault == No_Fault)
|
|
||||||
traceData->setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have a cache, do cache access too
|
// if we have a cache, do cache access too
|
||||||
if (fault == No_Fault && dcacheInterface) {
|
if (fault == No_Fault && dcacheInterface) {
|
||||||
memReq->cmd = Read;
|
memReq->cmd = Read;
|
||||||
|
@ -444,6 +445,24 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
lastDcacheStall = curTick;
|
lastDcacheStall = curTick;
|
||||||
unscheduleTickEvent();
|
unscheduleTickEvent();
|
||||||
_status = DcacheMissStall;
|
_status = DcacheMissStall;
|
||||||
|
} else {
|
||||||
|
// do functional access
|
||||||
|
fault = xc->read(memReq, data);
|
||||||
|
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setAddr(addr);
|
||||||
|
if (fault == No_Fault)
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(fault == No_Fault) {
|
||||||
|
// do functional access
|
||||||
|
fault = xc->read(memReq, data);
|
||||||
|
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setAddr(addr);
|
||||||
|
if (fault == No_Fault)
|
||||||
|
traceData->setData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,6 +624,9 @@ SimpleCPU::processCacheCompletion()
|
||||||
scheduleTickEvent(1);
|
scheduleTickEvent(1);
|
||||||
break;
|
break;
|
||||||
case DcacheMissStall:
|
case DcacheMissStall:
|
||||||
|
if (memReq->cmd.isRead()) {
|
||||||
|
curStaticInst->execute(this,traceData);
|
||||||
|
}
|
||||||
dcacheStallCycles += curTick - lastDcacheStall;
|
dcacheStallCycles += curTick - lastDcacheStall;
|
||||||
_status = Running;
|
_status = Running;
|
||||||
scheduleTickEvent(1);
|
scheduleTickEvent(1);
|
||||||
|
@ -750,10 +772,10 @@ SimpleCPU::tick()
|
||||||
comInstEventQueue[0]->serviceEvents(numInst);
|
comInstEventQueue[0]->serviceEvents(numInst);
|
||||||
|
|
||||||
// decode the instruction
|
// decode the instruction
|
||||||
inst = htoa(inst);
|
inst = htoa(inst);
|
||||||
StaticInstPtr<TheISA> si(inst);
|
curStaticInst = StaticInst<TheISA>::decode(inst);
|
||||||
|
|
||||||
traceData = Trace::getInstRecord(curTick, xc, this, si,
|
traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst,
|
||||||
xc->regs.pc);
|
xc->regs.pc);
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
|
@ -762,18 +784,18 @@ SimpleCPU::tick()
|
||||||
|
|
||||||
xc->func_exe_inst++;
|
xc->func_exe_inst++;
|
||||||
|
|
||||||
fault = si->execute(this, traceData);
|
fault = curStaticInst->execute(this, traceData);
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
if (xc->fnbin)
|
if (xc->fnbin)
|
||||||
xc->execute(si.get());
|
xc->execute(curStaticInst.get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (si->isMemRef()) {
|
if (curStaticInst->isMemRef()) {
|
||||||
numMemRefs++;
|
numMemRefs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (si->isLoad()) {
|
if (curStaticInst->isLoad()) {
|
||||||
++numLoad;
|
++numLoad;
|
||||||
comLoadEventQueue[0]->serviceEvents(numLoad);
|
comLoadEventQueue[0]->serviceEvents(numLoad);
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,6 +184,8 @@ class SimpleCPU : public BaseCPU
|
||||||
// Refcounted pointer to the one memory request.
|
// Refcounted pointer to the one memory request.
|
||||||
MemReqPtr memReq;
|
MemReqPtr memReq;
|
||||||
|
|
||||||
|
StaticInstPtr<TheISA> curStaticInst;
|
||||||
|
|
||||||
class CacheCompletionEvent : public Event
|
class CacheCompletionEvent : public Event
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue