mem-cache: Add a masked pattern to compressors

The masked pattern compares masked values to masked dictionary entries
to determine whether these values match. If successful, the bits that
do not match must be added to the compressed data.

Change-Id: I4b1c8feb0faa99576382b54a73a20c353f965d2a
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21150
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Daniel R. Carvalho
2019-09-16 16:22:55 +02:00
committed by Daniel Carvalho
parent 7973e49187
commit 83219d89de
2 changed files with 69 additions and 63 deletions

View File

@@ -154,55 +154,21 @@ class CPack::PatternXXXX : public UncompressedPattern
}
};
class CPack::PatternMMMM : public DictionaryCompressor::Pattern
class CPack::PatternMMMM : public MaskedPattern<0xFFFFFFFF>
{
public:
PatternMMMM(const DictionaryEntry bytes, const int match_location)
: Pattern(MMMM, 0x2, 6, 0, match_location, true) {}
static bool isPattern(const DictionaryEntry& bytes,
const DictionaryEntry& dict_bytes,
const int match_location)
: MaskedPattern<0xFFFFFFFF>(MMMM, 0x2, 6, match_location, bytes, true)
{
return (bytes == dict_bytes) && (match_location >= 0);
}
DictionaryEntry
decompress(const DictionaryEntry dict_bytes) const override
{
return dict_bytes;
}
};
class CPack::PatternMMXX : public DictionaryCompressor::Pattern
class CPack::PatternMMXX : public MaskedPattern<0xFFFF0000>
{
private:
/**
* A copy of the unmatched bytes.
*/
const uint8_t byte0;
const uint8_t byte1;
public:
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 DictionaryEntry& bytes,
const DictionaryEntry& dict_bytes,
const int match_location)
: MaskedPattern<0xFFFF0000>(MMXX, 0xC, 8, match_location, bytes, true)
{
// Notice we don't compare bytes[0], as otherwise we'd be unnecessarily
// discarding MMXM. If that pattern is added this should be modified
return (bytes[3] == dict_bytes[3]) && (bytes[2] == dict_bytes[2]) &&
(bytes[1] != dict_bytes[1]) && (match_location >= 0);
}
DictionaryEntry
decompress(const DictionaryEntry dict_bytes) const override
{
return {byte0, byte1, dict_bytes[2], dict_bytes[3]};
}
};
@@ -233,32 +199,12 @@ class CPack::PatternZZZX : public DictionaryCompressor::Pattern
}
};
class CPack::PatternMMMX : public DictionaryCompressor::Pattern
class CPack::PatternMMMX : public MaskedPattern<0xFFFFFF00>
{
private:
/**
* A copy of the unmatched byte.
*/
const uint8_t byte;
public:
PatternMMMX(const DictionaryEntry bytes, const int match_location)
: Pattern(MMMX, 0xE, 8, 1, match_location, true),
byte(bytes[0]) {}
static bool isPattern(const DictionaryEntry& bytes,
const DictionaryEntry& dict_bytes,
const int match_location)
: MaskedPattern<0xFFFFFF00>(MMMX, 0xE, 8, match_location, bytes, true)
{
return (bytes[3] == dict_bytes[3]) && (bytes[2] == dict_bytes[2]) &&
(bytes[1] == dict_bytes[1]) && (bytes[0] != dict_bytes[0]) &&
(match_location >= 0);
}
DictionaryEntry
decompress(const DictionaryEntry dict_bytes) const override
{
return {byte, dict_bytes[1], dict_bytes[2], dict_bytes[3]};
}
};

View File

@@ -111,6 +111,9 @@ template <class T>
class DictionaryCompressor : public BaseDictionaryCompressor
{
protected:
/** Convenience typedef for a dictionary entry. */
typedef std::array<uint8_t, sizeof(T)> DictionaryEntry;
/**
* Compression data for the dictionary compressor. It consists of a vector
* of patterns.
@@ -120,9 +123,8 @@ class DictionaryCompressor : public BaseDictionaryCompressor
// Forward declaration of a pattern
class Pattern;
class UncompressedPattern;
/** Convenience typedef for a dictionary entry. */
typedef std::array<uint8_t, sizeof(T)> DictionaryEntry;
template <T mask>
class MaskedPattern;
/**
* Create a factory to determine if input matches a pattern. The if else
@@ -420,4 +422,62 @@ class DictionaryCompressor<T>::UncompressedPattern
}
};
/**
* A pattern that compares masked values against dictionary entries. If
* the masked dictionary entry matches perfectly the masked value to be
* compressed, there is a pattern match.
*
* For example, if the mask is 0xFF00 (that is, this pattern matches the MSB),
* the value (V) 0xFF20 is being compressed, and the dictionary contains
* the value (D) 0xFF03, this is a match (V & mask == 0xFF00 == D & mask),
* and 0x0020 is added to the list of unmatched bits.
*
* @tparam mask A mask containing the bits that must match.
*/
template <class T>
template <T mask>
class DictionaryCompressor<T>::MaskedPattern
: public DictionaryCompressor<T>::Pattern
{
private:
static_assert(mask != 0, "The pattern's value mask must not be zero. Use "
"the uncompressed pattern instead.");
/** A copy of the bits that do not belong to the mask. */
const T bits;
public:
MaskedPattern(const int number,
const uint64_t code,
const uint64_t metadata_length,
const int match_location,
const DictionaryEntry bytes,
const bool allocate = true)
: DictionaryCompressor<T>::Pattern(number, code, metadata_length,
popCount(~mask) / 8, match_location, allocate),
bits(DictionaryCompressor<T>::fromDictionaryEntry(bytes) & ~mask)
{
}
static bool
isPattern(const DictionaryEntry& bytes, const DictionaryEntry& dict_bytes,
const int match_location)
{
const T masked_bytes =
DictionaryCompressor<T>::fromDictionaryEntry(bytes) & mask;
const T masked_dict_bytes =
DictionaryCompressor<T>::fromDictionaryEntry(dict_bytes) & mask;
return (match_location >= 0) && (masked_bytes == masked_dict_bytes);
}
DictionaryEntry
decompress(const DictionaryEntry dict_bytes) const override
{
const T masked_dict_bytes =
DictionaryCompressor<T>::fromDictionaryEntry(dict_bytes) & mask;
return DictionaryCompressor<T>::toDictionaryEntry(
bits | masked_dict_bytes);
}
};
#endif //__MEM_CACHE_COMPRESSORS_DICTIONARY_COMPRESSOR_HH__