configs: Remove Python 2.7 glue code
[gem5.git] / configs / example / fs.py
1 # Copyright (c) 2010-2013, 2016, 2019-2020 ARM Limited
2 # Copyright (c) 2020 Barkhausen Institut
3 # All rights reserved.
4 #
5 # The license below extends only to copyright in the software and shall
6 # not be construed as granting a license to any other intellectual
7 # property including but not limited to intellectual property relating
8 # to a hardware implementation of the functionality of the software
9 # licensed hereunder. You may use the software subject to the license
10 # terms below provided that you ensure that this notice is replicated
11 # unmodified and in its entirety in all distributions of the software,
12 # modified or unmodified, in source code or in binary form.
13 #
14 # Copyright (c) 2012-2014 Mark D. Hill and David A. Wood
15 # Copyright (c) 2009-2011 Advanced Micro Devices, Inc.
16 # Copyright (c) 2006-2007 The Regents of The University of Michigan
17 # All rights reserved.
18 #
19 # Redistribution and use in source and binary forms, with or without
20 # modification, are permitted provided that the following conditions are
21 # met: redistributions of source code must retain the above copyright
22 # notice, this list of conditions and the following disclaimer;
23 # redistributions in binary form must reproduce the above copyright
24 # notice, this list of conditions and the following disclaimer in the
25 # documentation and/or other materials provided with the distribution;
26 # neither the name of the copyright holders nor the names of its
27 # contributors may be used to endorse or promote products derived from
28 # this software without specific prior written permission.
29 #
30 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41
42 import optparse
43 import sys
44
45 import m5
46 from m5.defines import buildEnv
47 from m5.objects import *
48 from m5.util import addToPath, fatal, warn
49 from m5.util.fdthelper import *
50
51 addToPath('../')
52
53 from ruby import Ruby
54
55 from common.FSConfig import *
56 from common.SysPaths import *
57 from common.Benchmarks import *
58 from common import Simulation
59 from common import CacheConfig
60 from common import CpuConfig
61 from common import MemConfig
62 from common import ObjectList
63 from common.Caches import *
64 from common import Options
65
66 def cmd_line_template():
67 if options.command_line and options.command_line_file:
68 print("Error: --command-line and --command-line-file are "
69 "mutually exclusive")
70 sys.exit(1)
71 if options.command_line:
72 return options.command_line
73 if options.command_line_file:
74 return open(options.command_line_file).read().strip()
75 return None
76
77 def build_test_system(np):
78 cmdline = cmd_line_template()
79 if buildEnv['TARGET_ISA'] == "mips":
80 test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0], cmdline=cmdline)
81 elif buildEnv['TARGET_ISA'] == "sparc":
82 test_sys = makeSparcSystem(test_mem_mode, bm[0], cmdline=cmdline)
83 elif buildEnv['TARGET_ISA'] == "riscv":
84 test_sys = makeBareMetalRiscvSystem(test_mem_mode, bm[0],
85 cmdline=cmdline)
86 elif buildEnv['TARGET_ISA'] == "x86":
87 test_sys = makeLinuxX86System(test_mem_mode, np, bm[0], options.ruby,
88 cmdline=cmdline)
89 elif buildEnv['TARGET_ISA'] == "arm":
90 test_sys = makeArmSystem(
91 test_mem_mode,
92 options.machine_type,
93 np,
94 bm[0],
95 options.dtb_filename,
96 bare_metal=options.bare_metal,
97 cmdline=cmdline,
98 external_memory=options.external_memory_system,
99 ruby=options.ruby,
100 security=options.enable_security_extensions,
101 vio_9p=options.vio_9p,
102 bootloader=options.bootloader,
103 )
104 if options.enable_context_switch_stats_dump:
105 test_sys.enable_context_switch_stats_dump = True
106 else:
107 fatal("Incapable of building %s full system!", buildEnv['TARGET_ISA'])
108
109 # Set the cache line size for the entire system
110 test_sys.cache_line_size = options.cacheline_size
111
112 # Create a top-level voltage domain
113 test_sys.voltage_domain = VoltageDomain(voltage = options.sys_voltage)
114
115 # Create a source clock for the system and set the clock period
116 test_sys.clk_domain = SrcClockDomain(clock = options.sys_clock,
117 voltage_domain = test_sys.voltage_domain)
118
119 # Create a CPU voltage domain
120 test_sys.cpu_voltage_domain = VoltageDomain()
121
122 # Create a source clock for the CPUs and set the clock period
123 test_sys.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock,
124 voltage_domain =
125 test_sys.cpu_voltage_domain)
126
127 if buildEnv['TARGET_ISA'] == 'riscv':
128 test_sys.workload.bootloader = options.kernel
129 elif options.kernel is not None:
130 test_sys.workload.object_file = binary(options.kernel)
131
132 if options.script is not None:
133 test_sys.readfile = options.script
134
135 if options.lpae:
136 test_sys.have_lpae = True
137
138 if options.virtualisation:
139 test_sys.have_virtualization = True
140
141 test_sys.init_param = options.init_param
142
143 # For now, assign all the CPUs to the same clock domain
144 test_sys.cpu = [TestCPUClass(clk_domain=test_sys.cpu_clk_domain, cpu_id=i)
145 for i in range(np)]
146
147 if ObjectList.is_kvm_cpu(TestCPUClass) or \
148 ObjectList.is_kvm_cpu(FutureClass):
149 test_sys.kvm_vm = KvmVM()
150
151 if options.ruby:
152 bootmem = getattr(test_sys, '_bootmem', None)
153 Ruby.create_system(options, True, test_sys, test_sys.iobus,
154 test_sys._dma_ports, bootmem)
155
156 # Create a seperate clock domain for Ruby
157 test_sys.ruby.clk_domain = SrcClockDomain(clock = options.ruby_clock,
158 voltage_domain = test_sys.voltage_domain)
159
160 # Connect the ruby io port to the PIO bus,
161 # assuming that there is just one such port.
162 test_sys.iobus.master = test_sys.ruby._io_port.slave
163
164 for (i, cpu) in enumerate(test_sys.cpu):
165 #
166 # Tie the cpu ports to the correct ruby system ports
167 #
168 cpu.clk_domain = test_sys.cpu_clk_domain
169 cpu.createThreads()
170 cpu.createInterruptController()
171
172 test_sys.ruby._cpu_ports[i].connectCpuPorts(cpu)
173
174 else:
175 if options.caches or options.l2cache:
176 # By default the IOCache runs at the system clock
177 test_sys.iocache = IOCache(addr_ranges = test_sys.mem_ranges)
178 test_sys.iocache.cpu_side = test_sys.iobus.master
179 test_sys.iocache.mem_side = test_sys.membus.slave
180 elif not options.external_memory_system:
181 test_sys.iobridge = Bridge(delay='50ns', ranges = test_sys.mem_ranges)
182 test_sys.iobridge.slave = test_sys.iobus.master
183 test_sys.iobridge.master = test_sys.membus.slave
184
185 # Sanity check
186 if options.simpoint_profile:
187 if not ObjectList.is_noncaching_cpu(TestCPUClass):
188 fatal("SimPoint generation should be done with atomic cpu")
189 if np > 1:
190 fatal("SimPoint generation not supported with more than one CPUs")
191
192 for i in range(np):
193 if options.simpoint_profile:
194 test_sys.cpu[i].addSimPointProbe(options.simpoint_interval)
195 if options.checker:
196 test_sys.cpu[i].addCheckerCpu()
197 if not ObjectList.is_kvm_cpu(TestCPUClass):
198 if options.bp_type:
199 bpClass = ObjectList.bp_list.get(options.bp_type)
200 test_sys.cpu[i].branchPred = bpClass()
201 if options.indirect_bp_type:
202 IndirectBPClass = ObjectList.indirect_bp_list.get(
203 options.indirect_bp_type)
204 test_sys.cpu[i].branchPred.indirectBranchPred = \
205 IndirectBPClass()
206 test_sys.cpu[i].createThreads()
207
208 # If elastic tracing is enabled when not restoring from checkpoint and
209 # when not fast forwarding using the atomic cpu, then check that the
210 # TestCPUClass is DerivO3CPU or inherits from DerivO3CPU. If the check
211 # passes then attach the elastic trace probe.
212 # If restoring from checkpoint or fast forwarding, the code that does this for
213 # FutureCPUClass is in the Simulation module. If the check passes then the
214 # elastic trace probe is attached to the switch CPUs.
215 if options.elastic_trace_en and options.checkpoint_restore == None and \
216 not options.fast_forward:
217 CpuConfig.config_etrace(TestCPUClass, test_sys.cpu, options)
218
219 CacheConfig.config_cache(options, test_sys)
220
221 MemConfig.config_mem(options, test_sys)
222
223 return test_sys
224
225 def build_drive_system(np):
226 # driver system CPU is always simple, so is the memory
227 # Note this is an assignment of a class, not an instance.
228 DriveCPUClass = AtomicSimpleCPU
229 drive_mem_mode = 'atomic'
230 DriveMemClass = SimpleMemory
231
232 cmdline = cmd_line_template()
233 if buildEnv['TARGET_ISA'] == 'mips':
234 drive_sys = makeLinuxMipsSystem(drive_mem_mode, bm[1], cmdline=cmdline)
235 elif buildEnv['TARGET_ISA'] == 'sparc':
236 drive_sys = makeSparcSystem(drive_mem_mode, bm[1], cmdline=cmdline)
237 elif buildEnv['TARGET_ISA'] == 'x86':
238 drive_sys = makeLinuxX86System(drive_mem_mode, np, bm[1],
239 cmdline=cmdline)
240 elif buildEnv['TARGET_ISA'] == 'arm':
241 drive_sys = makeArmSystem(drive_mem_mode, options.machine_type, np,
242 bm[1], options.dtb_filename, cmdline=cmdline)
243
244 # Create a top-level voltage domain
245 drive_sys.voltage_domain = VoltageDomain(voltage = options.sys_voltage)
246
247 # Create a source clock for the system and set the clock period
248 drive_sys.clk_domain = SrcClockDomain(clock = options.sys_clock,
249 voltage_domain = drive_sys.voltage_domain)
250
251 # Create a CPU voltage domain
252 drive_sys.cpu_voltage_domain = VoltageDomain()
253
254 # Create a source clock for the CPUs and set the clock period
255 drive_sys.cpu_clk_domain = SrcClockDomain(clock = options.cpu_clock,
256 voltage_domain =
257 drive_sys.cpu_voltage_domain)
258
259 drive_sys.cpu = DriveCPUClass(clk_domain=drive_sys.cpu_clk_domain,
260 cpu_id=0)
261 drive_sys.cpu.createThreads()
262 drive_sys.cpu.createInterruptController()
263 drive_sys.cpu.connectAllPorts(drive_sys.membus)
264 if options.kernel is not None:
265 drive_sys.workload.object_file = binary(options.kernel)
266
267 if ObjectList.is_kvm_cpu(DriveCPUClass):
268 drive_sys.kvm_vm = KvmVM()
269
270 drive_sys.iobridge = Bridge(delay='50ns',
271 ranges = drive_sys.mem_ranges)
272 drive_sys.iobridge.slave = drive_sys.iobus.master
273 drive_sys.iobridge.master = drive_sys.membus.slave
274
275 # Create the appropriate memory controllers and connect them to the
276 # memory bus
277 drive_sys.mem_ctrls = [DriveMemClass(range = r)
278 for r in drive_sys.mem_ranges]
279 for i in range(len(drive_sys.mem_ctrls)):
280 drive_sys.mem_ctrls[i].port = drive_sys.membus.master
281
282 drive_sys.init_param = options.init_param
283
284 return drive_sys
285
286 # Add options
287 parser = optparse.OptionParser()
288 Options.addCommonOptions(parser)
289 Options.addFSOptions(parser)
290
291 # Add the ruby specific and protocol specific options
292 if '--ruby' in sys.argv:
293 Ruby.define_options(parser)
294
295 (options, args) = parser.parse_args()
296
297 if args:
298 print("Error: script doesn't take any positional arguments")
299 sys.exit(1)
300
301 # system under test can be any CPU
302 (TestCPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
303
304 # Match the memories with the CPUs, based on the options for the test system
305 TestMemClass = Simulation.setMemClass(options)
306
307 if options.benchmark:
308 try:
309 bm = Benchmarks[options.benchmark]
310 except KeyError:
311 print("Error benchmark %s has not been defined." % options.benchmark)
312 print("Valid benchmarks are: %s" % DefinedBenchmarks)
313 sys.exit(1)
314 else:
315 if options.dual:
316 bm = [SysConfig(disks=options.disk_image, rootdev=options.root_device,
317 mem=options.mem_size, os_type=options.os_type),
318 SysConfig(disks=options.disk_image, rootdev=options.root_device,
319 mem=options.mem_size, os_type=options.os_type)]
320 else:
321 bm = [SysConfig(disks=options.disk_image, rootdev=options.root_device,
322 mem=options.mem_size, os_type=options.os_type)]
323
324 np = options.num_cpus
325
326 test_sys = build_test_system(np)
327 if len(bm) == 2:
328 drive_sys = build_drive_system(np)
329 root = makeDualRoot(True, test_sys, drive_sys, options.etherdump)
330 elif len(bm) == 1 and options.dist:
331 # This system is part of a dist-gem5 simulation
332 root = makeDistRoot(test_sys,
333 options.dist_rank,
334 options.dist_size,
335 options.dist_server_name,
336 options.dist_server_port,
337 options.dist_sync_repeat,
338 options.dist_sync_start,
339 options.ethernet_linkspeed,
340 options.ethernet_linkdelay,
341 options.etherdump);
342 elif len(bm) == 1:
343 root = Root(full_system=True, system=test_sys)
344 else:
345 print("Error I don't know how to create more than 2 systems.")
346 sys.exit(1)
347
348 if options.timesync:
349 root.time_sync_enable = True
350
351 if options.frame_capture:
352 VncServer.frame_capture = True
353
354 if buildEnv['TARGET_ISA'] == "arm" and not options.bare_metal \
355 and not options.dtb_filename:
356 if options.machine_type not in ["VExpress_GEM5",
357 "VExpress_GEM5_V1",
358 "VExpress_GEM5_V2",
359 "VExpress_GEM5_Foundation"]:
360 warn("Can only correctly generate a dtb for VExpress_GEM5_* " \
361 "platforms, unless custom hardware models have been equipped "\
362 "with generation functionality.")
363
364 # Generate a Device Tree
365 for sysname in ('system', 'testsys', 'drivesys'):
366 if hasattr(root, sysname):
367 sys = getattr(root, sysname)
368 sys.workload.dtb_filename = \
369 os.path.join(m5.options.outdir, '%s.dtb' % sysname)
370 sys.generateDtb(sys.workload.dtb_filename)
371
372 Simulation.setWorkCountOptions(test_sys, options)
373 Simulation.run(options, root, test_sys, FutureClass)