# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import os
import re
import shutil
import subprocess
import sys

import yaml
from mako.template import Template

try:
    from yaml import CSafeLoader as YamlLoader, CSafeDumper as YamlDumper
except ImportError:
    from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper


def _split_vlnv(core_vlnv):
    (vendor, library, name, version) = core_vlnv.split(':', 4)
    return {
        'vendor': vendor,
        'library': library,
        'name': name,
        'version': version
    }


def _prim_cores(cores, prim_name=None):
    """ Get all cores of primitives found by fusesoc

    If prim_name is given, only primitives with the given name are returned.
    Otherwise, all primitives are returned, independent of their name.
    """
    def _filter_primitives(core):
        """ Filter a list of cores to find the primitives we're interested in

        Matching cores follow the pattern
        "lowrisc:prim_<TECHLIB_NAME>:<PRIM_NAME>", where "<TECHLIB_NAME>" and
        "<PRIM_NAME>" are placeholders.
        """

        vlnv = _split_vlnv(core[0])
        if (vlnv['vendor'] == 'lowrisc' and
                vlnv['library'].startswith('prim_') and
            (prim_name is None or vlnv['name'] == prim_name)):
            return core
        return None

    return dict(filter(_filter_primitives, cores.items()))


def _techlibs(prim_cores):
    techlibs = set()
    for name, info in prim_cores.items():
        vlnv = _split_vlnv(name)
        techlibs.add(_library_to_techlib_name(vlnv['library']))
    return techlibs


def _library_to_techlib_name(library):
    return library[len("prim_"):]


def _core_info_for_techlib(prim_cores, techlib):
    for name, info in prim_cores.items():
        vlnv = _split_vlnv(name)
        if _library_to_techlib_name(vlnv['library']) == techlib:
            return (name, info)


def _enum_name_for_techlib(techlib_name, qualified=True):
    name = "Impl" + techlib_name.capitalize()
    if qualified:
        name = "prim_pkg::" + name
    return name


def _top_module_file(core_files, module_name):
    module_filename = module_name + '.sv'
    for file in core_files:
        if os.path.basename(file) == module_filename:
            return file


def _parse_module_header(generic_impl_filepath, module_name):
    """ Parse a SystemVerilog file to extract the 'module' header

    Return a dict with the following entries:
    - module_header: the whole module header (including the 'module' keyword)
    - package_import_declaration: import declarations
    - parameter_port_list: parameter/localparam declarations in the header
    - ports: the list of ports. The portlist can be ANSI or non-ANSI style (with
      or without signal declarations; see the SV spec for details).
    """

    # TODO: Evaluate different Python SV parsers and use one instead of this
    # beautiful regex. A more complete parser would ignore comments, for
    # example, or properly handle matching parentheses ... Or write a minimal
    # parser that can parse the module header.
    #
    # Initial evaluations:
    # - https://github.com/PyHDI/Pyverilog:
    #   requires Icarus and Python 3.6
    # - https://kevinpt.github.io/hdlparse/:
    #   Didn't do anything in my tests.
    # - https://github.com/sepandhaghighi/verilogparser:
    #   Doesn't support SystemVerilog

    # Grammar fragments from the SV2017 spec:
    #
    # module_nonansi_header ::=
    #   { attribute_instance } module_keyword [ lifetime ] module_identifier
    #   { package_import_declaration } [ parameter_port_list ] list_of_ports ;
    # module_ansi_header ::=
    #   { attribute_instance } module_keyword [ lifetime ] module_identifier
    #   { package_import_declaration }1 [ parameter_port_list ] [ list_of_port_declarations ]
    # package_import_declaration ::=
    #   import package_import_item { , package_import_item } ;
    # package_import_item ::=
    #   package_identifier :: identifier
    #   | package_identifier :: *

    RE_MODULE_HEADER = (
        r'(?:\s|^)'
        r'(?P<module_header>'  # start: capture the whole module header
        r'module\s+'  # module_keyword
        r'(?:(?:static|automatic)\s+)?'  # lifetime (optional)
        + module_name +  # module_identifier
        r'\s*(?P<package_import_declaration>(?:import\s+[^;]+;)+)?'  # package_import_declaration (optional, skipped)
        r'\s*(?:#\s*\((?P<parameter_port_list>[^;]+)\))?'  # parameter_port_list (optional)
        r'\s*\(\s*(?P<ports>[^;]+)\s*\)'  # list_of_port_declarations or list_of_ports
        r'\s*;'  # trailing semicolon
        r')'  # end: capture the whole module header
    )

    data = ""
    with open(generic_impl_filepath, encoding="utf-8") as file:
        data = file.read()
    re_module_header = re.compile(RE_MODULE_HEADER, re.DOTALL)
    matches = re_module_header.search(data)
    if not matches:
        raise ValueError("Unable to extract module header from %s." %
                         (generic_impl_filepath, ))

    parameter_port_list = matches.group('parameter_port_list') or ''
    return {
        'module_header':
        matches.group('module_header').strip(),
        'package_import_declaration':
        matches.group('package_import_declaration') or '',
        'parameter_port_list':
        parameter_port_list,
        'ports':
        matches.group('ports').strip() or '',
        'parameters':
        _parse_parameter_port_list(parameter_port_list)
    }


