base.cc revision 9523
12SN/A/* 28922Swilliam.wang@arm.com * Copyright (c) 2011-2012 ARM Limited 38707Sandreas.hansson@arm.com * All rights reserved 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68707Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78707Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88707Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98707Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108707Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118707Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128707Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138707Sandreas.hansson@arm.com * 141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 157897Shestness@cs.utexas.edu * Copyright (c) 2011 Regents of the University of California 162SN/A * All rights reserved. 172SN/A * 182SN/A * Redistribution and use in source and binary forms, with or without 192SN/A * modification, are permitted provided that the following conditions are 202SN/A * met: redistributions of source code must retain the above copyright 212SN/A * notice, this list of conditions and the following disclaimer; 222SN/A * redistributions in binary form must reproduce the above copyright 232SN/A * notice, this list of conditions and the following disclaimer in the 242SN/A * documentation and/or other materials provided with the distribution; 252SN/A * neither the name of the copyright holders nor the names of its 262SN/A * contributors may be used to endorse or promote products derived from 272SN/A * this software without specific prior written permission. 282SN/A * 292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402665Ssaidi@eecs.umich.edu * 412665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 422665Ssaidi@eecs.umich.edu * Nathan Binkert 437897Shestness@cs.utexas.edu * Rick Strong 442SN/A */ 452SN/A 461388SN/A#include <iostream> 478229Snate@binkert.org#include <sstream> 482SN/A#include <string> 492SN/A 507781SAli.Saidi@ARM.com#include "arch/tlb.hh" 518229Snate@binkert.org#include "base/loader/symtab.hh" 521191SN/A#include "base/cprintf.hh" 531191SN/A#include "base/misc.hh" 541388SN/A#include "base/output.hh" 555529Snate@binkert.org#include "base/trace.hh" 561717SN/A#include "cpu/base.hh" 578887Sgeoffrey.blake@arm.com#include "cpu/checker/cpu.hh" 582651Ssaidi@eecs.umich.edu#include "cpu/cpuevent.hh" 598229Snate@binkert.org#include "cpu/profile.hh" 602680Sktlim@umich.edu#include "cpu/thread_context.hh" 618232Snate@binkert.org#include "debug/SyscallVerbose.hh" 625529Snate@binkert.org#include "params/BaseCPU.hh" 638779Sgblack@eecs.umich.edu#include "sim/full_system.hh" 642190SN/A#include "sim/process.hh" 6556SN/A#include "sim/sim_events.hh" 668229Snate@binkert.org#include "sim/sim_exit.hh" 672190SN/A#include "sim/system.hh" 682SN/A 692359SN/A// Hack 702359SN/A#include "sim/stat_control.hh" 712359SN/A 722SN/Ausing namespace std; 732SN/A 742SN/Avector<BaseCPU *> BaseCPU::cpuList; 752SN/A 762SN/A// This variable reflects the max number of threads in any CPU. Be 772SN/A// careful to only use it once all the CPUs that you care about have 782SN/A// been initialized 792SN/Aint maxThreadsPerCPU = 1; 802SN/A 815606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 826144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 836144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 843126Sktlim@umich.edu{ 856144Sksewell@umich.edu if (_interval) 867823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 873126Sktlim@umich.edu} 883126Sktlim@umich.edu 892356SN/Avoid 902356SN/ACPUProgressEvent::process() 912356SN/A{ 928834Satgutier@umich.edu Counter temp = cpu->totalOps(); 932356SN/A#ifndef NDEBUG 949179Sandreas.hansson@arm.com double ipc = double(temp - lastNumInst) / (_interval / cpu->clockPeriod()); 952367SN/A 966144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 976144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 986144Sksewell@umich.edu ipc); 992356SN/A ipc = 0.0; 1002367SN/A#else 1016144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 1027823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 1036144Sksewell@umich.edu temp - lastNumInst); 1042367SN/A#endif 1052356SN/A lastNumInst = temp; 1066144Sksewell@umich.edu 1076144Sksewell@umich.edu if (_repeatEvent) 1087823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 1092356SN/A} 1102356SN/A 1112356SN/Aconst char * 1125336Shines@cs.fsu.eduCPUProgressEvent::description() const 1132356SN/A{ 1144873Sstever@eecs.umich.edu return "CPU Progress"; 1152356SN/A} 1162356SN/A 1178876Sandreas.hansson@arm.comBaseCPU::BaseCPU(Params *p, bool is_checker) 1189157Sandreas.hansson@arm.com : MemObject(p), instCnt(0), _cpuId(p->cpu_id), 1198832SAli.Saidi@ARM.com _instMasterId(p->system->getMasterId(name() + ".inst")), 1208832SAli.Saidi@ARM.com _dataMasterId(p->system->getMasterId(name() + ".data")), 1219332Sdam.sunwoo@arm.com _taskId(ContextSwitchTaskId::Unknown), _pid(Request::invldPid), 1229433SAndreas.Sandberg@ARM.com _switchedOut(p->switched_out), 1239220Shestness@cs.wisc.edu interrupts(p->interrupts), profileEvent(NULL), 1249157Sandreas.hansson@arm.com numThreads(p->numThreads), system(p->system) 1252SN/A{ 1265712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1275712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1285712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1295712Shsul@eecs.umich.edu } 1305712Shsul@eecs.umich.edu 1312SN/A // add self to global list of CPUs 1322SN/A cpuList.push_back(this); 1332SN/A 1345712Shsul@eecs.umich.edu DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); 1355712Shsul@eecs.umich.edu 1366221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1376221Snate@binkert.org maxThreadsPerCPU = numThreads; 1382SN/A 1392SN/A // allocate per-thread instruction-based event queues 1406221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1416221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1426221Snate@binkert.org comInstEventQueue[tid] = 1436221Snate@binkert.org new EventQueue("instruction-based event queue"); 1442SN/A 1452SN/A // 1462SN/A // set up instruction-count-based termination events, if any 1472SN/A // 1485606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1495606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1506221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1515606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1526221Snate@binkert.org comInstEventQueue[tid]->schedule(event, p->max_insts_any_thread); 1535606Snate@binkert.org } 1545606Snate@binkert.org } 1552SN/A 1561400SN/A if (p->max_insts_all_threads != 0) { 1575606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1585606Snate@binkert.org 1592SN/A // allocate & initialize shared downcounter: each event will 1602SN/A // decrement this when triggered; simulation will terminate 1612SN/A // when counter reaches 0 1622SN/A int *counter = new int; 1636221Snate@binkert.org *counter = numThreads; 1646221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1655606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1666670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1675606Snate@binkert.org } 1682SN/A } 1692SN/A 170124SN/A // allocate per-thread load-based event queues 1716221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 1726221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1736221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 174124SN/A 175124SN/A // 176124SN/A // set up instruction-count-based termination events, if any 177124SN/A // 1785606Snate@binkert.org if (p->max_loads_any_thread != 0) { 1795606Snate@binkert.org const char *cause = "a thread reached the max load count"; 1806221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1815606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1826221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_any_thread); 1835606Snate@binkert.org } 1845606Snate@binkert.org } 185124SN/A 1861400SN/A if (p->max_loads_all_threads != 0) { 1875606Snate@binkert.org const char *cause = "all threads reached the max load count"; 188124SN/A // allocate & initialize shared downcounter: each event will 189124SN/A // decrement this when triggered; simulation will terminate 190124SN/A // when counter reaches 0 191124SN/A int *counter = new int; 1926221Snate@binkert.org *counter = numThreads; 1936221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1945606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1956221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 1965606Snate@binkert.org } 197124SN/A } 198124SN/A 1991191SN/A functionTracingEnabled = false; 2005529Snate@binkert.org if (p->function_trace) { 2018634Schris.emmons@arm.com const string fname = csprintf("ftrace.%s", name()); 2028634Schris.emmons@arm.com functionTraceStream = simout.find(fname); 2038634Schris.emmons@arm.com if (!functionTraceStream) 2048634Schris.emmons@arm.com functionTraceStream = simout.create(fname); 2058634Schris.emmons@arm.com 2061191SN/A currentFunctionStart = currentFunctionEnd = 0; 2075529Snate@binkert.org functionEntryTick = p->function_trace_start; 2081191SN/A 2095529Snate@binkert.org if (p->function_trace_start == 0) { 2101191SN/A functionTracingEnabled = true; 2111191SN/A } else { 2125606Snate@binkert.org typedef EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace> wrap; 2135606Snate@binkert.org Event *event = new wrap(this, true); 2145606Snate@binkert.org schedule(event, p->function_trace_start); 2151191SN/A } 2161191SN/A } 2178876Sandreas.hansson@arm.com 2188876Sandreas.hansson@arm.com // The interrupts should always be present unless this CPU is 2198876Sandreas.hansson@arm.com // switched in later or in case it is a checker CPU 2209433SAndreas.Sandberg@ARM.com if (!params()->switched_out && !is_checker) { 2218876Sandreas.hansson@arm.com if (interrupts) { 2228876Sandreas.hansson@arm.com interrupts->setCPU(this); 2238876Sandreas.hansson@arm.com } else { 2248876Sandreas.hansson@arm.com fatal("CPU %s has no interrupt controller.\n" 2258876Sandreas.hansson@arm.com "Ensure createInterruptController() is called.\n", name()); 2268876Sandreas.hansson@arm.com } 2278876Sandreas.hansson@arm.com } 2285810Sgblack@eecs.umich.edu 2298779Sgblack@eecs.umich.edu if (FullSystem) { 2308779Sgblack@eecs.umich.edu if (params()->profile) 2318779Sgblack@eecs.umich.edu profileEvent = new ProfileEvent(this, params()->profile); 2328779Sgblack@eecs.umich.edu } 2335529Snate@binkert.org tracer = params()->tracer; 2349384SAndreas.Sandberg@arm.com 2359384SAndreas.Sandberg@arm.com if (params()->isa.size() != numThreads) { 2369384SAndreas.Sandberg@arm.com fatal("Number of ISAs (%i) assigned to the CPU does not equal number " 2379384SAndreas.Sandberg@arm.com "of threads (%i).\n", params()->isa.size(), numThreads); 2389384SAndreas.Sandberg@arm.com } 2391917SN/A} 2401191SN/A 2411191SN/Avoid 2421191SN/ABaseCPU::enableFunctionTrace() 2431191SN/A{ 2441191SN/A functionTracingEnabled = true; 2451191SN/A} 2461191SN/A 2471191SN/ABaseCPU::~BaseCPU() 2481191SN/A{ 2499086Sandreas.hansson@arm.com delete profileEvent; 2509086Sandreas.hansson@arm.com delete[] comLoadEventQueue; 2519086Sandreas.hansson@arm.com delete[] comInstEventQueue; 2521191SN/A} 2531191SN/A 2541129SN/Avoid 2551129SN/ABaseCPU::init() 2561129SN/A{ 2579523SAndreas.Sandberg@ARM.com if (!params()->switched_out) { 2582680Sktlim@umich.edu registerThreadContexts(); 2599523SAndreas.Sandberg@ARM.com 2609523SAndreas.Sandberg@ARM.com verifyMemoryMode(); 2619523SAndreas.Sandberg@ARM.com } 2621129SN/A} 263180SN/A 2642SN/Avoid 2651917SN/ABaseCPU::startup() 2661917SN/A{ 2678779Sgblack@eecs.umich.edu if (FullSystem) { 2689433SAndreas.Sandberg@ARM.com if (!params()->switched_out && profileEvent) 2698779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 2708779Sgblack@eecs.umich.edu } 2712356SN/A 2725529Snate@binkert.org if (params()->progress_interval) { 2739179Sandreas.hansson@arm.com new CPUProgressEvent(this, params()->progress_interval); 2742356SN/A } 2751917SN/A} 2761917SN/A 2771917SN/A 2781917SN/Avoid 2792SN/ABaseCPU::regStats() 2802SN/A{ 281729SN/A using namespace Stats; 282707SN/A 283707SN/A numCycles 284707SN/A .name(name() + ".numCycles") 285707SN/A .desc("number of cpu cycles simulated") 286707SN/A ; 287707SN/A 2887914SBrad.Beckmann@amd.com numWorkItemsStarted 2897914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsStarted") 2907914SBrad.Beckmann@amd.com .desc("number of work items this cpu started") 2917914SBrad.Beckmann@amd.com ; 2927914SBrad.Beckmann@amd.com 2937914SBrad.Beckmann@amd.com numWorkItemsCompleted 2947914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsCompleted") 2957914SBrad.Beckmann@amd.com .desc("number of work items this cpu completed") 2967914SBrad.Beckmann@amd.com ; 2977914SBrad.Beckmann@amd.com 2982680Sktlim@umich.edu int size = threadContexts.size(); 2992SN/A if (size > 1) { 3002SN/A for (int i = 0; i < size; ++i) { 3012SN/A stringstream namestr; 3022SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 3032680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 3042SN/A } 3052SN/A } else if (size == 1) 3062680Sktlim@umich.edu threadContexts[0]->regStats(name()); 3072SN/A} 3082SN/A 3099294Sandreas.hansson@arm.comBaseMasterPort & 3109294Sandreas.hansson@arm.comBaseCPU::getMasterPort(const string &if_name, PortID idx) 3118850Sandreas.hansson@arm.com{ 3128850Sandreas.hansson@arm.com // Get the right port based on name. This applies to all the 3138850Sandreas.hansson@arm.com // subclasses of the base CPU and relies on their implementation 3148850Sandreas.hansson@arm.com // of getDataPort and getInstPort. In all cases there methods 3158850Sandreas.hansson@arm.com // return a CpuPort pointer. 3168850Sandreas.hansson@arm.com if (if_name == "dcache_port") 3178922Swilliam.wang@arm.com return getDataPort(); 3188850Sandreas.hansson@arm.com else if (if_name == "icache_port") 3198922Swilliam.wang@arm.com return getInstPort(); 3208850Sandreas.hansson@arm.com else 3218922Swilliam.wang@arm.com return MemObject::getMasterPort(if_name, idx); 3228850Sandreas.hansson@arm.com} 3238850Sandreas.hansson@arm.com 324180SN/Avoid 3252680Sktlim@umich.eduBaseCPU::registerThreadContexts() 326180SN/A{ 3276221Snate@binkert.org ThreadID size = threadContexts.size(); 3286221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3296221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 3302378SN/A 3315718Shsul@eecs.umich.edu /** This is so that contextId and cpuId match where there is a 3325718Shsul@eecs.umich.edu * 1cpu:1context relationship. Otherwise, the order of registration 3335718Shsul@eecs.umich.edu * could affect the assignment and cpu 1 could have context id 3, for 3345718Shsul@eecs.umich.edu * example. We may even want to do something like this for SMT so that 3355718Shsul@eecs.umich.edu * cpu 0 has the lowest thread contexts and cpu N has the highest, but 3365718Shsul@eecs.umich.edu * I'll just do this for now 3375718Shsul@eecs.umich.edu */ 3386221Snate@binkert.org if (numThreads == 1) 3395718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 3405718Shsul@eecs.umich.edu else 3415718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc)); 3428779Sgblack@eecs.umich.edu 3438779Sgblack@eecs.umich.edu if (!FullSystem) 3448779Sgblack@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 345180SN/A } 346180SN/A} 347180SN/A 348180SN/A 3494000Ssaidi@eecs.umich.eduint 3504000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 3514000Ssaidi@eecs.umich.edu{ 3526221Snate@binkert.org ThreadID size = threadContexts.size(); 3536221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3546221Snate@binkert.org if (tc == threadContexts[tid]) 3556221Snate@binkert.org return tid; 3564000Ssaidi@eecs.umich.edu } 3574000Ssaidi@eecs.umich.edu return 0; 3584000Ssaidi@eecs.umich.edu} 3594000Ssaidi@eecs.umich.edu 360180SN/Avoid 3612798Sktlim@umich.eduBaseCPU::switchOut() 362180SN/A{ 3639430SAndreas.Sandberg@ARM.com assert(!_switchedOut); 3649430SAndreas.Sandberg@ARM.com _switchedOut = true; 3652359SN/A if (profileEvent && profileEvent->scheduled()) 3665606Snate@binkert.org deschedule(profileEvent); 3679446SAndreas.Sandberg@ARM.com 3689446SAndreas.Sandberg@ARM.com // Flush all TLBs in the CPU to avoid having stale translations if 3699446SAndreas.Sandberg@ARM.com // it gets switched in later. 3709446SAndreas.Sandberg@ARM.com flushTLBs(); 371180SN/A} 372180SN/A 373180SN/Avoid 3748737Skoansin.tan@gmail.comBaseCPU::takeOverFrom(BaseCPU *oldCPU) 375180SN/A{ 3762680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 3779152Satgutier@umich.edu assert(_cpuId == oldCPU->cpuId()); 3789430SAndreas.Sandberg@ARM.com assert(_switchedOut); 3799430SAndreas.Sandberg@ARM.com assert(oldCPU != this); 3809332Sdam.sunwoo@arm.com _pid = oldCPU->getPid(); 3819332Sdam.sunwoo@arm.com _taskId = oldCPU->taskId(); 3829430SAndreas.Sandberg@ARM.com _switchedOut = false; 3835712Shsul@eecs.umich.edu 3846221Snate@binkert.org ThreadID size = threadContexts.size(); 3856221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 3862680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 3872680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 388180SN/A 3892680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 3902651Ssaidi@eecs.umich.edu 3912680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 3922651Ssaidi@eecs.umich.edu 3935714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 3945715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 3955714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 3962359SN/A 3975875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 3985875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 3995875Ssteve.reinhardt@amd.com * point. 4005875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 4015217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 4025875Ssteve.reinhardt@amd.com */ 4037781SAli.Saidi@ARM.com 4049294Sandreas.hansson@arm.com BaseMasterPort *old_itb_port = oldTC->getITBPtr()->getMasterPort(); 4059294Sandreas.hansson@arm.com BaseMasterPort *old_dtb_port = oldTC->getDTBPtr()->getMasterPort(); 4069294Sandreas.hansson@arm.com BaseMasterPort *new_itb_port = newTC->getITBPtr()->getMasterPort(); 4079294Sandreas.hansson@arm.com BaseMasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort(); 4087781SAli.Saidi@ARM.com 4097781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 4109178Sandreas.hansson@arm.com if (new_itb_port) { 4119178Sandreas.hansson@arm.com assert(!new_itb_port->isConnected()); 4127781SAli.Saidi@ARM.com assert(old_itb_port); 4139178Sandreas.hansson@arm.com assert(old_itb_port->isConnected()); 4149294Sandreas.hansson@arm.com BaseSlavePort &slavePort = old_itb_port->getSlavePort(); 4159178Sandreas.hansson@arm.com old_itb_port->unbind(); 4168922Swilliam.wang@arm.com new_itb_port->bind(slavePort); 4177781SAli.Saidi@ARM.com } 4189178Sandreas.hansson@arm.com if (new_dtb_port) { 4199178Sandreas.hansson@arm.com assert(!new_dtb_port->isConnected()); 4207781SAli.Saidi@ARM.com assert(old_dtb_port); 4219178Sandreas.hansson@arm.com assert(old_dtb_port->isConnected()); 4229294Sandreas.hansson@arm.com BaseSlavePort &slavePort = old_dtb_port->getSlavePort(); 4239178Sandreas.hansson@arm.com old_dtb_port->unbind(); 4248922Swilliam.wang@arm.com new_dtb_port->bind(slavePort); 4257781SAli.Saidi@ARM.com } 4268733Sgeoffrey.blake@arm.com 4278887Sgeoffrey.blake@arm.com // Checker whether or not we have to transfer CheckerCPU 4288887Sgeoffrey.blake@arm.com // objects over in the switch 4298887Sgeoffrey.blake@arm.com CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr(); 4308887Sgeoffrey.blake@arm.com CheckerCPU *newChecker = newTC->getCheckerCpuPtr(); 4318887Sgeoffrey.blake@arm.com if (oldChecker && newChecker) { 4329294Sandreas.hansson@arm.com BaseMasterPort *old_checker_itb_port = 4338922Swilliam.wang@arm.com oldChecker->getITBPtr()->getMasterPort(); 4349294Sandreas.hansson@arm.com BaseMasterPort *old_checker_dtb_port = 4358922Swilliam.wang@arm.com oldChecker->getDTBPtr()->getMasterPort(); 4369294Sandreas.hansson@arm.com BaseMasterPort *new_checker_itb_port = 4378922Swilliam.wang@arm.com newChecker->getITBPtr()->getMasterPort(); 4389294Sandreas.hansson@arm.com BaseMasterPort *new_checker_dtb_port = 4398922Swilliam.wang@arm.com newChecker->getDTBPtr()->getMasterPort(); 4408733Sgeoffrey.blake@arm.com 4418887Sgeoffrey.blake@arm.com // Move over any table walker ports if they exist for checker 4429178Sandreas.hansson@arm.com if (new_checker_itb_port) { 4439178Sandreas.hansson@arm.com assert(!new_checker_itb_port->isConnected()); 4448887Sgeoffrey.blake@arm.com assert(old_checker_itb_port); 4459178Sandreas.hansson@arm.com assert(old_checker_itb_port->isConnected()); 4469294Sandreas.hansson@arm.com BaseSlavePort &slavePort = 4479294Sandreas.hansson@arm.com old_checker_itb_port->getSlavePort(); 4489178Sandreas.hansson@arm.com old_checker_itb_port->unbind(); 4498922Swilliam.wang@arm.com new_checker_itb_port->bind(slavePort); 4508887Sgeoffrey.blake@arm.com } 4519178Sandreas.hansson@arm.com if (new_checker_dtb_port) { 4529178Sandreas.hansson@arm.com assert(!new_checker_dtb_port->isConnected()); 4538887Sgeoffrey.blake@arm.com assert(old_checker_dtb_port); 4549178Sandreas.hansson@arm.com assert(old_checker_dtb_port->isConnected()); 4559294Sandreas.hansson@arm.com BaseSlavePort &slavePort = 4569294Sandreas.hansson@arm.com old_checker_dtb_port->getSlavePort(); 4579178Sandreas.hansson@arm.com old_checker_dtb_port->unbind(); 4588922Swilliam.wang@arm.com new_checker_dtb_port->bind(slavePort); 4598887Sgeoffrey.blake@arm.com } 4608733Sgeoffrey.blake@arm.com } 461180SN/A } 462605SN/A 4633520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 4645810Sgblack@eecs.umich.edu interrupts->setCPU(this); 4659152Satgutier@umich.edu oldCPU->interrupts = NULL; 4662254SN/A 4678779Sgblack@eecs.umich.edu if (FullSystem) { 4688779Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; ++i) 4698779Sgblack@eecs.umich.edu threadContexts[i]->profileClear(); 4702254SN/A 4718779Sgblack@eecs.umich.edu if (profileEvent) 4728779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 4738779Sgblack@eecs.umich.edu } 4744192Sktlim@umich.edu 4759178Sandreas.hansson@arm.com // All CPUs have an instruction and a data port, and the new CPU's 4769178Sandreas.hansson@arm.com // ports are dangling while the old CPU has its ports connected 4779178Sandreas.hansson@arm.com // already. Unbind the old CPU and then bind the ports of the one 4789178Sandreas.hansson@arm.com // we are switching to. 4799178Sandreas.hansson@arm.com assert(!getInstPort().isConnected()); 4809178Sandreas.hansson@arm.com assert(oldCPU->getInstPort().isConnected()); 4819294Sandreas.hansson@arm.com BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort(); 4829178Sandreas.hansson@arm.com oldCPU->getInstPort().unbind(); 4839178Sandreas.hansson@arm.com getInstPort().bind(inst_peer_port); 4844192Sktlim@umich.edu 4859178Sandreas.hansson@arm.com assert(!getDataPort().isConnected()); 4869178Sandreas.hansson@arm.com assert(oldCPU->getDataPort().isConnected()); 4879294Sandreas.hansson@arm.com BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort(); 4889178Sandreas.hansson@arm.com oldCPU->getDataPort().unbind(); 4899178Sandreas.hansson@arm.com getDataPort().bind(data_peer_port); 490180SN/A} 491180SN/A 4929446SAndreas.Sandberg@ARM.comvoid 4939446SAndreas.Sandberg@ARM.comBaseCPU::flushTLBs() 4949446SAndreas.Sandberg@ARM.com{ 4959446SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < threadContexts.size(); ++i) { 4969446SAndreas.Sandberg@ARM.com ThreadContext &tc(*threadContexts[i]); 4979446SAndreas.Sandberg@ARM.com CheckerCPU *checker(tc.getCheckerCpuPtr()); 4989446SAndreas.Sandberg@ARM.com 4999446SAndreas.Sandberg@ARM.com tc.getITBPtr()->flushAll(); 5009446SAndreas.Sandberg@ARM.com tc.getDTBPtr()->flushAll(); 5019446SAndreas.Sandberg@ARM.com if (checker) { 5029446SAndreas.Sandberg@ARM.com checker->getITBPtr()->flushAll(); 5039446SAndreas.Sandberg@ARM.com checker->getDTBPtr()->flushAll(); 5049446SAndreas.Sandberg@ARM.com } 5059446SAndreas.Sandberg@ARM.com } 5069446SAndreas.Sandberg@ARM.com} 5079446SAndreas.Sandberg@ARM.com 508180SN/A 5095536Srstrong@hp.comBaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) 5105606Snate@binkert.org : cpu(_cpu), interval(_interval) 5111917SN/A{ } 5121917SN/A 5131917SN/Avoid 5141917SN/ABaseCPU::ProfileEvent::process() 5151917SN/A{ 5166221Snate@binkert.org ThreadID size = cpu->threadContexts.size(); 5176221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 5182680Sktlim@umich.edu ThreadContext *tc = cpu->threadContexts[i]; 5192680Sktlim@umich.edu tc->profileSample(); 5201917SN/A } 5212254SN/A 5227823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + interval); 5231917SN/A} 5241917SN/A 5252SN/Avoid 526921SN/ABaseCPU::serialize(std::ostream &os) 527921SN/A{ 5284000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 5299332Sdam.sunwoo@arm.com 5309448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 5319448SAndreas.Sandberg@ARM.com /* Unlike _pid, _taskId is not serialized, as they are dynamically 5329448SAndreas.Sandberg@ARM.com * assigned unique ids that are only meaningful for the duration of 5339448SAndreas.Sandberg@ARM.com * a specific run. We will need to serialize the entire taskMap in 5349448SAndreas.Sandberg@ARM.com * system. */ 5359448SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(_pid); 5369332Sdam.sunwoo@arm.com 5379448SAndreas.Sandberg@ARM.com interrupts->serialize(os); 5389448SAndreas.Sandberg@ARM.com 5399448SAndreas.Sandberg@ARM.com // Serialize the threads, this is done by the CPU implementation. 5409448SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) { 5419448SAndreas.Sandberg@ARM.com nameOut(os, csprintf("%s.xc.%i", name(), i)); 5429448SAndreas.Sandberg@ARM.com serializeThread(os, i); 5439448SAndreas.Sandberg@ARM.com } 5449448SAndreas.Sandberg@ARM.com } 545921SN/A} 546921SN/A 547921SN/Avoid 548921SN/ABaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 549921SN/A{ 5504000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 5519448SAndreas.Sandberg@ARM.com 5529448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 5539448SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(_pid); 5549448SAndreas.Sandberg@ARM.com interrupts->unserialize(cp, section); 5559448SAndreas.Sandberg@ARM.com 5569448SAndreas.Sandberg@ARM.com // Unserialize the threads, this is done by the CPU implementation. 5579448SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) 5589448SAndreas.Sandberg@ARM.com unserializeThread(cp, csprintf("%s.xc.%i", section, i), i); 5599448SAndreas.Sandberg@ARM.com } 560921SN/A} 561921SN/A 5621191SN/Avoid 5631191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 5641191SN/A{ 5651191SN/A if (!debugSymbolTable) 5661191SN/A return; 5671191SN/A 5681191SN/A // if pc enters different function, print new function symbol and 5691191SN/A // update saved range. Otherwise do nothing. 5701191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 5711191SN/A string sym_str; 5721191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 5731191SN/A currentFunctionStart, 5741191SN/A currentFunctionEnd); 5751191SN/A 5761191SN/A if (!found) { 5771191SN/A // no symbol found: use addr as label 5781191SN/A sym_str = csprintf("0x%x", pc); 5791191SN/A currentFunctionStart = pc; 5801191SN/A currentFunctionEnd = pc + 1; 5811191SN/A } 5821191SN/A 5831191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 5847823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 5857823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 5861191SN/A } 5871191SN/A} 5888707Sandreas.hansson@arm.com 5898707Sandreas.hansson@arm.combool 5908975Sandreas.hansson@arm.comBaseCPU::CpuPort::recvTimingResp(PacketPtr pkt) 5918707Sandreas.hansson@arm.com{ 5928948Sandreas.hansson@arm.com panic("BaseCPU doesn't expect recvTiming!\n"); 5938707Sandreas.hansson@arm.com return true; 5948707Sandreas.hansson@arm.com} 5958707Sandreas.hansson@arm.com 5968707Sandreas.hansson@arm.comvoid 5978707Sandreas.hansson@arm.comBaseCPU::CpuPort::recvRetry() 5988707Sandreas.hansson@arm.com{ 5998948Sandreas.hansson@arm.com panic("BaseCPU doesn't expect recvRetry!\n"); 6008707Sandreas.hansson@arm.com} 6018707Sandreas.hansson@arm.com 6028707Sandreas.hansson@arm.comvoid 6038948Sandreas.hansson@arm.comBaseCPU::CpuPort::recvFunctionalSnoop(PacketPtr pkt) 6048707Sandreas.hansson@arm.com{ 6058948Sandreas.hansson@arm.com // No internal storage to update (in the general case). A CPU with 6068948Sandreas.hansson@arm.com // internal storage, e.g. an LSQ that should be part of the 6078948Sandreas.hansson@arm.com // coherent memory has to check against stored data. 6088707Sandreas.hansson@arm.com} 609