# Copyright (c) 2020 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 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.

from __future__ import print_function
from itertools import cycle

Import('*')

from m5.util.grammar import Grammar

from gem5_scons import Transform, warning, error

import os.path

if env['USE_ARM_FASTMODEL']:
    if not env['USE_SYSTEMC']:
        warning('ARM Fast Models require systemc support')
        env['USE_ARM_FASTMODEL'] = False
        Return()

if not env['USE_ARM_FASTMODEL']:
    Return()


systemc_home = Dir('#/src/systemc/ext/systemc_home')
env['ENV']['SYSTEMC_HOME'] = systemc_home.abspath

def extract_var(name):
    if name not in env:
        error('Error: %s is not set' % name)
    print('%s = %s' % (name, env[name]))
    # Make sure the value of this variable shows up as an environment variable
    # for commands scons runs.
    env['ENV'][name] = env[name]
    return env[name]

pvlib_home, maxcore_home, armlmd_license_file = \
    list(map(extract_var, ('PVLIB_HOME', 'MAXCORE_HOME',
                           'ARMLMD_LICENSE_FILE')))

pvlib_home = Dir(pvlib_home)
maxcore_home = Dir(maxcore_home)
armlmd_license_file = File(armlmd_license_file)


pvlib_flavor = env['PVLIB_FLAVOR']
pvlib_lib_dir = pvlib_home.Dir('lib').Dir(pvlib_flavor)

simulation_engine_name = 'libMAXCOREInitSimulationEngine.3.so'
simulation_engine_lib = pvlib_lib_dir.File(simulation_engine_name)


def staticify(env, name):
    ''' Check for a static version of the library named 'name', and if it
        exists return a File node for it explicitly. Otherwise pass 'name'
        through for normal processing.'''

    static_name = env.subst('${LIBPREFIX}' + name + '${LIBSUFFIX}')

    for path in env.Flatten(env['LIBPATH']):
        full_name = Dir(path).File(static_name).get_abspath()
        if os.path.isfile(full_name):
            return File(full_name)

    return name


# Adjust the build environment to support building in Fast Models.

env.Append(CCFLAGS='-pthread')

cpppaths = (
    pvlib_home.Dir('include/fmruntime'),
    pvlib_home.Dir('include/fmruntime/eslapi'),
    pvlib_home.Dir('Iris/include'),

    systemc_home.Dir('include'),

    maxcore_home.Dir('AMBA-PV/include'),
)
env.Append(CPPPATH=cpppaths)

lib_paths = (
    pvlib_lib_dir,
    pvlib_home.Dir('Iris').Dir(pvlib_flavor),
)
env.Append(LIBPATH=lib_paths)
env.Append(RPATH=lib_paths)

libs = (
    'components',
    'pvbus',
    'armctmodel',
    'fmruntime',
    'IrisSupport',
    'atomic',
    'dl',
    'rt',
)
env.Append(LIBS=list(staticify(env, lib) for lib in libs))


