# HG changeset patch
# User Gabe Black <[email protected]>
# Date 1235378629 28800
# Node ID be1b2688d06c0ef7617a53c3efa80bf5ec36f062
# Parent  7cb5e4a59163173276c14ef69d311dc47cfd3edc
CPU: Implement translateTiming which defers to translateAtomic, and convert the 
timing simple CPU to use it.

diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -317,7 +317,7 @@
 }
 
 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()))
@@ -399,6 +399,14 @@
 
     return checkCacheability(req, true);
 
+}
+
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+        Translation *translation)
+{
+    assert(translation);
+    translation->finish(translateAtomic(req, tc), req, tc, false);
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -479,7 +487,7 @@
 }
 
 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 @@
     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
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -131,7 +131,9 @@
     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 @@
     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
--- a/src/arch/mips/tlb.cc
+++ b/src/arch/mips/tlb.cc
@@ -310,7 +310,7 @@
 }
 
 Fault
-ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
 {
 #if !FULL_SYSTEM
     Process * p = tc->getProcessPtr();
@@ -426,8 +426,16 @@
 #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 @@
 #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
--- a/src/arch/mips/tlb.hh
+++ b/src/arch/mips/tlb.hh
@@ -145,7 +145,9 @@
     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 @@
     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
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -436,7 +436,7 @@
 }
 
 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 @@
     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
@@ -846,6 +854,14 @@
     req->setPaddr(req->getVaddr());
     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
 
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -177,7 +177,9 @@
         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 @@
         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
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -190,7 +190,7 @@
 
 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,15 +663,31 @@
 };
 
 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
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -138,8 +138,10 @@
         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 @@
             _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 @@
         {
             _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
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -607,8 +607,10 @@
         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
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -330,7 +330,7 @@
 }
 
 
-Fault
+void
 BaseSimpleCPU::setupFetchRequest(Request *req)
 {
     Addr threadPC = thread->readPC();
@@ -346,10 +346,6 @@
 
     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
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -125,9 +125,11 @@
     enum Status {
         Idle,
         Running,
+        ITBWaitResponse,
         IcacheRetry,
         IcacheWaitResponse,
         IcacheWaitSwitch,
+        DTBWaitResponse,
         DcacheRetry,
         DcacheWaitResponse,
         DcacheWaitSwitch,
@@ -160,7 +162,7 @@
     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
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -104,7 +104,8 @@
 }
 
 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,40 +263,157 @@
     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);
+    _status = Running;
+    if (fault != NoFault) {
+        delete data;
+        delete req;
 
-    pkt1 = pkt2 = NULL;
-    if ((fault = buildPacket(pkt1, req1, read)) != NoFault ||
-            (fault = buildPacket(pkt2, req2, read)) != NoFault) {
-        delete req;
+        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
+
+        if (req->isLocked()) {
+            do_access = TheISA::handleLockedWrite(thread, req);
+        } else if (req->isCondSwap()) {
+            assert(res);
+            req->setExtraData(*res);
+        }
+
+        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;
-        req = NULL;
-        pkt1 = NULL;
-        return fault;
+        delete req2;
+        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();
+            }
+        }
+    }
+}
+
+void
+TimingSimpleCPU::translationFault(Fault fault)
+{
+    numCycles += tickToCycles(curTick - previousTick);
+    previousTick = curTick;
+
+    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);
+    }
+}
+
+void
+TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read)
+{
+    MemCmd cmd;
+    if (read) {
+        cmd = MemCmd::ReadReq;
+        if (req->isLocked())
+            cmd = MemCmd::LoadLockedReq;
+    } else {
+        cmd = MemCmd::WriteReq;
+        if (req->isLocked()) {
+            cmd = MemCmd::StoreCondReq;
+        } else if (req->isSwap()) {
+            cmd = MemCmd::SwapReq;
+        }
+    }
+    pkt = new Packet(req, cmd, Packet::Broadcast);
+}
+
+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);
-    if (req->getFlags().isSet(Request::NO_ACCESS)) {
-        delete req1;
-        delete pkt1;
-        delete req2;
-        delete pkt2;
-        pkt1 = pkt;
-        pkt2 = NULL;
-        return NoFault;
-    }
 
     pkt->dataDynamic<uint8_t>(data);
     pkt1->dataStatic<uint8_t>(data);
@@ -308,33 +426,6 @@
     main_send_state->outstanding = 2;
     pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
     pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
-    return fault;
-}
-
-Fault
-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) {
-        cmd = MemCmd::ReadReq;
-        if (req->isLocked())
-            cmd = MemCmd::LoadLockedReq;
-    } else {
-        cmd = MemCmd::WriteReq;
-        if (req->isLocked()) {
-            cmd = MemCmd::StoreCondReq;
-        } else if (req->isSwap()) {
-            cmd = MemCmd::SwapReq;
-        }
-    }
-    pkt = new Packet(req, cmd, Packet::Broadcast);
-    return NoFault;
 }
 
 template <class T>
@@ -348,42 +439,30 @@
     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 @@
     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 @@
     if (!fromRom) {
         Request *ifetch_req = new Request();
         ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
-        Fault fault = setupFetchRequest(ifetch_req);
-
-        ifetch_pkt = new Packet(ifetch_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;
-            }
-        } else {
-            delete ifetch_req;
-            delete ifetch_pkt;
-            // fetch fault: advance directly to next instruction (fault 
handler)
-            advanceInst(fault);
-        }
+        setupFetchRequest(ifetch_req);
+        thread->itb->translateTiming(ifetch_req, tc,
+                &fetchTranslation);
     } else {
         _status = IcacheWaitResponse;
         completeIfetch(NULL);
+
+        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 (!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;
+        }
+    } else {
+        delete req;
+        // fetch fault: advance directly to next instruction (fault handler)
+        advanceInst(fault);
     }
 
     numCycles += tickToCycles(curTick - previousTick);
@@ -699,28 +758,11 @@
         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 @@
         }
     }
 
-    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
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -96,9 +96,114 @@
         }
     };
 
-    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 @@
     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
--- a/src/sim/tlb.cc
+++ b/src/sim/tlb.cc
@@ -50,6 +50,14 @@
 }
 
 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
--- a/src/sim/tlb.hh
+++ b/src/sim/tlb.hh
@@ -47,6 +47,21 @@
 
   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 @@
     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__
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to