CPU: Add readBytes and writeBytes functions to the exec contexts.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 13 Aug 2010 13:16:02 +0000 (06:16 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 13 Aug 2010 13:16:02 +0000 (06:16 -0700)
15 files changed:
src/cpu/base_dyn_inst.hh
src/cpu/exec_context.hh
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/inorder_dyn_inst.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/cache_unit.hh
src/cpu/o3/cpu.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_unit.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh

index a9ba1295840525e795d15a088a04ab37d21a40f2..3ecec0f0cf2dd5e778de5b069fa04403c9e2c7e4 100644 (file)
@@ -120,6 +120,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
     template <class T>
     Fault read(Addr addr, T &data, unsigned flags);
 
+    Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
     /**
      * Does a write to a given address.
      * @param data The data to be written.
@@ -131,6 +133,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
     template <class T>
     Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 
+    Fault writeBytes(uint8_t *data, unsigned size,
+                     Addr addr, unsigned flags, uint64_t *res);
+
     /** Splits a request in two if it crosses a dcache block. */
     void splitRequest(RequestPtr req, RequestPtr &sreqLow,
                       RequestPtr &sreqHigh);
@@ -867,12 +872,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
 };
 
 template<class Impl>
-template<class T>
-inline Fault
-BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
+Fault
+BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
+                             unsigned size, unsigned flags)
 {
     reqMade = true;
-    Request *req = new Request(asid, addr, sizeof(T), flags, this->PC,
+    Request *req = new Request(asid, addr, size, flags, this->PC,
                                thread->contextId(), threadNumber);
 
     Request *sreqLow = NULL;
@@ -889,11 +894,6 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
         effAddrValid = true;
         fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
     } else {
-
-        // Return a fixed value to keep simulation deterministic even
-        // along misspeculated paths.
-        data = (T)-1;
-
         // Commit will have to clean up whatever happened.  Set this
         // instruction as executed.
         this->setExecuted();
@@ -901,7 +901,6 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
 
     if (traceData) {
         traceData->setAddr(addr);
-        traceData->setData(data);
     }
 
     return fault;
@@ -910,15 +909,35 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
 template<class Impl>
 template<class T>
 inline Fault
-BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
+BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
 {
+    Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
+
+    if (fault != NoFault) {
+        // Return a fixed value to keep simulation deterministic even
+        // along misspeculated paths.
+        data = (T)-1;
+    }
+    data = TheISA::gtoh(data);
+
     if (traceData) {
-        traceData->setAddr(addr);
         traceData->setData(data);
     }
 
+    return fault;
+}
+
+template<class Impl>
+Fault
+BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
+                              Addr addr, unsigned flags, uint64_t *res)
+{
+    if (traceData) {
+        traceData->setAddr(addr);
+    }
+
     reqMade = true;
-    Request *req = new Request(asid, addr, sizeof(T), flags, this->PC,
+    Request *req = new Request(asid, addr, size, flags, this->PC,
                                thread->contextId(), threadNumber);
 
     Request *sreqLow = NULL;
@@ -939,6 +958,18 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
     return fault;
 }
 
+template<class Impl>
+template<class T>
+inline Fault
+BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+    if (traceData) {
+        traceData->setData(data);
+    }
+    data = TheISA::htog(data);
+    return writeBytes((uint8_t *)&data, sizeof(T), addr, flags, res);
+}
+
 template<class Impl>
 inline void
 BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow,
index c930b5cce41596876f0ebfc64da051f78dba8fc4..22dffea1cc0b15afb3a46f77a4d10f4b25d58c0a 100644 (file)
@@ -111,12 +111,17 @@ class ExecContext {
     template <class T>
     Fault read(Addr addr, T &data, unsigned flags);
 
+    Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
     /** Writes to an address, creating a memory request with the given
      * flags.  Writes data to memory.  For store conditionals, returns
      * the result of the store in res. */
     template <class T>
     Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 
+    Fault writeBytes(uint8_t *data, unsigned size,
+                     Addr addr, unsigned flags, uint64_t *res);
+
     /** Prefetches an address, creating a memory request with the
      * given flags. */
     void prefetch(Addr addr, unsigned flags);
index 75873d97d63ccf71d2868af2f9fbcf7956be8fb2..059996b0723bc58b780ac1855fd64136975a4d90 100644 (file)
@@ -1518,135 +1518,25 @@ InOrderCPU::getDTBPtr()
     return dtb_res->tlb();
 }
 
-template <class T>
 Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
+InOrderCPU::read(DynInstPtr inst, Addr addr,
+                 uint8_t *data, unsigned size, unsigned flags)
 {
     //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
     //       you want to run w/out caches?
     CacheUnit *cache_res = 
         dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
 
-    return cache_res->read(inst, addr, data, flags);
+    return cache_res->read(inst, addr, data, size, flags);
 }
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags);
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, double &data, unsigned flags)
-{
-    return read(inst, addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, float &data, unsigned flags)
-{
-    return read(inst, addr, *(uint32_t*)&data, flags);
-}
-
-
-template<>
-Fault
-InOrderCPU::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags)
-{
-    return read(inst, addr, (uint32_t&)data, flags);
-}
-
-template <class T>
 Fault
-InOrderCPU::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
-                  uint64_t *write_res)
+InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size,
+                  Addr addr, unsigned flags, uint64_t *write_res)
 {
     //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
     //       you want to run w/out caches?
     CacheUnit *cache_res =
         dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
-    return cache_res->write(inst, data, addr, flags, write_res);
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, Twin32_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, Twin64_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, uint64_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, uint32_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, uint16_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderCPU::write(DynInstPtr inst, uint8_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-InOrderCPU::write(DynInstPtr inst, double data, Addr addr, unsigned flags, 
-                  uint64_t *res)
-{
-    return write(inst, *(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-InOrderCPU::write(DynInstPtr inst, float data, Addr addr, unsigned flags, 
-                  uint64_t *res)
-{
-    return write(inst, *(uint32_t*)&data, addr, flags, res);
-}
-
-
-template<>
-Fault
-InOrderCPU::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, 
-                  uint64_t *res)
-{
-    return write(inst, (uint32_t)data, addr, flags, res);
+    return cache_res->write(inst, data, size, addr, flags, write_res);
 }
index 6676d78cfe03f9bc9accb033c297f2918086afd5..450829e6416d40f2e13c638c996aae94d524270d 100644 (file)
@@ -523,15 +523,14 @@ class InOrderCPU : public BaseCPU
     /** Forwards an instruction read to the appropriate data
      *  resource (indexes into Resource Pool thru "dataPortIdx")
      */
-    template <class T>
-    Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+    Fault read(DynInstPtr inst, Addr addr,
+               uint8_t *data, unsigned size, unsigned flags);
 
     /** Forwards an instruction write. to the appropriate data
      *  resource (indexes into Resource Pool thru "dataPortIdx")
      */
-    template <class T>
-    Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
-                uint64_t *write_res = NULL);
+    Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+                Addr addr, unsigned flags, uint64_t *write_res = NULL);
 
     /** Forwards an instruction prefetch to the appropriate data
      *  resource (indexes into Resource Pool thru "dataPortIdx")
index 13ec7a3fff325bffd81cab5f975a98deb68bf86f..5486dedee1104b633e9c2c5bca5fd3c4401578c5 100644 (file)
@@ -610,6 +610,13 @@ InOrderDynInst::deallocateContext(int thread_num)
     this->cpu->deallocateContext(thread_num);
 }
 
+Fault
+InOrderDynInst::readBytes(Addr addr, uint8_t *data,
+                          unsigned size, unsigned flags)
+{
+    return cpu->read(this, addr, data, size, flags);
+}
+
 template<class T>
 inline Fault
 InOrderDynInst::read(Addr addr, T &data, unsigned flags)
@@ -618,8 +625,11 @@ InOrderDynInst::read(Addr addr, T &data, unsigned flags)
         traceData->setAddr(addr);
         traceData->setData(data);
     }
-
-    return cpu->read(this, addr, data, flags);
+    Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
+    data = TheISA::gtoh(data);
+    if (traceData)
+        traceData->setData(data);
+    return fault;
 }
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -663,20 +673,29 @@ InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags)
     return read(addr, (uint32_t&)data, flags);
 }
 
+Fault
+InOrderDynInst::writeBytes(uint8_t *data, unsigned size,
+                           Addr addr, unsigned flags, uint64_t *res)
+{
+    assert(sizeof(storeData) >= size);
+    memcpy(&storeData, data, size);
+    return cpu->write(this, (uint8_t *)&storeData, size, addr, flags, res);
+}
+
 template<class T>
 inline Fault
 InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
 {
-    if (traceData) {
-        traceData->setAddr(addr);
-        traceData->setData(data);
-    }
-
     storeData  = data;
 
     DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
             threadNumber, seqNum, storeData);
-    return cpu->write(this, data, addr, flags, res);
+    if (traceData) {
+        traceData->setAddr(addr);
+        traceData->setData(data);
+    }
+    storeData = TheISA::htog(data);
+    return writeBytes((uint8_t*)&data, sizeof(T), addr, flags, res);
 }
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
index ffb795e1e4a7e85a9425702e1709fb0a96b58633..0d42f46963120e37430ac507d466208ae57fa5e6 100644 (file)
@@ -334,7 +334,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
 
     PacketDataPtr splitMemData;
     RequestPtr splitMemReq;    
-    int splitTotalSize;
+    int totalSize;
     int split2ndSize;
     Addr split2ndAddr;
     bool split2ndAccess;
@@ -637,6 +637,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     template <class T>
     Fault read(Addr addr, T &data, unsigned flags);
 
+    Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
     /**
      * Does a write to a given address.
      * @param data The data to be written.
@@ -649,6 +651,9 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     Fault write(T data, Addr addr, unsigned flags,
                         uint64_t *res);
 
+    Fault writeBytes(uint8_t *data, unsigned size,
+                     Addr addr, unsigned flags, uint64_t *res);
+
     /** Initiates a memory access - Calculate Eff. Addr & Initiate Memory
      *  Access Only valid for memory operations.
      */
index 2ab9e889ec6ed3815bf303c2bb275741ca51ed4c..4d21f527eee4c804f3978265bf488935f38b73d8 100644 (file)
@@ -443,9 +443,9 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
     return cache_req->fault;
 }
 
-template <class T>
 Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
+CacheUnit::read(DynInstPtr inst, Addr addr,
+                uint8_t *data, unsigned size, unsigned flags)
 {
     CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
     assert(cache_req && "Can't Find Instruction for Read!");
@@ -454,14 +454,15 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
     unsigned blockSize = this->cachePort->peerBlockSize();
 
     //The size of the data we're trying to read.
-    int dataSize = sizeof(T);
+    int fullSize = size;
+    inst->totalSize = size;
 
     if (inst->traceData) {
         inst->traceData->setAddr(addr);
     }
 
     if (inst->split2ndAccess) {     
-        dataSize = inst->split2ndSize;
+        size = inst->split2ndSize;
         cache_req->splitAccess = true;        
         cache_req->split2ndAccess = true;
         
@@ -473,7 +474,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
 
     //The address of the second part of this access if it needs to be split
     //across a cache line boundary.
-    Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+    Addr secondAddr = roundDown(addr + size - 1, blockSize);
 
     
     if (secondAddr > addr && !inst->split2ndAccess) {
@@ -483,8 +484,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
         // Save All "Total" Split Information
         // ==============================
         inst->splitInst = true;        
-        inst->splitMemData = new uint8_t[dataSize];
-        inst->splitTotalSize = dataSize;
+        inst->splitMemData = new uint8_t[size];
         
         if (!inst->splitInstSked) {
             // Schedule Split Read/Complete for Instruction
@@ -517,22 +517,22 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
 
         // Split Information for First Access
         // ==============================
-        dataSize = secondAddr - addr;
+        size = secondAddr - addr;
         cache_req->splitAccess = true;
 
         // Split Information for Second Access
         // ==============================
-        inst->split2ndSize = addr + sizeof(T) - secondAddr;
+        inst->split2ndSize = addr + fullSize - secondAddr;
         inst->split2ndAddr = secondAddr;            
-        inst->split2ndDataPtr = inst->splitMemData + dataSize;            
+        inst->split2ndDataPtr = inst->splitMemData + size;
         inst->split2ndFlags = flags;        
     }
     
-    doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Read);
+    doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Read);
 
     if (cache_req->fault == NoFault) {
         if (!cache_req->splitAccess) {            
-            cache_req->reqData = new uint8_t[dataSize];
+            cache_req->reqData = new uint8_t[size];
             doCacheAccess(inst, NULL);
         } else {
             if (!inst->split2ndAccess) {                
@@ -548,10 +548,9 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
     return cache_req->fault;
 }
 
-template <class T>
 Fault
-CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
-            uint64_t *write_res)
+CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
+                 Addr addr, unsigned flags, uint64_t *write_res)
 {
     CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
     assert(cache_req && "Can't Find Instruction for Write!");
@@ -559,16 +558,16 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
     // The block size of our peer
     unsigned blockSize = this->cachePort->peerBlockSize();
 
-    //The size of the data we're trying to read.
-    int dataSize = sizeof(T);
+    //The size of the data we're trying to write.
+    int fullSize = size;
+    inst->totalSize = size;
 
     if (inst->traceData) {
         inst->traceData->setAddr(addr);
-        inst->traceData->setData(data);
     }
 
     if (inst->split2ndAccess) {     
-        dataSize = inst->split2ndSize;
+        size = inst->split2ndSize;
         cache_req->splitAccess = true;        
         cache_req->split2ndAccess = true;
         
@@ -579,7 +578,7 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
 
     //The address of the second part of this access if it needs to be split
     //across a cache line boundary.
-    Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+    Addr secondAddr = roundDown(addr + size - 1, blockSize);
 
     if (secondAddr > addr && !inst->split2ndAccess) {
             
@@ -589,7 +588,6 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
         // Save All "Total" Split Information
         // ==============================
         inst->splitInst = true;        
-        inst->splitTotalSize = dataSize;
 
         if (!inst->splitInstSked) {
             // Schedule Split Read/Complete for Instruction
@@ -624,25 +622,25 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
 
         // Split Information for First Access
         // ==============================
-        dataSize = secondAddr - addr;
+        size = secondAddr - addr;
         cache_req->splitAccess = true;
 
         // Split Information for Second Access
         // ==============================
-        inst->split2ndSize = addr + sizeof(T) - secondAddr;
+        inst->split2ndSize = addr + fullSize - secondAddr;
         inst->split2ndAddr = secondAddr;            
         inst->split2ndStoreDataPtr = &cache_req->inst->storeData;
-        inst->split2ndStoreDataPtr += dataSize;            
+        inst->split2ndStoreDataPtr += size;
         inst->split2ndFlags = flags;        
         inst->splitInstSked = true;
     }    
         
-    doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Write);
+    doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Write);
 
     if (cache_req->fault == NoFault) {
         if (!cache_req->splitAccess) {            
             // Remove this line since storeData is saved in INST?
-            cache_req->reqData = new uint8_t[dataSize];
+            cache_req->reqData = new uint8_t[size];
             doCacheAccess(inst, write_res);
         } else {            
             doCacheAccess(inst, write_res, cache_req);            
@@ -729,8 +727,8 @@ CacheUnit::execute(int slot_num)
                 cache_req->inst->split2ndAddr);
         inst->split2ndAccess = true;
         assert(inst->split2ndAddr != 0);
-        read(inst, inst->split2ndAddr, inst->split2ndData,
-             inst->split2ndFlags);
+        read(inst, inst->split2ndAddr, &inst->split2ndData,
+             inst->totalSize, inst->split2ndFlags);
         break;
 
       case InitSecondSplitWrite:
@@ -741,8 +739,8 @@ CacheUnit::execute(int slot_num)
 
         inst->split2ndAccess = true;
         assert(inst->split2ndAddr != 0);
-        write(inst, inst->split2ndAddr, inst->split2ndData,
-              inst->split2ndFlags, NULL);
+        write(inst, &inst->split2ndData, inst->totalSize,
+              inst->split2ndAddr, inst->split2ndFlags, NULL);
         break;
 
 
@@ -1075,7 +1073,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
                 if (inst->splitFinishCnt == 2) {
                     cache_req->memReq->setVirt(0/*inst->tid*/, 
                                                inst->getMemAddr(),
-                                               inst->splitTotalSize,
+                                               inst->totalSize,
                                                0,
                                                0);
                     
@@ -1301,113 +1299,3 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
         freeSlot(slot_remove_list[i]);
 }
 
-// Extra Template Definitions
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags);
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, double &data, unsigned flags)
-{
-    return read(inst, addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, float &data, unsigned flags)
-{
-    return read(inst, addr, *(uint32_t*)&data, flags);
-}
-
-
-template<>
-Fault
-CacheUnit::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags)
-{
-    return read(inst, addr, (uint32_t&)data, flags);
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, Twin32_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, Twin64_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, uint64_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, uint32_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, uint16_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-CacheUnit::write(DynInstPtr inst, uint8_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CacheUnit::write(DynInstPtr inst, double data, Addr addr, unsigned flags, 
-                 uint64_t *res)
-{
-    return write(inst, *(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags, 
-                 uint64_t *res)
-{
-    return write(inst, *(uint32_t*)&data, addr, flags, res);
-}
-
-
-template<>
-Fault
-CacheUnit::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, 
-                 uint64_t *res)
-{
-    return write(inst, (uint32_t)data, addr, flags, res);
-}
-
index 177f815596a99609a1480810717636b4e16a0ce0..2f369db7c44a47a55ce4876b8e615afebba058b7 100644 (file)
@@ -161,12 +161,11 @@ class CacheUnit : public Resource
     /** Returns a specific port. */
     Port *getPort(const std::string &if_name, int idx);
     
-    template <class T>
-    Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+    Fault read(DynInstPtr inst, Addr addr,
+               uint8_t *data, unsigned size, unsigned flags);
 
-    template <class T>
-    Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
-                        uint64_t *res);
+    Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+                Addr addr, unsigned flags, uint64_t *res);
 
     Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
                       int flags,  TheISA::TLB::Mode tlb_mode);
index 82d4ca25b677a19b7fbeb51cf54c928414c94d3b..a102a21f53239779ff52e0d83f2ac5f635e62741 100644 (file)
@@ -702,18 +702,16 @@ class FullO3CPU : public BaseO3CPU
     std::vector<ThreadID> tids;
 
     /** CPU read function, forwards read to LSQ. */
-    template <class T>
     Fault read(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
-               T &data, int load_idx)
+               uint8_t *data, int load_idx)
     {
         return this->iew.ldstQueue.read(req, sreqLow, sreqHigh,
                                         data, load_idx);
     }
 
     /** CPU write function, forwards write to LSQ. */
-    template <class T>
     Fault write(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
-                T &data, int store_idx)
+                uint8_t *data, int store_idx)
     {
         return this->iew.ldstQueue.write(req, sreqLow, sreqHigh,
                                          data, store_idx);
index 7a7ea917f6aa32245318d3bc735f2064840cc614..0ad5d51c2795ad163a24dc0491786c761248e7a0 100644 (file)
@@ -273,16 +273,14 @@ class LSQ {
     /** Executes a read operation, using the load specified at the load
      * index.
      */
-    template <class T>
     Fault read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
-               T &data, int load_idx);
+               uint8_t *data, int load_idx);
 
     /** Executes a store operation, using the store specified at the store
      * index.
      */
