More cache fixes. Atomic coherence now works as well.
authorRon Dreslinski <rdreslin@umich.edu>
Wed, 11 Oct 2006 22:28:33 +0000 (18:28 -0400)
committerRon Dreslinski <rdreslin@umich.edu>
Wed, 11 Oct 2006 22:28:33 +0000 (18:28 -0400)
src/cpu/memtest/memtest.cc:
src/cpu/memtest/memtest.hh:
    Make Memtester able to test atomic as well
src/mem/bus.cc:
src/mem/bus.hh:
    Handle atomic snoops properly for cache->cache transfers
src/mem/cache/cache_impl.hh:
    Debug output.
    Clean up memleak in atomic mode.
    Set hitLatency.
    Still need to send back reasonable number for atomic return value.
src/mem/packet.cc:
    Add command strings for new commands
src/python/m5/objects/MemTest.py:
    Add param to test atomic memory.

--HG--
extra : convert_revision : 43f880e29215776167c16ea90793ebf8122c785b

src/cpu/memtest/memtest.cc
src/cpu/memtest/memtest.hh
src/mem/bus.cc
src/mem/bus.hh
src/mem/cache/cache_impl.hh
src/mem/packet.cc
src/python/m5/objects/MemTest.py

index 127cad414a63e860aec75a32aca83a9cd3ec9804..f42f0f8e200e671bf16e483780a6fac2e8e0b99e 100644 (file)
@@ -72,6 +72,9 @@ void
 MemTest::CpuPort::recvFunctional(Packet *pkt)
 {
     //Do nothing if we see one come through
+    if (curTick != 0)//Supress warning durring initialization
+        warn("Functional Writes not implemented in MemTester\n");
+    //Need to find any response values that intersect and update
     return;
 }
 
@@ -90,6 +93,20 @@ MemTest::CpuPort::recvRetry()
     memtest->doRetry();
 }
 
+void
+MemTest::sendPkt(Packet *pkt) {
+    if (atomic) {
+        cachePort.sendAtomic(pkt);
+        pkt->makeAtomicResponse();
+        completeRequest(pkt);
+    }
+    else if (!cachePort.sendTiming(pkt)) {
+        accessRetry = true;
+        retryPkt = pkt;
+    }
+
+}
+
 MemTest::MemTest(const string &name,
 //              MemInterface *_cache_interface,
 //              PhysicalMemory *main_mem,
@@ -102,7 +119,8 @@ MemTest::MemTest(const string &name,
                  unsigned _percentSourceUnaligned,
                  unsigned _percentDestUnaligned,
                  Addr _traceAddr,
-                 Counter _max_loads)
+                 Counter _max_loads,
+                 bool _atomic)
     : MemObject(name),
       tickEvent(this),
       cachePort("test", this),
