Hello Giacomo Travaglini, Andreas Sandberg,

I'd like you to do a code review. Please visit

    https://gem5-review.googlesource.com/c/public/gem5/+/14819

to review the following change.


Change subject: mem-cache: Updated version of the Signature Path Preftcher
......................................................................

mem-cache: Updated version of the Signature Path Preftcher

This implementation is based in the description available in:
  Jinchun Kim, Seth H. Pugsley, Paul V. Gratz, A. L. Narasimha Reddy,
  Chris Wilkerson, and Zeshan Chishti. 2016.
  Path confidence based lookahead prefetching.
  In The 49th Annual IEEE/ACM International Symposium on Microarchitecture
  (MICRO-49). IEEE Press, Piscataway, NJ, USA, Article 60, 12 pages.

Change-Id: I4b8b54efef48ced7044bd535de9a69bca68d47d9
---
M src/mem/cache/prefetch/Prefetcher.py
M src/mem/cache/prefetch/SConscript
M src/mem/cache/prefetch/signaturepath.cc
M src/mem/cache/prefetch/signaturepath.hh
A src/mem/cache/prefetch/signaturepathv2.cc
A src/mem/cache/prefetch/signaturepathv2.hh
6 files changed, 523 insertions(+), 72 deletions(-)



diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py
index a4ae3e3..b3ac840 100644
--- a/src/mem/cache/prefetch/Prefetcher.py
+++ b/src/mem/cache/prefetch/Prefetcher.py
@@ -189,3 +189,30 @@
         "Minimum confidence to issue prefetches")
     lookahead_confidence_threshold = Param.Float(0.75,
         "Minimum confidence to continue exploring lookahead entries")
+
+class SignaturePathPrefetcherV2(SignaturePathPrefetcher):
+    type = 'SignaturePathPrefetcherV2'
+    cxx_class = 'SignaturePathPrefetcherV2'
+    cxx_header = "mem/cache/prefetch/signaturepathv2.hh"
+
+    signature_table_entries = "256"
+    signature_table_assoc = 1
+    pattern_table_entries = "512"
+    pattern_table_assoc = 1
+    filter_table_entries = "1024"
+    filter_table_assoc = 1
+    max_counter_value = 15
+    prefetch_confidence_threshold = 0.25
+    lookahead_confidence_threshold = 0.25
+
+    global_history_register_entries = Param.MemorySize("8",
+        "Number of entries of global history register")
+    global_history_register_assoc = Param.Unsigned(1,
+        "Associativity of the global history register")
+    global_history_register_indexing_policy = Param.BaseIndexingPolicy(
+        SetAssociative(entry_size = 1,
+        assoc = Parent.global_history_register_assoc,
+        size = Parent.global_history_register_entries),
+        "Indexing policy of the global history register")
+ global_history_register_replacement_policy = Param.BaseReplacementPolicy(
+        LRURP(), "Replacement policy of the global history register")
diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript
index f8a3d83..c033aef 100644
--- a/src/mem/cache/prefetch/SConscript
+++ b/src/mem/cache/prefetch/SConscript
@@ -37,3 +37,4 @@
 Source('stride.cc')
 Source('tagged.cc')
 Source('signaturepath.cc')
+Source('signaturepathv2.cc')
diff --git a/src/mem/cache/prefetch/signaturepath.cc b/src/mem/cache/prefetch/signaturepath.cc
index 07e0e18..2d00b63 100644
--- a/src/mem/cache/prefetch/signaturepath.cc
+++ b/src/mem/cache/prefetch/signaturepath.cc
@@ -69,26 +69,36 @@
     assert(isPowerOf2(filterTableAssoc));
 }

