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>
This commit is contained in:
Javier Bueno
2018-12-13 11:38:15 +01:00
committed by Javier Bueno Hedo
parent 6684d617da
commit 2775f55447
10 changed files with 488 additions and 61 deletions

View File

@@ -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);
}

View File

@@ -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'

View File

@@ -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')

View File

@@ -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)
{
}
@@ -145,6 +146,12 @@ BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const
return cache->inMissQueue(addr, is_secure);
}
bool
BasePrefetcher::hasBeenPrefetched(Addr addr, bool is_secure) const
{
return cache->hasBeenPrefetched(addr, is_secure);
}
bool
BasePrefetcher::samePage(Addr a, Addr b) const
{
@@ -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()) {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
@@ -120,6 +134,24 @@ SignaturePathPrefetcher::addPrefetch(Addr ppn, stride_t block,
addresses.push_back(AddrPriority(new_addr, 0));
}
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)
{
@@ -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);
}
}

View File

@@ -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() {}

View File

@@ -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);
}

View File

@@ -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__