From cc78d86661dfccaca2f144d5bdcc75761bf52521 Mon Sep 17 00:00:00 2001
From: Ron Dreslinski <rdreslin@umich.edu>
Date: Tue, 10 Oct 2006 01:32:18 -0400
Subject: [PATCH] Fix several bugs pertaining to upgrades/mem leaks.

src/mem/cache/base_cache.cc:
    Fix a bug about not having a request to send
src/mem/cache/base_cache.hh:
    Fix a bug with the blocking code
src/mem/cache/cache.hh:
    AFix a bug with snoop hits in WB buffer
src/mem/cache/cache_impl.hh:
    Fix a bug with snoop hits in WB buffer
    Also, add better DPRINTF's
src/mem/cache/miss/miss_queue.cc:
    Fix a bug with upgrades (Need to clean it up later)
src/mem/cache/miss/mshr.cc:
    Fix a memory leak bug, still some outstanding with writebacks not being deleted
src/mem/cache/miss/mshr_queue.cc:
    Fix a bug about upgrades (need to clean up later)
src/mem/packet.hh:
    Fix for newly added cmd attribute for upgrades
tests/configs/memtest.py:
    More interesting testcase

--HG--
extra : convert_revision : fcb4f17dd58b537bb4f67a8c835f50e455e8c688
---
 src/mem/cache/base_cache.cc      | 15 ++++++++++++
 src/mem/cache/base_cache.hh      | 10 +++++---
 src/mem/cache/cache.hh           |  1 +
 src/mem/cache/cache_impl.hh      | 42 ++++++++++++++++++++------------
 src/mem/cache/miss/miss_queue.cc |  8 ++++++
 src/mem/cache/miss/mshr.cc       |  1 +
 src/mem/cache/miss/mshr_queue.cc |  2 +-
 src/mem/packet.hh                |  4 +--
 tests/configs/memtest.py         | 11 ++++-----
 9 files changed, 66 insertions(+), 28 deletions(-)

diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index 8e2f4d2331..c4d42c0a41 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -104,10 +104,12 @@ BaseCache::CachePort::recvRetry()
             if (result)
                 drainList.pop_front();
         }
