diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index 3a7a50839..0d46dcde2 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -55,7 +55,7 @@ class MemBus(CoherentBus): default = Self.badaddr_responder.pio -def makeLinuxAlphaSystem(mem_mode, mdesc = None): +def makeLinuxAlphaSystem(mem_mode, MemClass, mdesc = None): IO_address_space_base = 0x80000000000 class BaseTsunami(Tsunami): ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) @@ -73,7 +73,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None): # base address (including the PCI config space) self.bridge = Bridge(delay='50ns', ranges = [AddrRange(IO_address_space_base, Addr.max)]) - self.physmem = SimpleDDR3(range = AddrRange(mdesc.mem())) + self.physmem = MemClass(range = AddrRange(mdesc.mem())) self.mem_ranges = [self.physmem.range] self.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master @@ -104,13 +104,13 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None): return self -def makeLinuxAlphaRubySystem(mem_mode, mdesc = None): +def makeLinuxAlphaRubySystem(mem_mode, MemClass, mdesc = None): class BaseTsunami(Tsunami): ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) ide = IdeController(disks=[Parent.disk0, Parent.disk2], pci_func=0, pci_dev=0, pci_bus=0) - physmem = SimpleDDR3(range = AddrRange(mdesc.mem())) + physmem = MemClass(range = AddrRange(mdesc.mem())) self = LinuxAlphaSystem(physmem = physmem) self.mem_ranges = [self.physmem.range] if not mdesc: @@ -157,7 +157,7 @@ def makeLinuxAlphaRubySystem(mem_mode, mdesc = None): return self -def makeSparcSystem(mem_mode, mdesc = None): +def makeSparcSystem(mem_mode, MemClass, mdesc = None): # Constants from iob.cc and uart8250.cc iob_man_addr = 0x9800000000 uart_pio_size = 8 @@ -180,10 +180,10 @@ def makeSparcSystem(mem_mode, mdesc = None): self.t1000 = T1000() self.t1000.attachOnChipIO(self.membus) self.t1000.attachIO(self.iobus) - self.physmem = SimpleDDR3(range = AddrRange(Addr('1MB'), size = '64MB'), - zero = True) - self.physmem2 = SimpleDDR3(range = AddrRange(Addr('2GB'), size ='256MB'), - zero = True) + self.physmem = MemClass(range = AddrRange(Addr('1MB'), size = '64MB'), + zero = True) + self.physmem2 = MemClass(range = AddrRange(Addr('2GB'), size ='256MB'), + zero = True) self.mem_ranges = [self.physmem.range, self.physmem2.range] self.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master @@ -227,8 +227,8 @@ def makeSparcSystem(mem_mode, mdesc = None): return self -def makeArmSystem(mem_mode, machine_type, mdesc = None, dtb_filename = None, - bare_metal=False): +def makeArmSystem(mem_mode, machine_type, MemClass, mdesc = None, + dtb_filename = None, bare_metal=False): assert machine_type if bare_metal: @@ -275,8 +275,8 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, dtb_filename = None, if bare_metal: # EOT character on UART will end the simulation self.realview.uart.end_on_eot = True - self.physmem = SimpleDDR3(range = AddrRange(Addr(mdesc.mem())), - zero = True) + self.physmem = MemClass(range = AddrRange(Addr(mdesc.mem())), + zero = True) self.mem_ranges = [self.physmem.range] else: self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8') @@ -292,10 +292,9 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, dtb_filename = None, boot_flags = 'earlyprintk console=ttyAMA0 lpj=19988480 norandmaps ' + \ 'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem() - self.physmem = SimpleDDR3(range = - AddrRange(self.realview.mem_start_addr, - size = mdesc.mem()), - conf_table_reported = True) + self.physmem = MemClass(range = AddrRange(self.realview.mem_start_addr, + size = mdesc.mem()), + conf_table_reported = True) self.mem_ranges = [self.physmem.range] self.realview.setupBootLoader(self.membus, self, binary) self.gic_cpu_addr = self.realview.gic.cpu_addr @@ -317,7 +316,7 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, dtb_filename = None, return self -def makeLinuxMipsSystem(mem_mode, mdesc = None): +def makeLinuxMipsSystem(mem_mode, MemClass, mdesc = None): class BaseMalta(Malta): ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) ide = IdeController(disks=[Parent.disk0, Parent.disk2], @@ -331,7 +330,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None): self.iobus = NoncoherentBus() self.membus = MemBus() self.bridge = Bridge(delay='50ns') - self.physmem = SimpleDDR3(range = AddrRange('1GB')) + self.physmem = MemClass(range = AddrRange('1GB')) self.mem_ranges = [self.physmem.range] self.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master @@ -425,7 +424,8 @@ def connectX86RubySystem(x86_sys): x86_sys.pc.attachIO(x86_sys.piobus, x86_sys._dma_ports) -def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False): +def makeX86System(mem_mode, MemClass, numCPUs = 1, mdesc = None, self = None, + Ruby = False): if self == None: self = X86System() @@ -437,7 +437,7 @@ def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False self.mem_mode = mem_mode # Physical memory - self.physmem = SimpleDDR3(range = AddrRange(mdesc.mem())) + self.physmem = MemClass(range = AddrRange(mdesc.mem())) self.mem_ranges = [self.physmem.range] # Platform @@ -521,11 +521,12 @@ def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False self.intel_mp_table.base_entries = base_entries self.intel_mp_table.ext_entries = ext_entries -def makeLinuxX86System(mem_mode, numCPUs = 1, mdesc = None, Ruby = False): +def makeLinuxX86System(mem_mode, MemClass, numCPUs = 1, mdesc = None, + Ruby = False): self = LinuxX86System() # Build up the x86 system and then specialize it for Linux - makeX86System(mem_mode, numCPUs, mdesc, self, Ruby) + makeX86System(mem_mode, MemClass, numCPUs, mdesc, self, Ruby) # We assume below that there's at least 1MB of memory. We'll require 2 # just to avoid corner cases. diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py new file mode 100644 index 000000000..4e772c3ea --- /dev/null +++ b/configs/common/MemConfig.py @@ -0,0 +1,125 @@ +# Copyright (c) 2013 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 +# Andreas Hansson + +import m5.objects +import inspect +import sys +from textwrap import TextWrapper + +# Dictionary of mapping names of real memory controller models to +# classes. +_mem_classes = {} + +# Memory aliases. We make sure they exist before we add them to the +# fina; list. A target may be specified as a tuple, in which case the +# first available memory controller model in the tuple will be used. +_mem_aliases_all = [ + ("simple_mem", "SimpleMemory"), + ("ddr3-1600", "SimpleDDR3"), + ("lpddr2_s4-1066", "SimpleLPDDR2_S4"), + ("wio-200", "SimpleWideIO"), + ] + +# Filtered list of aliases. Only aliases for existing memory +# controllers exist in this list. +_mem_aliases = {} + + +def is_mem_class(cls): + """Determine if a class is a memory controller 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.AbstractMemory) and \ + not cls.abstract + except TypeError: + return False + +def get(name): + """Get a memory class from a user provided class name or alias.""" + + real_name = _mem_aliases.get(name, name) + + try: + mem_class = _mem_classes[real_name] + return mem_class + except KeyError: + print "%s is not a valid memory controller." % (name,) + sys.exit(1) + +def print_mem_list(): + """Print a list of available memory classes including their aliases.""" + + print "Available memory classes:" + doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t") + for name, cls in _mem_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 _mem_aliases: + print "\nMemory aliases:" + for alias, target in _mem_aliases.items(): + print "\t%s => %s" % (alias, target) + +def mem_names(): + """Return a list of valid memory names.""" + return _mem_classes.keys() + _mem_aliases.keys() + +# Add all memory controllers in the object hierarchy. +for name, cls in inspect.getmembers(m5.objects, is_mem_class): + _mem_classes[name] = cls + +for alias, target in _mem_aliases_all: + if isinstance(target, tuple): + # Some aliases contain a list of memory controller models + # sorted in priority order. Use the first target that's + # available. + for t in target: + if t in _mem_classes: + _mem_aliases[alias] = t + break + elif target in _mem_classes: + # Normal alias + _mem_aliases[alias] = target diff --git a/configs/common/Options.py b/configs/common/Options.py index 474da94f4..e651e96ec 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -1,3 +1,15 @@ +# Copyright (c) 2013 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. +# # Copyright (c) 2006-2008 The Regents of The University of Michigan # All rights reserved. # @@ -32,11 +44,16 @@ from m5.objects import * from Benchmarks import * import CpuConfig +import MemConfig def _listCpuTypes(option, opt, value, parser): CpuConfig.print_cpu_list() sys.exit(0) +def _listMemTypes(option, opt, value, parser): + MemConfig.print_mem_list() + sys.exit(0) + def addCommonOptions(parser): # system options parser.add_option("--list-cpu-types", @@ -45,6 +62,12 @@ def addCommonOptions(parser): parser.add_option("--cpu-type", type="choice", default="atomic", choices=CpuConfig.cpu_names(), help = "type of cpu to run with") + parser.add_option("--list-mem-types", + action="callback", callback=_listMemTypes, + help="List available memory types") + parser.add_option("--mem-type", type="choice", default="simple_mem", + choices=MemConfig.mem_names(), + help = "type of memory to use") parser.add_option("--checker", action="store_true"); parser.add_option("-n", "--num-cpus", type="int", default=1) parser.add_option("--caches", action="store_true") diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index cecf030ad..27b1a510a 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -44,6 +44,7 @@ from os import getcwd from os.path import join as joinpath import CpuConfig +import MemConfig import m5 from m5.defines import buildEnv @@ -84,6 +85,11 @@ def setCPUClass(options): return (TmpClass, test_mem_mode, CPUClass) +def setMemClass(options): + """Returns a memory controller class.""" + + return MemConfig.get(options.mem_type) + def setWorkCountOptions(system, options): if options.work_item_id != None: system.work_item_id = options.work_item_id diff --git a/configs/example/fs.py b/configs/example/fs.py index 1f8e2d3a7..4fedf12db 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -84,6 +84,11 @@ def is_kvm_cpu(cpu_class): TestCPUClass.clock = options.clock DriveCPUClass.clock = options.clock +# Match the memories with the CPUs, the driver system always simple, +# and based on the options for the test system +DriveMemClass = SimpleMemory +TestMemClass = Simulation.setMemClass(options) + if options.benchmark: try: bm = Benchmarks[options.benchmark] @@ -100,16 +105,18 @@ else: np = options.num_cpus if buildEnv['TARGET_ISA'] == "alpha": - test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0]) + test_sys = makeLinuxAlphaSystem(test_mem_mode, TestMemClass, bm[0]) elif buildEnv['TARGET_ISA'] == "mips": - test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0]) + test_sys = makeLinuxMipsSystem(test_mem_mode, TestMemClass, bm[0]) elif buildEnv['TARGET_ISA'] == "sparc": - test_sys = makeSparcSystem(test_mem_mode, bm[0]) + test_sys = makeSparcSystem(test_mem_mode, TestMemClass, bm[0]) elif buildEnv['TARGET_ISA'] == "x86": - test_sys = makeLinuxX86System(test_mem_mode, options.num_cpus, bm[0]) + test_sys = makeLinuxX86System(test_mem_mode, TestMemClass, + options.num_cpus, bm[0]) elif buildEnv['TARGET_ISA'] == "arm": - test_sys = makeArmSystem(test_mem_mode, options.machine_type, bm[0], - options.dtb_filename, bare_metal=options.bare_metal) + test_sys = makeArmSystem(test_mem_mode, options.machine_type, + TestMemClass, bm[0], options.dtb_filename, + bare_metal=options.bare_metal) else: fatal("Incapable of building %s full system!", buildEnv['TARGET_ISA']) @@ -154,15 +161,16 @@ CacheConfig.config_cache(options, test_sys) if len(bm) == 2: if buildEnv['TARGET_ISA'] == 'alpha': - drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1]) + drive_sys = makeLinuxAlphaSystem(drive_mem_mode, DriveMemClass, bm[1]) elif buildEnv['TARGET_ISA'] == 'mips': - drive_sys = makeLinuxMipsSystem(drive_mem_mode, bm[1]) + drive_sys = makeLinuxMipsSystem(drive_mem_mode, DriveMemClass, bm[1]) elif buildEnv['TARGET_ISA'] == 'sparc': - drive_sys = makeSparcSystem(drive_mem_mode, bm[1]) + drive_sys = makeSparcSystem(drive_mem_mode, DriveMemClass, bm[1]) elif buildEnv['TARGET_ISA'] == 'x86': - drive_sys = makeX86System(drive_mem_mode, np, bm[1]) + drive_sys = makeX86System(drive_mem_mode, DriveMemClass, np, bm[1]) elif buildEnv['TARGET_ISA'] == 'arm': - drive_sys = makeArmSystem(drive_mem_mode, options.machine_type, bm[1]) + drive_sys = makeArmSystem(drive_mem_mode, options.machine_type, + DriveMemClass, bm[1]) drive_sys.cpu = DriveCPUClass(cpu_id=0) drive_sys.cpu.createThreads() diff --git a/configs/example/se.py b/configs/example/se.py index a5f0204fd..6878742c8 100644 --- a/configs/example/se.py +++ b/configs/example/se.py @@ -150,13 +150,15 @@ else: CPUClass.clock = options.clock CPUClass.numThreads = numThreads +MemClass = Simulation.setMemClass(options) + # Check -- do not allow SMT with multiple CPUs if options.smt and options.num_cpus > 1: fatal("You cannot use SMT with multiple CPUs!") np = options.num_cpus system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)], - physmem = SimpleMemory(range=AddrRange("512MB")), + physmem = MemClass(range=AddrRange("512MB")), membus = CoherentBus(), mem_mode = test_mem_mode) # Sanity check diff --git a/tests/configs/alpha_generic.py b/tests/configs/alpha_generic.py index a4ebba54d..5060eae39 100644 --- a/tests/configs/alpha_generic.py +++ b/tests/configs/alpha_generic.py @@ -59,7 +59,7 @@ class LinuxAlphaSystemBuilder(object): pass def create_system(self): - system = FSConfig.makeLinuxAlphaSystem(self.mem_mode) + system = FSConfig.makeLinuxAlphaSystem(self.mem_mode, SimpleDDR3) self.init_system(system) return system diff --git a/tests/configs/arm_generic.py b/tests/configs/arm_generic.py index 1b0e8ee8b..e6c56041b 100644 --- a/tests/configs/arm_generic.py +++ b/tests/configs/arm_generic.py @@ -61,6 +61,7 @@ class LinuxArmSystemBuilder(object): def create_system(self): system = FSConfig.makeArmSystem(self.mem_mode, self.machine_type, + SimpleDDR3, None, False) # We typically want the simulator to panic if the kernel diff --git a/tests/configs/pc-simple-timing-ruby.py b/tests/configs/pc-simple-timing-ruby.py index 23a0bb3d0..6413133c2 100644 --- a/tests/configs/pc-simple-timing-ruby.py +++ b/tests/configs/pc-simple-timing-ruby.py @@ -55,7 +55,7 @@ options.num_cpus = 2 #the system mdesc = SysConfig(disk = 'linux-x86.img') -system = FSConfig.makeLinuxX86System('timing', options.num_cpus, +system = FSConfig.makeLinuxX86System('timing', SimpleDDR3, options.num_cpus, mdesc=mdesc, Ruby=True) system.kernel = FSConfig.binary('x86_64-vmlinux-2.6.22.9.smp') system.cpu = [TimingSimpleCPU(cpu_id=i) for i in xrange(options.num_cpus)] diff --git a/tests/configs/twosys-tsunami-simple-atomic.py b/tests/configs/twosys-tsunami-simple-atomic.py index dbfcaaafe..89d497008 100644 --- a/tests/configs/twosys-tsunami-simple-atomic.py +++ b/tests/configs/twosys-tsunami-simple-atomic.py @@ -32,7 +32,7 @@ m5.util.addToPath('../configs/common') from FSConfig import * from Benchmarks import * -test_sys = makeLinuxAlphaSystem('atomic', +test_sys = makeLinuxAlphaSystem('atomic', SimpleDDR3, SysConfig('netperf-stream-client.rcS')) test_sys.cpu = AtomicSimpleCPU(cpu_id=0) # create the interrupt controller @@ -46,7 +46,7 @@ test_sys.iobridge = Bridge(delay='50ns', ranges = test_sys.mem_ranges) test_sys.iobridge.slave = test_sys.iobus.master test_sys.iobridge.master = test_sys.membus.slave -drive_sys = makeLinuxAlphaSystem('atomic', +drive_sys = makeLinuxAlphaSystem('atomic', SimpleDDR3, SysConfig('netperf-server.rcS')) drive_sys.cpu = AtomicSimpleCPU(cpu_id=0) # create the interrupt controller diff --git a/tests/configs/x86_generic.py b/tests/configs/x86_generic.py index b9f8f7122..e9e7bff63 100644 --- a/tests/configs/x86_generic.py +++ b/tests/configs/x86_generic.py @@ -58,6 +58,7 @@ class LinuxX86SystemBuilder(object): def create_system(self): mdesc = SysConfig(disk = 'linux-x86.img') system = FSConfig.makeLinuxX86System(self.mem_mode, + SimpleDDR3, numCPUs=self.num_cpus, mdesc=mdesc) system.kernel = FSConfig.binary('x86_64-vmlinux-2.6.22.9')