# Copyright (c) 2016, 2019 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2005 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import code
import datetime
import os
import socket
import sys

__all__ = [ 'options', 'arguments', 'main' ]

usage="%prog [gem5 options] script.py [script options]"
brief_copyright=\
    "gem5 is copyrighted software; use the --copyright option for details."

def _stats_help(option, opt, value, parser):
    import m5
    print("A stat file can either be specified as a URI or a plain")
    print("path. When specified as a path, gem5 uses the default text ")
    print("format.")
    print()
    print("The following stat formats are supported:")
    print()
    m5.stats.printStatVisitorTypes()
    sys.exit(0)


def parse_options():
    from .options import OptionParser

    options = OptionParser(usage=usage, description=brief_copyright)
    option = options.add_option
    group = options.set_group

    listener_modes = ( "on", "off", "auto" )

    # Help options
    option('-B', "--build-info", action="store_true", default=False,
        help="Show build information")
    option('-C', "--copyright", action="store_true", default=False,
        help="Show full copyright information")
    option('-R', "--readme", action="store_true", default=False,
        help="Show the readme")

    # Options for configuring the base simulator
    option('-d', "--outdir", metavar="DIR", default="m5out",
        help="Set the output directory to DIR [Default: %default]")
    option('-r', "--redirect-stdout", action="store_true", default=False,
        help="Redirect stdout (& stderr, without -e) to file")
    option('-e', "--redirect-stderr", action="store_true", default=False,
        help="Redirect stderr to file")
    option("--silent-redirect", action="store_true", default=False,
        help="Suppress printing a message when redirecting stdout or stderr")
    option("--stdout-file", metavar="FILE", default="simout",
        help="Filename for -r redirection [Default: %default]")
    option("--stderr-file", metavar="FILE", default="simerr",
        help="Filename for -e redirection [Default: %default]")
    option("--listener-mode", metavar="{on,off,auto}",
        choices=listener_modes, default="auto",
        help="Port (e.g., gdb) listener mode (auto: Enable if running " \
        "interactively) [Default: %default]")
    option("--allow-remote-connections", action="store_true", default=False,
        help="Port listeners will accept connections from anywhere (0.0.0.0). "
        "Default is only localhost.")
    option('-i', "--interactive", action="store_true", default=False,
        help="Invoke the interactive interpreter after running the script")
    option("--pdb", action="store_true", default=False,
        help="Invoke the python debugger before running the script")
    option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
        help="Prepend PATH to the system path when invoking the script")
    option('-q', "--quiet", action="count", default=0,
        help="Reduce verbosity")
    option('-v', "--verbose", action="count", default=0,
        help="Increase verbosity")

    # Statistics options
    group("Statistics Options")
    option("--stats-file", metavar="FILE", default="stats.txt",
        help="Sets the output file for statistics [Default: %default]")
    option("--stats-help",
           action="callback", callback=_stats_help,
           help="Display documentation for available stat visitors")

    # Configuration Options
    group("Configuration Options")
    option("--dump-config", metavar="FILE", default="config.ini",
        help="Dump configuration output file [Default: %default]")
    option("--json-config", metavar="FILE", default="config.json",
        help="Create JSON output of the configuration [Default: %default]")
    option("--dot-config", metavar="FILE", default="config.dot",
        help="Create DOT & pdf outputs of the configuration [Default: %default]")
    option("--dot-dvfs-config", metavar="FILE", default=None,
        help="Create DOT & pdf outputs of the DVFS configuration" + \
             " [Default: %default]")

    # Debugging options
    group("Debugging Options")
    option("--debug-break", metavar="TICK[,TICK]", action='append', split=',',
        help="Create breakpoint(s) at TICK(s) " \
             "(kills process if no debugger attached)")
    option("--debug-help", action='store_true',
        help="Print help on debug flags")
    option("--debug-flags", metavar="FLAG[,FLAG]", action='append', split=',',
        help="Sets the flags for debug output (-FLAG disables a flag)")
    option("--debug-start", metavar="TICK", type='int',
        help="Start debug output at TICK")
    option("--debug-end", metavar="TICK", type='int',
        help="End debug output at TICK")
    option("--debug-file", metavar="FILE", default="cout",
        help="Sets the output file for debug. Append '.gz' to the name for it"
              " to be compressed automatically [Default: %default]")
    option("--debug-ignore", metavar="EXPR", action='append', split=':',
        help="Ignore EXPR sim objects")
    option("--remote-gdb-port", type='int', default=7000,
        help="Remote gdb base port (set to 0 to disable listening)")

    # Help options
    group("Help Options")
    option("--list-sim-objects", action='store_true', default=False,
        help="List all built-in SimObjects, their params and default values")

    arguments = options.parse_args()
    return options,arguments

