# Copyright 2019 Google, Inc.
#
# 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 logging
import os
import socket

from m5.defines import buildEnv
import _m5.arm_fast_model

ARM_LICENSE_ENV = "ARMLMD_LICENSE_FILE"
LM_LICENSE_ENV = "LM_LICENSE_FILE"


def set_armlmd_license_file(force=False):
    """Set the ARMLMD_LICENSE_FILE environment variable. If "force" is
    False, then it will only be set if it wasn't already set in the
    environment. The value it's set to is the one gem5 was built with.
    """
    license_file = buildEnv[ARM_LICENSE_ENV]
    if force or ARM_LICENSE_ENV not in os.environ:
        os.environ[ARM_LICENSE_ENV] = license_file


def check_armlmd_license(timeout):
    """Check if any of the provided license server can be reached, or
    if a license file is provided. This allows to fail early and fast,
    as fastmodel code makes multiple lengthy attempts to connect to
    license server. "timeout" is in seconds.
    """
    servers = os.environ[ARM_LICENSE_ENV].split(":")

    extras = list()
    # Add LM_LICENSE_ENV to the list, if set.
    if LM_LICENSE_ENV in os.environ and os.environ[LM_LICENSE_ENV]:
        extras += os.environ[LM_LICENSE_ENV].split(":")
    # Fastmodel appears to always add this file.
    extras.append("/opt/arm/licenses/license.dat")
    for extra in extras:
        if extra not in servers:
            servers.append(extra)

    for server in servers:
        if os.path.exists(server):
            logging.debug("License file %s exists." % server)
            break

        tuple = server.split("@")
        if len(tuple) != 2:
            # Probably not a server, and we know the file doesn't exist.
            logging.debug('License file "%s" does not exist.' % server)
            continue

        try:
            # Try to connect to license server. This doesn't attempt to
            # communicate with it, just checking reachability.
            s = socket.create_connection(
                (tuple[1], int(tuple[0])), timeout=timeout
            )
            s.close()
            logging.debug("License server %s is reachable." % server)
            break
        except Exception as e:
            logging.debug(
                "Cannot connect to license server %s (%s: %s)."
                % (server, type(e).__name__, e)
            )
    else:
        raise ConnectionError(
            "Cannot connect to any of the license servers (%s)."
            % ", ".join(servers)
        )


# These methods wrap much of the SystemC Export API described in section
# 7.6 of the Fast Models User Guide.


def scx_initialize(id):
    # Actually run scx_initialize.
    _m5.arm_fast_model.scx_initialize(id)


def scx_load_application(instance, application):
    _m5.arm_fast_model.scx_load_application(instance, application)


def scx_load_application_all(application):
    _m5.arm_fast_model.scx_load_application_all(application)


def scx_load_data(instance, data, address):
    _m5.arm_fast_model.scx_load_data(instance, data, address)


def scx_load_data_all(data, address):
    _m5.arm_fast_model.scx_load_data_all(data, address)


def scx_set_parameter(name, value):
    _m5.arm_fast_model.scx_set_parameter(name, value)


def scx_get_parameter(name):
    value = ""
    _m5.arm_fast_model.scx_get_parameter(name, value)
    return value


def scx_get_parameter_list():
    return _m5.arm_fast_model.scx_get_parameter_list()


def scx_set_cpi_file(cpi_file_path):
    _m5.arm_fast_model.scx_set_cpi_file(cpi_file_path)


def scx_cpulimit(t):
    _m5.arm_fast_model.scx_cpulimit(t)


def scx_timelimit(t):
    _m5.arm_fast_model.scx_timelimit(t)


def scx_simlimit(t):
    _m5.arm_fast_model.scx_simlimit(t)


def scx_parse_and_configure(self, argc, argv, trailer=None, sig_handler=True):
    _m5.arm_fast_model.scx_parse_and_configure(
        argc, argv, trailer, sig_handler
    )


def scx_start_cadi_server(start=True, run=True, debug=False):
    _m5.arm_fast_model.scx_start_cadi_server(start, run, debug)


def scx_enable_cadi_log(log=True):
    _m5.arm_fast_model.scx_enable_cadi_log(log)


def scx_prefix_appli_output(prefix=True):
    _m5.arm_fast_model.scx_prefix_appli_output(prefix)


def scx_print_port_number(print_=True):
    _m5.arm_fast_model.scx_print_port_number(print_)


def scx_print_statistics(print_=True):
    _m5.arm_fast_model.scx_print_statistics(print_)


def scx_load_plugin(file_):
    _m5.arm_fast_model.scx_load_plugin(file_)


def scx_sync(sync_time):
    _m5.arm_fast_model.scx_sync(sync_time)


def scx_set_min_sync_latency(latency):
    _m5.arm_fast_model.scx_set_min_sync_latency(latency)


def scx_get_min_sync_latency(arg=None):
    if arg:
        return _m5.arm_fast_model.scx_get_min_sync_latency(arg)
    else:
        return _m5.arm_fast_model.scx_get_min_sync_latency()


# This should be called once per simulation
def setup_simulation(
    sim_name,
    min_sync_latency=100.0 / 100000000,
    exit_on_dmi_warning=False,
    license_precheck=False,
    license_precheck_timeout=1,
):
    set_armlmd_license_file()
    if license_precheck:
        check_armlmd_license(license_precheck_timeout)
    scx_initialize(sim_name)
    scx_set_min_sync_latency(min_sync_latency)
    if exit_on_dmi_warning:
        _m5.arm_fast_model.gem5.enable_exit_on_dmi_warning_handler()
