mem-cache: Fix non-bijective function in Skewed caches
[gem5.git] / src / mem / cache / mshr.hh
index 253f5f38802863872c7aff4ff996523d53e97acb..218de9244c0d0d8e506dd07083e28bb392a71ee1 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
 #ifndef __MEM_CACHE_MSHR_HH__
 #define __MEM_CACHE_MSHR_HH__
 
+#include <cassert>
+#include <iosfwd>
 #include <list>
+#include <string>
 
 #include "base/printable.hh"
+#include "base/types.hh"
 #include "mem/cache/queue_entry.hh"
+#include "mem/packet.hh"
+#include "sim/core.hh"
 
-class Cache;
+class BaseCache;
 
 /**
  * Miss Status and handling Register. This class keeps all the information
@@ -126,13 +132,32 @@ class MSHR : public QueueEntry, public Printable
         const Counter order;  //!< Global order (for memory consistency mgmt)
         const PacketPtr pkt;  //!< Pending request packet.
         const Source source;  //!< Request from cpu, memory, or prefetcher?
-        const bool markedPending; //!< Did we mark upstream MSHR
-                                  //!< as downstreamPending?
+
+        /**
+         * We use this flag to track whether we have cleared the
+         * downstreamPending flag for the MSHR of the cache above
+         * where this packet originates from and guard noninitial
+         * attempts to clear it.
+         *
+         * The flag markedPending needs to be updated when the
+         * TargetList is in service which can be:
+         * 1) during the Target instantiation if the MSHR is in
+         * service and the target is not deferred,
+         * 2) when the MSHR becomes in service if the target is not
+         * deferred,
+         * 3) or when the TargetList is promoted (deferredTargets ->
+         * targets).
+         */
+        bool markedPending;
+
+        const bool allocOnFill;   //!< Should the response servicing this
+                                  //!< target list allocate in the cache?
 
         Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
-               Source _source, bool _markedPending)
+               Source _source, bool _markedPending, bool alloc_on_fill)
             : recvTime(curTick()), readyTime(_readyTime), order(_order),
-              pkt(_pkt), source(_source), markedPending(_markedPending)
+              pkt(_pkt), source(_source), markedPending(_markedPending),
+              allocOnFill(alloc_on_fill)
         {}
     };
 
@@ -141,6 +166,13 @@ class MSHR : public QueueEntry, public Printable
       public:
         bool needsWritable;
         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();
 
@@ -150,10 +182,17 @@ class MSHR : public QueueEntry, public Printable
          *
          * @param pkt Packet considered for the flag update
          * @param source Indicates the source of the packet
+         * @param alloc_on_fill Whether the pkt would allocate on a fill
          */
-        void updateFlags(PacketPtr pkt, Target::Source source);
+        void updateFlags(PacketPtr pkt, Target::Source source,
+                         bool alloc_on_fill);
 
-        void resetFlags() { needsWritable = hasUpgrade = false; }
+        void resetFlags() {
+            needsWritable = false;
+            hasUpgrade = false;
+            allocOnFill = false;
+            hasFromCache = false;
+        }
 
         /**
          * Goes through the list of targets and uses them to populate
@@ -163,9 +202,30 @@ class MSHR : public QueueEntry, public Printable
          */
         void populateFlags();
 
-        bool isReset() const { return !needsWritable && !hasUpgrade; }
+        /**
+         * Tests if the flags of this TargetList have their default
+         * values.
+         */
+        bool isReset() const {
+            return !needsWritable && !hasUpgrade && !allocOnFill &&
+                !hasFromCache;
+        }
+
+        /**
+         * 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
+         * @param readTime Tick at which the packet is processed by this cache
+         * @param order A counter giving a unique id to each target
+         * @param source Indicates the source agent of the packet
+         * @param markPending Set for deferred targets or pending MSHRs
+         * @param alloc_on_fill Whether it should allocate on a fill
+         */
         void add(PacketPtr pkt, Tick readyTime, Counter order,
-                 Target::Source source, bool markPending);
+                 Target::Source source, bool markPending,
+                 bool alloc_on_fill);
 
         /**
          * Convert upgrades to the equivalent request if the cache line they
@@ -174,7 +234,8 @@ 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;
     };
@@ -184,9 +245,6 @@ class MSHR : public QueueEntry, public Printable
     /** MSHR list iterator. */
     typedef List::iterator Iterator;
 
-    /** Keep track of whether we should allocate on fill or not */
-    bool allocOnFill;
-
     /** The pending* and post* flags are only valid if inService is
      *  true.  Using the accessor functions lets us detect if these
      *  flags are accessed improperly.
@@ -195,6 +253,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;
     }
@@ -207,9 +270,32 @@ class MSHR : public QueueEntry, public Printable
         assert(inService); return postDowngrade;
     }
 
-    bool sendPacket(Cache &cache);
+    bool sendPacket(BaseCache &cache);
+
+    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.
@@ -269,6 +355,20 @@ class MSHR : public QueueEntry, public Printable
     int getNumTargets() const
     { return targets.size() + deferredTargets.size(); }
 
+    /**
+     * Extracts the subset of the targets that can be serviced given a
+     * received response. This function returns the targets list
+     * unless the response is a ReadRespWithInvalidate. The
+     * ReadRespWithInvalidate is only invalidating response that its
+     * invalidation was not expected when the request (a
+     * ReadSharedReq) was sent out. For ReadRespWithInvalidate we can
+     * safely service only the first FromCPU target and all FromSnoop
+     * targets (inform all snoopers that we no longer have the block).
+     *
+     * @param pkt The response from the downstream memory
+     */
+    TargetList extractServiceableTargets(PacketPtr pkt);
+
     /**
      * Returns true if there are targets left.
      * @return true if there are targets
@@ -295,9 +395,26 @@ 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);
 
     /**
      * Prints the contents of this MSHR for debugging.