mem-cache: Make PCTable context independent

Move the unordered_map outside of the PCTable, as it
belongs to the StridePrefetcher. By doing so we are
moving towards a table that ressembles the ones of
the Tags classes.

Some functions have been moved from the prefetcher to
the PCTable, as they didn't belong there. As such, they
have been renamed to remove the unnecessary prefix.

Change-Id: I3e54bc7dee65e1f78d96b0d548ac8345b7bd4364
Signed-off-by: Daniel <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/14358
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc
index fde4f30..c09face 100644
--- a/src/mem/cache/prefetch/stride.cc
+++ b/src/mem/cache/prefetch/stride.cc
@@ -66,28 +66,42 @@
       pcTableAssoc(p->table_assoc),
       pcTableSets(p->table_sets),
       useMasterId(p->use_master_id),
-      degree(p->degree),
-      pcTable(pcTableAssoc, pcTableSets, name())
+      degree(p->degree)
 {
     assert(isPowerOf2(pcTableSets));
 }
 
-std::vector<std::vector<StridePrefetcher::StrideEntry>>&
-StridePrefetcher::PCTable::allocateNewContext(int context)
+StridePrefetcher::PCTable*
+StridePrefetcher::findTable(int context)
 {
-    auto res = entries.insert(std::make_pair(context,
-        std::vector<std::vector<StrideEntry>>(pcTableSets)));
-    auto it = res.first;
-    chatty_assert(res.second, "Allocating an already created context\n");
-    assert(it->first == context);
+    // Check if table for given context exists
+    auto it = pcTables.find(context);
+    if (it != pcTables.end())
+        return &it->second;
+
+    // If table does not exist yet, create one
+    return allocateNewContext(context);
+}
+
+StridePrefetcher::PCTable*
+StridePrefetcher::allocateNewContext(int context)
+{
+    // Create new table
+    auto insertion_result = pcTables.insert(std::make_pair(context,
+        PCTable(pcTableAssoc, pcTableSets, name())));
 
     DPRINTF(HWPrefetch, "Adding context %i with stride entries\n", context);
 
-    std::vector<std::vector<StrideEntry>>& table = it->second;
-    for (auto& set : table) {
+    // Get iterator to new pc table, and then return a pointer to the new table
+    return &(insertion_result.first->second);
+}
+
+StridePrefetcher::PCTable::PCTable(int assoc, int sets, const std::string name)
+    : pcTableAssoc(assoc), pcTableSets(sets), _name(name), entries(pcTableSets)
+{
+    for (auto& set : entries) {
         set.resize(pcTableAssoc);
     }
-    return table;
 }
 
 StridePrefetcher::PCTable::~PCTable()
@@ -109,8 +123,11 @@
     bool is_secure = pkt->isSecure();
     MasterID master_id = useMasterId ? pkt->req->masterId() : 0;
 
+    // Get corresponding pc table
+    PCTable* pcTable = findTable(master_id);
+
     // Search for entry in the pc table
-    StrideEntry *entry = findEntry(pc, is_secure, master_id);
+    StrideEntry *entry = pcTable->findEntry(pc, is_secure);
 
     if (entry != nullptr) {
         // Hit in table
@@ -164,7 +181,7 @@
         DPRINTF(HWPrefetch, "Miss: PC %x pkt_addr %x (%s)\n", pc, pkt_addr,
                 is_secure ? "s" : "ns");
 
-        StrideEntry* entry = pcTableVictim(pc, master_id);
+        StrideEntry* entry = pcTable->findVictim(pc);
         entry->instAddr = pc;
         entry->lastAddr = pkt_addr;
         entry->isSecure= is_secure;
@@ -174,7 +191,7 @@
 }
 
 inline Addr
-StridePrefetcher::pcHash(Addr pc) const
+StridePrefetcher::PCTable::pcHash(Addr pc) const
 {
     Addr hash1 = pc >> 1;
     Addr hash2 = hash1 >> floorLog2(pcTableSets);
@@ -182,21 +199,21 @@
 }
 
 inline StridePrefetcher::StrideEntry*
-StridePrefetcher::pcTableVictim(Addr pc, int master_id)
+StridePrefetcher::PCTable::findVictim(Addr pc)
 {
     // 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 &pcTable[master_id][set][way];
+    return &entries[set][way];
 }
 
 inline StridePrefetcher::StrideEntry*
-StridePrefetcher::findEntry(Addr pc, bool is_secure, int master_id)
+StridePrefetcher::PCTable::findEntry(Addr pc, bool is_secure)
 {
     int set = pcHash(pc);
-    std::vector<StrideEntry>& set_entries = pcTable[master_id][set];
+    std::vector<StrideEntry>& set_entries = entries[set];
     for (int way = 0; way < pcTableAssoc; way++) {
         StrideEntry* entry = &set_entries[way];
         // Search ways for match
diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh
index da3bbb3..ec22ca6 100644
--- a/src/mem/cache/prefetch/stride.hh
+++ b/src/mem/cache/prefetch/stride.hh
@@ -89,44 +89,72 @@
     class PCTable
     {
       public:
-        PCTable(int assoc, int sets, const std::string name) :
-            pcTableAssoc(assoc), pcTableSets(sets), _name(name) {}
+        /**
+         * Default constructor. Create a table with given parameters.
+         *
+         * @param assoc Associativity of the table.
+         * @param sets Number of sets in the table.
+         * @param name Name of the prefetcher.
+         */
+        PCTable(int assoc, int sets, const std::string name);
 
-        std::vector<std::vector<StrideEntry>>& operator[] (int context) {
-            auto it = entries.find(context);
-            if (it != entries.end())
-                return it->second;
-
-            return allocateNewContext(context);
-        }
-
+        /**
+         * Default destructor.
+         */
         ~PCTable();
+
+        /**
+         * Search for an entry in the pc table.
+         *
+         * @param pc The PC to look for.
+         * @param is_secure True if the target memory space is secure.
+         * @return Pointer to the entry.
+         */
+        StrideEntry* findEntry(Addr pc, bool is_secure);
+
+        /**
+         * Find a replacement victim to make room for given PC.
+         *
+         * @param pc The PC value.
+         * @return The victimized entry.
+         */
+        StrideEntry* findVictim(Addr pc);
+
       private:
         const std::string name() {return _name; }
         const int pcTableAssoc;
         const int pcTableSets;
         const std::string _name;
-        std::unordered_map<int, std::vector<std::vector<StrideEntry>>> entries;
+        std::vector<std::vector<StrideEntry>> entries;
 
-        std::vector<std::vector<StrideEntry>>& allocateNewContext(int context);
+        /**
+         * PC hashing function to index sets in the table.
+         *
+         * @param pc The PC value.
+         * @return The set to which this PC maps.
+         */
+        Addr pcHash(Addr pc) const;
     };
-    PCTable pcTable;
+    std::unordered_map<int, PCTable> pcTables;
 
     /**
-     * Search for an entry in the pc table.
+     * Try to find a table of entries for the given context. If none is
+     * found, a new table is created.
      *
-     * @param pc The PC to look for.
-     * @param is_secure True if the target memory space is secure.
-     * @param master_id The context.
-     * @return Pointer to the entry.
+     * @param context The context to be searched for.
+     * @return The table corresponding to the given context.
      */
-    StrideEntry* findEntry(Addr pc, bool is_secure, int master_id);
+    PCTable* findTable(int context);
 
-    StrideEntry* pcTableVictim(Addr pc, int master_id);
+    /**
+     * Create a PC table for the given context.
+     *
+     * @param context The context of the new PC table.
+     * @return The new PC table
+     */
+    PCTable* allocateNewContext(int context);
 
-    Addr pcHash(Addr pc) const;
   public:
-
     StridePrefetcher(const StridePrefetcherParams *p);
 
     void calculatePrefetch(const PacketPtr &pkt,