__init__.py revision 11320:42ecb523c64a
112855Sgabeblack@google.com# Copyright (c) 2008-2009 The Hewlett-Packard Development Company 212855Sgabeblack@google.com# Copyright (c) 2004-2006 The Regents of The University of Michigan 312855Sgabeblack@google.com# All rights reserved. 412855Sgabeblack@google.com# 512855Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without 612855Sgabeblack@google.com# modification, are permitted provided that the following conditions are 712855Sgabeblack@google.com# met: redistributions of source code must retain the above copyright 812855Sgabeblack@google.com# notice, this list of conditions and the following disclaimer; 912855Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright 1012855Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the 1112855Sgabeblack@google.com# documentation and/or other materials provided with the distribution; 1212855Sgabeblack@google.com# neither the name of the copyright holders nor the names of its 1312855Sgabeblack@google.com# contributors may be used to endorse or promote products derived from 1412855Sgabeblack@google.com# this software without specific prior written permission. 1512855Sgabeblack@google.com# 1612855Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712855Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812855Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912855Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012855Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112855Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212855Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312855Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412855Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512855Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612855Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712855Sgabeblack@google.com# 2812855Sgabeblack@google.com# Authors: Nathan Binkert 2912855Sgabeblack@google.com 3012855Sgabeblack@google.comimport os 3112855Sgabeblack@google.comimport re 3212855Sgabeblack@google.comimport sys 3312855Sgabeblack@google.com 3412855Sgabeblack@google.comimport convert 3512855Sgabeblack@google.comimport jobfile 3612855Sgabeblack@google.com 3712855Sgabeblack@google.comfrom attrdict import attrdict, multiattrdict, optiondict 3812855Sgabeblack@google.comfrom code_formatter import code_formatter 3912855Sgabeblack@google.comfrom multidict import multidict 4012855Sgabeblack@google.comfrom orderdict import orderdict 4112855Sgabeblack@google.comfrom smartdict import SmartDict 4212855Sgabeblack@google.comfrom sorteddict import SortedDict 4312855Sgabeblack@google.comfrom region import neg_inf, pos_inf, Region, Regions 4412855Sgabeblack@google.com 4512855Sgabeblack@google.com# panic() should be called when something happens that should never 4612855Sgabeblack@google.com# ever happen regardless of what the user does (i.e., an acutal m5 4712855Sgabeblack@google.com# bug). 4812855Sgabeblack@google.comdef panic(fmt, *args): 4912855Sgabeblack@google.com print >>sys.stderr, 'panic:', fmt % args 5012855Sgabeblack@google.com sys.exit(1) 5112855Sgabeblack@google.com 5212855Sgabeblack@google.com# fatal() should be called when the simulation cannot continue due to 5312855Sgabeblack@google.com# some condition that is the user's fault (bad configuration, invalid 5412855Sgabeblack@google.com# arguments, etc.) and not a simulator bug. 5512855Sgabeblack@google.comdef fatal(fmt, *args): 5612855Sgabeblack@google.com print >>sys.stderr, 'fatal:', fmt % args 5712855Sgabeblack@google.com sys.exit(1) 5812855Sgabeblack@google.com 5912855Sgabeblack@google.com# warn() should be called when the user should be warned about some condition 6012855Sgabeblack@google.com# that may or may not be the user's fault, but that they should be made aware 6112855Sgabeblack@google.com# of as it may affect the simulation or results. 6212855Sgabeblack@google.comdef warn(fmt, *args): 6312855Sgabeblack@google.com print >>sys.stderr, 'warn:', fmt % args 6412855Sgabeblack@google.com 6512855Sgabeblack@google.com# inform() should be called when the user should be informed about some 6612855Sgabeblack@google.com# condition that they may be interested in. 6712855Sgabeblack@google.comdef inform(fmt, *args): 6812855Sgabeblack@google.com print >>sys.stdout, 'info:', fmt % args 6912855Sgabeblack@google.com 7012855Sgabeblack@google.comclass Singleton(type): 7112855Sgabeblack@google.com def __call__(cls, *args, **kwargs): 7212855Sgabeblack@google.com if hasattr(cls, '_instance'): 7312855Sgabeblack@google.com return cls._instance 7412855Sgabeblack@google.com 7512855Sgabeblack@google.com cls._instance = super(Singleton, cls).__call__(*args, **kwargs) 7612855Sgabeblack@google.com return cls._instance 7712855Sgabeblack@google.com 7812855Sgabeblack@google.comdef addToPath(path): 7912855Sgabeblack@google.com """Prepend given directory to system module search path. We may not 8012855Sgabeblack@google.com need this anymore if we can structure our config library more like a 8112855Sgabeblack@google.com Python package.""" 8212855Sgabeblack@google.com 8312855Sgabeblack@google.com # if it's a relative path and we know what directory the current 8412855Sgabeblack@google.com # python script is in, make the path relative to that directory. 8512855Sgabeblack@google.com if not os.path.isabs(path) and sys.path[0]: 8612855Sgabeblack@google.com path = os.path.join(sys.path[0], path) 8712855Sgabeblack@google.com path = os.path.realpath(path) 8812855Sgabeblack@google.com # sys.path[0] should always refer to the current script's directory, 8912855Sgabeblack@google.com # so place the new dir right after that. 9012855Sgabeblack@google.com sys.path.insert(1, path) 9112855Sgabeblack@google.com 9212855Sgabeblack@google.com# Apply method to object. 9312855Sgabeblack@google.com# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>) 9412855Sgabeblack@google.comdef applyMethod(obj, meth, *args, **kwargs): 9512855Sgabeblack@google.com return getattr(obj, meth)(*args, **kwargs) 9612855Sgabeblack@google.com 9712855Sgabeblack@google.com# If the first argument is an (non-sequence) object, apply the named 9812855Sgabeblack@google.com# method with the given arguments. If the first argument is a 9912855Sgabeblack@google.com# sequence, apply the method to each element of the sequence (a la 10012855Sgabeblack@google.com# 'map'). 10112855Sgabeblack@google.comdef applyOrMap(objOrSeq, meth, *args, **kwargs): 10212855Sgabeblack@google.com if not isinstance(objOrSeq, (list, tuple)): 10312855Sgabeblack@google.com return applyMethod(objOrSeq, meth, *args, **kwargs) 10412855Sgabeblack@google.com else: 10512855Sgabeblack@google.com return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] 10612855Sgabeblack@google.com 10712855Sgabeblack@google.comdef compareVersions(v1, v2): 10812855Sgabeblack@google.com """helper function: compare arrays or strings of version numbers. 10912855Sgabeblack@google.com E.g., compare_version((1,3,25), (1,4,1)') 11012855Sgabeblack@google.com returns -1, 0, 1 if v1 is <, ==, > v2 11112855Sgabeblack@google.com """ 11212855Sgabeblack@google.com def make_version_list(v): 11312855Sgabeblack@google.com if isinstance(v, (list,tuple)): 11412855Sgabeblack@google.com return v 11512855Sgabeblack@google.com elif isinstance(v, str): 11612855Sgabeblack@google.com return map(lambda x: int(re.match('\d+', x).group()), v.split('.')) 11712855Sgabeblack@google.com else: 11812855Sgabeblack@google.com raise TypeError 11912855Sgabeblack@google.com 12012855Sgabeblack@google.com v1 = make_version_list(v1) 12112855Sgabeblack@google.com v2 = make_version_list(v2) 12212855Sgabeblack@google.com # Compare corresponding elements of lists 12312855Sgabeblack@google.com for n1,n2 in zip(v1, v2): 12412855Sgabeblack@google.com if n1 < n2: return -1 12512855Sgabeblack@google.com if n1 > n2: return 1 12612855Sgabeblack@google.com # all corresponding values are equal... see if one has extra values 12712855Sgabeblack@google.com if len(v1) < len(v2): return -1 12812855Sgabeblack@google.com if len(v1) > len(v2): return 1 12912855Sgabeblack@google.com return 0 13012855Sgabeblack@google.com 13112855Sgabeblack@google.comdef crossproduct(items): 13212855Sgabeblack@google.com if len(items) == 1: 13312855Sgabeblack@google.com for i in items[0]: 13412855Sgabeblack@google.com yield (i,) 13512855Sgabeblack@google.com else: 13612855Sgabeblack@google.com for i in items[0]: 13712855Sgabeblack@google.com for j in crossproduct(items[1:]): 13812855Sgabeblack@google.com yield (i,) + j 13912855Sgabeblack@google.com 14012855Sgabeblack@google.comdef flatten(items): 14112855Sgabeblack@google.com while items: 14212855Sgabeblack@google.com item = items.pop(0) 14312855Sgabeblack@google.com if isinstance(item, (list, tuple)): 14412855Sgabeblack@google.com items[0:0] = item 14512855Sgabeblack@google.com else: 14612855Sgabeblack@google.com yield item 14712855Sgabeblack@google.com 14812855Sgabeblack@google.com# force scalars to one-element lists for uniformity 14912855Sgabeblack@google.comdef makeList(objOrList): 15012855Sgabeblack@google.com if isinstance(objOrList, list): 15112855Sgabeblack@google.com return objOrList 15212855Sgabeblack@google.com return [objOrList] 15312855Sgabeblack@google.com 15412855Sgabeblack@google.comdef printList(items, indent=4): 15512855Sgabeblack@google.com line = ' ' * indent 15612855Sgabeblack@google.com for i,item in enumerate(items): 15712855Sgabeblack@google.com if len(line) + len(item) > 76: 15812855Sgabeblack@google.com print line 15912855Sgabeblack@google.com line = ' ' * indent 16012855Sgabeblack@google.com 16112855Sgabeblack@google.com if i < len(items) - 1: 16212855Sgabeblack@google.com line += '%s, ' % item 16312855Sgabeblack@google.com else: 16412855Sgabeblack@google.com line += item 16512855Sgabeblack@google.com print line 16612855Sgabeblack@google.com 16712855Sgabeblack@google.comdef readCommand(cmd, **kwargs): 16812855Sgabeblack@google.com """run the command cmd, read the results and return them 16912855Sgabeblack@google.com this is sorta like `cmd` in shell""" 17012855Sgabeblack@google.com from subprocess import Popen, PIPE, STDOUT 17112855Sgabeblack@google.com 17212855Sgabeblack@google.com if isinstance(cmd, str): 17312855Sgabeblack@google.com cmd = cmd.split() 17412855Sgabeblack@google.com 17512855Sgabeblack@google.com no_exception = 'exception' in kwargs 17612855Sgabeblack@google.com exception = kwargs.pop('exception', None) 17712855Sgabeblack@google.com 17812855Sgabeblack@google.com kwargs.setdefault('shell', False) 17912855Sgabeblack@google.com kwargs.setdefault('stdout', PIPE) 180 kwargs.setdefault('stderr', STDOUT) 181 kwargs.setdefault('close_fds', True) 182 try: 183 subp = Popen(cmd, **kwargs) 184 except Exception, e: 185 if no_exception: 186 return exception 187 raise 188 189 return subp.communicate()[0] 190 191def makeDir(path): 192 """Make a directory if it doesn't exist. If the path does exist, 193 ensure that it is a directory""" 194 if os.path.exists(path): 195 if not os.path.isdir(path): 196 raise AttributeError, "%s exists but is not directory" % path 197 else: 198 os.mkdir(path) 199