gem5 v24.0.0.0
Loading...
Searching...
No Matches
dictionary_compressor.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018-2020 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
43#ifndef __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
44#define __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
45
46#include <array>
47#include <cstdint>
48#include <map>
49#include <memory>
50#include <string>
51#include <type_traits>
52#include <vector>
53
54#include "base/bitfield.hh"
55#include "base/statistics.hh"
56#include "base/types.hh"
58
59namespace gem5
60{
61
62struct BaseDictionaryCompressorParams;
63
64namespace compression
65{
66
68{
69 protected:
71 const std::size_t dictionarySize;
72
74 std::size_t numEntries;
75
88
94 virtual uint64_t getNumPatterns() const = 0;
95
102 virtual std::string getName(int number) const = 0;
103
104 public:
105 typedef BaseDictionaryCompressorParams Params;
108};
109
116template <class T>
118{
119 protected:
121 typedef std::array<uint8_t, sizeof(T)> DictionaryEntry;
122
127 class CompData;
128
129 // Forward declaration of a pattern
130 class Pattern;
132 template <T mask>
133 class MaskedPattern;
134 template <T value, T mask>
135 class MaskedValuePattern;
136 template <T mask, int location>
138 template <class RepT>
140 template <std::size_t DeltaSizeBits>
141 class DeltaPattern;
142 template <unsigned N>
144
150 template <class Head, class... Tail>
151 struct Factory
152 {
153 static std::unique_ptr<Pattern> getPattern(
154 const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
155 const int match_location)
156 {
157 // If match this pattern, instantiate it. If a negative match
158 // location is used, the patterns that use the dictionary bytes
159 // must return false. This is used when there are no dictionary
160 // entries yet
161 if (Head::isPattern(bytes, dict_bytes, match_location)) {
162 return std::unique_ptr<Pattern>(
163 new Head(bytes, match_location));
164 // Otherwise, go for next pattern
165 } else {
166 return Factory<Tail...>::getPattern(bytes, dict_bytes,
167 match_location);
168 }
169 }
170 };
171
178 template <class Head>
179 struct Factory<Head>
180 {
181 static_assert(std::is_base_of_v<UncompressedPattern, Head>,
182 "The last pattern must always be derived from the uncompressed "
183 "pattern.");
184
185 static std::unique_ptr<Pattern>
187 const DictionaryEntry& dict_bytes, const int match_location)
188 {
189 return std::unique_ptr<Pattern>(new Head(bytes, match_location));
190 }
191 };
192
195
201 virtual std::unique_ptr<Pattern>
202 getPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
203 const int match_location) const = 0;
204
211 std::unique_ptr<Pattern> compressValue(const T data);
212
219 T decompressValue(const Pattern* pattern);
220
222 virtual void resetDictionary();
223
229 virtual void addToDictionary(const DictionaryEntry data) = 0;
230
236 virtual std::unique_ptr<DictionaryCompressor::CompData>
238
245 std::unique_ptr<Base::CompressionData> compress(
246 const std::vector<Chunk>& chunks);
247
248 std::unique_ptr<Base::CompressionData> compress(
249 const std::vector<Chunk>& chunks,
250 Cycles& comp_lat, Cycles& decomp_lat) override;
251
253
254 void decompress(const CompressionData* comp_data, uint64_t* data) override;
255
262 static DictionaryEntry toDictionaryEntry(T value);
263
270 static T fromDictionaryEntry(const DictionaryEntry& entry);
271
272 public:
273 typedef BaseDictionaryCompressorParams Params;
276};
277
284template <class T>
286{
287 protected:
289 const int patternNumber;
290
292 const uint8_t code;
293
295 const uint8_t length;
296
298 const uint8_t numUnmatchedBits;
299
301 const int matchLocation;
302
304 const bool allocate;
305
306 public:
316 Pattern(const int number, const uint64_t code,
317 const uint64_t metadata_length, const uint64_t num_unmatched_bits,
318 const int match_location, const bool allocate = true)
319 : patternNumber(number), code(code), length(metadata_length),
320 numUnmatchedBits(num_unmatched_bits),
321 matchLocation(match_location), allocate(allocate)
322 {
323 }
324
326 virtual ~Pattern() = default;
327
333 int getPatternNumber() const { return patternNumber; };
334
340 uint8_t getCode() const { return code; }
341
347 uint8_t getMatchLocation() const { return matchLocation; }
348
355 virtual std::size_t
357 {
358 return numUnmatchedBits + length;
359 }
360
366 bool shouldAllocate() const { return allocate; }
367
373 std::string
374 print() const
375 {
376 return csprintf("pattern %s (encoding %x, size %u bits)",
377 getPatternNumber(), getCode(), getSizeBits());
378 }
379
388 const DictionaryEntry dict_bytes) const = 0;
389};
390
391template <class T>
393{
394 public:
397
398 CompData();
399 ~CompData() = default;
400
406 virtual void addEntry(std::unique_ptr<Pattern>);
407};
408
414template <class T>
416 : public DictionaryCompressor<T>::Pattern
417{
418 private:
421
422 public:
423 UncompressedPattern(const int number,
424 const uint64_t code,
425 const uint64_t metadata_length,
426 const int match_location,
427 const DictionaryEntry bytes)
428 : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
429 sizeof(T) * 8, match_location, true),
430 data(bytes)
431 {
432 }
433
434 static bool
435 isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
436 const int match_location)
437 {
438 // An entry can always be uncompressed
439 return true;
440 }
441
443 decompress(const DictionaryEntry dict_bytes) const override
444 {
445 return data;
446 }
447};
448
461template <class T>
462template <T mask>
464 : public DictionaryCompressor<T>::Pattern
465{
466 private:
467 static_assert(mask != 0, "The pattern's value mask must not be zero. Use "
468 "the uncompressed pattern instead.");
469
471 const T bits;
472
473 public:
474 MaskedPattern(const int number,
475 const uint64_t code,
476 const uint64_t metadata_length,
477 const int match_location,
478 const DictionaryEntry bytes,
479 const bool allocate = true)
480 : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
481 popCount(static_cast<T>(~mask)), match_location, allocate),
483 {
484 }
485
486 static bool
487 isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
488 const int match_location)
489 {
490 const T masked_bytes =
492 const T masked_dict_bytes =
494 return (match_location >= 0) && (masked_bytes == masked_dict_bytes);
495 }
496
498 decompress(const DictionaryEntry dict_bytes) const override
499 {
500 const T masked_dict_bytes =
503 bits | masked_dict_bytes);
504 }
505};
506
523template <class T>
524template <T value, T mask>
526 : public MaskedPattern<mask>
527{
528 private:
529 static_assert(mask != 0, "The pattern's value mask must not be zero.");
530
531 public:
532 MaskedValuePattern(const int number,
533 const uint64_t code,
534 const uint64_t metadata_length,
535 const int match_location,
536 const DictionaryEntry bytes,
537 const bool allocate = false)
538 : MaskedPattern<mask>(number, code, metadata_length, match_location,
539 bytes, allocate)
540 {
541 }
542
543 static bool
544 isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
545 const int match_location)
546 {
547 // Compare the masked fixed value to the value being checked for
548 // patterns. Since the dictionary is not being used the match_location
549 // is irrelevant.
550 const T masked_bytes =
552 return ((value & mask) == masked_bytes);
553 }
554
556 decompress(const DictionaryEntry dict_bytes) const override
557 {
560 }
561};
562
570template <class T>
571template <T mask, int location>
573 : public MaskedPattern<mask>
574{
575 public:
576 LocatedMaskedPattern(const int number,
577 const uint64_t code,
578 const uint64_t metadata_length,
579 const int match_location,
580 const DictionaryEntry bytes,
581 const bool allocate = true)
582 : MaskedPattern<mask>(number, code, metadata_length, match_location,
583 bytes, allocate)
584 {
585 }
586
587 static bool
588 isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
589 const int match_location)
590 {
591 // Besides doing the regular masked pattern matching, the match
592 // location must match perfectly with this instance's
593 return (match_location == location) &&
594 MaskedPattern<mask>::isPattern(bytes, dict_bytes, match_location);
595 }
596};
597
608template <class T>
609template <class RepT>
611 : public DictionaryCompressor<T>::Pattern
612{
613 private:
614 static_assert(sizeof(T) > sizeof(RepT), "The repeated value's type must "
615 "be smaller than the dictionary entry's type.");
616
618 RepT value;
619
620 public:
621 RepeatedValuePattern(const int number,
622 const uint64_t code,
623 const uint64_t metadata_length,
624 const int match_location,
625 const DictionaryEntry bytes,
626 const bool allocate = true)
627 : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
628 8 * sizeof(RepT), match_location, allocate),
630 {
631 }
632
633 static bool
634 isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
635 const int match_location)
636 {
637 // Parse the dictionary entry in a RepT granularity, and if all values
638 // are equal, this is a repeated value pattern. Since the dictionary
639 // is not being used, the match_location is irrelevant
641 const RepT rep_value = bytes_value;
642 for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
643 RepT cur_value = bytes_value;
644 if (cur_value != rep_value) {
645 return false;
646 }
647 bytes_value >>= 8 * sizeof(RepT);
648 }
649 return true;
650 }
651
653 decompress(const DictionaryEntry dict_bytes) const override
654 {
655 // The decompressed value is just multiple consecutive instances of
656 // the same value
657 T decomp_value = 0;
658 for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
659 decomp_value <<= 8 * sizeof(RepT);
660 decomp_value |= value;
661 }
663 }
664};
665
680template <class T>
681template <std::size_t DeltaSizeBits>
683 : public DictionaryCompressor<T>::Pattern
684{
685 private:
686 static_assert(DeltaSizeBits < (sizeof(T) * 8),
687 "Delta size must be smaller than base size");
688
695
696 public:
697 DeltaPattern(const int number,
698 const uint64_t code,
699 const uint64_t metadata_length,
700 const int match_location,
701 const DictionaryEntry bytes)
702 : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
703 DeltaSizeBits, match_location, false),
704 bytes(bytes)
705 {
706 }
707
716 static bool
718 const DictionaryEntry& base_bytes)
719 {
720 const typename std::make_signed<T>::type limit = DeltaSizeBits ?
721 mask(DeltaSizeBits - 1) : 0;
722 const T value =
724 const T base =
726 const typename std::make_signed<T>::type delta = value - base;
727 return (delta >= -limit) && (delta <= limit);
728 }
729
730 static bool
732 const DictionaryEntry& dict_bytes, const int match_location)
733 {
734 return (match_location >= 0) && isValidDelta(bytes, dict_bytes);
735 }
736
738 decompress(const DictionaryEntry dict_bytes) const override
739 {
740 return bytes;
741 }
742};
743
754template <class T>
755template <unsigned N>
757 : public DictionaryCompressor<T>::Pattern
758{
759 private:
760 static_assert((N > 0) & (N <= (sizeof(T) * 8)),
761 "The original data's type size must be smaller than the dictionary's");
762
764 const T bits : N;
765
766 public:
767 SignExtendedPattern(const int number,
768 const uint64_t code,
769 const uint64_t metadata_length,
770 const DictionaryEntry bytes,
771 const bool allocate = false)
772 : DictionaryCompressor<T>::Pattern(number, code, metadata_length, N,
773 -1, allocate),
774 bits(fromDictionaryEntry(bytes) & mask(N))
775 {
776 }
777
778 static bool
780 const DictionaryEntry& dict_bytes, const int match_location)
781 {
783 return data == (T)szext<N>(data);
784 }
785
787 decompress(const DictionaryEntry dict_bytes) const override
788 {
790 }
791};
792
793} // namespace compression
794} // namespace gem5
795
796#endif //__MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
const char data[]
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
virtual std::string getName(int number) const =0
Get meta-name assigned to the given pattern.
const std::size_t dictionarySize
Dictionary size.
virtual uint64_t getNumPatterns() const =0
Trick function to get the number of patterns.
std::size_t numEntries
Number of valid entries in the dictionary.
gem5::compression::BaseDictionaryCompressor::DictionaryStats dictionaryStats
Base cache compressor interface.
Definition base.hh:65
virtual std::unique_ptr< CompressionData > compress(const std::vector< Chunk > &chunks, Cycles &comp_lat, Cycles &decomp_lat)=0
Apply the compression process to the cache line.
std::vector< std::unique_ptr< Pattern > > entries
The patterns matched in the original line.
A pattern that checks whether the difference of the value and the dictionary entries' is below a cert...
DeltaPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
static bool isValidDelta(const DictionaryEntry &bytes, const DictionaryEntry &base_bytes)
Compares a given value against a base to calculate their delta, and then determines whether it fits a...
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
A pattern that narrows the MaskedPattern by allowing a only single possible dictionary entry to be ma...
LocatedMaskedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=true)
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
A pattern that compares masked values against dictionary entries.
MaskedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=true)
const T bits
A copy of the bits that do not belong to the mask.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
A pattern that compares masked values to a masked portion of a fixed value.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
MaskedValuePattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=false)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
The compressed data is composed of multiple pattern entries.
const int matchLocation
Index representing the the match location.
virtual DictionaryEntry decompress(const DictionaryEntry dict_bytes) const =0
Decompress the pattern.
const uint8_t length
Length, in bits, of the code and match location.
std::string print() const
Extract pattern's information to a string.
uint8_t getCode() const
Get code of this pattern.
bool shouldAllocate() const
Determine if pattern allocates a dictionary entry.
virtual std::size_t getSizeBits() const
Get size, in bits, of the pattern (excluding prefix).
Pattern(const int number, const uint64_t code, const uint64_t metadata_length, const uint64_t num_unmatched_bits, const int match_location, const bool allocate=true)
Default constructor.
int getPatternNumber() const
Get enum number associated to this pattern.
const bool allocate
Wether the pattern allocates a dictionary entry or not.
const uint8_t numUnmatchedBits
Number of unmatched bits.
uint8_t getMatchLocation() const
Get the index of the dictionary match location.
const uint8_t code
Code associated to the pattern.
virtual ~Pattern()=default
Default destructor.
A pattern that checks if dictionary entry sized values are solely composed of multiple copies of a si...
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
RepeatedValuePattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=true)
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
A pattern that checks whether the value is an N bits sign-extended value, that is,...
SignExtendedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const DictionaryEntry bytes, const bool allocate=false)
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
A pattern containing the original uncompressed data.
UncompressedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
const DictionaryEntry data
A copy of the original data.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
A template version of the dictionary compressor that allows to choose the dictionary size.
static T fromDictionaryEntry(const DictionaryEntry &entry)
Turn a dictionary entry into a value.
std::vector< DictionaryEntry > dictionary
The dictionary.
virtual void addToDictionary(const DictionaryEntry data)=0
Add an entry to the dictionary.
virtual std::unique_ptr< Pattern > getPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location) const =0
Since the factory cannot be instantiated here, classes that inherit from this base class have to impl...
virtual void resetDictionary()
Clear all dictionary entries.
std::unique_ptr< Pattern > compressValue(const T data)
Compress data.
virtual std::unique_ptr< DictionaryCompressor::CompData > instantiateDictionaryCompData() const
Instantiate a compression data of the sub-class compressor.
std::array< uint8_t, sizeof(T)> DictionaryEntry
Convenience typedef for a dictionary entry.
T decompressValue(const Pattern *pattern)
Decompress a pattern into a value that fits in a dictionary entry.
void decompress(const CompressionData *comp_data, uint64_t *data) override
Apply the decompression process to the compressed data.
std::unique_ptr< Base::CompressionData > compress(const std::vector< Chunk > &chunks)
Apply compression.
static DictionaryEntry toDictionaryEntry(T value)
Turn a value into a dictionary entry.
Statistics container.
Definition group.hh:93
A vector of scalar stats.
STL vector class.
Definition stl.hh:37
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr int popCount(uint64_t val)
Returns the number of set ones in the provided value.
Definition bitfield.hh:415
constexpr uint64_t szext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition bitfield.hh:161
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition bitfield.hh:129
Definition of a basic cache compressor.
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 0 > p
Bitfield< 51, 12 > base
Definition pagetable.hh:141
BitfieldType< SegDescriptorLimit > limit
Definition misc.hh:959
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
Declaration of Statistics objects.
statistics::Vector patterns
Number of data entries that were compressed to each pattern.
DictionaryStats(BaseStats &base_group, BaseDictionaryCompressor &_compressor)
static std::unique_ptr< Pattern > getPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
Create a factory to determine if input matches a pattern.
static std::unique_ptr< Pattern > getPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)

Generated on Tue Jun 18 2024 16:24:04 for gem5 by doxygen 1.11.0