MOESI_CMP_token.py revision 10519
112952Sgabeblack@google.com# Copyright (c) 2006-2007 The Regents of The University of Michigan
212952Sgabeblack@google.com# Copyright (c) 2009 Advanced Micro Devices, Inc.
312952Sgabeblack@google.com# All rights reserved.
412952Sgabeblack@google.com#
512952Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without
612952Sgabeblack@google.com# modification, are permitted provided that the following conditions are
712952Sgabeblack@google.com# met: redistributions of source code must retain the above copyright
812952Sgabeblack@google.com# notice, this list of conditions and the following disclaimer;
912952Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright
1012952Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the
1112952Sgabeblack@google.com# documentation and/or other materials provided with the distribution;
1212952Sgabeblack@google.com# neither the name of the copyright holders nor the names of its
1312952Sgabeblack@google.com# contributors may be used to endorse or promote products derived from
1412952Sgabeblack@google.com# this software without specific prior written permission.
1512952Sgabeblack@google.com#
1612952Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712952Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812952Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912952Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012952Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112952Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212952Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312952Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412952Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512952Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612952Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712952Sgabeblack@google.com#
2812952Sgabeblack@google.com# Authors: Brad Beckmann
2912952Sgabeblack@google.com
3012952Sgabeblack@google.comimport math
3112952Sgabeblack@google.comimport m5
3212952Sgabeblack@google.comfrom m5.objects import *
3312952Sgabeblack@google.comfrom m5.defines import buildEnv
3412997Sgabeblack@google.comfrom Ruby import create_topology
3512957Sgabeblack@google.com
3612952Sgabeblack@google.com#
3712952Sgabeblack@google.com# Note: the L1 Cache latency is only used by the sequencer on fast path hits
3812957Sgabeblack@google.com#
3912957Sgabeblack@google.comclass L1Cache(RubyCache):
4013132Sgabeblack@google.com    latency = 2
4112953Sgabeblack@google.com
4212952Sgabeblack@google.com#
4313063Sgabeblack@google.com# Note: the L2 Cache latency is not currently used
4412952Sgabeblack@google.com#
4512991Sgabeblack@google.comclass L2Cache(RubyCache):
4612957Sgabeblack@google.com    latency = 10
4712952Sgabeblack@google.com
4812957Sgabeblack@google.comdef define_options(parser):
4912952Sgabeblack@google.com    parser.add_option("--l1-retries", type="int", default=1,
5012997Sgabeblack@google.com                      help="Token_CMP: # of l1 retries before going persistent")
5112952Sgabeblack@google.com    parser.add_option("--timeout-latency", type="int", default=300,
5212952Sgabeblack@google.com                      help="Token_CMP: cycles until issuing again");
5312952Sgabeblack@google.com    parser.add_option("--disable-dyn-timeouts", action="store_true",
5412952Sgabeblack@google.com          help="Token_CMP: disable dyanimc timeouts, use fixed latency instead")
5513175Sgabeblack@google.com    parser.add_option("--allow-atomic-migration", action="store_true",
5613175Sgabeblack@google.com          help="allow migratory sharing for atomic only accessed blocks")
5713175Sgabeblack@google.com
5812957Sgabeblack@google.comdef create_system(options, full_system, system, dma_ports, ruby_system):
5912957Sgabeblack@google.com
6012957Sgabeblack@google.com    if buildEnv['PROTOCOL'] != 'MOESI_CMP_token':
6112957Sgabeblack@google.com        panic("This script requires the MOESI_CMP_token protocol to be built.")
6212957Sgabeblack@google.com
6312957Sgabeblack@google.com    #
6412957Sgabeblack@google.com    # number of tokens that the owner passes to requests so that shared blocks can
6512957Sgabeblack@google.com    # respond to read requests
6612957Sgabeblack@google.com    #
6713189Sgabeblack@google.com    n_tokens = options.num_cpus + 1
6813189Sgabeblack@google.com
6913189Sgabeblack@google.com    cpu_sequencers = []
7012957Sgabeblack@google.com
7112957Sgabeblack@google.com    #
7212957Sgabeblack@google.com    # The ruby network creation expects the list of nodes in the system to be
7312957Sgabeblack@google.com    # consistent with the NetDest list.  Therefore the l1 controller nodes must be
7412957Sgabeblack@google.com    # listed before the directory nodes and directory nodes before dma nodes, etc.
7512957Sgabeblack@google.com    #
7612957Sgabeblack@google.com    l1_cntrl_nodes = []
7712957Sgabeblack@google.com    l2_cntrl_nodes = []
7812957Sgabeblack@google.com    dir_cntrl_nodes = []
7912962Sgabeblack@google.com    dma_cntrl_nodes = []
8013063Sgabeblack@google.com
8112957Sgabeblack@google.com    #
8212957Sgabeblack@google.com    # Must create the individual controllers before the network to ensure the
8312957Sgabeblack@google.com    # controller constructors are called before the network constructor
8412957Sgabeblack@google.com    #
8512957Sgabeblack@google.com    l2_bits = int(math.log(options.num_l2caches, 2))
8612957Sgabeblack@google.com    block_size_bits = int(math.log(options.cacheline_size, 2))
8712957Sgabeblack@google.com
8812957Sgabeblack@google.com    for i in xrange(options.num_cpus):
8912957Sgabeblack@google.com        #
9012957Sgabeblack@google.com        # First create the Ruby objects associated with this cpu
9112957Sgabeblack@google.com        #
9212957Sgabeblack@google.com        l1i_cache = L1Cache(size = options.l1i_size,
9312957Sgabeblack@google.com                            assoc = options.l1i_assoc,
9412957Sgabeblack@google.com                            start_index_bit = block_size_bits)
9512957Sgabeblack@google.com        l1d_cache = L1Cache(size = options.l1d_size,
9612957Sgabeblack@google.com                            assoc = options.l1d_assoc,
9712957Sgabeblack@google.com                            start_index_bit = block_size_bits)
9812957Sgabeblack@google.com
9912957Sgabeblack@google.com        l1_cntrl = L1Cache_Controller(version = i,
10012957Sgabeblack@google.com                                      L1Icache = l1i_cache,
10112957Sgabeblack@google.com                                      L1Dcache = l1d_cache,
10212957Sgabeblack@google.com                                      l2_select_num_bits = l2_bits,
10312957Sgabeblack@google.com                                      N_tokens = n_tokens,
10412957Sgabeblack@google.com                                      retry_threshold = \
10512957Sgabeblack@google.com                                        options.l1_retries,
10612957Sgabeblack@google.com                                      fixed_timeout_latency = \
10712957Sgabeblack@google.com                                        options.timeout_latency,
10812957Sgabeblack@google.com                                      dynamic_timeout_enabled = \
10912957Sgabeblack@google.com                                        not options.disable_dyn_timeouts,
11012957Sgabeblack@google.com                                      no_mig_atomic = not \
11112962Sgabeblack@google.com                                        options.allow_atomic_migration,
11212957Sgabeblack@google.com                                      send_evictions = (
11312957Sgabeblack@google.com                                          options.cpu_type == "detailed"),
11412957Sgabeblack@google.com                                      transitions_per_cycle = options.ports,
11512957Sgabeblack@google.com                                      clk_domain=system.cpu[i].clk_domain,
11612957Sgabeblack@google.com                                      ruby_system = ruby_system)
11712957Sgabeblack@google.com
11812957Sgabeblack@google.com        cpu_seq = RubySequencer(version = i,
11912957Sgabeblack@google.com                                icache = l1i_cache,
12012957Sgabeblack@google.com                                dcache = l1d_cache,
12112957Sgabeblack@google.com                                clk_domain=system.cpu[i].clk_domain,
12212957Sgabeblack@google.com                                ruby_system = ruby_system)
12312957Sgabeblack@google.com
12412957Sgabeblack@google.com        l1_cntrl.sequencer = cpu_seq
12512957Sgabeblack@google.com        exec("ruby_system.l1_cntrl%d = l1_cntrl" % i)
12612957Sgabeblack@google.com
12712957Sgabeblack@google.com        # Add controllers and sequencers to the appropriate lists
12812957Sgabeblack@google.com        cpu_sequencers.append(cpu_seq)
12912957Sgabeblack@google.com        l1_cntrl_nodes.append(l1_cntrl)
13012957Sgabeblack@google.com
13112957Sgabeblack@google.com        # Connect the L1 controllers and the network
13212957Sgabeblack@google.com        l1_cntrl.requestFromL1Cache =  ruby_system.network.slave
13312957Sgabeblack@google.com        l1_cntrl.responseFromL1Cache =  ruby_system.network.slave
13412957Sgabeblack@google.com        l1_cntrl.persistentFromL1Cache =  ruby_system.network.slave
13513189Sgabeblack@google.com
13613189Sgabeblack@google.com        l1_cntrl.requestToL1Cache =  ruby_system.network.master
13712957Sgabeblack@google.com        l1_cntrl.responseToL1Cache =  ruby_system.network.master
13812957Sgabeblack@google.com        l1_cntrl.persistentToL1Cache =  ruby_system.network.master
13912957Sgabeblack@google.com
14012957Sgabeblack@google.com
14112957Sgabeblack@google.com    l2_index_start = block_size_bits + l2_bits
14212957Sgabeblack@google.com
14312957Sgabeblack@google.com    for i in xrange(options.num_l2caches):
14412957Sgabeblack@google.com        #
14512957Sgabeblack@google.com        # First create the Ruby objects associated with this cpu
14612957Sgabeblack@google.com        #
14712957Sgabeblack@google.com        l2_cache = L2Cache(size = options.l2_size,
14812957Sgabeblack@google.com                           assoc = options.l2_assoc,
14913075Sgabeblack@google.com                           start_index_bit = l2_index_start)
15013075Sgabeblack@google.com
15112957Sgabeblack@google.com        l2_cntrl = L2Cache_Controller(version = i,
15212957Sgabeblack@google.com                                      L2cache = l2_cache,
15312957Sgabeblack@google.com                                      N_tokens = n_tokens,
15412957Sgabeblack@google.com                                      transitions_per_cycle = options.ports,
15512957Sgabeblack@google.com                                      ruby_system = ruby_system)
15612957Sgabeblack@google.com
15712957Sgabeblack@google.com        exec("ruby_system.l2_cntrl%d = l2_cntrl" % i)
15812957Sgabeblack@google.com        l2_cntrl_nodes.append(l2_cntrl)
15912957Sgabeblack@google.com
16012957Sgabeblack@google.com        # Connect the L2 controllers and the network
16112957Sgabeblack@google.com        l2_cntrl.GlobalRequestFromL2Cache = ruby_system.network.slave
16212957Sgabeblack@google.com        l2_cntrl.L1RequestFromL2Cache = ruby_system.network.slave
16313189Sgabeblack@google.com        l2_cntrl.responseFromL2Cache = ruby_system.network.slave
16413189Sgabeblack@google.com
16512957Sgabeblack@google.com        l2_cntrl.GlobalRequestToL2Cache = ruby_system.network.master
16612957Sgabeblack@google.com        l2_cntrl.L1RequestToL2Cache = ruby_system.network.master
16712957Sgabeblack@google.com        l2_cntrl.responseToL2Cache = ruby_system.network.master
16812957Sgabeblack@google.com        l2_cntrl.persistentToL2Cache = ruby_system.network.master
16912957Sgabeblack@google.com
17012957Sgabeblack@google.com
17112957Sgabeblack@google.com    phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
17212957Sgabeblack@google.com    assert(phys_mem_size % options.num_dirs == 0)
17312957Sgabeblack@google.com    mem_module_size = phys_mem_size / options.num_dirs
17412957Sgabeblack@google.com
17512957Sgabeblack@google.com    # Run each of the ruby memory controllers at a ratio of the frequency of
17612957Sgabeblack@google.com    # the ruby system
17712957Sgabeblack@google.com    # clk_divider value is a fix to pass regression.
17812957Sgabeblack@google.com    ruby_system.memctrl_clk_domain = DerivedClockDomain(
17912957Sgabeblack@google.com                                          clk_domain=ruby_system.clk_domain,
18012957Sgabeblack@google.com                                          clk_divider=3)
18112957Sgabeblack@google.com
18212957Sgabeblack@google.com    for i in xrange(options.num_dirs):
18312957Sgabeblack@google.com        #
18412957Sgabeblack@google.com        # Create the Ruby objects associated with the directory controller
18512957Sgabeblack@google.com        #
18612957Sgabeblack@google.com
18712957Sgabeblack@google.com        mem_cntrl = RubyMemoryControl(
18812957Sgabeblack@google.com                              clk_domain = ruby_system.memctrl_clk_domain,
18912957Sgabeblack@google.com                              version = i,
19012957Sgabeblack@google.com                              ruby_system = ruby_system)
19112957Sgabeblack@google.com
19212957Sgabeblack@google.com        dir_size = MemorySize('0B')
19312957Sgabeblack@google.com        dir_size.value = mem_module_size
19412957Sgabeblack@google.com
19512957Sgabeblack@google.com        dir_cntrl = Directory_Controller(version = i,
19612957Sgabeblack@google.com                                         directory = \
19712957Sgabeblack@google.com                                         RubyDirectoryMemory(version = i,
19812957Sgabeblack@google.com                                             use_map = options.use_map,
19912957Sgabeblack@google.com                                             size = dir_size),
20012957Sgabeblack@google.com                                         memBuffer = mem_cntrl,
20112957Sgabeblack@google.com                                         l2_select_num_bits = l2_bits,
20212957Sgabeblack@google.com                                         transitions_per_cycle = options.ports,
20312957Sgabeblack@google.com                                         ruby_system = ruby_system)
20412957Sgabeblack@google.com
20512957Sgabeblack@google.com        exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
20612957Sgabeblack@google.com        dir_cntrl_nodes.append(dir_cntrl)
20712957Sgabeblack@google.com
20812957Sgabeblack@google.com        # Connect the directory controllers and the network
20912957Sgabeblack@google.com        dir_cntrl.requestToDir = ruby_system.network.master
21012957Sgabeblack@google.com        dir_cntrl.responseToDir = ruby_system.network.master
21112957Sgabeblack@google.com        dir_cntrl.persistentToDir = ruby_system.network.master
21212957Sgabeblack@google.com        dir_cntrl.dmaRequestToDir = ruby_system.network.master
21312957Sgabeblack@google.com
21412957Sgabeblack@google.com        dir_cntrl.requestFromDir = ruby_system.network.slave
21512957Sgabeblack@google.com        dir_cntrl.responseFromDir = ruby_system.network.slave
21612957Sgabeblack@google.com        dir_cntrl.persistentFromDir = ruby_system.network.slave
21712957Sgabeblack@google.com        dir_cntrl.dmaResponseFromDir = ruby_system.network.slave
21812957Sgabeblack@google.com
21912957Sgabeblack@google.com
22012957Sgabeblack@google.com    for i, dma_port in enumerate(dma_ports):
22112957Sgabeblack@google.com        #
22212957Sgabeblack@google.com        # Create the Ruby objects associated with the dma controller
22312957Sgabeblack@google.com        #
22412957Sgabeblack@google.com        dma_seq = DMASequencer(version = i,
22512957Sgabeblack@google.com                               ruby_system = ruby_system,
22612957Sgabeblack@google.com                               slave = dma_port)
22712957Sgabeblack@google.com
22812957Sgabeblack@google.com        dma_cntrl = DMA_Controller(version = i,
22912957Sgabeblack@google.com                                   dma_sequencer = dma_seq,
23012957Sgabeblack@google.com                                   transitions_per_cycle = options.ports,
23112957Sgabeblack@google.com                                   ruby_system = ruby_system)
23212957Sgabeblack@google.com
23312957Sgabeblack@google.com        exec("ruby_system.dma_cntrl%d = dma_cntrl" % i)
23412957Sgabeblack@google.com        dma_cntrl_nodes.append(dma_cntrl)
23513053Sgabeblack@google.com
23612957Sgabeblack@google.com        # Connect the dma controller to the network
23712957Sgabeblack@google.com        dma_cntrl.responseFromDir = ruby_system.network.master
23812957Sgabeblack@google.com        dma_cntrl.reqToDirectory = ruby_system.network.slave
23912957Sgabeblack@google.com
24012957Sgabeblack@google.com    all_cntrls = l1_cntrl_nodes + \
24112991Sgabeblack@google.com                 l2_cntrl_nodes + \
24212991Sgabeblack@google.com                 dir_cntrl_nodes + \
24312991Sgabeblack@google.com                 dma_cntrl_nodes
24412991Sgabeblack@google.com
24512991Sgabeblack@google.com    # Create the io controller and the sequencer
24612991Sgabeblack@google.com    if full_system:
24712991Sgabeblack@google.com        io_seq = DMASequencer(version=len(dma_ports), ruby_system=ruby_system)
24812991Sgabeblack@google.com        ruby_system._io_port = io_seq
24912991Sgabeblack@google.com        io_controller = DMA_Controller(version = len(dma_ports),
25012991Sgabeblack@google.com                                       dma_sequencer = io_seq,
25112991Sgabeblack@google.com                                       ruby_system = ruby_system)
25212991Sgabeblack@google.com        ruby_system.io_controller = io_controller
25312991Sgabeblack@google.com
25412991Sgabeblack@google.com        # Connect the dma controller to the network
25512991Sgabeblack@google.com        io_controller.responseFromDir = ruby_system.network.master
25612991Sgabeblack@google.com        io_controller.reqToDirectory = ruby_system.network.slave
25712991Sgabeblack@google.com
25812991Sgabeblack@google.com        all_cntrls = all_cntrls + [io_controller]
25912957Sgabeblack@google.com
26012957Sgabeblack@google.com
26112957Sgabeblack@google.com    topology = create_topology(all_cntrls, options)
26212957Sgabeblack@google.com    return (cpu_sequencers, dir_cntrl_nodes, topology)
26312957Sgabeblack@google.com