MemConfig.py revision 12094
112094Sandreas.sandberg@arm.com# Copyright (c) 2013, 2017 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
4211183Serfan.azarkhish@unibo.itimport HMC
439520SN/Afrom textwrap import  TextWrapper
449520SN/A
459665Sandreas.hansson@arm.com# Dictionary of mapping names of real memory controller models to
469665Sandreas.hansson@arm.com# classes.
479665Sandreas.hansson@arm.com_mem_classes = {}
489520SN/A
499665Sandreas.hansson@arm.comdef is_mem_class(cls):
509665Sandreas.hansson@arm.com    """Determine if a class is a memory controller that can be instantiated"""
519520SN/A
529520SN/A    # We can't use the normal inspect.isclass because the ParamFactory
539520SN/A    # and ProxyFactory classes have a tendency to confuse it.
549520SN/A    try:
559665Sandreas.hansson@arm.com        return issubclass(cls, m5.objects.AbstractMemory) and \
569665Sandreas.hansson@arm.com            not cls.abstract
579520SN/A    except TypeError:
589520SN/A        return False
599520SN/A
609520SN/Adef get(name):
6110789Sandreas.hansson@arm.com    """Get a memory class from a user provided class name."""
629520SN/A
639520SN/A    try:
6410789Sandreas.hansson@arm.com        mem_class = _mem_classes[name]
659665Sandreas.hansson@arm.com        return mem_class
669520SN/A    except KeyError:
679665Sandreas.hansson@arm.com        print "%s is not a valid memory controller." % (name,)
689520SN/A        sys.exit(1)
699520SN/A
709665Sandreas.hansson@arm.comdef print_mem_list():
7110789Sandreas.hansson@arm.com    """Print a list of available memory classes."""
729520SN/A
739665Sandreas.hansson@arm.com    print "Available memory classes:"
749520SN/A    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
759665Sandreas.hansson@arm.com    for name, cls in _mem_classes.items():
769520SN/A        print "\t%s" % name
779520SN/A
789520SN/A        # Try to extract the class documentation from the class help
799520SN/A        # string.
809520SN/A        doc = inspect.getdoc(cls)
819520SN/A        if doc:
829520SN/A            for line in doc_wrapper.wrap(doc):
839520SN/A                print line
849520SN/A
859665Sandreas.hansson@arm.comdef mem_names():
869665Sandreas.hansson@arm.com    """Return a list of valid memory names."""
8710789Sandreas.hansson@arm.com    return _mem_classes.keys()
889520SN/A
899665Sandreas.hansson@arm.com# Add all memory controllers in the object hierarchy.
909665Sandreas.hansson@arm.comfor name, cls in inspect.getmembers(m5.objects, is_mem_class):
919665Sandreas.hansson@arm.com    _mem_classes[name] = cls
929520SN/A
9310675Sandreas.hansson@arm.comdef create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits, intlv_size):
9410442Snilay@cs.wisc.edu    """
9510442Snilay@cs.wisc.edu    Helper function for creating a single memoy controller from the given
9610442Snilay@cs.wisc.edu    options.  This function is invoked multiple times in config_mem function
9710442Snilay@cs.wisc.edu    to create an array of controllers.
9810442Snilay@cs.wisc.edu    """
9910442Snilay@cs.wisc.edu
10010442Snilay@cs.wisc.edu    import math
10110675Sandreas.hansson@arm.com    intlv_low_bit = int(math.log(intlv_size, 2))
10210442Snilay@cs.wisc.edu
10310677Sandreas.hansson@arm.com    # Use basic hashing for the channel selection, and preferably use
10410677Sandreas.hansson@arm.com    # the lower tag bits from the last level cache. As we do not know
10510677Sandreas.hansson@arm.com    # the details of the caches here, make an educated guess. 4 MByte
10610677Sandreas.hansson@arm.com    # 4-way associative with 64 byte cache lines is 6 offset bits and
10710677Sandreas.hansson@arm.com    # 14 index bits.
10810677Sandreas.hansson@arm.com    xor_low_bit = 20
10910677Sandreas.hansson@arm.com
11010442Snilay@cs.wisc.edu    # Create an instance so we can figure out the address
11110442Snilay@cs.wisc.edu    # mapping and row-buffer size
11210442Snilay@cs.wisc.edu    ctrl = cls()
11310442Snilay@cs.wisc.edu
11410442Snilay@cs.wisc.edu    # Only do this for DRAMs
11510442Snilay@cs.wisc.edu    if issubclass(cls, m5.objects.DRAMCtrl):
11610442Snilay@cs.wisc.edu        # Inform each controller how many channels to account
11710442Snilay@cs.wisc.edu        # for
11810442Snilay@cs.wisc.edu        ctrl.channels = nbr_mem_ctrls
11910442Snilay@cs.wisc.edu
12010442Snilay@cs.wisc.edu        # If the channel bits are appearing after the column
12110442Snilay@cs.wisc.edu        # bits, we need to add the appropriate number of bits
12210442Snilay@cs.wisc.edu        # for the row buffer size
12310442Snilay@cs.wisc.edu        if ctrl.addr_mapping.value == 'RoRaBaChCo':
12410442Snilay@cs.wisc.edu            # This computation only really needs to happen
12510442Snilay@cs.wisc.edu            # once, but as we rely on having an instance we
12610442Snilay@cs.wisc.edu            # end up having to repeat it for each and every
12710442Snilay@cs.wisc.edu            # one
12810442Snilay@cs.wisc.edu            rowbuffer_size = ctrl.device_rowbuffer_size.value * \
12910442Snilay@cs.wisc.edu                ctrl.devices_per_rank.value
13010442Snilay@cs.wisc.edu
13110675Sandreas.hansson@arm.com            intlv_low_bit = int(math.log(rowbuffer_size, 2))
13210442Snilay@cs.wisc.edu
13310442Snilay@cs.wisc.edu    # We got all we need to configure the appropriate address
13410442Snilay@cs.wisc.edu    # range
13510442Snilay@cs.wisc.edu    ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
13610442Snilay@cs.wisc.edu                                      intlvHighBit = \
13710675Sandreas.hansson@arm.com                                          intlv_low_bit + intlv_bits - 1,
13810677Sandreas.hansson@arm.com                                      xorHighBit = \
13910677Sandreas.hansson@arm.com                                          xor_low_bit + intlv_bits - 1,
14010442Snilay@cs.wisc.edu                                      intlvBits = intlv_bits,
14110442Snilay@cs.wisc.edu                                      intlvMatch = i)
14210442Snilay@cs.wisc.edu    return ctrl
14310442Snilay@cs.wisc.edu
1449836Sandreas.hansson@arm.comdef config_mem(options, system):
1459836Sandreas.hansson@arm.com    """
1469836Sandreas.hansson@arm.com    Create the memory controllers based on the options and attach them.
1479836Sandreas.hansson@arm.com
1489836Sandreas.hansson@arm.com    If requested, we make a multi-channel configuration of the
1499836Sandreas.hansson@arm.com    selected memory controller class by creating multiple instances of
1509836Sandreas.hansson@arm.com    the specific class. The individual controllers have their
1519836Sandreas.hansson@arm.com    parameters set such that the address range is interleaved between
1529836Sandreas.hansson@arm.com    them.
1539836Sandreas.hansson@arm.com    """
1549836Sandreas.hansson@arm.com
15512094Sandreas.sandberg@arm.com    # Mandatory options
15612094Sandreas.sandberg@arm.com    opt_mem_type = options.mem_type
15712094Sandreas.sandberg@arm.com    opt_mem_channels = options.mem_channels
15812094Sandreas.sandberg@arm.com
15912094Sandreas.sandberg@arm.com    # Optional options
16012094Sandreas.sandberg@arm.com    opt_tlm_memory = getattr(options, "tlm_memory", None)
16112094Sandreas.sandberg@arm.com    opt_external_memory_system = getattr(options, "external_memory_system",
16212094Sandreas.sandberg@arm.com                                         None)
16312094Sandreas.sandberg@arm.com    opt_elastic_trace_en = getattr(options, "elastic_trace_en", False)
16412094Sandreas.sandberg@arm.com    opt_mem_ranks = getattr(options, "mem_ranks", None)
16512094Sandreas.sandberg@arm.com
16612094Sandreas.sandberg@arm.com    if opt_mem_type == "HMC_2500_1x32":
16711551Sabdul.mutaal@gmail.com        HMChost = HMC.config_host_hmc(options, system)
16811551Sabdul.mutaal@gmail.com        HMC.config_hmc(options, system, HMChost.hmc_host)
16911551Sabdul.mutaal@gmail.com        subsystem = system.hmc_dev
17011551Sabdul.mutaal@gmail.com        xbar = system.hmc_dev.xbar
17111183Serfan.azarkhish@unibo.it    else:
17211183Serfan.azarkhish@unibo.it        subsystem = system
17311183Serfan.azarkhish@unibo.it        xbar = system.membus
17411183Serfan.azarkhish@unibo.it
17512094Sandreas.sandberg@arm.com    if opt_tlm_memory:
17610993Sjungma@eit.uni-kl.de        system.external_memory = m5.objects.ExternalSlave(
17711818SChristian.Menard@tu-dresden.de            port_type="tlm_slave",
17812094Sandreas.sandberg@arm.com            port_data=opt_tlm_memory,
17910993Sjungma@eit.uni-kl.de            port=system.membus.master,
18010993Sjungma@eit.uni-kl.de            addr_ranges=system.mem_ranges)
18110993Sjungma@eit.uni-kl.de        system.kernel_addr_check = False
18210993Sjungma@eit.uni-kl.de        return
18310993Sjungma@eit.uni-kl.de
18412094Sandreas.sandberg@arm.com    if opt_external_memory_system:
18511183Serfan.azarkhish@unibo.it        subsystem.external_memory = m5.objects.ExternalSlave(
18612094Sandreas.sandberg@arm.com            port_type=opt_external_memory_system,
18711183Serfan.azarkhish@unibo.it            port_data="init_mem0", port=xbar.master,
18810780SCurtis.Dunham@arm.com            addr_ranges=system.mem_ranges)
18911183Serfan.azarkhish@unibo.it        subsystem.kernel_addr_check = False
19010780SCurtis.Dunham@arm.com        return
19110780SCurtis.Dunham@arm.com
19212094Sandreas.sandberg@arm.com    nbr_mem_ctrls = opt_mem_channels
1939836Sandreas.hansson@arm.com    import math
1949836Sandreas.hansson@arm.com    from m5.util import fatal
1959836Sandreas.hansson@arm.com    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
1969836Sandreas.hansson@arm.com    if 2 ** intlv_bits != nbr_mem_ctrls:
1979836Sandreas.hansson@arm.com        fatal("Number of memory channels must be a power of 2")
19810442Snilay@cs.wisc.edu
19912094Sandreas.sandberg@arm.com    cls = get(opt_mem_type)
2009836Sandreas.hansson@arm.com    mem_ctrls = []
2019836Sandreas.hansson@arm.com
20212094Sandreas.sandberg@arm.com    if opt_elastic_trace_en and not issubclass(cls, m5.objects.SimpleMemory):
20311251Sradhika.jagtap@ARM.com        fatal("When elastic trace is enabled, configure mem-type as "
20411251Sradhika.jagtap@ARM.com                "simple-mem.")
20511251Sradhika.jagtap@ARM.com
20610675Sandreas.hansson@arm.com    # The default behaviour is to interleave memory channels on 128
20710675Sandreas.hansson@arm.com    # byte granularity, or cache line granularity if larger than 128
20810675Sandreas.hansson@arm.com    # byte. This value is based on the locality seen across a large
20910675Sandreas.hansson@arm.com    # range of workloads.
21010675Sandreas.hansson@arm.com    intlv_size = max(128, system.cache_line_size.value)
21110675Sandreas.hansson@arm.com
2129836Sandreas.hansson@arm.com    # For every range (most systems will only have one), create an
2139836Sandreas.hansson@arm.com    # array of controllers and set their parameters to match their
2149836Sandreas.hansson@arm.com    # address mapping in the case of a DRAM
2159836Sandreas.hansson@arm.com    for r in system.mem_ranges:
2169836Sandreas.hansson@arm.com        for i in xrange(nbr_mem_ctrls):
21710620Sandreas.hansson@arm.com            mem_ctrl = create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits,
21810675Sandreas.hansson@arm.com                                       intlv_size)
21910620Sandreas.hansson@arm.com            # Set the number of ranks based on the command-line
22010620Sandreas.hansson@arm.com            # options if it was explicitly set
22112094Sandreas.sandberg@arm.com            if issubclass(cls, m5.objects.DRAMCtrl) and opt_mem_ranks:
22212094Sandreas.sandberg@arm.com                mem_ctrl.ranks_per_channel = opt_mem_ranks
22310620Sandreas.hansson@arm.com
22412094Sandreas.sandberg@arm.com            if opt_elastic_trace_en:
22511251Sradhika.jagtap@ARM.com                mem_ctrl.latency = '1ns'
22611251Sradhika.jagtap@ARM.com                print "For elastic trace, over-riding Simple Memory " \
22711251Sradhika.jagtap@ARM.com                    "latency to 1ns."
22811251Sradhika.jagtap@ARM.com
22910620Sandreas.hansson@arm.com            mem_ctrls.append(mem_ctrl)
2309836Sandreas.hansson@arm.com
23111183Serfan.azarkhish@unibo.it    subsystem.mem_ctrls = mem_ctrls
2329836Sandreas.hansson@arm.com
2339836Sandreas.hansson@arm.com    # Connect the controllers to the membus
23411183Serfan.azarkhish@unibo.it    for i in xrange(len(subsystem.mem_ctrls)):
23512094Sandreas.sandberg@arm.com        if opt_mem_type == "HMC_2500_1x32":
23611551Sabdul.mutaal@gmail.com            subsystem.mem_ctrls[i].port = xbar[i/4].master
23711551Sabdul.mutaal@gmail.com        else:
23811551Sabdul.mutaal@gmail.com            subsystem.mem_ctrls[i].port = xbar.master
239