diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py new file mode 100644 index 000000000..3415fad8c --- /dev/null +++ b/configs/example/arm/devices.py @@ -0,0 +1,144 @@ +# Copyright (c) 2016 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. +# +# Authors: Andreas Sandberg +# Gabor Dozsa + +# System components used by the bigLITTLE.py configuration script + +import m5 +from m5.objects import * +m5.util.addToPath('../../common') +from Caches import * + +class L1I(L1_ICache): + hit_latency = 1 + response_latency = 1 + mshrs = 4 + tgts_per_mshr = 8 + size = '48kB' + assoc = 3 + + +class L1D(L1_DCache): + hit_latency = 2 + response_latency = 1 + mshrs = 16 + tgts_per_mshr = 16 + size = '32kB' + assoc = 2 + write_buffers = 16 + + +class WalkCache(PageTableWalkerCache): + hit_latency = 4 + response_latency = 4 + mshrs = 6 + tgts_per_mshr = 8 + size = '1kB' + assoc = 8 + write_buffers = 16 + + +class L2(L2Cache): + hit_latency = 12 + response_latency = 5 + mshrs = 32 + tgts_per_mshr = 8 + size = '1MB' + assoc = 16 + write_buffers = 8 + clusivity='mostly_excl' + + +class L3(Cache): + size = '16MB' + assoc = 16 + hit_latency = 20 + response_latency = 20 + mshrs = 20 + tgts_per_mshr = 12 + clusivity='mostly_excl' + + +class MemBus(SystemXBar): + badaddr_responder = BadAddr(warn_access="warn") + default = Self.badaddr_responder.pio + + +class SimpleSystem(LinuxArmSystem): + cache_line_size = 64 + + voltage_domain = VoltageDomain(voltage="1.0V") + clk_domain = SrcClockDomain(clock="1GHz", + voltage_domain=Parent.voltage_domain) + + realview = VExpress_GEM5_V1() + + gic_cpu_addr = realview.gic.cpu_addr + flags_addr = realview.realview_io.pio_addr + 0x30 + + membus = MemBus() + + intrctrl = IntrControl() + terminal = Terminal() + vncserver = VncServer() + + iobus = IOXBar() + # CPUs->PIO + iobridge = Bridge(delay='50ns') + # Device DMA -> MEM + dmabridge = Bridge(delay='50ns', ranges=realview._mem_regions) + + _pci_devices = 0 + _clusters = [] + _cpus = [] + + def attach_pci(self, dev): + dev.pci_bus, dev.pci_dev, dev.pci_func = (0, self._pci_devices + 1, 0) + self._pci_devices += 1 + self.realview.attachPciDevice(dev, self.iobus) + + def connect(self): + self.iobridge.master = self.iobus.slave + self.iobridge.slave = self.membus.master + + self.dmabridge.master = self.membus.slave + self.dmabridge.slave = self.iobus.master + + self.gic_cpu_addr = self.realview.gic.cpu_addr + self.realview.attachOnChipIO(self.membus, self.iobridge) + self.realview.attachIO(self.iobus) + self.system_port = self.membus.slave diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py new file mode 100644 index 000000000..ed71e15dd --- /dev/null +++ b/configs/example/arm/fs_bigLITTLE.py @@ -0,0 +1,308 @@ +# Copyright (c) 2016 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. +# +# Authors: Gabor Dozsa +# Andreas Sandberg + +# This is an example configuration script for full system simulation of +# a generic ARM bigLITTLE system. + + +import argparse +import os +import sys +import m5 +from m5.objects import * + +m5.util.addToPath("../../common") +import SysPaths +import CpuConfig + +import devices + + +default_dtb = 'armv8_gem5_v1_big_little_2_2.dtb' +default_kernel = 'vmlinux4.3.aarch64' +default_disk = 'aarch64-ubuntu-trusty-headless.img' +default_rcs = 'bootscript.rcS' + +default_mem_size= "2GB" + +def createSystem(kernel, mem_mode, bootscript, disks=[]): + sys = devices.SimpleSystem(kernel=SysPaths.binary(kernel), + readfile=bootscript, + mem_mode=mem_mode, + machine_type="DTOnly") + + mem_region = sys.realview._mem_regions[0] + sys.mem_ctrls = SimpleMemory( + range=AddrRange(start=mem_region[0], size=default_mem_size)) + sys.mem_ctrls.port = sys.membus.master + + 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.membus, sys, SysPaths.binary) + + return sys + + +class CpuCluster(SubSystem): + def addCPUs(self, cpu_config, num_cpus, cpu_clock, cpu_voltage="1.0V"): + try: + self._cluster_id + m5.util.panic("CpuCluster.addCPUs() must be called exactly once") + except AttributeError: + pass + + assert num_cpus > 0 + system = self._parent + self._cluster_id = len(system._clusters) + system._clusters.append(self) + self._config = cpu_config + + self.voltage_domain = VoltageDomain(voltage=cpu_voltage) + self.clk_domain = SrcClockDomain(clock=cpu_clock, + voltage_domain=self.voltage_domain) + + cpu_class = cpu_config['cpu'] + self.cpus = [ cpu_class(cpu_id=len(system._cpus) + idx, + clk_domain=self.clk_domain) + for idx in range(num_cpus) ] + + for cpu in self.cpus: + cpu.createThreads() + cpu.createInterruptController() + cpu.socket_id = self._cluster_id + system._cpus.append(cpu) + + def createCache(self, key): + try: + return self._config[key]() + except KeyError: + return None + + def addL1(self): + self._cluster_id + for cpu in self.cpus: + l1i = self.createCache('l1i') + l1d = self.createCache('l1d') + iwc = self.createCache('wcache') + dwc = self.createCache('wcache') + cpu.addPrivateSplitL1Caches(l1i, l1d, iwc, dwc) + + def addL2(self, clk_domain): + self._cluster_id + self.toL2Bus = L2XBar(width=64, clk_domain=clk_domain) + #self.toL2Bus = L2XBar(width=64, clk_domain=clk_domain, + #snoop_filter=NULL) + self.l2 = self._config['l2']() + for cpu in self.cpus: + cpu.connectAllPorts(self.toL2Bus) + self.toL2Bus.master = self.l2.cpu_side + + def connectMemSide(self, bus): + self._cluster_id + bus.slave + try: + self.l2.mem_side = bus.slave + except AttributeError: + for cpu in self.cpus: + cpu.connectAllPorts(bus) + + +def addCaches(system, last_cache_level): + cluster_mem_bus = system.membus + assert last_cache_level >= 1 and last_cache_level <= 3 + for cluster in system._clusters: + cluster.addL1() + if last_cache_level > 1: + for cluster in system._clusters: + cluster.addL2(cluster.clk_domain) + if last_cache_level > 2: + max_clock_cluster = max(system._clusters, + key=lambda c: c.clk_domain.clock[0]) + system.l3 = devices.L3(clk_domain=max_clock_cluster.clk_domain) + system.toL3Bus = L2XBar(width=64) + system.toL3Bus.master = system.l3.cpu_side + system.l3.mem_side = system.membus.slave + cluster_mem_bus = system.toL3Bus + + return cluster_mem_bus + + +def main(): + parser = argparse.ArgumentParser( + description="Generic ARM big.LITTLE configuration") + + parser.add_argument("--restore-from", type=str, default=None, + help="Restore from checkpoint") + parser.add_argument("--dtb", type=str, default=default_dtb, + help="DTB file to load") + parser.add_argument("--kernel", type=str, default=default_kernel, + help="Linux kernel") + parser.add_argument("--disk", action="append", type=str, default=[], + 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("--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") + + m5.ticks.fixGlobalFrequency() + + options = parser.parse_args() + + if options.atomic: + cpu_config = { 'cpu' : AtomicSimpleCPU } + big_cpu_config, little_cpu_config = cpu_config, cpu_config + else: + big_cpu_config = { 'cpu' : CpuConfig.get("arm_detailed"), + 'l1i' : devices.L1I, + 'l1d' : devices.L1D, + 'wcache' : devices.WalkCache, + 'l2' : devices.L2 } + little_cpu_config = { 'cpu' : MinorCPU, + 'l1i' : devices.L1I, + 'l1d' : devices.L1D, + 'wcache' : devices.WalkCache, + 'l2' : devices.L2 } + + big_cpu_class = big_cpu_config['cpu'] + little_cpu_class = little_cpu_config['cpu'] + + kernel_cmd = [ + "earlyprintk=pl011,0x1c090000", + "console=ttyAMA0", + "lpj=19988480", + "norandmaps", + "loglevel=8", + "mem=%s" % default_mem_size, + "root=/dev/vda1", + "rw", + "init=%s" % options.kernel_init, + "vmalloc=768MB", + ] + + root = Root(full_system=True) + + assert big_cpu_class.memory_mode() == little_cpu_class.memory_mode() + disks = default_disk if len(options.disk) == 0 else options.disk + system = createSystem(options.kernel, big_cpu_class.memory_mode(), + options.bootscript, disks=disks) + + root.system = system + system.boot_osflags = " ".join(kernel_cmd) + + # big cluster + if options.big_cpus > 0: + system.bigCluster = CpuCluster() + system.bigCluster.addCPUs(big_cpu_config, options.big_cpus, + options.big_cpu_clock) + + + # LITTLE cluster + if options.little_cpus > 0: + system.littleCluster = CpuCluster() + system.littleCluster.addCPUs(little_cpu_config, options.little_cpus, + options.little_cpu_clock) + + # add caches + if options.caches: + cluster_mem_bus = addCaches(system, options.last_cache_level) + else: + if big_cpu_class.require_caches(): + m5.util.panic("CPU model %s requires caches" % str(big_cpu_class)) + if little_cpu_class.require_caches(): + m5.util.panic("CPU model %s requires caches" % + str(little_cpu_class)) + cluster_mem_bus = system.membus + + # connect each cluster to the memory hierarchy + for cluster in system._clusters: + cluster.connectMemSide(cluster_mem_bus) + + # Linux device tree + system.dtb_filename = SysPaths.binary(options.dtb) + + # Get and load from the chkpt or simpoint checkpoint + if options.restore_from is not None: + m5.instantiate(options.restore_from) + else: + m5.instantiate() + + # 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(m5.options.outdir, "cpt.%d" % m5.curTick()) + m5.checkpoint(os.path.join(cpt_dir)) + print "Checkpoint done." + else: + print exit_msg, " @ ", m5.curTick() + break + + sys.exit(event.getCode()) + + +if __name__ == "__m5_main__": + main() diff --git a/system/arm/dt/Makefile b/system/arm/dt/Makefile index 425230868..62cf65f27 100644 --- a/system/arm/dt/Makefile +++ b/system/arm/dt/Makefile @@ -1,4 +1,4 @@ -# Copyright (c) 2015 ARM Limited +# Copyright (c) 2015-2016 ARM Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,7 +37,9 @@ TARGETS=\ armv7_gem5_v1_16cpu.dtb \ armv8_gem5_v1_1cpu.dtb armv8_gem5_v1_2cpu.dtb \ armv8_gem5_v1_4cpu.dtb armv8_gem5_v1_8cpu.dtb \ - armv8_gem5_v1_16cpu.dtb + armv8_gem5_v1_16cpu.dtb \ + armv8_gem5_v1_big_little_2_2.dtb \ + armv8_gem5_v1_big_little_2_4.dtb GEN_DTS=mkdir -p .gen; \ $(CPP) -x assembler-with-cpp \ @@ -54,6 +56,10 @@ all: $(TARGETS) .gen/armv8_gem5_v1_%cpu.dts: armv8.dts platforms/vexpress_gem5_v1.dtsi $(call GEN_DTS,vexpress_gem5_v1.dtsi,$*) +.gen/armv8_gem5_v1_big_little%.dts: armv8_big_little.dts \ + platforms/vexpress_gem5_v1.dtsi + $(call GEN_DTS,vexpress_gem5_v1.dtsi,$*) + %.dtb: .gen/%.dts $(DTC) -I dts -O dtb -o $@ $< diff --git a/system/arm/dt/armv8_big_little.dts b/system/arm/dt/armv8_big_little.dts new file mode 100644 index 000000000..70049bbc3 --- /dev/null +++ b/system/arm/dt/armv8_big_little.dts @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015-2016 ARM Limited + * All rights reserved + * + * 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. + * + * Authors: Andreas Sandberg + * Gabor Dozsa + */ + +/dts-v1/; + +/memreserve/ 0x80000000 0x00010000; + +#include CONF_PLATFORM + +/* Assign a unique ID for pre-defined configurations. The selected + * configuration is picked up from CONF_CPUS +*/ +// 2 big and 2 little cpus +#define _2_2 1 +// 2 big and 4 little cpus +#define _2_4 2 + +#define CPU(n,id) \ + CPU ## n: cpu@ ## id { \ + device_type = "cpu"; \ + compatible = "gem5,armv8", "arm,armv8"; \ + reg = < ## id >; \ + enable-method = "spin-table"; \ + cpu-release-addr = <0 0x8000fff8>; \ + }; + + +/ { + model = "V2P-AARCH64"; + compatible = "arm,vexpress,v2p-aarch64", "arm,vexpress"; + + memory@80000000 { + device_type = "memory"; + reg = <0 0x80000000 0x4 0x00000000>; + }; + + + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + #if CONF_CPUS == _2_2 + CPU(0,0x0) + CPU(1,0x1) + CPU(2,0x102) + CPU(3,0x103) + cpu-map { + cluster0 { + core0 { cpu = <&CPU0>; }; + core1 { cpu = <&CPU1>; }; + }; + cluster1 { + core0 { cpu = <&CPU2>; }; + core1 { cpu = <&CPU3>; }; + }; + }; + #elif CONF_CPUS == _2_4 + CPU(0,0x0) + CPU(1,0x1) + CPU(2,0x102) + CPU(3,0x103) + CPU(4,0x104) + CPU(5,0x105) + cpu-map { + cluster0 { + core0 { cpu = <&CPU0>; }; + core1 { cpu = <&CPU1>; }; + }; + cluster1 { + core0 { cpu = <&CPU2>; }; + core1 { cpu = <&CPU3>; }; + core2 { cpu = <&CPU4>; }; + core3 { cpu = <&CPU5>; }; + }; + }; + #else + #error Missing configuration section + #endif + }; + + virt-encoder { + compatible = "drm,virtual-encoder"; + port { + hdlcd0_virt_input: endpoint@0 { + remote-endpoint = <&hdlcd0_output>; + }; + }; + + display-timings { + native-mode = <&timing0>; + + timing0: timing_1080p60 { + /* 1920x1080-60 */ + clock-frequency = <148500000>; + hactive = <1920>; + vactive = <1080>; + hfront-porch = <148>; + hback-porch = <88>; + hsync-len = <44>; + vfront-porch = <36>; + vback-porch = <4>; + vsync-len = <5>; + }; + }; + }; +}; + +&hdlcd0 { + status = "ok"; + + port { + hdlcd0_output: endpoint@0 { + remote-endpoint = <&hdlcd0_virt_input>; + }; + }; +}; + +