+# Copyright (c) 2017 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) 2007 The Regents of The University of Michigan
# Copyright (c) 2010 The Hewlett-Packard Development Company
# All rights reserved.
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Nathan Binkert
+# Andreas Sandberg
import m5
-from m5 import internal
-from m5.internal.stats import schedStatEvent as schedEvent
+import _m5.stats
from m5.objects import Root
from m5.util import attrdict, fatal
+# Stat exports
+from _m5.stats import schedStatEvent as schedEvent
+from _m5.stats import periodicStatDump
+
outputList = []
-def initText(filename, desc=True):
- output = internal.stats.initText(filename, desc)
- outputList.append(output)
+
+def _url_factory(func):
+ """Wrap a plain Python function with URL parsing helpers
+
+ Wrap a plain Python function f(fn, **kwargs) to expect a URL that
+ has been split using urlparse.urlsplit. First positional argument
+ is assumed to be a filename, this is created as the concatenation
+ of the netloc (~hostname) and path in the parsed URL. Keyword
+ arguments are derived from the query values in the URL.
+
+ For example:
+ wrapped_f(urlparse.urlsplit("text://stats.txt?desc=False")) ->
+ f("stats.txt", desc=False)
+
+ """
+
+ from functools import wraps
+
+ @wraps(func)
+ def wrapper(url):
+ from urlparse import parse_qs
+ from ast import literal_eval
+
+ qs = parse_qs(url.query, keep_blank_values=True)
+
+ # parse_qs returns a list of values for each parameter. Only
+ # use the last value since kwargs don't allow multiple values
+ # per parameter. Use literal_eval to transform string param
+ # values into proper Python types.
+ def parse_value(key, values):
+ if len(values) == 0 or (len(values) == 1 and not values[0]):
+ fatal("%s: '%s' doesn't have a value." % (url.geturl(), key))
+ elif len(values) > 1:
+ fatal("%s: '%s' has multiple values." % (url.geturl(), key))
+ else:
+ try:
+ return key, literal_eval(values[0])
+ except ValueError:
+ fatal("%s: %s isn't a valid Python literal" \
+ % (url.geturl(), values[0]))
+
+ kwargs = dict([ parse_value(k, v) for k, v in qs.items() ])
+
+ try:
+ return func("%s%s" % (url.netloc, url.path), **kwargs)
+ except TypeError:
+ fatal("Illegal stat visitor parameter specified")
+
+ return wrapper
+
+@_url_factory
+def _textFactory(fn, desc=True):
+ """Output stats in text format.
+
+ Text stat files contain one stat per line with an optional
+ description. The description is enabled by default, but can be
+ disabled by setting the desc parameter to False.
+
+ Example: text://stats.txt?desc=False
+
+ """
+
+ return _m5.stats.initText(fn, desc)
+
+factories = {
+ # Default to the text factory if we're given a naked path
+ "" : _textFactory,
+ "file" : _textFactory,
+ "text" : _textFactory,
+}
+
+def addStatVisitor(url):
+ """Add a stat visitor specified using a URL string
+
+ Stat visitors are specified using URLs on the following format:
+ format://path[?param=value[;param=value]]
+
+ The available formats are listed in the factories list. Factories
+ are called with the path as the first positional parameter and the
+ parameters are keyword arguments. Parameter values must be valid
+ Python literals.
+
+ """
+
+ from urlparse import urlsplit
+
+ parsed = urlsplit(url)
+
+ try:
+ factory = factories[parsed.scheme]
+ except KeyError:
+ fatal("Illegal stat file type specified.")
+
+ outputList.append(factory(parsed))
def initSimStats():
- internal.stats.initSimStats()
+ _m5.stats.initSimStats()
+ _m5.stats.registerPythonStatsHandlers()
names = []
stats_dict = {}
stats_list = []
-raw_stats_list = []
def enable():
'''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.'''
- __dynamic_cast = []
- for k, v in internal.stats.__dict__.iteritems():
- if k.startswith('dynamic_'):
- __dynamic_cast.append(v)
-
- for stat in internal.stats.statsList():
- for cast in __dynamic_cast:
- val = cast(stat)
- if val is not None:
- stats_list.append(val)
- raw_stats_list.append(val)
- break
- else:
- fatal("unknown stat type %s", stat)
+
+ global stats_list
+ stats_list = list(_m5.stats.statsList())
for stat in stats_list:
if not stat.check() or not stat.baseCheck():
stats_dict[stat.name] = stat
stat.enable()
- internal.stats.enable();
+ _m5.stats.enable();
def prepare():
'''Prepare all stats for data access. This must be done before
return
lastDump = curTick
- internal.stats.processDumpQueue()
+ _m5.stats.processDumpQueue()
prepare()
if output.valid():
output.begin()
for stat in stats_list:
- output.visit(stat)
+ stat.visit(output)
output.end()
def reset():
for stat in stats_list:
stat.reset()
- internal.stats.processResetQueue()
+ _m5.stats.processResetQueue()
flags = attrdict({
'none' : 0x0000,