-    template <class T>
     Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
-                T &data, int store_idx);
+                uint8_t *data, int store_idx);
 
     /** The CPU pointer. */
     O3CPU *cpu;
@@ -371,10 +369,9 @@ class LSQ {
 };
 
 template <class Impl>
-template <class T>
 Fault
 LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
-                T &data, int load_idx)
+                uint8_t *data, int load_idx)
 {
     ThreadID tid = req->threadId();
 
@@ -382,10 +379,9 @@ LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
 }
 
 template <class Impl>
-template <class T>
 Fault
 LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
-                 T &data, int store_idx)
+                 uint8_t *data, int store_idx)
 {
     ThreadID tid = req->threadId();
 
index c19a368d119c0d70e29236faff26067b1dffc096..10b1ed11a0cd99c16d562312d54b364f0a29d839 100644 (file)
@@ -474,14 +474,12 @@ class LSQUnit {
 
   public:
     /** Executes the load at the given index. */
-    template <class T>
-    Fault read(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
-               int load_idx);
+    Fault read(Request *req, Request *sreqLow, Request *sreqHigh,
+               uint8_t *data, int load_idx);
 
     /** Executes the store at the given index. */
-    template <class T>
-    Fault write(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
-                int store_idx);
+    Fault write(Request *req, Request *sreqLow, Request *sreqHigh,
+                uint8_t *data, int store_idx);
 
     /** Returns the index of the head load instruction. */
     int getLoadHead() { return loadHead; }
@@ -514,10 +512,9 @@ class LSQUnit {
 };
 
 template <class Impl>
-template <class T>
 Fault
 LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
-                    T &data, int load_idx)
+                    uint8_t *data, int load_idx)
 {
     DynInstPtr load_inst = loadQueue[load_idx];
 
@@ -605,7 +602,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
             // Get shift amount for offset into the store's data.
             int shift_amt = req->getVaddr() & (store_size - 1);
 
-            memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
+            memcpy(data, storeQueue[store_idx].data + shift_amt,
+                   req->getSize());
 
             assert(!load_inst->memData);
             load_inst->memData = new uint8_t[64];
@@ -809,10 +807,9 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
 }
 
 template <class Impl>
