Brown, N. T., & Sendag, R. Sandbox Based Optimal Offset Estimation.
Change-Id: Ieb693b6b2c3d8bdfb6948389ca10e92c85454862
Reviewed-on: https://gem5-review.googlesource.com/c/15095
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
delay_queue_cycles = Param.Cycles(60,
"Cycles to delay a write in the left RR table from the delay \
queue")
+
+class SBOOEPrefetcher(QueuedPrefetcher):
+ type = 'SBOOEPrefetcher'
+ cxx_class = 'SBOOEPrefetcher'
+ cxx_header = "mem/cache/prefetch/sbooe.hh"
+ latency_buffer_size = Param.Int(32, "Entries in the latency buffer")
+ sequential_prefetchers = Param.Int(9, "Number of sequential prefetchers")
+ sandbox_entries = Param.Int(1024, "Size of the address buffer")
+ score_threshold_pct = Param.Percent(25, "Min. threshold to issue a \
+ prefetch. The value is the percentage of sandbox entries to use")
Source('delta_correlating_prediction_tables.cc')
Source('irregular_stream_buffer.cc')
Source('queued.cc')
+Source('sbooe.cc')
Source('signature_path.cc')
Source('signature_path_v2.cc')
Source('slim_ampm.cc')
--- /dev/null
+/**
+ * Copyright (c) 2018 Metempsy Technology Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ivan Pizarro
+ */
+
+#include "mem/cache/prefetch/sbooe.hh"
+
+#include "debug/HWPrefetch.hh"
+#include "params/SBOOEPrefetcher.hh"
+
+SBOOEPrefetcher::SBOOEPrefetcher(const SBOOEPrefetcherParams *p)
+ : QueuedPrefetcher(p),
+ latencyBufferSize(p->latency_buffer_size),
+ sequentialPrefetchers(p->sequential_prefetchers),
+ scoreThreshold((p->sandbox_entries*p->score_threshold_pct)/100),
+ 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++) {
+ sandboxes.push_back(Sandbox(p->sandbox_entries, i-1));
+ }
+}
+
+void
+SBOOEPrefetcher::Sandbox::insert(Addr addr, Tick tick)
+{
+ entries[index].valid = true;
+ entries[index].line = addr + stride;
+ entries[index].expectedArrivalTick = tick;
+
+ index++;
+
+ if (index == entries.size()) {
+ index = 0;
+ }
+}
+
+bool
+SBOOEPrefetcher::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);
+
+ if (bestSandbox == NULL || sb.score() > bestSandbox->score()) {
+ bestSandbox = &sb;
+ }
+ }
+
+ accesses++;
+
+ return (accesses >= sandboxes.size());
+}
+
+void
+SBOOEPrefetcher::notifyFill(const PacketPtr& pkt)
+{
+ // (1) Look for the address in the demands list
+ // (2) Calculate the elapsed cycles until it was filled (curTick)
+ // (3) Insert the latency into the latency buffer (FIFO)
+ // (4) Calculate the new average access latency
+
+ auto it = demandAddresses.find(pkt->getAddr());
+
+ if (it != demandAddresses.end()) {
+ Tick elapsed_ticks = curTick() - it->second;
+
+ 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);
+ }
+}
+
+void
+SBOOEPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
+ std::vector<AddrPriority> &addresses)
+{
+ const Addr pfi_addr = pfi.getAddr();
+ const Addr pfi_line = pfi_addr >> lBlkSize;
+
+ auto it = demandAddresses.find(pfi_addr);
+
+ if (it == demandAddresses.end()) {
+ demandAddresses.insert(std::pair<Addr, Tick>(pfi_addr, curTick()));
+ }
+
+ const bool evaluationFinished = access(pfi_line);
+
+ if (evaluationFinished && bestSandbox->score() > scoreThreshold) {
+ Addr pref_line = pfi_line + bestSandbox->stride;
+ addresses.push_back(AddrPriority(pref_line << lBlkSize, 0));
+ }
+}
+
+SBOOEPrefetcher*
+SBOOEPrefetcherParams::create()
+{
+ return new SBOOEPrefetcher(this);
+}
--- /dev/null
+/**
+ * Copyright (c) 2018 Metempsy Technology Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ivan Pizarro
+ */
+
+/**
+ * Implementation of the 'Sandbox Based Optimal Offset Estimation'
+ * Reference:
+ * Brown, N. T., & Sendag, R. Sandbox Based Optimal Offset Estimation.
+*/
+
+#ifndef __MEM_CACHE_PREFETCH_SBOOE_HH__
+#define __MEM_CACHE_PREFETCH_SBOOE_HH__
+
+#include <deque>
+#include <unordered_map>
+#include <vector>
+
+#include "mem/cache/prefetch/queued.hh"
+#include "mem/packet.hh"
+
+struct SBOOEPrefetcherParams;
+
+class SBOOEPrefetcher : public QueuedPrefetcher
+{
+ private:
+
+ /** Prefetcher parameters */
+ const int latencyBufferSize;
+ const int sequentialPrefetchers;
+
+ /** Threshold used to issue prefetchers */
+ const unsigned int scoreThreshold;
+
+ /**
+ * Holds the current demand addresses and tick. This is later used to
+ * calculate the average latency buffer when the address is filled in
+ * the cache.
+ */
+ std::unordered_map<Addr, Tick> demandAddresses;
+
+ /**
+ * The latency buffer holds the elapsed ticks between the demand and
+ * the fill in the cache for the latest N accesses which are used to
+ * 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;
+
+ /** Holds the current average access latency */
+ Tick averageAccessLatency;
+
+ /** Holds the current sum of the latency buffer latency */
+ Tick latencyBufferSum;
+
+ struct SandboxEntry {
+ /** Cache line predicted by the candidate prefetcher */
+ Addr line;
+ /** Tick when the simulated prefetch is expected to be filled */
+ Tick expectedArrivalTick;
+ /** To indicate if it was initialized */
+ bool valid;
+
+ SandboxEntry()
+ : valid(false)
+ {}
+ };
+
+ struct Sandbox {
+ /** FIFO queue. Max entries is 'sandboxEntries' */
+ std::vector<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;
+ /** Sequential stride for this prefetcher */
+ const int stride;
+
+ Sandbox(unsigned int max_entries, int _stride)
+ : sandboxScore(0), lateScore(0), index(0), stride(_stride)
+ {
+ entries.resize(max_entries);
+ }
+
+ /**
+ * Insert the line address being accessed to the cache 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);
+
+ /** 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);
+ }
+ };
+
+ std::vector<Sandbox> sandboxes;
+
+ /** Current best sandbox */
+ Sandbox * bestSandbox;
+
+ /** Number of accesses notified to the prefetcher */
+ unsigned int accesses;
+
+ /**
+ * Process an access to the specified line address and update the
+ * sandbox counters counters.
+ * @param line Address of the line being accessed
+ * @return TRUE if the evaluation finished, FALSE otherwise
+ */
+ bool access(Addr line);
+
+ /** Update the latency buffer after a prefetch fill */
+ void notifyFill(const PacketPtr& pkt) override;
+
+ public:
+ SBOOEPrefetcher(const SBOOEPrefetcherParams *p);
+
+ void calculatePrefetch(const PrefetchInfo &pfi,
+ std::vector<AddrPriority> &addresses) override;
+};
+
+#endif // __MEM_CACHE_PREFETCH_SBOOE_HH__