diff --git a/scripts/run-gem5.sh b/scripts/run-gem5.sh new file mode 100755 index 00000000..902bdcc9 --- /dev/null +++ b/scripts/run-gem5.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# +# - needs to be called from within your build directory (i.e., $FAIL/build/) +# - expects 1 argument: path to experiment target (any location is possible) + +../simulators/gem5/build/ARM/gem5.debug ../simulators/gem5/configs/example/fail_fs.py --kernel "$1" diff --git a/simulators/gem5/configs/example/fail_fs.py b/simulators/gem5/configs/example/fail_fs.py new file mode 100644 index 00000000..443c4ef5 --- /dev/null +++ b/simulators/gem5/configs/example/fail_fs.py @@ -0,0 +1,185 @@ +# -------------------------------------------------------------- +# This script invokes the gem5 simulator. It is written to be used +# with the Fail* framework. For further information, see +# http://www.m5sim.org/Simulation_Scripts_Explained +# This script is based on $FAIL/simulators/gem5/configs/example/fs.py +# +# Author: Adrian Böckenkamp +# + +# -------------------------------------------------------------- +# Required Python modules: +import optparse +import sys + +import m5 # required by gem5 +from m5.objects import * # dito +from m5.util import addToPath, fatal # some helpers + +addToPath('../common') # to find the next modules: +from FSConfig import * +import Simulation # for setWorkCountOptions(), run() +import CacheConfig +import Options # for parsing the command line + +# -------------------------------------------------------------- +# Configuration phase: +parser = optparse.OptionParser() # TODO: functionality useful? +Options.addCommonOptions(parser) # TODO: remove unused options +Options.addFSOptions(parser) # TODO: dito + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) +print "[Fail*] Welcome to the FULL SYSTEM simulation script for gem5!" + +# Sets up the low-level system parameter: +class FailArmSystem(System): + type = 'ArmSystem' + load_addr_mask = 0xffffffff + # 0x35 Implementor is '5' from "M5" + # 0x0 Variant + # 0xf Architecture from CPUID scheme + # 0xc00 Primary part number ("c" or higher implies ARM v7) + # 0x0 Revision + midr_regval = Param.UInt32(0x350fc000, "MIDR value") + multi_proc = Param.Bool(True, "Multiprocessor system?") + boot_loader = Param.String("", "File that contains the boot loader code if any") + gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface") + flags_addr = Param.Addr(0, "Address of the flags register for MP booting") + +# Creates gem5-related (Python) system objects (hierarchy): +def makeFailArmSystem(mem_mode, machine_type): + assert machine_type + + self = FailArmSystem() + + # generic system + mdesc = SysConfig() + + self.readfile = mdesc.script() + self.iobus = NoncoherentBus() + self.membus = MemBus() + self.membus.badaddr_responder.warn_access = "warn" + self.bridge = Bridge(delay='50ns', nack_delay='4ns') + self.bridge.master = self.iobus.slave + self.bridge.slave = self.membus.master + + self.mem_mode = mem_mode + + if machine_type == "RealView_PBX": + self.realview = RealViewPBX() + elif machine_type == "RealView_EB": + self.realview = RealViewEB() + elif machine_type == "VExpress_ELT": + self.realview = VExpress_ELT() + elif machine_type == "VExpress_EMM": + self.realview = VExpress_EMM() + self.load_addr_mask = 0xffffffff + else: + print "Unknown Machine Type" + sys.exit(1) + + # No disk image / IDE controller interface stuff. + + # EOT character on UART will end the simulation + self.realview.uart.end_on_eot = True + self.physmem = SimpleMemory(range = AddrRange(Addr(mdesc.mem())), + zero = True) + self.physmem.port = self.membus.master + self.realview.attachOnChipIO(self.membus, self.bridge) + self.realview.attachIO(self.iobus) + self.intrctrl = IntrControl() + self.terminal = Terminal() + self.vncserver = VncServer() + + self.system_port = self.membus.slave + + return self + +# Driver system CPU is always simple... note this is an assignment of +# a class, not an instance. +DriveCPUClass = AtomicSimpleCPU +drive_mem_mode = 'atomic' + +# We use the atomic simple CPU model: +class TestCPUClass(AtomicSimpleCPU): pass +# "TestCPUClass" is our CPU class type (sic!), derived from AtomicSimpleCPU +test_mem_mode = 'atomic' +FutureClass = None + +TestCPUClass.clock = '2GHz' +DriveCPUClass.clock = '2GHz' + +# Extract #CPUs: +np = options.num_cpus + +# This script is only designed to be used with ARM targets. However, +# it should be simple to extend it. +if buildEnv['TARGET_ISA'] != "arm": + fatal("Incapable of building %s full system (only for ARM)! You may want to try fs.py instead.", buildEnv['TARGET_ISA']) + +# Create the gem5 component hierarchy (see above for the definition). +# In particular, it specifies system-specific parameters (e.g., Multi- +# processor system flag, memory bus (type), an UART, ...): +test_sys = makeFailArmSystem(test_mem_mode, options.machine_type) + +# Set the path to the kernel. Essentially, this the path to your +# experiment target (e.g., the abo-simple-arm.elf file). It should +# contain the bootload code as well. +if options.kernel is not None: + print "[Fail*] Using target: " + options.kernel + test_sys.kernel = options.kernel +else: + print "[Fail*] No kernel target given, exiting!" + sys.exit(1) + +test_sys.init_param = options.init_param + +# Construct the CPUs (np in total) and connect them to the "test system": +test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)] + +# Create the memory: +mem_size = SysConfig().mem() + +# Create the caches: +if options.caches or options.l2cache: + test_sys.iocache = IOCache(addr_ranges=[test_sys.physmem.range]) + test_sys.iocache.cpu_side = test_sys.iobus.master + test_sys.iocache.mem_side = test_sys.membus.slave +else: + test_sys.iobridge = Bridge(delay='50ns', nack_delay='4ns', + ranges = [test_sys.physmem.range]) + test_sys.iobridge.slave = test_sys.iobus.master + test_sys.iobridge.master = test_sys.membus.slave + +# Sanity check +if options.fastmem and (options.caches or options.l2cache): + fatal("You cannot use fastmem in combination with caches!") + +for i in xrange(np): + if options.fastmem: + test_sys.cpu[i].fastmem = True + if options.checker: + test_sys.cpu[i].addCheckerCpu() + +CacheConfig.config_cache(options, test_sys) + +# Setup the root node and connect the hierarchy: +root = Root(full_system=True, system=test_sys) + +# TODO: What's this for? +if options.timesync: + root.time_sync_enable = True + +# TODO: What's this for? +if options.frame_capture: + VncServer.frame_capture = True + +# -------------------------------------------------------------- +# Simulation phase: +Simulation.setWorkCountOptions(test_sys, options) # see Simulation.py +# In essence, "run(...)" calls m5.instantiate() and, finally, m5.simulate(). +Simulation.run(options, root, test_sys, FutureClass)