cpu.cc revision 12284
12623SN/A/* 22623SN/A * Copyright (c) 2011-2012, 2014, 2016, 2017 ARM Limited 32623SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 42623SN/A * All rights reserved 52623SN/A * 62623SN/A * The license below extends only to copyright in the software and shall 72623SN/A * not be construed as granting a license to any other intellectual 82623SN/A * property including but not limited to intellectual property relating 92623SN/A * to a hardware implementation of the functionality of the software 102623SN/A * licensed hereunder. You may use the software subject to the license 112623SN/A * terms below provided that you ensure that this notice is replicated 122623SN/A * unmodified and in its entirety in all distributions of the software, 132623SN/A * modified or unmodified, in source code or in binary form. 142623SN/A * 152623SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 162623SN/A * Copyright (c) 2011 Regents of the University of California 172623SN/A * All rights reserved. 182623SN/A * 192623SN/A * Redistribution and use in source and binary forms, with or without 202623SN/A * modification, are permitted provided that the following conditions are 212623SN/A * met: redistributions of source code must retain the above copyright 222623SN/A * notice, this list of conditions and the following disclaimer; 232623SN/A * redistributions in binary form must reproduce the above copyright 242623SN/A * notice, this list of conditions and the following disclaimer in the 252623SN/A * documentation and/or other materials provided with the distribution; 262623SN/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. 292623SN/A * 302623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 313170Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 325103Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 332623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 344040Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 356658Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 362623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 372623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 383348Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 393348Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 404762Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 417678Sgblack@eecs.umich.edu * 422901Ssaidi@eecs.umich.edu * Authors: Kevin Lim 432623SN/A * Korey Sewell 442623SN/A * Rick Strong 452623SN/A */ 462623SN/A 472856Srdreslin@umich.edu#include "cpu/o3/cpu.hh" 482856Srdreslin@umich.edu 492856Srdreslin@umich.edu#include "arch/generic/traits.hh" 502856Srdreslin@umich.edu#include "arch/kernel_stats.hh" 512856Srdreslin@umich.edu#include "config/the_isa.hh" 522856Srdreslin@umich.edu#include "cpu/activity.hh" 532856Srdreslin@umich.edu#include "cpu/checker/cpu.hh" 542856Srdreslin@umich.edu#include "cpu/checker/thread_context.hh" 552856Srdreslin@umich.edu#include "cpu/o3/isa_specific.hh" 562856Srdreslin@umich.edu#include "cpu/o3/thread_context.hh" 572623SN/A#include "cpu/quiesce_event.hh" 582623SN/A#include "cpu/simple_thread.hh" 592623SN/A#include "cpu/thread_context.hh" 602623SN/A#include "debug/Activity.hh" 612623SN/A#include "debug/Drain.hh" 622623SN/A#include "debug/O3CPU.hh" 632680Sktlim@umich.edu#include "debug/Quiesce.hh" 642680Sktlim@umich.edu#include "enums/MemoryMode.hh" 652623SN/A#include "sim/core.hh" 662623SN/A#include "sim/full_system.hh" 675712Shsul@eecs.umich.edu#include "sim/process.hh" 682623SN/A#include "sim/stat_control.hh" 692623SN/A#include "sim/system.hh" 702623SN/A 712623SN/A#if THE_ISA == ALPHA_ISA 722623SN/A#include "arch/alpha/osfpal.hh" 733349Sbinkertn@umich.edu#include "debug/Activity.hh" 742623SN/A 752623SN/A#endif 762623SN/A 772623SN/Astruct BaseCPUParams; 782623SN/A 792623SN/Ausing namespace TheISA; 803349Sbinkertn@umich.eduusing namespace std; 812623SN/A 823184Srdreslin@umich.eduBaseO3CPU::BaseO3CPU(BaseCPUParams *params) 833184Srdreslin@umich.edu : BaseCPU(params) 842623SN/A{ 852623SN/A} 862623SN/A 872623SN/Avoid 882623SN/ABaseO3CPU::regStats() 893647Srdreslin@umich.edu{ 903647Srdreslin@umich.edu BaseCPU::regStats(); 913647Srdreslin@umich.edu} 923647Srdreslin@umich.edu 933647Srdreslin@umich.edutemplate<class Impl> 942631SN/Abool 953647Srdreslin@umich.eduFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 962631SN/A{ 972623SN/A DPRINTF(O3CPU, "Fetch unit received timing\n"); 982623SN/A // We shouldn't ever get a cacheable block in Modified state 992623SN/A assert(pkt->req->isUncacheable() || 1002948Ssaidi@eecs.umich.edu !(pkt->cacheResponding() && !pkt->hasSharers())); 1012948Ssaidi@eecs.umich.edu fetch->processCacheCompletion(pkt); 1023349Sbinkertn@umich.edu 1032948Ssaidi@eecs.umich.edu return true; 1042948Ssaidi@eecs.umich.edu} 1055606Snate@binkert.org 1062948Ssaidi@eecs.umich.edutemplate<class Impl> 1072948Ssaidi@eecs.umich.eduvoid 1085529Snate@binkert.orgFullO3CPU<Impl>::IcachePort::recvReqRetry() 1095894Sgblack@eecs.umich.edu{ 1105894Sgblack@eecs.umich.edu fetch->recvReqRetry(); 1112623SN/A} 1122623SN/A 1133647Srdreslin@umich.edutemplate <class Impl> 1143647Srdreslin@umich.edubool 1153647Srdreslin@umich.eduFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 1163647Srdreslin@umich.edu{ 1172623SN/A return lsq->recvTimingResp(pkt); 1182839Sktlim@umich.edu} 1193222Sktlim@umich.edu 1202901Ssaidi@eecs.umich.edutemplate <class Impl> 1212623SN/Avoid 1222623SN/AFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 1232623SN/A{ 1242623SN/A for (ThreadID tid = 0; tid < cpu->numThreads; tid++) { 1252623SN/A if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) { 1262623SN/A cpu->wakeup(tid); 1272623SN/A } 1282623SN/A } 1292623SN/A lsq->recvTimingSnoopReq(pkt); 1302623SN/A} 1312915Sktlim@umich.edu 1322915Sktlim@umich.edutemplate <class Impl> 1332623SN/Avoid 1342623SN/AFullO3CPU<Impl>::DcachePort::recvReqRetry() 1352623SN/A{ 1362623SN/A lsq->recvReqRetry(); 1372623SN/A} 1382623SN/A 1392915Sktlim@umich.edutemplate <class Impl> 1402915Sktlim@umich.eduFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 1412623SN/A : BaseO3CPU(params), 1422798Sktlim@umich.edu itb(params->itb), 1432798Sktlim@umich.edu dtb(params->dtb), 1442901Ssaidi@eecs.umich.edu tickEvent([this]{ tick(); }, "FullO3CPU tick", 1452839Sktlim@umich.edu false, Event::CPU_Tick_Pri), 1462798Sktlim@umich.edu#ifndef NDEBUG 1472839Sktlim@umich.edu instcount(0), 1482798Sktlim@umich.edu#endif 1495496Ssaidi@eecs.umich.edu removeInstsThisCycle(false), 1502901Ssaidi@eecs.umich.edu fetch(this, params), 1512901Ssaidi@eecs.umich.edu decode(this, params), 1522798Sktlim@umich.edu rename(this, params), 1532839Sktlim@umich.edu iew(this, params), 1542839Sktlim@umich.edu commit(this, params), 1552901Ssaidi@eecs.umich.edu 1562798Sktlim@umich.edu /* It is mandatory that all SMT threads use the same renaming mode as 1572623SN/A * they are sharing registers and rename */ 1582623SN/A vecMode(initRenameMode<TheISA::ISA>::mode(params->isa[0])), 1592623SN/A regFile(params->numPhysIntRegs, 1602798Sktlim@umich.edu params->numPhysFloatRegs, 1612623SN/A params->numPhysVecRegs, 1625221Ssaidi@eecs.umich.edu params->numPhysCCRegs, 1632798Sktlim@umich.edu vecMode), 1644762Snate@binkert.org 1653201Shsul@eecs.umich.edu freeList(name() + ".freelist", ®File), 1665710Scws3k@cs.virginia.edu 1675710Scws3k@cs.virginia.edu rob(this, params), 1682915Sktlim@umich.edu 1695710Scws3k@cs.virginia.edu scoreboard(name() + ".scoreboard", 1702623SN/A regFile.totalNumPhysRegs()), 1712798Sktlim@umich.edu 1722901Ssaidi@eecs.umich.edu isa(numThreads, NULL), 1732798Sktlim@umich.edu 1742798Sktlim@umich.edu icachePort(&fetch, this), 1752798Sktlim@umich.edu dcachePort(&iew.ldstQueue, this), 1762798Sktlim@umich.edu 1772798Sktlim@umich.edu timeBuffer(params->backComSize, params->forwardComSize), 1785496Ssaidi@eecs.umich.edu fetchQueue(params->backComSize, params->forwardComSize), 1792798Sktlim@umich.edu decodeQueue(params->backComSize, params->forwardComSize), 1805099Ssaidi@eecs.umich.edu renameQueue(params->backComSize, params->forwardComSize), 1812867Sktlim@umich.edu iewQueue(params->backComSize, params->forwardComSize), 1822867Sktlim@umich.edu activityRec(name(), NumStages, 1832867Sktlim@umich.edu params->backComSize + params->forwardComSize, 1845710Scws3k@cs.virginia.edu params->activity), 1855606Snate@binkert.org 1862623SN/A globalSeqNum(1), 1872623SN/A system(params->system), 1882623SN/A lastRunningCycle(curCycle()) 1892623SN/A{ 1902623SN/A if (!params->switched_out) { 1912623SN/A _status = Running; 1924192Sktlim@umich.edu } else { 1932623SN/A _status = SwitchedOut; 1942680Sktlim@umich.edu } 1952623SN/A 1962680Sktlim@umich.edu if (params->checker) { 1972680Sktlim@umich.edu BaseCPU *temp_checker = params->checker; 1982680Sktlim@umich.edu checker = dynamic_cast<Checker<Impl> *>(temp_checker); 1992623SN/A checker->setIcachePort(&icachePort); 2002623SN/A checker->setSystem(params->system); 2012623SN/A } else { 2022623SN/A checker = NULL; 2033201Shsul@eecs.umich.edu } 2043201Shsul@eecs.umich.edu 2053201Shsul@eecs.umich.edu if (!FullSystem) { 2063201Shsul@eecs.umich.edu thread.resize(numThreads); 2075169Ssaidi@eecs.umich.edu tids.resize(numThreads); 2085101Ssaidi@eecs.umich.edu } 2092623SN/A 2102623SN/A // The stages also need their CPU pointer setup. However this 2112623SN/A // must be done at the upper level CPU because they have pointers 2122623SN/A // to the upper level CPU, and not this FullO3CPU. 2132623SN/A 2142623SN/A // Set up Pointers to the activeThreads list for each stage 2155221Ssaidi@eecs.umich.edu fetch.setActiveThreads(&activeThreads); 2165221Ssaidi@eecs.umich.edu decode.setActiveThreads(&activeThreads); 2172623SN/A rename.setActiveThreads(&activeThreads); 2182683Sktlim@umich.edu iew.setActiveThreads(&activeThreads); 2192623SN/A commit.setActiveThreads(&activeThreads); 2202623SN/A 2212623SN/A // Give each of the stages the time buffer they will use. 2222623SN/A fetch.setTimeBuffer(&timeBuffer); 2232623SN/A decode.setTimeBuffer(&timeBuffer); 2243686Sktlim@umich.edu rename.setTimeBuffer(&timeBuffer); 2252623SN/A iew.setTimeBuffer(&timeBuffer); 2265606Snate@binkert.org commit.setTimeBuffer(&timeBuffer); 2272623SN/A 2282623SN/A // Also setup each of the stages' queues. 2292623SN/A fetch.setFetchQueue(&fetchQueue); 2302623SN/A decode.setFetchQueue(&fetchQueue); 2312623SN/A commit.setFetchQueue(&fetchQueue); 2322623SN/A decode.setDecodeQueue(&decodeQueue); 2335221Ssaidi@eecs.umich.edu rename.setDecodeQueue(&decodeQueue); 2345221Ssaidi@eecs.umich.edu rename.setRenameQueue(&renameQueue); 2352623SN/A iew.setRenameQueue(&renameQueue); 2362683Sktlim@umich.edu iew.setIEWQueue(&iewQueue); 2372623SN/A commit.setIEWQueue(&iewQueue); 2386043Sgblack@eecs.umich.edu commit.setRenameQueue(&renameQueue); 2396043Sgblack@eecs.umich.edu 2406043Sgblack@eecs.umich.edu commit.setIEWStage(&iew); 2412644Sstever@eecs.umich.edu rename.setIEWStage(&iew); 2422623SN/A rename.setCommitStage(&commit); 2432644Sstever@eecs.umich.edu 2442644Sstever@eecs.umich.edu ThreadID active_threads; 2452623SN/A if (FullSystem) { 2462623SN/A active_threads = 1; 2472623SN/A } else { 2482623SN/A active_threads = params->workload.size(); 2492623SN/A 2505728Sgblack@eecs.umich.edu if (active_threads > Impl::MaxThreads) { 2515728Sgblack@eecs.umich.edu panic("Workload Size too large. Increase the 'MaxThreads' " 2525728Sgblack@eecs.umich.edu "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 2535728Sgblack@eecs.umich.edu "or edit your workload size."); 2545728Sgblack@eecs.umich.edu } 2555728Sgblack@eecs.umich.edu } 2565728Sgblack@eecs.umich.edu 2575728Sgblack@eecs.umich.edu //Make Sure That this a Valid Architeture 2585728Sgblack@eecs.umich.edu assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 2595728Sgblack@eecs.umich.edu assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 2605728Sgblack@eecs.umich.edu assert(params->numPhysVecRegs >= numThreads * TheISA::NumVecRegs); 2615728Sgblack@eecs.umich.edu assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 2625728Sgblack@eecs.umich.edu 2635728Sgblack@eecs.umich.edu rename.setScoreboard(&scoreboard); 2645728Sgblack@eecs.umich.edu iew.setScoreboard(&scoreboard); 2655728Sgblack@eecs.umich.edu 2665728Sgblack@eecs.umich.edu // Setup the rename map for whichever stages need it. 2675728Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 2685728Sgblack@eecs.umich.edu isa[tid] = params->isa[tid]; 2695728Sgblack@eecs.umich.edu assert(initRenameMode<TheISA::ISA>::equals(isa[tid], isa[0])); 2702623SN/A 2715894Sgblack@eecs.umich.edu // Only Alpha has an FP zero register, so for other ISAs we 2726973Stjones1@inf.ed.ac.uk // use an invalid FP register index to avoid special treatment 2736973Stjones1@inf.ed.ac.uk // of any valid FP reg. 2745744Sgblack@eecs.umich.edu RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 2755894Sgblack@eecs.umich.edu RegIndex fpZeroReg = 2765894Sgblack@eecs.umich.edu (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 2777691SAli.Saidi@ARM.com 2785894Sgblack@eecs.umich.edu commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 2795894Sgblack@eecs.umich.edu &freeList, 2805894Sgblack@eecs.umich.edu vecMode); 2815894Sgblack@eecs.umich.edu 2825894Sgblack@eecs.umich.edu renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 2835894Sgblack@eecs.umich.edu &freeList, vecMode); 2845894Sgblack@eecs.umich.edu } 2855894Sgblack@eecs.umich.edu 2865894Sgblack@eecs.umich.edu // Initialize rename map to assign physical registers to the 2876102Sgblack@eecs.umich.edu // architectural registers for active threads only. 2885894Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < active_threads; tid++) { 2895894Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 2905894Sgblack@eecs.umich.edu // Note that we can't use the rename() method because we don't 2915894Sgblack@eecs.umich.edu // want special treatment for the zero register at this point 2925894Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getIntReg(); 2935894Sgblack@eecs.umich.edu renameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg); 2945894Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg); 2955894Sgblack@eecs.umich.edu } 2965894Sgblack@eecs.umich.edu 2975894Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 2985894Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getFloatReg(); 2995894Sgblack@eecs.umich.edu renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg); 3005894Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry( 3015894Sgblack@eecs.umich.edu RegId(FloatRegClass, ridx), phys_reg); 3025894Sgblack@eecs.umich.edu } 3035894Sgblack@eecs.umich.edu 3045894Sgblack@eecs.umich.edu /* Here we need two 'interfaces' the 'whole register' and the 3056973Stjones1@inf.ed.ac.uk * 'register element'. At any point only one of them will be 3066973Stjones1@inf.ed.ac.uk * active. */ 3075894Sgblack@eecs.umich.edu if (vecMode == Enums::Full) { 3085894Sgblack@eecs.umich.edu /* Initialize the full-vector interface */ 3095894Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { 3105894Sgblack@eecs.umich.edu RegId rid = RegId(VecRegClass, ridx); 3115894Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getVecReg(); 3125894Sgblack@eecs.umich.edu renameMap[tid].setEntry(rid, phys_reg); 3135894Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(rid, phys_reg); 3145894Sgblack@eecs.umich.edu } 3155894Sgblack@eecs.umich.edu } else { 3165894Sgblack@eecs.umich.edu /* Initialize the vector-element interface */ 3175894Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) { 3185894Sgblack@eecs.umich.edu for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg; 3195894Sgblack@eecs.umich.edu ++ldx) { 3205894Sgblack@eecs.umich.edu RegId lrid = RegId(VecElemClass, ridx, ldx); 3215894Sgblack@eecs.umich.edu PhysRegIdPtr phys_elem = freeList.getVecElem(); 3225894Sgblack@eecs.umich.edu renameMap[tid].setEntry(lrid, phys_elem); 3235894Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(lrid, phys_elem); 3245894Sgblack@eecs.umich.edu } 3255894Sgblack@eecs.umich.edu } 3265894Sgblack@eecs.umich.edu } 3275894Sgblack@eecs.umich.edu 3285894Sgblack@eecs.umich.edu for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 3295894Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getCCReg(); 3305894Sgblack@eecs.umich.edu renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg); 3315894Sgblack@eecs.umich.edu commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg); 3325894Sgblack@eecs.umich.edu } 3335894Sgblack@eecs.umich.edu } 3345894Sgblack@eecs.umich.edu 3355894Sgblack@eecs.umich.edu rename.setRenameMap(renameMap); 3365894Sgblack@eecs.umich.edu commit.setRenameMap(commitRenameMap); 3375894Sgblack@eecs.umich.edu rename.setFreeList(&freeList); 3385894Sgblack@eecs.umich.edu 3395894Sgblack@eecs.umich.edu // Setup the ROB for whichever stages need it. 3405894Sgblack@eecs.umich.edu commit.setROB(&rob); 3415894Sgblack@eecs.umich.edu 3425894Sgblack@eecs.umich.edu lastActivatedCycle = 0; 3435894Sgblack@eecs.umich.edu#if 0 3446739Sgblack@eecs.umich.edu // Give renameMap & rename stage access to the freeList; 3456739Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 3465894Sgblack@eecs.umich.edu globalSeqNum[tid] = 1; 3475894Sgblack@eecs.umich.edu#endif 3485894Sgblack@eecs.umich.edu 3495894Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Creating O3CPU object.\n"); 3505894Sgblack@eecs.umich.edu 3515894Sgblack@eecs.umich.edu // Setup any thread state. 3525894Sgblack@eecs.umich.edu this->thread.resize(this->numThreads); 3535744Sgblack@eecs.umich.edu 3545744Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 3555894Sgblack@eecs.umich.edu if (FullSystem) { 3565894Sgblack@eecs.umich.edu // SMT is not supported in FS mode yet. 3575894Sgblack@eecs.umich.edu assert(this->numThreads == 1); 3585894Sgblack@eecs.umich.edu this->thread[tid] = new Thread(this, 0, NULL); 3595894Sgblack@eecs.umich.edu } else { 3605894Sgblack@eecs.umich.edu if (tid < params->workload.size()) { 3615894Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Workload[%i] process is %#x", 3625894Sgblack@eecs.umich.edu tid, this->thread[tid]); 3635894Sgblack@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3645894Sgblack@eecs.umich.edu (typename Impl::O3CPU *)(this), 3655894Sgblack@eecs.umich.edu tid, params->workload[tid]); 3665894Sgblack@eecs.umich.edu 3675894Sgblack@eecs.umich.edu //usedTids[tid] = true; 3685894Sgblack@eecs.umich.edu //threadMap[tid] = tid; 3695894Sgblack@eecs.umich.edu } else { 3705894Sgblack@eecs.umich.edu //Allocate Empty thread so M5 can use later 3716102Sgblack@eecs.umich.edu //when scheduling threads to CPU 3725894Sgblack@eecs.umich.edu Process* dummy_proc = NULL; 3735894Sgblack@eecs.umich.edu 3745894Sgblack@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 3756102Sgblack@eecs.umich.edu (typename Impl::O3CPU *)(this), 3765894Sgblack@eecs.umich.edu tid, dummy_proc); 3775894Sgblack@eecs.umich.edu //usedTids[tid] = false; 3785894Sgblack@eecs.umich.edu } 3795894Sgblack@eecs.umich.edu } 3805894Sgblack@eecs.umich.edu 3815894Sgblack@eecs.umich.edu ThreadContext *tc; 3825894Sgblack@eecs.umich.edu 3835894Sgblack@eecs.umich.edu // Setup the TC that will serve as the interface to the threads/CPU. 3845894Sgblack@eecs.umich.edu O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 3855894Sgblack@eecs.umich.edu 3865894Sgblack@eecs.umich.edu tc = o3_tc; 3875894Sgblack@eecs.umich.edu 3885894Sgblack@eecs.umich.edu // If we're using a checker, then the TC should be the 3895894Sgblack@eecs.umich.edu // CheckerThreadContext. 3905894Sgblack@eecs.umich.edu if (params->checker) { 3915744Sgblack@eecs.umich.edu tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 3925744Sgblack@eecs.umich.edu o3_tc, this->checker); 3935894Sgblack@eecs.umich.edu } 3945894Sgblack@eecs.umich.edu 3955894Sgblack@eecs.umich.edu o3_tc->cpu = (typename Impl::O3CPU *)(this); 3965894Sgblack@eecs.umich.edu assert(o3_tc->cpu); 3975894Sgblack@eecs.umich.edu o3_tc->thread = this->thread[tid]; 3985894Sgblack@eecs.umich.edu 3995894Sgblack@eecs.umich.edu // Setup quiesce event. 4005894Sgblack@eecs.umich.edu this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 4015744Sgblack@eecs.umich.edu 4025744Sgblack@eecs.umich.edu // Give the thread the TC. 4035744Sgblack@eecs.umich.edu this->thread[tid]->tc = tc; 4045744Sgblack@eecs.umich.edu 4057691SAli.Saidi@ARM.com // Add the TC to the CPU's list of TC's. 4065744Sgblack@eecs.umich.edu this->threadContexts.push_back(tc); 4075744Sgblack@eecs.umich.edu } 4085744Sgblack@eecs.umich.edu 4095744Sgblack@eecs.umich.edu // FullO3CPU always requires an interrupt controller. 4105744Sgblack@eecs.umich.edu if (!params->switched_out && interrupts.empty()) { 4115744Sgblack@eecs.umich.edu fatal("FullO3CPU %s has no interrupt controller.\n" 4125744Sgblack@eecs.umich.edu "Ensure createInterruptController() is called.\n", name()); 4135744Sgblack@eecs.umich.edu } 4145744Sgblack@eecs.umich.edu 4155744Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; tid++) 4165744Sgblack@eecs.umich.edu this->thread[tid]->setFuncExeInst(0); 4175744Sgblack@eecs.umich.edu} 4182623SN/A 4197520Sgblack@eecs.umich.edutemplate <class Impl> 4207520Sgblack@eecs.umich.eduFullO3CPU<Impl>::~FullO3CPU() 4212623SN/A{ 4225728Sgblack@eecs.umich.edu} 4235728Sgblack@eecs.umich.edu 4246221Snate@binkert.orgtemplate <class Impl> 4257720Sgblack@eecs.umich.eduvoid 4266227Snate@binkert.orgFullO3CPU<Impl>::regProbePoints() 4276973Stjones1@inf.ed.ac.uk{ 4282623SN/A BaseCPU::regProbePoints(); 4297045Ssteve.reinhardt@amd.com 4307045Ssteve.reinhardt@amd.com ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete"); 4317045Ssteve.reinhardt@amd.com ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete"); 4327045Ssteve.reinhardt@amd.com 4337520Sgblack@eecs.umich.edu fetch.regProbePoints(); 4346221Snate@binkert.org rename.regProbePoints(); 4355728Sgblack@eecs.umich.edu iew.regProbePoints(); 4367520Sgblack@eecs.umich.edu commit.regProbePoints(); 4375744Sgblack@eecs.umich.edu} 4385728Sgblack@eecs.umich.edu 4395894Sgblack@eecs.umich.edutemplate <class Impl> 4405744Sgblack@eecs.umich.eduvoid 4415894Sgblack@eecs.umich.eduFullO3CPU<Impl>::regStats() 4426102Sgblack@eecs.umich.edu{ 4435894Sgblack@eecs.umich.edu BaseO3CPU::regStats(); 4445894Sgblack@eecs.umich.edu 4456973Stjones1@inf.ed.ac.uk // Register any of the O3CPU's stats here. 4467520Sgblack@eecs.umich.edu timesIdled 4476973Stjones1@inf.ed.ac.uk .name(name() + ".timesIdled") 4486973Stjones1@inf.ed.ac.uk .desc("Number of times that the entire CPU went into an idle state and" 4496973Stjones1@inf.ed.ac.uk " unscheduled itself") 4506973Stjones1@inf.ed.ac.uk .prereq(timesIdled); 4516973Stjones1@inf.ed.ac.uk 4526973Stjones1@inf.ed.ac.uk idleCycles 4536973Stjones1@inf.ed.ac.uk .name(name() + ".idleCycles") 4546973Stjones1@inf.ed.ac.uk .desc("Total number of cycles that the CPU has spent unscheduled due " 4555744Sgblack@eecs.umich.edu "to idling") 4566973Stjones1@inf.ed.ac.uk .prereq(idleCycles); 4577520Sgblack@eecs.umich.edu 4586973Stjones1@inf.ed.ac.uk quiesceCycles 4596973Stjones1@inf.ed.ac.uk .name(name() + ".quiesceCycles") 4606973Stjones1@inf.ed.ac.uk .desc("Total number of cycles that CPU has spent quiesced or waiting " 4612623SN/A "for an interrupt") 4622623SN/A .prereq(quiesceCycles); 4635728Sgblack@eecs.umich.edu 4642623SN/A // Number of Instructions simulated 4652623SN/A // -------------------------------- 4667520Sgblack@eecs.umich.edu // Should probably be in Base CPU but need templated 4677520Sgblack@eecs.umich.edu // MaxThreads so put in here instead 4687520Sgblack@eecs.umich.edu committedInsts 4697520Sgblack@eecs.umich.edu .init(numThreads) 4707520Sgblack@eecs.umich.edu .name(name() + ".committedInsts") 4717520Sgblack@eecs.umich.edu .desc("Number of Instructions Simulated") 4727520Sgblack@eecs.umich.edu .flags(Stats::total); 4732623SN/A 4742623SN/A committedOps 4752623SN/A .init(numThreads) 4762623SN/A .name(name() + ".committedOps") 4774040Ssaidi@eecs.umich.edu .desc("Number of Ops (including micro ops) Simulated") 4784040Ssaidi@eecs.umich.edu .flags(Stats::total); 4794040Ssaidi@eecs.umich.edu 4804040Ssaidi@eecs.umich.edu cpi 4814115Ssaidi@eecs.umich.edu .name(name() + ".cpi") 4824115Ssaidi@eecs.umich.edu .desc("CPI: Cycles Per Instruction") 4834115Ssaidi@eecs.umich.edu .precision(6); 4844115Ssaidi@eecs.umich.edu cpi = numCycles / committedInsts; 4852623SN/A 4862623SN/A totalCpi 4872623SN/A .name(name() + ".cpi_total") 4882623SN/A .desc("CPI: Total CPI of All Threads") 4892623SN/A .precision(6); 4902623SN/A totalCpi = numCycles / sum(committedInsts); 4912623SN/A 4922623SN/A ipc 4932623SN/A .name(name() + ".ipc") 4942623SN/A .desc("IPC: Instructions Per Cycle") 4952623SN/A .precision(6); 4962623SN/A ipc = committedInsts / numCycles; 4972623SN/A 4982623SN/A totalIpc 4992623SN/A .name(name() + ".ipc_total") 5002623SN/A .desc("IPC: Total IPC of All Threads") 5012623SN/A .precision(6); 5022623SN/A totalIpc = sum(committedInsts) / numCycles; 5032623SN/A 5042623SN/A this->fetch.regStats(); 5052623SN/A this->decode.regStats(); 5062623SN/A this->rename.regStats(); 5072623SN/A this->iew.regStats(); 5082623SN/A this->commit.regStats(); 5092623SN/A this->rob.regStats(); 5102623SN/A 5112623SN/A intRegfileReads 5122623SN/A .name(name() + ".int_regfile_reads") 5132623SN/A .desc("number of integer regfile reads") 5142623SN/A .prereq(intRegfileReads); 5152623SN/A 5162623SN/A intRegfileWrites 5172623SN/A .name(name() + ".int_regfile_writes") 5182623SN/A .desc("number of integer regfile writes") 5192623SN/A .prereq(intRegfileWrites); 5202623SN/A 5212623SN/A fpRegfileReads 5225728Sgblack@eecs.umich.edu .name(name() + ".fp_regfile_reads") 5235728Sgblack@eecs.umich.edu .desc("number of floating regfile reads") 5245728Sgblack@eecs.umich.edu .prereq(fpRegfileReads); 5255728Sgblack@eecs.umich.edu 5265728Sgblack@eecs.umich.edu fpRegfileWrites 5275728Sgblack@eecs.umich.edu .name(name() + ".fp_regfile_writes") 5285728Sgblack@eecs.umich.edu .desc("number of floating regfile writes") 5295728Sgblack@eecs.umich.edu .prereq(fpRegfileWrites); 5305728Sgblack@eecs.umich.edu 5315728Sgblack@eecs.umich.edu vecRegfileReads 5325728Sgblack@eecs.umich.edu .name(name() + ".vec_regfile_reads") 5335728Sgblack@eecs.umich.edu .desc("number of vector regfile reads") 5345728Sgblack@eecs.umich.edu .prereq(vecRegfileReads); 5355728Sgblack@eecs.umich.edu 5365728Sgblack@eecs.umich.edu vecRegfileWrites 5375728Sgblack@eecs.umich.edu .name(name() + ".vec_regfile_writes") 5385728Sgblack@eecs.umich.edu .desc("number of vector regfile writes") 5395728Sgblack@eecs.umich.edu .prereq(vecRegfileWrites); 5405728Sgblack@eecs.umich.edu 5412623SN/A ccRegfileReads 5422623SN/A .name(name() + ".cc_regfile_reads") 5437520Sgblack@eecs.umich.edu .desc("number of cc regfile reads") 5447520Sgblack@eecs.umich.edu .prereq(ccRegfileReads); 5452623SN/A 5465728Sgblack@eecs.umich.edu ccRegfileWrites 5476221Snate@binkert.org .name(name() + ".cc_regfile_writes") 5487720Sgblack@eecs.umich.edu .desc("number of cc regfile writes") 5496227Snate@binkert.org .prereq(ccRegfileWrites); 5506973Stjones1@inf.ed.ac.uk 5513169Sstever@eecs.umich.edu miscRegfileReads 5527045Ssteve.reinhardt@amd.com .name(name() + ".misc_regfile_reads") 5537045Ssteve.reinhardt@amd.com .desc("number of misc regfile reads") 5547045Ssteve.reinhardt@amd.com .prereq(miscRegfileReads); 5557045Ssteve.reinhardt@amd.com 5567520Sgblack@eecs.umich.edu miscRegfileWrites 5576221Snate@binkert.org .name(name() + ".misc_regfile_writes") 5585728Sgblack@eecs.umich.edu .desc("number of misc regfile writes") 5597520Sgblack@eecs.umich.edu .prereq(miscRegfileWrites); 5605744Sgblack@eecs.umich.edu} 5615728Sgblack@eecs.umich.edu 5625894Sgblack@eecs.umich.edutemplate <class Impl> 5635744Sgblack@eecs.umich.eduvoid 5645894Sgblack@eecs.umich.eduFullO3CPU<Impl>::tick() 5656102Sgblack@eecs.umich.edu{ 5665894Sgblack@eecs.umich.edu DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 5675894Sgblack@eecs.umich.edu assert(!switchedOut()); 5686973Stjones1@inf.ed.ac.uk assert(drainState() != DrainState::Drained); 5697520Sgblack@eecs.umich.edu 5706973Stjones1@inf.ed.ac.uk ++numCycles; 5716973Stjones1@inf.ed.ac.uk updateCycleCounters(BaseCPU::CPU_STATE_ON); 5726973Stjones1@inf.ed.ac.uk 5736973Stjones1@inf.ed.ac.uk// activity = false; 5746973Stjones1@inf.ed.ac.uk 5756973Stjones1@inf.ed.ac.uk //Tick each of the stages 5766973Stjones1@inf.ed.ac.uk fetch.tick(); 5775744Sgblack@eecs.umich.edu 5786973Stjones1@inf.ed.ac.uk decode.tick(); 5797520Sgblack@eecs.umich.edu 5806973Stjones1@inf.ed.ac.uk rename.tick(); 5816973Stjones1@inf.ed.ac.uk 5826973Stjones1@inf.ed.ac.uk iew.tick(); 5832623SN/A 5842623SN/A commit.tick(); 5857045Ssteve.reinhardt@amd.com 5865728Sgblack@eecs.umich.edu // Now advance the time buffers 5872623SN/A timeBuffer.advance(); 5882623SN/A 5897520Sgblack@eecs.umich.edu fetchQueue.advance(); 5907520Sgblack@eecs.umich.edu decodeQueue.advance(); 5917520Sgblack@eecs.umich.edu renameQueue.advance(); 5927520Sgblack@eecs.umich.edu iewQueue.advance(); 5937520Sgblack@eecs.umich.edu 5947520Sgblack@eecs.umich.edu activityRec.advance(); 5957520Sgblack@eecs.umich.edu 5967520Sgblack@eecs.umich.edu if (removeInstsThisCycle) { 5977520Sgblack@eecs.umich.edu cleanUpRemovedInsts(); 5987520Sgblack@eecs.umich.edu } 5997520Sgblack@eecs.umich.edu 6007520Sgblack@eecs.umich.edu if (!tickEvent.scheduled()) { 6017520Sgblack@eecs.umich.edu if (_status == SwitchedOut) { 6027520Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Switched out!\n"); 6037520Sgblack@eecs.umich.edu // increment stat 6047520Sgblack@eecs.umich.edu lastRunningCycle = curCycle(); 6057691SAli.Saidi@ARM.com } else if (!activityRec.active() || _status == Idle) { 6067520Sgblack@eecs.umich.edu DPRINTF(O3CPU, "Idle!\n"); 6077520Sgblack@eecs.umich.edu lastRunningCycle = curCycle(); 6087520Sgblack@eecs.umich.edu timesIdled++; 6097520Sgblack@eecs.umich.edu } else { 6107520Sgblack@eecs.umich.edu schedule(tickEvent, clockEdge(Cycles(1))); 6112623SN/A DPRINTF(O3CPU, "Scheduling next tick!\n"); 6122623SN/A } 6132623SN/A } 6142623SN/A 6154224Sgblack@eecs.umich.edu if (!FullSystem) 6164224Sgblack@eecs.umich.edu updateThreadPriority(); 6174224Sgblack@eecs.umich.edu 6184224Sgblack@eecs.umich.edu tryDrain(); 6194224Sgblack@eecs.umich.edu} 6204224Sgblack@eecs.umich.edu 6214224Sgblack@eecs.umich.edutemplate <class Impl> 6224224Sgblack@eecs.umich.eduvoid 6234224Sgblack@eecs.umich.eduFullO3CPU<Impl>::init() 6244224Sgblack@eecs.umich.edu{ 6252623SN/A BaseCPU::init(); 6262623SN/A 6272623SN/A for (ThreadID tid = 0; tid < numThreads; ++tid) { 6282623SN/A // Set noSquashFromTC so that the CPU doesn't squash when initially 6292623SN/A // setting up registers. 6302623SN/A thread[tid]->noSquashFromTC = true; 6312623SN/A // Initialise the ThreadContext's memory proxies 6322623SN/A thread[tid]->initMemProxies(thread[tid]->getTC()); 6332623SN/A } 6342623SN/A 6352623SN/A if (FullSystem && !params()->switched_out) { 6362623SN/A for (ThreadID tid = 0; tid < numThreads; tid++) { 6372623SN/A ThreadContext *src_tc = threadContexts[tid]; 6382623SN/A TheISA::initCPU(src_tc, src_tc->contextId()); 6392623SN/A } 6402623SN/A } 6412623SN/A 6422623SN/A // Clear noSquashFromTC. 6432623SN/A for (int tid = 0; tid < numThreads; ++tid) 6442623SN/A thread[tid]->noSquashFromTC = false; 6452623SN/A 6462623SN/A commit.setThreads(thread); 6472623SN/A} 6482623SN/A 6492623SN/Atemplate <class Impl> 6502623SN/Avoid 6512623SN/AFullO3CPU<Impl>::startup() 6522623SN/A{ 6532623SN/A BaseCPU::startup(); 6542623SN/A for (int tid = 0; tid < numThreads; ++tid) 6552623SN/A isa[tid]->startup(threadContexts[tid]); 6562623SN/A 6572623SN/A fetch.startupStage(); 6582623SN/A decode.startupStage(); 6592623SN/A iew.startupStage(); 6602623SN/A rename.startupStage(); 6612623SN/A commit.startupStage(); 6622623SN/A} 6632623SN/A 6642623SN/Atemplate <class Impl> 6652623SN/Avoid 6662623SN/AFullO3CPU<Impl>::activateThread(ThreadID tid) 6672623SN/A{ 6682623SN/A list<ThreadID>::iterator isActive = 6696973Stjones1@inf.ed.ac.uk std::find(activeThreads.begin(), activeThreads.end(), tid); 6706973Stjones1@inf.ed.ac.uk 6716973Stjones1@inf.ed.ac.uk DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 6726973Stjones1@inf.ed.ac.uk assert(!switchedOut()); 6736973Stjones1@inf.ed.ac.uk 6746973Stjones1@inf.ed.ac.uk if (isActive == activeThreads.end()) { 6756973Stjones1@inf.ed.ac.uk DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 6766973Stjones1@inf.ed.ac.uk tid); 6777691SAli.Saidi@ARM.com 6786973Stjones1@inf.ed.ac.uk activeThreads.push_back(tid); 6796973Stjones1@inf.ed.ac.uk } 6806973Stjones1@inf.ed.ac.uk} 6816973Stjones1@inf.ed.ac.uk 6826973Stjones1@inf.ed.ac.uktemplate <class Impl> 6836973Stjones1@inf.ed.ac.ukvoid 6846973Stjones1@inf.ed.ac.ukFullO3CPU<Impl>::deactivateThread(ThreadID tid) 6856973Stjones1@inf.ed.ac.uk{ 6866973Stjones1@inf.ed.ac.uk //Remove From Active List, if Active 6876973Stjones1@inf.ed.ac.uk list<ThreadID>::iterator thread_it = 6886973Stjones1@inf.ed.ac.uk std::find(activeThreads.begin(), activeThreads.end(), tid); 6896973Stjones1@inf.ed.ac.uk 6906973Stjones1@inf.ed.ac.uk DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 6916973Stjones1@inf.ed.ac.uk assert(!switchedOut()); 6926973Stjones1@inf.ed.ac.uk 6936973Stjones1@inf.ed.ac.uk if (thread_it != activeThreads.end()) { 6946973Stjones1@inf.ed.ac.uk DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 6952623SN/A tid); 6962623SN/A activeThreads.erase(thread_it); 6975221Ssaidi@eecs.umich.edu } 6985221Ssaidi@eecs.umich.edu 6993387Sgblack@eecs.umich.edu fetch.deactivateThread(tid); 7003387Sgblack@eecs.umich.edu commit.deactivateThread(tid); 7012631SN/A} 7025348Ssaidi@eecs.umich.edu 7035348Ssaidi@eecs.umich.edutemplate <class Impl> 7047720Sgblack@eecs.umich.eduCounter 7057720Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalInsts() const 7062623SN/A{ 7077720Sgblack@eecs.umich.edu Counter total(0); 7085669Sgblack@eecs.umich.edu 7095712Shsul@eecs.umich.edu ThreadID size = thread.size(); 7105894Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; i++) 7116023Snate@binkert.org total += thread[i]->numInst; 7126023Snate@binkert.org 7132623SN/A return total; 7145669Sgblack@eecs.umich.edu} 7155669Sgblack@eecs.umich.edu 7165894Sgblack@eecs.umich.edutemplate <class Impl> 7175894Sgblack@eecs.umich.eduCounter 7185894Sgblack@eecs.umich.eduFullO3CPU<Impl>::totalOps() const 7195894Sgblack@eecs.umich.edu{ 7205894Sgblack@eecs.umich.edu Counter total(0); 7215894Sgblack@eecs.umich.edu 7225894Sgblack@eecs.umich.edu ThreadID size = thread.size(); 7235894Sgblack@eecs.umich.edu for (ThreadID i = 0; i < size; i++) 7245894Sgblack@eecs.umich.edu total += thread[i]->numOp; 7255894Sgblack@eecs.umich.edu 7265894Sgblack@eecs.umich.edu return total; 7275894Sgblack@eecs.umich.edu} 7285894Sgblack@eecs.umich.edu 7295894Sgblack@eecs.umich.edutemplate <class Impl> 7305894Sgblack@eecs.umich.eduvoid 7315894Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateContext(ThreadID tid) 7325894Sgblack@eecs.umich.edu{ 7335894Sgblack@eecs.umich.edu assert(!switchedOut()); 7345894Sgblack@eecs.umich.edu 7355894Sgblack@eecs.umich.edu // Needs to set each stage to running as well. 7365894Sgblack@eecs.umich.edu activateThread(tid); 7375894Sgblack@eecs.umich.edu 7385894Sgblack@eecs.umich.edu // We don't want to wake the CPU if it is drained. In that case, 7395894Sgblack@eecs.umich.edu // we just want to flag the thread as active and schedule the tick 7405894Sgblack@eecs.umich.edu // event from drainResume() instead. 7415894Sgblack@eecs.umich.edu if (drainState() == DrainState::Drained) 7425894Sgblack@eecs.umich.edu return; 7432623SN/A 7443222Sktlim@umich.edu // If we are time 0 or if the last activation time is in the past, 7455099Ssaidi@eecs.umich.edu // schedule the next tick and wake up the fetch unit 7463222Sktlim@umich.edu if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 7472623SN/A scheduleTickEvent(Cycles(0)); 7482623SN/A 7492623SN/A // Be sure to signal that there's some activity so the CPU doesn't 7502623SN/A // deschedule itself. 7512644Sstever@eecs.umich.edu activityRec.activity(); 7522623SN/A fetch.wakeFromQuiesce(); 7535726Sgblack@eecs.umich.edu 7545726Sgblack@eecs.umich.edu Cycles cycles(curCycle() - lastRunningCycle); 7552623SN/A // @todo: This is an oddity that is only here to match the stats 7562631SN/A if (cycles != 0) 7572631SN/A --cycles; 7582631SN/A quiesceCycles += cycles; 7592631SN/A 7602631SN/A lastActivatedCycle = curTick(); 7612631SN/A 7622623SN/A _status = Running; 7632623SN/A 7642623SN/A BaseCPU::activateContext(tid); 7652623SN/A } 7663349Sbinkertn@umich.edu} 7672623SN/A 7685221Ssaidi@eecs.umich.edutemplate <class Impl> 7695221Ssaidi@eecs.umich.eduvoid 7702623SN/AFullO3CPU<Impl>::suspendContext(ThreadID tid) 7712623SN/A{ 7725669Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 7735669Sgblack@eecs.umich.edu assert(!switchedOut()); 7742623SN/A 7752798Sktlim@umich.edu deactivateThread(tid); 7762623SN/A 7772644Sstever@eecs.umich.edu // If this was the last thread then unschedule the tick event. 7785099Ssaidi@eecs.umich.edu if (activeThreads.size() == 0) { 7793222Sktlim@umich.edu unscheduleTickEvent(); 7803222Sktlim@umich.edu lastRunningCycle = curCycle(); 7812839Sktlim@umich.edu _status = Idle; 7825669Sgblack@eecs.umich.edu } 7835669Sgblack@eecs.umich.edu 7845669Sgblack@eecs.umich.edu DPRINTF(Quiesce, "Suspending Context\n"); 7855669Sgblack@eecs.umich.edu 7863658Sktlim@umich.edu BaseCPU::suspendContext(tid); 7872839Sktlim@umich.edu} 7882798Sktlim@umich.edu 7892798Sktlim@umich.edutemplate <class Impl> 7902798Sktlim@umich.eduvoid 7912623SN/AFullO3CPU<Impl>::haltContext(ThreadID tid) 7925726Sgblack@eecs.umich.edu{ 7935726Sgblack@eecs.umich.edu //For now, this is the same as deallocate 7942623SN/A DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 7952623SN/A assert(!switchedOut()); 7963170Sstever@eecs.umich.edu 7973170Sstever@eecs.umich.edu deactivateThread(tid); 7985894Sgblack@eecs.umich.edu removeThread(tid); 7995894Sgblack@eecs.umich.edu 8003170Sstever@eecs.umich.edu updateCycleCounters(BaseCPU::CPU_STATE_SLEEP); 8012644Sstever@eecs.umich.edu} 8025894Sgblack@eecs.umich.edu 8035001Sgblack@eecs.umich.edutemplate <class Impl> 8045001Sgblack@eecs.umich.eduvoid 8055001Sgblack@eecs.umich.eduFullO3CPU<Impl>::insertThread(ThreadID tid) 8063170Sstever@eecs.umich.edu{ 8074998Sgblack@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 8082644Sstever@eecs.umich.edu // Will change now that the PC and thread state is internal to the CPU 8095103Ssaidi@eecs.umich.edu // and not in the ThreadContext. 8105103Ssaidi@eecs.umich.edu ThreadContext *src_tc; 8115103Ssaidi@eecs.umich.edu if (FullSystem) 8125103Ssaidi@eecs.umich.edu src_tc = system->threadContexts[tid]; 8132644Sstever@eecs.umich.edu else 8142644Sstever@eecs.umich.edu src_tc = tcBase(tid); 8155726Sgblack@eecs.umich.edu 8162623SN/A //Bind Int Regs to Rename Map 8172623SN/A 8184998Sgblack@eecs.umich.edu for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs; 8194998Sgblack@eecs.umich.edu reg_id.index()++) { 8204998Sgblack@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getIntReg(); 8214998Sgblack@eecs.umich.edu renameMap[tid].setEntry(reg_id, phys_reg); 8227655Sali.saidi@arm.com scoreboard.setReg(phys_reg); 8235001Sgblack@eecs.umich.edu } 8245001Sgblack@eecs.umich.edu 8255001Sgblack@eecs.umich.edu //Bind Float Regs to Rename Map 8264998Sgblack@eecs.umich.edu for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs; 8272644Sstever@eecs.umich.edu reg_id.index()++) { 8285103Ssaidi@eecs.umich.edu PhysRegIdPtr phys_reg = freeList.getFloatReg(); 8295103Ssaidi@eecs.umich.edu renameMap[tid].setEntry(reg_id, phys_reg); 8305103Ssaidi@eecs.umich.edu scoreboard.setReg(phys_reg); 8315103Ssaidi@eecs.umich.edu } 8322644Sstever@eecs.umich.edu 8335726Sgblack@eecs.umich.edu //Bind condition-code Regs to Rename Map 8345726Sgblack@eecs.umich.edu for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs; 8352623SN/A reg_id.index()++) { 8363658Sktlim@umich.edu PhysRegIdPtr phys_reg = freeList.getCCReg(); 8375669Sgblack@eecs.umich.edu renameMap[tid].setEntry(reg_id, phys_reg); 8385669Sgblack@eecs.umich.edu scoreboard.setReg(phys_reg); 8395669Sgblack@eecs.umich.edu } 8405669Sgblack@eecs.umich.edu 8412623SN/A //Copy Thread Data Into RegFile 8422623SN/A //this->copyFromTC(tid); 8432948Ssaidi@eecs.umich.edu 8442948Ssaidi@eecs.umich.edu //Set PC/NPC/NNPC 8452948Ssaidi@eecs.umich.edu pcState(src_tc->pcState(), tid); 8462948Ssaidi@eecs.umich.edu 8472948Ssaidi@eecs.umich.edu src_tc->setStatus(ThreadContext::Active); 8482623SN/A 8492623SN/A activateContext(tid); 8503349Sbinkertn@umich.edu 8512623SN/A //Reset ROB/IQ/LSQ Entries 8524986Ssaidi@eecs.umich.edu commit.rob->resetEntries(); 8533310Srdreslin@umich.edu iew.resetEntries(); 8544584Ssaidi@eecs.umich.edu} 8552948Ssaidi@eecs.umich.edu 8563495Sktlim@umich.edutemplate <class Impl> 8573310Srdreslin@umich.eduvoid 8583310Srdreslin@umich.eduFullO3CPU<Impl>::removeThread(ThreadID tid) 8593495Sktlim@umich.edu{ 8602948Ssaidi@eecs.umich.edu DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 8613310Srdreslin@umich.edu 8623310Srdreslin@umich.edu // Copy Thread Data From RegFile 8634870Sstever@eecs.umich.edu // If thread is suspended, it might be re-allocated 8644433Ssaidi@eecs.umich.edu // this->copyToTC(tid); 8654433Ssaidi@eecs.umich.edu 8664433Ssaidi@eecs.umich.edu 8674433Ssaidi@eecs.umich.edu // @todo: 2-27-2008: Fix how we free up rename mappings 8684433Ssaidi@eecs.umich.edu // here to alleviate the case for double-freeing registers 8694433Ssaidi@eecs.umich.edu // in SMT workloads. 8703310Srdreslin@umich.edu 8714433Ssaidi@eecs.umich.edu // Unbind Int Regs from Rename Map 8724433Ssaidi@eecs.umich.edu for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs; 8732623SN/A reg_id.index()++) { 8742623SN/A PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); 8752657Ssaidi@eecs.umich.edu scoreboard.unsetReg(phys_reg); 8762623SN/A freeList.addReg(phys_reg); 8772623SN/A } 8782623SN/A 8792623SN/A // Unbind Float Regs from Rename Map 8802623SN/A for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs; 8812623SN/A reg_id.index()++) { 8823349Sbinkertn@umich.edu PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); 8832657Ssaidi@eecs.umich.edu scoreboard.unsetReg(phys_reg); 8842657Ssaidi@eecs.umich.edu freeList.addReg(phys_reg); 8852657Ssaidi@eecs.umich.edu } 8862657Ssaidi@eecs.umich.edu 8872623SN/A // Unbind condition-code Regs from Rename Map 8882623SN/A for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs; 8892623SN/A reg_id.index()++) { 8903349Sbinkertn@umich.edu PhysRegIdPtr phys_reg = renameMap[tid].lookup(reg_id); 8912623SN/A scoreboard.unsetReg(phys_reg); 8922623SN/A freeList.addReg(phys_reg); 8932623SN/A } 8944870Sstever@eecs.umich.edu 8957516Shestness@cs.utexas.edu // Squash Throughout Pipeline 8967516Shestness@cs.utexas.edu DynInstPtr inst = commit.rob->readHeadInst(tid); 8972623SN/A InstSeqNum squash_seq_num = inst->seqNum; 8985099Ssaidi@eecs.umich.edu fetch.squash(0, squash_seq_num, inst, tid); 8993222Sktlim@umich.edu decode.squash(tid); 9003184Srdreslin@umich.edu rename.squash(squash_seq_num, tid); 9015728Sgblack@eecs.umich.edu iew.squash(tid); 9025728Sgblack@eecs.umich.edu iew.ldstQueue.squash(squash_seq_num, tid); 9035728Sgblack@eecs.umich.edu commit.rob->squash(squash_seq_num, tid); 9045728Sgblack@eecs.umich.edu 9055728Sgblack@eecs.umich.edu 9065728Sgblack@eecs.umich.edu assert(iew.instQueue.getCount(tid) == 0); 9075728Sgblack@eecs.umich.edu assert(iew.ldstQueue.getCount(tid) == 0); 9085728Sgblack@eecs.umich.edu 9095728Sgblack@eecs.umich.edu // Reset ROB/IQ/LSQ Entries 9105728Sgblack@eecs.umich.edu 9115728Sgblack@eecs.umich.edu // Commented out for now. This should be possible to do by 9125728Sgblack@eecs.umich.edu // telling all the pipeline stages to drain first, and then 9135728Sgblack@eecs.umich.edu // checking until the drain completes. Once the pipeline is 9145728Sgblack@eecs.umich.edu // drained, call resetEntries(). - 10-09-06 ktlim 9155728Sgblack@eecs.umich.edu/* 9165728Sgblack@eecs.umich.edu if (activeThreads.size() >= 1) { 9175728Sgblack@eecs.umich.edu commit.rob->resetEntries(); 9185728Sgblack@eecs.umich.edu iew.resetEntries(); 9195728Sgblack@eecs.umich.edu } 9205728Sgblack@eecs.umich.edu*/ 9215728Sgblack@eecs.umich.edu} 9225728Sgblack@eecs.umich.edu 9235728Sgblack@eecs.umich.edutemplate <class Impl> 9245728Sgblack@eecs.umich.eduFault 9255728Sgblack@eecs.umich.eduFullO3CPU<Impl>::hwrei(ThreadID tid) 9265728Sgblack@eecs.umich.edu{ 9275728Sgblack@eecs.umich.edu#if THE_ISA == ALPHA_ISA 9282623SN/A // Need to clear the lock flag upon returning from an interrupt. 9292623SN/A this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 9304998Sgblack@eecs.umich.edu 9314998Sgblack@eecs.umich.edu this->thread[tid]->kernelStats->hwrei(); 9324998Sgblack@eecs.umich.edu 9335001Sgblack@eecs.umich.edu // FIXME: XXX check for interrupts? XXX 9345001Sgblack@eecs.umich.edu#endif 9355001Sgblack@eecs.umich.edu return NoFault; 9365001Sgblack@eecs.umich.edu} 9375001Sgblack@eecs.umich.edu 9384998Sgblack@eecs.umich.edutemplate <class Impl> 9395507Sstever@gmail.combool 9405507Sstever@gmail.comFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 9416102Sgblack@eecs.umich.edu{ 9423170Sstever@eecs.umich.edu#if THE_ISA == ALPHA_ISA 9433170Sstever@eecs.umich.edu if (this->thread[tid]->kernelStats) 9443170Sstever@eecs.umich.edu this->thread[tid]->kernelStats->callpal(palFunc, 9452644Sstever@eecs.umich.edu this->threadContexts[tid]); 9462644Sstever@eecs.umich.edu 9472644Sstever@eecs.umich.edu switch (palFunc) { 9483184Srdreslin@umich.edu case PAL::halt: 9493227Sktlim@umich.edu halt(); 9503201Shsul@eecs.umich.edu if (--System::numSystemsRunning == 0) 9513201Shsul@eecs.umich.edu exitSimLoop("all cpus halted"); 9523201Shsul@eecs.umich.edu break; 9533201Shsul@eecs.umich.edu 9543201Shsul@eecs.umich.edu case PAL::bpt: 9553201Shsul@eecs.umich.edu case PAL::bugchk: 9563201Shsul@eecs.umich.edu if (this->system->breakpoint()) 9572644Sstever@eecs.umich.edu return false; 9582623SN/A break; 9592623SN/A } 9602623SN/A#endif 9612798Sktlim@umich.edu return true; 9622839Sktlim@umich.edu} 9632798Sktlim@umich.edu 9642839Sktlim@umich.edutemplate <class Impl> 9652901Ssaidi@eecs.umich.eduFault 9662839Sktlim@umich.eduFullO3CPU<Impl>::getInterrupts() 9672798Sktlim@umich.edu{ 9682623SN/A // Check if there are any outstanding interrupts 9694192Sktlim@umich.edu return this->interrupts[0]->getInterrupt(this->threadContexts[0]); 9704192Sktlim@umich.edu} 9714192Sktlim@umich.edu 9724192Sktlim@umich.edutemplate <class Impl> 9734192Sktlim@umich.eduvoid 9744192Sktlim@umich.eduFullO3CPU<Impl>::processInterrupts(const Fault &interrupt) 9754192Sktlim@umich.edu{ 9764192Sktlim@umich.edu // Check for interrupts here. For now can copy the code that 9775497Ssaidi@eecs.umich.edu // exists within isa_fullsys_traits.hh. Also assume that thread 0 9784192Sktlim@umich.edu // is the one that handles the interrupts. 9794192Sktlim@umich.edu // @todo: Possibly consolidate the interrupt checking code. 9804192Sktlim@umich.edu // @todo: Allow other threads to handle interrupts. 9812623SN/A 9823349Sbinkertn@umich.edu assert(interrupt != NoFault); 9832623SN/A this->interrupts[0]->updateIntrInfo(this->threadContexts[0]); 9844986Ssaidi@eecs.umich.edu 9853310Srdreslin@umich.edu DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 9864584Ssaidi@eecs.umich.edu this->trap(interrupt, 0, nullptr); 9872948Ssaidi@eecs.umich.edu} 9885728Sgblack@eecs.umich.edu 9893310Srdreslin@umich.edutemplate <class Impl> 9905728Sgblack@eecs.umich.eduvoid 9913495Sktlim@umich.eduFullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid, 9925728Sgblack@eecs.umich.edu const StaticInstPtr &inst) 9932948Ssaidi@eecs.umich.edu{ 9943310Srdreslin@umich.edu // Pass the thread's TC into the invoke method. 9953310Srdreslin@umich.edu fault->invoke(this->threadContexts[tid], inst); 9964870Sstever@eecs.umich.edu} 9974433Ssaidi@eecs.umich.edu 9984433Ssaidi@eecs.umich.edutemplate <class Impl> 9994433Ssaidi@eecs.umich.eduvoid 10004433Ssaidi@eecs.umich.eduFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid, Fault *fault) 10014433Ssaidi@eecs.umich.edu{ 10024433Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 10033310Srdreslin@umich.edu 10044433Ssaidi@eecs.umich.edu DPRINTF(Activity,"Activity: syscall() called.\n"); 10054433Ssaidi@eecs.umich.edu 10062948Ssaidi@eecs.umich.edu // Temporarily increase this by one to account for the syscall 10072948Ssaidi@eecs.umich.edu // instruction. 10082948Ssaidi@eecs.umich.edu ++(this->thread[tid]->funcExeInst); 10092948Ssaidi@eecs.umich.edu 10102948Ssaidi@eecs.umich.edu // Execute the actual syscall. 10112630SN/A this->thread[tid]->syscall(callnum, fault); 10122623SN/A 10132623SN/A // Decrease funcExeInst by one as the normal commit will handle 10142657Ssaidi@eecs.umich.edu // incrementing it. 10152623SN/A --(this->thread[tid]->funcExeInst); 10162623SN/A} 10172623SN/A 10182623SN/Atemplate <class Impl> 10192623SN/Avoid 10202623SN/AFullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const 10213349Sbinkertn@umich.edu{ 10225728Sgblack@eecs.umich.edu thread[tid]->serialize(cp); 10235728Sgblack@eecs.umich.edu} 10245728Sgblack@eecs.umich.edu 10255728Sgblack@eecs.umich.edutemplate <class Impl> 10265728Sgblack@eecs.umich.eduvoid 10275728Sgblack@eecs.umich.eduFullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid) 10285728Sgblack@eecs.umich.edu{ 10295728Sgblack@eecs.umich.edu thread[tid]->unserialize(cp); 10305728Sgblack@eecs.umich.edu} 10315728Sgblack@eecs.umich.edu 10325728Sgblack@eecs.umich.edutemplate <class Impl> 10335728Sgblack@eecs.umich.eduDrainState 10345728Sgblack@eecs.umich.eduFullO3CPU<Impl>::drain() 10355728Sgblack@eecs.umich.edu{ 10365728Sgblack@eecs.umich.edu // Deschedule any power gating event (if any) 10375728Sgblack@eecs.umich.edu deschedulePowerGatingEvent(); 10385728Sgblack@eecs.umich.edu 10395728Sgblack@eecs.umich.edu // If the CPU isn't doing anything, then return immediately. 10405728Sgblack@eecs.umich.edu if (switchedOut()) 10415728Sgblack@eecs.umich.edu return DrainState::Drained; 10425728Sgblack@eecs.umich.edu 10435728Sgblack@eecs.umich.edu DPRINTF(Drain, "Draining...\n"); 10445728Sgblack@eecs.umich.edu 10455728Sgblack@eecs.umich.edu // We only need to signal a drain to the commit stage as this 10465728Sgblack@eecs.umich.edu // initiates squashing controls the draining. Once the commit 10475728Sgblack@eecs.umich.edu // stage commits an instruction where it is safe to stop, it'll 10485728Sgblack@eecs.umich.edu // squash the rest of the instructions in the pipeline and force 10495728Sgblack@eecs.umich.edu // the fetch stage to stall. The pipeline will be drained once all 10505728Sgblack@eecs.umich.edu // in-flight instructions have retired. 10515728Sgblack@eecs.umich.edu commit.drain(); 10522657Ssaidi@eecs.umich.edu 10533170Sstever@eecs.umich.edu // Wake the CPU and record activity so everything can drain out if 10542657Ssaidi@eecs.umich.edu // the CPU was not able to immediately drain. 10552657Ssaidi@eecs.umich.edu if (!isDrained()) { 10562623SN/A // If a thread is suspended, wake it up so it can be drained 10572623SN/A for (auto t : threadContexts) { 10585606Snate@binkert.org if (t->status() == ThreadContext::Suspended){ 10595606Snate@binkert.org DPRINTF(Drain, "Currently suspended so activate %i \n", 10605606Snate@binkert.org t->threadId()); 10615103Ssaidi@eecs.umich.edu t->activate(); 10625606Snate@binkert.org // As the thread is now active, change the power state as well 10635103Ssaidi@eecs.umich.edu activateContext(t->threadId()); 10645103Ssaidi@eecs.umich.edu } 10655103Ssaidi@eecs.umich.edu } 10665103Ssaidi@eecs.umich.edu 10675103Ssaidi@eecs.umich.edu wakeCPU(); 10685103Ssaidi@eecs.umich.edu activityRec.activity(); 10695103Ssaidi@eecs.umich.edu 10705103Ssaidi@eecs.umich.edu DPRINTF(Drain, "CPU not drained\n"); 10715103Ssaidi@eecs.umich.edu 10725336Shines@cs.fsu.edu return DrainState::Draining; 10735103Ssaidi@eecs.umich.edu } else { 10745103Ssaidi@eecs.umich.edu DPRINTF(Drain, "CPU is already drained\n"); 10755103Ssaidi@eecs.umich.edu if (tickEvent.scheduled()) 10765103Ssaidi@eecs.umich.edu deschedule(tickEvent); 10772623SN/A 10785315Sstever@gmail.com // Flush out any old data from the time buffers. In 10795315Sstever@gmail.com // particular, there might be some data in flight from the 10805315Sstever@gmail.com // fetch stage that isn't visible in any of the CPU buffers we 10815315Sstever@gmail.com // test in isDrained(). 10825315Sstever@gmail.com for (int i = 0; i < timeBuffer.getSize(); ++i) { 10835315Sstever@gmail.com timeBuffer.advance(); 10845315Sstever@gmail.com fetchQueue.advance(); 10852623SN/A decodeQueue.advance(); 10862623SN/A renameQueue.advance(); 10872623SN/A iewQueue.advance(); 10882623SN/A } 10894762Snate@binkert.org 10904762Snate@binkert.org drainSanityCheck(); 10912623SN/A return DrainState::Drained; 10925529Snate@binkert.org } 10935529Snate@binkert.org} 10944762Snate@binkert.org 10954762Snate@binkert.orgtemplate <class Impl> 10962623SN/Abool 10975529Snate@binkert.orgFullO3CPU<Impl>::tryDrain() 10982623SN/A{ 1099 if (drainState() != DrainState::Draining || !isDrained()) 1100 return false; 1101 1102 if (tickEvent.scheduled()) 1103 deschedule(tickEvent); 1104 1105 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 1106 signalDrainDone(); 1107 1108 return true; 1109} 1110 1111template <class Impl> 1112void 1113FullO3CPU<Impl>::drainSanityCheck() const 1114{ 1115 assert(isDrained()); 1116 fetch.drainSanityCheck(); 1117 decode.drainSanityCheck(); 1118 rename.drainSanityCheck(); 1119 iew.drainSanityCheck(); 1120 commit.drainSanityCheck(); 1121} 1122 1123template <class Impl> 1124bool 1125FullO3CPU<Impl>::isDrained() const 1126{ 1127 bool drained(true); 1128 1129 if (!instList.empty() || !removeList.empty()) { 1130 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1131 drained = false; 1132 } 1133 1134 if (!fetch.isDrained()) { 1135 DPRINTF(Drain, "Fetch not drained.\n"); 1136 drained = false; 1137 } 1138 1139 if (!decode.isDrained()) { 1140 DPRINTF(Drain, "Decode not drained.\n"); 1141 drained = false; 1142 } 1143 1144 if (!rename.isDrained()) { 1145 DPRINTF(Drain, "Rename not drained.\n"); 1146 drained = false; 1147 } 1148 1149 if (!iew.isDrained()) { 1150 DPRINTF(Drain, "IEW not drained.\n"); 1151 drained = false; 1152 } 1153 1154 if (!commit.isDrained()) { 1155 DPRINTF(Drain, "Commit not drained.\n"); 1156 drained = false; 1157 } 1158 1159 return drained; 1160} 1161 1162template <class Impl> 1163void 1164FullO3CPU<Impl>::commitDrained(ThreadID tid) 1165{ 1166 fetch.drainStall(tid); 1167} 1168 1169template <class Impl> 1170void 1171FullO3CPU<Impl>::drainResume() 1172{ 1173 if (switchedOut()) 1174 return; 1175 1176 DPRINTF(Drain, "Resuming...\n"); 1177 verifyMemoryMode(); 1178 1179 fetch.drainResume(); 1180 commit.drainResume(); 1181 1182 _status = Idle; 1183 for (ThreadID i = 0; i < thread.size(); i++) { 1184 if (thread[i]->status() == ThreadContext::Active) { 1185 DPRINTF(Drain, "Activating thread: %i\n", i); 1186 activateThread(i); 1187 _status = Running; 1188 } 1189 } 1190 1191 assert(!tickEvent.scheduled()); 1192 if (_status == Running) 1193 schedule(tickEvent, nextCycle()); 1194 1195 // Reschedule any power gating event (if any) 1196 schedulePowerGatingEvent(); 1197} 1198 1199template <class Impl> 1200void 1201FullO3CPU<Impl>::switchOut() 1202{ 1203 DPRINTF(O3CPU, "Switching out\n"); 1204 BaseCPU::switchOut(); 1205 1206 activityRec.reset(); 1207 1208 _status = SwitchedOut; 1209 1210 if (checker) 1211 checker->switchOut(); 1212} 1213 1214template <class Impl> 1215void 1216FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1217{ 1218 BaseCPU::takeOverFrom(oldCPU); 1219 1220 fetch.takeOverFrom(); 1221 decode.takeOverFrom(); 1222 rename.takeOverFrom(); 1223 iew.takeOverFrom(); 1224 commit.takeOverFrom(); 1225 1226 assert(!tickEvent.scheduled()); 1227 1228 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1229 if (oldO3CPU) 1230 globalSeqNum = oldO3CPU->globalSeqNum; 1231 1232 lastRunningCycle = curCycle(); 1233 _status = Idle; 1234} 1235 1236template <class Impl> 1237void 1238FullO3CPU<Impl>::verifyMemoryMode() const 1239{ 1240 if (!system->isTimingMode()) { 1241 fatal("The O3 CPU requires the memory system to be in " 1242 "'timing' mode.\n"); 1243 } 1244} 1245 1246template <class Impl> 1247TheISA::MiscReg 1248FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const 1249{ 1250 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1251} 1252 1253template <class Impl> 1254TheISA::MiscReg 1255FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 1256{ 1257 miscRegfileReads++; 1258 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 1259} 1260 1261template <class Impl> 1262void 1263FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 1264 const TheISA::MiscReg &val, ThreadID tid) 1265{ 1266 this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 1267} 1268 1269template <class Impl> 1270void 1271FullO3CPU<Impl>::setMiscReg(int misc_reg, 1272 const TheISA::MiscReg &val, ThreadID tid) 1273{ 1274 miscRegfileWrites++; 1275 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 1276} 1277 1278template <class Impl> 1279uint64_t 1280FullO3CPU<Impl>::readIntReg(PhysRegIdPtr phys_reg) 1281{ 1282 intRegfileReads++; 1283 return regFile.readIntReg(phys_reg); 1284} 1285 1286template <class Impl> 1287FloatReg 1288FullO3CPU<Impl>::readFloatReg(PhysRegIdPtr phys_reg) 1289{ 1290 fpRegfileReads++; 1291 return regFile.readFloatReg(phys_reg); 1292} 1293 1294template <class Impl> 1295FloatRegBits 1296FullO3CPU<Impl>::readFloatRegBits(PhysRegIdPtr phys_reg) 1297{ 1298 fpRegfileReads++; 1299 return regFile.readFloatRegBits(phys_reg); 1300} 1301 1302template <class Impl> 1303auto 1304FullO3CPU<Impl>::readVecReg(PhysRegIdPtr phys_reg) const 1305 -> const VecRegContainer& 1306{ 1307 vecRegfileReads++; 1308 return regFile.readVecReg(phys_reg); 1309} 1310 1311template <class Impl> 1312auto 1313FullO3CPU<Impl>::getWritableVecReg(PhysRegIdPtr phys_reg) 1314 -> VecRegContainer& 1315{ 1316 vecRegfileWrites++; 1317 return regFile.getWritableVecReg(phys_reg); 1318} 1319 1320template <class Impl> 1321auto 1322FullO3CPU<Impl>::readVecElem(PhysRegIdPtr phys_reg) const -> const VecElem& 1323{ 1324 vecRegfileReads++; 1325 return regFile.readVecElem(phys_reg); 1326} 1327 1328template <class Impl> 1329CCReg 1330FullO3CPU<Impl>::readCCReg(PhysRegIdPtr phys_reg) 1331{ 1332 ccRegfileReads++; 1333 return regFile.readCCReg(phys_reg); 1334} 1335 1336template <class Impl> 1337void 1338FullO3CPU<Impl>::setIntReg(PhysRegIdPtr phys_reg, uint64_t val) 1339{ 1340 intRegfileWrites++; 1341 regFile.setIntReg(phys_reg, val); 1342} 1343 1344template <class Impl> 1345void 1346FullO3CPU<Impl>::setFloatReg(PhysRegIdPtr phys_reg, FloatReg val) 1347{ 1348 fpRegfileWrites++; 1349 regFile.setFloatReg(phys_reg, val); 1350} 1351 1352template <class Impl> 1353void 1354FullO3CPU<Impl>::setFloatRegBits(PhysRegIdPtr phys_reg, FloatRegBits val) 1355{ 1356 fpRegfileWrites++; 1357 regFile.setFloatRegBits(phys_reg, val); 1358} 1359 1360template <class Impl> 1361void 1362FullO3CPU<Impl>::setVecReg(PhysRegIdPtr phys_reg, const VecRegContainer& val) 1363{ 1364 vecRegfileWrites++; 1365 regFile.setVecReg(phys_reg, val); 1366} 1367 1368template <class Impl> 1369void 1370FullO3CPU<Impl>::setVecElem(PhysRegIdPtr phys_reg, const VecElem& val) 1371{ 1372 vecRegfileWrites++; 1373 regFile.setVecElem(phys_reg, val); 1374} 1375 1376template <class Impl> 1377void 1378FullO3CPU<Impl>::setCCReg(PhysRegIdPtr phys_reg, CCReg val) 1379{ 1380 ccRegfileWrites++; 1381 regFile.setCCReg(phys_reg, val); 1382} 1383 1384template <class Impl> 1385uint64_t 1386FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 1387{ 1388 intRegfileReads++; 1389 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1390 RegId(IntRegClass, reg_idx)); 1391 1392 return regFile.readIntReg(phys_reg); 1393} 1394 1395template <class Impl> 1396float 1397FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 1398{ 1399 fpRegfileReads++; 1400 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1401 RegId(FloatRegClass, reg_idx)); 1402 1403 return regFile.readFloatReg(phys_reg); 1404} 1405 1406template <class Impl> 1407uint64_t 1408FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 1409{ 1410 fpRegfileReads++; 1411 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1412 RegId(FloatRegClass, reg_idx)); 1413 1414 return regFile.readFloatRegBits(phys_reg); 1415} 1416 1417template <class Impl> 1418auto 1419FullO3CPU<Impl>::readArchVecReg(int reg_idx, ThreadID tid) const 1420 -> const VecRegContainer& 1421{ 1422 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1423 RegId(VecRegClass, reg_idx)); 1424 return readVecReg(phys_reg); 1425} 1426 1427template <class Impl> 1428auto 1429FullO3CPU<Impl>::getWritableArchVecReg(int reg_idx, ThreadID tid) 1430 -> VecRegContainer& 1431{ 1432 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1433 RegId(VecRegClass, reg_idx)); 1434 return getWritableVecReg(phys_reg); 1435} 1436 1437template <class Impl> 1438auto 1439FullO3CPU<Impl>::readArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, 1440 ThreadID tid) const -> const VecElem& 1441{ 1442 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1443 RegId(VecRegClass, reg_idx, ldx)); 1444 return readVecElem(phys_reg); 1445} 1446 1447template <class Impl> 1448CCReg 1449FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 1450{ 1451 ccRegfileReads++; 1452 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1453 RegId(CCRegClass, reg_idx)); 1454 1455 return regFile.readCCReg(phys_reg); 1456} 1457 1458template <class Impl> 1459void 1460FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 1461{ 1462 intRegfileWrites++; 1463 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1464 RegId(IntRegClass, reg_idx)); 1465 1466 regFile.setIntReg(phys_reg, val); 1467} 1468 1469template <class Impl> 1470void 1471FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 1472{ 1473 fpRegfileWrites++; 1474 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1475 RegId(FloatRegClass, reg_idx)); 1476 1477 regFile.setFloatReg(phys_reg, val); 1478} 1479 1480template <class Impl> 1481void 1482FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 1483{ 1484 fpRegfileWrites++; 1485 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1486 RegId(FloatRegClass, reg_idx)); 1487 1488 regFile.setFloatRegBits(phys_reg, val); 1489} 1490 1491template <class Impl> 1492void 1493FullO3CPU<Impl>::setArchVecReg(int reg_idx, const VecRegContainer& val, 1494 ThreadID tid) 1495{ 1496 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1497 RegId(VecRegClass, reg_idx)); 1498 setVecReg(phys_reg, val); 1499} 1500 1501template <class Impl> 1502void 1503FullO3CPU<Impl>::setArchVecElem(const RegIndex& reg_idx, const ElemIndex& ldx, 1504 const VecElem& val, ThreadID tid) 1505{ 1506 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1507 RegId(VecRegClass, reg_idx, ldx)); 1508 setVecElem(phys_reg, val); 1509} 1510 1511template <class Impl> 1512void 1513FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) 1514{ 1515 ccRegfileWrites++; 1516 PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup( 1517 RegId(CCRegClass, reg_idx)); 1518 1519 regFile.setCCReg(phys_reg, val); 1520} 1521 1522template <class Impl> 1523TheISA::PCState 1524FullO3CPU<Impl>::pcState(ThreadID tid) 1525{ 1526 return commit.pcState(tid); 1527} 1528 1529template <class Impl> 1530void 1531FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 1532{ 1533 commit.pcState(val, tid); 1534} 1535 1536template <class Impl> 1537Addr 1538FullO3CPU<Impl>::instAddr(ThreadID tid) 1539{ 1540 return commit.instAddr(tid); 1541} 1542 1543template <class Impl> 1544Addr 1545FullO3CPU<Impl>::nextInstAddr(ThreadID tid) 1546{ 1547 return commit.nextInstAddr(tid); 1548} 1549 1550template <class Impl> 1551MicroPC 1552FullO3CPU<Impl>::microPC(ThreadID tid) 1553{ 1554 return commit.microPC(tid); 1555} 1556 1557template <class Impl> 1558void 1559FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1560{ 1561 this->thread[tid]->noSquashFromTC = true; 1562 this->commit.generateTCEvent(tid); 1563} 1564 1565template <class Impl> 1566typename FullO3CPU<Impl>::ListIt 1567FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1568{ 1569 instList.push_back(inst); 1570 1571 return --(instList.end()); 1572} 1573 1574template <class Impl> 1575void 1576FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst) 1577{ 1578 // Keep an instruction count. 1579 if (!inst->isMicroop() || inst->isLastMicroop()) { 1580 thread[tid]->numInst++; 1581 thread[tid]->numInsts++; 1582 committedInsts[tid]++; 1583 system->totalNumInsts++; 1584 1585 // Check for instruction-count-based events. 1586 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1587 system->instEventQueue.serviceEvents(system->totalNumInsts); 1588 } 1589 thread[tid]->numOp++; 1590 thread[tid]->numOps++; 1591 committedOps[tid]++; 1592 1593 probeInstCommit(inst->staticInst); 1594} 1595 1596template <class Impl> 1597void 1598FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1599{ 1600 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1601 "[sn:%lli]\n", 1602 inst->threadNumber, inst->pcState(), inst->seqNum); 1603 1604 removeInstsThisCycle = true; 1605 1606 // Remove the front instruction. 1607 removeList.push(inst->getInstListIt()); 1608} 1609 1610template <class Impl> 1611void 1612FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1613{ 1614 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1615 " list.\n", tid); 1616 1617 ListIt end_it; 1618 1619 bool rob_empty = false; 1620 1621 if (instList.empty()) { 1622 return; 1623 } else if (rob.isEmpty(tid)) { 1624 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1625 end_it = instList.begin(); 1626 rob_empty = true; 1627 } else { 1628 end_it = (rob.readTailInst(tid))->getInstListIt(); 1629 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1630 } 1631 1632 removeInstsThisCycle = true; 1633 1634 ListIt inst_it = instList.end(); 1635 1636 inst_it--; 1637 1638 // Walk through the instruction list, removing any instructions 1639 // that were inserted after the given instruction iterator, end_it. 1640 while (inst_it != end_it) { 1641 assert(!instList.empty()); 1642 1643 squashInstIt(inst_it, tid); 1644 1645 inst_it--; 1646 } 1647 1648 // If the ROB was empty, then we actually need to remove the first 1649 // instruction as well. 1650 if (rob_empty) { 1651 squashInstIt(inst_it, tid); 1652 } 1653} 1654 1655template <class Impl> 1656void 1657FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1658{ 1659 assert(!instList.empty()); 1660 1661 removeInstsThisCycle = true; 1662 1663 ListIt inst_iter = instList.end(); 1664 1665 inst_iter--; 1666 1667 DPRINTF(O3CPU, "Deleting instructions from instruction " 1668 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1669 tid, seq_num, (*inst_iter)->seqNum); 1670 1671 while ((*inst_iter)->seqNum > seq_num) { 1672 1673 bool break_loop = (inst_iter == instList.begin()); 1674 1675 squashInstIt(inst_iter, tid); 1676 1677 inst_iter--; 1678 1679 if (break_loop) 1680 break; 1681 } 1682} 1683 1684template <class Impl> 1685inline void 1686FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1687{ 1688 if ((*instIt)->threadNumber == tid) { 1689 DPRINTF(O3CPU, "Squashing instruction, " 1690 "[tid:%i] [sn:%lli] PC %s\n", 1691 (*instIt)->threadNumber, 1692 (*instIt)->seqNum, 1693 (*instIt)->pcState()); 1694 1695 // Mark it as squashed. 1696 (*instIt)->setSquashed(); 1697 1698 // @todo: Formulate a consistent method for deleting 1699 // instructions from the instruction list 1700 // Remove the instruction from the list. 1701 removeList.push(instIt); 1702 } 1703} 1704 1705template <class Impl> 1706void 1707FullO3CPU<Impl>::cleanUpRemovedInsts() 1708{ 1709 while (!removeList.empty()) { 1710 DPRINTF(O3CPU, "Removing instruction, " 1711 "[tid:%i] [sn:%lli] PC %s\n", 1712 (*removeList.front())->threadNumber, 1713 (*removeList.front())->seqNum, 1714 (*removeList.front())->pcState()); 1715 1716 instList.erase(removeList.front()); 1717 1718 removeList.pop(); 1719 } 1720 1721 removeInstsThisCycle = false; 1722} 1723/* 1724template <class Impl> 1725void 1726FullO3CPU<Impl>::removeAllInsts() 1727{ 1728 instList.clear(); 1729} 1730*/ 1731template <class Impl> 1732void 1733FullO3CPU<Impl>::dumpInsts() 1734{ 1735 int num = 0; 1736 1737 ListIt inst_list_it = instList.begin(); 1738 1739 cprintf("Dumping Instruction List\n"); 1740 1741 while (inst_list_it != instList.end()) { 1742 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1743 "Squashed:%i\n\n", 1744 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1745 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1746 (*inst_list_it)->isSquashed()); 1747 inst_list_it++; 1748 ++num; 1749 } 1750} 1751/* 1752template <class Impl> 1753void 1754FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1755{ 1756 iew.wakeDependents(inst); 1757} 1758*/ 1759template <class Impl> 1760void 1761FullO3CPU<Impl>::wakeCPU() 1762{ 1763 if (activityRec.active() || tickEvent.scheduled()) { 1764 DPRINTF(Activity, "CPU already running.\n"); 1765 return; 1766 } 1767 1768 DPRINTF(Activity, "Waking up CPU\n"); 1769 1770 Cycles cycles(curCycle() - lastRunningCycle); 1771 // @todo: This is an oddity that is only here to match the stats 1772 if (cycles > 1) { 1773 --cycles; 1774 idleCycles += cycles; 1775 numCycles += cycles; 1776 } 1777 1778 schedule(tickEvent, clockEdge()); 1779} 1780 1781template <class Impl> 1782void 1783FullO3CPU<Impl>::wakeup(ThreadID tid) 1784{ 1785 if (this->thread[tid]->status() != ThreadContext::Suspended) 1786 return; 1787 1788 this->wakeCPU(); 1789 1790 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1791 this->threadContexts[tid]->activate(); 1792} 1793 1794template <class Impl> 1795ThreadID 1796FullO3CPU<Impl>::getFreeTid() 1797{ 1798 for (ThreadID tid = 0; tid < numThreads; tid++) { 1799 if (!tids[tid]) { 1800 tids[tid] = true; 1801 return tid; 1802 } 1803 } 1804 1805 return InvalidThreadID; 1806} 1807 1808template <class Impl> 1809void 1810FullO3CPU<Impl>::updateThreadPriority() 1811{ 1812 if (activeThreads.size() > 1) { 1813 //DEFAULT TO ROUND ROBIN SCHEME 1814 //e.g. Move highest priority to end of thread list 1815 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1816 1817 unsigned high_thread = *list_begin; 1818 1819 activeThreads.erase(list_begin); 1820 1821 activeThreads.push_back(high_thread); 1822 } 1823} 1824 1825// Forward declaration of FullO3CPU. 1826template class FullO3CPU<O3CPUImpl>; 1827