summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base/SConscript2
-rw-r--r--src/base/statistics.cc70
-rw-r--r--src/base/statistics.hh204
-rw-r--r--src/base/stats/group.cc129
-rw-r--r--src/base/stats/group.hh175
-rw-r--r--src/base/stats/output.hh16
-rw-r--r--src/base/stats/text.cc53
-rw-r--r--src/base/stats/text.hh41
-rw-r--r--src/python/m5/SimObject.py4
-rw-r--r--src/python/m5/simulate.py3
-rw-r--r--src/python/m5/stats/__init__.py73
-rw-r--r--src/python/pybind11/stats.cc16
-rw-r--r--src/sim/sim_object.cc17
-rw-r--r--src/sim/sim_object.hh14
14 files changed, 704 insertions, 113 deletions
diff --git a/src/base/SConscript b/src/base/SConscript
index 9449a3d4e..96f7b5b50 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -81,6 +81,7 @@ Source('loader/object_file.cc')
Source('loader/raw_object.cc')
Source('loader/symtab.cc')
+Source('stats/group.cc')
Source('stats/text.cc')
GTest('addr_range.test', 'addr_range.test.cc')
@@ -101,6 +102,7 @@ DebugFlag('GDBRecv', "Messages received from the remote application")
DebugFlag('GDBSend', "Messages sent to the remote application")
DebugFlag('GDBWrite', "Writes to the remote address space")
DebugFlag('SQL', "SQL queries sent to the server")
+DebugFlag('Stats', "Statistics management")
DebugFlag('StatEvents', "Statistics event tracking")
CompoundFlag('GDBAll',
diff --git a/src/base/statistics.cc b/src/base/statistics.cc
index 123351b80..a186f9763 100644
--- a/src/base/statistics.cc
+++ b/src/base/statistics.cc
@@ -1,4 +1,16 @@
/*
+ * 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
* All rights reserved.
*
@@ -67,10 +79,18 @@ statsMap()
}
void
-InfoAccess::setInfo(Info *info)
+InfoAccess::setInfo(Group *parent, Info *info)
{
- if (statsMap().find(this) != statsMap().end())
- panic("shouldn't register stat twice!");
+ panic_if(statsMap().find(this) != statsMap().end() ||
+ _info != nullptr,
+ "shouldn't register stat twice!");
+
+ // New-style stats are reachable through the hierarchy and
+ // shouldn't be added to the global lists.
+ if (parent) {
+ _info = info;
+ return;
+ }
statsList().push_back(info);
@@ -97,17 +117,29 @@ InfoAccess::setInit()
Info *
InfoAccess::info()
{
- MapType::const_iterator i = statsMap().find(this);
- assert(i != statsMap().end());
- return (*i).second;
+ if (_info) {
+ // New-style stats
+ return _info;
+ } else {
+ // Legacy stats
+ MapType::const_iterator i = statsMap().find(this);
+ assert(i != statsMap().end());
+ return (*i).second;
+ }
}
const Info *
InfoAccess::info() const
{
- MapType::const_iterator i = statsMap().find(this);
- assert(i != statsMap().end());
- return (*i).second;
+ if (_info) {
+ // New-style stats
+ return _info;
+ } else {
+ // Legacy stats
+ MapType::const_iterator i = statsMap().find(this);
+ assert(i != statsMap().end());
+ return (*i).second;
+ }
}
StorageParams::~StorageParams()
@@ -224,7 +256,8 @@ Info::baseCheck() const
#endif
panic("Not all stats have been initialized.\n"
"You may need to add <ParentClass>::regStats() to a"
- " new SimObject's regStats() function.");
+ " new SimObject's regStats() function. Name: %s",
+ name);
return false;
}
@@ -376,19 +409,23 @@ HistStor::add(HistStor *hs)
cvec[i] += hs->cvec[i];
}
-Formula::Formula()
+Formula::Formula(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
+
{
}
-Formula::Formula(Temp r)
+
+
+Formula::Formula(Group *parent, const char *name, const char *desc,
+ const Temp &r)
+ : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
{
- root = r.getNodePtr();
- setInit();
- assert(size());
+ *this = r;
}
const Formula &
-Formula::operator=(Temp r)
+Formula::operator=(const Temp &r)
{
assert(!root && "Can't change formulas");
root = r.getNodePtr();
@@ -421,6 +458,7 @@ Formula::operator/=(Temp r)
return *this;
}
+
void
Formula::result(VResult &vec) const
{
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
index 6ddf7ff17..f4fa123e9 100644
--- a/src/base/statistics.hh
+++ b/src/base/statistics.hh
@@ -1,4 +1,16 @@
/*
+ * 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.
@@ -63,6 +75,7 @@
#include <string>
#include <vector>
+#include "base/stats/group.hh"
#include "base/stats/info.hh"
#include "base/stats/output.hh"
#include "base/stats/types.hh"
@@ -172,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 */
@@ -186,6 +202,9 @@ class InfoAccess
const Info *info() const;
public:
+ InfoAccess()
+ : _info(nullptr) {};
+
/**
* Reset the stat to the default state.
*/
@@ -228,21 +247,27 @@ class DataWrap : public InfoAccess
return safe_cast<const Info *>(InfoAccess::info());
}
- protected:
- /**
- * Copy constructor, copies are not allowed.
- */
- DataWrap(const DataWrap &stat) = delete;
+ 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;
}
/**
@@ -335,13 +360,9 @@ class DataWrapVec : public DataWrap<Derived, InfoProxyType>
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
@@ -420,6 +441,11 @@ class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
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
@@ -677,7 +703,9 @@ class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
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();
}
@@ -807,7 +835,12 @@ class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
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>
@@ -1095,8 +1128,9 @@ class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
}
public:
- VectorBase()
- : storage(nullptr), _size(0)
+ VectorBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Derived, VectorInfoProxy>(parent, name, desc),
+ storage(nullptr), _size(0)
{}
~VectorBase()
@@ -1235,8 +1269,9 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
const Storage *data(off_type index) const { return &storage[index]; }
public:
- Vector2dBase()
- : x(0), y(0), _size(0), storage(nullptr)
+ Vector2dBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec2d<Derived, Vector2dInfoProxy>(parent, name, desc),
+ x(0), y(0), _size(0), storage(nullptr)
{}
~Vector2dBase()
@@ -1851,7 +1886,10 @@ class DistBase : public DataWrap<Derived, DistInfoProxy>
}
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
@@ -1945,8 +1983,9 @@ class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
}
public:
- VectorDistBase()
- : storage(NULL)
+ VectorDistBase(Group *parent, const char *name, const char *desc)
+ : DataWrapVec<Derived, VectorDistInfoProxy>(parent, name, desc),
+ storage(NULL)
{}
~VectorDistBase()
@@ -2472,6 +2511,12 @@ class Scalar : public ScalarBase<Scalar, StatStor>
{
public:
using ScalarBase<Scalar, StatStor>::operator=;
+
+ Scalar(Group *parent = nullptr, const char *name = nullptr,
+ const char *desc = nullptr)
+ : ScalarBase<Scalar, StatStor>(parent, name, desc)
+ {
+ }
};
/**
@@ -2482,10 +2527,22 @@ class Average : public ScalarBase<Average, AvgStor>
{
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)
+ {
+ }
};
/**
@@ -2494,6 +2551,12 @@ class Value : public ValueBase<Value>
*/
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)
+ {
+ }
};
/**
@@ -2502,6 +2565,12 @@ class Vector : public VectorBase<Vector, StatStor>
*/
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)
+ {
+ }
};
/**
@@ -2510,6 +2579,12 @@ class AverageVector : public VectorBase<AverageVector, AvgStor>
*/
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)
+ {
+ }
};
/**
@@ -2519,6 +2594,12 @@ class Vector2d : public Vector2dBase<Vector2d, StatStor>
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.
@@ -2550,6 +2631,12 @@ class Distribution : public DistBase<Distribution, DistStor>
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
@@ -2576,7 +2663,9 @@ class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
/**
* 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();
@@ -2594,7 +2683,9 @@ class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
/**
* 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();
@@ -2609,6 +2700,12 @@ class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
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).
@@ -2639,6 +2736,13 @@ class VectorStandardDeviation
: 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.
@@ -2662,6 +2766,13 @@ class VectorAverageDeviation
: 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.
@@ -2753,7 +2864,10 @@ class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
}
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
@@ -2870,6 +2984,12 @@ class SparseHistStor
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
@@ -2902,21 +3022,25 @@ class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
/**
* 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.
diff --git a/src/base/stats/group.cc b/src/base/stats/group.cc
new file mode 100644
index 000000000..2bfc89d00
--- /dev/null
+++ b/src/base/stats/group.cc
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * Authors: Andreas Sandberg
+ */
+
+#include "base/stats/group.hh"
+
+#include <cassert>
+
+#include "base/stats/info.hh"
+#include "base/trace.hh"
+#include "debug/Stats.hh"
+#include "sim/sim_object.hh"
+
+namespace Stats {
+
+Group::Group(Group *parent, const char *name)
+ : mergedParent(name ? nullptr : parent)
+{
+ if (parent && name) {
+ parent->addStatGroup(name, this);
+ } else if (parent && !name) {
+ parent->mergeStatGroup(this);
+ }
+}
+
+Group::~Group()
+{
+}
+
+void
+Group::regStats()
+{
+ for (auto &g : mergedStatGroups)
+ g->regStats();
+
+ for (auto &g : statGroups) {
+ if (DTRACE(Stats)) {
+ const SimObject *so = dynamic_cast<const SimObject *>(this);
+ DPRINTF(Stats, "%s: regStats in group %s\n",
+ so ? so->name() : "?",
+ g.first);
+ }
+ g.second->regStats();
+ }
+}
+
+void
+Group::resetStats()
+{
+ for (auto &s : stats)
+ s->reset();
+
+ for (auto &g : mergedStatGroups)
+ g->resetStats();
+
+ for (auto &g : statGroups)
+ g.second->resetStats();
+}
+
+void
+Group::addStat(Stats::Info *info)
+{
+ stats.push_back(info);
+ if (mergedParent)
+ mergedParent->addStat(info);
+}
+
+void
+Group::addStatGroup(const char *name, Group *block)
+{
+ assert(statGroups.find(name) == statGroups.end());
+
+ statGroups[name] = block;
+}
+
+void
+Group::mergeStatGroup(Group *block)
+{
+ mergedStatGroups.push_back(block);
+}
+
+const std::map<std::string, Group *> &
+Group::getStatGroups() const
+{
+ return statGroups;
+}
+
+const std::vector<Info *> &
+Group::getStats() const
+{
+ return stats;
+}
+
+} // namespace Stats
diff --git a/src/base/stats/group.hh b/src/base/stats/group.hh
new file mode 100644
index 000000000..f65e46448
--- /dev/null
+++ b/src/base/stats/group.hh
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * Authors: Andreas Sandberg
+ */
+
+#ifndef __BASE_STATS_GROUP_HH__
+#define __BASE_STATS_GROUP_HH__
+
+#include <map>
+#include <vector>
+#include <string>
+
+/**
+ * Convenience macro to add a stat to a statistics group.
+ *
+ * This macro is used to add a stat to a Stats::Group in the
+ * initilization list in the Group's constructor. The macro
+ * automatically assigns the stat to the current group and gives it
+ * the same name as in the class. For example:
+ *
+ * \code
+ * struct MyStats : public Stats::Group
+ * {
+ * Stats::Scalar scalar0;
+ * Stats::Scalar scalar1;
+ *
+ * Group()
+ * : ADD_STAT(scalar0, "Description of scalar0"),
+ * scalar1(this, "scalar1", "Description of scalar1")
+ * {
+ * }
+ * };
+ * \endcode
+ */
+#define ADD_STAT(n, ...) n(this, # n, __VA_ARGS__)
+
+namespace Stats {
+
+class Info;
+
+/**
+ * Statistics container.
+ *
+ * A stat group is a hierarchical structure that contain statistics
+ * and other groups. Groups are used by the stat system to reflect
+ * gem5's SimObject hierarchy and to expose internal hierarchy within
+ * an object. They can also be used to conveniently group stats into
+ * their own class/struct and then be merged into the parent group
+ * (typically a SimObject).
+ */
+class Group
+{
+ public:
+ Group() = delete;
+ Group(const Group &) = delete;
+ Group &operator=(const Group &) = delete;
+
+ /**
+ * Construct a new statistics group.
+ *
+ * The constructor takes two parameters, a parent and a name. The
+ * parent group should typically be specified. However, there are
+ * special cases where the parent group may be null. One such
+ * special case is SimObjects where the Python code performs late
+ * binding of the group parent.
+ *
+ * If the name parameter is NULL, the group gets merged into the
+ * parent group instead of creating a sub-group. Stats belonging
+ * to a merged group behave as if they have been added directly to
+ * the parent group.
+ *
+ * @param parent Parent group to associate this object to.
+ * @param name Name of this group, can be NULL to merge this group
+ * with the parent group.
+ */
+ Group(Group *parent, const char *name = nullptr);
+
+ virtual ~Group();
+
+ /**
+ * Callback to set stat parameters.
+ *
+ * This callback is typically used for complex stats (e.g.,
+ * distributions) that need parameters in addition to a name and a
+ * description. Stat names and descriptions should typically be
+ * set from the constructor usingo from the constructor using the
+ * ADD_STAT macro.
+ */
+ virtual void regStats();
+
+ /**
+ * Callback to reset stats.
+ */
+ virtual void resetStats();
+
+ /**
+ * Register a stat with this group. This method is normally called
+ * automatically when a stat is instantiated.
+ */
+ void addStat(Stats::Info *info);
+
+ /**
+ * Get all child groups associated with this object.
+ */
+ const std::map<std::string, Group *> &getStatGroups() const;
+
+ /**
+ * Get all stats associated with this object.
+ */
+ const std::vector<Info *> &getStats() const;
+
+ /**
+ * Add a stat block as a child of this block
+ *
+ * This method may only be called from a Group constructor or from
+ * regStats. It's typically only called explicitly from Python
+ * when setting up the SimObject hierarchy.
+ */
+ void addStatGroup(const char *name, Group *block);
+
+ private:
+ /**
+ * Merge the contents (stats & children) of a block to this block.
+ *
+ * This is called on a parent group by the child when it is being
+ * merged into the parent.
+ */
+ void mergeStatGroup(Group *block);
+
+ private:
+ /** Parent pointer if merged into parent */
+ Group *const mergedParent;
+
+ std::map<std::string, Group *> statGroups;
+ std::vector<Group *> mergedStatGroups;
+ std::vector<Info *> stats;
+};
+
+} // namespace Stats
+
+#endif // __BASE_STATS_GROUP_HH__
diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh
index 9cd33a5f9..fe3860dfb 100644
--- a/src/base/stats/output.hh
+++ b/src/base/stats/output.hh
@@ -1,4 +1,16 @@
/*
+ * 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) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -48,10 +60,14 @@ class SparseHistInfo; // Sparse histogram
struct Output
{
virtual ~Output() {}
+
virtual void begin() = 0;
virtual void end() = 0;
virtual bool valid() const = 0;
+ virtual void beginGroup(const char *name) = 0;
+ virtual void endGroup() = 0;
+
virtual void visit(const ScalarInfo &info) = 0;
virtual void visit(const VectorInfo &info) = 0;
virtual void visit(const DistInfo &info) = 0;
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index 10e94a770..da68188bd 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -1,4 +1,16 @@
/*
+ * 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) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -153,6 +165,32 @@ Text::end()
stream->flush();
}
+std::string
+Text::statName(const std::string &name) const
+{
+ if (path.empty())
+ return name;
+ else
+ return csprintf("%s.%s", path.top(), name);
+}
+
+void
+Text::beginGroup(const char *name)
+{
+ if (path.empty()) {
+ path.push(name);
+ } else {
+ path.push(csprintf("%s.%s", path.top(), name));
+ }
+}
+
+void
+Text::endGroup()
+{
+ assert(!path.empty());
+ path.pop();
+}
+
bool
Text::noOutput(const Info &info)
{
@@ -368,7 +406,7 @@ DistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i)
void
DistPrint::init(const Text *text, const Info &info)
{
- name = info.name;
+ name = text->statName(info.name);
separatorString = info.separatorString;
desc = info.desc;
flags = info.flags;
@@ -511,7 +549,7 @@ Text::visit(const ScalarInfo &info)
ScalarPrint print;
print.value = info.result();
- print.name = info.name;
+ print.name = statName(info.name);
print.desc = info.desc;
print.flags = info.flags;
print.descriptions = descriptions;
@@ -531,7 +569,7 @@ Text::visit(const VectorInfo &info)
size_type size = info.size();
VectorPrint print;
- print.name = info.name;
+ print.name = statName(info.name);
print.separatorString = info.separatorString;
print.desc = info.desc;
print.flags = info.flags;
@@ -606,8 +644,9 @@ Text::visit(const Vector2dInfo &info)
total += yvec[j];
}
- print.name = info.name + "_" +
- (havesub ? info.subnames[i] : std::to_string(i));
+ print.name = statName(
+ info.name + "_" +
+ (havesub ? info.subnames[i] : std::to_string(i)));
print.desc = info.desc;
print.vec = yvec;
print.total = total;
@@ -619,7 +658,7 @@ Text::visit(const Vector2dInfo &info)
total_subname.push_back("total");
if (info.flags.isSet(::Stats::total) && (info.x > 1)) {
- print.name = info.name;
+ print.name = statName(info.name);
print.subnames = total_subname;
print.desc = info.desc;
print.vec = VResult(1, info.total());
@@ -687,7 +726,7 @@ SparseHistPrint::SparseHistPrint(const Text *text, const SparseHistInfo &info)
void
SparseHistPrint::init(const Text *text, const Info &info)
{
- name = info.name;
+ name = text->statName(info.name);
separatorString = info.separatorString;
desc = info.desc;
flags = info.flags;
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index 8bb290a99..c8fba5a19 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -1,4 +1,16 @@
/*
+ * 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) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -32,6 +44,7 @@
#define __BASE_STATS_TEXT_HH__
#include <iosfwd>
+#include <stack>
#include <string>
#include "base/stats/output.hh"
@@ -46,6 +59,9 @@ class Text : public Output
bool mystream;
std::ostream *stream;
+ // Object/group path
+ std::stack<std::string> path;
+
protected:
bool noOutput(const Info &info);
@@ -60,20 +76,25 @@ class Text : public Output
void open(std::ostream &stream);
void open(const std::string &file);
+ std::string statName(const std::string &name) const;
// Implement Visit
- virtual void visit(const ScalarInfo &info);
- virtual void visit(const VectorInfo &info);
- virtual void visit(const DistInfo &info);
- virtual void visit(const VectorDistInfo &info);
- virtual void visit(const Vector2dInfo &info);
- virtual void visit(const FormulaInfo &info);
- virtual void visit(const SparseHistInfo &info);
+ void visit(const ScalarInfo &info) override;
+ void visit(const VectorInfo &info) override;
+ void visit(const DistInfo &info) override;
+ void visit(const VectorDistInfo &info) override;
+ void visit(const Vector2dInfo &info) override;
+ void visit(const FormulaInfo &info) override;
+ void visit(const SparseHistInfo &info) override;
+
+ // Group handling
+ void beginGroup(const char *name) override;
+ void endGroup() override;
// Implement Output
- virtual bool valid() const;
- virtual void begin();
- virtual void end();
+ bool valid() const override;
+ void begin() override;
+ void end() override;
};
std::string ValueToString(Result value, int precision);
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index 317ae6c33..3d2f123b9 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -1086,7 +1086,7 @@ class SimObject(object):
abstract = True
cxx_header = "sim/sim_object.hh"
- cxx_extra_bases = [ "Drainable", "Serializable" ]
+ cxx_extra_bases = [ "Drainable", "Serializable", "Stats::Group" ]
eventq_index = Param.UInt32(Parent.eventq_index, "Event Queue Index")
cxx_exports = [
@@ -1094,8 +1094,6 @@ class SimObject(object):
PyBindMethod("initState"),
PyBindMethod("memInvalidate"),
PyBindMethod("memWriteback"),
- PyBindMethod("regStats"),
- PyBindMethod("resetStats"),
PyBindMethod("regProbePoints"),
PyBindMethod("regProbeListeners"),
PyBindMethod("startup"),
diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py
index f8da1fb32..1369fb5ed 100644
--- a/src/python/m5/simulate.py
+++ b/src/python/m5/simulate.py
@@ -124,7 +124,8 @@ def instantiate(ckpt_dir=None):
for obj in root.descendants(): obj.init()
# Do a third pass to initialize statistics
- for obj in root.descendants(): obj.regStats()
+ stats._bindStatHierarchy(root)
+ root.regStats()
# Do a fourth pass to initialize probe points
for obj in root.descendants(): obj.regProbePoints()
diff --git a/src/python/m5/stats/__init__.py b/src/python/m5/stats/__init__.py
index 019c7ebb8..d9174d387 100644
--- a/src/python/m5/stats/__init__.py
+++ b/src/python/m5/stats/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 ARM Limited
+# Copyright (c) 2017, 2019 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@@ -158,6 +158,29 @@ def initSimStats():
_m5.stats.initSimStats()
_m5.stats.registerPythonStatsHandlers()
+def _visit_groups(root, visitor):
+ for group in root.getStatGroups().values():
+ visitor(group)
+ _visit_groups(group, visitor)
+
+def _visit_stats(root, visitor):
+ def for_each_stat(g):
+ for stat in g.getStats():
+ visitor(g, stat)
+ _visit_groups(root, for_each_stat)
+
+def _bindStatHierarchy(root):
+ def _bind_obj(name, obj):
+ if m5.SimObject.isSimObjectVector(obj):
+ for idx, obj in enumerate(obj):
+ _bind_obj("{}{}".format(name, idx), obj)
+ else:
+ root.addStatGroup(name, obj.getCCObject())
+ _bindStatHierarchy(obj)
+
+ for name, obj in root._children.items():
+ _bind_obj(name, obj)
+
names = []
stats_dict = {}
stats_list = []
@@ -166,10 +189,7 @@ def enable():
enabled, all statistics must be created and initialized and once
the package is enabled, no more statistics can be created.'''
- global stats_list
- stats_list = list(_m5.stats.statsList())
-
- for stat in stats_list:
+ def check_stat(group, stat):
if not stat.check() or not stat.baseCheck():
fatal("statistic '%s' (%d) was not properly initialized " \
"by a regStats() function\n", stat.name, stat.id)
@@ -177,21 +197,57 @@ def enable():
if not (stat.flags & flags.display):
stat.name = "__Stat%06d" % stat.id
+
+ # Legacy stat
+ global stats_list
+ stats_list = list(_m5.stats.statsList())
+
+ for stat in stats_list:
+ check_stat(None, stat)
+
stats_list.sort(key=lambda s: s.name.split('.'))
for stat in stats_list:
stats_dict[stat.name] = stat
stat.enable()
+
+ # New stats
+ _visit_stats(Root.getInstance(), check_stat)
+ _visit_stats(Root.getInstance(), lambda g, s: s.enable())
+
_m5.stats.enable();
def prepare():
'''Prepare all stats for data access. This must be done before
dumping and serialization.'''
+ # Legacy stats
for stat in stats_list:
stat.prepare()
+ # New stats
+ _visit_stats(Root.getInstance(), lambda g, s: s.prepare())
+
lastDump = 0
+
+def _dump_to_visitor(visitor):
+ # Legacy stats
+ for stat in stats_list:
+ stat.visit(visitor)
+
+ # New stats
+ def dump_group(group):
+ for stat in group.getStats():
+ stat.visit(visitor)
+
+ for n, g in group.getStatGroups().items():
+ visitor.beginGroup(n)
+ dump_group(g)
+ visitor.endGroup()
+
+ dump_group(Root.getInstance())
+
+
def dump():
'''Dump all statistics data to the registered outputs'''
@@ -210,8 +266,7 @@ def dump():
for output in outputList:
if output.valid():
output.begin()
- for stat in stats_list:
- stat.visit(output)
+ _dump_to_visitor(output)
output.end()
def reset():
@@ -220,9 +275,9 @@ def reset():
# call reset stats on all SimObjects
root = Root.getInstance()
if root:
- for obj in root.descendants(): obj.resetStats()
+ root.resetStats()
- # call any other registered stats reset callbacks
+ # call any other registered legacy stats reset callbacks
for stat in stats_list:
stat.reset()
diff --git a/src/python/pybind11/stats.cc b/src/python/pybind11/stats.cc
index 39d9ce873..1302c7cc5 100644
--- a/src/python/pybind11/stats.cc
+++ b/src/python/pybind11/stats.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited
+ * Copyright (c) 2017, 2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -93,9 +93,12 @@ pybind_init_stats(py::module &m_native)
.def("begin", &Stats::Output::begin)
.def("end", &Stats::Output::end)
.def("valid", &Stats::Output::valid)
+ .def("beginGroup", &Stats::Output::beginGroup)
+ .def("endGroup", &Stats::Output::endGroup)
;
- py::class_<Stats::Info>(m, "Info")
+ py::class_<Stats::Info, std::unique_ptr<Stats::Info, py::nodelete>>(
+ m, "Info")
.def_readwrite("name", &Stats::Info::name)
.def_readonly("desc", &Stats::Info::desc)
.def_readonly("id", &Stats::Info::id)
@@ -110,4 +113,13 @@ pybind_init_stats(py::module &m_native)
.def("zero", &Stats::Info::zero)
.def("visit", &Stats::Info::visit)
;
+
+ py::class_<Stats::Group, std::unique_ptr<Stats::Group, py::nodelete>>(
+ m, "Group")
+ .def("regStats", &Stats::Group::regStats)
+ .def("resetStats", &Stats::Group::resetStats)
+ .def("getStats", &Stats::Group::getStats)
+ .def("getStatGroups", &Stats::Group::getStatGroups)
+ .def("addStatGroup", &Stats::Group::addStatGroup)
+ ;
}
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 7b794a0b7..eb6e15ae1 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -56,7 +56,9 @@ SimObject::SimObjectList SimObject::simObjectList;
// SimObject constructor: used to maintain static simObjectList
//
SimObject::SimObject(const Params *p)
- : EventManager(getEventQueue(p->eventq_index)), _params(p)
+ : EventManager(getEventQueue(p->eventq_index)),
+ Stats::Group(nullptr),
+ _params(p)
{
#ifdef DEBUG
doDebugBreak = false;
@@ -98,19 +100,6 @@ SimObject::startup()
{
}
-//
-// no default statistics, so nothing to do in base implementation
-//
-void
-SimObject::regStats()
-{
-}
-
-void
-SimObject::resetStats()
-{
-}
-
/**
* No probe points by default, so do nothing in base.
*/
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 5c9bf0019..c938ba5e5 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -52,6 +52,7 @@
#include <string>
#include <vector>
+#include "base/stats/group.hh"
#include "params/SimObject.hh"
#include "sim/drain.hh"
#include "sim/eventq.hh"
@@ -92,7 +93,8 @@ class ProbeManager;
* SimObject.py). This has the effect of calling the method on the
* parent node <i>before</i> its children.
*/
-class SimObject : public EventManager, public Serializable, public Drainable
+class SimObject : public EventManager, public Serializable, public Drainable,
+ public Stats::Group
{
private:
typedef std::vector<SimObject *> SimObjectList;
@@ -146,16 +148,6 @@ class SimObject : public EventManager, public Serializable, public Drainable
virtual void initState();
/**
- * Register statistics for this object.
- */
- virtual void regStats();
-
- /**
- * Reset statistics associated with this object.
- */
- virtual void resetStats();
-
- /**
* Register probe points for this object.
*/
virtual void regProbePoints();