main.py revision 9495:ff4b1bde5f60
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="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    try:
133        from IPython.Shell import IPShellEmbed
134        ipshell = IPShellEmbed(argv=[], banner=banner, user_ns=scope)
135        ipshell()
136    except ImportError:
137        code.InteractiveConsole(scope).interact(banner)
138
139def main(*args):
140    import m5
141
142    import core
143    import debug
144    import defines
145    import event
146    import info
147    import stats
148    import trace
149
150    from util import fatal
151
152    if len(args) == 0:
153        options, arguments = parse_options()
154    elif len(args) == 2:
155        options, arguments = args
156    else:
157        raise TypeError, "main() takes 0 or 2 arguments (%d given)" % len(args)
158
159    m5.options = options
160
161    def check_tracing():
162        if defines.TRACING_ON:
163            return
164
165        fatal("Tracing is not enabled.  Compile with TRACING_ON")
166
167    if not os.path.isdir(options.outdir):
168        os.makedirs(options.outdir)
169
170    # These filenames are used only if the redirect_std* options are set
171    stdout_file = os.path.join(options.outdir, options.stdout_file)
172    stderr_file = os.path.join(options.outdir, options.stderr_file)
173
174    # Print redirection notices here before doing any redirection
175    if options.redirect_stdout and not options.redirect_stderr:
176        print "Redirecting stdout and stderr to", stdout_file
177    else:
178        if options.redirect_stdout:
179            print "Redirecting stdout to", stdout_file
180        if options.redirect_stderr:
181            print "Redirecting stderr to", stderr_file
182
183    # Now redirect stdout/stderr as desired
184    if options.redirect_stdout:
185        redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
186        os.dup2(redir_fd, sys.stdout.fileno())
187        if not options.redirect_stderr:
188            os.dup2(redir_fd, sys.stderr.fileno())
189
190    if options.redirect_stderr:
191        redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
192        os.dup2(redir_fd, sys.stderr.fileno())
193
194    done = False
195
196    if options.build_info:
197        done = True
198        print 'Build information:'
199        print
200        print 'compiled %s' % defines.compileDate;
201        print 'build options:'
202        keys = defines.buildEnv.keys()
203        keys.sort()
204        for key in keys:
205            val = defines.buildEnv[key]
206            print '    %s = %s' % (key, val)
207        print
208
209    if options.copyright:
210        done = True
211        print info.COPYING
212        print
213
214    if options.readme:
215        done = True
216        print 'Readme:'
217        print
218        print info.README
219        print
220
221    if options.debug_help:
222        done = True
223        check_tracing()
224        debug.help()
225
226    if options.list_sim_objects:
227        import SimObject
228        done = True
229        print "SimObjects:"
230        objects = SimObject.allClasses.keys()
231        objects.sort()
232        for name in objects:
233            obj = SimObject.allClasses[name]
234            print "    %s" % obj
235            params = obj._params.keys()
236            params.sort()
237            for pname in params:
238                param = obj._params[pname]
239                default = getattr(param, 'default', '')
240                print "        %s" % pname
241                if default:
242                    print "            default: %s" % default
243                print "            desc: %s" % param.desc
244                print
245            print
246
247    if done:
248        sys.exit(0)
249
250    # setting verbose and quiet at the same time doesn't make sense
251    if options.verbose > 0 and options.quiet > 0:
252        options.usage(2)
253
254    verbose = options.verbose - options.quiet
255    if options.verbose >= 0:
256        print "gem5 Simulator System.  http://gem5.org"
257        print brief_copyright
258        print
259
260        print "gem5 compiled %s" % defines.compileDate;
261
262        print "gem5 started %s" % \
263            datetime.datetime.now().strftime("%b %e %Y %X")
264        print "gem5 executing on %s" % socket.gethostname()
265
266        print "command line:",
267        for argv in sys.argv:
268            print argv,
269        print
270
271    # check to make sure we can find the listed script
272    if not arguments or not os.path.isfile(arguments[0]):
273        if arguments and not os.path.isfile(arguments[0]):
274            print "Script %s not found" % arguments[0]
275
276        options.usage(2)
277
278    # tell C++ about output directory
279    core.setOutputDir(options.outdir)
280
281    # update the system path with elements from the -p option
282    sys.path[0:0] = options.path
283
284    # set stats options
285    stats.initText(options.stats_file)
286
287    # set debugging options
288    debug.setRemoteGDBPort(options.remote_gdb_port)
289    for when in options.debug_break:
290        debug.schedBreakCycle(int(when))
291
292    if options.debug_flags:
293        check_tracing()
294
295        on_flags = []
296        off_flags = []
297        for flag in options.debug_flags:
298            off = False
299            if flag.startswith('-'):
300                flag = flag[1:]
301                off = True
302
303            if flag not in debug.flags:
304                print >>sys.stderr, "invalid debug flag '%s'" % flag
305                sys.exit(1)
306
307            if off:
308                debug.flags[flag].disable()
309            else:
310                debug.flags[flag].enable()
311
312    if options.trace_start:
313        check_tracing()
314        e = event.create(trace.enable, event.Event.Trace_Enable_Pri)
315        event.mainq.schedule(e, options.trace_start)
316    else:
317        trace.enable()
318
319    trace.output(options.trace_file)
320
321    for ignore in options.trace_ignore:
322        check_tracing()
323        trace.ignore(ignore)
324
325    sys.argv = arguments
326    sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
327
328    filename = sys.argv[0]
329    filedata = file(filename, 'r').read()
330    filecode = compile(filedata, filename, 'exec')
331    scope = { '__file__' : filename,
332              '__name__' : '__m5_main__' }
333
334    # we want readline if we're doing anything interactive
335    if options.interactive or options.pdb:
336        exec "import readline" in scope
337
338    # if pdb was requested, execfile the thing under pdb, otherwise,
339    # just do the execfile normally
340    if options.pdb:
341        import pdb
342        import traceback
343
344        pdb = pdb.Pdb()
345        try:
346            pdb.run(filecode, scope)
347        except SystemExit:
348            print "The program exited via sys.exit(). Exit status: ",
349            print sys.exc_info()[1]
350        except:
351            traceback.print_exc()
352            print "Uncaught exception. Entering post mortem debugging"
353            t = sys.exc_info()[2]
354            while t.tb_next is not None:
355                t = t.tb_next
356                pdb.interaction(t.tb_frame,t)
357    else:
358        exec filecode in scope
359
360    # once the script is done
361    if options.interactive:
362        interact(scope)
363
364if __name__ == '__main__':
365    from pprint import pprint
366
367    options, arguments = parse_options()
368
369    print 'opts:'
370    pprint(options, indent=4)
371    print
372
373    print 'args:'
374    pprint(arguments, indent=4)
375