04f60a19b36caed97b95eb9ee171084b100177e2
[gem5.git] / configs / example / arm / baremetal.py
1 # Copyright (c) 2016-2017,2019-2020 ARM Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Redistribution and use in source and binary forms, with or without
14 # modification, are permitted provided that the following conditions are
15 # met: redistributions of source code must retain the above copyright
16 # notice, this list of conditions and the following disclaimer;
17 # redistributions in binary form must reproduce the above copyright
18 # notice, this list of conditions and the following disclaimer in the
19 # documentation and/or other materials provided with the distribution;
20 # neither the name of the copyright holders nor the names of its
21 # contributors may be used to endorse or promote products derived from
22 # this software without specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #
36
37 """This script is the full system example script from the ARM
38 Research Starter Kit on System Modeling. More information can be found
39 at: http://www.arm.com/ResearchEnablement/SystemModeling
40 """
41
42 from __future__ import print_function
43 from __future__ import absolute_import
44
45 import os
46 import m5
47 from m5.util import addToPath
48 from m5.objects import *
49 from m5.options import *
50 import argparse
51
52 m5.util.addToPath('../..')
53
54 from common import SysPaths
55 from common import MemConfig
56 from common import ObjectList
57 from common.cores.arm import HPI
58
59 import devices
60 import workloads
61
62 # Pre-defined CPU configurations. Each tuple must be ordered as : (cpu_class,
63 # l1_icache_class, l1_dcache_class, walk_cache_class, l2_Cache_class). Any of
64 # the cache class may be 'None' if the particular cache is not present.
65 cpu_types = {
66
67 "atomic" : ( AtomicSimpleCPU, None, None, None, None),
68 "minor" : (MinorCPU,
69 devices.L1I, devices.L1D,
70 devices.WalkCache,
71 devices.L2),
72 "hpi" : ( HPI.HPI,
73 HPI.HPI_ICache, HPI.HPI_DCache,
74 HPI.HPI_WalkCache,
75 HPI.HPI_L2)
76 }
77
78 def create_cow_image(name):
79 """Helper function to create a Copy-on-Write disk image"""
80 image = CowDiskImage()
81 image.child.image_file = name
82 return image;
83
84
85 def create(args):
86 ''' Create and configure the system object. '''
87
88 if args.readfile and not os.path.isfile(args.readfile):
89 print("Error: Bootscript %s does not exist" % args.readfile)
90 sys.exit(1)
91
92 object_file = args.kernel if args.kernel else ""
93
94 cpu_class = cpu_types[args.cpu][0]
95 mem_mode = cpu_class.memory_mode()
96 # Only simulate caches when using a timing CPU (e.g., the HPI model)
97 want_caches = True if mem_mode == "timing" else False
98
99 platform = ObjectList.platform_list.get(args.machine_type)
100
101 system = devices.simpleSystem(ArmSystem,
102 want_caches,
103 args.mem_size,
104 platform=platform(),
105 mem_mode=mem_mode,
106 readfile=args.readfile)
107
108 MemConfig.config_mem(args, system)
109
110 if args.semi_enable:
111 system.semihosting = ArmSemihosting(
112 stdin=args.semi_stdin,
113 stdout=args.semi_stdout,
114 stderr=args.semi_stderr,
115 files_root_dir=args.semi_path,
116 cmd_line = " ".join([ object_file ] + args.args)
117 )
118
119 # Add the PCI devices we need for this system. The base system
120 # doesn't have any PCI devices by default since they are assumed
121 # to be added by the configurastion scripts needin them.
122 pci_devices = []
123 if args.disk_image:
124 # Create a VirtIO block device for the system's boot
125 # disk. Attach the disk image using gem5's Copy-on-Write
126 # functionality to avoid writing changes to the stored copy of
127 # the disk image.
128 system.disk = PciVirtIO(vio=VirtIOBlock(
129 image=create_cow_image(args.disk_image)))
130 pci_devices.append(system.disk)
131
132 # Attach the PCI devices to the system. The helper method in the
133 # system assigns a unique PCI bus ID to each of the devices and
134 # connects them to the IO bus.
135 for dev in pci_devices:
136 system.attach_pci(dev)
137
138 # Wire up the system's memory system
139 system.connect()
140
141 # Add CPU clusters to the system
142 system.cpu_cluster = [
143 devices.CpuCluster(system,
144 args.num_cores,
145 args.cpu_freq, "1.0V",
146 *cpu_types[args.cpu]),
147 ]
148
149 # Create a cache hierarchy for the cluster. We are assuming that
150 # clusters have core-private L1 caches and an L2 that's shared
151 # within the cluster.
152 for cluster in system.cpu_cluster:
153 system.addCaches(want_caches, last_cache_level=2)
154
155 # Setup gem5's minimal Linux boot loader.
156 system.auto_reset_addr = True
157
158 # Using GICv3
159 system.realview.gic.gicv4 = False
160
161 system.highest_el_is_64 = True
162 system.have_virtualization = True
163 system.have_security = True
164
165 workload_class = workloads.workload_list.get(args.workload)
166 system.workload = workload_class(
167 object_file, system)
168
169 return system
170
171 def run(args):
172 cptdir = m5.options.outdir
173 if args.checkpoint:
174 print("Checkpoint directory: %s" % cptdir)
175
176 while True:
177 event = m5.simulate()
178 exit_msg = event.getCause()
179 if exit_msg == "checkpoint":
180 print("Dropping checkpoint at tick %d" % m5.curTick())
181 cpt_dir = os.path.join(m5.options.outdir, "cpt.%d" % m5.curTick())
182 m5.checkpoint(os.path.join(cpt_dir))
183 print("Checkpoint done.")
184 else:
185 print(exit_msg, " @ ", m5.curTick())
186 break
187
188 sys.exit(event.getCode())
189
190
191 def main():
192 parser = argparse.ArgumentParser(epilog=__doc__)
193
194 parser.add_argument("--kernel", type=str,
195 default=None,
196 help="Binary to run")
197 parser.add_argument("--workload", type=str,
198 default="ArmBaremetal",
199 choices=workloads.workload_list.get_names(),
200 help="Workload type")
201 parser.add_argument("--disk-image", type=str,
202 default=None,
203 help="Disk to instantiate")
204 parser.add_argument("--readfile", type=str, default="",
205 help = "File to return with the m5 readfile command")
206 parser.add_argument("--cpu", type=str, choices=list(cpu_types.keys()),
207 default="atomic",
208 help="CPU model to use")
209 parser.add_argument("--cpu-freq", type=str, default="4GHz")
210 parser.add_argument("--num-cores", type=int, default=1,
211 help="Number of CPU cores")
212 parser.add_argument("--machine-type", type=str,
213 choices=ObjectList.platform_list.get_names(),
214 default="VExpress_GEM5_V2",
215 help="Hardware platform class")
216 parser.add_argument("--mem-type", default="DDR3_1600_8x8",
217 choices=ObjectList.mem_list.get_names(),
218 help = "type of memory to use")
219 parser.add_argument("--mem-channels", type=int, default=1,
220 help = "number of memory channels")
221 parser.add_argument("--mem-ranks", type=int, default=None,
222 help = "number of memory ranks per channel")
223 parser.add_argument("--mem-size", action="store", type=str,
224 default="2GB",
225 help="Specify the physical memory size")
226 parser.add_argument("--checkpoint", action="store_true")
227 parser.add_argument("--restore", type=str, default=None)
228 parser.add_argument("--dtb-gen", action="store_true",
229 help="Doesn't run simulation, it generates a DTB only")
230 parser.add_argument("--semi-enable", action="store_true",
231 help="Enable semihosting support")
232 parser.add_argument("--semi-stdin", type=str, default="stdin",
233 help="Standard input for semihosting " \
234 "(default: gem5's stdin)")
235 parser.add_argument("--semi-stdout", type=str, default="stdout",
236 help="Standard output for semihosting " \
237 "(default: gem5's stdout)")
238 parser.add_argument("--semi-stderr", type=str, default="stderr",
239 help="Standard error for semihosting " \
240 "(default: gem5's stderr)")
241 parser.add_argument('--semi-path', type=str,
242 default="",
243 help=('Search path for files to be loaded through '
244 'Arm Semihosting'))
245 parser.add_argument("args", default=[], nargs="*",
246 help="Semihosting arguments to pass to benchmark")
247 parser.add_argument("-P", "--param", action="append", default=[],
248 help="Set a SimObject parameter relative to the root node. "
249 "An extended Python multi range slicing syntax can be used "
250 "for arrays. For example: "
251 "'system.cpu[0,1,3:8:2].max_insts_all_threads = 42' "
252 "sets max_insts_all_threads for cpus 0, 1, 3, 5 and 7 "
253 "Direct parameters of the root object are not accessible, "
254 "only parameters of its children.")
255
256 args = parser.parse_args()
257
258 root = Root(full_system=True)
259 root.system = create(args)
260
261 root.apply_config(args.param)
262
263 if args.restore is not None:
264 m5.instantiate(args.restore)
265 else:
266 m5.instantiate()
267
268 if args.dtb_gen:
269 # No run, autogenerate DTB and exit
270 root.system.generateDtb(os.path.join(m5.options.outdir, 'system.dtb'))
271 else:
272 run(args)
273
274 if __name__ == "__m5_main__":
275 main()