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