Daniel Carvalho has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/37135 )

Change subject: base: Templatize SatCounter
......................................................................

base: Templatize SatCounter

Allow SatCounter to have larger unsigned types to accomodate
larger counters.

The template decision was taken because some predictors will
generate huge arrays of small counters, so smaller types will
lessen their overhead; however, isolated counters may require
any counter size.

Jira: https://gem5.atlassian.net/browse/GEM5-813

Change-Id: I5475a565ea7b97d1dfc176fa9d7cf827560fbe39
Signed-off-by: Daniel R. Carvalho <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/37135
Reviewed-by: Bobby R. Bruce <[email protected]>
Maintainer: Bobby R. Bruce <[email protected]>
Tested-by: kokoro <[email protected]>
---
M src/base/sat_counter.hh
M src/base/sat_counter.test.cc
2 files changed, 140 insertions(+), 30 deletions(-)

Approvals:
  Bobby R. Bruce: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/base/sat_counter.hh b/src/base/sat_counter.hh
index d257cda..4849c2a 100644
--- a/src/base/sat_counter.hh
+++ b/src/base/sat_counter.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Inria
+ * Copyright (c) 2019, 2020 Inria
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -50,12 +50,15 @@
 /**
  * Implements an n bit saturating counter and provides methods to
  * increment, decrement, and read it.
+ *
+ * @tparam T The type of the underlying counter container.
  */
