# 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_interrupts_define_render(self):
        return self._smc_c_define_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 _smc_c_define_render(self, enum):
        """ Add the c_helper CDefine rendering code for smc."""
        template = ("% for name, value, docstring in enum.constants:\n"
                    "#define ${name.as_c_define()} ${value} /**< ${docstring} */\n"
                    "% endfor\n")
        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
