simulate.py (10909:db1b5b20096f) simulate.py (10912:b99a6662d7c2)
1# Copyright (c) 2012 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

--- 52 unchanged lines hidden (view full) ---

61MaxTick = 2**64 - 1
62
63_memory_modes = {
64 "atomic" : objects.params.atomic,
65 "timing" : objects.params.timing,
66 "atomic_noncaching" : objects.params.atomic_noncaching,
67 }
68
1# Copyright (c) 2012 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

--- 52 unchanged lines hidden (view full) ---

61MaxTick = 2**64 - 1
62
63_memory_modes = {
64 "atomic" : objects.params.atomic,
65 "timing" : objects.params.timing,
66 "atomic_noncaching" : objects.params.atomic_noncaching,
67 }
68
69_drain_manager = internal.drain.DrainManager.instance()
70
69# The final hook to generate .ini files. Called from the user script
70# once the config is built.
71def instantiate(ckpt_dir=None):
72 from m5 import options
73
74 root = objects.Root.getInstance()
75
76 if not root:

--- 47 unchanged lines hidden (view full) ---

124 # Do a fifth pass to connect probe listeners
125 for obj in root.descendants(): obj.regProbeListeners()
126
127 # We're done registering statistics. Enable the stats package now.
128 stats.enable()
129
130 # Restore checkpoint (if any)
131 if ckpt_dir:
71# The final hook to generate .ini files. Called from the user script
72# once the config is built.
73def instantiate(ckpt_dir=None):
74 from m5 import options
75
76 root = objects.Root.getInstance()
77
78 if not root:

--- 47 unchanged lines hidden (view full) ---

