base.cc revision 7823
12SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 292665Ssaidi@eecs.umich.edu * Nathan Binkert 302SN/A */ 312SN/A 321388SN/A#include <iostream> 332SN/A#include <string> 342SN/A#include <sstream> 352SN/A 367781SAli.Saidi@ARM.com#include "arch/tlb.hh" 371191SN/A#include "base/cprintf.hh" 381191SN/A#include "base/loader/symtab.hh" 391191SN/A#include "base/misc.hh" 401388SN/A#include "base/output.hh" 415529Snate@binkert.org#include "base/trace.hh" 421717SN/A#include "cpu/base.hh" 432651Ssaidi@eecs.umich.edu#include "cpu/cpuevent.hh" 442680Sktlim@umich.edu#include "cpu/thread_context.hh" 451977SN/A#include "cpu/profile.hh" 465529Snate@binkert.org#include "params/BaseCPU.hh" 473144Shsul@eecs.umich.edu#include "sim/sim_exit.hh" 482190SN/A#include "sim/process.hh" 4956SN/A#include "sim/sim_events.hh" 502190SN/A#include "sim/system.hh" 512SN/A 522359SN/A// Hack 532359SN/A#include "sim/stat_control.hh" 542359SN/A 552SN/Ausing namespace std; 562SN/A 572SN/Avector<BaseCPU *> BaseCPU::cpuList; 582SN/A 592SN/A// This variable reflects the max number of threads in any CPU. Be 602SN/A// careful to only use it once all the CPUs that you care about have 612SN/A// been initialized 622SN/Aint maxThreadsPerCPU = 1; 632SN/A 645606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 656144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 666144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 673126Sktlim@umich.edu{ 686144Sksewell@umich.edu if (_interval) 697823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 703126Sktlim@umich.edu} 713126Sktlim@umich.edu 722356SN/Avoid 732356SN/ACPUProgressEvent::process() 742356SN/A{ 752367SN/A Counter temp = cpu->totalInstructions(); 762356SN/A#ifndef NDEBUG 776144Sksewell@umich.edu double ipc = double(temp - lastNumInst) / (_interval / cpu->ticks(1)); 782367SN/A 796144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 806144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 816144Sksewell@umich.edu ipc); 822356SN/A ipc = 0.0; 832367SN/A#else 846144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 857823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 866144Sksewell@umich.edu temp - lastNumInst); 872367SN/A#endif 882356SN/A lastNumInst = temp; 896144Sksewell@umich.edu 906144Sksewell@umich.edu if (_repeatEvent) 917823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 922356SN/A} 932356SN/A 942356SN/Aconst char * 955336Shines@cs.fsu.eduCPUProgressEvent::description() const 962356SN/A{ 974873Sstever@eecs.umich.edu return "CPU Progress"; 982356SN/A} 992356SN/A 1001858SN/A#if FULL_SYSTEM 1011400SN/ABaseCPU::BaseCPU(Params *p) 1025712Shsul@eecs.umich.edu : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), 1035712Shsul@eecs.umich.edu interrupts(p->interrupts), 1046221Snate@binkert.org numThreads(p->numThreads), system(p->system), 1053661Srdreslin@umich.edu phase(p->phase) 1062SN/A#else 1071400SN/ABaseCPU::BaseCPU(Params *p) 1085712Shsul@eecs.umich.edu : MemObject(p), clock(p->clock), _cpuId(p->cpu_id), 1096221Snate@binkert.org numThreads(p->numThreads), system(p->system), 1103661Srdreslin@umich.edu phase(p->phase) 1112SN/A#endif 1122SN/A{ 1137823Ssteve.reinhardt@amd.com// currentTick = curTick(); 1141062SN/A 1155712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1165712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1175712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1185712Shsul@eecs.umich.edu } 1195712Shsul@eecs.umich.edu 1202SN/A // add self to global list of CPUs 1212SN/A cpuList.push_back(this); 1222SN/A 1235712Shsul@eecs.umich.edu DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); 1245712Shsul@eecs.umich.edu 1256221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1266221Snate@binkert.org maxThreadsPerCPU = numThreads; 1272SN/A 1282SN/A // allocate per-thread instruction-based event queues 1296221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1306221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1316221Snate@binkert.org comInstEventQueue[tid] = 1326221Snate@binkert.org new EventQueue("instruction-based event queue"); 1332SN/A 1342SN/A // 1352SN/A // set up instruction-count-based termination events, if any 1362SN/A // 1375606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1385606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1396221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1405606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1416221Snate@binkert.org comInstEventQueue[tid]->schedule(event, p->max_insts_any_thread); 1425606Snate@binkert.org } 1435606Snate@binkert.org } 1442SN/A 1451400SN/A if (p->max_insts_all_threads != 0) { 1465606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1475606Snate@binkert.org 1482SN/A // allocate & initialize shared downcounter: each event will 1492SN/A // decrement this when triggered; simulation will terminate 1502SN/A // when counter reaches 0 1512SN/A int *counter = new int; 1526221Snate@binkert.org *counter = numThreads; 1536221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1545606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1556670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1565606Snate@binkert.org } 1572SN/A } 1582SN/A 159124SN/A // allocate per-thread load-based event queues 1606221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 1616221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1626221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 163124SN/A 164124SN/A // 165124SN/A // set up instruction-count-based termination events, if any 166124SN/A // 1675606Snate@binkert.org if (p->max_loads_any_thread != 0) { 1685606Snate@binkert.org const char *cause = "a thread reached the max load count"; 1696221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1705606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1716221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_any_thread); 1725606Snate@binkert.org } 1735606Snate@binkert.org } 174124SN/A 1751400SN/A if (p->max_loads_all_threads != 0) { 1765606Snate@binkert.org const char *cause = "all threads reached the max load count"; 177124SN/A // allocate & initialize shared downcounter: each event will 178124SN/A // decrement this when triggered; simulation will terminate 179124SN/A // when counter reaches 0 180124SN/A int *counter = new int; 1816221Snate@binkert.org *counter = numThreads; 1826221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1835606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1846221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 1855606Snate@binkert.org } 186124SN/A } 187124SN/A 1881191SN/A functionTracingEnabled = false; 1895529Snate@binkert.org if (p->function_trace) { 1901388SN/A functionTraceStream = simout.find(csprintf("ftrace.%s", name())); 1911191SN/A currentFunctionStart = currentFunctionEnd = 0; 1925529Snate@binkert.org functionEntryTick = p->function_trace_start; 1931191SN/A 1945529Snate@binkert.org if (p->function_trace_start == 0) { 1951191SN/A functionTracingEnabled = true; 1961191SN/A } else { 1975606Snate@binkert.org typedef EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace> wrap; 1985606Snate@binkert.org Event *event = new wrap(this, true); 1995606Snate@binkert.org schedule(event, p->function_trace_start); 2001191SN/A } 2011191SN/A } 2021917SN/A#if FULL_SYSTEM 2035810Sgblack@eecs.umich.edu interrupts->setCPU(this); 2045810Sgblack@eecs.umich.edu 2051917SN/A profileEvent = NULL; 2065529Snate@binkert.org if (params()->profile) 2075529Snate@binkert.org profileEvent = new ProfileEvent(this, params()->profile); 2081917SN/A#endif 2095529Snate@binkert.org tracer = params()->tracer; 2101917SN/A} 2111191SN/A 2121191SN/Avoid 2131191SN/ABaseCPU::enableFunctionTrace() 2141191SN/A{ 2151191SN/A functionTracingEnabled = true; 2161191SN/A} 2171191SN/A 2181191SN/ABaseCPU::~BaseCPU() 2191191SN/A{ 2201191SN/A} 2211191SN/A 2221129SN/Avoid 2231129SN/ABaseCPU::init() 2241129SN/A{ 2255529Snate@binkert.org if (!params()->defer_registration) 2262680Sktlim@umich.edu registerThreadContexts(); 2271129SN/A} 228180SN/A 2292SN/Avoid 2301917SN/ABaseCPU::startup() 2311917SN/A{ 2321917SN/A#if FULL_SYSTEM 2335529Snate@binkert.org if (!params()->defer_registration && profileEvent) 2347823Ssteve.reinhardt@amd.com schedule(profileEvent, curTick()); 2351917SN/A#endif 2362356SN/A 2375529Snate@binkert.org if (params()->progress_interval) { 2385606Snate@binkert.org Tick num_ticks = ticks(params()->progress_interval); 2396144Sksewell@umich.edu 2406144Sksewell@umich.edu Event *event; 2416144Sksewell@umich.edu event = new CPUProgressEvent(this, num_ticks); 2422356SN/A } 2431917SN/A} 2441917SN/A 2451917SN/A 2461917SN/Avoid 2472SN/ABaseCPU::regStats() 2482SN/A{ 249729SN/A using namespace Stats; 250707SN/A 251707SN/A numCycles 252707SN/A .name(name() + ".numCycles") 253707SN/A .desc("number of cpu cycles simulated") 254707SN/A ; 255707SN/A 2562680Sktlim@umich.edu int size = threadContexts.size(); 2572SN/A if (size > 1) { 2582SN/A for (int i = 0; i < size; ++i) { 2592SN/A stringstream namestr; 2602SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 2612680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 2622SN/A } 2632SN/A } else if (size == 1) 2642680Sktlim@umich.edu threadContexts[0]->regStats(name()); 2652190SN/A 2662190SN/A#if FULL_SYSTEM 2672190SN/A#endif 2682SN/A} 2692SN/A 2703495Sktlim@umich.eduTick 2713495Sktlim@umich.eduBaseCPU::nextCycle() 2723495Sktlim@umich.edu{ 2737823Ssteve.reinhardt@amd.com Tick next_tick = curTick() - phase + clock - 1; 2743495Sktlim@umich.edu next_tick -= (next_tick % clock); 2753661Srdreslin@umich.edu next_tick += phase; 2763495Sktlim@umich.edu return next_tick; 2773495Sktlim@umich.edu} 2783495Sktlim@umich.edu 2793495Sktlim@umich.eduTick 2803495Sktlim@umich.eduBaseCPU::nextCycle(Tick begin_tick) 2813495Sktlim@umich.edu{ 2823495Sktlim@umich.edu Tick next_tick = begin_tick; 2834599Sacolyte@umich.edu if (next_tick % clock != 0) 2844599Sacolyte@umich.edu next_tick = next_tick - (next_tick % clock) + clock; 2853661Srdreslin@umich.edu next_tick += phase; 2863495Sktlim@umich.edu 2877823Ssteve.reinhardt@amd.com assert(next_tick >= curTick()); 2883495Sktlim@umich.edu return next_tick; 2893495Sktlim@umich.edu} 290180SN/A 291180SN/Avoid 2922680Sktlim@umich.eduBaseCPU::registerThreadContexts() 293180SN/A{ 2946221Snate@binkert.org ThreadID size = threadContexts.size(); 2956221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 2966221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 2972378SN/A 2985718Shsul@eecs.umich.edu /** This is so that contextId and cpuId match where there is a 2995718Shsul@eecs.umich.edu * 1cpu:1context relationship. Otherwise, the order of registration 3005718Shsul@eecs.umich.edu * could affect the assignment and cpu 1 could have context id 3, for 3015718Shsul@eecs.umich.edu * example. We may even want to do something like this for SMT so that 3025718Shsul@eecs.umich.edu * cpu 0 has the lowest thread contexts and cpu N has the highest, but 3035718Shsul@eecs.umich.edu * I'll just do this for now 3045718Shsul@eecs.umich.edu */ 3056221Snate@binkert.org if (numThreads == 1) 3065718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 3075718Shsul@eecs.umich.edu else 3085718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc)); 3095713Shsul@eecs.umich.edu#if !FULL_SYSTEM 3105714Shsul@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 311180SN/A#endif 312180SN/A } 313180SN/A} 314180SN/A 315180SN/A 3164000Ssaidi@eecs.umich.eduint 3174000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 3184000Ssaidi@eecs.umich.edu{ 3196221Snate@binkert.org ThreadID size = threadContexts.size(); 3206221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3216221Snate@binkert.org if (tc == threadContexts[tid]) 3226221Snate@binkert.org return tid; 3234000Ssaidi@eecs.umich.edu } 3244000Ssaidi@eecs.umich.edu return 0; 3254000Ssaidi@eecs.umich.edu} 3264000Ssaidi@eecs.umich.edu 327180SN/Avoid 3282798Sktlim@umich.eduBaseCPU::switchOut() 329180SN/A{ 3302359SN/A// panic("This CPU doesn't support sampling!"); 3312359SN/A#if FULL_SYSTEM 3322359SN/A if (profileEvent && profileEvent->scheduled()) 3335606Snate@binkert.org deschedule(profileEvent); 3342359SN/A#endif 335180SN/A} 336180SN/A 337180SN/Avoid 3384192Sktlim@umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) 339180SN/A{ 3402680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 341180SN/A 3425712Shsul@eecs.umich.edu _cpuId = oldCPU->cpuId(); 3435712Shsul@eecs.umich.edu 3446221Snate@binkert.org ThreadID size = threadContexts.size(); 3456221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 3462680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 3472680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 348180SN/A 3492680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 3502651Ssaidi@eecs.umich.edu 3512680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 3522651Ssaidi@eecs.umich.edu 3535714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 3545715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 3555714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 3562359SN/A 3575875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 3585875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 3595875Ssteve.reinhardt@amd.com * point. 3605875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 3615217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 3625875Ssteve.reinhardt@amd.com */ 3637781SAli.Saidi@ARM.com 3647781SAli.Saidi@ARM.com Port *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port; 3657781SAli.Saidi@ARM.com old_itb_port = oldTC->getITBPtr()->getPort(); 3667781SAli.Saidi@ARM.com old_dtb_port = oldTC->getDTBPtr()->getPort(); 3677781SAli.Saidi@ARM.com new_itb_port = newTC->getITBPtr()->getPort(); 3687781SAli.Saidi@ARM.com new_dtb_port = newTC->getDTBPtr()->getPort(); 3697781SAli.Saidi@ARM.com 3707781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 3717781SAli.Saidi@ARM.com if (new_itb_port && !new_itb_port->isConnected()) { 3727781SAli.Saidi@ARM.com assert(old_itb_port); 3737781SAli.Saidi@ARM.com Port *peer = old_itb_port->getPeer();; 3747781SAli.Saidi@ARM.com new_itb_port->setPeer(peer); 3757781SAli.Saidi@ARM.com peer->setPeer(new_itb_port); 3767781SAli.Saidi@ARM.com } 3777781SAli.Saidi@ARM.com if (new_dtb_port && !new_dtb_port->isConnected()) { 3787781SAli.Saidi@ARM.com assert(old_dtb_port); 3797781SAli.Saidi@ARM.com Port *peer = old_dtb_port->getPeer();; 3807781SAli.Saidi@ARM.com new_dtb_port->setPeer(peer); 3817781SAli.Saidi@ARM.com peer->setPeer(new_dtb_port); 3827781SAli.Saidi@ARM.com } 383180SN/A } 384605SN/A 3851858SN/A#if FULL_SYSTEM 3863520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 3875810Sgblack@eecs.umich.edu interrupts->setCPU(this); 3882254SN/A 3896221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) 3902680Sktlim@umich.edu threadContexts[i]->profileClear(); 3912254SN/A 3924947Snate@binkert.org if (profileEvent) 3937823Ssteve.reinhardt@amd.com schedule(profileEvent, curTick()); 394612SN/A#endif 3954192Sktlim@umich.edu 3964192Sktlim@umich.edu // Connect new CPU to old CPU's memory only if new CPU isn't 3974192Sktlim@umich.edu // connected to anything. Also connect old CPU's memory to new 3984192Sktlim@umich.edu // CPU. 3995476Snate@binkert.org if (!ic->isConnected()) { 4005476Snate@binkert.org Port *peer = oldCPU->getPort("icache_port")->getPeer(); 4014192Sktlim@umich.edu ic->setPeer(peer); 4025476Snate@binkert.org peer->setPeer(ic); 4034192Sktlim@umich.edu } 4044192Sktlim@umich.edu 4055476Snate@binkert.org if (!dc->isConnected()) { 4065476Snate@binkert.org Port *peer = oldCPU->getPort("dcache_port")->getPeer(); 4074192Sktlim@umich.edu dc->setPeer(peer); 4085476Snate@binkert.org peer->setPeer(dc); 4094192Sktlim@umich.edu } 410180SN/A} 411180SN/A 412180SN/A 4131858SN/A#if FULL_SYSTEM 4145536Srstrong@hp.comBaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) 4155606Snate@binkert.org : cpu(_cpu), interval(_interval) 4161917SN/A{ } 4171917SN/A 4181917SN/Avoid 4191917SN/ABaseCPU::ProfileEvent::process() 4201917SN/A{ 4216221Snate@binkert.org ThreadID size = cpu->threadContexts.size(); 4226221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 4232680Sktlim@umich.edu ThreadContext *tc = cpu->threadContexts[i]; 4242680Sktlim@umich.edu tc->profileSample(); 4251917SN/A } 4262254SN/A 4277823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + interval); 4281917SN/A} 4291917SN/A 4302SN/Avoid 431921SN/ABaseCPU::serialize(std::ostream &os) 432921SN/A{ 4334000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 4345647Sgblack@eecs.umich.edu interrupts->serialize(os); 435921SN/A} 436921SN/A 437921SN/Avoid 438921SN/ABaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 439921SN/A{ 4404000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 4415647Sgblack@eecs.umich.edu interrupts->unserialize(cp, section); 442921SN/A} 443921SN/A 4442SN/A#endif // FULL_SYSTEM 4452SN/A 4461191SN/Avoid 4471191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 4481191SN/A{ 4491191SN/A if (!debugSymbolTable) 4501191SN/A return; 4511191SN/A 4521191SN/A // if pc enters different function, print new function symbol and 4531191SN/A // update saved range. Otherwise do nothing. 4541191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 4551191SN/A string sym_str; 4561191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 4571191SN/A currentFunctionStart, 4581191SN/A currentFunctionEnd); 4591191SN/A 4601191SN/A if (!found) { 4611191SN/A // no symbol found: use addr as label 4621191SN/A sym_str = csprintf("0x%x", pc); 4631191SN/A currentFunctionStart = pc; 4641191SN/A currentFunctionEnd = pc + 1; 4651191SN/A } 4661191SN/A 4671191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 4687823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 4697823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 4701191SN/A } 4711191SN/A} 472