tests: arch-power: Add 64-bit hello binaries
[gem5.git] / configs / ruby / MESI_Three_Level.py
1 # Copyright (c) 2006-2007 The Regents of The University of Michigan
2 # Copyright (c) 2009,2015 Advanced Micro Devices, Inc.
3 # Copyright (c) 2013 Mark D. Hill and David A. Wood
4 # Copyright (c) 2020 ARM Limited
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are
9 # met: redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer;
11 # redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution;
14 # neither the name of the copyright holders nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 import math
31 import m5
32 from m5.objects import *
33 from m5.defines import buildEnv
34 from .Ruby import create_topology, create_directories
35 from .Ruby import send_evicts
36 from common import FileSystemConfig
37
38 #
39 # Declare caches used by the protocol
40 #
41 class L0Cache(RubyCache): pass
42 class L1Cache(RubyCache): pass
43 class L2Cache(RubyCache): pass
44
45 def define_options(parser):
46 parser.add_option("--num-clusters", type = "int", default = 1,
47 help = "number of clusters in a design in which there are shared\
48 caches private to clusters")
49 parser.add_option("--l0i_size", type="string", default="4096B")
50 parser.add_option("--l0d_size", type="string", default="4096B")
51 parser.add_option("--l0i_assoc", type="int", default=1)
52 parser.add_option("--l0d_assoc", type="int", default=1)
53 parser.add_option("--l0_transitions_per_cycle", type="int", default=32)
54 parser.add_option("--l1_transitions_per_cycle", type="int", default=32)
55 parser.add_option("--l2_transitions_per_cycle", type="int", default=4)
56 parser.add_option("--enable-prefetch", action="store_true", default=False,\
57 help="Enable Ruby hardware prefetcher")
58 return
59
60 def create_system(options, full_system, system, dma_ports, bootmem,
61 ruby_system):
62
63 if buildEnv['PROTOCOL'] != 'MESI_Three_Level':
64 fatal("This script requires the MESI_Three_Level protocol to be\
65 built.")
66
67 cpu_sequencers = []
68
69 #
70 # The ruby network creation expects the list of nodes in the system to be
71 # consistent with the NetDest list. Therefore the l1 controller nodes
72 # must be listed before the directory nodes and directory nodes before
73 # dma nodes, etc.
74 #
75 l0_cntrl_nodes = []
76 l1_cntrl_nodes = []
77 l2_cntrl_nodes = []
78 dma_cntrl_nodes = []
79
80 assert (options.num_cpus % options.num_clusters == 0)
81 num_cpus_per_cluster = options.num_cpus / options.num_clusters
82
83 assert (options.num_l2caches % options.num_clusters == 0)
84 num_l2caches_per_cluster = options.num_l2caches / options.num_clusters
85
86 l2_bits = int(math.log(num_l2caches_per_cluster, 2))
87 block_size_bits = int(math.log(options.cacheline_size, 2))
88 l2_index_start = block_size_bits + l2_bits
89
90 #
91 # Must create the individual controllers before the network to ensure the
92 # controller constructors are called before the network constructor
93 #
94 for i in range(options.num_clusters):
95 for j in range(num_cpus_per_cluster):
96 #
97 # First create the Ruby objects associated with this cpu
98 #
99 l0i_cache = L0Cache(size = options.l0i_size,
100 assoc = options.l0i_assoc,
101 is_icache = True,
102 start_index_bit = block_size_bits,
103 replacement_policy = LRURP())
104
105 l0d_cache = L0Cache(size = options.l0d_size,
106 assoc = options.l0d_assoc,
107 is_icache = False,
108 start_index_bit = block_size_bits,
109 replacement_policy = LRURP())
110
111 # the ruby random tester reuses num_cpus to specify the
112 # number of cpu ports connected to the tester object, which
113 # is stored in system.cpu. because there is only ever one
114 # tester object, num_cpus is not necessarily equal to the
115 # size of system.cpu; therefore if len(system.cpu) == 1
116 # we use system.cpu[0] to set the clk_domain, thereby ensuring
117 # we don't index off the end of the cpu list.
118 if len(system.cpu) == 1:
119 clk_domain = system.cpu[0].clk_domain
120 else:
121 clk_domain = system.cpu[i].clk_domain
122
123 # Ruby prefetcher
124 prefetcher = RubyPrefetcher(
125 num_streams=16,
126 unit_filter = 256,
127 nonunit_filter = 256,
128 train_misses = 5,
129 num_startup_pfs = 4,
130 cross_page = True
131 )
132
133 l0_cntrl = L0Cache_Controller(
134 version = i * num_cpus_per_cluster + j,
135 Icache = l0i_cache, Dcache = l0d_cache,
136 transitions_per_cycle = options.l0_transitions_per_cycle,
137 prefetcher = prefetcher,
138 enable_prefetch = options.enable_prefetch,
139 send_evictions = send_evicts(options),
140 clk_domain = clk_domain,
141 ruby_system = ruby_system)
142
143 cpu_seq = RubySequencer(version = i * num_cpus_per_cluster + j,
144 clk_domain = clk_domain,
145 dcache = l0d_cache,
146 ruby_system = ruby_system)
147
148 l0_cntrl.sequencer = cpu_seq
149
150 l1_cache = L1Cache(size = options.l1d_size,
151 assoc = options.l1d_assoc,
152 start_index_bit = block_size_bits,
153 is_icache = False)
154
155 l1_cntrl = L1Cache_Controller(
156 version = i * num_cpus_per_cluster + j,
157 cache = l1_cache, l2_select_num_bits = l2_bits,
158 cluster_id = i,
159 transitions_per_cycle = options.l1_transitions_per_cycle,
160 ruby_system = ruby_system)
161
162 exec("ruby_system.l0_cntrl%d = l0_cntrl"
163 % ( i * num_cpus_per_cluster + j))
164 exec("ruby_system.l1_cntrl%d = l1_cntrl"
165 % ( i * num_cpus_per_cluster + j))
166
167 #
168 # Add controllers and sequencers to the appropriate lists
169 #
170 cpu_sequencers.append(cpu_seq)
171 l0_cntrl_nodes.append(l0_cntrl)
172 l1_cntrl_nodes.append(l1_cntrl)
173
174 # Connect the L0 and L1 controllers
175 l0_cntrl.prefetchQueue = MessageBuffer()
176 l0_cntrl.mandatoryQueue = MessageBuffer()
177 l0_cntrl.bufferToL1 = MessageBuffer(ordered = True)
178 l1_cntrl.bufferFromL0 = l0_cntrl.bufferToL1
179 l0_cntrl.bufferFromL1 = MessageBuffer(ordered = True)
180 l1_cntrl.bufferToL0 = l0_cntrl.bufferFromL1
181
182 # Connect the L1 controllers and the network
183 l1_cntrl.requestToL2 = MessageBuffer()
184 l1_cntrl.requestToL2.master = ruby_system.network.slave
185 l1_cntrl.responseToL2 = MessageBuffer()
186 l1_cntrl.responseToL2.master = ruby_system.network.slave
187 l1_cntrl.unblockToL2 = MessageBuffer()
188 l1_cntrl.unblockToL2.master = ruby_system.network.slave
189
190 l1_cntrl.requestFromL2 = MessageBuffer()
191 l1_cntrl.requestFromL2.slave = ruby_system.network.master
192 l1_cntrl.responseFromL2 = MessageBuffer()
193 l1_cntrl.responseFromL2.slave = ruby_system.network.master
194
195
196 for j in range(num_l2caches_per_cluster):
197 l2_cache = L2Cache(size = options.l2_size,
198 assoc = options.l2_assoc,
199 start_index_bit = l2_index_start)
200
201 l2_cntrl = L2Cache_Controller(
202 version = i * num_l2caches_per_cluster + j,
203 L2cache = l2_cache, cluster_id = i,
204 transitions_per_cycle =\
205 options.l2_transitions_per_cycle,
206 ruby_system = ruby_system)
207
208 exec("ruby_system.l2_cntrl%d = l2_cntrl"
209 % (i * num_l2caches_per_cluster + j))
210 l2_cntrl_nodes.append(l2_cntrl)
211
212 # Connect the L2 controllers and the network
213 l2_cntrl.DirRequestFromL2Cache = MessageBuffer()
214 l2_cntrl.DirRequestFromL2Cache.master = ruby_system.network.slave
215 l2_cntrl.L1RequestFromL2Cache = MessageBuffer()
216 l2_cntrl.L1RequestFromL2Cache.master = ruby_system.network.slave
217 l2_cntrl.responseFromL2Cache = MessageBuffer()
218 l2_cntrl.responseFromL2Cache.master = ruby_system.network.slave
219
220 l2_cntrl.unblockToL2Cache = MessageBuffer()
221 l2_cntrl.unblockToL2Cache.slave = ruby_system.network.master
222 l2_cntrl.L1RequestToL2Cache = MessageBuffer()
223 l2_cntrl.L1RequestToL2Cache.slave = ruby_system.network.master
224 l2_cntrl.responseToL2Cache = MessageBuffer()
225 l2_cntrl.responseToL2Cache.slave = ruby_system.network.master
226
227 # Run each of the ruby memory controllers at a ratio of the frequency of
228 # the ruby system
229 # clk_divider value is a fix to pass regression.
230 ruby_system.memctrl_clk_domain = DerivedClockDomain(
231 clk_domain = ruby_system.clk_domain, clk_divider = 3)
232
233 mem_dir_cntrl_nodes, rom_dir_cntrl_node = create_directories(
234 options, bootmem, ruby_system, system)
235 dir_cntrl_nodes = mem_dir_cntrl_nodes[:]
236 if rom_dir_cntrl_node is not None:
237 dir_cntrl_nodes.append(rom_dir_cntrl_node)
238 for dir_cntrl in dir_cntrl_nodes:
239 # Connect the directory controllers and the network
240 dir_cntrl.requestToDir = MessageBuffer()
241 dir_cntrl.requestToDir.slave = ruby_system.network.master
242 dir_cntrl.responseToDir = MessageBuffer()
243 dir_cntrl.responseToDir.slave = ruby_system.network.master
244 dir_cntrl.responseFromDir = MessageBuffer()
245 dir_cntrl.responseFromDir.master = ruby_system.network.slave
246 dir_cntrl.requestToMemory = MessageBuffer()
247 dir_cntrl.responseFromMemory = MessageBuffer()
248
249 for i, dma_port in enumerate(dma_ports):
250 #
251 # Create the Ruby objects associated with the dma controller
252 #
253 dma_seq = DMASequencer(version = i, ruby_system = ruby_system)
254
255 dma_cntrl = DMA_Controller(version = i,
256 dma_sequencer = dma_seq,
257 transitions_per_cycle = options.ports,
258 ruby_system = ruby_system)
259
260 exec("ruby_system.dma_cntrl%d = dma_cntrl" % i)
261 exec("ruby_system.dma_cntrl%d.dma_sequencer.slave = dma_port" % i)
262 dma_cntrl_nodes.append(dma_cntrl)
263
264 # Connect the dma controller to the network
265 dma_cntrl.mandatoryQueue = MessageBuffer()
266 dma_cntrl.responseFromDir = MessageBuffer(ordered = True)
267 dma_cntrl.responseFromDir.slave = ruby_system.network.master
268 dma_cntrl.requestToDir = MessageBuffer()
269 dma_cntrl.requestToDir.master = ruby_system.network.slave
270
271 all_cntrls = l0_cntrl_nodes + \
272 l1_cntrl_nodes + \
273 l2_cntrl_nodes + \
274 dir_cntrl_nodes + \
275 dma_cntrl_nodes
276
277 # Create the io controller and the sequencer
278 if full_system:
279 io_seq = DMASequencer(version=len(dma_ports), ruby_system=ruby_system)
280 ruby_system._io_port = io_seq
281 io_controller = DMA_Controller(version = len(dma_ports),
282 dma_sequencer = io_seq,
283 ruby_system = ruby_system)
284 ruby_system.io_controller = io_controller
285
286 # Connect the dma controller to the network
287 io_controller.mandatoryQueue = MessageBuffer()
288 io_controller.responseFromDir = MessageBuffer(ordered = True)
289 io_controller.responseFromDir.slave = ruby_system.network.master
290 io_controller.requestToDir = MessageBuffer()
291 io_controller.requestToDir.master = ruby_system.network.slave
292
293 all_cntrls = all_cntrls + [io_controller]
294 # Register configuration with filesystem
295 else:
296 for i in range(options.num_clusters):
297 for j in range(num_cpus_per_cluster):
298 FileSystemConfig.register_cpu(physical_package_id = 0,
299 core_siblings = range(options.num_cpus),
300 core_id = i*num_cpus_per_cluster+j,
301 thread_siblings = [])
302
303 FileSystemConfig.register_cache(level = 0,
304 idu_type = 'Instruction',
305 size = options.l0i_size,
306 line_size =\
307 options.cacheline_size,
308 assoc = 1,
309 cpus = [i*num_cpus_per_cluster+j])
310 FileSystemConfig.register_cache(level = 0,
311 idu_type = 'Data',
312 size = options.l0d_size,
313 line_size =\
314 options.cacheline_size,
315 assoc = 1,
316 cpus = [i*num_cpus_per_cluster+j])
317
318 FileSystemConfig.register_cache(level = 1,
319 idu_type = 'Unified',
320 size = options.l1d_size,
321 line_size = options.cacheline_size,
322 assoc = options.l1d_assoc,
323 cpus = [i*num_cpus_per_cluster+j])
324
325 FileSystemConfig.register_cache(level = 2,
326 idu_type = 'Unified',
327 size = str(MemorySize(options.l2_size) * \
328 num_l2caches_per_cluster)+'B',
329 line_size = options.cacheline_size,
330 assoc = options.l2_assoc,
331 cpus = [n for n in range(i*num_cpus_per_cluster, \
332 (i+1)*num_cpus_per_cluster)])
333
334 ruby_system.network.number_of_virtual_networks = 3
335 topology = create_topology(all_cntrls, options)
336 return (cpu_sequencers, mem_dir_cntrl_nodes, topology)