configs: Updates for python3
[gem5.git] / configs / example / arm / starter_se.py
1 # Copyright (c) 2016-2017 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 """This script is the syscall emulation example script from the ARM
37 Research Starter Kit on System Modeling. More information can be found
38 at: http://www.arm.com/ResearchEnablement/SystemModeling
39 """
40
41 from __future__ import print_function
42 from __future__ import absolute_import
43
44 import os
45 import m5
46 from m5.util import addToPath
47 from m5.objects import *
48 import argparse
49 import shlex
50
51 m5.util.addToPath('../..')
52
53 from common import ObjectList
54 from common import MemConfig
55 from common.cores.arm import HPI
56
57 import devices
58
59
60
61 # Pre-defined CPU configurations. Each tuple must be ordered as : (cpu_class,
62 # l1_icache_class, l1_dcache_class, walk_cache_class, l2_Cache_class). Any of
63 # the cache class may be 'None' if the particular cache is not present.
64 cpu_types = {
65 "atomic" : ( AtomicSimpleCPU, None, None, None, None),
66 "minor" : (MinorCPU,
67 devices.L1I, devices.L1D,
68 devices.WalkCache,
69 devices.L2),
70 "hpi" : ( HPI.HPI,
71 HPI.HPI_ICache, HPI.HPI_DCache,
72 HPI.HPI_WalkCache,
73 HPI.HPI_L2)
74 }
75
76
77 class SimpleSeSystem(System):
78 '''
79 Example system class for syscall emulation mode
80 '''
81
82 # Use a fixed cache line size of 64 bytes
83 cache_line_size = 64
84
85 def __init__(self, args, **kwargs):
86 super(SimpleSeSystem, self).__init__(**kwargs)
87
88 # Setup book keeping to be able to use CpuClusters from the
89 # devices module.
90 self._clusters = []
91 self._num_cpus = 0
92
93 # Create a voltage and clock domain for system components
94 self.voltage_domain = VoltageDomain(voltage="3.3V")
95 self.clk_domain = SrcClockDomain(clock="1GHz",
96 voltage_domain=self.voltage_domain)
97
98 # Create the off-chip memory bus.
99 self.membus = SystemXBar()
100
101 # Wire up the system port that gem5 uses to load the kernel
102 # and to perform debug accesses.
103 self.system_port = self.membus.slave
104
105
106 # Add CPUs to the system. A cluster of CPUs typically have
107 # private L1 caches and a shared L2 cache.
108 self.cpu_cluster = devices.CpuCluster(self,
109 args.num_cores,
110 args.cpu_freq, "1.2V",
111 *cpu_types[args.cpu])
112
113 # Create a cache hierarchy (unless we are simulating a
114 # functional CPU in atomic memory mode) for the CPU cluster
115 # and connect it to the shared memory bus.
116 if self.cpu_cluster.memoryMode() == "timing":
117 self.cpu_cluster.addL1()
118 self.cpu_cluster.addL2(self.cpu_cluster.clk_domain)
119 self.cpu_cluster.connectMemSide(self.membus)
120
121 # Tell gem5 about the memory mode used by the CPUs we are
122 # simulating.
123 self.mem_mode = self.cpu_cluster.memoryMode()
124
125 def numCpuClusters(self):
126 return len(self._clusters)
127
128 def addCpuCluster(self, cpu_cluster, num_cpus):
129 assert cpu_cluster not in self._clusters
130 assert num_cpus > 0
131 self._clusters.append(cpu_cluster)
132 self._num_cpus += num_cpus
133
134 def numCpus(self):
135 return self._num_cpus
136
137 def get_processes(cmd):
138 """Interprets commands to run and returns a list of processes"""
139
140 cwd = os.getcwd()
141 multiprocesses = []
142 for idx, c in enumerate(cmd):
143 argv = shlex.split(c)
144
145 process = Process(pid=100 + idx, cwd=cwd, cmd=argv, executable=argv[0])
146
147 print("info: %d. command and arguments: %s" % (idx + 1, process.cmd))
148 multiprocesses.append(process)
149
150 return multiprocesses
151
152
153 def create(args):
154 ''' Create and configure the system object. '''
155
156 system = SimpleSeSystem(args)
157
158 # Tell components about the expected physical memory ranges. This
159 # is, for example, used by the MemConfig helper to determine where
160 # to map DRAMs in the physical address space.
161 system.mem_ranges = [ AddrRange(start=0, size=args.mem_size) ]
162
163 # Configure the off-chip memory system.
164 MemConfig.config_mem(args, system)
165
166 # Parse the command line and get a list of Processes instances
167 # that we can pass to gem5.
168 processes = get_processes(args.commands_to_run)
169 if len(processes) != args.num_cores:
170 print("Error: Cannot map %d command(s) onto %d CPU(s)" %
171 (len(processes), args.num_cores))
172 sys.exit(1)
173
174 # Assign one workload to each CPU
175 for cpu, workload in zip(system.cpu_cluster.cpus, processes):
176 cpu.workload = workload
177
178 return system
179
180
181 def main():
182 parser = argparse.ArgumentParser(epilog=__doc__)
183
184 parser.add_argument("commands_to_run", metavar="command(s)", nargs='*',
185 help="Command(s) to run")
186 parser.add_argument("--cpu", type=str, choices=list(cpu_types.keys()),
187 default="atomic",
188 help="CPU model to use")
189 parser.add_argument("--cpu-freq", type=str, default="4GHz")
190 parser.add_argument("--num-cores", type=int, default=1,
191 help="Number of CPU cores")
192 parser.add_argument("--mem-type", default="DDR3_1600_8x8",
193 choices=ObjectList.mem_list.get_names(),
194 help = "type of memory to use")
195 parser.add_argument("--mem-channels", type=int, default=2,
196 help = "number of memory channels")
197 parser.add_argument("--mem-ranks", type=int, default=None,
198 help = "number of memory ranks per channel")
199 parser.add_argument("--mem-size", action="store", type=str,
200 default="2GB",
201 help="Specify the physical memory size")
202
203 args = parser.parse_args()
204
205 # Create a single root node for gem5's object hierarchy. There can
206 # only exist one root node in the simulator at any given
207 # time. Tell gem5 that we want to use syscall emulation mode
208 # instead of full system mode.
209 root = Root(full_system=False)
210
211 # Populate the root node with a system. A system corresponds to a
212 # single node with shared memory.
213 root.system = create(args)
214
215 # Instantiate the C++ object hierarchy. After this point,
216 # SimObjects can't be instantiated anymore.
217 m5.instantiate()
218
219 # Start the simulator. This gives control to the C++ world and
220 # starts the simulator. The returned event tells the simulation
221 # script why the simulator exited.
222 event = m5.simulate()
223
224 # Print the reason for the simulation exit. Some exit codes are
225 # requests for service (e.g., checkpoints) from the simulation
226 # script. We'll just ignore them here and exit.
227 print(event.getCause(), " @ ", m5.curTick())
228 sys.exit(event.getCode())
229
230
231 if __name__ == "__m5_main__":
232 main()