-void
-SignaturePathPrefetcher::updateFilter(FilterEntry &filter_entry, Addr ppn,
-                                      bool is_secure)
+SignaturePathPrefetcher::FilterEntry *
+SignaturePathPrefetcher::updateFilter(Addr addr, bool is_secure)
 {
-    // Check on positions set if the block has been evicted from the cache
-    // cache evictions are supposed to reset entries that were set to 1
- for (Addr block_id = 0; block_id < (pageBytes/blkSize); block_id += 1) {
-        if (filter_entry.bitmap[block_id]) {
-            filter_entry.bitmap[block_id] =
-                inCache(ppn + block_id * blkSize, is_secure);
+    Addr ppn = addr / pageBytes;
+    Addr hashed_ppn = ppnHash(ppn);
+ FilterEntry* filter_entry = filterTable.findEntry(hashed_ppn, is_secure);
+    if (filter_entry != nullptr) {
+ // Check on positions set if the block has been evicted from the cache
+        // cache evictions are supposed to reset entries that were set to 1
+        for (Addr block_id = 0;
+             block_id < (pageBytes/blkSize);
+             block_id += 1)
+        {
+            if (filter_entry->bitmap[block_id]) {
+                filter_entry->bitmap[block_id] =
+                    inCache(ppn + block_id * blkSize, is_secure);
+            }
         }
     }
+    return filter_entry;
 }

 SignaturePathPrefetcher::FilterEntry *
SignaturePathPrefetcher::filterAndAddPrefetch(FilterEntry *orig_filter_entry,
-    Addr ppn, stride_t block, bool is_secure,
+    Addr ppn, stride_t last_block, stride_t delta, double path_confidence,
+    signature_t current_signature, bool is_secure,
     std::vector<AddrPriority> &addresses)
 {
     FilterEntry *filter_entry = orig_filter_entry;
+    stride_t block = last_block + delta;
     /**
* block is relative to the provided ppn. Assuming a page size of 4kB and
      * a block size of 64B, the range of the stride of this prefetcher is
@@ -141,6 +151,16 @@
 }

 void
+SignaturePathPrefetcher::handleSignatureTableMiss(int8_t current_block,
+    signature_t &new_signature, double &new_conf, stride_t &new_stride)
+    const
+{
+    new_signature = current_block;
+    new_conf = 1.0;
+    new_stride = current_block;
+}
+
+void
 SignaturePathPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
                                  std::vector<AddrPriority> &addresses)
 {
@@ -151,12 +171,10 @@
     int8_t current_stride;
     bool is_secure = pfi.isSecure();

- FilterEntry* filter_entry = filterTable.findEntry(hashed_ppn, is_secure);
-    if (filter_entry != nullptr) {
-        // if the entry for this page exists, update the entries that
-        // may have been evicted
-        updateFilter(*filter_entry, ppn, is_secure);
-    }
+    signature_t initial_signature = 0;
+    double initial_confidence = 1.0;
+
+    FilterEntry* filter_entry = updateFilter(request_addr, is_secure);

     SignatureEntry* signature_entry =
         signatureTable.findEntry(hashed_ppn, is_secure);
@@ -166,11 +184,14 @@
     } else {
         signature_entry = signatureTable.findVictim(hashed_ppn);
         assert(signature_entry != nullptr);
-
         signature_entry->setValid();
-        signature_entry->signature =
-            signature_entry->lastBlock = current_block;
-        current_stride = current_block;
+
+        stride_t initial_stride;
+        handleSignatureTableMiss(current_block, initial_signature,
+            initial_confidence, initial_stride);
+        signature_entry->signature = initial_signature;
+        signature_entry->lastBlock = current_block;
+        current_stride = initial_stride;
         signatureTable.insertEntry(hashed_ppn, is_secure, signature_entry);
     }

@@ -231,18 +252,16 @@
         }
     }

-    if (pstride_entry->counter < maxCounterValue) {
-        pstride_entry->counter += 1;
-    }
+    increasePatternEntryCounter(*pattern_entry, *pstride_entry);

     signature_entry->signature =
         updateSignature(signature_entry->signature, current_stride);
     signature_entry->lastBlock = current_block;

     signature_t current_signature = signature_entry->signature;
-    double current_confidence = 1.0;

-    do {
+    double current_confidence = initial_confidence;
+    while (current_confidence > lookaheadConfidenceThreshold) {
         pattern_entry = patternTable.findEntry(current_signature, false);
         PatternStrideEntry *lookahead = nullptr;
         if (pattern_entry != nullptr) {
@@ -254,55 +273,77 @@
                     lookahead = &entry;
                 }
                 double prefetch_confidence =
-                    (double) entry.counter / maxCounterValue;
+                    prefetchConfidence(*pattern_entry, entry);

                 if (prefetch_confidence >= prefetchConfidenceThreshold) {
                     //prefetch candidate
- stride_t block = signature_entry->lastBlock + entry.stride;
                     filter_entry = filterAndAddPrefetch(filter_entry, ppn,
-                            block, is_secure,
+                            signature_entry->lastBlock, entry.stride,
+ current_confidence, current_signature, is_secure,
                             addresses);
                 }
             }
         }
         if (lookahead != nullptr) {
-            double lookahead_confidence;
-            if (lookahead->counter == maxCounterValue) {
-                /**
-                 * maximum confidence is 0.95, guaranteeing that
-                 * current confidence will eventually fall beyond
-                 * the threshold
-                 */
-                lookahead_confidence = 0.95;
-            } else {
-                lookahead_confidence =
-                    ((double) lookahead->counter / maxCounterValue);
-            }
-            current_confidence *= lookahead_confidence;
+            current_confidence *= lookaheadConfidence(*pattern_entry,
+                                                      *lookahead);
             current_signature =
                 updateSignature(current_signature, lookahead->stride);
         } else {
             current_confidence = 0.0;
         }
     }
