mem-cache: Use AssociativeSet in Stride prefetcher
Avoid replicating associative set functionality in Stride prefetcher's pc tables. The indexing policy used previously had some peculiarities, so both the extractTag and extractSet have been made virtual so that previous behavior could be kept. Change-Id: I19a86cb3c4b40031fef427d5f7eed9d5c5673a44 Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24603 Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Daniel Carvalho
parent
31b34874d5
commit
2848288097
18
src/mem/cache/prefetch/Prefetcher.py
vendored
18
src/mem/cache/prefetch/Prefetcher.py
vendored
@@ -139,6 +139,11 @@ class QueuedPrefetcher(BasePrefetcher):
|
||||
throttle_control_percentage = Param.Percent(0, "Percentage of requests \
|
||||
that can be throttled depending on the accuracy of the prefetcher.")
|
||||
|
||||
class StridePrefetcherHashedSetAssociative(SetAssociative):
|
||||
type = 'StridePrefetcherHashedSetAssociative'
|
||||
cxx_class = 'Prefetcher::StridePrefetcherHashedSetAssociative'
|
||||
cxx_header = "mem/cache/prefetch/stride.hh"
|
||||
|
||||
class StridePrefetcher(QueuedPrefetcher):
|
||||
type = 'StridePrefetcher'
|
||||
cxx_class = 'Prefetcher::Stride'
|
||||
@@ -154,15 +159,18 @@ class StridePrefetcher(QueuedPrefetcher):
|
||||
confidence_threshold = Param.Percent(50,
|
||||
"Prefetch generation confidence threshold")
|
||||
|
||||
table_sets = Param.Int(16, "Number of sets in PC lookup table")
|
||||
table_assoc = Param.Int(4, "Associativity of PC lookup table")
|
||||
use_master_id = Param.Bool(True, "Use master id based history")
|
||||
|
||||
degree = Param.Int(4, "Number of prefetches to generate")
|
||||
|
||||
# Get replacement policy
|
||||
replacement_policy = Param.BaseReplacementPolicy(RandomRP(),
|
||||
"Replacement policy")
|
||||
table_assoc = Param.Int(4, "Associativity of the PC table")
|
||||
table_entries = Param.MemorySize("64", "Number of entries of the PC table")
|
||||
table_indexing_policy = Param.BaseIndexingPolicy(
|
||||
StridePrefetcherHashedSetAssociative(entry_size = 1,
|
||||
assoc = Parent.table_assoc, size = Parent.table_entries),
|
||||
"Indexing policy of the PC table")
|
||||
table_replacement_policy = Param.BaseReplacementPolicy(RandomRP(),
|
||||
"Replacement policy of the PC table")
|
||||
|
||||
class TaggedPrefetcher(QueuedPrefetcher):
|
||||
type = 'TaggedPrefetcher'
|
||||
|
||||
100
src/mem/cache/prefetch/stride.cc
vendored
100
src/mem/cache/prefetch/stride.cc
vendored
@@ -53,13 +53,14 @@
|
||||
#include "base/random.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/HWPrefetch.hh"
|
||||
#include "mem/cache/prefetch/associative_set_impl.hh"
|
||||
#include "mem/cache/replacement_policies/base.hh"
|
||||
#include "params/StridePrefetcher.hh"
|
||||
|
||||
namespace Prefetcher {
|
||||
|
||||
Stride::StrideEntry::StrideEntry(const SatCounter& init_confidence)
|
||||
: ReplaceableEntry(), confidence(init_confidence)
|
||||
: TaggedEntry(), confidence(init_confidence)
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
@@ -67,9 +68,7 @@ Stride::StrideEntry::StrideEntry(const SatCounter& init_confidence)
|
||||
void
|
||||
Stride::StrideEntry::invalidate()
|
||||
{
|
||||
instAddr = 0;
|
||||
lastAddr = 0;
|
||||
isSecure = false;
|
||||
stride = 0;
|
||||
confidence.reset();
|
||||
}
|
||||
@@ -78,13 +77,11 @@ Stride::Stride(const StridePrefetcherParams *p)
|
||||
: Queued(p),
|
||||
initConfidence(p->confidence_counter_bits, p->initial_confidence),
|
||||
threshConf(p->confidence_threshold/100.0),
|
||||
pcTableAssoc(p->table_assoc),
|
||||
pcTableSets(p->table_sets),
|
||||
useMasterId(p->use_master_id),
|
||||
degree(p->degree),
|
||||
replacementPolicy(p->replacement_policy)
|
||||
pcTableInfo(p->table_assoc, p->table_entries, p->table_indexing_policy,
|
||||
p->table_replacement_policy)
|
||||
{
|
||||
assert(isPowerOf2(pcTableSets));
|
||||
}
|
||||
|
||||
Stride::PCTable*
|
||||
@@ -104,7 +101,8 @@ Stride::allocateNewContext(int context)
|
||||
{
|
||||
// Create new table
|
||||
auto insertion_result = pcTables.insert(std::make_pair(context,
|
||||
PCTable(pcTableAssoc, pcTableSets, name(), replacementPolicy,
|
||||
PCTable(pcTableInfo.assoc, pcTableInfo.numEntries,
|
||||
pcTableInfo.indexingPolicy, pcTableInfo.replacementPolicy,
|
||||
StrideEntry(initConfidence))));
|
||||
|
||||
DPRINTF(HWPrefetch, "Adding context %i with stride entries\n", context);
|
||||
@@ -113,28 +111,6 @@ Stride::allocateNewContext(int context)
|
||||
return &(insertion_result.first->second);
|
||||
}
|
||||
|
||||
Stride::PCTable::PCTable(int assoc, int sets, const std::string name,
|
||||
BaseReplacementPolicy* replacementPolicy, StrideEntry init_confidence)
|
||||
: pcTableSets(sets), _name(name), entries(pcTableSets),
|
||||
replacementPolicy(replacementPolicy)
|
||||
{
|
||||
for (int set = 0; set < sets; set++) {
|
||||
entries[set].resize(assoc, init_confidence);
|
||||
for (int way = 0; way < assoc; way++) {
|
||||
// Inform the entry its position
|
||||
entries[set][way].setPosition(set, way);
|
||||
|
||||
// Initialize replacement policy data
|
||||
entries[set][way].replacementData =
|
||||
replacementPolicy->instantiateEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stride::PCTable::~PCTable()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Stride::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
@@ -157,6 +133,8 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
StrideEntry *entry = pcTable->findEntry(pc, is_secure);
|
||||
|
||||
if (entry != nullptr) {
|
||||
pcTable->accessEntry(entry);
|
||||
|
||||
// Hit in table
|
||||
int new_stride = pf_addr - entry->lastAddr;
|
||||
bool stride_match = (new_stride == entry->stride);
|
||||
@@ -202,66 +180,34 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
|
||||
StrideEntry* entry = pcTable->findVictim(pc);
|
||||
|
||||
// Invalidate victim
|
||||
entry->invalidate();
|
||||
replacementPolicy->invalidate(entry->replacementData);
|
||||
|
||||
// Insert new entry's data
|
||||
entry->instAddr = pc;
|
||||
entry->lastAddr = pf_addr;
|
||||
entry->isSecure = is_secure;
|
||||
replacementPolicy->reset(entry->replacementData);
|
||||
pcTable->insertEntry(pc, is_secure, entry);
|
||||
}
|
||||
}
|
||||
|
||||
inline Addr
|
||||
Stride::PCTable::pcHash(Addr pc) const
|
||||
inline uint32_t
|
||||
StridePrefetcherHashedSetAssociative::extractSet(const Addr pc) const
|
||||
{
|
||||
Addr hash1 = pc >> 1;
|
||||
Addr hash2 = hash1 >> floorLog2(pcTableSets);
|
||||
return (hash1 ^ hash2) & (Addr)(pcTableSets - 1);
|
||||
const Addr hash1 = pc >> 1;
|
||||
const Addr hash2 = hash1 >> tagShift;
|
||||
return (hash1 ^ hash2) & setMask;
|
||||
}
|
||||
|
||||
inline Stride::StrideEntry*
|
||||
Stride::PCTable::findVictim(Addr pc)
|
||||
Addr
|
||||
StridePrefetcherHashedSetAssociative::extractTag(const Addr addr) const
|
||||
{
|
||||
// Rand replacement for now
|
||||
int set = pcHash(pc);
|
||||
|
||||
// Get possible entries to be victimized
|
||||
std::vector<ReplaceableEntry*> possible_entries;
|
||||
for (auto& entry : entries[set]) {
|
||||
possible_entries.push_back(&entry);
|
||||
}
|
||||
|
||||
// Choose victim based on replacement policy
|
||||
StrideEntry* victim = static_cast<StrideEntry*>(
|
||||
replacementPolicy->getVictim(possible_entries));
|
||||
|
||||
DPRINTF(HWPrefetch, "Victimizing lookup table[%d][%d].\n",
|
||||
victim->getSet(), victim->getWay());
|
||||
|
||||
return victim;
|
||||
}
|
||||
|
||||
inline Stride::StrideEntry*
|
||||
Stride::PCTable::findEntry(Addr pc, bool is_secure)
|
||||
{
|
||||
int set = pcHash(pc);
|
||||
for (auto& entry : entries[set]) {
|
||||
// Search ways for match
|
||||
if ((entry.instAddr == pc) && (entry.isSecure == is_secure)) {
|
||||
DPRINTF(HWPrefetch, "Lookup hit table[%d][%d].\n", entry.getSet(),
|
||||
entry.getWay());
|
||||
replacementPolicy->touch(entry.replacementData);
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // namespace Prefetcher
|
||||
|
||||
Prefetcher::StridePrefetcherHashedSetAssociative*
|
||||
StridePrefetcherHashedSetAssociativeParams::create()
|
||||
{
|
||||
return new Prefetcher::StridePrefetcherHashedSetAssociative(this);
|
||||
}
|
||||
|
||||
Prefetcher::Stride*
|
||||
StridePrefetcherParams::create()
|
||||
{
|
||||
|
||||
114
src/mem/cache/prefetch/stride.hh
vendored
114
src/mem/cache/prefetch/stride.hh
vendored
@@ -53,15 +53,38 @@
|
||||
|
||||
#include "base/sat_counter.hh"
|
||||
#include "base/types.hh"
|
||||
#include "mem/cache/prefetch/associative_set.hh"
|
||||
#include "mem/cache/prefetch/queued.hh"
|
||||
#include "mem/cache/replacement_policies/replaceable_entry.hh"
|
||||
#include "mem/cache/tags/indexing_policies/set_associative.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "params/StridePrefetcherHashedSetAssociative.hh"
|
||||
|
||||
class BaseIndexingPolicy;
|
||||
class BaseReplacementPolicy;
|
||||
struct StridePrefetcherParams;
|
||||
|
||||
namespace Prefetcher {
|
||||
|
||||
/**
|
||||
* Override the default set associative to apply a specific hash function
|
||||
* when extracting a set.
|
||||
*/
|
||||
class StridePrefetcherHashedSetAssociative : public SetAssociative
|
||||
{
|
||||
protected:
|
||||
uint32_t extractSet(const Addr addr) const override;
|
||||
Addr extractTag(const Addr addr) const override;
|
||||
|
||||
public:
|
||||
StridePrefetcherHashedSetAssociative(
|
||||
const StridePrefetcherHashedSetAssociativeParams *p)
|
||||
: SetAssociative(p)
|
||||
{
|
||||
}
|
||||
~StridePrefetcherHashedSetAssociative() = default;
|
||||
};
|
||||
|
||||
class Stride : public Queued
|
||||
{
|
||||
protected:
|
||||
@@ -71,86 +94,43 @@ class Stride : public Queued
|
||||
/** Confidence threshold for prefetch generation. */
|
||||
const double threshConf;
|
||||
|
||||
const int pcTableAssoc;
|
||||
const int pcTableSets;
|
||||
|
||||
const bool useMasterId;
|
||||
|
||||
const int degree;
|
||||
|
||||
/** Replacement policy used in the PC tables. */
|
||||
BaseReplacementPolicy* replacementPolicy;
|
||||
/**
|
||||
* Information used to create a new PC table. All of them behave equally.
|
||||
*/
|
||||
const struct PCTableInfo
|
||||
{
|
||||
const int assoc;
|
||||
const int numEntries;
|
||||
|
||||
struct StrideEntry : public ReplaceableEntry
|
||||
BaseIndexingPolicy* const indexingPolicy;
|
||||
BaseReplacementPolicy* const replacementPolicy;
|
||||
|
||||
PCTableInfo(int assoc, int num_entries,
|
||||
BaseIndexingPolicy* indexing_policy,
|
||||
BaseReplacementPolicy* replacement_policy)
|
||||
: assoc(assoc), numEntries(num_entries),
|
||||
indexingPolicy(indexing_policy),
|
||||
replacementPolicy(replacement_policy)
|
||||
{
|
||||
}
|
||||
} pcTableInfo;
|
||||
|
||||
/** Tagged by hashed PCs. */
|
||||
struct StrideEntry : public TaggedEntry
|
||||
{
|
||||
StrideEntry(const SatCounter& init_confidence);
|
||||
|
||||
/** Invalidate the entry */
|
||||
void invalidate();
|
||||
void invalidate() override;
|
||||
|
||||
Addr instAddr;
|
||||
Addr lastAddr;
|
||||
bool isSecure;
|
||||
int stride;
|
||||
SatCounter confidence;
|
||||
};
|
||||
|
||||
class PCTable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor. Create a table with given parameters.
|
||||
*
|
||||
* @param assoc Associativity of the table.
|
||||
* @param sets Number of sets in the table.
|
||||
* @param name Name of the prefetcher.
|
||||
* @param replacementPolicy Replacement policy used by the table.
|
||||
*/
|
||||
PCTable(int assoc, int sets, const std::string name,
|
||||
BaseReplacementPolicy* replacementPolicy,
|
||||
StrideEntry init_confidence);
|
||||
|
||||
/**
|
||||
* Default destructor.
|
||||
*/
|
||||
~PCTable();
|
||||
|
||||
/**
|
||||
* Search for an entry in the pc table.
|
||||
*
|
||||
* @param pc The PC to look for.
|
||||
* @param is_secure True if the target memory space is secure.
|
||||
* @return Pointer to the entry.
|
||||
*/
|
||||
StrideEntry* findEntry(Addr pc, bool is_secure);
|
||||
|
||||
/**
|
||||
* Find a replacement victim to make room for given PC.
|
||||
*
|
||||
* @param pc The PC value.
|
||||
* @return The victimized entry.
|
||||
*/
|
||||
StrideEntry* findVictim(Addr pc);
|
||||
|
||||
private:
|
||||
const std::string name() {return _name; }
|
||||
const int pcTableSets;
|
||||
const std::string _name;
|
||||
std::vector<std::vector<StrideEntry>> entries;
|
||||
|
||||
/**
|
||||
* Replacement policy used by StridePrefetcher.
|
||||
*/
|
||||
BaseReplacementPolicy* replacementPolicy;
|
||||
|
||||
/**
|
||||
* PC hashing function to index sets in the table.
|
||||
*
|
||||
* @param pc The PC value.
|
||||
* @return The set to which this PC maps.
|
||||
*/
|
||||
Addr pcHash(Addr pc) const;
|
||||
};
|
||||
typedef AssociativeSet<StrideEntry> PCTable;
|
||||
std::unordered_map<int, PCTable> pcTables;
|
||||
|
||||
/**
|
||||
|
||||
2
src/mem/cache/tags/indexing_policies/base.hh
vendored
2
src/mem/cache/tags/indexing_policies/base.hh
vendored
@@ -133,7 +133,7 @@ class BaseIndexingPolicy : public SimObject
|
||||
* @param addr The address to get the tag from.
|
||||
* @return The tag of the address.
|
||||
*/
|
||||
Addr extractTag(const Addr addr) const;
|
||||
virtual Addr extractTag(const Addr addr) const;
|
||||
|
||||
/**
|
||||
* Find all possible entries for insertion and replacement of an address.
|
||||
|
||||
@@ -78,14 +78,14 @@ class ReplaceableEntry;
|
||||
*/
|
||||
class SetAssociative : public BaseIndexingPolicy
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
/**
|
||||
* Apply a hash function to calculate address set.
|
||||
*
|
||||
* @param addr The address to calculate the set for.
|
||||
* @return The set index for given combination of address and way.
|
||||
*/
|
||||
uint32_t extractSet(const Addr addr) const;
|
||||
virtual uint32_t extractSet(const Addr addr) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user