# HG changeset patch
# User Timothy M. Jones <[email protected]>
# Date 1259064162 0
# Node ID 77dffd16710c4ad8e308b7dfee75cce4219b30a0
# Parent  b431ed08a6b7d809df9bfed51365e4d3bdf81f93
Cpu: Make TimingSimpleCPU use new DTB translation code.

This patch removes the duplicate code from cpu/simple/timing.hh and makes
TimingSimpleCPU use the new code in cpu/translation.hh.  I've had to make
a few additional changes to get it to work ok for both O3 and Timing.

diff --git a/src/cpu/base.hh b/src/cpu/base.hh
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -53,6 +53,7 @@
 class ThreadContext;
 class System;
 class Port;
+class WholeTranslationState;
 
 namespace TheISA
 {
@@ -276,6 +277,12 @@
 
     virtual Counter totalInstructions() const { return 0; }
 
+    /**
+     * Finish a DTB translation.
+     * @param state The DTB translation state.
+     */
+    virtual void finishTranslation(WholeTranslationState *state) {}
+
     // Function tracing
   private:
     bool functionTracingEnabled;
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -979,9 +979,9 @@
                                        BaseTLB::Mode mode)
 {
     WholeTranslationState *state =
-        new WholeTranslationState(req, res, mode);
-    DataTranslation<Impl> *trans =
-        new DataTranslation<Impl>(this, state);
+        new WholeTranslationState(req, NULL, res, mode);
+    DataTranslationInst<Impl> *trans =
+        new DataTranslationInst<Impl>(this, state);
     cpu->dtb->translateTiming(req, thread->getTC(), trans, mode);
 }
 
@@ -993,11 +993,11 @@
 {
     // Set up the translation state.
     WholeTranslationState *state =
-        new WholeTranslationState(req, sreqLow, sreqHigh, res, mode);
-    DataTranslation<Impl> *stransLow =
-        new DataTranslation<Impl>(this, state, 0);
-    DataTranslation<Impl> *stransHigh =
-        new DataTranslation<Impl>(this, state, 1);
+        new WholeTranslationState(req, sreqLow, sreqHigh, NULL, res, mode);
+    DataTranslationInst<Impl> *stransLow =
+        new DataTranslationInst<Impl>(this, state, 0);
+    DataTranslationInst<Impl> *stransHigh =
+        new DataTranslationInst<Impl>(this, state, 1);
 
     // Perform the translation.
     cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode);
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
@@ -268,19 +268,9 @@
 }
 
 void
-TimingSimpleCPU::sendData(Fault fault, RequestPtr req,
-        uint8_t *data, uint64_t *res, bool read)
+TimingSimpleCPU::sendData(RequestPtr req, uint8_t *data, uint64_t *res,
+                          bool read)
 {
-    _status = Running;
-    if (fault != NoFault) {
-        if (req->isPrefetch())
-            fault = NoFault;
-        delete data;
-        delete req;
-
-        translationFault(fault);
-        return;
-    }
     PacketPtr pkt;
     buildPacket(pkt, req, read);
     pkt->dataDynamic<uint8_t>(data);
@@ -311,25 +301,9 @@
 }
 
 void
-TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2,
-        RequestPtr req1, RequestPtr req2, RequestPtr req,
-        uint8_t *data, bool read)
+TimingSimpleCPU::sendSplitData(RequestPtr req1, RequestPtr req2,
+                               RequestPtr req, uint8_t *data, bool read)
 {
-    _status = Running;
-    if (fault1 != NoFault || fault2 != NoFault) {
-        if (req1->isPrefetch())
-            fault1 = NoFault;
-        if (req2->isPrefetch())
-            fault2 = NoFault;
-        delete data;
-        delete req1;
-        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)) {
@@ -450,6 +424,7 @@
     const Addr pc = thread->readPC();
     unsigned block_size = dcachePort.peerBlockSize();
     int data_size = sizeof(T);
+    BaseTLB::Mode mode = BaseTLB::Read;
 
     RequestPtr req  = new Request(asid, addr, data_size,
                                   flags, pc, _cpuId, tid);
@@ -457,24 +432,27 @@
     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) {
         RequestPtr req1, req2;
         assert(!req->isLLSC() && !req->isSwap());
         req->splitOnVaddr(split_addr, req1, req2);
 
-        typedef SplitDataTranslation::WholeTranslationState WholeState;
-        WholeState *state = new WholeState(req1, req2, req,
-                                           (uint8_t *)(new T), BaseTLB::Read);
-        thread->dtb->translateTiming(req1, tc,
-                new SplitDataTranslation(this, 0, state), BaseTLB::Read);
-        thread->dtb->translateTiming(req2, tc,
-                new SplitDataTranslation(this, 1, state), BaseTLB::Read);
+        WholeTranslationState *state =
+            new WholeTranslationState(req, req1, req2, (uint8_t *)(new T),
+                                      NULL, mode);
+        DataTranslationCpu *trans1 =
+            new DataTranslationCpu(this, state, 0);
+        DataTranslationCpu *trans2 =
+            new DataTranslationCpu(this, state, 1);
+
+        thread->dtb->translateTiming(req1, tc, trans1, mode);
+        thread->dtb->translateTiming(req2, tc, trans2, mode);
     } else {
-        DataTranslation *translation =
-            new DataTranslation(this, (uint8_t *)(new T), NULL, BaseTLB::Read);
-        thread->dtb->translateTiming(req, tc, translation, BaseTLB::Read);
+        WholeTranslationState *state =
+            new WholeTranslationState(req, (uint8_t *)(new T), NULL, mode);
+        DataTranslationCpu *translation = new DataTranslationCpu(this, state);
+        thread->dtb->translateTiming(req, tc, translation, mode);
     }
 
     if (traceData) {
@@ -568,6 +546,7 @@
     const Addr pc = thread->readPC();
     unsigned block_size = dcachePort.peerBlockSize();
     int data_size = sizeof(T);
+    BaseTLB::Mode mode = BaseTLB::Write;
 
     RequestPtr req = new Request(asid, addr, data_size,
                                  flags, pc, _cpuId, tid);
@@ -583,17 +562,21 @@
         assert(!req->isLLSC() && !req->isSwap());
         req->splitOnVaddr(split_addr, req1, req2);
 
-        typedef SplitDataTranslation::WholeTranslationState WholeState;
-        WholeState *state = new WholeState(req1, req2, req,
-                (uint8_t *)dataP, BaseTLB::Write);
-        thread->dtb->translateTiming(req1, tc,
-                new SplitDataTranslation(this, 0, state), BaseTLB::Write);
-        thread->dtb->translateTiming(req2, tc,
-                new SplitDataTranslation(this, 1, state), BaseTLB::Write);
+        WholeTranslationState *state =
+            new WholeTranslationState(req, req1, req2, (uint8_t *)dataP,
+                                      res, mode);
+        DataTranslationCpu *trans1 =
+            new DataTranslationCpu(this, state, 0);
+        DataTranslationCpu *trans2 =
+            new DataTranslationCpu(this, state, 1);
+
+        thread->dtb->translateTiming(req1, tc, trans1, mode);
+        thread->dtb->translateTiming(req2, tc, trans2, mode);
     } else {
-        DataTranslation *translation =
-            new DataTranslation(this, (uint8_t *)dataP, res, BaseTLB::Write);
-        thread->dtb->translateTiming(req, tc, translation, BaseTLB::Write);
+        WholeTranslationState *state =
+            new WholeTranslationState(req, (uint8_t *)dataP, res, mode);
+        DataTranslationCpu *translation = new DataTranslationCpu(this, state);
+        thread->dtb->translateTiming(req, tc, translation, mode);
     }
 
     if (traceData) {
@@ -668,6 +651,32 @@
 
 
 void
+TimingSimpleCPU::finishTranslation(WholeTranslationState *state)
+{
+    _status = Running;
+
+    if (state->getFault() != NoFault) {
+        if (state->isPrefetch()) {
+            state->setNoFault();
+        }
+        delete state->data;
+        state->deleteReqs();
+        translationFault(state->getFault());
+    } else {
+        if (!state->isSplit) {
+            sendData(state->mainReq, state->data, state->res,
+                     state->mode == BaseTLB::Read);
+        } else {
+            sendSplitData(state->sreqLow, state->sreqHigh, state->mainReq,
+                          state->data, state->mode == BaseTLB::Read);
+        }
+    }
+
+    delete state;
+}
+
+
+void
 TimingSimpleCPU::fetch()
 {
     DPRINTF(SimpleCPU, "Fetch\n");
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
@@ -32,6 +32,7 @@
 #define __CPU_SIMPLE_TIMING_HH__
 
 #include "cpu/simple/base.hh"
+#include "cpu/translation.hh"
 
 #include "params/TimingSimpleCPU.hh"
 
@@ -115,95 +116,9 @@
     };
     FetchTranslation fetchTranslation;
 
-    class DataTranslation : public BaseTLB::Translation
-    {
-      protected:
-        TimingSimpleCPU *cpu;
-        uint8_t *data;
-        uint64_t *res;
-        BaseTLB::Mode mode;
-
-      public:
-        DataTranslation(TimingSimpleCPU *_cpu,
-                uint8_t *_data, uint64_t *_res, BaseTLB::Mode _mode)
-            : cpu(_cpu), data(_data), res(_res), mode(_mode)
-        {
-            assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
-        }
-
-        void
-        finish(Fault fault, RequestPtr req, ThreadContext *tc,
-               BaseTLB::Mode mode)
-        {
-            assert(mode == this->mode);
-            cpu->sendData(fault, req, data, res, mode == BaseTLB::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;
-            BaseTLB::Mode mode;
-
-            WholeTranslationState(RequestPtr req1, RequestPtr req2,
-                    RequestPtr main, uint8_t *data, BaseTLB::Mode mode)
-            {
-                assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
-
-                outstanding = 2;
-                requests[0] = req1;
-                requests[1] = req2;
-                mainReq = main;
-                faults[0] = faults[1] = NoFault;
-                this->data = data;
-                this->mode = mode;
-            }
-        };
-
-        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,
-               BaseTLB::Mode mode)
-        {
-            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->mode == BaseTLB::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 sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
+    void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
+                       uint8_t *data, bool read);
 
     void translationFault(Fault fault);
 
@@ -351,6 +266,12 @@
      */
     void printAddr(Addr a);
 
+    /**
+     * Finish a DTB translation.
+     * @param state The DTB translation state.
+     */
+    virtual void finishTranslation(WholeTranslationState *state);
+
   private:
 
     typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
diff --git a/src/cpu/translation.hh b/src/cpu/translation.hh
--- a/src/cpu/translation.hh
+++ b/src/cpu/translation.hh
@@ -34,6 +34,7 @@
 #define __CPU_TRANSLATION_HH__
 
 #include "sim/tlb.hh"
+#include "cpu/base.hh"
 
 // Forward declaration
 template <class Impl>
@@ -50,13 +51,15 @@
     RequestPtr mainReq;
     RequestPtr sreqLow;
     RequestPtr sreqHigh;
+    uint8_t *data;
     uint64_t *res;
     BaseTLB::Mode mode;
 
     /** Single translation state. */
-    WholeTranslationState(RequestPtr _req, uint64_t *_res, BaseTLB::Mode _mode)
+    WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res,
+                          BaseTLB::Mode _mode)
         : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL),