def _parse_parameter_port_list(parameter_port_list):
    """ Parse a list of ports in a module header into individual parameters """

    # Grammar (SV2017):
    #
    # parameter_port_list ::=
    #     # ( list_of_param_assignments { , parameter_port_declaration } )
    #   | # ( parameter_port_declaration { , parameter_port_declaration } )
    #   | #( )
    # parameter_port_declaration ::=
    #   parameter_declaration
    #   | local_parameter_declaration
    #   | data_type list_of_param_assignments
    #   | type list_of_type_assignments

    # XXX: Not covering the complete grammar, e.g. `parameter x, y`
    RE_PARAMS = (
        r'parameter\s+'
        r'(?:[a-zA-Z0-9\]\[:\s\$]+\s+)?'  # type
        r'(?P<name>\w+)'  # name
        r'(?:\s*=\s*[^,;]+)'  # initial value
    )
    re_params = re.compile(RE_PARAMS)
    parameters = set()
    for m in re_params.finditer(parameter_port_list):
        parameters.add(m.group('name'))
    return parameters


def _check_gapi(gapi):
    if not 'cores' in gapi:
        print("Key 'cores' not found in GAPI structure. "
              "At least FuseSoC 1.11 is needed. "
              "Install a compatible version with "
              "'pip3 install --user -r python-requirements.txt'.")
        return False
    return True


def _generate_prim_pkg(gapi):
    all_prim_cores = _prim_cores(gapi['cores'])
    techlibs = _techlibs(all_prim_cores)

    techlib_enums = []

    # Insert the required generic library first to ensure it gets enum value 0
    techlib_enums.append(_enum_name_for_techlib('generic', qualified=False))

    for techlib in techlibs:
        if techlib == 'generic':
            # The generic implementation is required and handled separately.
            continue
        techlib_enums.append(_enum_name_for_techlib(techlib, qualified=False))

    # Render prim_pkg.sv file
    print("Creating prim_pkg.sv")
    prim_pkg_sv_tpl_filepath = os.path.join(os.path.dirname(__file__),
                                            'primgen', 'prim_pkg.sv.tpl')
    prim_pkg_sv_tpl = Template(filename=prim_pkg_sv_tpl_filepath)

    prim_pkg_sv = prim_pkg_sv_tpl.render(encoding="utf-8",
                                         techlib_enums=techlib_enums)
    with open('prim_pkg.sv', 'w') as f:
        f.write(prim_pkg_sv)

    # Copy prim_pkg.core (no changes needed)
    prim_pkg_core_src = os.path.join(os.path.dirname(__file__), 'primgen',
                                     'prim_pkg.core.tpl')
    prim_pkg_core_dest = 'prim_pkg.core'
    shutil.copyfile(prim_pkg_core_src, prim_pkg_core_dest)
    print("Core file written to %s." % (prim_pkg_core_dest, ))


def _instance_sv(prim_name, techlib, parameters):
    s = "prim_{techlib}_{prim_name} #(\n"
    s += ", ".join(".{p}({p})".format(p=p) for p in parameters)
    s += ") u_impl_{techlib} (\n" \
         "  .*\n" \
         ");\n"
    return s.format(prim_name=prim_name, techlib=techlib)


def _create_instances(prim_name, techlibs, parameters):
    """ Build SystemVerilog code instantiating primitives from the techlib """
    techlibs_wo_generic = [
        techlib for techlib in techlibs if techlib != 'generic'
    ]
    techlibs_generic_last = techlibs_wo_generic + ['generic']

    if not techlibs_wo_generic:
        # Don't output the if/else blocks if there no alternatives exist.
        # We still want the generate block to keep hierarchical path names
        # stable, even if more than one techlib is found.
        s = " if (1) begin : gen_generic\n"
        s += _instance_sv(prim_name, "generic", parameters) + "\n"
        s += "end"
        return s

    nr_techlibs = len(techlibs_generic_last)
    out = ""
    for pos, techlib in enumerate(techlibs_generic_last):
        is_first = pos == 0
        is_last = pos == nr_techlibs - 1

        s = ""
        if not is_first:
            s += "else "
        if not is_last:
            s += "if (Impl == {techlib_enum}) "

        # TODO: wildcard port lists are against our style guide, but it's safer
        # to let the synthesis tool figure out the connectivity than us trying
        # to parse the port list into individual signals.
        s += "begin : gen_{techlib}\n" + _instance_sv(prim_name, techlib,
                                                      parameters) + "end "

        out += s.format(prim_name=prim_name,
                        techlib=techlib,
                        techlib_enum=_enum_name_for_techlib(techlib))
    return out