@@ -118,7 +136,8 @@ MemTest::MemTest(const string &name,
       nextProgressMessage(_progressInterval),
       percentSourceUnaligned(_percentSourceUnaligned),
       percentDestUnaligned(percentDestUnaligned),
-      maxLoads(_max_loads)
+      maxLoads(_max_loads),
+      atomic(_atomic)
 {
     vector<string> cmd;
     cmd.push_back("/bin/ls");
@@ -368,10 +387,7 @@ MemTest::tick()
             completeRequest(pkt);
         } else {
 //         req->completionEvent = new MemCompleteEvent(req, result, this);
-            if (!cachePort.sendTiming(pkt)) {
-                accessRetry = true;
-                retryPkt = pkt;
-            }
+            sendPkt(pkt);
         }
     } else {
         // write
@@ -406,13 +422,10 @@ MemTest::tick()
 
         if (probe) {
             cachePort.sendFunctional(pkt);
-//         completeRequest(req, NULL);
+            completeRequest(pkt);
         } else {
 //         req->completionEvent = new MemCompleteEvent(req, NULL, this);
-            if (!cachePort.sendTiming(pkt)) {
-                accessRetry = true;
-                retryPkt = pkt;
-            }
+            sendPkt(pkt);
         }
     }
 /*    else {
@@ -484,6 +497,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
     Param<unsigned> percent_dest_unaligned;
     Param<Addr> trace_addr;
     Param<Counter> max_loads;
+    Param<bool> atomic;
 
 END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
 
@@ -503,7 +517,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
     INIT_PARAM(percent_dest_unaligned,
                "percent of copy dest address that are unaligned"),
     INIT_PARAM(trace_addr, "address to trace"),
-    INIT_PARAM(max_loads, "terminate when we have reached this load count")
+                              INIT_PARAM(max_loads, "terminate when we have reached this load count"),
+    INIT_PARAM(atomic, "Is the tester testing atomic mode (or timing)")
 
 END_INIT_SIM_OBJECT_PARAMS(MemTest)
 
@@ -514,7 +529,7 @@ CREATE_SIM_OBJECT(MemTest)
                        /*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/
                        percent_uncacheable, progress_interval,
                        percent_source_unaligned, percent_dest_unaligned,
-                       trace_addr, max_loads);
+                       trace_addr, max_loads, atomic);
 }
 
 REGISTER_SIM_OBJECT("MemTest", MemTest)
index 87ecc6de3d36bb900b88e2d420b0a21ac5b5a66d..5de41f0d8a1acf07432d608e573ccc93ddaa1fb5 100644 (file)
@@ -61,7 +61,8 @@ class MemTest : public MemObject
             unsigned _percentSourceUnaligned,
             unsigned _percentDestUnaligned,
             Addr _traceAddr,
-            Counter _max_loads);
+            Counter _max_loads,
+            bool _atomic);
 
     virtual void init();
 
@@ -175,6 +176,9 @@ class MemTest : public MemObject
 
     uint64_t numReads;
     uint64_t maxLoads;
+
+    bool atomic;
+
     Stats::Scalar<> numReadsStat;
     Stats::Scalar<> numWritesStat;
     Stats::Scalar<> numCopiesStat;
@@ -182,6 +186,8 @@ class MemTest : public MemObject
     // called by MemCompleteEvent::process()
     void completeRequest(Packet *pkt);
 
+    void sendPkt(Packet *pkt);
+
     void doRetry();
 
     friend class MemCompleteEvent;
index 3998666c7c6ef69de2952f91f376857e36a82dad..b34944ed70c83dbac28c14de2144b0566b122633 100644 (file)
@@ -293,16 +293,22 @@ Bus::findSnoopPorts(Addr addr, int id)
     return ports;
 }
 
-void
+Tick
 Bus::atomicSnoop(Packet *pkt)
 {
     std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+    Tick response_time = 0;
 
     while (!ports.empty())
     {
-        interfaces[ports.back()]->sendAtomic(pkt);
+        Tick response = interfaces[ports.back()]->sendAtomic(pkt);
+        if (response) {
+            assert(!response_time);  //Multiple responders
+            response_time = response;
+        }
         ports.pop_back();
     }
+    return response_time;
 }
 
 void
@@ -341,8 +347,11 @@ Bus::recvAtomic(Packet *pkt)
     DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
             pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
     assert(pkt->getDest() == Packet::Broadcast);
-    atomicSnoop(pkt);
-    return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
+    Tick snoopTime = atomicSnoop(pkt);
+    if (snoopTime)
+        return snoopTime;  //Snoop satisfies it
+    else
+        return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
 }
 
 /** Function called by the port when the bus is receiving a Functional
index 3d0d07a7f03e121aa894983ac75b79e06f95254e..a168c3c4992de89927ac9a5796fa39e334b786a6 100644 (file)
@@ -107,7 +107,7 @@ class Bus : public MemObject
     std::vector<int> findSnoopPorts(Addr addr, int id);
 
     /** Snoop all relevant ports atomicly. */
-    void atomicSnoop(Packet *pkt);
+    Tick atomicSnoop(Packet *pkt);
 
     /** Snoop all relevant ports functionally. */
     void functionalSnoop(Packet *pkt);
index 58eb0bdbcf31494bf76442be8a76bdc1694d111a..a68418f2445c1a1785a1feb1f18f5210da163efc 100644 (file)
@@ -100,7 +100,7 @@ doAtomicAccess(Packet *pkt, bool isCpuSide)
         if (pkt->isResponse())
             handleResponse(pkt);
         else
-            snoopProbe(pkt);
+            return snoopProbe(pkt);
     }
     //Fix this timing info
     return hitLatency;
@@ -148,7 +148,8 @@ Cache(const std::string &_name,
       prefetchAccess(params.prefetchAccess),
       tags(params.tags), missQueue(params.missQueue),
       coherence(params.coherence), prefetcher(params.prefetcher),
-      doCopy(params.doCopy), blockOnCopy(params.blockOnCopy)
+      doCopy(params.doCopy), blockOnCopy(params.blockOnCopy),
+      hitLatency(params.hitLatency)
 {
 //FIX BUS POINTERS
 //    if (params.in == NULL) {
@@ -284,8 +285,9 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, bool
             BlkType *blk = tags->findBlock(pkt);
             CacheBlk::State old_state = (blk) ? blk->status : 0;
             CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
-            DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
-                    pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+            if (old_state != new_state)
+                DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+                        pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
             //Set the state on the upgrade
             memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
             PacketList writebacks;
@@ -324,8 +326,9 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(Packet * &pkt)
             CacheBlk::State old_state = (blk) ? blk->status : 0;
             PacketList writebacks;
             CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
-            DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
-                    pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+            if (old_state != new_state)
+                DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+                        pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
             blk = tags->handleFill(blk, (MSHR*)pkt->senderState,
                                    new_state, writebacks, pkt);
             while (!writebacks.empty()) {
@@ -531,6 +534,10 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, CachePort
     int lat;
     BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update);
 
+    DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
+            pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
+            pkt->getAddr() & ~((Addr)blkSize - 1));
+
     if (!blk) {
         // Need to check for outstanding misses and writes
         Addr blk_addr = pkt->getAddr() & ~(blkSize - 1);
@@ -637,6 +644,11 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, CachePort
 
                 busPkt->time = curTick;
 
+                DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n",
+                        busPkt->cmdString(),
+                        busPkt->getAddr() & (((ULL(1))<<48)-1),
+                        busPkt->getAddr() & ~((Addr)blkSize - 1));
+
                 lat = memSidePort->sendAtomic(busPkt);
 
                 //Be sure to flip the response to a request for coherence
@@ -652,13 +664,26 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, CachePort
 */             misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
 
                 CacheBlk::State old_state = (blk) ? blk->status : 0;
+                CacheBlk::State new_state = coherence->getNewState(busPkt, old_state);
+                    DPRINTF(Cache, "Receive response:%s for blk addr %x in state %i\n",
+                            busPkt->cmdString(),
+                            busPkt->getAddr() & (((ULL(1))<<48)-1), old_state);
+                if (old_state != new_state)
+                    DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+                            busPkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+
                 tags->handleFill(blk, busPkt,
-                                 coherence->getNewState(busPkt, old_state),
+                                 new_state,
                                  writebacks, pkt);
+                //Free the packet
+                delete busPkt;
+
                 // Handle writebacks if needed
                 while (!writebacks.empty()){
-                    memSidePort->sendAtomic(writebacks.front());
+                    Packet *wbPkt = writebacks.front();
+                    memSidePort->sendAtomic(wbPkt);
                     writebacks.pop_front();
+                    delete wbPkt;
                 }
                 return lat + hitLatency;
             } else {
@@ -679,7 +704,7 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update, CachePort
             // Still need to change data in all locations.
             otherSidePort->sendFunctional(pkt);
         }
