MemConfig.py revision 9836
12929Sktlim@umich.edu# Copyright (c) 2013 ARM Limited
22929Sktlim@umich.edu# All rights reserved.
32932Sktlim@umich.edu#
42929Sktlim@umich.edu# The license below extends only to copyright in the software and shall
52929Sktlim@umich.edu# not be construed as granting a license to any other intellectual
62929Sktlim@umich.edu# property including but not limited to intellectual property relating
72929Sktlim@umich.edu# to a hardware implementation of the functionality of the software
82929Sktlim@umich.edu# licensed hereunder.  You may use the software subject to the license
92929Sktlim@umich.edu# terms below provided that you ensure that this notice is replicated
102929Sktlim@umich.edu# unmodified and in its entirety in all distributions of the software,
112929Sktlim@umich.edu# modified or unmodified, in source code or in binary form.
122929Sktlim@umich.edu#
132929Sktlim@umich.edu# Redistribution and use in source and binary forms, with or without
142929Sktlim@umich.edu# modification, are permitted provided that the following conditions are
152929Sktlim@umich.edu# met: redistributions of source code must retain the above copyright
162929Sktlim@umich.edu# notice, this list of conditions and the following disclaimer;
172929Sktlim@umich.edu# redistributions in binary form must reproduce the above copyright
182929Sktlim@umich.edu# notice, this list of conditions and the following disclaimer in the
192929Sktlim@umich.edu# documentation and/or other materials provided with the distribution;
202929Sktlim@umich.edu# neither the name of the copyright holders nor the names of its
212929Sktlim@umich.edu# contributors may be used to endorse or promote products derived from
222929Sktlim@umich.edu# this software without specific prior written permission.
232929Sktlim@umich.edu#
242929Sktlim@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
252929Sktlim@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
262929Sktlim@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
272929Sktlim@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
282932Sktlim@umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
292932Sktlim@umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
302932Sktlim@umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
312929Sktlim@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
326007Ssteve.reinhardt@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
337735SAli.Saidi@ARM.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
342929Sktlim@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352929Sktlim@umich.edu#
362929Sktlim@umich.edu# Authors: Andreas Sandberg
372929Sktlim@umich.edu#          Andreas Hansson
382929Sktlim@umich.edu
392929Sktlim@umich.eduimport m5.objects
402929Sktlim@umich.eduimport inspect
418947Sandreas.hansson@arm.comimport sys
428947Sandreas.hansson@arm.comfrom textwrap import  TextWrapper
438947Sandreas.hansson@arm.com
442929Sktlim@umich.edu# Dictionary of mapping names of real memory controller models to
452929Sktlim@umich.edu# classes.
462929Sktlim@umich.edu_mem_classes = {}
472929Sktlim@umich.edu
482929Sktlim@umich.edu# Memory aliases. We make sure they exist before we add them to the
492929Sktlim@umich.edu# fina; list. A target may be specified as a tuple, in which case the
506007Ssteve.reinhardt@amd.com# first available memory controller model in the tuple will be used.
516007Ssteve.reinhardt@amd.com_mem_aliases_all = [
526007Ssteve.reinhardt@amd.com    ("simple_mem", "SimpleMemory"),
536007Ssteve.reinhardt@amd.com    ("ddr3_1600_x64", "DDR3_1600_x64"),
546007Ssteve.reinhardt@amd.com    ("lpddr2_s4_1066_x32", "LPDDR2_S4_1066_x32"),
556007Ssteve.reinhardt@amd.com    ("lpddr3_1600_x32", "LPDDR3_1600_x32"),
566007Ssteve.reinhardt@amd.com    ("wio_200_x128", "WideIO_200_x128"),
576007Ssteve.reinhardt@amd.com    ]
586007Ssteve.reinhardt@amd.com
596007Ssteve.reinhardt@amd.com# Filtered list of aliases. Only aliases for existing memory
606007Ssteve.reinhardt@amd.com# controllers exist in this list.
616007Ssteve.reinhardt@amd.com_mem_aliases = {}
626007Ssteve.reinhardt@amd.com
636007Ssteve.reinhardt@amd.com
646007Ssteve.reinhardt@amd.comdef is_mem_class(cls):
656007Ssteve.reinhardt@amd.com    """Determine if a class is a memory controller that can be instantiated"""
669435SAndreas.Sandberg@ARM.com
679435SAndreas.Sandberg@ARM.com    # We can't use the normal inspect.isclass because the ParamFactory
689435SAndreas.Sandberg@ARM.com    # and ProxyFactory classes have a tendency to confuse it.
696007Ssteve.reinhardt@amd.com    try:
706007Ssteve.reinhardt@amd.com        return issubclass(cls, m5.objects.AbstractMemory) and \
716007Ssteve.reinhardt@amd.com            not cls.abstract
726007Ssteve.reinhardt@amd.com    except TypeError:
736007Ssteve.reinhardt@amd.com        return False
746007Ssteve.reinhardt@amd.com
756007Ssteve.reinhardt@amd.comdef get(name):
766007Ssteve.reinhardt@amd.com    """Get a memory class from a user provided class name or alias."""
776007Ssteve.reinhardt@amd.com
786007Ssteve.reinhardt@amd.com    real_name = _mem_aliases.get(name, name)
792929Sktlim@umich.edu
802929Sktlim@umich.edu    try:
812929Sktlim@umich.edu        mem_class = _mem_classes[real_name]
826007Ssteve.reinhardt@amd.com        return mem_class
836007Ssteve.reinhardt@amd.com    except KeyError:
846007Ssteve.reinhardt@amd.com        print "%s is not a valid memory controller." % (name,)
859781Sandreas.hansson@arm.com        sys.exit(1)
866007Ssteve.reinhardt@amd.com
876007Ssteve.reinhardt@amd.comdef print_mem_list():
882929Sktlim@umich.edu    """Print a list of available memory classes including their aliases."""
892929Sktlim@umich.edu
902929Sktlim@umich.edu    print "Available memory classes:"
912929Sktlim@umich.edu    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
922929Sktlim@umich.edu    for name, cls in _mem_classes.items():
936011Ssteve.reinhardt@amd.com        print "\t%s" % name
946007Ssteve.reinhardt@amd.com
956007Ssteve.reinhardt@amd.com        # Try to extract the class documentation from the class help
966007Ssteve.reinhardt@amd.com        # string.
976007Ssteve.reinhardt@amd.com        doc = inspect.getdoc(cls)
986007Ssteve.reinhardt@amd.com        if doc:
996007Ssteve.reinhardt@amd.com            for line in doc_wrapper.wrap(doc):
1006007Ssteve.reinhardt@amd.com                print line
1016007Ssteve.reinhardt@amd.com
1026007Ssteve.reinhardt@amd.com    if _mem_aliases:
1036007Ssteve.reinhardt@amd.com        print "\nMemory aliases:"
1046007Ssteve.reinhardt@amd.com        for alias, target in _mem_aliases.items():
1056007Ssteve.reinhardt@amd.com            print "\t%s => %s" % (alias, target)
1066007Ssteve.reinhardt@amd.com
10710384SCurtis.Dunham@arm.comdef mem_names():
10810384SCurtis.Dunham@arm.com    """Return a list of valid memory names."""
10910384SCurtis.Dunham@arm.com    return _mem_classes.keys() + _mem_aliases.keys()
11010384SCurtis.Dunham@arm.com
1116007Ssteve.reinhardt@amd.com# Add all memory controllers in the object hierarchy.
1129781Sandreas.hansson@arm.comfor name, cls in inspect.getmembers(m5.objects, is_mem_class):
1139781Sandreas.hansson@arm.com    _mem_classes[name] = cls
1149781Sandreas.hansson@arm.com
1159781Sandreas.hansson@arm.comfor alias, target in _mem_aliases_all:
1167735SAli.Saidi@ARM.com    if isinstance(target, tuple):
1176011Ssteve.reinhardt@amd.com        # Some aliases contain a list of memory controller models
1186007Ssteve.reinhardt@amd.com        # sorted in priority order. Use the first target that's
1199781Sandreas.hansson@arm.com        # available.
1206007Ssteve.reinhardt@amd.com        for t in target:
1216007Ssteve.reinhardt@amd.com            if t in _mem_classes:
1227735SAli.Saidi@ARM.com                _mem_aliases[alias] = t
1237735SAli.Saidi@ARM.com                break
1247735SAli.Saidi@ARM.com    elif target in _mem_classes:
1257735SAli.Saidi@ARM.com        # Normal alias
1267735SAli.Saidi@ARM.com        _mem_aliases[alias] = target
1277735SAli.Saidi@ARM.com
1287735SAli.Saidi@ARM.comdef config_mem(options, system):
1297735SAli.Saidi@ARM.com    """
1307735SAli.Saidi@ARM.com    Create the memory controllers based on the options and attach them.
1317735SAli.Saidi@ARM.com
1327735SAli.Saidi@ARM.com    If requested, we make a multi-channel configuration of the
1337735SAli.Saidi@ARM.com    selected memory controller class by creating multiple instances of
1347735SAli.Saidi@ARM.com    the specific class. The individual controllers have their
1357735SAli.Saidi@ARM.com    parameters set such that the address range is interleaved between
1366007Ssteve.reinhardt@amd.com    them.
1378599Ssteve.reinhardt@amd.com    """
1388599Ssteve.reinhardt@amd.com
1398599Ssteve.reinhardt@amd.com    nbr_mem_ctrls = options.mem_channels
1406007Ssteve.reinhardt@amd.com    import math
1416011Ssteve.reinhardt@amd.com    from m5.util import fatal
1426007Ssteve.reinhardt@amd.com    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
1436007Ssteve.reinhardt@amd.com    if 2 ** intlv_bits != nbr_mem_ctrls:
1446007Ssteve.reinhardt@amd.com        fatal("Number of memory channels must be a power of 2")
1456007Ssteve.reinhardt@amd.com    cls = get(options.mem_type)
1466007Ssteve.reinhardt@amd.com    mem_ctrls = []
1476007Ssteve.reinhardt@amd.com
1489781Sandreas.hansson@arm.com    # The default behaviour is to interleave on cache line granularity
1499781Sandreas.hansson@arm.com    cache_line_bit = int(math.log(system.cache_line_size.value, 2)) - 1
1509781Sandreas.hansson@arm.com    intlv_low_bit = cache_line_bit
1519781Sandreas.hansson@arm.com
1526007Ssteve.reinhardt@amd.com    # For every range (most systems will only have one), create an
1536007Ssteve.reinhardt@amd.com    # array of controllers and set their parameters to match their
1546007Ssteve.reinhardt@amd.com    # address mapping in the case of a DRAM
1559781Sandreas.hansson@arm.com    for r in system.mem_ranges:
1569781Sandreas.hansson@arm.com        for i in xrange(nbr_mem_ctrls):
1579781Sandreas.hansson@arm.com            # Create an instance so we can figure out the address
1589781Sandreas.hansson@arm.com            # mapping and row-buffer size
15910384SCurtis.Dunham@arm.com            ctrl = cls()
16010384SCurtis.Dunham@arm.com
16110384SCurtis.Dunham@arm.com            # Only do this for DRAMs
1629781Sandreas.hansson@arm.com            if issubclass(cls, m5.objects.SimpleDRAM):
1636008Ssteve.reinhardt@amd.com                # Inform each controller how many channels to account
1646008Ssteve.reinhardt@amd.com                # for
1656008Ssteve.reinhardt@amd.com                ctrl.channels = nbr_mem_ctrls
1666008Ssteve.reinhardt@amd.com
1676008Ssteve.reinhardt@amd.com                # If the channel bits are appearing after the column
1689401SAndreas.Sandberg@ARM.com                # bits, we need to add the appropriate number of bits
1699781Sandreas.hansson@arm.com                # for the row buffer size
1709781Sandreas.hansson@arm.com                if ctrl.addr_mapping.value == 'RaBaChCo':
1716008Ssteve.reinhardt@amd.com                    # This computation only really needs to happen
1729781Sandreas.hansson@arm.com                    # once, but as we rely on having an instance we
1736007Ssteve.reinhardt@amd.com                    # end up having to repeat it for each and every
1746007Ssteve.reinhardt@amd.com                    # one
1756007Ssteve.reinhardt@amd.com                    rowbuffer_size = ctrl.device_rowbuffer_size.value * \
1766007Ssteve.reinhardt@amd.com                        ctrl.devices_per_rank.value
1779781Sandreas.hansson@arm.com
1786007Ssteve.reinhardt@amd.com                    intlv_low_bit = int(math.log(rowbuffer_size, 2)) - 1
1796007Ssteve.reinhardt@amd.com
1802929Sktlim@umich.edu            # We got all we need to configure the appropriate address
1812929Sktlim@umich.edu            # range
1822929Sktlim@umich.edu            ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
1832929Sktlim@umich.edu                                              intlvHighBit = \
1846007Ssteve.reinhardt@amd.com                                                  intlv_low_bit + intlv_bits,
1856007Ssteve.reinhardt@amd.com                                              intlvBits = intlv_bits,
1862929Sktlim@umich.edu                                              intlvMatch = i)
1872929Sktlim@umich.edu            mem_ctrls.append(ctrl)
1886007Ssteve.reinhardt@amd.com
1892929Sktlim@umich.edu    system.mem_ctrls = mem_ctrls
1902929Sktlim@umich.edu
1918947Sandreas.hansson@arm.com    # Connect the controllers to the membus
1928947Sandreas.hansson@arm.com    for i in xrange(nbr_mem_ctrls):
1938947Sandreas.hansson@arm.com        system.mem_ctrls[i].port = system.membus.master
1948947Sandreas.hansson@arm.com