diff options
author | Javier Bueno <javier.bueno@metempsy.com> | 2018-12-13 11:38:15 +0100 |
---|---|---|
committer | Javier Bueno Hedo <javier.bueno@metempsy.com> | 2019-02-01 20:54:28 +0000 |
commit | 2775f55447edb344d99f30273ad93fea515d7e2b (patch) | |
tree | b1a274a936f8f3a970a1014bda73b2a92c873e0f | |
parent | 6684d617da52d1956f955a9452ff90058d66cf9e (diff) | |
download | gem5-2775f55447edb344d99f30273ad93fea515d7e2b.tar.xz |
mem-cache: Updated version of the Signature Path Prefetcher
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
Reviewed-on: https://gem5-review.googlesource.com/c/14819
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
-rw-r--r-- | src/mem/cache/base.hh | 9 | ||||
-rw-r--r-- | src/mem/cache/prefetch/Prefetcher.py | 23 | ||||
-rw-r--r-- | src/mem/cache/prefetch/SConscript | 1 | ||||
-rw-r--r-- | src/mem/cache/prefetch/base.cc | 13 | ||||
-rw-r--r-- | src/mem/cache/prefetch/base.hh | 7 | ||||
-rw-r--r-- | src/mem/cache/prefetch/queued.cc | 1 | ||||
-rw-r--r-- | src/mem/cache/prefetch/signature_path.cc | 153 | ||||
-rw-r--r-- | src/mem/cache/prefetch/signature_path.hh | 109 | ||||
-rw-r--r-- | src/mem/cache/prefetch/signature_path_v2.cc | 136 | ||||
-rw-r--r-- | src/mem/cache/prefetch/signature_path_v2.hh | 97 |
10 files changed, 488 insertions, 61 deletions
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 70b3d3e45..6144fd584 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -1132,6 +1132,15 @@ class BaseCache : public MemObject return tags->findBlock(addr, is_secure); } + bool hasBeenPrefetched(Addr addr, bool is_secure) const { + CacheBlk *block = tags->findBlock(addr, is_secure); + if (block) { + return block->wasPrefetched(); + } else { + return false; + } + } + bool inMissQueue(Addr addr, bool is_secure) const { return mshrQueue.findMatch(addr, is_secure); } diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index 3d9c66565..082590853 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -180,6 +180,29 @@ class SignaturePathPrefetcher(QueuedPrefetcher): 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/signature_path_v2.hh" + + signature_table_entries = "256" + signature_table_assoc = 1 + pattern_table_entries = "512" + pattern_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_indexing_policy = Param.BaseIndexingPolicy( + SetAssociative(entry_size = 1, + assoc = Parent.global_history_register_entries, + 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") + class AccessMapPatternMatchingPrefetcher(QueuedPrefetcher): type = 'AccessMapPatternMatchingPrefetcher' cxx_class = 'AccessMapPatternMatchingPrefetcher' diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript index b46158624..f9582b580 100644 --- a/src/mem/cache/prefetch/SConscript +++ b/src/mem/cache/prefetch/SConscript @@ -36,5 +36,6 @@ Source('access_map_pattern_matching.cc') Source('base.cc') Source('queued.cc') Source('signature_path.cc') +Source('signature_path_v2.cc') Source('stride.cc') Source('tagged.cc') diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index e58d4f3d5..cd3eade09 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -81,7 +81,8 @@ BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p) onWrite(p->on_write), onData(p->on_data), onInst(p->on_inst), masterId(p->sys->getMasterId(this)), pageBytes(p->sys->getPageBytes()), prefetchOnAccess(p->prefetch_on_access), - useVirtualAddresses(p->use_virtual_addresses) + useVirtualAddresses(p->use_virtual_addresses), issuedPrefetches(0), + usefulPrefetches(0) { } @@ -146,6 +147,12 @@ BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const } bool +BasePrefetcher::hasBeenPrefetched(Addr addr, bool is_secure) const +{ + return cache->hasBeenPrefetched(addr, is_secure); +} + +bool BasePrefetcher::samePage(Addr a, Addr b) const { return roundDown(a, pageBytes) == roundDown(b, pageBytes); @@ -190,6 +197,10 @@ BasePrefetcher::probeNotify(const PacketPtr &pkt) if (pkt->req->isCacheMaintenance()) return; if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return; + if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) { + usefulPrefetches += 1; + } + // Verify this access type is observed by prefetcher if (observeAccess(pkt)) { if (useVirtualAddresses && pkt->req->hasVaddr()) { diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index 63b0e1bed..06f77492d 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -214,6 +214,8 @@ class BasePrefetcher : public ClockedObject /** Determine if address is in cache miss queue */ bool inMissQueue(Addr addr, bool is_secure) const; + bool hasBeenPrefetched(Addr addr, bool is_secure) const; + /** Determine if addresses are on the same page */ bool samePage(Addr a, Addr b) const; /** Determine the address of the block in which a lays */ @@ -229,6 +231,11 @@ class BasePrefetcher : public ClockedObject Stats::Scalar pfIssued; + /** Total prefetches issued */ + uint64_t issuedPrefetches; + /** Total prefetches that has been useful */ + uint64_t usefulPrefetches; + public: BasePrefetcher(const BasePrefetcherParams *p); diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index bce6fbb97..d7b8aacd0 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -124,6 +124,7 @@ QueuedPrefetcher::getPacket() pfq.pop_front(); pfIssued++; + issuedPrefetches += 1; assert(pkt != nullptr); DPRINTF(HWPrefetch, "Generating prefetch for %#x.\n", pkt->getAddr()); return pkt; diff --git a/src/mem/cache/prefetch/signature_path.cc b/src/mem/cache/prefetch/signature_path.cc index a0356b1d1..857354e65 100644 --- a/src/mem/cache/prefetch/signature_path.cc +++ b/src/mem/cache/prefetch/signature_path.cc @@ -53,6 +53,14 @@ SignaturePathPrefetcher::SignaturePathPrefetcher( p->pattern_table_replacement_policy, PatternEntry(stridesPerPatternEntry)) { + fatal_if(prefetchConfidenceThreshold < 0, + "The prefetch confidence threshold must be greater than 0\n"); + fatal_if(prefetchConfidenceThreshold > 1, + "The prefetch confidence threshold must be less than 1\n"); + fatal_if(lookaheadConfidenceThreshold < 0, + "The lookahead confidence threshold must be greater than 0\n"); + fatal_if(lookaheadConfidenceThreshold > 1, + "The lookahead confidence threshold must be less than 1\n"); } SignaturePathPrefetcher::PatternStrideEntry & @@ -86,28 +94,34 @@ SignaturePathPrefetcher::PatternEntry::getStrideEntry(stride_t stride, } void -SignaturePathPrefetcher::addPrefetch(Addr ppn, stride_t block, +SignaturePathPrefetcher::addPrefetch(Addr ppn, stride_t last_block, + stride_t delta, double path_confidence, signature_t signature, bool is_secure, std::vector<AddrPriority> &addresses) { - /** - * 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))); - assert(block < 2*((stride_t)(pageBytes/blkSize))); + stride_t block = last_block + delta; Addr pf_ppn; stride_t pf_block; if (block < 0) { - pf_ppn = ppn - 1; - pf_block = block + (pageBytes/blkSize); + stride_t num_cross_pages = 1 + (-block) / (pageBytes/blkSize); + if (num_cross_pages > ppn) { + // target address smaller than page 0, ignore this request; + return; + } + pf_ppn = ppn - num_cross_pages; + pf_block = block + (pageBytes/blkSize) * num_cross_pages; + handlePageCrossingLookahead(signature, last_block, delta, + path_confidence); } else if (block >= (pageBytes/blkSize)) { - pf_ppn = ppn + 1; - pf_block = block - (pageBytes/blkSize); + stride_t num_cross_pages = block / (pageBytes/blkSize); + if (MaxAddr/pageBytes < (ppn + num_cross_pages)) { + // target address goes beyond MaxAddr, ignore this request; + return; + } + pf_ppn = ppn + num_cross_pages; + pf_block = block - (pageBytes/blkSize) * num_cross_pages; + handlePageCrossingLookahead(signature, last_block, delta, + path_confidence); } else { pf_ppn = ppn; pf_block = block; @@ -121,6 +135,24 @@ SignaturePathPrefetcher::addPrefetch(Addr ppn, stride_t block, } void +SignaturePathPrefetcher::handleSignatureTableMiss(stride_t current_block, + signature_t &new_signature, double &new_conf, stride_t &new_stride) +{ + new_signature = current_block; + new_conf = 1.0; + new_stride = current_block; +} + +void +SignaturePathPrefetcher::increasePatternEntryCounter( + PatternEntry &pattern_entry, PatternStrideEntry &pstride_entry) +{ + if (pstride_entry.counter < maxCounterValue) { + pstride_entry.counter += 1; + } +} + +void SignaturePathPrefetcher::updatePatternTable(Addr signature, stride_t stride) { assert(stride != 0); @@ -128,28 +160,31 @@ SignaturePathPrefetcher::updatePatternTable(Addr signature, stride_t stride) PatternEntry &p_entry = getPatternEntry(signature); PatternStrideEntry &ps_entry = p_entry.getStrideEntry(stride, maxCounterValue); - if (ps_entry.counter < maxCounterValue) { - ps_entry.counter += 1; - } + increasePatternEntryCounter(p_entry, ps_entry); } SignaturePathPrefetcher::SignatureEntry & SignaturePathPrefetcher::getSignatureEntry(Addr ppn, bool is_secure, - stride_t block, bool &miss) + stride_t block, bool &miss, stride_t &stride, + double &initial_confidence) { SignatureEntry* signature_entry = signatureTable.findEntry(ppn, is_secure); if (signature_entry != nullptr) { signatureTable.accessEntry(signature_entry); miss = false; + stride = block - signature_entry->lastBlock; } else { signature_entry = signatureTable.findVictim(ppn); assert(signature_entry != nullptr); + // Sets signature_entry->signature, initial_confidence, and stride + handleSignatureTableMiss(block, signature_entry->signature, + initial_confidence, stride); + signatureTable.insertEntry(ppn, is_secure, signature_entry); - signature_entry->signature = block; - signature_entry->lastBlock = block; miss = true; } + signature_entry->lastBlock = block; return *signature_entry; } @@ -170,6 +205,31 @@ SignaturePathPrefetcher::getPatternEntry(Addr signature) return *pattern_entry; } +double +SignaturePathPrefetcher::calculatePrefetchConfidence(PatternEntry const &sig, + PatternStrideEntry const &entry) const +{ + return ((double) entry.counter) / maxCounterValue; +} + +double +SignaturePathPrefetcher::calculateLookaheadConfidence(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; +} + void SignaturePathPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, std::vector<AddrPriority> &addresses) @@ -179,19 +239,20 @@ SignaturePathPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, stride_t current_block = (request_addr % pageBytes) / blkSize; stride_t stride; bool is_secure = pfi.isSecure(); + double initial_confidence = 1.0; // Get the SignatureEntry of this page to: // - compute the current stride // - obtain the current signature of accesses bool miss; SignatureEntry &signature_entry = getSignatureEntry(ppn, is_secure, - current_block, miss); + current_block, miss, stride, initial_confidence); + if (miss) { // No history for this page, can't continue return; } - stride = current_block - signature_entry.lastBlock; if (stride == 0) { // Can't continue with a stride 0 return; @@ -200,16 +261,17 @@ SignaturePathPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, // Update the confidence of the current signature updatePatternTable(signature_entry.signature, stride); - // Update the current SignatureEntry signature and lastBlock + // Update the current SignatureEntry signature signature_entry.signature = updateSignature(signature_entry.signature, stride); - signature_entry.lastBlock = current_block; signature_t current_signature = signature_entry.signature; - double current_confidence = 1.0; + double current_confidence = initial_confidence; stride_t current_stride = signature_entry.lastBlock; - do { + // Look for prefetch candidates while the current path confidence is + // high enough + while (current_confidence > lookaheadConfidenceThreshold) { // With the updated signature, attempt to generate prefetches // - search the PatternTable and select all entries with enough // confidence, these are prefetch candidates @@ -226,45 +288,40 @@ SignaturePathPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, lookahead = &entry; } double prefetch_confidence = - (double) entry.counter / maxCounterValue; + calculatePrefetchConfidence(*current_pattern_entry, entry); if (prefetch_confidence >= prefetchConfidenceThreshold) { assert(entry.stride != 0); //prefetch candidate - addPrefetch(ppn, current_stride + entry.stride, - is_secure, addresses); + addPrefetch(ppn, current_stride, entry.stride, + current_confidence, current_signature, + is_secure, addresses); } } } + if (lookahead != nullptr) { - // If a lookahead was selected, compute its confidence using - // the counter of its entry and the accumulated confidence - // if the confidence is high enough, generate a new signature - 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 *= calculateLookaheadConfidence( + *current_pattern_entry, *lookahead); current_signature = updateSignature(current_signature, lookahead->stride); current_stride += lookahead->stride; } else { current_confidence = 0.0; } - // If the accumulated confidence is high enough, keep repeating - // this process with the updated signature } - while (current_confidence > lookaheadConfidenceThreshold); + auxiliaryPrefetcher(ppn, current_block, is_secure, addresses); +} + +void +SignaturePathPrefetcher::auxiliaryPrefetcher(Addr ppn, stride_t current_block, + bool is_secure, std::vector<AddrPriority> &addresses) +{ if (addresses.empty()) { // Enable the next line prefetcher if no prefetch candidates are found - addPrefetch(ppn, current_block + 1, is_secure, addresses); + addPrefetch(ppn, current_block, 1, 0.0 /* unused*/, 0 /* unused */, + is_secure, addresses); } } diff --git a/src/mem/cache/prefetch/signature_path.hh b/src/mem/cache/prefetch/signature_path.hh index 0371b56e3..974c02746 100644 --- a/src/mem/cache/prefetch/signature_path.hh +++ b/src/mem/cache/prefetch/signature_path.hh @@ -50,6 +50,7 @@ struct SignaturePathPrefetcherParams; class SignaturePathPrefetcher : public QueuedPrefetcher { + protected: /** Signature type */ typedef uint16_t signature_t; /** Stride type */ @@ -96,7 +97,10 @@ class SignaturePathPrefetcher : public QueuedPrefetcher { /** group of stides */ std::vector<PatternStrideEntry> strideEntries; - PatternEntry(size_t num_strides) : strideEntries(num_strides) + /** use counter, used by SPPv2 */ + uint8_t counter; + PatternEntry(size_t num_strides) : strideEntries(num_strides), + counter(0) {} /** Reset the entries to their initial values */ @@ -106,6 +110,7 @@ class SignaturePathPrefetcher : public QueuedPrefetcher entry.counter = 0; entry.stride = 0; } + counter = 0; } /** @@ -157,34 +162,44 @@ class SignaturePathPrefetcher : public QueuedPrefetcher /** * Generates an address to be prefetched. * @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 accessed block within the page ppn + * @param delta difference, in number of 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 + * @param signature the current path signature * @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 addresses to prefetch will be added to this vector */ - void addPrefetch(Addr ppn, stride_t block, bool is_secure, - std::vector<AddrPriority> &addresses); + void addPrefetch(Addr ppn, stride_t last_block, stride_t delta, + double path_confidence, signature_t signature, + bool is_secure, + std::vector<AddrPriority> &addresses); /** * Obtains the SignatureEntry of the given page, if the page is not found, * it allocates a new one, replacing an existing entry if needed + * It also provides the stride of the current block and the initial + * path confidence of the corresponding entry * @param ppn physical page number of the page * @param is_secure whether this page is inside the secure memory area * @param block accessed block within the page - * @param miss output, if the entry is not found, this will be set to true + * @param miss if the entry is not found, this will be set to true + * @param stride set to the computed stride + * @param initial_confidence set to the initial confidence value * @result a reference to the SignatureEntry */ - SignatureEntry & getSignatureEntry(Addr ppn, bool is_secure, - stride_t block, bool &miss); + SignatureEntry &getSignatureEntry(Addr ppn, bool is_secure, stride_t block, + bool &miss, stride_t &stride, double &initial_confidence); /** * Obtains the PatternEntry of the given signature, if the signature is * not found, it allocates a new one, replacing an existing entry if needed * @param signature the signature of the desired entry * @result a reference to the PatternEntry */ - PatternEntry & getPatternEntry(Addr signature); + PatternEntry& getPatternEntry(Addr signature); /** * Updates the pattern table with the provided signature and stride @@ -194,6 +209,76 @@ class SignaturePathPrefetcher : public QueuedPrefetcher */ void updatePatternTable(Addr signature, stride_t stride); + /** + * 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 + */ + virtual double calculateLookaheadConfidence(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 calculatePrefetchConfidence(PatternEntry const &sig, + PatternStrideEntry const &entry) 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); + + /** + * Whenever a new SignatureEntry is allocated, it computes the new + * signature to be used with the new entry, the resulting stride and the + * initial path confidence of the new entry. + * @param current_block accessed block within the page of the associated + entry + * @param new_signature new signature of the allocated entry + * @param new_conf the initial path confidence of this entry + * @param new_stride the resulting current stride + */ + virtual void handleSignatureTableMiss(stride_t current_block, + signature_t &new_signature, double &new_conf, + stride_t &new_stride); + + /** + * 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 ppn physical page number of the current accessed page + * @param current_block last accessed block within the page ppn + * @param is_secure whether this page is inside the secure memory area + * @param addresses the addresses to be prefetched are added to this vector + * @param updated_filter_entries set of addresses containing these that + * their filter has been updated, if this call updates a new entry + */ + virtual void auxiliaryPrefetcher(Addr ppn, stride_t current_block, + bool is_secure, std::vector<AddrPriority> &addresses); + + /** + * Handles the situation when the lookahead process has crossed the + * boundaries of the current page. This is not fully described in the + * paper that was used to implement this code, however, the article + * describing the upgraded version of this prefetcher provides some + * details. For this prefetcher, there are no specific actions to be + * done. + * @param signature the lookahead signature that crossed the page + * @param delta the current stride that caused it + * @param last_offset the last accessed block within the page + * @param path_confidence the path confidence at the moment of crossing + */ + virtual void handlePageCrossingLookahead(signature_t signature, + stride_t last_offset, stride_t delta, double path_confidence) { + } + public: SignaturePathPrefetcher(const SignaturePathPrefetcherParams* p); ~SignaturePathPrefetcher() {} diff --git a/src/mem/cache/prefetch/signature_path_v2.cc b/src/mem/cache/prefetch/signature_path_v2.cc new file mode 100644 index 000000000..571c3d12b --- /dev/null +++ b/src/mem/cache/prefetch/signature_path_v2.cc @@ -0,0 +1,136 @@ +/** + * 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/signature_path_v2.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, + p->global_history_register_entries, + p->global_history_register_indexing_policy, + p->global_history_register_replacement_policy, + GlobalHistoryEntry()) +{ +} + +void +SignaturePathPrefetcherV2::handleSignatureTableMiss(stride_t current_block, + signature_t &new_signature, double &new_conf, stride_t &new_stride) +{ + bool found = false; + + // This should return all entries of the GHR, since it is a fully + // associative table + std::vector<GlobalHistoryEntry *> all_ghr_entries = + globalHistoryRegister.getPossibleEntries(0 /* any value works */); + + for (auto gh_entry : all_ghr_entries) { + 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; + globalHistoryRegister.accessEntry(gh_entry); + break; + } + } + if (!found) { + new_signature = current_block; + new_conf = 1.0; + new_stride = current_block; + } +} + +double +SignaturePathPrefetcherV2::calculateLookaheadConfidence( + PatternEntry const &sig, PatternStrideEntry const &lookahead) const +{ + if (sig.counter == 0) return 0.0; + return (((double) usefulPrefetches) / issuedPrefetches) * + (((double) lookahead.counter) / sig.counter); +} + +double +SignaturePathPrefetcherV2::calculatePrefetchConfidence(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; +} + +void +SignaturePathPrefetcherV2::handlePageCrossingLookahead(signature_t signature, + stride_t last_offset, stride_t delta, double path_confidence) +{ + // Always use the replacement policy to assign new entries, as all + // of them are unique, there are never "hits" in the GHR + GlobalHistoryEntry *gh_entry = globalHistoryRegister.findVictim(0); + assert(gh_entry != nullptr); + // Any address value works, as it is never used + globalHistoryRegister.insertEntry(0, false, gh_entry); + + gh_entry->signature = signature; + gh_entry->lastBlock = last_offset; + gh_entry->delta = delta; + gh_entry->confidence = path_confidence; +} + +SignaturePathPrefetcherV2* +SignaturePathPrefetcherV2Params::create() +{ + return new SignaturePathPrefetcherV2(this); +} diff --git a/src/mem/cache/prefetch/signature_path_v2.hh b/src/mem/cache/prefetch/signature_path_v2.hh new file mode 100644 index 000000000..2eed18de9 --- /dev/null +++ b/src/mem/cache/prefetch/signature_path_v2.hh @@ -0,0 +1,97 @@ +/** + * 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_SIGNATURE_PATH_V2_HH__ +#define __MEM_CACHE_PREFETCH_SIGNATURE_PATH_V2_HH__ + +#include "mem/cache/prefetch/associative_set.hh" +#include "mem/cache/prefetch/signature_path.hh" +#include "mem/packet.hh" + +struct SignaturePathPrefetcherV2Params; + +class SignaturePathPrefetcherV2 : public SignaturePathPrefetcher +{ + /** Global History Register entry datatype */ + struct GlobalHistoryEntry : public TaggedEntry + { + signature_t signature; + double confidence; + stride_t lastBlock; + stride_t delta; + GlobalHistoryEntry() : signature(0), confidence(0.0), lastBlock(0), + delta(0) {} + }; + /** Global History Register */ + AssociativeSet<GlobalHistoryEntry> globalHistoryRegister; + + double calculateLookaheadConfidence(PatternEntry const &sig, + PatternStrideEntry const &lookahead) const override; + + double calculatePrefetchConfidence(PatternEntry const &sig, + PatternStrideEntry const &lookahead) const override; + + void increasePatternEntryCounter(PatternEntry &pattern_entry, + PatternStrideEntry &pstride_entry) override; + + void handleSignatureTableMiss(stride_t current_block, + signature_t &new_signature, double &new_conf, + stride_t &new_stride) override; + + /** + * In this version of the Signature Path Prefetcher, there is no auxiliary + * prefetcher, so this function does not perform any actions. + */ + void auxiliaryPrefetcher(Addr ppn, stride_t current_block, bool is_secure, + std::vector<AddrPriority> &addresses) override + {} + + virtual void handlePageCrossingLookahead(signature_t signature, + stride_t last_offset, stride_t delta, double path_confidence) + override; + + public: + SignaturePathPrefetcherV2(const SignaturePathPrefetcherV2Params* p); + ~SignaturePathPrefetcherV2() {} +}; + +#endif//__MEM_CACHE_PREFETCH_SIGNATURE_PATH_V2_HH__ |