base.cc revision 14207
12SN/A/* 212276Sanouk.vanlaer@arm.com * Copyright (c) 2011-2012,2016-2017 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 169983Sstever@gmail.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 179983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 182SN/A * All rights reserved. 192SN/A * 202SN/A * Redistribution and use in source and binary forms, with or without 212SN/A * modification, are permitted provided that the following conditions are 222SN/A * met: redistributions of source code must retain the above copyright 232SN/A * notice, this list of conditions and the following disclaimer; 242SN/A * redistributions in binary form must reproduce the above copyright 252SN/A * notice, this list of conditions and the following disclaimer in the 262SN/A * documentation and/or other materials provided with the distribution; 272SN/A * neither the name of the copyright holders nor the names of its 282SN/A * contributors may be used to endorse or promote products derived from 292SN/A * this software without specific prior written permission. 302SN/A * 312SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 322SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 332SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 342SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 352SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 362SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 372SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 382SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 392SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 402SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 412SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 422665Ssaidi@eecs.umich.edu * 432665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 442665Ssaidi@eecs.umich.edu * Nathan Binkert 457897Shestness@cs.utexas.edu * Rick Strong 462SN/A */ 472SN/A 4811793Sbrandon.potter@amd.com#include "cpu/base.hh" 4911793Sbrandon.potter@amd.com 501388SN/A#include <iostream> 518229Snate@binkert.org#include <sstream> 522SN/A#include <string> 532SN/A 5412406Sgabeblack@google.com#include "arch/generic/tlb.hh" 5511793Sbrandon.potter@amd.com#include "base/cprintf.hh" 568229Snate@binkert.org#include "base/loader/symtab.hh" 5712334Sgabeblack@google.com#include "base/logging.hh" 581388SN/A#include "base/output.hh" 595529Snate@binkert.org#include "base/trace.hh" 6010529Smorr@cs.wisc.edu#include "cpu/checker/cpu.hh" 612651Ssaidi@eecs.umich.edu#include "cpu/cpuevent.hh" 628229Snate@binkert.org#include "cpu/profile.hh" 632680Sktlim@umich.edu#include "cpu/thread_context.hh" 6410529Smorr@cs.wisc.edu#include "debug/Mwait.hh" 658232Snate@binkert.org#include "debug/SyscallVerbose.hh" 6610529Smorr@cs.wisc.edu#include "mem/page_table.hh" 675529Snate@binkert.org#include "params/BaseCPU.hh" 6811526Sdavid.guillen@arm.com#include "sim/clocked_object.hh" 698779Sgblack@eecs.umich.edu#include "sim/full_system.hh" 702190SN/A#include "sim/process.hh" 7156SN/A#include "sim/sim_events.hh" 728229Snate@binkert.org#include "sim/sim_exit.hh" 732190SN/A#include "sim/system.hh" 742SN/A 752359SN/A// Hack 762359SN/A#include "sim/stat_control.hh" 772359SN/A 782SN/Ausing namespace std; 792SN/A 802SN/Avector<BaseCPU *> BaseCPU::cpuList; 812SN/A 822SN/A// This variable reflects the max number of threads in any CPU. Be 832SN/A// careful to only use it once all the CPUs that you care about have 842SN/A// been initialized 852SN/Aint maxThreadsPerCPU = 1; 862SN/A 875606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 886144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 896144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 903126Sktlim@umich.edu{ 916144Sksewell@umich.edu if (_interval) 927823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 933126Sktlim@umich.edu} 943126Sktlim@umich.edu 952356SN/Avoid 962356SN/ACPUProgressEvent::process() 972356SN/A{ 988834Satgutier@umich.edu Counter temp = cpu->totalOps(); 9910786Smalek.musleh@gmail.com 10010786Smalek.musleh@gmail.com if (_repeatEvent) 10110786Smalek.musleh@gmail.com cpu->schedule(this, curTick() + _interval); 10210786Smalek.musleh@gmail.com 10311321Ssteve.reinhardt@amd.com if (cpu->switchedOut()) { 10410786Smalek.musleh@gmail.com return; 10510786Smalek.musleh@gmail.com } 10610786Smalek.musleh@gmail.com 1072356SN/A#ifndef NDEBUG 1089179Sandreas.hansson@arm.com double ipc = double(temp - lastNumInst) / (_interval / cpu->clockPeriod()); 1092367SN/A 1106144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 1116144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 1126144Sksewell@umich.edu ipc); 1132356SN/A ipc = 0.0; 1142367SN/A#else 1156144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 1167823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 1176144Sksewell@umich.edu temp - lastNumInst); 1182367SN/A#endif 1192356SN/A lastNumInst = temp; 1202356SN/A} 1212356SN/A 1222356SN/Aconst char * 1235336Shines@cs.fsu.eduCPUProgressEvent::description() const 1242356SN/A{ 1254873Sstever@eecs.umich.edu return "CPU Progress"; 1262356SN/A} 1272356SN/A 1288876Sandreas.hansson@arm.comBaseCPU::BaseCPU(Params *p, bool is_checker) 12913892Sgabeblack@google.com : ClockedObject(p), instCnt(0), _cpuId(p->cpu_id), _socketId(p->socket_id), 13012680Sgiacomo.travaglini@arm.com _instMasterId(p->system->getMasterId(this, "inst")), 13112680Sgiacomo.travaglini@arm.com _dataMasterId(p->system->getMasterId(this, "data")), 13211050Sandreas.hansson@arm.com _taskId(ContextSwitchTaskId::Unknown), _pid(invldPid), 1339814Sandreas.hansson@arm.com _switchedOut(p->switched_out), _cacheLineSize(p->system->cacheLineSize()), 1349220Shestness@cs.wisc.edu interrupts(p->interrupts), profileEvent(NULL), 13510529Smorr@cs.wisc.edu numThreads(p->numThreads), system(p->system), 13612284Sjose.marinho@arm.com previousCycle(0), previousState(CPU_STATE_SLEEP), 13710537Sandreas.hansson@arm.com functionTraceStream(nullptr), currentFunctionStart(0), 13810537Sandreas.hansson@arm.com currentFunctionEnd(0), functionEntryTick(0), 13911877Sbrandon.potter@amd.com addressMonitor(p->numThreads), 14012276Sanouk.vanlaer@arm.com syscallRetryLatency(p->syscallRetryLatency), 14112276Sanouk.vanlaer@arm.com pwrGatingLatency(p->pwr_gating_latency), 14212277Sjose.marinho@arm.com powerGatingOnIdle(p->power_gating_on_idle), 14312276Sanouk.vanlaer@arm.com enterPwrGatingEvent([this]{ enterPwrGating(); }, name()) 1442SN/A{ 1455712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1465712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1475712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1485712Shsul@eecs.umich.edu } 1495712Shsul@eecs.umich.edu 1502SN/A // add self to global list of CPUs 1512SN/A cpuList.push_back(this); 1522SN/A 15310190Sakash.bagdia@arm.com DPRINTF(SyscallVerbose, "Constructing CPU with id %d, socket id %d\n", 15410190Sakash.bagdia@arm.com _cpuId, _socketId); 1555712Shsul@eecs.umich.edu 1566221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1576221Snate@binkert.org maxThreadsPerCPU = numThreads; 1582SN/A 1592SN/A // allocate per-thread instruction-based event queues 1606221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1616221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1626221Snate@binkert.org comInstEventQueue[tid] = 1636221Snate@binkert.org new EventQueue("instruction-based event queue"); 1642SN/A 1652SN/A // 1662SN/A // set up instruction-count-based termination events, if any 1672SN/A // 1685606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1695606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1709749Sandreas@sandberg.pp.se for (ThreadID tid = 0; tid < numThreads; ++tid) 1719749Sandreas@sandberg.pp.se scheduleInstStop(tid, p->max_insts_any_thread, cause); 1725606Snate@binkert.org } 1732SN/A 1749647Sdam.sunwoo@arm.com // Set up instruction-count-based termination events for SimPoints 1759647Sdam.sunwoo@arm.com // Typically, there are more than one action points. 1769647Sdam.sunwoo@arm.com // Simulation.py is responsible to take the necessary actions upon 1779647Sdam.sunwoo@arm.com // exitting the simulation loop. 1789647Sdam.sunwoo@arm.com if (!p->simpoint_start_insts.empty()) { 1799647Sdam.sunwoo@arm.com const char *cause = "simpoint starting point found"; 1809749Sandreas@sandberg.pp.se for (size_t i = 0; i < p->simpoint_start_insts.size(); ++i) 1819749Sandreas@sandberg.pp.se scheduleInstStop(0, p->simpoint_start_insts[i], cause); 1829647Sdam.sunwoo@arm.com } 1839647Sdam.sunwoo@arm.com 1841400SN/A if (p->max_insts_all_threads != 0) { 1855606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1865606Snate@binkert.org 1872SN/A // allocate & initialize shared downcounter: each event will 1882SN/A // decrement this when triggered; simulation will terminate 1892SN/A // when counter reaches 0 1902SN/A int *counter = new int; 1916221Snate@binkert.org *counter = numThreads; 1926221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1935606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1946670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1955606Snate@binkert.org } 1962SN/A } 1972SN/A 198124SN/A // allocate per-thread load-based event queues 1996221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 2006221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 2016221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 202124SN/A 203124SN/A // 204124SN/A // set up instruction-count-based termination events, if any 205124SN/A // 2065606Snate@binkert.org if (p->max_loads_any_thread != 0) { 2075606Snate@binkert.org const char *cause = "a thread reached the max load count"; 2089749Sandreas@sandberg.pp.se for (ThreadID tid = 0; tid < numThreads; ++tid) 2099749Sandreas@sandberg.pp.se scheduleLoadStop(tid, p->max_loads_any_thread, cause); 2105606Snate@binkert.org } 211124SN/A 2121400SN/A if (p->max_loads_all_threads != 0) { 2135606Snate@binkert.org const char *cause = "all threads reached the max load count"; 214124SN/A // allocate & initialize shared downcounter: each event will 215124SN/A // decrement this when triggered; simulation will terminate 216124SN/A // when counter reaches 0 217124SN/A int *counter = new int; 2186221Snate@binkert.org *counter = numThreads; 2196221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 2205606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 2216221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 2225606Snate@binkert.org } 223124SN/A } 224124SN/A 2251191SN/A functionTracingEnabled = false; 2265529Snate@binkert.org if (p->function_trace) { 2278634Schris.emmons@arm.com const string fname = csprintf("ftrace.%s", name()); 22811359Sandreas@sandberg.pp.se functionTraceStream = simout.findOrCreate(fname)->stream(); 2298634Schris.emmons@arm.com 2301191SN/A currentFunctionStart = currentFunctionEnd = 0; 2315529Snate@binkert.org functionEntryTick = p->function_trace_start; 2321191SN/A 2335529Snate@binkert.org if (p->function_trace_start == 0) { 2341191SN/A functionTracingEnabled = true; 2351191SN/A } else { 23612085Sspwilson2@wisc.edu Event *event = new EventFunctionWrapper( 23712085Sspwilson2@wisc.edu [this]{ enableFunctionTrace(); }, name(), true); 2385606Snate@binkert.org schedule(event, p->function_trace_start); 2391191SN/A } 2401191SN/A } 2418876Sandreas.hansson@arm.com 2428876Sandreas.hansson@arm.com // The interrupts should always be present unless this CPU is 2438876Sandreas.hansson@arm.com // switched in later or in case it is a checker CPU 2449433SAndreas.Sandberg@ARM.com if (!params()->switched_out && !is_checker) { 24511221Sandreas.sandberg@arm.com fatal_if(interrupts.size() != numThreads, 24611221Sandreas.sandberg@arm.com "CPU %s has %i interrupt controllers, but is expecting one " 24711221Sandreas.sandberg@arm.com "per thread (%i)\n", 24811221Sandreas.sandberg@arm.com name(), interrupts.size(), numThreads); 24911221Sandreas.sandberg@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) 25011221Sandreas.sandberg@arm.com interrupts[tid]->setCPU(this); 2518876Sandreas.hansson@arm.com } 2525810Sgblack@eecs.umich.edu 2538779Sgblack@eecs.umich.edu if (FullSystem) { 2548779Sgblack@eecs.umich.edu if (params()->profile) 25512127Sspwilson2@wisc.edu profileEvent = new EventFunctionWrapper( 25612127Sspwilson2@wisc.edu [this]{ processProfileEvent(); }, 25712127Sspwilson2@wisc.edu name()); 2588779Sgblack@eecs.umich.edu } 2595529Snate@binkert.org tracer = params()->tracer; 2609384SAndreas.Sandberg@arm.com 2619384SAndreas.Sandberg@arm.com if (params()->isa.size() != numThreads) { 2629384SAndreas.Sandberg@arm.com fatal("Number of ISAs (%i) assigned to the CPU does not equal number " 2639384SAndreas.Sandberg@arm.com "of threads (%i).\n", params()->isa.size(), numThreads); 2649384SAndreas.Sandberg@arm.com } 2651917SN/A} 2661191SN/A 2671191SN/Avoid 2681191SN/ABaseCPU::enableFunctionTrace() 2691191SN/A{ 2701191SN/A functionTracingEnabled = true; 2711191SN/A} 2721191SN/A 2731191SN/ABaseCPU::~BaseCPU() 2741191SN/A{ 2759086Sandreas.hansson@arm.com delete profileEvent; 2769086Sandreas.hansson@arm.com delete[] comLoadEventQueue; 2779086Sandreas.hansson@arm.com delete[] comInstEventQueue; 2781191SN/A} 2791191SN/A 2801129SN/Avoid 28111148Smitch.hayenga@arm.comBaseCPU::armMonitor(ThreadID tid, Addr address) 28210529Smorr@cs.wisc.edu{ 28311148Smitch.hayenga@arm.com assert(tid < numThreads); 28411148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 28511148Smitch.hayenga@arm.com 28611148Smitch.hayenga@arm.com monitor.armed = true; 28711148Smitch.hayenga@arm.com monitor.vAddr = address; 28811148Smitch.hayenga@arm.com monitor.pAddr = 0x0; 28911148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] Armed monitor (vAddr=0x%lx)\n", tid, address); 29010529Smorr@cs.wisc.edu} 29110529Smorr@cs.wisc.edu 29210529Smorr@cs.wisc.edubool 29311148Smitch.hayenga@arm.comBaseCPU::mwait(ThreadID tid, PacketPtr pkt) 29410529Smorr@cs.wisc.edu{ 29511148Smitch.hayenga@arm.com assert(tid < numThreads); 29611148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 29711148Smitch.hayenga@arm.com 29811325Ssteve.reinhardt@amd.com if (!monitor.gotWakeup) { 29910529Smorr@cs.wisc.edu int block_size = cacheLineSize(); 30010529Smorr@cs.wisc.edu uint64_t mask = ~((uint64_t)(block_size - 1)); 30110529Smorr@cs.wisc.edu 30210529Smorr@cs.wisc.edu assert(pkt->req->hasPaddr()); 30311148Smitch.hayenga@arm.com monitor.pAddr = pkt->getAddr() & mask; 30411148Smitch.hayenga@arm.com monitor.waiting = true; 30510529Smorr@cs.wisc.edu 30611148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, " 30711148Smitch.hayenga@arm.com "line's paddr=0x%lx)\n", tid, monitor.vAddr, monitor.pAddr); 30810529Smorr@cs.wisc.edu return true; 30910529Smorr@cs.wisc.edu } else { 31011148Smitch.hayenga@arm.com monitor.gotWakeup = false; 31110529Smorr@cs.wisc.edu return false; 31210529Smorr@cs.wisc.edu } 31310529Smorr@cs.wisc.edu} 31410529Smorr@cs.wisc.edu 31510529Smorr@cs.wisc.eduvoid 31612406Sgabeblack@google.comBaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseTLB *dtb) 31710529Smorr@cs.wisc.edu{ 31811148Smitch.hayenga@arm.com assert(tid < numThreads); 31911148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 32011148Smitch.hayenga@arm.com 32112784Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(); 32212784Sgiacomo.travaglini@arm.com 32311148Smitch.hayenga@arm.com Addr addr = monitor.vAddr; 32410529Smorr@cs.wisc.edu int block_size = cacheLineSize(); 32510529Smorr@cs.wisc.edu uint64_t mask = ~((uint64_t)(block_size - 1)); 32610529Smorr@cs.wisc.edu int size = block_size; 32710529Smorr@cs.wisc.edu 32810529Smorr@cs.wisc.edu //The address of the next line if it crosses a cache line boundary. 32910529Smorr@cs.wisc.edu Addr secondAddr = roundDown(addr + size - 1, block_size); 33010529Smorr@cs.wisc.edu 33110529Smorr@cs.wisc.edu if (secondAddr > addr) 33210529Smorr@cs.wisc.edu size = secondAddr - addr; 33310529Smorr@cs.wisc.edu 33412749Sgiacomo.travaglini@arm.com req->setVirt(0, addr, size, 0x0, dataMasterId(), tc->instAddr()); 33510529Smorr@cs.wisc.edu 33610529Smorr@cs.wisc.edu // translate to physical address 33712749Sgiacomo.travaglini@arm.com Fault fault = dtb->translateAtomic(req, tc, BaseTLB::Read); 33810529Smorr@cs.wisc.edu assert(fault == NoFault); 33910529Smorr@cs.wisc.edu 34012749Sgiacomo.travaglini@arm.com monitor.pAddr = req->getPaddr() & mask; 34111148Smitch.hayenga@arm.com monitor.waiting = true; 34210529Smorr@cs.wisc.edu 34311148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n", 34411148Smitch.hayenga@arm.com tid, monitor.vAddr, monitor.pAddr); 34510529Smorr@cs.wisc.edu} 34610529Smorr@cs.wisc.edu 34710529Smorr@cs.wisc.eduvoid 3481129SN/ABaseCPU::init() 3491129SN/A{ 3509523SAndreas.Sandberg@ARM.com if (!params()->switched_out) { 3512680Sktlim@umich.edu registerThreadContexts(); 3529523SAndreas.Sandberg@ARM.com 3539523SAndreas.Sandberg@ARM.com verifyMemoryMode(); 3549523SAndreas.Sandberg@ARM.com } 3551129SN/A} 356180SN/A 3572SN/Avoid 3581917SN/ABaseCPU::startup() 3591917SN/A{ 3608779Sgblack@eecs.umich.edu if (FullSystem) { 3619433SAndreas.Sandberg@ARM.com if (!params()->switched_out && profileEvent) 3628779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 3638779Sgblack@eecs.umich.edu } 3642356SN/A 3655529Snate@binkert.org if (params()->progress_interval) { 3669179Sandreas.hansson@arm.com new CPUProgressEvent(this, params()->progress_interval); 3672356SN/A } 36811526Sdavid.guillen@arm.com 36912276Sanouk.vanlaer@arm.com if (_switchedOut) 37012276Sanouk.vanlaer@arm.com ClockedObject::pwrState(Enums::PwrState::OFF); 37112276Sanouk.vanlaer@arm.com 37211526Sdavid.guillen@arm.com // Assumption CPU start to operate instantaneously without any latency 37311526Sdavid.guillen@arm.com if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED) 37411526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::ON); 37511526Sdavid.guillen@arm.com 3761917SN/A} 3771917SN/A 37810464SAndreas.Sandberg@ARM.comProbePoints::PMUUPtr 37910464SAndreas.Sandberg@ARM.comBaseCPU::pmuProbePoint(const char *name) 38010464SAndreas.Sandberg@ARM.com{ 38110464SAndreas.Sandberg@ARM.com ProbePoints::PMUUPtr ptr; 38210464SAndreas.Sandberg@ARM.com ptr.reset(new ProbePoints::PMU(getProbeManager(), name)); 38310464SAndreas.Sandberg@ARM.com 38410464SAndreas.Sandberg@ARM.com return ptr; 38510464SAndreas.Sandberg@ARM.com} 38610464SAndreas.Sandberg@ARM.com 38710464SAndreas.Sandberg@ARM.comvoid 38810464SAndreas.Sandberg@ARM.comBaseCPU::regProbePoints() 38910464SAndreas.Sandberg@ARM.com{ 39012284Sjose.marinho@arm.com ppAllCycles = pmuProbePoint("Cycles"); 39112284Sjose.marinho@arm.com ppActiveCycles = pmuProbePoint("ActiveCycles"); 39210464SAndreas.Sandberg@ARM.com 39310464SAndreas.Sandberg@ARM.com ppRetiredInsts = pmuProbePoint("RetiredInsts"); 39413818Sjavier.bueno@metempsy.com ppRetiredInstsPC = pmuProbePoint("RetiredInstsPC"); 39510464SAndreas.Sandberg@ARM.com ppRetiredLoads = pmuProbePoint("RetiredLoads"); 39610464SAndreas.Sandberg@ARM.com ppRetiredStores = pmuProbePoint("RetiredStores"); 39710464SAndreas.Sandberg@ARM.com ppRetiredBranches = pmuProbePoint("RetiredBranches"); 39812284Sjose.marinho@arm.com 39912284Sjose.marinho@arm.com ppSleeping = new ProbePointArg<bool>(this->getProbeManager(), 40012284Sjose.marinho@arm.com "Sleeping"); 40110464SAndreas.Sandberg@ARM.com} 40210464SAndreas.Sandberg@ARM.com 40310464SAndreas.Sandberg@ARM.comvoid 40413818Sjavier.bueno@metempsy.comBaseCPU::probeInstCommit(const StaticInstPtr &inst, Addr pc) 40510464SAndreas.Sandberg@ARM.com{ 40613818Sjavier.bueno@metempsy.com if (!inst->isMicroop() || inst->isLastMicroop()) { 40710464SAndreas.Sandberg@ARM.com ppRetiredInsts->notify(1); 40813818Sjavier.bueno@metempsy.com ppRetiredInstsPC->notify(pc); 40913818Sjavier.bueno@metempsy.com } 41010464SAndreas.Sandberg@ARM.com 41110464SAndreas.Sandberg@ARM.com if (inst->isLoad()) 41210464SAndreas.Sandberg@ARM.com ppRetiredLoads->notify(1); 41310464SAndreas.Sandberg@ARM.com 41413652Sqtt2@cornell.edu if (inst->isStore() || inst->isAtomic()) 41510643Snikos.nikoleris@gmail.com ppRetiredStores->notify(1); 41610464SAndreas.Sandberg@ARM.com 41710464SAndreas.Sandberg@ARM.com if (inst->isControl()) 41810464SAndreas.Sandberg@ARM.com ppRetiredBranches->notify(1); 41910464SAndreas.Sandberg@ARM.com} 4201917SN/A 4211917SN/Avoid 4222SN/ABaseCPU::regStats() 4232SN/A{ 42413892Sgabeblack@google.com ClockedObject::regStats(); 42511522Sstephan.diestelhorst@arm.com 426729SN/A using namespace Stats; 427707SN/A 428707SN/A numCycles 429707SN/A .name(name() + ".numCycles") 430707SN/A .desc("number of cpu cycles simulated") 431707SN/A ; 432707SN/A 4337914SBrad.Beckmann@amd.com numWorkItemsStarted 4347914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsStarted") 4357914SBrad.Beckmann@amd.com .desc("number of work items this cpu started") 4367914SBrad.Beckmann@amd.com ; 4377914SBrad.Beckmann@amd.com 4387914SBrad.Beckmann@amd.com numWorkItemsCompleted 4397914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsCompleted") 4407914SBrad.Beckmann@amd.com .desc("number of work items this cpu completed") 4417914SBrad.Beckmann@amd.com ; 4427914SBrad.Beckmann@amd.com 4432680Sktlim@umich.edu int size = threadContexts.size(); 4442SN/A if (size > 1) { 4452SN/A for (int i = 0; i < size; ++i) { 4462SN/A stringstream namestr; 4472SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 4482680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 4492SN/A } 4502SN/A } else if (size == 1) 4512680Sktlim@umich.edu threadContexts[0]->regStats(name()); 4522SN/A} 4532SN/A 45413784Sgabeblack@google.comPort & 45513784Sgabeblack@google.comBaseCPU::getPort(const string &if_name, PortID idx) 4568850Sandreas.hansson@arm.com{ 4578850Sandreas.hansson@arm.com // Get the right port based on name. This applies to all the 4588850Sandreas.hansson@arm.com // subclasses of the base CPU and relies on their implementation 45913784Sgabeblack@google.com // of getDataPort and getInstPort. 4608850Sandreas.hansson@arm.com if (if_name == "dcache_port") 4618922Swilliam.wang@arm.com return getDataPort(); 4628850Sandreas.hansson@arm.com else if (if_name == "icache_port") 4638922Swilliam.wang@arm.com return getInstPort(); 4648850Sandreas.hansson@arm.com else 46513892Sgabeblack@google.com return ClockedObject::getPort(if_name, idx); 4668850Sandreas.hansson@arm.com} 4678850Sandreas.hansson@arm.com 468180SN/Avoid 4692680Sktlim@umich.eduBaseCPU::registerThreadContexts() 470180SN/A{ 47111146Smitch.hayenga@arm.com assert(system->multiThread || numThreads == 1); 47211146Smitch.hayenga@arm.com 4736221Snate@binkert.org ThreadID size = threadContexts.size(); 4746221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 4756221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 4762378SN/A 47711146Smitch.hayenga@arm.com if (system->multiThread) { 47811146Smitch.hayenga@arm.com tc->setContextId(system->registerThreadContext(tc)); 47911146Smitch.hayenga@arm.com } else { 4805718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 48111146Smitch.hayenga@arm.com } 4828779Sgblack@eecs.umich.edu 4838779Sgblack@eecs.umich.edu if (!FullSystem) 4848779Sgblack@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 485180SN/A } 486180SN/A} 487180SN/A 48812276Sanouk.vanlaer@arm.comvoid 48912276Sanouk.vanlaer@arm.comBaseCPU::deschedulePowerGatingEvent() 49012276Sanouk.vanlaer@arm.com{ 49112276Sanouk.vanlaer@arm.com if (enterPwrGatingEvent.scheduled()){ 49212276Sanouk.vanlaer@arm.com deschedule(enterPwrGatingEvent); 49312276Sanouk.vanlaer@arm.com } 49412276Sanouk.vanlaer@arm.com} 49512276Sanouk.vanlaer@arm.com 49612276Sanouk.vanlaer@arm.comvoid 49712276Sanouk.vanlaer@arm.comBaseCPU::schedulePowerGatingEvent() 49812276Sanouk.vanlaer@arm.com{ 49912276Sanouk.vanlaer@arm.com for (auto tc : threadContexts) { 50012276Sanouk.vanlaer@arm.com if (tc->status() == ThreadContext::Active) 50112276Sanouk.vanlaer@arm.com return; 50212276Sanouk.vanlaer@arm.com } 50312276Sanouk.vanlaer@arm.com 50412277Sjose.marinho@arm.com if (ClockedObject::pwrState() == Enums::PwrState::CLK_GATED && 50512277Sjose.marinho@arm.com powerGatingOnIdle) { 50612276Sanouk.vanlaer@arm.com assert(!enterPwrGatingEvent.scheduled()); 50712276Sanouk.vanlaer@arm.com // Schedule a power gating event when clock gated for the specified 50812276Sanouk.vanlaer@arm.com // amount of time 50912276Sanouk.vanlaer@arm.com schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); 51012276Sanouk.vanlaer@arm.com } 51112276Sanouk.vanlaer@arm.com} 512180SN/A 5134000Ssaidi@eecs.umich.eduint 5144000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 5154000Ssaidi@eecs.umich.edu{ 5166221Snate@binkert.org ThreadID size = threadContexts.size(); 5176221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 5186221Snate@binkert.org if (tc == threadContexts[tid]) 5196221Snate@binkert.org return tid; 5204000Ssaidi@eecs.umich.edu } 5214000Ssaidi@eecs.umich.edu return 0; 5224000Ssaidi@eecs.umich.edu} 5234000Ssaidi@eecs.umich.edu 524180SN/Avoid 52511526Sdavid.guillen@arm.comBaseCPU::activateContext(ThreadID thread_num) 52611526Sdavid.guillen@arm.com{ 52712276Sanouk.vanlaer@arm.com // Squash enter power gating event while cpu gets activated 52812276Sanouk.vanlaer@arm.com if (enterPwrGatingEvent.scheduled()) 52912276Sanouk.vanlaer@arm.com deschedule(enterPwrGatingEvent); 53011526Sdavid.guillen@arm.com // For any active thread running, update CPU power state to active (ON) 53111526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::ON); 53212284Sjose.marinho@arm.com 53312284Sjose.marinho@arm.com updateCycleCounters(CPU_STATE_WAKEUP); 53411526Sdavid.guillen@arm.com} 53511526Sdavid.guillen@arm.com 53611526Sdavid.guillen@arm.comvoid 53711526Sdavid.guillen@arm.comBaseCPU::suspendContext(ThreadID thread_num) 53811526Sdavid.guillen@arm.com{ 53911526Sdavid.guillen@arm.com // Check if all threads are suspended 54011526Sdavid.guillen@arm.com for (auto t : threadContexts) { 54111526Sdavid.guillen@arm.com if (t->status() != ThreadContext::Suspended) { 54211526Sdavid.guillen@arm.com return; 54311526Sdavid.guillen@arm.com } 54411526Sdavid.guillen@arm.com } 54511526Sdavid.guillen@arm.com 54612284Sjose.marinho@arm.com // All CPU thread are suspended, update cycle count 54712284Sjose.marinho@arm.com updateCycleCounters(CPU_STATE_SLEEP); 54812284Sjose.marinho@arm.com 54911526Sdavid.guillen@arm.com // All CPU threads suspended, enter lower power state for the CPU 55011526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::CLK_GATED); 55112276Sanouk.vanlaer@arm.com 55212277Sjose.marinho@arm.com // If pwrGatingLatency is set to 0 then this mechanism is disabled 55312277Sjose.marinho@arm.com if (powerGatingOnIdle) { 55412277Sjose.marinho@arm.com // Schedule power gating event when clock gated for pwrGatingLatency 55512277Sjose.marinho@arm.com // cycles 55612277Sjose.marinho@arm.com schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); 55712277Sjose.marinho@arm.com } 55812276Sanouk.vanlaer@arm.com} 55912276Sanouk.vanlaer@arm.com 56012276Sanouk.vanlaer@arm.comvoid 56112284Sjose.marinho@arm.comBaseCPU::haltContext(ThreadID thread_num) 56212284Sjose.marinho@arm.com{ 56312284Sjose.marinho@arm.com updateCycleCounters(BaseCPU::CPU_STATE_SLEEP); 56412284Sjose.marinho@arm.com} 56512284Sjose.marinho@arm.com 56612284Sjose.marinho@arm.comvoid 56712276Sanouk.vanlaer@arm.comBaseCPU::enterPwrGating(void) 56812276Sanouk.vanlaer@arm.com{ 56912276Sanouk.vanlaer@arm.com ClockedObject::pwrState(Enums::PwrState::OFF); 57011526Sdavid.guillen@arm.com} 57111526Sdavid.guillen@arm.com 57211526Sdavid.guillen@arm.comvoid 5732798Sktlim@umich.eduBaseCPU::switchOut() 574180SN/A{ 5759430SAndreas.Sandberg@ARM.com assert(!_switchedOut); 5769430SAndreas.Sandberg@ARM.com _switchedOut = true; 5772359SN/A if (profileEvent && profileEvent->scheduled()) 5785606Snate@binkert.org deschedule(profileEvent); 5799446SAndreas.Sandberg@ARM.com 5809446SAndreas.Sandberg@ARM.com // Flush all TLBs in the CPU to avoid having stale translations if 5819446SAndreas.Sandberg@ARM.com // it gets switched in later. 5829446SAndreas.Sandberg@ARM.com flushTLBs(); 58312276Sanouk.vanlaer@arm.com 58412276Sanouk.vanlaer@arm.com // Go to the power gating state 58512276Sanouk.vanlaer@arm.com ClockedObject::pwrState(Enums::PwrState::OFF); 586180SN/A} 587180SN/A 588180SN/Avoid 5898737Skoansin.tan@gmail.comBaseCPU::takeOverFrom(BaseCPU *oldCPU) 590180SN/A{ 5912680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 5929152Satgutier@umich.edu assert(_cpuId == oldCPU->cpuId()); 5939430SAndreas.Sandberg@ARM.com assert(_switchedOut); 5949430SAndreas.Sandberg@ARM.com assert(oldCPU != this); 5959332Sdam.sunwoo@arm.com _pid = oldCPU->getPid(); 5969332Sdam.sunwoo@arm.com _taskId = oldCPU->taskId(); 59712276Sanouk.vanlaer@arm.com // Take over the power state of the switchedOut CPU 59812276Sanouk.vanlaer@arm.com ClockedObject::pwrState(oldCPU->pwrState()); 59912284Sjose.marinho@arm.com 60012284Sjose.marinho@arm.com previousState = oldCPU->previousState; 60112284Sjose.marinho@arm.com previousCycle = oldCPU->previousCycle; 60212284Sjose.marinho@arm.com 6039430SAndreas.Sandberg@ARM.com _switchedOut = false; 6045712Shsul@eecs.umich.edu 6056221Snate@binkert.org ThreadID size = threadContexts.size(); 6066221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 6072680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 6082680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 609180SN/A 6102680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 6112651Ssaidi@eecs.umich.edu 6122680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 6132651Ssaidi@eecs.umich.edu 6145714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 6155715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 6165714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 6172359SN/A 6185875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 6195875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 6205875Ssteve.reinhardt@amd.com * point. 6215875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 6225217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 6235875Ssteve.reinhardt@amd.com */ 6247781SAli.Saidi@ARM.com 62513784Sgabeblack@google.com Port *old_itb_port = oldTC->getITBPtr()->getTableWalkerPort(); 62613784Sgabeblack@google.com Port *old_dtb_port = oldTC->getDTBPtr()->getTableWalkerPort(); 62713784Sgabeblack@google.com Port *new_itb_port = newTC->getITBPtr()->getTableWalkerPort(); 62813784Sgabeblack@google.com Port *new_dtb_port = newTC->getDTBPtr()->getTableWalkerPort(); 6297781SAli.Saidi@ARM.com 6307781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 63114192Sgabeblack@google.com if (new_itb_port) 63214192Sgabeblack@google.com new_itb_port->takeOverFrom(old_itb_port); 63314192Sgabeblack@google.com if (new_dtb_port) 63414192Sgabeblack@google.com new_dtb_port->takeOverFrom(old_dtb_port); 63510194SGeoffrey.Blake@arm.com newTC->getITBPtr()->takeOverFrom(oldTC->getITBPtr()); 63610194SGeoffrey.Blake@arm.com newTC->getDTBPtr()->takeOverFrom(oldTC->getDTBPtr()); 6378733Sgeoffrey.blake@arm.com 6388887Sgeoffrey.blake@arm.com // Checker whether or not we have to transfer CheckerCPU 6398887Sgeoffrey.blake@arm.com // objects over in the switch 6408887Sgeoffrey.blake@arm.com CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr(); 6418887Sgeoffrey.blake@arm.com CheckerCPU *newChecker = newTC->getCheckerCpuPtr(); 6428887Sgeoffrey.blake@arm.com if (oldChecker && newChecker) { 64313784Sgabeblack@google.com Port *old_checker_itb_port = 64413784Sgabeblack@google.com oldChecker->getITBPtr()->getTableWalkerPort(); 64513784Sgabeblack@google.com Port *old_checker_dtb_port = 64613784Sgabeblack@google.com oldChecker->getDTBPtr()->getTableWalkerPort(); 64713784Sgabeblack@google.com Port *new_checker_itb_port = 64813784Sgabeblack@google.com newChecker->getITBPtr()->getTableWalkerPort(); 64913784Sgabeblack@google.com Port *new_checker_dtb_port = 65013784Sgabeblack@google.com newChecker->getDTBPtr()->getTableWalkerPort(); 6518733Sgeoffrey.blake@arm.com 65210194SGeoffrey.Blake@arm.com newChecker->getITBPtr()->takeOverFrom(oldChecker->getITBPtr()); 65310194SGeoffrey.Blake@arm.com newChecker->getDTBPtr()->takeOverFrom(oldChecker->getDTBPtr()); 65410194SGeoffrey.Blake@arm.com 6558887Sgeoffrey.blake@arm.com // Move over any table walker ports if they exist for checker 65614192Sgabeblack@google.com if (new_checker_itb_port) 65714192Sgabeblack@google.com new_checker_itb_port->takeOverFrom(old_checker_itb_port); 65814192Sgabeblack@google.com if (new_checker_dtb_port) 65914192Sgabeblack@google.com new_checker_dtb_port->takeOverFrom(old_checker_dtb_port); 6608733Sgeoffrey.blake@arm.com } 661180SN/A } 662605SN/A 6633520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 66411150Smitch.hayenga@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 66511150Smitch.hayenga@arm.com interrupts[tid]->setCPU(this); 66611150Smitch.hayenga@arm.com } 66711150Smitch.hayenga@arm.com oldCPU->interrupts.clear(); 6682254SN/A 6698779Sgblack@eecs.umich.edu if (FullSystem) { 6708779Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; ++i) 6718779Sgblack@eecs.umich.edu threadContexts[i]->profileClear(); 6722254SN/A 6738779Sgblack@eecs.umich.edu if (profileEvent) 6748779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 6758779Sgblack@eecs.umich.edu } 6764192Sktlim@umich.edu 6779178Sandreas.hansson@arm.com // All CPUs have an instruction and a data port, and the new CPU's 6789178Sandreas.hansson@arm.com // ports are dangling while the old CPU has its ports connected 6799178Sandreas.hansson@arm.com // already. Unbind the old CPU and then bind the ports of the one 6809178Sandreas.hansson@arm.com // we are switching to. 68114192Sgabeblack@google.com getInstPort().takeOverFrom(&oldCPU->getInstPort()); 68214192Sgabeblack@google.com getDataPort().takeOverFrom(&oldCPU->getDataPort()); 683180SN/A} 684180SN/A 6859446SAndreas.Sandberg@ARM.comvoid 6869446SAndreas.Sandberg@ARM.comBaseCPU::flushTLBs() 6879446SAndreas.Sandberg@ARM.com{ 6889446SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < threadContexts.size(); ++i) { 6899446SAndreas.Sandberg@ARM.com ThreadContext &tc(*threadContexts[i]); 6909446SAndreas.Sandberg@ARM.com CheckerCPU *checker(tc.getCheckerCpuPtr()); 6919446SAndreas.Sandberg@ARM.com 6929446SAndreas.Sandberg@ARM.com tc.getITBPtr()->flushAll(); 6939446SAndreas.Sandberg@ARM.com tc.getDTBPtr()->flushAll(); 6949446SAndreas.Sandberg@ARM.com if (checker) { 6959446SAndreas.Sandberg@ARM.com checker->getITBPtr()->flushAll(); 6969446SAndreas.Sandberg@ARM.com checker->getDTBPtr()->flushAll(); 6979446SAndreas.Sandberg@ARM.com } 6989446SAndreas.Sandberg@ARM.com } 6999446SAndreas.Sandberg@ARM.com} 7009446SAndreas.Sandberg@ARM.com 70112127Sspwilson2@wisc.eduvoid 70212127Sspwilson2@wisc.eduBaseCPU::processProfileEvent() 70312127Sspwilson2@wisc.edu{ 70412127Sspwilson2@wisc.edu ThreadID size = threadContexts.size(); 705180SN/A 70612127Sspwilson2@wisc.edu for (ThreadID i = 0; i < size; ++i) 70712127Sspwilson2@wisc.edu threadContexts[i]->profileSample(); 7081917SN/A 70912127Sspwilson2@wisc.edu schedule(profileEvent, curTick() + params()->profile); 7101917SN/A} 7111917SN/A 7122SN/Avoid 71310905Sandreas.sandberg@arm.comBaseCPU::serialize(CheckpointOut &cp) const 714921SN/A{ 7154000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 7169332Sdam.sunwoo@arm.com 7179448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 7189448SAndreas.Sandberg@ARM.com /* Unlike _pid, _taskId is not serialized, as they are dynamically 7199448SAndreas.Sandberg@ARM.com * assigned unique ids that are only meaningful for the duration of 7209448SAndreas.Sandberg@ARM.com * a specific run. We will need to serialize the entire taskMap in 7219448SAndreas.Sandberg@ARM.com * system. */ 7229448SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(_pid); 7239332Sdam.sunwoo@arm.com 7249448SAndreas.Sandberg@ARM.com // Serialize the threads, this is done by the CPU implementation. 7259448SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) { 72610905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 72711150Smitch.hayenga@arm.com interrupts[i]->serialize(cp); 72810905Sandreas.sandberg@arm.com serializeThread(cp, i); 7299448SAndreas.Sandberg@ARM.com } 7309448SAndreas.Sandberg@ARM.com } 731921SN/A} 732921SN/A 733921SN/Avoid 73410905Sandreas.sandberg@arm.comBaseCPU::unserialize(CheckpointIn &cp) 735921SN/A{ 7364000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 7379448SAndreas.Sandberg@ARM.com 7389448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 7399448SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(_pid); 7409448SAndreas.Sandberg@ARM.com 7419448SAndreas.Sandberg@ARM.com // Unserialize the threads, this is done by the CPU implementation. 74210905Sandreas.sandberg@arm.com for (ThreadID i = 0; i < numThreads; ++i) { 74310905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 74411150Smitch.hayenga@arm.com interrupts[i]->unserialize(cp); 74510905Sandreas.sandberg@arm.com unserializeThread(cp, i); 74610905Sandreas.sandberg@arm.com } 7479448SAndreas.Sandberg@ARM.com } 748921SN/A} 749921SN/A 7501191SN/Avoid 7519749Sandreas@sandberg.pp.seBaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause) 7529749Sandreas@sandberg.pp.se{ 7539749Sandreas@sandberg.pp.se const Tick now(comInstEventQueue[tid]->getCurTick()); 7549983Sstever@gmail.com Event *event(new LocalSimLoopExitEvent(cause, 0)); 7559749Sandreas@sandberg.pp.se 7569749Sandreas@sandberg.pp.se comInstEventQueue[tid]->schedule(event, now + insts); 7579749Sandreas@sandberg.pp.se} 7589749Sandreas@sandberg.pp.se 75911415SGeoffrey.Blake@arm.comuint64_t 76011415SGeoffrey.Blake@arm.comBaseCPU::getCurrentInstCount(ThreadID tid) 76111415SGeoffrey.Blake@arm.com{ 76211415SGeoffrey.Blake@arm.com return Tick(comInstEventQueue[tid]->getCurTick()); 76311415SGeoffrey.Blake@arm.com} 76411415SGeoffrey.Blake@arm.com 76510529Smorr@cs.wisc.eduAddressMonitor::AddressMonitor() { 76610529Smorr@cs.wisc.edu armed = false; 76710529Smorr@cs.wisc.edu waiting = false; 76810529Smorr@cs.wisc.edu gotWakeup = false; 76910529Smorr@cs.wisc.edu} 77010529Smorr@cs.wisc.edu 77110529Smorr@cs.wisc.edubool AddressMonitor::doMonitor(PacketPtr pkt) { 77210529Smorr@cs.wisc.edu assert(pkt->req->hasPaddr()); 77311321Ssteve.reinhardt@amd.com if (armed && waiting) { 77411321Ssteve.reinhardt@amd.com if (pAddr == pkt->getAddr()) { 77510529Smorr@cs.wisc.edu DPRINTF(Mwait,"pAddr=0x%lx invalidated: waking up core\n", 77610529Smorr@cs.wisc.edu pkt->getAddr()); 77710529Smorr@cs.wisc.edu waiting = false; 77810529Smorr@cs.wisc.edu return true; 77910529Smorr@cs.wisc.edu } 78010529Smorr@cs.wisc.edu } 78110529Smorr@cs.wisc.edu return false; 78210529Smorr@cs.wisc.edu} 78310529Smorr@cs.wisc.edu 7849749Sandreas@sandberg.pp.sevoid 7859749Sandreas@sandberg.pp.seBaseCPU::scheduleLoadStop(ThreadID tid, Counter loads, const char *cause) 7869749Sandreas@sandberg.pp.se{ 7879749Sandreas@sandberg.pp.se const Tick now(comLoadEventQueue[tid]->getCurTick()); 7889983Sstever@gmail.com Event *event(new LocalSimLoopExitEvent(cause, 0)); 7899749Sandreas@sandberg.pp.se 7909749Sandreas@sandberg.pp.se comLoadEventQueue[tid]->schedule(event, now + loads); 7919749Sandreas@sandberg.pp.se} 7929749Sandreas@sandberg.pp.se 7939749Sandreas@sandberg.pp.se 7949749Sandreas@sandberg.pp.sevoid 7951191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 7961191SN/A{ 7971191SN/A if (!debugSymbolTable) 7981191SN/A return; 7991191SN/A 8001191SN/A // if pc enters different function, print new function symbol and 8011191SN/A // update saved range. Otherwise do nothing. 8021191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 8031191SN/A string sym_str; 8041191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 8051191SN/A currentFunctionStart, 8061191SN/A currentFunctionEnd); 8071191SN/A 8081191SN/A if (!found) { 8091191SN/A // no symbol found: use addr as label 8101191SN/A sym_str = csprintf("0x%x", pc); 8111191SN/A currentFunctionStart = pc; 8121191SN/A currentFunctionEnd = pc + 1; 8131191SN/A } 8141191SN/A 8151191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 8167823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 8177823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 8181191SN/A } 8191191SN/A} 82012122Sjose.marinho@arm.com 82112122Sjose.marinho@arm.combool 82212122Sjose.marinho@arm.comBaseCPU::waitForRemoteGDB() const 82312122Sjose.marinho@arm.com{ 82412122Sjose.marinho@arm.com return params()->wait_for_remote_gdb; 82512122Sjose.marinho@arm.com} 826