mem-cache: Allow moving data contractions

Data contractions happen when a block passes from a less compressed
(e.g., uncompressed) to a more compressed (e.g., compressed) state.

Some compaction methods enforce that a block can only be allocated
in a location matches an exact compression factor, thus on data
contractions such blocks must be moved to another location, or
they must be padded to fake a bigger size.

For compaction methods that do not have that limitation, performance
can be improved if the contracted block is moved to co-allocate with
another existing entry, since it frees up an entry.

Change-Id: I302bc561b897f9d3ce1426331fe4b5c2df76f4b5
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/36578
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-06-17 17:41:09 +02:00
committed by Daniel Carvalho
parent a2b7f9544c
commit f6d2db4b93
3 changed files with 64 additions and 16 deletions

View File

@@ -105,6 +105,11 @@ class BaseCache(ClockedObject):
compressor = Param.BaseCacheCompressor(NULL, "Cache compressor.")
replace_expansions = Param.Bool(True, "Apply replacement policy to " \
"decide which blocks should be evicted on a data expansion")
# When a block passes from uncompressed to compressed, it may become
# co-allocatable with another existing entry of the same superblock,
# so try move the block to co-allocate it
move_contractions = Param.Bool(True, "Try to co-allocate blocks that "
"contract")
sequential_access = Param.Bool(False,
"Whether to access tags and data sequentially")

61
src/mem/cache/base.cc vendored
View File

@@ -100,6 +100,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size)
clusivity(p.clusivity),
isReadOnly(p.is_read_only),
replaceExpansions(p.replace_expansions),
moveContractions(p.move_contractions),
blocked(0),
order(0),
noTargetMSHR(nullptr),
@@ -862,15 +863,31 @@ BaseCache::updateCompressionData(CacheBlk *&blk, const uint64_t* data,
const bool is_co_allocatable = superblock->isCompressed(compression_blk) &&
superblock->canCoAllocate(compression_size);
// If block was compressed, possibly co-allocated with other blocks, and
// cannot be co-allocated anymore, one or more blocks must be evicted to
// make room for the expanded block
// If compressed size didn't change enough to modify its co-allocatability
// there is nothing to do. Otherwise we may be facing a data expansion
// (block passing from more compressed to less compressed state), or a
// data contraction (less to more).
const bool was_compressed = compression_blk->isCompressed();
bool is_data_expansion = false;
bool is_data_contraction = false;
string op_name = "";
if (was_compressed && !is_co_allocatable) {
is_data_expansion = true;
op_name = "expansion";
} else if (moveContractions && !was_compressed && is_co_allocatable) {
is_data_contraction = true;
op_name = "contraction";
}
// If block changed compression state, it was possibly co-allocated with
// other blocks and cannot be co-allocated anymore, so one or more blocks
// must be evicted to make room for the expanded/contracted block
std::vector<CacheBlk*> evict_blks;
if (is_data_expansion || is_data_contraction) {
std::vector<CacheBlk*> evict_blks;
bool victim_itself = false;
CacheBlk *victim = nullptr;
if (replaceExpansions) {
if (replaceExpansions || is_data_contraction) {
victim = tags->findVictim(regenerateBlkAddr(blk),
blk->isSecure(), compression_size, evict_blks);
@@ -889,8 +906,8 @@ BaseCache::updateCompressionData(CacheBlk *&blk, const uint64_t* data,
}
// Print victim block's information
DPRINTF(CacheRepl, "Data expansion replacement victim: %s\n",
victim->print());
DPRINTF(CacheRepl, "Data %s replacement victim: %s\n",
op_name, victim->print());
} else {
// If we do not move the expanded block, we must make room for
// the expansion to happen, so evict every co-allocated block
@@ -908,12 +925,10 @@ BaseCache::updateCompressionData(CacheBlk *&blk, const uint64_t* data,
return false;
}
// Update the number of data expansions
stats.dataExpansions++;
DPRINTF(CacheComp, "Data expansion: expanding [%s] from %d to %d bits"
"\n", blk->print(), prev_size, compression_size);
DPRINTF(CacheComp, "Data %s: [%s] from %d to %d bits\n",
op_name, blk->print(), prev_size, compression_size);
if (!victim_itself && replaceExpansions) {
if (!victim_itself && (replaceExpansions || is_data_contraction)) {
// Move the block's contents to the invalid block so that it now
// co-allocates with the other existing superblock entry
tags->moveBlock(blk, victim);
@@ -922,15 +937,27 @@ BaseCache::updateCompressionData(CacheBlk *&blk, const uint64_t* data,
}
}
// We always store compressed blocks when possible
if (is_co_allocatable) {
compression_blk->setCompressed();
} else {
compression_blk->setUncompressed();
// Update the number of data expansions/contractions
if (is_data_expansion) {
stats.dataExpansions++;
} else if (is_data_contraction) {
stats.dataContractions++;
}
compression_blk->setSizeBits(compression_size);
compression_blk->setDecompressionLatency(decompression_lat);
if (is_data_expansion || is_data_contraction) {
// If contracting data, for sure data is compressed. If expanding,
// both situations can arise. When no contraction or expansion happens
// block keeps its old state
if (is_co_allocatable) {
compression_blk->setCompressed();
} else {
compression_blk->setUncompressed();
}
}
return true;
}
@@ -2088,6 +2115,7 @@ BaseCache::CacheStats::CacheStats(BaseCache &c)
replacements(this, "replacements", "number of replacements"),
dataExpansions(this, "data_expansions", "number of data expansions"),
dataContractions(this, "data_contractions", "number of data contractions"),
cmd(MemCmd::NUM_MEM_CMDS)
{
for (int idx = 0; idx < MemCmd::NUM_MEM_CMDS; ++idx)
@@ -2307,6 +2335,7 @@ BaseCache::CacheStats::regStats()
}
dataExpansions.flags(nozero | nonan);
dataContractions.flags(nozero | nonan);
}
void

14
src/mem/cache/base.hh vendored
View File

@@ -901,6 +901,14 @@ class BaseCache : public ClockedObject
*/
const bool replaceExpansions;
/**
* Similar to data expansions, after a block improves its compression,
* it may need to be moved elsewhere compatible with the new compression
* factor, or, if not required by the compaction method, it may be moved
* to co-allocate with an existing block and thus free an entry.
*/
const bool moveContractions;
/**
* Bit vector of the blocking reasons for the access path.
* @sa #BlockedCause
@@ -1074,6 +1082,12 @@ class BaseCache : public ClockedObject
/** Number of data expansions. */
Stats::Scalar dataExpansions;
/**
* Number of data contractions (blocks that had their compression
* factor improved).
*/
Stats::Scalar dataContractions;
/** Per-command statistics */
std::vector<std::unique_ptr<CacheCmdStats>> cmd;
} stats;