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
3912564Sgabeblack@google.comfrom __future__ import print_function
4013774Sandreas.sandberg@arm.comfrom __future__ import absolute_import
4112564Sgabeblack@google.com
429520SN/Aimport m5.objects
439520SN/Aimport inspect
449520SN/Aimport sys
459520SN/Afrom textwrap import  TextWrapper
4613774Sandreas.sandberg@arm.comfrom . import HMC
479520SN/A
489665Sandreas.hansson@arm.com# Dictionary of mapping names of real memory controller models to
499665Sandreas.hansson@arm.com# classes.
509665Sandreas.hansson@arm.com_mem_classes = {}
519520SN/A
529665Sandreas.hansson@arm.comdef is_mem_class(cls):
539665Sandreas.hansson@arm.com    """Determine if a class is a memory controller that can be instantiated"""
549520SN/A
559520SN/A    # We can't use the normal inspect.isclass because the ParamFactory
569520SN/A    # and ProxyFactory classes have a tendency to confuse it.
579520SN/A    try:
589665Sandreas.hansson@arm.com        return issubclass(cls, m5.objects.AbstractMemory) and \
599665Sandreas.hansson@arm.com            not cls.abstract
609520SN/A    except TypeError:
619520SN/A        return False
629520SN/A
639520SN/Adef get(name):
6410789Sandreas.hansson@arm.com    """Get a memory class from a user provided class name."""
659520SN/A
669520SN/A    try:
6710789Sandreas.hansson@arm.com        mem_class = _mem_classes[name]
689665Sandreas.hansson@arm.com        return mem_class
699520SN/A    except KeyError:
7012564Sgabeblack@google.com        print("%s is not a valid memory controller." % (name,))
719520SN/A        sys.exit(1)
729520SN/A
739665Sandreas.hansson@arm.comdef print_mem_list():
7410789Sandreas.hansson@arm.com    """Print a list of available memory classes."""
759520SN/A
7612564Sgabeblack@google.com    print("Available memory classes:")
779520SN/A    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
789665Sandreas.hansson@arm.com    for name, cls in _mem_classes.items():
7912564Sgabeblack@google.com        print("\t%s" % name)
809520SN/A
819520SN/A        # Try to extract the class documentation from the class help
829520SN/A        # string.
839520SN/A        doc = inspect.getdoc(cls)
849520SN/A        if doc:
859520SN/A            for line in doc_wrapper.wrap(doc):
8612564Sgabeblack@google.com                print(line)
879520SN/A
889665Sandreas.hansson@arm.comdef mem_names():
899665Sandreas.hansson@arm.com    """Return a list of valid memory names."""
9013731Sandreas.sandberg@arm.com    return list(_mem_classes.keys())
919520SN/A
929665Sandreas.hansson@arm.com# Add all memory controllers in the object hierarchy.
939665Sandreas.hansson@arm.comfor name, cls in inspect.getmembers(m5.objects, is_mem_class):
949665Sandreas.hansson@arm.com    _mem_classes[name] = cls
959520SN/A
9610675Sandreas.hansson@arm.comdef create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits, intlv_size):
9710442Snilay@cs.wisc.edu    """
9810442Snilay@cs.wisc.edu    Helper function for creating a single memoy controller from the given
9910442Snilay@cs.wisc.edu    options.  This function is invoked multiple times in config_mem function
10010442Snilay@cs.wisc.edu    to create an array of controllers.
10110442Snilay@cs.wisc.edu    """
10210442Snilay@cs.wisc.edu
10310442Snilay@cs.wisc.edu    import math
10410675Sandreas.hansson@arm.com    intlv_low_bit = int(math.log(intlv_size, 2))
10510442Snilay@cs.wisc.edu
10610677Sandreas.hansson@arm.com    # Use basic hashing for the channel selection, and preferably use
10710677Sandreas.hansson@arm.com    # the lower tag bits from the last level cache. As we do not know
10810677Sandreas.hansson@arm.com    # the details of the caches here, make an educated guess. 4 MByte
10910677Sandreas.hansson@arm.com    # 4-way associative with 64 byte cache lines is 6 offset bits and
11010677Sandreas.hansson@arm.com    # 14 index bits.
11110677Sandreas.hansson@arm.com    xor_low_bit = 20
11210677Sandreas.hansson@arm.com
11310442Snilay@cs.wisc.edu    # Create an instance so we can figure out the address
11410442Snilay@cs.wisc.edu    # mapping and row-buffer size
11510442Snilay@cs.wisc.edu    ctrl = cls()
11610442Snilay@cs.wisc.edu
11710442Snilay@cs.wisc.edu    # Only do this for DRAMs
11810442Snilay@cs.wisc.edu    if issubclass(cls, m5.objects.DRAMCtrl):
11910442Snilay@cs.wisc.edu        # Inform each controller how many channels to account
12010442Snilay@cs.wisc.edu        # for
12110442Snilay@cs.wisc.edu        ctrl.channels = nbr_mem_ctrls
12210442Snilay@cs.wisc.edu
12310442Snilay@cs.wisc.edu        # If the channel bits are appearing after the column
12410442Snilay@cs.wisc.edu        # bits, we need to add the appropriate number of bits
12510442Snilay@cs.wisc.edu        # for the row buffer size
12610442Snilay@cs.wisc.edu        if ctrl.addr_mapping.value == 'RoRaBaChCo':
12710442Snilay@cs.wisc.edu            # This computation only really needs to happen
12810442Snilay@cs.wisc.edu            # once, but as we rely on having an instance we
12910442Snilay@cs.wisc.edu            # end up having to repeat it for each and every
13010442Snilay@cs.wisc.edu            # one
13110442Snilay@cs.wisc.edu            rowbuffer_size = ctrl.device_rowbuffer_size.value * \
13210442Snilay@cs.wisc.edu                ctrl.devices_per_rank.value
13310442Snilay@cs.wisc.edu
13410675Sandreas.hansson@arm.com            intlv_low_bit = int(math.log(rowbuffer_size, 2))
13510442Snilay@cs.wisc.edu
13610442Snilay@cs.wisc.edu    # We got all we need to configure the appropriate address
13710442Snilay@cs.wisc.edu    # range
13810442Snilay@cs.wisc.edu    ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
13910442Snilay@cs.wisc.edu                                      intlvHighBit = \
14010675Sandreas.hansson@arm.com                                          intlv_low_bit + intlv_bits - 1,
14110677Sandreas.hansson@arm.com                                      xorHighBit = \
14210677Sandreas.hansson@arm.com                                          xor_low_bit + intlv_bits - 1,
14310442Snilay@cs.wisc.edu                                      intlvBits = intlv_bits,
14410442Snilay@cs.wisc.edu                                      intlvMatch = i)
14510442Snilay@cs.wisc.edu    return ctrl
14610442Snilay@cs.wisc.edu
1479836Sandreas.hansson@arm.comdef config_mem(options, system):
1489836Sandreas.hansson@arm.com    """
1499836Sandreas.hansson@arm.com    Create the memory controllers based on the options and attach them.
1509836Sandreas.hansson@arm.com
1519836Sandreas.hansson@arm.com    If requested, we make a multi-channel configuration of the
1529836Sandreas.hansson@arm.com    selected memory controller class by creating multiple instances of
1539836Sandreas.hansson@arm.com    the specific class. The individual controllers have their
1549836Sandreas.hansson@arm.com    parameters set such that the address range is interleaved between
1559836Sandreas.hansson@arm.com    them.
1569836Sandreas.hansson@arm.com    """
1579836Sandreas.hansson@arm.com
15812094Sandreas.sandberg@arm.com    # Mandatory options
15912094Sandreas.sandberg@arm.com    opt_mem_type = options.mem_type
16012094Sandreas.sandberg@arm.com    opt_mem_channels = options.mem_channels
16112094Sandreas.sandberg@arm.com
16212094Sandreas.sandberg@arm.com    # Optional options
16312094Sandreas.sandberg@arm.com    opt_tlm_memory = getattr(options, "tlm_memory", None)
16412094Sandreas.sandberg@arm.com    opt_external_memory_system = getattr(options, "external_memory_system",
16512094Sandreas.sandberg@arm.com                                         None)
16612094Sandreas.sandberg@arm.com    opt_elastic_trace_en = getattr(options, "elastic_trace_en", False)
16712094Sandreas.sandberg@arm.com    opt_mem_ranks = getattr(options, "mem_ranks", None)
16814062Sgiacomo.travaglini@arm.com    opt_dram_powerdown = getattr(options, "enable_dram_powerdown", None)
16912094Sandreas.sandberg@arm.com
17012094Sandreas.sandberg@arm.com    if opt_mem_type == "HMC_2500_1x32":
17112340Szulian@eit.uni-kl.de        HMChost = HMC.config_hmc_host_ctrl(options, system)
17212340Szulian@eit.uni-kl.de        HMC.config_hmc_dev(options, system, HMChost.hmc_host)
17311551Sabdul.mutaal@gmail.com        subsystem = system.hmc_dev
17411551Sabdul.mutaal@gmail.com        xbar = system.hmc_dev.xbar
17511183Serfan.azarkhish@unibo.it    else:
17611183Serfan.azarkhish@unibo.it        subsystem = system
17711183Serfan.azarkhish@unibo.it        xbar = system.membus
17811183Serfan.azarkhish@unibo.it
17912094Sandreas.sandberg@arm.com    if opt_tlm_memory:
18010993Sjungma@eit.uni-kl.de        system.external_memory = m5.objects.ExternalSlave(
18111818SChristian.Menard@tu-dresden.de            port_type="tlm_slave",
18212094Sandreas.sandberg@arm.com            port_data=opt_tlm_memory,
18310993Sjungma@eit.uni-kl.de            port=system.membus.master,
18410993Sjungma@eit.uni-kl.de            addr_ranges=system.mem_ranges)
18510993Sjungma@eit.uni-kl.de        system.kernel_addr_check = False
18610993Sjungma@eit.uni-kl.de        return
18710993Sjungma@eit.uni-kl.de
18812094Sandreas.sandberg@arm.com    if opt_external_memory_system:
18911183Serfan.azarkhish@unibo.it        subsystem.external_memory = m5.objects.ExternalSlave(
19012094Sandreas.sandberg@arm.com            port_type=opt_external_memory_system,
19111183Serfan.azarkhish@unibo.it            port_data="init_mem0", port=xbar.master,
19210780SCurtis.Dunham@arm.com            addr_ranges=system.mem_ranges)
19311183Serfan.azarkhish@unibo.it        subsystem.kernel_addr_check = False
19410780SCurtis.Dunham@arm.com        return
19510780SCurtis.Dunham@arm.com
19612094Sandreas.sandberg@arm.com    nbr_mem_ctrls = opt_mem_channels
1979836Sandreas.hansson@arm.com    import math
1989836Sandreas.hansson@arm.com    from m5.util import fatal
1999836Sandreas.hansson@arm.com    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
2009836Sandreas.hansson@arm.com    if 2 ** intlv_bits != nbr_mem_ctrls:
2019836Sandreas.hansson@arm.com        fatal("Number of memory channels must be a power of 2")
20210442Snilay@cs.wisc.edu
20312094Sandreas.sandberg@arm.com    cls = get(opt_mem_type)
2049836Sandreas.hansson@arm.com    mem_ctrls = []
2059836Sandreas.hansson@arm.com
20612094Sandreas.sandberg@arm.com    if opt_elastic_trace_en and not issubclass(cls, m5.objects.SimpleMemory):
20711251Sradhika.jagtap@ARM.com        fatal("When elastic trace is enabled, configure mem-type as "
20811251Sradhika.jagtap@ARM.com                "simple-mem.")
20911251Sradhika.jagtap@ARM.com
21010675Sandreas.hansson@arm.com    # The default behaviour is to interleave memory channels on 128
21110675Sandreas.hansson@arm.com    # byte granularity, or cache line granularity if larger than 128
21210675Sandreas.hansson@arm.com    # byte. This value is based on the locality seen across a large
21310675Sandreas.hansson@arm.com    # range of workloads.
21410675Sandreas.hansson@arm.com    intlv_size = max(128, system.cache_line_size.value)
21510675Sandreas.hansson@arm.com
2169836Sandreas.hansson@arm.com    # For every range (most systems will only have one), create an
2179836Sandreas.hansson@arm.com    # array of controllers and set their parameters to match their
2189836Sandreas.hansson@arm.com    # address mapping in the case of a DRAM
2199836Sandreas.hansson@arm.com    for r in system.mem_ranges:
22013731Sandreas.sandberg@arm.com        for i in range(nbr_mem_ctrls):
22110620Sandreas.hansson@arm.com            mem_ctrl = create_mem_ctrl(cls, r, i, nbr_mem_ctrls, intlv_bits,
22210675Sandreas.hansson@arm.com                                       intlv_size)
22310620Sandreas.hansson@arm.com            # Set the number of ranks based on the command-line
22410620Sandreas.hansson@arm.com            # options if it was explicitly set
22512094Sandreas.sandberg@arm.com            if issubclass(cls, m5.objects.DRAMCtrl) and opt_mem_ranks:
22612094Sandreas.sandberg@arm.com                mem_ctrl.ranks_per_channel = opt_mem_ranks
22710620Sandreas.hansson@arm.com
22814038Smatthew.poremba@amd.com            # Enable low-power DRAM states if option is set
22914038Smatthew.poremba@amd.com            if issubclass(cls, m5.objects.DRAMCtrl):
23014062Sgiacomo.travaglini@arm.com                mem_ctrl.enable_dram_powerdown = opt_dram_powerdown
23114038Smatthew.poremba@amd.com
23212094Sandreas.sandberg@arm.com            if opt_elastic_trace_en:
23311251Sradhika.jagtap@ARM.com                mem_ctrl.latency = '1ns'
23412564Sgabeblack@google.com                print("For elastic trace, over-riding Simple Memory "
23512564Sgabeblack@google.com                    "latency to 1ns.")
23611251Sradhika.jagtap@ARM.com
23710620Sandreas.hansson@arm.com            mem_ctrls.append(mem_ctrl)
2389836Sandreas.hansson@arm.com
23911183Serfan.azarkhish@unibo.it    subsystem.mem_ctrls = mem_ctrls
2409836Sandreas.hansson@arm.com
2419836Sandreas.hansson@arm.com    # Connect the controllers to the membus
24213731Sandreas.sandberg@arm.com    for i in range(len(subsystem.mem_ctrls)):
24312094Sandreas.sandberg@arm.com        if opt_mem_type == "HMC_2500_1x32":
24411551Sabdul.mutaal@gmail.com            subsystem.mem_ctrls[i].port = xbar[i/4].master
24512340Szulian@eit.uni-kl.de            # Set memory device size. There is an independent controller for
24612340Szulian@eit.uni-kl.de            # each vault. All vaults are same size.
24712340Szulian@eit.uni-kl.de            subsystem.mem_ctrls[i].device_size = options.hmc_dev_vault_size
24811551Sabdul.mutaal@gmail.com        else:
24911551Sabdul.mutaal@gmail.com            subsystem.mem_ctrls[i].port = xbar.master
250