113960Sodanrc@yahoo.com.br/*
213960Sodanrc@yahoo.com.br * Copyright (c) 2019 Inria
313960Sodanrc@yahoo.com.br * All rights reserved.
413960Sodanrc@yahoo.com.br *
513960Sodanrc@yahoo.com.br * The license below extends only to copyright in the software and shall
613960Sodanrc@yahoo.com.br * not be construed as granting a license to any other intellectual
713960Sodanrc@yahoo.com.br * property including but not limited to intellectual property relating
813960Sodanrc@yahoo.com.br * to a hardware implementation of the functionality of the software
913960Sodanrc@yahoo.com.br * licensed hereunder.  You may use the software subject to the license
1013960Sodanrc@yahoo.com.br * terms below provided that you ensure that this notice is replicated
1113960Sodanrc@yahoo.com.br * unmodified and in its entirety in all distributions of the software,
1213960Sodanrc@yahoo.com.br * modified or unmodified, in source code or in binary form.
1313960Sodanrc@yahoo.com.br *
1413960Sodanrc@yahoo.com.br * Copyright (c) 2005-2006 The Regents of The University of Michigan
1513960Sodanrc@yahoo.com.br * All rights reserved.
1613960Sodanrc@yahoo.com.br *
1713960Sodanrc@yahoo.com.br * Redistribution and use in source and binary forms, with or without
1813960Sodanrc@yahoo.com.br * modification, are permitted provided that the following conditions are
1913960Sodanrc@yahoo.com.br * met: redistributions of source code must retain the above copyright
2013960Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer;
2113960Sodanrc@yahoo.com.br * redistributions in binary form must reproduce the above copyright
2213960Sodanrc@yahoo.com.br * notice, this list of conditions and the following disclaimer in the
2313960Sodanrc@yahoo.com.br * documentation and/or other materials provided with the distribution;
2413960Sodanrc@yahoo.com.br * neither the name of the copyright holders nor the names of its
2513960Sodanrc@yahoo.com.br * contributors may be used to endorse or promote products derived from
2613960Sodanrc@yahoo.com.br * this software without specific prior written permission.
2713960Sodanrc@yahoo.com.br *
2813960Sodanrc@yahoo.com.br * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2913960Sodanrc@yahoo.com.br * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3013960Sodanrc@yahoo.com.br * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3113960Sodanrc@yahoo.com.br * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3213960Sodanrc@yahoo.com.br * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3313960Sodanrc@yahoo.com.br * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3413960Sodanrc@yahoo.com.br * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3513960Sodanrc@yahoo.com.br * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3613960Sodanrc@yahoo.com.br * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3713960Sodanrc@yahoo.com.br * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3813960Sodanrc@yahoo.com.br * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913960Sodanrc@yahoo.com.br *
4013960Sodanrc@yahoo.com.br * Authors: Kevin Lim
4113960Sodanrc@yahoo.com.br *          Daniel Carvalho
4213960Sodanrc@yahoo.com.br */
4313960Sodanrc@yahoo.com.br
4413960Sodanrc@yahoo.com.br#ifndef __BASE_SAT_COUNTER_HH__
4513960Sodanrc@yahoo.com.br#define __BASE_SAT_COUNTER_HH__
4613960Sodanrc@yahoo.com.br
4713960Sodanrc@yahoo.com.br#include <cstdint>
4813960Sodanrc@yahoo.com.br
4913960Sodanrc@yahoo.com.br#include "base/logging.hh"
5013960Sodanrc@yahoo.com.br#include "base/types.hh"
5113960Sodanrc@yahoo.com.br
5213960Sodanrc@yahoo.com.br/**
5313960Sodanrc@yahoo.com.br * Implements an n bit saturating counter and provides methods to
5413960Sodanrc@yahoo.com.br * increment, decrement, and read it.
5513960Sodanrc@yahoo.com.br */
5613960Sodanrc@yahoo.com.brclass SatCounter
5713960Sodanrc@yahoo.com.br{
5813960Sodanrc@yahoo.com.br  public:
5913962Sodanrc@yahoo.com.br    /** The default constructor should never be used. */
6013962Sodanrc@yahoo.com.br    SatCounter() = delete;
6113962Sodanrc@yahoo.com.br
6213960Sodanrc@yahoo.com.br    /**
6313960Sodanrc@yahoo.com.br     * Constructor for the counter. The explicit keyword is used to make
6413960Sodanrc@yahoo.com.br     * sure the user does not assign a number to the counter thinking it
6513960Sodanrc@yahoo.com.br     * will be used as a counter value when it is in fact used as the number
6613960Sodanrc@yahoo.com.br     * of bits.
6713960Sodanrc@yahoo.com.br     *
6813960Sodanrc@yahoo.com.br     * @param bits How many bits the counter will have.
6913960Sodanrc@yahoo.com.br     * @param initial_val Starting value for the counter.
7013960Sodanrc@yahoo.com.br     */
7113960Sodanrc@yahoo.com.br    explicit SatCounter(unsigned bits, uint8_t initial_val = 0)
7213960Sodanrc@yahoo.com.br        : initialVal(initial_val), maxVal((1 << bits) - 1),
7313960Sodanrc@yahoo.com.br          counter(initial_val)
7413960Sodanrc@yahoo.com.br    {
7513960Sodanrc@yahoo.com.br        fatal_if(bits > 8*sizeof(uint8_t),
7613960Sodanrc@yahoo.com.br                 "Number of bits exceeds counter size");
7713960Sodanrc@yahoo.com.br        fatal_if(initial_val > maxVal,
7813960Sodanrc@yahoo.com.br                 "Saturating counter's Initial value exceeds max value.");
7913960Sodanrc@yahoo.com.br    }
8013960Sodanrc@yahoo.com.br
8113962Sodanrc@yahoo.com.br    /** Copy constructor. */
8213962Sodanrc@yahoo.com.br    SatCounter(const SatCounter& other)
8313962Sodanrc@yahoo.com.br        : initialVal(other.initialVal), maxVal(other.maxVal),
8413962Sodanrc@yahoo.com.br          counter(other.counter)
8513962Sodanrc@yahoo.com.br    {
8613962Sodanrc@yahoo.com.br    }
8713962Sodanrc@yahoo.com.br
8813962Sodanrc@yahoo.com.br    /** Copy assignment. */
8913962Sodanrc@yahoo.com.br    SatCounter& operator=(const SatCounter& other) {
9013962Sodanrc@yahoo.com.br        if (this != &other) {
9113962Sodanrc@yahoo.com.br            SatCounter temp(other);
9213962Sodanrc@yahoo.com.br            this->swap(temp);
9313962Sodanrc@yahoo.com.br        }
9413962Sodanrc@yahoo.com.br        return *this;
9513962Sodanrc@yahoo.com.br    }
9613962Sodanrc@yahoo.com.br
9713962Sodanrc@yahoo.com.br    /** Move constructor. */
9813962Sodanrc@yahoo.com.br    SatCounter(SatCounter&& other)
9913962Sodanrc@yahoo.com.br    {
10013962Sodanrc@yahoo.com.br        initialVal = other.initialVal;
10113962Sodanrc@yahoo.com.br        maxVal = other.maxVal;
10213962Sodanrc@yahoo.com.br        counter = other.counter;
10313962Sodanrc@yahoo.com.br        SatCounter temp(0);
10413962Sodanrc@yahoo.com.br        other.swap(temp);
10513962Sodanrc@yahoo.com.br    }
10613962Sodanrc@yahoo.com.br
10713962Sodanrc@yahoo.com.br    /** Move assignment. */
10813962Sodanrc@yahoo.com.br    SatCounter& operator=(SatCounter&& other) {
10913962Sodanrc@yahoo.com.br        if (this != &other) {
11013962Sodanrc@yahoo.com.br            initialVal = other.initialVal;
11113962Sodanrc@yahoo.com.br            maxVal = other.maxVal;
11213962Sodanrc@yahoo.com.br            counter = other.counter;
11313962Sodanrc@yahoo.com.br            SatCounter temp(0);
11413962Sodanrc@yahoo.com.br            other.swap(temp);
11513962Sodanrc@yahoo.com.br        }
11613962Sodanrc@yahoo.com.br        return *this;
11713962Sodanrc@yahoo.com.br    }
11813962Sodanrc@yahoo.com.br
11913962Sodanrc@yahoo.com.br    /**
12013962Sodanrc@yahoo.com.br     * Swap the contents of every member of the class. Used for the default
12113962Sodanrc@yahoo.com.br     * copy-assignment created by the compiler.
12213962Sodanrc@yahoo.com.br     *
12313962Sodanrc@yahoo.com.br     * @param other The other object to swap contents with.
12413962Sodanrc@yahoo.com.br     */
12513962Sodanrc@yahoo.com.br    void
12613962Sodanrc@yahoo.com.br    swap(SatCounter& other)
12713962Sodanrc@yahoo.com.br    {
12813962Sodanrc@yahoo.com.br        std::swap(initialVal, other.initialVal);
12913962Sodanrc@yahoo.com.br        std::swap(maxVal, other.maxVal);
13013962Sodanrc@yahoo.com.br        std::swap(counter, other.counter);
13113962Sodanrc@yahoo.com.br    }
13213962Sodanrc@yahoo.com.br
13313960Sodanrc@yahoo.com.br    /** Pre-increment operator. */
13413960Sodanrc@yahoo.com.br    SatCounter&
13513960Sodanrc@yahoo.com.br    operator++()
13613960Sodanrc@yahoo.com.br    {
13713960Sodanrc@yahoo.com.br        if (counter < maxVal) {
13813960Sodanrc@yahoo.com.br            ++counter;
13913960Sodanrc@yahoo.com.br        }
14013960Sodanrc@yahoo.com.br        return *this;
14113960Sodanrc@yahoo.com.br    }
14213960Sodanrc@yahoo.com.br
14313960Sodanrc@yahoo.com.br    /** Post-increment operator. */
14413960Sodanrc@yahoo.com.br    SatCounter
14513960Sodanrc@yahoo.com.br    operator++(int)
14613960Sodanrc@yahoo.com.br    {
14713960Sodanrc@yahoo.com.br        SatCounter old_counter = *this;
14813960Sodanrc@yahoo.com.br        ++*this;
14913960Sodanrc@yahoo.com.br        return old_counter;
15013960Sodanrc@yahoo.com.br    }
15113960Sodanrc@yahoo.com.br
15213960Sodanrc@yahoo.com.br    /** Pre-decrement operator. */
15313960Sodanrc@yahoo.com.br    SatCounter&
15413960Sodanrc@yahoo.com.br    operator--()
15513960Sodanrc@yahoo.com.br    {
15613960Sodanrc@yahoo.com.br        if (counter > 0) {
15713960Sodanrc@yahoo.com.br            --counter;
15813960Sodanrc@yahoo.com.br        }
15913960Sodanrc@yahoo.com.br        return *this;
16013960Sodanrc@yahoo.com.br    }
16113960Sodanrc@yahoo.com.br
16213960Sodanrc@yahoo.com.br    /** Post-decrement operator. */
16313960Sodanrc@yahoo.com.br    SatCounter
16413960Sodanrc@yahoo.com.br    operator--(int)
16513960Sodanrc@yahoo.com.br    {
16613960Sodanrc@yahoo.com.br        SatCounter old_counter = *this;
16713960Sodanrc@yahoo.com.br        --*this;
16813960Sodanrc@yahoo.com.br        return old_counter;
16913960Sodanrc@yahoo.com.br    }
17013960Sodanrc@yahoo.com.br
17113962Sodanrc@yahoo.com.br    /** Shift-right-assignment. */
17213962Sodanrc@yahoo.com.br    SatCounter&
17313962Sodanrc@yahoo.com.br    operator>>=(const int& shift)
17413962Sodanrc@yahoo.com.br    {
17513962Sodanrc@yahoo.com.br        this->counter >>= shift;
17613962Sodanrc@yahoo.com.br        return *this;
17713962Sodanrc@yahoo.com.br    }
17813962Sodanrc@yahoo.com.br
17913962Sodanrc@yahoo.com.br    /** Shift-left-assignment. */
18013962Sodanrc@yahoo.com.br    SatCounter&
18113962Sodanrc@yahoo.com.br    operator<<=(const int& shift)
18213962Sodanrc@yahoo.com.br    {
18313962Sodanrc@yahoo.com.br        this->counter <<= shift;
18413962Sodanrc@yahoo.com.br        if (this->counter > maxVal) {
18513962Sodanrc@yahoo.com.br            this->counter = maxVal;
18613962Sodanrc@yahoo.com.br        }
18713962Sodanrc@yahoo.com.br        return *this;
18813962Sodanrc@yahoo.com.br    }
18913962Sodanrc@yahoo.com.br
19013962Sodanrc@yahoo.com.br    /** Add-assignment. */
19113962Sodanrc@yahoo.com.br    SatCounter&
19213962Sodanrc@yahoo.com.br    operator+=(const int& value)
19313962Sodanrc@yahoo.com.br    {
19413962Sodanrc@yahoo.com.br        if (maxVal - this->counter >= value) {
19513962Sodanrc@yahoo.com.br            this->counter += value;
19613962Sodanrc@yahoo.com.br        } else {
19713962Sodanrc@yahoo.com.br            this->counter = maxVal;
19813962Sodanrc@yahoo.com.br        }
19913962Sodanrc@yahoo.com.br        return *this;
20013962Sodanrc@yahoo.com.br    }
20113962Sodanrc@yahoo.com.br
20213962Sodanrc@yahoo.com.br    /** Subtract-assignment. */
20313962Sodanrc@yahoo.com.br    SatCounter&
20413962Sodanrc@yahoo.com.br    operator-=(const int& value)
20513962Sodanrc@yahoo.com.br    {
20613962Sodanrc@yahoo.com.br        if (this->counter > value) {
20713962Sodanrc@yahoo.com.br            this->counter -= value;
20813962Sodanrc@yahoo.com.br        } else {
20913962Sodanrc@yahoo.com.br            this->counter = 0;
21013962Sodanrc@yahoo.com.br        }
21113962Sodanrc@yahoo.com.br        return *this;
21213962Sodanrc@yahoo.com.br    }
21313962Sodanrc@yahoo.com.br
21413960Sodanrc@yahoo.com.br    /**
21513960Sodanrc@yahoo.com.br     * Read the counter's value.
21613960Sodanrc@yahoo.com.br     */
21713960Sodanrc@yahoo.com.br    operator uint8_t() const { return counter; }
21813960Sodanrc@yahoo.com.br
21913960Sodanrc@yahoo.com.br    /** Reset the counter to its initial value. */
22013960Sodanrc@yahoo.com.br    void reset() { counter = initialVal; }
22113960Sodanrc@yahoo.com.br
22213962Sodanrc@yahoo.com.br    /**
22313962Sodanrc@yahoo.com.br     * Calculate saturation percentile of the current counter's value
22413962Sodanrc@yahoo.com.br     * with regard to its maximum possible value.
22513962Sodanrc@yahoo.com.br     *
22613962Sodanrc@yahoo.com.br     * @return A value between 0.0 and 1.0 to indicate which percentile of
22713962Sodanrc@yahoo.com.br     *         the maximum value the current value is.
22813962Sodanrc@yahoo.com.br     */
22913962Sodanrc@yahoo.com.br    double calcSaturation() const { return (double) counter / maxVal; }
23013962Sodanrc@yahoo.com.br
23113962Sodanrc@yahoo.com.br    /**
23213962Sodanrc@yahoo.com.br     * Whether the counter has achieved its maximum value or not.
23313962Sodanrc@yahoo.com.br     *
23413962Sodanrc@yahoo.com.br     * @return True if the counter saturated.
23513962Sodanrc@yahoo.com.br     */
23613962Sodanrc@yahoo.com.br    bool isSaturated() const { return counter == maxVal; }
23713962Sodanrc@yahoo.com.br
23814210Sodanrc@yahoo.com.br    /**
23914210Sodanrc@yahoo.com.br     * Saturate the counter.
24014210Sodanrc@yahoo.com.br     *
24114210Sodanrc@yahoo.com.br     * @return The value added to the counter to reach saturation.
24214210Sodanrc@yahoo.com.br     */
24314210Sodanrc@yahoo.com.br    uint8_t saturate()
24414210Sodanrc@yahoo.com.br    {
24514210Sodanrc@yahoo.com.br        const uint8_t diff = maxVal - counter;
24614210Sodanrc@yahoo.com.br        counter = maxVal;
24714210Sodanrc@yahoo.com.br        return diff;
24814210Sodanrc@yahoo.com.br    }
24914210Sodanrc@yahoo.com.br
25013960Sodanrc@yahoo.com.br  private:
25113960Sodanrc@yahoo.com.br    uint8_t initialVal;
25213960Sodanrc@yahoo.com.br    uint8_t maxVal;
25313960Sodanrc@yahoo.com.br    uint8_t counter;
25413960Sodanrc@yahoo.com.br};
25513960Sodanrc@yahoo.com.br
25613960Sodanrc@yahoo.com.br#endif // __BASE_SAT_COUNTER_HH__
257