main.py revision 9512
112027Sjungma@eit.uni-kl.de# Copyright (c) 2005 The Regents of The University of Michigan
212027Sjungma@eit.uni-kl.de# All rights reserved.
312027Sjungma@eit.uni-kl.de#
412027Sjungma@eit.uni-kl.de# Redistribution and use in source and binary forms, with or without
512027Sjungma@eit.uni-kl.de# modification, are permitted provided that the following conditions are
612027Sjungma@eit.uni-kl.de# met: redistributions of source code must retain the above copyright
712027Sjungma@eit.uni-kl.de# notice, this list of conditions and the following disclaimer;
812027Sjungma@eit.uni-kl.de# redistributions in binary form must reproduce the above copyright
912027Sjungma@eit.uni-kl.de# notice, this list of conditions and the following disclaimer in the
1012027Sjungma@eit.uni-kl.de# documentation and/or other materials provided with the distribution;
1112027Sjungma@eit.uni-kl.de# neither the name of the copyright holders nor the names of its
1212027Sjungma@eit.uni-kl.de# 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="TIME[,TIME]", action='append', split=',',
98        help="Cycle to create a breakpoint")
99    option("--debug-help", action='store_true',
100        help="Print help on trace flags")
101    option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',',
102        help="Sets the flags for tracing (-FLAG disables a flag)")
103    option("--remote-gdb-port", type='int', default=7000,
104        help="Remote gdb base port (set to 0 to disable listening)")
105
106    # Tracing options
107    group("Trace Options")
108    option("--trace-start", metavar="TIME", type='int',
109        help="Start tracing at TIME (must be in ticks)")
110    option("--trace-file", metavar="FILE", default="cout",
111        help="Sets the output file for tracing [Default: %default]")
112    option("--trace-ignore", metavar="EXPR", action='append', split=':',
113        help="Ignore EXPR sim objects")
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    if not os.path.isdir(options.outdir):
197        os.makedirs(options.outdir)
198
199    # These filenames are used only if the redirect_std* options are set
200    stdout_file = os.path.join(options.outdir, options.stdout_file)
201    stderr_file = os.path.join(options.outdir, options.stderr_file)
202
203    # Print redirection notices here before doing any redirection
204    if options.redirect_stdout and not options.redirect_stderr:
205        print "Redirecting stdout and stderr to", stdout_file
206    else:
207        if options.redirect_stdout:
208            print "Redirecting stdout to", stdout_file
209        if options.redirect_stderr:
210            print "Redirecting stderr to", stderr_file
211
212    # Now redirect stdout/stderr as desired
213    if options.redirect_stdout:
214        redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
215        os.dup2(redir_fd, sys.stdout.fileno())
216        if not options.redirect_stderr:
217            os.dup2(redir_fd, sys.stderr.fileno())
218
219    if options.redirect_stderr:
220        redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
221        os.dup2(redir_fd, sys.stderr.fileno())
222
223    done = False
224
225    if options.build_info:
226        done = True
227        print 'Build information:'
228        print
229        print 'compiled %s' % defines.compileDate;
230        print 'build options:'
231        keys = defines.buildEnv.keys()
232        keys.sort()
233        for key in keys:
234            val = defines.buildEnv[key]
235            print '    %s = %s' % (key, val)
236        print
237
238    if options.copyright:
239        done = True
240        print info.COPYING
241        print
242
243    if options.readme:
244        done = True
245        print 'Readme:'
246        print
247        print info.README
248        print
249
250    if options.debug_help:
251        done = True
252        check_tracing()
253        debug.help()
254
255    if options.list_sim_objects:
256        import SimObject
257        done = True
258        print "SimObjects:"
259        objects = SimObject.allClasses.keys()
260        objects.sort()
261        for name in objects:
262            obj = SimObject.allClasses[name]
263            print "    %s" % obj
264            params = obj._params.keys()
265            params.sort()
266            for pname in params:
267                param = obj._params[pname]
268                default = getattr(param, 'default', '')
269                print "        %s" % pname
270                if default:
271                    print "            default: %s" % default
272                print "            desc: %s" % param.desc
273                print
274            print
275
276    if done:
277        sys.exit(0)
278
279    # setting verbose and quiet at the same time doesn't make sense
280    if options.verbose > 0 and options.quiet > 0:
281        options.usage(2)
282
283    verbose = options.verbose - options.quiet
284    if options.verbose >= 0:
285        print "gem5 Simulator System.  http://gem5.org"
286        print brief_copyright
287        print
288
289        print "gem5 compiled %s" % defines.compileDate;
290
291        print "gem5 started %s" % \
292            datetime.datetime.now().strftime("%b %e %Y %X")
293        print "gem5 executing on %s" % socket.gethostname()
294
295        print "command line:",
296        for argv in sys.argv:
297            print argv,
298        print
299
300    # check to make sure we can find the listed script
301    if not arguments or not os.path.isfile(arguments[0]):
302        if arguments and not os.path.isfile(arguments[0]):
303            print "Script %s not found" % arguments[0]
304
305        options.usage(2)
306
307    # tell C++ about output directory
308    core.setOutputDir(options.outdir)
309
310    # update the system path with elements from the -p option
311    sys.path[0:0] = options.path
312
313    # set stats options
314    stats.initText(options.stats_file)
315
316    # set debugging options
317    debug.setRemoteGDBPort(options.remote_gdb_port)
318    for when in options.debug_break:
319        debug.schedBreakCycle(int(when))
320
321    if options.debug_flags:
322        check_tracing()
323
324        on_flags = []
325        off_flags = []
326        for flag in options.debug_flags:
327            off = False
328            if flag.startswith('-'):
329                flag = flag[1:]
330                off = True
331
332            if flag not in debug.flags:
333                print >>sys.stderr, "invalid debug flag '%s'" % flag
334                sys.exit(1)
335
336            if off:
337                debug.flags[flag].disable()
338            else:
339                debug.flags[flag].enable()
340
341    if options.trace_start:
342        check_tracing()
343        e = event.create(trace.enable, event.Event.Trace_Enable_Pri)
344        event.mainq.schedule(e, options.trace_start)
345    else:
346        trace.enable()
347
348    trace.output(options.trace_file)
349
350    for ignore in options.trace_ignore:
351        check_tracing()
352        trace.ignore(ignore)
353
354    sys.argv = arguments
355    sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
356
357    filename = sys.argv[0]
358    filedata = file(filename, 'r').read()
359    filecode = compile(filedata, filename, 'exec')
360    scope = { '__file__' : filename,
361              '__name__' : '__m5_main__' }
362
363    # we want readline if we're doing anything interactive
364    if options.interactive or options.pdb:
365        exec "import readline" in scope
366
367    # if pdb was requested, execfile the thing under pdb, otherwise,
368    # just do the execfile normally
369    if options.pdb:
370        import pdb
371        import traceback
372
373        pdb = pdb.Pdb()
374        try:
375            pdb.run(filecode, scope)
376        except SystemExit:
377            print "The program exited via sys.exit(). Exit status: ",
378            print sys.exc_info()[1]
379        except:
380            traceback.print_exc()
381            print "Uncaught exception. Entering post mortem debugging"
382            t = sys.exc_info()[2]
383            while t.tb_next is not None:
384                t = t.tb_next
385                pdb.interaction(t.tb_frame,t)
386    else:
387        exec filecode in scope
388
389    # once the script is done
390    if options.interactive:
391        interact(scope)
392
393if __name__ == '__main__':
394    from pprint import pprint
395
396    options, arguments = parse_options()
397
398    print 'opts:'
399    pprint(options, indent=4)
400    print
401
402    print 'args:'
403    pprint(arguments, indent=4)
404