1 # Copyright (c) 2016-2017 ARM Limited
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.
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.
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.
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
41 from __future__
import print_function
42 from __future__
import absolute_import
46 from m5
.util
import addToPath
47 from m5
.objects
import *
51 m5
.util
.addToPath('../..')
53 from common
import ObjectList
54 from common
import MemConfig
55 from common
.cores
.arm
import HPI
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.
65 "atomic" : ( AtomicSimpleCPU
, None, None, None, None),
67 devices
.L1I
, devices
.L1D
,
71 HPI
.HPI_ICache
, HPI
.HPI_DCache
,
77 class SimpleSeSystem(System
):
79 Example system class for syscall emulation mode
82 # Use a fixed cache line size of 64 bytes
85 def __init__(self
, args
, **kwargs
):
86 super(SimpleSeSystem
, self
).__init
__(**kwargs
)
88 # Setup book keeping to be able to use CpuClusters from the
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
)
98 # Create the off-chip memory bus.
99 self
.membus
= SystemXBar()
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
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
,
110 args
.cpu_freq
, "1.2V",
111 *cpu_types
[args
.cpu
])
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
)
121 # Tell gem5 about the memory mode used by the CPUs we are
123 self
.mem_mode
= self
.cpu_cluster
.memoryMode()
125 def numCpuClusters(self
):
126 return len(self
._clusters
)
128 def addCpuCluster(self
, cpu_cluster
, num_cpus
):
129 assert cpu_cluster
not in self
._clusters
131 self
._clusters
.append(cpu_cluster
)
132 self
._num
_cpus
+= num_cpus
135 return self
._num
_cpus
137 def get_processes(cmd
):
138 """Interprets commands to run and returns a list of processes"""
142 for idx
, c
in enumerate(cmd
):
143 argv
= shlex
.split(c
)
145 process
= Process(pid
=100 + idx
, cwd
=cwd
, cmd
=argv
, executable
=argv
[0])
147 print("info: %d. command and arguments: %s" % (idx
+ 1, process
.cmd
))
148 multiprocesses
.append(process
)
150 return multiprocesses
154 ''' Create and configure the system object. '''
156 system
= SimpleSeSystem(args
)
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
) ]
163 # Configure the off-chip memory system.
164 MemConfig
.config_mem(args
, system
)
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
))
174 # Assign one workload to each CPU
175 for cpu
, workload
in zip(system
.cpu_cluster
.cpus
, processes
):
176 cpu
.workload
= workload
182 parser
= argparse
.ArgumentParser(epilog
=__doc__
)
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()),
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,
201 help="Specify the physical memory size")
203 args
= parser
.parse_args()
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)
211 # Populate the root node with a system. A system corresponds to a
212 # single node with shared memory.
213 root
.system
= create(args
)
215 # Instantiate the C++ object hierarchy. After this point,
216 # SimObjects can't be instantiated anymore.
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()
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())
231 if __name__
== "__m5_main__":