# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import os
import logging

from edalize.edatool import Edatool

logger = logging.getLogger(__name__)


class Vcs(Edatool):

    _description = """ Synopsys VCS Backend

VCS is one of the "Big 3" simulators.

Example snippet of a CAPI2 description file for VCS:

.. code:: yaml

   vcs:
     vcs_options:
       # Compile-time options passed to the vcs command
       - -debug_access+pp
       - -debug_access+all
     run_options:
       # Run-time options passed to the simulation itself
       - -licqueue
"""

    tool_options = {
        "lists": {
            "vcs_options": "String",  # compile-time options (passed to VCS)
            "run_options": "String",  # runtime options (passed to simulation)
        }
    }

    argtypes = ["plusarg", "vlogdefine", "vlogparam"]

    def _filelist_has_filetype(self, file_list, string, match_type="prefix"):
        for f in file_list:
            if match_type == "prefix" and f.file_type.startswith(string):
                return True
            elif match_type == "exact" and f.file_type == string:
                return True
        return False

    def configure_main(self):
        def _vcs_filelist_filter(src_file):
            ft = src_file.file_type
            # XXX: C source files can be passed to VCS to be compiled into DPI
            # libraries; passing C sources together with RTL sources is a
            # workaround until we have proper DPI support
            # (https://github.com/olofk/fusesoc/issues/311).
            return (
                ft.startswith("verilogSource")
                or ft.startswith("systemVerilogSource")
                or ft == "cSource"
                or ft == "cppSource"
            )

        self._write_fileset_to_f_file(
            os.path.join(self.work_root, self.name + ".scr"),
            include_vlogparams=True,
            filter_func=_vcs_filelist_filter,
        )

        plusargs = []
        if self.plusarg:
            for key, value in self.plusarg.items():
                plusarg = "+" + key
                if value != True:
                    plusarg += "=" + self._param_value_str(value)
                plusargs.append(plusarg)

        vcs_options = self.tool_options.get("vcs_options", [])

        (src_files, incdirs) = self._get_fileset_files(force_slash=True)
        if self._filelist_has_filetype(src_files, "systemVerilog", match_type="prefix"):
            vcs_options.append("-sverilog")

        if self._filelist_has_filetype(src_files, "verilog2001", match_type="exact"):
            vcs_options.append("+v2k")

        template_vars = {
            "name": self.name,
            "vcs_options": vcs_options,
            "run_options": self.tool_options.get("run_options", []),
            "toplevel": self.toplevel,
            "plusargs": plusargs,
        }

        self.render_template("Makefile.j2", "Makefile", template_vars)

    def run_main(self):
        args = ["run"]

        # Set plusargs
        if self.plusarg:
            plusargs = []
            for key, value in self.plusarg.items():
                plusargs += ["+{}={}".format(key, self._param_value_str(value))]
            args.append("EXTRA_OPTIONS=" + " ".join(plusargs))

        self._run_tool("make", args)
