# Copyright (c) 2021 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. Neither the name of the copyright holder 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 HOLDER 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.defines import buildEnv
from m5.objects import *
from m5.util import fatal

from example.gpufs.DisjointNetwork import *
from ruby.GPU_VIPER import *
from ruby import Ruby


class DummySystem():
    def __init__(self, mem_ranges):

        self.mem_ctrls = []
        self.mem_ranges = mem_ranges


class Disjoint_VIPER(RubySystem):
    def __init__(self):
        if buildEnv['PROTOCOL'] != "GPU_VIPER":
            fatal("This ruby config only supports the GPU_VIPER protocol")

        super(Disjoint_VIPER, self).__init__()

    def create(self, options, system, piobus, dma_devices):

        # Disjoint network topology
        if "garnet" in options.network:
            self.network_cpu = DisjointGarnet(self)
            self.network_gpu = DisjointGarnet(self)
        else:
            self.network_cpu = DisjointSimple(self)
            self.network_gpu = DisjointSimple(self)


        # Construct CPU controllers
        cpu_dir_nodes = \
            construct_dirs(options, system, self, self.network_cpu)
        (cp_sequencers, cp_cntrl_nodes) = \
            construct_corepairs(options, system, self, self.network_cpu)

        # Construct GPU controllers
        (tcp_sequencers, tcp_cntrl_nodes) = \
            construct_tcps(options, system, self, self.network_gpu)
        (sqc_sequencers, sqc_cntrl_nodes) = \
            construct_sqcs(options, system, self, self.network_gpu)
        (scalar_sequencers, scalar_cntrl_nodes) = \
            construct_scalars(options, system, self, self.network_gpu)
        tcc_cntrl_nodes = \
            construct_tccs(options, system, self, self.network_gpu)

        # Construct CPU memories
        Ruby.setup_memory_controllers(system, self, cpu_dir_nodes, options)

        # Construct GPU memories
        (gpu_dir_nodes, gpu_mem_ctrls) = \
            construct_gpudirs(options, system, self, self.network_gpu)

        # Configure the directories based on which network they are in
        for cpu_dir_node in cpu_dir_nodes:
            cpu_dir_node.CPUonly = True
            cpu_dir_node.GPUonly = False
        for gpu_dir_node in gpu_dir_nodes:
            gpu_dir_node.CPUonly = False
            gpu_dir_node.GPUonly = True

        # Set access backing store if specified
        if options.access_backing_store:
            self.access_backing_store = True

        # Assign the memory controllers to the system
        cpu_abstract_mems = []
        for mem_ctrl in system.mem_ctrls:
            cpu_abstract_mems.append(mem_ctrl.dram)
        system.memories = cpu_abstract_mems

        gpu_abstract_mems = []
        for mem_ctrl in gpu_mem_ctrls:
            gpu_abstract_mems.append(mem_ctrl.dram)
        system.pc.south_bridge.gpu.memories = gpu_abstract_mems

        # Setup DMA controllers
        gpu_dma_types = ["VegaPagetableWalker", "AMDGPUMemoryManager"]

        cpu_dma_ctrls = []
        gpu_dma_ctrls = []
        dma_cntrls = []
        for i, dma_device in enumerate(dma_devices):
            dma_seq = DMASequencer(version=i, ruby_system=self)
            dma_cntrl = DMA_Controller(version=i, dma_sequencer=dma_seq,
                                       ruby_system=self)

            # Handle inconsistently named ports on various DMA devices:
            if not hasattr(dma_device, 'type'):
                # IDE doesn't have a .type but seems like everything else does.
                dma_seq.in_ports = dma_device
            elif dma_device.type in gpu_dma_types:
                dma_seq.in_ports = dma_device.port
            else:
                dma_seq.in_ports = dma_device.dma

            if hasattr(dma_device, 'type') and \
                    dma_device.type in gpu_dma_types:
                dma_cntrl.requestToDir = MessageBuffer(buffer_size=0)
                dma_cntrl.requestToDir.out_port = self.network_gpu.in_port
                dma_cntrl.responseFromDir = MessageBuffer(buffer_size=0)
                dma_cntrl.responseFromDir.in_port = self.network_gpu.out_port
                dma_cntrl.mandatoryQueue = MessageBuffer(buffer_size = 0)

                gpu_dma_ctrls.append(dma_cntrl)
            else:
                dma_cntrl.requestToDir = MessageBuffer(buffer_size=0)
                dma_cntrl.requestToDir.out_port = self.network_cpu.in_port
                dma_cntrl.responseFromDir = MessageBuffer(buffer_size=0)
                dma_cntrl.responseFromDir.in_port = self.network_cpu.out_port
                dma_cntrl.mandatoryQueue = MessageBuffer(buffer_size = 0)

                cpu_dma_ctrls.append(dma_cntrl)

            dma_cntrls.append(dma_cntrl)

        system.dma_cntrls = dma_cntrls


        # Collect CPU and GPU controllers into seperate lists
        cpu_cntrls = cpu_dir_nodes + cp_cntrl_nodes + cpu_dma_ctrls
        gpu_cntrls = tcp_cntrl_nodes + sqc_cntrl_nodes + \
                scalar_cntrl_nodes + tcc_cntrl_nodes + gpu_dma_ctrls + \
                gpu_dir_nodes


        # Setup number of vnets
        self.number_of_virtual_networks = 11
        self.network_cpu.number_of_virtual_networks = 11
        self.network_gpu.number_of_virtual_networks = 11


        # Set up the disjoint topology
        self.network_cpu.connectCPU(options, cpu_cntrls)
        self.network_gpu.connectGPU(options, gpu_cntrls)


        # Create port proxy for connecting system port. System port is used
        # for loading from outside guest, e.g., binaries like vmlinux.
        system.sys_port_proxy = RubyPortProxy(ruby_system = self)
        system.sys_port_proxy.pio_request_port = piobus.cpu_side_ports
        system.system_port = system.sys_port_proxy.in_ports


        # Only CPU sequencers connect to PIO bus. This acts as the "default"
        # destination for unknown address ranges. PCIe requests fall under
        # this category.
        for i in range(len(cp_sequencers)):
            cp_sequencers[i].pio_request_port = piobus.cpu_side_ports
            cp_sequencers[i].mem_request_port = piobus.cpu_side_ports

            # The CorePairs in MOESI_AMD_Base round up when constructing
            # sequencers, but if the CPU does not exit there would be no
            # sequencer to send a range change, leading to assert.
            if i < options.num_cpus:
                cp_sequencers[i].pio_response_port = piobus.mem_side_ports


        # Setup ruby port. Both CPU and GPU are actually connected here.
        all_sequencers = cp_sequencers + tcp_sequencers + \
                         sqc_sequencers + scalar_sequencers
        self._cpu_ports = all_sequencers
        self.num_of_sequencers = len(all_sequencers)
