# Copyright (c) 2016-2017, 2019-2021 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.

# This is an example configuration script for full system simulation of
# a generic ARM bigLITTLE system.

import argparse
import os
import sys
import m5
import m5.util
from m5.objects import *

m5.util.addToPath("../../")

from common import FSConfig
from common import SysPaths
from common import ObjectList
from common import Options
from common.cores.arm import ex5_big, ex5_LITTLE

import devices
from devices import AtomicCluster, KvmCluster, FastmodelCluster


default_disk = "aarch64-ubuntu-trusty-headless.img"

default_mem_size = "2GB"


def _to_ticks(value):
    """Helper function to convert a latency from string format to Ticks"""

    return m5.ticks.fromSeconds(m5.util.convert.anyToLatency(value))


def _using_pdes(root):
    """Determine if the simulator is using multiple parallel event queues"""

    for obj in root.descendants():
        if (
            not m5.proxy.isproxy(obj.eventq_index)
            and obj.eventq_index != root.eventq_index
        ):
            return True

    return False


class BigCluster(devices.ArmCpuCluster):
    def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"):
        cpu_config = [
            ObjectList.cpu_list.get("O3_ARM_v7a_3"),
            devices.L1I,
            devices.L1D,
            devices.L2,
        ]
        super().__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)


class LittleCluster(devices.ArmCpuCluster):
    def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"):
        cpu_config = [
            ObjectList.cpu_list.get("MinorCPU"),
            devices.L1I,
            devices.L1D,
            devices.L2,
        ]
        super().__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)


class Ex5BigCluster(devices.CpuCluster):
    def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"):
        cpu_config = [
            ObjectList.cpu_list.get("ex5_big"),
            ex5_big.L1I,
            ex5_big.L1D,
            ex5_big.L2,
        ]
        super().__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)


class Ex5LittleCluster(devices.CpuCluster):
    def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"):
        cpu_config = [
            ObjectList.cpu_list.get("ex5_LITTLE"),
            ex5_LITTLE.L1I,
            ex5_LITTLE.L1D,
            ex5_LITTLE.L2,
        ]
        super().__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config)


def createSystem(
    caches,
    kernel,
    bootscript,
    machine_type="VExpress_GEM5",
    disks=[],
    mem_size=default_mem_size,
    bootloader=None,
):
    platform = ObjectList.platform_list.get(machine_type)
    m5.util.inform("Simulated platform: %s", platform.__name__)

    sys = devices.SimpleSystem(
        caches,
        mem_size,
        platform(),
        workload=ArmFsLinux(object_file=SysPaths.binary(kernel)),
        readfile=bootscript,
    )

    sys.mem_ctrls = [
        SimpleMemory(range=r, port=sys.membus.mem_side_ports)
        for r in sys.mem_ranges
    ]

    sys.connect()

    # Attach disk images
    if disks:

        def cow_disk(image_file):
            image = CowDiskImage()
            image.child.image_file = SysPaths.disk(image_file)
            return image

        sys.disk_images = [cow_disk(f) for f in disks]
        sys.pci_vio_block = [
            PciVirtIO(vio=VirtIOBlock(image=img)) for img in sys.disk_images
        ]
        for dev in sys.pci_vio_block:
            sys.attach_pci(dev)

    sys.realview.setupBootLoader(sys, SysPaths.binary, bootloader)

    return sys


cpu_types = {
    "atomic": (AtomicCluster, AtomicCluster),
    "timing": (BigCluster, LittleCluster),
    "exynos": (Ex5BigCluster, Ex5LittleCluster),
}

# Only add the KVM CPU if it has been compiled into gem5
if devices.have_kvm:
    cpu_types["kvm"] = (KvmCluster, KvmCluster)

# Only add the FastModel CPU if it has been compiled into gem5
if devices.have_fastmodel:
    cpu_types["fastmodel"] = (FastmodelCluster, FastmodelCluster)


