# Copyright (c) 2021 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from abc import ABCMeta, abstractmethod

from .mem_mode import MemMode, mem_mode_to_string

from m5.objects import (
    System,
    Port,
    IOXBar,
    ClockDomain,
    SrcClockDomain,
    VoltageDomain,
)

from typing import List, final


class AbstractBoard(System):
    """The abstract board interface.

    Boards are used as the object which can connect together all other
    components. This abstract class defines the external interface that other
    boards must provide. Boards can be specialized for different ISAs or system
    designs (e.g., core counts, cache types, memory channels, I/O devices, etc)

    In addition to providing the place that system components are connected,
    the board also exposes an interface for the caches, processor, and memory
    to interact.

    The board also exposes an interface to set up I/O devices which needs to be
    specialized for each ISA and/or platform.

    Board inherits from System and can therefore be used as a System simobject
    when required.
    """

    __metaclass__ = ABCMeta

    def __init__(
        self,
        clk_freq: str,
        processor: "AbstractProcessor",
        memory: "AbstractMemory",
        cache_hierarchy: "AbstractCacheHierarchy",
    ) -> None:
        super().__init__()
        """
        :param clk_freq: The clock frequency for this board.
        :param processor: The processor for this board.
        :param memory: The memory for this board.
        :param cache_hierarchy: The Cachie Hierarchy for this board.
        """

        # Set up the clock domain and the voltage domain.
        self.clk_domain = SrcClockDomain()
        self.clk_domain.clock = clk_freq
        self.clk_domain.voltage_domain = VoltageDomain()

        # Set the processor, memory, and cache hierarchy.
        self.processor = processor
        self.memory = memory
        self.cache_hierarchy = cache_hierarchy

        # Setup the board and memory system's memory ranges.
        self._setup_memory_ranges()

        # Setup board properties unique to the board being constructed.
        self._setup_board()

        # Connect the memory, processor, and cache hierarchy.
        self._connect_things()

    def get_processor(self) -> "AbstractProcessor":
        """Get the processor connected to the board.

        :returns: The processor.
        """
        return self.processor

    def get_memory(self) -> "AbstractMemory":
        """Get the memory (RAM) connected to the board.

        :returns: The memory system.
        """
        return self.memory

    def get_cache_hierarchy(self) -> "AbstractCacheHierarchy":
        """Get the cache hierarchy connected to the board.

        :returns: The cache hierarchy.
        """
        return self.cache_hierarchy

    def get_cache_line_size(self) -> int:
        """Get the size of the cache line.

        :returns: The size of the cache line size.
        """
        return self.cache_line_size

    def connect_system_port(self, port: Port) -> None:
        self.system_port = port

    def set_mem_mode(self, mem_mode: MemMode) -> None:
        """
        Set the memory mode of the board.

        :param mem_mode: The memory mode the board is to be set to.
        """
        self.mem_mode = mem_mode_to_string(mem_mode=mem_mode)

    def get_clock_domain(self) -> ClockDomain:
        """Get the clock domain.
        :returns: The clock domain.
        """
        return self.clk_domain

    @abstractmethod
    def _setup_board(self) -> None:
        """
        This function is called in the AbstractBoard constructor, before the
        memory, processor, and cache hierarchy components are incorporated via
        `_connect_thing()`, but after the `_setup_memory_ranges()` function.
        This function should be overridden by boards to specify components,
        connections unique to that board.
        """
        raise NotImplementedError

    # Technically `get_dma_ports` returns a list. This list could be empty to
    # indicate the presense of dma ports. Though I quite like having this
    # boolean to quickly check a board.
    @abstractmethod
    def has_dma_ports(self) -> bool:
        """Determine whether the board has DMA ports or not.

        :returns: True if the board has DMA ports, otherwise False.
        """
        raise NotImplementedError

    @abstractmethod
    def get_dma_ports(self) -> List[Port]:
        """Get the board's Direct Memory Access ports.
        This abstract method must be implemented within the subclasses if they
        support DMA and/or full system simulation.

        :returns: A List of the Direct Memory Access ports.

        """
        raise NotImplementedError

    @abstractmethod
    def has_io_bus(self) -> bool:
        """Determine whether the board has an IO bus or not.

        :returns: True if the board has an IO bus, otherwise False.
        """
        raise NotImplementedError

    @abstractmethod
    def get_io_bus(self) -> IOXBar:
        """Get the board's IO Bus.
        This abstract method must be implemented within the subclasses if they
        support DMA and/or full system simulation.

        The I/O bus is a non-coherent bus (in the classic caches). On the CPU
        side, it accepts requests meant for I/O devices. On the memory side, it
        forwards these requests to the devices (e.g., the interrupt
        controllers on each core).

        :returns: The I/O Bus.
        """
        raise NotImplementedError

    @abstractmethod
    def has_coherent_io(self) -> bool:
        """Determine whether the board needs coherent I/O

        :returns: True if the board needs coherent I/O, false otherwise
        """
        raise NotImplementedError

    @abstractmethod
    def get_mem_side_coherent_io_port(self):
        """Get the memory-side coherent I/O port.
        This abstract method must be implemented if has_coherent_io is true.

        This returns a *port* (not a bus) that should be connected to a
        CPU-side port for which coherent I/O (DMA) is issued.
        """
        raise NotImplementedError

    @abstractmethod
    def _setup_memory_ranges(self) -> None:
        """
        Set the memory ranges for this board and memory system.

        This is called in the constructor, prior to `_setup_board` and
        `_connect_things`. It should query the board's memory to determine the
        size and the set the memory ranges on the memory system and on the
        board.

        The simplest implementation sets the board's memory range to the size
        of memory and memory system's range to be the same as the board. Full
        system implementations will likely need something more complicated.

        Notes
        -----
        * This *must* be called prior to the incorporation of the cache
        hierarchy (via `_connect_things`) as cache hierarchies depend upon
        knowing the memory system's ranges.
        """
        raise NotImplementedError

    @final
    def _connect_things(self) -> None:
        """Connects all the components to the board.

        The order of this board is always:

        1. Connect the memory.
        2. Connect the cache hierarchy.
        3. Connect the processor.

        Developers may build upon this assumption when creating components.

        Notes
        -----

        * The processor is incorporated after the cache hierarchy due to a bug
        noted here: https://gem5.atlassian.net/browse/GEM5-1113. Until this
        bug is fixed, this ordering must be maintained.
        """

        # Incorporate the memory into the motherboard.
        self.get_memory().incorporate_memory(self)

        # Incorporate the cache hierarchy for the motherboard.
        self.get_cache_hierarchy().incorporate_cache(self)

        # Incorporate the processor into the motherboard.
        self.get_processor().incorporate_processor(self)
