Deleted Added
sdiff udiff text old ( 13709:dd6b7ac5801f ) new ( 13714:35636064b7a1 )
full compact
1# Copyright (c) 2005-2006 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution;
11# neither the name of the copyright holders nor the names of its
12# contributors may be used to endorse or promote products derived from
13# this software without specific prior written permission.
14#
15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27# Authors: Nathan Binkert
28
29from __future__ import print_function
30from __future__ import absolute_import
31
32import sys
33
34class Data(object):
35 def __init__(self, name, desc, **kwargs):
36 self.name = name
37 self.desc = desc
38 self.__dict__.update(kwargs)
39
40 def update(self, obj):
41 if not isinstance(obj, Data):
42 raise AttributeError("can only update from Data object")
43
44 for key,val in obj.__dict__.items():
45 if key.startswith('_') or key in ('name', 'desc'):
46 continue
47
48 if key not in self.__dict__:
49 self.__dict__[key] = val
50 continue
51
52 if not isinstance(val, dict):
53 if self.__dict__[key] == val:
54 continue
55
56 raise AttributeError(
57 "%s specified more than once old: %s new: %s" % \
58 (key, self.__dict__[key], val))
59
60 d = self.__dict__[key]
61 for k,v in val.items():
62 if k in d:
63 raise AttributeError(
64 "%s specified more than once in %s" % (k, key))
65 d[k] = v
66
67 if hasattr(self, 'system') and hasattr(obj, 'system'):
68 if self.system != obj.system:
69 raise AttributeError(
70 "conflicting values for system: '%s'/'%s'" % \
71 (self.system, obj.system))
72
73 def printinfo(self):
74 if self.name:
75 print('name: %s' % self.name)
76 if self.desc:
77 print('desc: %s' % self.desc)
78 try:
79 if self.system:
80 print('system: %s' % self.system)
81 except AttributeError:
82 pass
83
84 def printverbose(self):
85 for key in self:
86 val = self[key]
87 if isinstance(val, dict):
88 import pprint
89 val = pprint.pformat(val)
90 print('%-20s = %s' % (key, val))
91 print()
92
93 def __contains__(self, attr):
94 if attr.startswith('_'):
95 return False
96 return attr in self.__dict__
97
98 def __getitem__(self, key):
99 if key.startswith('_'):
100 raise KeyError("Key '%s' not found" % attr)
101 return self.__dict__[key]
102
103 def __iter__(self):
104 keys = list(self.__dict__.keys())
105 keys.sort()
106 for key in keys:
107 if not key.startswith('_'):
108 yield key
109
110 def optiondict(self):
111 import m5.util
112 result = m5.util.optiondict()
113 for key in self:
114 result[key] = self[key]
115 return result
116
117 def __repr__(self):
118 d = {}
119 for key,value in self.__dict__.items():
120 if not key.startswith('_'):
121 d[key] = value
122
123 return "<%s: %s>" % (type(self).__name__, d)
124
125 def __str__(self):
126 return self.name
127
128class Job(Data):
129 def __init__(self, options):
130 super(Job, self).__init__('', '')
131
132 config = options[0]._config
133 for opt in options:
134 if opt._config != config:
135 raise AttributeError(
136 "All options are not from the same Configuration")
137
138 self._config = config
139 self._groups = [ opt._group for opt in options ]
140 self._options = options
141
142 self.update(self._config)
143 for group in self._groups:
144 self.update(group)
145
146 self._is_checkpoint = True
147
148 for option in self._options:
149 self.update(option)
150 if not option._group._checkpoint:
151 self._is_checkpoint = False
152
153 if option._suboption:
154 self.update(option._suboption)
155 self._is_checkpoint = False
156
157 names = [ ]
158 for opt in self._options:
159 if opt.name:
160 names.append(opt.name)
161 self.name = ':'.join(names)
162
163 descs = [ ]
164 for opt in self._options:
165 if opt.desc:
166 descs.append(opt.desc)
167 self.desc = ', '.join(descs)
168
169 self._checkpoint = None
170 if not self._is_checkpoint:
171 opts = []
172 for opt in options:
173 cpt = opt._group._checkpoint
174 if not cpt:
175 continue
176 if isinstance(cpt, Option):
177 opt = cpt.clone(suboptions=False)
178 else:
179 opt = opt.clone(suboptions=False)
180
181 opts.append(opt)
182
183 if opts:
184 self._checkpoint = Job(opts)
185
186 def clone(self):
187 return Job(self._options)
188
189 def printinfo(self):
190 super(Job, self).printinfo()
191 if self._checkpoint:
192 print('checkpoint: %s' % self._checkpoint.name)
193 print('config: %s' % self._config.name)
194 print('groups: %s' % [ g.name for g in self._groups ])
195 print('options: %s' % [ o.name for o in self._options ])
196 super(Job, self).printverbose()
197
198class SubOption(Data):
199 def __init__(self, name, desc, **kwargs):
200 super(SubOption, self).__init__(name, desc, **kwargs)
201 self._number = None
202
203class Option(Data):
204 def __init__(self, name, desc, **kwargs):
205 super(Option, self).__init__(name, desc, **kwargs)
206 self._suboptions = []
207 self._suboption = None
208 self._number = None
209
210 def __getattribute__(self, attr):
211 if attr == 'name':
212 name = self.__dict__[attr]
213 if self._suboption is not None:
214 name = '%s:%s' % (name, self._suboption.name)
215 return name
216
217 if attr == 'desc':
218 desc = [ self.__dict__[attr] ]
219 if self._suboption is not None and self._suboption.desc:
220 desc.append(self._suboption.desc)
221 return ', '.join(desc)
222
223 return super(Option, self).__getattribute__(attr)
224
225 def suboption(self, name, desc, **kwargs):
226 subo = SubOption(name, desc, **kwargs)
227 subo._config = self._config
228 subo._group = self._group
229 subo._option = self
230 subo._number = len(self._suboptions)
231 self._suboptions.append(subo)
232 return subo
233
234 def clone(self, suboptions=True):
235 option = Option(self.__dict__['name'], self.__dict__['desc'])
236 option.update(self)
237 option._group = self._group
238 option._config = self._config
239 option._number = self._number
240 if suboptions:
241 option._suboptions.extend(self._suboptions)
242 option._suboption = self._suboption
243 return option
244
245 def subopts(self):
246 if not self._suboptions:
247 return [ self ]
248
249 subopts = []
250 for subo in self._suboptions:
251 option = self.clone()
252 option._suboption = subo
253 subopts.append(option)
254
255 return subopts
256
257 def printinfo(self):
258 super(Option, self).printinfo()
259 print('config: %s' % self._config.name)
260 super(Option, self).printverbose()
261
262class Group(Data):
263 def __init__(self, name, desc, **kwargs):
264 super(Group, self).__init__(name, desc, **kwargs)
265 self._options = []
266 self._number = None
267 self._checkpoint = False
268
269 def option(self, name, desc, **kwargs):
270 opt = Option(name, desc, **kwargs)
271 opt._config = self._config
272 opt._group = self
273 opt._number = len(self._options)
274 self._options.append(opt)
275 return opt
276
277 def options(self):
278 return self._options
279
280 def subopts(self):
281 subopts = []
282 for opt in self._options:
283 for subo in opt.subopts():
284 subopts.append(subo)
285 return subopts
286
287 def printinfo(self):
288 super(Group, self).printinfo()
289 print('config: %s' % self._config.name)
290 print('options: %s' % [ o.name for o in self._options ])
291 super(Group, self).printverbose()
292
293class Configuration(Data):
294 def __init__(self, name, desc, **kwargs):
295 super(Configuration, self).__init__(name, desc, **kwargs)
296 self._groups = []
297 self._posfilters = []
298 self._negfilters = []
299
300 def group(self, name, desc, **kwargs):
301 grp = Group(name, desc, **kwargs)
302 grp._config = self
303 grp._number = len(self._groups)
304 self._groups.append(grp)
305 return grp
306
307 def groups(self):
308 return self._groups
309
310 def checkchildren(self, kids):
311 for kid in kids:
312 if kid._config != self:
313 raise AttributeError("child from the wrong configuration")
314
315 def sortgroups(self, groups):
316 groups = [ (grp._number, grp) for grp in groups ]
317 groups.sort()
318 return [ grp[1] for grp in groups ]
319
320 def options(self, groups=None, checkpoint=False):
321 if groups is None:
322 groups = self._groups
323 self.checkchildren(groups)
324 groups = self.sortgroups(groups)
325 if checkpoint:
326 groups = [ grp for grp in groups if grp._checkpoint ]
327 optgroups = [ g.options() for g in groups ]
328 else:
329 optgroups = [ g.subopts() for g in groups ]
330 if not optgroups:
331 return
332
333 import m5.util
334 for options in m5.util.crossproduct(optgroups):
335 for opt in options:
336 cpt = opt._group._checkpoint
337 if not isinstance(cpt, bool) and cpt != opt:
338 if checkpoint:
339 break
340 else:
341 yield options
342 else:
343 if checkpoint:
344 yield options
345
346 def addfilter(self, filt, pos=True):
347 import re
348 filt = re.compile(filt)
349 if pos:
350 self._posfilters.append(filt)
351 else:
352 self._negfilters.append(filt)
353
354 def jobfilter(self, job):
355 for filt in self._negfilters:
356 if filt.match(job.name):
357 return False
358
359 if not self._posfilters:
360 return True
361
362 for filt in self._posfilters:
363 if filt.match(job.name):
364 return True
365
366 return False
367
368 def checkpoints(self, groups=None):
369 for options in self.options(groups, True):
370 job = Job(options)
371 if self.jobfilter(job):
372 yield job
373
374 def jobs(self, groups=None):
375 for options in self.options(groups, False):
376 job = Job(options)
377 if self.jobfilter(job):
378 yield job
379
380 def alljobs(self, groups=None):
381 for options in self.options(groups, True):
382 yield Job(options)
383 for options in self.options(groups, False):
384 yield Job(options)
385
386 def find(self, jobname):
387 for job in self.alljobs():
388 if job.name == jobname:
389 return job
390 else:
391 raise AttributeError("job '%s' not found" % jobname)
392
393 def job(self, options):
394 self.checkchildren(options)
395 options = [ (opt._group._number, opt) for opt in options ]
396 options.sort()
397 options = [ opt[1] for opt in options ]
398 job = Job(options)
399 return job
400
401 def printinfo(self):
402 super(Configuration, self).printinfo()
403 print('groups: %s' % [ g.name for g in self._groups ])
404 super(Configuration, self).printverbose()
405
406def JobFile(jobfile):
407 from os.path import expanduser, isfile, join as joinpath
408 filename = expanduser(jobfile)
409
410 # Can't find filename in the current path, search sys.path
411 if not isfile(filename):
412 for path in sys.path:
413 testname = joinpath(path, filename)
414 if isfile(testname):
415 filename = testname
416 break
417 else:
418 raise AttributeError("Could not find file '%s'" % jobfile)
419
420 data = {}
421 exec(compile(open(filename).read(), filename, 'exec'), data)
422 if 'conf' not in data:
423 raise ImportError('cannot import name conf from %s' % jobfile)
424 return data['conf']
425
426def main(conf=None):
427 usage = 'Usage: %s [-b] [-c] [-v]' % sys.argv[0]
428 if conf is None:
429 usage += ' <jobfile>'
430
431 try:
432 import getopt
433 opts, args = getopt.getopt(sys.argv[1:], '-bcv')
434 except getopt.GetoptError:
435 sys.exit(usage)
436
437 both = False
438 checkpoint = False
439 verbose = False
440 for opt,arg in opts:
441 if opt == '-b':
442 both = True
443 checkpoint = True
444 if opt == '-c':
445 checkpoint = True
446 if opt == '-v':
447 verbose = True
448
449 if conf is None:
450 if len(args) != 1:
451 raise AttributeError(usage)
452 conf = JobFile(args[0])
453 else:
454 if len(args) != 0:
455 raise AttributeError(usage)
456
457 if both:
458 jobs = conf.alljobs()
459 elif checkpoint:
460 jobs = conf.checkpoints()
461 else:
462 jobs = conf.jobs()
463
464 for job in jobs:
465 if verbose:
466 job.printinfo()
467 else:
468 cpt = ''
469 if job._checkpoint:
470 cpt = job._checkpoint.name
471 print(job.name, cpt)
472
473if __name__ == '__main__':
474 main()