Javier Bueno Hedo has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/16223
Change subject: mem-cache: Added the Indirect Memory Prefetcher
......................................................................
mem-cache: Added the Indirect Memory Prefetcher
Reference:
Xiangyao Yu, Christopher J. Hughes, Nadathur Satish, and Srinivas
Devadas.
2015. IMP: indirect memory prefetcher. In Proceedings of the 48th
International Symposium on Microarchitecture (MICRO-48). ACM,
New York, NY, USA, 178-190. DOI: https://doi.org/10.1145/2830772.2830807
Change-Id: I52790f69c13ec55b8c1c8b9396ef9a1fb1be9797
---
M src/mem/cache/base.cc
M src/mem/cache/base.hh
M src/mem/cache/prefetch/Prefetcher.py
M src/mem/cache/prefetch/SConscript
M src/mem/cache/prefetch/associative_set.hh
M src/mem/cache/prefetch/associative_set_impl.hh
M src/mem/cache/prefetch/base.cc
M src/mem/cache/prefetch/base.hh
A src/mem/cache/prefetch/indirect_memory.cc
A src/mem/cache/prefetch/indirect_memory.hh
10 files changed, 533 insertions(+), 5 deletions(-)
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index 6049ca6..6f7bfea 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -1571,6 +1571,18 @@
}
}
+void
+BaseCache::getData(Addr addr, bool isSecure, unsigned int size, int8_t
*data)
+ const
+{
+ Addr blkAddr = addr & ~(Addr(blkSize - 1));
+ Addr offset = addr & Addr(blkSize -1);
+ CacheBlk *blk = tags->findBlock(blkAddr, isSecure);
+ assert(blk != nullptr);
+ assert(offset + size <= blkSize);
+ memcpy(data, &blk->data[offset], size);
+}
+
bool
BaseCache::sendWriteQueuePacket(WriteQueueEntry* wq_entry)
{
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh
index 6144fd5..874590c 100644
--- a/src/mem/cache/base.hh
+++ b/src/mem/cache/base.hh
@@ -1205,6 +1205,18 @@
bool sendWriteQueuePacket(WriteQueueEntry* wq_entry);
/**
+ * Retrieves the data allocated in the cache. The corresponding block
must
+ * exist in the cache.
+ * @param addr address of the data to read
+ * @param is_secure whether the addr
+ * @param whether this address targets the secure memory space
+ * @param size amount of data requested in bytes
+ * @param data pointer to copy the requested data
+ */
+ void getData(Addr addr, bool is_secure, unsigned int size, int8_t
*data)
+ const;
+
+ /**
* Serialize the state of the caches
*
* We currently don't support checkpointing cache state, so this
panics.
diff --git a/src/mem/cache/prefetch/Prefetcher.py
b/src/mem/cache/prefetch/Prefetcher.py
index 0825908..7322f11 100644
--- a/src/mem/cache/prefetch/Prefetcher.py
+++ b/src/mem/cache/prefetch/Prefetcher.py
@@ -141,6 +141,35 @@
degree = Param.Int(2, "Number of prefetches to generate")
+class IndirectMemoryPrefetcher(QueuedPrefetcher):
+ type = 'IndirectMemoryPrefetcher'
+ cxx_class = 'IndirectMemoryPrefetcher'
+ cxx_header = "mem/cache/prefetch/indirect_memory.hh"
+ pt_table_entries = Param.MemorySize("16",
+ "Number of entries of the Prefetch Table")
+ pt_table_assoc = Param.Unsigned(16, "Associativity of the Prefetch
Table")
+ pt_table_indexing_policy = Param.BaseIndexingPolicy(
+ SetAssociative(entry_size = 1, assoc = Parent.pt_table_assoc,
+ size = Parent.pt_table_entries),
+ "Indexing policy of the pattern table")
+ pt_table_replacement_policy = Param.BaseReplacementPolicy(LRURP(),
+ "Replacement policy of the pattern table")
+ max_prefetch_distance = Param.Unsigned(16, "Maximum prefetch distance")
+ ipd_table_entries = Param.MemorySize("4",
+ "Number of entries of the Indirect Pattern Detector")
+ ipd_table_assoc = Param.Unsigned(4,
+ "Associativity of the Indirect Pattern Detector")
+ ipd_table_indexing_policy = Param.BaseIndexingPolicy(
+ SetAssociative(entry_size = 1, assoc = Parent.ipd_table_assoc,
+ size = Parent.ipd_table_entries),
+ "Indexing policy of the Indirect Pattern Detector")
+ ipd_table_replacement_policy = Param.BaseReplacementPolicy(LRURP(),
+ "Replacement policy of the Indirect Pattern Detector")
+ shift_values = VectorParam.Int([2, 3, 4, -3], "Shift values to
consider")
+ addr_array_len = Param.Unsigned(4, "Number of misses tracked")
+ prefetch_threshold = Param.Unsigned(2,
+ "Counter threshold to start prefetching")
+
class SignaturePathPrefetcher(QueuedPrefetcher):
type = 'SignaturePathPrefetcher'
cxx_class = 'SignaturePathPrefetcher'
diff --git a/src/mem/cache/prefetch/SConscript
b/src/mem/cache/prefetch/SConscript
index f9582b5..3431e0d 100644
--- a/src/mem/cache/prefetch/SConscript
+++ b/src/mem/cache/prefetch/SConscript
@@ -34,6 +34,7 @@
Source('access_map_pattern_matching.cc')
Source('base.cc')
+Source('indirect_memory.cc')
Source('queued.cc')
Source('signature_path.cc')
Source('signature_path_v2.cc')
diff --git a/src/mem/cache/prefetch/associative_set.hh
b/src/mem/cache/prefetch/associative_set.hh
index 99b6a6d..ba7c5c2 100644
--- a/src/mem/cache/prefetch/associative_set.hh
+++ b/src/mem/cache/prefetch/associative_set.hh
@@ -195,6 +195,12 @@
* @param entry pointer to the container entry to be inserted
*/
void insertEntry(Addr addr, bool is_secure, Entry* entry);
+
+ /**
+ * Returns a referene to the vector containing all entries
+ * @result reference to the vector of entries
+ */
+ std::vector<Entry>& getAllEntries();
};
#endif//__CACHE_PREFETCH_ASSOCIATIVE_SET_HH__
diff --git a/src/mem/cache/prefetch/associative_set_impl.hh
b/src/mem/cache/prefetch/associative_set_impl.hh
index 5e6e7c5..57f21b0 100644
--- a/src/mem/cache/prefetch/associative_set_impl.hh
+++ b/src/mem/cache/prefetch/associative_set_impl.hh
@@ -116,4 +116,11 @@
replacementPolicy->reset(entry->replacementData);
}
+template<class Entry>
+std::vector<Entry>&
+AssociativeSet<Entry>::getAllEntries()
+{
+ return entries;
+}
+
#endif//__CACHE_PREFETCH_ASSOCIATIVE_SET_IMPL_HH__
diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc
index cd3eade..76057bc 100644
--- a/src/mem/cache/prefetch/base.cc
+++ b/src/mem/cache/prefetch/base.cc
@@ -59,13 +59,15 @@
BasePrefetcher::PrefetchInfo::PrefetchInfo(PacketPtr pkt, Addr addr)
: address(addr), pc(pkt->req->hasPC() ? pkt->req->getPC() : 0),
masterId(pkt->req->masterId()), validPC(pkt->req->hasPC()),
- secure(pkt->isSecure())
+ secure(pkt->isSecure()), size(pkt->req->getSize()),
write(pkt->isWrite()),
+ paddress(pkt->req->getPaddr())
{
}
BasePrefetcher::PrefetchInfo::PrefetchInfo(PrefetchInfo const &pfi, Addr
addr)
: address(addr), pc(pfi.pc), masterId(pfi.masterId),
validPC(pfi.validPC),
- secure(pfi.secure)
+ secure(pfi.secure), size(pfi.size), write(pfi.write),
+ paddress(pfi.paddress)
{
}
@@ -196,6 +198,7 @@
if (pkt->cmd.isSWPrefetch()) return;
if (pkt->req->isCacheMaintenance()) return;
if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return;
+ if (!pkt->req->hasPaddr()) return;
if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) {
usefulPrefetches += 1;
@@ -206,7 +209,7 @@
if (useVirtualAddresses && pkt->req->hasVaddr()) {
PrefetchInfo pfi(pkt, pkt->req->getVaddr());
notify(pkt, pfi);
- } else if (!useVirtualAddresses && pkt->req->hasPaddr()) {
+ } else if (!useVirtualAddresses) {
PrefetchInfo pfi(pkt, pkt->req->getPaddr());
notify(pkt, pfi);
}
diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh
index 06f7749..6fc2c81 100644
--- a/src/mem/cache/prefetch/base.hh
+++ b/src/mem/cache/prefetch/base.hh
@@ -83,7 +83,7 @@
* generate new prefetch requests.
*/
class PrefetchInfo {
- /** The address. */
+ /** The address used to train and generate prefetches */
Addr address;
/** The program counter that generated this address. */
Addr pc;
@@ -93,6 +93,12 @@
bool validPC;
/** Whether this address targets the secure memory space. */
bool secure;
+ /** Size in bytes of the request triggering this event */
+ unsigned int size;
+ /** Whether this event comes from a write request */
+ bool write;
+ /** Physical address, needed because address can be virtual */
+ Addr paddress;
public:
/**
@@ -142,6 +148,34 @@
}
/**
+ * Gets the size of the request triggering this event
+ * @return the size in bytes of the request triggering this event
+ */
+ unsigned int getSize() const
+ {
+ return size;
+ }
+
+ /**
+ * Checks if the request that caused this prefetch event was a
write
+ * request
+ * @return true if the request causing this event is a write
request
+ */
+ bool isWrite() const
+ {
+ return write;
+ }
+
+ /**
+ * Gets the physical address of the request
+ * @return physical address of the request
+ */
+ Addr getPaddr() const
+ {
+ return paddress;
+ }
+
+ /**
* Check for equality
* @param pfi PrefetchInfo to compare against
* @return True if this object and the provided one are equal
@@ -155,7 +189,8 @@
/**
* Constructs a PrefetchInfo using a PacketPtr.
* @param pkt PacketPtr used to generate the PrefetchInfo
- * @param addr the address value of the new object
+ * @param addr the address value of the new object, this address is
+ * used to train the prefetcher
*/
PrefetchInfo(PacketPtr pkt, Addr addr);
diff --git a/src/mem/cache/prefetch/indirect_memory.cc
b/src/mem/cache/prefetch/indirect_memory.cc
new file mode 100644
index 0000000..34c7f08
--- /dev/null
+++ b/src/mem/cache/prefetch/indirect_memory.cc
@@ -0,0 +1,248 @@
+/**
+ * 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/indirect_memory.hh"
+
+ #include "mem/cache/base.hh"
+ #include "mem/cache/prefetch/associative_set_impl.hh"
+ #include "params/IndirectMemoryPrefetcher.hh"
+
+IndirectMemoryPrefetcher::IndirectMemoryPrefetcher(
+ const IndirectMemoryPrefetcherParams *p) : QueuedPrefetcher(p),
+ maxPrefetchDistance(p->max_prefetch_distance),
+ shiftValues(p->shift_values),
+ prefetchThreshold(p->prefetch_threshold),
+ prefetchTable(p->pt_table_assoc, p->pt_table_entries,
+ p->pt_table_indexing_policy,
p->pt_table_replacement_policy),
+ ipd(p->ipd_table_assoc, p->ipd_table_entries,
p->ipd_table_indexing_policy,
+ p->ipd_table_replacement_policy,
+ IndirectPatternDetectorEntry(p->addr_array_len,
shiftValues.size())),
+ ipdEntryTrackingMisses(nullptr)
+{
+}
+
+void
+IndirectMemoryPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
+ std::vector<AddrPriority> &addresses)
+{
+ // This prefetcher requires a PC
+ if (!pfi.hasPC()) {
+ return;
+ }
+
+ bool is_secure = pfi.isSecure();
+ Addr pc = pfi.getPC();
+ Addr addr = pfi.getAddr();
+
+ // This prefetcher needs a cache to operate
+ assert(cache != nullptr);
+
+ bool miss = !inCache(pfi.getPaddr(), is_secure)
+ && !inMissQueue(pfi.getPaddr(), is_secure);
+ bool in_cache = inCache(pfi.getPaddr(), is_secure);
+
+ checkAccessMatchOnActiveEntries(addr);
+
+ // First check if this is a miss, if the prefetcher is tracking misses
+ if (ipdEntryTrackingMisses != nullptr && miss) {
+ // Check if the entry tracking misses has already set its second
index
+ if (!ipdEntryTrackingMisses->secondIndexSet) {
+ trackMissIndex1(ipdEntryTrackingMisses, addr);
+ } else {
+ trackMissIndex2(ipdEntryTrackingMisses, addr);
+ }
+ } else {
+ // if misses are not being tracked, attempt to detect stream
accesses
+ PrefetchTableEntry *pt_entry =
+ prefetchTable.findEntry(pc, false /* unused */);
+ if (pt_entry != nullptr) {
+ prefetchTable.accessEntry(pt_entry);
+
+ if (pt_entry->address != addr) {
+ // Streaming access found
+ pt_entry->streamCounter += 1;
+ pt_entry->address = addr;
+ pt_entry->secure = is_secure;
+
+ // if this is a read, read the data from the cache and
assume
+ // it is an index (this is only possible if the data is
already
+ // in the cache), also, onlly indexes up to 8 bytes are
+ // considered
+
+ if (in_cache && !pfi.isWrite() && pfi.getSize() <= 8) {
+ int64_t index = 0;
+ cache->getData(addr, is_secure, pfi.getSize(),
+ (int8_t *) &index);
+ if (!pt_entry->enabled) {
+ // Not enabled (not pattern detected in this
stream),
+ // add or update an entry in the pattern detector
and
+ // start tracking misses
+ allocateOrUpdateIPDEntry(pt_entry, index);
+ } else {
+ // Enabled entry, update the index
+ pt_entry->index = index;
+ if (!pt_entry->increasedIndirectCounter) {
+ if (pt_entry->indirectCounter < 0) {
+ pt_entry->indirectCounter -= 1;
+ }
+ } else {
+ // Set this to false, to see if the new index
+ // has any match
+ pt_entry->increasedIndirectCounter = false;
+ }
+
+ // If the counter is high enough, start prefetching
+ if (pt_entry->indirectCounter > prefetchThreshold)
{
+ unsigned distance = pt_entry->indirectCounter
/ 2;
+ for (int delta = 1; delta < distance; delta +=
1) {
+ Addr pf_addr = pt_entry->baseAddr +
+ (pt_entry->index << pt_entry->shift);
+ addresses.push_back(AddrPriority(pf_addr,
0));
+ }
+ }
+ }
+ }
+ }
+ } else {
+ pt_entry = prefetchTable.findVictim(pc);
+ assert(pt_entry != nullptr);
+ prefetchTable.insertEntry(pc, false /* unused */, pt_entry);
+ pt_entry->address = addr;
+ pt_entry->secure = is_secure;
+ }
+ }
+}
+
+void
+IndirectMemoryPrefetcher::allocateOrUpdateIPDEntry(
+ const PrefetchTableEntry *pt_entry, int64_t index)
+{
+ IndirectPatternDetectorEntry *ipd_entry = ipd.findEntry((Addr)
pt_entry,
+ false/* unused
*/);
+ if (ipd_entry != nullptr) {
+ ipd.accessEntry(ipd_entry);
+ if (!ipd_entry->secondIndexSet) {
+ // Second time we see an index, fill idx2
+ ipd_entry->idx2 = index;
+ ipd_entry->secondIndexSet = true;
+ ipdEntryTrackingMisses = ipd_entry;
+ } else {
+ // Third access! no pattern has been found so far,
+ // release the IPD entry
+ ipd_entry->reset();
+ ipd_entry->setInvalid();
+ ipdEntryTrackingMisses = nullptr;
+ }
+ } else {
+ ipd_entry = ipd.findVictim((Addr) pt_entry);
+ assert(ipd_entry != nullptr);
+ ipd.insertEntry((Addr) pt_entry, false /* unused */, ipd_entry);
+ ipd_entry->idx1 = index;
+ ipdEntryTrackingMisses = ipd_entry;
+ }
+}
+
+void
+IndirectMemoryPrefetcher::trackMissIndex1(IndirectPatternDetectorEntry
*entry,
+ Addr miss_addr)
+{
+ // If the second index is not set, we are just filling the baseAddr
+ // vector
+ if (entry->numMisses < entry->baseAddr.size()) {
+ std::vector<Addr> &ba_array = entry->baseAddr[entry->numMisses];
+ int idx = 0;
+ for (int shift : shiftValues) {
+ ba_array[idx] = miss_addr - (entry->idx1 << shift);
+ idx += 1;
+ }
+ entry->numMisses += 1;
+ if (entry->numMisses == entry->baseAddr.size()) {
+ // stop tracking misses once we have tracked enough
+ ipdEntryTrackingMisses = nullptr;
+ }
+ }
+}
+void
+IndirectMemoryPrefetcher::trackMissIndex2(IndirectPatternDetectorEntry
*entry,
+ Addr miss_addr)
+{
+ // Second index is filled, compare the addresses generated during
+ // the previous misses (using idx1) against newly generated values
+ // using idx2, if a match is found, fill the additional fields
+ // of the PT entry
+ bool match = false;
+ for (int midx = 0; midx < entry->numMisses && !match; midx += 1)
+ {
+ std::vector<Addr> &ba_array = entry->baseAddr[midx];
+ int idx = 0;
+ for (int shift : shiftValues) {
+ if (ba_array[idx] == (miss_addr - (entry->idx2 << shift))) {
+ // Match found!
+ match = true;
+ // Fill the corresponding pt_entry
+ PrefetchTableEntry *pt_entry =
+ (PrefetchTableEntry *) entry->getTag();
+ pt_entry->baseAddr = ba_array[idx];
+ pt_entry->shift = shift;
+ pt_entry->enabled = true;
+ pt_entry->indirectCounter = 0;
+ // Release the current IPD Entry
+ entry->reset();
+ entry->setInvalid();
+ // Do not track more misses
+ ipdEntryTrackingMisses = nullptr;
+ break;
+ }
+ idx += 1;
+ }
+ }
+}
+
+void
+IndirectMemoryPrefetcher::checkAccessMatchOnActiveEntries(Addr addr)
+{
+ for (auto &pt_entry : prefetchTable.getAllEntries()) {
+ if (pt_entry.enabled) {
+ if (addr == pt_entry.baseAddr +
+ (pt_entry.index << pt_entry.shift)) {
+ if (pt_entry.indirectCounter < (maxPrefetchDistance * 2)) {
+ pt_entry.indirectCounter += 1;
+ pt_entry.increasedIndirectCounter = true;
+ }
+ }
+ }
+ }
+}
+
+IndirectMemoryPrefetcher*
+IndirectMemoryPrefetcherParams::create()
+{
+ return new IndirectMemoryPrefetcher(this);
+}
diff --git a/src/mem/cache/prefetch/indirect_memory.hh
b/src/mem/cache/prefetch/indirect_memory.hh
new file mode 100644
index 0000000..c513b29
--- /dev/null
+++ b/src/mem/cache/prefetch/indirect_memory.hh
@@ -0,0 +1,175 @@
+/**
+ * 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 Indirect Memory Prefetcher
+ *
+ * References:
+ * IMP: Indirect memory prefetcher.
+ * Yu, X., Hughes, C. J., Satish, N., & Devadas, S. (2015, December).
+ * In Proceedings of the 48th International Symposium on Microarchitecture
+ * (pp. 178-190). ACM.
+ */
+
+#ifndef __MEM_CACHE_PREFETCH_INDIRECT_MEMORY_HH__
+#define __MEM_CACHE_PREFETCH_INDIRECT_MEMORY_HH__
+
+#include "mem/cache/prefetch/associative_set.hh"
+#include "mem/cache/prefetch/queued.hh"
+
+struct IndirectMemoryPrefetcherParams;
+
+class IndirectMemoryPrefetcher : public QueuedPrefetcher
+{
+ /** Maximum number of prefetches generated per event */
+ const unsigned int maxPrefetchDistance;
+ /** Shift valies considered */
+ const std::vector<int> shiftValues;
+ /** Counter threshold to start prefetching */
+ const unsigned int prefetchThreshold;
+
+ /** Prefetch Table Entry */
+ struct PrefetchTableEntry : public TaggedEntry
+ {
+ /* Stream table fields */
+
+ /** Accessed address */
+ Addr address;
+ /** Whether this address is in the secure region */
+ bool secure;
+ /** Confidence counter of the stream */
+ int streamCounter;
+
+ /* Indirect table fields */
+
+ /** Enable bit of the indirect fields */
+ bool enabled;
+ /** Current index value */
+ int64_t index;
+ /** BaseAddr detected */
+ Addr baseAddr;
+ /** Shift detected */
+ int shift;
+ /** Confidence counter of the indirect fields */
+ int indirectCounter;
+ /** Whether the counter has been increased between two index
updates */
+ bool increasedIndirectCounter;
+
+ PrefetchTableEntry() : TaggedEntry(), address(0), secure(false),
+ streamCounter(0), enabled(false), index(0), baseAddr(0),
shift(0),
+ indirectCounter(0), increasedIndirectCounter(false)
+ {}
+
+ void reset() override {
+ address = 0;
+ secure = false;
+ streamCounter = 0;
+ enabled = false;
+ index = 0;
+ baseAddr = 0;
+ shift = 0;
+ indirectCounter = 0;
+ increasedIndirectCounter = false;
+ }
+ };
+ /** Prefetch table */
+ AssociativeSet<PrefetchTableEntry> prefetchTable;
+
+ /** Indirect Pattern Detector entrt */
+ struct IndirectPatternDetectorEntry : public TaggedEntry
+ {
+ /** First index */
+ int64_t idx1;
+ /** Second index */
+ int64_t idx2;
+ /** Valid bit for the second index */
+ bool secondIndexSet;
+ /** Number of misses currently recorded */
+ int numMisses;
+ /** Potential BaseAddr candidates */
+ std::vector<std::vector<Addr>> baseAddr;
+
+ IndirectPatternDetectorEntry(unsigned int num_addresses,
+ unsigned int num_shifts)
+ : idx1(0), idx2(0), secondIndexSet(false), numMisses(0),
+ baseAddr(num_addresses, std::vector<Addr>(num_shifts))
+ {}
+
+ void reset() override {
+ idx1 = 0;
+ idx2 = 0;
+ secondIndexSet = false;
+ numMisses = 0;
+ }
+ };
+ /** Indirect Pattern Detector (IPD) table */
+ AssociativeSet<IndirectPatternDetectorEntry> ipd;
+
+ /** Entry currently tracking misses */
+ IndirectPatternDetectorEntry *ipdEntryTrackingMisses;
+
+ /**
+ * Allocate or update an entry in the IPD
+ * @param pt_entry Pointer to the associated page table entry
+ * @param index Detected first index value
+ */
+ void allocateOrUpdateIPDEntry(const PrefetchTableEntry *pt_entry,
+ int64_t index);
+ /**
+ * Update an IPD entry with a detected miss address, when the first
index
+ * is being tracked
+ * @param entry Pointer to the corresponding IPD entry
+ * @param miss_addr The address that caused the miss
+ */
+ void trackMissIndex1(IndirectPatternDetectorEntry *entry, Addr
miss_addr);
+
+ /**
+ * Update an IPD entry with a detected miss address, when the second
index
+ * is being tracked
+ * @param entry Pointer to the corresponding IPD entry
+ * @param miss_addr The address that caused the miss
+ */
+ void trackMissIndex2(IndirectPatternDetectorEntry *entry, Addr
miss_addr);
+
+ /**
+ * Checks if an access to the cache matches any active PT entry, if so,
+ * the indirect confidence counter is incremented
+ * @param addr address of the access
+ */
+ void checkAccessMatchOnActiveEntries(Addr addr);
+
+ public:
+ IndirectMemoryPrefetcher(const IndirectMemoryPrefetcherParams *p);
+ ~IndirectMemoryPrefetcher() {}
+
+ void calculatePrefetch(const PrefetchInfo &pfi,
+ std::vector<AddrPriority> &addresses) override;
+};
+#endif//__MEM_CACHE_PREFETCH_INDIRECT_MEMORY_HH__
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16223
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: I52790f69c13ec55b8c1c8b9396ef9a1fb1be9797
Gerrit-Change-Number: 16223
Gerrit-PatchSet: 1
Gerrit-Owner: Javier Bueno Hedo <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev