diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index 7d3f383f3..f7375cd9a 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 ARM Limited +# Copyright (c) 2016-2017 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -44,6 +44,8 @@ m5.util.addToPath('../../') from common.Caches import * from common import CpuConfig +have_kvm = "kvm" in CpuConfig.cpu_names() + class L1I(L1_ICache): tag_latency = 1 data_latency = 1 @@ -170,6 +172,14 @@ class AtomicCluster(CpuCluster): def addL1(self): pass +class KvmCluster(CpuCluster): + def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): + cpu_config = [ CpuConfig.get("kvm"), None, None, None, None ] + super(KvmCluster, self).__init__(system, num_cpus, cpu_clock, + cpu_voltage, *cpu_config) + def addL1(self): + pass + class SimpleSystem(LinuxArmSystem): cache_line_size = 64 diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py index c2ecf8831..d6825dfaa 100644 --- a/configs/example/arm/fs_bigLITTLE.py +++ b/configs/example/arm/fs_bigLITTLE.py @@ -44,6 +44,7 @@ import argparse import os import sys import m5 +import m5.util from m5.objects import * m5.util.addToPath("../../") @@ -52,6 +53,7 @@ from common import SysPaths from common import CpuConfig import devices +from devices import AtomicCluster, KvmCluster default_dtb = 'armv8_gem5_v1_big_little_2_2.dtb' @@ -61,6 +63,21 @@ default_rcs = 'bootscript.rcS' 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.CpuCluster): def __init__(self, system, num_cpus, cpu_clock, @@ -107,6 +124,15 @@ def createSystem(caches, kernel, bootscript, disks=[]): return sys +cpu_types = { + "atomic" : (AtomicCluster, AtomicCluster), + "timing" : (BigCluster, LittleCluster), +} + +# Only add the KVM CPU if it has been compiled into gem5 +if devices.have_kvm: + cpu_types["kvm"] = (KvmCluster, KvmCluster) + def addOptions(parser): parser.add_argument("--restore-from", type=str, default=None, @@ -119,8 +145,9 @@ def addOptions(parser): help="Disks to instantiate") parser.add_argument("--bootscript", type=str, default=default_rcs, help="Linux bootscript") - parser.add_argument("--atomic", action="store_true", default=False, - help="Use atomic CPUs") + parser.add_argument("--cpu-type", type=str, choices=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, @@ -135,9 +162,11 @@ def addOptions(parser): 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") return parser - def build(options): m5.ticks.fixGlobalFrequency() @@ -165,35 +194,31 @@ def build(options): root.system = system system.boot_osflags = " ".join(kernel_cmd) - AtomicCluster = devices.AtomicCluster - 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: - if options.atomic: - system.bigCluster = AtomicCluster(system, options.big_cpus, - options.big_cpu_clock) - else: - system.bigCluster = BigCluster(system, options.big_cpus, - options.big_cpu_clock) - mem_mode = system.bigCluster.memoryMode() + system.bigCluster = big_model(system, options.big_cpus, + options.big_cpu_clock) + system.mem_mode = system.bigCluster.memoryMode() + all_cpus += system.bigCluster.cpus + # little cluster if options.little_cpus > 0: - if options.atomic: - system.littleCluster = AtomicCluster(system, options.little_cpus, - options.little_cpu_clock) + system.littleCluster = little_model(system, options.little_cpus, + options.little_cpu_clock) + system.mem_mode = system.littleCluster.memoryMode() + all_cpus += system.littleCluster.cpus - else: - system.littleCluster = LittleCluster(system, options.little_cpus, - options.little_cpu_clock) - mem_mode = system.littleCluster.memoryMode() + # Figure out the memory mode + if options.big_cpus > 0 and options.little_cpus > 0 and \ + system.littleCluster.memoryMode() != system.littleCluster.memoryMode(): + m5.util.panic("Memory mode missmatch among CPU clusters") - if options.big_cpus > 0 and options.little_cpus > 0: - if system.bigCluster.memoryMode() != system.littleCluster.memoryMode(): - m5.util.panic("Memory mode missmatch among CPU clusters") - system.mem_mode = mem_mode # create caches system.addCaches(options.caches, options.last_cache_level) @@ -203,13 +228,43 @@ def build(options): if options.little_cpus > 0 and system.littleCluster.requireCaches(): m5.util.panic("Little CPU model requires caches") + # Create a KVM VM and do KVM-specific configuration + if issubclass(big_model, KvmCluster): + _build_kvm(system, all_cpus) + # Linux device tree system.dtb_filename = SysPaths.binary(options.dtb) return root +def _build_kvm(system, cpus): + system.kvm_vm = KvmVM() + + # 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):