misc: Changed gem5 version info for gem5 20.2 dev
[gem5.git] / src / base / sat_counter.hh
1 /*
2 * Copyright (c) 2019 Inria
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2005-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #ifndef __BASE_SAT_COUNTER_HH__
42 #define __BASE_SAT_COUNTER_HH__
43
44 #include <cassert>
45 #include <cstdint>
46
47 #include "base/logging.hh"
48 #include "base/types.hh"
49
50 /**
51 * Implements an n bit saturating counter and provides methods to
52 * increment, decrement, and read it.
53 */
54 class SatCounter
55 {
56 public:
57 /** The default constructor should never be used. */
58 SatCounter() = delete;
59
60 /**
61 * Constructor for the counter. The explicit keyword is used to make
62 * sure the user does not assign a number to the counter thinking it
63 * will be used as a counter value when it is in fact used as the number
64 * of bits.
65 *
66 * @param bits How many bits the counter will have.
67 * @param initial_val Starting value for the counter.
68 *
69 * @ingroup api_sat_counter
70 */
71 explicit SatCounter(unsigned bits, uint8_t initial_val = 0)
72 : initialVal(initial_val), maxVal((1 << bits) - 1),
73 counter(initial_val)
74 {
75 fatal_if(bits > 8*sizeof(uint8_t),
76 "Number of bits exceeds counter size");
77 fatal_if(initial_val > maxVal,
78 "Saturating counter's Initial value exceeds max value.");
79 }
80
81 /**
82 * Copy constructor.
83 *
84 * @ingroup api_sat_counter
85 */
86 SatCounter(const SatCounter& other)
87 : initialVal(other.initialVal), maxVal(other.maxVal),
88 counter(other.counter)
89 {
90 }
91
92 /**
93 * Copy assignment.
94 *
95 * @ingroup api_sat_counter
96 */
97 SatCounter& operator=(const SatCounter& other) {
98 if (this != &other) {
99 SatCounter temp(other);
100 this->swap(temp);
101 }
102 return *this;
103 }
104
105 /**
106 * Move constructor.
107 *
108 * @ingroup api_sat_counter
109 */
110 SatCounter(SatCounter&& other)
111 {
112 initialVal = other.initialVal;
113 maxVal = other.maxVal;
114 counter = other.counter;
115 SatCounter temp(0);
116 other.swap(temp);
117 }
118
119 /**
120 * Move assignment.
121 *
122 * @ingroup api_sat_counter
123 */
124 SatCounter& operator=(SatCounter&& other) {
125 if (this != &other) {
126 initialVal = other.initialVal;
127 maxVal = other.maxVal;
128 counter = other.counter;
129 SatCounter temp(0);
130 other.swap(temp);
131 }
132 return *this;
133 }
134
135 /**
136 * Swap the contents of every member of the class. Used for the default
137 * copy-assignment created by the compiler.
138 *
139 * @param other The other object to swap contents with.
140 *
141 * @ingroup api_sat_counter
142 */
143 void
144 swap(SatCounter& other)
145 {
146 std::swap(initialVal, other.initialVal);
147 std::swap(maxVal, other.maxVal);
148 std::swap(counter, other.counter);
149 }
150
151 /**
152 * Pre-increment operator.
153 *
154 * @ingroup api_sat_counter
155 */
156 SatCounter&
157 operator++()
158 {
159 if (counter < maxVal) {
160 ++counter;
161 }
162 return *this;
163 }
164
165 /**
166 * Post-increment operator.
167 *
168 * @ingroup api_sat_counter
169 */
170 SatCounter
171 operator++(int)
172 {
173 SatCounter old_counter = *this;
174 ++*this;
175 return old_counter;
176 }
177
178 /**
179 * Pre-decrement operator.
180 *
181 * @ingroup api_sat_counter
182 */
183 SatCounter&
184 operator--()
185 {
186 if (counter > 0) {
187 --counter;
188 }
189 return *this;
190 }
191
192 /**
193 * Post-decrement operator.
194 *
195 * @ingroup api_sat_counter
196 */
197 SatCounter
198 operator--(int)
199 {
200 SatCounter old_counter = *this;
201 --*this;
202 return old_counter;
203 }
204
205 /**
206 * Shift-right-assignment.
207 *
208 * @ingroup api_sat_counter
209 */
210 SatCounter&
211 operator>>=(const int& shift)
212 {
213 assert(shift >= 0);
214 this->counter >>= shift;
215 return *this;
216 }
217
218 /**
219 * Shift-left-assignment.
220 *
221 * @ingroup api_sat_counter
222 */
223 SatCounter&
224 operator<<=(const int& shift)
225 {
226 assert(shift >= 0);
227 this->counter <<= shift;
228 if (this->counter > maxVal) {
229 this->counter = maxVal;
230 }
231 return *this;
232 }
233
234 /**
235 * Add-assignment.
236 *
237 * @ingroup api_sat_counter
238 */
239 SatCounter&
240 operator+=(const int& value)
241 {
242 if (value >= 0) {
243 if (maxVal - this->counter >= value) {
244 this->counter += value;
245 } else {
246 this->counter = maxVal;
247 }
248 } else {
249 *this -= -value;
250 }
251 return *this;
252 }
253
254 /**
255 * Subtract-assignment.
256 *
257 * @ingroup api_sat_counter
258 */
259 SatCounter&
260 operator-=(const int& value)
261 {
262 if (value >= 0) {
263 if (this->counter > value) {
264 this->counter -= value;
265 } else {
266 this->counter = 0;
267 }
268 } else {
269 *this += -value;
270 }
271 return *this;
272 }
273
274 /**
275 * Read the counter's value.
276 *
277 * @ingroup api_sat_counter
278 */
279 operator uint8_t() const { return counter; }
280
281 /**
282 * Reset the counter to its initial value.
283 *
284 * @ingroup api_sat_counter
285 */
286 void reset() { counter = initialVal; }
287
288 /**
289 * Calculate saturation percentile of the current counter's value
290 * with regard to its maximum possible value.
291 *
292 * @return A value between 0.0 and 1.0 to indicate which percentile of
293 * the maximum value the current value is.
294 *
295 * @ingroup api_sat_counter
296 */
297 double calcSaturation() const { return (double) counter / maxVal; }
298
299 /**
300 * Whether the counter has achieved its maximum value or not.
301 *
302 * @return True if the counter saturated.
303 *
304 * @ingroup api_sat_counter
305 */
306 bool isSaturated() const { return counter == maxVal; }
307
308 /**
309 * Saturate the counter.
310 *
311 * @return The value added to the counter to reach saturation.
312 *
313 * @ingroup api_sat_counter
314 */
315 uint8_t saturate()
316 {
317 const uint8_t diff = maxVal - counter;
318 counter = maxVal;
319 return diff;
320 }
321
322 private:
323 uint8_t initialVal;
324 uint8_t maxVal;
325 uint8_t counter;
326 };
327
328 #endif // __BASE_SAT_COUNTER_HH__