gem5  v19.0.0.0
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  * Authors: Daniel Carvalho
29  */
30 
45 #ifndef __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
46 #define __MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__
47 
48 #include <array>
49 #include <cstdint>
50 #include <map>
51 #include <memory>
52 #include <string>
53 #include <type_traits>
54 #include <vector>
55 
56 #include "base/types.hh"
58 
59 struct BaseDictionaryCompressorParams;
60 
62 {
63  protected:
65  const std::size_t dictionarySize;
66 
68  std::size_t numEntries;
69 
77 
87  virtual uint64_t getNumPatterns() const = 0;
88 
95  virtual std::string getName(int number) const = 0;
96 
97  public:
98  typedef BaseDictionaryCompressorParams Params;
99  BaseDictionaryCompressor(const Params *p);
100  ~BaseDictionaryCompressor() = default;
101 
102  void regStats() override;
103 };
104 
111 template <class T>
113 {
114  protected:
116  typedef std::array<uint8_t, sizeof(T)> DictionaryEntry;
117 
122  class CompData;
123 
124  // Forward declaration of a pattern
125  class Pattern;
126  class UncompressedPattern;
127  template <T mask>
129  template <T value, T mask>
131  template <T mask, int location>
133  template <class RepT>
135  template <std::size_t DeltaSizeBits>
137 
143  template <class Head, class... Tail>
144  struct Factory
145  {
146  static std::unique_ptr<Pattern> getPattern(
147  const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
148  const int match_location)
149  {
150  // If match this pattern, instantiate it. If a negative match
151  // location is used, the patterns that use the dictionary bytes
152  // must return false. This is used when there are no dictionary
153  // entries yet
154  if (Head::isPattern(bytes, dict_bytes, match_location)) {
155  return std::unique_ptr<Pattern>(
156  new Head(bytes, match_location));
157  // Otherwise, go for next pattern
158  } else {
159  return Factory<Tail...>::getPattern(bytes, dict_bytes,
160  match_location);
161  }
162  }
163  };
164 
171  template <class Head>
172  struct Factory<Head>
173  {
174  static_assert(std::is_base_of<UncompressedPattern, Head>::value,
175  "The last pattern must always be derived from the uncompressed "
176  "pattern.");
177 
178  static std::unique_ptr<Pattern>
179  getPattern(const DictionaryEntry& bytes,
180  const DictionaryEntry& dict_bytes, const int match_location)
181  {
182  return std::unique_ptr<Pattern>(new Head(bytes, match_location));
183  }
184  };
185 
188 
194  virtual std::unique_ptr<Pattern>
195  getPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
196  const int match_location) const = 0;
197 
204  std::unique_ptr<Pattern> compressValue(const T data);
205 
212  T decompressValue(const Pattern* pattern);
213 
215  virtual void resetDictionary();
216 
222  virtual void addToDictionary(const DictionaryEntry data) = 0;
223 
230  std::unique_ptr<BaseCacheCompressor::CompressionData> compress(
231  const uint64_t* data);
232 
234 
241  void decompress(const CompressionData* comp_data, uint64_t* data) override;
242 
249  static DictionaryEntry toDictionaryEntry(T value);
250 
257  static T fromDictionaryEntry(const DictionaryEntry& entry);
258 
259  public:
260  typedef BaseDictionaryCompressorParams Params;
261  DictionaryCompressor(const Params *p);
262  ~DictionaryCompressor() = default;
263 };
264 
271 template <class T>
273 {
274  protected:
276  const int patternNumber;
277 
279  const uint8_t code;
280 
282  const uint8_t length;
283 
285  const uint8_t numUnmatchedBits;
286 
288  const int matchLocation;
289 
291  const bool allocate;
292 
293  public:
303  Pattern(const int number, const uint64_t code,
304  const uint64_t metadata_length, const uint64_t num_unmatched_bits,
305  const int match_location, const bool allocate = true)
306  : patternNumber(number), code(code), length(metadata_length),
307  numUnmatchedBits(num_unmatched_bits),
308  matchLocation(match_location), allocate(allocate)
309  {
310  }
311 
313  virtual ~Pattern() = default;
314 
320  int getPatternNumber() const { return patternNumber; };
321 
327  uint8_t getCode() const { return code; }
328 
334  uint8_t getMatchLocation() const { return matchLocation; }
335 
342  std::size_t
343  getSizeBits() const
344  {
345  return numUnmatchedBits + length;
346  }
347 
353  bool shouldAllocate() const { return allocate; }
354 
360  std::string
361  print() const
362  {
363  return csprintf("pattern %s (encoding %x, size %u bits)",
364  getPatternNumber(), getCode(), getSizeBits());
365  }
366 
374  virtual DictionaryEntry decompress(
375  const DictionaryEntry dict_bytes) const = 0;
376 };
377 
378 template <class T>
380 {
381  public:
384 
385  CompData();
386  ~CompData() = default;
387 
393  virtual void addEntry(std::unique_ptr<Pattern>);
394 };
395 
401 template <class T>
404 {
405  private:
408 
409  public:
410  UncompressedPattern(const int number,
411  const uint64_t code,
412  const uint64_t metadata_length,
413  const int match_location,
414  const DictionaryEntry bytes)
415  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
416  sizeof(T) * 8, match_location, true),
417  data(bytes)
418  {
419  }
420 
421  static bool
422  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
423  const int match_location)
424  {
425  // An entry can always be uncompressed
426  return true;
427  }
428 
430  decompress(const DictionaryEntry dict_bytes) const override
431  {
432  return data;
433  }
434 };
435 
448 template <class T>
449 template <T mask>
452 {
453  private:
454  static_assert(mask != 0, "The pattern's value mask must not be zero. Use "
455  "the uncompressed pattern instead.");
456 
458  const T bits;
459 
460  public:
461  MaskedPattern(const int number,
462  const uint64_t code,
463  const uint64_t metadata_length,
464  const int match_location,
465  const DictionaryEntry bytes,
466  const bool allocate = true)
467  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
468  popCount(~mask), match_location, allocate),
469  bits(DictionaryCompressor<T>::fromDictionaryEntry(bytes) & ~mask)
470  {
471  }
472 
473  static bool
474  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
475  const int match_location)
476  {
477  const T masked_bytes =
479  const T masked_dict_bytes =
481  return (match_location >= 0) && (masked_bytes == masked_dict_bytes);
482  }
483 
485  decompress(const DictionaryEntry dict_bytes) const override
486  {
487  const T masked_dict_bytes =
490  bits | masked_dict_bytes);
491  }
492 };
493 
510 template <class T>
511 template <T value, T mask>
513  : public MaskedPattern<mask>
514 {
515  private:
516  static_assert(mask != 0, "The pattern's value mask must not be zero.");
517 
518  public:
519  MaskedValuePattern(const int number,
520  const uint64_t code,
521  const uint64_t metadata_length,
522  const int match_location,
523  const DictionaryEntry bytes,
524  const bool allocate = false)
525  : MaskedPattern<mask>(number, code, metadata_length, match_location,
526  bytes, allocate)
527  {
528  }
529 
530  static bool
531  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
532  const int match_location)
533  {
534  // Compare the masked fixed value to the value being checked for
535  // patterns. Since the dictionary is not being used the match_location
536  // is irrelevant.
537  const T masked_bytes =
539  return ((value & mask) == masked_bytes);
540  }
541 
543  decompress(const DictionaryEntry dict_bytes) const override
544  {
547  }
548 };
549 
557 template <class T>
558 template <T mask, int location>
560  : public MaskedPattern<mask>
561 {
562  public:
563  LocatedMaskedPattern(const int number,
564  const uint64_t code,
565  const uint64_t metadata_length,
566  const int match_location,
567  const DictionaryEntry bytes)
568  : MaskedPattern<mask>(number, code, metadata_length, match_location,
569  bytes)
570  {
571  }
572 
573  static bool
574  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
575  const int match_location)
576  {
577  // Besides doing the regular masked pattern matching, the match
578  // location must match perfectly with this instance's
579  return (match_location == location) &&
580  MaskedPattern<mask>::isPattern(bytes, dict_bytes, match_location);
581  }
582 };
583 
594 template <class T>
595 template <class RepT>
598 {
599  private:
600  static_assert(sizeof(T) > sizeof(RepT), "The repeated value's type must "
601  "be smaller than the dictionary entry's type.");
602 
604  RepT value;
605 
606  public:
607  RepeatedValuePattern(const int number,
608  const uint64_t code,
609  const uint64_t metadata_length,
610  const int match_location,
611  const DictionaryEntry bytes,
612  const bool allocate = true)
613  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
614  8 * sizeof(RepT), match_location, allocate),
615  value(DictionaryCompressor<T>::fromDictionaryEntry(bytes))
616  {
617  }
618 
619  static bool
620  isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
621  const int match_location)
622  {
623  // Parse the dictionary entry in a RepT granularity, and if all values
624  // are equal, this is a repeated value pattern. Since the dictionary
625  // is not being used, the match_location is irrelevant
626  T bytes_value = DictionaryCompressor<T>::fromDictionaryEntry(bytes);
627  const RepT rep_value = bytes_value;
628  for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
629  RepT cur_value = bytes_value;
630  if (cur_value != rep_value) {
631  return false;
632  }
633  bytes_value >>= 8 * sizeof(RepT);
634  }
635  return true;
636  }
637 
639  decompress(const DictionaryEntry dict_bytes) const override
640  {
641  // The decompressed value is just multiple consecutive instances of
642  // the same value
643  T decomp_value = 0;
644  for (int i = 0; i < (sizeof(T) / sizeof(RepT)); i++) {
645  decomp_value <<= 8 * sizeof(RepT);
646  decomp_value |= value;
647  }
648  return DictionaryCompressor<T>::toDictionaryEntry(decomp_value);
649  }
650 };
651 
666 template <class T>
667 template <std::size_t DeltaSizeBits>
670 {
671  private:
672  static_assert(DeltaSizeBits < (sizeof(T) * 8),
673  "Delta size must be smaller than base size");
674 
680  const DictionaryEntry bytes;
681 
682  public:
683  DeltaPattern(const int number,
684  const uint64_t code,
685  const uint64_t metadata_length,
686  const int match_location,
687  const DictionaryEntry bytes)
688  : DictionaryCompressor<T>::Pattern(number, code, metadata_length,
689  DeltaSizeBits, match_location, false),
690  bytes(bytes)
691  {
692  }
693 
702  static bool
704  const DictionaryEntry& base_bytes)
705  {
706  const typename std::make_signed<T>::type limit = DeltaSizeBits ?
707  mask(DeltaSizeBits - 1) : 0;
708  const T value =
710  const T base =
712  const typename std::make_signed<T>::type delta = value - base;
713  return (delta >= -limit) && (delta <= limit);
714  }
715 
716  static bool
718  const DictionaryEntry& dict_bytes, const int match_location)
719  {
720  return (match_location >= 0) && isValidDelta(bytes, dict_bytes);
721  }
722 
724  decompress(const DictionaryEntry dict_bytes) const override
725  {
726  return bytes;
727  }
728 };
729 
730 #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:2550
int popCount(uint64_t val)
Returns the number of set ones in the provided value.
Definition: bitfield.hh:249
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:333
~BaseDictionaryCompressor()=default
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
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:142
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:54
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:926
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:64
uint8_t length
Definition: inet.hh:334
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:72
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 Fri Feb 28 2020 16:27:01 for gem5 by doxygen 1.8.13