cpu.cc revision 10023
1955SN/A/* 2955SN/A * Copyright (c) 2011-2012 ARM Limited 35871Snate@binkert.org * Copyright (c) 2013 Advanced Micro Devices, Inc. 41762SN/A * All rights reserved 5955SN/A * 6955SN/A * The license below extends only to copyright in the software and shall 7955SN/A * not be construed as granting a license to any other intellectual 8955SN/A * property including but not limited to intellectual property relating 9955SN/A * to a hardware implementation of the functionality of the software 10955SN/A * licensed hereunder. You may use the software subject to the license 11955SN/A * terms below provided that you ensure that this notice is replicated 12955SN/A * unmodified and in its entirety in all distributions of the software, 13955SN/A * modified or unmodified, in source code or in binary form. 14955SN/A * 15955SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 16955SN/A * Copyright (c) 2011 Regents of the University of California 17955SN/A * All rights reserved. 18955SN/A * 19955SN/A * Redistribution and use in source and binary forms, with or without 20955SN/A * modification, are permitted provided that the following conditions are 21955SN/A * met: redistributions of source code must retain the above copyright 22955SN/A * notice, this list of conditions and the following disclaimer; 23955SN/A * redistributions in binary form must reproduce the above copyright 24955SN/A * notice, this list of conditions and the following disclaimer in the 25955SN/A * documentation and/or other materials provided with the distribution; 26955SN/A * neither the name of the copyright holders nor the names of its 27955SN/A * contributors may be used to endorse or promote products derived from 28955SN/A * this software without specific prior written permission. 292665Ssaidi@eecs.umich.edu * 302665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 315863Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 33955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 34955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 36955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 372632Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 382632Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 392632Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 402632Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41955SN/A * 422632Sstever@eecs.umich.edu * Authors: Kevin Lim 432632Sstever@eecs.umich.edu * Korey Sewell 442761Sstever@eecs.umich.edu * Rick Strong 452632Sstever@eecs.umich.edu */ 462632Sstever@eecs.umich.edu 472632Sstever@eecs.umich.edu#include "arch/kernel_stats.hh" 482761Sstever@eecs.umich.edu#include "config/the_isa.hh" 492761Sstever@eecs.umich.edu#include "cpu/checker/cpu.hh" 502761Sstever@eecs.umich.edu#include "cpu/checker/thread_context.hh" 512632Sstever@eecs.umich.edu#include "cpu/o3/cpu.hh" 522632Sstever@eecs.umich.edu#include "cpu/o3/isa_specific.hh" 532761Sstever@eecs.umich.edu#include "cpu/o3/thread_context.hh" 542761Sstever@eecs.umich.edu#include "cpu/activity.hh" 552761Sstever@eecs.umich.edu#include "cpu/quiesce_event.hh" 562761Sstever@eecs.umich.edu#include "cpu/simple_thread.hh" 572761Sstever@eecs.umich.edu#include "cpu/thread_context.hh" 582632Sstever@eecs.umich.edu#include "debug/Activity.hh" 592632Sstever@eecs.umich.edu#include "debug/Drain.hh" 602632Sstever@eecs.umich.edu#include "debug/O3CPU.hh" 612632Sstever@eecs.umich.edu#include "debug/Quiesce.hh" 622632Sstever@eecs.umich.edu#include "enums/MemoryMode.hh" 632632Sstever@eecs.umich.edu#include "sim/core.hh" 642632Sstever@eecs.umich.edu#include "sim/full_system.hh" 65955SN/A#include "sim/process.hh" 66955SN/A#include "sim/stat_control.hh" 67955SN/A#include "sim/system.hh" 685863Snate@binkert.org 695863Snate@binkert.org#if THE_ISA == ALPHA_ISA 705863Snate@binkert.org#include "arch/alpha/osfpal.hh" 715863Snate@binkert.org#include "debug/Activity.hh" 725863Snate@binkert.org#endif 735863Snate@binkert.org 745863Snate@binkert.orgstruct BaseCPUParams; 755863Snate@binkert.org 765863Snate@binkert.orgusing namespace TheISA; 775863Snate@binkert.orgusing namespace std; 785863Snate@binkert.org 795863Snate@binkert.orgBaseO3CPU::BaseO3CPU(BaseCPUParams *params) 805863Snate@binkert.org : BaseCPU(params) 815863Snate@binkert.org{ 825863Snate@binkert.org} 835863Snate@binkert.org 845863Snate@binkert.orgvoid 855863Snate@binkert.orgBaseO3CPU::regStats() 865863Snate@binkert.org{ 875863Snate@binkert.org BaseCPU::regStats(); 885863Snate@binkert.org} 895863Snate@binkert.org 905863Snate@binkert.orgtemplate<class Impl> 915863Snate@binkert.orgbool 925863Snate@binkert.orgFullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 935863Snate@binkert.org{ 945863Snate@binkert.org DPRINTF(O3CPU, "Fetch unit received timing\n"); 955863Snate@binkert.org // We shouldn't ever get a block in ownership state 965863Snate@binkert.org assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); 975863Snate@binkert.org fetch->processCacheCompletion(pkt); 985863Snate@binkert.org 99955SN/A return true; 1005396Ssaidi@eecs.umich.edu} 1015863Snate@binkert.org 1025863Snate@binkert.orgtemplate<class Impl> 1034202Sbinkertn@umich.eduvoid 1045863Snate@binkert.orgFullO3CPU<Impl>::IcachePort::recvRetry() 1055863Snate@binkert.org{ 1065863Snate@binkert.org fetch->recvRetry(); 1075863Snate@binkert.org} 108955SN/A 1095273Sstever@gmail.comtemplate <class Impl> 1105871Snate@binkert.orgbool 1115273Sstever@gmail.comFullO3CPU<Impl>::DcachePort::recvTimingResp(PacketPtr pkt) 1125871Snate@binkert.org{ 1135863Snate@binkert.org return lsq->recvTimingResp(pkt); 1145863Snate@binkert.org} 1155863Snate@binkert.org 1165871Snate@binkert.orgtemplate <class Impl> 1175871Snate@binkert.orgvoid 1185871Snate@binkert.orgFullO3CPU<Impl>::DcachePort::recvTimingSnoopReq(PacketPtr pkt) 1195871Snate@binkert.org{ 1205871Snate@binkert.org lsq->recvTimingSnoopReq(pkt); 1215871Snate@binkert.org} 1225871Snate@binkert.org 1235871Snate@binkert.orgtemplate <class Impl> 1245871Snate@binkert.orgvoid 1255871Snate@binkert.orgFullO3CPU<Impl>::DcachePort::recvRetry() 1265871Snate@binkert.org{ 1275871Snate@binkert.org lsq->recvRetry(); 1285871Snate@binkert.org} 1295871Snate@binkert.org 1305871Snate@binkert.orgtemplate <class Impl> 1315863Snate@binkert.orgFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 1325227Ssaidi@eecs.umich.edu : Event(CPU_Tick_Pri), cpu(c) 1335396Ssaidi@eecs.umich.edu{ 1345396Ssaidi@eecs.umich.edu} 1355396Ssaidi@eecs.umich.edu 1365396Ssaidi@eecs.umich.edutemplate <class Impl> 1375396Ssaidi@eecs.umich.eduvoid 1385396Ssaidi@eecs.umich.eduFullO3CPU<Impl>::TickEvent::process() 1395396Ssaidi@eecs.umich.edu{ 1405396Ssaidi@eecs.umich.edu cpu->tick(); 1415588Ssaidi@eecs.umich.edu} 1425396Ssaidi@eecs.umich.edu 1435396Ssaidi@eecs.umich.edutemplate <class Impl> 1445396Ssaidi@eecs.umich.educonst char * 1455396Ssaidi@eecs.umich.eduFullO3CPU<Impl>::TickEvent::description() const 1465396Ssaidi@eecs.umich.edu{ 1475396Ssaidi@eecs.umich.edu return "FullO3CPU tick"; 1485396Ssaidi@eecs.umich.edu} 1495396Ssaidi@eecs.umich.edu 1505396Ssaidi@eecs.umich.edutemplate <class Impl> 1515396Ssaidi@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 1525396Ssaidi@eecs.umich.edu : Event(CPU_Switch_Pri) 1535396Ssaidi@eecs.umich.edu{ 1545396Ssaidi@eecs.umich.edu} 1555396Ssaidi@eecs.umich.edu 1565871Snate@binkert.orgtemplate <class Impl> 1575871Snate@binkert.orgvoid 1585871Snate@binkert.orgFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 1595871Snate@binkert.org FullO3CPU<Impl> *thread_cpu) 1605871Snate@binkert.org{ 1615871Snate@binkert.org tid = thread_num; 162955SN/A cpu = thread_cpu; 1635871Snate@binkert.org} 1645871Snate@binkert.org 1655871Snate@binkert.orgtemplate <class Impl> 1665871Snate@binkert.orgvoid 167955SN/AFullO3CPU<Impl>::ActivateThreadEvent::process() 1685871Snate@binkert.org{ 1695871Snate@binkert.org cpu->activateThread(tid); 1705871Snate@binkert.org} 1711533SN/A 1725871Snate@binkert.orgtemplate <class Impl> 1735871Snate@binkert.orgconst char * 1745863Snate@binkert.orgFullO3CPU<Impl>::ActivateThreadEvent::description() const 1755871Snate@binkert.org{ 1765871Snate@binkert.org return "FullO3CPU \"Activate Thread\""; 1775871Snate@binkert.org} 1785871Snate@binkert.org 1795871Snate@binkert.orgtemplate <class Impl> 1805863Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1815871Snate@binkert.org : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 1825863Snate@binkert.org{ 1835871Snate@binkert.org} 1844678Snate@binkert.org 1854678Snate@binkert.orgtemplate <class Impl> 1864678Snate@binkert.orgvoid 1874678Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1884678Snate@binkert.org FullO3CPU<Impl> *thread_cpu) 1894678Snate@binkert.org{ 1904678Snate@binkert.org tid = thread_num; 1914678Snate@binkert.org cpu = thread_cpu; 1924678Snate@binkert.org remove = false; 1934678Snate@binkert.org} 1944678Snate@binkert.org 1954678Snate@binkert.orgtemplate <class Impl> 1965871Snate@binkert.orgvoid 1974678Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::process() 1985871Snate@binkert.org{ 1995871Snate@binkert.org cpu->deactivateThread(tid); 2005871Snate@binkert.org if (remove) 2015871Snate@binkert.org cpu->removeThread(tid); 2025871Snate@binkert.org} 2035871Snate@binkert.org 2045871Snate@binkert.orgtemplate <class Impl> 2055871Snate@binkert.orgconst char * 2065871Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::description() const 2075871Snate@binkert.org{ 2085871Snate@binkert.org return "FullO3CPU \"Deallocate Context\""; 2095871Snate@binkert.org} 2105871Snate@binkert.org 2115871Snate@binkert.orgtemplate <class Impl> 2125871Snate@binkert.orgFullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) 2135871Snate@binkert.org : BaseO3CPU(params), 2144678Snate@binkert.org itb(params->itb), 2155871Snate@binkert.org dtb(params->dtb), 2165871Snate@binkert.org tickEvent(this), 2175871Snate@binkert.org#ifndef NDEBUG 2185871Snate@binkert.org instcount(0), 2195871Snate@binkert.org#endif 2205871Snate@binkert.org removeInstsThisCycle(false), 2215871Snate@binkert.org fetch(this, params), 2225871Snate@binkert.org decode(this, params), 2235871Snate@binkert.org rename(this, params), 2245871Snate@binkert.org iew(this, params), 2255871Snate@binkert.org commit(this, params), 2265871Snate@binkert.org 2275871Snate@binkert.org regFile(params->numPhysIntRegs, 2284678Snate@binkert.org params->numPhysFloatRegs, 2295871Snate@binkert.org params->numPhysCCRegs), 2304678Snate@binkert.org 2315871Snate@binkert.org freeList(name() + ".freelist", ®File), 2325871Snate@binkert.org 2335871Snate@binkert.org rob(this, params), 2345871Snate@binkert.org 2355871Snate@binkert.org scoreboard(name() + ".scoreboard", 2365871Snate@binkert.org regFile.totalNumPhysRegs(), TheISA::NumMiscRegs, 2375871Snate@binkert.org TheISA::ZeroReg, TheISA::ZeroReg), 2385871Snate@binkert.org 2395871Snate@binkert.org isa(numThreads, NULL), 2405863Snate@binkert.org 241955SN/A icachePort(&fetch, this), 242955SN/A dcachePort(&iew.ldstQueue, this), 2432632Sstever@eecs.umich.edu 2442632Sstever@eecs.umich.edu timeBuffer(params->backComSize, params->forwardComSize), 245955SN/A fetchQueue(params->backComSize, params->forwardComSize), 246955SN/A decodeQueue(params->backComSize, params->forwardComSize), 247955SN/A renameQueue(params->backComSize, params->forwardComSize), 248955SN/A iewQueue(params->backComSize, params->forwardComSize), 2495863Snate@binkert.org activityRec(name(), NumStages, 250955SN/A params->backComSize + params->forwardComSize, 2512632Sstever@eecs.umich.edu params->activity), 2522632Sstever@eecs.umich.edu 2532632Sstever@eecs.umich.edu globalSeqNum(1), 2542632Sstever@eecs.umich.edu system(params->system), 2552632Sstever@eecs.umich.edu drainManager(NULL), 2562632Sstever@eecs.umich.edu lastRunningCycle(curCycle()) 2572632Sstever@eecs.umich.edu{ 2582632Sstever@eecs.umich.edu if (!params->switched_out) { 2592632Sstever@eecs.umich.edu _status = Running; 2602632Sstever@eecs.umich.edu } else { 2612632Sstever@eecs.umich.edu _status = SwitchedOut; 2622632Sstever@eecs.umich.edu } 2632632Sstever@eecs.umich.edu 2643718Sstever@eecs.umich.edu if (params->checker) { 2653718Sstever@eecs.umich.edu BaseCPU *temp_checker = params->checker; 2663718Sstever@eecs.umich.edu checker = dynamic_cast<Checker<Impl> *>(temp_checker); 2673718Sstever@eecs.umich.edu checker->setIcachePort(&icachePort); 2683718Sstever@eecs.umich.edu checker->setSystem(params->system); 2695863Snate@binkert.org } else { 2705863Snate@binkert.org checker = NULL; 2713718Sstever@eecs.umich.edu } 2723718Sstever@eecs.umich.edu 2735863Snate@binkert.org if (!FullSystem) { 2745863Snate@binkert.org thread.resize(numThreads); 2753718Sstever@eecs.umich.edu tids.resize(numThreads); 2763718Sstever@eecs.umich.edu } 2772634Sstever@eecs.umich.edu 2782634Sstever@eecs.umich.edu // The stages also need their CPU pointer setup. However this 2795863Snate@binkert.org // must be done at the upper level CPU because they have pointers 2802638Sstever@eecs.umich.edu // to the upper level CPU, and not this FullO3CPU. 2812632Sstever@eecs.umich.edu 2822632Sstever@eecs.umich.edu // Set up Pointers to the activeThreads list for each stage 2832632Sstever@eecs.umich.edu fetch.setActiveThreads(&activeThreads); 2842632Sstever@eecs.umich.edu decode.setActiveThreads(&activeThreads); 2852632Sstever@eecs.umich.edu rename.setActiveThreads(&activeThreads); 2862632Sstever@eecs.umich.edu iew.setActiveThreads(&activeThreads); 2871858SN/A commit.setActiveThreads(&activeThreads); 2883716Sstever@eecs.umich.edu 2892638Sstever@eecs.umich.edu // Give each of the stages the time buffer they will use. 2902638Sstever@eecs.umich.edu fetch.setTimeBuffer(&timeBuffer); 2912638Sstever@eecs.umich.edu decode.setTimeBuffer(&timeBuffer); 2922638Sstever@eecs.umich.edu rename.setTimeBuffer(&timeBuffer); 2932638Sstever@eecs.umich.edu iew.setTimeBuffer(&timeBuffer); 2942638Sstever@eecs.umich.edu commit.setTimeBuffer(&timeBuffer); 2952638Sstever@eecs.umich.edu 2965863Snate@binkert.org // Also setup each of the stages' queues. 2975863Snate@binkert.org fetch.setFetchQueue(&fetchQueue); 2985863Snate@binkert.org decode.setFetchQueue(&fetchQueue); 299955SN/A commit.setFetchQueue(&fetchQueue); 3005341Sstever@gmail.com decode.setDecodeQueue(&decodeQueue); 3015341Sstever@gmail.com rename.setDecodeQueue(&decodeQueue); 3025863Snate@binkert.org rename.setRenameQueue(&renameQueue); 3035341Sstever@gmail.com iew.setRenameQueue(&renameQueue); 3044494Ssaidi@eecs.umich.edu iew.setIEWQueue(&iewQueue); 3054494Ssaidi@eecs.umich.edu commit.setIEWQueue(&iewQueue); 3065863Snate@binkert.org commit.setRenameQueue(&renameQueue); 3071105SN/A 3082667Sstever@eecs.umich.edu commit.setIEWStage(&iew); 3092667Sstever@eecs.umich.edu rename.setIEWStage(&iew); 3102667Sstever@eecs.umich.edu rename.setCommitStage(&commit); 3112667Sstever@eecs.umich.edu 3122667Sstever@eecs.umich.edu ThreadID active_threads; 3132667Sstever@eecs.umich.edu if (FullSystem) { 3145341Sstever@gmail.com active_threads = 1; 3155863Snate@binkert.org } else { 3165341Sstever@gmail.com active_threads = params->workload.size(); 3175341Sstever@gmail.com 3185341Sstever@gmail.com if (active_threads > Impl::MaxThreads) { 3195863Snate@binkert.org panic("Workload Size too large. Increase the 'MaxThreads' " 3205341Sstever@gmail.com "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) " 3215341Sstever@gmail.com "or edit your workload size."); 3225341Sstever@gmail.com } 3235863Snate@binkert.org } 3245341Sstever@gmail.com 3255341Sstever@gmail.com //Make Sure That this a Valid Architeture 3265341Sstever@gmail.com assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 3275341Sstever@gmail.com assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 3285341Sstever@gmail.com assert(params->numPhysCCRegs >= numThreads * TheISA::NumCCRegs); 3295341Sstever@gmail.com 3305341Sstever@gmail.com rename.setScoreboard(&scoreboard); 3315341Sstever@gmail.com iew.setScoreboard(&scoreboard); 3325341Sstever@gmail.com 3335341Sstever@gmail.com // Setup the rename map for whichever stages need it. 3345863Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 3355341Sstever@gmail.com isa[tid] = params->isa[tid]; 3365863Snate@binkert.org 3375341Sstever@gmail.com // Only Alpha has an FP zero register, so for other ISAs we 3385863Snate@binkert.org // use an invalid FP register index to avoid special treatment 3395863Snate@binkert.org // of any valid FP reg. 3405863Snate@binkert.org RegIndex invalidFPReg = TheISA::NumFloatRegs + 1; 3415397Ssaidi@eecs.umich.edu RegIndex fpZeroReg = 3425397Ssaidi@eecs.umich.edu (THE_ISA == ALPHA_ISA) ? TheISA::ZeroReg : invalidFPReg; 3435341Sstever@gmail.com 3445341Sstever@gmail.com commitRenameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 3455341Sstever@gmail.com &freeList); 3465341Sstever@gmail.com 3475341Sstever@gmail.com renameMap[tid].init(®File, TheISA::ZeroReg, fpZeroReg, 3485341Sstever@gmail.com &freeList); 3495341Sstever@gmail.com 3505341Sstever@gmail.com activateThreadEvent[tid].init(tid, this); 3515863Snate@binkert.org deallocateContextEvent[tid].init(tid, this); 3525341Sstever@gmail.com } 3535341Sstever@gmail.com 3545863Snate@binkert.org // Initialize rename map to assign physical registers to the 3555341Sstever@gmail.com // architectural registers for active threads only. 3565863Snate@binkert.org for (ThreadID tid = 0; tid < active_threads; tid++) { 3575863Snate@binkert.org for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) { 3585341Sstever@gmail.com // Note that we can't use the rename() method because we don't 3595863Snate@binkert.org // want special treatment for the zero register at this point 3605863Snate@binkert.org PhysRegIndex phys_reg = freeList.getIntReg(); 3615341Sstever@gmail.com renameMap[tid].setIntEntry(ridx, phys_reg); 3625863Snate@binkert.org commitRenameMap[tid].setIntEntry(ridx, phys_reg); 3635341Sstever@gmail.com } 3645871Snate@binkert.org 3655341Sstever@gmail.com for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) { 3665742Snate@binkert.org PhysRegIndex phys_reg = freeList.getFloatReg(); 3675742Snate@binkert.org renameMap[tid].setFloatEntry(ridx, phys_reg); 3685742Snate@binkert.org commitRenameMap[tid].setFloatEntry(ridx, phys_reg); 3695341Sstever@gmail.com } 3705742Snate@binkert.org 3715742Snate@binkert.org for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) { 3725341Sstever@gmail.com PhysRegIndex phys_reg = freeList.getCCReg(); 3732632Sstever@eecs.umich.edu renameMap[tid].setCCEntry(ridx, phys_reg); 3745199Sstever@gmail.com commitRenameMap[tid].setCCEntry(ridx, phys_reg); 3755871Snate@binkert.org } 3765871Snate@binkert.org } 3775871Snate@binkert.org 3785871Snate@binkert.org rename.setRenameMap(renameMap); 3795871Snate@binkert.org commit.setRenameMap(commitRenameMap); 3805871Snate@binkert.org rename.setFreeList(&freeList); 3815871Snate@binkert.org 3823942Ssaidi@eecs.umich.edu // Setup the ROB for whichever stages need it. 3833940Ssaidi@eecs.umich.edu commit.setROB(&rob); 3843918Ssaidi@eecs.umich.edu 3853918Ssaidi@eecs.umich.edu lastActivatedCycle = 0; 3861858SN/A#if 0 3873918Ssaidi@eecs.umich.edu // Give renameMap & rename stage access to the freeList; 3883918Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 3893918Ssaidi@eecs.umich.edu globalSeqNum[tid] = 1; 3903918Ssaidi@eecs.umich.edu#endif 3915571Snate@binkert.org 3923940Ssaidi@eecs.umich.edu contextSwitch = false; 3933940Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Creating O3CPU object.\n"); 3943918Ssaidi@eecs.umich.edu 3953918Ssaidi@eecs.umich.edu // Setup any thread state. 3963918Ssaidi@eecs.umich.edu this->thread.resize(this->numThreads); 3973918Ssaidi@eecs.umich.edu 3983918Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < this->numThreads; ++tid) { 3993918Ssaidi@eecs.umich.edu if (FullSystem) { 4005871Snate@binkert.org // SMT is not supported in FS mode yet. 4013918Ssaidi@eecs.umich.edu assert(this->numThreads == 1); 4023918Ssaidi@eecs.umich.edu this->thread[tid] = new Thread(this, 0, NULL); 4033940Ssaidi@eecs.umich.edu } else { 4043918Ssaidi@eecs.umich.edu if (tid < params->workload.size()) { 4053918Ssaidi@eecs.umich.edu DPRINTF(O3CPU, "Workload[%i] process is %#x", 4065397Ssaidi@eecs.umich.edu tid, this->thread[tid]); 4075397Ssaidi@eecs.umich.edu this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 4085397Ssaidi@eecs.umich.edu (typename Impl::O3CPU *)(this), 4095708Ssaidi@eecs.umich.edu tid, params->workload[tid]); 4105708Ssaidi@eecs.umich.edu 4115708Ssaidi@eecs.umich.edu //usedTids[tid] = true; 4125708Ssaidi@eecs.umich.edu //threadMap[tid] = tid; 4135708Ssaidi@eecs.umich.edu } else { 4145397Ssaidi@eecs.umich.edu //Allocate Empty thread so M5 can use later 4151851SN/A //when scheduling threads to CPU 4161851SN/A Process* dummy_proc = NULL; 4171858SN/A 4185200Sstever@gmail.com this->thread[tid] = new typename FullO3CPU<Impl>::Thread( 419955SN/A (typename Impl::O3CPU *)(this), 4203053Sstever@eecs.umich.edu tid, dummy_proc); 4213053Sstever@eecs.umich.edu //usedTids[tid] = false; 4223053Sstever@eecs.umich.edu } 4233053Sstever@eecs.umich.edu } 4243053Sstever@eecs.umich.edu 4253053Sstever@eecs.umich.edu ThreadContext *tc; 4263053Sstever@eecs.umich.edu 4275871Snate@binkert.org // Setup the TC that will serve as the interface to the threads/CPU. 4283053Sstever@eecs.umich.edu O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>; 4294742Sstever@eecs.umich.edu 4304742Sstever@eecs.umich.edu tc = o3_tc; 4313053Sstever@eecs.umich.edu 4323053Sstever@eecs.umich.edu // If we're using a checker, then the TC should be the 4333053Sstever@eecs.umich.edu // CheckerThreadContext. 4343053Sstever@eecs.umich.edu if (params->checker) { 4353053Sstever@eecs.umich.edu tc = new CheckerThreadContext<O3ThreadContext<Impl> >( 4363053Sstever@eecs.umich.edu o3_tc, this->checker); 4373053Sstever@eecs.umich.edu } 4383053Sstever@eecs.umich.edu 4393053Sstever@eecs.umich.edu o3_tc->cpu = (typename Impl::O3CPU *)(this); 4402667Sstever@eecs.umich.edu assert(o3_tc->cpu); 4414554Sbinkertn@umich.edu o3_tc->thread = this->thread[tid]; 4424554Sbinkertn@umich.edu 4432667Sstever@eecs.umich.edu if (FullSystem) { 4444554Sbinkertn@umich.edu // Setup quiesce event. 4454554Sbinkertn@umich.edu this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); 4464554Sbinkertn@umich.edu } 4474554Sbinkertn@umich.edu // Give the thread the TC. 4484554Sbinkertn@umich.edu this->thread[tid]->tc = tc; 4494554Sbinkertn@umich.edu 4504554Sbinkertn@umich.edu // Add the TC to the CPU's list of TC's. 4514781Snate@binkert.org this->threadContexts.push_back(tc); 4524554Sbinkertn@umich.edu } 4534554Sbinkertn@umich.edu 4542667Sstever@eecs.umich.edu // FullO3CPU always requires an interrupt controller. 4554554Sbinkertn@umich.edu if (!params->switched_out && !interrupts) { 4564554Sbinkertn@umich.edu fatal("FullO3CPU %s has no interrupt controller.\n" 4574554Sbinkertn@umich.edu "Ensure createInterruptController() is called.\n", name()); 4584554Sbinkertn@umich.edu } 4592667Sstever@eecs.umich.edu 4604554Sbinkertn@umich.edu for (ThreadID tid = 0; tid < this->numThreads; tid++) 4612667Sstever@eecs.umich.edu this->thread[tid]->setFuncExeInst(0); 4624554Sbinkertn@umich.edu} 4634554Sbinkertn@umich.edu 4642667Sstever@eecs.umich.edutemplate <class Impl> 4655522Snate@binkert.orgFullO3CPU<Impl>::~FullO3CPU() 4665522Snate@binkert.org{ 4675522Snate@binkert.org} 4685522Snate@binkert.org 4695522Snate@binkert.orgtemplate <class Impl> 4705522Snate@binkert.orgvoid 4715522Snate@binkert.orgFullO3CPU<Impl>::regProbePoints() 4725522Snate@binkert.org{ 4735522Snate@binkert.org ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete"); 4745522Snate@binkert.org ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete"); 4755522Snate@binkert.org fetch.regProbePoints(); 4765522Snate@binkert.org iew.regProbePoints(); 4775522Snate@binkert.org commit.regProbePoints(); 4785522Snate@binkert.org} 4795522Snate@binkert.org 4805522Snate@binkert.orgtemplate <class Impl> 4815522Snate@binkert.orgvoid 4825522Snate@binkert.orgFullO3CPU<Impl>::regStats() 4835522Snate@binkert.org{ 4845522Snate@binkert.org BaseO3CPU::regStats(); 4855522Snate@binkert.org 4865522Snate@binkert.org // Register any of the O3CPU's stats here. 4875522Snate@binkert.org timesIdled 4885522Snate@binkert.org .name(name() + ".timesIdled") 4895522Snate@binkert.org .desc("Number of times that the entire CPU went into an idle state and" 4905522Snate@binkert.org " unscheduled itself") 4912638Sstever@eecs.umich.edu .prereq(timesIdled); 4922638Sstever@eecs.umich.edu 4932638Sstever@eecs.umich.edu idleCycles 4943716Sstever@eecs.umich.edu .name(name() + ".idleCycles") 4955522Snate@binkert.org .desc("Total number of cycles that the CPU has spent unscheduled due " 4965522Snate@binkert.org "to idling") 4975522Snate@binkert.org .prereq(idleCycles); 4985522Snate@binkert.org 4995522Snate@binkert.org quiesceCycles 5005522Snate@binkert.org .name(name() + ".quiesceCycles") 5011858SN/A .desc("Total number of cycles that CPU has spent quiesced or waiting " 5025227Ssaidi@eecs.umich.edu "for an interrupt") 5035227Ssaidi@eecs.umich.edu .prereq(quiesceCycles); 5045227Ssaidi@eecs.umich.edu 5055227Ssaidi@eecs.umich.edu // Number of Instructions simulated 5065227Ssaidi@eecs.umich.edu // -------------------------------- 5075863Snate@binkert.org // Should probably be in Base CPU but need templated 5085227Ssaidi@eecs.umich.edu // MaxThreads so put in here instead 5095227Ssaidi@eecs.umich.edu committedInsts 5105227Ssaidi@eecs.umich.edu .init(numThreads) 5115227Ssaidi@eecs.umich.edu .name(name() + ".committedInsts") 5125227Ssaidi@eecs.umich.edu .desc("Number of Instructions Simulated"); 5135227Ssaidi@eecs.umich.edu 5145227Ssaidi@eecs.umich.edu committedOps 5155204Sstever@gmail.com .init(numThreads) 5165204Sstever@gmail.com .name(name() + ".committedOps") 5175204Sstever@gmail.com .desc("Number of Ops (including micro ops) Simulated"); 5185204Sstever@gmail.com 5195204Sstever@gmail.com totalCommittedInsts 5205204Sstever@gmail.com .name(name() + ".committedInsts_total") 5215204Sstever@gmail.com .desc("Number of Instructions Simulated"); 5225204Sstever@gmail.com 5235204Sstever@gmail.com cpi 5245204Sstever@gmail.com .name(name() + ".cpi") 5255204Sstever@gmail.com .desc("CPI: Cycles Per Instruction") 5265204Sstever@gmail.com .precision(6); 5275204Sstever@gmail.com cpi = numCycles / committedInsts; 5285204Sstever@gmail.com 5295204Sstever@gmail.com totalCpi 5305204Sstever@gmail.com .name(name() + ".cpi_total") 5315204Sstever@gmail.com .desc("CPI: Total CPI of All Threads") 5325204Sstever@gmail.com .precision(6); 5335204Sstever@gmail.com totalCpi = numCycles / totalCommittedInsts; 5343118Sstever@eecs.umich.edu 5353118Sstever@eecs.umich.edu ipc 5363118Sstever@eecs.umich.edu .name(name() + ".ipc") 5373118Sstever@eecs.umich.edu .desc("IPC: Instructions Per Cycle") 5383118Sstever@eecs.umich.edu .precision(6); 5395863Snate@binkert.org ipc = committedInsts / numCycles; 5403118Sstever@eecs.umich.edu 5415863Snate@binkert.org totalIpc 5423118Sstever@eecs.umich.edu .name(name() + ".ipc_total") 5435863Snate@binkert.org .desc("IPC: Total IPC of All Threads") 5445863Snate@binkert.org .precision(6); 5455863Snate@binkert.org totalIpc = totalCommittedInsts / numCycles; 5465863Snate@binkert.org 5475863Snate@binkert.org this->fetch.regStats(); 5485863Snate@binkert.org this->decode.regStats(); 5495863Snate@binkert.org this->rename.regStats(); 5505863Snate@binkert.org this->iew.regStats(); 5515863Snate@binkert.org this->commit.regStats(); 5525863Snate@binkert.org this->rob.regStats(); 5535863Snate@binkert.org 5545863Snate@binkert.org intRegfileReads 5555863Snate@binkert.org .name(name() + ".int_regfile_reads") 5565863Snate@binkert.org .desc("number of integer regfile reads") 5575863Snate@binkert.org .prereq(intRegfileReads); 5585863Snate@binkert.org 5595863Snate@binkert.org intRegfileWrites 5605863Snate@binkert.org .name(name() + ".int_regfile_writes") 5615863Snate@binkert.org .desc("number of integer regfile writes") 5625863Snate@binkert.org .prereq(intRegfileWrites); 5635863Snate@binkert.org 5645863Snate@binkert.org fpRegfileReads 5655863Snate@binkert.org .name(name() + ".fp_regfile_reads") 5665863Snate@binkert.org .desc("number of floating regfile reads") 5675863Snate@binkert.org .prereq(fpRegfileReads); 5683118Sstever@eecs.umich.edu 5695863Snate@binkert.org fpRegfileWrites 5703118Sstever@eecs.umich.edu .name(name() + ".fp_regfile_writes") 5713118Sstever@eecs.umich.edu .desc("number of floating regfile writes") 5725863Snate@binkert.org .prereq(fpRegfileWrites); 5735863Snate@binkert.org 5745863Snate@binkert.org ccRegfileReads 5755863Snate@binkert.org .name(name() + ".cc_regfile_reads") 5765863Snate@binkert.org .desc("number of cc regfile reads") 5775863Snate@binkert.org .prereq(ccRegfileReads); 5783118Sstever@eecs.umich.edu 5793483Ssaidi@eecs.umich.edu ccRegfileWrites 5803494Ssaidi@eecs.umich.edu .name(name() + ".cc_regfile_writes") 5813494Ssaidi@eecs.umich.edu .desc("number of cc regfile writes") 5823483Ssaidi@eecs.umich.edu .prereq(ccRegfileWrites); 5833483Ssaidi@eecs.umich.edu 5843483Ssaidi@eecs.umich.edu miscRegfileReads 5853053Sstever@eecs.umich.edu .name(name() + ".misc_regfile_reads") 5863053Sstever@eecs.umich.edu .desc("number of misc regfile reads") 5873918Ssaidi@eecs.umich.edu .prereq(miscRegfileReads); 5883053Sstever@eecs.umich.edu 5893053Sstever@eecs.umich.edu miscRegfileWrites 5903053Sstever@eecs.umich.edu .name(name() + ".misc_regfile_writes") 5913053Sstever@eecs.umich.edu .desc("number of misc regfile writes") 5923053Sstever@eecs.umich.edu .prereq(miscRegfileWrites); 5931858SN/A} 5941858SN/A 5951858SN/Atemplate <class Impl> 5961858SN/Avoid 5971858SN/AFullO3CPU<Impl>::tick() 5981858SN/A{ 5995863Snate@binkert.org DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 6005863Snate@binkert.org assert(!switchedOut()); 6011859SN/A assert(getDrainState() != Drainable::Drained); 6025863Snate@binkert.org 6031858SN/A ++numCycles; 6045863Snate@binkert.org 6051858SN/A// activity = false; 6061859SN/A 6071859SN/A //Tick each of the stages 6085863Snate@binkert.org fetch.tick(); 6093053Sstever@eecs.umich.edu 6103053Sstever@eecs.umich.edu decode.tick(); 6113053Sstever@eecs.umich.edu 6123053Sstever@eecs.umich.edu rename.tick(); 6131859SN/A 6141859SN/A iew.tick(); 6151859SN/A 6161859SN/A commit.tick(); 6171859SN/A 6181859SN/A if (!FullSystem) 6191859SN/A doContextSwitch(); 6201859SN/A 6211862SN/A // Now advance the time buffers 6221859SN/A timeBuffer.advance(); 6231859SN/A 6241859SN/A fetchQueue.advance(); 6255863Snate@binkert.org decodeQueue.advance(); 6265863Snate@binkert.org renameQueue.advance(); 6275863Snate@binkert.org iewQueue.advance(); 6285863Snate@binkert.org 6291858SN/A activityRec.advance(); 6301858SN/A 6315863Snate@binkert.org if (removeInstsThisCycle) { 6325863Snate@binkert.org cleanUpRemovedInsts(); 6335863Snate@binkert.org } 6345863Snate@binkert.org 6355863Snate@binkert.org if (!tickEvent.scheduled()) { 6365871Snate@binkert.org if (_status == SwitchedOut) { 6375871Snate@binkert.org DPRINTF(O3CPU, "Switched out!\n"); 6382139SN/A // increment stat 6394202Sbinkertn@umich.edu lastRunningCycle = curCycle(); 6404202Sbinkertn@umich.edu } else if (!activityRec.active() || _status == Idle) { 6412139SN/A DPRINTF(O3CPU, "Idle!\n"); 6422155SN/A lastRunningCycle = curCycle(); 6434202Sbinkertn@umich.edu timesIdled++; 6444202Sbinkertn@umich.edu } else { 6454202Sbinkertn@umich.edu schedule(tickEvent, clockEdge(Cycles(1))); 6462155SN/A DPRINTF(O3CPU, "Scheduling next tick!\n"); 6475863Snate@binkert.org } 6481869SN/A } 6491869SN/A 6505863Snate@binkert.org if (!FullSystem) 6515863Snate@binkert.org updateThreadPriority(); 6524202Sbinkertn@umich.edu 6535863Snate@binkert.org tryDrain(); 6545863Snate@binkert.org} 6555863Snate@binkert.org 6564202Sbinkertn@umich.edutemplate <class Impl> 6574202Sbinkertn@umich.eduvoid 6585863Snate@binkert.orgFullO3CPU<Impl>::init() 6595742Snate@binkert.org{ 6605742Snate@binkert.org BaseCPU::init(); 6615341Sstever@gmail.com 6625342Sstever@gmail.com for (ThreadID tid = 0; tid < numThreads; ++tid) { 6635342Sstever@gmail.com // Set noSquashFromTC so that the CPU doesn't squash when initially 6644202Sbinkertn@umich.edu // setting up registers. 6654202Sbinkertn@umich.edu thread[tid]->noSquashFromTC = true; 6664202Sbinkertn@umich.edu // Initialise the ThreadContext's memory proxies 6674202Sbinkertn@umich.edu thread[tid]->initMemProxies(thread[tid]->getTC()); 6684202Sbinkertn@umich.edu } 6695863Snate@binkert.org 6705863Snate@binkert.org if (FullSystem && !params()->switched_out) { 6715863Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) { 6725863Snate@binkert.org ThreadContext *src_tc = threadContexts[tid]; 6735863Snate@binkert.org TheISA::initCPU(src_tc, src_tc->contextId()); 6745863Snate@binkert.org } 6755863Snate@binkert.org } 6765863Snate@binkert.org 6775863Snate@binkert.org // Clear noSquashFromTC. 6785863Snate@binkert.org for (int tid = 0; tid < numThreads; ++tid) 6795863Snate@binkert.org thread[tid]->noSquashFromTC = false; 6805863Snate@binkert.org 6815863Snate@binkert.org commit.setThreads(thread); 6825863Snate@binkert.org} 6835863Snate@binkert.org 6845863Snate@binkert.orgtemplate <class Impl> 6855863Snate@binkert.orgvoid 6865863Snate@binkert.orgFullO3CPU<Impl>::startup() 6875863Snate@binkert.org{ 6885863Snate@binkert.org BaseCPU::startup(); 6891869SN/A for (int tid = 0; tid < numThreads; ++tid) 6901858SN/A isa[tid]->startup(threadContexts[tid]); 6915863Snate@binkert.org 6925863Snate@binkert.org fetch.startupStage(); 6931869SN/A decode.startupStage(); 6941858SN/A iew.startupStage(); 6955863Snate@binkert.org rename.startupStage(); 6965863Snate@binkert.org commit.startupStage(); 6975863Snate@binkert.org} 6985863Snate@binkert.org 6995863Snate@binkert.orgtemplate <class Impl> 7001858SN/Avoid 701955SN/AFullO3CPU<Impl>::activateThread(ThreadID tid) 702955SN/A{ 7031869SN/A list<ThreadID>::iterator isActive = 7041869SN/A std::find(activeThreads.begin(), activeThreads.end(), tid); 7051869SN/A 7061869SN/A DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 7071869SN/A assert(!switchedOut()); 7085863Snate@binkert.org 7095863Snate@binkert.org if (isActive == activeThreads.end()) { 7105863Snate@binkert.org DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 7111869SN/A tid); 7125863Snate@binkert.org 7131869SN/A activeThreads.push_back(tid); 7145863Snate@binkert.org } 7151869SN/A} 7161869SN/A 7171869SN/Atemplate <class Impl> 7181869SN/Avoid 7191869SN/AFullO3CPU<Impl>::deactivateThread(ThreadID tid) 7205863Snate@binkert.org{ 7215863Snate@binkert.org //Remove From Active List, if Active 7221869SN/A list<ThreadID>::iterator thread_it = 7231869SN/A std::find(activeThreads.begin(), activeThreads.end(), tid); 7241869SN/A 7251869SN/A DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 7261869SN/A assert(!switchedOut()); 7271869SN/A 7281869SN/A if (thread_it != activeThreads.end()) { 7295863Snate@binkert.org DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 7305863Snate@binkert.org tid); 7311869SN/A activeThreads.erase(thread_it); 7325863Snate@binkert.org } 7335863Snate@binkert.org} 7343356Sbinkertn@umich.edu 7353356Sbinkertn@umich.edutemplate <class Impl> 7363356Sbinkertn@umich.eduCounter 7373356Sbinkertn@umich.eduFullO3CPU<Impl>::totalInsts() const 7383356Sbinkertn@umich.edu{ 7394781Snate@binkert.org Counter total(0); 7405863Snate@binkert.org 7415863Snate@binkert.org ThreadID size = thread.size(); 7421869SN/A for (ThreadID i = 0; i < size; i++) 7431869SN/A total += thread[i]->numInst; 7441869SN/A 7451869SN/A return total; 7461869SN/A} 7472638Sstever@eecs.umich.edu 7482638Sstever@eecs.umich.edutemplate <class Impl> 7495871Snate@binkert.orgCounter 7502638Sstever@eecs.umich.eduFullO3CPU<Impl>::totalOps() const 7515749Scws3k@cs.virginia.edu{ 7525749Scws3k@cs.virginia.edu Counter total(0); 7535871Snate@binkert.org 7545749Scws3k@cs.virginia.edu ThreadID size = thread.size(); 7551869SN/A for (ThreadID i = 0; i < size; i++) 7561869SN/A total += thread[i]->numOp; 7573546Sgblack@eecs.umich.edu 7583546Sgblack@eecs.umich.edu return total; 7593546Sgblack@eecs.umich.edu} 7603546Sgblack@eecs.umich.edu 7614202Sbinkertn@umich.edutemplate <class Impl> 7625863Snate@binkert.orgvoid 7633546Sgblack@eecs.umich.eduFullO3CPU<Impl>::activateContext(ThreadID tid, Cycles delay) 7643546Sgblack@eecs.umich.edu{ 7653546Sgblack@eecs.umich.edu assert(!switchedOut()); 7663546Sgblack@eecs.umich.edu 7674781Snate@binkert.org // Needs to set each stage to running as well. 7685863Snate@binkert.org if (delay){ 7694781Snate@binkert.org DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 7704781Snate@binkert.org "on cycle %d\n", tid, clockEdge(delay)); 7714781Snate@binkert.org scheduleActivateThreadEvent(tid, delay); 7724781Snate@binkert.org } else { 7734781Snate@binkert.org activateThread(tid); 7745863Snate@binkert.org } 7754781Snate@binkert.org 7764781Snate@binkert.org // We don't want to wake the CPU if it is drained. In that case, 7774781Snate@binkert.org // we just want to flag the thread as active and schedule the tick 7784781Snate@binkert.org // event from drainResume() instead. 7793546Sgblack@eecs.umich.edu if (getDrainState() == Drainable::Drained) 7803546Sgblack@eecs.umich.edu return; 7813546Sgblack@eecs.umich.edu 7824781Snate@binkert.org // If we are time 0 or if the last activation time is in the past, 7833546Sgblack@eecs.umich.edu // schedule the next tick and wake up the fetch unit 7843546Sgblack@eecs.umich.edu if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 7853546Sgblack@eecs.umich.edu scheduleTickEvent(delay); 7863546Sgblack@eecs.umich.edu 7873546Sgblack@eecs.umich.edu // Be sure to signal that there's some activity so the CPU doesn't 7883546Sgblack@eecs.umich.edu // deschedule itself. 7893546Sgblack@eecs.umich.edu activityRec.activity(); 7903546Sgblack@eecs.umich.edu fetch.wakeFromQuiesce(); 7913546Sgblack@eecs.umich.edu 7923546Sgblack@eecs.umich.edu Cycles cycles(curCycle() - lastRunningCycle); 7934202Sbinkertn@umich.edu // @todo: This is an oddity that is only here to match the stats 7943546Sgblack@eecs.umich.edu if (cycles != 0) 7953546Sgblack@eecs.umich.edu --cycles; 7963546Sgblack@eecs.umich.edu quiesceCycles += cycles; 797955SN/A 798955SN/A lastActivatedCycle = curTick(); 799955SN/A 800955SN/A _status = Running; 8011858SN/A } 8021858SN/A} 8031858SN/A 8045863Snate@binkert.orgtemplate <class Impl> 8055863Snate@binkert.orgbool 8065343Sstever@gmail.comFullO3CPU<Impl>::scheduleDeallocateContext(ThreadID tid, bool remove, 8075343Sstever@gmail.com Cycles delay) 8085863Snate@binkert.org{ 8095863Snate@binkert.org // Schedule removal of thread data from CPU 8104773Snate@binkert.org if (delay){ 8115863Snate@binkert.org DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 8122632Sstever@eecs.umich.edu "on tick %d\n", tid, clockEdge(delay)); 8135863Snate@binkert.org scheduleDeallocateContextEvent(tid, remove, delay); 8142023SN/A return false; 8155863Snate@binkert.org } else { 8165863Snate@binkert.org deactivateThread(tid); 8175863Snate@binkert.org if (remove) 8185863Snate@binkert.org removeThread(tid); 8195863Snate@binkert.org return true; 8205863Snate@binkert.org } 8215863Snate@binkert.org} 8225863Snate@binkert.org 8235863Snate@binkert.orgtemplate <class Impl> 8242632Sstever@eecs.umich.eduvoid 8255863Snate@binkert.orgFullO3CPU<Impl>::suspendContext(ThreadID tid) 8262023SN/A{ 8272632Sstever@eecs.umich.edu DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 8285863Snate@binkert.org assert(!switchedOut()); 8295342Sstever@gmail.com bool deallocated = scheduleDeallocateContext(tid, false, Cycles(1)); 8305863Snate@binkert.org // If this was the last thread then unschedule the tick event. 8312632Sstever@eecs.umich.edu if ((activeThreads.size() == 1 && !deallocated) || 8325863Snate@binkert.org activeThreads.size() == 0) 8335863Snate@binkert.org unscheduleTickEvent(); 8342632Sstever@eecs.umich.edu 8355863Snate@binkert.org DPRINTF(Quiesce, "Suspending Context\n"); 8365863Snate@binkert.org lastRunningCycle = curCycle(); 8375863Snate@binkert.org _status = Idle; 8385863Snate@binkert.org} 8395863Snate@binkert.org 8405863Snate@binkert.orgtemplate <class Impl> 8412632Sstever@eecs.umich.eduvoid 8425863Snate@binkert.orgFullO3CPU<Impl>::haltContext(ThreadID tid) 8435863Snate@binkert.org{ 8442632Sstever@eecs.umich.edu //For now, this is the same as deallocate 8451888SN/A DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 8465863Snate@binkert.org assert(!switchedOut()); 8475863Snate@binkert.org scheduleDeallocateContext(tid, true, Cycles(1)); 8485863Snate@binkert.org} 8491858SN/A 8505863Snate@binkert.orgtemplate <class Impl> 8515863Snate@binkert.orgvoid 8525863Snate@binkert.orgFullO3CPU<Impl>::insertThread(ThreadID tid) 8535863Snate@binkert.org{ 8542598SN/A DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 8555863Snate@binkert.org // Will change now that the PC and thread state is internal to the CPU 8561858SN/A // and not in the ThreadContext. 8571858SN/A ThreadContext *src_tc; 8581858SN/A if (FullSystem) 8595863Snate@binkert.org src_tc = system->threadContexts[tid]; 8601858SN/A else 8611858SN/A src_tc = tcBase(tid); 8621858SN/A 8635863Snate@binkert.org //Bind Int Regs to Rename Map 8641871SN/A for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 8651858SN/A PhysRegIndex phys_reg = freeList.getIntReg(); 8661858SN/A 8671858SN/A renameMap[tid].setEntry(ireg,phys_reg); 8681858SN/A scoreboard.setReg(phys_reg); 8691858SN/A } 8701858SN/A 8711858SN/A //Bind Float Regs to Rename Map 8725863Snate@binkert.org int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 8731858SN/A for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { 8741858SN/A PhysRegIndex phys_reg = freeList.getFloatReg(); 8755863Snate@binkert.org 8761859SN/A renameMap[tid].setEntry(freg,phys_reg); 8771859SN/A scoreboard.setReg(phys_reg); 8781869SN/A } 8795863Snate@binkert.org 8805863Snate@binkert.org //Bind condition-code Regs to Rename Map 8811869SN/A max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; 8821965SN/A for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 8831965SN/A creg < max_reg; creg++) { 8841965SN/A PhysRegIndex phys_reg = freeList.getCCReg(); 8852761Sstever@eecs.umich.edu 8865863Snate@binkert.org renameMap[tid].setEntry(creg,phys_reg); 8871869SN/A scoreboard.setReg(phys_reg); 8885863Snate@binkert.org } 8892667Sstever@eecs.umich.edu 8901869SN/A //Copy Thread Data Into RegFile 8911869SN/A //this->copyFromTC(tid); 8922929Sktlim@umich.edu 8932929Sktlim@umich.edu //Set PC/NPC/NNPC 8945863Snate@binkert.org pcState(src_tc->pcState(), tid); 8952929Sktlim@umich.edu 896955SN/A src_tc->setStatus(ThreadContext::Active); 8972598SN/A 898 activateContext(tid, Cycles(1)); 899 900 //Reset ROB/IQ/LSQ Entries 901 commit.rob->resetEntries(); 902 iew.resetEntries(); 903} 904 905template <class Impl> 906void 907FullO3CPU<Impl>::removeThread(ThreadID tid) 908{ 909 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 910 911 // Copy Thread Data From RegFile 912 // If thread is suspended, it might be re-allocated 913 // this->copyToTC(tid); 914 915 916 // @todo: 2-27-2008: Fix how we free up rename mappings 917 // here to alleviate the case for double-freeing registers 918 // in SMT workloads. 919 920 // Unbind Int Regs from Rename Map 921 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 922 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 923 924 scoreboard.unsetReg(phys_reg); 925 freeList.addReg(phys_reg); 926 } 927 928 // Unbind Float Regs from Rename Map 929 int max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 930 for (int freg = TheISA::NumIntRegs; freg < max_reg; freg++) { 931 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 932 933 scoreboard.unsetReg(phys_reg); 934 freeList.addReg(phys_reg); 935 } 936 937 // Unbind condition-code Regs from Rename Map 938 max_reg = TheISA::NumIntRegs + TheISA::NumFloatRegs + TheISA::NumCCRegs; 939 for (int creg = TheISA::NumIntRegs + TheISA::NumFloatRegs; 940 creg < max_reg; creg++) { 941 PhysRegIndex phys_reg = renameMap[tid].lookup(creg); 942 943 scoreboard.unsetReg(phys_reg); 944 freeList.addReg(phys_reg); 945 } 946 947 // Squash Throughout Pipeline 948 DynInstPtr inst = commit.rob->readHeadInst(tid); 949 InstSeqNum squash_seq_num = inst->seqNum; 950 fetch.squash(0, squash_seq_num, inst, tid); 951 decode.squash(tid); 952 rename.squash(squash_seq_num, tid); 953 iew.squash(tid); 954 iew.ldstQueue.squash(squash_seq_num, tid); 955 commit.rob->squash(squash_seq_num, tid); 956 957 958 assert(iew.instQueue.getCount(tid) == 0); 959 assert(iew.ldstQueue.getCount(tid) == 0); 960 961 // Reset ROB/IQ/LSQ Entries 962 963 // Commented out for now. This should be possible to do by 964 // telling all the pipeline stages to drain first, and then 965 // checking until the drain completes. Once the pipeline is 966 // drained, call resetEntries(). - 10-09-06 ktlim 967/* 968 if (activeThreads.size() >= 1) { 969 commit.rob->resetEntries(); 970 iew.resetEntries(); 971 } 972*/ 973} 974 975 976template <class Impl> 977void 978FullO3CPU<Impl>::activateWhenReady(ThreadID tid) 979{ 980 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 981 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 982 tid); 983 984 bool ready = true; 985 986 // Should these all be '<' not '>='? This seems backwards... 987 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 988 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 989 "Phys. Int. Regs.\n", 990 tid); 991 ready = false; 992 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 993 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 994 "Phys. Float. Regs.\n", 995 tid); 996 ready = false; 997 } else if (freeList.numFreeCCRegs() >= TheISA::NumCCRegs) { 998 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 999 "Phys. CC. Regs.\n", 1000 tid); 1001 ready = false; 1002 } else if (commit.rob->numFreeEntries() >= 1003 commit.rob->entryAmount(activeThreads.size() + 1)) { 1004 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 1005 "ROB entries.\n", 1006 tid); 1007 ready = false; 1008 } else if (iew.instQueue.numFreeEntries() >= 1009 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 1010 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 1011 "IQ entries.\n", 1012 tid); 1013 ready = false; 1014 } else if (iew.ldstQueue.numFreeEntries() >= 1015 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 1016 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 1017 "LSQ entries.\n", 1018 tid); 1019 ready = false; 1020 } 1021 1022 if (ready) { 1023 insertThread(tid); 1024 1025 contextSwitch = false; 1026 1027 cpuWaitList.remove(tid); 1028 } else { 1029 suspendContext(tid); 1030 1031 //blocks fetch 1032 contextSwitch = true; 1033 1034 //@todo: dont always add to waitlist 1035 //do waitlist 1036 cpuWaitList.push_back(tid); 1037 } 1038} 1039 1040template <class Impl> 1041Fault 1042FullO3CPU<Impl>::hwrei(ThreadID tid) 1043{ 1044#if THE_ISA == ALPHA_ISA 1045 // Need to clear the lock flag upon returning from an interrupt. 1046 this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); 1047 1048 this->thread[tid]->kernelStats->hwrei(); 1049 1050 // FIXME: XXX check for interrupts? XXX 1051#endif 1052 return NoFault; 1053} 1054 1055template <class Impl> 1056bool 1057FullO3CPU<Impl>::simPalCheck(int palFunc, ThreadID tid) 1058{ 1059#if THE_ISA == ALPHA_ISA 1060 if (this->thread[tid]->kernelStats) 1061 this->thread[tid]->kernelStats->callpal(palFunc, 1062 this->threadContexts[tid]); 1063 1064 switch (palFunc) { 1065 case PAL::halt: 1066 halt(); 1067 if (--System::numSystemsRunning == 0) 1068 exitSimLoop("all cpus halted"); 1069 break; 1070 1071 case PAL::bpt: 1072 case PAL::bugchk: 1073 if (this->system->breakpoint()) 1074 return false; 1075 break; 1076 } 1077#endif 1078 return true; 1079} 1080 1081template <class Impl> 1082Fault 1083FullO3CPU<Impl>::getInterrupts() 1084{ 1085 // Check if there are any outstanding interrupts 1086 return this->interrupts->getInterrupt(this->threadContexts[0]); 1087} 1088 1089template <class Impl> 1090void 1091FullO3CPU<Impl>::processInterrupts(Fault interrupt) 1092{ 1093 // Check for interrupts here. For now can copy the code that 1094 // exists within isa_fullsys_traits.hh. Also assume that thread 0 1095 // is the one that handles the interrupts. 1096 // @todo: Possibly consolidate the interrupt checking code. 1097 // @todo: Allow other threads to handle interrupts. 1098 1099 assert(interrupt != NoFault); 1100 this->interrupts->updateIntrInfo(this->threadContexts[0]); 1101 1102 DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); 1103 this->trap(interrupt, 0, NULL); 1104} 1105 1106template <class Impl> 1107void 1108FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst) 1109{ 1110 // Pass the thread's TC into the invoke method. 1111 fault->invoke(this->threadContexts[tid], inst); 1112} 1113 1114template <class Impl> 1115void 1116FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid) 1117{ 1118 DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); 1119 1120 DPRINTF(Activity,"Activity: syscall() called.\n"); 1121 1122 // Temporarily increase this by one to account for the syscall 1123 // instruction. 1124 ++(this->thread[tid]->funcExeInst); 1125 1126 // Execute the actual syscall. 1127 this->thread[tid]->syscall(callnum); 1128 1129 // Decrease funcExeInst by one as the normal commit will handle 1130 // incrementing it. 1131 --(this->thread[tid]->funcExeInst); 1132} 1133 1134template <class Impl> 1135void 1136FullO3CPU<Impl>::serializeThread(std::ostream &os, ThreadID tid) 1137{ 1138 thread[tid]->serialize(os); 1139} 1140 1141template <class Impl> 1142void 1143FullO3CPU<Impl>::unserializeThread(Checkpoint *cp, const std::string §ion, 1144 ThreadID tid) 1145{ 1146 thread[tid]->unserialize(cp, section); 1147} 1148 1149template <class Impl> 1150unsigned int 1151FullO3CPU<Impl>::drain(DrainManager *drain_manager) 1152{ 1153 // If the CPU isn't doing anything, then return immediately. 1154 if (switchedOut()) { 1155 setDrainState(Drainable::Drained); 1156 return 0; 1157 } 1158 1159 DPRINTF(Drain, "Draining...\n"); 1160 setDrainState(Drainable::Draining); 1161 1162 // We only need to signal a drain to the commit stage as this 1163 // initiates squashing controls the draining. Once the commit 1164 // stage commits an instruction where it is safe to stop, it'll 1165 // squash the rest of the instructions in the pipeline and force 1166 // the fetch stage to stall. The pipeline will be drained once all 1167 // in-flight instructions have retired. 1168 commit.drain(); 1169 1170 // Wake the CPU and record activity so everything can drain out if 1171 // the CPU was not able to immediately drain. 1172 if (!isDrained()) { 1173 drainManager = drain_manager; 1174 1175 wakeCPU(); 1176 activityRec.activity(); 1177 1178 DPRINTF(Drain, "CPU not drained\n"); 1179 1180 return 1; 1181 } else { 1182 setDrainState(Drainable::Drained); 1183 DPRINTF(Drain, "CPU is already drained\n"); 1184 if (tickEvent.scheduled()) 1185 deschedule(tickEvent); 1186 1187 // Flush out any old data from the time buffers. In 1188 // particular, there might be some data in flight from the 1189 // fetch stage that isn't visible in any of the CPU buffers we 1190 // test in isDrained(). 1191 for (int i = 0; i < timeBuffer.getSize(); ++i) { 1192 timeBuffer.advance(); 1193 fetchQueue.advance(); 1194 decodeQueue.advance(); 1195 renameQueue.advance(); 1196 iewQueue.advance(); 1197 } 1198 1199 drainSanityCheck(); 1200 return 0; 1201 } 1202} 1203 1204template <class Impl> 1205bool 1206FullO3CPU<Impl>::tryDrain() 1207{ 1208 if (!drainManager || !isDrained()) 1209 return false; 1210 1211 if (tickEvent.scheduled()) 1212 deschedule(tickEvent); 1213 1214 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 1215 drainManager->signalDrainDone(); 1216 drainManager = NULL; 1217 1218 return true; 1219} 1220 1221template <class Impl> 1222void 1223FullO3CPU<Impl>::drainSanityCheck() const 1224{ 1225 assert(isDrained()); 1226 fetch.drainSanityCheck(); 1227 decode.drainSanityCheck(); 1228 rename.drainSanityCheck(); 1229 iew.drainSanityCheck(); 1230 commit.drainSanityCheck(); 1231} 1232 1233template <class Impl> 1234bool 1235FullO3CPU<Impl>::isDrained() const 1236{ 1237 bool drained(true); 1238 1239 for (ThreadID i = 0; i < thread.size(); ++i) { 1240 if (activateThreadEvent[i].scheduled()) { 1241 DPRINTF(Drain, "CPU not drained, tread %i has a " 1242 "pending activate event\n", i); 1243 drained = false; 1244 } 1245 if (deallocateContextEvent[i].scheduled()) { 1246 DPRINTF(Drain, "CPU not drained, tread %i has a " 1247 "pending deallocate context event\n", i); 1248 drained = false; 1249 } 1250 } 1251 1252 if (!instList.empty() || !removeList.empty()) { 1253 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1254 drained = false; 1255 } 1256 1257 if (!fetch.isDrained()) { 1258 DPRINTF(Drain, "Fetch not drained.\n"); 1259 drained = false; 1260 } 1261 1262 if (!decode.isDrained()) { 1263 DPRINTF(Drain, "Decode not drained.\n"); 1264 drained = false; 1265 } 1266 1267 if (!rename.isDrained()) { 1268 DPRINTF(Drain, "Rename not drained.\n"); 1269 drained = false; 1270 } 1271 1272 if (!iew.isDrained()) { 1273 DPRINTF(Drain, "IEW not drained.\n"); 1274 drained = false; 1275 } 1276 1277 if (!commit.isDrained()) { 1278 DPRINTF(Drain, "Commit not drained.\n"); 1279 drained = false; 1280 } 1281 1282 return drained; 1283} 1284 1285template <class Impl> 1286void 1287FullO3CPU<Impl>::commitDrained(ThreadID tid) 1288{ 1289 fetch.drainStall(tid); 1290} 1291 1292template <class Impl> 1293void 1294FullO3CPU<Impl>::drainResume() 1295{ 1296 setDrainState(Drainable::Running); 1297 if (switchedOut()) 1298 return; 1299 1300 DPRINTF(Drain, "Resuming...\n"); 1301 verifyMemoryMode(); 1302 1303 fetch.drainResume(); 1304 commit.drainResume(); 1305 1306 _status = Idle; 1307 for (ThreadID i = 0; i < thread.size(); i++) { 1308 if (thread[i]->status() == ThreadContext::Active) { 1309 DPRINTF(Drain, "Activating thread: %i\n", i); 1310 activateThread(i); 1311 _status = Running; 1312 } 1313 } 1314 1315 assert(!tickEvent.scheduled()); 1316 if (_status == Running) 1317 schedule(tickEvent, nextCycle()); 1318} 1319 1320template <class Impl> 1321void 1322FullO3CPU<Impl>::switchOut() 1323{ 1324 DPRINTF(O3CPU, "Switching out\n"); 1325 BaseCPU::switchOut(); 1326 1327 activityRec.reset(); 1328 1329 _status = SwitchedOut; 1330 1331 if (checker) 1332 checker->switchOut(); 1333} 1334 1335template <class Impl> 1336void 1337FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1338{ 1339 BaseCPU::takeOverFrom(oldCPU); 1340 1341 fetch.takeOverFrom(); 1342 decode.takeOverFrom(); 1343 rename.takeOverFrom(); 1344 iew.takeOverFrom(); 1345 commit.takeOverFrom(); 1346 1347 assert(!tickEvent.scheduled()); 1348 1349 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1350 if (oldO3CPU) 1351 globalSeqNum = oldO3CPU->globalSeqNum; 1352 1353 lastRunningCycle = curCycle(); 1354 _status = Idle; 1355} 1356 1357template <class Impl> 1358void 1359FullO3CPU<Impl>::verifyMemoryMode() const 1360{ 1361 if (!system->isTimingMode()) { 1362 fatal("The O3 CPU requires the memory system to be in " 1363 "'timing' mode.\n"); 1364 } 1365} 1366 1367template <class Impl> 1368TheISA::MiscReg 1369FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) 1370{ 1371 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1372} 1373 1374template <class Impl> 1375TheISA::MiscReg 1376FullO3CPU<Impl>::readMiscReg(int misc_reg, ThreadID tid) 1377{ 1378 miscRegfileReads++; 1379 return this->isa[tid]->readMiscReg(misc_reg, tcBase(tid)); 1380} 1381 1382template <class Impl> 1383void 1384FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, 1385 const TheISA::MiscReg &val, ThreadID tid) 1386{ 1387 this->isa[tid]->setMiscRegNoEffect(misc_reg, val); 1388} 1389 1390template <class Impl> 1391void 1392FullO3CPU<Impl>::setMiscReg(int misc_reg, 1393 const TheISA::MiscReg &val, ThreadID tid) 1394{ 1395 miscRegfileWrites++; 1396 this->isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); 1397} 1398 1399template <class Impl> 1400uint64_t 1401FullO3CPU<Impl>::readIntReg(int reg_idx) 1402{ 1403 intRegfileReads++; 1404 return regFile.readIntReg(reg_idx); 1405} 1406 1407template <class Impl> 1408FloatReg 1409FullO3CPU<Impl>::readFloatReg(int reg_idx) 1410{ 1411 fpRegfileReads++; 1412 return regFile.readFloatReg(reg_idx); 1413} 1414 1415template <class Impl> 1416FloatRegBits 1417FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1418{ 1419 fpRegfileReads++; 1420 return regFile.readFloatRegBits(reg_idx); 1421} 1422 1423template <class Impl> 1424CCReg 1425FullO3CPU<Impl>::readCCReg(int reg_idx) 1426{ 1427 ccRegfileReads++; 1428 return regFile.readCCReg(reg_idx); 1429} 1430 1431template <class Impl> 1432void 1433FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1434{ 1435 intRegfileWrites++; 1436 regFile.setIntReg(reg_idx, val); 1437} 1438 1439template <class Impl> 1440void 1441FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1442{ 1443 fpRegfileWrites++; 1444 regFile.setFloatReg(reg_idx, val); 1445} 1446 1447template <class Impl> 1448void 1449FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1450{ 1451 fpRegfileWrites++; 1452 regFile.setFloatRegBits(reg_idx, val); 1453} 1454 1455template <class Impl> 1456void 1457FullO3CPU<Impl>::setCCReg(int reg_idx, CCReg val) 1458{ 1459 ccRegfileWrites++; 1460 regFile.setCCReg(reg_idx, val); 1461} 1462 1463template <class Impl> 1464uint64_t 1465FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid) 1466{ 1467 intRegfileReads++; 1468 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1469 1470 return regFile.readIntReg(phys_reg); 1471} 1472 1473template <class Impl> 1474float 1475FullO3CPU<Impl>::readArchFloatReg(int reg_idx, ThreadID tid) 1476{ 1477 fpRegfileReads++; 1478 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1479 1480 return regFile.readFloatReg(phys_reg); 1481} 1482 1483template <class Impl> 1484uint64_t 1485FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, ThreadID tid) 1486{ 1487 fpRegfileReads++; 1488 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1489 1490 return regFile.readFloatRegBits(phys_reg); 1491} 1492 1493template <class Impl> 1494CCReg 1495FullO3CPU<Impl>::readArchCCReg(int reg_idx, ThreadID tid) 1496{ 1497 ccRegfileReads++; 1498 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1499 1500 return regFile.readCCReg(phys_reg); 1501} 1502 1503template <class Impl> 1504void 1505FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, ThreadID tid) 1506{ 1507 intRegfileWrites++; 1508 PhysRegIndex phys_reg = commitRenameMap[tid].lookupInt(reg_idx); 1509 1510 regFile.setIntReg(phys_reg, val); 1511} 1512 1513template <class Impl> 1514void 1515FullO3CPU<Impl>::setArchFloatReg(int reg_idx, float val, ThreadID tid) 1516{ 1517 fpRegfileWrites++; 1518 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1519 1520 regFile.setFloatReg(phys_reg, val); 1521} 1522 1523template <class Impl> 1524void 1525FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) 1526{ 1527 fpRegfileWrites++; 1528 PhysRegIndex phys_reg = commitRenameMap[tid].lookupFloat(reg_idx); 1529 1530 regFile.setFloatRegBits(phys_reg, val); 1531} 1532 1533template <class Impl> 1534void 1535FullO3CPU<Impl>::setArchCCReg(int reg_idx, CCReg val, ThreadID tid) 1536{ 1537 ccRegfileWrites++; 1538 PhysRegIndex phys_reg = commitRenameMap[tid].lookupCC(reg_idx); 1539 1540 regFile.setCCReg(phys_reg, val); 1541} 1542 1543template <class Impl> 1544TheISA::PCState 1545FullO3CPU<Impl>::pcState(ThreadID tid) 1546{ 1547 return commit.pcState(tid); 1548} 1549 1550template <class Impl> 1551void 1552FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) 1553{ 1554 commit.pcState(val, tid); 1555} 1556 1557template <class Impl> 1558Addr 1559FullO3CPU<Impl>::instAddr(ThreadID tid) 1560{ 1561 return commit.instAddr(tid); 1562} 1563 1564template <class Impl> 1565Addr 1566FullO3CPU<Impl>::nextInstAddr(ThreadID tid) 1567{ 1568 return commit.nextInstAddr(tid); 1569} 1570 1571template <class Impl> 1572MicroPC 1573FullO3CPU<Impl>::microPC(ThreadID tid) 1574{ 1575 return commit.microPC(tid); 1576} 1577 1578template <class Impl> 1579void 1580FullO3CPU<Impl>::squashFromTC(ThreadID tid) 1581{ 1582 this->thread[tid]->noSquashFromTC = true; 1583 this->commit.generateTCEvent(tid); 1584} 1585 1586template <class Impl> 1587typename FullO3CPU<Impl>::ListIt 1588FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1589{ 1590 instList.push_back(inst); 1591 1592 return --(instList.end()); 1593} 1594 1595template <class Impl> 1596void 1597FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst) 1598{ 1599 // Keep an instruction count. 1600 if (!inst->isMicroop() || inst->isLastMicroop()) { 1601 thread[tid]->numInst++; 1602 thread[tid]->numInsts++; 1603 committedInsts[tid]++; 1604 totalCommittedInsts++; 1605 } 1606 thread[tid]->numOp++; 1607 thread[tid]->numOps++; 1608 committedOps[tid]++; 1609 1610 system->totalNumInsts++; 1611 // Check for instruction-count-based events. 1612 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1613 system->instEventQueue.serviceEvents(system->totalNumInsts); 1614} 1615 1616template <class Impl> 1617void 1618FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1619{ 1620 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " 1621 "[sn:%lli]\n", 1622 inst->threadNumber, inst->pcState(), inst->seqNum); 1623 1624 removeInstsThisCycle = true; 1625 1626 // Remove the front instruction. 1627 removeList.push(inst->getInstListIt()); 1628} 1629 1630template <class Impl> 1631void 1632FullO3CPU<Impl>::removeInstsNotInROB(ThreadID tid) 1633{ 1634 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1635 " list.\n", tid); 1636 1637 ListIt end_it; 1638 1639 bool rob_empty = false; 1640 1641 if (instList.empty()) { 1642 return; 1643 } else if (rob.isEmpty(/*tid*/)) { 1644 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1645 end_it = instList.begin(); 1646 rob_empty = true; 1647 } else { 1648 end_it = (rob.readTailInst(tid))->getInstListIt(); 1649 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1650 } 1651 1652 removeInstsThisCycle = true; 1653 1654 ListIt inst_it = instList.end(); 1655 1656 inst_it--; 1657 1658 // Walk through the instruction list, removing any instructions 1659 // that were inserted after the given instruction iterator, end_it. 1660 while (inst_it != end_it) { 1661 assert(!instList.empty()); 1662 1663 squashInstIt(inst_it, tid); 1664 1665 inst_it--; 1666 } 1667 1668 // If the ROB was empty, then we actually need to remove the first 1669 // instruction as well. 1670 if (rob_empty) { 1671 squashInstIt(inst_it, tid); 1672 } 1673} 1674 1675template <class Impl> 1676void 1677FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) 1678{ 1679 assert(!instList.empty()); 1680 1681 removeInstsThisCycle = true; 1682 1683 ListIt inst_iter = instList.end(); 1684 1685 inst_iter--; 1686 1687 DPRINTF(O3CPU, "Deleting instructions from instruction " 1688 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1689 tid, seq_num, (*inst_iter)->seqNum); 1690 1691 while ((*inst_iter)->seqNum > seq_num) { 1692 1693 bool break_loop = (inst_iter == instList.begin()); 1694 1695 squashInstIt(inst_iter, tid); 1696 1697 inst_iter--; 1698 1699 if (break_loop) 1700 break; 1701 } 1702} 1703 1704template <class Impl> 1705inline void 1706FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) 1707{ 1708 if ((*instIt)->threadNumber == tid) { 1709 DPRINTF(O3CPU, "Squashing instruction, " 1710 "[tid:%i] [sn:%lli] PC %s\n", 1711 (*instIt)->threadNumber, 1712 (*instIt)->seqNum, 1713 (*instIt)->pcState()); 1714 1715 // Mark it as squashed. 1716 (*instIt)->setSquashed(); 1717 1718 // @todo: Formulate a consistent method for deleting 1719 // instructions from the instruction list 1720 // Remove the instruction from the list. 1721 removeList.push(instIt); 1722 } 1723} 1724 1725template <class Impl> 1726void 1727FullO3CPU<Impl>::cleanUpRemovedInsts() 1728{ 1729 while (!removeList.empty()) { 1730 DPRINTF(O3CPU, "Removing instruction, " 1731 "[tid:%i] [sn:%lli] PC %s\n", 1732 (*removeList.front())->threadNumber, 1733 (*removeList.front())->seqNum, 1734 (*removeList.front())->pcState()); 1735 1736 instList.erase(removeList.front()); 1737 1738 removeList.pop(); 1739 } 1740 1741 removeInstsThisCycle = false; 1742} 1743/* 1744template <class Impl> 1745void 1746FullO3CPU<Impl>::removeAllInsts() 1747{ 1748 instList.clear(); 1749} 1750*/ 1751template <class Impl> 1752void 1753FullO3CPU<Impl>::dumpInsts() 1754{ 1755 int num = 0; 1756 1757 ListIt inst_list_it = instList.begin(); 1758 1759 cprintf("Dumping Instruction List\n"); 1760 1761 while (inst_list_it != instList.end()) { 1762 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1763 "Squashed:%i\n\n", 1764 num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, 1765 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1766 (*inst_list_it)->isSquashed()); 1767 inst_list_it++; 1768 ++num; 1769 } 1770} 1771/* 1772template <class Impl> 1773void 1774FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1775{ 1776 iew.wakeDependents(inst); 1777} 1778*/ 1779template <class Impl> 1780void 1781FullO3CPU<Impl>::wakeCPU() 1782{ 1783 if (activityRec.active() || tickEvent.scheduled()) { 1784 DPRINTF(Activity, "CPU already running.\n"); 1785 return; 1786 } 1787 1788 DPRINTF(Activity, "Waking up CPU\n"); 1789 1790 Cycles cycles(curCycle() - lastRunningCycle); 1791 // @todo: This is an oddity that is only here to match the stats 1792 if (cycles != 0) 1793 --cycles; 1794 idleCycles += cycles; 1795 numCycles += cycles; 1796 1797 schedule(tickEvent, clockEdge()); 1798} 1799 1800template <class Impl> 1801void 1802FullO3CPU<Impl>::wakeup() 1803{ 1804 if (this->thread[0]->status() != ThreadContext::Suspended) 1805 return; 1806 1807 this->wakeCPU(); 1808 1809 DPRINTF(Quiesce, "Suspended Processor woken\n"); 1810 this->threadContexts[0]->activate(); 1811} 1812 1813template <class Impl> 1814ThreadID 1815FullO3CPU<Impl>::getFreeTid() 1816{ 1817 for (ThreadID tid = 0; tid < numThreads; tid++) { 1818 if (!tids[tid]) { 1819 tids[tid] = true; 1820 return tid; 1821 } 1822 } 1823 1824 return InvalidThreadID; 1825} 1826 1827template <class Impl> 1828void 1829FullO3CPU<Impl>::doContextSwitch() 1830{ 1831 if (contextSwitch) { 1832 1833 //ADD CODE TO DEACTIVE THREAD HERE (???) 1834 1835 ThreadID size = cpuWaitList.size(); 1836 for (ThreadID tid = 0; tid < size; tid++) { 1837 activateWhenReady(tid); 1838 } 1839 1840 if (cpuWaitList.size() == 0) 1841 contextSwitch = true; 1842 } 1843} 1844 1845template <class Impl> 1846void 1847FullO3CPU<Impl>::updateThreadPriority() 1848{ 1849 if (activeThreads.size() > 1) { 1850 //DEFAULT TO ROUND ROBIN SCHEME 1851 //e.g. Move highest priority to end of thread list 1852 list<ThreadID>::iterator list_begin = activeThreads.begin(); 1853 1854 unsigned high_thread = *list_begin; 1855 1856 activeThreads.erase(list_begin); 1857 1858 activeThreads.push_back(high_thread); 1859 } 1860} 1861 1862// Forward declaration of FullO3CPU. 1863template class FullO3CPU<O3CPUImpl>; 1864