From 1177e7a3c861d77360074e97661952d427cd8640 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 12 May 2011 11:19:35 -0700 Subject: stats: move code that loops over all stats into python --- src/python/m5/simulate.py | 2 +- src/python/m5/stats/__init__.py | 57 +++++++++++++++++++++++++++++++++-------- src/python/swig/stats.i | 56 +++++++++++++++++++++++++++++++++++----- 3 files changed, 97 insertions(+), 18 deletions(-) (limited to 'src/python') diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 9a5dc836d..b4ccf82c1 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -131,7 +131,7 @@ def curTick(): return internal.core.curTick() # Python exit handlers happen in reverse order. We want to dump stats last. -atexit.register(internal.stats.dump) +atexit.register(stats.dump) # register our C++ exit callback function with Python atexit.register(internal.core.doExitCleanup) diff --git a/src/python/m5/stats/__init__.py b/src/python/m5/stats/__init__.py index 612dbdfb5..f6da096f0 100644 --- a/src/python/m5/stats/__init__.py +++ b/src/python/m5/stats/__init__.py @@ -27,13 +27,17 @@ # # Authors: Nathan Binkert +import m5 + from m5 import internal from m5.internal.stats import schedStatEvent as schedEvent from m5.objects import Root -from m5.util import attrdict +from m5.util import attrdict, fatal +outputList = [] def initText(filename, desc=True): - internal.stats.initText(filename, desc) + output = internal.stats.initText(filename, desc) + outputList.append(output) def initMySQL(host, database, user='', passwd='', project='test', name='test', sample='0'): @@ -41,8 +45,9 @@ def initMySQL(host, database, user='', passwd='', project='test', name='test', import getpass user = getpass.getuser() - internal.stats.initMySQL(host, database, user, passwd, project, name, - sample) + output = internal.stats.initMySQL(host, database, user, passwd, + project, name, sample) + outputList.append(output) def initSimStats(): internal.stats.initSimStats() @@ -70,6 +75,13 @@ def enable(): else: fatal("unknown stat type %s", stat) + for stat in stats_list: + if not stat.check() or not stat.baseCheck(): + fatal("stat check failed for '%s' %d\n", stat.name, stat.id) + + if not (stat.flags & flags.display): + stat.name = "__Stat%06d" % stat.id + def less(stat1, stat2): v1 = stat1.name.split('.') v2 = stat2.name.split('.') @@ -78,24 +90,49 @@ def enable(): stats_list.sort(less) for stat in stats_list: stats_dict[stat.name] = stat + stat.enable() + +def prepare(): + '''Prepare all stats for data access. This must be done before + dumping and serialization.''' - internal.stats.enable() + for stat in stats_list: + stat.prepare() +lastDump = 0 def dump(): - # Currently prepare happens in the dump, but we should maybe move - # that out. + '''Dump all statistics data to the registered outputs''' - #internal.stats.prepare() - internal.stats.dump() + curTick = m5.curTick() + + global lastDump + assert lastDump <= curTick + if lastDump == curTick: + return + lastDump = curTick + + prepare() + + for output in outputList: + if output.valid(): + output.begin() + for stat in stats_list: + output.visit(stat) + output.end() def reset(): + '''Reset all statistics to the base state''' + # call reset stats on all SimObjects root = Root.getInstance() if root: for obj in root.descendants(): obj.resetStats() # call any other registered stats reset callbacks - internal.stats.reset() + for stat in stats_list: + stat.reset() + + internal.stats.processResetQueue() flags = attrdict({ 'none' : 0x0000, diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i index 63539ca83..0633a8c27 100644 --- a/src/python/swig/stats.i +++ b/src/python/swig/stats.i @@ -39,6 +39,8 @@ #include "base/stats/mysql.hh" #include "base/stats/text.hh" #include "base/stats/types.hh" +#include "base/callback.hh" +#include "base/misc.hh" #include "base/statistics.hh" #include "sim/core.hh" #include "sim/stat_control.hh" @@ -63,6 +65,48 @@ Stats_Info_flags_set(Info *info, FlagsType flags) info->flags = flags; } +inline void +processResetQueue() +{ + extern CallbackQueue resetQueue; + resetQueue.process(); +} + +inline char * +PCC(const char *string) +{ + return const_cast(string); +} + +void +call_module_function(const char *module_name, const char *func_name) +{ + PyObject *module = PyImport_ImportModule(PCC(module_name)); + if (module == NULL) + panic("Could not import %s", module); + + PyObject *result = PyObject_CallMethod(module, PCC(func_name), PCC("")); + if (result == NULL) { + PyErr_Print(); + panic("failure on call to function %s", func_name); + } + + Py_DECREF(module); + Py_DECREF(result); +} + +void +dump() +{ + call_module_function("m5.stats", "dump"); +} + +void +reset() +{ + call_module_function("m5.stats", "reset"); +} + } // namespace Stats %} @@ -72,9 +116,10 @@ Stats_Info_flags_set(Info *info, FlagsType flags) %ignore Stats::Info::flags; -%import "base/stats/types.hh" +%import "base/stats/types.hh" %include "base/stats/info.hh" +%include "base/stats/output.hh" namespace std { %template(list_info) list; @@ -95,18 +140,15 @@ template T cast_info(Info *info); %template(dynamic_FormulaInfo) cast_info; void initSimStats(); -void initText(const std::string &filename, bool desc); -void initMySQL(std::string host, std::string database, std::string user, +Output *initText(const std::string &filename, bool desc); +Output *initMySQL(std::string host, std::string database, std::string user, std::string passwd, std::string project, std::string name, std::string sample); void schedStatEvent(bool dump, bool reset, Tick when = curTick(), Tick repeat = 0); -void enable(); -void prepare(); -void dump(); -void reset(); +void processResetQueue(); std::list &statsList(); -- cgit v1.2.3