-template <class T>
 Fault
 LSQUnit<Impl>::write(Request *req, Request *sreqLow, Request *sreqHigh,
-                     T &data, int store_idx)
+                     uint8_t *data, int store_idx)
 {
     assert(storeQueue[store_idx].inst);
 
@@ -824,17 +821,17 @@ LSQUnit<Impl>::write(Request *req, Request *sreqLow, Request *sreqHigh,
     storeQueue[store_idx].req = req;
     storeQueue[store_idx].sreqLow = sreqLow;
     storeQueue[store_idx].sreqHigh = sreqHigh;
-    storeQueue[store_idx].size = sizeof(T);
+    unsigned size = req->getSize();
+    storeQueue[store_idx].size = size;
+    assert(size <= sizeof(storeQueue[store_idx].data));
 
     // Split stores can only occur in ISAs with unaligned memory accesses.  If
     // a store request has been split, sreqLow and sreqHigh will be non-null.
     if (TheISA::HasUnalignedMemAcc && sreqLow) {
         storeQueue[store_idx].isSplit = true;
     }
-    assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
 
-    T gData = htog(data);
-    memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
+    memcpy(storeQueue[store_idx].data, data, size);
 
     // This function only writes the data to the store queue, so no fault
     // can happen here.
index f8819c7349a52d914f905b9dd0986251d16078e4..8ee91758f175ac19f2031ecec7eb7f6a422286ee 100644 (file)
@@ -294,9 +294,9 @@ AtomicSimpleCPU::suspendContext(int thread_num)
 }
 
 
-template <class T>
 Fault
-AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
+AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data,
+                           unsigned size, unsigned flags)
 {
     // use the CPU's statically allocated read request and packet objects
     Request *req = &data_read_req;
@@ -308,21 +308,19 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
     //The block size of our peer.
     unsigned blockSize = dcachePort.peerBlockSize();
     //The size of the data we're trying to read.
-    int dataSize = sizeof(T);
-
-    uint8_t * dataPtr = (uint8_t *)&data;
+    int fullSize = size;
 
     //The address of the second part of this access if it needs to be split
     //across a cache line boundary.
-    Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+    Addr secondAddr = roundDown(addr + size - 1, blockSize);
 
-    if(secondAddr > addr)
-        dataSize = secondAddr - addr;
+    if (secondAddr > addr)
+        size = secondAddr - addr;
 
     dcache_latency = 0;
 
-    while(1) {
-        req->setVirt(0, addr, dataSize, flags, thread->readPC());
+    while (1) {
+        req->setVirt(0, addr, size, flags, thread->readPC());
 
         // translate to physical address
         Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
@@ -332,7 +330,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
             Packet pkt = Packet(req,
                     req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
                     Packet::Broadcast);
-            pkt.dataStatic(dataPtr);
+            pkt.dataStatic(data);
 
             if (req->isMmapedIpr())
                 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
@@ -363,10 +361,6 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
         //If we don't need to access a second cache line, stop now.
         if (secondAddr <= addr)
         {
-            data = gtoh(data);
-            if (traceData) {
-                traceData->setData(data);
-            }
             if (req->isLocked() && fault == NoFault) {
                 assert(!locked);
                 locked = true;
@@ -379,14 +373,30 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
          */
 
         //Move the pointer we're reading into to the correct location.
-        dataPtr += dataSize;
+        data += size;
         //Adjust the size to get the remaining bytes.
-        dataSize = addr + sizeof(T) - secondAddr;
+        size = addr + fullSize - secondAddr;
         //And access the right address.
         addr = secondAddr;
     }
 }
 
+
+template <class T>
+Fault
+AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
+{
+    uint8_t *dataPtr = (uint8_t *)&data;
+    memset(dataPtr, 0, sizeof(data));
+    Fault fault = readBytes(addr, dataPtr, sizeof(data), flags);
+    if (fault == NoFault) {
+        data = gtoh(data);
+        if (traceData)
+            traceData->setData(data);
+    }
+    return fault;
+}
+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
 template
@@ -438,38 +448,33 @@ AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
 }
 
 
-template <class T>
 Fault
-AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size,
+                            Addr addr, unsigned flags, uint64_t *res)
 {
     // use the CPU's statically allocated write request and packet objects
     Request *req = &data_write_req;
 
     if (traceData) {
         traceData->setAddr(addr);
-        traceData->setData(data);
     }
 
-    data = htog(data);
-
     //The block size of our peer.
     unsigned blockSize = dcachePort.peerBlockSize();
     //The size of the data we're trying to read.
-    int dataSize = sizeof(T);
-
-    uint8_t * dataPtr = (uint8_t *)&data;
+    int fullSize = size;
 
     //The address of the second part of this access if it needs to be split
     //across a cache line boundary.
-    Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+    Addr secondAddr = roundDown(addr + size - 1, blockSize);
 
     if(secondAddr > addr)
-        dataSize = secondAddr - addr;
+        size = secondAddr - addr;
 
     dcache_latency = 0;
 
     while(1) {
-        req->setVirt(0, addr, dataSize, flags, thread->readPC());
+        req->setVirt(0, addr, size, flags, thread->readPC());
 
         // translate to physical address
         Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
@@ -492,7 +497,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
 
             if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
                 Packet pkt = Packet(req, cmd, Packet::Broadcast);
-                pkt.dataStatic(dataPtr);
+                pkt.dataStatic(data);
 
                 if (req->isMmapedIpr()) {
                     dcache_latency +=
@@ -508,7 +513,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
 
                 if (req->isSwap()) {
                     assert(res);
-                    *res = pkt.get<T>();
+                    memcpy(res, pkt.getPtr<uint8_t>(), fullSize);
                 }
             }
 
@@ -537,15 +542,32 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
          */
 
         //Move the pointer we're reading into to the correct location.
-        dataPtr += dataSize;
+        data += size;
         //Adjust the size to get the remaining bytes.
-        dataSize = addr + sizeof(T) - secondAddr;
+        size = addr + fullSize - secondAddr;
         //And access the right address.
         addr = secondAddr;
     }
 }
 
 
+template <class T>
+Fault
+AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+    uint8_t *dataPtr = (uint8_t *)&data;
+    if (traceData)
+        traceData->setData(data);
+    data = htog(data);
+
+    Fault fault = writeBytes(dataPtr, sizeof(data), addr, flags, res);
+    if (fault == NoFault && data_write_req.isSwap()) {
+        *res = gtoh((T)*res);
+    }
+    return fault;
+}
+
+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
 template
