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