mem-cache: Irregular Stream Buffer Prefetcher

Based in the description of the following publication:
Akanksha Jain and Calvin Lin. 2013. Linearizing irregular memory accesses
for improved correlated prefetching. In Proceedings of the 46th Annual
IEEE/ACM International Symposium on Microarchitecture (MICRO-46). ACM,
New York, NY, USA, 247-259.

Change-Id: Ibeb6abc93ca40ad634df6ed5cf8becb0a49d1165
Reviewed-on: https://gem5-review.googlesource.com/c/15215
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
This commit is contained in:
Javier Bueno
2018-12-05 17:27:48 +01:00
committed by Javier Bueno Hedo
parent 9d4d620ef1
commit 626e8faf42
4 changed files with 385 additions and 0 deletions

View File

@@ -266,3 +266,46 @@ class DCPTPrefetcher(QueuedPrefetcher):
DeltaCorrelatingPredictionTables(),
"Delta Correlating Prediction Tables object")
class IrregularStreamBufferPrefetcher(QueuedPrefetcher):
type = "IrregularStreamBufferPrefetcher"
cxx_class = "IrregularStreamBufferPrefetcher"
cxx_header = "mem/cache/prefetch/irregular_stream_buffer.hh"
max_counter_value = Param.Unsigned(3,
"Maximum value of the confidence counter")
chunk_size = Param.Unsigned(256,
"Maximum number of addresses in a temporal stream")
degree = Param.Unsigned(4, "Number of prefetches to generate")
training_unit_assoc = Param.Unsigned(128,
"Associativity of the training unit")
training_unit_entries = Param.MemorySize("128",
"Number of entries of the training unit")
training_unit_indexing_policy = Param.BaseIndexingPolicy(
SetAssociative(entry_size = 1, assoc = Parent.training_unit_assoc,
size = Parent.training_unit_entries),
"Indexing policy of the training unit")
training_unit_replacement_policy = Param.BaseReplacementPolicy(LRURP(),
"Replacement policy of the training unit")
prefetch_candidates_per_entry = Param.Unsigned(16,
"Number of prefetch candidates stored in a SP-AMC entry")
address_map_cache_assoc = Param.Unsigned(128,
"Associativity of the PS/SP AMCs")
address_map_cache_entries = Param.MemorySize("128",
"Number of entries of the PS/SP AMCs")
ps_address_map_cache_indexing_policy = Param.BaseIndexingPolicy(
SetAssociative(entry_size = 1,
assoc = Parent.address_map_cache_assoc,
size = Parent.address_map_cache_entries),
"Indexing policy of the Physical-to-Structural Address Map Cache")
ps_address_map_cache_replacement_policy = Param.BaseReplacementPolicy(
LRURP(),
"Replacement policy of the Physical-to-Structural Address Map Cache")
sp_address_map_cache_indexing_policy = Param.BaseIndexingPolicy(
SetAssociative(entry_size = 1,
assoc = Parent.address_map_cache_assoc,
size = Parent.address_map_cache_entries),
"Indexing policy of the Structural-to-Physical Address Mao Cache")
sp_address_map_cache_replacement_policy = Param.BaseReplacementPolicy(
LRURP(),
"Replacement policy of the Structural-to-Physical Address Map Cache")

View File

@@ -35,6 +35,7 @@ SimObject('Prefetcher.py')
Source('access_map_pattern_matching.cc')
Source('base.cc')
Source('delta_correlating_prediction_tables.cc')
Source('irregular_stream_buffer.cc')
Source('queued.cc')
Source('signature_path.cc')
Source('signature_path_v2.cc')

View File

