# Copyright 2022 Google.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
""" Utility functions for topgen
"""

import logging as log
import sys
from collections import OrderedDict
from mako.template import Template
from typing import Dict, Tuple

from reggen.ip_block import IpBlock
from topgen import lib as lib
from topgen.c import TopGenC
from topgen.c_test import TopGenCTest


class TopGenMatchaC(TopGenC):
    """ A class to add the Opentitan TopGenC with extra plic rendering methods.
    """

    def __init__(self, top_info, name_to_block: Dict[str, IpBlock]):
        super().__init__(top_info, name_to_block)
        # Update plic CEnum objects with appended smc suffix in the name
        # for the first and last elements to avoid naming collision.
        self.plic_sources.constants[0][0].parts.append("smc")
        self.plic_sources.constants[-1][0].parts.append("smc")
        self.plic_targets.constants[0][0].parts.append("smc")
        self.plic_targets.constants[-1][0].parts.append("smc")
        self.plic_interrupts.constants[0][0].parts.append("smc")
        self.plic_interrupts.constants[-1][0].parts.append("smc")

    def smc_plic_sources_render(self):
        return self._smc_c_enum_render(self.plic_sources)

    def smc_plic_targets_render(self):
        return self._smc_c_enum_render(self.plic_targets)

    def smc_plic_interrupts_render(self):
        return self._smc_c_enum_render(self.plic_interrupts)

    def smc_plic_mapping_render_declaration(self):
        template = (
            "extern const ${mapping.output_type_name.as_snake_case()}_smc_t\n"
            "    ${mapping.name.as_snake_case()}_smc[${len(mapping.mapping)}];")
        return Template(template).render(mapping=self.plic_mapping)

    def smc_plic_mapping_render_definition(self):
        template = (
            "const ${mapping.output_type_name.as_snake_case()}_smc_t\n"
            "    ${mapping.name.as_snake_case()}_smc[${len(mapping.mapping)}] = {\n"
            "% for in_name, out_name in mapping.mapping.items():\n"
            "  [${in_name.as_c_enum()}] = ${out_name.as_c_enum()},\n"
            "% endfor\n"
            "};\n")
        return Template(template).render(mapping=self.plic_mapping)

    def _smc_c_enum_render(self, enum):
        """ Add the c_helper CEnum rendering code for smc."""
        template = ("typedef enum ${enum.name.as_snake_case()}_smc {\n"
                    "% for name, value, docstring in enum.constants:\n"
                    "  ${name.as_c_enum()} = ${value}, /**< ${docstring} */\n"
                    "% endfor\n"
                    "} ${enum.name.as_snake_case()}_smc_t;")
        return Template(template).render(enum=enum)


def _separate_interrupt_modules(top: OrderedDict, name_to_block: Dict[str,
                                                                      IpBlock],
                                intr_to_smc_list: list):
    """Populate top["interrupt_module"] if necessary

    Do this by adding each module in top['modules'] that defines at least one
    interrupt.
    """
    if ("sec_interrupt_module" in top) or ("smc_interrupt_module" in top):
        return

    modules_sec = []
    modules_smc = []
    for module in top["module"]:
        block = name_to_block[module["type"]]
        if block.interrupts:
            if module["name"] in intr_to_smc_list:
                modules_smc.append(module["name"])
            else:
                modules_sec.append(module["name"])
    log.info("the genreate modules_sec is: ", modules_sec)
    top["sec_interrupt_module"] = modules_sec
    log.info("the genreate modules_smc is: ", modules_smc)
    top["smc_interrupt_module"] = modules_smc


def create_smc_c_helper(helper: TopGenCTest, topcfg: OrderedDict,
                        name_to_block: Dict[str, IpBlock]) -> TopGenCTest:
    """ Create the smc-specific c-code helper object.

    A workaround to append the smc-specific helper rendering functions in
    addition to the OpenTitan c_helper class.
    """
    smc_helper = TopGenMatchaC(topcfg, name_to_block)
    helper.smc_helper = smc_helper
    return helper


def create_separate_interrupt_topcfg(
    top: OrderedDict,) -> Tuple[OrderedDict, OrderedDict]:
    """ Create two topcfg dictionaries from separated interrupt groups.

    This is a workaround to use the Opentitan utility infrastructure to generate
    the c template helpers, which assumes one interrupt list at the top level.
    """
    interrupt_group = ["sec_interrupt", "smc_interrupt", "interrupt"]
    if not all(x in top for x in interrupt_group):
        log.error(
            f"Need to have 'sec_interrupt', 'smc_interrupt, 'interrupt' keys "
            f"in topcfg")
        sys.exit(1)
    sec_topcfg = top.copy()
    sec_topcfg["interrupt"] = sec_topcfg["sec_interrupt"]
    sec_topcfg["interrupt_module"] = sec_topcfg["sec_interrupt_module"]
    smc_topcfg = top.copy()
    smc_topcfg["num_cores"] = 1  # used to define plic targets.
    smc_topcfg["interrupt"] = smc_topcfg["smc_interrupt"]
    smc_topcfg["interrupt_module"] = smc_topcfg["smc_interrupt_module"]
    return sec_topcfg, smc_topcfg


def amend_separate_interrupt(top: OrderedDict, name_to_block: Dict[str,
                                                                   IpBlock],
                             intr_to_smc_list: list) -> OrderedDict:
    """Check interrupt_module if exists, or just use all modules
    """
    _separate_interrupt_modules(top, name_to_block, intr_to_smc_list)

    if "sec_interrupt" not in top or top["sec_interrupt"] == "":
        top["sec_interrupt"] = []

    if "smc_interrupt" not in top or top["smc_interrupt"] == "":
        top["smc_interrupt"] = []

    interrupt_module_list = [
        top["sec_interrupt_module"], top["smc_interrupt_module"]
    ]
    interrupt_list = [top["sec_interrupt"], top["smc_interrupt"]]
    for idx, l in enumerate(interrupt_module_list):
        for m in l:
            ips = list(filter(lambda module: module["name"] == m,
                              top["module"]))
            if len(ips) == 0:
                log.warning(
                    "Cannot find IP %s which is used in the interrupt_module" %
                    m)
                continue

            ip = ips[0]
            block = name_to_block[ip["type"]]

            log.info("Adding interrupts from module %s" % ip["name"])
            for signal in block.interrupts:
                sig_dict = signal.as_nwt_dict('interrupt')
                qual = lib.add_module_prefix_to_signal(sig_dict,
                                                       module=m.lower())
                interrupt_list[idx].append(qual)
    return top
