# Copyright (c) 2021 Huawei International
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# 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 m5.objects.Platform import Platform
from m5.objects.PMAChecker import PMAChecker
from m5.objects.Clint import Clint
from m5.objects.Plic import Plic
from m5.objects.RTC import RiscvRTC
from m5.objects.Uart import Uart8250
from m5.objects.Terminal import Terminal
from m5.params import *
from m5.proxy import *

class HiFive(Platform):
    """HiFive Platform

    Implementation:
        This is the base class for SiFive's HiFive
        board series. It contains the CLINT and PLIC
        interrupt controllers, Uart and Disk.

        Implementation details are based on SiFive
        FU540-C000. https://sifive.cdn.prismic.io/
        sifive/b5e7a29c-d3c2-44ea-85fb-acc1df282e2
        1_FU540-C000-v1p3.pdf

    Setup:
        The following sections outline the required
        setup for a RISC-V HiFive platform. See
        configs/example/riscv/fs_linux.py for example.

    Driving CLINT:
        CLINT has an interrupt pin which increments
        mtime. It can be connected to any interrupt
        source pin which acts as the RTCCLK pin. An
        abstract RTC wrapper called RiscvRTC can be
        used.

    Attaching PLIC devices:
        PLIC handles external interrupts. Interrupt
        PioDevices should inherit from PlicIntDevice
        (PCI and DMA not yet implemented). It contains
        a parameter interrupt_id which should be used
        to call platform->postPciInt(id).

        All PLIC interrupt devices should be returned
        by _off_chip_devices(). Calling attachPlic sets
        up the PLIC interrupt source count.

    Uart:
        The HiFive platform also has an uart_int_id.
        This is because Uart8250 uses postConsoleInt
        instead of postPciInt. In the future if a Uart
        that inherits PlicIntDevice is implemented,
        this can be removed.

    Disk:
        See fs_linux.py for setup example.

    PMAChecker:
        The PMAChecker will be attached to the MMU of
        each CPU (which allows them to differ). See
        fs_linux.py for setup example.
    """
    type = 'HiFive'
    cxx_header = "dev/riscv/hifive.hh"
    system = Param.System(Parent.any, "system")

    # CLINT
    clint = Param.Clint(Clint(pio_addr=0x2000000), "CLINT")

    # PLIC
    plic = Param.Plic(Plic(pio_addr=0xc000000), "PLIC")

    # Uart
    uart = Uart8250(pio_addr=0x10000000)
    # Int source ID to redirect console interrupts to
    # Set to 0 if using a pci interrupt for Uart instead
    uart_int_id = Param.Int(0xa, "PLIC Uart interrupt ID")
    terminal = Terminal()

    def _on_chip_devices(self):
        """Returns a list of on-chip peripherals
        """
        return [
            self.clint,
            self.plic
        ]

    def _off_chip_devices(self):
        """Returns a list of off-chip peripherals
        """
        devices = [self.uart]
        if hasattr(self, "disk"):
            devices.append(self.disk)
        return devices

    def _on_chip_ranges(self):
        """Returns a list of on-chip peripherals
            address range
        """
        return [
            AddrRange(dev.pio_addr, size=dev.pio_size)
            for dev in self._on_chip_devices()
        ]

    def _off_chip_ranges(self):
        """Returns a list of off-chip peripherals
            address range
        """
        return [
            AddrRange(dev.pio_addr, size=dev.pio_size)
            for dev in self._off_chip_devices()
        ]

    def attachPlic(self):
        """Count number of PLIC interrupt sources
        """
        plic_srcs = [self.uart_int_id]
        for device in self._off_chip_devices():
            if hasattr(device, "interrupt_id"):
                plic_srcs.append(device.interrupt_id)
        self.plic.n_src = max(plic_srcs) + 1

    def attachOnChipIO(self, bus):
        """Attach on-chip IO devices, needs modification
            to support DMA and PCI
        """
        for device in self._on_chip_devices():
            device.pio = bus.mem_side_ports

    def attachOffChipIO(self, bus):
        """Attach off-chip IO devices, needs modification
            to support DMA and PCI
        """
        for device in self._off_chip_devices():
            device.pio = bus.mem_side_ports
