__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