Daniel Carvalho has submitted this change and it was merged. ( https://gem5-review.googlesource.com/c/public/gem5/+/17996 )

Change subject: base: Add operators to SatCounter
......................................................................

base: Add operators to SatCounter

Add shift, add and subtract assignment operators, as well as
copy and move constructor and assignments to SatCounter, so
that it they can be used by the prefetchers.

Also add extra useful functions to calculate saturation
oercentile so that the instantiator does not need to be aware
of the counter's maximum value.

Change-Id: I61d0cb28c8375b9d2774a39011e4a0aa6fe9ccb7
Signed-off-by: Daniel <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17996
Tested-by: kokoro <[email protected]>
Reviewed-by: Jason Lowe-Power <[email protected]>
Maintainer: Jason Lowe-Power <[email protected]>
---
M src/base/sat_counter.hh
M src/base/sat_counter.test.cc
2 files changed, 287 insertions(+), 0 deletions(-)

Approvals:
  Jason Lowe-Power: 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 342a338..3de9486 100644
--- a/src/base/sat_counter.hh
+++ b/src/base/sat_counter.hh
@@ -56,6 +56,9 @@
 class SatCounter
 {
   public:
+    /** The default constructor should never be used. */
+    SatCounter() = delete;
+
     /**
      * Constructor for the counter. The explicit keyword is used to make
      * sure the user does not assign a number to the counter thinking it
@@ -75,6 +78,58 @@
                  "Saturating counter's Initial value exceeds max value.");
     }

+    /** Copy constructor. */
+    SatCounter(const SatCounter& other)
+        : initialVal(other.initialVal), maxVal(other.maxVal),
+          counter(other.counter)
+    {
+    }
+
+    /** Copy assignment. */
+    SatCounter& operator=(const SatCounter& other) {
+        if (this != &other) {
+            SatCounter temp(other);
+            this->swap(temp);
+        }
+        return *this;
+    }
+
+    /** Move constructor. */
+    SatCounter(SatCounter&& other)
+    {
+        initialVal = other.initialVal;
+        maxVal = other.maxVal;
+        counter = other.counter;
+        SatCounter temp(0);
+        other.swap(temp);
+    }
+
+    /** Move assignment. */
+    SatCounter& operator=(SatCounter&& other) {
+        if (this != &other) {
+            initialVal = other.initialVal;
+            maxVal = other.maxVal;
+            counter = other.counter;
+            SatCounter temp(0);
+            other.swap(temp);
+        }
+        return *this;
+    }
+
+    /**
+     * Swap the contents of every member of the class. Used for the default
+     * copy-assignment created by the compiler.
+     *
+     * @param other The other object to swap contents with.
+     */
+    void
+    swap(SatCounter& other)
+    {
+        std::swap(initialVal, other.initialVal);
+        std::swap(maxVal, other.maxVal);
+        std::swap(counter, other.counter);
+    }
+
     /** Pre-increment operator. */
     SatCounter&
     operator++()
@@ -113,6 +168,49 @@
         return old_counter;
     }

+    /** Shift-right-assignment. */
+    SatCounter&
+    operator>>=(const int& shift)
+    {
+        this->counter >>= shift;
+        return *this;
+    }
+
+    /** Shift-left-assignment. */
+    SatCounter&
+    operator<<=(const int& shift)
+    {
+        this->counter <<= shift;
+        if (this->counter > maxVal) {
+            this->counter = maxVal;
+        }
+        return *this;
+    }
+
+    /** Add-assignment. */
+    SatCounter&
+    operator+=(const int& value)
+    {
+        if (maxVal - this->counter >= value) {
+            this->counter += value;
+        } else {
+            this->counter = maxVal;
+        }
+        return *this;
+    }
+
+    /** Subtract-assignment. */
+    SatCounter&
+    operator-=(const int& value)
+    {
+        if (this->counter > value) {
+            this->counter -= value;
+        } else {
+            this->counter = 0;
+        }
+        return *this;
+    }
+
     /**
      * Read the counter's value.
      */
@@ -121,6 +219,22 @@
     /** Reset the counter to its initial value. */
     void reset() { counter = initialVal; }

+    /**
+     * Calculate saturation percentile of the current counter's value
+     * with regard to its maximum possible value.
+     *
+     * @return A value between 0.0 and 1.0 to indicate which percentile of
+     *         the maximum value the current value is.
+     */
+    double calcSaturation() const { return (double) counter / maxVal; }
+
+    /**
+     * Whether the counter has achieved its maximum value or not.
+     *
+     * @return True if the counter saturated.
+     */
+    bool isSaturated() const { return counter == maxVal; }
+
   private:
     uint8_t initialVal;
     uint8_t maxVal;
diff --git a/src/base/sat_counter.test.cc b/src/base/sat_counter.test.cc
index efc79e0..dbdaf0a 100644
--- a/src/base/sat_counter.test.cc
+++ b/src/base/sat_counter.test.cc
@@ -30,6 +30,8 @@

 #include <gtest/gtest.h>

+#include <utility>
+
 #include "base/sat_counter.hh"

 /**
@@ -78,6 +80,23 @@
 }

 /**
+ * Test calculating saturation percentile.
+ */
+TEST(SatCounterTest, SaturationPercentile)
+{
+    const unsigned bits = 3;
+    const unsigned max_value = (1 << bits) - 1;
+    SatCounter counter(bits);
+
+    ASSERT_FALSE(counter.isSaturated());
+    for (double value = 0.0; value <= max_value; value++, counter++) {
+        const double saturation = value / max_value;
+        ASSERT_DOUBLE_EQ(counter.calcSaturation(), saturation);
+    }
+    ASSERT_TRUE(counter.isSaturated());
+}
+
+/**
  * Test back and forth against an int.
  */
 TEST(SatCounterTest, IntComparison)
@@ -102,6 +121,55 @@
 }

 /**
+ * Test shift operators.
+ */
+TEST(SatCounterTest, Shift)
+{
+    const unsigned bits = 3;
+    const unsigned max_value = (1 << bits) - 1;
+    const unsigned initial_value = 1;
+    SatCounter counter(bits, initial_value);
+    SatCounter other(bits, initial_value);
+    // The saturated shift value is just enough to saturate, since greater
+    // values could generate undefined behavior
+    SatCounter saturated_counter(bits, bits);
+    int value = initial_value;
+
+    // Test random shifts
+    counter <<= 2;
+    value <<= 2;
+    ASSERT_EQ(counter, value);
+    counter >>= 1;
+    value >>= 1;
+    ASSERT_EQ(counter, value);
+
+    // Test saturation
+    counter <<= bits;
+    ASSERT_EQ(counter, max_value);
+
+    // Test zeroing
+    counter >>= bits;
+    ASSERT_EQ(counter, 0);
+
+    // Test saturation against other saturating counter
+    counter.reset();
+    value = initial_value;
+    counter <<= other;
+    value <<= other;
+    ASSERT_EQ(counter, value);
+    counter <<= saturated_counter;
+    value = max_value;
+    ASSERT_EQ(counter, max_value);
+
+    // Test zeroing against other saturating counter
+    counter >>= other;
+    value >>= other;
+    ASSERT_EQ(counter, value);
+    counter >>= saturated_counter;
+    ASSERT_EQ(counter, 0);
+}
+
+/**
  * Test both pre and post operators.
  */
 TEST(SatCounterTest, PrePostOperators)
