main.py revision 11338
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 29import code 30import datetime 31import os 32import socket 33import sys 34 35__all__ = [ 'options', 'arguments', 'main' ] 36 37usage="%prog [gem5 options] script.py [script options]" 38version="%prog 2.0" 39brief_copyright=\ 40 "gem5 is copyrighted software; use the --copyright option for details." 41 42def 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="TICK[,TICK]", action='append', split=',', 98 help="Create breakpoint(s) at TICK(s) " \ 99 "(kills process if no debugger attached)") 100 option("--debug-help", action='store_true', 101 help="Print help on debug flags") 102 option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',', 103 help="Sets the flags for debug output (-FLAG disables a flag)") 104 option("--debug-start", metavar="TICK", type='int', 105 help="Start debug output at TICK") 106 option("--debug-end", metavar="TICK", type='int', 107 help="End debug output at TICK") 108 option("--debug-file", metavar="FILE", default="cout", 109 help="Sets the output file for debug [Default: %default]") 110 option("--debug-ignore", metavar="EXPR", action='append', split=':', 111 help="Ignore EXPR sim objects") 112 option("--remote-gdb-port", type='int', default=7000, 113 help="Remote gdb base port (set to 0 to disable listening)") 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 130def interact(scope): 131 banner = "gem5 Interactive Console" 132 133 ipshell = None 134 prompt_in1 = "gem5 \\#> " 135 prompt_out = "gem5 \\#: " 136 137 # Is IPython version 0.10 or earlier available? 138 try: 139 from IPython.Shell import IPShellEmbed 140 ipshell = IPShellEmbed(argv=["-prompt_in1", prompt_in1, 141 "-prompt_out", prompt_out], 142 banner=banner, user_ns=scope) 143 except ImportError: 144 pass 145 146 # Is IPython version 0.11 or later available? 147 if not ipshell: 148 try: 149 import IPython 150 from IPython.config.loader import Config 151 from IPython.frontend.terminal.embed import InteractiveShellEmbed 152 153 cfg = Config() 154 cfg.PromptManager.in_template = prompt_in1 155 cfg.PromptManager.out_template = prompt_out 156 ipshell = InteractiveShellEmbed(config=cfg, user_ns=scope, 157 banner1=banner) 158 except ImportError: 159 pass 160 161 if ipshell: 162 ipshell() 163 else: 164 # Use the Python shell in the standard library if IPython 165 # isn't available. 166 code.InteractiveConsole(scope).interact(banner) 167 168def main(*args): 169 import m5 170 171 import core 172 import debug 173 import defines 174 import event 175 import info 176 import stats 177 import trace 178 179 from util import fatal 180 181 if len(args) == 0: 182 options, arguments = parse_options() 183 elif len(args) == 2: 184 options, arguments = args 185 else: 186 raise TypeError, "main() takes 0 or 2 arguments (%d given)" % len(args) 187 188 m5.options = options 189 190 def check_tracing(): 191 if defines.TRACING_ON: 192 return 193 194 fatal("Tracing is not enabled. Compile with TRACING_ON") 195 196 # Set the main event queue for the main thread. 197 event.mainq = event.getEventQueue(0) 198 event.setEventQueue(event.mainq) 199 200 if not os.path.isdir(options.outdir): 201 os.makedirs(options.outdir) 202 203 # These filenames are used only if the redirect_std* options are set 204 stdout_file = os.path.join(options.outdir, options.stdout_file) 205 stderr_file = os.path.join(options.outdir, options.stderr_file) 206 207 # Print redirection notices here before doing any redirection 208 if options.redirect_stdout and not options.redirect_stderr: 209 print "Redirecting stdout and stderr to", stdout_file 210 else: 211 if options.redirect_stdout: 212 print "Redirecting stdout to", stdout_file 213 if options.redirect_stderr: 214 print "Redirecting stderr to", stderr_file 215 216 # Now redirect stdout/stderr as desired 217 if options.redirect_stdout: 218 redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 219 os.dup2(redir_fd, sys.stdout.fileno()) 220 if not options.redirect_stderr: 221 os.dup2(redir_fd, sys.stderr.fileno()) 222 223 if options.redirect_stderr: 224 redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) 225 os.dup2(redir_fd, sys.stderr.fileno()) 226 227 done = False 228 229 if options.build_info: 230 done = True 231 print 'Build information:' 232 print 233 print 'compiled %s' % defines.compileDate; 234 print 'build options:' 235 keys = defines.buildEnv.keys() 236 keys.sort() 237 for key in keys: 238 val = defines.buildEnv[key] 239 print ' %s = %s' % (key, val) 240 print 241 242 if options.copyright: 243 done = True 244 print info.COPYING 245 print 246 247 if options.readme: 248 done = True 249 print 'Readme:' 250 print 251 print info.README 252 print 253 254 if options.debug_help: 255 done = True 256 check_tracing() 257 debug.help() 258 259 if options.list_sim_objects: 260 import SimObject 261 done = True 262 print "SimObjects:" 263 objects = SimObject.allClasses.keys() 264 objects.sort() 265 for name in objects: 266 obj = SimObject.allClasses[name] 267 print " %s" % obj 268 params = obj._params.keys() 269 params.sort() 270 for pname in params: 271 param = obj._params[pname] 272 default = getattr(param, 'default', '') 273 print " %s" % pname 274 if default: 275 print " default: %s" % default 276 print " desc: %s" % param.desc 277 print 278 print 279 280 if done: 281 sys.exit(0) 282 283 # setting verbose and quiet at the same time doesn't make sense 284 if options.verbose > 0 and options.quiet > 0: 285 options.usage(2) 286 287 verbose = options.verbose - options.quiet 288 if verbose >= 0: 289 print "gem5 Simulator System. http://gem5.org" 290 print brief_copyright 291 print 292 293 print "gem5 compiled %s" % defines.compileDate; 294 295 print "gem5 started %s" % \ 296 datetime.datetime.now().strftime("%b %e %Y %X") 297 print "gem5 executing on %s, pid %d" % \ 298 (socket.gethostname(), os.getpid()) 299 300 # in Python 3 pipes.quote() is moved to shlex.quote() 301 import pipes 302 print "command line:", " ".join(map(pipes.quote, sys.argv)) 303 print 304 305 # check to make sure we can find the listed script 306 if not arguments or not os.path.isfile(arguments[0]): 307 if arguments and not os.path.isfile(arguments[0]): 308 print "Script %s not found" % arguments[0] 309 310 options.usage(2) 311 312 # tell C++ about output directory 313 core.setOutputDir(options.outdir) 314 315 # update the system path with elements from the -p option 316 sys.path[0:0] = options.path 317 318 # set stats options 319 stats.initText(options.stats_file) 320 321 # set debugging options 322 debug.setRemoteGDBPort(options.remote_gdb_port) 323 for when in options.debug_break: 324 debug.schedBreak(int(when)) 325 326 if options.debug_flags: 327 check_tracing() 328 329 on_flags = [] 330 off_flags = [] 331 for flag in options.debug_flags: 332 off = False 333 if flag.startswith('-'): 334 flag = flag[1:] 335 off = True 336 337 if flag not in debug.flags: 338 print >>sys.stderr, "invalid debug flag '%s'" % flag 339 sys.exit(1) 340 341 if off: 342 debug.flags[flag].disable() 343 else: 344 debug.flags[flag].enable() 345 346 if options.debug_start: 347 check_tracing() 348 e = event.create(trace.enable, event.Event.Debug_Enable_Pri) 349 event.mainq.schedule(e, options.debug_start) 350 else: 351 trace.enable() 352 353 if options.debug_end: 354 check_tracing() 355 e = event.create(trace.disable, event.Event.Debug_Enable_Pri) 356 event.mainq.schedule(e, options.debug_end) 357 358 trace.output(options.debug_file) 359 360 for ignore in options.debug_ignore: 361 check_tracing() 362 trace.ignore(ignore) 363 364 sys.argv = arguments 365 sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path 366 367 filename = sys.argv[0] 368 filedata = file(filename, 'r').read() 369 filecode = compile(filedata, filename, 'exec') 370 scope = { '__file__' : filename, 371 '__name__' : '__m5_main__' } 372 373 # we want readline if we're doing anything interactive 374 if options.interactive or options.pdb: 375 exec "import readline" in scope 376 377 # if pdb was requested, execfile the thing under pdb, otherwise, 378 # just do the execfile normally 379 if options.pdb: 380 import pdb 381 import traceback 382 383 pdb = pdb.Pdb() 384 try: 385 pdb.run(filecode, scope) 386 except SystemExit: 387 print "The program exited via sys.exit(). Exit status: ", 388 print sys.exc_info()[1] 389 except: 390 traceback.print_exc() 391 print "Uncaught exception. Entering post mortem debugging" 392 t = sys.exc_info()[2] 393 while t.tb_next is not None: 394 t = t.tb_next 395 pdb.interaction(t.tb_frame,t) 396 else: 397 exec filecode in scope 398 399 # once the script is done 400 if options.interactive: 401 interact(scope) 402 403if __name__ == '__main__': 404 from pprint import pprint 405 406 options, arguments = parse_options() 407 408 print 'opts:' 409 pprint(options, indent=4) 410 print 411 412 print 'args:' 413 pprint(arguments, indent=4) 414