| /* | |
| * 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__ |