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