MOESI_AMD_Base.py revision 12598
12068SN/A#
22068SN/A#  Copyright (c) 2010-2015 Advanced Micro Devices, Inc.
32068SN/A#  All rights reserved.
42068SN/A#
52068SN/A#  For use for simulation and test purposes only
62068SN/A#
72068SN/A#  Redistribution and use in source and binary forms, with or without
82068SN/A#  modification, are permitted provided that the following conditions are met:
92068SN/A#
102068SN/A#  1. Redistributions of source code must retain the above copyright notice,
112068SN/A#  this list of conditions and the following disclaimer.
122068SN/A#
132068SN/A#  2. Redistributions in binary form must reproduce the above copyright notice,
142068SN/A#  this list of conditions and the following disclaimer in the documentation
152068SN/A#  and/or other materials provided with the distribution.
162068SN/A#
172068SN/A#  3. Neither the name of the copyright holder nor the names of its contributors
182068SN/A#  may be used to endorse or promote products derived from this software
192068SN/A#  without specific prior written permission.
202068SN/A#
212068SN/A#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
222068SN/A#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232068SN/A#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242068SN/A#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
252068SN/A#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
262068SN/A#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
272068SN/A#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
282665Ssaidi@eecs.umich.edu#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
292665Ssaidi@eecs.umich.edu#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
302665Ssaidi@eecs.umich.edu#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
312068SN/A#  POSSIBILITY OF SUCH DAMAGE.
322649Ssaidi@eecs.umich.edu#
332649Ssaidi@eecs.umich.edu#  Author: Lisa Hsu
342649Ssaidi@eecs.umich.edu#
352649Ssaidi@eecs.umich.edu
362649Ssaidi@eecs.umich.eduimport math
372068SN/Aimport m5
382068SN/Afrom m5.objects import *
392068SN/Afrom m5.defines import buildEnv
402068SN/Afrom Ruby import create_topology
412068SN/Afrom Ruby import send_evicts
422068SN/A
432068SN/Afrom topologies.Cluster import Cluster
442068SN/Afrom topologies.Crossbar import Crossbar
452068SN/A
465736Snate@binkert.orgclass CntrlBase:
472068SN/A    _seqs = 0
482068SN/A    @classmethod
496181Sksewell@umich.edu    def seqCount(cls):
506181Sksewell@umich.edu        # Use SeqCount not class since we need global count
512068SN/A        CntrlBase._seqs += 1
522068SN/A        return CntrlBase._seqs - 1
532068SN/A
542068SN/A    _cntrls = 0
552068SN/A    @classmethod
562068SN/A    def cntrlCount(cls):
572068SN/A        # Use CntlCount not class since we need global count
582068SN/A        CntrlBase._cntrls += 1
592068SN/A        return CntrlBase._cntrls - 1
602068SN/A
612068SN/A    _version = 0
622068SN/A    @classmethod
632068SN/A    def versionCount(cls):
642068SN/A        cls._version += 1 # Use count for this particular type
652068SN/A        return cls._version - 1
662068SN/A
672068SN/Aclass L1DCache(RubyCache):
682068SN/A    resourceStalls = False
696181Sksewell@umich.edu    def create(self, options):
706181Sksewell@umich.edu        self.size = MemorySize(options.l1d_size)
712068SN/A        self.assoc = options.l1d_assoc
722068SN/A        self.replacement_policy = PseudoLRUReplacementPolicy()
732068SN/A
742068SN/Aclass L1ICache(RubyCache):
752068SN/A    resourceStalls = False
762068SN/A    def create(self, options):
772068SN/A        self.size = MemorySize(options.l1i_size)
782068SN/A        self.assoc = options.l1i_assoc
792068SN/A        self.replacement_policy = PseudoLRUReplacementPolicy()
802068SN/A
812068SN/Aclass L2Cache(RubyCache):
822068SN/A    resourceStalls = False
832068SN/A    def create(self, options):
842068SN/A        self.size = MemorySize(options.l2_size)
852068SN/A        self.assoc = options.l2_assoc
866181Sksewell@umich.edu        self.replacement_policy = PseudoLRUReplacementPolicy()
876181Sksewell@umich.edu
882068SN/Aclass CPCntrl(CorePair_Controller, CntrlBase):
892068SN/A
902068SN/A    def create(self, options, ruby_system, system):
912068SN/A        self.version = self.versionCount()
922068SN/A
932068SN/A        self.L1Icache = L1ICache()
942068SN/A        self.L1Icache.create(options)
952068SN/A        self.L1D0cache = L1DCache()
962068SN/A        self.L1D0cache.create(options)
972068SN/A        self.L1D1cache = L1DCache()
982068SN/A        self.L1D1cache.create(options)
992068SN/A        self.L2cache = L2Cache()
1002068SN/A        self.L2cache.create(options)
1012068SN/A
1022068SN/A        self.sequencer = RubySequencer()
1032068SN/A        self.sequencer.icache_hit_latency = 2
1042068SN/A        self.sequencer.dcache_hit_latency = 2
1052068SN/A        self.sequencer.version = self.seqCount()
1062068SN/A        self.sequencer.icache = self.L1Icache
1072068SN/A        self.sequencer.dcache = self.L1D0cache
1082068SN/A        self.sequencer.ruby_system = ruby_system
1092068SN/A        self.sequencer.coreid = 0
1102068SN/A        self.sequencer.is_cpu_sequencer = True
1112068SN/A
1122068SN/A        self.sequencer1 = RubySequencer()
1133953Sstever@eecs.umich.edu        self.sequencer1.version = self.seqCount()
1142068SN/A        self.sequencer1.icache = self.L1Icache
1152068SN/A        self.sequencer1.dcache = self.L1D1cache
1162068SN/A        self.sequencer1.icache_hit_latency = 2
1172068SN/A        self.sequencer1.dcache_hit_latency = 2
1182068SN/A        self.sequencer1.ruby_system = ruby_system
1192068SN/A        self.sequencer1.coreid = 1
1202068SN/A        self.sequencer1.is_cpu_sequencer = True
1212068SN/A
1222068SN/A        self.issue_latency = options.cpu_to_dir_latency
1232068SN/A        self.send_evictions = send_evicts(options)
1242068SN/A
1252068SN/A        self.ruby_system = ruby_system
1262068SN/A
1272068SN/A        if options.recycle_latency:
1282068SN/A            self.recycle_latency = options.recycle_latency
1292068SN/A
1302227SN/Aclass L3Cache(RubyCache):
1312068SN/A    assoc = 8
1322068SN/A    dataArrayBanks = 256
1332095SN/A    tagArrayBanks = 256
1346181Sksewell@umich.edu
1356181Sksewell@umich.edu    def create(self, options, ruby_system, system):
1362095SN/A        self.size = MemorySize(options.l3_size)
1372095SN/A        self.size.value /= options.num_dirs
1382095SN/A        self.dataArrayBanks /= options.num_dirs
1392068SN/A        self.tagArrayBanks /= options.num_dirs
1402068SN/A        self.dataArrayBanks /= options.num_dirs
1412068SN/A        self.tagArrayBanks /= options.num_dirs
1422095SN/A        self.dataAccessLatency = options.l3_data_latency
1436181Sksewell@umich.edu        self.tagAccessLatency = options.l3_tag_latency
1446181Sksewell@umich.edu        self.resourceStalls = options.no_resource_stalls
1456181Sksewell@umich.edu        self.replacement_policy = PseudoLRUReplacementPolicy()
1466181Sksewell@umich.edu
1472095SN/Aclass L3Cntrl(L3Cache_Controller, CntrlBase):
1482132SN/A    def create(self, options, ruby_system, system):
1492095SN/A        self.version = self.versionCount()
1502095SN/A        self.L3cache = L3Cache()
1512095SN/A        self.L3cache.create(options, ruby_system, system)
1522095SN/A
1533349Sbinkertn@umich.edu        self.l3_response_latency = max(self.L3cache.dataAccessLatency,
1542623SN/A                                       self.L3cache.tagAccessLatency)
1552095SN/A        self.ruby_system = ruby_system
1562095SN/A
1576181Sksewell@umich.edu        if options.recycle_latency:
1586181Sksewell@umich.edu            self.recycle_latency = options.recycle_latency
1596181Sksewell@umich.edu
1602068SN/A    def connectWireBuffers(self, req_to_dir, resp_to_dir, l3_unblock_to_dir,
1613953Sstever@eecs.umich.edu                           req_to_l3, probe_to_l3, resp_to_l3):
1622068SN/A        self.reqToDir = req_to_dir
1633953Sstever@eecs.umich.edu        self.respToDir = resp_to_dir
1642068SN/A        self.l3UnblockToDir = l3_unblock_to_dir
1652068SN/A        self.reqToL3 = req_to_l3
1666181Sksewell@umich.edu        self.probeToL3 = probe_to_l3
1676181Sksewell@umich.edu        self.respToL3 = resp_to_l3
1682068SN/A
1692068SN/Aclass DirCntrl(Directory_Controller, CntrlBase):
1702132SN/A    def create(self, options, dir_ranges, ruby_system, system):
1712068SN/A        self.version = self.versionCount()
1722068SN/A
1732068SN/A        self.response_latency = 30
1742068SN/A
1753953Sstever@eecs.umich.edu        self.addr_ranges = dir_ranges
1762068SN/A        self.directory = RubyDirectoryMemory()
1772090SN/A
1782068SN/A        self.L3CacheMemory = L3Cache()
1792068SN/A        self.L3CacheMemory.create(options, ruby_system, system)
1802068SN/A
1812068SN/A        self.l3_hit_latency = max(self.L3CacheMemory.dataAccessLatency,
1822068SN/A                                  self.L3CacheMemory.tagAccessLatency)
1832068SN/A
1842068SN/A        self.number_of_TBEs = options.num_tbes
1852068SN/A
1862068SN/A        self.ruby_system = ruby_system
1872069SN/A
1882132SN/A        if options.recycle_latency:
1892068SN/A            self.recycle_latency = options.recycle_latency
1902068SN/A
1912068SN/A        self.CPUonly = True
1922132SN/A
1932068SN/A    def connectWireBuffers(self, req_to_dir, resp_to_dir, l3_unblock_to_dir,
1942068SN/A                           req_to_l3, probe_to_l3, resp_to_l3):
1952068SN/A        self.reqToDir = req_to_dir
1962069SN/A        self.respToDir = resp_to_dir
1972068SN/A        self.l3UnblockToDir = l3_unblock_to_dir
1982068SN/A        self.reqToL3 = req_to_l3
1992090SN/A        self.probeToL3 = probe_to_l3
2008442Sgblack@eecs.umich.edu        self.respToL3 = resp_to_l3
2012068SN/A
2022068SN/Adef define_options(parser):
2032068SN/A    parser.add_option("--num-subcaches", type="int", default=4)
2042090SN/A    parser.add_option("--l3-data-latency", type="int", default=20)
2052069SN/A    parser.add_option("--l3-tag-latency", type="int", default=15)
2062069SN/A    parser.add_option("--cpu-to-dir-latency", type="int", default=15)
2072069SN/A    parser.add_option("--no-resource-stalls", action="store_false",
2082069SN/A                      default=True)
2092069SN/A    parser.add_option("--num-tbes", type="int", default=256)
2102069SN/A    parser.add_option("--l2-latency", type="int", default=50) # load to use
2112069SN/A
2122069SN/Adef create_system(options, full_system, system, dma_devices, bootmem,
2132095SN/A                  ruby_system):
2142132SN/A    if buildEnv['PROTOCOL'] != 'MOESI_AMD_Base':
2152095SN/A        panic("This script requires the MOESI_AMD_Base protocol.")
2162095SN/A
2172095SN/A    cpu_sequencers = []
2182132SN/A
2192095SN/A    #
2202095SN/A    # The ruby network creation expects the list of nodes in the system to
2212095SN/A    # be consistent with the NetDest list.  Therefore the l1 controller
2222095SN/A    # nodes must be listed before the directory nodes and directory nodes
2232095SN/A    # before dma nodes, etc.
2242095SN/A    #
2252098SN/A    l1_cntrl_nodes = []
2268442Sgblack@eecs.umich.edu    l3_cntrl_nodes = []
2272095SN/A    dir_cntrl_nodes = []
2282095SN/A
2292095SN/A    control_count = 0
2302095SN/A
2312095SN/A    #
2322095SN/A    # Must create the individual controllers before the network to ensure
2332095SN/A    # the controller constructors are called before the network constructor
2342095SN/A    #
2353349Sbinkertn@umich.edu
2362095SN/A    # This is the base crossbar that connects the L3s, Dirs, and cpu
2372095SN/A    # Cluster
2382095SN/A    mainCluster = Cluster(extBW = 512, intBW = 512) # 1 TB/s
2392132SN/A
2402095SN/A    if options.numa_high_bit:
2412095SN/A        numa_bit = options.numa_high_bit
2422506SN/A    else:
2432095SN/A        # if the numa_bit is not specified, set the directory bits as the
2448442Sgblack@eecs.umich.edu        # lowest bits above the block offset bits, and the numa_bit as the
2452095SN/A        # highest of those directory bits
2462098SN/A        dir_bits = int(math.log(options.num_dirs, 2))
2472095SN/A        block_size_bits = int(math.log(options.cacheline_size, 2))
2482095SN/A        numa_bit = block_size_bits + dir_bits - 1
2492095SN/A
2502098SN/A    for i in xrange(options.num_dirs):
2512095SN/A        dir_ranges = []
2522095SN/A        for r in system.mem_ranges:
2532095SN/A            addr_range = m5.objects.AddrRange(r.start, size = r.size(),
2542095SN/A                                              intlvHighBit = numa_bit,
2552095SN/A                                              intlvBits = dir_bits,
2562095SN/A                                              intlvMatch = i)
2572095SN/A            dir_ranges.append(addr_range)
2582095SN/A
2592069SN/A
2602132SN/A        dir_cntrl = DirCntrl(TCC_select_num_bits = 0)
2612069SN/A        dir_cntrl.create(options, dir_ranges, ruby_system, system)
2622069SN/A
2632069SN/A        # Connect the Directory controller to the ruby network
2642132SN/A        dir_cntrl.requestFromCores = MessageBuffer(ordered = True)
2654027Sstever@eecs.umich.edu        dir_cntrl.requestFromCores.slave = ruby_system.network.master
2664027Sstever@eecs.umich.edu
2674027Sstever@eecs.umich.edu        dir_cntrl.responseFromCores = MessageBuffer()
2684027Sstever@eecs.umich.edu        dir_cntrl.responseFromCores.slave = ruby_system.network.master
2694027Sstever@eecs.umich.edu
2704027Sstever@eecs.umich.edu        dir_cntrl.unblockFromCores = MessageBuffer()
2714027Sstever@eecs.umich.edu        dir_cntrl.unblockFromCores.slave = ruby_system.network.master
2724027Sstever@eecs.umich.edu
2734027Sstever@eecs.umich.edu        dir_cntrl.probeToCore = MessageBuffer()
2744027Sstever@eecs.umich.edu        dir_cntrl.probeToCore.master = ruby_system.network.slave
2754027Sstever@eecs.umich.edu
2768442Sgblack@eecs.umich.edu        dir_cntrl.responseToCore = MessageBuffer()
2778442Sgblack@eecs.umich.edu        dir_cntrl.responseToCore.master = ruby_system.network.slave
2784027Sstever@eecs.umich.edu
2794027Sstever@eecs.umich.edu        dir_cntrl.triggerQueue = MessageBuffer(ordered = True)
2804027Sstever@eecs.umich.edu        dir_cntrl.L3triggerQueue = MessageBuffer(ordered = True)
2814027Sstever@eecs.umich.edu        dir_cntrl.responseFromMemory = MessageBuffer()
2824027Sstever@eecs.umich.edu
2834027Sstever@eecs.umich.edu        exec("system.dir_cntrl%d = dir_cntrl" % i)
2844027Sstever@eecs.umich.edu        dir_cntrl_nodes.append(dir_cntrl)
2854027Sstever@eecs.umich.edu
2864027Sstever@eecs.umich.edu        mainCluster.add(dir_cntrl)
2874027Sstever@eecs.umich.edu
2884027Sstever@eecs.umich.edu    # Technically this config can support an odd number of cpus, but the top
2894027Sstever@eecs.umich.edu    # level config files, such as the ruby_random_tester, will get confused if
2904027Sstever@eecs.umich.edu    # the number of cpus does not equal the number of sequencers.  Thus make
2914027Sstever@eecs.umich.edu    # sure that an even number of cpus is specified.
2924027Sstever@eecs.umich.edu    assert((options.num_cpus % 2) == 0)
2934027Sstever@eecs.umich.edu
2944027Sstever@eecs.umich.edu    # For an odd number of CPUs, still create the right number of controllers
2954027Sstever@eecs.umich.edu    cpuCluster = Cluster(extBW = 512, intBW = 512)  # 1 TB/s
2964027Sstever@eecs.umich.edu    for i in xrange((options.num_cpus + 1) / 2):
2974027Sstever@eecs.umich.edu
2982069SN/A        cp_cntrl = CPCntrl()
2992069SN/A        cp_cntrl.create(options, ruby_system, system)
3002069SN/A
3012069SN/A        exec("system.cp_cntrl%d = cp_cntrl" % i)
3022069SN/A        #
3032069SN/A        # Add controllers and sequencers to the appropriate lists
3042069SN/A        #
3052090SN/A        cpu_sequencers.extend([cp_cntrl.sequencer, cp_cntrl.sequencer1])
3062069SN/A
3072069SN/A        # Connect the CP controllers and the network
3082069SN/A        cp_cntrl.requestFromCore = MessageBuffer()
3092090SN/A        cp_cntrl.requestFromCore.master = ruby_system.network.slave
3108442Sgblack@eecs.umich.edu
3118442Sgblack@eecs.umich.edu        cp_cntrl.responseFromCore = MessageBuffer()
3122069SN/A        cp_cntrl.responseFromCore.master = ruby_system.network.slave
3132069SN/A
3142090SN/A        cp_cntrl.unblockFromCore = MessageBuffer()
3152069SN/A        cp_cntrl.unblockFromCore.master = ruby_system.network.slave
3162069SN/A
3172069SN/A        cp_cntrl.probeToCore = MessageBuffer()
3182090SN/A        cp_cntrl.probeToCore.slave = ruby_system.network.master
3192069SN/A
3202069SN/A        cp_cntrl.responseToCore = MessageBuffer()
3212069SN/A        cp_cntrl.responseToCore.slave = ruby_system.network.master
3222069SN/A
3232069SN/A        cp_cntrl.mandatoryQueue = MessageBuffer()
3242069SN/A        cp_cntrl.triggerQueue = MessageBuffer(ordered = True)
3252069SN/A
3262095SN/A        cpuCluster.add(cp_cntrl)
3272132SN/A
3282095SN/A    # Assuming no DMA devices
3292095SN/A    assert(len(dma_devices) == 0)
3302095SN/A
3312132SN/A    # Add cpu/gpu clusters to main cluster
3322095SN/A    mainCluster.add(cpuCluster)
3332095SN/A
3342506SN/A    ruby_system.network.number_of_virtual_networks = 10
3352095SN/A
3362095SN/A    return (cpu_sequencers, dir_cntrl_nodes, mainCluster)
3372095SN/A