base.cc revision 13818:f0126488ef9e
18839Sandreas.hansson@arm.com/* 28839Sandreas.hansson@arm.com * Copyright (c) 2011-2012,2016-2017 ARM Limited 38839Sandreas.hansson@arm.com * All rights reserved 48839Sandreas.hansson@arm.com * 58839Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68839Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78839Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88839Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98839Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108839Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118839Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128839Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 133101Sstever@eecs.umich.edu * 148579Ssteve.reinhardt@amd.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 153101Sstever@eecs.umich.edu * Copyright (c) 2011 Regents of the University of California 163101Sstever@eecs.umich.edu * Copyright (c) 2013 Advanced Micro Devices, Inc. 173101Sstever@eecs.umich.edu * Copyright (c) 2013 Mark D. Hill and David A. Wood 183101Sstever@eecs.umich.edu * All rights reserved. 193101Sstever@eecs.umich.edu * 203101Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 213101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 223101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 233101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 243101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 253101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 263101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 273101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 283101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 293101Sstever@eecs.umich.edu * this software without specific prior written permission. 303101Sstever@eecs.umich.edu * 313101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 323101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 333101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 343101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 353101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 363101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 373101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 383101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 393101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 403101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 413101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 427778Sgblack@eecs.umich.edu * 438839Sandreas.hansson@arm.com * Authors: Steve Reinhardt 443101Sstever@eecs.umich.edu * Nathan Binkert 453101Sstever@eecs.umich.edu * Rick Strong 463101Sstever@eecs.umich.edu */ 473101Sstever@eecs.umich.edu 483101Sstever@eecs.umich.edu#include "cpu/base.hh" 493101Sstever@eecs.umich.edu 503101Sstever@eecs.umich.edu#include <iostream> 513101Sstever@eecs.umich.edu#include <sstream> 523101Sstever@eecs.umich.edu#include <string> 533101Sstever@eecs.umich.edu 543101Sstever@eecs.umich.edu#include "arch/generic/tlb.hh" 553101Sstever@eecs.umich.edu#include "base/cprintf.hh" 563101Sstever@eecs.umich.edu#include "base/loader/symtab.hh" 573101Sstever@eecs.umich.edu#include "base/logging.hh" 583101Sstever@eecs.umich.edu#include "base/output.hh" 593101Sstever@eecs.umich.edu#include "base/trace.hh" 603101Sstever@eecs.umich.edu#include "cpu/checker/cpu.hh" 613101Sstever@eecs.umich.edu#include "cpu/cpuevent.hh" 623885Sbinkertn@umich.edu#include "cpu/profile.hh" 633885Sbinkertn@umich.edu#include "cpu/thread_context.hh" 644762Snate@binkert.org#include "debug/Mwait.hh" 653885Sbinkertn@umich.edu#include "debug/SyscallVerbose.hh" 663885Sbinkertn@umich.edu#include "mem/page_table.hh" 677528Ssteve.reinhardt@amd.com#include "params/BaseCPU.hh" 683885Sbinkertn@umich.edu#include "sim/clocked_object.hh" 694380Sbinkertn@umich.edu#include "sim/full_system.hh" 704167Sbinkertn@umich.edu#include "sim/process.hh" 713102Sstever@eecs.umich.edu#include "sim/sim_events.hh" 723101Sstever@eecs.umich.edu#include "sim/sim_exit.hh" 734762Snate@binkert.org#include "sim/system.hh" 744762Snate@binkert.org 754762Snate@binkert.org// Hack 764762Snate@binkert.org#include "sim/stat_control.hh" 774762Snate@binkert.org 784762Snate@binkert.orgusing namespace std; 794762Snate@binkert.org 804762Snate@binkert.orgvector<BaseCPU *> BaseCPU::cpuList; 814762Snate@binkert.org 825033Smilesck@eecs.umich.edu// This variable reflects the max number of threads in any CPU. Be 835033Smilesck@eecs.umich.edu// careful to only use it once all the CPUs that you care about have 845033Smilesck@eecs.umich.edu// been initialized 855033Smilesck@eecs.umich.eduint maxThreadsPerCPU = 1; 865033Smilesck@eecs.umich.edu 875033Smilesck@eecs.umich.eduCPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) 885033Smilesck@eecs.umich.edu : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), 895033Smilesck@eecs.umich.edu cpu(_cpu), _repeatEvent(true) 905033Smilesck@eecs.umich.edu{ 915033Smilesck@eecs.umich.edu if (_interval) 923101Sstever@eecs.umich.edu cpu->schedule(this, curTick() + _interval); 933101Sstever@eecs.umich.edu} 943101Sstever@eecs.umich.edu 955033Smilesck@eecs.umich.eduvoid 963101Sstever@eecs.umich.eduCPUProgressEvent::process() 978596Ssteve.reinhardt@amd.com{ 988596Ssteve.reinhardt@amd.com Counter temp = cpu->totalOps(); 998596Ssteve.reinhardt@amd.com 1008596Ssteve.reinhardt@amd.com if (_repeatEvent) 1017673Snate@binkert.org cpu->schedule(this, curTick() + _interval); 1027673Snate@binkert.org 1037673Snate@binkert.org if (cpu->switchedOut()) { 1047673Snate@binkert.org return; 1058596Ssteve.reinhardt@amd.com } 1068596Ssteve.reinhardt@amd.com 1078596Ssteve.reinhardt@amd.com#ifndef NDEBUG 1087673Snate@binkert.org double ipc = double(temp - lastNumInst) / (_interval / cpu->clockPeriod()); 1097673Snate@binkert.org 1107673Snate@binkert.org DPRINTFN("%s progress event, total committed:%i, progress insts committed: " 1113101Sstever@eecs.umich.edu "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst, 1123101Sstever@eecs.umich.edu ipc); 1133101Sstever@eecs.umich.edu ipc = 0.0; 1143101Sstever@eecs.umich.edu#else 1153101Sstever@eecs.umich.edu cprintf("%lli: %s progress event, total committed:%i, progress insts " 1163101Sstever@eecs.umich.edu "committed: %lli\n", curTick(), cpu->name(), temp, 1173101Sstever@eecs.umich.edu temp - lastNumInst); 1183101Sstever@eecs.umich.edu#endif 1193101Sstever@eecs.umich.edu lastNumInst = temp; 1203101Sstever@eecs.umich.edu} 1213101Sstever@eecs.umich.edu 1223101Sstever@eecs.umich.educonst char * 1233101Sstever@eecs.umich.eduCPUProgressEvent::description() const 1243101Sstever@eecs.umich.edu{ 1253101Sstever@eecs.umich.edu return "CPU Progress"; 1263101Sstever@eecs.umich.edu} 1273101Sstever@eecs.umich.edu 1283101Sstever@eecs.umich.eduBaseCPU::BaseCPU(Params *p, bool is_checker) 1293101Sstever@eecs.umich.edu : MemObject(p), instCnt(0), _cpuId(p->cpu_id), _socketId(p->socket_id), 1303101Sstever@eecs.umich.edu _instMasterId(p->system->getMasterId(this, "inst")), 1313101Sstever@eecs.umich.edu _dataMasterId(p->system->getMasterId(this, "data")), 1323101Sstever@eecs.umich.edu _taskId(ContextSwitchTaskId::Unknown), _pid(invldPid), 1333101Sstever@eecs.umich.edu _switchedOut(p->switched_out), _cacheLineSize(p->system->cacheLineSize()), 1343101Sstever@eecs.umich.edu interrupts(p->interrupts), profileEvent(NULL), 1353101Sstever@eecs.umich.edu numThreads(p->numThreads), system(p->system), 1363101Sstever@eecs.umich.edu previousCycle(0), previousState(CPU_STATE_SLEEP), 1373101Sstever@eecs.umich.edu functionTraceStream(nullptr), currentFunctionStart(0), 1383101Sstever@eecs.umich.edu currentFunctionEnd(0), functionEntryTick(0), 1393101Sstever@eecs.umich.edu addressMonitor(p->numThreads), 1403101Sstever@eecs.umich.edu syscallRetryLatency(p->syscallRetryLatency), 1413101Sstever@eecs.umich.edu pwrGatingLatency(p->pwr_gating_latency), 1423101Sstever@eecs.umich.edu powerGatingOnIdle(p->power_gating_on_idle), 1433101Sstever@eecs.umich.edu enterPwrGatingEvent([this]{ enterPwrGating(); }, name()) 1443101Sstever@eecs.umich.edu{ 1453101Sstever@eecs.umich.edu // if Python did not provide a valid ID, do it here 1463101Sstever@eecs.umich.edu if (_cpuId == -1 ) { 1473101Sstever@eecs.umich.edu _cpuId = cpuList.size(); 1483101Sstever@eecs.umich.edu } 1493101Sstever@eecs.umich.edu 1503101Sstever@eecs.umich.edu // add self to global list of CPUs 1513101Sstever@eecs.umich.edu cpuList.push_back(this); 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu DPRINTF(SyscallVerbose, "Constructing CPU with id %d, socket id %d\n", 1543101Sstever@eecs.umich.edu _cpuId, _socketId); 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.edu if (numThreads > maxThreadsPerCPU) 1575033Smilesck@eecs.umich.edu maxThreadsPerCPU = numThreads; 1586656Snate@binkert.org 1595033Smilesck@eecs.umich.edu // allocate per-thread instruction-based event queues 1605033Smilesck@eecs.umich.edu comInstEventQueue = new EventQueue *[numThreads]; 1615033Smilesck@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) 1623101Sstever@eecs.umich.edu comInstEventQueue[tid] = 1633101Sstever@eecs.umich.edu new EventQueue("instruction-based event queue"); 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu // 1663101Sstever@eecs.umich.edu // set up instruction-count-based termination events, if any 1673101Sstever@eecs.umich.edu // 1683101Sstever@eecs.umich.edu if (p->max_insts_any_thread != 0) { 1693101Sstever@eecs.umich.edu const char *cause = "a thread reached the max instruction count"; 1703101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) 1713101Sstever@eecs.umich.edu scheduleInstStop(tid, p->max_insts_any_thread, cause); 1723101Sstever@eecs.umich.edu } 1733101Sstever@eecs.umich.edu 1743101Sstever@eecs.umich.edu // Set up instruction-count-based termination events for SimPoints 1753102Sstever@eecs.umich.edu // Typically, there are more than one action points. 1763101Sstever@eecs.umich.edu // Simulation.py is responsible to take the necessary actions upon 1773101Sstever@eecs.umich.edu // exitting the simulation loop. 1783101Sstever@eecs.umich.edu if (!p->simpoint_start_insts.empty()) { 1797673Snate@binkert.org const char *cause = "simpoint starting point found"; 1808607Sgblack@eecs.umich.edu for (size_t i = 0; i < p->simpoint_start_insts.size(); ++i) 1817673Snate@binkert.org scheduleInstStop(0, p->simpoint_start_insts[i], cause); 1823101Sstever@eecs.umich.edu } 1837673Snate@binkert.org 1847673Snate@binkert.org if (p->max_insts_all_threads != 0) { 1853101Sstever@eecs.umich.edu const char *cause = "all threads reached the max instruction count"; 1867673Snate@binkert.org 1877673Snate@binkert.org // allocate & initialize shared downcounter: each event will 1883101Sstever@eecs.umich.edu // decrement this when triggered; simulation will terminate 1893101Sstever@eecs.umich.edu // when counter reaches 0 1903101Sstever@eecs.umich.edu int *counter = new int; 1913101Sstever@eecs.umich.edu *counter = numThreads; 1923101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 1933101Sstever@eecs.umich.edu Event *event = new CountedExitEvent(cause, *counter); 1945033Smilesck@eecs.umich.edu comInstEventQueue[tid]->schedule(event, p->max_insts_all_threads); 1955475Snate@binkert.org } 1965475Snate@binkert.org } 1975475Snate@binkert.org 1985475Snate@binkert.org // allocate per-thread load-based event queues 1993101Sstever@eecs.umich.edu comLoadEventQueue = new EventQueue *[numThreads]; 2003101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) 2013101Sstever@eecs.umich.edu comLoadEventQueue[tid] = new EventQueue("load-based event queue"); 2024762Snate@binkert.org 2034762Snate@binkert.org // 2044762Snate@binkert.org // set up instruction-count-based termination events, if any 2053101Sstever@eecs.umich.edu // 2068460SAli.Saidi@ARM.com if (p->max_loads_any_thread != 0) { 2078459SAli.Saidi@ARM.com const char *cause = "a thread reached the max load count"; 2088459SAli.Saidi@ARM.com for (ThreadID tid = 0; tid < numThreads; ++tid) 2098459SAli.Saidi@ARM.com scheduleLoadStop(tid, p->max_loads_any_thread, cause); 2103101Sstever@eecs.umich.edu } 2117528Ssteve.reinhardt@amd.com 2127528Ssteve.reinhardt@amd.com if (p->max_loads_all_threads != 0) { 2137528Ssteve.reinhardt@amd.com const char *cause = "all threads reached the max load count"; 2147528Ssteve.reinhardt@amd.com // allocate & initialize shared downcounter: each event will 2157528Ssteve.reinhardt@amd.com // decrement this when triggered; simulation will terminate 2167528Ssteve.reinhardt@amd.com // when counter reaches 0 2173101Sstever@eecs.umich.edu int *counter = new int; 2187528Ssteve.reinhardt@amd.com *counter = numThreads; 2197528Ssteve.reinhardt@amd.com for (ThreadID tid = 0; tid < numThreads; ++tid) { 2207528Ssteve.reinhardt@amd.com Event *event = new CountedExitEvent(cause, *counter); 2217528Ssteve.reinhardt@amd.com comLoadEventQueue[tid]->schedule(event, p->max_loads_all_threads); 2227528Ssteve.reinhardt@amd.com } 2237528Ssteve.reinhardt@amd.com } 2247528Ssteve.reinhardt@amd.com 2257528Ssteve.reinhardt@amd.com functionTracingEnabled = false; 2267528Ssteve.reinhardt@amd.com if (p->function_trace) { 2277528Ssteve.reinhardt@amd.com const string fname = csprintf("ftrace.%s", name()); 2288321Ssteve.reinhardt@amd.com functionTraceStream = simout.findOrCreate(fname)->stream(); 2298321Ssteve.reinhardt@amd.com 2307528Ssteve.reinhardt@amd.com currentFunctionStart = currentFunctionEnd = 0; 2317528Ssteve.reinhardt@amd.com functionEntryTick = p->function_trace_start; 2327528Ssteve.reinhardt@amd.com 2337528Ssteve.reinhardt@amd.com if (p->function_trace_start == 0) { 2347528Ssteve.reinhardt@amd.com functionTracingEnabled = true; 2357528Ssteve.reinhardt@amd.com } else { 2367528Ssteve.reinhardt@amd.com Event *event = new EventFunctionWrapper( 2377528Ssteve.reinhardt@amd.com [this]{ enableFunctionTrace(); }, name(), true); 2387528Ssteve.reinhardt@amd.com schedule(event, p->function_trace_start); 2397528Ssteve.reinhardt@amd.com } 2407528Ssteve.reinhardt@amd.com } 2417528Ssteve.reinhardt@amd.com 2427528Ssteve.reinhardt@amd.com // The interrupts should always be present unless this CPU is 2433101Sstever@eecs.umich.edu // switched in later or in case it is a checker CPU 2448664SAli.Saidi@ARM.com if (!params()->switched_out && !is_checker) { 2458664SAli.Saidi@ARM.com fatal_if(interrupts.size() != numThreads, 2468664SAli.Saidi@ARM.com "CPU %s has %i interrupt controllers, but is expecting one " 2478664SAli.Saidi@ARM.com "per thread (%i)\n", 2488664SAli.Saidi@ARM.com name(), interrupts.size(), numThreads); 2498664SAli.Saidi@ARM.com for (ThreadID tid = 0; tid < numThreads; tid++) 2503101Sstever@eecs.umich.edu interrupts[tid]->setCPU(this); 2513101Sstever@eecs.umich.edu } 2523101Sstever@eecs.umich.edu 2533101Sstever@eecs.umich.edu if (FullSystem) { 2543101Sstever@eecs.umich.edu if (params()->profile) 2553101Sstever@eecs.umich.edu profileEvent = new EventFunctionWrapper( 2563101Sstever@eecs.umich.edu [this]{ processProfileEvent(); }, 2573101Sstever@eecs.umich.edu name()); 2584762Snate@binkert.org } 2594762Snate@binkert.org tracer = params()->tracer; 2604762Snate@binkert.org 2614762Snate@binkert.org if (params()->isa.size() != numThreads) { 2627528Ssteve.reinhardt@amd.com fatal("Number of ISAs (%i) assigned to the CPU does not equal number " 2634762Snate@binkert.org "of threads (%i).\n", params()->isa.size(), numThreads); 2644762Snate@binkert.org } 2654762Snate@binkert.org} 2668596Ssteve.reinhardt@amd.com 2678596Ssteve.reinhardt@amd.comvoid 2688596Ssteve.reinhardt@amd.comBaseCPU::enableFunctionTrace() 2697673Snate@binkert.org{ 2708596Ssteve.reinhardt@amd.com functionTracingEnabled = true; 2714762Snate@binkert.org} 2727673Snate@binkert.org 2738596Ssteve.reinhardt@amd.comBaseCPU::~BaseCPU() 2747675Snate@binkert.org{ 2757675Snate@binkert.org delete profileEvent; 2767675Snate@binkert.org delete[] comLoadEventQueue; 2777675Snate@binkert.org delete[] comInstEventQueue; 2788656Sandreas.hansson@arm.com} 2798656Sandreas.hansson@arm.com 2808656Sandreas.hansson@arm.comvoid 2817675Snate@binkert.orgBaseCPU::armMonitor(ThreadID tid, Addr address) 2827675Snate@binkert.org{ 2837673Snate@binkert.org assert(tid < numThreads); 2847675Snate@binkert.org AddressMonitor &monitor = addressMonitor[tid]; 2857675Snate@binkert.org 2867675Snate@binkert.org monitor.armed = true; 2877675Snate@binkert.org monitor.vAddr = address; 2887675Snate@binkert.org monitor.pAddr = 0x0; 2897673Snate@binkert.org DPRINTF(Mwait,"[tid:%d] Armed monitor (vAddr=0x%lx)\n", tid, address); 2907675Snate@binkert.org} 2917675Snate@binkert.org 2927675Snate@binkert.orgbool 2937675Snate@binkert.orgBaseCPU::mwait(ThreadID tid, PacketPtr pkt) 2947675Snate@binkert.org{ 2957675Snate@binkert.org assert(tid < numThreads); 2967675Snate@binkert.org AddressMonitor &monitor = addressMonitor[tid]; 2977675Snate@binkert.org 2987675Snate@binkert.org if (!monitor.gotWakeup) { 2997675Snate@binkert.org int block_size = cacheLineSize(); 3007675Snate@binkert.org uint64_t mask = ~((uint64_t)(block_size - 1)); 3017675Snate@binkert.org 3027675Snate@binkert.org assert(pkt->req->hasPaddr()); 3037675Snate@binkert.org monitor.pAddr = pkt->getAddr() & mask; 3047675Snate@binkert.org monitor.waiting = true; 3057675Snate@binkert.org 3067673Snate@binkert.org DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, " 3077673Snate@binkert.org "line's paddr=0x%lx)\n", tid, monitor.vAddr, monitor.pAddr); 3083101Sstever@eecs.umich.edu return true; 3097675Snate@binkert.org } else { 3107675Snate@binkert.org monitor.gotWakeup = false; 3117673Snate@binkert.org return false; 3127673Snate@binkert.org } 3137673Snate@binkert.org} 3143101Sstever@eecs.umich.edu 3157673Snate@binkert.orgvoid 3167673Snate@binkert.orgBaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseTLB *dtb) 3173101Sstever@eecs.umich.edu{ 3183101Sstever@eecs.umich.edu assert(tid < numThreads); 3193101Sstever@eecs.umich.edu AddressMonitor &monitor = addressMonitor[tid]; 3203101Sstever@eecs.umich.edu 3213101Sstever@eecs.umich.edu RequestPtr req = std::make_shared<Request>(); 3223101Sstever@eecs.umich.edu 3233101Sstever@eecs.umich.edu Addr addr = monitor.vAddr; 3243101Sstever@eecs.umich.edu int block_size = cacheLineSize(); 3253101Sstever@eecs.umich.edu uint64_t mask = ~((uint64_t)(block_size - 1)); 3263101Sstever@eecs.umich.edu int size = block_size; 3273101Sstever@eecs.umich.edu 3283101Sstever@eecs.umich.edu //The address of the next line if it crosses a cache line boundary. 3293101Sstever@eecs.umich.edu Addr secondAddr = roundDown(addr + size - 1, block_size); 3303101Sstever@eecs.umich.edu 3313101Sstever@eecs.umich.edu if (secondAddr > addr) 3325033Smilesck@eecs.umich.edu size = secondAddr - addr; 3335033Smilesck@eecs.umich.edu 3343101Sstever@eecs.umich.edu req->setVirt(0, addr, size, 0x0, dataMasterId(), tc->instAddr()); 3353101Sstever@eecs.umich.edu 3363101Sstever@eecs.umich.edu // translate to physical address 3373101Sstever@eecs.umich.edu Fault fault = dtb->translateAtomic(req, tc, BaseTLB::Read); 3383101Sstever@eecs.umich.edu assert(fault == NoFault); 3393101Sstever@eecs.umich.edu 3403101Sstever@eecs.umich.edu monitor.pAddr = req->getPaddr() & mask; 3413101Sstever@eecs.umich.edu monitor.waiting = true; 3423101Sstever@eecs.umich.edu 3433101Sstever@eecs.umich.edu DPRINTF(Mwait,"[tid:%d] mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n", 3443101Sstever@eecs.umich.edu tid, monitor.vAddr, monitor.pAddr); 3453101Sstever@eecs.umich.edu} 3463101Sstever@eecs.umich.edu 3473101Sstever@eecs.umich.eduvoid 3483101Sstever@eecs.umich.eduBaseCPU::init() 3493101Sstever@eecs.umich.edu{ 3503101Sstever@eecs.umich.edu if (!params()->switched_out) { 3513101Sstever@eecs.umich.edu registerThreadContexts(); 3523101Sstever@eecs.umich.edu 3533101Sstever@eecs.umich.edu verifyMemoryMode(); 3543101Sstever@eecs.umich.edu } 3553101Sstever@eecs.umich.edu} 3563101Sstever@eecs.umich.edu 3573101Sstever@eecs.umich.eduvoid 3583101Sstever@eecs.umich.eduBaseCPU::startup() 3597673Snate@binkert.org{ 3607673Snate@binkert.org if (FullSystem) { 3617673Snate@binkert.org if (!params()->switched_out && profileEvent) 3627673Snate@binkert.org schedule(profileEvent, curTick()); 3637673Snate@binkert.org } 3647673Snate@binkert.org 3657673Snate@binkert.org if (params()->progress_interval) { 3667673Snate@binkert.org new CPUProgressEvent(this, params()->progress_interval); 3674762Snate@binkert.org } 3684762Snate@binkert.org 3694762Snate@binkert.org if (_switchedOut) 3703101Sstever@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::OFF); 3713101Sstever@eecs.umich.edu 3723101Sstever@eecs.umich.edu // Assumption CPU start to operate instantaneously without any latency 3733101Sstever@eecs.umich.edu if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED) 3743101Sstever@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::ON); 3753101Sstever@eecs.umich.edu 3763101Sstever@eecs.umich.edu} 3773101Sstever@eecs.umich.edu 3783101Sstever@eecs.umich.eduProbePoints::PMUUPtr 3793101Sstever@eecs.umich.eduBaseCPU::pmuProbePoint(const char *name) 3803101Sstever@eecs.umich.edu{ 3813714Sstever@eecs.umich.edu ProbePoints::PMUUPtr ptr; 3823714Sstever@eecs.umich.edu ptr.reset(new ProbePoints::PMU(getProbeManager(), name)); 3833714Sstever@eecs.umich.edu 3843714Sstever@eecs.umich.edu return ptr; 3853714Sstever@eecs.umich.edu} 3863714Sstever@eecs.umich.edu 3873101Sstever@eecs.umich.eduvoid 3883101Sstever@eecs.umich.eduBaseCPU::regProbePoints() 3893101Sstever@eecs.umich.edu{ 3903101Sstever@eecs.umich.edu ppAllCycles = pmuProbePoint("Cycles"); 3913101Sstever@eecs.umich.edu ppActiveCycles = pmuProbePoint("ActiveCycles"); 3923101Sstever@eecs.umich.edu 3933101Sstever@eecs.umich.edu ppRetiredInsts = pmuProbePoint("RetiredInsts"); 3943101Sstever@eecs.umich.edu ppRetiredInstsPC = pmuProbePoint("RetiredInstsPC"); 3953101Sstever@eecs.umich.edu ppRetiredLoads = pmuProbePoint("RetiredLoads"); 3963101Sstever@eecs.umich.edu ppRetiredStores = pmuProbePoint("RetiredStores"); 3973101Sstever@eecs.umich.edu ppRetiredBranches = pmuProbePoint("RetiredBranches"); 3983101Sstever@eecs.umich.edu 3993101Sstever@eecs.umich.edu ppSleeping = new ProbePointArg<bool>(this->getProbeManager(), 4003101Sstever@eecs.umich.edu "Sleeping"); 4013101Sstever@eecs.umich.edu} 4023101Sstever@eecs.umich.edu 4033101Sstever@eecs.umich.eduvoid 4043101Sstever@eecs.umich.eduBaseCPU::probeInstCommit(const StaticInstPtr &inst, Addr pc) 4053101Sstever@eecs.umich.edu{ 4063101Sstever@eecs.umich.edu if (!inst->isMicroop() || inst->isLastMicroop()) { 4073101Sstever@eecs.umich.edu ppRetiredInsts->notify(1); 4083101Sstever@eecs.umich.edu ppRetiredInstsPC->notify(pc); 4093101Sstever@eecs.umich.edu } 4103101Sstever@eecs.umich.edu 4113101Sstever@eecs.umich.edu if (inst->isLoad()) 4125033Smilesck@eecs.umich.edu ppRetiredLoads->notify(1); 4133101Sstever@eecs.umich.edu 4143101Sstever@eecs.umich.edu if (inst->isStore() || inst->isAtomic()) 4153101Sstever@eecs.umich.edu ppRetiredStores->notify(1); 4163101Sstever@eecs.umich.edu 4173101Sstever@eecs.umich.edu if (inst->isControl()) 4183101Sstever@eecs.umich.edu ppRetiredBranches->notify(1); 4193101Sstever@eecs.umich.edu} 4203101Sstever@eecs.umich.edu 4213101Sstever@eecs.umich.eduvoid 4223101Sstever@eecs.umich.eduBaseCPU::regStats() 4233101Sstever@eecs.umich.edu{ 4243101Sstever@eecs.umich.edu MemObject::regStats(); 4255822Ssaidi@eecs.umich.edu 4265822Ssaidi@eecs.umich.edu using namespace Stats; 4273101Sstever@eecs.umich.edu 4283101Sstever@eecs.umich.edu numCycles 4293101Sstever@eecs.umich.edu .name(name() + ".numCycles") 4303101Sstever@eecs.umich.edu .desc("number of cpu cycles simulated") 4313101Sstever@eecs.umich.edu ; 4323101Sstever@eecs.umich.edu 4333101Sstever@eecs.umich.edu numWorkItemsStarted 4343101Sstever@eecs.umich.edu .name(name() + ".numWorkItemsStarted") 4353101Sstever@eecs.umich.edu .desc("number of work items this cpu started") 4363101Sstever@eecs.umich.edu ; 4373101Sstever@eecs.umich.edu 4383101Sstever@eecs.umich.edu numWorkItemsCompleted 4393101Sstever@eecs.umich.edu .name(name() + ".numWorkItemsCompleted") 4403101Sstever@eecs.umich.edu .desc("number of work items this cpu completed") 4413101Sstever@eecs.umich.edu ; 4423101Sstever@eecs.umich.edu 4433101Sstever@eecs.umich.edu int size = threadContexts.size(); 4443101Sstever@eecs.umich.edu if (size > 1) { 4453101Sstever@eecs.umich.edu for (int i = 0; i < size; ++i) { 4463101Sstever@eecs.umich.edu stringstream namestr; 4473101Sstever@eecs.umich.edu ccprintf(namestr, "%s.ctx%d", name(), i); 4483102Sstever@eecs.umich.edu threadContexts[i]->regStats(namestr.str()); 4493714Sstever@eecs.umich.edu } 4503101Sstever@eecs.umich.edu } else if (size == 1) 4513714Sstever@eecs.umich.edu threadContexts[0]->regStats(name()); 4523714Sstever@eecs.umich.edu} 4533714Sstever@eecs.umich.edu 4543101Sstever@eecs.umich.eduPort & 4553101Sstever@eecs.umich.eduBaseCPU::getPort(const string &if_name, PortID idx) 4567673Snate@binkert.org{ 4577673Snate@binkert.org // Get the right port based on name. This applies to all the 4587673Snate@binkert.org // subclasses of the base CPU and relies on their implementation 4597673Snate@binkert.org // of getDataPort and getInstPort. 4607673Snate@binkert.org if (if_name == "dcache_port") 4617673Snate@binkert.org return getDataPort(); 4627673Snate@binkert.org else if (if_name == "icache_port") 4637673Snate@binkert.org return getInstPort(); 4647673Snate@binkert.org else 4657673Snate@binkert.org return MemObject::getPort(if_name, idx); 4667673Snate@binkert.org} 4674762Snate@binkert.org 4684762Snate@binkert.orgvoid 4694762Snate@binkert.orgBaseCPU::registerThreadContexts() 4703101Sstever@eecs.umich.edu{ 4713101Sstever@eecs.umich.edu assert(system->multiThread || numThreads == 1); 4723101Sstever@eecs.umich.edu 4733101Sstever@eecs.umich.edu ThreadID size = threadContexts.size(); 4743101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < size; ++tid) { 4753101Sstever@eecs.umich.edu ThreadContext *tc = threadContexts[tid]; 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu if (system->multiThread) { 4783101Sstever@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc)); 4793101Sstever@eecs.umich.edu } else { 4803101Sstever@eecs.umich.edu tc->setContextId(system->registerThreadContext(tc, _cpuId)); 4813101Sstever@eecs.umich.edu } 4823101Sstever@eecs.umich.edu 4833101Sstever@eecs.umich.edu if (!FullSystem) 4843101Sstever@eecs.umich.edu tc->getProcessPtr()->assignThreadContext(tc->contextId()); 4853101Sstever@eecs.umich.edu } 4863101Sstever@eecs.umich.edu} 4873101Sstever@eecs.umich.edu 4883101Sstever@eecs.umich.eduvoid 4899184Sandreas.hansson@arm.comBaseCPU::deschedulePowerGatingEvent() 4909184Sandreas.hansson@arm.com{ 4919184Sandreas.hansson@arm.com if (enterPwrGatingEvent.scheduled()){ 4929184Sandreas.hansson@arm.com deschedule(enterPwrGatingEvent); 4939184Sandreas.hansson@arm.com } 4949184Sandreas.hansson@arm.com} 4959184Sandreas.hansson@arm.com 4969184Sandreas.hansson@arm.comvoid 4979184Sandreas.hansson@arm.comBaseCPU::schedulePowerGatingEvent() 4983101Sstever@eecs.umich.edu{ 4994446Sbinkertn@umich.edu for (auto tc : threadContexts) { 5003101Sstever@eecs.umich.edu if (tc->status() == ThreadContext::Active) 5015468Snate@binkert.org return; 5025468Snate@binkert.org } 5035468Snate@binkert.org 5045468Snate@binkert.org if (ClockedObject::pwrState() == Enums::PwrState::CLK_GATED && 5055468Snate@binkert.org powerGatingOnIdle) { 5065468Snate@binkert.org assert(!enterPwrGatingEvent.scheduled()); 5075468Snate@binkert.org // Schedule a power gating event when clock gated for the specified 5084762Snate@binkert.org // amount of time 5094762Snate@binkert.org schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); 5104762Snate@binkert.org } 5113101Sstever@eecs.umich.edu} 5123101Sstever@eecs.umich.edu 5133101Sstever@eecs.umich.eduint 5143101Sstever@eecs.umich.eduBaseCPU::findContext(ThreadContext *tc) 5153101Sstever@eecs.umich.edu{ 5163101Sstever@eecs.umich.edu ThreadID size = threadContexts.size(); 5173101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < size; ++tid) { 5183101Sstever@eecs.umich.edu if (tc == threadContexts[tid]) 5193102Sstever@eecs.umich.edu return tid; 5203101Sstever@eecs.umich.edu } 5213101Sstever@eecs.umich.edu return 0; 5223101Sstever@eecs.umich.edu} 5234168Sbinkertn@umich.edu 5243101Sstever@eecs.umich.eduvoid 5253101Sstever@eecs.umich.eduBaseCPU::activateContext(ThreadID thread_num) 5263101Sstever@eecs.umich.edu{ 5273101Sstever@eecs.umich.edu // Squash enter power gating event while cpu gets activated 5283101Sstever@eecs.umich.edu if (enterPwrGatingEvent.scheduled()) 5293101Sstever@eecs.umich.edu deschedule(enterPwrGatingEvent); 5303102Sstever@eecs.umich.edu // For any active thread running, update CPU power state to active (ON) 5313101Sstever@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::ON); 5323101Sstever@eecs.umich.edu 5333101Sstever@eecs.umich.edu updateCycleCounters(CPU_STATE_WAKEUP); 5343101Sstever@eecs.umich.edu} 5353101Sstever@eecs.umich.edu 5363101Sstever@eecs.umich.eduvoid 5373101Sstever@eecs.umich.eduBaseCPU::suspendContext(ThreadID thread_num) 5383101Sstever@eecs.umich.edu{ 5393101Sstever@eecs.umich.edu // Check if all threads are suspended 5403101Sstever@eecs.umich.edu for (auto t : threadContexts) { 5413101Sstever@eecs.umich.edu if (t->status() != ThreadContext::Suspended) { 5423102Sstever@eecs.umich.edu return; 5433101Sstever@eecs.umich.edu } 5443101Sstever@eecs.umich.edu } 5453101Sstever@eecs.umich.edu 5463584Ssaidi@eecs.umich.edu // All CPU thread are suspended, update cycle count 5473584Ssaidi@eecs.umich.edu updateCycleCounters(CPU_STATE_SLEEP); 5483584Ssaidi@eecs.umich.edu 5493584Ssaidi@eecs.umich.edu // All CPU threads suspended, enter lower power state for the CPU 5503584Ssaidi@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::CLK_GATED); 5513101Sstever@eecs.umich.edu 5523101Sstever@eecs.umich.edu // If pwrGatingLatency is set to 0 then this mechanism is disabled 5535033Smilesck@eecs.umich.edu if (powerGatingOnIdle) { 5543101Sstever@eecs.umich.edu // Schedule power gating event when clock gated for pwrGatingLatency 5553101Sstever@eecs.umich.edu // cycles 5563101Sstever@eecs.umich.edu schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); 5573101Sstever@eecs.umich.edu } 5583101Sstever@eecs.umich.edu} 5593101Sstever@eecs.umich.edu 5603101Sstever@eecs.umich.eduvoid 5613101Sstever@eecs.umich.eduBaseCPU::haltContext(ThreadID thread_num) 5623101Sstever@eecs.umich.edu{ 5633101Sstever@eecs.umich.edu updateCycleCounters(BaseCPU::CPU_STATE_SLEEP); 5643101Sstever@eecs.umich.edu} 5653101Sstever@eecs.umich.edu 5663101Sstever@eecs.umich.eduvoid 5673101Sstever@eecs.umich.eduBaseCPU::enterPwrGating(void) 5683101Sstever@eecs.umich.edu{ 5693101Sstever@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::OFF); 5703101Sstever@eecs.umich.edu} 5713101Sstever@eecs.umich.edu 5723101Sstever@eecs.umich.eduvoid 5733101Sstever@eecs.umich.eduBaseCPU::switchOut() 5743101Sstever@eecs.umich.edu{ 5753101Sstever@eecs.umich.edu assert(!_switchedOut); 5763101Sstever@eecs.umich.edu _switchedOut = true; 5773101Sstever@eecs.umich.edu if (profileEvent && profileEvent->scheduled()) 5783101Sstever@eecs.umich.edu deschedule(profileEvent); 5793101Sstever@eecs.umich.edu 5803101Sstever@eecs.umich.edu // Flush all TLBs in the CPU to avoid having stale translations if 5813101Sstever@eecs.umich.edu // it gets switched in later. 5823101Sstever@eecs.umich.edu flushTLBs(); 5835219Ssaidi@eecs.umich.edu 5845219Ssaidi@eecs.umich.edu // Go to the power gating state 5855219Ssaidi@eecs.umich.edu ClockedObject::pwrState(Enums::PwrState::OFF); 5863101Sstever@eecs.umich.edu} 5873101Sstever@eecs.umich.edu 5883101Sstever@eecs.umich.eduvoid 5893101Sstever@eecs.umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU) 5903101Sstever@eecs.umich.edu{ 5913101Sstever@eecs.umich.edu assert(threadContexts.size() == oldCPU->threadContexts.size()); 5923101Sstever@eecs.umich.edu assert(_cpuId == oldCPU->cpuId()); 5933101Sstever@eecs.umich.edu assert(_switchedOut); 5943101Sstever@eecs.umich.edu assert(oldCPU != this); 5953101Sstever@eecs.umich.edu _pid = oldCPU->getPid(); 5963101Sstever@eecs.umich.edu _taskId = oldCPU->taskId(); 5973101Sstever@eecs.umich.edu // Take over the power state of the switchedOut CPU 5983101Sstever@eecs.umich.edu ClockedObject::pwrState(oldCPU->pwrState()); 5993101Sstever@eecs.umich.edu 6003101Sstever@eecs.umich.edu previousState = oldCPU->previousState; 6013101Sstever@eecs.umich.edu previousCycle = oldCPU->previousCycle; 6027673Snate@binkert.org 6037673Snate@binkert.org _switchedOut = false; 6047675Snate@binkert.org 6057673Snate@binkert.org ThreadID size = threadContexts.size(); 6067675Snate@binkert.org for (ThreadID i = 0; i < size; ++i) { 6077675Snate@binkert.org ThreadContext *newTC = threadContexts[i]; 6087675Snate@binkert.org ThreadContext *oldTC = oldCPU->threadContexts[i]; 6097675Snate@binkert.org 6107675Snate@binkert.org newTC->takeOverFrom(oldTC); 6117673Snate@binkert.org 6123101Sstever@eecs.umich.edu CpuEvent::replaceThreadContext(oldTC, newTC); 6133101Sstever@eecs.umich.edu 6147673Snate@binkert.org assert(newTC->contextId() == oldTC->contextId()); 6154762Snate@binkert.org assert(newTC->threadId() == oldTC->threadId()); 6167675Snate@binkert.org system->replaceThreadContext(newTC, newTC->contextId()); 6174762Snate@binkert.org 6184762Snate@binkert.org /* This code no longer works since the zero register (e.g., 6194762Snate@binkert.org * r31 on Alpha) doesn't necessarily contain zero at this 6204762Snate@binkert.org * point. 6214762Snate@binkert.org if (DTRACE(Context)) 6223101Sstever@eecs.umich.edu ThreadContext::compare(oldTC, newTC); 6233101Sstever@eecs.umich.edu */ 6243101Sstever@eecs.umich.edu 6257673Snate@binkert.org Port *old_itb_port = oldTC->getITBPtr()->getTableWalkerPort(); 6264762Snate@binkert.org Port *old_dtb_port = oldTC->getDTBPtr()->getTableWalkerPort(); 6277675Snate@binkert.org Port *new_itb_port = newTC->getITBPtr()->getTableWalkerPort(); 6284762Snate@binkert.org Port *new_dtb_port = newTC->getDTBPtr()->getTableWalkerPort(); 6294762Snate@binkert.org 6304762Snate@binkert.org // Move over any table walker ports if they exist 6314762Snate@binkert.org if (new_itb_port) { 6324762Snate@binkert.org assert(!new_itb_port->isConnected()); 6333101Sstever@eecs.umich.edu assert(old_itb_port); 6343101Sstever@eecs.umich.edu assert(old_itb_port->isConnected()); 6353101Sstever@eecs.umich.edu auto &slavePort = 6363101Sstever@eecs.umich.edu dynamic_cast<BaseMasterPort *>(old_itb_port)->getSlavePort(); 6373101Sstever@eecs.umich.edu old_itb_port->unbind(); 6383101Sstever@eecs.umich.edu new_itb_port->bind(slavePort); 6393101Sstever@eecs.umich.edu } 6403101Sstever@eecs.umich.edu if (new_dtb_port) { 6413102Sstever@eecs.umich.edu assert(!new_dtb_port->isConnected()); 6423101Sstever@eecs.umich.edu assert(old_dtb_port); 6433101Sstever@eecs.umich.edu assert(old_dtb_port->isConnected()); 6443101Sstever@eecs.umich.edu auto &slavePort = 6454762Snate@binkert.org dynamic_cast<BaseMasterPort *>(old_dtb_port)->getSlavePort(); 6464762Snate@binkert.org old_dtb_port->unbind(); 6474762Snate@binkert.org new_dtb_port->bind(slavePort); 6483101Sstever@eecs.umich.edu } 6493101Sstever@eecs.umich.edu newTC->getITBPtr()->takeOverFrom(oldTC->getITBPtr()); 6503101Sstever@eecs.umich.edu newTC->getDTBPtr()->takeOverFrom(oldTC->getDTBPtr()); 6518934SBrad.Beckmann@amd.com 6528934SBrad.Beckmann@amd.com // Checker whether or not we have to transfer CheckerCPU 6538934SBrad.Beckmann@amd.com // objects over in the switch 6548934SBrad.Beckmann@amd.com CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr(); 6558934SBrad.Beckmann@amd.com CheckerCPU *newChecker = newTC->getCheckerCpuPtr(); 6563101Sstever@eecs.umich.edu if (oldChecker && newChecker) { 6573101Sstever@eecs.umich.edu Port *old_checker_itb_port = 6583101Sstever@eecs.umich.edu oldChecker->getITBPtr()->getTableWalkerPort(); 6593101Sstever@eecs.umich.edu Port *old_checker_dtb_port = 6603101Sstever@eecs.umich.edu oldChecker->getDTBPtr()->getTableWalkerPort(); 6613101Sstever@eecs.umich.edu Port *new_checker_itb_port = 6623101Sstever@eecs.umich.edu newChecker->getITBPtr()->getTableWalkerPort(); 6633101Sstever@eecs.umich.edu Port *new_checker_dtb_port = 6643101Sstever@eecs.umich.edu newChecker->getDTBPtr()->getTableWalkerPort(); 6653101Sstever@eecs.umich.edu 6663101Sstever@eecs.umich.edu newChecker->getITBPtr()->takeOverFrom(oldChecker->getITBPtr()); 6673101Sstever@eecs.umich.edu newChecker->getDTBPtr()->takeOverFrom(oldChecker->getDTBPtr()); 6683101Sstever@eecs.umich.edu 6693101Sstever@eecs.umich.edu // Move over any table walker ports if they exist for checker 6703101Sstever@eecs.umich.edu if (new_checker_itb_port) { 6713101Sstever@eecs.umich.edu assert(!new_checker_itb_port->isConnected()); 6723101Sstever@eecs.umich.edu assert(old_checker_itb_port); 6734380Sbinkertn@umich.edu assert(old_checker_itb_port->isConnected()); 6744380Sbinkertn@umich.edu auto &slavePort = 6754380Sbinkertn@umich.edu dynamic_cast<BaseMasterPort *>(old_checker_itb_port)-> 6763101Sstever@eecs.umich.edu getSlavePort(); 6774380Sbinkertn@umich.edu old_checker_itb_port->unbind(); 6784380Sbinkertn@umich.edu new_checker_itb_port->bind(slavePort); 6794380Sbinkertn@umich.edu } 6803101Sstever@eecs.umich.edu if (new_checker_dtb_port) { 6813101Sstever@eecs.umich.edu assert(!new_checker_dtb_port->isConnected()); 6823101Sstever@eecs.umich.edu assert(old_checker_dtb_port); 6837673Snate@binkert.org assert(old_checker_dtb_port->isConnected()); 6847673Snate@binkert.org auto &slavePort = 6857673Snate@binkert.org dynamic_cast<BaseMasterPort *>(old_checker_dtb_port)-> 6867673Snate@binkert.org getSlavePort(); 6877673Snate@binkert.org old_checker_dtb_port->unbind(); 6887673Snate@binkert.org new_checker_dtb_port->bind(slavePort); 6897673Snate@binkert.org } 6907673Snate@binkert.org } 6917673Snate@binkert.org } 6923101Sstever@eecs.umich.edu 6933101Sstever@eecs.umich.edu interrupts = oldCPU->interrupts; 6943101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 6953101Sstever@eecs.umich.edu interrupts[tid]->setCPU(this); 6963101Sstever@eecs.umich.edu } 6973101Sstever@eecs.umich.edu oldCPU->interrupts.clear(); 6983101Sstever@eecs.umich.edu 6993101Sstever@eecs.umich.edu if (FullSystem) { 7003101Sstever@eecs.umich.edu for (ThreadID i = 0; i < size; ++i) 7013101Sstever@eecs.umich.edu threadContexts[i]->profileClear(); 7023101Sstever@eecs.umich.edu 7033101Sstever@eecs.umich.edu if (profileEvent) 7043101Sstever@eecs.umich.edu schedule(profileEvent, curTick()); 7057743Sgblack@eecs.umich.edu } 7063101Sstever@eecs.umich.edu 7073101Sstever@eecs.umich.edu // All CPUs have an instruction and a data port, and the new CPU's 7083101Sstever@eecs.umich.edu // ports are dangling while the old CPU has its ports connected 7093101Sstever@eecs.umich.edu // already. Unbind the old CPU and then bind the ports of the one 7103101Sstever@eecs.umich.edu // we are switching to. 7113101Sstever@eecs.umich.edu assert(!getInstPort().isConnected()); 7124380Sbinkertn@umich.edu assert(oldCPU->getInstPort().isConnected()); 7133101Sstever@eecs.umich.edu auto &inst_peer_port = 7143101Sstever@eecs.umich.edu dynamic_cast<BaseMasterPort &>(oldCPU->getInstPort()).getSlavePort(); 7154762Snate@binkert.org oldCPU->getInstPort().unbind(); 7167677Snate@binkert.org getInstPort().bind(inst_peer_port); 7174762Snate@binkert.org 7184762Snate@binkert.org assert(!getDataPort().isConnected()); 7194380Sbinkertn@umich.edu assert(oldCPU->getDataPort().isConnected()); 7204380Sbinkertn@umich.edu auto &data_peer_port = 7213101Sstever@eecs.umich.edu dynamic_cast<BaseMasterPort &>(oldCPU->getDataPort()).getSlavePort(); 7227777Sgblack@eecs.umich.edu oldCPU->getDataPort().unbind(); 7237777Sgblack@eecs.umich.edu getDataPort().bind(data_peer_port); 7247777Sgblack@eecs.umich.edu} 7257777Sgblack@eecs.umich.edu 7267777Sgblack@eecs.umich.eduvoid 7277777Sgblack@eecs.umich.eduBaseCPU::flushTLBs() 7287777Sgblack@eecs.umich.edu{ 7297777Sgblack@eecs.umich.edu for (ThreadID i = 0; i < threadContexts.size(); ++i) { 7307777Sgblack@eecs.umich.edu ThreadContext &tc(*threadContexts[i]); 7317777Sgblack@eecs.umich.edu CheckerCPU *checker(tc.getCheckerCpuPtr()); 7327777Sgblack@eecs.umich.edu 7337777Sgblack@eecs.umich.edu tc.getITBPtr()->flushAll(); 7347777Sgblack@eecs.umich.edu tc.getDTBPtr()->flushAll(); 7357777Sgblack@eecs.umich.edu if (checker) { 7367777Sgblack@eecs.umich.edu checker->getITBPtr()->flushAll(); 7377777Sgblack@eecs.umich.edu checker->getDTBPtr()->flushAll(); 7387777Sgblack@eecs.umich.edu } 7397777Sgblack@eecs.umich.edu } 7407777Sgblack@eecs.umich.edu} 7417777Sgblack@eecs.umich.edu 7427777Sgblack@eecs.umich.eduvoid 7437777Sgblack@eecs.umich.eduBaseCPU::processProfileEvent() 7447777Sgblack@eecs.umich.edu{ 7458579Ssteve.reinhardt@amd.com ThreadID size = threadContexts.size(); 7468579Ssteve.reinhardt@amd.com 7478579Ssteve.reinhardt@amd.com for (ThreadID i = 0; i < size; ++i) 7488579Ssteve.reinhardt@amd.com threadContexts[i]->profileSample(); 7498579Ssteve.reinhardt@amd.com 7508579Ssteve.reinhardt@amd.com schedule(profileEvent, curTick() + params()->profile); 7518579Ssteve.reinhardt@amd.com} 7528579Ssteve.reinhardt@amd.com 7538579Ssteve.reinhardt@amd.comvoid 7548579Ssteve.reinhardt@amd.comBaseCPU::serialize(CheckpointOut &cp) const 7558579Ssteve.reinhardt@amd.com{ 7568579Ssteve.reinhardt@amd.com SERIALIZE_SCALAR(instCnt); 7578579Ssteve.reinhardt@amd.com 7588579Ssteve.reinhardt@amd.com if (!_switchedOut) { 7598579Ssteve.reinhardt@amd.com /* Unlike _pid, _taskId is not serialized, as they are dynamically 7608579Ssteve.reinhardt@amd.com * assigned unique ids that are only meaningful for the duration of 7618579Ssteve.reinhardt@amd.com * a specific run. We will need to serialize the entire taskMap in 7628579Ssteve.reinhardt@amd.com * system. */ 7637777Sgblack@eecs.umich.edu SERIALIZE_SCALAR(_pid); 7647777Sgblack@eecs.umich.edu 7657798Sgblack@eecs.umich.edu // Serialize the threads, this is done by the CPU implementation. 7667777Sgblack@eecs.umich.edu for (ThreadID i = 0; i < numThreads; ++i) { 7677777Sgblack@eecs.umich.edu ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 7687777Sgblack@eecs.umich.edu interrupts[i]->serialize(cp); 7697777Sgblack@eecs.umich.edu serializeThread(cp, i); 7707777Sgblack@eecs.umich.edu } 7717777Sgblack@eecs.umich.edu } 7727777Sgblack@eecs.umich.edu} 7737777Sgblack@eecs.umich.edu 7747777Sgblack@eecs.umich.eduvoid 7757777Sgblack@eecs.umich.eduBaseCPU::unserialize(CheckpointIn &cp) 7767777Sgblack@eecs.umich.edu{ 7777777Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(instCnt); 7787777Sgblack@eecs.umich.edu 7797777Sgblack@eecs.umich.edu if (!_switchedOut) { 7807777Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(_pid); 7817777Sgblack@eecs.umich.edu 7827777Sgblack@eecs.umich.edu // Unserialize the threads, this is done by the CPU implementation. 7837777Sgblack@eecs.umich.edu for (ThreadID i = 0; i < numThreads; ++i) { 7847777Sgblack@eecs.umich.edu ScopedCheckpointSection sec(cp, csprintf("xc.%i", i)); 7857777Sgblack@eecs.umich.edu interrupts[i]->unserialize(cp); 7867777Sgblack@eecs.umich.edu unserializeThread(cp, i); 7877777Sgblack@eecs.umich.edu } 7887777Sgblack@eecs.umich.edu } 7897777Sgblack@eecs.umich.edu} 7907777Sgblack@eecs.umich.edu 7917777Sgblack@eecs.umich.eduvoid 7927777Sgblack@eecs.umich.eduBaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause) 7937777Sgblack@eecs.umich.edu{ 7947777Sgblack@eecs.umich.edu const Tick now(comInstEventQueue[tid]->getCurTick()); 7957777Sgblack@eecs.umich.edu Event *event(new LocalSimLoopExitEvent(cause, 0)); 7967777Sgblack@eecs.umich.edu 7977777Sgblack@eecs.umich.edu comInstEventQueue[tid]->schedule(event, now + insts); 7987777Sgblack@eecs.umich.edu} 7997777Sgblack@eecs.umich.edu 8007777Sgblack@eecs.umich.eduuint64_t 8017777Sgblack@eecs.umich.eduBaseCPU::getCurrentInstCount(ThreadID tid) 8027777Sgblack@eecs.umich.edu{ 8037777Sgblack@eecs.umich.edu return Tick(comInstEventQueue[tid]->getCurTick()); 8047777Sgblack@eecs.umich.edu} 8057777Sgblack@eecs.umich.edu 8067777Sgblack@eecs.umich.eduAddressMonitor::AddressMonitor() { 8077777Sgblack@eecs.umich.edu armed = false; 8087777Sgblack@eecs.umich.edu waiting = false; 8097777Sgblack@eecs.umich.edu gotWakeup = false; 8107777Sgblack@eecs.umich.edu} 8117777Sgblack@eecs.umich.edu 8127777Sgblack@eecs.umich.edubool AddressMonitor::doMonitor(PacketPtr pkt) { 8137777Sgblack@eecs.umich.edu assert(pkt->req->hasPaddr()); 8147777Sgblack@eecs.umich.edu if (armed && waiting) { 8157777Sgblack@eecs.umich.edu if (pAddr == pkt->getAddr()) { 8167777Sgblack@eecs.umich.edu DPRINTF(Mwait,"pAddr=0x%lx invalidated: waking up core\n", 8177777Sgblack@eecs.umich.edu pkt->getAddr()); 8187777Sgblack@eecs.umich.edu waiting = false; 8197777Sgblack@eecs.umich.edu return true; 8207777Sgblack@eecs.umich.edu } 8218579Ssteve.reinhardt@amd.com } 8228579Ssteve.reinhardt@amd.com return false; 8238579Ssteve.reinhardt@amd.com} 8248579Ssteve.reinhardt@amd.com 8258579Ssteve.reinhardt@amd.comvoid 8268579Ssteve.reinhardt@amd.comBaseCPU::scheduleLoadStop(ThreadID tid, Counter loads, const char *cause) 8278579Ssteve.reinhardt@amd.com{ 8288579Ssteve.reinhardt@amd.com const Tick now(comLoadEventQueue[tid]->getCurTick()); 8298579Ssteve.reinhardt@amd.com Event *event(new LocalSimLoopExitEvent(cause, 0)); 8308579Ssteve.reinhardt@amd.com 8318579Ssteve.reinhardt@amd.com comLoadEventQueue[tid]->schedule(event, now + loads); 8328579Ssteve.reinhardt@amd.com} 8338579Ssteve.reinhardt@amd.com 8348579Ssteve.reinhardt@amd.com 8357777Sgblack@eecs.umich.eduvoid 8367777Sgblack@eecs.umich.eduBaseCPU::traceFunctionsInternal(Addr pc) 8377777Sgblack@eecs.umich.edu{ 8387777Sgblack@eecs.umich.edu if (!debugSymbolTable) 8397777Sgblack@eecs.umich.edu return; 8407777Sgblack@eecs.umich.edu 8417777Sgblack@eecs.umich.edu // if pc enters different function, print new function symbol and 8427777Sgblack@eecs.umich.edu // update saved range. Otherwise do nothing. 8437777Sgblack@eecs.umich.edu if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 8447777Sgblack@eecs.umich.edu string sym_str; 8457777Sgblack@eecs.umich.edu bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 8467777Sgblack@eecs.umich.edu currentFunctionStart, 8477777Sgblack@eecs.umich.edu currentFunctionEnd); 8487777Sgblack@eecs.umich.edu 8497777Sgblack@eecs.umich.edu if (!found) { 8507777Sgblack@eecs.umich.edu // no symbol found: use addr as label 8517777Sgblack@eecs.umich.edu sym_str = csprintf("0x%x", pc); 8527777Sgblack@eecs.umich.edu currentFunctionStart = pc; 8537777Sgblack@eecs.umich.edu currentFunctionEnd = pc + 1; 8547777Sgblack@eecs.umich.edu } 8557777Sgblack@eecs.umich.edu 8567777Sgblack@eecs.umich.edu ccprintf(*functionTraceStream, " (%d)\n%d: %s", 8577777Sgblack@eecs.umich.edu curTick() - functionEntryTick, curTick(), sym_str); 8587777Sgblack@eecs.umich.edu functionEntryTick = curTick(); 8597777Sgblack@eecs.umich.edu } 8607777Sgblack@eecs.umich.edu} 8617777Sgblack@eecs.umich.edu 8627777Sgblack@eecs.umich.edubool 8637777Sgblack@eecs.umich.eduBaseCPU::waitForRemoteGDB() const 8647777Sgblack@eecs.umich.edu{ 8657777Sgblack@eecs.umich.edu return params()->wait_for_remote_gdb; 8667777Sgblack@eecs.umich.edu} 8677777Sgblack@eecs.umich.edu