@@ -0,0 +1,210 @@
/**
* 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/irregular_stream_buffer.hh"
#include "debug/HWPrefetch.hh"
#include "mem/cache/prefetch/associative_set_impl.hh"
#include "params/IrregularStreamBufferPrefetcher.hh"
IrregularStreamBufferPrefetcher::IrregularStreamBufferPrefetcher(
const IrregularStreamBufferPrefetcherParams *p)
: QueuedPrefetcher(p), maxCounterValue(p->max_counter_value),
chunkSize(p->chunk_size),
prefetchCandidatesPerEntry(p->prefetch_candidates_per_entry),
degree(p->degree),
trainingUnit(p->training_unit_assoc, p->training_unit_entries,
p->training_unit_indexing_policy,
p->training_unit_replacement_policy),
psAddressMappingCache(p->address_map_cache_assoc,
p->address_map_cache_entries,
p->ps_address_map_cache_indexing_policy,
p->ps_address_map_cache_replacement_policy,
AddressMappingEntry(prefetchCandidatesPerEntry)),
spAddressMappingCache(p->address_map_cache_assoc,
p->address_map_cache_entries,
p->sp_address_map_cache_indexing_policy,
p->sp_address_map_cache_replacement_policy,
AddressMappingEntry(prefetchCandidatesPerEntry)),
structuralAddressCounter(0)
{
assert(isPowerOf2(prefetchCandidatesPerEntry));
}
void
IrregularStreamBufferPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
std::vector<AddrPriority> &addresses)
{
// This prefetcher requires a PC
if (!pfi.hasPC()) {
return;
}
bool is_secure = pfi.isSecure();
Addr pc = pfi.getPC();
Addr addr = blockIndex(pfi.getAddr());
// Training, if the entry exists, then we found a correlation between
// the entry lastAddress (named as correlated_addr_A) and the address of
// the current access (named as correlated_addr_B)
TrainingUnitEntry *entry = trainingUnit.findEntry(pc, is_secure);
bool correlated_addr_found = false;
Addr correlated_addr_A = 0;
Addr correlated_addr_B = 0;
if (entry != nullptr && entry->lastAddressSecure == is_secure) {
trainingUnit.accessEntry(entry);
correlated_addr_found = true;
correlated_addr_A = entry->lastAddress;
correlated_addr_B = addr;
} else {
entry = trainingUnit.findVictim(pc);
assert(entry != nullptr);
trainingUnit.insertEntry(pc, is_secure, entry);
}
// Update the entry
entry->lastAddress = addr;
entry->lastAddressSecure = is_secure;
if (correlated_addr_found) {
// If a correlation was found, update the Physical-to-Structural
// table accordingly
AddressMapping &mapping_A = getPSMapping(correlated_addr_A, is_secure);
AddressMapping &mapping_B = getPSMapping(correlated_addr_B, is_secure);
if (mapping_A.counter > 0 && mapping_B.counter > 0) {
// Entry for A and B
if (mapping_B.address == (mapping_A.address + 1)) {
if (mapping_B.counter < maxCounterValue) {
mapping_B.counter += 1;
}
} else {
if (mapping_B.counter == 1) {
// counter would hit 0, reassign address
mapping_B.counter = 1;
mapping_B.address = mapping_A.address + 1;
addStructuralToPhysicalEntry(mapping_B.address, is_secure,
correlated_addr_B);
} else {
mapping_B.counter -= 1;
}
}
} else {
if (mapping_A.counter == 0) {
// if A is not valid, generate a new structural address
mapping_A.counter = 1;
mapping_A.address = structuralAddressCounter;
structuralAddressCounter += chunkSize;
addStructuralToPhysicalEntry(mapping_A.address,
is_secure, correlated_addr_A);
}
mapping_B.counter = 1;
mapping_B.address = mapping_A.address + 1;
// update SP-AMC
addStructuralToPhysicalEntry(mapping_B.address, is_secure,
correlated_addr_B);
}
}
// Use the PS mapping to predict future accesses using the current address
// - Look for the structured address
// - if it exists, use it to generate prefetches for the subsequent
// addresses in ascending order, as many as indicated by the degree
// (given the structured address S, prefetch S+1, S+2, .. up to S+degree)
Addr amc_address = addr / prefetchCandidatesPerEntry;
Addr map_index = addr % prefetchCandidatesPerEntry;
AddressMappingEntry *ps_am = psAddressMappingCache.findEntry(amc_address,
is_secure);
if (ps_am != nullptr) {
AddressMapping &mapping = ps_am->mappings[map_index];
if (mapping.counter > 0) {
Addr sp_address = mapping.address / prefetchCandidatesPerEntry;
Addr sp_index = mapping.address % prefetchCandidatesPerEntry;
AddressMappingEntry *sp_am =
spAddressMappingCache.findEntry(sp_address, is_secure);
assert(sp_am != nullptr);
for (unsigned d = 1;
d <= degree && (sp_index + d) < prefetchCandidatesPerEntry;
d += 1)
{
AddressMapping &spm = sp_am->mappings[sp_index + d];
//generate prefetch
if (spm.counter > 0) {
Addr pf_addr = spm.address << lBlkSize;
addresses.push_back(AddrPriority(pf_addr, 0));
}
}
}
}
}
IrregularStreamBufferPrefetcher::AddressMapping&
IrregularStreamBufferPrefetcher::getPSMapping(Addr paddr, bool is_secure)
{
Addr amc_address = paddr / prefetchCandidatesPerEntry;
Addr map_index = paddr % prefetchCandidatesPerEntry;
AddressMappingEntry *ps_entry =
psAddressMappingCache.findEntry(amc_address, is_secure);
if (ps_entry != nullptr) {
// A PS-AMC line already exists
psAddressMappingCache.accessEntry(ps_entry);
} else {
ps_entry = psAddressMappingCache.findVictim(amc_address);
assert(ps_entry != nullptr);
psAddressMappingCache.insertEntry(amc_address, is_secure, ps_entry);
}
return ps_entry->mappings[map_index];
}
void
IrregularStreamBufferPrefetcher::addStructuralToPhysicalEntry(
Addr structural_address, bool is_secure, Addr physical_address)
{
Addr amc_address = structural_address / prefetchCandidatesPerEntry;
Addr map_index = structural_address % prefetchCandidatesPerEntry;
AddressMappingEntry *sp_entry =
spAddressMappingCache.findEntry(amc_address, is_secure);
if (sp_entry != nullptr) {
spAddressMappingCache.accessEntry(sp_entry);
} else {
sp_entry = spAddressMappingCache.findVictim(amc_address);
assert(sp_entry != nullptr);
spAddressMappingCache.insertEntry(amc_address, is_secure, sp_entry);
}
AddressMapping &mapping = sp_entry->mappings[map_index];
mapping.address = physical_address;
mapping.counter = 1;
}
IrregularStreamBufferPrefetcher*
IrregularStreamBufferPrefetcherParams::create()
{
return new IrregularStreamBufferPrefetcher(this);
}

View File

@@ -0,0 +1,131 @@
/**
* 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 Irregular Stream Buffer prefetcher
* Reference:
* Jain, A., & Lin, C. (2013, December). Linearizing irregular memory
* accesses for improved correlated prefetching. In Proceedings of the
* 46th Annual IEEE/ACM International Symposium on Microarchitecture
* (pp. 247-259). ACM.
*/
#ifndef __MEM_CACHE_PREFETCH_IRREGULAR_STREAM_BUFFER_HH__
#define __MEM_CACHE_PREFETCH_IRREGULAR_STREAM_BUFFER_HH__
#include "base/callback.hh"
#include "mem/cache/prefetch/associative_set.hh"
#include "mem/cache/prefetch/queued.hh"
struct IrregularStreamBufferPrefetcherParams;
class IrregularStreamBufferPrefetcher : public QueuedPrefetcher
{
/** Maximum value of the confidence counters */
const unsigned maxCounterValue;
/** Size in bytes of a temporal stream */
const size_t chunkSize;
/** Number of prefetch candidates per Physical-to-Structural entry */
const unsigned prefetchCandidatesPerEntry;
/** Number of maximum prefetches requests created when predicting */
const unsigned degree;
/**
* Training Unit Entry datatype, it holds the last accessed address and
* its secure flag
*/
struct TrainingUnitEntry : public TaggedEntry {
Addr lastAddress;
bool lastAddressSecure;
};
/** Map of PCs to Training unit entries */
AssociativeSet<TrainingUnitEntry> trainingUnit;
/** Address Mapping entry, holds an address and a confidence counter */
struct AddressMapping {
Addr address;
unsigned counter;
AddressMapping() : address(0), counter(0)
{}
};
/**
* Maps a set of contiguous addresses to another set of (not necessarily
* contiguos) addresses, with their corresponding confidence counters
*/
struct AddressMappingEntry : public TaggedEntry {
std::vector<AddressMapping> mappings;
AddressMappingEntry(size_t num_mappings) : mappings(num_mappings)
{}
void reset() override
{
for (auto &entry : mappings) {
entry.address = 0;
entry.counter = 0;
}
}
};
/** Physical-to-Structured mappings table */
AssociativeSet<AddressMappingEntry> psAddressMappingCache;
/** Structured-to-Physical mappings table */
AssociativeSet<AddressMappingEntry> spAddressMappingCache;
/**
* Counter of allocated structural addresses, increased by "chunkSize",
* each time a new structured address is allocated
*/
uint64_t structuralAddressCounter;
/**
* Add a mapping to the Structured-to-Physica mapping table
* @param structuralAddress structural address
* @param is_secure whether this page is inside the secure memory area
* @param physical_address corresponding physical address
*/
void addStructuralToPhysicalEntry(Addr structuralAddress, bool is_secure,
Addr physical_address);
/**
* Obtain the Physical-to-Structured mapping entry of the given physical
* address. If the entry does not exist a new one is allocated, replacing
* an existing one if needed.
* @param paddr physical address
* @param is_secure whether this page is inside the secure memory area
* @result reference to the entry
*/
AddressMapping& getPSMapping(Addr paddr, bool is_secure);
public:
IrregularStreamBufferPrefetcher(
const IrregularStreamBufferPrefetcherParams *p);
~IrregularStreamBufferPrefetcher() {}
void calculatePrefetch(const PrefetchInfo &pfi,
std::vector<AddrPriority> &addresses) override;
};
#endif//__MEM_CACHE_PREFETCH_IRREGULAR_STREAM_BUFFER_HH__