config: Command line support for multi-channel memory
authorAndreas Hansson <andreas.hansson@arm.com>
Mon, 19 Aug 2013 07:52:34 +0000 (03:52 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Mon, 19 Aug 2013 07:52:34 +0000 (03:52 -0400)
This patch adds support for specifying multi-channel memory
configurations on the command line, e.g. 'se/fs.py
--mem-type=ddr3_1600_x64 --mem-channels=4'. To enable this, it
enhances the functionality of MemConfig and moves the existing
makeMultiChannel class method from SimpleDRAM to the support scripts.

The se/fs.py example scripts are updated to make use of the new
feature.

configs/common/MemConfig.py
configs/common/Options.py
configs/example/fs.py
configs/example/se.py
src/mem/SimpleDRAM.py

index 6630be8ec34347c52c2a825ef3372fb05c63fafd..a74ff1d62844f49527a4889cbed30dc7e23e4b74 100644 (file)
@@ -124,3 +124,70 @@ for alias, target in _mem_aliases_all:
     elif target in _mem_classes:
         # Normal alias
         _mem_aliases[alias] = target
+
+def config_mem(options, system):
+    """
+    Create the memory controllers based on the options and attach them.
+
+    If requested, we make a multi-channel configuration of the
+    selected memory controller class by creating multiple instances of
+    the specific class. The individual controllers have their
+    parameters set such that the address range is interleaved between
+    them.
+    """
+
+    nbr_mem_ctrls = options.mem_channels
+    import math
+    from m5.util import fatal
+    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
+    if 2 ** intlv_bits != nbr_mem_ctrls:
+        fatal("Number of memory channels must be a power of 2")
+    cls = get(options.mem_type)
+    mem_ctrls = []
+
+    # The default behaviour is to interleave on cache line granularity
+    cache_line_bit = int(math.log(system.cache_line_size.value, 2)) - 1
+    intlv_low_bit = cache_line_bit
+
+    # For every range (most systems will only have one), create an
+    # array of controllers and set their parameters to match their
+    # address mapping in the case of a DRAM
+    for r in system.mem_ranges:
+        for i in xrange(nbr_mem_ctrls):
+            # Create an instance so we can figure out the address
+            # mapping and row-buffer size
+            ctrl = cls()
+
+            # Only do this for DRAMs
+            if issubclass(cls, m5.objects.SimpleDRAM):
+                # Inform each controller how many channels to account
+                # for
+                ctrl.channels = nbr_mem_ctrls
+
+                # If the channel bits are appearing after the column
+                # bits, we need to add the appropriate number of bits
+                # for the row buffer size
+                if ctrl.addr_mapping.value == 'RaBaChCo':
+                    # This computation only really needs to happen
+                    # once, but as we rely on having an instance we
+                    # end up having to repeat it for each and every
+                    # one
+                    rowbuffer_size = ctrl.device_rowbuffer_size.value * \
+                        ctrl.devices_per_rank.value
+
+                    intlv_low_bit = int(math.log(rowbuffer_size, 2)) - 1
+
+            # We got all we need to configure the appropriate address
+            # range
+            ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
+                                              intlvHighBit = \
+                                                  intlv_low_bit + intlv_bits,
+                                              intlvBits = intlv_bits,
+                                              intlvMatch = i)
+            mem_ctrls.append(ctrl)
+
+    system.mem_ctrls = mem_ctrls
+
+    # Connect the controllers to the membus
+    for i in xrange(nbr_mem_ctrls):
+        system.mem_ctrls[i].port = system.membus.master
index 73def510cf67413837008b9c0cac1d809eebf78e..6431d460f02914ecf07b5e35da4fdc6567bd424f 100644 (file)
@@ -88,6 +88,8 @@ def addCommonOptions(parser):
     parser.add_option("--mem-type", type="choice", default="simple_mem",
                       choices=MemConfig.mem_names(),
                       help = "type of memory to use")
+    parser.add_option("--mem-channels", type="int", default=1,
+                      help = "number of memory channels")
     parser.add_option("--mem-size", action="store", type="string",
                       default="512MB",
                       help="Specify the physical memory size (single memory)")
