#!/usr/bin/env python3
"""Runs test within Spike, Qemu and Renode simulators."""
import argparse
import os
import re
import sys
import tempfile

import io
import pexpect


parser = argparse.ArgumentParser(
    description="Run a springbok test on an simulator.")

parser.add_argument("simulator",
                    help="Select a simulator",
                    choices=["renode", "qemu", "spike"])
parser.add_argument("elf",
                    help="Elf to execute on a simulator")
parser.add_argument("--renode-path",
                    help="Path to renode simulator")
parser.add_argument("--trace-output",
                    help="Path to trace output file")
parser.add_argument("--qemu-path",
                    help="Path to qemu simulator")
parser.add_argument("--spike-path",
                    help="Path to spike simulator")
parser.add_argument("--timeout", type=int,
                    help="Timeout for test", default=1000)
parser.add_argument("--quick_test",
                    help="allow quickest test time", action="store_true")

args = parser.parse_args()

class Simulation: # pylint: disable=too-few-public-methods
    """ Base class for simulation """
    def __init__(self, simulator_cmd):
        self.simulator_cmd = simulator_cmd
        self.buffer = io.StringIO()
        self.child = None
        self.termination_strings = [
            "main returned",
            "Exception occurred",
            "ReadByte from non existing peripheral",
        ]

    def run(self, timeout=1000):
        """ Run the simulation command and quit the simulation."""
        self.child = pexpect.spawn(self.simulator_cmd, encoding="utf-8")
        self.child.logfile = self.buffer
        self.child.expect(self.termination_strings, timeout=timeout)
        self.child.send("\nq\n")
        self.child.expect(pexpect.EOF, timeout=timeout)
        self.child.close()
        self.buffer.seek(0)
        return self.buffer.read()

class QemuSimulation(Simulation): # pylint: disable=too-few-public-methods
    """ Qemu simulation """
    def __init__(self, path, elf):
        self.qemu_simulator_cmd = (
            "%(sim)s -M springbok -nographic -d springbok -device loader,file=%(elf)s")
        self.sim_params = {"sim": path, "elf": elf}
        super().__init__(self.qemu_simulator_cmd % self.sim_params)


class RenodeSimulation(Simulation): # pylint: disable=too-few-public-methods
    """ Renode Simulation """
    def __init__(self, path, elf):
        # Get the ROOTDIR path if it exists
        self.rootdir = os.environ.get("ROOTDIR", default=None)
        if self.rootdir is None:
            parser.error("ROOTDIR environment variable not set.")
        renode_script = """
$bin=@%(elf)s
path set @%(rootdir)s
include @sim/config/springbok.resc"""

        if args.quick_test:
            renode_script += """
sysbus.cpu2 PerformanceInMips 2000
emulation SetGlobalQuantum "1" """

        if args.trace_output:
            renode_script += """
sysbus.cpu2 EnableExecutionTracing @%(trace_file)s PCAndOpcode """

        renode_script += """
start
sysbus.vec_controlblock WriteDoubleWord 0xc 0"""
        self.script_params = {
            "elf": os.path.realpath(elf),
            "rootdir": self.rootdir,
            "trace_file": os.path.realpath(args.trace_output) if args.trace_output else ""
        }
        self.renode_script = renode_script % self.script_params
        self.renode_args = [
            "%s" % path,
            "--disable-xwt",
            " --console",
            "--plain",
        ]
        self.renode_simulator_cmd = " ".join(self.renode_args)
        super().__init__(self.renode_simulator_cmd)

    def run(self, timeout=120):
        file_desc, script_path = tempfile.mkstemp(suffix=".resc")
        try:
            with os.fdopen(file_desc, "w") as tmp:
                tmp.write(self.renode_script)
                tmp.flush()
            self.simulator_cmd += " %s" % script_path
            test_output = super().run(timeout=timeout)
        finally:
            os.remove(script_path)
        return test_output

class SpikeSimulation(Simulation): # pylint: disable=too-few-public-methods
    """ Spike Simulation """
    def __init__(self, path, elf):
        self.sim_params = {
                "path": path,
                "elf": elf,
                "trace_file": os.path.realpath(args.trace_output) if args.trace_output else ""
                }
        self.spike_simulator_cmd = "%(path)s -m0x32000000:0x100000,0x34000000:0x1000000 --pc=0x32000000 "

        if args.trace_output:
            self.spike_simulator_cmd += " -l --log=%(trace_file)s "

        self.spike_simulator_cmd += " %(elf)s"
        super().__init__(self.spike_simulator_cmd % self.sim_params)

Simulators = {
    "qemu": QemuSimulation,
    "renode": RenodeSimulation,
    "spike": SpikeSimulation,
}

simulators_paths = {
    "renode": args.renode_path,
    "qemu": args.qemu_path,
    "spike": args.spike_path,
}


def main():
    """ Run a test and check for Pass or Fail """
    simulator_path = simulators_paths[args.simulator]
    if simulator_path is None:
        parser.error(
            "Must provide path to simulator %s, use argument --%s-path" % (args.simulator,
                                                                           args.simulator))

    simulator_class = Simulators[args.simulator]
    simulator = simulator_class(simulator_path, args.elf)
    output = simulator.run(timeout=args.timeout)
    # mono API generates escape characters at the termination. Need to clean up.
    # TODO(hcindyl): Remove this when Renode fix the mono call.
    ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
    output = ansi_escape.sub("", output)
    print(output)
    failure_strings = [
        "FAILED",
        "Exception occurred",
        "ReadByte from non existing peripheral"
    ]
    if any(x in output for x in failure_strings):
        sys.exit(1)
    # Grab the return code from the output string with regex
    # Syntax: "main returned: ", <code> (<hex_code>)
    return_string = re.compile(
        r"\"main returned:\s\",(?P<ret_code>\s[0-9]+\s*)")
    code = return_string.search(output)
    sys.exit(int(code.group(1)))


if __name__ == "__main__":
    main()
