main.py revision 13714
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 from . 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 import defines 197 198 if defines.TRACING_ON: 199 return 200 201 fatal("Tracing is not enabled. Compile with TRACING_ON") 202 203def main(*args): 204 import m5 205 206 from . import core 207 from . import debug 208 from . import defines 209 from . import event 210 from . import info 211 from . import stats 212 from . import trace 213 214 from .util import inform, fatal, panic, isInteractive 215 216 if len(args) == 0: 217 options, arguments = parse_options() 218 elif len(args) == 2: 219 options, arguments = args 220 else: 221 raise TypeError("main() takes 0 or 2 arguments (%d given)" % len(args)) 222 223 m5.options = options 224 225 # Set the main event queue for the main thread. 226 event.mainq = event.getEventQueue(0) 227 event.setEventQueue(event.mainq) 228 229 if not os.path.isdir(options.outdir): 230 os.makedirs(options.outdir) 231 232 # These filenames are used only if the redirect_std* options are set 233 stdout_file = os.path.join(options.outdir, options.stdout_file) 234 stderr_file = os.path.join(options.outdir, options.stderr_file) 235 236 # Print redirection notices here before doing any redirection 237 if options.redirect_stdout and not options.redirect_stderr: 238 print("Redirecting stdout and stderr to", stdout_file) 239 else: 240 if options.redirect_stdout: 241 print("Redirecting stdout to", stdout_file) 242 if options.redirect_stderr: 243 print("Redirecting stderr to", stderr_file) 244 245 # Now redirect stdout/stderr as desired 246 if options.redirect_stdout: 247 redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 248 os.dup2(redir_fd, sys.stdout.fileno()) 249 if not options.redirect_stderr: 250 os.dup2(redir_fd, sys.stderr.fileno()) 251 252 if options.redirect_stderr: 253 redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 254 os.dup2(redir_fd, sys.stderr.fileno()) 255 256 done = False 257 258 if options.build_info: 259 done = True 260 print('Build information:') 261 print() 262 print('compiled %s' % defines.compileDate) 263 print('build options:') 264 keys = list(defines.buildEnv.keys()) 265 keys.sort() 266 for key in keys: 267 val = defines.buildEnv[key] 268 print(' %s = %s' % (key, val)) 269 print() 270 271 if options.copyright: 272 done = True 273 print(info.COPYING) 274 print() 275 276 if options.readme: 277 done = True 278 print('Readme:') 279 print() 280 print(info.README) 281 print() 282 283 if options.debug_help: 284 done = True 285 _check_tracing() 286 debug.help() 287 288 if options.list_sim_objects: 289 from . import SimObject 290 done = True 291 print("SimObjects:") 292 objects = list(SimObject.allClasses.keys()) 293 objects.sort() 294 for name in objects: 295 obj = SimObject.allClasses[name] 296 print(" %s" % obj) 297 params = list(obj._params.keys()) 298 params.sort() 299 for pname in params: 300 param = obj._params[pname] 301 default = getattr(param, 'default', '') 302 print(" %s" % pname) 303 if default: 304 print(" default: %s" % default) 305 print(" desc: %s" % param.desc) 306 print() 307 print() 308 309 if done: 310 sys.exit(0) 311 312 # setting verbose and quiet at the same time doesn't make sense 313 if options.verbose > 0 and options.quiet > 0: 314 options.usage(2) 315 316 verbose = options.verbose - options.quiet 317 if verbose >= 0: 318 print("gem5 Simulator System. http://gem5.org") 319 print(brief_copyright) 320 print() 321 322 print("gem5 compiled %s" % defines.compileDate) 323 324 print("gem5 started %s" % 325 datetime.datetime.now().strftime("%b %e %Y %X")) 326 print("gem5 executing on %s, pid %d" % 327 (socket.gethostname(), os.getpid())) 328 329 # in Python 3 pipes.quote() is moved to shlex.quote() 330 import pipes 331 print("command line:", " ".join(map(pipes.quote, sys.argv))) 332 print() 333 334 # check to make sure we can find the listed script 335 if not arguments or not os.path.isfile(arguments[0]): 336 if arguments and not os.path.isfile(arguments[0]): 337 print("Script %s not found" % arguments[0]) 338 339 options.usage(2) 340 341 # tell C++ about output directory 342 core.setOutputDir(options.outdir) 343 344 # update the system path with elements from the -p option 345 sys.path[0:0] = options.path 346 347 # set stats options 348 stats.addStatVisitor(options.stats_file) 349 350 # Disable listeners unless running interactively or explicitly 351 # enabled 352 if options.listener_mode == "off": 353 m5.disableAllListeners() 354 elif options.listener_mode == "auto": 355 if not isInteractive(): 356 inform("Standard input is not a terminal, disabling listeners.") 357 m5.disableAllListeners() 358 elif options.listener_mode == "on": 359 pass 360 else: 361 panic("Unhandled listener mode: %s" % options.listener_mode) 362 363 if options.listener_loopback_only: 364 m5.listenersLoopbackOnly() 365 366 # set debugging options 367 debug.setRemoteGDBPort(options.remote_gdb_port) 368 for when in options.debug_break: 369 debug.schedBreak(int(when)) 370 371 if options.debug_flags: 372 _check_tracing() 373 374 on_flags = [] 375 off_flags = [] 376 for flag in options.debug_flags: 377 off = False 378 if flag.startswith('-'): 379 flag = flag[1:] 380 off = True 381 382 if flag not in debug.flags: 383 print("invalid debug flag '%s'" % flag, file=sys.stderr) 384 sys.exit(1) 385 386 if off: 387 debug.flags[flag].disable() 388 else: 389 debug.flags[flag].enable() 390 391 if options.debug_start: 392 _check_tracing() 393 e = event.create(trace.enable, event.Event.Debug_Enable_Pri) 394 event.mainq.schedule(e, options.debug_start) 395 else: 396 trace.enable() 397 398 if options.debug_end: 399 _check_tracing() 400 e = event.create(trace.disable, event.Event.Debug_Enable_Pri) 401 event.mainq.schedule(e, options.debug_end) 402 403 trace.output(options.debug_file) 404 405 for ignore in options.debug_ignore: 406 _check_tracing() 407 trace.ignore(ignore) 408 409 sys.argv = arguments 410 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path 411 412 filename = sys.argv[0] 413 filedata = open(filename, 'r').read() 414 filecode = compile(filedata, filename, 'exec') 415 scope = { '__file__' : filename, 416 '__name__' : '__m5_main__' } 417 418 # if pdb was requested, execfile the thing under pdb, otherwise, 419 # just do the execfile normally 420 if options.pdb: 421 import pdb 422 import traceback 423 424 pdb = pdb.Pdb() 425 try: 426 pdb.run(filecode, scope) 427 except SystemExit: 428 print("The program exited via sys.exit(). Exit status: ", end=' ') 429 print(sys.exc_info()[1]) 430 except: 431 traceback.print_exc() 432 print("Uncaught exception. Entering post mortem debugging") 433 t = sys.exc_info()[2] 434 while t.tb_next is not None: 435 t = t.tb_next 436 pdb.interaction(t.tb_frame,t) 437 else: 438 exec(filecode, scope) 439 440 # once the script is done 441 if options.interactive: 442 interact(scope) 443 444if __name__ == '__main__': 445 from pprint import pprint 446 447 options, arguments = parse_options() 448 449 print('opts:') 450 pprint(options, indent=4) 451 print() 452 453 print('args:') 454 pprint(arguments, indent=4) 455