cpu.cc revision 4873
16876Ssteve.reinhardt@amd.com/* 26876Ssteve.reinhardt@amd.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 36876Ssteve.reinhardt@amd.com * All rights reserved. 46876Ssteve.reinhardt@amd.com * 56876Ssteve.reinhardt@amd.com * Redistribution and use in source and binary forms, with or without 66876Ssteve.reinhardt@amd.com * modification, are permitted provided that the following conditions are 76876Ssteve.reinhardt@amd.com * met: redistributions of source code must retain the above copyright 86876Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer; 96876Ssteve.reinhardt@amd.com * redistributions in binary form must reproduce the above copyright 106876Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer in the 116876Ssteve.reinhardt@amd.com * documentation and/or other materials provided with the distribution; 126876Ssteve.reinhardt@amd.com * neither the name of the copyright holders nor the names of its 136876Ssteve.reinhardt@amd.com * contributors may be used to endorse or promote products derived from 146876Ssteve.reinhardt@amd.com * this software without specific prior written permission. 156876Ssteve.reinhardt@amd.com * 166876Ssteve.reinhardt@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176876Ssteve.reinhardt@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186876Ssteve.reinhardt@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196876Ssteve.reinhardt@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206876Ssteve.reinhardt@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216876Ssteve.reinhardt@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226876Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236876Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246876Ssteve.reinhardt@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256876Ssteve.reinhardt@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266876Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276876Ssteve.reinhardt@amd.com * 286876Ssteve.reinhardt@amd.com * Authors: Kevin Lim 297632SBrad.Beckmann@amd.com * Korey Sewell 308688Snilay@cs.wisc.edu */ 318232Snate@binkert.org 328436SBrad.Beckmann@amd.com#include "config/full_system.hh" 337039Snate@binkert.org#include "config/use_checker.hh" 346285Snate@binkert.org 356285Snate@binkert.org#if FULL_SYSTEM 366876Ssteve.reinhardt@amd.com#include "cpu/quiesce_event.hh" 376893SBrad.Beckmann@amd.com#include "sim/system.hh" 386876Ssteve.reinhardt@amd.com#else 396876Ssteve.reinhardt@amd.com#include "sim/process.hh" 406876Ssteve.reinhardt@amd.com#endif 416876Ssteve.reinhardt@amd.com 426893SBrad.Beckmann@amd.com#include "cpu/activity.hh" 437039Snate@binkert.org#include "cpu/simple_thread.hh" 446882SBrad.Beckmann@amd.com#include "cpu/thread_context.hh" 456882SBrad.Beckmann@amd.com#include "cpu/o3/isa_specific.hh" 466876Ssteve.reinhardt@amd.com#include "cpu/o3/cpu.hh" 476876Ssteve.reinhardt@amd.com 486882SBrad.Beckmann@amd.com#include "sim/core.hh" 496893SBrad.Beckmann@amd.com#include "sim/stat_control.hh" 507910SBrad.Beckmann@amd.com 517910SBrad.Beckmann@amd.com#if USE_CHECKER 527915SBrad.Beckmann@amd.com#include "cpu/checker/cpu.hh" 538436SBrad.Beckmann@amd.com#endif 548688Snilay@cs.wisc.edu 558688Snilay@cs.wisc.eduusing namespace std; 568436SBrad.Beckmann@amd.comusing namespace TheISA; 578505Snilay@cs.wisc.edu 586876Ssteve.reinhardt@amd.comBaseO3CPU::BaseO3CPU(Params *params) 596876Ssteve.reinhardt@amd.com : BaseCPU(params), cpu_id(0) 607039Snate@binkert.org{ 617039Snate@binkert.org} 626882SBrad.Beckmann@amd.com 636882SBrad.Beckmann@amd.comvoid 646882SBrad.Beckmann@amd.comBaseO3CPU::regStats() 656882SBrad.Beckmann@amd.com{ 666882SBrad.Beckmann@amd.com BaseCPU::regStats(); 676876Ssteve.reinhardt@amd.com} 686876Ssteve.reinhardt@amd.com 696876Ssteve.reinhardt@amd.comtemplate <class Impl> 706882SBrad.Beckmann@amd.comFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 718686Snilay@cs.wisc.edu : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 728686Snilay@cs.wisc.edu{ 738686Snilay@cs.wisc.edu} 748686Snilay@cs.wisc.edu 757039Snate@binkert.orgtemplate <class Impl> 767039Snate@binkert.orgvoid 777039Snate@binkert.orgFullO3CPU<Impl>::TickEvent::process() 786882SBrad.Beckmann@amd.com{ 796882SBrad.Beckmann@amd.com cpu->tick(); 806882SBrad.Beckmann@amd.com} 817039Snate@binkert.org 826882SBrad.Beckmann@amd.comtemplate <class Impl> 836882SBrad.Beckmann@amd.comconst char * 847039Snate@binkert.orgFullO3CPU<Impl>::TickEvent::description() 857039Snate@binkert.org{ 867039Snate@binkert.org return "FullO3CPU tick"; 876893SBrad.Beckmann@amd.com} 886893SBrad.Beckmann@amd.com 896893SBrad.Beckmann@amd.comtemplate <class Impl> 907915SBrad.Beckmann@amd.comFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 918436SBrad.Beckmann@amd.com : Event(&mainEventQueue, CPU_Switch_Pri) 927039Snate@binkert.org{ 936893SBrad.Beckmann@amd.com} 947039Snate@binkert.org 957039Snate@binkert.orgtemplate <class Impl> 967039Snate@binkert.orgvoid 977039Snate@binkert.orgFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 987039Snate@binkert.org FullO3CPU<Impl> *thread_cpu) 997039Snate@binkert.org{ 1006893SBrad.Beckmann@amd.com tid = thread_num; 1016893SBrad.Beckmann@amd.com cpu = thread_cpu; 1026882SBrad.Beckmann@amd.com} 1037039Snate@binkert.org 1046876Ssteve.reinhardt@amd.comtemplate <class Impl> 1056876Ssteve.reinhardt@amd.comvoid 1066882SBrad.Beckmann@amd.comFullO3CPU<Impl>::ActivateThreadEvent::process() 1077039Snate@binkert.org{ 1086882SBrad.Beckmann@amd.com cpu->activateThread(tid); 1096882SBrad.Beckmann@amd.com} 1106882SBrad.Beckmann@amd.com 1118161SBrad.Beckmann@amd.comtemplate <class Impl> 1126882SBrad.Beckmann@amd.comconst char * 1136882SBrad.Beckmann@amd.comFullO3CPU<Impl>::ActivateThreadEvent::description() 1146882SBrad.Beckmann@amd.com{ 1158436SBrad.Beckmann@amd.com return "FullO3CPU \"Activate Thread\""; 1168436SBrad.Beckmann@amd.com} 1176882SBrad.Beckmann@amd.com 1186882SBrad.Beckmann@amd.comtemplate <class Impl> 1198161SBrad.Beckmann@amd.comFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1206882SBrad.Beckmann@amd.com : Event(&mainEventQueue, CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) 1218436SBrad.Beckmann@amd.com{ 1227910SBrad.Beckmann@amd.com} 1237915SBrad.Beckmann@amd.com 1246882SBrad.Beckmann@amd.comtemplate <class Impl> 1256882SBrad.Beckmann@amd.comvoid 1266882SBrad.Beckmann@amd.comFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1276882SBrad.Beckmann@amd.com FullO3CPU<Impl> *thread_cpu) 1286882SBrad.Beckmann@amd.com{ 1296882SBrad.Beckmann@amd.com tid = thread_num; 1306882SBrad.Beckmann@amd.com cpu = thread_cpu; 1316882SBrad.Beckmann@amd.com remove = false; 1326882SBrad.Beckmann@amd.com} 1336882SBrad.Beckmann@amd.com 1346882SBrad.Beckmann@amd.comtemplate <class Impl> 1356882SBrad.Beckmann@amd.comvoid 1366882SBrad.Beckmann@amd.comFullO3CPU<Impl>::DeallocateContextEvent::process() 1376882SBrad.Beckmann@amd.com{ 1386882SBrad.Beckmann@amd.com cpu->deactivateThread(tid); 1396882SBrad.Beckmann@amd.com if (remove) 1406882SBrad.Beckmann@amd.com cpu->removeThread(tid); 1416882SBrad.Beckmann@amd.com} 1426882SBrad.Beckmann@amd.com 1436882SBrad.Beckmann@amd.comtemplate <class Impl> 1447039Snate@binkert.orgconst char * 1457039Snate@binkert.orgFullO3CPU<Impl>::DeallocateContextEvent::description() 1468161SBrad.Beckmann@amd.com{ 1476882SBrad.Beckmann@amd.com return "FullO3CPU \"Deallocate Context\""; 1486882SBrad.Beckmann@amd.com} 1496882SBrad.Beckmann@amd.com 1506882SBrad.Beckmann@amd.comtemplate <class Impl> 1517039Snate@binkert.orgFullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params) 1526882SBrad.Beckmann@amd.com : BaseO3CPU(params), 1536882SBrad.Beckmann@amd.com#if FULL_SYSTEM 1546882SBrad.Beckmann@amd.com itb(params->itb), 1557039Snate@binkert.org dtb(params->dtb), 1566882SBrad.Beckmann@amd.com#endif 1576882SBrad.Beckmann@amd.com tickEvent(this), 1586882SBrad.Beckmann@amd.com removeInstsThisCycle(false), 1597039Snate@binkert.org fetch(o3_cpu, params), 1606882SBrad.Beckmann@amd.com decode(o3_cpu, params), 1617039Snate@binkert.org rename(o3_cpu, params), 1626882SBrad.Beckmann@amd.com iew(o3_cpu, params), 1636882SBrad.Beckmann@amd.com commit(o3_cpu, params), 1646882SBrad.Beckmann@amd.com 1656882SBrad.Beckmann@amd.com regFile(o3_cpu, params->numPhysIntRegs, 1666882SBrad.Beckmann@amd.com params->numPhysFloatRegs), 1676882SBrad.Beckmann@amd.com 1688161SBrad.Beckmann@amd.com freeList(params->numberOfThreads, 1697039Snate@binkert.org TheISA::NumIntRegs, params->numPhysIntRegs, 1706882SBrad.Beckmann@amd.com TheISA::NumFloatRegs, params->numPhysFloatRegs), 1716882SBrad.Beckmann@amd.com 1726882SBrad.Beckmann@amd.com rob(o3_cpu, 1737039Snate@binkert.org params->numROBEntries, params->squashWidth, 1747039Snate@binkert.org params->smtROBPolicy, params->smtROBThreshold, 1757039Snate@binkert.org params->numberOfThreads), 1766882SBrad.Beckmann@amd.com 1776882SBrad.Beckmann@amd.com scoreboard(params->numberOfThreads, 1786882SBrad.Beckmann@amd.com TheISA::NumIntRegs, params->numPhysIntRegs, 1796882SBrad.Beckmann@amd.com TheISA::NumFloatRegs, params->numPhysFloatRegs, 1806882SBrad.Beckmann@amd.com TheISA::NumMiscRegs * number_of_threads, 1816882SBrad.Beckmann@amd.com TheISA::ZeroReg), 1826882SBrad.Beckmann@amd.com 1836882SBrad.Beckmann@amd.com timeBuffer(params->backComSize, params->forwardComSize), 1846882SBrad.Beckmann@amd.com fetchQueue(params->backComSize, params->forwardComSize), 1856882SBrad.Beckmann@amd.com decodeQueue(params->backComSize, params->forwardComSize), 1866882SBrad.Beckmann@amd.com renameQueue(params->backComSize, params->forwardComSize), 1876922SBrad.Beckmann@amd.com iewQueue(params->backComSize, params->forwardComSize), 1886922SBrad.Beckmann@amd.com activityRec(NumStages, 1896922SBrad.Beckmann@amd.com params->backComSize + params->forwardComSize, 1906922SBrad.Beckmann@amd.com params->activity), 1916882SBrad.Beckmann@amd.com 1926882SBrad.Beckmann@amd.com globalSeqNum(1), 1936882SBrad.Beckmann@amd.com#if FULL_SYSTEM 1946882SBrad.Beckmann@amd.com system(params->system), 1958161SBrad.Beckmann@amd.com physmem(system->physmem), 1966922SBrad.Beckmann@amd.com#endif // FULL_SYSTEM 1976922SBrad.Beckmann@amd.com drainCount(0), 1986882SBrad.Beckmann@amd.com deferRegistration(params->deferRegistration), 1996882SBrad.Beckmann@amd.com numThreads(number_of_threads) 2006882SBrad.Beckmann@amd.com{ 2016882SBrad.Beckmann@amd.com if (!deferRegistration) { 2028615Snilay@cs.wisc.edu _status = Running; 2038615Snilay@cs.wisc.edu } else { 2047906SBrad.Beckmann@amd.com _status = Idle; 2056882SBrad.Beckmann@amd.com } 2068615Snilay@cs.wisc.edu 2077023SBrad.Beckmann@amd.com#if USE_CHECKER 2087550SBrad.Beckmann@amd.com if (params->checker) { 2097023SBrad.Beckmann@amd.com BaseCPU *temp_checker = params->checker; 2107023SBrad.Beckmann@amd.com checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 2117550SBrad.Beckmann@amd.com#if FULL_SYSTEM 2128161SBrad.Beckmann@amd.com checker->setSystem(params->system); 2136922SBrad.Beckmann@amd.com#endif 2146882SBrad.Beckmann@amd.com } else { 2157023SBrad.Beckmann@amd.com checker = NULL; 2167910SBrad.Beckmann@amd.com } 2177910SBrad.Beckmann@amd.com#endif // USE_CHECKER 2187910SBrad.Beckmann@amd.com 2197910SBrad.Beckmann@amd.com#if !FULL_SYSTEM 2207910SBrad.Beckmann@amd.com thread.resize(number_of_threads); 2217910SBrad.Beckmann@amd.com tids.resize(number_of_threads); 2227910SBrad.Beckmann@amd.com#endif 2237910SBrad.Beckmann@amd.com 2248161SBrad.Beckmann@amd.com // The stages also need their CPU pointer setup. However this 2257906SBrad.Beckmann@amd.com // must be done at the upper level CPU because they have pointers 2267039Snate@binkert.org // to the upper level CPU, and not this FullO3CPU. 2277039Snate@binkert.org 2286922SBrad.Beckmann@amd.com // Set up Pointers to the activeThreads list for each stage 2296922SBrad.Beckmann@amd.com fetch.setActiveThreads(&activeThreads); 2306922SBrad.Beckmann@amd.com decode.setActiveThreads(&activeThreads); 2316922SBrad.Beckmann@amd.com rename.setActiveThreads(&activeThreads); 2326882SBrad.Beckmann@amd.com iew.setActiveThreads(&activeThreads); 2336882SBrad.Beckmann@amd.com commit.setActiveThreads(&activeThreads); 2348436SBrad.Beckmann@amd.com 2358436SBrad.Beckmann@amd.com // Give each of the stages the time buffer they will use. 2368436SBrad.Beckmann@amd.com fetch.setTimeBuffer(&timeBuffer); 2378436SBrad.Beckmann@amd.com decode.setTimeBuffer(&timeBuffer); 2388436SBrad.Beckmann@amd.com rename.setTimeBuffer(&timeBuffer); 2398436SBrad.Beckmann@amd.com iew.setTimeBuffer(&timeBuffer); 2408436SBrad.Beckmann@amd.com commit.setTimeBuffer(&timeBuffer); 2418532SLisa.Hsu@amd.com 2428436SBrad.Beckmann@amd.com // Also setup each of the stages' queues. 2438436SBrad.Beckmann@amd.com fetch.setFetchQueue(&fetchQueue); 2448532SLisa.Hsu@amd.com decode.setFetchQueue(&fetchQueue); 2458436SBrad.Beckmann@amd.com commit.setFetchQueue(&fetchQueue); 2468532SLisa.Hsu@amd.com decode.setDecodeQueue(&decodeQueue); 2478532SLisa.Hsu@amd.com rename.setDecodeQueue(&decodeQueue); 2488532SLisa.Hsu@amd.com rename.setRenameQueue(&renameQueue); 2498532SLisa.Hsu@amd.com iew.setRenameQueue(&renameQueue); 2508532SLisa.Hsu@amd.com iew.setIEWQueue(&iewQueue); 2518532SLisa.Hsu@amd.com commit.setIEWQueue(&iewQueue); 2528532SLisa.Hsu@amd.com commit.setRenameQueue(&renameQueue); 2538532SLisa.Hsu@amd.com 2548532SLisa.Hsu@amd.com commit.setIEWStage(&iew); 2558532SLisa.Hsu@amd.com rename.setIEWStage(&iew); 2568532SLisa.Hsu@amd.com rename.setCommitStage(&commit); 2578532SLisa.Hsu@amd.com 2588532SLisa.Hsu@amd.com#if !FULL_SYSTEM 2598532SLisa.Hsu@amd.com int active_threads = params->workload.size(); 2608532SLisa.Hsu@amd.com 2618532SLisa.Hsu@amd.com if (active_threads > Impl::MaxThreads) { 2628532SLisa.Hsu@amd.com panic("Workload Size too large. Increase the 'MaxThreads'" 2638532SLisa.Hsu@amd.com "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 2648532SLisa.Hsu@amd.com "edit your workload size."); 2658532SLisa.Hsu@amd.com } 2668532SLisa.Hsu@amd.com#else 2678532SLisa.Hsu@amd.com int active_threads = 1; 2688532SLisa.Hsu@amd.com#endif 2698532SLisa.Hsu@amd.com 2708532SLisa.Hsu@amd.com //Make Sure That this a Valid Architeture 2718532SLisa.Hsu@amd.com assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 2728532SLisa.Hsu@amd.com assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 2738532SLisa.Hsu@amd.com 2748532SLisa.Hsu@amd.com rename.setScoreboard(&scoreboard); 2758532SLisa.Hsu@amd.com iew.setScoreboard(&scoreboard); 2768532SLisa.Hsu@amd.com 2778532SLisa.Hsu@amd.com // Setup the rename map for whichever stages need it. 2788532SLisa.Hsu@amd.com PhysRegIndex lreg_idx = 0; 2798532SLisa.Hsu@amd.com PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 2808532SLisa.Hsu@amd.com 2818532SLisa.Hsu@amd.com for (int tid=0; tid < numThreads; tid++) { 2828532SLisa.Hsu@amd.com bool bindRegs = (tid <= active_threads - 1); 2838532SLisa.Hsu@amd.com 2848532SLisa.Hsu@amd.com commitRenameMap[tid].init(TheISA::NumIntRegs, 2858532SLisa.Hsu@amd.com params->numPhysIntRegs, 2868532SLisa.Hsu@amd.com lreg_idx, //Index for Logical. Regs 2878532SLisa.Hsu@amd.com 2888532SLisa.Hsu@amd.com TheISA::NumFloatRegs, 2898436SBrad.Beckmann@amd.com params->numPhysFloatRegs, 2908532SLisa.Hsu@amd.com freg_idx, //Index for Float Regs 2918532SLisa.Hsu@amd.com 2928532SLisa.Hsu@amd.com TheISA::NumMiscRegs, 2938532SLisa.Hsu@amd.com 2948532SLisa.Hsu@amd.com TheISA::ZeroReg, 2958532SLisa.Hsu@amd.com TheISA::ZeroReg, 2968436SBrad.Beckmann@amd.com 2978436SBrad.Beckmann@amd.com tid, 2988532SLisa.Hsu@amd.com false); 2998532SLisa.Hsu@amd.com 3008532SLisa.Hsu@amd.com renameMap[tid].init(TheISA::NumIntRegs, 3018532SLisa.Hsu@amd.com params->numPhysIntRegs, 3028532SLisa.Hsu@amd.com lreg_idx, //Index for Logical. Regs 3038532SLisa.Hsu@amd.com 3048532SLisa.Hsu@amd.com TheISA::NumFloatRegs, 3058532SLisa.Hsu@amd.com params->numPhysFloatRegs, 3068532SLisa.Hsu@amd.com freg_idx, //Index for Float Regs 3078532SLisa.Hsu@amd.com 3088532SLisa.Hsu@amd.com TheISA::NumMiscRegs, 3098532SLisa.Hsu@amd.com 3108532SLisa.Hsu@amd.com TheISA::ZeroReg, 3118532SLisa.Hsu@amd.com TheISA::ZeroReg, 3128532SLisa.Hsu@amd.com 3138532SLisa.Hsu@amd.com tid, 3148532SLisa.Hsu@amd.com bindRegs); 3158532SLisa.Hsu@amd.com 3168532SLisa.Hsu@amd.com activateThreadEvent[tid].init(tid, this); 3178532SLisa.Hsu@amd.com deallocateContextEvent[tid].init(tid, this); 3188532SLisa.Hsu@amd.com } 3198532SLisa.Hsu@amd.com 3208532SLisa.Hsu@amd.com rename.setRenameMap(renameMap); 3218436SBrad.Beckmann@amd.com commit.setRenameMap(commitRenameMap); 3228532SLisa.Hsu@amd.com 3238532SLisa.Hsu@amd.com // Give renameMap & rename stage access to the freeList; 3248532SLisa.Hsu@amd.com for (int i=0; i < numThreads; i++) { 3258532SLisa.Hsu@amd.com renameMap[i].setFreeList(&freeList); 3268532SLisa.Hsu@amd.com } 3278532SLisa.Hsu@amd.com rename.setFreeList(&freeList); 3288532SLisa.Hsu@amd.com 3298532SLisa.Hsu@amd.com // Setup the ROB for whichever stages need it. 3308532SLisa.Hsu@amd.com commit.setROB(&rob); 3318436SBrad.Beckmann@amd.com 3328436SBrad.Beckmann@amd.com lastRunningCycle = curTick; 3338436SBrad.Beckmann@amd.com 3348436SBrad.Beckmann@amd.com lastActivatedCycle = -1; 3358436SBrad.Beckmann@amd.com 3368436SBrad.Beckmann@amd.com // Give renameMap & rename stage access to the freeList; 3378436SBrad.Beckmann@amd.com //for (int i=0; i < numThreads; i++) { 3388436SBrad.Beckmann@amd.com //globalSeqNum[i] = 1; 3398436SBrad.Beckmann@amd.com //} 3408436SBrad.Beckmann@amd.com 3418436SBrad.Beckmann@amd.com contextSwitch = false; 3428532SLisa.Hsu@amd.com} 3438436SBrad.Beckmann@amd.com 3448436SBrad.Beckmann@amd.comtemplate <class Impl> 3458436SBrad.Beckmann@amd.comFullO3CPU<Impl>::~FullO3CPU() 3468436SBrad.Beckmann@amd.com{ 3478436SBrad.Beckmann@amd.com} 3488436SBrad.Beckmann@amd.com 3498436SBrad.Beckmann@amd.comtemplate <class Impl> 3508532SLisa.Hsu@amd.comvoid 3518532SLisa.Hsu@amd.comFullO3CPU<Impl>::fullCPURegStats() 3528436SBrad.Beckmann@amd.com{ 3538436SBrad.Beckmann@amd.com BaseO3CPU::regStats(); 3548436SBrad.Beckmann@amd.com 3558532SLisa.Hsu@amd.com // Register any of the O3CPU's stats here. 3568532SLisa.Hsu@amd.com timesIdled 3578436SBrad.Beckmann@amd.com .name(name() + ".timesIdled") 3588532SLisa.Hsu@amd.com .desc("Number of times that the entire CPU went into an idle state and" 3598532SLisa.Hsu@amd.com " unscheduled itself") 3608532SLisa.Hsu@amd.com .prereq(timesIdled); 3618532SLisa.Hsu@amd.com 3628532SLisa.Hsu@amd.com idleCycles 3638532SLisa.Hsu@amd.com .name(name() + ".idleCycles") 3648532SLisa.Hsu@amd.com .desc("Total number of cycles that the CPU has spent unscheduled due " 3658532SLisa.Hsu@amd.com "to idling") 3668532SLisa.Hsu@amd.com .prereq(idleCycles); 3678532SLisa.Hsu@amd.com 3688532SLisa.Hsu@amd.com // Number of Instructions simulated 3698532SLisa.Hsu@amd.com // -------------------------------- 3708532SLisa.Hsu@amd.com // Should probably be in Base CPU but need templated 3718532SLisa.Hsu@amd.com // MaxThreads so put in here instead 3728532SLisa.Hsu@amd.com committedInsts 3738436SBrad.Beckmann@amd.com .init(numThreads) 3748436SBrad.Beckmann@amd.com .name(name() + ".committedInsts") 3758436SBrad.Beckmann@amd.com .desc("Number of Instructions Simulated"); 3768436SBrad.Beckmann@amd.com 3778436SBrad.Beckmann@amd.com totalCommittedInsts 3788436SBrad.Beckmann@amd.com .name(name() + ".committedInsts_total") 3798532SLisa.Hsu@amd.com .desc("Number of Instructions Simulated"); 3808532SLisa.Hsu@amd.com 3818532SLisa.Hsu@amd.com cpi 3828436SBrad.Beckmann@amd.com .name(name() + ".cpi") 3838436SBrad.Beckmann@amd.com .desc("CPI: Cycles Per Instruction") 3848436SBrad.Beckmann@amd.com .precision(6); 3858436SBrad.Beckmann@amd.com cpi = numCycles / committedInsts; 3868532SLisa.Hsu@amd.com 3878532SLisa.Hsu@amd.com totalCpi 3888532SLisa.Hsu@amd.com .name(name() + ".cpi_total") 3898532SLisa.Hsu@amd.com .desc("CPI: Total CPI of All Threads") 3908532SLisa.Hsu@amd.com .precision(6); 3918532SLisa.Hsu@amd.com totalCpi = numCycles / totalCommittedInsts; 3928532SLisa.Hsu@amd.com 3938436SBrad.Beckmann@amd.com ipc 3948532SLisa.Hsu@amd.com .name(name() + ".ipc") 3958532SLisa.Hsu@amd.com .desc("IPC: Instructions Per Cycle") 3968436SBrad.Beckmann@amd.com .precision(6); 3978532SLisa.Hsu@amd.com ipc = committedInsts / numCycles; 3988532SLisa.Hsu@amd.com 3998532SLisa.Hsu@amd.com totalIpc 4008532SLisa.Hsu@amd.com .name(name() + ".ipc_total") 4018436SBrad.Beckmann@amd.com .desc("IPC: Total IPC of All Threads") 4028436SBrad.Beckmann@amd.com .precision(6); 4038436SBrad.Beckmann@amd.com totalIpc = totalCommittedInsts / numCycles; 4048436SBrad.Beckmann@amd.com 4058436SBrad.Beckmann@amd.com} 4068532SLisa.Hsu@amd.com 4078436SBrad.Beckmann@amd.comtemplate <class Impl> 4088436SBrad.Beckmann@amd.comPort * 4098436SBrad.Beckmann@amd.comFullO3CPU<Impl>::getPort(const std::string &if_name, int idx) 4108436SBrad.Beckmann@amd.com{ 4118436SBrad.Beckmann@amd.com if (if_name == "dcache_port") 4128436SBrad.Beckmann@amd.com return iew.getDcachePort(); 4138436SBrad.Beckmann@amd.com else if (if_name == "icache_port") 4148436SBrad.Beckmann@amd.com return fetch.getIcachePort(); 4158436SBrad.Beckmann@amd.com else 4168436SBrad.Beckmann@amd.com panic("No Such Port\n"); 4178436SBrad.Beckmann@amd.com} 4188436SBrad.Beckmann@amd.com 4198436SBrad.Beckmann@amd.comtemplate <class Impl> 4208436SBrad.Beckmann@amd.comvoid 4218436SBrad.Beckmann@amd.comFullO3CPU<Impl>::tick() 4228436SBrad.Beckmann@amd.com{ 4238436SBrad.Beckmann@amd.com DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 4248436SBrad.Beckmann@amd.com 4258436SBrad.Beckmann@amd.com ++numCycles; 4268436SBrad.Beckmann@amd.com 4278436SBrad.Beckmann@amd.com// activity = false; 4288436SBrad.Beckmann@amd.com 4298436SBrad.Beckmann@amd.com //Tick each of the stages 4308436SBrad.Beckmann@amd.com fetch.tick(); 4318436SBrad.Beckmann@amd.com 4328436SBrad.Beckmann@amd.com decode.tick(); 4338436SBrad.Beckmann@amd.com 4348436SBrad.Beckmann@amd.com rename.tick(); 4358436SBrad.Beckmann@amd.com 4368436SBrad.Beckmann@amd.com iew.tick(); 4378436SBrad.Beckmann@amd.com 4388436SBrad.Beckmann@amd.com commit.tick(); 4398436SBrad.Beckmann@amd.com 4408436SBrad.Beckmann@amd.com#if !FULL_SYSTEM 4418436SBrad.Beckmann@amd.com doContextSwitch(); 4428436SBrad.Beckmann@amd.com#endif 4438436SBrad.Beckmann@amd.com 4448436SBrad.Beckmann@amd.com // Now advance the time buffers 4458436SBrad.Beckmann@amd.com timeBuffer.advance(); 4468436SBrad.Beckmann@amd.com 4478436SBrad.Beckmann@amd.com fetchQueue.advance(); 4488436SBrad.Beckmann@amd.com decodeQueue.advance(); 4498436SBrad.Beckmann@amd.com renameQueue.advance(); 4508436SBrad.Beckmann@amd.com iewQueue.advance(); 4518436SBrad.Beckmann@amd.com 4528436SBrad.Beckmann@amd.com activityRec.advance(); 4538436SBrad.Beckmann@amd.com 4548436SBrad.Beckmann@amd.com if (removeInstsThisCycle) { 4558436SBrad.Beckmann@amd.com cleanUpRemovedInsts(); 4568436SBrad.Beckmann@amd.com } 4578436SBrad.Beckmann@amd.com 4588436SBrad.Beckmann@amd.com if (!tickEvent.scheduled()) { 4598436SBrad.Beckmann@amd.com if (_status == SwitchedOut || 4608436SBrad.Beckmann@amd.com getState() == SimObject::Drained) { 4618436SBrad.Beckmann@amd.com DPRINTF(O3CPU, "Switched out!\n"); 4628436SBrad.Beckmann@amd.com // increment stat 4638436SBrad.Beckmann@amd.com lastRunningCycle = curTick; 4648436SBrad.Beckmann@amd.com } else if (!activityRec.active() || _status == Idle) { 4658436SBrad.Beckmann@amd.com DPRINTF(O3CPU, "Idle!\n"); 4668436SBrad.Beckmann@amd.com lastRunningCycle = curTick; 4678706Sandreas.hansson@arm.com timesIdled++; 4688706Sandreas.hansson@arm.com } else { 4698706Sandreas.hansson@arm.com tickEvent.schedule(nextCycle(curTick + cycles(1))); 4708706Sandreas.hansson@arm.com DPRINTF(O3CPU, "Scheduling next tick!\n"); 4718706Sandreas.hansson@arm.com } 4728436SBrad.Beckmann@amd.com } 4738436SBrad.Beckmann@amd.com 4748436SBrad.Beckmann@amd.com#if !FULL_SYSTEM 4758436SBrad.Beckmann@amd.com updateThreadPriority(); 4768436SBrad.Beckmann@amd.com#endif 4776882SBrad.Beckmann@amd.com 4786922SBrad.Beckmann@amd.com} 4796882SBrad.Beckmann@amd.com 4806922SBrad.Beckmann@amd.comtemplate <class Impl> 4817039Snate@binkert.orgvoid 4826922SBrad.Beckmann@amd.comFullO3CPU<Impl>::init() 4836922SBrad.Beckmann@amd.com{ 4846922SBrad.Beckmann@amd.com if (!deferRegistration) { 4857039Snate@binkert.org registerThreadContexts(); 4866922SBrad.Beckmann@amd.com } 4876922SBrad.Beckmann@amd.com 4886922SBrad.Beckmann@amd.com // Set inSyscall so that the CPU doesn't squash when initially 4896882SBrad.Beckmann@amd.com // setting up registers. 4906882SBrad.Beckmann@amd.com for (int i = 0; i < number_of_threads; ++i) 4917910SBrad.Beckmann@amd.com thread[i]->inSyscall = true; 4927910SBrad.Beckmann@amd.com 4937910SBrad.Beckmann@amd.com for (int tid=0; tid < number_of_threads; tid++) { 4947910SBrad.Beckmann@amd.com#if FULL_SYSTEM 4957910SBrad.Beckmann@amd.com ThreadContext *src_tc = threadContexts[tid]; 4967910SBrad.Beckmann@amd.com#else 4978162SBrad.Beckmann@amd.com ThreadContext *src_tc = thread[tid]->getTC(); 4988162SBrad.Beckmann@amd.com#endif 4998162SBrad.Beckmann@amd.com // Threads start in the Suspended State 5008162SBrad.Beckmann@amd.com if (src_tc->status() != ThreadContext::Suspended) { 5018162SBrad.Beckmann@amd.com continue; 5028162SBrad.Beckmann@amd.com } 5038162SBrad.Beckmann@amd.com 5048162SBrad.Beckmann@amd.com#if FULL_SYSTEM 5058162SBrad.Beckmann@amd.com TheISA::initCPU(src_tc, src_tc->readCpuId()); 5068162SBrad.Beckmann@amd.com#endif 5078162SBrad.Beckmann@amd.com } 5088162SBrad.Beckmann@amd.com 5098162SBrad.Beckmann@amd.com // Clear inSyscall. 5108162SBrad.Beckmann@amd.com for (int i = 0; i < number_of_threads; ++i) 5118162SBrad.Beckmann@amd.com thread[i]->inSyscall = false; 5127910SBrad.Beckmann@amd.com 5137910SBrad.Beckmann@amd.com // Initialize stages. 5148162SBrad.Beckmann@amd.com fetch.initStage(); 5158162SBrad.Beckmann@amd.com iew.initStage(); 5167910SBrad.Beckmann@amd.com rename.initStage(); 5177910SBrad.Beckmann@amd.com commit.initStage(); 5188688Snilay@cs.wisc.edu 5198688Snilay@cs.wisc.edu commit.setThreads(thread); 5208688Snilay@cs.wisc.edu} 5218688Snilay@cs.wisc.edu 5228688Snilay@cs.wisc.edutemplate <class Impl> 5238688Snilay@cs.wisc.eduvoid 5248688Snilay@cs.wisc.eduFullO3CPU<Impl>::activateThread(unsigned tid) 5258688Snilay@cs.wisc.edu{ 5268688Snilay@cs.wisc.edu list<unsigned>::iterator isActive = find( 5278688Snilay@cs.wisc.edu activeThreads.begin(), activeThreads.end(), tid); 5288688Snilay@cs.wisc.edu 5298688Snilay@cs.wisc.edu DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); 5308688Snilay@cs.wisc.edu 5318688Snilay@cs.wisc.edu if (isActive == activeThreads.end()) { 5328688Snilay@cs.wisc.edu DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 5338688Snilay@cs.wisc.edu tid); 5348688Snilay@cs.wisc.edu 5358688Snilay@cs.wisc.edu activeThreads.push_back(tid); 5368688Snilay@cs.wisc.edu } 5378688Snilay@cs.wisc.edu} 5388688Snilay@cs.wisc.edu 5398688Snilay@cs.wisc.edutemplate <class Impl> 5408688Snilay@cs.wisc.eduvoid 5418688Snilay@cs.wisc.eduFullO3CPU<Impl>::deactivateThread(unsigned tid) 5428688Snilay@cs.wisc.edu{ 5438688Snilay@cs.wisc.edu //Remove From Active List, if Active 5448688Snilay@cs.wisc.edu list<unsigned>::iterator thread_it = 5458688Snilay@cs.wisc.edu find(activeThreads.begin(), activeThreads.end(), tid); 5468688Snilay@cs.wisc.edu 5478688Snilay@cs.wisc.edu DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); 5488688Snilay@cs.wisc.edu 5498688Snilay@cs.wisc.edu if (thread_it != activeThreads.end()) { 5508688Snilay@cs.wisc.edu DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 5518688Snilay@cs.wisc.edu tid); 5528688Snilay@cs.wisc.edu activeThreads.erase(thread_it); 5538688Snilay@cs.wisc.edu } 5548688Snilay@cs.wisc.edu} 5558688Snilay@cs.wisc.edu 5568688Snilay@cs.wisc.edutemplate <class Impl> 5578688Snilay@cs.wisc.eduvoid 5588688Snilay@cs.wisc.eduFullO3CPU<Impl>::activateContext(int tid, int delay) 5598688Snilay@cs.wisc.edu{ 5608688Snilay@cs.wisc.edu // Needs to set each stage to running as well. 5618688Snilay@cs.wisc.edu if (delay){ 5628688Snilay@cs.wisc.edu DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 5638688Snilay@cs.wisc.edu "on cycle %d\n", tid, curTick + cycles(delay)); 5648688Snilay@cs.wisc.edu scheduleActivateThreadEvent(tid, delay); 5658688Snilay@cs.wisc.edu } else { 5668688Snilay@cs.wisc.edu activateThread(tid); 5678688Snilay@cs.wisc.edu } 5688688Snilay@cs.wisc.edu 5698688Snilay@cs.wisc.edu if (lastActivatedCycle < curTick) { 5708688Snilay@cs.wisc.edu scheduleTickEvent(delay); 5718688Snilay@cs.wisc.edu 5728688Snilay@cs.wisc.edu // Be sure to signal that there's some activity so the CPU doesn't 5738688Snilay@cs.wisc.edu // deschedule itself. 5748688Snilay@cs.wisc.edu activityRec.activity(); 5758688Snilay@cs.wisc.edu fetch.wakeFromQuiesce(); 5768688Snilay@cs.wisc.edu 5778688Snilay@cs.wisc.edu lastActivatedCycle = curTick; 5788688Snilay@cs.wisc.edu 5798688Snilay@cs.wisc.edu _status = Running; 5808688Snilay@cs.wisc.edu } 5818688Snilay@cs.wisc.edu} 5828688Snilay@cs.wisc.edu 5838688Snilay@cs.wisc.edutemplate <class Impl> 5848688Snilay@cs.wisc.edubool 5858688Snilay@cs.wisc.eduFullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay) 5868688Snilay@cs.wisc.edu{ 5878688Snilay@cs.wisc.edu // Schedule removal of thread data from CPU 5888688Snilay@cs.wisc.edu if (delay){ 5898688Snilay@cs.wisc.edu DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 5908688Snilay@cs.wisc.edu "on cycle %d\n", tid, curTick + cycles(delay)); 5918688Snilay@cs.wisc.edu scheduleDeallocateContextEvent(tid, remove, delay); 5928688Snilay@cs.wisc.edu return false; 5938688Snilay@cs.wisc.edu } else { 5946882SBrad.Beckmann@amd.com deactivateThread(tid); 5956882SBrad.Beckmann@amd.com if (remove) 5966882SBrad.Beckmann@amd.com removeThread(tid); 5976882SBrad.Beckmann@amd.com return true; 5986882SBrad.Beckmann@amd.com } 5996882SBrad.Beckmann@amd.com} 6006882SBrad.Beckmann@amd.com 6017550SBrad.Beckmann@amd.comtemplate <class Impl> 6027915SBrad.Beckmann@amd.comvoid 6038184Ssomayeh@cs.wisc.eduFullO3CPU<Impl>::suspendContext(int tid) 6047550SBrad.Beckmann@amd.com{ 6057915SBrad.Beckmann@amd.com DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 6067550SBrad.Beckmann@amd.com bool deallocated = deallocateContext(tid, false, 1); 6077550SBrad.Beckmann@amd.com // If this was the last thread then unschedule the tick event. 6087550SBrad.Beckmann@amd.com if (activeThreads.size() == 1 && !deallocated || 6097550SBrad.Beckmann@amd.com activeThreads.size() == 0) 6107550SBrad.Beckmann@amd.com unscheduleTickEvent(); 6117550SBrad.Beckmann@amd.com _status = Idle; 6127550SBrad.Beckmann@amd.com} 6137550SBrad.Beckmann@amd.com 6147550SBrad.Beckmann@amd.comtemplate <class Impl> 6157550SBrad.Beckmann@amd.comvoid 6167550SBrad.Beckmann@amd.comFullO3CPU<Impl>::haltContext(int tid) 6177550SBrad.Beckmann@amd.com{ 6187550SBrad.Beckmann@amd.com //For now, this is the same as deallocate 6197550SBrad.Beckmann@amd.com DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); 6207550SBrad.Beckmann@amd.com deallocateContext(tid, true, 1); 6217550SBrad.Beckmann@amd.com} 6227550SBrad.Beckmann@amd.com 6237550SBrad.Beckmann@amd.comtemplate <class Impl> 6247550SBrad.Beckmann@amd.comvoid 6257550SBrad.Beckmann@amd.comFullO3CPU<Impl>::insertThread(unsigned tid) 6267550SBrad.Beckmann@amd.com{ 6277550SBrad.Beckmann@amd.com DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 6287550SBrad.Beckmann@amd.com // Will change now that the PC and thread state is internal to the CPU 6298184Ssomayeh@cs.wisc.edu // and not in the ThreadContext. 6308184Ssomayeh@cs.wisc.edu#if FULL_SYSTEM 6318184Ssomayeh@cs.wisc.edu ThreadContext *src_tc = system->threadContexts[tid]; 6328184Ssomayeh@cs.wisc.edu#else 6338184Ssomayeh@cs.wisc.edu ThreadContext *src_tc = tcBase(tid); 6348184Ssomayeh@cs.wisc.edu#endif 6358184Ssomayeh@cs.wisc.edu 6368184Ssomayeh@cs.wisc.edu //Bind Int Regs to Rename Map 6378161SBrad.Beckmann@amd.com for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 6386882SBrad.Beckmann@amd.com PhysRegIndex phys_reg = freeList.getIntReg(); 6397550SBrad.Beckmann@amd.com 6407550SBrad.Beckmann@amd.com renameMap[tid].setEntry(ireg,phys_reg); 6418184Ssomayeh@cs.wisc.edu scoreboard.setReg(phys_reg); 6427915SBrad.Beckmann@amd.com } 6437550SBrad.Beckmann@amd.com 6446882SBrad.Beckmann@amd.com //Bind Float Regs to Rename Map 6456882SBrad.Beckmann@amd.com for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 6466882SBrad.Beckmann@amd.com PhysRegIndex phys_reg = freeList.getFloatReg(); 6478161SBrad.Beckmann@amd.com 6486882SBrad.Beckmann@amd.com renameMap[tid].setEntry(freg,phys_reg); 6496882SBrad.Beckmann@amd.com scoreboard.setReg(phys_reg); 6506882SBrad.Beckmann@amd.com } 6516882SBrad.Beckmann@amd.com 6528161SBrad.Beckmann@amd.com //Copy Thread Data Into RegFile 6536882SBrad.Beckmann@amd.com //this->copyFromTC(tid); 6546882SBrad.Beckmann@amd.com 6556882SBrad.Beckmann@amd.com //Set PC/NPC/NNPC 6566882SBrad.Beckmann@amd.com setPC(src_tc->readPC(), tid); 6576882SBrad.Beckmann@amd.com setNextPC(src_tc->readNextPC(), tid); 6587558SBrad.Beckmann@amd.com setNextNPC(src_tc->readNextNPC(), tid); 6597823Ssteve.reinhardt@amd.com 6606882SBrad.Beckmann@amd.com src_tc->setStatus(ThreadContext::Active); 6616882SBrad.Beckmann@amd.com 6626882SBrad.Beckmann@amd.com activateContext(tid,1); 6636882SBrad.Beckmann@amd.com 6646882SBrad.Beckmann@amd.com //Reset ROB/IQ/LSQ Entries 6656882SBrad.Beckmann@amd.com commit.rob->resetEntries(); 6667558SBrad.Beckmann@amd.com iew.resetEntries(); 6677823Ssteve.reinhardt@amd.com} 6686882SBrad.Beckmann@amd.com 6696882SBrad.Beckmann@amd.comtemplate <class Impl> 6706882SBrad.Beckmann@amd.comvoid 6716882SBrad.Beckmann@amd.comFullO3CPU<Impl>::removeThread(unsigned tid) 6726882SBrad.Beckmann@amd.com{ 6736882SBrad.Beckmann@amd.com DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 6746882SBrad.Beckmann@amd.com 6756882SBrad.Beckmann@amd.com // Copy Thread Data From RegFile 6766893SBrad.Beckmann@amd.com // If thread is suspended, it might be re-allocated 6777039Snate@binkert.org //this->copyToTC(tid); 6787039Snate@binkert.org 6797039Snate@binkert.org // Unbind Int Regs from Rename Map 6806882SBrad.Beckmann@amd.com for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 6818161SBrad.Beckmann@amd.com PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 6826882SBrad.Beckmann@amd.com 6836882SBrad.Beckmann@amd.com scoreboard.unsetReg(phys_reg); 6846882SBrad.Beckmann@amd.com freeList.addReg(phys_reg); 6856882SBrad.Beckmann@amd.com } 6866882SBrad.Beckmann@amd.com 6876882SBrad.Beckmann@amd.com // Unbind Float Regs from Rename Map 6887909Shestness@cs.utexas.edu for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 6897909Shestness@cs.utexas.edu PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 6907909Shestness@cs.utexas.edu 6917909Shestness@cs.utexas.edu scoreboard.unsetReg(phys_reg); 6927909Shestness@cs.utexas.edu freeList.addReg(phys_reg); 6937909Shestness@cs.utexas.edu } 694 695 // Squash Throughout Pipeline 696 InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; 697 fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid); 698 decode.squash(tid); 699 rename.squash(squash_seq_num, tid); 700 iew.squash(tid); 701 commit.rob->squash(squash_seq_num, tid); 702 703 assert(iew.ldstQueue.getCount(tid) == 0); 704 705 // Reset ROB/IQ/LSQ Entries 706 707 // Commented out for now. This should be possible to do by 708 // telling all the pipeline stages to drain first, and then 709 // checking until the drain completes. Once the pipeline is 710 // drained, call resetEntries(). - 10-09-06 ktlim 711/* 712 if (activeThreads.size() >= 1) { 713 commit.rob->resetEntries(); 714 iew.resetEntries(); 715 } 716*/ 717} 718 719 720template <class Impl> 721void 722FullO3CPU<Impl>::activateWhenReady(int tid) 723{ 724 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 725 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 726 tid); 727 728 bool ready = true; 729 730 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 731 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 732 "Phys. Int. Regs.\n", 733 tid); 734 ready = false; 735 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 736 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 737 "Phys. Float. Regs.\n", 738 tid); 739 ready = false; 740 } else if (commit.rob->numFreeEntries() >= 741 commit.rob->entryAmount(activeThreads.size() + 1)) { 742 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 743 "ROB entries.\n", 744 tid); 745 ready = false; 746 } else if (iew.instQueue.numFreeEntries() >= 747 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 748 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 749 "IQ entries.\n", 750 tid); 751 ready = false; 752 } else if (iew.ldstQueue.numFreeEntries() >= 753 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 754 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 755 "LSQ entries.\n", 756 tid); 757 ready = false; 758 } 759 760 if (ready) { 761 insertThread(tid); 762 763 contextSwitch = false; 764 765 cpuWaitList.remove(tid); 766 } else { 767 suspendContext(tid); 768 769 //blocks fetch 770 contextSwitch = true; 771 772 //@todo: dont always add to waitlist 773 //do waitlist 774 cpuWaitList.push_back(tid); 775 } 776} 777 778#if FULL_SYSTEM 779template <class Impl> 780void 781FullO3CPU<Impl>::updateMemPorts() 782{ 783 // Update all ThreadContext's memory ports (Functional/Virtual 784 // Ports) 785 for (int i = 0; i < thread.size(); ++i) 786 thread[i]->connectMemPorts(); 787} 788#endif 789 790template <class Impl> 791void 792FullO3CPU<Impl>::serialize(std::ostream &os) 793{ 794 SimObject::State so_state = SimObject::getState(); 795 SERIALIZE_ENUM(so_state); 796 BaseCPU::serialize(os); 797 nameOut(os, csprintf("%s.tickEvent", name())); 798 tickEvent.serialize(os); 799 800 // Use SimpleThread's ability to checkpoint to make it easier to 801 // write out the registers. Also make this static so it doesn't 802 // get instantiated multiple times (causes a panic in statistics). 803 static SimpleThread temp; 804 805 for (int i = 0; i < thread.size(); i++) { 806 nameOut(os, csprintf("%s.xc.%i", name(), i)); 807 temp.copyTC(thread[i]->getTC()); 808 temp.serialize(os); 809 } 810} 811 812template <class Impl> 813void 814FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 815{ 816 SimObject::State so_state; 817 UNSERIALIZE_ENUM(so_state); 818 BaseCPU::unserialize(cp, section); 819 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 820 821 // Use SimpleThread's ability to checkpoint to make it easier to 822 // read in the registers. Also make this static so it doesn't 823 // get instantiated multiple times (causes a panic in statistics). 824 static SimpleThread temp; 825 826 for (int i = 0; i < thread.size(); i++) { 827 temp.copyTC(thread[i]->getTC()); 828 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 829 thread[i]->getTC()->copyArchRegs(temp.getTC()); 830 } 831} 832 833template <class Impl> 834unsigned int 835FullO3CPU<Impl>::drain(Event *drain_event) 836{ 837 DPRINTF(O3CPU, "Switching out\n"); 838 839 // If the CPU isn't doing anything, then return immediately. 840 if (_status == Idle || _status == SwitchedOut) { 841 return 0; 842 } 843 844 drainCount = 0; 845 fetch.drain(); 846 decode.drain(); 847 rename.drain(); 848 iew.drain(); 849 commit.drain(); 850 851 // Wake the CPU and record activity so everything can drain out if 852 // the CPU was not able to immediately drain. 853 if (getState() != SimObject::Drained) { 854 // A bit of a hack...set the drainEvent after all the drain() 855 // calls have been made, that way if all of the stages drain 856 // immediately, the signalDrained() function knows not to call 857 // process on the drain event. 858 drainEvent = drain_event; 859 860 wakeCPU(); 861 activityRec.activity(); 862 863 return 1; 864 } else { 865 return 0; 866 } 867} 868 869template <class Impl> 870void 871FullO3CPU<Impl>::resume() 872{ 873 fetch.resume(); 874 decode.resume(); 875 rename.resume(); 876 iew.resume(); 877 commit.resume(); 878 879 changeState(SimObject::Running); 880 881 if (_status == SwitchedOut || _status == Idle) 882 return; 883 884#if FULL_SYSTEM 885 assert(system->getMemoryMode() == System::Timing); 886#endif 887 888 if (!tickEvent.scheduled()) 889 tickEvent.schedule(nextCycle()); 890 _status = Running; 891} 892 893template <class Impl> 894void 895FullO3CPU<Impl>::signalDrained() 896{ 897 if (++drainCount == NumStages) { 898 if (tickEvent.scheduled()) 899 tickEvent.squash(); 900 901 changeState(SimObject::Drained); 902 903 BaseCPU::switchOut(); 904 905 if (drainEvent) { 906 drainEvent->process(); 907 drainEvent = NULL; 908 } 909 } 910 assert(drainCount <= 5); 911} 912 913template <class Impl> 914void 915FullO3CPU<Impl>::switchOut() 916{ 917 fetch.switchOut(); 918 rename.switchOut(); 919 iew.switchOut(); 920 commit.switchOut(); 921 instList.clear(); 922 while (!removeList.empty()) { 923 removeList.pop(); 924 } 925 926 _status = SwitchedOut; 927#if USE_CHECKER 928 if (checker) 929 checker->switchOut(); 930#endif 931 if (tickEvent.scheduled()) 932 tickEvent.squash(); 933} 934 935template <class Impl> 936void 937FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 938{ 939 // Flush out any old data from the time buffers. 940 for (int i = 0; i < timeBuffer.getSize(); ++i) { 941 timeBuffer.advance(); 942 fetchQueue.advance(); 943 decodeQueue.advance(); 944 renameQueue.advance(); 945 iewQueue.advance(); 946 } 947 948 activityRec.reset(); 949 950 BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); 951 952 fetch.takeOverFrom(); 953 decode.takeOverFrom(); 954 rename.takeOverFrom(); 955 iew.takeOverFrom(); 956 commit.takeOverFrom(); 957 958 assert(!tickEvent.scheduled()); 959 960 // @todo: Figure out how to properly select the tid to put onto 961 // the active threads list. 962 int tid = 0; 963 964 list<unsigned>::iterator isActive = find( 965 activeThreads.begin(), activeThreads.end(), tid); 966 967 if (isActive == activeThreads.end()) { 968 //May Need to Re-code this if the delay variable is the delay 969 //needed for thread to activate 970 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 971 tid); 972 973 activeThreads.push_back(tid); 974 } 975 976 // Set all statuses to active, schedule the CPU's tick event. 977 // @todo: Fix up statuses so this is handled properly 978 for (int i = 0; i < threadContexts.size(); ++i) { 979 ThreadContext *tc = threadContexts[i]; 980 if (tc->status() == ThreadContext::Active && _status != Running) { 981 _status = Running; 982 tickEvent.schedule(nextCycle()); 983 } 984 } 985 if (!tickEvent.scheduled()) 986 tickEvent.schedule(nextCycle()); 987} 988 989template <class Impl> 990uint64_t 991FullO3CPU<Impl>::readIntReg(int reg_idx) 992{ 993 return regFile.readIntReg(reg_idx); 994} 995 996template <class Impl> 997FloatReg 998FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 999{ 1000 return regFile.readFloatReg(reg_idx, width); 1001} 1002 1003template <class Impl> 1004FloatReg 1005FullO3CPU<Impl>::readFloatReg(int reg_idx) 1006{ 1007 return regFile.readFloatReg(reg_idx); 1008} 1009 1010template <class Impl> 1011FloatRegBits 1012FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 1013{ 1014 return regFile.readFloatRegBits(reg_idx, width); 1015} 1016 1017template <class Impl> 1018FloatRegBits 1019FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 1020{ 1021 return regFile.readFloatRegBits(reg_idx); 1022} 1023 1024template <class Impl> 1025void 1026FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 1027{ 1028 regFile.setIntReg(reg_idx, val); 1029} 1030 1031template <class Impl> 1032void 1033FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 1034{ 1035 regFile.setFloatReg(reg_idx, val, width); 1036} 1037 1038template <class Impl> 1039void 1040FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 1041{ 1042 regFile.setFloatReg(reg_idx, val); 1043} 1044 1045template <class Impl> 1046void 1047FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 1048{ 1049 regFile.setFloatRegBits(reg_idx, val, width); 1050} 1051 1052template <class Impl> 1053void 1054FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1055{ 1056 regFile.setFloatRegBits(reg_idx, val); 1057} 1058 1059template <class Impl> 1060uint64_t 1061FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 1062{ 1063 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1064 1065 return regFile.readIntReg(phys_reg); 1066} 1067 1068template <class Impl> 1069float 1070FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 1071{ 1072 int idx = reg_idx + TheISA::FP_Base_DepTag; 1073 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1074 1075 return regFile.readFloatReg(phys_reg); 1076} 1077 1078template <class Impl> 1079double 1080FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 1081{ 1082 int idx = reg_idx + TheISA::FP_Base_DepTag; 1083 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1084 1085 return regFile.readFloatReg(phys_reg, 64); 1086} 1087 1088template <class Impl> 1089uint64_t 1090FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 1091{ 1092 int idx = reg_idx + TheISA::FP_Base_DepTag; 1093 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1094 1095 return regFile.readFloatRegBits(phys_reg); 1096} 1097 1098template <class Impl> 1099void 1100FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1101{ 1102 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1103 1104 regFile.setIntReg(phys_reg, val); 1105} 1106 1107template <class Impl> 1108void 1109FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1110{ 1111 int idx = reg_idx + TheISA::FP_Base_DepTag; 1112 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1113 1114 regFile.setFloatReg(phys_reg, val); 1115} 1116 1117template <class Impl> 1118void 1119FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1120{ 1121 int idx = reg_idx + TheISA::FP_Base_DepTag; 1122 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1123 1124 regFile.setFloatReg(phys_reg, val, 64); 1125} 1126 1127template <class Impl> 1128void 1129FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1130{ 1131 int idx = reg_idx + TheISA::FP_Base_DepTag; 1132 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1133 1134 regFile.setFloatRegBits(phys_reg, val); 1135} 1136 1137template <class Impl> 1138uint64_t 1139FullO3CPU<Impl>::readPC(unsigned tid) 1140{ 1141 return commit.readPC(tid); 1142} 1143 1144template <class Impl> 1145void 1146FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1147{ 1148 commit.setPC(new_PC, tid); 1149} 1150 1151template <class Impl> 1152uint64_t 1153FullO3CPU<Impl>::readMicroPC(unsigned tid) 1154{ 1155 return commit.readMicroPC(tid); 1156} 1157 1158template <class Impl> 1159void 1160FullO3CPU<Impl>::setMicroPC(Addr new_PC,unsigned tid) 1161{ 1162 commit.setMicroPC(new_PC, tid); 1163} 1164 1165template <class Impl> 1166uint64_t 1167FullO3CPU<Impl>::readNextPC(unsigned tid) 1168{ 1169 return commit.readNextPC(tid); 1170} 1171 1172template <class Impl> 1173void 1174FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1175{ 1176 commit.setNextPC(val, tid); 1177} 1178 1179template <class Impl> 1180uint64_t 1181FullO3CPU<Impl>::readNextNPC(unsigned tid) 1182{ 1183 return commit.readNextNPC(tid); 1184} 1185 1186template <class Impl> 1187void 1188FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid) 1189{ 1190 commit.setNextNPC(val, tid); 1191} 1192 1193template <class Impl> 1194uint64_t 1195FullO3CPU<Impl>::readNextMicroPC(unsigned tid) 1196{ 1197 return commit.readNextMicroPC(tid); 1198} 1199 1200template <class Impl> 1201void 1202FullO3CPU<Impl>::setNextMicroPC(Addr new_PC,unsigned tid) 1203{ 1204 commit.setNextMicroPC(new_PC, tid); 1205} 1206 1207template <class Impl> 1208typename FullO3CPU<Impl>::ListIt 1209FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1210{ 1211 instList.push_back(inst); 1212 1213 return --(instList.end()); 1214} 1215 1216template <class Impl> 1217void 1218FullO3CPU<Impl>::instDone(unsigned tid) 1219{ 1220 // Keep an instruction count. 1221 thread[tid]->numInst++; 1222 thread[tid]->numInsts++; 1223 committedInsts[tid]++; 1224 totalCommittedInsts++; 1225 1226 // Check for instruction-count-based events. 1227 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1228} 1229 1230template <class Impl> 1231void 1232FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1233{ 1234 removeInstsThisCycle = true; 1235 1236 removeList.push(inst->getInstListIt()); 1237} 1238 1239template <class Impl> 1240void 1241FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1242{ 1243 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1244 "[sn:%lli]\n", 1245 inst->threadNumber, inst->readPC(), inst->seqNum); 1246 1247 removeInstsThisCycle = true; 1248 1249 // Remove the front instruction. 1250 removeList.push(inst->getInstListIt()); 1251} 1252 1253template <class Impl> 1254void 1255FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1256{ 1257 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1258 " list.\n", tid); 1259 1260 ListIt end_it; 1261 1262 bool rob_empty = false; 1263 1264 if (instList.empty()) { 1265 return; 1266 } else if (rob.isEmpty(/*tid*/)) { 1267 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1268 end_it = instList.begin(); 1269 rob_empty = true; 1270 } else { 1271 end_it = (rob.readTailInst(tid))->getInstListIt(); 1272 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1273 } 1274 1275 removeInstsThisCycle = true; 1276 1277 ListIt inst_it = instList.end(); 1278 1279 inst_it--; 1280 1281 // Walk through the instruction list, removing any instructions 1282 // that were inserted after the given instruction iterator, end_it. 1283 while (inst_it != end_it) { 1284 assert(!instList.empty()); 1285 1286 squashInstIt(inst_it, tid); 1287 1288 inst_it--; 1289 } 1290 1291 // If the ROB was empty, then we actually need to remove the first 1292 // instruction as well. 1293 if (rob_empty) { 1294 squashInstIt(inst_it, tid); 1295 } 1296} 1297 1298template <class Impl> 1299void 1300FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1301 unsigned tid) 1302{ 1303 assert(!instList.empty()); 1304 1305 removeInstsThisCycle = true; 1306 1307 ListIt inst_iter = instList.end(); 1308 1309 inst_iter--; 1310 1311 DPRINTF(O3CPU, "Deleting instructions from instruction " 1312 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1313 tid, seq_num, (*inst_iter)->seqNum); 1314 1315 while ((*inst_iter)->seqNum > seq_num) { 1316 1317 bool break_loop = (inst_iter == instList.begin()); 1318 1319 squashInstIt(inst_iter, tid); 1320 1321 inst_iter--; 1322 1323 if (break_loop) 1324 break; 1325 } 1326} 1327 1328template <class Impl> 1329inline void 1330FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1331{ 1332 if ((*instIt)->threadNumber == tid) { 1333 DPRINTF(O3CPU, "Squashing instruction, " 1334 "[tid:%i] [sn:%lli] PC %#x\n", 1335 (*instIt)->threadNumber, 1336 (*instIt)->seqNum, 1337 (*instIt)->readPC()); 1338 1339 // Mark it as squashed. 1340 (*instIt)->setSquashed(); 1341 1342 // @todo: Formulate a consistent method for deleting 1343 // instructions from the instruction list 1344 // Remove the instruction from the list. 1345 removeList.push(instIt); 1346 } 1347} 1348 1349template <class Impl> 1350void 1351FullO3CPU<Impl>::cleanUpRemovedInsts() 1352{ 1353 while (!removeList.empty()) { 1354 DPRINTF(O3CPU, "Removing instruction, " 1355 "[tid:%i] [sn:%lli] PC %#x\n", 1356 (*removeList.front())->threadNumber, 1357 (*removeList.front())->seqNum, 1358 (*removeList.front())->readPC()); 1359 1360 instList.erase(removeList.front()); 1361 1362 removeList.pop(); 1363 } 1364 1365 removeInstsThisCycle = false; 1366} 1367/* 1368template <class Impl> 1369void 1370FullO3CPU<Impl>::removeAllInsts() 1371{ 1372 instList.clear(); 1373} 1374*/ 1375template <class Impl> 1376void 1377FullO3CPU<Impl>::dumpInsts() 1378{ 1379 int num = 0; 1380 1381 ListIt inst_list_it = instList.begin(); 1382 1383 cprintf("Dumping Instruction List\n"); 1384 1385 while (inst_list_it != instList.end()) { 1386 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1387 "Squashed:%i\n\n", 1388 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1389 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1390 (*inst_list_it)->isSquashed()); 1391 inst_list_it++; 1392 ++num; 1393 } 1394} 1395/* 1396template <class Impl> 1397void 1398FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1399{ 1400 iew.wakeDependents(inst); 1401} 1402*/ 1403template <class Impl> 1404void 1405FullO3CPU<Impl>::wakeCPU() 1406{ 1407 if (activityRec.active() || tickEvent.scheduled()) { 1408 DPRINTF(Activity, "CPU already running.\n"); 1409 return; 1410 } 1411 1412 DPRINTF(Activity, "Waking up CPU\n"); 1413 1414 idleCycles += (curTick - 1) - lastRunningCycle; 1415 1416 tickEvent.schedule(nextCycle()); 1417} 1418 1419template <class Impl> 1420int 1421FullO3CPU<Impl>::getFreeTid() 1422{ 1423 for (int i=0; i < numThreads; i++) { 1424 if (!tids[i]) { 1425 tids[i] = true; 1426 return i; 1427 } 1428 } 1429 1430 return -1; 1431} 1432 1433template <class Impl> 1434void 1435FullO3CPU<Impl>::doContextSwitch() 1436{ 1437 if (contextSwitch) { 1438 1439 //ADD CODE TO DEACTIVE THREAD HERE (???) 1440 1441 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1442 activateWhenReady(tid); 1443 } 1444 1445 if (cpuWaitList.size() == 0) 1446 contextSwitch = true; 1447 } 1448} 1449 1450template <class Impl> 1451void 1452FullO3CPU<Impl>::updateThreadPriority() 1453{ 1454 if (activeThreads.size() > 1) 1455 { 1456 //DEFAULT TO ROUND ROBIN SCHEME 1457 //e.g. Move highest priority to end of thread list 1458 list<unsigned>::iterator list_begin = activeThreads.begin(); 1459 list<unsigned>::iterator list_end = activeThreads.end(); 1460 1461 unsigned high_thread = *list_begin; 1462 1463 activeThreads.erase(list_begin); 1464 1465 activeThreads.push_back(high_thread); 1466 } 1467} 1468 1469// Forward declaration of FullO3CPU. 1470template class FullO3CPU<O3CPUImpl>; 1471