38#include "debug/CacheComp.hh"
40#include "params/FrequentValuesCompressor.hh"
49 :
Base(
p), useHuffmanEncoding(
p.max_code_length != 0),
50 indexEncoder(
p.max_code_length), counterBits(
p.counter_bits),
51 codeGenerationTicks(
p.code_generation_ticks),
52 checkSaturation(
p.check_saturation), numVFTEntries(
p.vft_entries),
53 numSamples(
p.num_samples), takenSamples(0), phase(SAMPLING),
54 VFT((
name() +
".VFT").c_str(),
55 p.vft_entries,
p.vft_assoc,
p.vft_replacement_policy,
56 p.vft_indexing_policy,
VFTEntry(counterBits)),
60 "There are more VFT entries than possible values.");
63std::unique_ptr<Base::CompressionData>
67 std::unique_ptr<CompData> comp_data =
68 std::unique_ptr<CompData>(
new CompData());
75 for (
const auto& chunk : chunks) {
85 const unsigned index = entry ? chunk : uncompressed_index;
91 if (
index == uncompressed_index) {
93 }
else if (code.
length > 64) {
103 code = {
index, code_size};
114 DPRINTF(CacheComp,
"Compressed %016x to %016x (Size = %d) "
115 "(Phase: %d)\n", chunk, code.
code, length,
phase);
117 comp_data->compressedValues.emplace_back(code, chunk);
123 comp_data->setSizeBits(size);
155 assert(((code.
length <= 64) &&
156 (code.
code == comp_chunk.code.code)) ||
157 (comp_chunk.code.code ==
163 VFT.findEntry(comp_chunk.value));
167 decomp_chunks.push_back(comp_chunk.value);
168 DPRINTF(CacheComp,
"Decompressed %016x to %016x\n",
169 comp_chunk.code.code, comp_chunk.value);
178 bool is_invalidation)
181 for (
const Chunk& chunk : chunks) {
183 bool saturated =
false;
184 if (!is_invalidation) {
188 entry =
VFT.findVictim(chunk);
189 assert(entry !=
nullptr);
190 entry->
value = chunk;
191 VFT.insertEntry(chunk, entry);
193 VFT.accessEntry(entry);
200 VFT.accessEntry(entry);
208 for (
auto& entry :
VFT) {
223 std::set<uint64_t> uncompressed_values;
225 uncompressed_values.insert(uncompressed_values.end(),
i);
228 for (
const auto& entry :
VFT) {
231 uncompressed_values.erase(entry.value);
236 assert(uncompressed_values.size() >= 1);
244 for (
const auto& entry :
VFT) {
271 if (data_update.
oldData.size() > 0) {
276 if (data_update.
newData.size() > 0) {
292 assert(
cache !=
nullptr);
Cycles is a wrapper class for representing cycle counts, i.e.
Base cache compressor interface.
const Cycles compExtraLatency
Extra latency added to compression due to packaging, shifting or other operations.
void fromChunks(const std::vector< Chunk > &chunks, uint64_t *data) const
This function re-joins the chunks to recreate the original data.
BaseCache * cache
Pointer to the parent cache.
std::vector< Chunk > toChunks(const uint64_t *data) const
This function splits the raw data into chunks, so that it can be parsed by the compressor.
const Cycles decompExtraLatency
Extra latency added to decompression due to packaging, shifting or other operations.
const Cycles compChunksPerCycle
Degree of parallelization of the compression process.
uint64_t Chunk
A chunk is a basic lexical unit.
const unsigned chunkSizeBits
Chunk size, in number of bits.
const Cycles decompChunksPerCycle
Degree of parallelization of the decompression process.
std::vector< CompressedValue > compressedValues
The values contained in the original data, after being compressed sequentially.
void notify(const DataUpdate &data_update) override
SatCounter32 counter
The ideal counter width (in bits) is determined by the maximum number of times a given value appears ...
uint64_t value
The value is stored as a 64 bit entry to accomodate for the uncompressed value.
std::vector< FrequentValuesListener * > listeners
FrequentValuesCompressorParams Params
void decompress(const CompressionData *comp_data, uint64_t *data) override
Apply the decompression process to the compressed data.
void regProbeListeners() override
Register probe listeners for this object.
void sampleValues(const std::vector< uint64_t > &data, bool is_invalidation)
Sample values from a packet, adding them to the VFT.
std::unique_ptr< Base::CompressionData > compress(const std::vector< Chunk > &chunks, Cycles &comp_lat, Cycles &decomp_lat) override
Apply the compression process to the cache line.
unsigned takenSamples
Number of samples taken so far.
AssociativeCache< VFTEntry > VFT
The Value Frequency Table, a small cache that keeps track and estimates the frequency distribution of...
void probeNotify(const DataUpdate &data_update)
Process a notification event from the ProbeListener.
FrequentValues(const Params &p)
const unsigned numVFTEntries
Maximum number of VFT entries, and thus of codewords too.
const Tick codeGenerationTicks
Ticks needed to perform the CODE_GENERATION phase.
const bool checkSaturation
Whether an action must be performed when counters saturate.
void generateCodes()
End sampling phase and start the code generation.
const unsigned numSamples
Number of samples in the sampling phase.
encoder::Huffman indexEncoder
The encoder applied to the VFT indices.
const bool useHuffmanEncoding
Whether Huffman encoding is applied to the VFT indices.
uint64_t uncompressedValue
A pseudo value is used as the representation of uncompressed values.
EventFunctionWrapper codeGenerationEvent
Event to handle finishing code generation and starting compression.
void sample(uint64_t value, uint64_t frequency)
Inserts the value-frequency pair in the tree.
Code encode(const uint64_t val) const override
The function responsible for the generation of the alternative value.
void generateCodeMaps()
Generation of the code maps.
void schedule(Event &event, Tick when)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
bool isSaturated() const
Whether the counter has achieved its maximum value or not.
ProbeManager * getProbeManager()
Get the probe manager for this object.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
A data contents update is composed of the updated block's address, the old contents,...
std::vector< uint64_t > newData
The new data contents.
std::vector< uint64_t > oldData
The stale data contents.
unsigned length
Number of bits in the code.
uint64_t code
Only the LSB of the code are relevant.
const std::string & name()