ce2979cd218d617fa1626aacb20aa83815af77e4
[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 os
32 import socket
33 import sys
34
35 __all__ = [ 'options', 'arguments', 'main' ]
36
37 usage="%prog [gem5 options] script.py [script options]"
38 version="%prog 2.0"
39 brief_copyright=\
40 "gem5 is copyrighted software; use the --copyright option for details."
41
42 def parse_options():
43 import config
44 from options import OptionParser
45
46 options = OptionParser(usage=usage, version=version,
47 description=brief_copyright)
48 option = options.add_option
49 group = options.set_group
50
51 # Help options
52 option('-B', "--build-info", action="store_true", default=False,
53 help="Show build information")
54 option('-C', "--copyright", action="store_true", default=False,
55 help="Show full copyright information")
56 option('-R', "--readme", action="store_true", default=False,
57 help="Show the readme")
58
59 # Options for configuring the base simulator
60 option('-d', "--outdir", metavar="DIR", default="m5out",
61 help="Set the output directory to DIR [Default: %default]")
62 option('-r', "--redirect-stdout", action="store_true", default=False,
63 help="Redirect stdout (& stderr, without -e) to file")
64 option('-e', "--redirect-stderr", action="store_true", default=False,
65 help="Redirect stderr to file")
66 option("--stdout-file", metavar="FILE", default="simout",
67 help="Filename for -r redirection [Default: %default]")
68 option("--stderr-file", metavar="FILE", default="simerr",
69 help="Filename for -e redirection [Default: %default]")
70 option('-i', "--interactive", action="store_true", default=False,
71 help="Invoke the interactive interpreter after running the script")
72 option("--pdb", action="store_true", default=False,
73 help="Invoke the python debugger before running the script")
74 option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
75 help="Prepend PATH to the system path when invoking the script")
76 option('-q', "--quiet", action="count", default=0,
77 help="Reduce verbosity")
78 option('-v', "--verbose", action="count", default=0,
79 help="Increase verbosity")
80
81 # Statistics options
82 group("Statistics Options")
83 option("--stats-file", metavar="FILE", default="stats.txt",
84 help="Sets the output file for statistics [Default: %default]")
85
86 # Configuration Options
87 group("Configuration Options")
88 option("--dump-config", metavar="FILE", default="config.ini",
89 help="Dump configuration output file [Default: %default]")
90 option("--json-config", metavar="FILE", default="config.json",
91 help="Create JSON output of the configuration [Default: %default]")
92 option("--dot-config", metavar="FILE", default="config.dot",
93 help="Create DOT & pdf outputs of the configuration [Default: %default]")
94
95 # Debugging options
96 group("Debugging Options")
97 option("--debug-break", metavar="TIME[,TIME]", action='append', split=',',
98 help="Cycle to create a breakpoint")
99 option("--debug-help", action='store_true',
100 help="Print help on trace flags")
101 option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',',
102 help="Sets the flags for tracing (-FLAG disables a flag)")
103 option("--remote-gdb-port", type='int', default=7000,
104 help="Remote gdb base port (set to 0 to disable listening)")
105
106 # Tracing options
107 group("Trace Options")
108 option("--trace-start", metavar="TIME", type='int',
109 help="Start tracing at TIME (must be in ticks)")
110 option("--trace-file", metavar="FILE", default="cout",
111 help="Sets the output file for tracing [Default: %default]")
112 option("--trace-ignore", metavar="EXPR", action='append', split=':',
113 help="Ignore EXPR sim objects")
114
115 # Help options
116 group("Help Options")
117 option("--list-sim-objects", action='store_true', default=False,
118 help="List all built-in SimObjects, their params and default values")
119
120 # load the options.py config file to allow people to set their own
121 # default options
122 options_file = config.get('options.py')
123 if options_file:
124 scope = { 'options' : options }
125 execfile(options_file, scope)
126
127 arguments = options.parse_args()
128 return options,arguments
129
130 def interact(scope):
131 banner = "gem5 Interactive Console"
132 sys.argv = []
133 try:
134 from IPython.Shell import IPShellEmbed
135 ipshell = IPShellEmbed(banner=banner,user_ns=scope)
136 ipshell()
137 except ImportError:
138 code.InteractiveConsole(scope).interact(banner)
139
140 def main(*args):
141 import m5
142
143 import core
144 import debug
145 import defines
146 import event
147 import info
148 import stats
149 import trace
150
151 from util import fatal
152
153 if len(args) == 0:
154 options, arguments = parse_options()
155 elif len(args) == 2:
156 options, arguments = args
157 else:
158 raise TypeError, "main() takes 0 or 2 arguments (%d given)" % len(args)
159
160 m5.options = options
161
162 def check_tracing():
163 if defines.TRACING_ON:
164 return
165
166 fatal("Tracing is not enabled. Compile with TRACING_ON")
167
168 if not os.path.isdir(options.outdir):
169 os.makedirs(options.outdir)
170
171 # These filenames are used only if the redirect_std* options are set
172 stdout_file = os.path.join(options.outdir, options.stdout_file)
173 stderr_file = os.path.join(options.outdir, options.stderr_file)
174
175 # Print redirection notices here before doing any redirection
176 if options.redirect_stdout and not options.redirect_stderr:
177 print "Redirecting stdout and stderr to", stdout_file
178 else:
179 if options.redirect_stdout:
180 print "Redirecting stdout to", stdout_file
181 if options.redirect_stderr:
182 print "Redirecting stderr to", stderr_file
183
184 # Now redirect stdout/stderr as desired
185 if options.redirect_stdout:
186 redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
187 os.dup2(redir_fd, sys.stdout.fileno())
188 if not options.redirect_stderr:
189 os.dup2(redir_fd, sys.stderr.fileno())
190
191 if options.redirect_stderr:
192 redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
193 os.dup2(redir_fd, sys.stderr.fileno())
194
195 done = False
196
197 if options.build_info:
198 done = True
199 print 'Build information:'
200 print
201 print 'compiled %s' % defines.compileDate;
202 print 'build options:'
203 keys = defines.buildEnv.keys()
204 keys.sort()
205 for key in keys:
206 val = defines.buildEnv[key]
207 print ' %s = %s' % (key, val)
208 print
209
210 if options.copyright:
211 done = True
212 print info.COPYING
213 print
214
215 if options.readme:
216 done = True
217 print 'Readme:'
218 print
219 print info.README
220 print
221
222 if options.debug_help:
223 done = True
224 check_tracing()
225 debug.help()
226
227 if options.list_sim_objects:
228 import SimObject
229 done = True
230 print "SimObjects:"
231 objects = SimObject.allClasses.keys()
232 objects.sort()
233 for name in objects:
234 obj = SimObject.allClasses[name]
235 print " %s" % obj
236 params = obj._params.keys()
237 params.sort()
238 for pname in params:
239 param = obj._params[pname]
240 default = getattr(param, 'default', '')
241 print " %s" % pname
242 if default:
243 print " default: %s" % default
244 print " desc: %s" % param.desc
245 print
246 print
247
248 if done:
249 sys.exit(0)
250
251 # setting verbose and quiet at the same time doesn't make sense
252 if options.verbose > 0 and options.quiet > 0:
253 options.usage(2)
254
255 verbose = options.verbose - options.quiet
256 if options.verbose >= 0:
257 print "gem5 Simulator System. http://gem5.org"
258 print brief_copyright
259 print
260
261 print "gem5 compiled %s" % defines.compileDate;
262
263 print "gem5 started %s" % \
264 datetime.datetime.now().strftime("%b %e %Y %X")
265 print "gem5 executing on %s" % socket.gethostname()
266
267 print "command line:",
268 for argv in sys.argv:
269 print argv,
270 print
271
272 # check to make sure we can find the listed script
273 if not arguments or not os.path.isfile(arguments[0]):
274 if arguments and not os.path.isfile(arguments[0]):
275 print "Script %s not found" % arguments[0]
276
277 options.usage(2)
278
279 # tell C++ about output directory
280 core.setOutputDir(options.outdir)
281
282 # update the system path with elements from the -p option
283 sys.path[0:0] = options.path
284
285 # set stats options
286 stats.initText(options.stats_file)
287
288 # set debugging options
289 debug.setRemoteGDBPort(options.remote_gdb_port)
290 for when in options.debug_break:
291 debug.schedBreakCycle(int(when))
292
293 if options.debug_flags:
294 check_tracing()
295
296 on_flags = []
297 off_flags = []
298 for flag in options.debug_flags:
299 off = False
300 if flag.startswith('-'):
301 flag = flag[1:]
302 off = True
303
304 if flag not in debug.flags:
305 print >>sys.stderr, "invalid debug flag '%s'" % flag
306 sys.exit(1)
307
308 if off:
309 debug.flags[flag].disable()
310 else:
311 debug.flags[flag].enable()
312
313 if options.trace_start:
314 check_tracing()
315 e = event.create(trace.enable, event.Event.Trace_Enable_Pri)
316 event.mainq.schedule(e, options.trace_start)
317 else:
318 trace.enable()
319
320 trace.output(options.trace_file)
321
322 for ignore in options.trace_ignore:
323 check_tracing()
324 trace.ignore(ignore)
325
326 sys.argv = arguments
327 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
328
329 filename = sys.argv[0]
330 filedata = file(filename, 'r').read()
331 filecode = compile(filedata, filename, 'exec')
332 scope = { '__file__' : filename,
333 '__name__' : '__m5_main__' }
334
335 # we want readline if we're doing anything interactive
336 if options.interactive or options.pdb:
337 exec "import readline" in scope
338
339 # if pdb was requested, execfile the thing under pdb, otherwise,
340 # just do the execfile normally
341 if options.pdb:
342 import pdb
343 import traceback
344
345 pdb = pdb.Pdb()
346 try:
347 pdb.run(filecode, scope)
348 except SystemExit:
349 print "The program exited via sys.exit(). Exit status: ",
350 print sys.exc_info()[1]
351 except:
352 traceback.print_exc()
353 print "Uncaught exception. Entering post mortem debugging"
354 t = sys.exc_info()[2]
355 while t.tb_next is not None:
356 t = t.tb_next
357 pdb.interaction(t.tb_frame,t)
358 else:
359 exec filecode in scope
360
361 # once the script is done
362 if options.interactive:
363 interact(scope)
364
365 if __name__ == '__main__':
366 from pprint import pprint
367
368 options, arguments = parse_options()
369
370 print 'opts:'
371 pprint(options, indent=4)
372 print
373
374 print 'args:'
375 pprint(arguments, indent=4)