summaryrefslogtreecommitdiff
path: root/src/python
diff options
context:
space:
mode:
Diffstat (limited to 'src/python')
-rw-r--r--src/python/SConscript8
-rw-r--r--src/python/m5/SimObject.py1
-rw-r--r--src/python/m5/main.py2
-rw-r--r--src/python/m5/util/__init__.py32
-rw-r--r--src/python/m5/util/attrdict.py (renamed from src/python/m5/attrdict.py)11
-rw-r--r--src/python/m5/util/jobfile.py450
-rw-r--r--src/python/m5/util/misc.py (renamed from src/python/m5/util.py)28
-rw-r--r--src/python/m5/util/multidict.py (renamed from src/python/m5/multidict.py)0
-rw-r--r--src/python/m5/util/orderdict.py80
9 files changed, 606 insertions, 6 deletions
diff --git a/src/python/SConscript b/src/python/SConscript
index b39c9ea9c..0785b4307 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -36,18 +36,20 @@ Source('swig/pyobject.cc')
PySource('m5', 'm5/__init__.py')
PySource('m5', 'm5/SimObject.py')
-PySource('m5', 'm5/attrdict.py')
PySource('m5', 'm5/convert.py')
PySource('m5', 'm5/event.py')
PySource('m5', 'm5/main.py')
-PySource('m5', 'm5/multidict.py')
PySource('m5', 'm5/params.py')
PySource('m5', 'm5/proxy.py')
PySource('m5', 'm5/simulate.py')
PySource('m5', 'm5/smartdict.py')
PySource('m5', 'm5/stats.py')
PySource('m5', 'm5/ticks.py')
-PySource('m5', 'm5/util.py')
+PySource('m5.util', 'm5/util/__init__.py')
+PySource('m5.util', 'm5/util/attrdict.py')
+PySource('m5.util', 'm5/util/jobfile.py')
+PySource('m5.util', 'm5/util/misc.py')
+PySource('m5.util', 'm5/util/multidict.py')
SwigSource('m5.internal', 'swig/core.i')
SwigSource('m5.internal', 'swig/debug.i')
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index d1aec44b3..41ed3df9e 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -32,7 +32,6 @@ import sys, types
import proxy
import m5
from util import *
-from multidict import multidict
# These utility functions have to come first because they're
# referenced in params.py... otherwise they won't be defined when we
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index cbdd65492..5c3324224 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -33,7 +33,7 @@ import os
import socket
import sys
-from attrdict import attrdict
+from util import attrdict
import defines
import traceflags
diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py
new file mode 100644
index 000000000..f82de696a
--- /dev/null
+++ b/src/python/m5/util/__init__.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2008 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+from attrdict import attrdict, optiondict
+from misc import *
+from multidict import multidict
+import jobfile
diff --git a/src/python/m5/attrdict.py b/src/python/m5/util/attrdict.py
index 4ee7f1b8c..44479c456 100644
--- a/src/python/m5/attrdict.py
+++ b/src/python/m5/util/attrdict.py
@@ -26,7 +26,7 @@
#
# Authors: Nathan Binkert
-__all__ = [ 'attrdict' ]
+__all__ = [ 'attrdict', 'optiondict' ]
class attrdict(dict):
def __getattr__(self, attr):
@@ -44,6 +44,15 @@ class attrdict(dict):
return self.__delitem__(attr)
return super(attrdict, self).__delattr__(attr, value)
+class optiondict(attrdict):
+ def __getattr__(self, attr):
+ try:
+ return super(optiondict, self).__getattr__(attr)
+ except AttributeError:
+ #d = optionsdict()
+ #setattr(self, attr, d)
+ return None
+
if __name__ == '__main__':
x = attrdict()
x.y = 1
diff --git a/src/python/m5/util/jobfile.py b/src/python/m5/util/jobfile.py
new file mode 100644
index 000000000..5e015c4ad
--- /dev/null
+++ b/src/python/m5/util/jobfile.py
@@ -0,0 +1,450 @@
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+import sys
+
+from attrdict import attrdict, optiondict
+from misc import crossproduct, flatten
+
+class Data(object):
+ def __init__(self, name, desc, **kwargs):
+ self.name = name
+ self.desc = desc
+ self.__dict__.update(kwargs)
+
+ def update(self, obj):
+ if not isinstance(obj, Data):
+ raise AttributeError, "can only update from Data object"
+
+ for k,v in obj.__dict__.iteritems():
+ if not k.startswith('_'):
+ self.__dict__[k] = v
+ if hasattr(self, 'system') and hasattr(obj, 'system'):
+ if self.system != obj.system:
+ raise AttributeError, \
+ "conflicting values for system: '%s'/'%s'" % \
+ (self.system, obj.system)
+
+ def printinfo(self):
+ if self.name:
+ print 'name: %s' % self.name
+ if self.desc:
+ print 'desc: %s' % self.desc
+ try:
+ if self.system:
+ print 'system: %s' % self.system
+ except AttributeError:
+ pass
+
+ def printverbose(self):
+ for key in self:
+ val = self[key]
+ if isinstance(val, dict):
+ import pprint
+ val = pprint.pformat(val)
+ print '%-20s = %s' % (key, val)
+ print
+
+ def __contains__(self, attr):
+ if attr.startswith('_'):
+ return False
+ return attr in self.__dict__
+
+ def __getitem__(self, key):
+ if key.startswith('_'):
+ raise KeyError, "Key '%s' not found" % attr
+ return self.__dict__[key]
+
+ def __iter__(self):
+ keys = self.__dict__.keys()
+ keys.sort()
+ for key in keys:
+ if not key.startswith('_'):
+ yield key
+
+ def optiondict(self):
+ result = optiondict()
+ for key in self:
+ result[key] = self[key]
+ return result
+
+ def __str__(self):
+ return self.name
+
+class Job(Data):
+ def __init__(self, options):
+ super(Job, self).__init__('', '')
+
+ config = options[0]._config
+ for opt in options:
+ if opt._config != config:
+ raise AttributeError, \
+ "All options are not from the same Configuration"
+
+ self._config = config
+ self._groups = [ opt._group for opt in options ]
+ self._options = options
+
+ self.update(self._config)
+ for group in self._groups:
+ self.update(group)
+
+ self._is_checkpoint = True
+
+ for option in self._options:
+ self.update(option)
+ if not option._group._checkpoint:
+ self._is_checkpoint = False
+
+ if option._suboption:
+ self.update(option._suboption)
+ self._is_checkpoint = False
+
+ names = [ ]
+ for opt in self._options:
+ if opt.name:
+ names.append(opt.name)
+ self.name = ':'.join(names)
+
+ descs = [ ]
+ for opt in self._options:
+ if opt.desc:
+ descs.append(opt.desc)
+ self.desc = ', '.join(descs)
+
+ self._checkpoint = None
+ if not self._is_checkpoint:
+ opts = []
+ for opt in options:
+ cpt = opt._group._checkpoint
+ if not cpt:
+ continue
+ if isinstance(cpt, Option):
+ opt = cpt.clone(suboptions=False)
+ else:
+ opt = opt.clone(suboptions=False)
+
+ opts.append(opt)
+
+ if opts:
+ self._checkpoint = Job(opts)
+
+ def clone(self):
+ return Job(self._options)
+
+ def printinfo(self):
+ super(Job, self).printinfo()
+ if self._checkpoint:
+ print 'checkpoint: %s' % self._checkpoint.name
+ print 'config: %s' % self._config.name
+ print 'groups: %s' % [ g.name for g in self._groups ]
+ print 'options: %s' % [ o.name for o in self._options ]
+ super(Job, self).printverbose()
+
+class SubOption(Data):
+ def __init__(self, name, desc, **kwargs):
+ super(SubOption, self).__init__(name, desc, **kwargs)
+ self._number = None
+
+class Option(Data):
+ def __init__(self, name, desc, **kwargs):
+ super(Option, self).__init__(name, desc, **kwargs)
+ self._suboptions = []
+ self._suboption = None
+ self._number = None
+
+ def __getattribute__(self, attr):
+ if attr == 'name':
+ name = self.__dict__[attr]
+ if self._suboption is not None:
+ name = '%s:%s' % (name, self._suboption.name)
+ return name
+
+ if attr == 'desc':
+ desc = [ self.__dict__[attr] ]
+ if self._suboption is not None and self._suboption.desc:
+ desc.append(self._suboption.desc)
+ return ', '.join(desc)
+
+ return super(Option, self).__getattribute__(attr)
+
+ def suboption(self, name, desc, **kwargs):
+ subo = SubOption(name, desc, **kwargs)
+ subo._config = self._config
+ subo._group = self._group
+ subo._option = self
+ subo._number = len(self._suboptions)
+ self._suboptions.append(subo)
+ return subo
+
+ def clone(self, suboptions=True):
+ option = Option(self.__dict__['name'], self.__dict__['desc'])
+ option.update(self)
+ option._group = self._group
+ option._config = self._config
+ option._number = self._number
+ if suboptions:
+ option._suboptions.extend(self._suboptions)
+ option._suboption = self._suboption
+ return option
+
+ def subopts(self):
+ if not self._suboptions:
+ return [ self ]
+
+ subopts = []
+ for subo in self._suboptions:
+ option = self.clone()
+ option._suboption = subo
+ subopts.append(option)
+
+ return subopts
+
+ def printinfo(self):
+ super(Option, self).printinfo()
+ print 'config: %s' % self._config.name
+ super(Option, self).printverbose()
+
+class Group(Data):
+ def __init__(self, name, desc, **kwargs):
+ super(Group, self).__init__(name, desc, **kwargs)
+ self._options = []
+ self._number = None
+ self._checkpoint = False
+
+ def option(self, name, desc, **kwargs):
+ opt = Option(name, desc, **kwargs)
+ opt._config = self._config
+ opt._group = self
+ opt._number = len(self._options)
+ self._options.append(opt)
+ return opt
+
+ def options(self):
+ return self._options
+
+ def subopts(self):
+ subopts = []
+ for opt in self._options:
+ for subo in opt.subopts():
+ subopts.append(subo)
+ return subopts
+
+ def printinfo(self):
+ super(Group, self).printinfo()
+ print 'config: %s' % self._config.name
+ print 'options: %s' % [ o.name for o in self._options ]
+ super(Group, self).printverbose()
+
+class Configuration(Data):
+ def __init__(self, name, desc, **kwargs):
+ super(Configuration, self).__init__(name, desc, **kwargs)
+ self._groups = []
+ self._posfilters = []
+ self._negfilters = []
+
+ def group(self, name, desc, **kwargs):
+ grp = Group(name, desc, **kwargs)
+ grp._config = self
+ grp._number = len(self._groups)
+ self._groups.append(grp)
+ return grp
+
+ def groups(self):
+ return self._groups
+
+ def checkchildren(self, kids):
+ for kid in kids:
+ if kid._config != self:
+ raise AttributeError, "child from the wrong configuration"
+
+ def sortgroups(self, groups):
+ groups = [ (grp._number, grp) for grp in groups ]
+ groups.sort()
+ return [ grp[1] for grp in groups ]
+
+ def options(self, groups=None, checkpoint=False):
+ if groups is None:
+ groups = self._groups
+ self.checkchildren(groups)
+ groups = self.sortgroups(groups)
+ if checkpoint:
+ groups = [ grp for grp in groups if grp._checkpoint ]
+ optgroups = [ g.options() for g in groups ]
+ else:
+ optgroups = [ g.subopts() for g in groups ]
+ if not optgroups:
+ return
+ for options in crossproduct(optgroups):
+ for opt in options:
+ cpt = opt._group._checkpoint
+ if not isinstance(cpt, bool) and cpt != opt:
+ if checkpoint:
+ break
+ else:
+ yield options
+ else:
+ if checkpoint:
+ yield options
+
+ def addfilter(self, filt, pos=True):
+ import re
+ filt = re.compile(filt)
+ if pos:
+ self._posfilters.append(filt)
+ else:
+ self._negfilters.append(filt)
+
+ def jobfilter(self, job):
+ for filt in self._negfilters:
+ if filt.match(job.name):
+ return False
+
+ if not self._posfilters:
+ return True
+
+ for filt in self._posfilters:
+ if filt.match(job.name):
+ return True
+
+ return False
+
+ def checkpoints(self, groups=None):
+ for options in self.options(groups, True):
+ job = Job(options)
+ if self.jobfilter(job):
+ yield job
+
+ def jobs(self, groups=None):
+ for options in self.options(groups, False):
+ job = Job(options)
+ if self.jobfilter(job):
+ yield job
+
+ def alljobs(self, groups=None):
+ for options in self.options(groups, True):
+ yield Job(options)
+ for options in self.options(groups, False):
+ yield Job(options)
+
+ def find(self, jobname):
+ for job in self.alljobs():
+ if job.name == jobname:
+ return job
+ else:
+ raise AttributeError, "job '%s' not found" % jobname
+
+ def job(self, options):
+ self.checkchildren(options)
+ options = [ (opt._group._number, opt) for opt in options ]
+ options.sort()
+ options = [ opt[1] for opt in options ]
+ job = Job(options)
+ return job
+
+ def printinfo(self):
+ super(Configuration, self).printinfo()
+ print 'groups: %s' % [ g.name for g in self._groups ]
+ super(Configuration, self).printverbose()
+
+def JobFile(jobfile):
+ from os.path import expanduser, isfile, join as joinpath
+ filename = expanduser(jobfile)
+
+ # Can't find filename in the current path, search sys.path
+ if not isfile(filename):
+ for path in sys.path:
+ testname = joinpath(path, filename)
+ if isfile(testname):
+ filename = testname
+ break
+ else:
+ raise AttributeError, \
+ "Could not find file '%s'" % jobfile
+
+ data = {}
+ execfile(filename, data)
+ if 'conf' not in data:
+ raise ImportError, 'cannot import name conf from %s' % jobfile
+ conf = data['conf']
+ import jobfile
+ if not isinstance(conf, Configuration):
+ raise AttributeError, \
+ 'conf in jobfile: %s (%s) is not type %s' % \
+ (jobfile, type(conf), Configuration)
+ return conf
+
+def main(conf=None):
+ import sys
+
+ usage = 'Usage: %s [-b] [-c] [-v] <jobfile>' % sys.argv[0]
+
+ try:
+ import getopt
+ opts, args = getopt.getopt(sys.argv[1:], '-bcv')
+ except getopt.GetoptError:
+ sys.exit(usage)
+
+ both = False
+ checkpoint = False
+ verbose = False
+ for opt,arg in opts:
+ if opt == '-b':
+ both = True
+ checkpoint = True
+ if opt == '-c':
+ checkpoint = True
+ if opt == '-v':
+ verbose = True
+
+ if conf is None:
+ if len(args) != 1:
+ raise AttributeError, usage
+ conf = JobFile(args[0])
+ else:
+ if len(args) != 0:
+ raise AttributeError, usage
+
+ if both:
+ jobs = conf.alljobs()
+ elif checkpoint:
+ jobs = conf.checkpoints()
+ else:
+ jobs = conf.jobs()
+
+ for job in jobs:
+ if verbose:
+ job.printinfo()
+ else:
+ cpt = ''
+ if job._checkpoint:
+ cpt = job._checkpoint.name
+ print job.name, cpt
+
+if __name__ == '__main__':
+ main()
diff --git a/src/python/m5/util.py b/src/python/m5/util/misc.py
index 28b8b1b94..094e3ed9a 100644
--- a/src/python/m5/util.py
+++ b/src/python/m5/util/misc.py
@@ -56,4 +56,32 @@ def applyOrMap(objOrSeq, meth, *args, **kwargs):
else:
return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq]
+def crossproduct(items):
+ if not isinstance(items, (list, tuple)):
+ raise AttributeError, 'crossproduct works only on sequences'
+ if not items:
+ yield None
+ return
+
+ current = items[0]
+ remainder = items[1:]
+
+ if not hasattr(current, '__iter__'):
+ current = [ current ]
+
+ for item in current:
+ for rem in crossproduct(remainder):
+ data = [ item ]
+ if rem:
+ data += rem
+ yield data
+
+def flatten(items):
+ if not isinstance(items, (list, tuple)):
+ yield items
+ return
+
+ for item in items:
+ for flat in flatten(item):
+ yield flat
diff --git a/src/python/m5/multidict.py b/src/python/m5/util/multidict.py
index b5cd700ef..b5cd700ef 100644
--- a/src/python/m5/multidict.py
+++ b/src/python/m5/util/multidict.py
diff --git a/src/python/m5/util/orderdict.py b/src/python/m5/util/orderdict.py
new file mode 100644
index 000000000..3f755d299
--- /dev/null
+++ b/src/python/m5/util/orderdict.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+__all__ = [ 'orderdict' ]
+
+class orderdict(dict):
+ def __init__(self, d = {}):
+ self._keys = d.keys()
+ super(orderdict, self).__init__(d)
+
+ def __setitem__(self, key, item):
+ super(orderdict, self).__setitem__(key, item)
+ if not hasattr(self, '_keys'):
+ self._keys = [key,]
+ if key not in self._keys:
+ self._keys.append(key)
+
+ def __delitem__(self, key):
+ super(orderdict, self).__delitem__(key)
+ self._keys.remove(key)
+
+ def clear(self):
+ super(orderdict, self).clear()
+ self._keys = []
+
+ def items(self):
+ for i in self._keys:
+ yield i, self[i]
+
+ def keys(self):
+ return self._keys
+
+ def popitem(self):
+ if len(self._keys) == 0:
+ raise KeyError('dictionary is empty')
+ else:
+ key = self._keys[-1]
+ val = self[key]
+ del self[key]
+ return key, val
+
+ def setdefault(self, key, failobj = None):
+ super(orderdict, self).setdefault(key, failobj)
+ if key not in self._keys:
+ self._keys.append(key)
+
+ def update(self, d):
+ for key in d.keys():
+ if not self.has_key(key):
+ self._keys.append(key)
+ super(orderdict, self).update(d)
+
+ def values(self):
+ for i in self._keys:
+ yield self[i]