MOESI_hammer.py revision 12976:125099a94768
113531Sjairo.balart@metempsy.com# Copyright (c) 2006-2007 The Regents of The University of Michigan
214258Sgiacomo.travaglini@arm.com# Copyright (c) 2009 Advanced Micro Devices, Inc.
314258Sgiacomo.travaglini@arm.com# All rights reserved.
414258Sgiacomo.travaglini@arm.com#
514258Sgiacomo.travaglini@arm.com# Redistribution and use in source and binary forms, with or without
614258Sgiacomo.travaglini@arm.com# modification, are permitted provided that the following conditions are
714258Sgiacomo.travaglini@arm.com# met: redistributions of source code must retain the above copyright
814258Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer;
914258Sgiacomo.travaglini@arm.com# redistributions in binary form must reproduce the above copyright
1014258Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer in the
1114258Sgiacomo.travaglini@arm.com# documentation and/or other materials provided with the distribution;
1214258Sgiacomo.travaglini@arm.com# neither the name of the copyright holders nor the names of its
1314258Sgiacomo.travaglini@arm.com# contributors may be used to endorse or promote products derived from
1413531Sjairo.balart@metempsy.com# this software without specific prior written permission.
1513531Sjairo.balart@metempsy.com#
1613531Sjairo.balart@metempsy.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713531Sjairo.balart@metempsy.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813531Sjairo.balart@metempsy.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913531Sjairo.balart@metempsy.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013531Sjairo.balart@metempsy.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113531Sjairo.balart@metempsy.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213531Sjairo.balart@metempsy.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313531Sjairo.balart@metempsy.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413531Sjairo.balart@metempsy.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513531Sjairo.balart@metempsy.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613531Sjairo.balart@metempsy.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713531Sjairo.balart@metempsy.com#
2813531Sjairo.balart@metempsy.com# Authors: Brad Beckmann
2913531Sjairo.balart@metempsy.com
3013531Sjairo.balart@metempsy.comimport math
3113531Sjairo.balart@metempsy.comimport m5
3213531Sjairo.balart@metempsy.comfrom m5.objects import *
3313531Sjairo.balart@metempsy.comfrom m5.defines import buildEnv
3413531Sjairo.balart@metempsy.comfrom Ruby import create_topology, create_directories
3513531Sjairo.balart@metempsy.comfrom Ruby import send_evicts
3613531Sjairo.balart@metempsy.com
3713531Sjairo.balart@metempsy.com#
3813531Sjairo.balart@metempsy.com# Declare caches used by the protocol
3913531Sjairo.balart@metempsy.com#
4013531Sjairo.balart@metempsy.comclass L1Cache(RubyCache): pass
4113531Sjairo.balart@metempsy.comclass L2Cache(RubyCache): pass
4213531Sjairo.balart@metempsy.com#
4313531Sjairo.balart@metempsy.com# Probe filter is a cache
4413531Sjairo.balart@metempsy.com#
4513531Sjairo.balart@metempsy.comclass ProbeFilter(RubyCache): pass
4613531Sjairo.balart@metempsy.com
4713531Sjairo.balart@metempsy.comdef define_options(parser):
4813531Sjairo.balart@metempsy.com    parser.add_option("--allow-atomic-migration", action="store_true",
4913756Sjairo.balart@metempsy.com          help="allow migratory sharing for atomic only accessed blocks")
5013531Sjairo.balart@metempsy.com    parser.add_option("--pf-on", action="store_true",
5113531Sjairo.balart@metempsy.com          help="Hammer: enable Probe Filter")
5213996Sgiacomo.travaglini@arm.com    parser.add_option("--dir-on", action="store_true",
5313531Sjairo.balart@metempsy.com          help="Hammer: enable Full-bit Directory")
5413531Sjairo.balart@metempsy.com
5513531Sjairo.balart@metempsy.comdef create_system(options, full_system, system, dma_ports, bootmem,
5613531Sjairo.balart@metempsy.com                  ruby_system):
5713826Sgiacomo.travaglini@arm.com
5813878Sgiacomo.travaglini@arm.com    if buildEnv['PROTOCOL'] != 'MOESI_hammer':
5913531Sjairo.balart@metempsy.com        panic("This script requires the MOESI_hammer protocol to be built.")
6013756Sjairo.balart@metempsy.com
6113531Sjairo.balart@metempsy.com    cpu_sequencers = []
6213531Sjairo.balart@metempsy.com
6313531Sjairo.balart@metempsy.com    #
6413996Sgiacomo.travaglini@arm.com    # The ruby network creation expects the list of nodes in the system to be
6513531Sjairo.balart@metempsy.com    # consistent with the NetDest list.  Therefore the l1 controller nodes must be
6613531Sjairo.balart@metempsy.com    # listed before the directory nodes and directory nodes before dma nodes, etc.
6713531Sjairo.balart@metempsy.com    #
6813878Sgiacomo.travaglini@arm.com    l1_cntrl_nodes = []
6913531Sjairo.balart@metempsy.com    dma_cntrl_nodes = []
7013531Sjairo.balart@metempsy.com
7113531Sjairo.balart@metempsy.com    #
7213756Sjairo.balart@metempsy.com    # Must create the individual controllers before the network to ensure the
7313531Sjairo.balart@metempsy.com    # controller constructors are called before the network constructor
7413531Sjairo.balart@metempsy.com    #
7513531Sjairo.balart@metempsy.com    block_size_bits = int(math.log(options.cacheline_size, 2))
7613531Sjairo.balart@metempsy.com
7713531Sjairo.balart@metempsy.com    for i in xrange(options.num_cpus):
7813531Sjairo.balart@metempsy.com        #
7913531Sjairo.balart@metempsy.com        # First create the Ruby objects associated with this cpu
8013531Sjairo.balart@metempsy.com        #
8113531Sjairo.balart@metempsy.com        l1i_cache = L1Cache(size = options.l1i_size,
8213756Sjairo.balart@metempsy.com                            assoc = options.l1i_assoc,
8313531Sjairo.balart@metempsy.com                            start_index_bit = block_size_bits,
8413531Sjairo.balart@metempsy.com                            is_icache = True)
8513531Sjairo.balart@metempsy.com        l1d_cache = L1Cache(size = options.l1d_size,
8613531Sjairo.balart@metempsy.com                            assoc = options.l1d_assoc,
8713531Sjairo.balart@metempsy.com                            start_index_bit = block_size_bits)
8813531Sjairo.balart@metempsy.com        l2_cache = L2Cache(size = options.l2_size,
8913531Sjairo.balart@metempsy.com                           assoc = options.l2_assoc,
9013756Sjairo.balart@metempsy.com                           start_index_bit = block_size_bits)
9113531Sjairo.balart@metempsy.com
9213531Sjairo.balart@metempsy.com        # the ruby random tester reuses num_cpus to specify the
9313531Sjairo.balart@metempsy.com        # number of cpu ports connected to the tester object, which
9413531Sjairo.balart@metempsy.com        # is stored in system.cpu. because there is only ever one
9513531Sjairo.balart@metempsy.com        # tester object, num_cpus is not necessarily equal to the
9613531Sjairo.balart@metempsy.com        # size of system.cpu; therefore if len(system.cpu) == 1
9713531Sjairo.balart@metempsy.com        # we use system.cpu[0] to set the clk_domain, thereby ensuring
9813531Sjairo.balart@metempsy.com        # we don't index off the end of the cpu list.
9913531Sjairo.balart@metempsy.com        if len(system.cpu) == 1:
10013531Sjairo.balart@metempsy.com            clk_domain = system.cpu[0].clk_domain
10113531Sjairo.balart@metempsy.com        else:
10213756Sjairo.balart@metempsy.com            clk_domain = system.cpu[i].clk_domain
10313756Sjairo.balart@metempsy.com
10413756Sjairo.balart@metempsy.com        l1_cntrl = L1Cache_Controller(version=i, L1Icache=l1i_cache,
10513756Sjairo.balart@metempsy.com                                      L1Dcache=l1d_cache, L2cache=l2_cache,
10613756Sjairo.balart@metempsy.com                                      no_mig_atomic=not \
10713756Sjairo.balart@metempsy.com                                      options.allow_atomic_migration,
10813756Sjairo.balart@metempsy.com                                      send_evictions=send_evicts(options),
10913756Sjairo.balart@metempsy.com                                      transitions_per_cycle=options.ports,
11013756Sjairo.balart@metempsy.com                                      clk_domain=clk_domain,
11113756Sjairo.balart@metempsy.com                                      ruby_system=ruby_system)
11213756Sjairo.balart@metempsy.com
11313756Sjairo.balart@metempsy.com        cpu_seq = RubySequencer(version=i, icache=l1i_cache,
11413531Sjairo.balart@metempsy.com                                dcache=l1d_cache,clk_domain=clk_domain,
11513531Sjairo.balart@metempsy.com                                ruby_system=ruby_system)
11613531Sjairo.balart@metempsy.com
11713531Sjairo.balart@metempsy.com        l1_cntrl.sequencer = cpu_seq
11813531Sjairo.balart@metempsy.com        if options.recycle_latency:
11913531Sjairo.balart@metempsy.com            l1_cntrl.recycle_latency = options.recycle_latency
12013531Sjairo.balart@metempsy.com
12113531Sjairo.balart@metempsy.com        exec("ruby_system.l1_cntrl%d = l1_cntrl" % i)
12213756Sjairo.balart@metempsy.com
12313531Sjairo.balart@metempsy.com        # Add controllers and sequencers to the appropriate lists
12413531Sjairo.balart@metempsy.com        cpu_sequencers.append(cpu_seq)
12513531Sjairo.balart@metempsy.com        l1_cntrl_nodes.append(l1_cntrl)
12613531Sjairo.balart@metempsy.com
12713756Sjairo.balart@metempsy.com        # Connect the L1 controller and the network
12813531Sjairo.balart@metempsy.com        # Connect the buffers from the controller to network
12913756Sjairo.balart@metempsy.com        l1_cntrl.requestFromCache = MessageBuffer()
13013531Sjairo.balart@metempsy.com        l1_cntrl.requestFromCache.master = ruby_system.network.slave
13113756Sjairo.balart@metempsy.com        l1_cntrl.responseFromCache = MessageBuffer()
13213756Sjairo.balart@metempsy.com        l1_cntrl.responseFromCache.master = ruby_system.network.slave
13313756Sjairo.balart@metempsy.com        l1_cntrl.unblockFromCache = MessageBuffer()
13413756Sjairo.balart@metempsy.com        l1_cntrl.unblockFromCache.master = ruby_system.network.slave
13513531Sjairo.balart@metempsy.com
13613531Sjairo.balart@metempsy.com        l1_cntrl.triggerQueue = MessageBuffer()
13713531Sjairo.balart@metempsy.com
13813531Sjairo.balart@metempsy.com        # Connect the buffers from the network to the controller
13913531Sjairo.balart@metempsy.com        l1_cntrl.mandatoryQueue = MessageBuffer()
14013531Sjairo.balart@metempsy.com        l1_cntrl.forwardToCache = MessageBuffer()
14113756Sjairo.balart@metempsy.com        l1_cntrl.forwardToCache.slave = ruby_system.network.master
14213756Sjairo.balart@metempsy.com        l1_cntrl.responseToCache = MessageBuffer()
14313756Sjairo.balart@metempsy.com        l1_cntrl.responseToCache.slave = ruby_system.network.master
14413756Sjairo.balart@metempsy.com
14513756Sjairo.balart@metempsy.com
14613756Sjairo.balart@metempsy.com    #
14713756Sjairo.balart@metempsy.com    # determine size and index bits for probe filter
14813531Sjairo.balart@metempsy.com    # By default, the probe filter size is configured to be twice the
14913531Sjairo.balart@metempsy.com    # size of the L2 cache.
15013531Sjairo.balart@metempsy.com    #
15113531Sjairo.balart@metempsy.com    pf_size = MemorySize(options.l2_size)
15213531Sjairo.balart@metempsy.com    pf_size.value = pf_size.value * 2
15313531Sjairo.balart@metempsy.com    dir_bits = int(math.log(options.num_dirs, 2))
15413531Sjairo.balart@metempsy.com    pf_bits = int(math.log(pf_size.value, 2))
15513756Sjairo.balart@metempsy.com    if options.numa_high_bit:
15613756Sjairo.balart@metempsy.com        if options.pf_on or options.dir_on:
15713925Sgiacomo.travaglini@arm.com            # if numa high bit explicitly set, make sure it does not overlap
15813925Sgiacomo.travaglini@arm.com            # with the probe filter index
15913925Sgiacomo.travaglini@arm.com            assert(options.numa_high_bit - dir_bits > pf_bits)
16013925Sgiacomo.travaglini@arm.com
16113531Sjairo.balart@metempsy.com        # set the probe filter start bit to just above the block offset
16213531Sjairo.balart@metempsy.com        pf_start_bit = block_size_bits
16313531Sjairo.balart@metempsy.com    else:
16413531Sjairo.balart@metempsy.com        if dir_bits > 0:
165            pf_start_bit = dir_bits + block_size_bits - 1
166        else:
167            pf_start_bit = block_size_bits
168
169    # Run each of the ruby memory controllers at a ratio of the frequency of
170    # the ruby system
171    # clk_divider value is a fix to pass regression.
172    ruby_system.memctrl_clk_domain = DerivedClockDomain(
173                                          clk_domain=ruby_system.clk_domain,
174                                          clk_divider=3)
175
176    mem_dir_cntrl_nodes, rom_dir_cntrl_node = create_directories(
177        options, bootmem, ruby_system, system)
178    dir_cntrl_nodes = mem_dir_cntrl_nodes[:]
179    if rom_dir_cntrl_node is not None:
180        dir_cntrl_nodes.append(rom_dir_cntrl_node)
181    for dir_cntrl in dir_cntrl_nodes:
182        pf = ProbeFilter(size = pf_size, assoc = 4,
183                         start_index_bit = pf_start_bit)
184
185        dir_cntrl.probeFilter = pf
186        dir_cntrl.probe_filter_enabled = options.pf_on
187        dir_cntrl.full_bit_dir_enabled = options.dir_on
188
189        if options.recycle_latency:
190            dir_cntrl.recycle_latency = options.recycle_latency
191
192        # Connect the directory controller to the network
193        dir_cntrl.forwardFromDir = MessageBuffer()
194        dir_cntrl.forwardFromDir.master = ruby_system.network.slave
195        dir_cntrl.responseFromDir = MessageBuffer()
196        dir_cntrl.responseFromDir.master = ruby_system.network.slave
197        dir_cntrl.dmaResponseFromDir = MessageBuffer(ordered = True)
198        dir_cntrl.dmaResponseFromDir.master = ruby_system.network.slave
199
200        dir_cntrl.triggerQueue = MessageBuffer(ordered = True)
201
202        dir_cntrl.unblockToDir = MessageBuffer()
203        dir_cntrl.unblockToDir.slave = ruby_system.network.master
204        dir_cntrl.responseToDir = MessageBuffer()
205        dir_cntrl.responseToDir.slave = ruby_system.network.master
206        dir_cntrl.requestToDir = MessageBuffer()
207        dir_cntrl.requestToDir.slave = ruby_system.network.master
208        dir_cntrl.dmaRequestToDir = MessageBuffer(ordered = True)
209        dir_cntrl.dmaRequestToDir.slave = ruby_system.network.master
210        dir_cntrl.responseFromMemory = MessageBuffer()
211
212
213    for i, dma_port in enumerate(dma_ports):
214        #
215        # Create the Ruby objects associated with the dma controller
216        #
217        dma_seq = DMASequencer(version = i,
218                               ruby_system = ruby_system,
219                               slave = dma_port)
220
221        dma_cntrl = DMA_Controller(version = i,
222                                   dma_sequencer = dma_seq,
223                                   transitions_per_cycle = options.ports,
224                                   ruby_system = ruby_system)
225
226        exec("ruby_system.dma_cntrl%d = dma_cntrl" % i)
227        dma_cntrl_nodes.append(dma_cntrl)
228
229        if options.recycle_latency:
230            dma_cntrl.recycle_latency = options.recycle_latency
231
232        # Connect the dma controller to the network
233        dma_cntrl.responseFromDir = MessageBuffer(ordered = True)
234        dma_cntrl.responseFromDir.slave = ruby_system.network.master
235        dma_cntrl.requestToDir = MessageBuffer()
236        dma_cntrl.requestToDir.master = ruby_system.network.slave
237        dma_cntrl.mandatoryQueue = MessageBuffer()
238
239    all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes
240
241    # Create the io controller and the sequencer
242    if full_system:
243        io_seq = DMASequencer(version=len(dma_ports), ruby_system=ruby_system)
244        ruby_system._io_port = io_seq
245        io_controller = DMA_Controller(version = len(dma_ports),
246                                       dma_sequencer = io_seq,
247                                       ruby_system = ruby_system)
248        ruby_system.io_controller = io_controller
249
250        # Connect the dma controller to the network
251        io_controller.responseFromDir = MessageBuffer(ordered = True)
252        io_controller.responseFromDir.slave = ruby_system.network.master
253        io_controller.requestToDir = MessageBuffer()
254        io_controller.requestToDir.master = ruby_system.network.slave
255        io_controller.mandatoryQueue = MessageBuffer()
256
257        all_cntrls = all_cntrls + [io_controller]
258
259    ruby_system.network.number_of_virtual_networks = 6
260    topology = create_topology(all_cntrls, options)
261    return (cpu_sequencers, mem_dir_cntrl_nodes, topology)
262