From c957d00dfeea618137cf14c02f6c20b0f02dbed3 Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Tue, 3 Sep 2019 12:22:59 +0200 Subject: [PATCH] configs: Port CPUConfig to use the common object list Factor out ObjectList functionality from CPUConfig. Change-Id: I34ca55142e14559e584d38b6cca3aa5c20923521 Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20589 Tested-by: kokoro Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg --- configs/common/CpuConfig.py | 79 ----------------------------- configs/common/ObjectList.py | 45 ++++++++++++++++ configs/common/Options.py | 9 ++-- configs/common/Simulation.py | 5 +- configs/example/arm/devices.py | 10 ++-- configs/example/arm/fs_bigLITTLE.py | 19 +++---- configs/example/fs.py | 10 ++-- configs/example/se.py | 5 +- 8 files changed, 78 insertions(+), 104 deletions(-) diff --git a/configs/common/CpuConfig.py b/configs/common/CpuConfig.py index 0228148d5..9a0fcd9d6 100644 --- a/configs/common/CpuConfig.py +++ b/configs/common/CpuConfig.py @@ -40,66 +40,6 @@ from __future__ import absolute_import from m5 import fatal import m5.objects -import inspect -import sys -from textwrap import TextWrapper - -# Dictionary of mapping names of real CPU models to classes. -_cpu_classes = {} - - -def is_cpu_class(cls): - """Determine if a class is a CPU 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.BaseCPU) and \ - not cls.abstract and \ - not issubclass(cls, m5.objects.CheckerCPU) - except (TypeError, AttributeError): - return False - -def _cpu_subclass_tester(name): - cpu_class = getattr(m5.objects, name, None) - - def tester(cls): - return cpu_class is not None and cls is not None and \ - issubclass(cls, cpu_class) - - return tester - -is_kvm_cpu = _cpu_subclass_tester("BaseKvmCPU") -is_noncaching_cpu = _cpu_subclass_tester("NonCachingSimpleCPU") - -def get(name): - """Get a CPU class from a user provided class name or alias.""" - - try: - cpu_class = _cpu_classes[name] - return cpu_class - except KeyError: - print("%s is not a valid CPU model." % (name,)) - sys.exit(1) - -def print_cpu_list(): - """Print a list of available CPU classes including their aliases.""" - - print("Available CPU classes:") - doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t") - for name, cls in _cpu_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) - -def cpu_names(): - """Return a list of valid CPU names.""" - return list(_cpu_classes.keys()) def config_etrace(cpu_cls, cpu_list, options): if issubclass(cpu_cls, m5.objects.DerivO3CPU): @@ -124,22 +64,3 @@ def config_etrace(cpu_cls, cpu_list, options): else: fatal("%s does not support data dependency tracing. Use a CPU model of" " type or inherited from DerivO3CPU.", cpu_cls) - -# Add all CPUs in the object hierarchy. -for name, cls in inspect.getmembers(m5.objects, is_cpu_class): - _cpu_classes[name] = cls - - -from m5.defines import buildEnv -from importlib import import_module -for package in [ "generic", buildEnv['TARGET_ISA']]: - try: - package = import_module(".cores." + package, - package=__name__.rpartition('.')[0]) - except ImportError: - # No timing models for this ISA - continue - - for mod_name, module in inspect.getmembers(package, inspect.ismodule): - for name, cls in inspect.getmembers(module, is_cpu_class): - _cpu_classes[name] = cls diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index fec78dca7..31f8c4194 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -103,3 +103,48 @@ class ObjectList(object): # Dictionary that maps names of real models to classes self._sub_classes = {} self._add_objects() + +class CPUList(ObjectList): + def _is_obj_class(self, cls): + """Determine if a class is a CPU 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 super(CPUList, self)._is_obj_class(cls) and \ + not issubclass(cls, m5.objects.CheckerCPU) + except (TypeError, AttributeError): + return False + + def _add_objects(self): + super(CPUList, self)._add_objects() + + from m5.defines import buildEnv + from importlib import import_module + for package in [ "generic", buildEnv['TARGET_ISA']]: + try: + package = import_module(".cores." + package, + package=__name__.rpartition('.')[0]) + except ImportError: + # No timing models for this ISA + continue + + for mod_name, module in \ + inspect.getmembers(package, inspect.ismodule): + for name, cls in inspect.getmembers(module, + self._is_obj_class): + self._sub_classes[name] = cls + +cpu_list = CPUList(m5.objects.BaseCPU) + +def _subclass_tester(name): + sub_class = getattr(m5.objects, name, None) + + def tester(cls): + return sub_class is not None and cls is not None and \ + issubclass(cls, sub_class) + + return tester + +is_kvm_cpu = _subclass_tester("BaseKvmCPU") +is_noncaching_cpu = _subclass_tester("NonCachingSimpleCPU") diff --git a/configs/common/Options.py b/configs/common/Options.py index f6fa0d031..57ee562cc 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -46,14 +46,14 @@ from m5.defines import buildEnv from m5.objects import * from .Benchmarks import * -from . import CpuConfig +from . import ObjectList from . import BPConfig from . import HWPConfig from . import MemConfig from . import PlatformConfig def _listCpuTypes(option, opt, value, parser): - CpuConfig.print_cpu_list() + ObjectList.cpu_list.print() sys.exit(0) def _listBPTypes(option, opt, value, parser): @@ -163,7 +163,7 @@ def addCommonOptions(parser): action="callback", callback=_listCpuTypes, help="List available CPU types") parser.add_option("--cpu-type", type="choice", default="AtomicSimpleCPU", - choices=CpuConfig.cpu_names(), + choices=ObjectList.cpu_list.get_names(), help = "type of cpu to run with") parser.add_option("--list-bp-types", action="callback", callback=_listBPTypes, @@ -317,7 +317,8 @@ def addCommonOptions(parser): parser.add_option("--work-cpus-checkpoint-count", action="store", type="int", help="checkpoint and exit when active cpu count is reached") parser.add_option("--restore-with-cpu", action="store", type="choice", - default="AtomicSimpleCPU", choices=CpuConfig.cpu_names(), + default="AtomicSimpleCPU", + choices=ObjectList.cpu_list.get_names(), help = "cpu type for restoring from a checkpoint") diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 56107c1e6..457caf9aa 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -46,7 +46,8 @@ import sys from os import getcwd from os.path import join as joinpath -from . import CpuConfig +from common import CpuConfig +from . import ObjectList from . import BPConfig from . import MemConfig @@ -59,7 +60,7 @@ addToPath('../common') def getCPUClass(cpu_type): """Returns the required cpu class and the mode of operation.""" - cls = CpuConfig.get(cpu_type) + cls = ObjectList.cpu_list.get(cpu_type) return cls, cls.memory_mode() def setCPUClass(options): diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index ff7a2a136..4d746edef 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -45,9 +45,9 @@ import m5 from m5.objects import * m5.util.addToPath('../../') from common.Caches import * -from common import CpuConfig +from common import ObjectList -have_kvm = "ArmV8KvmCPU" in CpuConfig.cpu_names() +have_kvm = "ArmV8KvmCPU" in ObjectList.cpu_list.get_names() class L1I(L1_ICache): tag_latency = 1 @@ -169,7 +169,8 @@ class CpuCluster(SubSystem): class AtomicCluster(CpuCluster): def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): - cpu_config = [ CpuConfig.get("AtomicSimpleCPU"), None, None, None, None ] + cpu_config = [ ObjectList.cpu_list.get("AtomicSimpleCPU"), None, + None, None, None ] super(AtomicCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config) def addL1(self): @@ -177,7 +178,8 @@ class AtomicCluster(CpuCluster): class KvmCluster(CpuCluster): def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): - cpu_config = [ CpuConfig.get("ArmV8KvmCPU"), None, None, None, None ] + cpu_config = [ ObjectList.cpu_list.get("ArmV8KvmCPU"), None, None, + None, None ] super(KvmCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config) def addL1(self): diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py index dcc2a5dce..a1ad2ce73 100644 --- a/configs/example/arm/fs_bigLITTLE.py +++ b/configs/example/arm/fs_bigLITTLE.py @@ -53,7 +53,7 @@ from m5.objects import * m5.util.addToPath("../../") from common import SysPaths -from common import CpuConfig +from common import ObjectList from common import PlatformConfig from common.cores.arm import ex5_big, ex5_LITTLE @@ -85,32 +85,33 @@ def _using_pdes(root): class BigCluster(devices.CpuCluster): def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): - cpu_config = [ CpuConfig.get("O3_ARM_v7a_3"), devices.L1I, devices.L1D, - devices.WalkCache, devices.L2 ] + cpu_config = [ ObjectList.cpu_list.get("O3_ARM_v7a_3"), + devices.L1I, devices.L1D, devices.WalkCache, devices.L2 ] super(BigCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config) class LittleCluster(devices.CpuCluster): def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"): - cpu_config = [ CpuConfig.get("MinorCPU"), devices.L1I, devices.L1D, - devices.WalkCache, devices.L2 ] + cpu_config = [ ObjectList.cpu_list.get("MinorCPU"), devices.L1I, + devices.L1D, devices.WalkCache, devices.L2 ] super(LittleCluster, self).__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 = [ CpuConfig.get("ex5_big"), ex5_big.L1I, ex5_big.L1D, - ex5_big.WalkCache, ex5_big.L2 ] + cpu_config = [ ObjectList.cpu_list.get("ex5_big"), ex5_big.L1I, + ex5_big.L1D, ex5_big.WalkCache, ex5_big.L2 ] super(Ex5BigCluster, self).__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 = [ CpuConfig.get("ex5_LITTLE"), ex5_LITTLE.L1I, - ex5_LITTLE.L1D, ex5_LITTLE.WalkCache, ex5_LITTLE.L2 ] + cpu_config = [ ObjectList.cpu_list.get("ex5_LITTLE"), + ex5_LITTLE.L1I, ex5_LITTLE.L1D, ex5_LITTLE.WalkCache, + ex5_LITTLE.L2 ] super(Ex5LittleCluster, self).__init__(system, num_cpus, cpu_clock, cpu_voltage, *cpu_config) diff --git a/configs/example/fs.py b/configs/example/fs.py index 386421d4f..ee813ff5d 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -62,8 +62,9 @@ from common.SysPaths import * from common.Benchmarks import * from common import Simulation from common import CacheConfig -from common import MemConfig from common import CpuConfig +from common import MemConfig +from common import ObjectList from common import BPConfig from common.Caches import * from common import Options @@ -144,7 +145,8 @@ def build_test_system(np): test_sys.cpu = [TestCPUClass(clk_domain=test_sys.cpu_clk_domain, cpu_id=i) for i in range(np)] - if CpuConfig.is_kvm_cpu(TestCPUClass) or CpuConfig.is_kvm_cpu(FutureClass): + if ObjectList.is_kvm_cpu(TestCPUClass) or \ + ObjectList.is_kvm_cpu(FutureClass): test_sys.kvm_vm = KvmVM() if options.ruby: @@ -193,7 +195,7 @@ def build_test_system(np): # Sanity check if options.simpoint_profile: - if not CpuConfig.is_noncaching_cpu(TestCPUClass): + if not ObjectList.is_noncaching_cpu(TestCPUClass): fatal("SimPoint generation should be done with atomic cpu") if np > 1: fatal("SimPoint generation not supported with more than one CPUs") @@ -278,7 +280,7 @@ def build_drive_system(np): print("Error: a kernel must be provided to run in full system mode") sys.exit(1) - if CpuConfig.is_kvm_cpu(DriveCPUClass): + if ObjectList.is_kvm_cpu(DriveCPUClass): drive_sys.kvm_vm = KvmVM() drive_sys.iobridge = Bridge(delay='50ns', diff --git a/configs/example/se.py b/configs/example/se.py index f43206ad2..e1396bfa2 100644 --- a/configs/example/se.py +++ b/configs/example/se.py @@ -62,6 +62,7 @@ from common import Options from common import Simulation from common import CacheConfig from common import CpuConfig +from common import ObjectList from common import BPConfig from common import MemConfig from common.FileSystemConfig import config_filesystem @@ -206,7 +207,7 @@ if options.elastic_trace_en: for cpu in system.cpu: cpu.clk_domain = system.cpu_clk_domain -if CpuConfig.is_kvm_cpu(CPUClass) or CpuConfig.is_kvm_cpu(FutureClass): +if ObjectList.is_kvm_cpu(CPUClass) or ObjectList.is_kvm_cpu(FutureClass): if buildEnv['TARGET_ISA'] == 'x86': system.kvm_vm = KvmVM() for process in multiprocesses: @@ -217,7 +218,7 @@ if CpuConfig.is_kvm_cpu(CPUClass) or CpuConfig.is_kvm_cpu(FutureClass): # Sanity check if options.simpoint_profile: - if not CpuConfig.is_noncaching_cpu(CPUClass): + if not ObjectList.is_noncaching_cpu(CPUClass): fatal("SimPoint/BPProbe should be done with an atomic cpu") if np > 1: fatal("SimPoint generation not supported with more than one CPUs") -- 2.30.2