# Copyright (c) 2012-2013, 2017-2018, 2020 ARM Limited
# 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 abc import ABCMeta, abstractmethod
import argparse
import m5
from m5.objects import *
from m5.proxy import *
from common import FSConfig
from common import Options
from common.Caches import *
from ruby import Ruby

_have_kvm_support = 'BaseKvmCPU' in globals()

class BaseSystem(object, metaclass=ABCMeta):
    """Base system builder.

    This class provides some basic functionality for creating an ARM
    system with the usual peripherals (caches, GIC, etc.). It allows
    customization by defining separate methods for different parts of
    the initialization process.
    """

    def __init__(self, mem_mode='timing', mem_class=SimpleMemory,
                 cpu_class=TimingSimpleCPU, num_cpus=1, num_threads=1,
                 checker=False, mem_size=None, use_ruby=False):
        """Initialize a simple base system.

        Keyword Arguments:
          mem_mode -- String describing the memory mode (timing or atomic)
          mem_class -- Memory controller class to use
          cpu_class -- CPU class to use
          num_cpus -- Number of CPUs to instantiate
          checker -- Set to True to add checker CPUs
          mem_size -- Override the default memory size
          use_ruby -- Set to True to use ruby memory
        """
        self.mem_mode = mem_mode
        self.mem_class = mem_class
        self.cpu_class = cpu_class
        self.num_cpus = num_cpus
        self.num_threads = num_threads
        self.checker = checker
        self.use_ruby = use_ruby

    def create_cpus(self, cpu_clk_domain):
        """Return a list of CPU objects to add to a system."""
        cpus = [ self.cpu_class(clk_domain=cpu_clk_domain,
                                numThreads=self.num_threads,
                                cpu_id=i)
                 for i in range(self.num_cpus) ]
        if self.checker:
            for c in cpus:
                c.addCheckerCpu()
        return cpus

    def create_caches_private(self, cpu):
        """Add private caches to a CPU.

        Arguments:
          cpu -- CPU instance to work on.
        """
        cpu.addPrivateSplitL1Caches(L1_ICache(size='32kB', assoc=1),
                                    L1_DCache(size='32kB', assoc=4))

    def create_caches_shared(self, system):
        """Add shared caches to a system.

        Arguments:
          system -- System to work on.

        Returns:
          A bus that CPUs should use to connect to the shared cache.
        """
        system.toL2Bus = L2XBar(clk_domain=system.cpu_clk_domain)
        system.l2c = L2Cache(clk_domain=system.cpu_clk_domain,
                             size='4MB', assoc=8)
        system.l2c.cpu_side = system.toL2Bus.mem_side_ports
        system.l2c.mem_side = system.membus.cpu_side_ports
        return system.toL2Bus

    def init_cpu(self, system, cpu, sha_bus):
        """Initialize a CPU.

        Arguments:
          system -- System to work on.
          cpu -- CPU to initialize.
        """
        if not cpu.switched_out:
            self.create_caches_private(cpu)
            cpu.createInterruptController()
            cached_bus = sha_bus if sha_bus != None else system.membus
            cpu.connectAllPorts(cached_bus.cpu_side_ports,
                                system.membus.cpu_side_ports,
                                system.membus.mem_side_ports)

    def init_kvm_cpus(self, cpus):
        """
        Assign KVM CPUs to their own event queues / threads. This
        has to be done after creating caches and other child objects
        since these mustn't inherit the CPU event queue.

        Arguments:
          cpus -- List of cpus
        """
        if len(cpus) > 1:
            device_eq = 0
            first_cpu_eq = 1
            for idx, cpu in enumerate(cpus):
                # Child objects usually inherit the parent's event
                # queue. Override that and use the same event queue for
                # all devices.
                for obj in cpu.descendants():
                    obj.eventq_index = device_eq
                cpu.eventq_index = first_cpu_eq + idx

    def init_kvm(self, system):
        """Do KVM-specific system initialization.

        Arguments:
          system -- System to work on.
        """
        system.kvm_vm = KvmVM()

    def init_system(self, system):
        """Initialize a system.

        Arguments:
          system -- System to initialize.
        """
        self.create_clk_src(system)
        system.cpu = self.create_cpus(system.cpu_clk_domain)

        if self.use_ruby:
            # Add the ruby specific and protocol specific options
            parser = argparse.ArgumentParser()
            Options.addCommonOptions(parser)
            Ruby.define_options(parser)
            args, extra = parser.parse_known_args()

            # Set the default cache size and associativity to be very
            # small to encourage races between requests and writebacks.
            args.l1d_size="32kB"
            args.l1i_size="32kB"
            args.l2_size="4MB"
            args.l1d_assoc=4
            args.l1i_assoc=2
            args.l2_assoc=8
            args.num_cpus = self.num_cpus
            args.num_dirs = 2

            bootmem = getattr(system, '_bootmem', None)
            Ruby.create_system(args, True, system, system.iobus,
                               system._dma_ports, bootmem)

            # Create a seperate clock domain for Ruby
            system.ruby.clk_domain = SrcClockDomain(
                clock = args.ruby_clock,
                voltage_domain = system.voltage_domain)
            for i, cpu in enumerate(system.cpu):
                if not cpu.switched_out:
                    cpu.createInterruptController()
                    cpu.connectCachedPorts(system.ruby._cpu_ports[i].in_ports)
        else:
            sha_bus = self.create_caches_shared(system)
            for cpu in system.cpu:
                self.init_cpu(system, cpu, sha_bus)

        if _have_kvm_support and \
                any([isinstance(c, BaseKvmCPU) for c in system.cpu]):
            self.init_kvm(system)
            self.init_kvm_cpus(system.cpu)

    def create_clk_src(self,system):
        # Create system clock domain. This provides clock value to every
        # clocked object that lies beneath it unless explicitly overwritten
        # by a different clock domain.
        system.voltage_domain = VoltageDomain()
        system.clk_domain = SrcClockDomain(clock = '1GHz',
                                           voltage_domain =
                                           system.voltage_domain)

        # Create a seperate clock domain for components that should
        # run at CPUs frequency
        system.cpu_clk_domain = SrcClockDomain(clock = '2GHz',
                                               voltage_domain =
                                               system.voltage_domain)

    @abstractmethod
    def create_system(self):
        """Create an return an initialized system."""
        pass

    @abstractmethod
    def create_root(self):
        """Create and return a simulation root using the system
        defined by this class."""
        pass

