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:
Daniel R. Carvalho
2019-12-29 10:14:26 +01:00
committed by Daniel Carvalho
parent 31b34874d5
commit 2848288097
5 changed files with 86 additions and 152 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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:
/**