base.cc revision 11526
12SN/A/* 211526Sdavid.guillen@arm.com * Copyright (c) 2011-2012,2016 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 481388SN/A#include <iostream> 498229Snate@binkert.org#include <sstream> 502SN/A#include <string> 512SN/A 527781SAli.Saidi@ARM.com#include "arch/tlb.hh" 538229Snate@binkert.org#include "base/loader/symtab.hh" 541191SN/A#include "base/cprintf.hh" 551191SN/A#include "base/misc.hh" 561388SN/A#include "base/output.hh" 575529Snate@binkert.org#include "base/trace.hh" 5810529Smorr@cs.wisc.edu#include "cpu/checker/cpu.hh" 591717SN/A#include "cpu/base.hh" 602651Ssaidi@eecs.umich.edu#include "cpu/cpuevent.hh" 618229Snate@binkert.org#include "cpu/profile.hh" 622680Sktlim@umich.edu#include "cpu/thread_context.hh" 6310529Smorr@cs.wisc.edu#include "debug/Mwait.hh" 648232Snate@binkert.org#include "debug/SyscallVerbose.hh" 6510529Smorr@cs.wisc.edu#include "mem/page_table.hh" 665529Snate@binkert.org#include "params/BaseCPU.hh" 6711526Sdavid.guillen@arm.com#include "sim/clocked_object.hh" 688779Sgblack@eecs.umich.edu#include "sim/full_system.hh" 692190SN/A#include "sim/process.hh" 7056SN/A#include "sim/sim_events.hh" 718229Snate@binkert.org#include "sim/sim_exit.hh" 722190SN/A#include "sim/system.hh" 732SN/A 742359SN/A// Hack 752359SN/A#include "sim/stat_control.hh" 762359SN/A 772SN/Ausing namespace std; 782SN/A 792SN/Avector<BaseCPU *> BaseCPU::cpuList; 802SN/A 812SN/A// This variable reflects the max number of threads in any CPU. Be 822SN/A// careful to only use it once all the CPUs that you care about have 832SN/A// been initialized 842SN/Aint maxThreadsPerCPU = 1; 852SN/A 865606Snate@binkert.orgCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 876144Sksewell@umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 886144Sksewell@umich.edu cpu(_cpu), _repeatEvent(true) 893126Sktlim@umich.edu{ 906144Sksewell@umich.edu if (_interval) 917823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + _interval); 923126Sktlim@umich.edu} 933126Sktlim@umich.edu 942356SN/Avoid 952356SN/ACPUProgressEvent::process() 962356SN/A{ 978834Satgutier@umich.edu Counter temp = cpu->totalOps(); 9810786Smalek.musleh@gmail.com 9910786Smalek.musleh@gmail.com if (_repeatEvent) 10010786Smalek.musleh@gmail.com cpu->schedule(this, curTick() + _interval); 10110786Smalek.musleh@gmail.com 10211321Ssteve.reinhardt@amd.com if (cpu->switchedOut()) { 10310786Smalek.musleh@gmail.com return; 10410786Smalek.musleh@gmail.com } 10510786Smalek.musleh@gmail.com 1062356SN/A#ifndef NDEBUG 1079179Sandreas.hansson@arm.com double ipc = double(temp - lastNumInst) / (_interval / cpu->clockPeriod()); 1082367SN/A 1096144Sksewell@umich.edu DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 1106144Sksewell@umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 1116144Sksewell@umich.edu ipc); 1122356SN/A ipc = 0.0; 1132367SN/A#else 1146144Sksewell@umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 1157823Ssteve.reinhardt@amd.com "committed: %lli\n", curTick(), cpu->name(), temp, 1166144Sksewell@umich.edu temp - lastNumInst); 1172367SN/A#endif 1182356SN/A lastNumInst = temp; 1192356SN/A} 1202356SN/A 1212356SN/Aconst char * 1225336Shines@cs.fsu.eduCPUProgressEvent::description() const 1232356SN/A{ 1244873Sstever@eecs.umich.edu return "CPU Progress"; 1252356SN/A} 1262356SN/A 1278876Sandreas.hansson@arm.comBaseCPU::BaseCPU(Params *p, bool is_checker) 12810190Sakash.bagdia@arm.com : MemObject(p), instCnt(0), _cpuId(p->cpu_id), _socketId(p->socket_id), 1298832SAli.Saidi@ARM.com _instMasterId(p->system->getMasterId(name() + ".inst")), 1308832SAli.Saidi@ARM.com _dataMasterId(p->system->getMasterId(name() + ".data")), 13111050Sandreas.hansson@arm.com _taskId(ContextSwitchTaskId::Unknown), _pid(invldPid), 1329814Sandreas.hansson@arm.com _switchedOut(p->switched_out), _cacheLineSize(p->system->cacheLineSize()), 1339220Shestness@cs.wisc.edu interrupts(p->interrupts), profileEvent(NULL), 13410529Smorr@cs.wisc.edu numThreads(p->numThreads), system(p->system), 13510537Sandreas.hansson@arm.com functionTraceStream(nullptr), currentFunctionStart(0), 13610537Sandreas.hansson@arm.com currentFunctionEnd(0), functionEntryTick(0), 13711148Smitch.hayenga@arm.com addressMonitor(p->numThreads) 1382SN/A{ 1395712Shsul@eecs.umich.edu // if Python did not provide a valid ID, do it here 1405712Shsul@eecs.umich.edu if (_cpuId == -1 ) { 1415712Shsul@eecs.umich.edu _cpuId = cpuList.size(); 1425712Shsul@eecs.umich.edu } 1435712Shsul@eecs.umich.edu 1442SN/A // add self to global list of CPUs 1452SN/A cpuList.push_back(this); 1462SN/A 14710190Sakash.bagdia@arm.com DPRINTF(SyscallVerbose, "Constructing CPU with id %d, socket id %d\n", 14810190Sakash.bagdia@arm.com _cpuId, _socketId); 1495712Shsul@eecs.umich.edu 1506221Snate@binkert.org if (numThreads > maxThreadsPerCPU) 1516221Snate@binkert.org maxThreadsPerCPU = numThreads; 1522SN/A 1532SN/A // allocate per-thread instruction-based event queues 1546221Snate@binkert.org comInstEventQueue = new EventQueue *[numThreads]; 1556221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1566221Snate@binkert.org comInstEventQueue[tid] = 1576221Snate@binkert.org new EventQueue("instruction-based event queue"); 1582SN/A 1592SN/A // 1602SN/A // set up instruction-count-based termination events, if any 1612SN/A // 1625606Snate@binkert.org if (p->max_insts_any_thread != 0) { 1635606Snate@binkert.org const char *cause = "a thread reached the max instruction count"; 1649749Sandreas@sandberg.pp.se for (ThreadID tid = 0; tid < numThreads; ++tid) 1659749Sandreas@sandberg.pp.se scheduleInstStop(tid, p->max_insts_any_thread, cause); 1665606Snate@binkert.org } 1672SN/A 1689647Sdam.sunwoo@arm.com // Set up instruction-count-based termination events for SimPoints 1699647Sdam.sunwoo@arm.com // Typically, there are more than one action points. 1709647Sdam.sunwoo@arm.com // Simulation.py is responsible to take the necessary actions upon 1719647Sdam.sunwoo@arm.com // exitting the simulation loop. 1729647Sdam.sunwoo@arm.com if (!p->simpoint_start_insts.empty()) { 1739647Sdam.sunwoo@arm.com const char *cause = "simpoint starting point found"; 1749749Sandreas@sandberg.pp.se for (size_t i = 0; i < p->simpoint_start_insts.size(); ++i) 1759749Sandreas@sandberg.pp.se scheduleInstStop(0, p->simpoint_start_insts[i], cause); 1769647Sdam.sunwoo@arm.com } 1779647Sdam.sunwoo@arm.com 1781400SN/A if (p->max_insts_all_threads != 0) { 1795606Snate@binkert.org const char *cause = "all threads reached the max instruction count"; 1805606Snate@binkert.org 1812SN/A // allocate & initialize shared downcounter: each event will 1822SN/A // decrement this when triggered; simulation will terminate 1832SN/A // when counter reaches 0 1842SN/A int *counter = new int; 1856221Snate@binkert.org *counter = numThreads; 1866221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 1875606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 1886670Shsul@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1895606Snate@binkert.org } 1902SN/A } 1912SN/A 192124SN/A // allocate per-thread load-based event queues 1936221Snate@binkert.org comLoadEventQueue = new EventQueue *[numThreads]; 1946221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) 1956221Snate@binkert.org comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 196124SN/A 197124SN/A // 198124SN/A // set up instruction-count-based termination events, if any 199124SN/A // 2005606Snate@binkert.org if (p->max_loads_any_thread != 0) { 2015606Snate@binkert.org const char *cause = "a thread reached the max load count"; 2029749Sandreas@sandberg.pp.se for (ThreadID tid = 0; tid < numThreads; ++tid) 2039749Sandreas@sandberg.pp.se scheduleLoadStop(tid, p->max_loads_any_thread, cause); 2045606Snate@binkert.org } 205124SN/A 2061400SN/A if (p->max_loads_all_threads != 0) { 2075606Snate@binkert.org const char *cause = "all threads reached the max load count"; 208124SN/A // allocate & initialize shared downcounter: each event will 209124SN/A // decrement this when triggered; simulation will terminate 210124SN/A // when counter reaches 0 211124SN/A int *counter = new int; 2126221Snate@binkert.org *counter = numThreads; 2136221Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; ++tid) { 2145606Snate@binkert.org Event *event = new CountedExitEvent(cause, *counter); 2156221Snate@binkert.org comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 2165606Snate@binkert.org } 217124SN/A } 218124SN/A 2191191SN/A functionTracingEnabled = false; 2205529Snate@binkert.org if (p->function_trace) { 2218634Schris.emmons@arm.com const string fname = csprintf("ftrace.%s", name()); 22211359Sandreas@sandberg.pp.se functionTraceStream = simout.findOrCreate(fname)->stream(); 2238634Schris.emmons@arm.com 2241191SN/A currentFunctionStart = currentFunctionEnd = 0; 2255529Snate@binkert.org functionEntryTick = p->function_trace_start; 2261191SN/A 2275529Snate@binkert.org if (p->function_trace_start == 0) { 2281191SN/A functionTracingEnabled = true; 2291191SN/A } else { 2305606Snate@binkert.org typedef EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace> wrap; 2315606Snate@binkert.org Event *event = new wrap(this, true); 2325606Snate@binkert.org schedule(event, p->function_trace_start); 2331191SN/A } 2341191SN/A } 2358876Sandreas.hansson@arm.com 2368876Sandreas.hansson@arm.com // The interrupts should always be present unless this CPU is 2378876Sandreas.hansson@arm.com // switched in later or in case it is a checker CPU 2389433SAndreas.Sandberg@ARM.com if (!params()->switched_out && !is_checker) { 23911221Sandreas.sandberg@arm.com fatal_if(interrupts.size() != numThreads, 24011221Sandreas.sandberg@arm.com "CPU %s has %i interrupt controllers, but is expecting one " 24111221Sandreas.sandberg@arm.com "per thread (%i)\n", 24211221Sandreas.sandberg@arm.com name(), interrupts.size(), numThreads); 24311221Sandreas.sandberg@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) 24411221Sandreas.sandberg@arm.com interrupts[tid]->setCPU(this); 2458876Sandreas.hansson@arm.com } 2465810Sgblack@eecs.umich.edu 2478779Sgblack@eecs.umich.edu if (FullSystem) { 2488779Sgblack@eecs.umich.edu if (params()->profile) 2498779Sgblack@eecs.umich.edu profileEvent = new ProfileEvent(this, params()->profile); 2508779Sgblack@eecs.umich.edu } 2515529Snate@binkert.org tracer = params()->tracer; 2529384SAndreas.Sandberg@arm.com 2539384SAndreas.Sandberg@arm.com if (params()->isa.size() != numThreads) { 2549384SAndreas.Sandberg@arm.com fatal("Number of ISAs (%i) assigned to the CPU does not equal number " 2559384SAndreas.Sandberg@arm.com "of threads (%i).\n", params()->isa.size(), numThreads); 2569384SAndreas.Sandberg@arm.com } 2571917SN/A} 2581191SN/A 2591191SN/Avoid 2601191SN/ABaseCPU::enableFunctionTrace() 2611191SN/A{ 2621191SN/A functionTracingEnabled = true; 2631191SN/A} 2641191SN/A 2651191SN/ABaseCPU::~BaseCPU() 2661191SN/A{ 2679086Sandreas.hansson@arm.com delete profileEvent; 2689086Sandreas.hansson@arm.com delete[] comLoadEventQueue; 2699086Sandreas.hansson@arm.com delete[] comInstEventQueue; 2701191SN/A} 2711191SN/A 2721129SN/Avoid 27311148Smitch.hayenga@arm.comBaseCPU::armMonitor(ThreadID tid, Addr address) 27410529Smorr@cs.wisc.edu{ 27511148Smitch.hayenga@arm.com assert(tid < numThreads); 27611148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 27711148Smitch.hayenga@arm.com 27811148Smitch.hayenga@arm.com monitor.armed = true; 27911148Smitch.hayenga@arm.com monitor.vAddr = address; 28011148Smitch.hayenga@arm.com monitor.pAddr = 0x0; 28111148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] Armed monitor (vAddr=0x%lx)\n", tid, address); 28210529Smorr@cs.wisc.edu} 28310529Smorr@cs.wisc.edu 28410529Smorr@cs.wisc.edubool 28511148Smitch.hayenga@arm.comBaseCPU::mwait(ThreadID tid, PacketPtr pkt) 28610529Smorr@cs.wisc.edu{ 28711148Smitch.hayenga@arm.com assert(tid < numThreads); 28811148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 28911148Smitch.hayenga@arm.com 29011325Ssteve.reinhardt@amd.com if (!monitor.gotWakeup) { 29110529Smorr@cs.wisc.edu int block_size = cacheLineSize(); 29210529Smorr@cs.wisc.edu uint64_t mask = ~((uint64_t)(block_size - 1)); 29310529Smorr@cs.wisc.edu 29410529Smorr@cs.wisc.edu assert(pkt->req->hasPaddr()); 29511148Smitch.hayenga@arm.com monitor.pAddr = pkt->getAddr() & mask; 29611148Smitch.hayenga@arm.com monitor.waiting = true; 29710529Smorr@cs.wisc.edu 29811148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, " 29911148Smitch.hayenga@arm.com "line's paddr=0x%lx)\n", tid, monitor.vAddr, monitor.pAddr); 30010529Smorr@cs.wisc.edu return true; 30110529Smorr@cs.wisc.edu } else { 30211148Smitch.hayenga@arm.com monitor.gotWakeup = false; 30310529Smorr@cs.wisc.edu return false; 30410529Smorr@cs.wisc.edu } 30510529Smorr@cs.wisc.edu} 30610529Smorr@cs.wisc.edu 30710529Smorr@cs.wisc.eduvoid 30811148Smitch.hayenga@arm.comBaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, TheISA::TLB *dtb) 30910529Smorr@cs.wisc.edu{ 31011148Smitch.hayenga@arm.com assert(tid < numThreads); 31111148Smitch.hayenga@arm.com AddressMonitor &monitor = addressMonitor[tid]; 31211148Smitch.hayenga@arm.com 31310529Smorr@cs.wisc.edu Request req; 31411148Smitch.hayenga@arm.com Addr addr = monitor.vAddr; 31510529Smorr@cs.wisc.edu int block_size = cacheLineSize(); 31610529Smorr@cs.wisc.edu uint64_t mask = ~((uint64_t)(block_size - 1)); 31710529Smorr@cs.wisc.edu int size = block_size; 31810529Smorr@cs.wisc.edu 31910529Smorr@cs.wisc.edu //The address of the next line if it crosses a cache line boundary. 32010529Smorr@cs.wisc.edu Addr secondAddr = roundDown(addr + size - 1, block_size); 32110529Smorr@cs.wisc.edu 32210529Smorr@cs.wisc.edu if (secondAddr > addr) 32310529Smorr@cs.wisc.edu size = secondAddr - addr; 32410529Smorr@cs.wisc.edu 32510529Smorr@cs.wisc.edu req.setVirt(0, addr, size, 0x0, dataMasterId(), tc->instAddr()); 32610529Smorr@cs.wisc.edu 32710529Smorr@cs.wisc.edu // translate to physical address 32810529Smorr@cs.wisc.edu Fault fault = dtb->translateAtomic(&req, tc, BaseTLB::Read); 32910529Smorr@cs.wisc.edu assert(fault == NoFault); 33010529Smorr@cs.wisc.edu 33111148Smitch.hayenga@arm.com monitor.pAddr = req.getPaddr() & mask; 33211148Smitch.hayenga@arm.com monitor.waiting = true; 33310529Smorr@cs.wisc.edu 33411148Smitch.hayenga@arm.com DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n", 33511148Smitch.hayenga@arm.com tid, monitor.vAddr, monitor.pAddr); 33610529Smorr@cs.wisc.edu} 33710529Smorr@cs.wisc.edu 33810529Smorr@cs.wisc.eduvoid 3391129SN/ABaseCPU::init() 3401129SN/A{ 3419523SAndreas.Sandberg@ARM.com if (!params()->switched_out) { 3422680Sktlim@umich.edu registerThreadContexts(); 3439523SAndreas.Sandberg@ARM.com 3449523SAndreas.Sandberg@ARM.com verifyMemoryMode(); 3459523SAndreas.Sandberg@ARM.com } 3461129SN/A} 347180SN/A 3482SN/Avoid 3491917SN/ABaseCPU::startup() 3501917SN/A{ 3518779Sgblack@eecs.umich.edu if (FullSystem) { 3529433SAndreas.Sandberg@ARM.com if (!params()->switched_out && profileEvent) 3538779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 3548779Sgblack@eecs.umich.edu } 3552356SN/A 3565529Snate@binkert.org if (params()->progress_interval) { 3579179Sandreas.hansson@arm.com new CPUProgressEvent(this, params()->progress_interval); 3582356SN/A } 35911526Sdavid.guillen@arm.com 36011526Sdavid.guillen@arm.com // Assumption CPU start to operate instantaneously without any latency 36111526Sdavid.guillen@arm.com if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED) 36211526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::ON); 36311526Sdavid.guillen@arm.com 3641917SN/A} 3651917SN/A 36610464SAndreas.Sandberg@ARM.comProbePoints::PMUUPtr 36710464SAndreas.Sandberg@ARM.comBaseCPU::pmuProbePoint(const char *name) 36810464SAndreas.Sandberg@ARM.com{ 36910464SAndreas.Sandberg@ARM.com ProbePoints::PMUUPtr ptr; 37010464SAndreas.Sandberg@ARM.com ptr.reset(new ProbePoints::PMU(getProbeManager(), name)); 37110464SAndreas.Sandberg@ARM.com 37210464SAndreas.Sandberg@ARM.com return ptr; 37310464SAndreas.Sandberg@ARM.com} 37410464SAndreas.Sandberg@ARM.com 37510464SAndreas.Sandberg@ARM.comvoid 37610464SAndreas.Sandberg@ARM.comBaseCPU::regProbePoints() 37710464SAndreas.Sandberg@ARM.com{ 37810464SAndreas.Sandberg@ARM.com ppCycles = pmuProbePoint("Cycles"); 37910464SAndreas.Sandberg@ARM.com 38010464SAndreas.Sandberg@ARM.com ppRetiredInsts = pmuProbePoint("RetiredInsts"); 38110464SAndreas.Sandberg@ARM.com ppRetiredLoads = pmuProbePoint("RetiredLoads"); 38210464SAndreas.Sandberg@ARM.com ppRetiredStores = pmuProbePoint("RetiredStores"); 38310464SAndreas.Sandberg@ARM.com ppRetiredBranches = pmuProbePoint("RetiredBranches"); 38410464SAndreas.Sandberg@ARM.com} 38510464SAndreas.Sandberg@ARM.com 38610464SAndreas.Sandberg@ARM.comvoid 38710464SAndreas.Sandberg@ARM.comBaseCPU::probeInstCommit(const StaticInstPtr &inst) 38810464SAndreas.Sandberg@ARM.com{ 38910464SAndreas.Sandberg@ARM.com if (!inst->isMicroop() || inst->isLastMicroop()) 39010464SAndreas.Sandberg@ARM.com ppRetiredInsts->notify(1); 39110464SAndreas.Sandberg@ARM.com 39210464SAndreas.Sandberg@ARM.com 39310464SAndreas.Sandberg@ARM.com if (inst->isLoad()) 39410464SAndreas.Sandberg@ARM.com ppRetiredLoads->notify(1); 39510464SAndreas.Sandberg@ARM.com 39610464SAndreas.Sandberg@ARM.com if (inst->isStore()) 39710643Snikos.nikoleris@gmail.com ppRetiredStores->notify(1); 39810464SAndreas.Sandberg@ARM.com 39910464SAndreas.Sandberg@ARM.com if (inst->isControl()) 40010464SAndreas.Sandberg@ARM.com ppRetiredBranches->notify(1); 40110464SAndreas.Sandberg@ARM.com} 4021917SN/A 4031917SN/Avoid 4042SN/ABaseCPU::regStats() 4052SN/A{ 40611522Sstephan.diestelhorst@arm.com MemObject::regStats(); 40711522Sstephan.diestelhorst@arm.com 408729SN/A using namespace Stats; 409707SN/A 410707SN/A numCycles 411707SN/A .name(name() + ".numCycles") 412707SN/A .desc("number of cpu cycles simulated") 413707SN/A ; 414707SN/A 4157914SBrad.Beckmann@amd.com numWorkItemsStarted 4167914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsStarted") 4177914SBrad.Beckmann@amd.com .desc("number of work items this cpu started") 4187914SBrad.Beckmann@amd.com ; 4197914SBrad.Beckmann@amd.com 4207914SBrad.Beckmann@amd.com numWorkItemsCompleted 4217914SBrad.Beckmann@amd.com .name(name() + ".numWorkItemsCompleted") 4227914SBrad.Beckmann@amd.com .desc("number of work items this cpu completed") 4237914SBrad.Beckmann@amd.com ; 4247914SBrad.Beckmann@amd.com 4252680Sktlim@umich.edu int size = threadContexts.size(); 4262SN/A if (size > 1) { 4272SN/A for (int i = 0; i < size; ++i) { 4282SN/A stringstream namestr; 4292SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 4302680Sktlim@umich.edu threadContexts[i]->regStats(namestr.str()); 4312SN/A } 4322SN/A } else if (size == 1) 4332680Sktlim@umich.edu threadContexts[0]->regStats(name()); 4342SN/A} 4352SN/A 4369294Sandreas.hansson@arm.comBaseMasterPort & 4379294Sandreas.hansson@arm.comBaseCPU::getMasterPort(const string &if_name, PortID idx) 4388850Sandreas.hansson@arm.com{ 4398850Sandreas.hansson@arm.com // Get the right port based on name. This applies to all the 4408850Sandreas.hansson@arm.com // subclasses of the base CPU and relies on their implementation 4418850Sandreas.hansson@arm.com // of getDataPort and getInstPort. In all cases there methods 4429608Sandreas.hansson@arm.com // return a MasterPort pointer. 4438850Sandreas.hansson@arm.com if (if_name == "dcache_port") 4448922Swilliam.wang@arm.com return getDataPort(); 4458850Sandreas.hansson@arm.com else if (if_name == "icache_port") 4468922Swilliam.wang@arm.com return getInstPort(); 4478850Sandreas.hansson@arm.com else 4488922Swilliam.wang@arm.com return MemObject::getMasterPort(if_name, idx); 4498850Sandreas.hansson@arm.com} 4508850Sandreas.hansson@arm.com 451180SN/Avoid 4522680Sktlim@umich.eduBaseCPU::registerThreadContexts() 453180SN/A{ 45411146Smitch.hayenga@arm.com assert(system->multiThread || numThreads == 1); 45511146Smitch.hayenga@arm.com 4566221Snate@binkert.org ThreadID size = threadContexts.size(); 4576221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 4586221Snate@binkert.org ThreadContext *tc = threadContexts[tid]; 4592378SN/A 46011146Smitch.hayenga@arm.com if (system->multiThread) { 46111146Smitch.hayenga@arm.com tc->setContextId(system->registerThreadContext(tc)); 46211146Smitch.hayenga@arm.com } else { 4635718Shsul@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 46411146Smitch.hayenga@arm.com } 4658779Sgblack@eecs.umich.edu 4668779Sgblack@eecs.umich.edu if (!FullSystem) 4678779Sgblack@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 468180SN/A } 469180SN/A} 470180SN/A 471180SN/A 4724000Ssaidi@eecs.umich.eduint 4734000Ssaidi@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 4744000Ssaidi@eecs.umich.edu{ 4756221Snate@binkert.org ThreadID size = threadContexts.size(); 4766221Snate@binkert.org for (ThreadID tid = 0; tid < size; ++tid) { 4776221Snate@binkert.org if (tc == threadContexts[tid]) 4786221Snate@binkert.org return tid; 4794000Ssaidi@eecs.umich.edu } 4804000Ssaidi@eecs.umich.edu return 0; 4814000Ssaidi@eecs.umich.edu} 4824000Ssaidi@eecs.umich.edu 483180SN/Avoid 48411526Sdavid.guillen@arm.comBaseCPU::activateContext(ThreadID thread_num) 48511526Sdavid.guillen@arm.com{ 48611526Sdavid.guillen@arm.com // For any active thread running, update CPU power state to active (ON) 48711526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::ON); 48811526Sdavid.guillen@arm.com} 48911526Sdavid.guillen@arm.com 49011526Sdavid.guillen@arm.comvoid 49111526Sdavid.guillen@arm.comBaseCPU::suspendContext(ThreadID thread_num) 49211526Sdavid.guillen@arm.com{ 49311526Sdavid.guillen@arm.com // Check if all threads are suspended 49411526Sdavid.guillen@arm.com for (auto t : threadContexts) { 49511526Sdavid.guillen@arm.com if (t->status() != ThreadContext::Suspended) { 49611526Sdavid.guillen@arm.com return; 49711526Sdavid.guillen@arm.com } 49811526Sdavid.guillen@arm.com } 49911526Sdavid.guillen@arm.com 50011526Sdavid.guillen@arm.com // All CPU threads suspended, enter lower power state for the CPU 50111526Sdavid.guillen@arm.com ClockedObject::pwrState(Enums::PwrState::CLK_GATED); 50211526Sdavid.guillen@arm.com} 50311526Sdavid.guillen@arm.com 50411526Sdavid.guillen@arm.comvoid 5052798Sktlim@umich.eduBaseCPU::switchOut() 506180SN/A{ 5079430SAndreas.Sandberg@ARM.com assert(!_switchedOut); 5089430SAndreas.Sandberg@ARM.com _switchedOut = true; 5092359SN/A if (profileEvent && profileEvent->scheduled()) 5105606Snate@binkert.org deschedule(profileEvent); 5119446SAndreas.Sandberg@ARM.com 5129446SAndreas.Sandberg@ARM.com // Flush all TLBs in the CPU to avoid having stale translations if 5139446SAndreas.Sandberg@ARM.com // it gets switched in later. 5149446SAndreas.Sandberg@ARM.com flushTLBs(); 515180SN/A} 516180SN/A 517180SN/Avoid 5188737Skoansin.tan@gmail.comBaseCPU::takeOverFrom(BaseCPU *oldCPU) 519180SN/A{ 5202680Sktlim@umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 5219152Satgutier@umich.edu assert(_cpuId == oldCPU->cpuId()); 5229430SAndreas.Sandberg@ARM.com assert(_switchedOut); 5239430SAndreas.Sandberg@ARM.com assert(oldCPU != this); 5249332Sdam.sunwoo@arm.com _pid = oldCPU->getPid(); 5259332Sdam.sunwoo@arm.com _taskId = oldCPU->taskId(); 5269430SAndreas.Sandberg@ARM.com _switchedOut = false; 5275712Shsul@eecs.umich.edu 5286221Snate@binkert.org ThreadID size = threadContexts.size(); 5296221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 5302680Sktlim@umich.edu ThreadContext *newTC = threadContexts[i]; 5312680Sktlim@umich.edu ThreadContext *oldTC = oldCPU->threadContexts[i]; 532180SN/A 5332680Sktlim@umich.edu newTC->takeOverFrom(oldTC); 5342651Ssaidi@eecs.umich.edu 5352680Sktlim@umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 5362651Ssaidi@eecs.umich.edu 5375714Shsul@eecs.umich.edu assert(newTC->contextId() == oldTC->contextId()); 5385715Shsul@eecs.umich.edu assert(newTC->threadId() == oldTC->threadId()); 5395714Shsul@eecs.umich.edu system->replaceThreadContext(newTC, newTC->contextId()); 5402359SN/A 5415875Ssteve.reinhardt@amd.com /* This code no longer works since the zero register (e.g., 5425875Ssteve.reinhardt@amd.com * r31 on Alpha) doesn't necessarily contain zero at this 5435875Ssteve.reinhardt@amd.com * point. 5445875Ssteve.reinhardt@amd.com if (DTRACE(Context)) 5455217Ssaidi@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 5465875Ssteve.reinhardt@amd.com */ 5477781SAli.Saidi@ARM.com 5489294Sandreas.hansson@arm.com BaseMasterPort *old_itb_port = oldTC->getITBPtr()->getMasterPort(); 5499294Sandreas.hansson@arm.com BaseMasterPort *old_dtb_port = oldTC->getDTBPtr()->getMasterPort(); 5509294Sandreas.hansson@arm.com BaseMasterPort *new_itb_port = newTC->getITBPtr()->getMasterPort(); 5519294Sandreas.hansson@arm.com BaseMasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort(); 5527781SAli.Saidi@ARM.com 5537781SAli.Saidi@ARM.com // Move over any table walker ports if they exist 5549178Sandreas.hansson@arm.com if (new_itb_port) { 5559178Sandreas.hansson@arm.com assert(!new_itb_port->isConnected()); 5567781SAli.Saidi@ARM.com assert(old_itb_port); 5579178Sandreas.hansson@arm.com assert(old_itb_port->isConnected()); 5589294Sandreas.hansson@arm.com BaseSlavePort &slavePort = old_itb_port->getSlavePort(); 5599178Sandreas.hansson@arm.com old_itb_port->unbind(); 5608922Swilliam.wang@arm.com new_itb_port->bind(slavePort); 5617781SAli.Saidi@ARM.com } 5629178Sandreas.hansson@arm.com if (new_dtb_port) { 5639178Sandreas.hansson@arm.com assert(!new_dtb_port->isConnected()); 5647781SAli.Saidi@ARM.com assert(old_dtb_port); 5659178Sandreas.hansson@arm.com assert(old_dtb_port->isConnected()); 5669294Sandreas.hansson@arm.com BaseSlavePort &slavePort = old_dtb_port->getSlavePort(); 5679178Sandreas.hansson@arm.com old_dtb_port->unbind(); 5688922Swilliam.wang@arm.com new_dtb_port->bind(slavePort); 5697781SAli.Saidi@ARM.com } 57010194SGeoffrey.Blake@arm.com newTC->getITBPtr()->takeOverFrom(oldTC->getITBPtr()); 57110194SGeoffrey.Blake@arm.com newTC->getDTBPtr()->takeOverFrom(oldTC->getDTBPtr()); 5728733Sgeoffrey.blake@arm.com 5738887Sgeoffrey.blake@arm.com // Checker whether or not we have to transfer CheckerCPU 5748887Sgeoffrey.blake@arm.com // objects over in the switch 5758887Sgeoffrey.blake@arm.com CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr(); 5768887Sgeoffrey.blake@arm.com CheckerCPU *newChecker = newTC->getCheckerCpuPtr(); 5778887Sgeoffrey.blake@arm.com if (oldChecker && newChecker) { 5789294Sandreas.hansson@arm.com BaseMasterPort *old_checker_itb_port = 5798922Swilliam.wang@arm.com oldChecker->getITBPtr()->getMasterPort(); 5809294Sandreas.hansson@arm.com BaseMasterPort *old_checker_dtb_port = 5818922Swilliam.wang@arm.com oldChecker->getDTBPtr()->getMasterPort(); 5829294Sandreas.hansson@arm.com BaseMasterPort *new_checker_itb_port = 5838922Swilliam.wang@arm.com newChecker->getITBPtr()->getMasterPort(); 5849294Sandreas.hansson@arm.com BaseMasterPort *new_checker_dtb_port = 5858922Swilliam.wang@arm.com newChecker->getDTBPtr()->getMasterPort(); 5868733Sgeoffrey.blake@arm.com 58710194SGeoffrey.Blake@arm.com newChecker->getITBPtr()->takeOverFrom(oldChecker->getITBPtr()); 58810194SGeoffrey.Blake@arm.com newChecker->getDTBPtr()->takeOverFrom(oldChecker->getDTBPtr()); 58910194SGeoffrey.Blake@arm.com 5908887Sgeoffrey.blake@arm.com // Move over any table walker ports if they exist for checker 5919178Sandreas.hansson@arm.com if (new_checker_itb_port) { 5929178Sandreas.hansson@arm.com assert(!new_checker_itb_port->isConnected()); 5938887Sgeoffrey.blake@arm.com assert(old_checker_itb_port); 5949178Sandreas.hansson@arm.com assert(old_checker_itb_port->isConnected()); 5959294Sandreas.hansson@arm.com BaseSlavePort &slavePort = 5969294Sandreas.hansson@arm.com old_checker_itb_port->getSlavePort(); 5979178Sandreas.hansson@arm.com old_checker_itb_port->unbind(); 5988922Swilliam.wang@arm.com new_checker_itb_port->bind(slavePort); 5998887Sgeoffrey.blake@arm.com } 6009178Sandreas.hansson@arm.com if (new_checker_dtb_port) { 6019178Sandreas.hansson@arm.com assert(!new_checker_dtb_port->isConnected()); 6028887Sgeoffrey.blake@arm.com assert(old_checker_dtb_port); 6039178Sandreas.hansson@arm.com assert(old_checker_dtb_port->isConnected()); 6049294Sandreas.hansson@arm.com BaseSlavePort &slavePort = 6059294Sandreas.hansson@arm.com old_checker_dtb_port->getSlavePort(); 6069178Sandreas.hansson@arm.com old_checker_dtb_port->unbind(); 6078922Swilliam.wang@arm.com new_checker_dtb_port->bind(slavePort); 6088887Sgeoffrey.blake@arm.com } 6098733Sgeoffrey.blake@arm.com } 610180SN/A } 611605SN/A 6123520Sgblack@eecs.umich.edu interrupts = oldCPU->interrupts; 61311150Smitch.hayenga@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 61411150Smitch.hayenga@arm.com interrupts[tid]->setCPU(this); 61511150Smitch.hayenga@arm.com } 61611150Smitch.hayenga@arm.com oldCPU->interrupts.clear(); 6172254SN/A 6188779Sgblack@eecs.umich.edu if (FullSystem) { 6198779Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; ++i) 6208779Sgblack@eecs.umich.edu threadContexts[i]->profileClear(); 6212254SN/A 6228779Sgblack@eecs.umich.edu if (profileEvent) 6238779Sgblack@eecs.umich.edu schedule(profileEvent, curTick()); 6248779Sgblack@eecs.umich.edu } 6254192Sktlim@umich.edu 6269178Sandreas.hansson@arm.com // All CPUs have an instruction and a data port, and the new CPU's 6279178Sandreas.hansson@arm.com // ports are dangling while the old CPU has its ports connected 6289178Sandreas.hansson@arm.com // already. Unbind the old CPU and then bind the ports of the one 6299178Sandreas.hansson@arm.com // we are switching to. 6309178Sandreas.hansson@arm.com assert(!getInstPort().isConnected()); 6319178Sandreas.hansson@arm.com assert(oldCPU->getInstPort().isConnected()); 6329294Sandreas.hansson@arm.com BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort(); 6339178Sandreas.hansson@arm.com oldCPU->getInstPort().unbind(); 6349178Sandreas.hansson@arm.com getInstPort().bind(inst_peer_port); 6354192Sktlim@umich.edu 6369178Sandreas.hansson@arm.com assert(!getDataPort().isConnected()); 6379178Sandreas.hansson@arm.com assert(oldCPU->getDataPort().isConnected()); 6389294Sandreas.hansson@arm.com BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort(); 6399178Sandreas.hansson@arm.com oldCPU->getDataPort().unbind(); 6409178Sandreas.hansson@arm.com getDataPort().bind(data_peer_port); 641180SN/A} 642180SN/A 6439446SAndreas.Sandberg@ARM.comvoid 6449446SAndreas.Sandberg@ARM.comBaseCPU::flushTLBs() 6459446SAndreas.Sandberg@ARM.com{ 6469446SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < threadContexts.size(); ++i) { 6479446SAndreas.Sandberg@ARM.com ThreadContext &tc(*threadContexts[i]); 6489446SAndreas.Sandberg@ARM.com CheckerCPU *checker(tc.getCheckerCpuPtr()); 6499446SAndreas.Sandberg@ARM.com 6509446SAndreas.Sandberg@ARM.com tc.getITBPtr()->flushAll(); 6519446SAndreas.Sandberg@ARM.com tc.getDTBPtr()->flushAll(); 6529446SAndreas.Sandberg@ARM.com if (checker) { 6539446SAndreas.Sandberg@ARM.com checker->getITBPtr()->flushAll(); 6549446SAndreas.Sandberg@ARM.com checker->getDTBPtr()->flushAll(); 6559446SAndreas.Sandberg@ARM.com } 6569446SAndreas.Sandberg@ARM.com } 6579446SAndreas.Sandberg@ARM.com} 6589446SAndreas.Sandberg@ARM.com 659180SN/A 6605536Srstrong@hp.comBaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) 6615606Snate@binkert.org : cpu(_cpu), interval(_interval) 6621917SN/A{ } 6631917SN/A 6641917SN/Avoid 6651917SN/ABaseCPU::ProfileEvent::process() 6661917SN/A{ 6676221Snate@binkert.org ThreadID size = cpu->threadContexts.size(); 6686221Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 6692680Sktlim@umich.edu ThreadContext *tc = cpu->threadContexts[i]; 6702680Sktlim@umich.edu tc->profileSample(); 6711917SN/A } 6722254SN/A 6737823Ssteve.reinhardt@amd.com cpu->schedule(this, curTick() + interval); 6741917SN/A} 6751917SN/A 6762SN/Avoid 67710905Sandreas.sandberg@arm.comBaseCPU::serialize(CheckpointOut &cp) const 678921SN/A{ 6794000Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(instCnt); 6809332Sdam.sunwoo@arm.com 6819448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 6829448SAndreas.Sandberg@ARM.com /* Unlike _pid, _taskId is not serialized, as they are dynamically 6839448SAndreas.Sandberg@ARM.com * assigned unique ids that are only meaningful for the duration of 6849448SAndreas.Sandberg@ARM.com * a specific run. We will need to serialize the entire taskMap in 6859448SAndreas.Sandberg@ARM.com * system. */ 6869448SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(_pid); 6879332Sdam.sunwoo@arm.com 6889448SAndreas.Sandberg@ARM.com // Serialize the threads, this is done by the CPU implementation. 6899448SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) { 69010905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 69111150Smitch.hayenga@arm.com interrupts[i]->serialize(cp); 69210905Sandreas.sandberg@arm.com serializeThread(cp, i); 6939448SAndreas.Sandberg@ARM.com } 6949448SAndreas.Sandberg@ARM.com } 695921SN/A} 696921SN/A 697921SN/Avoid 69810905Sandreas.sandberg@arm.comBaseCPU::unserialize(CheckpointIn &cp) 699921SN/A{ 7004000Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 7019448SAndreas.Sandberg@ARM.com 7029448SAndreas.Sandberg@ARM.com if (!_switchedOut) { 7039448SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(_pid); 7049448SAndreas.Sandberg@ARM.com 7059448SAndreas.Sandberg@ARM.com // Unserialize the threads, this is done by the CPU implementation. 70610905Sandreas.sandberg@arm.com for (ThreadID i = 0; i < numThreads; ++i) { 70710905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 70811150Smitch.hayenga@arm.com interrupts[i]->unserialize(cp); 70910905Sandreas.sandberg@arm.com unserializeThread(cp, i); 71010905Sandreas.sandberg@arm.com } 7119448SAndreas.Sandberg@ARM.com } 712921SN/A} 713921SN/A 7141191SN/Avoid 7159749Sandreas@sandberg.pp.seBaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause) 7169749Sandreas@sandberg.pp.se{ 7179749Sandreas@sandberg.pp.se const Tick now(comInstEventQueue[tid]->getCurTick()); 7189983Sstever@gmail.com Event *event(new LocalSimLoopExitEvent(cause, 0)); 7199749Sandreas@sandberg.pp.se 7209749Sandreas@sandberg.pp.se comInstEventQueue[tid]->schedule(event, now + insts); 7219749Sandreas@sandberg.pp.se} 7229749Sandreas@sandberg.pp.se 72311415SGeoffrey.Blake@arm.comuint64_t 72411415SGeoffrey.Blake@arm.comBaseCPU::getCurrentInstCount(ThreadID tid) 72511415SGeoffrey.Blake@arm.com{ 72611415SGeoffrey.Blake@arm.com return Tick(comInstEventQueue[tid]->getCurTick()); 72711415SGeoffrey.Blake@arm.com} 72811415SGeoffrey.Blake@arm.com 72910529Smorr@cs.wisc.eduAddressMonitor::AddressMonitor() { 73010529Smorr@cs.wisc.edu armed = false; 73110529Smorr@cs.wisc.edu waiting = false; 73210529Smorr@cs.wisc.edu gotWakeup = false; 73310529Smorr@cs.wisc.edu} 73410529Smorr@cs.wisc.edu 73510529Smorr@cs.wisc.edubool AddressMonitor::doMonitor(PacketPtr pkt) { 73610529Smorr@cs.wisc.edu assert(pkt->req->hasPaddr()); 73711321Ssteve.reinhardt@amd.com if (armed && waiting) { 73811321Ssteve.reinhardt@amd.com if (pAddr == pkt->getAddr()) { 73910529Smorr@cs.wisc.edu DPRINTF(Mwait,"pAddr=0x%lx invalidated: waking up core\n", 74010529Smorr@cs.wisc.edu pkt->getAddr()); 74110529Smorr@cs.wisc.edu waiting = false; 74210529Smorr@cs.wisc.edu return true; 74310529Smorr@cs.wisc.edu } 74410529Smorr@cs.wisc.edu } 74510529Smorr@cs.wisc.edu return false; 74610529Smorr@cs.wisc.edu} 74710529Smorr@cs.wisc.edu 7489749Sandreas@sandberg.pp.sevoid 7499749Sandreas@sandberg.pp.seBaseCPU::scheduleLoadStop(ThreadID tid, Counter loads, const char *cause) 7509749Sandreas@sandberg.pp.se{ 7519749Sandreas@sandberg.pp.se const Tick now(comLoadEventQueue[tid]->getCurTick()); 7529983Sstever@gmail.com Event *event(new LocalSimLoopExitEvent(cause, 0)); 7539749Sandreas@sandberg.pp.se 7549749Sandreas@sandberg.pp.se comLoadEventQueue[tid]->schedule(event, now + loads); 7559749Sandreas@sandberg.pp.se} 7569749Sandreas@sandberg.pp.se 7579749Sandreas@sandberg.pp.se 7589749Sandreas@sandberg.pp.sevoid 7591191SN/ABaseCPU::traceFunctionsInternal(Addr pc) 7601191SN/A{ 7611191SN/A if (!debugSymbolTable) 7621191SN/A return; 7631191SN/A 7641191SN/A // if pc enters different function, print new function symbol and 7651191SN/A // update saved range. Otherwise do nothing. 7661191SN/A if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 7671191SN/A string sym_str; 7681191SN/A bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 7691191SN/A currentFunctionStart, 7701191SN/A currentFunctionEnd); 7711191SN/A 7721191SN/A if (!found) { 7731191SN/A // no symbol found: use addr as label 7741191SN/A sym_str = csprintf("0x%x", pc); 7751191SN/A currentFunctionStart = pc; 7761191SN/A currentFunctionEnd = pc + 1; 7771191SN/A } 7781191SN/A 7791191SN/A ccprintf(*functionTraceStream, " (%d)\n%d: %s", 7807823Ssteve.reinhardt@amd.com curTick() - functionEntryTick, curTick(), sym_str); 7817823Ssteve.reinhardt@amd.com functionEntryTick = curTick(); 7821191SN/A } 7831191SN/A} 784