cpu.cc revision 14085
12SN/A/* 21762SN/A * Copyright (c) 2011-2012, 2014, 2016, 2017, 2019 ARM Limited 32SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 42SN/A * All rights reserved 52SN/A * 62SN/A * The license below extends only to copyright in the software and shall 72SN/A * not be construed as granting a license to any other intellectual 82SN/A * property including but not limited to intellectual property relating 92SN/A * to a hardware implementation of the functionality of the software 102SN/A * licensed hereunder. You may use the software subject to the license 112SN/A * terms below provided that you ensure that this notice is replicated 122SN/A * unmodified and in its entirety in all distributions of the software, 132SN/A * modified or unmodified, in source code or in binary form. 142SN/A * 152SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 162SN/A * Copyright (c) 2011 Regents of the University of California 172SN/A * All rights reserved. 182SN/A * 192SN/A * Redistribution and use in source and binary forms, with or without 202SN/A * modification, are permitted provided that the following conditions are 212SN/A * met: redistributions of source code must retain the above copyright 222SN/A * notice, this list of conditions and the following disclaimer; 232SN/A * redistributions in binary form must reproduce the above copyright 242SN/A * notice, this list of conditions and the following disclaimer in the 252SN/A * documentation and/or other materials provided with the distribution; 262SN/A * neither the name of the copyright holders nor the names of its 272665Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 282665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 292665Ssaidi@eecs.umich.edu * 302665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 312665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 322SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 332SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 342SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 352SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 363506Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 373506Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 382SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 392973Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 403584Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4156SN/A * 423614Sgblack@eecs.umich.edu * Authors: Kevin Lim 431717SN/A * Korey Sewell 442518SN/A * Rick Strong 4556SN/A */ 462518SN/A 472518SN/A#include "cpu/o3/cpu.hh" 482SN/A 493614Sgblack@eecs.umich.edu#include "arch/generic/traits.hh" 503614Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh" 513614Sgblack@eecs.umich.edu#include "config/the_isa.hh" 523614Sgblack@eecs.umich.edu#include "cpu/activity.hh" 533065Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 543065Sgblack@eecs.umich.edu#include "cpu/checker/thread_context.hh" 553506Ssaidi@eecs.umich.edu#include "cpu/o3/isa_specific.hh" 563065Sgblack@eecs.umich.edu#include "cpu/o3/thread_context.hh" 572SN/A#include "cpu/quiesce_event.hh" 582973Sgblack@eecs.umich.edu#include "cpu/simple_thread.hh" 592SN/A#include "cpu/thread_context.hh" 603840Shsul@eecs.umich.edu#include "debug/Activity.hh" 613825Ssaidi@eecs.umich.edu#include "debug/Drain.hh" 623903Ssaidi@eecs.umich.edu#include "debug/O3CPU.hh" 633840Shsul@eecs.umich.edu#include "debug/Quiesce.hh" 643825Ssaidi@eecs.umich.edu#include "enums/MemoryMode.hh" 653506Ssaidi@eecs.umich.edu#include "sim/core.hh" 663506Ssaidi@eecs.umich.edu#include "sim/full_system.hh" 673506Ssaidi@eecs.umich.edu#include "sim/process.hh" 683506Ssaidi@eecs.umich.edu#include "sim/stat_control.hh" 692SN/A#include "sim/system.hh" 702SN/A 712SN/A#if THE_ISA == ALPHA_ISA 722SN/A#include "arch/alpha/osfpal.hh" 732SN/A#include "debug/Activity.hh" 743748Sgblack@eecs.umich.edu 753748Sgblack@eecs.umich.edu#endif 763748Sgblack@eecs.umich.edu 773748Sgblack@eecs.umich.edustruct BaseCPUParams; 783748Sgblack@eecs.umich.edu 793748Sgblack@eecs.umich.eduusing namespace TheISA; 803748Sgblack@eecs.umich.eduusing namespace std; 813748Sgblack@eecs.umich.edu 823748Sgblack@eecs.umich.eduBaseO3CPU::BaseO3CPU(BaseCPUParams *params) 833748Sgblack@eecs.umich.edu : BaseCPU(params) 843748Sgblack@eecs.umich.edu{ 853748Sgblack@eecs.umich.edu} 863748Sgblack@eecs.umich.edu 873748Sgblack@eecs.umich.eduvoid 883748Sgblack@eecs.umich.eduBaseO3CPU::regStats() 893748Sgblack@eecs.umich.edu{ 903748Sgblack@eecs.umich.edu BaseCPU::regStats(); 913748Sgblack@eecs.umich.edu} 923748Sgblack@eecs.umich.edu 933748Sgblack@eecs.umich.edutemplate<class Impl> 943748Sgblack@eecs.umich.edubool 953748Sgblack@eecs.umich.eduFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 963748Sgblack@eecs.umich.edu{ 973748Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Fetch unit received timing\n"); 983748Sgblack@eecs.umich.edu // We shouldn't ever get a cacheable block in Modified state 993748Sgblack@eecs.umich.edu assert(pkt->req->isUncacheable() || 1003748Sgblack@eecs.umich.edu !(pkt->cacheResponding() && !pkt->hasSharers())); 1013748Sgblack@eecs.umich.edu fetch->processCacheCompletion(pkt); 1023748Sgblack@eecs.umich.edu 1033748Sgblack@eecs.umich.edu return true; 1043748Sgblack@eecs.umich.edu} 1053748Sgblack@eecs.umich.edu 1063748Sgblack@eecs.umich.edutemplate<class Impl> 1073748Sgblack@eecs.umich.eduvoid 1083748Sgblack@eecs.umich.eduFullO3CPU<Impl>::IcachePort::recvReqRetry() 1093748Sgblack@eecs.umich.edu{ 1103748Sgblack@eecs.umich.edu fetch->recvReqRetry(); 1113748Sgblack@eecs.umich.edu} 1123748Sgblack@eecs.umich.edu 1133748Sgblack@eecs.umich.edutemplate <class Impl> 1143748Sgblack@eecs.umich.edubool 1153748Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 1163748Sgblack@eecs.umich.edu{ 1173748Sgblack@eecs.umich.edu return lsq->recvTimingResp(pkt); 1183748Sgblack@eecs.umich.edu} 1193748Sgblack@eecs.umich.edu 1203748Sgblack@eecs.umich.edutemplate <class Impl> 1213748Sgblack@eecs.umich.eduvoid 1223748Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 1233748Sgblack@eecs.umich.edu{ 1242SN/A for (ThreadID tid = 0; tid < cpu->numThreads; tid++) { 1252SN/A if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) { 1262SN/A cpu->wakeup(tid); 1272SN/A } 1283903Ssaidi@eecs.umich.edu } 1292973Sgblack@eecs.umich.edu lsq->recvTimingSnoopReq(pkt); 1302973Sgblack@eecs.umich.edu} 1313065Sgblack@eecs.umich.edu 1323380Sgblack@eecs.umich.edutemplate <class Impl> 1333380Sgblack@eecs.umich.eduvoid 1343380Sgblack@eecs.umich.eduFullO3CPU<Impl>::DcachePort::recvReqRetry() 1353380Sgblack@eecs.umich.edu{ 1363380Sgblack@eecs.umich.edu lsq->recvReqRetry(); 1373380Sgblack@eecs.umich.edu} 1383380Sgblack@eecs.umich.edu 1393380Sgblack@eecs.umich.edutemplate <class Impl> 1403380Sgblack@eecs.umich.eduFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 1413380Sgblack@eecs.umich.edu : BaseO3CPU(params), 1423380Sgblack@eecs.umich.edu itb(params->itb), 1433380Sgblack@eecs.umich.edu dtb(params->dtb), 1443380Sgblack@eecs.umich.edu tickEvent([this]{ tick(); }, "FullO3CPU tick", 1453380Sgblack@eecs.umich.edu false, Event::CPU_Tick_Pri), 1463065Sgblack@eecs.umich.edu threadExitEvent([this]{ exitThreads(); }, "FullO3CPU exit threads", 1473588Sgblack@eecs.umich.edu false, Event::CPU_Exit_Pri), 1483588Sgblack@eecs.umich.edu#ifndef NDEBUG 1493588Sgblack@eecs.umich.edu instcount(0), 1503380Sgblack@eecs.umich.edu#endif 1513380Sgblack@eecs.umich.edu removeInstsThisCycle(false), 1523059Sgblack@eecs.umich.edu fetch(this, params), 1533588Sgblack@eecs.umich.edu decode(this, params), 1543380Sgblack@eecs.umich.edu rename(this, params), 1553380Sgblack@eecs.umich.edu iew(this, params), 1563380Sgblack@eecs.umich.edu commit(this, params), 1573380Sgblack@eecs.umich.edu 1583380Sgblack@eecs.umich.edu /* It is mandatory that all SMT threads use the same renaming mode as 1593588Sgblack@eecs.umich.edu * they are sharing registers and rename */ 1603380Sgblack@eecs.umich.edu vecMode(RenameMode<TheISA::ISA>::init(params->isa[0])), 1613380Sgblack@eecs.umich.edu regFile(params->numPhysIntRegs, 1623380Sgblack@eecs.umich.edu params->numPhysFloatRegs, 1633380Sgblack@eecs.umich.edu params->numPhysVecRegs, 1643380Sgblack@eecs.umich.edu params->numPhysVecPredRegs, 1653059Sgblack@eecs.umich.edu params->numPhysCCRegs, 1663380Sgblack@eecs.umich.edu vecMode), 1673380Sgblack@eecs.umich.edu 1683380Sgblack@eecs.umich.edu freeList(name() + ".freelist", ®File), 1693380Sgblack@eecs.umich.edu 1703588Sgblack@eecs.umich.edu rob(this, params), 1713380Sgblack@eecs.umich.edu 1723380Sgblack@eecs.umich.edu scoreboard(name() + ".scoreboard", 1733059Sgblack@eecs.umich.edu regFile.totalNumPhysRegs()), 1743059Sgblack@eecs.umich.edu 1753380Sgblack@eecs.umich.edu isa(numThreads, NULL), 1763380Sgblack@eecs.umich.edu 1773380Sgblack@eecs.umich.edu icachePort(&fetch, this), 1783380Sgblack@eecs.umich.edu dcachePort(&iew.ldstQueue, this), 1793380Sgblack@eecs.umich.edu 1803588Sgblack@eecs.umich.edu timeBuffer(params->backComSize, params->forwardComSize), 1813380Sgblack@eecs.umich.edu fetchQueue(params->backComSize, params->forwardComSize), 1823380Sgblack@eecs.umich.edu decodeQueue(params->backComSize, params->forwardComSize), 1833380Sgblack@eecs.umich.edu renameQueue(params->backComSize, params->forwardComSize), 1843588Sgblack@eecs.umich.edu iewQueue(params->backComSize, params->forwardComSize), 1853059Sgblack@eecs.umich.edu activityRec(name(), NumStages, 1863065Sgblack@eecs.umich.edu params->backComSize + params->forwardComSize, 1872973Sgblack@eecs.umich.edu params->activity), 1882973Sgblack@eecs.umich.edu 1891968SN/A globalSeqNum(1), 1903064Sgblack@eecs.umich.edu system(params->system), 1911968SN/A lastRunningCycle(curCycle()) 1921968SN/A{ 1931968SN/A if (!params->switched_out) { 1941968SN/A _status = Running; 1951967SN/A } else { 1961967SN/A _status = SwitchedOut; 1971967SN/A } 1981967SN/A 1991967SN/A if (params->checker) { 2001967SN/A BaseCPU *temp_checker = params->checker; 2011967SN/A checker = dynamic_cast<Checker<Impl> *>(temp_checker); 2021967SN/A checker->setIcachePort(&icachePort); 2031967SN/A checker->setSystem(params->system); 2041967SN/A } else { 2051904SN/A checker = NULL; 2061904SN/A } 2071904SN/A 2081904SN/A if (!FullSystem) { 209452SN/A thread.resize(numThreads); 2103064Sgblack@eecs.umich.edu tids.resize(numThreads); 2112SN/A } 2121904SN/A 2131904SN/A // The stages also need their CPU pointer setup. However this 2142SN/A // must be done at the upper level CPU because they have pointers 2151904SN/A // to the upper level CPU, and not this FullO3CPU. 2163064Sgblack@eecs.umich.edu 2172SN/A // Set up Pointers to the activeThreads list for each stage 2182SN/A fetch.setActiveThreads(&activeThreads); 2191904SN/A decode.setActiveThreads(&activeThreads); 2201904SN/A rename.setActiveThreads(&activeThreads); 2211904SN/A iew.setActiveThreads(&activeThreads); 2222299SN/A commit.setActiveThreads(&activeThreads); 2232299SN/A 2241904SN/A // Give each of the stages the time buffer they will use. 2251904SN/A fetch.setTimeBuffer(&timeBuffer); 2261904SN/A decode.setTimeBuffer(&timeBuffer); 2271904SN/A rename.setTimeBuffer(&timeBuffer); 2281904SN/A iew.setTimeBuffer(&timeBuffer); 2291904SN/A commit.setTimeBuffer(&timeBuffer); 2301904SN/A 231452SN/A // Also setup each of the stages' queues. 2321904SN/A fetch.setFetchQueue(&fetchQueue); 2331904SN/A decode.setFetchQueue(&fetchQueue); 2341904SN/A commit.setFetchQueue(&fetchQueue); 2352SN/A decode.setDecodeQueue(&decodeQueue); 2362SN/A rename.setDecodeQueue(&decodeQueue); 2371904SN/A rename.setRenameQueue(&renameQueue); 2381904SN/A iew.setRenameQueue(&renameQueue); 2391904SN/A iew.setIEWQueue(&iewQueue); 2401904SN/A commit.setIEWQueue(&iewQueue); 2411904SN/A commit.setRenameQueue(&renameQueue); 2421904SN/A 2432SN/A commit.setIEWStage(&iew); 2441904SN/A rename.setIEWStage(&iew); 2452SN/A rename.setCommitStage(&commit); 2462SN/A 2471904SN/A ThreadID active_threads; 2482SN/A if (FullSystem) { 2491904SN/A active_threads = 1; 2501904SN/A } else { 2511904SN/A active_threads = params->workload.size(); 2521904SN/A 2531904SN/A if (active_threads > Impl::MaxThreads) { 2541904SN/A panic("Workload Size too large. Increase the 'MaxThreads' " 2551904SN/A "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 2561904SN/A "or edit your workload size."); 2571904SN/A } 2581904SN/A } 2591904SN/A 2601904SN/A //Make Sure That this a Valid Architeture 2611904SN/A assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 2621904SN/A assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 2631904SN/A assert(params->numPhysVecRegs >= numThreads * TheISA::NumVecRegs); 2641904SN/A assert(params->numPhysVecPredRegs >= numThreads * TheISA::NumVecPredRegs); 2651904SN/A assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 2661904SN/A 2671904SN/A rename.setScoreboard(&scoreboard); 2681904SN/A iew.setScoreboard(&scoreboard); 2692525SN/A 2701904SN/A // Setup the rename map for whichever stages need it. 2712525SN/A for (ThreadID tid = 0; tid < numThreads; tid++) { 2722525SN/A isa[tid] = params->isa[tid]; 2732525SN/A assert(RenameMode<TheISA::ISA>::equalsInit(isa[tid], isa[0])); 2741904SN/A 2751904SN/A // Only Alpha has an FP zero register, so for other ISAs we 2761904SN/A // use an invalid FP register index to avoid special treatment 2771904SN/A // of any valid FP reg. 2781904SN/A RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 2791904SN/A RegIndex fpZeroReg = 2801904SN/A (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 2811904SN/A 2821967SN/A commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 2831967SN/A &freeList, 2841967SN/A vecMode); 2851967SN/A 2861967SN/A renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 2872SN/A &freeList, vecMode); 2883817Ssaidi@eecs.umich.edu } 2893506Ssaidi@eecs.umich.edu 2903506Ssaidi@eecs.umich.edu // Initialize rename map to assign physical registers to the 2913506Ssaidi@eecs.umich.edu // architectural registers for active threads only. 2923506Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < active_threads; tid++) { 2933506Ssaidi@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 2943814Ssaidi@eecs.umich.edu // Note that we can't use the rename() method because we don't 2953506Ssaidi@eecs.umich.edu // want special treatment for the zero register at this point 2963931Ssaidi@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getIntReg(); 2973931Ssaidi@eecs.umich.edu renameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg); 2983748Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg); 2993748Sgblack@eecs.umich.edu } 3003748Sgblack@eecs.umich.edu 3013748Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 3023748Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getFloatReg(); 3033748Sgblack@eecs.umich.edu renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg); 3043748Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry( 3053748Sgblack@eecs.umich.edu RegId(FloatRegClass, ridx), phys_reg); 3063748Sgblack@eecs.umich.edu } 3073748Sgblack@eecs.umich.edu 3083748Sgblack@eecs.umich.edu /* Here we need two 'interfaces' the 'whole register' and the 3093748Sgblack@eecs.umich.edu * 'register element'. At any point only one of them will be 3103748Sgblack@eecs.umich.edu * active. */ 3113748Sgblack@eecs.umich.edu if (vecMode == Enums::Full) { 3123748Sgblack@eecs.umich.edu /* Initialize the full-vector interface */ 3133748Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { 3143748Sgblack@eecs.umich.edu RegId rid = RegId(VecRegClass, ridx); 3153748Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getVecReg(); 3163748Sgblack@eecs.umich.edu renameMap[tid].setEntry(rid, phys_reg); 3173748Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(rid, phys_reg); 3183880Ssaidi@eecs.umich.edu } 3193603Ssaidi@eecs.umich.edu } else { 3203603Ssaidi@eecs.umich.edu /* Initialize the vector-element interface */ 3213903Ssaidi@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { 3223903Ssaidi@eecs.umich.edu for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg; 3233903Ssaidi@eecs.umich.edu ++ldx) { 3243903Ssaidi@eecs.umich.edu RegId lrid = RegId(VecElemClass, ridx, ldx); 3253903Ssaidi@eecs.umich.edu PhysRegIdPtr phys_elem = freeList.getVecElem(); 3263903Ssaidi@eecs.umich.edu renameMap[tid].setEntry(lrid, phys_elem); 3273903Ssaidi@eecs.umich.edu commitRenameMap[tid].setEntry(lrid, phys_elem); 3283903Ssaidi@eecs.umich.edu } 3293903Ssaidi@eecs.umich.edu } 3303903Ssaidi@eecs.umich.edu } 3313903Ssaidi@eecs.umich.edu 3323903Ssaidi@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumVecPredRegs; ++ridx) { 3333903Ssaidi@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getVecPredReg(); 3343903Ssaidi@eecs.umich.edu renameMap[tid].setEntry(RegId(VecPredRegClass, ridx), phys_reg); 3353903Ssaidi@eecs.umich.edu commitRenameMap[tid].setEntry( 3363903Ssaidi@eecs.umich.edu RegId(VecPredRegClass, ridx), phys_reg); 3373903Ssaidi@eecs.umich.edu } 3383903Ssaidi@eecs.umich.edu 3393506Ssaidi@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 3403584Ssaidi@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getCCReg(); 3413584Ssaidi@eecs.umich.edu renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg); 3423584Ssaidi@eecs.umich.edu commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg); 3433748Sgblack@eecs.umich.edu } 3443928Ssaidi@eecs.umich.edu } 3453928Ssaidi@eecs.umich.edu 3463928Ssaidi@eecs.umich.edu rename.setRenameMap(renameMap); 3473748Sgblack@eecs.umich.edu commit.setRenameMap(commitRenameMap); 3483603Ssaidi@eecs.umich.edu rename.setFreeList(&freeList); 3493584Ssaidi@eecs.umich.edu 3503814Ssaidi@eecs.umich.edu // Setup the ROB for whichever stages need it. 3513814Ssaidi@eecs.umich.edu commit.setROB(&rob); 3523814Ssaidi@eecs.umich.edu 3533814Ssaidi@eecs.umich.edu lastActivatedCycle = 0; 3543814Ssaidi@eecs.umich.edu 3553743Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Creating O3CPU object.\n"); 3563743Sgblack@eecs.umich.edu 3573584Ssaidi@eecs.umich.edu // Setup any thread state. 3583743Sgblack@eecs.umich.edu this->thread.resize(this->numThreads); 3593754Sgblack@eecs.umich.edu 3603603Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 3613931Ssaidi@eecs.umich.edu if (FullSystem) { 3623603Ssaidi@eecs.umich.edu // SMT is not supported in FS mode yet. 3633584Ssaidi@eecs.umich.edu assert(this->numThreads == 1); 3643931Ssaidi@eecs.umich.edu this->thread[tid] = new Thread(this, 0, NULL); 3653931Ssaidi@eecs.umich.edu } else { 3663931Ssaidi@eecs.umich.edu if (tid < params->workload.size()) { 3673931Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Workload[%i] process is %#x", 3683931Ssaidi@eecs.umich.edu tid, this->thread[tid]); 3693931Ssaidi@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3703748Sgblack@eecs.umich.edu (typename Impl::O3CPU *)(this), 3713748Sgblack@eecs.umich.edu tid, params->workload[tid]); 3723748Sgblack@eecs.umich.edu 3733748Sgblack@eecs.umich.edu //usedTids[tid] = true; 3743748Sgblack@eecs.umich.edu //threadMap[tid] = tid; 3753815Ssaidi@eecs.umich.edu } else { 3763748Sgblack@eecs.umich.edu //Allocate Empty thread so M5 can use later 3773748Sgblack@eecs.umich.edu //when scheduling threads to CPU 3783815Ssaidi@eecs.umich.edu Process* dummy_proc = NULL; 3793748Sgblack@eecs.umich.edu 3803748Sgblack@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3813815Ssaidi@eecs.umich.edu (typename Impl::O3CPU *)(this), 3823748Sgblack@eecs.umich.edu tid, dummy_proc); 3833748Sgblack@eecs.umich.edu //usedTids[tid] = false; 3843815Ssaidi@eecs.umich.edu } 3853748Sgblack@eecs.umich.edu } 3863748Sgblack@eecs.umich.edu 3873815Ssaidi@eecs.umich.edu ThreadContext *tc; 3883748Sgblack@eecs.umich.edu 3893748Sgblack@eecs.umich.edu // Setup the TC that will serve as the interface to the threads/CPU. 3903748Sgblack@eecs.umich.edu O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 3913584Ssaidi@eecs.umich.edu 3923748Sgblack@eecs.umich.edu tc = o3_tc; 3933748Sgblack@eecs.umich.edu 3943748Sgblack@eecs.umich.edu // If we're using a checker, then the TC should be the 3953748Sgblack@eecs.umich.edu // CheckerThreadContext. 3963748Sgblack@eecs.umich.edu if (params->checker) { 3973748Sgblack@eecs.umich.edu tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 3983748Sgblack@eecs.umich.edu o3_tc, this->checker); 3993748Sgblack@eecs.umich.edu } 4003748Sgblack@eecs.umich.edu 4013748Sgblack@eecs.umich.edu o3_tc->cpu = (typename Impl::O3CPU *)(this); 4023748Sgblack@eecs.umich.edu assert(o3_tc->cpu); 4033748Sgblack@eecs.umich.edu o3_tc->thread = this->thread[tid]; 4043748Sgblack@eecs.umich.edu 4053748Sgblack@eecs.umich.edu // Setup quiesce event. 4063748Sgblack@eecs.umich.edu this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 4073748Sgblack@eecs.umich.edu 4083748Sgblack@eecs.umich.edu // Give the thread the TC. 4093748Sgblack@eecs.umich.edu this->thread[tid]->tc = tc; 4103748Sgblack@eecs.umich.edu 4113748Sgblack@eecs.umich.edu // Add the TC to the CPU's list of TC's. 4123748Sgblack@eecs.umich.edu this->threadContexts.push_back(tc); 4133748Sgblack@eecs.umich.edu } 4143748Sgblack@eecs.umich.edu 4153748Sgblack@eecs.umich.edu // FullO3CPU always requires an interrupt controller. 4163748Sgblack@eecs.umich.edu if (!params->switched_out && interrupts.empty()) { 4173748Sgblack@eecs.umich.edu fatal("FullO3CPU %s has no interrupt controller.\n" 4183748Sgblack@eecs.umich.edu "Ensure createInterruptController() is called.\n", name()); 4193748Sgblack@eecs.umich.edu } 4203748Sgblack@eecs.umich.edu 4213748Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; tid++) 4223748Sgblack@eecs.umich.edu this->thread[tid]->setFuncExeInst(0); 4233748Sgblack@eecs.umich.edu} 4243748Sgblack@eecs.umich.edu 4253748Sgblack@eecs.umich.edutemplate <class Impl> 4263748Sgblack@eecs.umich.eduFullO3CPU<Impl>::~FullO3CPU() 4273748Sgblack@eecs.umich.edu{ 4283880Ssaidi@eecs.umich.edu} 4293880Ssaidi@eecs.umich.edu 4303880Ssaidi@eecs.umich.edutemplate <class Impl> 4313880Ssaidi@eecs.umich.eduvoid 4323880Ssaidi@eecs.umich.eduFullO3CPU<Impl>::regProbePoints() 4333880Ssaidi@eecs.umich.edu{ 4343880Ssaidi@eecs.umich.edu BaseCPU::regProbePoints(); 4353931Ssaidi@eecs.umich.edu 4363931Ssaidi@eecs.umich.edu ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete"); 4373931Ssaidi@eecs.umich.edu ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete"); 4383931Ssaidi@eecs.umich.edu 4393931Ssaidi@eecs.umich.edu fetch.regProbePoints(); 4403931Ssaidi@eecs.umich.edu rename.regProbePoints(); 4413863Ssaidi@eecs.umich.edu iew.regProbePoints(); 4423880Ssaidi@eecs.umich.edu commit.regProbePoints(); 4433880Ssaidi@eecs.umich.edu} 4443880Ssaidi@eecs.umich.edu 4453863Ssaidi@eecs.umich.edutemplate <class Impl> 4463584Ssaidi@eecs.umich.eduvoid 4473584Ssaidi@eecs.umich.eduFullO3CPU<Impl>::regStats() 4483584Ssaidi@eecs.umich.edu{ 4493814Ssaidi@eecs.umich.edu BaseO3CPU::regStats(); 4503814Ssaidi@eecs.umich.edu 4513584Ssaidi@eecs.umich.edu // Register any of the O3CPU's stats here. 4523584Ssaidi@eecs.umich.edu timesIdled 4533931Ssaidi@eecs.umich.edu .name(name() + ".timesIdled") 4543584Ssaidi@eecs.umich.edu .desc("Number of times that the entire CPU went into an idle state and" 4553931Ssaidi@eecs.umich.edu " unscheduled itself") 4563931Ssaidi@eecs.umich.edu .prereq(timesIdled); 4573748Sgblack@eecs.umich.edu 4583748Sgblack@eecs.umich.edu idleCycles 4593748Sgblack@eecs.umich.edu .name(name() + ".idleCycles") 4603748Sgblack@eecs.umich.edu .desc("Total number of cycles that the CPU has spent unscheduled due " 4613748Sgblack@eecs.umich.edu "to idling") 4623748Sgblack@eecs.umich.edu .prereq(idleCycles); 4633748Sgblack@eecs.umich.edu 4643748Sgblack@eecs.umich.edu quiesceCycles 4653748Sgblack@eecs.umich.edu .name(name() + ".quiesceCycles") 4663748Sgblack@eecs.umich.edu .desc("Total number of cycles that CPU has spent quiesced or waiting " 4673748Sgblack@eecs.umich.edu "for an interrupt") 4683748Sgblack@eecs.umich.edu .prereq(quiesceCycles); 4693748Sgblack@eecs.umich.edu 4703748Sgblack@eecs.umich.edu // Number of Instructions simulated 4713748Sgblack@eecs.umich.edu // -------------------------------- 4723748Sgblack@eecs.umich.edu // Should probably be in Base CPU but need templated 4733748Sgblack@eecs.umich.edu // MaxThreads so put in here instead 4743748Sgblack@eecs.umich.edu committedInsts 4753748Sgblack@eecs.umich.edu .init(numThreads) 4763748Sgblack@eecs.umich.edu .name(name() + ".committedInsts") 4773748Sgblack@eecs.umich.edu .desc("Number of Instructions Simulated") 4783748Sgblack@eecs.umich.edu .flags(Stats::total); 4793748Sgblack@eecs.umich.edu 4803748Sgblack@eecs.umich.edu committedOps 4813748Sgblack@eecs.umich.edu .init(numThreads) 4823748Sgblack@eecs.umich.edu .name(name() + ".committedOps") 4833748Sgblack@eecs.umich.edu .desc("Number of Ops (including micro ops) Simulated") 4843748Sgblack@eecs.umich.edu .flags(Stats::total); 4853748Sgblack@eecs.umich.edu 4863748Sgblack@eecs.umich.edu cpi 4873748Sgblack@eecs.umich.edu .name(name() + ".cpi") 4883748Sgblack@eecs.umich.edu .desc("CPI: Cycles Per Instruction") 4893748Sgblack@eecs.umich.edu .precision(6); 4903748Sgblack@eecs.umich.edu cpi = numCycles / committedInsts; 4913748Sgblack@eecs.umich.edu 4923748Sgblack@eecs.umich.edu totalCpi 4933748Sgblack@eecs.umich.edu .name(name() + ".cpi_total") 4943748Sgblack@eecs.umich.edu .desc("CPI: Total CPI of All Threads") 4953880Ssaidi@eecs.umich.edu .precision(6); 4963880Ssaidi@eecs.umich.edu totalCpi = numCycles / sum(committedInsts); 4973603Ssaidi@eecs.umich.edu 4983584Ssaidi@eecs.umich.edu ipc 4993603Ssaidi@eecs.umich.edu .name(name() + ".ipc") 5003584Ssaidi@eecs.umich.edu .desc("IPC: Instructions Per Cycle") 5013603Ssaidi@eecs.umich.edu .precision(6); 5023584Ssaidi@eecs.umich.edu ipc = committedInsts / numCycles; 5033584Ssaidi@eecs.umich.edu 5043603Ssaidi@eecs.umich.edu totalIpc 5053584Ssaidi@eecs.umich.edu .name(name() + ".ipc_total") 5063814Ssaidi@eecs.umich.edu .desc("IPC: Total IPC of All Threads") 5073814Ssaidi@eecs.umich.edu .precision(6); 5083814Ssaidi@eecs.umich.edu totalIpc = sum(committedInsts) / numCycles; 5093814Ssaidi@eecs.umich.edu 5103814Ssaidi@eecs.umich.edu this->fetch.regStats(); 5113814Ssaidi@eecs.umich.edu this->decode.regStats(); 5123814Ssaidi@eecs.umich.edu this->rename.regStats(); 5133584Ssaidi@eecs.umich.edu this->iew.regStats(); 5143584Ssaidi@eecs.umich.edu this->commit.regStats(); 5153584Ssaidi@eecs.umich.edu this->rob.regStats(); 5163603Ssaidi@eecs.umich.edu 5173584Ssaidi@eecs.umich.edu intRegfileReads 5183584Ssaidi@eecs.umich.edu .name(name() + ".int_regfile_reads") 5193748Sgblack@eecs.umich.edu .desc("number of integer regfile reads") 5203748Sgblack@eecs.umich.edu .prereq(intRegfileReads); 5213748Sgblack@eecs.umich.edu 5223584Ssaidi@eecs.umich.edu intRegfileWrites 5233584Ssaidi@eecs.umich.edu .name(name() + ".int_regfile_writes") 5243584Ssaidi@eecs.umich.edu .desc("number of integer regfile writes") 5253584Ssaidi@eecs.umich.edu .prereq(intRegfileWrites); 5263603Ssaidi@eecs.umich.edu 5273748Sgblack@eecs.umich.edu fpRegfileReads 5283584Ssaidi@eecs.umich.edu .name(name() + ".fp_regfile_reads") 5293748Sgblack@eecs.umich.edu .desc("number of floating regfile reads") 5303748Sgblack@eecs.umich.edu .prereq(fpRegfileReads); 5313748Sgblack@eecs.umich.edu 5323748Sgblack@eecs.umich.edu fpRegfileWrites 5333748Sgblack@eecs.umich.edu .name(name() + ".fp_regfile_writes") 5343748Sgblack@eecs.umich.edu .desc("number of floating regfile writes") 5353748Sgblack@eecs.umich.edu .prereq(fpRegfileWrites); 5363748Sgblack@eecs.umich.edu 5373748Sgblack@eecs.umich.edu vecRegfileReads 5383748Sgblack@eecs.umich.edu .name(name() + ".vec_regfile_reads") 5393748Sgblack@eecs.umich.edu .desc("number of vector regfile reads") 5403748Sgblack@eecs.umich.edu .prereq(vecRegfileReads); 5413748Sgblack@eecs.umich.edu 5423748Sgblack@eecs.umich.edu vecRegfileWrites 5433748Sgblack@eecs.umich.edu .name(name() + ".vec_regfile_writes") 5443748Sgblack@eecs.umich.edu .desc("number of vector regfile writes") 5453748Sgblack@eecs.umich.edu .prereq(vecRegfileWrites); 5463748Sgblack@eecs.umich.edu 5473748Sgblack@eecs.umich.edu vecPredRegfileReads 5483748Sgblack@eecs.umich.edu .name(name() + ".pred_regfile_reads") 5493748Sgblack@eecs.umich.edu .desc("number of predicate regfile reads") 5503748Sgblack@eecs.umich.edu .prereq(vecPredRegfileReads); 5513748Sgblack@eecs.umich.edu 5523748Sgblack@eecs.umich.edu vecPredRegfileWrites 5533748Sgblack@eecs.umich.edu .name(name() + ".pred_regfile_writes") 5543748Sgblack@eecs.umich.edu .desc("number of predicate regfile writes") 5553748Sgblack@eecs.umich.edu .prereq(vecPredRegfileWrites); 5563748Sgblack@eecs.umich.edu 5573748Sgblack@eecs.umich.edu ccRegfileReads 5583748Sgblack@eecs.umich.edu .name(name() + ".cc_regfile_reads") 5593748Sgblack@eecs.umich.edu .desc("number of cc regfile reads") 5603748Sgblack@eecs.umich.edu .prereq(ccRegfileReads); 5613748Sgblack@eecs.umich.edu 5623748Sgblack@eecs.umich.edu ccRegfileWrites 5633748Sgblack@eecs.umich.edu .name(name() + ".cc_regfile_writes") 5643748Sgblack@eecs.umich.edu .desc("number of cc regfile writes") 5653748Sgblack@eecs.umich.edu .prereq(ccRegfileWrites); 5663748Sgblack@eecs.umich.edu 5673748Sgblack@eecs.umich.edu miscRegfileReads 5683748Sgblack@eecs.umich.edu .name(name() + ".misc_regfile_reads") 5693748Sgblack@eecs.umich.edu .desc("number of misc regfile reads") 5703748Sgblack@eecs.umich.edu .prereq(miscRegfileReads); 5713748Sgblack@eecs.umich.edu 5723748Sgblack@eecs.umich.edu miscRegfileWrites 5733748Sgblack@eecs.umich.edu .name(name() + ".misc_regfile_writes") 5743748Sgblack@eecs.umich.edu .desc("number of misc regfile writes") 5753748Sgblack@eecs.umich.edu .prereq(miscRegfileWrites); 5763748Sgblack@eecs.umich.edu} 5773748Sgblack@eecs.umich.edu 5783748Sgblack@eecs.umich.edutemplate <class Impl> 5793748Sgblack@eecs.umich.eduvoid 5803815Ssaidi@eecs.umich.eduFullO3CPU<Impl>::tick() 5813748Sgblack@eecs.umich.edu{ 5823748Sgblack@eecs.umich.edu DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 5833815Ssaidi@eecs.umich.edu assert(!switchedOut()); 5843748Sgblack@eecs.umich.edu assert(drainState() != DrainState::Drained); 5853748Sgblack@eecs.umich.edu 5863815Ssaidi@eecs.umich.edu ++numCycles; 5873748Sgblack@eecs.umich.edu updateCycleCounters(BaseCPU::CPU_STATE_ON); 5883748Sgblack@eecs.umich.edu 5893815Ssaidi@eecs.umich.edu// activity = false; 5903748Sgblack@eecs.umich.edu 5913748Sgblack@eecs.umich.edu //Tick each of the stages 5923815Ssaidi@eecs.umich.edu fetch.tick(); 5933748Sgblack@eecs.umich.edu 5943748Sgblack@eecs.umich.edu decode.tick(); 5953584Ssaidi@eecs.umich.edu 5963584Ssaidi@eecs.umich.edu rename.tick(); 5973748Sgblack@eecs.umich.edu 5983584Ssaidi@eecs.umich.edu iew.tick(); 5993931Ssaidi@eecs.umich.edu 6003931Ssaidi@eecs.umich.edu commit.tick(); 6013748Sgblack@eecs.umich.edu 6023748Sgblack@eecs.umich.edu // Now advance the time buffers 6033748Sgblack@eecs.umich.edu timeBuffer.advance(); 6043748Sgblack@eecs.umich.edu 6053748Sgblack@eecs.umich.edu fetchQueue.advance(); 6063931Ssaidi@eecs.umich.edu decodeQueue.advance(); 6073931Ssaidi@eecs.umich.edu renameQueue.advance(); 6083931Ssaidi@eecs.umich.edu iewQueue.advance(); 6093931Ssaidi@eecs.umich.edu 6103931Ssaidi@eecs.umich.edu activityRec.advance(); 6113931Ssaidi@eecs.umich.edu 6123931Ssaidi@eecs.umich.edu if (removeInstsThisCycle) { 6133931Ssaidi@eecs.umich.edu cleanUpRemovedInsts(); 6143931Ssaidi@eecs.umich.edu } 6153584Ssaidi@eecs.umich.edu 6163584Ssaidi@eecs.umich.edu if (!tickEvent.scheduled()) { 6173903Ssaidi@eecs.umich.edu if (_status == SwitchedOut) { 6183903Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Switched out!\n"); 6193903Ssaidi@eecs.umich.edu // increment stat 6203903Ssaidi@eecs.umich.edu lastRunningCycle = curCycle(); 6213903Ssaidi@eecs.umich.edu } else if (!activityRec.active() || _status == Idle) { 6223903Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Idle!\n"); 6233903Ssaidi@eecs.umich.edu lastRunningCycle = curCycle(); 6243903Ssaidi@eecs.umich.edu timesIdled++; 6253903Ssaidi@eecs.umich.edu } else { 6263903Ssaidi@eecs.umich.edu schedule(tickEvent, clockEdge(Cycles(1))); 6273880Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Scheduling next tick!\n"); 6283903Ssaidi@eecs.umich.edu } 6293903Ssaidi@eecs.umich.edu } 6303903Ssaidi@eecs.umich.edu 6313903Ssaidi@eecs.umich.edu if (!FullSystem) 6323903Ssaidi@eecs.umich.edu updateThreadPriority(); 6333903Ssaidi@eecs.umich.edu 6343903Ssaidi@eecs.umich.edu tryDrain(); 6353903Ssaidi@eecs.umich.edu} 6363903Ssaidi@eecs.umich.edu 6373903Ssaidi@eecs.umich.edutemplate <class Impl> 6383880Ssaidi@eecs.umich.eduvoid 6393826Ssaidi@eecs.umich.eduFullO3CPU<Impl>::init() 6403825Ssaidi@eecs.umich.edu{ 6413832Ssaidi@eecs.umich.edu BaseCPU::init(); 6423825Ssaidi@eecs.umich.edu 6433892Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 6443892Ssaidi@eecs.umich.edu // Set noSquashFromTC so that the CPU doesn't squash when initially 6453584Ssaidi@eecs.umich.edu // setting up registers. 6463584Ssaidi@eecs.umich.edu thread[tid]->noSquashFromTC = true; 6473584Ssaidi@eecs.umich.edu // Initialise the ThreadContext's memory proxies 6483506Ssaidi@eecs.umich.edu thread[tid]->initMemProxies(thread[tid]->getTC()); 6493584Ssaidi@eecs.umich.edu } 6503584Ssaidi@eecs.umich.edu 6513506Ssaidi@eecs.umich.edu if (FullSystem && !params()->switched_out) { 6523584Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 6532SN/A ThreadContext *src_tc = threadContexts[tid]; 6542SN/A TheISA::initCPU(src_tc, src_tc->contextId()); 6552SN/A } 6562SN/A } 6571967SN/A 6582SN/A // Clear noSquashFromTC. 6592SN/A for (int tid = 0; tid < numThreads; ++tid) 6602SN/A thread[tid]->noSquashFromTC = false; 6612SN/A 6622SN/A commit.setThreads(thread); 6632SN/A} 6642SN/A 6652SN/Atemplate <class Impl> 6662SN/Avoid 6672SN/AFullO3CPU<Impl>::startup() 6682SN/A{ 6692SN/A BaseCPU::startup(); 6702SN/A for (int tid = 0; tid < numThreads; ++tid) 6712SN/A isa[tid]->startup(threadContexts[tid]); 6722SN/A 6732SN/A fetch.startupStage(); 6742SN/A decode.startupStage(); 6752SN/A iew.startupStage(); 6762SN/A rename.startupStage(); 6772SN/A commit.startupStage(); 6781413SN/A} 6792SN/A 6802SN/Atemplate <class Impl> 6812SN/Avoid 6822SN/AFullO3CPU<Impl>::activateThread(ThreadID tid) 6832SN/A{ 6842SN/A list<ThreadID>::iterator isActive = 6852SN/A std::find(activeThreads.begin(), activeThreads.end(), tid); 6862SN/A 6872SN/A DPRINTF(O3CPU, "[tid:%i] Calling activate thread.\n", tid); 6882SN/A assert(!switchedOut()); 6892SN/A 6902SN/A if (isActive == activeThreads.end()) { 6912SN/A DPRINTF(O3CPU, "[tid:%i] Adding to active threads list\n", 6922SN/A tid); 6932SN/A 6942SN/A activeThreads.push_back(tid); 6952SN/A } 6962973Sgblack@eecs.umich.edu} 6972973Sgblack@eecs.umich.edu 6982299SN/Atemplate <class Impl> 6992299SN/Avoid 7001904SN/AFullO3CPU<Impl>::deactivateThread(ThreadID tid) 7011904SN/A{ 7023506Ssaidi@eecs.umich.edu //Remove From Active List, if Active 7033506Ssaidi@eecs.umich.edu list<ThreadID>::iterator thread_it = 7043506Ssaidi@eecs.umich.edu std::find(activeThreads.begin(), activeThreads.end(), tid); 7051967SN/A 7061967SN/A DPRINTF(O3CPU, "[tid:%i] Calling deactivate thread.\n", tid); 7071967SN/A assert(!switchedOut()); 7081904SN/A 7092SN/A if (thread_it != activeThreads.end()) { 7102SN/A DPRINTF(O3CPU,"[tid:%i] Removing from active threads list\n", 7112SN/A tid); 7122SN/A activeThreads.erase(thread_it); 7132SN/A } 7142SN/A 7152SN/A fetch.deactivateThread(tid); 7162SN/A commit.deactivateThread(tid); 7172SN/A} 7182SN/A 7192SN/Atemplate <class Impl> 7202SN/ACounter 7212SN/AFullO3CPU<Impl>::totalInsts() const 7222SN/A{ 7232SN/A Counter total(0); 7242SN/A 7252SN/A ThreadID size = thread.size(); 7262SN/A for (ThreadID i = 0; i < size; i++) 7272973Sgblack@eecs.umich.edu total += thread[i]->numInst; 7282299SN/A 7291904SN/A return total; 7303506Ssaidi@eecs.umich.edu} 7311967SN/A 7323506Ssaidi@eecs.umich.edutemplate <class Impl> 7333506Ssaidi@eecs.umich.eduCounter 7343506Ssaidi@eecs.umich.eduFullO3CPU<Impl>::totalOps() const 7353506Ssaidi@eecs.umich.edu{ 7363603Ssaidi@eecs.umich.edu Counter total(0); 7373506Ssaidi@eecs.umich.edu 7383506Ssaidi@eecs.umich.edu ThreadID size = thread.size(); 7393506Ssaidi@eecs.umich.edu for (ThreadID i = 0; i < size; i++) 7403506Ssaidi@eecs.umich.edu total += thread[i]->numOp; 7413506Ssaidi@eecs.umich.edu 7423506Ssaidi@eecs.umich.edu return total; 7433506Ssaidi@eecs.umich.edu} 7443506Ssaidi@eecs.umich.edu 7453506Ssaidi@eecs.umich.edutemplate <class Impl> 7463506Ssaidi@eecs.umich.eduvoid 7473506Ssaidi@eecs.umich.eduFullO3CPU<Impl>::activateContext(ThreadID tid) 7483506Ssaidi@eecs.umich.edu{ 7493506Ssaidi@eecs.umich.edu assert(!switchedOut()); 7503506Ssaidi@eecs.umich.edu 7513603Ssaidi@eecs.umich.edu // Needs to set each stage to running as well. 7523603Ssaidi@eecs.umich.edu activateThread(tid); 7533506Ssaidi@eecs.umich.edu 7542SN/A // We don't want to wake the CPU if it is drained. In that case, 7552SN/A // we just want to flag the thread as active and schedule the tick 7562SN/A // event from drainResume() instead. 7572SN/A if (drainState() == DrainState::Drained) 7582SN/A return; 7592SN/A 7602SN/A // If we are time 0 or if the last activation time is in the past, 7612SN/A // schedule the next tick and wake up the fetch unit 762 if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 763 scheduleTickEvent(Cycles(0)); 764 765 // Be sure to signal that there's some activity so the CPU doesn't 766 // deschedule itself. 767 activityRec.activity(); 768 fetch.wakeFromQuiesce(); 769 770 Cycles cycles(curCycle() - lastRunningCycle); 771 // @todo: This is an oddity that is only here to match the stats 772 if (cycles != 0) 773 --cycles; 774 quiesceCycles += cycles; 775 776 lastActivatedCycle = curTick(); 777 778 _status = Running; 779 780 BaseCPU::activateContext(tid); 781 } 782} 783 784template <class Impl> 785void 786FullO3CPU<Impl>::suspendContext(ThreadID tid) 787{ 788 DPRINTF(O3CPU,"[tid:%i] Suspending Thread Context.\n", tid); 789 assert(!switchedOut()); 790 791 deactivateThread(tid); 792 793 // If this was the last thread then unschedule the tick event. 794 if (activeThreads.size() == 0) { 795 unscheduleTickEvent(); 796 lastRunningCycle = curCycle(); 797 _status = Idle; 798 } 799 800 DPRINTF(Quiesce, "Suspending Context\n"); 801 802 BaseCPU::suspendContext(tid); 803} 804 805template <class Impl> 806void 807FullO3CPU<Impl>::haltContext(ThreadID tid) 808{ 809 //For now, this is the same as deallocate 810 DPRINTF(O3CPU,"[tid:%i] Halt Context called. Deallocating\n", tid); 811 assert(!switchedOut()); 812 813 deactivateThread(tid); 814 removeThread(tid); 815 816 updateCycleCounters(BaseCPU::CPU_STATE_SLEEP); 817} 818 819template <class Impl> 820void 821FullO3CPU<Impl>::insertThread(ThreadID tid) 822{ 823 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 824 // Will change now that the PC and thread state is internal to the CPU 825 // and not in the ThreadContext. 826 ThreadContext *src_tc; 827 if (FullSystem) 828 src_tc = system->threadContexts[tid]; 829 else 830 src_tc = tcBase(tid); 831 832 //Bind Int Regs to Rename Map 833 834 for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs; 835 reg_id.index()++) { 836 PhysRegIdPtr phys_reg = freeList.getIntReg(); 837 renameMap[tid].setEntry(reg_id, phys_reg); 838 scoreboard.setReg(phys_reg); 839 } 840 841 //Bind Float Regs to Rename Map 842 for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs; 843 reg_id.index()++) { 844 PhysRegIdPtr phys_reg = freeList.getFloatReg(); 845 renameMap[tid].setEntry(reg_id, phys_reg); 846 scoreboard.setReg(phys_reg); 847 } 848 849 //Bind condition-code Regs to Rename Map 850 for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs; 851 reg_id.index()++) { 852 PhysRegIdPtr phys_reg = freeList.getCCReg(); 853 renameMap[tid].setEntry(reg_id, phys_reg); 854 scoreboard.setReg(phys_reg); 855 } 856 857 //Copy Thread Data Into RegFile 858 //this->copyFromTC(tid); 859 860 //Set PC/NPC/NNPC 861 pcState(src_tc->pcState(), tid); 862 863 src_tc->setStatus(ThreadContext::Active); 864 865 activateContext(tid); 866 867 //Reset ROB/IQ/LSQ Entries 868 commit.rob->resetEntries(); 869} 870 871template <class Impl> 872void 873FullO3CPU<Impl>::removeThread(ThreadID tid) 874{ 875 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 876 877 // Copy Thread Data From RegFile 878 // If thread is suspended, it might be re-allocated 879 // this->copyToTC(tid); 880 881 882 // @todo: 2-27-2008: Fix how we free up rename mappings 883 // here to alleviate the case for double-freeing registers 884 // in SMT workloads. 885 886 // clear all thread-specific states in each stage of the pipeline 887 // since this thread is going to be completely removed from the CPU 888 commit.clearStates(tid); 889 fetch.clearStates(tid); 890 decode.clearStates(tid); 891 rename.clearStates(tid); 892 iew.clearStates(tid); 893 894 // at this step, all instructions in the pipeline should be already 895 // either committed successfully or squashed. All thread-specific 896 // queues in the pipeline must be empty. 897 assert(iew.instQueue.getCount(tid) == 0); 898 assert(iew.ldstQueue.getCount(tid) == 0); 899 assert(commit.rob->isEmpty(tid)); 900 901 // Reset ROB/IQ/LSQ Entries 902 903 // Commented out for now. This should be possible to do by 904 // telling all the pipeline stages to drain first, and then 905 // checking until the drain completes. Once the pipeline is 906 // drained, call resetEntries(). - 10-09-06 ktlim 907/* 908 if (activeThreads.size() >= 1) { 909 commit.rob->resetEntries(); 910 iew.resetEntries(); 911 } 912*/ 913} 914 915template <class Impl> 916void 917FullO3CPU<Impl>::switchRenameMode(ThreadID tid, UnifiedFreeList* freelist) 918{ 919 auto pc = this->pcState(tid); 920 921 // new_mode is the new vector renaming mode 922 auto new_mode = RenameMode<TheISA::ISA>::mode(pc); 923 924 // We update vecMode only if there has been a change 925 if (new_mode != vecMode) { 926 vecMode = new_mode; 927 928 renameMap[tid].switchMode(vecMode); 929 commitRenameMap[tid].switchMode(vecMode); 930 renameMap[tid].switchFreeList(freelist); 931 } 932} 933 934template <class Impl> 935Fault 936FullO3CPU<Impl>::getInterrupts() 937{ 938 // Check if there are any outstanding interrupts 939 return this->interrupts[0]->getInterrupt(this->threadContexts[0]); 940} 941 942template <class Impl> 943void 944FullO3CPU<Impl>::processInterrupts(const Fault &interrupt) 945{ 946 // Check for interrupts here. For now can copy the code that 947 // exists within isa_fullsys_traits.hh. Also assume that thread 0 948 // is the one that handles the interrupts. 949 // @todo: Possibly consolidate the interrupt checking code. 950 // @todo: Allow other threads to handle interrupts. 951 952 assert(interrupt != NoFault); 953 this->interrupts[0]->updateIntrInfo(this->threadContexts[0]); 954 955 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 956 this->trap(interrupt, 0, nullptr); 957} 958 959template <class Impl> 960void 961FullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid, 962 const StaticInstPtr &inst) 963{ 964 // Pass the thread's TC into the invoke method. 965 fault->invoke(this->threadContexts[tid], inst); 966} 967 968template <class Impl> 969void 970FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid, Fault *fault) 971{ 972 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 973 974 DPRINTF(Activity,"Activity: syscall() called.\n"); 975 976 // Temporarily increase this by one to account for the syscall 977 // instruction. 978 ++(this->thread[tid]->funcExeInst); 979 980 // Execute the actual syscall. 981 this->thread[tid]->syscall(callnum, fault); 982 983 // Decrease funcExeInst by one as the normal commit will handle 984 // incrementing it. 985 --(this->thread[tid]->funcExeInst); 986} 987 988template <class Impl> 989void 990FullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const 991{ 992 thread[tid]->serialize(cp); 993} 994 995template <class Impl> 996void 997FullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid) 998{ 999 thread[tid]->unserialize(cp); 1000} 1001 1002template <class Impl> 1003DrainState 1004FullO3CPU<Impl>::drain() 1005{ 1006 // Deschedule any power gating event (if any) 1007 deschedulePowerGatingEvent(); 1008 1009 // If the CPU isn't doing anything, then return immediately. 1010 if (switchedOut()) 1011 return DrainState::Drained; 1012 1013 DPRINTF(Drain, "Draining...\n"); 1014 1015 // We only need to signal a drain to the commit stage as this 1016 // initiates squashing controls the draining. Once the commit 1017 // stage commits an instruction where it is safe to stop, it'll 1018 // squash the rest of the instructions in the pipeline and force 1019 // the fetch stage to stall. The pipeline will be drained once all 1020 // in-flight instructions have retired. 1021 commit.drain(); 1022 1023 // Wake the CPU and record activity so everything can drain out if 1024 // the CPU was not able to immediately drain. 1025 if (!isCpuDrained()) { 1026 // If a thread is suspended, wake it up so it can be drained 1027 for (auto t : threadContexts) { 1028 if (t->status() == ThreadContext::Suspended){ 1029 DPRINTF(Drain, "Currently suspended so activate %i \n", 1030 t->threadId()); 1031 t->activate(); 1032 // As the thread is now active, change the power state as well 1033 activateContext(t->threadId()); 1034 } 1035 } 1036 1037 wakeCPU(); 1038 activityRec.activity(); 1039 1040 DPRINTF(Drain, "CPU not drained\n"); 1041 1042 return DrainState::Draining; 1043 } else { 1044 DPRINTF(Drain, "CPU is already drained\n"); 1045 if (tickEvent.scheduled()) 1046 deschedule(tickEvent); 1047 1048 // Flush out any old data from the time buffers. In 1049 // particular, there might be some data in flight from the 1050 // fetch stage that isn't visible in any of the CPU buffers we 1051 // test in isCpuDrained(). 1052 for (int i = 0; i < timeBuffer.getSize(); ++i) { 1053 timeBuffer.advance(); 1054 fetchQueue.advance(); 1055 decodeQueue.advance(); 1056 renameQueue.advance(); 1057 iewQueue.advance(); 1058 } 1059 1060 drainSanityCheck(); 1061 return DrainState::Drained; 1062 } 1063} 1064 1065template <class Impl> 1066bool 1067FullO3CPU<Impl>::tryDrain() 1068{ 1069 if (drainState() != DrainState::Draining || !isCpuDrained()) 1070 return false; 1071 1072 if (tickEvent.scheduled()) 1073 deschedule(tickEvent); 1074 1075 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 1076 signalDrainDone(); 1077 1078 return true; 1079} 1080 1081template <class Impl> 1082void 1083FullO3CPU<Impl>::drainSanityCheck() const 1084{ 1085 assert(isCpuDrained()); 1086 fetch.drainSanityCheck(); 1087 decode.drainSanityCheck(); 1088 rename.drainSanityCheck(); 1089 iew.drainSanityCheck(); 1090 commit.drainSanityCheck(); 1091} 1092 1093template <class Impl> 1094bool 1095FullO3CPU<Impl>::isCpuDrained() const 1096{ 1097 bool drained(true); 1098 1099 if (!instList.empty() || !removeList.empty()) { 1100 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1101 drained = false; 1102 } 1103 1104 if (!fetch.isDrained()) { 1105 DPRINTF(Drain, "Fetch not drained.\n"); 1106 drained = false; 1107 } 1108 1109 if (!decode.isDrained()) { 1110 DPRINTF(Drain, "Decode not drained.\n"); 1111 drained = false; 1112 } 1113 1114 if (!rename.isDrained()) { 1115 DPRINTF(Drain, "Rename not drained.\n"); 1116 drained = false; 1117 } 1118 1119 if (!iew.isDrained()) { 1120 DPRINTF(Drain, "IEW not drained.\n"); 1121 drained = false; 1122 } 1123 1124 if (!commit.isDrained()) { 1125 DPRINTF(Drain, "Commit not drained.\n"); 1126 drained = false; 1127 } 1128 1129 return drained; 1130} 1131 1132template <class Impl> 1133void 1134FullO3CPU<Impl>::commitDrained(ThreadID tid) 1135{ 1136 fetch.drainStall(tid); 1137} 1138 1139template <class Impl> 1140void 1141FullO3CPU<Impl>::drainResume() 1142{ 1143 if (switchedOut()) 1144 return; 1145 1146 DPRINTF(Drain, "Resuming...\n"); 1147 verifyMemoryMode(); 1148 1149 fetch.drainResume(); 1150 commit.drainResume(); 1151 1152 _status = Idle; 1153 for (ThreadID i = 0; i < thread.size(); i++) { 1154 if (thread[i]->status() == ThreadContext::Active) { 1155 DPRINTF(Drain, "Activating thread: %i\n", i); 1156 activateThread(i); 1157 _status = Running; 1158 } 1159 } 1160 1161 assert(!tickEvent.scheduled()); 1162 if (_status == Running) 1163 schedule(tickEvent, nextCycle()); 1164 1165 // Reschedule any power gating event (if any) 1166 schedulePowerGatingEvent(); 1167} 1168 1169template <class Impl> 1170void 1171FullO3CPU<Impl>::switchOut() 1172{ 1173 DPRINTF(O3CPU, "Switching out\n"); 1174 BaseCPU::switchOut(); 1175 1176 activityRec.reset(); 1177 1178 _status = SwitchedOut; 1179 1180 if (checker) 1181 checker->switchOut(); 1182} 1183 1184template <class Impl> 1185void 1186FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1187{ 1188 BaseCPU::takeOverFrom(oldCPU); 1189 1190 fetch.takeOverFrom(); 1191 decode.takeOverFrom(); 1192 rename.takeOverFrom(); 1193 iew.takeOverFrom(); 1194 commit.takeOverFrom(); 1195 1196 assert(!tickEvent.scheduled()); 1197 1198 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1199 if (oldO3CPU) 1200 globalSeqNum = oldO3CPU->globalSeqNum; 1201 1202 lastRunningCycle = curCycle(); 1203 _status = Idle; 1204} 1205 1206template <class Impl> 1207void 1208FullO3CPU<Impl>::verifyMemoryMode() const 1209{ 1210 if (!system->isTimingMode()) { 1211 fatal("The O3 CPU requires the memory system to be in " 1212 "'timing' mode.\n"); 1213 } 1214} 1215 1216template <class Impl> 1217RegVal 1218FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const 1219{ 1220 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1221} 1222 1223template <class Impl> 1224RegVal 1225FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 1226{ 1227 miscRegfileReads++; 1228 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 1229} 1230 1231template <class Impl> 1232void 1233FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, RegVal val, ThreadID tid) 1234{ 1235 this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 1236} 1237 1238template <class Impl> 1239void 1240FullO3CPU<Impl>::setMiscReg(int misc_reg, RegVal val, ThreadID tid) 1241{ 1242 miscRegfileWrites++; 1243 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 1244} 1245 1246template <class Impl> 1247RegVal 1248FullO3CPU<Impl>::readIntReg(PhysRegIdPtr phys_reg) 1249{ 1250 intRegfileReads++; 1251 return regFile.readIntReg(phys_reg); 1252} 1253 1254template <class Impl> 1255RegVal 1256FullO3CPU<Impl>::readFloatReg(PhysRegIdPtr phys_reg) 1257{ 1258 fpRegfileReads++; 1259 return regFile.readFloatReg(phys_reg); 1260} 1261 1262template <class Impl> 1263auto 1264FullO3CPU<Impl>::readVecReg(PhysRegIdPtr phys_reg) const 1265 -> const VecRegContainer& 1266{ 1267 vecRegfileReads++; 1268 return regFile.readVecReg(phys_reg); 1269} 1270 1271template <class Impl> 1272auto 1273FullO3CPU<Impl>::getWritableVecReg(PhysRegIdPtr phys_reg) 1274 -> VecRegContainer& 1275{ 1276 vecRegfileWrites++; 1277 return regFile.getWritableVecReg(phys_reg); 1278} 1279 1280template <class Impl> 1281auto 1282FullO3CPU<Impl>::readVecElem(PhysRegIdPtr phys_reg) const -> const VecElem& 1283{ 1284 vecRegfileReads++; 1285 return regFile.readVecElem(phys_reg); 1286} 1287 1288template <class Impl> 1289auto 1290FullO3CPU<Impl>::readVecPredReg(PhysRegIdPtr phys_reg) const 1291 -> const VecPredRegContainer& 1292{ 1293 vecPredRegfileReads++; 1294 return regFile.readVecPredReg(phys_reg); 1295} 1296 1297template <class Impl> 1298auto 1299FullO3CPU<Impl>::getWritableVecPredReg(PhysRegIdPtr phys_reg) 1300 -> VecPredRegContainer& 1301{ 1302 vecPredRegfileWrites++; 1303 return regFile.getWritableVecPredReg(phys_reg); 1304} 1305 1306template <class Impl> 1307RegVal 1308FullO3CPU<Impl>::readCCReg(PhysRegIdPtr phys_reg) 1309{ 1310 ccRegfileReads++; 1311 return regFile.readCCReg(phys_reg); 1312} 1313 1314template <class Impl> 1315void 1316FullO3CPU<Impl>::setIntReg(PhysRegIdPtr phys_reg, RegVal val) 1317{ 1318 intRegfileWrites++; 1319 regFile.setIntReg(phys_reg, val); 1320} 1321 1322template <class Impl> 1323void 1324FullO3CPU<Impl>::setFloatReg(PhysRegIdPtr phys_reg, RegVal val) 1325{ 1326 fpRegfileWrites++; 1327 regFile.setFloatReg(phys_reg, val); 1328} 1329 1330template <class Impl> 1331void 1332FullO3CPU<Impl>::setVecReg(PhysRegIdPtr phys_reg, const VecRegContainer& val) 1333{ 1334 vecRegfileWrites++; 1335 regFile.setVecReg(phys_reg, val); 1336} 1337 1338template <class Impl> 1339void 1340FullO3CPU<Impl>::setVecElem(PhysRegIdPtr phys_reg, const VecElem& val) 1341{ 1342 vecRegfileWrites++; 1343 regFile.setVecElem(phys_reg, val); 1344} 1345 1346template <class Impl> 1347void 1348FullO3CPU<Impl>::setVecPredReg(PhysRegIdPtr phys_reg, 1349 const VecPredRegContainer& val) 1350{ 1351 vecPredRegfileWrites++; 1352 regFile.setVecPredReg(phys_reg, val); 1353} 1354 1355template <class Impl> 1356void 1357FullO3CPU<Impl>::setCCReg(PhysRegIdPtr phys_reg, RegVal val) 1358{ 1359 ccRegfileWrites++; 1360 regFile.setCCReg(phys_reg, val); 1361} 1362 1363template <class Impl> 1364RegVal 1365FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 1366{ 1367 intRegfileReads++; 1368 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1369 RegId(IntRegClass, reg_idx)); 1370 1371 return regFile.readIntReg(phys_reg); 1372} 1373 1374template <class Impl> 1375RegVal 1376FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 1377{ 1378 fpRegfileReads++; 1379 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1380 RegId(FloatRegClass, reg_idx)); 1381 1382 return regFile.readFloatReg(phys_reg); 1383} 1384 1385template <class Impl> 1386auto 1387FullO3CPU<Impl>::readArchVecReg(int reg_idx, ThreadID tid) const 1388 -> const VecRegContainer& 1389{ 1390 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1391 RegId(VecRegClass, reg_idx)); 1392 return readVecReg(phys_reg); 1393} 1394 1395template <class Impl> 1396auto 1397FullO3CPU<Impl>::getWritableArchVecReg(int reg_idx, ThreadID tid) 1398 -> VecRegContainer& 1399{ 1400 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1401 RegId(VecRegClass, reg_idx)); 1402 return getWritableVecReg(phys_reg); 1403} 1404 1405template <class Impl> 1406auto 1407FullO3CPU<Impl>::readArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, 1408 ThreadID tid) const -> const VecElem& 1409{ 1410 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1411 RegId(VecElemClass, reg_idx, ldx)); 1412 return readVecElem(phys_reg); 1413} 1414 1415template <class Impl> 1416auto 1417FullO3CPU<Impl>::readArchVecPredReg(int reg_idx, ThreadID tid) const 1418 -> const VecPredRegContainer& 1419{ 1420 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1421 RegId(VecPredRegClass, reg_idx)); 1422 return readVecPredReg(phys_reg); 1423} 1424 1425template <class Impl> 1426auto 1427FullO3CPU<Impl>::getWritableArchVecPredReg(int reg_idx, ThreadID tid) 1428 -> VecPredRegContainer& 1429{ 1430 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1431 RegId(VecPredRegClass, reg_idx)); 1432 return getWritableVecPredReg(phys_reg); 1433} 1434 1435template <class Impl> 1436RegVal 1437FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 1438{ 1439 ccRegfileReads++; 1440 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1441 RegId(CCRegClass, reg_idx)); 1442 1443 return regFile.readCCReg(phys_reg); 1444} 1445 1446template <class Impl> 1447void 1448FullO3CPU<Impl>::setArchIntReg(int reg_idx, RegVal val, ThreadID tid) 1449{ 1450 intRegfileWrites++; 1451 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1452 RegId(IntRegClass, reg_idx)); 1453 1454 regFile.setIntReg(phys_reg, val); 1455} 1456 1457template <class Impl> 1458void 1459FullO3CPU<Impl>::setArchFloatReg(int reg_idx, RegVal val, ThreadID tid) 1460{ 1461 fpRegfileWrites++; 1462 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1463 RegId(FloatRegClass, reg_idx)); 1464 1465 regFile.setFloatReg(phys_reg, val); 1466} 1467 1468template <class Impl> 1469void 1470FullO3CPU<Impl>::setArchVecReg(int reg_idx, const VecRegContainer& val, 1471 ThreadID tid) 1472{ 1473 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1474 RegId(VecRegClass, reg_idx)); 1475 setVecReg(phys_reg, val); 1476} 1477 1478template <class Impl> 1479void 1480FullO3CPU<Impl>::setArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, 1481 const VecElem& val, ThreadID tid) 1482{ 1483 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1484 RegId(VecElemClass, reg_idx, ldx)); 1485 setVecElem(phys_reg, val); 1486} 1487 1488template <class Impl> 1489void 1490FullO3CPU<Impl>::setArchVecPredReg(int reg_idx, const VecPredRegContainer& val, 1491 ThreadID tid) 1492{ 1493 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1494 RegId(VecPredRegClass, reg_idx)); 1495 setVecPredReg(phys_reg, val); 1496} 1497 1498template <class Impl> 1499void 1500FullO3CPU<Impl>::setArchCCReg(int reg_idx, RegVal val, ThreadID tid) 1501{ 1502 ccRegfileWrites++; 1503 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1504 RegId(CCRegClass, reg_idx)); 1505 1506 regFile.setCCReg(phys_reg, val); 1507} 1508 1509template <class Impl> 1510TheISA::PCState 1511FullO3CPU<Impl>::pcState(ThreadID tid) 1512{ 1513 return commit.pcState(tid); 1514} 1515 1516template <class Impl> 1517void 1518FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 1519{ 1520 commit.pcState(val, tid); 1521} 1522 1523template <class Impl> 1524Addr 1525FullO3CPU<Impl>::instAddr(ThreadID tid) 1526{ 1527 return commit.instAddr(tid); 1528} 1529 1530template <class Impl> 1531Addr 1532FullO3CPU<Impl>::nextInstAddr(ThreadID tid) 1533{ 1534 return commit.nextInstAddr(tid); 1535} 1536 1537template <class Impl> 1538MicroPC 1539FullO3CPU<Impl>::microPC(ThreadID tid) 1540{ 1541 return commit.microPC(tid); 1542} 1543 1544template <class Impl> 1545void 1546FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1547{ 1548 this->thread[tid]->noSquashFromTC = true; 1549 this->commit.generateTCEvent(tid); 1550} 1551 1552template <class Impl> 1553typename FullO3CPU<Impl>::ListIt 1554FullO3CPU<Impl>::addInst(const DynInstPtr &inst) 1555{ 1556 instList.push_back(inst); 1557 1558 return --(instList.end()); 1559} 1560 1561template <class Impl> 1562void 1563FullO3CPU<Impl>::instDone(ThreadID tid, const DynInstPtr &inst) 1564{ 1565 // Keep an instruction count. 1566 if (!inst->isMicroop() || inst->isLastMicroop()) { 1567 thread[tid]->numInst++; 1568 thread[tid]->numInsts++; 1569 committedInsts[tid]++; 1570 system->totalNumInsts++; 1571 1572 // Check for instruction-count-based events. 1573 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1574 system->instEventQueue.serviceEvents(system->totalNumInsts); 1575 } 1576 thread[tid]->numOp++; 1577 thread[tid]->numOps++; 1578 committedOps[tid]++; 1579 1580 probeInstCommit(inst->staticInst, inst->instAddr()); 1581} 1582 1583template <class Impl> 1584void 1585FullO3CPU<Impl>::removeFrontInst(const DynInstPtr &inst) 1586{ 1587 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1588 "[sn:%lli]\n", 1589 inst->threadNumber, inst->pcState(), inst->seqNum); 1590 1591 removeInstsThisCycle = true; 1592 1593 // Remove the front instruction. 1594 removeList.push(inst->getInstListIt()); 1595} 1596 1597template <class Impl> 1598void 1599FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1600{ 1601 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1602 " list.\n", tid); 1603 1604 ListIt end_it; 1605 1606 bool rob_empty = false; 1607 1608 if (instList.empty()) { 1609 return; 1610 } else if (rob.isEmpty(tid)) { 1611 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1612 end_it = instList.begin(); 1613 rob_empty = true; 1614 } else { 1615 end_it = (rob.readTailInst(tid))->getInstListIt(); 1616 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1617 } 1618 1619 removeInstsThisCycle = true; 1620 1621 ListIt inst_it = instList.end(); 1622 1623 inst_it--; 1624 1625 // Walk through the instruction list, removing any instructions 1626 // that were inserted after the given instruction iterator, end_it. 1627 while (inst_it != end_it) { 1628 assert(!instList.empty()); 1629 1630 squashInstIt(inst_it, tid); 1631 1632 inst_it--; 1633 } 1634 1635 // If the ROB was empty, then we actually need to remove the first 1636 // instruction as well. 1637 if (rob_empty) { 1638 squashInstIt(inst_it, tid); 1639 } 1640} 1641 1642template <class Impl> 1643void 1644FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1645{ 1646 assert(!instList.empty()); 1647 1648 removeInstsThisCycle = true; 1649 1650 ListIt inst_iter = instList.end(); 1651 1652 inst_iter--; 1653 1654 DPRINTF(O3CPU, "Deleting instructions from instruction " 1655 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1656 tid, seq_num, (*inst_iter)->seqNum); 1657 1658 while ((*inst_iter)->seqNum > seq_num) { 1659 1660 bool break_loop = (inst_iter == instList.begin()); 1661 1662 squashInstIt(inst_iter, tid); 1663 1664 inst_iter--; 1665 1666 if (break_loop) 1667 break; 1668 } 1669} 1670 1671template <class Impl> 1672inline void 1673FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1674{ 1675 if ((*instIt)->threadNumber == tid) { 1676 DPRINTF(O3CPU, "Squashing instruction, " 1677 "[tid:%i] [sn:%lli] PC %s\n", 1678 (*instIt)->threadNumber, 1679 (*instIt)->seqNum, 1680 (*instIt)->pcState()); 1681 1682 // Mark it as squashed. 1683 (*instIt)->setSquashed(); 1684 1685 // @todo: Formulate a consistent method for deleting 1686 // instructions from the instruction list 1687 // Remove the instruction from the list. 1688 removeList.push(instIt); 1689 } 1690} 1691 1692template <class Impl> 1693void 1694FullO3CPU<Impl>::cleanUpRemovedInsts() 1695{ 1696 while (!removeList.empty()) { 1697 DPRINTF(O3CPU, "Removing instruction, " 1698 "[tid:%i] [sn:%lli] PC %s\n", 1699 (*removeList.front())->threadNumber, 1700 (*removeList.front())->seqNum, 1701 (*removeList.front())->pcState()); 1702 1703 instList.erase(removeList.front()); 1704 1705 removeList.pop(); 1706 } 1707 1708 removeInstsThisCycle = false; 1709} 1710/* 1711template <class Impl> 1712void 1713FullO3CPU<Impl>::removeAllInsts() 1714{ 1715 instList.clear(); 1716} 1717*/ 1718template <class Impl> 1719void 1720FullO3CPU<Impl>::dumpInsts() 1721{ 1722 int num = 0; 1723 1724 ListIt inst_list_it = instList.begin(); 1725 1726 cprintf("Dumping Instruction List\n"); 1727 1728 while (inst_list_it != instList.end()) { 1729 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1730 "Squashed:%i\n\n", 1731 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1732 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1733 (*inst_list_it)->isSquashed()); 1734 inst_list_it++; 1735 ++num; 1736 } 1737} 1738/* 1739template <class Impl> 1740void 1741FullO3CPU<Impl>::wakeDependents(const DynInstPtr &inst) 1742{ 1743 iew.wakeDependents(inst); 1744} 1745*/ 1746template <class Impl> 1747void 1748FullO3CPU<Impl>::wakeCPU() 1749{ 1750 if (activityRec.active() || tickEvent.scheduled()) { 1751 DPRINTF(Activity, "CPU already running.\n"); 1752 return; 1753 } 1754 1755 DPRINTF(Activity, "Waking up CPU\n"); 1756 1757 Cycles cycles(curCycle() - lastRunningCycle); 1758 // @todo: This is an oddity that is only here to match the stats 1759 if (cycles > 1) { 1760 --cycles; 1761 idleCycles += cycles; 1762 numCycles += cycles; 1763 } 1764 1765 schedule(tickEvent, clockEdge()); 1766} 1767 1768template <class Impl> 1769void 1770FullO3CPU<Impl>::wakeup(ThreadID tid) 1771{ 1772 if (this->thread[tid]->status() != ThreadContext::Suspended) 1773 return; 1774 1775 this->wakeCPU(); 1776 1777 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1778 this->threadContexts[tid]->activate(); 1779} 1780 1781template <class Impl> 1782ThreadID 1783FullO3CPU<Impl>::getFreeTid() 1784{ 1785 for (ThreadID tid = 0; tid < numThreads; tid++) { 1786 if (!tids[tid]) { 1787 tids[tid] = true; 1788 return tid; 1789 } 1790 } 1791 1792 return InvalidThreadID; 1793} 1794 1795template <class Impl> 1796void 1797FullO3CPU<Impl>::updateThreadPriority() 1798{ 1799 if (activeThreads.size() > 1) { 1800 //DEFAULT TO ROUND ROBIN SCHEME 1801 //e.g. Move highest priority to end of thread list 1802 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1803 1804 unsigned high_thread = *list_begin; 1805 1806 activeThreads.erase(list_begin); 1807 1808 activeThreads.push_back(high_thread); 1809 } 1810} 1811 1812template <class Impl> 1813void 1814FullO3CPU<Impl>::addThreadToExitingList(ThreadID tid) 1815{ 1816 DPRINTF(O3CPU, "Thread %d is inserted to exitingThreads list\n", tid); 1817 1818 // the thread trying to exit can't be already halted 1819 assert(tcBase(tid)->status() != ThreadContext::Halted); 1820 1821 // make sure the thread has not been added to the list yet 1822 assert(exitingThreads.count(tid) == 0); 1823 1824 // add the thread to exitingThreads list to mark that this thread is 1825 // trying to exit. The boolean value in the pair denotes if a thread is 1826 // ready to exit. The thread is not ready to exit until the corresponding 1827 // exit trap event is processed in the future. Until then, it'll be still 1828 // an active thread that is trying to exit. 1829 exitingThreads.emplace(std::make_pair(tid, false)); 1830} 1831 1832template <class Impl> 1833bool 1834FullO3CPU<Impl>::isThreadExiting(ThreadID tid) const 1835{ 1836 return exitingThreads.count(tid) == 1; 1837} 1838 1839template <class Impl> 1840void 1841FullO3CPU<Impl>::scheduleThreadExitEvent(ThreadID tid) 1842{ 1843 assert(exitingThreads.count(tid) == 1); 1844 1845 // exit trap event has been processed. Now, the thread is ready to exit 1846 // and be removed from the CPU. 1847 exitingThreads[tid] = true; 1848 1849 // we schedule a threadExitEvent in the next cycle to properly clean 1850 // up the thread's states in the pipeline. threadExitEvent has lower 1851 // priority than tickEvent, so the cleanup will happen at the very end 1852 // of the next cycle after all pipeline stages complete their operations. 1853 // We want all stages to complete squashing instructions before doing 1854 // the cleanup. 1855 if (!threadExitEvent.scheduled()) { 1856 schedule(threadExitEvent, nextCycle()); 1857 } 1858} 1859 1860template <class Impl> 1861void 1862FullO3CPU<Impl>::exitThreads() 1863{ 1864 // there must be at least one thread trying to exit 1865 assert(exitingThreads.size() > 0); 1866 1867 // terminate all threads that are ready to exit 1868 auto it = exitingThreads.begin(); 1869 while (it != exitingThreads.end()) { 1870 ThreadID thread_id = it->first; 1871 bool readyToExit = it->second; 1872 1873 if (readyToExit) { 1874 DPRINTF(O3CPU, "Exiting thread %d\n", thread_id); 1875 haltContext(thread_id); 1876 tcBase(thread_id)->setStatus(ThreadContext::Halted); 1877 it = exitingThreads.erase(it); 1878 } else { 1879 it++; 1880 } 1881 } 1882} 1883 1884// Forward declaration of FullO3CPU. 1885template class FullO3CPU<O3CPUImpl>; 1886