index bcd58ca5ef1cf7b80038aecbbe5e99c90f7a9222..4d6d87eb859a78214acc5247e8736a02a1e95792 100644 (file)
@@ -53,6 +53,7 @@ from SysPaths import *
 from Benchmarks import *
 import Simulation
 import CacheConfig
+import MemConfig
 from Caches import *
 import Options
 
@@ -171,12 +172,7 @@ for i in xrange(np):
     test_sys.cpu[i].createThreads()
 
 CacheConfig.config_cache(options, test_sys)
-
-# Create the appropriate memory controllers and connect them to the
-# memory bus
-test_sys.mem_ctrls = [TestMemClass(range = r) for r in test_sys.mem_ranges]
-for i in xrange(len(test_sys.mem_ctrls)):
-    test_sys.mem_ctrls[i].port = test_sys.membus.master
+MemConfig.config_mem(options, test_sys)
 
 if len(bm) == 2:
     if buildEnv['TARGET_ISA'] == 'alpha':
index 39572cd862e14c016f58a940522eb237ec67198d..02a0d3b9631357d26bd6663f71df5f9ddfcc5e39 100644 (file)
@@ -58,6 +58,7 @@ import Options
 import Ruby
 import Simulation
 import CacheConfig
+import MemConfig
 from Caches import *
 from cpu2000 import *
 
@@ -157,8 +158,8 @@ if options.smt and options.num_cpus > 1:
 
 np = options.num_cpus
 system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
-                physmem = MemClass(range=AddrRange(options.mem_size)),
                 mem_mode = test_mem_mode,
+                mem_ranges = [AddrRange(options.mem_size)],
                 cache_line_size = options.cacheline_size)
 
 # Create a top-level voltage domain
@@ -221,7 +222,8 @@ if options.ruby:
         sys.exit(1)
 
     # Set the option for physmem so that it is not allocated any space
-    system.physmem.null = True
+    system.physmem = MemClass(range=AddrRange(options.mem_size),
+                              null = True)
 
     options.use_map = True
     Ruby.create_system(options, system)
@@ -247,8 +249,8 @@ if options.ruby:
 else:
     system.membus = CoherentBus()
     system.system_port = system.membus.slave
-    system.physmem.port = system.membus.master
     CacheConfig.config_cache(options, system)
+    MemConfig.config_mem(options, system)
 
 root = Root(full_system = False, system = system)
 Simulation.run(options, root, system, FutureClass)
index b066b27def5ba194256bc868849a6355fbb33f0a..0ce94ba3e38ae9e8c685d584761fe1a121e03389 100644 (file)
@@ -64,38 +64,6 @@ class SimpleDRAM(AbstractMemory):
     type = 'SimpleDRAM'
     cxx_header = "mem/simple_dram.hh"
 
-    @classmethod
-    def makeMultiChannel(cls, nbr_mem_ctrls, mem_start_addr, mem_size,
-                         intlv_high_bit = 11):
-        """
-        Make a multi-channel configuration of this class.
-
-        Create multiple instances of the specific class and set their
-        parameters such that the address range is interleaved between
-        them.
-
-        Returns a list of controllers.
-        """
-        import math
-        from m5.util import fatal
-        intlv_bits = int(math.log(nbr_mem_ctrls, 2))
-        if 2 ** intlv_bits != nbr_mem_ctrls:
-            fatal("Number of memory channels must be a power of 2")
-        mem_ctrls = []
-        for i in xrange(nbr_mem_ctrls):
-            # The default interleaving granularity is tuned to match a
-            # row buffer size of 32 cache lines of 64 bytes (starting
-            # at bit 11 for 2048 bytes). There is unfortunately no
-            # good way of checking this at instantiation time.
-            mem_ctrls.append(cls(range = AddrRange(mem_start_addr,
-                                                   size = mem_size,
-                                                   intlvHighBit = \
-                                                       intlv_high_bit,
-                                                   intlvBits = intlv_bits,
-                                                   intlvMatch = i),
-                                 channels = nbr_mem_ctrls))
-        return mem_ctrls
-
     # single-ported on the system interface side, instantiate with a
     # bus in front of the controller for multiple ports
     port = SlavePort("Slave port")