126 # Do a fifth pass to connect probe listeners
127 for obj in root.descendants(): obj.regProbeListeners()
128
129 # We're done registering statistics. Enable the stats package now.
130 stats.enable()
131
132 # Restore checkpoint (if any)
133 if ckpt_dir:
134 _drain_manager.preCheckpointRestore()
132 ckpt = internal.core.getCheckpoint(ckpt_dir)
133 internal.core.unserializeGlobals(ckpt);
134 for obj in root.descendants(): obj.loadState(ckpt)
135 ckpt = internal.core.getCheckpoint(ckpt_dir)
136 internal.core.unserializeGlobals(ckpt);
137 for obj in root.descendants(): obj.loadState(ckpt)
135 need_resume.append(root)
136 else:
137 for obj in root.descendants(): obj.initState()
138
139 # Check to see if any of the stat events are in the past after resuming from
140 # a checkpoint, If so, this call will shift them to be at a valid time.
141 updateStatEvents()
142
138 else:
139 for obj in root.descendants(): obj.initState()
140
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.
143 updateStatEvents()
144
143need_resume = []
144need_startup = True
145def simulate(*args, **kwargs):
145need_startup = True
146def simulate(*args, **kwargs):
146 global need_resume, need_startup
147 global need_startup
147
148 if need_startup:
149 root = objects.Root.getInstance()
150 for obj in root.descendants(): obj.startup()
151 need_startup = False
152
153 # Python exit handlers happen in reverse order.
154 # We want to dump stats last.
155 atexit.register(stats.dump)
156
157 # register our C++ exit callback function with Python
158 atexit.register(internal.core.doExitCleanup)
159
160 # Reset to put the stats in a consistent state.
161 stats.reset()
162
148
149 if need_startup:
150 root = objects.Root.getInstance()
151 for obj in root.descendants(): obj.startup()
152 need_startup = False
153
154 # Python exit handlers happen in reverse order.
155 # We want to dump stats last.
156 atexit.register(stats.dump)
157
158 # register our C++ exit callback function with Python
159 atexit.register(internal.core.doExitCleanup)
160
161 # Reset to put the stats in a consistent state.
162 stats.reset()
163
163 for root in need_resume:
164 resume(root)
165 need_resume = []
164 if _drain_manager.isDrained():
165 _drain_manager.resume()
166
167 return internal.event.simulate(*args, **kwargs)
168
169# Export curTick to user script.
170def curTick():
171 return internal.core.curTick()
172
166
167 return internal.event.simulate(*args, **kwargs)
168
169# Export curTick to user script.
170def curTick():
171 return internal.core.curTick()
172
173# Drain the system in preparation of a checkpoint or memory mode
174# switch.
175def drain(root):
173def drain():
174 """Drain the simulator in preparation of a checkpoint or memory mode
175 switch.
176
177 This operation is a no-op if the simulator is already in the
178 Drained state.
179
180 """
181
176 # Try to drain all objects. Draining might not be completed unless
177 # all objects return that they are drained on the first call. This
178 # is because as objects drain they may cause other objects to no
179 # longer be drained.
180 def _drain():
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
185 # longer be drained.
186 def _drain():
181 all_drained = False
182 dm = internal.drain.createDrainManager()
183 unready_objs = sum(obj.drain(dm) for obj in root.descendants())
184 # If we've got some objects that can't drain immediately, then simulate
185 if unready_objs > 0:
186 dm.setCount(unready_objs)
187 #WARNING: if a valid exit event occurs while draining, it will not
188 # get returned to the user script
187 # Try to drain the system. The drain is successful if all
188 # objects are done without simulation. We need to simulate
189 # more if not.
190 if _drain_manager.tryDrain():
191 return True
192
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':
189 exit_event = simulate()
197 exit_event = simulate()
190 while exit_event.getCause() != 'Finished drain':
191 exit_event = simulate()
192 else:
193 all_drained = True
194 internal.drain.cleanupDrainManager(dm)
195 return all_drained
196
198
197 all_drained = _drain()
198 while (not all_drained):
199 all_drained = _drain()
199 return False
200
200
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()
205
206 assert _drain_manager.isDrained(), "Drain state inconsistent"
207
201def memWriteback(root):
202 for obj in root.descendants():
203 obj.memWriteback()
204
205def memInvalidate(root):
206 for obj in root.descendants():
207 obj.memInvalidate()
208
208def memWriteback(root):
209 for obj in root.descendants():
210 obj.memWriteback()
211
212def memInvalidate(root):
213 for obj in root.descendants():
214 obj.memInvalidate()
215
209def resume(root):
210 for obj in root.descendants(): obj.drainResume()
211
212def checkpoint(dir):
213 root = objects.Root.getInstance()
214 if not isinstance(root, objects.Root):
215 raise TypeError, "Checkpoint must be called on a root object."
216def checkpoint(dir):
217 root = objects.Root.getInstance()
218 if not isinstance(root, objects.Root):
219 raise TypeError, "Checkpoint must be called on a root object."
216 drain(root)
220
221 drain()
217 memWriteback(root)
218 print "Writing checkpoint"
219 internal.core.serializeAll(dir)
222 memWriteback(root)
223 print "Writing checkpoint"
224 internal.core.serializeAll(dir)
220 resume(root)
221
222def _changeMemoryMode(system, mode):
223 if not isinstance(system, (objects.Root, objects.System)):
224 raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \
225 (type(system), objects.Root, objects.System)
226 if system.getMemoryMode() != mode:
227 system.setMemoryMode(mode)
228 else:
229 print "System already in target mode. Memory mode unchanged."
230
225
226def _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)
232 else:
233 print "System already in target mode. Memory mode unchanged."
234
231def switchCpus(system, cpuList, do_drain=True, verbose=True):
235def switchCpus(system, cpuList, verbose=True):
232 """Switch CPUs in a system.
233
236 """Switch CPUs in a system.
237
234 By default, this method drains and resumes the system. This
235 behavior can be disabled by setting the keyword argument
236 'do_drain' to false, which might be desirable if multiple
237 operations requiring a drained system are going to be performed in
238 sequence.
239
240 Note: This method may switch the memory mode of the system if that
241 is required by the CPUs. It may also flush all caches in the
242 system.
243
244 Arguments:
245 system -- Simulated system.
246 cpuList -- (old_cpu, new_cpu) tuples
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
240 system.
241
242 Arguments:
243 system -- Simulated system.
244 cpuList -- (old_cpu, new_cpu) tuples
247
248 Keyword Arguments:
249 do_drain -- Perform a drain/resume of the system when switching.
250 """
251
252 if verbose:
253 print "switching cpus"
254
255 if not isinstance(cpuList, list):
256 raise RuntimeError, "Must pass a list to this function"
257 for item in cpuList:

--- 29 unchanged lines hidden (view full) ---

287 raise RuntimeError, \
288 "Old CPU (%s) does not support CPU handover." % (old_cpu,)
289
290 try:
291 memory_mode = _memory_modes[memory_mode_name]
292 except KeyError:
293 raise RuntimeError, "Invalid memory mode (%s)" % memory_mode_name
294
245 """
246
247 if verbose:
248 print "switching cpus"
249
250 if not isinstance(cpuList, list):
251 raise RuntimeError, "Must pass a list to this function"
252 for item in cpuList:

--- 29 unchanged lines hidden (view full) ---

282 raise RuntimeError, \
283 "Old CPU (%s) does not support CPU handover." % (old_cpu,)
284
285 try:
286 memory_mode = _memory_modes[memory_mode_name]
287 except KeyError:
288 raise RuntimeError, "Invalid memory mode (%s)" % memory_mode_name
289
295 if do_drain:
296 drain(system)
290 drain()
297
298 # Now all of the CPUs are ready to be switched out
299 for old_cpu, new_cpu in cpuList:
300 old_cpu.switchOut()
301
302 # Change the memory mode if required. We check if this is needed
303 # to avoid printing a warning if no switch was performed.
304 if system.getMemoryMode() != memory_mode:

--- 4 unchanged lines hidden (view full) ---

309 memWriteback(system)
310 memInvalidate(system)
311
312 _changeMemoryMode(system, memory_mode)
313
314 for old_cpu, new_cpu in cpuList:
315 new_cpu.takeOverFrom(old_cpu)
316
291
292 # Now all of the CPUs are ready to be switched out
293 for old_cpu, new_cpu in cpuList:
294 old_cpu.switchOut()
295
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:

--- 4 unchanged lines hidden (view full) ---

303 memWriteback(system)
304 memInvalidate(system)
305
306 _changeMemoryMode(system, memory_mode)
307
308 for old_cpu, new_cpu in cpuList:
309 new_cpu.takeOverFrom(old_cpu)
310
317 if do_drain:
318 resume(system)
319
320from internal.core import disableAllListeners
311from internal.core import disableAllListeners