diff options
author | Daniel R. Carvalho <odanrc@yahoo.com.br> | 2019-09-05 17:39:38 +0200 |
---|---|---|
committer | Daniel Carvalho <odanrc@yahoo.com.br> | 2019-10-29 21:32:02 +0000 |
commit | 7a8debf0fa391a5e34fd1f47a4d1ae7ad6e3028d (patch) | |
tree | 2c17f2565bb8bd1114e9362265c5c3461d67020e /src/mem/cache/compressors | |
parent | 7ce9fe0af9f04a6f94bec9542af025a043c46b35 (diff) | |
download | gem5-7a8debf0fa391a5e34fd1f47a4d1ae7ad6e3028d.tar.xz |
mem-cache: Templatize DictionaryCompressor
Templatize DictionaryCompressor so that the dictionary entries' sizes
can be changed.
Change-Id: I3d89e3c692a721cefcd7e3c55d2ccdefa425f614
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21148
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Diffstat (limited to 'src/mem/cache/compressors')
-rw-r--r-- | src/mem/cache/compressors/Compressors.py | 18 | ||||
-rw-r--r-- | src/mem/cache/compressors/SConscript | 2 | ||||
-rw-r--r-- | src/mem/cache/compressors/base_dictionary_compressor.cc | 61 | ||||
-rw-r--r-- | src/mem/cache/compressors/cpack.cc | 7 | ||||
-rw-r--r-- | src/mem/cache/compressors/cpack.hh | 85 | ||||
-rw-r--r-- | src/mem/cache/compressors/dictionary_compressor.hh | 168 | ||||
-rw-r--r-- | src/mem/cache/compressors/dictionary_compressor_impl.hh (renamed from src/mem/cache/compressors/dictionary_compressor.cc) | 158 |
7 files changed, 295 insertions, 204 deletions
diff --git a/src/mem/cache/compressors/Compressors.py b/src/mem/cache/compressors/Compressors.py index b6315ad8d..4ed72190c 100644 --- a/src/mem/cache/compressors/Compressors.py +++ b/src/mem/cache/compressors/Compressors.py @@ -40,6 +40,14 @@ class BaseCacheCompressor(SimObject): "in bytes, in which a block must be compressed to. Otherwise it is " "stored in its uncompressed state") +class BaseDictionaryCompressor(BaseCacheCompressor): + type = 'BaseDictionaryCompressor' + abstract = True + cxx_header = "mem/cache/compressors/dictionary_compressor.hh" + + dictionary_size = Param.Int(Parent.cache_line_size, + "Number of dictionary entries") + class BDI(BaseCacheCompressor): type = 'BDI' cxx_class = 'BDI' @@ -49,15 +57,7 @@ class BDI(BaseCacheCompressor): "combinations of base and delta for the compressors. False if using" \ "only the lowest possible delta size for each base size."); -class DictionaryCompressor(BaseCacheCompressor): - type = 'DictionaryCompressor' - abstract = True - cxx_header = "mem/cache/compressors/dictionary_compressor.hh" - - dictionary_size = Param.Int(Parent.cache_line_size, - "Number of dictionary entries") - -class CPack(DictionaryCompressor): +class CPack(BaseDictionaryCompressor): type = 'CPack' cxx_class = 'CPack' cxx_header = "mem/cache/compressors/cpack.hh" diff --git a/src/mem/cache/compressors/SConscript b/src/mem/cache/compressors/SConscript index 68cf7ef10..052dbe04f 100644 --- a/src/mem/cache/compressors/SConscript +++ b/src/mem/cache/compressors/SConscript @@ -33,6 +33,6 @@ Import('*') SimObject('Compressors.py') Source('base.cc') +Source('base_dictionary_compressor.cc') Source('bdi.cc') Source('cpack.cc') -Source('dictionary_compressor.cc') diff --git a/src/mem/cache/compressors/base_dictionary_compressor.cc b/src/mem/cache/compressors/base_dictionary_compressor.cc new file mode 100644 index 000000000..e41d87599 --- /dev/null +++ b/src/mem/cache/compressors/base_dictionary_compressor.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018-2019 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 + * Implementation of a base sim object for the templated dictionary-based + * cache compressor. + */ + +#include "mem/cache/compressors/dictionary_compressor.hh" +#include "params/BaseDictionaryCompressor.hh" + +BaseDictionaryCompressor::BaseDictionaryCompressor(const Params *p) + : BaseCacheCompressor(p), dictionarySize(p->dictionary_size), numEntries(0) +{ +} + +void +BaseDictionaryCompressor::regStats() +{ + BaseCacheCompressor::regStats(); + + // We store the frequency of each pattern + patternStats + .init(getNumPatterns()) + .name(name() + ".pattern") + .desc("Number of data entries that were compressed to this pattern.") + ; + + for (unsigned i = 0; i < getNumPatterns(); ++i) { + patternStats.subname(i, getName(i)); + patternStats.subdesc(i, "Number of data entries that match pattern " + + getName(i)); + } +} diff --git a/src/mem/cache/compressors/cpack.cc b/src/mem/cache/compressors/cpack.cc index 9e0cc2d42..5603b0bf6 100644 --- a/src/mem/cache/compressors/cpack.cc +++ b/src/mem/cache/compressors/cpack.cc @@ -34,15 +34,16 @@ #include "mem/cache/compressors/cpack.hh" +#include "mem/cache/compressors/dictionary_compressor_impl.hh" #include "params/CPack.hh" CPack::CPack(const Params *p) - : DictionaryCompressor(p) + : DictionaryCompressor<uint32_t>(p) { } void -CPack::addToDictionary(std::array<uint8_t, 4> data) +CPack::addToDictionary(DictionaryEntry data) { assert(numEntries < dictionarySize); dictionary[numEntries++] = data; @@ -52,7 +53,7 @@ std::unique_ptr<BaseCacheCompressor::CompressionData> CPack::compress(const uint64_t* data, Cycles& comp_lat, Cycles& decomp_lat) { std::unique_ptr<BaseCacheCompressor::CompressionData> comp_data = - DictionaryCompressor::compress(data); + DictionaryCompressor<uint32_t>::compress(data); // Set compression latency (Accounts for pattern matching, length // generation, packaging and shifting) diff --git a/src/mem/cache/compressors/cpack.hh b/src/mem/cache/compressors/cpack.hh index bd258b372..75a091c27 100644 --- a/src/mem/cache/compressors/cpack.hh +++ b/src/mem/cache/compressors/cpack.hh @@ -36,7 +36,6 @@ #ifndef __MEM_CACHE_COMPRESSORS_CPACK_HH__ #define __MEM_CACHE_COMPRESSORS_CPACK_HH__ -#include <array> #include <cstdint> #include <map> #include <memory> @@ -46,9 +45,11 @@ struct CPackParams; -class CPack : public DictionaryCompressor +class CPack : public DictionaryCompressor<uint32_t> { private: + using DictionaryEntry = DictionaryCompressor<uint32_t>::DictionaryEntry; + // Forward declaration of all possible patterns class PatternZZZZ; class PatternXXXX; @@ -88,14 +89,14 @@ class CPack : public DictionaryCompressor }; std::unique_ptr<Pattern> getPattern( - const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, + const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, const int match_location) const override { return PatternFactory::getPattern(bytes, dict_bytes, match_location); } - void addToDictionary(std::array<uint8_t, 4> data) override; + void addToDictionary(DictionaryEntry data) override; /** * Apply compression. @@ -126,19 +127,19 @@ class CPack : public DictionaryCompressor class CPack::PatternZZZZ : public DictionaryCompressor::Pattern { public: - PatternZZZZ(const std::array<uint8_t, 4> bytes, const int match_location) + PatternZZZZ(const DictionaryEntry bytes, const int match_location) : Pattern(ZZZZ, 0x0, 2, 0, 0, false) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { return (bytes[3] == 0) && (bytes[2] == 0) && (bytes[1] == 0) && (bytes[0] == 0); } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return {0, 0, 0, 0}; } @@ -150,23 +151,23 @@ class CPack::PatternXXXX : public DictionaryCompressor::Pattern /** * A copy of the word. */ - const std::array<uint8_t, 4> bytes; + const DictionaryEntry bytes; public: - PatternXXXX(const std::array<uint8_t, 4> bytes, const int match_location) + PatternXXXX(const DictionaryEntry bytes, const int match_location) : Pattern(XXXX, 0x1, 2, 4, 0, true), bytes(bytes) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { // It can always be an unmatch, as it is set to this class when other // patterns fail return true; } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return bytes; } @@ -175,18 +176,18 @@ class CPack::PatternXXXX : public DictionaryCompressor::Pattern class CPack::PatternMMMM : public DictionaryCompressor::Pattern { public: - PatternMMMM(const std::array<uint8_t, 4> bytes, const int match_location) + PatternMMMM(const DictionaryEntry bytes, const int match_location) : Pattern(MMMM, 0x2, 6, 0, match_location, true) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { return (bytes == dict_bytes) && (match_location >= 0); } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return dict_bytes; } @@ -202,13 +203,13 @@ class CPack::PatternMMXX : public DictionaryCompressor::Pattern const uint8_t byte1; public: - PatternMMXX(const std::array<uint8_t, 4> bytes, const int match_location) + PatternMMXX(const DictionaryEntry bytes, const int match_location) : Pattern(MMXX, 0xC, 8, 2, match_location, true), byte0(bytes[0]), byte1(bytes[1]) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { // Notice we don't compare bytes[0], as otherwise we'd be unnecessarily // discarding MMXM. If that pattern is added this should be modified @@ -217,8 +218,8 @@ class CPack::PatternMMXX : public DictionaryCompressor::Pattern } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return {byte0, byte1, dict_bytes[2], dict_bytes[3]}; } @@ -233,19 +234,19 @@ class CPack::PatternZZZX : public DictionaryCompressor::Pattern const uint8_t byte; public: - PatternZZZX(const std::array<uint8_t, 4> bytes, const int match_location) + PatternZZZX(const DictionaryEntry bytes, const int match_location) : Pattern(ZZZX, 0xD, 4, 1, 0, false), byte(bytes[0]) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { return (bytes[3] == 0) && (bytes[2] == 0) && (bytes[1] == 0) && (bytes[0] != 0); } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return {byte, 0, 0, 0}; } @@ -260,21 +261,21 @@ class CPack::PatternMMMX : public DictionaryCompressor::Pattern const uint8_t byte; public: - PatternMMMX(const std::array<uint8_t, 4> bytes, const int match_location) + PatternMMMX(const DictionaryEntry bytes, const int match_location) : Pattern(MMMX, 0xE, 8, 1, match_location, true), byte(bytes[0]) {} - static bool isPattern(const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, - const int match_location) + static bool isPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, + const int match_location) { return (bytes[3] == dict_bytes[3]) && (bytes[2] == dict_bytes[2]) && (bytes[1] == dict_bytes[1]) && (bytes[0] != dict_bytes[0]) && (match_location >= 0); } - std::array<uint8_t, 4> - decompress(const std::array<uint8_t, 4> dict_bytes) const override + DictionaryEntry + decompress(const DictionaryEntry dict_bytes) const override { return {byte, dict_bytes[1], dict_bytes[2], dict_bytes[3]}; } diff --git a/src/mem/cache/compressors/dictionary_compressor.hh b/src/mem/cache/compressors/dictionary_compressor.hh index 87e69ccc8..7467d5a17 100644 --- a/src/mem/cache/compressors/dictionary_compressor.hh +++ b/src/mem/cache/compressors/dictionary_compressor.hh @@ -55,9 +55,60 @@ #include "base/types.hh" #include "mem/cache/compressors/base.hh" -struct DictionaryCompressorParams; +struct BaseDictionaryCompressorParams; -class DictionaryCompressor : public BaseCacheCompressor +class BaseDictionaryCompressor : public BaseCacheCompressor +{ + protected: + /** Dictionary size. */ + const std::size_t dictionarySize; + + /** Number of valid entries in the dictionary. */ + std::size_t numEntries; + + /** + * @defgroup CompressionStats Compression specific statistics. + * @{ + */ + + /** Number of data entries that were compressed to each pattern. */ + Stats::Vector patternStats; + + /** + * @} + */ + + /** + * Trick function to get the number of patterns. + * + * @return The number of defined patterns. + */ + virtual uint64_t getNumPatterns() const = 0; + + /** + * Get meta-name assigned to the given pattern. + * + * @param number The number of the pattern. + * @return The meta-name of the pattern. + */ + virtual std::string getName(int number) const = 0; + + public: + typedef BaseDictionaryCompressorParams Params; + BaseDictionaryCompressor(const Params *p); + ~BaseDictionaryCompressor() = default; + + void regStats() override; +}; + +/** + * A template version of the dictionary compressor that allows to choose the + * dictionary size. + * + * @tparam The type of a dictionary entry (e.g., uint16_t, uint32_t, etc). + */ +template <class T> +class DictionaryCompressor : public BaseDictionaryCompressor { protected: /** @@ -69,6 +120,9 @@ class DictionaryCompressor : public BaseCacheCompressor // Forward declaration of a pattern class Pattern; + /** Convenience typedef for a dictionary entry. */ + typedef std::array<uint8_t, sizeof(T)> DictionaryEntry; + /** * Create a factory to determine if input matches a pattern. The if else * chains are constructed by recursion. The patterns should be explored @@ -78,8 +132,8 @@ class DictionaryCompressor : public BaseCacheCompressor struct Factory { static std::unique_ptr<Pattern> getPattern( - const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, const int match_location) + const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes, + const int match_location) { // If match this pattern, instantiate it. If a negative match // location is used, the patterns that use the dictionary bytes @@ -100,9 +154,9 @@ class DictionaryCompressor : public BaseCacheCompressor template <class Head> struct Factory<Head> { - static std::unique_ptr<Pattern> getPattern( - const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, const int match_location) + static std::unique_ptr<Pattern> + getPattern(const DictionaryEntry& bytes, + const DictionaryEntry& dict_bytes, const int match_location) { // Instantiate last pattern. Should be the XXXX pattern. return std::unique_ptr<Pattern>(new Head(bytes, match_location)); @@ -110,51 +164,15 @@ class DictionaryCompressor : public BaseCacheCompressor }; /** The dictionary. */ - std::vector<std::array<uint8_t, 4>> dictionary; - - /** Dictionary size. */ - const std::size_t dictionarySize; - - /** Number of valid entries in the dictionary. */ - std::size_t numEntries; - - /** - * @defgroup CompressionStats Compression specific statistics. - * @{ - */ - - /** - * Number of data entries that were compressed to each pattern. - */ - Stats::Vector patternStats; - - /** - * @} - */ - - /** - * Trick function to get the number of patterns. - * - * @return The number of defined patterns. - */ - virtual uint64_t getNumPatterns() const = 0; - - /** - * Get meta-name assigned to the given pattern. - * - * @param number The number of the pattern. - * @return The meta-name of the pattern. - */ - virtual std::string getName(int number) const = 0; + std::vector<DictionaryEntry> dictionary; /** * Since the factory cannot be instantiated here, classes that inherit * from this base class have to implement the call to their factory's * getPattern. */ - virtual std::unique_ptr<Pattern> getPattern( - const std::array<uint8_t, 4>& bytes, - const std::array<uint8_t, 4>& dict_bytes, + virtual std::unique_ptr<Pattern> + getPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes, const int match_location) const = 0; /** @@ -163,15 +181,15 @@ class DictionaryCompressor : public BaseCacheCompressor * @param data Data to be compressed. * @return The pattern this data matches. */ - std::unique_ptr<Pattern> compressWord(const uint32_t data); + std::unique_ptr<Pattern> compressValue(const T data); /** - * Decompress a word. + * Decompress a pattern into a value that fits in a dictionary entry. * * @param pattern The pattern to be decompressed. * @return The decompressed word. */ - uint32_t decompressWord(const Pattern* pattern); + T decompressValue(const Pattern* pattern); /** Clear all dictionary entries. */ void resetDictionary(); @@ -181,7 +199,7 @@ class DictionaryCompressor : public BaseCacheCompressor * * @param data The new entry. */ - virtual void addToDictionary(std::array<uint8_t, 4> data) = 0; + virtual void addToDictionary(const DictionaryEntry data) = 0; /** * Apply compression. @@ -200,18 +218,26 @@ class DictionaryCompressor : public BaseCacheCompressor */ void decompress(const CompressionData* comp_data, uint64_t* data) override; - public: - /** Convenience typedef. */ - typedef DictionaryCompressorParams Params; - - /** Default constructor. */ - DictionaryCompressor(const Params *p); + /** + * Turn a value into a dictionary entry. + * + * @param value The value to turn. + * @return A dictionary entry containing the value. + */ + static DictionaryEntry toDictionaryEntry(T value); - /** Default destructor. */ - ~DictionaryCompressor() {}; + /** + * Turn a dictionary entry into a value. + * + * @param The dictionary entry to turn. + * @return The value that the dictionary entry contained. + */ + static T fromDictionaryEntry(const DictionaryEntry& entry); - /** Register local statistics. */ - void regStats() override; + public: + typedef BaseDictionaryCompressorParams Params; + DictionaryCompressor(const Params *p); + ~DictionaryCompressor() = default; }; /** @@ -220,7 +246,8 @@ class DictionaryCompressor : public BaseCacheCompressor * decompress(). Then the new pattern must be added to the PatternFactory * declaration in crescent order of size (in the DictionaryCompressor class). */ -class DictionaryCompressor::Pattern +template <class T> +class DictionaryCompressor<T>::Pattern { protected: /** Pattern enum number. */ @@ -322,25 +349,26 @@ class DictionaryCompressor::Pattern * @param dict_bytes The bytes in the corresponding matching entry. * @return The decompressed pattern. */ - virtual std::array<uint8_t, 4> decompress( - const std::array<uint8_t, 4> dict_bytes) const = 0; + virtual DictionaryEntry decompress( + const DictionaryEntry dict_bytes) const = 0; }; -class DictionaryCompressor::CompData : public CompressionData +template <class T> +class DictionaryCompressor<T>::CompData : public CompressionData { public: /** The patterns matched in the original line. */ std::vector<std::unique_ptr<Pattern>> entries; + CompData(); + ~CompData() = default; + /** - * Default constructor. + * Add a pattern entry to the list of patterns. * - * @param dictionary_size Number of entries in the dictionary. + * @param entry The new pattern entry. */ - CompData(const std::size_t dictionary_size); - - /** Default destructor. */ - ~CompData(); + virtual void addEntry(std::unique_ptr<Pattern>); }; #endif //__MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__ diff --git a/src/mem/cache/compressors/dictionary_compressor.cc b/src/mem/cache/compressors/dictionary_compressor_impl.hh index c53d14a9b..66827d774 100644 --- a/src/mem/cache/compressors/dictionary_compressor.cc +++ b/src/mem/cache/compressors/dictionary_compressor_impl.hh @@ -32,55 +32,63 @@ * Implementation of a dictionary based cache compressor. */ -#include "mem/cache/compressors/dictionary_compressor.hh" +#ifndef __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_IMPL_HH__ +#define __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_IMPL_HH__ #include <algorithm> #include "debug/CacheComp.hh" -#include "params/DictionaryCompressor.hh" +#include "mem/cache/compressors/dictionary_compressor.hh" +#include "params/BaseDictionaryCompressor.hh" -DictionaryCompressor::CompData::CompData(const std::size_t dictionary_size) +template <class T> +DictionaryCompressor<T>::CompData::CompData() : CompressionData() { } -DictionaryCompressor::CompData::~CompData() +template <class T> +void +DictionaryCompressor<T>::CompData::addEntry(std::unique_ptr<Pattern> pattern) { + // Increase size + setSizeBits(getSizeBits() + pattern->getSizeBits()); + + // Push new entry to list + entries.push_back(std::move(pattern)); } -DictionaryCompressor::DictionaryCompressor(const Params *p) - : BaseCacheCompressor(p), dictionarySize(p->dictionary_size) +template <class T> +DictionaryCompressor<T>::DictionaryCompressor(const Params *p) + : BaseDictionaryCompressor(p) { dictionary.resize(dictionarySize); resetDictionary(); } +template <class T> void -DictionaryCompressor::resetDictionary() +DictionaryCompressor<T>::resetDictionary() { // Reset number of valid entries numEntries = 0; // Set all entries as 0 - std::array<uint8_t, 4> zero_word = {0, 0, 0, 0}; - std::fill(dictionary.begin(), dictionary.end(), zero_word); + std::fill(dictionary.begin(), dictionary.end(), toDictionaryEntry(0)); } -std::unique_ptr<DictionaryCompressor::Pattern> -DictionaryCompressor::compressWord(const uint32_t data) +template <typename T> +std::unique_ptr<typename DictionaryCompressor<T>::Pattern> +DictionaryCompressor<T>::compressValue(const T data) { // Split data in bytes - const std::array<uint8_t, 4> bytes = { - static_cast<uint8_t>(data & 0xFF), - static_cast<uint8_t>((data >> 8) & 0xFF), - static_cast<uint8_t>((data >> 16) & 0xFF), - static_cast<uint8_t>((data >> 24) & 0xFF) - }; + const DictionaryEntry bytes = toDictionaryEntry(data); // Start as a no-match pattern. A negative match location is used so that // patterns that depend on the dictionary entry don't match - std::unique_ptr<Pattern> pattern = getPattern(bytes, {0, 0, 0, 0}, -1); + std::unique_ptr<Pattern> pattern = + getPattern(bytes, toDictionaryEntry(0), -1); // Search for word on dictionary for (std::size_t i = 0; i < numEntries; i++) { @@ -105,69 +113,51 @@ DictionaryCompressor::compressWord(const uint32_t data) return pattern; } +template <class T> std::unique_ptr<BaseCacheCompressor::CompressionData> -DictionaryCompressor::compress(const uint64_t* data) +DictionaryCompressor<T>::compress(const uint64_t* data) { std::unique_ptr<CompData> comp_data = - std::unique_ptr<CompData>(new CompData(dictionarySize)); - - // Compression size - std::size_t size = 0; + std::unique_ptr<CompData>(new CompData()); // Reset dictionary resetDictionary(); - // Compress every word sequentially - for (std::size_t i = 0; i < blkSize/8; i++) { - const uint32_t first_word = ((data[i])&0xFFFFFFFF00000000) >> 32; - const uint32_t second_word = (data[i])&0x00000000FFFFFFFF; - - // Compress both words - std::unique_ptr<Pattern> first_pattern = compressWord(first_word); - std::unique_ptr<Pattern> second_pattern = compressWord(second_word); - - // Update total line compression size - size += first_pattern->getSizeBits() + second_pattern->getSizeBits(); - - // Print debug information - DPRINTF(CacheComp, "Compressed %08x to %s\n", first_word, - first_pattern->print()); - DPRINTF(CacheComp, "Compressed %08x to %s\n", second_word, - second_pattern->print()); - - // Append to pattern list - comp_data->entries.push_back(std::move(first_pattern)); - comp_data->entries.push_back(std::move(second_pattern)); + // Compress every value sequentially + const std::vector<T> values((T*)data, (T*)data + blkSize / sizeof(T)); + for (const auto& value : values) { + std::unique_ptr<Pattern> pattern = compressValue(value); + DPRINTF(CacheComp, "Compressed %016x to %s\n", value, + pattern->print()); + comp_data->addEntry(std::move(pattern)); } - // Set final compression size - comp_data->setSizeBits(size); - // Return compressed line return std::move(comp_data); } -uint32_t -DictionaryCompressor::decompressWord(const Pattern* pattern) +template <class T> +T +DictionaryCompressor<T>::decompressValue(const Pattern* pattern) { // Search for matching entry - std::vector<std::array<uint8_t, 4>>::iterator entry_it = - dictionary.begin(); + auto entry_it = dictionary.begin(); std::advance(entry_it, pattern->getMatchLocation()); // Decompress the match. If the decompressed value must be added to // the dictionary, do it - const std::array<uint8_t, 4> data = pattern->decompress(*entry_it); + const DictionaryEntry data = pattern->decompress(*entry_it); if (pattern->shouldAllocate()) { addToDictionary(data); } - // Return word - return (((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]; + // Return value + return fromDictionaryEntry(data); } +template <class T> void -DictionaryCompressor::decompress(const CompressionData* comp_data, +DictionaryCompressor<T>::decompress(const CompressionData* comp_data, uint64_t* data) { const CompData* casted_comp_data = static_cast<const CompData*>(comp_data); @@ -176,37 +166,47 @@ DictionaryCompressor::decompress(const CompressionData* comp_data, resetDictionary(); // Decompress every entry sequentially - std::vector<uint32_t> decomp_words; + std::vector<T> decomp_values; for (const auto& entry : casted_comp_data->entries) { - const uint32_t word = decompressWord(&*entry); - decomp_words.push_back(word); - - // Print debug information - DPRINTF(CacheComp, "Decompressed %s to %x\n", entry->print(), word); + const T value = decompressValue(&*entry); + decomp_values.push_back(value); + DPRINTF(CacheComp, "Decompressed %s to %x\n", entry->print(), value); } - // Concatenate the decompressed words to generate the cache lines + // Concatenate the decompressed values to generate the original data for (std::size_t i = 0; i < blkSize/8; i++) { - data[i] = (static_cast<uint64_t>(decomp_words[2*i]) << 32) | - decomp_words[2*i+1]; + data[i] = 0; + const std::size_t values_per_entry = sizeof(uint64_t)/sizeof(T); + for (int j = values_per_entry - 1; j >= 0; j--) { + data[i] |= + static_cast<uint64_t>(decomp_values[values_per_entry*i+j]) << + (j*8*sizeof(T)); + } } } -void -DictionaryCompressor::regStats() +template <class T> +typename DictionaryCompressor<T>::DictionaryEntry +DictionaryCompressor<T>::toDictionaryEntry(T value) { - BaseCacheCompressor::regStats(); - - // We store the frequency of each pattern - patternStats - .init(getNumPatterns()) - .name(name() + ".pattern") - .desc("Number of data entries that were compressed to this pattern.") - ; - - for (unsigned i = 0; i < getNumPatterns(); ++i) { - patternStats.subname(i, getName(i)); - patternStats.subdesc(i, "Number of data entries that match pattern " + - getName(i)); + DictionaryEntry entry; + for (int i = 0; i < sizeof(T); i++) { + entry[i] = value & 0xFF; + value >>= 8; } + return entry; } + +template <class T> +T +DictionaryCompressor<T>::fromDictionaryEntry(const DictionaryEntry& entry) +{ + T value = 0; + for (int i = sizeof(T) - 1; i >= 0; i--) { + value <<= 8; + value |= entry[i]; + } + return value; +} + +#endif //__MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_IMPL_HH__ |