def addOptions(parser):
    parser.add_argument(
        "--restore-from",
        type=str,
        default=None,
        help="Restore from checkpoint",
    )
    parser.add_argument(
        "--dtb", type=str, default=None, help="DTB file to load"
    )
    parser.add_argument(
        "--kernel", type=str, required=True, help="Linux kernel"
    )
    parser.add_argument(
        "--root",
        type=str,
        default="/dev/vda1",
        help="Specify the kernel CLI root= argument",
    )
    parser.add_argument(
        "--machine-type",
        type=str,
        choices=ObjectList.platform_list.get_names(),
        default="VExpress_GEM5",
        help="Hardware platform class",
    )
    parser.add_argument(
        "--disk",
        action="append",
        type=str,
        default=[],
        help="Disks to instantiate",
    )
    parser.add_argument(
        "--bootscript", type=str, default="", help="Linux bootscript"
    )
    parser.add_argument(
        "--cpu-type",
        type=str,
        choices=list(cpu_types.keys()),
        default="timing",
        help="CPU simulation mode. Default: %(default)s",
    )
    parser.add_argument(
        "--kernel-init", type=str, default="/sbin/init", help="Override init"
    )
    parser.add_argument(
        "--big-cpus",
        type=int,
        default=1,
        help="Number of big CPUs to instantiate",
    )
    parser.add_argument(
        "--little-cpus",
        type=int,
        default=1,
        help="Number of little CPUs to instantiate",
    )
    parser.add_argument(
        "--caches",
        action="store_true",
        default=False,
        help="Instantiate caches",
    )
    parser.add_argument(
        "--last-cache-level",
        type=int,
        default=2,
        help="Last level of caches (e.g. 3 for L3)",
    )
    parser.add_argument(
        "--big-cpu-clock",
        type=str,
        default="2GHz",
        help="Big CPU clock frequency",
    )
    parser.add_argument(
        "--little-cpu-clock",
        type=str,
        default="1GHz",
        help="Little CPU clock frequency",
    )
    parser.add_argument(
        "--sim-quantum",
        type=str,
        default="1ms",
        help="Simulation quantum for parallel simulation. "
        "Default: %(default)s",
    )
    parser.add_argument(
        "--mem-size",
        type=str,
        default=default_mem_size,
        help="System memory size",
    )
    parser.add_argument(
        "--kernel-cmd",
        type=str,
        default=None,
        help="Custom Linux kernel command",
    )
    parser.add_argument(
        "--bootloader",
        action="append",
        help="executable file that runs before the --kernel",
    )
    parser.add_argument(
        "--kvm-userspace-gic",
        action="store_true",
        default=False,
        help="Use the gem5 GIC in a KVM simulation",
    )
    parser.add_argument(
        "-P",
        "--param",
        action="append",
        default=[],
        help="Set a SimObject parameter relative to the root node. "
        "An extended Python multi range slicing syntax can be used "
        "for arrays. For example: "
        "'system.cpu[0,1,3:8:2].max_insts_all_threads = 42' "
        "sets max_insts_all_threads for cpus 0, 1, 3, 5 and 7 "
        "Direct parameters of the root object are not accessible, "
        "only parameters of its children.",
    )
    parser.add_argument(
        "--vio-9p", action="store_true", help=Options.vio_9p_help
    )
    parser.add_argument(
        "--dtb-gen",
        action="store_true",
        help="Doesn't run simulation, it generates a DTB only",
    )
    return parser


