mem-cache: Cleanup of SBOOE prefetcher

Made the latencyBuffer a CircularQueue.

Improved encapsulation of the Sandbox struct.

Fixed score() to follow function declaration guidelines.

Removed redundant fatal error checking for score threshold.

Change-Id: I1904884e96f103c67930abafc28b75796aadc406
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24541
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/mem/cache/prefetch/sbooe.cc b/src/mem/cache/prefetch/sbooe.cc
index ecbab68..2faa137 100644
--- a/src/mem/cache/prefetch/sbooe.cc
+++ b/src/mem/cache/prefetch/sbooe.cc
@@ -35,17 +35,13 @@
 
 SBOOE::SBOOE(const SBOOEPrefetcherParams *p)
     : Queued(p),
-      latencyBufferSize(p->latency_buffer_size),
       sequentialPrefetchers(p->sequential_prefetchers),
       scoreThreshold((p->sandbox_entries*p->score_threshold_pct)/100),
+      latencyBuffer(p->latency_buffer_size),
       averageAccessLatency(0), latencyBufferSum(0),
       bestSandbox(NULL),
       accesses(0)
 {
-    if (!(p->score_threshold_pct >= 0 && p->score_threshold_pct <= 100)) {
-        fatal("%s: the score threshold should be between 0 and 100\n", name());
-    }
-
     // Initialize a sandbox for every sequential prefetcher between
     // -1 and the number of sequential prefetchers defined
     for (int i = 0; i < sequentialPrefetchers; i++) {
@@ -54,34 +50,31 @@
 }
 
 void
-SBOOE::Sandbox::insert(Addr addr, Tick tick)
+SBOOE::Sandbox::access(Addr addr, Tick tick)
 {
-    entries[index].valid = true;
-    entries[index].line = addr + stride;
-    entries[index].expectedArrivalTick = tick;
-
-    index++;
-
-    if (index == entries.size()) {
-        index = 0;
+    // Search for the address in the FIFO queue to update the score
+    for (const SandboxEntry &entry: entries) {
+        if (entry.valid && entry.line == addr) {
+            sandboxScore++;
+            if (entry.expectedArrivalTick > curTick()) {
+                lateScore++;
+            }
+        }
     }
+
+    // Insert new access in this sandbox
+    SandboxEntry entry;
+    entry.valid = true;
+    entry.line = addr + stride;
+    entry.expectedArrivalTick = tick;
+    entries.push_back(entry);
 }
 
 bool
 SBOOE::access(Addr access_line)
 {
     for (Sandbox &sb : sandboxes) {
-        // Search for the address in the FIFO queue
-        for (const SandboxEntry &entry: sb.entries) {
-            if (entry.valid && entry.line == access_line) {
-                sb.sandboxScore++;
-                if (entry.expectedArrivalTick > curTick()) {
-                    sb.lateScore++;
-                }
-            }
-        }
-
-        sb.insert(access_line, curTick() + averageAccessLatency);
+        sb.access(access_line, curTick() + averageAccessLatency);
 
         if (bestSandbox == NULL || sb.score() > bestSandbox->score()) {
             bestSandbox = &sb;
@@ -106,14 +99,12 @@
     if (it != demandAddresses.end()) {
         Tick elapsed_ticks = curTick() - it->second;
 
+        if (latencyBuffer.full()) {
+            latencyBufferSum -= latencyBuffer.front();
+        }
         latencyBuffer.push_back(elapsed_ticks);
         latencyBufferSum += elapsed_ticks;
 
-        if (latencyBuffer.size() > latencyBufferSize) {
-            latencyBufferSum -= latencyBuffer.front();
-            latencyBuffer.pop_front();
-        }
-
         averageAccessLatency = latencyBufferSum / latencyBuffer.size();
 
         demandAddresses.erase(it);
diff --git a/src/mem/cache/prefetch/sbooe.hh b/src/mem/cache/prefetch/sbooe.hh
index 8076732..42deaf3 100644
--- a/src/mem/cache/prefetch/sbooe.hh
+++ b/src/mem/cache/prefetch/sbooe.hh
@@ -35,10 +35,10 @@
 #ifndef __MEM_CACHE_PREFETCH_SBOOE_HH__
 #define __MEM_CACHE_PREFETCH_SBOOE_HH__
 
-#include <deque>
 #include <unordered_map>
 #include <vector>
 
+#include "base/circular_queue.hh"
 #include "mem/cache/prefetch/queued.hh"
 #include "mem/packet.hh"
 
@@ -51,7 +51,6 @@
     private:
 
         /** Prefetcher parameters */
-        const int latencyBufferSize;
         const int sequentialPrefetchers;
 
         /** Threshold used to issue prefetchers */
@@ -70,7 +69,7 @@
          * calculate the average access latency which is later used to
          * predict if a prefetcher would be filled on time if issued.
          */
-        std::deque<Tick> latencyBuffer;
+        CircularQueue<Tick> latencyBuffer;
 
         /** Holds the current average access latency */
         Tick averageAccessLatency;
@@ -91,48 +90,51 @@
             {}
         };
 
-        struct Sandbox {
-            /** FIFO queue. Max entries is 'sandboxEntries' */
-            std::vector<SandboxEntry> entries;
+        class Sandbox
+        {
+          private:
+            /** FIFO queue containing the sandbox entries. */
+            CircularQueue<SandboxEntry> entries;
+
             /**
              * Accesses during the eval period that were present
              * in the sandbox
              */
             unsigned int sandboxScore;
+
             /** Hits in the sandbox that wouldn't have been filled on time */
             unsigned int lateScore;
-            /** Index of the oldest entry in the FIFO */
-            unsigned int index;
+
+          public:
             /** Sequential stride for this prefetcher */
             const int stride;
 
             Sandbox(unsigned int max_entries, int _stride)
-                : sandboxScore(0), lateScore(0), index(0), stride(_stride)
+              : entries(max_entries), sandboxScore(0), lateScore(0),
+                stride(_stride)
             {
-                entries.resize(max_entries);
             }
 
             /**
-             * Insert the line address being accessed to the cache into the
+             * Update score and insert the line address being accessed into the
              * FIFO queue of the sandbox.
+             *
              * @param line Line address being accessed
              * @param tick Tick in which the access is expected to be filled
              */
-            void insert(Addr line, Tick tick);
+            void access(Addr line, Tick tick);
 
             /** Calculate the useful score
              *  @return Useful score of the sandbox. Sandbox score adjusted by
              *          by the late score
              */
-            unsigned int score() const {
-                return (sandboxScore - lateScore);
-            }
+            unsigned int score() const { return (sandboxScore - lateScore); }
         };
 
         std::vector<Sandbox> sandboxes;
 
         /** Current best sandbox */
-        Sandbox * bestSandbox;
+        const Sandbox* bestSandbox;
 
         /** Number of accesses notified to the prefetcher */
         unsigned int accesses;