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 |