mem-cache: Standardize data parsing in compressors
[gem5.git] / src / mem / cache / compressors / base.hh
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
29 /** @file
30 * Definition of a basic cache compressor.
31 * A cache compressor must consist of a compression and a decompression
32 * methods. It must also be aware of the size of an uncompressed cache
33 * line.
34 */
35
36 #ifndef __MEM_CACHE_COMPRESSORS_BASE_HH__
37 #define __MEM_CACHE_COMPRESSORS_BASE_HH__
38
39 #include <cstdint>
40
41 #include "base/statistics.hh"
42 #include "base/types.hh"
43 #include "sim/sim_object.hh"
44
45 class CacheBlk;
46 struct BaseCacheCompressorParams;
47
48 namespace Compressor {
49
50 /**
51 * Base cache compressor interface. Every cache compressor must implement a
52 * compression and a decompression method.
53 *
54 * Compressors usually cannot parse all data input at once. Therefore, they
55 * typically divide the input into multiple *chunks*, and parse them one at
56 * a cycle.
57 */
58 class Base : public SimObject
59 {
60 public:
61 /**
62 * Forward declaration of compression data. Every new compressor must
63 * create a new compression data based on it.
64 */
65 class CompressionData;
66
67 protected:
68 /**
69 * A chunk is a basic lexical unit. The data being compressed is received
70 * by the compressor as a raw pointer. In order to parse this data, the
71 * compressor must divide it into smaller units. Typically, state-of-the-
72 * art compressors interpret cache lines as sequential 32-bit chunks
73 * (chunks), but any size is valid.
74 * @sa chunkSizeBits
75 */
76 typedef uint64_t Chunk;
77
78 /**
79 * This compressor must be able to access the protected functions of
80 * its sub-compressors.
81 */
82 friend class Multi;
83
84 /**
85 * Uncompressed cache line size (in bytes).
86 */
87 const std::size_t blkSize;
88
89 /** Chunk size, in number of bits. */
90 const unsigned chunkSizeBits;
91
92 /**
93 * Size in bytes at which a compression is classified as bad and therefore
94 * the compressed block is restored to its uncompressed format.
95 */
96 const std::size_t sizeThreshold;
97
98 struct BaseStats : public Stats::Group
99 {
100 const Base& compressor;
101
102 BaseStats(Base& compressor);
103
104 void regStats() override;
105
106 /** Number of compressions performed. */
107 Stats::Scalar compressions;
108
109 /** Number of blocks that were compressed to this power of two size. */
110 Stats::Vector compressionSize;
111
112 /** Total compressed data size, in number of bits. */
113 Stats::Scalar compressionSizeBits;
114
115 /** Average data size after compression, in number of bits. */
116 Stats::Formula avgCompressionSizeBits;
117
118 /** Number of decompressions performed. */
119 Stats::Scalar decompressions;
120 } stats;
121
122 /**
123 * This function splits the raw data into chunks, so that it can be
124 * parsed by the compressor.
125 *
126 * @param data The raw pointer to the data being compressed.
127 * @return The raw data divided into a vector of sequential chunks.
128 */
129 std::vector<Chunk> toChunks(const uint64_t* data) const;
130
131 /**
132 * This function re-joins the chunks to recreate the original data.
133 *
134 * @param chunks The raw data divided into a vector of sequential chunks.
135 * @param data The raw pointer to the data.
136 */
137 void fromChunks(const std::vector<Chunk>& chunks, uint64_t* data) const;
138
139 /**
140 * Apply the compression process to the cache line.
141 * Returns the number of cycles used by the compressor, however it is
142 * usually covered by a good pipelined execution, and is currently ignored.
143 * The decompression latency is also returned, in order to avoid
144 * increasing simulation time and memory consumption.
145 *
146 * @param chunks The cache line to be compressed, divided into chunks.
147 * @param comp_lat Compression latency in number of cycles.
148 * @param decomp_lat Decompression latency in number of cycles.
149 * @return Cache line after compression.
150 */
151 virtual std::unique_ptr<CompressionData> compress(
152 const std::vector<Chunk>& chunks, Cycles& comp_lat,
153 Cycles& decomp_lat) = 0;
154
155 /**
156 * Apply the decompression process to the compressed data.
157 *
158 * @param comp_data Compressed cache line.
159 * @param cache_line The cache line to be decompressed.
160 */
161 virtual void decompress(const CompressionData* comp_data,
162 uint64_t* cache_line) = 0;
163
164 public:
165 typedef BaseCacheCompressorParams Params;
166 Base(const Params *p);
167 virtual ~Base() = default;
168
169 /**
170 * Apply the compression process to the cache line. Ignores compression
171 * cycles.
172 *
173 * @param data The cache line to be compressed.
174 * @param comp_lat Compression latency in number of cycles.
175 * @param decomp_lat Decompression latency in number of cycles.
176 * @return Cache line after compression.
177 */
178 std::unique_ptr<CompressionData>
179 compress(const uint64_t* data, Cycles& comp_lat, Cycles& decomp_lat);
180
181 /**
182 * Get the decompression latency if the block is compressed. Latency is 0
183 * otherwise.
184 *
185 * @param blk The compressed block.
186 */
187 Cycles getDecompressionLatency(const CacheBlk* blk);
188
189 /**
190 * Set the decompression latency of compressed block.
191 *
192 * @param blk The compressed block.
193 * @param lat The decompression latency.
194 */
195 static void setDecompressionLatency(CacheBlk* blk, const Cycles lat);
196
197 /**
198 * Set the size of the compressed block, in bits.
199 *
200 * @param blk The compressed block.
201 * @param size_bits The block size.
202 */
203 static void setSizeBits(CacheBlk* blk, const std::size_t size_bits);
204 };
205
206 class Base::CompressionData
207 {
208 private:
209 /**
210 * Compressed cache line size (in bits).
211 */
212 std::size_t _size;
213
214 public:
215 /**
216 * Default constructor.
217 */
218 CompressionData();
219
220 /**
221 * Virtual destructor. Without it unique_ptr will cause mem leak.
222 */
223 virtual ~CompressionData();
224
225 /**
226 * Set compression size (in bits).
227 *
228 * @param size Compressed data size.
229 */
230 void setSizeBits(std::size_t size);
231
232 /**
233 * Get compression size (in bits).
234 *
235 * @return Compressed data size.
236 */
237 std::size_t getSizeBits() const;
238
239 /**
240 * Get compression size (in bytes).
241 *
242 * @return Compressed data size.
243 */
244 std::size_t getSize() const;
245 };
246
247 } // namespace Compressor
248
249 #endif //__MEM_CACHE_COMPRESSORS_BASE_HH__