base, mem-cache: Do not expose tags to the AssociativeCache

Exposing the tag of a cache entry through the associative
cache APIs makes it hard to generalize the cache for
structured tags. Ultimately the tag should be a property
of the cache entry and any tag extraction logic (if needed)
should reside there. In this we can reuse the associative
cache for different Entry params, each one bearing a different
representation of a tag

Change-Id: I51b4526be64683614e01d763b1656e5be23a611b
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Giacomo Travaglini
2024-04-12 14:16:10 +01:00
parent 31d967b453
commit 4814fedef0
28 changed files with 140 additions and 79 deletions

View File

@@ -1,4 +1,16 @@
/*
* Copyright (c) 2024 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2024 Pranith Kumar
* Copyright (c) 2018 Metempsy Technology Consulting
* All rights reserved
@@ -148,17 +160,6 @@ class AssociativeCache : public Named
initParams(num_entries, associativity);
}
/**
* Get the tag for the addr
* @param addr Addr to get the tag for
* @return Tag for the address
*/
virtual Addr
getTag(const Addr addr) const
{
return indexingPolicy->extractTag(addr);
}
/**
* Do an access to the entry if it exists.
* This is required to update the replacement information data.
@@ -196,13 +197,11 @@ class AssociativeCache : public Named
virtual Entry*
findEntry(const Addr addr) const
{
auto tag = getTag(addr);
auto candidates = indexingPolicy->getPossibleEntries(addr);
for (auto candidate : candidates) {
Entry *entry = static_cast<Entry*>(candidate);
if (entry->matchTag(tag)) {
if (entry->match(addr)) {
return entry;
}
}
@@ -247,7 +246,7 @@ class AssociativeCache : public Named
virtual void
insertEntry(const Addr addr, Entry *entry)
{
entry->insert(indexingPolicy->extractTag(addr));
entry->insert(addr);
replPolicy->reset(entry->replacementData);
}

View File

@@ -1,4 +1,16 @@
/**
* Copyright (c) 2024 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2024 - Pranith Kumar
* Copyright (c) 2020 Inria
* All rights reserved.
@@ -35,6 +47,7 @@
#include "base/cprintf.hh"
#include "base/types.hh"
#include "mem/cache/replacement_policies/replaceable_entry.hh"
#include "mem/cache/tags/indexing_policies/base.hh"
namespace gem5
{
@@ -46,8 +59,11 @@ namespace gem5
class CacheEntry : public ReplaceableEntry
{
public:
CacheEntry() = default;
CacheEntry(BaseIndexingPolicy *ip) : indexingPolicy(ip) {}
~CacheEntry() = default;
CacheEntry(const CacheEntry &rhs)
: indexingPolicy(rhs.indexingPolicy)
{}
/**
* Checks if the entry is valid.
@@ -66,26 +82,26 @@ class CacheEntry : public ReplaceableEntry
/**
* Checks if the given tag information corresponds to this entry's.
*
* @param tag The tag value to compare to.
* @param addr The address value to be compared before tag is extracted
* @return True if the tag information match this entry's.
*/
virtual bool
matchTag(const Addr tag) const
match(const Addr addr) const
{
return isValid() && (getTag() == tag);
return isValid() && (getTag() == extractTag(addr));
}
/**
* Insert the block by assigning it a tag and marking it valid. Touches
* block if it hadn't been touched previously.
*
* @param tag The tag value.
* @param addr The address value.
*/
virtual void
insert(const Addr tag)
insert(const Addr addr)
{
setValid();
setTag(tag);
setTag(extractTag(addr));
}
/** Invalidate the block. Its contents are no longer valid. */
@@ -103,6 +119,12 @@ class CacheEntry : public ReplaceableEntry
isValid(), ReplaceableEntry::print());
}
void
setIndexingPolicy(BaseIndexingPolicy *ip)
{
indexingPolicy = ip;
}
protected:
/**
* Set tag associated to this block.
@@ -119,6 +141,12 @@ class CacheEntry : public ReplaceableEntry
valid = true;
}
virtual Addr
extractTag(Addr addr) const
{
return indexingPolicy->extractTag(addr);
}
private:
/**
* Valid bit. The contents of this entry are only valid if this bit is set.
@@ -127,6 +155,8 @@ class CacheEntry : public ReplaceableEntry
*/
bool valid{false};
BaseIndexingPolicy *indexingPolicy{nullptr};
/** The entry's tag. */
Addr tag{MaxAddr};
};

