blob: 9a145fa815132484df1fe2c8a7656c3f72411d5a [file] [log] [blame]
/*
* Copyright (c) 2018 Inria
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Daniel Carvalho
*/
/** @file
* Definition of "Base-Delta-Immediate Compression: Practical Data Compression
* for On-Chip Caches".
*/
#ifndef __MEM_CACHE_COMPRESSORS_BDI_HH__
#define __MEM_CACHE_COMPRESSORS_BDI_HH__
#include <cstdint>
#include <memory>
#include <vector>
#include "base/types.hh"
#include "mem/cache/compressors/base.hh"
struct BDIParams;
/**
* Default maximum number of bases in the original BDI.
*/
#define BDI_DEFAULT_MAX_NUM_BASES 2
class BDI : public BaseCacheCompressor
{
protected:
/**
* Forward declaration of comp data classes.
*/
class BDICompData;
class BDICompDataZeros;
class BDICompDataRep;
class BDICompDataUncompressed;
template <class TB, class TD> class BDICompDataBaseDelta;
/**
* The possible encoding values. If modified, ENCODING_NAMES must be too.
*/
enum ENCODING {ZERO, REP_VALUES, BASE8_1, BASE8_2, BASE8_4, BASE4_1,
BASE4_2, BASE2_1, UNCOMPRESSED, NUM_ENCODINGS};
/**
* The respective encoding names. They are indexed by the ENCODING enum.
* The values are assigned in the source file, and should be modified if
* ENCODING is changed.
*/
static const char* ENCODING_NAMES[];
/**
* If set, create multiple compressor instances for each possible
* combination of base and delta size. Otherwise, just create a
* compressor for each base size with the highest available delta
* size. This can be used to save area and power (having less
* compressors). True by default.
*/
const bool useMoreCompressors;
/**
* Number of qwords in a cache line.
*/
const std::size_t qwordsPerCacheLine;
/**
* @defgroup CompressionStats Compression specific statistics.
* @{
*/
/**
* Number of data entries that were compressed to each encoding.
*/
Stats::Vector encodingStats;
/**
* @}
*/
/**
* Check if the cache line consists of only zero values.
*
* @param data The cache line.
* @return True if it is a ZERO cache line.
*/
bool isZeroPackable(const uint64_t* data) const;
/**
* Check if the cache line consists only of same values.
*
* @param data The cache line.
* @return True if it is a REP_VALUES cache line.
*/
bool isSameValuePackable(const uint64_t* data) const;
/**
* Instantiate a BaseDelta compressor with given TB and TD, and try to
* compress the cache line. If the compression fails, it returns a nullptr.
* @sa BDICompDataBaseDelta
*
* @tparam TB Type of a base entry.
* @tparam TD Type of a delta entry.
* @param data The cache line to be compressed.
* @param encoding Encoding value for given TB-TD combination.
* @return Cache line after compression or nullptr.
*/
template <class TB, class TD>
std::unique_ptr<BDICompData> tryCompress(const uint64_t* data,
const uint8_t encoding) const;
/**
* Apply compression.
*
* @param data The cache line to be compressed.
* @param comp_lat Compression latency in number of cycles.
* @param decomp_lat Decompression latency in number of cycles.
* @param comp_size Compressed data size.
*/
std::unique_ptr<BaseCacheCompressor::CompressionData> compress(
const uint64_t* data, Cycles& comp_lat, Cycles& decomp_lat) override;
/**
* Decompress data.
*
* @param comp_data Compressed cache line.
* @param data The cache line to be decompressed.
* @return Decompression latency in number of cycles.
*/
void decompress(const BaseCacheCompressor::CompressionData* comp_data,
uint64_t* data) override;
public:
/** Convenience typedef. */
typedef BDIParams Params;
/**
* Default constructor.
*/
BDI(const Params *p);
/**
* Default destructor.
*/
~BDI() = default;
/**
* Register local statistics.
*/
void regStats() override;
};
/**
* Template for the BDI compression data.
*/
class BDI::BDICompData : public CompressionData
{
private:
/**
* Data encoding.
* @sa BDI
*/
const uint8_t _encoding;
protected:
/**
* Number of bits needed for the encoding field.
*/
static const std::size_t encodingBits = 4;
/**
* Calculate and set compressed data size.
* Each BDI compressor generates compressed data with different sizes.
*/
virtual void calculateCompressedSize() = 0;
public:
/**
* Default constructor.
*
* @param encoding The encoding value.
*/
BDICompData(const uint8_t encoding);
/**
* Default destructor.
*/
virtual ~BDICompData() = default;
/**
* Get and decompress data at given index.
*
* The index is given relative to 64-bit entries, therefore if the base
* size of the given compressed data is smaller than that, this function
* joins multiple base-delta entries to generate the respective 64-bit
* entry.
*
* @param index The index of the compressed data.
* @return Decompressed data for the given index.
*/
virtual uint64_t access(const int index) const = 0;
/**
* Get encoding.
*
* @return The encoding.
*/
uint8_t getEncoding() const;
/**
* Get encoding name.
*
* @return The encoding name.
*/
std::string getName() const;
};
/**
* BDI compressed data containing the ZERO encoding.
*/
class BDI::BDICompDataZeros : public BDICompData
{
protected:
/**
* Calculate compressed data size using ZERO encoding.
*/
void calculateCompressedSize() override;
public:
/**
* Default constructor.
*/
BDICompDataZeros();
/**
* Get and decompress data at given index. Must always return 0.
*
* @param index The index of the compressed data.
* @return Decompressed data for the given index.
*/
uint64_t access(const int index) const override;
};
/**
* BDI compressed data containing the REP_VALUES encoding.
*/
class BDI::BDICompDataRep : public BDICompData
{
private:
/**
* The repeated value.
*/
uint64_t base;
protected:
/**
* Calculate compressed data size using REP_VALUES encoding.
*/
void calculateCompressedSize() override;
public:
/**
* Default constructor.
*
* @param rep_value The repeated value.
*/
BDICompDataRep(const uint64_t rep_value);
/**
* Get and decompress data at given index. Must always return the same
* value as data[0].
*
* @param index The index of the compressed data.
* @return Decompressed data for the given index.
*/
uint64_t access(const int index) const override;
};
/**
* BDI compressed data containing the UNCOMPRESSED encoding.
*/
class BDI::BDICompDataUncompressed : public BDICompData
{
private:
/**
* Uncompressed cache line size (in bytes).
*/
const std::size_t blkSize;
/**
* The compressed data is the original cache line.
*/
const std::vector<uint64_t> _data;
protected:
/**
* Calculate compressed data size using UNCOMPRESSED encoding.
*/
void calculateCompressedSize() override;
public:
/**
* Default constructor.
*
* @param data The data on which compression was applied.
* @param blk_size Size of a cache line in bytes.
*/
BDICompDataUncompressed(const uint64_t* data,
const std::size_t blk_size);
/**
* Get and decompress data at given index. Must return the same
* value as _data[index].
*
* @param index The index of the compressed data.
* @return Decompressed data for the given index.
*/
uint64_t access(const int index) const override;
};
/**
* Template class for BDI compressed data containing all the BASE_DELTA
* encodings. TB's size must always be greater than TD's.
*
* @tparam TB Type of a base entry.
* @tparam TD Type of a delta entry.
*/
template <class TB, class TD>
class BDI::BDICompDataBaseDelta : public BDICompData
{
protected:
/**
* Maximum number of bases.
*/
const std::size_t maxNumBases;
/**
* Bit mask to differentiate between the bases.
*/
std::vector<uint8_t> bitMask;
/**
* Bases. bases[0] is 0 and is not stored in a hardware implementation.
*/
std::vector<TB> bases;
/**
* Array of deltas (or immediate values).
*/
std::vector<TD> deltas;
/**
* Add a base to the bases vector.
*
* @param base The base to be added.
* @return True on success, false if already used all base slots.
*/
bool addBase(const TB base);
/**
* Add a delta to the deltas vector.
*
* @param base_index Base to which the delta refers.
* @param delta The delta value.
*/
void addDelta(const std::size_t base_index, const TD delta);
/**
* Calculate compressed data size using number of bases, the base size and
* the delta size.
*/
void calculateCompressedSize() override;
public:
/**
* Default constructor.
*
* @param encoding The encoding value for this compressor.
* @param blk_size Size of a cache line in bytes.
* @param max_num_bases Maximum number of bases allowed to be stored.
*/
BDICompDataBaseDelta(const uint8_t encoding, const std::size_t blk_size,
const std::size_t max_num_bases = BDI_DEFAULT_MAX_NUM_BASES);
/**
* Get and decompress data at given index.
*
* @param index The index of the compressed data.
* @return Decompressed data for the given index.
*/
uint64_t access(const int index) const override;
/**
* Apply base delta compression.
*
* @param data The data on which compression was applied.
* @param blk_size Size of a cache line in bytes.
* @return True on success.
*/
bool compress(const uint64_t* data, const std::size_t blk_size);
};
#endif //__MEM_CACHE_COMPRESSORS_BDI_HH__