# 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.
#
# Authors: Gabe Black

from __future__ import print_function

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',
    '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]


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 = map(simgen_static, static_libs)
        shared_lib_nodes = 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)

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

lisa_protocol_types_header_path = 'include/lisa_protocol_types.h'
lisa_protocol_types_header_target = \
    gic_protocol_dest.File(lisa_protocol_types_header_path)
lisa_protocol_types_header_src = \
    examples_common_dir.File(lisa_protocol_types_header_path)
Command(lisa_protocol_types_header_target, lisa_protocol_types_header_src,
        Copy('${TARGET}', '${SOURCE}'))
