X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fbase%2Fstatistics.hh;h=f4fa123e970d71780883f1c2495adae18dd8deee;hb=6f38428abbe106d63318dd86bfa82a03b6b368ee;hp=67c09bb6ac3914263653a9bf492d86ba8f424149;hpb=ec50c78f8311d37aa57be571be05fbb128ab8bb7;p=gem5.git diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 67c09bb6a..f4fa123e9 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -1,5 +1,18 @@ /* + * Copyright (c) 2019 Arm Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2017, Centre National de la Recherche Scientifique * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +39,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Pierre-Yves Peneau */ /** @file @@ -57,16 +71,17 @@ #include #include #include +#include #include #include +#include "base/stats/group.hh" #include "base/stats/info.hh" #include "base/stats/output.hh" #include "base/stats/types.hh" #include "base/cast.hh" #include "base/cprintf.hh" #include "base/intmath.hh" -#include "base/refcnt.hh" #include "base/str.hh" #include "base/types.hh" @@ -159,6 +174,8 @@ class Vector2dInfoProxy : public InfoProxy { public: Vector2dInfoProxy(Stat &stat) : InfoProxy(stat) {} + + Result total() const { return this->s.total(); } }; struct StorageParams @@ -168,9 +185,12 @@ struct StorageParams class InfoAccess { + private: + Info *_info; + protected: /** Set up an info class for this statistic */ - void setInfo(Info *info); + void setInfo(Group *parent, Info *info); /** Save Storage class parameters if any */ void setParams(const StorageParams *params); /** Save Storage class parameters if any */ @@ -182,6 +202,9 @@ class InfoAccess const Info *info() const; public: + InfoAccess() + : _info(nullptr) {}; + /** * Reset the stat to the default state. */ @@ -224,21 +247,27 @@ class DataWrap : public InfoAccess return safe_cast(InfoAccess::info()); } - protected: - /** - * Copy constructor, copies are not allowed. - */ - DataWrap(const DataWrap &stat); + public: + DataWrap() = delete; + DataWrap(const DataWrap &) = delete; + DataWrap &operator=(const DataWrap &) = delete; - /** - * Can't copy stats. - */ - void operator=(const DataWrap &); - public: - DataWrap() + DataWrap(Group *parent, const char *name, const char *desc) { - this->setInfo(new Info(self())); + auto info = new Info(self()); + this->setInfo(parent, info); + + if (parent) + parent->addStat(info); + + if (name) { + info->setName(name); + info->flags.set(display); + } + + if (desc) + info->desc = desc; } /** @@ -331,6 +360,11 @@ class DataWrapVec : public DataWrap public: typedef InfoProxyType Info; + DataWrapVec(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DataWrap(parent, name, desc) + {} + // The following functions are specific to vectors. If you use them // in a non vector context, you will get a nice compiler error! @@ -407,6 +441,11 @@ class DataWrapVec2d : public DataWrapVec public: typedef InfoProxyType Info; + DataWrapVec2d(Group *parent, const char *name, const char *desc) + : DataWrapVec(parent, name, desc) + { + } + /** * @warning This makes the assumption that if you're gonna subnames a 2d * vector, you're subnaming across all y @@ -664,7 +703,9 @@ class ScalarBase : public DataWrap Counter value() const { return data()->value(); } public: - ScalarBase() + ScalarBase(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DataWrap(parent, name, desc) { this->doInit(); } @@ -732,7 +773,7 @@ class ScalarBase : public DataWrap class ProxyInfo : public ScalarInfo { public: - std::string str() const { return to_string(value()); } + std::string str() const { return std::to_string(value()); } size_type size() const { return 1; } bool check() const { return true; } void prepare() { } @@ -768,6 +809,25 @@ class FunctorProxy : public ProxyInfo Result total() const { return (*functor)(); } }; +/** + * A proxy similar to the FunctorProxy, but allows calling a method of a bound + * object, instead of a global free-standing function. + */ +template +class MethodProxy : public ProxyInfo +{ + private: + T *object; + typedef V (T::*MethodPointer) () const; + MethodPointer method; + + public: + MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {} + Counter value() const { return (object->*method)(); } + Result result() const { return (object->*method)(); } + Result total() const { return (object->*method)(); } +}; + template class ValueBase : public DataWrap { @@ -775,7 +835,12 @@ class ValueBase : public DataWrap ProxyInfo *proxy; public: - ValueBase() : proxy(NULL) { } + ValueBase(Group *parent, const char *name, const char *desc) + : DataWrap(parent, name, desc), + proxy(NULL) + { + } + ~ValueBase() { if (proxy) delete proxy; } template @@ -796,6 +861,22 @@ class ValueBase : public DataWrap return this->self(); } + /** + * Extended functor that calls the specified method of the provided object. + * + * @param obj Pointer to the object whose method should be called. + * @param method Pointer of the function / method of the object. + * @return Updated stats item. + */ + template + Derived & + method(T *obj, V (T::*method)() const) + { + proxy = new MethodProxy(obj, method); + this->setInit(); + return this->self(); + } + Counter value() { return proxy->value(); } Result result() const { return proxy->result(); } Result total() const { return proxy->total(); }; @@ -1047,8 +1128,9 @@ class VectorBase : public DataWrapVec } public: - VectorBase() - : storage(NULL) + VectorBase(Group *parent, const char *name, const char *desc) + : DataWrapVec(parent, name, desc), + storage(nullptr), _size(0) {} ~VectorBase() @@ -1187,8 +1269,9 @@ class Vector2dBase : public DataWrapVec2d const Storage *data(off_type index) const { return &storage[index]; } public: - Vector2dBase() - : storage(NULL) + Vector2dBase(Group *parent, const char *name, const char *desc) + : DataWrapVec2d(parent, name, desc), + x(0), y(0), _size(0), storage(nullptr) {} ~Vector2dBase() @@ -1246,12 +1329,19 @@ class Vector2dBase : public DataWrapVec2d zero() const { return data(0)->zero(); -#if 0 + } + + /** + * Return a total of all entries in this vector. + * @return The total of all vector entries. + */ + Result + total() const + { + Result total = 0.0; for (off_type i = 0; i < size(); ++i) - if (!data(i)->zero()) - return false; - return true; -#endif + total += data(i)->result(); + return total; } void @@ -1300,7 +1390,7 @@ struct DistParams : public StorageParams }; /** - * Templatized storage and interface for a distrbution stat. + * Templatized storage and interface for a distribution stat. */ class DistStor { @@ -1317,7 +1407,8 @@ class DistStor /** The number of buckets. Equal to (max-min)/bucket_size. */ size_type buckets; - Params() : DistParams(Dist) {} + Params() : DistParams(Dist), min(0), max(0), bucket_size(0), + buckets(0) {} }; private: @@ -1327,8 +1418,6 @@ class DistStor Counter max_track; /** The number of entries in each bucket. */ Counter bucket_size; - /** The number of buckets. Equal to (max-min)/bucket_size. */ - size_type buckets; /** The smallest value sampled. */ Counter min_val; @@ -1416,9 +1505,8 @@ class DistStor data.underflow = underflow; data.overflow = overflow; - size_type buckets = params->buckets; - data.cvec.resize(buckets); - for (off_type i = 0; i < buckets; ++i) + data.cvec.resize(params->buckets); + for (off_type i = 0; i < params->buckets; ++i) data.cvec[i] = cvec[i]; data.sum = sum; @@ -1464,7 +1552,7 @@ class HistStor /** The number of buckets.. */ size_type buckets; - Params() : DistParams(Hist) {} + Params() : DistParams(Hist), buckets(0) {} }; private: @@ -1496,6 +1584,7 @@ class HistStor void grow_up(); void grow_out(); void grow_convert(); + void add(HistStor *); /** * Add a value to the distribution for the given number of times. @@ -1525,7 +1614,7 @@ class HistStor size_type index = (int64_t)std::floor((val - min_bucket) / bucket_size); - assert(index >= 0 && index < size()); + assert(index < size()); cvec[index] += number; sum += val * number; @@ -1797,7 +1886,10 @@ class DistBase : public DataWrap } public: - DistBase() { } + DistBase(Group *parent, const char *name, const char *desc) + : DataWrap(parent, name, desc) + { + } /** * Add a value to the distribtion n times. Calls sample on the storage @@ -1834,6 +1926,12 @@ class DistBase : public DataWrap { data()->reset(this->info()); } + + /** + * Add the argument distribution to the this distribution. + */ + void add(DistBase &d) { data()->add(d.data()); } + }; template @@ -1885,8 +1983,9 @@ class VectorDistBase : public DataWrapVec } public: - VectorDistBase() - : storage(NULL) + VectorDistBase(Group *parent, const char *name, const char *desc) + : DataWrapVec(parent, name, desc), + storage(NULL) {} ~VectorDistBase() @@ -2001,7 +2100,7 @@ class DistProxy * Base class for formula statistic node. These nodes are used to build a tree * that represents the formula. */ -class Node : public RefCounted +class Node { public: /** @@ -2024,10 +2123,12 @@ class Node : public RefCounted * */ virtual std::string str() const = 0; + + virtual ~Node() {}; }; -/** Reference counting pointer to a function Node. */ -typedef RefCountingPtr NodePtr; +/** Shared pointer to a function Node. */ +typedef std::shared_ptr NodePtr; class ScalarStatNode : public Node { @@ -2122,7 +2223,7 @@ class ConstNode : public Node const VResult &result() const { return vresult; } Result total() const { return vresult[0]; }; size_type size() const { return 1; } - std::string str() const { return to_string(vresult[0]); } + std::string str() const { return std::to_string(vresult[0]); } }; template @@ -2152,7 +2253,7 @@ class ConstVectorNode : public Node size_type size = this->size(); std::string tmp = "("; for (off_type i = 0; i < size; i++) - tmp += csprintf("%s ",to_string(vresult[i])); + tmp += csprintf("%s ", std::to_string(vresult[i])); tmp += ")"; return tmp; } @@ -2254,7 +2355,7 @@ class BinaryNode : public Node BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {} const VResult & - result() const + result() const override { Op op; const VResult &lvec = l->result(); @@ -2286,17 +2387,39 @@ class BinaryNode : public Node } Result - total() const + total() const override { const VResult &vec = this->result(); + const VResult &lvec = l->result(); + const VResult &rvec = r->result(); Result total = 0.0; - for (off_type i = 0; i < size(); i++) + Result lsum = 0.0; + Result rsum = 0.0; + Op op; + + assert(lvec.size() > 0 && rvec.size() > 0); + assert(lvec.size() == rvec.size() || + lvec.size() == 1 || rvec.size() == 1); + + /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */ + if (lvec.size() == rvec.size() && lvec.size() > 1) { + for (off_type i = 0; i < size(); ++i) { + lsum += lvec[i]; + rsum += rvec[i]; + } + return op(lsum, rsum); + } + + /** Otherwise divide each item by the divisor */ + for (off_type i = 0; i < size(); ++i) { total += vec[i]; + } + return total; } size_type - size() const + size() const override { size_type ls = l->size(); size_type rs = r->size(); @@ -2311,7 +2434,7 @@ class BinaryNode : public Node } std::string - str() const + str() const override { return csprintf("(%s %s %s)", l->str(), OpString::str(), r->str()); } @@ -2350,13 +2473,13 @@ class SumNode : public Node size_type size = lvec.size(); assert(size > 0); - Result vresult = 0.0; + Result result = 0.0; Op op; for (off_type i = 0; i < size; ++i) - vresult = op(vresult, lvec[i]); + result = op(result, lvec[i]); - return vresult; + return result; } size_type size() const { return 1; } @@ -2388,6 +2511,12 @@ class Scalar : public ScalarBase { public: using ScalarBase::operator=; + + Scalar(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : ScalarBase(parent, name, desc) + { + } }; /** @@ -2398,10 +2527,22 @@ class Average : public ScalarBase { public: using ScalarBase::operator=; + + Average(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : ScalarBase(parent, name, desc) + { + } }; class Value : public ValueBase { + public: + Value(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : ValueBase(parent, name, desc) + { + } }; /** @@ -2410,6 +2551,12 @@ class Value : public ValueBase */ class Vector : public VectorBase { + public: + Vector(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : VectorBase(parent, name, desc) + { + } }; /** @@ -2418,6 +2565,12 @@ class Vector : public VectorBase */ class AverageVector : public VectorBase { + public: + AverageVector(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : VectorBase(parent, name, desc) + { + } }; /** @@ -2426,6 +2579,12 @@ class AverageVector : public VectorBase */ class Vector2d : public Vector2dBase { + public: + Vector2d(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : Vector2dBase(parent, name, desc) + { + } }; /** @@ -2435,6 +2594,12 @@ class Vector2d : public Vector2dBase class Distribution : public DistBase { public: + Distribution(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DistBase(parent, name, desc) + { + } + /** * Set the parameters of this distribution. @sa DistStor::Params * @param min The minimum value of the distribution. @@ -2449,6 +2614,9 @@ class Distribution : public DistBase params->min = min; params->max = max; params->bucket_size = bkt; + // Division by zero is especially serious in an Aarch64 host, + // where it gets rounded to allocate 32GiB RAM. + assert(bkt > 0); params->buckets = (size_type)ceil((max - min + 1.0) / bkt); this->setParams(params); this->doInit(); @@ -2463,6 +2631,12 @@ class Distribution : public DistBase class Histogram : public DistBase { public: + Histogram(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DistBase(parent, name, desc) + { + } + /** * Set the parameters of this histogram. @sa HistStor::Params * @param size The number of buckets in the histogram @@ -2489,7 +2663,9 @@ class StandardDeviation : public DistBase /** * Construct and initialize this distribution. */ - StandardDeviation() + StandardDeviation(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DistBase(parent, name, desc) { SampleStor::Params *params = new SampleStor::Params; this->doInit(); @@ -2507,7 +2683,9 @@ class AverageDeviation : public DistBase /** * Construct and initialize this distribution. */ - AverageDeviation() + AverageDeviation(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : DistBase(parent, name, desc) { AvgSampleStor::Params *params = new AvgSampleStor::Params; this->doInit(); @@ -2522,6 +2700,12 @@ class AverageDeviation : public DistBase class VectorDistribution : public VectorDistBase { public: + VectorDistribution(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : VectorDistBase(parent, name, desc) + { + } + /** * Initialize storage and parameters for this distribution. * @param size The size of the vector (the number of distributions). @@ -2552,6 +2736,13 @@ class VectorStandardDeviation : public VectorDistBase { public: + VectorStandardDeviation(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : VectorDistBase(parent, name, + desc) + { + } + /** * Initialize storage for this distribution. * @param size The size of the vector. @@ -2575,6 +2766,13 @@ class VectorAverageDeviation : public VectorDistBase { public: + VectorAverageDeviation(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : VectorDistBase(parent, name, + desc) + { + } + /** * Initialize storage for this distribution. * @param size The size of the vector. @@ -2666,7 +2864,10 @@ class SparseHistBase : public DataWrap } public: - SparseHistBase() { } + SparseHistBase(Group *parent, const char *name, const char *desc) + : DataWrap(parent, name, desc) + { + } /** * Add a value to the distribtion n times. Calls sample on the storage @@ -2783,6 +2984,12 @@ class SparseHistStor class SparseHistogram : public SparseHistBase { public: + SparseHistogram(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr) + : SparseHistBase(parent, name, desc) + { + } + /** * Set the parameters of this histogram. @sa HistStor::Params * @param size The number of buckets in the histogram @@ -2815,21 +3022,25 @@ class Formula : public DataWrapVec /** * Create and initialize thie formula, and register it with the database. */ - Formula(); + Formula(Group *parent = nullptr, const char *name = nullptr, + const char *desc = nullptr); - /** - * Create a formula with the given root node, register it with the - * database. - * @param r The root of the expression tree. - */ - Formula(Temp r); + Formula(Group *parent, const char *name, const char *desc, + const Temp &r); /** * Set an unitialized Formula to the given root. * @param r The root of the expression tree. * @return a reference to this formula. */ - const Formula &operator=(Temp r); + const Formula &operator=(const Temp &r); + + template + const Formula &operator=(const T &v) + { + *this = Temp(v); + return *this; + } /** * Add the given tree to the existing one. @@ -2837,6 +3048,14 @@ class Formula : public DataWrapVec * @return a reference to this formula. */ const Formula &operator+=(Temp r); + + /** + * Divide the existing tree by the given one. + * @param r The root of the expression tree. + * @return a reference to this formula. + */ + const Formula &operator/=(Temp r); + /** * Return the result of the Fomula in a vector. If there were no Vector * components to the Formula, then the vector is size 1. If there were, @@ -2910,7 +3129,9 @@ class Temp * Copy the given pointer to this class. * @param n A pointer to a Node object to copy. */ - Temp(NodePtr n) : node(n) { } + Temp(const NodePtr &n) : node(n) { } + + Temp(NodePtr &&n) : node(std::move(n)) { } /** * Return the node pointer. @@ -2918,6 +3139,11 @@ class Temp */ operator NodePtr&() { return node; } + /** + * Makde gcc < 4.6.3 happy and explicitly get the underlying node. + */ + NodePtr getNodePtr() const { return node; } + public: /** * Create a new ScalarStatNode. @@ -3076,51 +3302,51 @@ class Temp inline Temp operator+(Temp l, Temp r) { - return NodePtr(new BinaryNode >(l, r)); + return Temp(std::make_shared > >(l, r)); } inline Temp operator-(Temp l, Temp r) { - return NodePtr(new BinaryNode >(l, r)); + return Temp(std::make_shared > >(l, r)); } inline Temp operator*(Temp l, Temp r) { - return NodePtr(new BinaryNode >(l, r)); + return Temp(std::make_shared > >(l, r)); } inline Temp operator/(Temp l, Temp r) { - return NodePtr(new BinaryNode >(l, r)); + return Temp(std::make_shared > >(l, r)); } inline Temp operator-(Temp l) { - return NodePtr(new UnaryNode >(l)); + return Temp(std::make_shared > >(l)); } template inline Temp constant(T val) { - return NodePtr(new ConstNode(val)); + return Temp(std::make_shared >(val)); } template inline Temp constantVector(T val) { - return NodePtr(new ConstVectorNode(val)); + return Temp(std::make_shared >(val)); } inline Temp sum(Temp val) { - return NodePtr(new SumNode >(val)); + return Temp(std::make_shared > >(val)); } /** Dump all statistics data to the registered outputs */ @@ -3129,14 +3355,49 @@ void reset(); void enable(); bool enabled(); +/** + * Register reset and dump handlers. These are the functions which + * will actually perform the whole statistics reset/dump actions + * including processing the reset/dump callbacks + */ +typedef void (*Handler)(); + +void registerHandlers(Handler reset_handler, Handler dump_handler); + /** * Register a callback that should be called whenever statistics are * reset */ void registerResetCallback(Callback *cb); +/** + * Register a callback that should be called whenever statistics are + * about to be dumped + */ +void registerDumpCallback(Callback *cb); + +/** + * Process all the callbacks in the reset callbacks queue + */ +void processResetQueue(); + +/** + * Process all the callbacks in the dump callbacks queue + */ +void processDumpQueue(); + std::list &statsList(); +typedef std::map MapType; +MapType &statsMap(); + +typedef std::map NameMapType; +NameMapType &nameMap(); + +bool validateStatName(const std::string &name); + } // namespace Stats +void debugDumpStats(); + #endif // __BASE_STATISTICS_HH__