blob: 1d7d640ddb05deba6cc3a439cb66613759e85ffe [file] [log] [blame]
/*
* Copyright (c) 2021 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __BASE_STATS_UNITS_HH__
#define __BASE_STATS_UNITS_HH__
#include <type_traits>
#include "base/compiler.hh"
#include "base/cprintf.hh"
namespace gem5
{
/**
* Convenience macros to declare the unit of a stat.
*/
#define UNIT_CYCLE GEM5_DEPRECATED_MACRO( \
UNIT_CYCLE, statistics::units::Cycle::get(), \
"Use statistics::units::Cycle::get()")
#define UNIT_TICK GEM5_DEPRECATED_MACRO( \
UNIT_TICK, statistics::units::Tick::get(), "Use statistics::units::Tick::get()")
#define UNIT_SECOND GEM5_DEPRECATED_MACRO( \
UNIT_SECOND, statistics::units::Second::get(), \
"Use statistics::units::Second::get()")
#define UNIT_BIT GEM5_DEPRECATED_MACRO( \
UNIT_BIT, statistics::units::Bit::get(), "Use statistics::units::Bit::get()")
#define UNIT_BYTE GEM5_DEPRECATED_MACRO( \
UNIT_BYTE, statistics::units::Byte::get(), "Use statistics::units::Byte::get()")
#define UNIT_JOULE GEM5_DEPRECATED_MACRO( \
UNIT_JOULE, statistics::units::Joule::get(), \
"Use statistics::units::Joule::get()")
#define UNIT_VOLT GEM5_DEPRECATED_MACRO( \
UNIT_VOLD, statistics::units::Volt::get(), "Use statistics::units::Volt::get()")
#define UNIT_CELSIUS GEM5_DEPRECATED_MACRO( \
UNIT_CELSIUS, statistics::units::DegreeCelsius::get(), \
"Use statistics::units::DegreeCelsius::get()")
#define UNIT_RATE(T1, T2) GEM5_DEPRECATED_MACRO( \
UNIT_RATE, (statistics::units::Rate<T1, T2>::get()), \
"Use statistics::units::Rate<T1, T2>::get()")
#define UNIT_RATIO GEM5_DEPRECATED_MACRO( \
UNIT_RATIO, statistics::units::Ratio::get(), \
"Use statistics::units::Ratio::get()")
#define UNIT_COUNT GEM5_DEPRECATED_MACRO( \
UNIT_COUNT, statistics::units::Count::get(), \
"Use statistics::units::Count::get()")
#define UNIT_WATT GEM5_DEPRECATED_MACRO( \
UNIT_WATT, statistics::units::Watt::get(), "Use statistics::units::Watt::get()")
#define UNIT_UNSPECIFIED GEM5_DEPRECATED_MACRO( \
UNIT_UNSPECIFIED, statistics::units::Unspecified::get(), \
"Use statistics::units::Unspecified::get()")
namespace statistics
{
/**
* Units for Stats.
*
* This header file provides an ability to associate a stat object with a
* specific unit.
*
* The supported units are:
* - Cycle: represents clock cycles.
* - Tick: represents the count of gem5's Tick.
* - Second: represents the base unit of time defined by SI.
* - Bit: represents the number of computer bits.
* - Byte: represents 8 bits.
* - Volt: a SI derived unit measuring potential difference.
* - Joule: represents joule, a unit of energy, as defined by SI.
* - Watt: represents 1 watt, where 1 watt = 1 joule / second.
* - Celsius: represents 1 Celsius degree as defined by SI.
* - Rate(T1, T2): represents the unit of a quantity of T1 divided by
* a quantity of T2.
* - Ratio: represents the unit of a quantity of unit T divided by a quantity
* of T.
* - Count: represents the count of a quantity that is not defined above.
* - Unspecified: the unit of the stat is unspecified.
*
* Each unit class is intended to be a singleton, which means only each unit
* class has at most one object of that class exist throughout the program.
* Therefore, copy constructors and assignment operators are deleted functions.
*
* When any of the following criteria is met, a new unit should be added,
* - The new unit is significant enough to be not included in Count unit.
* (e.g. Cycle unit, Tick unit)
*/
namespace units
{
/**
* The Base class is the parent class of all unit classes.
* This class is intended to an abstract class specifying common behaviors of
* all unit classes.
*/
class Base
{
public:
virtual std::string getUnitString() const = 0;
};
class Cycle : public Base
{
private:
Cycle() {}
public:
Cycle(Cycle const&) = delete;
void operator=(Cycle const&) = delete;
static Cycle*
get()
{
static Cycle instance;
return &instance;
}
static std::string toString() { return "Cycle"; }
std::string getUnitString() const override { return Cycle::toString(); }
};
class Tick : public Base
{
private:
Tick() {}
public:
Tick(Tick const&) = delete;
void operator=(Tick const&) = delete;
static Tick*
get()
{
static Tick instance;
return &instance;
}
static std::string toString() { return "Tick"; }
std::string getUnitString() const override { return Tick::toString(); }
};
class Second : public Base
{
private:
Second() {}
public:
Second(Second const&) = delete;
void operator=(Second const&) = delete;
static Second*
get()
{
static Second instance;
return &instance;
}
static std::string toString() { return "Second"; }
std::string getUnitString() const override { return Second::toString(); }
};
class Bit : public Base
{
private:
Bit() {}
public:
Bit(Bit const&) = delete;
void operator=(Bit const&) = delete;
static Bit*
get()
{
static Bit instance;
return &instance;
}
static std::string toString() { return "Bit"; }
std::string getUnitString() const override { return Bit::toString(); }
};
class Byte : public Base
{
private:
Byte() {}
public:
Byte(Byte const&) = delete;
void operator=(Byte const&) = delete;
static Byte*
get()
{
static Byte instance;
return &instance;
}
static std::string toString() { return "Byte"; }
std::string getUnitString() const override { return Byte::toString(); }
};
class Watt : public Base
{
private:
Watt() {}
public:
Watt(Watt const&) = delete;
void operator=(Watt const&) = delete;
static Watt*
get()
{
static Watt instance;
return &instance;
}
static std::string toString() { return "Watt"; }
std::string getUnitString() const override { return Watt::toString(); }
};
class Joule : public Base
{
private:
Joule() {}
public:
Joule(Joule const&) = delete;
void operator=(Joule const&) = delete;
static Joule*
get()
{
static Joule instance;
return &instance;
}
static std::string toString() { return "Joule"; }
std::string getUnitString() const override { return Joule::toString(); }
};
class Volt : public Base
{
private:
Volt() {}
public:
Volt(Volt const&) = delete;
void operator=(Volt const&) = delete;
static Volt*
get()
{
static Volt instance;
return &instance;
}
static std::string toString() { return "Volt"; }
std::string getUnitString() const override { return Volt::toString(); }
};
class DegreeCelsius : public Base
{
private:
DegreeCelsius() {}
public:
DegreeCelsius(DegreeCelsius const&) = delete;
void operator=(DegreeCelsius const&) = delete;
static DegreeCelsius*
get()
{
static DegreeCelsius instance;
return &instance;
}
static std::string toString() { return "Celsius"; }
std::string
getUnitString() const override
{
return DegreeCelsius::toString();
}
};
class Count : public Base
{
private:
Count() {}
public:
Count(Count const&) = delete;
void operator=(Count const&) = delete;
static Count*
get()
{
static Count instance;
return &instance;
}
static std::string toString() { return "Count"; }
std::string getUnitString() const override { return Count::toString(); }
};
class Ratio : public Base
{
private:
Ratio() {}
public:
Ratio(Ratio const&) = delete;
void operator=(Ratio const&) = delete;
static Ratio*
get()
{
static Ratio instance;
return &instance;
}
static std::string toString() { return "Ratio"; }
std::string getUnitString() const override { return Ratio::toString(); }
};
class Unspecified : public Base
{
private:
Unspecified() {}
public:
Unspecified(Unspecified const&) = delete;
void operator=(Unspecified const&) = delete;
static Unspecified*
get()
{
static Unspecified instance;
return &instance;
}
static std::string toString() { return "Unspecified"; }
std::string
getUnitString() const override
{
return Unspecified::toString();
}
};
template <typename T1, typename T2>
class Rate : public Base
{
static_assert(std::is_base_of_v<Base, T1>, "Rate(T1,T2) must have "
"T1 and T2 derived from statistics::units::Base");
static_assert(std::is_base_of_v<Base, T2>, "Rate(T1,T2) must have "
"T1 and T2 derived from statistics::units::Base");
static_assert(!std::is_same_v<T1, T2> || std::is_same_v<T1, Count> ||
std::is_same_v<T1, Unspecified>,
"Rate(T1,T2) must have T1 and T2 of different types; "
"otherwise, it would be a Ratio");
private:
Rate<T1,T2>() {}
public:
Rate<T1,T2>(Rate<T1,T2> const&) = delete;
void operator=(Rate<T1,T2> const&) = delete;
static Rate<T1,T2>*
get()
{
static Rate<T1,T2> instance;
return &instance;
}
static std::string
toString()
{
return csprintf("(%s/%s)", T1::toString(), T2::toString());
}
std::string
getUnitString() const override
{
return Rate<T1,T2>::toString();
}
};
} // namespace units
} // namespace statistics
} // namespace gem5
#endif // __BASE_STATS_UNITS_HH__