gem5  v21.1.0.2
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 
155 TEST(SatCounterTest, IntComparison)
156 {
157  const unsigned bits = 3;
158  SatCounter8 counter(bits);
159  int value = 0;
160 
161  ASSERT_EQ(counter++, value++);
162  ASSERT_EQ(counter++, value++);
163  ASSERT_EQ(counter--, value--);
164  ASSERT_EQ(counter++, value++);
165  ASSERT_EQ(counter++, value++);
166  ASSERT_EQ(counter--, value--);
167  ASSERT_EQ(counter++, value++);
168  ASSERT_EQ(counter--, value--);
169  ASSERT_EQ(counter--, value--);
170  ASSERT_EQ(counter++, value++);
171  ASSERT_EQ(counter--, value--);
172  ASSERT_EQ(counter--, value--);
173  ASSERT_EQ(counter, 0);
174 }
175 
179 TEST(SatCounterTest, Shift)
180 {
181  const unsigned bits = 3;
182  const unsigned max_value = (1 << bits) - 1;
183  const unsigned initial_value = 1;
184  SatCounter8 counter(bits, initial_value);
185  SatCounter8 other(bits, initial_value);
186  // The saturated shift value is just enough to saturate, since greater
187  // values could generate undefined behavior
188  SatCounter8 saturated_counter(bits, bits);
189  int value = initial_value;
190 
191  // Test random shifts
192  counter <<= 2;
193  value <<= 2;
194  ASSERT_EQ(counter, value);
195  counter >>= 1;
196  value >>= 1;
197  ASSERT_EQ(counter, value);
198 
199  // Test saturation
200  counter <<= bits;
201  ASSERT_EQ(counter, max_value);
202 
203  // Test zeroing
204  counter >>= bits;
205  ASSERT_EQ(counter, 0);
206 
207  // Test saturation against other saturating counter
208  counter.reset();
209  value = initial_value;
210  counter <<= other;
211  value <<= other;
212  ASSERT_EQ(counter, value);
213  counter <<= saturated_counter;
214  value = max_value;
215  ASSERT_EQ(counter, max_value);
216 
217  // Test zeroing against other saturating counter
218  counter >>= other;
219  value >>= other;
220  ASSERT_EQ(counter, value);
221  counter >>= saturated_counter;
222  ASSERT_EQ(counter, 0);
223 }
224 
229 TEST(SatCounterDeathTest, RightShiftNegative)
230 {
231 #ifdef NDEBUG
232  GTEST_SKIP() << "Skipping as assertions are "
233  "stripped out of fast builds";
234 #endif
235 
236  SatCounter8 counter(8);
237  ASSERT_DEATH(counter >>= -1, "");
238 }
239 
244 TEST(SatCounterDeathTest, LeftShiftNegative)
245 {
246 #ifdef NDEBUG
247  GTEST_SKIP() << "Skipping as assertions are "
248  "stripped out of fast builds";
249 #endif
250 
251  SatCounter8 counter(8);
252  ASSERT_DEATH(counter <<= -1, "");
253 }
254 
258 TEST(SatCounterTest, PrePostOperators)
259 {
260  const unsigned bits = 3;
261  const unsigned max_value = (1 << bits) - 1;
262  SatCounter8 counter_pre(bits);
263  SatCounter8 counter_post(bits);
264 
265  for (int i = 0; i < 2*max_value; i++) {
266  counter_post++;
267  SatCounter8 value_pre = ++counter_pre;
268  ASSERT_EQ(counter_post, value_pre);
269  }
270 
271  ASSERT_EQ(counter_pre, max_value);
272  ASSERT_EQ(counter_post, max_value);
273 
274  for (int i = 0; i < 2*max_value; i++) {
275  counter_post--;
276  SatCounter8 value_pre = --counter_pre;
277  ASSERT_EQ(counter_post, value_pre);
278  }
279 
280  ASSERT_EQ(counter_pre, 0);
281  ASSERT_EQ(counter_post, 0);
282 }
283 
287 TEST(SatCounterTest, CopyMove)
288 {
289  const unsigned bits = 3;
290  const unsigned max_value = (1 << bits) - 1;
291  const unsigned initial_value = 1;
292  SatCounter8 counter(bits, initial_value);
293  SatCounter8 deep_copy(1);
294  SatCounter8 counter_copy(2);
295 
296  // Increase counter value so that we can check if the inner counter is
297  // being copied
298  counter++;
299 
300  // Copy counter using both the copy constructor and the copy assignment
301  SatCounter8 counter_copy_constructor(counter);
302  deep_copy = counter_copy = counter;
303  ASSERT_EQ(counter_copy_constructor, initial_value + 1);
304  ASSERT_EQ(counter_copy, initial_value + 1);
305  ASSERT_EQ(deep_copy, initial_value + 1);
306 
307  // Make sure max value is the same for all of them, and that modifying
308  // the copies does not modify the original
309  for (int i = 0; i < 2*max_value; i++) {
310  counter_copy_constructor++;
311  counter_copy++;
312  deep_copy++;
313  }
314  ASSERT_EQ(counter, initial_value + 1);
315  ASSERT_EQ(counter_copy_constructor, max_value);
316  ASSERT_EQ(counter_copy, max_value);
317  ASSERT_EQ(deep_copy, max_value);
318 
319  // Make sure initial value is the same for all of them
320  counter_copy_constructor.reset();
321  counter_copy.reset();
322  deep_copy.reset();
323  ASSERT_EQ(counter_copy_constructor, initial_value);
324  ASSERT_EQ(counter_copy, initial_value);
325  ASSERT_EQ(deep_copy, initial_value);
326 
327  // Now check move
328  SatCounter8 counter_move_constructor(std::move(counter));
329  ASSERT_EQ(counter, 0);
330  ASSERT_EQ(counter_move_constructor, initial_value + 1);
331 
332  SatCounter8 counter_move(bits);
333  counter_move = std::move(counter_move_constructor);
334  ASSERT_EQ(counter_move_constructor, 0);
335  ASSERT_EQ(counter_move, initial_value + 1);
336 }
337 
341 TEST(SatCounterTest, AddSubAssignment)
342 {
343  const unsigned bits = 3;
344  const unsigned max_value = (1 << bits) - 1;
345  SatCounter8 counter(bits);
346  SatCounter8 other(bits, 2);
347  SatCounter8 saturated_counter(bits, max_value);
348  int value = 0;
349 
350  // Test add-assignment for a few random values and then saturate
351  counter += 2;
352  value += 2;
353  ASSERT_EQ(counter, value);
354  counter += 3;
355  value += 3;
356  ASSERT_EQ(counter, value);
357  counter += max_value;
358  value = max_value;
359  ASSERT_EQ(counter, value);
360 
361  // Test subtract-assignment for a few random values until back to zero
362  counter -= 2;
363  value -= 2;
364  ASSERT_EQ(counter, value);
365  counter -= 3;
366  value -= 3;
367  ASSERT_EQ(counter, value);
368  counter -= max_value;
369  value = 0;
370  ASSERT_EQ(counter, value);
371 
372  // Test add-assignment of other saturating counter
373  counter += other;
374  value += other;
375  ASSERT_EQ(counter, value);
376  counter += saturated_counter;
377  value = max_value;
378  ASSERT_EQ(counter, saturated_counter);
379 
380  // Test subtract-assignment of other saturating counter
381  counter -= other;
382  value -= other;
383  ASSERT_EQ(counter, value);
384  counter -= saturated_counter;
385  ASSERT_EQ(counter, 0);
386 }
387 
391 TEST(SatCounterTest, NegativeAddSubAssignment)
392 {
393  const unsigned bits = 3;
394  const unsigned max_value = (1 << bits) - 1;
395  SatCounter8 counter(bits, max_value);
396  int value = max_value;
397 
398  // Test add-assignment for a few negative values until zero is reached
399  counter += -2;
400  value += -2;
401  ASSERT_EQ(counter, value);
402  counter += -3;
403  value += -3;
404  ASSERT_EQ(counter, value);
405  counter += (int)-max_value;
406  value = 0;
407  ASSERT_EQ(counter, value);
408 
409  // Test subtract-assignment for a few negative values until saturation
410  counter -= -2;
411  value -= -2;
412  ASSERT_EQ(counter, value);
413  counter -= -3;
414  value -= -3;
415  ASSERT_EQ(counter, value);
416  counter -= (int)-max_value;
417  value = max_value;
418  ASSERT_EQ(counter, value);
419 }
420 
422 TEST(SatCounterTest, Size16)
423 {
424  const uint16_t bits_16 = 9;
425  const uint16_t max_value_16 = (1 << bits_16) - 1;
426  SatCounter16 counter_16(bits_16);
427 
428  // Increasing
429  counter_16++;
430  ASSERT_EQ(counter_16, 1);
431  counter_16 <<= 1;
432  ASSERT_EQ(counter_16, 2);
433  counter_16 += 2 * max_value_16;
434  ASSERT_EQ(counter_16, max_value_16);
435  counter_16++;
436  ASSERT_EQ(counter_16, max_value_16);
437  counter_16 <<= 1;
438  ASSERT_EQ(counter_16, max_value_16);
439 
440  // Decreasing
441  counter_16--;
442  ASSERT_EQ(counter_16, max_value_16 - 1);
443  counter_16 >>= 1;
444  ASSERT_EQ(counter_16, (max_value_16 - 1) >> 1);
445  counter_16 -= 2 * max_value_16;
446  ASSERT_EQ(counter_16, 0);
447  counter_16--;
448  ASSERT_EQ(counter_16, 0);
449  counter_16 >>= 1;
450  ASSERT_EQ(counter_16, 0);
451 }
452 
454 TEST(SatCounterTest, Size32)
455 {
456  const uint32_t bits_32 = 17;
457  const uint32_t max_value_32 = (1 << bits_32) - 1;
458  SatCounter32 counter_32(bits_32);
459 
460  // Increasing
461  counter_32++;
462  ASSERT_EQ(counter_32, 1);
463  counter_32 <<= 1;
464  ASSERT_EQ(counter_32, 2);
465  counter_32 += 2 * max_value_32;
466  ASSERT_EQ(counter_32, max_value_32);
467  counter_32++;
468  ASSERT_EQ(counter_32, max_value_32);
469  counter_32 <<= 1;
470  ASSERT_EQ(counter_32, max_value_32);
471 
472  // Decreasing
473  counter_32--;
474  ASSERT_EQ(counter_32, max_value_32 - 1);
475  counter_32 >>= 1;
476  ASSERT_EQ(counter_32, (max_value_32 - 1) >> 1);
477  counter_32 -= 2 * max_value_32;
478  ASSERT_EQ(counter_32, 0);
479  counter_32--;
480  ASSERT_EQ(counter_32, 0);
481  counter_32 >>= 1;
482  ASSERT_EQ(counter_32, 0);
483 }
484 
486 TEST(SatCounterTest, Size64)
487 {
488  const uint64_t bits_64 = 33;
489  const uint64_t max_value_64 = (1ULL << bits_64) - 1;
490  SatCounter64 counter_64(bits_64);
491 
492  // Increasing
493  counter_64++;
494  ASSERT_EQ(counter_64, 1);
495  counter_64 <<= 1;
496  ASSERT_EQ(counter_64, 2);
497  counter_64 += max_value_64;
498  ASSERT_EQ(counter_64, max_value_64);
499  counter_64++;
500  ASSERT_EQ(counter_64, max_value_64);
501  counter_64 <<= 1;
502  ASSERT_EQ(counter_64, max_value_64);
503 
504  // Decreasing
505  counter_64--;
506  ASSERT_EQ(counter_64, max_value_64 - 1);
507  counter_64 >>= 1;
508  ASSERT_EQ(counter_64, (max_value_64 - 1) >> 1);
509  counter_64 -= max_value_64;
510  ASSERT_EQ(counter_64, 0);
511  counter_64--;
512  ASSERT_EQ(counter_64, 0);
513  counter_64 >>= 1;
514  ASSERT_EQ(counter_64, 0);
515 }
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::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:66
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::GenericSatCounter::saturate
uint8_t saturate()
Saturate the counter.
Definition: sat_counter.hh:321
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: decoder.cc:40

Generated on Tue Sep 21 2021 12:24:57 for gem5 by doxygen 1.8.17