def build(options):
    m5.ticks.fixGlobalFrequency()

    kernel_cmd = [
        "earlyprintk",
        "earlycon=pl011,0x1c090000",
        "console=ttyAMA0",
        "lpj=19988480",
        "norandmaps",
        "loglevel=8",
        f"mem={options.mem_size}",
        f"root={options.root}",
        "rw",
        f"init={options.kernel_init}",
        "vmalloc=768MB",
    ]

    root = Root(full_system=True)

    disks = [default_disk] if len(options.disk) == 0 else options.disk
    system = createSystem(
        options.caches,
        options.kernel,
        options.bootscript,
        options.machine_type,
        disks=disks,
        mem_size=options.mem_size,
        bootloader=options.bootloader,
    )

    root.system = system
    if options.kernel_cmd:
        system.workload.command_line = options.kernel_cmd
    else:
        system.workload.command_line = " ".join(kernel_cmd)

    if options.big_cpus + options.little_cpus == 0:
        m5.util.panic("Empty CPU clusters")

    big_model, little_model = cpu_types[options.cpu_type]

    all_cpus = []
    # big cluster
    if options.big_cpus > 0:
        system.bigCluster = big_model(
            system, options.big_cpus, options.big_cpu_clock
        )
        system.mem_mode = system.bigCluster.memory_mode()
        all_cpus += system.bigCluster.cpus

    # little cluster
    if options.little_cpus > 0:
        system.littleCluster = little_model(
            system, options.little_cpus, options.little_cpu_clock
        )
        system.mem_mode = system.littleCluster.memory_mode()
        all_cpus += system.littleCluster.cpus

    # Figure out the memory mode
    if (
        options.big_cpus > 0
        and options.little_cpus > 0
        and system.bigCluster.memory_mode()
        != system.littleCluster.memory_mode()
    ):
        m5.util.panic("Memory mode missmatch among CPU clusters")

    # create caches
    system.addCaches(options.caches, options.last_cache_level)
    if not options.caches:
        if options.big_cpus > 0 and system.bigCluster.require_caches():
            m5.util.panic("Big CPU model requires caches")
        if options.little_cpus > 0 and system.littleCluster.require_caches():
            m5.util.panic("Little CPU model requires caches")

    # Create a KVM VM and do KVM-specific configuration
    if issubclass(big_model, KvmCluster):
        _build_kvm(options, system, all_cpus)

    # Linux device tree
    if options.dtb is not None:
        system.workload.dtb_filename = SysPaths.binary(options.dtb)
    else:
        system.workload.dtb_filename = os.path.join(
            m5.options.outdir, "system.dtb"
        )
        system.generateDtb(system.workload.dtb_filename)

    if devices.have_fastmodel and issubclass(big_model, FastmodelCluster):
        from m5 import arm_fast_model as fm, systemc as sc

        # setup FastModels for simulation
        fm.setup_simulation("cortexa76")
        # setup SystemC
        root.systemc_kernel = m5.objects.SystemC_Kernel()
        m5.tlm.tlm_global_quantum_instance().set(
            sc.sc_time(10000.0 / 100000000.0, sc.sc_time.SC_SEC)
        )

    if options.vio_9p:
        FSConfig.attach_9p(system.realview, system.iobus)

    return root


def _build_kvm(options, system, cpus):
    system.kvm_vm = KvmVM()
    system.release = ArmDefaultRelease.for_kvm()

    if options.kvm_userspace_gic:
        # We will use the simulated GIC.
        # In order to make it work we need to remove the system interface
        # of the generic timer from the DTB and we need to inform the
        # MuxingKvmGic class to use the gem5 GIC instead of relying on the
        # host interrupt controller
        GenericTimer.generateDeviceTree = SimObject.generateDeviceTree
        system.realview.gic.simulate_gic = True

    # 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.
    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 instantiate(options, checkpoint_dir=None):
    # Setup the simulation quantum if we are running in PDES-mode
    # (e.g., when using KVM)
    root = Root.getInstance()
    if root and _using_pdes(root):
        m5.util.inform(
            "Running in PDES mode with a %s simulation quantum.",
            options.sim_quantum,
        )
        root.sim_quantum = _to_ticks(options.sim_quantum)

    # Get and load from the chkpt or simpoint checkpoint
    if options.restore_from:
        if checkpoint_dir and not os.path.isabs(options.restore_from):
            cpt = os.path.join(checkpoint_dir, options.restore_from)
        else:
            cpt = options.restore_from

        m5.util.inform("Restoring from checkpoint %s", cpt)
        m5.instantiate(cpt)
    else:
        m5.instantiate()


def run(checkpoint_dir=m5.options.outdir):
    # start simulation (and drop checkpoints when requested)
    while True:
        event = m5.simulate()
        exit_msg = event.getCause()
        if exit_msg == "checkpoint":
            print("Dropping checkpoint at tick %d" % m5.curTick())
            cpt_dir = os.path.join(checkpoint_dir, "cpt.%d" % m5.curTick())
            m5.checkpoint(cpt_dir)
            print("Checkpoint done.")
        else:
            print(exit_msg, " @ ", m5.curTick())
            break

    sys.exit(event.getCode())


def generateDtb(root):
    root.system.generateDtb(os.path.join(m5.options.outdir, "system.dtb"))


def main():
    parser = argparse.ArgumentParser(
        description="Generic ARM big.LITTLE configuration"
    )
    addOptions(parser)
    options = parser.parse_args()
    root = build(options)
    root.apply_config(options.param)
    instantiate(options)
    if options.dtb_gen:
        generateDtb(root)
    else:
        run()


if __name__ == "__m5_main__":
    main()
