jobfile.py revision 6654
12141SN/A# Copyright (c) 2005-2006 The Regents of The University of Michigan 21376SN/A# All rights reserved. 31376SN/A# 41376SN/A# Redistribution and use in source and binary forms, with or without 51376SN/A# modification, are permitted provided that the following conditions are 61376SN/A# met: redistributions of source code must retain the above copyright 71376SN/A# notice, this list of conditions and the following disclaimer; 81376SN/A# redistributions in binary form must reproduce the above copyright 91376SN/A# notice, this list of conditions and the following disclaimer in the 101376SN/A# documentation and/or other materials provided with the distribution; 111376SN/A# neither the name of the copyright holders nor the names of its 121376SN/A# contributors may be used to endorse or promote products derived from 131376SN/A# this software without specific prior written permission. 141376SN/A# 151376SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161376SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171376SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 181376SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 191376SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 201376SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 211376SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 221376SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 231376SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 241376SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 251376SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 261376SN/A# 271376SN/A# Authors: Nathan Binkert 281376SN/A 291428SN/Aimport sys 301428SN/A 311881SN/Aclass Data(object): 321881SN/A def __init__(self, name, desc, **kwargs): 331881SN/A self.name = name 341881SN/A self.desc = desc 355467Snate@binkert.org self.__dict__.update(kwargs) 361881SN/A 371881SN/A def update(self, obj): 381881SN/A if not isinstance(obj, Data): 391881SN/A raise AttributeError, "can only update from Data object" 401881SN/A 415618Snate@binkert.org for key,val in obj.__dict__.iteritems(): 425618Snate@binkert.org if key.startswith('_') or key in ('name', 'desc'): 435618Snate@binkert.org continue 445618Snate@binkert.org 455618Snate@binkert.org if key not in self.__dict__: 465618Snate@binkert.org self.__dict__[key] = val 475618Snate@binkert.org continue 485618Snate@binkert.org 495618Snate@binkert.org if not isinstance(val, dict): 505618Snate@binkert.org if self.__dict__[key] == val: 515618Snate@binkert.org continue 525618Snate@binkert.org 535618Snate@binkert.org raise AttributeError, \ 545618Snate@binkert.org "%s specified more than once old: %s new: %s" % \ 555618Snate@binkert.org (key, self.__dict__[key], val) 565618Snate@binkert.org 575618Snate@binkert.org d = self.__dict__[key] 585618Snate@binkert.org for k,v in val.iteritems(): 595618Snate@binkert.org if k in d: 605618Snate@binkert.org raise AttributeError, \ 615618Snate@binkert.org "%s specified more than once in %s" % (k, key) 625618Snate@binkert.org d[k] = v 635618Snate@binkert.org 645467Snate@binkert.org if hasattr(self, 'system') and hasattr(obj, 'system'): 655467Snate@binkert.org if self.system != obj.system: 661881SN/A raise AttributeError, \ 671881SN/A "conflicting values for system: '%s'/'%s'" % \ 681881SN/A (self.system, obj.system) 691881SN/A 701881SN/A def printinfo(self): 711881SN/A if self.name: 721881SN/A print 'name: %s' % self.name 731881SN/A if self.desc: 741881SN/A print 'desc: %s' % self.desc 755467Snate@binkert.org try: 765467Snate@binkert.org if self.system: 775467Snate@binkert.org print 'system: %s' % self.system 785467Snate@binkert.org except AttributeError: 795467Snate@binkert.org pass 801881SN/A 811881SN/A def printverbose(self): 825467Snate@binkert.org for key in self: 835467Snate@binkert.org val = self[key] 845467Snate@binkert.org if isinstance(val, dict): 855467Snate@binkert.org import pprint 865467Snate@binkert.org val = pprint.pformat(val) 875467Snate@binkert.org print '%-20s = %s' % (key, val) 885467Snate@binkert.org print 895467Snate@binkert.org 905467Snate@binkert.org def __contains__(self, attr): 915467Snate@binkert.org if attr.startswith('_'): 925467Snate@binkert.org return False 935467Snate@binkert.org return attr in self.__dict__ 945467Snate@binkert.org 955467Snate@binkert.org def __getitem__(self, key): 965467Snate@binkert.org if key.startswith('_'): 975467Snate@binkert.org raise KeyError, "Key '%s' not found" % attr 985467Snate@binkert.org return self.__dict__[key] 995467Snate@binkert.org 1005467Snate@binkert.org def __iter__(self): 1015467Snate@binkert.org keys = self.__dict__.keys() 1021881SN/A keys.sort() 1031881SN/A for key in keys: 1045467Snate@binkert.org if not key.startswith('_'): 1055467Snate@binkert.org yield key 1065467Snate@binkert.org 1075467Snate@binkert.org def optiondict(self): 1086654Snate@binkert.org import m5.util 1096654Snate@binkert.org result = m5.util.optiondict() 1105467Snate@binkert.org for key in self: 1115467Snate@binkert.org result[key] = self[key] 1125467Snate@binkert.org return result 1131881SN/A 1145618Snate@binkert.org def __repr__(self): 1155618Snate@binkert.org d = {} 1165618Snate@binkert.org for key,value in self.__dict__.iteritems(): 1175618Snate@binkert.org if not key.startswith('_'): 1185618Snate@binkert.org d[key] = value 1195618Snate@binkert.org 1205618Snate@binkert.org return "<%s: %s>" % (type(self).__name__, d) 1215618Snate@binkert.org 1221881SN/A def __str__(self): 1231881SN/A return self.name 1241881SN/A 1251881SN/Aclass Job(Data): 1261881SN/A def __init__(self, options): 1271881SN/A super(Job, self).__init__('', '') 1281881SN/A 1295467Snate@binkert.org config = options[0]._config 1301881SN/A for opt in options: 1315467Snate@binkert.org if opt._config != config: 1321881SN/A raise AttributeError, \ 1331881SN/A "All options are not from the same Configuration" 1341881SN/A 1355467Snate@binkert.org self._config = config 1365467Snate@binkert.org self._groups = [ opt._group for opt in options ] 1375467Snate@binkert.org self._options = options 1381881SN/A 1395467Snate@binkert.org self.update(self._config) 1405467Snate@binkert.org for group in self._groups: 1411881SN/A self.update(group) 1421881SN/A 1435467Snate@binkert.org self._is_checkpoint = True 1445467Snate@binkert.org 1455467Snate@binkert.org for option in self._options: 1461881SN/A self.update(option) 1475467Snate@binkert.org if not option._group._checkpoint: 1485467Snate@binkert.org self._is_checkpoint = False 1495467Snate@binkert.org 1501881SN/A if option._suboption: 1511881SN/A self.update(option._suboption) 1525467Snate@binkert.org self._is_checkpoint = False 1535467Snate@binkert.org 1545467Snate@binkert.org names = [ ] 1555467Snate@binkert.org for opt in self._options: 1565467Snate@binkert.org if opt.name: 1575467Snate@binkert.org names.append(opt.name) 1585467Snate@binkert.org self.name = ':'.join(names) 1595467Snate@binkert.org 1605467Snate@binkert.org descs = [ ] 1615467Snate@binkert.org for opt in self._options: 1625467Snate@binkert.org if opt.desc: 1635467Snate@binkert.org descs.append(opt.desc) 1645467Snate@binkert.org self.desc = ', '.join(descs) 1655467Snate@binkert.org 1665467Snate@binkert.org self._checkpoint = None 1675467Snate@binkert.org if not self._is_checkpoint: 1685467Snate@binkert.org opts = [] 1695467Snate@binkert.org for opt in options: 1705467Snate@binkert.org cpt = opt._group._checkpoint 1715467Snate@binkert.org if not cpt: 1725467Snate@binkert.org continue 1735467Snate@binkert.org if isinstance(cpt, Option): 1745467Snate@binkert.org opt = cpt.clone(suboptions=False) 1755467Snate@binkert.org else: 1765467Snate@binkert.org opt = opt.clone(suboptions=False) 1775467Snate@binkert.org 1785467Snate@binkert.org opts.append(opt) 1795467Snate@binkert.org 1805467Snate@binkert.org if opts: 1815467Snate@binkert.org self._checkpoint = Job(opts) 1825467Snate@binkert.org 1835467Snate@binkert.org def clone(self): 1845467Snate@binkert.org return Job(self._options) 1851881SN/A 1861881SN/A def printinfo(self): 1871881SN/A super(Job, self).printinfo() 1885467Snate@binkert.org if self._checkpoint: 1895467Snate@binkert.org print 'checkpoint: %s' % self._checkpoint.name 1905467Snate@binkert.org print 'config: %s' % self._config.name 1915467Snate@binkert.org print 'groups: %s' % [ g.name for g in self._groups ] 1925467Snate@binkert.org print 'options: %s' % [ o.name for o in self._options ] 1931881SN/A super(Job, self).printverbose() 1941881SN/A 1951881SN/Aclass SubOption(Data): 1961881SN/A def __init__(self, name, desc, **kwargs): 1971881SN/A super(SubOption, self).__init__(name, desc, **kwargs) 1985467Snate@binkert.org self._number = None 1991881SN/A 2001881SN/Aclass Option(Data): 2011881SN/A def __init__(self, name, desc, **kwargs): 2021881SN/A super(Option, self).__init__(name, desc, **kwargs) 2031881SN/A self._suboptions = [] 2041881SN/A self._suboption = None 2055467Snate@binkert.org self._number = None 2061881SN/A 2071881SN/A def __getattribute__(self, attr): 2081881SN/A if attr == 'name': 2091881SN/A name = self.__dict__[attr] 2101881SN/A if self._suboption is not None: 2111881SN/A name = '%s:%s' % (name, self._suboption.name) 2121881SN/A return name 2131881SN/A 2141881SN/A if attr == 'desc': 2152142SN/A desc = [ self.__dict__[attr] ] 2162142SN/A if self._suboption is not None and self._suboption.desc: 2172142SN/A desc.append(self._suboption.desc) 2182142SN/A return ', '.join(desc) 2192142SN/A 2201881SN/A return super(Option, self).__getattribute__(attr) 2211881SN/A 2221881SN/A def suboption(self, name, desc, **kwargs): 2231881SN/A subo = SubOption(name, desc, **kwargs) 2245467Snate@binkert.org subo._config = self._config 2255467Snate@binkert.org subo._group = self._group 2265467Snate@binkert.org subo._option = self 2275467Snate@binkert.org subo._number = len(self._suboptions) 2281881SN/A self._suboptions.append(subo) 2291881SN/A return subo 2301881SN/A 2311881SN/A def clone(self, suboptions=True): 2321881SN/A option = Option(self.__dict__['name'], self.__dict__['desc']) 2331881SN/A option.update(self) 2345467Snate@binkert.org option._group = self._group 2355467Snate@binkert.org option._config = self._config 2365467Snate@binkert.org option._number = self._number 2371881SN/A if suboptions: 2381881SN/A option._suboptions.extend(self._suboptions) 2391881SN/A option._suboption = self._suboption 2401881SN/A return option 2411881SN/A 2421881SN/A def subopts(self): 2431881SN/A if not self._suboptions: 2441881SN/A return [ self ] 2451881SN/A 2461881SN/A subopts = [] 2471881SN/A for subo in self._suboptions: 2481881SN/A option = self.clone() 2491881SN/A option._suboption = subo 2501881SN/A subopts.append(option) 2511881SN/A 2521881SN/A return subopts 2531881SN/A 2541881SN/A def printinfo(self): 2551881SN/A super(Option, self).printinfo() 2565467Snate@binkert.org print 'config: %s' % self._config.name 2571881SN/A super(Option, self).printverbose() 2581881SN/A 2591881SN/Aclass Group(Data): 2601881SN/A def __init__(self, name, desc, **kwargs): 2611881SN/A super(Group, self).__init__(name, desc, **kwargs) 2621881SN/A self._options = [] 2635467Snate@binkert.org self._number = None 2645467Snate@binkert.org self._checkpoint = False 2651881SN/A 2661881SN/A def option(self, name, desc, **kwargs): 2671881SN/A opt = Option(name, desc, **kwargs) 2685467Snate@binkert.org opt._config = self._config 2695467Snate@binkert.org opt._group = self 2705467Snate@binkert.org opt._number = len(self._options) 2711881SN/A self._options.append(opt) 2721881SN/A return opt 2731881SN/A 2741881SN/A def options(self): 2751881SN/A return self._options 2761881SN/A 2771881SN/A def subopts(self): 2781881SN/A subopts = [] 2791881SN/A for opt in self._options: 2801881SN/A for subo in opt.subopts(): 2811881SN/A subopts.append(subo) 2821881SN/A return subopts 2831881SN/A 2841881SN/A def printinfo(self): 2851881SN/A super(Group, self).printinfo() 2865467Snate@binkert.org print 'config: %s' % self._config.name 2871881SN/A print 'options: %s' % [ o.name for o in self._options ] 2881881SN/A super(Group, self).printverbose() 2891881SN/A 2901881SN/Aclass Configuration(Data): 2911881SN/A def __init__(self, name, desc, **kwargs): 2921881SN/A super(Configuration, self).__init__(name, desc, **kwargs) 2931881SN/A self._groups = [] 2942141SN/A self._posfilters = [] 2952141SN/A self._negfilters = [] 2961881SN/A 2971881SN/A def group(self, name, desc, **kwargs): 2981881SN/A grp = Group(name, desc, **kwargs) 2995467Snate@binkert.org grp._config = self 3005467Snate@binkert.org grp._number = len(self._groups) 3011881SN/A self._groups.append(grp) 3021881SN/A return grp 3031881SN/A 3045467Snate@binkert.org def groups(self): 3055467Snate@binkert.org return self._groups 3061881SN/A 3071881SN/A def checkchildren(self, kids): 3081881SN/A for kid in kids: 3095467Snate@binkert.org if kid._config != self: 3101881SN/A raise AttributeError, "child from the wrong configuration" 3111881SN/A 3121881SN/A def sortgroups(self, groups): 3135467Snate@binkert.org groups = [ (grp._number, grp) for grp in groups ] 3141881SN/A groups.sort() 3151881SN/A return [ grp[1] for grp in groups ] 3161881SN/A 3175467Snate@binkert.org def options(self, groups=None, checkpoint=False): 3181881SN/A if groups is None: 3191881SN/A groups = self._groups 3201881SN/A self.checkchildren(groups) 3211881SN/A groups = self.sortgroups(groups) 3221881SN/A if checkpoint: 3235467Snate@binkert.org groups = [ grp for grp in groups if grp._checkpoint ] 3241881SN/A optgroups = [ g.options() for g in groups ] 3251881SN/A else: 3261881SN/A optgroups = [ g.subopts() for g in groups ] 3275467Snate@binkert.org if not optgroups: 3285467Snate@binkert.org return 3296654Snate@binkert.org 3306654Snate@binkert.org import m5.util 3316654Snate@binkert.org for options in m5.util.crossproduct(optgroups): 3321881SN/A for opt in options: 3335467Snate@binkert.org cpt = opt._group._checkpoint 3341881SN/A if not isinstance(cpt, bool) and cpt != opt: 3351881SN/A if checkpoint: 3361881SN/A break 3371881SN/A else: 3381881SN/A yield options 3391881SN/A else: 3401881SN/A if checkpoint: 3411881SN/A yield options 3421881SN/A 3432141SN/A def addfilter(self, filt, pos=True): 3442141SN/A import re 3452141SN/A filt = re.compile(filt) 3462141SN/A if pos: 3472141SN/A self._posfilters.append(filt) 3482141SN/A else: 3492141SN/A self._negfilters.append(filt) 3502141SN/A 3512141SN/A def jobfilter(self, job): 3522141SN/A for filt in self._negfilters: 3532141SN/A if filt.match(job.name): 3542141SN/A return False 3552141SN/A 3562141SN/A if not self._posfilters: 3572141SN/A return True 3582141SN/A 3592141SN/A for filt in self._posfilters: 3602141SN/A if filt.match(job.name): 3612141SN/A return True 3622141SN/A 3632141SN/A return False 3642141SN/A 3655467Snate@binkert.org def checkpoints(self, groups=None): 3661881SN/A for options in self.options(groups, True): 3672141SN/A job = Job(options) 3682141SN/A if self.jobfilter(job): 3692141SN/A yield job 3701881SN/A 3715467Snate@binkert.org def jobs(self, groups=None): 3721881SN/A for options in self.options(groups, False): 3732141SN/A job = Job(options) 3742141SN/A if self.jobfilter(job): 3752141SN/A yield job 3761881SN/A 3775467Snate@binkert.org def alljobs(self, groups=None): 3781881SN/A for options in self.options(groups, True): 3791881SN/A yield Job(options) 3801881SN/A for options in self.options(groups, False): 3811881SN/A yield Job(options) 3821881SN/A 3831881SN/A def find(self, jobname): 3841881SN/A for job in self.alljobs(): 3851881SN/A if job.name == jobname: 3861881SN/A return job 3871881SN/A else: 3881881SN/A raise AttributeError, "job '%s' not found" % jobname 3891881SN/A 3901881SN/A def job(self, options): 3911881SN/A self.checkchildren(options) 3925467Snate@binkert.org options = [ (opt._group._number, opt) for opt in options ] 3931881SN/A options.sort() 3941881SN/A options = [ opt[1] for opt in options ] 3951881SN/A job = Job(options) 3961881SN/A return job 3971881SN/A 3981881SN/A def printinfo(self): 3991881SN/A super(Configuration, self).printinfo() 4005467Snate@binkert.org print 'groups: %s' % [ g.name for g in self._groups ] 4011881SN/A super(Configuration, self).printverbose() 4021881SN/A 4031881SN/Adef JobFile(jobfile): 4041881SN/A from os.path import expanduser, isfile, join as joinpath 4051881SN/A filename = expanduser(jobfile) 4061881SN/A 4071881SN/A # Can't find filename in the current path, search sys.path 4081881SN/A if not isfile(filename): 4091881SN/A for path in sys.path: 4101881SN/A testname = joinpath(path, filename) 4111881SN/A if isfile(testname): 4121881SN/A filename = testname 4131881SN/A break 4141881SN/A else: 4151881SN/A raise AttributeError, \ 4161881SN/A "Could not find file '%s'" % jobfile 4171881SN/A 4181881SN/A data = {} 4191881SN/A execfile(filename, data) 4201881SN/A if 'conf' not in data: 4211881SN/A raise ImportError, 'cannot import name conf from %s' % jobfile 4225618Snate@binkert.org return data['conf'] 4231881SN/A 4245467Snate@binkert.orgdef main(conf=None): 4255618Snate@binkert.org usage = 'Usage: %s [-b] [-c] [-v]' % sys.argv[0] 4265618Snate@binkert.org if conf is None: 4275618Snate@binkert.org usage += ' <jobfile>' 4281881SN/A 4291881SN/A try: 4301881SN/A import getopt 4311881SN/A opts, args = getopt.getopt(sys.argv[1:], '-bcv') 4321881SN/A except getopt.GetoptError: 4331881SN/A sys.exit(usage) 4341881SN/A 4351881SN/A both = False 4361881SN/A checkpoint = False 4371881SN/A verbose = False 4381881SN/A for opt,arg in opts: 4391881SN/A if opt == '-b': 4401881SN/A both = True 4411881SN/A checkpoint = True 4421881SN/A if opt == '-c': 4431881SN/A checkpoint = True 4441881SN/A if opt == '-v': 4451881SN/A verbose = True 4461881SN/A 4475467Snate@binkert.org if conf is None: 4485467Snate@binkert.org if len(args) != 1: 4495467Snate@binkert.org raise AttributeError, usage 4505467Snate@binkert.org conf = JobFile(args[0]) 4515467Snate@binkert.org else: 4525467Snate@binkert.org if len(args) != 0: 4535467Snate@binkert.org raise AttributeError, usage 4541881SN/A 4551881SN/A if both: 4565467Snate@binkert.org jobs = conf.alljobs() 4571881SN/A elif checkpoint: 4585467Snate@binkert.org jobs = conf.checkpoints() 4591881SN/A else: 4605467Snate@binkert.org jobs = conf.jobs() 4611881SN/A 4625467Snate@binkert.org for job in jobs: 4635467Snate@binkert.org if verbose: 4645467Snate@binkert.org job.printinfo() 4655467Snate@binkert.org else: 4661881SN/A cpt = '' 4675467Snate@binkert.org if job._checkpoint: 4685467Snate@binkert.org cpt = job._checkpoint.name 4691881SN/A print job.name, cpt 4705467Snate@binkert.org 4715467Snate@binkert.orgif __name__ == '__main__': 4725467Snate@binkert.org main() 473