def _generate_abstract_impl(gapi):
    prim_name = gapi['parameters']['prim_name']
    prim_cores = _prim_cores(gapi['cores'], prim_name)

    techlibs = _techlibs(prim_cores)

    if not 'generic' in techlibs:
        raise ValueError("Techlib generic is required, but not found for "
                         "primitive %s." % prim_name)
    print("Implementations for primitive %s: %s" %
          (prim_name, ', '.join(techlibs)))

    # Extract port list out of generic implementation
    generic_core = _core_info_for_techlib(prim_cores, 'generic')[1]
    generic_module_name = 'prim_generic_' + prim_name
    top_module_filename = _top_module_file(generic_core['files'],
                                           generic_module_name)
    top_module_file = os.path.join(generic_core['core_root'],
                                   top_module_filename)

    print("Inspecting generic module %s" % (top_module_file, ))
    generic_hdr = _parse_module_header(top_module_file, generic_module_name)

    # Render abstract primitive HDL from template
    print("Creating SystemVerilog module for abstract primitive")
    abstract_prim_sv_tpl_filepath = os.path.join(os.path.dirname(__file__),
                                                 'primgen',
                                                 'abstract_prim.sv.tpl')
    abstract_prim_sv_tpl = Template(filename=abstract_prim_sv_tpl_filepath)

    abstract_prim_sv = abstract_prim_sv_tpl.render(
        encoding="utf-8",
        prim_name=prim_name,
        module_header_imports=generic_hdr['package_import_declaration'],
        module_header_params=generic_hdr['parameter_port_list'],
        module_header_ports=generic_hdr['ports'],
        # Creating the code to instantiate the primitives in the Mako templating
        # language is tricky to do; do it in Python instead.
        instances=_create_instances(prim_name, techlibs,
                                    generic_hdr['parameters']))
    abstract_prim_sv_filepath = 'prim_%s.sv' % (prim_name)
    with open(abstract_prim_sv_filepath, 'w') as f:
        f.write(abstract_prim_sv)
    print("Abstract primitive written to %s" %
          (os.path.abspath(abstract_prim_sv_filepath), ))

    # Create core file depending on all primitive implementations we have in the
    # techlibs.
    print("Creating core file for primitive %s." % (prim_name, ))
    abstract_prim_core_filepath = os.path.abspath('prim_%s.core' % (prim_name))
    dependencies = []
    dependencies.append('lowrisc:prim:prim_pkg')
    dependencies += [
        _core_info_for_techlib(prim_cores, t)[0] for t in techlibs
    ]
    abstract_prim_core = {
        'name': "lowrisc:prim_abstract:%s" % (prim_name, ),
        'filesets': {
            'files_rtl': {
                'depend': dependencies,
                'files': [
                    abstract_prim_sv_filepath,
                ],
                'file_type': 'systemVerilogSource'
            },
        },
        'targets': {
            'default': {
                'filesets': [
                    'files_rtl',
                ],
            },
        },
    }
    with open(abstract_prim_core_filepath, 'w') as f:
        # FuseSoC requires this line to appear first in the YAML file.
        # Inserting this line through the YAML serializer requires ordered dicts
        # to be used everywhere, which is annoying syntax-wise on Python <3.7,
        # where native dicts are not sorted.
        f.write('CAPI=2:\n')
        yaml.dump(abstract_prim_core,
                  f,
                  encoding="utf-8",
                  default_flow_style=False,
                  sort_keys=False)
    print("Core file written to %s" % (abstract_prim_core_filepath, ))


def _get_action_from_gapi(gapi, default_action):
    if 'parameters' in gapi and 'action' in gapi['parameters']:
        return gapi['parameters']['action']
    return default_action


def main():
    gapi_filepath = sys.argv[1]
    gapi = yaml.load(open(gapi_filepath), Loader=YamlLoader)

    if not _check_gapi(gapi):
        sys.exit(1)

    action = _get_action_from_gapi(gapi, 'generate_abstract_impl')

    if action == 'generate_abstract_impl':
        return _generate_abstract_impl(gapi)
    elif action == 'generate_prim_pkg':
        return _generate_prim_pkg(gapi)
    else:
        raise ValueError("Invalid action: %s" % (action, ))


if __name__ == '__main__':
    main()