-          sreqHigh(NULL), res(_res), mode(_mode)
+          sreqHigh(NULL), data(_data), res(_res), mode(_mode)
     {
         faults[0] = faults[1] = NoFault;
         assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
@@ -64,10 +67,10 @@
 
     /** Split translation state. */
     WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow,
-                          RequestPtr _sreqHigh, uint64_t *_res,
+                          RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res,
                           BaseTLB::Mode _mode)
         : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow),
-          sreqHigh(_sreqHigh), res(_res), mode(_mode)
+          sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode)
     {
         faults[0] = faults[1] = NoFault;
         assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
@@ -104,12 +107,24 @@
             return NoFault;
     }
 
+    void
+    setNoFault()
+    {
+        faults[0] = faults[1] = NoFault;
+    }
+
     bool
     isUncacheable() const
     {
         return mainReq->isUncacheable();
     }
 
+    bool
+    isPrefetch() const
+    {
+        return mainReq->isPrefetch();
+    }
+
     Addr
     getPaddr() const
     {
@@ -134,7 +149,7 @@
 };
 
 template <class Impl>
-class DataTranslation : public BaseTLB::Translation
+class DataTranslationInst : public BaseTLB::Translation
 {
   protected:
     typedef BaseDynInst<Impl> DynInst;
@@ -145,13 +160,13 @@
     int index;
 
   public:
-    DataTranslation(DynInstPtr _inst, WholeTranslationState *_state)
+    DataTranslationInst(DynInstPtr _inst, WholeTranslationState *_state)
         : inst(_inst), state(_state), index(0)
     {
     }
 
-    DataTranslation(DynInstPtr _inst, WholeTranslationState *_state,
-                    int _index)
+    DataTranslationInst(DynInstPtr _inst, WholeTranslationState *_state,
+                        int _index)
         : inst(_inst), state(_state), index(_index)
     {
     }
@@ -163,10 +178,44 @@
         assert(state);
         assert(mode == state->mode);
         if (state->finish(fault, index)) {
+            assert(inst);
             inst->finishTranslation(state);
         }
         delete this;
     }
 };
 
+class DataTranslationCpu : public BaseTLB::Translation
+{
+  protected:
+    BaseCPU *cpu;
+    WholeTranslationState *state;
+    int index;
+
+  public:
+    DataTranslationCpu(BaseCPU *_cpu, WholeTranslationState *_state)
+        : cpu(_cpu), state(_state), index(0)
+    {
+    }
+
+    DataTranslationCpu(BaseCPU *_cpu, WholeTranslationState *_state,
+                       int _index)
+        : cpu(_cpu), state(_state), index(_index)
+    {
+    }
+
+    virtual void
+    finish(Fault fault, RequestPtr req, ThreadContext *tc,
+           BaseTLB::Mode mode)
+    {
+        assert(state);
+        assert(mode == state->mode);
+        if (state->finish(fault, index)) {
+            assert(cpu);
+            cpu->finishTranslation(state);
+        }
+        delete this;
+    }
+};
+
 #endif // __CPU_TRANSLATION_HH__

-- 
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.

_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to