if (stCondFailures % 100000 == 0) {
                 warn("cpu %d: %d consecutive "
                      "store conditional failures\n",
-                     xc->readCpuId(), stCondFailures);
+                     xc->cpuId(), stCondFailures);
             }
 
             // store conditional failed already, so don't issue it to mem
 
             if (stCondFailures % 10 == 0) {
                 warn("%i: cpu %d: %d consecutive "
                      "store conditional failures\n",
-                     curTick, xc->readCpuId(), stCondFailures);
+                     curTick, xc->cpuId(), stCondFailures);
             }
 
             if (stCondFailures == 5000) {
 
         temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative);
         // Check that the CPU array is fully populated
         // (by calling getNumCPus())
-        assert(sys->getNumCPUs() > tc->readCpuId());
+        assert(sys->getNumCPUs() > tc->cpuId());
 
-        temp |= tc->readCpuId()  << STS::shft_id;
+        temp |= tc->cpuId()  << STS::shft_id;
 
-        for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) {
+        for (x = tc->cpuId() & ~3; x < sys->threadContexts.size(); x++) {
             switch (sys->threadContexts[x]->status()) {
               case ThreadContext::Active:
                 temp |= STS::st_run << (STS::shft_fsm0 -
 
         */
         // Force the access to be uncacheable.
         req->setFlags(req->getFlags() | UNCACHEABLE);
-        req->setPaddr(x86LocalAPICAddress(tc->readCpuId(), paddr - baseAddr));
+        req->setPaddr(x86LocalAPICAddress(tc->cpuId(), paddr - baseAddr));
     }
 #endif
     return NoFault;
 
     abstract = True
 
     system = Param.System(Parent.any, "system object")
-    cpu_id = Param.Int("CPU identifier")
+    cpu_id = Param.Int(-1, "CPU identifier")
     numThreads = Param.Unsigned(1, "number of HW thread contexts")
 
     function_trace = Param.Bool(False, "Enable function trace")
 
 
 #if FULL_SYSTEM
 BaseCPU::BaseCPU(Params *p)
-    : MemObject(p), clock(p->clock), instCnt(0), interrupts(p->interrupts),
+    : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id),
+      interrupts(p->interrupts),
       number_of_threads(p->numThreads), system(p->system),
       phase(p->phase)
 #else
 BaseCPU::BaseCPU(Params *p)
-    : MemObject(p), clock(p->clock),
+    : MemObject(p), clock(p->clock), _cpuId(p->cpu_id),
       number_of_threads(p->numThreads), system(p->system),
       phase(p->phase)
 #endif
 {
 //    currentTick = curTick;
 
+    // if Python did not provide a valid ID, do it here
+    if (_cpuId == -1 ) {
+        _cpuId = cpuList.size();
+    }
+
     // add self to global list of CPUs
     cpuList.push_back(this);
 
+    DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId);
+
     if (number_of_threads > maxThreadsPerCPU)
         maxThreadsPerCPU = number_of_threads;
 
         ThreadContext *tc = threadContexts[i];
 
 #if FULL_SYSTEM
-        int id = params()->cpu_id;
-        if (id != -1)
-            id += i;
-
-        tc->setCpuId(system->registerThreadContext(tc, id));
+        system->registerThreadContext(tc);
 #else
-        tc->setCpuId(tc->getProcessPtr()->registerThreadContext(tc));
+        tc->getProcessPtr()->registerThreadContext(tc);
 #endif
     }
 }
 {
     assert(threadContexts.size() == oldCPU->threadContexts.size());
 
+    _cpuId = oldCPU->cpuId();
+
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *newTC = threadContexts[i];
         ThreadContext *oldTC = oldCPU->threadContexts[i];
 
         CpuEvent::replaceThreadContext(oldTC, newTC);
 
-        assert(newTC->readCpuId() == oldTC->readCpuId());
+        assert(newTC->cpuId() == oldTC->cpuId());
 #if FULL_SYSTEM
-        system->replaceThreadContext(newTC, newTC->readCpuId());
+        system->replaceThreadContext(newTC, newTC->cpuId());
 #else
         assert(newTC->getProcessPtr() == oldTC->getProcessPtr());
-        newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->readCpuId());
+        newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->cpuId());
 #endif
 
         if (DTRACE(Context))
 
     Tick clock;
     // @todo remove me after debugging with legion done
     Tick instCnt;
+    // every cpu has an id, put it in the base cpu
+    // Set at initialization, only time a cpuId might change is during a
+    // takeover (which should be done from within the BaseCPU anyway, 
+    // therefore no setCpuId() method is provided
+    int _cpuId;
 
   public:
