arm, config: Automatically discover available platforms
authorAndreas Sandberg <andreas.sandberg@arm.com>
Fri, 4 Dec 2015 00:19:05 +0000 (00:19 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Fri, 4 Dec 2015 00:19:05 +0000 (00:19 +0000)
Add support for automatically discover available platforms. The
Python-side uses functionality similar to what we use when
auto-detecting available CPU models. The machine IDs have been updated
to match the platform configurations. If there isn't a matching
machine ID, the configuration scripts default to -1 which Linux uses
for device tree only platforms.

configs/common/FSConfig.py
configs/common/Options.py
configs/common/PlatformConfig.py [new file with mode: 0644]
src/arch/arm/ArmSystem.py

index 7dd2e05fd8c845a053b40c0877524ac6b59e51f5..e449efbd533dc3dc9816e58687c673148956af41 100644 (file)
@@ -42,6 +42,7 @@
 from m5.objects import *
 from Benchmarks import *
 from m5.util import *
+import PlatformConfig
 
 # Populate to reflect supported os types per target ISA
 os_types = { 'alpha' : [ 'linux' ],
@@ -207,6 +208,20 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
                   external_memory=""):
     assert machine_type
 
+    default_dtbs = {
+        "RealViewEB": None,
+        "RealViewPBX": None,
+        "VExpress_EMM": "vexpress.aarch32.ll_20131205.0-gem5.%dcpu.dtb" % num_cpus,
+        "VExpress_EMM64": "vexpress.aarch64.20140821.dtb",
+    }
+
+    default_kernels = {
+        "RealViewEB": "vmlinux.arm.smp.fb.2.6.38.8",
+        "RealViewPBX": "vmlinux.arm.smp.fb.2.6.38.8",
+        "VExpress_EMM": "vmlinux.aarch32.ll_20131205.0-gem5",
+        "VExpress_EMM64": "vmlinux.aarch64.20140821",
+    }
+
     if bare_metal:
         self = ArmSystem()
     else:
@@ -226,24 +241,23 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
 
     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_EMM":
-        self.realview = VExpress_EMM()
-        if not dtb_filename:
-            dtb_filename = 'vexpress.aarch32.ll_20131205.0-gem5.%dcpu.dtb' % num_cpus
-    elif machine_type == "VExpress_EMM64":
-        self.realview = VExpress_EMM64()
+    platform_class = PlatformConfig.get(machine_type)
+    # Resolve the real platform name, the original machine_type
+    # variable might have been an alias.
+    machine_type = platform_class.__name__
+    self.realview = platform_class()
+
+    if not dtb_filename and not bare_metal:
+        try:
+            dtb_filename = default_dtbs[machine_type]
+        except KeyError:
+            fatal("No DTB specified and no default DTB known for '%s'" % \
+                  machine_type)
+
+    if isinstance(self.realview, VExpress_EMM64):
         if os.path.split(mdesc.disk())[-1] == 'linux-aarch32-ael.img':
             print "Selected 64-bit ARM architecture, updating default disk image..."
             mdesc.diskname = 'linaro-minimal-aarch64.img'
-        if not dtb_filename:
-            dtb_filename = 'vexpress.aarch64.20140821.dtb'
-    else:
-        print "Unknown Machine Type"
-        sys.exit(1)
 
     self.cf0 = CowIdeDisk(driveID='master')
     self.cf0.childImage(mdesc.disk())
@@ -278,16 +292,15 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
         # EOT character on UART will end the simulation
         self.realview.uart.end_on_eot = True
     else:
-        if machine_type == "VExpress_EMM64":
-            self.kernel = binary('vmlinux.aarch64.20140821')
-        elif machine_type == "VExpress_EMM":
-            self.kernel = binary('vmlinux.aarch32.ll_20131205.0-gem5')
-        else:
-            self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8')
+        if machine_type in default_kernels:
+            self.kernel = binary(default_kernels[machine_type])
 
         if dtb_filename:
             self.dtb_filename = binary(dtb_filename)
-        self.machine_type = machine_type
+
+        self.machine_type = machine_type if machine_type in ArmMachineType.map \
+                            else "DTOnly"
+
         # Ensure that writes to the UART actually go out early in the boot
         if not cmdline:
             cmdline = 'earlyprintk=pl011,0x1c090000 console=ttyAMA0 ' + \
index 1922f78a656a794b19da8ecd3f0a818581a3edab..f4cf9fbd64d063cc5187d32fa7326e7288dce339 100644 (file)
@@ -45,6 +45,7 @@ from Benchmarks import *
 
 import CpuConfig
 import MemConfig
+import PlatformConfig
 
 from FSConfig import os_types
 
@@ -56,6 +57,10 @@ def _listMemTypes(option, opt, value, parser):
     MemConfig.print_mem_list()
     sys.exit(0)
 
+def _listPlatformTypes(option, opt, value, parser):
+    PlatformConfig.print_platform_list()
+    sys.exit(0)
+
 def addCommonOptions(parser):
     # system options
     parser.add_option("--list-cpu-types",
@@ -263,8 +268,12 @@ def addFSOptions(parser):
     if buildEnv['TARGET_ISA'] == "arm":
         parser.add_option("--bare-metal", action="store_true",
                    help="Provide the raw system without the linux specific bits")
+        parser.add_option("--list-machine-types",
+                          action="callback", callback=_listPlatformTypes,
+                      help="List available platform types")
         parser.add_option("--machine-type", action="store", type="choice",
-                choices=ArmMachineType.map.keys(), default="VExpress_EMM")
+                choices=PlatformConfig.platform_names(),
+                default="VExpress_EMM")
         parser.add_option("--dtb-filename", action="store", type="string",
               help="Specifies device tree blob file to use with device-tree-"\
               "enabled kernels")
diff --git a/configs/common/PlatformConfig.py b/configs/common/PlatformConfig.py
new file mode 100644 (file)
index 0000000..636e6d8
--- /dev/null
@@ -0,0 +1,109 @@
+# Copyright (c) 2012, 2015 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
+
+import m5.objects
+import inspect
+import sys
+from textwrap import TextWrapper
+
+# Dictionary of mapping names of real CPU models to classes.
+_platform_classes = {}
+
+# Platform aliases. The platforms listed here might not be compiled,
+# we make sure they exist before we add them to the platform list.
+_platform_aliases_all = [
+    ("RealView_EB", "RealViewEB"),
+    ("RealView_PBX", "RealViewPBX"),
+    ]
+
+# Filtered list of aliases. Only aliases for existing platforms exist
+# in this list.
+_platform_aliases = {}
+
+def is_platform_class(cls):
+    """Determine if a class is a Platform that can be instantiated"""
+
+    # We can't use the normal inspect.isclass because the ParamFactory
+    # and ProxyFactory classes have a tendency to confuse it.
+    try:
+        return issubclass(cls, m5.objects.Platform) and \
+            not cls.abstract
+    except TypeError:
+        return False
+
+def get(name):
+    """Get a platform class from a user provided class name."""
+
+    real_name = _platform_aliases.get(name, name)
+
+    try:
+        return _platform_classes[real_name]
+    except KeyError:
+        print "%s is not a valid Platform model." % (name,)
+        sys.exit(1)
+
+def print_platform_list():
+    """Print a list of available Platform classes including their aliases."""
+
+    print "Available Platform classes:"
+    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
+    for name, cls in _platform_classes.items():
+        print "\t%s" % name
+
+        # Try to extract the class documentation from the class help
+        # string.
+        doc = inspect.getdoc(cls)
+        if doc:
+            for line in doc_wrapper.wrap(doc):
+                print line
+
+    if _platform_aliases:
+        print "\Platform aliases:"
+        for alias, target in _platform_aliases.items():
+            print "\t%s => %s" % (alias, target)
+
+def platform_names():
+    """Return a list of valid Platform names."""
+    return _platform_classes.keys() + _platform_aliases.keys()
+
+# Add all Platforms in the object hierarchy.
+for name, cls in inspect.getmembers(m5.objects, is_platform_class):
+    _platform_classes[name] = cls
+
+for alias, target in _platform_aliases_all:
+    if target in _platform_classes:
+        _platform_aliases[alias] = target
index 1e5acc4e658e1a427cbcd8acb507130ba0c4045d..9bb939c5e1cfa903a4c80fe714099c170f5003c0 100644 (file)
@@ -40,10 +40,13 @@ from m5.params import *
 from System import System
 
 class ArmMachineType(Enum):
-    map = {'RealView_EB' : 827,
-           'RealView_PBX' : 1901,
-           'VExpress_EMM' : 2272,
-           'VExpress_EMM64' : 2272}
+    map = {
+        'RealViewEB' : 827,
+        'RealViewPBX' : 1901,
+        'VExpress_EMM' : 2272,
+        'VExpress_EMM64' : 2272,
+        'DTOnly' : -1,
+    }
 
 class ArmSystem(System):
     type = 'ArmSystem'