mem-cache: Use CircularQueue for the STeMS's RMOB

Replace rmobHead functionality with a CircularQueue. As a side
effect, RMOB entry's valid bit was removed.

Change-Id: If0b39cfe15de1e47dde0689a0ebc46b623ec1e55
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24539
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Javier Bueno Hedo <javier.bueno@metempsy.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc
index 932c7f6..dd15012 100644
--- a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc
+++ b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc
@@ -50,7 +50,7 @@
                          p->pattern_sequence_table_replacement_policy,
                          ActiveGenerationTableEntry(
                              spatialRegionSize / blkSize)),
-    rmob(p->region_miss_order_buffer_entries), rmobHead(0)
+    rmob(p->region_miss_order_buffer_entries)
 {
     fatal_if(!isPowerOf2(spatialRegionSize),
         "The spatial region size must be a power of 2.");
@@ -106,13 +106,12 @@
 void
 STeMS::addToRMOB(Addr sr_addr, Addr pst_addr, unsigned int delta)
 {
-    RegionMissOrderBufferEntry &rmob_entry = rmob[rmobHead];
-    rmobHead = (rmobHead + 1) % rmob.size();
-
+    RegionMissOrderBufferEntry rmob_entry;
     rmob_entry.srAddress = sr_addr;
     rmob_entry.pstAddress = pst_addr;
     rmob_entry.delta = delta;
-    rmob_entry.valid = true;
+
+    rmob.push_back(rmob_entry);
 }
 
 void
@@ -171,13 +170,12 @@
     // Prefetch generation: if this is a miss, search for the most recent
     // entry in the RMOB, and reconstruct the registered access sequence
     if (pfi.isCacheMiss()) {
-        for (unsigned int idx = (rmobHead - 1) % rmob.size();
-             idx != rmobHead && rmob[idx].valid;
-             idx = (idx - 1) % rmob.size())
-        {
-            if (rmob[idx].srAddress == sr_addr) {
+        auto it = rmob.end();
+        while (it != rmob.begin()) {
+            --it;
+            if (it->srAddress == sr_addr) {
                 // reconstruct the access sequence
-                reconstructSequence(idx, addresses);
+                reconstructSequence(it, addresses);
                 break;
             }
         }
@@ -185,37 +183,34 @@
 }
 
 void
-STeMS::reconstructSequence(unsigned int rmob_idx,
+STeMS::reconstructSequence(
+    CircularQueue<RegionMissOrderBufferEntry>::iterator rmob_it,
     std::vector<AddrPriority> &addresses)
 {
     std::vector<Addr> reconstruction(reconstructionEntries, MaxAddr);
     unsigned int idx = 0;
-    // process rmob entries from rmob_idx (most recent with
-    // address = sr_addr) to the last one (rmobHead)
-    for (int i = rmob_idx;
-         i != rmobHead && idx < reconstructionEntries;
-         i = (i + 1) % rmob.size())
-    {
-        reconstruction[idx] = rmob[i].srAddress * spatialRegionSize;
-        unsigned int next_i = (i + 1) % rmob.size();
-        idx += rmob[next_i].delta + 1;
+
+    // Process rmob entries from rmob_it (most recent with address = sr_addr)
+    // to the latest one
+    for (auto it = rmob_it; it != rmob.end() && (idx < reconstructionEntries);
+        it++) {
+        reconstruction[idx] = it->srAddress * spatialRegionSize;
+        idx += (it+1)->delta + 1;
     }
+
     // Now query the PST with the PC of each RMOB entry
     idx = 0;
-    for (int i = rmob_idx;
-         i != rmobHead && idx < reconstructionEntries;
-         i = (i + 1) % rmob.size())
-    {
+    for (auto it = rmob_it; it != rmob.end() && (idx < reconstructionEntries);
+        it++) {
         ActiveGenerationTableEntry *pst_entry =
-            patternSequenceTable.findEntry(rmob[i].pstAddress,
-                                           false /* unused */);
+            patternSequenceTable.findEntry(it->pstAddress, false /* unused */);
         if (pst_entry != nullptr) {
             patternSequenceTable.accessEntry(pst_entry);
             for (auto &seq_entry : pst_entry->sequence) {
                 if (seq_entry.counter > 1) {
                     // 2-bit counter: high enough confidence with a
                     // value greater than 1
-                    Addr rec_addr = rmob[i].srAddress * spatialRegionSize +
+                    Addr rec_addr = it->srAddress * spatialRegionSize +
                         seq_entry.offset;
                     unsigned ridx = idx + seq_entry.delta;
                     // Try to use the corresponding position, if it has been
@@ -241,9 +236,9 @@
                 }
             }
         }
-        unsigned int next_i = (i + 1) % rmob.size();
-        idx += rmob[next_i].delta + 1;
+        idx += (it+1)->delta + 1;
     }
+
     for (Addr pf_addr : reconstruction) {
         if (pf_addr != MaxAddr) {
             addresses.push_back(AddrPriority(pf_addr, 0));
diff --git a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh
index 8f8704a..4e0ca28 100644
--- a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh
+++ b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh
@@ -43,6 +43,7 @@
 
 #include <vector>
 
+#include "base/circular_queue.hh"
 #include "base/sat_counter.hh"
 #include "mem/cache/prefetch/associative_set.hh"
 #include "mem/cache/prefetch/queued.hh"
@@ -161,14 +162,10 @@
         Addr pstAddress;
         /** Delta within the global miss order sequence */
         unsigned int delta;
-        /** Valid bit */
-        bool valid;
     };
 
     /** Region Miss Order Buffer (RMOB) */
-    std::vector<RegionMissOrderBufferEntry> rmob;
-    /** First free position (or older, if it is full) of the RMOB */
-    unsigned int rmobHead;
+    CircularQueue<RegionMissOrderBufferEntry> rmob;
 
     /** Counter to keep the count of accesses between trigger accesses */
     unsigned int lastTriggerCounter;
@@ -186,11 +183,14 @@
     /**
      * Reconstructs a sequence of accesses and generates the prefetch
      * addresses, adding them to the addresses vector
-     * @param rmob_idx rmob position to start generating from
+     *
+     * @param rmob_it rmob position to start generating from.
      * @param addresses vector to add the addresses to be prefetched
      */
-    void reconstructSequence(unsigned int rmob_idx,
-                             std::vector<AddrPriority> &addresses);
+    void reconstructSequence(
+        CircularQueue<RegionMissOrderBufferEntry>::iterator rmob_it,
+        std::vector<AddrPriority> &addresses);
+
   public:
     STeMS(const STeMSPrefetcherParams* p);
     ~STeMS() = default;