-class SatCounter
+template <class T>
+class GenericSatCounter
 {
   public:
     /** The default constructor should never be used. */
-    SatCounter() = delete;
+    GenericSatCounter() = delete;

     /**
      * Constructor for the counter. The explicit keyword is used to make
@@ -68,11 +71,11 @@
      *
      * @ingroup api_sat_counter
      */
-    explicit SatCounter(unsigned bits, uint8_t initial_val = 0)
-        : initialVal(initial_val), maxVal((1 << bits) - 1),
+    explicit GenericSatCounter(unsigned bits, T initial_val = 0)
+        : initialVal(initial_val), maxVal((1ULL << bits) - 1),
           counter(initial_val)
     {
-        fatal_if(bits > 8*sizeof(uint8_t),
+        fatal_if(bits > 8*sizeof(T),
                  "Number of bits exceeds counter size");
         fatal_if(initial_val > maxVal,
                  "Saturating counter's Initial value exceeds max value.");
@@ -83,7 +86,7 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter(const SatCounter& other)
+    GenericSatCounter(const GenericSatCounter& other)
         : initialVal(other.initialVal), maxVal(other.maxVal),
           counter(other.counter)
     {
@@ -94,9 +97,9 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter& operator=(const SatCounter& other) {
+    GenericSatCounter& operator=(const GenericSatCounter& other) {
         if (this != &other) {
-            SatCounter temp(other);
+            GenericSatCounter temp(other);
             this->swap(temp);
         }
         return *this;
@@ -107,12 +110,12 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter(SatCounter&& other)
+    GenericSatCounter(GenericSatCounter&& other)
     {
         initialVal = other.initialVal;
         maxVal = other.maxVal;
         counter = other.counter;
-        SatCounter temp(0);
+        GenericSatCounter temp(0);
         other.swap(temp);
     }

@@ -121,12 +124,12 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter& operator=(SatCounter&& other) {
+    GenericSatCounter& operator=(GenericSatCounter&& other) {
         if (this != &other) {
             initialVal = other.initialVal;
             maxVal = other.maxVal;
             counter = other.counter;
-            SatCounter temp(0);
+            GenericSatCounter temp(0);
             other.swap(temp);
         }
         return *this;
@@ -141,7 +144,7 @@
      * @ingroup api_sat_counter
      */
     void
-    swap(SatCounter& other)
+    swap(GenericSatCounter& other)
     {
         std::swap(initialVal, other.initialVal);
         std::swap(maxVal, other.maxVal);
@@ -153,7 +156,7 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
+    GenericSatCounter&
     operator++()
     {
         if (counter < maxVal) {
@@ -167,10 +170,10 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter
+    GenericSatCounter
     operator++(int)
     {
-        SatCounter old_counter = *this;
+        GenericSatCounter old_counter = *this;
         ++*this;
         return old_counter;
     }
@@ -180,7 +183,7 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
+    GenericSatCounter&
     operator--()
     {
         if (counter > 0) {
@@ -194,10 +197,10 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter
+    GenericSatCounter
     operator--(int)
     {
-        SatCounter old_counter = *this;
+        GenericSatCounter old_counter = *this;
         --*this;
         return old_counter;
     }
@@ -207,7 +210,7 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
+    GenericSatCounter&
     operator>>=(const int& shift)
     {
         assert(shift >= 0);
@@ -220,7 +223,7 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
+    GenericSatCounter&
     operator<<=(const int& shift)
     {
         assert(shift >= 0);
@@ -236,8 +239,8 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
-    operator+=(const int& value)
+    GenericSatCounter&
+    operator+=(const long long& value)
     {
         if (value >= 0) {
             if (maxVal - this->counter >= value) {
@@ -256,8 +259,8 @@
      *
      * @ingroup api_sat_counter
      */
-    SatCounter&
-    operator-=(const int& value)
+    GenericSatCounter&
+    operator-=(const long long& value)
     {
         if (value >= 0) {
             if (this->counter > value) {
@@ -276,7 +279,7 @@
      *
      * @ingroup api_sat_counter
      */
-    operator uint8_t() const { return counter; }
+    operator T() const { return counter; }

     /**
      * Reset the counter to its initial value.
@@ -320,9 +323,21 @@
     }

   private:
-    uint8_t initialVal;
-    uint8_t maxVal;
-    uint8_t counter;
+    T initialVal;
+    T maxVal;
+    T counter;
 };

+/** @ingroup api_sat_counter
+ *  @{
+ */
+typedef GenericSatCounter<uint8_t> SatCounter8;
+typedef GenericSatCounter<uint16_t> SatCounter16;
+typedef GenericSatCounter<uint32_t> SatCounter32;
+typedef GenericSatCounter<uint64_t> SatCounter64;
+/** @} */
+
+[[deprecated("Use SatCounter8 (or variants) instead")]]
+typedef SatCounter8 SatCounter;
+
 #endif // __BASE_SAT_COUNTER_HH__
diff --git a/src/base/sat_counter.test.cc b/src/base/sat_counter.test.cc
index 214b015..4d400c0 100644
--- a/src/base/sat_counter.test.cc
+++ b/src/base/sat_counter.test.cc
@@ -360,3 +360,98 @@
     ASSERT_EQ(counter, value);
 }

+/** Test max and min when using SatCounter16. */
+TEST(SatCounterTest, Size16)
+{
+    const uint16_t bits_16 = 9;
+    const uint16_t max_value_16 = (1 << bits_16) - 1;
+    SatCounter16 counter_16(bits_16);
+
+    // Increasing
+    counter_16++;
+    ASSERT_EQ(counter_16, 1);
+    counter_16 <<= 1;
+    ASSERT_EQ(counter_16, 2);
+    counter_16 += 2 * max_value_16;
+    ASSERT_EQ(counter_16, max_value_16);
+    counter_16++;
+    ASSERT_EQ(counter_16, max_value_16);
+    counter_16 <<= 1;
+    ASSERT_EQ(counter_16, max_value_16);
+
+    // Decreasing
+    counter_16--;
+    ASSERT_EQ(counter_16, max_value_16 - 1);
+    counter_16 >>= 1;
+    ASSERT_EQ(counter_16, (max_value_16 - 1) >> 1);
+    counter_16 -= 2 * max_value_16;
+    ASSERT_EQ(counter_16, 0);
+    counter_16--;
+    ASSERT_EQ(counter_16, 0);
+    counter_16 >>= 1;
+    ASSERT_EQ(counter_16, 0);
+}
+
+/** Test max and min when using SatCounter32. */
+TEST(SatCounterTest, Size32)
+{
+    const uint32_t bits_32 = 17;
+    const uint32_t max_value_32 = (1 << bits_32) - 1;
+    SatCounter32 counter_32(bits_32);
+
+    // Increasing
+    counter_32++;
+    ASSERT_EQ(counter_32, 1);
+    counter_32 <<= 1;
+    ASSERT_EQ(counter_32, 2);
+    counter_32 += 2 * max_value_32;
+    ASSERT_EQ(counter_32, max_value_32);
+    counter_32++;
+    ASSERT_EQ(counter_32, max_value_32);
+    counter_32 <<= 1;
+    ASSERT_EQ(counter_32, max_value_32);
+
+    // Decreasing
+    counter_32--;
+    ASSERT_EQ(counter_32, max_value_32 - 1);
+    counter_32 >>= 1;
+    ASSERT_EQ(counter_32, (max_value_32 - 1) >> 1);
+    counter_32 -= 2 * max_value_32;
+    ASSERT_EQ(counter_32, 0);
+    counter_32--;
+    ASSERT_EQ(counter_32, 0);
+    counter_32 >>= 1;
+    ASSERT_EQ(counter_32, 0);
+}
+
+/** Test max and min when using SatCounter64. */
+TEST(SatCounterTest, Size64)
+{
+    const uint64_t bits_64 = 33;
+    const uint64_t max_value_64 = (1ULL << bits_64) - 1;
+    SatCounter64 counter_64(bits_64);
+
+    // Increasing
+    counter_64++;
+    ASSERT_EQ(counter_64, 1);
+    counter_64 <<= 1;
+    ASSERT_EQ(counter_64, 2);
+    counter_64 += max_value_64;
+    ASSERT_EQ(counter_64, max_value_64);
+    counter_64++;
+    ASSERT_EQ(counter_64, max_value_64);
+    counter_64 <<= 1;
+    ASSERT_EQ(counter_64, max_value_64);
+
+    // Decreasing
+    counter_64--;
+    ASSERT_EQ(counter_64, max_value_64 - 1);
+    counter_64 >>= 1;
+    ASSERT_EQ(counter_64, (max_value_64 - 1) >> 1);
+    counter_64 -= max_value_64;
+    ASSERT_EQ(counter_64, 0);
+    counter_64--;
+    ASSERT_EQ(counter_64, 0);
+    counter_64 >>= 1;
+    ASSERT_EQ(counter_64, 0);
+}

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/37135
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I5475a565ea7b97d1dfc176fa9d7cf827560fbe39
Gerrit-Change-Number: 37135
Gerrit-PatchSet: 4
Gerrit-Owner: Daniel Carvalho <[email protected]>
Gerrit-Reviewer: Bobby R. Bruce <[email protected]>
Gerrit-Reviewer: Daniel Carvalho <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to