1# Copyright (c) 2011-2015 Advanced Micro Devices, Inc.
2# All rights reserved.
3#
4# For use for simulation and test purposes only
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are met:
8#
9# 1. Redistributions of source code must retain the above copyright notice,
10# this list of conditions and the following disclaimer.
11#
12# 2. Redistributions in binary form must reproduce the above copyright notice,
13# this list of conditions and the following disclaimer in the documentation
14# and/or other materials provided with the distribution.
15#
16# 3. Neither the name of the copyright holder nor the names of its
17# contributors may be used to endorse or promote products derived from this
18# software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30# POSSIBILITY OF SUCH DAMAGE.
31#
32# Authors: Lisa Hsu
33
34from __future__ import print_function
35from __future__ import absolute_import
36
37# Configure the TLB hierarchy
38# Places which would probably need to be modified if you
39# want a different hierarchy are specified by a <Modify here .. >'
40# comment
41import m5
42from m5.objects import *
43
44def TLB_constructor(level):
45
46    constructor_call = "X86GPUTLB(size = options.L%(level)dTLBentries, \
47            assoc = options.L%(level)dTLBassoc, \
48            hitLatency = options.L%(level)dAccessLatency,\
49            missLatency2 = options.L%(level)dMissLatency,\
50            maxOutstandingReqs = options.L%(level)dMaxOutstandingReqs,\
51            accessDistance = options.L%(level)dAccessDistanceStat,\
52            clk_domain = SrcClockDomain(\
53                clock = options.GPUClock,\
54                voltage_domain = VoltageDomain(\
55                    voltage = options.gpu_voltage)))" % locals()
56    return constructor_call
57
58def Coalescer_constructor(level):
59
60    constructor_call = "TLBCoalescer(probesPerCycle = \
61                options.L%(level)dProbesPerCycle, \
62                coalescingWindow = options.L%(level)dCoalescingWindow,\
63                disableCoalescing = options.L%(level)dDisableCoalescing,\
64                clk_domain = SrcClockDomain(\
65                    clock = options.GPUClock,\
66                    voltage_domain = VoltageDomain(\
67                        voltage = options.gpu_voltage)))" % locals()
68    return constructor_call
69
70def create_TLB_Coalescer(options, my_level, my_index, TLB_name, Coalescer_name):
71    # arguments: options, TLB level, number of private structures for this Level,
72    # TLB name and  Coalescer name
73    for i in range(my_index):
74        TLB_name.append(eval(TLB_constructor(my_level)))
75        Coalescer_name.append(eval(Coalescer_constructor(my_level)))
76
77def config_tlb_hierarchy(options, system, shader_idx):
78    n_cu = options.num_compute_units
79    # Make this configurable now, instead of the hard coded val.  The dispatcher
80    # is always the last item in the system.cpu list.
81    dispatcher_idx = len(system.cpu) - 1
82
83    if options.TLB_config == "perLane":
84        num_TLBs = 64 * n_cu
85    elif options.TLB_config == "mono":
86        num_TLBs = 1
87    elif options.TLB_config == "perCU":
88        num_TLBs = n_cu
89    elif options.TLB_config == "2CU":
90        num_TLBs = n_cu >> 1
91    else:
92        print("Bad option for TLB Configuration.")
93        sys.exit(1)
94
95    #----------------------------------------------------------------------------------------
96    # A visual representation of the TLB hierarchy
97    # for ease of configuration
98    # < Modify here the width and the number of levels if you want a different configuration >
99    # width is the number of TLBs of the given type (i.e., D-TLB, I-TLB etc) for this level
100    L1 = [{'name': 'sqc', 'width': options.num_sqc, 'TLBarray': [], 'CoalescerArray': []},
101          {'name': 'dispatcher', 'width': 1, 'TLBarray': [], 'CoalescerArray': []},
102          {'name': 'l1', 'width': num_TLBs, 'TLBarray': [], 'CoalescerArray': []}]
103
104    L2 = [{'name': 'l2', 'width': 1, 'TLBarray': [], 'CoalescerArray': []}]
105    L3 = [{'name': 'l3', 'width': 1, 'TLBarray': [], 'CoalescerArray': []}]
106
107    TLB_hierarchy = [L1, L2, L3]
108
109    #----------------------------------------------------------------------------------------
110    # Create the hiearchy
111    # Call the appropriate constructors and add objects to the system
112
113    for i in range(len(TLB_hierarchy)):
114        hierarchy_level = TLB_hierarchy[i]
115        level = i+1
116        for TLB_type in hierarchy_level:
117            TLB_index = TLB_type['width']
118            TLB_array = TLB_type['TLBarray']
119            Coalescer_array = TLB_type['CoalescerArray']
120            # If the sim calls for a fixed L1 TLB size across CUs,
121            # override the TLB entries option
122            if options.tot_L1TLB_size:
123                options.L1TLBentries = options.tot_L1TLB_size / num_TLBs
124                if options.L1TLBassoc > options.L1TLBentries:
125                    options.L1TLBassoc = options.L1TLBentries
126            # call the constructors for the TLB and the Coalescer
127            create_TLB_Coalescer(options, level, TLB_index,\
128                TLB_array, Coalescer_array)
129
130            system_TLB_name = TLB_type['name'] + '_tlb'
131            system_Coalescer_name = TLB_type['name'] + '_coalescer'
132
133            # add the different TLB levels to the system
134            # Modify here if you want to make the TLB hierarchy a child of
135            # the shader.
136            exec('system.%s = TLB_array' % system_TLB_name)
137            exec('system.%s = Coalescer_array' % system_Coalescer_name)
138
139    #===========================================================
140    # Specify the TLB hierarchy (i.e., port connections)
141    # All TLBs but the last level TLB need to have a memSidePort (master)
142    #===========================================================
143
144    # Each TLB is connected with its Coalescer through a single port.
145    # There is a one-to-one mapping of TLBs to Coalescers at a given level
146    # This won't be modified no matter what the hierarchy looks like.
147    for i in range(len(TLB_hierarchy)):
148        hierarchy_level = TLB_hierarchy[i]
149        level = i+1
150        for TLB_type in hierarchy_level:
151            name = TLB_type['name']
152            for index in range(TLB_type['width']):
153                exec('system.%s_coalescer[%d].master[0] = \
154                        system.%s_tlb[%d].slave[0]' % \
155                        (name, index, name, index))
156
157    # Connect the cpuSidePort (slave) of all the coalescers in level 1
158    # < Modify here if you want a different configuration >
159    for TLB_type in L1:
160        name = TLB_type['name']
161        num_TLBs = TLB_type['width']
162        if name == 'l1':     # L1 D-TLBs
163            tlb_per_cu = num_TLBs // n_cu
164            for cu_idx in range(n_cu):
165                if tlb_per_cu:
166                    for tlb in range(tlb_per_cu):
167                        exec('system.cpu[%d].CUs[%d].translation_port[%d] = \
168                                system.l1_coalescer[%d].slave[%d]' % \
169                                (shader_idx, cu_idx, tlb, cu_idx*tlb_per_cu+tlb, 0))
170                else:
171                    exec('system.cpu[%d].CUs[%d].translation_port[%d] = \
172                            system.l1_coalescer[%d].slave[%d]' % \
173                            (shader_idx, cu_idx, tlb_per_cu, cu_idx / (n_cu / num_TLBs), cu_idx % (n_cu / num_TLBs)))
174
175        elif name == 'dispatcher': # Dispatcher TLB
176            for index in range(TLB_type['width']):
177                exec('system.cpu[%d].translation_port = \
178                        system.dispatcher_coalescer[%d].slave[0]' % \
179                        (dispatcher_idx, index))
180        elif name == 'sqc': # I-TLB
181            for index in range(n_cu):
182                sqc_tlb_index = index / options.cu_per_sqc
183                sqc_tlb_port_id = index % options.cu_per_sqc
184                exec('system.cpu[%d].CUs[%d].sqc_tlb_port = \
185                        system.sqc_coalescer[%d].slave[%d]' % \
186                        (shader_idx, index, sqc_tlb_index, sqc_tlb_port_id))
187
188
189    # Connect the memSidePorts (masters) of all the TLBs with the
190    # cpuSidePorts (slaves) of the Coalescers of the next level
191    # < Modify here if you want a different configuration >
192    # L1 <-> L2
193    l2_coalescer_index = 0
194    for TLB_type in L1:
195        name = TLB_type['name']
196        for index in range(TLB_type['width']):
197            exec('system.%s_tlb[%d].master[0] = \
198                    system.l2_coalescer[0].slave[%d]' % \
199                    (name, index, l2_coalescer_index))
200            l2_coalescer_index += 1
201    # L2 <-> L3
202    system.l2_tlb[0].master[0] = system.l3_coalescer[0].slave[0]
203
204    return system
205