main.py revision 13671
1# Copyright (c) 2016 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# Authors: Nathan Binkert 40 41from __future__ import print_function 42 43import code 44import datetime 45import os 46import socket 47import sys 48 49__all__ = [ 'options', 'arguments', 'main' ] 50 51usage="%prog [gem5 options] script.py [script options]" 52version="%prog 2.0" 53brief_copyright=\ 54 "gem5 is copyrighted software; use the --copyright option for details." 55 56def parse_options(): 57 import config 58 from options import OptionParser 59 60 options = OptionParser(usage=usage, version=version, 61 description=brief_copyright) 62 option = options.add_option 63 group = options.set_group 64 65 listener_modes = ( "on", "off", "auto" ) 66 67 # Help options 68 option('-B', "--build-info", action="store_true", default=False, 69 help="Show build information") 70 option('-C', "--copyright", action="store_true", default=False, 71 help="Show full copyright information") 72 option('-R', "--readme", action="store_true", default=False, 73 help="Show the readme") 74 75 # Options for configuring the base simulator 76 option('-d', "--outdir", metavar="DIR", default="m5out", 77 help="Set the output directory to DIR [Default: %default]") 78 option('-r', "--redirect-stdout", action="store_true", default=False, 79 help="Redirect stdout (& stderr, without -e) to file") 80 option('-e', "--redirect-stderr", action="store_true", default=False, 81 help="Redirect stderr to file") 82 option("--stdout-file", metavar="FILE", default="simout", 83 help="Filename for -r redirection [Default: %default]") 84 option("--stderr-file", metavar="FILE", default="simerr", 85 help="Filename for -e redirection [Default: %default]") 86 option("--listener-mode", metavar="{on,off,auto}", 87 choices=listener_modes, default="auto", 88 help="Port (e.g., gdb) listener mode (auto: Enable if running " \ 89 "interactively) [Default: %default]") 90 option("--listener-loopback-only", action="store_true", default=False, 91 help="Port listeners will only accept connections over the " \ 92 "loopback device") 93 option('-i', "--interactive", action="store_true", default=False, 94 help="Invoke the interactive interpreter after running the script") 95 option("--pdb", action="store_true", default=False, 96 help="Invoke the python debugger before running the script") 97 option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':', 98 help="Prepend PATH to the system path when invoking the script") 99 option('-q', "--quiet", action="count", default=0, 100 help="Reduce verbosity") 101 option('-v', "--verbose", action="count", default=0, 102 help="Increase verbosity") 103 104 # Statistics options 105 group("Statistics Options") 106 option("--stats-file", metavar="FILE", default="stats.txt", 107 help="Sets the output file for statistics [Default: %default]") 108 109 # Configuration Options 110 group("Configuration Options") 111 option("--dump-config", metavar="FILE", default="config.ini", 112 help="Dump configuration output file [Default: %default]") 113 option("--json-config", metavar="FILE", default="config.json", 114 help="Create JSON output of the configuration [Default: %default]") 115 option("--dot-config", metavar="FILE", default="config.dot", 116 help="Create DOT & pdf outputs of the configuration [Default: %default]") 117 option("--dot-dvfs-config", metavar="FILE", default=None, 118 help="Create DOT & pdf outputs of the DVFS configuration" + \ 119 " [Default: %default]") 120 121 # Debugging options 122 group("Debugging Options") 123 option("--debug-break", metavar="TICK[,TICK]", action='append', split=',', 124 help="Create breakpoint(s) at TICK(s) " \ 125 "(kills process if no debugger attached)") 126 option("--debug-help", action='store_true', 127 help="Print help on debug flags") 128 option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',', 129 help="Sets the flags for debug output (-FLAG disables a flag)") 130 option("--debug-start", metavar="TICK", type='int', 131 help="Start debug output at TICK") 132 option("--debug-end", metavar="TICK", type='int', 133 help="End debug output at TICK") 134 option("--debug-file", metavar="FILE", default="cout", 135 help="Sets the output file for debug [Default: %default]") 136 option("--debug-ignore", metavar="EXPR", action='append', split=':', 137 help="Ignore EXPR sim objects") 138 option("--remote-gdb-port", type='int', default=7000, 139 help="Remote gdb base port (set to 0 to disable listening)") 140 141 # Help options 142 group("Help Options") 143 option("--list-sim-objects", action='store_true', default=False, 144 help="List all built-in SimObjects, their params and default values") 145 146 # load the options.py config file to allow people to set their own 147 # default options 148 options_file = config.get('options.py') 149 if options_file: 150 scope = { 'options' : options } 151 exec(compile(open(options_file).read(), options_file, 'exec'), scope) 152 153 arguments = options.parse_args() 154 return options,arguments 155 156def interact(scope): 157 banner = "gem5 Interactive Console" 158 159 ipshell = None 160 prompt_in1 = "gem5 \\#> " 161 prompt_out = "gem5 \\#: " 162 163 # Is IPython version 0.10 or earlier available? 164 try: 165 from IPython.Shell import IPShellEmbed 166 ipshell = IPShellEmbed(argv=["-prompt_in1", prompt_in1, 167 "-prompt_out", prompt_out], 168 banner=banner, user_ns=scope) 169 except ImportError: 170 pass 171 172 # Is IPython version 0.11 or later available? 173 if not ipshell: 174 try: 175 import IPython 176 from IPython.config.loader import Config 177 from IPython.terminal.embed import InteractiveShellEmbed 178 179 cfg = Config() 180 cfg.PromptManager.in_template = prompt_in1 181 cfg.PromptManager.out_template = prompt_out 182 ipshell = InteractiveShellEmbed(config=cfg, user_ns=scope, 183 banner1=banner) 184 except ImportError: 185 pass 186 187 if ipshell: 188 ipshell() 189 else: 190 # Use the Python shell in the standard library if IPython 191 # isn't available. 192 code.InteractiveConsole(scope).interact(banner) 193 194 195def _check_tracing(): 196 if defines.TRACING_ON: 197 return 198 199 fatal("Tracing is not enabled. Compile with TRACING_ON") 200 201def main(*args): 202 import m5 203 204 import core 205 import debug 206 import defines 207 import event 208 import info 209 import stats 210 import trace 211 212 from util import inform, fatal, panic, isInteractive 213 214 if len(args) == 0: 215 options, arguments = parse_options() 216 elif len(args) == 2: 217 options, arguments = args 218 else: 219 raise TypeError("main() takes 0 or 2 arguments (%d given)" % len(args)) 220 221 m5.options = options 222 223 # Set the main event queue for the main thread. 224 event.mainq = event.getEventQueue(0) 225 event.setEventQueue(event.mainq) 226 227 if not os.path.isdir(options.outdir): 228 os.makedirs(options.outdir) 229 230 # These filenames are used only if the redirect_std* options are set 231 stdout_file = os.path.join(options.outdir, options.stdout_file) 232 stderr_file = os.path.join(options.outdir, options.stderr_file) 233 234 # Print redirection notices here before doing any redirection 235 if options.redirect_stdout and not options.redirect_stderr: 236 print("Redirecting stdout and stderr to", stdout_file) 237 else: 238 if options.redirect_stdout: 239 print("Redirecting stdout to", stdout_file) 240 if options.redirect_stderr: 241 print("Redirecting stderr to", stderr_file) 242 243 # Now redirect stdout/stderr as desired 244 if options.redirect_stdout: 245 redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 246 os.dup2(redir_fd, sys.stdout.fileno()) 247 if not options.redirect_stderr: 248 os.dup2(redir_fd, sys.stderr.fileno()) 249 250 if options.redirect_stderr: 251 redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 252 os.dup2(redir_fd, sys.stderr.fileno()) 253 254 done = False 255 256 if options.build_info: 257 done = True 258 print('Build information:') 259 print() 260 print('compiled %s' % defines.compileDate) 261 print('build options:') 262 keys = defines.buildEnv.keys() 263 keys.sort() 264 for key in keys: 265 val = defines.buildEnv[key] 266 print(' %s = %s' % (key, val)) 267 print() 268 269 if options.copyright: 270 done = True 271 print(info.COPYING) 272 print() 273 274 if options.readme: 275 done = True 276 print('Readme:') 277 print() 278 print(info.README) 279 print() 280 281 if options.debug_help: 282 done = True 283 _check_tracing() 284 debug.help() 285 286 if options.list_sim_objects: 287 import SimObject 288 done = True 289 print("SimObjects:") 290 objects = SimObject.allClasses.keys() 291 objects.sort() 292 for name in objects: 293 obj = SimObject.allClasses[name] 294 print(" %s" % obj) 295 params = obj._params.keys() 296 params.sort() 297 for pname in params: 298 param = obj._params[pname] 299 default = getattr(param, 'default', '') 300 print(" %s" % pname) 301 if default: 302 print(" default: %s" % default) 303 print(" desc: %s" % param.desc) 304 print() 305 print() 306 307 if done: 308 sys.exit(0) 309 310 # setting verbose and quiet at the same time doesn't make sense 311 if options.verbose > 0 and options.quiet > 0: 312 options.usage(2) 313 314 verbose = options.verbose - options.quiet 315 if verbose >= 0: 316 print("gem5 Simulator System. http://gem5.org") 317 print(brief_copyright) 318 print() 319 320 print("gem5 compiled %s" % defines.compileDate) 321 322 print("gem5 started %s" % 323 datetime.datetime.now().strftime("%b %e %Y %X")) 324 print("gem5 executing on %s, pid %d" % 325 (socket.gethostname(), os.getpid())) 326 327 # in Python 3 pipes.quote() is moved to shlex.quote() 328 import pipes 329 print("command line:", " ".join(map(pipes.quote, sys.argv))) 330 print() 331 332 # check to make sure we can find the listed script 333 if not arguments or not os.path.isfile(arguments[0]): 334 if arguments and not os.path.isfile(arguments[0]): 335 print("Script %s not found" % arguments[0]) 336 337 options.usage(2) 338 339 # tell C++ about output directory 340 core.setOutputDir(options.outdir) 341 342 # update the system path with elements from the -p option 343 sys.path[0:0] = options.path 344 345 # set stats options 346 stats.addStatVisitor(options.stats_file) 347 348 # Disable listeners unless running interactively or explicitly 349 # enabled 350 if options.listener_mode == "off": 351 m5.disableAllListeners() 352 elif options.listener_mode == "auto": 353 if not isInteractive(): 354 inform("Standard input is not a terminal, disabling listeners.") 355 m5.disableAllListeners() 356 elif options.listener_mode == "on": 357 pass 358 else: 359 panic("Unhandled listener mode: %s" % options.listener_mode) 360 361 if options.listener_loopback_only: 362 m5.listenersLoopbackOnly() 363 364 # set debugging options 365 debug.setRemoteGDBPort(options.remote_gdb_port) 366 for when in options.debug_break: 367 debug.schedBreak(int(when)) 368 369 if options.debug_flags: 370 _check_tracing() 371 372 on_flags = [] 373 off_flags = [] 374 for flag in options.debug_flags: 375 off = False 376 if flag.startswith('-'): 377 flag = flag[1:] 378 off = True 379 380 if flag not in debug.flags: 381 print("invalid debug flag '%s'" % flag, file=sys.stderr) 382 sys.exit(1) 383 384 if off: 385 debug.flags[flag].disable() 386 else: 387 debug.flags[flag].enable() 388 389 if options.debug_start: 390 _check_tracing() 391 e = event.create(trace.enable, event.Event.Debug_Enable_Pri) 392 event.mainq.schedule(e, options.debug_start) 393 else: 394 trace.enable() 395 396 if options.debug_end: 397 _check_tracing() 398 e = event.create(trace.disable, event.Event.Debug_Enable_Pri) 399 event.mainq.schedule(e, options.debug_end) 400 401 trace.output(options.debug_file) 402 403 for ignore in options.debug_ignore: 404 _check_tracing() 405 trace.ignore(ignore) 406 407 sys.argv = arguments 408 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path 409 410 filename = sys.argv[0] 411 filedata = open(filename, 'r').read() 412 filecode = compile(filedata, filename, 'exec') 413 scope = { '__file__' : filename, 414 '__name__' : '__m5_main__' } 415 416 # if pdb was requested, execfile the thing under pdb, otherwise, 417 # just do the execfile normally 418 if options.pdb: 419 import pdb 420 import traceback 421 422 pdb = pdb.Pdb() 423 try: 424 pdb.run(filecode, scope) 425 except SystemExit: 426 print("The program exited via sys.exit(). Exit status: ", end=' ') 427 print(sys.exc_info()[1]) 428 except: 429 traceback.print_exc() 430 print("Uncaught exception. Entering post mortem debugging") 431 t = sys.exc_info()[2] 432 while t.tb_next is not None: 433 t = t.tb_next 434 pdb.interaction(t.tb_frame,t) 435 else: 436 exec(filecode, scope) 437 438 # once the script is done 439 if options.interactive: 440 interact(scope) 441 442if __name__ == '__main__': 443 from pprint import pprint 444 445 options, arguments = parse_options() 446 447 print('opts:') 448 pprint(options, indent=4) 449 print() 450 451 print('args:') 452 pprint(arguments, indent=4) 453