sat_counter.hh (13962:9c1c64414fb7) sat_counter.hh (14210:8f7626532f4d)
1/*
2 * Copyright (c) 2019 Inria
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2005-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Daniel Carvalho
42 */
43
44#ifndef __BASE_SAT_COUNTER_HH__
45#define __BASE_SAT_COUNTER_HH__
46
47#include <cstdint>
48
49#include "base/logging.hh"
50#include "base/types.hh"
51
52/**
53 * Implements an n bit saturating counter and provides methods to
54 * increment, decrement, and read it.
55 */
56class SatCounter
57{
58 public:
59 /** The default constructor should never be used. */
60 SatCounter() = delete;
61
62 /**
63 * Constructor for the counter. The explicit keyword is used to make
64 * sure the user does not assign a number to the counter thinking it
65 * will be used as a counter value when it is in fact used as the number
66 * of bits.
67 *
68 * @param bits How many bits the counter will have.
69 * @param initial_val Starting value for the counter.
70 */
71 explicit SatCounter(unsigned bits, uint8_t initial_val = 0)
72 : initialVal(initial_val), maxVal((1 << bits) - 1),
73 counter(initial_val)
74 {
75 fatal_if(bits > 8*sizeof(uint8_t),
76 "Number of bits exceeds counter size");
77 fatal_if(initial_val > maxVal,
78 "Saturating counter's Initial value exceeds max value.");
79 }
80
81 /** Copy constructor. */
82 SatCounter(const SatCounter& other)
83 : initialVal(other.initialVal), maxVal(other.maxVal),
84 counter(other.counter)
85 {
86 }
87
88 /** Copy assignment. */
89 SatCounter& operator=(const SatCounter& other) {
90 if (this != &other) {
91 SatCounter temp(other);
92 this->swap(temp);
93 }
94 return *this;
95 }
96
97 /** Move constructor. */
98 SatCounter(SatCounter&& other)
99 {
100 initialVal = other.initialVal;
101 maxVal = other.maxVal;
102 counter = other.counter;
103 SatCounter temp(0);
104 other.swap(temp);
105 }
106
107 /** Move assignment. */
108 SatCounter& operator=(SatCounter&& other) {
109 if (this != &other) {
110 initialVal = other.initialVal;
111 maxVal = other.maxVal;
112 counter = other.counter;
113 SatCounter temp(0);
114 other.swap(temp);
115 }
116 return *this;
117 }
118
119 /**
120 * Swap the contents of every member of the class. Used for the default
121 * copy-assignment created by the compiler.
122 *
123 * @param other The other object to swap contents with.
124 */
125 void
126 swap(SatCounter& other)
127 {
128 std::swap(initialVal, other.initialVal);
129 std::swap(maxVal, other.maxVal);
130 std::swap(counter, other.counter);
131 }
132
133 /** Pre-increment operator. */
134 SatCounter&
135 operator++()
136 {
137 if (counter < maxVal) {
138 ++counter;
139 }
140 return *this;
141 }
142
143 /** Post-increment operator. */
144 SatCounter
145 operator++(int)
146 {
147 SatCounter old_counter = *this;
148 ++*this;
149 return old_counter;
150 }
151
152 /** Pre-decrement operator. */
153 SatCounter&
154 operator--()
155 {
156 if (counter > 0) {
157 --counter;
158 }
159 return *this;
160 }
161
162 /** Post-decrement operator. */
163 SatCounter
164 operator--(int)
165 {
166 SatCounter old_counter = *this;
167 --*this;
168 return old_counter;
169 }
170
171 /** Shift-right-assignment. */
172 SatCounter&
173 operator>>=(const int& shift)
174 {
175 this->counter >>= shift;
176 return *this;
177 }
178
179 /** Shift-left-assignment. */
180 SatCounter&
181 operator<<=(const int& shift)
182 {
183 this->counter <<= shift;
184 if (this->counter > maxVal) {
185 this->counter = maxVal;
186 }
187 return *this;
188 }
189
190 /** Add-assignment. */
191 SatCounter&
192 operator+=(const int& value)
193 {
194 if (maxVal - this->counter >= value) {
195 this->counter += value;
196 } else {
197 this->counter = maxVal;
198 }
199 return *this;
200 }
201
202 /** Subtract-assignment. */
203 SatCounter&
204 operator-=(const int& value)
205 {
206 if (this->counter > value) {
207 this->counter -= value;
208 } else {
209 this->counter = 0;
210 }
211 return *this;
212 }
213
214 /**
215 * Read the counter's value.
216 */
217 operator uint8_t() const { return counter; }
218
219 /** Reset the counter to its initial value. */
220 void reset() { counter = initialVal; }
221
222 /**
223 * Calculate saturation percentile of the current counter's value
224 * with regard to its maximum possible value.
225 *
226 * @return A value between 0.0 and 1.0 to indicate which percentile of
227 * the maximum value the current value is.
228 */
229 double calcSaturation() const { return (double) counter / maxVal; }
230
231 /**
232 * Whether the counter has achieved its maximum value or not.
233 *
234 * @return True if the counter saturated.
235 */
236 bool isSaturated() const { return counter == maxVal; }
237
1/*
2 * Copyright (c) 2019 Inria
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2005-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Daniel Carvalho
42 */
43
44#ifndef __BASE_SAT_COUNTER_HH__
45#define __BASE_SAT_COUNTER_HH__
46
47#include <cstdint>
48
49#include "base/logging.hh"
50#include "base/types.hh"
51
52/**
53 * Implements an n bit saturating counter and provides methods to
54 * increment, decrement, and read it.
55 */
56class SatCounter
57{
58 public:
59 /** The default constructor should never be used. */
60 SatCounter() = delete;
61
62 /**
63 * Constructor for the counter. The explicit keyword is used to make
64 * sure the user does not assign a number to the counter thinking it
65 * will be used as a counter value when it is in fact used as the number
66 * of bits.
67 *
68 * @param bits How many bits the counter will have.
69 * @param initial_val Starting value for the counter.
70 */
71 explicit SatCounter(unsigned bits, uint8_t initial_val = 0)
72 : initialVal(initial_val), maxVal((1 << bits) - 1),
73 counter(initial_val)
74 {
75 fatal_if(bits > 8*sizeof(uint8_t),
76 "Number of bits exceeds counter size");
77 fatal_if(initial_val > maxVal,
78 "Saturating counter's Initial value exceeds max value.");
79 }
80
81 /** Copy constructor. */
82 SatCounter(const SatCounter& other)
83 : initialVal(other.initialVal), maxVal(other.maxVal),
84 counter(other.counter)
85 {
86 }
87
88 /** Copy assignment. */
89 SatCounter& operator=(const SatCounter& other) {
90 if (this != &other) {
91 SatCounter temp(other);
92 this->swap(temp);
93 }
94 return *this;
95 }
96
97 /** Move constructor. */
98 SatCounter(SatCounter&& other)
99 {
100 initialVal = other.initialVal;
101 maxVal = other.maxVal;
102 counter = other.counter;
103 SatCounter temp(0);
104 other.swap(temp);
105 }
106
107 /** Move assignment. */
108 SatCounter& operator=(SatCounter&& other) {
109 if (this != &other) {
110 initialVal = other.initialVal;
111 maxVal = other.maxVal;
112 counter = other.counter;
113 SatCounter temp(0);
114 other.swap(temp);
115 }
116 return *this;
117 }
118
119 /**
120 * Swap the contents of every member of the class. Used for the default
121 * copy-assignment created by the compiler.
122 *
123 * @param other The other object to swap contents with.
124 */
125 void
126 swap(SatCounter& other)
127 {
128 std::swap(initialVal, other.initialVal);
129 std::swap(maxVal, other.maxVal);
130 std::swap(counter, other.counter);
131 }
132
133 /** Pre-increment operator. */
134 SatCounter&
135 operator++()
136 {
137 if (counter < maxVal) {
138 ++counter;
139 }
140 return *this;
141 }
142
143 /** Post-increment operator. */
144 SatCounter
145 operator++(int)
146 {
147 SatCounter old_counter = *this;
148 ++*this;
149 return old_counter;
150 }
151
152 /** Pre-decrement operator. */
153 SatCounter&
154 operator--()
155 {
156 if (counter > 0) {
157 --counter;
158 }
159 return *this;
160 }
161
162 /** Post-decrement operator. */
163 SatCounter
164 operator--(int)
165 {
166 SatCounter old_counter = *this;
167 --*this;
168 return old_counter;
169 }
170
171 /** Shift-right-assignment. */
172 SatCounter&
173 operator>>=(const int& shift)
174 {
175 this->counter >>= shift;
176 return *this;
177 }
178
179 /** Shift-left-assignment. */
180 SatCounter&
181 operator<<=(const int& shift)
182 {
183 this->counter <<= shift;
184 if (this->counter > maxVal) {
185 this->counter = maxVal;
186 }
187 return *this;
188 }
189
190 /** Add-assignment. */
191 SatCounter&
192 operator+=(const int& value)
193 {
194 if (maxVal - this->counter >= value) {
195 this->counter += value;
196 } else {
197 this->counter = maxVal;
198 }
199 return *this;
200 }
201
202 /** Subtract-assignment. */
203 SatCounter&
204 operator-=(const int& value)
205 {
206 if (this->counter > value) {
207 this->counter -= value;
208 } else {
209 this->counter = 0;
210 }
211 return *this;
212 }
213
214 /**
215 * Read the counter's value.
216 */
217 operator uint8_t() const { return counter; }
218
219 /** Reset the counter to its initial value. */
220 void reset() { counter = initialVal; }
221
222 /**
223 * Calculate saturation percentile of the current counter's value
224 * with regard to its maximum possible value.
225 *
226 * @return A value between 0.0 and 1.0 to indicate which percentile of
227 * the maximum value the current value is.
228 */
229 double calcSaturation() const { return (double) counter / maxVal; }
230
231 /**
232 * Whether the counter has achieved its maximum value or not.
233 *
234 * @return True if the counter saturated.
235 */
236 bool isSaturated() const { return counter == maxVal; }
237
238 /**
239 * Saturate the counter.
240 *
241 * @return The value added to the counter to reach saturation.
242 */
243 uint8_t saturate()
244 {
245 const uint8_t diff = maxVal - counter;
246 counter = maxVal;
247 return diff;
248 }
249
238 private:
239 uint8_t initialVal;
240 uint8_t maxVal;
241 uint8_t counter;
242};
243
244#endif // __BASE_SAT_COUNTER_HH__
250 private:
251 uint8_t initialVal;
252 uint8_t maxVal;
253 uint8_t counter;
254};
255
256#endif // __BASE_SAT_COUNTER_HH__