*/
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.
*
// 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);
+}
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);
} else {
// Increment tag counter
stats.tagsInUse++;
+ assert(stats.tagsInUse.value() <= numSectors);
// A new entry resets the replacement data
replacementPolicy->reset(sector_blk->replacementData);
BaseTags::insertBlock(pkt, blk);
}
+void
+SectorTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
+{
+ const bool dest_was_valid =
+ static_cast<SectorSubBlk*>(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<SectorSubBlk*>(src_blk);
+ const SectorBlk* src_sector_blk = src_sub_blk->getSectorBlock();
+ SectorSubBlk* dest_sub_blk = static_cast<SectorSubBlk*>(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
{