-    while (current_confidence > lookaheadConfidenceThreshold);

+    filter_entry = auxiliaryPrefetcher(filter_entry, ppn, current_block,
+                                       is_secure, addresses);
+}
+
+SignaturePathPrefetcher::FilterEntry *
+SignaturePathPrefetcher::auxiliaryPrefetcher(FilterEntry *filter_entry,
+        Addr ppn, int8_t current_block, bool is_secure,
+        std::vector<AddrPriority> &addresses)
+{
     if (addresses.empty()) {
//enable the next line prefetcher if no prefetch candidates are found
         filter_entry = filterAndAddPrefetch(filter_entry, ppn,
- current_block + 1, is_secure, addresses); + current_block, 1, 0.0 /* unused*/ , 0 /* unused */, is_secure,
+                addresses);
     }
-
-
+    return filter_entry;
 }

-inline Addr
-SignaturePathPrefetcher::ppnHash(Addr ppn) const
+void
+SignaturePathPrefetcher::increasePatternEntryCounter(
+        PatternEntry &pattern_entry, PatternStrideEntry &pstride_entry)
 {
-    int num_signature_sets = signatureTableEntries/signatureTableAssoc;
-    Addr hash1 = ppn >> 1;
-    Addr hash2 = hash1 >> floorLog2(num_signature_sets);
-    return (hash1 ^ hash2) & (Addr)(num_signature_sets - 1);
+    if (pstride_entry.counter < maxCounterValue) {
+        pstride_entry.counter += 1;
+    }
+}
+
+double
+SignaturePathPrefetcher::lookaheadConfidence(PatternEntry const &sig,
+        PatternStrideEntry const &lookahead) const
+{
+    double lookahead_confidence;
+    if (lookahead.counter == maxCounterValue) {
+        /**
+         * maximum confidence is 0.95, guaranteeing that
+         * current confidence will eventually fall beyond
+         * the threshold
+         */
+        lookahead_confidence = 0.95;
+    } else {
+ lookahead_confidence = ((double) lookahead.counter / maxCounterValue);
+    }
+    return lookahead_confidence;
+}
+
+double
+SignaturePathPrefetcher::prefetchConfidence(PatternEntry const &sig,
+        PatternStrideEntry const &entry) const
+{
+    return ((double) entry.counter) / maxCounterValue;
 }

 SignaturePathPrefetcher*
