cpu.cc revision 11793
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright (c) 2011-2012, 2014 ARM Limited 312854Sgabeblack@google.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 412854Sgabeblack@google.com * All rights reserved 512854Sgabeblack@google.com * 612854Sgabeblack@google.com * The license below extends only to copyright in the software and shall 712854Sgabeblack@google.com * not be construed as granting a license to any other intellectual 812854Sgabeblack@google.com * property including but not limited to intellectual property relating 912854Sgabeblack@google.com * to a hardware implementation of the functionality of the software 1012854Sgabeblack@google.com * licensed hereunder. You may use the software subject to the license 1112854Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated 1212854Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software, 1312854Sgabeblack@google.com * modified or unmodified, in source code or in binary form. 1412854Sgabeblack@google.com * 1512854Sgabeblack@google.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 1612854Sgabeblack@google.com * Copyright (c) 2011 Regents of the University of California 1712854Sgabeblack@google.com * All rights reserved. 1812854Sgabeblack@google.com * 1912854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 2012854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 2112854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 2212854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 2312854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 2412854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 2512854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 2612854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 2712854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 2812854Sgabeblack@google.com * this software without specific prior written permission. 2912854Sgabeblack@google.com * 3012854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3112854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3212854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3312854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3412854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3512854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3612854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3712854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3812854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3912854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 4012854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4112854Sgabeblack@google.com * 4212854Sgabeblack@google.com * Authors: Kevin Lim 4312854Sgabeblack@google.com * Korey Sewell 4412854Sgabeblack@google.com * Rick Strong 4512854Sgabeblack@google.com */ 4612854Sgabeblack@google.com 4712854Sgabeblack@google.com#include "cpu/o3/cpu.hh" 4812854Sgabeblack@google.com 4912854Sgabeblack@google.com#include "arch/kernel_stats.hh" 5012854Sgabeblack@google.com#include "config/the_isa.hh" 5112854Sgabeblack@google.com#include "cpu/activity.hh" 5212854Sgabeblack@google.com#include "cpu/checker/cpu.hh" 5312854Sgabeblack@google.com#include "cpu/checker/thread_context.hh" 5412854Sgabeblack@google.com#include "cpu/o3/isa_specific.hh" 5512854Sgabeblack@google.com#include "cpu/o3/thread_context.hh" 5612854Sgabeblack@google.com#include "cpu/quiesce_event.hh" 5712854Sgabeblack@google.com#include "cpu/simple_thread.hh" 5812854Sgabeblack@google.com#include "cpu/thread_context.hh" 5912854Sgabeblack@google.com#include "debug/Activity.hh" 6012854Sgabeblack@google.com#include "debug/Drain.hh" 6112854Sgabeblack@google.com#include "debug/O3CPU.hh" 6212854Sgabeblack@google.com#include "debug/Quiesce.hh" 6312854Sgabeblack@google.com#include "enums/MemoryMode.hh" 6412854Sgabeblack@google.com#include "sim/core.hh" 6512854Sgabeblack@google.com#include "sim/full_system.hh" 6612854Sgabeblack@google.com#include "sim/process.hh" 6712854Sgabeblack@google.com#include "sim/stat_control.hh" 6812854Sgabeblack@google.com#include "sim/system.hh" 6912854Sgabeblack@google.com 7012854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA 7112854Sgabeblack@google.com#include "arch/alpha/osfpal.hh" 7212854Sgabeblack@google.com#include "debug/Activity.hh" 7312854Sgabeblack@google.com 7412854Sgabeblack@google.com#endif 7512854Sgabeblack@google.com 7612854Sgabeblack@google.comstruct BaseCPUParams; 7712854Sgabeblack@google.com 7812854Sgabeblack@google.comusing namespace TheISA; 7912854Sgabeblack@google.comusing namespace std; 8012854Sgabeblack@google.com 8112854Sgabeblack@google.comBaseO3CPU::BaseO3CPU(BaseCPUParams *params) 8212854Sgabeblack@google.com : BaseCPU(params) 8312854Sgabeblack@google.com{ 8412854Sgabeblack@google.com} 8512854Sgabeblack@google.com 8612854Sgabeblack@google.comvoid 8712854Sgabeblack@google.comBaseO3CPU::regStats() 8812854Sgabeblack@google.com{ 8912854Sgabeblack@google.com BaseCPU::regStats(); 9012854Sgabeblack@google.com} 9112854Sgabeblack@google.com 9212854Sgabeblack@google.comtemplate<class Impl> 9312854Sgabeblack@google.combool 9412854Sgabeblack@google.comFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 9512854Sgabeblack@google.com{ 9612854Sgabeblack@google.com DPRINTF(O3CPU, "Fetch unit received timing\n"); 9712854Sgabeblack@google.com // We shouldn't ever get a cacheable block in Modified state 9812854Sgabeblack@google.com assert(pkt->req->isUncacheable() || 9912854Sgabeblack@google.com !(pkt->cacheResponding() && !pkt->hasSharers())); 10012854Sgabeblack@google.com fetch->processCacheCompletion(pkt); 10112854Sgabeblack@google.com 10212854Sgabeblack@google.com return true; 10312854Sgabeblack@google.com} 10412854Sgabeblack@google.com 10512854Sgabeblack@google.comtemplate<class Impl> 10612854Sgabeblack@google.comvoid 10712854Sgabeblack@google.comFullO3CPU<Impl>::IcachePort::recvReqRetry() 10812854Sgabeblack@google.com{ 10912854Sgabeblack@google.com fetch->recvReqRetry(); 11012854Sgabeblack@google.com} 11112854Sgabeblack@google.com 11212854Sgabeblack@google.comtemplate <class Impl> 11312854Sgabeblack@google.combool 11412854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 11512854Sgabeblack@google.com{ 11612854Sgabeblack@google.com return lsq->recvTimingResp(pkt); 11712854Sgabeblack@google.com} 11812854Sgabeblack@google.com 11912854Sgabeblack@google.comtemplate <class Impl> 12012854Sgabeblack@google.comvoid 12112854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 12212854Sgabeblack@google.com{ 12312854Sgabeblack@google.com for (ThreadID tid = 0; tid < cpu->numThreads; tid++) { 12412854Sgabeblack@google.com if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) { 12512854Sgabeblack@google.com cpu->wakeup(tid); 12612854Sgabeblack@google.com } 12712854Sgabeblack@google.com } 12812854Sgabeblack@google.com lsq->recvTimingSnoopReq(pkt); 12912854Sgabeblack@google.com} 13012854Sgabeblack@google.com 13112854Sgabeblack@google.comtemplate <class Impl> 13212854Sgabeblack@google.comvoid 13312854Sgabeblack@google.comFullO3CPU<Impl>::DcachePort::recvReqRetry() 13412854Sgabeblack@google.com{ 13512854Sgabeblack@google.com lsq->recvReqRetry(); 13612854Sgabeblack@google.com} 13712854Sgabeblack@google.com 13812854Sgabeblack@google.comtemplate <class Impl> 13912854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 14012854Sgabeblack@google.com : Event(CPU_Tick_Pri), cpu(c) 14112854Sgabeblack@google.com{ 14212854Sgabeblack@google.com} 14312854Sgabeblack@google.com 14412854Sgabeblack@google.comtemplate <class Impl> 14512854Sgabeblack@google.comvoid 14612854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::process() 14712854Sgabeblack@google.com{ 14812854Sgabeblack@google.com cpu->tick(); 14912854Sgabeblack@google.com} 15012854Sgabeblack@google.com 15112854Sgabeblack@google.comtemplate <class Impl> 15212854Sgabeblack@google.comconst char * 15312854Sgabeblack@google.comFullO3CPU<Impl>::TickEvent::description() const 15412854Sgabeblack@google.com{ 15512854Sgabeblack@google.com return "FullO3CPU tick"; 15612854Sgabeblack@google.com} 15712854Sgabeblack@google.com 15812854Sgabeblack@google.comtemplate <class Impl> 15912854Sgabeblack@google.comFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 16012854Sgabeblack@google.com : BaseO3CPU(params), 16112854Sgabeblack@google.com itb(params->itb), 16212854Sgabeblack@google.com dtb(params->dtb), 16312854Sgabeblack@google.com tickEvent(this), 16412854Sgabeblack@google.com#ifndef NDEBUG 16512854Sgabeblack@google.com instcount(0), 16612854Sgabeblack@google.com#endif 16712854Sgabeblack@google.com removeInstsThisCycle(false), 16812854Sgabeblack@google.com fetch(this, params), 16912854Sgabeblack@google.com decode(this, params), 17012854Sgabeblack@google.com rename(this, params), 17112854Sgabeblack@google.com iew(this, params), 17212854Sgabeblack@google.com commit(this, params), 17312854Sgabeblack@google.com 17412854Sgabeblack@google.com regFile(params->numPhysIntRegs, 17512854Sgabeblack@google.com params->numPhysFloatRegs, 17612854Sgabeblack@google.com params->numPhysCCRegs), 17712854Sgabeblack@google.com 17812854Sgabeblack@google.com freeList(name() + ".freelist", ®File), 17912854Sgabeblack@google.com 18012854Sgabeblack@google.com rob(this, params), 18112854Sgabeblack@google.com 18212854Sgabeblack@google.com scoreboard(name() + ".scoreboard", 18312854Sgabeblack@google.com regFile.totalNumPhysRegs(), TheISA::NumMiscRegs, 18412854Sgabeblack@google.com TheISA::ZeroReg, TheISA::ZeroReg), 18512854Sgabeblack@google.com 18612854Sgabeblack@google.com isa(numThreads, NULL), 18712854Sgabeblack@google.com 18812854Sgabeblack@google.com icachePort(&fetch, this), 18912854Sgabeblack@google.com dcachePort(&iew.ldstQueue, this), 19012854Sgabeblack@google.com 19112854Sgabeblack@google.com timeBuffer(params->backComSize, params->forwardComSize), 19212854Sgabeblack@google.com fetchQueue(params->backComSize, params->forwardComSize), 19312854Sgabeblack@google.com decodeQueue(params->backComSize, params->forwardComSize), 19412854Sgabeblack@google.com renameQueue(params->backComSize, params->forwardComSize), 19512854Sgabeblack@google.com iewQueue(params->backComSize, params->forwardComSize), 19612854Sgabeblack@google.com activityRec(name(), NumStages, 19712854Sgabeblack@google.com params->backComSize + params->forwardComSize, 19812854Sgabeblack@google.com params->activity), 19912854Sgabeblack@google.com 20012854Sgabeblack@google.com globalSeqNum(1), 20112854Sgabeblack@google.com system(params->system), 20212854Sgabeblack@google.com lastRunningCycle(curCycle()) 20312854Sgabeblack@google.com{ 20412854Sgabeblack@google.com if (!params->switched_out) { 20512854Sgabeblack@google.com _status = Running; 20612854Sgabeblack@google.com } else { 20712854Sgabeblack@google.com _status = SwitchedOut; 20812854Sgabeblack@google.com } 20912854Sgabeblack@google.com 21012854Sgabeblack@google.com if (params->checker) { 21112854Sgabeblack@google.com BaseCPU *temp_checker = params->checker; 21212854Sgabeblack@google.com checker = dynamic_cast<Checker<Impl> *>(temp_checker); 21312854Sgabeblack@google.com checker->setIcachePort(&icachePort); 21412854Sgabeblack@google.com checker->setSystem(params->system); 21512854Sgabeblack@google.com } else { 21612854Sgabeblack@google.com checker = NULL; 21712854Sgabeblack@google.com } 21812854Sgabeblack@google.com 21912854Sgabeblack@google.com if (!FullSystem) { 22012854Sgabeblack@google.com thread.resize(numThreads); 22112854Sgabeblack@google.com tids.resize(numThreads); 22212854Sgabeblack@google.com } 22312854Sgabeblack@google.com 22412854Sgabeblack@google.com // The stages also need their CPU pointer setup. However this 22512854Sgabeblack@google.com // must be done at the upper level CPU because they have pointers 22612854Sgabeblack@google.com // to the upper level CPU, and not this FullO3CPU. 22712854Sgabeblack@google.com 22812854Sgabeblack@google.com // Set up Pointers to the activeThreads list for each stage 22912854Sgabeblack@google.com fetch.setActiveThreads(&activeThreads); 23012854Sgabeblack@google.com decode.setActiveThreads(&activeThreads); 23112854Sgabeblack@google.com rename.setActiveThreads(&activeThreads); 23212854Sgabeblack@google.com iew.setActiveThreads(&activeThreads); 23312854Sgabeblack@google.com commit.setActiveThreads(&activeThreads); 23412854Sgabeblack@google.com 23512854Sgabeblack@google.com // Give each of the stages the time buffer they will use. 23612854Sgabeblack@google.com fetch.setTimeBuffer(&timeBuffer); 23712854Sgabeblack@google.com decode.setTimeBuffer(&timeBuffer); 23812854Sgabeblack@google.com rename.setTimeBuffer(&timeBuffer); 23912854Sgabeblack@google.com iew.setTimeBuffer(&timeBuffer); 24012854Sgabeblack@google.com commit.setTimeBuffer(&timeBuffer); 24112854Sgabeblack@google.com 24212854Sgabeblack@google.com // Also setup each of the stages' queues. 24312854Sgabeblack@google.com fetch.setFetchQueue(&fetchQueue); 24412854Sgabeblack@google.com decode.setFetchQueue(&fetchQueue); 24512854Sgabeblack@google.com commit.setFetchQueue(&fetchQueue); 24612854Sgabeblack@google.com decode.setDecodeQueue(&decodeQueue); 24712854Sgabeblack@google.com rename.setDecodeQueue(&decodeQueue); 24812854Sgabeblack@google.com rename.setRenameQueue(&renameQueue); 24912854Sgabeblack@google.com iew.setRenameQueue(&renameQueue); 25012854Sgabeblack@google.com iew.setIEWQueue(&iewQueue); 25112854Sgabeblack@google.com commit.setIEWQueue(&iewQueue); 25212854Sgabeblack@google.com commit.setRenameQueue(&renameQueue); 25312854Sgabeblack@google.com 25412854Sgabeblack@google.com commit.setIEWStage(&iew); 25512854Sgabeblack@google.com rename.setIEWStage(&iew); 25612854Sgabeblack@google.com rename.setCommitStage(&commit); 25712854Sgabeblack@google.com 25812854Sgabeblack@google.com ThreadID active_threads; 25912854Sgabeblack@google.com if (FullSystem) { 26012854Sgabeblack@google.com active_threads = 1; 26112854Sgabeblack@google.com } else { 26212854Sgabeblack@google.com active_threads = params->workload.size(); 26312854Sgabeblack@google.com 26412854Sgabeblack@google.com if (active_threads > Impl::MaxThreads) { 26512854Sgabeblack@google.com panic("Workload Size too large. Increase the 'MaxThreads' " 26612854Sgabeblack@google.com "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 26712854Sgabeblack@google.com "or edit your workload size."); 26812854Sgabeblack@google.com } 26912854Sgabeblack@google.com } 27012854Sgabeblack@google.com 27112854Sgabeblack@google.com //Make Sure That this a Valid Architeture 27212854Sgabeblack@google.com assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 27312854Sgabeblack@google.com assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 27412854Sgabeblack@google.com assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 27512854Sgabeblack@google.com 27612854Sgabeblack@google.com rename.setScoreboard(&scoreboard); 27712854Sgabeblack@google.com iew.setScoreboard(&scoreboard); 27812854Sgabeblack@google.com 27912854Sgabeblack@google.com // Setup the rename map for whichever stages need it. 28012854Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; tid++) { 28112854Sgabeblack@google.com isa[tid] = params->isa[tid]; 28212854Sgabeblack@google.com 28312854Sgabeblack@google.com // Only Alpha has an FP zero register, so for other ISAs we 28412854Sgabeblack@google.com // use an invalid FP register index to avoid special treatment 28512854Sgabeblack@google.com // of any valid FP reg. 28612854Sgabeblack@google.com RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 28712854Sgabeblack@google.com RegIndex fpZeroReg = 28812854Sgabeblack@google.com (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 28912854Sgabeblack@google.com 29012854Sgabeblack@google.com commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 29112854Sgabeblack@google.com &freeList); 29212854Sgabeblack@google.com 29312854Sgabeblack@google.com renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 29412854Sgabeblack@google.com &freeList); 29512854Sgabeblack@google.com } 29612854Sgabeblack@google.com 29712854Sgabeblack@google.com // Initialize rename map to assign physical registers to the 29812854Sgabeblack@google.com // architectural registers for active threads only. 29912854Sgabeblack@google.com for (ThreadID tid = 0; tid < active_threads; tid++) { 30012854Sgabeblack@google.com for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 30112854Sgabeblack@google.com // Note that we can't use the rename() method because we don't 30212854Sgabeblack@google.com // want special treatment for the zero register at this point 30312854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getIntReg(); 30412854Sgabeblack@google.com renameMap[tid].setIntEntry(ridx, phys_reg); 30512854Sgabeblack@google.com commitRenameMap[tid].setIntEntry(ridx, phys_reg); 30612854Sgabeblack@google.com } 30712854Sgabeblack@google.com 30812854Sgabeblack@google.com for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 30912854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getFloatReg(); 31012854Sgabeblack@google.com renameMap[tid].setFloatEntry(ridx, phys_reg); 31112854Sgabeblack@google.com commitRenameMap[tid].setFloatEntry(ridx, phys_reg); 31212854Sgabeblack@google.com } 31312854Sgabeblack@google.com 31412854Sgabeblack@google.com for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 31512854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getCCReg(); 31612854Sgabeblack@google.com renameMap[tid].setCCEntry(ridx, phys_reg); 31712854Sgabeblack@google.com commitRenameMap[tid].setCCEntry(ridx, phys_reg); 31812854Sgabeblack@google.com } 31912854Sgabeblack@google.com } 32012854Sgabeblack@google.com 32112854Sgabeblack@google.com rename.setRenameMap(renameMap); 32212854Sgabeblack@google.com commit.setRenameMap(commitRenameMap); 32312854Sgabeblack@google.com rename.setFreeList(&freeList); 32412854Sgabeblack@google.com 32512854Sgabeblack@google.com // Setup the ROB for whichever stages need it. 32612854Sgabeblack@google.com commit.setROB(&rob); 32712854Sgabeblack@google.com 32812854Sgabeblack@google.com lastActivatedCycle = 0; 32912854Sgabeblack@google.com#if 0 33012854Sgabeblack@google.com // Give renameMap & rename stage access to the freeList; 33112854Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; tid++) 33212854Sgabeblack@google.com globalSeqNum[tid] = 1; 33312854Sgabeblack@google.com#endif 33412854Sgabeblack@google.com 33512854Sgabeblack@google.com DPRINTF(O3CPU, "Creating O3CPU object.\n"); 33612854Sgabeblack@google.com 33712854Sgabeblack@google.com // Setup any thread state. 33812854Sgabeblack@google.com this->thread.resize(this->numThreads); 33912854Sgabeblack@google.com 34012854Sgabeblack@google.com for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 34112854Sgabeblack@google.com if (FullSystem) { 34212854Sgabeblack@google.com // SMT is not supported in FS mode yet. 34312854Sgabeblack@google.com assert(this->numThreads == 1); 34412854Sgabeblack@google.com this->thread[tid] = new Thread(this, 0, NULL); 34512854Sgabeblack@google.com } else { 34612854Sgabeblack@google.com if (tid < params->workload.size()) { 34712854Sgabeblack@google.com DPRINTF(O3CPU, "Workload[%i] process is %#x", 34812854Sgabeblack@google.com tid, this->thread[tid]); 34912854Sgabeblack@google.com this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 35012854Sgabeblack@google.com (typename Impl::O3CPU *)(this), 35112854Sgabeblack@google.com tid, params->workload[tid]); 35212854Sgabeblack@google.com 35312854Sgabeblack@google.com //usedTids[tid] = true; 35412854Sgabeblack@google.com //threadMap[tid] = tid; 35512854Sgabeblack@google.com } else { 35612854Sgabeblack@google.com //Allocate Empty thread so M5 can use later 35712854Sgabeblack@google.com //when scheduling threads to CPU 35812854Sgabeblack@google.com Process* dummy_proc = NULL; 35912854Sgabeblack@google.com 36012854Sgabeblack@google.com this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 36112854Sgabeblack@google.com (typename Impl::O3CPU *)(this), 36212854Sgabeblack@google.com tid, dummy_proc); 36312854Sgabeblack@google.com //usedTids[tid] = false; 36412854Sgabeblack@google.com } 36512854Sgabeblack@google.com } 36612854Sgabeblack@google.com 36712854Sgabeblack@google.com ThreadContext *tc; 36812854Sgabeblack@google.com 36912854Sgabeblack@google.com // Setup the TC that will serve as the interface to the threads/CPU. 37012854Sgabeblack@google.com O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 37112854Sgabeblack@google.com 37212854Sgabeblack@google.com tc = o3_tc; 37312854Sgabeblack@google.com 37412854Sgabeblack@google.com // If we're using a checker, then the TC should be the 37512854Sgabeblack@google.com // CheckerThreadContext. 37612854Sgabeblack@google.com if (params->checker) { 37712854Sgabeblack@google.com tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 37812854Sgabeblack@google.com o3_tc, this->checker); 37912854Sgabeblack@google.com } 38012854Sgabeblack@google.com 38112854Sgabeblack@google.com o3_tc->cpu = (typename Impl::O3CPU *)(this); 38212854Sgabeblack@google.com assert(o3_tc->cpu); 38312854Sgabeblack@google.com o3_tc->thread = this->thread[tid]; 38412854Sgabeblack@google.com 38512854Sgabeblack@google.com // Setup quiesce event. 38612854Sgabeblack@google.com this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 38712854Sgabeblack@google.com 38812854Sgabeblack@google.com // Give the thread the TC. 38912854Sgabeblack@google.com this->thread[tid]->tc = tc; 39012854Sgabeblack@google.com 39112854Sgabeblack@google.com // Add the TC to the CPU's list of TC's. 39212854Sgabeblack@google.com this->threadContexts.push_back(tc); 39312854Sgabeblack@google.com } 39412854Sgabeblack@google.com 39512854Sgabeblack@google.com // FullO3CPU always requires an interrupt controller. 39612854Sgabeblack@google.com if (!params->switched_out && interrupts.empty()) { 39712854Sgabeblack@google.com fatal("FullO3CPU %s has no interrupt controller.\n" 39812854Sgabeblack@google.com "Ensure createInterruptController() is called.\n", name()); 39912854Sgabeblack@google.com } 40012854Sgabeblack@google.com 40112854Sgabeblack@google.com for (ThreadID tid = 0; tid < this->numThreads; tid++) 40212854Sgabeblack@google.com this->thread[tid]->setFuncExeInst(0); 40312854Sgabeblack@google.com} 40412854Sgabeblack@google.com 40512854Sgabeblack@google.comtemplate <class Impl> 40612854Sgabeblack@google.comFullO3CPU<Impl>::~FullO3CPU() 40712854Sgabeblack@google.com{ 40812854Sgabeblack@google.com} 40912854Sgabeblack@google.com 41012854Sgabeblack@google.comtemplate <class Impl> 41112854Sgabeblack@google.comvoid 41212854Sgabeblack@google.comFullO3CPU<Impl>::regProbePoints() 41312854Sgabeblack@google.com{ 41412854Sgabeblack@google.com BaseCPU::regProbePoints(); 41512854Sgabeblack@google.com 41612854Sgabeblack@google.com ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete"); 41712854Sgabeblack@google.com ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete"); 41812854Sgabeblack@google.com 41912854Sgabeblack@google.com fetch.regProbePoints(); 42012854Sgabeblack@google.com rename.regProbePoints(); 42112854Sgabeblack@google.com iew.regProbePoints(); 42212854Sgabeblack@google.com commit.regProbePoints(); 42312854Sgabeblack@google.com} 42412854Sgabeblack@google.com 42512854Sgabeblack@google.comtemplate <class Impl> 42612854Sgabeblack@google.comvoid 42712854Sgabeblack@google.comFullO3CPU<Impl>::regStats() 42812854Sgabeblack@google.com{ 42912854Sgabeblack@google.com BaseO3CPU::regStats(); 43012854Sgabeblack@google.com 43112854Sgabeblack@google.com // Register any of the O3CPU's stats here. 43212854Sgabeblack@google.com timesIdled 43312854Sgabeblack@google.com .name(name() + ".timesIdled") 43412854Sgabeblack@google.com .desc("Number of times that the entire CPU went into an idle state and" 43512854Sgabeblack@google.com " unscheduled itself") 43612854Sgabeblack@google.com .prereq(timesIdled); 43712854Sgabeblack@google.com 43812854Sgabeblack@google.com idleCycles 43912854Sgabeblack@google.com .name(name() + ".idleCycles") 44012854Sgabeblack@google.com .desc("Total number of cycles that the CPU has spent unscheduled due " 44112854Sgabeblack@google.com "to idling") 44212854Sgabeblack@google.com .prereq(idleCycles); 44312854Sgabeblack@google.com 44412854Sgabeblack@google.com quiesceCycles 44512854Sgabeblack@google.com .name(name() + ".quiesceCycles") 44612854Sgabeblack@google.com .desc("Total number of cycles that CPU has spent quiesced or waiting " 44712854Sgabeblack@google.com "for an interrupt") 44812854Sgabeblack@google.com .prereq(quiesceCycles); 44912854Sgabeblack@google.com 45012854Sgabeblack@google.com // Number of Instructions simulated 45112854Sgabeblack@google.com // -------------------------------- 45212854Sgabeblack@google.com // Should probably be in Base CPU but need templated 45312854Sgabeblack@google.com // MaxThreads so put in here instead 45412854Sgabeblack@google.com committedInsts 45512854Sgabeblack@google.com .init(numThreads) 45612854Sgabeblack@google.com .name(name() + ".committedInsts") 45712854Sgabeblack@google.com .desc("Number of Instructions Simulated") 45812854Sgabeblack@google.com .flags(Stats::total); 45912854Sgabeblack@google.com 46012854Sgabeblack@google.com committedOps 46112854Sgabeblack@google.com .init(numThreads) 46212854Sgabeblack@google.com .name(name() + ".committedOps") 46312854Sgabeblack@google.com .desc("Number of Ops (including micro ops) Simulated") 46412854Sgabeblack@google.com .flags(Stats::total); 46512854Sgabeblack@google.com 46612854Sgabeblack@google.com cpi 46712854Sgabeblack@google.com .name(name() + ".cpi") 46812854Sgabeblack@google.com .desc("CPI: Cycles Per Instruction") 46912854Sgabeblack@google.com .precision(6); 47012854Sgabeblack@google.com cpi = numCycles / committedInsts; 47112854Sgabeblack@google.com 47212854Sgabeblack@google.com totalCpi 47312854Sgabeblack@google.com .name(name() + ".cpi_total") 47412854Sgabeblack@google.com .desc("CPI: Total CPI of All Threads") 47512854Sgabeblack@google.com .precision(6); 47612854Sgabeblack@google.com totalCpi = numCycles / sum(committedInsts); 47712854Sgabeblack@google.com 47812854Sgabeblack@google.com ipc 47912854Sgabeblack@google.com .name(name() + ".ipc") 48012854Sgabeblack@google.com .desc("IPC: Instructions Per Cycle") 48112854Sgabeblack@google.com .precision(6); 48212854Sgabeblack@google.com ipc = committedInsts / numCycles; 48312854Sgabeblack@google.com 48412854Sgabeblack@google.com totalIpc 48512854Sgabeblack@google.com .name(name() + ".ipc_total") 48612854Sgabeblack@google.com .desc("IPC: Total IPC of All Threads") 48712854Sgabeblack@google.com .precision(6); 48812854Sgabeblack@google.com totalIpc = sum(committedInsts) / numCycles; 48912854Sgabeblack@google.com 49012854Sgabeblack@google.com this->fetch.regStats(); 49112854Sgabeblack@google.com this->decode.regStats(); 49212854Sgabeblack@google.com this->rename.regStats(); 49312854Sgabeblack@google.com this->iew.regStats(); 49412854Sgabeblack@google.com this->commit.regStats(); 49512854Sgabeblack@google.com this->rob.regStats(); 49612854Sgabeblack@google.com 49712854Sgabeblack@google.com intRegfileReads 49812854Sgabeblack@google.com .name(name() + ".int_regfile_reads") 49912854Sgabeblack@google.com .desc("number of integer regfile reads") 50012854Sgabeblack@google.com .prereq(intRegfileReads); 50112854Sgabeblack@google.com 50212854Sgabeblack@google.com intRegfileWrites 50312854Sgabeblack@google.com .name(name() + ".int_regfile_writes") 50412854Sgabeblack@google.com .desc("number of integer regfile writes") 50512854Sgabeblack@google.com .prereq(intRegfileWrites); 50612854Sgabeblack@google.com 50712854Sgabeblack@google.com fpRegfileReads 50812854Sgabeblack@google.com .name(name() + ".fp_regfile_reads") 50912854Sgabeblack@google.com .desc("number of floating regfile reads") 51012854Sgabeblack@google.com .prereq(fpRegfileReads); 51112854Sgabeblack@google.com 51212854Sgabeblack@google.com fpRegfileWrites 51312854Sgabeblack@google.com .name(name() + ".fp_regfile_writes") 51412854Sgabeblack@google.com .desc("number of floating regfile writes") 51512854Sgabeblack@google.com .prereq(fpRegfileWrites); 51612854Sgabeblack@google.com 51712854Sgabeblack@google.com ccRegfileReads 51812854Sgabeblack@google.com .name(name() + ".cc_regfile_reads") 51912854Sgabeblack@google.com .desc("number of cc regfile reads") 52012854Sgabeblack@google.com .prereq(ccRegfileReads); 52112854Sgabeblack@google.com 52212854Sgabeblack@google.com ccRegfileWrites 52312854Sgabeblack@google.com .name(name() + ".cc_regfile_writes") 52412854Sgabeblack@google.com .desc("number of cc regfile writes") 52512854Sgabeblack@google.com .prereq(ccRegfileWrites); 52612854Sgabeblack@google.com 52712854Sgabeblack@google.com miscRegfileReads 52812854Sgabeblack@google.com .name(name() + ".misc_regfile_reads") 52912854Sgabeblack@google.com .desc("number of misc regfile reads") 53012854Sgabeblack@google.com .prereq(miscRegfileReads); 53112854Sgabeblack@google.com 53212854Sgabeblack@google.com miscRegfileWrites 53312854Sgabeblack@google.com .name(name() + ".misc_regfile_writes") 53412854Sgabeblack@google.com .desc("number of misc regfile writes") 53512854Sgabeblack@google.com .prereq(miscRegfileWrites); 53612854Sgabeblack@google.com} 53712854Sgabeblack@google.com 53812854Sgabeblack@google.comtemplate <class Impl> 53912854Sgabeblack@google.comvoid 54012854Sgabeblack@google.comFullO3CPU<Impl>::tick() 54112854Sgabeblack@google.com{ 54212854Sgabeblack@google.com DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 54312854Sgabeblack@google.com assert(!switchedOut()); 54412854Sgabeblack@google.com assert(drainState() != DrainState::Drained); 54512854Sgabeblack@google.com 54612854Sgabeblack@google.com ++numCycles; 54712854Sgabeblack@google.com ppCycles->notify(1); 54812854Sgabeblack@google.com 54912854Sgabeblack@google.com// activity = false; 55012854Sgabeblack@google.com 55112854Sgabeblack@google.com //Tick each of the stages 55212854Sgabeblack@google.com fetch.tick(); 55312854Sgabeblack@google.com 55412854Sgabeblack@google.com decode.tick(); 55512854Sgabeblack@google.com 55612854Sgabeblack@google.com rename.tick(); 55712854Sgabeblack@google.com 55812854Sgabeblack@google.com iew.tick(); 55912854Sgabeblack@google.com 56012854Sgabeblack@google.com commit.tick(); 56112854Sgabeblack@google.com 56212854Sgabeblack@google.com // Now advance the time buffers 56312854Sgabeblack@google.com timeBuffer.advance(); 56412854Sgabeblack@google.com 56512854Sgabeblack@google.com fetchQueue.advance(); 56612854Sgabeblack@google.com decodeQueue.advance(); 56712854Sgabeblack@google.com renameQueue.advance(); 56812854Sgabeblack@google.com iewQueue.advance(); 56912854Sgabeblack@google.com 57012854Sgabeblack@google.com activityRec.advance(); 57112854Sgabeblack@google.com 57212854Sgabeblack@google.com if (removeInstsThisCycle) { 57312854Sgabeblack@google.com cleanUpRemovedInsts(); 57412854Sgabeblack@google.com } 57512854Sgabeblack@google.com 57612854Sgabeblack@google.com if (!tickEvent.scheduled()) { 57712854Sgabeblack@google.com if (_status == SwitchedOut) { 57812854Sgabeblack@google.com DPRINTF(O3CPU, "Switched out!\n"); 57912854Sgabeblack@google.com // increment stat 58012854Sgabeblack@google.com lastRunningCycle = curCycle(); 58112854Sgabeblack@google.com } else if (!activityRec.active() || _status == Idle) { 58212854Sgabeblack@google.com DPRINTF(O3CPU, "Idle!\n"); 58312854Sgabeblack@google.com lastRunningCycle = curCycle(); 58412854Sgabeblack@google.com timesIdled++; 58512854Sgabeblack@google.com } else { 58612854Sgabeblack@google.com schedule(tickEvent, clockEdge(Cycles(1))); 58712854Sgabeblack@google.com DPRINTF(O3CPU, "Scheduling next tick!\n"); 58812854Sgabeblack@google.com } 58912854Sgabeblack@google.com } 59012854Sgabeblack@google.com 59112854Sgabeblack@google.com if (!FullSystem) 59212854Sgabeblack@google.com updateThreadPriority(); 59312854Sgabeblack@google.com 59412854Sgabeblack@google.com tryDrain(); 59512854Sgabeblack@google.com} 59612854Sgabeblack@google.com 59712854Sgabeblack@google.comtemplate <class Impl> 59812854Sgabeblack@google.comvoid 59912854Sgabeblack@google.comFullO3CPU<Impl>::init() 60012854Sgabeblack@google.com{ 60112854Sgabeblack@google.com BaseCPU::init(); 60212854Sgabeblack@google.com 60312854Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; ++tid) { 60412854Sgabeblack@google.com // Set noSquashFromTC so that the CPU doesn't squash when initially 60512854Sgabeblack@google.com // setting up registers. 60612854Sgabeblack@google.com thread[tid]->noSquashFromTC = true; 60712854Sgabeblack@google.com // Initialise the ThreadContext's memory proxies 60812854Sgabeblack@google.com thread[tid]->initMemProxies(thread[tid]->getTC()); 60912854Sgabeblack@google.com } 61012854Sgabeblack@google.com 61112854Sgabeblack@google.com if (FullSystem && !params()->switched_out) { 61212854Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; tid++) { 61312854Sgabeblack@google.com ThreadContext *src_tc = threadContexts[tid]; 61412854Sgabeblack@google.com TheISA::initCPU(src_tc, src_tc->contextId()); 61512854Sgabeblack@google.com } 61612854Sgabeblack@google.com } 61712854Sgabeblack@google.com 61812854Sgabeblack@google.com // Clear noSquashFromTC. 61912854Sgabeblack@google.com for (int tid = 0; tid < numThreads; ++tid) 62012854Sgabeblack@google.com thread[tid]->noSquashFromTC = false; 62112854Sgabeblack@google.com 62212854Sgabeblack@google.com commit.setThreads(thread); 62312854Sgabeblack@google.com} 62412854Sgabeblack@google.com 62512854Sgabeblack@google.comtemplate <class Impl> 62612854Sgabeblack@google.comvoid 62712854Sgabeblack@google.comFullO3CPU<Impl>::startup() 62812854Sgabeblack@google.com{ 62912854Sgabeblack@google.com BaseCPU::startup(); 63012854Sgabeblack@google.com for (int tid = 0; tid < numThreads; ++tid) 63112854Sgabeblack@google.com isa[tid]->startup(threadContexts[tid]); 63212854Sgabeblack@google.com 63312854Sgabeblack@google.com fetch.startupStage(); 63412854Sgabeblack@google.com decode.startupStage(); 63512854Sgabeblack@google.com iew.startupStage(); 63612854Sgabeblack@google.com rename.startupStage(); 63712854Sgabeblack@google.com commit.startupStage(); 63812854Sgabeblack@google.com} 63912854Sgabeblack@google.com 64012854Sgabeblack@google.comtemplate <class Impl> 64112854Sgabeblack@google.comvoid 64212854Sgabeblack@google.comFullO3CPU<Impl>::activateThread(ThreadID tid) 64312854Sgabeblack@google.com{ 64412854Sgabeblack@google.com list<ThreadID>::iterator isActive = 64512854Sgabeblack@google.com std::find(activeThreads.begin(), activeThreads.end(), tid); 64612854Sgabeblack@google.com 64712854Sgabeblack@google.com DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 64812854Sgabeblack@google.com assert(!switchedOut()); 64912854Sgabeblack@google.com 65012854Sgabeblack@google.com if (isActive == activeThreads.end()) { 65112854Sgabeblack@google.com DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 65212854Sgabeblack@google.com tid); 65312854Sgabeblack@google.com 65412854Sgabeblack@google.com activeThreads.push_back(tid); 65512854Sgabeblack@google.com } 65612854Sgabeblack@google.com} 65712854Sgabeblack@google.com 65812854Sgabeblack@google.comtemplate <class Impl> 65912854Sgabeblack@google.comvoid 66012854Sgabeblack@google.comFullO3CPU<Impl>::deactivateThread(ThreadID tid) 66112854Sgabeblack@google.com{ 66212854Sgabeblack@google.com //Remove From Active List, if Active 66312854Sgabeblack@google.com list<ThreadID>::iterator thread_it = 66412854Sgabeblack@google.com std::find(activeThreads.begin(), activeThreads.end(), tid); 66512854Sgabeblack@google.com 66612854Sgabeblack@google.com DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 66712854Sgabeblack@google.com assert(!switchedOut()); 66812854Sgabeblack@google.com 66912854Sgabeblack@google.com if (thread_it != activeThreads.end()) { 67012854Sgabeblack@google.com DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 67112854Sgabeblack@google.com tid); 67212854Sgabeblack@google.com activeThreads.erase(thread_it); 67312854Sgabeblack@google.com } 67412854Sgabeblack@google.com 67512854Sgabeblack@google.com fetch.deactivateThread(tid); 67612854Sgabeblack@google.com commit.deactivateThread(tid); 67712854Sgabeblack@google.com} 67812854Sgabeblack@google.com 67912854Sgabeblack@google.comtemplate <class Impl> 68012854Sgabeblack@google.comCounter 68112854Sgabeblack@google.comFullO3CPU<Impl>::totalInsts() const 68212854Sgabeblack@google.com{ 68312854Sgabeblack@google.com Counter total(0); 68412854Sgabeblack@google.com 68512854Sgabeblack@google.com ThreadID size = thread.size(); 68612854Sgabeblack@google.com for (ThreadID i = 0; i < size; i++) 68712854Sgabeblack@google.com total += thread[i]->numInst; 68812854Sgabeblack@google.com 68912854Sgabeblack@google.com return total; 69012854Sgabeblack@google.com} 69112854Sgabeblack@google.com 69212854Sgabeblack@google.comtemplate <class Impl> 69312854Sgabeblack@google.comCounter 69412854Sgabeblack@google.comFullO3CPU<Impl>::totalOps() const 69512854Sgabeblack@google.com{ 69612854Sgabeblack@google.com Counter total(0); 69712854Sgabeblack@google.com 69812854Sgabeblack@google.com ThreadID size = thread.size(); 69912854Sgabeblack@google.com for (ThreadID i = 0; i < size; i++) 70012854Sgabeblack@google.com total += thread[i]->numOp; 70112854Sgabeblack@google.com 70212854Sgabeblack@google.com return total; 70312854Sgabeblack@google.com} 70412854Sgabeblack@google.com 70512854Sgabeblack@google.comtemplate <class Impl> 70612854Sgabeblack@google.comvoid 70712854Sgabeblack@google.comFullO3CPU<Impl>::activateContext(ThreadID tid) 70812854Sgabeblack@google.com{ 70912854Sgabeblack@google.com assert(!switchedOut()); 71012854Sgabeblack@google.com 71112854Sgabeblack@google.com // Needs to set each stage to running as well. 71212854Sgabeblack@google.com activateThread(tid); 71312854Sgabeblack@google.com 71412854Sgabeblack@google.com // We don't want to wake the CPU if it is drained. In that case, 71512854Sgabeblack@google.com // we just want to flag the thread as active and schedule the tick 71612854Sgabeblack@google.com // event from drainResume() instead. 71712854Sgabeblack@google.com if (drainState() == DrainState::Drained) 71812854Sgabeblack@google.com return; 71912854Sgabeblack@google.com 72012854Sgabeblack@google.com // If we are time 0 or if the last activation time is in the past, 72112854Sgabeblack@google.com // schedule the next tick and wake up the fetch unit 72212854Sgabeblack@google.com if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 72312854Sgabeblack@google.com scheduleTickEvent(Cycles(0)); 72412854Sgabeblack@google.com 72512854Sgabeblack@google.com // Be sure to signal that there's some activity so the CPU doesn't 72612854Sgabeblack@google.com // deschedule itself. 72712854Sgabeblack@google.com activityRec.activity(); 72812854Sgabeblack@google.com fetch.wakeFromQuiesce(); 72912854Sgabeblack@google.com 73012854Sgabeblack@google.com Cycles cycles(curCycle() - lastRunningCycle); 73112854Sgabeblack@google.com // @todo: This is an oddity that is only here to match the stats 73212854Sgabeblack@google.com if (cycles != 0) 73312854Sgabeblack@google.com --cycles; 73412854Sgabeblack@google.com quiesceCycles += cycles; 73512854Sgabeblack@google.com 73612854Sgabeblack@google.com lastActivatedCycle = curTick(); 73712854Sgabeblack@google.com 73812854Sgabeblack@google.com _status = Running; 73912854Sgabeblack@google.com 74012854Sgabeblack@google.com BaseCPU::activateContext(tid); 74112854Sgabeblack@google.com } 74212854Sgabeblack@google.com} 74312854Sgabeblack@google.com 74412854Sgabeblack@google.comtemplate <class Impl> 74512854Sgabeblack@google.comvoid 74612854Sgabeblack@google.comFullO3CPU<Impl>::suspendContext(ThreadID tid) 74712854Sgabeblack@google.com{ 74812854Sgabeblack@google.com DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 74912854Sgabeblack@google.com assert(!switchedOut()); 75012854Sgabeblack@google.com 75112854Sgabeblack@google.com deactivateThread(tid); 75212854Sgabeblack@google.com 75312854Sgabeblack@google.com // If this was the last thread then unschedule the tick event. 75412854Sgabeblack@google.com if (activeThreads.size() == 0) { 75512854Sgabeblack@google.com unscheduleTickEvent(); 75612854Sgabeblack@google.com lastRunningCycle = curCycle(); 75712854Sgabeblack@google.com _status = Idle; 75812854Sgabeblack@google.com } 75912854Sgabeblack@google.com 76012854Sgabeblack@google.com DPRINTF(Quiesce, "Suspending Context\n"); 76112854Sgabeblack@google.com 76212854Sgabeblack@google.com BaseCPU::suspendContext(tid); 76312854Sgabeblack@google.com} 76412854Sgabeblack@google.com 76512854Sgabeblack@google.comtemplate <class Impl> 76612854Sgabeblack@google.comvoid 76712854Sgabeblack@google.comFullO3CPU<Impl>::haltContext(ThreadID tid) 76812854Sgabeblack@google.com{ 76912854Sgabeblack@google.com //For now, this is the same as deallocate 77012854Sgabeblack@google.com DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 77112854Sgabeblack@google.com assert(!switchedOut()); 77212854Sgabeblack@google.com 77312854Sgabeblack@google.com deactivateThread(tid); 77412854Sgabeblack@google.com removeThread(tid); 77512854Sgabeblack@google.com} 77612854Sgabeblack@google.com 77712854Sgabeblack@google.comtemplate <class Impl> 77812854Sgabeblack@google.comvoid 77912854Sgabeblack@google.comFullO3CPU<Impl>::insertThread(ThreadID tid) 78012854Sgabeblack@google.com{ 78112854Sgabeblack@google.com DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 78212854Sgabeblack@google.com // Will change now that the PC and thread state is internal to the CPU 78312854Sgabeblack@google.com // and not in the ThreadContext. 78412854Sgabeblack@google.com ThreadContext *src_tc; 78512854Sgabeblack@google.com if (FullSystem) 78612854Sgabeblack@google.com src_tc = system->threadContexts[tid]; 78712854Sgabeblack@google.com else 78812854Sgabeblack@google.com src_tc = tcBase(tid); 78912854Sgabeblack@google.com 79012854Sgabeblack@google.com //Bind Int Regs to Rename Map 79112854Sgabeblack@google.com for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 79212854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getIntReg(); 79312854Sgabeblack@google.com 79412854Sgabeblack@google.com renameMap[tid].setEntry(ireg,phys_reg); 79512854Sgabeblack@google.com scoreboard.setReg(phys_reg); 79612854Sgabeblack@google.com } 79712854Sgabeblack@google.com 79812854Sgabeblack@google.com //Bind Float Regs to Rename Map 79912854Sgabeblack@google.com int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs; 80012854Sgabeblack@google.com for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) { 80112854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getFloatReg(); 80212854Sgabeblack@google.com 80312854Sgabeblack@google.com renameMap[tid].setEntry(freg,phys_reg); 80412854Sgabeblack@google.com scoreboard.setReg(phys_reg); 80512854Sgabeblack@google.com } 80612854Sgabeblack@google.com 80712854Sgabeblack@google.com //Bind condition-code Regs to Rename Map 80812854Sgabeblack@google.com max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs; 80912854Sgabeblack@google.com for (int creg = TheISA::CC_Reg_Base; 81012854Sgabeblack@google.com creg < max_reg; creg++) { 81112854Sgabeblack@google.com PhysRegIndex phys_reg = freeList.getCCReg(); 81212854Sgabeblack@google.com 81312854Sgabeblack@google.com renameMap[tid].setEntry(creg,phys_reg); 81412854Sgabeblack@google.com scoreboard.setReg(phys_reg); 81512854Sgabeblack@google.com } 81612854Sgabeblack@google.com 81712854Sgabeblack@google.com //Copy Thread Data Into RegFile 81812854Sgabeblack@google.com //this->copyFromTC(tid); 81912854Sgabeblack@google.com 82012854Sgabeblack@google.com //Set PC/NPC/NNPC 82112854Sgabeblack@google.com pcState(src_tc->pcState(), tid); 82212854Sgabeblack@google.com 82312854Sgabeblack@google.com src_tc->setStatus(ThreadContext::Active); 82412854Sgabeblack@google.com 82512854Sgabeblack@google.com activateContext(tid); 82612854Sgabeblack@google.com 82712854Sgabeblack@google.com //Reset ROB/IQ/LSQ Entries 82812854Sgabeblack@google.com commit.rob->resetEntries(); 82912854Sgabeblack@google.com iew.resetEntries(); 83012854Sgabeblack@google.com} 83112854Sgabeblack@google.com 83212854Sgabeblack@google.comtemplate <class Impl> 83312854Sgabeblack@google.comvoid 83412854Sgabeblack@google.comFullO3CPU<Impl>::removeThread(ThreadID tid) 83512854Sgabeblack@google.com{ 83612854Sgabeblack@google.com DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 83712854Sgabeblack@google.com 83812854Sgabeblack@google.com // Copy Thread Data From RegFile 83912854Sgabeblack@google.com // If thread is suspended, it might be re-allocated 84012854Sgabeblack@google.com // this->copyToTC(tid); 84112854Sgabeblack@google.com 84212854Sgabeblack@google.com 84312854Sgabeblack@google.com // @todo: 2-27-2008: Fix how we free up rename mappings 84412854Sgabeblack@google.com // here to alleviate the case for double-freeing registers 84512854Sgabeblack@google.com // in SMT workloads. 84612854Sgabeblack@google.com 84712854Sgabeblack@google.com // Unbind Int Regs from Rename Map 84812854Sgabeblack@google.com for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 84912854Sgabeblack@google.com PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 85012854Sgabeblack@google.com scoreboard.unsetReg(phys_reg); 85112854Sgabeblack@google.com freeList.addReg(phys_reg); 85212854Sgabeblack@google.com } 85312854Sgabeblack@google.com 85412854Sgabeblack@google.com // Unbind Float Regs from Rename Map 85512854Sgabeblack@google.com int max_reg = TheISA::FP_Reg_Base + TheISA::NumFloatRegs; 85612854Sgabeblack@google.com for (int freg = TheISA::FP_Reg_Base; freg < max_reg; freg++) { 85712854Sgabeblack@google.com PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 85812854Sgabeblack@google.com scoreboard.unsetReg(phys_reg); 85912854Sgabeblack@google.com freeList.addReg(phys_reg); 86012854Sgabeblack@google.com } 86112854Sgabeblack@google.com 86212854Sgabeblack@google.com // Unbind condition-code Regs from Rename Map 86312854Sgabeblack@google.com max_reg = TheISA::CC_Reg_Base + TheISA::NumCCRegs; 86412854Sgabeblack@google.com for (int creg = TheISA::CC_Reg_Base; creg < max_reg; creg++) { 86512854Sgabeblack@google.com PhysRegIndex phys_reg = renameMap[tid].lookup(creg); 86612854Sgabeblack@google.com scoreboard.unsetReg(phys_reg); 86712854Sgabeblack@google.com freeList.addReg(phys_reg); 86812854Sgabeblack@google.com } 86912854Sgabeblack@google.com 87012854Sgabeblack@google.com // Squash Throughout Pipeline 87112854Sgabeblack@google.com DynInstPtr inst = commit.rob->readHeadInst(tid); 87212854Sgabeblack@google.com InstSeqNum squash_seq_num = inst->seqNum; 87312854Sgabeblack@google.com fetch.squash(0, squash_seq_num, inst, tid); 87412854Sgabeblack@google.com decode.squash(tid); 87512854Sgabeblack@google.com rename.squash(squash_seq_num, tid); 87612854Sgabeblack@google.com iew.squash(tid); 87712854Sgabeblack@google.com iew.ldstQueue.squash(squash_seq_num, tid); 87812854Sgabeblack@google.com commit.rob->squash(squash_seq_num, tid); 87912854Sgabeblack@google.com 88012854Sgabeblack@google.com 88112854Sgabeblack@google.com assert(iew.instQueue.getCount(tid) == 0); 88212854Sgabeblack@google.com assert(iew.ldstQueue.getCount(tid) == 0); 88312854Sgabeblack@google.com 88412854Sgabeblack@google.com // Reset ROB/IQ/LSQ Entries 88512854Sgabeblack@google.com 88612854Sgabeblack@google.com // Commented out for now. This should be possible to do by 88712854Sgabeblack@google.com // telling all the pipeline stages to drain first, and then 88812854Sgabeblack@google.com // checking until the drain completes. Once the pipeline is 88912854Sgabeblack@google.com // drained, call resetEntries(). - 10-09-06 ktlim 89012854Sgabeblack@google.com/* 89112854Sgabeblack@google.com if (activeThreads.size() >= 1) { 89212854Sgabeblack@google.com commit.rob->resetEntries(); 89312854Sgabeblack@google.com iew.resetEntries(); 89412854Sgabeblack@google.com } 89512854Sgabeblack@google.com*/ 89612854Sgabeblack@google.com} 89712854Sgabeblack@google.com 89812854Sgabeblack@google.comtemplate <class Impl> 89912854Sgabeblack@google.comFault 90012854Sgabeblack@google.comFullO3CPU<Impl>::hwrei(ThreadID tid) 90112854Sgabeblack@google.com{ 90212854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA 90312854Sgabeblack@google.com // Need to clear the lock flag upon returning from an interrupt. 90412854Sgabeblack@google.com this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 90512854Sgabeblack@google.com 90612854Sgabeblack@google.com this->thread[tid]->kernelStats->hwrei(); 90712854Sgabeblack@google.com 90812854Sgabeblack@google.com // FIXME: XXX check for interrupts? XXX 90912854Sgabeblack@google.com#endif 91012854Sgabeblack@google.com return NoFault; 91112854Sgabeblack@google.com} 91212854Sgabeblack@google.com 91312854Sgabeblack@google.comtemplate <class Impl> 91412854Sgabeblack@google.combool 91512854Sgabeblack@google.comFullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 91612854Sgabeblack@google.com{ 91712854Sgabeblack@google.com#if THE_ISA == ALPHA_ISA 91812854Sgabeblack@google.com if (this->thread[tid]->kernelStats) 91912854Sgabeblack@google.com this->thread[tid]->kernelStats->callpal(palFunc, 92012854Sgabeblack@google.com this->threadContexts[tid]); 92112854Sgabeblack@google.com 92212854Sgabeblack@google.com switch (palFunc) { 92312854Sgabeblack@google.com case PAL::halt: 92412854Sgabeblack@google.com halt(); 92512854Sgabeblack@google.com if (--System::numSystemsRunning == 0) 92612854Sgabeblack@google.com exitSimLoop("all cpus halted"); 92712854Sgabeblack@google.com break; 92812854Sgabeblack@google.com 92912854Sgabeblack@google.com case PAL::bpt: 93012854Sgabeblack@google.com case PAL::bugchk: 93112854Sgabeblack@google.com if (this->system->breakpoint()) 93212854Sgabeblack@google.com return false; 93312854Sgabeblack@google.com break; 93412854Sgabeblack@google.com } 93512854Sgabeblack@google.com#endif 93612854Sgabeblack@google.com return true; 93712854Sgabeblack@google.com} 93812854Sgabeblack@google.com 93912854Sgabeblack@google.comtemplate <class Impl> 94012854Sgabeblack@google.comFault 94112854Sgabeblack@google.comFullO3CPU<Impl>::getInterrupts() 94212854Sgabeblack@google.com{ 94312854Sgabeblack@google.com // Check if there are any outstanding interrupts 94412854Sgabeblack@google.com return this->interrupts[0]->getInterrupt(this->threadContexts[0]); 94512854Sgabeblack@google.com} 94612854Sgabeblack@google.com 94712854Sgabeblack@google.comtemplate <class Impl> 94812854Sgabeblack@google.comvoid 94912854Sgabeblack@google.comFullO3CPU<Impl>::processInterrupts(const Fault &interrupt) 95012854Sgabeblack@google.com{ 95112854Sgabeblack@google.com // Check for interrupts here. For now can copy the code that 95212854Sgabeblack@google.com // exists within isa_fullsys_traits.hh. Also assume that thread 0 95312854Sgabeblack@google.com // is the one that handles the interrupts. 95412854Sgabeblack@google.com // @todo: Possibly consolidate the interrupt checking code. 95512854Sgabeblack@google.com // @todo: Allow other threads to handle interrupts. 95612854Sgabeblack@google.com 95712854Sgabeblack@google.com assert(interrupt != NoFault); 95812854Sgabeblack@google.com this->interrupts[0]->updateIntrInfo(this->threadContexts[0]); 95912854Sgabeblack@google.com 96012854Sgabeblack@google.com DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 96112854Sgabeblack@google.com this->trap(interrupt, 0, nullptr); 96212854Sgabeblack@google.com} 96312854Sgabeblack@google.com 96412854Sgabeblack@google.comtemplate <class Impl> 96512854Sgabeblack@google.comvoid 96612854Sgabeblack@google.comFullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid, 96712854Sgabeblack@google.com const StaticInstPtr &inst) 96812854Sgabeblack@google.com{ 96912854Sgabeblack@google.com // Pass the thread's TC into the invoke method. 97012854Sgabeblack@google.com fault->invoke(this->threadContexts[tid], inst); 97112854Sgabeblack@google.com} 97212854Sgabeblack@google.com 97312854Sgabeblack@google.comtemplate <class Impl> 97412854Sgabeblack@google.comvoid 97512854Sgabeblack@google.comFullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid) 97612854Sgabeblack@google.com{ 97712854Sgabeblack@google.com DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 97812854Sgabeblack@google.com 97912854Sgabeblack@google.com DPRINTF(Activity,"Activity: syscall() called.\n"); 98012854Sgabeblack@google.com 98112854Sgabeblack@google.com // Temporarily increase this by one to account for the syscall 98212854Sgabeblack@google.com // instruction. 98312854Sgabeblack@google.com ++(this->thread[tid]->funcExeInst); 98412854Sgabeblack@google.com 98512854Sgabeblack@google.com // Execute the actual syscall. 98612854Sgabeblack@google.com this->thread[tid]->syscall(callnum); 98712854Sgabeblack@google.com 98812854Sgabeblack@google.com // Decrease funcExeInst by one as the normal commit will handle 98912854Sgabeblack@google.com // incrementing it. 99012854Sgabeblack@google.com --(this->thread[tid]->funcExeInst); 99112854Sgabeblack@google.com} 99212854Sgabeblack@google.com 99312854Sgabeblack@google.comtemplate <class Impl> 99412854Sgabeblack@google.comvoid 99512854Sgabeblack@google.comFullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const 99612854Sgabeblack@google.com{ 99712854Sgabeblack@google.com thread[tid]->serialize(cp); 99812854Sgabeblack@google.com} 99912854Sgabeblack@google.com 100012854Sgabeblack@google.comtemplate <class Impl> 100112854Sgabeblack@google.comvoid 100212854Sgabeblack@google.comFullO3CPU<Impl>::unserializeThread(CheckpointIn &cp, ThreadID tid) 100312854Sgabeblack@google.com{ 100412854Sgabeblack@google.com thread[tid]->unserialize(cp); 100512854Sgabeblack@google.com} 100612854Sgabeblack@google.com 100712854Sgabeblack@google.comtemplate <class Impl> 100812854Sgabeblack@google.comDrainState 100912854Sgabeblack@google.comFullO3CPU<Impl>::drain() 101012854Sgabeblack@google.com{ 101112854Sgabeblack@google.com // If the CPU isn't doing anything, then return immediately. 101212854Sgabeblack@google.com if (switchedOut()) 101312854Sgabeblack@google.com return DrainState::Drained; 101412854Sgabeblack@google.com 101512854Sgabeblack@google.com DPRINTF(Drain, "Draining...\n"); 101612854Sgabeblack@google.com 101712854Sgabeblack@google.com // We only need to signal a drain to the commit stage as this 101812854Sgabeblack@google.com // initiates squashing controls the draining. Once the commit 101912854Sgabeblack@google.com // stage commits an instruction where it is safe to stop, it'll 102012854Sgabeblack@google.com // squash the rest of the instructions in the pipeline and force 102112854Sgabeblack@google.com // the fetch stage to stall. The pipeline will be drained once all 102212854Sgabeblack@google.com // in-flight instructions have retired. 102312854Sgabeblack@google.com commit.drain(); 102412854Sgabeblack@google.com 102512854Sgabeblack@google.com // Wake the CPU and record activity so everything can drain out if 102612854Sgabeblack@google.com // the CPU was not able to immediately drain. 102712854Sgabeblack@google.com if (!isDrained()) { 102812854Sgabeblack@google.com wakeCPU(); 102912854Sgabeblack@google.com activityRec.activity(); 103012854Sgabeblack@google.com 103112854Sgabeblack@google.com DPRINTF(Drain, "CPU not drained\n"); 103212854Sgabeblack@google.com 103312854Sgabeblack@google.com return DrainState::Draining; 103412854Sgabeblack@google.com } else { 103512854Sgabeblack@google.com DPRINTF(Drain, "CPU is already drained\n"); 103612854Sgabeblack@google.com if (tickEvent.scheduled()) 103712854Sgabeblack@google.com deschedule(tickEvent); 103812854Sgabeblack@google.com 103912854Sgabeblack@google.com // Flush out any old data from the time buffers. In 104012854Sgabeblack@google.com // particular, there might be some data in flight from the 104112854Sgabeblack@google.com // fetch stage that isn't visible in any of the CPU buffers we 104212854Sgabeblack@google.com // test in isDrained(). 104312854Sgabeblack@google.com for (int i = 0; i < timeBuffer.getSize(); ++i) { 104412854Sgabeblack@google.com timeBuffer.advance(); 104512854Sgabeblack@google.com fetchQueue.advance(); 104612854Sgabeblack@google.com decodeQueue.advance(); 104712854Sgabeblack@google.com renameQueue.advance(); 104812854Sgabeblack@google.com iewQueue.advance(); 104912854Sgabeblack@google.com } 105012854Sgabeblack@google.com 105112854Sgabeblack@google.com drainSanityCheck(); 105212854Sgabeblack@google.com return DrainState::Drained; 105312854Sgabeblack@google.com } 105412854Sgabeblack@google.com} 105512854Sgabeblack@google.com 105612854Sgabeblack@google.comtemplate <class Impl> 105712854Sgabeblack@google.combool 105812854Sgabeblack@google.comFullO3CPU<Impl>::tryDrain() 105912854Sgabeblack@google.com{ 106012854Sgabeblack@google.com if (drainState() != DrainState::Draining || !isDrained()) 106112854Sgabeblack@google.com return false; 106212854Sgabeblack@google.com 106312854Sgabeblack@google.com if (tickEvent.scheduled()) 106412854Sgabeblack@google.com deschedule(tickEvent); 106512854Sgabeblack@google.com 106612854Sgabeblack@google.com DPRINTF(Drain, "CPU done draining, processing drain event\n"); 106712854Sgabeblack@google.com signalDrainDone(); 106812854Sgabeblack@google.com 106912854Sgabeblack@google.com return true; 107012854Sgabeblack@google.com} 107112854Sgabeblack@google.com 107212854Sgabeblack@google.comtemplate <class Impl> 107312854Sgabeblack@google.comvoid 107412854Sgabeblack@google.comFullO3CPU<Impl>::drainSanityCheck() const 107512854Sgabeblack@google.com{ 107612854Sgabeblack@google.com assert(isDrained()); 107712854Sgabeblack@google.com fetch.drainSanityCheck(); 107812854Sgabeblack@google.com decode.drainSanityCheck(); 107912854Sgabeblack@google.com rename.drainSanityCheck(); 108012854Sgabeblack@google.com iew.drainSanityCheck(); 108112854Sgabeblack@google.com commit.drainSanityCheck(); 108212854Sgabeblack@google.com} 108312854Sgabeblack@google.com 108412854Sgabeblack@google.comtemplate <class Impl> 108512854Sgabeblack@google.combool 108612854Sgabeblack@google.comFullO3CPU<Impl>::isDrained() const 108712854Sgabeblack@google.com{ 108812854Sgabeblack@google.com bool drained(true); 108912854Sgabeblack@google.com 109012854Sgabeblack@google.com if (!instList.empty() || !removeList.empty()) { 109112854Sgabeblack@google.com DPRINTF(Drain, "Main CPU structures not drained.\n"); 109212854Sgabeblack@google.com drained = false; 109312854Sgabeblack@google.com } 109412854Sgabeblack@google.com 109512854Sgabeblack@google.com if (!fetch.isDrained()) { 109612854Sgabeblack@google.com DPRINTF(Drain, "Fetch not drained.\n"); 109712854Sgabeblack@google.com drained = false; 109812854Sgabeblack@google.com } 109912854Sgabeblack@google.com 110012854Sgabeblack@google.com if (!decode.isDrained()) { 110112854Sgabeblack@google.com DPRINTF(Drain, "Decode not drained.\n"); 110212854Sgabeblack@google.com drained = false; 110312854Sgabeblack@google.com } 110412854Sgabeblack@google.com 110512854Sgabeblack@google.com if (!rename.isDrained()) { 110612854Sgabeblack@google.com DPRINTF(Drain, "Rename not drained.\n"); 110712854Sgabeblack@google.com drained = false; 110812854Sgabeblack@google.com } 110912854Sgabeblack@google.com 111012854Sgabeblack@google.com if (!iew.isDrained()) { 111112854Sgabeblack@google.com DPRINTF(Drain, "IEW not drained.\n"); 111212854Sgabeblack@google.com drained = false; 111312854Sgabeblack@google.com } 111412854Sgabeblack@google.com 111512854Sgabeblack@google.com if (!commit.isDrained()) { 111612854Sgabeblack@google.com DPRINTF(Drain, "Commit not drained.\n"); 111712854Sgabeblack@google.com drained = false; 111812854Sgabeblack@google.com } 111912854Sgabeblack@google.com 112012854Sgabeblack@google.com return drained; 112112854Sgabeblack@google.com} 112212854Sgabeblack@google.com 112312854Sgabeblack@google.comtemplate <class Impl> 112412854Sgabeblack@google.comvoid 112512854Sgabeblack@google.comFullO3CPU<Impl>::commitDrained(ThreadID tid) 112612854Sgabeblack@google.com{ 112712854Sgabeblack@google.com fetch.drainStall(tid); 112812854Sgabeblack@google.com} 112912854Sgabeblack@google.com 113012854Sgabeblack@google.comtemplate <class Impl> 113112854Sgabeblack@google.comvoid 113212854Sgabeblack@google.comFullO3CPU<Impl>::drainResume() 113312854Sgabeblack@google.com{ 113412854Sgabeblack@google.com if (switchedOut()) 113512854Sgabeblack@google.com return; 113612854Sgabeblack@google.com 113712854Sgabeblack@google.com DPRINTF(Drain, "Resuming...\n"); 113812854Sgabeblack@google.com verifyMemoryMode(); 113912854Sgabeblack@google.com 114012854Sgabeblack@google.com fetch.drainResume(); 114112854Sgabeblack@google.com commit.drainResume(); 114212854Sgabeblack@google.com 114312854Sgabeblack@google.com _status = Idle; 114412854Sgabeblack@google.com for (ThreadID i = 0; i < thread.size(); i++) { 114512854Sgabeblack@google.com if (thread[i]->status() == ThreadContext::Active) { 114612854Sgabeblack@google.com DPRINTF(Drain, "Activating thread: %i\n", i); 114712854Sgabeblack@google.com activateThread(i); 114812854Sgabeblack@google.com _status = Running; 114912854Sgabeblack@google.com } 115012854Sgabeblack@google.com } 115112854Sgabeblack@google.com 115212854Sgabeblack@google.com assert(!tickEvent.scheduled()); 115312854Sgabeblack@google.com if (_status == Running) 115412854Sgabeblack@google.com schedule(tickEvent, nextCycle()); 115512854Sgabeblack@google.com} 115612854Sgabeblack@google.com 115712854Sgabeblack@google.comtemplate <class Impl> 115812854Sgabeblack@google.comvoid 115912854Sgabeblack@google.comFullO3CPU<Impl>::switchOut() 116012854Sgabeblack@google.com{ 116112854Sgabeblack@google.com DPRINTF(O3CPU, "Switching out\n"); 116212854Sgabeblack@google.com BaseCPU::switchOut(); 116312854Sgabeblack@google.com 116412854Sgabeblack@google.com activityRec.reset(); 116512854Sgabeblack@google.com 116612854Sgabeblack@google.com _status = SwitchedOut; 116712854Sgabeblack@google.com 116812854Sgabeblack@google.com if (checker) 116912854Sgabeblack@google.com checker->switchOut(); 117012854Sgabeblack@google.com} 117112854Sgabeblack@google.com 117212854Sgabeblack@google.comtemplate <class Impl> 117312854Sgabeblack@google.comvoid 117412854Sgabeblack@google.comFullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 117512854Sgabeblack@google.com{ 117612854Sgabeblack@google.com BaseCPU::takeOverFrom(oldCPU); 117712854Sgabeblack@google.com 117812854Sgabeblack@google.com fetch.takeOverFrom(); 117912854Sgabeblack@google.com decode.takeOverFrom(); 118012854Sgabeblack@google.com rename.takeOverFrom(); 118112854Sgabeblack@google.com iew.takeOverFrom(); 118212854Sgabeblack@google.com commit.takeOverFrom(); 118312854Sgabeblack@google.com 118412854Sgabeblack@google.com assert(!tickEvent.scheduled()); 118512854Sgabeblack@google.com 118612854Sgabeblack@google.com FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 118712854Sgabeblack@google.com if (oldO3CPU) 118812854Sgabeblack@google.com globalSeqNum = oldO3CPU->globalSeqNum; 118912854Sgabeblack@google.com 119012854Sgabeblack@google.com lastRunningCycle = curCycle(); 119112854Sgabeblack@google.com _status = Idle; 119212854Sgabeblack@google.com} 119312854Sgabeblack@google.com 119412854Sgabeblack@google.comtemplate <class Impl> 119512854Sgabeblack@google.comvoid 119612854Sgabeblack@google.comFullO3CPU<Impl>::verifyMemoryMode() const 119712854Sgabeblack@google.com{ 119812854Sgabeblack@google.com if (!system->isTimingMode()) { 119912854Sgabeblack@google.com fatal("The O3 CPU requires the memory system to be in " 120012854Sgabeblack@google.com "'timing' mode.\n"); 120112854Sgabeblack@google.com } 120212854Sgabeblack@google.com} 120312854Sgabeblack@google.com 120412854Sgabeblack@google.comtemplate <class Impl> 120512854Sgabeblack@google.comTheISA::MiscReg 120612854Sgabeblack@google.comFullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) const 120712854Sgabeblack@google.com{ 120812854Sgabeblack@google.com return this->isa[tid]->readMiscRegNoEffect(misc_reg); 120912854Sgabeblack@google.com} 121012854Sgabeblack@google.com 121112854Sgabeblack@google.comtemplate <class Impl> 121212854Sgabeblack@google.comTheISA::MiscReg 121312854Sgabeblack@google.comFullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 121412854Sgabeblack@google.com{ 121512854Sgabeblack@google.com miscRegfileReads++; 121612854Sgabeblack@google.com return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 121712854Sgabeblack@google.com} 121812854Sgabeblack@google.com 121912854Sgabeblack@google.comtemplate <class Impl> 122012854Sgabeblack@google.comvoid 122112854Sgabeblack@google.comFullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 122212854Sgabeblack@google.com const TheISA::MiscReg &val, ThreadID tid) 122312854Sgabeblack@google.com{ 122412854Sgabeblack@google.com this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 122512854Sgabeblack@google.com} 122612854Sgabeblack@google.com 122712854Sgabeblack@google.comtemplate <class Impl> 122812854Sgabeblack@google.comvoid 122912854Sgabeblack@google.comFullO3CPU<Impl>::setMiscReg(int misc_reg, 123012854Sgabeblack@google.com const TheISA::MiscReg &val, ThreadID tid) 123112854Sgabeblack@google.com{ 123212854Sgabeblack@google.com miscRegfileWrites++; 123312854Sgabeblack@google.com this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 123412854Sgabeblack@google.com} 123512854Sgabeblack@google.com 123612854Sgabeblack@google.comtemplate <class Impl> 123712854Sgabeblack@google.comuint64_t 123812854Sgabeblack@google.comFullO3CPU<Impl>::readIntReg(int reg_idx) 123912854Sgabeblack@google.com{ 124012854Sgabeblack@google.com intRegfileReads++; 124112854Sgabeblack@google.com return regFile.readIntReg(reg_idx); 124212854Sgabeblack@google.com} 124312854Sgabeblack@google.com 124412854Sgabeblack@google.comtemplate <class Impl> 124512854Sgabeblack@google.comFloatReg 124612854Sgabeblack@google.comFullO3CPU<Impl>::readFloatReg(int reg_idx) 124712854Sgabeblack@google.com{ 124812854Sgabeblack@google.com fpRegfileReads++; 124912854Sgabeblack@google.com return regFile.readFloatReg(reg_idx); 125012854Sgabeblack@google.com} 125112854Sgabeblack@google.com 125212854Sgabeblack@google.comtemplate <class Impl> 125312854Sgabeblack@google.comFloatRegBits 125412854Sgabeblack@google.comFullO3CPU<Impl>::readFloatRegBits(int reg_idx) 125512854Sgabeblack@google.com{ 125612854Sgabeblack@google.com fpRegfileReads++; 125712854Sgabeblack@google.com return regFile.readFloatRegBits(reg_idx); 125812854Sgabeblack@google.com} 125912854Sgabeblack@google.com 126012854Sgabeblack@google.comtemplate <class Impl> 126112854Sgabeblack@google.comCCReg 126212854Sgabeblack@google.comFullO3CPU<Impl>::readCCReg(int reg_idx) 126312854Sgabeblack@google.com{ 126412854Sgabeblack@google.com ccRegfileReads++; 126512854Sgabeblack@google.com return regFile.readCCReg(reg_idx); 126612854Sgabeblack@google.com} 126712854Sgabeblack@google.com 126812854Sgabeblack@google.comtemplate <class Impl> 126912854Sgabeblack@google.comvoid 127012854Sgabeblack@google.comFullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 127112854Sgabeblack@google.com{ 127212854Sgabeblack@google.com intRegfileWrites++; 127312854Sgabeblack@google.com regFile.setIntReg(reg_idx, val); 127412854Sgabeblack@google.com} 127512854Sgabeblack@google.com 127612854Sgabeblack@google.comtemplate <class Impl> 127712854Sgabeblack@google.comvoid 127812854Sgabeblack@google.comFullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 127912854Sgabeblack@google.com{ 128012854Sgabeblack@google.com fpRegfileWrites++; 128112854Sgabeblack@google.com regFile.setFloatReg(reg_idx, val); 128212854Sgabeblack@google.com} 128312854Sgabeblack@google.com 128412854Sgabeblack@google.comtemplate <class Impl> 128512854Sgabeblack@google.comvoid 128612854Sgabeblack@google.comFullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 128712854Sgabeblack@google.com{ 128812854Sgabeblack@google.com fpRegfileWrites++; 128912854Sgabeblack@google.com regFile.setFloatRegBits(reg_idx, val); 129012854Sgabeblack@google.com} 129112854Sgabeblack@google.com 129212854Sgabeblack@google.comtemplate <class Impl> 129312854Sgabeblack@google.comvoid 129412854Sgabeblack@google.comFullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val) 129512854Sgabeblack@google.com{ 129612854Sgabeblack@google.com ccRegfileWrites++; 129712854Sgabeblack@google.com regFile.setCCReg(reg_idx, val); 129812854Sgabeblack@google.com} 129912854Sgabeblack@google.com 130012854Sgabeblack@google.comtemplate <class Impl> 130112854Sgabeblack@google.comuint64_t 130212854Sgabeblack@google.comFullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 130312854Sgabeblack@google.com{ 130412854Sgabeblack@google.com intRegfileReads++; 130512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 130612854Sgabeblack@google.com 130712854Sgabeblack@google.com return regFile.readIntReg(phys_reg); 130812854Sgabeblack@google.com} 130912854Sgabeblack@google.com 131012854Sgabeblack@google.comtemplate <class Impl> 131112854Sgabeblack@google.comfloat 131212854Sgabeblack@google.comFullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 131312854Sgabeblack@google.com{ 131412854Sgabeblack@google.com fpRegfileReads++; 131512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 131612854Sgabeblack@google.com 131712854Sgabeblack@google.com return regFile.readFloatReg(phys_reg); 131812854Sgabeblack@google.com} 131912854Sgabeblack@google.com 132012854Sgabeblack@google.comtemplate <class Impl> 132112854Sgabeblack@google.comuint64_t 132212854Sgabeblack@google.comFullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 132312854Sgabeblack@google.com{ 132412854Sgabeblack@google.com fpRegfileReads++; 132512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 132612854Sgabeblack@google.com 132712854Sgabeblack@google.com return regFile.readFloatRegBits(phys_reg); 132812854Sgabeblack@google.com} 132912854Sgabeblack@google.com 133012854Sgabeblack@google.comtemplate <class Impl> 133112854Sgabeblack@google.comCCReg 133212854Sgabeblack@google.comFullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 133312854Sgabeblack@google.com{ 133412854Sgabeblack@google.com ccRegfileReads++; 133512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 133612854Sgabeblack@google.com 133712854Sgabeblack@google.com return regFile.readCCReg(phys_reg); 133812854Sgabeblack@google.com} 133912854Sgabeblack@google.com 134012854Sgabeblack@google.comtemplate <class Impl> 134112854Sgabeblack@google.comvoid 134212854Sgabeblack@google.comFullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 134312854Sgabeblack@google.com{ 134412854Sgabeblack@google.com intRegfileWrites++; 134512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 134612854Sgabeblack@google.com 134712854Sgabeblack@google.com regFile.setIntReg(phys_reg, val); 134812854Sgabeblack@google.com} 134912854Sgabeblack@google.com 135012854Sgabeblack@google.comtemplate <class Impl> 135112854Sgabeblack@google.comvoid 135212854Sgabeblack@google.comFullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 135312854Sgabeblack@google.com{ 135412854Sgabeblack@google.com fpRegfileWrites++; 135512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 135612854Sgabeblack@google.com 135712854Sgabeblack@google.com regFile.setFloatReg(phys_reg, val); 135812854Sgabeblack@google.com} 135912854Sgabeblack@google.com 136012854Sgabeblack@google.comtemplate <class Impl> 136112854Sgabeblack@google.comvoid 136212854Sgabeblack@google.comFullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 136312854Sgabeblack@google.com{ 136412854Sgabeblack@google.com fpRegfileWrites++; 136512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 136612854Sgabeblack@google.com 136712854Sgabeblack@google.com regFile.setFloatRegBits(phys_reg, val); 136812854Sgabeblack@google.com} 136912854Sgabeblack@google.com 137012854Sgabeblack@google.comtemplate <class Impl> 137112854Sgabeblack@google.comvoid 137212854Sgabeblack@google.comFullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) 137312854Sgabeblack@google.com{ 137412854Sgabeblack@google.com ccRegfileWrites++; 137512854Sgabeblack@google.com PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 137612854Sgabeblack@google.com 137712854Sgabeblack@google.com regFile.setCCReg(phys_reg, val); 137812854Sgabeblack@google.com} 137912854Sgabeblack@google.com 138012854Sgabeblack@google.comtemplate <class Impl> 138112854Sgabeblack@google.comTheISA::PCState 138212854Sgabeblack@google.comFullO3CPU<Impl>::pcState(ThreadID tid) 138312854Sgabeblack@google.com{ 138412854Sgabeblack@google.com return commit.pcState(tid); 138512854Sgabeblack@google.com} 138612854Sgabeblack@google.com 138712854Sgabeblack@google.comtemplate <class Impl> 138812854Sgabeblack@google.comvoid 138912854Sgabeblack@google.comFullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 139012854Sgabeblack@google.com{ 139112854Sgabeblack@google.com commit.pcState(val, tid); 139212854Sgabeblack@google.com} 139312854Sgabeblack@google.com 139412854Sgabeblack@google.comtemplate <class Impl> 139512854Sgabeblack@google.comAddr 139612854Sgabeblack@google.comFullO3CPU<Impl>::instAddr(ThreadID tid) 139712854Sgabeblack@google.com{ 139812854Sgabeblack@google.com return commit.instAddr(tid); 139912854Sgabeblack@google.com} 140012854Sgabeblack@google.com 140112854Sgabeblack@google.comtemplate <class Impl> 140212854Sgabeblack@google.comAddr 140312854Sgabeblack@google.comFullO3CPU<Impl>::nextInstAddr(ThreadID tid) 140412854Sgabeblack@google.com{ 140512854Sgabeblack@google.com return commit.nextInstAddr(tid); 140612854Sgabeblack@google.com} 140712854Sgabeblack@google.com 140812854Sgabeblack@google.comtemplate <class Impl> 140912854Sgabeblack@google.comMicroPC 141012854Sgabeblack@google.comFullO3CPU<Impl>::microPC(ThreadID tid) 141112854Sgabeblack@google.com{ 141212854Sgabeblack@google.com return commit.microPC(tid); 141312854Sgabeblack@google.com} 141412854Sgabeblack@google.com 141512854Sgabeblack@google.comtemplate <class Impl> 141612854Sgabeblack@google.comvoid 141712854Sgabeblack@google.comFullO3CPU<Impl>::squashFromTC(ThreadID tid) 141812854Sgabeblack@google.com{ 141912854Sgabeblack@google.com this->thread[tid]->noSquashFromTC = true; 142012854Sgabeblack@google.com this->commit.generateTCEvent(tid); 142112854Sgabeblack@google.com} 142212854Sgabeblack@google.com 142312854Sgabeblack@google.comtemplate <class Impl> 142412854Sgabeblack@google.comtypename FullO3CPU<Impl>::ListIt 142512854Sgabeblack@google.comFullO3CPU<Impl>::addInst(DynInstPtr &inst) 142612854Sgabeblack@google.com{ 142712854Sgabeblack@google.com instList.push_back(inst); 142812854Sgabeblack@google.com 142912854Sgabeblack@google.com return --(instList.end()); 143012854Sgabeblack@google.com} 143112854Sgabeblack@google.com 143212854Sgabeblack@google.comtemplate <class Impl> 143312854Sgabeblack@google.comvoid 143412854Sgabeblack@google.comFullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst) 143512854Sgabeblack@google.com{ 143612854Sgabeblack@google.com // Keep an instruction count. 143712854Sgabeblack@google.com if (!inst->isMicroop() || inst->isLastMicroop()) { 143812854Sgabeblack@google.com thread[tid]->numInst++; 143912854Sgabeblack@google.com thread[tid]->numInsts++; 144012854Sgabeblack@google.com committedInsts[tid]++; 144112854Sgabeblack@google.com system->totalNumInsts++; 144212854Sgabeblack@google.com 144312854Sgabeblack@google.com // Check for instruction-count-based events. 144412854Sgabeblack@google.com comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 144512854Sgabeblack@google.com system->instEventQueue.serviceEvents(system->totalNumInsts); 144612854Sgabeblack@google.com } 144712854Sgabeblack@google.com thread[tid]->numOp++; 144812854Sgabeblack@google.com thread[tid]->numOps++; 144912854Sgabeblack@google.com committedOps[tid]++; 145012854Sgabeblack@google.com 145112854Sgabeblack@google.com probeInstCommit(inst->staticInst); 145212854Sgabeblack@google.com} 145312854Sgabeblack@google.com 145412854Sgabeblack@google.comtemplate <class Impl> 145512854Sgabeblack@google.comvoid 145612854Sgabeblack@google.comFullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 145712854Sgabeblack@google.com{ 145812854Sgabeblack@google.com DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 145912854Sgabeblack@google.com "[sn:%lli]\n", 146012854Sgabeblack@google.com inst->threadNumber, inst->pcState(), inst->seqNum); 146112854Sgabeblack@google.com 146212854Sgabeblack@google.com removeInstsThisCycle = true; 146312854Sgabeblack@google.com 146412854Sgabeblack@google.com // Remove the front instruction. 146512854Sgabeblack@google.com removeList.push(inst->getInstListIt()); 146612854Sgabeblack@google.com} 146712854Sgabeblack@google.com 146812854Sgabeblack@google.comtemplate <class Impl> 146912854Sgabeblack@google.comvoid 147012854Sgabeblack@google.comFullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 147112854Sgabeblack@google.com{ 147212854Sgabeblack@google.com DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 147312854Sgabeblack@google.com " list.\n", tid); 147412854Sgabeblack@google.com 147512854Sgabeblack@google.com ListIt end_it; 147612854Sgabeblack@google.com 147712854Sgabeblack@google.com bool rob_empty = false; 147812854Sgabeblack@google.com 147912854Sgabeblack@google.com if (instList.empty()) { 148012854Sgabeblack@google.com return; 148112854Sgabeblack@google.com } else if (rob.isEmpty(tid)) { 148212854Sgabeblack@google.com DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 148312854Sgabeblack@google.com end_it = instList.begin(); 148412854Sgabeblack@google.com rob_empty = true; 148512854Sgabeblack@google.com } else { 148612854Sgabeblack@google.com end_it = (rob.readTailInst(tid))->getInstListIt(); 148712854Sgabeblack@google.com DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 148812854Sgabeblack@google.com } 148912854Sgabeblack@google.com 149012854Sgabeblack@google.com removeInstsThisCycle = true; 149112854Sgabeblack@google.com 149212854Sgabeblack@google.com ListIt inst_it = instList.end(); 149312854Sgabeblack@google.com 149412854Sgabeblack@google.com inst_it--; 149512854Sgabeblack@google.com 149612854Sgabeblack@google.com // Walk through the instruction list, removing any instructions 149712854Sgabeblack@google.com // that were inserted after the given instruction iterator, end_it. 149812854Sgabeblack@google.com while (inst_it != end_it) { 149912854Sgabeblack@google.com assert(!instList.empty()); 150012854Sgabeblack@google.com 150112854Sgabeblack@google.com squashInstIt(inst_it, tid); 150212854Sgabeblack@google.com 150312854Sgabeblack@google.com inst_it--; 150412854Sgabeblack@google.com } 150512854Sgabeblack@google.com 150612854Sgabeblack@google.com // If the ROB was empty, then we actually need to remove the first 150712854Sgabeblack@google.com // instruction as well. 150812854Sgabeblack@google.com if (rob_empty) { 150912854Sgabeblack@google.com squashInstIt(inst_it, tid); 151012854Sgabeblack@google.com } 151112854Sgabeblack@google.com} 151212854Sgabeblack@google.com 151312854Sgabeblack@google.comtemplate <class Impl> 151412854Sgabeblack@google.comvoid 151512854Sgabeblack@google.comFullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 151612854Sgabeblack@google.com{ 151712854Sgabeblack@google.com assert(!instList.empty()); 151812854Sgabeblack@google.com 151912854Sgabeblack@google.com removeInstsThisCycle = true; 152012854Sgabeblack@google.com 152112854Sgabeblack@google.com ListIt inst_iter = instList.end(); 152212854Sgabeblack@google.com 152312854Sgabeblack@google.com inst_iter--; 152412854Sgabeblack@google.com 152512854Sgabeblack@google.com DPRINTF(O3CPU, "Deleting instructions from instruction " 152612854Sgabeblack@google.com "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 152712854Sgabeblack@google.com tid, seq_num, (*inst_iter)->seqNum); 152812854Sgabeblack@google.com 152912854Sgabeblack@google.com while ((*inst_iter)->seqNum > seq_num) { 153012854Sgabeblack@google.com 153112854Sgabeblack@google.com bool break_loop = (inst_iter == instList.begin()); 153212854Sgabeblack@google.com 153312854Sgabeblack@google.com squashInstIt(inst_iter, tid); 153412854Sgabeblack@google.com 153512854Sgabeblack@google.com inst_iter--; 153612854Sgabeblack@google.com 153712854Sgabeblack@google.com if (break_loop) 153812854Sgabeblack@google.com break; 153912854Sgabeblack@google.com } 154012854Sgabeblack@google.com} 154112854Sgabeblack@google.com 154212854Sgabeblack@google.comtemplate <class Impl> 154312854Sgabeblack@google.cominline void 154412854Sgabeblack@google.comFullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 154512854Sgabeblack@google.com{ 154612854Sgabeblack@google.com if ((*instIt)->threadNumber == tid) { 154712854Sgabeblack@google.com DPRINTF(O3CPU, "Squashing instruction, " 154812854Sgabeblack@google.com "[tid:%i] [sn:%lli] PC %s\n", 154912854Sgabeblack@google.com (*instIt)->threadNumber, 155012854Sgabeblack@google.com (*instIt)->seqNum, 155112854Sgabeblack@google.com (*instIt)->pcState()); 155212854Sgabeblack@google.com 155312854Sgabeblack@google.com // Mark it as squashed. 155412854Sgabeblack@google.com (*instIt)->setSquashed(); 155512854Sgabeblack@google.com 155612854Sgabeblack@google.com // @todo: Formulate a consistent method for deleting 155712854Sgabeblack@google.com // instructions from the instruction list 155812854Sgabeblack@google.com // Remove the instruction from the list. 155912854Sgabeblack@google.com removeList.push(instIt); 156012854Sgabeblack@google.com } 156112854Sgabeblack@google.com} 156212854Sgabeblack@google.com 156312854Sgabeblack@google.comtemplate <class Impl> 156412854Sgabeblack@google.comvoid 156512854Sgabeblack@google.comFullO3CPU<Impl>::cleanUpRemovedInsts() 156612854Sgabeblack@google.com{ 156712854Sgabeblack@google.com while (!removeList.empty()) { 156812854Sgabeblack@google.com DPRINTF(O3CPU, "Removing instruction, " 156912854Sgabeblack@google.com "[tid:%i] [sn:%lli] PC %s\n", 157012854Sgabeblack@google.com (*removeList.front())->threadNumber, 157112854Sgabeblack@google.com (*removeList.front())->seqNum, 157212854Sgabeblack@google.com (*removeList.front())->pcState()); 157312854Sgabeblack@google.com 157412854Sgabeblack@google.com instList.erase(removeList.front()); 157512854Sgabeblack@google.com 157612854Sgabeblack@google.com removeList.pop(); 157712854Sgabeblack@google.com } 157812854Sgabeblack@google.com 157912854Sgabeblack@google.com removeInstsThisCycle = false; 158012854Sgabeblack@google.com} 158112854Sgabeblack@google.com/* 158212854Sgabeblack@google.comtemplate <class Impl> 158312854Sgabeblack@google.comvoid 158412854Sgabeblack@google.comFullO3CPU<Impl>::removeAllInsts() 158512854Sgabeblack@google.com{ 158612854Sgabeblack@google.com instList.clear(); 158712854Sgabeblack@google.com} 158812854Sgabeblack@google.com*/ 158912854Sgabeblack@google.comtemplate <class Impl> 159012854Sgabeblack@google.comvoid 159112854Sgabeblack@google.comFullO3CPU<Impl>::dumpInsts() 159212854Sgabeblack@google.com{ 159312854Sgabeblack@google.com int num = 0; 159412854Sgabeblack@google.com 159512854Sgabeblack@google.com ListIt inst_list_it = instList.begin(); 159612854Sgabeblack@google.com 159712854Sgabeblack@google.com cprintf("Dumping Instruction List\n"); 159812854Sgabeblack@google.com 159912854Sgabeblack@google.com while (inst_list_it != instList.end()) { 160012854Sgabeblack@google.com cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 160112854Sgabeblack@google.com "Squashed:%i\n\n", 160212854Sgabeblack@google.com num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 160312854Sgabeblack@google.com (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 160412854Sgabeblack@google.com (*inst_list_it)->isSquashed()); 160512854Sgabeblack@google.com inst_list_it++; 160612854Sgabeblack@google.com ++num; 160712854Sgabeblack@google.com } 160812854Sgabeblack@google.com} 160912854Sgabeblack@google.com/* 161012854Sgabeblack@google.comtemplate <class Impl> 161112854Sgabeblack@google.comvoid 161212854Sgabeblack@google.comFullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 161312854Sgabeblack@google.com{ 161412854Sgabeblack@google.com iew.wakeDependents(inst); 161512854Sgabeblack@google.com} 161612854Sgabeblack@google.com*/ 161712854Sgabeblack@google.comtemplate <class Impl> 161812854Sgabeblack@google.comvoid 161912854Sgabeblack@google.comFullO3CPU<Impl>::wakeCPU() 162012854Sgabeblack@google.com{ 162112854Sgabeblack@google.com if (activityRec.active() || tickEvent.scheduled()) { 162212854Sgabeblack@google.com DPRINTF(Activity, "CPU already running.\n"); 162312854Sgabeblack@google.com return; 162412854Sgabeblack@google.com } 162512854Sgabeblack@google.com 162612854Sgabeblack@google.com DPRINTF(Activity, "Waking up CPU\n"); 162712854Sgabeblack@google.com 162812854Sgabeblack@google.com Cycles cycles(curCycle() - lastRunningCycle); 162912854Sgabeblack@google.com // @todo: This is an oddity that is only here to match the stats 163012854Sgabeblack@google.com if (cycles > 1) { 163112854Sgabeblack@google.com --cycles; 163212854Sgabeblack@google.com idleCycles += cycles; 163312854Sgabeblack@google.com numCycles += cycles; 163412854Sgabeblack@google.com ppCycles->notify(cycles); 163512854Sgabeblack@google.com } 163612854Sgabeblack@google.com 163712854Sgabeblack@google.com schedule(tickEvent, clockEdge()); 163812854Sgabeblack@google.com} 163912854Sgabeblack@google.com 164012854Sgabeblack@google.comtemplate <class Impl> 164112854Sgabeblack@google.comvoid 164212854Sgabeblack@google.comFullO3CPU<Impl>::wakeup(ThreadID tid) 164312854Sgabeblack@google.com{ 164412854Sgabeblack@google.com if (this->thread[tid]->status() != ThreadContext::Suspended) 164512854Sgabeblack@google.com return; 164612854Sgabeblack@google.com 164712854Sgabeblack@google.com this->wakeCPU(); 164812854Sgabeblack@google.com 164912854Sgabeblack@google.com DPRINTF(Quiesce, "Suspended Processor woken\n"); 165012854Sgabeblack@google.com this->threadContexts[tid]->activate(); 165112854Sgabeblack@google.com} 165212854Sgabeblack@google.com 165312854Sgabeblack@google.comtemplate <class Impl> 165412854Sgabeblack@google.comThreadID 165512854Sgabeblack@google.comFullO3CPU<Impl>::getFreeTid() 165612854Sgabeblack@google.com{ 165712854Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; tid++) { 165812854Sgabeblack@google.com if (!tids[tid]) { 165912854Sgabeblack@google.com tids[tid] = true; 166012854Sgabeblack@google.com return tid; 166112854Sgabeblack@google.com } 166212854Sgabeblack@google.com } 166312854Sgabeblack@google.com 166412854Sgabeblack@google.com return InvalidThreadID; 166512854Sgabeblack@google.com} 166612854Sgabeblack@google.com 166712854Sgabeblack@google.comtemplate <class Impl> 166812854Sgabeblack@google.comvoid 166912854Sgabeblack@google.comFullO3CPU<Impl>::updateThreadPriority() 167012854Sgabeblack@google.com{ 167112854Sgabeblack@google.com if (activeThreads.size() > 1) { 167212854Sgabeblack@google.com //DEFAULT TO ROUND ROBIN SCHEME 167312854Sgabeblack@google.com //e.g. Move highest priority to end of thread list 167412854Sgabeblack@google.com list<ThreadID>::iterator list_begin = activeThreads.begin(); 167512854Sgabeblack@google.com 167612854Sgabeblack@google.com unsigned high_thread = *list_begin; 167712854Sgabeblack@google.com 167812854Sgabeblack@google.com activeThreads.erase(list_begin); 167912854Sgabeblack@google.com 168012854Sgabeblack@google.com activeThreads.push_back(high_thread); 168112854Sgabeblack@google.com } 168212854Sgabeblack@google.com} 168312854Sgabeblack@google.com 168412854Sgabeblack@google.com// Forward declaration of FullO3CPU. 168512854Sgabeblack@google.comtemplate class FullO3CPU<O3CPUImpl>; 168612854Sgabeblack@google.com