+    /** Reads this CPU's ID. */
+    int cpuId() { return _cpuId; }
+
 //    Tick currentTick;
     inline Tick frequency() const { return Clock::Frequency / clock; }
     inline Tick ticks(int numCycles) const { return clock * numCycles; }
 
     void dump(std::string &outstring);
 
     /** Read this CPU's ID. */
-    int readCpuId() { return cpu->readCpuId(); }
+    int cpuId() { return cpu->cpuId(); }
 
     /** Returns the fault type. */
     Fault getFault() { return fault; }
     reqMade = true;
     Request *req = new Request();
     req->setVirt(asid, vaddr, size, flags, PC);
-    req->setThreadContext(thread->readCpuId(), threadNumber);
+    req->setThreadContext(thread->cpuId(), threadNumber);
 
     fault = cpu->translateDataReadReq(req, thread);
 
     reqMade = true;
     Request *req = new Request();
     req->setVirt(asid, addr, sizeof(T), flags, this->PC);
-    req->setThreadContext(thread->readCpuId(), threadNumber);
+    req->setThreadContext(thread->cpuId(), threadNumber);
 
     fault = cpu->translateDataReadReq(req, thread);
 
     reqMade = true;
     Request *req = new Request();
     req->setVirt(asid, vaddr, size, flags, PC);
-    req->setThreadContext(thread->readCpuId(), threadNumber);
+    req->setThreadContext(thread->cpuId(), threadNumber);
 
     fault = cpu->translateDataWriteReq(req, thread);
 
     reqMade = true;
     Request *req = new Request();
     req->setVirt(asid, addr, sizeof(T), flags, this->PC);
-    req->setThreadContext(thread->readCpuId(), threadNumber);
+    req->setThreadContext(thread->cpuId(), threadNumber);
 
     fault = cpu->translateDataWriteReq(req, thread);
 
 
         memReq = new Request(inst->threadNumber, fetch_PC,
                              sizeof(uint32_t),
                              IFETCH_FLAGS(thread->readPC()),
-                             fetch_PC, thread->readCpuId(), inst->threadNumber);
+                             fetch_PC, thread->cpuId(), inst->threadNumber);
 
         bool succeeded = translateInstReq(memReq);
 
 
         checkerTC->setCpuId(id);
     }
 
-    int readCpuId() { return actualTC->readCpuId(); }
+    int cpuId() { return actualTC->cpuId(); }
 
     TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); }
 
 
 using namespace TheISA;
 
 BaseO3CPU::BaseO3CPU(BaseCPUParams *params)
-    : BaseCPU(params), cpuId(0)
+    : BaseCPU(params)
 {
 }
 
 #endif
         // Give the thread the TC.
         this->thread[i]->tc = tc;
-        this->thread[i]->setCpuId(params->cpu_id);
 
         // Add the TC to the CPU's list of TC's.
         this->threadContexts.push_back(tc);
         }
 
 #if FULL_SYSTEM
-        TheISA::initCPU(src_tc, src_tc->readCpuId());
+        TheISA::initCPU(src_tc, src_tc->cpuId());
 #endif
     }
 
 
     BaseO3CPU(BaseCPUParams *params);
 
     void regStats();
-
-    /** Sets this CPU's ID. */
-    void setCpuId(int id) { cpuId = id; }
-
-    /** Reads this CPU's ID. */
-    int readCpuId() { return cpuId; }
-
-  protected:
-    int cpuId;
 };
 
 /**
 
     // Set the appropriate read size and flags as well.
     // Build request here.
     RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0,
-                                     fetch_PC, cpu->readCpuId(), tid);
+                                     fetch_PC, cpu->cpuId(), tid);
 
     memReq[tid] = mem_req;
 
 
     /** Returns a pointer to this CPU. */
     virtual BaseCPU *getCpuPtr() { return cpu; }
 
-    /** Sets this CPU's ID. */
-    virtual void setCpuId(int id) { cpu->setCpuId(id); }
-
     /** Reads this CPU's ID. */
-    virtual int readCpuId() { return cpu->readCpuId(); }
+    virtual int cpuId() { return cpu->cpuId(); }
 
 #if FULL_SYSTEM
     /** Returns a pointer to the system. */
 
     // copy over functional state
     setStatus(old_context->status());
     copyArchRegs(old_context);
-    setCpuId(old_context->readCpuId());
 
 #if !FULL_SYSTEM
     thread->funcExeInst = old_context->readFuncExeInst();
 
 
 #if FULL_SYSTEM
     O3ThreadState(O3CPU *_cpu, int _thread_num)