View File

@@ -125,7 +125,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size)
// forward snoops is overridden in init() once we can query
// whether the connected requestor is actually snooping or not
tempBlock = new TempCacheBlk(blkSize);
tempBlock = new TempCacheBlk(blkSize, tags->params().indexing_policy);
tags->tagsInit();
if (prefetcher)

View File

@@ -526,9 +526,11 @@ class TempCacheBlk final : public CacheBlk
* Creates a temporary cache block, with its own storage.
* @param size The size (in bytes) of this cache block.
*/
TempCacheBlk(unsigned size) : CacheBlk()
TempCacheBlk(unsigned size, BaseIndexingPolicy *ip) : CacheBlk()
{
data = new uint8_t[size];
setIndexingPolicy(ip);
}
TempCacheBlk(const TempCacheBlk&) = delete;
using CacheBlk::operator=;

View File

@@ -53,7 +53,8 @@ FrequentValues::FrequentValues(const Params &p)
numSamples(p.num_samples), takenSamples(0), phase(SAMPLING),
VFT((name() + ".VFT").c_str(),
p.vft_entries, p.vft_assoc, p.vft_replacement_policy,
p.vft_indexing_policy, VFTEntry(counterBits)),
p.vft_indexing_policy,
VFTEntry(counterBits, p.vft_indexing_policy)),
codeGenerationEvent([this]{ phase = COMPRESSING; }, name())
{
fatal_if((numVFTEntries - 1) > mask(chunkSizeBits),

View File

@@ -129,8 +129,8 @@ class FrequentValues : public Base
*/
SatCounter32 counter;
VFTEntry(std::size_t num_bits)
: CacheEntry(), value(0), counter(num_bits)
VFTEntry(std::size_t num_bits, BaseIndexingPolicy *ip)
: CacheEntry(ip), value(0), counter(num_bits)
{
}

View File

@@ -56,7 +56,8 @@ AccessMapPatternMatching::AccessMapPatternMatching(
p.access_map_table_assoc,
p.access_map_table_replacement_policy,
p.access_map_table_indexing_policy,
AccessMapEntry(hotZoneSize / blkSize)),
AccessMapEntry(hotZoneSize / blkSize,
p.access_map_table_indexing_policy)),
numGoodPrefetches(0), numTotalPrefetches(0), numRawCacheMisses(0),
numRawCacheHits(0), degree(startDegree), usefulDegree(startDegree),
epochEvent([this]{ processEpochEvent(); }, name())

View File

@@ -94,8 +94,8 @@ class AccessMapPatternMatching : public ClockedObject
/** vector containing the state of the cachelines in this zone */
std::vector<AccessMapState> states;
AccessMapEntry(size_t num_entries)
: TaggedEntry(), states(num_entries, AM_INIT)
AccessMapEntry(size_t num_entries, BaseIndexingPolicy *ip)
: TaggedEntry(ip), states(num_entries, AM_INIT)
{
}

View File

@@ -86,7 +86,6 @@ class AssociativeSet : public AssociativeCache<Entry>
private:
// The following APIs are excluded since they lack the secure bit
using AssociativeCache<Entry>::getTag;
using AssociativeCache<Entry>::accessEntryByAddr;
using AssociativeCache<Entry>::findEntry;
using AssociativeCache<Entry>::insertEntry;

View File

@@ -44,7 +44,8 @@ DeltaCorrelatingPredictionTables::DeltaCorrelatingPredictionTables(
deltaBits(p.delta_bits), deltaMaskBits(p.delta_mask_bits),
table((name() + "DCPT").c_str(), p.table_entries,
p.table_assoc, p.table_replacement_policy,
p.table_indexing_policy, DCPTEntry(p.deltas_per_entry))
p.table_indexing_policy,
DCPTEntry(p.deltas_per_entry, p.table_indexing_policy))
{
}

View File

@@ -76,8 +76,8 @@ class DeltaCorrelatingPredictionTables : public SimObject
* Constructor
* @param num_deltas number of deltas stored in the entry
*/
DCPTEntry(unsigned int num_deltas)
: CacheEntry(), lastAddress(0), deltas(num_deltas)
DCPTEntry(unsigned int num_deltas, BaseIndexingPolicy *ip)
: CacheEntry(ip), lastAddress(0), deltas(num_deltas)
{
}

View File

@@ -49,11 +49,13 @@ IndirectMemory::IndirectMemory(const IndirectMemoryPrefetcherParams &p)
p.pt_table_assoc,
p.pt_table_replacement_policy,
p.pt_table_indexing_policy,
PrefetchTableEntry(p.num_indirect_counter_bits)),
PrefetchTableEntry(p.num_indirect_counter_bits,
p.pt_table_indexing_policy)),
ipd((name() + ".IPD").c_str(), p.ipd_table_entries, p.ipd_table_assoc,
p.ipd_table_replacement_policy,
p.ipd_table_indexing_policy,
IndirectPatternDetectorEntry(p.addr_array_len, shiftValues.size())),
IndirectPatternDetectorEntry(p.addr_array_len, shiftValues.size(),
p.ipd_table_indexing_policy)),
ipdEntryTrackingMisses(nullptr), byteOrder(p.sys->getGuestByteOrder())
{
}