class ProjectFileParser(Grammar):
    class Param(object):
        def __init__(self, is_object):
            self.is_object = is_object

        def __str__(self):
            return self._to_str(0)

    class StringParam(Param):
        def __init__(self, name, value):
            super(ProjectFileParser.StringParam, self).__init__(
                    is_object=False)
            self.name = name
            self.value = value

        def _to_str(self, indent):
            indent_str = "    " * indent
            return indent_str + self.name + ' = \"' + self.value + '\"'

    class ObjectParam(Param):
        def __init__(self, type_name, name, params):
            super(ProjectFileParser.ObjectParam, self).__init__(
                    is_object=True)
            self.type_name = type_name
            self.name = name
            self.params = params

        def _to_str(self, indent):
            indent_str = "    " * indent
            val = indent_str + self.type_name
            if self.name is not None:
                val += ' "' + self.name + '"'
            val += "\n" + indent_str + "{\n"
            for param in self.params:
                val += param._to_str(indent + 1) + "\n"
            val += indent_str + "}"
            return val

    #########
    # Lexer #
    #########

    tokens = (
        # identifier
        'ID',

        # string literal
        'STRLIT',

        # = { } ;
        'EQUALS',
        'LBRACE',
        'RBRACE',
        'SEMI',
    )

    t_ID = r'[A-Za-z_]\w*'

    def t_STRLIT(self, t):
        r'(?m)"([^"])*"'
        # strip off quotes
        t.value = t.value[1:-1]
        t.lexer.lineno += t.value.count('\n')
        return t

    t_EQUALS = r'='
    t_LBRACE = r'\{'
    t_RBRACE = r'\}'
    t_SEMI = r';'

    def t_NEWLINE(self, t):
        r'\n+'
        t.lexer.lineno += t.value.count('\n')

    t_ignore = ' \t\x0c'

    ##########
    # Parser #
    ##########

    def p_object(self, t):
        'object : object_heading LBRACE params RBRACE'
        t[0] = self.ObjectParam(t[1][0], t[1][1], t[3])

    def p_object_heading_0(self, t):
        'object_heading : ID STRLIT'
        t[0] = (t[1], t[2])

    def p_object_heading_1(self, t):
        'object_heading : ID'
        t[0] = (t[1], None)

    def p_params_0(self, t):
        'params : '
        t[0] = []

    def p_params_1(self, t):
        'params : param params'
        t[0] = [t[1]] + t[2]

    def p_param_0(self, t):
        'param : ID EQUALS STRLIT SEMI'
        t[0] = self.StringParam(t[1], t[3])

    def p_param_1(self, t):
        'param : object'
        t[0] = t[1]


license_count = int(env['ARMLMD_LICENSE_COUNT'])
arm_licenses = list((Value(i) for i in range(license_count)))
license_cycle = cycle(arm_licenses)

class ArmFastModelComponent(object):
    def __init__(self, project_file, *extra_deps):
        project_file = File(project_file)
        project_file_dir = project_file.Dir('.')

        parser = ProjectFileParser()
        proj = parser.parse_file(project_file.srcnode().abspath)

        # Top level component.
        tlc = None
        # Config name.
        config_name = None

        # Scan for particular properties of the project.
        for param in proj.params:
            if not param.is_object:
                if param.name == 'TOP_LEVEL_COMPONENT':
                    tlc = param.value
                elif param.name == 'ACTIVE_CONFIG_LINUX':
                    config_name = param.value

        assert tlc is not None and config_name is not None

        simgen_dir = project_file_dir.Dir(config_name)

        def simgen_static(name):
            return simgen_dir.File(env.subst(
                        '${LIBPREFIX}%s${LIBSUFFIX}' % name))

        def simgen_shared(name):
            return simgen_dir.File(env.subst(
                        '${SHLIBPREFIX}%s${SHLIBSUFFIX}' % name))

        static_libs = [
            'scx-%s-%s' % (tlc, config_name),
            'scx',
        ]
        shared_libs = [
            '%s-%s' % (tlc, config_name),
        ]

        static_lib_nodes = list(map(simgen_static, static_libs))
        shared_lib_nodes = list(map(simgen_shared, shared_libs))
        # We need to use the static libraries as files so that the linker
        # doesn't use the shared versions of them instead. We need to use
        # the shared libraries by name so that the linker will apply RPATH
        # and be able to find them at run time. If a shared libary includes
        # a path, the dynamic linker will apparently ignore RPATH when looking
        # for it.
        lib_nodes = static_lib_nodes + shared_lib_nodes

        gen_dir = simgen_dir.Dir('gen')

        header = gen_dir.File('scx_evs_%s.h' % tlc)

        self.headers = [header]
        self.headerpaths = [gen_dir]
        self.libs = static_lib_nodes + shared_libs
        self.libpaths = [simgen_dir]
        self.rpaths = [simgen_dir]

        simgen_cmd = env.subst('${SIMGEN} -p %s --configuration %s -b ' +
            '--verbose off --num-build-cpus 100 --build-dir %s') % \
            (project_file.srcnode().abspath, config_name, simgen_dir.abspath)
        if not GetOption('verbose'):
            simgen_cmd += ' > /dev/null'
        simgen_action = MakeAction(simgen_cmd, Transform('SIMGEN'))
        sources = [project_file]
        sources.extend(extra_deps)
        env.Command(lib_nodes + self.headers, sources, simgen_action)
        # Distribute simgen actions among ARM license slots. All actions which
        # have a given license as a "side effect" will be serialized relative
        # to each other, meaning the number of licenses being used concurrently
        # will never be larger than the number of license nodes.
        #
        # This allocation is fixed and may not be as optimal as a dynamic one,
        # but the difference is probably not significant.
        env.SideEffect(next(license_cycle), lib_nodes[0])

    def prepare_env(self, env):
        env.Append(LIBPATH=self.libpaths)
        env.AddLocalRPATH(*self.rpaths)
        env.Append(CPPPATH=self.headerpaths)
        env.Prepend(LIBS=self.libs)