-        : ThreadState(_cpu, -1, _thread_num),
+        : ThreadState(_cpu, _thread_num),
           cpu(_cpu), inSyscall(0), trapPending(0)
     {
         if (cpu->params()->profile) {
     }
 #else
     O3ThreadState(O3CPU *_cpu, int _thread_num, Process *_process, int _asid)
-        : ThreadState(_cpu, -1, _thread_num, _process, _asid),
+        : ThreadState(_cpu, _thread_num, _process, _asid),
           cpu(_cpu), inSyscall(0), trapPending(0)
     { }
 #endif
 
 
         BaseCPU *getCpuPtr();
 
-        void setCpuId(int id);
-
-        int readCpuId() { return thread->readCpuId(); }
-
         TheISA::ITB *getITBPtr() { return cpu->itb; }
 
         TheISA::DTB * getDTBPtr() { return cpu->dtb; }
   public:
     BaseCPU *getCpuPtr() { return this; }
 
-    void setCpuId(int id) { cpuId = id; }
-
-    int readCpuId() { return cpuId; }
-
-    int cpuId;
-
     void switchOut();
     void signalSwitched();
     void takeOverFrom(BaseCPU *oldCPU);
 
         ThreadContext *tc = threadContexts[i];
 
         // initialize CPU, including PC
-        TheISA::initCPU(tc, tc->readCpuId());
+        TheISA::initCPU(tc, tc->cpuId());
     }
 #endif
     frontEnd->renameTable.copyFrom(thread.renameTable);
     // copy over functional state
     setStatus(old_context->status());
     copyArchRegs(old_context);
-    setCpuId(old_context->readCpuId());
+    setCpuId(old_context->cpuId());
 
     thread->setInst(old_context->getInst());
 #if !FULL_SYSTEM
 
     // Setup the memReq to do a read of the first isntruction's address.
     // Set the appropriate read size and flags as well.
     memReq = new Request(0, fetch_PC, cacheBlkSize, 0,
-                         PC, cpu->readCpuId(), 0);
+                         PC, cpu->cpuId(), 0);
 
     // Translate the instruction request.
     fault = cpu->translateInstReq(memReq, thread);
 
 AtomicSimpleCPU::init()
 {
     BaseCPU::init();
-    cpuId = tc->readCpuId();
 #if FULL_SYSTEM
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *tc = threadContexts[i];
 
         // initialize CPU, including PC
-        TheISA::initCPU(tc, cpuId);
+        TheISA::initCPU(tc, _cpuId);
     }
 #endif
     if (hasPhysMemPort) {
         physmemPort.getPeerAddressRanges(pmAddrList, snoop);
         physMemAddr = *pmAddrList.begin();
     }
-    ifetch_req.setThreadContext(cpuId, 0); // Add thread ID if we add MT
-    data_read_req.setThreadContext(cpuId, 0); // Add thread ID here too
-    data_write_req.setThreadContext(cpuId, 0); // Add thread ID here too
+    ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT
+    data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too
+    data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
 }
 
 bool
         _status = Idle;
     }
     assert(threadContexts.size() == 1);
-    cpuId = tc->readCpuId();
-    ifetch_req.setThreadContext(cpuId, 0); // Add thread ID if we add MT
-    data_read_req.setThreadContext(cpuId, 0); // Add thread ID here too
-    data_write_req.setThreadContext(cpuId, 0); // Add thread ID here too
+    ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT
+    data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too
+    data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
 }
 
 
 
      */
     ThreadContext *tc;
   protected:
-    int cpuId;
 
     enum Status {
         Idle,
 
 TimingSimpleCPU::init()
 {
     BaseCPU::init();
-    cpuId = tc->readCpuId();
 #if FULL_SYSTEM
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *tc = threadContexts[i];
 
         // initialize CPU, including PC
-        TheISA::initCPU(tc, cpuId);
+        TheISA::initCPU(tc, _cpuId);
     }
 #endif
 }
         _status = Idle;
     }
     assert(threadContexts.size() == 1);
-    cpuId = tc->readCpuId();
+    _cpuId = tc->cpuId();
     previousTick = curTick;
 }
 
 {
     Request *req =
         new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
-                    cpuId, /* thread ID */ 0);
+                    _cpuId, /* thread ID */ 0);
 
     if (traceData) {
         traceData->setAddr(req->getVaddr());
         int size, unsigned flags)
 {
     Request *req =
-        new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0);
+        new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0);
 
     if (traceData) {
         traceData->setAddr(vaddr);
 {
     Request *req =
         new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
-                    cpuId, /* thread ID */ 0);
+                    _cpuId, /* thread ID */ 0);
 
     if (traceData) {
         traceData->setAddr(req->getVaddr());
         int size, unsigned flags)
 {
     Request *req =
-        new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0);
+        new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0);
 
     if (traceData) {
         traceData->setAddr(vaddr);
 
     if (!fromRom) {
         Request *ifetch_req = new Request();
-        ifetch_req->setThreadContext(cpuId, /* thread ID */ 0);
+        ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
         Fault fault = setupFetchRequest(ifetch_req);
 
         ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast);
 
 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
                            TheISA::ITB *_itb, TheISA::DTB *_dtb,
                            bool use_kernel_stats)