@@ -129,3 +197,108 @@
     ASSERT_EQ(counter_pre, 0);
     ASSERT_EQ(counter_post, 0);
 }
+
+/**
+ * Test copy and move for both constructor and assignment.
+ */
+TEST(SatCounterTest, CopyMove)
+{
+    const unsigned bits = 3;
+    const unsigned max_value = (1 << bits) - 1;
+    const unsigned initial_value = 1;
+    SatCounter counter(bits, initial_value);
+    SatCounter deep_copy(1);
+    SatCounter counter_copy(2);
+
+    // Increase counter value so that we can check if the inner counter is
+    // being copied
+    counter++;
+
+    // Copy counter using both the copy constructor and the copy assignment
+    SatCounter counter_copy_constructor(counter);
+    deep_copy = counter_copy = counter;
+    ASSERT_EQ(counter_copy_constructor, initial_value + 1);
+    ASSERT_EQ(counter_copy, initial_value + 1);
+    ASSERT_EQ(deep_copy, initial_value + 1);
+
+    // Make sure max value is the same for all of them, and that modifying
+    // the copies does not modify the original
+    for (int i = 0; i < 2*max_value; i++) {
+        counter_copy_constructor++;
+        counter_copy++;
+        deep_copy++;
+    }
+    ASSERT_EQ(counter, initial_value + 1);
+    ASSERT_EQ(counter_copy_constructor, max_value);
+    ASSERT_EQ(counter_copy, max_value);
+    ASSERT_EQ(deep_copy, max_value);
+
+    // Make sure initial value is the same for all of them
+    counter_copy_constructor.reset();
+    counter_copy.reset();
+    deep_copy.reset();
+    ASSERT_EQ(counter_copy_constructor, initial_value);
+    ASSERT_EQ(counter_copy, initial_value);
+    ASSERT_EQ(deep_copy, initial_value);
+
+    // Now check move
+    SatCounter counter_move_constructor(std::move(counter));
+    ASSERT_EQ(counter, 0);
+    ASSERT_EQ(counter_move_constructor, initial_value + 1);
+
+    SatCounter counter_move(bits);
+    counter_move = std::move(counter_move_constructor);
+    ASSERT_EQ(counter_move_constructor, 0);
+    ASSERT_EQ(counter_move, initial_value + 1);
+}
+
+/**
+ * Test add-assignment and subtract assignment.
+ */
+TEST(SatCounterTest, AddSubAssignment)
+{
+    const unsigned bits = 3;
+    const unsigned max_value = (1 << bits) - 1;
+    SatCounter counter(bits);
+    SatCounter other(bits, 2);
+    SatCounter saturated_counter(bits, max_value);
+    int value = 0;
+
+    // Test add-assignment for a few random values and then saturate
+    counter += 2;
+    value += 2;
+    ASSERT_EQ(counter, value);
+    counter += 3;
+    value += 3;
+    ASSERT_EQ(counter, value);
+    counter += max_value;
+    value = max_value;
+    ASSERT_EQ(counter, value);
+
+    // Test subtract-assignment for a few random values until back to zero
+    counter -= 2;
+    value -= 2;
+    ASSERT_EQ(counter, value);
+    counter -= 3;
+    value -= 3;
+    ASSERT_EQ(counter, value);
+    counter -= max_value;
+    value = 0;
+    ASSERT_EQ(counter, value);
+
+    // Test add-assignment of other saturating counter
+    counter += other;
+    value += other;
+    ASSERT_EQ(counter, value);
+    counter += saturated_counter;
+    value = max_value;
+    ASSERT_EQ(counter, saturated_counter);
+
+    // Test subtract-assignment of other saturating counter
+    counter -= other;
+    value -= other;
+    ASSERT_EQ(counter, value);
+    counter -= saturated_counter;
+    ASSERT_EQ(counter, 0);
+}
+

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

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I61d0cb28c8375b9d2774a39011e4a0aa6fe9ccb7
Gerrit-Change-Number: 17996
Gerrit-PatchSet: 4
Gerrit-Owner: Daniel Carvalho <[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]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to