MemConfig.py revision 9836
111308Santhony.gutierrez@amd.com# Copyright (c) 2013 ARM Limited
211308Santhony.gutierrez@amd.com# All rights reserved.
311308Santhony.gutierrez@amd.com#
411308Santhony.gutierrez@amd.com# The license below extends only to copyright in the software and shall
511308Santhony.gutierrez@amd.com# not be construed as granting a license to any other intellectual
611308Santhony.gutierrez@amd.com# property including but not limited to intellectual property relating
711308Santhony.gutierrez@amd.com# to a hardware implementation of the functionality of the software
811308Santhony.gutierrez@amd.com# licensed hereunder.  You may use the software subject to the license
911308Santhony.gutierrez@amd.com# terms below provided that you ensure that this notice is replicated
1011308Santhony.gutierrez@amd.com# unmodified and in its entirety in all distributions of the software,
1111308Santhony.gutierrez@amd.com# modified or unmodified, in source code or in binary form.
1211308Santhony.gutierrez@amd.com#
1311308Santhony.gutierrez@amd.com# Redistribution and use in source and binary forms, with or without
1411308Santhony.gutierrez@amd.com# modification, are permitted provided that the following conditions are
1511308Santhony.gutierrez@amd.com# met: redistributions of source code must retain the above copyright
1611308Santhony.gutierrez@amd.com# notice, this list of conditions and the following disclaimer;
1711308Santhony.gutierrez@amd.com# redistributions in binary form must reproduce the above copyright
1811308Santhony.gutierrez@amd.com# notice, this list of conditions and the following disclaimer in the
1911308Santhony.gutierrez@amd.com# documentation and/or other materials provided with the distribution;
2011308Santhony.gutierrez@amd.com# neither the name of the copyright holders nor the names of its
2111308Santhony.gutierrez@amd.com# contributors may be used to endorse or promote products derived from
2211308Santhony.gutierrez@amd.com# this software without specific prior written permission.
2311308Santhony.gutierrez@amd.com#
2411308Santhony.gutierrez@amd.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2511308Santhony.gutierrez@amd.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2611308Santhony.gutierrez@amd.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2711308Santhony.gutierrez@amd.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2811308Santhony.gutierrez@amd.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2911308Santhony.gutierrez@amd.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3011308Santhony.gutierrez@amd.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3111308Santhony.gutierrez@amd.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3211308Santhony.gutierrez@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3311308Santhony.gutierrez@amd.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3411308Santhony.gutierrez@amd.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3511308Santhony.gutierrez@amd.com#
3611308Santhony.gutierrez@amd.com# Authors: Andreas Sandberg
3711308Santhony.gutierrez@amd.com#          Andreas Hansson
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.comimport m5.objects
4011308Santhony.gutierrez@amd.comimport inspect
4111308Santhony.gutierrez@amd.comimport sys
4211308Santhony.gutierrez@amd.comfrom textwrap import  TextWrapper
4311308Santhony.gutierrez@amd.com
4411308Santhony.gutierrez@amd.com# Dictionary of mapping names of real memory controller models to
4511308Santhony.gutierrez@amd.com# classes.
4611308Santhony.gutierrez@amd.com_mem_classes = {}
4711308Santhony.gutierrez@amd.com
4811308Santhony.gutierrez@amd.com# Memory aliases. We make sure they exist before we add them to the
4911308Santhony.gutierrez@amd.com# fina; list. A target may be specified as a tuple, in which case the
5011308Santhony.gutierrez@amd.com# first available memory controller model in the tuple will be used.
5111308Santhony.gutierrez@amd.com_mem_aliases_all = [
5211308Santhony.gutierrez@amd.com    ("simple_mem", "SimpleMemory"),
5312126Sspwilson2@wisc.edu    ("ddr3_1600_x64", "DDR3_1600_x64"),
5412126Sspwilson2@wisc.edu    ("lpddr2_s4_1066_x32", "LPDDR2_S4_1066_x32"),
5512126Sspwilson2@wisc.edu    ("lpddr3_1600_x32", "LPDDR3_1600_x32"),
5611308Santhony.gutierrez@amd.com    ("wio_200_x128", "WideIO_200_x128"),
5711308Santhony.gutierrez@amd.com    ]
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.com# Filtered list of aliases. Only aliases for existing memory
6011308Santhony.gutierrez@amd.com# controllers exist in this list.
6111308Santhony.gutierrez@amd.com_mem_aliases = {}
6211308Santhony.gutierrez@amd.com
6311308Santhony.gutierrez@amd.com
6411308Santhony.gutierrez@amd.comdef is_mem_class(cls):
6511308Santhony.gutierrez@amd.com    """Determine if a class is a memory controller that can be instantiated"""
6611308Santhony.gutierrez@amd.com
6711308Santhony.gutierrez@amd.com    # We can't use the normal inspect.isclass because the ParamFactory
6811308Santhony.gutierrez@amd.com    # and ProxyFactory classes have a tendency to confuse it.
6911308Santhony.gutierrez@amd.com    try:
7011308Santhony.gutierrez@amd.com        return issubclass(cls, m5.objects.AbstractMemory) and \
7111308Santhony.gutierrez@amd.com            not cls.abstract
7211308Santhony.gutierrez@amd.com    except TypeError:
7311308Santhony.gutierrez@amd.com        return False
7411308Santhony.gutierrez@amd.com
7511308Santhony.gutierrez@amd.comdef get(name):
7611308Santhony.gutierrez@amd.com    """Get a memory class from a user provided class name or alias."""
7711308Santhony.gutierrez@amd.com
7811308Santhony.gutierrez@amd.com    real_name = _mem_aliases.get(name, name)
7911308Santhony.gutierrez@amd.com
8011308Santhony.gutierrez@amd.com    try:
8111308Santhony.gutierrez@amd.com        mem_class = _mem_classes[real_name]
8211308Santhony.gutierrez@amd.com        return mem_class
8311308Santhony.gutierrez@amd.com    except KeyError:
8411308Santhony.gutierrez@amd.com        print "%s is not a valid memory controller." % (name,)
8511308Santhony.gutierrez@amd.com        sys.exit(1)
8611308Santhony.gutierrez@amd.com
8711308Santhony.gutierrez@amd.comdef print_mem_list():
8811308Santhony.gutierrez@amd.com    """Print a list of available memory classes including their aliases."""
8911308Santhony.gutierrez@amd.com
9011308Santhony.gutierrez@amd.com    print "Available memory classes:"
9111308Santhony.gutierrez@amd.com    doc_wrapper = TextWrapper(initial_indent="\t\t", subsequent_indent="\t\t")
9211308Santhony.gutierrez@amd.com    for name, cls in _mem_classes.items():
9311308Santhony.gutierrez@amd.com        print "\t%s" % name
9411308Santhony.gutierrez@amd.com
9511308Santhony.gutierrez@amd.com        # Try to extract the class documentation from the class help
9611308Santhony.gutierrez@amd.com        # string.
9711308Santhony.gutierrez@amd.com        doc = inspect.getdoc(cls)
9811308Santhony.gutierrez@amd.com        if doc:
9911308Santhony.gutierrez@amd.com            for line in doc_wrapper.wrap(doc):
10011308Santhony.gutierrez@amd.com                print line
10111308Santhony.gutierrez@amd.com
10211308Santhony.gutierrez@amd.com    if _mem_aliases:
10311308Santhony.gutierrez@amd.com        print "\nMemory aliases:"
10411308Santhony.gutierrez@amd.com        for alias, target in _mem_aliases.items():
10511308Santhony.gutierrez@amd.com            print "\t%s => %s" % (alias, target)
10611308Santhony.gutierrez@amd.com
10711308Santhony.gutierrez@amd.comdef mem_names():
10811308Santhony.gutierrez@amd.com    """Return a list of valid memory names."""
10911308Santhony.gutierrez@amd.com    return _mem_classes.keys() + _mem_aliases.keys()
11011308Santhony.gutierrez@amd.com
11111308Santhony.gutierrez@amd.com# Add all memory controllers in the object hierarchy.
11211308Santhony.gutierrez@amd.comfor name, cls in inspect.getmembers(m5.objects, is_mem_class):
11311308Santhony.gutierrez@amd.com    _mem_classes[name] = cls
11411308Santhony.gutierrez@amd.com
11511308Santhony.gutierrez@amd.comfor alias, target in _mem_aliases_all:
11611308Santhony.gutierrez@amd.com    if isinstance(target, tuple):
11711308Santhony.gutierrez@amd.com        # Some aliases contain a list of memory controller models
11811308Santhony.gutierrez@amd.com        # sorted in priority order. Use the first target that's
11911308Santhony.gutierrez@amd.com        # available.
12011308Santhony.gutierrez@amd.com        for t in target:
12111308Santhony.gutierrez@amd.com            if t in _mem_classes:
12211308Santhony.gutierrez@amd.com                _mem_aliases[alias] = t
12311308Santhony.gutierrez@amd.com                break
12411308Santhony.gutierrez@amd.com    elif target in _mem_classes:
12511308Santhony.gutierrez@amd.com        # Normal alias
12611308Santhony.gutierrez@amd.com        _mem_aliases[alias] = target
12711308Santhony.gutierrez@amd.com
12811308Santhony.gutierrez@amd.comdef config_mem(options, system):
12911308Santhony.gutierrez@amd.com    """
13011308Santhony.gutierrez@amd.com    Create the memory controllers based on the options and attach them.
13111308Santhony.gutierrez@amd.com
13211308Santhony.gutierrez@amd.com    If requested, we make a multi-channel configuration of the
13311308Santhony.gutierrez@amd.com    selected memory controller class by creating multiple instances of
13411308Santhony.gutierrez@amd.com    the specific class. The individual controllers have their
13511308Santhony.gutierrez@amd.com    parameters set such that the address range is interleaved between
13611308Santhony.gutierrez@amd.com    them.
13711308Santhony.gutierrez@amd.com    """
13811308Santhony.gutierrez@amd.com
13911308Santhony.gutierrez@amd.com    nbr_mem_ctrls = options.mem_channels
14011308Santhony.gutierrez@amd.com    import math
14111308Santhony.gutierrez@amd.com    from m5.util import fatal
14211308Santhony.gutierrez@amd.com    intlv_bits = int(math.log(nbr_mem_ctrls, 2))
14311308Santhony.gutierrez@amd.com    if 2 ** intlv_bits != nbr_mem_ctrls:
14411308Santhony.gutierrez@amd.com        fatal("Number of memory channels must be a power of 2")
14511308Santhony.gutierrez@amd.com    cls = get(options.mem_type)
14611308Santhony.gutierrez@amd.com    mem_ctrls = []
14711308Santhony.gutierrez@amd.com
14811308Santhony.gutierrez@amd.com    # The default behaviour is to interleave on cache line granularity
14911308Santhony.gutierrez@amd.com    cache_line_bit = int(math.log(system.cache_line_size.value, 2)) - 1
15011308Santhony.gutierrez@amd.com    intlv_low_bit = cache_line_bit
15111308Santhony.gutierrez@amd.com
15211308Santhony.gutierrez@amd.com    # For every range (most systems will only have one), create an
15311308Santhony.gutierrez@amd.com    # array of controllers and set their parameters to match their
15411308Santhony.gutierrez@amd.com    # address mapping in the case of a DRAM
15511308Santhony.gutierrez@amd.com    for r in system.mem_ranges:
15611308Santhony.gutierrez@amd.com        for i in xrange(nbr_mem_ctrls):
15711308Santhony.gutierrez@amd.com            # Create an instance so we can figure out the address
15811308Santhony.gutierrez@amd.com            # mapping and row-buffer size
15911308Santhony.gutierrez@amd.com            ctrl = cls()
16011308Santhony.gutierrez@amd.com
16111308Santhony.gutierrez@amd.com            # Only do this for DRAMs
16211308Santhony.gutierrez@amd.com            if issubclass(cls, m5.objects.SimpleDRAM):
16311308Santhony.gutierrez@amd.com                # Inform each controller how many channels to account
16411308Santhony.gutierrez@amd.com                # for
16511308Santhony.gutierrez@amd.com                ctrl.channels = nbr_mem_ctrls
16611308Santhony.gutierrez@amd.com
16711308Santhony.gutierrez@amd.com                # If the channel bits are appearing after the column
16811308Santhony.gutierrez@amd.com                # bits, we need to add the appropriate number of bits
16911308Santhony.gutierrez@amd.com                # for the row buffer size
17011308Santhony.gutierrez@amd.com                if ctrl.addr_mapping.value == 'RaBaChCo':
17111308Santhony.gutierrez@amd.com                    # This computation only really needs to happen
17211308Santhony.gutierrez@amd.com                    # once, but as we rely on having an instance we
17311308Santhony.gutierrez@amd.com                    # end up having to repeat it for each and every
17411308Santhony.gutierrez@amd.com                    # one
17511308Santhony.gutierrez@amd.com                    rowbuffer_size = ctrl.device_rowbuffer_size.value * \
17611308Santhony.gutierrez@amd.com                        ctrl.devices_per_rank.value
17711308Santhony.gutierrez@amd.com
17811308Santhony.gutierrez@amd.com                    intlv_low_bit = int(math.log(rowbuffer_size, 2)) - 1
17911308Santhony.gutierrez@amd.com
18011308Santhony.gutierrez@amd.com            # We got all we need to configure the appropriate address
18111308Santhony.gutierrez@amd.com            # range
18211308Santhony.gutierrez@amd.com            ctrl.range = m5.objects.AddrRange(r.start, size = r.size(),
18311308Santhony.gutierrez@amd.com                                              intlvHighBit = \
18411308Santhony.gutierrez@amd.com                                                  intlv_low_bit + intlv_bits,
18511308Santhony.gutierrez@amd.com                                              intlvBits = intlv_bits,
18611308Santhony.gutierrez@amd.com                                              intlvMatch = i)
18711308Santhony.gutierrez@amd.com            mem_ctrls.append(ctrl)
18811308Santhony.gutierrez@amd.com
18911308Santhony.gutierrez@amd.com    system.mem_ctrls = mem_ctrls
19011308Santhony.gutierrez@amd.com
19111308Santhony.gutierrez@amd.com    # Connect the controllers to the membus
19211308Santhony.gutierrez@amd.com    for i in xrange(nbr_mem_ctrls):
19311308Santhony.gutierrez@amd.com        system.mem_ctrls[i].port = system.membus.master
19411308Santhony.gutierrez@amd.com