# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""This contains a class which is used to help generate `top_{name}.h` and
`top_{name}.h`.
"""
from collections import OrderedDict

from mako.template import Template

from math import ceil


class Name(object):
    """We often need to format names in specific ways; this class does so."""
    def __add__(self, other):
        return Name(self.parts + other.parts)

    @staticmethod
    def from_snake_case(input):
        return Name(input.split("_"))

    def __init__(self, parts):
        self.parts = list(parts)
        for p in parts:
            assert len(p) > 0, "cannot add zero-length name piece"

    def as_snake_case(self):
        return "_".join([p.lower() for p in self.parts])

    def as_camel_case(self):
        out = ""
        for p in self.parts:
            # If we're about to join two parts which would introduce adjacent
            # numbers, put an underscore between them.
            if out[-1:].isnumeric() and p[:1].isnumeric():
                out += "_" + p
            else:
                out += p.capitalize()
        return out

    def as_c_define(self):
        return "_".join([p.upper() for p in self.parts])

    def as_c_enum(self):
        return "k" + self.as_camel_case()

    def as_c_type(self):
        return self.as_snake_case() + "_t"


class MemoryRegion(object):
    def __init__(self, name, base_addr, size_bytes):
        self.name = name
        self.base_addr = base_addr
        self.size_bytes = size_bytes
        self.size_words = ceil(int(str(size_bytes), 0) / 4)

    def base_addr_name(self):
        return self.name + Name(["base", "addr"])

    def offset_name(self):
        return self.name + Name(["offset"])

    def size_bytes_name(self):
        return self.name + Name(["size", "bytes"])

    def size_words_name(self):
        return self.name + Name(["size", "words"])


class CEnum(object):
    def __init__(self, name):
        self.name = name
        self.enum_counter = 0
        self.finalized = False

        self.constants = []

    def add_constant(self, constant_name, docstring=""):
        assert not self.finalized

        full_name = self.name + constant_name

        value = self.enum_counter
        self.enum_counter += 1

        self.constants.append((full_name, value, docstring))

        return full_name

    def add_last_constant(self, docstring=""):
        assert not self.finalized

        full_name = self.name + Name(["last"])

        _, last_val, _ = self.constants[-1]

        self.constants.append((full_name, last_val, r"\internal " + docstring))
        self.finalized = True

    def render(self):
        template = ("typedef enum ${enum.name.as_snake_case()} {\n"
                    "% for name, value, docstring in enum.constants:\n"
                    "  ${name.as_c_enum()} = ${value}, /**< ${docstring} */\n"
                    "% endfor\n"
                    "} ${enum.name.as_c_type()};")
        return Template(template).render(enum=self)


class CArrayMapping(object):
    def __init__(self, name, output_type_name):
        self.name = name
        self.output_type_name = output_type_name

        self.mapping = OrderedDict()

    def add_entry(self, in_name, out_name):
        self.mapping[in_name] = out_name

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

    def render_definition(self):
        template = (
            "const ${mapping.output_type_name.as_c_type()}\n"
            "    ${mapping.name.as_snake_case()}[${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)


class TopGenC(object):
    def __init__(self, top_info):
        self.top = top_info
        self._top_name = Name(["top"]) + Name.from_snake_case(top_info["name"])

        # The .c file needs the .h file's relative path, store it here
        self.header_path = None

        self._init_plic_targets()
        self._init_plic_mapping()
        self._init_alert_mapping()
        self._init_pinmux_mapping()
        self._init_pwrmgr_wakeups()
        self._init_rstmgr_sw_rsts()

    def modules(self):
        return [(m["name"],
                 MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
                              m["base_addr"], m["size"]))
                for m in self.top["module"]]

    def memories(self):
        return [(m["name"],
                 MemoryRegion(self._top_name + Name.from_snake_case(m["name"]),
                              m["base_addr"], m["size"]))
                for m in self.top["memory"]]

    def _init_plic_targets(self):
        enum = CEnum(self._top_name + Name(["plic", "target"]))

        for core_id in range(int(self.top["num_cores"])):
            enum.add_constant(Name(["ibex", str(core_id)]),
                              docstring="Ibex Core {}".format(core_id))

        enum.add_last_constant("Final PLIC target")

        self.plic_targets = enum

    def _init_plic_mapping(self):
        """We eventually want to generate a mapping from interrupt id to the
        source peripheral.

        In order to do so, we generate two enums (one for interrupts, one for
        sources), and store the generated names in a dictionary that represents
        the mapping.

        PLIC Interrupt ID 0 corresponds to no interrupt, and so no peripheral,
        so we encode that in the enum as "unknown".

        The interrupts have to be added in order, with "none" first, to ensure
        that they get the correct mapping to their PLIC id, which is used for
        addressing the right registers and bits.
        """
        sources = CEnum(self._top_name + Name(["plic", "peripheral"]))
        interrupts = CEnum(self._top_name + Name(["plic", "irq", "id"]))
        plic_mapping = CArrayMapping(
            self._top_name + Name(["plic", "interrupt", "for", "peripheral"]),
            sources.name)

        unknown_source = sources.add_constant(Name(["unknown"]),
                                              docstring="Unknown Peripheral")
        none_irq_id = interrupts.add_constant(Name(["none"]),
                                              docstring="No Interrupt")
        plic_mapping.add_entry(none_irq_id, unknown_source)

        # When we generate the `interrupts` enum, the only info we have about
        # the source is the module name. We'll use `source_name_map` to map a
        # short module name to the full name object used for the enum constant.
        source_name_map = {}

        for name in self.top["interrupt_module"]:
            source_name = sources.add_constant(Name.from_snake_case(name),
                                               docstring=name)
            source_name_map[name] = source_name

        sources.add_last_constant("Final PLIC peripheral")

        for intr in self.top["interrupt"]:
            # Some interrupts are multiple bits wide. Here we deal with that by
            # adding a bit-index suffix
            if "width" in intr and int(intr["width"]) != 1:
                for i in range(int(intr["width"])):
                    name = Name.from_snake_case(
                        intr["name"]) + Name([str(i)])
                    irq_id = interrupts.add_constant(name,
                                                     docstring="{} {}".format(
                                                         intr["name"], i))
                    source_name = source_name_map[intr["module_name"]]
                    plic_mapping.add_entry(irq_id, source_name)
            else:
                name = Name.from_snake_case(intr["name"])
                irq_id = interrupts.add_constant(name, docstring=intr["name"])
                source_name = source_name_map[intr["module_name"]]
                plic_mapping.add_entry(irq_id, source_name)

        interrupts.add_last_constant("The Last Valid Interrupt ID.")

        self.plic_sources = sources
        self.plic_interrupts = interrupts
        self.plic_mapping = plic_mapping

    def _init_alert_mapping(self):
        """We eventually want to generate a mapping from alert id to the source
        peripheral.

        In order to do so, we generate two enums (one for alerts, one for
        sources), and store the generated names in a dictionary that represents
        the mapping.

        Alert Handler has no concept of "no alert", unlike the PLIC.

        The alerts have to be added in order, to ensure that they get the
        correct mapping to their alert id, which is used for addressing the
        right registers and bits.
        """
        sources = CEnum(self._top_name + Name(["alert", "peripheral"]))
        alerts = CEnum(self._top_name + Name(["alert", "id"]))
        alert_mapping = CArrayMapping(
            self._top_name + Name(["alert", "for", "peripheral"]),
            sources.name)

        # When we generate the `alerts` enum, the only info we have about the
        # source is the module name. We'll use `source_name_map` to map a short
        # module name to the full name object used for the enum constant.
        source_name_map = {}

        for name in self.top["alert_module"]:
            source_name = sources.add_constant(Name.from_snake_case(name),
                                               docstring=name)
            source_name_map[name] = source_name

        sources.add_last_constant("Final Alert peripheral")

        for alert in self.top["alert"]:
            if "width" in alert and int(alert["width"]) != 1:
                for i in range(int(alert["width"])):
                    name = Name.from_snake_case(
                        alert["name"]) + Name([str(i)])
                    irq_id = alerts.add_constant(name, docstring="{} {}".format(
                                                         alert["name"], i))
                    source_name = source_name_map[alert["module_name"]]
                    alert_mapping.add_entry(irq_id, source_name)
            else:
                name = Name.from_snake_case(alert["name"])
                alert_id = alerts.add_constant(name, docstring=alert["name"])
                source_name = source_name_map[alert["module_name"]]
                alert_mapping.add_entry(alert_id, source_name)

        alerts.add_last_constant("The Last Valid Alert ID.")

        self.alert_sources = sources
        self.alert_alerts = alerts
        self.alert_mapping = alert_mapping

    def _init_pinmux_mapping(self):
        """Generate C enums for addressing pinmux registers and in/out selects.

        Inputs are connected in order: inouts, then inputs
        Outputs are connected in order: inouts, then outputs

        Inputs:
        - Peripheral chooses register field (pinmux_peripheral_in)
        - Insel chooses MIO input (pinmux_insel)

        Outputs:
        - MIO chooses register field (pinmux_mio_out)
        - Outsel chooses peripheral output (pinmux_outsel)

        Insel and outsel have some special values which are captured here too.
        """
        pinmux_info = self.top["pinmux"]

        # Peripheral Inputs
        peripheral_in = CEnum(self._top_name +
                              Name(["pinmux", "peripheral", "in"]))
        for signal in pinmux_info["inouts"] + pinmux_info["inputs"]:
            if "width" in signal and int(signal["width"]) != 1:
                for i in range(int(signal["width"])):
                    name = Name.from_snake_case(
                        signal["name"]) + Name([str(i)])
                    peripheral_in.add_constant(name,
                                               docstring="{} {}".format(
                                                   signal["name"], i))
            else:
                peripheral_in.add_constant(Name.from_snake_case(
                    signal["name"]),
                                           docstring=signal["name"])
        peripheral_in.add_last_constant("Last valid peripheral input")

        # Pinmux Input Selects
        insel = CEnum(self._top_name + Name(["pinmux", "insel"]))
        insel.add_constant(Name(["constant", "zero"]),
                           docstring="Tie constantly to zero")
        insel.add_constant(Name(["constant", "one"]),
                           docstring="Tie constantly to one")
        for i in range(int(pinmux_info["num_mio"])):
            insel.add_constant(Name(["mio", str(i)]),
                               docstring="MIO Pad {}".format(i))
        insel.add_last_constant("Last valid insel value")

        # MIO Outputs
        mio_out = CEnum(self._top_name + Name(["pinmux", "mio", "out"]))
        for i in range(int(pinmux_info["num_mio"])):
            mio_out.add_constant(Name([str(i)]),
                                 docstring="MIO Pad {}".format(i))
        mio_out.add_last_constant("Last valid mio output")

        # Pinmux Output Selects
        outsel = CEnum(self._top_name + Name(["pinmux", "outsel"]))
        outsel.add_constant(Name(["constant", "zero"]),
                            docstring="Tie constantly to zero")
        outsel.add_constant(Name(["constant", "one"]),
                            docstring="Tie constantly to one")
        outsel.add_constant(Name(["constant", "high", "z"]),
                            docstring="Tie constantly to high-Z")
        for signal in pinmux_info["inouts"] + pinmux_info["outputs"]:
            if "width" in signal and int(signal["width"]) != 1:
                for i in range(int(signal["width"])):
                    name = Name.from_snake_case(
                        signal["name"]) + Name([str(i)])
                    outsel.add_constant(name,
                                        docstring="{} {}".format(
                                            signal["name"], i))
            else:
                outsel.add_constant(Name.from_snake_case(signal["name"]),
                                    docstring=signal["name"])
        outsel.add_last_constant("Last valid outsel value")

        self.pinmux_peripheral_in = peripheral_in
        self.pinmux_insel = insel
        self.pinmux_mio_out = mio_out
        self.pinmux_outsel = outsel

    def _init_pwrmgr_wakeups(self):
        enum = CEnum(self._top_name + Name(["power", "manager", "wake", "ups"]))

        for signal in self.top["wakeups"]:
            enum.add_constant(Name.from_snake_case(signal["module"]) +
                              Name.from_snake_case(signal["name"]))

        enum.add_last_constant("Last valid pwrmgr wakeup signal")

        self.pwrmgr_wakeups = enum

    # Enumerates the positions of all software controllable resets
    def _init_rstmgr_sw_rsts(self):
        sw_rsts = [rst for rst in self.top["resets"]["nodes"] if 'sw' in rst
                   and rst['sw'] == 1]

        enum = CEnum(self._top_name + Name(["reset", "manager", "sw", "resets"]))

        for rst in sw_rsts:
            enum.add_constant(Name.from_snake_case(rst["name"]))

        enum.add_last_constant("Last valid rstmgr software reset request")

        self.rstmgr_sw_rsts = enum
