config: Command line support for multi-channel memory
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.
This commit is contained in:
parent
49d88f08b0
commit
c26911013c
|
@ -124,3 +124,70 @@ for alias, target in _mem_aliases_all:
|
||||||
elif target in _mem_classes:
|
elif target in _mem_classes:
|
||||||
# Normal alias
|
# Normal alias
|
||||||
_mem_aliases[alias] = target
|
_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
|
||||||
|
|
|
@ -88,6 +88,8 @@ def addCommonOptions(parser):
|
||||||
parser.add_option("--mem-type", type="choice", default="simple_mem",
|
parser.add_option("--mem-type", type="choice", default="simple_mem",
|
||||||
choices=MemConfig.mem_names(),
|
choices=MemConfig.mem_names(),
|
||||||
help = "type of memory to use")
|
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",
|
parser.add_option("--mem-size", action="store", type="string",
|
||||||
default="512MB",
|
default="512MB",
|
||||||
help="Specify the physical memory size (single memory)")
|
help="Specify the physical memory size (single memory)")
|
||||||
|
|
|
@ -53,6 +53,7 @@ from SysPaths import *
|
||||||
from Benchmarks import *
|
from Benchmarks import *
|
||||||
import Simulation
|
import Simulation
|
||||||
import CacheConfig
|
import CacheConfig
|
||||||
|
import MemConfig
|
||||||
from Caches import *
|
from Caches import *
|
||||||
import Options
|
import Options
|
||||||
|
|
||||||
|
@ -171,12 +172,7 @@ for i in xrange(np):
|
||||||
test_sys.cpu[i].createThreads()
|
test_sys.cpu[i].createThreads()
|
||||||
|
|
||||||
CacheConfig.config_cache(options, test_sys)
|
CacheConfig.config_cache(options, test_sys)
|
||||||
|
MemConfig.config_mem(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
|
|
||||||
|
|
||||||
if len(bm) == 2:
|
if len(bm) == 2:
|
||||||
if buildEnv['TARGET_ISA'] == 'alpha':
|
if buildEnv['TARGET_ISA'] == 'alpha':
|
||||||
|
|
|
@ -58,6 +58,7 @@ import Options
|
||||||
import Ruby
|
import Ruby
|
||||||
import Simulation
|
import Simulation
|
||||||
import CacheConfig
|
import CacheConfig
|
||||||
|
import MemConfig
|
||||||
from Caches import *
|
from Caches import *
|
||||||
from cpu2000 import *
|
from cpu2000 import *
|
||||||
|
|
||||||
|
@ -157,8 +158,8 @@ if options.smt and options.num_cpus > 1:
|
||||||
|
|
||||||
np = options.num_cpus
|
np = options.num_cpus
|
||||||
system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
|
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_mode = test_mem_mode,
|
||||||
|
mem_ranges = [AddrRange(options.mem_size)],
|
||||||
cache_line_size = options.cacheline_size)
|
cache_line_size = options.cacheline_size)
|
||||||
|
|
||||||
# Create a top-level voltage domain
|
# Create a top-level voltage domain
|
||||||
|
@ -221,7 +222,8 @@ if options.ruby:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Set the option for physmem so that it is not allocated any space
|
# 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
|
options.use_map = True
|
||||||
Ruby.create_system(options, system)
|
Ruby.create_system(options, system)
|
||||||
|
@ -247,8 +249,8 @@ if options.ruby:
|
||||||
else:
|
else:
|
||||||
system.membus = CoherentBus()
|
system.membus = CoherentBus()
|
||||||
system.system_port = system.membus.slave
|
system.system_port = system.membus.slave
|
||||||
system.physmem.port = system.membus.master
|
|
||||||
CacheConfig.config_cache(options, system)
|
CacheConfig.config_cache(options, system)
|
||||||
|
MemConfig.config_mem(options, system)
|
||||||
|
|
||||||
root = Root(full_system = False, system = system)
|
root = Root(full_system = False, system = system)
|
||||||
Simulation.run(options, root, system, FutureClass)
|
Simulation.run(options, root, system, FutureClass)
|
||||||
|
|
|
@ -64,38 +64,6 @@ class SimpleDRAM(AbstractMemory):
|
||||||
type = 'SimpleDRAM'
|
type = 'SimpleDRAM'
|
||||||
cxx_header = "mem/simple_dram.hh"
|
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
|
# single-ported on the system interface side, instantiate with a
|
||||||
# bus in front of the controller for multiple ports
|
# bus in front of the controller for multiple ports
|
||||||
port = SlavePort("Slave port")
|
port = SlavePort("Slave port")
|
||||||
|
|
Loading…
Reference in a new issue