-        return curTick + lat;
+        return hitLatency;
     }
     fatal("Probe not handled.\n");
     return 0;
index 7b8fa4a96880afcafc3879ccf232fdc5d8176468..4758fda89496e2cf5ad0fe2ee92327e2d9fdd1dd 100644 (file)
 
 static const std::string ReadReqString("ReadReq");
 static const std::string WriteReqString("WriteReq");
-static const std::string WriteReqNoAckString("WriteReqNoAck");
+static const std::string WriteReqNoAckString("WriteReqNoAck|Writeback");
 static const std::string ReadRespString("ReadResp");
 static const std::string WriteRespString("WriteResp");
+static const std::string SoftPFReqString("SoftPFReq");
+static const std::string SoftPFRespString("SoftPFResp");
+static const std::string HardPFReqString("HardPFReq");
+static const std::string HardPFRespString("HardPFResp");
+static const std::string InvalidateReqString("InvalidateReq");
+static const std::string WriteInvalidateReqString("WriteInvalidateReq");
+static const std::string UpgradeReqString("UpgradeReq");
+static const std::string ReadExReqString("ReadExReq");
+static const std::string ReadExRespString("ReadExResp");
 static const std::string OtherCmdString("<other>");
 
 const std::string &
@@ -53,6 +62,15 @@ Packet::cmdString() const
       case WriteReqNoAck:   return WriteReqNoAckString;
       case ReadResp:        return ReadRespString;
       case WriteResp:       return WriteRespString;
+      case SoftPFReq:       return SoftPFReqString;
+      case SoftPFResp:      return SoftPFRespString;
+      case HardPFReq:       return HardPFReqString;
+      case HardPFResp:      return HardPFRespString;
+      case InvalidateReq:   return InvalidateReqString;
+      case WriteInvalidateReq:return WriteInvalidateReqString;
+      case UpgradeReq:      return UpgradeReqString;
+      case ReadExReq:       return ReadExReqString;
+      case ReadExResp:      return ReadExRespString;
       default:              return OtherCmdString;
     }
 }
@@ -66,6 +84,15 @@ Packet::cmdIdxToString(Packet::Command idx)
       case WriteReqNoAck:   return WriteReqNoAckString;
       case ReadResp:        return ReadRespString;
       case WriteResp:       return WriteRespString;
+      case SoftPFReq:       return SoftPFReqString;
+      case SoftPFResp:      return SoftPFRespString;
+      case HardPFReq:       return HardPFReqString;
+      case HardPFResp:      return HardPFRespString;
+      case InvalidateReq:   return InvalidateReqString;
+      case WriteInvalidateReq:return WriteInvalidateReqString;
+      case UpgradeReq:      return UpgradeReqString;
+      case ReadExReq:       return ReadExReqString;
+      case ReadExResp:      return ReadExRespString;
       default:              return OtherCmdString;
     }
 }
index 18aff03f4a34220ee65d166dbab559806d66d521..83399be80c569f7d531cce7ff05bea80211c0051 100644 (file)
@@ -6,6 +6,7 @@ from m5 import build_env
 class MemTest(SimObject):
     type = 'MemTest'
     max_loads = Param.Counter("number of loads to execute")
+    atomic = Param.Bool(False, "Execute tester in atomic mode? (or timing)\n")
     memory_size = Param.Int(65536, "memory size")
     percent_dest_unaligned = Param.Percent(50,
         "percent of copy dest address that are unaligned")