Automated merge with ssh://m5sim.org//repo/m5
[gem5.git] / src / python / m5 / main.py
1 # Copyright (c) 2005 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
29 import code
30 import datetime
31 import optparse
32 import os
33 import socket
34 import sys
35
36 from attrdict import attrdict
37 import defines
38 import traceflags
39
40 __all__ = [ 'options', 'arguments', 'main' ]
41
42 usage="%prog [m5 options] script.py [script options]"
43 version="%prog 2.0"
44 brief_copyright='''
45 Copyright (c) 2001-2008
46 The Regents of The University of Michigan
47 All Rights Reserved
48 '''
49
50 def print_list(items, indent=4):
51 line = ' ' * indent
52 for i,item in enumerate(items):
53 if len(line) + len(item) > 76:
54 print line
55 line = ' ' * indent
56
57 if i < len(items) - 1:
58 line += '%s, ' % item
59 else:
60 line += item
61 print line
62
63 # there's only one option parsing done, so make it global and add some
64 # helper functions to make it work well.
65 parser = optparse.OptionParser(usage=usage, version=version,
66 description=brief_copyright,
67 formatter=optparse.TitledHelpFormatter())
68 parser.disable_interspersed_args()
69
70 # current option group
71 group = None
72
73 def set_group(*args, **kwargs):
74 '''set the current option group'''
75 global group
76 if not args and not kwargs:
77 group = None
78 else:
79 group = parser.add_option_group(*args, **kwargs)
80
81 class splitter(object):
82 def __init__(self, split):
83 self.split = split
84 def __call__(self, option, opt_str, value, parser):
85 getattr(parser.values, option.dest).extend(value.split(self.split))
86
87 def add_option(*args, **kwargs):
88 '''add an option to the current option group, or global none set'''
89
90 # if action=split, but allows the option arguments
91 # themselves to be lists separated by the split variable'''
92
93 if kwargs.get('action', None) == 'append' and 'split' in kwargs:
94 split = kwargs.pop('split')
95 kwargs['default'] = []
96 kwargs['type'] = 'string'
97 kwargs['action'] = 'callback'
98 kwargs['callback'] = splitter(split)
99
100 if group:
101 return group.add_option(*args, **kwargs)
102
103 return parser.add_option(*args, **kwargs)
104
105 def bool_option(name, default, help):
106 '''add a boolean option called --name and --no-name.
107 Display help depending on which is the default'''
108
109 tname = '--%s' % name
110 fname = '--no-%s' % name
111 dest = name.replace('-', '_')
112 if default:
113 thelp = optparse.SUPPRESS_HELP
114 fhelp = help
115 else:
116 thelp = help
117 fhelp = optparse.SUPPRESS_HELP
118
119 add_option(tname, action="store_true", default=default, help=thelp)
120 add_option(fname, action="store_false", dest=dest, help=fhelp)
121
122 # Help options
123 add_option('-A', "--authors", action="store_true", default=False,
124 help="Show author information")
125 add_option('-B', "--build-info", action="store_true", default=False,
126 help="Show build information")
127 add_option('-C', "--copyright", action="store_true", default=False,
128 help="Show full copyright information")
129 add_option('-R', "--readme", action="store_true", default=False,
130 help="Show the readme")
131 add_option('-N', "--release-notes", action="store_true", default=False,
132 help="Show the release notes")
133
134 # Options for configuring the base simulator
135 add_option('-d', "--outdir", metavar="DIR", default=".",
136 help="Set the output directory to DIR [Default: %default]")
137 add_option('-i', "--interactive", action="store_true", default=False,
138 help="Invoke the interactive interpreter after running the script")
139 add_option("--pdb", action="store_true", default=False,
140 help="Invoke the python debugger before running the script")
141 add_option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
142 help="Prepend PATH to the system path when invoking the script")
143 add_option('-q', "--quiet", action="count", default=0,
144 help="Reduce verbosity")
145 add_option('-v', "--verbose", action="count", default=0,
146 help="Increase verbosity")
147
148 # Statistics options
149 set_group("Statistics Options")
150 add_option("--stats-file", metavar="FILE", default="m5stats.txt",
151 help="Sets the output file for statistics [Default: %default]")
152
153 # Debugging options
154 set_group("Debugging Options")
155 add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',',
156 help="Cycle to create a breakpoint")
157
158 # Tracing options
159 set_group("Trace Options")
160 add_option("--trace-help", action='store_true',
161 help="Print help on trace flags")
162 add_option("--trace-flags", metavar="FLAG[,FLAG]", action='append', split=',',
163 help="Sets the flags for tracing (-FLAG disables a flag)")
164 add_option("--trace-start", metavar="TIME", type='int',
165 help="Start tracing at TIME (must be in ticks)")
166 add_option("--trace-file", metavar="FILE", default="cout",
167 help="Sets the output file for tracing [Default: %default]")
168 add_option("--trace-ignore", metavar="EXPR", action='append', split=':',
169 help="Ignore EXPR sim objects")
170
171 options = attrdict()
172 arguments = []
173
174 def usage(exitcode=None):
175 parser.print_help()
176 if exitcode is not None:
177 sys.exit(exitcode)
178
179 def parse_args():
180 _opts,args = parser.parse_args()
181 opts = attrdict(_opts.__dict__)
182
183 # setting verbose and quiet at the same time doesn't make sense
184 if opts.verbose > 0 and opts.quiet > 0:
185 usage(2)
186
187 # store the verbosity in a single variable. 0 is default,
188 # negative numbers represent quiet and positive values indicate verbose
189 opts.verbose -= opts.quiet
190
191 del opts.quiet
192
193 options.update(opts)
194 arguments.extend(args)
195 return opts,args
196
197 def main():
198 import defines
199 import event
200 import info
201 import internal
202
203 parse_args()
204
205 done = False
206
207 if options.build_info:
208 done = True
209 print 'Build information:'
210 print
211 print 'compiled %s' % internal.core.cvar.compileDate;
212 print 'started %s' % datetime.datetime.now().ctime()
213 print 'executing on %s' % socket.gethostname()
214 print 'build options:'
215 keys = defines.m5_build_env.keys()
216 keys.sort()
217 for key in keys:
218 val = defines.m5_build_env[key]
219 print ' %s = %s' % (key, val)
220 print
221
222 if options.copyright:
223 done = True
224 print info.LICENSE
225 print
226
227 if options.authors:
228 done = True
229 print 'Author information:'
230 print
231 print info.AUTHORS
232 print
233
234 if options.readme:
235 done = True
236 print 'Readme:'
237 print
238 print info.README
239 print
240
241 if options.release_notes:
242 done = True
243 print 'Release Notes:'
244 print
245 print info.RELEASE_NOTES
246 print
247
248 if options.trace_help:
249 done = True
250 print "Base Flags:"
251 print_list(traceflags.baseFlags, indent=4)
252 print
253 print "Compound Flags:"
254 for flag in traceflags.compoundFlags:
255 if flag == 'All':
256 continue
257 print " %s:" % flag
258 print_list(traceflags.compoundFlagMap[flag], indent=8)
259 print
260
261 if done:
262 sys.exit(0)
263
264 if options.verbose >= 0:
265 print "M5 Simulator System"
266 print brief_copyright
267 print
268 print "M5 compiled %s" % internal.core.cvar.compileDate;
269 print "M5 started %s" % datetime.datetime.now().ctime()
270 print "M5 executing on %s" % socket.gethostname()
271
272 print "M5 revision %s" % internal.core.cvar.hgRev
273 print "M5 commit date %s" % internal.core.cvar.hgDate
274
275 print "command line:",
276 for argv in sys.argv:
277 print argv,
278 print
279
280 # check to make sure we can find the listed script
281 if not arguments or not os.path.isfile(arguments[0]):
282 if arguments and not os.path.isfile(arguments[0]):
283 print "Script %s not found" % arguments[0]
284
285 usage(2)
286
287 # tell C++ about output directory
288 internal.core.setOutputDir(options.outdir)
289
290 # update the system path with elements from the -p option
291 sys.path[0:0] = options.path
292
293 import objects
294
295 # set stats options
296 internal.stats.initText(options.stats_file)
297
298 # set debugging options
299 for when in options.debug_break:
300 internal.debug.schedBreakCycle(int(when))
301
302 on_flags = []
303 off_flags = []
304 for flag in options.trace_flags:
305 off = False
306 if flag.startswith('-'):
307 flag = flag[1:]
308 off = True
309 if flag not in traceflags.allFlags:
310 print >>sys.stderr, "invalid trace flag '%s'" % flag
311 sys.exit(1)
312
313 if off:
314 off_flags.append(flag)
315 else:
316 on_flags.append(flag)
317
318 for flag in on_flags:
319 internal.trace.set(flag)
320
321 for flag in off_flags:
322 internal.trace.clear(flag)
323
324 if options.trace_start:
325 def enable_trace():
326 internal.trace.cvar.enabled = True
327 event.create(enable_trace, int(options.trace_start))
328 else:
329 internal.trace.cvar.enabled = True
330
331 internal.trace.output(options.trace_file)
332
333 for ignore in options.trace_ignore:
334 internal.trace.ignore(ignore)
335
336 sys.argv = arguments
337 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
338
339 scope = { '__file__' : sys.argv[0],
340 '__name__' : '__m5_main__' }
341
342 # we want readline if we're doing anything interactive
343 if options.interactive or options.pdb:
344 exec "import readline" in scope
345
346 # if pdb was requested, execfile the thing under pdb, otherwise,
347 # just do the execfile normally
348 if options.pdb:
349 from pdb import Pdb
350 debugger = Pdb()
351 debugger.run('execfile("%s")' % sys.argv[0], scope)
352 else:
353 execfile(sys.argv[0], scope)
354
355 # once the script is done
356 if options.interactive:
357 interact = code.InteractiveConsole(scope)
358 interact.interact("M5 Interactive Console")
359
360 if __name__ == '__main__':
361 from pprint import pprint
362
363 parse_args()
364
365 print 'opts:'
366 pprint(options, indent=4)
367 print
368
369 print 'args:'
370 pprint(arguments, indent=4)