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