sat_counter.hh revision 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 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 250 private: 251 uint8_t initialVal; 252 uint8_t maxVal; 253 uint8_t counter; 254}; 255 256#endif // __BASE_SAT_COUNTER_HH__ 257