View File

@@ -98,8 +98,9 @@ class IndirectMemory : public Queued
*/
bool increasedIndirectCounter;
PrefetchTableEntry(unsigned indirect_counter_bits)
: TaggedEntry(), address(0), secure(false), streamCounter(0),
PrefetchTableEntry(unsigned indirect_counter_bits,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), address(0), secure(false), streamCounter(0),
enabled(false), index(0), baseAddr(0), shift(0),
indirectCounter(indirect_counter_bits),
increasedIndirectCounter(false)
@@ -142,8 +143,9 @@ class IndirectMemory : public Queued
std::vector<std::vector<Addr>> baseAddr;
IndirectPatternDetectorEntry(unsigned int num_addresses,
unsigned int num_shifts)
: TaggedEntry(), idx1(0), idx2(0), secondIndexSet(false),
unsigned int num_shifts,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), idx1(0), idx2(0), secondIndexSet(false),
numMisses(0),
baseAddr(num_addresses, std::vector<Addr>(num_shifts))
{

View File

@@ -48,21 +48,22 @@ IrregularStreamBuffer::IrregularStreamBuffer(
p.training_unit_entries,
p.training_unit_assoc,
p.training_unit_replacement_policy,
p.training_unit_indexing_policy),
p.training_unit_indexing_policy,
TrainingUnitEntry(p.training_unit_indexing_policy)),
psAddressMappingCache((name() + ".PSAddressMappingCache").c_str(),
p.address_map_cache_entries,
p.address_map_cache_assoc,
p.ps_address_map_cache_replacement_policy,
p.ps_address_map_cache_indexing_policy,
AddressMappingEntry(prefetchCandidatesPerEntry,
p.num_counter_bits)),
p.address_map_cache_entries,
p.address_map_cache_assoc,
p.ps_address_map_cache_replacement_policy,
p.ps_address_map_cache_indexing_policy,
AddressMappingEntry(prefetchCandidatesPerEntry,
p.num_counter_bits, p.ps_address_map_cache_indexing_policy)),
spAddressMappingCache((name() + ".SPAddressMappingCache").c_str(),
p.address_map_cache_entries,
p.address_map_cache_assoc,
p.sp_address_map_cache_replacement_policy,
p.sp_address_map_cache_indexing_policy,
AddressMappingEntry(prefetchCandidatesPerEntry,
p.num_counter_bits)),
p.address_map_cache_entries,
p.address_map_cache_assoc,
p.sp_address_map_cache_replacement_policy,
p.sp_address_map_cache_indexing_policy,
AddressMappingEntry(prefetchCandidatesPerEntry,
p.num_counter_bits, p.sp_address_map_cache_indexing_policy)),
structuralAddressCounter(0)
{
assert(isPowerOf2(prefetchCandidatesPerEntry));

View File

@@ -66,6 +66,9 @@ class IrregularStreamBuffer : public Queued
*/
struct TrainingUnitEntry : public TaggedEntry
{
TrainingUnitEntry(BaseIndexingPolicy *ip)
: TaggedEntry(ip), lastAddress(0), lastAddressSecure(false)
{}
Addr lastAddress;
bool lastAddressSecure;
};
@@ -88,8 +91,9 @@ class IrregularStreamBuffer : public Queued
struct AddressMappingEntry : public TaggedEntry
{
std::vector<AddressMapping> mappings;
AddressMappingEntry(size_t num_mappings, unsigned counter_bits)
: TaggedEntry(), mappings(num_mappings, counter_bits)
AddressMappingEntry(size_t num_mappings, unsigned counter_bits,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), mappings(num_mappings, counter_bits)
{
}

View File

@@ -48,7 +48,8 @@ PIF::PIF(const PIFPrefetcherParams &p)
historyBuffer(p.history_buffer_size),
index((name() + ".PIFIndex").c_str(), p.index_entries, p.index_assoc,
p.index_replacement_policy,
p.index_indexing_policy),
p.index_indexing_policy,
IndexEntry(p.index_indexing_policy)),
streamAddressBuffer(p.stream_address_buffer_entries),
listenersPC()
{

View File

@@ -136,6 +136,7 @@ class PIF : public Queued
struct IndexEntry : public TaggedEntry
{
using TaggedEntry::TaggedEntry;
HistoryBuffer::iterator historyIt;
};

View File

@@ -52,13 +52,15 @@ SignaturePath::SignaturePath(const SignaturePathPrefetcherParams &p)
p.signature_table_entries,
p.signature_table_assoc,
p.signature_table_replacement_policy,
p.signature_table_indexing_policy),
p.signature_table_indexing_policy,
SignatureEntry(p.signature_table_indexing_policy)),
patternTable((name() + ".PatternTable").c_str(),
p.pattern_table_entries,
p.pattern_table_assoc,
p.pattern_table_replacement_policy,
p.pattern_table_indexing_policy,
PatternEntry(stridesPerPatternEntry, p.num_counter_bits))
PatternEntry(stridesPerPatternEntry, p.num_counter_bits,
p.pattern_table_indexing_policy))
{
fatal_if(prefetchConfidenceThreshold < 0,
"The prefetch confidence threshold must be greater than 0\n");

View File

@@ -79,7 +79,8 @@ class SignaturePath : public Queued
signature_t signature;
/** Last accessed block within a page */
stride_t lastBlock;
SignatureEntry() : signature(0), lastBlock(0)
SignatureEntry(BaseIndexingPolicy *ip)
: TaggedEntry(ip), signature(0), lastBlock(0)
{}
};
/** Signature table */
@@ -102,8 +103,9 @@ class SignaturePath : public Queued
std::vector<PatternStrideEntry> strideEntries;
/** use counter, used by SPPv2 */
SatCounter8 counter;
PatternEntry(size_t num_strides, unsigned counter_bits)
: TaggedEntry(), strideEntries(num_strides, counter_bits),
PatternEntry(size_t num_strides, unsigned counter_bits,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), strideEntries(num_strides, counter_bits),
counter(counter_bits)
{
}

