base.cc revision 8850
12SN/A/* 28707Sandreas.hansson@arm.com * Copyright (c) 2011 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" 568733Sgeoffrey.blake@arm.com#include "config/use_checker.hh" 571717SN/A#include "cpu/base.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 698733Sgeoffrey.blake@arm.com#if USE_CHECKER 708733Sgeoffrey.blake@arm.com#include "cpu/checker/cpu.hh" 718733Sgeoffrey.blake@arm.com#endif 728733Sgeoffrey.blake@arm.com 732359SN/A// Hack 742359SN/A#include "sim/stat_control.hh" 752359SN/A 762SN/Ausing namespace std; 772SN/A 782SN/Avector<BaseCPU *> BaseCPU::cpuList; 792SN/A 802SN/A// This variable reflects the max number of threads in any CPU. Be 812SN/A// careful to only use it once all the CPUs that you care about have 822SN/A// been initialized 832SN/Aint maxThreadsPerCPU = 1; 842SN/A 855606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 866144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 876144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 883126Sktlim@umich.edu{ 896144Sksewell@umich.edu if (_interval) 907823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 913126Sktlim@umich.edu} 923126Sktlim@umich.edu 932356SN/Avoid 942356SN/ACPUProgressEvent::process() 952356SN/A{ 968834Satgutier@umich.edu Counter temp = cpu->totalOps(); 972356SN/A#ifndef NDEBUG 986144Sksewell@umich.edu double ipc = double(temp - lastNumInst) / (_interval / cpu->ticks(1)); 992367SN/A 1006144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 1016144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 1026144Sksewell@umich.edu ipc); 1032356SN/A ipc = 0.0; 1042367SN/A#else 1056144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 1067823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 1076144Sksewell@umich.edu temp - lastNumInst); 1082367SN/A#endif 1092356SN/A lastNumInst = temp; 1106144Sksewell@umich.edu 1116144Sksewell@umich.edu if (_repeatEvent) 1127823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 1132356SN/A} 1142356SN/A 1152356SN/Aconst char * 1165336Shines@cs.fsu.eduCPUProgressEvent::description() const 1172356SN/A{ 1184873Sstever@eecs.umich.edu return "CPU Progress"; 1192356SN/A} 1202356SN/A 1211400SN/ABaseCPU::BaseCPU(Params *p) 1225712Shsul@eecs.umich.edu : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), 1238832SAli.Saidi@ARM.com _instMasterId(p->system->getMasterId(name() + ".inst")), 1248832SAli.Saidi@ARM.com _dataMasterId(p->system->getMasterId(name() + ".data")), 1255712Shsul@eecs.umich.edu interrupts(p->interrupts), 1266221Snate@binkert.org numThreads(p->numThreads), system(p->system), 1273661Srdreslin@umich.edu phase(p->phase) 1282SN/A{ 1297823Ssteve.reinhardt@amd.com// currentTick = curTick(); 1301062SN/A 1315712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1325712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1335712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1345712Shsul@eecs.umich.edu } 1355712Shsul@eecs.umich.edu 1362SN/A // add self to global list of CPUs 1372SN/A cpuList.push_back(this); 1382SN/A 1395712Shsul@eecs.umich.edu DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); 1405712Shsul@eecs.umich.edu 1416221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1426221Snate@binkert.org maxThreadsPerCPU = numThreads; 1432SN/A 1442SN/A // allocate per-thread instruction-based event queues 1456221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1466221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1476221Snate@binkert.org comInstEventQueue[tid] = 1486221Snate@binkert.org new EventQueue("instruction-based event queue"); 1492SN/A 1502SN/A // 1512SN/A // set up instruction-count-based termination events, if any 1522SN/A // 1535606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1545606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1556221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1565606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1576221Snate@binkert.org comInstEventQueue[tid]->schedule(event, p->max_insts_any_thread); 1585606Snate@binkert.org } 1595606Snate@binkert.org } 1602SN/A 1611400SN/A if (p->max_insts_all_threads != 0) { 1625606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1635606Snate@binkert.org 1642SN/A // allocate & initialize shared downcounter: each event will 1652SN/A // decrement this when triggered; simulation will terminate 1662SN/A // when counter reaches 0 1672SN/A int *counter = new int; 1686221Snate@binkert.org *counter = numThreads; 1696221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1705606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1716670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1725606Snate@binkert.org } 1732SN/A } 1742SN/A 175124SN/A // allocate per-thread load-based event queues 1766221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 1776221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1786221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 179124SN/A 180124SN/A // 181124SN/A // set up instruction-count-based termination events, if any 182124SN/A // 1835606Snate@binkert.org if (p->max_loads_any_thread != 0) { 1845606Snate@binkert.org const char *cause = "a thread reached the max load count"; 1856221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1865606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1876221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_any_thread); 1885606Snate@binkert.org } 1895606Snate@binkert.org } 190124SN/A 1911400SN/A if (p->max_loads_all_threads != 0) { 1925606Snate@binkert.org const char *cause = "all threads reached the max load count"; 193124SN/A // allocate & initialize shared downcounter: each event will 194124SN/A // decrement this when triggered; simulation will terminate 195124SN/A // when counter reaches 0 196124SN/A int *counter = new int; 1976221Snate@binkert.org *counter = numThreads; 1986221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1995606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 2006221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 2015606Snate@binkert.org } 202124SN/A } 203124SN/A 2041191SN/A functionTracingEnabled = false; 2055529Snate@binkert.org if (p->function_trace) { 2068634Schris.emmons@arm.com const string fname = csprintf("ftrace.%s", name()); 2078634Schris.emmons@arm.com functionTraceStream = simout.find(fname); 2088634Schris.emmons@arm.com if (!functionTraceStream) 2098634Schris.emmons@arm.com functionTraceStream = simout.create(fname); 2108634Schris.emmons@arm.com 2111191SN/A currentFunctionStart = currentFunctionEnd = 0; 2125529Snate@binkert.org functionEntryTick = p->function_trace_start; 2131191SN/A 2145529Snate@binkert.org if (p->function_trace_start == 0) { 2151191SN/A functionTracingEnabled = true; 2161191SN/A } else { 2175606Snate@binkert.org typedef EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace> wrap; 2185606Snate@binkert.org Event *event = new wrap(this, true); 2195606Snate@binkert.org schedule(event, p->function_trace_start); 2201191SN/A } 2211191SN/A } 2228733Sgeoffrey.blake@arm.com // Check if CPU model has interrupts connected. The CheckerCPU 2238733Sgeoffrey.blake@arm.com // cannot take interrupts directly for example. 2248733Sgeoffrey.blake@arm.com if (interrupts) 2258733Sgeoffrey.blake@arm.com interrupts->setCPU(this); 2265810Sgblack@eecs.umich.edu 2278779Sgblack@eecs.umich.edu if (FullSystem) { 2288779Sgblack@eecs.umich.edu profileEvent = NULL; 2298779Sgblack@eecs.umich.edu if (params()->profile) 2308779Sgblack@eecs.umich.edu profileEvent = new ProfileEvent(this, params()->profile); 2318779Sgblack@eecs.umich.edu } 2325529Snate@binkert.org tracer = params()->tracer; 2331917SN/A} 2341191SN/A 2351191SN/Avoid 2361191SN/ABaseCPU::enableFunctionTrace() 2371191SN/A{ 2381191SN/A functionTracingEnabled = true; 2391191SN/A} 2401191SN/A 2411191SN/ABaseCPU::~BaseCPU() 2421191SN/A{ 2431191SN/A} 2441191SN/A 2451129SN/Avoid 2461129SN/ABaseCPU::init() 2471129SN/A{ 2485529Snate@binkert.org if (!params()->defer_registration) 2492680Sktlim@umich.edu registerThreadContexts(); 2501129SN/A} 251180SN/A 2522SN/Avoid 2531917SN/ABaseCPU::startup() 2541917SN/A{ 2558779Sgblack@eecs.umich.edu if (FullSystem) { 2568779Sgblack@eecs.umich.edu if (!params()->defer_registration && profileEvent) 2578779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 2588779Sgblack@eecs.umich.edu } 2592356SN/A 2605529Snate@binkert.org if (params()->progress_interval) { 2615606Snate@binkert.org Tick num_ticks = ticks(params()->progress_interval); 2626144Sksewell@umich.edu 2638607Sgblack@eecs.umich.edu new CPUProgressEvent(this, num_ticks); 2642356SN/A } 2651917SN/A} 2661917SN/A 2671917SN/A 2681917SN/Avoid 2692SN/ABaseCPU::regStats() 2702SN/A{ 271729SN/A using namespace Stats; 272707SN/A 273707SN/A numCycles 274707SN/A .name(name() + ".numCycles") 275707SN/A .desc("number of cpu cycles simulated") 276707SN/A ; 277707SN/A 2787914SBrad.Beckmann@amd.com numWorkItemsStarted 2797914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsStarted") 2807914SBrad.Beckmann@amd.com .desc("number of work items this cpu started") 2817914SBrad.Beckmann@amd.com ; 2827914SBrad.Beckmann@amd.com 2837914SBrad.Beckmann@amd.com numWorkItemsCompleted 2847914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsCompleted") 2857914SBrad.Beckmann@amd.com .desc("number of work items this cpu completed") 2867914SBrad.Beckmann@amd.com ; 2877914SBrad.Beckmann@amd.com 2882680Sktlim@umich.edu int size = threadContexts.size(); 2892SN/A if (size > 1) { 2902SN/A for (int i = 0; i < size; ++i) { 2912SN/A stringstream namestr; 2922SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 2932680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 2942SN/A } 2952SN/A } else if (size == 1) 2962680Sktlim@umich.edu threadContexts[0]->regStats(name()); 2972SN/A} 2982SN/A 2998850Sandreas.hansson@arm.comPort * 3008850Sandreas.hansson@arm.comBaseCPU::getPort(const string &if_name, int idx) 3018850Sandreas.hansson@arm.com{ 3028850Sandreas.hansson@arm.com // Get the right port based on name. This applies to all the 3038850Sandreas.hansson@arm.com // subclasses of the base CPU and relies on their implementation 3048850Sandreas.hansson@arm.com // of getDataPort and getInstPort. In all cases there methods 3058850Sandreas.hansson@arm.com // return a CpuPort pointer. 3068850Sandreas.hansson@arm.com if (if_name == "dcache_port") 3078850Sandreas.hansson@arm.com return &getDataPort(); 3088850Sandreas.hansson@arm.com else if (if_name == "icache_port") 3098850Sandreas.hansson@arm.com return &getInstPort(); 3108850Sandreas.hansson@arm.com else 3118850Sandreas.hansson@arm.com panic("CPU %s has no port named %s\n", name(), if_name); 3128850Sandreas.hansson@arm.com} 3138850Sandreas.hansson@arm.com 3143495Sktlim@umich.eduTick 3153495Sktlim@umich.eduBaseCPU::nextCycle() 3163495Sktlim@umich.edu{ 3177823Ssteve.reinhardt@amd.com Tick next_tick = curTick() - phase + clock - 1; 3183495Sktlim@umich.edu next_tick -= (next_tick % clock); 3193661Srdreslin@umich.edu next_tick += phase; 3203495Sktlim@umich.edu return next_tick; 3213495Sktlim@umich.edu} 3223495Sktlim@umich.edu 3233495Sktlim@umich.eduTick 3243495Sktlim@umich.eduBaseCPU::nextCycle(Tick begin_tick) 3253495Sktlim@umich.edu{ 3263495Sktlim@umich.edu Tick next_tick = begin_tick; 3274599Sacolyte@umich.edu if (next_tick % clock != 0) 3284599Sacolyte@umich.edu next_tick = next_tick - (next_tick % clock) + clock; 3293661Srdreslin@umich.edu next_tick += phase; 3303495Sktlim@umich.edu 3317823Ssteve.reinhardt@amd.com assert(next_tick >= curTick()); 3323495Sktlim@umich.edu return next_tick; 3333495Sktlim@umich.edu} 334180SN/A 335180SN/Avoid 3362680Sktlim@umich.eduBaseCPU::registerThreadContexts() 337180SN/A{ 3386221Snate@binkert.org ThreadID size = threadContexts.size(); 3396221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3406221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 3412378SN/A 3425718Shsul@eecs.umich.edu /** This is so that contextId and cpuId match where there is a 3435718Shsul@eecs.umich.edu * 1cpu:1context relationship. Otherwise, the order of registration 3445718Shsul@eecs.umich.edu * could affect the assignment and cpu 1 could have context id 3, for 3455718Shsul@eecs.umich.edu * example. We may even want to do something like this for SMT so that 3465718Shsul@eecs.umich.edu * cpu 0 has the lowest thread contexts and cpu N has the highest, but 3475718Shsul@eecs.umich.edu * I'll just do this for now 3485718Shsul@eecs.umich.edu */ 3496221Snate@binkert.org if (numThreads == 1) 3505718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 3515718Shsul@eecs.umich.edu else 3525718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc)); 3538779Sgblack@eecs.umich.edu 3548779Sgblack@eecs.umich.edu if (!FullSystem) 3558779Sgblack@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 356180SN/A } 357180SN/A} 358180SN/A 359180SN/A 3604000Ssaidi@eecs.umich.eduint 3614000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 3624000Ssaidi@eecs.umich.edu{ 3636221Snate@binkert.org ThreadID size = threadContexts.size(); 3646221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3656221Snate@binkert.org if (tc == threadContexts[tid]) 3666221Snate@binkert.org return tid; 3674000Ssaidi@eecs.umich.edu } 3684000Ssaidi@eecs.umich.edu return 0; 3694000Ssaidi@eecs.umich.edu} 3704000Ssaidi@eecs.umich.edu 371180SN/Avoid 3722798Sktlim@umich.eduBaseCPU::switchOut() 373180SN/A{ 3742359SN/A if (profileEvent && profileEvent->scheduled()) 3755606Snate@binkert.org deschedule(profileEvent); 376180SN/A} 377180SN/A 378180SN/Avoid 3798737Skoansin.tan@gmail.comBaseCPU::takeOverFrom(BaseCPU *oldCPU) 380180SN/A{ 3818850Sandreas.hansson@arm.com CpuPort &ic = getInstPort(); 3828850Sandreas.hansson@arm.com CpuPort &dc = getDataPort(); 3832680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 384180SN/A 3855712Shsul@eecs.umich.edu _cpuId = oldCPU->cpuId(); 3865712Shsul@eecs.umich.edu 3876221Snate@binkert.org ThreadID size = threadContexts.size(); 3886221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 3892680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 3902680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 391180SN/A 3922680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 3932651Ssaidi@eecs.umich.edu 3942680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 3952651Ssaidi@eecs.umich.edu 3965714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 3975715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 3985714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 3992359SN/A 4005875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 4015875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 4025875Ssteve.reinhardt@amd.com * point. 4035875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 4045217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 4055875Ssteve.reinhardt@amd.com */ 4067781SAli.Saidi@ARM.com 4077781SAli.Saidi@ARM.com Port *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port; 4087781SAli.Saidi@ARM.com old_itb_port = oldTC->getITBPtr()->getPort(); 4097781SAli.Saidi@ARM.com old_dtb_port = oldTC->getDTBPtr()->getPort(); 4107781SAli.Saidi@ARM.com new_itb_port = newTC->getITBPtr()->getPort(); 4117781SAli.Saidi@ARM.com new_dtb_port = newTC->getDTBPtr()->getPort(); 4127781SAli.Saidi@ARM.com 4137781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 4147781SAli.Saidi@ARM.com if (new_itb_port && !new_itb_port->isConnected()) { 4157781SAli.Saidi@ARM.com assert(old_itb_port); 4167781SAli.Saidi@ARM.com Port *peer = old_itb_port->getPeer();; 4177781SAli.Saidi@ARM.com new_itb_port->setPeer(peer); 4187781SAli.Saidi@ARM.com peer->setPeer(new_itb_port); 4197781SAli.Saidi@ARM.com } 4207781SAli.Saidi@ARM.com if (new_dtb_port && !new_dtb_port->isConnected()) { 4217781SAli.Saidi@ARM.com assert(old_dtb_port); 4227781SAli.Saidi@ARM.com Port *peer = old_dtb_port->getPeer();; 4237781SAli.Saidi@ARM.com new_dtb_port->setPeer(peer); 4247781SAli.Saidi@ARM.com peer->setPeer(new_dtb_port); 4257781SAli.Saidi@ARM.com } 4268733Sgeoffrey.blake@arm.com 4278733Sgeoffrey.blake@arm.com#if USE_CHECKER 4288733Sgeoffrey.blake@arm.com Port *old_checker_itb_port, *old_checker_dtb_port; 4298733Sgeoffrey.blake@arm.com Port *new_checker_itb_port, *new_checker_dtb_port; 4308733Sgeoffrey.blake@arm.com 4318733Sgeoffrey.blake@arm.com CheckerCPU *oldChecker = 4328733Sgeoffrey.blake@arm.com dynamic_cast<CheckerCPU*>(oldTC->getCheckerCpuPtr()); 4338733Sgeoffrey.blake@arm.com CheckerCPU *newChecker = 4348733Sgeoffrey.blake@arm.com dynamic_cast<CheckerCPU*>(newTC->getCheckerCpuPtr()); 4358733Sgeoffrey.blake@arm.com old_checker_itb_port = oldChecker->getITBPtr()->getPort(); 4368733Sgeoffrey.blake@arm.com old_checker_dtb_port = oldChecker->getDTBPtr()->getPort(); 4378733Sgeoffrey.blake@arm.com new_checker_itb_port = newChecker->getITBPtr()->getPort(); 4388733Sgeoffrey.blake@arm.com new_checker_dtb_port = newChecker->getDTBPtr()->getPort(); 4398733Sgeoffrey.blake@arm.com 4408733Sgeoffrey.blake@arm.com // Move over any table walker ports if they exist for checker 4418733Sgeoffrey.blake@arm.com if (new_checker_itb_port && !new_checker_itb_port->isConnected()) { 4428733Sgeoffrey.blake@arm.com assert(old_checker_itb_port); 4438733Sgeoffrey.blake@arm.com Port *peer = old_checker_itb_port->getPeer();; 4448733Sgeoffrey.blake@arm.com new_checker_itb_port->setPeer(peer); 4458733Sgeoffrey.blake@arm.com peer->setPeer(new_checker_itb_port); 4468733Sgeoffrey.blake@arm.com } 4478733Sgeoffrey.blake@arm.com if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) { 4488733Sgeoffrey.blake@arm.com assert(old_checker_dtb_port); 4498733Sgeoffrey.blake@arm.com Port *peer = old_checker_dtb_port->getPeer();; 4508733Sgeoffrey.blake@arm.com new_checker_dtb_port->setPeer(peer); 4518733Sgeoffrey.blake@arm.com peer->setPeer(new_checker_dtb_port); 4528733Sgeoffrey.blake@arm.com } 4538733Sgeoffrey.blake@arm.com#endif 4548733Sgeoffrey.blake@arm.com 455180SN/A } 456605SN/A 4573520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 4585810Sgblack@eecs.umich.edu interrupts->setCPU(this); 4592254SN/A 4608779Sgblack@eecs.umich.edu if (FullSystem) { 4618779Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; ++i) 4628779Sgblack@eecs.umich.edu threadContexts[i]->profileClear(); 4632254SN/A 4648779Sgblack@eecs.umich.edu if (profileEvent) 4658779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 4668779Sgblack@eecs.umich.edu } 4674192Sktlim@umich.edu 4684192Sktlim@umich.edu // Connect new CPU to old CPU's memory only if new CPU isn't 4694192Sktlim@umich.edu // connected to anything. Also connect old CPU's memory to new 4704192Sktlim@umich.edu // CPU. 4718850Sandreas.hansson@arm.com if (!ic.isConnected()) { 4728850Sandreas.hansson@arm.com Port *peer = oldCPU->getInstPort().getPeer(); 4738850Sandreas.hansson@arm.com ic.setPeer(peer); 4748850Sandreas.hansson@arm.com peer->setPeer(&ic); 4754192Sktlim@umich.edu } 4764192Sktlim@umich.edu 4778850Sandreas.hansson@arm.com if (!dc.isConnected()) { 4788850Sandreas.hansson@arm.com Port *peer = oldCPU->getDataPort().getPeer(); 4798850Sandreas.hansson@arm.com dc.setPeer(peer); 4808850Sandreas.hansson@arm.com peer->setPeer(&dc); 4814192Sktlim@umich.edu } 482180SN/A} 483180SN/A 484180SN/A 4855536Srstrong@hp.comBaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) 4865606Snate@binkert.org : cpu(_cpu), interval(_interval) 4871917SN/A{ } 4881917SN/A 4891917SN/Avoid 4901917SN/ABaseCPU::ProfileEvent::process() 4911917SN/A{ 4926221Snate@binkert.org ThreadID size = cpu->threadContexts.size(); 4936221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 4942680Sktlim@umich.edu ThreadContext *tc = cpu->threadContexts[i]; 4952680Sktlim@umich.edu tc->profileSample(); 4961917SN/A } 4972254SN/A 4987823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + interval); 4991917SN/A} 5001917SN/A 5012SN/Avoid 502921SN/ABaseCPU::serialize(std::ostream &os) 503921SN/A{ 5044000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 5055647Sgblack@eecs.umich.edu interrupts->serialize(os); 506921SN/A} 507921SN/A 508921SN/Avoid 509921SN/ABaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 510921SN/A{ 5114000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 5125647Sgblack@eecs.umich.edu interrupts->unserialize(cp, section); 513921SN/A} 514921SN/A 5151191SN/Avoid 5161191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 5171191SN/A{ 5181191SN/A if (!debugSymbolTable) 5191191SN/A return; 5201191SN/A 5211191SN/A // if pc enters different function, print new function symbol and 5221191SN/A // update saved range. Otherwise do nothing. 5231191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 5241191SN/A string sym_str; 5251191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 5261191SN/A currentFunctionStart, 5271191SN/A currentFunctionEnd); 5281191SN/A 5291191SN/A if (!found) { 5301191SN/A // no symbol found: use addr as label 5311191SN/A sym_str = csprintf("0x%x", pc); 5321191SN/A currentFunctionStart = pc; 5331191SN/A currentFunctionEnd = pc + 1; 5341191SN/A } 5351191SN/A 5361191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 5377823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 5387823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 5391191SN/A } 5401191SN/A} 5418707Sandreas.hansson@arm.com 5428707Sandreas.hansson@arm.combool 5438707Sandreas.hansson@arm.comBaseCPU::CpuPort::recvTiming(PacketPtr pkt) 5448707Sandreas.hansson@arm.com{ 5458707Sandreas.hansson@arm.com panic("BaseCPU doesn't expect recvTiming callback!"); 5468707Sandreas.hansson@arm.com return true; 5478707Sandreas.hansson@arm.com} 5488707Sandreas.hansson@arm.com 5498707Sandreas.hansson@arm.comvoid 5508707Sandreas.hansson@arm.comBaseCPU::CpuPort::recvRetry() 5518707Sandreas.hansson@arm.com{ 5528707Sandreas.hansson@arm.com panic("BaseCPU doesn't expect recvRetry callback!"); 5538707Sandreas.hansson@arm.com} 5548707Sandreas.hansson@arm.com 5558707Sandreas.hansson@arm.comTick 5568707Sandreas.hansson@arm.comBaseCPU::CpuPort::recvAtomic(PacketPtr pkt) 5578707Sandreas.hansson@arm.com{ 5588707Sandreas.hansson@arm.com panic("BaseCPU doesn't expect recvAtomic callback!"); 5598707Sandreas.hansson@arm.com return curTick(); 5608707Sandreas.hansson@arm.com} 5618707Sandreas.hansson@arm.com 5628707Sandreas.hansson@arm.comvoid 5638707Sandreas.hansson@arm.comBaseCPU::CpuPort::recvFunctional(PacketPtr pkt) 5648707Sandreas.hansson@arm.com{ 5658707Sandreas.hansson@arm.com // No internal storage to update (in the general case). In the 5668707Sandreas.hansson@arm.com // long term this should never be called, but that assumed a split 5678707Sandreas.hansson@arm.com // into master/slave and request/response. 5688707Sandreas.hansson@arm.com} 5698707Sandreas.hansson@arm.com 5708707Sandreas.hansson@arm.comvoid 5718711Sandreas.hansson@arm.comBaseCPU::CpuPort::recvRangeChange() 5728707Sandreas.hansson@arm.com{ 5738707Sandreas.hansson@arm.com} 574