main.py revision 13709
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 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 import core 207 import debug 208 import defines 209 import event 210 import info 211 import stats 212 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 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