mem-cache: Make findVictim non-const
[gem5.git] / src / mem / cache / mshr.hh
index 1f59607bf31d7f38d2fbbf1394da6e16cba14984..685064f3926b333845ceb6c5047b9d7970c8a4db 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
@@ -38,6 +38,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Erik Hallnor
+ *          Nikos Nikoleris
  */
 
 /**
 #ifndef __MEM_CACHE_MSHR_HH__
 #define __MEM_CACHE_MSHR_HH__
 
+#include <cassert>
+#include <iosfwd>
 #include <list>
+#include <string>
+#include <vector>
 
 #include "base/printable.hh"
+#include "base/types.hh"
 #include "mem/cache/queue_entry.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
+#include "sim/core.hh"
 
-class Cache;
+class BaseCache;
 
 /**
  * Miss Status and handling Register. This class keeps all the information
@@ -109,10 +118,13 @@ class MSHR : public QueueEntry, public Printable
 
   public:
 
+    /** Track if we sent this as a whole line write or not */
+    bool wasWholeLineWrite;
+
     /** True if the entry is just a simple forward from an upper level */
     bool isForward;
 
-    class Target {
+    class Target : public QueueEntry::Target {
       public:
 
         enum Source {
@@ -121,10 +133,6 @@ class MSHR : public QueueEntry, public Printable
             FromPrefetcher
         };
 
-        const Tick recvTime;  //!< Time when request was received (for stats)
-        const Tick readyTime; //!< Time when request is ready to be serviced
-        const Counter order;  //!< Global order (for memory consistency mgmt)
-        const PacketPtr pkt;  //!< Pending request packet.
         const Source source;  //!< Request from cpu, memory, or prefetcher?
 
         /**
@@ -149,9 +157,8 @@ class MSHR : public QueueEntry, public Printable
 
         Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
                Source _source, bool _markedPending, bool alloc_on_fill)
-            : recvTime(curTick()), readyTime(_readyTime), order(_order),
-              pkt(_pkt), source(_source), markedPending(_markedPending),
-              allocOnFill(alloc_on_fill)
+            : QueueEntry::Target(_pkt, _readyTime, _order), source(_source),
+              markedPending(_markedPending), allocOnFill(alloc_on_fill)
         {}
     };
 
@@ -162,6 +169,11 @@ class MSHR : public QueueEntry, public Printable
         bool hasUpgrade;
         /** Set when the response should allocate on fill */
         bool allocOnFill;
+        /**
+         * Determine whether there was at least one non-snooping
+         * target coming from another cache.
+         */
+        bool hasFromCache;
 
         TargetList();
 
@@ -176,7 +188,29 @@ class MSHR : public QueueEntry, public Printable
         void updateFlags(PacketPtr pkt, Target::Source source,
                          bool alloc_on_fill);
 
-        void resetFlags() { needsWritable = hasUpgrade = allocOnFill = false; }
+        /**
+         * Reset state
+         *
+         * @param blk_addr Address of the cache block
+         * @param blk_size Size of the cache block
+         */
+        void init(Addr blk_addr, Addr blk_size) {
+            blkAddr = blk_addr;
+            blkSize = blk_size;
+            writesBitmap.resize(blk_size);
+
+            resetFlags();
+        }
+
+        void resetFlags() {
+            canMergeWrites = true;
+            std::fill(writesBitmap.begin(), writesBitmap.end(), false);
+
+            needsWritable = false;
+            hasUpgrade = false;
+            allocOnFill = false;
+            hasFromCache = false;
+        }
 
         /**
          * Goes through the list of targets and uses them to populate
@@ -186,12 +220,24 @@ class MSHR : public QueueEntry, public Printable
          */
         void populateFlags();
 
+        /**
+         * Add the specified packet in the TargetList. This function
+         * stores information related to the added packet and updates
+         * accordingly the flags.
+         *
+         * @param pkt Packet considered for adding
+         */
+        void updateWriteFlags(PacketPtr pkt);
+
         /**
          * Tests if the flags of this TargetList have their default
          * values.
+         *
+         * @return True if the TargetList are reset, false otherwise.
          */
         bool isReset() const {
-            return !needsWritable && !hasUpgrade && !allocOnFill;
+            return !needsWritable && !hasUpgrade && !allocOnFill &&
+                !hasFromCache && canMergeWrites;
         }
 
         /**
@@ -207,8 +253,7 @@ class MSHR : public QueueEntry, public Printable
          * @param alloc_on_fill Whether it should allocate on a fill
          */
         void add(PacketPtr pkt, Tick readyTime, Counter order,
-                 Target::Source source, bool markPending,
-                 bool alloc_on_fill);
+                 Target::Source source, bool markPending, bool alloc_on_fill);
 
         /**
          * Convert upgrades to the equivalent request if the cache line they
@@ -217,9 +262,42 @@ class MSHR : public QueueEntry, public Printable
         void replaceUpgrades();
 
         void clearDownstreamPending();
-        bool checkFunctional(PacketPtr pkt);
+        void clearDownstreamPending(iterator begin, iterator end);
+        bool trySatisfyFunctional(PacketPtr pkt);
         void print(std::ostream &os, int verbosity,
                    const std::string &prefix) const;
+
+        /**
+         * Check if this list contains writes that cover an entire
+         * cache line. This is used as part of the miss-packet
+         * creation. Note that new requests may arrive after a
+         * miss-packet has been created, and for the corresponding
+         * fill we use the wasWholeLineWrite field.
+         */
+        bool isWholeLineWrite() const
+        {
+            return std::all_of(writesBitmap.begin(), writesBitmap.end(),
+                               [](bool i) { return i; });
+        }
+
+      private:
+        /** Address of the cache block for this list of targets. */
+        Addr blkAddr;
+
+        /** Size of the cache block. */
+        Addr blkSize;
+
+        /** Indicates whether we can merge incoming write requests */
+        bool canMergeWrites;
+
+        // NOTE: std::vector<bool> might not meet satisfy the
+        // ForwardIterator requirement and therefore cannot be used
+        // for writesBitmap.
+        /**
+         * Track which bytes are written by requests in this target
+         * list.
+         */
+        std::vector<char> writesBitmap;
     };
 
     /** A list of MSHRs. */