index 2a66e93411cea9da8fee978507a8451669568356..5ec1970e70de39b3d8f899800ded62df6f5b65d3 100644 (file)
@@ -134,9 +134,14 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     template <class T>
     Fault read(Addr addr, T &data, unsigned flags);
 
+    Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
     template <class T>
     Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 
+    Fault writeBytes(uint8_t *data, unsigned size,
+                     Addr addr, unsigned flags, uint64_t *res);
+
     /**
      * Print state of address in memory system via PrintReq (for
      * debugging).
index b8fc5ab84614554330f6b5025bd3575a3dd6cf0a..1670cb06695233ad7e60f3d717bb942aa0a0c87f 100644 (file)
@@ -414,26 +414,25 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
     pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
 }
 
-template <class T>
 Fault
-TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
+TimingSimpleCPU::readBytes(Addr addr, uint8_t *data,
+                           unsigned size, unsigned flags)
 {
     Fault fault;
     const int asid = 0;
     const ThreadID tid = 0;
     const Addr pc = thread->readPC();
     unsigned block_size = dcachePort.peerBlockSize();
-    int data_size = sizeof(T);
     BaseTLB::Mode mode = BaseTLB::Read;
 
     if (traceData) {
         traceData->setAddr(addr);
     }
 
-    RequestPtr req  = new Request(asid, addr, data_size,
+    RequestPtr req  = new Request(asid, addr, size,
                                   flags, pc, _cpuId, tid);
 
-    Addr split_addr = roundDown(addr + data_size - 1, block_size);
+    Addr split_addr = roundDown(addr + size - 1, block_size);
     assert(split_addr <= addr || split_addr - addr < block_size);
 
     _status = DTBWaitResponse;
@@ -443,7 +442,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
         req->splitOnVaddr(split_addr, req1, req2);
 
         WholeTranslationState *state =
-            new WholeTranslationState(req, req1, req2, (uint8_t *)(new T),
+            new WholeTranslationState(req, req1, req2, new uint8_t[size],
                                       NULL, mode);
         DataTranslation<TimingSimpleCPU> *trans1 =
             new DataTranslation<TimingSimpleCPU>(this, state, 0);
@@ -454,7 +453,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
         thread->dtb->translateTiming(req2, tc, trans2, mode);
     } else {
         WholeTranslationState *state =
-            new WholeTranslationState(req, (uint8_t *)(new T), NULL, mode);
+            new WholeTranslationState(req, new uint8_t[size], NULL, mode);
         DataTranslation<TimingSimpleCPU> *translation
             = new DataTranslation<TimingSimpleCPU>(this, state);
         thread->dtb->translateTiming(req, tc, translation, mode);
@@ -463,6 +462,13 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
     return NoFault;
 }
 
+template <class T>
+Fault
+TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
+{
+    return readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
+}
+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
 template
@@ -532,30 +538,26 @@ TimingSimpleCPU::handleWritePacket()
     return dcache_pkt == NULL;
 }
 
-template <class T>
 Fault
-TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size,
+                                 Addr addr, unsigned flags, uint64_t *res)
 {
     const int asid = 0;
     const ThreadID tid = 0;
     const Addr pc = thread->readPC();
     unsigned block_size = dcachePort.peerBlockSize();
-    int data_size = sizeof(T);
     BaseTLB::Mode mode = BaseTLB::Write;
 
     if (traceData) {
         traceData->setAddr(addr);
-        traceData->setData(data);
     }
 
-    RequestPtr req = new Request(asid, addr, data_size,
+    RequestPtr req = new Request(asid, addr, size,
                                  flags, pc, _cpuId, tid);
 
-    Addr split_addr = roundDown(addr + data_size - 1, block_size);
+    Addr split_addr = roundDown(addr + size - 1, block_size);
     assert(split_addr <= addr || split_addr - addr < block_size);
 
-    T *dataP = new T;
-    *dataP = TheISA::htog(data);
     _status = DTBWaitResponse;
     if (split_addr > addr) {
         RequestPtr req1, req2;
@@ -563,8 +565,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         req->splitOnVaddr(split_addr, req1, req2);
 
         WholeTranslationState *state =
-            new WholeTranslationState(req, req1, req2, (uint8_t *)dataP,
-                                      res, mode);
+            new WholeTranslationState(req, req1, req2, data, res, mode);
         DataTranslation<TimingSimpleCPU> *trans1 =
             new DataTranslation<TimingSimpleCPU>(this, state, 0);
         DataTranslation<TimingSimpleCPU> *trans2 =
@@ -574,7 +575,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         thread->dtb->translateTiming(req2, tc, trans2, mode);
     } else {
         WholeTranslationState *state =
-            new WholeTranslationState(req, (uint8_t *)dataP, res, mode);
+            new WholeTranslationState(req, data, res, mode);
         DataTranslation<TimingSimpleCPU> *translation =
             new DataTranslation<TimingSimpleCPU>(this, state);
         thread->dtb->translateTiming(req, tc, translation, mode);
@@ -584,6 +585,28 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
     return NoFault;
 }
 
+Fault
+TimingSimpleCPU::writeBytes(uint8_t *data, unsigned size,
+                            Addr addr, unsigned flags, uint64_t *res)
+{
+    uint8_t *newData = new uint8_t[size];
+    memcpy(newData, data, size);
+    return writeTheseBytes(newData, size, addr, flags, res);
+}
+
+template <class T>
+Fault
+TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+    if (traceData) {
+        traceData->setData(data);
+    }
+    T *dataP = new T;
+    *dataP = TheISA::htog(data);
+
+    return writeTheseBytes((uint8_t *)dataP, sizeof(T), addr, flags, res);
+}
+
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 template
index 62c105418f125aafb7ba8a9096679228f990384e..65cbe309897514766ca6a1325f0db98cf04938ca 100644 (file)
@@ -251,9 +251,14 @@ class TimingSimpleCPU : public BaseSimpleCPU
     template <class T>
     Fault read(Addr addr, T &data, unsigned flags);
 
+    Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
     template <class T>
     Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 
+    Fault writeBytes(uint8_t *data, unsigned size,
+                     Addr addr, unsigned flags, uint64_t *res);
+
     void fetch();
     void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
     void completeIfetch(PacketPtr );
@@ -274,6 +279,11 @@ class TimingSimpleCPU : public BaseSimpleCPU
 
   private:
 
+    // The backend for writeBytes and write. It's the same as writeBytes, but
+    // doesn't make a copy of data.
+    Fault writeTheseBytes(uint8_t *data, unsigned size,
+                          Addr addr, unsigned flags, uint64_t *res);
+
     typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
     FetchEvent fetchEvent;