class ArmFastModelBin(Executable):
    def __init__(self, target, *components_and_sources):
        def is_component(x):
            return isinstance(x, ArmFastModelComponent)

        def not_component(x):
            return not is_component(x)

        components = list(filter(is_component, components_and_sources))
        sources = list(filter(not_component, components_and_sources))

        self.components = components
        super(ArmFastModelBin, self).__init__(target, *sources)

    @classmethod
    def declare_all(cls, env):
        env = env.Clone()
        env.Prepend(LIBS=env['STATIC_LIB'][0])
        super(ArmFastModelBin, cls).declare_all(env)

    def declare(self, env):
        env = env.Clone()

        sources = list(self.sources)
        for f in self.filters:
            sources += Source.all.apply_filter(f)

        objs = self.srcs_to_objs(env, sources)
        objs = objs + env['MAIN_OBJS']

        for component in self.components:
            component.prepare_env(env)

        binary = super(ArmFastModelBin, self).declare(env, objs)[0]

        # We need a copy of the simulation engine lib alongside the executable
        # so that the license check works properly.
        local_engine = binary.File(simulation_engine_name)
        Depends(binary, local_engine)
        main.Command(local_engine, simulation_engine_lib,
                MakeAction("cp ${SOURCE} ${TARGET}", Transform('COPY')))

Export('ArmFastModelComponent')
Export('ArmFastModelBin')

PySource('m5', 'arm_fast_model.py')
Source('fastmodel.cc')

SimObject('FastModel.py')
Source('amba_to_tlm_bridge.cc')
Source('amba_from_tlm_bridge.cc')

# HACK: Make sure the gic protocol headers are somewhere we can find them.
# These should start out alongside other headers fast model provides which we
# are already able to include, but unfortunately they're in the examples
# directory.
gicv3_comms_headers = (
        'gicv3_comms_base.h', 'gicv3_comms_if.h', 'gicv3_comms_sockets.h')
examples_common_dir = pvlib_home.Dir('examples/SystemCExport/Common')
gic_protocol_path = 'Protocols/GICv3Comms'
gic_protocol_dest = Dir(env['BUILDDIR']).Dir(gic_protocol_path)
gic_protocol_src = examples_common_dir.Dir(gic_protocol_path)

for header in gicv3_comms_headers:
    Command(gic_protocol_dest.File(header), gic_protocol_src.File(header),
            Copy('${TARGET}', '${SOURCE}'))

common_headers = ('lisa_protocol_types.h', 'tlm_has_get_protocol_types.h')
for header in common_headers:
    header_target = gic_protocol_dest.Dir('include').File(header)
    header_src = examples_common_dir.Dir('include').File(header)
    Command(header_target, header_src, Copy('${TARGET}', '${SOURCE}'))
