gem5 v24.0.0.0
Loading...
Searching...
No Matches
sat_counter.test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019, 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#include <gtest/gtest-spi.h>
30#include <gtest/gtest.h>
31
32#include <utility>
33
34#include "base/gtest/logging.hh"
35#include "base/sat_counter.hh"
36
37using namespace gem5;
38
43TEST(SatCounterDeathTest, BitCountExceeds)
44{
45#ifdef NDEBUG
46 GTEST_SKIP() << "Skipping as assertions are "
47 "stripped out of fast builds";
48#endif
49
50 gtestLogOutput.str("");
51 EXPECT_ANY_THROW(SatCounter8 counter(9));
52 ASSERT_NE(gtestLogOutput.str().find("Number of bits exceeds counter size"),
53 std::string::npos);
54}
55
60TEST(SatCounterDeathTest, InitialValueExceeds)
61{
62#ifdef NDEBUG
63 GTEST_SKIP() << "Skipping as assertions are "
64 "stripped out of fast builds";
65#endif
66
67 gtestLogOutput.str("");
68 EXPECT_ANY_THROW(SatCounter8 counter(7, 128));
69 ASSERT_NE(gtestLogOutput.str().find("initial value exceeds max value"),
70 std::string::npos);
71}
72
76TEST(SatCounterTest, MaximumValue)
77{
78 const unsigned bits = 3;
79 const unsigned max_value = (1 << bits) - 1;
80 SatCounter8 counter(bits);
81
82 for (int i = 0; i < 2*max_value; i++) {
83 counter++;
84 }
85
86 ASSERT_EQ(counter, max_value);
87}
88
92TEST(SatCounterTest, MinimumValue)
93{
94 const unsigned bits = 3;
95 SatCounter8 counter(bits);
96
97 for (int i = 0; i < 2; i++) {
98 counter--;
99 }
100
101 ASSERT_EQ(counter, 0);
102}
103
107TEST(SatCounterTest, InitialValue)
108{
109 const unsigned bits = 3;
110 const unsigned initial_value = 4;
111 SatCounter8 counter(bits, initial_value);
112 ASSERT_EQ(counter, initial_value);
113 counter++;
114 counter.reset();
115 ASSERT_EQ(counter, initial_value);
116}
117
121TEST(SatCounterTest, SaturationPercentile)
122{
123 const unsigned bits = 3;
124 const unsigned max_value = (1 << bits) - 1;
125 SatCounter8 counter(bits);
126
127 ASSERT_FALSE(counter.isSaturated());
128 for (double value = 0.0; value <= max_value; value++, counter++) {
129 const double saturation = value / max_value;
130 ASSERT_DOUBLE_EQ(counter.calcSaturation(), saturation);
131 }
132 ASSERT_TRUE(counter.isSaturated());
133}
134
138TEST(SatCounterTest, Saturate)
139{
140 const unsigned bits = 3;
141 const unsigned max_value = (1 << bits) - 1;
142 SatCounter8 counter(bits);
143 counter++;
144 ASSERT_FALSE(counter.isSaturated());
145
146 // Make sure the value added is what was missing to saturate
147 const unsigned diff = counter.saturate();
148 ASSERT_EQ(diff, max_value - 1);
149 ASSERT_TRUE(counter.isSaturated());
150}
151
152TEST(SatCounterTest, Saturate16)
153{
154 const unsigned bits = 14;
155 const unsigned max_value = (1 << bits) - 1;
156 SatCounter16 counter(bits);
157 counter++;
158 ASSERT_FALSE(counter.isSaturated());
159
160 // Make sure the value added is what was missing to saturate
161 const unsigned diff = counter.saturate();
162 ASSERT_EQ(diff, max_value - 1);
163 ASSERT_TRUE(counter.isSaturated());
164}
165
169TEST(SatCounterTest, IntComparison)
170{
171 const unsigned bits = 3;
172 SatCounter8 counter(bits);
173 int value = 0;
174
175 ASSERT_EQ(counter++, value++);
176 ASSERT_EQ(counter++, value++);
177 ASSERT_EQ(counter--, value--);
178 ASSERT_EQ(counter++, value++);
179 ASSERT_EQ(counter++, value++);
180 ASSERT_EQ(counter--, value--);
181 ASSERT_EQ(counter++, value++);
182 ASSERT_EQ(counter--, value--);
183 ASSERT_EQ(counter--, value--);
184 ASSERT_EQ(counter++, value++);
185 ASSERT_EQ(counter--, value--);
186 ASSERT_EQ(counter--, value--);
187 ASSERT_EQ(counter, 0);
188}
189
193TEST(SatCounterTest, Shift)
194{
195 const unsigned bits = 3;
196 const unsigned max_value = (1 << bits) - 1;
197 const unsigned initial_value = 1;
198 SatCounter8 counter(bits, initial_value);
199 SatCounter8 other(bits, initial_value);
200 // The saturated shift value is just enough to saturate, since greater
201 // values could generate undefined behavior
202 SatCounter8 saturated_counter(bits, bits);
203 int value = initial_value;
204
205 // Test random shifts
206 counter <<= 2;
207 value <<= 2;
208 ASSERT_EQ(counter, value);
209 counter >>= 1;
210 value >>= 1;
211 ASSERT_EQ(counter, value);
212
213 // Test saturation
214 counter <<= bits;
215 ASSERT_EQ(counter, max_value);
216
217 // Test zeroing
218 counter >>= bits;
219 ASSERT_EQ(counter, 0);
220
221 // Test saturation against other saturating counter
222 counter.reset();
223 value = initial_value;
224 counter <<= other;
225 value <<= other;
226 ASSERT_EQ(counter, value);
227 counter <<= saturated_counter;
228 value = max_value;
229 ASSERT_EQ(counter, max_value);
230
231 // Test zeroing against other saturating counter
232 counter >>= other;
233 value >>= other;
234 ASSERT_EQ(counter, value);
235 counter >>= saturated_counter;
236 ASSERT_EQ(counter, 0);
237}
238
243TEST(SatCounterDeathTest, RightShiftNegative)
244{
245#ifdef NDEBUG
246 GTEST_SKIP() << "Skipping as assertions are "
247 "stripped out of fast builds";
248#endif
249
250 SatCounter8 counter(8);
251 ASSERT_DEATH(counter >>= -1, "");
252}
253
258TEST(SatCounterDeathTest, LeftShiftNegative)
259{
260#ifdef NDEBUG
261 GTEST_SKIP() << "Skipping as assertions are "
262 "stripped out of fast builds";
263#endif
264
265 SatCounter8 counter(8);
266 ASSERT_DEATH(counter <<= -1, "");
267}
268
272TEST(SatCounterTest, PrePostOperators)
273{
274 const unsigned bits = 3;
275 const unsigned max_value = (1 << bits) - 1;
276 SatCounter8 counter_pre(bits);
277 SatCounter8 counter_post(bits);
278
279 for (int i = 0; i < 2*max_value; i++) {
280 counter_post++;
281 SatCounter8 value_pre = ++counter_pre;
282 ASSERT_EQ(counter_post, value_pre);
283 }
284
285 ASSERT_EQ(counter_pre, max_value);
286 ASSERT_EQ(counter_post, max_value);
287
288 for (int i = 0; i < 2*max_value; i++) {
289 counter_post--;
290 SatCounter8 value_pre = --counter_pre;
291 ASSERT_EQ(counter_post, value_pre);
292 }
293
294 ASSERT_EQ(counter_pre, 0);
295 ASSERT_EQ(counter_post, 0);
296}
297
301TEST(SatCounterTest, CopyMove)
302{
303 const unsigned bits = 3;
304 const unsigned max_value = (1 << bits) - 1;
305 const unsigned initial_value = 1;
306 SatCounter8 counter(bits, initial_value);
307 SatCounter8 deep_copy(1);
308 SatCounter8 counter_copy(2);
309
310 // Increase counter value so that we can check if the inner counter is
311 // being copied
312 counter++;
313
314 // Copy counter using both the copy constructor and the copy assignment
315 SatCounter8 counter_copy_constructor(counter);
316 deep_copy = counter_copy = counter;
317 ASSERT_EQ(counter_copy_constructor, initial_value + 1);
318 ASSERT_EQ(counter_copy, initial_value + 1);
319 ASSERT_EQ(deep_copy, initial_value + 1);
320
321 // Make sure max value is the same for all of them, and that modifying
322 // the copies does not modify the original
323 for (int i = 0; i < 2*max_value; i++) {
324 counter_copy_constructor++;
325 counter_copy++;
326 deep_copy++;
327 }
328 ASSERT_EQ(counter, initial_value + 1);
329 ASSERT_EQ(counter_copy_constructor, max_value);
330 ASSERT_EQ(counter_copy, max_value);
331 ASSERT_EQ(deep_copy, max_value);
332
333 // Make sure initial value is the same for all of them
334 counter_copy_constructor.reset();
335 counter_copy.reset();
336 deep_copy.reset();
337 ASSERT_EQ(counter_copy_constructor, initial_value);
338 ASSERT_EQ(counter_copy, initial_value);
339 ASSERT_EQ(deep_copy, initial_value);
340
341 // Now check move
342 SatCounter8 counter_move_constructor(std::move(counter));
343 ASSERT_EQ(counter, 0);
344 ASSERT_EQ(counter_move_constructor, initial_value + 1);
345
346 SatCounter8 counter_move(bits);
347 counter_move = std::move(counter_move_constructor);
348 ASSERT_EQ(counter_move_constructor, 0);
349 ASSERT_EQ(counter_move, initial_value + 1);
350}
351
355TEST(SatCounterTest, AddSubAssignment)
356{
357 const unsigned bits = 3;
358 const unsigned max_value = (1 << bits) - 1;
359 SatCounter8 counter(bits);
360 SatCounter8 other(bits, 2);
361 SatCounter8 saturated_counter(bits, max_value);
362 int value = 0;
363
364 // Test add-assignment for a few random values and then saturate
365 counter += 2;
366 value += 2;
367 ASSERT_EQ(counter, value);
368 counter += 3;
369 value += 3;
370 ASSERT_EQ(counter, value);
371 counter += max_value;
372 value = max_value;
373 ASSERT_EQ(counter, value);
374
375 // Test subtract-assignment for a few random values until back to zero
376 counter -= 2;
377 value -= 2;
378 ASSERT_EQ(counter, value);
379 counter -= 3;
380 value -= 3;
381 ASSERT_EQ(counter, value);
382 counter -= max_value;
383 value = 0;
384 ASSERT_EQ(counter, value);
385
386 // Test add-assignment of other saturating counter
387 counter += other;
388 value += other;
389 ASSERT_EQ(counter, value);
390 counter += saturated_counter;
391 value = max_value;
392 ASSERT_EQ(counter, saturated_counter);
393
394 // Test subtract-assignment of other saturating counter
395 counter -= other;
396 value -= other;
397 ASSERT_EQ(counter, value);
398 counter -= saturated_counter;
399 ASSERT_EQ(counter, 0);
400}
401
405TEST(SatCounterTest, NegativeAddSubAssignment)
406{
407 const unsigned bits = 3;
408 const unsigned max_value = (1 << bits) - 1;
409 SatCounter8 counter(bits, max_value);
410 int value = max_value;
411
412 // Test add-assignment for a few negative values until zero is reached
413 counter += -2;
414 value += -2;
415 ASSERT_EQ(counter, value);
416 counter += -3;
417 value += -3;
418 ASSERT_EQ(counter, value);
419 counter += (int)-max_value;
420 value = 0;
421 ASSERT_EQ(counter, value);
422
423 // Test subtract-assignment for a few negative values until saturation
424 counter -= -2;
425 value -= -2;
426 ASSERT_EQ(counter, value);
427 counter -= -3;
428 value -= -3;
429 ASSERT_EQ(counter, value);
430 counter -= (int)-max_value;
431 value = max_value;
432 ASSERT_EQ(counter, value);
433}
434
436TEST(SatCounterTest, Size16)
437{
438 const uint16_t bits_16 = 9;
439 const uint16_t max_value_16 = (1 << bits_16) - 1;
440 SatCounter16 counter_16(bits_16);
441
442 // Increasing
443 counter_16++;
444 ASSERT_EQ(counter_16, 1);
445 counter_16 <<= 1;
446 ASSERT_EQ(counter_16, 2);
447 counter_16 += 2 * max_value_16;
448 ASSERT_EQ(counter_16, max_value_16);
449 counter_16++;
450 ASSERT_EQ(counter_16, max_value_16);
451 counter_16 <<= 1;
452 ASSERT_EQ(counter_16, max_value_16);
453
454 // Decreasing
455 counter_16--;
456 ASSERT_EQ(counter_16, max_value_16 - 1);
457 counter_16 >>= 1;
458 ASSERT_EQ(counter_16, (max_value_16 - 1) >> 1);
459 counter_16 -= 2 * max_value_16;
460 ASSERT_EQ(counter_16, 0);
461 counter_16--;
462 ASSERT_EQ(counter_16, 0);
463 counter_16 >>= 1;
464 ASSERT_EQ(counter_16, 0);
465}
466
468TEST(SatCounterTest, Size32)
469{
470 const uint32_t bits_32 = 17;
471 const uint32_t max_value_32 = (1 << bits_32) - 1;
472 SatCounter32 counter_32(bits_32);
473
474 // Increasing
475 counter_32++;
476 ASSERT_EQ(counter_32, 1);
477 counter_32 <<= 1;
478 ASSERT_EQ(counter_32, 2);
479 counter_32 += 2 * max_value_32;
480 ASSERT_EQ(counter_32, max_value_32);
481 counter_32++;
482 ASSERT_EQ(counter_32, max_value_32);
483 counter_32 <<= 1;
484 ASSERT_EQ(counter_32, max_value_32);
485
486 // Decreasing
487 counter_32--;
488 ASSERT_EQ(counter_32, max_value_32 - 1);
489 counter_32 >>= 1;
490 ASSERT_EQ(counter_32, (max_value_32 - 1) >> 1);
491 counter_32 -= 2 * max_value_32;
492 ASSERT_EQ(counter_32, 0);
493 counter_32--;
494 ASSERT_EQ(counter_32, 0);
495 counter_32 >>= 1;
496 ASSERT_EQ(counter_32, 0);
497}
498
500TEST(SatCounterTest, Size64)
501{
502 const uint64_t bits_64 = 33;
503 const uint64_t max_value_64 = (1ULL << bits_64) - 1;
504 SatCounter64 counter_64(bits_64);
505
506 // Increasing
507 counter_64++;
508 ASSERT_EQ(counter_64, 1);
509 counter_64 <<= 1;
510 ASSERT_EQ(counter_64, 2);
511 counter_64 += max_value_64;
512 ASSERT_EQ(counter_64, max_value_64);
513 counter_64++;
514 ASSERT_EQ(counter_64, max_value_64);
515 counter_64 <<= 1;
516 ASSERT_EQ(counter_64, max_value_64);
517
518 // Decreasing
519 counter_64--;
520 ASSERT_EQ(counter_64, max_value_64 - 1);
521 counter_64 >>= 1;
522 ASSERT_EQ(counter_64, (max_value_64 - 1) >> 1);
523 counter_64 -= max_value_64;
524 ASSERT_EQ(counter_64, 0);
525 counter_64--;
526 ASSERT_EQ(counter_64, 0);
527 counter_64 >>= 1;
528 ASSERT_EQ(counter_64, 0);
529}
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
bool isSaturated() const
Whether the counter has achieved its maximum value or not.
double calcSaturation() const
Calculate saturation percentile of the current counter's value with regard to its maximum possible va...
T saturate()
Saturate the counter.
void reset()
Reset the counter to its initial value.
Bitfield< 7 > i
Definition misc_types.hh:67
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
thread_local GTestLogOutput gtestLogOutput
Definition logging.cc:33
TEST(SatCounterDeathTest, BitCountExceeds)
Test that an error is triggered when the number of bits exceeds the counter's capacity.

Generated on Tue Jun 18 2024 16:24:01 for gem5 by doxygen 1.11.0