d89629d2df6d4c6c5db0b61a9c3a7c6229f46595
1 # Copyright (c) 2012 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 # Copyright (c) 2005 The Regents of The University of Michigan
14 # Copyright (c) 2010 Advanced Micro Devices, Inc.
15 # All rights reserved.
17 # Redistribution and use in source and binary forms, with or without
18 # modification, are permitted provided that the following conditions are
19 # met: redistributions of source code must retain the above copyright
20 # notice, this list of conditions and the following disclaimer;
21 # redistributions in binary form must reproduce the above copyright
22 # notice, this list of conditions and the following disclaimer in the
23 # documentation and/or other materials provided with the distribution;
24 # neither the name of the copyright holders nor the names of its
25 # contributors may be used to endorse or promote products derived from
26 # this software without specific prior written permission.
28 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 # Authors: Nathan Binkert
47 # import the SWIG-wrapped main C++ functions
54 from m5
.util
.dot_writer
import do_dot
55 from m5
.internal
.stats
import updateEvents
as updateStatEvents
57 from util
import fatal
58 from util
import attrdict
60 # define a MaxTick parameter, unsigned 64 bit
64 "atomic" : objects
.params
.atomic
,
65 "timing" : objects
.params
.timing
,
66 "atomic_noncaching" : objects
.params
.atomic_noncaching
,
69 _drain_manager
= internal
.drain
.DrainManager
.instance()
71 # The final hook to generate .ini files. Called from the user script
72 # once the config is built.
73 def instantiate(ckpt_dir
=None):
74 from m5
import options
76 root
= objects
.Root
.getInstance()
79 fatal("Need to instantiate Root() before calling instantiate()")
81 # we need to fix the global frequency
82 ticks
.fixGlobalFrequency()
84 # Make sure SimObject-valued params are in the configuration
85 # hierarchy so we catch them with future descendants() walks
86 for obj
in root
.descendants(): obj
.adoptOrphanParams()
88 # Unproxy in sorted order for determinism
89 for obj
in root
.descendants(): obj
.unproxyParams()
91 if options
.dump_config
:
92 ini_file
= file(os
.path
.join(options
.outdir
, options
.dump_config
), 'w')
93 # Print ini sections in sorted order for easier diffing
94 for obj
in sorted(root
.descendants(), key
=lambda o
: o
.path()):
95 obj
.print_ini(ini_file
)
98 if options
.json_config
:
101 json_file
= file(os
.path
.join(options
.outdir
, options
.json_config
), 'w')
102 d
= root
.get_config_as_dict()
103 json
.dump(d
, json_file
, indent
=4)
108 do_dot(root
, options
.outdir
, options
.dot_config
)
110 # Initialize the global statistics
113 # Create the C++ sim objects and connect ports
114 for obj
in root
.descendants(): obj
.createCCObject()
115 for obj
in root
.descendants(): obj
.connectPorts()
117 # Do a second pass to finish initializing the sim objects
118 for obj
in root
.descendants(): obj
.init()
120 # Do a third pass to initialize statistics
121 for obj
in root
.descendants(): obj
.regStats()
123 # Do a fourth pass to initialize probe points
124 for obj
in root
.descendants(): obj
.regProbePoints()
126 # Do a fifth pass to connect probe listeners
127 for obj
in root
.descendants(): obj
.regProbeListeners()
129 # We're done registering statistics. Enable the stats package now.
132 # Restore checkpoint (if any)
134 _drain_manager
.preCheckpointRestore()
135 ckpt
= internal
.core
.getCheckpoint(ckpt_dir
)
136 internal
.core
.unserializeGlobals(ckpt
);
137 for obj
in root
.descendants(): obj
.loadState(ckpt
)
139 for obj
in root
.descendants(): obj
.initState()
141 # Check to see if any of the stat events are in the past after resuming from
142 # a checkpoint, If so, this call will shift them to be at a valid time.
146 def simulate(*args
, **kwargs
):
150 root
= objects
.Root
.getInstance()
151 for obj
in root
.descendants(): obj
.startup()
154 # Python exit handlers happen in reverse order.
155 # We want to dump stats last.
156 atexit
.register(stats
.dump
)
158 # register our C++ exit callback function with Python
159 atexit
.register(internal
.core
.doExitCleanup
)
161 # Reset to put the stats in a consistent state.
164 if _drain_manager
.isDrained():
165 _drain_manager
.resume()
167 return internal
.event
.simulate(*args
, **kwargs
)
169 # Export curTick to user script.
171 return internal
.core
.curTick()
174 """Drain the simulator in preparation of a checkpoint or memory mode
177 This operation is a no-op if the simulator is already in the
182 # Try to drain all objects. Draining might not be completed unless
183 # all objects return that they are drained on the first call. This
184 # is because as objects drain they may cause other objects to no
187 # Try to drain the system. The drain is successful if all
188 # objects are done without simulation. We need to simulate
190 if _drain_manager
.tryDrain():
193 # WARNING: if a valid exit event occurs while draining, it
194 # will not get returned to the user script
195 exit_event
= internal
.event
.simulate()
196 while exit_event
.getCause() != 'Finished drain':
197 exit_event
= simulate()
201 # Don't try to drain a system that is already drained
202 is_drained
= _drain_manager
.isDrained()
203 while not is_drained
:
204 is_drained
= _drain()
206 assert _drain_manager
.isDrained(), "Drain state inconsistent"
208 def memWriteback(root
):
209 for obj
in root
.descendants():
212 def memInvalidate(root
):
213 for obj
in root
.descendants():
217 root
= objects
.Root
.getInstance()
218 if not isinstance(root
, objects
.Root
):
219 raise TypeError, "Checkpoint must be called on a root object."
223 print "Writing checkpoint"
224 internal
.core
.serializeAll(dir)
226 def _changeMemoryMode(system
, mode
):
227 if not isinstance(system
, (objects
.Root
, objects
.System
)):
228 raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \
229 (type(system
), objects
.Root
, objects
.System
)
230 if system
.getMemoryMode() != mode
:
231 system
.setMemoryMode(mode
)
233 print "System already in target mode. Memory mode unchanged."
235 def switchCpus(system
, cpuList
, verbose
=True):
236 """Switch CPUs in a system.
238 Note: This method may switch the memory mode of the system if that
239 is required by the CPUs. It may also flush all caches in the
243 system -- Simulated system.
244 cpuList -- (old_cpu, new_cpu) tuples
248 print "switching cpus"
250 if not isinstance(cpuList
, list):
251 raise RuntimeError, "Must pass a list to this function"
253 if not isinstance(item
, tuple) or len(item
) != 2:
254 raise RuntimeError, "List must have tuples of (oldCPU,newCPU)"
256 old_cpus
= [old_cpu
for old_cpu
, new_cpu
in cpuList
]
257 new_cpus
= [new_cpu
for old_cpu
, new_cpu
in cpuList
]
258 old_cpu_set
= set(old_cpus
)
259 memory_mode_name
= new_cpus
[0].memory_mode()
260 for old_cpu
, new_cpu
in cpuList
:
261 if not isinstance(old_cpu
, objects
.BaseCPU
):
262 raise TypeError, "%s is not of type BaseCPU" % old_cpu
263 if not isinstance(new_cpu
, objects
.BaseCPU
):
264 raise TypeError, "%s is not of type BaseCPU" % new_cpu
265 if new_cpu
in old_cpu_set
:
266 raise RuntimeError, \
267 "New CPU (%s) is in the list of old CPUs." % (old_cpu
,)
268 if not new_cpu
.switchedOut():
269 raise RuntimeError, \
270 "New CPU (%s) is already active." % (new_cpu
,)
271 if not new_cpu
.support_take_over():
272 raise RuntimeError, \
273 "New CPU (%s) does not support CPU handover." % (old_cpu
,)
274 if new_cpu
.memory_mode() != memory_mode_name
:
275 raise RuntimeError, \
276 "%s and %s require different memory modes." % (new_cpu
,
278 if old_cpu
.switchedOut():
279 raise RuntimeError, \
280 "Old CPU (%s) is inactive." % (new_cpu
,)
281 if not old_cpu
.support_take_over():
282 raise RuntimeError, \
283 "Old CPU (%s) does not support CPU handover." % (old_cpu
,)
286 memory_mode
= _memory_modes
[memory_mode_name
]
288 raise RuntimeError, "Invalid memory mode (%s)" % memory_mode_name
292 # Now all of the CPUs are ready to be switched out
293 for old_cpu
, new_cpu
in cpuList
:
296 # Change the memory mode if required. We check if this is needed
297 # to avoid printing a warning if no switch was performed.
298 if system
.getMemoryMode() != memory_mode
:
299 # Flush the memory system if we are switching to a memory mode
300 # that disables caches. This typically happens when switching to a
301 # hardware virtualized CPU.
302 if memory_mode
== objects
.params
.atomic_noncaching
:
304 memInvalidate(system
)
306 _changeMemoryMode(system
, memory_mode
)
308 for old_cpu
, new_cpu
in cpuList
:
309 new_cpu
.takeOverFrom(old_cpu
)
311 def notifyFork(root
):
312 for obj
in root
.descendants():
315 from internal
.core
import disableAllListeners