-    : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb),
+    : ThreadState(_cpu, _thread_num), cpu(_cpu), system(_sys), itb(_itb),
       dtb(_dtb)
 
 {
 #else
 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
                            TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid)
-    : ThreadState(_cpu, -1, _thread_num, _process, _asid),
+    : ThreadState(_cpu, _thread_num, _process, _asid),
       cpu(_cpu), itb(_itb), dtb(_dtb)
 {
     regs.clear();
 
 SimpleThread::SimpleThread()
 #if FULL_SYSTEM
-    : ThreadState(NULL, -1, -1)
+    : ThreadState(NULL, -1)
 #else
-    : ThreadState(NULL, -1, -1, NULL, -1)
+    : ThreadState(NULL, -1, NULL, -1)
 #endif
 {
     tc = new ProxyThreadContext<SimpleThread>(this);
     // copy over functional state
     _status = oldContext->status();
     copyArchRegs(oldContext);
-    cpuId = oldContext->readCpuId();
 #if !FULL_SYSTEM
     funcExeInst = oldContext->readFuncExeInst();
 #endif
 
     if (npc1 != npc2)
         panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2);
 
-    int id1 = one->readCpuId();
-    int id2 = two->readCpuId();
+    int id1 = one->cpuId();
+    int id2 = two->cpuId();
     if (id1 != id2)
         panic("CPU ids don't match, one: %d, two: %d", id1, id2);
 }
 
 
     virtual BaseCPU *getCpuPtr() = 0;
 
-    virtual void setCpuId(int id) = 0;
-
-    virtual int readCpuId() = 0;
+    virtual int cpuId() = 0;
 
     virtual TheISA::ITB *getITBPtr() = 0;
 
 
     BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); }
 
-    void setCpuId(int id) { actualTC->setCpuId(id); }
-
-    int readCpuId() { return actualTC->readCpuId(); }
+    int cpuId() { return actualTC->cpuId(); }
 
     TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); }
 
 
 #endif
 
 #if FULL_SYSTEM
-ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid)
-    : baseCpu(cpu), cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0),
+ThreadState::ThreadState(BaseCPU *cpu, int _tid)
+    : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0),
       profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL),
       kernelStats(NULL), physPort(NULL), virtPort(NULL),
       microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0)
 #else
-ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process,
+ThreadState::ThreadState(BaseCPU *cpu, int _tid, Process *_process,
                          short _asid)
-    : baseCpu(cpu), cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0),
+    : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0),
       port(NULL), process(_process), asid(_asid),
       microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0)
 #endif
 
 #include "arch/types.hh"
 #include "cpu/profile.hh"
 #include "cpu/thread_context.hh"
+#include "cpu/base.hh"
 
 #if !FULL_SYSTEM
 #include "mem/mem_object.hh"
 };
 #endif
 
-class BaseCPU;
 class Checkpoint;
 class Port;
 class TranslatingPort;
     typedef ThreadContext::Status Status;
 
 #if FULL_SYSTEM
-    ThreadState(BaseCPU *cpu, int _cpuId, int _tid);
+    ThreadState(BaseCPU *cpu, int _tid);
 #else
-    ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process,
+    ThreadState(BaseCPU *cpu, int _tid, Process *_process,
                 short _asid);
 #endif
 
 
     void unserialize(Checkpoint *cp, const std::string §ion);
 
-    void setCpuId(int id) { cpuId = id; }
-
-    int readCpuId() { return cpuId; }
+    int cpuId() { return baseCpu->cpuId(); }
 
     void setTid(int id) { tid = id; }
 
     // Pointer to the base CPU.
     BaseCPU *baseCpu;
 
-    // ID of this context w.r.t. the System or Process object to which
-    // it belongs.  For full-system mode, this is the system CPU ID.
-    int cpuId;
-
     // Index of hardware thread context on the CPU that this represents.
     int tid;
 
 
 }
 
 int
-System::registerThreadContext(ThreadContext *tc, int id)
+System::registerThreadContext(ThreadContext *tc)
 {
-    if (id == -1) {
-        for (id = 0; id < threadContexts.size(); id++) {
-            if (!threadContexts[id])
-                break;
-        }
+    int id;
+    for (id = 0; id < threadContexts.size(); id++) {
+        if (!threadContexts[id])
+            break;
     }
 
     if (threadContexts.size() <= id)
 
 
 #endif // FULL_SYSTEM
 
-    int registerThreadContext(ThreadContext *tc, int tcIndex);
+    int registerThreadContext(ThreadContext *tc);
     void replaceThreadContext(ThreadContext *tc, int tcIndex);
 
     void serialize(std::ostream &os);