def interact(scope):
    banner = "gem5 Interactive Console"

    ipshell = None
    prompt_in1 = "gem5 \\#> "
    prompt_out = "gem5 \\#: "

    try:
        import IPython
        from IPython.config.loader import Config
        from IPython.terminal.embed import InteractiveShellEmbed

        cfg = Config()
        cfg.PromptManager.in_template = prompt_in1
        cfg.PromptManager.out_template = prompt_out
        ipshell = InteractiveShellEmbed(config=cfg, user_ns=scope,
                                        banner1=banner)
    except ImportError:
        pass

    if ipshell:
        ipshell()
    else:
        # Use the Python shell in the standard library if IPython
        # isn't available.
        code.InteractiveConsole(scope).interact(banner)


def _check_tracing():
    import _m5.core

    if _m5.core.TRACING_ON:
        return

    fatal("Tracing is not enabled.  Compile with TRACING_ON")

def main():
    import m5
    import _m5.core

    from . import core
    from . import debug
    from . import defines
    from . import event
    from . import info
    from . import stats
    from . import trace

    from .util import inform, fatal, panic, isInteractive
    from m5.util.terminal_formatter import TerminalFormatter

    options, arguments = parse_options()

    m5.options = options

    # Set the main event queue for the main thread.
    event.mainq = event.getEventQueue(0)
    event.setEventQueue(event.mainq)

    if not os.path.isdir(options.outdir):
        os.makedirs(options.outdir)

    # These filenames are used only if the redirect_std* options are set
    stdout_file = os.path.join(options.outdir, options.stdout_file)
    stderr_file = os.path.join(options.outdir, options.stderr_file)

    if not options.silent_redirect:
        # Print redirection notices here before doing any redirection
        if options.redirect_stdout and not options.redirect_stderr:
            print("Redirecting stdout and stderr to", stdout_file)
        else:
            if options.redirect_stdout:
                print("Redirecting stdout to", stdout_file)
            if options.redirect_stderr:
                print("Redirecting stderr to", stderr_file)

    # Now redirect stdout/stderr as desired
    if options.redirect_stdout:
        redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
        os.dup2(redir_fd, sys.stdout.fileno())
        if not options.redirect_stderr:
            os.dup2(redir_fd, sys.stderr.fileno())

    if options.redirect_stderr:
        redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC)
        os.dup2(redir_fd, sys.stderr.fileno())

    done = False

    if options.build_info:
        done = True
        print('Build information:')
        print()
        print('gem5 version %s' % defines.gem5Version)
        print('compiled %s' % defines.compileDate)
        print('build options:')
        keys = list(defines.buildEnv.keys())
        keys.sort()
        for key in keys:
            val = defines.buildEnv[key]
            print('    %s = %s' % (key, val))
        print()

    if options.copyright:
        done = True
        print(info.COPYING)
        print()

    if options.readme:
        done = True
        print('Readme:')
        print()
        print(info.README)
        print()

    if options.debug_help:
        done = True
        _check_tracing()
        debug.help()

    if options.list_sim_objects:
        from . import SimObject
        done = True
        print("SimObjects:")
        objects = list(SimObject.allClasses.keys())
        objects.sort()
        terminal_formatter = TerminalFormatter()
        for name in objects:
            obj = SimObject.allClasses[name]
            print(terminal_formatter.format_output(str(obj), indent=4))
            params = list(obj._params.keys())
            params.sort()
            for pname in params:
                param = obj._params[pname]
                default = getattr(param, 'default', '')
                print(terminal_formatter.format_output(pname, indent=8))
                if default:
                    print(terminal_formatter.format_output(
                        str(default), label="default: ", indent=21))
                print(terminal_formatter.format_output(
                    param.desc, label="desc: ", indent=21))
                print()
            print()

    if done:
        sys.exit(0)

    # setting verbose and quiet at the same time doesn't make sense
    if options.verbose > 0 and options.quiet > 0:
        options.usage(2)

    verbose = options.verbose - options.quiet
    if verbose >= 0:
        print("gem5 Simulator System.  https://www.gem5.org")
        print(brief_copyright)
        print()

        print("gem5 version %s" % _m5.core.gem5Version)
        print("gem5 compiled %s" % _m5.core.compileDate)

        print("gem5 started %s" %
              datetime.datetime.now().strftime("%b %e %Y %X"))
        print("gem5 executing on %s, pid %d" %
              (socket.gethostname(), os.getpid()))

        # in Python 3 pipes.quote() is moved to shlex.quote()
        import pipes
        print("command line:", " ".join(map(pipes.quote, sys.argv)))
        print()

    # check to make sure we can find the listed script
    if not arguments or not os.path.isfile(arguments[0]):
        if arguments and not os.path.isfile(arguments[0]):
            print("Script %s not found" % arguments[0])

        options.usage(2)

    # tell C++ about output directory
    core.setOutputDir(options.outdir)

    # update the system path with elements from the -p option
    sys.path[0:0] = options.path

    # set stats options
    stats.addStatVisitor(options.stats_file)

    # Disable listeners unless running interactively or explicitly
    # enabled
    if options.listener_mode == "off":
        m5.disableAllListeners()
    elif options.listener_mode == "auto":
        if not isInteractive():
            inform("Standard input is not a terminal, disabling listeners.")
            m5.disableAllListeners()
    elif options.listener_mode == "on":
        pass
    else:
        panic("Unhandled listener mode: %s" % options.listener_mode)

    if not options.allow_remote_connections:
        m5.listenersLoopbackOnly()

    # set debugging options
    debug.setRemoteGDBPort(options.remote_gdb_port)
    for when in options.debug_break:
        debug.schedBreak(int(when))

    if options.debug_flags:
        _check_tracing()

        on_flags = []
        off_flags = []
        for flag in options.debug_flags:
            off = False
            if flag.startswith('-'):
                flag = flag[1:]
                off = True

            if flag not in debug.flags:
                print("invalid debug flag '%s'" % flag, file=sys.stderr)
                sys.exit(1)

            if off:
                debug.flags[flag].disable()
            else:
                debug.flags[flag].enable()

    if options.debug_start:
        _check_tracing()
        e = event.create(trace.enable, event.Event.Debug_Enable_Pri)
        event.mainq.schedule(e, options.debug_start)
    else:
        trace.enable()

    if options.debug_end:
        _check_tracing()
        e = event.create(trace.disable, event.Event.Debug_Enable_Pri)
        event.mainq.schedule(e, options.debug_end)

    trace.output(options.debug_file)

    for ignore in options.debug_ignore:
        _check_tracing()
        trace.ignore(ignore)

    sys.argv = arguments
    sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path

    filename = sys.argv[0]
    filedata = open(filename, 'r').read()
    filecode = compile(filedata, filename, 'exec')
    scope = { '__file__' : filename,
              '__name__' : '__m5_main__' }

    # if pdb was requested, execfile the thing under pdb, otherwise,
    # just do the execfile normally
    if options.pdb:
        import pdb
        import traceback

        pdb = pdb.Pdb()
        try:
            pdb.run(filecode, scope)
        except SystemExit:
            print("The program exited via sys.exit(). Exit status: ", end=' ')
            print(sys.exc_info()[1])
        except:
            traceback.print_exc()
            print("Uncaught exception. Entering post mortem debugging")
            t = sys.exc_info()[2]
            while t.tb_next is not None:
                t = t.tb_next
                pdb.interaction(t.tb_frame,t)
    else:
        exec(filecode, scope)

    # once the script is done
    if options.interactive:
        interact(scope)
