From 6f787e3d368eb248aee0854d99ed55e332d80170 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: [PATCH] stats: create an enable phase, and a prepare phase. Enable more or less takes the place of check, but also allows stats to do some other configuration. Prepare moves all of the code that readies a stat for dumping into a separate function in preparation for supporting serialization of certain pieces of statistics data. While we're at it, clean up the visitor code and some of the python code. --- src/base/statistics.cc | 65 +++++++--- src/base/statistics.hh | 264 ++++++++++++++++++-------------------- src/base/stats/output.cc | 3 + src/python/m5/core.py | 7 + src/python/m5/simulate.py | 14 +- src/python/m5/stats.py | 19 ++- src/python/swig/stats.i | 3 +- 7 files changed, 214 insertions(+), 161 deletions(-) diff --git a/src/base/statistics.cc b/src/base/statistics.cc index c77816f23..0a59248e7 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "base/callback.hh" @@ -174,6 +175,41 @@ Info::baseCheck() const return true; } +void +Info::enable() +{ +} + +void +VectorInfoBase::enable() +{ + size_type s = size(); + if (subnames.size() < s) + subnames.resize(s); + if (subdescs.size() < s) + subdescs.resize(s); +} + +void +VectorDistInfoBase::enable() +{ + size_type s = size(); + if (subnames.size() < s) + subnames.resize(s); + if (subdescs.size() < s) + subdescs.resize(s); +} + +void +Vector2dInfoBase::enable() +{ + if (subnames.size() < x) + subnames.resize(x); + if (subdescs.size() < x) + subdescs.resize(x); + if (y_subnames.size() < y) + y_subnames.resize(y); +} Formula::Formula() { @@ -244,11 +280,6 @@ Formula::zero() const return true; } -void -Formula::update() -{ -} - string Formula::str() const { @@ -256,7 +287,7 @@ Formula::str() const } void -check() +enable() { typedef list::iterator iter_t; @@ -277,17 +308,21 @@ check() statsList().sort(Info::less); - if (i == end) - return; - - iter_t last = i; - ++i; - for (i = statsList().begin(); i != end; ++i) { - if ((*i)->name == (*last)->name) - panic("same name used twice! name=%s\n", (*i)->name); + Info *info = *i; + info->enable(); + } +} - last = i; +void +prepare() +{ + list::iterator i = statsList().begin(); + list::iterator end = statsList().end(); + while (i != end) { + Info *info = *i; + info->prepare(); + ++i; } } diff --git a/src/base/statistics.hh b/src/base/statistics.hh index ef22ebe24..6240be7a2 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -122,6 +122,16 @@ class Info virtual bool check() const = 0; bool baseCheck() const; + /** + * Enable the stat for use + */ + virtual void enable(); + + /** + * Prepare the stat for dumping. + */ + virtual void prepare() = 0; + /** * Reset the stat to the default state. */ @@ -159,7 +169,13 @@ class InfoWrap : public Base InfoWrap(Stat &stat) : s(stat) {} bool check() const { return s.check(); } + void prepare() { s.prepare(); } void reset() { s.reset(); } + void + visit(Visit &visitor) + { + visitor.visit(*static_cast(this)); + } bool zero() const { return s.zero(); } }; @@ -169,7 +185,6 @@ class ScalarInfoBase : public Info virtual Counter value() const = 0; virtual Result result() const = 0; virtual Result total() const = 0; - void visit(Visit &visitor) { visitor.visit(*this); } }; template @@ -190,24 +205,14 @@ class VectorInfoBase : public Info std::vector subnames; std::vector subdescs; + public: + void enable(); + public: virtual size_type size() const = 0; virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; virtual Result total() const = 0; - - void - update() - { - if (!subnames.empty()) { - size_type s = size(); - if (subnames.size() < s) - subnames.resize(s); - - if (subdescs.size() < s) - subdescs.resize(s); - } - } }; template @@ -237,14 +242,6 @@ class VectorInfo : public InfoWrap } Result total() const { return this->s.total(); } - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; struct DistData @@ -271,13 +268,6 @@ class DistInfo : public InfoWrap { public: DistInfo(Stat &stat) : InfoWrap(stat) {} - - void - visit(Visit &visitor) - { - this->s.update(); - visitor.visit(*this); - } }; class VectorDistInfoBase : public Info @@ -288,6 +278,7 @@ class VectorDistInfoBase : public Info /** Names and descriptions of subfields. */ std::vector subnames; std::vector subdescs; + void enable(); protected: /** Local storage for the entry values, used for printing. */ @@ -295,17 +286,6 @@ class VectorDistInfoBase : public Info public: virtual size_type size() const = 0; - - void - update() - { - size_type s = size(); - if (subnames.size() < s) - subnames.resize(s); - - if (subdescs.size() < s) - subdescs.resize(s); - } }; template @@ -315,14 +295,6 @@ class VectorDistInfo : public InfoWrap VectorDistInfo(Stat &stat) : InfoWrap(stat) {} size_type size() const { return this->s.size(); } - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; class Vector2dInfoBase : public Info @@ -339,13 +311,7 @@ class Vector2dInfoBase : public Info /** Local storage for the entry values, used for printing. */ mutable VCounter cvec; - public: - void - update() - { - if (subnames.size() < x) - subnames.resize(x); - } + void enable(); }; template @@ -353,14 +319,6 @@ class Vector2dInfo : public InfoWrap { public: Vector2dInfo(Stat &stat) : InfoWrap(stat) {} - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; class InfoAccess @@ -382,7 +340,7 @@ class InfoAccess /** * Reset the stat to the default state. */ - void reset() {} + void reset() { } /** * @return true if this stat has a value and satisfies its @@ -525,7 +483,7 @@ class DataWrapVec : public DataWrap subname(off_type index, const std::string &name) { Derived &self = this->self(); - Info *info = this->info(); + Info *info = self.info(); std::vector &subn = info->subnames; if (subn.size() <= index) @@ -558,6 +516,17 @@ class DataWrapVec : public DataWrap return this->self(); } + void + prepare() + { + Derived &self = this->self(); + Info *info = this->info(); + + size_t size = self.size(); + for (off_type i = 0; i < size; ++i) + self.data(i)->prepare(info); + } + void reset() { @@ -657,6 +626,10 @@ class StatStor * @return The value of this stat. */ Result result() const { return (Result)data; } + /** + * Prepare stat data for dumping or serialization + */ + void prepare(Info *info) { } /** * Reset stat value to default */ @@ -734,8 +707,7 @@ class AvgStor Result result() const { - total += current * (curTick - last); - last = curTick; + assert(last == curTick); return (Result)(total + current) / (Result)(curTick + 1); } @@ -744,6 +716,16 @@ class AvgStor */ bool zero() const { return total == 0.0; } + /** + * Prepare stat data for dumping or serialization + */ + void + prepare(Info *info) + { + total += current * (curTick - last); + last = curTick; + } + /** * Reset stat value to default */ @@ -863,11 +845,6 @@ class ScalarBase : public DataWrap */ size_type size() const { return 1; } - /** - * Reset stat value to default - */ - void reset() { data()->reset(this->info()); } - Counter value() { return data()->value(); } Result result() { return data()->result(); } @@ -875,17 +852,22 @@ class ScalarBase : public DataWrap Result total() { return result(); } bool zero() { return result() == 0.0; } + + void reset() { data()->reset(this->info()); } + void prepare() { data()->prepare(this->info()); } }; class ProxyInfo : public ScalarInfoBase { public: - void visit(Visit &visitor) { visitor.visit(*this); } std::string str() const { return to_string(value()); } size_type size() const { return 1; } bool check() const { return true; } - void reset() {} + void prepare() { } + void reset() { } bool zero() const { return value() == 0; } + + void visit(Visit &visitor) { visitor.visit(*this); } }; template @@ -950,6 +932,7 @@ class ValueBase : public DataWrap std::string str() const { return proxy->str(); } bool zero() const { return proxy->zero(); } bool check() const { return proxy != NULL; } + void prepare() { } void reset() { } }; @@ -1230,8 +1213,6 @@ class VectorBase : public DataWrapVec assert (index >= 0 && index < size()); return Proxy(this->self(), index); } - - void update() {} }; template @@ -1348,16 +1329,6 @@ class Vector2dBase : public DataWrapVec2d delete [] reinterpret_cast(storage); } - void - update() - { - Info *info = this->info(); - size_type size = this->size(); - info->cvec.resize(size); - for (off_type i = 0; i < size; ++i) - info->cvec[i] = data(i)->value(); - } - Derived & init(size_type _x, size_type _y) { @@ -1413,6 +1384,20 @@ class Vector2dBase : public DataWrapVec2d #endif } + void + prepare() + { + Info *info = this->info(); + size_type size = this->size(); + + for (off_type i = 0; i < size; ++i) + data(i)->prepare(info); + + info->cvec.resize(size); + for (off_type i = 0; i < size; ++i) + info->cvec[i] = data(i)->value(); + } + /** * Reset stat value to default */ @@ -1541,7 +1526,7 @@ class DistStor } void - update(Info *info, DistData &data) + prepare(Info *info, DistData &data) { const Params *params = safe_cast(info->storageParams); @@ -1630,14 +1615,6 @@ class FancyStor samples += number; } - void - update(Info *info, DistData &data) - { - data.sum = sum; - data.squares = squares; - data.samples = samples; - } - /** * Return the number of entries in this stat, 1 * @return 1. @@ -1650,6 +1627,14 @@ class FancyStor */ bool zero() const { return samples == Counter(); } + void + prepare(Info *info, DistData &data) + { + data.sum = sum; + data.squares = squares; + data.samples = samples; + } + /** * Reset stat value to default */ @@ -1702,14 +1687,6 @@ class AvgFancy squares += value * value; } - void - update(Info *info, DistData &data) - { - data.sum = sum; - data.squares = squares; - data.samples = curTick; - } - /** * Return the number of entries, in this case 1. * @return 1. @@ -1722,6 +1699,14 @@ class AvgFancy */ bool zero() const { return sum == Counter(); } + void + prepare(Info *info, DistData &data) + { + data.sum = sum; + data.squares = squares; + data.samples = curTick; + } + /** * Reset stat value to default */ @@ -1801,10 +1786,10 @@ class DistBase : public DataWrap bool zero() const { return data()->zero(); } void - update() + prepare() { Info *info = this->info(); - data()->update(info, info->data); + data()->prepare(info, info->data); } /** @@ -1900,24 +1885,21 @@ class VectorDistBase : public DataWrapVec #endif } + void + prepare() + { + Info *info = this->info(); + size_type size = this->size(); + info->data.resize(size); + for (off_type i = 0; i < size; ++i) + data(i)->prepare(info, info->data[i]); + } + bool check() const { return storage != NULL; } - - void - update() - { - Derived &self = this->self(); - Info *info = this->info(); - - size_type size = self.size(); - info.data.resize(size); - for (off_type i = 0; i < size; ++i) { - data(i)->update(info, info.data[i]); - } - } }; template @@ -2589,14 +2571,6 @@ class FormulaInfo : public InfoWrap Result total() const { return this->s.total(); } VCounter &value() const { return cvec; } - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } - std::string str() const { return this->s.str(); } }; @@ -2677,11 +2651,6 @@ class Formula : public DataWrapVec */ bool zero() const; - /** - * - */ - void update(); - std::string str() const; }; @@ -2876,11 +2845,6 @@ class Temp * @} */ -void check(); -void dump(); -void reset(); -void registerResetCallback(Callback *cb); - inline Temp operator+(Temp l, Temp r) { @@ -2931,6 +2895,34 @@ sum(Temp val) return NodePtr(new SumNode >(val)); } +/** + * Enable the statistics package. Before the statistics package is + * enabled, all statistics must be created and initialized and once + * the package is enabled, no more statistics can be created. + */ +void enable(); + +/** + * Prepare all stats for data access. This must be done before + * dumping and serialization. + */ +void prepare(); + +/** + * Dump all statistics data to the registered outputs + */ +void dump(); + +/** + * Reset all statistics to the base state + */ +void reset(); +/** + * Register a callback that should be called whenever statistics are + * reset + */ +void registerResetCallback(Callback *cb); + std::list &statsList(); /* namespace Stats */ } diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc index 9f2b91c77..31aa21c45 100644 --- a/src/base/stats/output.cc +++ b/src/base/stats/output.cc @@ -30,6 +30,7 @@ #include +#include "base/statistics.hh" #include "base/stats/output.hh" #include "sim/eventq.hh" #include "sim/host.hh" @@ -49,6 +50,8 @@ dump() return; lastDump = curTick; + prepare(); + list::iterator i = OutputList.begin(); list::iterator end = OutputList.end(); for (; i != end; ++i) { diff --git a/src/python/m5/core.py b/src/python/m5/core.py index 232fe2ceb..1d7985be6 100644 --- a/src/python/m5/core.py +++ b/src/python/m5/core.py @@ -27,7 +27,14 @@ # Authors: Nathan Binkert import internal +from internal.core import initAll, regAllStats def setOutputDir(dir): internal.core.setOutputDir(dir) +def initAll(): + internal.core.initAll() + +def regAllStats(): + internal.core.regAllStats() + diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 617ac3be2..45992fe85 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -33,6 +33,8 @@ import sys # import the SWIG-wrapped main C++ functions import internal +import core +import stats from main import options import SimObject import ticks @@ -52,23 +54,23 @@ def instantiate(root): ini_file.close() # Initialize the global statistics - internal.stats.initSimStats() + stats.initSimStats() # Create the C++ sim objects and connect ports root.createCCObject() root.connectPorts() # Do a second pass to finish initializing the sim objects - internal.core.initAll() + core.initAll() # Do a third pass to initialize statistics - internal.core.regAllStats() + core.regAllStats() - # Check to make sure that the stats package is properly initialized - internal.stats.check() + # We're done registering statistics. Enable the stats package now. + stats.enable() # Reset to put the stats in a consistent state. - internal.stats.reset() + stats.reset() def doDot(root): dot = pydot.Dot() diff --git a/src/python/m5/stats.py b/src/python/m5/stats.py index 041a3f58d..5bd9d5f6a 100644 --- a/src/python/m5/stats.py +++ b/src/python/m5/stats.py @@ -28,9 +28,6 @@ import internal -from internal.stats import dump -from internal.stats import initSimStats -from internal.stats import reset from internal.stats import StatEvent as event def initText(filename, desc=True, compat=True): @@ -44,3 +41,19 @@ def initMySQL(host, database, user='', passwd='', project='test', name='test', internal.stats.initMySQL(host, database, user, passwd, project, name, sample) + +def initSimStats(): + internal.stats.initSimStats() + +def enable(): + internal.stats.enable() + +def dump(): + # Currently prepare happens in the dump, but we should maybe move + # that out. + + #internal.stats.prepare() + internal.stats.dump() + +def reset(): + internal.stats.reset() diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i index d36f82dbc..284df8ff8 100644 --- a/src/python/swig/stats.i +++ b/src/python/swig/stats.i @@ -48,7 +48,8 @@ void initMySQL(std::string host, std::string database, std::string user, void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); -void check(); +void enable(); +void prepare(); void dump(); void reset();