sparc,sim: Remove special handling of SPARC in the clone system call.
[gem5.git] / src / python / m5 / main.py
1 # Copyright (c) 2016, 2019 Arm Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Copyright (c) 2005 The Regents of The University of Michigan
14 # All rights reserved.
15 #
16 # Redistribution and use in source and binary forms, with or without
17 # modification, are permitted provided that the following conditions are
18 # met: redistributions of source code must retain the above copyright
19 # notice, this list of conditions and the following disclaimer;
20 # redistributions in binary form must reproduce the above copyright
21 # notice, this list of conditions and the following disclaimer in the
22 # documentation and/or other materials provided with the distribution;
23 # neither the name of the copyright holders nor the names of its
24 # contributors may be used to endorse or promote products derived from
25 # this software without specific prior written permission.
26 #
27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39 from __future__ import print_function
40
41 import code
42 import datetime
43 import os
44 import socket
45 import sys
46
47 __all__ = [ 'options', 'arguments', 'main' ]
48
49 usage="%prog [gem5 options] script.py [script options]"
50 version="%prog 2.0"
51 brief_copyright=\
52 "gem5 is copyrighted software; use the --copyright option for details."
53
54 def _stats_help(option, opt, value, parser):
55 import m5
56 print("A stat file can either be specified as a URI or a plain")
57 print("path. When specified as a path, gem5 uses the default text ")
58 print("format.")
59 print()
60 print("The following stat formats are supported:")
61 print()
62 m5.stats.printStatVisitorTypes()
63 sys.exit(0)
64
65
66 def parse_options():
67 from . import config
68 from .options import OptionParser
69
70 options = OptionParser(usage=usage, version=version,
71 description=brief_copyright)
72 option = options.add_option
73 group = options.set_group
74
75 listener_modes = ( "on", "off", "auto" )
76
77 # Help options
78 option('-B', "--build-info", action="store_true", default=False,
79 help="Show build information")
80 option('-C', "--copyright", action="store_true", default=False,
81 help="Show full copyright information")
82 option('-R', "--readme", action="store_true", default=False,
83 help="Show the readme")
84
85 # Options for configuring the base simulator
86 option('-d', "--outdir", metavar="DIR", default="m5out",
87 help="Set the output directory to DIR [Default: %default]")
88 option('-r', "--redirect-stdout", action="store_true", default=False,
89 help="Redirect stdout (& stderr, without -e) to file")
90 option('-e', "--redirect-stderr", action="store_true", default=False,
91 help="Redirect stderr to file")
92 option("--stdout-file", metavar="FILE", default="simout",
93 help="Filename for -r redirection [Default: %default]")
94 option("--stderr-file", metavar="FILE", default="simerr",
95 help="Filename for -e redirection [Default: %default]")
96 option("--listener-mode", metavar="{on,off,auto}",
97 choices=listener_modes, default="auto",
98 help="Port (e.g., gdb) listener mode (auto: Enable if running " \
99 "interactively) [Default: %default]")
100 option("--listener-loopback-only", action="store_true", default=False,
101 help="Port listeners will only accept connections over the " \
102 "loopback device")
103 option('-i', "--interactive", action="store_true", default=False,
104 help="Invoke the interactive interpreter after running the script")
105 option("--pdb", action="store_true", default=False,
106 help="Invoke the python debugger before running the script")
107 option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
108 help="Prepend PATH to the system path when invoking the script")
109 option('-q', "--quiet", action="count", default=0,
110 help="Reduce verbosity")
111 option('-v', "--verbose", action="count", default=0,
112 help="Increase verbosity")
113
114 # Statistics options
115 group("Statistics Options")
116 option("--stats-file", metavar="FILE", default="stats.txt",
117 help="Sets the output file for statistics [Default: %default]")
118 option("--stats-help",
119 action="callback", callback=_stats_help,
120 help="Display documentation for available stat visitors")
121
122 # Configuration Options
123 group("Configuration Options")
124 option("--dump-config", metavar="FILE", default="config.ini",
125 help="Dump configuration output file [Default: %default]")
126 option("--json-config", metavar="FILE", default="config.json",
127 help="Create JSON output of the configuration [Default: %default]")
128 option("--dot-config", metavar="FILE", default="config.dot",
129 help="Create DOT & pdf outputs of the configuration [Default: %default]")
130 option("--dot-dvfs-config", metavar="FILE", default=None,
131 help="Create DOT & pdf outputs of the DVFS configuration" + \
132 " [Default: %default]")
133
134 # Debugging options
135 group("Debugging Options")
136 option("--debug-break", metavar="TICK[,TICK]", action='append', split=',',
137 help="Create breakpoint(s) at TICK(s) " \
138 "(kills process if no debugger attached)")
139 option("--debug-help", action='store_true',
140 help="Print help on debug flags")
141 option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',',
142 help="Sets the flags for debug output (-FLAG disables a flag)")
143 option("--debug-start", metavar="TICK", type='int',
144 help="Start debug output at TICK")
145 option("--debug-end", metavar="TICK", type='int',
146 help="End debug output at TICK")
147 option("--debug-file", metavar="FILE", default="cout",
148 help="Sets the output file for debug [Default: %default]")
149 option("--debug-ignore", metavar="EXPR", action='append', split=':',
150 help="Ignore EXPR sim objects")
151 option("--remote-gdb-port", type='int', default=7000,
152 help="Remote gdb base port (set to 0 to disable listening)")
153
154 # Help options
155 group("Help Options")
156 option("--list-sim-objects", action='store_true', default=False,
157 help="List all built-in SimObjects, their params and default values")
158
159 # load the options.py config file to allow people to set their own
160 # default options
161 options_file = config.get('options.py')
162 if options_file:
163 scope = { 'options' : options }
164 exec(compile(open(options_file).read(), options_file, 'exec'), scope)
165
166 arguments = options.parse_args()
167 return options,arguments
168
169 def interact(scope):
170 banner = "gem5 Interactive Console"
171
172 ipshell = None
173 prompt_in1 = "gem5 \\#> "
174 prompt_out = "gem5 \\#: "
175
176 # Is IPython version 0.10 or earlier available?
177 try:
178 from IPython.Shell import IPShellEmbed
179 ipshell = IPShellEmbed(argv=["-prompt_in1", prompt_in1,
180 "-prompt_out", prompt_out],
181 banner=banner, user_ns=scope)
182 except ImportError:
183 pass
184
185 # Is IPython version 0.11 or later available?
186 if not ipshell:
187 try:
188 import IPython
189 from IPython.config.loader import Config
190 from IPython.terminal.embed import InteractiveShellEmbed
191
192 cfg = Config()
193 cfg.PromptManager.in_template = prompt_in1
194 cfg.PromptManager.out_template = prompt_out
195 ipshell = InteractiveShellEmbed(config=cfg, user_ns=scope,
196 banner1=banner)
197 except ImportError:
198 pass
199
200 if ipshell:
201 ipshell()
202 else:
203 # Use the Python shell in the standard library if IPython
204 # isn't available.
205 code.InteractiveConsole(scope).interact(banner)
206
207
208 def _check_tracing():
209 from . import defines
210
211 if defines.TRACING_ON:
212 return
213
214 fatal("Tracing is not enabled. Compile with TRACING_ON")
215
216 def main(*args):
217 import m5
218
219 from . import core
220 from . import debug
221 from . import defines
222 from . import event
223 from . import info
224 from . import stats
225 from . import trace
226
227 from .util import inform, fatal, panic, isInteractive
228 from m5.util.terminal_formatter import TerminalFormatter
229
230 if len(args) == 0:
231 options, arguments = parse_options()
232 elif len(args) == 2:
233 options, arguments = args
234 else:
235 raise TypeError("main() takes 0 or 2 arguments (%d given)" % len(args))
236
237 m5.options = options
238
239 # Set the main event queue for the main thread.
240 event.mainq = event.getEventQueue(0)
241 event.setEventQueue(event.mainq)
242
243 if not os.path.isdir(options.outdir):
244 os.makedirs(options.outdir)
245
246 # These filenames are used only if the redirect_std* options are set
247 stdout_file = os.path.join(options.outdir, options.stdout_file)
248 stderr_file = os.path.join(options.outdir, options.stderr_file)
249
250 # Print redirection notices here before doing any redirection
251 if options.redirect_stdout and not options.redirect_stderr:
252 print("Redirecting stdout and stderr to", stdout_file)
253 else:
254 if options.redirect_stdout:
255 print("Redirecting stdout to", stdout_file)
256 if options.redirect_stderr:
257 print("Redirecting stderr to", stderr_file)
258
259 # Now redirect stdout/stderr as desired
260 if options.redirect_stdout:
261 redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
262 os.dup2(redir_fd, sys.stdout.fileno())
263 if not options.redirect_stderr:
264 os.dup2(redir_fd, sys.stderr.fileno())
265
266 if options.redirect_stderr:
267 redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
268 os.dup2(redir_fd, sys.stderr.fileno())
269
270 done = False
271
272 if options.build_info:
273 done = True
274 print('Build information:')
275 print()
276 print('gem5 version %s' % defines.gem5Version)
277 print('compiled %s' % defines.compileDate)
278 print('build options:')
279 keys = list(defines.buildEnv.keys())
280 keys.sort()
281 for key in keys:
282 val = defines.buildEnv[key]
283 print(' %s = %s' % (key, val))
284 print()
285
286 if options.copyright:
287 done = True
288 print(info.COPYING)
289 print()
290
291 if options.readme:
292 done = True
293 print('Readme:')
294 print()
295 print(info.README)
296 print()
297
298 if options.debug_help:
299 done = True
300 _check_tracing()
301 debug.help()
302
303 if options.list_sim_objects:
304 from . import SimObject
305 done = True
306 print("SimObjects:")
307 objects = list(SimObject.allClasses.keys())
308 objects.sort()
309 terminal_formatter = TerminalFormatter()
310 for name in objects:
311 obj = SimObject.allClasses[name]
312 print(terminal_formatter.format_output(str(obj), indent=4))
313 params = list(obj._params.keys())
314 params.sort()
315 for pname in params:
316 param = obj._params[pname]
317 default = getattr(param, 'default', '')
318 print(terminal_formatter.format_output(pname, indent=8))
319 if default:
320 print(terminal_formatter.format_output(
321 str(default), label="default: ", indent=21))
322 print(terminal_formatter.format_output(
323 param.desc, label="desc: ", indent=21))
324 print()
325 print()
326
327 if done:
328 sys.exit(0)
329
330 # setting verbose and quiet at the same time doesn't make sense
331 if options.verbose > 0 and options.quiet > 0:
332 options.usage(2)
333
334 verbose = options.verbose - options.quiet
335 if verbose >= 0:
336 print("gem5 Simulator System. http://gem5.org")
337 print(brief_copyright)
338 print()
339
340 print("gem5 version %s" % defines.gem5Version)
341 print("gem5 compiled %s" % defines.compileDate)
342
343 print("gem5 started %s" %
344 datetime.datetime.now().strftime("%b %e %Y %X"))
345 print("gem5 executing on %s, pid %d" %
346 (socket.gethostname(), os.getpid()))
347
348 # in Python 3 pipes.quote() is moved to shlex.quote()
349 import pipes
350 print("command line:", " ".join(map(pipes.quote, sys.argv)))
351 print()
352
353 # check to make sure we can find the listed script
354 if not arguments or not os.path.isfile(arguments[0]):
355 if arguments and not os.path.isfile(arguments[0]):
356 print("Script %s not found" % arguments[0])
357
358 options.usage(2)
359
360 # tell C++ about output directory
361 core.setOutputDir(options.outdir)
362
363 # update the system path with elements from the -p option
364 sys.path[0:0] = options.path
365
366 # set stats options
367 stats.addStatVisitor(options.stats_file)
368
369 # Disable listeners unless running interactively or explicitly
370 # enabled
371 if options.listener_mode == "off":
372 m5.disableAllListeners()
373 elif options.listener_mode == "auto":
374 if not isInteractive():
375 inform("Standard input is not a terminal, disabling listeners.")
376 m5.disableAllListeners()
377 elif options.listener_mode == "on":
378 pass
379 else:
380 panic("Unhandled listener mode: %s" % options.listener_mode)
381
382 if options.listener_loopback_only:
383 m5.listenersLoopbackOnly()
384
385 # set debugging options
386 debug.setRemoteGDBPort(options.remote_gdb_port)
387 for when in options.debug_break:
388 debug.schedBreak(int(when))
389
390 if options.debug_flags:
391 _check_tracing()
392
393 on_flags = []
394 off_flags = []
395 for flag in options.debug_flags:
396 off = False
397 if flag.startswith('-'):
398 flag = flag[1:]
399 off = True
400
401 if flag not in debug.flags:
402 print("invalid debug flag '%s'" % flag, file=sys.stderr)
403 sys.exit(1)
404
405 if off:
406 debug.flags[flag].disable()
407 else:
408 debug.flags[flag].enable()
409
410 if options.debug_start:
411 _check_tracing()
412 e = event.create(trace.enable, event.Event.Debug_Enable_Pri)
413 event.mainq.schedule(e, options.debug_start)
414 else:
415 trace.enable()
416
417 if options.debug_end:
418 _check_tracing()
419 e = event.create(trace.disable, event.Event.Debug_Enable_Pri)
420 event.mainq.schedule(e, options.debug_end)
421
422 trace.output(options.debug_file)
423
424 for ignore in options.debug_ignore:
425 _check_tracing()
426 trace.ignore(ignore)
427
428 sys.argv = arguments
429 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
430
431 filename = sys.argv[0]
432 filedata = open(filename, 'r').read()
433 filecode = compile(filedata, filename, 'exec')
434 scope = { '__file__' : filename,
435 '__name__' : '__m5_main__' }
436
437 # if pdb was requested, execfile the thing under pdb, otherwise,
438 # just do the execfile normally
439 if options.pdb:
440 import pdb
441 import traceback
442
443 pdb = pdb.Pdb()
444 try:
445 pdb.run(filecode, scope)
446 except SystemExit:
447 print("The program exited via sys.exit(). Exit status: ", end=' ')
448 print(sys.exc_info()[1])
449 except:
450 traceback.print_exc()
451 print("Uncaught exception. Entering post mortem debugging")
452 t = sys.exc_info()[2]
453 while t.tb_next is not None:
454 t = t.tb_next
455 pdb.interaction(t.tb_frame,t)
456 else:
457 exec(filecode, scope)
458
459 # once the script is done
460 if options.interactive:
461 interact(scope)
462
463 if __name__ == '__main__':
464 from pprint import pprint
465
466 options, arguments = parse_options()
467
468 print('opts:')
469 pprint(options, indent=4)
470 print()
471
472 print('args:')
473 pprint(arguments, indent=4)