if exit_cause != "simulate() limit reached":
return exit_event
- print "draining the system"
- m5.drain(testsys)
- m5.switchCpus(repeat_switch_cpu_list)
- m5.resume(testsys)
+ m5.switchCpus(testsys, repeat_switch_cpu_list)
tmp_cpu_list = []
for old_cpu, new_cpu in repeat_switch_cpu_list:
exit_event = m5.simulate(10000)
print "Switched CPUS @ tick %s" % (m5.curTick())
- # when you change to Timing (or Atomic), you halt the system
- # given as argument. When you are finished with the system
- # changes (including switchCpus), you must resume the system
- # manually. You DON'T need to resume after just switching
- # CPUs if you haven't changed anything on the system level.
-
- m5.changeToTiming(testsys)
- m5.switchCpus(switch_cpu_list)
- m5.resume(testsys)
+ m5.switchCpus(testsys, switch_cpu_list)
if options.standard_switch:
print "Switch at instruction count:%d" % \
print "Switching CPUS @ tick %s" % (m5.curTick())
print "Simulation ends instruction count:%d" % \
(testsys.switch_cpus_1[0].max_insts_any_thread)
- m5.drain(testsys)
- m5.switchCpus(switch_cpu_list1)
- m5.resume(testsys)
+ m5.switchCpus(testsys, switch_cpu_list1)
# If we're taking and restoring checkpoints, use checkpoint_dir
# option only for finding the checkpoints to restore from. This
# define a MaxTick parameter
MaxTick = 2**63 - 1
+_memory_modes = {
+ "atomic" : objects.params.atomic,
+ "timing" : objects.params.timing,
+ }
+
# The final hook to generate .ini files. Called from the user script
# once the config is built.
def instantiate(ckpt_dir=None):
internal.core.serializeAll(dir)
resume(root)
-def changeMemoryMode(system, mode):
+def _changeMemoryMode(system, mode):
if not isinstance(system, (objects.Root, objects.System)):
raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \
(type(system), objects.Root, objects.System)
else:
print "System already in target mode. Memory mode unchanged."
-def changeToAtomic(system, **kwargs):
- print "Changing memory mode to atomic"
- changeMemoryMode(system, objects.params.atomic, **kwargs)
+def switchCpus(system, cpuList, do_drain=True):
+ """Switch CPUs in a system.
+
+ By default, this method drains and resumes the system. This
+ behavior can be disabled by setting the keyword argument
+ 'do_drain' to false, which might be desirable if multiple
+ operations requiring a drained system are going to be performed in
+ sequence.
+
+ Note: This method may switch the memory mode of the system if that
+ is required by the CPUs. It may also flush all caches in the
+ system.
-def changeToTiming(system, **kwargs):
- print "Changing memory mode to timing"
- changeMemoryMode(system, objects.params.timing, **kwargs)
+ Arguments:
+ system -- Simulated system.
+ cpuList -- (old_cpu, new_cpu) tuples
-def switchCpus(cpuList):
+ Keyword Arguments:
+ do_drain -- Perform a drain/resume of the system when switching.
+ """
print "switching cpus"
if not isinstance(cpuList, list):
raise RuntimeError, "Must pass a list to this function"
if not isinstance(item, tuple) or len(item) != 2:
raise RuntimeError, "List must have tuples of (oldCPU,newCPU)"
- old_cpu_set = set([old_cpu for old_cpu, new_cpu in cpuList])
+ old_cpus = [old_cpu for old_cpu, new_cpu in cpuList]
+ new_cpus = [new_cpu for old_cpu, new_cpu in cpuList]
+ old_cpu_set = set(old_cpus)
+ memory_mode_name = new_cpus[0].memory_mode()
for old_cpu, new_cpu in cpuList:
if not isinstance(old_cpu, objects.BaseCPU):
raise TypeError, "%s is not of type BaseCPU" % old_cpu
if not new_cpu.switchedOut():
raise RuntimeError, \
"New CPU (%s) is already active." % (new_cpu,)
+ if not new_cpu.support_take_over():
+ raise RuntimeError, \
+ "New CPU (%s) does not support CPU handover." % (old_cpu,)
+ if new_cpu.memory_mode() != memory_mode_name:
+ raise RuntimeError, \
+ "%s and %s require different memory modes." % (new_cpu,
+ new_cpus[0])
if old_cpu.switchedOut():
raise RuntimeError, \
"Old CPU (%s) is inactive." % (new_cpu,)
+ if not old_cpu.support_take_over():
+ raise RuntimeError, \
+ "Old CPU (%s) does not support CPU handover." % (old_cpu,)
+
+ try:
+ memory_mode = _memory_modes[memory_mode_name]
+ except KeyError:
+ raise RuntimeError, "Invalid memory mode (%s)" % memory_mode_name
+
+ if do_drain:
+ drain(system)
# Now all of the CPUs are ready to be switched out
for old_cpu, new_cpu in cpuList:
old_cpu.switchOut()
+ # Change the memory mode if required. We check if this is needed
+ # to avoid printing a warning if no switch was performed.
+ if system.getMemoryMode() != memory_mode:
+ _changeMemoryMode(system, memory_mode)
+
for old_cpu, new_cpu in cpuList:
new_cpu.takeOverFrom(old_cpu)
+ if do_drain:
+ resume(system)
+
from internal.core import disableAllListeners
m5.util.addToPath('../configs/common')
from Caches import *
-def _memMode(cclass):
- if cclass == AtomicSimpleCPU:
- return "atomic", m5.objects.params.atomic
- else:
- return "timing", m5.objects.params.timing
-
class Sequential:
"""Sequential CPU switcher.
current_cpu = switcher.first()
system = root.system
- system.mem_mode = _memMode(type(current_cpu))[0]
+ system.mem_mode = type(current_cpu).memory_mode()
# instantiate configuration
m5.instantiate()
print "Switching CPUs..."
print "Next CPU: %s" % type(next_cpu)
m5.drain(system)
- system.setMemoryMode(_memMode(type(next_cpu))[1])
if current_cpu != next_cpu:
- m5.switchCpus([ (current_cpu, next_cpu) ])
+ m5.switchCpus(system, [ (current_cpu, next_cpu) ],
+ do_drain=False)
else:
print "Source CPU and destination CPU are the same, skipping..."
m5.resume(system)