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:
committed by
Javier Bueno Hedo
parent
6684d617da
commit
2775f55447
9
src/mem/cache/base.hh
vendored
9
src/mem/cache/base.hh
vendored
@@ -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);
|
||||
}
|
||||
|
||||
23
src/mem/cache/prefetch/Prefetcher.py
vendored
23
src/mem/cache/prefetch/Prefetcher.py
vendored
@@ -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'
|
||||
|
||||
1
src/mem/cache/prefetch/SConscript
vendored
1
src/mem/cache/prefetch/SConscript
vendored
@@ -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')
|
||||
|
||||
13
src/mem/cache/prefetch/base.cc
vendored
13
src/mem/cache/prefetch/base.cc
vendored
@@ -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()) {
|
||||
|
||||
7
src/mem/cache/prefetch/base.hh
vendored
7
src/mem/cache/prefetch/base.hh
vendored
@@ -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);
|
||||
|
||||
1
src/mem/cache/prefetch/queued.cc
vendored
1
src/mem/cache/prefetch/queued.cc
vendored
@@ -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;
|
||||
|
||||
153
src/mem/cache/prefetch/signature_path.cc
vendored
153
src/mem/cache/prefetch/signature_path.cc
vendored
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
109
src/mem/cache/prefetch/signature_path.hh
vendored
109
src/mem/cache/prefetch/signature_path.hh
vendored
@@ -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() {}
|
||||
|
||||
136
src/mem/cache/prefetch/signature_path_v2.cc
vendored
Normal file
136
src/mem/cache/prefetch/signature_path_v2.cc
vendored
Normal 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);
|
||||
}
|
||||
97
src/mem/cache/prefetch/signature_path_v2.hh
vendored
Normal file
97
src/mem/cache/prefetch/signature_path_v2.hh
vendored
Normal 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__
|
||||
Reference in New Issue
Block a user