mem: write streaming support via WriteInvalidate promotion
[gem5.git] / src / mem / cache / mshr_queue.cc
index b412891d9376fb4f2163814d6b5413997d6bf35f..7bfbb90f5519266a936871583af688423227a91a 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012-2013 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2003-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -26,6 +38,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Erik Hallnor
+ *          Andreas Sandberg
  */
 
 /** @file
@@ -38,32 +51,24 @@ using namespace std;
 
 MSHRQueue::MSHRQueue(const std::string &_label,
                      int num_entries, int reserve, int _index)
-    : label(_label),
-      numEntries(num_entries + reserve - 1), numReserve(reserve),
-      index(_index)
+    : label(_label), numEntries(num_entries + reserve - 1),
+      numReserve(reserve), registers(numEntries),
+      drainManager(NULL), allocated(0), inServiceEntries(0), index(_index)
 {
-    allocated = 0;
-    inServiceEntries = 0;
-    registers = new MSHR[numEntries];
     for (int i = 0; i < numEntries; ++i) {
         registers[i].queue = this;
         freeList.push_back(&registers[i]);
     }
 }
 
-MSHRQueue::~MSHRQueue()
-{
-    delete [] registers;
-}
-
 MSHR *
-MSHRQueue::findMatch(Addr addr) const
+MSHRQueue::findMatch(Addr addr, bool is_secure) const
 {
     MSHR::ConstIterator i = allocatedList.begin();
     MSHR::ConstIterator end = allocatedList.end();
     for (; i != end; ++i) {
         MSHR *mshr = *i;
-        if (mshr->addr == addr) {
+        if (mshr->addr == addr && mshr->isSecure == is_secure) {
             return mshr;
         }
     }
@@ -71,7 +76,7 @@ MSHRQueue::findMatch(Addr addr) const
 }
 
 bool
-MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
+MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const
 {
     // Need an empty vector
     assert(matches.empty());
@@ -80,7 +85,7 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
     MSHR::ConstIterator end = allocatedList.end();
     for (; i != end; ++i) {
         MSHR *mshr = *i;
-        if (mshr->addr == addr) {
+        if (mshr->addr == addr && mshr->isSecure == is_secure) {
             retval = true;
             matches.push_back(mshr);
         }
@@ -108,19 +113,19 @@ MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
 
 
 MSHR *
-MSHRQueue::findPending(Addr addr, int size) const
+MSHRQueue::findPending(Addr addr, int size, bool is_secure) const
 {
     MSHR::ConstIterator i = readyList.begin();
     MSHR::ConstIterator end = readyList.end();
     for (; i != end; ++i) {
         MSHR *mshr = *i;
-        if (mshr->addr < addr) {
-            if (mshr->addr + mshr->size > addr) {
-                return mshr;
-            }
-        } else {
-            if (addr + size > mshr->addr) {
-                return mshr;
+        if (mshr->isSecure == is_secure) {
+            if (mshr->addr < addr) {
+                if (mshr->addr + mshr->size > addr)
+                    return mshr;
+            } else {
+                if (addr + size > mshr->addr)
+                    return mshr;
             }
         }
     }
@@ -183,6 +188,13 @@ MSHRQueue::deallocateOne(MSHR *mshr)
         readyList.erase(mshr->readyIter);
     }
     mshr->deallocate();
+    if (drainManager && allocated == 0) {
+        // Notify the drain manager that we have completed draining if
+        // there are no other outstanding requests in this MSHR queue.
+        drainManager->signalDrainDone();
+        drainManager = NULL;
+        setDrainState(Drainable::Drained);
+    }
     return retval;
 }
 
@@ -220,6 +232,22 @@ MSHRQueue::markPending(MSHR *mshr)
     mshr->readyIter = addToReadyList(mshr);
 }
 
+bool
+MSHRQueue::forceDeallocateTarget(MSHR *mshr)
+{
+    bool was_full = isFull();
+    assert(mshr->hasTargets());
+    // Pop the prefetch off of the target list
+    mshr->popTarget();
+    // Delete mshr if no remaining targets
+    if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
+        deallocateOne(mshr);
+    }
+
+    // Notify if MSHR queue no longer full
+    return was_full && !isFull();
+}
+
 void
 MSHRQueue::squash(int threadNum)
 {
@@ -233,7 +261,7 @@ MSHRQueue::squash(int threadNum)
                 assert(0/*target->req->threadId()*/ == threadNum);
             }
             assert(!mshr->hasTargets());
-            assert(mshr->ntargets==0);
+            assert(mshr->getNumTargets()==0);
             if (!mshr->inService) {
                 i = deallocateOne(mshr);
             } else {
@@ -245,3 +273,16 @@ MSHRQueue::squash(int threadNum)
         }
     }
 }
+
+unsigned int
+MSHRQueue::drain(DrainManager *dm)
+{
+    if (allocated == 0) {
+        setDrainState(Drainable::Drained);
+        return 0;
+    } else {
+        drainManager = dm;
+        setDrainState(Drainable::Draining);
+        return 1;
+    }
+}