/*
+ * Copyright (c) 2019-2020 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
* 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.
- *
- * Authors: Nathan Binkert
*/
/** @file
#include <iosfwd>
#include <list>
#include <map>
+#include <memory>
#include <string>
#include <vector>
+#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"
-
-class Callback;
-
-/** The current simulated tick. */
-extern Tick curTick();
+// For curTick().
+#include "sim/core.hh"
/* A namespace for all of the Statistics */
namespace Stats {
{
public:
Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
+
+ Result total() const { return this->s.total(); }
};
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 */
const Info *info() const;
public:
+ InfoAccess()
+ : _info(nullptr) {};
+
/**
* Reset the stat to the default state.
*/
return safe_cast<const Info *>(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(parent, name);
+ info->flags.set(display);
+ }
+
+ if (desc)
+ info->desc = desc;
}
/**
public:
typedef InfoProxyType<Derived> Info;
- DataWrapVec()
- {}
-
- DataWrapVec(const DataWrapVec &ref)
- {}
-
- void operator=(const DataWrapVec &)
+ DataWrapVec(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DataWrap<Derived, InfoProxyType>(parent, name, desc)
{}
// The following functions are specific to vectors. If you use them
public:
typedef InfoProxyType<Derived> Info;
+ DataWrapVec2d(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Derived, InfoProxyType>(parent, name, desc)
+ {
+ }
+
/**
* @warning This makes the assumption that if you're gonna subnames a 2d
* vector, you're subnaming across all y
protected:
/** The storage of this stat. */
- char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
+ M5_ALIGNED(8) char storage[sizeof(Storage)];
protected:
/**
Counter value() const { return data()->value(); }
public:
- ScalarBase()
+ ScalarBase(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc)
{
this->doInit();
}
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() { }
Result total() const { return *scalar; }
};
-template <class T>
+template <class T, class Enabled=void>
class FunctorProxy : public ProxyInfo
{
private:
Result total() const { return (*functor)(); }
};
+/**
+ * Template specialization for type std::function<Result()> which holds a copy
+ * of its target instead of a pointer to it. This makes it possible to use a
+ * lambda or other type inline without having to keep track of an instance
+ * somewhere else.
+ */
+template <class T>
+class FunctorProxy<T,
+ typename std::enable_if_t<std::is_constructible<std::function<Result()>,
+ const T &>::value>> : public ProxyInfo
+{
+ private:
+ std::function<Result()> functor;
+
+ public:
+ FunctorProxy(const T &func) : functor(func) {}
+ Counter value() const { return functor(); }
+ Result result() const { return functor(); }
+ 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.
ProxyInfo *proxy;
public:
- ValueBase() : proxy(NULL) { }
+ ValueBase(Group *parent, const char *name, const char *desc)
+ : DataWrap<Derived, ScalarInfoProxy>(parent, name, desc),
+ proxy(NULL)
+ {
+ }
+
~ValueBase() { if (proxy) delete proxy; }
template <class T>
return this->self();
}
+ template <class T>
+ Derived &
+ functor(const T &func)
+ {
+ proxy = new FunctorProxy<T>(func);
+ this->setInit();
+ return this->self();
+ }
+
template <class T>
Derived &
functor(T &func)
}
public:
- VectorBase()
- : storage(NULL)
+ VectorBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Derived, VectorInfoProxy>(parent, name, desc),
+ storage(nullptr), _size(0)
{}
~VectorBase()
Proxy
operator[](off_type index)
{
- assert (index >= 0 && index < size());
+ assert (index < size());
return Proxy(this->self(), index);
}
};
ScalarProxy<Stat>
operator[](off_type index)
{
- assert (index >= 0 && index < size());
+ assert (index < size());
return ScalarProxy<Stat>(stat, offset + index);
}
const Storage *data(off_type index) const { return &storage[index]; }
public:
- Vector2dBase()
- : storage(NULL)
+ Vector2dBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec2d<Derived, Vector2dInfoProxy>(parent, name, desc),
+ x(0), y(0), _size(0), storage(nullptr)
{}
~Vector2dBase()
operator[](off_type index)
{
off_type offset = index * y;
- assert (index >= 0 && offset + y <= size());
+ assert (offset + y <= size());
return Proxy(this->self(), offset, y);
}
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
};
/**
- * Templatized storage and interface for a distrbution stat.
+ * Templatized storage and interface for a distribution stat.
*/
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:
/** The number of buckets.. */
size_type buckets;
- Params() : DistParams(Hist) {}
+ Params() : DistParams(Hist), buckets(0) {}
};
private:
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;
void
sample(Counter val, int number)
{
- Counter value = val * number;
- sum += value;
- squares += value * value;
+ sum += val * number;
+ squares += val * val * number;
samples += number;
}
void
sample(Counter val, int number)
{
- Counter value = val * number;
- sum += value;
- squares += value * value;
+ sum += val * number;
+ squares += val * val * number;
}
/**
protected:
/** The storage for this stat. */
- char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
+ M5_ALIGNED(8) char storage[sizeof(Storage)];
protected:
/**
}
public:
- DistBase() { }
+ DistBase(Group *parent, const char *name, const char *desc)
+ : DataWrap<Derived, DistInfoProxy>(parent, name, desc)
+ {
+ }
/**
* Add a value to the distribtion n times. Calls sample on the storage
}
/**
- * Add the argument distribution to the this distibution.
+ * Add the argument distribution to the this distribution.
*/
void add(DistBase &d) { data()->add(d.data()); }
}
public:
- VectorDistBase()
- : storage(NULL)
+ VectorDistBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Derived, VectorDistInfoProxy>(parent, name, desc),
+ storage(NULL)
{}
~VectorDistBase()
Proxy operator[](off_type index)
{
- assert(index >= 0 && index < size());
+ assert(index < size());
return Proxy(this->self(), index);
}
* 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:
/**
*
*/
virtual std::string str() const = 0;
+
+ virtual ~Node() {};
};
-/** Reference counting pointer to a function Node. */
-typedef RefCountingPtr<Node> NodePtr;
+/** Shared pointer to a function Node. */
+typedef std::shared_ptr<Node> NodePtr;
class ScalarStatNode : 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 <class T>
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;
}
BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
const VResult &
- result() const
+ result() const override
{
Op op;
const VResult &lvec = l->result();
}
Result
- total() const
+ total() const override
{
const VResult &vec = this->result();
const VResult &lvec = l->result();
}
size_type
- size() const
+ size() const override
{
size_type ls = l->size();
size_type rs = r->size();
}
std::string
- str() const
+ str() const override
{
return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
}
{
public:
using ScalarBase<Scalar, StatStor>::operator=;
+
+ Scalar(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : ScalarBase<Scalar, StatStor>(parent, name, desc)
+ {
+ }
};
/**
{
public:
using ScalarBase<Average, AvgStor>::operator=;
+
+ Average(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : ScalarBase<Average, AvgStor>(parent, name, desc)
+ {
+ }
};
class Value : public ValueBase<Value>
{
+ public:
+ Value(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : ValueBase<Value>(parent, name, desc)
+ {
+ }
};
/**
*/
class Vector : public VectorBase<Vector, StatStor>
{
+ public:
+ Vector(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : VectorBase<Vector, StatStor>(parent, name, desc)
+ {
+ }
};
/**
*/
class AverageVector : public VectorBase<AverageVector, AvgStor>
{
+ public:
+ AverageVector(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : VectorBase<AverageVector, AvgStor>(parent, name, desc)
+ {
+ }
};
/**
*/
class Vector2d : public Vector2dBase<Vector2d, StatStor>
{
+ public:
+ Vector2d(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : Vector2dBase<Vector2d, StatStor>(parent, name, desc)
+ {
+ }
};
/**
class Distribution : public DistBase<Distribution, DistStor>
{
public:
+ Distribution(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DistBase<Distribution, DistStor>(parent, name, desc)
+ {
+ }
+
/**
* Set the parameters of this distribution. @sa DistStor::Params
* @param min The minimum value of the distribution.
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();
class Histogram : public DistBase<Histogram, HistStor>
{
public:
+ Histogram(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DistBase<Histogram, HistStor>(parent, name, desc)
+ {
+ }
+
/**
* Set the parameters of this histogram. @sa HistStor::Params
* @param size The number of buckets in the histogram
/**
* Construct and initialize this distribution.
*/
- StandardDeviation()
+ StandardDeviation(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DistBase<StandardDeviation, SampleStor>(parent, name, desc)
{
SampleStor::Params *params = new SampleStor::Params;
this->doInit();
/**
* Construct and initialize this distribution.
*/
- AverageDeviation()
+ AverageDeviation(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : DistBase<AverageDeviation, AvgSampleStor>(parent, name, desc)
{
AvgSampleStor::Params *params = new AvgSampleStor::Params;
this->doInit();
class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
{
public:
+ VectorDistribution(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : VectorDistBase<VectorDistribution, DistStor>(parent, name, desc)
+ {
+ }
+
/**
* Initialize storage and parameters for this distribution.
* @param size The size of the vector (the number of distributions).
: public VectorDistBase<VectorStandardDeviation, SampleStor>
{
public:
+ VectorStandardDeviation(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : VectorDistBase<VectorStandardDeviation, SampleStor>(parent, name,
+ desc)
+ {
+ }
+
/**
* Initialize storage for this distribution.
* @param size The size of the vector.
: public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
{
public:
+ VectorAverageDeviation(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : VectorDistBase<VectorAverageDeviation, AvgSampleStor>(parent, name,
+ desc)
+ {
+ }
+
/**
* Initialize storage for this distribution.
* @param size The size of the vector.
}
public:
- SparseHistBase() { }
+ SparseHistBase(Group *parent, const char *name, const char *desc)
+ : DataWrap<Derived, SparseHistInfoProxy>(parent, name, desc)
+ {
+ }
/**
* Add a value to the distribtion n times. Calls sample on the storage
class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
{
public:
+ SparseHistogram(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : SparseHistBase<SparseHistogram, SparseHistStor>(parent, name, desc)
+ {
+ }
+
/**
* Set the parameters of this histogram. @sa HistStor::Params
* @param size The number of buckets in the histogram
/**
* 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<typename T>
+ const Formula &operator=(const T &v)
+ {
+ *this = Temp(v);
+ return *this;
+ }
/**
* Add the given tree to the existing one.
* 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.
*/
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.
inline Temp
operator+(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
+ return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
}
inline Temp
operator-(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
+ return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
}
inline Temp
operator*(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
+ return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
}
inline Temp
operator/(Temp l, Temp r)
{
- return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
+ return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
}
inline Temp
operator-(Temp l)
{
- return NodePtr(new UnaryNode<std::negate<Result> >(l));
+ return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
}
template <typename T>
inline Temp
constant(T val)
{
- return NodePtr(new ConstNode<T>(val));
+ return Temp(std::make_shared<ConstNode<T> >(val));
}
template <typename T>
inline Temp
constantVector(T val)
{
- return NodePtr(new ConstVectorNode<T>(val));
+ return Temp(std::make_shared<ConstVectorNode<T> >(val));
}
inline Temp
sum(Temp val)
{
- return NodePtr(new SumNode<std::plus<Result> >(val));
+ return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
}
/** Dump all statistics data to the registered outputs */
void reset();
void enable();
bool enabled();
+const Info* resolve(const std::string &name);
+
+/**
+ * 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);
+void registerResetCallback(const std::function<void()> &callback);
/**
* Register a callback that should be called whenever statistics are
* about to be dumped
*/
-void registerDumpCallback(Callback *cb);
+void registerDumpCallback(const std::function<void()> &callback);
+
+/**
+ * Process all the callbacks in the reset callbacks queue
+ */
+void processResetQueue();
+
+/**
+ * Process all the callbacks in the dump callbacks queue
+ */
+void processDumpQueue();
std::list<Info *> &statsList();
typedef std::map<const void *, Info *> MapType;
MapType &statsMap();
-typedef std::map<std::string, Info *> NameMapType;
-NameMapType &nameMap();
-
-bool validateStatName(const std::string &name);
-
} // namespace Stats
void debugDumpStats();