arch-arm: Cache a pointer to previously matched TLB entry (#1752)
One of the perks of the previous TLB storage implementation [1] is that
its custom implementation of LRU exploited temporal locality to speed up
simulation performance
TlbEntry tmp_entry = *entry;
for (int i = idx; i > 0; i--)
table[i] = table[i - 1];
table[0] = tmp_entry;
return &table[0];
In other words the matching entry was placed as the first entry of the
TLB table (table[0], top of LRU stack). In this way a following lookup
would encounter it as the first entry while looping over the TLB table,
therefore massively reducing simulation time when temporal locality is
present
(most of TLB table loops would find a match in the first iteration).
int x = 0;
while (x < size) {
if (table[x].match(lookup_data)) {
With the new implementation we decouple TLB storage from the replacement
policy. The result is a more flexible implementation but with the
drawback of a slower lookup/search. We therefore we need to find another
way to exploit temporal locality. This patch addresses it by caching a
previously matched entry in the TLB table
[1]: https://github.com/gem5/gem5/blob/v24.0.0.0/src/arch/arm/tlb.cc
Change-Id: Id7dedf5411ea6f6724d1e4bdb51635417a6d5363
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
committed by
GitHub
parent
2e998c9fc0
commit
3e628dd1c0
@@ -73,21 +73,31 @@ TLB::Table::accessEntry(const KeyType &key)
|
||||
TlbEntry*
|
||||
TLB::Table::findEntry(const KeyType &key) const
|
||||
{
|
||||
auto candidates = indexingPolicy->getPossibleEntries(key);
|
||||
// Exploiting locality to maximaize simulator performance
|
||||
if (prev && prev->N == key.pageSize && prev->match(key)) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
for (auto candidate : candidates) {
|
||||
for (auto candidate : indexingPolicy->getPossibleEntries(key)) {
|
||||
auto entry = static_cast<TlbEntry*>(candidate);
|
||||
// We check for pageSize match outside of the Entry::match
|
||||
// as the latter is also used to match entries in TLBI invalidation
|
||||
// where we don't care about the pageSize
|
||||
if (entry->N == key.pageSize && entry->match(key)) {
|
||||
return entry;
|
||||
return prev = entry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::Table::invalidatePrev(const TlbEntry *invalid)
|
||||
{
|
||||
if (!invalid || invalid == prev)
|
||||
prev = nullptr;
|
||||
}
|
||||
|
||||
TLB::TLB(const ArmTLBParams &p)
|
||||
: BaseTLB(p),
|
||||
table(name().c_str(), p.size, p.assoc,
|
||||
@@ -239,6 +249,8 @@ TLB::insert(const Lookup &lookup_data, TlbEntry &entry)
|
||||
|
||||
table.insertEntry(lookup_data, victim);
|
||||
|
||||
table.invalidatePrev(victim);
|
||||
|
||||
observedPageSizes.insert(entry.N);
|
||||
stats.inserts++;
|
||||
ppRefills->notify(1);
|
||||
@@ -280,6 +292,8 @@ TLB::flushAll()
|
||||
}
|
||||
}
|
||||
|
||||
table.invalidatePrev();
|
||||
|
||||
stats.flushTlb++;
|
||||
observedPageSizes.clear();
|
||||
}
|
||||
@@ -292,6 +306,9 @@ TLB::flush(const TLBIOp& tlbi_op)
|
||||
if (tlbi_op.match(&te, vmid)) {
|
||||
DPRINTF(TLB, " - %s\n", te.print());
|
||||
table.invalidate(&te);
|
||||
|
||||
table.invalidatePrev(&te);
|
||||
|
||||
stats.flushedEntries++;
|
||||
}
|
||||
valid_entry = valid_entry || te.valid;
|
||||
|
||||
@@ -110,6 +110,21 @@ class TLB : public BaseTLB
|
||||
using AssociativeCache<TlbEntry>::accessEntry;
|
||||
TlbEntry* accessEntry(const KeyType &key) override;
|
||||
TlbEntry* findEntry(const KeyType &key) const override;
|
||||
|
||||
/**
|
||||
* Invalidate the last matched entry
|
||||
* The method has an optional param, which means: invalidate
|
||||
* cached prev only if matches the entry argument. This is
|
||||
* to be used for example on TLB entry invalidations
|
||||
*
|
||||
* @param invalid flush prev if param is nullptr, otherwise
|
||||
* only if prev == invalid
|
||||
*/
|
||||
void invalidatePrev(const TlbEntry *invalid=nullptr);
|
||||
|
||||
private:
|
||||
/** Last matched entry */
|
||||
mutable TlbEntry *prev = nullptr;
|
||||
} table;
|
||||
|
||||
/** TLB Size */
|
||||
|
||||
Reference in New Issue
Block a user