summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:15 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:15 -0800
commit6ed47e94644f854baa33d1e9f367cc9eebd99abf (patch)
treebc19d10504d3ef0bcaa56b6256cfc732897d1531 /src
parent15940d06b5f6aabbe917a2a8c4cc4bb1cab991e2 (diff)
downloadgem5-6ed47e94644f854baa33d1e9f367cc9eebd99abf.tar.xz
CPU: Implement translateTiming which defers to translateAtomic, and convert the timing simple CPU to use it.
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/tlb.cc20
-rw-r--r--src/arch/alpha/tlb.hh8
-rw-r--r--src/arch/mips/tlb.cc20
-rw-r--r--src/arch/mips/tlb.hh8
-rw-r--r--src/arch/sparc/tlb.cc20
-rw-r--r--src/arch/sparc/tlb.hh9
-rw-r--r--src/arch/x86/tlb.cc22
-rw-r--r--src/arch/x86/tlb.hh12
-rw-r--r--src/cpu/simple/atomic.cc6
-rw-r--r--src/cpu/simple/base.cc6
-rw-r--r--src/cpu/simple/base.hh4
-rw-r--r--src/cpu/simple/timing.cc364
-rw-r--r--src/cpu/simple/timing.hh114
-rw-r--r--src/sim/tlb.cc8
-rw-r--r--src/sim/tlb.hh17
15 files changed, 447 insertions, 191 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index 82d410987..2b0afacfe 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -317,7 +317,7 @@ ITB::regStats()
}
Fault
-ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{
//If this is a pal pc, then set PHYSICAL
if (FULL_SYSTEM && PcPAL(req->getPC()))
@@ -401,6 +401,14 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
}
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc), req, tc, false);
+}
+
///////////////////////////////////////////////////////////////////////
//
// Alpha DTB
@@ -479,7 +487,7 @@ DTB::regStats()
}
Fault
-DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
+DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{
Addr pc = tc->readPC();
@@ -616,6 +624,14 @@ DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
return checkCacheability(req);
}
+void
+DTB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
TlbEntry &
TLB::index(bool advance)
{
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
index f5d2dbca9..877533797 100644
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -131,7 +131,9 @@ class ITB : public TLB
ITB(const Params *p);
virtual void regStats();
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation);
};
class DTB : public TLB
@@ -155,7 +157,9 @@ class DTB : public TLB
DTB(const Params *p);
virtual void regStats();
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write);
};
} // namespace AlphaISA
diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc
index db21c7919..eac44eba8 100644
--- a/src/arch/mips/tlb.cc
+++ b/src/arch/mips/tlb.cc
@@ -310,7 +310,7 @@ TLB::regStats()
}
Fault
-ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{
#if !FULL_SYSTEM
Process * p = tc->getProcessPtr();
@@ -426,8 +426,16 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
#endif
}
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc), req, tc, false);
+}
+
Fault
-DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
+DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{
#if !FULL_SYSTEM
Process * p = tc->getProcessPtr();
@@ -564,6 +572,14 @@ DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
#endif
}
+void
+DTB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
///////////////////////////////////////////////////////////////////////
//
// Mips ITB
diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh
index acb393116..1ab9d77e5 100644
--- a/src/arch/mips/tlb.hh
+++ b/src/arch/mips/tlb.hh
@@ -145,7 +145,9 @@ class ITB : public TLB {
typedef MipsTLBParams Params;
ITB(const Params *p);
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation);
};
class DTB : public TLB {
@@ -153,8 +155,10 @@ class DTB : public TLB {
typedef MipsTLBParams Params;
DTB(const Params *p);
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc,
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc,
bool write = false);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write = false);
};
class UTB : public ITB, public DTB {
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 683d916df..95ad0229e 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -436,7 +436,7 @@ DTB::writeSfsr(Addr a, bool write, ContextType ct,
}
Fault
-ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
@@ -548,8 +548,16 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
return NoFault;
}
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc), req, tc, false);
+}
+
Fault
-DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
+DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{
/*
* @todo this could really use some profiling and fixing to make
@@ -847,6 +855,14 @@ handleMmuRegAccess:
return NoFault;
};
+void
+DTB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
#if FULL_SYSTEM
Tick
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
index d563772e6..4fe532d4a 100644
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -177,7 +177,9 @@ class ITB : public TLB
cacheEntry = NULL;
}
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation);
private:
void writeSfsr(bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
@@ -199,7 +201,10 @@ class DTB : public TLB
cacheEntry[1] = NULL;
}
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write);
+ Fault translateAtomic(RequestPtr req,
+ ThreadContext *tc, bool write=false);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write=false);
#if FULL_SYSTEM
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 33017a6aa..a34922b44 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -190,7 +190,7 @@ TLB::demapPage(Addr va, uint64_t asn)
template<class TlbFault>
Fault
-TLB::translateAtomic(RequestPtr &req, ThreadContext *tc,
+TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
bool write, bool execute)
{
Addr vaddr = req->getVaddr();
@@ -663,17 +663,33 @@ TLB::translateAtomic(RequestPtr &req, ThreadContext *tc,
};
Fault
-DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
+DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{
return TLB::translateAtomic<FakeDTLBFault>(req, tc, write, false);
}
+void
+DTB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
Fault
-ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{
return TLB::translateAtomic<FakeITLBFault>(req, tc, false, true);
}
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc), req, tc, false);
+}
+
#if FULL_SYSTEM
Tick
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 91bb4a761..56730983a 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -138,8 +138,10 @@ namespace X86ISA
EntryList entryList;
template<class TlbFault>
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc,
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc,
bool write, bool execute);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write, bool execute);
public:
@@ -159,7 +161,9 @@ namespace X86ISA
_allowNX = false;
}
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation);
friend class DTB;
};
@@ -172,7 +176,9 @@ namespace X86ISA
{
_allowNX = true;
}
- Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write);
#if FULL_SYSTEM
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 7a1cf71c4..2ada12b8d 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -607,8 +607,10 @@ AtomicSimpleCPU::tick()
Fault fault = NoFault;
bool fromRom = isRomMicroPC(thread->readMicroPC());
- if (!fromRom)
- fault = setupFetchRequest(&ifetch_req);
+ if (!fromRom) {
+ setupFetchRequest(&ifetch_req);
+ fault = thread->itb->translateAtomic(&ifetch_req, tc);
+ }
if (fault == NoFault) {
Tick icache_latency = 0;
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index ddeb9a7c8..9372ff43d 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -330,7 +330,7 @@ BaseSimpleCPU::checkForInterrupts()
}
-Fault
+void
BaseSimpleCPU::setupFetchRequest(Request *req)
{
Addr threadPC = thread->readPC();
@@ -346,10 +346,6 @@ BaseSimpleCPU::setupFetchRequest(Request *req)
Addr fetchPC = (threadPC & PCMask) + fetchOffset;
req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC);
-
- Fault fault = thread->itb->translateAtomic(req, tc);
-
- return fault;
}
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 34d0f5954..d2ccc0ff1 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -125,9 +125,11 @@ class BaseSimpleCPU : public BaseCPU
enum Status {
Idle,
Running,
+ ITBWaitResponse,
IcacheRetry,
IcacheWaitResponse,
IcacheWaitSwitch,
+ DTBWaitResponse,
DcacheRetry,
DcacheWaitResponse,
DcacheWaitSwitch,
@@ -160,7 +162,7 @@ class BaseSimpleCPU : public BaseCPU
bool stayAtPC;
void checkForInterrupts();
- Fault setupFetchRequest(Request *req);
+ void setupFetchRequest(Request *req);
void preExecute();
void postExecute();
void advancePC(Fault fault);
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 65222266e..3f5778138 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -104,7 +104,8 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
}
TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
- : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock), fetchEvent(this)
+ : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock),
+ dcachePort(this, p->clock), fetchEvent(this)
{
_status = Idle;
@@ -262,66 +263,123 @@ TimingSimpleCPU::handleReadPacket(PacketPtr pkt)
return dcache_pkt == NULL;
}
-Fault
-TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
- RequestPtr &req, Addr split_addr, uint8_t *data, bool read)
+void
+TimingSimpleCPU::sendData(Fault fault, RequestPtr req,
+ uint8_t *data, uint64_t *res, bool read)
{
- Fault fault;
- RequestPtr req1, req2;
- assert(!req->isLocked() && !req->isSwap());
- req->splitOnVaddr(split_addr, req1, req2);
-
- pkt1 = pkt2 = NULL;
- if ((fault = buildPacket(pkt1, req1, read)) != NoFault ||
- (fault = buildPacket(pkt2, req2, read)) != NoFault) {
+ _status = Running;
+ if (fault != NoFault) {
+ delete data;
delete req;
- delete req1;
- delete pkt1;
- req = NULL;
- pkt1 = NULL;
- return fault;
+
+ translationFault(fault);
+ return;
}
+ PacketPtr pkt;
+ buildPacket(pkt, req, read);
+ pkt->dataDynamic<uint8_t>(data);
+ if (req->getFlags().isSet(Request::NO_ACCESS)) {
+ assert(!dcache_pkt);
+ pkt->makeResponse();
+ completeDataAccess(pkt);
+ } else if (read) {
+ handleReadPacket(pkt);
+ } else {
+ bool do_access = true; // flag to suppress cache access
- assert(!req1->isMmapedIpr() && !req2->isMmapedIpr());
+ if (req->isLocked()) {
+ do_access = TheISA::handleLockedWrite(thread, req);
+ } else if (req->isCondSwap()) {
+ assert(res);
+ req->setExtraData(*res);
+ }
- req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags());
- PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(),
- Packet::Broadcast);
- if (req->getFlags().isSet(Request::NO_ACCESS)) {
+ if (do_access) {
+ dcache_pkt = pkt;
+ handleWritePacket();
+ } else {
+ _status = DcacheWaitResponse;
+ completeDataAccess(pkt);
+ }
+ }
+}
+
+void
+TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read)
+{
+ _status = Running;
+ if (fault1 != NoFault || fault2 != NoFault) {
+ delete data;
delete req1;
- delete pkt1;
delete req2;
- delete pkt2;
- pkt1 = pkt;
- pkt2 = NULL;
- return NoFault;
+ if (fault1 != NoFault)
+ translationFault(fault1);
+ else if (fault2 != NoFault)
+ translationFault(fault2);
+ return;
+ }
+ PacketPtr pkt1, pkt2;
+ buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read);
+ if (req->getFlags().isSet(Request::NO_ACCESS)) {
+ assert(!dcache_pkt);
+ pkt1->makeResponse();
+ completeDataAccess(pkt1);
+ } else if (read) {
+ if (handleReadPacket(pkt1)) {
+ SplitFragmentSenderState * send_state =
+ dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
+ send_state->clearFromParent();
+ if (handleReadPacket(pkt2)) {
+ send_state = dynamic_cast<SplitFragmentSenderState *>(
+ pkt1->senderState);
+ send_state->clearFromParent();
+ }
+ }
+ } else {
+ dcache_pkt = pkt1;
+ if (handleWritePacket()) {
+ SplitFragmentSenderState * send_state =
+ dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
+ send_state->clearFromParent();
+ dcache_pkt = pkt2;
+ if (handleWritePacket()) {
+ send_state = dynamic_cast<SplitFragmentSenderState *>(
+ pkt1->senderState);
+ send_state->clearFromParent();
+ }
+ }
}
+}
- pkt->dataDynamic<uint8_t>(data);
- pkt1->dataStatic<uint8_t>(data);
- pkt2->dataStatic<uint8_t>(data + req1->getSize());
+void
+TimingSimpleCPU::translationFault(Fault fault)
+{
+ numCycles += tickToCycles(curTick - previousTick);
+ previousTick = curTick;
- SplitMainSenderState * main_send_state = new SplitMainSenderState;
- pkt->senderState = main_send_state;
- main_send_state->fragments[0] = pkt1;
- main_send_state->fragments[1] = pkt2;
- main_send_state->outstanding = 2;
- pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
- pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
- return fault;
+ if (traceData) {
+ // Since there was a fault, we shouldn't trace this instruction.
+ delete traceData;
+ traceData = NULL;
+ }
+
+ postExecute();
+
+ if (getState() == SimObject::Draining) {
+ advancePC(fault);
+ completeDrain();
+ } else {
+ advanceInst(fault);
+ }
}
-Fault
-TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read)
+void
+TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
{
- Fault fault = thread->dtb->translateAtomic(req, tc, !read);
MemCmd cmd;
- if (fault != NoFault) {
- delete req;
- req = NULL;
- pkt = NULL;
- return fault;
- } else if (read) {
+ if (read) {
cmd = MemCmd::ReadReq;
if (req->isLocked())
cmd = MemCmd::LoadLockedReq;
@@ -334,7 +392,40 @@ TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read)
}
}
pkt = new Packet(req, cmd, Packet::Broadcast);
- return NoFault;
+}
+
+void
+TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read)
+{
+ pkt1 = pkt2 = NULL;
+
+ assert(!req1->isMmapedIpr() && !req2->isMmapedIpr());
+
+ if (req->getFlags().isSet(Request::NO_ACCESS)) {
+ buildPacket(pkt1, req, read);
+ return;
+ }
+
+ buildPacket(pkt1, req1, read);
+ buildPacket(pkt2, req2, read);
+
+ req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags());
+ PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(),
+ Packet::Broadcast);
+
+ pkt->dataDynamic<uint8_t>(data);
+ pkt1->dataStatic<uint8_t>(data);
+ pkt2->dataStatic<uint8_t>(data + req1->getSize());
+
+ SplitMainSenderState * main_send_state = new SplitMainSenderState;
+ pkt->senderState = main_send_state;
+ main_send_state->fragments[0] = pkt1;
+ main_send_state->fragments[1] = pkt2;
+ main_send_state->outstanding = 2;
+ pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
+ pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
}
template <class T>
@@ -348,42 +439,30 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
int block_size = dcachePort.peerBlockSize();
int data_size = sizeof(T);
- PacketPtr pkt;
RequestPtr req = new Request(asid, addr, data_size,
flags, pc, _cpuId, thread_id);
Addr split_addr = roundDown(addr + data_size - 1, block_size);
assert(split_addr <= addr || split_addr - addr < block_size);
+
+ _status = DTBWaitResponse;
if (split_addr > addr) {
- PacketPtr pkt1, pkt2;
- Fault fault = this->buildSplitPacket(pkt1, pkt2, req,
- split_addr, (uint8_t *)(new T), true);
- if (fault != NoFault)
- return fault;
- if (req->getFlags().isSet(Request::NO_ACCESS)) {
- dcache_pkt = pkt1;
- } else if (handleReadPacket(pkt1)) {
- SplitFragmentSenderState * send_state =
- dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
- send_state->clearFromParent();
- if (handleReadPacket(pkt2)) {
- send_state =
- dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
- send_state->clearFromParent();
- }
- }
+ RequestPtr req1, req2;
+ assert(!req->isLocked() && !req->isSwap());
+ req->splitOnVaddr(split_addr, req1, req2);
+
+ typedef SplitDataTranslation::WholeTranslationState WholeState;
+ WholeState *state = new WholeState(req1, req2, req,
+ (uint8_t *)(new T), true);
+ thread->dtb->translateTiming(req1, tc,
+ new SplitDataTranslation(this, 0, state), false);
+ thread->dtb->translateTiming(req2, tc,
+ new SplitDataTranslation(this, 1, state), false);
} else {
- Fault fault = buildPacket(pkt, req, true);
- if (fault != NoFault) {
- return fault;
- }
- if (req->getFlags().isSet(Request::NO_ACCESS)) {
- dcache_pkt = pkt;
- } else {
- pkt->dataDynamic<T>(new T);
- handleReadPacket(pkt);
- }
+ thread->dtb->translateTiming(req, tc,
+ new DataTranslation(this, (uint8_t *)(new T), NULL, true),
+ false);
}
if (traceData) {
@@ -484,54 +563,25 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
Addr split_addr = roundDown(addr + data_size - 1, block_size);
assert(split_addr <= addr || split_addr - addr < block_size);
+ T *dataP = new T;
+ *dataP = TheISA::gtoh(data);
+ _status = DTBWaitResponse;
if (split_addr > addr) {
- PacketPtr pkt1, pkt2;
- T *dataP = new T;
- *dataP = data;
- Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr,
- (uint8_t *)dataP, false);
- if (fault != NoFault)
- return fault;
- dcache_pkt = pkt1;
- if (!req->getFlags().isSet(Request::NO_ACCESS)) {
- if (handleWritePacket()) {
- SplitFragmentSenderState * send_state =
- dynamic_cast<SplitFragmentSenderState *>(
- pkt1->senderState);
- send_state->clearFromParent();
- dcache_pkt = pkt2;
- if (handleReadPacket(pkt2)) {
- send_state =
- dynamic_cast<SplitFragmentSenderState *>(
- pkt1->senderState);
- send_state->clearFromParent();
- }
- }
- }
+ RequestPtr req1, req2;
+ assert(!req->isLocked() && !req->isSwap());
+ req->splitOnVaddr(split_addr, req1, req2);
+
+ typedef SplitDataTranslation::WholeTranslationState WholeState;
+ WholeState *state = new WholeState(req1, req2, req,
+ (uint8_t *)dataP, false);
+ thread->dtb->translateTiming(req1, tc,
+ new SplitDataTranslation(this, 0, state), true);
+ thread->dtb->translateTiming(req2, tc,
+ new SplitDataTranslation(this, 1, state), true);
} else {
- bool do_access = true; // flag to suppress cache access
-
- Fault fault = buildPacket(dcache_pkt, req, false);
- if (fault != NoFault)
- return fault;
-
- if (!req->getFlags().isSet(Request::NO_ACCESS)) {
- if (req->isLocked()) {
- do_access = TheISA::handleLockedWrite(thread, req);
- } else if (req->isCondSwap()) {
- assert(res);
- req->setExtraData(*res);
- }
-
- dcache_pkt->allocate();
- if (req->isMmapedIpr())
- dcache_pkt->set(htog(data));
- else
- dcache_pkt->set(data);
-
- if (do_access)
- handleWritePacket();
- }
+ thread->dtb->translateTiming(req, tc,
+ new DataTranslation(this, (uint8_t *)dataP, res, false),
+ true);
}
if (traceData) {
@@ -620,30 +670,39 @@ TimingSimpleCPU::fetch()
if (!fromRom) {
Request *ifetch_req = new Request();
ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
- Fault fault = setupFetchRequest(ifetch_req);
+ setupFetchRequest(ifetch_req);
+ thread->itb->translateTiming(ifetch_req, tc,
+ &fetchTranslation);
+ } else {
+ _status = IcacheWaitResponse;
+ completeIfetch(NULL);
- ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast);
+ numCycles += tickToCycles(curTick - previousTick);
+ previousTick = curTick;
+ }
+}
+
+
+void
+TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc)
+{
+ if (fault == NoFault) {
+ ifetch_pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
ifetch_pkt->dataStatic(&inst);
- if (fault == NoFault) {
- if (!icachePort.sendTiming(ifetch_pkt)) {
- // Need to wait for retry
- _status = IcacheRetry;
- } else {
- // Need to wait for cache to respond
- _status = IcacheWaitResponse;
- // ownership of packet transferred to memory system
- ifetch_pkt = NULL;
- }
+ if (!icachePort.sendTiming(ifetch_pkt)) {
+ // Need to wait for retry
+ _status = IcacheRetry;
} else {
- delete ifetch_req;
- delete ifetch_pkt;
- // fetch fault: advance directly to next instruction (fault handler)
- advanceInst(fault);
+ // Need to wait for cache to respond
+ _status = IcacheWaitResponse;
+ // ownership of packet transferred to memory system
+ ifetch_pkt = NULL;
}
} else {
- _status = IcacheWaitResponse;
- completeIfetch(NULL);
+ delete req;
+ // fetch fault: advance directly to next instruction (fault handler)
+ advanceInst(fault);
}
numCycles += tickToCycles(curTick - previousTick);
@@ -699,28 +758,11 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt)
Fault fault = curStaticInst->initiateAcc(this, traceData);
if (_status != Running) {
// instruction will complete in dcache response callback
- assert(_status == DcacheWaitResponse || _status == DcacheRetry);
+ assert(_status == DcacheWaitResponse ||
+ _status == DcacheRetry || DTBWaitResponse);
assert(fault == NoFault);
} else {
- if (fault == NoFault) {
- // Note that ARM can have NULL packets if the instruction gets
- // squashed due to predication
- // early fail on store conditional: complete now
- assert(dcache_pkt != NULL || THE_ISA == ARM_ISA);
-
- fault = curStaticInst->completeAcc(dcache_pkt, this,
- traceData);
- if (dcache_pkt != NULL)
- {
- delete dcache_pkt->req;
- delete dcache_pkt;
- dcache_pkt = NULL;
- }
-
- // keep an instruction count
- if (fault == NoFault)
- countInst();
- } else if (traceData) {
+ if (fault != NoFault && traceData) {
// If there was a fault, we shouldn't trace this instruction.
delete traceData;
traceData = NULL;
@@ -843,7 +885,7 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt)
}
}
- assert(_status == DcacheWaitResponse);
+ assert(_status == DcacheWaitResponse || _status == DTBWaitResponse);
_status = Running;
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index 0a639a627..a02ec48c9 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -96,9 +96,114 @@ class TimingSimpleCPU : public BaseSimpleCPU
}
};
- Fault buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, RequestPtr &req,
- Addr split_addr, uint8_t *data, bool read);
- Fault buildPacket(PacketPtr &pkt, RequestPtr &req, bool read);
+ class FetchTranslation : public BaseTLB::Translation
+ {
+ protected:
+ TimingSimpleCPU *cpu;
+
+ public:
+ FetchTranslation(TimingSimpleCPU *_cpu) : cpu(_cpu)
+ {}
+
+ void finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ cpu->sendFetch(fault, req, tc);
+ }
+ };
+ FetchTranslation fetchTranslation;
+
+ class DataTranslation : public BaseTLB::Translation
+ {
+ protected:
+ TimingSimpleCPU *cpu;
+ uint8_t *data;
+ uint64_t *res;
+ bool read;
+
+ public:
+ DataTranslation(TimingSimpleCPU *_cpu,
+ uint8_t *_data, uint64_t *_res, bool _read) :
+ cpu(_cpu), data(_data), res(_res), read(_read)
+ {}
+
+ void
+ finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ cpu->sendData(fault, req, data, res, read);
+ delete this;
+ }
+ };
+
+ class SplitDataTranslation : public BaseTLB::Translation
+ {
+ public:
+ struct WholeTranslationState
+ {
+ public:
+ int outstanding;
+ RequestPtr requests[2];
+ RequestPtr mainReq;
+ Fault faults[2];
+ uint8_t *data;
+ bool read;
+
+ WholeTranslationState(RequestPtr req1, RequestPtr req2,
+ RequestPtr main, uint8_t *_data, bool _read)
+ {
+ outstanding = 2;
+ requests[0] = req1;
+ requests[1] = req2;
+ mainReq = main;
+ faults[0] = faults[1] = NoFault;
+ data = _data;
+ read = _read;
+ }
+ };
+
+ TimingSimpleCPU *cpu;
+ int index;
+ WholeTranslationState *state;
+
+ SplitDataTranslation(TimingSimpleCPU *_cpu, int _index,
+ WholeTranslationState *_state) :
+ cpu(_cpu), index(_index), state(_state)
+ {}
+
+ void
+ finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write)
+ {
+ assert(state);
+ assert(state->outstanding);
+ state->faults[index] = fault;
+ if (--state->outstanding == 0) {
+ cpu->sendSplitData(state->faults[0],
+ state->faults[1],
+ state->requests[0],
+ state->requests[1],
+ state->mainReq,
+ state->data,
+ state->read);
+ delete state;
+ }
+ delete this;
+ }
+ };
+
+ void sendData(Fault fault, RequestPtr req,
+ uint8_t *data, uint64_t *res, bool read);
+ void sendSplitData(Fault fault1, Fault fault2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read);
+
+ void translationFault(Fault fault);
+
+ void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
+ void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
+ RequestPtr req1, RequestPtr req2, RequestPtr req,
+ uint8_t *data, bool read);
bool handleReadPacket(PacketPtr pkt);
// This function always implicitly uses dcache_pkt.
@@ -228,8 +333,9 @@ class TimingSimpleCPU : public BaseSimpleCPU
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
void fetch();
+ void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
void completeIfetch(PacketPtr );
- void completeDataAccess(PacketPtr );
+ void completeDataAccess(PacketPtr pkt);
void advanceInst(Fault fault);
/**
diff --git a/src/sim/tlb.cc b/src/sim/tlb.cc
index f7b57cbbc..e82e4f277 100644
--- a/src/sim/tlb.cc
+++ b/src/sim/tlb.cc
@@ -50,6 +50,14 @@ GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool)
}
void
+GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
+void
GenericTLB::demapPage(Addr vaddr, uint64_t asn)
{
warn("Demapping pages in the generic TLB is unnecessary.\n");
diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh
index 8429c0df5..8893f8c97 100644
--- a/src/sim/tlb.hh
+++ b/src/sim/tlb.hh
@@ -47,6 +47,21 @@ class BaseTLB : public SimObject
public:
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
+
+ class Translation
+ {
+ public:
+ virtual ~Translation()
+ {}
+
+ /*
+ * The memory for this object may be dynamically allocated, and it may
+ * be responsible for cleaning itself up which will happen in this
+ * function. Once it's called, the object is no longer valid.
+ */
+ virtual void finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write=false) = 0;
+ };
};
class GenericTLB : public BaseTLB
@@ -59,6 +74,8 @@ class GenericTLB : public BaseTLB
void demapPage(Addr vaddr, uint64_t asn);
Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool=false);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool=false);
};
#endif // __ARCH_SPARC_TLB_HH__