diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 697be87e1..957203150 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -95,6 +95,7 @@ class BaseCPU(MemObject): code(''' void switchOut(); void takeOverFrom(BaseCPU *cpu); + bool switchedOut(); ''') def takeOverFrom(self, old_cpu): diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 2b1df6696..b8cd60f63 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -119,6 +119,7 @@ BaseCPU::BaseCPU(Params *p, bool is_checker) _instMasterId(p->system->getMasterId(name() + ".inst")), _dataMasterId(p->system->getMasterId(name() + ".data")), _taskId(ContextSwitchTaskId::Unknown), _pid(Request::invldPid), + _switchedOut(p->defer_registration), interrupts(p->interrupts), profileEvent(NULL), numThreads(p->numThreads), system(p->system) { @@ -356,6 +357,8 @@ BaseCPU::findContext(ThreadContext *tc) void BaseCPU::switchOut() { + assert(!_switchedOut); + _switchedOut = true; if (profileEvent && profileEvent->scheduled()) deschedule(profileEvent); } @@ -365,8 +368,11 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) { assert(threadContexts.size() == oldCPU->threadContexts.size()); assert(_cpuId == oldCPU->cpuId()); + assert(_switchedOut); + assert(oldCPU != this); _pid = oldCPU->getPid(); _taskId = oldCPU->taskId(); + _switchedOut = false; ThreadID size = threadContexts.size(); for (ThreadID i = 0; i < size; ++i) { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 6552be0d6..633b7f2a7 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -114,6 +114,9 @@ class BaseCPU : public MemObject * used to generate a taskId */ uint32_t _pid; + /** Is the CPU switched out or active? */ + bool _switchedOut; + /** * Define a base class for the CPU ports (instruction and data) * that is refined in the subclasses. This class handles the @@ -320,6 +323,13 @@ class BaseCPU : public MemObject */ virtual void takeOverFrom(BaseCPU *cpu); + /** + * Determine if the CPU is switched out. + * + * @return True if the CPU is switched out, false otherwise. + */ + bool switchedOut() const { return _switchedOut; } + /** * Number of threads we're actually simulating (<= SMT_MAX_THREADS). * This is a constant for the duration of the simulation. diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 8ad273225..a30648929 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -228,11 +228,21 @@ def switchCpus(cpuList): 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]) 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 isinstance(new_cpu, objects.BaseCPU): raise TypeError, "%s is not of type BaseCPU" % new_cpu + if new_cpu in old_cpu_set: + raise RuntimeError, \ + "New CPU (%s) is in the list of old CPUs." % (old_cpu,) + if not new_cpu.switchedOut(): + raise RuntimeError, \ + "New CPU (%s) is already active." % (new_cpu,) + if old_cpu.switchedOut(): + raise RuntimeError, \ + "Old CPU (%s) is inactive." % (new_cpu,) # Now all of the CPUs are ready to be switched out for old_cpu, new_cpu in cpuList: