mem-cache: Make StridePrefetcher use Replacement Policies

Previously StridePrefetcher was only able to use random
replacement policy. This change allows all replacement
policies to be applied to the pc table.

Change-Id: I8714e71a6a4c9c31fbca49a07a456dcacd3e402c
Signed-off-by: Daniel <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/14360
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py
index 09717df..bae235d 100644
--- a/src/mem/cache/prefetch/Prefetcher.py
+++ b/src/mem/cache/prefetch/Prefetcher.py
@@ -43,6 +43,7 @@
 from m5.SimObject import *
 from m5.params import *
 from m5.proxy import *
+from ReplacementPolicies import *
 
 class HWPProbeEvent(object):
     def __init__(self, prefetcher, obj, *listOfNames):
@@ -126,6 +127,10 @@
 
     degree = Param.Int(4, "Number of prefetches to generate")
 
+    # Get replacement policy
+    replacement_policy = Param.BaseReplacementPolicy(RandomRP(),
+        "Replacement policy")
+
 class TaggedPrefetcher(QueuedPrefetcher):
     type = 'TaggedPrefetcher'
     cxx_class = 'TaggedPrefetcher'
diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc
index 4520f12..44849cd 100644
--- a/src/mem/cache/prefetch/stride.cc
+++ b/src/mem/cache/prefetch/stride.cc
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2018 Inria
  * Copyright (c) 2012-2013, 2015 ARM Limited
  * All rights reserved
  *
@@ -39,6 +40,7 @@
  *
  * Authors: Ron Dreslinski
  *          Steve Reinhardt
+ *          Daniel Carvalho
  */
 
 /**
@@ -55,6 +57,7 @@
 #include "base/random.hh"
 #include "base/trace.hh"
 #include "debug/HWPrefetch.hh"
+#include "mem/cache/replacement_policies/base.hh"
 #include "params/StridePrefetcher.hh"
 
 StridePrefetcher::StrideEntry::StrideEntry()
@@ -81,7 +84,8 @@
       pcTableAssoc(p->table_assoc),
       pcTableSets(p->table_sets),
       useMasterId(p->use_master_id),
-      degree(p->degree)
+      degree(p->degree),
+      replacementPolicy(p->replacement_policy)
 {
     assert(isPowerOf2(pcTableSets));
 }
@@ -103,7 +107,7 @@
 {
     // Create new table
     auto insertion_result = pcTables.insert(std::make_pair(context,
-        PCTable(pcTableAssoc, pcTableSets, name())));
+        PCTable(pcTableAssoc, pcTableSets, name(), replacementPolicy)));
 
     DPRINTF(HWPrefetch, "Adding context %i with stride entries\n", context);
 
@@ -111,11 +115,21 @@
     return &(insertion_result.first->second);
 }
 
-StridePrefetcher::PCTable::PCTable(int assoc, int sets, const std::string name)
-    : pcTableAssoc(assoc), pcTableSets(sets), _name(name), entries(pcTableSets)
+StridePrefetcher::PCTable::PCTable(int assoc, int sets, const std::string name,
+                                   BaseReplacementPolicy* replacementPolicy)
+    : pcTableSets(sets), _name(name), entries(pcTableSets),
+      replacementPolicy(replacementPolicy)
 {
-    for (auto& set : entries) {
-        set.resize(pcTableAssoc);
+    for (int set = 0; set < sets; set++) {
+        entries[set].resize(assoc);
+        for (int way = 0; way < assoc; way++) {
+            // Inform the entry its position
+            entries[set][way].setPosition(set, way);
+
+            // Initialize replacement policy data
+            entries[set][way].replacementData =
+                replacementPolicy->instantiateEntry();
+        }
     }
 }
 
@@ -200,12 +214,14 @@
 
         // Invalidate victim
         entry->invalidate();
+        replacementPolicy->invalidate(entry->replacementData);
 
         // Insert new entry's data
         entry->instAddr = pc;
         entry->lastAddr = pkt_addr;
-        entry->isSecure= is_secure;
+        entry->isSecure = is_secure;
         entry->confidence = startConf;
+        replacementPolicy->reset(entry->replacementData);
     }
 }
 
@@ -222,23 +238,34 @@
 {
     // Rand replacement for now
     int set = pcHash(pc);
-    int way = random_mt.random<int>(0, pcTableAssoc - 1);
 
-    DPRINTF(HWPrefetch, "Victimizing lookup table[%d][%d].\n", set, way);
-    return &entries[set][way];
+    // Get possible entries to be victimized
+    std::vector<ReplaceableEntry*> possible_entries;
+    for (auto& entry : entries[set]) {
+        possible_entries.push_back(&entry);
+    }
+
+    // Choose victim based on replacement policy
+    StrideEntry* victim = static_cast<StrideEntry*>(
+        replacementPolicy->getVictim(possible_entries));
+
+    DPRINTF(HWPrefetch, "Victimizing lookup table[%d][%d].\n",
+            victim->getSet(), victim->getWay());
+
+    return victim;
 }
 
 inline StridePrefetcher::StrideEntry*
 StridePrefetcher::PCTable::findEntry(Addr pc, bool is_secure)
 {
     int set = pcHash(pc);
-    std::vector<StrideEntry>& set_entries = entries[set];
-    for (int way = 0; way < pcTableAssoc; way++) {
-        StrideEntry* entry = &set_entries[way];
+    for (auto& entry : entries[set]) {
         // Search ways for match
-        if ((entry->instAddr == pc) && (entry->isSecure == is_secure)) {
-            DPRINTF(HWPrefetch, "Lookup hit table[%d][%d].\n", set, way);
-            return entry;
+        if ((entry.instAddr == pc) && (entry.isSecure == is_secure)) {
+            DPRINTF(HWPrefetch, "Lookup hit table[%d][%d].\n", entry.getSet(),
+                    entry.getWay());
+            replacementPolicy->touch(entry.replacementData);
+            return &entry;
         }
     }
     return nullptr;
diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh
index 772c3a5..aa02287 100644
--- a/src/mem/cache/prefetch/stride.hh
+++ b/src/mem/cache/prefetch/stride.hh
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2018 Inria
  * Copyright (c) 2012-2013, 2015 ARM Limited
  * All rights reserved
  *
@@ -38,6 +39,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Ron Dreslinski
+ *          Daniel Carvalho
  */
 
 /**
@@ -54,8 +56,10 @@
 
 #include "base/types.hh"
 #include "mem/cache/prefetch/queued.hh"
+#include "mem/cache/replacement_policies/replaceable_entry.hh"
 #include "mem/packet.hh"
 
+class BaseReplacementPolicy;
 struct StridePrefetcherParams;
 
 class StridePrefetcher : public QueuedPrefetcher
@@ -73,7 +77,10 @@
 
     const int degree;
 
-    struct StrideEntry
+    /** Replacement policy used in the PC tables. */
+    BaseReplacementPolicy* replacementPolicy;
+
+    struct StrideEntry : public ReplaceableEntry
     {
         /** Default constructor */
         StrideEntry();
@@ -97,8 +104,10 @@
          * @param assoc Associativity of the table.
          * @param sets Number of sets in the table.
          * @param name Name of the prefetcher.
+         * @param replacementPolicy Replacement policy used by the table.
          */
-        PCTable(int assoc, int sets, const std::string name);
+        PCTable(int assoc, int sets, const std::string name,
+                BaseReplacementPolicy* replacementPolicy);
 
         /**
          * Default destructor.
@@ -124,12 +133,16 @@
 
       private:
         const std::string name() {return _name; }
-        const int pcTableAssoc;
         const int pcTableSets;
         const std::string _name;
         std::vector<std::vector<StrideEntry>> entries;
 
         /**
+         * Replacement policy used by StridePrefetcher.
+         */
+        BaseReplacementPolicy* replacementPolicy;
+
+        /**
          * PC hashing function to index sets in the table.
          *
          * @param pc The PC value.