__init__.py revision 14205
114205Sandreas.sandberg@arm.com# Copyright (c) 2017, 2019 Arm Limited 211878Sandreas.sandberg@arm.com# All rights reserved. 311878Sandreas.sandberg@arm.com# 411878Sandreas.sandberg@arm.com# The license below extends only to copyright in the software and shall 511878Sandreas.sandberg@arm.com# not be construed as granting a license to any other intellectual 611878Sandreas.sandberg@arm.com# property including but not limited to intellectual property relating 711878Sandreas.sandberg@arm.com# to a hardware implementation of the functionality of the software 811878Sandreas.sandberg@arm.com# licensed hereunder. You may use the software subject to the license 911878Sandreas.sandberg@arm.com# terms below provided that you ensure that this notice is replicated 1011878Sandreas.sandberg@arm.com# unmodified and in its entirety in all distributions of the software, 1111878Sandreas.sandberg@arm.com# modified or unmodified, in source code or in binary form. 1211878Sandreas.sandberg@arm.com# 134126SN/A# Copyright (c) 2007 The Regents of The University of Michigan 148295Snate@binkert.org# Copyright (c) 2010 The Hewlett-Packard Development Company 154126SN/A# All rights reserved. 164126SN/A# 174126SN/A# Redistribution and use in source and binary forms, with or without 184126SN/A# modification, are permitted provided that the following conditions are 194126SN/A# met: redistributions of source code must retain the above copyright 204126SN/A# notice, this list of conditions and the following disclaimer; 214126SN/A# redistributions in binary form must reproduce the above copyright 224126SN/A# notice, this list of conditions and the following disclaimer in the 234126SN/A# documentation and/or other materials provided with the distribution; 244126SN/A# neither the name of the copyright holders nor the names of its 254126SN/A# contributors may be used to endorse or promote products derived from 264126SN/A# this software without specific prior written permission. 274126SN/A# 284126SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294126SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304126SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 314126SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324126SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334126SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344126SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354126SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364126SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374126SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384126SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394126SN/A# 404126SN/A# Authors: Nathan Binkert 4111878Sandreas.sandberg@arm.com# Andreas Sandberg 424126SN/A 438296Snate@binkert.orgimport m5 448296Snate@binkert.org 4511802Sandreas.sandberg@arm.comimport _m5.stats 468295Snate@binkert.orgfrom m5.objects import Root 478296Snate@binkert.orgfrom m5.util import attrdict, fatal 484126SN/A 4911766Sandreas.sandberg@arm.com# Stat exports 5011802Sandreas.sandberg@arm.comfrom _m5.stats import schedStatEvent as schedEvent 5111802Sandreas.sandberg@arm.comfrom _m5.stats import periodicStatDump 5211766Sandreas.sandberg@arm.com 538296Snate@binkert.orgoutputList = [] 5411878Sandreas.sandberg@arm.com 5511878Sandreas.sandberg@arm.comdef _url_factory(func): 5611878Sandreas.sandberg@arm.com """Wrap a plain Python function with URL parsing helpers 5711878Sandreas.sandberg@arm.com 5811878Sandreas.sandberg@arm.com Wrap a plain Python function f(fn, **kwargs) to expect a URL that 5911878Sandreas.sandberg@arm.com has been split using urlparse.urlsplit. First positional argument 6011878Sandreas.sandberg@arm.com is assumed to be a filename, this is created as the concatenation 6111878Sandreas.sandberg@arm.com of the netloc (~hostname) and path in the parsed URL. Keyword 6211878Sandreas.sandberg@arm.com arguments are derived from the query values in the URL. 6311878Sandreas.sandberg@arm.com 6411878Sandreas.sandberg@arm.com For example: 6511878Sandreas.sandberg@arm.com wrapped_f(urlparse.urlsplit("text://stats.txt?desc=False")) -> 6611878Sandreas.sandberg@arm.com f("stats.txt", desc=False) 6711878Sandreas.sandberg@arm.com 6811878Sandreas.sandberg@arm.com """ 6911878Sandreas.sandberg@arm.com 7011878Sandreas.sandberg@arm.com from functools import wraps 7111878Sandreas.sandberg@arm.com 7211878Sandreas.sandberg@arm.com @wraps(func) 7311878Sandreas.sandberg@arm.com def wrapper(url): 7413712Sandreas.sandberg@arm.com try: 7513712Sandreas.sandberg@arm.com from urllib.parse import parse_qs 7613712Sandreas.sandberg@arm.com except ImportError: 7713712Sandreas.sandberg@arm.com # Python 2 fallback 7813712Sandreas.sandberg@arm.com from urlparse import parse_qs 7911878Sandreas.sandberg@arm.com from ast import literal_eval 8011878Sandreas.sandberg@arm.com 8111878Sandreas.sandberg@arm.com qs = parse_qs(url.query, keep_blank_values=True) 8211878Sandreas.sandberg@arm.com 8311878Sandreas.sandberg@arm.com # parse_qs returns a list of values for each parameter. Only 8411878Sandreas.sandberg@arm.com # use the last value since kwargs don't allow multiple values 8511878Sandreas.sandberg@arm.com # per parameter. Use literal_eval to transform string param 8611878Sandreas.sandberg@arm.com # values into proper Python types. 8711878Sandreas.sandberg@arm.com def parse_value(key, values): 8811878Sandreas.sandberg@arm.com if len(values) == 0 or (len(values) == 1 and not values[0]): 8911878Sandreas.sandberg@arm.com fatal("%s: '%s' doesn't have a value." % (url.geturl(), key)) 9011878Sandreas.sandberg@arm.com elif len(values) > 1: 9111878Sandreas.sandberg@arm.com fatal("%s: '%s' has multiple values." % (url.geturl(), key)) 9211878Sandreas.sandberg@arm.com else: 9311878Sandreas.sandberg@arm.com try: 9411878Sandreas.sandberg@arm.com return key, literal_eval(values[0]) 9511878Sandreas.sandberg@arm.com except ValueError: 9611878Sandreas.sandberg@arm.com fatal("%s: %s isn't a valid Python literal" \ 9711878Sandreas.sandberg@arm.com % (url.geturl(), values[0])) 9811878Sandreas.sandberg@arm.com 9911878Sandreas.sandberg@arm.com kwargs = dict([ parse_value(k, v) for k, v in qs.items() ]) 10011878Sandreas.sandberg@arm.com 10111878Sandreas.sandberg@arm.com try: 10211878Sandreas.sandberg@arm.com return func("%s%s" % (url.netloc, url.path), **kwargs) 10311878Sandreas.sandberg@arm.com except TypeError: 10411878Sandreas.sandberg@arm.com fatal("Illegal stat visitor parameter specified") 10511878Sandreas.sandberg@arm.com 10611878Sandreas.sandberg@arm.com return wrapper 10711878Sandreas.sandberg@arm.com 10811878Sandreas.sandberg@arm.com@_url_factory 10911878Sandreas.sandberg@arm.comdef _textFactory(fn, desc=True): 11011878Sandreas.sandberg@arm.com """Output stats in text format. 11111878Sandreas.sandberg@arm.com 11211878Sandreas.sandberg@arm.com Text stat files contain one stat per line with an optional 11311878Sandreas.sandberg@arm.com description. The description is enabled by default, but can be 11411878Sandreas.sandberg@arm.com disabled by setting the desc parameter to False. 11511878Sandreas.sandberg@arm.com 11611878Sandreas.sandberg@arm.com Example: text://stats.txt?desc=False 11711878Sandreas.sandberg@arm.com 11811878Sandreas.sandberg@arm.com """ 11911878Sandreas.sandberg@arm.com 12011878Sandreas.sandberg@arm.com return _m5.stats.initText(fn, desc) 12111878Sandreas.sandberg@arm.com 12211878Sandreas.sandberg@arm.comfactories = { 12311878Sandreas.sandberg@arm.com # Default to the text factory if we're given a naked path 12411878Sandreas.sandberg@arm.com "" : _textFactory, 12511878Sandreas.sandberg@arm.com "file" : _textFactory, 12611878Sandreas.sandberg@arm.com "text" : _textFactory, 12711878Sandreas.sandberg@arm.com} 12811878Sandreas.sandberg@arm.com 12911878Sandreas.sandberg@arm.comdef addStatVisitor(url): 13011878Sandreas.sandberg@arm.com """Add a stat visitor specified using a URL string 13111878Sandreas.sandberg@arm.com 13211878Sandreas.sandberg@arm.com Stat visitors are specified using URLs on the following format: 13311878Sandreas.sandberg@arm.com format://path[?param=value[;param=value]] 13411878Sandreas.sandberg@arm.com 13511878Sandreas.sandberg@arm.com The available formats are listed in the factories list. Factories 13611878Sandreas.sandberg@arm.com are called with the path as the first positional parameter and the 13711878Sandreas.sandberg@arm.com parameters are keyword arguments. Parameter values must be valid 13811878Sandreas.sandberg@arm.com Python literals. 13911878Sandreas.sandberg@arm.com 14011878Sandreas.sandberg@arm.com """ 14111878Sandreas.sandberg@arm.com 14213712Sandreas.sandberg@arm.com try: 14313712Sandreas.sandberg@arm.com from urllib.parse import urlsplit 14413712Sandreas.sandberg@arm.com except ImportError: 14513712Sandreas.sandberg@arm.com # Python 2 fallback 14613712Sandreas.sandberg@arm.com from urlparse import urlsplit 14711878Sandreas.sandberg@arm.com 14811878Sandreas.sandberg@arm.com parsed = urlsplit(url) 14911878Sandreas.sandberg@arm.com 15011878Sandreas.sandberg@arm.com try: 15111878Sandreas.sandberg@arm.com factory = factories[parsed.scheme] 15211878Sandreas.sandberg@arm.com except KeyError: 15311878Sandreas.sandberg@arm.com fatal("Illegal stat file type specified.") 15411878Sandreas.sandberg@arm.com 15511878Sandreas.sandberg@arm.com outputList.append(factory(parsed)) 1564126SN/A 1576001SN/Adef initSimStats(): 15811802Sandreas.sandberg@arm.com _m5.stats.initSimStats() 15911802Sandreas.sandberg@arm.com _m5.stats.registerPythonStatsHandlers() 1606001SN/A 16114205Sandreas.sandberg@arm.comdef _visit_groups(root, visitor): 16214205Sandreas.sandberg@arm.com for group in root.getStatGroups().values(): 16314205Sandreas.sandberg@arm.com visitor(group) 16414205Sandreas.sandberg@arm.com _visit_groups(group, visitor) 16514205Sandreas.sandberg@arm.com 16614205Sandreas.sandberg@arm.comdef _visit_stats(root, visitor): 16714205Sandreas.sandberg@arm.com def for_each_stat(g): 16814205Sandreas.sandberg@arm.com for stat in g.getStats(): 16914205Sandreas.sandberg@arm.com visitor(g, stat) 17014205Sandreas.sandberg@arm.com _visit_groups(root, for_each_stat) 17114205Sandreas.sandberg@arm.com 17214205Sandreas.sandberg@arm.comdef _bindStatHierarchy(root): 17314205Sandreas.sandberg@arm.com def _bind_obj(name, obj): 17414205Sandreas.sandberg@arm.com if m5.SimObject.isSimObjectVector(obj): 17514205Sandreas.sandberg@arm.com for idx, obj in enumerate(obj): 17614205Sandreas.sandberg@arm.com _bind_obj("{}{}".format(name, idx), obj) 17714205Sandreas.sandberg@arm.com else: 17814205Sandreas.sandberg@arm.com root.addStatGroup(name, obj.getCCObject()) 17914205Sandreas.sandberg@arm.com _bindStatHierarchy(obj) 18014205Sandreas.sandberg@arm.com 18114205Sandreas.sandberg@arm.com for name, obj in root._children.items(): 18214205Sandreas.sandberg@arm.com _bind_obj(name, obj) 18314205Sandreas.sandberg@arm.com 1848295Snate@binkert.orgnames = [] 1858295Snate@binkert.orgstats_dict = {} 1868295Snate@binkert.orgstats_list = [] 1876001SN/Adef enable(): 1888295Snate@binkert.org '''Enable the statistics package. Before the statistics package is 1898295Snate@binkert.org enabled, all statistics must be created and initialized and once 1908295Snate@binkert.org the package is enabled, no more statistics can be created.''' 1918295Snate@binkert.org 19214205Sandreas.sandberg@arm.com def check_stat(group, stat): 1938296Snate@binkert.org if not stat.check() or not stat.baseCheck(): 19410169SCurtis.Dunham@arm.com fatal("statistic '%s' (%d) was not properly initialized " \ 19510169SCurtis.Dunham@arm.com "by a regStats() function\n", stat.name, stat.id) 1968296Snate@binkert.org 1978296Snate@binkert.org if not (stat.flags & flags.display): 1988296Snate@binkert.org stat.name = "__Stat%06d" % stat.id 1998296Snate@binkert.org 20014205Sandreas.sandberg@arm.com 20114205Sandreas.sandberg@arm.com # Legacy stat 20214205Sandreas.sandberg@arm.com global stats_list 20314205Sandreas.sandberg@arm.com stats_list = list(_m5.stats.statsList()) 20414205Sandreas.sandberg@arm.com 20514205Sandreas.sandberg@arm.com for stat in stats_list: 20614205Sandreas.sandberg@arm.com check_stat(None, stat) 20714205Sandreas.sandberg@arm.com 20813681Sandreas.sandberg@arm.com stats_list.sort(key=lambda s: s.name.split('.')) 2098295Snate@binkert.org for stat in stats_list: 2108295Snate@binkert.org stats_dict[stat.name] = stat 2118296Snate@binkert.org stat.enable() 2128295Snate@binkert.org 21314205Sandreas.sandberg@arm.com 21414205Sandreas.sandberg@arm.com # New stats 21514205Sandreas.sandberg@arm.com _visit_stats(Root.getInstance(), check_stat) 21614205Sandreas.sandberg@arm.com _visit_stats(Root.getInstance(), lambda g, s: s.enable()) 21714205Sandreas.sandberg@arm.com 21811802Sandreas.sandberg@arm.com _m5.stats.enable(); 2198986SAli.Saidi@ARM.com 2208296Snate@binkert.orgdef prepare(): 2218296Snate@binkert.org '''Prepare all stats for data access. This must be done before 2228296Snate@binkert.org dumping and serialization.''' 2236001SN/A 22414205Sandreas.sandberg@arm.com # Legacy stats 2258296Snate@binkert.org for stat in stats_list: 2268296Snate@binkert.org stat.prepare() 2278296Snate@binkert.org 22814205Sandreas.sandberg@arm.com # New stats 22914205Sandreas.sandberg@arm.com _visit_stats(Root.getInstance(), lambda g, s: s.prepare()) 23014205Sandreas.sandberg@arm.com 2318296Snate@binkert.orglastDump = 0 23214205Sandreas.sandberg@arm.com 23314205Sandreas.sandberg@arm.comdef _dump_to_visitor(visitor): 23414205Sandreas.sandberg@arm.com # Legacy stats 23514205Sandreas.sandberg@arm.com for stat in stats_list: 23614205Sandreas.sandberg@arm.com stat.visit(visitor) 23714205Sandreas.sandberg@arm.com 23814205Sandreas.sandberg@arm.com # New stats 23914205Sandreas.sandberg@arm.com def dump_group(group): 24014205Sandreas.sandberg@arm.com for stat in group.getStats(): 24114205Sandreas.sandberg@arm.com stat.visit(visitor) 24214205Sandreas.sandberg@arm.com 24314205Sandreas.sandberg@arm.com for n, g in group.getStatGroups().items(): 24414205Sandreas.sandberg@arm.com visitor.beginGroup(n) 24514205Sandreas.sandberg@arm.com dump_group(g) 24614205Sandreas.sandberg@arm.com visitor.endGroup() 24714205Sandreas.sandberg@arm.com 24814205Sandreas.sandberg@arm.com dump_group(Root.getInstance()) 24914205Sandreas.sandberg@arm.com 25014205Sandreas.sandberg@arm.com 2516001SN/Adef dump(): 2528296Snate@binkert.org '''Dump all statistics data to the registered outputs''' 2536001SN/A 2548296Snate@binkert.org curTick = m5.curTick() 2558296Snate@binkert.org 2568296Snate@binkert.org global lastDump 2578296Snate@binkert.org assert lastDump <= curTick 2588296Snate@binkert.org if lastDump == curTick: 2598296Snate@binkert.org return 2608296Snate@binkert.org lastDump = curTick 2618296Snate@binkert.org 26211802Sandreas.sandberg@arm.com _m5.stats.processDumpQueue() 2639042SMitchell.Hayenga@ARM.com 2648296Snate@binkert.org prepare() 2658296Snate@binkert.org 2668296Snate@binkert.org for output in outputList: 2678296Snate@binkert.org if output.valid(): 2688296Snate@binkert.org output.begin() 26914205Sandreas.sandberg@arm.com _dump_to_visitor(output) 2708296Snate@binkert.org output.end() 2716001SN/A 2726001SN/Adef reset(): 2738296Snate@binkert.org '''Reset all statistics to the base state''' 2748296Snate@binkert.org 2757527SN/A # call reset stats on all SimObjects 2767527SN/A root = Root.getInstance() 2777802SN/A if root: 27814205Sandreas.sandberg@arm.com root.resetStats() 2797802SN/A 28014205Sandreas.sandberg@arm.com # call any other registered legacy stats reset callbacks 2818296Snate@binkert.org for stat in stats_list: 2828296Snate@binkert.org stat.reset() 2838296Snate@binkert.org 28411802Sandreas.sandberg@arm.com _m5.stats.processResetQueue() 2858295Snate@binkert.org 2868295Snate@binkert.orgflags = attrdict({ 2878295Snate@binkert.org 'none' : 0x0000, 2888295Snate@binkert.org 'init' : 0x0001, 2898295Snate@binkert.org 'display' : 0x0002, 2908295Snate@binkert.org 'total' : 0x0010, 2918295Snate@binkert.org 'pdf' : 0x0020, 2928295Snate@binkert.org 'cdf' : 0x0040, 2938295Snate@binkert.org 'dist' : 0x0080, 2948295Snate@binkert.org 'nozero' : 0x0100, 2958295Snate@binkert.org 'nonan' : 0x0200, 2968295Snate@binkert.org}) 297