base.cc revision 8634
12SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 37897Shestness@cs.utexas.edu * Copyright (c) 2011 Regents of the University of California 42SN/A * All rights reserved. 52SN/A * 62SN/A * Redistribution and use in source and binary forms, with or without 72SN/A * modification, are permitted provided that the following conditions are 82SN/A * met: redistributions of source code must retain the above copyright 92SN/A * notice, this list of conditions and the following disclaimer; 102SN/A * redistributions in binary form must reproduce the above copyright 112SN/A * notice, this list of conditions and the following disclaimer in the 122SN/A * documentation and/or other materials provided with the distribution; 132SN/A * neither the name of the copyright holders nor the names of its 142SN/A * contributors may be used to endorse or promote products derived from 152SN/A * this software without specific prior written permission. 162SN/A * 172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 302665Ssaidi@eecs.umich.edu * Nathan Binkert 317897Shestness@cs.utexas.edu * Rick Strong 322SN/A */ 332SN/A 341388SN/A#include <iostream> 358229Snate@binkert.org#include <sstream> 362SN/A#include <string> 372SN/A 387781SAli.Saidi@ARM.com#include "arch/tlb.hh" 398229Snate@binkert.org#include "base/loader/symtab.hh" 401191SN/A#include "base/cprintf.hh" 411191SN/A#include "base/misc.hh" 421388SN/A#include "base/output.hh" 435529Snate@binkert.org#include "base/trace.hh" 441717SN/A#include "cpu/base.hh" 452651Ssaidi@eecs.umich.edu#include "cpu/cpuevent.hh" 468229Snate@binkert.org#include "cpu/profile.hh" 472680Sktlim@umich.edu#include "cpu/thread_context.hh" 488232Snate@binkert.org#include "debug/SyscallVerbose.hh" 495529Snate@binkert.org#include "params/BaseCPU.hh" 502190SN/A#include "sim/process.hh" 5156SN/A#include "sim/sim_events.hh" 528229Snate@binkert.org#include "sim/sim_exit.hh" 532190SN/A#include "sim/system.hh" 542SN/A 552359SN/A// Hack 562359SN/A#include "sim/stat_control.hh" 572359SN/A 582SN/Ausing namespace std; 592SN/A 602SN/Avector<BaseCPU *> BaseCPU::cpuList; 612SN/A 622SN/A// This variable reflects the max number of threads in any CPU. Be 632SN/A// careful to only use it once all the CPUs that you care about have 642SN/A// been initialized 652SN/Aint maxThreadsPerCPU = 1; 662SN/A 675606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 686144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 696144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 703126Sktlim@umich.edu{ 716144Sksewell@umich.edu if (_interval) 727823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 733126Sktlim@umich.edu} 743126Sktlim@umich.edu 752356SN/Avoid 762356SN/ACPUProgressEvent::process() 772356SN/A{ 782367SN/A Counter temp = cpu->totalInstructions(); 792356SN/A#ifndef NDEBUG 806144Sksewell@umich.edu double ipc = double(temp - lastNumInst) / (_interval / cpu->ticks(1)); 812367SN/A 826144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 836144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 846144Sksewell@umich.edu ipc); 852356SN/A ipc = 0.0; 862367SN/A#else 876144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 887823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 896144Sksewell@umich.edu temp - lastNumInst); 902367SN/A#endif 912356SN/A lastNumInst = temp; 926144Sksewell@umich.edu 936144Sksewell@umich.edu if (_repeatEvent) 947823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 952356SN/A} 962356SN/A 972356SN/Aconst char * 985336Shines@cs.fsu.eduCPUProgressEvent::description() const 992356SN/A{ 1004873Sstever@eecs.umich.edu return "CPU Progress"; 1012356SN/A} 1022356SN/A 1031858SN/A#if FULL_SYSTEM 1041400SN/ABaseCPU::BaseCPU(Params *p) 1055712Shsul@eecs.umich.edu : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), 1065712Shsul@eecs.umich.edu interrupts(p->interrupts), 1076221Snate@binkert.org numThreads(p->numThreads), system(p->system), 1083661Srdreslin@umich.edu phase(p->phase) 1092SN/A#else 1101400SN/ABaseCPU::BaseCPU(Params *p) 1115712Shsul@eecs.umich.edu : MemObject(p), clock(p->clock), _cpuId(p->cpu_id), 1126221Snate@binkert.org numThreads(p->numThreads), system(p->system), 1133661Srdreslin@umich.edu phase(p->phase) 1142SN/A#endif 1152SN/A{ 1167823Ssteve.reinhardt@amd.com// currentTick = curTick(); 1171062SN/A 1185712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1195712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1205712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1215712Shsul@eecs.umich.edu } 1225712Shsul@eecs.umich.edu 1232SN/A // add self to global list of CPUs 1242SN/A cpuList.push_back(this); 1252SN/A 1265712Shsul@eecs.umich.edu DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); 1275712Shsul@eecs.umich.edu 1286221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1296221Snate@binkert.org maxThreadsPerCPU = numThreads; 1302SN/A 1312SN/A // allocate per-thread instruction-based event queues 1326221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1336221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1346221Snate@binkert.org comInstEventQueue[tid] = 1356221Snate@binkert.org new EventQueue("instruction-based event queue"); 1362SN/A 1372SN/A // 1382SN/A // set up instruction-count-based termination events, if any 1392SN/A // 1405606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1415606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1426221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1435606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1446221Snate@binkert.org comInstEventQueue[tid]->schedule(event, p->max_insts_any_thread); 1455606Snate@binkert.org } 1465606Snate@binkert.org } 1472SN/A 1481400SN/A if (p->max_insts_all_threads != 0) { 1495606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1505606Snate@binkert.org 1512SN/A // allocate & initialize shared downcounter: each event will 1522SN/A // decrement this when triggered; simulation will terminate 1532SN/A // when counter reaches 0 1542SN/A int *counter = new int; 1556221Snate@binkert.org *counter = numThreads; 1566221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1575606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1586670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1595606Snate@binkert.org } 1602SN/A } 1612SN/A 162124SN/A // allocate per-thread load-based event queues 1636221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 1646221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1656221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 166124SN/A 167124SN/A // 168124SN/A // set up instruction-count-based termination events, if any 169124SN/A // 1705606Snate@binkert.org if (p->max_loads_any_thread != 0) { 1715606Snate@binkert.org const char *cause = "a thread reached the max load count"; 1726221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1735606Snate@binkert.org Event *event = new SimLoopExitEvent(cause, 0); 1746221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_any_thread); 1755606Snate@binkert.org } 1765606Snate@binkert.org } 177124SN/A 1781400SN/A if (p->max_loads_all_threads != 0) { 1795606Snate@binkert.org const char *cause = "all threads reached the max load count"; 180124SN/A // allocate & initialize shared downcounter: each event will 181124SN/A // decrement this when triggered; simulation will terminate 182124SN/A // when counter reaches 0 183124SN/A int *counter = new int; 1846221Snate@binkert.org *counter = numThreads; 1856221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1865606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1876221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 1885606Snate@binkert.org } 189124SN/A } 190124SN/A 1911191SN/A functionTracingEnabled = false; 1925529Snate@binkert.org if (p->function_trace) { 1938634Schris.emmons@arm.com const string fname = csprintf("ftrace.%s", name()); 1948634Schris.emmons@arm.com functionTraceStream = simout.find(fname); 1958634Schris.emmons@arm.com if (!functionTraceStream) 1968634Schris.emmons@arm.com functionTraceStream = simout.create(fname); 1978634Schris.emmons@arm.com 1981191SN/A currentFunctionStart = currentFunctionEnd = 0; 1995529Snate@binkert.org functionEntryTick = p->function_trace_start; 2001191SN/A 2015529Snate@binkert.org if (p->function_trace_start == 0) { 2021191SN/A functionTracingEnabled = true; 2031191SN/A } else { 2045606Snate@binkert.org typedef EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace> wrap; 2055606Snate@binkert.org Event *event = new wrap(this, true); 2065606Snate@binkert.org schedule(event, p->function_trace_start); 2071191SN/A } 2081191SN/A } 2091917SN/A#if FULL_SYSTEM 2105810Sgblack@eecs.umich.edu interrupts->setCPU(this); 2115810Sgblack@eecs.umich.edu 2121917SN/A profileEvent = NULL; 2135529Snate@binkert.org if (params()->profile) 2145529Snate@binkert.org profileEvent = new ProfileEvent(this, params()->profile); 2151917SN/A#endif 2165529Snate@binkert.org tracer = params()->tracer; 2171917SN/A} 2181191SN/A 2191191SN/Avoid 2201191SN/ABaseCPU::enableFunctionTrace() 2211191SN/A{ 2221191SN/A functionTracingEnabled = true; 2231191SN/A} 2241191SN/A 2251191SN/ABaseCPU::~BaseCPU() 2261191SN/A{ 2271191SN/A} 2281191SN/A 2291129SN/Avoid 2301129SN/ABaseCPU::init() 2311129SN/A{ 2325529Snate@binkert.org if (!params()->defer_registration) 2332680Sktlim@umich.edu registerThreadContexts(); 2341129SN/A} 235180SN/A 2362SN/Avoid 2371917SN/ABaseCPU::startup() 2381917SN/A{ 2391917SN/A#if FULL_SYSTEM 2405529Snate@binkert.org if (!params()->defer_registration && profileEvent) 2417823Ssteve.reinhardt@amd.com schedule(profileEvent, curTick()); 2421917SN/A#endif 2432356SN/A 2445529Snate@binkert.org if (params()->progress_interval) { 2455606Snate@binkert.org Tick num_ticks = ticks(params()->progress_interval); 2466144Sksewell@umich.edu 2478607Sgblack@eecs.umich.edu new CPUProgressEvent(this, num_ticks); 2482356SN/A } 2491917SN/A} 2501917SN/A 2511917SN/A 2521917SN/Avoid 2532SN/ABaseCPU::regStats() 2542SN/A{ 255729SN/A using namespace Stats; 256707SN/A 257707SN/A numCycles 258707SN/A .name(name() + ".numCycles") 259707SN/A .desc("number of cpu cycles simulated") 260707SN/A ; 261707SN/A 2627914SBrad.Beckmann@amd.com numWorkItemsStarted 2637914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsStarted") 2647914SBrad.Beckmann@amd.com .desc("number of work items this cpu started") 2657914SBrad.Beckmann@amd.com ; 2667914SBrad.Beckmann@amd.com 2677914SBrad.Beckmann@amd.com numWorkItemsCompleted 2687914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsCompleted") 2697914SBrad.Beckmann@amd.com .desc("number of work items this cpu completed") 2707914SBrad.Beckmann@amd.com ; 2717914SBrad.Beckmann@amd.com 2722680Sktlim@umich.edu int size = threadContexts.size(); 2732SN/A if (size > 1) { 2742SN/A for (int i = 0; i < size; ++i) { 2752SN/A stringstream namestr; 2762SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 2772680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 2782SN/A } 2792SN/A } else if (size == 1) 2802680Sktlim@umich.edu threadContexts[0]->regStats(name()); 2812190SN/A 2822190SN/A#if FULL_SYSTEM 2832190SN/A#endif 2842SN/A} 2852SN/A 2863495Sktlim@umich.eduTick 2873495Sktlim@umich.eduBaseCPU::nextCycle() 2883495Sktlim@umich.edu{ 2897823Ssteve.reinhardt@amd.com Tick next_tick = curTick() - phase + clock - 1; 2903495Sktlim@umich.edu next_tick -= (next_tick % clock); 2913661Srdreslin@umich.edu next_tick += phase; 2923495Sktlim@umich.edu return next_tick; 2933495Sktlim@umich.edu} 2943495Sktlim@umich.edu 2953495Sktlim@umich.eduTick 2963495Sktlim@umich.eduBaseCPU::nextCycle(Tick begin_tick) 2973495Sktlim@umich.edu{ 2983495Sktlim@umich.edu Tick next_tick = begin_tick; 2994599Sacolyte@umich.edu if (next_tick % clock != 0) 3004599Sacolyte@umich.edu next_tick = next_tick - (next_tick % clock) + clock; 3013661Srdreslin@umich.edu next_tick += phase; 3023495Sktlim@umich.edu 3037823Ssteve.reinhardt@amd.com assert(next_tick >= curTick()); 3043495Sktlim@umich.edu return next_tick; 3053495Sktlim@umich.edu} 306180SN/A 307180SN/Avoid 3082680Sktlim@umich.eduBaseCPU::registerThreadContexts() 309180SN/A{ 3106221Snate@binkert.org ThreadID size = threadContexts.size(); 3116221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3126221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 3132378SN/A 3145718Shsul@eecs.umich.edu /** This is so that contextId and cpuId match where there is a 3155718Shsul@eecs.umich.edu * 1cpu:1context relationship. Otherwise, the order of registration 3165718Shsul@eecs.umich.edu * could affect the assignment and cpu 1 could have context id 3, for 3175718Shsul@eecs.umich.edu * example. We may even want to do something like this for SMT so that 3185718Shsul@eecs.umich.edu * cpu 0 has the lowest thread contexts and cpu N has the highest, but 3195718Shsul@eecs.umich.edu * I'll just do this for now 3205718Shsul@eecs.umich.edu */ 3216221Snate@binkert.org if (numThreads == 1) 3225718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 3235718Shsul@eecs.umich.edu else 3245718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc)); 3255713Shsul@eecs.umich.edu#if !FULL_SYSTEM 3265714Shsul@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 327180SN/A#endif 328180SN/A } 329180SN/A} 330180SN/A 331180SN/A 3324000Ssaidi@eecs.umich.eduint 3334000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 3344000Ssaidi@eecs.umich.edu{ 3356221Snate@binkert.org ThreadID size = threadContexts.size(); 3366221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 3376221Snate@binkert.org if (tc == threadContexts[tid]) 3386221Snate@binkert.org return tid; 3394000Ssaidi@eecs.umich.edu } 3404000Ssaidi@eecs.umich.edu return 0; 3414000Ssaidi@eecs.umich.edu} 3424000Ssaidi@eecs.umich.edu 343180SN/Avoid 3442798Sktlim@umich.eduBaseCPU::switchOut() 345180SN/A{ 3462359SN/A// panic("This CPU doesn't support sampling!"); 3472359SN/A#if FULL_SYSTEM 3482359SN/A if (profileEvent && profileEvent->scheduled()) 3495606Snate@binkert.org deschedule(profileEvent); 3502359SN/A#endif 351180SN/A} 352180SN/A 353180SN/Avoid 3544192Sktlim@umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) 355180SN/A{ 3562680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 357180SN/A 3585712Shsul@eecs.umich.edu _cpuId = oldCPU->cpuId(); 3595712Shsul@eecs.umich.edu 3606221Snate@binkert.org ThreadID size = threadContexts.size(); 3616221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 3622680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 3632680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 364180SN/A 3652680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 3662651Ssaidi@eecs.umich.edu 3672680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 3682651Ssaidi@eecs.umich.edu 3695714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 3705715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 3715714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 3722359SN/A 3735875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 3745875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 3755875Ssteve.reinhardt@amd.com * point. 3765875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 3775217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 3785875Ssteve.reinhardt@amd.com */ 3797781SAli.Saidi@ARM.com 3807781SAli.Saidi@ARM.com Port *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port; 3817781SAli.Saidi@ARM.com old_itb_port = oldTC->getITBPtr()->getPort(); 3827781SAli.Saidi@ARM.com old_dtb_port = oldTC->getDTBPtr()->getPort(); 3837781SAli.Saidi@ARM.com new_itb_port = newTC->getITBPtr()->getPort(); 3847781SAli.Saidi@ARM.com new_dtb_port = newTC->getDTBPtr()->getPort(); 3857781SAli.Saidi@ARM.com 3867781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 3877781SAli.Saidi@ARM.com if (new_itb_port && !new_itb_port->isConnected()) { 3887781SAli.Saidi@ARM.com assert(old_itb_port); 3897781SAli.Saidi@ARM.com Port *peer = old_itb_port->getPeer();; 3907781SAli.Saidi@ARM.com new_itb_port->setPeer(peer); 3917781SAli.Saidi@ARM.com peer->setPeer(new_itb_port); 3927781SAli.Saidi@ARM.com } 3937781SAli.Saidi@ARM.com if (new_dtb_port && !new_dtb_port->isConnected()) { 3947781SAli.Saidi@ARM.com assert(old_dtb_port); 3957781SAli.Saidi@ARM.com Port *peer = old_dtb_port->getPeer();; 3967781SAli.Saidi@ARM.com new_dtb_port->setPeer(peer); 3977781SAli.Saidi@ARM.com peer->setPeer(new_dtb_port); 3987781SAli.Saidi@ARM.com } 399180SN/A } 400605SN/A 4011858SN/A#if FULL_SYSTEM 4023520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 4035810Sgblack@eecs.umich.edu interrupts->setCPU(this); 4042254SN/A 4056221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) 4062680Sktlim@umich.edu threadContexts[i]->profileClear(); 4072254SN/A 4084947Snate@binkert.org if (profileEvent) 4097823Ssteve.reinhardt@amd.com schedule(profileEvent, curTick()); 410612SN/A#endif 4114192Sktlim@umich.edu 4124192Sktlim@umich.edu // Connect new CPU to old CPU's memory only if new CPU isn't 4134192Sktlim@umich.edu // connected to anything. Also connect old CPU's memory to new 4144192Sktlim@umich.edu // CPU. 4155476Snate@binkert.org if (!ic->isConnected()) { 4165476Snate@binkert.org Port *peer = oldCPU->getPort("icache_port")->getPeer(); 4174192Sktlim@umich.edu ic->setPeer(peer); 4185476Snate@binkert.org peer->setPeer(ic); 4194192Sktlim@umich.edu } 4204192Sktlim@umich.edu 4215476Snate@binkert.org if (!dc->isConnected()) { 4225476Snate@binkert.org Port *peer = oldCPU->getPort("dcache_port")->getPeer(); 4234192Sktlim@umich.edu dc->setPeer(peer); 4245476Snate@binkert.org peer->setPeer(dc); 4254192Sktlim@umich.edu } 426180SN/A} 427180SN/A 428180SN/A 4291858SN/A#if FULL_SYSTEM 4305536Srstrong@hp.comBaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) 4315606Snate@binkert.org : cpu(_cpu), interval(_interval) 4321917SN/A{ } 4331917SN/A 4341917SN/Avoid 4351917SN/ABaseCPU::ProfileEvent::process() 4361917SN/A{ 4376221Snate@binkert.org ThreadID size = cpu->threadContexts.size(); 4386221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 4392680Sktlim@umich.edu ThreadContext *tc = cpu->threadContexts[i]; 4402680Sktlim@umich.edu tc->profileSample(); 4411917SN/A } 4422254SN/A 4437823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + interval); 4441917SN/A} 4451917SN/A 4462SN/Avoid 447921SN/ABaseCPU::serialize(std::ostream &os) 448921SN/A{ 4494000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 4505647Sgblack@eecs.umich.edu interrupts->serialize(os); 451921SN/A} 452921SN/A 453921SN/Avoid 454921SN/ABaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 455921SN/A{ 4564000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 4575647Sgblack@eecs.umich.edu interrupts->unserialize(cp, section); 458921SN/A} 459921SN/A 4602SN/A#endif // FULL_SYSTEM 4612SN/A 4621191SN/Avoid 4631191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 4641191SN/A{ 4651191SN/A if (!debugSymbolTable) 4661191SN/A return; 4671191SN/A 4681191SN/A // if pc enters different function, print new function symbol and 4691191SN/A // update saved range. Otherwise do nothing. 4701191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 4711191SN/A string sym_str; 4721191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 4731191SN/A currentFunctionStart, 4741191SN/A currentFunctionEnd); 4751191SN/A 4761191SN/A if (!found) { 4771191SN/A // no symbol found: use addr as label 4781191SN/A sym_str = csprintf("0x%x", pc); 4791191SN/A currentFunctionStart = pc; 4801191SN/A currentFunctionEnd = pc + 1; 4811191SN/A } 4821191SN/A 4831191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 4847823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 4857823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 4861191SN/A } 4871191SN/A} 488