# 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 itertools import cycle
import logging
import shlex

Import('*')

from grammar import Grammar

from gem5_scons import Transform, warning, error

import os.path

if env['CONF']['USE_ARM_FASTMODEL']:
    if env['CONF']['USE_SYSTEMC']:
        env.TagImplies('arm fastmodel', 'arm isa')
    else:
        warning('ARM Fast Models require systemc support')
        env['CONF']['USE_ARM_FASTMODEL'] = False


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

def extract_var(name):
    val = env['CONF'].get(name, None)
    if val is None:
        error(f'{name} is not set')
    if env['CONF']['USE_ARM_FASTMODEL']:
        print(f'{name} = {val}')
    # Make sure the value of this variable shows up as an environment variable
    # for commands scons runs.
    env['ENV'][name] = val
    return val

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)

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

simulation_engine_name = 'libMAXCOREInitSimulationEngine.3.so'
simulation_engine_lib = env.Command(
            Dir(env['BUILDDIR']).File(simulation_engine_name),
            pvlib_lib_dir.File(simulation_engine_name),
            MakeAction("cp ${SOURCE} ${TARGET}", Transform('COPY')))

arm_singleton_registry_name = 'arm_singleton_registry.so'
arm_singleton_registry_lib = env.Command(
            Dir(env['BUILDDIR']).File(arm_singleton_registry_name),
            pvlib_lib_dir.File(arm_singleton_registry_name),
            MakeAction("cp ${SOURCE} ${TARGET}", Transform('COPY')))


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)
    if env['CONF']['USE_ARM_FASTMODEL']:
        warning("Failed to find FM static lib: " + name)
    return name

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

env.Append(CCFLAGS='-pthread')

cpppaths = (
    pvlib_home.Dir('examples/SystemCExport/Common/include'),
    pvlib_home.Dir('include'),
    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)

# Per ARM's 11.16 release note, a platform build with simgen automatically
# copies libraries into the build target directory along with the other
# dependencies. Therefore, we only need to add each simgen result into rpath and
# no other shared librarires are required here.
fm_static_libs = (
    'components',
    'pvbus',
    'armctmodel',
    'fmruntime',
    'IrisSupport',
)
for lib in fm_static_libs:
    SourceLib(staticify(env, lib), tags='arm fastmodel')

SourceLib('atomic', tags='arm fastmodel')
SourceLib('dl', tags='arm fastmodel')
SourceLib('rt', tags='arm fastmodel')

class ProjectFileParser(Grammar):
    def __init__(self):
        self.log = logging.getLogger('fm_proj_ply')
        if GetOption('verbose'):
            self.log.setLevel(logging.DEBUG)

        self.yacc_kwargs['write_tables'] = False

        self.yacc_kwargs['debuglog'] = self.log
        self.yacc_kwargs['errorlog'] = self.log

        self.lex_kwargs['debuglog'] = self.log
        self.lex_kwargs['errorlog'] = self.log

    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().__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().__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]


# If fast model is disabled, ARMLMD_LICENSE_COUNT will be 0 which will break
# the cycle() iterator below. The fast model components won't be built, but
# they still need to be set up successfully with valid license slots.
license_count = max(int(env['CONF']['ARMLMD_LICENSE_COUNT']), 1)
arm_licenses = list((Value(object()) for i in range(license_count)))
license_cycle = cycle(arm_licenses)

# 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}'))
# Since we are copying the source files to a different directory, Scons's
# dependency scanner does not pick up the dependency between these files.
# Specify them manually.
env.Depends(gic_protocol_dest.File('gicv3_comms_base.h'),
            gic_protocol_dest.File('gicv3_comms_if.h'))
env.Depends(gic_protocol_dest.File('gicv3_comms_sockets.h'),
            gic_protocol_dest.File('gicv3_comms_if.h'))

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}'))

class ArmFastModelComponent(object):
    def __init__(self, project_file, *extra_deps, tags=None):
        if not tags:
            tags = ['arm fastmodel']
        self.tags = tags
        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]
        # Simgen also puts required share library under the project folder.
        self.rpaths = [simgen_dir, project_file_dir]
        self.log = gen_dir.File('build_%s.log' % tlc)
        self.simgen_cmd = env.subst('${CONF["SIMGEN"]} -p %s '
            '--configuration %s -b --verbose off --num-build-cpus %d '
            '--build-dir %s >%s') % \
            (shlex.quote(project_file.srcnode().abspath),
             shlex.quote(config_name),
             GetOption('num_jobs'),
             shlex.quote(simgen_dir.abspath),
             shlex.quote(self.log.abspath))

        sources = [project_file]
        sources.extend(extra_deps)
        # The simgen-generated .lisa files may #include these gicv3 files, but
        # SCons does not detect this dependency since they are generated files.
        # Add the dependencies manually.
        sources.extend([gic_protocol_dest.File('gicv3_comms_sockets.h'),
                        gic_protocol_dest.File('gicv3_comms_base.h')])
        env.Command(lib_nodes + self.headers + [self.log], sources,
                    Action(self.simgen_builder, Transform('SIMGEN')))
        # 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])

        # We need a copy of the simulation engine lib and arm_singleton_registry
        # (introduced in 11.16) alongside the executable.
        Depends(lib_nodes[0], simulation_engine_lib)
        Depends(lib_nodes[0], arm_singleton_registry_lib)

    def prepare_env(self, env):
        env.Append(LIBPATH=self.libpaths)
        env.AddLocalRPATH(*self.rpaths)
        env.Append(CPPPATH=self.headerpaths)
        # Put these libraries earlier in the list by setting priority.
        for lib in self.libs:
            SourceLib(lib, priority=1, tags=self.tags)

    def simgen_builder(self, target, source, env):
        cmd = self.simgen_cmd
        if not GetOption('verbose'):
            cmd = "@" + cmd
        res = env.Execute(cmd)
        # Print output when execution return non-zero or in verbose mode.
        if res or GetOption('verbose'):
            env.Execute('@cat %s' % self.log.abspath)
        return res


Export('ArmFastModelComponent')

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

SimObject('FastModel.py', sim_objects=[
    'AmbaToTlmBridge64', 'AmbaFromTlmBridge64'], tags='arm fastmodel')
Source('amba_to_tlm_bridge.cc', tags='arm fastmodel')
Source('amba_from_tlm_bridge.cc', tags='arm fastmodel')