class BaseSESystem(BaseSystem):
    """Basic syscall-emulation builder."""

    def __init__(self, **kwargs):
        super(BaseSESystem, self).__init__(**kwargs)

    def init_system(self, system):
        super(BaseSESystem, self).init_system(system)

    def create_system(self):
        if issubclass(self.mem_class, m5.objects.DRAMInterface):
            mem_ctrl = MemCtrl()
            mem_ctrl.dram = self.mem_class()
        else:
            mem_ctrl = self.mem_class()
        system = System(physmem = mem_ctrl,
                        membus = SystemXBar(),
                        mem_mode = self.mem_mode,
                        multi_thread = (self.num_threads > 1))
        if not self.use_ruby:
            system.system_port = system.membus.cpu_side_ports
        system.physmem.port = system.membus.mem_side_ports
        self.init_system(system)
        return system

    def create_root(self):
        system = self.create_system()
        m5.ticks.setGlobalFrequency('1THz')
        return Root(full_system=False, system=system)

class BaseSESystemUniprocessor(BaseSESystem):
    """Basic syscall-emulation builder for uniprocessor systems.

    Note: This class is only really needed to provide backwards
    compatibility in existing test cases.
    """

    def __init__(self, **kwargs):
        super(BaseSESystemUniprocessor, self).__init__(**kwargs)

    def create_caches_private(self, cpu):
        # The atomic SE configurations do not use caches
        if self.mem_mode == "timing":
            # @todo We might want to revisit these rather enthusiastic L1 sizes
            cpu.addTwoLevelCacheHierarchy(L1_ICache(size='128kB'),
                                          L1_DCache(size='256kB'),
                                          L2Cache(size='2MB'))

    def create_caches_shared(self, system):
        return None

class BaseFSSystem(BaseSystem):
    """Basic full system builder."""

    def __init__(self, **kwargs):
        super(BaseFSSystem, self).__init__(**kwargs)

    def init_system(self, system):
        super(BaseFSSystem, self).init_system(system)

        if self.use_ruby:
            # Connect the ruby io port to the PIO bus,
            # assuming that there is just one such port.
            system.iobus.mem_side_ports = system.ruby._io_port.in_ports
        else:
            # create the memory controllers and connect them, stick with
            # the physmem name to avoid bumping all the reference stats
            if issubclass(self.mem_class, m5.objects.DRAMInterface):
                mem_ctrls = []
                for r in system.mem_ranges:
                    mem_ctrl = MemCtrl()
                    mem_ctrl.dram = self.mem_class(range = r)
                    mem_ctrls.append(mem_ctrl)
                system.physmem = mem_ctrls
            else:
                system.physmem = [self.mem_class(range = r)
                                  for r in system.mem_ranges]
            for i in range(len(system.physmem)):
                system.physmem[i].port = system.membus.mem_side_ports

            # create the iocache, which by default runs at the system clock
            system.iocache = IOCache(addr_ranges=system.mem_ranges)
            system.iocache.cpu_side = system.iobus.mem_side_ports
            system.iocache.mem_side = system.membus.cpu_side_ports

    def create_root(self):
        system = self.create_system()
        m5.ticks.setGlobalFrequency('1THz')
        return Root(full_system=True, system=system)

class BaseFSSystemUniprocessor(BaseFSSystem):
    """Basic full system builder for uniprocessor systems.

    Note: This class is only really needed to provide backwards
    compatibility in existing test cases.
    """

    def __init__(self, **kwargs):
        super(BaseFSSystemUniprocessor, self).__init__(**kwargs)

    def create_caches_private(self, cpu):
        cpu.addTwoLevelCacheHierarchy(L1_ICache(size='32kB', assoc=1),
                                      L1_DCache(size='32kB', assoc=4),
                                      L2Cache(size='4MB', assoc=8))

    def create_caches_shared(self, system):
        return None

class BaseFSSwitcheroo(BaseFSSystem):
    """Uniprocessor system prepared for CPU switching"""

    def __init__(self, cpu_classes, **kwargs):
        super(BaseFSSwitcheroo, self).__init__(**kwargs)
        self.cpu_classes = tuple(cpu_classes)

    def create_cpus(self, cpu_clk_domain):
        cpus = [ cclass(clk_domain = cpu_clk_domain,
                        cpu_id=0,
                        switched_out=True)
                 for cclass in self.cpu_classes ]
        cpus[0].switched_out = False
        return cpus