diff --git a/src/mem/cache/prefetch/signaturepath.hh b/src/mem/cache/prefetch/signaturepath.hh
index 294c597..8707b04 100644
--- a/src/mem/cache/prefetch/signaturepath.hh
+++ b/src/mem/cache/prefetch/signaturepath.hh
@@ -48,6 +48,7 @@

 class SignaturePathPrefetcher : public QueuedPrefetcher
 {
+  protected:
     /** Signature type */
     typedef uint16_t signature_t;
     /** Stride type */
@@ -106,6 +107,8 @@
     {
         /** group of stides */
         std::vector<PatternStrideEntry> strideEntries;
+        /** use counter, used by SPPv2 */
+        uint8_t counter;
         PatternEntry() : strideEntries()
         {}
     };
@@ -117,7 +120,9 @@
     {
         /** bitmap with the already accessed blocks of a page */
         std::vector<bool> bitmap;
-        FilterEntry() : bitmap()
+        /** tag entry for SPPv2 */
+        Addr tag;
+        FilterEntry() : bitmap(), tag(0)
         {}
     };
     /** Filter table */
@@ -129,7 +134,8 @@
      * @param str stride to add to the new signature
      * @result the new signature
      */
- inline signature_t updateSignature(signature_t sig, stride_t str) const {
+    inline signature_t updateSignature(signature_t sig, stride_t str) const
+    {
         sig <<= signatureShift;
         sig ^= str;
         sig &= (1<<signatureBits)-1;
@@ -137,40 +143,104 @@
     }

     /**
-     * Updates the filter entry for the given page entry, it checks
-     * if the blocks marked as prefetched have been evicted from the cache
-     * @param filter_entry entry to update
-     * @param ppn page number of the entry
-     * @param is_secure whether this page is inside the secure memory area
+     * Hash function to calculate the signature table key
+     * @param ppn the physical page number
+     * @return the computed hash
      */
-    void updateFilter(FilterEntry &filter_entry, Addr ppn, bool is_secure);
+    inline Addr ppnHash(Addr ppn) const
+    {
+        int num_signature_sets = signatureTableEntries/signatureTableAssoc;
+        Addr hash1 = ppn >> 1;
+        Addr hash2 = hash1 >> floorLog2(num_signature_sets);
+        return (hash1 ^ hash2) & (Addr)(num_signature_sets - 1);
+    }
+
+    /**
+     * Checks if the filter entry exists for this address it checks
+     * if the blocks marked as prefetched have been evicted from the cache
+     * @param addr address of this request
+     * @param is_secure whether this page is inside the secure memory area
+     * @return pointer to the corresponding FilterEntry if it existed,
+     *        nullptr otherwise
+     */
+    virtual FilterEntry *updateFilter(Addr addr, bool is_secure);

     /**
      * Filters an address and adds it to the address vector if the filter
      * entry does not indicate that it would be a redundant prefetch.
* This function also checks if the block falls within the provided page
      * if not, the prefetch is also ignored.
-     * @param filter_entry the filter entry, it can be NULL if there is no
+ * @param filter_entry the filter entry, it can be nullptr if there is no * entry allocated in the table, in this case, a victim is selected
      *        and a new entry is assigned to this page
      * @param ppn page number to prefetch from
- * @param block block number within the page, this value can be negative,
-     *        which means that the block refered is actualy in the previous
- * page (ppn-1), if the value is greater than (pageBytes/blkSize-1)
-     *        then the block refers to a block within the next page (ppn+1)
+ * @param last_block last block (cacheline) accessed in the provided ppn + * @param delta difference, in blocks, from the last_block accessed to the
+     *        block to prefetch (the block to prefetch is computed by this
+     *        formula: ppn * pageBytes + (last_block + delta) * blkSize.
+     *        This value can be negative.
+     * @param path_confidence the confidence factor of this prefetch
+ * @paran current_signature signature used to index the current signature
+     *        table entry, and caused this prefetch
      * @param is_secure whether this page is inside the secure memory area
- * @param addresses if allowed, the address will be added to this vector + * @param addresses the addresses to be prefetched are added to this vector
      * @return a pointer to the filter entry
      */
-    FilterEntry *filterAndAddPrefetch(FilterEntry *filter_entry, Addr ppn,
-                                      stride_t block, bool is_secure,
- std::vector<AddrPriority> &addresses);
+    virtual FilterEntry *filterAndAddPrefetch(FilterEntry *filter_entry,
+            Addr ppn, stride_t last_block, stride_t delta,
+            double path_confidence, signature_t current_signature,
+            bool is_secure, std::vector<AddrPriority> &addresses);
+
     /**
-     * Hash function to calculate the signature table key
-     * @param ppn the physical page number
-     * @return the computed hash
+     * Computes the lookahead path confidence of the provided pattern entry
+     * @param sig the PatternEntry to use
+     * @param lookahead PatternStrideEntry within the provided PatternEntry
+     * @return the computed confidence factor
      */
-    Addr ppnHash(Addr ppn) const;
+    virtual double lookaheadConfidence(PatternEntry const &sig,
+            PatternStrideEntry const &lookahead) const;
+
+    /**
+     * Computes the prefetch confidence of the provided pattern entry
+     * @param sig the PatternEntry to use
+     * @param entry PatternStrideEntry within the provided PatternEntry
+     * @return the computed confidence factor
+     */
+    virtual double prefetchConfidence(PatternEntry const &sig,
+            PatternStrideEntry const &lookahead) const;
+
+    /**
+     * Increases the counter of a given PatternEntry/PatternStrideEntry
+     * @param pattern_entry the corresponding PatternEntry
+     * @param pstride_entry the PatternStrideEntry within the PatternEntry
+     */
+    virtual void increasePatternEntryCounter(PatternEntry &pattern_entry,
+            PatternStrideEntry &pstride_entry);
+
+    /**
+     * Increases the counter of a given PatternEntry/PatternStrideEntry
+     * @param pattern_entry the corresponding PatternEntry
+     * @param pstride_entry the PatternStrideEntry within the PatternEntry
+     */
+    virtual void handleSignatureTableMiss(int8_t current_block,
+            signature_t &new_signature, double &new_conf,
+            stride_t &new_stride) const;
+
+    /**
+     * Auxiliar prefetch mechanism used at the end of calculatePrefetch.
+     * This prefetcher uses this to activate the next line prefetcher if
+     * no prefetch candidates have been found.
+ * @param filter_entry the filter entry, it can be nullptr if there is no + * entry allocated in the table, in this case, a victim is selected
+     *        and a new entry is assigned to this page
+     * @param ppn physical page number of the current accessed page
+     * @param current_block block (cacheline) accessed within the page
+     * @param is_secure whether this page is inside the secure memory area
+ * @param addresses the addresses to be prefetched are added to this vector
+     */
+    virtual FilterEntry *auxiliaryPrefetcher(FilterEntry *filter_entry,
+            Addr ppn, int8_t current_block, bool is_secure,
+            std::vector<AddrPriority> &addresses);

   public:
     SignaturePathPrefetcher(const SignaturePathPrefetcherParams* p);
diff --git a/src/mem/cache/prefetch/signaturepathv2.cc b/src/mem/cache/prefetch/signaturepathv2.cc
new file mode 100644
index 0000000..8515d9c
--- /dev/null
+++ b/src/mem/cache/prefetch/signaturepathv2.cc
@@ -0,0 +1,204 @@
+/**
+ * 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: Javier Bueno
+ */
+
+#include "mem/cache/prefetch/signaturepathv2.hh"
+
+#include <cassert>
+
+#include "debug/HWPrefetch.hh"
+#include "mem/cache/prefetch/associative_set_impl.hh"
+#include "params/SignaturePathPrefetcherV2.hh"
+
+SignaturePathPrefetcherV2::SignaturePathPrefetcherV2(
+    const SignaturePathPrefetcherV2Params *p)
+    : SignaturePathPrefetcher(p),
+      globalHistoryRegister(p->global_history_register_entries,
+                            GlobalHistoryEntry())
+{
+}
+
+SignaturePathPrefetcherV2::FilterEntry *
+SignaturePathPrefetcherV2::updateFilter(Addr addr, bool is_secure)
+{
+    // Check on positions set if the block has been evicted from the cache
+    // cache evictions are supposed to reset entries that were set to 1
+    Addr cacheline = blockAddress(addr);
+ FilterEntry* filter_entry = filterTable.findEntry(cacheline, is_secure);
+    if (filter_entry != nullptr) {
+        if (filter_entry->bitmap[FILTER_ENTRY_VALID]) {
+            // check if the cache has evicted this line first, if so,
+            // the prefetcher would had observed the eviction and it would
+            // had invalidated this entry
+            filter_entry->bitmap[FILTER_ENTRY_VALID] =
+                inCache(cacheline, is_secure);
+
+ // if this entry is still valid, check increase the used prefetches
+            // counter if this line was not counted yet
+            if (filter_entry->bitmap[FILTER_ENTRY_VALID]) {
+                if (!filter_entry->bitmap[FILTER_ENTRY_USED]) {
+                    usefulPrefetches += 1;
+                    filter_entry->bitmap[FILTER_ENTRY_USED] = true;
+                }
+            }
+        }
+    }
+    return filter_entry;
+}
+
+SignaturePathPrefetcherV2::FilterEntry *
+SignaturePathPrefetcherV2::filterAndAddPrefetch(FilterEntry *orig_filter_entry,
+    Addr ppn, stride_t last_block, stride_t delta, double path_confidence,
+    signature_t current_signature, bool is_secure,
+    std::vector<AddrPriority> &addresses)
+{
+    FilterEntry *filter_entry = orig_filter_entry;
+    stride_t block = last_block + delta;
+    /**
+ * block is relative to the provided ppn. Assuming a page size of 4kB and
+     * a block size of 64B, the range of the stride of this prefetcher is
+ * -63,63 (pageBytes/blkSize) as the last accessed block also ranges from
+     * 0,63, the block value is expected to be between -63 and 126
+ * Negative block means that we are accessing the lower contiguous page,
+     * 64 or greater point to the next contiguous.
+     */
+    assert(block > -((stride_t)(pageBytes/blkSize)) &&
+           block < 2*((stride_t)(pageBytes/blkSize)));
+
+    Addr pf_ppn;
+    stride_t pf_block;
+    if (block < 0) {
+        pf_ppn = ppn - 1;
+        pf_block = block + (pageBytes/blkSize);
+ //insertToGHR(current_signature, path_confidence, last_block, delta);
+    } else if (block >= (pageBytes/blkSize)) {
+        pf_ppn = ppn + 1;
+        pf_block = block - (pageBytes/blkSize);
+ //insertToGHR(current_signature, path_confidence, last_block, delta);
+    } else {
+        pf_ppn = ppn;
+        pf_block = block;
+    }
+
+    Addr new_addr = pf_ppn * pageBytes;
+    new_addr += pf_block * (Addr)blkSize;
+    //filter entry was not allocated, allocate now
+    if (filter_entry == nullptr) {
+        filter_entry = filterTable.findVictim(blockAddress(new_addr));
+        assert(filter_entry != nullptr);
+        if (!filter_entry->isValid()) {
+            filter_entry->setValid();
+            filter_entry->bitmap.resize(2, false); // two entries only
+        }
+        filterTable.insertEntry(blockAddress(new_addr), is_secure,
+                                filter_entry);
+    }
+    if (!filter_entry->bitmap[FILTER_ENTRY_VALID]) {
+        DPRINTF(HWPrefetch, "Queuing prefetch to %#x.\n", new_addr);
+        addresses.push_back(AddrPriority(new_addr, 0));
+        filter_entry->bitmap[FILTER_ENTRY_VALID] = true;
+        totalPrefetches += 1;
+    } else {
+        DPRINTF(HWPrefetch, "Filter out prefetch to %#x.\n", new_addr);
+    }
+    if (pf_ppn == ppn) {
+        return filter_entry;
+    } else {
+        return orig_filter_entry;
+    }
+}
+
+void
+SignaturePathPrefetcherV2::handleSignatureTableMiss(int8_t current_block,
+    signature_t &new_signature, double &new_conf, stride_t &new_stride)
+    const
+{
+    bool found = false;
+    for (auto &gh_entry : globalHistoryRegister) {
+        if (gh_entry.lastBlock + gh_entry.delta == current_block) {
+            new_signature = gh_entry.signature;
+            new_conf = gh_entry.confidence;
+            new_stride = gh_entry.delta;
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        new_signature = current_block;
+        new_conf = 1.0;
+        new_stride = current_block;
+    }
+}
+
+double SignaturePathPrefetcherV2::lookaheadConfidence(PatternEntry const &sig,
+        PatternStrideEntry const &lookahead) const
+{
+    if (sig.counter == 0) return 0.0;
+    return (((double) usefulPrefetches) / totalPrefetches) *
+            (((double) lookahead.counter) / sig.counter);
+}
+
+double SignaturePathPrefetcherV2::prefetchConfidence(PatternEntry const &sig,
+        PatternStrideEntry const &entry) const
+{
+    if (sig.counter == 0) return 0.0;
+    return ((double) entry.counter) / sig.counter;
+}
+
+void SignaturePathPrefetcherV2::increasePatternEntryCounter(
+        PatternEntry &pattern_entry, PatternStrideEntry &pstride_entry) {
+    if (pattern_entry.counter == maxCounterValue) {
+        pattern_entry.counter >>= 1;
+        for (auto &entry : pattern_entry.strideEntries) {
+            entry.counter >>= 1;
+        }
+    }
+    if (pstride_entry.counter == maxCounterValue) {
+        pattern_entry.counter >>= 1;
+        for (auto &entry : pattern_entry.strideEntries) {
+            entry.counter >>= 1;
+        }
+    }
+    pattern_entry.counter += 1;
+    pstride_entry.counter += 1;
+}
+
+SignaturePathPrefetcherV2::FilterEntry *
+SignaturePathPrefetcherV2::auxiliaryPrefetcher(FilterEntry *filter_entry,
+        Addr ppn, int8_t current_block, bool is_secure,
+        std::vector<AddrPriority> &addresses)
+{
+    return filter_entry;
+}
+
+SignaturePathPrefetcherV2*
+SignaturePathPrefetcherV2Params::create()
+{
+    return new SignaturePathPrefetcherV2(this);
+}
diff --git a/src/mem/cache/prefetch/signaturepathv2.hh b/src/mem/cache/prefetch/signaturepathv2.hh
new file mode 100644
index 0000000..a778c77
--- /dev/null
+++ b/src/mem/cache/prefetch/signaturepathv2.hh
@@ -0,0 +1,108 @@
+/**
+ * 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: Javier Bueno
+ */
+
+ /**
+  * Implementation of the Signature Path Prefetcher (v2)
+  *
+  * References:
+  *     Path confidence based lookahead prefetching
+  *     Jinchun Kim, Seth H. Pugsley, Paul V. Gratz, A. L. Narasimha Reddy,
+  *     Chris Wilkerson, and Zeshan Chishti. 2016.
+  *     In The 49th Annual IEEE/ACM International Symposium on
+  *     Microarchitecture (MICRO-49). IEEE Press, Piscataway, NJ, USA,
+  *     Article 60, 12 pages.
+  */
+
+#ifndef __MEM_CACHE_PREFETCH_SPPV2_HH__
+#define __MEM_CACHE_PREFETCH_SPPV2_HH__
+
+#include "mem/cache/prefetch/associative_set.hh"
+#include "mem/cache/prefetch/queued.hh"
+#include "mem/cache/prefetch/signaturepath.hh"
+#include "mem/packet.hh"
+
+struct SignaturePathPrefetcherV2Params;
+
+class SignaturePathPrefetcherV2 : public SignaturePathPrefetcher
+{
+    /** Global History Register entry datatype */
+    struct GlobalHistoryEntry
+    {
+        signature_t signature;
+        double confidence;
+        stride_t lastBlock;
+        stride_t delta;
+        GlobalHistoryEntry() : signature(0), confidence(0.0), lastBlock(0),
+                               delta(0) {}
+    };
+    /** Global History Register */
+    std::vector<GlobalHistoryEntry> globalHistoryRegister;
+
+    /** Index of the PatternStrideEntry bitmap */
+    enum FilterBitmapIndices {
+        FILTER_ENTRY_VALID = 0,
+        FILTER_ENTRY_USED = 1
+    };
+
+    /** Total prefetches issued */
+    uint16_t totalPrefetches;
+    /** Total prefetches that has been useful */
+    uint16_t usefulPrefetches;
+
+    FilterEntry *filterAndAddPrefetch(FilterEntry *filter_entry,
+            Addr ppn, stride_t last_block, stride_t delta,
+            double path_confidence, signature_t current_signature,
+            bool is_secure, std::vector<AddrPriority> &addresses) override;
+
+    double lookaheadConfidence(PatternEntry const &sig,
+            PatternStrideEntry const &lookahead) const override;
+
+    double prefetchConfidence(PatternEntry const &sig,
+            PatternStrideEntry const &lookahead) const override;
+
+    void increasePatternEntryCounter(PatternEntry &pattern_entry,
+            PatternStrideEntry &pstride_entry) override;
+
+    FilterEntry *updateFilter(Addr addr, bool is_secure) override;
+
+    void handleSignatureTableMiss(int8_t current_block,
+            signature_t &new_signature, double &new_conf,
+            stride_t &new_stride) const override;
+
+    FilterEntry *auxiliaryPrefetcher(FilterEntry *, Addr ppn,
+            int8_t current_block, bool is_secure,
+            std::vector<AddrPriority> &addresses) override;
+
+  public:
+    SignaturePathPrefetcherV2(const SignaturePathPrefetcherV2Params* p);
+    ~SignaturePathPrefetcherV2() {}
+};
+
+#endif//__MEM_CACHE_PREFETCH_SPPV2_HH__

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/14819
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I4b8b54efef48ced7044bd535de9a69bca68d47d9
Gerrit-Change-Number: 14819
Gerrit-PatchSet: 1
Gerrit-Owner: Javier Bueno Hedo <javier.bu...@metempsy.com>
Gerrit-Reviewer: Andreas Sandberg <andreas.sandb...@arm.com>
Gerrit-Reviewer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to