+        if (!result) return;
     }
 
     if (!isCpuSide)
     {
+        if (!cache->doMasterRequest()) return;
         pkt = cache->getPacket();
         MSHR* mshr = (MSHR*)pkt->senderState;
         bool success = sendTiming(pkt);
@@ -179,10 +181,23 @@ BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt)
 void
 BaseCache::CacheEvent::process()
 {
+    if (!cachePort->drainList.empty()) {
+        //We have some responses to drain first
+        bool result = true;
+        while (result && !cachePort->drainList.empty()) {
+            result = cachePort->sendTiming(cachePort->drainList.front());
+            if (result)
+                cachePort->drainList.pop_front();
+        }
+        if (!result) return;
+    }
+
     if (!pkt)
     {
         if (!cachePort->isCpuSide)
         {
+            //For now, doMasterRequest somehow is still getting set
+            if (!cachePort->cache->doMasterRequest()) return;
             //MSHR
             pkt = cachePort->cache->getPacket();
             MSHR* mshr = (MSHR*) pkt->senderState;
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index c45f3b71be..e0f12940f0 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -392,11 +392,13 @@ class BaseCache : public MemObject
             blocked_causes[cause]++;
             blockedCycle = curTick;
         }
+        int old_state = blocked;
         if (!(blocked & flag)) {
             //Wasn't already blocked for this cause
             blocked |= flag;
             DPRINTF(Cache,"Blocking for cause %s\n", cause);
-            cpuSidePort->setBlocked();
+            if (!old_state)
+                cpuSidePort->setBlocked();
         }
     }
 
@@ -408,10 +410,12 @@ class BaseCache : public MemObject
     void setBlockedForSnoop(BlockedCause cause)
     {
         uint8_t flag = 1 << cause;
-        if (!(blocked & flag)) {
+        uint8_t old_state = blockedSnoop;
+        if (!(blockedSnoop & flag)) {
             //Wasn't already blocked for this cause
             blockedSnoop |= flag;
-            memSidePort->setBlocked();
+            if (!old_state)
+                memSidePort->setBlocked();
         }
     }
 
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 923bf82553..41b270030b 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -103,6 +103,7 @@ class Cache : public BaseCache
       * Used to append to target list, to cause an invalidation.
       */
     Packet * invalidatePkt;
+    Request *invalidateReq;
 
     /**
      * Temporarily move a block into a MSHR.
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 5c12075cdf..8c0521b52d 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -163,10 +163,8 @@ Cache(const std::string &_name,
     prefetcher->setCache(this);
     prefetcher->setTags(tags);
     prefetcher->setBuffer(missQueue);
-#if 0
-    invalidatePkt = new Packet;
-    invalidatePkt->cmd = Packet::InvalidateReq;
-#endif
+    invalidateReq = new Request((Addr) NULL, blkSize, 0);
+    invalidatePkt = new Packet(invalidateReq, Packet::InvalidateReq, 0);
 }
 
 template<class TagStore, class Buffering, class Coherence>
@@ -267,6 +265,7 @@ template<class TagStore, class Buffering, class Coherence>
 Packet *
 Cache<TagStore,Buffering,Coherence>::getPacket()
 {
+    assert(missQueue->havePending());
     Packet * pkt = missQueue->getPacket();
     if (pkt) {
         if (!pkt->req->isUncacheable()) {
@@ -292,7 +291,17 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, bool
           //Temp Hack for UPGRADES
           if (pkt->cmd == Packet::UpgradeReq) {
               pkt->flags &= ~CACHE_LINE_FILL;
-              handleResponse(pkt);
+              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);
+              //Set the state on the upgrade
+              memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
+              PacketList writebacks;
+              tags->handleFill(blk, mshr, new_state, writebacks, pkt);
+              assert(writebacks.empty());
+              missQueue->handleResponse(pkt, curTick + hitLatency);
           }
     } else if (pkt && !pkt->req->isUncacheable()) {
         pkt->flags &= ~NACKED_LINE;
@@ -402,7 +411,8 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
                     assert(!(pkt->flags & SATISFIED));
                     pkt->flags |= SATISFIED;
                     pkt->flags |= NACKED_LINE;
-                    warn("NACKs from devices not connected to the same bus not implemented\n");
+                    ///@todo NACK's from other levels
+                    //warn("NACKs from devices not connected to the same bus not implemented\n");
                     //respondToSnoop(pkt, curTick + hitLatency);
                     return;
                 }
@@ -416,7 +426,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
                     //@todo Make it so that a read to a pending read can't be exclusive now.
 
                     //Set the address so find match works
-                    panic("Don't have invalidates yet\n");
+                    //panic("Don't have invalidates yet\n");
                     invalidatePkt->addrOverride(pkt->getAddr());
 
                     //Append the invalidate on
@@ -447,7 +457,7 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
                         pkt->flags |= SHARED_LINE;
 
                         assert(pkt->isRead());
-                        Addr offset = pkt->getAddr() & ~(blkSize - 1);
+                        Addr offset = pkt->getAddr() & (blkSize - 1);
                         assert(offset < blkSize);
                         assert(pkt->getSize() <= blkSize);
                         assert(offset + pkt->getSize() <=blkSize);
@@ -468,16 +478,16 @@ Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt)
     CacheBlk::State new_state;
     bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
     if (satisfy) {
-        DPRINTF(Cache, "Cache snooped a %s request and now supplying data,"
+        DPRINTF(Cache, "Cache snooped a %s request for addr %x and now supplying data,"
                 "new state is %i\n",
-                pkt->cmdString(), new_state);
+                pkt->cmdString(), blk_addr, new_state);
 
         tags->handleSnoop(blk, new_state, pkt);
         respondToSnoop(pkt, curTick + hitLatency);
         return;
     }
-    if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n",
-                     pkt->cmdString(), new_state);
+    if (blk) DPRINTF(Cache, "Cache snooped a %s request for addr %x, new state is %i\n",
+                     pkt->cmdString(), blk_addr, new_state);
     tags->handleSnoop(blk, new_state);
 }
 
@@ -695,15 +705,15 @@ Cache<TagStore,Buffering,Coherence>::snoopProbe(PacketPtr &pkt)
         CacheBlk::State new_state = 0;
         bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
         if (satisfy) {
-            DPRINTF(Cache, "Cache snooped a %s request and now supplying data,"
+            DPRINTF(Cache, "Cache snooped a %s request for addr %x and now supplying data,"
                     "new state is %i\n",
-                    pkt->cmdString(), new_state);
+                    pkt->cmdString(), blk_addr, new_state);
 
             tags->handleSnoop(blk, new_state, pkt);
             return hitLatency;
         }
-        if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n",
-                     pkt->cmdString(), new_state);
+        if (blk) DPRINTF(Cache, "Cache snooped a %s request for addr %x, new state is %i\n",
+                     pkt->cmdString(), blk_addr, new_state);
         tags->handleSnoop(blk, new_state);
         return 0;
 }
diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc
index bdb7a39c8f..c7b0e0890e 100644
--- a/src/mem/cache/miss/miss_queue.cc
+++ b/src/mem/cache/miss/miss_queue.cc
@@ -515,6 +515,14 @@ MissQueue::setBusCmd(Packet * &pkt, Packet::Command cmd)
     assert(pkt->senderState != 0);
     MSHR * mshr = (MSHR*)pkt->senderState;
     mshr->originalCmd = pkt->cmd;
+    if (cmd == Packet::UpgradeReq || cmd == Packet::InvalidateReq) {
+        pkt->flags |= NO_ALLOCATE;
+        pkt->flags &= ~CACHE_LINE_FILL;
+    }
+    else if (!pkt->req->isUncacheable() && !pkt->isNoAllocate() &&
+             (cmd & (1 << 6)/*NeedsResponse*/)) {
+        pkt->flags |= CACHE_LINE_FILL;
+    }
     if (pkt->isCacheFill() || pkt->isNoAllocate())
         pkt->cmd = cmd;
 }
diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc
index f36032672c..455798f158 100644
--- a/src/mem/cache/miss/mshr.cc
+++ b/src/mem/cache/miss/mshr.cc
@@ -100,6 +100,7 @@ MSHR::deallocate()
 {
     assert(targets.empty());
     assert(ntargets == 0);
+    delete pkt;
     pkt = NULL;
     inService = false;
     //allocIter = NULL;
diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc
index bd96675290..78897c8fb9 100644
--- a/src/mem/cache/miss/mshr_queue.cc
+++ b/src/mem/cache/miss/mshr_queue.cc
@@ -213,7 +213,7 @@ void
 MSHRQueue::markInService(MSHR* mshr)
 {
     //assert(mshr == pendingList.front());
-    if (!mshr->pkt->needsResponse()) {
+    if (!(mshr->pkt->needsResponse() || mshr->pkt->cmd == Packet::UpgradeReq)) {
         assert(mshr->getNumTargets() == 0);
         deallocate(mshr);
         return;
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index e8cbfd10ef..8d9f8ee606 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -59,8 +59,8 @@ typedef std::list<PacketPtr> PacketList;
 #define SNOOP_COMMIT 1 << 6
 
 //For statistics we need max number of commands, hard code it at
-//20 for now.  @todo fix later
-#define NUM_MEM_CMDS 1 << 9
+//for now.  @todo fix later
+#define NUM_MEM_CMDS 1 << 10
 
 /**
  * A Packet is used to encapsulate a transfer between two objects in
diff --git a/tests/configs/memtest.py b/tests/configs/memtest.py
index c5cd0246d0..17992976cb 100644
--- a/tests/configs/memtest.py
+++ b/tests/configs/memtest.py
@@ -36,7 +36,7 @@ from m5.objects import *
 class L1(BaseCache):
     latency = 1
     block_size = 64
-    mshrs = 4
+    mshrs = 12
     tgts_per_mshr = 8
     protocol = CoherenceProtocol(protocol='moesi')
 
@@ -46,14 +46,14 @@ class L1(BaseCache):
 
 class L2(BaseCache):
     block_size = 64
-    latency = 100
+    latency = 10
     mshrs = 92
     tgts_per_mshr = 16
     write_buffers = 8
 
 #MAX CORES IS 8 with the fals sharing method
 nb_cores = 8
-cpus = [ MemTest(max_loads=1e12) for i in xrange(nb_cores) ]
+cpus = [ MemTest(max_loads=1e12, percent_uncacheable=0) for i in xrange(nb_cores) ]
 
 # system simulated
 system = System(cpu = cpus, funcmem = PhysicalMemory(),
@@ -61,7 +61,7 @@ system = System(cpu = cpus, funcmem = PhysicalMemory(),
 
 # l2cache & bus
 system.toL2Bus = Bus()
-system.l2c = L2(size='4MB', assoc=8)
+system.l2c = L2(size='64kB', assoc=8)
 system.l2c.cpu_side = system.toL2Bus.port
 
 # connect l2c to membus
@@ -90,5 +90,4 @@ system.physmem.port = system.membus.port
 
 root = Root( system = system )
 root.system.mem_mode = 'timing'
-#root.trace.flags="InstExec"
-root.trace.flags="Bus"
+root.trace.flags="Cache"
