From f415f274141838a168b7d88d21126450d4070ad4 Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Fri, 7 Jun 2019 17:16:39 +0200 Subject: [PATCH] mem-cache: Add function to move blocks in the tags Add a function to allow moving a block's metadata from a source entry to an invalid destination entry. Change-Id: I7c8adbcd1133c907f1eea7f69dca983215bc3960 Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/36576 Reviewed-by: Nikos Nikoleris Maintainer: Nikos Nikoleris Tested-by: kokoro --- src/mem/cache/tags/base.cc | 13 ++++++++ src/mem/cache/tags/base.hh | 10 ++++++ src/mem/cache/tags/base_set_assoc.cc | 12 +++++++ src/mem/cache/tags/base_set_assoc.hh | 2 ++ src/mem/cache/tags/fa_lru.cc | 6 ++++ src/mem/cache/tags/fa_lru.hh | 2 ++ src/mem/cache/tags/sector_tags.cc | 48 ++++++++++++++++++++++++++++ src/mem/cache/tags/sector_tags.hh | 2 ++ 8 files changed, 95 insertions(+) diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc index b00ad4921..edd85a47a 100644 --- a/src/mem/cache/tags/base.cc +++ b/src/mem/cache/tags/base.cc @@ -123,6 +123,19 @@ BaseTags::insertBlock(const PacketPtr pkt, CacheBlk *blk) stats.dataAccesses += 1; } +void +BaseTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) +{ + assert(!dest_blk->isValid()); + assert(src_blk->isValid()); + + // Move src's contents to dest's + *dest_blk = std::move(*src_blk); + + assert(dest_blk->isValid()); + assert(!src_blk->isValid()); +} + Addr BaseTags::extractTag(const Addr addr) const { diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh index deda63ec2..5a407a6b1 100644 --- a/src/mem/cache/tags/base.hh +++ b/src/mem/cache/tags/base.hh @@ -308,6 +308,16 @@ class BaseTags : public ClockedObject */ virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk); + /** + * Move a block's metadata to another location decided by the replacement + * policy. It behaves as a swap, however, since the destination block + * should be invalid, the result is a move. + * + * @param src_blk The source block. + * @param dest_blk The destination block. Must be invalid. + */ + virtual void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk); + /** * Regenerate the block address. * diff --git a/src/mem/cache/tags/base_set_assoc.cc b/src/mem/cache/tags/base_set_assoc.cc index 6507007a7..66635335d 100644 --- a/src/mem/cache/tags/base_set_assoc.cc +++ b/src/mem/cache/tags/base_set_assoc.cc @@ -93,3 +93,15 @@ BaseSetAssoc::invalidate(CacheBlk *blk) // Invalidate replacement data replacementPolicy->invalidate(blk->replacementData); } + +void +BaseSetAssoc::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) +{ + BaseTags::moveBlock(src_blk, dest_blk); + + // Since the blocks were using different replacement data pointers, + // we must touch the replacement data of the new entry, and invalidate + // the one that is being moved. + replacementPolicy->invalidate(src_blk->replacementData); + replacementPolicy->reset(dest_blk->replacementData); +} diff --git a/src/mem/cache/tags/base_set_assoc.hh b/src/mem/cache/tags/base_set_assoc.hh index 787cc6bd0..b13b0078a 100644 --- a/src/mem/cache/tags/base_set_assoc.hh +++ b/src/mem/cache/tags/base_set_assoc.hh @@ -199,6 +199,8 @@ class BaseSetAssoc : public BaseTags replacementPolicy->reset(blk->replacementData); } + void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override; + /** * Limit the allocation for the cache ways. * @param ways The maximum number of ways available for replacement. diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc index 78d601d77..79019fc76 100644 --- a/src/mem/cache/tags/fa_lru.cc +++ b/src/mem/cache/tags/fa_lru.cc @@ -225,6 +225,12 @@ FALRU::insertBlock(const PacketPtr pkt, CacheBlk *blk) tagHash[std::make_pair(blk->getTag(), blk->isSecure())] = falruBlk; } +void +FALRU::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) +{ + panic("Moving blocks in FALRU has not been implemented"); +} + void FALRU::moveToHead(FALRUBlk *blk) { diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index f03ecee58..f24ac0e8c 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -232,6 +232,8 @@ class FALRU : public BaseTags */ void insertBlock(const PacketPtr pkt, CacheBlk *blk) override; + void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override; + /** * Generate the tag from the addres. For fully associative this is just the * block address. diff --git a/src/mem/cache/tags/sector_tags.cc b/src/mem/cache/tags/sector_tags.cc index 8a4b86f90..ff2f4a415 100644 --- a/src/mem/cache/tags/sector_tags.cc +++ b/src/mem/cache/tags/sector_tags.cc @@ -128,6 +128,7 @@ SectorTags::invalidate(CacheBlk *blk) if (!sector_blk->isValid()) { // Decrease the number of tags in use stats.tagsInUse--; + assert(stats.tagsInUse.value() >= 0); // Invalidate replacement data, as we're invalidating the sector replacementPolicy->invalidate(sector_blk->replacementData); @@ -186,6 +187,7 @@ SectorTags::insertBlock(const PacketPtr pkt, CacheBlk *blk) } else { // Increment tag counter stats.tagsInUse++; + assert(stats.tagsInUse.value() <= numSectors); // A new entry resets the replacement data replacementPolicy->reset(sector_blk->replacementData); @@ -195,6 +197,52 @@ SectorTags::insertBlock(const PacketPtr pkt, CacheBlk *blk) BaseTags::insertBlock(pkt, blk); } +void +SectorTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) +{ + const bool dest_was_valid = + static_cast(dest_blk)->getSectorBlock()->isValid(); + + BaseTags::moveBlock(src_blk, dest_blk); + + // Get blocks' sectors. The blocks have effectively been swapped by now, + // so src points to an invalid block, and dest to the moved valid one. + SectorSubBlk* src_sub_blk = static_cast(src_blk); + const SectorBlk* src_sector_blk = src_sub_blk->getSectorBlock(); + SectorSubBlk* dest_sub_blk = static_cast(dest_blk); + const SectorBlk* dest_sector_blk = dest_sub_blk->getSectorBlock(); + + // Since the blocks were using different replacement data pointers, + // we must touch the replacement data of the new entry, and invalidate + // the one that is being moved. + // When a block in a sector is invalidated, it does not make the tag + // invalid automatically, as there might be other blocks in the sector + // using it. The tag is invalidated only when there is a single block + // in the sector. + if (!src_sector_blk->isValid()) { + // Invalidate replacement data, as we're invalidating the sector + replacementPolicy->invalidate(src_sector_blk->replacementData); + + if (dest_was_valid) { + // If destination sector was valid, and the source sector became + // invalid, there is one less tag being used + stats.tagsInUse--; + assert(stats.tagsInUse.value() >= 0); + } + } else if (!dest_was_valid) { + // If destination sector was invalid and became valid, and the source + // sector is still valid, there is one extra tag being used + stats.tagsInUse++; + assert(stats.tagsInUse.value() <= numSectors); + } + + if (dest_was_valid) { + replacementPolicy->touch(dest_sector_blk->replacementData); + } else { + replacementPolicy->reset(dest_sector_blk->replacementData); + } +} + CacheBlk* SectorTags::findBlock(Addr addr, bool is_secure) const { diff --git a/src/mem/cache/tags/sector_tags.hh b/src/mem/cache/tags/sector_tags.hh index c56ef2409..5c228eeea 100644 --- a/src/mem/cache/tags/sector_tags.hh +++ b/src/mem/cache/tags/sector_tags.hh @@ -149,6 +149,8 @@ class SectorTags : public BaseTags */ void insertBlock(const PacketPtr pkt, CacheBlk *blk) override; + void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override; + /** * Finds the given address in the cache, do not update replacement data. * i.e. This is a no-side-effect find of a block. -- 2.30.2