MemConfig.py revision 10789
19665Sandreas.hansson@arm.com# Copyright (c) 2013 ARM Limited
29520SN/A# All rights reserved.
39520SN/A#
49520SN/A# The license below extends only to copyright in the software and shall
59520SN/A# not be construed as granting a license to any other intellectual
69520SN/A# property including but not limited to intellectual property relating
79520SN/A# to a hardware implementation of the functionality of the software
89520SN/A# licensed hereunder.  You may use the software subject to the license
99520SN/A# terms below provided that you ensure that this notice is replicated
109520SN/A# unmodified and in its entirety in all distributions of the software,
119520SN/A# modified or unmodified, in source code or in binary form.
129520SN/A#
139520SN/A# Redistribution and use in source and binary forms, with or without
149520SN/A# modification, are permitted provided that the following conditions are
159520SN/A# met: redistributions of source code must retain the above copyright
169520SN/A# notice, this list of conditions and the following disclaimer;
179520SN/A# redistributions in binary form must reproduce the above copyright
189520SN/A# notice, this list of conditions and the following disclaimer in the
199520SN/A# documentation and/or other materials provided with the distribution;
209520SN/A# neither the name of the copyright holders nor the names of its
219520SN/A# contributors may be used to endorse or promote products derived from
229520SN/A# this software without specific prior written permission.
239520SN/A#
249520SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
259520SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
269520SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
279520SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
289520SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
299520SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
309520SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
319520SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
329520SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
339520SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
349520SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
359520SN/A#
369520SN/A# Authors: Andreas Sandberg
379665Sandreas.hansson@arm.com#          Andreas Hansson
389520SN/A
399520SN/Aimport m5.objects
409520SN/Aimport inspect
419520SN/Aimport sys
429520SN/Afrom textwrap import  TextWrapper
439520SN/A
449665Sandreas.hansson@arm.com# Dictionary of mapping names of real memory controller models to
459665Sandreas.hansson@arm.com# classes.
469665Sandreas.hansson@arm.com_mem_classes = {}
479520SN/A
489665Sandreas.hansson@arm.comdef is_mem_class(cls):
499665Sandreas.hansson@arm.com    """Determine if a class is a memory controller that can be instantiated"""
509520SN/A
519520SN/A    # We can't use the normal inspect.isclass because the ParamFactory
529520SN/A    # and ProxyFactory classes have a tendency to confuse it.
539520SN/A    try:
549665Sandreas.hansson@arm.com        return issubclass(cls, m5.objects.AbstractMemory) and \
559665Sandreas.hansson@arm.com            not cls.abstract
569520SN/A    except TypeError:
579520SN/A        return False
589520SN/A
599520SN/Adef get(name):
6010789Sandreas.hansson@arm.com    """Get a memory class from a user provided class name."""
619520SN/A
629520SN/A    try:
6310789Sandreas.hansson@arm.com        mem_class = _mem_classes[name]
649665Sandreas.hansson@arm.com        return mem_class
659520SN/A    except KeyError:
669665Sandreas.hansson@arm.com        print "%s is not a valid memory controller." % (name,)
679520SN/A        sys.exit(1)
689520SN/A
699665Sandreas.hansson@arm.comdef print_mem_list():
7010789Sandreas.hansson@arm.com    """Print a list of available memory classes."""
719520SN/A
729665Sandreas.hansson@arm.com    print "Available memory classes:"
739520SN/A    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
749665Sandreas.hansson@arm.com    for name, cls in _mem_classes.items():
759520SN/A        print "\t%s" % name
769520SN/A
779520SN/A        # Try to extract the class documentation from the class help
789520SN/A        # string.
799520SN/A        doc = inspect.getdoc(cls)
809520SN/A        if doc:
819520SN/A            for line in doc_wrapper.wrap(doc):
829520SN/A                print line
839520SN/A
849665Sandreas.hansson@arm.comdef mem_names():
859665Sandreas.hansson@arm.com    """Return a list of valid memory names."""
8610789Sandreas.hansson@arm.com    return _mem_classes.keys()
879520SN/A
889665Sandreas.hansson@arm.com# Add all memory controllers in the object hierarchy.
899665Sandreas.hansson@arm.comfor name, cls in inspect.getmembers(m5.objects, is_mem_class):
909665Sandreas.hansson@arm.com    _mem_classes[name] = cls
919520SN/A
9210675Sandreas.hansson@arm.comdef create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits, intlv_size):
9310442Snilay@cs.wisc.edu    """
9410442Snilay@cs.wisc.edu    Helper function for creating a single memoy controller from the given
9510442Snilay@cs.wisc.edu    options.  This function is invoked multiple times in config_mem function
9610442Snilay@cs.wisc.edu    to create an array of controllers.
9710442Snilay@cs.wisc.edu    """
9810442Snilay@cs.wisc.edu
9910442Snilay@cs.wisc.edu    import math
10010675Sandreas.hansson@arm.com    intlv_low_bit = int(math.log(intlv_size, 2))
10110442Snilay@cs.wisc.edu
10210677Sandreas.hansson@arm.com    # Use basic hashing for the channel selection, and preferably use
10310677Sandreas.hansson@arm.com    # the lower tag bits from the last level cache. As we do not know
10410677Sandreas.hansson@arm.com    # the details of the caches here, make an educated guess. 4 MByte
10510677Sandreas.hansson@arm.com    # 4-way associative with 64 byte cache lines is 6 offset bits and
10610677Sandreas.hansson@arm.com    # 14 index bits.
10710677Sandreas.hansson@arm.com    xor_low_bit = 20
10810677Sandreas.hansson@arm.com
10910442Snilay@cs.wisc.edu    # Create an instance so we can figure out the address
11010442Snilay@cs.wisc.edu    # mapping and row-buffer size
11110442Snilay@cs.wisc.edu    ctrl = cls()
11210442Snilay@cs.wisc.edu
11310442Snilay@cs.wisc.edu    # Only do this for DRAMs
11410442Snilay@cs.wisc.edu    if issubclass(cls, m5.objects.DRAMCtrl):
11510442Snilay@cs.wisc.edu        # Inform each controller how many channels to account
11610442Snilay@cs.wisc.edu        # for
11710442Snilay@cs.wisc.edu        ctrl.channels = nbr_mem_ctrls
11810442Snilay@cs.wisc.edu
11910442Snilay@cs.wisc.edu        # If the channel bits are appearing after the column
12010442Snilay@cs.wisc.edu        # bits, we need to add the appropriate number of bits
12110442Snilay@cs.wisc.edu        # for the row buffer size
12210442Snilay@cs.wisc.edu        if ctrl.addr_mapping.value == 'RoRaBaChCo':
12310442Snilay@cs.wisc.edu            # This computation only really needs to happen
12410442Snilay@cs.wisc.edu            # once, but as we rely on having an instance we
12510442Snilay@cs.wisc.edu            # end up having to repeat it for each and every
12610442Snilay@cs.wisc.edu            # one
12710442Snilay@cs.wisc.edu            rowbuffer_size = ctrl.device_rowbuffer_size.value * \
12810442Snilay@cs.wisc.edu                ctrl.devices_per_rank.value
12910442Snilay@cs.wisc.edu
13010675Sandreas.hansson@arm.com            intlv_low_bit = int(math.log(rowbuffer_size, 2))
13110442Snilay@cs.wisc.edu
13210442Snilay@cs.wisc.edu    # We got all we need to configure the appropriate address
13310442Snilay@cs.wisc.edu    # range
13410442Snilay@cs.wisc.edu    ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
13510442Snilay@cs.wisc.edu                                      intlvHighBit = \
13610675Sandreas.hansson@arm.com                                          intlv_low_bit + intlv_bits - 1,
13710677Sandreas.hansson@arm.com                                      xorHighBit = \
13810677Sandreas.hansson@arm.com                                          xor_low_bit + intlv_bits - 1,
13910442Snilay@cs.wisc.edu                                      intlvBits = intlv_bits,
14010442Snilay@cs.wisc.edu                                      intlvMatch = i)
14110442Snilay@cs.wisc.edu    return ctrl
14210442Snilay@cs.wisc.edu
1439836Sandreas.hansson@arm.comdef config_mem(options, system):
1449836Sandreas.hansson@arm.com    """
1459836Sandreas.hansson@arm.com    Create the memory controllers based on the options and attach them.
1469836Sandreas.hansson@arm.com
1479836Sandreas.hansson@arm.com    If requested, we make a multi-channel configuration of the
1489836Sandreas.hansson@arm.com    selected memory controller class by creating multiple instances of
1499836Sandreas.hansson@arm.com    the specific class. The individual controllers have their
1509836Sandreas.hansson@arm.com    parameters set such that the address range is interleaved between
1519836Sandreas.hansson@arm.com    them.
1529836Sandreas.hansson@arm.com    """
1539836Sandreas.hansson@arm.com
15410780SCurtis.Dunham@arm.com    if options.external_memory_system:
15510780SCurtis.Dunham@arm.com        system.external_memory = m5.objects.ExternalSlave(
15610780SCurtis.Dunham@arm.com            port_type=options.external_memory_system,
15710780SCurtis.Dunham@arm.com            port_data="init_mem0", port=system.membus.master,
15810780SCurtis.Dunham@arm.com            addr_ranges=system.mem_ranges)
15910780SCurtis.Dunham@arm.com        system.kernel_addr_check = False
16010780SCurtis.Dunham@arm.com        return
16110780SCurtis.Dunham@arm.com
1629836Sandreas.hansson@arm.com    nbr_mem_ctrls = options.mem_channels
1639836Sandreas.hansson@arm.com    import math
1649836Sandreas.hansson@arm.com    from m5.util import fatal
1659836Sandreas.hansson@arm.com    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
1669836Sandreas.hansson@arm.com    if 2 ** intlv_bits != nbr_mem_ctrls:
1679836Sandreas.hansson@arm.com        fatal("Number of memory channels must be a power of 2")
16810442Snilay@cs.wisc.edu
1699836Sandreas.hansson@arm.com    cls = get(options.mem_type)
1709836Sandreas.hansson@arm.com    mem_ctrls = []
1719836Sandreas.hansson@arm.com
17210675Sandreas.hansson@arm.com    # The default behaviour is to interleave memory channels on 128
17310675Sandreas.hansson@arm.com    # byte granularity, or cache line granularity if larger than 128
17410675Sandreas.hansson@arm.com    # byte. This value is based on the locality seen across a large
17510675Sandreas.hansson@arm.com    # range of workloads.
17610675Sandreas.hansson@arm.com    intlv_size = max(128, system.cache_line_size.value)
17710675Sandreas.hansson@arm.com
1789836Sandreas.hansson@arm.com    # For every range (most systems will only have one), create an
1799836Sandreas.hansson@arm.com    # array of controllers and set their parameters to match their
1809836Sandreas.hansson@arm.com    # address mapping in the case of a DRAM
1819836Sandreas.hansson@arm.com    for r in system.mem_ranges:
1829836Sandreas.hansson@arm.com        for i in xrange(nbr_mem_ctrls):
18310620Sandreas.hansson@arm.com            mem_ctrl = create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits,
18410675Sandreas.hansson@arm.com                                       intlv_size)
18510620Sandreas.hansson@arm.com            # Set the number of ranks based on the command-line
18610620Sandreas.hansson@arm.com            # options if it was explicitly set
18710620Sandreas.hansson@arm.com            if issubclass(cls, m5.objects.DRAMCtrl) and \
18810620Sandreas.hansson@arm.com                    options.mem_ranks:
18910620Sandreas.hansson@arm.com                mem_ctrl.ranks_per_channel = options.mem_ranks
19010620Sandreas.hansson@arm.com
19110620Sandreas.hansson@arm.com            mem_ctrls.append(mem_ctrl)
1929836Sandreas.hansson@arm.com
1939836Sandreas.hansson@arm.com    system.mem_ctrls = mem_ctrls
1949836Sandreas.hansson@arm.com
1959836Sandreas.hansson@arm.com    # Connect the controllers to the membus
19610041Snilay@cs.wisc.edu    for i in xrange(len(system.mem_ctrls)):
1979836Sandreas.hansson@arm.com        system.mem_ctrls[i].port = system.membus.master
198