@@ -235,6 +313,11 @@ class MSHR : public QueueEntry, public Printable
     /** True if we need to get a writable copy of the block. */
     bool needsWritable() const { return targets.needsWritable; }
 
+    bool isCleaning() const {
+        PacketPtr pkt = targets.front().pkt;
+        return pkt->isClean();
+    }
+
     bool isPendingModified() const {
         assert(inService); return pendingModified;
     }
@@ -247,12 +330,32 @@ class MSHR : public QueueEntry, public Printable
         assert(inService); return postDowngrade;
     }
 
-    bool sendPacket(Cache &cache);
+    bool sendPacket(BaseCache &cache) override;
 
     bool allocOnFill() const {
         return targets.allocOnFill;
     }
+
+    /**
+     * Determine if there are non-deferred requests from other caches
+     *
+     * @return true if any of the targets is from another cache
+     */
+    bool hasFromCache() const {
+        return targets.hasFromCache;
+    }
+
   private:
+    /**
+     * Promotes deferred targets that satisfy a predicate
+     *
+     * Deferred targets are promoted to the target list if they
+     * satisfy a given condition. The operation stops at the first
+     * deferred target that doesn't satisfy the condition.
+     *
+     * @param pred A condition on a Target
+     */
+    void promoteIf(const std::function<bool (Target &)>& pred);
 
     /**
      * Pointer to this MSHR on the ready list.
@@ -272,6 +375,16 @@ class MSHR : public QueueEntry, public Printable
     TargetList deferredTargets;
 
   public:
+    /**
+     * Check if this MSHR contains only compatible writes, and if they
+     * span the entire cache line. This is used as part of the
+     * miss-packet creation. Note that new requests may arrive after a
+     * miss-packet has been created, and for the fill we therefore use
+     * the wasWholeLineWrite field.
+     */
+    bool isWholeLineWrite() const {
+        return targets.isWholeLineWrite();
+    }
 
     /**
      * Allocate a miss to this MSHR.
@@ -336,7 +449,7 @@ class MSHR : public QueueEntry, public Printable
      * Returns a reference to the first target.
      * @return A pointer to the first target.
      */
-    Target *getTarget()
+    QueueEntry::Target *getTarget() override
     {
         assert(hasTargets());
         return &targets.front();
@@ -352,16 +465,43 @@ class MSHR : public QueueEntry, public Printable
 
     bool promoteDeferredTargets();
 
+    /**
+     * Promotes deferred targets that do not require writable
+     *
+     * Move targets from the deferred targets list to the target list
+     * starting from the first deferred target until the first target
+     * that is a cache maintenance operation or needs a writable copy
+     * of the block
+     */
+    void promoteReadable();
+
+    /**
+     * Promotes deferred targets that do not require writable
+     *
+     * Requests in the deferred target list are moved to the target
+     * list up until the first target that is a cache maintenance
+     * operation or needs a writable copy of the block
+     */
     void promoteWritable();
 
-    bool checkFunctional(PacketPtr pkt);
+    bool trySatisfyFunctional(PacketPtr pkt);
+
+    /**
+     * Adds a delay relative to the current tick to the current MSHR
+     * @param delay_ticks the desired delay in ticks
+     */
+    void delay(Tick delay_ticks)
+    {
+        assert(readyTime <= curTick());
+        readyTime = curTick() + delay_ticks;
+    }
 
     /**
      * Prints the contents of this MSHR for debugging.
      */
     void print(std::ostream &os,
                int verbosity = 0,
-               const std::string &prefix = "") const;
+               const std::string &prefix = "") const override;
     /**
      * A no-args wrapper of print(std::ostream...)  meant to be
      * invoked from DPRINTFs avoiding string overheads in fast mode
@@ -369,6 +509,10 @@ class MSHR : public QueueEntry, public Printable
      * @return string with mshr fields + [deferred]targets
      */
     std::string print() const;
+
+    bool matchBlockAddr(const Addr addr, const bool is_secure) const override;
+    bool matchBlockAddr(const PacketPtr pkt) const override;
+    bool conflictAddr(const QueueEntry* entry) const override;
 };
 
 #endif // __MEM_CACHE_MSHR_HH__