gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
dictionary_compressor.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 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/types.hh"
56 
57 struct BaseDictionaryCompressorParams;
58 
60 {
61  protected:
63  const std::size_t dictionarySize;
64 
66  std::size_t numEntries;
67 
75 
85  virtual uint64_t getNumPatterns() const = 0;
86 
93  virtual std::string getName(int number) const = 0;
94 
95  public:
96  typedef BaseDictionaryCompressorParams Params;
97  BaseDictionaryCompressor(const Params *p);
98  ~BaseDictionaryCompressor() = default;
99 
100  void regStats() override;
101 };
102 
109 template <class T>
111 {
112  protected:
114  typedef std::array<uint8_t, sizeof(T)> DictionaryEntry;
115 
120  class CompData;
121 
122  // Forward declaration of a pattern
123  class Pattern;
124  class UncompressedPattern;
125  template <T mask>
127  template <T value, T mask>
129  template <T mask, int location>
131  template <class RepT>
133  template <std::size_t DeltaSizeBits>
135 
141  template <class Head, class... Tail>
142  struct Factory
143  {
144  static std::unique_ptr<Pattern> getPattern(
145  const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
146  const int match_location)
147  {
148  // If match this pattern, instantiate it. If a negative match
149  // location is used, the patterns that use the dictionary bytes
150  // must return false. This is used when there are no dictionary
151  // entries yet
152  if (Head::isPattern(bytes, dict_bytes, match_location)) {
153  return std::unique_ptr<Pattern>(
154  new Head(bytes, match_location));
155  // Otherwise, go for next pattern
156  } else {
157  return Factory<Tail...>::getPattern(bytes, dict_bytes,
158  match_location);
159  }
160  }
161  };
162 
169  template <class Head>
170  struct Factory<Head>
171  {
172  static_assert(std::is_base_of<UncompressedPattern, Head>::value,
173  "The last pattern must always be derived from the uncompressed "
174  "pattern.");
175 
176  static std::unique_ptr<Pattern>
177  getPattern(const DictionaryEntry& bytes,
178  const DictionaryEntry& dict_bytes, const int match_location)
179  {
180  return std::unique_ptr<Pattern>(new Head(bytes, match_location));
181  }
182  };
183 
186 
192  virtual std::unique_ptr<Pattern>
193  getPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
194  const int match_location) const = 0;
195 
202  std::unique_ptr<Pattern> compressValue(const T data);
203 
210  T decompressValue(const Pattern* pattern);
211 
213  virtual void resetDictionary();
214 
220  virtual void addToDictionary(const DictionaryEntry data) = 0;
221 
228  std::unique_ptr<BaseCacheCompressor::CompressionData> compress(
229  const uint64_t* data);
230 
232 
239  void decompress(const CompressionData* comp_data, uint64_t* data) override;
240 
247  static DictionaryEntry toDictionaryEntry(T value);
248 
255  static T fromDictionaryEntry(const DictionaryEntry& entry);
256 
257  public:
258  typedef BaseDictionaryCompressorParams Params;
259  DictionaryCompressor(const Params *p);
260  ~DictionaryCompressor() = default;
261 };
262 
269 template <class T>
271 {
272  protected:
274  const int patternNumber;
275 
277  const uint8_t code;
278 
280  const uint8_t length;
281 
283  const uint8_t numUnmatchedBits;
284 
286  const int matchLocation;
287 
289  const bool allocate;
290 
291  public:
301  Pattern(const int number, const uint64_t code,
302  const uint64_t metadata_length, const uint64_t num_unmatched_bits,
303  const int match_location, const bool allocate = true)
304  : patternNumber(number), code(code), length(metadata_length),
305  numUnmatchedBits(num_unmatched_bits),
306  matchLocation(match_location), allocate(allocate)
307  {
308  }
309 
311  virtual ~Pattern() = default;
312 
318  int getPatternNumber() const { return patternNumber; };
319 
325  uint8_t getCode() const { return code; }
326 
332  uint8_t getMatchLocation() const { return matchLocation; }
333 
340  std::size_t
341  getSizeBits() const
342  {
343  return numUnmatchedBits + length;
344  }
345 
351  bool shouldAllocate() const { return allocate; }
352 
358  std::string
359  print() const
360  {
361  return csprintf("pattern %s (encoding %x, size %u bits)",
362  getPatternNumber(), getCode(), getSizeBits());
363  }
364 
372  virtual DictionaryEntry decompress(
373  const DictionaryEntry dict_bytes) const = 0;
374 };
375 
376 template <class T>
378 {
379  public:
382 
383  CompData();
384  ~CompData() = default;
385 
391  virtual void addEntry(std::unique_ptr<Pattern>);
392 };
393 
399 template <class T>
402 {
403  private:
406 
407  public:
408  UncompressedPattern(const int number,
409  const uint64_t code,
410  const uint64_t metadata_length,
411  const int match_location,
412  const DictionaryEntry bytes)
413  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
414  sizeof(T) * 8, match_location, true),
415  data(bytes)
416  {
417  }
418 
419  static bool
420  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
421  const int match_location)
422  {
423  // An entry can always be uncompressed
424  return true;
425  }
426 
428  decompress(const DictionaryEntry dict_bytes) const override
429  {
430  return data;
431  }
432 };
433 
446 template <class T>
447 template <T mask>
450 {
451  private:
452  static_assert(mask != 0, "The pattern's value mask must not be zero. Use "
453  "the uncompressed pattern instead.");
454 
456  const T bits;
457 
458  public:
459  MaskedPattern(const int number,
460  const uint64_t code,
461  const uint64_t metadata_length,
462  const int match_location,
463  const DictionaryEntry bytes,
464  const bool allocate = true)
465  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
466  popCount(~mask), match_location, allocate),
467  bits(DictionaryCompressor<T>::fromDictionaryEntry(bytes) & ~mask)
468  {
469  }
470 
471  static bool
472  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
473  const int match_location)
474  {
475  const T masked_bytes =
477  const T masked_dict_bytes =
479  return (match_location >= 0) && (masked_bytes == masked_dict_bytes);
480  }
481 
483  decompress(const DictionaryEntry dict_bytes) const override
484  {
485  const T masked_dict_bytes =
488  bits | masked_dict_bytes);
489  }
490 };
491 
508 template <class T>
509 template <T value, T mask>
511  : public MaskedPattern<mask>
512 {
513  private:
514  static_assert(mask != 0, "The pattern's value mask must not be zero.");
515 
516  public:
517  MaskedValuePattern(const int number,
518  const uint64_t code,
519  const uint64_t metadata_length,
520  const int match_location,
521  const DictionaryEntry bytes,
522  const bool allocate = false)
523  : MaskedPattern<mask>(number, code, metadata_length, match_location,
524  bytes, allocate)
525  {
526  }
527 
528  static bool
529  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
530  const int match_location)
531  {
532  // Compare the masked fixed value to the value being checked for
533  // patterns. Since the dictionary is not being used the match_location
534  // is irrelevant.
535  const T masked_bytes =
537  return ((value & mask) == masked_bytes);
538  }
539 
541  decompress(const DictionaryEntry dict_bytes) const override
542  {
545  }
546 };
547 
555 template <class T>
556 template <T mask, int location>
558  : public MaskedPattern<mask>
559 {
560  public:
561  LocatedMaskedPattern(const int number,
562  const uint64_t code,
563  const uint64_t metadata_length,
564  const int match_location,
565  const DictionaryEntry bytes)
566  : MaskedPattern<mask>(number, code, metadata_length, match_location,
567  bytes)
568  {
569  }
570 
571  static bool
572  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
573  const int match_location)
574  {
575  // Besides doing the regular masked pattern matching, the match
576  // location must match perfectly with this instance's
577  return (match_location == location) &&
578  MaskedPattern<mask>::isPattern(bytes, dict_bytes, match_location);
579  }
580 };
581 
592 template <class T>
593 template <class RepT>
596 {
597  private:
598  static_assert(sizeof(T) > sizeof(RepT), "The repeated value's type must "
599  "be smaller than the dictionary entry's type.");
600 
602  RepT value;
603 
604  public:
605  RepeatedValuePattern(const int number,
606  const uint64_t code,
607  const uint64_t metadata_length,
608  const int match_location,
609  const DictionaryEntry bytes,
610  const bool allocate = true)
611  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
612  8 * sizeof(RepT), match_location, allocate),
613  value(DictionaryCompressor<T>::fromDictionaryEntry(bytes))
614  {
615  }
616 
617  static bool
618  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
619  const int match_location)
620  {
621  // Parse the dictionary entry in a RepT granularity, and if all values
622  // are equal, this is a repeated value pattern. Since the dictionary
623  // is not being used, the match_location is irrelevant
624  T bytes_value = DictionaryCompressor<T>::fromDictionaryEntry(bytes);
625  const RepT rep_value = bytes_value;
626  for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
627  RepT cur_value = bytes_value;
628  if (cur_value != rep_value) {
629  return false;
630  }
631  bytes_value >>= 8 * sizeof(RepT);
632  }
633  return true;
634  }
635 
637  decompress(const DictionaryEntry dict_bytes) const override
638  {
639  // The decompressed value is just multiple consecutive instances of
640  // the same value
641  T decomp_value = 0;
642  for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
643  decomp_value <<= 8 * sizeof(RepT);
644  decomp_value |= value;
645  }
646  return DictionaryCompressor<T>::toDictionaryEntry(decomp_value);
647  }
648 };
649 
664 template <class T>
665 template <std::size_t DeltaSizeBits>
668 {
669  private:
670  static_assert(DeltaSizeBits < (sizeof(T) * 8),
671  "Delta size must be smaller than base size");
672 
678  const DictionaryEntry bytes;
679 
680  public:
681  DeltaPattern(const int number,
682  const uint64_t code,
683  const uint64_t metadata_length,
684  const int match_location,
685  const DictionaryEntry bytes)
686  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
687  DeltaSizeBits, match_location, false),
688  bytes(bytes)
689  {
690  }
691 
700  static bool
702  const DictionaryEntry& base_bytes)
703  {
704  const typename std::make_signed<T>::type limit = DeltaSizeBits ?
705  mask(DeltaSizeBits - 1) : 0;
706  const T value =
708  const T base =
710  const typename std::make_signed<T>::type delta = value - base;
711  return (delta >= -limit) && (delta <= limit);
712  }
713 
714  static bool
716  const DictionaryEntry& dict_bytes, const int match_location)
717  {
718  return (match_location >= 0) && isValidDelta(bytes, dict_bytes);
719  }
720 
722  decompress(const DictionaryEntry dict_bytes) const override
723  {
724  return bytes;
725  }
726 };
727 
728 #endif //__MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
MaskedValuePattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=false)
virtual std::unique_ptr< CompressionData > compress(const uint64_t *cache_line, Cycles &comp_lat, Cycles &decomp_lat)=0
Apply the compression process to the cache line.
A pattern that compares masked values against dictionary entries.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
uint8_t getMatchLocation() const
Get the index of the dictionary match location.
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
Bitfield< 7 > i
static DictionaryEntry toDictionaryEntry(T value)
Turn a value into a dictionary entry.
void regStats() override
Callback to set stat parameters.
static std::unique_ptr< Pattern > getPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
Definition of a basic cache compressor.
A vector of scalar stats.
Definition: statistics.hh:2547
int popCount(uint64_t val)
Returns the number of set ones in the provided value.
Definition: bitfield.hh:248
std::size_t numEntries
Number of valid entries in the dictionary.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
A pattern that compares masked values to a masked portion of a fixed value.
uint8_t getCode() const
Get code of this pattern.
bool shouldAllocate() const
Determine if pattern allocates a dictionary entry.
std::string print() const
Extract pattern&#39;s information to a string.
const std::size_t dictionarySize
Dictionary size.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
std::size_t getSizeBits() const
Get size, in bits, of the pattern (excluding prefix).
int getPatternNumber() const
Get enum number associated to this pattern.
uint8_t type
Definition: inet.hh:328
~BaseDictionaryCompressor()=default
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
virtual std::string getName(int number) const =0
Get meta-name assigned to the given pattern.
BaseDictionaryCompressorParams Params
virtual uint64_t getNumPatterns() const =0
Trick function to get the number of patterns.
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
Create a factory to determine if input matches a pattern.
The compressed data is composed of multiple pattern entries.
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
const bool allocate
Wether the pattern allocates a dictionary entry or not.
const uint8_t code
Code associated to the pattern.
std::vector< std::unique_ptr< Pattern > > entries
The patterns matched in the original line.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
A pattern that checks if dictionary entry sized values are solely composed of multiple copies of a si...
Base cache compressor interface.
Definition: base.hh:52
const DictionaryEntry data
A copy of the original data.
A pattern that narrows the MaskedPattern by allowing a only single possible dictionary entry to be ma...
static bool isPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
static T fromDictionaryEntry(const DictionaryEntry &entry)
Turn a dictionary entry into a value.
std::array< uint8_t, sizeof(T)> DictionaryEntry
Convenience typedef for a dictionary entry.
UncompressedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes)
std::vector< DictionaryEntry > dictionary
The dictionary.
DeltaPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes)
A pattern that checks whether the difference of the value and the dictionary entries&#39; is below a cert...
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.
Stats::Vector patternStats
Number of data entries that were compressed to each pattern.
static std::unique_ptr< Pattern > getPattern(const DictionaryEntry &bytes, const DictionaryEntry &dict_bytes, const int match_location)
BitfieldType< SegDescriptorLimit > limit
Definition: misc.hh:924
A pattern containing the original uncompressed data.
const DictionaryEntry bytes
The original value.
const int patternNumber
Pattern enum number.
const T bits
A copy of the bits that do not belong to the mask.
MaskedPattern(const int number, const uint64_t code, const uint64_t metadata_length, const int match_location, const DictionaryEntry bytes, const bool allocate=true)
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
DictionaryEntry decompress(const DictionaryEntry dict_bytes) const override
Decompress the pattern.
LocatedMaskedPattern(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.
Bitfield< 3, 0 > mask
Definition: types.hh:62
uint8_t length
Definition: inet.hh:329
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...
BaseDictionaryCompressorParams Params
const uint8_t length
Length, in bits, of the code and match location.
const uint8_t numUnmatchedBits
Number of unmatched bits.
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
Bitfield< 0 > p
const char data[]
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)
const int matchLocation
Index representing the the match location.
A template version of the dictionary compressor that allows to choose the dictionary size...
virtual void decompress(const CompressionData *comp_data, uint64_t *cache_line)=0
Apply the decompression process to the compressed data.

Generated on Mon Jun 8 2020 15:45:11 for gem5 by doxygen 1.8.13