mem-cache: Ensure that responses get data from the right source
[gem5.git] / src / mem / cache / queue.hh
index 11d456e11422f8dbe015faff99fdb30e96d3d13f..c75894a763888f303fd5d946185dc6afbe1ced13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, 2015-2016 ARM Limited
+ * Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
 #define __MEM_CACHE_QUEUE_HH__
 
 #include <cassert>
+#include <string>
+#include <type_traits>
 
+#include "base/logging.hh"
 #include "base/trace.hh"
+#include "base/types.hh"
 #include "debug/Drain.hh"
 #include "mem/cache/queue_entry.hh"
+#include "mem/packet.hh"
+#include "sim/core.hh"
 #include "sim/drain.hh"
 
 /**
 template<class Entry>
 class Queue : public Drainable
 {
+    static_assert(std::is_base_of<QueueEntry, Entry>::value,
+        "Entry must be derived from QueueEntry");
+
   protected:
     /** Local label (for functional print requests) */
     const std::string label;
 
     /**
      * The total number of entries in this queue. This number is set
-     * as the number of entries requested plus (numReserve - 1). This
+     * as the number of entries requested plus any reserve. This
      * allows for the same number of effective entries while still
      * maintaining an overflow reserve.
      */
@@ -104,8 +113,7 @@ class Queue : public Drainable
                 return readyList.insert(i, entry);
             }
         }
-        assert(false);
-        return readyList.end();  // keep stupid compilers happy
+        panic("Failed to add to ready list.");
     }
 
     /** The number of entries that are in service. */
@@ -120,10 +128,10 @@ class Queue : public Drainable
      * Create a queue with a given number of entries.
      *
      * @param num_entries The number of entries in this queue.
-     * @param num_overflow The extra overflow entries needed.
+     * @param reserve The extra overflow entries needed.
      */
     Queue(const std::string &_label, int num_entries, int reserve) :
-        label(_label), numEntries(num_entries + reserve - 1),
+        label(_label), numEntries(num_entries + reserve),
         numReserve(reserve), entries(numEntries), _numInService(0),
         allocated(0)
     {
@@ -139,7 +147,7 @@ class Queue : public Drainable
 
     bool isFull() const
     {
-        return (allocated > numEntries - numReserve);
+        return (allocated >= numEntries - numReserve);
     }
 
     int numInService() const
@@ -148,12 +156,15 @@ class Queue : public Drainable
     }
 
     /**
-     * Find the first WriteQueueEntry that matches the provided address.
+     * Find the first entry that matches the provided address.
+     *
      * @param blk_addr The block address to find.
      * @param is_secure True if the target memory space is secure.
+     * @param ignore_uncacheable Should uncacheables be ignored or not
      * @return Pointer to the matching WriteQueueEntry, null if not found.
      */
-    Entry* findMatch(Addr blk_addr, bool is_secure) const
+    Entry* findMatch(Addr blk_addr, bool is_secure,
+                     bool ignore_uncacheable = true) const
     {
         for (const auto& entry : allocatedList) {
             // we ignore any entries allocated for uncacheable
@@ -162,19 +173,20 @@ class Queue : public Drainable
             // uncacheable entries, and we do not want normal
             // cacheable accesses being added to an WriteQueueEntry
             // serving an uncacheable access
-            if (!entry->isUncacheable() && entry->blkAddr == blk_addr &&
-                entry->isSecure == is_secure) {
+            if (!(ignore_uncacheable && entry->isUncacheable()) &&
+                entry->matchBlockAddr(blk_addr, is_secure)) {
                 return entry;
             }
         }
         return nullptr;
     }
 
-    bool checkFunctional(PacketPtr pkt, Addr blk_addr)
+    bool trySatisfyFunctional(PacketPtr pkt)
     {
         pkt->pushLabel(label);
         for (const auto& entry : allocatedList) {
-            if (entry->blkAddr == blk_addr && entry->checkFunctional(pkt)) {
+            if (entry->matchBlockAddr(pkt) &&
+                entry->trySatisfyFunctional(pkt)) {
                 pkt->popLabel();
                 return true;
             }
@@ -184,16 +196,17 @@ class Queue : public Drainable
     }
 
     /**
-     * Find any pending requests that overlap the given request.
-     * @param blk_addr Block address.
-     * @param is_secure True if the target memory space is secure.
-     * @return A pointer to the earliest matching WriteQueueEntry.
+     * Find any pending requests that overlap the given request of a
+     * different queue.
+     *
+     * @param entry The entry to be compared against.
+     * @return A pointer to the earliest matching entry.
      */
-    Entry* findPending(Addr blk_addr, bool is_secure) const
+    Entry* findPending(const QueueEntry* entry) const
     {
-        for (const auto& entry : readyList) {
-            if (entry->blkAddr == blk_addr && entry->isSecure == is_secure) {
-                return entry;
+        for (const auto& ready_entry : readyList) {
+            if (ready_entry->conflictAddr(entry)) {
+                return ready_entry;
             }
         }
         return nullptr;
@@ -206,7 +219,7 @@ class Queue : public Drainable
     Entry* getNext() const
     {
         if (readyList.empty() || readyList.front()->readyTime > curTick()) {
-            return NULL;
+            return nullptr;
         }
         return readyList.front();
     }