mem-cache: Replace block visitor with std::function
authorNikos Nikoleris <nikos.nikoleris@arm.com>
Wed, 30 May 2018 10:54:57 +0000 (11:54 +0100)
committerNikos Nikoleris <nikos.nikoleris@arm.com>
Thu, 31 May 2018 17:45:23 +0000 (17:45 +0000)
This change modifies forEachBlk tags function to accept std::function
as parameter. It also adds an anyBlk tags function that given a
condition, it iterates through the blocks and returns whether the
condition is met.

Finally, it uses forEachBlk to implement the print, computeStats and
cleanupRefs functions that also work for the FALRU class.

Change-Id: I2f75f4baa1fdd5a1d343a63ecace3eb9458fbf03
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/10621
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>

src/mem/cache/base.cc
src/mem/cache/base.hh
src/mem/cache/blk.hh
src/mem/cache/tags/base.cc
src/mem/cache/tags/base.hh
src/mem/cache/tags/base_set_assoc.cc
src/mem/cache/tags/base_set_assoc.hh
src/mem/cache/tags/fa_lru.hh

index c50fcdb6e21103e662472cd18309b8e24f3de9da..e6315cf04e87a3680f5a7ab97a431ea222c21037 100644 (file)
@@ -1326,27 +1326,22 @@ BaseCache::writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
 void
 BaseCache::memWriteback()
 {
-    CacheBlkVisitorWrapper visitor(*this, &BaseCache::writebackVisitor);
-    tags->forEachBlk(visitor);
+    tags->forEachBlk([this](CacheBlk &blk) { writebackVisitor(blk); });
 }
 
 void
 BaseCache::memInvalidate()
 {
-    CacheBlkVisitorWrapper visitor(*this, &BaseCache::invalidateVisitor);
-    tags->forEachBlk(visitor);
+    tags->forEachBlk([this](CacheBlk &blk) { invalidateVisitor(blk); });
 }
 
 bool
 BaseCache::isDirty() const
 {
-    CacheBlkIsDirtyVisitor visitor;
-    tags->forEachBlk(visitor);
-
-    return visitor.isDirty();
+    return tags->anyBlk([](CacheBlk &blk) { return blk.isDirty(); });
 }
 
-bool
+void
 BaseCache::writebackVisitor(CacheBlk &blk)
 {
     if (blk.isDirty()) {
@@ -1366,11 +1361,9 @@ BaseCache::writebackVisitor(CacheBlk &blk)
 
         blk.status &= ~BlkDirty;
     }
-
-    return true;
 }
 
-bool
+void
 BaseCache::invalidateVisitor(CacheBlk &blk)
 {
     if (blk.isDirty())
@@ -1381,8 +1374,6 @@ BaseCache::invalidateVisitor(CacheBlk &blk)
         assert(!blk.isDirty());
         invalidateBlock(&blk);
     }
-
-    return true;
 }
 
 Tick
index aacf09afbe6a3f623d0bcb395d6ce7662f62162d..04225c12f67906d1daeef116685169f85df1b0e9 100644 (file)
@@ -1108,19 +1108,15 @@ class BaseCache : public MemObject
     /**
      * Cache block visitor that writes back dirty cache blocks using
      * functional writes.
-     *
-     * @return Always returns true.
      */
-    bool writebackVisitor(CacheBlk &blk);
+    void writebackVisitor(CacheBlk &blk);
 
     /**
      * Cache block visitor that invalidates all blocks in the cache.
      *
      * @warn Dirty cache lines will not be written back to memory.
-     *
-     * @return Always returns true.
      */
-    bool invalidateVisitor(CacheBlk &blk);
+    void invalidateVisitor(CacheBlk &blk);
 
     /**
      * Take an MSHR, turn it into a suitable downstream packet, and
@@ -1152,62 +1148,4 @@ class BaseCache : public MemObject
 
 };
 
-/**
- * Wrap a method and present it as a cache block visitor.
- *
- * For example the forEachBlk method in the tag arrays expects a
- * callable object/function as their parameter. This class wraps a
- * method in an object and presents  callable object that adheres to
- * the cache block visitor protocol.
- */
-class CacheBlkVisitorWrapper : public CacheBlkVisitor
-{
-  public:
-    typedef bool (BaseCache::*VisitorPtr)(CacheBlk &blk);
-
-    CacheBlkVisitorWrapper(BaseCache &_cache, VisitorPtr _visitor)
-        : cache(_cache), visitor(_visitor) {}
-
-    bool operator()(CacheBlk &blk) override {
-        return (cache.*visitor)(blk);
-    }
-
-  private:
-    BaseCache &cache;
-    VisitorPtr visitor;
-};
-
-/**
- * Cache block visitor that determines if there are dirty blocks in a
- * cache.
- *
- * Use with the forEachBlk method in the tag array to determine if the
- * array contains dirty blocks.
- */
-class CacheBlkIsDirtyVisitor : public CacheBlkVisitor
-{
-  public:
-    CacheBlkIsDirtyVisitor()
-        : _isDirty(false) {}
-
-    bool operator()(CacheBlk &blk) override {
-        if (blk.isDirty()) {
-            _isDirty = true;
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Does the array contain a dirty line?
-     *
-     * @return true if yes, false otherwise.
-     */
-    bool isDirty() const { return _isDirty; };
-
-  private:
-    bool _isDirty;
-};
-
 #endif //__MEM_CACHE_BASE_HH__
index 951abd5bec977a1b4616013e88734dbda67cf3e6..c94c3ba7d2055d9e01c27816607f571be8f891ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 ARM Limited
+ * Copyright (c) 2012-2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -409,20 +409,4 @@ class CacheBlkPrintWrapper : public Printable
                const std::string &prefix = "") const;
 };
 
-/**
- * Base class for cache block visitor, operating on the cache block
- * base class (later subclassed for the various tag classes). This
- * visitor class is used as part of the forEachBlk interface in the
- * tag classes.
- */
-class CacheBlkVisitor
-{
-  public:
-
-    CacheBlkVisitor() {}
-    virtual ~CacheBlkVisitor() {}
-
-    virtual bool operator()(CacheBlk &blk) = 0;
-};
-
 #endif //__MEM_CACHE_BLK_HH__
index c7ea17bd1dc6d6ba60c1fd133e36d87863299b74..13e1245c6bb89add47c3c69258f2e364bf08433e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013,2016 ARM Limited
+ * Copyright (c) 2013,2016,2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -110,6 +110,77 @@ BaseTags::insertBlock(PacketPtr pkt, CacheBlk *blk)
     dataAccesses += 1;
 }
 
+void
+BaseTags::cleanupRefsVisitor(CacheBlk &blk)
+{
+    if (blk.isValid()) {
+        totalRefs += blk.refCount;
+        ++sampledRefs;
+    }
+}
+
+void
+BaseTags::cleanupRefs()
+{
+    forEachBlk([this](CacheBlk &blk) { cleanupRefsVisitor(blk); });
+}
+
+void
+BaseTags::computeStatsVisitor(CacheBlk &blk)
+{
+    if (blk.isValid()) {
+        assert(blk.task_id < ContextSwitchTaskId::NumTaskId);
+        occupanciesTaskId[blk.task_id]++;
+        assert(blk.tickInserted <= curTick());
+        Tick age = curTick() - blk.tickInserted;
+
+        int age_index;
+        if (age / SimClock::Int::us < 10) { // <10us
+            age_index = 0;
+        } else if (age / SimClock::Int::us < 100) { // <100us
+            age_index = 1;
+        } else if (age / SimClock::Int::ms < 1) { // <1ms
+            age_index = 2;
+        } else if (age / SimClock::Int::ms < 10) { // <10ms
+            age_index = 3;
+        } else
+            age_index = 4; // >10ms
+
+        ageTaskId[blk.task_id][age_index]++;
+    }
+}
+
+void
+BaseTags::computeStats()
+{
+    for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
+        occupanciesTaskId[i] = 0;
+        for (unsigned j = 0; j < 5; ++j) {
+            ageTaskId[i][j] = 0;
+        }
+    }
+
+    forEachBlk([this](CacheBlk &blk) { computeStatsVisitor(blk); });
+}
+
+std::string
+BaseTags::print()
+{
+    std::string str;
+
+    auto print_blk = [&str](CacheBlk &blk) {
+        if (blk.isValid())
+            str += csprintf("\tset: %d way: %d %s\n", blk.set, blk.way,
+                            blk.print());
+    };
+    forEachBlk(print_blk);
+
+    if (str.empty())
+        str = "no valid tags\n";
+
+    return str;
+}
+
 void
 BaseTags::regStats()
 {
index 806f63aae212c6c01a4ea2b8635230f2f98ffde8..90469cd8e0835e6f42af7da1bd06f5598691bf03 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014,2016-2017 ARM Limited
+ * Copyright (c) 2012-2014,2016-2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -50,6 +50,7 @@
 #define __MEM_CACHE_TAGS_BASE_HH__
 
 #include <cassert>
+#include <functional>
 #include <string>
 
 #include "base/callback.hh"
@@ -177,17 +178,17 @@ class BaseTags : public ClockedObject
      * Average in the reference count for valid blocks when the simulation
      * exits.
      */
-    virtual void cleanupRefs() {}
+    void cleanupRefs();
 
     /**
      * Computes stats just prior to dump event
      */
-    virtual void computeStats() {}
+    void computeStats();
 
     /**
      * Print all tags used
      */
-    virtual std::string print() const = 0;
+    std::string print();
 
     /**
      * Find a block using the memory address
@@ -289,7 +290,42 @@ class BaseTags : public ClockedObject
 
     virtual int extractSet(Addr addr) const = 0;
 
-    virtual void forEachBlk(CacheBlkVisitor &visitor) = 0;
+
+    /**
+     * Visit each block in the tags and apply a visitor
+     *
+     * The visitor should be a std::function that takes a cache block
+     * reference as its parameter.
+     *
+     * @param visitor Visitor to call on each block.
+     */
+    virtual void forEachBlk(std::function<void(CacheBlk &)> visitor) = 0;
+
+    /**
+     * Find if any of the blocks satisfies a condition
+     *
+     * The visitor should be a std::function that takes a cache block
+     * reference as its parameter. The visitor will terminate the
+     * traversal early if the condition is satisfied.
+     *
+     * @param visitor Visitor to call on each block.
+     */
+    virtual bool anyBlk(std::function<bool(CacheBlk &)> visitor) = 0;
+
+  private:
+    /**
+     * Update the reference stats using data from the input block
+     *
+     * @param blk The input block
+     */
+    void cleanupRefsVisitor(CacheBlk &blk);
+
+    /**
+     * Update the occupancy and age stats using data from the input block
+     *
+     * @param blk The input block
+     */
+    void computeStatsVisitor(CacheBlk &blk);
 };
 
 class BaseTagsCallback : public Callback
index d3420b440829601679106d38b00074f181e0a935..9cd93dbea9c381fb0223bb12b42a3ed3900efdf5 100644 (file)
 
 #include "mem/cache/tags/base_set_assoc.hh"
 
-#include <cassert>
 #include <string>
 
 #include "base/intmath.hh"
-#include "mem/request.hh"
 
 BaseSetAssoc::BaseSetAssoc(const Params *p)
     :BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
@@ -134,64 +132,6 @@ BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
     return sets[set].blks[way];
 }
 
-std::string
-BaseSetAssoc::print() const {
-    std::string cache_state;
-    for (const CacheBlk& blk : blks) {
-        if (blk.isValid())
-            cache_state += csprintf("\tset: %d way: %d %s\n", blk.set,
-                                    blk.way, blk.print());
-    }
-    if (cache_state.empty())
-        cache_state = "no valid tags\n";
-    return cache_state;
-}
-
-void
-BaseSetAssoc::cleanupRefs()
-{
-    for (const CacheBlk& blk : blks) {
-        if (blk.isValid()) {
-            totalRefs += blk.refCount;
-            ++sampledRefs;
-        }
-    }
-}
-
-void
-BaseSetAssoc::computeStats()
-{
-    for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
-        occupanciesTaskId[i] = 0;
-        for (unsigned j = 0; j < 5; ++j) {
-            ageTaskId[i][j] = 0;
-        }
-    }
-
-    for (const CacheBlk& blk : blks) {
-        if (blk.isValid()) {
-            assert(blk.task_id < ContextSwitchTaskId::NumTaskId);
-            occupanciesTaskId[blk.task_id]++;
-            assert(blk.tickInserted <= curTick());
-            Tick age = curTick() - blk.tickInserted;
-
-            int age_index;
-            if (age / SimClock::Int::us < 10) { // <10us
-                age_index = 0;
-            } else if (age / SimClock::Int::us < 100) { // <100us
-                age_index = 1;
-            } else if (age / SimClock::Int::ms < 1) { // <1ms
-                age_index = 2;
-            } else if (age / SimClock::Int::ms < 10) { // <10ms
-                age_index = 3;
-            } else
-                age_index = 4; // >10ms
-
-            ageTaskId[blk.task_id][age_index]++;
-        }
-    }
-}
-
 BaseSetAssoc *
 BaseSetAssocParams::create()
 {
index bf227c067e28a6dae4194ae37d489f59ad2270f5..33b2d39c40309ed1d19485c20dcb8958e2b04065 100644 (file)
@@ -48,6 +48,7 @@
 #ifndef __MEM_CACHE_TAGS_BASE_SET_ASSOC_HH__
 #define __MEM_CACHE_TAGS_BASE_SET_ASSOC_HH__
 
+#include <functional>
 #include <string>
 #include <vector>
 
@@ -298,38 +299,19 @@ class BaseSetAssoc : public BaseTags
         return ((blk->tag << tagShift) | ((Addr)blk->set << setShift));
     }
 
-    /**
-     * Called at end of simulation to complete average block reference stats.
-     */
-    void cleanupRefs() override;
-
-    /**
-     * Print all tags used
-     */
-    std::string print() const override;
-
-    /**
-     * Called prior to dumping stats to compute task occupancy
-     */
-    void computeStats() override;
+    void forEachBlk(std::function<void(CacheBlk &)> visitor) override {
+        for (CacheBlk& blk : blks) {
+            visitor(blk);
+        }
+    }
 
-    /**
-     * Visit each block in the tag store and apply a visitor to the
-     * block.
-     *
-     * The visitor should be a function (or object that behaves like a
-     * function) that takes a cache block reference as its parameter
-     * and returns a bool. A visitor can request the traversal to be
-     * stopped by returning false, returning true causes it to be
-     * called for the next block in the tag store.
-     *
-     * \param visitor Visitor to call on each block.
-     */
-    void forEachBlk(CacheBlkVisitor &visitor) override {
+    bool anyBlk(std::function<bool(CacheBlk &)> visitor) override {
         for (CacheBlk& blk : blks) {
-            if (!visitor(blk))
-                return;
+            if (visitor(blk)) {
+                return true;
+            }
         }
+        return false;
     }
 };
 
index 98a64577e35b2569ebe91cd6c6b2887616ee971c..e063a6ca1aa731a2417e84f2093661e3fc78e653 100644 (file)
@@ -50,6 +50,7 @@
 #define __MEM_CACHE_TAGS_FA_LRU_HH__
 
 #include <cstdint>
+#include <functional>
 #include <string>
 #include <unordered_map>
 
@@ -240,28 +241,19 @@ class FALRU : public BaseTags
         return blk->tag;
     }
 
-    /**
-     * @todo Implement as in lru. Currently not used
-     */
-    virtual std::string print() const override { return ""; }
+    void forEachBlk(std::function<void(CacheBlk &)> visitor) override {
+        for (int i = 0; i < numBlocks; i++) {
+            visitor(blks[i]);
+        }
+    }
 
-    /**
-     * Visit each block in the tag store and apply a visitor to the
-     * block.
-     *
-     * The visitor should be a function (or object that behaves like a
-     * function) that takes a cache block reference as its parameter
-     * and returns a bool. A visitor can request the traversal to be
-     * stopped by returning false, returning true causes it to be
-     * called for the next block in the tag store.
-     *
-     * \param visitor Visitor to call on each block.
-     */
-    void forEachBlk(CacheBlkVisitor &visitor) override {
+    bool anyBlk(std::function<bool(CacheBlk &)> visitor) override {
         for (int i = 0; i < numBlocks; i++) {
-            if (!visitor(blks[i]))
-                return;
+            if (visitor(blks[i])) {
+                return true;
+            }
         }
+        return false;
     }
 
   private: