1 # Copyright (c) 2010-2013, 2016, 2019-2020 ARM Limited
2 # Copyright (c) 2020 Barkhausen Institut
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.
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.
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.
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.
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 *
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
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 "
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()
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],
86 elif buildEnv
['TARGET_ISA'] == "x86":
87 test_sys
= makeLinuxX86System(test_mem_mode
, np
, bm
[0], options
.ruby
,
89 elif buildEnv
['TARGET_ISA'] == "arm":
90 test_sys
= makeArmSystem(
96 bare_metal
=options
.bare_metal
,
98 external_memory
=options
.external_memory_system
,
100 security
=options
.enable_security_extensions
,
101 vio_9p
=options
.vio_9p
,
102 bootloader
=options
.bootloader
,
104 if options
.enable_context_switch_stats_dump
:
105 test_sys
.enable_context_switch_stats_dump
= True
107 fatal("Incapable of building %s full system!", buildEnv
['TARGET_ISA'])
109 # Set the cache line size for the entire system
110 test_sys
.cache_line_size
= options
.cacheline_size
112 # Create a top-level voltage domain
113 test_sys
.voltage_domain
= VoltageDomain(voltage
= options
.sys_voltage
)
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
)
119 # Create a CPU voltage domain
120 test_sys
.cpu_voltage_domain
= VoltageDomain()
122 # Create a source clock for the CPUs and set the clock period
123 test_sys
.cpu_clk_domain
= SrcClockDomain(clock
= options
.cpu_clock
,
125 test_sys
.cpu_voltage_domain
)
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
)
132 if options
.script
is not None:
133 test_sys
.readfile
= options
.script
136 test_sys
.have_lpae
= True
138 if options
.virtualisation
:
139 test_sys
.have_virtualization
= True
141 test_sys
.init_param
= options
.init_param
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
)
147 if ObjectList
.is_kvm_cpu(TestCPUClass
) or \
148 ObjectList
.is_kvm_cpu(FutureClass
):
149 test_sys
.kvm_vm
= KvmVM()
152 bootmem
= getattr(test_sys
, '_bootmem', None)
153 Ruby
.create_system(options
, True, test_sys
, test_sys
.iobus
,
154 test_sys
._dma
_ports
, bootmem
)
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
)
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
164 for (i
, cpu
) in enumerate(test_sys
.cpu
):
166 # Tie the cpu ports to the correct ruby system ports
168 cpu
.clk_domain
= test_sys
.cpu_clk_domain
170 cpu
.createInterruptController()
172 test_sys
.ruby
._cpu
_ports
[i
].connectCpuPorts(cpu
)
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
186 if options
.simpoint_profile
:
187 if not ObjectList
.is_noncaching_cpu(TestCPUClass
):
188 fatal("SimPoint generation should be done with atomic cpu")
190 fatal("SimPoint generation not supported with more than one CPUs")
193 if options
.simpoint_profile
:
194 test_sys
.cpu
[i
].addSimPointProbe(options
.simpoint_interval
)
196 test_sys
.cpu
[i
].addCheckerCpu()
197 if not ObjectList
.is_kvm_cpu(TestCPUClass
):
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
= \
206 test_sys
.cpu
[i
].createThreads()
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
)
219 CacheConfig
.config_cache(options
, test_sys
)
221 MemConfig
.config_mem(options
, test_sys
)
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
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],
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
)
244 # Create a top-level voltage domain
245 drive_sys
.voltage_domain
= VoltageDomain(voltage
= options
.sys_voltage
)
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
)
251 # Create a CPU voltage domain
252 drive_sys
.cpu_voltage_domain
= VoltageDomain()
254 # Create a source clock for the CPUs and set the clock period
255 drive_sys
.cpu_clk_domain
= SrcClockDomain(clock
= options
.cpu_clock
,
257 drive_sys
.cpu_voltage_domain
)
259 drive_sys
.cpu
= DriveCPUClass(clk_domain
=drive_sys
.cpu_clk_domain
,
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
)
267 if ObjectList
.is_kvm_cpu(DriveCPUClass
):
268 drive_sys
.kvm_vm
= KvmVM()
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
275 # Create the appropriate memory controllers and connect them to the
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
282 drive_sys
.init_param
= options
.init_param
287 parser
= optparse
.OptionParser()
288 Options
.addCommonOptions(parser
)
289 Options
.addFSOptions(parser
)
291 # Add the ruby specific and protocol specific options
292 if '--ruby' in sys
.argv
:
293 Ruby
.define_options(parser
)
295 (options
, args
) = parser
.parse_args()
298 print("Error: script doesn't take any positional arguments")
301 # system under test can be any CPU
302 (TestCPUClass
, test_mem_mode
, FutureClass
) = Simulation
.setCPUClass(options
)
304 # Match the memories with the CPUs, based on the options for the test system
305 TestMemClass
= Simulation
.setMemClass(options
)
307 if options
.benchmark
:
309 bm
= Benchmarks
[options
.benchmark
]
311 print("Error benchmark %s has not been defined." % options
.benchmark
)
312 print("Valid benchmarks are: %s" % DefinedBenchmarks
)
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
)]
321 bm
= [SysConfig(disks
=options
.disk_image
, rootdev
=options
.root_device
,
322 mem
=options
.mem_size
, os_type
=options
.os_type
)]
324 np
= options
.num_cpus
326 test_sys
= build_test_system(np
)
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
,
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
,
343 root
= Root(full_system
=True, system
=test_sys
)
345 print("Error I don't know how to create more than 2 systems.")
349 root
.time_sync_enable
= True
351 if options
.frame_capture
:
352 VncServer
.frame_capture
= True
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",
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.")
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
)
372 Simulation
.setWorkCountOptions(test_sys
, options
)
373 Simulation
.run(options
, root
, test_sys
, FutureClass
)