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 2912563Sgabeblack@google.comfrom __future__ import print_function 3013714Sandreas.sandberg@arm.comfrom __future__ import absolute_import 3112563Sgabeblack@google.com 321428SN/Aimport sys 331428SN/A 341881SN/Aclass Data(object): 351881SN/A def __init__(self, name, desc, **kwargs): 361881SN/A self.name = name 371881SN/A self.desc = desc 385467Snate@binkert.org self.__dict__.update(kwargs) 391881SN/A 401881SN/A def update(self, obj): 411881SN/A if not isinstance(obj, Data): 4213663Sandreas.sandberg@arm.com raise AttributeError("can only update from Data object") 431881SN/A 4413709Sandreas.sandberg@arm.com for key,val in obj.__dict__.items(): 455618Snate@binkert.org if key.startswith('_') or key in ('name', 'desc'): 465618Snate@binkert.org continue 475618Snate@binkert.org 485618Snate@binkert.org if key not in self.__dict__: 495618Snate@binkert.org self.__dict__[key] = val 505618Snate@binkert.org continue 515618Snate@binkert.org 525618Snate@binkert.org if not isinstance(val, dict): 535618Snate@binkert.org if self.__dict__[key] == val: 545618Snate@binkert.org continue 555618Snate@binkert.org 5613663Sandreas.sandberg@arm.com raise AttributeError( 5713663Sandreas.sandberg@arm.com "%s specified more than once old: %s new: %s" % \ 5813663Sandreas.sandberg@arm.com (key, self.__dict__[key], val)) 595618Snate@binkert.org 605618Snate@binkert.org d = self.__dict__[key] 6113709Sandreas.sandberg@arm.com for k,v in val.items(): 625618Snate@binkert.org if k in d: 6313663Sandreas.sandberg@arm.com raise AttributeError( 6413663Sandreas.sandberg@arm.com "%s specified more than once in %s" % (k, key)) 655618Snate@binkert.org d[k] = v 665618Snate@binkert.org 675467Snate@binkert.org if hasattr(self, 'system') and hasattr(obj, 'system'): 685467Snate@binkert.org if self.system != obj.system: 6913663Sandreas.sandberg@arm.com raise AttributeError( 7013663Sandreas.sandberg@arm.com "conflicting values for system: '%s'/'%s'" % \ 7113663Sandreas.sandberg@arm.com (self.system, obj.system)) 721881SN/A 731881SN/A def printinfo(self): 741881SN/A if self.name: 7512563Sgabeblack@google.com print('name: %s' % self.name) 761881SN/A if self.desc: 7712563Sgabeblack@google.com print('desc: %s' % self.desc) 785467Snate@binkert.org try: 795467Snate@binkert.org if self.system: 8012563Sgabeblack@google.com print('system: %s' % self.system) 815467Snate@binkert.org except AttributeError: 825467Snate@binkert.org pass 831881SN/A 841881SN/A def printverbose(self): 855467Snate@binkert.org for key in self: 865467Snate@binkert.org val = self[key] 875467Snate@binkert.org if isinstance(val, dict): 885467Snate@binkert.org import pprint 895467Snate@binkert.org val = pprint.pformat(val) 9012563Sgabeblack@google.com print('%-20s = %s' % (key, val)) 9112563Sgabeblack@google.com print() 925467Snate@binkert.org 935467Snate@binkert.org def __contains__(self, attr): 945467Snate@binkert.org if attr.startswith('_'): 955467Snate@binkert.org return False 965467Snate@binkert.org return attr in self.__dict__ 975467Snate@binkert.org 985467Snate@binkert.org def __getitem__(self, key): 995467Snate@binkert.org if key.startswith('_'): 10013663Sandreas.sandberg@arm.com raise KeyError("Key '%s' not found" % attr) 1015467Snate@binkert.org return self.__dict__[key] 1025467Snate@binkert.org 1035467Snate@binkert.org def __iter__(self): 10413709Sandreas.sandberg@arm.com keys = list(self.__dict__.keys()) 1051881SN/A keys.sort() 1061881SN/A for key in keys: 1075467Snate@binkert.org if not key.startswith('_'): 1085467Snate@binkert.org yield key 1095467Snate@binkert.org 1105467Snate@binkert.org def optiondict(self): 1116654Snate@binkert.org import m5.util 1126654Snate@binkert.org result = m5.util.optiondict() 1135467Snate@binkert.org for key in self: 1145467Snate@binkert.org result[key] = self[key] 1155467Snate@binkert.org return result 1161881SN/A 1175618Snate@binkert.org def __repr__(self): 1185618Snate@binkert.org d = {} 11913709Sandreas.sandberg@arm.com for key,value in self.__dict__.items(): 1205618Snate@binkert.org if not key.startswith('_'): 1215618Snate@binkert.org d[key] = value 1225618Snate@binkert.org 1235618Snate@binkert.org return "<%s: %s>" % (type(self).__name__, d) 1245618Snate@binkert.org 1251881SN/A def __str__(self): 1261881SN/A return self.name 1271881SN/A 1281881SN/Aclass Job(Data): 1291881SN/A def __init__(self, options): 1301881SN/A super(Job, self).__init__('', '') 1311881SN/A 1325467Snate@binkert.org config = options[0]._config 1331881SN/A for opt in options: 1345467Snate@binkert.org if opt._config != config: 13513663Sandreas.sandberg@arm.com raise AttributeError( 13613663Sandreas.sandberg@arm.com "All options are not from the same Configuration") 1371881SN/A 1385467Snate@binkert.org self._config = config 1395467Snate@binkert.org self._groups = [ opt._group for opt in options ] 1405467Snate@binkert.org self._options = options 1411881SN/A 1425467Snate@binkert.org self.update(self._config) 1435467Snate@binkert.org for group in self._groups: 1441881SN/A self.update(group) 1451881SN/A 1465467Snate@binkert.org self._is_checkpoint = True 1475467Snate@binkert.org 1485467Snate@binkert.org for option in self._options: 1491881SN/A self.update(option) 1505467Snate@binkert.org if not option._group._checkpoint: 1515467Snate@binkert.org self._is_checkpoint = False 1525467Snate@binkert.org 1531881SN/A if option._suboption: 1541881SN/A self.update(option._suboption) 1555467Snate@binkert.org self._is_checkpoint = False 1565467Snate@binkert.org 1575467Snate@binkert.org names = [ ] 1585467Snate@binkert.org for opt in self._options: 1595467Snate@binkert.org if opt.name: 1605467Snate@binkert.org names.append(opt.name) 1615467Snate@binkert.org self.name = ':'.join(names) 1625467Snate@binkert.org 1635467Snate@binkert.org descs = [ ] 1645467Snate@binkert.org for opt in self._options: 1655467Snate@binkert.org if opt.desc: 1665467Snate@binkert.org descs.append(opt.desc) 1675467Snate@binkert.org self.desc = ', '.join(descs) 1685467Snate@binkert.org 1695467Snate@binkert.org self._checkpoint = None 1705467Snate@binkert.org if not self._is_checkpoint: 1715467Snate@binkert.org opts = [] 1725467Snate@binkert.org for opt in options: 1735467Snate@binkert.org cpt = opt._group._checkpoint 1745467Snate@binkert.org if not cpt: 1755467Snate@binkert.org continue 1765467Snate@binkert.org if isinstance(cpt, Option): 1775467Snate@binkert.org opt = cpt.clone(suboptions=False) 1785467Snate@binkert.org else: 1795467Snate@binkert.org opt = opt.clone(suboptions=False) 1805467Snate@binkert.org 1815467Snate@binkert.org opts.append(opt) 1825467Snate@binkert.org 1835467Snate@binkert.org if opts: 1845467Snate@binkert.org self._checkpoint = Job(opts) 1855467Snate@binkert.org 1865467Snate@binkert.org def clone(self): 1875467Snate@binkert.org return Job(self._options) 1881881SN/A 1891881SN/A def printinfo(self): 1901881SN/A super(Job, self).printinfo() 1915467Snate@binkert.org if self._checkpoint: 19212563Sgabeblack@google.com print('checkpoint: %s' % self._checkpoint.name) 19312563Sgabeblack@google.com print('config: %s' % self._config.name) 19412563Sgabeblack@google.com print('groups: %s' % [ g.name for g in self._groups ]) 19512563Sgabeblack@google.com print('options: %s' % [ o.name for o in self._options ]) 1961881SN/A super(Job, self).printverbose() 1971881SN/A 1981881SN/Aclass SubOption(Data): 1991881SN/A def __init__(self, name, desc, **kwargs): 2001881SN/A super(SubOption, self).__init__(name, desc, **kwargs) 2015467Snate@binkert.org self._number = None 2021881SN/A 2031881SN/Aclass Option(Data): 2041881SN/A def __init__(self, name, desc, **kwargs): 2051881SN/A super(Option, self).__init__(name, desc, **kwargs) 2061881SN/A self._suboptions = [] 2071881SN/A self._suboption = None 2085467Snate@binkert.org self._number = None 2091881SN/A 2101881SN/A def __getattribute__(self, attr): 2111881SN/A if attr == 'name': 2121881SN/A name = self.__dict__[attr] 2131881SN/A if self._suboption is not None: 2141881SN/A name = '%s:%s' % (name, self._suboption.name) 2151881SN/A return name 2161881SN/A 2171881SN/A if attr == 'desc': 2182142SN/A desc = [ self.__dict__[attr] ] 2192142SN/A if self._suboption is not None and self._suboption.desc: 2202142SN/A desc.append(self._suboption.desc) 2212142SN/A return ', '.join(desc) 2222142SN/A 2231881SN/A return super(Option, self).__getattribute__(attr) 2241881SN/A 2251881SN/A def suboption(self, name, desc, **kwargs): 2261881SN/A subo = SubOption(name, desc, **kwargs) 2275467Snate@binkert.org subo._config = self._config 2285467Snate@binkert.org subo._group = self._group 2295467Snate@binkert.org subo._option = self 2305467Snate@binkert.org subo._number = len(self._suboptions) 2311881SN/A self._suboptions.append(subo) 2321881SN/A return subo 2331881SN/A 2341881SN/A def clone(self, suboptions=True): 2351881SN/A option = Option(self.__dict__['name'], self.__dict__['desc']) 2361881SN/A option.update(self) 2375467Snate@binkert.org option._group = self._group 2385467Snate@binkert.org option._config = self._config 2395467Snate@binkert.org option._number = self._number 2401881SN/A if suboptions: 2411881SN/A option._suboptions.extend(self._suboptions) 2421881SN/A option._suboption = self._suboption 2431881SN/A return option 2441881SN/A 2451881SN/A def subopts(self): 2461881SN/A if not self._suboptions: 2471881SN/A return [ self ] 2481881SN/A 2491881SN/A subopts = [] 2501881SN/A for subo in self._suboptions: 2511881SN/A option = self.clone() 2521881SN/A option._suboption = subo 2531881SN/A subopts.append(option) 2541881SN/A 2551881SN/A return subopts 2561881SN/A 2571881SN/A def printinfo(self): 2581881SN/A super(Option, self).printinfo() 25912563Sgabeblack@google.com print('config: %s' % self._config.name) 2601881SN/A super(Option, self).printverbose() 2611881SN/A 2621881SN/Aclass Group(Data): 2631881SN/A def __init__(self, name, desc, **kwargs): 2641881SN/A super(Group, self).__init__(name, desc, **kwargs) 2651881SN/A self._options = [] 2665467Snate@binkert.org self._number = None 2675467Snate@binkert.org self._checkpoint = False 2681881SN/A 2691881SN/A def option(self, name, desc, **kwargs): 2701881SN/A opt = Option(name, desc, **kwargs) 2715467Snate@binkert.org opt._config = self._config 2725467Snate@binkert.org opt._group = self 2735467Snate@binkert.org opt._number = len(self._options) 2741881SN/A self._options.append(opt) 2751881SN/A return opt 2761881SN/A 2771881SN/A def options(self): 2781881SN/A return self._options 2791881SN/A 2801881SN/A def subopts(self): 2811881SN/A subopts = [] 2821881SN/A for opt in self._options: 2831881SN/A for subo in opt.subopts(): 2841881SN/A subopts.append(subo) 2851881SN/A return subopts 2861881SN/A 2871881SN/A def printinfo(self): 2881881SN/A super(Group, self).printinfo() 28912563Sgabeblack@google.com print('config: %s' % self._config.name) 29012563Sgabeblack@google.com print('options: %s' % [ o.name for o in self._options ]) 2911881SN/A super(Group, self).printverbose() 2921881SN/A 2931881SN/Aclass Configuration(Data): 2941881SN/A def __init__(self, name, desc, **kwargs): 2951881SN/A super(Configuration, self).__init__(name, desc, **kwargs) 2961881SN/A self._groups = [] 2972141SN/A self._posfilters = [] 2982141SN/A self._negfilters = [] 2991881SN/A 3001881SN/A def group(self, name, desc, **kwargs): 3011881SN/A grp = Group(name, desc, **kwargs) 3025467Snate@binkert.org grp._config = self 3035467Snate@binkert.org grp._number = len(self._groups) 3041881SN/A self._groups.append(grp) 3051881SN/A return grp 3061881SN/A 3075467Snate@binkert.org def groups(self): 3085467Snate@binkert.org return self._groups 3091881SN/A 3101881SN/A def checkchildren(self, kids): 3111881SN/A for kid in kids: 3125467Snate@binkert.org if kid._config != self: 31313663Sandreas.sandberg@arm.com raise AttributeError("child from the wrong configuration") 3141881SN/A 3151881SN/A def sortgroups(self, groups): 3165467Snate@binkert.org groups = [ (grp._number, grp) for grp in groups ] 3171881SN/A groups.sort() 3181881SN/A return [ grp[1] for grp in groups ] 3191881SN/A 3205467Snate@binkert.org def options(self, groups=None, checkpoint=False): 3211881SN/A if groups is None: 3221881SN/A groups = self._groups 3231881SN/A self.checkchildren(groups) 3241881SN/A groups = self.sortgroups(groups) 3251881SN/A if checkpoint: 3265467Snate@binkert.org groups = [ grp for grp in groups if grp._checkpoint ] 3271881SN/A optgroups = [ g.options() for g in groups ] 3281881SN/A else: 3291881SN/A optgroups = [ g.subopts() for g in groups ] 3305467Snate@binkert.org if not optgroups: 3315467Snate@binkert.org return 3326654Snate@binkert.org 3336654Snate@binkert.org import m5.util 3346654Snate@binkert.org for options in m5.util.crossproduct(optgroups): 3351881SN/A for opt in options: 3365467Snate@binkert.org cpt = opt._group._checkpoint 3371881SN/A if not isinstance(cpt, bool) and cpt != opt: 3381881SN/A if checkpoint: 3391881SN/A break 3401881SN/A else: 3411881SN/A yield options 3421881SN/A else: 3431881SN/A if checkpoint: 3441881SN/A yield options 3451881SN/A 3462141SN/A def addfilter(self, filt, pos=True): 3472141SN/A import re 3482141SN/A filt = re.compile(filt) 3492141SN/A if pos: 3502141SN/A self._posfilters.append(filt) 3512141SN/A else: 3522141SN/A self._negfilters.append(filt) 3532141SN/A 3542141SN/A def jobfilter(self, job): 3552141SN/A for filt in self._negfilters: 3562141SN/A if filt.match(job.name): 3572141SN/A return False 3582141SN/A 3592141SN/A if not self._posfilters: 3602141SN/A return True 3612141SN/A 3622141SN/A for filt in self._posfilters: 3632141SN/A if filt.match(job.name): 3642141SN/A return True 3652141SN/A 3662141SN/A return False 3672141SN/A 3685467Snate@binkert.org def checkpoints(self, groups=None): 3691881SN/A for options in self.options(groups, True): 3702141SN/A job = Job(options) 3712141SN/A if self.jobfilter(job): 3722141SN/A yield job 3731881SN/A 3745467Snate@binkert.org def jobs(self, groups=None): 3751881SN/A for options in self.options(groups, False): 3762141SN/A job = Job(options) 3772141SN/A if self.jobfilter(job): 3782141SN/A yield job 3791881SN/A 3805467Snate@binkert.org def alljobs(self, groups=None): 3811881SN/A for options in self.options(groups, True): 3821881SN/A yield Job(options) 3831881SN/A for options in self.options(groups, False): 3841881SN/A yield Job(options) 3851881SN/A 3861881SN/A def find(self, jobname): 3871881SN/A for job in self.alljobs(): 3881881SN/A if job.name == jobname: 3891881SN/A return job 3901881SN/A else: 39113663Sandreas.sandberg@arm.com raise AttributeError("job '%s' not found" % jobname) 3921881SN/A 3931881SN/A def job(self, options): 3941881SN/A self.checkchildren(options) 3955467Snate@binkert.org options = [ (opt._group._number, opt) for opt in options ] 3961881SN/A options.sort() 3971881SN/A options = [ opt[1] for opt in options ] 3981881SN/A job = Job(options) 3991881SN/A return job 4001881SN/A 4011881SN/A def printinfo(self): 4021881SN/A super(Configuration, self).printinfo() 40312563Sgabeblack@google.com print('groups: %s' % [ g.name for g in self._groups ]) 4041881SN/A super(Configuration, self).printverbose() 4051881SN/A 4061881SN/Adef JobFile(jobfile): 4071881SN/A from os.path import expanduser, isfile, join as joinpath 4081881SN/A filename = expanduser(jobfile) 4091881SN/A 4101881SN/A # Can't find filename in the current path, search sys.path 4111881SN/A if not isfile(filename): 4121881SN/A for path in sys.path: 4131881SN/A testname = joinpath(path, filename) 4141881SN/A if isfile(testname): 4151881SN/A filename = testname 4161881SN/A break 4171881SN/A else: 41813663Sandreas.sandberg@arm.com raise AttributeError("Could not find file '%s'" % jobfile) 4191881SN/A 4201881SN/A data = {} 42113671Sandreas.sandberg@arm.com exec(compile(open(filename).read(), filename, 'exec'), data) 4221881SN/A if 'conf' not in data: 42313663Sandreas.sandberg@arm.com raise ImportError('cannot import name conf from %s' % jobfile) 4245618Snate@binkert.org return data['conf'] 4251881SN/A 4265467Snate@binkert.orgdef main(conf=None): 4275618Snate@binkert.org usage = 'Usage: %s [-b] [-c] [-v]' % sys.argv[0] 4285618Snate@binkert.org if conf is None: 4295618Snate@binkert.org usage += ' <jobfile>' 4301881SN/A 4311881SN/A try: 4321881SN/A import getopt 4331881SN/A opts, args = getopt.getopt(sys.argv[1:], '-bcv') 4341881SN/A except getopt.GetoptError: 4351881SN/A sys.exit(usage) 4361881SN/A 4371881SN/A both = False 4381881SN/A checkpoint = False 4391881SN/A verbose = False 4401881SN/A for opt,arg in opts: 4411881SN/A if opt == '-b': 4421881SN/A both = True 4431881SN/A checkpoint = True 4441881SN/A if opt == '-c': 4451881SN/A checkpoint = True 4461881SN/A if opt == '-v': 4471881SN/A verbose = True 4481881SN/A 4495467Snate@binkert.org if conf is None: 4505467Snate@binkert.org if len(args) != 1: 45113663Sandreas.sandberg@arm.com raise AttributeError(usage) 4525467Snate@binkert.org conf = JobFile(args[0]) 4535467Snate@binkert.org else: 4545467Snate@binkert.org if len(args) != 0: 45513663Sandreas.sandberg@arm.com raise AttributeError(usage) 4561881SN/A 4571881SN/A if both: 4585467Snate@binkert.org jobs = conf.alljobs() 4591881SN/A elif checkpoint: 4605467Snate@binkert.org jobs = conf.checkpoints() 4611881SN/A else: 4625467Snate@binkert.org jobs = conf.jobs() 4631881SN/A 4645467Snate@binkert.org for job in jobs: 4655467Snate@binkert.org if verbose: 4665467Snate@binkert.org job.printinfo() 4675467Snate@binkert.org else: 4681881SN/A cpt = '' 4695467Snate@binkert.org if job._checkpoint: 4705467Snate@binkert.org cpt = job._checkpoint.name 47112563Sgabeblack@google.com print(job.name, cpt) 4725467Snate@binkert.org 4735467Snate@binkert.orgif __name__ == '__main__': 4745467Snate@binkert.org main() 475