View File

@@ -56,10 +56,11 @@ SignaturePathV2::SignaturePathV2(const SignaturePathPrefetcherV2Params &p)
: SignaturePath(p),
globalHistoryRegister((name() + ".GlobalHistoryRegister").c_str(),
p.global_history_register_entries,
p.global_history_register_entries,
p.global_history_register_entries,
p.global_history_register_replacement_policy,
p.global_history_register_indexing_policy,
GlobalHistoryEntry())
GlobalHistoryEntry(
p.global_history_register_indexing_policy))
{
}

View File

@@ -62,8 +62,10 @@ class SignaturePathV2 : public SignaturePath
double confidence;
stride_t lastBlock;
stride_t delta;
GlobalHistoryEntry() : signature(0), confidence(0.0), lastBlock(0),
delta(0) {}
GlobalHistoryEntry(BaseIndexingPolicy *ip)
: TaggedEntry(ip), signature(0), confidence(0.0), lastBlock(0),
delta(0)
{}
};
/** Global History Register */
AssociativeSet<GlobalHistoryEntry> globalHistoryRegister;

View File

@@ -44,18 +44,20 @@ STeMS::STeMS(const STeMSPrefetcherParams &p)
reconstructionEntries(p.reconstruction_entries),
activeGenerationTable((name() + ".ActiveGenerationTable").c_str(),
p.active_generation_table_entries,
p.active_generation_table_assoc,
p.active_generation_table_assoc,
p.active_generation_table_replacement_policy,
p.active_generation_table_indexing_policy,
ActiveGenerationTableEntry(
spatialRegionSize / blkSize)),
spatialRegionSize / blkSize,
p.active_generation_table_indexing_policy)),
patternSequenceTable((name() + ".PatternSequenceTable").c_str(),
p.pattern_sequence_table_entries,
p.pattern_sequence_table_assoc,
p.pattern_sequence_table_assoc,
p.pattern_sequence_table_replacement_policy,
p.pattern_sequence_table_indexing_policy,
ActiveGenerationTableEntry(
spatialRegionSize / blkSize)),
spatialRegionSize / blkSize,
p.pattern_sequence_table_indexing_policy)),
rmob(p.region_miss_order_buffer_entries),
addDuplicateEntriesToRMOB(p.add_duplicate_entries_to_rmob),
lastTriggerCounter(0)

