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