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