View File

@@ -93,8 +93,9 @@ class STeMS : public Queued
/** Sequence of accesses */
std::vector<SequenceEntry> sequence;
ActiveGenerationTableEntry(int num_positions)
: TaggedEntry(), paddress(0), pc(0),
ActiveGenerationTableEntry(int num_positions,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), paddress(0), pc(0),
seqCounter(0), sequence(num_positions)
{
}

View File

@@ -63,8 +63,9 @@ namespace gem5
namespace prefetch
{
Stride::StrideEntry::StrideEntry(const SatCounter8& init_confidence)
: TaggedEntry(), confidence(init_confidence)
Stride::StrideEntry::StrideEntry(const SatCounter8& init_confidence,
BaseIndexingPolicy *ip)
: TaggedEntry(ip), confidence(init_confidence)
{
invalidate();
}
@@ -114,7 +115,7 @@ Stride::allocateNewContext(int context)
pcTableInfo.assoc,
pcTableInfo.replacementPolicy,
pcTableInfo.indexingPolicy,
StrideEntry(initConfidence)));
StrideEntry(initConfidence, pcTableInfo.indexingPolicy)));
DPRINTF(HWPrefetch, "Adding context %i with stride entries\n", context);

View File

@@ -135,7 +135,8 @@ class Stride : public Queued
/** Tagged by hashed PCs. */
struct StrideEntry : public TaggedEntry
{
StrideEntry(const SatCounter8& init_confidence);
StrideEntry(const SatCounter8& init_confidence,
BaseIndexingPolicy *ip);
void invalidate() override;

View File

@@ -161,7 +161,7 @@ class BaseTags : public ClockedObject
} stats;
public:
typedef BaseTagsParams Params;
PARAMS(BaseTags);
BaseTags(const Params &p);
/**

View File

@@ -82,6 +82,9 @@ BaseSetAssoc::tagsInit()
// Associate a replacement data entry to the block
blk->replacementData = replacementPolicy->instantiateEntry();
// This is not used as of now but we set it for security
blk->setIndexingPolicy(indexingPolicy);
}
}

View File

@@ -48,7 +48,9 @@ namespace gem5
class TaggedEntry : public CacheEntry
{
public:
TaggedEntry() : CacheEntry(), _secure(false) {}
TaggedEntry(BaseIndexingPolicy *ip=nullptr)
: CacheEntry(ip), _secure(false)
{}
~TaggedEntry() = default;
/**
@@ -103,7 +105,7 @@ class TaggedEntry : public CacheEntry
}
bool
matchTag(const Addr tag) const override
match(const Addr tag) const override
{
panic("Need is_secure arg");
return false;
@@ -130,7 +132,7 @@ class TaggedEntry : public CacheEntry
void clearSecure() { _secure = false; }
/** Do not use API without is_secure flag. */
using CacheEntry::matchTag;
using CacheEntry::match;
using CacheEntry::insert;
};