gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
37 using namespace gem5;
38 
43 TEST(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 
60 TEST(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 
76 TEST(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 
92 TEST(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 
107 TEST(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 
121 TEST(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 
138 TEST(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 
152 TEST(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 
169 TEST(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 
193 TEST(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 
243 TEST(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 
258 TEST(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 
272 TEST(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 
301 TEST(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 
355 TEST(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 
405 TEST(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 
436 TEST(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 
468 TEST(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 
500 TEST(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 }
gem5::GenericSatCounter::calcSaturation
double calcSaturation() const
Calculate saturation percentile of the current counter's value with regard to its maximum possible va...
Definition: sat_counter.hh:303
logging.hh
gem5::GenericSatCounter::saturate
T saturate()
Saturate the counter.
Definition: sat_counter.hh:321
gem5::GenericSatCounter::isSaturated
bool isSaturated() const
Whether the counter has achieved its maximum value or not.
Definition: sat_counter.hh:312
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
sat_counter.hh
gem5::GenericSatCounter< uint8_t >
gem5::GenericSatCounter::reset
void reset()
Reset the counter to its initial value.
Definition: sat_counter.hh:292
gem5::bits
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:76
gem5::gtestLogOutput
thread_local GTestLogOutput gtestLogOutput
Definition: logging.cc:33
TEST
TEST(SatCounterDeathTest, BitCountExceeds)
Test that an error is triggered when the number of bits exceeds the counter's capacity.
Definition: sat_counter.test.cc:43
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37

Generated on Sun Jul 30 2023 01:56:51 for gem5 by doxygen 1.8.17