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